summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-10-16 06:09:09 +0000
committerobrien <obrien@FreeBSD.org>1999-10-16 06:09:09 +0000
commitcae8fa8120c70195f34a2456f18c4c848a2d3e0c (patch)
treef7d3a3ab9c32694206552e767626366f016f2062 /contrib
parent84656b55b6e25e30322dc903a05de53706361d3d (diff)
downloadFreeBSD-src-cae8fa8120c70195f34a2456f18c4c848a2d3e0c.zip
FreeBSD-src-cae8fa8120c70195f34a2456f18c4c848a2d3e0c.tar.gz
Virgin import of the GCC 2.95.1 compilers
Diffstat (limited to 'contrib')
-rw-r--r--contrib/gcc/BUGS10
-rw-r--r--contrib/gcc/ChangeLog23760
-rw-r--r--contrib/gcc/FSFChangeLog2154
-rw-r--r--contrib/gcc/LANGUAGES12
-rw-r--r--contrib/gcc/Makefile.in1003
-rw-r--r--contrib/gcc/NEWS8
-rw-r--r--contrib/gcc/README8
-rw-r--r--contrib/gcc/acconfig.h56
-rw-r--r--contrib/gcc/aclocal.m4448
-rw-r--r--contrib/gcc/alias.c579
-rw-r--r--contrib/gcc/basic-block.h178
-rw-r--r--contrib/gcc/bitmap.c6
-rw-r--r--contrib/gcc/bitmap.h6
-rw-r--r--contrib/gcc/c-aux-info.c244
-rw-r--r--contrib/gcc/c-common.c408
-rw-r--r--contrib/gcc/c-convert.c2
-rw-r--r--contrib/gcc/c-decl.c438
-rw-r--r--contrib/gcc/c-iterate.c6
-rw-r--r--contrib/gcc/c-lang.c21
-rw-r--r--contrib/gcc/c-lex.c705
-rw-r--r--contrib/gcc/c-lex.h6
-rw-r--r--contrib/gcc/c-parse.gperf8
-rw-r--r--contrib/gcc/c-parse.in90
-rw-r--r--contrib/gcc/c-pragma.c465
-rw-r--r--contrib/gcc/c-pragma.h69
-rw-r--r--contrib/gcc/c-tree.h65
-rw-r--r--contrib/gcc/c-typeck.c557
-rw-r--r--contrib/gcc/caller-save.c738
-rw-r--r--contrib/gcc/calls.c2115
-rw-r--r--contrib/gcc/cccp.c1445
-rw-r--r--contrib/gcc/cexp.y376
-rw-r--r--contrib/gcc/collect2.c567
-rw-r--r--contrib/gcc/collect2.h36
-rw-r--r--contrib/gcc/combine.c330
-rw-r--r--contrib/gcc/config.in178
-rw-r--r--contrib/gcc/config/alpha/alpha-interix.h252
-rw-r--r--contrib/gcc/config/alpha/alpha.c1462
-rw-r--r--contrib/gcc/config/alpha/alpha.h325
-rw-r--r--contrib/gcc/config/alpha/alpha.md1037
-rw-r--r--contrib/gcc/config/alpha/alpha32.h104
-rw-r--r--contrib/gcc/config/alpha/crtbegin.asm89
-rw-r--r--contrib/gcc/config/alpha/crtend.asm3
-rw-r--r--contrib/gcc/config/alpha/elf.h62
-rw-r--r--contrib/gcc/config/alpha/lib1funcs.asm325
-rw-r--r--contrib/gcc/config/alpha/linux-ecoff.h7
-rw-r--r--contrib/gcc/config/alpha/linux-elf.h3
-rw-r--r--contrib/gcc/config/alpha/linux.h6
-rw-r--r--contrib/gcc/config/alpha/netbsd-elf.h3
-rw-r--r--contrib/gcc/config/alpha/netbsd.h3
-rw-r--r--contrib/gcc/config/alpha/osf.h12
-rw-r--r--contrib/gcc/config/alpha/t-ieee6
-rw-r--r--contrib/gcc/config/alpha/t-interix16
-rw-r--r--contrib/gcc/config/alpha/vms.h4
-rw-r--r--contrib/gcc/config/alpha/vxworks.h6
-rw-r--r--contrib/gcc/config/alpha/xm-alpha-interix.h45
-rw-r--r--contrib/gcc/config/alpha/xm-alpha.h2
-rw-r--r--contrib/gcc/config/dbxcoff.h4
-rw-r--r--contrib/gcc/config/dbxelf.h109
-rw-r--r--contrib/gcc/config/elfos.h704
-rw-r--r--contrib/gcc/config/float-sh.h2
-rw-r--r--contrib/gcc/config/fp-bit.c15
-rw-r--r--contrib/gcc/config/i386/aix386ng.h6
-rw-r--r--contrib/gcc/config/i386/bsd.h4
-rw-r--r--contrib/gcc/config/i386/crtdll.h6
-rw-r--r--contrib/gcc/config/i386/cygwin.asm32
-rw-r--r--contrib/gcc/config/i386/cygwin.h525
-rw-r--r--contrib/gcc/config/i386/dgux.c4
-rw-r--r--contrib/gcc/config/i386/dgux.h37
-rw-r--r--contrib/gcc/config/i386/djgpp-rtems.h41
-rw-r--r--contrib/gcc/config/i386/djgpp.h161
-rw-r--r--contrib/gcc/config/i386/freebsd-elf.h122
-rw-r--r--contrib/gcc/config/i386/gas.h7
-rw-r--r--contrib/gcc/config/i386/gnu.h27
-rw-r--r--contrib/gcc/config/i386/i386-coff.h8
-rw-r--r--contrib/gcc/config/i386/i386-interix.h575
-rw-r--r--contrib/gcc/config/i386/i386.c1831
-rw-r--r--contrib/gcc/config/i386/i386.h407
-rw-r--r--contrib/gcc/config/i386/i386.md3357
-rw-r--r--contrib/gcc/config/i386/interix.c110
-rw-r--r--contrib/gcc/config/i386/isc.h33
-rw-r--r--contrib/gcc/config/i386/isccoff.h4
-rw-r--r--contrib/gcc/config/i386/linux.h14
-rw-r--r--contrib/gcc/config/i386/mingw32.h23
-rw-r--r--contrib/gcc/config/i386/moss.h3
-rw-r--r--contrib/gcc/config/i386/netbsd.h8
-rw-r--r--contrib/gcc/config/i386/next.h4
-rw-r--r--contrib/gcc/config/i386/openbsd.h8
-rw-r--r--contrib/gcc/config/i386/osf1elf.h4
-rw-r--r--contrib/gcc/config/i386/osfrose.h34
-rw-r--r--contrib/gcc/config/i386/sco.h4
-rw-r--r--contrib/gcc/config/i386/sco5.h43
-rw-r--r--contrib/gcc/config/i386/scodbx.h4
-rw-r--r--contrib/gcc/config/i386/sequent.h7
-rw-r--r--contrib/gcc/config/i386/sol2.h3
-rw-r--r--contrib/gcc/config/i386/sun386.h8
-rw-r--r--contrib/gcc/config/i386/sysv5.h35
-rw-r--r--contrib/gcc/config/i386/t-cygwin16
-rw-r--r--contrib/gcc/config/i386/t-dgux6
-rw-r--r--contrib/gcc/config/i386/t-djgpp2
-rw-r--r--contrib/gcc/config/i386/t-interix16
-rw-r--r--contrib/gcc/config/i386/t-udk2
-rw-r--r--contrib/gcc/config/i386/t-uwin5
-rw-r--r--contrib/gcc/config/i386/udk.h30
-rw-r--r--contrib/gcc/config/i386/unix.h9
-rw-r--r--contrib/gcc/config/i386/uwin.asm32
-rw-r--r--contrib/gcc/config/i386/uwin.h93
-rw-r--r--contrib/gcc/config/i386/vxi386.h39
-rw-r--r--contrib/gcc/config/i386/win-nt.h4
-rw-r--r--contrib/gcc/config/i386/win32.h280
-rw-r--r--contrib/gcc/config/i386/winnt.c36
-rw-r--r--contrib/gcc/config/i386/x-cygwin4
-rw-r--r--contrib/gcc/config/i386/x-djgpp24
-rw-r--r--contrib/gcc/config/i386/xm-cygwin.h58
-rw-r--r--contrib/gcc/config/i386/xm-djgpp.h44
-rw-r--r--contrib/gcc/config/i386/xm-dos.h24
-rw-r--r--contrib/gcc/config/i386/xm-i386-interix.h34
-rw-r--r--contrib/gcc/config/i386/xm-mingw32.h8
-rw-r--r--contrib/gcc/config/i386/xm-os2.h8
-rw-r--r--contrib/gcc/config/i386/xm-uwin.h39
-rw-r--r--contrib/gcc/config/interix.h107
-rw-r--r--contrib/gcc/config/nextstep.c13
-rw-r--r--contrib/gcc/config/nextstep.h17
-rw-r--r--contrib/gcc/config/openbsd.h6
-rw-r--r--contrib/gcc/config/ptx4.h7
-rw-r--r--contrib/gcc/config/sparc/elf.h16
-rw-r--r--contrib/gcc/config/sparc/gmon-sol2.c24
-rw-r--r--contrib/gcc/config/sparc/hal.h33
-rw-r--r--contrib/gcc/config/sparc/linux.h2
-rw-r--r--contrib/gcc/config/sparc/linux64.h157
-rw-r--r--contrib/gcc/config/sparc/pbd.h30
-rw-r--r--contrib/gcc/config/sparc/sol2-c1.asm42
-rw-r--r--contrib/gcc/config/sparc/sol2-ci.asm8
-rw-r--r--contrib/gcc/config/sparc/sol2-cn.asm2
-rw-r--r--contrib/gcc/config/sparc/sol2-sld-64.h363
-rw-r--r--contrib/gcc/config/sparc/sol2.h12
-rw-r--r--contrib/gcc/config/sparc/sp64-elf.h9
-rw-r--r--contrib/gcc/config/sparc/sparc.c4272
-rw-r--r--contrib/gcc/config/sparc/sparc.h970
-rw-r--r--contrib/gcc/config/sparc/sparc.md5504
-rw-r--r--contrib/gcc/config/sparc/splet.h28
-rw-r--r--contrib/gcc/config/sparc/sun4o3.h8
-rw-r--r--contrib/gcc/config/sparc/sysv4.h35
-rw-r--r--contrib/gcc/config/sparc/t-halos2
-rw-r--r--contrib/gcc/config/sparc/t-linux6421
-rw-r--r--contrib/gcc/config/sparc/t-sol222
-rw-r--r--contrib/gcc/config/sparc/t-sol2-648
-rw-r--r--contrib/gcc/config/sparc/t-splet5
-rw-r--r--contrib/gcc/config/sparc/xm-sp64.h2
-rw-r--r--contrib/gcc/config/sparc/xm-sysv4-64.h27
-rw-r--r--contrib/gcc/config/svr4.h96
-rw-r--r--contrib/gcc/config/t-freebsd1
-rw-r--r--contrib/gcc/config/t-gnu7
-rw-r--r--contrib/gcc/config/t-openbsd2
-rw-r--r--contrib/gcc/config/t-rtems7
-rw-r--r--contrib/gcc/config/tm-dwarf2.h4
-rw-r--r--contrib/gcc/config/x-interix24
-rw-r--r--contrib/gcc/config/xm-interix.h77
-rwxr-xr-xcontrib/gcc/configure4182
-rw-r--r--contrib/gcc/configure.in1861
-rw-r--r--contrib/gcc/convert.c8
-rw-r--r--contrib/gcc/cp/ChangeLog6220
-rw-r--r--contrib/gcc/cp/Make-lang.in91
-rw-r--r--contrib/gcc/cp/Makefile.in89
-rw-r--r--contrib/gcc/cp/NEWS36
-rw-r--r--contrib/gcc/cp/call.c787
-rw-r--r--contrib/gcc/cp/class.c2956
-rw-r--r--contrib/gcc/cp/config-lang.in2
-rw-r--r--contrib/gcc/cp/cp-tree.def42
-rw-r--r--contrib/gcc/cp/cp-tree.h1241
-rw-r--r--contrib/gcc/cp/cvt.c233
-rw-r--r--contrib/gcc/cp/decl.c4733
-rw-r--r--contrib/gcc/cp/decl.h5
-rw-r--r--contrib/gcc/cp/decl2.c2516
-rw-r--r--contrib/gcc/cp/errfn.c166
-rw-r--r--contrib/gcc/cp/error.c529
-rw-r--r--contrib/gcc/cp/except.c204
-rw-r--r--contrib/gcc/cp/exception.cc35
-rw-r--r--contrib/gcc/cp/expr.c83
-rw-r--r--contrib/gcc/cp/friend.c294
-rw-r--r--contrib/gcc/cp/g++spec.c19
-rw-r--r--contrib/gcc/cp/gxx.gperf9
-rw-r--r--contrib/gcc/cp/gxxint.texi150
-rw-r--r--contrib/gcc/cp/inc/exception6
-rw-r--r--contrib/gcc/cp/inc/new6
-rw-r--r--contrib/gcc/cp/inc/new.h2
-rw-r--r--contrib/gcc/cp/inc/typeinfo8
-rw-r--r--contrib/gcc/cp/init.c1000
-rw-r--r--contrib/gcc/cp/input.c8
-rw-r--r--contrib/gcc/cp/lang-options.h43
-rw-r--r--contrib/gcc/cp/lang-specs.h31
-rw-r--r--contrib/gcc/cp/lex.c1182
-rw-r--r--contrib/gcc/cp/lex.h4
-rw-r--r--contrib/gcc/cp/method.c604
-rw-r--r--contrib/gcc/cp/new.cc2
-rw-r--r--contrib/gcc/cp/new1.cc2
-rw-r--r--contrib/gcc/cp/new2.cc2
-rw-r--r--contrib/gcc/cp/parse.y842
-rw-r--r--contrib/gcc/cp/pt.c7681
-rw-r--r--contrib/gcc/cp/ptree.c16
-rw-r--r--contrib/gcc/cp/repo.c22
-rw-r--r--contrib/gcc/cp/rtti.c167
-rw-r--r--contrib/gcc/cp/search.c3737
-rw-r--r--contrib/gcc/cp/semantics.c461
-rw-r--r--contrib/gcc/cp/sig.c161
-rw-r--r--contrib/gcc/cp/spew.c24
-rw-r--r--contrib/gcc/cp/tinfo.cc6
-rw-r--r--contrib/gcc/cp/tinfo.h4
-rw-r--r--contrib/gcc/cp/tinfo2.cc2
-rw-r--r--contrib/gcc/cp/tree.c1067
-rw-r--r--contrib/gcc/cp/typeck.c2266
-rw-r--r--contrib/gcc/cp/typeck2.c417
-rw-r--r--contrib/gcc/cp/xref.c69
-rw-r--r--contrib/gcc/cpp.texi164
-rw-r--r--contrib/gcc/cppalloc.c45
-rw-r--r--contrib/gcc/cpperror.c105
-rw-r--r--contrib/gcc/cppexp.c593
-rw-r--r--contrib/gcc/cppfiles.c1605
-rw-r--r--contrib/gcc/cpphash.c1613
-rw-r--r--contrib/gcc/cpphash.h47
-rw-r--r--contrib/gcc/cppinit.c1778
-rw-r--r--contrib/gcc/cpplib.c7219
-rw-r--r--contrib/gcc/cpplib.h313
-rw-r--r--contrib/gcc/cppmain.c57
-rw-r--r--contrib/gcc/cppspec.c234
-rw-r--r--contrib/gcc/cppulp.c26
-rw-r--r--contrib/gcc/cross-make11
-rw-r--r--contrib/gcc/crtstuff.c107
-rw-r--r--contrib/gcc/cse.c636
-rw-r--r--contrib/gcc/dbxout.c24
-rw-r--r--contrib/gcc/doprint.c27
-rw-r--r--contrib/gcc/dwarf2.h31
-rw-r--r--contrib/gcc/dwarf2out.c899
-rw-r--r--contrib/gcc/dwarfout.c199
-rw-r--r--contrib/gcc/dwarfout.h2
-rw-r--r--contrib/gcc/dyn-string.c33
-rw-r--r--contrib/gcc/dyn-string.h29
-rw-r--r--contrib/gcc/eh-common.h25
-rw-r--r--contrib/gcc/emit-rtl.c408
-rw-r--r--contrib/gcc/except.c559
-rw-r--r--contrib/gcc/except.h50
-rwxr-xr-xcontrib/gcc/exgettext118
-rw-r--r--contrib/gcc/explow.c75
-rw-r--r--contrib/gcc/expmed.c297
-rw-r--r--contrib/gcc/expr.c1075
-rw-r--r--contrib/gcc/expr.h82
-rw-r--r--contrib/gcc/extend.texi297
-rw-r--r--contrib/gcc/f/BUGS114
-rw-r--r--contrib/gcc/f/ChangeLog5324
-rw-r--r--contrib/gcc/f/INSTALL352
-rw-r--r--contrib/gcc/f/Make-lang.in115
-rw-r--r--contrib/gcc/f/Makefile.in21
-rw-r--r--contrib/gcc/f/NEWS1651
-rw-r--r--contrib/gcc/f/RELEASE-PREP5
-rw-r--r--contrib/gcc/f/ansify.c4
-rw-r--r--contrib/gcc/f/assert.j2
-rw-r--r--contrib/gcc/f/bad.c26
-rw-r--r--contrib/gcc/f/bad.def6
-rw-r--r--contrib/gcc/f/bad.h6
-rw-r--r--contrib/gcc/f/bit.c2
-rw-r--r--contrib/gcc/f/bit.h2
-rw-r--r--contrib/gcc/f/bld-op.def2
-rw-r--r--contrib/gcc/f/bld.c15
-rw-r--r--contrib/gcc/f/bld.h23
-rw-r--r--contrib/gcc/f/bugs.texi204
-rw-r--r--contrib/gcc/f/bugs0.texi14
-rw-r--r--contrib/gcc/f/com-rt.def7
-rw-r--r--contrib/gcc/f/com.c4047
-rw-r--r--contrib/gcc/f/com.h37
-rw-r--r--contrib/gcc/f/config.j2
-rw-r--r--contrib/gcc/f/convert.j2
-rw-r--r--contrib/gcc/f/data.c6
-rw-r--r--contrib/gcc/f/data.h2
-rw-r--r--contrib/gcc/f/equiv.c2
-rw-r--r--contrib/gcc/f/equiv.h2
-rw-r--r--contrib/gcc/f/expr.c189
-rw-r--r--contrib/gcc/f/expr.h2
-rw-r--r--contrib/gcc/f/ffe.texi2024
-rw-r--r--contrib/gcc/f/fini.c39
-rw-r--r--contrib/gcc/f/flags.j2
-rw-r--r--contrib/gcc/f/g77.114
-rw-r--r--contrib/gcc/f/g77.texi2774
-rw-r--r--contrib/gcc/f/g77spec.c18
-rw-r--r--contrib/gcc/f/glimits.j2
-rw-r--r--contrib/gcc/f/global.c165
-rw-r--r--contrib/gcc/f/global.h6
-rw-r--r--contrib/gcc/f/hconfig.j2
-rw-r--r--contrib/gcc/f/implic.c10
-rw-r--r--contrib/gcc/f/implic.h4
-rw-r--r--contrib/gcc/f/info-b.def2
-rw-r--r--contrib/gcc/f/info-k.def2
-rw-r--r--contrib/gcc/f/info-w.def2
-rw-r--r--contrib/gcc/f/info.c22
-rw-r--r--contrib/gcc/f/info.h12
-rw-r--r--contrib/gcc/f/input.j2
-rw-r--r--contrib/gcc/f/intdoc.c101
-rw-r--r--contrib/gcc/f/intdoc.in229
-rw-r--r--contrib/gcc/f/intdoc.texi289
-rw-r--r--contrib/gcc/f/intrin.c84
-rw-r--r--contrib/gcc/f/intrin.def22
-rw-r--r--contrib/gcc/f/intrin.h17
-rw-r--r--contrib/gcc/f/lab.c2
-rw-r--r--contrib/gcc/f/lab.h2
-rw-r--r--contrib/gcc/f/lang-options.h253
-rw-r--r--contrib/gcc/f/lang-specs.h30
-rw-r--r--contrib/gcc/f/lex.c84
-rw-r--r--contrib/gcc/f/lex.h10
-rw-r--r--contrib/gcc/f/malloc.c16
-rw-r--r--contrib/gcc/f/malloc.h8
-rw-r--r--contrib/gcc/f/name.c6
-rw-r--r--contrib/gcc/f/name.h6
-rw-r--r--contrib/gcc/f/news.texi933
-rw-r--r--contrib/gcc/f/news0.texi17
-rw-r--r--contrib/gcc/f/output.j3
-rw-r--r--contrib/gcc/f/parse.c2
-rw-r--r--contrib/gcc/f/proj.c2
-rw-r--r--contrib/gcc/f/proj.h2
-rw-r--r--contrib/gcc/f/root.texi40
-rw-r--r--contrib/gcc/f/rtl.j2
-rw-r--r--contrib/gcc/f/src.c2
-rw-r--r--contrib/gcc/f/src.h2
-rw-r--r--contrib/gcc/f/st.c2
-rw-r--r--contrib/gcc/f/st.h2
-rw-r--r--contrib/gcc/f/sta.c8
-rw-r--r--contrib/gcc/f/sta.h8
-rw-r--r--contrib/gcc/f/stb.c122
-rw-r--r--contrib/gcc/f/stb.h16
-rw-r--r--contrib/gcc/f/stc.c50
-rw-r--r--contrib/gcc/f/stc.h2
-rw-r--r--contrib/gcc/f/std.c129
-rw-r--r--contrib/gcc/f/std.h2
-rw-r--r--contrib/gcc/f/ste.c3020
-rw-r--r--contrib/gcc/f/ste.h14
-rw-r--r--contrib/gcc/f/storag.c2
-rw-r--r--contrib/gcc/f/storag.h2
-rw-r--r--contrib/gcc/f/stp.c2
-rw-r--r--contrib/gcc/f/stp.h2
-rw-r--r--contrib/gcc/f/str-1t.fin2
-rw-r--r--contrib/gcc/f/str-2t.fin2
-rw-r--r--contrib/gcc/f/str-fo.fin2
-rw-r--r--contrib/gcc/f/str-io.fin2
-rw-r--r--contrib/gcc/f/str-nq.fin2
-rw-r--r--contrib/gcc/f/str-op.fin2
-rw-r--r--contrib/gcc/f/str-ot.fin2
-rw-r--r--contrib/gcc/f/str.c2
-rw-r--r--contrib/gcc/f/str.h2
-rw-r--r--contrib/gcc/f/sts.c14
-rw-r--r--contrib/gcc/f/sts.h16
-rw-r--r--contrib/gcc/f/stt.c8
-rw-r--r--contrib/gcc/f/stt.h8
-rw-r--r--contrib/gcc/f/stu.c8
-rw-r--r--contrib/gcc/f/stu.h2
-rw-r--r--contrib/gcc/f/stv.c2
-rw-r--r--contrib/gcc/f/stv.h2
-rw-r--r--contrib/gcc/f/stw.c8
-rw-r--r--contrib/gcc/f/stw.h11
-rw-r--r--contrib/gcc/f/symbol.c15
-rw-r--r--contrib/gcc/f/symbol.def2
-rw-r--r--contrib/gcc/f/symbol.h13
-rw-r--r--contrib/gcc/f/system.j2
-rw-r--r--contrib/gcc/f/target.c4
-rw-r--r--contrib/gcc/f/target.h30
-rw-r--r--contrib/gcc/f/tconfig.j2
-rw-r--r--contrib/gcc/f/tm.j2
-rw-r--r--contrib/gcc/f/top.c37
-rw-r--r--contrib/gcc/f/top.h11
-rw-r--r--contrib/gcc/f/toplev.j2
-rw-r--r--contrib/gcc/f/tree.j2
-rw-r--r--contrib/gcc/f/type.c2
-rw-r--r--contrib/gcc/f/type.h2
-rw-r--r--contrib/gcc/f/version.c2
-rw-r--r--contrib/gcc/f/version.h2
-rw-r--r--contrib/gcc/f/where.c4
-rw-r--r--contrib/gcc/f/where.h2
-rw-r--r--contrib/gcc/final.c230
-rw-r--r--contrib/gcc/fix-header.c140
-rwxr-xr-xcontrib/gcc/fixincludes155
-rwxr-xr-xcontrib/gcc/fixproto27
-rw-r--r--contrib/gcc/flags.h59
-rw-r--r--contrib/gcc/floatlib.c627
-rw-r--r--contrib/gcc/flow.c4610
-rw-r--r--contrib/gcc/fold-const.c714
-rw-r--r--contrib/gcc/frame.c53
-rw-r--r--contrib/gcc/frame.h24
-rw-r--r--contrib/gcc/function.c1212
-rw-r--r--contrib/gcc/function.h36
-rw-r--r--contrib/gcc/gansidecl.h86
-rw-r--r--contrib/gcc/gcc.14
-rw-r--r--contrib/gcc/gcc.c1048
-rw-r--r--contrib/gcc/gcc.texi699
-rw-r--r--contrib/gcc/gccspec.c43
-rw-r--r--contrib/gcc/gcov-io.h12
-rw-r--r--contrib/gcc/gcov.c120
-rw-r--r--contrib/gcc/gcse.c1607
-rw-r--r--contrib/gcc/gen-protos.c46
-rw-r--r--contrib/gcc/genattr.c49
-rw-r--r--contrib/gcc/genattrtab.c378
-rw-r--r--contrib/gcc/gencheck.c18
-rw-r--r--contrib/gcc/gencodes.c49
-rw-r--r--contrib/gcc/genconfig.c49
-rw-r--r--contrib/gcc/genemit.c63
-rw-r--r--contrib/gcc/genextract.c108
-rw-r--r--contrib/gcc/genflags.c49
-rw-r--r--contrib/gcc/gengenrtl.c66
-rw-r--r--contrib/gcc/genopinit.c61
-rw-r--r--contrib/gcc/genoutput.c254
-rw-r--r--contrib/gcc/genpeep.c51
-rw-r--r--contrib/gcc/genrecog.c206
-rw-r--r--contrib/gcc/getpwd.c9
-rw-r--r--contrib/gcc/glimits.h2
-rw-r--r--contrib/gcc/global.c389
-rw-r--r--contrib/gcc/gmon.c2
-rw-r--r--contrib/gcc/graph.c475
-rw-r--r--contrib/gcc/gthr-vxworks.h18
-rw-r--r--contrib/gcc/gthr.h8
-rw-r--r--contrib/gcc/haifa-sched.c600
-rw-r--r--contrib/gcc/halfpic.c10
-rw-r--r--contrib/gcc/halfpic.h6
-rw-r--r--contrib/gcc/hash.c137
-rw-r--r--contrib/gcc/hash.h85
-rw-r--r--contrib/gcc/hwint.h96
-rw-r--r--contrib/gcc/input.h2
-rw-r--r--contrib/gcc/integrate.c585
-rw-r--r--contrib/gcc/integrate.h46
-rw-r--r--contrib/gcc/intl.c6
-rw-r--r--contrib/gcc/intl.h52
-rw-r--r--contrib/gcc/invoke.texi1505
-rw-r--r--contrib/gcc/jump.c1046
-rw-r--r--contrib/gcc/lcm.c799
-rw-r--r--contrib/gcc/libgcc2.c538
-rw-r--r--contrib/gcc/local-alloc.c461
-rw-r--r--contrib/gcc/longlong.h10
-rw-r--r--contrib/gcc/loop.c4488
-rw-r--r--contrib/gcc/loop.h100
-rw-r--r--contrib/gcc/machmode.h118
-rw-r--r--contrib/gcc/mbchar.c290
-rw-r--r--contrib/gcc/mbchar.h41
-rw-r--r--contrib/gcc/md.texi86
-rw-r--r--contrib/gcc/mips-tdump.c112
-rw-r--r--contrib/gcc/mips-tfile.c246
-rw-r--r--contrib/gcc/objc/Make-lang.in161
-rw-r--r--contrib/gcc/objc/Makefile.in48
-rw-r--r--contrib/gcc/objc/config-lang.in2
-rw-r--r--contrib/gcc/objc/lang-specs.h96
-rw-r--r--contrib/gcc/objc/objc-act.c165
-rw-r--r--contrib/gcc/objc/objc-tree.def2
-rw-r--r--contrib/gcc/optabs.c705
-rw-r--r--contrib/gcc/output.h67
-rw-r--r--contrib/gcc/prefix.c120
-rw-r--r--contrib/gcc/prefix.h28
-rw-r--r--contrib/gcc/print-rtl.c150
-rw-r--r--contrib/gcc/print-tree.c12
-rw-r--r--contrib/gcc/profile.c15
-rw-r--r--contrib/gcc/protoize.c533
-rw-r--r--contrib/gcc/pself4.c2
-rw-r--r--contrib/gcc/pself5.c5
-rw-r--r--contrib/gcc/real.c569
-rw-r--r--contrib/gcc/real.h18
-rw-r--r--contrib/gcc/recog.c817
-rw-r--r--contrib/gcc/recog.h105
-rw-r--r--contrib/gcc/reg-stack.c787
-rw-r--r--contrib/gcc/regclass.c685
-rw-r--r--contrib/gcc/regmove.c555
-rw-r--r--contrib/gcc/regs.h21
-rw-r--r--contrib/gcc/reload.c1229
-rw-r--r--contrib/gcc/reload.h106
-rw-r--r--contrib/gcc/reload1.c6529
-rw-r--r--contrib/gcc/reorg.c1428
-rw-r--r--contrib/gcc/resource.c1289
-rw-r--r--contrib/gcc/resource.h46
-rw-r--r--contrib/gcc/rtl.c86
-rw-r--r--contrib/gcc/rtl.def30
-rw-r--r--contrib/gcc/rtl.h302
-rw-r--r--contrib/gcc/rtl.texi229
-rw-r--r--contrib/gcc/rtlanal.c334
-rw-r--r--contrib/gcc/sbitmap.c470
-rw-r--r--contrib/gcc/sbitmap.h122
-rw-r--r--contrib/gcc/scan-decls.c11
-rw-r--r--contrib/gcc/scan.c2
-rw-r--r--contrib/gcc/scan.h12
-rw-r--r--contrib/gcc/sched.c270
-rw-r--r--contrib/gcc/sdbout.c89
-rw-r--r--contrib/gcc/stab.def2
-rw-r--r--contrib/gcc/stmt.c1098
-rw-r--r--contrib/gcc/stor-layout.c98
-rw-r--r--contrib/gcc/stupid.c223
-rw-r--r--contrib/gcc/system.h249
-rw-r--r--contrib/gcc/tlink.c183
-rw-r--r--contrib/gcc/tm.texi371
-rw-r--r--contrib/gcc/toplev.c2208
-rw-r--r--contrib/gcc/toplev.h121
-rw-r--r--contrib/gcc/tree.c277
-rw-r--r--contrib/gcc/tree.def76
-rw-r--r--contrib/gcc/tree.h190
-rw-r--r--contrib/gcc/unroll.c1253
-rw-r--r--contrib/gcc/varasm.c267
-rw-r--r--contrib/gcc/varray.h43
-rw-r--r--contrib/gcc/version.c2
-rw-r--r--contrib/gcc/xcoffout.c4
-rw-r--r--contrib/gcc/xcoffout.h21
499 files changed, 124694 insertions, 75734 deletions
diff --git a/contrib/gcc/BUGS b/contrib/gcc/BUGS
index 33c9386..2d875a0 100644
--- a/contrib/gcc/BUGS
+++ b/contrib/gcc/BUGS
@@ -1,9 +1,9 @@
-If you think you may have found a bug in GNU CC, please
+If you think you may have found a bug in GCC, please
read the Bugs section of the GCC manual for advice on
(1) how to tell when to report a bug,
(2) where to send your bug report, and
-(2) how to write a useful bug report and what information
+(3) how to write a useful bug report and what information
it needs to have.
There are three ways to read the Bugs section.
@@ -20,4 +20,8 @@ to get to the section on bugs. Or use standalone Info in
a like manner. (Standalone Info is part of the Texinfo distribution.)
(3) By hand. Search for the chapter "Reporting Bugs" in gcc.texi, or
- cat /usr/local/info/gcc* | more "+/^File: emacs, Node: Bugs,"
+ cat /usr/local/info/gcc* | more "+/^File: gcc.info, Node: Bugs,"
+
+You may also want to take a look at the GCC FAQ, in which there are
+additional instructions for submitting bug reports:
+ http://www.gnu.org/software/gcc/faq.html#bugreport
diff --git a/contrib/gcc/ChangeLog b/contrib/gcc/ChangeLog
index f1be44e..446c775 100644
--- a/contrib/gcc/ChangeLog
+++ b/contrib/gcc/ChangeLog
@@ -1,14110 +1,17060 @@
-Sun Mar 14 02:38:07 PST 1999 Jeff Law (law@cygnus.com)
+Mon Aug 16 01:29:24 PDT 1999 Jeff Law (law@cygnus.com)
- * egcs-1.1.2 Released.
+ * gcc-2.95.1 Released.
-Sun Mar 14 03:23:47 1999 Jeffrey A Law (law@cygnus.com)
+1999-08-13 Michael Meissner <meissner@cygnus.com>
- * README, gcc.1, gcc.texi, version.c: Update for egcs-1.1.2 release.
+ * Makefile.in (GCC_FOR_TARGET): Move -B./ after the tooldir -B.
-Thu Mar 11 14:00:58 1999 Richard Henderson <rth@cygnus.com>
+Fri Aug 13 01:42:24 1999 Jeffrey A Law (law@cygnus.com)
- * alpha.h (HARD_REGNO_MODE_OK): Disallow QI/HImode in fp regs.
- (MODES_TIEABLE_P): Update.
+ Tue Aug 3 00:03:41 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * fixincludes: Fix the return type of bsearch, char* -> void*.
+ * fixinc/inclhack.def: Likewise.
-Thu Mar 11 00:20:52 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
+Fri Aug 13 01:29:57 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * gcc.texi: Update bug reporting instructions to match
- current ezmlm list reality.
+ * dwarfout.c (fundamental_type_code): Return FT_boolean for
+ INTEGER_TYPE with precision==1, it's __java_boolean.
-Mon Mar 8 01:19:23 1999 Jeffrey A Law (law@cygnus.com)
+1999-08-11 Richard Earnshaw (rearnsha@arm.com)
- * version.c: Bump for prerelease.
+ * emit-rtl.c (mark_reg_pointer): Don't increase the alignment of
+ a register that is already known to be a pointer.
-Mon Mar 8 01:16:30 1999 Manfred Hollstein <manfred@s-direktnet.de>
- Jeff Law <law@cygnus.com>
+1999-08-11 Bruce Korb <ddsinc09@ix.netcom.com>
- * configure.in (cpp_install_dir): Initialize from $enable_cpp
- if that's looking like a pathname.
- * configure: Rebuilt.
+ * fixinc/inclhack.tpl: Only install assert.h conditionally.
+ * fixinc/inclhack.sh: Regenerated.
+ * fixinc/fixincl.sh: Regenerated.
- * Makefile.in (install-cpp, uninstall-cpp): cpp_install_dir is an
- absolute pathname, not a $prefix relative pathname.
+Wed Aug 11 00:34:22 1999 Joe Buck <jbuck@synopsys.com>
-Fri Mar 5 01:19:22 1999 Jeffrey A Law (law@cygnus.com)
+ * invoke.texi: s/GNU CC/GCC/ for consistency with gcc.texi.
+ Fix documentation of -ansi flag to describe its C++ behavior.
+ Remove bogus reference to GCC 2.9.
- Thu Dec 17 18:21:49 1998 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- * fixincludes (c_asm.h): Wrap Digital UNIX V4.0B DEC C specific
- asm() etc. function declarations in __DECC.
+Tue Aug 10 22:40:36 1999 Jeffrey A Law (law@cygnus.com)
-Wed Mar 3 23:55:14 1999 Zack Weinberg <zack@rabi.columbia.edu>
+ Thu Aug 5 22:27:15 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * config/sh/lib1funcs.asm (___movstrSI0): Change or r0,r0,r0 to nop.
+ (___mulsi3): Use '!' comment character.
- * cpp.in: New. Better cpp shell script.
- * cpp.sh: Delete.
- * Makefile.in (cpp.sh): Build from cpp.in
+Sat Aug 7 00:06:30 1999 Jeffrey A Law (law@cygnus.com)
-Tue Mar 2 01:27:52 1999 H.J. Lu (hjl@gnu.org)
+ * gcc.texi: Update bug reporting text.
- * Makefile.in (cpp_install_dir, INSTALL_CPP, UNINSTALL_CPP): New
- variables.
- (install-cpp, uninstall-cpp): New targets.
- (install-normal): Depend on $(INSTALL_CPP).
- (uninstall): Depend on $(UNINSTALL_CPP).
- * configure.in (cpp_install_dir): New, substitute.
- (tmake_file): Added t-install-cpp for --enable-cpp.
- * configure: Rebuilt.
- * cpp.sh: New cpp script.
- * config/t-install-cpp: New target fragment.
+ Tue Jul 20 17:07:54 1999 Richard Henderson <rth@cygnus.com>
+ * rs6000.h (struct rs6000_args): Add sysv_gregno.
+ * rs6000.c (init_cumulative_args): Init sysv_gregno.
+ (function_arg_boundary): Align DFmode.
+ (function_arg_advance): Restructure for ABI_V4; use sysv_gregno
+ to get fp reg and stack overflow correct.
+ (function_arg): Likewise.
+ (function_arg_pass_by_reference): True for TFmode for ABI_V4.
+ (setup_incoming_varargs): Restructure for ABI_V4; use
+ function_arg_advance to skip final named argument.
+ (expand_builtin_saveregs): Properly unskip the last integer arg
+ when doing varargs. Adjust overflow location calculation.
+ * ginclude/va-ppc.h (struct __va_list_tag): Make gpr and fpr
+ explicitly unsigned.
+ (__VA_FP_REGSAVE): Use new OFS argument instead of AP->fpr directly.
+ (__VA_GP_REGSAVE): Similarly.
+ (__va_longlong_p): Delete.
+ (__va_arg_type_violation): New declaration.
+ (va_arg): Restructure. Flag promotion errors. Align double.
+ TFmode passed by reference.
+ * rs6000.md (movdi_32+1): Use GEN_INT after arithmetic
+ in the HOST_BITS_PER_WIDE_INT > 32 case.
-Mon Mar 1 23:38:20 1999 Jeffrey A Law (law@cygnus.com)
+1999-08-6 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
- Tue Feb 2 23:38:35 1999 David O'Brien <obrien@FreeBSD.org>
- * i386/freebsd*.h now allows '$' in label names and does not use the
- PCC struct return method.
+ * reg-stack.c (change_stack) Fixed problem with negative array index.
- Wed Dec 30 23:00:28 1998 David O'Brien <obrien@NUXI.com>
- * configure.in (FreeBSD ELF): Needs special crt files.
- * configure: Rebuilt.
+Fri Aug 6 20:41:08 1999 Jeffrey A Law (law@cygnus.com)
-Sun Feb 28 14:47:53 1999 Arturo Montes <mitosys@colomsat.com.co>
+ Mon Jul 19 15:09:29 1999 David Edelsohn <edelsohn@gnu.org>
+ * rs6000.md (arithmetic, logical, and shift Rc combiner patterns):
+ Disable patterns performing SImode comparisons with SImode values
+ if TARGET_POWERPC64 and instruction does not sign-extend or does
+ not mask to narrower than SImode, i.e. where bit 31 and bit 63 may
+ differ for signed quantities.
+ (indirect_jump): Add expander to choose RTL based on TARGET_64BIT.
+ (tablejump): Patterns contingent on TARGET_64BIT not TARGET_POWERPC64.
+ (decrement_and_branch_on_count): Add 64-bit variant.
- * config/i386/t-sco5gas (crti.o): New target.
+Thu Aug 5 02:40:42 1999 Jeffrey A Law (law@cygnus.com)
-Sun Feb 28 00:50:28 1999 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- Jeffrey A Law (law@cygnus.com)
+ * gcc.c: Update URLs and mail addresses.
+ * gcc.texi: Likewise.
- * cse.c (fold_rtx): Update comments for (const (minus (label) (label)))
- case.
- (cse_insn): Avoid creating a bogus REG_EQUAL note for
- (const (minus (label) (label)))
- (record_jump_cond): Fix mismatched paren in comment.
-
-Sat Feb 27 22:48:38 1999 H.J. Lu (hjl@gnu.org)
- Jeffrey A Law (law@cygnus.com)
+Thu Aug 5 01:14:13 1999 Daniel Jacobowitz <drow@false.org>
- * frame.h: Update some comments.
- * crtstuff.c (TARGET_ATTRIBUTE_WEAK): Define.
- (__register_frame_info, __deregister_frame_info): Declare using
- TARGET_WEAK_ATTRIBUTE.
- (__do_global_dtors_aux): Check if __deregister_frame_info is
- zero before calling it.
- (__do_global_dtors): Likewise.
- (frame_dummy): Check if __register_frame_info is zero before
- calling it.
- (__frame_dummy): Likewise.
-
-Sat Feb 27 19:47:39 1999 Marc Espie <espie@openbsd.org>
+ * rs6000.c (current_file_function_operand): Return zero for
+ weak functions.
+ (rs6000_encode_section_info): Do not set SYMBOL_REF_FLAG for
+ weak symbols.
+ * rs6000.h (ENCODE_SECTION_NIFO): Do not set SYMBOL_REF_FLAG
+ for weak symbols.
- * config/t-openbsd (T_CFLAGS): Add -Dmkstemps=my_mkstemps.
+Thu Aug 5 00:56:30 1999 Geoffrey Keating <geoffk@cygnus.com>
-Sat Feb 27 19:37:04 1999 Arturo Montes <mitosys@colomsat.com.co>
+ * rs6000.c (rs6000_stack_info): For ABI_V4/ABI_SOLARIS -fpic, always
+ allocate space in the stack frame for the PIC register.
- * i386/t-sco5 (crti.o): New target.
- * i386/sco5.h (STARTFILE_SPEC): Include crti.o when
- linking -shared.
- * configure.in (i[34567]86-*-sco3.2v5*): Add crti.o.
- * configure: Rebuilt.
+Thu Aug 5 00:20:47 1999 Jeffrey A Law (law@cygnus.com)
-Sat Feb 27 19:29:46 1999 Toon Moene <toon@moene.indiv.nluug.nl>
- Mark Mitchell <mark@markmitchell.com>
- Jeffrey A Law (law@cygnus.com)
+ * m68k.md (xordi3, anddi3): These patterns are not available on
+ the coldfire.
- * alias.c (true_dependence): Only apply MEM_IN_STRUCT_P tests
- when flag_structure_noalias is set.
- * toplev.c (flag_structure_noalias): New variable.
- (f_options): Add -fstructure-noalias.
- * flags.h (flag_structure_noalias): Declare.
- * invoke.texi: Update documentation.
+Wed Aug 4 23:39:20 1999 Mark Mitchell <mark@codesourcery.com>
-Sat Feb 27 19:19:36 1999 Jeffrey A Law (law@cygnus.com)
+ * real.c (GET_REAL): Don't violate ANSI/ISO aliasing rules.
+ (PUT_REAL): Likewise.
- * SERVICE: Update from the FSF.
+Wed Aug 4 02:15:32 1999 Richard Henderson <rth@cygnus.com>
-Fri Feb 26 19:31:25 1999 Dave Love <fx@gnu.org>
+ * jump.c (delete_insn): Delete the addr_vec when deleting a tablejump.
- * md.texi, invoke.texi: Fix unterminated @xrefs.
+Wed Aug 4 01:08:44 1999 Jeffrey A Law (law@cygnus.com)
-Fri Feb 26 01:47:46 1999 Jeffrey A Law (law@cygnus.com)
+ * flow.c (delete_unreachable_blocks): Do not call merge_blocks
+ or tidy_fallthru_edge if the last insn in the block is not
+ an unconditional jump or a simple conditional jump.
- Sun Jan 17 03:20:47 1999 H.J. Lu (hjl@gnu.org)
- * reg-stack.c (subst_stack_regs_pat): Abort if the destination
- of a FP conditional move is not on the FP register stack.
+Tue Aug 3 03:51:20 1999 Jeffrey A Law (law@cygnus.com)
- * Makefile.in (compare, gnucompare): We do not care about
- comparison failures for objc/linking.o either.
+ * cse.c (cse_insn): Fix dumb thinko in last change.
-Wed Feb 24 23:17:41 1999 Jeffrey A Law (law@cygnus.com)
+Mon Aug 2 23:45:45 1999 Hans-Peter Nilsson <hp@bitrange.com>
- Thu Feb 18 19:59:37 1999 Marc Espie <espie@cvs.openbsd.org>
- * configure.in :Handle OpenBSD platforms.
- * configure: Rebuilt.
- * config/openbsd.h: New file.
- * config/xm-openbsd.h: New file.
- * config/t-openbsd: New file.
- * config/t-openbsd-thread: New file.
+ * dwarf2out.c (add_location_or_const_value_attribute): Correct
+ test for sizes of passed and declared parameter types.
- Thu Feb 18 13:15:56 1999 Marc Espie <espie@cvs.openbsd.org>
- * alpha/openbsd.h: New file.
- * alpha/xm-openbsd.h: New file.
- * sparc/openbsd.h: New file.
- * sparc/xm-openbsd.h: New file.
- * m68k/openbsd.h: New file.
- * m68k/xm-openbsd.h: New file.
- * i386/openbsd.h: New file, originally from netbsd.
- * i386/xm-openbsd.h: New file.
+Mon Aug 2 12:45:09 1999 Richard Henderson <rth@cygnus.com>
- Wed Nov 19 12:56:54 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
- * configure.in: Fix check for <inttypes.h>.
- * configure: Rebuilt.
+ * alpha.c (override_options): Don't force ALPHA_TP_PROG for ev6.
- * varasm.c (declare_weak): If HANDLE_PRAGMA_WEAK, call
- handle_pragma_weak.
-
-Wed Feb 24 03:17:56 1999 Jeffrey A Law (law@cygnus.com)
+Mon Aug 2 01:34:22 1999 Jeffrey A Law (law@cygnus.com)
- * version.c: Bump for prerelease.
+ * fix-header.c (main): When testing for CONTINUED, use string
+ equality, not pointer equality.
- * Makefile.in (compare, gnucompare): Ignore comparison failures
- for some objects in the ObjC runtime.
+Mon Aug 2 01:27:24 1999 Dan Nicolaescu <dann@ics.uci.edu>
-Wed Feb 24 02:39:08 1999 Jeffrey A Law (law@cygnus.com)
+ * sparc.c (sparc_block_profiler): Use the %g2 register, not %o0.
- Mon Dec 7 16:15:51 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * sh.c (output_far_jump): Emit braf only for TARGET_SH2.
+Sun Aug 1 22:46:42 1999 Jeffrey A Law (law@cygnus.com)
- Mon Nov 23 16:46:46 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * va-sh.h (__va_arg_sh1): Use __asm instead of asm.
+ * cse.c (cse_insn): Fix loop which deletes insns after a jump
+ that has become an unconditional jump.
-Tue Feb 23 00:38:17 1999 Jeffrey A Law (law@cygnus.com)
+ * m68k.c (output_function_prologue): Fix typo in CPU32 case.
+ (output_function_epilogue): Similarly.
- Thu Sep 3 00:23:21 1998 Richard Henderson <rth@cygnus.com>
- * ginclude/va-alpha.h: Protect entire second portion of the
- file against double inclusion.
+ Tue Jul 20 12:37:30 1999 Hans-Peter Nilsson <hp@bitrange.com>
+ * dwarf2out.c (output_abbrev_section): Terminate with a zero.
- Mon Aug 31 13:57:55 1998 Richard Henderson <rth@cygnus.com>
- * alpha/va_list.h: New file.
- * alpha/x-alpha (EXTRA_HEADERS): New. Add va_list.h.
+ Thu Jul 15 15:40:09 1999 Jim Wilson <wilson@cygnus.com>
+ * tree.c (build_type_attribute_variant): Move current_obstack restore
+ after build_qualified_type call.
- Sat Aug 1 17:59:30 1998 Richard Henderson <rth@cygnus.com>
- * ginclude/va-alpha.h (va_list): Use a typedef, not a define.
+ Fri Jun 4 03:20:40 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * sh.c (fixup_addr_diff_vecs): Emit braf reference label.
+ (braf_label_ref_operand): Delete.
+ * sh.h (PREDICATE_CODES): Remove braf_label_ref_operand.
+ * sh.md (casesi_jump_2): Operand1 is now the inside of a
+ label_ref, and has no predicate.
+ The patten has a predicate to guard against invalid substitutions.
+ (dummy_jump): Delete.
+ (casesi): Update use of casesi_jump_2.
-Sun Feb 21 20:35:10 1999 Jeffrey A Law (law@cygnus.com)
+Thu Jul 31 12:34:45 1999 Joe Buck <jbuck@synopsys.com>
- Wed Oct 28 22:58:35 1998 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (append_random_chars): New fn.
- (get_file_function_name_long): Use it.
+ * gcc.texi: Use terms "GNU Compiler Collection" and "GCC".
+ Also update copyright.
- Thu Aug 13 17:08:11 1998 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (get_file_function_name_long): Split out...
- (get_file_function_name): ...from here.
+Wed Jul 28 21:39:31 PDT 1999 Jeff Law (law@cygnus.com)
- * config/aoutos.h (ASM_OUTPUT_CONSTRUCTOR): Delete.
- (ASM_OUTPUT_DESTRUCTOR, ASM_OUTPUT_GC_ENTRY): Likewise.
- * tm.texi: Update docs for constructors and destructors.
+ * gcc-2.95 Released.
-Tue Feb 16 21:02:07 1999 Anton Hartl <toni@devsoft.com>
+ * verison.c: No longer a prerelease.
- * rs6000.md (call_value): Fix typo.
+Wed Jul 28 13:49:03 1999 Jeffrey A Law (law@cygnus.com)
-Tue Feb 16 01:37:33 1999 Charles G Waldman <cgw@alum.mit.edu>
+ * README: Update.
- * c-common.c (shorten_compare): Get the min/max value from the
- underlying type of an enumeration, not the enumerated type itself.
+Sun Jul 25 21:40:33 1999 Jeffrey A Law (law@cygnus.com)
-Mon Feb 15 11:33:51 1999 Jeffrey A Law (law@cygnus.com)
+ * gcc.texi: More changes related to list conversion.
+ * invoke.texi: Likewise.
- Sat Jan 16 21:48:17 1999 Marc Espie (Marc.Espie@openbsd.org)
- * gcc.c: (do_spec_1): Fix obvious typo.
+Sat Jul 17 23:58:24 1999 David Edelsohn <edelsohn@gnu.org>
- * jump.c: Include insn-attr.h.
- (delete_computation): If reload has completed and insn scheduling
- after reload is enabled, then do not depend on REG_DEAD notes.
- * Makefile.in (jump.o): Depend on insn-attr.h.
+ * rs6000.md (insv, extzv): Remove SImode dependence in named
+ patterns. Explicitly generate DImode RTL if PowerPC64 and
+ operand is DImode.
+ (insvdi): Reverse start and size in instruction template.
- * sparc.c (output_scc_insn): Add missing argument to output_cbranch.
+1999-07-17 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * gcc.texi: Update e-mail addresses and URLs to gcc.gnu.org.
+ Removed paragraph about compression of files and size limitation,
+ duplicated in the FAQ. Use gcc-patches for posting patches.
+ * gcc.c (main): Updated URL with bug reporting instructions to
+ gcc.gnu.org. Removed e-mail address.
+ * system.h (abort): Likewise.
- * loop.c (mark_loop_jump): Handle LO_SUM. If we encounter something
- we do not understand, mark the loop and containing loops as invalid.
+1999-07-17 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Sun Feb 14 23:05:34 1999 Jeffrey A Law (law@cygnus.com)
+ * Makefile.in (stmp-multilib-sub): Make the files extracted
+ from $(LIBGCC1) writable.
- Tue Feb 9 21:14:03 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * alias.c (init_alias_analysis): Avoid self-referential value
- when setting reg_known_value from REG_EQUAL notes.
+Fri Jul 16 01:39:57 1999 Jeffrey A Law (law@cygnus.com)
- Mon Aug 17 02:03:55 1998 Richard Henderson <rth@cygnus.com>
- * regclass.c (allocate_reg_info): Respect MIN when clearing data.
+ * m68k.c (output_function_prologue): Fix computation of save mask
+ when generating PIC code.
- * loop.c (scan_loop): Fix typo in last change.
+1999-07-12 Joseph S. Myers <jsm28@cam.ac.uk>
-Sat Feb 13 11:53:12 1999 Jeffrey A Law (law@cygnus.com)
+ * invoke.texi: Typo fixes.
- 1999-02-05 Michael Meissner <meissner@cygnus.com>
- J"orn Rennecke <amylaar@cygnus.co.uk>
- * loop.c (check_dbra_loop): A store using an address giv for which
- we have no life information is not reversible.
- * loop.c (first_loop_store_insn): New file-scope variable.
- (prescan_loop): Set it.
- (check_dbra_loop): Check if a store depends on a register
- that is set after the store.
+Wed Jul 14 23:28:06 1999 Jeffrey A Law (law@cygnus.com)
- Sun Jan 31 13:22:02 1999 John Wehle (john@feith.com)
- * i386.md (movsicc, movhicc, movsfcc, movdfcc,
- movxfcc, movdicc): Delete unconstrained alternatives.
- * i386.c (output_fp_conditional_move,
- output_int_conditional_move): Delete unused case.
+ * emit-rtl.c (gen_realpart): Issue an error for cases GCC can not
+ handle at this time instead of silently generating incorrect code.
+ (gen_imagpart): Likewise.
- Tue Aug 18 10:33:30 1998 Jeffrey A Law (law@cygnus.com)
- * expr.c (emit_block_move): Do not call memcpy as a libcall
- instead build up a CALL_EXPR and call it like any other
- function.
- (clear_storage): Similarly for memset.
+ * reload.c (find_reloads): Emit a USE for a pseudo register without
+ a hard register if we could not create an optional reload for the
+ pseudo.
- Sun Sep 20 20:57:02 1998 Robert Lipe <robertl@dgii.com>
- * configure.in (i*86-*-sysv5*): Use fixinc.svr4 to patch byteorder
- problems.
- * configure: Regenerate.
+Wed Jul 14 01:57:39 1999 Richard Henderson <rth@cygnus.com>
-Fri Feb 12 23:20:54 1999 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+ * regclass.c (scan_one_insn): Notice subregs that change the
+ size of their operand.
+ (record_reg_classes): Use that to obey CLASS_CANNOT_CHANGE_SIZE.
- * loop.c (scan_loop): Call reg_in_basic_block_p before
- loop_reg_used_before_p.
+Wed Jul 14 01:37:06 1999 Jeffrey A Law (law@cygnus.com)
-Thu Feb 11 01:53:10 1999 Jeffrey A Law (law@cygnus.com)
+ * configure.in (alpha*-*-*): Include alpha/t-ieee.
+ * configure: Rebuilt.
+ * alpha/t-ieee: New file.
- Wed Nov 18 22:13:00 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * expr.c (store_expr): Don't generate load-store pair
- if TEMP is identical (according to ==) with TARGET.
+Tue Jul 13 10:44:14 1999 Jeffrey A Law (law@cygnus.com)
-Thu Feb 11 01:06:49 1999 Nathan Sidwell <nathan@acm.org>
+ Wed Jun 16 20:29:00 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * cse.c (cse_insn): Don't put hard register source into tables for
+ the last insn of a libcall.
- * fold-const.c (range_binop): Take account of the bounded nature
- of fixed length arithmetic when comparing unbounded ranges.
+ * rs6000.c (find_addr_reg): Do not select r0 as an address
+ register.
-Wed Feb 10 11:03:22 1999 Richard Henderson <rth@cygnus.com>
+Tue Jul 13 00:46:18 1999 Philippe De Muyter <phdm@macqel.be>
- * configure.in (alphaev6*): Fix typo in target_cpu_default2.
+ * m68k/x-mot3300 (XCFLAGS): List of big files now includes `cse.o'.
-Tue Feb 9 00:00:14 1999 Mark Kettenis <kettenis@gnu.org>
+Mon Jul 12 23:39:08 1999 Jeffrey A Law (law@cygnus.com)
- * configure.in (i[34567]86-*gnu*): Set float_format to i386.
- * configure: Rebuilt.
+ * rs6000.md (movsf): Do not force easy FP constants into memory.
-Sat Feb 6 16:03:36 1999 Jeffrey A Law (law@cygnus.com)
+Sun Jul 11 11:21:24 1999 Jason Merrill <jason@yorick.cygnus.com>
- * invoke.texi, expr.c: Update email addresses.
+ * toplev.c (main): Don't complain about saying -gdwarf.
- * gcc.c, gcc.texi: Update email addresses.
+Fri Jul 9 03:51:52 1999 Jeffrey A Law (law@cygnus.com)
-Sat Jan 30 05:27:25 1999 Jeffrey A Law (law@cygnus.com)
+ * version.c: Drop "gcc-" prefix from version #.
- Thu Jan 21 01:59:30 1999 Richard Henderson <rth@cygnus.com>
- * explow.c (allocate_dynamic_stack_space): Use register_operand
- instead of arith_operand, which does not exist.
+Thu Jul 8 19:15:51 1999 Jim Wilson <wilson@cygnus.com>
-Thu Jan 28 09:44:04 1999 Jeffrey A Law (law@cygnus.com)
+ * unroll.c (unroll_loops): Don't delete named CODE_LABEL or
+ NOTE_INSN_DELETED_LABEL note.
- * configure.in (hppa1.0-hp-hpux10*): Use t-pa.
- * configure: Rebuilt.
+Thu Jul 8 14:18:46 1999 Richard Henderson <rth@cygnus.com>
-Thu Jan 21 23:27:06 1999 Jeffrey A Law (law@cygnus.com)
+ * m68k.c (output_function_prologue): Add pic register to mask
+ if live and flag_pic.
+ (output_function_epilogue): Likewise.
- * m68k.md (ashldi_const): Disable for !TARGET_5200. Fix indention.
- (ashldi3 expander): Similarly. Update comments.
- (ashrdi_const, lshrdi_const): Fix indention.
- (ashrdi3, lshrdi3): FIx indention. Update comments.
+Thu Jul 8 10:28:25 1999 Craig Burley <craig@jcb-sc.com>
-Thu Jan 21 20:33:31 1999 Richard Henderson <rth@cygnus.com>
+ * invoke.texi (DEC Alpha Options): Put @end table at
+ beginning of line, to avoid confusing texi2html.
- * rs6000.h (LEGITIMIZE_RELOAD_ADDRESS): Recognize and accept
- transformations that we have performed earlier.
- * alpha.h (LEGITIMIZE_RELOAD_ADDRESS): Likewise.
+Wed Jul 7 02:00:04 1999 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
-Sun Jan 17 20:39:20 1999 Richard Henderson <rth@cygnus.com>
+ * reload1.c (gen_reload): When synthesizing a 3 operand add
+ sequence, improve test for when to reload OP1 into the reload
+ register instead of OP0.
- * jump.c (rtx_renumbered_equal_p): Special case CODE_LABEL.
+Wed Jul 7 01:38:03 1999 Jim Wilson <wilson@cygnus.com>
-Sun Jan 17 19:01:47 1999 Jeffrey A Law (law@cygnus.com)
+ * unroll.c (unroll_loop): Don't delete NOTE_INSN_DELETED_LABEL notes.
- * i386.md (integer conditional moves): Add missing earlyclobbers.
+1999-07-07 Manfred Hollstein <mhollstein@cygnus.com>
- * regmove.c (optimize_reg_copy_1): Undo Aug 18 change. Update
- REG_N_CALLS_CROSSED and REG_LIVE_LENGH if and only if we change
- where a register is live.
+ * m88k/dguxbcs.h (CPP_SPEC): Add missing \ in multi-line
+ string literal.
-Fri Jan 15 01:19:42 1999 Jeffrey A Law (law@cygnus.com)
+Wed Jul 7 01:16:43 1999 Richard Henderson <rth@cygnus.com>
- * unroll.c (find_splittable_givs): For a DEST_ADDR giv, do not share
- a register with another DEST_ADDR giv if the address is not valid.
+ * ginclude/varargs.h (__builtin_va_alist_t): New typedef.
+ (va_dcl): Use __builtin_va_alist_t.
- * h8300.h (ASM_OUTPUT_LABELREF): Use asm_fprintf, not fprintf.
+Wed Jul 7 01:13:31 1999 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jan 11 20:23:34 1999 Richard Henderson <rth@cygnus.com>
+ * dwarf2out.c (gen_struct_or_union_type_die): Only remember types
+ on the permanent_obstack.
+ * dwarfout.c (output_type): Likewise.
- * sparc.c (legitimize_pic_address): Treat labels like symbols.
- (emit_move_sequence): Likewise.
- * sparc.h (PRINT_OPERAND_ADDRESS): Likewise.
- (ASM_OUTPUT_ADDR_VEC_ELT): Don't special case CM_MEDLOW.
- (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise. Don't reference magic `1b'.
- * sparc.md (move_pic_label_si): Kill.
- (move_label_di): Kill.
- (pic_tablejump_32, pic_tablejump_64): Kill.
- (tablejump): Expose pic arithmetic to the compiler.
+Fri Jul 2 03:05:13 1999 Jeffrey A Law (law@cygnus.com)
-Thu Jan 7 00:33:33 1999 Bernd Schmidt <crux@ohara.Informatik.RWTH-Aachen.DE>
+ * dwarfout.c (field_byte_offset): Correctly compute the object's
+ byte offset for the first bit of a field which crosses an alignment
+ boundary on a !BYTES_BIG_ENDIAN target.
- * combine.c (num_sign_bit_copies): In NEG, MULT, DIV and MOD cases,
- when a test can't be performed due to limited width of
- HOST_BITS_PER_WIDE_INT, use the more conservative approximation.
- Fix UDIV case for cases where the first operand has the highest bit
- set.
+Fri Jul 2 01:36:36 1999 Robert Lipe <robertlipe@usa.net>
-Wed Jan 6 23:37:47 1999 Jeffrey A Law (law@cygnus.com)
+ * fixinc.svr4: Fix <arpa/inet.h> by deleting protos for htons and
+ ntohs.
- * h8300.h (ASM_OUTPUT_LABELREF): Define.
+Fri Jul 2 00:46:47 1999 Richard Henderson <rth@cygnus.com>
+ Jeff Law <law@cygnus.com>
-Wed Jan 6 02:23:36 1999 "Charles M. Hannum" <root@ihack.net>
+ * ginclude/varargs.h (va_dcl): Use word_mode for type of
+ __builtin_va_list.
- * expr.c (store_expr): If the lhs is a memory location pointed
- to be a postincremented (or postdecremented) pointer, always
- force the rhs to be evaluated into a pseudo.
+ * except.c: Include intl.h.
+ (expand_eh_return): Set current_function_cannot_inline.
+ (save_eh_status, restore_eh_status): Twiddle eh_return_stub_label.
+ * function.h (struct function): Add eh_return_stub_label.
+ * flow.c (delete_unreachable_blocks): Don't merge across EH edges.
+ * Makefile.in (except.o): Depend on intl.h.
-Fri Jan 1 11:48:20 1999 Jeffrey A Law (law@cygnus.com)
+Fri Jul 2 00:04:23 1999 David Edelsohn <edelsohn@gnu.org>
- * i386.md (doubleword shifts): Fix dumb mistakes in previous change.
+ * rs6000.md (movdf_hardfloat32): Handle PRE_INC and PRE_DEC the
+ same as offsettable in cases 1 and 2.
-Wed Dec 30 23:44:11 1998 Jeffrey A Law (law@cygnus.com)
+1999-07-01 Mark Kettenis <kettenis@gnu.org>
- * m68k.md (adddi_dilshr32): Allow all operands to be registers too.
- (adddi_dishl32): Similarly.
+ * config/i386/gnu.h (CPP_SPEC): Define __PIC__ and __pic__ if
+ -fPIC or -fpic is specified.
- * cse.c (invalidate_skipped_block): Call invalidate_from_clobbers
- for each insn in the skipped block.
+Wed Jun 30 23:56:01 1999 Jeffrey A Law (law@cygnus.com)
- * i386.md (doubleword shifts): Avoid namespace pollution.
+ * expr.c (emit_block_move): Use copy_to_mode_reg for
+ !TARGET_MEM_FUNCTIONS case too.
-Mon Dec 28 10:44:40 1998 Richard Henderson <rth@cygnus.com>
+Tue Jun 29 01:37:53 1999 Jeffrey A Law (law@cygnus.com)
- * combine.c (subst): Process the inputs to a parallel asm_operands
- only once.
+ * mips.md (leasi, leadi): New patterns.
-Sun Dec 13 00:09:47 1998 Jeffrey A Law (law@cygnus.com)
+ * expr.c (emit_block_move): Properly handle case where one of the
+ block move arguments has a queued increment or decrement.
+ (clear_storage): Similarly. Fix formatting goof.
- * i386/next.h (ASM_OUTPUT_ALIGN): Use 0x90 for fill character.
+Mon Jun 28 05:32:09 1999 Jeffrey A Law (law@cygnus.com)
- * h8300.c (h8300_encode_label): Use '&' for tiny data items.
- * h8300.h (TINY_DATA_NAME_P): Likewise.
- (STRIP_NAME_ENCODING): Handle '&'.
+ * m68k.h (CONDITIONAL_REGISTER_USAGE): Define for !SUN_FPA
+ case. Also make the PIC register call_used.
-Wed Dec 2 01:44:58 1998 Jeffrey A Law (law@cygnus.com)
+ * m68k.h (FINALIZE_PIC): Delete.
+ * m68k.c (finalize_pic): Delete.
- * egcs-1.1.1 released.
+ * m68k.h (CONDITIONAL_REGISTER_USAGE): Make the PIC register fixed
+ when -fpic/-fPIC.
-Mon Nov 23 20:28:02 1998 Mike Stump <mrs@wrs.com>
+Mon Jun 28 05:16:35 1999 Richard Henderson <rth@cygnus.com>
- * libgcc2.c (top_elt): Remove top_elt, it isn't thread safe.
- The strategy we now use is to pre allocate the top_elt along
- with the EH context so that each thread has its own top_elt.
- This is necessary as the dynmanic cleanup chain is used on the
- top element of the stack and each thread MUST have its own.
- (new_eh_context): Likewise.
- (__sjthrow): Likewise.
+ * m68k.h (PREFERRED_RELOAD_CLASS): Don't force any FP const_doubles
+ to memory.
-Mon Nov 23 09:53:44 1998 Richard Henderson <rth@cygnus.com>
+Mon Jun 28 04:07:27 1999 David Edelsohn <edelsohn@gnu.org>
- * local-alloc.c (local_alloc): Use malloc not alloca for
- reg_qty, reg_offset, ref_next_in_qty.
+ * rs6000.c (output_toc): Always use hex values for floating-point
+ constants. Store single-precision values in upper-half of TOC
+ entry in 64-bit mode.
+ * rs6000.md (floatsidf2, floatunssidf2): Add !TARGET_POWERPC64
+ to final constraints.
+ (fix_truncdfsi2 splitter): Change pattern matching fctiwz.
+ (fctiwz): Improve accuracy of RTL for pattern.
-Mon Nov 23 09:49:49 1998 Andrew MacLeod <amacleod@cygnus.com>
+ * rs6000.c (print_operand, case 'L'): Use plus_constant_for_output.
- * cplus-dem.c (demangle_prefix): Use the last "__"
- in the mangled name when looking for the signature. This allows
- template names to begin with "__".
+ * expmed.c (expand_divmod): Ensure unsigned value fits in reg_note.
-Mon Nov 23 09:40:41 1998 David Edelsohn <edelsohn@mhpcc.edu>
+Fri Jun 25 06:06:37 1999 Richard Henderson <rth@cygnus.com>
- * rs6000.h (LEGITIMIZE_ADDRESS): Add missing "goto WIN".
+ * alpha.h (MASK_SUPPORT_ARCH, MASK_CPU_EV5, MASK_CPU_EV6): Define
+ such that MASK_SUPPORT_ARCH is not negative.
-Mon Nov 9 23:29:39 1998 David Edelsohn <edelsohn@mhpcc.edu>
+Fri Jun 25 05:35:44 1999 Jeffrey A Law (law@cygnus.com)
- * rs6000.md (floatunssidf2_internal splitter): Use base register
- operand, not hard-coded SP.
+ * loop.c (verify_dominator): Properly handle ADDR_VEC and
+ ADDR_DIFF_VEC insns that appear inside loops.
-Mon Nov 9 23:05:51 1998 Richard Earnshaw (rearnsha@arm.com)
+Thu Jun 24 22:54:05 1999 David Edelsohn <edelsohn@gnu.org>
+ Jeff Law <law@cygnus.com>
- Restore ABI compatibility for NetBSD.
- * arm/netbsd.h (DEFAULT_PCC_STRUCT_RETURN): Override setting in
- arm.h
- (RETURN_IN_MEMORY): Likewise.
+ * rs6000.md (movdf_hardfloat32): Revert previous patch.
+ Handle LO_SUM the same as offsettable in cases 1 and 2.
+ * rs6000.c (find_addr_reg): Revert previous patch.
- * arm.c (add_constant): When taking the address of an item in the
- pool, get the mode of the item addressed.
+Thu Jun 24 22:43:12 1999 Philippe De Muyter <phdm@macqel.be>
- * arm.c (final_prescan_insn, case INSN): If an insn doesn't
- contain a SET or a PARALLEL, don't consider it for conditional
- execution.
+ * system.h (strstr): New external function declaration.
+ * acconfig.h (NEED_DECLARATION_STRSTR): New define slot.
+ * configure.in (GCC_NEED_DECLARATIONS): Check for strstr.
+ * config.in, configure: Rebuilt.
-Mon Nov 9 22:43:57 1998 Jean-Pierre Radley <jpr@jpr.com>
+1999-06-24 Tom Tromey <tromey@cygnus.com>
- * fixinc.sco: Paramaterize #include_next values.
- * fixinc/fixinc.sco: Likewise.
+ * gcc.c (main): Read user-specified specs files after computing
+ additional startfile_prefixes.
-Mon Nov 9 22:43:57 1998 Robert Lipe <robertl@dgii.com>
+1999-06-24 Bruce Korb <ddsinc09@ix.netcom.com>
- * fixinc.sco: Borrow code to wrap 'bool' typedefs from tinfo.h
- and term.h from fixinc.wrap.
+ *fixinc/inclhack.def(end_else_label): combined else_label
+ and endif_label and fixed the sed expression.
+ *fixinc/{fixincl.x|inclhack.sh}: regen
-Thu Nov 5 07:57:45 EST 1998 Andrew MacLeod <amacleod@cygnus.com>
+Tue Jun 22 01:58:18 1999 Jeffrey A Law (law@cygnus.com)
- * except.c (expand_fixup_region_end): Make sure outer context labels
- are not issued in an inner context during cleanups.
+ * rs6000.md (movdf_hardfloat32): Use %X instead of always emitting
+ 'x' when handling non-offsettable addresses
-Sun Nov 1 11:04:32 1998 Jeffrey A Law (law@cygnus.com)
+Tue Jun 22 00:20:05 1999 Richard Earnshaw (rearnsha@arm.com)
- * i386/linux.h (CPP_PREDEFINES): Bring back -Di386 for the last time.
+ * final.c (shorten_branches): Don't try to split an insn that has
+ been deleted.
- * From Christian Gafton:
- * i386/linux.h (CPP_PREDEFINES): Add -D__i386__.
- * sparc/linux.h (CPP_PREDEFINES): Add -D__sparc__.
- * sparc/linux64.h (CPP_PREDEFIENS): Add -D__sparc__.
+Mon Jun 21 23:32:17 1999 Jeffrey A Law (law@cygnus.com)
-Sat Oct 31 00:40:05 1998 Jeffrey A Law (law@cygnus.com)
+ Thu Jun 17 15:07 1999 Bruce Korb <ddsinc09@ix.netcom.com>
+ * fixincludes: ISCNTL patch
- * jump.c (jump_optimize): Initialize mappings from INSN_UID to
- EH region if exceptions are enabled and we're performing cross
- jump optimizations.
- (find_cross_jump): Exit loop if the insns are in different EH regions.
+Mon Jun 21 22:15:50 1999 Jeffrey A Law (law@cygnus.com)
-Fri Oct 30 00:54:25 1998 Peter Jakubek <pjak@snafu.de>
+ * rs6000.c (find_addr_reg): Handle LO_SUM addresses.
- * m68k.h (INDIRECTABLE_1_ADDRESS_P): Fix thinko.
+Mon Jun 21 22:14:05 1999 David Edelsohn <edelsohn@gnu.org>
-Thu Oct 29 12:14:58 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * rs6000.md (movdf_hardfloat32): Fix typo.
- * alpha/linux.h (CPP_PREDEFINES): Add missing space.
+Mon Jun 21 20:10:42 1999 Richard Henderson <rth@cygnus.com>
-Tue Oct 27 16:11:43 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * collect2.c (main): Log frame table count.
+ (GCC_OK_SYMBOL) [ECOFF]: Accept stGlobal.
+ (scan_prog_file) [COFF]: Handle frame tables.
- * collect2.c (aix64_flag): New variable.
- (main, case 'b'): Parse it.
- (GCC_CHECK_HDR): object magic number must match mode.
- (scan_prog_file): Only check for shared object if valid header.
- Print debugging if header/mode mismatch.
- * README.RS6000: Update.
+ * alpha/alpha.h (UNALIGNED_SHORT_ASM_OP): Define.
+ (UNALIGNED_INT_ASM_OP, UNALIGNED_DOUBLE_INT_ASM_OP): Define.
+ * alpha/elf.h: Undef them again.
+ * alpha/vms.h: Remove their definitions.
-Sun Oct 25 23:36:52 1998 Jason Merrill <jason@yorick.cygnus.com>
+1999-06-21 Jakub Jelinek <jj@ultra.linux.cz>
- * stmt.c (expand_fixup): Set fixup->before_jump to a
- NOTE_INSN_DELETED instead of a NOTE_INSN_BLOCK_BEG.
+ * real.c (ereal_from_double): Fix for 64-bit big endian hosts.
+ * emit-rtl.c (gen_lowpart_common): Add case for hosts where double
+ fits in HOST_WIDE_INT and one uses union to access a long constant
+ as double.
-Sun Oct 25 18:35:06 1998 David Edelsohn <edelsohn@mhpcc.edu>
+Mon Jun 21 17:18:25 1999 Richard Henderson <rth@cygnus.com>
- * ginclude/va-ppc.h (va_arg): longlong types in overflow area are
- not doubleword aligned.
+ * sparc.c (sparc_override_options): Don't allow profiling for
+ code models other than medlow.
+ (sparc_function_profiler): New function from old FUNCTION_PROFILER
+ macro. Use ASM_GENERATE_INTERNAL_LABEL and MCOUNT_FUNCTION.
+ (sparc_function_block_profiler): Likewise. Use user_label_prefix.
+ (sparc_block_profiler): Likewise.
+ (sparc_function_block_profiler_exit): Likewise.
+ * sparc.h (FUNCTION_PROFILER): Call new sparc.c function.
+ (FUNCTION_BLOCK_PROFILER): Likewise.
+ (BLOCK_PROFILER): Likewise.
+ (FUNCTION_BLOCK_PROFILER_EXIT): Likewise.
+ (MCOUNT_FUNCTION): New.
+ * sparc/pbd.h (FUNCTION_PROFILER): Delete.
+ (FUNCTION_BLOCK_PROFILER, BLOCK_PROFILER): Delete.
+ * sparc/sun4o3.h (FUNCTION_PROFILER): Delete.
+ (MCOUNT_FUNCTION): New.
+ * sparc/sysv4.h (FUNCTION_BLOCK_PROFILER): Delete.
+ (BLOCK_PROFILER): Delete.
+ (MCOUNT_FUNCTION): New.
-Sun Oct 25 12:07:00 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Mon Jun 21 06:22:21 1999 Mark Elbrecht <snowball3@bigfoot.com>
- * i386/crtdll.h (CPP_PREDEFINES): Fix typo.
- * i386/mingw32.h (CPP_PREDEFINES): Likewise.
+ * i386/djgpp.h (LIB_SPEC): New.
+ (STARTFILE_SPEC): New.
-Fri Oct 23 22:41:40 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * i386/xm-djgpp.h (NO_SYS_SIGLIST): Deleted. Now obsolete.
- * rs6000.md (movsf): Disable explicit secondary-reload-like
- functionality if TARGET_POWERPC64.
- (movdf): Remove TARGET_POWERPC64 explicit secondary-reload-like
- functionality.
+Mon Jun 21 06:19:33 1999 Philippe De Muyter <phdm@macqel.be>
-Fri Oct 23 22:38:57 1998 Jeffrey A Law (law@cygnus.com)
+ * fixinc/Makefile.in (gnu-regex.o): Do not define STDC_HEADERS in
+ compiler flags.
- * m68k.md (5200 movqi): Do not allow byte sized memory references
- using address regs.
- * m68k.c (output_move_qimode): Do not use byte sized operations on
- address registers.
+ * system.h (WSTOPSIG): New macro.
-Fri Oct 23 00:56:11 1998 Jason Merrill <jason@yorick.cygnus.com>
+Mon Jun 21 05:33:15 1999 Mumit Khan <khan@xraylith.wisc.edu>
- * expr.c (pending_chain): Move up.
- (save_expr_status): Do save pending_chain.
- (restore_expr_status): And restore it.
- * function.h (struct function): Add pending_chain.
+ * c-pragma.c (push_alignment): Don't ignore alignments greater than
+ 4 bytes.
+ (insert_pack_attributes): Take into account member natural
+ alignment.
-Mon Oct 19 13:22:13 1998 Geoff Keating <geoffk@ozemail.com.au>
+ * i386/winnt.c (exports_head): New static variable.
+ (i386_pe_record_exported_symbol): New function.
+ (i386_pe_asm_file_end): Use.
+ * i386/cygwin.h (ASM_OUTPUT_COMMON): Record the exported
+ symbols to be emitted at end of assembly.
+ (ASM_DECLARE_OBJECT_NAME): Likewise.
+ (ASM_DECLARE_FUNCTION_NAME): Likewise.
- * loop.c (scan_loop): Be more selective about what invariants are
- moved out of a loop.
+ * i386/uwin.h (CPP_SPEC): Use -idirafter instead -iprefix and
+ -iwithprefix.
-Wed Oct 14 23:27:08 1998 Didier FORT (didier.fort@fedex.com)
+Mon Jun 21 05:17:00 1999 David Edelsohn <edelsohn@gnu.org>
- * fixincludes: Fix up rpc/{clnt,svr,xdr}.h for SunOS.
+ * rs6000.md (movdf_hardfloat32): Use worst case insn length
+ attributes for cases 1 and 2.
-Wed Oct 14 22:13:28 1998 Joel Sherrill (joel@OARcorp.com)
+ * rs6000.c (find_addr_reg): New function.
+ * rs6000.h (find_addr_reg): Declare.
+ (offsettable_addr_operand): Delete.
+ * rs6000.md (movdf_hardfloat32): Handle non-offsettable loads
+ from and stores to GPRs.
- * Makefile.in (stmp-fixinc): Do not install assert.h if not desired.
- * config/t-rtems: Do not install assert.h -- use newlib's.
+Mon Jun 21 04:44:31 1999 Jeffrey A Law (law@cygnus.com)
-Sat Oct 3 19:01:03 1998 Richard Henderson <rth@cygnus.com>
+ * sparc.h (LEGITIMIZE_RELOAD_ADDRESS): Fix paren error introduced
+ in last change.
- * alpha/linux.h (CPP_PREDEFINES): Define __alpha__ for imake.
+Sun Jun 20 17:24:35 1999 Richard Henderson <rth@cygnus.com>
-Fri Oct 2 01:33:30 1998 Jim Wilson <wilson@cygnus.com>
+ * haifa-sched.c (sched_analyze): Don't clear reg_last_uses on calls.
- * i386/winnt.c (i386_pe_asm_file_end): Check
- TREE_SYMBOL_REFERENCED.
+Sat Jun 19 22:52:55 1999 Richard Henderson <rth@cygnus.com>
-Fri Oct 2 01:31:54 1998 Jeffrey A Law (law@cygnus.com)
+ * haifa-sched.c (sched_analyze): Mark call-user regs as clobbered
+ instead of set.
- * regclass.c (reg_scan_mark_refs): Return immediately if passed a
- NULL_RTX as an argument.
+Sat Jun 19 05:40:07 1999 Philip Blundell <pb@nexus.co.uk>
- * gcc.texi: Fix version # that somehow slipped through.
+ * arm.c (arm_reload_in_hi): Invert sense of test on BYTES_BIG_ENDIAN.
-Fri Oct 2 01:24:19 1998 Geoff Keating <geoffk@ozemail.com.au>
+Sat Jun 19 05:25:05 1999 Richard Earnshaw (rearnsha@arm.com)
- * gcse.c: New definition NEVER_SET for reg_first_set, reg_last_set,
- mem_first_set, mem_last_set; because 0 can be a CUID.
- (oprs_unchanged_p): Use new definition.
- (record_last_reg_set_info): Likewise.
- (record_last_mem_set_info): Likewise.
- (compute_hash_table): Likewise.
+ * arm.h (CONDITIONAL_REGISTER_USAGE): If flag_pic, never use
+ PIC_OFFSET_TABLE_REGNUM for general alloaction.
+ (INITIAL_ELIMINATION_OFFSET): Count the fact that the PIC register
+ must be stacked if it is used for PIC accesses.
+ * arm.c (use_return_insn): Handle PIC register specially.
+ (output_return_instruction): Likewise.
+ (output_func_{prologue,epilogue}): Likewise.
+ (output_expand_prologue): Likewise.
-Fri Oct 2 01:20:04 1998 Richard Earnshaw (rearnsha@arm.com)
+ * arm.c (arm_override_options): Remove warning about PIC code
+ not being supported.
- * arm.c (add_constant): New parameter address_only, change caller.
- Set it non-zero if taking the address of an item in the pool.
- (arm_reorg): Handle cases where we need the address of an item in
- the pool.
+Fri Jun 18 15:44:18 1999 Richard Henderson <rth@cygnus.com>
- * arm.c (bad_signed_byte_operand): Check both arms of a sum in
- a memory address.
- * arm.md (splits for *extendqihi_insn and *extendqisi_insn): Handle
- memory addresses that are not in standard canonical form.
+ * alpha.c (alpha_expand_block_move): Use get_insns rather than
+ gen_sequence as argument to emit_no_conflict_block.
-Fri Oct 2 01:16:02 1998 Jeffrey A Law (law@cygnus.com)
+Fri Jun 18 06:48:30 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * reg-stack.c (straighten_stack): Do nothing if the virtual stack is
- empty or has a single entry.
+ * fixinc/inclhack.def (ioctl_fix_ctrl): Fix the definition of _*ISCTRL().
+ * fixinc/{fixincl.x,inclhack.sh}: regen
-Sat Sep 5 23:29:39 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Thu Jun 17 13:28:30 1999 David O'Brien <obrien@FreeBSD.org>
- * i386/cygwin32.h (ASM_OUTPUT_SECTION_NAME): Don't check for
- for exact section attributions.
+ * i386/freebsd-elf.h (LINK_SPEC): Fix typo.
- * i386/mingw32.h (CPP_PREDEFINES): Add __MSVCRT__ for msvc
- runtime.
- * i386/crtdll.h (CPP_PREDEFINES): Define.
+ * i386/freebsd-elf.h (FUNCTION_PROFILER): labels are not needed and
+ the reference to `mcount' was not correct for the ELF on FreeBSD.
-Sat Sep 5 21:46:47 1998 Richard Henderson <rth@cygnus.com>
+Thu Jun 17 02:54:30 1999 Jeffrey A Law (law@cygnus.com)
- * alpha.c (alpha_ra_ever_killed): Inspect the topmost sequence,
- not whatever we're generating now.
+ * invoke.texi (ia32 options): Fix typo.
-Sat Sep 5 14:23:31 1998 Torbjorn Granlund <tege@matematik.su.se>
+ * emit-rtl.c (operand_subword): Tighten checks for when it is safe
+ to safe to extract a subword out of a REG.
- * m68k.md (zero_extendsidi2): Fix typo.
+Wed Jun 16 10:33:02 1999 Jason Merrill <jason@yorick.cygnus.com>
-Tue Sep 1 01:58:38 1998 Jeffrey A Law (law@cygnus.com)
+ * dwarfout.c (add_incomplete_type): New fn.
+ (output_type): Call it.
+ (retry_incomplete_types): New fn.
+ (dwarfout_finish): Call it.
- * egcs-1.1 released.
- * version.c: Update for egcs-1.1 release.
+ From Eric Raskin <ehr@listworks.com>:
+ (output_type): Output types for bases.
-Mon Aug 31 14:55:02 1998 Jeffrey A Law (law@cygnus.com)
+Tue Jun 15 01:55:20 1999 David O'Brien <obrien@FreeBSD.org>
- * NEWS: Add SCO Openserver and Unixware 7 notes.
+ * i386/freebsd-elf.h (LINK_SPEC): clean up the linking library
+ specifications and make it realistic.
+ (LIB_SPEC): Likewise.
- * NEWS: Fix typos.
+Mon Jun 14 03:55:40 1999 Jeffrey A Law (law@cygnus.com)
-Sat Aug 29 14:52:28 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+ * configure.in (rs6000-ibm-aix4.3*, powerpc-ibm-aix4.3*): Do not
+ require a sub-version #.
+ * configure: Rebuilt.
- * config/sparc/sparc.md (movdf_insn, movtf_insn): Fix type and
- length attributes to match May 3rd changes made here.
- * config/sparc/sparc.h (CONDITIONAL_REGISTER_USAGE): Fix and make
- call-used %l7 when generating pic code.
+1999-06-14 Robert Lipe (robertlipe@usa.net)
-Sat Aug 29 14:59:32 1998 Mumit Khan <khan@xraylith.wisc.edu>
+ * svr4.h (DWARF2_DEBUGGING_INFO): Check for redefinition.
- * i386/cygwin32.h (ASM_OUTPUT_SECTION_NAME): Don't emit
- .linkonce directive after the first time.
+1999-06-14 Andreas Jaeger <aj@arthur.rhein-neckar.de>
-Sat Aug 29 14:48:12 1998 Jeffrey A Law (law@cygnus.com)
+ * gcc.texi: Mention gcc 2.95 instead of egcs 1.00.
- * m68k.md (beq0_di): Generate correct (and more efficient) code when
- the clobbered operand overlaps with an input.
- (bne0_di): Similarly.
+Sun Jun 13 01:08:02 1999 Mark Mitchell <mark@codesourcery.com>
-Sat Aug 29 12:38:54 1998 Jeffrey A Law (law@cygnus.com)
+ * invoke.texi (node Option Summary): Add -fpermissive flag.
- * NEWS: Various updates.
+Sat Jun 12 03:40:42 1999 Jeffrey A Law (law@cygnus.com)
-Tue Aug 25 19:35:24 1998 Jim Wilson <wilson@cygnus.com>
+ * sparc.h (LEGITIMIZE_RELOAD_ADDRESS): Do nothing with operands
+ that require PIC code sequences.
- * configure.in (powerpc-ibm-aix4.[12]*): Change from 4.[12].*.
- (rs6000-ibm-aix4.[12]*): Likewise.
- * configure: Regnerate.
+Fri Jun 11 03:17:51 1999 Jeffrey A Law (law@cygnus.com)
-Thu Aug 27 23:44:49 1998 Jeffrey A Law (law@cygnus.com)
+ * Makefile.in (libgcc2): Pass MAYBE_USE_COLLECT2 as an argument.
+ * libgcc2.c (__CTOR_LIST, __DTOR_LIST); Do not provide
+ initializers is some circumstances.
- * reload1.c (forget_old_reloads_1): Keep track of the largest mode
- found while stripping SUBREGS and invalidate reloads for all the hard
- regs specified by that largest mode. egcs-1.1 only hack. The
- mainline tree will get a better fix.
+ * fixinc/inclhack.def (endif_label): Add additional selector for
+ more bogus stuff after #endif statements.
+ * fixinc/inclhack.sh, fixinc/fixincl.x: Rebuilt.
-Tue Aug 25 19:43:11 1998 Jeffrey A Law (law@cygnus.com)
+Thu Jun 10 20:45:27 1999 Mumit Khan <khan@xraylith.wisc.edu>
- * From Alexandre:
- * configure.in: Do not set thread_file to "irix" since no such
- support exists yet.
+ * i386/cygwin.h (SET_ASM_OP): Define.
- * reorg.c (fill_simple_delay_slots): Do not abort if we encounter
- an insn on the unfilled_slots_list that has no delay slots.
- (fill_eager_delay_slots): Similarly.
+Thu Jun 10 20:37:57 1999 Mumit Khan <khan@xraylith.wisc.edu>
-Mon Aug 24 15:20:19 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * reg-stack.c (stack_reg_life_analysis): Find all the RETURN insns.
- * rs6000.h (GO_IF_LEGITIMATE_ADDRESS): Use TARGET_POWERPC64
- when testing LEGITIMATE_INDEXED_ADDRESS_P DFmode and DImode.
- (LEGITIMIZE_ADDRESS): Use TARGET_POWERPC64 for INDEXED fixup.
- * rs6000.c (print_operand, case 'L'): Add UNITS_PER_WORD, not 4.
- (print_operand, cases 'O' and 'T'): Fix typos in lossage strings.
- * rs6000.md (fix_truncdfsi2_store): Remove %w from non-CONST_INT
- operand.
- (movdf_softfloat32, movdf_hardfloat64, movdf_softfloat64): Change
- 'o' to 'm' for GPR variant constraints.
+Thu Jun 10 14:47:59 1999 Bruce Korb <ddsinc09@ix.netcom.com>
- * rs6000.md (movqi, movhi): Add CONSTANT_P_RTX.
+ * fixinc/inclhack.def(sun_auth_proto): We do not know how to
+ test for the presence of valid prototypes. Delete bypass expr.
+ (ioctl_fix_ctrl): Correct the selection expression.
-Mon Aug 24 01:21:38 PDT 1998 Jeff Law (law@cygnus.com)
+ * fixinc/inclhack.def(no_double_slash): fixed quoting rules
+ * fixinc/inclhack.sh: regen
+ * fixinc/fixincl.x: regen
- * version.c: Bump for snapshot.
+Thu Jun 10 01:22:59 1999 Jeffrey A Law (law@cygnus.com)
-Sun Aug 23 00:47:52 1998 Jeffrey A Law (law@cygnus.com)
+ * loop.c (strength_reduce): Disable biv->giv translations and
+ giv recombination. For the release branch only.
- * regmove.c (optimize_reg_copy_3): Disable for egcs-1.1.
+Wed Jun 9 15:57:57 1999 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
-Thu Aug 20 13:56:53 1998 Michael Meissner <meissner@cygnus.com>
+ * rs6000.md (movsi_got_internal_mem): Delete.
+ * rs6000.h (CONDITIONAL_REGISTER_USAGE): Mark PIC_OFFSET_TABLE_REGNUM.
+ (GOT_TOC_REGNUM): Delete.
+ (PIC_OFFSET_TABLE_REGNUM): Define.
+ (FINALIZE_PIC): Disable.
+ * rs6000.c (rs6000_got_register): New code for fixed pic register.
+ (rs6000_replace_regno): Delete.
+ (rs6000_finalize_pic): Likewise.
+ (output_prolog): Handle PIC_OFFSET_TABLE_REGNUM.
- * config/i386/winnt.c: Include system.h, not stdio.h to get
- sys/param.h pulled in before rtl.h in case the system defines MIN
- and MAX.
+Wed Jun 9 19:44:26 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Wed Aug 19 21:33:19 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * loop.c (loop_insn_first_p): Don't compare LUIDs when P
+ is a note; use <= for the compare; advance P while it is
+ a NOTE.
- * rs6000.c (rs6000_output_load_toc_table): Use ld for 64-bit.
- (output_toc): Use single TOC slot or llong minimal-toc for DFmode
- and DImode 64-bit. Use llong for minimal-toc SFmode and
- SYMBOL_REF / LABEL_REF 64-bit.
- (output_function_profiler): Use llong for profiler label and ld to
- load 64-bit label address.
+Wed Jun 9 13:12:24 1999 Jeffrey A Law (law@cygnus.com)
-Tue Aug 18 23:48:30 1998 Richard Henderson <rth@cygnus.com>
+ * fixinc/inclhack.def (no_double_slash): Fix quoting for test.
+ * fixinc/inclhack.sh, fixinc/fixincl.x, fixinc/fixincl.sh; Rebuilt.
- * c-common.c (decl_attributes): Issue an error if the argument
- to alias is not a string.
+ * varasm.c (remove_from_pending_weak_list): Verify t->name
+ is non-NULL before passing it to strcmp.
-Tue Aug 18 13:05:59 BST 1998 Richard Earnshaw (rearnsha@arm.com)
+Wed Jun 9 23:01:17 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * arm.c (arm_override_options): Remove lie about ignoring PIC flag.
+ * invoke.texi: Add C4x invocation docs.
-Tue Aug 18 10:32:11 1998 Jeffrey A Law (law@cygnus.com)
+Wed Jun 9 22:42:49 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * haifa-sched.c (sched_analyze): Put all JUMP_INSNs on the last
- pending memory flush list.
+ * config/c4x/c4x.h (TARGET_EXPOSE_LDP, LEGITIMIZE_RELOAD_ADDRESS):
+ Define new macros.
+ * config/c4x/c4x.c (c4x_emit_move_sequence, src_operand): Use
+ TARGET_EXPOSE_LDP.
+ (c4x_legitimize_reload_address): New function.
+ * config/c4x/c4x.md: Update docs.
- * regmove.c (fixup_match_2): Do not call reg_overlap_mentioned_p
- on notes.
+Wed Jun 9 06:50 1999 Bruce Korb <ddsinc09@ix.netcom.com>
- * regmove.c (optimize_reg_copy_1): Update REG_N_CALLS_CROSSED
- and REG_LIVE_LENGTH as successful substitutions are made.
+ * fixinc/inclhack.def(sun_auth_proto): bypass the patch if
+ the typed arguments are not part of a comment
+ (ioctl_fix_ctrl): Added a purpose comment
+ * fixinc/fixincl.x: regenerate
+ * fixinc/inclhack.sh: regenerate
-Mon Aug 17 21:07:19 1998 Jeffrey A Law (law@cygnus.com)
+Wed Jun 9 04:14:48 1999 Jeffrey A Law (law@cygnus.com)
- * From Graham
- * tree.c (build_index_type): Copy TYPE_SIZE_UNIT from sizetype
- to itype.
- * c-decl.c (finish_enum): Copy TYPE_SIZ_UNIT from enumtype to tem.
+ * fixincludes: Avoid removing '.'.
+ * fixinc/fixinc.svr4: Likewise.
+ * fixinc/fixinc.winnt: Likewise.
+ * fixinc/inclhack.tpl: Likewise.
+ * fixinc/fixincl.sh, fixinc/inclhack.sh: Rebuilt.
- * rs6000.c (secondary_reload_class): For TARGET_ELF, indicate that
- a BASE_REGS register is needed as an intermediate when copying
- a symbolic value into any register class other than BASE_REGS.
+Wed Jun 9 03:55:34 1999 Jim Wilson <wilson@cygnus.com>
-Mon Aug 17 11:25:52 1998 Richard Earnshaw <rearnsha@arm.com>
+ * configure.in (rs6000-ibm-aix4.[12]*): Change rx6000 to rs6000.
+ * configure: Regenerate.
- * arm.h (SECONDARY_INPUT_RELOAD_CLASS): Return NO_REGS if compiling
- for architecture v4.
+ * configure.in (rs6000-ibm-aix4.[12]*): Delete use of aix41-gld.h.
+ Add use of x-aix41-gld.
-Sun Aug 16 00:57:48 PDT 1998 Jeff Law (law@cygnus.com)
+1999-06-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * version.c: Bump for snapshot.
+ * fixinc/inclhack.def (sun_catmacro): Escape parens in the select
+ pattern.
+ * fixinc/fixincl.x, fixinc/inclhack.sh: Rebuilt.
-Sun Aug 16 01:53:21 1998 Richard Henderson <rth@cygnus.com>
+Wed Jun 9 03:10:34 1999 Mumit Khan <khan@xraylith.wisc.edu>
- * reload.c (find_equiv_reg): Reject equivalences separated
- by a volatile instruction.
+ * c-pragma.c (handle_pragma_token): Handle `#pragma pack()'
+ correctly.
-Sun Aug 16 00:21:44 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+Tue Jun 8 05:47:48 1999 Richard Earnshaw (rearnsha@arm.com)
- * rs6000/linux.h (CPP_OS_DEFAULT_SPEC): Define.
+ * optabs.c (expand_cmplxdiv_wide): Use expand_abs to get the absolute
+ values.
-Sat Aug 15 20:22:33 1998 H.J. Lu (hjl@gnu.org)
+Mon Jun 7 22:30:37 1999 Jeffrey A Law (law@cygnus.com)
- * config/alpha/alpha.h (ASM_OUTPUT_MI_THUNK): Handle aggregated
- return type.
- * config/alpha/win-nt.h (ASM_OUTPUT_MI_THUNK): Likewise.
+ * fixinc/inclhack.def (bad_lval): Remove bogus selector.
+ * fixinc/inclhack.sh, fixinc/fixincl.x, fixinc/fixincl.sh; Rebuilt.
-Fri Aug 14 21:07:03 1998 Jeffrey A Law (law@cygnus.com)
+ * fixinc/inclhack.def (avoid_bool): Also catch
+ "typedef [unsigned] int bool".
+ * fixinc/inclhack.sh, fixinc/fixincl.x, fixinc/fixincl.sh: Rebuilt.
- From Joern:
- * expr.c (store_expr): Don't optimize away load-store pair
- when either source or destination have a side effect.
+ * m68k/x-hp3bsd44: Delete obsolete and incorrect file.
+ * configure.in (m68k-hp-bsd4.4): No longer use x-hp3bsd44.
+ * configure: Rebuilt.
- * loop.c (add_label_notes): Do not ignore references to labels
- before dispatch tables. Mirrors Apr 8 change to mark_jump_label.
- * gcse.c (add_label_notes): Similarly.
+Mon Jun 7 22:05:03 1999 Mark Kettenis <kettenis@gnu.org>
- * pa.h (ASM_OUTPUT_MI_THUNK): Strip name encoding.
+ * config/i386/gnu.h: Include <gnu.h> right after <i386/linux.h>,
+ such that we can override its definitions if necessary.
+ (CPP_SPEC): New define. Support processor specific predefines via
+ %(cpp_cpu).
+ (CC1_SPEC): New define. Support processor specific compiler
+ options via %(cc1_cpu).
+ (STARTFILE_SPEC): New define. Use crt0.o instead of crt1.o for
+ -static.
- * m68k.md (adddi_dilshr32): One of the operands must be a register.
- (adddi_dishl32): Similarly.
+1999-06-07 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Fri Aug 14 01:45:06 1998 Mumit Khan <khan@xraylith.wisc.edu>
+ * fixinc/inclhack.def (math_gcc_ifndefs): Insert whitespace
+ between sed's -e flag, and the open-quote following it.
+ * fixinc/fixincl.x, fixinc/fixincl.sh: Rebuilt.
- * i386/cygwin32.h (DEFAULT_PCC_STRUCT_RETURN): Define.
+Mon Jun 7 20:34:20 1999 Robert Lipe <robertlipe@usa.net>
+ Jeffrey A Law (law@cygnus.com)
-Fri Aug 14 01:40:21 1998 Geoffrey Keating <geoffk@ozemail.com.au>
+ * varasm.c (assemble_start_function): Remove the function
+ from the pending weak decls list when we define a function.
+ (assemble_variable): Similarly for variables.
+ (weak_finish): Ignore items on the list with a NULL name.
+ (remove_from_ending_weak_list); New function to "remove" an item
+ from the pending weak declarations list.
- * rs6000/linux.h (LINK_SPEC): Pass -G args to the linker.
+Mon Jun 7 19:27:07 1999 Jerry Quinn <jquinn@nortelnetworks.com>
-Fri Aug 14 01:23:23 1998 Richard Earnshaw (rearnsha@arm.com)
+ * pa.md (fmpyfadd, fmpynfadd, fnegabs): New patterns.
- * arm/netbsd.h (TARGET_DEFAULT): Default includes software floating
- point.
- (CPP_FLOAT_DEFAULT_SPEC): Re-define accordingly.
+Sun Jun 6 11:58:34 1999 Jakub Jelinek <jj@ultra.linux.cz>
-Fri Aug 14 01:23:23 1998 Jeffrey A Law (law@cygnus.com)
+ * sparc.md (abstf2): This should be an expand.
+ (split after abstf2_notv9): Fix mode.
+ (abstf2_hq_v9): New pattern.
+ (abstf2_v9): Only use when no hard quad.
+ (absdf2_v9): Fix if target is not the same as source.
+ (ashrsi3_extend, ashrsi3_extend2, lshrsi3_extend, lshrsi3_extend2):
+ Add correct output constraints.
- * README.RS6000: Bring over dje's changes from the mainline
- source tree.
+Sat Jun 5 17:04:16 1999 Craig Burley <craig@jcb-sc.com>
-Fri Aug 14 01:19:08 1998 Robert Lipe <robertl@dgii.com>
+ From Dave Love to egcs-patches on 20 May 1999 17:38:38 +0100:
+ * invoke.texi: Clarify text vis-a-vis Intel CPUs.
- * install.texi: Various SCO OpenServer tweaks.
+Fri Jun 4 13:30:27 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
-Thu Aug 13 19:55:05 1998 Jim Wilson <wilson@cygnus.com>
+ * alpha/osf.h (CPP_SUBTARGET_SPEC): Handle -threads.
+ (LIB_SPEC): Likewise.
+ Link with -lprof1_r for -g/-pg.
- * reload1.c (eliminate_regs_in_insn): Handle another case when
- eliminating the frame pointer to the hard frame pointer. Add
- missing ep->to_rtx check to one existing case.
+1999-06-04 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Tue Aug 11 17:45:39 1998 Dave Love <d.love@dl.ac.uk>
+ * loop.c (check_dbra_loop): Fix change of Jan 19.
- * README.g77: Update from Craig.
+Fri Jun 4 00:12:40 1999 Marc Espie <espie@cvs.openbsd.org>
-Sat Aug 8 19:20:22 1998 Gary Thomas (gdt@linuxppc.org)
+ * freebsd-elf.h (SWITCH_TAKES_ARG): Redefine, not define.
+ (STARTFILE_SPEC): Define, override the svr4.h version.
+ (ENDFILE_SPEC): Likewise.
- * rs6000.c (rs6000_allocate_stack_space) Fix typo which
- caused bad assembly code to be generated.
+Thu Jun 3 23:58:55 1999 Jeffrey A Law (law@cygnus.com)
-Sat Aug 8 18:52:51 1998 Jeffrey A Law (law@cygnus.com)
+ * fixinc/inclhack.def (limits_ifndefs): Also apply to sys/limits.h
+ * fixinc/fixincl.x: Regenerated.
+ * fixinc/inclhack.sh: Regenerated.
- * netbsd.h: Fix typo.
+Thu Jun 3 07:48 1999 Bruce Korb <ddsinc09@ix.netcom.com>
-Mon Aug 3 23:43:55 PDT 1998 Jeff Law (law@cygnus.com)
+ * fixinc/inclhack.def(Io_Def_Quotes): corrected sed expression
+ * fixinc/fixincl.x: regenerate
+ * fixinc/inclhack.sh: regenerate
- * version.c: Bump for snapshot.
+Thu Jun 3 22:27:50 1999 Robert Lipe <robertlipe@usa.net>
-Sun Aug 2 00:42:50 1998 Jeffrey A Law (law@cygnus.com)
+ * i386/udk.h (LINK_SPEC): Correct linker search path for
+ system libraries.
- * i386/netbsd.h: Undo previous change to DWARF2_UNWIND_INFO.
- * m68k/netbsd.h: Likewise.
- * ns32k/netbsd.h: Likewise.
- * sparc/netbsd.h: Likewise.
+Thu Jun 3 02:15:07 1999 Jason Merrill <jason@yorick.cygnus.com>
-Fri Jul 31 17:08:59 1998 Jeffrey A Law (law@cygnus.com)
+ * dwarf2out.c (add_incomplete_type): New fn.
+ (gen_struct_or_union_type_die): Call it.
+ (retry_incomplete_types): New fn.
+ (dwarf2out_finish): Call it.
- * configure.in (mingw configuration): Fix typo.
- * configure: Rebuilt.
+Thu Jun 3 01:19:03 1999 Jeffrey A Law (law@cygnus.com)
-Fri Jul 31 20:22:02 1998 Michael Meissner <meissner@cygnus.com>
+ * gcse.c (insert_insn_end_bb): Correct placement of insns when the
+ current block starts with a CODE_LABEL and ends with a CALL and
+ we can not find all the argument setup instructions for the CALL.
- * rs6000.c (rs6000_override_options): If big endian and -Os, use
- load/store multiple instructions unless user overrides.
+Wed Jun 2 12:25:55 1999 Richard Henderson <rth@cygnus.com>
-Fri Jul 31 17:08:59 1998 Jeffrey A Law (law@cygnus.com)
+ * alpha.c (override_options): Thinko in last patch.
- * ns32k/netbsd.h: Fix typo.
+ * alpha/osf.h (CPP_SUBTARGET_SPEC): Define.
+ (LIB_SPEC): Recognize -pthread.
-Thu Jul 30 19:50:15 1998 David Edelsohn <edelsohn@mhpcc.edu>
+Wed Jun 2 07:07 1999 Bruce Korb <ddsinc09@ix.netcom.com>
- * rs6000/x-aix43 (AR_FOR_TARGET_FLAGS): Delete.
- (AR_FOR_TARGET): Define.
+ * fixinc/fixincl.c(global def): Add FD_SHELL_SCRIPT to mark
+ fixes that need "file=xxx\n" prepended before invocation
+ (start_fixer - new): starting the fixer process is complex enough
+ to warrent its own routine. It prepends the "file=xxx\n" stuff.
+ (process): uses the new routine; omit usage of putenv()
+ * fixinc/fixincl.tpl: mark shell scripts with FD_SHELL_SCRIPT
+ * fixinc/fixincl.x: regenerate
-Thu Jul 30 19:11:30 1998 Richard Henderson <rth@cygnus.com>
+Wed Jun 2 06:36:14 1999 Richard Earnshaw (rearnsha@arm.com)
- * alpha.md (fp cmp): Replicate patterns for ALPHA_TP_INSN.
- (fcmov): Remove ALPHA_TP_INSN patterns -- fcmov doesn't trap.
+ * arm.md (zero_extendqidi2): Don't allow operand1 to be a memory
+ reference. Temporary work-around for problems with constant
+ pool handling.
-Thu Jul 30 12:51:09 1998 Mark Mitchell <mark@markmitchell.com>
+Wed Jun 2 02:40:43 1999 Jeffrey A Law (law@cygnus.com)
- * dyn-string.h: New file.
- * dyn-string.c: Likewise.
- * Makefile.in (OBJS): Add dyn-string.o.
- (dwarf2out.o): Add dyn-string.h dependency.
- (dyn-string.o): List dependencies.
- * dwarf2out.c: Include dyn-string.h.
- (ASM_NAME_TO_STRING): Use dyn_string_append, rather than strcpy.
- (addr_const_to_string): Take a dyn_string_t, not a char* as a
- prototype. Use dyn_string_append rather than strcat, throughout.
- (addr_to_string): Use dyn_string_t.
+ * README, configure.in, gcc.1, gcc.texi: Update name (egcs -> gcc)
+ and version #s (1.1 -> 2.95) as needed.
+ * README.g77: Kill way out of date file in the toplevel directory.
-Thu Jul 30 00:58:34 1998 Jeffrey A Law (law@cygnus.com)
+Wed Jun 2 00:52:34 1999 David O'Brien <obrien@FreeBSD.org>
- * i386.md (movqi): When optimizing a load of (const_int 1) into a
- NON_QI_REG_P, pretend the register is SImode.
+ * configure.in (i[34567]86-*-freebsdelf): Don't include linux.h,
+ i386/freebsd-elf.h no longer requires it. Instead include svr4.h.
+ * configure: Rebuilt.
+ * i386/freebsd-elf.h (DEFAULT_VTABLE_THUNKS): Define.
+ (ASM_COMMENT_START, ASM_APP_ON, ASM_APP_OFF, SET_ASM_OP): Likewise.
+ (PREFERRED_DEBUGGING_TYPE, WCHAR_UNSIGNED): Likewise.
+ (SWITCH_TAKES_ARG): Likewise.
+ * i386/freebsd.h: Remove FREEBSD_NATIVE support.
+ * config/t-freebsd: Moved from config/i386/ so it can used for all
+ FreeBSD targets.
+
+Mon May 31 02:22:55 1999 Philippe De Muyter <phdm@macqel.be>
-Wed Jul 29 23:49:23 1998 Todd Vierling <tv@netbsd.org>
+ * m68k/x-mot3300 (XCFLAGS): Fixed to match stb.o, not f/stb.o.
- * configure.in: Use xm-netbsd.h as the NetBSD xm file (not xm-siglist).
- Accept arm32 as arm, m68k4k as m68k, mipsle as mips-dec, and any
- manufacturer id for ns32k.
- * configure: Regenerated.
- * config/netbsd.h: When using ASM_WEAKEN_LABEL, make it global too.
- * config/t-netbsd: Don't compile libgcc1-test as the fns are in libc.
- * config/i386/netbsd.h: Undefine DWARF2_UNWIND_INFO, not define as 0.
- * config/m68k/netbsd.h: Same.
- * config/ns32k/netbsd.h: Same.
- * config/sparc/netbsd.h: Same.
+Wed Jun 2 00:08:34 1999 Robert Lipe <robertlipe@usa.net>
-Wed Jul 29 22:39:21 1998 Jeffrey A Law (law@cygnus.com)
+ * configure.in (i[34567]86-*-udk*): Install headers with cpio.
+ * configure: Rebuilt.
- * unroll.c (unroll_loop): Do not abort for an UNROLL_MODULO
- or UNROLL_COMPLETELY loop that starts with a jump to its
- exit code.
+Wed Jun 2 00:49:00 EDT 1999 John Wehle (john@feith.com)
-Wed Jul 29 22:18:14 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * flow.c (mark_regs_live_at_end, insn_dead_p,
+ mark_set_1, mark_used_regs): Only give FRAME_POINTER_REGNUM
+ and HARD_FRAME_POINTER_REGNUM special treatment if reload
+ hasn't run or the frame pointer is needed.
+ * haifa-sched.c (attach_deaths): Likewise.
+ * sched.c (attach_deaths): Likewise.
- * rs6000/rs6000.md (absdi2 define_split): Swap operands of MINUS.
- * rs6000/rs6000.c (mask64_operand): Use HOST_BITS_PER_WIDE_INT.
- (print_operand, case 'B'): Don't fall through.
- (print_operand, case 'S'): Correct mask begin/end computation.
- Use HOST_BITS_PER_WIDE_INT.
- * rs6000/rs6000.h (CPP_PREDEFINES): Define _LONG_LONG.
- (CONDITIONAL_REGISTER_USAGE): GPR13 fixed if TARGET_64BIT.
- * rs6000/aix41.h (CPP_PREDEFINES): Same.
- * rs6000/aix43.h (CPP_PREDEFINES): Same.
+Thu May 27 22:06:52 1999 Mark Mitchell <mark@codesourcery.com>
-Tue Jul 28 23:29:04 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * cccp.c (handle_directive): Handle backslash-newlines in quoted
+ strings correctly.
- * configure.in: Fix --without/--disable cases for local-prefix,
- gxx-include-dir and checking.
+Mon May 31 22:42:02 1999 Jeffrey A Law (law@cygnus.com)
-Tue Jul 28 22:10:43 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+ * Remove this patch (from the branch only)
+ Wed May 26 09:53:05 1999 Mark Mitchell <mark@codesourcery.com>
+ * fold-const.c (fold): STRIP_NOPS when deciding whether or not
+ something is a candidate for optimize_bit_field_compare.
- * configure.in (enable_haifa): Set by default for sparc64 too.
- configure: Rebuilt.
+Mon May 31 15:23:23 1999 Richard Henderson <rth@cygnus.com>
-Tue Jul 28 23:29:04 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * alpha.md (reload_*_help): New patterns and splitters.
+ (reload_*): Use them.
+ (mov[qh]i): Likewise.
- * i386/cygwin32.h (VALID_MACHINE_TYPE_ATTRIBUTE): New macro.
- * i386/winnt.c (associated_type): New fn.
- (i386_pe_valid_type_attribute_p): New fn.
- (i386_pe_check_vtable_importexport): Remove.
- (i386_pe_dllexport_p): Use associated_type.
- (i386_pe_dllimport_p): Likewise.
+Mon May 31 09:36:11 1999 Cort Dougan <cort@cs.nmt.edu>
- From Antonio M. O. Neto <anmendes@cruzeironet.com.br>:
- * i386.c (i386_valid_type_attribute_p): Also accept
- attributes for METHOD_TYPEs.
+ * rs6000/linux.h (LINK_SPEC): Use emulation elf32ppclinux.
-Tue Jul 28 23:17:39 1998 Peter Gerwinski <peter@gerwinski.de>
+Sat May 29 19:08:10 1999 Philip Blundell <philb@gnu.org>
- * tree.c (build_range_type): Copy TYPE_SIZE_UNIT.
+ * config/arm/aout.h (ASM_OUTPUT_ALIGN): Only define if not already
+ defined.
+ * config/arm/elf.h (ASM_OUTPUT_ALIGN): Define.
+ (MAX_OFILE_ALIGNMENT): Likewise.
-Tue Jul 28 22:31:12 1998 Craig Burley <burley@gnu.org>
+Mon May 31 00:45:14 1999 Jeffrey A Law (law@cygnus.com)
- * gcc.c: Fix commentary describing %g, %u, %U, and %O.
+ * jump.c (jump_optimize_1): Only set CAN_REACH_END if
+ calculate_can_reach_end returns nonzero.
- * gcc.c (do_spec_1): Fix handling of %g%O and %U%O to prevent
- them from generating a new base name for each occurence of
- a specific suffix.
+ * Makefile.in (CFLAGS): Remove warning flags.
+ (WARN_CFLAGS): Disable.
-1998-07-28 Vladimir N. Makarov <vmakarov@cygnus.com>
+ * configure.in (native gas tests): Search for an assembler in the
+ same manner that the installed compiler will.
+ * configure: Rebuilt.
+ * tm.texi (MD_EXEC_PREFIX): Note need to update configure.in too.
- * cse.c (cse_insn): Enable subsitution inside libcall only for REG,
- SUBREG, MEM.
- * rtlanal.c (replace_rtx): Prohibit replaces in CONST_DOUBLE.
+ * alias.c (find_base_term): Improve handling of addresses
+ constructed from binary operations.
-Mon Jul 27 00:54:41 1998 Jason Merrill <jason@yorick.cygnus.com>
+Sun May 30 14:43:37 1999 Robert Lipe <robertlipe@usa.net>
- * tree.c (simple_cst_equal, case CONSTRUCTOR): OK if the elts are
- identical.
+ * fixincl.c: Replace local include scheme with #includes of
+ gansidecl.h and system.h.
+ * procopen.c: Likewise.
+ * server.c: Likewise.
-Mon Jul 27 22:20:02 1998 Jeffrey A Law (law@cygnus.com)
+Sun May 30 14:18:40 1999 Jeffrey A Law (law@cygnus.com)
- * pa.c (move_operand): Accept CONSTANT_P_RTX.
+ * function.h (cleanup_label, frame_offset): Declare.
+ (tail_recursion_label, tail_recursion_reentry): Likewise.
+ (arg_pointer_save_area, rtl_expr_chain): Likewise.
+ * stmt.c (cleanup_label, frame_offset): Delete extern declarations.
+ (tail_recursion_label, tail_recursion_reentry): Likewise.
+ (arg_pointer_save_area, rtl_expr_chain): Likewise.
-Mon Jul 27 00:46:56 PDT 1998 Jeff Law (law@cygnus.com)
+Fri May 28 03:47:03 1999 Eric Raskin (ehr@listworks.com)
- * version.c: Bump for snapshot.
+ * i386/t-dgux (EXTRA_PARTS): Add crti.o.
+ (crti.o): Add build rule and dependencies.
-Sun Jul 26 01:11:12 1998 H.J. Lu (hjl@gnu.org)
+Fri May 28 03:07:10 1999 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * i386.h (CONST_DOUBLE_OK_FOR_LETTER_P): Return 0 when eliminating
- the frame pointer and compiling PIC code and reload has not completed.
+ * rs6000/sysv4.h (CC1_SPEC): Add support for -profile
+ (LIB_LINUX_SPEC): Likewise.
+ (LIB_LINUX_SPEC): Add support for -pthread
+ (CPP_OS_LINUX_SPEC): Likewise.
+ (CPP_SYSV_SPEC): Avoid redefinitions if both -fpic and -fPIC are
+ specified
- * i386.c (output_to_reg): Add code to emulate non-popping DImode
- case.
+ * rs6000.c (output_mi_thunk): Enable full support again.
-Sun Jul 26 01:02:54 1998 Jeffrey A Law (law@cygnus.com)
+Thu May 27 13:04:52 1999 H.J. Lu (hjl@gnu.org)
- * regmove.c (regmove_optimize): Fix typo initializing regmove_bb_head.
+ * i386.c (output_fp_cc0_set): Don't check the JUMP_INSN code for
+ conditional move.
+ (notice_update_cc, output_float_compare): Enable TARGET_CMOVE support.
+ (output_float_compare, output_fp_cc0_set): Fix the FLOAT comparison
+ for IEEE math and CC_FCOMI.
+ (put_jump_code): No IEEE if CC_FCOMI is set.
-Sat Jul 25 23:29:23 1998 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+1999-05-27 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * Makefile.in (install-info): Only try to update the info
- directory file if it exists in the first place.
+ * fold-const.c (fold_truthop): Make the field reference unsigned
+ when converting a single bit compare.
-Fri Jul 24 18:58:37 1998 Klaus Espenlaub <kespenla@student.informatik.uni-ulm.de>
+Thu May 27 03:07:13 1999 Philip Blundell <pb@nexus.co.uk>
- * rs6000.h (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): Delete.
+ Based on patch by Scott Bambrough and Pat Beirne:
+ * config/arm/arm.c (making_const_table): New variable.
+ * config/arm/arm.h (making_const_table): Declare.
+ (OUTPUT_INT_ADDR_CONST): Mark symbols as position independent if
+ appropriate.
+ * config/arm/arm.md (consttable_4, consttable_8, consttable_end):
+ Keep track of when we are building the constant table.
-Thu Jul 23 18:53:20 1998 Jim Wilson <wilson@cygnus.com>
+Thu May 27 02:52:55 1999 Jeffrey A Law (law@cygnus.com)
- * dbxout.c (dbxout_range_type): Only call dbxout_type_index for
- already defined type.
+ * varasm.c (STRIP_NAME_ENCODING): Remove default definition.
+ * output.h (STRIP_NAME_ENCODING): Strip '*' like the old varasm
+ version did.
-Wed Jul 22 14:08:54 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+Thu May 27 02:40:48 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * profile.c (branch_prob): Call allocate_reg_info after outputting
- profile rtl in instrument_arcs.
+ * loop.c (strength_reduce): Don't do biv->giv conversion on constants.
-Tue Jul 21 22:40:09 PDT 1998 Jeff Law (law@cygnus.com)
+Thu May 27 02:09:27 1999 Jeffrey A Law (law@cygnus.com)
- * version.c: Bump for snapshot.
+ * reload.c (push_reload): Do not call remove_address_replacements
+ when presented with identical optional reloads.
-Tue Jul 21 23:28:35 1998 Klaus Kaempf <kkaempf@rmi.de>
+Wed May 26 14:18:05 1999 Richard Henderson <rth@cygnus.com>
- * cccp.c (do_include): Fix vax c style include handling.
+ * alpha.h (MASK_FIX, TARGET_FIX): New.
+ (MASK_*): Reorganize constants.
+ (CPP_AM_FIX_SPEC): New.
+ (TARGET_SWITCHES): Add FIX.
+ (EXTRA_SPECS): Likewise.
+ (CPP_CPU_EV6_SPEC): Use FIX, not CIX.
+ (SECONDARY_MEMORY_NEEDED): Likewise.
+ (REGISTER_MOVE_COST): Likewise.
+ * alpha.c (override_options): Add FIX support. Always use
+ ALPHA_TP_PROG for ev6.
+ * alpha.md (sqrt and mov[sd]i patterns): Use FIX, not CIX.
+ * alpha/elf.h (ASM_FILE_START): Look at FIX too.
+ * configure.in (target_cpu_default2) [ev6]: Use FIX, not CIX.
-Tue Jul 21 15:49:31 1998 David Edelsohn <edelsohn@mhpcc.edu>
+Wed May 26 09:53:05 1999 Mark Mitchell <mark@codesourcery.com>
- * rs6000.h (PREDICATE_CODES): Add CONSTANT_P_RTX.
- * rs6000.md (movsi, movdi): Add CONSTANT_P_RTX.
- * rs6000.c (short_cint_operand): Add CONSTANT_P_RTX.
- (u_short_cint_operand): Same.
- (reg_or_cint_operand): Same.
- (logical_operand): Same.
- (input_operand): Same.
- (reg_or_short_operand): Use u_short_cint_operand.
+ * fold-const.c (fold): STRIP_NOPS when deciding whether or not
+ something is a candidate for optimize_bit_field_compare.
-Tue Jul 21 03:59:08 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+Wed May 26 03:54:33 1999 Melissa O'Neill <oneill@cs.sfu.ca>
- * jump.c (jump_optimize): When simplifying noop moves and
- PUSH_ROUNDING, fix thinko so we use same criterion for identifying
- the PUSHes to rewrite in second loop as we did in the first.
+ * fixinc/fixincl.c: (WIFSIGNALED): Define if not already defined.
+ (WTERMSIG, WIFEXITED, WEXITSTATUS, WIFSTOPPED, WSTOPSIG): Likewise.
+ (S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP): Likewise.
+ (S_IROTH, S_IWOTH, S_IXOTH, S_IRWXU, S_IRWXG, S_IRWXO): Likewise.
-Tue Jul 21 00:31:01 1998 Jeffrey A Law (law@cygnus.com)
+Wed May 26 02:19:31 1999 Philip Blundell <pb@nexus.co.uk>
- * gcc.c (do_spec): Call "error" not "warning".
+ * arm.h (NEED_PLT_GOT): Fix mistake in last change.
+ (GOT_PCREL): New macro. Define to 1 if not already defined.
+ * arm/elf.h (GOT_PCREL): Define to 0.
+ * arm.c (arm_finalize_pic): Take into account the setting of
+ GOT_PCREL.
- * configure.in: Fix minor problems with gas feature detection code.
- * configure: Rebuilt.
+Tue May 25 14:06:06 1999 Jeffrey A Law (law@cygnus.com)
- * gcc.c (do_spec): Issue a warning for '%[]' usage.
+ * output.h (STRIP_NAME_ENCODING): Provide default definition.
+ * dwarf2out.c (ASM_NAME_TO_STRING): Use STRIP_NAME_ENCODING.
- * Undo this change.
- * gcc.c: Delete %[spec] support.
- (do_spec_1, case '('): Likewise.
- (do_spec_1, case '['): Call error.
+ * flow.c (mark_set_1): Do not record BLKmode stores as dead
+ store elimination candidates.
-Mon Jul 20 22:34:17 1998 Richard Henderson <rth@cygnus.com>
+Mon May 24 14:34:31 1999 Jeffrey A Law (law@cygnus.com)
- * alpha.h (CPP_SPEC): Tidy. Hook to cpp_cpu and cpp_subtarget.
- (CPP_SUBTARGET_SPEC): Default to empty string.
- (CPP_AM_*, CPP_IM_*, CPP_CPU_*, CPP_CPU_SPEC): New.
- (EXTRA_SPECS, SUBTARGET_EXTRA_SPECS): New.
- * alpha/elf.h (LD_SPEC): Use %(elf_dynamic_linker).
- * alpha/linux-elf.h (SUBTARGET_EXTRA_SPECS): New.
- (LIB_SPEC): Tidy.
- * alpha/linux.h (CPP_PREDEFINES): Tidy.
- * alpha/netbsd-elf.h (SUBTARGET_EXTRA_SPECS): New.
- * alpha/netbsd.h (CPP_PREDEFINES): Tidy.
- * alpha/osf.h (CPP_PREDEFINES): Remove bits subsumed by CPP_CPU_SPEC.
- * alpha/win-nt.h (CPP_PREDEFINES): Likewise.
- * alpha/vsf.h (CPP_PREDEFINES): Likewise.
- (CPP_SUBTARGET_SPEC): New. Do this instead of overriding CPP_SPEC.
- * alpha/vxworks.h: Likewise.
+ * loop.c (strength_reduce): Do not clear NOT_EVERY_ITERATION at the
+ last CODE_LABEL in a loop if we have previously passed a jump
+ to the top of the loop.
-Mon Jul 20 22:51:57 1998 Ken Raeburn <raeburn@cygnus.com>
+Mon May 24 01:02:58 1999 Mark Mitchell <mark@codesourcery.com>
- * mips.md (reload_outsi): Added missing REGNO call.
- (smulsi3_highpart, umulsi3_highpart): Provide prototype for
- function pointer.
- (mul_acc_di, mul_acc_64bit_di): Don't use match_op_dup, use
- another match_operator and compare the codes.
+ * stmt.c (expand_end_bindings): Ignore any elements of VARS that
+ are not VAR_DECLs.
- * mips.h (MASK_DEBUG_E, MASK_DEBUG_I): Set to zero.
+Sun May 23 20:31:16 1999 Jeffrey A Law (law@cygnus.com)
- * MIPS multiply pattern fixes:
- * mips.h (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS):
- Add union classes for HI, LO, or HILO plus general registers.
- (GENERATE_MADD): Deleted.
- * mips.md (mulsi3_mult3): Don't disparage output-LO alternative.
- Add TARGET_MAD to condition.
- (mulsi3): Test HAVE_mulsi3_mult3, not specific flags.
- (mul_acc_si): Expand GENERATE_MADD here; it's the only use. Use
- "*d" for accumulator, to give preference to LO initially but not
- during reload.
+ * loop.c (strength_reduce): Grow reg_single_usage as needed.
-Mon Jul 20 01:13:19 1998 Jim Wilson <wilson@cygnus.com>
+Sun May 23 10:13:20 1999 David O'Brien <obrien@FreeBSD.org>
- * function.c (fixup_var_refs_insns): Handle CLOBBER of a CONCAT.
+ * i386/freebsd-elf.h (LINK_SPEC): Change -static to -Bstatic.
+ Also remove a useless comment.
-Sat Jul 18 15:20:19 1998 Mark Mitchell <mark@markmitchell.com>
+Sun May 23 10:05:23 1999 Jerry Quinn <jquinn@nortelnetworks.com>
- * loop.c (maybe_eliminate_biv_1): Avoid signed/unsigned comparison
- confusion when setting cc0.
+ * pa.md (negdf2,negsf2): Use fneg instead of fsub on pa 2.0.
-Fri Jul 17 03:26:12 1998 Rihcard Earnshaw (rearnsha@arm.com)
+Sat May 22 01:27:49 1999 Mark Mitchell <mark@codesourcery.com>
- * tree.c (valid_machine_attribute): Only create a new type variant if
- there is a decl to use it.
+ * expr.h (lang_expand_constant): Guard with #ifdef TREE_CODE.
-Fri Jul 17 02:01:00 1998 Jeffrey A Law (law@cygnus.com)
+Thu May 20 10:00:42 1999 Stephen L Moshier <moshier@world.std.com>
- * Makefile.in (WARN_CFLAGS): Disable -W -Wall for the release
- branch.
+ * Makefile.in (GCC_FOR_TARGET): Add -I$(build_tooldir)/include.
+
+Thu May 20 09:58:57 1999 Jan Hubicka <hubicka@freesoft.cz>
-Thu Jul 16 14:48:04 1998 Nick Clifton <nickc@cygnus.com>
+ * function.c (assign_stack_local): Align stack slot propertly.
+ (assign_outer_stack_local): Likewise.
+
+Thu May 20 10:38:43 1999 Mark Mitchell <mark@codesourcery.com>
- * gcc.c (do_spec_1): Cope with %g/%u/%U options which do not have
- a suffix.
+ * expr.h (lang_expand_constant): Declare.
+ * toplev.c (lang_expand_constant): Define it.
+ * varasm.c (output_constant): Use it.
-Thu Jul 16 17:07:24 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Thu May 20 11:28:53 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * cplus-dem.c (demangle_nested_args): Make function definition
- static to match the prototype.
+ * optabs.c (expand_cmplxdiv_straight, expand_cmplxdiv_wide):
+ Change function definitions to K&R style.
-Thu Jul 16 01:17:44 1998 Richard Henderson <rth@cygnus.com>
+Thu May 20 08:15:00 1999 Bruce Korb <ddsinc09@ix.netcom.com>
- * loop.c (emit_iv_add_mult): Scan the entire insn list generated
- for the sequence, recording base values.
+ * fixinc/fixincl.c(main): we must not ignore SIGCLD now.
-Wed Jul 15 00:52:54 PDT 1998 Jeff Law (law@cygnus.com)
+Thu May 20 07:06:39 1999 Alexandre Oliva <aoliva@acm.org>
- * version.c: Bump for snapshot.
+ * fixinc/Makefile.in(gnu-regex.o): add $(INCLUDES) to compile options
+ * fixinc/fixincl.c(wait_for_pid): K&R-ify arguments
+ (several places): omit static initialization
+ (process): use single fd, since only the read fd is used
+ * fixinc/gnu-regex.c: define 'const' away, if not supported
+ * fixinc/procopen.c(several places): omit static initialization
+ * fixinc/server.c: define 'volitile' away, if not supported
-Wed Jul 15 00:52:20 PDT 1998 Jeff Law (law@cygnus.com)
+1999-05-20 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * version.c: Bump for snapshot.
+ * config/dbxcoff.h (DBX_OUTPUT_MAIN_SOURCE_FILE_END): Use
+ asm_fprintf and %L to generate the label name.
+ * config/dbxelf.h (DBX_OUTPUT_MAIN_SOURCE_FILE_END): Likewise.
+ (ASM_OUTPUT_SOURCE_LINE): Correct generation of internal labels.
-Tue Jul 14 14:15:30 1998 Nick Clifton <nickc@cygnus.com>
+Thu May 20 01:40:55 1999 Jeffrey A Law (law@cygnus.com)
- * gcc.c: Remove ANSI-C ism from --help code.
+ * jump.c (can_reverse_comparison_p): Do not abort if the comparison
+ insn for a conditional jump can not be found.
- * toplev.c: Support --help with USE_CPPLIB.
+Wed May 19 23:58:58 1999 Jeffrey A Law (law@cygnus.com)
-Tue Jul 14 02:20:38 1998 Jeffrey A Law (law@cygnus.com)
+ * mips.h (ENCODE_SECTION_INFO): Do not perform GP optimizations
+ on variables in specific sections other than .sbss and .sdata.
- * configure.in: Rework gas feature code to work with symlink based
- source trees.
+Tue May 18 11:20:48 1999 Mark Mitchell <mark@codesourcery.com>
- * version.c: Bump to avoid problems with old spec files during
- bootstrap.
+ * stmt.c (expand_return): Call start_cleanup_deferral and
+ end_cleanup_deferral around conditional code.
-Mon Jul 13 23:11:44 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+Wed May 19 03:10:08 1999 Bruce Korb <ddsinc09@ix.netcom.com>
- * config/sparc/sparc.c (output_scc_insn): Enclose || conditions in
- parens while walking over notes.
- * config/sparc/sparc.md (reg movdi split): Clean up matching
- conditions.
- (all DI arithop splits on 32-bit): Handle immediate arguments
- correctly when they are CONST_INTs.
+ * fixinc/fixincl.tpl: Avoid depending on ANSI C features for
+ filename lists. Utilizes new AutoGen function "krstr".
+ * fixinc/fixincl.x: Rebuilt.
-Mon Jul 13 23:57:21 1998 Kamil Iskra <iskra@student.uci.agh.edu.pl>
+Wed May 19 02:47:11 1999 Jan Hubicka (hubicka@freesoft.cz)
- * m68k/m68k.h (TARGET_SWITCHES): Clear MASK_68040_ONLY for
- -m68020-40, -m68020-60 and -m5200.
+ * i386.c (output_float_compare): Avoid GNU-C extensions.
-Mon Jul 13 23:52:05 1998 Weiwen Liu <weiwen.liu@yale.edu>
+Wed May 19 00:50:24 1999 Jeffrey A Law (law@cygnus.com)
- * gcc.c (do_spec_1): Fix %O handling for secure temporary file
- creation.
+ * version.c: Bump version to gcc-2.95 prerelease.
-Mon Jul 13 23:42:36 1998 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+Tue May 18 03:53:37 1999 Craig Burley <craig@jcb-sc.com>
- * sh/elf.h (MAX_OFILE_ALIGNMENT): Undefine before including svr4.h.
+ Improve open-coding of complex divide:
+ * flags.h: Declare new front-end-malleable flag.
+ * toplev.c: Define new flag.
+ * optabs.c (expand_cmplxdiv_straight): New function to do original
+ open-coding.
+ (expand_cmplxdiv_wide): New function to do new open-coding,
+ from Toon Moene, with changes (call to emit_barrier, dropping
+ of spurious `ok = 1;', plus the obvious `break;' -> `return 0;').
+ (expand_binop): A bit of spacing fixing, while at it.
+ Use new functions instead of inlining the open-coding code.
-Mon Jul 13 23:36:08 1998 Jim Wilson <wilson@cygnus.com>
+Tue May 18 00:51:46 1999 Krister Walfridsson <cato@df.lth.se>
- * i386/i386.h (CPP_486_SPEC, CPP_586_SPEC, CPP_686_SPEC): New specs.
- (CPP_CPU_DEFAULT_SPEC, CPP_CPU_SPEC): Use them.
- (EXTRA_SPECS): Support them.
- * gcc.c: Delete %[spec] support.
- (do_spec_1, case '('): Likewise.
- (do_spec_1, case '['): Call error.
- * i386/aix386ng.h, cygwin32.h, freebsd-elf.h, gas.h, isc.h,
- linux-aout.h, linux-oldld.h, linux.h, osfelf.h, osfrose.h, sco.h,
- sco4.h, sco4dbx.h, sco5.h, sol2.h, sysv3.h (CPP_SPEC): Delete
- %[cpp_cpu].
+ * configure.in (arm*-*-netbsd*): Use collect2.
+ (i[34567]86-*-netbsd*): Likewise.
+ (m68k*-*-netbsd*): Likewise.
+ (ns32k-*-netbsd*): Likewise.
+ (sparc-*-netbsd*): Likewise.
+ (vax-*-netbsd*): Likewise.
+ * configure: Rebuilt.
-Mon Jul 13 23:31:04 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Tue May 18 00:21:34 1999 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * m68k.c (output_scc_di): Use cmpw #0 only for address registers.
+ * cppspec.c: Insert -no-gcc into command line unless -gcc was
+ given by user.
+ * gcc.c (default_compilers): Define __GNUC__ and
+ __GNUC_MINOR__ only if -no-gcc was not given.
+ * objc/lang-specs.h: Likewise.
+ * cpp.texi: Document -x and -std options; explain that -lang
+ is no longer supported. Minor related corrections.
-Mon Jul 13 23:26:43 1998 Jeffrey A Law (law@cygnus.com)
+Mon May 17 23:56:39 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * tree.h (tree_common): Note front-end dependencies on layout of
- this structure.
+ * Makefile.in (stmp-fixproto): Pass location of mkinstalldirs to
+ fixproto.
+ * fixproto: Avoid unportable constructs such as `basename' and
+ `mkdir -p'. Use mkinstalldirs from the environment if `mkdir -p'
+ fails.
-Mon Jul 13 23:18:39 1998 Craig Burley <burley@gnu.org>
+ * fixinc/fixincl.c: Remove #error, it is not portable.
- * stmt.c (expand_expr_stmt): If not assigning fresh
- value to last_expr_value, zero it, so old garbage
- doesn't get dereferenced.
+Mon May 17 23:50:41 1999 Marc Espie <espie@cvs.openbsd.org>
-Mon Jul 13 23:06:55 1998 Henning.Petersen@t-online.de (Henning Petersen)
+ * collect2.c (main): Fix typo in COLLECT2_HOST_INITIALIZATION.
- * gcse.c (hash_scan_insn): Add missing argument declaration.
+Mon May 17 19:45:41 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
-Mon Jul 13 18:59:13 1998 Jim Wilson <wilson@cygnus.com>
+ * fixinc/fixincl.c (process): Wait for children from chain_open()
+ to avoid creating zombies.
- * configure.in (mips-sgi-irix5cross64, mips-sgi-irix5*): Remove
- HAVE_INTTYPES_H from xm_defines. Define xm_file to mips/xm-iris5.h.
- * mips/xm-iris5.h (USG): Delete.
+ * fixinc/inclhack.tpl: Removed no-op pipe.
-Mon Jul 13 17:18:47 1998 Nick Clifton <nickc@cygnus.com>
+ * fixinc/inclhack.sh fixinc/fixincl.sh: regenerate
- * cccp.c (main): Add support for parsing --help.
- (display_help): New function: display command line switches.
+Mon May 17 07:23:34 1999 Mark Mitchell <mark@codesourcery.com>
- * cpplib.c (cpp_handle_option): Add support for parsing --help.
- (display_help): New function: display command line switches.
+ * tree.def (TYPE_NONCOPIED_PARTS): Revise documentation to match
+ reality.
+ * expr.c (init_noncopied_parts): Don't generate initializers for
+ parts that don't need them.
- * gcc.c (main): Add support for parsing --help, and passing it on
- to the sub-processes invoked by gcc.
- (display_help): New function: display comman line switches.
+Mon May 17 02:56:35 PDT 1999 Jeff Law (law@cygnus.com)
- * tm.texi (TARGET_SWITCHES and TARGET_OPTIONS): Document
- 'description' field added to structure.
+ * version.c: Bump for snapshot.
- * toplev.c: Add support for parsing --help.
- Add documentation strings to command line option tables.
- (display_help): New function: display comman line switches.
+Sat Oct 31 05:08:34 CET 1998 Jan Hubicka (hubicka@freesoft.cz)
-Mon Jul 13 16:15:10 1998 John Carr <jfc@mit.edu>
+ * reg-stack.c: Do not emit pop insns after cc0 setter.
+ (emit_pop_insn): Do not emit insn in case WHEN is NULL.
+ (compare_for_stack_reg): Update REG_DEAD note and
+ do not emit push insn.
- * sparc.c, sparc.h, sparc.md: New trampoline code.
- Allow integer operand 1 to V8+ DImode shift instructions.
- Fix bugs in V8+ wide multiply patterns.
- In 32 bit mode, split DImode register moves and logical instructions.
- Write V9 branch prediction flag.
- Use V9 conditional move more often for scc.
+ * i386.c: (output_float_compare): Handle new REG_DEAD notes.
-Mon Jul 13 15:10:09 1998 Philippe De Muyter <phdm@macqel.be>
+Mon May 17 01:57:37 1999 David Daney <daney@ibw.com.ni>
- * invoke.texi(-fno-builtin): Explain that the names of built-in
- functions begin with `__builtin_', not `__'.
+ * i386/sol2.h (LINK_SPEC): Do not pass "-z text" to the linker
+ if -mimpure-text.
-Mon Jul 13 19:01:52 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+1999-05-17 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * reload1.c (reload_reg_free_before_p): Abort for RELOAD_FOR_OUTPUT.
+ * m68k.c (standard_68881_constant_p): Don't accept -0.0 as valid
+ 68881 constant.
-Mon Jul 13 10:50:17 1998 Mark Mitchell <mark@markmitchell.com>
+ * fold-const.c (fold_truthop): When converting a one-bit
+ comparison don't sign extend the constant.
- * cplus-dem.c (SCOPE_STRING): Remove DMGL_JAVA stuff.
- (cplus_demangle_opname): Initialize work.
- (demangle_template): Remove is_java_array.
- (do_type): Remove DMGL_JAVA stuff.
- (long_options): Remove "java".
- (main): Remove 'j' option.
+ * cse.c (cse_insn): Copy SRC_CONST before putting it in the
+ REG_EQUAL note.
-Mon Jul 13 10:19:00 1998 Jeffrey A Law (law@cygnus.com)
+1999-05-17 Mike Stump <mrs@wrs.com>
- * mn10300.h (REG_CLASS_FROM_LETTER): Map 'y' to SP_REGS.
- Handle 'x' as NO_REGS for this cpu.
- (REGNO_OK_FOR_BIT_BASE_P): Define.
- (REG_OK_FOR_BIT_BASE_P): Define.
- (GO_IF_LEGITIMATE_ADDRESS): Use them.
- (REG_OK_FOR_INDEX_P): Tweak.
- * mn13000.c (REG_SAVE_BYTES): Define.
- (expand_epilogue, initial_offset): Use it.
- (secondary_reload_class): Slightly reformat.
- (output_tst): Tweak comments.
- * mn10300.md: Change 'x' to 'y' for SP_REGS. Then add 'x' to many
- patterns.
- (addsi3): Turn into a define_expand/define_insn pair. Rework code for
- three operand addition case to be more efficient.
- (subsi3): Turn into a define_expand/define_insn pair.
+ * rs6000/vxppc.h (CPP_SPEC): Fix support for vararg functions.
- * expr.c (expand_expr): Only set MEM_IN_STRUCT_P if the memory address
- is not varying for REFERENCE_TYPE or when we think we might have found
- an optimized access to the first element in an array.
+Sat May 15 14:22:40 1999 Jeffrey A Law (law@cygnus.com)
-Mon Jul 13 02:24:08 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+ * fixinc/hackshell.tpl: Fix mis-applied patch.
+ * fixinc/inclhack.sh: Regenerated.
- * regclass.c (reg_scan_mark_refs): New arg min_regno. Only update
- regscan information for REGs with numbers greater than or equal to
- this. All callers changed.
- (reg_scan_update): New function to efficiently update regscan
- information on the fly.
- * rtl.h: Add prototype.
- * jump.c (jump_optimize): Call it when we make a transformation
- which generates new pseudo-REGs.
+Thu May 13 21:05:55 1999 Mark Kettenis <kettenis@gnu.org>
-Sun Jul 12 13:08:14 1998 Jeffrey A Law (law@cygnus.com)
+ * fixinc/mkfixinc.sh: Add the Hurd (*-*-gnu*) to the list of
+ targets that do not need any fixes.
- * collect2.c (main): Use "-x c" instead of "-lang-c" for force the
- compiler into C mode.
+Sat May 15 14:12:38 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Sun Jul 12 01:27:05 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * config/c4x/c4x.md (set_lo_sum+2): New splitter to load large
+ const_ints.
- * cplus-dem.c (demangle_nested_args): Return a value.
-
- * tree.h (TYPE_P): New macro.
-
-Sat Jul 11 16:19:48 1998 Mark Mitchell <mark@markmitchell.com>
-
- * cplus-dem.c (string): Move definition before work_stuff.
- (work_stuff): Add volatile_type, forgetting_types,
- previous_argument, and nrepeats fields.
- (SCOPE_STRING): New macro.
- (demangle_template): Add `remember' parameter. Add comment.
- Register the `B' code type here, if remembering. Tidy. Fix crash
- on NULL tmpl_argvec. Be consistent with use of tname/trawname.
- (demangle_nested_args): New function.
- (internal_cplus_demangle): Handle volatile-qualified member
- functions.
- (mop_up): Delete the previous_argument string if present.
- (demangle_signature): Tidy. Handle volatile-qualified member
- functions. Handle back-references using the `B' code. Use extra
- parameter to demangle_template and SCOPE_STRING where appropriate.
- (demangle_template_value_parm): Fix thinko; 'B' is not an integral
- code.
- (demangle_class): Use SCOPE_STRING.
- (gnu_special): Pass additional argument to demangle_template.
- Use SCOPE_STRING.
- (demangle_qualified): Save qualified types for later
- back-references. Handle constructors and destructors for template
- types correctly.
- (do_type): Tidy. Use SCOPE_STRING. Pass extra argument to
- demangle_template. Use demangled_nested_args. Don't remember
- qualified types here; that's now done in demangle_qualified.
- Similarly for templates.
- (do_arg): Improve commment. Handle 'n' repeat code.
- (remember_type): Check forgetting_types.
- (demangle_args): Deal with 'n' repeat codes. Tidy.
-
-Sat Jul 11 02:59:08 1998 Richard Earnshaw <rearnsha@arm.com>
+Sat May 15 14:09:08 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * arm.md (extendhisi2_mem, movhi, movhi_bytes): Propagate the volatile
- and structure attribute flags to MEMs generated.
- (splits for sign-extended HI & QI mode from memory): Also propagate
- the volatile flag.
+ * config/c4x/c4x.md (decrement_and_branch_on_count): Disabled.
+ (doloop_begin, doloop_end): New patterns.
+ (*rptb_init): Added extra operands.
- * configure.in (thumb-*-coff*): Don't cause fixincludes to be run.
+Fri May 14 21:31:36 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Fri Jul 10 19:06:59 1998 Michael Meissner <meissner@cygnus.com>
+ * config/c4x/c4x.md (*umulqi3_highpart_clobber): Fix operand 2
+ constraints order.
- * varray.h: Include system.h if it hasn't already been included
- before to get size_t declared.
+1999-05-14 Ulrich Drepper <drepper@cygnus.com>
-Fri Jul 10 12:53:58 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+ * fixinc/fixinc.x86-linux-gnu (FD_ZERO): Fix operand numbers in
+ asm input operands.
- * jump.c (jump_optimize): If after_regscan and our transformations
- generate new REGs, rerun reg_scan.
+Thu May 13 15:34:18 1999 David Edelsohn <edelsohn@gnu.org>
-Fri Jul 10 11:50:43 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+ * rs6000.c (mask_constant): Delete.
+ (mask_operand): Move mask_constant() body to here.
+ * rs6000.h (mask_constant): Delete declaration.
+ * rs6000.md (nabsdi2): Reverse subtraction in splitter.
- * config/i960/i960.c (i960_address_cost): MEMA operands with
- positive offsets < 4096 are free.
+Thu May 13 02:25:01 1999 Jeffrey A Law (law@cygnus.com)
-Fri Jul 10 12:34:37 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * cpp.texi: Fix some typos.
- * config/m68k/m68k.c (const_uint32_operand): Recognize
- CONSTANT_P_RTX.
- (const_sint32_operand): Likewise.
+Thu May 13 01:49:55 1999 Graham Stott <GrahamS@RCP.co.uk>
-Thu Jul 9 22:58:59 1998 Jeffrey A Law (law@cygnus.com)
+ * loop.c (maybe_eliminate_biv): Check regno against
+ max_reg_before_loop.
- * Makefile.in (alias.o): Depend on $(EXPR_H).
+ * i386.c (memory_address_info): Correct the scale
+ factor test.
-Thu Jul 9 18:24:56 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Thu May 13 01:31:19 1999 Nick Burrett <nick.burrett@btinternet.com>
- * reload1.c (choose_reload_regs): If using an equivalence from
- find_equiv_reg and reg_reloaded_valid is not set for this register,
- clear the associated spill_reg_store.
+ * arm.md (nop): Backout Apr 27 change. Ensure REGISTER_PREFIX is
+ applied to each register.
+ * aof.h (ASM_FILE_START): Define register `r0'.
-Thu Jul 9 18:12:49 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+1999-05-12 20:22 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * reload1.c (emit_reload_insns): If an output reload copies only
- to a secondary reload register, indicate that the secondary reload
- does the actual store.
+ * configure.in: Make --enable-cpp and --with-cpp-install-dir
+ documented options. Enable the cpp driver by default.
+ * configure: Rebuilt.
-Thu Jul 9 18:01:05 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Wed May 12 18:08:48 1999 David Edelsohn <edelsohn@gnu.org>
+ Richard Henderson <rth@cygnus.com>
- * reload.c (find_equiv_reg): If need_stable_sp is set,
- check if stack pointer is changed directly in a PARALLEL.
+ * rs6000.c (print_operand) [w]: Calculate signed constant more clearly.
+ (rs6000_allocate_stack_space): Print as hexadecimal value.
+ * rs6000.h (CONST_OK_FOR_LETTER_P): 'L' checks for a signed,
+ 16-bit shifted constant. Fix typo for 'P'.
+ (EXTRA_CONSTARINT): 'T' checks for a 32-bit mask operand.
+ * rs6000.md (movsi, addsi3_internal1, movdi, adddi3_internal1):
+ Use 'L' for shifted constant.
+ (anddi3_internal3): Fix typo.
+ (32-bit mask patterns): Use 'T'.
-Thu Jul 9 10:38:14 1998 Jeffrey A Law (law@cygnus.com)
+Wed May 12 07:30:31 1999 Bruce Korb <ddsinc09@ix.netcom.com>
- * jump.c (duplicate_loop_exit_test): Fix thinko.
+ * fixinc/fixincl.c(quoted_file_exists): new procedure to ensure that
+ a file exists before trying to copy it into the destination
+ (extract_quoted_files): use that routine.
-Thu Jul 9 01:30:37 1998 Joel Sherrill <joel@OARcorp.com>
- Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+Wed May 12 07:27:31 1999 Craig Burley <craig@jcb-sc.com>
- * config/i386/rtemself.h: Updated to keep in sync with
- config/i386/linux.h.
+ Allow front end (like g77's) to override maintenance of errno:
+ * expr.c (expand_builtin): Bother with errno only if
+ flag_errno_math.
+ * flags.h: Declare flag_errno_math.
+ * toplev.c: Define flag_errno_math.
- * configure.in: Added sh-rtemself.
- * configure: Rebuilt.
- * config/sh/rtems.h: Removed -D__ELF__ since it is now COFF.
- * config/sh/rtemself.h: New file.
+Tue May 11 23:55:49 1999 Jeffrey A Law (law@cygnus.com)
- * config/rs6000/rtems.h: Defined STARTFILE_DEFAULT_SPEC.
+ * fixproto: Change "mkdir" calls to "mkdir -p"
-Wed Jul 8 21:43:14 1998 Jeffrey A Law (law@cygnus.com)
+ * fixinc/inclhack.def (io_def_quotes): Consistently allow multiple
+ whitespace characters between the "define" and the name of the macro.
+ * fixinc/fixincl.x, fixinc/inclhack.sh: Rebuilt.
- * configure.in: Check if the assembler supports ".balign" and
- ".p2align" and define HAVE_GAS_BALIGN_AND_P2ALIGN appropriately.
- * acconfig.h (HAVE_GAS_BALIGN_AND_P2ALIGN): New tag.
- * i386/gas.h (ASM_OUTPUT_ALIGN): If the assembler has support for
- ".balign" then use it.
+Tue May 11 20:46:37 1999 Richard Henderson <rth@cygnus.com>
- * print-rtl.c (print_rtx): Revert previous patch.
+ * alpha.c (alpha_expand_block_move): Handle TImode registers
+ used with ADDRESSOF.
+ (alpha_expand_block_clear): Handle ADDRESSOF specially.
- * jump.c (duplicate_loop_exit_test): Do not duplicate the loop exit
- test if the exit code has an insn with ASM_OPERANDS.
+1999-05-11 Ulrich Drepper <drepper@cygnus.com>
- * i386/cygwin32.h (STDIO_PROTO): Fix typo.
- * m32r.h (STDIO_PROTO): Fix typo.
+ * fixinc/fixinc.x86-linux-gnu (FD_ZERO): Remove unneccessary
+ memory output operand which irritates gcc.
- * pa.h (LEGITIMIZE_RELOAD_ADDRESS): Handle addresses created by
- LEGITIMIZE_RELOAD_ADDRESS.
- * tm.texi (LEGITIMIZE_RELOAD_ADDRESS): Note that this macro must be
- able to handle addresses created by previous invocations of the macro.
+Tue May 11 11:45:16 1999 Dave Brolley <brolley@cygnus.com>
- * flow.c (find_auto_inc): Remove most recent change. Real bug was
- elsewhere.
+ * toplev.c (documented_lang_options): Add -MD, -MMD, -M and -MM for
+ cpplib-enabled compilers.
- * cse.c (count_reg_usage): Count registers used in addresses of
- CLOBBERs.
+Tue May 11 11:34:56 1999 Vladimir Makarov <vmakarov@tofu.to.cygnus.com>
-Wed Jul 8 15:08:29 1998 Jim Wilson <wilson@cygnus.com>
+ * config/sparc/sparc.h (GO_IF_LEGITIMATE_ADDRESS): Add parentheses
+ around &&.
- * Makefile.in (STAGESTUFF): Readd line lost during June 9 FSF merge.
+Mon May 10 13:51:24 1999 Nick Clifton <nickc@cygnus.com>
- * configure.in (mips64orion-*-rtems*): Use elf64.h not elfl64.h.
+ * tm.texi (FUNCTION_ARG): Stack element of PARALLEL must come
+ first.
-1998-07-08 Vladimir N. Makarov <vmakarov@cygnus.com>
+Tue May 11 01:32:01 1999 Jeffrey A Law (law@cygnus.com)
- * config/fp-bit.c (__gexf2, __fixxfsi, __floatsixf): Add function
- stubs.
+ * fixinc/inclhack.def (sun_auth_proto): Apply to all targets.
+ (sysz_stdlib_for_sun): Similarly.
+ * fixinc/fixincl.x, fixinc/inclhack.sh: Rebuilt.
- * toplev.c (lang_options): Add -Wlong-long, -Wno-long-long
- options.
- * c-decl.c (warn_long_long): Define.
- (c_decode_option): Parse -Wlong-long, -Wno-long-long options.
- (grokdeclarator): Add flag `warn_long_long' as guard for
- warning "ANSI C does not support `long long'".
- * invoke.texi: Add description of options -Wlong-long,
- -Wno-long-long.
- * gcc.1: The same as above.
-
-Wed Jul 8 02:43:34 1998 Jeffrey A Law (law@cygnus.com)
+Mon May 10 20:34:10 1999 Jim Wilson <wilson@cygnus.com>
- * rtlanal.c (reg_overlap_mentioned_p): Handle STRICT_LOW_PART. If
- either argument is CONSTANT_P, then return zero.
- * reload.c (reg_overlap_mentioned_for_reload_p): Similarly.
+ * config/mips/elf.h (UNIQUE_SECTION_P): Undef.
+ * config/mips/elf64.h (UNIQUE_SECTION_P): Undef.
+ * config/mips/mips.h (UNIQUE_SECTION_P): Define to 0.
- * configure.in: Also look at $srcdir/gas/configure to find a
- gas version #.
+1999-05-10 18:21 -0400 Zack Weinberg <zack@rabi.columbia.edu>
-Wed Jul 8 00:28:22 1998 Carlo Wood <carlo@runaway.xs4all.nl>
+ * cppfiles.c (initialize_input_buffer): New function.
+ (finclude): Call it, if pfile->input_buffer is NULL. Accept
+ any character device as an input file.
+ (read_and_prescan): Use pfile->input_buffer and
+ pfile->input_speccase.
+ * cppinit.c (cpp_cleanup): Free pfile->input_buffer and
+ pfile->input_speccase.
+ * cpplib.h (cpp_reader): Add input_buffer, input_speccase, and
+ input_buffer_len members. Use memcpy in CPP_PUTS_Q.
- * dsp16xx.h : Clean up of macro OPTIMIZATION_OPTIONS
+ * cppmain.c: Buffer output in the token_buffer; throttle
+ number of calls to fwrite; check for errors from fwrite.
-Tue Jul 7 21:18:14 1998 Mumit Khan <khan@xraylith.wisc.edu>
+1999-05-10 18:21 -0400 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * i386/cygwin32.h (ASM_DECLARE_FUNCTION_NAME): Merge duplicate
- definitions from last two patches.
+ * cppspec.c: Treat two non-option arguments as input and
+ output file. Three or more non-option args is an error.
+ Clean up.
+ * gcc.c (default_compilers): Pass -$ to the preprocessor.
+ * objc/lang-specs.h: Likewise.
-Tue Jul 7 23:03:34 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon May 10 12:59:20 1999 Jeffrey A Law (law@cygnus.com)
- * reload1.c (choose_reload_regs): Don't set reload_override_in
- if EQUIV is clobbered in INSN and the reload is done after INSN.
+ * optabs.c (emit_cmp_and_jump_insns): Handle the case where both
+ operands to the comparison are constants.
-Tue Jul 7 21:23:36 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon May 10 07:28:10 1999 Bruce Korb <autogen@autogen.freeservers.com>
- * expr.c (emit_queue): If emitting a SEQUENCE, set QUEUED_INSN
- to the first insn of the sequence.
+ * fixinc/inclhack.def(arm_norcroft_hint): check before fixing
+ (no_double_slash): portability
+ (math_exception): added reminder comment
-Tue Jul 7 21:05:25 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon May 10 01:28:10 1999 Craig Burley <craig@jcb-sc.com>
- * cse.c (cse_insn): Don't make change without validation.
+ From Fri May 7 9:31:41 1999 Donn Terry (donn@interix.com):
+ * varasm.c (mark_constant_pool): Add some transitive closure.
-Tue Jul 7 11:40:05 1998 Jeffrey A Law (law@cygnus.com)
+Sun May 9 22:51:04 1999 Craig Burley <craig@jcb-sc.com>
- * mn10200.md (various zero/sign extension patterns): zero and sign
- extensions which use "sub" clobber cc0.
+ Fix gcc.dg/990506-0.c:
+ * c-typeck.c (require_complete_type): Handle ERROR_MARK input.
-Tue Jul 7 09:12:08 PDT 1998 Jeff Law (law@cygnus.com)
+Sun May 9 13:19:12 1999 Jeffrey A Law (law@cygnus.com)
- * version.c: Bump for snapshot.
+ * gcse.c (cprop_insn): Do not try to simplify a simple jump.
-Tue Jul 7 10:07:20 1998 Jeffrey A Law (law@cygnus.com)
+Sun May 9 11:12:19 1999 Philip Blundell <bp@nexus.co.uk>
- * print-rtl.c (print_rtx): Use REAL_VALUE_TYPE instead of "double".
+ * config/arm/arm.h (ASM_OUTPUT_MI_THUNK): Add (PLT) to branch if
+ necessary. Reported by jim@federated.com.
-Tue Jul 7 08:41:27 1998 Richard Henderson (rth@cygnus.com)
+Sat May 8 23:05:35 1999 Jeffrey A Law (law@cygnus.com)
- * print-rtl.c (print_rtx): Only print fp values when REAL_VALUE_TYPE
- is a double.
+ * pa.h (PRINT_OPERAND_ADDRESS): Output "%r0", not "r0" for the
+ base register in an absolute memory address.
+ * pa.md (conditional moves): Avoid using immediate zero for
+ register zero.
-Tue Jul 7 00:31:58 PDT 1998 Jeff Law (law@cygnus.com)
+Sat May 8 06:23:21 1999 Philip Blundell <pb@nexus.co.uk>
- * version.c: Bump for snapshot.
+ Based on patch by Scott Bambrough:
+ * config/arm/arm.h (NEED_PLT_GOT): New macro. Set to 0 if not
+ already defined.
+ * config/arm/elf.h (NEED_PLT_GOT): Define to flag_pic.
+ * config/arm/arm.md (call_symbol, call_value_symbol et al.): If
+ NEED_PLT_GOT is true, add explicit "(PLT)" to generated branches.
+ * config/arm/arm.c (output_func_epilogue,
+ output_return_instruction): Likewise for calls to abort.
-Tue Jul 7 01:03:03 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Sat May 8 01:57:58 1999 Donn Terry (donn@interix.com)
- Support for dllimport and dllexport attributes for i386-pe.
+ * calls.c (rtx_for_function_call): Extend function pointer being
+ passed to chkr_check_exec_libfunc, if needed.
- * tree.h (DECL_NON_ADDR_CONST_P): New accessor macro.
- (struct tree_decl): Add non_addr_const_p field.
- * tree.c (staticp): Use.
+Sat May 8 01:51:50 1999 David Edelsohn <edelsohn@gnu.org>
- * i386/cygwin32.h (CPP_PREDEFINES): Map __declspec(x) to GCC
- attributes.
- (SUBTARGET_SWITCHES): Switches to turn on/off dllimport|export
- attributes. Also accept -mwindows option.
- (VALID_MACHINE_DECL_ATTRIBUTE): New macro.
- (MERGE_MACHINE_DECL_ATTRIBUTE): New macro.
- (REDO_SECTION_INFO_P): New macro.
- (DRECTVE_SECTION_FUNCTION): New macro.
- (drectve_section): Cover function to implement above.
- (SWITCH_TO_SECTION_FUNCTION): New macro.
- (switch_to_section): Covert function to implement above.
- (EXTRA_SECTIONS): Add in_drectve.
- (EXTRA_SECTION_FUNCTIONS): Add in_drectve and switch_to_section.
- (ENCODE_SECTION_INFO): Delete old macro and redefine as a function.
- (STRIP_NAME_ENCODING): Handle new attributes.
- (ASM_OUTPUT_LABELREF): New macro.
- (ASM_OUTPUT_FUNCTION_NAME): New macro.
- (ASM_OUTPUT_COMMON): New macro.
- (ASM_OUTPUT_DECLARE_OBJECT_NAME): New macro.
+ * ginclude/stdarg.h (__va_rounded_size): Use long type for
+ rounding on AIX.
+ * ginclude/varargs.h: Likewise.
- * i386/mingw32.h (CPP_PREDEFINES): Map __declspec(x) to GCC
- attributes.
+Sat May 8 01:47:20 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * i386/winnt.c (i386_pe_valid_decl_attribute_p): New function.
- (i386_pe_merge_decl_attributes): New function.
- (i386_pe_check_vtable_importexport): New function.
- (i386_pe_dllexport_p): New function.
- (i386_pe_dllimport_p): New function.
- (i386_pe_dllexport_name_p): New function.
- (i386_pe_dllimport_name_p): New function.
- (i386_pe_mark_dllexport): New function.
- (i386_pe_mark_dllimport): New function.
- (i386_pe_encode_section_info): New function.
- (i386_pe_unique_section): Strip encoding from name first.
+ * invoke.texi: Remove duplicates in the description of -d
+ letters. Fix use of @item vs. @itemx.
-Tue Jul 7 00:50:17 1998 Manfred Hollstein (manfred@s-direktnet.de)
+Sat May 8 01:43:02 1999 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * libgcc2.c (L_exit): Provide a fake for atexit on systems which
- define ON_EXIT but not HAVE_ATEXIT.
+ * rs6000.h (RS6000_VARARGS_OFFSET): Die die die.
+ (CUMULATIVE_ARGS): Remove varargs_offset; update commentary.
+ * rs6000.c (setup_incoming_varargs): Fix typo last change.
+ (init_cumulative_args): Remove varargs_offset references.
-Tue Jul 7 00:44:35 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+ * rs6000/linux.h (NO_IMPLICIT_EXTERN_C): Define.
+ (MD_EXEC_PREFIX, MD_STARTFILE_PREFIX): Undefine.
- * m68k.md (zero_extend QI to HI): Correctly handle TARGET_5200.
+Sat May 8 01:34:19 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Tue Jul 7 00:36:41 1998 Ulrich Drepper <drepper@cygnus.com>
+ * reload1.c (gen_mode_int): New function.
+ (reload_cse_move2add): Use it to generate the new constants.
- * i386.c: Remove random whitespace at end of lines.
+Sat May 8 01:25:09 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * i386.c (ix86_epilogue): For pentium processors, try to deallocate
- 4 or 8 byte stacks with pop instructions instead of an add instruction.
+ * varasm.c (output_constant): Do nothing if -fsyntax-only.
-Tue Jul 7 00:30:08 1998 Klaus Kaempf <kkaempf@rmi.de>
+Fri May 7 19:10:15 1999 Vladimir Makarov <vmakarov@tofu.to.cygnus.com>
- * alpha.c: Include tree.h before expr.h.
+ * sparc.h (GO_IF_LEGITIMATE_ADDRESS): Prohibit REG+REG addressing
+ for TFmode when there are no instructions which accept REG+REG
+ instructions.
-Mon Jul 6 22:50:48 1998 Jason Merrill <jason@yorick.cygnus.com>
+Fri May 7 12:38:54 1999 Jim Wilson <wilson@cygnus.com>
- * c-parse.in (struct_head, union_head, enum_head): New nonterminals.
- (structsp): Use them. Update files generated from c-parse.in.
- * extend.texi (Type Attributes): Document it.
+ * mips/elf64.h (MAKE_DECL_ONE_ONLY, UNIQUE_SECTION_P): Define.
+ * mips/mips.c (mips_select_rtx_section): When TARGET_MIPS16, use
+ function_section instead of text_section.
+ * mips/mips.h (ENCODE_SECTION_INFO): Add check for UNIQUE_SECTION_P
+ in TARGET_MIPS16 STRING_CST handling.
- * c-decl.c: Add warn_multichar.
- (c_decode_option): Handle -Wno-multichar.
- * c-lex.c (yylex): Check it.
- * c-tree.h: Declare it.
- * toplev.c (lang_options): Add it.
- * invoke.texi: Document it.
+Fri May 7 09:54:11 1999 Nick Clifton <nickc@cygnus.com>
-Mon Jul 6 22:47:55 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ Patch from: Nick Burrett <nick.burrett@btinternet.com>
- * reload.c (find_equiv_reg): When looking for stack pointer + const,
- make sure we don't use a stack adjust.
+ * arm.c (arm_poke_function_name): New function to implement
+ -mpoke-function-name.
+ * aof.h (ASM_DECLARE_FUNCTION_NAME): Call it.
+ * aout.h (ASM_DECLARE_FUNCTION_NAME): Likewise.
+ * elf.h (ASM_DECLARE_FUNCTION_NAME): Likewise.
+ * arm.h: Prototype it.
+ (TARGET_SWITCHES): Add `no-poke-function-name'.
- * reload.c (find_equiv_reg): If need_stable_sp is set,
- check if stack pointer is changed directly.
+Fri May 7 14:19:31 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- * reload1.c (delete_dead_insn): Don't delete feeding insn
- if that insn has side effects.
+ * fixinc/server.c (load_data): Cast text_size to long, adapt
+ format.
+ * fixinc/server.c (read_pipe_timeout): Declare volatile, modified
+ in signal handler.
+ (sig_handler): Add debug code.
+ * fixinc/server.c (run_shell): Don't \-escape cd, it breaks the
+ Ultrix V4.3 /bin/sh.
+ * fixinc/server.c (def_args): Use static instead of STATIC to
+ avoid redefinition error from linker iff DEBUG.
- * flow.c (find_auto_inc): Clear UNCHANGING bit of register that is
- changed.
+ * fixinc/hackshell.tpl: Don't strip trailing directory from
+ DESTDIR - that is already done
- * reload1.c (reload_reg_free_before_p): RELOAD_FOR_OPADDR_ADDR
- precedes RELOAD_FOR_OUTADDR_ADDRESS.
+ * fixinc/fixincl.c (run_compiles): fix memory leak
- * gcse.c (hash_scan_insn): New argument IN_LIBCALL_BLOCK. Changed
- caller.
+Thu May 6 20:34:00 1999 Mark Mitchell <mark@codesourcery.com>
-Mon Jul 6 22:21:56 1998 Kamil Iskra <iskra@student.uci.agh.edu.pl>
+ * resource.c (mark_referenced_resources): Make volatil
+ monotonically increasing.
+ (mark_set_resources): Likewise.
- * m68k.c (output_scc_di): Use cmpw #0 instead of tstl when
- testing address registers on the 68000.
+Thu May 6 20:02:33 1999 Fred Fish <fnf@be.com>
-Mon Jul 6 22:17:19 1998 Alasdair Baird <alasdair@wildcat.demon.co.uk>
+ * rs6000/xm-beos.h (HAVE_VPRINTF): Don't redefine if already defined.
+ (HAVE_PUTENV, HAVE_ATEXIT, HAVE_RENAME): Likewise.
- * i386.c (is_fp_test): Fix thinko.
+Wed May 5 20:28:32 1999 Jason Merrill <jason@yorick.cygnus.com>
- * jump.c (jump_optimize) Check for CONST_INT before using INTVAL.
+ * install.texi (Header Dirs): s/GPLUS/GPLUSPLUS/.
-Mon Jul 6 22:14:31 1998 Richard Henderson (rth@cygnus.com)
+Wed May 5 23:44:15 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * print-rtl.c (print_rtx): Display the real-value equivalent of
- a const_double when easy.
+ * unroll.c (copy_loop_body): Don't copy VTOP notes from copy_notes_from.
- * real.h (REAL_VALUE_TO_TARGET_SINGLE): Use a union to pun types.
- Zero memory first for predictability.
- (REAL_VALUE_TO_TARGET_DOUBLE): Likewise.
- * varasm.c (immed_real_const_1): Notice width of H_W_I == double.
+Wed May 5 16:26:13 1999 Vladimir Makarov <vmakarov@tofu.to.cygnus.com>
- * regclass.c (allocate_reg_info): Initialize the entire reg_data
- virtual array.
+ * function.c (purge_addressof_replacements): Rename into
+ purge_bitfield_addressof_replacements.
+ (purge_addressof_replacements): New variable.
+ (purge_addressof_1): Add code for changing addressof in notes for
+ field values which are extracted by usage MEM with narrower mode.
+ (purge_addressof): Initialize purge_bitfield_addressof_replacements.
-Mon Jul 6 22:09:32 1998 Ian Lance Taylor <ian@cygnus.com>
- Jeff Law <law@cygnus.com>
+Wed May 5 07:40:02 1999 Nick Clifton <nickc@cygnus.com>
+ Patch from: Nick Burrett <nick.burrett@btinternet.com>
+ * config/arm/arm.h (ARM_MCOUNT_NAME): Define.
+ (FUNCTION_PROFILER): Remove assembler dialect dependency and use
+ ARM_MCOUNT_NAME.
+ (TRAMPOLINE_TEMPLATE): Remove assembler dialect dependency.
- * i386/cygwin32.h: Add some declaration of external functions.
- (ASM_DECLARE_FUNCTION_NAME): Define.
- (ASM_OUTPUT_EXTERNAL, ASM_OUTPUT_EXTERNAL_LIBCALL): Define.
- (ASM_FILE_END): Define.
- * i386/winnt.c (i386_pe_declare_function_type): New function.
- (struct extern_list, extern_head): Define.
- (i386_pe_record_external_function): New function.
- (i386_pe_asm_file_end): New function.
+ * config/arm/aof.h (ARM_MCOUNT_NAME): Define.
- * cpplib.c (cpp_options_init): Initialize cplusplus_comments to 1,
- matching July 18, 1995 change to cccp.c. If -traditional then
- disable cplusplus_comments.
+1999-05-05 09:58 -0400 Zack Weinberg <zack@rabi.columbia.edu>
-Mon Jul 6 21:28:14 1998 Jeffrey A Law (law@cygnus.com)
+ * gcc.c (default_compilers): Fix brace nesting bug.
+ * objc/lang-specs.h: Use %i, not %g.mi, for the input file
+ when processing an .mi file.
- * combine.c (expand_compound_operation): Fix thinko in code to optimize
- (zero_extend:DI (subreg:SI (foo:DI) 0)) to foo:DI.
+Tue May 4 13:17:55 1999 Mark Mitchell <mark@codesourcery.com>
- * Disable the following change from gcc2. Not appropriate for egcs:
+ * resource.c (mark_set_resources): Handle UNSPEC_VOLATILE,
+ ASM_INPUT, TRAP_IF, and ASM_OPERANDS just like in
+ mark_referenced_resources.
- Sun Jun 7 09:30:31 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
- * reload.c (find_reloads): Give preference to pseudo that was the
- reloaded output of previous insn.
+Mon May 3 22:38:41 1999 David Edelsohn <edelsohn@gnu.org>
-Mon Jul 6 21:07:14 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * rs6000/aix43.h (SUBTARGET_OVERRIDE_OPTIONS): Change non-PowerPC
+ and AIX64 combination to warning. Add warning for disabling
+ PowerPC64 support when using 64-bit mode.
+ (LIB_SPEC): Do not link with libg.a in 64-bit mode.
+ (LINK_SPEC): Do not export libg.exp symbols in 64-bit mode.
+ * rs6000/rs6000.h (MY_ISCOFF): Treat import/export files as valid
+ XCOFF files.
+ (read_only_data_section, private_data_section,
+ read_only_private_data_section): Always align CSECTs to doubleword
+ boundary regardless of mode.
+ (TEXT_SECTION_ASM_OP): Align text CSECT on doubleword boundary in
+ 64-bit mode.
+ (DATA_SECTION_ASM_OP): Always align CSECT to doubleword boundary.
+ (ASM_OUTPUT_LOCAL): Use rounded size in 64-bit mode to
+ maintain doublword alignment.
- * aclocal.m4 (GCC_FUNC_PRINTF_PTR): Don't define HOST_PTR_PRINTF.
- Instead, define a new macro HAVE_PRINTF_PTR which only signifies
- whether we have the %p format specifier or not.
+Mon May 3 14:45:23 1999 Jeffrey A Law (law@cygnus.com)
- * acconfig.h: Delete stub for HOST_PTR_PRINTF, add HAVE_PRINTF_PTR.
-
- * machmode.h (HOST_PTR_PRINTF): When determining the definition,
- check HAVE_PRINTF_PTR to see whether "%p" is okay.
+ * mn10200.md (btst insns): btst does not leave cc0 in a useable
+ state for redundant tst eliminatino.
+ * mn10300.md (btst insns): Likewise.
- * mips-tfile.c: Include machmode.h to get HOST_PTR_PRINTF.
+Mon May 3 16:14:32 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * Makefile.in (mips-tfile.o): Depend on machmode.h.
+ * mips.h (Pmode): Revert Oct 14th change which added a cast.
-Mon Jul 6 10:42:05 1998 Mark Mitchell <mark@markmitchell.com>
+Sun May 2 14:02:21 1999 Mark Mitchell <mark@codesourcery.com>
- * jump.c (duplicate_loop_exit_test): Don't refuse to copy a
- section of code just because it contains
- NOTE_INSN_BLOCK_{BEG,END}.
- * stmt.c (expand_end_loop): Likewise. Also, don't refuse to
- move CALL_INSNs or CODE_LABELs. When moving code, don't move
- NOTE_INSN_BLOCK_{BEG,END}.
+ * tree.h (struct tree_decl): Add comdat_flag.
+ (DECL_COMDAT): Define it.
+ * toplev.c (wrapup_global_declarations): Don't output a
+ DECL_COMDAT function just because it's public.
-Mon Jul 6 09:38:15 1998 Mark Mitchell <mark@markmitchell.com>
+Sun May 2 15:16:42 1999 Joseph S. Myers <jsm28@cam.ac.uk>
- * cse.c (CSE_ADDRESS_COST): New macro, based on ADDRESS_COST, but
- dealing with ADDRESSOF.
- (find_best_addr): Use it.
+ * pdp11.h (TARGET_SWITCHES): Fix error in previous change.
+ (ASSEMBLER_DIALECT): Define.
+ (CONDITIONAL_REGISTER_USAGE): Rename floating point registers if
+ required for the UNIX assembler.
+ (ASM_OUTPUT_INT): Remove. The compiler will synthesise it.
+ (ASM_OUTPUT_ADDR_VEC_PROLOGUE): Remove.
+ (ASM_OPEN_PAREN, ASM_CLOSE_PAREN): Change to "[" and "]".
+ (TRAMPOLINE_TEMPLATE): Use ASM_OUTPUT_SHORT.
+ * pdp11.c (output_addr_const_pdp11): Copy of output_addr_const
+ adapted to output constants in octal.
+ * pdp11.c, pdp11.h, pdp11.md: Use output_addr_const_pdp11 instead
+ of output_addr_const. Output constants in octal. Use assembler
+ dialect alternatives where DEC and UNIX assemblers use different
+ instruction names.
-Mon Jul 6 09:27:08 1998 Richard Henderson <rth@cygnus.com>
+Sun May 2 01:15:06 PDT 1999 Jeff Law (law@cygnus.com)
- * alpha/vms.h (TRAMPOLINE_TEMPLATE): Revert last change.
+ * version.c: Bump for snapshot.
-Mon Jul 6 09:25:06 1998 Dave Love <d.love@dl.ac.uk>
+Fri Apr 30 13:55:43 1999 Richard Henderson <rth@cygnus.com>
- * libgcc2.c (__eprintf): Make args consistent with prototype in
- assert.h.
+ * va-ppc.h (__va_start_common): Let __builtin_saveregs do the work.
+ * rs6000.c (expand_builtin_saveregs): For V4, initialize a private
+ va_list struct, and return a pointer to it.
+ (setup_incoming_varargs): V4 save area based off virtual_stack_vars
+ instead of frame_pointer.
-Mon Jul 6 00:28:43 1998 Mark Mitchell <mark@markmitchell.com>
+Thu Apr 29 23:02:22 1999 Mark Mitchell <mark@codesourcery.com>
- * cse.c (cse_insn): When SETting (MEM (ADDRESSOF (X))) to Y,
- don't claim that the former is equivalent to the latter.
+ * emit-rtl.c (start_sequence): Expand comments.
+ (start_sequence_for_rtl_expr): Likewise.
+ (push_to_sequence): Likewise.
+ (end_sequence): Likewise.
+ * expr.c (inhibit_defer_pop): Likewise.
+ * expr.h (inhibit_defer_pop): Likewise.
+ (NO_DEFER_POP): Likewise.
+ (OK_DEFER_POP): Likewise.
-Sun Jul 5 23:58:19 1998 Jeffrey A Law (law@cygnus.com)
+Thu Apr 29 22:13:46 1999 Robert Lipe <robertlipe@usa.net>
- * cse.c (cse_insn): Second arg is an RTX now. Update all callers.
- (cse_basic_block): Keep track of the current RETVAL insn for a
- libcall instead of just noting that we're in a libcall.
+ * configure.in (i?86-UnixWare7*-sysv): Set thread_file to 'posix'
+ --enable-threads[={yes,pthreads,posix}] is passed as a command
+ line parameter to configure.
+ * config/i386/sysv5.h (LIB_SPEC): Add support for '-pthread'.
+ (CPP_SPEC): Likewise.
- * combine.c (simplify_comparison): Do not commute a AND into
- a paradoxical SUBREG if not WORD_REGISTER_OPERATIONS.
+Thu Apr 29 17:23:59 1999 Richard Henderson <rth@cygnus.com>
- * i386/freebsd-elf.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Protect with
- HAVE_GAS_MAX_SKIP_P2ALIGN.
- * i386/linux.h: Likewise.
-
-Fri Jul 3 02:33:35 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-
- * sparc.c (sparc_operand, move_operand, arith_operand,
- arith11_operand, arith10_operand, arith_double_operand,
- arith11_double_operand, arith10_double_operand, small_int,
- uns_small_int): Recognize CONSTANT_P_RTX.
- (output_sized_memop, output_move_with_extension,
- output_load_address, output_size_for_block_move,
- output_block_move, delay_operand): Remove, has not been
- enabled or referenced for years.
- * sparc.md (movstrsi, block_move_insn): Likewise.
- * sparc.h (PREDICATE_CODES): Define.
- * linux-aout.h (MACHINE_STATE_{SAVE,RESTORE}): Override with
- version which uses getcc/setcc traps to save/restore condition
- codes.
- * linux64.h: Likewise.
- * sunos4.h: Likewise.
- * linux.h: Likewise.
- * sol2.h: Likewise.
- * sun4o3.h: Likewise.
-
-Fri Jul 3 02:28:05 1998 Richard Henderson <rth@cygnus.com>
-
- * alpha.c (alpha_initialize_trampoline): Hack around Pmode/ptr_mode
- lossage on VMS. Reported by kkaempf@rmi.de.
- * alpha/vms.h (TRAMPOLINE_TEMPLATE): Add missing 0.
-
-Thu Jul 2 17:41:14 1998 Nick Clifton <nickc@cygnus.com>
-
- * config/m32r/m32r.h (MUST_PASS_IN_STACK): Override default
- version.
-
-Thu Jul 2 14:34:48 1998 David Edelsohn <edelsohn@mhpcc.edu>
-
- * expr.h (STACK_SIZE_MODE): New macro.
- * explow.c (allocate_dynamic_stack_space): Use it for
- mode of allocate_stack pattern increment operand.
- * tm.texi (STACK_SAVEAREA_MODE, STACK_SIZE_MODE): Document.
- * md.texi (stack_save_block, ...): Reflect use of macro.
-
- * rs6000.h (PROMOTE_MODE): Always promote to word_mode.
- (PROMOTE_FUNCTION_ARGS): Define.
- (PROMOTE_FUNCTION_RETURN): Define.
- (FUNCTION_VALUE): Promote to word_mode if smaller.
- Convert to gen_rtx_FOO.
- * rs6000.md (call_indirect): Store doubleword in 64-bit mode.
- Convert to gen_rtx_FOO.
- * rs6000.c: Convert to gen_rtx_FOO.
-
-Thu Jul 2 14:16:11 1998 Michael Meissner <meissner@cygnus.com>
+ * emit-rtl.c (operand_subword): Religiously mask and sign-extend
+ from 32-bits to HOST_WIDE_INT.
- * varray.{c,h}: New files to provide virtual array support.
+Thu Apr 29 15:58:52 1999 Robert Lipe <robertlipe@usa.net>
- * Makefile.in (OBJS): Add varray.o.
- (varray.o): Add new file.
- (REGS_H): New variable for dependencies for files including
- regs.h. Add varray.h and files it includes. Change all regs.h
- dependencies to $(REGS_H).
+ * fixinc/regex.c, fixinc/regex.h: Removed. Replace with...
+ * fixinc/gnu-regex.c, fixinc/gnu-regex.h: Imported from GDB 4.18.
+ * fixinc/Makefile.in (OBJ, HDR): Handle name changes from above.
+ (gnu-regex.o): Define REGEX_MALLOC to avoid memory leak.
+ * fixinc/fixincl.c: new regex.h header name
+ * Makefile.in: new regex.[ch] file names
- * toplev.c (x{m,re}alloc): If size is 0, allocate 1 byte.
- (xcalloc): Provide frontend for calloc.
- * {tree,rtl}.h (xcalloc): Add declaration.
+Thu Apr 29 12:53:33 1999 Richard Henderson <rth@cygnus.com>
- * basic-block.h (REG_BASIC_BLOCK): Convert reg_n_info to be a
- varray.
+ * calls.c (emit_call_1): Pass rounded_stack_size to emit_call
+ instead of the unrounded size.
- * regs.h (toplevel): Include varray.h.
- (reg_n_info): Switch to use a varray.
- (REG_*): Ditto.
- (allocate_reg_info): Change num_regs argument to be size_t.
+1999-04-28 14:40 Bruce Korb <ddsinc09@ix.netcom.com>
- * regclass.c (reg_info_data): New structure to remember groups of
- reg_info structures allocated that are to be zeroed.
- ({pref,alt}class_buffer): New statics to hold buffers
- allocate_reg_info allocates for {pref,alt}class_buffer.
- (regclass): Use {pref,alt}class_buffer to initialize
- {pref,alt}class.
- (allocate_reg_info): Switch to make reg_n_info use varrays.
- Allocate buffers for the preferred and alter register class
- information. Change num_regs argument to be size_t, not int.
+ * fixinc/mkfixinc.sh: Makesure the result shell script is writable
- * flow.c (reg_n_info): Switch to use varrays.
+Wed Apr 28 10:36:39 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Thu Jul 2 10:11:47 1998 Robert Lipe <robertl@dgii.com>
+ * config/m68k/m68k.md (cmpsi+1): Use cmp.w when comparing a 16 bit
+ constant with an address register.
- * install.texi (sco3.2v5): Document new --with-gnu-as flag.
- * config/i386/sco5.h (JUMP_TABLES_IN_TEXT_SECTION): Defined as
- in other targets.
- (USE_GAS): Conditionalize away native assembler usage.
- * config/i386/sco5gas.h: New file.
- * config/i386/t-sco5gas: New file.
- * configure.in (ix86-sco3.2v5*): Use new files if --with-gnu-as
+Wed Apr 28 00:14:41 PDT 1999 Jeff Law (law@cygnus.com)
-Thu Jul 2 08:20:00 1998 Catherine Moore <clm@cygnus.com>
+ * version.c: Bump for snapshot.
- * haifa-sched.c (alloc_EXPR_LIST): Change to use
- unused_expr_list.
+Tue Apr 27 19:50:25 EDT 1999 Andrew MacLeod <amacleod@cygnus.com>
+
+ * rtl.h (REG_EH_REGION): Update comment to indicate a value of -1
+ indicates no throw and no nonlocal gotos.
+ * optabs.c (emit_libcall_block): Emit REG_EH_REGION with a value
+ of -1 instead of 0 to indicate a nonlocal goto won't happen either.
+ * flow.c (count_basic_blocks, find_basic_blocks_1): Ignore libcall
+ blocks, look for REG_EH_REGION note exclusively.
+ (make_edges): Check for REG_EH_REGION > 0 for specified handlers.
-Thu Jul 2 14:13:28 1998 Dave Love <d.love@dl.ac.uk>
+Tue Apr 27 15:33:42 1999 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.h (read_only_data_section, private_data_section,
+ read_only_private_data_section, toc_section): Align CSECT on
+ doubleword boundary for 64-bit target.
+ (DATA_SECTION_ASM_OP): Likewise.
+ * rs6000.c (rs6000_stack_info): Leaf procedure stack limit is 288.
+
+Tue Apr 27 20:19:47 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * sh.md (insv): Use copy_addr_to_reg.
+
+ * final.c (insn_lengths_max_uid): New variable.
+ (init_insn_lengths, shorten_branches): Set it.
+ (get_attr_lengths): Test insn uid against insn_lengths_max_uid.
+
+1999-04-27 08:32 -0400 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * expr.c (emit_move_insn_1): Abort if MODE argument is invalid.
+ (compare): Punt if TREE_OPERAND (exp, 0) is an ERROR_MARK.
+
+Tue Apr 27 01:33:43 1999 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (ORDINARY_FLAGS_TO_PASS): Renmaed from FLAGS_TO_PASS.
+ Remove "CC".
+ (FLAGS_TO_PASS): New variable.
+
+Tue Apr 27 00:36:44 1999 Nick Burrett <nick.burrett@btinternet.com>
+
+ * arm.md (nop): Output instruction using output_asm_insn to fix
+ assembler dialect problems.
- * Makefile.in (install-info): Don't use $realfile. Ignore
- possible errors from the install-info program.
+Mon Apr 26 23:55:50 1999 Robert Lipe <robertlipe@usa.net>
-Thu Jul 2 01:53:32 1998 Alasdair Baird <alasdair@wildcat.demon.co.uk>
+ * Makefile.in (fixinc.sh): Fix dependencies.
- * combine.c (simplify_comparison): Apply SUBREG_REG to SUBREGs.
+ * fixinc/inclhack.def (avoid_bool): Enable match if typedefs are
+ prepended by spaces.
+ (sco5_stat_wrappers): New fix. Make sys/stat.h C++ safe.
+ * fixinc/fixincl.sh, fixinc/fixincl.x, fixinc/inclhack.sh: Rebuilt.
-Wed Jul 1 23:06:03 1998 Richard Henderson <rth@cygnus.com>
+Mon Apr 26 23:28:54 1999 Mumit Khan <khan@xraylith.wisc.edu>
+ Donn Terry <donn@interix.com>
- * i386.h (HARD_REGNO_MODE_OK): Kill spurrious test.
- (MODES_TIEABLE_P): Tie SImode and HImode.
+ * function.c (put_var_into_stack): Change ptr_mode to Pmode
+ in setup for chkr_set_right_libfunc calls.
+ (assign_params): Likewise.
+ * expr.c (emit_push_insn): Change ptr_mode to Pmode in
+ setup for chkr_copy_bitmap_libfunc and chkr_set_right_libfunc calls.
+ (expand_assignment): Change ptr_mode to Pmode in
+ setup for chkr_add_libfunc and chkr_copy_bitmap_libfunc.
+ (store_expr): Change ptr_mode to Pmode in
+ setup for chkr_add_libfunc and chkr_copy_bitmap_libfunc.
+ (expand_expr): Change ptr_mode to Pmode in
+ setup for chkr_check_addr_libfunc.
+ (expand_builtin): Change ptr_mode to Pmode in
+ setup for chkr_check_str_libfunc, chkr_copy_bitmap_libfunc and
+ chkr_check_addr_libfunc.
+ * calls.c (rtx_for_function_call): Change ptr_mode to Pmode in
+ setup for chkr_check_exec_libfunc.
+ (expand_call): Change ptr_mode to Pmode in
+ setup for chkr_set_right_libfunc.
+ (expand_call): Change ptr_mode to Pmode in
+ setup for chkr_set_right_libfunc.
+ (store_one_arg): Change ptr_mode to Pmode in
+ setup for chkr_set_right_libfunc.
-1998-07-01 Andreas Jaeger <aj@arthur.rhein-neckar.de>
+ * c-parse.in (absdcl1): Allow attributes in explicit typespecs.
+ (%expect): Update.
+ * c-parse.y: Regenerate.
+ * c-parse.c: Likewise.
+ * objc/objc-parse.c: Likewise.
+ * objc/objc-parse.y: Likewise.
- * invoke.texi (Optimize Options): Fix typo.
+Mon Apr 26 21:17:41 1999 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jul 1 22:25:43 1998 Jim Wilson <wilson@cygnus.com>
+ * c-pragma.c (push_alignment): Don't ignore alignments greater than
+ 4 bytes.
+ (handle_pragma_token): Likewise.
- * xcoffout.c (xcoffout_begin_function): Call xcoffout_block for
- the zero'th block.
+ * c-pragma.c: Support for #pragma pack (push, <id>, <n>).
+ (struct align_stack): Add id field.
+ (push_alignment, pop_alignment): Take id parameter.
+ (handle_pragma_token): Add necessary states.
+ * c-pragma.h (enum pragma_state): Add necessary states.
-Wed Jul 1 23:12:58 1998 Ken Raeburn <raeburn@cygnus.com>
+Tue Apr 27 13:58:23 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * h8300.c (print_operand): Delete %L support.
- * h8300.md (branch_true, branch_false): Use %= with a prefix
- instead of %L for local branch labels.
+ * config/c4x/c4x.md (*cmpqf, *cmpqf_noov, *cmpqi_test,
+ *cmpqi_test_noov): Remove ? modifier from constraints list.
+ (*smulqi3_highpart_clobber, *umulqi3_highpart_clobber): Swap
+ output strings to match new constraint ordering.
-Wed Jul 1 21:27:13 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+1999-04-26 19:16 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * reload1.c (emit_reload_insns): Use proper register classes for
- SECONDARY_INPUT_RELOAD_CLASS / SECONDARY_MEMORY_NEEDED code.
+ * cpphash.c (dump_definition): New function.
+ * cpphash.h: Prototype it.
-Wed Jul 1 21:17:36 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * cpplib.c (handle_directive): Don't output anything here.
+ Streamline.
+ (pass_thru_directive): Take a length, not a pointer to the
+ end. All callers changed.
+ (do_define): Handle -dD, -dN, -g3 entirely here. Streamline.
+ (do_include): Handle -dI here.
+ (do_ident): Correct to match cccp.
+ (do_pragma): Copy the pragma through here.
+ (do_assert, do_unassert): Tidy.
- * reload.c (find_reloads): If there are multiple
- RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_OUTPUT_ADDRESS reloads for
- one operand, change RELOAD_FOR_INPADDR_ADDRESS /
- RELOAD_FOR_OUTADDR_ADDRESS for all but the first
- RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_OUTPUT_ADDRESS reloads.
+ * cppinit.c (cpp_finish): If -dM was specified, walk the macro
+ hash table and call dump_definition on all the entries.
+ * cppmain.c: cpp_finish may produce output.
-Wed Jul 1 17:23:23 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Apr 26 15:27:33 1999 Mark Mitchell <mark@codesourcery.com>
- * regmove.c (fixup_match_2): Check that P has RTX_CLASS 'i' before
- using its PATTERN.
+ * toplev.c (compile_file): Move call to check_global_declarations
+ after output_exception_table to restore behavior as it was before
+ 1999-04-22 change.
-Wed Jul 1 05:04:41 1998 Richard Henderson <rth@cygnus.com>
+1999-04-26 10:50 -0700 Bruce Korb <ddsinc09@ix.netcom.com>
+
+ * fixinc/fixincl.c: Improve the handling of child process exits
+ * fixinc/server.[ch]: Export the interface for shutting down
+ the server process
+ * fixinc/inclhack.tpl: Remove unnecessary character quote
+ * fixinc/fixincl.sh, fixinc/inclhack.sh: Regenerate
+
+Mon Apr 26 10:41:42 EDT 1999 Andrew MacLeod <amacleod@cygnus.com>
+
+ * alpha.md (builtin_setjmp_receiver): Use a label_ref instead of
+ a code label.
+
+1999-04-26 09:47 -0400 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * rtl.texi: Document the rtl classes and their relation to
+ formats.
+
+Mon Apr 26 01:02:38 1999 Richard Henderson <rth@cygnus.com>
+
+ * alpha.md (fix_trunc patterns): Use reg_no_subreg_operand on op0
+ for less work in reload.
+ (movsf and movdf patterns): Put fp reg alternatives first.
+
+Mon Apr 26 01:55:56 1999 Marc Espie <espie@cvs.openbsd.org>
+
+ * configure.in (openbsd): Factorize xmake_file.
+ (ix86 openbsd): Trim obsolete comment.
+ (vax openbsd): Fix typo.
+ * configure: Rebuilt.
- * expr.c (emit_group_load, emit_group_store): Rewrite considering
- the size and alignment of the structure being manipulated.
- * expr.c, calls.c, function.c: Update all callers.
- * expr.h: Update prototypes.
- * cse.c (invalidate): Cope with parallels.
+Mon Apr 26 01:30:59 1999 Donn Terry <donn@interix.com>
-Wed Jul 1 04:22:23 1998 Richard Henderson <rth@cygnus.com>
+ * expr.c (expand_assignment): Improve test for pointer type.
- * sparc.c (function_arg_record_value): Take a MODE arg with which to
- create the PARALLEL. Update all callers.
+Mon Apr 26 00:26:18 1999 Richard Henderson <rth@cygnus.com>
-Wed Jul 1 04:10:35 1998 Richard Henderson <rth@cygnus.com>
+ * alpha.c (print_operand_address): Account for the subreg word.
- * expr.c (expand_assignment, store_constructor, expand_expr): Use
- convert_memory_address instead of convert_to_mode when possible.
+Mon Apr 26 01:08:36 1999 Toshiyasu Morita (tm@netcom.com)
-Wed Jul 1 03:48:00 1998 Richard Henderson <rth@cygnus.com>
+ * fold-const.c (make_range): Always initialize arg0 and arg1.
+ (fold): Similarly for alt0 and alt1.
+ * function.c (fixup_var_refs_insns): Initialize insn_list.
+ (instantiate_virtual_regs_1): Initialize offset.
+ * optabs.c (expand_binop): Initialize carry_in, carry_out, op0_xhigh
+ and op1_xhigh.
+ * stmt.c (expand_end_case): Initialize minval and maxval.
- * alpha.c (alpha_initialize_trampoline): Take arguments describing
- the layout. Use ptr_mode. Disable hint generation. Use gen_imb.
- * alpha.h (INITIALIZE_TRAMPOLINE): Pass extra args to the init func.
- (TRANSFER_FROM_TRAMPOLINE): Move ...
- * alpha/osf.h: ... here.
- * alpha/vms.h (INITIALIZE_TRAMPOLINE): Use alpha_initialize_trampoline.
- (TRANSFER_FROM_TRAMPOLINE): Remove undef.
- * alpha/win-nt.h: Likewise.
- * alpha/vxworks.h: Likewise.
+Mon Apr 26 01:02:34 1999 Nathan Sidwell <nathan@acm.org>
- * alpha/linux.h: Revert gcc2 merge lossage.
+ * toplev.c (report_error_function): Reorder file stack and
+ function name printing. Ignore FILE parameter.
-Wed Jul 1 10:56:55 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Mon Apr 26 00:58:54 1999 Jerry Quinn <jquinn@nortelnetworks.com>
- * c-decl.c (grokdeclarator): Don't warn about implicit int in
- `typedef foo = bar'.
+ * pa.h (architecture_type): New enum.
+ (pa_arch_string, pa_arch): Declare.
+ (MASK_PA_10, MASK_PA_20): New flags.
+ (TARGET_SWITCHES): Add pa-risc-2-0. Update docs for PA1.0 codegen.
+ (TARGET_OPTIONS): Add -march= option.
+ * pa.c (pa_arch, pa_arch_string): Define.
+ (override_options): Set them.
+ * pa/pa-hpux10.h (ASM_FILE_START): Output LEVEL 2.0 asm directive for
+ 2.0 architecture.
+ * invoke.texi (Option Summary, HPPA Options): Document new
+ architecture flags.
-Wed Jul 1 02:12:33 1998 Robert Lipe <robertl@dgii.com>
+ * pa/pa-hpux.h, pa/pa-hpux10.h, pa/pa-hpux9.h, pa/pa-osf.h, pa.h,
+ pa.c, pa.md, configure.in, configure: Replace TARGET_SNAKE by
+ TARGET_PA_11 and MASK_SNAKE by MASK_PA_11.
- * i386.c (asm_output_function_prefix): Make 686 function
- prologues not issue .types for non-global lables.
+Mon Apr 26 00:28:25 1999 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
-Tue Jun 30 23:46:53 1998 Dmitrij Tejblum <tejblum@arc.hq.cti.ru>
+ * flags.h (inline_max_insns): Declare.
+ * integrate.c (inline_max_insns): New variable.
+ (function_cannot_inline_p): Use it.
+ * toplev.c (main): Add the flag -finline-limit-n.
+ (display_help): Document -finline-limit-n.
+ * invoke.texi: Document -finline-limit-n
- * i386/freebsd.h (WCHAR_TYPE): Chagne to an "int".
- (WCHAR_TYPE_SIZE): Update appropriately.
+Sun Apr 25 23:03:32 1999 Richard Henderson <rth@cygnus.com>
-Tue Jun 30 23:16:39 1998 Jeffrey A Law (law@cygnus.com)
+ * stmt.c (expand_asm_operands): Reload in-out reg-only memory operands.
- * flow.c (recompute_reg_usage): Does not return a value.
- * rtl.h (recompute_reg_usage): Update prototype.
+Sun Apr 25 13:06:13 1999 Richard Henderson <rth@cygnus.com>
- * jump.c (jump_optimize): Show that the jump chain is not
- valid when not optimizing.
+ * function.c (assign_parms/STACK_BYTES): Revert last change,
+ and that of 19 Nov.
-Tue Jun 30 16:01:01 1998 Richard Henderson <rth@cygnus.com>
+Sun Apr 25 12:30:50 1999 Richard Henderson <rth@cygnus.com>
- * rtl.def (CONSTANT_P_RTX): New.
- * rtl.h (CONSTANT_P): Recognize it.
- * cse.c (fold_rtx): Eliminate it.
- * expr.c (can_handle_constant_p): New variable.
- (init_expr_once): Initialize it.
- (expand_builtin): Generate CONSTANT_P_RTX if the expression is not
- immediately recognizable as a constant.
+ * calls.c (emit_call_1): New arg rounded_stack_size; update callers.
+ Update pending_stack_adjust based on this value.
+ (compute_argument_block_size): Include pending_stack_adjust in
+ PREFERRED_STACK_BOUNDARY alignment.
+ * function.c (assign_parms): Don't round to PREFERRED_STACK_BOUNDARY.
- * alpha.c (reg_or_6bit_operand): Recognize CONSTANT_P_RTX.
- (reg_or_8bit_operand, cint8_operand, add_operand): Likewise.
- (sext_add_operand, and_operand, or_operand): Likewise.
- (reg_or_cint_operand, some_operand, input_operand): Likewise.
- * alpha.h (PREDICATE_CODES): Add CONSTANT_P_RTX where needed.
+Sun Apr 25 14:38:10 EDT 1999 John Wehle (john@feith.com)
-1998-06-30 Benjamin Kosnik <bkoz@bliss.nabi.net>
+ * stupid.c (stupid_mark_refs): Generate a REG_UNUSED note
+ for a register which is clobbered even if the register
+ was used by an earlier instruction.
- * dbxout.c (dbxout_type_methods): Remove warn_template_debugging.
+ * i386.md (fix_truncsfdi2, fix_truncdfdi2,
+ fix_truncxfdi2): Don't bother with the gen_reg_RTX.
+ (fix_truncsfsi2, fix_truncsfdi2, fix_truncdfsi2,
+ fix_truncdfdi2, fix_truncxfsi2, fix_truncxfdi2): Update
+ operand constraints and modes.
+ * i386.c (output_fix_trunc): Use HImode register to avoid
+ memory stalls. Call output_move_double instead of output_to_reg.
+ (output_to_reg): Remove.
+ * i386.h: Likewise.
-Tue Jun 30 14:03:34 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * i386.md (negsf2, negdf2, negxf2): Set the type
+ attribute to fpop.
- * aclocal.m4 (GCC_NEED_DECLARATION): Accept an optional second
- argument, which is typically preprocessor code used to draw in
- additional header files when looking for a function declaration.
- (GCC_NEED_DECLARATIONS): Likewise.
+Sat Apr 24 23:15:57 1999 Donn Terry (donn@interix.com)
- * configure.in (GCC_NEED_DECLARATIONS): Add checks for getrlimit
- and setrlimit, search for them in sys/resource.h.
+ * alpha.md (call_value_nt): Correct subscripts.
- * acconfig.h: Add stubs for NEED_DECLARATION_GETRLIMIT and
- NEED_DECLARATION_SETRLIMIT.
+Sat Apr 24 20:49:20 1999 Richard Henderson <rth@cygnus.com>
- * system.h: Prototype getrlimit/setrlimit if necessary.
+ * alpha.h (PRINT_OPERAND_ADDRESS): Break out to ...
+ * alpha.c (print_operand_address): here. Handle subregs.
-Tue Jun 30 10:54:48 1998 Mark Mitchell <mark@markmitchell.com>
+Fri Apr 23 22:35:41 EDT 1999 John Wehle (john@feith.com)
- * rtl.texi: Don't say that RTX_INTEGRATED_P is not depended
- upon.
+ * acconfig.h (HAVE_GAS_FILDS_FISTS): Add.
+ * configure.in: Check assembler instructions.
+ * configure: Rebuild.
+ * config.in: Likewise.
+ * i386.md (floathisf2, floathidf2, floathixf2): New patterns.
+ * i386.c (print_operand): Use the proper suffix for a 387 HImode
+ operand. Abort if a 387 operand has an unsupported size.
-Tue Jun 30 13:11:42 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+Fri Apr 23 16:57:40 1999 Richard Henderson <rth@cygnus.com>
- * rs6000/sysv4.h (asm output): add tabs for asm directives.
+ * alpha.c (alpha_write_verstamp): Mark `file' unused.
+ * alpha.h (FUNCTION_VALUE): Use gen_rtx_REG not gen_rtx.
+ (LIBCALL_VALUE): Likewise.
+ (GO_IF_LEGITIMATE_SIMPLE_ADDRESS): Handle normal subregs.
-Tue Jun 30 13:11:42 1998 David Edelsohn <edelsohn@mhpcc.edu>
+Fri Apr 23 14:57:33 1999 Donn Terry <donn@interix.com>
- * Makefile.in (FLAGS_TO_PASS): Set AR_FLAGS to AR_FOR_TARGET_FLAGS.
+ * alpha32.h (INITIALIZE_TRAMPOLINE): Get offsets right.
-Tue Jun 30 08:59:15 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * alpha.c (alpha_initialize_trampoline): Add covert_memory_address
+ calls as needed.
- * gansidecl.h (ATTRIBUTE_UNUSED): Use __unused__ not `unused'.
- Don't define NULL here. Also, remove all vestiges of autoconf
- based checks for bcmp/bcopy/bzero/index/rindex.
+Fri Apr 23 14:36:47 1999 Richard Henderson <rth@cygnus.com>
- * system.h: Immediately after including stdio.h, check for and if
- necessary provide a default definition of NULL.
+ * alpha.c (alpha_expand_prologue): Don't negate frame size
+ for use with subq.
-Tue Jun 30 08:22:05 1998 Michael Meissner <meissner@cygnus.com>
+Fri Apr 23 09:43:18 1999 Nick Clifton <nickc@cygnus.com>
- * reload1.c (reload_cse_simplify_operands): Call
- fatal_insn_not_found, not abort.
+ * print-rtl.c (print_rtx): Display LABEL_NUSES for labels.
-Tue Jun 30 02:34:02 1998 Jeffrey A Law (law@cygnus.com)
+Thu Apr 22 23:08:37 1999 Mark Mitchell <mark@codesourcery.com>
- * choose-temp.c (make_temp_file): Accept new argument for the
- file suffix to use. Allocate space for it and add it to the
- template.
- * mkstemp.c (mkstemps): Renamed from mkstemp. Accept new argument
- for the length of the suffix. Update template struture checks
- to handle optinal suffix.
- * collect2.c (make_temp_file): Update prototype.
- (main): Put proper suffixes on temporary files.
- * gcc.c (make_temp_file): Update prototype.
- (do_spec_1): Put proper suffixes on temporary files.
+ * toplev.h (wrapup_global_declarations): Declare.
+ (check_global_declarations): Likewise.
+ * toplev.c (wrapup_global_declarations): New function, split out
+ from ...
+ (check_global_declarations): Likewise...
+ (compile_file): Here.
-Tue Jun 30 00:56:19 1998 Bruno Haible <haible@ilog.fr>
+Thu Apr 22 22:34:41 1999 Richard Henderson <rth@cygnus.com>
- * invoke.texi: Document new implicit structure initialization
- warning.
+ * c-parse.in (expr_no_commas): Verify we've an expr before
+ calling C_SET_EXP_ORIGINAL_CODE.
-Mon Jun 29 22:12:06 1998 Jeffrey A Law (law@cygnus.com)
+Thu Apr 22 22:22:15 EDT 1999 John Wehle (john@feith.com)
- * Merge from gcc2 June 9, 1998 snapshot. See ChangeLog.13 for
- details.
+ * toplev.c (rest_of_compilation): Always set
+ current_function_uses_only_leaf_regs appropriately.
- * pa.c, pa.h, pa.md: Convert to gen_rtx_FOO.
+Thu Apr 22 14:39:43 1999 Mumit Khan <khan@xraylith.wisc.edu>
-Mon Jun 29 20:12:41 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * i386/xm-cygwin.h (HAVE_BCOPY): Delete unneeded macro.
+ (HAVE_BZERO): Likewise.
+ (HAVE_BCMP): Likewise.
+ (HAVE_RINDEX): Likewise.
+ (HAVE_INDEX): Likewise.
+ (DIR_SEPARATOR_2): Define.
+ (GET_ENV_PATH_LIST): Turn path lists into POSIX.
+ (PATH_SEPARATOR): Use ':'.
- * Makefile.in (fix-header): Don't needlessly depend on cpperror.o.
+1999-04-22 Bruce Korb <ddsinc09@ix.netcom.com>
- * alias.c (CHECK_ALIAS_SETS_FOR_CONSISTENCY): Cast expansion to
- void since it is evaluated in a comma list.
+ * configure.in: enable disabling of fast fixincludes
+ * configure: regenerate
- * mips.h (ASM_GENERATE_INTERNAL_LABEL): Always sprintf `NUM'
- argument as a long and cast `NUM' to long to ensure it is of the
- proper width. Wrap macro arguments in parens when they appear in
- the expansion.
+1999-04-21 14:55 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * sol2.h (ASM_GENERATE_INTERNAL_LABEL): Likewise.
+ * gen-protos.c: #undef abort after including system.h.
+ Delete defns of fancy_abort and fatal.
+ * fix-header.c: Delete defn of fancy_abort.
- * sparc.h (ASM_GENERATE_INTERNAL_LABEL): Likewise.
- (ASM_DECLARE_RESULT): Fix fprintf format specifier to match
- function argument return type.
- (REGNO_OK_FOR_INDEX_P, REGNO_OK_FOR_BASE_P, REGNO_OK_FOR_FP_P,
- REGNO_OK_FOR_CCFP_P): Use `(unsigned)' not `U'.
+Wed Apr 21 12:09:38 1999 Mumit Khan <khan@xraylith.wisc.edu>
- * cpplib.c (cpp_message_from_errno): Remove unneeded argument to
- cpp_message.
+ * cccp.c (simplify_filename): Always preserve leading double slash.
- * dbxout.c: Fix the comments after an #endif to reflect the actual
- condition tested in the preceding #if.
+Wed Apr 21 18:15:55 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * except.c (find_all_handler_type_matches): Switch to old-style
- function definition.
+ * config/c4x/c4x.md: Add new peepholes to remove redundant loads.
- * expr.c (expand_builtin): Remove unused variable `type' twice.
+Wed Apr 21 17:41:29 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * gbl-ctors.h (DO_GLOBAL_CTORS_BODY): Cast -1 before comparing it
- to an unsigned long.
+ * config/c4x/c4x.md (binary patterns): Reorder alternatives
+ so that two operand instructions are chosen before three operand
+ instructions.
- * haifa-sched.c (print_insn_chain): Remove unused function.
+Tue Apr 20 23:38:58 1999 Nathan Sidwell <nathan@acm.org>
- * objc/objc-act.c (build_msg_pool_reference): Hide prototype and
- definition.
+ * objc/Make-lang.in (objc-parse.c): Put BISON parameters in correct
+ order.
- * toplev.c: When testing whether to include dbxout.h, also include
- it when XCOFF_DEBUGGING_INFO is defined.
+ * Makefile.in (c-parse.c): Put BISON parameters in correct
+ order.
- * unroll.c (unroll_loop): Add parentheses around assignment used
- as truth value.
+Tue Apr 20 16:38:11 1999 Richard Henderson <rth@cygnus.com>
-Mon Jun 29 12:18:00 1998 Catherine Moore <clm@cygnus.com>
+ * alpha.md (nt_lda): New pattern.
+ * alpha.c (alpha_expand_prologue): Use it for large frames
+ under windows nt.
- * config/lb1spc.asm (.div, .udiv): Replace routines.
+Tue Apr 20 17:57:14 1999 Catherine Moore <clm@cygnus.com>
-Mon Jun 29 09:44:24 1998 Mark Mitchell <mark@markmitchell.com>
+ * config/arm/arm.md (movhi): Add check for odd offset.
- * rtl.h: Update comment about special gen_rtx variants.
- * emit-rtl.c (gen_rtx): Handle MEMs using gen_rtx_MEM.
+Tue Apr 20 13:14:58 EDT 1999 John Wehle (john@feith.com)
-Sun Jun 28 20:58:51 1998 Jeffrey A Law (law@cygnus.com)
+ * i386.c (output_move_double): Abort if a non-offsettable
+ memory operand is encountered. Delete unused code.
+ (find_addr_reg): Remove.
- * choose-temp.c (choose_temp_base): Restore original variant of
- this function for compatibility.
- (make_temp_file): This is the new, preferred interface to create
- temporary files.
- * collect2.c (choose_temp_base): Delete declaration.
- (make_temp_file): Declare.
- (temp_filename_length, temp_filename): Delete.
- (main): Use make_temp_file to get temporary files. Use --lang-c
- to force the resulting ctort/dtor file to be compiled with the C
- compiler. Make sure to remove temporary files on all exit paths.
- * gcc.c (make_temp_file): Provide prototype if MKTEMP_EACH_FILE is
- defined.
- (choose_temp_base): Only provide prototype if MKTEMP_EACH_FILE is
- not defined.
- (do_spec): Use make_temp_file if MKTEMP_EACH_FILE is defined.
+Mon Apr 19 21:13:02 1999 Craig Burley <craig@jcb-sc.com>
-Sun Jun 28 08:57:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * tree.def (BLOCK): Fix typo in comment.
- * configure.in (GCC_NEED_DECLARATIONS): Add strerror, getcwd and
- getwd.
+1999-04-19 14:51 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * acconfig.m4: Add stubs for NEED_DECLARATION_STRERROR,
- NEED_DECLARATION_GETCWD and NEED_DECLARATION_GETWD.
+ * cpplib.c (output_line_command): Drop CONDITIONAL argument.
+ We can omit unnecessary line commands if file_change ==
+ same_file and pfile->lineno != 0. All callers changed.
+ (cpp_get_token [case '\n']): Don't bump pfile->lineno if
+ CPP_OPTIONS (pfile)->no_line_commands is set.
+ * cpplib.h: Fix prototype of output_line_command.
- * cccp.c: Remove strerror()/sys_nerr/sys_errlist decls.
- (my_strerror): Add prototype and make it static.
+1999-04-18 17:46 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * collect2.c: Likewise.
+ * cppfiles.c (find_position, read_and_prescan): Use `unsigned
+ long' variables consistently to count line and column numbers.
- * cpplib.c: Likewise.
+Sun Apr 18 15:50:33 EDT 1999 John Wehle (john@feith.com)
- * gcc.c: Likewise, but keep `my_strerror' extern.
+ * output.h (current_function_is_leaf,
+ current_function_uses_only_leaf_regs): Declare.
+ * function.c (current_function_is_leaf,
+ current_function_uses_only_leaf_regs): Define.
+ (init_function_start): Initialize current_function_is_leaf
+ and current_function_uses_only_leaf_regs.
+ * final.c (leaf_function): Don't define.
+ (final_start_function): Replace uses of leaf_function with
+ current_function_uses_only_leaf_regs.
+ * toplev.c (rest_of_compilation): Set current_function_is_leaf
+ prior to invoking local register allocation.
+ (rest_of_compilation): Replace uses of leaf_function with
+ current_function_uses_only_leaf_regs.
+ * dbxout.c (dbxout_symbol, dbxout_parms): Likewise.
+ * dwarf2out.c (add_location_or_const_vaule_attribute): Likewise.
+ * dwarfout.c (add_location_or_const_value_attribute): Likewise.
+ * sdbout.c (sdbout_symbol): Likewise.
+ * sparc.h (FUNCTION_PROLOGUE, FUNCTION_EPILOGUE): Likewise.
+ * sparc.c (eligible_for_epilogue_delay, output_return,
+ sparc_return_peephole_ok): Likewise.
+ * sparc.md (leaf_function attribute, untyped_return): Likewise.
+ * i386.c (ix86_compute_frame_size): Don't align the stack
+ for leaf functions which don't allocate any stack slots.
+ * tm.texi: Update documentation.
- * protoize.c: Likewise.
+Sun Apr 18 02:15:09 PDT 1999 Jeff Law (law@cygnus.com)
- * pexecute.c (my_strerror): Add argument to prototype.
+ * version.c: Bump for snapshot.
- * system.h: Add prototypes for getcwd, getwd and strerror. Add
- extern decls for sys_nerr and sys_errlist. Make abort decl
- explicitly extern.
+Sun Apr 18 00:08:45 1999 Richard Henderson <rth@cygnus.com>
- * getpwd.c: Remove decls for getwd and getcwd.
+ * alpha.h (GO_IF_LEGITIMATE_SIMPLE_ADDRESS): Correct last change --
+ make sure FP_BASE_P registers are only used with an integer.
-Sun Jun 28 02:11:16 PDT 1998 Jeff Law (law@cygnus.com)
+Sat Apr 17 22:54:17 1999 Richard Henderson <rth@cygnus.com>
- * version.c: Bump for snapshot.
+ * alpha.h (REG_OK_FP_BASE_P): New macro.
+ (GO_IF_LEGITIMATE_SIMPLE_ADDRESS): Use it.
+ * alpha.md (adddi3+1): New insn to handle large constants off
+ the soft frame pointer.
+ (adddi3+2): Don't split soft frame pointer or arg pointer additions.
-Sat Jun 27 23:32:25 1998 Richard Henderson <rth@cygnus.com>
-
- * jump.c (jump_optimize): Use side_effects_p & may_trap_p instead
- of rtx_unsafe_p. Use modified_between_p instead of reg_set_between_p.
- Allow FP moves to be optimized.
- (rtx_unsafe_p): Delete.
-
-Sat Jun 27 23:02:04 1998 Richard Henderson <rth@cygnus.com>
-
- * objc/archive.c: Remove <string.h> prototypes.
-
-Sat Jun 27 22:37:05 1998 Jeffrey A Law (law@cygnus.com)
-
- * tm.texi (NEED_MATH_LIBRARY): Document new target macro.
-
- * Makefile.in (gencheck): Remove $(TREE_H) dependency.
-
-Sat Jun 27 20:20:00 1998 John Carr <jfc@mit.edu>
-
- * dsp16xx.h (FIRST_PSEUDO_REGISTER): Add parentheses to definition.
- * dsp16xx.c (next_cc_user_unsigned): New function.
- Remove save_next_cc_user_code.
- (print_operand): Use HOST_WIDE_INT_PRINT_* macros.
- * dsp16xx.md: Call next_cc_user_unsigned instead of using
- save_next_cc_user_code.
- Use gen_rtx_* functions instead of gen_rtx.
-
-Sat Jun 27 20:18:34 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
-
- * rs6000.h: Add trap_comparison_operator to PREDICATE_CODES.
-
-Sat Jun 27 16:45:42 1998 Jeffrey A Law (law@cygnus.com)
-
- * flow.c (count_reg_sets): New function.
- (count_reg_sets_1, count_ref_references): Likewise.
- (recompute_reg_usage): Likewise.
- * rtl.h (recompute_reg_usage): Add prototype.
- * toplev.c (rest_of_compilation): Call recompute_reg_usage just
- before local register allocation.
-
-Sat Jun 27 13:15:30 1998 Richard Henderson <rth@cygnus.com>
-
- * alpha.md (negsf, negdf): Revert Jan 22 change.
-
-Sat Jun 27 07:35:21 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * mkstemp.c: Include gansidecl.h. Rename uint64_t to gcc_uint64_t.
- (mkstemp): Remove size specifier for variable `letters'. Call
- gettimeofday, not __gettimeofday.
-
- * Makefile.in (EXPR_H): New dependency variable.
- (c-typeck.o): Depend on $(EXPR_H) instead of expr.h.
- (c-iterate.o): Likewise.
- (gencheck): Depend on $(TREE_H) instead of tree.h, etc.
- (stor-layout.o): Depend on $(EXPR_H) instead of expr.h.
- (toplev.o): Likewise. Also depend on $(RECOG_H) instead of recog.h.
- (varasm.o): Depend on $(EXPR_H) instead of expr.h.
- (function.o): Likewise.
- (stmt.o): Likewise.
- (except.o): Likewise.
- (expr.o): Likewise.
- (calls.o): Likewise.
- (expmed.o): Likewise.
- (explow.o): Likewise.
- (optabs.o): Likewise.
- (sdbout.o): Likewise.
- (dwarf2out.o): Likewise.
- (emit-rtl.o): Likewise.
- (integrate.o): Likewise.
- (jump.o): Likewise.
- (cse.o): Likewise.
- (gcse.o): Likewise. Also depend on $(BASIC_BLOCK_H) instead of
- basic-block.h.
- (loop.o): Depend on $(EXPR_H) instead of expr.h.
- (unroll.o): Likewise.
- (combine.o): Likewise.
- (reload.o): Likewise.
- (reload1.o): Likewise.
- (caller-save.o): Likewise.
- (reorg.o): Likewise.
- (alias.o): Don't depend on insn-codes.h.
- (regmove.o): Depend on $(RECOG_H)/$(EXPR_H) instead of recog.h/expr.h.
- (insn-emit.o): Depend on $(EXPR_H) instead of expr.h.
- (insn-opinit.o): Likewise.
-
-Sat Jun 27 01:35:14 1998 Jeffrey A Law (law@cygnus.com)
-
- * choose-temp.c (choose_temp_base): Remove MPW bits. Use mkstemp
- instead of mktemp.
- * gcc.c (MKTEMP_EACH_FILE): Define.
- (main): No need to call choose_temp_base if we are going to
- use choose_temp_base to create each file later.
- * mkstemp.c: New file. Adapted from glibc.
- * Makefile.in (xgcc, colect2, protoize, unprotoize): Link in mkstemp.o
- (mkstemp.o): Add dependencies.
-
- * configure.in (gettimeofday): Check for its existance.
- * config.in (HAVE_GETTIMEOFDAY): Define.
- * configure: Rebuilt.
+Sun Apr 18 17:24:10 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-1998-06-26 Michael Meissner <meissner@cygnus.com>
+ * config/c4x/c4x.c (legitimize_operands): Use rtx_cost
+ to determine if it is worthwhile forcing a constant into a register.
+ * config/c4x/c4x.h (CONST_COSTS): An integer value of 255 or 65535
+ used with a logical and or an integer value of 16 or 24 used with
+ a right shift has zero cost on the C40.
- * rs6000.md (ne 0, non power case): Add missing & constraint.
- Name pattern ne0.
- (negative abs insns): Add pattern names.
+Sat Apr 17 21:30:11 1999 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
-Fri Jun 26 17:36:42 1998 Dave Love <d.love@dl.ac.uk>
+ * gcse.c (compute_local_properties): If setp is nonzero, clear
+ TRANSP instead of setting it to all ones.
- * Makefile.in (install-info): Run install-info program in separate
- loop.
+Sat Apr 17 21:10:10 1999 Jan Hubicka <hubicka@freesoft.cz>
-Fri Jun 26 16:03:15 1998 Michael Meissner <meissner@cygnus.com>
+ * i386.c (i386_preferred_stack_boundary_string): New global variable.
+ (i386_preferred_stack_boundary): New global variable.
+ (override_functions): Set it. Tidy option setting code.
+ * i386.h (TARGET_OPTIONS): New command line option.
+ (i386_preferred_stack_boundary_string): Declare it.
+ (i386_preferred_stack_boundary): Likewise.
+ (PREFERRED_STACK_BOUNDARY): Use i386_preferred_stack_boundary.
- * haifa-sched.c (schedule_block): Add hooks for the machine
- description to reorder the ready list, and update how many more
- instructions can be issued this cycle.
- * tm.texi (MD_SCHED_{INIT,REORDER,VARIABLE_ISSUE}): Document.
-
-Fri Jun 26 11:54:11 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-
- * config/sparc/sparc.h (REGNO_OK_FOR_{INDEX,BASE,FP,CCFP}_P):
- Explicitly mark the constant being compared against as unsigned.
- * config/sparc/sparc.c (sparc_select, cpu_default, cpu_table):
- Fully initialize final members.
- (mem_aligned_8): Explicit init of offset to zero.
- (output_function_prologue): Explicit init of n_regs to zero.
- (output_function_epilogue): Likewise, and mark arg size as
- unused.
- (init_cumulative_args): Mark libname and indirect as unused.
- (function_arg_pass_by_reference): Likewise for cum and named.
- (sparc_builtin_saveregs): Likewise for arglist.
- (sparc_flat_eligible_for_epilogue_delay): Likewise for slot.
-
-Fri Jun 26 06:58:54 1998 Richard Earnshaw (rearnsha@arm.com)
-
- * arm.h (SECONDARY_INPUT_RELOAD_CLASS): Only need a secondary reload
- if reloading a MEM.
-
- * arm.h (arm_adjust_cost): Renamed bogus prototype from
- arm_adjust_code.
- (bad_signed_byte_operand): Add prototype.
- * arm.c (arm_override_options): Make I unsigned.
- (const_ok_for_arm): Add casts to the constants.
- (load_multiple_operation): Don't redeclare elt in sub-block.
- (arm_gen_movstrqi): Delete external declaration of optimize.
- (gen_compare_reg): Declare parameter fp.
-
- * arm.c (final_prescan_insn): Only initialize scanbody if the insn
- has a pattern.
-
-Fri Jun 26 09:31:24 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * alpha.c: Include system.h and toplev.h.
- (cint8_operand): Mark parameter `mode' with ATTRIBUTE_UNUSED.
- (const48_operand): Likewise.
- (mode_width_operand): Likewise.
- (mode_mask_operand): Likewise.
- (mul8_operand): Likewise.
- (current_file_function_operand): Likewise.
- (signed_comparison_operator): Likewise.
- (divmod_operator): Likewise.
- (any_memory_operand): Likewise.
- (alpha_return_addr): Likewise for parameter `frame'.
- (alpha_builtin_saveregs): Likewise for parameter `arglist'.
- (vms_valid_decl_attribute_p): Likewise for parameters `decl' and
- `attributes'.
- (alpha_start_function): Likewise for parameter `decl'. Use
- HOST_WIDE_INT_PRINT_DEC in call to fprintf. Fix various format
- specifiers. Remove unused variables `lab' and `name'.
- (alpha_end_function): Mark parameter `decl' with ATTRIBUTE_UNUSED.
- (check_float_value): Likewise for parameter `overflow'.
- (alpha_need_linkage): Likewise for parameters `name' and `is_local'.
-
- * alpha.h (ASM_IDENTIFY_GCC, ASM_IDENTIFY_LANGUAGE): Define as
- taking an argument.
- (ASM_OUTPUT_SHORT): Cast argument to `int' in call to fprintf.
- (ASM_OUTPUT_CHAR): Likewise.
- (ASM_OUTPUT_BYTE): Likewise.
- (PRINT_OPERAND_ADDRESS): Use HOST_WIDE_INT_PRINT_DEC in call to
- fprintf.
- (PUT_SDB_EPILOGUE_END): Mention argument `NAME' in definition.
- Add prototypes for functions in alpha.c.
-
- * alpha.md (ashldi3): Add default case in switch.
-
-1998-06-26 Manfred Hollstein <manfred@s-direktnet.de>
-
- * Makefile.in (gcc_version, gcc_version_trigger): New macros.
- (version): Initialize from $(gcc_version).
-
- * configure.in (version): Rename to gcc_version.
- (gcc_version_trigger): New variable; call AC_SUBST for it and
- emit it into the generated config.status.
- * configure: Regenerate.
+Sat Apr 17 19:22:38 1999 Jan Hubicka <hubicka@freesoft.cz>
-Thu Jun 25 12:47:41 1998 Mark Mitchell <mark@markmitchell.com>
+ * i386.c (k6_cost): Take into account the decoding time.
- * fold-const.c (make_range): Don't go looking at TREE_OPERANDs of
- nodes that are not expressions.
+Sat Apr 17 19:13:22 1999 Donn Terry <donn@interix.com>
-Thu Jun 25 15:08:16 1998 Mark Mitchell <mark@markmitchell.com>
+ * i386.h (PRINT_OPERAND_PUNCT_VALID_P): Allow _.
+ * i386.c (print_operand): New %_ operator.
+ (load_pic_register): Proper number of leading _ in GOT literal.
+ * i386.md (prologue_get_pc_and_set_got): Likewise.
+ * i386/unix.h (ASM_OUTPUT_MI_THUNK): Likewise.
- * invoke.texi (-fstrict-aliasing): Document.
- * rtl.texi (MEM_ALIAS_SET): Document.
+Sat Apr 17 19:13:07 1999 Richard Henderson <rth@cygnus.com>
- * flags.h (flag_strict_aliasing): Declare.
- * toplev.c (flag_strict_aliasing): Define.
- (f_options): Add -strict-aliasing.
- (main): Set flag_strict_aliasing if -O2 or higher.
+ * alpha.c (alpha_expand_prologue): Use gen_adddi3 instead of
+ emit_move_insn+plus_constant. For NT, don't use the stack probe
+ loop pointer to allocate stack space.
+ * alpha.md (adddi3): Always use lda to set the stack pointer.
- * tree.h (tree_type): Add alias_set field.
- (TYPE_ALIAS_SET): New macro.
- (TYPE_ALIAS_SET_KNOWN_P): Likewise.
- (get_alias_set): Declare.
- * tree.c (lang_get_alias_set): Define.
- (make_node): Initialize TYPE_ALIAS_SET.
- (get_alias_set): New function.
- * print-tree.c (print_node): Dump the alias set for a type.
+1999-04-17 20:11 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * c-tree.h (c_get_alias_set): Declare.
- * c-common.c (c_get_alias_set): New function.
- * c-decl.c (init_decl_processing): Set lang_get_alias_set.
+ * c-aux-info.c, emit-rtl.c, explow.c, expmed.c, gcse.c,
+ haifa-sched.c, optabs.c, reorg.c, resource.c, sched.c: Include
+ toplev.h for real declaration of trim_filename.
+ * Makefile.in: Update dependencies.
- * expr.c (protect_from_queue): Propogage alias sets.
- (expand_assignment): Calculate alias set for new MEMs.
- (expand_expr): Likewise.
- * function.c (put_var_into_stack): Likewise.
- (put_reg_into_stack): Likewise.
- (gen_mem_addressof): Likewise.
- (assign_parms): Likewise.
- * stmt.c (expand_decl): Likewise.
- * varasm.c (make_decl_rtl): Eliminate redundant clearing of
- DECL_RTL. Calculate alias set for new MEMs.
-
- * rtl.def (REG): Add dummy operand.
- (MEM): Add extra operand to store the MEM_ALIAS_SET.
- * rtl.h (MEM_ALIAS_SET): New macro.
- (gen_rtx_MEM): Declare.
- * emit-rtl.c (gen_rtx_MEM): New function.
- * gengenrtl.c (sepcial_rtx): Make MEMs special.
-
- * alias.c (CHECK_ALIAS_SETS_FOR_CONSISTENCY): New macro.
- (DIFFERENT_ALIAS_SETS_P): Likewise.
- (canon_rtx): Propogate the alias set to the new MEM.
- (true_dependence): Check the alias sets.
- (anti_dependence): Likewise.
- (output_dependence): Likewise.
- * explow.c (stabilize): Progoate alias sets.
- * integrate.c (copy_rtx_and_substitute): Likewise.
- * final.c (alter_subreg): Make sure not to leave MEM_IN_STRUCT_P
- in an unpredictable state. Propogate alias sets.
- * reload1.c (reload): Clear MEM_ALIAS_SET for new MEMs about which
- we have no alias information.
-
-Thu Jun 25 16:59:18 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
-
- * except.h (CATCH_ALL_TYPE): Definition moved to eh-common.h.
- (find_all_handler_type_matches): Add function prototype.
- * eh-common.h (CATCH_ALL_TYPE): Definition added.
- * except.c (find_all_handler_type_matches): Add function to find all
- runtime type info in the exception table.
- (output_exception_table_entry): Special case for CATCH_ALL_TYPE.
-
-Thu Jun 25 15:47:55 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * Makefile.in (xcoffout.o): Depend on toplev.h, output.h and dbxout.h.
-
- * config/fp-bit.c (_fpmul_parts): Move variables `x', `ylow',
- `yhigh' and `bit' into the scope in which they are used.
- (_fpdiv_parts): Remove unused variables `low', `high', `r0', `r1',
- `y0', `y1', `q', `remainder', `carry', `d0' and `d1'.
-
- * rs6000.c: Move include of output.h below tree.h. Include toplev.h.
- (any_operand): Mark unused parameters `op' and `mode' with
- ATTRIBUTE_UNUSED.
- (count_register_operand): Likewise for parameter `mode'.
- (fpmem_operand): Likewise.
- (short_cint_operand): Likewise.
- (u_short_cint_operand): Likewise.
- (non_short_cint_operand): Likewise.
- (got_operand): Likewise.
- (got_no_const_operand): Likewise.
- (non_add_cint_operand): Likewise.
- (non_logical_cint_operand): Likewise.
- (mask_operand): Likewise.
- (current_file_function_operand): Likewise.
- (small_data_operand): Likewise for parameters `op' and `mode' but
- only when !TARGET_ELF.
- (init_cumulative_args): Mark parameters `libname' with
- ATTRIBUTE_UNUSED.
- (function_arg_pass_by_reference): Likewise for parameters `cum',
- `mode' and `named'.
- (expand_builtin_saveregs): Likewise for parameter `args'.
- (load_multiple_operation): Likewise for parameter `mode'.
- (store_multiple_operation): Likewise.
- (branch_comparison_operator): Likewise.
- (secondary_reload_class): Likewise.
- (print_operand): Add parentheses around & operation.
- (output_prolog): Mark parameter `size' with ATTRIBUTE_UNUSED.
- (output_epilog): Likewise. Cast argument to fprintf to int.
- (rs6000_adjust_cost): Mark parameter `dep_insn' with ATTRIBUTE_UNUSED.
- (rs6000_valid_decl_attribute_p): Likewise for parameters `decl',
- `attributes', `identifier' and `args'.
- (rs6000_valid_type_attribute_p): Likewise for parameter `attributes'.
- (rs6000_comp_type_attributes): Likewise for parameters `type1' and
- `type2'.
- (rs6000_set_default_type_attributes): Likewise for parameter `type'.
-
- * rs6000.h (RTX_COSTS): Add parentheses around & operation.
- (toc_section, private_data_section, trap_comparison_operator): Add
- prototypes.
+Sat Apr 17 14:36:19 1999 Craig Burley <craig@jcb-sc.com>
- * dbxout.h (dbxout_parms, dbxout_reg_parms, dbxout_syms): Add
- prototypes.
+ * tree.c (chainon): Check for circularity only if
+ ENABLE_CHECKING is defined.
- * xcoffout.c: Include toplev.h, outout.h and dbxout.h.
+1999-04-17 10:15 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * xcoffout.h (stab_to_sclass, xcoffout_begin_function,
- xcoffout_begin_block, xcoffout_end_epilogue,
- xcoffout_end_function, xcoffout_end_block,
- xcoff_output_standard_types, xcoffout_declare_function,
- xcoffout_source_line): Add prototypes.
+ * cccp.c: Make fatal non-static.
-Thu Jun 25 09:54:55 1998 Nick Clifton <nickc@cygnus.com>
+Sat Apr 17 23:47:24 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * config/arm/arm.h (REG_ALLOC_ORDER): Add ARG_POINTER_REGNUM,
- noticed by grahams@rcp.co.uk.
+ * config/c4x/c4x.md (*andqi3_255_clobber,*andqi3_65535_clobber):
+ New logical and patterns using C40 bit-field insert instructions.
+ (*lshrqi3_24_clobber,*ashrqi3_24_clobber,*lshrqi3_16_clobber,
+ *ashrqi3_16_clobber): New shift patterns using C40 bit-field insert
+ instructions.
-Thu Jun 25 11:12:29 1998 Dave Brolley <brolley@cygnus.com>
+1999-04-16 22:44 -0400 Zack Weinberg <zack@rabi.columbia.edu>
- * gcc.c (default_compilers): Use new | syntax to eliminate
- string concatenation.
+ * system.h: Always prototype abort. Prototype fatal. Define
+ abort to call fatal, not fprintf/exit. Define a stub macro
+ for trim_filename.
+ * toplev.c: Define DIR_SEPARATOR. (trim_filename): New
+ function.
+ * toplev.h: Prototype trim_filename, and #undef system.h's stub.
-Thu Jun 25 01:00:48 1998 Richard Henderson <rth@cygnus.com>
+ * gcc.c, genattr.c, genattrtab.c, gencodes.c, genconfig.c,
+ genemit.c, genextract.c, genflags.c, genopinit.c, genoutput.c,
+ genpeep.c, genrecog.c: Make fatal non-static.
+ * gcov.c, gengenrtl.c, protoize.c: #undef abort after
+ including system.h.
- * alpha.c (alpha_function_name): Delete.
- (alpha_ra_ever_killed): Notice current_function_is_thunk.
- (alpha_sa_mask, alpha_sa_size, alpha_does_function_need_gp): Likewise.
- (alpha_start_function): Reorg from output_prologue.
- (alpha_end_function): Reorg from output_epilogue.
- * alpha.h (ASM_DECLARE_FUNCTION_NAME): Call alpha_start_function.
- (ASM_DECLARE_FUNCTION_SIZE): New.
- (FUNCTION_PROLOGUE, FUNCTION_EPILOGUE): Delete.
- (PROFILE_BEFORE_PROLOGUE): Set.
- (ASM_OUTPUT_MI_THUNK): Remove bits now output by start/end_function.
- * alpha/win-nt.h (ASM_OUTPUT_MI_THUNK): Likewise.
+ * config/i386/dgux.h, config/m68k/xm-amix.h: Remove stale code
+ relating to abort.
-Thu Jun 25 01:18:47 1998 John Wehle (john@feith.com)
+Sat Apr 17 11:25:44 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * i386/freebsd-elf.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Define.
+ * config/c4x/c4x.md (mulqf3_clrqf_clobber, mulqi3_clrqi_clobber):
+ New patterns to support parallel multiply and load of zero.
-1998-06-25 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+Fri Apr 16 01:23:47 1999 Jason Merrill <jason@yorick.cygnus.com>
- * expr.c (expand_assignment): Rework address calculation for structure
- field members to expose more invariant computations to the loop
- optimizer.
- (expand_expr): Likewise.
+ * tree.c (valid_machine_attribute): If we're modifying the
+ FUNCTION_TYPE within a POINTER_TYPE and we don't get a decl,
+ update the POINTER_TYPE.
-Wed Jun 24 22:44:22 1998 Jeffrey A Law (law@cygnus.com)
+Fri Apr 16 00:19:31 1999 Jan Hubicka <hubicka@freesoft.cz>
- * local-alloc.c (block_alloc): Do not try to avoid false dependencies
- when SMALL_REGISTER_CLASSES is nonzero.
+ * i386.c (x86_adjust_cost): Move break statement to correct place.
-Wed Jun 24 17:55:15 1998 Klaus Kaempf <kkaempf@progis.de>
+Thu Apr 15 23:17:33 1999 Jerry Quinn <jquinn@nortelnetworks.com>
- * alpha.md (call_vms, call_value_vms): Strip leading * from symbol.
+ * pa.h (HAVE_PRE_INCREMENT, HAVE_POST_INCREMENT,
+ HAVE_PRE_DECREMENT, HAVE_POST_DECREMENT): Fix pa_cpu value from
+ 8000 to PROCESSOR_8000.
-Wed Jun 24 16:27:23 1998 John Carr <jfc@mit.edu>
+Thu Apr 15 20:46:57 1999 Donn Terry (donn@interix.com)
- * expr.c (get_memory_rtx): New function.
- (expand_builtin): Call get_memory_rtx for MEM arguments to builtin
- string functions.
+ * expr.c (expand_assignment): Force pointers to proper mode if
+ POINTERS_EXTEND_UNSIGNED is defined.
- * expmed.c (init_expmed): Initialize all elements of *_cost arrays.
+ * xm-alpha.h (alloca.h): Add Interix to list of special machines
+ that don't like alloca.h, pending using autoconf results.
- * optabs.c: Use gen_rtx_FOO (...) instead of gen_rtx (FOO, ...).
- * expr.c: Likewise.
- * explow.c: Likewise.
- * combine.c: Likewise.
- * reload1.c: Likewise.
- * gcse.c: Likewise.
+ * except.c (start_catch_hadler): Be sure rtime_address is Pmode
+ if POINTERS_EXTEND_UNSIGNED.
+
+ * except.c (expand_eh_return): Force pointers to proper mode if
+ POINTERS_EXTEND_UNSIGNED.
+
+Thu Apr 15 23:13:35 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Wed Jun 24 15:13:01 1998 Dave Brolley <brolley@cygnus.com>
+ * config/c4x/c4x.h: Tweaked comment formatting.
+ * config/c4x/c4x.c: Likewise.
- * README.gnat: Add patch for new lang_decode_options interface.
+Thu Apr 15 02:45:19 1999 Mumit Khan <khan@xraylith.wisc.edu>
-Wed Jun 24 09:14:04 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+ * aclocal.m4 (GCC_FUNC_MKDIR_TAKES_ONE_ARG): Define.
+ * configure.in: Use.
+ * configure: Rebuilt.
+ * acconfig.h (MKDIR_TAKES_ONE_ARG): Add.
+ * config.in: Rebuilt.
+ * system.h: Use.
- * except.c (start_catch_handler): Do nothing if EH is not on.
+Thu Apr 15 01:03:21 1999 Jan Hubicka <hubicka@freesoft.cz>
+ Jeff Law <law@cygnus.com>
-1998-06-24 Manfred Hollstein <manfred@s-direktnet.de>
+ * i386.md (QImode add pattern): Support lea instruction.
+ (HImode add pattern): Likewise.
+
+ * i386.md (ashlsi patterns): Call output_ashl instead of output_ashlsi3.
+ (ashlqi): Use expander, separate LEA and SAL / ADD patterns; call
+ output_ashl.
+ (ashlhi): Likewise.
+ * i386.h (output_ashl): Renamed from output_ashlsi3.
+ * i386.c (output_ashl): Likewise; support HImode and QImode operands
+ as well.
+
+ * i386.md (notsi, nothi, xorsi, xorhi, and xorqi patterns): Call
+ memory_address_displacement_length instead of memory_address_length.
+ * i386.c (memory_address_info): Renamed from memory_address_length.
+ Accept new argument DISP_LENGTH. All callers changed. If DISP_LENGTH,
+ then return the displacement length. Else return length of the
+ entire memory address. Handle MULT case correctly.
+ * i386.h (memory_address_info): Update declaration.
+
+ * i386.md (memory_bit_test): Fix paren error.
+
+Wed Apr 14 21:29:18 1999 Andrew Haley <aph@cygnus.com>
+
+ * flow.c: (make_edges): Always make edges from a basic block
+ to its exception handlers, even if the block ends with a jump.
+
+1999-04-14 23:26 -0400 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * graph.c (node_data): Return void. Ignore result of
+ print_rtl_single. Change caller to match.
+ * integrate.c (subst_constants): Initialize op0_mode to an
+ invalid mode, and abort before use if it's still invalid.
+ (Can only happen if the RTX_CLASS, RTX_FORMAT tables are corrupted.)
+ * objc/objc-act.c (get_objc_string_decl,
+ build_selector_translation_table, generate_protocol_list,
+ synth_id_with_class_suffix, build_keyword_selector,
+ build_selector_expr, gen_declarator): Abort when the tree
+ structure is corrupted.
+
+Wed Apr 14 19:57:49 1999 Jeffrey A Law (law@cygnus.com)
+
+ * configure.in (alpha interix): Use symbolic names to set
+ target_cpu_default.
+ * configure: Rebuilt.
- * configure.in (gxx_include_dir): Initialize default value depending on
- new flag --enable-version-specific-runtime-libs; remove superfluous
- default initialization afterwards.
+ * explow.c (allocate_dynamic_stack_space): Undo last change. Use
+ convert_memory_address instead.
+
+Wed Apr 14 19:42:02 1999 Donn Terry (donn@interix.com)
+
+ * alpha/lib1funcs.asm: New file.
+ * alpha/t-interix (lib1funcs.asm): Add to build.
+
+ * explow.c (allocate_dynamic_stack_space): Correctly convert TARGET
+ to Pmode.
+
+Wed Apr 14 14:26:36 1999 John Wehle (john@feith.com)
+
+ * i386.md (truncxfdf): Output the template supplied
+ by output_move_double with the correct operands.
+
+ * i386.md (extendsfdf, extendsfxf, extenddfxf): Use
+ output_float_extend instead specifying '#' as the template.
+ * i386.c (output_float_extend): Define.
+ * i386.h (output_float_extend): Declare.
+
+Wed Apr 14 10:48:03 1999 Catherine Moore <clm@cygnus.com>
+
+ * config/mips/elf.h, config/mips/elf64.h
+ (CTORS_SECTION_ASM_OP): Define.
+ (DTORS_SECTION_ASM_OP): Define.
+ (EXTRA_SECTIONS): Define.
+ (INVOKE__main): Define.
+ (NAME__MAIN): Define.
+ (SYMBOL__MAIN): Define.
+ (EXTRA_SECTIONS_FUNCTIONS): Define.
+ (SECTION_FUNCTION_TEMPLATE): Define.
+ (ASM_OUTPUT_CONSTRUCTOR): Define.
+ (ASM_OUTPUT_DESTRUCTOR): Define.
+ (CTOR_LIST_BEGIN): Define.
+ (CTOR_LIST_END): Define.
+ (DTOR_LIST_BEGIN): Define.
+ (DTOR_LIST_END): Define.
+ (LIB_SPEC): Define.
+ (STARTFILE_SPEC): Define.
+ (ENDFILE_SPEC): Define.
+ * config/mips/linux.h: Undefine all of the above.
+ * config/mips/rtems64.h: Likewise.
+ * config/mips/t-r3900: Likewise.
+ * config/mips/t-elf: New file.
+ * config/mips/vxworks.h: New file.
+ * configure.in (mips-wrs-vxworks): Use mips/vxworks.h.
+ (mips*-*-*elf*): Use t-elf instead of t-ecoff.
* configure: Regenerate.
-Wed Jun 24 01:32:12 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+Wed Apr 14 09:59:38 1999 Richard Henderson <rth@cygnus.com>
- * toplev.c (rest_of_compilation): Revert May 15 change.
+ * reload1.c (emit_reload_insns): Also find equivalent mems
+ for subregs of pseudos.
-Tue Jun 23 21:27:27 1998 Ken Raeburn <raeburn@cygnus.com>
+ * alpha.c (aligned_memory_operand): Recognize the output of
+ LEGITIMIZE_RELOAD_ADDRESS. Examine reg_equiv_memory_loc in
+ the event of a pseudo.
+ (unaligned_memory_operand): Likewise. Don't otherwise accept
+ completely illegal addresses.
+ (normal_memory_operand): Likewise. Handle subregs of pseudos.
+ (get_aligned_mem): Revert previous change. Abort if we don't have a
+ mem. During reload, call find_replacement on all illegal memories.
+ (get_unaligned_address): Likewise.
+ * alpha.h (SECONDARY_INPUT_RELOAD_CLASS): Use !aligned_memory_operand
+ instead of unaligned_memory_operand.
+ * alpha.md: Revert extra argument to get_aligned_mem.
+ (reload_inqi): Use any_memory_operand in constraints. Abort if
+ we're not given some sort of mem.
+ (reload_inhi): Likewise.
+ (reload_outqi, reload_outhi): Likewise.
- * reload.c (find_reloads): Fix check for failure to match any
- alternative, to account for Mar 26 change in initial "best" cost.
+Wed Apr 14 09:39:20 1999 Richard Henderson <rth@cygnus.com>
-Tue Jun 23 16:44:21 1998 Dave Brolley <brolley@cygnus.com>
+ * i386.md (neghi): Use the whole register when widening the op.
- * cpplib.c (do_line): Typo broke #line directive.
- (cpp_message_from_errno): New function.
- (cpp_error_from_errno): Call cpp_message_from_errno.
- * cpplib.h (cpp_message_from_errno): New function.
+1999-04-14 12:37 -0400 Zack Weinberg <zack@rabi.columbia.edu>
-Tue Jun 23 13:38:18 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+ * cpperror.c, cppexp.c, cpplib.c: Never call abort.
+ * cpphash.c: Only call abort when we detect corruption of the
+ malloc arena.
+ * cppmain.c: Don't define fatal or fancy_abort.
- * libgcc2.c (__get_eh_table_version, __get_eh_table_language): New
- functions to return exception descriptor information.
- (find_exception_handler): Pass match_info field to runtime matcher,
- not a descriptor table entry.
+Wed Apr 14 09:19:39 1999 Jan Hubicka <hubicka@freesoft.cz>
-Tue Jun 23 09:30:58 1998 Dave Love <d.love@dl.ac.uk>
+ * i386.c (x86_adjust_cost): Agi stall takes 1 cycle on Pentium, fst
+ requires value to be ready one extra cycle.
- * cpp.texi, gcc.texi: Add @dircategory, @direntry meant to
- accompany previous Makefile.in (install-info) change.
+Wed Apr 14 11:28:34 1999 Dave Brolley <brolley@cygnus.com>
-Tue Jun 23 10:06:07 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+ * config/i386/i386.c (memory_address_length): Add missing parenthesis.
- * eh-common.h (struct __eh_info): Remove coerced value field.
- * libgcc2.c (find_exception_handler): Don't set coerced_value field.
- * except.c (get_dynamic_handler_chain, get_dynamic_cleanup_chain): Use
- POINTER_SIZE instead of Pmode.
- (expand_start_all_catch): Call start_catch_handler() if we are not
- using new style exceptions.
+Wed Apr 14 13:59:27 1999 Martin von Loewis <loewis@informatik.hu-berlin.de>
-Tue Jun 23 06:45:00 1998 Catherine Moore <clm@cygnus.com>
+ * extend.texi (Deprecated Features): New node.
+ * invoke.texi (-Wdeprecated): Document.
- * varasm.c (assemble_variable): Remove reference to warn_bss_align.
+Wed Apr 14 00:18:22 1999 Jan Hubicka <hubicka@freesoft.cz>
-Mon Jun 22 23:57:31 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+ * i386.md (SImode logical compare): Avoid outputing non-pariable testw
+ and testl on Pentium.
+ (register and memory bit tests): Likewise.
+ (setcc, normal and reversed conditional branches): Use shorter
+ sequence for testing flags stored in EAX.
- * config/sparc/sparc.md (zero_extendhidi2, extendhisi2,
- extendqihi2, extendqisi2, extendqidi2, extendhidi2, adddi3,
- subdi3, negdi2, call, call_value, untyped_return, nonlocal_goto,
- splits and peepholes): Change remaining generic gen_rtx calls to
- specific genrtl ones.
- * config/sparc/sparc.c: Likewise.
-
-Mon Jun 22 22:21:46 1998 Richard Henderson <rth@cygnus.com>
+ * i386.md (xorsi3): Do not output NOT instrctions on Pentium.
+ (xorqi3): Likewise.
+ (xorhi3): Likewise.
+ (notsi2): Likewise.
+ (notqi2): Likewise.
+ (nothi2): Likewise; do not output prefixed opcodes when possible.
- * gcc.c (handle_braces): Recognize | between options as an or.
+ * i386.md (neghi2): Do not output prefixed opcode when possible.
+ (ashlhi3): Likewise.
-Mon Jun 22 23:13:47 1998 John Wehle (john@feith.com)
+Wed Apr 14 00:08:46 1999 Richard Henderson <rth@cygnus.com>
- * i386/freebsd-elf.h (JUMP_TABLES_IN_TEXT_SECTION): Define as flag_pic.
- * i386/sysv4.h (JUMP_TABLES_IN_TEXT_SECTION): Define as flag_pic.
+ * i386.c (memory_address_length): New function.
+ * i386.h (memory_address_length): Declare it.
- * i386.md (exception_receiver): Define.
+Tue Apr 13 22:52:04 1999 Donn Terry (donn@interix.com)
+ Martin Heller (Ing.-Buero_Heller@t-online.de)
-Mon Jun 22 12:01:48 1998 Jim Wilson <wilson@cygnus.com>
+ * configure.in (interix Alpha): Add.
+ (winnt Alpha): Use alpha32.h
+ (interix i386): Parallel Alpha32.
+ * configure: Rebuilt.
- * Makefile.in (PROTOIZE_INSTALL_NAME, UNPROTOIZE_INSTALL_NAME,
- PROTOIZE_CROSS_NAME, UNPROTOIZE_CROSS_NAME): New variables.
- (install-common): Use them.
+ * config/interix.h: Move common elements from i386-interix.h.
+ * config/i386/i386-interix.h: Delete same.
+ * config/alpha/alpha-interix.h: New file.
- * gcse.c (add_label_notes): New function.
- (pre_insert_insn): Call it.
- * unroll.c (unroll_loop): Look for insns with a REG_LABEL note, and
- pass the label to set_label_in_map.
+ * config/alpha/alpha32.h: New file, part fron win-nt.h.
+ * config/alpha/win-nt.h: Deletions (-> alpha32.h).
+ * config/alpha/interix.h: New file
-Mon Jun 22 19:01:14 1998 Dave Love <d.love@dl.ac.uk>
+ * config/alpha/alpha.md (interix): Comment.
- * Makefile.in (install-info): Fix typpo in previous change.
+ * config/alpha/xm-alpha-interix.h: New file.
-Mon Jun 22 11:10:00 1998 Catherine Moore <clm@cygnus.com>
+ * config/alpha/t-interix: New file.
- * varasm.c (assemble_variable): Emit alignment warning.
+ * fixinc/mkfixinc.sh (interix/Alpha): Add.
-Mon Jun 22 08:18:46 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+1999-04-13 Mike Stump <mrs@wrs.com>
- * Makefile.in (varasm.o): Depend on sdbout.h.
- (sdbout.o): Depend on toplev.h.
+ * i386/vxi386.h (CPP_CPU_SPEC): Define appropriately for vxworks.
+ (CPP_PREDEFINES, LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): likewise.
- * collect2.c (scan_prog_file): Cast fprintf argument to `long' and
- use %ld specifier.
+Tue Apr 13 21:01:36 1999 Jason Merrill <jason@yorick.cygnus.com>
- * final.c (shorten_branches): Cast first arg of `bzero' to char *.
+ * c-common.c (default_valid_lang_attribute): New fn.
+ (valid_lang_attribute): New callback ptr.
+ (decl_attributes): Call it. Move init_priority support into
+ C++ frontend.
- * genextract.c (main): When creating insn-extract.c, mark variable
- `i' with ATTRIBUTE_UNUSED.
+Tue Apr 13 17:47:14 1999 John Wehle (john@feith.com)
- * genpeep.c (main): When creating insn-peep.c, mark variables
- `insn', `x' and `pat' with ATTRIBUTE_UNUSED.
+ * i386.md (movdi): Add splitter.
- * objc/init.c (__objc_tree_print): Wrap function definition in
- macro `DEBUG'.
+Wed Apr 14 10:04:27 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * objc/objc-act.c (encode_array): Cast sprintf argument to `long'
- and use %ld specifier.
- (adorn_decl): Likewise, twice.
+ * config/c4x/c4x.md (storeqf_int, storeqf_int_clobber, loadqf_int,
+ loadqf_int_clobber): Add new patterns with corresponding splitters
+ to handle moves of floating point values into and out of intager
+ registers by using memory.
- * reload1.c (reload_cse_regs): Cast first arg of `bzero' to char *.
+ * config/c4x/c4x.c (c4x_check_legit_addr): Disallow PRE_INC for modes
+ other than QFmode and QImode.
+ (mixed_subreg_operand): New function.
+ (c4x_emit_move_sequence): If moving a floating point value into or
+ out of an integer register, use the new patterns storeqf_int_clobber
+ or loadqf_int_clobber.
+ (reg_imm_operand, *_reg_operand): Call reg_operand instead of
+ register_operand.
+ (reg_operand, src_operand): Disallow operand if it satisifes
+ mixed_subreg_operand.
- * sdbout.c: Include output.h and toplev.h.
- (PUT_SDB_INT_VAL): Use HOST_WIDE_INT_PRINT_DEV to print argument
- `a'. Cast `a' to HOST_WIDE_INT to force it to always be so.
- (PUT_SDB_SIZE): Likewise.
+ * config/c4x/c4x.h (mixed_subreg_operand): Add prototype.
- * sdbout.h (sdbout_mark_begin_function): Add prototype.
+Tue Apr 13 14:49:13 1999 Jan Hubicka <hubicka@freesoft.cz>
- * stmt.c (check_for_full_enumeration_handling): Cast argument of
- `warning' to long and use %ld specifier.
+ * i386.c (agi_dependent): Handle push operation more correctly.
- * toplev.c (main): Likewise for `fprintf'.
+Tue Apr 13 14:45:17 1999 Jan Hubicka <hubicka@freesoft.cz>
- * toplev.h (output_file_directive): Add prototype.
+ * i386.md (anddi3): Add % constraint.
+ (iordi3, xordi3): Likewise.
- * unroll.c (unroll_loop): Use HOST_WIDE_INT_PRINT_DEC specifier in
- call to `fprintf'.
- (precondition_loop_p): Likewise.
+Tue Apr 13 14:29:58 1999 Jan Hubicka <hubicka@freesoft.cz>
- * varasm.c Include sdbout.h.
- (assemble_static_space): Move sometimes-unused variable `rounded'
- into the scope in which it is used.
-
- * mips.c (gpr_mode): Don't say `static' twice.
+ * i386.md (extendhisi2): Output mov instead of cw instruction for K6
+ to improve decoding bandwidth.
+ * i386.md (extendhiqi2): Likewise.
- * cpplib.c (cpp_handle_option): Don't pass unneeded NULL to cpp_fatal.
+Tue Apr 13 14:26:31 1999 Jan Hubicka <hubicka@freesoft.cz>
- * objc/objc-act.c (init_selector): Hide prototype and definition.
+ * i386.md (movsf_push): Handle memory to memory case too, new splitter.
+ (movdf_push, movxf_push): Likewise.
+ (movsf_push_memory, movdf_push_memory, movxf_push_memory): Remove.
- * optabs.c (gen_cond_trap): Remove unused variable `icode'.
-
- * regmove.c (copy_src_to_dest): Likewise for `i'.
+Tue Apr 13 14:14:06 1999 Jan Hubicka <hubicka@freesoft.cz>
- * mips-tfile.c (add_local_symbol): Cast width format specifier to int.
- (add_ext_symbol): Likewise.
- (add_file): Likewise.
- (parse_def): Likewise.
- (write_varray): Use HOST_PTR_PRINTF to print a pointer. Fix
- remaining format specifiers and arguments.
- (write_object): Likewise, several times.
- (read_seek): Likewise.
- (out_of_bounds): Likewise.
- (allocate_cluster): Likewise.
- (xmalloc): Likewise.
- (xcalloc): Likewise.
- (xrealloc): Likewise.
- (xfree): Likewise.
-
- * mips-tdump.c (print_symbol): Likewise.
-
-Sun Jun 21 17:05:34 1998 Dave Love <d.love@dl.ac.uk>
+ * i386.md: Do not output mov %0,reg on AMD K6.
- * Makefile.in (install-info): Use install-info program if
- available, per GNU standard.
+Tue Apr 13 12:14:07 1999 Dave Brolley <brolley@cygnus.com>
-Sun Jun 21 18:56:44 1998 Jeffrey A Law (law@cygnus.com)
+ * cppinit.c (cpp_start_read): Fix buffer overwrite.
+ * Makefile.in (cppinit.o): Typo in dependencies.
- * invoke.texi: Document -mrelax for the mn10300 and mn10200.
+Tue Apr 13 05:04:59 1999 Richard Earnshaw (rearnsha@arm.com)
- * basic-block.h (init_regset_vector): Delete declaration.
- * flow.c (init_regset_vector): Make it static and add a prototype.
+ * arm.h (function prototypes for arm.c): Ifdef these out if
+ HAVE_CONFIG_H is not defined.
- * bitmap.h (debug_bitmap): Declare.
+Tue Apr 13 02:11:11 1999 Jeffrey A Law (law@cygnus.com)
- * haifa-sched.c (debug_ready_list): Make static.
+ * pa.c: Avoid Using immediate zero for register zero.
+ * pa.md: Likewise.
- * toplev.h (fancy_abort): Declare.
+ * pa.c (print_operand, case 'f'): New case for FP register or 0.0.
+ (print_operand, case 'r'): Use %r0 for zero value.
+ * pa.md (move patterns, fcmp patterns): Use new %f output arg.
-Sun Jun 21 18:30:13 1998 H.J. Lu (hjl@gnu.org)
+ * pa.c: Use a register name, not a raw immediate in branch,
+ compare/clear, sub, subb, uaddcm and vshd instructions.
+ * pa.md: Likewise.
- * basic-block.h (init_regset_vector): New declaration.
+ * pa.md, pa.h, ee.asm, ee_fp.asm, lib2funcs.asm: Likewise.
- * Makefile.in (sdbout.o): Add insn-codes.h to dependency.
+ * pa.c: Use a register name, not a raw immediate in "bv" instructions.
+ * pa.md, pa.h, ee.asm, ee_fp.asm, lib2funcs.asm: Likewise.
- * global.c: Include machmode.h amd move hard-reg-set.h before
- rtl.h.
+ * pa.c: Remove space register specification in memory addresses,
+ except where it is actually needed.
+ * pa.md, pa.h, ee.asm, ee_fp.asm, lib2funcs.asm: Likewise.
- * haifa-sched.c (insn_issue_delay, birthing_insn_p,
- adjust_priority, print_insn_chaino): New declaration.
- (schedule_insns): Remove declaration.
- (init_target_units, get_visual_tbl_length,
- init_block_visualization): Add prototype.
+Mon Apr 12 23:34:35 1999 Jeff Law (law@cygnus.com)
- * integrate.c (pushdecl, poplevel): Remove declaration.
+ * version.c: Bump for snapshot.
- * rtl.h (expand_expr): Remove declaration.
+Mon Apr 12 14:58:30 1999 Jan Hubicka <hubicka@freesoft.cz>
- * loop.c (oballoc): Remove declaration.
- (replace_call_address): Add prototype.
+ * reg-stack.c (check_stack_regs_mentioned): Remove variable SIZE.
-Sun Jun 21 01:08:17 PDT 1998 Jeff Law (law@cygnus.com)
+Mon Apr 12 19:15:17 1999 Daniel Jacobowitz <dan@debian.org>
- * version.c: Bump for snapshot.
+ * rs6000/sysv4.h (CPP_OS_LINUX_SPEC): Add missing backslash.
+
+Mon Apr 12 19:11:38 1999 Mumit Khan <khan@xraylith.wisc.edu>
+
+ * i386/cygwin.h (SUBTARGET_SWITCHES): Add -mconsole; fix
+ -mno-nop-fun-dllimport and minor doc fixes.
+ (STARTFILE_SPEC): Cygwin DLLs don't have dllcrt0.
+ (LINK_SPEC): Add -mconsole support.
+ * i386/mingw32.h (LIB_SPEC): Make libraries consistent with
+ Cygwin.
+ (LINK_SPEC): Remove. Use Cygwin's version.
+ (MATH_LIBRARY): Make it null.
+ * i386/crtdll.h (MATH_LIBRARY): Likewise.
+
+Fri Apr 12 15:00:52 1999 Stan Cox <scox@cygnus.com>
+
+ * c-decl.c (c_decode_option, start_decl, start_function,
+ finish_function) : Recognize -Wno-main so we can avoid warnings.
+
+1999-04-12 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * cpphash.c (collect_expansion, macroexpand,
+ push_macro_expansion): Make the escape character in macro
+ buffers '\r', not '@'. Remove code to protect literal
+ occurences of the escape character; '\r' cannot appear
+ in a macro buffer unless we put it there.
+ * cpplib.c (skip_comment, copy_comment, cpp_skip_hspace,
+ copy_rest_of_line, cpp_get_token, parse_string,
+ parse_assertion): '\r' might be a backslash-newline marker, or
+ it might be a macro escape marker, depending on
+ CPP_BUFFER (pfile)->has_escapes. '@' is not a special
+ character.
+ * cpplib.h: Update commentary.
+
+Mon Apr 12 09:30:03 1999 Richard Earnshaw (rearnsha@arm.com)
+
+ * arm.h (target_fp_name, structure_size_string, arm_cpu_select):
+ Const-ify.
+ * arm.c (target_fp_name, structure_size_string): Const-ify.
+
+ * arm.md (reload_inhi, reload_outhi): Make the scratch DImode.
+ * arm.c (arm_reload_in_hi): Handle cases when the input is still
+ a pseudo, make use of scratch registers for reloading the address
+ as appropriate.
+ (arm_reload_outhi): Similarly for when the output is still a pseudo.
+
+ * riscix.h (SUBTARGET_SWITCHES): Document.
+
+1999-04-12 Bruce Korb <ddsinc09@ix.netcom.com>
+
+ * fixincludes:
+ make fixincludes behave like the scripts in fixinc/
+
+ * Makefile.in( stmp-fixinc ):
+ ensure the SHELL value is that of the make
+
+ * fixincl/inclhack.tpl:
+ the file name lists ought to be restricted to "*.h" anyway
+ C++ files may be named .../[a-z]++/... also
+ Adding copyright year and attribution to output
+
+ * fixincl/inclhack.def:
+ fixed broken expression
+ Clarify a some comments
+
+ * fixincl/fixincl.tpl:
+ Clarify a some comments
+ Remove dead template text
+ Correct the counting of regular expressions
+
+Mon Apr 12 03:07:44 1999 Richard Henderson <rth@cygnus.com>
+
+ * alpha.c (aligned_memory_operand): Handle out of range stack slots.
+ Take a new SCRATCH argument for the occasion. Update all callers.
+ (get_unaligned_address): Abort on out of range stack slots.
+ * alpha.md (adddi3 splitter): Check s_p_rtx not REGNO.
+ (reload_inqi): Check for aligned mems before unaligned.
+ (reload_inhi): Likewise.
+
+Mon Apr 12 03:11:30 1999 Jeffrey A Law (law@cygnus.com)
+
+ * flow.c (flow_delete_insn): If we delete a CODE_LABEL, also remove
+ it from the nonlocal_goto_handler_labels list.
+ * jump.c (delete_insn): Likewise.
+ (jump_optimize_1): Also recompute LABEL_NUSES when we are just
+ marking labels.
+ * rtl.h (remove_node_from_expr_list): Declare.
+ * rtlanal.c (remove_node_from_expr_list): New function.
+
+Mon Apr 12 02:37:02 1999 Jan Hubicka <hubicka@freesoft.cz>
+
+ * reg-stack.c: Update comment, include varray.h.
+ (stack_regs_mentioned_data): New global variable.
+ (check_stack_regs_mentioned): New function.
+ (stack_regs_mentioned): New function.
+ (reg_to_stack): Initialize and free stack_regs_mentioned_data,
+ use stack_regs_mentioned.
+ (record_asm_reg_life): Change insn type cache for changed insn.
+ (record_reg_life): Do not change the insn mode.
+ (emit_pop_insn): Likewise.
+ (emit_swap_insn): Likewise.
+ (move_for_stack_reg): Likewise.
+ (stack_reg_life_analysis): Use stack_regs_mentioned.
+ (emit_swap_insn): Likewise.
+ (subst_stack_regs): Likewise.
+ (convert_regs): Likewise.
+ * jump.c (find_cross_jump): Use stack_regs_mentioned.
+ * rtl.h (stack_regs_mentioned): Declare.
-Sun Jun 21 01:16:38 1998 John Wehle (john@feith.com)
+Mon Apr 12 00:57:10 1999 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
- * i386.c (output_fp_conditional_move): Don't bother handling
- (cc_prev_status.flags && CC_NO_OVERFLOW) since the INSN patterns
- prevent this from happening.
+ * integrate.c (INTEGRATE_THRESHOLD): Sync it with the comment.
- * i386.md (nonlocal_goto_receiver): Delete.
+Sun Apr 11 10:24:18 1999 Mark Mitchell <mark@codesourcery.com>
-Sun Jun 21 00:42:20 1998 H.J. Lu (hjl@gnu.org)
+ * rtl.h (rtx_def): Update documentation for jump and call.
- * Makefile.in (crtbeginS.o, crtendS.o): Add -fno-exceptions and
- -DCRTSTUFFS_O.
- (INSTALL): cd $(srcdir) before make.
+Sun Apr 11 07:43:44 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * flow.c (allocate_for_life_analysis, init_regset_vector):
- Remove declaration.
+ * jump.c (jump_optimize_1): Make the definition static to match
+ the prototype.
- * function.h (get_first_block_beg): New declaration.
+Sat Apr 10 22:51:53 1999 Jan Hubicka <hubicka@limax.paru.cas.cz>
- * gbl-ctors.h (__do_global_dtors): Add prototype.
+ * flow.c (life_analysis): New parameter remove_dead_code.
+ (life_analysis_1): Likewise.
+ (propagate_block): Likewise; use it.
+ * output.h: Update prototype.
+ * toplev.c: Update calls to life_analysis.
- * gcov-io.h (__fetch_long): New declaration.
- (__store_long): Likewise.
- (__read_long): Likewise.
- (__write_long): Likewise.
+Sat Apr 10 22:12:12 1999 Jan Hubicka <hubicka@freesoft.cz>
- * gcov.c (print_usage): New declaration.
+ * recog.c (constrain_operands): Ignore unary operators when
+ matching operands. Recognize '5'..'9' as well.
- * Makefile.in (c-iterate.o): Depend on insn-codes.h too.
+Sat Apr 10 21:53:02 1999 Philipp Thomas (kthomas@gwdg.de)
+ Richard Henderson <rth@cygnus.com>
-Sat Jun 20 00:36:16 1998 Jeffrey A Law (law@cygnus.com)
+ * configure.in: Set target_cpu_default2 for target_alias k6.
+ * i386.h (TARGET_SWITCHES): Remove no-<cpu> entries.
+ (CC1_CPU_SPEC): Likewise.
+ (CPP_CPU_DEFAULT_SPEC): Streamline definition. Add K6 version.
+ (CPP_K6_SPEC): New.
+ (CPP_CPU_SPEC): Add K6 variant.
+ (EXTRA_SPECS): Likewise.
- * calls.c (expand_call): Initialize "src" and "dest".
- * stmt.c (expand_return): Likewise.
- * expmed.c (extract_split_bit_field): Similarly for "result"
- * gcse.c (compute_hash_table): Mark first arg as unused.
- * jump.c (jump_optimize): Initialize reversep.
- * tree.c (make_node): Initialize length.
+Fri Apr 9 11:29:17 1999 Richard Henderson <rth@cygnus.com>
- * c-common.c (check_format_info): Initialize length_char and
- fci to keep -Wall quiet.
+ * flow.c (merge_blocks_nomove): Rewrite to properly handle two
+ blocks that vanish entirely during merging.
- * except.c (jumpif_rtx): Put declaration and definition
- inside a suitable #ifdef.
- (jumpifnot_rtx): Delete dead function.
+Sat Apr 10 20:09:55 1999 John Wehle (john@feith.com)
- * i386.h (output_int_conditional_move): Declare.
- (output_fp_conditional_move): Likewise.
- (ix86_can_use_return_insn_p): Likewise.
+ * i386.md (floatsisf2, floatdisf2, floatsidf2, floatdidf2,
+ floatsixf2, floatdixf2, movsicc, movhicc, movsfcc, movdfcc,
+ movxfcc, movdicc): Remove unused register constraints from
+ the splitters.
- * optabs.c (init_traps): Put prototype inside a suitable #ifdef.
+ * i386.md (fixuns_truncsfsi2, fixuns_truncdfsi2,
+ fixuns_truncxfsi2): Delete.
-Sat Jun 20 00:27:40 1998 Graham <grahams@rcp.co.uk>
+ * reg-stack.c (delete_insn_for_stacker): Ensure that
+ the only side effects of a PARALLEL are clobbers.
+ (subst_stack_regs): Handle subst_stack_regs_pat deleting
+ a PARALLEL.
+ * i386.md (extendsfdf2, extenddfxf2,
+ extendsfxf2): Rewrite using a splitter.
+ * i386.c (output_op_from_reg): Remove.
+ * i386.h: Likewise.
- * alias.c: Include toplev.h
- * caller-save.c: Include toplev.h
- * combine.c: Include toplev.h
- * flow.c Include toplev.h
- * global.c: Include toplev.h
- * jump.c: Include toplev.h
- * local-alloc.c: Include toplev.h
- * loop.c: Include toplev.h
- * regmove.c: Include toplev.h
- * stupid.c: Include toplev.h
- * unroll.c: Include toplev.h
- * Makefile.in: Add toplev.h dependencies.
+Sat Apr 10 13:09:18 1999 Nick Clifton <nickc@cygnus.com>
-Fri Jun 19 22:40:25 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * config/arm/arm.c (di_operand): Allow SUBREGs as well.
+ (soft_df_operand): Allow SUBREGs as well.
- * regmove.c (copy_src_to_dest): Add decl for loop_depth.
+Sat Apr 10 06:14:31 1999 Jan Hubicka <hubicka@paru.cas.cz>
- * svr4.h (ASM_GENERATE_INTERNAL_LABEL): Cast arg to unsigned.
- * dwarf2out.c (ASM_OUTPUT_DWARF_DATA1): Likewise.
- Add parens to various macros.
+ * extend.texi (Assembler Instructions with C Expression Operands):
+ Document the i386 floating point operands.
-Fri Jun 19 23:22:42 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+1999-04-10 Mike Stump <mrs@wrs.com>
- * c-typeck.c (pop_init_level): Warn about implicit zero initialization
- of struct members.
+ * configure.in (*-*-vxworks): Add vxWorks thread support for all
+ vxWorks targets.
+ * configure.in (thumb-wrs-xvworks): Add vxWorks support for thumb.
+ * configure: Rebuilt.
-Fri Jun 19 23:06:33 1998 Jason Merrill <jason@yorick.cygnus.com>
+Sat Apr 10 06:04:50 1999 Donn Terry (donn@interix.com)
+
+ * i386/t-interix: Use mostly system headers unchanged.
+ Use system assert.h
+ * fixinc/fixinc.interix: Ditto (make almost no-op).
+ * config/x-interix.h (_ALL_SOURCE): add -D
+ * config/x-interix.h (crti.o): Delete dependency.
+ * config/xm-interix.h (ONLY_INT_FIELDS): Define only when bootstrapping.
+ * i386/xm-i386-interix.h: New file.
+ * i386/interix.h (ASM_OUTPUT_LIMITED_STRING): Fix warnings.
+ * i386/i386-interix.h: Renamed from interix.h.
+ * configure.in (interix): Use new files.
+ * configure: Rebuilt.
- * varasm.c (assemble_start_function): Add weak_global_object_name.
- * tree.c (get_file_function_name): Use it.
+Sat Apr 10 05:25:28 1999 Daniel Jacobowitz <dan@debian.org>
+
+ * rs6000/sysv4.h (CPP_OS_LINUX_SPEC): Fix conditions
+ for -Dunix and -Dlinux, and remove duplicate definition.
+ Change -Asystem(linux) to -Asystem(posix).
+ (CPP_OS_SOLARIS_SPEC): Fix conditions for -Dunix, -Dsun,
+ -DSVR4, -D__EXTENSIONS__.
+
+ * rs6000/linux.h (CPP_PREDEFINES): Remove -Dunix,
+ -Dlinux, -Asystem(linux), and -Asystem(unix).
+
+Sat Apr 10 05:14:50 1999 Mark Elbrecht <snowball3@usa.net>
+
+ * i386/djgpp.h (SET_ASM_OP): Define.
+
+ * cccp.c (DIR_SEPARATOR): Move to the top of the file.
+ (is_dir_separator): New function.
+ (simplify_filename): Use it.
+ * collect2.c (find_a_file): Use HAVE_DOS_BASED_FILE_SYSTEM in place
+ of the DIR_SEPARATOR test.
+ Consider any file starting with a drivename to be absolute.
+ If the absolute filename test fails and EXECUTABLE_SUFFIX is
+ defined, append EXECUTABLE_SUFFIX to the file and try again.
+ * cppinit.c (base_name): Use HAVE_DOS_BASED_FILE_SYSTEM
+ in place of __MSDOS__ and _WIN32.
+ * cppfiles.c (simplify_pathname): Likewise.
+ * gcc.c (IS_DIR_SEPARATOR): Define new macro. Returns true if a
+ character is a directory separator.
+ (find_a_file): Use it.
+ (convert_filename): Likewise.
+ (process_command): Likewise.
+ (do_spec_1): Likewise.
+ (is_directory): Likewise.
+ (main): Likewise.
+ * prefix.c (IS_DIR_SEPARATOR): Define. Tests whether a character is
+ a directory separator.
+ (translate_name): Use it.
+ (update_path): Change DIR_SEPARATOR_2 to DIR_SEPARATOR. Fix
+ warning in block where '/' is changed to DIR_SEPARATOR.
+ * i386/xm-djgpp.h (DIR_SEPARATOR): Set to '/'.
+ (DIR_SEPARATOR_2): New macro. Set to '\'.
+ (HAVE_DOS_BASED_FILESYS): Define.
+ * i386/xm-mingw32.h: Updated copyright. Set
+ DIR_SEPARATOR_2 to '/'. Define HAVE_DOS_BASED_FILE_SYSTEM.
+ * i386/xm-os2.h: Likewise.
+ * winnt/xm-winnt.h: Likewise.
+ * i386/xm-dos.h: Likewise. Add copyright.
+
+1999-04-10 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * pdp11.h (TARGET_SWITCHES): Add option to vary assembler syntax.
+ (TARGET_DEFAULT): Possibly use UNIX syntax.
+ (TARGET_UNIX_ASM, TARGET_UNIX_ASM_DEFAULT): New macros.
+ (REGISTER_NAMES): Use "r5" instead of "fp".
+ (ASM_OUTPUT_ALIGN): Use ".even" directive, and abort for any
+ greater alignment.
+ * 2bsd.h (TARGET_UNIX_ASM_DEFAULT): Default to UNIX assembler
+ syntax for 2BSD.
+ * pdp11.c (output_ascii): Use working syntax for ".byte".
+ (print_operand_address): Use "*" instead of "@" when using UNIX
+ assembler syntax.
+
+Sat Apr 10 03:50:12 1999 Jeffrey A Law (law@cygnus.com)
+
+ * rtl.h (rebuild_jump_labels): Declare.
+ * jump.c (jump_optimize_1): Renamed from jump_optimize. Make static.
+ Add new argument MARK_LABELS_ONLY. Quit after mark_all_labels if
+ requested.
+ (jump_optimize, rebuild_jump_labels): New wrapper functions for
+ jump_optimize_1.
+ * toplev.c (rest_of_compilation): Use rebuild_jump_labels instead of
+ running the entire jump optimizer.
+
+ * rtl.h (local_alloc): Returns an integer now.
+ * local-alloc.c (recorded_label_ref): New file scoped variable.
+ (local_alloc): Initialize recorded_label_ref to zero. Return its
+ value when local allocation has completed.
+ (update_equiv_regs); If we create an equivalence for a LABEL_REF,
+ set recorded_label_ref.
+ * toplev.c (rest_of_compilation): Run the jump optimizer after
+ register allocation and reloading if needed.
+
+Fri Apr 9 21:02:57 1999 Krister Walfridsson (cato@df.lth.se)
+
+ * i386/gas.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Fix typo.
+ * i386/freebsd-elf.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
+
+1999-04-09 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * cpphash.c (special_symbol): When expanding __LINE__, use the
+ top file buffer, not the top buffer.
+
+Fri Apr 9 13:41:04 1999 Jim Wilson <wilson@cygnus.com>
+
+ * Makefile.in (check-g++, check-gcc, check-g77, check-objc): Add
+ cd .. to TCL_LIBRARY command.
+
+Fri Apr 9 13:04:52 1999 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/unknown-elf.h (SUBTARGET_CPU_DEFAULT): Only define if
+ not already specified.
+
+Fri Apr 9 11:18:55 1999 Jason Merrill <jason@yorick.cygnus.com>
+
+ * c-common.c (decl_attributes, A_INIT_PRIORITY): Allow arrays
+ of classes, too.
+
+Fri Apr 9 10:40:10 1999 Kaveh R. Ghazi <ghazi@snafu.rutgers.edu>
+
+ * rs6000.c (rs6000_override_options, ptt, rs6000_file_start,
+ rs6000_float_const, rs6000_replace_regno, debug_stack_info,
+ rs6000_output_load_toc_table, output_prolog, output_epilog):
+ Const-ify a char*.
+ (output_mi_thunk): Likewise. Mark parameter `thunk_fndecl' with
+ ATTRIBUTE_UNUSED. Hide unused variables `r0', `sp', `toc',
+ `schain', `r12', `buf' and `labelno'.
+ (output_ascii): Const-ify a char*.
+ (rs6000_gen_section_name): Initialize variable `last_period'.
+ (rs6000_adjust_priority): Mark parameter `insn' with
+ ATTRIBUTE_UNUSED.
+ (rs6000_trampoline_template, rs6000_dll_import_ref,
+ rs6000_longcall_ref, rs6000_encode_section_info): Const-ify a char*.
-Fri Jun 19 22:55:14 1998 Jeffrey A Law (law@cygnus.com)
+ * rs6000.h (offsettable_mem_operand, optimization_options): Add
+ prototypes.
- * except.c (jumpif_rtx): Make static and add prototype.
- (jumpifnot_rtx): Likewise.
+ * rs6000.md (movdi, define_split): Cast a value to HOST_WIDE_INT
+ when comparing against one.
- * README.gnat: Add a build patch from Fred Fish.
+Thu Apr 8 19:20:18 1999 Jeffrey A Law (law@cygnus.com)
- * c-lang.c (GNU_xref_begin, GNU_xref_end): Deleted.
+ * expr.c (expand_expr, case ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF):
+ Do not try to optimize a aggregate address which has VOIDmode.
+ Mirrors March 23 change to expand_assignment.
- * Makefile.in (c-iterate.o): Depend on expr.h.
+ * flow.c (delete_unreachable_blocks): Do not require EDGE_FALLTHRU
+ for an edge when tidying an edge which connects consecutive basic
+ blocks.
-Fri Jun 19 20:38:34 1998 H.J. Lu (hjl@gnu.org)
+ * flow.c (can_delete_label_p): Do not convert a label into a
+ deleted label here.
- * except.h (emit_unwinder, end_eh_unwinder): Removed.
+ * cse.c (flush_hash_table): New function.
+ (cse_insn): Flush the hash table when we encounter a volatile asm.
+ (cse_basic_block): Use flush_hash_table instead of doing it
+ inline.
- * dwarfout.c (getpwd): Add prototype.
- (is_pseudo_reg, type_main_variant, is_tagged_type,
- is_redundant_typedef): New declaration.
- (output_decl): Add prototype for FUNC.
- (type_main_variant): Make it static.
- (is_tagged_type): Likewise.
- (is_redundant_typedef): Likewise.
+ * reload1.c (reload_cse_regs_1): Flush known register values if
+ we encounter a volatile asm.
- * expr.c (do_jump_by_parts_greater_rtx): Removed.
- (truthvalue_conversion): Likewise.
+ * loop.c (strength_reduce): Re-enable Joern's loop improvements.
- * c-iterate.c: Include "expr.h".
- (expand_expr): Use proper values when calling the function.
+Thu Apr 8 09:37:40 1999 Nick Clifton <nickc@cygnus.com>
- * explow.c (emit_stack_save): Add prototype for FCN.
- (emit_stack_restore): Likewise.
+ * config/arm/arm.c (arm_print_operand): Undo previous change -
+ always print large constants in decimal.
- * dwarf2out.c (getpwd): Add prototype.
+Thu Apr 8 10:22:23 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * dwarf2out.h (debug_dwarf, debug_dwarf_die): New declarations.
+ * configure.in (host_xm_file, build_xm_file): Include hwint.h.
+ Use case statements instead of "if test -a ... -a ... -a ..."
- * c-typeck.c (c_expand_asm_operands): Use proper values when calling
- expand_expr.
+ * machmode.h: Don't define HOST_WIDE_INT, etc. Wrap use of
+ HOST_WIDE_INT in #ifdef.
- * c-lex.c (yyprint): Add prototype.
- (check_newline, build_objc_string): Remove declaration.
+ * mips.h: Include hwint.h instead of providing definitions for
+ HOST_WIDE_INT, etc. Wrap uses of HOST_WIDE_INT in #ifdef.
- * c-tree.h (comptypes_record_hook): Removed.
- (finish_incomplete_decl): New prototype.
+Thu Apr 8 06:16:14 1999 John Wehle (john@feith.com)
- * alias.c (find_base_value): Add prototype.
- (true_dependence): Add prototype for function argument.
+ * i386.md (truncdfsf2, truncxfsf2,
+ truncxfdf2): Rewrite using a splitter.
- * c-aux-info.c (xmalloc): Remove declaration.
+Thu Apr 8 01:26:05 1999 Arg Haas (ahaas@neosoft.com)
+ Jeffrey A Law (law@cygnus.com)
-Fri Jun 19 20:23:05 1998 Robert Lipe <robertl@dgii.com>
+ * freebsd-elf.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Avoid ambiguous
+ else statement.
+ * gas.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
+ * linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
+ * openbsd.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
- * i386.c: Include system.h. Remove redundant includes.
- (optimization_options): Mark param 'size' with ATTRIBUTE_UNUSED.
- (i386_cc_probably_useless_p): Likewise for 'decl', 'attributes',
- 'identifier', 'args'.
- (i386_valid_type_attribute_p): Likewise for 'attributes'.
- (i386_comp_type_attribute_p): Likewise for 'type1', 'type2'.
- (function_arg_partial_nregs): Likewise for 'cum', 'mode', 'type',
- and 'named'.
- (symbolic_operand): Likewise for 'mode'.
- (call_insn_operand): Likewise.
- (expander_call_insn_operand): Likewise.
- (ix86_logical_operator): Likewise.
- (ix86_binary_operator_ok): Likewise.
- (emit_pic_move): Likewise.
- (VOIDmode_compare_op): Likewise.
- (is_mul): Likewise.
- (str_immediate_operand): Likewise.
- (ix86_uary_operator_ok): Likewise for 'code', 'mode', and 'operands'.yy
- (asm_output_function_prefix): Likewise for 'name'.
- (function_prologue): Likewise for 'file', and 'size'.
- (function_epilogue): Likewise.
+Wed Apr 7 22:40:19 1999 Jim Wilson <wilson@cygnus.com>
-1998-06-19 Jim Wilson <wilson@cygnus.com>
+ * i960/i960.c (i960_function_prologue): Don't save static chain
+ pointer.
+ * i960/i960.h (STACK_CHAIN_REGNUM): Change from r3 to g12.
+ (TRAMPOLINE_TEMPLATE): Likewise.
+ (FRAME_POINTER_REQUIRED): Check current_function_has_nonlocal_goto.
+ * i960/i960.md (nonlocal_goto): Rewrite.
- * loop.h (struct induction): Clarify comment for unrolled field.
- * unroll.c (find_splittable_givs): Move set of unrolled field
- after address validity check.
+Tue Apr 6 17:49:49 1999 Philip Blundell <pb@nexus.co.uk>
-Fri Jun 19 18:38:04 1998 Michael Meissner <meissner@cygnus.com>
+ * config/arm/lib1funcs.asm: Test for __ELF__ not __elf__.
- * config/fp-bit.c (INLINE): Only define if not already defined.
+Wed Apr 7 14:07:34 1999 Jeffrey A Law (law@cygnus.com)
-1998-06-19 Manfred Hollstein <manfred@s-direktnet.de>
+ * h8300.c (h8300_adjust_insn_length): Also avoid recognizing
+ ADDR_VEC and ADDR_DIFF_VEC insns.
- * Makefile.in (installdirs): Loop over directories in $(libsubdir)
- creating probably missing ones, instead of single if statements.
+ * h8300.c (h8300_adjust_insn_length): Avoid trying to recognize
+ USE, CLOBBER or SEQUENCE insns.
-Fri Jun 19 10:43:52 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * unroll.c (unroll_loop): For HAVE_cc0 machines, adjust copy_end_luid
+ to account for the uncopied insn that sets cc0 at the end of the loop.
- * c-common.c (truthvalue_conversion): Protect side effects in the
- expression when splitting a complex value.
- * fold-const.c (fold): Likewise.
+ * unroll.c (copy_loop_body): Always ensure at least two insns
+ are in the copied loop.
-Fri Jun 19 02:31:16 1998 Klaus Kaempf (kkaempf@progis.de)
+Wed Apr 7 14:52:18 1999 Catherine Moore <clm@cygnus.com>
- * cccp.c (hack_vms_include_specification): rewrite to handle
- '#include <dir/file.h>' correctly.
+ * config/mips/elf.h (MAKE_DECL_ONE_ONLY): Define.
+ (UNIQUE_SECTION_P): Define.
-Fri Jun 19 02:24:11 1998 H.J. Lu (hjl@gnu.org)
+1999-04-07 Bruce Korb <ddsinc09@ix.netcom.com>
- * config/i386/linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Defined.
+ * fixinc/inclhack.tpl & fixincl.tpl:
+ Remove dynamic content from generated files
-Fri Jun 19 02:10:10 1998 John Wehle (john@feith.com)
+Wed Apr 7 13:16:22 1999 John Wehle (john@feith.com)
- * i386.c (notice_update_cc): Integer conditional moves don't
- affect cc0.
+ * i386.c (output_move_memory): Remove.
+ * i386.h: Likewise.
- * i386.md (movsfcc, movdfcc, movxfcc): Use emit_store_flag
- to support LT, LE, GE, and GT signed integer comparisons.
- (movsfcc+1, movsfcc+2, movdfcc+1, movdfcc+2,
- movxfcc+1, movxfcc+2): Pattern doesn't match if the comparison
- is LT, LE, GE, or GT.
- (movdicc): Remove code resulting from an earlier patch which
- didn't apply correctly.
+ * i386.md (movsi, movhi, movstricthi, movqi, movstrictqi,
+ movsf, movdf, movxf, movdi): Check no_new_pseudos instead
+ of (reload_in_progress | reload_completed).
-Fri Jun 19 02:00:19 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+Wed Apr 7 03:16:45 1999 Richard Henderson <rth@cygnus.com>
- * reload1.c (reload_cse_regno_equal_p): If -ffloat-store, don't
- consider a MEM in FP mode as equal.
+ * alpha.c (reg_no_subreg_operand): New function.
+ * alpha.h (PREDICATE_CODES): Add it.
+ * alpha.md (floatdi?f patterns): Use it for op1.
-Fri Jun 19 01:02:17 1998 Jeffrey A Law (law@cygnus.com)
+ * alpha.c (alpha_end_function): Don't flag weak functions.
- * c-decl.c (duplicate_decls): Avoid setting TREE_ASM_WRITTEN for
- duplicate declarations of a function.
+Wed Apr 7 02:11:55 1999 Richard Henderson <rth@cygnus.com>
-Fri Jun 19 00:33:33 1998 H.J. Lu (hjl@gnu.org)
+ * expr.c (expand_builtin) [BUILT_IN_RETURN_ADDRESS]: Use
+ copy_to_mode_reg; don't force constants into a register.
- * config/float-i386.h: New.
+Tue Apr 6 22:55:25 1999 Richard Henderson <rth@cygnus.com>
- * configure.in (i[34567]86-*-linux-*): Set float_format to i386.
+ * toplev.c (compile_file): Typo flow_dump -> flow2_dump.
-Thu Jun 18 20:11:00 1998 Jim Wilson <wilson@cygnus.com>
+1999-04-06 Joseph S. Myers <jsm28@cam.ac.uk>
- * sched.c (schedule_insns): Use xmalloc not alloca for max_uid
- indexed arrays. Call free at the end of the function for them.
- * haifa-sched.c (schedule_insns): Likewise.
+ * pdp11.c (simple_memory_operand): Add default case in switch.
+ * pdp11.h (TARGET_SWITCHES): Add help strings.
+ (NOTICE_UPDATE_CC): Don't include excess argument to format.
+ (ASM_OUTPUT_DOUBLE_INT): Remove.
-Thu Jun 18 18:16:01 1998 Jim Wilson <wilson@cygnus.com>
+Tue Apr 6 22:09:40 1999 Richard Henderson <rth@cygnus.com>
- * dwarf2out.c (size_of_string): Do count backslashes.
+ * expr.c (expand_builtin_setjmp): Put setjmp return label on
+ nonlocal_goto_handler_labels for flow.
-Thu Jun 18 11:43:54 1998 Nick Clifton <nickc@cygnus.com>
+Tue Apr 6 22:05:21 1999 Jan Hubicka <hubicka@paru.cas.cz>
+ Richard Henderson <rth@cygnus.com>
- * config/arm/thumb.h (GO_IF_LEGITIMATE_ADDRESS): Disallow REG+REG
- addressing when one register is the frame pointer or stack
- pointer. Disallow REG+CONST addressing in HI mode.
+ * flow.c (verify_flow_info): New function.
+ (find_basic_blocks): Call it if ENABLE_CHECKING.
+ (merge_blocks): Don't merge if there are non-deletable labels.
+ * toplev.c (fatal_insn): Allow a printf-style arg list.
+ * toplev.h (fatal_insn): Update prototype.
-Thu Jun 18 17:30:39 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Tue Apr 6 16:18:58 1999 Jan Hubicka <hubicka@paru.cas.cz>
- * reload.c (find_reloads): Don't narrow scope of RELOAD_OTHER to
- RELOAD_FOR_INSN.
+ * flow.c (split_edge) update correctly flow graph, disable
+ EDGE_CRITICAL flag on the split edge, update NUSES for new label.
-Thu Jun 18 09:36:50 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Tue Apr 6 15:47:51 1999 Richard Henderson <rth@cygnus.com>
- * Makefile.in (c-lang.o): Depend on output.h.
+ * emit-rtl.c (gen_rtx_CONST_DOUBLE): Use XWINT not XINT.
+ Clear third and following slots, if they exist.
- * c-lang.c: Include output.h.
+Tue Apr 6 15:45:28 1999 Richard Henderson <rth@cygnus.com>
- * sparc.c (sparc_builtin_saveregs): Remove unused variable `fntype'.
+ * flow.c (create_basic_block): Make sure the bb note is in the block.
+ (can_delete_note_p): Rename from delete_note_p.
+ (delete_insn_chain): Preserve undeleteable labels too.
+ (tidy_fallthru_edge): Use next_real_insn instead of confusing
+ inline code.
- * except.c (expand_builtin_eh_stub): Likewise for variable `jump_to'.
+1999-04-06 Zack Weinberg <zack@rabi.columbia.edu>
- * genrecog.c (write_subroutine): When writing insn-recog.c, mark
- variables `insn', `pnum_clobbers', `x[0 .. max_depth]' and `tem'
- with ATTRIBUTE_UNUSED.
+ * cppexp.c (parse_charconst): Initialize c.
+ (cpp_parse_expr): Initialize rprio.
+ * cppfiles.c (merge_include_chains): Initialize prev.
+ (finclude): Set fp->line_base to fp->buf before returning.
+ * cpphash.c (macroexpand): Initialize token.
+ * cppspec.c (lang_specific_driver): Change suff to
+ const char *const *.
- * regmove.c (copy_src_to_dest): Make function static to match its
- prototype.
+1999-04-06 Zack Weinberg <zack@rabi.columbia.edu>
- * reload1.c Include hard-reg-set.h before rtl.h to get macro
- HARD_CONST. Include machmode.h before hard-reg-set.h.
+ * cppinit.c (install_predefs): Delete function.
+ (cpp_start_read): Don't call install_predefs.
+ (cpp_handle_option): Remove case 'u' and all refs to
+ opts->inhibit_predefs.
+ (print_help): Don't mention -undef.
+ (initialize_builtins): Define __HAVE_BUILTIN_SETJMP__, to
+ match cccp.
+ * cpplib.h (struct cpp_options): Remove inhibit_predefs
+ member.
- * rtl.h: Prototype `retry_global_alloc' and wrap with macro
- HARD_CONST to protect usage of typedef HARD_REG_SET.
+ * cccp.c (predefs): Delete variable.
+ (main): Remove case 'u' in argument parse loop,
+ 'inhibit_predefs' variable, and the code block that would
+ process CPP_PREDEFINES.
+ (initialize_builtins): Don't define __OBJC__, the driver will
+ do that.
- * tree.c: Prototype `_obstack_allocated_p'.
+ * gcc.c (default_compilers): Remove -undef from all specs that
+ invoke a C preprocessor.
+ * ch/lang-specs.h: Likewise.
+ * cp/lang-specs.h: Likewise.
+ * f/lang-specs.h: Likewise.
+ * objc/lang-specs.h: Likewise.
- * varasm.c: Wrap prototype of `asm_output_aligned_bss' in macro
- BSS_SECTION_ASM_OP.
+Mon Apr 5 11:55:31 1999 Donn Terry (donn@interix.com)
-Thu Jun 18 09:20:47 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * Makefile.in (SUBDIR_FLAGS_TO_PASS): Fix misapplied patch.
- * pa.c: Include system.h and toplev.h. Remove redundant code.
- (call_operand_address): Mark parameter `mode' with ATTRIBUTE_UNUSED.
- (symbolic_operand): Likewise.
- (symbolic_memory_operand): Likewise.
- (pic_label_operand): Likewise.
- (fp_reg_operand): Likewise.
- (pre_cint_operand): Likewise.
- (post_cint_operand): Likewise.
- (ireg_or_int5_operand): Likewise.
- (int5_operand): Likewise.
- (uint5_operand): Likewise.
- (int11_operand): Likewise.
- (uint32_operand): Likewise.
- (ior_operand): Likewise.
- (lhs_lshift_cint_operand): Likewise.
- (pc_or_label_operand): Likewise.
- (legitimize_pic_address): Likewise.
- (hppa_legitimize_address): Likewise for parameter `old'.
- (output_block_move): Likewise for parameter `size_is_constant'.
- (output_function_prologue): Likewise for parameter `size'.
- (output_function_epilogue): Likewise.
- (return_addr_rtx): Likewise for parameter `count'.
- (output_mul_insn): Likewise for parameter `unsignedp'.
- (hppa_builtin_saveregs): Likewise for parameter `arglist'.
- (output_bb): Likewise for parameter `operands'.
- (output_bvb): Likewise.
- (function_label_operand): Likewise for parameter `mode'.
- (plus_xor_ior_operator): Likewise.
- (shadd_operand): Likewise.
- (non_hard_reg_operand): Likewise.
- (eq_neq_comparison_operator): Likewise.
- (movb_comparison_operator): Likewise.
- (pa_combine_instructions): Likewise for parameter `insns'.
+Mon Apr 5 11:51:38 1999 Jeffrey A Law (law@cygnus.com)
- * pa.h: Add prototypes for functions `output_deferred_plabels',
- `override_options', `output_ascii', `output_function_prologue',
- `output_function_epilogue', `print_operand',
- `symbolic_expression_p', `reloc_needed', `compute_frame_size',
- `hppa_address_cost', `and_mask_p', `symbolic_memory_operand',
- `pa_adjust_cost', `pa_adjust_insn_length' and
- `secondary_reload_class'.
+ * m68k.md (movdf): Hide GPR sources & destinations from regclass.
-Wed Jun 17 22:28:48 1998 Jason Merrill <jason@yorick.cygnus.com>
+Mon Apr 5 09:54:42 1999 Jeff Law (law@cygnus.com)
- * configure.in: Don't turn on collect2 unconditionally.
+ * version.c: Bump for snapshot.
-Wed Jun 17 20:20:48 1998 Mark Mitchell <mark@markmitchell.com>
+Mon Apr 5 05:55:15 1999 Bruce Korb <ddsinc09@ix.netcom.com>
- * cse.c (cse_basic_block): Don't include NOTE insns in the count
- that is used to decide whether or not it is time to erase the
- equivalence table.
+ * fixincl.tpl: Separate "-e" from its argument, a la
+ the Sat Apr 3 17:05:13 1999 fix.
+ * genfixes: Ensure that the server shell is _NOT_ csh.
-Wed Jun 17 18:30:43 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+Mon Apr 5 03:52:30 1999 Jeff Law (law@cygnus.com)
- * rs6000/linux.h (JUMP_TABLES_IN_TEXT_SECTION): Define to zero.
+ * version.c: Bump for snapshot.
-Wed Jun 17 19:05:03 1998 John Carr <jfc@mit.edu>
+Mon Apr 5 04:47:14 1999 Jeffrey A Law (law@cygnus.com)
- * haifa-sched.c (haifa_classify_insn): TRAP_IF is risky.
- (sched_analyze_2): Allow scheduling TRAP_IF.
+ * i386.c (x86_double_with_add): Turn off for Pentium and PPro.
+ (small_shift_operand, output_ashlsi3): New functions.
+ * i386.h (small_shift_operand, output_ashlsi3): Declare.
+ * i386.md (ashlsi3): Simplify ahlsi3 patterns. Remove splitters
+ that are no longer needed.
- * reorg.c (mark_referenced_resources): Examine operands of TRAP_IF.
+Sun Apr 4 04:05:04 1999 Jeffrey A Law (law@cygnus.com)
- * rtl.h (TRAP_CODE): New macro.
+ * stmt.c (expand_loop_end): When copying the loop exit test,
+ do not walk into a nested loop.
- * rtl.def (TRAP_IF): Change second operand type to rtx.
+Sun Apr 4 00:14:54 1999 Jeffrey A Law (law@cygnus.com)
- * optabs.c (gen_cond_trap): New function.
- (init_traps): New function.
- (init_optabs): Call init_traps.
- * expr.h: Declare gen_cond_trap.
+ * fixinc/hackshell.tpl: Skip links to directories, to avoid
+ removing them.
+ * fixinc/inclhack.tpl: Likewise.
+ * fixinc/fixinc.sh, fixinc/fixincl.x, fixinc/inclhack.sh: Rebuilt.
- * jump.c (jump_optimize): Optimize jumps to and around traps.
+Sat Apr 3 23:46:13 1999 David Edelsohn <edelsohn@gnu.org>
- * sparc.md: Define trap instructions.
+ * rs6000.md (addsi3, iorsi3, xorsi3, adddi3, iordi3, xordi3,
+ movsi_got, movsi, movsf): Use no_new_pseudos.
+ * rs6000.c (rs6000_got_register): Likewise.
+ (offsettable_mem_opereand): Use || not |.
- * rs6000.md: Define trap instructions.
- * rs6000.c (print_operand): New code 'V' for trap condition.
- (trap_comparison_operator): New function.
+Sat Apr 3 22:02:56 1999 Jeffrey A Law (law@cygnus.com)
- * m88k.md: Update use of TRAP_IF.
+ * acconfig.h (ENABLE_CHECKING): Remove redundant #undef.
+ * config.in: Rebuilt.
- * tree.h (enum built_in_function): New function code BUILT_IN_TRAP.
- * c-decl.c (init_decl_processing): New builtin __builtin_trap.
- * expr.c (expand_builtin): Handle BUILT_IN_TRAP.
+Sat Apr 3 16:22:59 1999 Toshiyasu Morita (tm@netcom.com)
- * expr.c (expand_builtin): Error if __builtin_longjmp second argument
- is not 1.
+ * gcc.texi: Add info on regmove pass.
-Wed Jun 17 15:20:00 PDT 1998 Catherine Moore <clm@cygnus.com>
+ * regmove.c (fixup_match_1): Consistently evaluate
+ HAVE_POST_INCREMENT and HAVE_POST_DECREMENT.
- * reload1.c (spill_hard_reg): Check mode of register when
- spilling from scratch_list.
-
-Wed Jun 17 16:25:38 EDT 1998 Andrew MacLeod (amacleod@cygnus.com)
+Sat Apr 3 19:21:05 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * except.c (add_new_handler): fix bug in finding last region handler.
- * libgcc2.c (find_exception_handler): Pass exception table pointer
- to runtime type matcher, not the match info field.
+ * configure.in (DEFAULT_LINKER, DEFAULT_ASSEMBLER): Use grep
+ instead of test and sed to check whether they're GNU programs.
+ * configure: Rebuilt.
-Wed Jun 17 15:57:48 EDT 1998 Andrew MacLeod (amacleod@cygnus.com)
+Sat Apr 3 17:57:35 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * eh-common.h (struct eh_context): Add comment for hidden use of
- field dynamic_handler_chain.
- * except.c (get_dynamic_handler_chain): Comment on, and use the
- correct offset of the dynamic_handler_chain field.
+ * Makefile.in (install-headers-tar, install-headers-cpio): Avoid
+ problems with CDPATH.
+ Reported by Ralf Canis <canis@bigfoot.com>
-1998-06-17 12:46:56 1998 Jim Wilson <wilson@cygnus.com>
+Sat Apr 3 13:50:16 1999 Jeffrey A Law (law@cygnus.com)
- * mips/iris6.h (LINK_SPEC): Add -woff 131.
+ * fixinc.x86-linux-gnu: Deleted.
-1998-06-17 Jason Merrill <jason@yorick.cygnus.com>
+Sat Apr 3 17:05:13 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * dwarf2out.c: Disable EH_FRAME_SECTION if we don't have .init.
+ * inclhack.tpl: Insert spaces between `sed -e' and '...'.
+ Reported by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * fixinc/fixincl.sh, fixinc/fixincl.x, fixinc/inclhack.sh: Regen.
- * configure.in: Don't disable collect2 when we have GNU ld.
+Sat Apr 3 14:54:46 1999 Craig Burley <craig@jcb-sc.com>
-Wed Jun 17 08:38:13 1998 Jeffrey A Law (law@cygnus.com)
+ * tree.def (BLOCK): Fix typo in comment.
- * fold-const.c (make_range): Do not widen the type of the expression.
+Sat Apr 3 00:53:29 1999 John Wehle (john@feith.com)
- * expr.c (check_max_integer_computation_mode): New function.
- (expand_expr): Avoid integer computations in modes wider than
- MAX_INTEGER_COMPUTATION_MODE.
- * fold-const.c (fold): Likewise.
- * tree.h (check_max_integer_computation_mode): Declare.
- * tm.texi (MAX_INTEGER_COMPUTATION_MODE): Document it.
+ * i386.md (floatsisf2, floatdisf2, floatsidf2, floatdidf2,
+ floatsixf2, floatdixf2): Rewrite using a splitter.
- * configure.in (nm): Make a link to "nm" in the build tree too.
+Fri Apr 2 17:36:10 1999 Nick Clifton <nickc@cygnus.com>
- * mn10300.md (andsi3): Fix typo.
+ * config/arm/arm.c (arm_print_operand): Print large constants in
+ hex rather than decimal.
-Tue Jun 16 22:58:40 1998 Richard Henderson <rth@cygnus.com>
+Fri Apr 2 17:23:58 1999 Nick Clifton <nickc@cygnus.com>
- * reload1.c (reload_cse_regs): Call bzero instead of looping.
+ * print-rtl.c (print_rtx): Use both HOST_WIDE_INT_PRINT_DEC
+ and HOST_WIDE_INT_PRINT_HEX to display constants.
-Tue Jun 16 18:30:35 1998 Jim Wilson <wilson@cygnus.com>
+1999-04-02 Zack Weinberg <zack@rabi.columbia.edu>
- * dwarf2out.c (stripattributes): Prepend '*' to the section name.
+ * config/i386/i386.h: Document all TARGET_SWITCHES or add
+ explicit null initializer.
-Tue Jun 16 16:49:26 1998 Richard Henderson <rth@cygnus.com>
+ * config/i386/cygwin.h: Document all SUBTARGET_SWITCHES.
+ * config/i386/dgux.h: Likewise.
+ * config/i386/osf1elf.h: Likewise.
+ * config/i386/win32.h: Likewise.
+ * config/i386/osfrose.h: Likewise. Drop obsolete -mno-ident option.
- * alpha.c (alpha_expand_prologue, alpha_expand_epilogue): New fns.
- (output_prologue, output_epilogue): Merge VMS and OSF versions;
- Remove anything related to the actual code generation.
- (output_end_prologue): New function.
- (alpha_sa_mask, alpha_sa_size): Merge VMS and OSF versions.
- (alpha_does_function_need_gp): Return false for VMS.
- (alpha_function_needs_gp): Make static.
- (add_long_const): Delete.
- (summarize_insn): Don't assume a SUBREG is of a REG.
- Prototype all static functions. Rename VMS-specific global
- variables vms_*.
- * alpha.h (TARGET_CAN_FAULT_IN_PROLOGUE): Default to 0.
- (FUNCTION_BOUNDARY): Align to cache line.
- (LOOP_ALIGN, ALIGN_LABEL_AFTER_BARRIER): Align to octaword.
- (FUNCTION_END_PROLOGUE): New macro.
- * alpha.md (attribute length): New. Mark all insns.
- (return_internal, prologue_stack_probe_loop) New patterns.
- (prologue, init_fp, epilogue): New patterns.
- Disable peepholes.
- * linux.h (TARGET_CAN_FAULT_IN_PROLOGUE): Define.
+Fri Apr 2 17:49:44 1999 Toshiyasu Morita <tm@netcom.com>
-Tue Jun 16 17:36:35 1998 Dave Brolley <brolley@cygnus.com>
+ * regmove.c (fixup_match_1): Remove now useless if (0).
- * toplev.c (lang_options): Add -trigraphs option for cpplib.
+Sat Apr 3 11:37:20 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Tue Jun 16 23:33:24 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * tm.texi (USE_LOAD_POST_DECREMENT, USE_LOAD_PRE_DECREMENT,
+ USE_STORE_POST_DECREMENT, USE_STORE_PRE_DECREMENT): Document.
+ (USE_LOAD_POST_INCREMENT, USE_LOAD_PRE_INCREMENT,
+ USE_STORE_POST_INCREMENT, USE_STORE_PRE_INCREMENT): Fix documentation.
- * reload1.c (reload_reg_free_before_p): RELOAD_FOR_OUTADDR_ADDRESS
- is earlier than RELOAD_FOR_OUTPUT_ADDRESS; RELOAD_FOR_INPADDR_ADDRESS
- is earlier than RELOAD_FOR_INPUT_ADDRESS.
+ * rtl.h (USE_LOAD_POST_DECREMENT, USE_LOAD_PRE_DECREMENT,
+ USE_STORE_POST_DECREMENT, USE_STORE_PRE_DECREMENT,
+ USE_LOAD_POST_INCREMENT, USE_LOAD_PRE_INCREMENT,
+ USE_STORE_POST_INCREMENT, USE_STORE_PRE_INCREMENT): Provide default
+ definition.
-Tue Jun 16 13:15:16 1998 Jim Wilson <wilson@cygnus.com>
+ * expr.c (USE_LOAD_POST_INCREMENT, USE_LOAD_PRE_INCREMENT,
+ USE_STORE_POST_INCREMENT, USE_STORE_PRE_INCREMENT): Delete default
+ definition.
- * libgcc1-test.c (memcpy): Define.
+Fri Apr 2 16:03:05 1999 Jeffrey A Law (law@cygnus.com)
-Tue Jun 16 13:44:02 1998 Michael Meissner <meissner@cygnus.com>
+ * fixinc.dgux, fixinc.interix, fixinc.irix, fixinc.ptx: Deleted.
+ * fixinc.sco, fixinc.svr4, fixinc.winnt, fixinc.wrap: Likewise.
- * genattrtab.c (struct attr_desc): Change int flags to bit
- fields. Add bit fields for this being function_units_used
- or *_blockage_range attributes.
- (write_unit_name): New function to print a function unit name
- given unit #.
- (expand_units): Indicate whether this is function_units_used or
- *_blockage_range attributes.
- (write_toplevel_expr): Print function_units_used and
- *_blockage_range attributes in a more friendly fashion.
- (make_internal_attr): Indicate whether this attribute is either
- function_units_used or *_blockage_range.
+Fri Apr 2 15:46:25 1999 Donn Terry (donn@interix.com)
-Mon Jun 15 17:06:43 1998 Michael Meissner <meissner@cygnus.com>
- Jim Wilson <wilson@cygnus.com>
+ * configure.in: Set and substitute quoted_cc_set_by_configure.
+ * configure: Rebuilt.
+ * Makefile.in (SUBDIR_FLAGS_TO_PASS): Fix quoting problem with ``.
- * regmove.c (copy_src_to_dest): Do not copy src to dest if either
- the source or destination is special.
+Fri Apr 2 14:35:45 1999 Stan Cox <scox@cygnus.com>
+
+ * config/i386/cygwin.h (CPP_SPEC): Use mingw_include_path instead
+ of a hardcoded path for -mno-cygwin.
+ (mingw_include_path): New.
+
+1999-04-02 Joseph S. Myers <jsm28@cam.ac.uk>
-Mon Jun 15 13:20:33 1998 Jim Wilson <wilson@cygnus.com>
+ * pdp11.c: Include "recog.h".
+ (output_function_prologue): Remove unused variables `nregs', `i',
+ `offset'.
+ (output_function_epilogue): Remove unused variables
+ `may_call_alloca', `nregs', `regno', `adjust_fp'.
+ (output_ascii): Mark as returning void.
+ (print_operand_address: Likewise.
+ (simple_memory_operand): Remove unused variables `plus0', `plus1',
+ `offset'.
+ * pdp11.h: Declare functions `arith_operand',
+ `const_immediate_operand', `expand_shift_operand',
+ `legitimate_address_p', `notice_update_cc_on_set', `output_ascii',
+ `output_function_epilogue', `output_function_prologue',
+ `print_operand_address', `register_move_cost',
+ `simple_memory_operand'.
+ (HARD_REGNO_MODE_OK): Parenthesize `REGNO' arg.
+ (REGNO_REG_CLASS): Likewise.
+ * pdp11.md: Add explicit `int' to `static count' (in two places).
+ (addhi3): Add explicit braces to avoid ambiguous else.
+ (addqi3): Likewise.
+ (ashlhi3): Likewise.
- * c-decl.c (shadow_tag_warned): Use specs not declspecs in for loop.
+Fri Apr 2 14:17:10 1999 Jerry James <jerry@cs.ucsb.edu>
-Mon Jun 15 07:16:29 PDT 1998 Jeff Law (law@cygnus.com)
+ * gcc/invoke.texi: Add documentation for additional supported
+ MIPS CPU types, options -mips16 and -mentry, and ABI and ISA
+ defaults.
- * version.c: Bump for snapshot.
+Fri Apr 2 14:12:06 1999 John Wehle (john@feith.com)
-Sat Jun 13 13:10:40 1998 Krister Walfridsson <cato@df.lth.se>
-
- * config/sparc/netbsd.h (DEFAULT_PCC_STRUCT_RETURN): Undefine before
- redefining it.
-
-Fri Jun 12 18:06:45 1998 Doug Evans <devans@egcs.cygnus.com>
-
- * m32r/m32r.h (STARTFILE_SPEC): Delete crtsysc.o.
- (ENDFILE_SPEC): Add -lgloss.
-
-Fri Jun 12 14:57:59 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * mips.c (small_int): Mark parameter `mode' with ATTRIBUTE_UNUSED.
- (large_int): Likewise.
- (pc_or_label_operand): Likewise.
- (call_insn_operand): Likewise.
- (consttable_operand): Likewise.
- (m16_uimm3_b): Likewise.
- (m16_simm4_1): Likewise.
- (m16_nsimm4_1): Likewise.
- (m16_simm5_1): Likewise.
- (m16_nsimm5_1): Likewise.
- (m16_uimm5_4): Likewise.
- (m16_nuimm5_4): Likewise.
- (m16_simm8_1): Likewise.
- (m16_nsimm8_1): Likewise.
- (m16_uimm8_1): Likewise.
- (m16_nuimm8_1): Likewise.
- (m16_uimm8_m1_1): Likewise.
- (m16_uimm8_4): Likewise.
- (m16_nuimm8_4): Likewise.
- (m16_simm8_8): Likewise.
- (m16_nsimm8_8): Likewise.
- (m16_usym8_4): Likewise.
- (m16_usym5_4): Likewise.
- (mips_move_1word): Change type of variable `i' from int to size_t.
- (mips_move_2words): Likewise.
- (output_block_move): Mark parameter `libname' with ATTRIBUTE_UNUSED.
- (function_arg_advance): Use HOST_PTR_PRINTF to print an address.
- (function_arg): Likewise.
- (function_arg_partial_nregs): Mark parameter `named' with
- ATTRIBUTE_UNUSED.
- (override_options): Use ISDIGIT instead of isdigit.
- (mips_output_external): Mark parameter `file' with ATTRIBUTE_UNUSED.
- (final_prescan_insn): Likewise for parameters `opvec' and `noperands'.
- (save_restore_insns): Cast HOST_WIDE_INT arguments passed to
- function `fatal' to long before printing. Use
- HOST_WIDE_INT_PRINT_DEC in fprintf. Both changes done several
- times in this function.
- (function_prologue): Mark parameter `size' with ATTRIBUTE_UNUSED.
- (function_epilogue): Likewise for parameters `file' and `size'.
- Print an int with "%d" not "%ld".
- (mips_select_rtx_section): Mark parameter `x' with ATTRIBUTE_UNUSED.
- (mips_function_value): Likewise for parameter `func'.
- (function_arg_pass_by_reference): Likewise for parameters `cum'
- and `named'.
- (extend_operator): Likewise for parameter `mode'
- (highpart_shift_operator): Likewise.
+ * i386.md: Delete floating point compare, add, subtract,
+ multiply, and divide patterns which allowed integer
+ operands.
+ * i386.c (output_387_binary_op): Delete unused code.
+ (output_float_compare): Likewise.
- * mips.md (mul_acc_si): Remove unused variable `macc'.
+Fri Apr 2 11:53:37 1999 John Wehle (john@feith.com)
-Fri Jun 12 09:33:44 1998 Richard Henderson <rth@cygnus.com>
+ * i386.md (movsf+1, movdf+1, movxf+1): Update constraints
+ so that SECONDARY_MEMORY_RELOAD is used. Remove dead code.
- * fold-const.c (fold): Revert last change. It breaks constant
- expressions somehow.
+1999-04-02 Bruce Korb <ddsinc09@ix.netcom.com>
-Fri Jun 12 10:23:36 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * fixinc/mkfixinc.sh: Added support for x86-interix.
+ * fixinc/fixinc.interix: Fixincludes script, slight changes
+ from ./fixinc.interix. Untested (needs interix box).
+ * fixinc/inclhack.def:
+ Complete the change to the 'fixinc.tmp' file.
+ Fixed regex for finding C++ headers.
+ * fixincl.x, fixincl.sh, inclhack.sh: Regenerate.
- * expr.c (do_jump, case EQ_EXPR, NE_EXPR): When comparing complex
- prevent operands from being evaluated twice.
+Fri Apr 2 11:36:12 1999 Jan Hubicka (hubicka@paru.cas.cz)
-Fri Jun 12 00:50:27 1998 Sergey Okhapkin <sos@prospect.com.ru>
+ * i386.c (print_operand_address, case REG): Do not use ESI addressing
+ mode for the K6.
- * toplev.c (lang_options): Add -remap as a preprocessor option.
+ * i386.c (print_operand_address, case MULT): Use more efficient
+ encoding (mult (reg) (const_int 2)).
-Fri Jun 12 00:30:32 1998 John Wehle (john@feith.com)
+Thu Apr 1 17:01:50 1999 Richard Henderson <rth@cygnus.com>
- * i386.md (cmpsi_1, cmphi_1, cmpqi_1): Remove code
- which set CC_REVERSED since reload should ensure that
- the operands are already the correct type.
+ Move over patch from Bernd Schmidt from GC branch:
+ * emit-rtl.c (gen_rtx_CONST_DOUBLE): New function.
+ (gen_rtx): Call it. Tidy cases.
+ * rtl.h (gen_rtx_CONST_DOUBLE): Prototype it.
+ * gengenrtl.c: Add commentary.
+ (special_rtx): Also match CONST_DOUBLE.
+ (gencode): Emit call to memset instead of bzero.
-Thu Jun 11 17:14:15 1998 Jim Wilson <wilson@cygnus.com>
+Fri Apr 2 12:58:26 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * except.c (expand_builtin_eh_stub): Call emit_move_insn rather than
- calling gen_rtx_SET.
+ * config/c4x/c4x.md (ashlhi3, lshrhi3, ashrhi3): Force operand 1
+ into a register if shift count not constant.
+ (ashlhi3_reg, lshrhi3_reg, ashrhi3_reg): Ensure that operand 1
+ is a register.
-Thu Jun 11 18:45:49 1998 David Edelsohn <edelsohn@mhpcc.edu>
+Fri Apr 2 12:19:17 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * config/rs6000/x-aix43 (AR): Delete.
- (AR_FOR_TARGET_FLAGS): Add -X32_64 here.
+ * config/c4x/c4x.md (*db): Enable pattern if TARGET_LOOP_UNSIGNED
+ is non-zero.
+ (movstrqi_small, movstrqi_large, *cmpstrqi): Add + modifier to address
+ register constraints.
+ (*movhi_clobber+1): Modify splitter pattern to handle destination
+ register that is used in the source address.
+ (*xorhi3_clobber): Replace AND with XOR in call to legitimize_operands.
-Thu Jun 11 16:19:17 1998 David W. Schuler <schuld@btv.ibm.com>
+Fri Apr 2 12:16:15 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * config/i386/aix386ng.h (CPP_SPEC): Remove extraneous quote.
+ * config/c4x/c4x.h: Added more comments.
-Thu Jun 11 12:40:27 1998 Jim Wilson <wilson@cygnus.com>
+Fri Apr 2 11:58:22 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * mips.c (override_options): Replace word_mode with explicit
- TARGET_64BIT check.
+ * config/c4x/c4x.c (c4x_emit_move_sequence): Force invalid QImode
+ constants into memory if we get called directly from gen_move_insn
+ rather than emit_move_insn.
+ (c4x_legitimize_address): Fix up LABEL_REF addresses.
-Thu Jun 11 14:50:02 1998 Michael Meissner <meissner@cygnus.com>
+Thu Apr 1 12:04:05 1999 Jim Wilson <wilson@cygnus.com>
- * regmove.c (regmove_optimize): If we can't replace the
- destination in an insn that sets the source, generate an explicit
- move of the source to the destination.
- (copy_src_to_dest): New function.
- (toplevel): Include basic-block.h
+ * expr.c (store_field): When check direct_store, assume all complex
+ modes can be directly stored.
- * Makefile.in (regmove.o): Add basic-block.h dependencies.
+1999-04-01 Bruce Korb <ddsinc09@ix.netcom.com>
-Thu Jun 11 10:30:09 1998 Dave Brolley <brolley@cygnus.com>
+ * fixinc/genfixes: New shell script that runs autogen
+ to create the generated files.
- * toplev.c (lang_options): Add missing options (nostdinc, idirafter).
+1999-04-01 Manfred Hollstein <manfred@s-direktnet.de>
-Wed Jun 10 23:39:32 1998 Mark Mitchell <mark@markmitchell.com>
+ * Makefile.in (cppmain$(exeext)): Depend on intl.o. Link in intl.o.
- * rtl.h (rtx_def): Improve documentation.
- (MEM_IN_STRUCT_P): Likewise.
+Thu Apr 1 03:48:34 1999 H.J. Lu (hjl@gnu.org)
-Wed Jun 10 23:23:17 1998 Graham <grahams@rcp.co.uk>
+ * i386.c (output_fp_conditional_move): Abort for LT, LE, GE, and GT
+ signed integer comparisons.
- * c-decl.c (start_decl): Correct test for -Wmain.
+ * i386.c (output_int_conditional_move): Use "enum rtx_code" for code
+ type.
- * c-decl.c (grokdeclarator): Remove unused variable "last".
+ * i386.c (notice_update_cc): No need to check the INT mode for
+ conditional moves since FLOAT conditional moves don't affect cc0.
-Wed Jun 10 14:52:27 1998 Jim Wilson <wilson@cygnus.com>
+Thu Apr 1 02:17:18 1999 Jeffrey A Law (law@cygnus.com)
- * expr.c (expand_builtin_setjmp): Store const1_rtx in target.
- (expand_builtin_longjmp): Abort if value isn't const1_rtx.
- Delete code storing value in static_chain_rtx.
- (expand_builtin, case BUILT_IN_LONGJMP): Pass NULL_RTX for target
- to second expand_expr call.
+ * fixinc/inclhack.def (zzz_ki_syscalls, zzz_time): Fix trigger
+ string to only match on hpux11.
+ * fixinc/fixincl.x, fixinc/inclhack.sh, fixinc/fixinc.sh: Rebuilt.
-Wed Jun 10 13:08:41 1998 Mark Mitchell <mark@markmitchell.com>
+Thu Apr 1 01:09:27 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * mips/mips.c: Remove -mabi=o32 and -mabi=n64.
+ * fixinc/hackshell.tpl: Complete transition to fixinc.tmp.
+ * fixinc/inclhack.sh: Rebuilt.
-Wed Jun 10 13:41:23 1998 Dave Brolley <brolley@cygnus.com>
+ * fixinc/inclhack.def: Fix typos in c_asm.h fix.
+ * fixinc/fixincl.x, fixinc/inclhack.sh, fixinc/fixinc.sh: Rebuilt.
- * cppmain.c (fatal): New function.
- * configure.in (cpp_main): New configuration variable.
- * configure: Regenerated.
- * Makefile.in (CCCP): Use a configuration variable to select basex
- for cccp.
- (cppmain$(exeext)): Add @extra_cpp_objs@.
+Wed Mar 31 17:20:11 1999 Jeffrey A Law (law@cygnus.com)
-Wed Jun 10 13:07:02 1998 Dave Brolley <brolley@cygnus.com>
+ * toplev.c (rest_of_compilation): Allow dbr_schedule to write to
+ the dump file too.
- * objc/objc-act.c: Add cpplib declarations.
- (lang_decode_option): Initialize cpplib if necessary.
- (lang_decode_option): New argc/argv interface.
- * tree.h (lang_decode_option): New argc/argv interface.
- * toplev.c (lang_options): Add cpp options.
- (main): New interface for lang_decode_option.
- * gcc.c (default_compilers): Don't call cpp for a cpplib-enabled C compiler
- unless -E, -M or -MM is specified.
- * cpplib.h (cpp_handle_option): New function.
- * cpplib.c (cpp_handle_option): New function.
- (cpp_handle_options): Now calls cpp_handle_option.
- * c-tree.h (c_decode_option): New argc/argv interface.
- * c-lex.c (init_parse): cpplib now initialized in c_decode_option.
- * c-lang.c (lang_decode_option): New argc/argv interface.
- * c-decl.c: Add cpplib declarations.
- (c_decode_option): New argc/argv interface.
- (c_decode_option): Call cpp_handle_option.
- (c_decode_option): Now returns number of strings processed.
+Wed Mar 31 12:32:43 1999 Richard Henderson <rth@cygnus.com>
-Wed Jun 10 09:47:13 1998 Richard Earnshaw (rearnsha@arm.com)
+ * flow.c (find_basic_blocks): New argument `do_cleanup'.
+ Conditionally call delete_unreachable_blocks.
+ (free_basic_block_vars): Zero ENTRY/EXIT data.
+ (allocate_for_life_analysis): Kill. Split into...
+ (allocate_bb_life_data, allocate_reg_life_data): ... new functions.
+ (life_analysis_1): Update.
+ * gcse.c (gcse_main): Update find_basic_blocks call.
+ * toplev.c (rest_of_compilation): Likewise.
+ * stupid.c (stupid_life_analysis): Update life data calls.
+ * rtl.h, output.h: Update prototypes.
- * unroll.c (verify_addresses): Use validate_replace_rtx to undo the
- changes. Abort if the undo fails.
+Wed Mar 31 12:10:00 1999 Bruce Korb <ddsinc09@ix.netcom.com>
-1998-06-10 Vladimir N. Makarov <vmakarov@cygnus.com>
+ * inclhack.def (several): Added spaces in tests to ensure
+ correct shell syntax. Added c_asm.h fix from fixincludes.
+ Also corrected the corrected fix to C++ comments :-}
- * config/rs6000/rs6000.c (output_prolog): Change locations and
- directions of saving and restoring arguments of main on the stack.
+ * inclhack.tpl: Changed method of traversing symlink trees
+ so that file name matching will work correctly.
-Wed Jun 10 08:56:27 1998 John Carr <jfc@mit.edu>
+ * fixincl.c, hackshell.tpl: Fallout from above.
+ * fixincl.x, inclhack.sh, fixincl.sh: Rebuilt.
- * reload1.c (reload_cse_simplify_operands): Do not call gen_rtx_REG
- for each alternative. Do not replace a CONST_INT with a REG unless
- the reg is cheaper.
+Tue Mar 30 10:43:49 1999 Philip Blundell <pb@nexus.co.uk>
-Wed Jun 10 02:11:55 1998 Jeffrey A Law (law@cygnus.com)
+ * config/arm/aout.h (DBX_DEBUGGING_INFO): Avoid redefinition if
+ dbxelf.h was previously included.
+ (CPP_APCS_PC_DEFAULT_SPEC): No need to undefine.
- * decl.c (init_decl_processing): Fix typo.
+ * config/arm/linux-elf.h (FP_DEFAULT): Correctly override the
+ definition from arm.h.
- * mips.c (gpr_mode): New variable.
- (override_options): Initialize gpr_mode.
- (compute_frame_size): Use "gpr_mode" instead of "word_mode" to
- determine size and offset of general purpose registers save slots.
- (save_restore_insns, mips_expand_prologue): Similarly.
+Wed Mar 31 10:33:37 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * reload.c (find_reloads_toplev): Use gen_lowpart common to convert
- between constant representations when we have (SUBREG (REG)) with
- REG equivalent to a constant.
+ * Makefile.in (c-gperf.h): Generate using gperf language 'C', not
+ 'KR-C', so gperf uses the `const' keyword on strings.
-Wed Jun 10 01:39:00 1998 Juha Sarlin <juha@c3l.tyreso.se>
+ * c-parse.gperf (resword): Const-ify a char*.
- * h8300.c (get_shift_alg): Add special cases for shifts of 8 and 24.
+Wed Mar 31 01:49:31 1999 Ian Lance Taylor <ian@zembu.com>
-Tue Jun 9 22:05:34 1998 Richard Henderson <rth@cygnus.com>
+ * t-rtems (LIMITS_H_TEST, LIBGCC2_INCLUDES): Define.
- * fold-const.c (fold): Even with otherwise constant trees, look for
- opportunities to combine integer constants.
+Wed Mar 31 00:50:48 1999 Jeffrey A Law (law@cygnus.com)
-Wed Jun 3 23:41:24 EDT 1998 John Wehle (john@feith.com)
+ * system.h (STDERR_FILENO): Fix typo.
- * i386.c (notice_update_cc): Clear cc_status.value2 in the
- case of UNSPEC 5 (bsf).
+ * inclhack.def (bool): Also fix bogus bool in curses_colr/curses.h.
+ * fixincl.x, inclhack.sh, fixincl.sh: Rebuilt.
- * i386.md (movsfcc, movdfcc, movxfcc): The floating point
- conditional move instructions don't support signed integer
- comparisons.
+Tue Mar 30 20:51:40 1999 Mark Mitchell <mark@codesourcery.com>
-Tue Jun 9 14:31:19 1998 Nick Clifton <nickc@cygnus.com>
+ * alias.c (alias_set_compare): Remove.
+ (record_alias_subset): Use splay_tree_compare_ints instead of
+ alias_set_compare.
+ (init_alias_once): Likewise.
+ * cse.c: Include splay-tree.h.
+ (reg_qty): Remove.
+ (reg_tick): Likewise.
+ (reg_table): Likewise.
+ (cse_reg_info): New structure.
+ (cse_reg_info_free_list): New variable.
+ (cse_reg_info_tree): Likewise.
+ (cached_regno): Likewise.
+ (cached_cse_reg_info): Likewise.
+ (all_minus_one): Remove.
+ (consec_ints): Likewise.
+ (GET_CSE_REG_INFO): New macro.
+ (REG_TICK): Likewise. Use throughout instead of reg_tick.
+ (REG_IN_TABLE): Likewise. Use throughout instead of reg_in_table.
+ (REG_QTY): Likewise. Use throughout instead of reg_qty.
+ (get_cse_reg_info): New function.
+ (free_cse_reg_info): Likewise.
+ (new_basic_block): Reinitialize cse_reg_info_tree instead of
+ reg_tick, all_minus_one, and consec_ints.
+ * Makefile.in (cse.o): Depend on splay-tree.h
- * config/v850/t-v850 (TCFLAGS): Add assembler options to warn of
- overlfows.
+Tue Mar 30 13:19:36 1999 Jason Merrill <jason@yorick.cygnus.com>
- * config/v850/lib1funcs.asm (__return_interrupt): Use 'addi
- 16,sp,sp' ratehr than 'add 16,sp'. Patch courtesy of Biomedin
- <glctr@abc.it>.
+ * libgcc2.c (throw_helper): Just return the SP offset, rather than
+ a whole udata. Include args_size in the offset.
+ (__throw, __rethrow): Adjust.
-Tue Jun 9 16:23:13 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Tue Mar 30 11:39:27 1999 Craig Burley <craig@jcb-sc.com>
- * except.c (expand_start_catch): Rename to start_catch_handler.
- (expand_end_catch): Delete function.
- (expand_end_all_catch): Remove catch status that expand_end_catch
- use to do.
- * except.h (expand_start_catch): Rename prototype.
- (expand_end_catch): Delete prototype.
+ * extend.texi (Extended Asm): Delete spurious `b' before
+ `@end example', which was confusing texi2html.
-Tue Jun 9 12:57:32 1998 Mark Mitchell <mark@markmitchell.com>
+Tue Mar 30 00:26:34 1999 Jason Merrill <jason@yorick.cygnus.com>
- * invoke.texi: Add documentation for -mips4 and -mabi=*.
+ * dwarf2out.c (output_line_info): Don't emit redundant info.
+ Do start a new row if the file changes and the line # doesn't.
-Tue Jun 9 12:12:34 1998 Klaus Kaempf (kkaempf@progis.de)
+Mon Mar 29 15:48:39 1999 Jason Merrill <jason@yorick.cygnus.com>
- * alpha/vms.h (EXTRA_SECTIONS): Add in_ctors and in_dtors.
- (EXTRA_SECTION_FUNCTIONS): Add ctors_section and dtors_section.
- (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): Define.
+ * invoke.texi (Invoking G++, C++ Dialect Options): Update.
-Tue Jun 9 12:10:27 1998 John Carr <jfc@mit.edu>
+Mon Mar 29 15:05:39 1999 Richard Henderson <rth@cygnus.com>
- * haifa-sched.c (update_flow_info): Use UNITS_PER_WORD, not MOVE_MAX,
- as the threshold to permit splitting memory operations.
+ * except.c (start_dynamic_handler): Force jmp_buf address to
+ and operand before moving to memory.
-Tue Jun 9 12:36:16 1998 Jeffrey A Law (law@cygnus.com)
+Mon Mar 29 15:11:10 1999 Craig Burley <craig@jcb-sc.com>
- * mips.c (gpr_mode): New variable.
- (override_options): Initialize gpr_mode.
- (compute_frame_size): Use "gpr_mode" instead of "word_mode" to
- determine size and offset of general purpose registers save slots.
- (save_restore_insns, mips_expand_prologue): Similarly.
+ * invoke.texi (Code Gen Options): Attempt to clarify
+ -fcheck-memory-usage. Minor edits to -fprefix-function-name.
- * Makefile.in (LIB2FUNCS_EH): Define. Just "_eh" for now.
- (LIBGCC2_CFLAGS): Remove -fexceptions.
- (LIB2FUNCS): Remove "_eh".
- (libgcc2.a): Iterate over LIB2FUNCS_EH and build everything in
- it with -fexceptions.
+Mon Mar 29 20:52:47 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * Makefile.in (local-alloc.o): Depend on insn-attr.h.
- * local-alloc.c (block_alloc): Avoid creating false
- dependencies for targets which use instruction scheduling.
+ * loop.c (maybe_eliminate_biv): For libcalls that set a giv, skip to
+ end of libcall.
-Tue Jun 9 02:40:49 1998 Richard Henderson <rth@cygnus.com>
+Mon Mar 29 20:35:49 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * mips/elf.h (ASM_DECLARE_OBJECT_NAME): Define.
- (ASM_FINISH_DECLARE_OBJECT): Define;
- * mips/elf64.h: Likewise.
+ * sh.md (mulsi3): Tag an extra REG_EQUAL note to the middle insn.
-Tue Jun 9 01:08:47 1998 Richard Henderson <rth@cygnus.com>
+Mon Mar 29 11:50:34 1999 Jerry Quinn <jquinn@nortelnetworks.com>
- * toplev.c (flag_new_exceptions): Remove extraneous `extern'.
+ * pa.h (HAVE_PRE_INCREMENT): Disable when optimizing for a PA8000
+ class machine.
+ (HAVE_PRE_DECREMENT, HAVE_POST_INCREMENT): Likewise.
+ (HAVE_POST_DECREMENT): Likewise.
-Mon Jun 8 23:24:48 PDT 1998 Jeff Law (law@cygnus.com)
+Mon Mar 29 08:24:43 1999 Bruce Korb <korb@datadesign.com>
- * version.c: Bump for snapshot.
+ * fixinc/mkfixinc.sh: Fix portability problems with old shells.
-Mon Jun 8 23:24:58 1998 David Edelsohn <edelsohn@mhpcc.edu>
-
- * rs6000.md (mulsidi3): Add !TARGET_POWERPC64 constraint.
- (mulsidi3_ppc64): Delete.
-
-Mon Jun 8 20:57:40 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * Makefile.in (varasm.o): Depend on dbxout.h.
- (cse.o): Depend on toplev.h and output.h.
- (gcse.o): Depend on output.h.
-
- * mips.c: Include system.h and toplev.h and remove redundant code.
- Include output.h after tree.h so all its prototypes get activated.
- * mips.md (table_jump): Remove unused variable `dest'.
-
- * sparc.h: Add prototype for `v8plus_regcmp_op'.
-
- * crtstuff.c (fini_dummy, init_dummy): Mark function definitions
- with __attribute__ ((__unused__)).
- (__frame_dummy): Provide prototype before use, wrap it with
- EH_FRAME_SECTION_ASM_OP.
-
- * cse.c: Move inclusion of <setjmp.h> above local headers.
- Include toplev.h and output.h.
-
- * dbxout.h: Add prototype for `dbxout_begin_function'.
-
- * final.c (final_scan_insn): Wrap variable `max_skip' in macro
- ASM_OUTPUT_MAX_SKIP_ALIGN.
-
- * gcse.c: Include system.h and output.h.
- (dump_cuid_table, dump_rd_table, dump_cprop_data, dump_pre_data):
- Make extern instead of static.
- (compute_can_copy): Only declare variables `reg' and `insn' when
- AVOID_CCMODE_COPIES is not defined.
- (record_set_info): Mark parameter `setter' with ATTRIBUTE_UNUSED.
- (hash_scan_clobber): Likewise for `x' and `insn'.
- (hash_scan_call): Likewise.
- (record_last_set_info): Likewise for `setter'.
- (mark_call): Likewise for `pat'.
- (pre_insert_insn): Wrap variable `note' in macro HAVE_cc0.
-
- * libgcc2.c (__bb_init_prg): Replace bzero with memset and fix the
- length parameter so that it multiplies the number of elements by
- the sizeof(element).
-
- * output.h: Add prototype for `weak_finish'.
-
- * recog.h: Likewise for `validate_replace_src'.
-
- * rtl.h: Likewise for `optimize_save_area_alloca',
- `fix_sched_param', `purge_addressof', `gcse_main',
- `regmove_optimize', `dbr_schedule', `branch_prob' and
- `end_branch_prob'.
-
- * toplev.h: Likewise for `set_float_handler' and
- `output_quoted_string'.
-
- * varasm.c: Include dbxout.h.
-
-Mon Jun 8 18:12:06 1998 Jim Wilson <wilson@cygnus.com>
-
- * mips.c (mips_secondary_reload_class): Use gp_reg_p instead of
- GP_REG_P. Use gr_regs instead of GR_REGS.
-
-Mon Jun 8 16:54:12 1998 Ken Raeburn <raeburn@cygnus.com>
- Jeff Law <law@cygnus.com>
-
- * Revamped multiply support for MIPS chips.
- * mips.c (extend_operator): New function.
- (highpart_shift_operator): Likewise.
- * mips.h: Declare new functions.
- (PREDICATE_CODES): Add support for new predicates.
- * mips.md (mulsi3 expander): Simplify.
- (mulsi_mult3): Add another constraint alternative. Support
- 3 operand multiply instructions as found on various mips
- parts.
- (mulsi3_r4650): Delete pattern, now handled by mulsi_mult3.
- (mul_acc_si): New pattern and associated splitters.
- (mulsidi3 expander): Rework to use mulsidi3_64bit and
- mulsidi3_internal.
- (umulsidi3): New expander.
- (mulsidi3_internal): Accept either sign or zero extended
- operands and generate code as appropriate appropriately.
- (mulsidi3_64bit): Similarly.
- (smulsi3_highpart): Turn into an expander and generate code
- to match new patterns.
- (umulsi3_highpart): Likewise.
- (xmulsi3_highpart_internal): New pattern.
- (maddi patterns): Delete. Replace with:
- (mul_acc_di, mul-acc_64bit_di): New patterns.
-
-Mon Jun 8 14:16:15 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
-
- * eh-common.h: Remove NEW_EH_MODEL compile time flag, and replace with
- flag_new_exceptions runtime flag.
- (struct old_exception_table): New struct which represents what
- the exception table looks like without the new model.
- (NEW_EH_RUNTIME): New value used as a tag in the exception table to
- flag that this is a new style table.
- * except.h: Remove compile time flag NEW_EH_MODEL.
- (expand_builtin_eh_stub_old): New prototype.
- * tree.h (enum built_in_function): Add BUILT_IN_EH_STUB_OLD.
- * expr.c (expand_builtin): New builtin func BUILT_IN_EH_STUB_OLD.
- * c-decl.c (init_decl_processing): Add new builtin function
- __builtin_eh_stub_old.
- * final.c (final_scan_insn): Replace compile time flag NEW_EH_MODEL.
- * flags.h (flag_new_exceptions): New runtime flag.
- * toplev.c (flag_new_exceptions): Initialize default to 0,
- -fnew-exceptions sets to 1.
- * except.c (output_exception_table_entry): Output New style exception
- identifier into table, and replace compile time flag NEW_EH_MODEL
- with runtime flag flag_new_exceptions.
- (output_exception_table): Replace compile time flag NEW_EH_MODEL.
- (expand_builtin_eh_stub_old): Duplicates original functionality of
- expand_builtin_eh_stub.
- (expand_builtin_eh_stub): Replace compile time flag NEW_EH_MODEL.
- * libgcc2.c (find_exception_handler): Remove NEW_EH_MODEL #ifdefs.
- (old_find_exception_handler): New func, same as find_exception_handler
- except it works on the old style exception table.
- (__throw): Replace NEW_EH_MODEL. Detect new model based on presence
- of identifier in the exception table, and call appropriate routines.
-
-Mon Jun 8 01:21:13 1998 Jason Merrill <jason@yorick.cygnus.com>
-
- * function.c: Define current_function_cannot_inline.
- (push_function_context_to): Save it.
- (pop_function_context_from): Restore it.
- * function.h (struct function): Provide it a home.
- * output.h: Declare it.
- * integrate.c (function_cannot_inline_p): Check it.
+ * fixinc/README: Updated for release announcement
-Mon Jun 8 10:43:15 1998 Richard Henderson <rth@cygnus.com>
+Sun Mar 28 20:26:55 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * expr.c (force_operand): Detect PIC address loads before
- splitting arithmetic.
+ * recog.h (insn_outfun, insn_operand_predicate): Add prototype
+ arguments.
-Mon Jun 8 09:22:38 PDT 1998 Jeff Law (law@cygnus.com)
+ * rtl.h (note_stores): Likewise.
- * version.c: Bump for snapshot.
+ * rtlanal.c (note_stores): Likewise.
-Mon Jun 8 02:55:56 1998 Graham <grahams@rcp.co.uk>
+Sun Mar 28 15:34:28 1999 Richard Henderson <rth@cygnus.com>
- * tree.c (tree_class_check): Add braces to eliminate ambigious
- else warning.
- (tree_check): Likewise.
+ * varasm.c (output_constant_pool): Always mark the constant pool.
-Mon Jun 8 02:49:23 1998 H.J. Lu (hjl@gnu.org)
+Sun Mar 28 16:09:01 1999 Jerry Quinn <jquinn@nortelnetworks.com>
- * reg-stack.c (subst_stack_regs_pat): Make sure the top of
- stack is the destination for conditional move insn.
+ * pa.md (pa7100LCshiftmem, pa7100LCalu): Change simultaneity. Use
+ shift/mem ops in pa7100LCalu.
-Mon Jun 8 01:21:13 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * pa.c (pa_adjust_cost): Don't do cost adjustments on pa8000.
+ (pa_reorg): Don't call pa_combine_instructions on pa8000.
- * tree.h (TREE_VEC_END): Cast unused value to void.
+Sun Mar 28 15:27:26 1999 Jeffrey A Law (law@cygnus.com)
- * i386.c (print_operand): Use %lx for long operand.
+ * reload1.c (reload): Remove accidental code duplication.
-Mon Jun 8 00:04:07 1998 Richard Henderson <rth@cygnus.com>
+Sun Mar 28 12:22:12 1999 Robert Lipe (robertlipe@usa.net)
- * alpha.c (summarize_insn): Ignore rtl slot format 'i'.
+ * i386/sysv5.h: New file to describe UnixWare7/SVR5.
+ * configure.in (i?86-UnixWare7*-sysv): Use it.
+ * i386/udk.h: Use sysv5.h. Now uses Dwarf-2.
-Sun Jun 7 14:15:45 1998 John Carr <jfc@mit.edu>
+Sun Mar 28 01:15:04 1999 Jeff Law (law@cygnus.com)
- * sol2.h (INIT_SUBTARGET_OPTABS): Use Solaris libc float/long long
- conversion functions.
+ * version.c: Bump for snapshot.
-Sun Jun 7 14:02:58 1998 Richard Henderson <rth@cygnus.com>
+Sun Mar 28 00:44:27 1999 Jeffrey A Law (law@cygnus.com)
- * toplev.c (flag_exceptions): Default to 0.
- (compile_file): Remove flag_exceptions == 2 hack.
- (main): Call lang_init_options.
- * tree.h: Declare it.
- * c-lang.c: Implement it.
- * objc/objc-act.c: Likewise.
-
-Sun Jun 7 12:27:30 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * sdbout.c (sdbout_symbol): Do not call build_pointer_type, build
+ one on the fly and do not cache the result.
- * rs6000.md (restore_stack_block): Generate MEM and specify mode.
- * rs6000.h (STACK_SAVEAREA_MODE): SAVE_FUNCTION is VOIDmode.
- * rs6000.c (rs6000_output_load_toc_table): Use fputs.
- (output_function_profiler): Use asm_fprintf and fputs.
+ * gcc.cps, cpp.cps: Delete unwanted files.
-Sat Jun 6 12:17:12 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Sat Mar 27 23:37:40 1999 John Wehle (john@feith.com)
- * gencheck.c: Remove redundant stdio.h include. Add a definition
- of xmalloc for when we are forced to link with alloca.o.
+ * i386.md (movdicc+3, movdicc+4): Rewrite using split_di.
+ * i386.c (output_int_conditional_move): Delete unused code.
- * reload1.c (reload_reg_free_for_value_p): Use `(unsigned)1'
- instead of `1U'.
+Sat Mar 27 21:17:36 1999 David Edelsohn <edelsohn@gnu.org>
- * fold-const.c (constant_boolean_node): Make definition static to
- match the prototype.
+ * rs6000/{aix41.h,aix43.h} (ASM_CPU_SPEC): Add 604e.
-Fri Jun 5 15:53:17 1998 Per Bothner <bothner@cygnus.com>
+Sat Mar 27 16:13:50 1999 Jeffrey A Law (law@cygnus.com)
- * gcc.c (lang_specific_pre_link): New LANG_SPECIFIC_DRIVER function.
- (lang_specific_extra_outfiles): New LANG_SPECIFIC_DRIVER variable.
- (do_spec, input_filename, input_filename_length): Make public.
- (main): Adjust outfiles allocation by lang_specific_extra_outfiles.
- Call lang_specific_pre_link befor elinking.
+ * flow.c (mark_used_regs): Improve handling of ASMs.
-Fri Jun 5 12:29:28 1998 Jeffrey A Law (law@cygnus.com)
+1999-03-26 Zack Weinberg <zack@rabi.columbia.edu>
- * haifa-sched.c (rank_for_schedule): For "equally good insns", prefer
- the insn which has the most insns dependent on it.
+ * Makefile.in (xcpp, cppspec.o): New targets.
+ (CPP_INSTALL_NAME): New macro.
+ (install-cpp): Install xcpp. Use CPP_INSTALL_NAME.
+ (all.build, start.encap): Build xcpp.
-Fri Jun 5 09:03:22 1998 John Carr <jfc@mit.edu>
+ * cppspec.c: New file, implements argument filtering for a
+ user-visible C preprocessor.
+ * cpp.sh: Removed.
- * alias.c (find_base_value): Avoid reading past end of reg_base_value.
+Fri Mar 26 20:41:46 1999 Jim Wilson <wilson@cygnus.com>
-Fri Jun 5 03:05:34 1998 Richard Henderson <rth@cygnus.com>
+ * Makefile.in (stmp-fixinc): Use tooldir instead of gcc_tooldir.
- * alpha.md (insxh-1): New insxl pattern for combine.
+Fri Mar 26 16:02:37 1999 Nick Clifton <nickc@cygnus.com>
-Fri Jun 5 01:12:15 1998 H.J. Lu (hjl@gnu.org)
+ * configure.in (arm-*-vxworks*): Just include arm/vxarm.h.
+ * configure: Regenerate.
+ * config/arm/vxarm.h: Define SUBTARGET_CPU_DEFAULT before
+ including arm/coff.h
- * i386/i386.c (output_fp_conditional_move): New function
- to output floating point conditional move.
- (output_int_conditional_move): New function to output integer
- conditional move.
+1999-02-16 Scott Bambrough <scottb@corelcomputer.com>
- * i386/i386.md (movsicci+5, movhicc+5, movdicc+5): Call
- output_int_conditional_move () to output int conditional move.
- (movsfcc+5, movdfcc+5, movxfcc+5): Call
- output_fp_conditional_move () to output floating point
- conditional move.
+ * configure.in (arm*-*-linux-gnu*): Set thread_file to 'posix' if
+ --enable-threads[={yes,pthreads,posix}] is passed as a command
+ line parameter to configure.
- * i386/i386.c (put_condition_code): In INT mode, check
- cc_prev_status.flags & CC_NO_OVERFLOW for GE and LT.
-
-Thu Jun 4 16:09:51 1998 Dave Brolley <brolley@cygnus.com>
-
- * dbxout.c (dbxout_type): Output arrays of bits as if
- they were bitstrings for Chill
-
-Thu Jun 4 14:35:27 1998 David Edelsohn <edelsohn@mhpcc.edu>
-
- * tree.c (get_inner_array_type): New function.
- * tree.h (get_inner_array_type): Prototype.
- * expr.h (STACK_SAVEAREA_MODE): New macro.
- * expr.c (expand_builtin_setjmp): Initialize sa_mode using
- STACK_SAVEAREA_MODE.
- (expand_builtin_longjmp): Likewise.
- * explow.c (emit_stack_save): Likewise.
- (allocate_dynamic_stack_space): Use Pmode not insn_operand_mode.
-
- * rs6000/aix41.h (ASM_CPU_SPEC): Define relative to ASM_DEFAULT_SPEC.
- (CPP_CPU_SPEC): Define relative to CPU_DEFAULT_SPEC.
- * rs6000/aix43.h: New file.
- * rs6000/t-aix43: New file.
- * rs6000/x-aix41: New file.
- * rs6000/x-aix43: New file.
- * configure.in (rs6000-ibm-aix*): Use them.
- * rs6000/powerpc.h: Delete.
- * rs6000/sysv4.h: Move necessary powerpc.h definitions to here.
- * rs6000/netware.h: and here.
- * rs6000/win-nt.h: and here.
-
- * rs6000/rs6000.c (processor_target_table, 620): Do not affect
- MASK_POWERPC64.
- (rs6000_override_options): Ignore flag_pic for AIX.
- (rs6000_immed_double_const): Delete.
- (u_short_cint_operand): Don't assume 32-bit CONST_INT.
- (reg_or_u_short_operand): Don't assume 32-bit CONST_INT.
- (num_insns_constant): mask64_operand() is 2 insns.
- (logical_operand): Don't assume 32-bit CONST_INT.
- (non_logical_cint_operand): Don't assume 32-bit CONST_INT.
- (easy_fp_constant): Any CONST_DOUBLE_HIGH is okay for 64-bit.
- (mask_constant): HOST_WIDE_INT parameter.
- (non_and_cint_operand): Delete.
- (mask64_operand): New function.
- (and64_operand): New function.
- (function_arg_advance): DImode arguments do not need special
- alignment when 64-bit.
- (function_arg): Likewise.
- (setup_incoming_varargs): Reverse reg_size assignment.
- (print_operand): HOST_WIDE_INT second parameter.
- (print_operand, 'B'): New case.
- (print_operand, 'M'): Fix typo in lossage string.
- (print_operandm 'S'): New case.
- (rs6000_stack_info): Reverse reg_size assignment. Use total_raw_size
- to compute AIX push_p. Use reg_size to compute {cr,lr}_save_offset.
- (rs6000_output_load_toc_table): Reverse init_ptr assignment. Use
- TARGET_64BIT not TARGET_POWERPC64. Convert fprintf to fputs.
- Load GOT highpart, don't add it. Add lowpart with {cal|la}.
- (rs6000_allocate_stack_space): Use {cal|la}.
- (output_epilog): Use {cal|la}
- (output_function_profiler): Add call glue to mcount call.
- Load GOT highpart, don't add it. Add lowpart with {cal|la}.
-
- * rs6000/rs6000.h (TARGET_SWITCHES): Add powerpc64.
- (STACK_BOUNDARY): Depend on TARGET_32BIT.
- (ADJUST_FIELD_ALIGN): Calculate array alignment using innermost type.
- (CONST_OK_FOR_LETTER_P): Don't assume 32-bit CONST_INT.
- (EXTRA_CONSTRAINTS): Remove NT 'S' and 'T'. Replace 'S' with
- 64-bit mask operand.
- (RS6000_SAVE_TOC): Depend on TARGET_32BIT.
- (STACK_SAVEAREA_MODE): New macro.
- (LEGITIMATE_CONSTANT_P): DImode okay for 64bit.
- (LEGITIMIZE_RELOAD_ADDRESS): New macro.
- (RTX_COSTS, AND/IOR/XOR): Reflect current machine description.
- (ASM_FILE_START): Emit 64-bit ABI directive.
- (ASM_DECLARE_FUNCTION_NAME): Align CSECT on doubleword in 64-bit mode.
- (ASM_OUTPUT_SPECIAL_POOL_ENTRY): DImode okay for 64-bit.
- (PREDICATE_CODES): Add "and64_operand" and "mask64_operand".
- Delete "non_and_cint_operand". "input_operand" includes CONST_DOUBLE.
-
- * rs6000/rs6000.md (iorsi3, xorsi3): Use HOST_WIDE_INT for mask.
- Restore define_splits.
- (floatsidf2, floatunssidf2): Remove !TARGET_POWERPC64 final constraint.
- (floatsidf2_internal, floatunssidf2_internal2): Likewise.
- Do not specify base register operand mode.
- (floatsidf2_loadaddr): Do not specify base register operand mode.
- (floatsidf2_store1, floatsidf2_store2): Operand 1 must be base
- register; do not specify mode. Remove !TARGET_POWERPC64 final
- constraint.
- (floatsidf2_load): Do not specify base register operand mode. Remove
- !TARGET_POWERPC64 final constraint.
- (fix_truncdfsi2_internal, fix_truncdfsi2_{store,load}): Do not specify
- base register operand mode.
- (adddi3): Split large constants early.
- (absdi3): Shift by 63, not 31.
- (*mulsidi3_ppc64): New pattern.
- (rotldi3): Add masking combiner patterns.
- (anddi3): Add rldic{r,l} masking. Remove split of large constants
- because PPC insns zero-extend.
- (iordi3, xordi3): Split large constants early.
- (movsi matcher): Remove S and T constraints.
- (movsf const_double): create SImode constant from TARGET_DOUBLE.
- (movdf_hardfloat32): Add default abort() case.
- (movdf easy_fp_const): create DImode constant from TARGET_DOUBLE.
- (movdi): Remove 64-bit constant generator. Try to convert
- CONST_DOUBLE to CONST_INT. Handle TOC memory constants.
- (movdi_32): Add default abort() case.
- (movdi_64): Add numerous ways to split 64-bit constants.
- Make catch-all define_split more optimal and never FAIL.
- (movti_ppc64): Add default abort() case.
- (allocate_stack): Remove operand modes. Use Pmode.
- (restore_stack_block): Remove operand modes. Generate Pmode
- temporary.
- (save_stack_nonlocal, restore_stack_nonlocal): Generate Pmode
- temporary. Save area is double Pmode.
- (call_indirect_aix64, call_value_indirect_aix64): New patterns.
- (call, call_value): Do not specify address operand mode. Choose
- appropriate AIX ABI.
- (*call_local64, *ret_call_local64): New patterns.
- (*call_nonlocal_aix64, *ret_call_nonlocal_aix64): New patterns.
- (*ret_call_nonlocal_aix32): Use call_value_indirect for REG.
- (compare): Materialize DImode truthvalues.
+ * configure: Regenerate.
-Thu Jun 4 01:26:57 1998 Craig Burley <burley@gnu.org>
+ * gcc/config/arm/t-linux (TARGET_LIBGCC2_CFLAGS): Include -fPIC.
- * expr.c (safe_from_p): Avoid combinatorial explosion
- over duplicate SAVE_EXPRs by ensuring we never recurse
- on one that has already been visited.
+Fri Mar 26 19:42:19 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Thu Jun 4 00:54:21 1998 Graham <grahams@rcp.co.uk>
+ * loop.c (combine_givs): Fix index into can_combine when doing
+ benefit adjustment for remaining givs when having combined a giv.
- * loop.c (check_dbra_loop): Initialise final_value before
- normalizing the loop.
+Fri Mar 26 11:38:01 1999 Nick Clifton <nickc@cygnus.com>
-Wed Jun 3 20:00:04 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * config/arm/t-arm-elf (EXTRA_MULTILIB_PARTS): Define.
- * reload1.c (reload_reg_free_for_value_p): New arguments out and
- reloadnum. Changed all callers.
+Fri Mar 26 10:48:27 1999 Nick Clifton <nickc@cygnus.com>
-1998-06-03 Ulrich Drepper <drepper@cygnus.com>
+ * config/arm/linux-elf.h: Include dbxelf.h
- * system.h: Add _() and N_() macros in preparation for gettext.
+Fri Mar 26 10:43:47 1999 Nick Clifton <nickc@cygnus.com>
-Wed Jun 3 11:02:24 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * config/svr4.h: Include new header file dbxelf.h.
+ (DBX_DEBUGGING_INFO): Remove definition.
+ (DBX_USE_BINCL): Remove definition.
+ (DBX_BLOCKS_FUNCTION_RELATIVE): Remove definition.
+ (ASM_IDENTIFY_GCC): Remove definition.
+ (ASM_IDENTIFY_GCC_AFTER_SOURCE): Remove definition.
+ (ASM_OUTPUT_SOURCE_LINE): Remove definition.
+ (DBX_FUNCTION_FIRST): Remove definition.
+ (DBX_OUTPUT_MAIN_SOURCE_FILE_END): Remove definition.
- * c-common.c (check_format_info): Put back check for C9x `hh'
- length modifier. Warn about %n format writing into const. Remove
- obsolete comment.
- (format_char_info): Fix comments.
+ * config/elfos.h: Include new header file dbxelf.h.
+ (DBX_DEBUGGING_INFO): Remove definition.
+ (DBX_BLOCKS_FUNCTION_RELATIVE): Remove definition.
+ (ASM_IDENTIFY_GCC): Remove definition.
+ (ASM_IDENTIFY_GCC_AFTER_SOURCE): Remove definition.
+ (ASM_OUTPUT_SOURCE_LINE): Remove definition.
+ (DBX_FUNCTION_FIRST): Remove definition.
- * configure.in: Set float_format to m68k for all m68k targets that
- do not override LONG_DOUBLE_TYPE_SIZE.
- * config/float-m68k.h: New file.
+ * config/dbxelf.h: New header file.
+ (DBX_DEBUGGING_INFO): Define.
+ (DBX_BLOCKS_FUNCTION_RELATIVE): Define.
+ (DBX_FUNCTION_FIRST): Define.
+ (DBX_USE_BINCL): Define.
+ (DBX_CONTIN_LENGTH): Define.
+ (ASM_IDENTIFY_GCC): Define.
+ (ASM_IDENTIFY_GCC_AFTER_SOURCE): Define.
+ (ASM_OUTPUT_SOURCE_LINE): Define.
+ (DBX_OUTPUT_MAIN_SOURCE_FILE_END): Define.
-Tue Jun 2 23:14:01 1998 Richard Henderson <rth@cygnus.com>
+Fri Mar 26 01:59:15 1999 "Charles M. Hannum" <root@ihack.net>
- * jump.c (jump_optimize): Remove debug messages accidentally left in
- with the previous change.
+ * fold-const.c (fold_truthop): Optimize bitfield references with
+ different masks as long as their size and bit position are the same.
-Tue Jun 2 22:46:08 1998 Richard Henderson <rth@cygnus.com>
+ * fold-const.c (fold_truthop): Build a type for both the lhs and
+ rhs and use it appropriately.
- * expr.c (store_expr): Revert stray patch associated with
- 1998-05-23 commit.
+ * fold-const.c (fold_truthop): Mask the lhs and rhs after merging
+ adjacent bitfield references.
-Tue Jun 2 21:59:01 1998 Richard Henderson <rth@cygnus.com>
+ * fold-const.c (fold_truthop): Verify that the lhs and rhs are
+ in the same bit position when optimizing bitfield references
+ which have the same mask.
- * jump.c (rtx_unsafe_p): New function.
- (jump_optimize): Use it on if/then/else transformations and
- conditional move transformations.
+Thu Mar 25 22:53:27 1999 Martin von Löwis <loewis@informatik.hu-berlin.de>
-Tue Jun 2 22:50:10 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * gcc.texi (Copy Assignment): New node.
- * fold-const.c (fold, case EQ_EXPR): When folding VAR++ == CONST
- or VAR-- == CONST construct a proper mask if VAR is a bitfield.
- Cope with CONST being out of range for the bitfield.
+1999-03-25 Zack Weinberg <zack@rabi.columbia.edu>
-Tue Jun 2 22:28:31 1998 Bernd Schmidt <crux@ohara.Informatik.RWTH-Aachen.DE>
+ * gcc.c: Compile unconditionally all code formerly dependent
+ on #ifdef LANG_SPECIFIC_DRIVER.
+ * gccspec.c: New file with stub lang_specific_driver,
+ lang_specific_pre_link.
+ * Makefile.in: Link gccspec.o into xgcc. Add rule to compile
- * expr.c (emit_move_insn_1): When moving complex values in several
- steps, emit a CLOBBER to show the destination dies.
+Thu Mar 25 21:08:02 1999 Jason Merrill <jason@yorick.cygnus.com>
-Tue Jun 2 22:17:26 1998 Jeffrey A Law (law@cygnus.com)
+ * gcc.texi (Temporaries): Update.
- * Makefile.in (site.exp): Use the object testsuite directory as
- the temporary directory.
+Thu Mar 25 16:53:53 1999 Richard Henderson <rth@cygnus.com>
- * expr.c (expand_expr, case ADDR_EXPR): Handle taking the
- address of an ADDRESSOF rtx.
+ * combine.c (distribute_notes): Place REG_LABEL also where
+ REG_EQUAL indicates.
-1998-06-02 Mike Stump <mrs@wrs.com>
+Thu Mar 25 12:46:37 1999 Jim Wilson <wilson@cygnus.com>
- * expr.c (expand_builtin_setjmp): Handle BUILTIN_SETJMP_FRAME_VALUE.
- * i960.h (SETUP_FRAME_ADDRESSES, BUILTIN_SETJMP_FRAME_VALUE): Define.
- * i960.md (ret, flush_register_windows): Define.
- (nonlocal_goto): Likewise. Nested function nonlocal gotos don't
- work yet.
- * tm.texi (BUILTIN_SETJMP_FRAME_VALUE): Document new macro.
+ * a29k/a29k.h (TARGET_SWITCHES): Add doc strings.
+ * i960/i960.h (TARGET_SWITCHES): Add doc strings.
+ * invoke.texi (a29k): Add documentation for -mno-multm option.
-Tue Jun 2 14:02:38 1998 Richard Henderson <rth@cygnus.com>
+Thu Mar 25 14:04:54 1999 Andrew MacLeod <amacleod@cygnus.com>
- * alpha.md (divsi3, udivsi3, modsi3, umodsi3): Enable, and work
- around an OSF/1 library bug wrt sign-extension of inputs.
+ * rtl.texi (RTX_FRAME_RELATED_P): Add documentation.
+ * rtl.h (struct rtx_def): Update comment for frame_related field.
+ (set_unique_reg_note): Declare prototype.
+ * dwarf2out.c (dwarf2out_frame_debug_expr): Split out from
+ 'dwarf2out_frame_debug' to handle only expressions, and process
+ component parts of a PARALLEL expression.
+ (dwarf2out_frame_debug): Process insns only, and call
+ new function 'dwarf2out_frame_debug_expr' for patterns.
+ * emit-rtl.c (set_unique_reg_note): New function to add a reg note,
+ but if there is an existing one, delete it first.
+ * expmed.c (expand_mult, expand_divmod): Use set_unique_reg_note.
+ * optabs.c (add_equal_note, expand_binop): Use set_unique_reg_note.
+ (emit_no_conflict_block, emit_libcall_block): Use set_unique_reg_note.
+ (expand_fix): Use set_unique_reg_note.
-Tue Jun 2 13:02:44 1998 Richard Henderson <rth@cygnus.com>
+Thu Mar 25 11:47:49 1999 Art Haas <ahaas@neosoft.com>
- * vax/netbsd.h (DWARF2_UNWIND_INFO): Must be undef, not defined 0.
+ * tlink.c (symbol_hash_newfunc): Remove redundant call to
+ hash_newfunc.
+ (file_hash_newfunc, demangled_hash_newfunc): Likewise.
-Mon Jun 1 03:44:03 1998 Catherine Moore <clm@cygnus.com>
+Thu Mar 25 10:05:56 1999 Richard Henderson <rth@cygnus.com>
- * config/sh/sh.h (MAX_OFILE_ALIGNMENT): Define.
+ * i386.h (PREFERRED_STACK_BOUNDARY): Set to 128.
- * varasm.c (assemble_variable): Augment alignment warning.
+1999-03-25 Philip Blundell <pb@nexus.co.uk>
-Mon Jun 1 12:14:28 1998 Michael Meissner <meissner@cygnus.com>
+ Based on patch from Jim Studt <jim@federated.com>:
+ * config/arm/linux-elf.h (STARTFILE_SPEC, ENDFILE_SPEC): Copy
+ definitions from config/linux.h.
+ (DBX_BLOCKS_FUNCTION_RELATIVE): Define to 1.
- * config/fp-bit.c (_fp{add,div}_parts): Return correct IEEE result
- in the presence of IEEE negative 0's.
+Thu Mar 25 02:12:42 1999 Finn Hakansson <finn@axis.com>
-Sun May 31 16:11:41 1998 John Wehle (john@feith.com)
+ * loop.c (strength_reduce): Correct a comment.
- * reload.c (find_reloads): Record the existing mode if
- operand_mode == VOIDmode before replacing a register with
- a constant.
- * i386.md (tstsi, tsthi, tstqi, tstsf, tstdf, tstxf): Set
- i386_compare_op1 to const0_rtx for the benefit of the
- conditional move patterns.
- (movsicc, movhicc, movsfcc, movdfcc, movxfcc, movdicc): Rewrite
- based on suggestions from Jim Wilson.
+ * rtl.h (MEM_COPY_ATTRIBUTES): Remove unnecessary ending backslash.
-Sun May 31 00:44:02 PDT 1998 Jeff Law (law@cygnus.com)
+Thu Mar 25 02:02:13 1999 Axel Thimm <Axel.Thimm@physik.fu-berlin.de>
- * version.c: Bump for snapshot.
+ * Makefile.in (RANLIB_TEST): Improve test.
+
+Thu Mar 25 01:15:33 1999 Donn Terry <donn@interix.com>
+
+ * combine.c (force_to_mode, case PLUS): Use sign extended mask
+ when masking the low bits out of a constant.
-Sun May 31 00:34:17 1998 Bruce Korb <korbb@datadesign.com>
+Tue Mar 23 15:45:25 1999 Richard Earnshaw (rearnsha@arm.com)
+ Jeff Law <law@cygnus.com>
- * Makefile.in (fixinc.sh): Update rules again.
+ * fold-const.c (make_range): If orig_type is unset, set it as soon
+ as we know the type. Remove now unnecessary set of orig_type for
+ conversions.
-Sun May 31 00:27:47 1998 Jeffrey A Law (law@cygnus.com)
+Wed Mar 24 23:27:25 1999 Mark Elbrecht <snowball3@usa.net>
+ Jeff Law <law@cygnus.com>
- * extend.texi: Bring back reference to trampoline paper.
+ * system.h (STDIN_FILENO): Provide default definition if one is not
+ provided by the system header files.
+ (STDOUT_FILENO, STDERR_FILENO): Likewise.
-Sun May 31 00:22:34 1998 Ulrich Drepper <drepper@cygnus.com>
+ * i386/xm-djgpp.h (COLLECT2_HOST_INITIALIZATION): New macro.
+ * collect2.c (main): Use it.
+ (pexecute_pid): New variable. Holds return value from call to pexecute.
+ (collect2_execute): Rework to use pexecute instead of fork.
+ (collect2_wait): Use pwait() instead of wait().
- * Makefile.in (USER_H): Add stdbool.h.
- * ginclude/stdbool.h: New file.
+ * i386/djgpp.h: Fix typo.
-Fri May 29 01:48:25 1998 Jeffrey A Law (law@cygnus.com)
+Wed Mar 24 23:24:30 1999 Jeffrey A Law (law@cygnus.com)
- * jump.c (thread_jumps): Do not look at the NOTE_LINE_NUMBER
- of a non-note insn.
+ * fixinc/mkfixinc.sh: Recognize cygwin* instead of only
+ cygwin32.
- * gcse.c (pre_delete): Fix code to determine the mode of
- the reaching pseudo register.
+Wed Mar 24 15:44:12 1999 Nick Clifton <nickc@cygnus.com>
-Fri May 29 01:07:28 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
+ * config/m32r/m32r.c (init_idents): Accept both NAME and __NAME__
+ versions of attribute names and values.
+ (m32r_valid_machine_decl_attribute): Likewise.
+ (m32r_encode_section_info): Likewise.
- * Makefile.in (GEN): Add gencheck
- (STAGESTUFF): Add tree-check.h and gencheck.
+Wed Mar 24 21:42:15 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Fri May 29 00:57:37 1998 Bruce Korb <korbb@datadesign.com>
+ * reload1.c (choose_reload_regs): If output-reloading for a
+ simple move insn, try to inherit an equivalence for the input.
- * Makefile.in (cstamp-h.in): Remove before trying to recreate.
- (fixinc.sh): Set some additional environment variables before
- calling mkfixinc.sh.
+1999-02-24 Mike Stump <mrs@wrs.com>
-Thu May 28 12:57:05 1998 Jeffrey A Law (law@cygnus.com)
+ * arm/aout.h (DBX_OUTPUT_MAIN_SOURCE_FILENAME): Fix quoting.
- * reload.c (find_reloads): Do not force a reloads of match_operators.
+1999-03-24 Jim Blandy <jimb@zwingli.cygnus.com>
-Thu May 28 10:22:22 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+ * libgcc2.c (__CTOR_LIST__, __DTOR_LIST__): Initialize on all
+ platforms.
- * except.h (remove_handler): Add new prototype.
- * except.c (remove_handler): New function to remove handlers
- from an exception region.
- * flow.c (find_basic_blocks_1): Remove handlers from regions when
- handler label is deleted; remove exception regions with no handlers.
+Wed Mar 24 01:35:01 1999 Geoff Keating <geoffk@ozemail.com.au>
-Thu May 28 09:36:39 1998 Michael Meissner <meissner@cygnus.com>
+ * fold-const.c (fold): Recognize a rotate by an unsigned amount.
- * except.h (rtx): Define rtx type correctly if needed.
- * function.h (rtx): Ditto.
- (tree): Define tree type correctly if needed.
+Tue Mar 23 23:32:14 1999 Jeffrey A Law (law@cygnus.com)
- * c-pragma.c (toplevel): Include rtl.h.
+ * pa.md (rotlsi3): New expander. Synthesize a variable rotate
+ left using a variable rotate right. Provide anonymous pattern for
+ rotate left by a constant value.
- * stor-layout.c (toplevel): Move include of rtl.h before
- except.h.
+ * expr.c (expand_assignment): Do not try to optimize a aggregate
+ address which has VOIDmode.
- * Makefile.in (c-pragma.o): Add except.h, rtl.h dependencies.
- (tree.o): Add except.h dependency.
+Tue Mar 23 22:51:48 1999 Mumit Khan <khan@xraylith.wisc.edu>
+ Donn Terry <donn@interix.com>
-Wed May 27 22:02:40 1998 Jeffrey A Law (law@cygnus.com)
+ * protoize.c (abspath): Preserve multiple leading slashes for
+ _WIN32 and Interix.
- * reload1.c: Revert accidental checkin.
+1999-01-23 Mike Stump <mrs@wrs.com>
- * configure.lang: Fix thinko when adding a definition for
- target_alias to the Makefile.
+ * arm/vxarm.h: Split out vxWorks support into separate headerfile
+ and vxify.
+ * arm/arm.c (cpu_defaults): Allow arm710 as default.
-Wed May 27 02:50:00 1998 Catherine Moore (clm@cygnus.com)
+ * configure.in: Split out vxWorks support for Arm.
+ * configure: Rebuilt.
- * config/sparc/lb1spc.asm (.rem and .urem): Replace
- routines.
+Tue Mar 23 11:20:03 1999 Per Bothner <bothner@cygnus.com>
+
+ * tree.c (first_rtl_op, has_cleanups): Handle GOTO_SUBROUTINE_EXPR.
+
+Tue Mar 23 09:00:39 1999 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/riscix1.h (SUBTARGET_SWITCHES): Add doc string.
+ * config/arm/riscix1-1.h (SUBTARGET_SWITCHES): Add doc string.
+
+Tue Mar 23 07:50:20 1999 Mark Mitchell <mark@codesourcery.com>
+
+ * function.c: Include hash.h.
+ (insns_for_mem_entry): New struct.
+ (put_reg_into_stack): Take an optional hash-table mapping MEMs to
+ the INSNs that use them.
+ (fixup_var_refs): Likewise.
+ (put_addressof_into_stack): Likewise.
+ (purge_addressof_1): Likewise. Keep the hash-table up to date if
+ we add new instructions.
+ (fixup_var_refs_insns): Use it to avoid searching the entire
+ instruction chain.
+ (insns_for_mem_newfunc): New function.
+ (insns_for_mem_comp): Likewise.
+ (insns_for_mem_walk): Likewise.
+ (compute_insns_for_mem): Likewise.
+ (pop_function_context_from): Pass NULL for the hash-table.
+ (put_var_into_stack): Likewise.
+ (gen_mem_addressof): Likewise.
+ (flush_addressof): Likewise.
+ (purge_addressof): Call compute_insns_for_mem to pre-compute the
+ hash table.
+ * Makefile.in (OBJS): Include hash.o.
+ (function.o): Depend on hash.h.
-Wed May 27 02:48:31 1998 Richard Earnshaw (rearnsha@arm.com)
+Tue Mar 23 00:39:14 1999 Jeffrey A Law (law@cygnus.com)
- * arm.c (arm_gen_constant): Rework to eliminate uninitialized
- variable warnings. Don't generate scratch registers if only
- counting insns.
- (find_barrier): Eliminate unused variable SRC.
+ * i386/openbsd.h (TARGET_DEFAULT): Use symbolic names instead of
+ numbers.
+ * i386/netbsd.h, i386/freebsd.h: Likewise.
-1998-05-27 Manfred Hollstein <manfred@s-direktnet.de>
+ * crtstuff.c: Use ANSI function definitions. Fix minor whitespace
+ problems.
- * toplev.h (rtx_def): Provide global declaration to avoid
- `limited scope' warnings.
+ * i386/openbsd.h (TARGET_DEFAULT): Define.
+ * configure.in: Do not set TARGET_CPU_DEFAULT for x86 OpenBSD
+ configurations.
+ * configure: Rebuilt.
-Tue May 26 23:47:52 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Tue Mar 23 00:39:10 1999 John Wehle (john@feith.com)
- * Makefile.in (gencheck.o): Use HOST_CC.
- * i386/t-mingw32: New file.
- * configure.in (i386-*-mingw32*): Use.
+ * i386/freebsd.h (TARGET_DEFAULT): Define instead
+ of TARGET_CPU_DEFAULT.
+ * i386/netbsd.h (TARGET_DEFAULT): Likewise.
-Tue May 26 07:31:04 1998 Richard Earnshaw (rearnsha@arm.com)
+Mon Mar 22 23:52:01 1999 Mumit Khan <khan@xraylith.wisc.edu>
+ Donn Terry <donn@interix.com>
- * arm.c (bad_signed_byte_operand): New predicate function.
- * arm.h (PREDICATE_CODES): Add it to the list.
- * arm.md (*extendqi[sh]i_insn): Split any addresses that ldrsb
- can't handle.
- (define_split): Two new splits for above insns.
+ * sdbout.c (syms.h): Don't include on Interix.
+ * toplev.c (main): No sbrk on Interix.
- * arm.c: Include toplev.h.
- (arm_override_options): Add parentheses around use of tune_flags.
- (arm_split_constant): Remove unused variable.
- (arm_gen_constant, arm_gen_movstrqi, add_constant): Likewise.
- (output_func_prologue, arm_expand_prologue): Likewise.
- (arm_canonicalize_comparison): Make I unsigned; rework constants
- accordignly. Add missing paratheses around << operation.
- (arm_rtx_costs): Correctly parenthesise MULT costs. Add a DEFAULT
- clause.
- ({load,store}_multiple_sequence): Initialize BASE_REG.
- (select_dominance_cc_mode): Add DEFAULT clauses.
- (broken_move): Return zero if the destination is not a register.
- (arm_reorg): Move unused REGNO declaration into the dead code.
- * arm.h (CANONICALIZE_COMPARISON): Ensure OP1 is updated.
+ * configure.in: Add i386-pc-interix support.
+ * configure: Regenerate.
+ * fixinc.interix: New file.
+ * config/interix.h: New file.
+ * config/x-interix: New file.
+ * config/xm-interix.h: New file.
+ * i386/interix.h: New file.
+ * i386/interix.c: New file.
+ * i386/t-interix: New file.
+
+Mon Mar 22 23:41:49 1999 Jeffrey A Law (law@cygnus.com)
-Mon May 25 22:49:56 PDT 1998 Jeff Law (law@cygnus.com)
+ * i386.h (PREFERRED_STACK_BOUNDARY): Define.
+
+Mon Mar 22 23:41:31 1999 John Wehle (john@feith.com)
+
+ * i386.c (ix86_compute_frame_size): New function.
+ (ix86_prologue, ix86_epilogue): Use it.
+ * i386.h (INITIAL_ELIMINATION_OFFSET): Likewise.
+ * reload1.c: Provide default for PREFERRED_STACK_BOUNDARY.
+
+Mon Mar 22 18:06:59 1999 Jim Wilson <wilson@cygnus.com>
+
+ * mips/mips.h (TARGET_SWITCHES, TARGET_OPTIONS): Add option doc
+ strings.
+ * mips/abi64.h (SUBTARGET_TARGET_OPTIONS): Likewise.
+
+Mon Mar 22 16:18:27 1999 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/elf.h (VALID_MACHINE_DECL_ATTRIBUTE): Do not bother
+ passing ATTRIBUTES to arm_valid_machine_decl_attribute.
+
+ * config/arm/coff.h (VALID_MACHINE_DECL_ATTRIBUTE): Do not bother
+ passing ATTRIBUTES to arm_valid_machine_decl_attribute.
+
+ * config/arm/arm.h (DEFAULT_RTX_COSTS): Do not bother passing
+ OUTER_CODE to arm_rtx_costs - it is not used.
+ (arm_compare_fp): Delete declaration.
+ (FINAL_PRESCAN_INSN): Do not bother passing OPVEC or NOPERANDS to
+ arm_final_prescan_insn - they are not used.
+ (const_ok_for_op): Remove prototype.
+ (arm_rtx_costs): Fix prototype.
+ (arm_valid_machine_decl_attribute): Fix prototype.
+ (final_prescan_insn): Fix prototype.
+
+ * config/arm/arm.md: Remove references to arm_compare_fp.
+
+ * config/arm/arm.c (arm_compare_fp): Delete.
+ (const_ok_for_op): Make function static. Add prototype. Remove
+ mode parameter - it is unused.
+ (arm_rtx_costs): Remove outer_code parameter.
+ (reload_memory_operand): Declare mode parameter unused.
+ (power_of_two_operand): Declare mode parameter unused.
+ (equality_operator): Declare mode parameter unused.
+ (load_multiple_operation): Declare mode parameter unused.
+ (store_multiple_operation): Declare mode parameter unused.
+ (multi_register_push): Declare mode parameter unused.
+ (arm_valid_machine_decl_attribute): Remove attributes parameter -
+ it is unused.
+ (select_dominance_cc_mode): Remove op parameter - it is unused.
+ (gen_compare_reg): Remove fp parameter - it is unused.
+ (final_prescan_insn): Remove opvec and noperands parameters - they
+ are unused.
+
+Mon Mar 22 14:35:28 1999 Nick Clifton <nickc@cygnus.com>
+
+ * tm.texi (MD_SCHED_INIT): Add missing closing parenthesis.
+
+Mon Mar 22 22:24:30 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * reload1.c (reload_as_needed): Set reload_is_output_reload /
+ reload_has_output_reload for auto_inc expressions that could be
+ reloaded. Call forget_old_reloads for REG_INC notes.
+
+Mon Mar 22 21:51:57 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * cse.c (cse_insn): Don't change the result register of a libcall.
+
+Mon Mar 22 21:08:59 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * rtl.h (shallow_copy_rtx): Declare.
+ * rtl.c (shallow_copy_rtx): New function.
+ * reload.c (find_reloads_toplev): Use shallow_copy_rtx instead of
+ copy_rtx.
+
+Mon Mar 22 10:44:33 1999 Vladimir Makarov <vmakarov@tofu.to.cygnus.com>
+
+ * config/h8300/h8300.md (adjust_length): New attribute.
+ (modhi3+1, andsi3+1, iorsi3+1, extzv+1, extzv+2): Change insn
+ default value of attribute "adjust_length" onto "no".
+
+ * config/h8300/h8300.c (h8300_adjust_insn_length): Adjust
+ length only if the attribute "adjust_length" value is "yes".
+ Use 0 if the shift is negative.
+
+ * final.c (shorten_branches): Check insn length after its
+ adjusting.
+
+Sun Mar 21 17:33:48 1999 Jeffrey A Law (law@cygnus.com)
+
+ * i860.h (TARGET_SWITCHES): Add documentation for default case.
+ * i860/paragon.h (TARGET_SWITCHES): Add documentation for default case.
+ * i370.h (TARGET_SWITCHES): Add documentation for default case.
+ * fx80.h (TARGET_SWITCHES): Add documentation for default case.
+ * elxsi.h (TARGET_SWITCHES): Add documentation for default case.
+ * clipper.h (TARGET_SWITCHES): Add documentation for default case.
+ * 1750a.h (TARGET_SWITCHES): Add documentation for default case.
+ * pa.h (TARGET_SWITCHES): Add documentation for default case.
+ (TARGET_OPTIONS): Likewise for default case.
+ * mn10300.h (TARGET_SWITCHES): Add documentation for default case.
+ * h8300.h (TARGET_SWITCHES): Add documentation for default case.
- * version.c: Bump for snapshot.
+ * gcse.c (dump_hash_table): Fix whitespace in declaration.
+ (compute_transpout): Renamed from pre_compute_transpout.
+ (compute_pre_*): Deleted.
+ (pre_expr_reaches_here_p): New argument, CHECK_PRE_COMP. All
+ callers changed.
+ (insert_insn_end_bb): Renamed from pre_insert_insn.
+ (pre_*): Delete unused variables. Only leave local properties and
+ global redundant/optimal computation points.
+ (alloc_pre_mem, free_pre_mem): Corresponding changes.
+ (compute_pre_data): Simplify and call pre_lcm to run the lazy
+ code motion dataflow analysis.
+ (pre_insert, pre_insert_copies, pre_delete): Revamp to use LCM
+ based redundant and optimal computation points.
+
+ * basic-block.h (pre_lcm, pre_rev_lcm): Declare.
+
+ * toplev.c (main): A debug option without a level defaults to
+ level 2.
+
+Sun Mar 21 12:13:01 1999 Nick Clifton <nickc@cygnus.com>
+
+ * flow.c (can_delete_label_p): Do not allow user specified
+ labels to be deleted.
+ * dwarf2out.c (gen_label_die): Generate addresses for deleted
+ (programmer specified) labels.
+ * dwarfout.c (output_label_die): Generate addresses for deleted
+ (programmer specified) labels.
+
+1999-03-21 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * Makefile.in (xgcc$(exeext)): Add intl.o to list of files to be
+ linked with.
-Mon May 25 11:56:24 PDT 1998 Jeff Law (law@cygnus.com)
+Sun Mar 21 01:15:03 1999 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Mon May 25 14:00:13 1998 Dave Brolley <brolley@cygnus.com>
+Sat Mar 20 22:26:23 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * cpperror.c (v_cpp_message): Remove static prototype.
- * cpplib.c (v_cpp_message): Move prototype to cpplib.h.
- * cpplib.h (v_cpp_message): Add protoptype.
- (stdarg.h,varargs.h): Needed for v_cpp_message prototype.
+ * sparc.h (TARGET_SWITCHES): Add null description to default case.
-Sun May 24 20:36:15 PDT 1998 Jeff Law (law@cygnus.com)
+Sat Mar 20 21:46:06 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * version.c: Bump for snapshot.
+ * c-lex.c (yylex): Remove unused variable `bytes'.
-Sun May 24 02:08:57 PDT 1998 Jeff Law (law@cygnus.com)
+ * flow.c (print_rtl_with_bb): Cast the return value of alloca.
- * version.c: Bump for snapshot.
+ * function.c (assign_parms): Wrap variable `varargs_setup' in
+ macro SETUP_INCOMING_VARARGS.
+ (thread_prologue_and_epilogue_insns): Mark parameter `f' with
+ ATTRIBUTE_UNUSED.
-1998-05-24 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * local-alloc.c (no_equiv): Likewise for parameter `store'.
- * m68k.h: Declare more functions used in macros.
- (REG_CLASS_CONTENTS): Completely embrace initializer.
- * m68k.md (adddi3, subdi3): Add abort call to avoid warning
- about returning no value.
- * cse.c (find_best_addr): Declare p and found_better only if
- needed.
- * dbxout.c (dbxout_continue): Define only if DBX_CONTIN_LENGTH > 0.
- * dwarfout.c (string_length_attribute): #if 0 away.
- * function.c (expand_function_end): Define varible blktramp only
- if needed.
- * jump.c (find_insert_position): Define only if !HAVE_cc0.
- * loop.c (combine_givs_p): Define variable tem only if needed.
- * real.c: Comment out unused functions eabs, eround,
- e{24,53,64,113}toasc and eiinfin.
+ * sched.c (schedule_insns): Remove unused variables `insn' and `next'.
+
+ * tlink.c (symbol_hash_newfunc, symbol_hash_lookup,
+ file_hash_newfunc, file_hash_lookup, demangled_hash_newfunc,
+ demangled_hash_lookup, symbol_push, symbol_pop, file_push,
+ file_pop, tlink_init, tlink_execute, frob_extension,
+ obstack_fgets, tfgets, pfgets, freadsym, read_repo_file,
+ maybe_tweak, recompile_files, read_repo_files,
+ demangle_new_symbols, scan_linker_output): Add static prototype.
+ (symbol_hash_newfunc, file_hash_newfunc, demangled_hash_newfunc):
+ Make the third argument a `hash_table_key'.
-Sat May 23 23:44:53 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
+ * toplev.c (debug_start_source_file): Mark parameter `filename'
+ with ATTRIBUTE_UNUSED.
- * Makefile.in (boostrap2-lean, bootstrap3-lean,
- bootstrap4-lean): New targets.
+Sun Mar 21 02:28:21 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Sat May 23 23:35:14 1998 Jeffrey A Law (law@cygnus.com)
+ * tm.texi (Varargs): Don't split argument of @item across lines.
- * warn_summary, test_summary: Moved into the contrib directory.
+ * invoke.texi: Fix use of @item vs @itemx.
-1998-05-23 Manfred Hollstein <manfred@s-direktnet.de>
+Sun Mar 21 09:59:54 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * Makefile.in (ENQUIRE_CFLAGS, ENQUIRE_LDFLAGS): Move down to the end
- of the Makefile.
- (FLOAT_H_TEST): Likewise.
- (ENQUIRE): Likewise.
- (float.h-nat): Likewise.
- (float.h-cross): Likewise.
- (enquire): Likewise.
- (enquire.o): Likewise.
- (stmp-int-hdrs): Fix comment about enquire; depend upon gfloat.h.
- (stmp-headers): Move actions to stmp-int-hdrs, retaining only a
- no-op.
- (FLOAT_H): Remove old float.h-nat version; move current definition
- to CROSS_FLOAT_H location.
- (all.cross): Remove comments about enquire stuff.
+ * config/c4x/c4x.h (TARGET_SWITCHES): Add null description to
+ default case.
- * Makefile.in (all.cross): Swap $(LIBGCC) and $(STMP_FIXPROTO).
- (rest.encap): Likewise.
- (libgcc2.ready): Depend upon $(STMP_FIXPROTO)
+Sat Mar 20 23:33:54 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * toplev.h (tree_node): Provide global declaration to avoid
- `limited scope' warnings.
+ * loop.c (check_dbra_loop): Fix debug message.
-Sat May 23 23:23:35 1998 Robert Lipe <robertl@dgii.com>
+Sat Mar 20 15:54:35 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * test_summary: Display section breaks for each entry
- in a multilibbed target's output.
+ * config/c4x/c4x.md (decrement_and_branch_on_count): Emit rptb_end
+ pattern instead of decrement_and_branch_until_zero pattern.
-1998-05-23 Richard Henderson <rth@cygnus.com>
+Sat Mar 20 11:39:58 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * expr.c (expand_expr): For {BITFIELD,COMPONENT,ARRAY}_REF, if the
- offset's mode is not ptr_mode, convert it.
+ * config/c4x/c4x.h (TARGET_SWITCHES): Add documentation.
+ * config/c4x/c4x.h (TARGET_OPTIONS): Add documentation.
-1998-05-22 Jason Merrill <jason@yorick.cygnus.com>
+Fri Mar 19 23:26:29 1999 Martin von Löwis <loewis@informatik.hu-berlin.de>
- * fold-const.c (ssize_binop): New fn.
- * tree.h: Declare it.
+ * expr.c (expand_expr): Handle ERROR_MARK much earlier.
-Fri May 22 03:42:05 1998 Richard Earnshaw (rearnsha@arm.com)
+Fri Mar 19 15:28:38 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * genextract.c (print_path): Handle zero-length path as a special
- case.
+ * cccp.c (create_definition): Cast to U_CHAR* when assigning to one.
-Fri May 22 01:38:07 1998 Hans-Peter Nilsson <hp@axis.se>
+ * cppfiles.c (read_and_prescan): Likewise.
+ Start a #define in column 0.
- * cplus-dem.c (MBUF_SIZE): Bumped from 512 to 32767.
+ * cpplib.c (cpp_define): Cast to U_CHAR* when assigning to one.
+ (cpp_push_buffer): Likewise for cpp_buffer*.
+ (do_include): Change the type of `fbeg' and `fend' to unsigned char*.
+ (do_endif): Cast to char* when assigning to one.
+ (do_assert): Likewise.
+ (do_unassert): Likewise.
+ (cpp_read_check_assertion): Change the type of `name' to U_CHAR*.
+ Don't do unnecessary cast to char* anymore.
-Fri May 22 00:57:00 1998 Bernd Schmidt (crux@pool.informatik.rwth-aachen.de>
+ * genrecog.c (make_insn_sequence): Cast to char** when assigning
+ to one. Cast the first argument of bzero to PTR.
- * final.c (JUMP_TABLES_IN_TEXT_SECTION): Provide a default value.
- (shorten_branches, final_scan_insn): Test value of
- JUMP_TABLES_IN_TEXT_SECTION instead of just testing whether it
- is defined.
- * tm.texi (JUMP_TABLES_IN_TEXT_SECTION): Corresponding changes.
- * arm/coff.h: Define JUMP_TABLES_IN_TEXT_SECTION to 1.
- * arm/tcoff.h: Likewise.
- * i386/386bsd.h: Likewise.
- * i386/freebsd-elf.h: Likewise.
- * i386/freebsd.h: Likewise.
- * i386/netbsd.h: Likewise.
- * i386/ptx4-i.h: Likewise.
- * i386/sysv4.h: Likewise.
- * pa/pa.h: Likewise.
- * rs6000/linux.h: Likewise.
- * rs6000/rs6000.h: Likewise.
- * sh/sh.h: Likewise.
- * sparc/sp64-elf.h: Likewise.
- * v850/v850.h: Likewise.
- * rs6000/sysv4.h: Define JUMP_TABLES_IN_TEXT_SECTION to 0.
- * i386/linux.h: Define JUMP_TABLES_IN_TEXT_SECTION to (flag_pic).
-
-Thu May 21 19:50:13 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * regmove.c (gen_add3_insn): New function.
- (fixup_match_2): Use it instead of calling gen_addsi3.
-
-Thu May 21 23:09:50 1998 Jeffrey A Law (law@cygnus.com)
-
- * Makefile.in (gencheck): Depend on HOST_LIBDEPS.
-
- * alias.c (rtx_equal_for_memref_p): Handle SCRATCH as a memory
- address.
-
-Thu May 21 20:18:13 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
-
- * Makefile.in (TREE_H): Add tree-check.h.
- (tree-check.h, gencheck): New targets.
- * gencheck.c: New file.
- * tree.c (tree_check, tree_class_check): New functions.
- * tree.h (TREE_CHECK, TREE_CLASS_CHECK): Define.
- (TYPE_CHECK, DECL_CHECK): Define.
- Modify all access macros to use generated checking macros.
-
-Wed May 20 23:44:28 EDT 1998 John Wehle (john@feith.com)
-
- * acconfig.h (HAVE_GAS_MAX_SKIP_P2ALIGN): New tag.
- * configure.in: Check for it.
- * i386/gas.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Use it.
- * final.c (uid_align, uid_shuid, label_align): Make static.
- (label_align): Change type to struct label_alignment pointer.
- (LABEL_TO_ALIGNMENT, shorten_branches): Update due to type change.
- (LABEL_TO_MAX_SKIP): Define.
- (LABEL_ALIGN_MAX_SKIP, LOOP_ALIGN_MAX_SKIP,
- LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP): Provide defaults.
- (shorten_branches): Record the maximum bytes to skip when
- aligning a label.
- (final_scan_insn): Use the maximum bytes to skip when aligning a label
- if ASM_OUTPUT_MAX_SKIP_ALIGN is available.
- * i386.h (LOOP_ALIGN_MAX_SKIP,
- LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP): Define.
- * i386.c (override_options): i386_align_jumps and i386_align_loops
- default to 4 if ASM_OUTPUT_MAX_SKIP_ALIGN is available.
- * invoke.texi: Document new i386 align-loops and align-jumps behavior.
-
-1998-05-21 Mark Mitchell <mmitchell@usa.net>
-
- * cplus-dem.c (do_type): Handle volatile qualification.
-
-Thu May 21 12:23:17 1998 Per Bothner <bothner@cygnus.com>
-
- * function.c (init_function_start): Don't call emit_line_note if
- lineno is 0. (Can happen when compiling Java .class files.)
-
-Thu May 21 19:50:13 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * reload1.c (reload_reg_free_for_value_p): Fix RELOAD_FOR_INPUT
- end of lifetime and RELOAD_FOR_OUTPUT start of lifetime.
-
-Thu May 21 19:32:27 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * combine.c (nonzero_bits): For paradoxical subregs, take
- LOAD_EXTENDED_OP into account.
-
-Thu May 21 11:51:15 1998 Dave Brolley <brolley@cygnus.com>
-
- * configure.in (extra_c_objs): add prefix.o.
- (extra_cxx_objs): extra objects for C++ with cpplib.
- * configure: Regenerate.
+ * loop.c (strength_reduce): Remove unused variable `note'.
- * c-tree.h: (get_directive_line): Different prototype for cpplib.
- (GET_DIRECTIVE_LINE): Macro wrapper for get_directive_line.
+ * reload1.c (new_insn_chain): Cast to struct insn_chain* when
+ assigning to one.
- * c-lex.h: (get_directive_line): Not needed here for cpplib.
+ * rtl.c (copy_rtx): Use memcpy instead of bcopy.
- * c-lex.c: (yy_cur,yy_lim,yy_get_token): Move to c-common.c.
- (GET_DIRECTIVE_LINE): Move to c-common.c and rename to get_directive_line.
+Fri Mar 19 11:19:31 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * c-common.c (parse_in,parse_options,cpp_token): Declare for cpplib.
- (yy_cur,yy_lim,yy_get_token,get_directive,line): Moved here from c-lex.c
+ * calls.c (initialize_argument_information): Mark parameters
+ `num_actuals' and `n_named_args' with ATTRIBUTE_UNUSED.
-Thu May 21 09:04:42 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * dbxout.c (dbxout_start_new_source_file): Likewise for parameter
+ `filename'.
+ (dbxout_finish): Likewise for parameters `file' and `filename'.
+ (dbxout_prepare_symbol): Likewise for parameter `decl'.
+ (dbxout_begin_function): Likewise.
- * gengenrtl.c (type_from_format, accessor_from_format): Change
- type of parameter `c' from `char' to `int'.
+ * explow.c (hard_function_value): Likewise for parameter `func'.
-Wed May 20 22:28:34 1998 Jeffrey A Law (law@cygnus.com)
+ * function.c (locate_and_pad_parm): Likewise for parameter `fndecl'.
- * warn_summary, test_summary: New scripts from
- Kaveh Ghazi and Alexandre Oliva respectively.
+ * expmed.c (expand_divmod): Omit unused argument to `expand_abs'.
+ * expr.c (expand_expr): Likewise.
+ * expr.h (expand_abs): Delete unused argument from prototype.
+ * optabs.c (expand_abs): Remove unused parameter `unsignedp'.
- * gcse.c (current_function_calls_longjmp): Declare.
+ * sdbout.c (sdbout_init): Mark parameter `syms' with ATTRIBUTE_UNUSED.
+ (sdbout_end_block): Likewise for parameter `n'.
-1998-05-20 Jason Merrill <jason@yorick.cygnus.com>
+ * toplev.c (debug_define): Likewise for parameters `lineno' and
+ `buffer'.
+ (debug_undef): Likewise.
- * dwarf2out.c (base_type_die): Use int_size_in_bytes.
+ * varasm.c (named_section): Likewise for parameter 'reloc'.
+ (assemble_external): Likewise for parameter `decl'.
+ (assemble_alias): Likewise for parameter `target'.
-Wed May 20 01:11:02 1998 Doug Evans (devans@cygnus.com)
- Jeff Law (law@cygnus.com)
+Fri Mar 19 01:54:30 1999 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
- * Global CSE and constant/copy propagation.
- * Makefile.in (OBJS): Add gcse.o
- (STAGESTUFF): Add *.gcse.
- (gcse.o): Add dependencies.
- (mostlyclean): Remove *.gcse and */*.gcse.
- * gcse.c: New file.
- * loop.c (loop_optimize): Move call to init_alias_analysis.
- * recog.c (validate_replace_src): New function.
- * toplev.c (gcse_dump): New global variable.
- (flag_gcse, gcse_time): Likewise.
- (compile_file): Initialize gcse_time and clean out the gcse dump
- file if necessary.
- (rest_of_compilation): Call gcse_main as requested. Dump RTL
- after gcse if requested.
- (main): Enable gcse for -O2 and above. Handle -dG. Enable gcse
- dumps for -da.
- * gcc.texi: Add gcse related internal documentation.
- * invoke.texi: Note new command line options for gcse.
- * tm.texi: Document AVOID_CCMODE_COPIES.
- * mips.h (AVOID_CCMODE_COPIES): Define.
+ * toplev.c (read_integral_parameter): Constify. Better control of
+ error messages.
+ (main): Use read_integral_parameter to set optimize, id_clash_len,
+ larger_than_size, and the debugging level.
+ * toplev.h (read_integral_parameter): Update prototype.
-Tue May 19 22:31:20 1998 Jeffrey A Law (law@cygnus.com)
+Fri Mar 19 01:42:05 1999 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * Makefile.in (deduced.h): Only run scan-types if $(SYSTEM_HEADER_DIR)
- exists.
- (stmp-fixproto): Simlarly for running fixproto.
- * cross-make (SYSTEM_HEADER_DIR): Now $(tooldir)/sys-include.
+ * system.h: Use putc_unlocked, fputc_unlocked, and
+ fputs_unlocked only if putc_unlocked has a prototype already.
+ Prototype fputs_unlocked if necessary.
+ * configure.in: Check for prototypes of putc_unlocked and
+ fputs_unlocked.
+ * acconfig.h: Updated.
+ * config.in, configure: Rebuilt.
-Tue May 19 19:08:52 1998 Jim Wilson <wilson@cygnus.com>
+Fri Mar 19 02:45:12 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * config/mips/mips.c (double_memory_operand): Accept any MEM during
- reload when TARGET_64BIT.
+ * Makefile.in (INTL_TARGETS): New macro.
+ ($(INTL_TARGETS)): Depend on generated sources; drop dependencies
+ on cp/parse.c and objc/objc-parse.c.
+ ($(srcdir)/cp/parse.c): Move to cp/Make-lang.in.
+ * objc/Make-lang.in ($(INTL_TARGETS)): Depend on objc/objc-parse.c.
-Tue May 19 18:21:25 1998 Jim Wilson <wilson@cygnus.com>
+Thu Mar 18 22:28:53 1999 Jeffrey A Law (law@cygnus.com)
- Finish incomplete change started by Kenner.
- * configure.in (*-*-linux-gnu*): Delete NO_STAB_H from xm_defines.
- (powerpcle-*-cygwin32): Delete xm_defines.
- * final.c, mips-tfile.c, xcoffout.c, config/mips/mips.c: Use
- HAVE_STAB_H instead of NO_STAB_H.
- * config/xm-linux.h (NO_STAB_H): Delete.
- (HAVE_STAB_H): Undefine.
- * config/i386/xm-go32.h (NO_STAB_H): Delete.
+ * i860.h (TARGET_SWITCHES): Add documentation.
+ * i860/paragon.h (TARGET_SWITCHES): Add documentation.
+ * i370.h (TARGET_SWITCHES): Add documentation.
+ * fx80.h (TARGET_SWITCHES): Add documentation.
+ * elxsi.h (TARGET_SWITCHES): Add documentation.
+ * clipper.h (TARGET_SWITCHES): Add documentation.
+ * 1750a.h (TARGET_SWITCHES): Add documentation.
+ * pa.h (TARGET_SWITCHES): Add documentation.
+ (TARGET_OPTIONS): Likewise.
+ * mn10300.h (TARGET_SWITCHES): Add documentation.
+ * h8300.h (TARGET_SWITCHES): Add documentation.
-1998-05-19 Jim Wilson <wilson@cygnus.com>
+Thu Mar 18 15:58:26 1999 Nick Clifton <nickc@cygnus.com>
- * dwarfout.c (dwarfout_file_scope_decl, case TYPE_DECL): Ignore
- LANG_TYPE trees with DECL_SOURCE_LINE of 0.
+ * loop.c (strength_reduce): Do not perform pseudo replacements
+ if the loop contains volatile memory references.
-Tue May 19 15:07:54 1998 Todd Vierling <tv@netbsd.org>
+Thu Mar 18 19:09:50 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * arm/netbsd.h: Ensure DWARF2_UNWIND_INFO is undefined.
+ * reload.c (find_reloads_toplev): When processing X recursively,
+ don't alter it destructively except by filling in constants.
-Tue May 19 17:19:16 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Thu Mar 18 10:14:18 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * reload1.c (reload_reg_free_for_value_p): New function.
- (allocate_reload_reg, choose_reload_regs): Use it.
+ * cccp.c (default_include): Initialize structure members.
+ (pass_thru_directive): Change the type of 'keyword_length' to int.
+ (main): Cast `bindtextdomain' and `textdomain' to (void).
-Tue May 19 11:51:00 EDT 1998 Andrew MacLeod (amacleod@cygnus.com)
+ * collect2.c (main): Likewise.
- * except.c (expand_start_catch): Correct logic for when to
- generate a new handler label, and when to use the old one.
+ * cppmain.c (main): Likewise.
-Tue May 19 11:08:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * gcc.c (main): Likewise.
- * Makefile.in (print-rtl.o): Depend on bitmap.h.
- (dbxout.o): Depend on toplev.h.
- ($(SCHED_PREFIX)sched.o): Likewise.
- ($(out_object_file)): Likewise for system.h and toplev.h.
- (cppmain.o): Depend on gansidecl.h.
- (cpplib.o): Likewise.
- (cpperror.o): Likewise.
- (cppexp.o): Likewise.
- (cpphash.o): Likewise.
- (cppalloc.o): Likewise.
- (fix-header.o): Depend on cpplib.h and cpphash.h.
- (scan-decls.o): Depend on gansidecl.h.
+ * gcov.c (main): Likewise.
- * basic-block.h (free_regset_vector): Add prototype.
+ * protoize.c (main): Likewise.
- * cccp.c (check_precompiled): Mark parameter `fname' with
- ATTRIBUTE_UNUSED.
- (do_assert): Likewise for `op' and `keyword'.
- (do_unassert): Likewise.
- (do_line): Likewise for `keyword'.
- (do_error): Likewise for `op' and `keyword'.
- (do_warning): Likewise.
- (do_ident): Likewise for `keyword'.
- (do_pragma): Likewise for `limit', `op' and `keyword'.
- (do_sccs): Likewise.
- (do_if): Likewise for `keyword'.
- (do_elif): Likewise.
- (do_else): Likewise.
- (do_endif): Likewise.
-
- * collect2.c (getenv): Remove redundant prototype.
- (collect_exit, collect_execute, dump_file): Likewise.
- (dump_list): Wrap prototype and definition in COLLECT_EXPORT_LIST.
- (dump_prefix_list): Hide prototype and definition.
-
- * sparc.c: Include toplev.h.
- (intreg_operand): Mark parameter `mode' with ATTRIBUTE_UNUSED.
- (symbolic_memory_operand): Likewise.
- (sp64_medium_pic_operand): Likewise.
- (data_segment_operand): Likewise.
- (text_segment_operand): Likewise.
- (splittable_symbolic_memory_operand): Likewise.
- (splittable_immediate_memory_operand): Likewise.
- (eq_or_neq): Likewise.
- (normal_comp_operator): Likewise.
- (noov_compare_op): Likewise.
- (v9_regcmp_op): Likewise.
- (v8plus_regcmp_op): Likewise.
- (extend_op): Likewise.
- (cc_arithop): Likewise.
- (cc_arithopn): Likewise.
- (small_int): Likewise.
- (uns_small_int): Likewise.
- (clobbered_register): Likewise.
- (legitimize_pic_address): Likewise.
- (delay_operand): Likewise.
- (sparc_builtin_saveregs): Remove unused variable `stdarg'.
+ * toplev.c (main): Likewise.
- * sparc.h (order_regs_for_local_alloc, eligible_for_return_delay,
- sparc_issue_rate, v8plus_regcmp_p): Add prototypes.
+1999-03-18 Gavin Romig-Koch <gavin@cygnus.com>
- * sparc.md (cmpdi_v8plus): Add abort for default case in switch.
+ * config/mips/mips.c (mips_explicit_type_size_string): Correct
+ its type.
- * cppalloc.c: Include gansidecl.h.
+Thu Mar 18 01:24:25 1999 Jeffrey A Law (law@cygnus.com)
- * cpperror.c: Include stdarg.h/varargs.h and gansidecl.h.
- (cpp_file_line_for_message): Mark parameter `pfile' with
- ATTRIBUTE_UNUSED.
- (v_cpp_message): New function.
- (cpp_message): Use it. Also convert to variable arguments.
- (cpp_fatal): Likewise.
- (cpp_pfatal_with_name): Constify parameter `name'.
+ * configure.in: Use "exit 1", not "exit (1)".
+ * configure: Rebuilt.
- * cppexp.c: Move gansidecl.h before cpplib.h.
- * cpphash.c: Likewise.
- * cpphash.h (hashf, delete_macro): Add prototypes.
-
- * cpplib.c: Include stdarg.h/varargs.h and move gansidecl.h before
- cpplib.h. Don't include errno.h.
- (update_path): Add arguments to prototype.
- (cpp_fatal, cpp_file_line_for_message, cpp_message, delete_macro,
- cpp_print_containing_files): Remove redundant prototypes.
- (cpp_hash_cleanup, add_import, append_include_chain,
- make_assertion, path_include, initialize_builtins,
- initialize_char_syntax, finclude, validate_else, comp_def_part,
- lookup_import, redundant_include_p, is_system_include,
- read_name_map, read_filename_string, open_include_file,
- check_macro_name, compare_defs, compare_token_lists,
- eval_if_expression, change_newlines): Add prototype arguments.
- (hashf): Remove redundant prototype.
- (read_token_list, free_token_list, safe_read, xcalloc, savestring,
- conditional_skip, skip_if_group): Add prototype arguments.
- (fdopen): Remove redundant prototype.
- (do_define, do_line, do_include, do_undef, do_error, do_pragma,
- do_ident, do_if, do_xifdef, do_else, do_elif, do_endif, do_sccs,
- do_once, do_assert, do_unassert, do_warning): Add prototype arguments.
- (struct directive): Add prototype arguments to function pointer
- member `func'.
- (handle_directive): Add missing arguments to call to `do_line'.
- (do_include): Mark parameters `unused1' and `unused2' with
- ATTRIBUTE_UNUSED.
- (do_line): Likewise for `keyword' and new parameters `unused1' and
- `unused2'.
- (do_error): Likewise for `keyword'.
- (do_warning): Likewise. Also add missing argument `pfile' in call
- to cpp_pedwarn.
- (do_once): Mark parameter `keyword', `unused1' and `unused2' with
- ATTRIBUTE_UNUSED.
- (do_ident): Likewise for `keyword', `buf' and `limit'.
- (do_pragma): Likewise. Also add missing arguments in call to do_once.
- (do_sccs): Mark parameter `keyword', `buf' and `limit' with
- ATTRIBUTE_UNUSED.
- (do_if): Likewise for `keyword'.
- (do_elif): Likewise.
- (eval_if_expression): Likewise for `buf' and `length'.
- (do_xifdef): Likewise for `unused1' and `unused2'.
- (do_else): Likewise for `keyword', `buf' and `limit'.
- (do_endif): Likewise.
- (parse_name): Add missing argument `pfile' in call to cpp_pedwarn.
- (cpp_handle_options): Remove superfluous NULL argument in call to
- cpp_fatal.
- (cpp_handle_options): Likewise.
- (do_assert): Mark parameter `keyword', `buf' and `limit' with
- ATTRIBUTE_UNUSED.
- (do_unassert): Likewise.
- (cpp_print_file_and_line): Add missing argument `pfile' in call to
- cpp_file_line_for_message.
- (v_cpp_error): New function.
- (cpp_error): Use it. Also accept variable arguments.
- (v_cpp_warning): New function.
- (cpp_warning): Use it. Also accept variable arguments.
- (cpp_pedwarn): Accept variable arguments.
- (v_cpp_error_with_line): New function
- (cpp_error_with_line): Use it. Accept variable arguments.
- (v_cpp_warning_with_line): New function.
- (cpp_warning_with_line): Use it. Accept variable arguments. Hide
- definition.
- (cpp_pedwarn_with_line): Accept variable arguments.
- (cpp_pedwarn_with_file_and_line): Likewise.
- (cpp_error_from_errno): Constify parameter `name'. Add missing
- argument `pfile' in call to cpp_file_line_for_message.
- (cpp_perror_with_name): Constify parameter `name'.
-
- * cpplib.h: Define PARAMS() in terms of PROTO().
- (fatal): Remove redundant prototype.
- (cpp_error, cpp_warning, cpp_pedwarn, cpp_error_with_line,
- cpp_pedwarn_with_line, cpp_pedwarn_with_file_and_line,
- cpp_error_from_errno, cpp_perror_with_name, cpp_pfatal_with_name,
- cpp_fatal, cpp_message, cpp_pfatal_with_name,
- cpp_file_line_for_message, cpp_print_containing_files): Add
- arguments to prototypes.
- (scan_decls, cpp_finish): Add prototypes.
-
- * cppmain.c: Include gansidecl.h.
- (main): Remove unused variable `i'.
-
- * dbxout.c: Include toplev.h.
-
- * demangle.h (do_tlink, collect_execute, collect_exit,
- collect_wait, dump_file, file_exists): Add prototype.
-
- * dwarf2out.c (dwarf_type_encoding_name, decl_start_label): Hide
- prototype and definition.
- (gen_unspecified_parameters_die): Don't assign results of call to
- function new_die() to unused variable `parm_die'.
- (dwarf2out_line): Mark parameter `filename' with ATTRIBUTE_UNUSED.
- (dwarf2out_define): Likewise for `lineno' and `buffer'.
-
- * dwarfout.c (output_unsigned_leb128, output_signed_leb128): Hide
- prototype and definition.
- (output_die): Add prototype arguments to function pointer arg.
- (output_unspecified_parameters_die): Mark parameter `arg' with
- ATTRIBUTE_UNUSED.
+Wed Mar 17 23:17:42 1999 Mark Kettenis <kettenis@gnu.org>
+
+ * config/t-gnu (SYSTEM_HEADER_DIR): New variable. Set to
+ `/include' in order to find the system's limits.h.
+
+Wed Mar 17 23:00:18 1999 Robert Lipe <robertlipe@usa.net>
+
+ * fixinc/fixincl.c: Include auto-host.h instead of config.h.
+ * fixinc/procopen.c: Likewise.
+ * fixinc/regex.c: Likewise.
+ * fixinc/server.c: Likewise.
+
+Wed Mar 17 22:46:13 1999 Mark Elbrecht <snowball3@usa.net.
+
+ * config/i386/go32.h: Delete.
+ * config/i386/djgpp.h: New. Renamed from go32.h.
+ Added -DDJGPP=2 to CPP_PREDEFINES.
+ * config/i386/go32-rtems.h: Delete.
+ * config/i386/djgpp-rtems.h: New. Renamed from go32-rtems.h.
+ Added -DDJGPP=2 to CPP_PREDEFINES.
+ * config/i386/xm-go32.h: Delete.
+ * config/i386/xm-djgpp.h: New. Renamed from xm-go32.h.
+ * config/i386/x-go32: Delete.
+ * config/i386/x-djgpp: New. Renamed from x-go32.
+ * config/i386/t-go32: Delete.
+ * config/i386/t-djgpp: New. Renamed from t-go32.
+ * configure.in(pc-msdosdjgpp): Set xm_file to i386/xm-djgpp.h.
+ Set tm_file to i386/djgpp.h. Set tmake_file to i386/t-djgpp.
+ Set xmake_file to i386/x-djgpp.
+ (*-go32-msdos, *-go32*): Remove entries. Warn that GO32/DJGPP V1.X
+ is now unsupported and *-pc-msdosdjgpp for DJGPP V2.X should be
+ used instead.
+ * configure: Rebuilt.
+
+ * gcc.c (process_command): Dump link_command_spec too.
- * except.c (output_exception_table_entry): Remove unused variable
- `eh_entry'.
+Wed Mar 17 20:38:08 1999 Jerry Quinn <jquinn@nortelnetworks.com>
+ Jeff Law <law@cygnus.com>
- * except.h (expand_fixup_region_start, expand_fixup_region_end):
- Add prototypes.
+ * pa.md: Add real PA8000 scheduling information.
- * expr.c (do_jump_by_parts_equality_rtx): Remove prototype.
+ * pa.h (processor_type): Add PROCESSOR_8000 symbol.
+ (ISSUE_RATE): Revamp, including PA8000 support.
+ * pa.c (override_options): Add 8000 as -mschedule= option.
+ Do not call strcmp if pa_cpu_string is null.
+ * pa.md (attr cpu): Add 8000.
+ * invoke.texi: Add documentation for PA8000 scheduling.
- * expr.h (do_jump_by_parts_equality_rtx): Add prototype.
+Wed Mar 17 18:20:24 1999 David S. Miller <davem@redhat.com>
- * fix-header.c: Include stdarg.h/varargs.h, move gansidecl.h
- before cpplib.h, include cpphash.h, remove redundant prototype of
- cpp_fatal, don't define `const', add a prototype for `fatal'.
- (cpp_file_line_for_message): Add missing arguments `pfile'.
- (v_cpp_message): New function.
- (cpp_message): Use it.
- (v_fatal): New function.
- (fatal, cpp_fatal): Use it.
- (cpp_pfatal_with_name): Constify parameter `name'.
+ * config/sparc/sparc.h (TARGET_SWITCHES, TARGET_OPTIONS):
+ Add descriptions.
+ * config/sparc/sp64-elf.h (SUBTARGET_SWITCHES): Likewise.
+ * config/sparc/splet.h (SUBTARGET_SWITCHES): Likewise.
- * flow.c (free_regset_vector): Remove redundant prototype.
+Wed Mar 17 14:51:19 1999 Richard Henderson <rth@cygnus.com>
- * function.c (round_down): Wrap prototype and definition with
- macro ARGS_GROW_DOWNWARD.
- (record_insns): Wrap prototype and definition with
- defined (HAVE_prologue) || defined (HAVE_epilogue).
+ * flow.c (compute_immediate_dominators): New function.
+ * basic-block.h (compute_immediate_dominators): Declare it.
- * gansidecl.h (ATTRIBUTE_PRINTF_4, ATTRIBUTE_PRINTF_5): New macros.
+ * alpha.h (HARD_REGNO_MODE_OK): Allow only 4 and 8 byte unit modes
+ in FP regs.
+ (MODES_TIEABLE_P): Define asymmetricly wrt modes illegal in FP regs.
- * gen-protos.c: Include gansidecl.h.
- (hashf): Don't make it static, constify parameter `name'.
+Wed Mar 17 14:41:41 1999 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/aout.h (ASM_GENERATE_INTERNAL_LABEL): Fix compile
+ time warning.
+ * config/arm/arm.md: Fix various compile time warnings.
+ * config/arm/arm.h: Fix various compile time warnings. Add
+ function prototypes.
+ * config/arm/arm.c: Fix various compile time warnings.
+ (arm_override_options): Reorganize to separate tuning from
+ targetting.
+ (bit_count): New function: Return a count of the number of bits
+ set in a word.
+
+Wed Mar 17 21:29:12 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * reload1.c (eliminate_regs): Don't keep REG_DEAD notes around for
+ things that were eliminated.
+
+Wed Mar 17 12:16:26 1999 Richard Henderson <rth@cygnus.com>
+
+ * function.c (fixup_var_refs_1): First try moving the expression
+ directly into a register. Don't separate cc0 setter and user.
+
+Wed Mar 17 11:20:29 1999 Dave Brolley <brolley@cygnus.com>
+
+ * cppfiles.c (PIPE_BUF): #define PIPE_BUF if not defined already.
+
+Wed Mar 17 09:25:06 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * c-lex.c: Don't include setjmp.h.
+ (parse_float): New static function.
+ (pf_args): New struct.
+ (yylex): Use them in call to `do_float_handler'.
+
+1999-03-16 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * cexp.y (yyerror): Call verror to get a useful error message.
+ * cexp.c: Rebuilt.
+
+ * .gdbinit: Move command to put breakpoint at abort to end of file
+ so that gdb does not bail out early.
+
+Tue Mar 16 15:30:19 1999 Nick Clifton <nickc@cygnus.com>
+
+ * rtl.h: Rename prototype for free_bb_memory to free_bb_mem.
+
+Tue Mar 16 23:40:09 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * sh.md (movsi_i): Move t/r alternative after r/rI alternative.
+
+Tue Mar 16 13:44:50 1999 Jim Wilson <wilson@cygnus.com>
+
+ * mn10200/mn10200.md (addsi3, subsi3, ashlsi3, lshrsi3, ashrsi3):
+ Delete emit_library_call_value declaration.
+
+1999-03-16 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * cppfiles.c (read_and_prescan): Map backslash-newline to '\r'
+ (which cannot otherwise appear in the processed buffer) and
+ move it out of tokens that it appears in the middle of.
+ Improve performance.
+ (find_position): New function.
+
+ * cpplib.c: \r (one character) indicates backslash
+ newline, not \\\n (two characters). It cannot appear in the
+ middle of a token. Call CPP_BUMP_LINE (pfile) whenever
+ parsing moves past \n or \r. Increment pfile->lineno whenever
+ a \n is placed into token_buffer. Only one mark can exist at
+ a time, and CPP_BUMP_LINE must not be used while it is
+ active. It is automatically cleared by cpp_pop_buffer and
+ parse_goto_mark. \r is not in is_hor_space or is_space.
+
+ (NEWLINE_FIX, NEWLINE_FIX1, adjust_position,
+ update_position, count_newlines, parse_move_mark): Removed.
+ (parse_string, copy_comment): New functions.
+ (parse_name): Returns void.
+ (parse_set_mark, parse_clear_mark, parse_goto_mark): Take only
+ one argument, a cpp_reader *. Change for new marking scheme.
+ (skip_comment): Handle CHILL line comments too. Second
+ argument is now first character of comment marker; all callers
+ changed. Issue error for unterminated block comment here.
+ (cpp_skip_hspace): Recognize CHILL comments.
+ (copy_rest_of_line): Likewise. Call skip_comment and
+ parse_string directly, don't go through cpp_get_token. Emit
+ "/**/" for block comments if -traditional (create_definition
+ needs this).
+ (do_define): Don't play with put_out_comments.
+ (cpp_push_buffer): Initialize ->mark to -1.
+ (cpp_buf_line_and_col): Just read out the values in the buffer
+ structure.
+ (output_line_command): Use cpp_buf_line_and_col. Fix
+ formatting. Remove stale code.
+ (cpp_get_token): Break out string parsing code to
+ parse_string. Use skip_comment for CHILL comments too. Use
+ copy_comment for put_out_comments instead of dinking with
+ marks. Remove stale code. Don't call output_line_command
+ unless it's necessary.
+
+ * cpplib.h (parse_marker): Removed.
+ (struct cpp_buffer): Line_base is now a unsigned char *; add
+ `mark' [long], remove `marks' [struct parse_marker *].
+ (parse_set_mark, parse_clear_mark, parse_goto_mark): Update
+ prototypes.
+ (CPP_BUMP_LINE, CPP_BUMP_BUFFER_LINE): New macros.
+ * cppinit.c (is_hor_space, is_space): '\r' is not considered
+ whitespace.
+ * cppexp.c (cpp_parse_expression): Use cpp_skip_hspace, not
+ SKIP_WHITE_SPACE.
+ * cpphash.c (macarg): Disable line commands while expanding.
+
+Tue Mar 16 11:30:19 1999 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * c-lex.c (yylex) : Remove warning for integer literals being
+ larger than the largest target int. Add warning for integer
+ literal being larger than than its chosen type.
+
+Tue Mar 16 10:53:17 1999 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * invoke.texi: Add -mlong32 documentation.
+ * config/mips/mips.h (mips_explicit_type_size_string): New.
+ (TARGET_SWITCHES): Add 'long32'.
+ (TARGET_OPTIONS): Add 'explicit-type-size'.
+ (CC1_SPECS): Set -mexplicit-type-size.
+ (LONG_MAX_SPEC): Change a use of 'no-long64' to 'long32'.
+ * config/mips/abi64.h (LONG_MAX_SPEC): Same. Add 'mabi=32'.
+ * config/mips/mips.c (mips_explicit_type_size_string): New.
+ (override_options): Use it.
+ * config/mips/osfrose.h (CC1_SPECS): Set -mexplicit-type-size.
+
+ * config/mips/mips.h (SUBTARGET_CPP_SIZE_SPEC):
+ Pointer size now depends on both size longs and size of GP
+ registers.
+
+Tue Mar 16 10:22:22 1999 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/mips/iris.h (CTORS_SECTION_ASM_OP,DTORS_SECTION_ASM_OP,
+ dtors_section): Use Pmode == DImode rather than TARGET_LONG64.
+ * config/mips/mips.c (override_options): Allow -mlong64 and
+ -mint64 with -mips2 or less.
+ * config/mips/mips.h (MASK_LONG64): Fix comment.
+ (POINTER_SIZE): Use Pmode == DImode rather than TARGET_LONG64.
+ (Pmode): Make Pmode the smaller of longs or gp registers.
+ * invoke.texi: Note the new size for pointers.
+
+Mon Mar 15 22:45:25 1999 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.h (ASM_OUTPUT_{DOUBLE,FLOAT}): Always generate IEEE 754
+ bit-pattern directly.
+ (ASM_OUTPUT_REG_{PUSH,POP}): Delete.
+ * rs6000.c (first_reg_to_save): If profiling and context needed,
+ allocate a reg to save static chain for all ABIs. For AIX
+ profiling, calculate parameter registers to save based on need.
+ (output_function_profiler): Save and restore static chain around
+ profile call for all ABIs.
+
+1999-03-15 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * cppinit.c: Instead of one pending list, keep separate lists
+ for each category of pending option: -D/-U, -A, -include,
+ -imacros. Move the four partial include-path lists into the
+ pending block. Use head and tail pointers so we don't ever
+ have to reverse the lists.
+
+ (cpp_start_read): Break out blocks of code to their own
+ functions: install_predefs and initialize_dependency_output.
+ Use path_include for C_INCLUDE_PATH and friends as well as
+ CPATH. Remove include_defaults gunk. Warn about the
+ combination of -lang-chill and -trigraphs. Optimize string
+ bashing. Walk each pending list once, deallocating as we go.
+
+ (append_include_chain): Brought over from cppfiles.c. Mark
+ dirs as system include dirs if and only if appending to
+ system include path. If opts->verbose, print a notice when a
+ dir is dropped from the include path because it doesn't
+ exist. Fix memory leak: this function is not supposed to copy
+ its DIR argument.
+
+ (nreverse_pending, push_pending): Removed.
+ (APPEND): New macro for adding to pending lists.
+ (path_include): Can now add to any partial include path.
+ (base_name): Bring over from cccp.c.
+ (cpp_options_init): Allocate the pending block.
+ (cpp_handle_option): Add --version. Exit after --help. Fix
+ formatting. Order -ifoo options by frequency of usage.
+ (install_predefs): New function, simplified version of code
+ that was in cpp_start_read.
+ (initialize_dependency_output): Likewise. Understand OBJECT_SUFFIX.
+
+ * cppfiles.c (simplify_pathname): Export.
+ (merge_include_chains): Don't nreverse the lists. If
+ opts->verbose, print a notice when a duplicate dir is detected
+ and dropped from the include path.
+ (finclude): Fix excessive cleverness in setting
+ fp->system_header_p.
+ (actual_directory): Set x->sysp from
+ CPP_BUFFER (pfile)->system_header_p so that one system header
+ may include another with "".
+ (deps_output): Fix double adjustment of deps_size which would
+ cause all dependencies after the first two lines to be lost.
+
+ * cpplib.c (cpp_unassert): New function.
+ * cpplib.h: Lay out struct cpp_pending here. Adjust
+ prototypes. Add include_prefix_len to struct cpp_options.
+
+Mon Mar 15 16:01:52 1999 Jim Wilson <wilson@cygnus.com>
+
+ * config/misp/mips.h (REGISTER_MOVE_COST): Make the cost of moving
+ from HI/LO/HILO/MD into general registers the same as for one
+ of moving general registers to HI/LO/HILO/MD.
+
+Mon Mar 15 12:39:38 1999 Nick Clifton <nickc@cygnus.com>
+
+ * config/m32r/m32r.c (init_idents): New function. Initialize
+ static tree nodes for m32r specific attribute identifiers. Remove
+ leading and trailing double underscores from the attribute names.
+ (m32r_valid_machine_decl_attribute): Call init_idents.
+ (m32r_encode_section_info): Call init_idents.
+
+Mon Mar 15 10:20:20 1999 Mark Mitchell <mark@markmitchell.com>
+
+ * reload.c (find_reloads): Add a REG_LABEL note if we substitute a
+ LABEL_REF for something else.
+
+Mon Mar 15 08:24:17 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * fold-const.c (exact_real_inverse): Move variable `float_error'
+ into the scope where it is used.
+ (const_binop_1): New static function.
+ (cb_args): New struct.
+ (const_binop): Use them in call to `do_float_handler'.
+ (fold_convert_1): New static function.
+ (fc_args): New struct.
+ (fold_convert): Use them in call to `do_float_handler'.
+
+Mon Mar 15 22:50:18 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * rtlanal.c (auto_inc_p): New function.
+ * rtl.h (auto_inc_p): Prototype it.
+ * reload1.c (add_auto_inc_notes): New function.
+ (reload): Strip REG_INC notes and call add_auto_inc_notes
+ for each insn to restore them correctly.
+
+1999-03-15 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * fixinc/Makefile.in (procopen.o): List the actual
+ dependencies.
+
+Sun Mar 14 16:22:10 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cse.c (check_fold_consts): New static function.
+ (cfc_args): New struct.
+ (simplify_relational_operation): Use them in call to
+ `do_float_handler'.
+
+ * toplev.c (do_float_handler): New function to wrap calls to
+ setjmp/set_float_handler.
+
+ * toplev.h (do_float_handler): Add extern prototype.
+
+ * tree.c (build_real_from_int_cst_1): New static function.
+ (brfic_args): New struct.
+ (build_real_from_int_cst): Use them in call to
+ `do_float_handler'.
+
+Sun Mar 14 01:15:06 1999 Jeff Law (law@cygnus.com)
- * genattrtab.c (check_attr_test): Change XEXP() to XSTR() to match
- specifier %s in calls to function `fatal'.
+ * version.c: Bump for snapshot.
- * haifa-sched.c: Include toplev.h.
- (find_rgns): Remove unused variable `j'.
+Sat Mar 13 17:37:18 1999 Richard Henderson <rth@cygnus.com>
- * integrate.c (note_modified_parmregs): Mark parameter `x' with
- ATTRIBUTE_UNUSED.
- (mark_stores): Likewise.
+ * haifa-sched.c (sched_analyze_1): Only clear reg_last_uses on a SET.
- * jump.c (mark_modified_reg): Likewise.
+Sat Mar 13 11:36:16 1999 Richard Earnshaw (rearnsha@arm.com)
- * output.h (insn_current_reference_address): Add prototype.
- (eh_frame_section): Likewise.
+ * arm.c (arm_split_constant): Don't try to force a constant to
+ memory after arm_reorg has run.
+ (after_arm_reorg): New static variable.
+ (arm_reorg): Set it.
+ (output_func_epilogue): Clear it.
- * print-rtl.c: Include bitmap.h.
+Fri Mar 12 20:26:32 1999 David Edelsohn <edelsohn@gnu.org>
- * reload1.c (reload): Wrap variables `note' and `next' in macro
- PRESERVE_DEATH_INFO_REGNO_P.
- (forget_old_reloads_1): Mark parameter `ignored' with
- ATTRIBUTE_UNUSED.
- (choose_reload_regs): Remove unused variable `in'.
- (reload_cse_invalidate_mem): Mark parameter `ignore' with
- ATTRIBUTE_UNUSED.
- (reload_cse_check_clobber): Likewise.
+ * configure.in ({rs6000,powerpc}-ibm-aix*): Set float_format to none.
+ * configure: Rebuilt.
- * rtl.h (expand_null_return, reg_classes_intersect_p): Add prototype.
- (mark_elimination): Fix typo in prototype.
+Fri Mar 12 20:45:30 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * scan-decls.c: Include gansidecl.h.
+ * unroll.c (loop_iterations): Don't return a final value for EQ
+ comparison loops.
- * tree.h (using_eh_for_cleanups, supports_one_only): Add prototype.
+Fri Mar 12 12:35:01 1999 Jim Wilson <wilson@cygnus.com>
-Mon May 18 22:37:33 1998 Jeffrey A Law (law@cygnus.com)
+ * reload1.c (calculate_needs_all_insns): When ignore equivalence
+ setting insn, clear need_elim, need_reload, and need_operand_change.
- * function.c (identify_blocks): Fix thinko when setting the
- block number for NOTE_INSN_BLOCK_END.
+Fri Mar 12 07:54:43 1999 Bruce Korb <korb@datadesign.com>
-Mon May 18 15:30:42 1998 Nick Clifton <nickc@cygnus.com>
+ * fixinc/fixinc.*: Some changes from the fixincl-branch
+ were not applied (??!!). Corrected.
- * config/v850/lib1funcs.asm: Add .text pseudo op to start of
- ___udivsi3.
+ * fixinc/Makefile.in: Same thing.
- * config/v850/lib1funcs.asm: Fix .size pseudo ops to use three
- underscores for the prefixes to the names of the maths functions.
+Fri Mar 12 00:51:43 1999 Jeffrey A Law (law@cygnus.com)
- * dbxout.c (dbxout_parms): Revert to using DECL_ARG_TYPE. Add
- comment explaining why.
+ * expr.c (expand_expr): Allow a CALL_EXPR with a mode wider than
+ MAX_INTEGER_COMPUTATION_MODE.
-Mon May 18 13:20:23 1998 Richard Henderson <rth@cygnus.com>
+Thu Mar 11 14:00:58 1999 Richard Henderson <rth@cygnus.com>
- * tree.h (TYPE_SIZE_UNIT): New.
- (struct tree_type): Add size_unit member.
- * stor-layout.c (layout_type): Initialize it.
- * expr.c (get_inner_reference) [ARRAY_REF]: Use it.
- * tree.c (size_in_bytes, int_size_in_bytes): Likewise.
+ * alpha.h (HARD_REGNO_MODE_OK): Disallow QI/HImode in fp regs.
+ (MODES_TIEABLE_P): Update.
-Mon May 18 12:07:37 1998 Richard Earnshaw (rearnsha@arm.com)
+ * alpha.md (ev5_e0): Conflict loads and stores.
- * stor-layout.c (layout_record): Fix off-by-one error when checking
- length of the TYPE_BINFO vector.
+Thu Mar 11 13:55:52 1999 Richard Henderson <rth@cygnus.com>
-Mon May 18 10:59:23 1998 Nick Clifton <nickc@cygnus.com>
+ * machmode.h (smallest_mode_for_size): Prototype.
+ * stor-layout.c (smallest_mode_for_size): Remove static.
- * dbxout.c (dbxout_parms): Use TREE_ARG to compute the type of a
- function parameter passed in memory.
+Thu Mar 11 21:25:59 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Mon May 18 09:02:09 1998 Robert Lipe <robertl@dgii.com>
+ * loop.c (strength_reduce): Don't do biv increment -> DEST_REG giv
+ conversion if we don't know the lifetime.
- * dwarfout.h, dwarf2out.h, dbxout.h, sdbout.h: New files.
- Prototypes for externally used functions in respective C files.
- * dwarfout.c, dbxout.c, dwarf2out.c, sdbout.c, toplev,c,
- final.c: Include above files.
- * Makefile.in (toplev.o): Add dependency for above four headers.
- (final.o): Likewise.
- (dwarfout.o, dbxout.o, dwarf2out.o, sdbout.o): Depend on four
- respective header files.
+Thu Mar 11 20:37:59 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Mon May 18 01:23:33 1998 Jeffrey A Law (law@cygnus.com)
+ * reload.1c (delete_address_reloads_1): Check for reloads of
+ CURRENT_INSN even if it sets DST.
- * Makefile.in (TARGET_TOOLPREFIX): No longer define.
- (AR_FOR_TARGET, RANLIB_FOR_TARGET): Define to use versions in
- the build tree if they exist.
- (AR, AR_FLAGS, OLDAR, OLDAR_FLAGS, RANLIB, RANLIB_TEST): Update
- appropriately.
- (objdir): Let configure substitute value.
- (FLOAT_H): Let configure select a pre-built version from the
- config subdir.
- * build-make (INSTALL_TARGET, ALL): Disable, no longer needed.
- * configure.in: Substitute for objdir.
+Thu Mar 11 10:29:50 1999 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (build_canonical, host_canonical): Let configure
- substitute values for these variables.
- * configure.in: Substitute for build_canonical, host_canonical
- and target_subdir in generated Makefile.
+ * dwarf2out.c (add_AT_lbl_offset): Rename from add_AT_section_offset.
+ (print_die, size_of_die, value_format, output_die): Adjust.
- * output.h (find_basic_blocks): Declare.
- (free_basic_block_vars, set_block_num, life_analysis): Likewise.
+Thu Mar 11 10:27:42 1999 Robert Lipe <robertlipe@usa.net>
- * Makefile.in (BISON): Use bison from the build tree if it exists.
- (FLEX): Similarly.
+ * dwarf2out.c (TEXT_SECTION_LABEL, DEBUG_LINE_SECTION_LABEL,
+ DEBUG_INFO_SECTION_LABEL, ABBREV_SECTION_LABEL,
+ text_section_label, debug_line_section_label,
+ debug_info_section_label, abbrev_section_label): New.
+ (output_compilation_unit_header): Emit label associated
+ with section instead of section name itself.
+ (out_pubnames, output_aranges, output_line_info,
+ dwarf2out_finish): Likewise.
+ (dwarf2out_init): Build internal label names for sections
+ from static labels.
-Mon May 18 00:08:19 1998 Nick Clifton <nickc@cygnus.com>
+Thu Mar 11 17:28:32 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * gcc.c (SWITCH_CURTAILS_COMPILATION): Definition.
- (DEFAULT_SWITCH_CURTAILS_COMPILATION): True for options -S and -c.
- (process_command): If HAVE_EXECUTABLE_SUFFIX is defined then scan
- command line arguments to see if an executable is not being
- created, and if so - do not append the suffix.
+ * sh.md (mulsi3): End mul.l sequence with a no-op move.
- * tm.texi (SWITCH_CURTAILS_COMPILATION): Add description of new
- driver macro.
+Thu Mar 11 08:52:02 1999 Bruce Korb <korb@datadesign.com>
-Sun May 17 23:59:45 1998 John Wehle (john@feith.com)
+ * Makefile.in: Activated fixinc/mkfixinc.sh.
+ * configure.in: Activated fixinc/mkfixinc.sh.
- * i386.h (ALIGN_DFmode): Delete.
- (CONSTANT_ALIGNMENT): Define.
- * varasm.c (force_const_mem): Use it.
+Thu Mar 11 01:38:02 1999 Mumit Khan <khan@xraylith.wisc.edu>
-Sun May 17 19:31:05 1998 Richard Henderson <rth@cygnus.com>
+ * cppfiles.c (INO_T_EQ): Handle UWIN.
- * alpha.c (alpha_emit_conditional_branch): Clear cmp_code after
- using it with swap_condition, not before.
+ * c-common.c (decl_attributes): Flag unrecognized attribute
+ functions as warnings instead of as errors.
-Sun May 17 13:44:32 1998 Jim Wilson <wilson@cygnus.com>
+ Support for i386-pc-uwin.
+ * i386/uwin.h: New file.
+ * i386/xm-uwin.h: New file.
+ * i386/t-uwin: New file.
+ * i386/uwin.asm: New file.
+ * configure.in (i[3456]86-*-uwin*): Define.
+ Add Workaround for vfork bug when hosted on uwin.
+ * configure: Regenerate.
- * alias.c (mode_alias_check): Delete.
- (true_dependence, anti_dependence, output_dependence): Revert April 21
- change.
+ * cccp.c (INO_T_EQ): Undefine. UWIN has inodes.
+ (absolute_filename): UWIN uses POSIX pathnames only.
+ * libgcc2.c (getpagesize): Do not define for UWIN.
+ (mprotect): Likewise.
+ * protoize.c (dirent.h): Conditionally include.
+ (fputc): Prototype only if it's not a macro.
-Sun May 17 08:45:21 1998 Krister Walfridsson <cato@df.lth.se>
+Wed Mar 10 02:49:04 1999 Jason Merrill <jason@yorick.cygnus.com>
- * toplev.c (output_lang_identify): Enable prototype and definition.
+ * configure.in: Remove init_priority stuff.
-Sun May 17 01:12:27 PDT 1998 Jeff Law (law@cygnus.com)
+1999-03-11 Colin Smith <colin@wrs.com>
- * version.c: Bump for snapshot.
+ * sdbout.c (plain_type_1): Make boolean types work better with sdb.
-Sat May 16 23:20:32 1998 Richard Henderson <rth@cygnus.com>
+Thu Mar 11 00:20:52 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
- * alpha/osf.h (HAVE_STAMP_H): Define.
- * alpha.c: Use it.
- * alpha/netbsd.h, alpha/netbsd-elf.h: New files.
- * configure.in (alpha*-*-netbsd*): New.
- Based on patches from Paul H. Anderson <pha@pdq.com>.
+ * gcc.texi: Update bug reporting instructions to match
+ current ezmlm list reality.
- * configure.in (alpha*-*-linux-*): Kill xm_defines.
- (alpha*-*-linux-gnulibc1*) [fixincludes]: Define.
- * alpha/xm-linux.h: Remove file.
+Wed Mar 10 23:11:19 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.c (print_file_name, print_prog_name, spec_machine,
+ read_specs, set_spec, lookup_compiler, build_search_list,
+ putenv_from_prefixes, find_a_file, record_temp_file,
+ delete_if_ordinary, handle_braces, do_spec, do_spec_1, find_file,
+ is_directory, validate_switches, used_arg, default_arg,
+ pfatal_with_name, perror_with_name, pfatal_pexecute, fatal, error,
+ notice, add_preprocessor_option, add_assembler_option,
+ add_linker_option, process_command, execute,
+ unused_prefix_warnings, clear_args, fatal_error,
+ lang_specific_driver, user_specs, compiler, link_command_spec,
+ option_map, translate_options, make_temp_file, temp_name,
+ programname, path_prefix, machine_suffix, just_machine_suffix,
+ gcc_exec_prefix, standard_exec_prefix, standard_exec_prefix_1,
+ md_exec_prefix, md_startfile_prefix, md_startfile_prefix_1,
+ standard_startfile_prefix, standard_startfile_prefix_1,
+ standard_startfile_prefix_2, tooldir_base_prefix, tooldir_prefix,
+ multilib_dir, temp_filename, temp_file, command, switchstr,
+ infile, outfiles, input_filename, input_basename, input_suffix,
+ check_live_switch, main): Qualify a char* with the `const' keyword.
+
+Wed Mar 10 20:28:29 1999 Jeffrey A Law (law@cygnus.com)
+
+ * lcm.c: New file.
+ * Makefile.in (OBJS): Add lcm.o.
+ (lcm.o): Add dependencies.
+
+ * gcse.c (compute_pre_local_properties): Delete.
+ (compute_pre_data): Use compute_local_properties instead of
+ compute_pre_local_properties.
+
+ * gcse.c: More comments, whitespace and similar fixes.
+ (dump_cuid_table, maybe_set_rd_gen, dump_cprop_data): Delete.
+ (dump_pre_data, compute_cprop_local_properties): Likewise.
+ (one_classic_gcse_pass): Lose unused argument. All callers changed.
+ (compute_hash_table, compute_expr_hash_table): Likewise.
+ (compute_set_hash_table, one_pre_gcse_pass, mark_call): Likewise.
+ (cprop_insn, cprop, one_cprop_pass): Add new argument ALTER_JUMPS.
+ All callers changed. Only alter jumps if ALTER_JUMPS is nonzero.
+ Lose unused argument.
+ (gcse_main): Always run a cprop pass after finishing global cse.
+ (compute_local_properties): New function.
+ (hash_scan_pat, hash_scan_insn): No longer call maybe_set_rd_gen.
+ (compute_cprop_data): Use compute_local_properties.
+
+ * gcse.c: Update various comments.
+ (current_function_calls_longjmp): Delete declaration.
+
+ * gcse.c (run_jump_opt_after_gcse): New variable.
+ (gcse_main): Returns an integer.
+ (hash_scan_set): Record initializations from CONST_DOUBLEs too.
+ (try_replace_reg): Update some comments.
+ (cprop_insn): Allow propagation into some JUMP_INSNs too.
+ * rtl.h (gcse_main): Update prototype.
+ * toplev.c (rest_of_compilation): If gcse_main returns nonzero,
+ then run a jump optimization pass.
+ * jump.c (delete_barrier_successors): Delete nop jumps too.
+
+Wed Mar 10 19:04:31 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * sh.c (fp_arith_reg_operand): Actually test if reg is suitable
+ for FP arithmetic. Changed caller.
+ * sh.md (subsf3, subsf_i): Use fp_arith_reg_operand.
+
+Wed Mar 10 18:56:31 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * reload1.c (choose_reload_regs): When inheriting from the frame
+ pointer, don't clobber it.
+
+Wed Mar 10 08:01:52 1999 Bruce Korb <korb@datadesign.com>
+
+ * fixinc/fixinc.*: Resync-ed with the files in this
+ directory.
-Sat May 16 18:32:45 1998 Doug Evans <devans@canuck.cygnus.com>
+ * fixinc/mkfixinc.sh: The machine case elements were
+ out-of-order. (the ix86-*-linux-gnu* entry needed to
+ be earlier).
- * dbxout.c (dbxout_parms): If mode of type of parameter living
- in memory doesn't match mode of DECL_RTL, make big endian correction.
+Wed Mar 10 00:01:24 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Fri May 15 21:40:06 1998 John Wehle (john@feith.com)
+ * reload1.c (reload_combine_note_store): Fix calculation of number
+ of affected registers.
- * i386.md (movdi-1, movdi): Rewrite based on SI move patterns.
+Tue Mar 9 15:48:15 1999 Richard Henderson <rth@cygnus.com>
-Fri May 15 18:55:22 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * flow.c (tidy_fallthru_edge): Be more careful finding the last
+ BARRIER of a list. Delete the cc0 setter as well as a cond jump.
- * tree.h (BINFO_SIZE, TYPE_BINFO_SIZE): New macros.
- * stor-layout.c (layout_record): Set it.
+Tue Mar 9 15:26:02 1999 Hans-Peter Nilsson <hp@bitrange.com>
-Fri May 15 18:49:30 1998 Mark Mitchell <mmitchell@usa.net>
+ * i386.md (ashlsi3 splitter): Fix typo in last change.
- * toplev.c (rest_of_compilation): Don't defer nested functions.
+Tue Mar 9 11:35:20 1999 Richard Henderson <rth@cygnus.com>
-Fri May 15 17:42:52 1998 Bob Manson <manson@charmed.cygnus.com>
+ * reg-stack.c (stack_reg_life_analysis): Use returnjump_p
+ instead of an explicit test for RETURN.
- * config/rs6000/rs6000.c (rs6000_stack_info): Align the stack bottom
- to an 8-byte boundary if info_ptr->fpmem_p.
+Tue Mar 9 09:33:16 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Fri May 15 17:36:11 1998 Bill Moyer <ttk@cygnus.com>
+ * Makefile.in (toplev.o): Depend on $(BASIC_BLOCK_H).
- * loop.c (basic_induction_var): Added test preventing
- CCmode parameter passed to convert_modes().
+ * toplev.c: Include basic-block.h.
-Fri May 15 17:26:18 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
+Tue Mar 9 02:08:17 1999 Jeffrey A Law (law@cygnus.com)
- * expr.c (expand_expr, case EXPR_WITH_FILE_LOCATION): Save/restore
- input_filename and lineno around expand_expr call. Set them to values
- in WFL before expand_expr call.
+ * calls.c (load_register_parameters): New function.
+ (expand_call): Use it.
-Fri May 15 12:44:57 1998 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+ * calls.c (expand_call): Slightly reorganize code.
- * stor-layout.c (set_sizetype): Set TYPE_NAME on bitsizetype.
+ * calls.c (compute_argument_addresses): New function.
+ (rtx_for_function_call): New function.
+ (expand_call): Use them.
-Fri May 15 07:20:03 1998 Mark Mitchell <mmitchell@usa.net>
+ * i386.md (zero_extendhisi2): Split into an expander and anonymous
+ pattern. Add new anonymous pattern for use when optimizing for
+ size or for the PPro.
+ (zero_extendqihi2, zero_extendqisi2): Likewise.
- * fold-const.c (constant_boolean_node): New function.
- (fold): Use it.
+Mon Mar 8 23:43:47 1999 Richard Henderson <rth@cygnus.com>
-Fri May 15 11:21:16 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * haifa-sched.c (sched_analyze_1): Fix last change -- add clobber
+ dependencies to sets in the non-hard-reg case too.
- * sh.c (gen_shl_and): Don't sign extend constant for kind two.
- Abort if trying to split kind 3 or 4 outside of combine.
+Mon Mar 8 18:55:21 1999 Marc Espie <espie@cvs.openbsd.org>
-Fri May 15 01:47:37 1998 Jeffrey A Law (law@cygnus.com)
+ * config/openbsd.h (HANDLE_SYSV_PRAGMA): Define.
- * mips.c (print_operand, case 'x'): Use HOST_WIDE_INT_PRINT_HEX.
+Mon Mar 8 16:04:44 1999 Jim Wilson <wilson@cygnus.com>
-Fri May 15 01:42:45 1998 Mumit Khan <khan@xraylith.wisc.edu>
+ * local-alloc.c (combine_regs): Don't combine if we have a hard reg
+ for which CLASS_LIKELY_SPILLED_P is true.
- * objc/Make-lang.in (OBJC_O): Add missing exeext.
- (libobjc.a, runtime-info.h): Likewise.
+ * unroll.c (loop_iterations): Only call loop_find_equiv_value if we
+ have a REG or SUBREG.
-Fri May 15 01:29:39 1998 John Wehle (john@feith.com)
+Mon Mar 8 15:27:42 1999 Jeffrey A Law (law@cygnus.com)
- * i386.h (DATA_ALIGNMENT): Define.
+ * i386.md (ashlsi3): Revise comments. Provide new anonymous
+ pattern for Pentium and PPro/PII. Reverse constraints in
+ generic ashlsi3 anonymous pattern.
-Fri May 15 05:35:37 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * calls.c (initialize_argument_info): Accept a pointer to
+ CUMULATIVE_ARGS.
+ (expand_call): Pass the address of CUMULATIVE_ARGS.
- * reload1.c (delete_output_reload): Ignore single USE that
- was emitted for the pseudo use of this INSN.
- If the no reference to REG between OUTPUT_RELOAD_INSN and INSN
- remains, we can always delete OUTPUT_RELOAD_INSN.
+ * rs6000/xm-sysv4.h (HOST_BITS_PER_LONGLONG): Remove #if 0.
-Thu May 14 18:38:50 1998 Jim Wilson <wilson@cygnus.com>
+ * mn10300.h (CASE_DROPS_THROUGH): Delete.
+ * mn10200.h (CASE_DROPS_THROUGH): Delete.
+ * h8300.h (CASE_DROPS_THROUGH): Delete.
- * reload.c (find_reloads): Don't penalize SCRATCH output reload.
+ * flow.c (merge_blocks_nomove): For HAVE_cc0 targets, make sure
+ to also delete the cc0 setter when deleting a conditional branch
+ to the next block.
-Thu May 14 15:10:30 1998 Jeffrey A Law (law@cygnus.com)
+Mon Mar 8 18:47:11 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * Makefile.in (expr.o): Remove dependency on deleted modemap.def file.
+ * regmove.c (copy_src_to_dest): New argument max_old_uid.
-Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Mon Mar 8 08:23:00 1999 Bruce Korb <korb@datadesign.com>
- * eh-common.h: New file for basic EH data structures.
- * except.h: Various prototypes and structures for NEW_EH_MODEL
- * function.h (struct function): Add a struct eh_stack for the catch
- clause stack.
- * except.c (gen_exception_label): New function to generate an
- exception label.
- (push_eh_entry): Use gen_exception_label() and init 'label_used' field.
- (push_entry): New function to push an existing entry onto a stack.
- (receive_exception_label): New function to emit the code required
- at the start of all catch blocks.
- (struct func_eh_entry): New structure for maintaining handlers
- associated with EH regions.
- (new_eh_region_entry): New function to register an EH region.
- (add_new_handler): New function to register a handler with a region.
- (get_new_handler): Creates anew handler entry for registering.
- (find_func_region): New function to convert a NOTE eh region number
- to an Eh region index.
- (get_first_handler): New function to get the first handler in a region.
- (clear_function_eh_region): New function to release memory.
- (duplicate_handlers): New function to duplicate a list of handlers.
- (expand_eh_region_end): Create a new region entry node as well.
- (expand_leftover_cleanups): Call receive_exception_label() and
- register the cleanup as a handler to the current region.
- (expand_start_catch): New function to start a catch clause.
- (expand_end_catch): New function to end a catch clause.
- (expand_start_all_catch): restructure to not do the equivilent of
- what expand_start_catch() does now. Push the exception region being
- handled onto the catch stack.
- (output_exception_table_entry): Issue an entry for each handler
- associated with a region.
- (set_exception_lang_code): New function for setting the language code.
- (set_exception_version_code): New function to set the version number.
- (output_exception_table): Output version and language codes.
- (find_exception_handler_labels): Find handler labels using new scheme.
- (is_exception_handler_label): New function, returns 1 if label is
- present as a handler in some exception region.
- (check_exception_handler_labels): Use the new scheme.
- (init_eh_for_function): Initialize the catch stack.
- (save_eh_status): Save the catch stack.
- (restore_eh_status): Restore the catch stack.
- (scan_region): Don't remove unreferenced handler label. Flow does it.
- (get_reg_for_handler): New function to get the eh_context pointer
- passed by __throw.
- (expand_builtin_eh_stub): Changes required for NEW_EH_MODEL only.
- * final.c (final_scan_insn): With NEW_EH_MODEL, add EH table
- entry when processing END region rather that START region.
- * flow.c (find_basic_blocks_1): Find all potential handler regions
- now that we don't automatically know what the labels might be.
- Let scan_region() remove unreferenced EH BEGIN/END labels.
- * integrate.c (get_label_from_map): Put inlined labels onto the
- permanent obstack since we dont know which ones might be exception
- labels.
- (save_for_inline_copying): Make new copies of all the handlers.
- (expand_inline_function): Make new copies of all the handlers.
- * libgcc2.c: Remove local struct decls, and include eh-common.h.
- (find_exception_handler): With NEW_EH_MODEL the first matching
- region we find is the right one. Add eh_info as a new parameter.
- (__throw): Pass eh_info to find_exception_handler. Set handler
- and pass use different regs under NEW_EH_MODEL.
-
-Thu May 14 12:58:21 1998 Jim Wilson <wilson@cygnus.com>
-
- * i960.h (hard_regno_mode_ok): Changed to function from array of
- unsigned.
- (HARD_REGNO_MODE_OK): Call function instead of testing bit.
- * i960.c (hard_regno_mode_ok): Changed to function from array of
- unsigned.
-
-Thu May 14 08:41:46 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * reload.c (remove_replacements): New function.
- * reload.h (remove_replacements): Declare.
- * reload1.c (choose_reload_regs): Disable some reloads that
- belong to inherited reloads.
-
-Thu May 14 02:17:17 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * loop.c (scan_loop): Don't call move_moveables for optimize_size.
-
- * reload1.c (merge_assigned_reloads): When merging, reset
- reload_spill_index for the eliminated reload.
-
-Wed May 13 17:51:13 1998 Jeffrey A Law (law@cygnus.com)
-
- * haifa-sched.c (schedule_insns): Fix merge goof.
-
-1998-05-13 Jim Wilson <wilson@cygnus.com>
-
- * varasm.c (make_decl_rtl): Revert April 1 change.
- * alpha/alpha.h, alpha/win-nt.h, arm/arm.h, i386/unix.h, i960/i960.h,
- m68k/linux.h, pa/pa.h, sparc/sparc.h, vax/vax.h (ASM_OUTPUT_MI_THUNK):
- Get function name from the SYMBOL_REF in the DECL_RTL, not from
- DECL_ASSEMBLER_NAME.
- * i386/winnt.c (gen_stdcall_suffix): Comment for questionable use of
- DECL_ASSEMBLER_NAME.
-
-Wed May 13 13:09:19 1998 Jim Wilson <wilson@cygnus.com>
-
- * i386.c (notice_update_cc, output_float_compare): Disable
- TARGET_CMOVE support.
-
-Wed May 13 15:28:59 1998 Michael Meissner <meissner@cygnus.com>
- Jeff Law <law@cygnus.com>
+ * ChangeLog: Merged entries from fixincl-branch.
- * rtlanal.c (find_reg_note): Ignore notes that are not on on
- insns of class 'i'.
- (find_regno_note): Likewise.
-
- * Makefile.in (stor-layout.o): Depend on except.h
- (varasm.o, function.o): Likewise.
- (expr.o): Depend on except.h, modemap.def and hard-reg-set.h.
-
- * Makefile.in (HOST_RTL): Add $(HOST_PREFIX)bitmap.o.
- (rtl.o, emit-rtl.o): Add dependency on bitmap.h.
- ($(HOST_PREFIX_1)rtl.o): Likewise.
- ($(HOST_PREFIX_1)bitmap.o): New host object.
- * emit-rtl.c (toplevel): Include bitmap.h.
- (gen_rtx): Handle 't' and 'b' nodes.
- * print-rtl.c (print_rtx): Handle printing NOTE_INSN_LIVE notes.
- Print block number for block begin/end notes. Print 't' type
- nodes as a pointer. Know that the 3rd argument of live range
- start/stop notes is really a range_info rtx. If type is 'b', print
- out argument as a bitmap.
- * rtl.c: Include bitmap.c.
- (copy_rtx): Copy tree nodes as is. Copy bitmaps if type is 'b'.
- (note_insn_name): Add NOTE_INSN_RANGE_{START,END}, NOTE_INSN_LIVE.
- * rtl.def (RANGE_LIVE): New node to hold live information while we
- recalculate the basic blocks.
- (RANGE_REG, RANGE_INFO): New rtl types for live range splitting.
- (RANGE_VAR): New node, to hold information saved in symbol node for New
- communicating live range information to the debug output functions.
- * rtl.h (rtunion_def): Add rttree and rtbit fields.
- (XBITMAP, XTREE): New accessor macros.
- (NOTE_LIVE_INFO): Overload NOTE_SOURCE_FILE for NOTE_INSN_LIVE notes.
- (NOTE_RANGE_INFO): Similarly for NOTE_INSN_RANGE_{START,END} notes.
- (NOTE_BLOCK_LIVE_RANGE_BLOCK): Define.
- (NOTE_INSN_RANGE_START, NOTE_INSN_RANGE_END, NOTE_INSN_LIVE): New notes.
- (RANGE_LIVE_{BITMAP,ORIG_BLOCK}): New accessor macros.
- (RANGE_REG_{SYMBOL,BLOCK}_NODE, RANGE_VAR_*): New accessor macros.
- (RANGE_INFO_*): Likewise.
- * sched.c (sched_analyze): Keep live range start/stop notes.
- (unlink_other_notes): Likewise.
- * haifa-sched.c (sched_analyze): Keep live range start/stop notes.
- (unlink_other_notes): Likewise.
- * tree.h (BLOCK_LIVE_RANGE_{START,END,VAR_FLAG}): New accessor macros.
- (BLOCK_LIVE_RANGE_FLAG): Likewise.
- (DECL_LIVE_RANGE_RTL): Likewise.
- (struct tree_block): Add live_range_flag, live_range_var_flag,
- live_range_start and live_range_end.
- (struct tree_decl): Add live_range_rtl field.
- * gengenrtl.c (type_from_format): Handle 'b' and 't'.
- (accessor_from_format): Likewise.
-
- * haifa-sched.c (schedule_block): Make verbose output line up.
- Also add a blank line in printing the individual ready lists.
-
-Wed May 13 15:43:44 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * Makefile.in (c-lang.o): Depend on c-tree.h, c-lex.h and toplev.h.
- (c-lex.o): Depend on output.h.
- (c-common.o): Likewise.
- (stmt.o): Likewise.
- (calls.o): Likewise.
- (integrate.o): Depend on toplev.h.
- (regclass.o): Depend on output.h.
- (final.o): Depend on reload.h.
-
- * c-common.c: Include output.h.
- (check_format_info): Remove unused variable `integral_format'.
-
- * c-decl.c (print_lang_decl): Mark parameters `file', `node' and
- `indent' with ATTRIBUTE_UNUSED.
- (print_lang_type): Likewise.
- (maybe_build_cleanup): Likewise for parameter `decl'.
- (copy_lang_decl): Likewise for parameter `node'.
-
- * c-lang.c: Include c-tree.h, c-lex.h and toplev.h.
- (lang_print_xnode): Mark parameters `file', `node' and `indent'
- with ATTRIBUTE_UNUSED.
- (lookup_interface): Likewise for parameter `arg'.
- (is_class_name): Likewise.
- (maybe_objc_check_decl): Likewise for parameter `decl'.
- (maybe_objc_comptypes): Likewise for parameters `lhs', `rhs' and
- `reflexive'.
- (maybe_objc_method_name): Likewise for parameter `decl'.
- (build_objc_string): Likewise for parameters `len' and `str'.
-
- * c-lex.c: Include output.h.
-
- * c-lex.h (position_after_white_space): Correct typo in prototype.
-
- * c-tree.h (finish_file, c_expand_start_cond, c_expand_start_else,
- c_expand_end_cond, init_iterators): Add prototypes.
-
- * caller-save.c (set_reg_live): Mark parameters `reg' and `setter'
- with ATTRIBUTE_UNUSED.
+Sun Mar 7 11:48:56 1999 Richard Henderson <rth@cygnus.com>
- * calls.c: Include output.h.
+ * haifa-sched.c (ENCODE_BLOCKAGE): Don't shift unit too far.
+ (print_exp): Special case addition of a constant.
+ (print_value) [CONST_INT]: Use HOST_WIDE_INT_PRINT_HEX.
- * cccp.c (pipe_closed): Mark parameter `signo' with
- ATTRIBUTE_UNUSED.
+Sun Mar 7 11:21:02 1999 Richard Henderson <rth@cygnus.com>
- * combine.c: Move inclusion of expr.h to after insn-config.h.
+ * haifa-sched.c (reg_last_clobbers): New.
+ (reg_pending_clobbers, bb_reg_last_clobbers): New.
+ (compute_block_backward_dependences): Allocate memory for them.
+ (schedule_region): Likewise.
+ (sched_analyze_1): Clobbers don't interfere with one another.
+ They do interfere with sets ...
+ (sched_analyze_2): ... and uses.
+ (sched_analyze): Likewise.
+ (sched_analyze_insn): Update reg_last_clobbers appropriately.
- * iris6.h (ASM_IDENTIFY_GCC, ASM_IDENTIFY_LANGUAGE): Don't define
- as empty, rather define as ((void)0).
+Sun Mar 7 08:30:37 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * sparc.c (sparc_check_64): Add braces around ambiguous `else'.
- Add parentheses around assignment used as truth value.
+ * gmon-sol2.c: Include config.h and system.h. Don't redundantly
+ include system header files.
+ (sccsid): Remove.
+ (moncontrol, monstartup, _mcleanup, internal_mcount): Prototype.
+ (_mcleanup): Add the `const' keyword to a char*.
+ (internal_mcount): Declare `etext' as a char[] not a function.
+ Cast `etext' to char* when calling `monstartup'.
- * cplus-dem.c (squangle_mop_up): Change return type to void.
- (internal_cplus_demangle): Remove unused parameter `options'.
- All callers changed.
- (cplus_demangle_opname): Remove function wide variable `int i' and
- replace with `size_t i' at each location where it is used.
- (cplus_demangle_opname): change type of `i' from int to size_t.
+ * sparc.c (frame_base_name, save_regs, restore_regs,
+ build_big_number, sparc_cmodel_string, sparc_align_loops_string,
+ sparc_align_jumps_string, sparc_align_funcs_string, code_model,
+ cpu_default, cpu_table, output_function_prologue,
+ output_function_epilogue, output_return,
+ sparc_flat_output_function_prologue, ultra_code_names,
+ sparc_flat_output_function_epilogue): Constify a char*.
+ (hypersparc_adjust_cost): Add a default case in a switch.
- * cppexp.c (right_shift): Mark parameter `pfile' with
- ATTRIBUTE_UNUSED.
+ * sparc.h (sparc_cmodel_string, OVERRIDE_OPTIONS,
+ sparc_cpu_select, sparc_align_loops_string,
+ sparc_align_jumps_string, sparc_align_funcs_string,
+ output_return): Constify a char*.
- * cpphash.c (cpp_lookup): Likewise.
- (cpp_hash_cleanup): Likewise.
+ * sparc.md (movdi): Change the comparison of HOST_BITS_PER_WIDE_INT
+ so that we check "== 32", instead of "!= 64". Cast a value to
+ HOST_WIDE_INT when comparing against one. Hide the declaration
+ for variable `chain'.
- * cpplib.c (parse_name): Add a prototype and make it static.
- (null_underflow): Mark parameter `pfile' with ATTRIBUTE_UNUSED.
- (null_cleanup): Likewise for parameters `pbuf' and `pfile'.
- (macro_cleanup): Likewise for parameter `pfile'.
- (file_cleanup): Likewise.
+Sun Mar 7 08:05:27 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * cpplib.h (cpp_reader_init, cpp_options_init, cpp_start_read,
- cpp_read_check_assertion, skip_rest_of_line): Add prototypes.
+ * system.h (const, inline): Move the stage2 handling of these
+ keywords-as-macros from here...
- * crtstuff.c (force_to_data, __CTOR_LIST__, force_to_data,
- __DTOR_END__, __FRAME_END__): Mark with ATTRIBUTE_UNUSED.
+ * gansidecl.h (const, inline): ...to here.
- * cse.c (cse_check_loop_start): Mark parameter `set' with
- ATTRIBUTE_UNUSED.
+Sun Mar 7 02:44:15 1999 Richard Henderson <rth@cygnus.com>
- * dbxout.c (flag_minimal_debug, have_used_extensions,
- source_label_number): Move inside macro wrapper check against
- defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO).
+ * recog.c (push_operand, pop_operand): VOIDmode needn't match modes.
- * dwarf2out.c (gen_entry_point_die): Hide prototype and definition.
+Sun Mar 7 01:58:47 1999 Richard Henderson <rth@cygnus.com>
- * except.h (doing_eh): Provide prototype.
+ * cse.c (canon_hash): Never reject hard regs in CCmode.
- * expr.c: Move inclusion of expr.h to after insn-config.h.
+Sun Mar 7 01:15:04 1999 Jeff Law (law@cygnus.com)
- * final.c: Include reload.h.
- (shorten_branches): Cast the first argument of bzero to char *.
+ * version.c: Bump for snapshot.
- * fix-header.c (cpp_print_containing_files): Mark parameter
- `pfile' with ATTRIBUTE_UNUSED.
- (cpp_fatal): Likewise.
+Sat Mar 6 17:18:44 1999 Richard Earnshaw (rearnsha@arm.com)
+ Richard Henderson <rth@cygnus.com>
- * flow.c (find_basic_blocks_1): Cast the first argument of bzero
- to char *.
+ * flow.c (make_edges): Handle casesi that jump to default branch.
+ If CASE_DROPS_THROUGH, force fallthru to block after casesi.
- * genattrtab.c (make_length_attrs): Change the type of variable
- `i' from int to size_t.
- (zero_fn): Mark parameter `exp' with ATTRIBUTE_UNUSED.
- (one_fn): Likewise.
+Sat Mar 6 07:49:23 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * genextract.c (main): When generating insn-extract.c, mark
- variable `junk' with ATTRIBUTE_UNUSED.
+ * c-aux-info.c (data_type, affix_data_type, gen_decl,
+ gen_formal_list_for_type, gen_formal_list_for_func_def, gen_type):
+ Qualify a char* with the `const' keyword.
- * gengenrtl.c (gencode): When generating genrtl.c, cast the first
- argument of bzero to char*.
+ * c-common.c (declare_hidden_char_array, add_attribute, if_elt,
+ declare_function_name, decl_attributes, format_char_info,
+ check_format_info, binary_op_error): Likewise.
- * integrate.c: Include toplev.h.
+ * cexp.y (yyerror, error, pedwarn, warning, token): Likewise.
- * libgcc2.c: Wrap `struct exception_table' and
- `find_exception_handler' in macro DWARF2_UNWIND_INFO.
+ * gcse.c (dump_hash_table): Likewise.
- * objc/Make-lang.in (objc-act.o): Depend on toplev.h.
+ * integrate.c (function_cannot_inline_p): Likewise.
- * objc/objc-act.c: Include toplev.h.
- (lang_print_xnode): Mark parameters `file', `node' and `indent'
- with ATTRIBUTE_UNUSED.
- (finish_protocol): Likewise for parameter `protocol'.
+ * optabs.c: Include insn-config.h earlier.
+ (init_libfuncs, init_integral_libfuncs, init_floating_libfuncs):
+ Qualify a char* with the `const' keyword.
- * output.h (declare_weak): Add prototype.
- (decode_reg_name): Don't wrap with TREE_CODE macro.
- (assemble_alias): Add prototype.
+ * real.c (asctoe24, asctoe53, asctoe64, asctoe113, asctoe,
+ asctoeg, mtherr, ereal_atof): Likewise.
- * regclass.c: Include output.h.
+ * real.h (ereal_atof): Likewise.
- * reload.h (reloads_conflict): Add prototype.
+ * sbitmap.c (dump_sbitmap_vector): Likewise.
- * rtl.h (print_rtl_single, mark_elimiation, reg_class_subset_p,
- output_func_start_profiler): Add prototypes.
+ * sbitmap.h (dump_sbitmap_vector): Likewise.
- * rtlanal.c (reg_set_p_1): Mark parameters `x' and `pat' with
- ATTRIBUTE_UNUSED.
+ * stmt.c (nesting, n_occurrences, expand_start_case): Likewise.
- * scan-decls.c: Include scan.h.
+ * toplev.c (rest_of_compilation): Likewise.
- * scan.h (recognized_function, recognized_extern): Add prototypes.
+ * tree.h (function_cannot_inline_p, expand_start_case): Likewise.
- * stmt.c: Include output.h.
+Fri Mar 5 23:16:42 1999 David Edelsohn <edelsohn@gnu.org>
- * toplev.c (error_for_asm, warning_for_asm): Remove prototypes.
- (output_lang_identify): Hide prototype and definition.
- (float_signal): Mark parameter `signo' with ATTRIBUTE_UNUSED.
- (pipe_closed): Likewise.
+ * rs6000.h (ASM_OUTPUT_REG_{PUSH,POP}): Add 64-bit support and do
+ not overwrite AIX link register save area.
- * toplev.h (count_error, strip_off_ending, error_for_asm,
- warning_for_asm): Add prototypes.
+Fri Mar 5 23:08:01 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Wed May 13 12:54:19 1998 Michael Meissner <meissner@cygnus.com>
+ * reload.c (find_reloads_subreg_address): Actually create the USE
+ for the register, not the new memory location.
- * toplev.c (rest_of_compilation): "Charge" final for any time
- doing various cleanup operations after finishing compilation
- of a function.
+Fri Mar 5 21:41:07 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * flow.c (dump_flow_info): Also print number of sets and
- whether or not the pseudo is a user variable.
+ * reload1.c (emit_reload_insns): If pseudo that can't be replaced
+ with its equivalent constant, fall back to reload_in.
- * flow.c (reg_n_max): New global variable.
- * regclass.c (allocate_reg_info): Keep reg_n_max up to date.
- Delete regno_max variable.
- * regs.h (REG_N_CHECK): Define.
- (REG_N_REFS, REG_N_SETS, REG_N_DEATHS): Use REG_N_CHECK.
- (REG_N_CHANGES_SIZE, REG_N_CALLS_CROSSED, REG_LIVE_LENGTH): Likewise.
- (REGNO_FIRST_UID, REGNO_LAST_UID, REGNO_LAST_NOTE_UID): Likewise.
+Fri Mar 5 13:20:39 1999 Richard Henderson <rth@cygnus.com>
-Wed May 13 12:54:19 1998 Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>
+ * Makefile.in: Delete .flow2 debugging files.
- * acconfig.h (ENABLE_CHECKING): Undefine.
- * configure.in (--enable-checking): New option.
+Fri Mar 5 11:36:11 1999 Nick Clifton <nickc@cygnus.com>
-Wed May 13 08:52:08 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * config/arm/arm.c (arm_override_options): Change default target
+ cpu selection so that enabling TARGET_APCS_32 does not override
+ default target CPU.
- * reload1.c (merge_assigned_reloads): Can merge
- RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_OTHER_ADDRESS even
- if RELOAD_FOR_INPUT with the same reload_reg_rtx is present.
+Fri Mar 5 19:26:23 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Tue May 12 20:05:57 1998 Jim Wilson <wilson@cygnus.com>
+ * sh.h (SLOW_BYTE_ACCESS): Define to 1.
+ (BOOL_TYPE_SIZE): Define.
- * collect2.c (main): Ignore do_collecting when COLLECT_EXPORT_LIST.
+Fri Mar 5 02:14:54 1999 John Wehle (john@feith.com)
-Wed May 13 03:23:45 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * function.c (assign_stack_temp_for_type): Abort
+ if mode == Blkmode and align is less than
+ BIGGEST_ALIGNMENT / BITS_PER_UNIT.
+ (assign_stack_temp_for_type): Round the size parameter
+ passed to assign_stack_local instead of size itself.
- * reload1.c (gen_reload): Create REG_EQUIV notes.
+Thu Mar 4 15:00:35 1999 Richard Henderson <rth@cygnus.com>
-Tue May 12 22:21:07 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * flow.c (delete_unreachable_blocks): Mark blocks as they
+ are put on to the worklist, not as they are taken off.
- * reload1.c (reload): Fix check for USEs to use code of pattern.
- (choose_reload_regs): Remove dead variable use_insn.
+Thu Mar 4 00:05:44 1999 Jeffrey A Law (law@cygnus.com)
-Tue May 12 14:04:49 1998 Jeffrey A Law (law@cygnus.com)
+ * function.c (current_function_has_computed_jump): Remove duplicate
+ definition.
- * pa.h (DBX_CONTIN_LENGTH): Reduce to 3000 bytes.
+Wed Mar 3 19:09:11 1999 Jim Wilson <wilson@cygnus.com>
-Tue May 12 15:16:02 1998 Michael Meissner <meissner@cygnus.com>
+ * m68k/m68020-elf.h (INIT_SECTION_ASM_OP, FINI_SECTION_ASM_OP): Undef.
+ (STARTFILE_SPEC, ENDFILE_SPEC): Define to empty string.
- * haifa-sched.c (HAIFA_INLINE): Define to be __inline unless
- already defined.
- (find_insn_{,mem_}list): Use HAIFA_INLINE, not __inline.
- (insn_{unit,issue_delay}): Ditto.
- (blockage_range): Ditto.
- (actual_hazard{,_this_instance}): Ditto.
- (schedule_unit): Ditto.
- (potential_hazard): Ditto.
- (insn_cost): Ditto.
- (swap_sort): Ditto.
- (queue_insn): Ditto.
- (birthing_insn_p): Ditto.
- (adjust_priority): Ditto.
- (get_block_head_tail): Ditto.
- (init_rgn_data_dependences): Ditto.
+ * sparc/elf.h (MULDI3_LIBCALL, DIVDI3_LIBCALL, UDIVDI3_LIBCALL,
+ MODDI3_LIBCALL, UMODDI3_LIBCALL, STDC_0_IN_SYSTEM_HEADERS): Undef.
+ (INIT_SUBTARGET_OPTABS): Define to empty.
-Tue May 12 10:27:54 1998 Klaus Kaempf <kkaempf@progis.de>
+Wed Mar 3 00:00:37 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * alpha/vms.h (COMMON_ASM_OP, ASM_OUTPUT_ALIGNED_COMMON): Define.
+ * sh.c (force_into): New function.
+ (expand_block_move): Use it.
-Tue May 12 11:44:14 1998 Gavin Koch <gavin@cygnus.com>
+Tue Mar 2 10:39:43 1999 Nick Clifton <nickc@cygnus.com>
- * config/mips/mips.h (ASM_OUTPUT_ALIGN): Remove trailing semi-colon.
+ * cccp.c (struct default_include): Add 'included' field.
+ (main): Set 'included' field when a default include directory
+ is added to the chain. If -v is specified list all default
+ include directories which do not get appended to the chain.
-Tue May 12 11:38:31 1998 Gavin Koch <gavin@cygnus.com>
+Tue Mar 2 09:24:10 1999 Nick Clifton <nickc@cygnus.com>
- * config/mips/mips.md (dslot): Move after definition of "cpu"
- attribute. Handle r3900 case.
+ * configure.in (gxx_include_dir): Rename to
+ gcc_gxx_include_dir in order to prevent it being overridden by
+ a top level Makefile.
+ (gcc_tooldir): If $exec_prefix != $prefix then use the
+ difference between the two as the basis for gcc_tooldir.
-Tue May 12 10:21:36 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * configure: Rebuild.
- * system.h: Define the STRINGIFY macro here.
- * protoize.c: Not here.
- * gengenrtl.c (DEF_RTL_EXPR): Use the STRINGIFY macro.
+ * Makefile.in: Rename gxx_include_dir to gcc_gxx_include_dir.
-Tue May 12 00:47:33 1998 John Wehle (john@feith.com)
+Tue Mar 2 16:45:31 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * varasm.c (assemble_variable): Compute the alignment of the data
- earlier so that both initialized and uninitialized variables are
- effected by DATA_ALIGNMENT.
- * tm.texi (DATA_ALIGNMENT): Updated appropriately.
+ * unroll.c (copy_loop_body): Don't make extra copies of
+ NOTE_INSN_LOOP_CONT notes.
-Mon May 11 19:57:58 1998 Jeffrey A Law (law@cygnus.com)
+Tue Mar 2 07:44:56 1999 Mark Mitchell <mark@markmitchell.com>
- * mips.c: Prototype static functions.
+ * tree.c (save_tree_status): Don't treat functions with no context
+ as nested.
-Mon May 11 17:43:03 1998 Jim Wilson <wilson@cygnus.com>
+Tue Mar 2 09:37:05 1999 Robert Lipe <robertlipe@usa.net>
- * regmove.c (fixup_match_2, find_matches, regmove_profitable):
- Add explanatory comments.
+ * Makefile.in (MAKEINFO): Use makeinfo built from sibling
+ tree when available.
- * sparc.h (SPARC_INCOMING_INT_ARG_FIRST): Support TARGET_FLAT.
+Tue Mar 2 10:12:48 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon May 11 17:24:27 1998 Richard Henderson <rth@cygnus.com>
+ * alpha.c (alpha_cpu_name, alpha_cpu_string, alpha_tp_string,
+ alpha_fprm_string, alpha_fptm_string, alpha_mlat_string,
+ current_function_file): Add the `const' keyword.
+ (normal_memory_operand): Mark parameter `mode' with
+ ATTRIBUTE_UNUSED.
+ (alpha_expand_unaligned_load): Add a default case to a switch.
- * sparc.md (ffsdi2): Disable. Simplify the expression as well.
+ * alpha.h (alpha_cpu_string, alpha_fprm_string, alpha_fptm_string,
+ alpha_tp_string, alpha_mlat_string): Add the `const' keyword.
+ (normal_memory_operand): Add prototype.
-Mon May 11 13:30:44 1998 Jim Wilson <wilson@cygnus.com>
+ * alpha.md: Cast an expression to `unsigned HOST_WIDE_INT' when
+ comparing against one.
- * varasm.c (make_decl_rtl): Disable April 1 change.
+Tue Mar 2 10:00:21 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon May 11 09:14:41 1998 Richard Henderson <rth@cygnus.com>
+ * mips.c (abort_with_insn): Make function static, add a prototype,
+ constify 2nd parameter and mark with ATTRIBUTE_NORETURN.
+ (current_function_file, mips_cpu_string, mips_isa_string,
+ mips_abi_string, mips_no_mips16_string, mips_entry_string,
+ mips_move_1word, mips_move_2words, output_block_move, load_store,
+ override_options, make_temp_file, mips16_fp_args): Qualify a char*
+ with the `const' keyword.
- * configure.in (alpha-*-linux-gnu): Undo lossage from gcc2 merge.
+ * mips.h (current_function_file, mips_cpu_string, mips_isa_string,
+ mips_abi_string, mips_entry_string, mips_no_mips16_string,
+ mips_move_1word, mips_move_2words, output_block_move): Likewise.
+ (abort_with_insn): Remove extern prototype.
-Mon May 11 08:24:18 1998 Richard Henderson <rth@cygnus.com>
+ * mips.md: Qualify a char* with the `const' keyword.
+ Remove many unused variables named `label'.
- * alpha.h (PRINT_OPERAND_PUNCT_VALID_P): Add '`'.
- * alpha.c (print_operand): Handle it.
- * alpha.md (fix_truncdfsi2, fix_truncsfsi2): New patterns and
- related define_splits. Also add peepholes for SImode reload
- plus sign_extend lossage.
+Tue Mar 2 01:27:52 1999 H.J. Lu (hjl@gnu.org)
-Mon May 11 09:33:10 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * Makefile.in (cpp_install_dir, INSTALL_CPP, UNINSTALL_CPP): New
+ variables.
+ (install-cpp, uninstall-cpp): New targets.
+ (install-normal): Depend on $(INSTALL_CPP).
+ (uninstall): Depend on $(UNINSTALL_CPP).
+ * configure.in (cpp_install_dir): New, substitute.
+ (tmake_file): Added t-install-cpp for --enable-cpp.
+ * configure: Rebuilt.
+ * cpp.sh: New cpp script.
+ * config/t-install-cpp: New target fragment.
- * genattr.c: Include stdarg.h/varargs.h. Change function
- `fatal' to use variable arguments instead of faking it with
- integer parameters. Provide a prototype which also
- checks the format specifiers using ATTRIBUTE_PRINTF_1.
+Tue Mar 2 01:40:01 1999 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+ Jeffrey A Law (law@cygnus.com)
- * genattrtab.c: Likewise.
- * gencodes.c: Likewise.
- * genconfig.c: Likewise.
- * genemit.c: Likewise.
- * genextract.c: Likewise.
- * genflags.c: Likewise.
- * genopinit.c: Likewise.
- * genpeep.c: Likewise.
- * genrecog.c: Likewise.
- * genoutput.c: Likewise. Similarly for function `error'.
+ * cse.c (fold_rtx): Update comments for (const (minus (label) (label)))
+ case.
+ (cse_insn): Avoid creating a bogus REG_EQUAL note for
+ (const (minus (label) (label)))
+ (record_jump_cond): Fix mismatched paren in comment.
-Sun May 10 02:27:03 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Tue Mar 2 01:07:12 1999 Dan Nicolaescu <dann@godzilla.ics.uci.edu>
- * acconfig.h (HAVE_VOLATILE): Insert stub for autoconf.
- * alocal.m4 (GCC_C_VOLATILE): New autoconf test.
- * configure.in: Use GCC_C_VOLATILE.
- * system.h (volatile): Define as empty if no volatile support is
- available.
+ * final.c (end_final): There are 11 words in the "main header"
+ structure, not 10.
-Sun May 10 01:21:43 1998 Jeffrey A Law (law@cygnus.com)
+Tue Mar 2 00:09:18 1999 Marc Espie <espie@cvs.openbsd.org>
- * genemit.c (output_add_clobbers): Removed unused variable 'i' from
- generated fucntion.
+ * extend.texi: Reference __extension__ in the index.
-Sat May 9 02:02:15 1998 Richard Henderson <rth@cygnus.com>
+Mon Mar 1 19:09:32 1999 Jim Wilson <wilson@cygnus.com>
- * loop.c (get_condition): Don't combine when either compare is MODE_CC.
- * alpha.c (alpha_emit_conditional_branch): New function. Taken from
- the body of beq; additionally set the mode of the branch to CCmode for
- FP compares and not fast_math.
- (alpha_emit_conditional_move): Always use a compare insn for FP
- when not fast_math, as well as setting CCmode on the cmov.
- * alpha.md (beq, bne, blt, et al): Call alpha_emit_conditional_branch.
+ * Makefile.in (CROSS_FLOAT_H): Delete.
+ (FLOAT_H): Use float_h_file.
+ (rest.cross, stmp-int-hdrs): Delete gfloat.h dependency.
+ (gfloat.h): Delete.
+ (stmp-int-hdrs): Use FLOAT_H instead of gfloat.h.
+ (mostlyclean): Delete gloat.h reference.
+ (install-cross-rest, install-float-h-cross, stmp-headers): Update
+ comments.
+ * configure.in (sparcv9-*-solaris2*): Set float_format to none.
+ (sparc-*-solaris2*): Set float_format to none for 2.5 and higher.
+ (float_h_file): Set from float_format. Substitute into Makefile.in.
+ (float_format): No longer substitute into Makefile.in.
+ * cross-make (FLOAT_H): Delete.
+ * config/mips/t-cross64 (FLOAT_H): Delete.
+ * configure: Rebuilt.
- * machmode.h (COMPLEX_MODE_P): New macro.
+Mon Mar 1 16:36:18 1999 Jeffrey A Law (law@cygnus.com)
-Sat May 9 01:53:23 1998 Richard Henderson <rth@cygnus.com>
+ * mips.md (div_trap_normal, div_trap_mips16): Require the dependent
+ insn to be an INSN before looking at its pattern.
- * haifa-sched.c (print_exp): Fix typo.
+Mon Mar 1 15:03:51 1999 Jim Wilson <wilson@cygnus.com>
-Fri May 8 21:48:50 PDT 1998 Jeff Law (law@cygnus.com)
+ * config/m68k/lb1sf68.asm (udivsi3): Change jmi to jcs. Fix comments.
+ * config/m68k/m68k.h (LEGITIMATE_INDEX_REG_P): Reject SIGN_EXTEND of
+ HImode reg when TARGET_5200.
- * version.c: Bump for snapshot.
+Mon Mar 1 21:44:30 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Fri May 8 18:23:08 1998 Michael Meissner <meissner@cygnus.com>
-
- * final.c (final_scan_insn): Call fatal_insn instead of abort if
- we could not split an insn when required to.
-
- * m32r.md ({add,sub}di3): Add define_splits and appropriate low
- level insns.
- (peepholes): Disable peepholes that call dead_or_set_p.
- (movsi): Rewrite to handle addresses better after last change.
- Add define_split to split load of addresses in large/medium modes.
- (prologue): Call m32r_expand_prologue.
- (movsi_{push,pop}): Generators for push/pop.
- (movsi): Support PRE_{INC,DEC}, POST_INC.
- (mov{di,df}): Rewrite. Always split the insns.
- (movsf): Add define_split to get register load in correct mode.
- (cmp_ne_small_const_insn): Use 'N' instead of 'S' constraint.
- (attributes): Rewrite attributes so that type indicates both the
- type and the length of the insn directly.
- (all insns): Change to use new type attributes.
- (debug): New attribute to convey whether -mdebug was used.
- (opt_space): New attribute to convey whether -Os was used.
- (function units): Loads are 3 cycles, not 2. Better classify all
- insns into short/long.
- (load/store/extend insns): Add separate case for load/store
- indirect operations without an offset.
- (divsi3): Division is a long operation, not short.
-
- * m32r.h (LEGITIMATE_LO_SUM_ADDRESS_P): Do not allow LO_SUM for
- modes > 1 word.
- (GO_IF_MODE_DEPENDENT_ADDRESS): LO_SUM is now mode dependent.
- (CONST_OK_FOR_LETTER_P): Make 'N' handle reverse 8 bit compares.
- (EXTRA_CONSTRAINT): Remove 'S' special support. Add 'U' for
- operands with PRE_{INC,DEC}, POST_INC.
- (FUNCTION_PROFILER): Call abort instead of doing nothing.
- (GO_IF_LEGITIMATE_ADDRESS): Allow PRE_{INC,DEC}, POST_INC of
- SImode variables.
- (gen_split_move_double): Declare.
- (EXTRA_CONSTRAINT): Add 'T' for memory reference with no offset.
-
- * m32r.c (gen_split_move_double): Fix typo. Also, don't call
- emit_move_insn, build up SET's directly.
- (toplevel): Include system.h, not stdio.h.
- (move_double_src_operand): Allow any DF or DI mode constant.
- (gen_split_move_double): Split moves of DI or DF values into the
- appropriate moves, loads, or stores. Don't handle use of auto
- inc/dec if using dead index. Do handle overlapping moves, etc.
- (m32r_frame_info): Remove prologue_size field.
- (m32r_compute_frame_size): Don't calculate prologue size.
- (m32r_output_function_prologue): Change to pretty much a NOP.
- (m32r_expand_prologue): Expand prologue as a series of INSNs.
- (m32r_print_operand): Add support for PRE_{INC,DEC}, POST_INC.
- (m32r_print_operand_address): Ditto.
-
-Fri May 8 14:13:21 1998 H.J. Lu (hjl@gnu.org)
-
- * reload1.c (emit_reload_insns): When performing expensive
- optimizations, do not output the last reload insn if OLD is
- not the dest of NSN and is in the src and is clobbered by INSN.
-
-Fri May 8 09:47:29 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * Makefile.in (genrtl.o): Depend on system.h.
- * gengenrtl.c (gencode): When creating genrtl.c, have it
- include system.h.
-
-Fri May 8 10:57:33 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-
- * config/m68k/t-linux: Remove extra stuff already included in
- config/t-linux.
-
-Fri May 8 09:53:24 Paul Eggert <eggert@twinsun.com>
-
- * fixinc.wrap: Renamed from fixinc.math. Put wrapper around
- curses.h if it contains `typedef char bool;', as suggested by
- Manfred Hollstein <manfred@s-direktnet.de>.
-
- * configure.in: Rename fixinc.math to fixinc.wrap.
-
-Thu May 7 19:26:34 1998 Jim Wilson <wilson@cygnus.com>
-
- * gcc.c (read_specs): Handle missing blank line at end of specs file.
-
- * i386.md (movsicc, movhicc, movsicc_1, movhicc_1, movsfcc_1,
- movdfcc_1): Disable.
-
-Thu May 7 15:39:14 1998 Jim Wilson <wilson@cygnus.com>
-
- * configure.in (enable_threads): Rename to enable_threads_flag before
- main loop. Set enable_threads to enable_threads_flag inside main
- loop.
-
-Thu May 7 17:38:03 1998 Michael Meissner <meissner@cygnus.com>
-
- * r6000/eabi.asm (__eabi): Restore LR in case __eabi is called
- multiple times.
-
-Thu May 7 14:26:05 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * aclocal.m4 (GCC_FUNC_VFPRINTF_DOPRNT): New macro.
-
- * configure.in: Add a call to GCC_FUNC_VFPRINTF_DOPRNT.
- (AC_CHECK_HEADERS): Remove unused check for varargs.h,sys/varargs.h.
- (AC_CHECK_FUNCS): Remove unused check for vprintf.
-
- * Makefile.in: Add support for linking in vfprintf.c and doprint.c.
- (cccp.o): Depend on gansidecl.h.
- (cexp.o): Likewise.
-
- * cccp.c: Convert from using PRINTF_ALIST/PRINTF_DCL to VPROTO as
- per the rest of gcc source.
- * cexp.y: Likewise. Include gansidecl.h and remove all code made
- redundant.
-
- * cccp.c: Remove checks for HAVE_VPRINTF and the associated code
- used when vfprintf is missing.
- * cexp.y: Likewise.
- * gcc.c: Likewise.
- * genattrtab.c: Likewise.
- * mips-tfile.c: Likewise.
- * toplev.c: Likewise.
+ From Toshiyasu Morita:
+ * sh.h (CACHE_LOG): SH2 has cache, too.
+
+Mon Mar 1 14:23:36 1999 Catherine Moore <clm@cygnus.com>
+
+ * toplev.c (compile_file): Disable -ffunction-sections and
+ debugging warning if the object format is elf.
- * vfprintf.c: New file.
- * doprint.c: New file.
+Mon Mar 1 11:46:25 1999 Vladimir N. Makarov <vmakarov@cygnus.com>
-Thu May 7 10:18:41 1998 Jeffrey A Law (law@cygnus.com)
+ * config/h8300/h8300.c (print_operand): Use 16 bit addressing
+ when the data in 8-bit area and can not be addressed by 8-bit.
- * config/linux.h (ASM_COMMENT_START): Remove from here,
- * config/linux-aout.h (ASM_COMMENT_START): and here,
- * config/i386/linux.h (ASM_COMMENT_START): to here,
- * config/i386/linux-aout.h (ASM_COMMENT_START): and here.
- * config/i386/linux-oldld.h (ASM_COMMENT_START): Define
- here as '#' too.
+Sun Feb 28 16:40:00 1999 Richard Henderson <rth@cygnus.com>
-Thu May 7 10:55:59 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * flow.c (create_basic_block): Disregard integrated bb notes.
- * config/m68k/m68k.md (adddi3, subdi3): Properly negate the DImode
- constant.
+Sun Feb 28 15:57:06 1999 Richard Henderson <rth@cygnus.com>
+
+ * sparc.md (blockage, nonlocal_goto_receiver): Set length to 0.
+
+Sun Feb 28 14:47:53 1999 Arturo Montes <mitosys@colomsat.com.co>
-Wed May 6 22:32:37 CDT 1998 Robert Lipe <robertl@dgii.com>
+ * config/i386/t-sco5gas (crti.o): New target.
- * Makefile.in (dwarfout.o) Add toplev.h dependency.
- * dwarfout.c, i386.c: Include toplev.h
- * toplev.h: (pfatal_with_name) Add prototype.
+Sun Feb 28 15:10:17 1999 David Edelsohn <edelsohn@gnu.org>
-Wed May 6 19:02:29 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * rs6000.md (elf_high, movsi_got, *movsi_got_internal,
+ *movsi_got_internal_mem, GOT splitter, movdf_hardfloat32,
+ movdf_softfloat32, movdf_hardfloat64, movdf_softfloat64,
+ load_multiple, allocate_stack, call_indirect_aix32,
+ call_indirect_aix64, call_value_indirect_aix32,
+ call_value_indirect_aix64, call_indirect_nt,
+ call_value_indirect_nt): Use gpc_reg_operand instead of
+ register_operand.
- * Makefile.in: Fix .SUFFIXES.
+Sun Feb 28 15:10:17 1999 Michael Meissner <meissner@cygnus.com>
-Wed May 6 19:31:32 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+ * rs6000.md (one_cmplsi2, andsi3, iorsi3, xorsi3, *eqvsi3,
+ *andcsi3, *iorcsi3, *nandsi3, *norsi3): Add alternatives to use CR
+ other than cr0.
+ * rs6000.c (and{,64}_operand): If the user did -ffixed-cr0, don't
+ allow andi. or andis. which always set cr0.
- * config/linux.h (ASM_COMMENT_START): Define as "#".
- * config/linux-aout.h (ASM_COMMENT_START): Likewise.
+Sun Feb 28 01:15:04 1999 Jeff Law (law@cygnus.com)
-Wed May 6 15:51:39 1998 Jim Wilson <wilson@cygnus.com>
+ * version.c: Bump for snapshot.
- * objc/Make-lang.h (objc-parse.o): Add toplev.h dependency.
- * objc/objc-parse.y, objc/objc-parse.c: Regenerate.
+Sun Feb 28 02:00:38 1999 Jeffrey A Law (law@cygnus.com)
- * toplev.c: Include toplev.h.
- * Makefile.in (c-common.o, c-convert.o, c-decl.o, c-iterate.o,
- c-lex.o, c-parse.o, c-pragma.o, c-typeck.o, calls.o, convert.o,
- dwarf2out.o, except.o, expr.o, final.o, fold-const.o, function.o,
- hash.o, profile.o, real.o, reg-stack.o, regclass.o, reload.o,
- reload1.o, stmt.o, stor-layout.o, tlink.o, tree.o, varasm.o): Add
- toplev.h dependency.
+ * invoke.texi: Update information for PA scheduling.
- * mips/mips.c (save_restore_insns): Change FRAME_POINTER_REGNUM to
- HARD_FRAME_POINTER_REGNUM.
+Sat Feb 27 23:21:47 1999 Jerry Quinn <jquinn@nortelnetworks.com>
+ Mike Stump <mrs@wrs.com>
- * expr.c (target_temp_slot_level): Delete duplicate definition.
+ * pa.c (override_options): Change default to 7100LC.
-Wed May 6 16:46:01 1998 Jeffrey A Law (law@cygnus.com)
+ * pa.h (REG_ALLOC_ORDER): Change order to allocate left half of
+ float regs before right half of float regs.
- * stmt.c (mark_seen_cases): Make it have external linkage again.
- * expr.h (mark_seen_cases): Add declaration, but only when tree.h
- has been included.
+Sat Feb 27 22:48:38 1999 H.J. Lu (hjl@gnu.org)
+ Jeffrey A Law (law@cygnus.com)
- * haifa-sched.c (print_value, case SUBREG): Fix typo.
+ * frame.h: Update some comments.
+ * defaults.h (TARGET_ATTRIBUTE_WEAK): Define.
+ * crtstuff.c (__register_frame_info, __deregister_frame_info): Declare
+ using TARGET_WEAK_ATTRIBUTE.
+ (__do_global_dtors_aux): Check if __deregister_frame_info is
+ zero before calling it.
+ (__do_global_dtors): Likewise.
+ (frame_dummy): Check if __register_frame_info is zero before
+ calling it.
+ (__frame_dummy): Likewise.
- * i386.c (output_387_binary_op): Add some braces to avoid warnings.
- * i386.h (REG_CLASS_CONTENTS): Similarly.
+Sat Feb 27 19:18:24 1999 Jeffrey A Law (law@cygnus.com)
- * toplev.c (-fsched-max): Delete flag.
- (-fsched-interblock-max-blocks,-fsched-interblock-max-insns): Likewise.
- * haifa-sched.c: Remove -fsched-max-N, -fsched-interblock-max-blocks-N
- and -fsched-interblock-max-insns-N support. Remove INTERBLOCK_DEBUG
- conditionals.
+ * SERVICE: Update from the FSF.
- * haifa-sched.c (find_rgns): Correctly handle reducible loops with
- inner loops which are not reducible.
+Sat Feb 27 14:31:22 1999 Arturo Montes <mitosys@colomsat.com.co>
- * loop.c (regs_match_p): Fix typo in prototype.
+ * config/i386/t-sco5 (crti.o): New target.
+ * config/i386/sco5.h (STARTFILE_SPEC): Include crti.o when
+ linking -shared.
+ * configure.in (i[34567]86-*-sco3.2v5*): Add crti.o.
- * regmove.c (try_auto_increment): Wrap declaration inside an
- #ifdef AUTO_INC_DEC.
+Sat Feb 27 01:12:40 1999 Jeffrey A Law (law@cygnus.com)
-Wed May 6 17:07:47 1998 Michael Meissner <meissner@cygnus.com>
+ * md.texi (prologue,epilogue): Document named patterns.
- * final.c (output_operand_lossage): Call fatal with the operand
- lossage message instead of calling abort.
+Fri Feb 26 19:31:25 1999 Dave Love <fx@gnu.org>
-Wed May 6 15:37:27 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * md.texi, invoke.texi: Fix unterminated @xrefs.
+
+Fri Feb 26 15:33:45 1999 Richard Henderson <rth@cygnus.com>
+
+ * genattrtab.c (simplify_knowing): Fix uninitialized read
+ in Feb 21 change.
+
+ * genextract.c (main): Clear recog_operands before extracting.
+
+Fri Feb 26 02:24:57 1999 Jeffrey A Law (law@cygnus.com)
+
+ * c-pragma.c (add_weak); Delete. Moved into...
+ * varasm.c (add_weak): New external function.
+ (declare_weak): If HANDLE_PRAGMA_WEAK, then add the function to
+ the list of weak functions.
+ * c-pragma (add_weak): Declare.
+
+Thu Feb 25 23:43:59 1999 Richard Henderson <rth@cygnus.com>
+
+ Flow rewrite to use basic block structures and edge lists:
+
+ * basic-block.h (x_basic_block_head, x_basic_block_end): Kill.
+ (basic_block_computed_jump_target, basic_block_live_at_start): Kill.
+ (struct edge_def): New.
+ (struct basic_block_def): New.
+ (basic_block_info): New.
+ (BLOCK_HEAD, BLOCK_END): Update.
+ (ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR): New.
+ (uid_block_number): Kill.
+ (basic_block_for_insn, BLOCK_FOR_INSN): New.
+ (BLOCK_NUM): Update.
+ * flow.c (XNMALLOC): Kill.
+ (max_uid_for_flow): Kill.
+ (uid_block_number): Kill.
+ (uid_volatile): Turn into a bitmap.
+ (SET_INSN_VOLATILE): New.
+ (basic_block_info): New.
+ (entry_exit_blocks): New.
+ (x_basic_block_head, x_basic_block_end): Kill.
+ (basic_block_computed_jump_target, basic_block_live_at_start): Kill.
+ (flow_int_list_blocks, basic_block_succ, basic_block_pred): Kill.
+ (basic_block_loop_depth): Kill.
+ (basic_block_for_insn): New.
+ (find_basic_blocks): Split out initial block counting into
+ count_basic_blocks. Call functions split out of find_basic_blocks_1.
+ (count_basic_blocks): New.
+ (find_basic_blocks_1): Split out edge recognition, unreachable
+ block deletion.
+ (create_basic_block): New.
+ (compute_bb_for_insn): New.
+ (clear_edges): New.
+ (free_bb_memory): Kill.
+ (add_edge, add_edge_to_label): Kill.
+ (mark_label_ref): Kill.
+ (make_edges): Rewrite to use edge lists.
+ (make_edge, make_label_edge): New.
+ (mark_critical_edges): New.
+ (split_edge, insert_insn_on_edge): New.
+ (commit_one_edge_insertion, commit_edge_insertions): New.
+ (delete_unreachable_blocks): Rewrite to use edge lists.
+ Split out EH region manipulation into delete_eh_regions.
+ Call tidy_fallthru_edge and merge_blocks.
+ (delete_eh_regions): New.
+ (delete_note_p): New.
+ (delete_insn_chain): New.
+ (delete_block): Split out code into delete_insn_chain and
+ tidy_fallthru_edge. Update edge lists.
+ (expunge_block): New.
+ (flow_delete_insn): New?
+ (can_delete_label_p): New?
+ (merge_blocks_nomove, merge_blocks): New.
+ (tidy_fallthru_edge): New.
+ (calculate_loop_depth): New.
+ (life_analysis): Allocate and free uid_volatile.
+ (free_basic_block_vars): Update for new structures.
+ (record_volatile_insns): Use SET_INSN_VOLATILE.
+ (mark_regs_live_at_end): Tidy EXIT_IGNORE_STACK usage.
+ (mark_used_regs): Likewise.
+ (life_analysis_1): Use bb global_live_at_start, global_live_at_end,
+ local_set regsets. Use bb->aux to store new_live_at_end. Begin
+ life propagation from EXIT_BLOCK rather than last block. Clear
+ regs_ever_live after mark_regs_live_at_end.
+ (allocate_for_life_analysis): Update for new structures.
+ (propagate_block): Split out loop depth calculation to
+ calculate_loop_depth.
+ (regno_uninitialized): Use bb->global_live_at_start.
+ (regno_clobbered_at_setjmp): Likewise.
+ (dump_bb_data): Likewise.
+ (find_auto_inc): Use BLOCK_FOR_INSN instead of BLOCK_NUM.
+ (dump_flow_info): Update for new structures.
+ (dump_edge_info): New.
+ (print_rtl_with_bb): Update for new structures.
+ (compute_preds_succs): Do no work -- convert edge lists.
+ (set_block_for_insn): From corpse of old set_block_num.
+ (set_block_num): Call it.
+
+ * rtl.c (note_insn_name): Add NOTE_INSN_BASIC_BLOCK.
+ * rtl.h (rtunion_def): Add bb entry.
+ (NOTE_BASIC_BLOCK): New.
+ (NOTE_INSN_BASIC_BLOCK): New.
+
+ * varray.h (varray_data_tag): Add bb entry.
+ (VARRAY_BB_INIT, VARRAY_BB): New.
+
+ * emit-rtl.c (emit_label_before): New.
+
+ * except.c (expand_rethrow): Delete insns following the call to
+ rethrow. Put the REG_EH_RETHROW on the call.
+
+ * jump.c (returnjump_p, returnjump_p_1): New.
+
+ * expr.h (nonlocal_goto_handler_labels): New declaration.
+ * function.c (nonlocal_goto_handler_labels): Define it.
+ (push_function_context_to): Save it.
+ (pop_function_context_from): Restore it.
+ (init_function_start): Clear it.
+ (nonlocal_label_rtx_list): Kill.
+ * function.h (struct function): Add storage space for it.
+ * stmt.c (expand_nl_handler_label): Return the new label.
+ (expand_nl_goto_receivers): Collect a list of them in
+ nonlocal_goto_handler_labels.
+
+ * Makefile.in (print-rtl.o): Depend on basic-block.h.
+ (flow.o): Depend on insn-flags.h.
+
+ * function.c (thread_prologue_and_epilogue_insns): Do not
+ half-heartedly update bb structures.
+
+ * toplev.c: Add flow2 dump as -dw.
+ (rest_of_compilation): Finish .greg before flow2.
+
+ * graph.c (draw_edge): Handle class 3.
+ (print_rtl_graph_with_bb): Make abnormal edges red class 2,
+ change non-fall-thru but adjacent to green class 3. Update
+ to use new structures.
+
+ * print-rtl.c (print_rtx): Handle NOTE_INSN_BASIC_BLOCK.
+
+ * reg-stack.c (BLOCK_NUM): Convert to function. Abort if
+ block_number is -1.
+ (reg_to_stack): Initialize block_num to -1.
+
+ * combine.c (set_nonzero_bits_and_sign_copies): Update reference
+ to basic_block_live_at_start to bb->global_live_at_start.
+ (try_combine): Likewise.
+ (reg_dead_at_p): Likewise.
+ * global.c (global_conflicts): Likewise.
+ Handle stack regs on all abnormal edges, not just computed jumps.
+ (mark_elimination): Update reference to basic_block_live_at_start.
+ (build_insn_chain): Likewise.
+ * haifa-sched.c (haifa_edge): Rename from edge for conflict.
+ (is_cfg_nonregular): Look at nonlocal_goto_handler_labels instead
+ of nonlocal_label_rtx_list.
+ (check_live_1): Update reference to basic_block_live_at_start.
+ (update_live_1): Likewise.
+ (find_pre_sched_live): Likewise.
+ (find_post_sched_live): Likewise.
+ * local-alloc.c (update_equiv_regs): Likewise.
+ (block_alloc): Likewise.
+ * reload1.c (reload, reload_combine): Likewise.
+ * regmove.c (mark_flags_life_zones): Likewise.
+ * resource.c (mark_target_live_regs): Likewise.
+ * sched.c (schedule_block): Likewise.
+
+ * regclass.c (regset_release_memory): Don't free
+ basic_block_live_at_start.
+
+ * unroll.c (copy_loop_body): Don't duplicate NOTE_INSN_BASIC_BLOCK.
+
+Thu Feb 25 21:32:34 1999 Jason Merrill <jason@yorick.cygnus.com>
+
+ * fixinc.wrap: Also handle struct queue in sys/stream.h.
+ * fixinc.svr4: Likewise.
+
+ * dwarf2out.c (scope_die_for): Set scope_die to comp_unit_die
+ rather than asserting it.
+
+Thu Feb 25 23:33:06 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cppexp.c (left_shift, right_shift, parse_charconst, COMPARE,
+ cpp_parse_expr): Replace uses of long/HOST_BITS_PER_LONG with
+ HOST_WIDEST_INT/HOST_BITS_PER_WIDEST_INT.
+
+ * Makefile.in (cppmain.o, cpplib.o, cpphash.o, cppalloc.o,
+ cpperror.o, cppexp.o, cppfiles.o, cppinit.o, fix-header.o,
+ scan-decls.o): Don't depend on machmode.h.
+
+ * cppexp.c: Don't define CHAR_BIT or HOST_BITS_PER_WIDE_INT anymore.
+ Replace all instances of HOST_WIDE_INT with HOST_WIDEST_INT.
+
+ * cppfiles.c: Likewise.
- * c-common.c: Convert to using ctype macros defined in system.h.
- * c-lex.c: Likewise.
- * cccp.c: Likewise.
- * collect2.c: Likewise.
- * rs6000.c: Likewise.
* cpplib.c: Likewise.
- * fix-header.c: Likewise.
- * gcc.c: Likewise.
- * gen-protos.c: Likewise.
- * pexecute.c: Likewise.
- * protoize.c: Likewise.
- * rtl.c: Likewise.
- * scan.c: Likewise.
- * stmt.c: Likewise.
- * tlink.c: Likewise.
- * toplev.c: Likewise.
-Wed May 6 14:44:14 1998 Gavin Koch <gavin@cygnus.com>
+ * cpplib.h: Likewise. Also don't include machmode.h anymore.
- * config/mips/r3900.h (SUBTARGET_ASM_DEBUGGING_SPEC) :
- Replace -gdwarf-2 with -g0.
+Thu Feb 25 18:46:26 1999 Richard Henderson <rth@cygnus.com>
-Wed May 6 11:43:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * gcc.c (default_compilers): Define __FAST_MATH__ when appropriate.
+ * objc/lang-specs.h: Likewise.
- * Makefile.in (mips-tfile.o, mips-tdump.o): Depend on system.h.
- * mips-tdump.c: Include system.h, remove redundant headers.
- * mips-tfile.c: Likewise. Also, convert all ctype function calls
- to calls of the macro versions defined in system.h.
+Thu Feb 25 16:19:43 1999 Jeffrey A Law (law@cygnus.com)
- * objc/Make-lang.in (objc-act.o): Depend on system.h.
- * objc/objc-act.c: Include system.h, remove redundant headers.
+ * pa.md (call patterns): Lose unused argument to output_call.
-Wed May 6 11:21:06 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * print-rtl.c (print_rtl): Print /j and /c for the jump/call flags.
- * configure.in (AC_CHECK_FUNCS): Add isascii.
- (GCC_NEED_DECLARATIONS): Add atof.
+1999-02-25 Zack Weinberg <zack@rabi.columbia.edu>
- * system.h: Provide prototypes for abort, atof, atol and sbrk here.
- * rtl.c, rtl.h, toplev.c, tree.h: Not here.
+ * cpphash.c (install): Rename to cpp_install, add cpp_reader*
+ first argument. All callers changed.
+ (hashtab): Removed.
+ (cpp_lookup, cpp_install): Change all refs to hashtab to
+ pfile->hashtab.
+ (cpp_hash_cleanup): Removed.
+ * cpphash.h: Adjust prototypes.
+ * cpplib.h (struct cpp_reader): Add hashtab pointer.
+ * cppinit.c (cpp_reader_init): Also allocate space for the
+ hashtab.
+ (cpp_cleanup): Delete all macros and free the hashtab.
-Wed May 6 10:52:49 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Thu Feb 25 21:52:54 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * system.h: Wrap time.h and sys/file.h in autoconf checks.
- Provide default definitions for O_RDONLY and O_WRONLY here.
+ * sh.h (PASS_IN_REG_P): For TARGET_HITACHI, don't pass structures
+ in registers.
- * cccp.c, cpplib.c, fix-header.c, gcc.c, protoize.c: Not here.
+ * expr.h (PRETEND_OUTGOING_VARARGS_NAMED): Provide default definition.
+ * function.c (assign_parms): Honour PRETEND_OUTGOING_VARARGS_NAMED.
+ * calls.c (expand_call): Likewise.
-1998-05-06 Mark Mitchell <mmitchell@usa.net>
+ * sh.c (sh_expand_prologue): For TARGET_HITACHI, don't push varargs /
+ stdarg arguments.
+ * sh.h (CPP_SPEC): Add -D__HITACHI__ for -mhitachi.
+ (FUNCTION_ARG): For TARGET_HITACHI, don't pass unnamed
+ arguments in registers.
+ (PRETEND_OUTGOING_VARARGS_NAMED): Define.
+ * va-sh.h (entire file): If __HITACHI__ is defined, use sh[123]
+ flavor varargs.
- * tree.h (IS_EXPR_CODE_CLASS): Remove bogus '3'.
+Thu Feb 25 14:32:40 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Wed May 6 06:35:38 1998 Robert Lipe <robertl@dgii.com>
+ * cse.c (dump_class): Revert last change and make the prototype
+ extern.
- * toplev.h: New file. Protypes for functions in toplev.c.
- * tree.h, rtl.h: Deleted protos for functions in toplev.c.
- * c-common.c, c-convert.c, c-decl.c, c-iterate.c, c-lex.c,
- c-parse.in, c-parse.y, c-pragma.c, c-typeck.c, calls.c,
- convert.c, dwarf2out.c, except.c, expr.c, final.c, fold-const.c,
- function.c, hash.c, profile.c, real.c, reg-stack.c, regclass.c,
- reload.c, reload1.c, stmt.c, stor-layout.c, tlink.c, tree.c,
- varasm.c: include it.
+Thu Feb 25 19:13:42 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Wed May 6 01:09:01 1998 Jeffrey A Law (law@cygnus.com)
- Jim Wilson (wilson@cygnus.com)
+ * rtl.h (insn_first_p): Don't declare.
+ * rtlanal.c (insn_first_p): Delete.
+ * loop.c (loop_insn_first_p): Faster implementation.
- * haifa-sched.c (find_rgns): In no_loops case, fix test for leaf
- blocks. Check for 1 successor which is the EXIT_BLOCK.
+Thu Feb 25 10:44:35 1999 Richard Earnshaw (rearnsha@arm.com)
- * haifa-sched.c (find_rgns): Detect unreachable blocks, including
- unreachable loops with more than one block.
+ * arm.h (TARGET_SWITCHES): Delete deprecated switches -m[236].
+ (TARGET_3, TARGET_6): Delete.
+ (ARM_FLAG_ARM[36]): Delete.
+ (CPP_CPU_ARCH_SPEC): No need to handle -m[236] any more.
+ (CC1_SPEC): Don't expand -m[236] into new equivalents.
+ (CPP_APCS_PC_SPEC): No need to handle -m[236] any more.
+ * arm.c (arm_override_options): Delete warnings about deprecated
+ options -m[236].
-Wed May 6 08:22:24 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * arm.c (arm_finalize_pic): Build the label into the special pic
+ adjustment insn instead of issuing it separately.
+ * arm.md (pic_add_dot_plus_eight): Rework to contain the label
+ that is needed.
- * fix-header.c (write_rbrac): Add "abort" to functions which need to
- be protected.
+ * arm.md (*zeroextractqi_compare0_scratch): Delete.
+ (*ne_zeroextractsi): New pattern.
-Wed May 6 00:09:36 1998 Jeffrey A Law (law@cygnus.com)
+Thu Feb 25 18:40:06 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * Check in merge from gcc2. See ChangeLog.12 for details.
+ * stmt.c (expand_end_loop): Grok code emitted by
+ expand_exit_loop_if_false.
-Tue May 5 14:33:49 1998 Jim Wilson <wilson@cygnus.com>
+Thu Feb 25 10:17:32 1999 Nick Clifton <nickc@cygnus.com>
- * c-common.c (scan_char_table): Separate 's' and 'c'. 'c' does not
- accept 'a' flag. 'S' does accept 'a' flag.
- (check_format_info): When pedantic, warn for m/C/S/a/A formats,
- and `a' flag.
+ * config/arm/arm.c (return_in_memory): Float fields in unions
+ force a return in memory.
+ (load_multiple_sequence): Add comment explaining why two LDR
+ instructions can be better than an LDMIA instruction.
- * elf64.h (MULTILIB_DEFAULTS): Move definition after mips.h include.
+ * config/arm/arm.h (TARGET_SHORT_BY_BYTES): Add comment
+ describing the real meaning of this option.
+ (FIXED_REGISTERS): Default r10 to not-fixed.
+ (CALL_USED_REGISTERS): Default r10 to not-call-used.
+ (SUBTARGET_CONDITIONAL_REGISTER_USAGE): If not defined, define
+ as empty.
+ (CONDITIONAL_REGISTER_USAGE): Fix r10 if TARGET_APCS_STACK is
+ true. Invoke SUBTARGET_CONDITIONAL_REGISTER_USAGE after
+ performing other checks.
-Tue May 5 10:50:39 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * config/arm/arm.md (zero_extendhisi2): Undo previous change.
+ (extendhisi2): Undo previous change.
+ Also add comments describing why TARGET_SHORT_BY_BYTES can be
+ ignored for armv4(t) architectures.
- * config/m68k/m68k.h: Declare functions from m68k.c used in
- macros and machine description.
- (ASM_OUTPUT_LONG_DOUBLE): Always use `l' flag in print format for
- long values.
- (ASM_OUTPUT_FLOAT): Likewise.
- (ASM_OUTPUT_FLOAT_OPERAND): Likewise.
+ * config/arm/riscix.h (SUBTARGET_CONDITIONAL_REGISTER_USAGE):
+ Define to fix r10.
-Tue May 5 01:28:12 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * config/arm/riscix1-1.h
+ (SUBTARGET_CONDITIONAL_REGISTER_USAGE): Define to fix r10.
+
+Thu Feb 25 12:09:04 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cse.c (dump_class): Make the function definition static to match
+ the prototype.
+
+Wed Feb 24 17:47:28 1999 Jim Wilson <wilson@cygnus.com>
+
+ * dbxout.c (gstab.h): Use if CROSS_COMPILE.
+
+ * dwarf2out.c (add_location_or_const_value_attribute): Add big
+ endian correction for parms passed in regs but living on the stack.
+
+Wed Feb 24 14:03:54 1999 Jeffrey A Law (law@cygnus.com)
+
+ * calls.c (initialize_argument_information): New function extracted
+ from expand_call.
+ (expand_call): Use initialize_argument_information. Remove variables
+ which are no longer used due to cleanups.
- * tree.def: Add NAMESPACE_DECL.
- * dwarfout.c (type_ok_for_scope): Ignore NAMESPACE_DECLs for now.
- * dwarf2out.c (push_decl_scope): Likewise.
- (scope_die_for): Likewise.
- * tree.c (decl_function_context): Use TREE_CODE_CLASS to determine
- how to get next context level.
+ * calls.c (compute_argument_block_size): New function, extracted from
+ expand_calls.
+ (expand_calls): Use compute_argument_block_size. Delete
+ original_args_size, use unadjusted_args_size instead.
+
+ * calls.c (precompute_arguments): New function, extracted from
+ expand_call.
+ (expand_call): Use precompute_arguments.
+
+ * calls.c (finalize_must_preallocate): New function, extracted from
+ expand_call.
+ (expand_call): Use finalize_must_preallocate.
+
+ * calls.c (store_one_arg): Mark "variable_size" as possibly unused.
-Tue May 5 01:43:16 1998 Jim Wilson <wilson@cygnus.com>
+ * regclass.c (record_reg_classes, case 'p'): Set classes appropriately.
+ An alternative always fails if it needs a pseudo and no suitable
+ register class can be found.
- * i386.c (output_fix_trunc): Add code to emulate non-popping DImode
- case.
+Wed Feb 24 19:47:56 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * loop.h (loop_insn_first_p): Declare.
+ * loop.c (loop_insn_first_p): No longer static.
+ * unroll.c (iteration_info): Fix comparison to
+ reg_iv_type->num_elements.
+ Before accessing reg_biv_class, check index against
+ max_reg_before_loop.
+ Fix and enable code for giv iterators.
+ (loop_iterations): Compare with reg_iv_type->num_elements instead
+ of with max_reg_before_loop.
+
+Wed Feb 24 19:17:11 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * unroll.c (unroll_loop): Avoid out-of-bounds index for local_regno.
+
+Wed Feb 24 11:26:41 1999 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * config/sparc/sparc.h (CONDITIONAL_REGISTER_USAGE): Don't use
+ PIC_OFFSET_TABLE_REGNUM for register allocation when -fPIC.
-Tue May 5 01:15:06 1998 Jeffrey A Law (law@cygnus.com)
+Tue Feb 23 16:24:19 1999 Marc Lehmann <pcg@goof.com>
+
+ * config/i386/i386.md: Fix typo.
- * h8300.h (ADDITIONAL_REGISTER_NAMES): Add "er" registers.
+Mon Feb 22 19:36:33 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * config/mips/mips.c (mips_debugger_offset): When TARGET_MIPS16 &&
+ frame_pointer_needed adjust frame size.
+ (function_prologue): Don't MIPS16 .mask GPOFFSET. Already adjusted
+ in .frame pseudo-op.
+ Frm Jim Wilson <wilson@cygnus.com>:
+ * mips.c (function_prologue): Adjust frame size in .frame pseudo-op
+ when TARGET_MIPS16 && frame_pointer_needed.
+
+1999-02-22 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/arm.h: Add TARGET_CPU_strongarm1100.
+ Add -mno-sched command line switch to disable scheduling of
+ instructions into the function's prologue.
+ (enum processor_type): Remove.
+ (TARGET_OPTIONS): Add "fpe=" option to match documentation.
+ (struct arm_cpu_select): Replace 'set_tune_p' and 'set_arch_p'
+ fields with 'processors' field.
+ (CONDITIONAL_REGISTER_USAGE): Allow r10 to be used if stack
+ checking is not enabled.
+ (RETURN_IN_MEMORY): Always call arm_return_in_memory.
- * reorg.c (fill_slots_from_thread): Update REG_DEAD/REG_UNUSED notes
- for any insns skipped at the start of a block because they were
- redundant.
+ * config/arm/arm.c (arm_cpu): Remove.
+ (tune_flags): Remove.
+ (arm_is_strong): New variable: true iff the target processor is a
+ StrongARM.
+ (arm_is_6_or_7): New variable: true iff the target processor is an
+ ARM6 or and ARM7.
+ (arm_select): Fields reorganised.
+ (struct processors): processor_type field removed.
+ (all_procs): Remove.
+ (all_cores): New array: Definitions of all known ARM cpu cores.
+ (all_architectures): New array: Definitions of all known ARM
+ architectures.
+ (streq): New macro.
+ (FL_SCHED): New processor flag: processor required load
+ scheduling.
+ (FL_STRONG): New processor flag: processor is a StrongARM.
+ (arm_override_options): Reorganized to make code clearer.
+ (use_return_insn): Test for "not (TARGET_APCS and
+ frame_pointer_needed)".
+ (arm_return_in_memory): Improve handling of structures.
+
+ * config/arm/arm.md: Remove "cpu" attribute. Replace with
+ "is_strongarm" and "is_arm_6_or_7" attributes.
+ (zero_extendhisi2): Check for TARGET_SHORT_BY_BYTES before
+ arm_arch4.
+ (extendhisi2): Check for TARGET_SHORT_BY_BYTES before arm_arch4.
+
+ * invoke.texi (ARM Options): Document -mtune= and -mfp= options.
+
+1999-02-22 Philip Blundell <philb@gnu.org>
+
+ * config/arm/linux-gas.h (INITIALIZE_TRAMPOLINE): Replace default
+ definition with one including cache synchronization.
+ (CLEAR_INSN_CACHE): Correct syscall number and enable definition.
+ Move definition of inhibit_libc to...
+ * config/arm/xm-linux.h: ... here.
+
+ * config/arm/t-linux: Disable multilib configurations since the
+ only effect for most people is to cause builds to fail.
+
+ * config/arm/elf.h (ASM_FILE_START): Add .file directive.
+ (ASM_SPEC): Translate -mapcs-float to -mfloat for the assembler.
+
+ * config/arm/linux-elf.h (DEFAULT_VTABLE_THUNKS): Define.
+ (HANDLE_SYSV_PRAGMA): Likewise.
+ (LIB_SPEC): Copy definition from generic Linux files.
+ (LIBGCC_SPEC): Include -lfloat if -msoft-float was given.
+ (FP_DEFAULT): Set to SOFT3 on 32-bit targets.
+ (DWARF2_DEBUGGING_INFO): Define.
+ (PREFERRED_DEBUGGING_TYPE): Define as DBX_DEBUG.
-Mon May 4 20:23:51 1998 Jim Wilson <wilson@cygnus.com>
+Mon Feb 22 16:54:18 1999 Andrew MacLeod <amacleod@cygnus.com>
- * alpha.h (DBX_CONTIN_LENGTH): Decrease to 3000.
+ * loop.c (libcall_other_regs): Make extern.
+ * rtl.h (find_last_value): Add parameter to prototype.
+ (libcall_other_reg): Add extern declaration.
+ * rtlanal.c (find_last_value): Add another parameter to allow
+ a definition using a hardware register to be found as well.
-1998-05-04 Ulrich Drepper <drepper@cygnus.com>
+Mon Feb 22 13:33:47 1999 Mark Mitchell <mark@markmitchell.com>
- * c-common.c (format_char_info): Add new field hhlen.
- (print_char_table, scan_char_table, time_char_table): Initialize
- hhlen field appropriately.
- (char_format_info): Recognize hh modifier and lookup correct char
- table entry.
+ * cse.c (dump_class): New function.
+ (invalidate_memory): Fix typo in comment.
+ * function.c (temp_slot): Add an alias set field.
+ (assign_stack_temp): Only reuse slots if they will have the
+ same alias set as before.
+ (combine_temp_slots): Don't combine if -fstrict-aliasing;
+ that's unsafe.
+ * rtl.c (copy_rtx): Copy all the flags (in particular,
+ MEM_SCALAR_P).
-Mon May 4 19:15:29 1998 Jim Wilson <wilson@cygnus.com>
+Mon Feb 22 14:13:23 1999 Vladimir N. Makarov <vmakarov@cygnus.com>
- * expr.c (expand_expr, case INDIRECT_REF): Don't optimize string
- reference if this is a store.
+ * configure.in (i[34567]86-*-linux-gnu*,
+ i[34567]86-*-linux-gnulibc1, i[34567]86-*-linux-gnuaout*,
+ i[34567]86-*-linux-gnuoldld*): Use fixinc.x86-linux-gnu as
+ fixincludes.
-Mon May 4 17:25:17 1998 Richard Henderson <rth@cygnus.com>
+ * configure: Rebuilt.
- * sparc.c (output_move_quad): Fix typo in mov_by_64 argument.
+ * fixinc.x86-linux-gnu: New script for fixing asm-statements bug
+ on x86 linux.
-Sun May 3 23:57:25 1998 Robert Lipe <robertl@dgii.com>
+ * fixinc/fixinc.x86-linux-gnu: Copy of the previous one.
- Make UnixWare 7 bootstrap support work with final shipping product.
- * configure.in: (i[34567]86-*-sysv5): append, not overwrite, xm_file.
- Pick up xm-siglist and xm-alloca.
- (xm_defines): Add USG so dbxout will build.
- * configure: Regenerate.
+ * fixinc/mkfixinc.sh (i[34567]86-*-linux-gnu*,
+ i[34567]86-*-linux-gnulibc1, i[34567]86-*-linux-gnuaout*,
+ i[34567]86-*-linux-gnuoldld*): Use fixinc.x86-linux-gnu as
+ fixincludes.
-Sun May 3 13:51:34 PDT 1998 Richard Henderson <rth@cygnus.com>
-
- Support for official Sparc V9 ABI:
- * sparc.c (sparc_override_options): Force stack bias off for !arch64.
- Care for flag_pcc_struct_return default.
- (output_move_quad): Rewrite to move by halves on v9 and in the
- proper direction.
- (move_quad_direction): New function.
- (output_fp_move_quad): Use it to determine the direction of copy.
- (function_arg_slotno): Return -1 for FP reg overflow as well.
- (function_arg_record_value*): New functions.
- (function_arg): Use them. Streamline unprototyped parameter passing.
- (function_arg_pass_by_reference): Pass TCmode by reference.
- (function_value): New function.
- * sparc.h (PTRDIFF_TYPE, SIZE_TYPE): For -pedantic's sake, don't use
- long long in 64-bit mode.
- (RETURN_IN_MEMORY): v9 returns structs < 32-bytes in regs.
- (DEFAULT_PCC_STRUCT_RETURN): Make the default detectable.
- (BASE_RETURN_VALUE_REG): Consider complex float types for arch64.
- (BASE_OUTGOING_VALUE_REG, BASE_PASSING_ARG_REG): Likewise.
- (BASE_INCOMING_ARG_REG): Likewise.
- (FUNCTION_VALUE): Call function_value.
- (FUNCTION_OUTGOING_VALUE, LIBCALL_VALUE): Likewise.
- * sparc.md (movdi_sp32_v9): Disable for arch64.
- (movsf, movdf, movtf): Sort all ulternatives using fp regs first.
- (call_value_address_sp64): Remove register class constraints.
- (call_value_symbolic_sp64): Likewise.
- (nonlocal_goto): Pass label reg directly to goto_handlers. Constrain
- v9 case to 32-bit constants.
- (goto_handler_and_restore_v9): Provide a version for arch64.
- * sparc/linux64.h (SIZE_TYPE, PTRDIFF_TYPE): Remove private definition.
- * sparc/sp64-aout.h (TARGET_DEFAULT): Turn on stack bias.
- (CPP_PREDEFINES): New.
- * sparc/sp64-elf.h: Likewise.
- (PREFERRED_DEBUGGING_TYPE): Dwarf2.
- (ASM_OUTPUT_DWARF2_ADDR_CONST): New.
- * sparc/sysv4.h (SIZE_TYPE, PTRDIFF_TYPE): Undo svr4.h's changes.
-
-Sat May 2 17:47:17 PDT 1998 Jeff Law (law@cygnus.com)
+Mon Feb 22 08:55:05 1999 Ovidiu Predescu <ovidiu@cup.hp.com>
- * version.c: Bump for snapshot.
+ * objc/objc-act.c (encode_type): Temporary revert to the old
+ behavior of encoding types as the new one seems to break the
+ encoding of bitfields.
-Sat May 2 01:37:29 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Feb 22 11:40:44 1999 Craig Burley <craig@jcb-sc.com>
+Sat Feb 20 09:59:36 1999 Craig Burley <craig@jcb-sc.com>
- * reload.c (find_reloads): Emit USEs to mark where a pseudo
- is reloaded with the MEM of its stack slot.
- * reload1.c (cannot_omit_stores): Delete.
- (reload): Don't initialize it.
- Don't apply avoid_return_reg logic to USEs.
- When done, remove USEs that have a REG_EQUAL note on them.
- (emit_reload_insns): Handle case where we have inherited a MEM.
- (choose_reload_regs): Likewise.
- (delete_output_reload): Don't use cannot_omit_stores.
+ * Makefile.in (all.internal, all.cross): Depend on `doc'
+ target, to ensure docs get made before installation.
-Thu Apr 30 18:59:03 1998 Jim Wilson <wilson@cygnus.com>
+ Decrease spurious warnings from -fsyntax-only:
+ * stmt.c (expand_expr_stmt): Expand expr even when -fsyntax-only.
- * Makefile.in (cpp.info, gcc.info): Put -o option before input file.
+Mon Feb 22 10:55:00 1999 Gavin Romig-Koch <gavin@cygnus.com>
-Thu Apr 30 16:57:34 1998 Michael Meissner <meissner@cygnus.com>
+ * c-lex.c (yylex): Replace warning about integer constants being
+ larger than long-longs, with a warning about integer constants
+ being larger than the largest target integer.
- * haifa-sched.c (print_{exp,value}): Various changes to make the
- debug output easier to read. Also, use only one buffer, and make
- sure the buffer we are passed in doesn't overflow.
- (safe_concat): Concatenate to a buffer without overflow.
+Mon Feb 22 08:35:38 1999 Craig Burley <craig@jcb-sc.com>
-Thu Apr 30 16:57:34 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ Fix -fsyntax-only ICEs:
+ * varasm.c (assemble_zeros, assemble_variable,
+ output_constant_def): Do nothing when -fsyntax-only.
- * haifa-sched.c (alloc_{INSN,EXPR}_LIST): Make static to agree
- with the prototype.
+Fri Feb 19 18:18:56 1999 Don Bowman <don@pixstream.com>
-Wed Apr 29 21:45:16 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * configure.in (mips*-*-vxworks*): Enable gthreads vxworks support.
+ * configure: Rebuilt.
- * sched.c (new_insn_dead_notes): Check if the register was
- used in the original instruction.
- * haifa-sched.c (new_insn_dead_notes): Likewise.
+Sun Feb 21 20:34:44 1999 Jeff Law (law@cygnus.com)
-Wed Apr 29 13:46:03 1998 Jim Wilson <wilson@cygnus.com>
+ * version.c: Bump for snapshot.
- * dwarf2out.c (scope_die_for): If could not find proper scope,
- check for and handle tagged type with incorrect TYPE_CONTEXT.
+Sun Feb 21 20:35:10 1999 Jeffrey A Law (law@cygnus.com)
-Wed Apr 29 15:34:40 1998 John Carr <jfc@mit.edu>
+ * config/aoutos.h (ASM_OUTPUT_CONSTRUCTOR): Delete.
+ (ASM_OUTPUT_DESTRUCTOR, ASM_OUTPUT_GC_ENTRY): Likewise.
+ * tm.texi: Update docs for constructors and destructors.
- * calls.c (expand_call): Fix recognition of C++ operator new.
+Sun Feb 21 17:11:18 1999 Richard Henderson <rth@cygnus.com>
- * alias.c (mode_alias_check): Disable type based alias detection.
+ * genattrtab.c (check_attr_value): Allow negative const_int if
+ negative_ok. Accept integral arithmetic operators. Accept
+ direct references to other attributes. Accept symbol_ref in
+ non-constant attributes.
+ (max_attr_value): Add new argument `unknownp'. Update all callers.
+ (or_attr_value): Likewise.
+ (simplify_knowing): Don't optimize if max_attr_value unknown.
+ (write_length_unit_log): Likewise with or_attr_value.
+ (find_and_mark_used_attributes): Don't fallthru case.
+ (write_attr_set): Pass thru all non-cond expressions.
+ (write_attr_value): Handle symbol_ref, attr, and arithmetic.
-Wed Apr 29 15:06:42 1998 Gavin Koch <gavin@cygnus.com>
+Sun Feb 21 13:16:44 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * config/mips/elf.h (ASM_OUTPUT_DEF,ASM_WEAKEN_LABEL,
- ASM_OUTPUT_WEAK_ALIAS): Define.
- * config/mips/elf64.h: Same.
- * config/mips/r3900.h (ASM_OUTPUT_DEF,SUPPORTS_WEAK,
- ASM_WEAKEN_LABEL): Removed.
+ * regmove.c (discover_flags_reg): Use word_mode instead of SImode.
-Wed Apr 29 10:53:29 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Sun Feb 21 13:15:40 1999 Richard Henderson <rth@cygnus.com>
- * calls.c (expand_call): Bump the length limit on the specially
- recognized function names to 17.
+ * regmove.c (discover_flags_reg): Remove cc0 code.
+ (mark_flags_life_zones) [HAVE_cc0]: Force use of cc0; bail if
+ a potential flags register was identified.
-Tue Apr 28 17:53:33 1998 Jim Wilson <wilson@cygnus.com>
+Sat Feb 20 16:16:07 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * ginclude/stddef.h: Add check for _MACHINE_ANSI_H_ for BSD/OS
- when undefining macros at the end.
+ * rs6000.md (scc plus ltu): Fix typo in last change.
- * expr.c (expand_builtin, case BUILT_IN_MEMSET): Break if either
- val or len has TREE_SIDE_EFFECTS set.
+Sat Feb 20 09:08:44 1999 Richard Earnshaw (rearnsha@arm.com)
- * sparc.md (mulsidi3): Call const v8plus and v8plus routines.
- (mulsidi3_v8plus, const_mulsidi3_v8plus): Delete asterisk from name.
- (smuldi3_highpart): Call const v8plus routine.
- (smulsi3_highpart_v8plus): Renamed from smulsidi3_highpart_v8plus.
- (const_smulsi3_highpart_v8plus): New pattern.
- (smulsi3_highpart_sp32): Renamed from smulsidi3_highpart_sp32.
- (umulsidi3): Call const v8plus routine.
- (umulsi3_highpart): Handle const before v8plus. Call const v8plus
- routine.
- (umulsi3_highpart_v8plus): Renamed from umulsidi3_highpart_v8plus.
- (umulsi3_highpart_sp32): Renamed from umulsidi3_highpart_sp32.
+ * xm-arm.h (HOST_BITS_PER_LONGLONG): Define.
-Tue Apr 28 08:55:26 1998 Michael Meissner <meissner@cygnus.com>
+Fri Feb 19 23:02:02 1999 Richard Henderson <rth@cygnus.com>
- * m32r.c (*_oper{and|ator}): Change enum arguments and return
- values to int, so they can be prototyped even in files that don't
- include rtl.h.
- ({small,large}_insn_p): Ditto.
- (m32r_select_cc_mode): Ditto.
- (gen_compare): Ditto.
- (function_arg_partial_nregs): Ditto.
- (m32r_setup_incoming_varargs): Ditto.
- (init_reg_tables): Add prototype.
- (m32r_frame_info): Add prolog_size field.
- (m32r_compute_frame_size): Calculate the size of the prologue.
- (m32r_first_insn_address): Return prologue size.
- (m32r_output_function_prologue): Calculate frame size before
- printing out information. Print out the prologue size.
+ * regmove.c (discover_flags_reg): New function.
+ (flags_set_1, mark_flags_life_zones): New functions.
+ (regmove_optimize): Call them.
+ (fixup_match_1): Use insn modes rather than sets_cc0_p.
- * m32r.h: Prototype all functions in m32r.c.
- (FIRST_INSN_ADDRESS): Declare, returning prologue size.
+Fri Feb 19 22:47:01 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * m32r.md (bcc functions): Cast enum's to int.
+ * rtlanal.c (insn_first_p): Fix return value for insn == reference.
- * m32r.c (conditional_move_operand): Silence a debug message.
- ({small,long}_insn): New predicates.
+ * loop.c (strength_reduce, check_final_value, check_dbra_loop):
+ Use loop_insn_first_p.
- * m32r.h (TARGET_M32R): New macro.
- (PREDICATE_CODES): Rearrange somewhat, add small_insn/long_insn.
- (HAIFA_P): Define as 1/0 depending on whether the Haifa scheduler
- was selected.
- (ISSUE_RATE): Define as 2.
+Fri Feb 19 15:49:26 1999 Michael Meissner <meissner@cygnus.com>
+ David Edelsohn <edelsohn@gnu.org>
- * m32r.md (insn_size): New attribute.
- ({,rev_}branch_insn): Add .s qualifier to branches believed to be
- short.
- (m32r): New attribute.
+ * rs6000.md (scc plus eq): Fix output template.
+ (scc plus ltu): Fix output template and collapse variants
+ correcting early clobbers.
+ (scc plus geu): Fix output template.
+ (scc plus gt): Fix output template.
+ (scc plus gtu): Fix output template and collapse variants.
- * configure.in (enable_haifa): Switch m32r to Haifa by default.
- * configure: Regenerate.
+Fri Feb 19 15:43:59 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- (Changes from Nick Clifton <nickc@cygnus.com>)
- * m32r.h (EXTRA_CONSTRAINT): Implement 'S' constraint to perfoirm
- the equivalent of a negated 'I' constraint.
- (PRESERVE_DEATH_INFO_REGNO_P): Define in order to allow peephole
- optimisation to work.
+ * cppinit.c (print_help): Remove unescaped newline in string.
- * m32r.md (cmp_ne_small_const_insn): Use 'S' constriant rather
- than 'I' since the value is negated.
- (peephole): Add peephole optimisation to cope with optimization of
- divide and subtracts of the same operands.
+Fri Feb 19 19:55:06 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * m32r.c zero_and_one, emit_cond_move): Add support for MVFC.
- * m32r.h: Ditto.
- * m32r.md: Ditto.
+ * loop.c (strength_reduce): Check for intervening jumps when
+ converting biv increment to giv.
- * m32r.h (PREDICATE_CODES): Add declaration of machine specific
- predicates.
+Thu Feb 18 16:36:58 1999 Per Bothner <bothner@cygnus.com>
+
+ * tree.def (TRY_FINALLY_EXPR, GOTO_SUBROUTINE_EXPR): New tree nodes,
+ * expr.c (expand_expr): Support new tree nodes.
+
+Fri Feb 19 10:17:56 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Tue Apr 28 07:25:53 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * config/m68k/m68k.c (m68k_align_loops_string,
+ m68k_align_jumps_string, m68k_align_funcs_string): Add const.
+ * config/m68k/m68k.h (m68k_align_loops_string,
+ m68k_align_jumps_string, m68k_align_funcs_string): Likewise.
- * Makefile.in (libgcc2.ready): Revert last patch (Apr 24).
+Thu Feb 18 23:28:35 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon Apr 27 18:39:47 1998 Nick Clifton <nickc@cygnus.com>
+ * bitmap.c (bitmap_print): Qualify a char* with the `const' keyword.
- * config/arm/thumb.h (GO_IF_LEGITIMATE_ADDRESS): Check against
- frame_pointer_rtx not FRAME_POINTER_REGNUM.
+ * bitmap.h (bitmap_print): Likewise.
-Mon Apr 27 18:36:28 1998 Jim Wilson <wilson@cygnus.com>
+ * c-decl.c (builtin_function, grokdeclarator, grokfield): Likewise.
- * reg-stack.c: Revert last patch (Apr 20).
- (convert_regs): Set insn to PREV_INSN (next) after do while loop.
+ * c-lang.c (build_objc_string): Likewise.
- * m68k/lb1sf68.asm (Laddsf$3): Fix typos in mcf5200 exg code.
+ * c-lex.c (yyerror, extend_token_buffer): Likewise. Don't include
+ limits.h or ctype.h. Remove unused variable `p'.
- * loop.c (check_dbra_loop): New locals jump, first_compare, and
- compare_and_branch. Call get_condition to set first_compare.
- Set compare_and_branch to number of compare/branch instructions.
- Replace PREV_INSN (PREV_INSN (loop_end)) with first_compare.
- Replace '2' with compare_and_branch.
+ * c-lex.h (yyerror): Qualify a char* with the `const' keyword.
-Mon Apr 27 15:53:30 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+ * c-pragma.c (handle_pragma_token): Likewise.
- * cplus-dem.c (demangle_qualified): Replace missing else.
+ * c-pragma.h (handle_pragma_token): Likewise.
-Mon Apr 27 20:22:08 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * c-tree.h (build_objc_string, builtin_function, grokfield,
+ build_indirect_ref, lvalue_or_else, readonly_warning, error_init,
+ pedwarn_init): Likewise.
- * sh.c (gen_ashift_hi): Don't make SUBREG of a SUBREG.
+ * c-typeck.c (convert_for_assignment, warn_for_assignment,
+ push_string, warning_init, incomplete_type_error,
+ build_indirect_ref, lvalue_or_else, readonly_warning,
+ build_c_cast, spelling, push_member_name, print_spelling,
+ error_init, pedwarn_init, start_init): Likewise.
-Mon Apr 27 18:23:51 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * objc/objc-act.c (build_objc_string): Likewise.
- * sh.c (sh_expand_prologue, sh_expand_epilogue):
- If TARGET_DOUBLE_ALIGN, preserve 64 bit stack alignment.
- * sh.h (STACK_BOUNDARY): Likewise.
+ * print-tree.c (print_node_brief, print_node): Likewise.
-Mon Apr 27 17:22:48 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * tree.h (lvalue_or_else, print_node, print_node_brief): Likewise.
- * sh.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
+Thu Feb 18 20:44:21 1999 David Edelsohn <edelsohn@gnu.org>
-Mon Apr 27 08:55:23 1998 Michael Meissner <meissner@cygnus.com>
+ * regclass.c (record_reg_classes): Correctly handle 'p' constraint.
- * system.h (abort): If abort is not defined, and neither is
- USE_SYSTEM_ABORT, redefine abort to call fprintf and exit,
- reporting the line and filename of the error.
+Thu Feb 18 19:59:37 1999 Marc Espie <espie@cvs.openbsd.org>
+
+ * configure.in :Handle OpenBSD platforms.
+ * configure: Rebuilt.
+ * config/openbsd.h: New file.
+ * config/xm-openbsd.h: New file.
+ * config/t-openbsd: New file.
+ * config/t-openbsd-thread: New file.
- * .gdbinit: Add breakpoints on exit and fancy_abort.
+Thu Feb 18 18:47:09 1999 Jeffrey A Law (law@cygnus.com)
+
+ * function.c (assign_stack_temp_for_type): Round SIZE before calling
+ assign_stack_local for BLKmode slots.
+
+Fri Feb 19 01:45:06 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * loop.c (strength_reduce): For derived givs, replace the
+ giv this was derived from with its new_reg.
+ (recombine_givs): Don't set new_reg for derived giv.
+ And don't print it, print SUM instead.
+
+Thu Feb 18 15:52:49 1999 Jim Wilson <wilson@cygnus.com>
+
+ * m68kelf.h (ASM_RETURN_CASE_JUMP): Add 5200 support.
+
+1999-02-18 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * cpplib.c: Kill define of STDC_VALUE. Don't include output.h
+ or prefix.h. Change CPP_IS_MACRO_BUFFER to not refer to
+ macro_cleanup.
+ (GET_ENV_PATH_LIST, PATH_SEPARATOR, STANDARD_INCLUDE_DIR,
+ predefs, SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE,
+ CPP_WCHAR_TYPE, USER_LABEL_PREFIX, REGISTER_PREFIX, struct
+ cpp_pending, version_string, struct default_include,
+ include_defaults_array, path_include, cpp_options_init,
+ dump_special_to_buffer, initialize_builtins, cpp_start_read,
+ cpp_reader_init, nreverse_pending, push_pending, print_help,
+ cpp_handle_option, cpp_handle_options, cpp_finish,
+ cpp_cleanup): Move to cppinit.c.
+ (macro_cleanup, struct arglist, collect_expansion,
+ create_definition, compare_defs, comp_def_part, ARG_BASE,
+ struct argdata, macarg, change_newlines, timestamp,
+ monthnames, special_symbol, unsafe_chars, macroexpand,
+ push_macro_expansion): Move to cpphash.c.
+ (quote_string, check_macro_name, cpp_expand_to_buffer,
+ output_line_command, cpp_undef): Export.
+ (null_underflow, null_cleanup, handle_directive): Make static.
+
+ * cpplib.h: Prototype now-exported functions. Adjust decls of
+ syntax tables so we can include cpplib.h in cppinit.c.
+ * cpphash.h: Prototype all functions exported by cpphash.c.
+ * cppinit.c: Make syntax tables initialized data if possible
+ (uses GCC designated-initializer extension).
+ * cppexp.c: Make cpp_lex static.
+ * Makefile.in: Move -D switches for the various include dirs
+ from cpplib.o rule to cppinit.o rule. Adjust dependencies.
+
+Thu Feb 18 13:15:56 1999 Marc Espie <espie@cvs.openbsd.org>
- * final.c (split_double): Avoid a compiler warning if
- BITS_PER_WORD is less than or equal to HOST_BIT_PER_WIDE_INT.
+ * alpha/openbsd.h: New file.
+ * alpha/xm-openbsd.h: New file.
+ * sparc/openbsd.h: New file.
+ * sparc/xm-openbsd.h: New file.
+ * m68k/openbsd.h: New file.
+ * m68k/xm-openbsd.h: New file.
+ * i386/openbsd.h: New file, originally from netbsd.
+ * i386/xm-openbsd.h: New file.
- * rtl.h (JUMP_{CROSS_JUMP,NOOP_MOVES,AFTER_REGSCAN}): New macros
- for calling jump_optimize.
+1999-02-17 Zack Weinberg <zack@rabi.columbia.edu>
- * toplev.c (rest_of_compilation): Call jump_optimize using JUMP_*
- macros, rather than 0/1's.
+ * Makefile.in: Correct dependencies for cpplib object files.
-Sun Apr 26 23:19:10 1998 Richard Henderson <rth@cygnus.com>
+Wed Feb 17 14:04:18 1999 Michael Meissner <meissner@cygnus.com>
- * alpha.h (CONST_COSTS): Zero is always free.
- (RTX_COSTS): Add EV6 costs. Abort if alpha_cpu is unknown.
+ * rs6000.md ({add,sub}si3 `.'): Add alternatives to use CR other
+ than cr0.
-Sun Apr 26 15:38:50 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Wed Feb 17 16:59:28 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * cplus-dem.c (gnu_special): Fix off-by-one bug when checking the
- length in the name of a virtual table.
+ * loop.c (strength_reduce): Don't move giv insn for biv turned giv
+ below scan_start.
-Sun Apr 26 01:21:06 1998 Richard Henderson <rth@cygnus.com>
+Wed Feb 17 10:56:24 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * alpha.c (print_operand): Don't add 'v' suffix for ALPHA_FPTM_N.
+ * tree.c (tree_node_kind_names, print_obstack_name,
+ get_identifier, maybe_get_identifier, build_string,
+ build_expr_wfl, is_attribute_p, lookup_attribute,
+ print_obstack_statistics, get_file_function_name_long, tree_check,
+ tree_class_check, expr_check): Qualify a char* with the `const'
+ keyword.
-Sat Apr 25 22:11:38 PDT 1998 Jeff Law (law@cygnus.com)
+ * tree.h (get_identifier, maybe_get_identifier, build_string,
+ build_expr_wfl, is_attribute_p, lookup_attribute,
+ print_obstack_statistics, print_obstack_name, tree_check,
+ tree_class_check, expr_check): Likewise.
- * version.c: Bump for snapshot.
+Tue Feb 16 21:29:38 1999 Jeffrey A Law (law@cygnus.com)
-Sat Apr 25 17:17:15 1998 Jeffrey A Law (law@cygnus.com)
+ * i386/freebsd-elf.h, i386/gas.h, i386/linux.h: Fix minor spacing
+ errors.
- * fold-const.c (fold_convert): Fix typo.
+ * calls.c (store_one_arg): Mark any slots used for the argument
+ as in-use immediately after we're done saving any slots which
+ will be overwritten by this argument.
-Sat Apr 25 17:55:54 1998 John Carr <jfc@mit.edu>
+Tue Feb 16 21:02:07 1999 Anton Hartl <toni@devsoft.com>
- * alias.c (alias_invariant): New variable.
- (record_base_value): New argument INVARIANT.
- (memrefs_conflict_p): If a register has an entry in the alias_invariant
- array, try substituting that value for the register.
+ * rs6000.md (call_value): Fix typo.
- * rtl.h: Declare record_base_value.
+Wed Feb 17 01:29:07 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * loop.c, unroll.c: Update callers of record_base_value.
+ * loop.c (strength_reduce): Calculate maybe_dead before
+ calling recombine_givs.
- * alias.c (find_base_value, find_base_term): SIGN_EXTEND and
- ZERO_EXTEND do not affect base values.
+Wed Feb 17 00:43:12 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Fri Apr 24 15:57:02 1998 Jeffrey A Law (law@cygnus.com)
+ * loop.c (strength_reduce): Dump biv increment -> giv conversions.
- * dbxout.c (dbxout_type): Fix typo.
- (dbxout_range_type): Another HOST_WIDE_INT_PRINT_DEC fix.
+Tue Feb 16 15:31:39 1999 Ovidiu Predescu <ovidiu@cup.hp.com>
- * configure.in: Use CC_FOR_BUILD, not BUILD_CC.
+ * objc/objc-act.c (encode_type): Encode the type instead of
+ encoding the mode of the type (patch from Richard Frith-Macdonald
+ <richard@brainstorm.co.uk>).
-Fri Apr 24 16:11:47 1998 John Carr <jfc@mit.edu>
+Tue Feb 16 10:53:51 1999 Richard Earnshaw (rearnsha@arm.com)
- * expr.c (expand_builtin, case MEMSET): Set MEM_IN_STRUCT_P
- if the argument is the address of a structure or array.
+ * config/arm/arm.md (*zeroextractqi_compare0_scratch): Re-add load
+ instruction killed in previous change. Simplify mask generation.
+ (*zeroextractsi_compare0_scratch): Simplify mask generation.
- * configure.in: Enable Haifa scheduler by default for SPARC.
+Tue Feb 16 09:52:26 1999 Nick Clifton <nickc@cygnus.com>
-Fri Apr 24 20:55:47 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * config/arm/arm.md (zeroextractqi_compare0_scratch): Ensure that
+ bitfield does not overflow a byte boundary.
- * cse.c (cse_set_around_loop): Don't do optimization when
- new pseudos are created.
+Tue Feb 16 01:37:33 1999 Charles G Waldman <cgw@alum.mit.edu>
-Fri Apr 24 11:00:18 1998 Jeffrey A Law (law@cygnus.com)
+ * c-common.c (shorten_compare): Get the min/max value from the
+ underlying type of an enumeration, not the enumerated type itself.
- * dbxout.c (dbxout_type_fields): Use HOST_WIDE_INT_PRINT_DEC
- appropriately.
- (dbxout_type_method_1, dbxout_type): Likewise.
- (print_int_cst_octal, print_octal, dbxout_symbol): Likewise.
- (dbxout_type): Fix check for when to print a type range in
- octal vs decimal.
+Mon Feb 15 23:04:48 1999 Jeffrey A Law (law@cygnus.com)
-Fri Apr 24 16:45:03 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * jump.c: Include insn-attr.h.
+ (delete_computation): If reload has completed and insn scheduling
+ after reload is enabled, then do not depend on REG_DEAD notes.
+ * Makefile.in (jump.o): Depend on insn-attr.h.
- * (gen_shl_and, in case 1): Fix comparison with mask.
+Mon Feb 15 16:57:38 1999 Richard Henderson <rth@cygnus.com>
-Fri Apr 24 06:46:40 1998 Nick Clifton <nickc@cygnus.com>
+ * i386.md (addsi3): Allow lea for any constant_p.
- * config/arm/thumb.h (GO_IF_LEGITIMATE_ADDRESS): Disallow frame
- pointer as second register in REG+REG pair.
+1999-02-15 Zack Weinberg <zack@rabi.columbia.edu>
-Fri Apr 24 09:22:23 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * toplev.c (documented_lang_options): Remove -fident and
+ -fnoident, which are now handled by the language independent
+ option parser.
+
+1999-02-15 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * c-common.c (UNGETC [USE_CPPLIB=1]): Do nothing if c is EOF.
+ * c-lex.c: Likewise.
+ * cpplib.c (cpp_push_buffer, cpp_pop_buffer): Use a linked
+ list in malloced memory for the buffer stack.
+ (cpp_get_token): Don't pop the last buffer off the stack.
+ Calls after CPP_EOF has been returned produce CPP_EOF with no
+ state change.
+ (cpp_finish): Pop last buffer here.
+ (do_line): Don't free ip->last_nominal_fname if it is equal to
+ ip->fname.
+ (special_symbol): If a T_CONST is the empty string, push a
+ single `@ ' escape instead.
+ (macroexpand): Special symbol buffers have escapes too.
+ * cpplib.h (struct cpp_buffer): Remove unused fields, add prev
+ buffer pointer.
+ (struct cpp_reader): Remove buffer_stack. Add
+ buffer_stack_depth.
+ (CPP_PREV_BUFFER, CPP_NULL_BUFFER): Buffer stack is now a
+ linked list.
+
+Mon Feb 15 14:44:53 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cccp.c: Don't define HOST_WIDE_INT. Replace all occurrences of
+ WIDE_INT with WIDEST_INT.
- * c-common.c (check_format_info): Don't check for the 'x' format
- character twice, instead check for 'x' and 'X'
+ * cexp.y: Likewise.
+ Don't define unsigned_HOST_WIDE_INT, CHAR_BIT or
+ HOST_BITS_PER_WIDE_INT. Replace occurrences of PRINTF_PROTO_1()
+ style with PVPROTO() ATTRIBUTE_PRINTF_1 style macros. Replace
+ occurrences of "unsigned_HOST" with "unsigned HOST". Provide a
+ definition of variable `c89' when compiling a test binary and set it.
-Fri Apr 24 08:02:30 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * system.h: Don't define the PRINTF_PROTO_* macros.
- * Makefile.in (libgcc2.ready): Add explicit dependancy from
- $(STMP_FIXPROTO) to ensure all necessary include files have
- been created and to guarantee proper parallel builds.
+Mon Feb 15 11:33:51 1999 Jeffrey A Law (law@cygnus.com)
-Fri Apr 24 04:42:35 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * loop.c (mark_loop_jump): Handle LO_SUM. If we encounter something
+ we do not understand, mark the loop and containing loops as invalid.
- * sh.c (sh_expand_prologue, in !SH3E code): Don't push an extra
- register for stdarg functions.
- * sh.h (current_function_varargs): Declare.
- (FUNCTION_ARG): Ignore NAMED for stdarg functions.
+Mon Feb 15 00:40:45 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-1998-04-23 Jim Wilson <wilson@cygnus.com>
+ * alias.c (init_alias_analysis): Avoid self-referential value
+ when setting reg_known_value from REG_EQUAL notes.
- * frame.c, libgcc2.c (stdlib.h, unistd.h): Don't include when
- inhibit_libc is defined.
+Sun Feb 14 23:12:10 1999 Richard Henderson <rth@cygnus.com>
- * c-aux-info.c (gen_type): Use DECL_NAME only for TYPE_DECL.
+ * i386.c (legitimate_address_p): Verify modes of base and index.
-Thu Apr 23 19:09:33 1998 Jim Wilson <wilson@cygnus.com>
+Sun Feb 14 23:01:28 1999 Richard Henderson <rth@cygnus.com>
- * profile.c (tablejump_entry_p): New function.
- (branch_prob): Add code to recognize MIPS tablejump entry branch.
- Use tablejump_entry_p in MIPS and HPPA tablejump checking code.
+ * i386.c (legitimate_pic_address_disp_p): Remove static.
+ * i386.h (LEGITIMATE_PIC_OPERAND_P): Use it instead of
+ open-coding cases.
-Thu Apr 23 15:01:13 1998 Nick Clifton <nickc@cygnus.com>
+Sun Feb 14 21:03:28 1999 Jeffrey A Law (law@cygnus.com)
- * config/arm/arm.c (find_barrier): Return as soon as a barrier is
- found, rather than at end of the loop, after the insn has been
- changed.
+ * except.c (start_catch_handler): Use emit_cmp_and_jump_insns.
+ * explow.c (probe_stack_range): Likewise.
+ * expmed.c (do_cmp_and_jump): Likewise.
+ * expr.c (store_expr, expand_expr, expand_builtin): Likewise.
+ (do_tablejump): Likewise.
+ * stmt.c (expand_expr_stmt, expand_end_case): Likewise.
+ (do_jump_if_equal, emit_case_nodes): Likewise.
+ * optabs.c (emit_cmp_and_jump_insns): Clarify comments. If UNSIGNEDP,
+ then convert comparison to an unsigned code before emitting the jump.
+ (expand_float, expand_fix): Use emit_cmp_and_jump_insns.
-Thu Apr 23 20:21:06 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Sun Feb 14 02:24:15 1999 Jeff Law (law@cygnus.com)
- * sh.c (gen_ashift_hi): Implement right shifts via gen_ashift.
- * sh.md (ashrhi3_k, lshrhi3_k, lshrhi3_m, lshrhi3, lshrhi3+1): Delete.
+ * version.c: Bump for snapshot.
-Wed Apr 22 17:07:35 1998 Michael Meissner <meissner@cygnus.com>
+Sun Feb 14 01:15:04 1999 Jeff Law (law@cygnus.com)
- * loop.c (note_addr_stored): Correct function to take 2 arguments,
- instead of 1.
+ * version.c: Bump for snapshot.
- * rtl.def (MATCH_INSN2): Add new matching pattern.
- * genrecog.c (add_to_sequence): Support MATCH_INSN2.
+Sun Feb 14 00:45:50 1999 Jeffrey A Law (law@cygnus.com)
-Wed Apr 22 15:52:22 1998 John Carr <jfc@mit.edu>
+ * loop.c: Disable recent loop changes. Temporary as Joern
+ continues to fix problems.
- * emit-rtl.c (gen_highpart): The high part of a CONST_INT is not zero
- if HOST_BITS_PER_WIDE_INT is larger than BITS_PER_WORD.
+Sat Feb 13 23:29:42 1999 Richard Henderson <rth@cygnus.com>
- * final.c (split_double): Sign extend both halves of a split CONST_INT.
+ * loop.c (combine_givs_used_by_other): Delete.
+ (combine_givs_benefit_from): Delete.
+ (combine_givs): Deny combination of givs only used once. Simplify
+ code with the death of combine_givs_benefit_from.
-Wed Apr 22 10:42:45 1998 Jeffrey A Law (law@cygnus.com)
+Sun Feb 14 11:24:05 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * mips.c (compute_frame_size): Change only argument to a HOST_WIDE_INT.
+ * loop.c (scan_loop): Call reg_in_basic_block_p before
+ loop_reg_used_before_p.
-Wed Apr 22 10:53:49 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Sat Feb 13 05:32:00 1999 Richard Earnshaw (rearnsha@arm.com)
- * cplus-dem.c (struct work stuff): Add field for B and K mangle codes.
- (cplus_demangle_opname): Call mop_up_squangle.
- (cplus_demangle): Initialize squangle info, then call
- internal_cplus_demangle. (Most code moved there as well)
- (internal_cplus_demangle): New function, performs most of what use
- to be done in cplus_demangle, but is only called with this file.
- (squangle_mop_up): New function to clean up B and K code data.
- (mop_up): set pointers to NULL after freeing.
- (demangle_signature, demangle_template, demangle_class): Add
- switch elements to handle K and B codes.
- (demangle_prefix, gnu_special, demangle_qualified): Add
- code to handle K and B codes.
- (do_type, demangle_fund_type): Handle B and K codes.
- (remember_Ktype): New function to store K info.
- (register_Btype, remember_Btype): New functions for B codes.
- (forget_B_and_K_types): New function to destroy B and K info.
+ * arm.md: Use gen_rtx_FOO instead of gen_rtx (FOO, ...).
+ * arm.h: Likewise.
+ * arm.c: Likewise.
-1998-04-21 Jim Wilson <wilson@cygnus.com>
+ * arm.h (TARGET_OPTIONS): Reformat for clarity.
+ (GO_IF_LEGITIMATE_ADDRESS): When generating PIC, references to symbols
+ in the constant pool aren't valid.
+ (LEGITIMATE_PIC_OPERAND_P): Likewise.
- * stmt.c (check_seenlabel): When search for line number note for
- warning, handle case where there is no such note.
+ * arm.c: Include "system.h", not stdio.h and string.h.
-Tue Apr 21 20:48:37 1998 John Carr <jfc@mit.edu>
+Fri Feb 12 13:06:28 1999 Jim Wilson <wilson@cygnus.com>
- * genemit.c (gen_exp): Allow machine description to set mode of
- MATCH_OP_DUP.
+ * stmt.c (expand_return): Return if optimize_tail_recursion succeeded.
+ (optimize_tail_recursion): Change return type from void to int.
+ Add return statements.
+ * tree.h (optimize_tail_recursion): Change prototype to match.
-Tue Apr 21 16:36:01 1998 John Carr <jfc@mit.edu>
+Fri Feb 12 21:09:51 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * alias.c (mode_alias_check): New function.
- (true_dependence, anti_dependence, output_dependence): Call
- mode_alias_check.
+ * reload.c (find_reloads_subreg_address): New function, broken out of
+ find_reloads_toplev.
+ (find_reloads_toplev, find_reloads_address_1): Use it.
-Tue Apr 21 12:05:32 1998 Jeffrey A Law (law@cygnus.com)
+Fri Feb 12 13:20:52 1999 Jeffrey A Law (law@cygnus.com)
- * mips.h (STACK_BOUNDARY): Allow specific targets to override.
- (MIPS_STACK_ALIGN): Similarly.
+ * h8300.md (zero_extendhisi2 H8/300 variant): Correctly handle
+ extending a CONST_INT.
- * c-common.c (type_for_mode): Handle TI types.
- * c-decl.c (intTI_type_node, unsigned_int_TI_type_node): Define.
- (init_decl_processing): Handle TI types.
- * c-tree.h (intTI_type_node, unsigned_int_TI_type_node): Declare.
+ * h8300.md (peephole for combining memrefs): Delete incorrect peephole.
- * mips.c (block_move_loop): Test Pmode == DImode instead of
- TARGET_MIPS64.
- (expand_block_move, save_restore_insns): Likewise.
- (function_prologue, mips_expand_prologue): Likewise.
- (mips_expand_epilogue): Likewise.
- * mips.h (POINTER_SIZE): Allow specific targets to override.
- (Pmode): Allow specific targets to override.
- (FUNCTION_PROFILER): Test Pmode == DImode instead of TARGET_MIPS64
- (POINTER_BOUNDARY, FUNCTION_MODE): Likewise.
- (TRAMPOLINE_TEMPLATE, TRAMPOLINE_SIZE): Likewise.
- (TRAMPOLINE_ALIGNMENT, INITIALIZE_TRAMPOLINE): Likewise.
- (CASE_VECTOR_MODE, ASM_OUTPUT_ADDR_VEC_ELT): Likewise.
- (ASM_OUTPUT_ADDR_DIFF_ELT, SIZE_TYPE, PTRDIFF_TYPE): Likewise.
- * mips.md (indirect, tablejump & casesi support): Test for
- Pmode == DImode instead of TARGET_MIPS64.
- (call patterns): Likewise.
+Fri Feb 12 18:29:11 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Tue Apr 21 09:43:55 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * loop.c (loop_insn_first_p, biv_elimination_giv_has_0_offset):
+ New functions.
+ (maybe_eliminate_biv_1): Use biv_elimination_giv_has_0_offset.
- * objc/sendmsg.c: Define gen_rtx_MEM() to 1, as is already done
- for gen_rtx(MEM, ...).
+Fri Feb 12 16:56:10 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Tue Apr 21 02:15:36 1998 Richard Henderson <rth@cygnus.com>
+ * loop.c (load_mems): Don't guess how to do a load / store, use
+ emit_move_insn.
- * sparc.h (MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): Rewrite
- to not be so gross, and to properly function with PIC.
+Fri Feb 12 09:24:26 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon Apr 20 20:44:25 1998 Jim Wilson <wilson@cygnus.com>
+ * system.h: Provide a definition for HOST_WIDEST_INT, etc.
- * frame.c (heapsort): Rename to frame_heapsort.
+Fri Feb 12 23:37:26 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * gcc.c (do_spec_1, case '['): Move flag out of loop and initialize it.
+ * config/c4x/c4x.c (c4x_address_cost): Revert 9 Feb change.
-Mon Apr 20 12:43:09 1998 Doug Evans <devans@canuck.cygnus.com>
+Fri Feb 12 00:51:26 1999 Jeffrey A Law (law@cygnus.com)
- * flow.c (sbitmap_vector_alloc): Ensure sbitmaps properly aligned.
+ * reload.c (find_reloads_address_1): Fix handling of an autoincremented
+ pseudo which is homed in the stack.
-Mon Apr 20 15:04:14 1998 John Wehle (john@feith.com)
+ * mips.c (save_restore_insns): Fix loop to save/restore FP registers.
+ (compute_frame_size): Change loop over FP regs to be consistent
+ with the loop in save_restore_insns.
- * i386.md (movsf_push, movdf_push, movxf_push): Allow memory
- operands during and after reload.
+Thu Feb 11 17:38:40 1999 Jim Wilson <wilson@cygnus.com>
-Mon Apr 20 22:37:50 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * i960/i960.h (OVERRIDE_OPTIONS): Warn if -mlong-double-64 is used.
+ (LONG_DOUBLE_TYPE_SIZE): Undef then unconditionally define to 96.
- * final.c (shorten_branches, init_insn_lengths): Move code
- to free label_align, uid_shuid, insn_lengths, insn_addresses
- and uid_align from the former function into the latter one;
- Add code to clear these variables.
- * sh.h (label_align): Remove declaration.
+Thu Feb 11 15:11:35 1999 Jeffrey A Law (law@cygnus.com)
-Mon Apr 20 14:48:29 1998 Michael Meissner <meissner@cygnus.com>
+ * mn10200.md (bset); Re-enable.
- * gcc.c (lang_specific_driver): Declare prototype properly so
- fatal can be passed to it without error.
+Thu Feb 11 15:20:49 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * configure.in (AC_CHECK_FUNCS): Check for strchr and strrchr.
- * configure: Regenerate.
- * config.in: Add #undef's for strchr and strrchr.
+ * sh.md (is_sfunc): New attribute.
+ * sh.h (INSN_SETS_ARE_DELAYED, INSN_REFERENCES_ARE_DELAYED): Use it.
+
+Thu Feb 11 01:06:49 1999 Nathan Sidwell <nathan@acm.org>
- * protoize.c (toplevel): If we have rindex, but not strrchr, map
- rindex to strrchr.
- (file_could_be_converted): Use strrchr, not rindex since rindex is
- not defined on Linux systems when _POSIX_SOURCE is defined.
- (file_normally_convertible): Ditto.
- (process_aux_info_file): Ditto.
- (main): Ditto.
+ * fold-const.c (range_binop): Take account of the bounded nature
+ of fixed length arithmetic when comparing unbounded ranges.
- * rs6000.md (mov{sf,df} define_splits): When splitting a move of
- a constant to an integer register, don't split the insns that do
- the simple AND and OR operations, rather just split each word, and
- let the normal movsi define split handle it further.
+Thu Feb 11 00:08:17 1999 John Wehle (john@feith.com)
-Mon Apr 20 18:19:40 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * function.c (assign_stack_temp_for_type): Clear best_p
+ when an exact match is found.
- * sh.c (find_barrier): Fix bug in ADDR_DIFF_VEC handling.
- (split_branches): Call init_insn_lengths.
+ * i386.h (LOCAL_ALIGNMENT): Define.
+ * function.c (assign_stack_local, assign_outer_stack_local): Use it.
+ (assign_stack_temp_for_type): New function based on assign_stack_temp.
+ (assign_stack_temp): Call it.
+ (assign_temp): Use assign_stack_temp_for_type, not assign_stack_temp.
+ * stmt.c: Use assign_temp, not assign_stack_temp.
+ * tm.texi: Document LOCAL_ALIGNMENT.
-Mon Apr 20 07:37:49 1998 Michael Meissner <meissner@cygnus.com>
+Wed Feb 10 23:28:28 1999 Jeffrey A Law (law@cygnus.com)
- * i386.c: Include expr.h to get the change_address prototype
- declared.
+ * reorg.c: Finish deleting half-deleted comment.
-Mon Apr 20 01:00:05 1998 H.J. Lu (hjl@gnu.org)
+Wed Feb 10 17:12:21 1999 Jim Wilson <wilson@cygnus.com>
- * reg-stack.c (subst_asm_stack_regs): Change to return the last
- new insn generated by this function.
- (subst_stack_regs): Likewise.
- (convert_regs): Record the last newly generated insn and use
- it for change_stack () instead of INSN.
+ * emit-rtl.c (operand_subword): Sign extend REAL_VALUE_TO_TARGET_SINGLE
+ result.
+ * final.c (split_double): Sign extend REAL_VALUE_TO_TARGET_DOUBLE
+ result.
+ * real.c (endian): Delete sign extension code.
+ * config/m32r/m32r.md (movsf_insn+1): REAL_VALUE_TO_TARGET_SINGLE call
+ replaced with operand_subword call.
-Sun Apr 19 15:41:24 1998 Manfred Hollstein <manfred@s-direktnet.de>
+Wed Feb 10 15:16:39 1999 Richard Henderson <rth@cygnus.com>
- * fix-header.c (enum special_file): Undefine enumerators if they
- are already defined by include files.
- * fixproto (rel_source_file in unistd.h stdlib.h): Prefix file protection
- macro with '__' to not pollute user namespace.
+ * alpha.md (cmov compound patterns): Delete. Jump can now
+ create the correct constructs in the first place.
-Sun Apr 19 02:42:06 1998 Richard Henderson <rth@cygnus.com>
+Wed Feb 10 11:03:22 1999 Richard Henderson <rth@cygnus.com>
- * haifa-sched.c (queue_to_ready): Fix typo in prototype.
+ * configure.in (alphaev6*): Fix typo in target_cpu_default2.
-Sat Apr 18 23:52:35 PDT 1998 Jeff Law (law@cygnus.com)
+Wed Feb 10 13:59:18 1999 Dave Brolley <brolley@cygnus.com>
- * version.c: Bump for snapshot.
+ * mbchar.c (local_mb_cur_max): Handle the case where MB_CUR_MAX is 0.
-Sat Apr 18 18:30:22 1998 Jim Wilson <wilson@cygnus.com>
+Wed Feb 10 10:35:05 1999 Jim Wilson <wilson@cygnus.com>
- * i386.md (fix_truncsfdi2+[123]): Add + to operand 1 constraints.
+ * tmp-emsgids.c: Delete.
- * i386.h (CPP_CPU_DEFAULT): Renamed to CPP_CPU_DEFAULT_SPEC.
- Add missing -Dpentium* options.
- (CPP_CPU_SPEC): Delete redundant definition. Include cpp_cpu_default
- instead of CPP_CPU_DEFAULT.
- (EXTRA_SPECS): Add entry for cpp_cpu_default.
+Wed Feb 10 09:57:08 1999 Mark Mitchell <mark@markmitchell.com>
-Sat Apr 18 19:06:59 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * rtlanal.c (for_each_rtx): Fix declaration to conform to GNU
+ coding standards.
- * rs6000.md (floatsidf2_loadaddr): rs6000_fpmem_offset will be
- negative in a stackless frame.
- * rs6000.c (rs6000_stack_info): Don't include fixed-size link area
- in stackless frame size. Support 64-bit stackless frame size.
- Combine fpmem offset calculations and don't add total_size to
- offset if not pushing a stack frame.
+Wed Feb 10 10:09:41 1999 Jeffrey A Law (law@cygnus.com)
-Sat Apr 18 15:41:16 1998 Jim Wilson <wilson@cygnus.com>
+ * mn10200.md (bset, bclr): Operand 0 is a read/write operand.
- * regmove.c (fixup_match_1): In three places, in flag_exceptions
- check, change p to q.
+ * reload1.c (reload_combine_note_store): Second argument is no
+ longer unused/ignored. Handle multi-register hard regs.
+ (move2add_note_store): Simplify.
-Sat Apr 18 15:30:49 1998 Jim Wilson <wilson@cygnus.com>
+Wed Feb 10 10:05:23 1999 Mumit Khan <khan@xraylith.wisc.edu>
- * gcc.c (lang_specific_driver): Add new parm type to prototype.
- (added_libraries): New file scope static variable.
- (process_command): Initialize added_libraries. Pass it to
- lang_specific_driver.
- (main): Use added_libraries in check for no input files.
+ * collect2.c (collect_execute): Remove cygwin-specific code.
-Sat Apr 18 01:23:11 1998 John Carr <jfc@mit.edu>
+Tue Feb 9 17:27:29 1999 Nathan Sidwell <nathan@acm.org>
- * sparc.c, sparc.h, sparc.md, sol2.h: Many changes related to V9
- code generation. Use 64 bit instructions in 32 bit mode when
- possible. Use V9 return instruction. UltraSPARC optimizations.
+ * system.h (_, N_): Remove dummy i18n macros.
+ * protoize.c: Move inclusion of intl.h to after system.h.
+ * cexp.y: Include intl.h.
+ * cexp.c: Rebuilt.
- * sparc.h: Change gen_rtx (CODE to gen_rtx_CODE (.
+Tue Feb 9 16:52:22 1999 Mumit Khan <khan@xraylith.wisc.edu>
-Fri Apr 17 22:38:17 1998 Jeffrey A Law (law@cygnus.com)
+ * i386/cygwin.h (SUBTARGET_OVERRIDE_OPTIONS): New macro to ignore
+ fpic/fPIC for windows32 targets.
+ * i386/xm-cygwin.h (GET_ENV_PATH_LIST): Replace '\\' in windows32
+ paths with '/'.
+ * i386/mingw32.h (CPP_SPEC): Define.
+ (CPP_PREDEFINES): Add MINGW32 version id.
+ * i386/crtdll.h (CPP_PREDEFINES): Likewise.
- * global.c (global_alloc): Don't pass HARD_CONST (0) to find_reg,
- just pass zero. That will work regardless of the size of HARD_REG_SET.
+ * Makefile.in (collect2$(exeext)): Delete redundant dependency and
+ add missing exeext to target.
- * libgcc2.c (__floatdisf): Fix a couple typos.
+ * gcc.c (convert_filename): Handle null filename argument.
-Fri Apr 17 17:28:26 1998 Jim Wilson <wilson@cygnus.com>
+Wed Feb 10 15:46:10 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * Makefile.in (mostlyclean): Delete *.mach and *.bp files.
+ * config/c4x/c4x.md (*movhf_noclobber, *movhi_noclobber): Use
+ m constraint instead of QT.
-Fri Apr 17 16:35:35 1998 Greg McGary <gkm@gnu.org>
+1999-02-09 Brendan Kehoe <brendan@cygnus.com>
- * emit-rtl.c (gen_highpart): initialize `word' properly for pseudo.
+ * cpplib.c (special_symbol): Move IP to be declared in function
+ scope, rather than individual case statements.
-Fri Apr 17 14:30:37 1998 John Carr <jfc@mit.edu>
+1999-02-09 Zack Weinberg <zack@rabi.columbia.edu>
- * emit-rtl.c (operand_subword_force): If a register can not be
- accessed by words, copy it to a pseudo register.
+ * cppfiles.c (finclude): Handle pipes properly under old BSD
+ derivatives.
-Fri Apr 17 14:30:37 1998 Jim Wilson <wilson@cygnus.com>
+1999-02-09 Melissa O'Neill <oneill@cs.sfu.ca>
- * rs6000/vxppc.h (CPP_SPEC): Add support for mrelocatable*.
+ * system.h: Provide fallback definitions for S_ISCHR,
+ S_ISSOCK, S_ISFIFO, O_NONBLOCK, and O_NOCTTY.
-Fri Apr 17 17:01:25 1998 Michael Meissner <meissner@cygnus.com>
+1999-02-09 Zack Weinberg <zack@rabi.columbia.edu>
- * tree.h (mark_seen_cases): Delete declaration.
+ * cpplib.c (do_define): Allow redefining __STDC__ with -D.
-Fri Apr 17 13:32:20 1998 Jeffrey A Law (law@cygnus.com)
+1999-02-09 Jim Blandy <jimb@zwingli.cygnus.com>
- * stmt.c (mark_seen_cases): Make static and add prototype.
+ * configure.in: For PowerPC configurations, accept "401", "ec603e",
+ "740", and "750" as valid arguments to --with-cpu.
+ * configure: Rebuilt.
+
+Tue Feb 9 00:00:14 1999 Mark Kettenis <kettenis@gnu.org>
+
+ * configure.in (i[34567]86-*gnu*): Set float_format to i386.
+ * configure: Rebuilt.
+
+Mon Feb 8 22:38:24 1999 Jeffrey A Law (law@cygnus.com)
-Fri Apr 17 11:21:43 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * rs6000.md: Revert "alternate use of crs if cr0 not available"
+ patches from 01-22-1999, 01-24-1999, 01-26-1999, and 02-08-1999.
- * frame.c: Include stdlib.h and unistd.h to possibly get various
- function prototypes. The fixproto script guarantees these header
- files exist on the target system.
- * libgcc2.c: Likewise.
+Mon Feb 8 21:36:44 1999 Richard Henderson <rth@cygnus.com>
- * gthr-single.h (__gthread_mutex_lock, __gthread_mutex_trylock,
- __gthread_mutex_unlock): Add __attribute__ ((__unused__)) to the
- function parameters.
- * libgcc2.c (__udiv_w_sdiv): Likewise.
+ * output.h (current_function_has_computed_jump): Rename from
+ current_function_addresses_labels.
+ * function.h (struct function): Likewise for addresses_labels member.
+ * rtl.h (FUNCTION_FLAGS_HAS_COMPUTED_JUMP): Likewise.
+ * function.c (current_function_has_computed_jump): Likewise.
+ Update all references.
+ * integrate.c (function_cannot_inline_p):
+ Test current_function_has_computed_jump instead of addresses_labels.
+ (initialize_for_inline): Likewise save.
+ (output_inline_function): Likewise restore.
-Thu Apr 16 22:41:02 1998 Jeffrey A Law (law@cygnus.com)
+ * expr.c (expand_expr): Don't reference addresses_labels variables.
+ * stmt.c (expand_computed_goto): Set has_computed_jump.
- * varasm.c (asm_output_bss): Add prototype.
- (asm_output_aligned_bss): Likewise.
+1999-02-08 Michael Meissner <meissner@cygnus.com>
- * unroll.c (verify_addresses): Add prototype.
+ This is being installed only to get it into the repository to help
+ with the revert, resubmit & review process for the massive rs6000.md
+ changes.
+ * rs6000.md (andsi3_internal1 splitter): Don't split if using the
+ rlwinm instruction.
+ (anddi3_internal1): Likewise.
+ (andsi3_internal{2,3}): Correct some insn lengths.
+ (anddi3*): Restore missing TARGET_POWERPC64, and don't emit old
+ mnemonics.
+
+Mon Feb 8 21:31:06 1999 Richard Henderson <rth@cygnus.com>
+
+ * loop.c (reg_single_usage): New file-scope variable ...
+ (scan_loop): ... moved out of here. Always initialize.
+ Test loop_has_call instead of reg_single_usage not zero.
+ Free reg_single_usage after strength reduction.
+ (count_loop_regs_set): Assume single_usage non-zero.
+ (combine_givs_used_by_other): Test reg_single_usage.
+ (load_mems_and_recount_loop_regs_set): Remove reg_single_usage
+ as a parameter. Assume non-zero.
+
+1999-02-08 Zack Weinberg <zack@midnite.ec.rhno.columbia.edu>
+
+ * cpplib.c (special_symbol): Rewrite. Don't copy things
+ multiple times. Handle __STDC__ specially. T_CONST
+ indicates a constant /string/. Don't handle T_*_TYPE and
+ T_SPEC_DEFINED. Use cpp_buf_line_and_col instead of
+ adjust_position. Determine the file buffer only if needed.
+ (initialize_builtins): Handle __SIZE_TYPE__,
+ __PTRDIFF_TYPE__, __WCHAR_TYPE__, __USER_LABEL_PREFIX__, and
+ __REGISTER_PREFIX__ with T_CONST special hashtab entries.
+ Don't provide __OBJC__; the driver does that. Provide
+ __STDC_VERSION__, using T_CONST. Use T_STDC for
+ __STDC__. Give install the length of all symbols defined.
+ (eval_if_expression): Drop code to insert and remove the
+ "defined" special symbol.
+
+ * cpplib.h: Remove SELF_DIR_DUMMY (no longer used). Remove
+ T_*_TYPE and T_SPEC_DEFINED from enum node_type; add T_STDC.
+
+ * cpphash.c (install): Drop the `ivalue' parameter. Constify
+ the `value' parameter. All callers changed.
+ * cpphash.h (install): Change prototype to match.
+ (union hashval): Remove `ival' member.
+ * cppexp.c (cpp_lex): Handle `defined' here.
+
+Mon Feb 8 17:29:42 1999 Jeffrey A Law (law@cygnus.com)
+
+ * pa.h (EXTRA_CONSTRAINT): Fix comment.
+
+Mon Feb 8 18:57:45 1999 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * c-typeck.c (check_init_type_bitfields): Use nonincremental
+ initialization of unions whose first member is a bitfield.
+ Remove unnecessary code for checking the declaration mode
+ after DECL_C_BIT_FIELD.
+
+ * varasm.c (output_constructor): Additional comment about the
+ constructor of bitfield union initialization.
+
+Tue Feb 9 11:55:04 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.md (*movhi_stik): New pattern.
+ (movhi): Allow some immediate constants to be directly
+ stored in memory.
+
+Tue Feb 9 11:34:15 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.md (all call patterns): Add constraints "Ur".
+ (call, call_value): Force address into a register if not valid
+ for a call instruction.
+ (load_immed_address): Emit a USE of the SYMBOL_REF that is
+ forced into memory.
+ * config/c4x/c4x.c (c4x_print_operand): Fix 'C' and 'U' modifiers.
+
+Tue Feb 9 11:08:41 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.c (call_address_operand, symbolic_address_operand):
+ Rename from call_operand and symbolic_operand respectively. All
+ callers changed.
+ * config/c4x/c4x.md (call_address_operand, symbolic_address_operand):
+ Likewise.
+ * config/c4x/c4x.h (call_address_operand, symbolic_address_operand):
+ Likewise.
+ (PREDICATE_CODES): Allow CONST, LABEL_REF for call_address_operand.
- * toplev.c: Add many prototypes. Too many to mention here.
+Tue Feb 9 10:52:27 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * stmt.c (check_seenlabel): Add prototype.
+ * config/c4x/c4x.c (c4x_legitimize_address): Don't generate a
+ LO_SUM address for HImode or HFmode but instead force address into
+ a register so that it is offsettable.
+ (c4x_emit_move_sequence): Handle LO_SUM immediate address.
- * rtlanal.c (reg_set_p_1): Add prototype.
- (reg_set_last_1): Likewise.
+Tue Feb 9 10:46:42 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * reorg.c (find_dead_or_set_registers): Add prototype.
+ * config/c4x/c4x.c (c4x_address_cost): Return cost of 1 for
+ REG+REG addressing if strength reduction enabled.
- * regmove (try_auto_increment): Add prototype.
+Tue Feb 9 10:10:31 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * reg-stack.c (pop_stack): Add prototype.
+ * config/c4x/t-c4x (LIBGCC2_CFLAGS): Delete.
+ (TARGET_LIBGCC2_CFLAGS): Define.
- * recog.c (validate_replace_rtx_1): Add prototype.
- (find_cosntant_term_loc): Likewise.
+1999-02-08 Nick Clifton <nickc@cygnus.com>
- * loop.c (regs_patch_p): Add prototype.
- (add_label_notes, count_nonfixed_reads): Likewise.
- (find_single_use_in_loop): Likewise.
- (express_from): Surround prototype with #ifdef.
- (giv_sort): Similarly.
+ * config/v850/v850.md: Replace \\n\\t with \\;
- * jump.c (mark_modified_reg): Add prototype.
+ * config/v850/v850.md: Enforce TARGET_LONG_CALLS option.
+ * config/v850/v850.c (construct_restore_jr, construct_save_jarl):
+ Enforce TARGET_LONG_CALLS option.
- * haifa-sched.c (is_prisky): Add prototype.
- (queue_to_ready): Likewise.
+Mon Feb 8 11:43:07 1999 Donn Terry <donn@interix.com>
- * genextract.c (gen_insn): Add prototype.
+ * real.c (PUT_REAL) [XFmode]: Zero the balance of the structure.
- * genemit.c (max_operand_1): Add prototype.
- (max_operand_vec, print_code, gen_exp, gen_insn): Likewise.
- (gen_expand, gen_explit, output_add_clobbers): Likewise.
- (output_init_mov_optab): Likewise.
+Mon Feb 8 11:37:24 1999 Marc Espie (espie@cvs.openbsd.org)
- * genattrtab.c (attr_hash_add_rtx): Add prototype.
- (attr_hash_add_string, write_length_unit_log): Likewise.
+ * m88k/t-luna-gas: Remove bash dependency.
- * genattr.c (init_range): Add prototype.
+Mon Feb 8 11:34:44 1999 Graham <grahams@rcp.co.uk>
- * combine.c (sets_function_arg_p): Add prototype.
+ * collect2.c (xrealloc): Fix typo in last change.
- * expr.c (store_constructor_field): Add prototype.
- (get_memory_usage_from_modifier): Likewise
+Mon Feb 8 09:13:38 1999 Jeff Law (law@cygnus.com)
- * expmed.c (synth_mult): Add prototype.
- (choose_multiplier, invert_mod2n): Likewise.
+ * version.c: Bump for snapshot.
- * except.c (push_eh_entry): Add prototype.
- (pop_eh_entry, enqueue_eh_entry, dequeu_eh_entry): Likewise.
- (call_get_eh_context, start_dynamic_cleanup): Likewise.
- (start_dynamic_handler, can_throw): Likewise.
- (output_exception_table_entry, scan_region): Likewise.
- (eh_regs, set_insn_eh_region): Likewise.
+Sun Feb 7 22:18:42 1999 Robert Lipe <robertlipe@usa.net>
- * dwarfout.c (decl_class_context): Add prototype.
- (output_inheritance_die, type_ok_for_scope): Likewise.
+ * tree.h (TYPE_CHECK): Make it clear to the preprocessor
+ that we do not want macro replacement within a character constant.
+ (TYPE_CHECK1): Likewise.
- * c-lex.c (skip_white_space_on_line): Add prototype.
+Sun Feb 7 15:37:10 1999 Jason Merrill <jason@yorick.cygnus.com>
- * alias.c (record_set): Add prototype.
- (find_base_term, base_alias_check): Likewise.
+ * tree.h (DECL_P): New macro.
- * function.c (assign_outer_stack_local): Make static and add prototype.
+Sun Feb 7 01:15:04 1999 Jeff Law (law@cygnus.com)
- * haifa-sched.c (build_control_flow): Accept raw data as inputs
- instead of computing it locally. Callers changed.
- (find_rgns): Several new arguments. Callers changed.
- Generally clean up and comment better. Use dominators to
- identify reducible loops. Convert some flag arrays to bitmaps.
- Convert most of the code to work on pred/succ lists instead of
- an edge table. Add comments for future improvements.
- (schedule_insns): Allocate temporary tables for flow data, call
- routines to compute flow data and pass it along to children as
- arguments.
- (debug_control_flow): Delete. Use dump_bb_data instead.
+ * version.c: Bump for snapshot.
- * basic-block.h (compute_dominators): Declare.
+Sat Feb 6 18:14:46 1999 Jeffrey A Law (law@cygnus.com)
+
+ * mn10300.md (reload_insi): Do not earlyclobber the output operand.
+
+ * README.g77, gcc.c, gcc.texi: Update email addresses.
+ * invoke.texi system.h: Likewise.
+
+Sat Feb 6 11:04:08 1999 Jim Wilson <wilson@cygnus.com>
+
+ * unroll.c (find_splittable_givs): After express_from, call replace_rtx
+ to convert dest_reg to new_reg.
+
+Sat Feb 6 10:31:35 1999 Jeffrey A Law (law@cygnus.com)
+
+ * reload1.c (reload_combine_note_store): Be more careful with
+ STRICT_LOW_PART, ZERO_EXTRACT and SIGN_EXTRACT.
+ (move2add_note_store): Likewise.
+
+Sat Feb 6 10:18:01 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cppfiles.c (read_and_prescan): Cast the result of `xrealloc' to
+ U_CHAR* when assigning to one. Ensure the values of a ?: operator
+ have the same type.
+
+ * cppinit.c (initialize_char_syntax): Use K&R function definition.
+
+Sat Feb 6 11:17:03 1999 Richard Earnshaw <rearnsha@arm.com>
+
+ Support for ARM9
+ * config/arm/arm.c (all_procs): Add arm9 and arm9tdmi.
+ * config/arm/arm.h ((TARGET_CPU_arm9, TARGET_CPUD_arm9tdmi): Define.
+ (TARGET_CPU_DEFAULT): Rework to support ARM9.
+ (CPP_CPU_ARCH_SPEC): Likewise.
+ (enum processor_type): Likewise.
+ * config/arm/arm.md (attr cpu): Add arm9.
+
+ General scheduling changes
+ * config/arm/arm.c (MAX_INSNS_SKIPPED): Delete.
+ (max_insns_skipped): New variable.
+ (arm_override_options): If generating hard floating point code for
+ the FPA, emit code for version 3.
+ When optimizing for space, don't synthesize constants.
+ Reword several flags based on the requested processor and optimization
+ level.
+ (use_return_insn): New argument iscond, all callers changed. Don't
+ use a return insn if it will be conditional and that would be
+ expensive; eg on StrongARM.
+ (arm_adjust_cost): Anti- and output- dependencies normally have no
+ cost.
+ (load_multiple_sequence): Newer ARMs don't benefit from ldm if
+ the sequence is short.
+ (final_prescan_insn): Use max_insns_skipped instead of
+ MAX_INSNS_SKIPPED. Note whether we will make a return instruction
+ conditional, and aviod this if it would be expensive.
+ * config/arm/arm.md (scheduling attributes and function units):
+ Rewrite to better describe ARM8, 9 and StrongARM.
+
+ * config/arm/arm.md (*movhi_insn_littleend): Make op0 predicate
+ s_register_operand.
+ (*ifcompare_plus_move): Use arm_rhs_operand in place of
+ arm_rhsm_operand. Rework constraints.
+ (*if_plus_move): Likewise.
+ (*ifcompare_move_plus): Likewise.
+ (*if_move_plus): Likewise.
+ (*ifcompre_arith_move): Likewise.
+ (*if_arith_move): Likewise.
+ (*ifcompare_move_arith): Likewise.
+ (*if_move_arith): Likewise.
+
+ * config/arm/xm-netbsd.h: Don't include arm/xm-arm.h.
+
+1999-02-05 Michael Meissner <meissner@cygnus.com>
- * flow.c (dump_sbitmap, dump_sbitmap_vector): New debugging
- functions.
- * basic-block.h: Declare them.
+ * loop.c (check_dbra_loop): A store using an address giv for which
+ we have no life information is not reversible.
-Thu Apr 16 13:45:51 1998 Jim Wilson <wilson@cygnus.com>
+Fri Feb 5 17:08:01 1999 Dave Brolley <brolley@cygnus.com>
- * reg-stack.c (constrain_asm_operands): Set n_alternatives to zero if
- no operands.
+ * function.c (fixup_var_refs): Scan catch_clauses too.
-Wed Apr 15 11:33:09 1998 Alexandre Petit-Bianco <apbianco@sendai.cygnus.com>
+Fri Feb 5 11:49:49 1999 Benjamin Kosnik <bkoz@loony.cygnus.com>
- * tree.c (build_expr_wfl): Use NULL_TREE if the file name is NULL.
- Propagate TREE_SIDE_EFFECTS and TREE_TYPE iff the encapsulated
- node is non NULL. Cache last file name and file name identifier node.
+ * c-common.c (decl_attributes): Fix reserved space for init_priority.
+ * tree.h (MAX_RESERVED_INIT_PRIORITY): New macro.
-1998-04-15 Mark Mitchell <mmitchell@usa.net>
+Fri Feb 5 12:37:05 1999 Jeffrey A Law (law@cygnus.com)
- * c-common.c (declare_hidden_char_array): Use TYPE_DOMAIN to get
- the length of an array, not TREE_TYPE.
+ * loop.c (strength_reduce): Clear not_every_iteration when
+ passing the NOTE_INSN_LOOP_CONT note.
-Wed Apr 15 15:31:34 1998 Jeffrey A Law (law@cygnus.com)
+ * haifa-sched.c (add_dependence): Do not add a dependency on a
+ note.
- * flow.c (sbitmap_union_of_successors): New function.
- * basic-block.h (sbitmap_union_of_successors): Declare it.
+Fri Feb 5 10:55:43 1999 Nick Clifton <nickc@cygnus.com>
-Wed Apr 15 12:38:03 1998 Jim Wilson <wilson@cygnus.com>
+ * recog.c (split_block_insns): Only call update_flow_info if
+ instruction scheduling is enabled.
- * configure.in (gnu_ld): Rename to gnu_ld_flag before main loop.
- Set gnu_ld to gnu_ld_flag inside main loop.
- (gas): Likewise.
+1999-02-05 Zack Weinberg <zack@rabi.columbia.edu>
-Wed Apr 15 14:50:05 1998 Dave Brolley <brolley@cygnus.com>
+ * Makefile.in (gen-protos): Use libcpp.a like everyone else.
- * toplev.c (compile_file): Call init_parse using new interface.
- (init_lex): Remove declaration.
+Fri Feb 5 07:09:29 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * c-lex.c (init_parse): Now returns char* containing filename.
+ * loop.c (first_loop_store_insn): New file-scope variable.
+ (prescan_loop): Set it.
+ (check_dbra_loop): Check if a store depends on a register
+ that is set after the store.
-Wed Apr 15 12:37:10 1998 Jeffrey A Law (law@cygnus.com)
+Fri Feb 5 06:55:15 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * unroll.c (entire file): Remove tabs / spaces at end of lines.
+ Replace spaces with tabs where appropriate.
+
+Thu Feb 4 15:12:41 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * loop.c (scan_loop): New argument loop_cont. Changed caller.
+ (strength_reduce): New argument loop_cont. Changed caller.
+ Before clearing not_every_iteration after a label, check if
+ we are not already past LOOP_CONT.
+
+1999-02-04 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * cpperror.c (cpp_print_containing_files): Fix formatting
+ bug induced by merge.
+
+1999-02-04 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cpplib.c (initialize_char_syntax): Move to cppinit.c.
+ (cpp_define): Remove redundant syntax checks.
+ (make_assertion): Rename cpp_assert, remove redundant syntax
+ checks, export.
+ (cpp_options_init): Don't init things to zero twice.
+ (cpp_expand_to_buffer): Use memcpy, not a char-by-char loop.
+ (do_include): Kill excessively verbose #import warning that
+ snuck back in in the gcc2 merge.
+ (convert_string): Removed.
+ (do_line): Rewrite with simple last-name-used cache instead of
+ private hashtable.
+ (cpp_start_read): Call initialize_char_syntax here, not...
+ (cpp_reader_init): ...here.
+ (cpp_handle_options): Support the -std switch.
+ * cpplib.h (cpp_buffer): Add last_nominal_fname member.
+ (cpp_options): Add c9x flag.
+ Declare all the is_* tables and trigraph table here, as const.
+ Prototype cpp_assert and initialize_char_syntax.
+ * cppinit.c: New file.
+ * cppfiles.c (read_and_prescan): Optimize.
+ * Makefile.in (LIBCPP_OBJS): Add cppinit.o.
+
+Thu Feb 4 10:46:30 1999 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/mips/mips.md ([u]divmodsi4,[u]divmoddi4,[u]divsi3,[u]divdi3,
+ [u]modsi3,[u]moddi3) : Don't copy the "zero" argument to a register
+ before calling gen_div_trap.
+
+Wed Feb 3 21:56:27 1999 Jeffrey A Law (law@cygnus.com)
+
+ * configure.in (hppa1.1-*-*, hppa2*-*): Use symbolic value rather
+ than numeric value for target_cpu_default..
+ * configure: Rebuilt.
- * pa.h (LEGITIMIZE_RELOAD_ADDRESS): Do nothing if not optimizing.
+Wed Feb 3 21:55:56 1999 Marc Espie <Marc.Espie@liafa.jussieu.fr>
+
+ * Makefile.in (xgcc$(exeext)): Remove choose-temp, pexecute and
+ mkstemp. Get them from libiberty.
+ (COLLECT2_OBJS): Similarly for choose-temp, cplus-dem and mkstemp.
+ (PROTO_OBJS): Similarly for choose-temp, getopt, getopt1 and pexecute.
+ (cplus-dem.o, pexecute.o, choose-temp.o): Remove build rules.
+ (mkstemp.o, getopt1.o, getopt.o): Likewise.
+
+ * pa-gas.h (TARGET_DEFAULT): Use symbolic values rather than numeric
+ values.
+ * pa-hpux.h (LINK_SPEC): Likewise.
+ * pa-hpux10.h (LINK_SPEC): Likewise.
+ * pa-hpux9.h (LINK_SPEC): Likewise.
+ * pa-osf.h (LINK_SPEC): Likewise.
+ * pa-pro.h (TARGET_DEFAULT): Likewise.
+ * pa1.h (TARGET_DEFAULT): Likewise.
+ * pa.h (MASK_*): New defines.
+ (TARGET_*): Use symbolic values rather than numeric values.
+ (TARGET_SWITCHES): Likewise.
+ (TARGET_DEFAULT): Likewise.
+ (CPP_SPEC): Likewise.
+
+Wed Feb 3 21:07:38 1999 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * reload1.c (reload_cse_regs_1): Undo Jan 16 patch.
+ * reload.c (find_reusable_reload): New function, broken out of
+ push_reload. Add code to verify that none of the involved
+ outputs are subject to earlyclobbers.
+ (push_reload): Break out new function find_reusable_reload.
+ Delete "register" keyword for IN, OUT args.
+
+Wed Feb 3 15:51:04 1999 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/mips/mips.c (true_reg_or_0_operand) : New function.
+ * config/mips/mips.h (PREDICATE_CODES): Add true_reg_or_0_operand.
+ * config/mips/mips.md (div_trap,div_trap_normal,div_trap_mips16):
+ Use true_reg_or_0_operand for div_trap.
+
+Wed Feb 3 20:44:59 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * loop.h (express_from): Declare.
+ (struct induction): Replace derived flag with derived_from pointer.
+ * loop.c (strength_reduce, record_giv, recombine_givs): Likewise.
+ (express_from): No longer static.
+ * unroll.c (find_splittable_givs): Replace derived with derived_from.
+ When processing an address giv with which another giv has been
+ combined that has also been derived from a third giv, handle like
+ having combined with the third giv.
+ Set splittable_regs_updates appropriately for derived givs.
+
+Wed Feb 3 15:26:58 1999 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/mips/mips.md (div_trap_mips16): Remove nop's after branches.
+
+Wed Feb 3 11:56:23 1999 Jeffrey A Law (law@cygnus.com)
+
+ * pa.c (insn_sets_and_refs_are_delayed): New function.
+ * pa.h (INSN_SETS_ARE_DELAYED): Use it.
+ (INSN_REFERENCES_ARE_DELAYED): Likewise.
+
+Wed Feb 3 06:24:49 1999 Richard Earnshaw (rearnsha@arm.com)
+
+ * config/arm/t-arm-elf (LIBGCC2_CFLAGS): Delete.
+ * config/arm/t-linux (LIBGCC2_CFLAGS): Delete.
+ (TARGET_LIBGCC2_CFLAGS): Define.
+ (LIBGCC2_DEBUG_CFLAGS): Define.
+ * config/arm/t-netbsd: Likewise.
+ * config/arm/t-semi: Likewise.
+ * config/arm/t-semiaof: Likewise.
+ * config/arm/t-riscix: Likewise.
+
+Wed Feb 3 10:59:07 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * config/m68k/m68k.c (print_operand_address): When printing a
+ SYMBOL_REF that ends in `.<letter>' put parentheses around it.
+
+Tue Feb 2 23:38:35 1999 David O'Brien <obrien@FreeBSD.org>
-Wed Apr 15 12:10:18 1998 Michael Meissner <meissner@cygnus.com>
+ * i386/freebsd*.h now allows '$' in label names and does not use the
+ PCC struct return method.
- * Makefile.in (gen{config,flags,codes,emit}): Link in host print-rtl.o.
- (gen{extract,peep,opinit,output}): Ditto.
+Tue Feb 2 22:38:23 1999 Jim Wilson <wilson@cygnus.com>
- * gen{attr,codes,config,emit,output}.c (insn_attr_name): Provide a
- global definition so print-rtl.o can be linked in.
- * gen{peep,recog}.c (insn_attr_name): Ditto.
+ * Makefile.in: Change all uses of AR to AR_FOR_TARGET. Change all uses
+ of HOST_AR to AR. Likewise for AR_FLAGS, RANLIB, and RANLIB_TEST.
+ (RANLIB_TEST): Test to see if ranlib exists. Only test absolute file
+ names if host == target.
+ (HOST_AR, HOST_AR_FLAGS, HOST_RANLIB, HOST_RANLIB_TEST): Delete.
+ (AR_FLAGS_FOR_TARGET): Renamed from AR_FOR_TARGET_FLAGS.
+ (AR, AR_FLAGS, OLDAR, OLDAR_FLAGS, RANLIB, RANLIB_TEST): Delete rules
+ setting them to *_FOR_TARGET.
+ * cross-make (AR, AR_FLAGS, OLDAR, OLDAR_FLAGS, RANLIB, RANLIB_TEST):
+ Delete.
-Tue Apr 14 07:30:57 1998 K. Richard Pixley <rich@kyoto.noir.com>
+Tue Feb 2 22:38:19 1999 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
- * fixincludes: discard empty C++ comments, as found in sys/time.h
- on hpux-11.0.
+ * toplev.h (read_integral_parameter): Declare.
+ * toplev.c (read_integral_parameter): New function.
-Wed Apr 15 10:47:21 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Fri Jan 29 21:00:56 1999 Bob Manson <manson@charmed.cygnus.com>
- * config/m68k/m68k.md (adddi3, subdi3): Optimize for constant
- operand.
+ * resource.c, resource.h: New files.
+ * Makefile.in (OBJS): Add it.
-Wed Apr 15 01:21:21 1998 Jeffrey A Law (law@cygnus.com)
+ * haifa-sched.c (regno_use_in): Moved to rtlanal.c.
+ (split_block_insns): Moved to recog.c.
+ (update_flow_info): Make public.
+ * rtl.h: Declare them.
- * emit-rtl.c (operand_subword): Rework slightly to avoid
- bogus warning from previous change.
+ * reorg.c: Moved the functions dealing with computing resource
+ usage to resource.c.
-Tue Apr 14 23:39:13 1998 Richard Henderson <rth@cygnus.com>
+ * sched.c (regno_use_in): Moved to rtlanal.c.
+ (update_flow_info): Make public.
+ (schedule_insns): Use split_block_insns.
- * alpha.md: Revert Oct 27 change, as it is superceeded by Kenner's
- Nov 8 find_replacement change. Move decls of get_unaligned_address
- * alpha.h: ... here.
+ * recog.c (split_block_insns): New function.
-Tue Apr 14 22:00:39 1998 John Carr <jfc@mit.edu>
+Tue Feb 2 22:03:26 1999 David Edelsohn <edelsohn@gnu.org>
- * function.c (assign_parms): Initialize unsignedp before passing
- its pointer to promote_mode.
+ * rs6000/linux.h (LINK_START_DEFAULT_SPEC): Delete, unused.
+ (LINK_OS_DEFAULT_SPEC): Delete, unused.
- * genattrtab.c (check_attr_test): Handle MATCH_INSN like MATCH_OPERAND.
- (write_test_expr): Allow MATCH_INSN.
+Tue Feb 2 20:29:34 1999 Catherine Moore <clm@cygnus.com>
-Tue Apr 14 21:57:57 1998 Paul Eggert <eggert@twinsun.com>
+ * configure.in (arm-*-oabi): Support.
+ * configure: Regenerate.
+ * config/arm/unknown-elf-oabi.h: New file.
- * install.texi: Update section on warnings that can be safely ignored.
+Tue Feb 2 19:43:59 1999 Jeffrey A Law (law@cygnus.com)
-Tue Apr 14 14:55:16 1998 Jim Wilson <wilson@cygnus.com>
+ * i386.md (ashlsi3): Turn into a define_expand an anonymous pattern.
+ Make the anonymous pattern match when ! optimize_size.
+ (ashlsi3 size optimizer): New pattern.
- * mips.md (reload_outdi): Change the scratch mode from DImode to
- TImode. New variable scratch, used instead of operand[2] in template.
- Add code for MIPS16 HILO_REGNUM case where output reg is not M16_REG_P.
+ * intl/Makefile.in (uninstall): Add missing "; \".
-Tue Apr 14 16:19:03 1998 Michael Meissner <meissner@cygnus.com>
+Tue Feb 2 18:21:23 1999 Stan Cox <scox@cygnus.com>
- * expr.c (MOVE_RATIO): Set to 3 if optimizing for space.
+ * sparc.h (TARGET_CPU_sparc86x): Added. TARGET_CPU_sparclite86x
+ synonym.
-Tue Apr 14 11:31:28 1998 Krister Walfridsson <cato@df.lth.se>
+Tue Feb 2 20:24:11 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * i386/bsd386.h (ASM_OUTPUT_ALIGN): Redefine.
+ * loop.c (loop_optimize): Fix value max_uid_for_loop is reset
+ to after find_and_verify_loops call.
-Tue Apr 14 09:02:32 1998 Jeffrey A Law (law@cygnus.com)
+Tue Feb 2 19:48:29 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * svr4.h (ASM_DECLARE_OBJECT_NAME): Use HOST_WIDE_INT_PRINT_DEC.
- (ASM_FINISH_DECLARE_OBJECT): Likewise.
+ * (recombine_givs): Don't use a giv that's likely to be dead to
+ derive others.
- * Idea and part of the patch from HJ.
- * Makefile.in: auto-host.h renamed from auto-config.h. All references
- changed.
- (distclean): Remove auto-build.h too.
- * configure.in: Rename host autoconf generated file to auto-host.h.
- If host != build, then run autoconf to generate auto-build.h for
- the build machine and include it in build_xm_files.
- Check for wait.h and sys/wait.h.
+ * loop.c (recombine_givs): Fix test for lifetime overlaps / loop
+ wrap around when deriving givs.
- * combine.c (simplify_rtx, case TRUNCATE): Respect value of
- TRULY_NOOP_TRUNCATION.
+Mon Feb 1 20:00:40 1999 Richard Henderson <rth@cygnus.com>
-Mon Apr 13 11:31:49 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * recog.c (check_asm_operands): Treat indeterminate operand ok
+ results as success. Try harder to resolve a matching constraint.
+ * stmt.c (expand_asm_operands): Recognize when an output operand's
+ constraint does not allow memory. Treat indeterminate operand ok
+ results as failure. Try harder to resolve a matching constraint.
- * tree.h (BINFO_OFFSET_ZEROP): Use integer_zerop.
+Mon Feb 1 15:00:02 1999 Ken Raeburn <raeburn@cygnus.com>
-Sun Apr 12 20:55:32 1998 Catherine Moore <clm@cygnus.com>
+ Use varrays for constant-equivalence data:
- * invoke.texi (ld options) Include memset requirements
- for options -nodstdlib and -nodefaultlibs.
+ * varray.h (struct const_equiv_data): New type.
+ (union varray_data_tag): New element const_equiv.
+ (VARRAY_CONST_EQUIV_INIT, VARRAY_CONST_EQUIV): New macros.
+ (VARRAY_SIZE): New macro, returns number of elements.
+ * integrate.h: Include varray.h.
+ (struct inline_remap): Replace const_equiv_map, const_age_map and
+ const_equiv_map_size with a const_equiv_varray element.
+ (MAYBE_EXTEND_CONST_EQUIV_VARRAY): New macro; grows varray if
+ needed.
+ (SET_CONST_EQUIV_DATA): New macro; sets rtx and age fields
+ simultaneously, growing the varray if needed.
-1998-04-12 Paul Eggert <eggert@twinsun.com>
+ * integrate.c (global_const_equiv_map,
+ global_const_equiv_map_size): Deleted, replaced by....
+ (global_const_equiv_varray): New variable.
+ (expand_inline_function): References changed.
+ * integrate.h: Update declarations.
- This change is from an idea suggested by Arthur David Olson.
+ * integrate.c (process_reg_parm, expand_inline_function,
+ copy_rtx_and_substitute, try_constants, subst_constants,
+ mark_stores): Use varray allocation and accessor macros, new
+ integrate.h macros, and global_const_equiv_varray. Don't
+ conditionalize non-NULL stores on array size; instead, expand the
+ array as needed.
+ * unroll.c (unroll_loop): Likewise.
- * c-common.c (decl_attributes, record_function_format,
- check_format_info, init_function_format_info):
- Add support for strftime format checking.
- (enum format_type): New type.
- (record_function_format): Now static, and takes value of type
- enum format_type instead of int.
- (time_char_table): New constant.
- (struct function_format_info): format_type member renamed from is_scan.
- (check_format_info): Use `warning' rather than sprintf followed by
- `warning', to avoid mishandling `%' in warnings.
- Change `pedwarn' to `warning', since these warnings do not necessarily
- mean the program does not conform to the C Standard, as the code
- need not be executed.
+ * unroll.c (unroll_loop): Initialize const_equiv_varray element to
+ zero. After allocating varray, always exit through bottom of
+ function, where it can be deallocated if needed. Don't explicitly
+ reallocate const_equiv_map storage; instead, just ensure the
+ varray has been initialized, and update the global reference.
- * c-tree.h (record_function_format): Remove decl; no longer extern.
+Mon Feb 1 09:40:25 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * extend.texi: Add documentation for strftime format checking.
+ * system.h (inline, const): Handle these for stage2 (and later) gcc.
-Sun Apr 12 20:23:03 1998 Jeffrey A Law (law@cygnus.com)
+ * dwarf2out.c (inline): Don't define.
- * mips/ecoffl.h: Do not include mips.h.
- * mips/elf.h: Likewise.
+ * dwarfout.c (inline): Likewise.
- * configure.in (mips-*-ecoff): Do not mention mips/mips.h in tm_files.
- * mips/ecoff.h: Include "mips/mips.h".
+Sun Jan 31 22:04:37 1999 Richard Henderson <rth@cygnus.com>
-Sat Apr 11 22:42:54 PDT 1998 Jeff Law (law@cygnus.com)
+ * loop.c (recombine_givs): Dump recombination and derivation data.
- * version.c: Bump for snapshot.
+Sun Jan 31 20:34:29 1999 Zack Weinberg <zack@rabi.columbia.edu>
-Sat Apr 11 01:24:28 1998 Jeffrey A Law (law@cygnus.com)
+ * flags.h: Declare flag_no_ident.
+ * toplev.c: Define flag_no_ident. Process -f(no-)ident here.
+ * c-tree.h: Don't declare flag_no_ident.
+ * c-decl.c: Don't define flag_no_ident. Don't process
+ -f(no-)ident switches here.
- * cse.c (count_reg_usage): Correctly handle REG_NONNEG notes.
- (delete_trivially_dead_insns): Renamed from delete_dead_from_cse.
- * toplev.c (rest_of_compilation): Call delete_trivially_dead_insns instead of delete_dead_from_cse. Also call delete_trivially_dead_insns
- between loop optimization passes.
- * rtl.h: Updated appropriately.
+ * config/elfos.h (ASM_FILE_END): Output final .ident directive
+ only if !flag_no_ident.
+ * config/ptx4.h: Likewise.
+ * config/svr4.h: Likewise.
+ * config/alpha/elf.h: Likewise.
+ * config/arm/linux-elf.h: Likewise.
+ * config/i386/sco5.h: Likewise.
+ * config/i860/fx2800.h: Likewise.
+ * config/mips/gnu.h: Likewise.
+ * config/i386/osfrose.h: Likewise.
-Fri Apr 10 22:28:32 1998 Jeffrey A Law (law@cygnus.com)
+ * gcc.c (C specs): Map -Qn to -fno-ident.
+ * objc/lang-specs.h: Likewise.
- Reinstall this patch from Jason.
- * function.c (push_function_context_to): Don't call init_emit.
+Mon Feb 1 10:52:07 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Fri Apr 10 13:40:20 1998 Nick Clifton <nickc@cygnus.com>
+ * configure.in: Don't remove loop.o and unroll.o when
+ enable-haifa is selected.
+ * configure: Rebuilt.
- * rtl.c (read_skip_spaces): Prevent infinite loops upon
- encountering unterminated comments.
+Sun Jan 31 13:22:02 1999 John Wehle (john@feith.com)
-Fri Apr 10 10:43:41 1998 Jeffrey A Law (law@cygnus.com)
+ * i386.md (movsicc, movhicc, movsfcc, movdfcc,
+ movxfcc, movdicc): Delete unconstrained alternatives.
+ * i386.c (output_fp_conditional_move,
+ output_int_conditional_move): Delete unused case.
- * emit-rtl.c (operand_subword): Properly handle CONST_INTs for
- 64x32 cross builds.
+Sun Jan 31 01:15:04 1999 Jeff Law (law@cygnus.com)
- * configure.in: Handle --with-fast-fixincludes.
- (fixincludes): If --with-fast-fixincludes, then use a different
- fixincludes program by default.
- * Makefile.in (fixinc.sh): New rule.
+ * version.c: Bump for snapshot.
-Fri Apr 10 00:36:31 1998 H.J. Lu (hjl@gnu.org)
+Sun Jan 31 00:52:37 1999 Richard Henderson <rth@cygnus.com>
- * i386.md (movqi+1): Handle invalid QI register.
- (movsf_push-1): Likewise.
+ * alpha.md (mov patterns): Emit the assembler aliases mov and fmov
+ instead of bis and cpys. Combine alternatives where possible.
-Thu Apr 9 16:53:59 1998 Nick Clifton <nickc@cygnus.com>
+Sat Jan 30 23:14:13 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * config/m32r/m32r.c: call_address_operand(): Only accept symbolic
- addresses.
- symbolic_memort_operand(), call32_operand(), int8_operand(),
- int16_operand(), uint24_operand(), reg_or_int8_operand(): Removed.
- Not used.
- uint16_operand(): Made static.
+ * gcov.c (fnotice): Add missing FILE* parameter.
+ (function_summary): Fix format specifiers in calls to `fnotice'.
+ (output_data): Likewise.
-Thu Apr 9 01:43:04 1998 Jeffrey A Law (law@cygnus.com)
+ * toplev.c (fnotice): Constify char* parameter.
- * calls.c (expand_call): Fix typo.
+ * toplev.h (fnotice): Add prototype.
+ Wrap prototype with BUFSIZ to protect FILE* usage.
-Thu Apr 9 00:18:44 1998 Dave Brolley (brolley@cygnus.com)
+Sun Jan 31 15:33:09 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * c-lex.c (finput): New global.
- (init_parse): Always included. Handle !USE_CPPLIB using
- code originally in compile_file.
- (finish_parse): Update for CPPLIB.
- * toplev.c (init_parse, finish_parse): Declare.
- (finput): Delete variable. Now in front-ends.
- (compile_file): Remove code which is now handled by init_parse
- which is unconditionally called. Similarly for finish_parse.
+ * config/c4x/c4x.h (RTX_COSTS): Explicitly define c4x costs.
-Wed Apr 8 23:13:50 1998 Gavin Koch <gavin@cygnus.com>
+Sat Jan 30 08:27:23 1999 Jeffrey A Law (law@cygnus.com)
- * config/mips/r3900.h (ASM_OUTPUT_DEF,SUPPORTS_WEAK,
- ASM_WEAKEN_LABEL): Add.
+ * combine.c (distribute_notes): Handle REG_EH_REGION notes.
-Wed Apr 8 18:21:30 1998 Richard Henderson <rth@cygnus.com>
+ * alias.c (fixed_scalar_and_varying_struct_p): Add "static" to
+ function definition.
+ (aliases_everything_p, write_dependence_p):Likewise.
- * alpha/crtbegin.asm, alpha/crtend.asm, alpha/t-crtb: New files.
- * configure.in (alpha-*-linux*): Use them.
+ * install.texi: Fix merge lossages.
-Fri Apr 3 17:02:13 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
+ * cccp.c (main): Only call setlocale (LC_MESSAGES, ...) if LC_MESSAGES
+ is defined.
+ * collect2.c (main): Likewise.
+ * cppmain.c (main): Likewise.
+ * gcc.c (main): Likewise.
+ * gcov.c (main): Likewise.
+ * protoize.c (main): Likewise.
+ * toplev.c (main): Likewise.
- * tree.def (EXPR_WITH_FILE_LOCATION): New tree node definition.
- * tree.h (EXPR_WFL_{NODE,FILENAME,FILENAME_NODE,LINENO,
- COLNO,LINECOL,SET_LINECOL,EMIT_LINE_NOTE}): New macros.
- (build_expr_wfl): New prototype declaration.
- * tree.c (build_expr_wfl): New function, to build
- EXPR_WITH_FILE_LOCATION nodes.
- (copy_node): Don't zero TREE_CHAIN if copying a
- EXPR_WITH_FILE_LOCATION node.
- * print-tree.c (print_node): Handle EXPR_WITH_FILE_LOCATION.
- * expr.c (expand_expr): Handle EXPR_WITH_FILE_LOCATION.
+ * pa.md (parallel shift and shiftadd): Mark output of shift as an
+ earlyclobber.
-Wed Apr 8 12:51:19 1998 Jeffrey A Law (law@cygnus.com)
+ * loop.c: Disable recent loop changes. Temporary as Joern
+ continues to fix problems.
- * configure.in (v850): Use t-v850.
- (ix86-wrs-vxworks): Recognize 786 just like other x86 configurations.
+Sat Jan 30 03:24:37 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * protoize.c (creat, read, write): Do not declare.
+ * loop.c (strength_reduce): Size reg_map according to reg_iv_type.
- * jump.c (mark_jump_label): Record REG_LABEL notes for insns which
- refer to the CODE_LABEL before a dispatch table.
+Fri Jan 29 18:26:07 1999 Dave Brolley <brolley@cygnus.com>
- * invoke.texi: Add ARC options.
+ * emit-rtl.c (remove_insn): New function.
+ * rtl.h (remove_insn): Add prototype.
+ * function.c (reposition_prologue_and_epilogue_notes): Call remove_insn.
- * gcc.c (proces_command): Improve error message for -o with
- either -c or -S.
+Fri Jan 29 22:34:41 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * i386/x-cygwin32 (CLIB): Link in advapi32.
+ * loop.c (recombine_givs): Don't try to derive givs that have combined.
- * alpha.h (ASM_IDENTIFY_GCC): Define to nothing.
- (ASM_IDENTIFY_LANGUAGE): Likewise.
+Fri Jan 29 15:00:39 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * i386.md (movqi recognizer): Don't perfom byte increment into
- a NON_QI_REG_P.
+ * toplev.c (notice, fnotice): Check ANSI_PROTOTYPES, not __STDC__,
+ when declaring arguments and calling va_arg() to initialize them.
- * configure.in (x86-dg-dgux): Run fixinc.dgux.
+ * collect2.c (notice): Likewise.
- * i370.h: Fix typo in GEN_INT changes.
+ * loop.c (find_life_end): Use PROTO() macro in the prototype.
- * bitmap.c (bitmap_element_allocate): Use "void" for arglist instead
- of an empty arglist in prototype.
+Fri Jan 29 14:36:11 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * Makefile.in: Remove bytecode crud that crept back in after the
- gcc2 merge.
+ * collect2.c (error): Fix typo in declaration.
-1998-04-08 Brendan Kehoe <brendan@cygnus.com>
+ * cpperror.c (cpp_message): Likewise.
- * c-lex.h (is_class_name): Fix arg type to be tree, not void.
- (make_pointer_declarator, reinit_parse_for_function): Fix typo.
+ * cpplib.c (cpp_warning): Likewise.
-Wed Apr 8 06:16:45 1998 Richard Earnshaw (rearnsha@arm.com)
+ * cpplib.h (cpp_notice): Use PVPROTO not VPROTO, also add
+ ATTRIBUTE_PRINTF_1.
- * arm.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
+ * toplev.c (error): Fix typo in declaration.
-Wed Apr 8 00:44:18 1998 Bernd Schmidt (crux@pool.informatik.rwth-aachen.de>
+Fri Jan 29 15:44:13 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * c-lex.c (is_class_name): Delete declaration.
- (whitespace_cr): Make static and add prototype.
- * c-lex.h (make_pointer_declarator, reinit_parse_for_function,
- yylex, get_directive_line): Turn declarations into prototypes.
- (position_after_whitespace, check_newline, yyerror,, is_class_name,
- forget_protocol_qualifiers, remember_protocol_qualifiers): Add
- prototypes.
- * genattr.c (extend_range, write_upcase, gen_attr, write_units): Add
- prototypes.
- * gencodes.c (gen_insn): Add prototype.
- * genconfig.c (walk_insn, gen_insn, gen_expand, gen_split,
- gen_peephole): Add prototypes.
- * genflags.c (num_operands, gen_proto, gen_nonproto, gen_insn): Add
- prototypes.
- * gengenrtl.c (type_from_format, accessor_from_format, special_rtx,
- special_format, find_formats, gendecl, genmacro, gendef, genlegend,
- genheader, gencode): Add prototypes.
- * genopinit.c (gen_insn): Add prototype.
- * genoutput.c (output_prologue, output_epilogue, scan_operands,
- process_template, validate_insn_alternatives, gen_insn, gen_peephole,
- gen_expand, gen_split, n_occurrences): Add prototypes.
- * genpeep.c (gen_peephole): Add prototype.
- * loop.c (find_and_verify_loops, mark_loop_jump, prescan_loop,
- reg_in_basic_block_p, consec_sets_invariant_p, libcall_other_reg,
- labels_in_range_p, count_loop_regs_set, note_addr_stored,
- loop_reg_used_before_p, scan_loop, replace_call_address,
- skip_consec_insns, libcall_benefit, ignore_some_movables,
- force_movables, combine_movables, rtx_equal_for_loop_p, move_movables,
- strength_reduce, valid_initial_value_p, find_mem_givs, record_biv,
- check_final_value, record_giv, update_giv_derive, basic_induction_var,
- simplify_giv_expr, general_induction_var, consec_sets_giv,
- check_dbra_loop, express_from, combine_givs_p, combine_givs,
- product_cheap_p, maybe_eliminate_biv, maybe_eliminate_biv_1,
- last_use_this_basic_block, record_initial, update_reg_last_use,
- iteration_info, analyze_loop_iterations, insert_bct,
- instrument_loop_bct, indirect_jump_in_function_p): Turn declarations
- into prototypes.
+ * loop.c (strength_reduce): Fix HAVE_cc0 handling when scanning
+ forward from cont dominator.
-Tue Apr 7 21:48:52 1998 Jeffrey A Law (law@cygnus.com)
+Fri Jan 29 07:10:27 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * pa.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
+ * cccp.c (eprint_string): Constify a char*.
+ (notice): Likewise. Use PVPROTO not VPROTO, add ATTRIBUTE_PRINTF_1.
+ (vnotice): Constify a char*.
+ (error): Likewise. Use PVPROTO not VPROTO, add ATTRIBUTE_PRINTF_1.
+ (verror): Constify a char*.
+ (warning): Likewise. Use PVPROTO not VPROTO, add ATTRIBUTE_PRINTF_1.
+ (vwarning): Constify a char*.
+ (error_with_line): Likewise. Use PVPROTO not VPROTO, add
+ ATTRIBUTE_PRINTF_2.
+ (verror_with_line): Constify a char*.
+ (vwarning_with_line): Likewise.
+ (warning_with_line): Likewise. Use PVPROTO not VPROTO, add
+ ATTRIBUTE_PRINTF_2.
+ (pedwarn): Constify a char*. Use PVPROTO not VPROTO, add
+ ATTRIBUTE_PRINTF_1.
+ (pedwarn_with_line): Likewise with ATTRIBUTE_PRINTF_2.
+ (pedwarn_with_file_and_line): Likewise with ATTRIBUTE_PRINTF_4.
+ Also correct typo in parameter name declaration.
+ (make_assertion): Constify a char*.
+ (quote_string_for_make): Likewise.
+ (deps_output): Likewise.
+ (fatal): Likewise. Use PVPROTO not VPROTO, add
+ ATTRIBUTE_PRINTF_1. Use ATTRIBUTE_NORETURN not an explicit
+ "__attribute__ ((noreturn))".
+ (fancy_abort): Likewise for ATTRIBUTE_NORETURN.
+ (pfatal_with_name): Likewise.
+ (pipe_closed): Likewise.
+ (memory_full): Likewise.
-1998-04-07 Ken Raeburn <raeburn@cygnus.com>
+Fri Jan 29 00:14:55 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * config/mips/mips.c (siginfo): Deleted.
- (override_options): Don't install SIGINFO signal handler.
+ * loop.c (strength_reduce): Grow set_in_loop / n_times_set /
+ may_not_optimize to proper size when converting biv increments
+ into givs.
+ If necessary, reallocate reg_iv_type / reg_iv_info before calling
+ recombine_givs.
-Tue Apr 7 11:58:04 1998 Jim Wilson <wilson@cygnus.com>
+Thu Jan 28 23:24:08 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * loop.c (check_dbra_loop): When normalize comparison_val, add check
- to verify it is non-negative.
+ * loop.c (recombine_givs): New parameter unroll_p. If set, don't
+ generate complex adds. Changed caller.
+ Don't generate adds that cost more than the original one.
+ (strength_reduce): Warning fixes.
-Tue Apr 7 02:01:47 1998 Richard Henderson <rth@cygnus.com>
+Thu Jan 28 09:41:11 1999 Jeffrey A Law (law@cygnus.com)
- * alpha.c (alpha_expand_block_move): Correctly collect block offsets.
- (alpha_expand_block_clear): Likewise.
+ * configure.in (hppa1.0-hp-hpux10*): Use t-pa.
+ * configure: Rebuilt.
-Mon Apr 6 23:36:01 1998 Richard Henderson <rth@cygnus.com>
+Wed Jan 27 23:39:53 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * rtl.h (insn_first_p, no_jumps_between_p): Declare.
+ * rtlanal.c (insn_first_p, no_jumps_between_p): New function.
+ * loop.h (varray.h): Include.
+ (struct induction): Change combined_with to unsigned.
+ New members derived, ix and last_use.
+ (reg_iv_type, reg_iv_info): Now varray_type. All references changed.
+ (REG_IV_TYPE, REG_IV_INFO): Define.
+ (first_increment_giv, last_increment_giv): Declare.
+ * loop.c (loop_number_loop_cont): New static variable.
+ (loop_number_cont_dominator): Likewise.
+ (reg_iv_type, reg_iv_info): Now varray_type.
+ (first_increment_giv, last_increment_giv): New variables.
+ (compute_luids, verify_dominator, find_life_end): New functions.
+ (cmp_recombine_givs_stats, recombine_givs): Likewise.
+ (loop_optimize): Allocate loop_number_loop_cont and
+ loop_number_cont_dominator. Use compute_luids.
+ (find_and_verify_loops): Initialize loop_number_loop_cont and
+ loop_number_cont_dominator.
+ (strength_reduce): Try to find bivs that can be expressed as givs
+ of another biv, and to convert biv increments into givs.
+ Call recombine_givs. Handle derived givs.
+ (record_biv): New argument location. All callers changed.
+ (record_giv): Initialize derived and last_use fields.
+ (basic_induction_var): New argument location. All callers changed.
+ (combine_givs): Don't combine a DEST_REG giv with a DEST_ADDR giv.
+ Increment combined_with instead of setting to 1.
+ * unroll.c (derived_regs): New static variable.
+ (unroll_loop): Initialize it.
+ Allocate local_regno according to max_reg_num.
+ (copy_loop_body): Cope with derived givs.
+ (find_splittable_givs): Check for Givs made from biv increments.
+ Set derived_regs for givs.
+ * Makefile.in (stmt.o, loop.o, unroll.o): Depend on loop.h .
+
+Wed Jan 27 19:31:36 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * function.c (purge_addressof_1): Handle case when a register
+ has been used in a wider mode.
+
+1999-01-27 Bruce Korb <autogen@linuxbox.com>
+
+ * fixinc/fixincl.c, fixinc/server.[ch]:
+ Removed the last of the capitalized variable and proc names.
+
+ * fixinc/server.c: Removed the process open code.
+ * fixinc/procopen.c: New file containing the proc open code.
+ * fixinc/inclhack.tpl: Added code to bypass a readability test
+ when a file is not present. A problem on some systems.
+ * fixinc/inclhack.sh, fixinc/fixincl.sh: Regenerated.
+
+Wed Jan 27 11:58:18 1999 Dave Brolley <brolley@cygnus.com>
+
+ * cpplib.h (cpp_notice): Add prototype.
+
+Wed Jan 27 02:20:48 1999 Jeffrey A Law (law@cygnus.com)
+
+ * Merge gcc2 snapshot 19980929.
+
+ * cccp.c (PRINTF_PROTO): Remove.
+ (PRINTF_PROTO_{1,2,3,4}: Likewise.
+ * cexp.y: Likewise.
+ * system.h: Add PRINTF_PROTO and PRINTF_PROTO_{1,2,3,4}.
+
+ * fix-header.c (cpp_file_lin_for_message): Delete. In libcpp.
+ (cpp_print_containing_files, v_cpp_message, cpp_message): Likewise.
+ (cpp_fatal, cpp-Pfatal_with_name): Likewise.
+
+ * gen-protos.c (hashf): Delete in cpphash.o.
+ * gen-protos.c (hashf): Delete in cpphash.o.
+
+ * expr.c: Do not merge SAVE_STACKAREA_MODE changes.
+ * expmed.c: Likewise.
+ * rs6000.md: Likewise.
+
+ * rs6000.c, rs6000.md: Do not merge formatting changes yet.
+
+Wed Jan 27 01:13:42 1999 Richard Henderson <rth@cygnus.com>
+
+ * rs6000.c (input_operand): Don't expect CONST around CONSTANT_P_RTX.
+ * rs6000.md (movsi, movdi): Likewise.
+
+Tue Jan 26 13:31:38 1999 Jim Wilson <wilson@cygnus.com>
+
+ * function.c (expand_function_end): Pass arg_pointer_save_area to
+ validize_mem before using it. Emit code into a sequence.
+
+Tue Jan 26 13:41:38 1999 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.md (doz + set cr and or + set cr patterns): Add missing
+ '#' to split patterns. Correct indentation of some new patterns.
+
+1999-01-26 Zack Weinberg <zack@midnite.ec.rhno.columbia.edu>
+
+ * cppfiles.c (safe_read): Deleted.
+ (read_and_prescan): New function, replaces safe_read, converts
+ and/or warns about trigraphs, silently converts odd line
+ terminators (\r, \n\r, \r\n). Warns about no newline at EOF.
+ (finclude): Use read_and_prescan; turn off nonblocking mode on
+ the input descriptor; remove file-size-examination and
+ no-newline-at-EOF gunk which is longer necessary; be more
+ careful about checking that we've been handed a legitimate
+ file to read (only real files, pipes, and ttys are acceptable).
+ * cpplib.h (cpp_options): Rename no_trigraphs flag to
+ `trigraphs' and invert its sense.
+ (trigraph_table): Declare.
+ (cpp_warning_with_line): Prototype.
+ * cpplib.c: Remove all references to trigraph_pcp. Define
+ trigraph_table; initialize it in initialize_char_syntax. Open
+ files in nonblocking mode. s/no_trigraphs/trigraphs/
+ throughout, and invert sense. Put cpp_warning_with_line back
+ in and export it.
+
+Tue Jan 26 23:21:49 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.h (COUNTER_REGS): New register class.
+ * config/c4x/c4x.md (*rptb_init): Change constraints.
+ (rptb_end): Emit alternate looping instructions if
+ RC register not allocated for loop counter.
+ (decrement_and_branch_on_count): Allow other registers
+ for loop counter.
+
+1999-01-25 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * cppexp.c (struct arglist): Removed.
+ (parse_number): Use HOST_WIDE_INT for the accumulator.
+ Allow two `l' suffixes unless C89. Clean up. Make static.
+ (parse_charconst): New function broken out of cpp_lex.
+ Code cleaned up drastically. Don't use a token_buffer.
+ (token_buffer): Removed.
+ (cpp_lex): Don't call parse_number on a constant string.
+ Use parse_charconst.
+ (cpp_parse_expr): Properly handle an ERROR op returned by
+ cpp_lex.
+
+1999-01-25 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cpplib.c: Don't include signal.h, sys/times.h, or
+ sys/resource.h. Don't declare localtime.
+ (macroexpand): Handle special symbols here.
+ (push_macro_expansion): Chop off the trailing '@ ' if possible
+ here.
+ (cpp_get_token): Don't do either of the above two things here.
+ Move `string' label just after case '"' so that wide strings
+ don't crash the preprocessor.
+
+Sun Jan 24 20:13:45 1999 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.md (left shift + set cr patterns): Add missing '#' to
+ split patterns.
+ (move register + set cr pattern): Likewise.
+ (movdi, !TARGET_POWERPC64 splitters): Add back in Jan. 15th patch,
+ inadvertently deleted.
+
+Sun Jan 24 08:07:59 1999 Jeffrey A Law (law@cygnus.com)
+
+ * stmt.c (stmt_loop_nest_empty): New function.
+ * tree.h (stmt_loop_nest_empty): Declare it.
+ * rtl.def (CALL_PLACEHOLDER): New rtx code.
+
+Sun Jan 24 21:24:43 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.c (c4x_emit_move_sequence, c4x_encode_section_info):
+ New functions.
+ (c4x_check_legit_addr): Remove USE and PLUS, allow
+ LO_SUM, and disable SYMBOL_REF, LABEL_REF, and CONST cases.
+ (c4x_legitimize_address): Penalize SYMBOL_REF, LABEL_REF, and
+ CONST cases. Add LO_SUM.
+ (c4x_print_operand): Modified 'C' and 'R' cases for calls.
+ Added 'U' case. Remove dependence on SYMBOL_REF_FLAG.
+ (c4x_print_operand_address): Handle LO_SUM.
+ (c4x_scan_for_ldp): Delete. Hooray!
+ (c4x_process_after_reload): Remove call to c4x_scan_for_ldp.
+ Split all insns.
+ (c4x_immed_int_constant): Renamed from c4x_int_constant. All callers
+ changed.
+ (c4x_immed_float_constant): Renamed from c4x_float_constant. All
+ callers changed.
+ (c4x_T_constraint): Allow LO_SUM, disable SYMBOL_REF, LABEL_REF,
+ and CONST.
+ (c4x_U_constraint, symbolic_operand): New functions.
+ (src_operand): Allow 'I' constants in HImode. Allow LO_SUM,
+ disable SYMBOL_REF, LABEL_REF, and CONST.
+ (lsrc_operand, tsrc_operand): Call src_operand instead of
+ general_operand.
+ (c4x_operand_subword): Update comments.
+
+ * config/c4x/c4x.c (TARGET_LOAD_ADDRESS): New macro.
+ (LEGITIMATE_CONSTANT_P): Allow SYMBOL_REF, LABEL_REF, CONST,
+ plus HIGH and LO_SUM for the C40.
+ (ENCODE_SECTION_INFO): Define macro.
+ (symbolic_operand, c4x_U_constraint, c4x_emit_move_sequence): New
+ prototypes.
+ (PREDICATE_CODES): Add symbolic_operand.
- * tree.h (sizetype_tab): Fix previous change for K&R.
+ * config/c4x/c4x.md (movqi, movgqf, movhi, movhi): Call
+ c4x_emit_move_sequence.
+ (floatunsqiqf2, fixuns_truncqfqi2): Rework emitted RTL
+ to avoid symbol references.
+ (all patterns with g constraint): Replace 'g' constraint with 'rIm'.
+ (set_high): Renamed from set_high_use.
+ (set_lo_sum): Renamed from set_ior_lo_use.
+ (all call patterns): Make MEM explicit in call address operands.
+ Modified output templates to use 'U' modifier.
-Mon Apr 6 22:23:29 PDT 1998 Jeff Law (law@cygnus.com)
+Sun Jan 24 01:15:05 1999 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Mon Apr 6 23:16:10 1998 Richard Earnshaw (rearnsha@arm.com)
+Sat Jan 23 22:34:57 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * configure.in (sparc-*-solaris2*): Add xm-siglist.h to xm_file.
- Add USG and POSIX to xm_defines.
+ * final.c (bb_str): Qualify a char* with the keyword `const'.
+ (add_bb_string, final_scan_insn, output_asm_insn): Likewise.
-Mon Apr 6 21:49:57 1998 Bob Manson <manson@charmed.cygnus.com>
+ * fix-header.c (read_scan_file): Likewise.
- * gcc.c: Add linker spec.
- (link_command_spec): Use %(linker) instead of ld.
- (main): If collect2 is requested as the linker, see if it exists;
- if not, use ld instead.
+ * genoutput.c (output_epilogue, process_template): Likewise.
- * Makefile.in (USE_COLLECT2): It's named collect2 now, not ld.
- (ld:) Deleted.
- (install-collect2): Install as collect2, not ld.
+ * local-alloc.c (requires_inout, block_alloc): Likewise.
- * configure.in(will_use_collect2): It's named collect2 now.
+ * output.h (output_asm_insn, assemble_string): Likewise.
- * collect2: Remove checks to see if we were invoked recursively.
- (collect_execute): Use _spawnvp under cygwin32.
+ * recog.c (recog_constraints, check_asm_operands,
+ decode_asm_operands, extract_insn, preprocess_constraints,
+ constrain_operands): Likewise.
-Mon Apr 6 17:23:41 1998 Jim Wilson <wilson@cygnus.com>
+ * recog.h (operand_alternative, recog_constraints, insn_template,
+ insn_outfun, insn_operand_constraint, insn_name): Likewise.
- * haifa-sched.c (build_control_flow): Set unreachable for block whose
- only predecessor is itself.
+ * regclass.c (record_reg_classes, scan_one_insn): Likewise.
-Mon Apr 6 16:08:04 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * regmove.c (find_matches): Likewise.
- * c-parse.in: Include system.h, and remove stuff now made redundant.
- * cccp.c: Likewise.
- * cexp.y: Likewise.
- * protoize.c: Likewise. Properly check for cpp stringification.
+ * reload.c (alternative_allows_memconst): Likewise.
- * Makefile.in (c-parse.o, cccp.o, cexp.o, protoize.o, unprotoize.o):
- Depend on system.h.
+ * reload1.c (constraint_accepts_reg_p,
+ reload_cse_simplify_operands): Likewise.
- * objc/Make-lang.in (objc-parse.o): Likewise.
+ * rtl.h (decode_asm_operands): Likewise.
-Mon Apr 6 14:59:58 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * scan.h (fn_decl): Likewise.
- * gansidecl.h: Check if compiler supports __attribute__. Provide
- definitions for ATTRIBUTE_UNUSED and ATTRIBUTE_PRINTF using
- __attribute__ when its available. Also provide definitions for
- ATTRIBUTE_PRINTF_1, ATTRIBUTE_PRINTF_2 and ATTRIBUTE_PRINTF_3 in
- terms of ATTRIBUTE_PRINTF.
+ * varasm.c (assemble_string): Likewise.
- * genoutput.c (process_template): Use ATTRIBUTE_UNUSED in place
- of __attribute__.
+Sat Jan 23 01:37:36 1999 Jeffrey A Law (law@cygnus.com)
-Mon Apr 6 07:17:52 1998 Catherine Moore <clm@cygnus.com>
+ * configure.in (gcc_tooldir): Handle case where exec_prefix has
+ not been explicitly set.
+ * configure: Rebuilt.
- * combine.c (can_combine_p): Include successor in volatile test.
+ * fold-const.c (lshift_double): Mark 'prec' arguments as possibly
+ unused.
-Mon Apr 6 14:16:33 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * bitmap.h (bitmap_head_def): Make indx field unsigned.
- * sh.h (CASE_VECTOR_SHORTEN_MODE): Fix logic when to set
- offset_unsigned.
+ * configure.in (gcc_tooldir): When not making a relative gcc_tooldir,
+ use $exec_prefix/$target_alias for gcc_tooldir.
+ * configure: Rebuilt.
-Mon Apr 6 02:03:29 1998 Jeffrey A Law (law@cygnus.com)
+Fri Jan 22 11:48:56 1999 Richard Henderson <rth@cygnus.com>
- * objc/objc-act.c (encode_aggregate_within): Avoid GNU extensions
- in prototype and definition.
+ * cppp.c (xrealloc): Fix typo last change.
+ * cppalloc.c, gcc.c, genattr.c, genattrtab.c, gencodes.c: Likewise.
+ * genconfig.c, genemit.c, genextract.c, genflags.c: Likewise.
+ * genopinit.c, genoutput.c, genpeep.c, genrecog.c: Likewise.
-Mon Apr 6 00:48:56 PDT 1998 Jeff Law (law@cygnus.com)
+1999-01-22 Michael Meissner <meissner@cygnus.com>
- * version.c: Bump for snapshot.
+ * rs6000.h (CR0_REGNO_P): New macro to test if cr0.
+ (CR_REGNO_NOT_CR0_P): New macro to test if cr, but not cr0.
+ (PREDICATE_CODES): Add cc_reg_not_cr0_operand.
+ (cc_reg_not_cr0_operand): Add declaration.
-Mon Apr 6 00:08:50 1998 Richard Henderson <rth@cygnus.com>
+ * rs6000.c (cc_reg_not_cr0_operand): Return true if register is a
+ pseudo register, or a control register that is not CR0.
- * alpha.c (alpha_expand_block_clear): Add missing offset arg to
- alpha_expand_unaligned_store_words.
+ * rs6000.md (all combiner patterns building . instructions): For
+ all `.' instructions that do something and set cr0, add an
+ alternative that does the operation, and then sets a different
+ flag, in order to avoid using the costly mcrf instruction and also
+ allow cr0 to be clobbered in asm statements. Also fix a few
+ patterns that used the wrong register.
-Sun Apr 5 21:31:24 1998 John Wehle (john@feith.com)
+ * rs6000.h (rs6000_cpu_select): Make string, names be const char *.
+ (rs6000_debug_name): Make const char *, not char *.
- * i386.md (movsf_push, movsf_mem): Remove.
- (movsf_push): Rename from movsf_push_nomove and move in front of
- movsf. Use nonmemory_operand predicate and don't bother checking
- TARGET_MOVE.
- (movsf_push_memory): New pattern.
- (movsf): Don't bother checking for push_operand. If TARGET_MOVE and
- both operands refer to memory then force operand[1] into a register.
- (movsf_normal): Change to unnamed pattern.
- Likewise for movdf, movxf, and friends.
+ * sysv4.h (rs6000_{abi,sdata}_name): Make const char *.
-Sun Apr 5 18:45:51 PDT 1998 Jeff Law (law@cygnus.com)
+ * rs6000.c (rs6000_{debug,abi,sdata}_name): Make const char *.
+ (rs6000_select): Use const char * in casts.
- * version.c: Bump for snapshot.
+Fri Jan 22 07:43:01 1999 Jeffrey A Law (law@cygnus.com)
-Sun Apr 5 16:31:10 1998 Richard Henderson <rth@cygnus.com>
+ * Makefile.in (gcc_tooldir): Move before first reference.
+ Let autoconf substitute in a value.
+ * configure.in (gcc_tooldir): Only use a relative path to the
+ tool directory if $exec_prefix == $prefix.
+ * configure: Rebuilt.
- * configure.in (alpha-dec-osf*): Match osf1.3 correctly.
+ * Makefile.in (tooldir): Replace with gcc_tooldir.
-Sun Apr 5 16:53:37 1998 Don Bowman <don@pixsci.com>
+Thu Jan 21 23:21:57 1999 Jeffrey A Law (law@cygnus.com)
- * configure.in (mips-wrs-vxworks): New target.
+ * m68k.md (ashldi_const): Disable for !TARGET_5200. Fix indentation.
+ (ashldi3 expander): Similarly. Update comments.
+ (ashrdi_const, lshrdi_const): Fix indentation.
+ (ashrdi3, lshrdi3): Fix indentation. Update comments.
-Sat Apr 4 23:34:32 PST 1998 Jeff Law (law@cygnus.com)
+Thu Jan 21 21:53:36 1999 Richard Henderson <rth@cygnus.com>
- * expmed.c (synth_mult): The value -1, has no zeros, so it can
- never have the form ...011.
+ * emit-rtl.c (try_split): Don't try to split non-instructions.
- * version.c: Bump for snapshot.
+Thu Jan 21 23:47:30 1999 Andrew MacLeod <amacleod@cygnus.com>
-Sat Apr 4 20:16:46 1998 Richard Henderson <rth@cygnus.com>
+ * expr.c (emit_push_insn): Fix dumb typo.
- * i386.c (asm_output_function_prefix, load_pic_register):
- Use ASM_GENERATE_INTERNAL_LABEL properly.
- (output_pic_addr_const): Recognize %X to supress any PIC sym suffix.
- (print_operand): Ignore it.
- (load_pic_register): Use it for the got load call.
- * i386.md (prologue_set_got, prologue_get_pc): Likewise.
- (prologue_get_pc_and_set_got): Likewise.
- * i386.h: Update print_operand docs.
+Thu Jan 21 20:24:02 1999 Richard Henderson <rth@cygnus.com>
-Sat Apr 4 19:08:37 1998 Richard Henderson <rth@cygnus.com>
+ * rs6000.h (LEGITIMIZE_RELOAD_ADDRESS): Recognize and accept
+ transformations that we have performed earlier.
+ * alpha.h (LEGITIMIZE_RELOAD_ADDRESS): Likewise.
- * i386.md (ffssi, ffshi): Rewrite as define_expands.
- (ffssi_1, ffshi_1): New (unspec [] 5) support patterns.
- * i386.c (notice_update_cc): Recognize unspec 5.
+ * alpha.md (prologue_stack_probe_loop): Don't do our own label
+ handling, call gen_label_rtx instead.
-Sat Apr 4 18:07:16 1998 David Mosberger-Tang (davidm@mostang.com)
+Thu Jan 21 17:45:18 1999 Richard Henderson <rth@cygnus.com>
- * alpha.h (PRINT_OPERAND_PUNCT_VALID_P): Accept '(' for s/sv/svi.
- * alpha.c (print_operand): Handle it.
- * alpha.md (fix_truncsfdi2): Use it. Add earlyclobber pattern
- for ALPHA_TP_INSN.
- (fix_truncdfdi2): Likewise.
+ * configure.in ({rs6000|powerpc}-ibm-aix4.[12]*): Add missing `then'.
-Sat Apr 4 17:42:05 1998 Richard Henderson <rth@cygnus.com>
+ * cccp.c (xrealloc): Call malloc given a NULL old pointer.
+ * collect2.c, cppalloc.c, gcc.c, genattr.c, genattrtab.c: Likewise.
+ * gencodes.c, genconfig.c, genemit.c, genextract.c: Likewise.
+ * genflags.c, genopinit.c, genoutput.c, genpeep.c: Likewise.
+ * genrecog.c, mips-tfile.c, protoize.c: Likewise.
- * tree.h (sizetype_tab[2], sbitsizetype, ubitsizetype): Merge all
- of these into a single struct, with additional [us]sizetype entries.
- * stor-layout.c (set_sizetype): Initialize [us]sizetype.
- * fold-const.c (size_int_wide): Don't rely on sizetype_tab being
- an array.
+Thu Jan 21 19:44:55 1999 Michael Meissner <meissner@cygnus.com>
-Sat Apr 4 17:04:41 1998 Richard Henderson <rth@cygnus.com>
+ * configure.in ({rs6000|powerpc}-ibm-aix4.[12]*): If
+ --with-gnu-ld, use x-aix41-gld instead of x-aix41 to suppress
+ adding -Wl,-bbigtoc to BOOT_LDFLAGS.
+ * configure: Regenerate.
- * configure.in (alpha-*-linux-*): Undo tm_file changes from gcc2 merge.
+ * config/rs6000/x-aix41-gld: New file, don't set BOOT_LDFLAGS.
-Sat Apr 4 13:50:01 1998 Richard Henderson <rth@cygnus.com>
+Thu Jan 21 15:48:03 1999 Dave Brolley <brolley@cygnus.com>
- * haifa-sched.c (split_block_insns): Don't supress insn splitting
- on subsequent passes.
+ * cppexp.c (cpp_lex): Allocate token_buffer dynamically.
- * alpha.c (hard_fp_register_operand): New function.
- * alpha.h (PREDICATE_CODES): Add it.
- * alpha.md (extendsidi2): Kill bogus f<-f cvtql+cvtlq case. Add an
- f<-m case and accompanying define_split.
- (trapb): Use a unique unspec_volatile number.
+Thu Jan 21 14:18:04 1999 Andrew MacLeod <amacleod@cygnus.com>
-Sat Apr 4 13:32:08 1998 Richard Henderson <rth@cygnus.com>
+ * expr.c (MOVE_BY_PIECES_P): Define condition for deciding to use
+ move_by_pieces.
+ (MOVE_MAX_PIECES): Define maximum number of bytes to move at once.
+ (USE_LOAD_POST_INCREMENT, USE_LOAD_PRE_DECREMENT): Define defaults.
+ (USE_STORE_POST_INCREMENT, USE_STORE_PRE_DECREMENT): Define defaults.
+ (move_by_pieces): Use new macros.
+ (emit_block_move): Use new macros.
+ (clear_by_pieces): Use new macros.
+ (clear_storage): Use new macros.
+ (emit_push_insn): Use new macros.
+ (expand_expr): Use new macros.
+ * config/sh/sh.h (USE_LOAD_POST_INCREMENT, USE_LOAD_PRE_DECREMENT):
+ Define.
+ (USE_STORE_POST_INCREMENT, USE_STORE_PRE_DECREMENT): Define.
+ (MOVE_BY_PIECES_P): Define based on alignment and TARGET_SMALLCODE.
+ (MOVE_MAX_PIECES): Move 8 bytes on SH4.
+ * tm.texi(MOVE_BY_PIECES_P, MOVE_MAX_PIECES, USE_LOAD_POST_INCREMENT,
+ USE_LOAD_PRE_DECREMENT, USE_STORE_POST_INCREMENT,
+ USE_STORE_PRE_DECREMENT): Describe new macros.
- * configure.in (alpha-*-linux-gnu*): Undo Feb 3 change brought in
- from gcc2 merge.
+Thu Jan 21 14:13:31 1999 Vladimir N. Makarov <vmakarov@cygnus.com>
-Sat Apr 4 10:23:41 1998 Jeffrey A Law (law@cygnus.com)
+ * varasm.c (output_constant_pool): Use floor_log2 instead of
+ exact_log2 for ASM_OUTPUT_ALIGN.
- * Check in merge from gcc2. See ChangeLog.11 and ChangeLog.12
- for details.
+ * stor-layout.c (layout_type): Do machine-dependent extra alignment.
- * haifa-sched.c: Mirror recent changes from gcc2.
+ * emit-rtl.c (operand_subword): Handle case when a subword outside
+ the operand.
-Fri Apr 3 00:17:01 1998 Jeffrey A Law (law@cygnus.com)
+ * tm.texi (ROUND_TYPE_{SIZE,ALIGN}): More accurate descriptions of
+ the macros.
- * Makefile.in (insn*.o): Depend on system.h.
+Thu Jan 21 01:59:30 1999 Richard Henderson <rth@cygnus.com>
- * pa.c (output_global_address): Initialize base.
- * pa.h (GO_IF_LEGITIMATE_ADDRESS): Initialize index.
+ * cse.c (fold_rtx): Revert 29 Dec change.
+ (cse_insn): Revert 12 Jan change.
+ * expr.c (expand_builtin): Don't emit CONST around CONSTANT_P_RTX.
+ * regclass.c (reg_scan_mark_refs): Revert 29 Dec change.
+ * rtl.def: Likewise.
+ * rtl.h (CONSTANT_P): Likewise.
-1998-04-03 Mike Stump <mrs@wrs.com>
+ * expr.c (emit_move_insn): Never try to flush CONSTANT_P_RTX
+ to memory.
+ * recog.c (immediate_operand): Accept CONSTANT_P_RTX.
+ * alpha.c (input_operand): Likewise.
+ * c4x.c (const_operand): Likewise.
- * gthr.h: Support systems that don't have weak, but have threads.
- * configure.in (*wrs-vxworks*): Use VxWorks threads by default.
- * gthr-vxworks.h: New file.
- * objc/thr-vxworks.h: Dummy file from thr-single.c for now.
+ * explow.c (allocate_dynamic_stack_space): Use register_operand
+ instead of arith_operand, which does not exist.
-Thu Apr 2 18:00:52 1998 Jim Wilson <wilson@cygnus.com>
+ * 1750a.h: Fix comment closure.
+ * a29k.c (a29k_set_memflags): Fix typo in 19 Jan change.
+ * arc.md (one_cmplsi2_set_cc_insn): Fix set mode mismatch.
+ * arm.h (TARGET_SWITCHES): Fix typo.
+ * i370.md (anon mult and div patterns): Fix set mode mismatch.
+ * i860.c (output_delayed_branch): Fix operands to constrain_operands.
+ (output_delay_insn): Likewise.
+ * m88k.md (anon rotate insns): Fix set mode mismatch.
+ (anon BLKmode moves): Commonize and fix set mode mismatches.
+ * ns32k.md (udivmoddi[shq]i4_internal): Fix mode mismatch.
+ * romp.md (movdf): Fix typo.
- * i386.md (movqi+1): Change alternative 1 from *r/r to *r/*rn.
+Thu Jan 21 00:29:35 1999 Nathan Sidwell <nathan@acm.org>
-1998-04-02 Vladimir N. Makarov <vmakarov@cygnus.com>
+ * Makefile.in (install-common): Remove extraneous chmod for gcov
+ install.
- * ginclude/va-i960.h (va_end): Change void * to void.
+Wed Jan 20 18:15:08 1999 Dave Brolley <brolley@cygnus.com>
-Thu Apr 2 13:51:10 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * function.c (assign_parms): Save and restore setting of
+ TREE_USED (parm).
- * Makefile.in (choose-temp.o): Depend on system.h.
+Wed Jan 20 12:51:42 1999 Mark Mitchell <mark@markmitchell.com>
- * choose-temp.c: Include system.h when IN_GCC.
+ * arm.md: Use MEM_COPY_ATTRIBUTES where appropriate throughout.
+ Pass MEM_SCALAR_P to arm_gen_store_multiple where appropriate.
-Thu Apr 2 02:37:07 1998 Joern Rennecke (amylaar@cygnus.co.uk)
- Richard Henderson <rth@cygnus.com>
+Tue Jan 19 21:20:52 1999 Richard Henderson <rth@cygnus.com>
- * reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS.
- (move_replacements): New function.
- * reload.h: Prototype it.
+ * recog.c (pop_operand): New function.
+ * recog.h (pop_operand): Declare it.
+ * genrecog.c (preds): Define it.
- * alpha.h (LEGITIMIZE_RELOAD_ADDRESS): New definition.
+ * expr.c (do_jump_for_compare): Handle conditional branch expanders
+ emitting multiple jump instructions.
+ * jump.c (condjump_label): New function.
+ * rtl.h (condjump_label): Declare it.
-Thu Apr 2 01:01:34 1998 Richard Henderson <rth@cygnus.com>
+Tue Jan 19 21:08:20 1999 Richard Henderson <rth@cygnus.com>
- * configure (alpha-*-linuxecoff, alpha-*-linux-gnulibc1):
- Run fixincludes.
+ * expr.c (emit_move_insn_1): Revert 17 Dec change. Don't emit
+ clobber during or after reload.
- * emit-rtl.c (gen_lowpart_common): Skip count by HARD_REGNO_NREGS.
- (gen_highpart): Likewise.
- * final.c (alter_subreg): Allow the target to hook by-mode subreg
- hard register number changes.
+Tue Jan 19 16:56:03 1999 Richard Henderson <rth@cygnus.com>
-Wed Apr 1 22:26:22 1998 Jeffrey A Law (law@cygnus.com)
+ * genoutput.c (name_for_index): New function.
+ (scan_operands, validate_insn_alternatives): Use it.
+ * genrecog.c (insn_name_ptr_size): New variable.
+ (make_insn_sequence): Fill in insn_name_ptr.
+ (merge_trees): Use it.
- * fold-const.c optimze_bit_field_compare): Initialize rnbitpos,
- rnbitsize, rnmode and rinner.
- (make_range): Initialize type.
- (fold): Initialize arg0, arg1 and varop.
+Tue Jan 19 16:37:36 1999 Richard Henderson <rth@cygnus.com>
- * function.c (instantiate_virtual_regs_1): Initialize offset, regnoi
- and regnor.
- (expand_function_start): Initialize last_ptr.
+ * i386/isc.h (TARGET_DEFAULT): Define symbolicly.
+ * i386/isccoff.h, i386/next.h, i386/sco.h, i386/sco5.h: Likewise.
+ * i386/scodbx.h, i386/sequent.h, i386.unix.h: Likewise.
- * stor-layout.c (layout_record): Initialize desired_align.
- (get_best_mode): Initialize unit.
+Tue Jan 19 15:00:10 1999 Jeffrey A Law (law@cygnus.com)
- * tree.c (copy_node): Initialize length.
+ * loop.c (NUM_STORES): Delete.
+ (loop_store_mems): Turn into an EXPR_LIST of MEMs.
+ (prescan_loop): Properly initialize loop_mems_idx.
+ (note_addr_stored): Simplify using list structure instead of
+ fixed sized array.
+ (invariant_p, check_dbra_loop, load_mems): Similarly.
- * c-lex.c (yylex): Initialize traditional_type, ansi_type and type.
+ * flow.c (invalidate_from_autoinc): New function.
+ (mark_set_1, mark_used_regs): Use it.
- * caller-save.c (insert_save_restore): Initialize pat, code and
- numregs.
+ * Makefile.in (protoize.o, unprotoize.o): Depend on Makefile.
- * emit-rtl.c (push_to_sequence): Initialize top.
- (push_topmost_sequence): Likewise.
+1999-01-19 Vladimir N. Makarov <vmakarov@cygnus.com>
- * genattrtab.c (simplify_by_exploding): Initialize defval.
+ * invoke.texi (-mlong-double-64): New option description.
- * profile.c (branch_prob): Initialize dest.
+1999-01-19 Jim Wilson <wilson@cygnus.com>
- * rtl.h (note_stores): Remove duplicate prototype.
- (GEN_INT): Re-instate cast of second arg to HOST_WIDE_INT.
+ * libgcc2.c: Change all uses of LONG_DOUBLE_TYPE_SIZE to
+ LIBGCC2_LONG_DOUBLE_TYPE_SIZE.
+ (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): New. Set to LONG_DOUBLE_TYPE_SIZE
+ if not defined.
+ * i960/i960.h (MULTILIB_DEFAULTS): Define to mnumerics.
+ (CPP_SPECS): Add -mlong-double-64 support.
+ (TARGET_FLAG_LONG_DOUBLE_64, TARGET_LONG_DOUBLE_64): New.
+ (TARGET_SWITCHES): Add -mlong-double-64 support.
+ (LONG_DOUBLE_TYPE_SIZE): Likewise.
+ (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Define.
+ * i960/vx960-coff.h (MULTILIB_DEFAULTS): Define to msoft-float.
+ (CPP_SPECS): Add -mlong-double-64 support.
+ * i960/t-960bare (MULTILIB_OPTIONS): Add mlong-double-64.
+ (MULTILIB_DIRNAMES): Add ld64.
+ * i960/t-vxworks960 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Likewise.
- * cplus-dem.c (gnu_special): Don't get confused by .<digits>
- strings that are not actually lengths.
+Tue Jan 19 11:54:04 1999 Jason Merrill <jason@yorick.cygnus.com>
- * genattrtab.c: Make generated file use system.h, instead of
- including stdio.h, etc directly.
- * genextract.c, genopinit.c, genoutput.c: Likewise.
- * genpeep.c, genrecog.c: Likewise
+ * calls.c (expand_call): Strip a TARGET_EXPR if we're passing by
+ invisible reference.
- * genoutput.c (process_template): Mark operands in the generated
- function as potentially unused if compiling with GNU CC.
+Tue Jan 19 14:51:36 1999 David Edelsohn <edelsohn@gnu.org>
- * i386/freebsd-elf.h (CPP_PREDEFINES): Update from FreeBSD folks.
+ * rs6000.c (offsettable_addr_operand): Delete.
+ (offsettable_mem_operand): New function.
+ * rs6000.h (PREDICATE_CODES): Reflect function change.
+ (RS6000_SAVE_TOC): Represent address as MEM.
+ * win-nt.h (RS6000_SAVE_TOC): Same.
+ * rs6000.md (indirect calls): Change offsettable address parameter
+ to offsettable memory parameter.
- * pa.md (reload peepholes): Remove unused variable "mode".
+Tue Jan 19 10:24:53 1999 Mark Mitchell <mark@markmitchell.com>
-Wed Apr 1 17:06:19 1998 Nick Clifton <nickc@cygnus.com>
+ * rtl.h (rtx_def): Update documentation.
+ (MEM_IN_STRUCT_P): Likewise.
+ (MEM_SCALAR_P): New macro.
+ (MEM_COPY_ATTRIBUTES): Likewise.
+ (MEM_SET_IN_STRUCT_P): Likewise.
+ * rtl.texi (MEM_SCALAR_P): Document.
+ * alias.c (canon_rtx): Use MEM_COPY_ATTRIBUTES.
+ (fixed_scalar_and_varying_struct_p): New function. Use
+ MEM_SCALAR_P rather than !MEM_IN_STRUCT_P.
+ (aliases_everything_p): Likewise.
+ (true_dependence): Use them.
+ (write_dependence_p): New function, containing code common to
+ anti_dependence and output_dependence.
+ (anti_dependence): Use it.
+ (output_dependence): Likewise.
+ * calls.c (save_fixed_argument_area): Don't clear
+ MEM_IN_STRUCT_P.
+ (expand_call): Use MEM_SET_IN_STRUCT_P.
+ (emit_library_call): Don't clear MEM_IN_STRUCT_P.
+ (emit_library_call_value): Likewise.
+ (store_one_arg): Use MEM_SET_IN_STRUCT_P.
+ * combine.c (simplify_rtx): Use MEM_COPY_ATTRIBUTES.
+ (make_extraction): Likewise.
+ (simplify_shift_const): Likewise.
+ (gen_lowpart_for_combine): Likewise.
+ * cse.c (gen_lowpart_if_possible): Use MEM_COPY_ATTRIBUTES.
+ * emit-rtl.c (operand_subword): Likewise.
+ (change_address): Likewise.
+ * explow.c (stabilize): Use MEM_COPY_ATTRIBUTES.
+ * expr.c (protect_from_queue): Use MEM_COPY_ATTRIBUTES.
+ (emit_group_store): Use MEM_SET_IN_STRUCT_P.
+ (copy_blkmode_from_reg): Likewise.
+ (store_field): Likewise.
+ (expand_expr): Remove bogus guesswork setting MEM_IN_STRUCT_P
+ heuristically. Use MEM_SET_IN_STRUCT_P.
+ (get_memory_rtx): Likewise.
+ * final.c (alter_subreg): Use MEM_COPY_ATTRIBUTES.
+ * function.c (assign_stack_temp): Clear MEM_SCALAR_P and
+ MEM_ALIAS_SET on newly returned MEMs.
+ (assign_temp): Use MEM_SET_IN_STRUCT_P.
+ (put_reg_into_stack): Likewise.
+ (fixup_var_refs1): Use MEM_COPY_ATTRIBUTES.
+ (gen_mem_addressof): Use MEM_SET_IN_STRUCT_P.
+ (assign_parms): Likewise.
+ (expand_function): Likewise.
+ * integrate.c (expand_inline_function): Likewise.
+ (copy_rtx_and_substitute): Use MEM_COPY_ATTRIBUTES.
+ * loop.c (note_addr_stored): Remove check on MEM_IN_STRUCT_P.
+ * optabs.c (gen_move_insn): Use MEM_COPY_ATTRIBUTES.
+ * print-rtl.c (print_rtx): Print /f for frame_related.
+ * recog.c (validate_replace_rtx_1): Use MEM_COPY_ATTRIBUTES.
+ * reload1.c (reload): Copy MEM_SCALAR_P as well.
+ * stmt.c (expand_decl): Use MEM_SET_IN_STRUCT_P.
+ (expand_anon_union_decl): Use MEM_COPY_ATTRIBUTES.
+ * varasm.c (make_decl_rtl): Use MEM_SET_IN_STRUCT_P.
+ (output_constant_def): Likewise.
+ * a29k.c (a29k_set_memflags_1): Take scalar_p.
+ Set MEM_SCALAR_P.
+ (a29k_set_memflags): Use it.
+ * alpha.c (get_aligned_mem): Use MEM_COPY_ATTRIBUTES.
+ * c4x.c (c4x_scan_for_ld): Likewise.
+ * h8300.c (fix_bit_operand): Likewise.
+ * m88k.c (legitimize_address): Likewise.
+ (block_move_loop): Likewise.
+ (block_move_no_loop): Likewise.
+ (block_move_sequence): Likewise.
+ (m88k_builtin_saveregs): Use MEM_SET_IN_STRUCT_P.
+ * mips/abi64.h (SETUP_INCOMING_VARARGS): Likewise.
+ * rs6000.c (expand_block_move_insn): Use MEM_COPY_ATTRIBUTES.
+ * sh.c (sh_builtin_saveregs): Use MEM_SET_IN_STRUCT_P.
+ * arm.h (arm_gen_load_multiple): Take scalar_p.
+ (arm_store_load_multiple): Likewise.
+ * arm.c (arm_gen_load_multiple): Likewise.
+ (arm_gen_store_multiple): Likewise.
+ (arm_gen_movstrqi): Treat MEM_SCALAR_P like MEM_IN_STRUCT_P.
+
+Tue Jan 19 12:30:37 1999 Andrew MacLeod <amacleod@cygnus.com>
+
+ * optabs.c (emit_libcall_block): Add a REG_EH_REGION reg note to all
+ calls within a libcall block to indicate no throws are possible.
+ * flow.c (find_basic_blocks, find_basic_blocks_1): Don't look for
+ libcall blocks. Don't add edges to exception handlers if we see
+ a REG_EH_REGION note with a value of 0.
+ (make_edges): Override active_eh_region vector if the call has a note
+ indicating the call does not throw.
+
+1999-01-19 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * config/rs6000/sysv4.h (CC1_SPEC): Fix correct numbers of {}.
+
+Tue Jan 19 06:26:30 1999 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (cccp.o, cpplib.o): Depend on Makefile.
+
+Mon Jan 18 09:56:41 1999 Jason Merrill <jason@yorick.cygnus.com>
+
+ * invoke.texi (C++ Dialect Options): Document -fno-rtti.
+
+1999-01-18 Vladimir N. Makarov <vmakarov@cygnus.com>
+
+ * invoke.texi (-mcpu=740, -mcpu=750): New options.
+ (-m(no-)multiple, -m(no-)string): Describe cases for PPC740 &
+ PPC750.
+
+1999-01-18 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000.h ({ASM,CPP}_CPU_SPEC): Add support for all machines
+ supported with -mcpu=xxx.
+ (processor_type): Add PROCESSOR_PPC750.
+ (ADJUST_PRIORITY): Call rs6000_adjust_priority.
+ (RTX_COSTS): Supply costs for 750 multiply/divide operations.
+ (rs6000_adjust_priority): Add declaration.
+
+ * rs6000.c (rs6000_override_options): -mcpu={750,740} now sets the
+ processor type as 750, not 603. Allow -mmultiple and -mstring on
+ little endian 750 systems.
+ (rs6000_adjust_priority): Stub for now.
+ (get_issue_rate): The PowerPC 750 can issue 2 instructions/cycle.
+
+ * rs6000.md (function/cpu attributes): Add initial ppc750 support.
+
+ * sysv4.h (STRICT_ALIGNMENT): Don't force strict alignment if
+ little endian.
+ (CC1_SPEC): Pass -mstrict-align if little endian, and not
+ overridden.
+ (CC1_ENDIAN_{LITTLE,BIG,DEFAULT}_SPEC): Endian specific configs.
+ (SUBTARGET_EXTRA_SPECS): Add cc1 endian specs.
+
+ * {sysv4,eabi}le.h (CC1_ENDIAN_DEFAULT_SPEC): Override, default is
+ little endian.
+
+ * t-ppcgas (MULTILIB_*): Delete obsolete Solaris multilibs.
+
+Mon Jan 18 12:03:08 1999 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/mips/mips.md (div_trap): Split div_trap_mips16
+ from div_trap.
+ (div_trap_normal,div_trap_mips16): Correct the length attributes.
+
+Mon Jan 18 11:48:28 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cpplib.c (special_symbol): Qualify a char* with the `const' keyword.
+ Instead of writing to const char *buf directly, use a non-const
+ variable `wbuf' to allocate and write a string, then set buf = wbuf.
+
+ * cppulp.c (user_label_prefix): Qualify a char* with the `const'
+ keyword.
+
+ * dyn-string.c (dyn_string_append): Likewise.
- * config/arm/thumb.h: Add super interworking support.
- * config/arm/thumb.c: Add super interworking support.
- * config/arm/thumb.md: Add super interworking support.
- * config/arm/lib1funcs.asm: Add interworking support.
- * config/arm/lib1thumb.asm: Add super interworking support.
- * config/arm/t-semi: Add interworking support.
- * config/arm/t-thumb: Add interworking support.
- * config/arm/README-interworking: New file.
+ * dyn-string.h (dyn_string_append): Likewise.
-Wed Apr 1 14:38:10 1998 Jim Wilson <wilson@cygnus.com>
+ * final.c (end_final, output_operand_lossage, asm_fprintf): Likewise.
- * config/mips/iris6.h (MD_EXEC_PREFIX): Set to /usr/bin/.
- (MD_STARTFILE_PREFIX): Unset.
+ * output.h (end_final, output_operand_lossage, asm_fprintf,
+ named_section, decode_reg_name, make_decl_rtl, user_label_prefix):
+ Likewise.
-1998-04-01 Mark Mitchell <mmitchell@usa.net>
+ * profile.c (init_branch_prob): Likewise.
+
+ * toplev.c (set_target_switch, vmessage,
+ v_message_with_file_and_line, v_message_with_decl,
+ v_error_with_file_and_line, v_error_with_decl, v_error_for_asm,
+ verror, vfatal, v_warning_with_file_and_line, v_warning_with_decl,
+ v_warning_for_asm, vwarning, vpedwarn, v_pedwarn_with_decl,
+ v_pedwarn_with_file_and_line, vsorry, v_really_sorry,
+ open_dump_file, dump_rtl, clean_dump_file,
+ print_version, print_single_switch, print_switch_values,
+ dump_base_name, debug_args, lang_independent_options,
+ user_label_prefix, documented_lang_options, target_switches,
+ target_options, print_time, pfatal_with_name, fatal_io_error,
+ fatal_insn, default_print_error_function, print_error_function,
+ report_error_function, error_with_file_and_line, error_with_decl,
+ error_for_asm, error, fatal, warning_with_file_and_line,
+ warning_with_decl, warning_for_asm, warning, pedwarn,
+ pedwarn_with_decl, pedwarn_with_file_and_line, sorry,
+ really_sorry, botch, output_quoted_string, output_file_directive,
+ open_dump_file, rest_of_decl_compilation, display_help, main):
+ Likewise.
- * varasm.c (make_decl_rtl): Update the DECL_ASSEMBLER_NAME for a
- entity in a local scope.
+ * toplev.h (print_time, fatal, fatal_io_error, pfatal_with_name,
+ fatal_insn, warning, error, pedwarn, pedwarn_with_file_and_line,
+ warning_with_file_and_line, error_with_file_and_line, sorry,
+ really_sorry, default_print_error_function, report_error_function,
+ rest_of_decl_compilation, pedwarn_with_decl, warning_with_decl,
+ error_with_decl, error_for_asm, warning_for_asm, output_quoted_string,
+ output_file_directive, botch): Likewise.
- * fold-const.c (fold): Call truthvalue_conversion for values which
- are folded to boolean type.
+ * tree.h (make_decl_rtl): Likewise.
-Wed Apr 1 06:09:53 1998 Jeffrey A Law (law@cygnus.com)
+ * varasm.c (strip_reg_name, named_section, decode_reg_name,
+ make_decl_rtl): Likewise.
- * 1750a.md, arm.c, clipper.c, clipper.md: Use GEN_INT consistently.
- * convex.h, dsp16xx.c, fx80.md, gmicro.c, gmicro.md: Likewise.
- * i370.h, i370.md, i860.c, i860.h, i860.md, i960.c: Likewise.
- * i960.h, i960.md, m32r.md, m68k.md, m68kv4.h, m88k.c: Likewise.
- * m88k.md, ns32k.c, ns32k.md, pdp11.c, pdp11.h, pdp11.md: Likewise.
- * pyr.c, pyr.h, pyr.md, romp.c, romp.h, romp.md: Likewise.
- * rs6000.md, sparc.c, sparc.h, sparc.md, spur.c, spur.md: Likewise.
- * tahoe.md, vax.h, vax.md, we32k.c, we32k.h, we32k.md: Likewise.
- * md.texi: Likewise.
+Mon Jan 18 11:35:49 1999 Gavin Romig-Koch <gavin@cygnus.com>
-Wed Apr 1 08:33:44 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * Makefile.in (TCL_LIBRARY): Use 'cd' to find the library
+ directory logically rather than physically.
- * fixincludes (limits.h): Fix nested comments in Motorola's
- limits.h and sys/limits.h.
+Mon Jan 18 09:05:37 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Tue Mar 31 16:57:33 1998 Jim Wilson <wilson@cygnus.com>
+ * loop.c (insert_bct): Hide the definition of variables
+ `increment_direction', `compare_direction', `add_iteration' and
+ `loop_var_mode'.
- * alpha.c (alpha_expand_unaligned_load): Use tgt instead of addr
- as dest of expand_binop call.
+ * recog.c (mode_dependent_address_p): Mark parameter `addr' with
+ ATTRIBUTE_UNUSED. Mark label `win' with ATTRIBUTE_UNUSED_LABEL.
+ (mode_independent_operand): Mark label `lose' with
+ ATTRIBUTE_UNUSED_LABEL.
- * alpha.md (extzv): Correct check for valid operand[2] values.
+ * regclass.c (n_occurrences): Remove prototype and definition.
- * profile.c (branch_prob): Add code to recognize HPPA tablejump entry
- branch.
+ * reload.c (find_reloads_address_1): Mark variable `tem' with
+ ATTRIBUTE_UNUSED.
- * toplev.c (rest_of__compilation): Call init_recog_no_volatile at end.
+ * reload1.c (reload): Cast the first two arguments of `bcopy' to PTR.
-Mon Mar 30 13:11:05 1998 Stan Cox <scox@cygnus.com>
+ * sbitmap.c (sbitmap_copy): Likewise.
- * libgcc2.c: (__main, __do_global_dtors, __do_global_ctors):
- For __CYGWIN32__ use the versions in winsup/dcrt0.cc.
+ * scan-decls.c (scan_decls): Hide label `handle_comma'.
- * gcc.c, cccp.c, cpplib.c, collect2.c (GET_ENVIRONMENT): Added.
- cygwin32 can override this to allow both unix and win32 style PATHs.
+ * toplev.c (output_lang_identify): Mark prototype with
+ ATTRIBUTE_UNUSED.
- * i386/xm-cygwin32.h (GET_ENVIRONMENT): Defined to allow win32
- style environment paths.
+ * tree.c (make_node): Cast the first argument of `bzero' to PTR.
+ (make_tree_vec): Likewise.
+ (build1): Likewise.
-Mon Mar 30 14:43:20 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * varasm.c (assemble_static_space): Mark variable `tem' with
+ ATTRIBUTE_UNUSED.
- * Makefile.in (cppalloc.o, cpperror.o, cppexp.o, cpphash.o,
- cpplib.o, cppmain.o, fix-header.o, gcov.o, gen-protos.o,
- gengenrtl.o, halfpic.o, hash.o, scan-decls.o, scan.o): Depend on
- system.h.
+Mon Jan 18 04:28:36 1999 Nathan Sidwell <nathan@acm.org>
- * cpphash.c: Include config.h.
- * cppalloc.c: Include system.h. Add parameters to various
- function prototypes.
- * cpperror.c: Likewise.
- * cppexp.c: Likewise.
- * cpphash.c: Likewise.
- * cpplib.c: Likewise.
- * cppmain.c: Likewise.
- * fix-header.c: Likewise.
- * gcov.c: Likewise.
- * gen-protos.c: Likewise.
- * gengenrtl.c: Likewise.
- * halfpic.c: Likewise.
- * hash.c: Likewise.
- * scan-decls.c: Likewise.
- * scan.c: Likewise.
+ * Makefile.in (GCOV_INSTALL_NAME): New macro.
+ (install-common): Use it.
+ (uninstall): Use it.
+ (uninstall): Use correct names for protoize and unprotoize.
-Mon Mar 30 11:06:45 1998 Jim Wilson <wilson@cygnus.com>
+Mon Jan 18 03:52:56 1999 Christian Bruel <Christian.Bruel@st.com>
+ Jeffrey A Law (law@cygnus.com)
- * README.gnat: Add lang_print_xnode definition.
+ * flow.c (last_mem_set): Delete variable. References removed.
+ (mem_set_list): New variable.
+ (life_analysis): Initialize and finalize alias analysis.
+ (propagate_block); Initialize mem_set_list. Clear for CALL_INSNs.
+ (insn_dead_p): For a store to memory, search the entire mem_set_list
+ for a match.
+ (mark_set_1): Kill entries on the mem_set_list for aliased writes or
+ changes to their addresses. Add new entries to the mem_set_list for
+ memory writes writes.
+ (mark_used_regs): Kill entries on the mem_set_list which may be
+ referenced by a load operation.
-Mon Mar 30 11:12:24 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Mon Jan 18 01:01:02 1999 Jeffrey A Law (law@cygnus.com)
- * config/m68k/m68k.c (standard_68881_constant_p): Don't use
- fmovecr on the 68060.
+ * alias.c (base_alias_check): Add missing return for differing
+ symbols case.
-Mon Mar 30 00:21:03 1998 Jeffrey A Law (law@cygnus.com)
+Mon Jan 18 00:36:13 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- * genemit.c (DONE): Rework so that it works in the true arm if
- an if-else conditional.
- (FAIL): Likewise.
+ * mips-tdump.c (print_file_desc): Handle unknown filenames and
+ missing local symbols.
-Sun Mar 29 12:45:23 1998 Jeffrey A Law (law@cygnus.com)
+Sun Jan 17 21:04:31 1999 Richard Henderson <rth@cygnus.com>
- * rs6000.c: Do not include stdioh or ctype.h anymore.
+ * jump.c (rtx_renumbered_equal_p): Special case CODE_LABEL.
- * Makefile.in (c-typeck.o): Delete on expr.h, insn-codes.h and
- $(RTL_H).
- (stor-layout.o): Likewise.
- * c-typeck.c: Include rtl.h and expr.h.
- * stor-layout.c: Likewise.
+ * system.h (bcopy): Implement with memmove not memcpy.
- * cpplib.c (cpp_file_line_for_message): Delete unused parameter.
- All callers changed.
- (do_sccs): Wrap in an SCCS_DIRECTIVE ifdef.
- * fix-header.c (cpp_file_line_for_message): Delete unused paramter.
- All callers changed.
+Sun Jan 17 19:23:20 1999 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (cppulp.o): Add dependencies.
- * collect2.c (is_in_list): Wrap inside COLLECT_EXPORT_LIST ifdef.
+ * i386.md (integer conditional moves): Add missing earlyclobbers.
+
+ * regmove.c (optimize_reg_copy_1): Undo Aug 18 change. Update
+ REG_N_CALLS_CROSSED and REG_LIVE_LENGH if and only if we change
+ where a register is live.
- * local-alloc.c (reg_classes_overlap_p): Delete dead function.
+Sun Jan 17 03:20:47 1999 H.J. Lu (hjl@gnu.org)
- * tree.h (lang_print_xnode): Provide prototype.
+ * reg-stack.c (subst_stack_regs_pat): Abort if the destination
+ of a FP conditional move is not on the FP register stack.
-Sat Mar 28 23:50:44 PST 1998 Jeff Law (law@cygnus.com)
+Sun Jan 17 01:15:04 1999 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Sun Mar 29 00:42:21 1998 Jeffrey A Law (law@cygnus.com)
+Sat Jan 16 23:40:33 1999 Jeffrey A Law (law@cygnus.com)
- * objc/sendmsg.c (__objc_block_forward): Add braces for return
- value if INVISIBLE_STRUCT_RETURN.
+ * reload1.c (reload_cse_regs_1): Do not call
+ reload_cse_simplify_operands for an insn with asm operands.
- * pa.c (arith_double_operand): Fix parens.
+ * cccp.c (print_help): Fix typos.
+ * cpplib.c (print_help): Fix typos.
+ * toplev.c (f_optiosn): Fix typos.
+ (documented_lang_options): Fix typos.
- * haifa-sched.c (print_pattern): Correct arg to sprintf.
+Sat Jan 16 21:48:17 1999 Marc Espie (Marc.Espie@openbsd.org)
- * Makefile.in (libgcc1.null): Make return type for __foo void.
+ * gcc.c (do_spec_1): Fix obvious typo.
-Sat Mar 28 14:37:20 1998 Jeffrey A Law (law@cygnus.com)
+Sat Jan 16 19:31:07 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * pa.h: Add declarations for many functions defined in pa.c.
+ * c-decl.c (duplicate_decls): If `warn_traditional', warn when
+ a non-static function declaration follows a static one.
- * genpeep.c (main): Remove unused variable 'i' from the generated
- file.
+ * invoke.texi (-Wtraditional): Document the extra check now done
+ by this flag.
- * genemit.c (gen_expand): Do not emit "_done" or "_fail" labels.
- (gen_split): Likewise.
- (main): Rework generated definitions of DONE and FAIL so that they
- no longer use gotos. Avoids warnings about unused labels.
+Sat Jan 16 15:13:46 1999 Jeffrey A Law (law@cygnus.com)
- * integrate.c (copy_rtx_and_substitute): Rework to avoid need for
- unused "junk" variable.
+ * pa.md (shadd): Create shadd insns, even if the result of the shift is
+ needed without the addition.
- * genattrtab.c (write_complex_function): Add a default case in
- generated switch statement to keep -W -Wall quiet.
+Sat Jan 16 10:48:16 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
-Sat Mar 28 10:47:21 1998 Nick Clifton <nickc@cygnus.com>
+ * sh.md (movdf, movsf): Temporary workaround for no_new_pseudos lossage.
- * invoke.texi: Document more ARM and Thumb command line options.
+Fri Jan 15 23:44:37 1999 Richard Henderson <rth@cygnus.com>
- * config/arm/xm-thumb.h: New file.
+ * sparc.c (sparc_issue): Add hypersparc/sparclite86x entries.
-Sat Mar 28 01:37:33 1998 Craig Burley <burley@gnu.ai.mit.edu>
+Fri Jan 15 22:30:04 1999 David Edelsohn <edelsohn@gnu.org>
- * stmt.c (expand_expr_stmt): Must generate code for
- statements within an expression (gcc's `({ ... )}')
- even if -fsyntax-only.
+ * rs6000.h (CONST_OK_FOR_LETTER_P): Do not assume 32-bit CONST_INT.
+ * rs6000.c (u_short_cint_operand, add_operand, logical_operand,
+ non_add_cint_operand, non_logical_cint_operand): Likewise.
+ (get_issue_rate): Add CPU_PPC604E case.
+ * rs6000.md (movdi, !TARGET_POWERPC64 splitters): Handle 64-bit hosts.
-Sat Mar 28 01:06:12 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- Jeffrey A Law (law@cygnus.com)
+Fri Jan 15 18:42:12 1999 Richard Henderson <rth@cygnus.com>
- * basic-block.h (basic_block_computed_jump_target): Declare.
- * flags.h: (current_function_has_computed_jump): Declare.
- * flow.c: (basic_block_computed_jump_target): Define.
- (flow_analysis): Allocate it. Set current_function_has_computed_jump
- to 0.
- (find_basic_blocks): Set current_function_has_computed_jump and
- elements of basic_block_computed_jump_target to 1 as appropriate.
- * function.c: (current_function_has_computed_jump): Define.
- * global.c (global_conflicts): Don't allocate pseudos into stack regs
- at the start of a block that is reachable by a computed jump.
- * reg-stack.c (stack_reg_life_analysis): If must restart, do so
- immediately.
- (subst_stack_regs): Undo change from Sep 4 1997.
- (uses_reg_or_mem): Now unused, deleted.
- * stupid.c (stupid_life_analysis): Compute
- current_function_has_computed_jump.
- (stupid_find_reg): Don't allocate stack regs if the function has a
- computed goto.
- * haifa-sched.c (is_cfg_nonregular): Delete code to determine if
- the current function has a computed jump. Use the global value
+ * expr.c (queued_subexp_p): Make public.
+ * expr.h (queued_subexp_p): Declare it.
+ * recog.c (asm_operand_ok): New function.
+ (check_asm_operands): Use it. After reload, use constrain_operands
instead.
+ * recog.h (asm_operand_ok): Declare it.
+ * stmt.c (expand_asm_operands): Use it to try harder to make
+ asms initially satisfy their constraints.
-Sat Mar 28 00:21:37 1998 Jeffrey A Law (law@cygnus.com)
+Fri Jan 15 17:43:59 1999 Jeffrey A. Law <law@rtl.cygnus.com>
- * i386/freebsd.h (CPP_PREDEFINES): Remove __386BSD__.
- (DWARF2_UNWIND_INFO): Define to zero.
+ * sparc.h (LEGITIMIZE_RELOAD_ADDRESS): Do not create
+ (mem (lo_sum (...)) for TFmode unless TARGET_V9.
-Fri Mar 27 16:04:49 1998 Michael Meissner <meissner@cygnus.com>
+Sat Jan 16 12:47:15 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * gcc.c (set_std_prefix): Add declaration.
- (process_command): If GCC_EXEC_PREFIX is set, remove /lib/gcc-lib/
- suffix, and update the standard prefix prefix.c uses.
+ * config/c4x/c4x.md (not_repeat_reg): Allow ldp instruction
+ in delay slot of RPTBD.
- * prefix.c (std_prefix): New global to hold default prefix value.
- (get_key_value): Change to use std_prefix instead of PREFIX.
- (translate_name): Ditto.
- (update_path): Ditto.
- (get_key_value): Release allocated scratch storage.
- (set_std_prefix): New function to reset the standard prefix.
+Sat Jan 16 12:26:40 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Fri Mar 27 18:08:21 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * config/c4x/libgcc.S (___divhi3, ___modhi3): Fix long long
+ divide and modulo sign problem.
- * sh.c (find_barrier): Fix calculations for alignment increase.
+Fri Jan 15 11:02:31 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Fri Mar 27 08:56:52 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * unroll.c (loop_iterations): Return 0 if the last loop insn
+ is not a jump insn or if the loop has multiple back edges.
- * Makefile.in (stmp-fixinc): If we're actually fixing include
- files, copy gcc's assert.h into the fixed include dir.
- * fixincludes (assert.h): Avoid any attempts to fix a probably
- broken system specific assert.h file.
- * fixproto (stdlib.h): Make sure, it'll contain a definition of
- size_t.
+1999-01-15 Manfred Hollstein <manfred@s-direktnet.de>
-Fri Mar 27 00:49:46 1998 Jeffrey A Law (law@cygnus.com)
+ * configure.in (fixinc_defs): Do not define for m[68]8k-motorola-sysv{,3};
+ it's working properly now. Remove comment saying "see m68k-motorola-sysv
+ as an example".
+ * configure: Regenerate using autoconf.
- * regclass.c (reg_scan_mark_refs): Be more selective about
- when we mark a register with REGNO_POINTER_FLAG.
+ * fixinc/fixincl.c (main): Do not ignore SIGCHLD.
-Thu Mar 26 23:00:11 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Thu Jan 14 22:38:41 1999 Jeffrey A Law (law@cygnus.com)
- reload inheritance improvement:
- * reload1.c (reg_reloaded_contents, reg_reloaded_insn):
- Change meaning: index is now hard reg number.
- (reg_reloaded_valid, reg_reloaded_dead): New variables.
- (reload_spill_index): Content is now a hard reg number.
- (reload_as_needed): Change to fit new variable meaning.
- (forget_old_reloads_1, allocate_reload_reg): Likewise.
- (choose_reload_regs, emit_reload_insns): Likewise.
+ * unroll.c (find_splittable_givs): For a DEST_ADDR giv, do not share
+ a register with another DEST_ADDR giv if the address is not valid.
-Thu Mar 26 18:34:13 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * pa.c (hppa_expand_epilogue): Save and restore the static chain
+ around the call to mcount.
- * regclass.c (record_reg_classes): '?' increases cost by two.
+ * h8300.h (ASM_OUTPUT_LABELREF): Use asm_fprintf, not fprintf.
- * reload.c (find_reloads): Double previous costs. Output
- reloads cost one unit extra.
+ * stmt.c (expand_end_case): Use emit_cmp_and_jump_insns to avoid
+ generating non-canonical rtl.
- * reload1.c (eliminate_regs): Delete LOAD_EXTENDED_OP code that
- boiled down to && ! 0.
+1999-01-14 Vladimir N. Makarov <vmakarov@cygnus.com>
- * reload.c (find_equiv_reg): Also consider a goal offset from the
- frame pointer to be constant.
+ * config/i960/i960.c (i960_output_move_double_zero,
+ i960_output_move_quad_zero): New functions for moving zeros.
+ (i960_output_move_double, i960_output_move_quad): Additional code
+ for situation when moving unaligned register group.
-Thu Mar 26 17:34:46 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * config/i960/i960.h (i960_output_move_double_zero,
+ i960_output_move_quad_zero): The function definitions.
- * sh.h (OPTIMIZATION_OPTIONS): Define.
+ * config/i960/i960.md (movdi+1, movti+1): Usage of the functions.
-Thu Mar 26 00:19:47 1998 Richard Henderson <rth@cygnus.com>
+1999-01-13 Vladimir N. Makarov <vmakarov@cygnus.com>
- * combine.c (make_compound_operation): Simplify (subreg (*_extend) 0).
+ * config/i960/i960.c (i960_function_prologue): New code (optimal
+ solution) for saving global registers in local registers.
+ (form_reg_groups, reg_group_compare, split_reg_group): New
+ functions used by the code.
+ (reg_group): New structure definition for the new code.
-Wed Mar 25 23:53:11 1998 Jeffrey A Law (law@cygnus.com)
+1999-01-13 Manfred Hollstein <manfred@s-direktnet.de>
- * pa.c (pa_adjust_cost): Avoid redundant calls to get_attr_type.
+ * fixinc/fixincl.c (create_file): Pass file creation mask as
+ third parameter to "open". Use O_TRUNC flag to open instead of
+ explicitly unlink'ing the file.
+ (process): and forget about the "chmod" stuff.
-Wed Mar 25 13:40:48 1998 Jim Wilson <wilson@cygnus.com>
+Wed Jan 13 20:12:37 1999 Richard Henderson <rth@cygnus.com>
- * c-common.c (check_format_info): Initialize type, is_type. New local
- integral_format. Don't warn for 'L' when pedantic. Do warn for 'L'
- when pedantic if used with integral format specifier.
+ * integrate.c (expand_inline_function): Recognize (mem (addressof))
+ and substitute. Copy the return value from there into a new pseudo.
-Wed Mar 25 16:09:01 1998 Michael Meissner <meissner@cygnus.com>
+Wed Jan 13 16:47:00 1999 Catherine Moore <clm@cygnus.com>
- * rs6000.h (FUNCTION_ARG_PADDING): Cast result to be enum
- direction.
- (function_arg_padding): Declare.
+ * config/arm.c (output_func_epilogue): Check TARGET_ABORT_NORETURN
+ before generating a call to abort for volatile functions.
+ * config/arm.h (ARM_FLAG_ABORT_NORETURN): Define.
+ (TARGET_ABORT_NORETURN): Define.
+ (abort-on-noreturn): New option.
- * rs6000.c: Include system.h.
- (function_arg_padding): Change return type to int, cast enum's to
- int.
+Thu Jan 14 13:52:42 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- (From Kaveh R. Ghazi <ghazi@caip.rutgers.edu>)
- * collect2.c (scan_prog_file): Add explicit braces to avoid
- ambiguous `else'.
+ * config/c4x/c4x.md (in_annul_slot_3): Correctly allow unarycc
+ and binarycc operations in 3rd annulled delay slot!
- * dbxout.c (dbxout_type_fields): Add braces around empty body in
- an if-statement.
- (dbxout_type): Likewise.
+Wed Jan 13 16:16:44 1999 Catherine Moore <clm@cygnus.com>
- * rs6000.c (rs6000_override_options): Change type of `i', `j' and
- `ptt_size' from int to size_t.
- (rs6000_file_start): Likewise for `i'.
- (rs6000_replace_regno): Add default case in enumeration switch.
- (output_epilog): Remove unused variable `i'.
- (rs6000_longcall_ref): Remove unused variables `len', `p', `reg1'
- and `reg2'.
+ * config/arm.c (output_func_epilogue): Check TARGET_ABORT_NORETURN
+ before generating a call to abort for volatile functions.
+ * config/arm.h (ARM_FLAG_ABORT_NORETURN): Define.
+ (TARGET_ABORT_NORETURN): Define.
+ (abort-on-noreturn): New option.
- * rs6000.h (ADDITIONAL_REGISTER_NAMES): Add missing braces around
- initializer.
- (get_issue_rate, non_logical_cint_operand): Add prototype.
- (rs6000_output_load_toc_table): Ditto.
+Wed Jan 13 13:30:08 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * rs6000.md (udivmodsi4): Add explicit braces to avoid ambiguous
- `else'.
+ * cccp.c (xstrdup): Renamed from `savestring'. All callers changed.
+ Remove prototype which we get from libiberty.h.
-Wed Mar 25 10:05:19 1998 Nick Clifton <nickc@cygnus.com>
+ * collect2.c (xstrdup): Likewise.
- * config/arm/thumb.c: New File. Support for ARM's Thumb
- instruction set.
- * config/arm/thumb.h: New File. Thumb definitions.
- * config/arm/thumb.md: New File. Thumb machine description.
- * config/arm/tcoff.h: New File. Thumb COFF support.
- * config/arm/t-thumb: New File. Thumb makefile fragment.
- * config/arm/lib1thumb.asm: New File. Thumb libgcc support functions.
+ * genextract.c (xstrdup): Likewise for `copystr'.
+ (mybzero): Remove it and use `memset' instead.
- * configure.in: Add Thumb-coff target.
- * configure: Add Thumb-coff target.
- * config.sub: Add Thumb-coff target.
+ * genoutput.c (mybcopy, mybzero): Remove these. All callers changed
+ to use `memcpy' and `memset' instead.
-Wed Mar 25 10:30:32 1998 Jim Wilson <wilson@cygnus.com>
+ * genrecog.c (xstrdup): Renamed from `copystr'. All callers
+ changed. Remove prototype.
+ (mybcopy, mybzero): Remove these and use memcpy/memset.
- * loop.c (scan_loop): Initialize move_insn_first to zero.
+Wed Jan 13 00:59:04 1999 Jeffrey A Law (law@cygnus.com)
-Wed Mar 25 01:06:49 1998 Joel Sherrill (joel@OARcorp.com)
+ * mips.h (LOAD_EXTEND_OP): Correct for SImode and CCmode moves when
+ generating code for TARGET_64BIT.
- * config/i386/go32-rtems.h: Defined TARGET_MEM_FUNCTIONS.
- * config/i386/rtems.h: Likewise.
- * config/i960/rtems.h: Likewise.
- * config/m68k/rtems.h: Likewise.
- * config/mips/rtems64.h: Likewise.
- * config/pa/rtems.h: Likewise.
- * config/rs6000/rtems.h: Likewise.
- * config/sh/rtems.h: Likewise.
- * config/sparc/rtems.h: Likewise.
+Tue Jan 12 14:05:37 1999 David Edelsohn <edelsohn@gnu.org>
-Wed Mar 25 00:57:26 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * rs6000.c (print_operand, cases 'm' and 'M'): Do not depend on
+ HOST_WIDE_INT word-size.
+ (rs6000_stack_info): Remove redundant alignment of fpmem.
- * pa.c (emit_move_sequence): If in reload, call find_replacement.
+Tue Jan 12 14:05:37 1999 Richard Henderson <rth@cygnus.com>
-Tue Mar 24 10:44:11 1998 Nick Clifton <nickc@cygnus.com>
+ * rs6000.c (short_cint_operand): Remove CONSTANT_P_RTX handling.
+ (u_short_cint_operand, reg_or_cint_operand, logical_operand): Likewise.
+ (input_operand): Adjust CONSTANT_P_RTX handling.
+ * rs6000.h (PREDICATE_CODES): Remove CONSTANT_P_RTX references.
+ * rs6000.md (movsi): Adjust CONSTANT_P_RTX handling.
+ (movhi, movqi): Remove CONSTANT_P_RTX handling.
+ (movdi): Adjust CONSTANT_P_RTX handling.
- * Makefile.in (gcov$(exeext)): Support .exe extension to gcov.
+1999-01-12 Manfred Hollstein <manfred@s-direktnet.de>
- * collect2.c (find_a_file): Add debugging.
- (find_a_file): Test for win32 style absolute paths if
- DIR_SERPARATOR is defined.
- (prefix_from_string): Add debugging.
- (main): Test for debug command line switch at start of program
- execution.
- (main): Use GET_ENVIRONMENT rather than getenv().
- (prefix_from_env): Use GET_ENVIRONMENT.
+ * configure: Regenerate using autoconf.
-1998-03-24 Mark Mitchell <mmitchell@usa.net>
+ * fixinc/Makefile.in (INCLUDES): Add -I$(srcdir)/../../include.
+ * fixinc/fixincl.c (SIGCHLD): Use SIGCLD on (very) old systems.
+ (process): "fchmod" isn't available on all systems, use "chmod"
+ instead.
+ * fixinc/server.c: Add #include <sys/types.h>.
+ (STDIN_FILENO): Add default definition if no include file defines
+ it already.
+ (STDOUT_FILENO): Likewise.
- * cplus-dem.c (optable): Add sizeof.
- (demangle_template_value_parm): New function containing code
- previously found in demangle_template.
- (demangle_integral_value): New function which handles complicated
- integral expressions.
- (demangle_template): Use them.
+Tue Jan 12 10:23:24 1999 Stan Cox <scox@cygnus.com>
-Tue Mar 24 12:13:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * mips.md (call_value_internal3c): New pattern for -mips16 -mlong-calls.
- * Makefile.in (genconfig.o, genflags.o, gencodes.o, genemit.o,
- genopinit.o, genrecog.o, genextract.o, genpeep.o, genattr.o,
- genattrtab.o, genoutput.o): Depend on system.h.
+1999-01-12 Manfred Hollstein <manfred@s-direktnet.de>
- * genattr.c: Include system.h. Add arguments to various function
- prototypes. Remove redundant prototype of read_rtx().
- * genattrtab.c: Likewise.
- * gencodes.c: Likewise.
- * genconfig.c: Likewise.
- * genemit.c: Likewise.
- * genextract.c: Likewise.
- * genflags.c: Likewise.
- * genopinit.c: Likewise.
- * genoutput.c: Likewise.
- * genpeep.c: Likewise.
- * genrecog.c: Likewise.
+ * m68k/mot3300.h (ADD_MISSING_POSIX, ADD_MISSING_XOPEN): Define to
+ ensure all prototypes necessary for building libio will be available.
+ * m68k/xm-mot3300.h (ADD_MISSING_POSIX, ADD_MISSING_XOPEN): Remove
+ definitions here as they are not host specific.
+ * m88k/sysv3.h, m88k/xm-sysv3.h: Likewise.
-1998-03-24 Martin von Loewis <loewis@informatik.hu-berlin.de>
+Tue Jan 12 02:53:46 1999 Richard Henderson <rth@cygnus.com>
- * c-lang.c (lang_print_xnode): New function.
- * objc/objc-act.c (lang_print_xnode): Likewise.
- * print-tree.c (print_node): Call it
+ * cse.c (cse_insn): Never prefer (const (constant_p_rtx)).
-Mon Mar 23 23:59:11 1998 H.J. Lu (hjl@gnu.org)
+Tue Jan 12 02:36:10 1999 Jeff Law (law@cygnus.com)
- * c-parse.in: Recognize protocol qualifiers in class
- definitions for objc.
- Include "output.h".
- (yyerror): Remove redundant decl.
- (yyprint): Fix prototype.
+ * version.c: Bump for snapshot.
-Mon Mar 23 23:49:47 1998 Jeffrey A Law (law@cygnus.com)
+Tue Jan 12 01:30:19 1999 Richard Henderson <rth@cygnus.com>
- * cse.c (rtx_cost): Only call CONST_COSTS if it is defined.
+ * rtl.c (rtx_alloc): Use memset instead of inline loop.
- * stmt.c (unroll_block_trees): Free block_vector if needed.
+ * recog.h (recog_op_alt): Declare extern.
-Mon Mar 23 23:26:42 1998 Philippe De Muyter <phdm@macqel.be>
+Tue Jan 12 00:23:31 1999 Richard Henderson <rth@cygnus.com>
- * m68k/m68k.md (zero_extendqidi2, zero_extendhidi2): New patterns.
- (zero_extendsidi2): Avoid useless copy.
- (iordi_zext): New pattern.
- (iorsi_zexthi_ashl16): Pattern reworked to avoid "0" constraint for
- operand 2.
- (iorsi_zext): New name for old unnamed pattern; indentation fixes.
+ * function.c (purge_addressof_1): If the note accesses a mem+addressof
+ in a wider mode than any replacement, adjust the cached replacement.
+ Cache trivial substitutions as well.
- * m68k/m68k.md (ashldi_const): Allow shift count in range ]32,63].
- (ashldi3): Allow constant shift count in range ]32,63].
- (ashrdi_const, ashrid3, lshrdi_const, lshrdi3): Likewise.
+Tue Jan 12 00:06:00 1999 Richard Henderson <rth@cygnus.com>
-1998-03-22 Mark Mitchell <mmitchell@usa.net>
+ * Makefile.in (OBJECTS): Add sbitmap.o.
+ (BASIC_BLOCK_H): Add sbitmap.h.
+ * basic-block.h: Move simple bitmap code to sbitmap.h.
+ * flow.c: Move simple bitmap code to sbitmap.c.
+ * sbitmap.h, sbitmap.c: New files.
- * tree.h (IS_EXPR_CODE_CLASS): New macro.
+Mon Jan 11 23:51:50 1999 Richard Henderson <rth@cygnus.com>
-Mon Mar 23 23:18:48 1998 Jeffrey A Law (law@cygnus.com)
+ * alpha.h (TARGET_SWITCHES): Document switches.
+ (TARGET_OPTIONS): Likewise.
- * h8300.h (CONST_COSTS): Remove definition.
- (DEFAULT_RTX_COSTS): Define.
+ * alpha/elf.h (ASM_FINISH_DECLARE_OBJECT): Use HOST_WIDE_INT_PRINT_DEC.
-Mon Mar 23 22:58:22 1998 Joel Sherrill (joel@OARcorp.com)
+Mon Jan 11 22:54:14 1999 Richard Henderson <rth@cygnus.com>
- * config/sh/rtems.h: Switched from ELF to COFF.
+ * tree.c (new_alias_set): Return zero if !flag_strict_aliasing.
-Mon Mar 23 14:14:20 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Jan 11 22:36:01 1999 Richard Henderson <rth@cygnus.com>
- * freebsd.h (ASM_OUTPUT_ALIGN): Redefine.
+ * basic-block.h (basic_block_head): Rename to x_basic_block_head.
+ (basic_block_end): Rename to x_basic_block_end.
+ (BLOCK_HEAD, BLOCK_END): Update.
-Sat Mar 21 23:52:56 PST 1998 Jeff Law (law@cygnus.com)
+ * caller-save.c: Change basic_block_head/end references to
+ BLOCK_HEAD/END.
+ * combine.c, flow.c, function.c, gcse.c, global.c: Likewise.
+ * graph.c, haifa-sched.c, local-alloc.c, regclass.c: Likewise.
+ * regmove.c, reload1.c, reorg.c, sched.c: Likewise.
- * version.c: Bump for snapshot.
+Sat Jan 9 23:54:09 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.c (xstrerror): Renamed from my_strerror. All callers
+ changed. Remove prototype since we get that from libiberty.h.
+
+ * protoize.c (xstrerror): Likewise.
+
+Sat Jan 9 23:22:04 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.c (read_specs): Ensure format specifiers match their arguments.
+
+Sat Jan 9 20:04:24 1999 Richard Henderson <rth@cygnus.com>
+
+ * tree.c (copy_node): Oops. That would be copy not zero
+ in that last change.
+
+Sun Jan 10 15:35:41 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.c: Include system.h.
+ (c4x_caller_save_map): Disable caller save for RC.
+ (c4x_optimization_options): Disable scheduling before reload.
+ (valid_parallel_load_store) : Define return type as int.
+ Remove unused variable regs.
+ * config/c4x/c4x.h (REGISTER_MOVE_COST): Make independent of register
+ class.
+ * config/c4x/c4x.md (rotlqi3, rotrqi3): Fix up emitted RTL to
+ handle rotations.
+ (*db, decrement_and_branch_until_zero): Fix up constraints
+ to keep reload happy.
-Sun Mar 22 00:50:42 1998 Nick Clifton <nickc@cygnus.com>
- Geoff Noer <noer@cygnus.com>
+Sat Jan 9 18:35:29 1999 Richard Henderson <rth@cygnus.com>
- * Makefile.in: Various fixes for building cygwin32 native toolchains.
+ * tree.c (make_node): Call bzero instead of inline clear.
+ (copy_node, make_tree_vec, build1): Likewise.
+ (get_identifier): Call strlen instead of inline count.
+ (maybe_get_identifier): Likewise.
- * objc/Makefile.in: Various fixes for building cygwin32 native toolchains.
- * objc/Make-lang.in: Likewise.
+Sun Jan 10 14:04:51 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * config/i386/xm-cygwin32.h (PATH_SEPARATOR): Set to a semi-colon.
+ * config/c4x/c4x.md (in_annul_slot_3): Allow unarycc and binarycc
+ operations in 3rd annulled delay slot.
+ (*lshrqi3_const_set): Disallow c constraint for operand0.
+ (modhi3+1, modhi3+2): Set attribute type to multi.
+ * config/c4x/c4x.c (c4x_S_constraint): Removed space in middle of
+ != operator.
-Sun Mar 22 00:21:46 1998 R. Ganesan <rganesan@novell.com>
+Sat Jan 9 11:44:55 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * configure.in: Handle with-PACKAGE=no correctly
+ * gansidecl.h: Allow attribute unused on labels only when we are
+ version 2.93 or higher. Not all versions of 2.92 have this feature.
-Fri Mar 20 17:36:23 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * version.c: Bump minor number to 93.
- * Makefile.in (alias.o, bitmap.o, c-aux-info.o, c-common.o,
- c-decl.o, c-iterate.o, c-lang.o, c-lex.o, c-pragma.o, c-typeck.o,
- caller-save.o, calls.o, collect2.o, combine.o, cse.o, dbxout.o,
- dwarf2out.o, dwarfout.o, emit-rtl.o, except.o, explow.o, expmed.o,
- expr.o, final.o, flow.o, function.o, getpwd.o, global.o,
- integrate.o, jump.o, local-alloc.o, loop.o, optabs.o, pexecute.o,
- prefix.o, print-rtl.o, print-tree.o, profile.o, real.o, recog.o,
- reg-stack.o, regclass.o, regmove.o, reload.o, reload1.o, reorg.o,
- rtl.o, rtlanal.o, sdbout.o, stmt.o, stor-layout.o, stupid.o,
- tlink.o, toplev.o, tree.o, unroll.o, varasm.o, xcoffout.o): Depend
- on system.h.
+Fri Jan 8 10:51:13 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * alias.c, bitmap.c, c-aux-info.c, c-common.c, c-decl.c,
- c-iterate.c, c-lang.c, c-lex.c, c-pragma.c, c-typeck.c,
- caller-save.c, calls.c, collect2.c, combine.c, cse.c, dbxout.c,
- dwarf2out.c, dwarfout.c, emit-rtl.c, except.c, explow.c, expmed.c,
- expr.c, final.c, flow.c, function.c, gcc.c, getpwd.c, global.c,
- integrate.c, jump.c, local-alloc.c, loop.c, optabs.c, pexecute.c,
- prefix.c, print-rtl.c, print-tree.c, profile.c, real.c, recog.c,
- reg-stack.c, regclass.c, regmove.c, reload.c, reload1.c, reorg.c,
- rtl.c, rtlanal.c, sched.c, sdbout.c, stmt.c, stor-layout.c,
- stupid.c, tlink.c, toplev.c, tree.c, unroll.c, varasm.c,
- xcoffout.c: Include system.h. Organize include ordering so
- that stdarg/varargs comes before other system headers. Remove
- spurious casts of functions assured of a prototype in system.h.
+ * config/m68k/m68k.h: Declare output_function_epilogue.
+ * recog.h: Declare next_insn_tests_no_inequality.
-Fri Mar 20 11:19:40 1998 Stan Cox <scox@equinox.cygnus.com>
+Fri Jan 8 01:43:53 1999 Jeffrey A Law (law@cygnus.com)
- * reg-stack.c (pop_stack): Define. Pops any register on the
- regstack and adjusts regstack.
- (compare_for_stack_reg): Use pop_stack.
+ * stmt.c (optimize_tail_recursion): New function, extracted from ...
+ (expand_return): Use optimize_tail_recursion.
+ * tree.h (optimize_tail_recursion): Declare.
-Thu Mar 19 23:51:01 1998 Jeffrey A Law (law@cygnus.com)
+ * toplev.c (compile_file): Move call to output_func_start_profiler
+ to after the loop to emit deferred functions.
- * configure.in (hppa1.0-hp-hpux10): Handle threads for this
- config too.
+Thu Jan 7 19:52:53 1999 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-Thu Mar 19 20:30:31 1998 Philippe De Muyter <phdm@macqel.be>
+ * system.h (abort): Supply more detailed information on how to
+ report an Internal Compiler Error.
- * libgcc2.c (exit): Do not call __bb_exit_func if HAVE_ATEXIT.
+Thu Jan 7 09:25:58 1999 Bruce Korb (korb@datadesign.com)
- * fold-const.c (fold): Replace sign-extension of a zero extended
- value by a single zero extension.
+ * fixinc/fixincl.c (*): More decapitalization of variables
+ plus some explanatory comments.
-Thu Mar 19 00:58:07 1998 Jason Merrill <jason@yorick.cygnus.com>
+ * fixinc/Makefile.in fixinc/mkfixinc.sh:
+ When the fixincl program does not work for a certain system,
+ we substitute a shell script. Added user commentary when
+ this happens.
- * except.c (init_eh): Do nothing.
- (save_eh_status): Call init_eh_for_function, not init_eh.
- * function.c (push_function_context_to): Don't call init_emit.
+Thu Jan 7 11:26:17 1999 Mark Mitchell <mark@markmitchell.com>
-Thu Mar 19 13:39:52 1998 Michael Meissner <meissner@cygnus.com>
+ * calls.c (store_unaligned_arguments_into_pseudos): Use xmalloc to
+ allocate memory that will live beyond this function.
+ (expand_call): Free it here.
- * rs6000/sysv4.h (RELATIVE_PREFIX_NOT_LINKDIR): Undef for System V
- and EABI.
+Thu Jan 7 03:08:17 1999 Richard Henderson <rth@cygnus.com>
-Thu Mar 19 10:10:36 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * sparc.h (PREFERRED_RELOAD_CLASS): Select GENERAL_REGS for
+ integer data not destined for fp regs.
+ (LEGITIMIZE_RELOAD_ADDRESS): New.
- * final.c (shorten_branches): Add parentheses around +/- in
- operand of &.
+Thu Jan 7 03:03:42 1999 Stan Cox <scox@cygnus.com>
+ Richard Henderson <rth@cygnus.com>
- * flow.c (life_analysis): Wrap variable `i' in macro ELIMINABLE_REGS.
+ Support for Hypersparc and Sparclite86x:
+ * sparc.h (TARGET_CPU_hypersparc, TARGET_CPU_sparclite86x): New.
+ (CPP_CPU32_DEFAULT_SPEC): Fix up for the new targets.
+ (ASM_CPU32_DEFAULT_SPEC): Likewise.
+ (TARGET_CPU_DEFAULT): Likewise.
+ (enum processor_type): Likewise.
+ (CPP_ENDIAN_SPEC): Handle little endian data.
+ (LIBGCC2_WORDS_BIG_ENDIAN): Likewise.
+ (ADJUST_COST): Call sparc_adjust_cost.
+ * sparc.c (sparc_override_options): Fix up for the new targets.
+ (supersparc_adjust_cost): Make static.
+ (hypersparc_adjust_cost): New.
+ (ultrasparc_adjust_cost): Make static.
+ (sparc_adjust_cost): New.
+ * sparc.md (attr cpu): Add hypersparc and sparclite86x.
+ (function_unit): Add hypersparc scheduling rules.
-Thu Mar 19 09:15:17 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * configure.in (with_cpu handler): Recognize hypersparc.
- * regclass.c (memory_move_secondary_cost): Wrap uses of
- SECONDARY_INPUT_RELOAD_CLASS and SECONDARY_OUTPUT_RELOAD_CLASS
- with #ifdef tests.
+Thu Jan 7 23:54:05 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Thu Mar 19 09:06:35 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * config/c4x/c4x.c: Added space after negation operator.
+ * config/c4x/c4x.h: Likewise.
+ * config/c4x/c4x.md: Likewise.
- * config/m68k/m68k.md (addqi3): Fix typo gen_INT vs. GEN_INT.
+Thu Jan 7 23:39:27 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * flow.c (life_analysis): #include <sys/types.h> to make sure
- size_t is defined.
- * cplus-dem.c (demangle_function_name): Likewise.
+ * config/c4x/c4x.c (c4x_preferred_reload_class): Always return class.
-Thu Mar 19 09:00:01 1998 Manfred Hollstein <manfred@s-direktnet.de>
+Thu Jan 7 00:29:25 1999 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * final.c (insn_noperands): Change type to unsigned int.
- (final_scan_insn): Likewise for noperands;
- properly check operand number boundaries.
+ * combine.c (num_sign_bit_copies): In NEG, MULT, DIV and MOD cases,
+ when a test can't be performed due to limited width of
+ HOST_BITS_PER_WIDE_INT, use the more conservative approximation.
+ Fix UDIV case for cases where the first operand has the highest bit
+ set.
+
+Thu Jan 7 00:01:38 1999 Lutz Vieweg <lkv@mania.robin.de>
+
+ * pa.h (reg_class): Add FPUPPER_REGS.
+ (REG_CLASS_NAMES): Similarly.
+ (REG_CLASS_CONTENTS): Similarly.
+ (REGNO_REG_CLASS): Handle FPUPPER_REGS.
+ (FP_REG_CLASS_P): Likewise.
+ (REG_CLASS_FROM_LETTER): Similarly.
+ (CLASS_MAX_NREGS): Similarly.
-Wed Mar 18 16:20:30 1998 Richard Henderson <rth@cygnus.com>
+1999-01-06 Brendan Kehoe <brendan@cygnus.com>
- * alpha.md (extzv): Don't reject register operands. Fix
- mode of operand 1.
+ * fixincludes: For HP/UX 10.20, also look in curses_colr/curses.h
+ for a typedef of bool. Make sure to have a copy of the file is
+ in place before we look to fix it. Fix typo in variable name to
+ FILE.
-Wed Mar 18 16:14:23 1998 Richard Henderson <rth@cygnus.com>
+Wed Jan 6 07:51:05 1999 Richard Henderson <rth@cygnus.com>
- * dbxout.c (dbxout_function_end): Fix last change. The correct
- predicate is ASM_OUTPUT_SECTION_NAME.
+ * expr.c (expand_builtin) [case BUILT_IN_CONSTANT_P]: Use
+ value_mode for the return mode.
-Wed Mar 18 12:43:20 1998 Jim Wilson <wilson@cygnus.com>
+Wed Jan 6 17:55:19 1999 Robert Lipe <robertlipe@usa.net>
- * sh.md (ashlsi_c-1): Delete 3rd argument to gen_ashlsi_c.
- (ashlsi): Use match_dup 1 instead of match_operand 2.
+ * configure.in: New flag --with-dwarf2. If set, enables DWARF-2
+ debugging as default.
-Wed Mar 18 13:46:07 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * config/tm-dwarf2.h: New file.
- * fold-const.c (operand_equal_for_comparison_p): See if equal
- when nop conversions are removed.
+Wed Jan 6 16:08:54 1999 Jeffrey A Law (law@cygnus.com)
-Wed Mar 18 13:42:01 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * h8300.h (ASM_OUTPUT_LABELREF): Define.
- * expr.c (expand_expr, case COND_EXPR): If have conditional move,
- don't use ORIGINAL_TARGET unless REG.
+ * pa.h (DONT_RECORD_EQUIVALENCE): Kill.
+ * local-alloc.c (update_equiv_regs): Corresponding changes.
+ * tm.texi (DONT_RECORD_EQUIVALENCE): Kill.
-Wed Mar 18 16:53:19 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * calls.c (special_function_p): Push alloca test inside the large
+ conditional which excludes functions not at file scope or not
+ extern.
- * netbsd.h (ASM_OUTPUT_ALIGN): Redefine.
+ * calls.c (special_function_p): New function broken out of
+ expand_call.
+ (precompute_register_parameters): Likewise.
+ (store_one_arg): Likewise.
+ (store_unaligned_argumetns_into_pseudos): Likewise.
+ (save_fixed_argument_area): Likewise.
+ (restore_fixed_argument_area): Likewise.
+ (expand_call): Corresponding changes.
-Wed Mar 18 12:43:20 1998 Jim Wilson <wilson@cygnus.com>
+Thu Jan 7 00:12:24 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * loop.c (struct movable): New field move_insn_first.
- (scan_loop): In consec sets code, set it. Clear it otherwise.
- (move_movables): In consec sets code, use it. Copy REG_NOTES from
- p to i1 only if i1 does not have REG_NOTES. Delete obsolete ifdefed
- out code.
+ * config/c4x/c4x.md (addqi3): If the destination operand is
+ a hard register other than an extended precision register,
+ emit addqi3_noclobber.
+ (*addqi3_noclobber_reload): New pattern added so that reload
+ will recognize a store of a pseudo, equivalent to the sum
+ of the frame pointer and a constant, as an add insn.
-Wed Mar 18 09:52:56 1998 Richard Henderson <rth@cygnus.com>
+1999-01-06 Manfred Hollstein <manfred@s-direktnet.de>
- * rtl.c (read_rtx): Fall back on homebrew atoll if HOST_WIDE_INT
- is large, and the system doesn't provide atoll or atoq.
- (atoll): New.
+ * fixinc/fixincl.c: Re-indent according to the GNU standards.
+ fixinc/server.c: Likewise.
+ fixinc/server.h: Likewise.
- * alpha/xm-vms.h (HAVE_ATOLL): Define.
- Reported by Klaus Kaempf <kkaempf@progis.de>.
+Wed Jan 6 10:43:29 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Wed Mar 18 09:56:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * config/m68k/m68k.c (const_uint32_operand): Remove CONSTANT_P_RTX
+ handling.
+ (const_sint32_operand): Likewise.
- * c-lang.c (finish_file): Wrap variable `void_list_node' with macro
- test !ASM_OUTPUT_CONSTRUCTOR || !ASM_OUTPUT_DESTRUCTOR.
+Wed Jan 6 09:44:51 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * calls.c (emit_call_1): Wrap variable `already_popped' with macro
- test !ACCUMULATE_OUTGOING_ARGS.
+ * toplev.h: In addition to checking _JBLEN, also check if `setjmp'
+ is a macro when deciding if we can use `jmp_buf' in prototypes.
- * collect2.c (write_c_file_glob): Wrap function definition in
- macro test !LD_INIT_SWITCH.
+Wed Jan 6 03:18:53 1999 Mark Elbrecht <snowball3@usa.net>
- * combine.c (try_combine): Wrap variables `cc_use' and
- `compare_mode' in macro test EXTRA_CC_MODES.
+ * configure.in (pc-msdosdjgpp): Set x_make to x-go32.
+ * configure: Rebuilt.
+ * i386/xm-go32.h: Define LIBSTDCXX.
+ * i386/x-go32: New.
+ * i386/go32.h (MD_EXEC_PREFIX): Define.
+ (FILE_NAME_ABSOLUTE_P): Define.
+ (LINK_COMMAND_SPEC): Define.
- * cpplib.c (do_ident): Remove unused variable `len'.
- (skip_if_group): Remove unused variables `at_beg_of_line' and
- `after_ident'.
- (cpp_get_token): Remove unused variable `dummy'.
+Wed Jan 6 02:23:36 1999 "Charles M. Hannum" <root@ihack.net>
- * dbxout.c (scope_labelno): Move static variable definition inside
- the one function scope where it is used.
- (dbxout_function_end): Wrap prototype and definition in
- macro test !NO_DBX_FUNCTION_END.
+ * expr.c (store_expr): If the lhs is a memory location pointed
+ to be a postincremented (or postdecremented) pointer, always
+ force the rhs to be evaluated into a pseudo.
- * dwarf2out.c (add_subscript_info): Wrap variable `dimension_number'
- in macro test !MIPS_DEBUGGING_INFO.
+Wed Jan 6 00:54:21 1999 Geoff Keating <geoffk@ozemail.com.au>
- * expr.c (expand_builtin_setjmp): Move declaration of variable `i'
- into the scope where it is used. Wrap empty else-statement body
- in braces.
+ * real.c (mtherr): Print more reasonable warning messages.
- * fix-header.c: Fix typo in comment.
- (inf_skip_spaces): Cast results of INF_UNGET to (void).
- (check_protection, main): Likewise.
+Tue Jan 5 21:57:42 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * flow.c (find_basic_blocks_1): Remove dangling comment text.
+ * Makefile.in (gcc.o, prefix.o, cccp.o, cpplib.o): Depend on prefix.h.
- * function.c (contains): Wrap prototype and definition in macro
- test HAVE_prologue || HAVE_epilogue.
- (fixup_var_refs_1): Remove unused variable `width'.
+ * cccp.c: Include prefix.h, don't prototype prefix.c functions.
+ (new_include_prefix): Constify char* parameters.
- * gen-protos.c (main): Remove unused variable `optr'.
+ * cppfiles.c (read_name_map): Likewise.
+ (append_include_chain): Likewise. Also, use a writable char* copy
+ of parameter `dir' which we then modify, rather than using the
+ parameter itself to store the new writable string.
+ (remap_filename): Constify some variables. Also, use a writable
+ char* to store an allocated string which we will be modifying.
- * haifa-sched.c (debug_control_flow): Remove unused variable `j'.
+ * cpplib.c: Include prefix.h, don't prototype prefix.c functions.
+ (cpp_start_read): Constify variable `str'.
- * libgcc2.c (__udiv_w_sdiv): Provide dummy return value of 0.
- (__sjpopnthrow): Remove unused variable `jmpbuf'.
- (__throw): Remove unused variable `val'.
+ * cpplib.h (append_include_chain): Constify a char* parameter.
- * protoize.c: Check for a previously existing definition before
- defining *_OK macros.
+ * gcc.c Include prefix.h, don't prototype prefix.c functions.
+ (add_prefix, save_string): Constify char* parameters.
+ (fatal, error): Add ATTRIBUTE_PRINTF_1 to prototypes.
- * scan-decls.c (scan_decls): Remove unused variable `old_written'.
+ * prefix.c: Include prefix.h.
+ (get_key_value, translate_name, save_string, update_path,
+ set_std_prefix): Constify various char* parameters and variables.
+ (save_string): Use xmalloc, not malloc.
+ (translate_name): Use a writable temporary variable to create and
+ modify a string before setting it to a const char*.
-Tue Mar 17 00:45:48 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * prefix.h: New file to prototype functions exported from prefix.c.
- * vax.h (ADDR_VEC_ALIGN): Define.
+Tue Jan 5 08:52:18 1999 Bruce Korb (korb@datadesign.com)
-Mon Mar 16 15:57:17 1998 Michael Meissner <meissner@cygnus.com>
+ * fixinc/fixincl.c (various): Added debug code so
+ Manfred can trace the processing.
- * gcc.c (default_arg): Don't wander off the end of allocated
- memory.
+ * fixinc/inclhack.def (sys/utsname.h): Provide forward declaration of
+ struct utsname on Ultrix V4.[35].
- (From Geoffrey Keating <geoffk@ozemail.com.au>)
- * rs6000.c (small_data_operand): Ensure that any address
- referenced relative to the small data area is inside the SDA.
+ * fixinc/{fixincl.x|fixincl.sh|inclhack.sh} : Regenerated.
-Mon Mar 16 12:55:15 1998 Jim Wilson <wilson@cygnus.com>
+Mon Jan 4 15:37:30 1999 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * config/m68k/netbsd.h (ASM_SPEC): Add %{m68060}.
+ * cpplib.c (skip_if_group): Split out the logic that handles
+ directive recognition to its own function. Don't use
+ parse markers; use a bare pointer into the buffer. Use
+ copy/skip_rest_of_line instead of doing it by hand. Remove
+ `return on any directive' mode which was never used, and take
+ only one argument.
+ (consider_directive_while_skipping): New function, subroutine
+ of skip_if_group. Logic streamlined a bit.
+ (conditional_skip, do_elif, do_else): Call skip_if_group with
+ only one argument.
-Mon Mar 16 15:50:20 EST 1998 Andrew MacLeod <amacleod@cygnus.com>
+Mon Jan 4 15:27:30 1999 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * except.h (in_same_eh_region): New prototype.
- (free_insn_eh_region, init_insn_eh_region): New prototypes.
- * except.c (insn_eh_region, maximum_uid): New static variables.
- (set_insn_eh_region): New static function to set region numbers.
- (free_insn_eh_region): New function to free EH region table.
- (init_insn_eh_region): New function to initialize EH region table.
- (in_same_eh_region): New function used to determine if two rtl
- instructions are in the same exception region or not.
- * final.c (final): Initialize the table indicating which instructions
- belong in which exception region.
- * genpeep.c (main): Add "except.h" to include file list in generated
- file insn-peep.c.
- * config/sparc/sparc.md: Add calls to 'in_same_eh_region' in 4
- peepholes involving calls and unconditional branches.
+ * cpplib.c (do_undef): EOF immediately after '#undef FOO' is not an
+ error.
-Mon Mar 16 11:16:50 1998 Jim Wilson <wilson@cygnus.com>
+Mon Jan 4 11:55:51 1999 Jason Merrill <jason@yorick.cygnus.com>
- * README.gnat: New file.
+ * extend.texi (Bound member functions): Document.
-Mon Mar 16 11:14:20 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Mon Jan 4 11:01:48 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * config/m68k/m68k.c: Include <stdlib.h> for atoi. Include
- "recog.h" for offsettable_memref_p.
- (legitimize_pic_address): Remove unused variable `offset'.
- (notice_update_cc): Change return type to void. Add default label
- to switch.
- (standard_68881_constant_p): Remove unused variable mode.
- (print_operand): Define local variable i only if SUPPORT_SUN_FPA.
- (const_int_cost): Explicitly declare as returning int.
- (output_dbcc_and_branch): Change return type to void.
+ * mips-tdump.c (st_to_string, sc_to_string, glevel_to_string,
+ lang_to_string, type_to_string): Make return type const char*.
+ (print_symbol): Apply `const' keyword to a char*.
+ (print_file_desc): Cast structure member `crfd' to ulong when
+ comparing against one.
- * config/m68k/linux.h, config/m68k/m68k.md, config/m68k/m68k.c,
- config/m68k/m68k.h: Replace gen_rtx (XXX, ...) with gen_rtx_XXX
- (...). Use GEN_INT instead of gen_rtx_CONST_INT.
+ * mips-tfile.c (pfatal_with_name): Apply `const' keyword to char*.
+ (fatal, error): Add ATTRIBUTE_PRINTF_1 to prototypes.
+ (progname, input_name): Apply `const' keyword to a char*.
+ Don't redundantly include sys/stat.h.
+ (alloc_info): Apply `const' keyword to a char*.
+ (st_to_string, sc_to_string): Likewise.
+ (hash_string): Cast variable `hash_string' to a symint_t when
+ comparing against one.
+ (add_string): Cast PAGE_USIZE to Ptrdiff_t when comparing against one.
+ Likewise cast it to long when comparing against one.
+ (add_local_symbol): Apply `const' keyword to a char*.
+ (add_ext_symbol): Likewise.
+ (add_unknown_tag): Likewise.
+ (add_procedure): Cast a printf-style field width to an int.
+ (add_file): Cast PAGE_USIZE to long when comparing against one.
+ (parse_begin): Cast a printf-style field width to an int.
+ (parse_bend): Likewise.
+ (parse_def): Likewise.
+ (parse_end): Likewise.
+ (mark_stabs): Mark parameter `start' with ATTRIBUTE_UNUSED.
+ (parse_stabs_common): Fix format specifier.
+ (parse_input): Change type of variable `i' to Size_t.
+ (write_object): Fix arguments to match format specifiers.
+ Cast variable `num_write' to long when comparing against one.
+ (read_seek): Cast variable `sys_read' to symint_t when comparing
+ against one. Fix arguments to match format specifiers. Cast
+ variable `size' to long when comparing against one.
+ (copy_object): Cast result of `sizeof' to int when comparing
+ against one. Fix arguments to match format specifiers. Cast
+ variable `ifd' to long when comparing against a signed value.
+ Likewise, likewise.
-Sun Mar 15 22:30:44 PST 1998 Jeff Law (law@cygnus.com)
+Mon Jan 4 10:30:33 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * c-common.c (decl_attributes): Allow applying attribute `unused'
+ on a LABEL_DECL.
+
+ * c-parse.in (label): Parse attributes after a label, and call
+ `decl_attributes' to handle them.
+
+ * gansidecl.h (ATTRIBUTE_UNUSED_LABEL): Define.
+
+ * genrecog.c (OUTPUT_LABEL, write_tree_1, write_tree): When
+ generating labels, mark them with ATTRIBUTE_UNUSED_LABEL.
+
+ * invoke.texi: Note that labels can be marked `unused'.
+
+Sun Jan 3 23:32:18 1999 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Fri Mar 13 11:30:12 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Sun Jan 3 23:00:42 1999 Jeffrey A Law (law@cygnus.com)
- * config/m68k/m68k.h (CONST_OK_FOR_LETTER_P): Fix logic in range
- check for 'M' constraint.
+ * optabs.c (emit_cmp_and_jump_insns): Use CONSTANT_P canonicalizing
+ RTL for a compare/jump sequence.
-Thu Mar 12 14:47:14 1998 Jim Wilson <wilson@cygnus.com>
+Sun Jan 3 22:58:15 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * cccp.c (create_definition): If pedantic, call pedwarn for macro
- varargs feature.
+ * optabs.c (emit_cmp_insn): Abort if asked to emit non-canonical RTL
+ for a target with HAVE_cc0 defined.
+ (emit_cmp_and_jump_insns): New function.
+ * expr.h (emit_cmp_and_jump_insns): Prototype it.
+ * loop.c (check_dbra_loop): Use it to replace calls
+ to emit_cmp_insn and emit_jump_insn and to canonicalize
+ the comparison if necessary.
+ * unroll.c (unroll_loop): Likewise.
-Thu Mar 12 13:43:25 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
+Sun Jan 3 21:01:04 1999 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- * i386.c (ix86_logical_operator): New function.
- (split_di): Ensure that when a MEM is split, the resulting MEMs have
- SImode.
- * i386.md (anddi3, xordi3, iordi3): New patterns. Add a define_split
- to implement them.
+ * fixincludes (sys/utsname.h): Provide forward declaration of
+ struct utsname on Ultrix V4.[35].
-Thu Mar 12 15:13:16 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- Richard Earnshaw <rearnsha@arm.com>
- Nick Clifton <nickc@cygnus.com>
+ * mips.md (div_trap): Use local labels instead of dot-relative
+ branches.
- * tm.texi (DEFAULT_RTX_COSTS): Document new macro.
+Sun Jan 3 20:40:34 1999 Jeffrey A Law (law@cygnus.com)
- * arm.h (DEFAULT_RTX_COSTS): Define instead of RTX_COSTS.
+ * pa.md (branch, negated branch): Handle (const_int 0) as first
+ source operand.
+ * pa.c (output_cbranch): Likewise.
- * cse.c (rtx_cost): Provide a default case in an enumeration
- switch, and call DEFAULT_RTX_COSTS if it's defined.
+Sun Jan 3 03:20:38 1999 David Edelsohn <edelsohn@gnu.org>
-Thu Mar 12 10:02:38 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * rs6000.c (rs6000_stack_info): Undo spurious part of last
+ change.
- * basic-block.h (compute_preds_succs): Change return type in
- prototype to void.
- * flow.c (compute_preds_succs): Likewise in function definition.
+1999-01-01 Manfred Hollstein <manfred@s-direktnet.de>
- * regmove.c (find_matches): Cast char used as array index to unsigned char
- to supress warning.
+ * extend.texi (__builtin_constant_p): Add missing @smallexample.
-Thu Mar 12 09:39:40 1998 Manfred Hollstein <manfred@s-direktnet.de>
+Fri Jan 1 11:48:20 1999 Jeffrey A Law (law@cygnus.com)
- * i386.h (RTX_COSTS): Insert braces around nested if.
- (ADDITIONAL_REGISTER_NAMES): Insert braces around structured
- elements.
+ * i386.md (doubleword shifts): Fix dumb mistakes in previous change.
- * gcc.c (default_compilers): Properly put brackets around array elements in
- initializer.
+Wed Dec 30 23:38:55 1998 Jeffrey A Law (law@cygnus.com)
- * getopt.c (_getopt_internal): Add explicit braces around nested if;
- reformatted.
+ * m68k.md (adddi_dilshr32): Allow all operands to be registers too.
+ (adddi_dishl32): Similarly.
- * reg-stack.c (record_asm_reg_life): Add explicit braces around nested if's.
- (record_reg_life_pat): Add explicit parens around && and || in expression.
- (stack_reg_life_analysis): Add parens around assignment used as expression.
- (convert_regs): Likewise.
+ * cse.c (invalidate_skipped_block): Call invalidate_from_clobbers
+ for each insn in the skipped block.
+
+ * reload1.c (reload_as_needed): Verify that the insn satisfies its
+ constraints after replacing a register address with an autoincrement
+ address for reload inheritance purposes.
+
+ * i386.md (doubleword shifts): Avoid namespace pollution.
+
+Wed Dec 30 23:00:28 1998 David O'Brien <obrien@NUXI.com>
+
+ * configure.in (FreeBSD ELF): Needs special crt files.
+
+Wed Dec 30 22:50:13 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * i386/xm-cygwin.h: Change DIR_SEPARATOR to forward slash.
+
+1998-12-30 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * loop.c (check_dbra_loop): While reversing the loop, if the
+ comparison value has a VOID mode use the mode of the other operand
+ to compute the mask.
+
+Wed Dec 30 22:24:00 1998 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000.md ({save,restore}_stack_function): Take 2 operands to
+ avoid warnings in compiling explow.c.
+
+ (patch from Ken Raeburn, raeburn@cygnus.com)
+ * rs6000.c (rs6000_stack_info): Force 8-byte alignment of
+ fpmem_offset. Compute total size after that, and then
+ rs6000_fpmem_offset using both values.
+
+Mon Dec 28 19:26:32 1998 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * gcc.texi (Non-bugs): ``Empty'' loops will be optimized away in
+ the future; indeed that already happens in some cases.
-Thu Mar 12 09:25:29 1998 Manfred Hollstein <manfred@s-direktnet.de>
+Tue Dec 29 11:58:53 1998 Richard Henderson <rth@cygnus.com>
- * bitmap.c (bitmap_element_allocate): Remove unused parameter;
- change callers accordingly.
+ * sparc.c (input_operand): Recognize (const (constant_p_rtx)).
+ (arith_operand): Remove constant_p_rtx handling.
+ (const64_operand, const64_high_operand): Likewise.
+ (arith11_operand, arith10_operand, arith_double_operand): Likewise.
+ (arith11_double_operand, arith10_double_operand, small_int): Likewise.
+ (small_int_or_double, uns_small_int, zero_operand): Likewise.
+ * sparc.h (PREDICATE_CODES): Likewise.
- * cplus-dem.c (arm_special): Remove unused parameter work in prototype
- and definition; change all callers accordingly.
+ * rtl.h (CONSTANT_P): Remove CONSTANT_P_RTX.
- * except.c (init_eh): Avoid assignment of unused return value of
- build_pointer_type; cast it to void, instead, and remove unused
- variable type.
+Tue Dec 29 11:32:54 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
- * gcc.c (lang_specific_driver): Define prototype only #ifdef
- LANG_SPECIFIC_DRIVER.
- (temp_names): Define only #ifdef MKTEMP_EACH_FILE.
+ * rtl.def (CONSTANT_P_RTX): Clarify commentary.
+ * expr.c (expand_builtin, case BUILT_IN_CONSTANT_P): Rework to
+ consider constant CONSTRUCTOR constant and to defer some cases
+ to cse.
+ * cse.c (fold_rtx, case CONST): Add handling for CONSTANT_P_RTX.
+ * regclass.c (reg_scan_mark_refs, case CONST): Likewise.
- * genoutput.c (output_epilogue): Initialize next_name to 0.
+Tue Dec 29 11:30:10 1998 Richard Henderson <rth@cygnus.com>
- * real.c (efrexp): #if 0 prototype and function definition.
- (eremain): Likewise.
- (uditoe): Likewise.
- (ditoe): Likewise.
- (etoudi): Likewise.
- (etodi): Likewise.
- (esqrt): Likewise.
+ * expr.c (init_expr_once): Kill can_handle_constant_p recognition.
+ * cse.c (fold_rtx, case 'x'): Remove standalone CONSTANT_P_RTX code.
- * reload.c (push_secondary_reload): Define prototype only
- #ifdef HAVE_SECONDARY_RELOADS.
+ * alpha.c (reg_or_6bit_operand): Remove CONSTANT_P_RTX handling.
+ (reg_or_8bit_operand, cint8_operand, add_operand): Likewise.
+ (sext_add_operand, and_operand, or_operand): Likewise.
+ (reg_or_cint_operand, some_operand, input_operand): Likewise.
+ * alpha.h (PREDICATE_CODES): Likewise.
+
+Sat Dec 26 23:26:26 1998 Jeff Law (law@cygnus.com)
+
+ * version.c: Bump for snapshot.
+
+Sat Dec 26 09:17:04 1998 Jeffrey A Law (law@cygnus.com)
- * varasm.c (assemble_static_space): Define rounded only
- #ifndef ASM_OUTPUT_ALIGNED_LOCAL.
+ * gengenrtl.c (gencode): Always use bzero to clear memory instead
+ of dangerous casts and stores.
-Thu Mar 12 09:11:35 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * Makefile.in (compare, gnucompare): Add missing else true clauses.
- * i386.md (andsi): Add default case in enumeration switch.
- (iorsi3): Likewise.
- (iorhi3): Likewise.
- (xorsi3): Likewise.
+Fri Dec 25 23:00:56 1998 Jeffrey A Law (law@cygnus.com)
-Thu Mar 12 08:37:02 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * alpha.md (builtin_longjmp): Add missing "DONE".
- * c-decl (finish_struct): Change type of min_align to unsigned.
+Thu Dec 24 10:39:57 1998 Stan Cox <scox@cygnus.com>
- * cplus-dem.c (demangle_function_name): Change type of variable i to size_t;
- remove unused variable len.
+ * gcc.c (execute): Enable -pipe with win32.
- * dwarf2out.c (reg_save): Add explicit cast of -1 to unsigned and a
- comment indicating this is proper behaviour.
- (reg_loc_descriptor): Remove redundant comparison of unsigned variable
- reg >= 0.
- (based_loc_descr): Likewise.
+Wed Dec 23 10:27:44 1998 Nick Clifton <nickc@cygnus.com>
- * enquire.c (bitpattern): Change type of variable i to unsigned.
+ * config/arm/t-arm-elf: Add multiplib option for leading
+ underscores.
- * final.c (output_asm_insn): Don't cast insn_noperands to unsigned.
+ * config/arm/thumb.h (ASM_OUTPUT_LABELREF): Use variable
+ 'user_label_prefix' rather than macro USER_LABEL_PREFIX.
- * flow.c (life_analysis): Change type of variable i to size_t;
- remove unused variable insn.
+ (thumb_shiftable_const): Use macro 'BASE_REG_CLASS' rather
+ than variable 'reload_address_base_reg_class'. [Note this
+ change is unrelated to the others in this patch].
- * gcc.c (translate_options): Change type of variables optlen, arglen and
- complen to size_t.
- (input_filename_length): Change type to size_t.
- (do_spec_1): Change type of variable bufsize to size_t.
- (main): Change type of variables i and j to size_t;
- remove subblock local definition of variable i.
- (lookup_compiler): Change type of second argument to size_t;
- change type of variable i to size_t.
+ * config/arm/unknown-elf.h (USER_LABEL_PREFIX): Default to no
+ leading underscore.
- * genemit.c (output_init_mov_optab): Change type of variable i to size_t.
+Wed Dec 23 09:51:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * genopinit.c (get_insn): Change type of variable pindex to size_t.
+ * alias.c (record_alias_subset): Remove ignored `&'.
+ (init_alias_once): Likewise.
- * genrecog.c (add_to_sequence): Change type of variable i to size_t.
+ * c-lex.c (UNGETC): Cast first argument of comma expression to void.
- * global.c (global_alloc): Change type of variable i to size_t.
+ * config/mips/mips.c (mips_asm_file_end): Cast the result of
+ fwrite to `int' when comparing against one.
- * regclass.c (init_reg_sets): Change type of variables i and j to unsigned.
+ * config/mips/mips.h (CAN_ELIMINATE): Add parens around && within ||.
+ (INITIAL_ELIMINATION_OFFSET): Add braces to avoid ambiguous `else'.
- * stmt.c (expand_end_bindings): Change type of variable i to size_t.
- (expand_end_case): Change type of variable count to size_t.
+ * cse.c (rehash_using_reg): Change type of variable `i' to
+ unsigned int.
- * toplev.c (main): Change type of variable j to size_t.
- (set_target_switch): Change type of variable j to size_t.
- (print_switch_values): Change type of variable j to size_t;
- remove unused variable flags.
+ * dwarf2out.c (initial_return_save): Cast -1 to unsigned before
+ assigning it to one.
- * varasm.c (assemble_variable): Change type of variable align to size_t.
- (const_hash_rtx): Change type of variable i to size_t.
+ * except.c (duplicate_eh_handlers): Remove unused variable `tmp'.
-1998-03-11 Mark Mitchell <mmitchell@usa.net>
+ * final.c (final_scan_insn): Likewise for variable `i'.
+ (output_asm_insn): Cast a char to unsigned char when used as an
+ array index.
- * dbxout.c (dbxout_type_methods): Only treat TYPE_METHODS as a
- TREE_VEC if that's what it really is.
+ * gcse.c (compute_pre_ppinout): Cast -1 to SBITMAP_ELT_TYPE when
+ assigning it to one.
-Wed Mar 11 15:16:01 1998 Michael Meissner <meissner@cygnus.com>
+ * loop.c (strength_reduce): Remove unused variables `count' and `temp'.
- * {haifa-,}sched.c (rank_for_schedule): Only take void * arguments
- as per ISO C spec.
+ * recog.c (preprocess_constraints): Cast a char to unsigned char
+ when used as an array index.
-Wed Mar 11 12:05:20 1998 Teemu Torma <tot@trema.com>
+ * regmove.c (find_matches): Likewise.
- * gthr.h: Changed the comment about return values.
- * gthr-solaris.h (__gthread_once): Do not use errno; return the
- error number instead of -1.
- (__gthread_key_create): Any non-zero return value is an error.
- * libgcc2.c (eh_context_initialize): Check for non-zero return
- value from __gthread_once.
- Check that the value of get_eh_context was really changed.
+ * reload1.c (calculate_needs): Add default case in switch.
+ (eliminate_regs_in_insn): Initialize variable `offset'.
+ (set_offsets_for_label): Change type of variable `i' to unsigned.
+ (reload_as_needed): Wrap variable `i' in macro check on
+ AUTO_INC_DEC || INSN_CLOBBERS_REGNO_P.
-Wed Mar 11 18:26:25 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * scan-decls.c (scan_decls): Mark parameters `argc' and `argv'
+ with ATTRIBUTE_UNUSED. Cast variable `start_written' to size_t
+ when comparing against one.
- * sh.h (LOOP_ALIGN): Only align when optimizing.
- * sh.c (find_barrier): Clear inc for CODE_LABELs.
- When not optimizing, calculate alignment for BARRIERs directly.
+ * stor-layout.c (layout_decl): Cast maximum_field_alignment to
+ unsigned when comparing against one. Likewise for
+ GET_MODE_ALIGNMENT().
+ (layout_record): Cast record_align to int when comparing against a
+ signed value.
+ (layout_type): Cast TYPE_ALIGN() to int when comparing against a
+ signed value.
-Wed Mar 11 15:07:18 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * tree.c (get_identifier): Cast variable `len' to unsigned when
+ comparing against one.
+ (maybe_get_identifier): Likewise
- * final.c (shorten_branches): Remove conditionalizing on
- SHORTEN_WITH_ADJUST_INSN_LENGTH
- * sh.h, pa.h (SHORTEN_WITH_ADJUST_INSN_LENGTH): Remove.
+Wed Dec 23 00:10:01 1998 Jeffrey A Law (law@cygnus.com)
-Wed Mar 11 02:37:41 1998 Jeffrey A Law (law@cygnus.com)
+ * toplev.c (rest_of_compilation): Do not set reload_completed.
+ * reload1.c (reload): Set reload_completed before calling
+ cleanup_subreg_operands.
- * flow.c (find_basic_blocks_1): Keep the cfg accurate when removing
- an unconditional jump around deleted blocks.
+Tue Dec 22 23:58:31 1998 Richard Henderson <rth@cygnus.com>
-Mon Mar 9 12:02:23 1998 Jim Wilson <wilson@cygnus.com>
+ * reload1.c (emit_reload_insns): Check `set' not null before use.
- * profile.c (branch_prob): If see computed goto, call fatal instead of
- abort.
+Tue Dec 22 15:15:45 1998 Nick Clifton <nickc@cygnus.com>
- * config/mips/sni-svr4.h (CPP_PREDEFINE): Add -DSNI and -Dsinix.
+ * rtlanal.c (multiple_sets): Change type of 'found' from 'rtx' to
+ 'int'.
- * configure.in (alpha-dec-osf): Add default case for osf* to switch.
- Patch from Bruno Haible.
+Tue Dec 22 13:55:44 1998 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
- * function.c (put_reg_into_stack): Copy MEM_IN_STRUCT_P from new.
- (assign_parms): Set aggregate if hide_last_arg and last_named.
+ * halfpic.c (half_pic_encode): Delete redundant code.
-Mon Mar 9 19:57:56 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Tue Dec 22 13:02:22 1998 Michael Meissner <meissner@cygnus.com>
- * final.c (shorten_branches): Initialize insn_addresses.
+ * toplev.c (main): Delete handling of -dM as a preprocessor
+ option.
-Mon Mar 9 14:10:23 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Dec 21 17:39:38 1998 Michael Meissner <meissner@cygnus.com>
- * sh.h (MUST_PASS_IN_STACK): Define.
+ * toplev.c (main): Don't emit any warnings when using -dD, -dM, or
+ -dI, which are handled by the preprocessor.
-Sun Mar 8 13:01:56 1998 Jeffrey A Law (law@cygnus.com)
+Sun Dec 20 16:13:44 1998 John F. Carr <jfc@mit.edu>
- * final.c (shorten_branches): Fix minor logic error in
- ADDR_DIFF_VEC shortening support.
+ * configure.in: Handle Digital UNIX 5.x the same as 4.x.
+ * i386/sol2.h: Define LOCAL_LABEL_PREFIX as ".".
-Sun Mar 8 02:17:42 PST 1998 Jeff Law (law@cygnus.com)
+Sun Dec 20 07:39:52 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Sat Mar 7 00:54:15 1998 Jeffrey A Law (law@cygnus.com)
-
- * haifa-sched.c (is_cfg_nonregular): Change return type to
- an int. No longer compute "estimated" number of edges. Use
- computed_jump_p instead of duplicating the code. Fixup/add
- some comments.
- (build_control_flow): Returns a value indicating an irregularity
- in the cfg was detected. Count the number of edges in the cfg.
- allocate various edge tables.
- (find_rgns): No longer look for unreachable blocks.
- (schedule_insns): Do not allocate memory for edge tables here.
- Free memory for edge tables before returning. Do not perform
- cross block scheduling if build_control_flow returns nonzero.
- * flow.c (compute_preds_succs): More accurately determine when
- a block drops in.
-
- * basic-block.h (free_basic_block_vargs): Provide prototype.
-
- * cccp.c (main): Fix dumb mistakes in last change.
-
-Fri Mar 6 21:28:45 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * rtl.h (addr_diff_vec_flags): New typedef.
- (union rtunion_def): New member rt_addr_diff_vec_flags.
- (ADDR_DIFF_VEC_FLAGS): New macro.
-
- * sh.c (output_branch): Fix offset overflow problems.
-
- * final.c (shorten_branches): Implement CASE_VECTOR_SHORTEN_MODE.
- (final_scan_insn): New argument BODY for ASM_OUTPUT_ADDR_DIFF_ELT.
- * rtl.def (ADDR_DIFF_VEC): Three new fields (min, max and flags).
- * stmt.c (expand_end_case): Supply new arguments to
- gen_rtx_ADDR_DIFF_VEC.
- * 1750a.h (ASM_OUTPUT_ADDR_DIFF_ELT): New argument BODY.
- * alpha.h, arc.h, clipper.h, convex.h : Likewise.
- * dsp16xx.h, elxsi.h, fx80.h, gmicro.h, h8300.h : Likewise.
- * i370.h, i386.h, i860.h, i960.h, m32r.h, m68k.h, m88k.h : Likewise.
- * mips.h, mn10200.h, mn10300.h, ns32k.h, pa.h, pyr.h : Likewise.
- * rs6000.h, sh.h, sparc.h, spur.h, tahoe.h, v850.h : Likewise.
- * vax.h, we32k.h, alpha/vms.h, arm/aof.h, arm/aout.h : Likewise.
- * i386/386bsd.h, i386/freebsd-elf.h : Likewise.
- * i386/freebsd.h, i386/linux.h : Likewise.
- * i386/netbsd.h, i386/osfrose.h, i386/ptx4-i.h, i386/sco5.h : Likewise.
- * i386/sysv4.h, m68k/3b1.h, m68k/dpx2.h, m68k/hp320.h : Likewise.
- * m68k/mot3300.h, m68k/sgs.h : Likewise.
- * m68k/tower-as.h, ns32k/encore.h, sparc/pbd.h : Likewise.
- * sh.h (INSN_ALIGN, INSN_LENGTH_ALIGNMENT): Define.
- (CASE_VECTOR_SHORTEN_MODE): Define.
- (short_cbranch_p, align_length, addr_diff_vec_adjust): Don't declare.
- (med_branch_p, braf_branch_p): Don't declare.
- (mdep_reorg_phase, barrier_align): Declare.
- (ADJUST_INSN_LENGTH): Remove alignment handling.
- * sh.c (uid_align, uid_align_max): Deleted.
- (max_uid_before_fixup_addr_diff_vecs, branch_offset): Deleted.
- (short_cbranch_p, med_branch_p, braf_branch_p, align_length): Deleted.
- (cache_align_p, fixup_aligns, addr_diff_vec_adjust): Deleted.
- (output_far_jump): Don't use braf_branch_p.
- (output_branchy_insn): Don't use branch_offset.
- (find_barrier): Remove checks for max_uid_before_fixup_addr_diff_vecs.
- Remove paired barrier stuff.
- Don't use cache_align_p.
- Take alignment insns into account.
- (fixup_addr_diff_vecs): Reduce to only fixing up the base label of
- the addr_diff_vec.
- (barrier_align, branch_dest): New function.
- (machine_dependent_reorg, split_branches): Remove infrastructure
- for branch shortening that is now provided in the backend.
- * sh.md (short_cbranch_p, med_branch_p, med_cbranch_p): New attributes.
- (braf_branch_p, braf_cbranch_p): Likewise.
- (attribute length): Use new attributes.
- (casesi_worker): Get mode and unsignednedd from ADDR_DIFF_VEC.
- (addr_diff_vec_adjust): Delete.
- (align_2): Now a define_expand.
- (align_log): Now length 0.
-
-Fri Mar 6 14:41:33 1998 Michael Meissner <meissner@cygnus.com>
-
- * m32r.md (right): Correctly check for length == 2, not 1.
-
-Fri Mar 6 14:00:04 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * mips/mips.h: Prototype `machine_dependent_reorg'.
- (ASM_OUTPUT_ALIGN): Remove unused variable `mask'.
-
-Fri Mar 6 11:43:35 1998 Joern Rennecke (amylaar@cygnus.co.uk)
-
- * final.c (shorten_branches): Restore accidentally removed code.
-
-Fri Mar 6 11:00:49 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-
- * configure.in: Remove duplicate uses of AC_PROG_CC and
- AC_PROG_MAKE_SET.
-
-Fri Mar 6 00:59:30 1998 Richard Henderson <rth@cygnus.com>
-
- * configure.in (target_cpu_default2): Correct typo for alphapca56.
-
-Thu Mar 5 23:24:50 1998 Jeffrey A Law (law@cygnus.com)
- Doug Evans (devans@cygnus.com)
-
- * haifa-sched.c (build_jmp_edges): Delete dead function.
- (build_control_flow): Use cfg routines from flow.c
- (schedule_insns): Remove debugging code accidentally checked
- in earlier today.
-
- * basic-block.h: Add external integer list structures, typdefs,
- accessor macros and function declarations. Simlarly for
- basic block pred/succ support and simple bitmap stuff.
- * flow.c: Add functions for integer list, basic block pred/succ
- support and simple bitmap support.
- (compute_dominators): New function to compute dominators and
- post dominators.
- (find_basic_blocks): Split into two functions.
- (life_analysis): Likewise.
- (flow_analysis): Removed. Now handled by calling find_basic_blocks,
- the life_analysis from toplev.c
- * toplev.c (rest_of_compilation): Call find_basic_blocks, then
- life_analysis instead of flow_analysis.
-
-Thu Mar 5 23:06:26 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * jump.c (jump_optimize): Call mark_jump_label also for deleted
- insns.
- (mark_jump_label): Don't increment ref counts for deleted insns.
-
-Thu Mar 5 09:55:15 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * mips/iris6.h (TARGET_DEFAULT): Parenthesize macro definition.
-
- * mips/mips.c: Include stdlib.h and unistd.h.
- (mips_asm_file_end): Add braces around empty body in an if-statement.
- (function_prologue): Wrap variable `fnname' in
- !FUNCTION_NAME_ALREADY_DECLARED. Correct format specifier in fprintf.
- (mips_select_rtx_section, mips_select_section): Declare as void.
+Sat Dec 19 22:24:22 1998 Jeff Law (law@cygnus.com)
- * mips/mips.h: Add prototypes for extern functions in mips.c.
- (FUNCTION_ARG_REGNO_P): Add parentheses around && within ||.
- (ENCODE_SECTION_INFO): Add braces around empty body in an
- if-statement.
+ * version.c: Bump for snapshot.
- * mips/mips.md (movdi): Add parentheses around && within ||.
- (movsf, movdf): Likewise.
- (branch_zero, branch_zero_di): Add default case in
- enumeration switch.
+Sat Dec 19 21:41:32 1998 Jeff Law (law@cygnus.com)
+ * version.c: Bump for snapshot.
-Thu Mar 5 02:45:48 1998 Richard Henderson <rth@cygnus.com>
+Sat Dec 19 09:52:27 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * genattr.c (fatal): Qualify a char* with the `const' keyword.
+
+ * genattrtab.c (fatal, attr_printf, attr_string, write_attr_set,
+ write_unit_name, write_eligible_delay, expand_units,
+ make_length_attrs, write_attr_case, find_attr,
+ make_internal_attr): Likewise.
+ * gencheck.c (tree_codes): Likewise.
+ * gencodes.c (fatal): Likewise.
+ * genconfig.c (fatal): Likewise.
+ * genemit.c (fatal): Likewise.
+ * genextract.c (fatal, walk_rtx, copystr): Likewise.
+ * genflags.c (fatal): Likewise.
+ * genopinit.c (fatal, optabs, gen_insn): Likewise.
+ * genoutput.c (fatal, error, predicates): Likewise.
+ * genpeep.c (fatal): Likewise.
+ * genrecog.c (fatal, decision, pred_table, add_to_sequence,
+ write_tree_1, write_tree, change_state, copystr, indents): Likewise.
+
+Thu Dec 17 18:21:49 1998 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * configure.in (with-fast-fixincludes): Fix whitespace.
+ * configure: Rebuilt.
- * alpha/alpha.h (TARGET_WINDOWS_NT, TARGET_OPEN_VMS): Just make them
- real constants, since they can't be changed.
- (TARGET_AS_CAN_SUBTRACT_LABELS): New.
- * alpha/alpha.md (builtin_setjmp_receiver): Use it.
- * alpha/osf.h (TARGET_AS_CAN_SUBTRACT_LABELS): New.
- * alpha/osf2or3.h (TARGET_AS_CAN_SUBTRACT_LABELS): New.
- * alpha/vms.h (TARGET_OPEN_VMS): New.
- * alpha/win-nt.h (TARGET_WINDOWS_NT): New.
+ * fixincludes (c_asm.h): Wrap Digital UNIX V4.0B DEC C specific
+ asm() etc. function declarations in __DECC.
-Thu Mar 5 02:41:27 1998 Richard Henderson <rth@cygnus.com>
+Thu Dec 17 13:57:23 1998 Nick Clifton <nickc@cygnus.com>
- * reload.c (find_reloads): Always force (subreg (mem)) to be
- reloaded if WORD_REGISTER_OPERATIONS.
+ * expr.c (emit_move_insn_1): Only emit a clobber if the target
+ is a pseudo register.
-Thu Mar 5 02:14:44 1998 Richard Henderson <rth@cygnus.com>
+Thu Dec 17 13:50:29 1998 Nick Clifton <nickc@cygnus.com>
- * haifa-sched.c (free_list): Rename from free_pnd_lst.
- (free_pending_lists): Rename free_pnd_lst uses.
- (remove_dependence): Place expunged element on unused_insn_list.
- (alloc_INSN_LIST, alloc_EXPR_LIST): New. Change all callers of
- gen_rtx_*_LIST and alloc_rtx to use them.
- (compute_block_backward_dependences): Free the reg_last_* lists.
+ * gcse.c: Include expr.h in order to get the prototype for
+ get_condition() which is used in delete_null_pointer_checks().
-Thu Mar 5 00:05:40 1998 Jeffrey A Law (law@cygnus.com)
+Thu Dec 17 15:58:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * cccp.c (main): Avoid undefined behavior when setting pend_includes
- and pend_files.
+ * hwint.h: New file to consolidate HOST_WIDE_INT (etc) macros.
-Wed Mar 4 21:58:25 1998 Franz Sirl <franz.sirl-kernel@lauterbach.com>
+Thu Dec 17 12:31:12 1998 Jim Wilson <wilson@cygnus.com>
- * rs6000/linux.h: don't define DEFAULT_VTABLE_THUNKS to 1 if
- USE_GNULIBC_1 is defined
- * configure.in: add a new case powerpc-*-linux-gnulibc1 which
- includes the t-linux-gnulibc1 fragment
+ * Makefile.in (INTERNAL_CFLAGS): Add SCHED_CFLAGS.
+ (ALL_CFLAGS): Delete SCHED_CFLAGS.
-Wed Mar 4 12:11:36 1998 Jim Wilson <wilson@cygnus.com>
+1998-12-17 Vladimir N. Makarov <vmakarov@cygnus.com>
- * mips.md (movdf_internal1a): Fix misplaced parenthesis in condition.
+ * config/i60/i960.md (extendqihi2): Fix typo (usage ',' instead of
+ ';').
-Wed Mar 4 18:47:48 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+1998-12-17 Michael Tiemann <tiemann@axon.cygnus.com>
- * final.c (final_scan_insn, case CODE_LABEL: Cleanup.
+ * i960.md (extend*, zero_extend*): Don't generate rtl that looks
+ like (subreg:SI (reg:SI N) 0), because it's wrong, and it hides
+ optimizations from the combiner.
-Wed Mar 4 15:51:19 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Thu Dec 17 08:27:03 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * final.c (shorten_branches): Tag the loop alignment onto the
- first label after NOTE_INSN_LOOP_BEG even if there is an
- intervening insn.
+ * loop.c (combine_givs_used_by_other): Don't depend on n_times_set.
-Tue Mar 3 21:48:35 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Wed Dec 16 17:30:35 1998 Nick Clifton <nickc@cygnus.com>
- * final.c (insn_current_reference_address):
- Use SEQ instead of BRANCH as argument to align_fuzz, to get a
- proper alignment chain.
+ * toplev.c (main): Disable optimize_size if a specific
+ optimization level is requested. Always set optimization
+ level to 2 if -Os is specified.
- * final.c (max_labelno): New static variable.
- (final_scan_insn): Check max_labelno before outputting an
- alignment for a label.
- (shorten_branches): Remove unused variable length_align.
+Wed Dec 16 16:33:04 1998 Dave Brolley <brolley@cygnus.com>
-Tue Mar 3 14:27:23 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * objc/lang-specs.h: Pass -MD, -MMD and -MG to cc1obj if configured with
+ cpplib.
+ * cpplib.c (cpp_start_read): If in_fname is not initialized, try to
+ initialize it using fname.
- * sparc.c (ultrasparc_adjust_cost): Add default case in
- enumeration switch.
+1998-12-16 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * sparc.h: Add prototypes for extern functions defined in
- sparc.c.
+ * cpplib.c (do_include): Treat #include_next in the
+ primary source file as #include plus warning. Treat
+ #include_next in a file included by absolute path as an
+ error. fp == CPP_NULL_BUFFER is a fatal inconsistency.
-Tue Mar 3 10:00:11 1998 Nick Clifton <nickc@cygnus.com>
+Wed Dec 16 12:28:54 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * toplev.c: Only generate <name>.dbr file when dumping RTL if
- DEALY_SLOTS is defined.
+ * cccp.c: Don't define MIN/MAX anymore.
+ * cpplib.c: Likewise.
+ * machmode.h: Likewise.
+ * system.h: Provide definitions for MIN/MAX.
+
+Tue Dec 15 23:47:42 1998 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * fix-header.c: Don't define xstrdup here.
+
+Wed Dec 16 05:11:04 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * loop.c (consec_sets_giv): New argument last_consec_insn.
+ (strength_reduce): Provide / use it.
+
+Wed Dec 16 17:24:07 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Tue Mar 3 07:36:37 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * loop.h (loop_info): New field 'vtop'.
+ * loop.c (check_dbra_loop): Use loop_info->vtop rather than
+ scanning loop for vtop.
+ * unroll.c (subtract_reg_term, find_common_reg_term): New functions.
+ (loop_iterations): Use them to determine if loop has a constant
+ number of iterations. Set loop_info->vtop. Don't subtract
+ common reg term from initial_value and final_value if have a
+ do-while loop.
+
+Tue Dec 15 13:49:55 1998 Jeffrey A Law (law@cygnus.com)
+
+ * mn10200.md (addsi3 expander): Use "nonmemory_operand" for operand 2.
+
+ * mn10300.md (bset, bclr): Operand 0 is a read/write operand.
+
+ * mn10200.md (abssf2, negsf2): New expanders.
- * reorg.c (fill_eager_delay_slots): Add new argument delay_list
- in call to fill_slots_from_thread.
+ * mn10300.md (absdf2, abssf2, negdf2, negsf2): New expanders.
+
+Tue Dec 15 11:55:30 1998 Nick Clifton <nickc@cygnus.com>
-Mon Mar 2 13:45:03 1998 Richard Henderson <rth@cygnus.com>
+ * integrate.c (copy_rtx_and_substitute): If a SUBREG is
+ replaced by a CONCAT whose components do not have the same
+ mode as the original SUBREG, use a new SUBREG to restore the
+ mode.
+
+ * emit-rtl.c (subreg_realpart_p): Cope with subregs containing
+ multiword complex values.
- * alpha/linux.h (CPP_PREDEFINES): Correct connecting whitespace
- to SUB_CPP_PREDEFINES. Reported by asun@saul4.u.washington.edu.
+1998-12-15 Zack Weinberg <zack@rabi.phys.columbia.edu>
-Mon Mar 2 22:59:28 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * cppalloc.c: Add xstrdup here.
+ * cpplib.h: Remove savestring prototype.
+ * cpplib.c: Remove savestring function. s/savestring/xstrdup/
+ throughout.
+ * cppfiles.c: s/savestring/xstrdup/ throughout.
- * final.c (insn_last_address, insn_current_align, uid_align):
- New variables.
- (in_align_chain, align_fuzz, align_shrink_fuzz): New functions.
- (insn_current_reference_address): Likewise.
- (shorten_branches, final_scan_insn): Implement LABEL_ALIGN,
- LABEL_ALIGN_AFTER_BARRIER and LOOP_ALIGN target macros.
- (label_to_alignment): New function.
- * genattrtab.c (write_test_expr): If one of LABEL_ALIGN,
- LABEL_ALIGN_AFTER_BARRIER or LOOP_ALIGN is defined, call
- insn_current_reference_address instead of insn_current_address.
- (or_attr_value, write_length_unit_log): New functions.
- (main): Call write_length_unit_log.
- (write_const_num_delay_slots): Output extra '\n'.
- * alpha.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE):
- replace with:
- (LOOP_ALIGN, ALIGN_LABEL_AFTER_BARRIER).
- * i386.h, i386/osfrose.h, i386/svr3dbx.h, m68k.h, sparc.h: Likewise.
- * arc.h, m32r.h (ASM_OUTPUT_LOOP_ALIGN): replace with:
- (LOOP_ALIGN).
- * i960.h, m88k.h: (ASM_OUTPUT_ALIGN_CODE): Replace with:
- (LABEL_ALIGN_AFTER_BARRIER).
- * ns32k/encore.h, ns32k/merlin.h, ns32k.h, ns32k/sequent.h: Likewise.
- * ns32k/tek6000.h: Likewise.
- * i386/gas.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE): Delete.
- * i386.md (casesi+1): Use ASM_OUTPUT_ALIGN instead of
- ASM_OUTPUT_ALIGN_CODE.
-
-Mon Mar 2 01:05:50 PST 1998 Jeff Law (law@cygnus.com)
+1998-12-15 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cpplib.c: Make all directive handlers read their own
+ arguments.
+ (struct directive): Remove last two arguments from FUNC
+ member prototype. Remove `command_reads_line' member
+ entirely.
+ (directive_table): Remove initializations of
+ command_reads_line flag. Pretty-print.
+ (eval_if_expression, do_define, do_line, do_include,
+ do_undef, do_error, do_pragma, do_ident, do_if, do_xifdef,
+ do_else, do_elif, do_sccs, do_assert, do_unassert,
+ do_warning): Take only two args.
+
+ (cpp_define): Call do_define with two args and the text to
+ define stuffed into a buffer.
+ (make_assertion): Call do_assert with two args.
+ (handle_directive): Call do_line with two args. Call
+ kt->func with two args. Remove command_reads_line
+ processing.
+ (do_define, do_undef, do_error, do_warning, do_pragma,
+ do_sccs): Read the rest of the line here.
+ (do_ident): Gobble rest of line, as cccp does.
+ (cpp_undef): New function.
+ (cpp_start_read): Call cpp_undef instead of do_undef.
+
+1998-12-15 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cpphash.h (union hash_value): Remove `keydef' member, add a
+ `struct hashnode *aschain' member for #assert.
+
+ * cpplib.c (struct tokenlist_list, struct
+ assertion_hashnode): Delete structure definitions.
+ (assertion_install, assertion_lookup, delete_assertion,
+ check_assertion, compare_token_lists, reverse_token_list,
+ read_token_list, free_token_list): Delete functions.
+ (parse_assertion): New function.
+ (cpp_cleanup): Don't destroy the assertion_hashtable.
+
+ (do_assert): Gut and rewrite. #assert foo (bar) places
+ entries for `#foo' and `#foo(bar)' in the macro hash table,
+ type T_ASSERT. The value union's `aschain' member is used
+ to chain all answers for a given predicate together.
+ (do_unassert): Also rewritten. Take an un-asserted
+ answer off the chain from its predicate and call
+ delete_macro on the hashnode, or walk a predicate chain
+ calling delete_macro on all the entries.
+ (cpp_read_check_assertion): Simply call parse_assertion to
+ get the canonical assertion name, and look that up in the
+ hash table.
+
+ * cpplib.h (ASSERTION_HASHNODE,ASSERTION_HASHSIZE,assertion_hashtab):
+ Removed.
+
+ * cpphash.c (install): Use bcopy instead of an explicit loop
+ to copy the macro name.
+
+ * cppexp.c (cpp_lex): Convert the result of
+ cpp_read_check_assertion to a `struct operation' directly;
+ don't go through parse_number.
+
+Tue Dec 15 18:27:39 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * loop.h (struct induction): Delete times_used member.
+ * loop.c (n_times_set): Rename to set_in_loop. Changed all users.
+ (n_times_used): Rename to n_times_set. Changed all users.
+ (scan_loop): Free reg_single_usage before strength reduction.
+ (record_giv, combine_givs): Remove handling of times_used member.
+ (combine_givs_used_once): Rename to:
+ (combine_givs_used_by_other) . Changed all callers.
+
+Tue Dec 15 01:45:26 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * dwarf2out.c (gen_struct_or_union_type_die): Check AGGREGATE_TYPE_P
+ instead of TREE_CODE_CLASS == 't'.
+ (gen_type_die): Likewise.
+ (scope_die_for): Ignore FUNCTION_TYPE "scopes".
+
+Mon Dec 14 16:23:27 1998 Jim Wilson <wilson@cygnus.com>
+
+ * real.c (endian): Disable last change unless
+ HOST_BITS_PER_WIDE_INT is greater than 32.
+
+Mon Dec 14 17:13:36 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * output.h (force_data_section): New prototype.
+ * varasm.c (force_data_section): New function to force the
+ data section, regardless of what in_section thinks.
+ * dwarf2out.c (output_call_frame_info): Call force_data_section
+ since varasm may not realize we've changes sections.
+
+Mon Dec 14 14:09:34 1998 Nick Clifton <nickc@cygnus.com>
+
+ * reload1.c (reload): Delete REG_RETVAL and REG_LIBCALL notes
+ after completing reload.
+
+ * rtl.texi: Document that REG_RETVAL and REG_LIBCALL are
+ deleted after reload.
+
+Mon Dec 14 01:39:28 1998 Jeffrey A Law (law@cygnus.com)
+
+ * rtl.h (multiple_sets): Fix prototype.
+ * rtlanal.c (multiple_sets): Fix return type.
+
+Sun Dec 13 12:43:58 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Mon Mar 2 00:52:18 PST 1998 Jeff Law (law@cygnus.com)
+Sun Dec 13 01:05:22 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Sun Mar 1 18:25:49 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+1998-12-13 Manfred Hollstein <manfred@s-direktnet.de>
- * reorg.c (fill_slots_from_thread): Don't steal delay list from target
- if condition code of jump conflicts with opposite_needed.
+ * protoize.c (fputs): Wrap extern declaration in #ifndef fputs.
- * reorg.c (fill_slots_from_thread): Mark resources referenced in
- opposite_needed thread. Return delay_list even when cannot get
- any more delay insns from end of subroutine.
+Sun Dec 13 00:24:14 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Sun Mar 1 18:26:21 1998 Ken Rose (rose@acm.org)
+ * rtl.h (recompute_reg_usage): Add second argument.
+ * flow.c (recompute_reg_usage): Likewise.
+ * toplev.c (rest_of_compilation): Supply second argument to
+ recompute_reg_usage.
- * reorg.c (fill_slots_from_thread): New parameter, delay_list.
- All callers changed.
+ * reload1.c (compute_use_by_pseudos): Allow reg_renumber[regno] < 0
+ after reload.
-Sun Mar 1 18:25:37 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+Sat Dec 12 23:39:10 1998 Jeffrey A Law (law@cygnus.com)
- * frame.c (start_fde_sort, fde_split, heapsort, fde_merge,
- end_fde_sort): New functions for fast sorting of an FDE array.
- (fde_insert): Simplified.
- (add_fdes): Change argument list.
- (frame_init): Use the new functions.
+ * m68k/t-m68kelf (MULTILIB_OPTIONS): Add mcpu32.
+ (MULTILIB_MATCHES): -m68332 now uses mcpu32 libraries, not m68000.
+ (MULTILIB_EXCEPTIONS): Don't build 68881 libraries for m68000,
+ mcpu32 or m5200.
-Sun Mar 1 18:06:21 1998 Jeffrey A Law (law@cygnus.com)
+ * i386/next.h (ASM_OUTPUT_ALIGN): Use 0x90 for fill character.
- * ginclude/va-ppc.h (va_arg): Fix typo in long long support.
+ * rtlanal.c (multiple_sets): New function.
+ * rtl.h (multiple_sets): Declare it.
+ * local-alloc.c (wipe_dead_reg): Use it.
+ * global.c (global_conflicts): Likewise.
- * i386.c (reg_mentioned_in_mem): Fix dangling else statement.
+Sat Dec 12 22:13:02 1998 Mark Mitchell <mark@markmitchell.com>
- * fold-const.c (fold_range_test): Always return a value.
+ * global.c (record_conflicts): Don't use an array of shorts to
+ store an array of ints.
+ (global_conflicts): Likewise.
-Sun Mar 1 17:57:34 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Sat Dec 12 16:49:24 1998 Richard Henderson <rth@cygnus.com>
- * config/i386/winnt.c (i386_pe_unique_section): Put read-only
- data in the text section unless READONLY_DATA_SECTION is defined.
+ * alpha.c (alpha_expand_block_move): mode_for_size expects
+ bits, not bytes. Infer extra alignment from addressof.
-Sun Mar 1 17:48:46 1998 Jeffrey A Law (law@cygnus.com)
+1998-12-11 Michael Meissner <meissner@cygnus.com>
- * c-parse.in (undeclared variable error): Tweak error message to
- be clearer.
+ * rs6000/sysv4.h (ASM_OUTPUT_ALIGNED_LOCAL): Put small data in the
+ .sbss section, not .sdata.
-Sun Mar 1 10:22:36 PST 1998 Jeff Law (law@cygnus.com)
+1998-12-11 Manfred Hollstein <manfred@s-direktnet.de>
- * version.c: Bump for snapshot.
+ * cccp.c: Do not #include <sys/stat.h> here; this is already done
+ by "system.h".
+ * collect2.c: Likewise.
+ * cpplib.h: Likewise.
+ * gcc.c: Likewise.
+ * gcov.c: Likewise.
+ * getpwd.c: Likewise.
+ * protoize.c: Likewise.
+ * toplev.c: Likewise.
+
+ * cpplib.h (HOST_WIDE_INT): Get definition from "machmode.h"
+ and don't try to define it here.
+ * Makefile.in (cppmain.o): Depend on machmode.h.
+ (cpplib.o): Likewise.
+ (cpperror.o): Likewise.
+ (cppexp.o): Likewise.
+ (cppfiles.o): Likewise.
+ (cpphash.o): Likewise.
+ (cppalloc.o): Likewise.
+ (fix-header.o): Likewise.
+ (scan-decls.o): Likewise.
-1998-02-28 Mark Mitchell <mmitchell@usa.net>
-
- * final.c (final_scan_insn): Undo overzealous removal of `set'.
-
-Sat Feb 28 07:54:03 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Fri Dec 11 11:02:49 1998 Stan Cox <scox@cygnus.com>
- * pa.h (CONST_COSTS): When checking the CONST_DOUBLE enumerated
- case, add parentheses to specify the proper order of precedence in
- the if-statement.
+ * sh.c (print_operand): Lookup interrupt_handler attribute instead
+ of relying on static variable.
+ * (calc_live_regs): Likewise.
+ * (sh_pragma_insert_attributes): Create interrupt_handler
+ attribute if a pragma was specified.
+ * (sh_valid_machine_decl_attribute): Don't set static flag.
+ * sh.h (PRAGMA_INSERT_ATTRIBUTES): New.
+Fri Dec 11 12:56:07 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * c-aux-info.c: Include string.h/strings.h.
-
- * pa.c: Include stdlib.h.
- (pa_combine_instructions): Prototype the function.
- (pa_can_combine_p, forward_branch_p, shadd_constant_p): Likewise.
- (reloc_needed): Add default case for enumeration switch.
- (remove_useless_addtr_insns): Remove unused variable `all'.
- (hppa_expand_prologue): Add explicit braces to avoid
- ambiguous `else'.
- (output_function_epilogue): Remove unused variable `i'.
- (output_millicode_call): Remove unused variable `link'.
- (shadd_constant_p, forward_branch_p): Make the function static.
- (following_call): Explicitly declare to return int.
- (pa_reorg): Declare as void.
- (pa_combine_instructions): Declare as static void. Add
- parentheses around && within ||.
+ * reload1.c (reload_combine): Use BASIC_BLOCK_LIVE_AT_START
+ to determine if a register is live at a jump destination.
+ Everything is dead at a BARRIER.
- * pa.h: Add prototypes for pa_reorg, symbolic_operand,
- following_call, function_label_operand, lhs_lshift_cint_operand
- and zdepi_cint_p.
+Thu Dec 10 16:02:06 1998 Jim Wilson <wilson@cygnus.com>
- * pa.md: Add parentheses around && within ||.
+ * cse.c (simplify_unary_operation): Sign-extend constants when
+ they have the most significant bit set for the target.
+ * real.c (endian): Sign-extend 32 bit output values on a 64 bit
+ host.
+ * m32r/m32r.c (m32r_expand_prologue): Store pretend_size in
+ HOST_WIDE_INT temporary before negating it.
+ * m32r/m32r.md (movsi_insn+1): Use ~0xffff instead of 0xffff0000.
- * cppalloc.c: Include stdlib.h.
+Thu Dec 10 15:05:59 1998 Dave Brolley <brolley@cygnus.com>
- * cpperror.c (cpp_print_containing_files): Remove unused variable
- `i'. Fix format specifier in fprintf.
+ * objc/objc-act.c (lang_init_options): Enclose cpplib related code in
+ #if USE_CPPLIB.
- * cse.c (cse_around_loop): Add explicit braces to avoid
- ambiguous `else'.
- (delete_dead_from_cse): Wrap variable `tem' in macro HAVE_cc0.
+Thu Dec 10 13:39:46 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * expr.c (expand_expr): Add parentheses around && within ||.
+ * collect2.h: New header file for prototypes.
- * final.c (app_enable): Replace fprintf with fputs where there are
- no format specifiers and no trailing argument after the string.
- Eg, when printing ASM_APP_ON/ASM_APP_OFF.
- (app_disable): Likewise.
- (final_end_function): Likewise.
- (final_scan_insn): Likewise. Remove unused variable `set'.
- (profile_function): Wrap empty if-statement body in {} brackets.
+ * Makefile.in (collect2.o, tlink.o): Depend on collect2.h.
- * function.c: Include stdlib.h.
- (pad_below): Wrap prototype and definition in ARGS_GROW_DOWNWARD.
- (reposition_prologue_and_epilogue_notes): Add parentheses
- around assignment used as truth value.
+ * collect2.c: Include collect2.h.
+ * tlink.c: Likewise.
- * integrate.c (expand_inline_function): Wrap variable
- `cc0_insn' in macro HAVE_cc0.
+Wed Dec 9 23:55:11 1998 Jeffrey A Law (law@cygnus.com)
- * jump.c (jump_optimize): Wrap variable `q' in macro
- HAVE_cc0. Remove unused variable `prev1'.
+ * flow.c: Update some comments.
- * libgcc2.c (__bb_exit_trace_func): Add parentheses around &&
- within ||. Fix format specifier in fprintf.
- (__bb_init_prg): Add parentheses around assignment used as
- truth value.
+Wed Dec 9 15:29:26 1998 Dave Brolley <brolley@cygnus.com>
- * local-alloc.c: Include stdlib.h.
- (requires_inout): Add parentheses around assignment used
- as truth value.
+ * objc/objc-act.c (cpp_initialized): Removed.
+ (lang_init_options): Initialize cpplib.
+ (lang_decode_option): Move initialization of cpplib to
+ lang_init_options.
+ * c-lang.c (parse_options,parse_in): Added.
+ (lang_init_options): Initialized cpplib here.
+ * c-decl.c (parse_options,cpp_initialized): Removed.
+ (c_decode_option): Move initialization of cpplib to
+ lang_init_options.
- * loop.c (analyze_loop_iterations): Wrap prototype and definition
- in macro HAVE_decrement_and_branch_on_count.
- (insert_bct, instrument_loop_bct): Likewise.
- (move_movables): Add parentheses around assignment used as
- truth value.
- (consec_sets_invariant_p): Likewise.
- (maybe_eliminate_biv_1): Wrap variable `new' in macro HAVE_cc0.
+Wed Dec 9 19:36:57 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * objc/objc-act.c: Include stdlib.h.
- (lookup_method_in_protocol_list): Wrap empty else-statement body
- in braces.
- (lookup_protocol_in_reflist): Likewise.
- (objc_add_static_instance): Remove unused variables `decl_expr'
- and `decl_spec'.
- (get_objc_string_decl): Remove unused variable `decl'.
- (generate_static_references): Remove unused variables `idecl' and
- `instance'.
- (check_protocols): Wrap empty else-statement body in braces.
+ * reload1.c (reload_combine, reload_combine_note_store):
+ Make STORE_RUID always valid.
+ (reload_combine): Check if BASE is clobbered too early.
- * protoize.c: Include stdlib.h.
- (substr): Add parentheses around assignment used as truth value.
- (abspath): Likewise.
- (shortpath): Likewise.
+Wed Dec 9 09:53:58 1998 Nick Clifton <nickc@cygnus.com>
+
+ * reload.c (find_reloads): Display the insn that cannot be
+ reloaded.
+
+Wed Dec 9 12:15:26 1998 Dave Brolley <brolley@cygnus.com>
+
+ * cccp.c (create_definition): Fix end of buffer logic.
+
+Wed Dec 9 10:15:45 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * except.c (duplicate_eh_handlers, rethrow_symbol_map): Function
+ pointer parameters changed to use the PARAMS() macro.
+
+Wed Dec 9 09:12:40 1998 Andrew MacLeod <amacleod@cygnus.com>
- * regmove.c (fixup_match_1): Add parentheses around assignment
- used as truth value.
+ * except.h (struct handler_info): Add handler_number field.
+ * except.c (gen_exception_label): EH labels no longer need to be
+ on the permanent obstack.
+ (get_new_handler): Set the label number field.
+ (output_exception_table_entry): Regenerate handler label reference
+ from the label number field.
+ (init_eh): Remove a blank line.
+ * integrate.c (get_label_from_map): Labels no longer need to be
+ on the permanent obstack.
- * reload.c (push_secondary_reload): Remove unused variable `i'.
- (find_reloads): Add parentheses around assignment used as truth
- value.
+Tue Dec 8 22:04:33 1998 Jim Wilson <wilson@cygnus.com>
- * reload1.c: Include stdlib.h.
+ * i960/i960.h (CONST_COSTS, case CONST_INT): Accept power2_operand
+ only when OUTER_CODE is SET.
- * rtl.h: Correct typo in prototype of offsettable_memref_p.
-
- * stmt.c (add_case_node): Add parentheses around assignment used
- as truth value.
- (case_tree2list): Likewise.
-
- * tree.c (valid_machine_attribute): Wrap variable `decl_attr_list'
- in macro VALID_MACHINE_DECL_ATTRIBUTE. Wrap variable
- `type_attr_list' in macro VALID_MACHINE_TYPE_ATTRIBUTE.
- (merge_attributes): Add explicit braces to avoid ambiguous
- `else'.
-
- * unroll.c (copy_loop_body): Wrap variable `cc0_insn' in
- macro HAVE_cc0.
-
- * varasm.c: Include stdlib.h.
+Tue Dec 8 22:47:15 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * loop.c (strength_reduce): If scan_start points to the loop exit
+ test, be wary of subversive use of gotos inside expression statements.
+ Don't set maybe_multiple for a backward jump that does not
+ include the label under consideration into its range.
+ * unroll.c (biv_total_increment): Make use of maybe_multiple field.
- * system.h: Remove sys/stat.h.
- * gcc.c: Add sys/stat.h.
+Tue Dec 8 22:33:18 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * genattr.c: Wrap prototype of `free' in NEED_DECLARATION_FREE.
- * genattrtab.c: Likewise.
- * genconfig.c: Likewise.
- * genemit.c: Likewise.
- * genextract.c: Likewise.
- * genflags.c: Likewise.
- * genopinit.c: Likewise.
- * genoutput.c: Likewise.
- * genpeep.c: Likewise.
- * genrecog.c: Likewise.
- * tlink.c: Likewise. Also wrap `getenv' in NEED_DECLARATION_GETENV.
+ * explow.c (plus_constant_wide): Don't immediately return with
+ result of recursive call.
-Fri Feb 27 11:02:47 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Tue Dec 8 15:32:56 1998 Andrew MacLeod <amacleod@cygnus.com>
- * invoke.texi: Use @itemx for a secondary item in a @table.
+ * eh-common.h (struct eh_context): Add table_index for rethrows.
- * config/m68k/m68k.md (movsf+1): Optimize moving a CONST_DOUBLE
- zero.
+ * rtl.h (enum reg_note): Add REG_EH_REGION and REG_EH_RETHROW reg notes.
+ (SYMBOL_REF_NEED_ADJUST): New flag indicating symbol needs to be
+ processed when inlined or unrolled (ie duplicated in some way).
+
+ * rtl.c (reg_note_name): Add strings for new reg_note enums.
+
+ * expr.h (rethrow_libfunc): New library decl.
+
+ * optabs.c (rethrow_libfunc): Initialize.
+
+ * except.h (struct eh_entry): Add new field 'rethrow_label'.
+ (new_eh_region_entry): No longer exported from except.c.
+ (duplicate_handlers): Renamed to duplicate_eh_handlers and
+ different prototype.
+ (rethrow_symbol_map, rethrow_used): New exported functions.
+ (eh_region_from_symbol): New exported function.
+
+ * except.c (create_rethrow_ref): New function to create a single
+ SYMBOL_REF for a rethrow region.
+ (push_eh_entry): Initialize a rethrow ref.
+ (func_eh_entry): Add a rethrow_label field.
+ (new_eh_region_entry): Make static, and initialize the rethrow entry.
+ (duplicate_eh_handlers): Create a new region, and remap labels/symbols.
+ (eh_region_from_symbol): Find an EH region based on its rethrow symbol.
+ (rethrow_symbol_map): Given a label map, maps a rethrow symbol for
+ a region into an appropriate new symbol.
+ (rethrow_used): Indicate whether a rethrow symbol has been referenced.
+ (expand_eh_region_end): Don't issue jump around code for new-exceptions.
+ (end_catch_handler): Emit a barrier for new-exceptions since
+ control can never drop through the end of a catch block.
+ (expand_end_all_catch): new-exceptions never fall through a catch
+ block.
+ (expand_rethrow): Use __rethrow routine for new exceptions.
+ (output_exception_table_entry): Generate rethrow labels, if needed.
+ (output_exception_table): Generate start and end rethrow labels.
+ (init_eh): Create rethrow symbols for beginning and end of table.
+ (scan_region): Don't eliminate EH regions which are the targets of
+ rethrows.
+
+ * flow.c (make_edges): Add different edges for rethrow calls,
+ identified by having the REG_EH_RETHROW reg label.
+ (delete_unreachable_blocks): Don't delete regions markers which are
+ the target of a rethrow.
+
+ * integrate.c (save_for_inline_eh_labelmap): New callback routine to
+ allow save_for_inline_copying to call duplicate_eh_handlers.
+ (save_for_inline_copying): Call duplicate_eh_handlers instead of
+ exposing internal details of exception regions.
+ (copy_for_inline): Check if SYMBOL_REFs need adjustment.
+ (expand_inline_function_eh_labelmap): New callback routine to
+ allow expand_inline_function to call duplicate_eh_handlers.
+ (expand_inline_function): Call duplicate_eh_handlers instead of
+ exposing internal details of exception regions.
+ (copy_rtx_and_substitute): Adjust SYMBOL_REFS if SYMBOL_REF_NEED_ADJUST
+ flag is set.
+
+ * libgcc2.c (find_exception_handler): Generalize to enable it to
+ pick up processing where it left off last time for a rethrow.
+ (__unwinding_cleanup): New function. debug hook which is called before
+ unwinding when __throw finds there is nothing but cleanups left.
+ (throw_helper): Common parts of __throw extracted out for reuse.
+ (__throw): Common parts moved to throw_helper.
+ (__rethrow): New function for performing rethrows.
+
+Tue Dec 8 13:11:04 1998 Jeffrey A Law (law@cygnus.com)
+
+ * reload1.c (current_function_decl): Tweak declaration.
+
+Tue Dec 8 10:23:52 1998 Richard Henderson <rth@cygnus.com>
+
+ * c-decl.c (flag_isoc9x): Default off.
+ (c_decode_option): Kill -std=gnu, add -std=gnu89 and -std=gnu9x.
+ * cccp.c (print_help, main): Likewise.
+ * gcc.c (default_compilers): Update for -std=gnu*.
+
+Tue Dec 8 01:14:46 1998 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (DEMANGLE_H): Change location to shared demangle.h.
+ * demangle.h: Deleted.
+
+ * reload1.c (current_function_decl): Declare.
+
+Tue Dec 8 11:58:51 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cpplib.c (convert_string): Use `0x00ff', not `0x00ffU'.
+
+Tue Dec 8 09:28:36 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * dbxout.c: If USG is defined use gstab.h, even if HAVE_STAB_H is set.
+
+1998-12-08 Ulrich Drepper <drepper@cygnus.com>
+
+ * configure.in: Test for availability of putc_unlocked, fputc_unlocked,
+ and fputs_unlocked.
+ * configure: Rebuilt.
+ * system.h: If the *_unlocked functions are available use them
+ instead of the locked counterparts by defining macros.
+ * config.in: Regenerated.
+
+Tue Dec 8 00:34:05 1998 Mike Stump <mrs@wrs.com>
+
+ * i386/bsd.h (ASM_FILE_START): Don't use dump_base_name, it is
+ wrong and should only be used for dump related things, not
+ debugging information, instead main_input_filename should be used.
+ Also, reuse output_file_directive if possible.
+ * i386/aix386ng.h (ASM_FILE_START): Likewise.
+ * i386/isc.h (ASM_FILE_START): Likewise.
+ * i386/win-nt.h (ASM_FILE_START): Likewise.
+ * i386/sun386.h (ASM_FILE_START): Likewise.
+
+Mon Dec 7 23:56:28 1998 Robert Lipe <robertl@dgii.com>
+
+ * configure.in (mips*-*-linux*): Handle big and little endian
+ systems.
+ * configure: Rebuilt.
+
+Mon Dec 7 23:14:51 1998 Mike Stump <mrs@wrs.com>
+
+ * emit-rtl.c: Fix typo.
-Thu Feb 26 00:13:21 1998 Ian Lance Taylor <ian@cygnus.com>
+Mon Dec 7 23:07:38 1998 Nathan Sidwell <nathan@acm.org>
- * choose-temp.c: Fix handling of sys/file.h to work in libiberty.
+ * reload1.c (eliminate_regs): Don't do anything, if we're not
+ generating code.
-Wed Feb 25 23:40:54 1998 Jeffrey A Law (law@cygnus.com)
+Mon Dec 7 15:27:09 1998 DJ Delorie <dj@cygnus.com>
- * i386.c (struct machine_function): Add new fields for PIC stuff.
- (save_386_machine_status): Fix argument to xmalloc. Save pic_label_rtx
- and pic_label_name.
- (restore_386_machine_status): Corresponding changes.
- (clear_386_stack_locals): Also clear pic_label_rtx and pic_label_name.
+ * mips/mips.h (ENCODE_SECTION_INFO): Handle TARGET_EMBEDDED_DATA.
+ Add comment.
+ * mips/mips.c (mips_select_section): Add comment.
-Wed Feb 25 01:31:40 1998 Jeffrey A Law (law@cygnus.com)
+Mon Dec 7 17:55:06 1998 Mike Stump <mrs@wrs.com>
- * c-parse.y (undeclared variable error): Tweak error message
- to be clearer.
+ * cccp.c (ignore_escape_flag): Add support for \ as `natural'
+ characters in file names in #line to be consistent with #include
+ handling. We support escape processing in the # 1 "..." version of
+ the command. See also support in cp/lex.c.
+ (handle_directive): Likewise.
+ (do_line): Likewise.
-Tue Feb 24 23:54:07 1998 Richard Henderson <rth@cygnus.com>
+1998-12-07 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * flags.h (g_switch_value, g_switch_set): Declare.
- * alpha.c (override_options): Set g_switch_value=8 if not set.
- * alpha/elf.h (CC1_SPEC): New.
- (ASM_SPEC): New.
- (LINK_SPEC): Pass along the -G value we were given.
- (LOCAL_ASM_OP): Remove.
- (ASM_OUTPUT_ALIGNED_LOCAL): Output to .bss or .sbss by size.
- (MAX_OFILE_ALIGNMENT): New.
- (BSS_SECTION_ASM_OP, SBSS_SECTION_ASM_OP, SDATA_SECTION_ASM_OP): New.
- (EXTRA_SECTIONS): Add sbss and sdata.
- (SECTION_FUNCTION_TEMPLATE): New.
- (EXTRA_SECTION_FUNCTIONS): Use it.
- (CTORS_SECTION_FUNCTION, DTORS_SECTION_FUNCTION): Remove.
- (SELECT_SECTION): Use sdata when small enough.
- * alpha/linux.h (ASM_SPEC): Remove.
+ * cpplib.c (initialize_char_syntax): Use ISALPHA and ISALNUM
+ so it'll work on non-ASCII platforms. Always consider $ an
+ identifier character. Take no arguments.
+ (cpp_reader_init): Call initialize_char_syntax with no
+ arguments.
+ (cpp_start_read): Don't call initialize_char_syntax again.
+ Clear is_idchar['$'] and is_idstart['$'] if not
+ opts->dollars_in_ident.
+ * cpplib.h (struct cpp_reader): Replace void *data element by
+ cpp_options *opts. Rearrange elements to make gdb printout
+ less annoying (put buffer stack at end).
+ (CPP_OPTIONS): Get rid of now-unnecessary cast.
-Mon Feb 23 15:09:18 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * config.sub (sco5): Fix typo.
+ * cppmain.c: s/data/opts/ when initializing cpp_reader
+ structure.
+ * c-decl.c: Likewise.
+ * objc/objc-act.c: Likewise.
+ * fix-header.c: Likewise.
-Mon Feb 23 18:19:31 1998 Manfred Hollstein <manfred@s-direktnet.de>
+1998-12-07 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * config/t-linux (LIBGCC1, CROSS_LIBGCC1, LIBGCC1_TEST): Add macros and
- set to empty.
- * config/t-linux-aout (LIBGCC1, CROSS_LIBGCC1, LIBGCC1_TEST): Likewise.
- * config/alpha/t-linux: Remove file.
- * config/sparc/t-linux: Remove file.
- * config/m68k/t-linux (LIBGCC1, CROSS_LIBGCC1): Remove.
- * config/m68k/t-linux-aout (LIBGCC1, CROSS_LIBGCC1): Likewise.
- * configure.in (alpha*-*-linux-gnulibc1*): Use t-linux instead of alpha/t-linux
- for tmake_file.
- (alpha*-*-linux-gnu*): Likewise.
- (sparc-*-linux-gnulibc1*): Use t-linux instead of sparc/t-linux for tmake_file.
- (sparc-*-linux-gnu*): Likewise.
+ * cpplib.h (struct cpp_buffer): Replace dir and dlen members
+ with a struct file_name_list pointer.
+ (struct cpp_reader): Add pointer to chain of `actual
+ directory' include searchpath entries.
+ (struct file_name_list): Add *alloc pointer for the sake of
+ the actual-directory chain.
-Mon Feb 23 10:47:39 1998 Robert Lipe <robertl@dgii.com>
- * collect2.c (ldd_file_name): Bracket declaration with same
- manifests as use.
- (full_real_ld_suffix): Deleted. Variable was calloced and
- written into, but never read.
+ Move definition of HOST_WIDE_INT here.
+ (cpp_parse_escape): Change prototype to match changes in
+ cppexp.c.
-1998-02-23 Mike Stump <mrs@wrs.com>
+ * cppfiles.c (actual_directory): New function.
+ (finclude): Use it to initialize the buffer's actual_dir
+ entry.
+ (find_include_file): We don't need to fix up max_include_len
+ here.
- * configure.in: Add support for i386-wrs-vxworks configuration.
- * i386/vxi386.h: New file.
+ * cpplib.c (do_include): Don't allocate a file_name_list on
+ the fly for current directory "" includes, use the one that's
+ been preallocated in pfile->buffer->actual_dir. Hoist out
+ duplicate code from the search_start selection logic.
+ (cpp_reader_init): Initialize pfile->actual_dirs.
-Sun Feb 22 21:16:51 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+ Remove definition of HOST_WIDE_INT. Change calls
+ to cpp_parse_escape to match changes in cppexp.c (note
+ hardcoded MASK, which is safe since this is the source
+ character set).
- * tree.c (contains_placeholder_p): Ensure function always returns
- a value.
- * sparc.md (movdi_sp64_insn): Add default case in enumeration switch.
- (movsf_const_insn, movdf_const_insn, movtf_const_insn): Likewise.
+ * cppexp.c: Bring over changes to cpp_parse_escape from cccp.c
+ to handle wide character constants in #if directives. The
+ function now returns a HOST_WIDE_INT, and takes a third
+ argument which is a binary mask for all legal values (0x00ff
+ for 8-bit `char', 0xffff for 16-bit `wchar_t', etc.) Define
+ MAX_CHAR_TYPE_MASK and MAX_WCHAR_TYPE_MASK. Change callers of
+ cpp_parse_escape to match. [Fixes c-torture/execute/widechar-1.c]
-Sun Feb 22 20:58:19 1998 Jeffrey A Law (law@cygnus.com)
+Mon Dec 7 15:38:25 1998 Dave Brolley <brolley@cygnus.com>
- * vms.h (SELECT_SECTION): Use TREE_CODE_CLASS correctly.
+ * gcc.c (default_compilers): Fix typo in USE_CPPLIB spec for cc1.
-1998-02-22 Paul Eggert <eggert@twinsun.com>
+Mon Dec 7 15:38:25 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * config/sparc/sol2-sld.h (LINKER_DOES_NOT_WORK_WITH_DWARF2):
- Define this new symbol.
- (DWARF2_DEBUGGING_INFO, DWARF_DEBUGGING_INFO): Do not #undef.
- * toplev.c (main): Do not default to DWARF2_DEBUG with -ggdb if
- LINKER_DOES_NOT_WORK_WITH_DWARF2 is defined.
+ * c-aux-info.c (concat): Wrap function definition in !USE_CPPLIB.
+ * cppalloc.c: Move function `xcalloc' from cpplib.c to here.
+ * cpplib.c: Move function `xcalloc' from here to cppalloc.c.
-Sun Feb 22 20:07:32 1998 Jim Wilson <wilson@cygnus.com>
+Mon Dec 7 11:30:49 1998 Nick Clifton <nickc@cygnus.com>
- * iris5.h (DWARF2_UNWIND_INFO): Define to 0.
- * iris5gas.h (DWARF2_UNWIND_INFO): Define to 1.
+ * final.c (output_asm_name): Use tabs to separate comments from
+ assembly text.
-Sun Feb 22 15:29:48 1998 Richard Henderson <rth@cygnus.com>
+ Include instruction lengths (if defined) in output.
- * objc/Object.m (-error): Call objc_verror with our va_list.
+Mon Dec 7 10:53:38 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Sun Feb 22 09:45:39 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * loop.c (check_dbra_loop): Fix initial_value and initial_equiv_value
+ in the loop_info structure.
- * collect2.c (scan_prog_file): Completely cover uses of variable
- `exports' with macro COLLECT_EXPORT_LIST.
+Mon Dec 7 11:04:40 1998 Catherine Moore <clm@cygnus.com>
+
+ * configure.in (arm*-*-ecos-elf): New target.
+ * configure: Regenerated.
+ * config/arm/elf.h (ASM_WEAKEN_LABEL): Define.
+ * config/arm/ecos-elf.h: New file.
+ * config/arm/unknown-elf.h (TARGET_VERSION): Check
+ for redefinition.
+
+Mon Dec 7 16:15:51 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * sh.c (output_far_jump): Emit braf only for TARGET_SH2.
-Sat Feb 21 20:36:23 1998 Jeff Law (law@cygnus.com)
+Sun Dec 6 04:19:45 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Fri Feb 20 16:22:13 1998 Michael Meissner <meissner@cygnus.com>
+Sun Dec 6 05:16:16 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * sched.c (schedule_block): Remove code to get arguments from hard
- regs into pseudos early. Same as Aug 25, 1997 change to
- haifa-sched.c.
+ * loop.c (check_dbra_loop): New argument loop_info. Update fields
+ as needed.
-1998-02-20 Jason Merrill <jason@yorick.cygnus.com>
+Sun Dec 6 03:40:13 1998 Jeff Law (law@cygnus.com)
- * collect2.c (main): Still handle !do_collecting for non-AIX targets.
+ * version.c: Bump for snapshot.
-1998-02-16 Mark Mitchell <mmitchell@usa.net>
+Sun Dec 6 07:49:29 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
- * toplev.c (rest_of_compilation): Do not defer the output of a
- nested function.
+ * gcc.texi (Bug Reporting): 40Kb is a soft limit, larger
+ compressed reports are ok and preferred over URLs.
-Fri Feb 20 10:39:47 1998 Michael Tiemann <michael@impact.tiemann.org>
+Sun Dec 6 07:45:33 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
- * ginclude/va-mips.h (va_arg): Remove trailing space after '\'
- continuation character (line 243).
+ * invoke.texi (Warning Options): Soften the tone of -pedantic.
-Fri Feb 20 12:10:26 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Sun Dec 6 00:20:44 1998 H.J. Lu (hjl@gnu.org)
- * genrecog.c (main): Remove duplicated sentence in emitted comment.
+ * print-rtl.c (print_rtx): Add prototype.
-Thu Feb 19 22:36:53 1998 Andrey Slepuhin <pooh@msu.net>
- David Edelsohn <edelsohn@mhpcc.edu>
+ * unroll.c (iteration_info): Make it static.
- * collect2.c (XCOFF_SCAN_LIBS): Remove.
- (export_flag): New variable.
- (export_file): #ifdef COLLECT_EXPORT_LIST.
- (import_file, exports, imports, undefined): New variables.
- (libs, cmdline_lib_dirs, libpath_lib_dirs, libpath, libexts): Same.
- (dump_list, dump_prefix_list, is_in_list): New functions.
- (write_export_file): $ifdef COLLECT_EXPORT_LIST.
- (write_import_file, resolve_lib_name): New functions.
- (use_import_list, ignore_library): Same.
- (collect_exit): maybe_unlink import_file and #ifdef.
- (handler): Same.
- (main): New variable importf, #ifdef exportf. Move parsing of
- -shared before general argument parsing. Resolve AIX library
- paths and import libgcc.a symbols. Treat .so shared libraries the
- same as objects and .a libraries. Create alias for object_lst and
- increment it instead of original pointer. Scan AIX libraries as
- objects earlier instead of using scan_libraries. Perform AIX
- tlink later to resolve templates instead of forking ld.
- (GCC_OK_SYMBOL): Ensure symbol not in undef section.
- (GCC_UNDEF_SYMBOL): New macro.
- (scan_prog_file): Loop for members of AIX libraries. Handle
- export/import of ctors/dtors.
- (aix_std_libs): New variable.
- (scan_libraries, XCOFF): Delete.
+Sun Dec 6 01:19:46 1998 Richard Henderson <rth@cygnus.com>
-Thu Feb 19 22:36:52 1998 Robert Lipe <robertl@dgii.com>
+ * alias.c (memrefs_conflict_p): A second ANDed address
+ disables the aligned address optimization.
- * collect2.c (full_real_ld_suffix): #ifdef CROSS_COMPILE.
+Sat Dec 5 18:48:25 1998 Richard Henderson <rth@cygnus.com>
-1998-02-19 Mike Stump <mrs@wrs.com>
+ * alpha.c (alpha_emit_set_const_1): Fix parenthesis error
+ in -c << n case.
- * Makefile.in: Use $tooldir for sys-include to match toplevel
- configure.
+Sat Dec 5 15:14:52 1998 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 19 01:32:37 1998 Jeffrey A Law (law@cygnus.com)
- Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * i960.h (BOOL_TYPE_SIZE): Define.
- * emit-rtl.c (gen_lowpart_common): Suppress last change if __complex__.
+Sun Dec 6 00:28:16 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * emit-rtl.c (hard-reg-set.h): Include.
- (get_lowpart_common): Don't make new REG for hard reg in a
- class that cannot change size.
- * Makefile.in (emit-rtl.o): Depend on hard-reg-set.h.
+ * config/c4x/c4x.c (valid_parallel_load_store): Flog functionality
+ from old valid_parallel_operands_4.
+ (valid_parallel_operands_4): Check that operands for 4 operand
+ parallel insns are valid, excluding load/store insns.
+ * config/c4x/c4x.h (valid_parallel_load_store): Add prototype.
+ * config/c4x/c4x.md (*movqf_parallel, *movqi_parallel): Use
+ valid_parallel_load_store instead of valid_parallel_operands_4.
+ (*absqf2_movqf_clobber, *floatqiqf2_movqf_clobber,
+ *negqf2_movqf_clobber, *absqi2_movqi_clobber,
+ *fixqfqi2_movqi_clobber, *negqi2_movqi_clobber,
+ *notqi_movqi_clobber): Use valid_parallel_operands_4.
+ (*subqf3_movqf_clobber, *ashlqi3_movqi_clobber,
+ *ashrqi3_movqi_clobber, *lshrqi3_movqi_clobber,
+ *subqi3_movqi_clobber): Use valid_parallel_operands_5.
- * combine.c: Revert previous patch.
+Sat Dec 5 23:52:01 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-1998-02-19 Paul Eggert <eggert@twinsun.com>
+ * config/c4x/c4x.c (iteration_info): Delete extern.
- * config/sparc/sol2-sld.h: New file.
- * configure.in (sparc-*-solaris2*): Use it when using the
- system linker.
+Fri Dec 4 20:15:57 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
-Thu Feb 19 00:46:59 1998 Jeffrey A Law (law@cygnus.com)
+ * tm.texi (SMALL_REGISTER_CLASSES): Make description match reality.
- * loop.c (force_movables): Fix typo.
+ * final.c (cleanup_subreg_operands): Delete some unused code.
-Thu Feb 19 08:26:30 1998 Manfred Hollstein <manfred@s-direktnet.de>
+ * recog.h (MAX_RECOG_ALTERNATIVES): New macro.
+ (struct insn_alternative): New structure definition.
+ (recog_op_alt): Declare variable.
+ (preprocess_constraints): Declare function.
+ * recog.c (recog_op_alt): New variable.
+ (extract_insn): Verify number of alternatives is in range.
+ (preprocess_constraints): New function.
+ * reg-stack.c: Include recog.h.
+ (constrain_asm_operands): Delete.
+ (get_asm_operand_lengths): Delete.
+ (get_asm_operand_n_inputs): New function.
+ (record_asm_reg_life): Delete OPERANDS, CONSTRAINTS, N_INPUTS and
+ N_OUTPUTS args. All callers changed.
+ Compute number of inputs and outputs here by calling
+ get_asm_operand_n_inputs.
+ Instead of constrain_asm_operands, call extract_insn,
+ constrain_operands and preprocess_constraints. Use information
+ computed by these functions throughout.
+ (record_reg_life): Delete code that is unused due to changes in
+ record_asm_reg_life.
+ (subst_asm_stack_regs): Delete OPERANDS, OPERAND_LOC, CONSTRAINTS,
+ N_INPUTS and N_OUTPUTS args. All callers changed.
+ Similar changes as in record_asm_reg_life.
+ (subst_stack_regs): Move n_operands declaration into the if statement
+ where it's used.
+ Delete code that is unused due to changes in subst_asm_stack_regs.
+ * stmt.c (expand_asm_operands): Verify number of alternatives is in
+ range.
+ * Makefile.in (reg-stack.o): Depend on recog.h.
- * m88k.h: Change file pattern to match reality.
+Fri Dec 4 02:23:24 1998 Jeffrey A Law (law@cygnus.com)
-Wed Feb 18 23:19:52 1998 Jeffrey A Law (law@cygnus.com)
+ * except.c (set_exception_version_code): Argument is an "int".
- * varasm.c (output_constant_pool): Fix dumb thinko in last
- change.
+Fri Dec 4 01:29:28 1998 Jeffrey A Law (law@cygnus.com)
- * pa.h (ASM_OUTPUT_FUNCTION_PREFIX): Correctly translate from
- a function name to a section name.
+ * configure.in (hppa2*-*-*): Handle like hppa1.1-*-* for now.
+ * configure: Rebuilt.
-1998-02-18 Doug Evans <devans@cygnus.com>
+Fri Dec 4 01:29:28 1998 Robert Lipe <robertl@dgii.com>
- * tree.h (merge_machine_{type,decl}_attributes): Declare.
- (split_specs_attrs, strip_attrs): Add prototypes.
- * tree.c (merge_machine_{type,decl}_attributes): New functions.
- * c-decl.c (duplicate_decls): Call merge_machine_decl_attributes.
- Update olddecl's attributes too.
- * c-common.c (strip_attrs): New function.
- * c-typeck.c (common_type): Call merge_machine_type_attributes.
- * varasm.c (make_function_rtl): New target macro REDO_SECTION_INFO_P.
- (make_decl_rtl): Likewise.
+ * configure.in (mipsel-*-linux*): New target.
+ * mips/linux.h: New file, based on other Linux targets.
-1998-02-18 Jim Wilson <wilson@cygnus.com>
+Thu Dec 3 11:19:50 1998 Mike Stump <mrs@wrs.com>
- * c-decl.c (shadow_tag_warned): Call split_specs_attrs.
+ * gthr-vxworks.h (__ehdtor): Fix memory leak. The delete hook
+ runs in the context of the deleter, not the deletee, so we must
+ use taskVarGet to find the correct memory to free.
+ (__gthread_key_create): Initialize the task
+ variable subsystem so that the task variable is still active when
+ the delete hook is run.
-Wed Feb 18 09:09:50 1998 Jeffrey A Law (law@cygnus.com)
+1998-12-03 Joseph S. Myers <jsm28@cam.ac.uk>
- Remove this change until we can fix it correctly.
- * collect2.c: Bracket declaration of 'exportf' and
- 'full_real_ld_suffix'.
+ * pdp11.h: Use optimize_size for space optimizations.
+ * pdp11.c: Likewise.
+ * pdp11.md: Likewise.
-Wed Feb 18 08:44:25 1998 Bernd Schmidt <crux@ohara.Informatik.RWTH-Aachen.DE>
+ * pdp11.h (TARGET_40_PLUS): Fix typo.
- * Makefile.in (STAGESTUFF): Add genrtl.c, genrtl.h and gengenrtl.
+Thu Dec 3 11:48:32 1998 Jeffrey A Law (law@cygnus.com)
-Tue Feb 17 23:30:20 1998 Bernd Schmidt <crux@ohara.Informatik.RWTH-Aachen.DE>
+ * local-alloc.c (block_alloc): Slightly retune heuristic to widen
+ qty lifetimes.
- * c-common.c (c_expand_start_cond, c_expand_end_cond,
- c_expand_start_else): Don't warn about non-ambiguous else even if
- braces are missing.
+Thu Dec 3 22:30:18 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Tue Feb 17 23:56:50 1998 Robert Lipe <robertl@dgii.com>
+ * alias.c (addr_side_effect_eval): New function.
+ (memrefs_conflict_p): Use it.
+ * rtl.h (addr_side_effect_eval): Prototype it.
- * sco5.h (ASM_OUTPUT_DOUBLE, ASM_OUTPUT_FLOAT,
- ASM_OUTPUT_LONG_DOUBLE): Delete. Use the ones from i386.h
- instead.
+1998-12-02 Joseph S. Myers <jsm28@cam.ac.uk>
-Tue Feb 17 22:56:14 1998 Richard Henderson <rth@cygnus.com>
+ * pdp11.md (extendsfdf2): Fix mode mismatch in SET.
- * combine.c (simplify_rtx): Obey CLASS_CANNOT_CHANGE_SIZE when
- simplifying a subreg of a hard reg.
- (expand_compound_operation): Likewise.
- (force_to_mode): Likewise.
+Wed Dec 2 11:23:07 1998 Jim Wilson <wilson@cygnus.com>
-Tue Feb 17 22:37:22 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * reload.c (find_reloads): When force const to memory, put result
+ in substed_operand not *recog_operand_loc.
- * fold-const.c: Include "system.h" to get stdlib.h and stdio.h.
- (lshift_double): Add parentheses around + or - inside shift.
- (rshift_double): Likewise.
- (size_int_wide): Explicitly set type of `bit_p' to `int'.
+1998-12-02 Ulrich Drepper <drepper@cygnus.com>
- * Makefile.in (fold-const.o): Depend on system.h.
+ * c-lex.c: Fix indentation from last patch.
+ Remove trailing whitespace.
+ * real.c: Likewise.
- * Makefile.in (gcc.o): Depend on system.h, in accordance with last
- change to gcc.c.
+Wed Dec 2 10:11:12 1998 Jeffrey A Law (law@cygnus.com)
- * haifa-sched.c: Include "system.h" to get <stdlib.h> and <stdio.h>.
- (BLOCKAGE_RANGE): Add parentheses around arithmetic in operand of |.
- (sched_note_set): Remove unused parameter `b', all callers changed.
- (schedule_block): Likewise for `rgn'.
- (split_hard_reg_notes): Likewise for `orig_insn'.
- (check_live): Likewise for `trg'.
- (update_live): Likewise.
- (check_live_1): Explcitly declare variable `i' as int.
- (update_live_1): Likewise.
- (insn_issue_delay): Remove unused variable `link'.
- (sched_analyze_2): Add default case in enumeration switch.
- (schedule_insns): Remove unused variable `i'.
+ * flow.c (delete_block): Call set_last_insn after we have reset
+ NEXT_INSN (kept_tail).
- * Makefile.in ($(SCHED_PREFIX)sched.o): Depend on system.h.
+Wed Dec 2 00:47:31 1998 Jeffrey A Law (law@cygnus.com)
-Tue Feb 17 22:31:04 1998 Jeffrey A Law (law@cygnus.com)
+ * mips.md (trap_if): Use "$0" for the value zero.
- * loop.c (rtx_equal_for_loop_p): Add some braces to disambiguate
- a dangling else clause.
+Tue Dec 1 20:49:49 1998 Ulrich Drepper <drepper@cygnus.com>
+ Stephen L Moshier <moshier@world.std.com>
+ Richard Henderson <rth@cygnus.com>
-Tue Feb 17 21:28:12 1998 Gavin Koch <gavin@cygnus.com>
+ * c-common.c (declare_function_name): Declare predefined variable
+ `__func__'.
- * mips/mips.h (CAN_ELIMINATE): Don't eliminate the frame
- pointer for the stack pointer in MIPS16 and 64BIT.
+ * c-decl.c (flag_isoc9x): Set to 1 by default.
+ (c_decode_option): Handle -std= option. Remove -flang-isoc9x.
+ (grokdeclarator): Always emit warning about implicit int for ISO C 9x.
-Tue Feb 17 21:17:30 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * c-parse.in: Allow constructors in ISO C 9x.
+ Rewrite designator list handling.
+ Allow [*] parameters.
+ Don't warn about comma at end of enum definition for ISO C 9x.
- * rtl.h (force_line_numbers, restore_line_number_status): Declare.
- * emit-rtl.c (force_line_numbers, restore_line_number_status):
- New functions.
- * stmt.c (struct nesting): Replace seenlabel with line_number_status.
- (expand_start_case): Adjust to this change.
- (check_seenlabel): New function.
- (pushcase, pushcase_range, expand_endcase): Use it.
+ * cccp.c (c9x): New variable.
+ (rest_extension): New variable.
+ (print_help): Document new -std= option.
+ (main): Recognize -std= option. Set c9x appropriately.
+ (create_definition): Recognize ISO C 9x vararg macros.
-Tue Feb 17 10:14:32 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * gcc.c (default_compilers): Adjust specs for -std options.
+ (option_map): Add --std.
+ (display_help): Document -std.
- * i386.md (adddi3): Add =!r,0,0,X alternative.
+ * toplev.c (documented_lang_options): Add -std and remove
+ -flang-isoc9x.
-Mon Feb 16 16:13:43 1998 David Edelsohn <edelsohn@mhpcc.edu>
+ * c-lex.c (yylex): Recognize hex FP constants and call REAL_VALUE_ATOF
+ or REAL_VALUE_HTOF based on base of the constants.
+ * fold-const.c (real_hex_to_f): New function. Replacement function
+ for hex FP conversion if REAL_ARITHMETIC is not defined.
+ * real.c (asctoeg): Add handling of hex FP constants.
+ * real.h: Define REAL_VALUE_HTOF if necessary using ereal_atof or
+ real_hex_to_f.
- * rs6000.h (MY_ISCOFF): Add numeric value of U803XTOCMAGIC.
- * x-aix31 (INSTALL): Delete.
+Tue Dec 1 16:45:49 1998 Stan Cox <scox@cygnus.com>
-Mon Feb 16 09:24:32 1998 Gavin Koch <gavin@cygnus.com>
+ * mips.md (divmodsi4*, divmoddi4*, udivmodsi4*, udivmoddi4): Add
+ -mcheck-range-division/-mcheck-zero-division checking. Avoid as macro
+ expansion. Use hi/lo as destination register.
+ (div_trap): New.
+ (divsi3*, divdi3*, modsi3*, moddi3*, udivsi3*, udivdi3*, umodsi3*,
+ umoddi3*): Add -mcheck-range-division/-mcheck-zero-division checking.
+ Avoid as macro expansion. Use hi/lo as destination register.
- * mips/mips.c (mips_expand_epilogue): Update tsize_rtx if
- tsize changes to something other than zero.
+ * mips.h (MASK_CHECK_RANGE_DIV): New.
+ (MASK_NO_CHECK_ZERO_DIV): New.
+ (ELIMINABLE_REGS): Added GP_REG_FIRST + 31.
+ (CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET): Allow for getting
+ return address for leaf functions out of r31 to support
+ builtin_return_address.
-Mon Feb 16 09:11:48 1998 Gavin Koch <gavin@cygnus.com>
+Tue Dec 1 15:03:30 1998 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
- * ginclude/va-mips.h: Replace casts of pointers to int with
- casts of pointers to __PTRDIFF_TYPE__.
+ * jump.c (jump_optimize): Call regs_set_between_p with PREV_INSN(x),
+ NEXT_INSN(x) to check insn x.
-Mon Feb 16 08:17:14 1998 John Carr <jfc@mit.edu>
+Tue Dec 1 15:20:44 1998 Jeffrey A Law (law@cygnus.com)
- * loop.c (strength_reduce, record_biv, record_giv): Use
- HOST_WIDE_INT_PRINT_DEC to print CONST_INT values.
+ * flow.c (delete_block): Call set_last_insn if we end up deleting the
+ last insn in the rtl chain.
-1998-02-16 Jason Merrill <jason@yorick.cygnus.com>
+ * reload1.c (reload): Do not set reload_completed or split insns
+ here. Instead...
+ * toplev.c (rest_of_compilation): Set reload_completed after
+ reload returns. Split insns after reload_cse has run.
- * tree.c (first_rtl_op): New fn.
- (unsave_expr_now): Use it.
- * print-tree.c (print_node): Likewise.
- * tree.c (has_cleanups): New fn.
- * fold-const.c (fold, case CLEANUP_POINT_EXPR): Use it. Be more
- conservative about pushing the cleanup point down.
- * tree.h: Declare them.
+Tue Dec 1 11:55:04 1998 Richard Henderson <rth@cygnus.com>
-Sun Feb 15 23:28:44 1998 Jeffrey A Law (law@cygnus.com)
+ * final.c (final_scan_insn): Abort if block_depth falls below 0.
- * toplev.c (flag_schedule_reverse_before_reload): Delete variable.
- (flag_schedule_reverse_after_reload): Likewise.
- (f_options): Remove reverse scheduling support.
- * flags.h (flag_schedule_reverse_before_reload): Delete declaration.
- (flag_schedule_reverse_after_reload): Likewise.
- * haifa-sched.c (rank_for_schedule): Remove support for reverse
- scheduling.
+Tue Dec 1 10:23:16 1998 Nick Clifton <nickc@cygnus.com>
-Sun Feb 15 21:33:55 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * config/arm/t-arm-elf (LIBGCC2_CFLAGS): Define inhibit_libc.
- * gcc.c: Get system includes, prototypes and macros via "system.h"
- instead of doing it manually. Change all calls of the ctype
- macros to custom versions defined in "system.h".
+Tue Dec 1 10:22:18 1998 Nick Clifton <nickc@cygnus.com>
- * system.h: Fix return type of bcmp prototype from `void' to `int'.
- Make bcopy, bcmp and bzero prototypes explicitly `extern'.
- Add a prototype for getenv.
+ * config/arm/unknown-elf.h (ASM_OUTPUT_DWARF2_ADDR_CONST): Remove
+ use of user-label_prefix.
-Sun Feb 15 17:05:41 1998 Jim Wilson <wilson@cygnus.com>
+Tue Dec 1 17:58:26 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * mips/mips.h (INITIAL_ELIMINATION_OFFSET): Readd Jun 6 change.
+ * reload1.c (emit_reload_insns): Clear spill_reg_store
+ when doing a new non-inherited reload from the same pseudo.
-Sun Feb 15 15:23:15 1998 John Carr <jfc@mit.edu>
+ * local-alloc.c (function_invariant_p): New function.
+ (update_equiv_regs): Use function_invariant_p instead of CONSTANT_P
+ to decide if an equivalence should be recorded.
+ * reload1.c (num_eliminable_invariants): New static variable.
+ (reload): Set it. Use function_invariant_p instead of CONSTANT_P
+ to decide if an equivalence should be recorded.
+ Unshare PLUS.
+ (calculate_needs_all_insns): Skip insns that only set an equivalence.
+ Take num_eliminable_invariants into account when deciding
+ if register elimination should be done.
+ (reload_as_needed): Take num_eliminable_invariants into account
+ when deciding if register elimination should be done.
+ (eliminate_regs): Handle non-constant reg_equiv_constant.
+ * rtl.h (function_invariant_p): Declare.
- * alias.c: Include <stdlib.h> and <string.h>.
- (init_alias_analysis): Pass NULL_RTX instead of 0 to record_set.
+Mon Nov 30 02:00:08 1998 Jeff Law (law@cygnus.com)
-Sat Feb 14 11:23:09 PST 1998 Jeff Law (law@cygnus.com)
+ * version.c: Bump for snapshot.
+
+Mon Nov 30 00:42:59 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Sat Feb 14 05:08:21 1998 Richard Earnshaw (rearnsha@arm.com)
-
- * arm.md (movsfcc): Also validate operands[3] when compiling hard
- float.
- (movdfcc): Only accept fpu_add_operand for operands[3].
-
- * arm/t-semi (STMP_FIXPROTO): Define to nothing.
- * arm/t-semiaof (STMP_FIXPROTO): Likewise.
-
-Sat Feb 14 02:02:41 1998 Jeffrey A Law (law@cygnus.com)
-
- * varasm.c (output_constant_pool): Bring back 'done' label inside
- an appropriate #ifdef.
-
- * bitmap.c (bitmap_element_allocate): Wrap variable 'i' in an
- appropriate #ifdef.
- (bitmap_copy, bitmap_operation): Likewise.
- * combine.c (combinable_i3pat): Similarly for 'src'.
- * function.c (fixup_var_refs_1): Similarly for 'outerdest'.
- (locate_and_pad_parm): Similarly for 'reg_parm_stack_space'.
- * regclass.c (copy_cost): Similarly for 'secondary_class'.
- * reload.c (make_memloc): Simliarly for 'i'.
- (find_reloads_address_1): Similarly for 'link'.
- * reload1.c (reload): Similarly for 'previous_frame_pointer_needed'.
- (emit_reload_insns): Similarly for 'second_reloadreg'.
- * unroll.c (iteration_info): Similarly for 'v'.
-
- * caller-save.c (insert_save_restore): Remove unused variable 'i'.
- * calls.c (expand_call): Similarly for 'i'.
- (emit_library_call, emit_library_call_value): Similarly for 'mode'.
- * fold-const.c (strip_compund_expr): Similarly for 'type'.
- * function.c (fixup_var_refs_1): Similarly for 'width'.
- (fixup_memory_subreg): Similarly for 'saved'.
- (locate_and_pad_parm): Similarly for 'boundary_in_bytes.'
- (setjmp_protect): Similarly for 'sub'.
- (thread_prologue_and_epilogue_insns): Similarly for 'insn'.
- * loop.c (record_giv): Similarly for 'p'.
- (combine_givs): Similarly for 'temp_iv'.
- (indirect_jump_in_function_p): Similarly for 'is_indirect_jump'.
- * recog.c (validate_replace_rtx_1): Similarly for 'width'.
- * tree.c (get_set_constructor_bytes): Similarly for 'vals'.
- * unroll.c (unroll_loop): Similarly for 'copy'.
- (iteration_info): Similarly for 'b'.
- * varasm.c (assemble_string): Similarly for 'i'.
- * i386.h (LEGITIMIZE_ADDRESS): Similarly for 'orig_x'.
-
-1998-02-13 Martin von Loewis <loewis@informatik.hu-berlin.de>
-
- * c-lang.c (lang_print_xnode): New function.
- * objc/objc-act.c (lang_print_xnode): Likewise.
- * print-tree.c (print_node): Call it
-
-Fri Feb 13 14:38:34 1998 Jim Wilson <wilson@cygnus.com>
-
- * dwarf2out.c (decl_scope_node): New type.
- (decl_scope_table): Change type to use it.
- (decl_scope_table_allocated, decl_scope_depth): Change type to int.
- (push_decl_scope): Use new type. New locals containing_scope, i.
- Add code to handle setting previous field.
- (scope_die_for): Change type of local i to int. Add code to use
- previous field.
- (dwarf2out_init): Use new type.
-
-1998-02-13 Jason Merrill <jason@yorick.cygnus.com>
-
- * except.c (emit_throw): Lose throw_used.
-
-Fri Feb 13 20:36:05 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * sched.c (update_flow_info, REG_WAS_0): Ignore if setting insn
- was deleted.
- * haifa-sched.c (update_flow_info, REG_WAS_0): Likewise.
-
-Fri Feb 13 12:18:40 1998 Jeffrey A Law (law@cygnus.com)
-
- * genextract.c (main): Fix typo.
-
-Fri Feb 13 08:41:49 1998 Robert Lipe <robertl@dgii.com>
-
- * c-lang.c (finish_file): Bracket declaration of static_ctors,
- static_dtors.
-
- * calls.c (expand_call): Bracket declaration of 'rtx_before_call',
- 'old_stack_arg_under_construction'
- (emit_library_call): Bracket declaration of 'upper_bound',
- 'lower_bound', 'i', 'reg_parm_stack_space'
- (emit_library_call_value): Likewise.
- (store_one_arg):
+Sun Nov 29 22:59:40 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * except.c (add_new_handler): Complain about additional handlers
+ after one that catches everything.
+
+Sat Nov 28 10:56:32 1998 Jeffrey A Law (law@cygnus.com)
+
+ * configure.in (alpha*-*-netbsd): Fix typo.
+ * configure: Rebuilt.
- * collect2.c: include <unistd.h> when appropriate.
- Bracket declaration of 'exportf' and 'full_real_ld_suffix'.
+Fri Nov 27 12:28:56 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * emit-rtl.c (prev_cc0_setter): Remove unused variable 'link'.
+ * system.h: Include libiberty.h.
- * explow.c (plus_constant_for_output_wide): Remove unused variable
- 'code'.
- (memory_address): Remove unused variable 'orig_x'.
+ * c-aux-info.c: Remove prototypes for concat/concat3. Change
+ function `concat' from fixed parameters to variable parameters,
+ as is done in libiberty. All callers of concat/concat3
+ changed to use the new `concat' with variable args.
+
+ * cccp.c: Remove things made redundant by libiberty.h and/or
+ conform to libiberty standards.
+ * cexp.y: Likewise.
+ * collect2.c: Likewise.
+ * config/1750a/1750a.h: Likewise.
+ * cppalloc.c: Likewise.
+ * cppexp.c: Likewise.
+ * cppfiles.c: Likewise.
+ * cpphash.c: Likewise.
+ * cpplib.c: Likewise.
+ * dyn-string.c: Likewise.
+ * fix-header.c: Likewise.
+ * gcc.c: Likewise.
+ * gcov.c: Likewise.
+ * genattr.c: Likewise.
+ * genattrtab.c: Likewise.
+ * gencheck.c: Likewise.
+ * gencodes.c: Likewise.
+ * genconfig.c: Likewise.
+ * genemit.c: Likewise.
+ * genextract.c: Likewise.
+ * genflags.c: Likewise.
+ * gengenrtl.c: Likewise.
+ * genopinit.c: Likewise.
+ * genoutput.c: Likewise.
+ * genpeep.c: Likewise.
+ * genrecog.c: Likewise.
+ * getpwd.c: Likewise.
+ * halfpic.c: Likewise.
+ * hash.c: Likewise.
+ * mips-tdump.c: Likewise. Wrap malloc/realloc/calloc prototypes
+ in NEED_DECLARATION_* macros.
- * genattrtab.c (make_canonical): Remove unreferenced label 'cond:'.
- (write_const_num_delay_slots): Remove unused variable 'i'.
+ * mips-tfile.c: Remove things made redundant by libiberty.h and/or
+ conform to libiberty standards.
+ (fatal): Fix const-ification of variable `format' in
+ !ANSI_PROTOTYPES case.
- * genopinit.c (main): Remove unused variables 'dummy', 'insn_ptr'.
- (gen_insn): Remove unused variable 'obstack_ptr'.
+ * prefix.c: Remove things made redundant by libiberty.h and/or
+ conform to libiberty standards.
- * libgcc2.c (__bb_exit_func): Remove unused variables 'ret',
- 'j', 'tmp', 'i'.
- (__bb_exit_trace_func): Remove unused variable 'e'.
+ * print-rtl.c: Rename variable `spaces' to `xspaces' to avoid
+ conflicting with function `spaces' from libiberty.
- * optabs.c (expand_binop): remove unused variables 'lhs', 'rhs',
- 'funexp'.
- (expand_unop): Remove unused variable 'funexp'.
- (expand_complex_abs): Remove unused variable 'funexp'.
- (init_optabs): Bracket declaration of 'j'.
- (init_complex_libfuncs): Deleted. Dead static function.
+ * profile.c: Remove things made redundant by libiberty.h and/or
+ conform to libiberty standards.
+ * protoize.c: Likewise.
+ * rtl.h: Likewise.
+ * scan.h: Likewise.
+ * tlink.c: Likewise.
+ * toplev.c: Likewise.
+ * toplev.h: Likewise.
+ * tree.h: Likewise.
- * profile.c (branch_prob): Remove unused variables 'insn', 'dest'.
+Thu Nov 26 08:38:06 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * reg-stack.c: Fix typo in proto for 'get_asm_operand_lengths'
- (reg_to_stack): 'initialized', 'before_function_beg'
- explictly type as ints instead of defaulting.
- (emit_swap_insn): Remove unused variable 'i2'.
- (compare_for_stack_reg): Remove unused variable 'src_note'.
+ * cppfiles.c (simplify_pathname): Un-ANSI-fy function definition.
- * rtlanal.c (computed_jump_p): Remove unused variable 'computed_jump'.
+Thu Nov 26 23:45:37 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * sched.c (actual_hazard): Bracket declaration of 'this_cost'.
+ * README.C4X: Updated URLs.
+ * config/c4x/c4x.c (c4x_address_conflict): Fix typo.
+ (valid_parallel_operands_5): Remove unused variable.
- * stmt.c (add_case_node): Add parens for assignment used as truth.
- (all_cases_count): Remove unused variable 'count_high'.
- (mark_seen_cases): Remove unused variable 'i'.
- (check_for_full_enumeration_handling): Remove unused variable 't'.
- Bracket declaration of 'all_values', 'l'.
+Thu Nov 26 23:40:03 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * tlink.c: Include <stdlib.h>, <unistd.h>, <string.h>/<strings.h>.
+ * config/c4x/c4x.h (TARGET_DEFAULT): Fix typo.
- * varasm.c (assemble_string): Remove unused variable 'i'.
- (immed_double_const): Remove unused variable 'in_current_obstack'.
- (immed_real_const_1): Likewise.
- (output_constant_pool): Remove unreferenced label 'done'.
- (output_constant): Remove unused variable 'x'.
+1998-11-26 Manfred Hollstein <manfred@s-direktnet.de>
- * i386/i386.h (ENCODE_SECTION_INFO): TREE_PUBLIC is an int, not
- a string.
+ * Makefile.in (CONFIG_LANGUAGES): New macro taking all languages
+ which can be configured.
+ (LANGUAGES): Use $(CONFIG_LANGUAGES) instead of @all_languages@
+ (Makefile): Pass actual LANGUAGES through the environment when
+ re-configuring.
+ (cstamp-h): Likewise.
+ (config.status): Likewise.
- * i386/sco5.h (ASM_OUTPUT_ASCII): Add parens for assignment used
- as truth.
+ * configure.in (enable_languages): Add new configuration parameter
+ "--enable-languages=lang1,lang2,...".
+ (${srcdir}/*/config-lang.in): Change handling to configure only
+ those directories, that the user might have enabled; default to
+ "all" existing languages.
+ * configure: Regenerate.
-Fri Feb 13 10:21:41 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Thu Nov 26 00:19:19 1998 Richard Henderson <rth@cygnus.com>
+
+ * rtlanal.c (regs_set_between_p): New function.
+ * rtl.h (regs_set_between_p): Prototype it.
+ * jump.c (jump_optimize): Use it instead of modified_between_p
+ in the Sep 2 change.
+
+Wed Nov 25 23:32:02 1998 Ian Dall <Ian.Dall@dsto.defence.gov.au>
+ Matthias Pfaller <leo@dachau.marco.de>
+
+ * invoke.texi (Option Summary, NS32K Options): Add description
+ of NS32K specific options.
+
+ * ns32k.md (tstdf, cmpdf, movdf, truncdfsf2, fixdfqi2, fixdfhi2,
+ fixdfsi2, fixunsdfqi2, fixunsdfhi2, fixunsdfsi2, fix_truncdfqi2,
+ fix_truncdfhi2, fix_truncdfsi2, adddf3, subdf3, muldf3, divdf3,
+ negdf2, absdf2): Use l instead of f since the double class and
+ float class are no longer the same.
+ (cmpsi, truncsiqi2, truncsihi2, addsi3, subsi3, mulsi3, umulsidi3,
+ divsi3, modsi3, andsi3, iorsi3, xorsi3, negsi2, one_cmplsi2,
+ ashlsi3, ashlhi3, ashlqi3, rotlsi3, rotlhi3, rotlqi3, abssi2,...):
+ Use "g" instead of "rmn" since LEGITIMATE_PIC_OPERAND has been
+ fixed.
+ (cmpsi, cmphi, cmpqi): Use general_operand instead of
+ non_immediate_operand. Removes erroneous assumption that can't
+ compare constants.
+ (movsf, movsi, movhi, movqi,...): New register numbering scheme.
+ (movsi, addsi3): Use NS32K_DISPLACEMENT_P instead of hard coded
+ constants.
+ (movstrsi, movstrsi1, movstrsi2): Completely new block move
+ scheme.
+ (...): Patterns to exploit multiply-add instructions.
+ (udivmodsi4, udivmodsi_internal4, udivmodhi4,
+ udivmoddihi4_internal, udivmodqi4, udivmoddiqi4_internal): New
+ patterns to exploit extended divide insns.
+ (udivsi3, udivhi3, udivqi3): Remove since superseded by udivmodsi
+ etc patterns.
+
+ * ns32k.h (FUNCTION_VALUE, LIBCALL_VALUE): Use f0 for complex
+ float return values as well as simple scalar floats.
+ (TARGET_32381, TARGET_MULT_ADD, TARGET_SWITCHES):
+ Support new flag to denote 32381 fpu.
+ (OVERRIDE_OPTIONS): 32381 is a strict superset of 32081.
+ (CONDITIONAL_REGISTER_USAGE): Disable extra 32381 registers if not
+ compiling for 32381.
+ (FIRST_PSEUDO_REGISTER, FIXED_REGISTERS, CALL_USED_REGISTERS,
+ REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES, OUTPUT_REGISTER_NAMES,
+ REG_ALLOC_ORDER, DBX_REGISTER_NUMBER, R0_REGNUM, F0_REGNUM,
+ L1_REGNUM, STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM,
+ LONG_FP_REGS_P, ARG_POINTER_REGNUM, reg_class, REG_CLASS_NAMES,
+ REG_CLASS_CONTENTS, SUBSET_P,REGNO_REG_CLASS,
+ REG_CLASS_FROM_LETTER, FUNCTION_PROLOGUE, FUNCTION_EPILOGUE,
+ REGNO_OK_FOR_INDEX_P, FP_REG_P, REG_OK_FOR_INDEX_P,
+ REG_OK_FOR_BASE_P, MEM_REG): New register scheme to include 32381
+ fpu registers and special register classes for new 32381
+ instructions dotf and polyf.
+ (MODES_TIEABLE_P): Allow all integer modes, notably DI and SI, to
+ be tieable.
+ (INCOMING_RETURN_ADDR_RTX, RETURN_ADDR_RTX,
+ INCOMING_FRAME_SP_OFFSET): New macros in case DWARF support is
+ required.
+ (SMALL_REGISTER_CLASSES): Make dependent on -mmult-add option.
+ (MOVE_RATIO): Set to zero because of smart movstrsi implementation.
+ (REGISTER_MOVE_COST): Move code to register_move_cost function for
+ ease of coding and debugging.
+ (CLASS_LIKELY_SPILLED_P): Under new register scheme class
+ LONG_FLOAT_REGO is likely spilled but not caught by default
+ definition.
+ (CONSTANT_ADDRESS_P, CONSTANT_ADDRESS_NO_LABEL_P): Use macro
+ instead of hard coded numbers in range check.
+ (ASM_OUTPUT_LABELREF_AS_INT): Delete since unused.
+ (...): Add prototypes for functions in ns32k.c but disable because
+ of problems when ns32k.h is included in machine independent files.
+
+ * ns32k.c: Include "system.h", "tree.h", "expr.h", "flags.h".
+ (ns32k_reg_class_contents, regcass_map, ns32k_out_reg_names,
+ hard_regno_mode_ok, secondary_reload_class,
+ print_operand, print_operand_address): New register scheme to
+ include 32381 fpu registers and special register classes for new
+ 32381 instructions dotf and polyf.
+ (gen_indexed_expr): Make static to keep namespace clean.
+ (check_reg): Remove since never called.
+ (move_tail, expand_block_move): Helper functions for "movstrsi"
+ block move insn.
+ (register_move_cost): Helper function for REGISTER_MOVE_COST macro.
+ Increase cost of moves which go via memory.
+ * netbsd.h (TARGET_DEFAULT): Set (new) 32381 fpu flag.
+ (CPP_PREDEFINES): No longer predefine "unix".
+
+ * ns32k.md (movsi, movsi, adddi3, subdi3, subsi3, subhi3, subqi3,...):
+ Remove erroneous %$. print_operand() can work out from the rtx is
+ an immediate prefix is required.
+
+ * ns32k.h (RETURN_POPS_ARGS, VALID_MACHINE_DECL_ATTRIBUTE,
+ VALID_MACHINE_TYPE_ATTRIBUTE, COMP_TYPE_ATTRIBUTES,
+ SET_DEFAULT_TYPE_ATTRIBUTES): Support for -mrtd calling
+ convention.
+ (LEGITIMATE_PIC_OPERAND_P, SYMBOLIC_CONST): Correct handling of
+ pic operands.
+
+ * ns32k.c (symbolic_reference_mentioned_p, print_operand):
+ Correct handling of pic operands.
+ (ns32k_valid_decl_attribute_p, ns32k_valid_type_attribute_p,
+ ns32k_comp_type_attributes, ns32k_return_pops_args): Support for
+ -mrtd calling convention.
+
+Wed Nov 25 23:42:20 1998 Tom Tromey <tromey@cygnus.com>
+
+ * gcc.c (option_map): Recognize --output-class-directory.
+
+Thu Nov 26 18:26:21 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * loop.h (precondition_loop_p): Added new mode argument.
+ * unroll.c (precondition_loop_p): Likewise.
+ (approx_final_value): Function deleted and subsumed
+ into loop_iterations.
+ (loop_find_equiv_value): New function.
+ (loop_iterations): Use loop_find_equiv_value to find increments
+ too large to be immediate constants. Also use it to find terms
+ common to initial and final iteration values that can be removed.
+
+Thu Nov 26 18:05:04 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * loop.h (struct loop_info): Define new structure.
+ (precondition_loop_p): Added prototype.
+ (unroll_loop): Added new argument loop_info to prototype.
+ (final_biv_value, final_giv_value): Added new argument n_iterations
+ to prototype.
+ * loop.c (strength_reduce): Declare new structure loop_iteration_info
+ and new pointer loop_info.
+ (loop_n_iterations): Replace global variable by element in
+ loop_info structure.
+ (check_final_value): New argument n_iterations.
+ (insert_bct): New argument loop_info.
+ (loop_unroll_factor): Replace global array by element in
+ loop_info structure.
+ (loop_optimize): Remove code to allocate and initialize
+ loop_unroll_factor_array.
+ * unroll.c (precondition_loop_p): No longer static since
+ used by branch on count optimization.
+ (precondition_loop_p, unroll_loop): New argument loop_info.
+ (final_biv_value, final_giv_value, find_splittable_regs): New
+ argument n_iterations.
+ (loop_iteration_var, loop_initial_value, loop_increment,
+ loop_final_value, loop_comparison_code, loop_unroll_factor):
+ Replaced global variables by loop_info structure.
+ (loop_unroll_factor): Replace global array by element in
+ loop_info structure.
+
+Thu Nov 26 17:49:29 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * loop.c (check_dbra_loop): Update JUMP_LABEL field of jump insn
+ when loop reversed.
+
+ * unroll.c (precondition_loop_p): Return loop_initial_value
+ for initial_value instead of loop_iteration_var.
+
+Thu Nov 26 17:15:38 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.md: Fix minor formatting problems. Update docs.
+ (*b, *b_rev, *b_noov, *b_noov_rev, *db,
+ decrement_and_branch_until_zero, rptb_end): Use c4x_output_cbranch
+ to output the instruction sequences.
+ (rpts): Delete.
+ (rptb_top): Provide alternatives to use any register or memory
+ for loop counter.
+ (rptb_end): Emit use of operands rather than assigning them
+ explicitly to the RS and RE registers.
+
+Thu Nov 26 16:37:59 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.c (c4x_modified_between_p, c4x_mem_set_p,
+ c4x_mem_set_p, c4x_mem_modified_between_p, c4x_insn_moveable_p,
+ c4x_parallel_pack, c4x_parallel_find, c4x_update_info_reg,
+ c4x_update_info_regs, c4x_copy_insn_after, c4x_copy_insns_after,
+ c4x_merge_notes, c4x_parallel_process,
+ c4x_combine_parallel_independent, c4x_combine_parallel_dependent,
+ c4x_combine_parallel): Delete.
+
+Thu Nov 26 15:16:05 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.c (c4x_override_options): For compatibility
+ with old target options clear flag_branch_on_count_reg if
+ -mno-rptb specified and set flag_argument_alias is -mno-aliases
+ specified.
+ (c4x_output_cbranch): Handle a sequence of insns rather than a
+ single insn.
+ (c4x_rptb_insert): Do not emit a RPTB insn if the RC register
+ has not been allocated as the loop counter.
+ (c4x_address_conflict): Do not allow two volatile memory references.
+ (valid_parallel_operands_4, valid_parallel_operands_5,
+ valid_parallel_operands_6): Reject pattern if the register destination
+ of the first set is used as part of an address in the second set.
+
+Thu Nov 26 14:56:32 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.h (TARGET_DEFAULT): Add PARALEL_MPY_FLAG.
+ (TARGET_SMALL_REG_CLASS): Set to 0 so that SMALL_REGISTER_CLASSES
+ is no longer enabled if PARALLEL_MPY_FLAG set.
+ (HARD_REGNO_CALL_CLOBBERED): Add parentheses to remove ambiguity.
+ (REG_CLASS_CONTENTS): Add braces around initializers.
+ (HAVE_MULTIPLE_PACK): Define.
+ (ASM_OUTPUT_BYTE_FLOAT): Use %lf format specifier with
+ REAL_VALUE_TO_DECIMAL.
+ (ASM_OUTPUT_SHORT_FLOAT): Use %lf format specifier with
+ REAL_VALUE_TO_DECIMAL.
+ (ar0_reg_operand): Add prototype.
+ (ar0_mem_operand): Likewise.
+ (ar1_reg_operand): Likewise.
+ (ar1_mem_operand): Likewise.
+ (ar2_reg_operand): Likewise.
+ (ar2_mem_operand): Likewise.
+ (ar3_reg_operand): Likewise.
+ (ar3_mem_operand): Likewise.
+ (ar4_reg_operand): Likewise.
+ (ar4_mem_operand): Likewise.
+ (ar5_reg_operand): Likewise.
+ (ar5_mem_operand): Likewise.
+ (ar6_reg_operand): Likewise.
+ (ar6_mem_operand): Likewise.
+ (ar7_reg_operand): Likewise.
+ (ar7_mem_operand): Likewise.
+ (ir0_reg_operand): Likewise.
+ (ir0_mem_operand): Likewise.
+ (ir1_reg_operand): Likewise.
+ (ir1_mem_operand): Likewise.
+ (group1_reg_operand): Likewise.
+ (group1_mem_operand): Likewise.
+ (ir1_reg_operand): Likewise.
+ (arx_reg_operand): Likewise.
+ (not_rc_reg): Likewise.
+ (not_modify_reg): Likewise.
+ (c4x_group1_reg_operand): Remove prototype.
+ (c4x_group1_mem_operand): Likewise.
+ (c4x_arx_reg_operand): Likewise.
+
+Wed Nov 25 19:02:55 1998 (Stephen L Moshier) <moshier@world.std.com>
+
+ * emit-rtl.c (gen_lowpart_common): Remove earlier change.
+ * real.c (make_nan): Make SIGN arg actually specify the sign bit.
+
+Thu Nov 26 14:12:05 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.md (addqi3): Emit addqi3_noclobber pattern
+ during reload.
- * combine.c (can_combine_p): Handle USEs in PARALLELs.
+Wed Nov 25 22:05:28 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * config/sh/lib1funcs.asm (___udivsi3_i4): Don't switch to sz == 1
+ unless FMOVD_WORKS is defined.
+
+Wed Nov 25 20:11:04 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * regclass.c (init_reg_sets): Move code that calculates tables
+ dependent on reg_class_contents from here...
+ (init_reg_sets_1): To here.
+
+Wed Nov 25 14:54:46 1998 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cpplib.h: Delete struct import_file. Add ihash element to
+ struct cpp_buffer. Delete dont_repeat_files and
+ import_hash_table elements from cpp_reader; change
+ all_include_files to a hash table. Delete all foobar_include
+ / last_foobar_include elements from struct cpp_options; put
+ back four such: quote_include, bracket_include,
+ system_include, after_include. Redo struct file_name_list
+ completely. Add new structure type include_hash. Add
+ prototypes for merge_include_chains and include_hash. Change
+ prototypes for finclude, find_include_file, and
+ append_include_chain to match changes below.
+
+ * cppfiles.c (simplify_pathname, include_hash,
+ remap_filename, merge_include_chains): New functions.
+ (add_import, lookup_import, open_include_file): Removed.
+ (INO_T_EQ): Define this (copied from cccp.c).
+ (hack_vms_include_specification): Remove all calls and #if 0
+ out the definition. It was being called incorrectly and at
+ the wrong times. Until a VMSie can look at this, it's better
+ to not pretend to support it.
+ (append_include_chain): Change calling convention; now takes
+ only one directory at a time, and sets up the data structure
+ itself.
+ (redundant_include_p): Rewritten - this is now used for all
+ include redundancy, whether by #ifndef, #import, or #pragma
+ once. Looks up things in the include hash table.
+ (file_cleanup): Decrement pfile->system_include_depth here if
+ it's >0.
+ (find_include_file): Calling convention changed; now passes
+ around a struct include_hash instead of 3 separate parameters.
+ Guts ripped out and replaced with new include_hash mechanism.
+ (finclude): Calling convention changed as for
+ find_include_file. Error exits pulled out-of-line. Reformat.
+ (safe_read): Return a long, not an int.
+ (deps_output): Don't recurse.
+
+ * cpplib.c (is_system_include): Deleted.
+ (path_include): Fix up call to append_include_chain.
+ (do_include): Fix up calls to find_include_file and finclude.
+ Clean up dependency output a bit. Shorten obnoxiously lengthy
+ #import warning message. Don't decrement
+ pfile->system_include_depth here.
+ (do_pragma): Understand the include_hash structure. Reformat.
+ (do_endif): Correct handling of control macros. Understand
+ the include_hash.
+ (cpp_start_read): Fix up calls to finclude. Call
+ merge_include_chains.
+ (cpp_handle_option): Fix up calls to append_include_chain.
+ Understand the four partial include chains.
+ (cpp_finish): Add debugging code (#if 0-ed out) for the
+ include_hash.
+ (cpp_cleanup): Free the include_hash, not the import hash and
+ the all_include and dont_repeat lists which no longer exist.
+
+Wed Nov 25 11:26:19 1998 Jeffrey A Law (law@cygnus.com)
+
+ * toplev.c (no_new_pseudos): Define.
+ (rest_of_compilation): Set no_new_pseudos as needed.
+ * emit-rtl.c (gen_reg_rtx): Abort if we try to create a new pseudo
+ if no_new_pseudos is set.
+ * rtl.h (no_new_pseudos): Declare it.
+ * reload1.c (reload): Update comments.
+ * md.texi: Corresponding changes.
+
+Wed Nov 25 11:26:17 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * reload1.c (reg_used_in_insn): Renamed from reg_used_by_pseudo.
+ (choose_reload_regs): Rename it here as well. When computing it,
+ also merge in used hardregs.
+
+1998-11-25 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * gcc.c: Split out Objective-C specs to...
+ * objc/lang-specs.h: here. (New file.) Make the specs cpplib
+ aware.
+
+ * c-lex.c (init_parse): Always initialize the filename global.
+ * objc/objc-act.c (lang_init): Always call check_newline at
+ beginning of file.
+
+Wed Nov 25 00:48:29 1998 Graham <grahams@rcp.co.uk>
+
+ * reload1.c (reload): Remove unused variable.
+ (reload_reg_free_for_value_p): Add missing parameter definition.
+
+ * jump.c (jump_optimize): Remove unused variable.
+
+Wed Nov 25 00:07:11 1998 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (graph.o): Depend on $(RTL_H), not rtl.h.
+
+ * cse.c (fold_rtx): Make autoincrement addressing mode tests be
+ runtime selectable.
+ * expr.c (move_by_pieces): Similarly.
+ (move_by_pieces_1, clear_by_pieces, clear_by_pieces_1): Similarly.
+ * flow.c (find_auto_inc): Similarly.
+ (try_pre_increment): Similarly.
+ * loop.c (strength_reduce): Similarly.
+ * regclass.c (auto_inc_dec_reg_p): Similarly.
+ * regmove.c (try_auto_increment): Similarly.
+ (fixup_match_1): Similarly.
+ * rtl.h (HAVE_PRE_INCREMENT): Define if not already defined.
+ (HAVE_PRE_DECREMENT): Similarly.
+ (HAVE_POST_INCREMENT, HAVE_POST_DECREMENT): Similarly.
+ * Corresponding changes to all target header files.
+ * tm.texi: Update docs for autoinc addressing modes.
+
+Tue Nov 24 20:24:59 1998 Jim Wilson <wilson@cygnus.com>
+
+ * configure.in (m68020-*-elf*, m68k-*-elf*): New targets.
+ * configure: Rebuild.
+ * config/elfos.h: New file.
+ * config/m68k/m68020-elf.h, config/m68k/m68kelf.h,
+ config/m68k/t-m68kelf: New file.
-Fri Feb 13 01:34:14 1998 H.J. Lu (hjl@gnu.org)
+Tue Nov 24 13:40:06 1998 Jeffrey A Law (law@cygnus.com)
- * config/linux.h (LIB_SPEC): Add -lc for -shared if
- USE_GNULIBC_1 is not defined.
- * config/sparc/linux.h; Ditto.
+ * Makefile.in (HOST_AR): Define.
+ (HOST_AR_FLAGS, HOST_RANLIB, HOST_RANLIB_TEST): Similarly.
+ (libcpp.a): Use the host tools explicitly.
+ (STAGESTUFF): Add libcpp.a.
- * config/sparc/linux64.h (LIB_SPEC): Add -lc for -shared.
+Tue Nov 24 09:33:49 1998 Nick Clifton <nickc@cygnus.com>
- * config/alpha/linux-elf.h (LIB_SPEC): New. Defined if
- USE_GNULIBC_1 is not defined.
+ * config/m32r/m32r.md (movstrsi_internal): Describe changes made
+ to source and destination registers.
-Fri Feb 13 01:29:29 1998 Franz Sirl <franz.sirl-kernel@lauterbach.com>
+Mon Nov 23 20:28:02 1998 Mike Stump <mrs@wrs.com>
- * rs6000/sysv4.h (ENDFILE_SPEC): add missing %(endfile_linux)
- for -mcall-linux
+ * libgcc2.c (top_elt): Remove top_elt, it isn't thread safe.
+ The strategy we now use is to pre allocate the top_elt along
+ with the EH context so that each thread has its own top_elt.
+ This is necessary as the dynamic cleanup chain is used on the
+ top element of the stack and each thread MUST have its own.
+ (eh_context_static): Likewise.
+ (new_eh_context): Likewise.
+ (__sjthrow): Likewise.
-Fri Feb 13 01:23:46 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Mon Nov 23 20:25:03 1998 Jason Merrill <jason@yorick.cygnus.com>
- * system.h: New file to get common systems includes and various
- definitions and declarations based on autoconf macros.
+ * i386/linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Wrap in do...while.
+ * i386.md (prologue_get_pc): Remove unused variable.
-Fri Feb 13 00:46:19 1998 Jeffrey A Law (law@cygnus.com)
+Mon Nov 23 17:05:40 1998 Geoffrey Noer <noer@cygnus.com>
- * cccp.c (new_include_prefix): Correctly handle -I./.
+ * i386/xm-cygwin.h: Rename cygwin_ path funcs back to cygwin32_.
-Thu Feb 12 20:16:35 1998 Michael Meissner <meissner@cygnus.com>
+Mon Nov 23 16:40:00 1998 Ulrich Drepper <drepper@cygnus.com>
- * rs6000.md: Replace gen_rtx (CONST_INT,...) with GEN_INT.
+ * Makefile.in (OBJS): Add graph.o.
+ (graph.o): New dependency list.
+ * flags.h: Declare dump_for_graph and define graph_dump_types type.
+ * print-rtl.c (dump_for_graph): Define new variable.
+ (print_rtx): Rewrite to allow use in graph dumping functions.
+ * toplev.c: Declare print_rtl_graph_with_bb, clean_graph_dump_file,
+ finish_graph_dump_file.
+ Define graph_dump_format.
+ (compile_file): If graph dumping is enabled also clear these files.
+ Finish graph dump files.
+ (rest_of_compilation): Also dump graph information if enabled.
+ (main): Recognize -dv to enabled VCG based graph dumping.
+ * graph.c: New file. Graph dumping functions.
-Thu Feb 12 16:45:17 1998 Robert Lipe <robertl@dgii.com>
+Mon Nov 23 16:39:04 1998 Richard Henderson <rth@cygnus.com>
- * expr.c (expand_assignment): Correct typo exposed by -Wall.
- offset should have been a truth value, not an assignment.
+ * configure.in: Look for <sys/stat.h>.
+ * system.h: Include it before substitute S_ISREG definitions.
-Thu Feb 12 15:26:50 1998 Jeffrey A Law (law@cygnus.com)
+Mon Nov 23 17:40:37 1998 Gavin Romig-Koch <gavin@cygnus.com>
- * cse.c (delete_dead_from_cse): If a libcall produces a constant
- result and that result can be substituted into SET_SRC of the
- insn with the REG_RETVAL note, then perform the substitution
- and delete the libcall.
+ * config/mips/abi.h: Use ABI_O64, duplicating ABI_32 usage.
+ * config/mips/iris6.h: Same.
+ * config/mips/mips.md: Same.
+ * config/mips/mips.c: Same; also add "-mabi=o64" option.
+ * config/mips/mips.h: Same; also define ABI_O64.
-Thu Feb 12 14:04:09 1998 Gavin Koch <gavin@cygnus.com>
+Mon Nov 23 17:02:27 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * mips.md (trucndihi2,truncdiqi2): Change these to support
- mips16.
+ * configure.in: Use AC_PREREQ(2.12.1).
-Thu Feb 12 11:34:55 1998 Gavin Koch <gavin@cygnus.com>
+Mon Nov 23 10:16:38 1998 Melissa O'Neill <oneill@cs.sfu.ca>
- * mips/mips.c (movdi_operand): Direct referances to symbols
- that arn't mips16 consts in mips16 mode arn't valid operands.
+ * cccp.c (S_ISREG, S_ISDIR): Delete defines.
+ * cpplib.c, gcc.c: Likewise.
+ * system.h (S_ISREG, S_ISDIR): Define if not already defined.
- * mips/mips.c (mips_move_2words): Add gprel handling.
+Mon Nov 23 09:53:44 1998 Richard Henderson <rth@cygnus.com>
-Thu Feb 12 11:18:37 1998 Gavin Koch <gavin@cygnus.com>
+ * local-alloc.c (local_alloc): Use malloc not alloca for
+ reg_qty, reg_offset, ref_next_in_qty.
- * mips.md (extendsidi2): Allow extension to/from a non-mips16
- register.
+Mon Nov 23 16:46:46 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * caller-save.c (insert_one_insn): Initialize the live_before and
+ live_after register sets.
+
+ Add SH4 support:
+
+ * config/sh/lib1funcs.asm (___movstr_i4_even, ___movstr_i4_odd): Define.
+ (___movstrSI12_i4, ___sdivsi3_i4, ___udivsi3_i4): Define.
+ * sh.c (reg_class_from_letter, regno_reg_class): Add DF_REGS.
+ (fp_reg_names, assembler_dialect): New variables.
+ (print_operand_address): Handle SUBREGs.
+ (print_operand): Added 'o' case.
+ Don't use adj_offsettable_operand on PRE_DEC / POST_INC.
+ Name of FP registers depends on mode.
+ (expand_block_move): Emit different code for SH4 hardware.
+ (prepare_scc_operands): Use emit_sf_insn / emit_df_insn as appropriate.
+ (from_compare): Likewise.
+ (add_constant): New argument last_value. Changed all callers.
+ (find_barrier): Don't try HImode load for FPUL_REG.
+ (machine_dependent_reorg): Likewise.
+ (sfunc_uses_reg): A CLOBBER cannot be the address register use.
+ (gen_far_branch): Emit a barrier after the new jump.
+ (barrier_align): Don't trust instruction lengths before
+ fixing up pcloads.
+ (machine_dependent_reorg): Add support for FIRST_XD_REG .. LAST_XD_REG.
+ Use auto-inc addressing for fp registers if doubles need to
+ be loaded in two steps.
+ Set sh_flag_remove_dead_before_cse.
+ (push): Support for TARGET_FMOVD. Use gen_push_fpul for fpul.
+ (pop): Support for TARGET_FMOVD. Use gen_pop_fpul for fpul.
+ (calc_live_regs): Support for TARGET_FMOVD. Don't save FPSCR.
+ Support for FIRST_XD_REG .. LAST_XD_REG.
+ (sh_expand_prologue): Support for FIRST_XD_REG .. LAST_XD_REG.
+ (sh_expand_epilogue): Likewise.
+ (sh_builtin_saveregs): Use DFmode moves for fp regs on SH4.
+ (initial_elimination_offset): Take TARGET_ALIGN_DOUBLE into account.
+ (arith_reg_operand): FPUL_REG is OK for SH4.
+ (fp_arith_reg_operand, fp_extended_operand): New functions.
+ (tertiary_reload_operand, fpscr_operand): Likewise.
+ (commutative_float_operator, noncommutative_float_operator): Likewise.
+ (binary_float_operator, get_fpscr_rtx, emit_sf_insn): Likewise.
+ (emit_df_insn, expand_sf_unop, expand_sf_binop): Likewise.
+ (expand_df_unop, expand_df_binop, expand_fp_branch): Likewise.
+ (emit_fpscr_use, mark_use, remove_dead_before_cse): Likewise.
+ * sh.h (CPP_SPEC): Add support for -m4, m4-single, m4-single-only.
+ (CONDITIONAL_REGISTER_USAGE): Likewise.
+ (HARD_SH4_BIT, FPU_SINGLE_BIT, SH4_BIT, FMOVD_BIT): Define.
+ (TARGET_CACHE32, TARGET_SUPERSCALAR, TARGET_HARWARD): Define.
+ (TARGET_HARD_SH4, TARGET_FPU_SINGLE, TARGET_SH4, TARGET_FMOVD): Define.
+ (target_flag): Add -m4, m4-single, m4-single-only, -mfmovd.
+ (OPTIMIZATION_OPTIONS): If optimizing, set flag_omit_frame_pointer
+ to -1 and sh_flag_remove_dead_before_cse to 1.
+ (ASSEMBLER_DIALECT): Define to assembler_dialect.
+ (assembler_dialect, fp_reg_names): Declare.
+ (OVERRIDE_OPTIONS): Add code for TARGET_SH4.
+ Hide names of registers that are not accessible.
+ (CACHE_LOG): Take TARGET_CACHE32 into account.
+ (LOOP_ALIGN): Take TARGET_HARWARD into account.
+ (FIRST_XD_REG, LAST_XD_REG, FPSCR_REG): Define.
+ (FIRST_PSEUDO_REGISTER: Now 49.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS): Include values for registers.
+ (HARD_REGNO_NREGS): Special treatment of FIRST_XD_REG .. LAST_XD_REG.
+ (HARD_REGNO_MODE_OK): Update.
+ (enum reg_class): Add DF_REGS and FPSCR_REGS.
+ (REG_CLASS_NAMES, REG_CLASS_CONTENTS, REG_ALLOC_ORDER): Likewise.
+ (SECONDARY_OUTPUT_RELOAD_CLASS, SECONDARY_INPUT_RELOAD_CLASS): Update.
+ (CLASS_CANNOT_CHANGE_SIZE, DEBUG_REGISTER_NAMES): Define.
+ (NPARM_REGS): Eight floating point parameter registers on SH4.
+ (BASE_RETURN_VALUE_REG): SH4 also passes double values
+ in floating point registers.
+ (GET_SH_ARG_CLASS): Likewise.
+ Complex float types are also returned in float registers.
+ (BASE_ARG_REG): Complex float types are also passes in float registers.
+ (FUNCTION_VALUE): Change mode like PROMOTE_MODE does.
+ (LIBCALL_VALUE): Remove trailing semicolon.
+ (ROUND_REG): Round when double precision value is passed in floating
+ point register(s).
+ (FUNCTION_ARG_ADVANCE): No change wanted for SH4 when things are
+ passed on the stack.
+ (FUNCTION_ARG): Little endian adjustment for SH4 SFmode.
+ (FUNCTION_ARG_PARTIAL_NREGS): Zero for SH4.
+ (TRAMPOLINE_ALIGNMENT): Take TARGET_HARWARD into account.
+ (INITIALIZE_TRAMPOLINE): Emit ic_invalidate_line for TARGET_HARWARD.
+ (MODE_DISP_OK_8): Not for SH4 DFmode.
+ (GO_IF_LEGITIMATE_ADDRESS): No base reg + index reg for SH4 DFmode.
+ Allow indexed addressing for PSImode after reload.
+ (LEGITIMIZE_ADDRESS): Not for SH4 DFmode.
+ (LEGITIMIZE_RELOAD_ADDRESS): Handle SH3E SFmode.
+ Don't change SH4 DFmode nor PSImode RELOAD_FOR_INPUT_ADDRESS.
+ (DOUBLE_TYPE_SIZE): 64 for SH4.
+ (RTX_COSTS): Add PLUS case.
+ Increase cost of ASHIFT, ASHIFTRT, LSHIFTRT case.
+ (REGISTER_MOVE_COST): Add handling of R0_REGS, FPUL_REGS, T_REGS,
+ MAC_REGS, PR_REGS, DF_REGS.
+ (REGISTER_NAMES): Use fp_reg_names.
+ (enum processor_type): Add PROCESSOR_SH4.
+ (sh_flag_remove_dead_before_cse): Declare.
+ (rtx_equal_function_value_matters, fpscr_rtx, get_fpscr_rtx): Declare.
+ (PREDICATE_CODES): Add binary_float_operator,
+ commutative_float_operator, fp_arith_reg_operand, fp_extended_operand,
+ fpscr_operand, noncommutative_float_operator.
+ (ADJUST_COST): Use different scale for TARGET_SUPERSCALAR.
+ (SH_DYNAMIC_SHIFT_COST): Cheaper for SH4.
+ * sh.md (attribute cpu): Add value sh4.
+ (attrbutes fmovd, issues): Define.
+ (attribute type): Add values dfp_arith, dfp_cmp, dfp_conv, dfdiv.
+ (function units memory, int, mpy, fp): Make dependent on issue rate.
+ (function units issue, single_issue, load_si, load): Define.
+ (function units load_store, fdiv, gp_fpul): Define.
+ (attribute hit_stack): Provide proper default.
+ (use_sfunc_addr+1, udivsi3): Predicated on ! TARGET_SH4.
+ (udivsi3_i4, udivsi3_i4_single, divsi3_i4, divsi3_i4_single): New insns.
+ (udivsi3, divsi3): Emit special patterns for SH4 hardware,
+ (mulsi3_call): Now uses match_operand for function address.
+ (mulsi3): Also emit code for SH1 case. Wrap result in REG_LIBCALL /
+ REG_RETVAL notes.
+ (push, pop, push_e, pop_e): Now define_expands.
+ (push_fpul, push_4, pop_fpul, pop_4, ic_invalidate_line): New expanders.
+ (movsi_ie): Added y/i alternative.
+ (ic_invalidate_line_i, movdf_i4): New insns.
+ (movdf_i4+[123], reload_outdf+[12345], movsi_y+[12]): New splitters.
+ (reload_indf, reload_outdf, reload_outsf, reload_insi): New expanders.
+ (movdf): Add special code for SH4.
+ (movsf_ie, movsf_ie+1, reload_insf, calli): Make use of fpscr visible.
+ (call_valuei, calli, call_value): Likewise.
+ (movsf): Emit no-op move.
+ (mov_nop, movsi_y): New insns.
+ (blt, sge): Generalize to handle DFmode.
+ (return predicate): Call emit_fpscr_use and remove_dead_before_cse.
+ (block_move_real, block_lump_real): Predicate on ! TARGET_HARD_SH4.
+ (block_move_real_i4, block_lump_real_i4, fpu_switch): New insns.
+ (fpu_switch0, fpu_switch1, movpsi): New expanders.
+ (fpu_switch+[12], fix_truncsfsi2_i4_2+1): New splitters.
+ (toggle_sz): New insn.
+ (addsf3, subsf3, mulsf3, divsf3): Now define_expands.
+ (addsf3_i, subsf3_i, mulsf3_i4, mulsf3_ie, divsf3_i): New insns.
+ (macsf3): Make use of fpscr visible. Disable for SH4.
+ (floatsisf2): Make use of fpscr visible.
+ (floatsisf2_i4): New insn.
+ (floatsisf2_ie, fixsfsi, cmpgtsf_t, cmpeqsf_t): Disable for SH4.
+ (ieee_ccmpeqsf_t): Likewise.
+ (fix_truncsfsi2): Emit different code for SH4.
+ (fix_truncsfsi2_i4, fix_truncsfsi2_i4_2, cmpgtsf_t_i4): New insns.
+ (cmpeqsf_t_i4, ieee_ccmpeqsf_t_4): New insns.
+ (negsf2, sqrtsf2, abssf2): Now expanders.
+ (adddf3, subdf3i, muldf2, divdf3, floatsidf2): New expanders.
+ (negsf2_i, sqrtsf2_i, abssf2_i, adddf3_i, subdf3_i): New insns.
+ (muldf3_i, divdf3_i, floatsidf2_i, fix_truncdfsi2_i): New insns.
+ (fix_truncdfsi2, cmpdf, negdf2, sqrtdf2, absdf2): New expanders.
+ (fix_truncdfsi2_i4, cmpgtdf_t, cmpeqdf_t, ieee_ccmpeqdf_t): New insns.
+ (fix_truncdfsi2_i4_2+1): New splitters.
+ (negdf2_i, sqrtdf2_i, absdf2_i, extendsfdf2_i4): New insns.
+ (extendsfdf2, truncdfsf2): New expanders.
+ (truncdfsf2_i4): New insn.
+ * t-sh (LIB1ASMFUNCS): Add _movstr_i4, _sdivsi3_i4, _udivsi3_i4.
+ (MULTILIB_OPTIONS): Add m4-single-only/m4-single/m4.
+ * float-sh.h: When testing for __SH3E__, also test for
+ __SH4_SINGLE_ONLY__ .
+ * va-sh.h (__va_freg): Define to float.
+ (__va_greg, __fa_freg, __gnuc_va_list, va_start):
+ Define for __SH4_SINGLE_ONLY__ like for __SH3E__ .
+ (__PASS_AS_FLOAT, __TARGET_SH4_P): Likewise.
+ (__PASS_AS_FLOAT): Use different definition for __SH4__ and
+ __SH4_SINGLE__.
+ (TARGET_SH4_P): Define.
+ (va_arg): Use it.
-Thu Feb 12 00:04:16 1998 Marc Lehmann <pcg@goof.com>
+ * sh.md (movdf_k, movsf_i): Tweak the condition so that
+ init_expr_once is satisfied about the existence of load / store insns.
- * i386.c: Conditionally include <stdlib.h>, <string.h>, and
- <strings.h>.
+ * sh.md (movsi_i, movsi_ie, movsi_i_lowpart, movsf_i, movsf_ie):
+ Change m constraint in source operand to mr / mf.
-Wed Feb 11 11:43:34 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * va-sh.h (__va_arg_sh1): Use __asm instead of asm.
- * Makefile.in (WARN_CFLAGS): New variable.
- (bootstrap, bootstrap2, bootstrap3, bootstrap4): Use it.
+ * (__VA_REEF): Define.
+ (__va_arg_sh1): Use it.
-1998-02-11 Mark Mitchell <mmitchell@usa.net>
+ * va-sh.h (va_start, va_arg, va_copy): Add parentheses.
- * config/i386/i386.c (reg_mentioned_in_mem): Don't abort when
- falling through default case in switch.
- (i386_aligned_p): Likewise.
+Sun Nov 22 21:34:02 1998 Jeffrey A Law (law@cygnus.com)
-Wed Feb 11 12:59:56 1998 Lee Iverson <leei@Canada.AI.SRI.COM>
+ * i386/dgux.c (struct option): Add new "description field".
+ * m88k/m88k.c (struct option): Likewise.
- * mips/mips.h (mips_abi_string): Correct typo in comment.
+Sun Nov 22 16:07:57 1998 Jeff Law (law@cygnus.com)
-Wed Feb 11 08:29:56 1998 Gavin Koch <gavin@cygnus.com>
+ * version.c: Bump for snapshot.
- * mips/mips.md (movdi): These PLUS's need to be Pmode.
+Sun Nov 22 13:40:02 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
-Wed Feb 11 01:47:54 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * regmove.c (regmove_profitable_p): Use return value of find_matches
+ properly.
- * Makefile.in (dwarf2out.o, emit-rtl.o, jump.o, cse.o, unroll.o,
- reorg.o, regmove.o): Depend on insn-codes.h, it gets included
- indirectly via expr.h.
+Sun Nov 22 02:47:37 1998 Jeff Law (law@cygnus.com)
-Wed Feb 11 01:44:13 1998 Richard Henderson <rth@cygnus.com>
+ * version.c: Bump for snapshot.
- * stor-layout.c (layout_type): Do upper - lower in the native type,
- so as to properly handle negative indices.
+Sat Nov 21 22:12:09 1998 Jeffrey A Law (law@cygnus.com)
+
+ * reload1.c (eliminate_regs): Do not lose if eliminate_regs is called
+ without reload having been called earlier.
+
+ * v850.c (ep_memory_operand): Offsets < 0 are not valid for EP
+ addressing modes.
+ (v850_reorg): Similarly.
+
+ * loop.c (check_dbra_loop): Avoid using gen_add2_insn.
+
+Sat Nov 21 02:18:38 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * loop.c (move_movables): Start of libcall might be new loop start.
+
+Fri Nov 20 12:14:16 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * hash.c (hash_table_init_n): Wrap prototype arguments in PARAMS().
+
+Fri Nov 20 08:34:00 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * function.c (nonlocal_goto_handler_slots): Renamed from
+ nonlocal_goto_handler_slot; now an EXPR_LIST chain.
+ (push_function_context_to): Adjust for this change.
+ (pop_function_context_from): Likewise.
+ (init_function_start): Likewise.
+ (expand_function_end): Likewise.
+ * function.h (struct function): Likewise.
+ * calls.c (expand_call): Likewise.
+ * explow.c (allocate_dynamic_stack_space): Likewise.
+ * expr.h (nonlocal_goto_handler_slots): Rename its declaration.
+ * stmt.c (declare_nonlocal_label): Make a new handler slot for each
+ label.
+ (expand_goto): When doing a nonlocal goto, find corresponding handler
+ slot for it. Don't put the label address in the static chain register.
+ (expand_end_bindings): Break out nonlocal goto handling code into
+ three new functions.
+ (expand_nl_handler_label, expand_nl_goto_receiver,
+ expand_nl_goto_receivers): New static functions, broken out of
+ expand_end_bindings and adapted to create one handler per nonlocal
+ label.
+ * function.c (delete_handlers): Delete insn if it references any of
+ the nonlocal goto handler slots.
+ * i960.md (nonlocal_goto): Comment out code that modifies
+ static_chain_rtx.
+ * sparc.md (nonlocal_goto): Likewise.
+ (goto_handler_and_restore_v9): Comment out.
+ (goto_handler_and_restore_v9_sp64): Comment out.
+
+Thu Nov 19 23:44:38 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * expr.c (STACK_BYTES): Delete unused macro.
+ * calls.c: Provide default for PREFERRED_STACK_BOUNDARY.
+ (STACK_BYTES): Use PREFERRED_STACK_BOUNDARY, not STACK_BOUNDARY.
+ (expand_call): Likewise.
+ (emit_library_call): Likewise.
+ (emit_library_call_value): Likewise.
+ * function.c: Provide default for PREFERRED_STACK_BOUNDARY.
+ (STACK_BYTES): Use PREFERRED_STACK_BOUNDARY, not STACK_BOUNDARY.
+ * explow.c: Provide default for PREFERRED_STACK_BOUNDARY.
+ (round_push): Use PREFERRED_STACK_BOUNDARY, not STACK_BOUNDARY.
+ (allocate_dynamic_stack_space): Likewise.
+ * tm.texi (PREFERRED_STACK_BOUNDARY): Document new macro.
+ (STACK_BOUNDARY): Update description to reflect the new situation.
-Wed Feb 11 01:35:55 1998 Robert Lipe <robertl@dgii.com>
+Thu Nov 19 22:20:51 1998 Jeffrey A Law (law@cygnus.com)
- * except.c (start_dynamic_cleanup): Remove unused variable 'dhc'.
- (expand_eh_region_start_tree): Remove unused variable 'note'.
- (exception_optimize): Remove unused variable 'regions'.
- (expand_builtin_eh_stub): Remove unused variable 'temp'.
- (copy_eh_entry): Deleted. Dead function.
+ * reorg.c (relax_delay_slots): When optimizing for code size, if a
+ return with a filled delay slot is followed by a return with an
+ unfilled delay slot, delete the first return and reemit the insn
+ that was previously in its delay slot.
- * expr.c (move_block_to_reg) Bracket declaration of 'pat' and
- 'last' with same #if HAVE_load_multiple as use of it.
- (move_block_from_reg): Likewise.
- (emit_move_insn_1): Remove unused variable 'insns'.
- (store_constructor): Bracket declaration of startb, endb with
- #if TARGET_MEMFUNCTIONS. Remove unused variables 'set_word_size'
- 'target', and 'xtarget'.
- (expand_builtin_setjmp): Remove unused variables 'op0',
- 'next_arg_reg', 'old_inhibit_defer_pop'.
- (expand_builtin): Remove unused variable 'offset'.
- (do_store_flag): Remove unused variables 'pattern', 'jump_pat'.
- (emit_queue): Add parens for assignment used as conditional.
- (expand_expr): case TARGET_EXPR: Remove unused variable 'temp'.
+ * i860.c (single_insn_src_p): Add missing parens.
+ * ginclude/math-3300.h: Likewise.
-Wed Feb 11 01:30:49 1998 Marc Lehmann <pcg@goof.com>
+Thu Nov 19 20:55:59 1998 H.J. Lu (hjl@gnu.org)
- * i386.c: Added include for recog.h.
- (override_options): Removed unused variable p. Initialized regno to
- avoid warning.
- (order_regs_for_local_alloc): Initialized regno to avoid warning.
- (legitimize_address): Likewise for 'other'.
- (i386_aligned_reg_p): Added default case with abort ().
- (print_operand): Likewise.
- (reg_mentioned_in_mem): Likewise.
- (ix86_expand_binary_operator): Removed unused variables i & insn.
- (ix86_expand_unary_operator): Removed unused variable insn.
- (output_fp_cc0_set): Removed unused variable unordered_label.
+ * regclass.c (init_reg_sets_1): Add prototype.
+ (init_reg_modes): Likewise.
-Wed Feb 11 01:23:03 1998 John F. Carr <jfc@mit.edu>
+1998-11-19 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * i386.c, i386.h, i386.md: Change gen_rtx (X, ...) to gen_rtx_X (...).
- Use GEN_INT instead of gen_rtx (CONST_INT). Make printf arguments
- and format string match.
+ * c-common.c: Change warning messages to say `comparison is
+ always true' or `comparison is always false' instead of the
+ confusing `is always 0', `is always 1'.
-Wed Feb 11 01:17:39 1998 Jeffrey A Law (law@cygnus.com)
+Thu Nov 19 19:05:49 1998 Per Bothner <bothner@cygnus.com>
- * flow.c (life_analysis): Do not conside the stack pointer live at
- the end of a function if the fucntio ncalls alloca.
- (mark_used_regs): Similarly.
+ * print-tree.c (print_node): After printing BLOCK or BIND_EXPR,
+ break instead of return (which loses closing '>').
-1998-02-10 John F Carr <jfc@mit.edu>
+Thu Nov 19 19:34:13 1998 Jeffrey A Law (law@cygnus.com)
- * config/sparc/sparc.md (movdi_v8plus): Output stx on alternative
- 1, fzero on alternative 8.
+ * i386.h (LEGITIMATE_CONSTANT_P): Reject CONST_DOUBLEs that are not
+ standard 387 constants.
-Tue Feb 10 09:02:19 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * i386.md (jump): Explicitly set "memory" attribute.
+ (indirect_jump, prologue_set_stack_ptr): Likewise.
+ (prologue_get_pc_and_set_got, pop): Likewise.
+ (allocate_stack_worder, blockage, return_internal): Likewise.
+ (return_pop_internal, nop): Likewise.
+ (epilogue_set_stack_ptr, leave): Likewise.
- * rs6000.c (setup_incoming_varargs): Always set rs6000_sysv_varargs_p.
+Thu Nov 19 15:42:54 1998 Nick Clifton <nickc@cygnus.com>
-Tue Feb 10 03:35:43 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * config/arm/coff.h: Set USER_LABEL_PREFIX to "_".
- * reload.c (find_reloads_toplev): Handle arbitrary non-paradoxical
- SUBREGs of CONST_INTs.
+Thu Nov 19 23:20:59 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Mon Feb 9 17:52:36 1998 John Carr <jfc@mit.edu>
+ * reload1.c (reload_reg_free_for_value_p):
+ Early auto_inc reloads don't conflict with outputs.
- * mips.c (print_operand, function_prologue): Make printf format
- match argument type.
+Thu Nov 19 12:58:55 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon Feb 9 02:37:25 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * configure.in: Don't do AC_CHECK_HEADERS(wait.h sys/wait.h).
+ Instead call AC_HEADER_SYS_WAIT.
- * alpha.c (alpha_return_addr): Remove unused variable `first'.
- (alpha_ra_ever_killed): Remove unused variables `ra' and `i'.
- (output_epilog): Remove unused variable `frame_size_from_reg_save'.
+ * collect2.c: Don't provide defaults for sys/wait.h macros.
+ * gcc.c: Likewise.
+ * protoize.c: Likewise. Also, don't include sys/wait.h.
-Sun Feb 8 14:56:03 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * system.h: Include sys/wait.h and provide macro defaults.
- * loop.c (strength_reduce): When placing increment for auto-inc
- case, do comparison in loop order.
+1998-11-19 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Sun Feb 8 13:21:38 1998 John Carr <jfc@mit.edu>
+ * Makefile.in (mandir): Set to @mandir@.
+ (man1dir): New variable to hold the former value of $(mandir).
+ Replace all uses of $(mandir) by $(man1dir).
- * bitmap.c (bitmap_debug_file): HOST_PTR_PRINTF converts a pointer,
- not a HOST_WIDE_INT.
+Wed Nov 18 16:31:28 1998 Jim Wilson <wilson@cygnus.com>
- * calls.c (expand_call): Change test of expand_inline_function
- return value to stop compiler warning.
+ * reload.c (find_reloads_address_part): If have a CONST_INT, create
+ a new one before passing it to force_const_mem.
- * genattrtab.c (RTL_HASH): Cast pointer to long, not HOST_WIDE_INT.
+ * reload.c (find_reloads_toplev): Pass &x instead of NULL_PTR in
+ find_reloads_address call.
-Sun Feb 8 12:04:24 1998 Jim Wilson (wilson@cygnus.com)
- Jeff Law (law@cygnus.com)
+Wed Nov 18 22:13:00 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * regmove.c: Fix various minor formatting problems.
- (optimize_reg_copy_1): Stop search at CALL_INSNs if flag_exceptions
- is true. Make end of basic block tests consistent through regmove.c.
- (optimize_reg_copy_2, optimize_reg_copy_3): Likewise.
- (fixup_match_2, fixup_match_1, regmove_optimize): Likewise.
+ * expr.c (store_expr): Don't generate load-store pair
+ if TEMP is identical (according to ==) with TARGET.
-Sun Feb 8 01:49:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Tue Nov 17 22:25:16 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * gansidecl.h: Check for a conflicting macro definition before
- attempting to prototype bcopy, bcmp or bzero.
+ * reload1.c (reload_reg_free_for_value_p): When considered reload
+ has an output, matching inputs are not sufficient to avoid conflict.
-Sun Feb 8 00:09:59 1998 Jeffrey A Law (law@cygnus.com)
+Tue Nov 17 11:51:16 1998 Mark Mitchell <mark@markmitchell.com>
- * expr.c (clear_pending_stack_adjust): Handle case where a function
- calls alloca, but the user has specified -fomit-fframe-pointer.
+ * hash.h (hash_table_key): New type.
+ (hash_entry): Change `string' field to generic `key'.
+ (hash_table): Add `comp' and `hash' functions.
+ (hash_table_init): Take them as input.
+ (hash_table_init_n): Likewise.
+ (hash_lookup): Modify for generic keys.
+ (hash_newfunc): Likewise.
+ (hash_traverse): Likewise.
+ (string_hash): New function.
+ (string_compare): Likewise.
+ (string_copy): Likewise.
+ * hash.c (hash_table_init_n): Modify for generic keys.
+ (hash_table_init): Likewise.
+ (hash_lookup): Likewise.
+ (hash_newfunc): Likewise.
+ (hash_traverse): Likewise.
+ (string_hash): Split out from hash_lookup.
+ (string_compare): New function.
+ (string_copy): Split out from hash_lookup.
+ * tlink.c (symbol_hash_newfunc): Modify for new interfaces to hash
+ tables.
+ (symbol_hash_lookup): Likewise.
+ (file_hash_newfunc): Likewise.
+ (file_hash_lookup): Likewise.
+ (demangled_hash_newfunc): Likewise.
+ (demangled_hash_lookup): Likewise.
+ (tlink_int): Likewise.
+ (read_repo_file): Likewise.
+ (recompile_files): Likewise.
+ (demangle_new_symbols): Likewise.
+ (scan_linker_output): Likewise.
- * function.c (assign_parms): Fix typo in last change.
+Tue Nov 17 17:13:53 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Sat Feb 7 23:54:29 1998 Robert Lipe <robertl@dgii.com>
+ * flow.c (insn_dead_p): New argument NOTES. Changed all callers.
- * gcc.c: Include <strings.h>/<string.h>, <stdlib.h>, <unistd.h>,
- <fcntl.h>.
- (free_path_suffix): Remove unreferenced static function.
- (process_command): Remove unused variable temp.
- (default_arg): Remove unused variable i.
- (do_spec_1): Add parens for assignment used as truth value.
- (main): Likewise.
- (validate_all_switches): Likewise.
- (main): Remove unused variables i, first_time>
+Mon Nov 16 17:56:07 1998 David Edelsohn <edelsohn@gnu.org>
- * c-common.c: Include <stdlib.h> and <string.h>/<strings.h>.
+ * rs6000.c (output_mi_thunk): Improve test for local branch.
- * calls.c (expand_call): Remove unused variables funtree,
- n_regs, and tmpmode.
+Mon Nov 16 17:56:07 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * dbxout.c, except.c: Include <string.h>/<strings.h>.
+ * rs6000.c (output_mi_thunk): Correct test for aggregate values.
- * explow.c: (plus_constant_for_output_wide) Removed unused
- variable all_constant.
+Mon Nov 16 21:02:52 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * c-decl.c, genattr.c, genattrtab.c, getconfig.c, genemit.c
- genextract.c, genflags.c, genopinit.c genoutput.c, genpeep.c,
- genrecog.c, global.c, integrate.c , stupid.c : Include
- <stdlib.h>.
+ * reload1.c (reload_reg_free_before_p): Delete.
+ Changed all callers to use reload_reg_free_for_value_p instead.
+ (reload_reg_free_for_value_p): Handle more reload types.
+ A RELOAD_FOR_INPUT doesn't conflict with its
+ RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS.
+ Add special case for OUT == const0_rtx.
+ Added ignore_address_reloads argument. Changed all callers.
- * genextract.c: (walk_rtx) Remove unused variable link.
+Mon Nov 16 02:22:29 1998 Jason Merrill <jason@yorick.cygnus.com>
- * genrecog.c: (concat) Remove unreferenced static function.
+ * toplev.c (compile_file): Don't pedwarn about undefined static
+ functions just because we passed -Wunused.
- * prefix.c: Include <string.h>/<strings.h>, <stdlib.h>
+Mon Nov 16 04:41:41 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * stmt.c: Include <stdlib.h>.
- (expand_asm_operands): Remove unused variable val1.
- (expand_return): Remove unused variable block.
- (pushcase): Remove unused variables l and n.
- (pushcaserange): Likewise.
+ * function.c (purge_addressof_1): Unshare rtl created by
+ store_bit_field.
- * unroll.c (unroll_loop): Remove unused variable temp.
+Mon Nov 16 04:23:06 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Sat Feb 7 23:46:09 1998 Greg McGary <gkm@gnu.org>
+ * regmove.c (regmove_optimize): Don't do anything but
+ optimize_reg_copy[123] when flag_regmove is not set.
- * c-decl.c (pushdecl): Set DECL_ORIGINAL_TYPE once only.
+Sat Nov 14 15:05:07 1998 Richard Henderson <rth@cygnus.com>
-Sat Feb 7 15:11:28 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * alpha.md (addsi3, subsi3): Revise 5 Nov change to store DImode
+ value in paradoxical SImode result, rather than truncating midpoint.
- * aclocal.m4 (GCC_FUNC_PRINTF_PTR): New macro to test the printf
- functions for whether they support the %p format specifier.
- * acconfig.h (HOST_PTR_PRINTF): Insert stub for autoconf.
- * configure.in (GCC_FUNC_PRINTF_PTR): Use it.
- * configure, config.in: Rebuild.
+Fri Nov 13 22:19:23 1998 Richard Henderson <rth@cygnus.com>
-Fri Feb 6 14:20:16 1998 Jim Wilson <wilson@cygnus.com>
+ * alpha.c (reg_not_elim_operand): New.
+ * alpha.h (PREDICATE_CODES): Add it.
+ * alpha.md (s48addq, s48subq patterns): Use it as the predicate
+ for the multiplicand.
+
+Fri Nov 13 22:50:37 1998 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.md (movsf): Remove explicit secondary-reload-like
+ functionality. Only truncate SFmode store if in FPR.
+ (movsf splitters): Combine const_double splitters.
+ (movsf_hardfloat): Add GPR support.
+
+Fri Nov 13 11:02:11 1998 Stan Cox <scox@cygnus.com>
+
+ * splet.h (SUBTARGET_OVERRIDE_OPTIONS): New to
+ deprecate -mlive-g0 and -mbroken-saverestore.
+ * t-splet (MULTILIB_OPTIONS): Likewise.
+
+ * sparc.c (sparc_flat_compute_frame_size): Correctly calc args_size
+ in a leaf function. Clarify total_size/extra_size relationship.
+
+Thu Nov 12 19:20:57 1998 Geoffrey Noer <noer@cygnus.com>
+
+ * i386/cygwin32.asm: Delete.
+ * i386/cygwin.asm: New file, renamed from cygwin32.asm.
+ * i386/cygwin32.h: Delete.
+ * i386/cygwin.h: New file, renamed from cygwin32.h.
+ * i386/t-cygwin32: Delete.
+ * i386/t-cygwin: New file, renamed from t-cygwin32. Include
+ cygwin.asm instead of cygwin32.asm. Remove "32" from comment.
+ * i386/x-cygwin32: Delete.
+ * i386/x-cygwin: New file, renamed from x-cygwin32.
+ * i386/xm-cygwin32: Delete.
+ * i386/xm-cygwin: New file, renamed from xm-cygwin32. Use newly
+ renamed cygwin_ funcs for path translations.
+ * i386/win32.h: Define __CYGWIN__ when -mcygwin given.
+ * i386/winnt.c: Remove "32" from comment about cygwin.
+ * i386/mingw32.h: Fix references to cygwin32.h in light of above.
+ * rs6000/cygwin32.h: Delete.
+ * rs6000/cygwin.h: New file, renamed from cygwin32.h. Add
+ -D__CYGWIN__ to CPP_PREDEFINES.
+ * rs6000/x-cygwin32: Delete.
+ * rs6000/x-cygwin: New file, renamed from x-cygwin32.
+ * rs6000/xm-cygwin32: Delete.
+ * rs6000/xm-cygwin: New file, renamed from xm-cygwin32.
+
+ * configure.in: Check for cygwin* instead of cygwin32. Account
+ for the rename of cygwin-related config files to lose the "32"s.
+ * configure: Regenerate.
- * function.c (assign_parms): New variable named_arg, with value
- depending on STRICT_ARGUMENT_NAMING. Use instead of ! last_named.
+ * cccp.c, collect2.c, gcc.c, getpwd.c, libgcc2.c, protoize.c,
+ toplev.c: Change all refs to __CYGWIN32__ to __CYGWIN__.
-Fri Feb 6 14:34:28 1998 Gavin Koch <gavin@cygnus.com>
+Wed Nov 11 12:25:19 1998 Tom Tromey <tromey@cygnus.com>
- * mips/t-r3900: New - same as t-ecoff but eliminate
- multilibs: mips1 and mips3.
- * configure.in (tx39*): Use new mips/t-r3900.
- * configure: Rebuild.
- * mips/r3900.h (MULTILIB_DEFAULTS): Eliminate mips1.
+ * Makefile.in (JAVAGC): New macro.
+ * configure: Rebuilt.
+ * configure.in: Recognize --enable-java-gc argument. Subst
+ `JAVAGC' variable.
-1998-02-06 Jason Merrill <jason@yorick.cygnus.com>
+Thu Nov 12 03:32:16 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * dwarf2out.c: Add old_args_size.
- (dwarf2out_args_size): Use it.
- (dwarf2out_begin_prologue): Initialize it.
- (dwarf2out_stack_adjust): If !asynchronous_exceptions, save up
- pushed args until we see a call.
- * final.c (final_scan_insn): Hand CALL_INSNs off to the dwarf2 code
- before outputting them.
+ Handle equivalences that have been obscured by gcse:
-1998-02-06 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
+ * reload1.c (reload): Handle equivalences set up in multiple places.
+ * local-alloc.c (reg_equiv_init_insns): New variable.
+ (no_equiv): New function.
+ (update_equiv_regs): Handle equivalences set up in multiple places.
+ Don't ignore an insn just because its destination is likely to be
+ spilled.
- * cplus-dem.c (demangle_template_template_parm): New function.
- (demangle_template): Handle template template parameters.
+Wed Nov 11 13:46:13 1998 Jim Wilson <wilson@cygnus.com>
-1998-02-02 Mark Mitchell <mmitchell@usa.net>
+ * except.c (expand_eh_return): Readd force_operand call lost in
+ Sept 15 change.
- * calls.c (expand_call): Don't confuse member functions named
- realloc, setjmp, and so forth with the standard library
- functions of the same names.
+Tue Nov 10 17:04:11 1998 David Edelsohn <edelsohn@gnu.org>
-Thu Feb 5 21:59:49 1998 Jeffrey A Law (law@cygnus.com)
+ * rs6000.h (LEGITIMIZE_ADDRESS): Add missing goto on last case.
- * stmt.c (expand_asm_operands): Correctly identify asm statements
- no output operands.
+1998-11-09 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Thu Feb 5 21:56:06 1998 Mumit Khan <khan@xraylith.wisc.edu>
+ * dbxout.c: Check HAVE_STAB_H instead of HAVE_STABS_H.
- * c-common.c (decl_attributes): Flag unrecognized attribute
- functions as warnings instead of as errors.
+Mon Nov 9 20:15:19 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * regmove.c (regmove_optimize): Fix error in last change.
-1998-02-05 Marc Lehmann <pcg@goof.com>
+Mon Nov 9 16:37:52 1998 Andrew Cagney <cagney@b1.cygnus.com>
- * integrate.c (INTEGRATE_THRESHOLD): Inline only small functions
- when -Os is specified.
- * toplev.c (main): Don't disable flag_inline_functions anymore when
- -Os is in effect.
+ * mips.c (function_prologue): When TARGET_MIPS16, adjust the register
+ offset in the .mask pseudo to compensate for frame pointer adjustments.
+ (mips16_fp_args, build_mips16_call_stub): For little endian, do not
+ word swap arguments moved to/from FP registers.
+ * mips16.S (DFREVCMP): Reverse arguments to OPCODE.
-Fri Feb 6 00:27:36 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Nov 9 09:47:06 1998 Jeff Law (law@cygnus.com)
- * regmove.c: Update.
- * flags.h (flag_regmove): Declare.
- * rtl.h (optimize_reg_copy_1, optimize_reg_copy_2): Don't declare.
- * local-alloc.c (optimize_reg_copy_1, optimize_reg_copy_2):
- Moved into regmove; changed caller.
- * toplev.c (rest_of_compilation): Call regmove_optimize also for
- expensive_optimizations.
+ * version.c: Bump for snapshot.
-Thu Feb 5 13:38:42 PST 1998 Jeff Law (law@cygnus.com)
+Mon Nov 9 02:14:14 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Thu Feb 5 01:45:19 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- Undo this change (the problem was actually in reload):
- Fri Jan 23 23:28:59 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Nov 9 03:06:24 1998 Jeffrey A Law (law@cygnus.com)
+
+ * reload1.c (delete_output_reload_insn): If a pseudo is set multiple
+ times, then it can not be completely replaced.
+
+Mon Nov 9 00:39:02 1998 Richard Henderson <rth@cygnus.com>
+
+ * alpha.md (call, call_value) [OSF]: Correct alt 3 insn length.
+
+Sun Nov 8 17:50:30 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * sh.md (movqi_i+1): New peephole.
+ * gansidecl.h: Prepend a "G" to the macro wrapping this file
+ (to distinguish it from the macro wrapping ansidecl.h.)
+ Include libiberty's ansidecl.h. Remove all redundant definitions.
+ Define the PROTO() style macros in terms of the PARAMS() ones.
-Tue Feb 3 01:11:12 1998 Jeffrey A Law (law@cygnus.com)
- * jump.c (jump_optimize): Lose calls to modified_in_p they are
- not needed anymore due to changes elsewhere in jump.c.
+ * calls.c (emit_library_call): Switch on ANSI_PROTOTYPES, not
+ __STDC__, when deciding whether to use ANSI variable args.
+ (emit_library_call_value): Likewise.
- * jump.c (jump_optimize): Fix first arg to modified_in_p in
- previous change.
+ * cccp.c (error): Likewise.
+ (warning): Likewise.
+ (error_with_line): Likewise.
+ (warning_with_line): Likewise.
+ (pedwarn): Likewise.
+ (pedwarn_with_line): Likewise.
+ (pedwarn_with_file_and_line): Likewise.
+ (fatal): Likewise.
-Mon Feb 2 19:18:14 1998 Richard Henderson <rth@cygnus.com>
+ * cexp.y (error): Likewise.
+ (pedwarn): Likewise.
+ (warning): Likewise.
- * expr.c (expand_builtin_setjmp): Accept two new arguments for
- the labels to branch to on first and subsequent executions. Don't
- play with __dummy. Rename `setjmp' insn to `builtin_setjmp_setup',
- and provide it with the jmp_buf. Use only one of
- `builtin_setjmp_receiver' or `nonlocal_goto_receiver',
- and provide the former with the target label.
- (expand_builtin) [BUILTIN_SETJMP]: Generate a label for use by setjmp.
- (expand_builtin) [BUILTIN_LONGJMP]: Split out to ...
- (expand_builtin_longjmp): ... here. Recognize a `builtin_longjmp'
- insn to replace all of the normal nonlocal_goto code. Don't play
- with __dummy. Correct arguments to nonlocal_goto.
- * expr.h (expand_builtin_setjmp): Update prototype.
- * except.c (start_dynamic_handler): When using builtin_setjmp,
- generate more accurate flow information.
+ * collect2.c (fatal_perror): Likewise.
+ (fatal): Likewise.
+ (error): Likewise.
- * alpha.md (nonlocal_goto_receiver_osf): Delete.
- (nonlocal_goto_receiver_vms): Rename to nonlocal_goto_receiver.
- (builtin_longjmp, builtin_setjmp_receiver): New.
- * sparc.md (update_return): Disambiguate unspec number.
- (nonlocal_goto): Rearrange arguments to match caller in except.c.
- (builtin_setjmp_setup): Rename from setjmp. Match and ignore the
- jmp_buf operand.
- * mips.md (nonlocal_goto_receiver, builtin_setjmp_receiver): Remove.
- (builtin_setjmp_setup*, builtin_longjmp): New.
+ * combine.c (gen_rtx_combine): Likewise.
-Mon Feb 2 16:43:10 1998 John Carr <jfc@mit.edu>
+ * cpperror.c (cpp_message): Likewise.
+ (cpp_fatal): Likewise.
- * mips.md: Change gen_rtx (CONST_INT) to GEN_INT.
+ * cpplib.c (cpp_error): Likewise.
+ (cpp_warning): Likewise.
+ (cpp_pedwarn): Likewise.
+ (cpp_error_with_line): Likewise.
+ (cpp_warning_with_line): Likewise.
+ (cpp_pedwarn_with_line): Likewise.
+ (cpp_pedwarn_with_file_and_line): Likewise.
-Mon Feb 2 13:06:47 1998 Jim Wilson <wilson@cygnus.com>
+ * cpplib.h: Don't define PARAMS() macro.
- * vmsconfig.com: Remove bytecode references.
+ * demangle.h: Likewise.
-1998-01-30 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * doprint.c (checkit): Switch on ANSI_PROTOTYPES, not __STDC__,
+ when deciding whether to use ANSI variable args.
- * dwarf2out.c (dwarf2out_frame_init): Undo last change, so that
- -fno-sjlj-exceptions works for a target that defines
- DWARF2_UNWIND_INFO as zero.
+ * emit-rtl.c (gen_rtx): Likewise.
+ (gen_rtvec): Likewise.
- * regmove.c (fixup_match_1): Undo last change which removed some
- "useless" code, and add a comment explaining this.
+ * final.c (asm_fprintf): Likewise.
-Mon Feb 2 10:47:14 1998 Gavin Koch (gavin@cygnus.com)
+ * fix-header.c (cpp_message): Likewise.
+ (fatal): Likewise.
+ (cpp_fatal): Likewise.
- * mips.c (mips_expand_prologue): Change uses of TARGET_64BIT
- to TARGET_LONG64.
+ * gcc.c (concat): Likewise.
+ (fatal): Likewise.
+ (error): Likewise.
-Mon Feb 2 10:38:41 1998 Klaus Kaempf <kkaempf@progis.de>
+ * genattr.c (fatal): Likewise.
- * makefile.vms: Remove bytecode references.
- Create genrtl files.
+ * genattrtab.c (attr_rtx): Likewise.
+ (attr_printf): Likewise.
+ (fatal): Likewise.
-Mon Feb 2 02:08:04 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+ * gencodes.c (fatal): Likewise.
- * jump.c (jump_optimize): Allow conditional loading of floating point
- constants and constants from memory. Reinstalled modified_in_p tests.
+ * genconfig.c (fatal): Likewise.
-Mon Feb 2 01:38:39 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * genemit.c (fatal): Likewise.
- * loop.c (get_condition): Handle sign-extended constants.
+ * genextract.c (fatal): Likewise.
-Mon Feb 2 01:22:46 1998 Hans-Peter Nilsson <hp@axis.se>
+ * genflags.c (fatal): Likewise.
- * expr.c (emit_push_insn): Add code to use movstrti if present.
+ * genopinit.c (fatal): Likewise.
- * expr.c (emit_push_insn): Use same max-move-amount for movstrhi
- and movstrqi as in emit_block_move ().
+ * genoutput.c (fatal): Likewise.
+ (error): Likewise.
-Mon Feb 2 00:09:52 1998 Toon Moene <toon@moene.indiv.nluug.nl>
+ * genpeep.c (fatal): Likewise.
- * config/m68k/x-next: Remove /NextDeveloper/Headers from
- the directories to fixinclude - /usr/include is a link
- to it and hence its contents are fixed by default.
+ * genrecog.c (fatal): Likewise.
-Sun Feb 1 14:15:33 1998 Franz Sirl <franz.sirl-kernel@lauterbach.com>
+ * halfpic.h: Switch on ANSI_PROTOTYPES, not __STDC__, when
+ deciding whether to declare `tree_node' and `rtx_def'.
- * rs6000/linux.h: define JUMP_TABLES_IN_TEXT_SECTION
+ * hash.h: Don't define stuff we get from gansidecl.h.
-Sun Feb 1 13:01:15 1998 Klaus Kaempf <kkaempf@progis.de>
+ * mips-tfile.c: Likewise. Define __proto() in terms of PARAMS().
+ (fatal): Switch on ANSI_PROTOTYPES, not __STDC__, when deciding
+ whether to use ANSI variable args.
+ (error): Likewise.
- * cccp.c (main): Predefine __VMS_VER on VMS.
+ * prefix.c (concat): Likewise.
-Sun Feb 1 12:39:53 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * scan.h: Likewise.
- * expr.c (get_inner_reference): Use sbitsizetype for type sizes.
- * fold-const.c (size_int): Replace with
- (size_int_wide).
- (make_bit_field_ref): Use bitsize_int for bit position.
- * stor-layout.c (sizetype): Delete.
- (sizetype_tab, sbitsizetype, ubitsizetype): Declare.
- (layout_record, layout_union, layout_type):
- Use bitsize_int for bit size.
- (set_sizetype): New function.
- (make_signed_type, make_unsigned_type): Use it.
- * c-decl.c (init_decl_processing): Likewise.
- * tree.h (size_int): Don't delcare, #define.
- (size_int_wide, sizetype_tab, sbitsize, ubitsize): Declare.
- (set_sizetype): Declare.
- (bitsize_int, size_int_2, BITS_PER_UNIT_LOG, sizetype, bitsizetype):
- Define.
- * c-typeck.c (c_sizeof, c_sizeof_nowarn, c_size_in_bytes):
- Convert result to sizetype.
- (really_start_incremental_init, push_init_level):
- Set type of constructor_bit_index to sbitsizetype.
- (push_init_level): Use unsigned arithmetic to determine padding.
- (output_init_element): Likewise.
-
-Sun Feb 1 03:32:07 1998 Jeffrey A Law (law@cygnus.com)
-
- * combine.c (simplify_shift_const): Fix typo in last change.
-
-Sun Feb 1 02:50:46 1998 John Carr <jfc@mit.edu>
-
- * combine.c (simplify_shift_const): (lshiftrt (truncate (lshiftrt)))
- is (truncate (lshiftrt)).
-
-Sun Feb 1 01:06:53 1998 Richard Henderson <rth@cygnus.com>
-
- * alpha.c (alpha_expand_unaligned_load): Use expand_binop properly.
- Make sure result winds up in TGT.
- (alpha_expand_unaligned_store): Use expand_binop properly. Allow
- src to be other than DImode.
- (alpha_expand_unaligned_load_words): Tidy. Take an offset argument.
- (alpha_expand_unaligned_store_words): Likewise.
- (alpha_expand_block_move): Use REGNO_POINTER_ALIGN. Restructure so
- that source and destination are separately optimized for alignment.
- (alpha_expand_block_clear): Use REGNO_POINTER_ALIGN.
-
-Sun Feb 1 01:55:09 1998 Jeffrey A Law (law@cygnus.com)
-
- * mips.md (adddi3_internal_2): Be consistent with adddi3 expander
- with handling of -32768.
-
-Sun Feb 1 01:48:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * aclocal.m4 (GCC_NEED_DECLARATION): Modify macro to accept a
- shell variable argument instead of only hard coded functions.
- (GCC_NEED_DECLARATIONS): New macro to accept multiple functions.
-
- * configure.in: Collapse multiple calls to AC_CHECK_FUNCS into one
- call. Collapse multiple calls to GCC_NEED_DECLARATION into one
- call to GCC_NEED_DECLARATIONS (new macro.) Check if we need
- declarations for bcopy, bcmp and bzero.
-
- * acconfig.h: Add stubs for bcopy, bcmp and bzero declarations.
-
- * gansidecl.h: If we have bcopy but don't declare it, then do so.
- Likewise for bcmp and bzero. Only define macros for bcopy, bcmp,
- bzero, index and rindex if they aren't already present.
-
-Sat Jan 31 11:26:58 1998 Jeffrey A Law (law@cygnus.com)
-
- * toplev.c (close_dump_file): Wrap function prototype for
- argument "func" in PROTO.
- (dump_rtl): Likewise.
-
-Fri Jan 30 22:30:39 1998 John Carr <jfc@mit.edu>
-
- * sparc.c (sparc_override_options): Make v8plus and ultrasparc set
- MASK_V8PLUS.
- (output_function_epilogue): Omit epilogue if nothing drops through.
- (output_move_double): Supress int ldd usage on ultrasparc and v9.
- (registers_ok_for_ldd_peep): Likewise.
- (print_operand): Supress b,a on ultrasparc. Let Y accept a constant.
- (ultrasparc_adjust_cost): New function.
- (sparc_issue_rate): New function.
- * sparc.h (MASK_VIS, TARGET_VIS): New
- (MASK_V8PLUS, TARGET_V8PLUS): New.
- (TARGET_HARD_MUL32, TARGET_HARD_MUL): New.
- (TARGET_SWITCHES): Add vis and v8plus.
- (REG_CLASS_FROM_LETTER): Accept d and b for VIS.
- (REGISTER_MOVE_COST): FP<->INT move cost 12 for ultrasparc.
- (RTX_COSTS): Use TARGET_HARD_MUL
- (ADJUST_COST): Call ultrasparc_adjust_cost.
- (ISSUE_RATE): New.
- * sparc.md (attr type): Add sload, fpmove, fpcmove. Adjust users
- of load & fp appropritely.
- (supersparc function units): Adjust for Haifa.
- (ultrasparc function units): Likewise.
- (get_pc_via_rdpc): All v9, not just arch64.
- (movdi_v8plus, movdi_v8plus+1): New.
- (adddi3_sp32+1): New.
- (subdi3_sp32+1): New.
- (movsi_insn, movsf_const_insn, movdf_const_insn): Know VIS.
- (addsi3, subsi3, anddi3_sp32, andsi3, and_not_di_sp32): Likewise.
- (and_not_si, iordi3_sp32, iorsi3, or_not_di_sp32, or_not_si): Likewise.
- (xorsi3_sp32, xorsi3, xor_not_di_sp32, xor_not_si): Likewise.
- (one_cmpldi2_sp32, one_cmplsi2): Likewise.
- (ldd peepholes): Suppress for v9.
- (return_adddi): Kill redundant test. Arg1 may be arith_operand.
- (return_subsi): Revmove.
-
-Fri Jan 30 18:30:03 1998 John F Carr <jfc@mit.edu>
-
- * mips.c (save_restore_insns): Set RTX_UNCHANGING_P in register
- save/restore MEM rtl.
-
-Fri Jan 30 09:08:16 1998 Jeffrey A Law (law@cygnus.com)
-
- * configure.in: Check for declaration of abort.
- * acconfig.h: Corresponding changes.
- * toplev.c: Use NEED_DECLARATION_ABORT to determine if abort should
- be declared.
-
-Thu Jan 29 20:26:12 1998 Jeffrey A Law (law@cygnus.com)
-
- * genattrtab.c (optimize): Define in case PRESERVE_DEATH_INFO_REGNO_P
- uses it.
-
-Thu Jan 29 09:27:56 PST 1998 Jeff Law (law@cygnus.com)
+ * system.h: Likewise.
+
+ * toplev.c (error_with_file_and_line): Likewise.
+ (error_with_decl): Likewise.
+ (error_for_asm): Likewise.
+ (error): Likewise.
+ (fatal): Likewise.
+ (warning_with_file_and_line): Likewise.
+ (warning_with_decl): Likewise.
+ (warning_for_asm): Likewise.
+ (warning): Likewise.
+ (pedwarn): Likewise.
+ (pedwarn_with_decl): Likewise.
+ (pedwarn_with_file_and_line): Likewise.
+ (sorry): Likewise.
+ (really_sorry): Likewise.
+
+ * toplev.h: Switch on ANSI_PROTOTYPES, not __STDC__, when deciding
+ whether to declare `tree_node' and `rtx_def'.
+
+ * tree.c (build): Switch on ANSI_PROTOTYPES, not __STDC__, when
+ deciding whether to use ANSI variable args.
+ (build_nt): Likewise.
+ (build_parse_node): Likewise.
+
+Sun Nov 8 13:10:55 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Thu Jan 29 10:12:27 1998 Jeffrey A Law (law@cygnus.com)
+Sat Nov 7 23:34:01 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * configure.in: Check for atoq and atoll.
- * rtl.c (read_rtx): Use HAVE_ATOLL and HAVE_ATOQ to select the
- proper routine for converting ascii into long long values.
+ * Makefile.in (libcpp.a): Check RANLIB_TEST before runing RANLIB.
-Thu Jan 29 01:28:14 1998 Klaus Kaempf <kkaempf@progis.de>
+Sat Nov 7 22:26:19 1998 David Edelsohn <edelsohn@gnu.org>
- * cccp.c (SYS$SEARCH, SYS$PARSE): Write as upper-case.
+ * collect2.c (main, case 'b'): Use else if.
- * vmsconfig.com: Remove bytecode references.
+Sat Nov 7 15:35:25 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * alpha/vms.h (PREFIX): Define.
+ * configure.in (host_xm_file, build_xm_file, xm_file, tm_file):
+ Arrange to include gansidecl.h in {ht}config.h & tm.h just
+ before the config/ directory headers.
+ (tm_file_list, host_xm_file_list, build_xm_file_list): Handle
+ gansidecl.h in the list of dependencies.
- * alpha/vms.h (ASM_OUTPUT_ALIGNED_COMMON): Remove.
+ * Makefile.in (RTL_BASE_H): Don't depend on gansidecl.h.
+ (TREE_H, DEMANGLE_H, RECOG_H, REGS_H, libgcc2.a, stmp-multilib,
+ mbchar.o, collect2.o, pexecute.o, vfprintf.o, splay-tree.o, gcc.o,
+ gencheck.o, choose-temp.o, mkstemp.o, mkstemp.o, prefix.o,
+ dyn-string.o, cexp.o, cccp.o, cppmain.o, cpplib.o, cpperror.o,
+ cppexp.o, cppfiles.o, cpphash.o, cppalloc.o, scan-decls.o):
+ Likewise.
- * am-alpha.h: Don't include alloca for OPEN_VMS.
+ * cccp.c: Don't include gansidecl.h.
+ * cexp.y: Likewise.
+ * collect2.c: Likewise.
+ * config/c4x/c4x.c: Likewise.
+ * config/v850/v850.h: Likewise.
+ * cppalloc.c: Likewise.
+ * cpperror.c: Likewise.
+ * cppexp.c: Likewise.
+ * cppfiles.c: Likewise.
+ * cpphash.c: Likewise.
+ * cpplib.c: Likewise.
+ * cppmain.c: Likewise.
+ * cppulp.c: Likewise.
+ * demangle.h: Likewise.
+ * doprint.c: Likewise.
+ * dyn-string.c: Likewise.
+ * eh-common.h: Likewise.
+ * fix-header.c: Likewise.
+ * frame.c: Likewise.
+ * gcc.c: Likewise.
+ * gcov.c: Likewise.
+ * gen-protos.c: Likewise.
+ * gencheck.c: Likewise.
+ * halfpic.h: Likewise.
+ * hash.c: Likewise.
+ * machmode.h: Likewise.
+ * mbchar.c: Likewise.
+ * prefix.c: Likewise.
+ * protoize.c: Likewise.
+ * recog.h: Likewise.
+ * rtl.h: Likewise.
+ * scan-decls.c: Likewise.
+ * tree.h: Likewise.
+ * varray.h: Likewise.
- * alpha/xm-vms.h (HAVE_CPP_STRINGIFY): Define.
+Sat Nov 7 11:37:53 1998 Richard Henderson <rth@cygnus.com>
- * alpha/xm-vms.h (INCLUDE_DEFAULTS): Define.
- (GCC_INCLUDE_DIR): Define
+ * i386.md (call_value_pop): If we're not popping anything,
+ defer to call_value.
+ (call_pop): Likewise defer to call.
- * make-cc.com, make-cccp.com, make-cc1.com: Removed.
- * makefile.vms: New file.
+Sat Nov 7 02:49:56 1998 Richard Henderson <rth@cygnus.com>
- * alpha/vms.h (CPP_PREDEFINES): Remove -Dalpha.
+ * function.c (purge_addressof): Clear purge_addressof_replacements
+ only after processing the whole function.
- * alpha.c (output_prolog): Output '.name' directive
- for minimal traceback information.
+Sat Nov 7 00:54:55 1998 Jeffrey A Law (law@cygnus.com)
- * alpha.c (output_prolog): Don't prepend entry point symbols
- with '$' on OPEN_VMS.
+ * reload1.c (reload): If we can not perform a particular elimination
+ when we thought we could earlier, then we must always iterate through
+ the loop at least one more time.
-Thu Jan 29 00:25:35 1998 David S. Miller <davem@tanya.rutgers.edu>
- Jeffrey A Law (law@cygnus.com)
+Fri Nov 6 19:37:33 1998 Richard Henderson <rth@cygnus.com>
- * rtl.c (read_rtx): Use atol/atoq based upon disposition of
- HOST_WIDE_INT.
+ * alpha.c (add_operand): Simplify the CONST_INT match.
+ (sext_add_operand): Correct typo in comparison by using
+ CONST_OK_FOR_LETTER_P.
+ * alpha.md (s?addq): Use sext_add_operand to allow the negative
+ constant alternatives to be generated.
+ (mulsi3, muldi3, umuldi3_highpart): Loosen constraints to allow
+ small constants, since the hw instructions do.
- * genattrtab.c (write_test_expr): Use HOST_WIDE_INT_PRINT_DEC
- as needed.
- * genemit.c (gen_exp): Likewise.
- * genpeep.c (match_rtx): Likewise.
- * genrecog.c (write_tree_1): Likewise.
+Fri Nov 6 20:15:19 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * c-lex.c (yyprint): Use proper format string based upon
- disposition of HOST_BITS_PER_WIDE_INT.
- (yylex): Put casts in right place for args to build_int_2.
+ * reload1.c (emit_reload_insns): When rewriting the SET_DEST of a
+ previous insn to store directly into our reload register, make sure
+ that if the source of the previous insn is a reload register, its
+ spill_reg_store and spill_reg_stored_to values are cleared.
-Thu Jan 29 00:24:29 1998 Jeffrey A Law (law@cygnus.com)
+Fri Nov 6 16:35:10 1998 David Edelsohn <edelsohn@gnu.org>
- * combine.c: Fix typos in Jan27 changes.
+ * rs6000.md (floatunssidf2_internal splitter): Use base register
+ operand, not hard-coded SP.
-Thu Jan 29 00:07:49 1998 Ollivier Robert <roberto@keltia.freenix.fr>
+Fri Nov 6 04:07:53 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * i386/freebsd.h (LIB_SPEC): Correctly handle -shared, -p and friends.
- (LINK_SPEC): Likewise.
- (STARTFILE_SPEC): Likewise.
+ * jump.c (calculate_can_reach_end): Fix thinko.
-1998-01-28 Mike Stump <mrs@wrs.com>
+Fri Nov 6 00:16:04 1998 Jeffrey A Law (law@cygnus.com)
- * rtlanal.c (dead_or_set_regno_p): Ignore REG_DEAD notes after
- reload completes.
- * genattrtab.c (reload_completed): Define.
+ * reorg.c (fill_simple_delay_slots): Fix typo.
- * m32r.md, mips.md, mn10200.md, mn10300.md, pyr.md: Remove obsolete
- comments.
+ * romp.h (LEGITIMIZE_ADDRESS): Fix typo.
-Wed Jan 28 20:11:06 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-
- * reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the
- SUBREG_REG if the word count is unchanged, also in the input reload
- case. Disable non-applicable sanity checks.
-
-Wed Jan 28 20:08:26 1998 Jeffrey A Law (law@cygnus.com)
-
- * config/t-svr4 (TARGET_LIBGCC2_CFLAGS): Add -fPIC.
-
-Wed Jan 28 20:04:43 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * i386/t-cygwin32 (LIMITS_H_TEST, LIBGCC2_INCLUDES): Define.
-
-Wed Jan 28 11:45:27 1998 Per Bothner <bothner@cygnus.com>
-
- * dbxout.c (dbxout_type): For a RECORD_TYPE, check that TYPE_BINFO
- is a TREE_VEC before trying to use it for baseclasses.
- (Chill uses the same field for a different purpose.)
-
- * toplev.c (strip_off_ending): Generalize to endings up to 5 chars.
-
-Tue Jan 27 23:15:55 1998 Lassi A. Tuura <lat@iki.fi>
-
- * config.sub: More accurate determination of HP processor types.
-
-Tue Jan 27 23:11:11 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * c-lex.c: Include <stdlib.h> and <string.h>/<strings.h>. Add
- prototype for `handle_sysv_pragma', and make it static. Add
- parentheses around assignment used as truth value.
-
- * combine.c (combine_instructions): Protect variable `prev' with
- macro HAVE_cc0.
- (can_combine_p): Protect variable `link' with AUTO_INC_DEC.
- (extract_left_shift): Add parentheses around operand of &.
- (merge_outer_ops): Avoid an empty body in an else-statement.
- (gen_rtx_combine): Remove unused variable `i'.
-
- * sparc/gmon-sol2.c: Include <fcntl.h>. Make return type of
- function monstartup `void'. Likewise for internal_mcount. Add
- `static void' prototype for moncontrol. Reconcile sprintf format
- vs. args.
-
- * sparc/sparc.c: Include <stdlib.h> and <string.h>/<strings.h>.
- Make return type of function_arg_slotno explicitly `int'.
- (reg_unused_after): Add parentheses around assignment used as
- truth value.
- (save_regs): Add explicit braces to avoid ambiguous `else'.
- (function_arg_slotno): Add parentheses around && within ||.
- (function_arg_pass_by_reference): Likewise.
- (sparc_flat_output_function_prologue): Reconcile fprintf format
- vs. args.
-
- * svr4.h (ASM_OUTPUT_LIMITED_STRING): Add parentheses around
- assignment used as truth value.
-
- * cplus-dem.c: Include <stdlib.h>.
- (demangle_signature): Avoid an empty body in an else-statement.
- (do_type): Remove unused variable `lvl'.
-
- * cppexp.c: Don't have <stdlib.h> depend on MULTIBYTE_CHARS.
- Include <string.h>/<strings.h>.
- (cpp_lex): Remove unused variable `namelen'.
- (cpp_lex): Explicitly declare `num_chars' as an int.
-
- * cpplib.c: Avoid duplicate inclusion of <stdlib.h>, include
- <unistd.h> instead. Explicitly declare is_system_include
- returning int.
- (make_assertion): Remove unused variable `kt'.
- (cpp_expand_to_buffer): Hide variable `obuf'.
- (output_line_command): Remove unused variables, `line_end',
- `line_cmd_buf' and `len'.
- (macarg): Remove unused variable `arg_start'.
- (special_symbol): Remove unused variable `i'. Add parentheses
- around assignment used as truth value.
- (do_include): Remove unused variables `pcfname' and `retried',
- hide `pcf' and `pcfbuflimit'.
- (do_line): Remove unused variable `i'.
- (finclude): Hide variable `missing_newline'.
- (cpp_handle_options): Remove unused variable `j'.
- (read_token_list): Remove unused variable `eofp'.
- (cpp_error_with_line): Remove unused variable `i'.
- (cpp_warning_with_line): Likewise.
- (cpp_pedwarn_with_line): Explicitly declare `column' as int.
- (cpp_error_from_errno): Remove unused variable `i'.
-
- * cse.c (invalidate): Add parentheses around assignment used as
- truth value.
- (find_best_addr): Move declaration of variable `our_cost' inside
- the conditional macro where its used.
- (fold_rtx): Avoid an empty body in an if-statement.
- (cse_insn): Wrap variables `this_insn_cc0_mode' and
- `this_insn_cc0' in macro HAVE_cc0.
-
- * dwarf2out.c: Include <stdlib.h> and <string.h>/<string.h>.
- (ASM_OUTPUT_DWARF_DATA8): Reconcile format vs. args in fprintf's.
- (output_uleb128): Likewise.
- (output_sleb128): Likewise.
- (output_cfi): Likewise.
- (output_call_frame_info): Remove unused variables `j', `fde_size'
- and `fde_pad'.
- (comp_unit_has_inlines): Hide declaration as per rest of file.
- (size_of_line_prolog): Correct typo in prototype.
- (add_arange): Likewise.
- (output_aranges): Likewise.
- (add_name_and_src_coords_attributes): Likewise.
- (gen_array_type_die): Likewise.
- (gen_inlined_subroutine_die): Likewise.
- (equate_decl_number_to_die): Remove unused variable `i'.
- (print_die): Reconcile format vs. args in fprintf's.
- (print_dwarf_line_table): Likewise.
- (output_die): Likewise.
- (output_line_info): Likewise.
- (add_subscript_info): Avoid an empty body in an else-statement.
- (gen_subprogram_die): Remove unused variable `fp_loc'.
-
- * dwarfout.c: Explicitly declare `next_pubname_number' as int.
- Protect `ordering_attribute' prototype with USE_ORDERING_ATTRIBUTE
- macro. Protect `src_coords_attribute' prototype with
- DWARF_DECL_COORDINATES macro. Hide `output_entry_point_die'
- prototype as in the rest of the file. Likewise for
- `output_pointer_type_die' and `output_reference_type_die'. Remove
- prototype for `type_of_for_scope'.
- (output_unsigned_leb128): Reconcile format vs. args in fprintf.
- (type_attribute): Add explicit braces to avoid ambiguous `else'.
-
- * final.c: Include <stdlib.h> and <string.h>/<strings.h>.
- (shorten_branches): Protect declaration of tmp_length with
- SHORTEN_WITH_ADJUST_INSN_LENGTH and ADJUST_INSN_LENGTH macros.
- (profile_function): Protect declaration of `sval' and `cxt'
- variables with appropriate macros.
- (final_scan_insn): Likewise for `note' variable. Add explicit
- braces to avoid empty body in an if-statement.
- (output_asm_insn): Move variable `i' inside macro conditional
- where it is used. Add parentheses around assignment used as truth
- value.
- (asm_fprintf) Likewise, likewise.
-
- * fix-header.c (main): Remove unused variable `done'. Protect
- declaration of `i' with FIXPROTO_IGNORE_LIST.
-
- * pexecute.c: Include <unistd.h>. Prototype `my_strerror'.
-
- * print-rtl.c (print_inline_rtx): Explicitly declare the parameter
- `ind'.
-
- * profile.c: Include <string.h>/<strings.h>.
- (instrument_arcs): Remove unused variables `note', `inverted',
- `zero' and `neg_one'.
- (branch_prob): Avoid empty body in an if-statement.
-
- * regclass.c: Include <stdlib.h>.
- (reg_alternate_class): Explicitly declare parameter `regno'.
-
- * regmove.c (regmove_optimize): Remove unused variable `p'. Add
- parentheses around assignment used as truth value.
- (find_matches): Remove unused variables `output_operand' and
- `matching_operand'.
- (fixup_match_1): Remove statement with no effect: "if (0) ;".
-
- * scan.c (sstring_append): Explicitly declare `count' as int.
- (scan_string): Explicitly declare parameter `init' as int.
-
- * sched.c: Include <stdlib.h>.
- (BLOCKAGE_RANGE): Add parentheses around arithmetic in operand of |.
- (rank_for_schedule): Add parentheses around assignment used as
- truth value.
- (schedule_block): Likewise.
- (regno_use_in): Likewise.
- (schedule_insns): Remove unused variable `i'.
-
- * toplev.c: Include <stdlib.h> and <string.h>/<strings.h>.
- (v_message_with_decl): Remove unused variable `n'.
- (botch): Explicitly declare parameter `s' as char *.
- (main): Add parentheses around assignment used as truth value.
-
- * tree.c (make_node): Protect the variable `kind' with the
- GATHER_STATISTICS macro.
- (real_value_from_int_cst): Move variable `e' inside conditional
- macro area where it is used.
- (tree_last): Add parentheses around assignment used as truth value.
- (build1): Protect the variable `kind' with the GATHER_STATISTICS
- macro.
- (print_obstack_statistics): Reconcile format vs. args in fprintf.
- Protect variables `i', `total_nodes', and `total_bytes' with the
- GATHER_STATISTICS macro.
-
-Tue Jan 27 23:01:55 1998 Mike Stump (mrs@wrs.com)
-
- * m32r.md, mips.md, mn10200.md, mn10300.md, pyr.md: Add
- some comments regarding use of dead_or_set_p.
-
-Tue Jan 27 22:14:48 1998 Todd Vierling <tv@pobox.com>
-
- * fixincludes: Tweak fix for struct exception in math.h
-
-Tue Jan 27 17:21:09 1998 Gavin Koch (gavin@cygnus.com)
-
- * mips/mips.c (mips_expand_prologue,mips_expand_epilogue):
- Change mode of registers used to add/sub from
- hard_frame_pointer_rtx from word_mode to Pmode.
-
-Tue Jan 27 11:02:04 1998 Nick Clifton <nickc@cygnus.com>
-
- * v850.h (ASM_OUTPUT_ALIGNED_BSS): Use
- asm_output_aligned_bss() instead of asm_output_bss().
-
- * toplev.c (rest_of_compilation): Replace references to
- stack_reg_dump_file and dbr_sched_dump_file with references to
- rtl_dump_file.
-
-Tue Jan 27 10:22:13 1998 Kamil Iskra <iskra@student.uci.agh.edu.pl>
-
- * tlink.c (scan_linker_output): Call fclose() for opened files.
-
-Tue Jan 27 05:05:26 1998 Richard Henderson <rth@cygnus.com>
-
- * alpha.c (output_epilog [!VMS]): Don't tag global functions if
- compiling with -fpic -- we want to be able to override symbols
- properly.
- (alpha_expand_block_move): Fix thinko in last change.
+Fri Nov 6 00:10:00 1998 Jan Hubicka (hubicka@freesoft.cz)
- * alpha.h (ASM_OUTPUT_MI_THUNK): New define.
- * config/alpha/win-nt.h (ASM_OUTPUT_MI_THUNK): New define.
- * config/alpha/vms.h (ASM_OUTPUT_MI_THUNK): New undef.
+ * i386.md (extendsidi2): Use # in the output template.
+ (extendsidi splitters): New splitters.
-Tue Jan 27 03:21:23 1998 Richard Henderson <rth@cygnus.com>
+Thu Nov 5 11:13:27 1998 Nick Clifton <nickc@cygnus.com>
- * alpha.md (abssf, absdf): Revert last change.
+ * configure.in: Use unknown-elf.h as tm_file for arm-elf
+ configurations.
+ * configure: Regenerate.
-Tue Jan 27 00:26:50 1998 John Carr <jfc@mit.edu>
+Thu Nov 5 07:59:05 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * dwarf2out.c (dwarf2out_frame_init): Test value of DWARF2_UNWIND_INFO.
- * mips/sni-svr4.h: Define DWARF2_UNWIND_INFO as 0.
+ * jump.c (init_label_info, delete_barrier_successors,
+ mark_all_labels, delete_unreferenced_labels,
+ delete_noop_moves, calculate_can_reach_end): New functions broken
+ out of jump_optimize.
+ (jump_optimize): Use them.
-Tue Jan 27 00:07:02 1998 Jeffrey A Law (law@cygnus.com)
+Thu Nov 5 07:57:45 1998 Andrew MacLeod <amacleod@cygnus.com>
- * emit-rtl.c (gen_lowpart_common): Handle more case where converting
- a CONST_INT into SFmode.
+ * except.c (expand_fixup_region_end): Make sure outer context labels
+ are not issued in an inner context during cleanups.
-Tue Jan 20 16:01:03 1998 Anthony Green <green@cygnus.com>
+Thu Nov 5 04:03:06 1998 Richard Henderson <rth@cygnus.com>
- * flags.h: New flag (optimize_size).
- * toplev.c (main): Parse -Os option and set optimize_space
- accordingly.
- * gcc.c (default_compilers), cp/lang-specs.h, f/lang-specs.h: Define
- __OPTIMIZE_SIZE__ when compiling with -Os.
- * config/dsp16xx/dsp16xx.h, config/i386/i386.h,
- config/i386/dgux.h, config/i960/i960.h, config/pdp11/pdp11.h,
- config/v850/v850.h (OPTIMIZATION_OPTIONS): New SIZE argument
- to macro.
- * config/i386/i386.c (optimization_options): Accept new SIZE argument.
+ * alpha.md (addsi3, subsi3): No new temporaries once cse is
+ no longer expected.
-Mon Jan 26 23:57:39 1998 Manfred Hollstein <manfred@s-direktnet.de>
+Thu Nov 5 03:29:19 1998 Richard Henderson <rth@cygnus.com>
- * libgcc2.c (__clear_insn_cache): On sysV68 enable the memctl
- stuff only if MCT_TEXT is #define'd.
+ * alpha.md (addsi3, subsi3): Expand to a DImode temporary so as
+ to expose this midpoint to CSE.
-Mon Jan 26 23:52:51 1998 Markus F.X.J. Oberhumer <k3040e4@c210.edvz.uni-linz.ac.at>
+Thu Nov 5 03:42:54 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * configure.in (i*86-pc-msdosdjgpp): Treat like msdos & go32
- configurations.
+ * config/sparc/sparc.md (movdf_const_intreg_sp64): Enable again.
-Fri Jan 23 09:39:36 1998 Nick Clifton <nickc@cygnus.com>
+Thu Nov 5 10:53:01 1998 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * toplev.c: Add -dM command line option to dump RTL after the
- machine dependent reorganisation pass, if there is one.
- Reorganise RTL dump code, so that only one file handle is
- needed.
+ * configure.in: Bring over gcc2 change of Nov 19 1997.
-Mon Jan 26 12:09:42 1998 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+Wed Nov 4 23:43:08 1998 Graham <grahams@rcp.co.uk>
- * except.c (check_exception_handler_labels): Disable warning when
- flag_syntax_only.
+ * toplev.c (output_lang_identify): Make definition dependent on
+ ASM_IDENTIFY_LANGUAGE.
-Mon Jan 26 18:17:32 1998 Jim Wilson <wilson@cygnus.com>
+ * print-rtl.c (spaces): Make static.
- * sparc.c (pic_setup_code): Don't set LABEL_PRESERVE_P.
+Wed Nov 4 22:16:36 1998 Hans-Peter Nilsson <hp@axis.se>
-Mon Jan 26 18:11:30 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * extend.texi: Clarify proper uses for register clobbers in asms.
- * c-decl.c (grokdeclarator): Get parameter tags from
- last_function_parm_tags.
- * dwarfout.c (output_formal_types): Set TREE_ASM_WRITTEN before
- traversing the parameter types.
- (output_type): No early exit for FUNCTION_TYPE / METHOD_TYPE context.
+Wed Nov 4 22:16:36 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
-Mon Jan 26 01:44:12 1998 Jeffrey A Law (law@cygnus.com)
+ * recog.h (enum op_type): Define.
+ (constrain_operands): Adjust prototype.
+ (recog_op_type): Declare new variable.
+ * recog.c (recog_op_type): New variable.
+ (insn_invalid_p): Allow modifying an asm statement after reload.
+ (extract_insn): Set up recog_op_type.
+ (constrain_operands): Lose INSN_CODE_NUM arg. All callers changed.
+ Don't compute operand types, use recog_op_type.
+ Use the information computed by extract_insn instead of the previous
+ method of finding it by insn code number.
+ * caller-save.c (init_caller_save): Use extract_insn, not insn_extract.
+ * reorg.c (fill_slots_from_thread): Likewise.
+ * reload1.c (reload_as_needed): Likewise.
+ (gen_reload): Likewise.
+ (inc_for_reload): Likewise.
+ (reload_cse_simplify_operands): Likewise.
+ Use the information computed by extract_insn instead of the previous
+ method of finding it by insn code number.
+ * genattrtab.c (write_attr_case): Generate call to extract_insn, not
+ insn_extract.
+ * final.c (final_scan_insn): Use extract_insn, not insn_extract.
+ (cleanup_operand_subregs): Use extract_insn, not insn_extract.
+ Use the information computed by extract_insn instead of the previous
+ method of finding it by insn code number.
+ * regmove.c (find_matches): Likewise. Change meaning of the return
+ value to be nonzero if the optimization can be performed, zero if
+ not. All callers changed.
+ Shorten some variable names to fix formatting problems.
+ (regmove_optimize): Shorten some variable names to fix formatting
+ problems.
+ Use the information computed by extract_insn instead of the previous
+ method of finding it by insn code number.
+ * regclass.c (scan_one_insn): Likewise.
+ (record_reg_classes): Don't compute operand types, use recog_op_type.
+ * reload.c (find_reloads): Lose CONSTRAINTS1 variable; use
+ recog_constraints instead.
- * h8300.c (print_operand): Handle CONST_DOUBLE for 'e', 'f', and
- the default case.
- (get_shift_alg): Fix typo.
+Wed Nov 4 21:37:46 1998 Jeffrey A Law (law@cygnus.com)
-Sun Jan 25 22:22:04 1998 Richard Henderson <rth@cygnus.com>
+ * rtl.h (flow2_completed): Declare.
+ * flow.c (flow2_completed): Definition.
+ * toplev.c (rest_of_compilation): Set and clear flow2_completed
+ as necessary.
- * alpha.c (alpha_expand_block_move): Copy ADDRESSOF to reg.
+Wed Nov 4 19:15:37 1998 Melissa O'Neill <oneill@cs.sfu.ca>
-Sun Jan 25 22:14:28 1998 Richard Henderson <rth@cygnus.com>
+ * Makefile.in (libcpp.a): Ranlib libcpp.a.
- * toplev.c (get_run_time): Make sure each case gets its variables.
+ * cppulp.c (user_label_prefix): Initialize.
-Sun Jan 25 22:10:21 1998 Richard Henderson <rth@cygnus.com>
+Wed Nov 4 19:07:08 1998 John Wehle (john@feith.com)
- * configure.in (build_xm_file): Add auto-config.h if host=build.
- (host_xm_file_list): Don't add $(srcdir) to auto-config.h.
- (build_xm_file_list): Likewise.
- * configure: Rebuild.
+ * flow.c (mark_regs_live_at_end): Mark the stack pointer as live
+ at a RETURN if current_function_sp_is_unchanging is set.
-Sun Jan 25 22:00:25 1998 Alasdair Baird <alasdair@wildcat.demon.co.uk>
+Wed Nov 4 18:16:29 1998 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
- * recog.c (validate_replace_rtx_1): Only perform substitutions
- of arguments to commutative and comparison operators once.
+ * emit-rtl.c (try_split): Fixed error in Oct 10 patch.
-Sun Jan 25 12:30:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Wed Nov 4 15:11:15 1998 Geoffrey Noer <noer@cygnus.com>
- * sparc.c (output_cbranch): Add default case in
- enumeration switch.
+ * i386/cygwin32.h (MASK_WIN32, MASK_CYGWIN, MASK_WINDOWS, MASK_DLL,
+ TARGET_WIN32, TARGET_CYGWIN, TARGET_WINDOWS, TARGET_DLL): New.
+ (SUBTARGET_SWITCHES): Add -mno-cygwin, -mcygwin, and -mdll options.
+ (CPP_PREDEFINES): Don't define __CYGWIN32__ here.
+ (STARTFILE_SPEC): Handle -mdll, -mno-cygwin options.
+ (CPP_SPEC): Handle -mno-cygwin option. Define __CYWIN__ in addition
+ to __CYGWIN32__.
+ (LIB_SPEC): Handle -mno-cygwin option.
+ (LINK_SPEC): Handle -mdll.
- * reorg.c (insn_sets_resource_p): Correct typo in prototype.
- (emit_delay_sequence): Eliminate unused parameter, all callers
- changed.
- (fill_simple_delay_slots): Likewise.
- (fill_slots_from_thread): Likewise.
- (fill_eager_delay_slots): Likewise.
- (mark_referenced_resources): Add default case in enumeration switch.
- (mark_set_resources): Likewise.
- (rare_destination): Likewise.
- (mostly_true_jump): Likewise.
- (find_dead_or_set_registers): Likewise.
- (redirect_with_delay_slots_safe_p): Remove unused variable `slots'.
- (update_reg_unused_notes): Remove unused variable `p'.
- (mark_target_live_regs): Remove unused variables `next' and
- `jump_count'.
- (fill_simple_delay_slots): Remove unused variable `j'.
- (fill_slots_from_thread): Add parentheses around assignment used
- as truth value.
- (dbr_schedule): Likewise.
+Wed Nov 4 22:56:14 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * objc/Make-lang.in (objc.stage1): Depend on stage1-start.
- (objc.stage2, objc.stage3, objc.stage4): Likewise.
+ * reload.c (find_reloads): Fix test for usage by other reload
+ to handle secondary reloads properly.
-Sun Jan 25 12:13:47 1998 Michael Tiemann <michael@tiemann.org>
+Wed Nov 4 17:25:10 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * cse.c (simplify_ternary_operation): Don't try to simplify
- IF_THEN_ELSE expressions (created by combine) that don't use
- relational operators.
+ * reload1.c (ELIMINABLE_REGS, NUM_ELIMINABLE_REGS): Introduce an
+ intermediate structure which has exactly the members provided by
+ ELIMINABLE_REGS. Define NUM_ELIMINABLE_REGS in terms of the
+ static intermediate structure.
-Fri Jan 23 22:48:24 1998 Jeffrey A Law (law@cygnus.com)
+ (init_elim_table): Xmalloc() `reg_eliminate', and initialize it
+ from the intermediate structure. Do the same analogous fix in
+ the case where ELIMINABLE_REGS is not defined.
- * cse.c (simplify_ternary_operation): Handle more IF_THEN_ELSE
- simplifications.
+Tue Nov 3 20:50:03 1998 Jeffrey A Law (law@cygnus.com)
- * crtstuff.c (init_dummy): Keep the epilogue in the init
- section for non-ELF systems.
+ * pa.h (SELECT_SECTION): Fix thinko.
-Fri Jan 23 23:28:59 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Tue Nov 3 17:51:36 1998 Jim Wilson <wilson@cygnus.com>
- * sh.md (movqi_i+1): New peephole.
+ * dwarf2out.c (output_call_frame_info): Comments on last change.
-Fri Jan 23 15:39:42 1998 Jim Wilson <wilson@cygnus.com>
+Tue Nov 3 07:51:43 1998 Richard Earnshaw (rearnsha@arm.com)
- * Makefile.in: Remove remaining bytecode stuff.
- * emit-rtl.c, expr.c: Likewise.
+ * arm.c (add_constant): When taking the address of an item in the
+ pool, get the mode of the item addressed.
-Fri Jan 23 12:41:10 1998 Nick Clifton (nickc@cygnus.com)
+ * arm.c (final_prescan_insn case INSN): If an insn doesn't
+ contain a SET or a PARALLEL, don't consider it for conditional
+ execution.
- * toplev.c (lang_options): Add unknown-pragma options.
+ Restore ABI compatibility for NetBSD.
+ * arm/netbsd.h (DEFAULT_PCC_STRUCT_RETURN): Override setting in
+ arm.h.
+ (RETURN_IN_MEMORY): Likewise.
-Thu Jan 22 23:43:38 1998 Per Bothner <bothner@cygnus.com>
+Mon Nov 2 11:46:17 1998 Doug Evans <devans@canuck.cygnus.com>
- * dwarfout.c (byte_size_attribute): Simplify and fix - don't need
- special (and incomplete) handling for Chill arrays.
+ * m32r/m32r.c (m32r_expand_block_move): Fix byte count computations.
+ (m32r_output_block_move): Rewrite bytes < 4 handling.
-Fri Jan 23 00:27:23 1998 John Carr <jfc@mit.edu>
+Mon Nov 2 10:10:35 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * toplev.c (get_run_time): Call sysconf(_SC_CLK_TCK), when available,
- to get clock rate.
+ * configure.in: Call AC_FUNC_VFORK.
-Fri Jan 23 00:19:36 1998 Gavin Koch (gavin@cygnus.com)
+ * collect2.c: Define VFORK_STRING as a printable string for
+ error messages (either "vfork" or "fork".) If HAVE_VFORK_H is
+ defined, include vfork.h. If VMS is defined, define vfork()
+ appropriately. Remove vfork check on USG, we're using autoconf.
+ (collect_execute): Pass VFORK_STRING to fatal_perror instead of
+ checking locally what string to pass.
+ (scan_prog_file): Likewise.
+ (scan_libraries): Likewise.
- * mips.md (muldi3_internal2): Reverse test for TARGET_MIPS16.
+ * gcc.c: Remove vfork check on USG, we're using autoconf.
+ Besides, no calls to vfork/fork occur in this file.
-1998-01-22 scott snyder <snyder@d0sgif.fnal.gov>
+ * protoize.c: Likewise.
- * mips.c (function_prologue): Use HARD_FRAME_POINTER_REGNUM in
- .frame directive instead of FRAME_POINTER_REGNUM.
+Mon Nov 2 07:52:28 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
-Fri Jan 23 00:08:55 1998 Robin Kirkham <rjk@mlb.dmt.csiro.au>
+ * configure.in (DEFAULT_LINKER): Renamed from LD.
+ (DEFAULT_ASSEMBLER): Renamed from AS; reverted Schwab's patch.
+ (gcc_cv_as): Try $DEFAULT_ASSEMBLER before $AS.
+ * configure: Rebuilt.
- * m68k.h (TARGET_SWITCHES): -mcpu32 now clears MASK_68881.
- (MACHINE_STATE_m68010_up): Replaced __mc68332__ with __mcpu32__.
- * m68k/m68k-none.h(CPP_FPU_SPEC): Update relative to TARGET_SWITCHES.
- (CPP_SPEC, ASM_SPEC, CC1_SPEC): Likewise.
- (CPP_SPEC): -m68332 defines both __mc68332 and __mcpu32__.
- * m68k/t-m68kbare (MULTILIB_OPTIONS): Add mcpu32.
- (MULTILIB_MATCHES): -m68332 now uses mcpu32 libraries, not m68000.
- (MULTILIB_EXCEPTIONS): Don't build 68881 libraries for m68000,
- mcpu32 or m5200.
- * longlong.h: Replace __mc68332__ with __mcpu32__.
+Mon Nov 2 01:48:10 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
-Thu Jan 22 19:55:40 PST 1998 Jeff Law (law@cygnus.com)
+ * BUGS: Fix the regexp for `more' to find the appropriate node.
+ Reported by Joerg Pietschmann <joerg_pietschmann@zkb.ch>
- * version.c: Bump for snapshot.
+ * BUGS: Added link to the WWW FAQ.
-Thu Jan 22 14:47:31 1998 Jim Wilson <wilson@cygnus.com>
+Sun Nov 1 18:27:15 1998 Jeff Law (law@cygnus.com)
- * reload.c (push_reload): In WORD_REGISTER_OPERATIONS code, add test
- to require the SUBREG mode to be smaller than the SUBREG_REG mode.
- * reload1.c (eliminate_regs): Likewise.
+ * version.c: Bump for snapshot.
-Thu Jan 22 14:49:14 1998 Jeffrey A Law (law@cygnus.com)
+Sun Nov 1 11:04:32 1998 Jeffrey A Law (law@cygnus.com)
- * regmove.c (find_matches): Initialize matches->earlyclobber too.
+ * From Christian Gafton:
+ * i386/linux.h (CPP_PREDEFINES): Add -D__i386__.
+ * sparc/linux.h (CPP_PREDEFINES): Add -D__sparc__.
+ * sparc/linux64.h (CPP_PREDEFINES): Add -D__sparc__.
-Thu Jan 22 01:40:52 1998 Richard Henderson <rth@cygnus.com>
+Sat Oct 31 21:42:39 1998 Mark Mitchell <mark@markmitchell.com>
- * alpha.md (abssf2, absdf2): Disable in IEEE mode.
- (negsf2, negdf2): Use proper subtract in IEEE mode.
+ * c-common.c (c_get_alias_set): Allow all type-punning through
+ unions. Don't get confused about the type of a bit-field, despite
+ the antics of build_modify_expr.
-Tue Jan 20 09:29:09 1998 Jeffrey A Law (law@cygnus.com)
+Sat Oct 31 22:35:29 1998 Jean-Pierre Radley <jpr@jpr.com>
- * Makefile.in: Remove more bytecode stuff.
- * expr.c, stmt.c, config/msdos/top.sed: Likewise.
- * vax/xm-vms.h, winnt/config-nt.sed: Likewise.
- * f/install.texi, objc/Make-lang.in: Likewise.
+ * fixinc.sco: Parameterize #include_next values.
+ * fixinc/fixinc.sco: Likewise.
- * Makefile.in: Remove all bytecode support.
- (OBJS): Make sure last entry is a real object file, not EXTRA_OBJS.
- * emit-rtl.c: Remove all bytecode support.
- * expr.c, expr.h function.c, integrate.c: Likewise.
- * output.h, regclass.c, rtl.h, stmt.c, toplev.c: Likewise.
- * tree.h, varasm.c: Likewise.
- * config/m68k/m68k.h: Likewise.
- * bi-*, bc-*, bytecode*: Delete bytecode related files.
- * modemap.def: Likewise.
+Sat Oct 31 20:39:35 1998 Jeffrey A Law (law@cygnus.com)
-Tue Jan 20 09:02:31 1998 Gavin Koch (gavin@cygnus.com)
+ * toplev.c (rest_of_compilation): No longer set reload_completed.
+ * reload1.c (reload): Set it here. Perform instruction splitting
+ after reload has completed if we will be running the scheduler
+ again.
- * mips/mips.md (divsi3,divdi3,modsi3,moddi3,udivsi3,udivdi3,
- umodsi3,umoddi3): Handle mips16 div/mod by a constant.
+Sat Oct 31 12:30:02 1998 Jeffrey A Law (law@cygnus.com)
-Mon Jan 19 21:57:00 1998 Richard Henderson <rth@cygnus.com>
+ * jump.c (jump_optimize): Initialize mappings from INSN_UID to
+ EH region if exceptions are enabled and we're performing cross
+ jump optimizations.
+ (find_cross_jump): Exit loop if the insns are in different EH regions.
- * i386.md (push): Prohibit symbolic constants if flag_pic.
- (movsi+1): Likewise for move to non-register.
+Sat Oct 31 10:02:48 1998 Mark Mitchell <mark@markmitchell.com>
-Mon Jan 19 11:15:38 1998 Jim Wilson <wilson@cygnus.com>
+ * dwarf2out.c (output_call_frame_info): Use
+ ASM_OUTPUT_DWARF_DELTA4 for the CIE offset to match frame.c.
- * alpha.c (mode_mask_operand): Accept 0xffffffff on 32 bit host.
- (print_operand): Handle 0xffffffff on 32 bit host.
+Sat Oct 31 10:23:14 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * configure.in (thread_file): Rename uses before main loop to
- target_thread_file. Initialize to empty in main loop. Set thread_file
- to target_thread_file after main loop if not set.
- * configure: Rebuild.
+ Reinstall Apr 24th fix, lost during May 6th gcc2 merge:
+ * c-common.c (check_format_info): Don't check for the 'x'
+ format character twice, instead check for 'x' and 'X'
- * genattrtab.c (find_and_mark_used_attributes): Handle CONST_INT.
- (add_values_to_cover): Revert last change (which had no ChangeLog
- entry).
- (simplify_with_current_value_aux): Handle CONST_INT.
+Fri Oct 30 14:50:25 1998 Jeffrey A Law (law@cygnus.com)
-Mon Jan 19 10:14:55 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * configure.in (assembler features): Also make gas is configured if
+ we find it in the source tree.
- * unprotoize.c: Define UNPROTOIZE first, to actually take effect.
+Fri Oct 30 13:23:20 1998 Richard Henderson <rth@cygnus.com>
-Mon Jan 19 10:11:52 1998 Richard Henderson <rth@cygnus.com>
+ * i386.c (i386_comp_type_attributes): Compare whether the
+ attributes are defined, not their tree nodes.
- * configure.in: Add cpp stringify test.
- * acconfig.h (HAVE_CPP_STRINGIFY): New tag.
- * gengenrtl.c: Use it.
- * configure, config.in: Rebuild.
+Fri Oct 30 11:39:47 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
-Mon Jan 19 09:43:15 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * configure.in (gxx_include_dir): Bitten by autoconf quoting
+ characters. :-(
+ * configure: Rebuilt.
- * Makefile.in (genrtl.c genrtl.h): Add dummy command for GNU make.
+Fri Oct 30 10:43:29 1998 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Mon Jan 19 09:38:18 1998 Richard Henderson <rth@cygnus.com>
+ * configure.in: Ignore non-absolute value in $AS.
- * configure.in: Find declaration for sbrk.
- * acconfig.h (NEED_DECLARATION_SBRK): New tag.
- * config.in, configure: Rebuild.
- * mips-tfile.c: Properly protect declaration of sbrk and free.
- * toplev.c: Properly protect declaration of sbrk.
+Fri Oct 30 00:54:25 1998 Peter Jakubek <pjak@snafu.de>
-Sun Jan 18 20:18:01 1998 Richard Henderson <rth@cygnus.com>
+ * m68k.h (INDIRECTABLE_1_ADDRESS_P): Fix thinko.
- * alpha.c (alpha_handle_trap_shadows): Ignore CLOBBERs.
+Fri Oct 30 00:42:34 1998 Mark Elbrecht <snowball3@usa.net>
+
+ * configure.in (msdosdjgpp): Set exeext and target_alias.
+
+Thu Oct 29 23:55:43 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * flow.c (XNMALLOC): New macro.
+ (flow_int_list_blocks, basic_block_succ, basic_block_pred): New
+ static variables.
+ (add_edge, add_edge_to_label): New static functions.
+ (free_bb_memory): New function.
+ (flow_delete_insn): Delete function.
+ (basic_block_drops_in): Delete variable.
+ (find_basic_blocks): Allocate and initialize basic_block_head,
+ basic_block_succ. Don't allocate basic_block_drops_in.
+ Call free_bb_memory at the beginning.
+ (find_basic_blocks_1): Don't do multiple passes.
+ Delete code to compute basic_block_drops_in.
+ After calling make_edges, mark blocks reached by current block live.
+ Update test for unreachable live blocks.
+ (mark_label_ref): Delete args X, CHECKDUP. Add PRED arg. All callers
+ changed.
+ Simplify to call add_edge_to_label when a LABEL_REF is found.
+ (make_edges): Simplify to call add_edge_to_label instead of
+ mark_label_ref most of the time.
+ Compute here whether control drops into the next block.
+ (delete_unreachable_blocks): Return void. All callers changed.
+ Delete unreachable blocks in reverse order.
+ After deleting all unreachable blocks, renumber the remaining ones
+ and update n_basic_blocks.
+ (delete_block): Speed up deletion a bit.
+ Don't set basic_block_drops_in for deleted blocks.
+ (free_basic_block_vars): Don't free basic_block_drops_in.
+ (life_analysis_1): Update to use new edge representation.
+ (dump_flow_info): Delete code to print basic block info; call
+ dump_bb_data instead.
+ (compute_preds_succs): Delete code to recompute basic_block_drops_in
+ and uid_block_number.
+ Simply copy the previously computed cfg.
+ (dump_bb_data): New arg LIVE_INFO. All callers changed.
+ Print register lifetime information if LIVE_INFO is nonzero.
+ * basic-block.h (dump_bb_data): Adjust prototype.
+ * gcse.c (gcse_main): Update call to dump_bb_data.
+ * rtl.h (free_bb_memory): Declare.
+ * toplev.c (rest_of_compilation): Call free_bb_memory.
+
+ * reload1.c (struct elim_table): Delete MAX_OFFSET member.
+ (update_eliminable_offsets): Don't compute it.
+ (set_initial_elim_offsets): Don't initialize it.
+ Break out some code into set_initial_label_offsets so the rest of
+ this function can be called from reload_as_needed.
+ Assume that INITIAL_FRAME_POINTER_OFFSET is defined when
+ ELIMINABLE_REGS isn't.
+ (set_initial_label_offsets): New function, broken out of
+ set_initial_elim_offsets.
+ (set_offsets_for_label): New function, broken out of set_label_offsets
+ and reload_as_needed.
+ (reload): Call the two new functions.
+ (reload_as_needed): Call set_initial_elim_offsets instead of
+ duplicating the code. Likewise for set_offsets_for_label.
+
+ * reload1.c (choose_reload_regs): Fix typo in Oct 17 change.
+ (emit_reload_insns): Ensure that when we set reg_reloaded_valid for
+ any hard reg, reg_reloaded_dead contains valid data.
+
+Thu Oct 29 22:30:54 1998 Marcus Meissner <Marcus.Meissner@informatik.uni-erlangen.de>
+
+ * i386.c (i386_comp_type_attributes): Return nonzero for mismatched
+ "stdcall" and "cdecl" attributes.
+
+Thu Oct 29 19:05:17 1998 Jim Wilson <wilson@cygnus.com>
+
+ * sched.c (update_flow_info): Add code to ! found_orig_dest case to
+ handle deleted no-op moves of hard registers.
+ * haifa-sched.c (update_flow_info): Likewise.
-Sun Jan 18 01:54:27 1998 Jeffrey A Law (law@cygnus.com)
+Thu Oct 29 18:07:47 1998 Jeffrey A Law (law@cygnus.com)
- * alpha/xm-winnt.h (HAS_INIT_SECTION): Undefine.
+ * mips.md (reload_{in,out}{si,di}): Emit a USE of HILO at the end
+ of the sequences to reload the HILO register which do not actually
+ reference HILO.
-Sun Jan 18 00:57:35 1998 Mike Stump (mrs@wrs.com)
+Thu Oct 29 12:39:35 1998 Jim Wilson <wilson@cygnus.com>
- * configure.in (i960-wrs-vxworks): Default to latest vxworks release.
+ * c-common.c (c_get_alias_set): Handle ARRAY_REF of union field.
-Sat Jan 17 23:41:36 1998 David S. Miller <davem@tanya.rutgers.edu>
+Thu Oct 29 14:10:22 1998 Andrew MacLeod <amacleod@cygnus.com>
- * combine.c (force_to_mode, nonzero_bits): Correctly optimize
- constant offset computations from objects with known alignment in
- the presence of STACK_BIAS.
+ * except.c (emit_eh_context): Make the EH context register stay alive
+ at -O0 so stupid.c doesn't get confused.
- * varasm.c (immed_double_const): Add casts to HOST_WIDE_INT where
- necessary.
- (const_hash): Hash val is unsigned long.
- (SYMHASH): Likewise.
+1998-10-29 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
- * tree.c (TYPE_HASH): Type of hash val is unsigned long.
+ * emit-rtl.c (try_split): Do not try to split a BARRIER.
- * print-tree.c (print_node_brief): HOST_PTR_PRINTF format wants a
- char pointer, not HOST_WIDE_INT.
- (print_node): Likewise. Also hash is unsigned long not
- HOST_WIDE_INT.
+Thu Oct 29 01:33:54 1998 Jan Hubicka <hubicka@freesoft.cz>
+ Jeffrey A Law (law@cygnus.com)
- * cse.c (canon_hash): Hash is unsigned long not HOST_WIDE_INT.
+ * i386.md: Change ix86_cpu == PROCESSOR_PENTIUM to TARGET_PENTIUM.
+ (zero_extendsidi2): Use # in output template and handle completely by
+ splits.
+ (zero_extend splitters): New define_splits.
+ (ashiftrt_32): New pattern.
- * explow.c (optimize_save_area_alloca): New function for targets
- where SETJMP_VIA_SAVE_AREA is true.
- (allocate_dynamic_stack_space): On SETJMP_VIA_SAVE_AREA targets,
- compute the amount of stack space needed should we find later that
- setjmp is never called by this function, stuff rtl for this inside
- a REG_NOTE of the final SET of stack_pointer_rtx.
- * toplev.c (rest_of_compilation): If SETJMP_VIA_SAVE_AREA and
- current_function_calls_alloca, call optimize_save_area_alloca.
+Wed Oct 28 22:58:35 1998 Jason Merrill <jason@yorick.cygnus.com>
-Sat Jan 17 23:22:59 1998 John Wehle (john@feith.com)
+ * tree.c (append_random_chars): New fn.
+ (get_file_function_name_long): Use it.
- * i386.md: Remove redundant integer push patterns.
- Don't bother checking for TARGET_PUSH_MEMORY when
- pushing constants or registers.
+Wed Oct 28 22:27:05 1998 Richard Henderson <rth@cygnus.com>
+
+ * Makefile.in (cc1): Put C_OBJS, and thence @extra_c_objs@ last.
+ (LIBCPP_OBJS): New. Add cppulp.o.
+ (cppmain, fix-header): Depend on and use libcpp.a.
+ * configure.in (extra_c_objs, extra_cxx_objs): Use libcpp.a instead
+ of the individual object files.
+ * objc/Make-lang.in (cc1obj): Put OBJC_OBJS, and thence @extra_c_objs@,
+ last.
+
+ * cccp.c (user_label_prefix): New.
+ (main): Set it off -f*leading-underscore.
+ (special_symbol): Use it.
+ * cpplib.c (special_symbol): Likewise.
+ (cpp_handle_option): Handle -f*leading-underscore.
+ * cppulp.c: New file.
-Sat Jan 17 22:35:39 1998 Mumit Khan <khan@xraylith.wisc.edu>
- J.J VanderHeijden <J.J.vanderHeijden@student.utwente.nl>
+ * output.h (user_label_prefix): Declare it.
+ * dwarf2out.c (ASM_NAME_TO_STRING): Prepend user_label_prefix.
+ * toplev.c (f_options, main): Handle -f*leading-underscore.
+
+ * defaults.h (ASM_OUTPUT_LABELREF): Use asm_fprintf instead of
+ referencing USER_LABEL_PREFIX directly.
+ * config/nextstep.h (ASM_OUTPUT_LABELREF): Likewise.
+ * m32r/m32r.h (ASM_OUTPUT_LABELREF): Likewise.
+ * final.c (asm_fprintf): Use user_label_prefix instead.
+ * arm/thumb.c (thumb_print_operand): Likewise.
+
+ * gcc.c (default_compilers): Pass -f*leading-underscore on to
+ cpp wherever appropriate.
+
+Wed Oct 28 23:09:25 1998 Robert Lipe <robertl@dgii.com>
- * pexecute.c (pexecute): New function for mingw32. Supports pipes.
- (pwait): New function for mingw32.
+ * sco5.h (SUBTARGET_SWITCHES): Add documentation for OpenServer-
+ specific compiler switches.
- * gcc.c (execute): Mingw32 pexecute() supports pipes, but cygwin32
- pipe support is broken for now.
+Wed Oct 28 21:05:53 1998 Jeffrey A Law (law@cygnus.com)
-1998-01-17 Lee Iverson <leei@Canada.AI.SRI.COM>
+ * Makefile.in (c-common.o): Depend on c-pragma.h. Use $(RTL_H) instead
+ of rtl.h.
- * emit_rtl.c (init_emit_once): Ensure that potential aliasing
- between frame_pointer_rtx, hard_frame_pointer_rtx, and
- arg_pointer_rtx is respected in initialization.
- (init_emit_once): Use gen_rtx_raw_REG() to create
- return_address_pointer_rtx.
+Wed Oct 28 20:52:47 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * reorg.c: #include "expr.h" for rtx prototypes.
- * Makefile.in (reorg.o): Depend on expr.h
+ * gcc.c (EXTRA_SPECS, extra_specs): Introduce an intermediate
+ structure which has exactly the members provided by EXTRA_SPECS.
+ Xmalloc() the real `extra_specs', and initialize it from this
+ intermediate structure.
-Sat Jan 17 21:28:08 1998 Pieter Nagel <pnagel@epiuse.co.za>
+ * alpha.h (EXTRA_SPECS): Revert change for missing initializers.
- * Makefile.in (FLAGS_TO_PASS): Pass down gcc_include_dir and
- local_prefix to sub-make invocations.
+ * mips.h (EXTRA_SPECS): Likewise.
-Sat Jan 17 21:24:16 1998 David T. McWherter <dtm@waterw.com>
+ * sparc.h (EXTRA_SPECS): Likewise.
- * objc-parse.c: Recognize protocol qualifiers in class definitions.
+Wed Oct 28 16:46:07 1998 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
-Sat Jan 17 21:16:19 1998 Jeffrey A Law (law@cygnus.com)
+ * function.c (purge_addressof_1): Instead of aborting when a
+ bitfield insertion as a replacement for (MEM (ADDRESSOF)) does not
+ work just put the ADDRESSOF on stack. Otherwise remember all such
+ successful replacements, so that exactly the same replacements
+ can be made on the REG_NOTEs. Remove the special case for CALL
+ insns again.
+ (purge_addressof_replacements): New variable.
+ (purge_addressof): Clear it at end.
- * rtl.h: Fix typos.
+1998-10-28 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * acconfig.h (NEED_DECLARATION_ATOL): New declaration to check for.
- * configure.in: Check for atol.
- * rtl.c (atol): Only provide the declaration if NEED_DECLARATION_ATOL.
+ * c-lang.c: Declare extern char *yy_cur if USE_CPPLIB.
+ (lang_init): Call check_newline always.
+ * c-lex.c (init_parse) [USE_CPPLIB=1]: After calling
+ cpp_start_read, set yy_cur and yy_lim to read from
+ parse_in.token_buffer, so that we'll see the first #line
+ directive.
+ * cpplib.c (cpp_start_read): finclude the main input file
+ before processing -include/-imacros. Process -imacros and
+ -include separately, and handle -include by stacking a
+ buffer for the file in question as if it'd been #included.
+ * toplev.c (documented_lang_options): Recognize -H when
+ USE_CPPLIB is on.
+
+1998-10-28 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cpplib.c: Merge do_once into do_pragma. Break file handling
+ code out of do_include.
+ Move append_include_chain, deps_output,
+ file_cleanup, redundant_include_p, import_hash,
+ lookup_import, add_import, read_filename_string, read_name_map,
+ open_include_file, finclude, safe_read to cppfiles.c.
+ Move prototypes for deps_output, append_include_chain,
+ finclude to cpplib.h. Move definition of struct
+ file_name_list there also.
+
+ * cppfiles.c: New file. Contains all the above functions
+ broken out of cpplib.c; also hack_vms_include_specification
+ from cccp.c and find_include_file, a new function broken out of
+ do_include.
+
+ * Makefile.in (cppmain): Depend on cppfiles.o.
+ (fix-header): Likewise.
+ (cppfiles.o): New target.
+ * configure.in (--enable-c-cpplib): Add cppfiles.o to
+ extra_c_objs. Add ../cppfiles.o to extra_cxx_objs.
+
+Wed Oct 28 14:06:49 1998 Jim Wilson <wilson@cygnus.com>
+
+ * dwarfout.c (dwarfout_file_scope_decl): If DECL_CONTEXT, don't abort
+ if pending_types is non-zero.
+ (dwarfout_finish): Verify pending_types is zero before finishing.
+
+Wed Oct 28 10:29:09 1998 Nick Clifton <nickc@cygnus.com>
+
+ * expr.c (convert_move): Use shifts to perform the move if a
+ suitable extend pattern cannot be found. Code written by
+ Richard Henderson <rth@cygnus.com>.
+
+Wed Oct 28 03:59:29 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * regclass.c (renumber, regno_allocated): New static variables, moved
+ out of allocate_reg_info.
+ (allocate_reg_info): Move these two variables outside the function.
+ Move code to free memory into new function free_reg_info.
+ (free_reg_info): New function, broken out of allocate_reg_info.
+ * toplev.c (compile_file): Call free_reg_info, not allocate_reg_info.
+ * rtl.h (allocate_reg_info): Don't declare.
+ (free_reg_info): Declare.
+
+ * final.c (cleanup_subreg_operands): ASM_INPUTs need no treatment.
+
+Wed Oct 28 02:38:12 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * toplev.c (compile_file): Temporarily revert last change.
+
+Wed Oct 28 00:00:35 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * c-typeck.c (convert_for_assignment): Parenthesize.
+
+1998-10-28 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * reload1.c (delete_output_reload): Avoid ambigous else.
+
+Wed Oct 28 00:10:35 1998 Jeffrey A Law (law@cygnus.com)
+
+ * toplev.c (compile_file): Call allocate_reg_info to free register
+ table memory.
+ * rtl.h (allocate_reg_info): Declare.
+
+ * PROJECTS: Remove entry for local spilling.
+
+ * final.c (cleanup_subreg_operands): New function.
+ (final_scan_insn): Use it.
+ (alter_subreg): Clear the "used" field when we turn a SUBREG into
+ a REG.
+ * reload1.c (reload): Delete CLOBBER insns and also cleanup SUBREG
+ operands when reload has finished.
+ * reload.h (cleanup_subreg_operands): Declare..
+ * flow.c (life_analysis_1): No longer delete CLOBBER insns after
+ reload. Handled in reload itself.
+
+Tue Oct 27 23:32:34 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * reload1.c (verify_initial_offsets): New function.
+ (reload): Call it after reload_as_needed. Also verify that the frame
+ size stays constant during reload_as_needed.
+ * i386.h (CONST_DOUBLE_OK_FOR_LETTER_P): Undo Jul 26 change.
+
+ * reload.h (struct insn_chain): Add need_operand_change element.
+ * reload1.c (new_insn_chain): Clear it.
+ (calculate_needs_all_insns): Set it; don't overload need_reload.
+ (reload_as_needed): Use it.
+
+ * reload.c (find_reloads_address): Use BASE_REG_CLASS instead of
+ reload_address_base_reg_class throughout. Similar for INDEX_REG_CLASS
+ and reload_address_index_reg_class.
+ (find_reloads_address_1): Likewise.
+ * reload.h (reload_address_base_reg_class,
+ reload_address_index_reg_class): Don't declare.
+ * reload1.c (reg_old_renumber, pseudo_previous_regs,
+ pseudo_forbidden_regs, bad_spill_regs_global): New static variables.
+ (used_spill_regs): Now static.
+ (reload_address_base_reg_class, reload_address_index_reg_class,
+ regs_explicitly_used, counted_for_groups, counted_for_nongroups,
+ basic_block_needs, max_needs, group_size, group_mode, max_groups,
+ max_nongroups, max_needs_insn, max_groups_insn, max_nongroups_insn,
+ forbidden_regs):
+ Deleted variables.
+ (init_reload): Delete code to compute base/index reg classes.
+ (reload): Delete variable J.
+ Delete code to manage basic_block_needs.
+ Don't compute regs_explicitly_used.
+ Allocate, initialize and free reg_old_renumber, pseudo_forbidden_regs,
+ pseudo_previous_regs.
+ Initialize bad_spill_regs_global.
+ Don't call order_regs_for_reload here.
+ Don't initialize spill_reg_order and n_spills.
+ Don't forbid explicitly used regs to be used for spill regs.
+ Change main loop to infinite loop, with explicit break statements.
+ Make SOMETHING_CHANGED variable local to that loop.
+ Don't initialize max_needs, max_groups, max_nongroups, max_needs_insn,
+ max_groups_insn, max_nongroups_insn, group_size, group_mode.
+ Make sure spilled_pseudos is cleared before calling spill_hard_reg or
+ new_spill_reg.
+ Don't call dump_needs.
+ Delete code to reset potential_reload_regs.
+ Delete code to terminate loop conditional on the global needs variables
+ showing no further needs.
+ (calculate_needs_all_insns): Return void. All callers changed.
+ Initialize something_needs_elimination here, not in reload.
+ Delete avoid_return_reg kludge.
+ (calculate_needs): Lose AVOID_RETURN_REG and GLOBAL args, return void.
+ All callers changed.
+ Initialize the group_mode and group_size elements of the arg CHAIN.
+ Delete code to manage basic_block_needs.
+ Operate on elements of CHAIN instead of global variables.
+ Delete avoid_return_reg kludge.
+ (find_tworeg_group): Lose GLOBAL arg, take CHAIN arg, return void.
+ All callers changed.
+ Operate on elements of CHAIN instead of global variables.
+ Delete special SMALL_REGISTER_CLASSES code.
+ Delete spill_failure code; now in new_spill_reg.
+ (find_group): Lose GLOBAL arg, take CHAIN arg, return void.
+ All callers changed.
+ Operate on elements of CHAIN instead of global variables.
+ (maybe_mark_pseudo_spilled): New static function.
+ (find_reload_regs): Lose GLOBAL arg, take CHAIN arg, return void.
+ All callers changed.
+ Operate on elements of CHAIN instead of global variables.
+ Call order_regs_for_reload here, not in reload.
+ Initialize spill_reg_order and n_spills.
+ Simplify test whether an asm insn is involved.
+ Delete spill_failure code; now in new_spill_reg.
+ Call maybe_mark_pseudo_spilled for everything marked as live in
+ CHAIN. Merge CHAIN's used_spill_regs into the global variable
+ used_spill_regs.
+ (dump_needs): Take CHAIN arg. No longer static, to prevent the
+ compiler from optimizing this function (now unused) away.
+ Operate on elements of CHAIN instead of global variables.
+ (possible_group_p): Lose MAX_GROUPS arg, take CHAIN arg. All callers
+ changed.
+ Operate on elements of CHAIN instead of global variables.
+ (count_possible_groups): Lose GROUP_SIZE, GROUP_MODE, MAX_GROUPS args,
+ take CHAIN arg. All callers changed.
+ Operate on elements of CHAIN instead of global variables.
+ (new_spill_reg): Lose MAX_NEEDS, MAX_NONGROUPS, GLOBAL args, take
+ CHAIN, NONGROUP args. Return void. All callers changed.
+ Verify caller isn't trying to spill a pseudo.
+ Simplify test for illegal reg, just use bad_spill_regs.
+ Generate better error messages.
+ Operate on elements of CHAIN instead of global variables.
+ Mark spilled register in CHAIN's used_spill_regs element.
+ Don't call spill_hard_reg.
+ (spill_hard_reg): Lose GLOBAL arg, return void. All callers changed.
+ Mark spilled hard regs in bad_spill_regs_global.
+ Mark affected pseudos in spilled_pseudos, but don't spill them.
+ (ior_hard_reg_set): New static function.
+ (finish_spills): Return int. All callers changed.
+ Compute spill_reg_order, n_spills and spill_regs here. Also update
+ regs_ever_live for regs used as spills.
+ For every pseudo in spilled_pseudos, spill it and mark the previous
+ hard reg it had in pseudo_previous_regs. Compute which hard regs
+ are used as spills in insns during which it is live, and retry global
+ register allocation. Update all life information in the
+ reload_insn_chain not to include pseudos without hard regs.
+ Call alter_reg for all affected speudos.
+
+ (scan_paradoxical_subregs): Disable SMALL_REGISTER_CLASSES special
+ case, it's not clear what it's supposed to do.
+
+ (hard_reg_use_compare): Take bad_spill_regs into account.
+ (pseudos_counted): New static variable.
+ (count_pseudo): New static function.
+ (order_regs_for_reload): Take CHAIN arg. All callers changed.
+ Initialize bad_spill_regs from bad_spill_regs_global, then merge any
+ hard registers explicitly used across the current insn into the set.
+ Compute hard_reg_n_uses taking only pseudos live across this insn
+ into account.
+ Tweak sorting of potential_reload_regs.
+ (compare_spill_regs): Delete function.
+ (reload_as_needed): Don't sort the spill_regs array, it's computed
+ in proper order in finish_spills.
+ Delete avoid_return_reg kludge.
+ Delete code to manage basic_block_needs.
+ (allocate_reload_reg): Minor speed/readability tweaks.
+ Operate on elements of CHAIN instead of global variables.
+ (choose_reload_regs): Lose AVOID_RETURN_REG arg. All callers changed.
+ Delete avoid_return_reg kludge.
+ Initialize reload_reg_used from CHAIN's used_spill_regs element.
+ Delete unused label FAIL.
+ (reload_combine): Replace reload_address_index_reg_class with
+ INDEX_REGS.
+ Don't use used_spill_regs to determine information about lifetime of
+ hard regs.
+
+Tue Oct 27 13:15:02 1998 Nick Clifton <nickc@cygnus.com>
+
+ * toplev.c (display_help): Ignore empty target specific
+ options, and if -W is also specified on the command line then
+ display undocumented options.
+
+ * config/arm/arm.c: Updated with changes in devo sources.
+ * config/arm/arm.h: Updated with changes in devo sources.
+ * config/arm/lib1funcs.asm: Updated with changes in devo sources.
+ * config/arm/lib1thumb.asm: Add ELF support.
+
+Tue Oct 27 16:11:43 1998 David Edelsohn <edelsohn@gnu.org>
- * rtl.c (read_rtx): Initialize list_rtx to NULL, not NULL_RTX.
+ * collect2.c (aix64_flag): New variable.
+ (main, case 'b'): Parse it.
+ (GCC_CHECK_HDR): Object magic number must match mode.
+ (scan_prog_file): Only check for shared object if valid header.
+ Print debugging if header/mode mismatch.
- * loop.c (find_and_verify_loops): When attempting to move insns from
- inside the loop outside the loop, create a BARRIER if no suitable
- one was found.
+Tue Oct 27 10:15:02 1998 Nick Clifton <nickc@cygnus.com>
- * jump.c (jump_optimize): Remove Dec 17, 1997 chance in
- favor of an equivalent change from gcc-2.8.
+ Added support for arm-elf-linux configuration, submitted by Philip
+ Blundell <pb@nexus.co.uk>, and integrated this with the arm-elf
+ code developed by Catherine Moore <clm@cygnus.com>. The following
+ files are affected:
- * i386/x-sco5 (CC): Remove trailing whitespace.
+ * configure.in: Add arm-*-linux-gnu, armv2-*-linux and arm-*-elf
+ targets.
-Sat Jan 17 21:09:46 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * configure: Regenerated.
- * gengenrtl.c (type_from_format): De-ANSIfy function signature.
- (accessor_from_format): Likewise.
- (xmalloc): New function for use when linking with alloca.o.
+ * config/arm/aout.h: Add default definitions of REGISTER_PREFIX,
+ USER_LABEL_PREFIX and LOCAL_LABEL_PREFIX. Make other macro
+ definitions conditional on their not having been already defined.
-Mon Jan 5 02:53:01 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+ * config/arm/lin1funcs.asm: Add ELF only macros to generate .size
+ and .type directives, and add "(PLT)" qualification to function
+ calls.
- * frame.c (find_fde): Correct FDE's upper bound.
+ * config/arm/linux.h: Deleted. This file is now superseded by
+ either linux-elf.h or linux-aout.h.
-Fri Jan 16 16:23:52 1998 Richard Henderson <rth@cygnus.com>
+ * config/arm/linux-gas.h: Define `inhibit_libc' if cross-compiling.
+ (CLEAR_INSN_CACHE): New macro, currently disabled (awaiting kernel
+ support).
+ Move definitions from old linux.h file here.
- * gengenrtl.c (DEF_RTL_EXPR): Provide a K&R compliant version.
+ * config/arm/elf.h: New file. Generic ARM/ELF support.
-Fri Jan 16 10:16:10 1998 Jeffrey A Law (law@cygnus.com)
+ * config/arm/linux-aout.h: New file. Support for Linux with a.out.
- * calls.c (expand_call): Move #ifdef code out of macro argument
- lists.
- (emit_library_call, emit_library_call_value): Likewise.
+ * config/arm/linux-elf.h: New file. Support for Linux with ELF.
-Fri Jan 16 00:46:40 1998 Jeffrey A Law (law@cygnus.com)
+ * config/arm/linux-elf26.h: New file. Support for Linux with ELF
+ using the 26bit APCS.
- * rtl.def (INLINE_HEADER): Fix bug exposed by gen_rtx_FOO changes.
+ * config/arm/unknown-elf.h: New file. Support for OS'es other
+ than Linux with ELF.
-Thu Jan 15 01:02:30 1998 Jeffrey A Law (law@cygnus.com)
+ * config/arm/t-arm-elf: New file. makefile fragment for arm-elf
+ builds.
- * version.c: Bump for snapshot.
+ * config/arm/coff.h: Include aout.h for basic assembler macros.
+ Add support for -mstructure_size_boundary=<n> command line option.
-Wed Jan 14 22:49:17 1998 Richard Henderson <rth@cygnus.com>
+ * config/arm/arm.h: Add support for -mstructure_size_boundary=<n>
+ command line option. Make macro definitions conditional on their
+ not having been already defined.
- * alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
- change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
- * caller-save.c, calls.c, combine.c, cse.c: Likewise.
- * dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
- * final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
- * halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
- * profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
- * reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
- * unroll.c, varasm.c: Likewise.
- * config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
+ * config/arm/arm.c: Add support for -mstructure_size_boundary=<n>
+ command line option.
-Wed Jan 14 19:36:08 1998 Gavin Koch (gavin@cygnus.com)
- * mips.h: Fix some type-o's from a previous change.
+Tue Oct 27 08:56:46 1998 Andrew MacLeod <amacleod@cygnus.com>
-Wed Jan 14 01:26:05 1998 Jeffrey A Law (law@cygnus.com)
+ * dwarfout.c (ASM_OUTPUT_DWARF_STRING_NEWLINE): ASM_OUTPUT_DWARF_STRING
+ has been changed to not include a newline. Use this macro instead.
+ (output_enumeral_list, const_value_attribute, name_attribute,
+ comp_dir_attribute, prototyped_attribute, producer_attribute,
+ inline_attribute, pure_or_virtual_attribute, output_inheritance_die,
+ dwarfout_file_scope_decl, generate_new_sfname_entry,
+ generate_macinfo_entry, dwarfout_init, dwarfout_finish): Use
+ ASM_OUTPUT_DWARF_STRING_NEWLINE macro.
- * loop.c (check_dbra_loop): Make sure initial value is a
- CONST_INT before trying to normalize it.
+Mon Oct 26 13:35:02 1998 Richard Henderson <rth@cygnus.com>
-Tue Jan 13 23:27:54 1998 Robert Lipe (robertl@dgii.com)
+ * combine.c (subst): Process the inputs to a parallel asm_operands
+ only once.
- * sco5.h (ASM_OUTPUT_SECTION_NAME): Refresh from ../svr4.h.
+Mon Oct 26 13:32:31 1998 Richard Henderson <rth@cygnus.com>
-Tue Jan 13 22:47:02 1998 Herman ten Brugge <herman@htbrug.net.HCC.nl>
+ * stmt.c (expand_asm_operands): Accept `=' or `+' at any position.
- * cppexp.c: Include gansidecl.h
+Mon Oct 26 12:53:14 1998 Jeffrey A Law (law@cygnus.com)
-Tue Jan 13 22:43:35 1998 Ian Lance Taylor <ian@cygnus.com>
+ * tm.texi (ASM_OUTPUT_MAX_SKIP_ALIGN): Document.
- * svr4.h (LINK_SPEC): Never specify -h.
- * ptx4.h (LINK_SPEC): Likewise.
- * rs6000/sysv4.h (LINK_SPEC): Likewise.
- * sparc/sol2.h (LINK_SPEC): Likewise.
+Mon Oct 26 00:36:58 1998 Jeff Law (law@cygnus.com)
-Tue Jan 13 22:39:40 1998 Richard Henderson (rth@cygnus.com)
+ * version.c: Bump for snapshot.
- * c-typeck.c (comptypes): Exit early on NULL input.
+Sun Oct 25 23:36:52 1998 Jason Merrill <jason@yorick.cygnus.com>
- * haifa-sched.c (schedule_insns): Correctly remove inter-block
- dependencies after reload.
+ * stmt.c (expand_fixup): Set fixup->before_jump to a
+ NOTE_INSN_DELETED instead of a NOTE_INSN_BLOCK_BEG.
-Tue Jan 13 22:22:31 1998 Franz Sirl <franz.sirl-kernel@lauterbach.com>
+Sun Oct 25 15:49:57 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * rs6000/linux.h (CPP_PREDEFINES): Add -D__ELF__.
+ * Makefile.in (recog.o): Depend on toplev.h.
+ (insn-emit.o): Depend on recog.h.
+ (insn-peep.o): Depend on recog.h and insn-config.h.
-Tue Jan 13 22:14:57 1998 Klaus Kaempf <kkaempf@progis.de>
+ * combine.c (simplify_set): Remove unused variable `scratches'.
- * alpha/vms.h (DIR_SEPARATOR): define
+ * final.c (final_scan_insn): Wrap declaration of variables `vlen'
+ and `idx' in macro conditional controlling their use.
-Tue Jan 13 22:13:04 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+ * genemit.c (main): Make the generated output file include
+ recog.h. Don't have it declare `insn_operand_constraint', since
+ we get it from recog.h.
- * Makefile.in (stamp-proto): Remove.
- (protoize.o, unprotoize.o): Straightforward compile.
- * unprotoize.c: Define UNPROTOIZE here, not in the Makefile.
+ * genpeep.c (main): Make the generated output file include
+ insn-config.h and recog.h.
-Tue Jan 13 21:59:39 1998 Mumit Khan <khan@xraylith.wisc.edu>
+ * recog.c: Include toplev.h.
+ (extract_insn): Remove unused variable `p'.
- * i386/cygwin32.h (STRIP_NAME_ENCODING): Define for Win32 to strip
- off the trailing @[NUM] added by ENCODE_SECTION_INFO.
+ * regclass.c (fix_register): Add missing braces around initializer
+ for `what_option'.
+ (allocate_reg_info): Move variable `i' into the scope where it is
+ used. Change its type to `size_t'.
-Tue Jan 13 21:55:06 1998 Jeffrey A Law (law@cygnus.com)
+Sun Oct 25 13:10:15 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * arm/netbsd.h (DWARF2_UNWIND_INFO): Define as zero for now.
- * i386/netbsd.h, m68k/netbsd.h, ns32k/netbsd.h: Likewise.
- * sparc/netbsd.h, vax/netbsd.h: Likewise.
+ * reload.c (push_reload): When merging reloads, make sure
+ that reload_in_reg and reload_in are from the same reload in
+ all cases.
-Tue Jan 13 21:37:07 1998 Shigeya Suzuki <shigeya@foretune.co.jp>
+Sun Oct 25 12:07:00 1998 Mumit Khan <khan@xraylith.wisc.edu>
- * i386/bsd386.h (DWARF2_UNWIND_INFO): Define as zero for now.
+ * i386/crtdll.h (CPP_PREDEFINES): Fix typo.
+ * i386/mingw32.h (CPP_PREDEFINES): Likewise.
-Tue Jan 13 17:50:55 1998 Jim Wilson <wilson@cygnus.com>
+Fri Oct 23 23:42:03 1998 David Edelsohn <edelsohn@gnu.org>
- * configure.in (target_cpu_default, target_cpu_default2): Use double
- quotes around them when testing their value.
- * configure: Rebuilt.
+ * loop.c (loop_has_tablejump): New variable.
+ (prescan_loop): Scan for it.
+ (insert_bct): Replace explicit scan with use of it.
+ * regclass.c (regclass): Restore loop variable j.
+ (record_reg_classes): Deterine op_types modifiers and initialize
+ classes[i] before matching constraints. Handle matching
+ constraints 5-9.
-Tue Jan 13 09:07:44 1998 John Carr <jfc@mit.edu>
+Fri Oct 23 13:55:48 1998 Jim Wilson <wilson@cygnus.com>
- * gengenrtl.c (gencode): Emit new function obstack_alloc_rtx
- to allocate rtx.
- (gendef): Call obstack_alloc_rtx.
+ * m32r/m32r.c (gen_split_move_double): Call alter_subreg. Delete
+ subreg support.
-Tue Jan 13 01:16:36 1998 Robert Lipe (robertl@dgii.com)
+Fri Oct 23 16:19:24 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * configure.in: (i[3456]86-UnixWare7-sysv5): Treat much like SVR4
- for now.
+ * mips.h (EXTRA_SPECS): Add missing initializers.
-Thu Dec 18 18:40:17 1997 Mumit Khan <khan@xraylith.wisc.edu>
+Fri Oct 23 16:08:39 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * i386/mingw32.h (INCOMING_RETURN_ADDR_RTX): Delete. Use the value
- of DWARF2_UNWIND_INFO, if any, from i386/cygwin32.h instead.
- (STANDARD_INCLUDE_DIR): Change to /usr/local/i386-mingw32/include.
+ * sparc.h (EXTRA_SPECS): Add missing initializers.
+ (sparc_defer_case_vector): Provide a prototype.
-Tue Jan 13 00:44:02 1998 Jim Wilson <wilson@cygnus.com>
+ * svr4.h (ASM_OUTPUT_ASCII): Cast STRING_LIMIT to (long) when
+ comparing it to the result of a pointer subtraction.
- * mips.md (return_internal): Change mode from SImode to VOIDmode.
+Fri Oct 23 15:34:14 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Sat Jan 10 22:11:39 1998 J. Kean Johnston <jkj@sco.com>
+ * alpha.c (override_options): Use ISDIGIT(), not isdigit(). Cast
+ the argument to (unsigned char).
- * i386/sco5.h (STARTFILE_SPEC, ENDFILE_SPEC): Correctly handle
- "-static".
+ * alpha.h (EXTRA_SPECS): Add missing initializers.
+ (ASM_GENERATE_INTERNAL_LABEL): Ensure the argument matches the
+ format specifier.
-Sat Jan 10 22:04:15 1998 Stan Cox <scox@equinox.cygnus.com>
+Fri Oct 23 13:12:35 1998 Jeffrey A Law (law@cygnus.com)
- * i386.md: (movsicc_1, movhicc_1): For alternate 3 set the opcode
- suffix from operand 3.
+ * flow.c (life_analysis_1): Enable "rescan" code after reload.
+ (propagate_block): Delete dead code after reload.
-Sat Jan 10 21:50:16 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- Jeffrey A Law (law@cygnus.com)
+ * sched.c (update_flow_info): Revert Oct 19, 1998 change. Brings
+ back Oct 15, 1998 change.
+ * haifa-sched.c (update_flow_info): Likewise.
+ * flow.c (life_analysis_1): Delete CLOBBER insns after reload.
- * regmove.c: New implementation of regmove pass.
- * local-alloc.c (optimize_reg_copy_1, optimize_reg_copy_2): Remove
- decls, make them have external linkage. Return a value from
- optimize_reg_copy_1.
- * reload.h (count_occurrences): Add decl.
- * reload1.c (count_occurrences): Delete decl, make it have external
- linkage.
- * rtl.h (optimize_reg_copy_1, optimize_reg_copy_2): Declare.
+ * mn10200.md (truncated shift): Accept constant inputs too.
-Sat Jan 10 20:30:12 1998 Jeffrey A Law (law@cygnus.com)
+Fri Oct 23 04:06:57 1998 Richard Earnshaw (rearnsha@arm.com)
- * regclass.c (record_address_regs): Don't use REG_OK_FOR_BASE_P
- if it is not defined.
+ * machmode.h (mode_mask_array): No longer const.
+ * rtl.c (init_rtl): Fully initialize it if EXTRA_CC_MODES defined.
-Thu Jan 8 21:06:54 1998 Richard Henderson <rth@cygnus.com>
+Fri Oct 23 11:19:06 1998 Martin v. Löwis <loewis@informatik.hu-berlin.de>
- * Makefile.in (OBJ, GEN, RTL_H): Add genrtl.[oh] bits.
- * emit-rtl.c (gen_rtx): Move special code to ...
- (gen_rtx_CONST_INT): New function.
- (gen_rtx_REG): New function.
- (*): Update all calls to gen_rtx.
- * genemit.c (gen_exp): Emit calls to gen_rtx_FOO for constant FOO.
- * rtl.h: Include genrtl.h; prototype CONST_INT & REG generators.
- (GEN_INT): Call gen_rtx_CONST_INT.
- * gengenrtl.c: New file.
+ * frame.c: Somewhat explain `FDE'.
+ Suggested by Brendan Kehoe
-Mon Jan 5 13:00:18 1998 John F. Carr <jfc@mit.edu>
+Fri Oct 23 00:56:11 1998 Jason Merrill <jason@yorick.cygnus.com>
- * alias.c (*_dependence): Call base_alias_check before canon_rtx.
- (base_alias_check): If no base found for address call canon_rtx and
- try again.
+ * expr.c (pending_chain): Move up.
+ (save_expr_status): Do save pending_chain.
+ (restore_expr_status): And restore it.
+ * function.h (struct function): Add pending_chain.
-Mon Jan 5 11:39:49 1998 Jeffrey A Law (law@cygnus.com)
+1998-10-23 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * reorg.c (relax_delay_slots): Fixed test for mostly_true_jump. The
+ did not match the code.
+
+Fri Oct 23 00:07:01 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * regclass.c (regclass): Break out some code into new function
+ scan_one_insn, and into regclass_init.
+ (init_cost): New static variable, moved out of regclass.
+ (regclass_init): Initialize it here, not in .
+ (scan_one_insn): New static function, broken out of regclass.
+ * recog.c (apply_change_group): Break out some code into new
+ function insn_invalid_p.
+ (insn_invalid_p): New static fn, broken out of apply_change_group.
+
+Thu Oct 22 22:34:42 1998 Jim Wilson <wilson@cygnus.com>
+
+ * reload1.c (reload_as_needed): When rewrite POST_INC, verify
+ reg_reloaded_contents matches incremented pseudo.
+
+ * v850/v850.c (v850_reorg): Call alter_subreg. Delete subreg support.
+
+Fri Oct 23 11:11:56 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * rtl.def (POST_MODIFY, PRE_MODIFY): New generalized operators for
+ addressing modes with side effects. These are currently
+ placeholders for the C4x target.
+
+Thu Oct 22 16:46:35 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * loop.c (express_from): Make sure that when generating a PLUS of
+ a PLUS, any constant expression appears on the outermost PLUS.
+
+Thu Oct 22 15:46:23 1998 Per Bothner (bothner@cygnus.com)
+
+ * Makefile.in (distdir-cvs, distdir-start): Clean up so it
+ works if "$(srcdir)" != ".".
+
+Wed Oct 21 19:23:59 1998 Jim Wilson <wilson@cygnus.com>
+
+ * expmed.c (store_bit_field): If need to add a SUBREG, then remove
+ existing SUBREG if we can, otherwise abort.
+
+Wed Oct 21 09:58:51 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * c-common.c (c_apply_type_quals_to_decl): Don't crash when
+ `restrict' is applied to a non-pointer variable.
+
+Wed Oct 21 09:18:58 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * invoke.texi: Document -flang-isoc9x.
- * mips.c (mips_expand_prologue): Handle large frame with no outgoing
- arguments for mips16.
- (mips_expand_epilogue): Pass "orig_tsize" to save_restore_insns.
- Don't lose if tsize is zero after handling large stack for mips16.
- * mips.md (return): For trivial return, return address is in $31.
+ * Makefile.in (OBJS): Add splay-tree.o.
+ (c-common.o): Depend on rtl.h.
+ (splay-tree.o): List dependencies and provide build rule.
+
+ * rtl.h (record_alias_subset): New function.
+ * alias.c: Include splay-tree.h.
+ (alias_set_entry): New type.
+ (CHECK_ALIAS_SETS_FOR_CONSISTENCY): Remove.
+ (DIFFERENT_ALIAS_SETS_P): Use mem_in_disjoint_alias_sets_p.
+ (mems_in_disjoin_alias_sets_p): New function.
+ (alias_set_compare): Likewise.
+ (insert_subset_children): Likewise.
+ (get_alias_set_entry): Likewise.
+
+ * tree.h (TYPE_RESTRICT): New macro.
+ (TYPE_UNQUALIFIED): New manifest constant.
+ (TYPE_QUAL_CONST): Likewise.
+ (TYPE_QUAL_VOLATILE): Likewise.
+ (TYPE_QUAL_RESTRICT): Likewise.
+ (tree_type): Add restrict_flag. Reduce count of free bits.
+ (DECL_POINTER_ALIAS_SET): New macro.
+ (DECL_POINTER_ALIAS_SET_KNOWN_P): Likewise.
+ (tree_decl): Add pointer_alias_set.
+ (build_qualified_type): New function.
+ (build_type_variant): Define in terms of build_qualified_type.
+ * tree.c (set_type_quals): New function.
+ (make_node): Initialize DECL_POINTER_ALIAS_SET.
+ (build_type_attribute_variant): Use build_qualified_type and
+ set_type_quals.
+ (build_type_variant): Rename, and modify, to become...
+ (build_qualified_type): New function.
+ (build_complex_type): Use set_type_quals.
-Sun Jan 4 20:24:00 1998 Nigel Stephens <nigel@algor.co.uk>
+ * c-tree.h (C_TYPE_OBJECT_P): New macro.
+ (C_TYPE_FUNCTION_P): Likewise.
+ (C_TYPE_INCOMPLETE_P): Likewise.
+ (C_TYPE_OBJECT_OR_INCOMPLETE_P): Likewise.
+ (c_apply_type_quals_to_decl): New function.
+ (c_build_qualified_type): New function.
+ (c_build_type_variant): Define in terms of c_build_qualified_type.
+ (flag_isoc9x): Declare.
+ * c-typeck.c (qualify_type): Use c_build_qualified_type.
+ (common_type): Change to use TYPE_QUALS.
+ (comptypes): Likewise.
+ (convert_for_assignment): Likewise.
+ * c-aux-info.c (gen_type): Likewise. Deal with `restrict'.
+ * c-decl.c (flag_isoc9x): Define.
+ (c_decode_option): Handle -flang-isoc9x.
+ (grokdeclarator): Update to handle restrict. Use TYPE_QUALS,
+ c_build_qualified_type, etc. Use c_apply_type_quals_to_decl.
+ * c-lex.c (init_lex): Deal with restrict.
+ (init_lex): Don't treat restrict as a reserved word in
+ -traditional mode, or without -flang-isoc9x.
+ * c-lex.h (rid): Add RID_RESTRICT.
+ * c-parse.gperf (restrict, __restrict, __restrict__): Make
+ equivalent to RID_RESTRICT.
+ * c-parse.in (TYPE_QUAL): Update comment.
+ * c-common.c: Include rtl.h.
+ (c_find_base_decl): New function.
+ (c_build_type_variant): Rename, and modify, to become ...
+ (c_build_qualified_type): New function.
+ (c_apply_type_quals_to_decl): Likewise.
+ (c_get_alias_set): For INDIRECT_REFs, check to see if we can find
+ a particular alias set for the reference.
+ * toplev.c (documented_lang_options): Add -flang-isoc9x.
- * mips/mips16.S: Various changes to make it work with -msingle-float
- and -EL.
+Wed Oct 21 09:15:06 1998 Nick Clifton <nickc@cygnus.com>
-Sun Jan 4 14:25:18 1998 Gavin Koch <gavin@cygnus.com>
- Ian Lance Taylor <ian@cygnus.com>
- Jeff Law <law@cygnus.com>
+ * config/arm/arm.h (TARGET_SWITCHES): Document arm specific
+ command line switches.
- * mips.c, mips.h, mips.md: First cut at merging in mips16
- support. Major modifications throughout all three files.
+Tue Oct 20 10:04:51 1998 Graham <grahams@rcp.co.uk>
-Sun Jan 4 01:01:50 1998 scott snyder <snyder@d0sgif.fnal.gov>
+ * reload.c (loc_mentioned_in_p): Add missing braces to bind
+ else to correct if.
- * configure.in: Make gthr-default.h a forwarding header instead of
- a symlink.
+Mon Oct 19 16:34:05 1998 Tom Tromey <tromey@cygnus.com>
-Sat Jan 3 12:08:06 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * gcc.c (option_map): Added --classpath and --CLASSPATH.
- * gcov-io.h: Include sys/types.h to ensure we get size_t.
+Tue Oct 20 10:59:02 1998 Gavin Romig-Koch <gavin@cygnus.com>
- * pa.h (ASM_OUTPUT_MI_THUNK): Add missing % in fprintf.
+ * regclass.c (fix_register): Add error message.
+ * invoke.texi (-fcall-used-REG,-fcall-saved-REG): Note the
+ new error message.
-Fri Jan 2 23:40:09 1998 Jim Wilson (wilson@cygnus.com)
- Jeffrey A Law (law@cygnus.com)
+Tue Oct 20 10:12:17 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * crtstuff.c (__frame_dummy): New function for irix6.
- (__do_global_ctors): Call __frame_dummy for irix6.
- * iris6.h (LINK_SPEC): Hide __frame_dummy too.
+ * c-decl.c (warn_missing_noreturn): New global variable.
+ (c_decode_option): Check for new flags -W{no-}missing-noreturn.
+ (finish_function): Implement missing noreturn warning.
+
+ * c-tree.h (warn_missing_noreturn): Declare extern.
+
+ * invoke.texi: Document new flags.
+
+ * toplev.c (documented_lang_options): Add description.
+
+Tue Oct 20 22:16:11 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.c (c4x_parallel_process): Disable until BCT
+ loop optimization stable for the C4x.
+ (c4x_rptb_info_t, c4x_dump, c4x_rptb_in_range, c4x_rptb_unjumped_loop,
+ c4x_rptb_find_comp_and_jump, c4x_rptb_loop_info_get,
+ c4x_rptb_emit_init, c4x_rptb_process): Deleted (superseded by BCT
+ loop optimization).
+ (c4x_address_conflict): Be more paranoid when packing a volatile
+ memref in a parallel load/store.
+
+Tue Oct 20 21:56:05 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.md (repeat_block_top, repeat_block_end,
+ repeat_block_filler): Deleted.
+ (*ashlqi3_set, *ashrqi3_const_set, *ashrqi3_nonconst_clobber):
+ Condition code not set if destination register from 'c' class.
+ (*subbqi3_carry_clobber): Fix typo.
+
+1998-10-18 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * reorg.c (steal_delay_list_from_target): Check for insns that
+ modify the condition codes and effect the direction of the jump
+ in the sequence.
-Fri Jan 2 04:57:57 1998 Weiwen Liu <liu@hepmail.physics.yale.edu>
+Sat Oct 17 13:09:09 1998 Graham <grahams@rcp.co.uk>
- * alpha.c (vms_valid_decl_attribute_p): Move within #if OPEN_VMS.
+ * function.c (purge_addressof_1): Replace call to
+ emit_insns_before() with emit_insn_before().
-Fri Jan 2 04:34:14 1998 Richard Henderson <rth@cygnus.com>
+Mon Oct 19 19:34:03 1998 Mike Stump <mrs@wrs.com>
- * c-decl.c (init_decl_processing): Provide proper fallback symbol
- for __builtin_memset.
- * expr.c (expand_builtin) [MEMSET]: Arg 3 type code is INTEGER_TYPE
- not INTEGER_CST. Assert arg 3 is a constant.
+ * libgcc2.c (__pure_virtual): Call __terminate instead of _exit.
- * alpha.c (mode_width_operand): Accept 64-bit modes.
- (mode_mask_operand): Likewise.
- (print_operand): Likewise for 'M' and 'U' codes.
- (alpha_expand_unaligned_load): New function.
- (alpha_expand_unaligned_store): Likewise.
- (alpha_expand_unaligned_load_words): Likewise.
- (alpha_expand_unaligned_store_words): Likewise.
- (alpha_expand_block_move): Likewise.
- (alpha_expand_block_clear): Likewise.
- * alpha.h (MOVE_RATIO): New define.
- * alpha.md (extxl, ext*h, ins*l, mskxl): Name them.
- (insql, insxh, mskxh, extv, extzv, insv, movstrqi, clrstrqi): New.
+Mon Oct 19 13:26:24 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * alpha.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE): Set to 3.
- (CONSTANT_ALIGNMENT, DATA_ALIGNMENT): Disable.
+ * jump.c (sets_cc0_p): Compile only if HAVE_cc0.
-Thu Jan 1 15:40:15 1998 Richard Henderson <rth@cygnus.com>
+Mon Oct 19 11:40:56 1998 Jeffrey A Law (law@cygnus.com)
- * configure.in: Put parenthesis around TARGET_CPU_DEFAULT's value.
- * configure: Update.
+ * gcse.c (compute_hash_table): Correctly identify hard regs which are
+ clobbered across calls.
-Thu Jan 1 10:49:12 1998 Jeffrey A Law (law@cygnus.com)
+ * loop.c (scan_loop): Be more selective about what invariants are
+ moved out of a loop.
- * emit-rtl.c (operand_subword): Correctly handle extracting a word
- from a CONST_DOUBLE for 16bit targets with !WORDS_BIG_ENDIAN.
+Mon Oct 19 10:46:58 1998 Jeff Law (law@cygnus.com)
- * mn10200.md (tstxx, cmpxx): Use "nonimmediate_operand" as predicate
- for first argument.
+ * version.c: Bump for snapshot.
-Wed Dec 31 14:42:18 1997 Ian Lance Taylor <ian@cygnus.com>
+Mon Oct 19 11:40:56 1998 Jeffrey A Law (law@cygnus.com)
- * configure.in: Set and subsitute host_exeext. Use it when creating
- the assembler and linker symlinks.
- * configure: Rebuild.
- * Makefile.in (exeext): Set to @host_exeext@.
- (build_exeext): New variable, set to @build_exeext@.
- (FLAGS_TO_PASS): Pass down build_exeext.
- (STAGESTUFF): Use build_exeext, not exeext, for gen* and bi*
- programs.
+ * libgcc2.c (eh_context_static): Do not call malloc to allocate the
+ static eh_context structure.
-Wed Dec 31 10:05:44 1997 Jeffrey A Law (law@cygnus.com)
+Mon Oct 19 10:45:40 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * mn10200.md (addsi3, subsi3): Fix thinkos.
+ * combine.c (recog_for_combine): Lose PADDED_SCRATCHES arg. All
+ callers changed.
+ (try_combine): Don't update max_scratch.
+ * flow.c (max_scratch, num_scratch): Delete variables.
+ (life_analysis_1): Don't initialize max_scratch.
+ (propagate_block): Don't update max_scratch.
+ (mark_set_1): Don't increment num_scratch.
+ * regs.h (max_scratch): Delete declaration.
-Tue Dec 30 00:04:49 1997 Richard Henderson <rth@cygnus.com>
+Mon Oct 19 10:28:15 1998 Jeffrey A Law (law@cygnus.com)
- * sparc.h (ASM_OUTPUT_MI_THUNK): Move %o7 through %g1 instead of
- save+restore. Fix pic+big_offset delay slot. Use "pic" case for
- unix always, since we want to be able to thunk to functions in a
- shared library from an application.
+ * reload1.c (reload_reg_free_before_p): Hack. Return 0 if EQUIV
+ is nonzero. This is temporary!
-Mon Dec 29 14:37:31 1997 Ian Lance Taylor <ian@cygnus.com>
+ * sched.c (update_flow_info): Handle death notes made invalid by
+ instruction splitting. Partially reverts Oct 15, 1998 patch.
+ * haifa-sched.c (update_flow_info): Likewise.
- * mips/t-ecoff (CROSS_LIBGCC1): Define to libgcc1-asm.a.
- (LIB1ASMSRC, LIB1ASMFUNCS): Define.
+Sun Oct 18 17:31:26 1998 Jeffrey A Law (law@cygnus.com)
-Mon Dec 29 14:03:38 1997 Jeffrey A Law (law@cygnus.com)
+ * function.c (uninitialized_vars_warning): Do not warn for a VAR_DECL
+ if it has a nonzero DECL_INITIAL.
- * expr.c (expand_expr): For {BITFIELD,COMPONENT,ARRAY}_REF, if the
- offset's mode is not ptr_mode, convert it.
+Sat Oct 17 23:18:08 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon Dec 29 15:58:18 1997 Michael Meissner <meissner@cygnus.com>
+ * Makefile.in (flow.o): Depend on recog.h.
- * libgcc2.c (inhibit_libc): Don't define inhibit_libc when cross
- compiling if it was already defined.
+ * cpplib.h (directive_table): Add missing initializiers.
+ (finclude): Change type of variable `bsize' to size_t.
-Sun Dec 28 00:32:16 1997 Jeffrey A Law (law@cygnus.com)
+ * cse.c (rtx_cost): Mark parameter `outer_code' with ATTRIBUTE_UNUSED.
- * flow.c (find_basic_blocks): Don't create a new basic block
- for calls in a LIBCALL block.
+ * dwarfout.h (dwarfout_label): Wrap prototype in macro RTX_CODE.
-Sun Dec 28 00:30:24 1997 David Edelsohn <edelsohn@mhpcc.edu>
+ * fix-header.c (lookup_std_proto): Cast the result of `strlen' to
+ `int' when comparing against one.
+ (cpp_file_line_for_message): Mark parameter `pfile' with
+ ATTRIBUTE_UNUSED.
+ (cpp_fatal): Mark parameter `pfile' with ATTRIBUTE_UNUSED.
- * config/fp-bit.c (L_df_to_sf): Fix typo in last change.
+ * flow.c: Include recog.h.
+ (sbitmap_copy): Cast arguments 1 & 2 of `bcopy' to (PTR).
-Sat Dec 27 22:43:12 1997 Jeffrey A Law (law@cygnus.com)
+ * function.c (thread_prologue_and_epilogue_insns): Mark parameter
+ `f' with ATTRIBUTE_UNUSED.
+ (reposition_prologue_and_epilogue_notes): Likewise.
- * cse.c (rtx_cost): Remove conflicting default case.
+ * genopinit.c (gen_insn): Cast argument of ctype functions to
+ `unsigned char'.
-Sat Dec 27 21:20:02 1997 Richard Henderson <rth@cygnus.com>
+ * haifa-sched.c: Include recog.h.
+ (blockage_range): Cast result of UNIT_BLOCKED macro to (int) when
+ comparing against one.
- * configure.in: Move default enabling of Haifa out of for loop.
- * configure: Rebuild.
+ * libgcc2.a (__throw): Revert ATTRIBUTE_UNUSED change for now.
-Thu Dec 25 01:02:54 1997 Jeffrey A Law (law@cygnus.com)
+ * mips-tfile.c (parse_end): Cast the argument of ctype function to
+ `unsigned char'.
+ (parse_ent): Likewise.
+ (parse_input): Likewise.
- * version.c: Bump for snapshot.
+ * optabs.c (init_libfuncs): Likewise.
-1997-12-25 Teemu Torma <tot@trema.com>
+ * protoize.c (find_rightmost_formals_list): Likewise.
- * Makefile.in (GTHREAD_FLAGS): New var.
- (LIBGCC2_CFLAGS): Added $(GTHREAD_FLAGS).
- (distclean): Remove gthr-default.h.
+ * recog.h (const_double_operand): Fix typo in prototype.
- * configure.in: Accept dce as a thread package.
- Check for thread.h and pthread.h.
- Link gthr-default.h to appropriate thread file and set
- gthread_flags.
- (hppa1.1-*-hpux10*): If --enable-threads, use dce threads and
- include multilib definitions from pa/t-dce-thr.
- (sparc-*-solaris2*): Enable threads by default, if thread.h or
- pthread.h is found, preferring posix threads over solaris ones.
+ * tlink.c (scan_linker_output): Cast the argument of ctype
+ function to `unsigned char'.
- * config/pa/t-dce-thr: New file.
- * config/pa/t-pa: Removed multilibs.
- * config/sparc/t-sol2: Ditto.
+ * toplev.c (check_lang_option): Cast the result of `strlen' to
+ `int' when comparing against one.
- * gthr.h: New file.
- * gthr-single.h: New file.
- * gthr-posix.h: New file.
- * gthr-solaris.h: New file.
- * gthr-dce.h: New file.
- * libgcc-thr.h: Removed.
- * objc/thr-dce.c: New file copied from thr-decosf1.c.
+Sat Oct 17 13:09:09 1998 Graham <grahams@rcp.co.uk>
- * frame.c: Include gthr.h instead of libgcc-thr.h.
- * libgcc2.c: Include gthr.h instead of libgcc-thr.h.
- (eh_context_initialize): If __gthread_once fails, use static eh
- context.
- (eh_context_free): Call __gthread_key_dtor.
+ * gcse.c (dump_cuid_table): Correct typo.
-Wed Dec 24 23:33:17 1997 Jeffrey A Law (law@cygnus.com)
+Sat Oct 17 11:02:47 1998 Nick Clifton <nickc@cygnus.com>
- * expr.h (MUST_PASS_IN_STACK): Allow target port to override.
+ * toplev.c (display_help): Prepend '-m' to target specific
+ options.
+ (check_lang_option): Ignore text after end of first word of a
+ language specific option.
+
+Sat Oct 17 02:26:03 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+ * reload1.c (reg_used_by_pseudo): New static variable.
+ (choose_reload_regs): Initialize it.
+ Use it instead of testing spill_reg_order to determine whether a
+ pseudo is live in a hard register across the current insn.
+ Fix a typo in a reference to reload_reg_rtx.
+
+ * flow.c (propagate_block): Replace code that computes and uses
+ regs_sometimes_live with simpler code that just walks the set of
+ currently live registers.
+
+ * Makefile.in (insn-extract.o): Fix dependencies.
+ * genextract.c (main): Generate includes for insn-config.h and
+ recog.h.
+ Delete generation of declarations which are now in recog.h.
+ * genrecog.c (main): Delete generation of definitions which are
+ now in recog.c.
+ * local-alloc.c (block_alloc): Use extract_insn and the variables
+ it sets up instead of looking up values by insn_code.
+ * recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
+ recog_dup_num): Define here instead of generating the definition in
+ genrecog.c.
+ (recog_n_operands, recog_n_dups, recog_n_alternatives,
+ recog_operand_mode, recog_constraints, recog_operand_address_p):
+ New variables.
+ (extract_insn): New function.
+ * recog.h (extract_insn): Declare function.
+ (which_alternative, recog_n_operands, recog_n_dups,
+ recog_n_alternatives, recog_operand_mode, recog_constraints,
+ recog_operand_address_p): Declare variables.
+ * regclass.c (n_occurrences): New static function.
+ * reload.c (n_occurrences): Delete function.
+ (find_reloads): Use extract_insn.
+ * reload.h (n_occurrences): Delete declaration.
+
+Sat Oct 17 01:17:51 1998 Jeffrey A Law (law@cygnus.com)
+
+ * reload1.c (reload_as_needed): Fix test for when to call
+ update_eliminable_offsets.
+
+Fri Oct 16 20:40:50 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ Fix consistency problems with reg_equiv_{mem,address};
+ Improve reload inheritance;
+
+ * reload.c (reload_out_reg): New variable.
+ (loc_mentioned_in_p, remove_address_replacements): New functions.
+ (remove_replacements): Deleted.
+ (push_reload): Set reload_out_reg[i].
+ When merging, also set reload_{in,out}_reg[i], and remove
+ duplicate address reloads.
+ (combine_reloads): Copy reload_out_reg[i].
+ (find_reloads): Do make_memloc substitution also when
+ reg_equiv_memory_loc[regno] and num_not_at_initial_offset
+ are both nonzero.
+ Include *recog_operand_loc in commutativity operand changes.
+ Generate optional output reloads.
+ Delete reference to n_memlocs. Don't set *recog_operand_loc before
+ processing operands. Call make_memloc in reg_equiv_address code.
+ Set *recog_operand_loc only after processing operands, and only
+ if replace is true. Return a value.
+ When changing address reload types for operands that didn't get
+ reloaded, use RELOAD_FOR_OPADDR_ADDRESS for
+ RELOAD_FOR_INPADDR_ADDRESS / RELOAD_FOR_OUTADDR_ADDRESS reloads.
+ Don't emit USEs for pseudo SUBREGs when not replacing.
+ (find_reloads_address): Do make_memloc substitution also when
+ reg_equiv_memory_loc[regno] and num_not_at_initial_offset
+ are both nonzero.
+ (find_reloads_toplev): Likewise.
+ Call make_memloc in reg_equiv_address code.
+ (debug_reload_to_stream): Add code to output reload_out_reg.
+ (make_memloc): Delete local variable i, ifdefed out code, and
+ references to memlocs and n_memlocs.
+ (memlocs, n_memlocs): Delete.
+ (push_secondary_reload): Clear reload_out_reg.
+ (find_reloads_address_1): Provide memrefloc argument to all calls
+ to find_reloads_address.
+ In AUTO_INC code, handle non-directly addressable equivalences properly.
+ * reload.h (reload_out_reg, num_not_at_initial_offset): Declare.
+ (find_reloads): Add return type.
+ (remove_address_replacements, deallocate_reload_reg): Declare.
+ * reload1.c (num_not_at_initial_offset): No longer static.
+ (delete_address_reloads, delete_address_reloads_1): Likewise.
+ (deallocate_reload_reg): New function.
+ (spill_reg_stored_to): New array.
+ (eliminate_regs): Don't substitute from reg_equiv_memory_loc.
+ (eliminate_regs_in_insn): Move assignments of previous_offset and
+ max_offset fields, and recalculation of num_not_at_initial_offset
+ into new static function:
+ (update_eliminable_offsets) .
+ (reload_as_needed): Call update_eliminable_offsets after calling
+ find_reloads.
+ Call forget_old_reloads_1 with contents of reloaded auto_inc
+ expressions if the actual addressing can't be changed to match the
+ auto_inc.
+ (choose_reload_regs): For inheritance, replace
+ reload_reg_free_before_p test with reload_reg_used_at_all test, and
+ remove stand-alone reload_reg_used_at_all test.
+ Use reload_out_reg to determine which reload regs have output reloads.
+ Treat reload_override_in more similar to inherited reloads.
+ Handle (subreg (reg... for inheritance.
+ For flag_expensive_optimizations, add an extra pass to remove
+ unnecessary reloads from known working inheritance.
+ Delete obsolete code for pseudos replaced with MEMs.
+ Handle inheritance from auto_inc expressions.
+ (emit_reload_insns): If reload_in is a MEM, set OLD to
+ reload_in_reg[j].
+ Don't reload directly from oldequiv; if it's a pseudo with a
+ stack slot, use reload_in[j].
+ Check that reload_in_reg[j] is a MEM before replacing reload_in
+ from reg_reloaded_contents.
+ Include non-spill registers in reload inheritance processing.
+ Also try to use reload_out_reg to set spill_reg_store /
+ reg_last_reload_reg.
+ In code to set new_spill_reg_store, use single_set to find out if
+ there is a single set.
+ Add code that allows to delete optional output reloads.
+ Add code to allow deletion of output reloads that use no spill reg.
+ At the end, set reload_override_in to oldequiv.
+ Also call delete_output_reload if reload_out_reg is equal to old
+ in oldequiv code.
+ Add code to call delete_output_reload for stores with no matching load.
+ Set / use spill_reg_stored_to.
+ Handle case where secondary output reload uses a temporary, but
+ actual store isn't found.
+ When looking for a store of a value not loaded in order to call
+ delete_output_reload, count_occurrences should return 0 for no
+ loads; but discount inherited input reloadill_reg_stored_to.
+ Do checks for extra uses of REG. Changed all
+ callers.
+ Use delete_address_reloads.
+ (reload): Take return value of find_reloads into account.
+ If a no-op set needs more than one reload, delete it.
+ (reload_reg_free_before_p): RELOAD_FOR_INPUT
+ can ignore RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
+ for the same operand.
+ (clear_reload_reg_in_use): Check for other reloads that keep a
+ register in use.
+ (reload_reg_free_for_value_p): Handle RELOAD_FOR_OPERAND_ADDRESS /
+ RELOAD_FOR_OPADDR_ADDR.
+ Take into account when an address address reload is only needed
+ for the address reload we are considering.
+ (count_occurrences): Use rtx_equal_p for MEMs.
+ (inc_for_reload): Return instruction that stores into RELOADREG.
+ New argument two, IN, and rtx. Changed all callers.
+ (calculate_needs_all_insns, reload_as_needed):
+ Don't clear after_call for a CLOBBER.
+ Keep track of how many hard registers need to be copied from
+ after_call, and don't clear after_call before we have seen
+ that much copies, or we see a different instruction.
+
+Fri Oct 16 10:58:23 1998 Jeffrey A Law (law@cygnus.com)
+
+ * flow.c (find_basic_blocks_1): Do not delete unreachable blocks
+ after reload has completed.
+
+Fri Oct 16 17:26:10 1998 Dave Brolley <brolley@cygnus.com>
+
+ * cpplib.c (cpp_get_token): Replace whitespace that occurs between
+ a macro name and the next token with a single blank if that whitespace
+ is in a macro buffer and the next token is not '('.
+
+Fri Oct 16 15:44:02 1998 Dave Brolley <brolley@cygnus.com>
+
+ * cccp.c (rescan): Handle multibyte characters ending in backslash.
+ (rescan): Likewise.
+ (skip_if_group): Likewise.
+ (skip_to_end_of_comment): Likewise.
+ (macarg1): Likewise.
+ (discard_comments): Likewise.
+ (change_newlines): Likewise.
+
+Fri Oct 16 15:26:24 1998 Dave Brolley <brolley@cygnus.com>
+
+ * c-lex.c (yylex): Fix unaligned access of wchar_t.
+
+Fri Oct 16 10:47:53 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/arm.h (TARGET_SWITCHES): Add --help documentation.
+ (TARGET_OPTIONS): Add --help documentation.
+
+Fri Oct 16 11:49:01 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * rtl.h (sets_cc0_p): Revert Oct 14 ATTRIBUTE_NORETURN change.
+
+Fri Oct 16 07:08:46 1998 Bruce Korb <korb@datadesign.com>
+
+ * fixinc/* Moved in from ../contrib directory in preparation
+ for integrating it into the normal build process. In particular,
+ fixinc/Makefile.in must be config-ed into the build directory
+ as fixinc/Makefile. Proposed patches to ./Makefile.in and
+ ./configure.in will be "in the mail" momentarily.
+
+Fri Oct 16 08:13:46 1998 David S. Miller <davem@pierdol.cobaltnet.com>
+
+ * cse.c (cse_basic_block): Fixup hash flushing loop so we do not
+ accidently walk into the free list. Comment how that can happen.
+ (invalidate): Fix indentation.
+
+Thu Oct 15 23:53:29 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+ Jeffrey A Law (law@cygnus.com)
-Wed Dec 24 23:12:14 1997 Jim Wilson <wilson@cygnus.com>
+ * flow.c (life_analysis_1): Do not clobber regs_ever_live after
+ reload. Never perform rescans of the insn chain after reload.
+ (propagate_block): Do not delete insn or create new autoinc addressing
+ modes after reload.
- * cse.c (max_insn_uid): New variable.
- (cse_around_loop): Use max_insn_uid.
- (cse_main): Set max_insn_uid.
+ * jump.c (jump_optimize): Unconditionally use the code that was
+ previously conditional on PRESERVE_DEATH_INFO_REGNO_P.
+ * reload1.c (reload): When reloading is finished, delete all
+ REG_DEAD and REG_UNUSED notes.
+ (emit_reload_insns): Delete all code that was conditional on
+ PRESERVE_DEATH_INFO_REGNO_P.
+ (no_longer_dead_regs): Delete variable.
+ (reload_cse_delete_death_notes): Delete function.
+ (reload_cse_no_longer_dead): Delete function.
+ (reload_cse_regs_1): Delete all code to handle deletion of death
+ notes.
+ (reload_cse_noop_set_p): Likewise.
+ (reload_cse_simplify_set): Likewise.
+ (reload_cse_simplify_operands): Likewise.
+ (reload_cse_move2add): Likewise.
+ * reorg.c (used_spill_regs): Delete declaration.
+ (max_label_num_after_reload): Delete declaration.
+ (find_dead_or_set_registers): Don't assume that spill regs are
+ dead at a CODE_LABEL.
+ * rtlanal.c (dead_or_set_regno_p): Death notes are always accurate,
+ even after reload.
+ * sched.c (sched_analyze_insn): Likewise.
+ (update_flow_info): Likewise.
+ * haifa-sched.c (sched_analyze_insn): Likewise.
+ (update_flow_info): Likewise.
+ * tm.texi (PRESERVE_DEATH_INFO_REGNO_P): Delete documentation.
+ * toplev.c (max_label_num_after_reload): Delete variable.
+ (rest_of_compilation): Don't set max_label_num_after_reload.
+ Call life_analysis after reload_cse_regs if optimizing.
+ * config/gmicro/gmicro.h: Delete comment referring to
+ PRESERVE_DEATH_INFO_REGNO_P.
+ * config/i386/i386.h: Likewise.
+ * config/m88k/m88k.h: Likewise.
+ * config/m32r/m32r.h (PRESERVE_DEATH_INFO_REGNO_P): Delete definition.
+ * config/sh/sh.h: Likewise.
- * abi64.h (LONG_MAX_SPEC): Check MIPS_ABI_DEFAULT and TARGET_DEFAULT,
- and define __LONG_MAX__ appropriately. Add support for -mabi=X,
- -mlong64, and -mgp{32,64} options.
- * mips.c (mips_abi): Change type to int.
- * mips.h (enum mips_abi_type): Delete.
- (ABI_32, ABI_N32, ABI_64, ABI_EABI): Define as constants.
- (mips_abi): Change type to int.
+Thu Oct 15 19:48:41 1998 David Edelsohn <edelsohn@gnu.org>
-Wed Dec 24 22:38:34 1997 John Carr <jfc@mit.edu>
+ * loop.c (strength_reduce): Restore marking bct_p as
+ ATTRIBUTE_UNUSED.
+ * rs6000.c (optimization_options): Change #ifdef HAIFA to
+ HAVE_decrement_and_branch_on_count.
+ (small_data_operand): Remove TARGET_ELF condition for marking
+ parameters ATTRIBUTE_UNUSED.
- * flags.h, toplev.c, calls.c, alias.c: Remove flag_alias_check;
- optimization is now always enabled.
+Thu Oct 15 11:45:51 1998 Robert Lipe <robertl@dgii.com>
- * calls.c (expand_call): Recognize C++ operator new as malloc-like
- function.
+ * config/i386/sco5.h (MAX_OFILE_ALIGNMENT): Define.
+ (SELECT_SECTION): Resync with svr4.h.
- * alias.c (memrefs_conflict_p): Eliminate tests now done by
- base_alias_check.
- (*_dependence): Call canon_rtx before base_alias_check.
- (init_alias_once): New function to precompute set of registers which
- can hold Pmode function arguments.
-
- * rtl.h: Declare init_alias_once.
-
- * toplev.c (compile_file): Call init_alias_once.
-
-Wed Dec 24 22:34:55 1997 Jeffrey A Law (law@cygnus.com)
-
- * tree.c (restore_tree_status): Do not dereference a null pointer.
-
-Tue Dec 23 12:56:46 1997 Paul Eggert <eggert@twinsun.com>:
-
- * genattrtab.c (main): Check HAVE_{G,S}ETRLIMIT in addition to
- RLIMIT_STACK. This maintains consistency with the recent, similar
- patch to cccp.c and toplev.c.
-
-Tue Dec 23 05:17:28 1997 Richard Henderson <rth@cygnus.com>
-
- * genattrtab.c (expand_units): For large nr opclasses, expand
- function_units_used with ORX to prevent blowups. Tag with FFS.
- (num_unit_opclasses): New variable.
- (gen_unit): Update it.
- (enum operator): Add ORX_OP.
- (operate_exp): Treat ORX as or, except don't expand across an if.
- Reuse number rtx's after operating on them.
- (check_attr_value): Accept IOR, AND, & FFS.
- (write_test_expr): Transmute `in_comparison' to `flags'. Allow
- for attribute value caching. Handle CONST_STRING, IF_THEN_ELSE.
- (write_expr_attr_cache, write_toplevel_expr): New functions.
- (write_attr_get): Handle FFS-tagged expressions.
- (make_canonical): Don't expand const attributes.
- (convert_const_symbol_ref): Dike out.
- (evaluate_eq_attr): Handle SYMBOL_REF.
- (main): Don't emit get_attr_foo for const attributes.
-
- * alpha.c (override_options): Reinstate PROCESSOR_EV6.
- (alpha_adjust_cost): Add EV6 tuning; streamline EV5 tests.
- * alpha.h (REGISTER_MOVE_COST): Increase ftoi/itof cost slightly.
- * alpha.md: Redo all of the scheduling, adding EV6 support, and
- combining function units where possible.
- (attr "type"): Split loads, stores, cmov into int/fp. Combine
- multiplies and divides. Add EV6 sqrt, ftoi, itof.
- (attr "opsize"): New attribute.
- (sqrtsf2-1, sqrtdf2-1): Provide proper TP_INSN patterns.
- (movsf2-[12], movdf2-[12]): Provide CIX varients; don't allow CIX
- to control register allocation.
- (movsi2-1, movdi2-1): Likewise.
-
-Tue Dec 23 03:53:21 1997 Richard Henderson <rth@cygnus.com>
-
- * alpha.h (CPP_PREDEFINES, LIB_SPEC, LINK_SPEC, STARTFILE_SPEC,
- MD_STARTFILE_PREFIX, ASM_FILE_START, ASM_SPEC, ASM_FINAL_SPEC):
- Move OSF/1 specific defines out.
- * alpha/elf.h (TARGET_VERSION, CPP_PREDEFINES, DEFAULT_VTABLE_THUNKS):
- Move Linux specific defines out.
- (LINK_SPEC): Genericize.
- (ASM_FILE_START): Emit .arch if using more than the base insn set.
- (ASM_OUTPUT_SOURCE_LINE): Remove; identical to alpha.h version.
- (SDB_DEBUGGING_INFO): Remove; gas can't handle it.
- (HANDLE_SYSV_PRAGMA): Define.
- * alpha/osf.h: New file.
- * alpha/linux.h: Split. Retain file-format independant defines.
- Import Linux bits from elf.h.
- (CPP_PREDEFINES): Take a file-format specific SUB_CPP_PREDEFINES
- (FUNCTION_PROFILER): _mcount takes its address in $28.
- (MD_EXEC_PREFIX, MD_STARTFILE_PREFIX): Remove undef.
- * alpha/linux-ecoff.h: New file.
- * alpha/linux-elf.h: New file.
- * alpha/vms.h (LIB_SPEC, LINK_SPEC): Copy from osf.h.
- * alpha/win-nt.h (TARGET_DEFAULT): Define.
- * configure.in (alpha*-*-osf*, alpha*-*-linux*) [tm_file]:
- Add new headers as appropriate.
-
- * configure.in (alpha*): Enable Haifa by default.
- (*-*-winnt3*): Change to winnt*, since we're not v3 specific.
- * configure: Rebuild.
+Thu Oct 15 12:42:13 1998 David Edelsohn <edelsohn@gnu.org>
-Tue Dec 23 03:14:54 1997 Richard Henderson <rth@cygnus.com>
+ * loop.c (strength_reduce): Undo Oct 14 change marking bct_p
+ ATTRIBUTE_UNUSED.
- * Makefile.in (clean): Remove the stages with their objects here ...
- (distclean): ... instead of here.
+Thu Oct 15 00:57:55 1998 Robert Lipe <robertl@dgii.com>
-Mon Dec 22 11:24:01 1997 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * c-pragma.c (handle_pragma_token): Test for null tree before
+ dereferencing TREE_CODE.
- * cse.c (rtx_cost): Add default case in enumeration switch.
- * fix-header.c (recognized_macro): Likewise.
- (recognized_extern): Likewise.
- (write_rbrac): Likewise.
- * objc/objc-act.c (encode_aggregate): Likewise.
- (gen_declarator): Likewise.
- (gen_declspecs): Likewise.
+Thu Oct 15 17:36:48 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Mon Dec 22 09:58:51 1997 Jeffrey A Law (law@cygnus.com)
+ * config/c4x/c4x.c: Convert to use GEN_INT.
+ (c4x_parallel_process): Rework to handle new repeat loop structure.
- * haifa-sched.c (create_reg_dead_note): Detect and handle another
- case where we kill more regs after sched than were killed before
- sched.
- * sched.c (create_reg_dead_note): Similarly.
+ * config/c4x/c4x.md: Convert to use GEN_INT.
+ (rptb_end): Convert to use GE test. Replace uses with clobbers.
+ (decrement_and_branch_on_count): Likewise.
-Mon Dec 22 09:18:37 1997 Jeffrey A Law (law@cygnus.com)
+ * config/c4x/c4x.h (REPEAT_BLOCK_PROCESS): Deleted hook now that
+ loop.c has the desired functionality.
+ (rc_reg_operand): New prototype.
- * c-pragma.c: Include flags.h.
+ * config/c4x/t-c4x: Can now build all front ends.
-Sun Dec 21 22:10:59 1997 Mumit Khan <khan@xraylith.wisc.edu>
+Wed Oct 14 23:27:08 1998 Didier FORT (didier.fort@fedex.com)
- * i386/cygwin32.h (NO_IMPLICIT_EXTERN_C): Don't assume anything
- about system headers.
- (LIB_SPEC): Add -ladvapi32 -lshell32 to be consistent with mingw32
- and also to resolve symbols in prefix.c.
+ * fixincludes: Fix up rpc/{clnt,svr,xdr}.h for SunOS.
- * i386/xm-cygwin32.h (HAVE_BCOPY): Define. This avoids a conflict
- between gansidecl.h and newlib's _ansi.h when building libgcc2.a,
- when the definitions in auto-config.h is not visible.
- (HAVE_BZERO): Likewise.
- (HAVE_BCMP): Likewise.
- (HAVE_RINDEX): Likewise.
- (HAVE_INDEX): Likewise.
+Wed Oct 14 22:13:28 1998 Joel Sherrill (joel@OARcorp.com)
-Sun Dec 21 21:54:22 1997 Jeffrey A Law (law@cygnus.com)
+ * Makefile.in (stmp-fixinc): Do not install assert.h if not desired.
+ * config/t-rtems: Do not install assert.h -- use newlib's.
- * pa.c (emit_move_sequence): Handle a function label source
- operand.
+Wed Oct 14 21:57:08 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Sun Dec 21 16:13:55 1997 Nick Clifton <nickc@cygnus.com
+ * combine.c (combine_instructions): When finished, call init_recog.
+ * regmove.c (optimize_reg_copy_3): Reject volatile MEMs.
- * c-pragma.c (handle_pragma_token): Generate warning messages
- about unknown pragmas if warn_unknown_pragmas is set.
+Wed Oct 14 16:10:22 1998 Per Bothner <bothner@cygnus.com>
- * c-decl.c (c_decode_option): Parse -Wunknown-pragmas command
- line option to set variable: warn_unknown_pragmas.
+ * toplev.c: If flag_syntax_only, don't open or write assembler file.
-Sun Dec 21 15:51:10 1997 Manfred Hollstein <manfred@lts.sel.alcatel.de>
+Wed Oct 14 13:26:05 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * m68k/mot3300.h (ASM_BYTE_OP): Don't include '\t' in the
- definition.
- (ASM_OUTPUT_ASCII): Prefix ASM_BYTE_OP by one single '\t'.
-
-Sun Dec 21 13:58:39 1997 Jeffrey A Law (law@cygnus.com)
-
- * Makefile.in (FPBIT_FUNCS, DPBIT_FUNCS): Define.
- (libgcc2.a): Depend on $(DPBIT) and $(FPBIT). Add rules to
- generate more fine grained floating point emulation libraries.
- * config/fp-bit.c: Add protecting #ifdef to all functions so
- that they can be compiled separately. If !FINE_GRAINED_LIBRARIES,
- then compile all suitable functions.
- (pack_d, unpack_d, fpcmp_parts): Add declarations, define with two
- underscores to avoid namespace pollution.
- * t-mn10200 (LIB2FUNCS_EXTRA): Remove fp-bit.c
- (FPBIT): Define.
- * t-mn10300 (LIB2FUNCS_EXTRA): Remove fp-bit.c and dp-bit.c
- (FPBIT): Define.
- (DPBIT): Define.
-
-Sat Dec 20 11:26:47 1997 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- Jeff Law <law@cygnus.com>
+ * cppalloc.c (memory_full): Mark function prototype with
+ ATTRIBUTE_NORETURN.
- * bitmap.c (bitmap_clear): Ensure `inline' is at the beginning
- of the declaration.
- * c-decl.c (finish_decl): Use parentheses around && within ||.
- * rtl.c: Include stdlib.h.
- (read_skip_spaces): Add parentheses around assignments used as
- truth values.
- (read_rtx): Initialize list_rtx.
- * cppexp.c (parse_number): Use || when operands are truth values.
- * alias.c (find_base_value): Add default case.
- (memrefs_conflict): Likewise.
- * combine.c (sets_function_arg_p): Likewise.
- * genemit.c (gen_exp): Likewise.
- * local-alloc.c (contains_replace_regs): Likewise.
- * rtlanal.c (jmp_uses_reg_or_mem): Likewise.
- * fold-const.c (fold_convert): Use "&&" for truth values.
- (fold): Add default case.
- * sdbout.c (sdbout_field_types): Fix typo in declaration.
- (sdbout_one_type): Add default case.
- * alpha.c (alpha_sa_mask): Prototype only if OPEN_VMS.
- (some_operand): Add default case.
- (input_operand): Likewise.
- (signed_comparison_operator): Likewise.
- (divmod_operator): Likewise.
- (alpha_set_memflags_1): Likewise.
- * reload1.c (reload_cse_simplify_operands): Ensure function
- always returns a value.
- * scan-decls.c (scan_decls): Likewise.
- * c-lex.c (skip_white_space): Fix typo in declaraion.
- * c-typeck.c (comp_target_types): Add parentheses around assignment
- used as truth value.
- (print_spelling): Likewise.
- (constructor_implicit, constructor_result): Remove unused variables.
- * collect2.c (scan_library): Protect prototype with
- #ifdef SCAN_LIBRARIES.
- * emit-rtl.c (find_line_note): Fix typo in declaration.
- * final.c (asm_insn_count): Protect prototype with
- #ifdef HAVE_ATTR_length.
- * flow.c (find_auto_inc): Protect prototype with #ifdef AUTO_INC_DEC.
- (try_pre_increment_1, try_pre_increment): Likewise.
- * regclass.c (auto_inc_dec_reg_p): Protect prototype with
- #ifdef FORBIDDEN_INC_DEC_CLASSES. Make return type explicit.
- * gcov-io.h (__store_long, __write_long, __read_long): Fix
- unsigned/signed comparisons.
- * gcov.c (read_files): Remove unused "first_type" variable.
- (scan _for_source_files): Initialize s_ptr.
- (function_summary): Eliminate "%lf" formatting, use %ld for
- longs.
- (output_data): Initialize branch_probs and last_line_num.
- Eliminate "%lf" formatting, use "%ld" for longs.
-
-Fri Dec 19 17:31:11 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * mips16.S: New file.
-
- * libgcc2.c (varargs): Handle mips16.
-
- * expr.c (do_tablejump): Let CASE_VECTOR_PC_RELATIVE be an
- expression.
- * stmt.c (expand_end_case): Likewise.
- * alpha.h (CASE_VECTOR_PC_RELATIVE): Update.
- * fx80.h, gmicro.h, m68k.h, m88k.h, ns32k.h: Likewise.
- * rs6000.h, sh.h, tahoe.h, v850.h, vax.h: Likewise.
-
-Tue Dec 16 15:14:09 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-
- * objc/Make-lang.in: Create runtime-info.h and libobjc_entry.o in
- the build directory.
- (libobjc.a): Update dependency list.
- (libobjc.dll): Likewise. Use libobjc_entry.o from the build
- directory.
- (objc/sendmsg.o): Add -Iobjc to find runtime-info.h.
- (objc.mostlyclean): Remove runtime-info.h.
+ * demangle.h (collect_exit): Likewise.
-Fri Dec 19 00:19:42 1997 Richard Henderson <rth@cygnus.com>
+ * fix-header.c (v_fatal, fatal): Likewise.
- * tree.c (build_range_type): Allow creation of ranges with no maximum.
- * dbxout.c (dbxout_range_type): Handle missing TYPE_MAX_VALUE.
- * dwarf2out.c (add_subscript_info): Likewise.
- * dwarfout.c (subscript_data_attribute, byte_size_attribute): Likewise.
- * sdbout.c (plain_type_1): Likewise.
- * stmt.c (pushcase_range, all_cases_count, node_has_high_bound):
- Likewise.
- * fold-const.c (int_const_binop, fold_convert, make_range, fold):
+ * gcc.c (pfatal_with_name, pfatal_pexecute, fatal, fancy_abort):
Likewise.
-Thu Dec 18 17:05:10 1997 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * gcov.c (print_usage): Likewise.
- * mips.c (fatal): Remove declaration.
+ * genattr.c (fatal, fancy_abort): Likewise.
-1997-12-18 Mark Mitchell <mmitchell@usa.net>
+ * genattrtab.c (fatal, fancy_abort): Likewise.
- * integrate.c (get_label_from_map): New function.
- (expand_inline_function): Use it. Initialize the label_map to
- NULL_RTX instead of gen_label_rtx.
- (copy_rtx_and_substitute): Use get_label_from_map.
- * integrate.h (get_label_from_map): New function.
- (set_label_from_map): New macro.
- * unroll.c (unroll_loop): Use them.
- (copy_loop_body): Ditto.
+ * gencodes.c (fatal, fancy_abort): Likewise.
-Thu Dec 18 19:19:57 1997 Ian Lance Taylor <ian@cygnus.com>
+ * genconfig.c (fatal, fancy_abort): Likewise.
- * mips/mips.h (INIT_SUBTARGET_OPTABS): Define if not defined.
- (INIT_TARGET_OPTABS): Define.
- * mips/ecoff.h: Include gofast.h before mips.h.
- (INIT_SUBTARGET_OPTABS): Define instead of INIT_TARGET_OPTABS.
- * mips/elf64.h: Likewise.
- * mips/elf.h (ASM_OUTPUT_SECTION_NAME): Define.
+ * genemit.c (fatal, fancy_abort): Likewise.
-Thu Dec 18 14:51:12 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * genextract.c (fatal, fancy_abort): Likewise.
- * except.c: Remove register_exception_table{,_p}.
+ * genflags.c (fatal, fancy_abort): Likewise.
-Thu Dec 18 14:57:29 1997 Gavin Koch <gavin@cygnus.com>
+ * genopinit.c (fatal, fancy_abort): Likewise.
- * unroll.c (calculate_giv_inc): Handle constant increment found in
- a MEM with an appropriate REG_EQUAL note.
+ * genoutput.c (fatal, fancy_abort): Likewise.
- * calls.c (expand_call): Implement LOAD_ARGS_REVERSED.
+ * genpeep.c (fatal, fancy_abort): Likewise.
- * dwarf2out.c (dwarf2out_frame_debug): Handle adjustments of the
- frame pointer in the prologue.
+ * genrecog.c (fatal, fancy_abort): Likewise.
-Thu Dec 18 00:19:38 1997 Robert Lipe <robertl@dgii.com>
+ * libgcc2.c (__eprintf, __default_terminate, __sjthrow,
+ __sjpopnthrow, __throw): Likewise.
- * i386/x-sco5 (CLIB) Deleted. (ALLOCA) Added.
- * i386/xm-sco5.h (USE_C_ALLOCA) Added.
+ * objc/objc-act.c (objc_fatal): Likewise.
-Tue Dec 16 18:51:00 1997 Bill Moyer <billm@cygnus.com>
+ * protoize.c (usage, aux_info_corrupted,
+ declare_source_confusing): Likewise.
- * config/m68k/m68k.c (output_function_prologue): Typecast
- dwarf2out_cfi_label to (char *).
- * config/m68k/m68kemb.h (STARTFILE_SPEC): Redefined to "".
+ * rtl.c (dump_and_abort): Likewise.
-Wed Dec 17 15:06:04 1997 Richard Henderson <rth@cygnus.com>
+ * rtl.h (sets_cc0_p): Likewise.
- * sparc.md (jump): Don't use the annul bit around an empty loop.
- Patch from Kevin.Kelly@East.Sun.COM.
+ * toplev.c (float_signal, pipe_closed): Likewise.
-Wed Dec 17 00:51:36 1997 Stan Cox (scox@cygnus.com)
+1998-10-14 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * jump.c: (jump_optimize): Don't use the return register as a
- source1 of a conditional move.
+ * dwarf2out.c (expand_builtin_dwarf_reg_size): Look at all ranges
+ when generating the decision tree for the general case.
-Tue Dec 16 23:45:40 1997 Richard Henderson <rth@cygnus.com>
+ * config/m68k/m68k.h (HARD_REGNO_MODE_OK): Don't accept modes
+ wider that 12 bytes in fpu regs or wider than 8 byte in fpa regs.
- * sparc.c (DF_MODES): Or the mask not the bit number.
- (function_arg) [ARCH64]: Send unprototyped arg to fp reg first.
+Wed Oct 14 11:14:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Wed Dec 17 00:13:48 1997 Christian Iseli <Christian.Iseli@lslsun.epfl.ch>
+ * Makefile.in (sched.o): Depend on recog.h.
- * combine.c (force_to_mode): return immediately if operand is a CLOBBER.
+ * alias.c (REG_BASE_VALUE): Cast the result of REGNO() macro to
+ (unsigned) when comparing against one.
+ (find_base_value): Likewise.
+ (record_base_value): Cast variable `regno' to (unsigned) when
+ comparing against one. Cast the result of REGNO() macro to
+ (unsigned) when comparing against one.
+ (memrefs_conflict_p): Change type of variables `r_x' and `r_y' to
+ unsigned.
+ (init_alias_analysis): Add unsigned variable `ui'. Use it as loop
+ variable where an unsigned index is needed.
-Tue Dec 16 23:44:54 1997 Manfred Hollstein <manfred@s-direktnet.de>
+ * caller-save.c (init_caller_save): Cast `-1' to (enum insn_code)
+ before comparing against one.
- * fixincludes (size_t): Add support for Motorola's stdlib.h
- which fails to provide a definition for size_t.
- (fabs/hypot): Provide a prototype for fabs on m88k-motorola-sysv3.
- (strlen,strspn,strcspn return value): Handle different layout on sysV88.
- (hypot): Provide a fake for hypot for m88k-motorola-sysv3.
+ * collect2.c: Add prototypes for functions `error', `fatal' and
+ `fatal_perror'. Make these functions take variable arguments
+ instead of faking it with a fixed number of args.
+ (write_c_file_stat): Cast the argument of ctype macro to (unsigned
+ char).
- * m68k/xm-mot3300.h (ADD_MISSING_POSIX, ADD_MISSING_XOPEN): Define to
- prevent unresolved externals in libio.
- * m88k/xm-sysv3.h (ADD_MISSING_POSIX, ADD_MISSING_XOPEN): Likewise.
+ * combine.c (can_combine_p): Mark parameter `pred' with
+ ATTRIBUTE_UNUSED.
+ (find_split_point): Cast variable `src' to (unsigned
+ HOST_WIDE_INT) when comparing against one.
+ (simplify_rtx): Cast 1 to (unsigned HOST_WIDE_INT) in shift.
+ (simplify_logical): Likewise.
+ (force_to_mode): Cast result of INTVAL() macro to (unsigned
+ HOST_WIDE_INT) when comparing against one. Cast 1 to (unsigned
+ HOST_WIDE_INT) in shift.
+ (simplify_and_const_int): Cast result of INTVAL() macro to
+ `unsigned HOST_WIDE_INT' when comparing against one.
+ (merge_outer_ops): Cast variable const0 to `unsigned
+ HOST_WIDE_INT' when comparing against the result of
+ GET_MODE_MASK() macro.
+ (simplify_comparison): Likewise for variable `c0'. Cast variable
+ `const_op' to `unsigned HOST_WIDE_INT' when comparing against
+ one. Cast `1' to `unsigned HOST_WIDE_INT' in shift. Cast the
+ result of `GET_MODE_MASK()/2' to `HOST_WIDE_INT' when comparing
+ against one. Cast `1' to `unsigned HOST_WIDE_INT' in shift. Cast
+ result of INTVAL() macro to `unsigned HOST_WIDE_INT' when
+ comparing against one.
+ (distribute_notes): Wrap variable `cc0_setter' in macro `HAVE_cc0'.
+
+ config/mips/mips.c (gen_int_relational): Cast result of INTVAL()
+ macro to `unsigned HOST_WIDE_INT' when comparing against one.
+ (output_block_move): Cast `sizeof' expression to (int) when
+ comparing against one.
+ (function_arg): Cast BITS_PER_WORD to `unsigned' when comparing
+ against one.
+ (save_restore_insns): Cast `base_offset' to `long' to match format
+ specifier in fprintf.
+
+ * config/mips/mips.h (Pmode): Cast the result of `Pmode' macro
+ to `enum machine_mode'.
+
+ * flow.c (life_analysis_1): Remove unused variable `insn'.
+
+ * gcc.c (translate_options): Move variables `j' and `k' into the
+ scope in which they are used. Change their types to `size_t'.
+ (set_spec): Cast the argument of ctype macro to `unsigned char'.
+ (read_specs): Likewise.
+ (process_command): Cast `sizeof' to (int) when comparing against one.
+ (do_spec_1): Cast the argument of ctype macro to `unsigned char'.
+ (handle_braces): Cast both sides of `==' expression to `long' to
+ ensure sign matching.
+ (main): Cast variable `i' to `int' when comparing against one.
+
+ * gcov-io.h (__fetch_long): Change type of parameter `bytes' from
+ int to size_t. Cast variable `i' to size_t when comparing against
+ one.
+
+ * genattrtab.c (convert_set_attr_alternative): Remove unused
+ parameter `insn_code'. All callers changed.
+ (convert_set_attr): Likewise.
+
+ * genrecog.c (add_to_sequence): Cast result of XVECLEN() macro to
+ size_t when comparing against one. Likewise for variable `len'.
+
+ * global.c (global_alloc): Cast variable `max_regno' to size_t
+ when comparing against one. Likewise for variable `max_allocno'.
+
+ * jump.c (sets_cc0_p): Mark parameter `x' with ATTRIBUTE_UNUSED.
+
+ * local-alloc.c (validate_equiv_mem_from_store): Mark parameter
+ `set' with ATTRIBUTE_UNUSED.
+ (find_free_reg): Cast `sizeof' expression to (int) when comparing
+ against one.
+
+ * loop.c (count_loop_regs_set): Remove unused variable `dest'.
+ (strength_reduce): Mark parameter `bct_p' with ATTRIBUTE_UNUSED.
+ (get_condition): Cast variable `const_val' to `unsigned
+ HOST_WIDE_INT' when comparing against one. Cast unsigned
+ expression to HOST_WIDE_INT when comparing against one.
+ (insert_loop_mem): Mark parameter `data' with ATTRIBUTE_UNUSED.
+ (load_mems_and_recount_loop_regs_set): Cast variable `nregs' to
+ `unsigned' when comparing against one.
+
+ * protoize.c (is_id_char): Change type of parameter `ch' to
+ unsigned char.
+ (munge_compile_params): Cast argument of ctype macro to (const
+ unsigned char).
+ (process_aux_info_file): Cast variable `aux_info_size' to int when
+ comparing against one.
+ (forward_to_next_token_char): Cast argument of ctype macro to
+ `const unsigned char'.
+ (edit_formals_lists): Likewise.
+ (find_rightmost_formals_list): Likewise.
+ (add_local_decl): Likewise.
+ (add_global_decls): Likewise.
+ (edit_fn_definition): Likewise.
+ (do_cleaning): Likewise.
+ (scan_for_missed_items): Likewise.
+ (edit_file): Cast variable `orig_size' to (int) when comparing
+ against one.
+ (main): Cast argument of ctype macro to `const unsigned char'.
+
+ * recog.c (const_int_operand): Mark parameter `mode' with
+ ATTRIBUTE_UNUSED.
-Tue Dec 16 23:25:45 1997 H.J. Lu (hjl@gnu.org)
+ * regclass.c (record_reg_classes): Change type of variable `c' to
+ `unsigned char'. Cast `char' array index to `unsigned char'.
+
+ * reload.c (push_secondary_reload): Cast argument to
+ REG_CLASS_FROM_LETTER() macro to `unsigned char'.
+
+ * reload1.c (calculate_needs): Cast `char' array index to
+ `unsigned char'.
+ (set_label_offsets): Change type of variable `i' to unsigned int.
+ Cast result of XVECLEN() macro to unsigned when comparing against
+ one.
+ (mark_not_eliminable): Change type of variable `i' to unsigned.
+ (order_regs_for_reload): Likewise. Cast `max_regno' to unsigned
+ when comparing against one.
+ (reload_as_needed): Cast macro NUM_ELIMINABLE_REGS to (int) when
+ comparing against one.
+ (choose_reload_regs): Hide unused label `fail'.
+ (reload_cse_simplify_operands): Cast `char' array index to
+ `unsigned char'.
+ (reload_combine_note_store): Mark parameter `set' with
+ ATTRIBUTE_UNUSED. Cast UNITS_PER_WORD to unsigned when comparing
+ against one.
+ (reload_cse_move2add): Remove unused variable `src2'.
+
+ * sched.c: Include recog.h.
+ (sched_note_set): Remove unused parameter `b'. All callers
+ changed.
+ (split_hard_reg_notes): Likewise for parameter `orig_insn'.
+ (blockage_range): Cast result of UNIT_BLOCKED() macro to (int)
+ when comparing against one.
- * config/sparc/linux64.h (LIBGCC_SPEC): Removed.
- (CPP_SUBTARGET_SPEC): Add %{pthread:-D_REENTRANT}.
- (LIB_SPEC): Updated for glibc 2.
+ * stupid.c (stupid_find_reg): Mark parameter `changes_size' with
+ ATTRIBUTE_UNUSED. Cast `sizeof' expression to (int) when
+ comparing against one.
-Tue Dec 16 20:11:36 1997 Jeffrey A Law (law@cygnus.com)
+ * unroll.c (precondition_loop_p): Remove unused parameter
+ `loop_end'. All callers changed.
- * ginclude/stdarg.h: Undo BeOS changes, they break hpux.
- * ginclude/varargs.h: Likewise.
+Tue Oct 13 22:12:11 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
-Tue Dec 16 00:32:01 1997 Jeffrey A Law (law@cygnus.com)
+ * reload1.c (maybe_fix_stack_asms): New static function.
+ (reload): Call it.
- * version.c: Bump for snapshot.
+ * reload.h (compute_use_by_pseudos): Declare.
-Tue Dec 16 00:14:29 1997 H.J. Lu (hjl@gnu.org)
+ * reload1.c (spilled_pseudos, insns_need_reload): New variables.
+ (something_needs_reloads): Delete variable.
+ (finish_spills): New function.
+ (compute_use_by_pseudos): New function.
- * frame.h (__register_frame, __register_frame_table,
- __deregister_frame): New.
- * frame.c (__register_frame, __register_frame_table,
- __deregister_frame): New.
- * frame.c (__deregister_frame_info): Return void *.
- * frame.h (__deregister_frame_info): Ditto.
- * collect2.c (__deregister_frame_info): Ditto.
+ (delete_caller_save_insns): Lose argument FIRST. All callers changed.
+ Use the reload_insn_chain instead of walking the rtl directly.
-Mon Dec 15 18:40:08 1997 Richard Henderson <rth@cygnus.com>
+ (reload): Allocate and free spilled_pseudos.
+ Ensure that all calls of spill_hard_reg are followed by a call to
+ finish_spills.
+ Use the insns_need_reload list instead of something_needs_reloads
+ to find out if reload_as_needed must be called.
+ Clear unused_insn_chains at the end.
- * expmed.c (expand_shift): If SHIFT_COUNT_TRUNCATED, drop a SUBREG.
+ (calculate_needs_all_insns): Lose FIRST parameter. All callers
+ changed.
+ Delete code to keep track of current basic block.
+ Walk reload_insn_chain instead of the rtl structure. Build the
+ insns_need_reload chain.
+ Remember which insns need reloading/elimination by setting the
+ appropriate fields in struct insn_chain, not by putting modes on the
+ insn.
+
+ (calculate_needs): Lose THIS_BLOCK arg. Accept arg CHAIN instead of
+ arg INSN. All callers changed.
+ Delete declaration of struct needs.
+ Don't set something_needs_reloads.
+ Record insn needs in the CHAIN argument.
+
+ (spill_hard_reg): Record the affected pseudos in spilled_pseudos.
+
+ (reload_as_needed): Lose FIRST arg. All callers changed.
+ Walk the reload_insn_chain instead of the rtx structure.
+ Delete code to keep track of current basic block.
+ Rename one of the NEXT variables to OLD_NEXT.
+
+ (allocate_reload_reg): Accept arg CHAIN instead of arg INSN. All
+ callers changed.
+ (choose_reload_regs): Likewise.
-Mon Dec 15 18:31:43 1997 Richard Henderson <rth@cygnus.com>
+ (emit_reload_insns): Replace INSN and BB args with arg CHAIN. All
+ callers changed.
- * alpha.c (alpha_cpu_name): New variable.
- (alpha_mlat_string): Likewise.
- (alpha_memory_latency): Likewise.
- (override_options): Handle -mmemory-latency.
- (alpha_adjust_cost): Adjust load cost for latency.
- * alpha.h (TARGET_OPTIONS): Add meory-latency.
- (REGISTER_MOVE_COST): Define in terms of memory_latency. Take
- TARGET_CIX into account.
- (MEMORY_MOVE_COST): Define in terms of memory_latency.
- * invoke.texi (DEC Alpha Options): Document -mmemory-latency.
+ * caller-save.c (MOVE_MAX_WORDS): New macro. Use it throughout
+ instead of (MOVE_MAX / UNITS_PER_WORD) computation.
+ (hard_regs_live, hard_regs_need_restore): Delete variables.
+ (n_regs_saved): Now static.
+ (referenced_regs, this_insn_sets): New variables.
- * alpha.h (ASM_COMMENT_START): New macro.
+ (setup_save_areas): Restructure the code a bit.
-Mon Dec 15 17:48:05 1997 Richard Henderson <rth@cygnus.com>
+ (restore_referenced_regs): Delete function.
+ (mark_referenced_regs): New function, similar to the old
+ restore_referenced_regs, but mark registers in referenced_regs.
- * reload.h, reload1.c (eliminate_regs), caller-save.c, dbxout.c,
- dwarfout.c, dwarf2out.c, reload.c, sdbout.c: Revert March 15 change.
+ (clear_reg_live): Delete function.
+ (mark_set_regs): Renamed from set_reg_live. All callers changed.
+ Only mark registers in this_insn_sets.
- * reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the
- SUBREG_REG if the word count is unchanged.
- * reload1.c (eliminate_regs) [case SET]: If W_R_O, preserve
- subregs of identical word size for push_reload.
+ (save_call_clobbered_regs): Rework this function to walk the
+ reload_insn_chain instead of using the list of instructions directly.
+ Delete code to keep track of register lives, compute live regs on the
+ fly from information in the chain.
+ Instead of calling restore_referenced_regs, use mark_referenced_regs,
+ then walk the set it computes and call insert_restore as appropriate.
-Mon Dec 15 Mark Mitchell <mmitchell@usa.net> 11:41:32 1997
+ (insert_restore): Lose INSN and BLOCK args. Add CHAIN arg. All
+ callers changed.
+ Restructure the code a bit. Test hard_regs_saved instead of
+ hard_regs_need_restore.
+ (insert_save): Lose INSN and BLOCK args. Add CHAIN and TO_SAVE
+ args. All callers changed.
+ Restructure the code a bit. Use TO_SAVE to determine which regs to
+ save instead of more complicated test.
+ (insert_one_arg): Lose INSN and BLOCK args. Add CHAIN arg. All
+ callers changed.
+ Create a new insn_chain structure for the new insn and place it
+ into the chain.
- * toplev.c (rest_of_compilation): Don't call save_for_inline_copy
- if all we're doing is dealing with -Wreturn-type.
+ * rtl.texi: Update documentation to reflect that reload no longer
+ puts modes on the insns.
-Mon Dec 15 09:44:39 1997 Richard Henderson <rth@cygnus.com>
+1998-10-14 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
- * alpha.md (zero_extendqihi2, zero_extendqisi2, zero_extendqidi2):
- Use and 255 instead of zapnot 1, since it schedules better.
+ * function.c (purge_addressof_1): Force the first argument of a
+ CALL insn to memory.
-Mon Dec 15 08:48:24 1997 Jeffrey A Law (law@cygnus.com)
+Wed Oct 14 00:38:40 1998 Jeffrey A Law (law@cygnus.com)
- * stmt.c (expand_asm_operands): If an ASM has no outputs, then treat
- it as volatile.
+ * rtl.h: Delete duplicate prototypes. Add some missing
+ prototypes.
+ * rtlanal.c (for_each_rtx): Formatting tweak.
-Mon Dec 15 00:04:48 1997 Jeffrey A Law (law@cygnus.com)
+1998-10-13 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
- * haifa-sched.c (remove_dependencies): Set RTX_INTEGRATED_P on
- dependency we delete. Properly update prev for multiple consecutive
- deletions.
- (priority): Skip deleted dependence.
+ * real.c (emdnorm and etoasc): Disable round to even for c4x target
+ to be compatible with TI compiler.
-Fri Dec 12 18:54:23 1997 Per Bothner <bothner@cygnus.com>
+ * Makefile.in (USER_H): Add va-c4x.h to definition.
- * expr.c (expand_builtin): Support BUILT_IN_FMOD - just call fmod.
+Tue Oct 13 23:03:37 1998 Richard Henderson <rth@cygnus.com>
-Fri Dec 12 01:19:48 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * function.c (purge_addressof_1): Fix typo in inequality: do
+ bitfield optimization for equal mode sizes.
+ * expmed.c (store_bit_field): Don't take subregs of subregs in
+ the movstrict case. Tidy a potential problem in the multi-word case.
+ (extract_bit_field): Likewise.
- * flow.c (flow_analysis): Be consistent with find_basic_blocks in
- determining when a new basic block starts.
+Tue Oct 13 22:12:11 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * alpha/osf2or3.h (LIB_SPEC): Restore missing defn.
+ * flow.c (find_basic_blocks): Emit NOPs after normal calls in this
+ function.
+ Compute max_uid_for_flow by calling get_max_uid after the scan.
+ (find_basic_blocks_1): Don't emit NOPs here.
- * pa.h (TEXT_SPACE_P): Use TREE_CODE_CLASS.
- * pa.md (iorsi3): Add missing args to *_operand calls.
+Tue Oct 13 22:05:49 1998 Richard Henderson <rth@cygnus.com>
- * except.c (call_get_eh_context): Don't mess with sequences.
- (emit_eh_context): Include the call in the sequence here.
+ * alias.c (base_alias_check): Accept new args for the modes of the
+ two references. Use them to determine if an AND can overlap. Update
+ all callers.
+ (memrefs_conflict_p): Assume sizes are aligned, and uses them
+ to determine if an AND can overlap.
-1997-12-11 Paul Eggert <eggert@twinsun.com>
+Tue Oct 13 17:51:04 1998 Jim Wilson <wilson@cygnus.com>
- * collect2.c (write_c_file_glob): Allocate initial frame object
- in static storage and pass its address.
+ * config/m68k/m68k.h (HARD_REGNO_MODE_OK): For FP regs, add REGNO >= 16
+ check. Add comment to document problems with TARGET_SUN_FPA version
+ of this macro.
+ * config/m68k/m68k.md (movxf+1): Support 'r'/'r' moves.
-Thu Dec 11 23:33:48 1997 Jason Merrill <jason@yorick.cygnus.com>
+Tue Oct 13 17:46:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * except.c (call_get_eh_context): Don't take a parm.
- Put the call at the top of the function.
- (emit_eh_context): Adjust.
- (get_eh_context): Replace with former use_eh_context.
- (get_eh_context_once, get_saved_pc_ref): Remove.
- (start_eh_unwinder, end_eh_unwinder, emit_unwinder): Remove.
- * except.h: Adjust.
- * integrate.c (expand_inline_function): Adjust.
- * toplev.c (rest_of_compilation): Don't call emit_unwinder.
+ * Makefile.in (gencheck.o): Depend on gansidecl.h.
-Fri Oct 10 17:58:31 CEST 1997 Marc Lehmann <pcg@goof.com>
+ * c-common.c (print_char_table): Add missing initializers.
+ (scan_char_table): Likewise.
+ (time_char_table): Likewise.
- * i386/xm-go32.h (EXECUTABLE_SUFFIX): Define.
- (DIR_SEPARATOR, NO_SYS_SIGLIST): Likewise.
+ * c-decl.c (c_decode_option): Mark parameter `argc' with
+ ATTRIBUTE_UNUSED.
+ (declare_parm_level): Mark parameter `definition_flag' with
+ ATTRIBUTE_UNUSED.
-Thu Dec 11 23:55:17 1997 Manfred Hollstein <manfred@s-direktnet.de>
+ * c-lex.c (readescape): Use `(unsigned)1' in shift.
+ (yylex): Likewise. Cast `sizeof' to an (int) when comparing
+ against one.
- * fixincludes (strlen,strspn,strcspn return value): Handle different
- layout on sysV88.
- (hypot): Provide a fake for hypot which is broken on
- m88k-motorola-sysv3.
+ * calls.c (store_one_arg): Remove unused parameter `fndecl'. All
+ callers changed.
+ (emit_call_1): Mark parameters `fndecl' and `funtype' with
+ ATTRIBUTE_UNUSED.
+ (expand_call): Cast result of MIN() to (unsigned int) when
+ comparing against an unsigned value.
-Thu Dec 11 23:50:17 1997 John F. Carr <jfc@mit.edu>
+ * cccp.c (pcfinclude): Remove unused parameter `limit'. All
+ callers changed.
+ (make_definition): Remove unused parameter `op'. All callers
+ changed.
+ (create_definition): Cast REST_EXTENSION_LENGTH to (long) when
+ comparing against the result of pointer arithmetic.
+
+ * config/mips/mips.h (FUNCTION_ARG_BOUNDARY): Cast to (unsigned)
+ when comparing against one.
+
+ * dwarf2out.c (dwarf2out_frame_debug): Cast REGNO() and
+ HARD_FRAME_POINTER_REGNUM to (unsigned) when comparing against
+ one.
+ (output_die): Move variable `i' into the scope in which it is
+ used. Change its type to `unsigned'.
+ (output_die): Cast the result of `strlen' to (int) when passing it
+ to ASM_OUTPUT_ASCII().
+ (output_pubnames): Likewise.
+ (output_line_info): Likewise.
- * tree.c, tree.h: Change tree_code_type, tree_code_length, and
- tree_code_name from pointers to arrays.
- * tree.c: Remove standard_tree_code_* variables, no longer used.
- * print-tree.c: Remove declaration of tree_code_name.
+ * emit-rtl.c (global_rtl): Add missing initializers.
- * cp/lex.c (init_lex): Update for tree_code_* changes.
- * objc/objc-act.c (init_objc): Likewise.
+ * explow.c (promote_mode): Mark parameter `for_call' with
+ ATTRIBUTE_UNUSED.
- * tree.def, cp/cp-tree.def, objc/objc-tree.def: Update for tree_code
- changes.
+ * expmed.c (expand_shift): Cast the result of GET_MODE_BITSIZE to
+ `unsigned HOST_WIDE_INT' when comparing against one.
+ (synth_mult): Change type of variable `cost' to int.
+ (emit_store_flag): Use `(unsigned HOST_WIDE_INT) 1' in shift.
+
+ * expr.c (copy_blkmode_from_reg): Cast BITS_PER_WORD to (unsigned)
+ when comparing against one.
+ (get_inner_reference): Change variable `alignment' to unsigned.
+ (expand_expr): Cast the result of GET_MODE_ALIGNMENT to (unsigned
+ int) when comparing against one.
+ (expand_builtin_setjmp): Change type of variable `i' to size_t.
+
+ * fold-const.c (div_and_round_double): Cast BASE to
+ (HOST_WIDE_INT) when comparing against one.
+
+ * gencheck.c: Include gansidecl.h.
+ (main): Mark parameter `argv' with ATTRIBUTE_UNUSED.
+
+ * optabs.c (gen_cond_trap): Mark parameters `code', `op2' and
+ `tcode' with ATTRIBUTE_UNUSED.
+
+ * real.c (edivm): Cast constant value to (unsigned long) in
+ expression compared against an unsigned value.
+
+ * stmt.c (expand_return): Cast BITS_PER_WORD to (unsigned) when
+ comparing against one.
+ (expand_end_case): Cast CASE_VALUES_THRESHOLD to (unsigned int)
+ when comparing against one.
+
+ * stor-layout.c (mode_for_size): Cast MAX_FIXED_MODE_SIZE to
+ (unsigned int) when comparing against one. Likewise for
+ GET_MODE_BITSIZE.
+ (smallest_mode_for_size): Likewise.
+ (save_storage_status): Mark parameter `p' with ATTRIBUTE_UNUSED.
+ (restore_storage_status): Likewise.
+
+ * toplev.c (debug_args): Add missing initializer.
+ (f_options): Spelling correction. Add missing initializers.
+ (documented_lang_options): Likewise.
+ (debug_end_source_file): Mark parameter `lineno' with
+ ATTRIBUTE_UNUSED.
-Thu Dec 11 23:34:54 1997 Fred Fish <fnf@ninemoons.com>
+ * tree.c (valid_machine_attribute): Mark parameters `attr_args',
+ `decl' and `type' with ATTRIBUTE_UNUSED.
- * config.sub: Add support for BeOS target.
- * configure.in: Likewise.
- * ginclude/stdarg.h: Likewise.
- * ginclude/stddef.h: Likewise.
- * ginclude/varargs.h: Likewise.
- * rs6000/beos.h: New file for BeOS.
- * rs6000/t-beos: Likewise.
- * rs6000/x-beos: Likewise.
- * rs6000/xm-beos.h: Likewise.
- * toplev.c (get_run_time): Just return 0 on BeOS.
+ * varasm.c (decode_reg_name): Cast `sizeof' expression to (int)
+ when comparing against one.
+ (assemble_variable): Mark parameter `top_level' with
+ ATTRIBUTE_UNUSED.
+ (assemble_external_libcall): Mark parameter `fun' with
+ ATTRIBUTE_UNUSED.
+ (output_constant_pool): Mark parameters `fnname' and `fndecl' with
+ ATTRIBUTE_UNUSED.
-Thu Dec 11 23:25:23 1997 Jeffrey A Law (law@cygnus.com)
- Toon Moene (toon@moene.indiv.nluug.nl)
+Tue Oct 13 12:51:04 1998 Nick Clifton <nickc@cygnus.com>
- * m68k.h (GO_IF_LEGITIMATE_ADDRESS): No longer cater to horribly
- old and broken Sun3 assemblers. Newer versions handle large
- offsets correctly as does the GNU assembler.
+ * config/v850/lib1funcs.asm (_udivsi3): Add .type declaration.
+ Replace use of r5 with use of r19.
-Thu Dec 11 23:06:48 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+ * config/v850/v850.h (LINK_POINTER_REGNUM): Define.
- * objc/objc-act.c (lang_report_error_function): Disable.
- * objc/objc-parse.y: Include "output.h".
- (yyerror): Remove redundant decl.
- (yyprint): Fix prototype.
- (apply_args_register_offset): Remove redundant decl.
- (get_file_function_name): Likewise.
+ * config/v850/v850.c (compute_register_save_size): Allow for the
+ fact that helper functions save all registers, not just those used
+ by the function.
-Thu Dec 11 22:02:10 1997 Jason Merrill <jason@yorick.cygnus.com>
+ Replace constant 31 with macro LINK_POINTER_REGNUM.
- * flow.c (find_basic_blocks): A CALL_INSN that can throw starts
- a new basic block.
- (find_basic_blocks_1): Likewise.
+ * config/v850/v850.md: Use 'indirect_operand' rather than
+ 'memory_operand' for bit test/set/clear patterns.
-Thu Dec 11 21:08:48 1997 Jason Merrill <jason@yorick.cygnus.com>
+Tue Oct 13 11:49:14 1998 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (use_eh_context): Don't copy_rtx a REG.
- (emit_throw): Lose old unwinder support.
- (expand_internal_throw): Likewise.
- * libgcc2.c (struct eh_context): Likewise.
- (new_eh_context): Likewise.
- (__get_eh_info): Lose redundant cast.
- (__get_dynamic_handler_chain): Likewise.
- (__get_saved_pc): Lose.
- Lose all old unwinder support code.
-
-Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
-
- Thread-safe EH support for pthreads, DCE threads and Solaris threads.
-
- * integrate.c (expand_inline_function): If the inline fn uses eh
- context, make sure that the current fn has one.
- * toplev.c (rest_of_compilation): Call emit_eh_context.
- * except.c (use_eh_context): New fn.
- (get_eh_context_once): New fn.
- (call_get_eh_context): New fn.
- (emit_eh_context): New fn.
- (get_eh_context): Call either get_eh_context_once or
- call_get_eh_context, depending on what we have.
- (get_dynamic_handler_chain): Call get_eh_context_once.
- * except.h: Prototypes for fns above.
- * optabs.c (get_eh_context_libfunc): Removed.
- (init_optabs): Don't initialize it.
- * expr.h (get_eh_context_libfunc): Removed.
- * rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
- * config/pa/pa.h (CPP_SPEC): Support for -threads.
- * config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
- * config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
- New multilib for -threads.
- * config/sparc/t-sol2: Added multilibs for -threads and
- made -pthreads alias to it.
- * config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
- Added -threads and -pthreads options.
- * libgcc-thr.h: New file.
- * libgcc2.c: (__get_cpp_eh_context): Removed.
- (struct cpp_eh_context): Removed.
- (struct eh_context): Replaced cpp_eh_context with generic language
- specific pointer.
- (__get_eh_info): New function.
- (__throw): Check eh_context::info.
- (__sjthrow): Ditto.
- * libgcc2.c: Include libgcc-thr.h.
- (new_eh_context, __get_eh_context,
- eh_pthread_initialize, eh_context_initialize, eh_context_static,
- eh_context_specific, eh_context_free): New functions.
- (get_eh_context, eh_context_key): New variables.
- (__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
- get_eh_context to get the context.
- (longjmp): Move the declaration inside
- #ifdef DONT_USE_BUILTIN_SETJMP.
- * frame.c: Include libgcc-thr.h.
- (object_mutex): Mutex to protect the object list.
- (find_fde, __register_frame, __register_frame_table,
- __deregister_frame): Hold the lock while accessing objects.
- * except.h (get_eh_context): Declare.
- * except.c (current_function_ehc): Define.
- (current_function_dhc, current_function_dcc): Removed.
- (get_eh_context): New function.
- (get_dynamic_handler_chain): Use get_eh_context.
- (get_saved_pc_ref): Ditto.
- (get_dynamic_cleanup_chain): Removed references to
- current_function_dcc.
- (save_eh_status, restore_eh_status): Save and restore
- current_function_ehc instead.
- * optabs.c (get_eh_context_libfunc): New variable.
- (init_optabs): Initialize it.
- * expr.h: Declare get_eh_context_libfunc.
- * function.h (struct function): Replaced dhc and dcc with ehc.
- * except.c (get_saved_pc_ref): New functions.
- (eh_saved_pc_rtx, eh_saved_pc): Deleted.
- (expand_internal_throw_indirect): Use get_saved_pc_ref() instead
- of eh_saved_pc.
- (end_eh_unwinder): Likewise.
- (init_eh): Remove initialization of eh_saved_pc.
- * optabs.c (get_saved_pc_libfunc): New variable.
- (init_optabs): Initialize it.
- * expr.h: Declare get_saved_pc_libfunc.
- * except.h (eh_saved_pc_rtx): Deleted.
- (get_saved_pc_ref): Declared.
-
- From Scott Snyder <snyder@d0sgif.fnal.gov>:
- * libgcc2.c (__get_saved_pc): New.
- (__eh_type, __eh_pc): Deleted.
- (__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
- (__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
- this fcn.
-
-Thu Dec 11 17:23:48 1997 John F. Carr <jfc@mit.edu>
-
- * sparc/sol2.h: Use 64 bit multiply and divide functions in
- Solaris libc. Define TARGET_LIVE_G0 and TARGET_BROKEN_SAVERESTORE
- as 0.
-
- * rtl.h (global_rtl): New variable, replacing separate variables for
- commonly used rtl.
- (const_int_rtx): Now array of rtx_def, not rtx.
- * emit-rtl.c: Update for new rtl data structures.
- * genattrtab.c: Define global_rtl.
-
-Thu Dec 11 15:50:29 1997 David Edelsohn <edelsohn@mhpcc.edu>
-
- * configure.in ({rs6000,powerpc}-*-*): Enable Haifa scheduler by
- default.
-
-Wed Dec 10 12:30:18 1997 Anthony Green <green@cygnus.com>
-
- * crtstuff.c (__do_global_ctors): Fix typo.
-
-Tue Dec 9 09:43:59 1997 Manfred Hollstein <manfred@s-direktnet.de>
-
- * toplev.c (main): Check HAVE_GETRLIMIT and HAVE_SETRLIMIT in addition
- to RLIMIT_STACK to see if we can call getrlimit and setrlimit.
-
-Tue Dec 9 09:38:58 1997 David Edelsohn <edelsohn@mhpcc.edu>
-
- * rs6000.h (FUNCTION_ARG_PADDING): Define.
- * rs6000.c (function_arg_padding): New function.
-
-Tue Dec 9 10:34:21 1997 Manfred Hollstein <manfred@s-direktnet.de>
-
- * m68k.c: Include tree.h only once.
-
-Tue Dec 9 09:32:33 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-
- * integrate.c (save_for_inline_copying): Make a new reg_parm_stack_loc.
-
-Tue Dec 9 01:16:06 1997 Jeffrey A Law (law@cygnus.com)
-
- * Partially cleaned up prototyping code from HJ.
- * tree.h: Add many prototypes.
- * haifa-sched.c (haifa_classify_insn): Renamed from classify_insn.
- All references changed.
- * rtl.h: Protect from multiple inclusions. Add many prototypes.
+ * mips/iris6.h (ASM_OUTPUT_WEAK_ALIAS): Call ASM_GLOBALIZE_LABEL.
+ * varasm.c (assemble_start_function et al): Don't call
+ ASM_GLOBALIZE_LABEL for weak symbols.
+
+Tue Oct 13 11:37:45 1998 Nick Clifton <nickc@cygnus.com>
+
+ * cse.c (equiv_constant): Check for NULL return from
+ gen_lowpart_if_possible().
+
+Tue Oct 13 11:24:51 1998 Jeffrey A Law (law@cygnus.com)
-Tue Dec 9 01:15:15 1997 Fred Fish <fnf@ninemoons.com>
+ * mn10200.md (addsi3, subsi3, negsi2): Only allow register operands.
- * libgcc2.c (string.h): Hoist inclusion to occur before first use of
- string functions like strlen.
+ * collect2.c (main): Pass -EL/-EB through to the compiler.
-Tue Dec 9 00:57:38 1997 Manfred Hollstein <manfred@s-direktnet.de>
+1998-10-12 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
- * configure.in: Check for functions getrlimit and setrlimit.
- * cccp.c (main): Check HAVE_GETRLIMIT and HAVE_SETRLIMIT in addition
- to RLIMIT_STACK to see if we can call getrlimit and setrlimit.
+ * expr.c (push_block): Handle targets where the stack grows
+ to higher addresses, but args grow to lower addresses and
+ ACCUMULATE_OUTGOING_ARGS is not defined.
-Mon Dec 8 23:53:26 1997 Jay Sachs <sachs@bull.cs.williams.edu>
+Tue Oct 13 08:00:52 1998 Catherine Moore <clm@cygnus.com>
- * Makefile.in (compare*): Handle losing behavior from 4.4bsd make.
+ * config/v850/v850.c (print_operand): Extend meaning
+ of 'c' operands to support .vtinherit.
-Mon Dec 8 21:03:28 1997 Richard Henderson <rth@cygnus.com>
+Tue Oct 13 21:38:35 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * alpha.c (REG_RA, alpha_return_addr, output_epilog):
- Fix merge problems.
+ * config/c4x/c4x.c: Convert to gen_rtx_FOO.
+ Added ATTRIBUTE_UNUSED to unused function arguments.
+ (rc_reg_operand): New predicate.
+ (c4x_rptb_insert): New function.
+ (c4x_rptb_nop_p): Recognize modified rptb_top pattern.
+ (c4x_optimization_options): New function.
- * alpha.c (override_options): Don't know about scheduling for EV6.
- * alpha.md (ev5 function units): Don't overload as ev6.
+ * config/c4x/c4x.md: Convert to gen_rtx_FOO.
+ (decrement_and_branch_on_count): New pattern.
+ (rptb_top): Modified pattern to work with BCT optimization.
- * alpha.c (alpha_adjust_cost): Simplify. Fix typo in ev5 mult case.
- * alpha.md (define_attr type): Add mvi.
- (ev5_e0): Define sceduling parameters for it.
- (TARGET_MAX insns): Type is mvi not shift.
+ * config/c4x/c4x.h (RC_REG): New register class.
+ (rc_reg_operand): Define prototype.
+ (IS_RC_REG): New macro.
+ (IS_RC_OR_PSEUDO_REG): New macro.
+ (IS_RC_OR_PSEUDO_REGNO): New macro.
+ (OPTIMIZATION_OPTIONS): Define.
-Mon Dec 8 18:15:00 1997 Richard Henderson <rth@cygnus.com>
+Mon Oct 12 19:57:34 1998 Jason Merrill <jason@yorick.cygnus.com>
- * alpha/win-nt.h (TRAMPOLINE_TEMPLATE): Fix backported gcc-2.8 bug.
+ * collect2.c (extract_init_priority): No priority is 65535.
-Mon Dec 8 21:17:28 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Oct 12 12:10:37 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
- * cstamp-h, auto-config.h: Delete.
+ * Makefile.in (build_tooldir): New variable, same as old
+ $(tooldir), but without depending on $(libdir)/$(unlibsubdir).
+ (GCC_FOR_TARGET): Add -B$(build_tooldir)/bin/.
+ (bootstrap, bootstrap2, bootstrap3, bootstrap4): Likewise.
+
+ * configure.in (gxx_include_dir): Set default based on unlibsubdir.
+ * Makefile.in (tooldir): Likewise.
+ (cccp.o, cpplib.o): Use unlibsubdir implicitly through
+ gxx_include_dir, includedir and tooldir.
+ (protoize.o, unprotoize.o): Likewise.
+
+Mon Oct 12 10:50:44 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/arm.md: Replace (reg 24) with (reg:CC 24).
+
+ * config/arm/thumb.c (thumb_override_options): Add warning about
+ PIC code not being supported just yet.
+
+Sun Oct 11 16:49:15 1998 John Wehle (john@feith.com)
+
+ * flow.c: Update comment.
+ (notice_stack_pointer_modification): New static function.
+ (record_volatile_insns): Use it.
+ (mark_regs_live_at_end): Mark the stack pointer as alive
+ at the end of the function if current_function_sp_is_unchanging
+ is set.
+ (life_analysis_1): Set current_function_sp_is_unchanging.
+ * function.c: Define it.
+ (init_function_start): Initialize it.
+ * output.h: Declare it.
+ * reorg.c (fill_simple_delay_slots, dbr_schedule): Mark
+ the stack pointer as alive at the end of the function if
+ current_function_sp_is_unchanging is set.
+ * i386.c (ix86_epilogue): Optimize the restoring
+ of the stack pointer.
-Sun Dec 7 19:19:03 1997 Jeffrey A Law (law@cygnus.com)
+Mon Oct 12 01:22:53 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Sat Dec 6 22:22:22 1997 Jeffrey A Law (law@cygnus.com)
+Sun Oct 11 23:04:30 1998 Robert Lipe <robertl@dgii.com>
+
+ * c-pragma.c (handle_pragma_token): If passed a token instead
+ of a tree, use that as the pack value.
+
+Sun Oct 11 14:21:14 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * flow.c (find_basic_blocks_1): Fix prototype.
+
+Sun Oct 11 05:03:41 1998 Ken Raeburn <raeburn@cygnus.com>
+
+ * tree.h (DECL_NO_CHECK_MEMORY_USAGE): New macros.
+ (struct tree_decl): New fields no_check_memory_usage.
+ * c-common.c (enum attrs): Add A_NO_CHECK_MEMORY_USAGE.
+ (init_attributes): Register it as a new attribute.
+ (decl_attributes): Set flags on functions given that attribute.
+ * c-decl.c (duplicate_decls): Merge new attribute.
+ * expr.h (current_function_check_memory_usage): Declare new var.
+ * calls.c, expr.c, function.c, stmt.c, alpha.c, clipper.c, m88k.c,
+ pa.c, sparc.c: Replace uses of flag_check_memory_usage with
+ current_function_check_memory_usage.
+ * function.h: Add field to struct function.
+ * function.c (current_function_check_memory_usage): Define it.
+ (push_function_context_to, pop_function_context_from): Save and
+ restore it.
+ (expand_function_start): Set it, based on global flag and function
+ attribute.
+
+ * expr.c (expand_expr, case VAR_DECL): In memory-checking code, do
+ check non-automatic variables, to permit detection of writes to
+ read-only locations in embedded systems without memory management.
+ * calls.c (store_one_arg): Use ARGS_SIZE_RTX to get size of argument
+ when emitting chkr_set_right_libfunc call, even if the argument is
+ BLKmode or variable-sized; don't abort.
+
+ * optabs.c (init_optabs): Create Checker and __cyg_profile_*
+ symbols in Pmode, not VOIDmode.
- * cccp.c: Fix typo brought over in merge.
+Sun Oct 11 01:03:05 1998 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * Merge in changes from gcc-2.8.
+ * cppexp.c: When forcing unsigned comparisons, cast both sides
+ of the operation.
-Mon Nov 3 05:45:32 1997 Philippe De Muyter <phdm@macqel.be>
+ * cpphash.h: Move static declaration of hashtab[]...
+ * cpphash.c: ...here.
- * m68k.c: Include tree.h for dwarf2out_cfi_label.
+ * cpplib.c: Cast difference of two pointers to size_t before
+ comparing it to size_t. Cast signed to unsigned
+ before comparing to size_t. (FIXME: struct argdata should use
+ unsigned buffer sizes.)
+ * cpplib.h (struct cpp_reader): Declare token_buffer_size as
+ unsigned int. (CPP_WRITTEN): Cast return value to size_t.
+ (CPP_RESERVE): Parenthesize N for evaluation order, cast to
+ size_t before comparison.
- * gcc.c (process_command): Do not take address of function fatal when
- calling lang_specific_driver.
+Sun Oct 11 00:15:29 1998 Jeffrey A Law (law@cygnus.com)
-Sat Dec 6 01:02:38 1997 Mumit Khan <khan@xraylith.wisc.edu>
+ * flow.c (find_basic_blocks): Delete "live_reachable_p" argument.
+ (find_basic_blocks_1): Similarly.
+ * output.h (find_basic_blocks): Fix prototype.
+ * gcse.c, toplev.c: Don't pass "live_reachable_p" argument to
+ find_basic_blocks anymore.
- * config/i386/cygwin32.h (DWARF2_UNWIND): Exception handling
- doesn't work with it yet, so set it to 0.
- * config/i386/xm-cygwin32.h (NO_SYS_SIGLIST): Define.
+Sat Oct 10 22:00:34 1998 Richard Henderson <rth@cygnus.com>
-Sat Dec 6 01:01:02 1997 Christian Iseli <Christian.Iseli@lslsun.epfl.ch>
+ * basic-block.h (EXECUTE_IF_SET_IN_SBITMAP): New macro.
+ (sbitmap_free, sbitmap_vector_free): New macros.
+ * output.h (rtl_dump_file): Declare.
- * cse.c (cse_insn): Check for invalid entries when taking references.
+Sat Oct 10 17:01:42 1998 Jeffrey A Law (law@cygnus.com)
-Fri Dec 5 18:26:25 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * regmove.c (optimize_reg_copy_3): Honor TRULY_NOOP_TRUNCATION.
- * loop.c (invariant_p): Don't test flag_rerun_loop_opt.
- (loop_optimize, scan_loop, strength_reduce): New argument unroll_p.
- * toplev.c (rest_of_compilation): Pass it. Remove code to
- save / clear / restore flag_unroll_{,all_}loops.
+Fri Oct 9 22:08:05 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Fri Dec 5 16:26:03 1997 Bernd Schmidt <crux@ohara.Informatik.RWTH-Aachen.DE>
+ * fp-bit.c (SFtype): Don't implicitly use int in declaration.
+ (DFtype): Likewise.
+ (_fpdiv_parts): Remove unused parameter `tmp', all callers changed.
+ (divide): Remove unused variable `tmp'.
+ (si_to_float): Cast numeric constant to (SItype) before comparing
+ it against one.
- * i386.c (notice_update_cc): Remove bogus pentium GCC code.
+Fri Oct 9 16:03:19 1998 Graham <grahams@rcp.co.uk>
-Fri Dec 5 16:25:14 1997 Jeffrey A Law (law@cygnus.com)
+ * flow.c (print_rtl_with_bb): Changed type of in_bb_p to match use.
+ * gcc.c (add_preprocessor_option): Correct typo when allocating
+ memory, sizeof() argument had one too many `*'.
+ (add_assembler_option): Likewise.
+ (add_linker_option): Likewise.
+ * gcov.c (output_data): Likewise.
+ * local-alloc.c (memref_used_between_p): Likewise.
+ (update_equiv_regs): Likewise.
+ * loop.c (strength_reduce): Likewise.
+ * reg-stack.c (record_asm_reg_life): Likewise.
+ (subst_asm_stack_reg): Likewise.
+ * reorg.c (dbr_schedule): Likewise.
- * stmt.c (warn_if_unused_value): Don't warn for TRY_CATCH_EXPR.
+Fri Oct 9 15:57:51 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
-Thu Dec 4 11:51:00 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * flow.c (life_analysis_1): Break out some functions.
+ (find_basic_blocks_1): Likewise. Also move some variables out and
+ make them static.
+ Rename NONLOCAL_LABEL_LIST arg to NONLOCAL_LABELS and initialize
+ new static var nonlocal_label_list with it.
+ (active_eh_region, nested_eh_region, label_value_list,
+ nonlocal_label_list): New static variables.
+ (make_edges, delete_unreachable_blocks, delete_block): New static
+ functions, broken out of find_basic_blocks_1.
+ (record_volatile_insns, mark_regs_live_at_end, set_noop_p,
+ noop_move_p): New static functions, broken out of life_analysis_1.
- * except.c (get_dynamic_handler_chain): Only make the call once per
- function.
+Fri Oct 9 15:49:29 1998 Richard Henderson <rth@cygnus.com>
- * except.c (expand_end_all_catch): Fix for sjlj exceptions.
+ * expmed.c (store_bit_field): Pun non-integral str_rtx modes.
+ Take extra care for op0 now possibly being a subreg.
+ (extract_bit_field): Likewise.
+ * function.c (purge_addressof_1): Revert Oct 4 change. Drop
+ the reg to memory if there is no equal sized integral mode.
+ * stor-layout.c (int_mode_for_mode): New function.
+ * machmode.h: Prototype it.
-Thu Dec 4 12:30:40 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Fri Oct 9 14:26:44 1998 Jeffrey A Law (law@cygnus.com)
- * sh.c (final_prescan_insn): Use local label prefix
- when emitting .uses pseudo-ops.
+ * global.c (build_insn_chain): Verify no real insns exist past the
+ end of the last basic block, then exit the loop.
-Wed Dec 3 12:01:56 1997 Jason Merrill <jason@yorick.cygnus.com>
+Fri Oct 9 11:44:47 1998 David Edelsohn <edelsohn@gnu.org>
- * libgcc2.c (__throw): Use __builtin_return_addr instead of __eh_pc.
- * except.c: Lose outer_context_label_stack.
- (expand_eh_region_end): Rethrow from outer_context here.
- (expand_fixup_region_end): Let expand_eh_region_end do the rethrow.
- (expand_internal_throw): Take no args.
- (expand_internal_throw_indirect): Lose.
- (expand_leftover_cleanups, expand_start_all_catch): Use expand_rethrow.
- (expand_start_all_catch): Start a rethrow region.
- (expand_end_all_catch): End it.
- (expand_rethrow): New fn.
- * except.h: Reflect above changes.
- * flow.c: Revert change of Nov 27.
+ * loop.c (insert_bct): Ensure loop_iteration_var non-zero before use.
-Thu Dec 4 00:24:09 1997 Jeffrey A Law (law@cygnus.com)
+Thu Oct 8 21:59:47 1998 Dave Brolley <brolley@cygnus.com>
- * i386/t-sol2 (CRTSTUFF_T_CFLAGS): Turn on the optimizer.
+ * emit-rtl.c (init_emit_once): Call INIT_EXPANDERS.
-Wed Dec 3 12:01:56 1997 Jason Merrill <jason@yorick.cygnus.com>
+Thu Oct 8 22:03:45 1998 David Edelsohn <edelsohn@gnu.org>
- * except.c (expand_fixup_region_end): New fn.
- (expand_fixup_region_start): Likewise.
- (expand_eh_region_start_tree): Store cleanup into finalization here.
- * stmt.c (expand_cleanups): Use them to protect fixups.
+ * rs6000.h (RTX_COSTS): Add PROCESSOR_PPC604e cases.
-Wed Dec 3 11:41:13 1997 Gavin Koch <gavin@cygnus.com>
+Thu Oct 8 17:00:18 1998 Richard Henderson <rth@cygnus.com>
- * mips/mips.md (muldi3_r4000): Broaden the output template
- and attribute assignments to handle three operand dmult;
- rename to muldi3_internal2.
- (muldi3): Call the new muldi3_internal2 for R4000, and
- any GENERATE_MULT3 chip.
+ * flow.c (find_basic_blocks): Correctly determine when a call
+ is within an exception region.
-Tue Dec 2 19:40:43 1997 Jason Merrill <jason@yorick.cygnus.com>
+Thu Oct 8 17:15:04 1998 Jeffrey A Law (law@cygnus.com)
- * stmt.c (expand_decl_cleanup): Update thisblock after eh_region_start.
+ * toplev.c (output_file_directive): Use DIR_SEPARATOR, not '/'.
-Tue Dec 2 12:54:33 1997 Jim Wilson <wilson@cygnus.com>
+ * cpplib.h: Protect from multiple inclusions.
+ * cpplib.c: Fix minor formatting problems.
- * unroll.c (find_splittable_givs): Remove last change. Handle givs
- with a dest_reg that was created by loop.
+ * i386/xm-cygwin32.h: Only define POSIX if it is not already defined.
-Sat Nov 29 12:44:57 1997 David Edelsohn <edelsohn@mhpcc.edu>
+ * jump.c (jump_optimize): Revert accidental patch.
- * rs6000.c (function_arg_partial_nregs): Undo Nov. 26 patch.
+ * Makefile.in (cpplib.o): Use unlibsubdir.
- * rs6000/aix41.h (ASM_CPU_SPEC): Define.
+Thu Oct 8 12:50:47 1998 Jim Wilson <wilson@cygnus.com>
-Fri Nov 28 10:00:27 1997 Jeffrey A Law (law@cygnus.com)
+ * loop.c (get_condition): Allow combine when either compare is
+ VOIDmode.
- * configure.in: Fix NCR entries.
+Thu Oct 8 11:31:01 1998 Jeff Law (law@cygnus.com)
-Thu Nov 27 12:20:19 1997 Jeffrey A Law (law@cygnus.com)
+ * version.c: Bump for snapshot.
- * flow.c (find_basic_blocks): Handle cfg issues for rethrows and
- nested exceptions correctly.
+Thu Oct 8 12:21:14 1998 Richard Frith-Macdonald <richard@brainstorm.co.uk>
- * unroll.c (find_splittable_givs): Don't split givs with a dest_reg
- that was created by loop.
+ * c-lex.c (remember_protocol_qualifiers): Handle RID_BYREF.
+ (init_lex): Initialize ridpointers[RID_BYREF].
+ * c-lex.h (enum rid): Add RID_BYREF.
+ * c-parse.gperf: Add RID_BYREF as a type qualifier.
+ * objc/objc-act.c (is_objc_type_qualifiers): Handle RID_BYREF.
+ (encode_type_qualifiers): Similarly.
+ * c-gperf.h: Rebuilt.
-Thu Nov 27 09:34:58 1997 Jason Merrill <jason@yorick.cygnus.com>
+Thu Oct 8 05:56:00 1998 Jeffrey A Law (law@cygnus.com)
- * expr.c (preexpand_calls): Don't look past a TRY_CATCH_EXPR.
+ * c-common.c (type_for_mode): Only return TItype nodes when
+ HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ * c-decl.c (intTI_type_node, unsigned_intTI_type_node): Only declare
+ when HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ (init_decl_processing): Only create TItype nodes when
+ HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ * c-tree.h (intTI_type_node, unsigned_intTI_type_node): Only declare
+ when HOST_BITS_PER_WIDE_INT is >= 64 bits.
- * except.c (expand_start_all_catch): One more do_pending_stack_adjust.
+Thu Oct 8 05:05:34 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
-Wed Nov 26 15:47:30 1997 Michael Meissner <meissner@cygnus.com>
+ * stmt.c (n_occurrences): New static function.
+ (expand_asm_operands): Verify that all constrains match in the
+ number of alternatives.
+ Verify that '+' or '=' are at the beginning of an output constraint.
+ Don't allow '&' for input operands.
+ Verify that '%' isn't written for the last operand.
+ * reload.c (find_reloads): Abort if an asm is found with invalid
+ constraints; all possible problems ought to be checked for earlier.
- * rs6000.c (SMALL_DATA_REG): Register to use for small data relocs.
- (print_operand): Use SMALL_DATA_REG for the register involved in
- small data relocations.
- (print_operand_address): Ditto.
+Thu Oct 8 04:26:20 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * rs6000/linux.h (LINK_SPEC): Pass -dynamic-linker /lib/ld.so.1 if
- -dynamic linker is not used.
+ * flags.h (flag_branch_on_count_reg): Always declare.
+ * toplev.c (flag_branch_on_count_reg): Likewise.
+ * toplev.c: Fix typos.
- * rs6000.md (call insns): For local calls, use @local suffix under
- System V. Don't use @plt under Solaris.
+ * real.c (c4xtoe): Remove unused variables. Add some missing parens.
+ (toc4x): Similarly.
- * rs6000.c (output_function_profiler): Put label address in r0, and
- store LR in 4(sp) for System V/eabi.
+Thu Oct 8 01:25:22 1998 Richard Henderson <rth@cygnus.com>
- * rs6000.h (ASM_OUTPUT_REG_{PUSH,POP}): Keep stack aligned to 16
- byte boundary, and maintain stack backchain.
+ * flow.c (find_basic_blocks): Calc upper bound for extra nops in
+ max_uids_for_flow.
+ (find_basic_blocks_1): Add a nop to the end of a basic block when
+ a trailing call insn does not have abnormal control flow.
+ * gcse.c (pre_transpout): New variable.
+ (alloc_pre_mem, free_pre_mem, dump_pre_data): Bookkeeping for it.
+ (compute_pre_transpout): Calculate it.
+ (compute_pre_ppinout): Use it to eliminate impossible placements
+ due to abnormal control flow through calls.
+ (compute_pre_data): Call compute_pre_transpout.
-Tue Nov 25 14:08:12 1997 Jim Wilson <wilson@cygnus.com>
+Wed Oct 7 21:40:24 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * mips.md (fix_truncdfsi2, fix_truncsfsi2, fix_truncdfdi2,
- fix_truncsfdi2): Change *.
+ * config/sparc/sol2-sld-64.h (ASM_CPU_SPEC): Fix typo.
-Wed Nov 26 11:12:26 1997 Jason Merrill <jason@yorick.cygnus.com>
+Wed Oct 7 21:19:46 1998 Ken Raeburn <raeburn@cygnus.com>
- * toplev.c (main): Complain about -gdwarfn.
+ * config/mips/mips.md (tablejump_internal3, tablejump_internal4
+ and matching define_insns): Tack on a `use' of the table label, so
+ flow analysis will recognize a tablejump.
-Tue Nov 25 22:43:30 1997 Jason Merrill <jason@yorick.cygnus.com>
+Wed Oct 7 17:33:39 1998 Richard Henderson <rth@cygnus.com>
- * dwarfout.c (output_type): If finalizing, write out nested types
- of types we've already written.
+ * gcse.c (pre_insert_insn): Tweek to notice that calls do not
+ always end basic blocks for abnormal edge reasons.
-Tue Nov 25 20:32:24 1997 Michael Meissner <meissner@cygnus.com>
+Wed Oct 7 14:40:43 1998 Nick Clifton <nickc@cygnus.com>
- (patches originally from Geoffrey Keating)
- * rs6000.c (function_arg): Excess floating point arguments don't
- go into GPR registers after exhausting FP registers under the
- System V.4 ABI.
- (function_arg_partial_nregs): Ditto.
+ * config/i386/i386.h: Remove definition of
+ HANDLE_PRAGMA_PACK_PUSH_POP.
- * rs6000.md (call insns): If -fPIC or -mrelocatable, add @plt
- suffix to calls.
+ * config/i386/go32.h: Add definition of
+ HANDLE_PRAGMA_PACK_PUSH_POP.
-Tue Nov 25 23:37:27 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * config/i386/win32.h: Add definition of
+ HANDLE_PRAGMA_PACK_PUSH_POP.
- * integrate.c (output_inline_function): Just unset DECL_INLINE.
+ * config/i386/cygwin32.h: Add definition of
+ HANDLE_PRAGMA_PACK_PUSH_POP.
-Tue Nov 25 23:33:29 1997 scott snyder <snyder@d0sgif.fnal.gov>
+ * c-pragma.c (insert_pack_attributes): Do not insert
+ attributes unless #pragma pack(push,<n>) is in effect.
- * dwarf2out.c (outout_call_frame_info): Ensure that the info has
- proper alignment.
+Wed Oct 7 12:10:46 1998 Jim Wilson <wilson@cygnus.com>
- * libgcc2.c (__throw): Initialize HANDLER.
+ * expr.c (emit_group_store): Handle a PARALLEL destination.
-Tue Nov 25 14:08:12 1997 Jim Wilson <wilson@cygnus.com>
+Wed Oct 7 10:07:29 1998 Richard Henderson <rth@cygnus.com>
- * mips.md (fix_truncdfsi2, fix_truncsfsi2, fix_truncdfdi2,
- fix_truncsfdi2): Change *X to ?*X.
+ * gcse.c (pre_insert_insn): When a call ends a bb, insert
+ the new insns before the argument regs are loaded.
-Tue Nov 25 10:00:42 1997 Richard Henderson (rth@cygnus.com)
+Wed Oct 7 12:55:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * alpha.h (CONST_OK_FOR_LETTER): Fix 'L' handling.
+ * Makefile.in (c-gperf.h): Add -L KR-C -F ', 0, 0' flags to gperf.
+ (c-parse.gperf): Update comments describing invocation flags.
+ (c-gperf.h): Regenerate using gperf 2.7.1 (19981006 egcs).
-Tue Nov 25 10:00:42 1997 Jeffrey A Law (law@cygnus.com)
+1998-10-07 Manfred Hollstein <manfred@s-direktnet.de>
- * crtstuff.c (do_global_dtors_aux): Handle multiple calls better.
+ * reload1.c (reload): Call free before clobbering the memory
+ locations or constants pointers.
-Tue Nov 25 01:26:55 1997 Bruno Haible <haible@ilog.fr>:
+Wed Oct 7 02:05:20 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * dwarf2out.c (ASM_OUTPUT_DWARF_DELTA1): Implement.
+ * config/sparc/sol2-sld-64.h (TRANSFER_FROM_TRAMPOLINE): Rework
+ for efficiency by checking whether we need to modify the current
+ stack permission at all.
+ (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): Define.
+ * config/sparc/sparc.c (sparc_initialize_trampoline): Emit
+ __enable_execute_stack libcall here too if
+ TRANSFER_FROM_TRAMPOLINE is defined.
+ * config/sparc/sparc.h: Set TARGET_ARCH32 to a constant if
+ IN_LIBGCC2.
-Mon Nov 24 22:41:55 1997 Jason Merrill <jason@yorick.cygnus.com>
+Wed Oct 7 02:27:52 1998 Jeffrey A Law (law@cygnus.com)
- * except.c (get_dynamic_handler_chain): Build up a FUNCTION_DECL.
- * optabs.c (init_optabs): Lose get_dynamic_handler_chain_libfunc.
- * expr.h: Likewise.
+ * Makefile.in (DRIVER_DEFINES): Remove last change.
-Sat Nov 22 18:58:20 1997 Jeffrey A Law (law@cygnus.com)
+Wed Oct 7 01:08:43 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
- * pa-hpux10.h (NEW_HP_ASSEMBLER): Define.
- * pa.h (LEGITIMATE_CONSTANT_P): Reject LABEL_REFs if not using
- gas and not using the new HP assembler.
+ * jump.c (duplicate_loop_exit_test): Strip REG_WAS_0 notes off all
+ insns we're going to copy.
+ * regclass.c (reg_scan_mark_refs): Don't test X for NULL_RTX.
-Fri Nov 21 15:20:05 1997 Jeffrey A Law (law@cygnus.com)
+ * loop.c (count_one_set): Add prototype.
- * Makefile.in (program_transform_cross_name): Clean up "-e" confusion.
- (GCC_INSTALL_NAME, GCC_CROSS_NAME): Likewise.
+ * caller-save.c (restore_referenced_regs): Lose mode argument.
+ (insert_save): Lose mode argument.
+ (insert_restore): Lose mode argument.
+ (insert_one_insn): Lose mode argument.
+ (save_call_clobbered_regs): Lose mode argument.
+ (setup_save_areas): Take no argument and return void. All callers
+ changed.
+ Don't verify validity of memory addresses.
+ * reload.h (setup_save_ares): Adjust prototype.
+ (save_call_clobbered_regs): Likewise.
+ * reload1.c (delete_caller_save_insns): New function.
+ (caller_save_spill_class): Delete variable.
+ (caller_save_group_size): Delete variable.
+ (reload): Call setup_save_areas and save_call_clobbered_regs
+ in the main loop, before calling calculate_needs_all_insns.
+ Don't call save_call_clobbered_regs after the loop.
+ Call delete_caller_save_insns at the end of an iteration if
+ something changed.
+ Delete code to manage caller_save_spill_class.
+ Emit the final note before setting reload_first_uid.
+ Simplify test that determines whether reload_as_needed gets run.
+ (calculate_needs): Delete code to manage caller_save_spill_class.
+
+Tue Oct 6 15:42:27 1998 Richard Henderson <rth@cygnus.com>
+
+ * collect2.c (main): Initialize ld_file_name.
+
+Tue Oct 6 15:45:15 1998 Catherine Moore <clm@cygnus.com>
+
+ * config/sparc/sysv4.h (ASM_OUTPUT_SECTION_NAME): Don't
+ check for flag_function_sections.
+
+Tue Oct 6 20:02:31 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * cse.c (insert_regs): Fix bug in Sep 24 change.
+
+Tue Oct 6 17:00:42 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * flags.h (flag_dump_unnumbered): Declare.
+ * toplev.c (flag_dump_unnumbered): Don't declare.
+ * print-rtl.c (flags.h): Include.
+ (print_rtl_single): Add return value.
+ * rtl.h (print_rtl_single): Update declaration.
+ * flow.c (flag_dump_unnumbered): Don't declare.
+ (print_rtl_with_bb): Use return value of print_rtl_single.
+
+Tue Oct 6 01:36:00 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
+
+ * loop.c (count_one_set): New static function, broken out of
+ count_loop_regs_set.
+ (count_loop_regs_set): Call it.
+ * global.c (mark_reg_store): Handle clobbers here by not calling
+ set_preference.
+ (mark_reg_clobber): Just call mark_reg_store after ensuring SETTER
+ is in fact a clobber.
+ * integrate.c (process_reg_param): New function, broken out of
+ expand_inline_function.
+ (expand_inline_function): Call it.
+
+ * i386.md (addsidi3_1): Delete unused variable temp.
+ (addsidi3_2): Likewise.
+ (clstrstrsi): Delete unused variable addr1.
+
+ * rtl.h: Don't declare any functions also declared in recog.h.
+
+ * Makefile.in (stupid.o): Update dependencies.
+ (global.o): Likewise.
+
+ * global.c: Include reload.h.
+ (reg_becomes_live): New function.
+ (reg_dies): New function.
+ (build_insn_chain): New function.
+ (global_alloc): Call build_insn_chain before calling reload.
+
+ * reload.h (struct needs): New structure definition.
+ (struct insn_chain): Likewise.
+ (reload_insn_chain): Declare variable.
+ (new_insn_chain): Declare function.
+
+ * reload1.c (reload_startobj): New variable.
+ (reload_insn_chain): New variable.
+ (unused_insn_chains): New variable.
+ (new_insn_chain): New function.
+ (init_reload): Initialize reload_startobj, not reload_firstobj.
+ (reload): Initialize reload_firstobj.
+ Before returning, free everything on the reload_obstack.
+
+ * stupid.c: Include insn-config.h, reload.h and basic-block.h.
+ (reg_where_dead_chain, reg_where_born_exact, reg_where_born_clobber,
+ current_chain): New variables.
+ (reg_where_born): Delete variable.
+ (REG_WHERE_BORN): New macro.
+ (find_clobbered_regs): New function.
+ (stupid_life_analysis): Don't allocate/free reg_where_born.
+ Allocate and free reg_where_born_exact, reg_where_born_clobber,
+ reg_where_dead_chain.
+ Use REG_WHERE_BORN instead of reg_where_born.
+ While processing the insns, build the reload_insn_chain with
+ information about register lifetimes.
+ (stupid_reg_compare): Use REG_WHERE_BORN instead of reg_where_born.
+ (stupid_mark_refs): Replace arg INSN with arg CHAIN. All callers
+ changed.
+ Compute and information about birth and death of pseudo registers in
+ reg_where_dead_chain, reg_where_born_exact and reg_where_born_clobber.
+ Delete code to set elements of reg_where_born.
+
+Mon Oct 5 22:34:30 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
+
+ * tree.def (GOTO_EXPR): Modified documentation.
+ * expr.c (expand_expr): Expand GOTO_EXPR into a goto or a computed
+ goto.
+
+Mon Oct 5 22:43:36 1998 David Edelsohn <edelsohn@gnu.org>
+
+ * unroll.c (loop_iteration_var, loop_initial_value, loop_increment
+ loop_final_value, loop_comparison_code): No longer static.
+ (unroll_loop): Delete loop_start_value update.
+ * loop.h (loop_iteration_var, loop_initial_value, loop_increment,
+ loop_final_value, loop_comparison_code): Extern.
+ (loop_start_value): Delete extern.
+ * loop.c (loop_can_insert_bct, loop_increment, loop_start_value,
+ loop_comparison_value, loop_comparison_code): Delete.
+ (loop_optimize): Remove initialization for deleted variables.
+ (strength_reduce): Delete analyze_loop_iterations call. Only call
+ insert_bct if flag_branch_count_on_reg set.
+ (analyze_loop_iterations): Delete.
+ (insert_bct): Remove iteration count calculation. Move checks for
+ viable BCT optimization to here. Obtain iteration count from
+ loop_iterations and correct for unrolling. Check for enough
+ iteration to be beneficial. Comment out runtime iteration count
+ case.
+ (insert_bct): Print iteration count in dump file. Remove
+ loop_var_mode and use word_mode directly.
-Fri Nov 21 19:37:40 1997 Andrew Cagney <cagney@b1.cygnus.com>
+ * rs6000.h (processor_type): Add PROCESSOR_PPC604e.
+ * rs6000.c (rs6000_override_options): Use it.
+ (optimization_options): Enable use of flag_branch_on_count_reg.
+ * rs6000.md (define_function_unit): Describe 604e.
- * config/mips/elf64.h (MULTILIB_DEFAULTS): Test for
- TARGET_ENDIAN_DEFAULT == zero instead of testing for macro
- definition.
+1998-10-05 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
-Fri Nov 21 12:49:56 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+ * loop.c (move_movables): Corrected threshold calculation for
+ moved_once registers.
- * stmt.c (expand_end_bindings): Allow jump into block with cleanups.
+Mon Oct 5 21:18:45 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
-Fri Nov 21 12:18:51 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * loop.c (combine_givs_p): Fix test for identical givs.
- * except.h: Add outer_context_label_stack.
- * except.c: Likewise.
- (expand_start_all_catch): Push the outer_context for the try block
- onto outer_context_label_stack.
- (expand_end_all_catch): Use it and pop it.
+Mon Oct 5 10:11:28 1998 Nick Clifton <nickc@cygnus.com>
-Fri Nov 21 10:13:11 1997 Robert Lipe (robertl@dgii.com)
+ * dwarf2out.c (gen_subprogram_die): If errorcount nonzero, don't
+ call abort if the function is already defined.
- * i386/sco5.h (HAVE_ATEXIT): Revert last change.
+Mon Oct 5 10:02:36 1998 Jeffrey A Law (law@cygnus.com)
-Thu Nov 20 16:11:50 1997 Richard Henderson <rth@cygnus.com>
+ * combine.c (simplify_rtx): Do not replace TRUNCATE with a SUBREG if
+ truncation is not a no-op.
- * alpha.c (alpha_emit_set_const_1): Handle narrow hosts better.
+Mon Oct 5 09:02:04 1998 Jeff Law (law@cygnus.com)
-Thu Nov 20 16:11:50 1997 Klaus Kaempf <kkaempf@progis.de>
+ * version.c: Bump for snapshot.
- * alpha/vms.h (ASM_OUTPUT_ADDR_VEC_ELT): Add an L for the local label
- to correspond with the change to ASM_GENERATE_INTERNAL_LABEL.
+Mon Oct 5 08:19:55 1998 Jeff Law (law@cygnus.com)
-Thu Nov 20 14:42:15 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * version.c: Bump for snapshot.
- * Makefile.in (LIB2FUNCS): Remove C++ memory management support.
- * libgcc2.c: Remove __builtin_new, __builtin_vec_new, set_new_handler,
- __builtin_delete, and __builtin_vec_delete.
+Mon Oct 5 01:07:23 1998 Torbjorn Granlund <tege@matematik.su.se>
- * except.c (output_exception_table): Don't bother with
- __EXCEPTION_END__.
+ * expmed.c (expand_divmod): Don't widen for computing remainder
+ if we seem to have a divmod pattern for needed mode.
-Thu Nov 20 16:11:50 1997 Jeffrey A Law (law@cygnus.com)
+Mon Oct 5 01:01:42 1998 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * pa.md (pre_stwm, post_stwm, pre_ldwm, post_ldwm): Base register
- is an in/out operand.
- (zero extended variants of stwm/stwm patterns): Similarly.
+ * cpplib.c (macroexpand): Correct off-by-one error in handling
+ of escapes.
- * mips/x-iris (FIXPROTO_DEFINES): Add -D_SGI_SOURCE.
+Sun Oct 4 23:58:30 1998 Richard Henderson <rth@cygnus.com>
-Thu Nov 20 13:19:32 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * combine.c (expand_field_assignment): Don't do bitwise operations
+ on MODE_FLOAT; pun to MODE_INT if possible.
- * dwarf2out.c (ASM_OUTPUT_DWARF_OFFSET4): Rename from VALUE4.
- Use assemble_name.
- (ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL): Use assemble_name.
- (output_call_frame_info): Emit a \n after using it.
+Sun Oct 4 18:33:24 1998 Jason Merrill <jason@yorick.cygnus.com>
+ scott snyder <snyder@d0sgif.fnal.gov>
-Thu Nov 20 00:38:46 1997 Dave Love <d.love@dl.ac.uk>
+ * tlink.c (scan_linker_output): Recognize errors from irix 6.2
+ linker. Recognize mangled names in quotes.
- * configure.in: Add AC_ARG_ENABLE for Haifa as documentation.
+Sun Oct 4 02:58:20 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
-Wed Nov 19 12:03:04 1997 Philippe De Muyter <phdm@macqel.be>
+ * config/sparc/sparc.md (ashldi3+1): Name it ashldi3_sp64.
+ (ashlsi3_const1, ashldi3_const1): New combiner patterns.
+ (ashrsi3_extend, ashrsi3_extend2): New combiner patterns.
+ (lshrsi3_extend, lshrsi3_extend2): Likewise.
- * dwarf2out.c (CIE_LENGTH_LABEL, FDE_LENGTH_LABEL): New macros.
- (ASM_OUTPUT_DWARF_VALUE4): New macro.
- (ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL): Define if SET_ASM_OP is
- defined.
- (output_call_frame_info): Do not output forward label differences
- if ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL is defined.
- * m68k/mot3300.h (SET_ASM_OP): Define when not using gas.
+Sun Oct 4 00:23:00 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Tue Nov 18 23:03:30 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * function.c (purge_addressof_1): If trying to take a sub-word
+ integral piece of a floating point mode, put it on the stack.
- * sh.md (attribute "type"): Add nil.
- (movsi_ie): y/y alternative is type nil.
- (movsf_ie): Replace ry/yr/X alternative by r/y/X , y/r/X and y/y/X
- alternatives.
- (movsf_ie+1): Delete.
+Sat Oct 3 19:01:03 1998 Richard Henderson <rth@cygnus.com>
-Tue Nov 18 15:39:59 1997 Jim Wilson <wilson@cygnus.com>
+ * alpha/linux.h (CPP_PREDEFINES): Define __alpha__ for imake.
- * mips/mips.c (save_restore_insns): If gp_offset or fp_offset are
- large_int, emit two insns instead of one splitable insn.
- * dwarf2out.c (dwarf2out_frame_debug): When set cfa_store_offset
- from cfa_temp_value, use cfa_offset. Add assert checking that
- cfa_reg is SP.
+Sat Oct 3 14:42:19 1998 Jason Merrill <jason@yorick.cygnus.com>
-Mon Nov 17 15:35:38 1997 Tom Tromey <tromey@cygnus.com>
+ * PROJECTS: Remove template friends.
- * cccp.c (deps_output): Properly quote file names for make.
+ * collect2.c (sort_ids): Remove unused variable.
-Mon Nov 17 13:21:40 1997 Jeffrey A Law (law@cygnus.com)
+ * tm.texi (MATH_LIBRARY): Document.
+ (NEED_MATH_LIBRARY): Remove.
- * t-h8300 (MULTILIB_EXCEPTIONS): Define.
+ * varasm.c (assemble_start_function, assemble_variable, weak_finish,
+ assemble_alias): Do ASM_GLOBALIZE_LABEL for weak symbols, too.
-Fri Nov 7 15:33:11 1997 Robert Lipe (robertl@dgii.com)
+Sat Oct 3 16:14:44 1998 John Carr <jfc@mit.edu>
- * i386/sco5.h (HAVE_ATEXIT): Delete definition.
+ * dwarf2out.c (expand_builtin_dwarf_reg_size): Initialize
+ last_end to 0x7fffffff.
-Sun Nov 16 23:52:48 1997 Jeffrey A Law (law@cygnus.com)
+Fri Oct 2 19:14:20 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * cse.c (cse_insn): Don't look at JUMP_LABEL field of a conditionl
- return.
- (cse_end_of_basic_block): Similarly.
+ * function.c (purge_addressof_1): Do not perform endianness
+ corrections on bitpos, who we call will do it for us.
-Sun Nov 16 23:01:40 1997 J. Kean Johnston <jkj@sco.com>
+Fri Oct 2 11:52:35 1998 Jeffrey A Law (law@cygnus.com)
- * i386/sco5.h (ASM_OUTPUT_ALIGNED_BSS): Define.
- (SELECT_RTX_SECTION): Define.
- (LIBGCC_SPEC, LIB_SPEC): Do the right thing for PIC.
+ * h8300.c (WORD_REG_USED): Fix typo.
+ (initial_offset): Use WORD_REG_USED.
-Sun Nov 16 22:47:03 1997 Manfred Hollstein <manfred@s-direktnet.de>
+ * h8300.c (handle_pragma): Fix typo.
- * Makefile.in (compare, compare-lean): Define $stage for each
- shell command.
- (gnucompare, gnucompare-lean): Likewise.
+Fri Oct 2 10:51:35 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
-Sun Nov 16 22:02:16 1997 Richard Henderson (rth@cygnus.com)
+ * caller-save.c (insert_save_restore): Break this function up
+ into new functions insert_restore, insert_save and insert_one_insn.
+ All callers changed.
+ (insert_restore): New function, mostly broken out of
+ insert_save_restore.
+ (insert_save): Likewise.
+ (insert_one_insn): Likewise.
+ (restore_referenced_regs): New argument BLOCK. All callers changed.
+ (save_call_clobbered_regs): Don't keep track of basic block boundaries
+ in this function, do it in insert_one_insn instead.
+
+ * reload1.c (reload): Break out some more pieces into separate
+ functions.
+ (dump_needs): New function, broken out of reload.
+ (set_initial_elim_offsets): Likewise.
+ (init_elim_table): Likewise.
+ (update_eliminables): Likewise.
+
+ * global.c (global_alloc): Delete code to manage the scratch_list.
+ * local-alloc.c (qty_scratch_rtx): Delete.
+ (scratch_block): Delete.
+ (scratch_list): Delete.
+ (scratch_list_length): Delete.
+ (scratch_index): Delete.
+ (alloc_qty_for_scratch): Delete.
+ (local-alloc): Update initialization of max_qty.
+ Delete code to manage the scratch list.
+ Delete code to allocate/initialize qty_scratch_rtx.
+ (block_alloc): Don't allocate quantities for scratches.
+ Delete code to manage the scratch list.
+ * regs.h (scratch_list): Delete declaration.
+ (scratch_block): Delete declaration.
+ (scratch_list_length): Delete declaration.
+ * reload1.c (reload): Delete code to manage the scratch list.
+ (spill_hard_reg): Likewise.
+ (mark_scratch_live): Delete.
+
+ * recog.c (alter_subreg): Delete declaration.
+
+1998-10-02 Andreas Jaeger <aj@arthur.rhein-neckar.de>
+
+ * Makefile.in (cccp.o): Fix typo in last patch.
+
+Fri Oct 2 16:13:12 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+
+ * t-sh (LIB1ASMFUNCS): Add _set_fpscr .
+ * config/sh/lib1funcs.asm (___set_fpscr): Add.
+
+Fri Oct 2 02:01:59 1998 Jeffrey A Law (law@cygnus.com)
- * alpha/win-nt.h (TRAMPOLINE_TEMPLATE): Fix offsets.
+ * regclass.c (reg_scan_mark_refs): Return immediately if passed a
+ NULL_RTX as an argument.
- * alpha.h (ASM_OUTPUT_ADDR_DIFF_ELT): Add an L for the local label
- to correspond with the change to ASM_GENERATE_INTERNAL_LABEL.
+ * Makefile.in (unlibsubdir): Define.
+ (DRIVER_DEFINES): Use unlibsubdir.
+ (cccp.o, cpplib.o, protoize.o, unprotoize.o): Similarly.
+ (stmp-fixinc): Similarly.
-Fri Nov 14 09:09:20 1997 Fred Fish (fnf@cygnus.com)
+Thu Oct 1 19:58:30 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
- * dwarfout.c (byte_size_attribute): Add local var upper_bound
- and add case to handle STRING_TYPE.
- * dwarfout.c (output_string_type_die): Fix code to generate
- correct string length attribute for fixed length strings.
- Still needs support for varying length strings.
+ * regmove.c (regmove_optimize): Add variable old_max_uid.
+ At the end of the function, update basic_block_end.
-Fri Nov 14 08:46:56 1997 Jeffrey A Law (law@cygnus.com)
+Thu Oct 1 17:58:25 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * toplev.c (get_run_time): Do something sensible for cygwin32.
+ * dwarf2out.c (expand_builtin_dwarf_reg_size): Use
+ FIRST_PSEUDO_REGISTER as upper bound for last_end, not an
+ arbitrary constant.
-Fri Nov 14 07:24:20 1997 Richard Henderson <rth@cygnus.com>
+Thu Oct 1 17:57:14 1998 Nick Clifton <nickc@cygnus.com>
- * expr.c (expand_builtin_setjmp): Set
- current_function_has_nonlocal_label.
- * stupid.c (stupid_life_analysis): If has_nonlocal_label, kill
- call-saved registers across calls.
+ * config/arm/arm.c: Improve interworking support.
- * alpha.md (exception_receiver): Remove.
- (nonlocal_goto_receiver_osf): New
- (nonlocal_goto_receiver_vms): Renamed from nonlocal_goto_receiver.
- (nonlocal_goto_receiver): New, select _osf or _vms.
+Thu Oct 1 18:43:35 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * alpha.c (output_prolog [*]): Prefix entry labels with '$' to
- keep them from being propogated to the object file.
- (alpha_write_linkage): Likewise.
- * alpha.md (call_vms): Likewise.
- (call_value_vms): Likewise.
- (unnamed osf call insns): Likewise.
+ * reload1.c (choose_reload_regs): Fix test if reload_reg_rtx[r] was
+ copied from reload_out[r] .
- * alpha.h (ASM_OUTPUT_INTERNAL_LABEL): Don't omit L from local label.
- (ASM_GENERATE_INTERNAL_LABEL): Likewise.
+Thu Oct 1 19:20:09 1998 John Carr <jfc@mit.edu>
- * alpha.c (call_operand): Any reg is valid for WinNT.
- * alpha.md (call_nt, call_value_nt): Don't force address into $27.
- (anon nt calls): Add 'R' alternative.
- * alpha/win-nt.h (TRAMPOLINE_TEMPLATE, TRAMPOLINE_SIZE,
- INITIALIZE_TRAMPOLINE): Handle lack of original $27 and 32-bit ptrs.
+ * dwarf2out.c (expand_builtin_dwarf_reg_size): Fix to work
+ with more than three size ranges.
-Fri Nov 14 06:59:33 1997 Jeffrey A Law (law@cygnus.com)
+ * flow.c (sbitmap_copy): Use bcopy to copy bitmap.
- * calls.c (expand_call): Handle pcc_struct_value correctly for C++.
+ * rtl.c (mode_name): Add a null string at the end of the array.
+ (mode_wider_mode): Change type to unsigned char.
+ (mode_mask_array): New variable.
+ (init_rtl): Update for mode_wider_mode type change.
- * i386/xm-cygwin32.h (HAVE_FILE_H, HAVE_RUSAGE): Delete defines.
- * i386/xm-mingw32.h (HAVE_FILE_H, HAVE_RUSAGE): Likewise.
- * rs6000/xm-cygwin32.h (HAVE_FILE_H, HAVE_RUSAGE): Likewise.
+ * rtl.h (mode_wider_mode): Change type to unsigned char.
+ (mode_mask_array): Declare.
+ (GET_MODE_MASK): Use mode_mask_array.
-Thu Nov 13 20:37:33 1997 Michael Meissner <meissner@tiktok.cygnus.com>
+Thu Oct 1 15:56:01 1998 Gavin Romig-Koch <gavin@cygnus.com>
- * reload1.c (new_spill_reg): Improve fixed or forbidden register
- spill error message.
+ * calls.c (expand_call) : Encapsulate code into
+ copy_blkmode_from_reg.
+ * expr.c (copy_blkmode_from_reg): New function.
+ * expr.h (copy_blkmode_from_reg): New function.
+ * integrate.c (function_cannot_inline_p): We can inline
+ these now.
+ (expand_inline_function): Use copy_blkmode_from_reg
+ if needed. Avoid creating BLKmode REGs.
+ (copy_rtx_and_substitute): Don't try to SUBREG a BLKmode
+ object.
-Thu Nov 13 20:29:08 1997 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Thu Oct 1 10:42:27 1998 Nick Clifton <nickc@cygnus.com>
- * prefix.c: Use stdarg.h only ifdef __STDC__. Otherwise,
- use varargs.h. Wrap header with <>, not "".
+ * config/v850/v850.c: Add function prototypes.
+ Add support for v850 special data areas.
-Thu Nov 13 20:21:17 1997 Jeffrey A Law (law@cygnus.com)
+ * config/v850/v850.h: Add support for v850 special data areas.
- * integrate.c (save_for_inline_copying): Add return value from
- savealloc.
+ * c-pragma.c: Add support for HANDLE_PRAGMA_PACK and
+ HANDLE_PRAGMA_PACK_PUSH_POP.
+ (push_alignment): New function: Cache an alignment requested
+ by a #pragma pack(push,<n>).
+ (pop_alignment): New function: Pop an alignment from the
+ alignment stack.
+ (insert_pack_attributes): New function: Generate __packed__
+ and __aligned__ attributes for new decls whilst a #pragma pack
+ is in effect.
+ (add_weak): New function: Cache a #pragma weak directive.
+ (handle_pragma_token): Document calling conventions. Add
+ support for #pragma pack(push,<n>) and #pragma pack (pop).
-Thu Nov 13 19:12:33 1997 Brendan Kehoe <brendan@cygnus.com>
+ * c-pragma.h: If HANDLE_SYSV_PRAGMA or HANDLE_PRAGMA_PACK_PUSH_POP
+ are defined enable HANDLE_PRAGMA_PACK.
+ Move 'struct weak_syms' here (from varasm.c).
+ Add pragma states for push and pop pragmas.
- * fixincludes: Be a little more restrictive on what we will
- substitute to replace definitions of MAXINT for HPUX.
+ * c-common.c (decl_attributes): Call PRAGMA_INSERT_ATTRIBUTES
+ if it is defined.
-Thu Nov 13 18:41:02 1997 Michael Meissner <meissner@cygnus.com>
+ * c-lex.c: Replace occurances of HANDLE_SYSV_PRAGMA with
+ HANDLE_GENERIC_PRAGMAS.
- * dbxout.c (dbxout_symbol_location): Don't assume that variables
- whose address is the stack or argument pointers are indirect
- pointers.
+ * varasm.c: Move definition of 'struct weak_syms' into
+ c-pragma.h.
+ (handle_pragma_weak): Deleted.
-1997-11-13 Paul Eggert <eggert@twinsun.com>
+ * config/i386/i386.h: Define HANDLE_PRAGMA_PACK_PUSH_POP.
- * cccp.c, cpplib.c (compare_defs):
- Don't complain about arg name respellings unless pedantic.
- * cpplib.c (compare_defs): Accept pfile as new arg.
- All callers changed.
+ * config/winnt/win-nt.h: Define HANDLE_PRAGMA_PACK_PUSH_POP.
-Thu Nov 13 23:33:50 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * c-decl.c (start_function): Add invocation of
+ SET_DEFAULT_DECL_ATTRIBUTES, if defined.
- * fold-const.c (fold_truthop): Fix bug in last change.
+ * tm.texi: Remove description of non-existent macro
+ SET_DEFAULT_SECTION_NAME.
-1997-11-13 Paul Eggert <eggert@twinsun.com>
+ (HANDLE_SYSV_PRAGMA): Document.
+ (HANDLE_PRAGMA_PACK_PUSH_POP): Document.
- Fix some confusion with IEEE minus zero.
+Wed Sep 30 22:27:53 1998 Robert Lipe <robertl@dgii.com>
- * real.h (REAL_VALUES_IDENTICAL): New macro.
+ * config.sub: Recognize i[34567]86-pc-udk as new target.
+ * configure.in: Likewise.
+ * config/i386/t-udk: New file.
+ * config/i386/udk.h: New file.
- * expr.c (is_zeros_p): Don't consider -0.0 to be all zeros.
- * fold-const.c (operand_equal_p): Don't consider -0.0 to be
- identical to 0.0.
- * tree.c (simple_cst_equal): Don't consider -0.0 to have the
- same tree structure as 0.0.
+Wed Sep 30 19:33:07 1998 Jeffrey A Law (law@cygnus.com)
- * varasm.c (immed_real_const_1): Use new REAL_VALUES_IDENTICAL
- macro instead of doing it by hand.
+ * reorg.c (check_annul_list_true_false): Remove unused variables.
+ (steal_delay_list_from_target): Add missing "used_annul" variable.
+ (try_merge_delay_insns): Close out half formed comment.
-Thu Nov 13 16:56:14 1997 Jeffrey A Law (law@cygnus.com)
+Wed Sep 30 19:13:20 1998 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * v850/lib1funcs.asm: Minor whitespace changes.
- * v850.c: Fix minor formatting problems in many places.
- (construct_restore_jr, construct_save_jarl): Remove unwanted aborts.
+ * cpplib.c (macroexpand): If arg->raw_before or
+ arg->raw_after, remove any no-reexpansion escape at the
+ beginning of the pasted token. Correct handling of whitespace
+ markers and no-reexpand markers at the end if arg->raw_after.
-Thu Nov 13 12:53:44 1997 Jim Wilson <wilson@cygnus.com>
+ * toplev.c (documented_lang_options): Recognize -include,
+ -imacros, -iwithprefix, -iwithprefixbefore.
+ * cpplib.c (cpp_start_read): Process -imacros and -include
+ switches at the same time and in command-line order, after
+ initializing the dependency-output code. Emit properly nested
+ #line directives for them. Emit a #line for the main file
+ before processing these switches, and don't do it again
+ afterward.
- * mips.h (GO_IF_LEGITIMATE_ADDRESS): Delete code swapping xplus0 and
- xplus1 when xplus0 is not a register.
+Wed Sep 30 18:03:22 1998 Richard Henderson <rth@cygnus.com>
-Thu Nov 13 11:41:42 1997 Jeffrey A Law (law@cygnus.com)
+ * function.c (purge_addressof_1): Use bitfield manipulation
+ routines to handle mem mode < reg mode.
- * flow.c (find_basic_blocks): During marking phase, if we encounter
- an insn with a REG_LABEL note, make the target block live and
- create an edge from the insn to the target block. Do not make
- edges from all blocks to the target block.
+Wed Sep 30 18:43:32 1998 Herman ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
- * m68k/x-next (OTHER_FIXINCLUDES_DIRS): Include /NextDeveloper/Headers.
+ * reorg.c (try_merge_delay_insns): Account for resources referenced
+ in each instruction in INSN's delay list before trying to eliminate
+ useless instructions. Similarly when looking at a trial insn's delay
+ slots.
- * confiugre.in: Tweak NCR entries.
- * configure: Rebuilt.
+ * reorg.c (check_annul_list_true_false): New function.
+ (steal_delay_list_from_{target,fallthrough}): Call it and also
+ refine tests for when we may annul if already filled a slot.
+ (fill_slots_from_thread): Likewise.
+ (delete_from_delay_slot): Return newly-created thread.
+ (try_merge_delay_isns): Use its new return value.
-Thu Nov 13 11:07:41 1997 Michael Meissner <meissner@cygnus.com>
+Wed Sep 30 18:29:26 1998 Jeffrey A Law (law@cygnus.com)
- * rs6000.c (num_insns_constant): Use REAL_VALUE_FROM_CONST_DOUBLE to
- pick apart floating point values, instead of using CONST_DOUBLE_LOW
- and CONST_DOUBLE_HIGH.
+ * loop.c (check_dbra_loop): Use a vanilla loop reversal if the biv is
+ used to compute a giv or as some other non-counting use.
- * rs6000.md (define_splits for DF constants): Use the appropriate
- REAL_VALUE_* interface to pick apart DF floating point constants in
- a machine independent fashion.
+Wed Sep 30 18:19:27 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Thu Nov 13 00:06:58 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * regs.h (HARD_REGNO_CALL_PART_CLOBBERED): New macro.
+ * local-alloc.c (find_free_reg): Use it.
+ * global.c (find_reg): Likewise.
+ * tm.texi: Document HARD_REGNO_CALL_PART_CLOBBERED.
- * fold-const.c (fold_truthop): When changing a one-bit comparison
- against zero into a comparison against mask, do a proper sign
- extension.
+ * regs.h (HARD_REGNO_CALLER_SAVE_MODE): New macro.
+ * caller-save.c (init_caller_save): Use it.
+ * tm.texi: Document HARD_REGNO_CALLER_SAVE_MODE.
-Wed Nov 12 09:37:01 1997 Jeffrey A Law (law@cygnus.com)
+Wed Sep 30 12:57:30 1998 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * except.c: Do not include "assert.h".
- (save_eh_status): Turn asserts into conditional aborts.
- (restore_eh_status, scan_region): Likewise.
- * dwarfout.c: Do not include "assert.h".
- (bit_offset_attribute): Turn asserts into conditional aborts.
- (bit_size_attribute, output_inlined_enumeration_type_die): Likewise.
- (output_inlined_structure_type_die): Likewise.
- (output_inlined_union_type_die): Likewise
- (output_tagged_type_instantiation): Likewise.
- (dwarfout_file_scope_decl): Likewise.
- * dwarf2out.c: Do not include "assert.h"
- (expand_builtin_dwarf_reg_size): Turn asserts into conditional aborts.
- (reg_save, initial_return_save, dwarf2out_frame_debug): Likewise.
- (add_child_die, modified_type_die, add_bit_offset_attribute): Likewise.
- (add_bit_size_attribute, scope_die_for): Likewise.
- (output_pending_types_for_scope): Likewise.
- (get_inlined_enumeration_type_die): Likewise.
- (get_inlined_structure_type_die): Likewise.
- (get_inlined_union_type_die, gen_subprogram_die): Likewise.
- (gen_tagged_type_instantiation_die): Likewise.
+ * configure.in: Add --enable-cpplib option which uses cpplib
+ for cpp, but doesn't link cpplib into cc1. Make help text
+ capitalization consistent.
+ * configure: Rebuilt.
- * flow.c (find_basic_blocks): Refine further to get a more correct
- cfg, especially in the presense of exception handling, computed
- gotos, and other non-trivial cases. Call abort if an inaccuracy
- is detected in the cfg.
+Wed Sep 30 10:09:39 1998 Mark Mitchell <mark@markmitchell.com>
-Tue Nov 11 21:47:27 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * function.c (gen_mem_addressof): If the address REG is
+ REG_USERVAR_P make the new REG be so also.
+ * loop.c (scan_loop): Apply DeMorgan's laws and add documentation
+ in an attempt to clarify slightly.
- * glimits.h (SHRT_MIN): Define in a way suitable for 16 bit hosts.
+Wed Sep 30 09:57:40 1998 Jeffrey A Law (law@cygnus.com)
- * c-lex.c (whitespace_cr, skip_white_space_on_line): New functions.
- (skip_white_space): Use whitespace_cr.
- (check_newline): Handle whitespace more consistently.
+ * expr.c (expand_expr): Handle COMPONENT_REF, BIT_FIELD_REF ARRAY_REF
+ and INDIRECT_REF in code to check MAX_INTEGER_COMPUTATION_MODE.
-Tue Nov 11 16:25:49 1997 Jim Wilson <wilson@cygnus.com>
+Wed Sep 30 10:13:39 1998 Catherine Moore <clm@cygnus.com>
- * i386/cygwin32.h (CPP_PREDEFINES): Delete -DPOSIX.
- * i386/xm-cygwin32.h (POSIX): Define.
+ * toplev.c: Fix last patch.
-Mon Nov 10 20:53:11 1997 Gavin Koch <gavin@cygnus.com>
+Tue Sep 29 20:03:18 1998 Jim Wilson <wilson@cygnus.com>
- * config/mips/mips.h (MASK_DEBUG_H): Set to zero, so this bit
- is available elsewhere.
+ * loop.c (get_condition): Fix typo in May 9 change.
-Mon Nov 10 16:21:58 1997 Doug Evans <devans@canuck.cygnus.com>
+Tue Sep 29 11:11:38 1998 Andrew MacLeod <amacleod@cygnus.com>
- * sparc/sparc.md (mov[sdt]f_const_insn): Fix condition to match
- what the instruction can handle.
+ * invoke.texi (-fexceptions): Merge 2 different descriptions.
-Mon Nov 10 03:02:19 1997 Jason Merrill <jason@yorick.cygnus.com>
+Mon Sep 28 22:08:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * stmt.c (expand_decl_cleanup_no_eh): New fn.
+ * toplev.c (documented_lang_options): Spelling corrections.
- * except.c (expand_leftover_cleanups): do_pending_stack_adjust.
+Mon Sep 28 19:41:24 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
-Mon Nov 10 00:05:56 1997 Jeffrey A Law (law@cygnus.com)
+ * configure.in: New flags --with-ld and --with-as, equivalent
+ to setting LD and AS environment variables. Test whether
+ specified arguments are GNU commands, and report them with
+ checking messages. Use the specified AS for configure
+ tests too.
+ * configure: Likewise.
+ * acconfig.h: Add DEFAULT_ASSEMBLER and DEFAULT_LINKER.
+ * config.in: Likewise.
+ * gcc.c (find_a_file): When looking for `as' and `ld', return
+ the DEFAULT program if it exists.
+ * collect2.c (main): Use DEFAULT_LINKER if it exists.
- * alias.c (MAX_ALIAS_LOOP_PASSES): Define.
- (init_alias_analysis): Break out of loops after MAX_ALIAS_LOOP_PASSES.
+ * gcc.c (find_a_file): The test for existence of a full
+ pathname was reversed.
-Sun Nov 9 14:34:47 1997 David Edelsohn <edelsohn@mhpcc.edu>
+Mon Sep 28 17:34:35 1998 Michael Meissner <meissner@cygnus.com>
- * rs6000.md (lshrdi3_power): Delete '&' from first alternative and
- swap instruction order.
+ * rs6000.h (ASM_OUTPUT_MI_THUNK): Only define on ELF systems.
+ * rs6000.c (output_mi_thunk): Always use a raw jump for now.
-Sun Nov 9 02:07:16 1997 Jeffrey A Law (law@cygnus.com)
+Mon Sep 28 14:24:03 1998 Mark Mitchell <mark@markmitchell.com>
- * fixinc.svr4 (__STDC__): Add another case.
+ * tree.h (TYPE_BINFO): Document.
-Sun Nov 9 02:00:29 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Sep 28 12:55:49 1998 Stan Cox <scox@cygnus.com>
- * a29k.h (ELIGIBLE_FOR_EPILOGUE_DELAY): Avoid loads from varying
- addresses in the epilogue delay slot.
+ * i386-coff.h (dbxcoff.h): Added.
-Sun Nov 9 01:40:40 1997 Manfred Hollstein (manfred@s-direktnet.de)
+Mon Sep 28 12:51:00 1998 Catherine Moore <clm@cygnus.com>
- * m88k/dgux.h (ASM_CPU_SPEC): Reformatted to suppress wrong whitespace
- in generated `specs' file.
+ * toplev.c: Fix bad patch around flag_data_sections.
-Sun Nov 9 01:37:11 1997 Jim Wilson (wilson@cygnus.com)
+Mon Sep 28 10:32:28 1998 Nick Clifton <nickc@cygnus.com>
- * flags.h (flag_rerun_loop_opt): Declare.
- * loop.c (invariant_p, case LABEL_REF): Check flag_rerun_loop_opt.
- * toplev.c (flag_rerum_loop_opt): Delete static.
+ * reload1.c (reload): Use reload_address_index_reg_class and
+ reload_address_base_reg_class when setting
+ caller_save_spill_class. (Patch generated by Jim Wilson:
+ wilson@cygnus.com).
-Sat Nov 8 18:20:21 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Sep 28 07:43:34 1998 Mark Mitchell <mark@markmitchell.com>
- Bring over from FSF:
+ * c-common.c (c_get_alias_set): Tighten slightly for FUNCTION_TYPEs
+ and ARRAY_TYPEs. Tidy up. Improve support for type-punning.
+ * expr.c (store_field): Add alias_set parameter. Set the
+ MEM_ALIAS_SET accordingly, if the target is a MEM.
+ (expand_assignment): Use it.
+ (store_constructor_field): Pass 0.
+ (expand_expr): Likewise.
- Thu Oct 30 12:21:06 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Sep 28 07:54:03 1998 Catherine Moore <clm@cygnus.com>
- * va-sh.h (__va_arg_sh1): Define.
- (va_arg): Use it.
- SH3E doesn't use any integer registers for subsequent arguments
- once a non-float value was passed in the stack.
- * sh.c (machine_dependent_reorg): If optimizing, put explicit
- alignment in front label for ADDR_DIFF_VEC.
- * sh.h (PASS_IN_REG_P): Fix SH3E case.
- (ADJUST_INSN_LENGTH): If not optimizing, add two extra bytes length.
+ * flags.h: Add flag_data_sections.
+ * toplev.c: Add option -fdata-sections. Add flag_data_sections.
+ (compile_file): Error if flag_data_sections not supported.
+ * varasm.c (assemble_variable): Handle flag_data_sections.
+ * config/svr4.h: Modify prefixes for UNIQUE_SECTION_NAME.
+ * config/mips/elf.h: Likewise.
+ * config/mips/elf64.h: Likewise.
+ * invoke.texi: Describe -fdata-sections.
- Tue Oct 28 15:06:44 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Sep 28 04:15:44 1998 Craig Burley <burley@melange.gnu.org>
- * sh/elf.h (PREFERRED_DEBUGGING_TYPE): Undefine before including
- svr4.h.
+ * invoke.texi (-ffloat-store): Clarify that this option
+ does not affect intermediate results -- only variables.
- Mon Oct 27 16:11:52 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Sep 28 04:11:35 1998 Jeffrey A Law (law@cygnus.com)
- * sh.c (machine_dependent_reorg): When -flag_delayed_branches,
- put an use_sfunc_addr before each sfunc.
- * sh.md (use_sfunc_addr, dummy_jump): New insns.
- (casesi): For TARGET_SH2, emit a dummy_jump after LAB.
+ * cpp.texi: Update for Fortran usage from Craig.
- Tue Oct 21 07:12:28 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Fri Sep 25 22:09:47 1998 David Edelsohn <edelsohn@gnu.org>
- * sh/elf.h (PREFERRED_DEBUGGING_TYPE): Don't redefine.
+ * rs6000.c (function_arg_boundary): Revert accidental change on
+ September 18.
-Fri Nov 7 10:22:24 1997 Jason Merrill <jason@yorick.cygnus.com>
+Fri Sep 25 20:30:00 1998 Michael Meissner <meissner@cygnus.com>
- * frame.c (add_fdes, count_fdes): Go back to checking pc_begin for
- linked once FDEs.
+ * rs6000.h (ASM_OUTPUT_MI_THUNK): Declare, call output_mi_thunk.
+ (output_mi_thunk): Declare.
-Wed Nov 5 14:26:05 1997 Jeffrey A Law (law@cygnus.com)
+ * rs6000.c (output_mi_thunk): Function to create thunks for MI.
+ (output_function_profiler): Use r12 for temp, instead of r11 so
+ that we preserve the static chain register.
- * alias.c (find_base_value): Only return the known base value for
- pseudo registers.
+Fri Sep 25 14:18:33 1998 Jim Wilson <wilson@cygnus.com>
-Wed Nov 5 11:27:14 1997 Jim Wilson <wilson@cygnus.com>
+ * sdbout.c (sdbout_one_type): Don't look at TYPE_BINFO field of enums.
- * i386.c (load_pic_register): Call prologue_get_pc_and_set_got.
- * i386.md (prologue_set_got, prologue_get_pc): Add UNSPEC_VOLATILE
- to pattern.
- (prologue_get_pc_and_set_got): New pattern.
+Fri Sep 25 19:30:19 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Tue Nov 4 20:36:50 1997 Richard Henderson (rth@cygnus.com)
+ * sh.c (gen_shl_sext): Fix case 5.
- * alpha.c (summarize_insn): Handle ASM_OPERANDS. Don't recurse
- for SUBREG, just fall through.
+Fri Sep 25 17:35:23 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * alpha.c (alpha_handle_trap_shadows): Init sum.defd to zero.
+ * reload1.c (reload_combine): Re-add line that got accidentally lost.
- * alpha.md (attr trap): Make TRAP_YES non-zero for sanity's sake.
+Fri Sep 25 10:43:47 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Tue Nov 4 18:49:42 1997 Jeffrey A Law (law@cygnus.com)
+ * cccp.c (pedwarn_with_file_and_line): For !__STDC__ case, avoid
+ accessing variables until they are initialized via va_arg().
- * fixincludes: Fix "hypot" prototype in NeXT math.h.
+Thu Sep 24 22:12:16 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * Makefile.in (USE_ALLOCA): Always include alloca.o.
- (USE_HOST_ALLOCA): Likewise.
+ * reload1.c (reload_combine): Initialize set before using.
- * rtl.def (CODE_LABEL): Use separate fields for LABEL_NUSES
- and LABEL_REFS fields.
- * rtl.h (LABEL_REFS): Update.
+Thu Sep 24 18:53:20 1998 Jason Merrill <jason@yorick.cygnus.com>
-Tue Nov 4 16:55:11 1997 Jim Wilson <wilson@cygnus.com>
+ * sdbout.c (sdbout_field_types): Don't emit the types of fields we
+ won't be emitting.
- * combine.c (try_combine): When setting elim_i2, check whether newi2pat
- sets i2dest. When calling distribute_notes for i3dest_killed, pass
- elim_i2 and elim_i1. When setting elim_i1, check if newi2pat
- sets i1dest.
+Thu Sep 24 17:05:30 1998 Nick Clifton <nickc@cygnus.com>
- * mips.md (insv, extzv, extv): Add change_address call.
- (movsi_ulw, movsi_usw): Change QImode to BLKmode in pattern.
+ * config/arm/arm.md (insv): Add comment. In CONST_INT case, and
+ operand3 with mask before using it. Patch provided by Jim Wilson.
- * integrate.c (save_for_inline_copying): Copy parm_reg_stack_loc.
+Thu Sep 24 15:08:08 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
- * reload.c (find_reloads, case 'm' and 'o'): Reject HIGH constants.
+ * config/sparc/sparc.c (function_value): Perform the equivalent of
+ PROMOTE_MODE for ARCH64.
+ (eligible_for_epilogue_delay): Allow DImode operations in delay
+ slot of a return for ARCH64.
- * mips.c (mips_expand_epilogue): Emit blockage insn before call to
- save_restore_insns if no FP and GP will be restored.
+Thu Sep 24 22:17:54 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * dwarf2out.c (expand_builtin_dwarf_reg_size): New variable mode.
- Convert CCmode to word_mode before calling GET_MODE_SIZE.
+ * sh.md (sqrtsf2): Fix mode of sqrt.
- * acconfig.h (HAVE_INTTYPES_H): Undef.
- * configure.in (inttypes.h): Check for conflicts between sys/types.h
- and inttypes.h, and verify that intmax_t is defined.
- * config/mips/x-iris (CC, OPT, OLDCC): Comment out.
- * config/mips/x-iris3: Likewise.
+Thu Sep 24 21:48:51 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Tue Nov 4 16:07:15 1997 Jeffrey A Law (law@cygnus.com)
+ * reload1.c (choose_reload_regs): Also try inheritance when
+ reload_in is a stack slot of a pseudo, even if we already got a
+ reload reg.
- * alias.c (find_base_value): When copying arguments, return the
- tenative value for a hard register.
+Thu Sep 24 21:22:39 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Tue Nov 4 13:40:35 1997 Doug Evans <devans@canuck.cygnus.com>
+ * reload1.c (reload_cse_regs_1): Renamed from reload_cse_regs.
+ (reload_cse_regs): New function body: call reload_cse_regs_1,
+ reload_combine, reload_cse_move2add.
+ When doing expensive_optimizations, call reload_cse_regs_1 a
+ second time after reload_cse_move2add.
+ (reload_combine, reload_combine_note_store): New functions.
+ (reload_combine_note_use): New function.
+ (reload_cse_move2add, move2add_note_store): New functions.
- * c-lex.c (MULTIBYTE_CHARS): #undef if cross compiling.
- (yylex): Record wide strings using target endianness, not host.
+Thu Sep 24 18:48:43 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Tue Nov 4 13:13:12 1997 Jeffrey A Law (law@cygnus.com)
+ * reload.c (find_reloads): In code to promote RELOAD_FOR_X_ADDR_ADDR
+ reloads to RELOAD_FOR_X_ADDRESS reloads, test for reload sharing.
- * mn10200.h (ASM_OUTPUT_BSS): Delete.
- (ASM_OUTPUT_ALIGNED_BSS): New macro
- * mn10300.h (ASM_OUTPUT_BSS): Delete.
- (ASM_OUTPUT_ALIGNED_BSS): New macro.
- * v850.h (ASM_OUTPUT_BSS): Delete.
- (ASM_OUTPUT_ALIGNED_BSS): New macro.
+ Properly keep track of first RELOAD_FOR_X_ADDRESS also for
+ more than 3 such reloads.
-Tue Nov 4 00:55:48 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ If there is not more than one RELOAD_FOR_X_ADDRESS, don't change
+ RELOAD_FOR_X_ADDR_ADDR reload.
- * profile.c (branch_prob): Insert an insn after a NOTE_INSN_SETJMP.
+Thu Sep 24 17:45:55 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Mon Nov 3 14:36:50 1997 Jeffrey A Law (law@cygnus.com)
+ * expr.c (store_constructor): When initializing a field that is smaller
+ than a word, at the start of a word, try to widen it to a full word.
- * configure.in (sco5): Use cpio to install header files.
+ * cse.c (cse_insn): When we are about to change a register,
+ remove any invalid references to it.
-Sun Nov 2 23:31:43 1997 Manfred Hollstein <manfred@s-direktnet.de>
+ (remove_invalid_subreg_refs): New function.
+ (mention_regs): Special treatment for SUBREGs.
+ (insert_regs): Don't strip SUBREG for call to mention_regs.
+ Check if reg_tick needs to be bumped up before that call.
+ (lookup_as_function): Try to match known word_mode constants when
+ looking for a norrower constant.
+ (canon_hash): Special treatment for SUBREGs.
- * aclocal.m4 (conftestdata_from, conftestdata_to): Names shortened to
- 14 char length.
- * configure: Rebuild.
+Thu Sep 24 01:35:34 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Sun Nov 2 19:44:00 1997 Robert Lipe (robertl@dgii.com)
+ * config/sparc/sol2-sld-64.h (TRANSFER_FROM_TRAMPOLINE): Define.
+ * config/sparc/sparc.c (sparc64_initialize_trampoline): If that is
+ defined, emit libcall to __enable_execute_stack. Also fix opcodes
+ and offsets in actual stack trampoline code so they match the
+ commentary and actually work.
- * i386/sco5.h: enable -gstabs once again.
+Thu Sep 24 01:19:02 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
-Sun Nov 2 19:27:21 1997 Jeffrey A Law (law@cygnus.com)
+ * configure.in (sparcv9-*-solaris): Use t-sol2 and t-sol2-64 for
+ tmake_file.
+ (sparc64-*-linux): Use t-linux and sparc/t-linux64 for
+ tmake_file. Set extra_parts to needed crt objects.
+ * configure: Rebuilt.
+ * config/sparc/linux64.h (SPARC_BI_ARCH): Define.
+ (TARGET_DEFAULT): Set if default is v9 or ultra.
+ (STARTFILE_SPEC32, STARTFILE_SPEC64): New macros.
+ (STARTFILE_SPEC): Set to those upon SPARC_BI_ARCH.
+ (ENDFILE_SPEC32, ENDFILE_SPEC64, ENDFILE_SPEC): Likewise.
+ (SUBTARGET_EXTRA_SPECS, LINK_ARCH32_SPEC, LINK_ARCH64_SPEC,
+ LINK_SPEC, LINK_ARCH_SPEC): Likewise.
+ (TARGET_VERSION): Define.
+ (MULTILIB_DEFAULT): Define.
+ * config/sparc/sparc.h (CPP_CPU_DEFAULT_SPEC): Rearrange so that
+ mixed 32/64 bit compilers based upon SPARC_BI_ARCH work.
+ (CPP_CPU64_DEFAULT_SPEC, CPP_CPU32_DEFAULT_SEC): Define
+ appropriately.
+ (TARGET_SWITCHES): Allow ptr32/ptr64 options once more.
+ * config/sparc/sparc.c (sparc_override_options): If arch and
+ pointer size disagree, emit diagnostic and fix it up. If
+ SPARC_BI_ARCH and TARGET_ARCH32, set cmodel to CM_32. Turn off
+ V8PLUS in 64-bit mode.
+ * config/sparc/t-linux64: New file.
+ * config/sparc/t-sol2-64: New file.
+ * config/sparc/t-sol2: Adjust build rules to use MULTILIB_CFLAGS.
+ * config/sparc/sol2-sld-64.h (SPARC_BI_ARCH): Define.
+ (ASM_CPU32_DEFAULT_SPEC, ASM_CPU64_DEFAULT_SPEC,
+ CPP_CPU32_DEFAULT_SPEC, CPP_CPU64_DEFAULT_SPEC): Define.
+ (ASM_SPEC, CPP_CPU_SPEC): Set appropriately based upon those.
+ (STARTFILE_SPEC32, STARTFILE_SPEC32, STARTFILE_ARCH_SPEC):
+ Define.
+ (STARTFILE_SPEC): Set appropriately based upon those.
+ (CPP_CPU_DEFAULT_SPEC, ASM_CPU_DEFAULT_SPEC): Set based upon
+ disposition of DEFAULT_ARCH32_P.
+ (LINK_ARCH32_SPEC, LINK_ARCH64_SPEC): Define.
+ (LINK_ARCH_SPEC, LINK_ARCH_DEFAULT_SPEC): Set based upon those.
+ (CC1_SPEC, MULTILIB_DEFAULTS): Set based upon DEFAULT_ARCH32_P.
+ (MD_STARTFILE_PREFIX): Set correctly based upon SPARC_BI_ARCH.
+ * config/sparc/xm-sysv4-64.h (HOST_BITS_PER_LONG): Only set on
+ arch64/v9.
+ * config/sparc/xm-sp64.h (HOST_BITS_PER_LONG): Likewise.
- * arm.c (output_move_double): Allocate 3 entries in otherops array.
+Wed Sep 23 22:32:31 1998 Mark Mitchell <mark@markmitchell.com>
-Sat Nov 1 21:43:00 1997 Mike Stump (mrs@wrs.com)
+ * rtl.h (init_virtual_regs): New function.
+ * emit-rtl.c (init_virtual_regs): Define.
+ (insn_emit): Use it.
+ * integrate.c (save_for_inline_copying): Likewise.
- * except.c (expand_ex_region_start_for_decl): Emit EH_REGION_BEG
- notes for sjlj exceptions too.
- (expand_eh_region_end): Similarly for EH_REGION_END notes.
- (exception_optimize): Optimize EH regions for sjlj exceptions too.
- * final.c (final_scan_insn): Don't output labels for EH REGION
- notes if doing sjlj exceptions.
+Wed Sep 23 16:22:01 1998 Nick Clifton <nickc@cygnus.com>
-Sat Nov 1 19:15:28 1997 Jeffrey A Law (law@cygnus.com)
+ * config/arm/thumb.h: The following patches were made by Jim Wilson:
+ (enum reg_class): Add NONARG_LO_REGS support.
+ (REG_CLASS_NAMES, REG_CLASS_CONTENTS, REGNO_REG_CLASS,
+ PREFERRED_RELOAD_CLASS, SECONDARY_RELOAD_CLASS): Likewise.
+ (GO_IF_LEGITIMATE_ADDRESS): Disable REG+REG addresses before reload
+ completes. Re-enable HImode REG+OFFSET addresses.
+ (LEGITIMIZE_RELOAD_ADDRESS): Define.
- * alias.c (init_alias_analysis): Handle -fno-alias-check when
- optimizing correctly.
+ * expmed.c (extract_bit_field): Add comment from Jim Wilson.
- * expr.c (expand_builtin_setjmp): Don't emit a SETJMP note
- or set current_function_calls_setjmp anymore.
+Wed Sep 23 13:26:02 1998 Richard Henderson <rth@cygnus.com>
- * flow.c (find_basic_blocks): If we delete the label for an
- exception handler, remove it from the EH label list and remove
- the EH_BEGIN/EH_END notes for that EH region.
+ * alpha.c (get_aligned_mem): Revert Sep 20 change.
+ (alpha_set_memflags, alpha_set_memflags_1): Likewise.
+ (alpha_align_insns): Properly calculate initial offset wrt max_align.
-Sat Nov 1 16:44:49 1997 Jason Merrill (jason@cygnus.com)
+Wed Sep 23 10:45:44 1998 Richard Earnshaw (rearnsha@arm.com)
- * flow.c (find_basic_blocks): Generate correct flow control
- information when exception handling notes are present.
+ * arm.c (find_barrier): Revert change of Apr 23. Handle table
+ jumps as a single entity, taking into account the size of the
+ table.
-Sat Nov 1 13:42:19 1997 Jeffrey A Law (law@cygnus.com)
+Tue Sep 22 15:13:34 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
- * dwarf2out.c (output_call_frame_info): Fix length argument
- to ASM_OUTPUT_ASCII.
- (output_die, output_pubnames, output_line_info): Likewise.
+ * tree.def (SWITCH_EXPR): New tree node definition.
+
+Mon Sep 21 23:40:38 1998 Jeff Law (law@cygnus.com)
+
+ * version.c: Bump for snapshot.
-Fri Oct 31 07:10:09 1997 Jeffrey A Law (law@cygnus.com)
+Mon Sep 21 22:31:14 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
- * dwarf2out.c (output_call_frame_info): Use ASM_OUTPUT_ASCII to
- output ASCII by default. Only use ASM_OUTPUT_DWARF_STRING if
- flag_debug_asm is on.
- (output_die, output_pubnames, output_line_info): Likewise.
+Mon Sep 21 22:48:09 1998 Jeffrey A Law (law@cygnus.com)
- * alias.c (init_alias_analysis): Add struct_value_incoming_rtx
- and static_chain_rtx into the potential base values array if
- they are registers.
+ * configure.in: Recognize i[34567]86-*-openbsd* and handle it like
+ NetBSD.
- * alias.c (new_reg_base_value): New array of potential base values.
- (unique_id): Now file scoped static.
- (find_base_value, case REG): Return the value in reg_base_value
- array for the REG if it exists. Else, return the value from
- new_reg_base_value if copying args and REG is a hard register.
- (find_base_value, case PLUS): If either operand of the PLUS is
- a REG, try to get its base value. Handle base + index and
- index + base.
- (record_set): Use new_reg_base_value instead of reg_base_value.
- (init_alias_analysis): Allocate space for new_reg_base_value too.
- Rework code to iterate over the insns propagating base value
- information until nothing changes.
+Mon Sep 21 22:05:28 1998 Jeffrey A Law (law@cygnus.com)
+
+ * Revert this patch.
+ * reload.c (find_reloads): Do not replace a pseudo with
+ (MEM (reg_equiv_addr)) in the initializing insn for the
+ pseudo.
+
+Mon Sep 21 20:19:41 1998 John Carr <jfc@mit.edu>
+
+ * final.c (final_scan_insn): Disable tracking CC across branches.
+
+Mon Sep 21 17:15:26 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * expr.h (eh_rtime_match_libfunc): New extern declaration.
+ * optabs.c (init_optabs): Set eh_rtime_match_libfunc.
+ * except.c (start_catch_handler): Use eh_rtime_match_libfunc.
+ * libgcc2.c (__eh_rtime_match): Always return 0 if the matcher is
+ NULL. Only include <stdio.h> if inhibit_libc is not defined.
+
+Mon Sep 21 14:10:51 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * toplev.c (rest_of_compilation): Skip compiling anything with
+ DECL_EXTERNAL set, not just if it has DECL_INLINE as well.
+
+Mon Sep 21 13:51:05 1998 Jim Wilson <wilson@cygnus.com>
+
+ * flow.c (find_basic_blocks): Delete check for in_libcall_block when
+ prev_code is a CALL_INSN. Change check for REG_RETVAL note to
+ use in_libcall_block.
+ (find_basic_blocks_1): Delete check for in_libcall_block when prev_code
+ is a CALL_INSN. If CALL_INSN and in_libcall_block, then change code
+ to INSN.
+
+Mon Sep 21 14:02:23 1998 Robert Lipe <robertl@dgii.com>
+
+ * i386.h (TARGET_SWITCHES): Improve doc for align-double. Fix
+ typo in no-fancy-math-387 description.
+
+Mon Sep 21 09:27:18 1998 Jeff Law (law@cygnus.com)
+
+ * version.c: Bump for snapshot.
- * global.c (global_alloc): Free the conflict matrix after
- reload has finished.
+Mon Sep 21 09:24:49 1998 Stan Cox <scox@cygnus.com>
-Fri Oct 31 01:45:31 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * i386-coff.h (DBX_DEBUGGING_INFO): Added.
- * libgcc2.c (L_eh): Define __eh_pc.
- Replace __eh_type with generic pointer __eh_info.
+Mon Sep 21 09:14:49 1998 Robert Lipe <robertl@dgii.com>
-Fri Oct 31 00:34:55 1996 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * i386.h (TARGET_SWITCHES): Add description fields for flags
+ documented in install.texi.
+ (TARGET_OPTIONS): Likewise.
- * expr.c (expand_increment): When enqueing a postincrement for a MEM,
- use copy_to_reg if address is not a general_operand.
+Mon Sep 21 01:39:03 1998 Jeff Law (law@cygnus.com)
-Fri Oct 31 00:16:55 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * version.c: Bump for snapshot.
- * profile.c (output_func_start_profiler): Clear flag_inline_functions
- for the duration of the call to rest_of_compilation.
+Mon Sep 21 01:53:05 1998 Felix Lee <flee@cygnus.com>
-Thu Oct 30 14:40:10 1997 Doug Evans <devans@canuck.cygnus.com>
+ * c-lex.c (init_lex): Use getenv ("LANG"), not GET_ENVIRONMENT ().
+ * cccp.c (main): Likewise.
- * configure.in (sparc-*-elf*): Use sparc/elf.h, sparc/t-elf.
- Set extra_parts.
- (sparc*-*-*): Recognize --with-cpu=v9.
- * sparc/elf.h: New file.
- * sparc/t-elf: New file.
+ * cccp.c, collect2.c, cpplib.c, gcc.c, config/i386/xm-cygwin32.h:
+ Rename GET_ENVIRONMENT to GET_ENV_PATH_LIST, and fix some
+ macro-use bugs.
-Thu Oct 30 13:26:12 1997 Jeffrey A Law (law@cygnus.com)
+Mon Sep 21 00:52:12 1998 Per Bothner <bothner@cygnus.com>
- * mn10300.c (const_8bit_operand): New function.
- (mask_ok_for_mem_btst): New funtion.
- * mn10300.md (btst patterns with mem operands): Use new functions
- to avoid creating btst instructions with invalid operands.
+ * Makefile.in (LIBS): Link in libiberty.a.
+ * c-common.c, gcc.c, toplev.c: Replace (some) bcopy calls by memcpy.
-Wed Oct 29 16:57:19 1997 Michael Meissner <meissner@cygnus.com>
+Sun Sep 20 23:28:11 1998 Richard Henderson <rth@cygnus.com>
- * rs6000/xm-sysv4.h: Include xm-linux.h instead of xm-svr4.h if we
- are running on PowerPC Linux.
+ * reload1.c (emit_reload_insns): Accept a new arg for the bb. Use
+ it to update bb boundaries. Update caller.
+ * function.c (reposition_prologue_and_epilogue_notes): Update
+ bb boundaries wrt the moved note.
-Wed Oct 29 13:10:11 1997 Gavin Koch <gavin@cygnus.com>
+Sun Sep 20 20:57:02 1998 Robert Lipe <robertl@dgii.com>
- * config/mips/elf64.h (PREFERRED_DEBUGGING_TYPE): Only define
- if not previously defined.
+ * configure.in (i*86-*-sysv5*): Use fixinc.svr4 to patch byteorder
+ problems.
+ * configure: Regenerate.
-Tue Oct 28 23:55:27 1997 Doug Evans (devans@cygnus.com)
+Sun Sep 20 19:01:51 1998 Richard Henderson <rth@cygnus.com>
- * function.c (assign_parms): Correct mode of stack_parm if
- entry_parm underwent a mode conversion.
+ * alpha.c (alpha_sr_alias_set): New variable.
+ (override_options): Set it.
+ (alpha_expand_prologue, alpha_expand_epilogue): Use it.
+ (mode_mask_operand): Fix signed-unsigned comparison warning.
+ (alpha_expand_block_move): Likewise.
+ (print_operand): Likewise.
+ (get_aligned_mem): Use change_address.
+ (alpha_set_memflags, alpha_set_memflags_1): Set the alias set.
+ (alphaev4_insn_pipe, alphaev4_next_group): New functions.
+ (alphaev4_next_nop, alphaev5_next_nop): New functions.
+ (alpha_align_insns): Remade from old alphaev5_align_insns
+ to handle multiple processors.
+ (alpha_reorg): Call alpha_align_insns for both ev4 and ev5.
+ * output.h (label_to_alignment): Prototype.
-1997-10-28 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * tree.c (new_alias_set): New function.
+ * tree.h (new_alias_set): Declare it.
+ * c-common.c (c_get_alias_set): Use it.
- * global.c (global_alloc): Use xmalloc instead of alloca for
- CONFLICTS, since max_allocno * allocno_row_words alone can be more
- than 2.5Mb sometimes.
+Sun Sep 20 12:35:55 1998 Richard Henderson <rth@cygnus.com>
-Tue Oct 28 15:29:15 1997 Richard Henderson <rth@cygnus.com>
+ * fold-const.c (fold): Yet another COND_EXPR bug: when folding
+ to an ABS expr, convert an unsigned input to signed.
- * reload1.c (eliminate_regs [SET]): If [SUBREG] widened the mode of
- DEST for the spill, adjust mode of SRC to compensate.
+Sun Sep 20 12:14:45 1998 Jeffrey A Law (law@cygnus.com)
-Tue Oct 28 14:36:45 1997 Richard Henderson <rth@cygnus.com>
+ * fold-const.c (fold): Fix another type in COND_EXPR handling code.
- * alpha.md (reload_inqi): Check for MEM before strict_memory_address_p,
- since any_memory_operand() allows pseudos during reload.
- (reload_inhi, reload_outqi, reload_outhi): Likewise.
+1998-09-20 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Tue Oct 28 11:53:14 1997 Jim Wilson <wilson@cygnus.com>
+ * configure.in: Add support for c4x targets.
+ * configure: Rebuilt.
- * m68k.md (btst patterns): Add 5200 support.
+Sun Sep 20 00:00:51 1998 Richard Henderson <rth@cygnus.com>
-Tue Oct 28 11:58:40 1997 Toon Moene <toon@moene.indiv.nluug.nl>
+ * combine.c (distribute_notes): If an insn is a cc0 user, only
+ delete it if we can also delete the cc0 setter.
- * fold-const.c (fold): For ((a * C1) / C3) or (((a * C1) + C2) / C3)
- optimizations, look inside dividend to determine if the expression
- can be simplified by using EXACT_DIV_EXPR.
+Sun Sep 20 00:22:23 1998 Michael Tiemann <michael@impact.tiemann.org>
-Tue Oct 28 10:19:01 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * fold-const.c (fold): Fix typo in COND_EXPR handling code.
+ (invert_truthvalue): Enable truthvalue inversion for
+ floating-point operands if -ffast-math.
- From Brendan:
- * dwarf2out.c (output_call_frame_info): Use l1 instead of ".".
+Sat Sep 19 23:58:07 1998 Melissa O'Neill <oneill@cs.sfu.ca>
-Tue Oct 28 00:32:14 1997 Richard Henderson <rth@cygnus.com>
+ * configure.in: Disable collect2 for nextstep. Instead use
+ crtbegin/crtend.
+ * configure: Rebuilt.
+ * config/nextstep.h (STARTFILE_SPEC): Add crtbegin.
+ (ENDFILE_SPEC): Define.
+ (OBJECT_FORMAT_MACHO): Define.
+ (EH_FRAME_SECTION_ASM_OP): Define.
+ * crtstuff.c: Handle MACHO.
- * alpha.c (summarize_insn [SUBREG]): Propogate SET.
+Sun Sep 20 00:24:24 1998 Robert Lipe <robertl@dgii.com>
-Mon Oct 27 23:59:26 1997 Richard Henderson <rth@cygnus.com>
+ * config/i386/sco5.h (TARGET_MEM_FUNCTIONS): Define.
- * alpha.c (alpha_handle_trap_shadows): Don't call get_attr_trap
- on a CLOBBER.
+1998-09-19 Torbjorn Granlund <tege@matematik.su.se>
-Mon Oct 27 21:25:20 1997 Richard Henderson <rth@cygnus.com>
+ * fp-bit.c (pack_d): Do not clear SIGN when fraction is 0.
+ (_fpadd_parts): Get sign right for 0.
- * alpha.md (movqi, movhi): Make sure new insns created during reload
- won't need reloading themselves.
- (reload_inqi, reload_inhi, reload_outqi, reload_outhi): Likewise.
+1998-09-19 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-Mon Oct 27 16:11:10 1997 Jeffrey A Law (law@cygnus.com)
+ * ginclude/varargs.h: Add support for C4x target.
+ * ginclude/stdargs.h: Likewise.
- * mn10300.h (GO_IF_LEGITIMATE_ADDRESS): Disable reg+reg.
+Sat Sep 19 12:05:09 1998 Richard Henderson <rth@cygnus.com>
-Sun Oct 26 13:50:44 1997 Richard Henderson <rth@cygnus.com>
+ * alpha.c (alpha_return_addr): SET should be VOIDmode.
+ (alpha_emit_set_long_const): Rewrite to be callable from reload
+ and 32-bit hosts.
+ (alpha_expand_epilogue): Update for alpha_emit_set_long_const.
+ * alpha.md (movdi): Likewise.
- * alpha.c (alpha_sa_mask [VMS]): Don't include $26 in the mask.
- Patch from Klaus Kaempf <kkaempf@progis.de>.
+Sat Sep 19 07:33:36 1998 Richard Earnshaw (rearnsha@arm.com)
-Sun Oct 26 13:31:47 1997 Jim Wilson (wilson@cygnus.com)
+ * arm.c (add_constant): New parameter address_only, change caller.
+ Set it non-zero if taking the address of an item in the pool.
+ (arm_reorg): Handle cases where we need the address of an item in
+ the pool.
- * expr.c (expand_expr, case INDIRECT_REF): Optimize a reference
- to an element in a constant string.
+ * arm.c (bad_signed_byte_operand): Check both arms of a sum in
+ a memory address.
+ * arm.md (splits for *extendqihi_insn and *extendqisi_insn): Handle
+ memory addresses that are not in standard canonical form.
-Sun Oct 26 11:41:49 1997 Jason Merrill <jason@yorick.cygnus.com>
+Sat Sep 19 01:00:32 1998 Michael Hayes (mph@elec.canterbury.ac.nz)
- * dwarf2out.c (output_call_frame_info): The CIE pointer is now a 32
- bit PC-relative offset. The exception range table pointer is now in
- the CIE.
- * frame.c (dwarf_cie, dwarf_fde): Rename CIE_pointer to CIE_delta.
- (count_fdes, add_fdes, get_cie): Adjust.
- (cie_info, extract_cie_info, __frame_state_for): Adjust eh_ptr uses.
+ * README.C4X: New file with information about the c4x ports.
+ * ginclude/va-c4x.h: New file for c4x varargs support.
+ * config/c4x: New directory with c4x port files.
- From H.J. Lu:
- * frame.c (count_fdes, add_fdes): Skip linked once FDE entries.
+Fri Sep 18 22:52:05 1998 Jeffrey A Law (law@cygnus.com)
-Sun Oct 26 11:52:01 1997 Richard Henderson <rth@cygnus.com>
+ * reload.c (find_reloads): Do not replace a pseudo with
+ (MEM (reg_equiv_addr)) in the initializing insn for the
+ pseudo.
- * alias.c (memrefs_conflict_p): Treat arg_pointer_rtx just
- like stack_pointer_rtx.
+Fri Sep 18 23:50:56 1998 David Edelsohn <edelsohn@gnu.org>
-Sun Oct 26 11:32:16 1997 Manfred Hollstein <manfred@s-direktnet.de>
+ * toplev.c (rest_of_compilation): Set bct_p on second call to
+ loop_optimize.
+ * loop.c (loop_optimize, scan_loop, strength_reduce): New argument
+ bct_p.
+ (strength_reduce): Only call analyze_loop_iterations and
+ insert_bct if bct_p set.
+ (check_dbra_loop): Fix typo.
+ (insert_bct): Use word_mode instead of SImode.
+ (instrument_loop_bct): Likewise. Do not delete iteration count
+ condition code generation insn. Initialize iteration count before
+ loop start.
+ * rtl.h (loop_optimize): Update prototype.
- * Makefile.in (bootstrap-lean): Combined with `normal' bootstrap
- targets using "$@" to provide support for similar but not identical
- targets without having to duplicate code.
- (bootstrap4): New goal.
+ * ginclude/va-ppc.h (va_arg): longlong types in overflow area are
+ not doubleword aligned.
- * Makefile.in (compare, compare-lean, compare3): Combined to one
- ruleset determining actions to be performed via $@.
- (compare4, compare4-lean): New targets.
- (gnucompare, gnucompare3): Combined to one ruleset determining
- actions to be performed via $@. Also, note which files failed
- the comparison test in .bad_compare.
- (gnucompare-lean, gnucompare3-lean, gnucompare4-lean): New targets.
+ * rs6000.c (optimization_options): New function.
+ (secondary_reload_class): Only call true_regnum for PSEUDO_REGs.
+ * rs6000.h (OPTIMIZATION_OPTIONS): Define.
+ (REG_ALLOC_ORDER): Allocate highest numbered condition regsiters
+ first; cr1 can be used for FP record condition insns.
-Sun Oct 26 10:06:11 1997 Toon Moene <toon@moene.indiv.nluug.nl>
+Fri Sep 18 09:44:55 1998 Nick Clifton <nickc@cygnus.com>
- * fold-const (fold): Also simplify FLOOR_DIV_EXPR to EXACT_DIV_EXPR
- if the dividend is a multiple of the divisor.
+ * config/m32r/m32r.h (m32r_block_immediate_operand): Add to
+ PREDICATE_CODES.
-Sun Oct 26 09:21:40 1997 Jeffrey A Law (law@cygnus.com)
+ * config/m32r/m32r.md: Add "movstrsi" and "movstrsi_internal"
+ patterns.
- * Makefile.in (LIBGCC2_CFLAGS): Add -fexceptions.
+ * config/m32r/m32r.c (m32r_print_operand): Add 's' and 'p'
+ operators.
+ (block_move_call): New function: Call a library routine to copy a
+ block of memory.
+ (m32r_expand_block_move): New function: Expand a "movstrsi"
+ pattern into a sequence of insns.
+ (m32r_output_block_move): New function: Expand a
+ "movstrsi_internal" pattern into a sequence of assembler opcodes.
+ (m32r_block_immediate_operand): New function: Return true if the
+ RTL is an integer constant, less than or equal to MAX_MOVE_BYTES.
- * alias.c (find_base_term): Handle PRE_INC, PRE_DEC, POST_INC,
- and POS_DEC.
+Thu Sep 17 16:42:16 1998 Andrew MacLeod <amacleod@cygnus.com>
- * alias.c (true_dependence): Fix typo.
+ * except.c (start_catch_handler): Issue 'fatal' instead of 'error' and
+ re-align some code.
+ * libgcc2.c (__eh_rtime_match): fprintf a runtime error. Use <stdio.h>.
- * toplev.c (flag_rerun_loop_opt): New variable.
- (f_options): Handle -frerun-loop-opt.
- (rest_of_compilation): If -frerun-loop-opt, then run the loop
- optimizer twice.
- (main): Enable -frerun-loop-opt by default for -O2 or greater.
+Thu Sep 17 12:24:33 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * loop.c (simplify_giv_expr): Adding two invariants results
- in an invariant.
+ * regmove.c (copy_src_to_dest): Check that modes match.
-Sun Oct 26 09:15:15 1997 Richard Henderson <rth@cygnus.com>
+Wed Sep 16 22:10:42 1998 Robert Lipe <robertl@dgii.com>
- * expr.c (get_inner_reference): Remove the array bias after
- converting the index to Pmode.
+ * config/i386/sco5.h (SUPPORTS_WEAK): True only if targeting ELF.
-Sat Oct 25 12:20:58 1997 Jeffrey A Law (law@cygnus.com)
+Wed Sep 16 15:24:54 1998 Richard Henderson <rth@cygnus.com>
- * mn10300.h (TARGET_SWITCHES): Add -mmult-bug and -mno-mult-bug.
- (TARGET_MULT_BUG): Define.
- (TARGET_DEFAULT): Default to TARGET_MULT_BUG.
- * mn10300.md (mulsi3): Handle TARGET_MULT_BUG.
+ * i386.h (PREFERRED_RELOAD_CLASS): Respect an existing class
+ narrower than FLOAT_REGS.
-Fri Oct 24 17:40:34 1997 Jeffrey A Law (law@cygnus.com)
+Wed Sep 16 17:51:00 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
- * mn10200.c (indirect_memory_operand): Delete unused function.
- * mn10200.h (EXTRA_CONSTRAINT): Handle 'R'.
- * mn10200.md (bset, bclr insns): Handle output in a reg too.
+ * cpplib.c: Removed OLD_GPLUSPLUS_INCLUDE_DIR.
+ * cccp.c: Likewise.
+ * Makefile.in (old_gxx_include_dir): Removed.
-Fri Oct 24 15:54:57 1997 Richard Henderson <rth@cygnus.com>
+Wed Sep 16 12:29:22 1998 Nick Clifton <nickc@cygnus.com>
- * alpha.md (call patterns): Revert Oct 16 change; if we are to elide
- the callee's ldgp, we must do it ourselves, and we use the jsr tag
- for more than scheduling.
+ * config/sh/sh.h: Update definition of HANDLE_PRAGMA to match
+ new specification.
-Fri Oct 24 13:23:04 1997 Doug Evans <devans@canuck.cygnus.com>
+ * config/sh/sh.c (handle_pragma): Rename to sh_handle_pragma().
+ (sh_handle_pragma): Change function arguments to match new
+ specification for HANDLE_PRAGMA.
- * sparc/sparc.h (ASM_SPEC): Delete asm_arch.
+Wed Sep 16 12:43:19 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Fri Oct 24 13:19:40 1997 Jeffrey A Law (law@cygnus.com)
+ * gen-protos.c (parse_fn_proto): Cast argument of ISALNUM to
+ `unsigned char'.
+ (main): Mark parameter `argc' with ATTRIBUTE_UNUSED.
+ When generating output, initialize missing struct member to zero.
- * mn10300.c (symbolic_operand, legitimize_address): New functions.
- * mn10300.h (LEGITIMIZE_ADDRESS): Call legitimize_address.
- (GO_IF_LEGITIMATE_ADDRESS): Don't allow base + symbolic.
+Wed Sep 16 14:47:43 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Thu Oct 23 09:35:12 1997 Jeffrey A Law (law@cygnus.com)
+ * regmove.c (copy_src_to_dest): Don't copy if that requires
+ (a) new register(s).
- * version.c: Bump for snapshot.
+Wed Sep 16 01:29:12 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
-Thu Oct 23 08:03:59 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * global.c (reg_allocno): Now static.
+ * reload1.c (reg_allocno): Delete declaration.
+ (order_regs_for_reload): Take no arguments. Don't treat regs
+ allocated by global differently than those allocated by local-alloc.
- * dbxout.c (dbxout_start_new_source_file): Use output_quoted_string
- for FILENAME.
+Wed Sep 16 01:09:01 1998 Kamil Iskra <iskra@student.uci.agh.edu.pl>
-Wed Oct 22 00:34:12 1997 Jeffrey A Law (law@cygnus.com)
+ * m68k/m68k.c (output_function_prologue): Reverse NO_ADDSUB_Q
+ condition, fix format strings.
+ (output_function_epilogue): Likewise.
- * toplev.c (flag_exceptions): Default value is 2.
- (compile_file): If flag_exceptions still has the value 2, then
- set it to 0.
+ * m68k/m68k.c: Don't include <stdlib.h> directly.
- * rs6000.c (struct machine_function): Add pic_offset_table_rtx.
- (rs6000_save_machine_status): Save pic_offset_table_rtx.
- (rs6000_restore_machine_status: Restore pic_offset_table_rtx.
+Wed Sep 16 00:30:56 1998 Geoff Keating <geoffk@ozemail.com.au>
- * local-alloc.c (block_alloc): Don't lose if two SCRATCH expressions
- are shared.
+ * gcse.c: New definition NEVER_SET for reg_first_set, reg_last_set,
+ mem_first_set, mem_last_set; because 0 can be a CUID.
+ (oprs_unchanged_p): Use new definition.
+ (record_last_reg_set_info): Likewise.
+ (record_last_mem_set_info): Likewise.
+ (compute_hash_table): Likewise.
- * rs6000.md (*movsi_got_internal_mem): New pattern.
- (*movsi_got_internal_mem splitter): New define_split.
-
-Tue Oct 21 18:14:03 1997 Jim Wilson <wilson@cygnus.com>
-
- * obstack.h (obstack_empty_p): Fix spurious space after backslash.
-
-Tue Oct 21 18:34:01 1997 Geoffrey KEATING <geoffk@ozemail.com.au>
-
- * rs6000.c: Avoid creating a stack frame under SYSV ABI if we
- only need to save LR.
-
-Tue Oct 21 10:06:40 1997 Jeffrey A Law (law@cygnus.com)
-
- * mn10300.md (movqi, movhi): Avoid using address registers as
- destinations unless absolutely necessary.
-
- * mn10200.c (expand_prologue): Fix typo.
-
- * mn10200.h (GO_IF_LEGITIMATE_ADDRESS): Do not allow indexed
- addresses.
- * mn10200.md (neghi2): Provide an alternative which works if
- the input and output register are the same.
-
- * mn10300.c (print_operand): Handle 'S'.
- * mn10300.md (ashlsi3, lshrsi3, ashrsi3): Use %S for
- shift amount in last alternative
-
- * mn10300.c (expand_epilogue): Rework to handle register restores
- in "ret" and "retf" instructions correctly.
-
-Mon Oct 20 16:47:08 1997 Jim Wilson <wilson@cygnus.com>
-
- * expmed.c (extract_bit_field): Don't make flag_force_mem disable
- extzv for memory operands.
-
- * cse.c (simplify_ternary_operation, case IF_THEN_ELSE): Collapse
- redundant conditional moves to single operand.
-
-Mon Oct 20 15:30:26 1997 Nick Clifton <nickc@cygnus.com>
-
- * v850.h: Move define of __v850__ from CPP_PREDEFINES
- to CPP_SPEC.
-
- * xm-v850.h: Use __v850 rather than __v850__ to
- identify v850 port.
-
-Mon Oct 20 14:15:02 1997 Jim Wilson <wilson@cygnus.com>
-
- * mips/mips.c (compute_frame_size): Not a leaf function if
- profile_flag set.
-
-Mon Oct 20 14:16:38 1997 Geoffrey KEATING <geoffk@ozemail.com.au>
-
- * rs6000/t-ppccomm: Use -msdata=none for crtstuff.
-
-Mon Oct 20 12:28:17 1997 Doug Evans <devans@canuck.cygnus.com>
-
- * sparc/sparc.h (SPARC_V9,SPARC_ARCH64): Delete.
- (DEFAULT_ARCH32_P): New macro.
- (TARGET_ARCH{32,64}): Allow compile time or runtime selection.
- (enum cmodel): Declare.
- (sparc_cmodel_string,sparc_cmodel): Declare.
- (SPARC_DEFAULT_CMODEL): Provide default.
- (TARGET_{MEDLOW,MEDANY}): Renamed to TARGET_CM_{MEDLOW,MEDANY}.
- (TARGET_FULLANY): Deleted.
- (TARGET_CM_MEDMID): New macro.
- (CPP_CPU_DEFAULT_SPEC): Renamed from CPP_DEFAULT_SPEC.
- (ASM_CPU_DEFAULT_SPEC): Renamed from ASM_DEFAULT_SPEC.
- (CPP_PREDEFINES): Take out stuff now handled by %(cpp_arch).
- (CPP_SPEC): Rewrite.
- (CPP_ARCH{,32,64,_DEFAULT}_SPEC): New macros.
- (CPP_{ENDIAN,SUBTARGET}_SPEC): New macros.
- (ASM_ARCH{,32,64,_DEFAULT}_SPEC): New macros.
- (ASM_SPEC): Add %(asm_arch).
- (EXTRA_SPECS): Rename cpp_default to cpp_cpu_default.
- Rename asm_default to asm_cpu_default.
- Add cpp_arch32, cpp_arch64, cpp_arch_default, cpp_arch, cpp_endian,
- cpp_subtarget, asm_arch32, asm_arch64, asm_arch_default, asm_arch.
- (NO_BUILTIN_{PTRDIFF,SIZE}_TYPE): Define ifdef SPARC_BI_ARCH.
- ({PTRDIFF,SIZE}_TYPE): Provide 32 and 64 bit values.
- (MASK_INT64,MASK_LONG64): Delete.
- (MASK_ARCH64): Renamed to MASK_64BIT.
- (MASK_{MEDLOW,MEDANY,FULLANY,CODE_MODEL}): Delete.
- (EMBMEDANY_BASE_REG): Renamed from MEDANY_BASE_REG.
- (TARGET_SWITCHES): Always provide 64 bit options.
- (ARCH64_SWITCHES): Delete.
- (TARGET_OPTIONS): New option -mcmodel=.
- (INT_TYPE_SIZE): Always 32.
- (MAX_LONG_TYPE_SIZE): Define ifdef SPARC_BI_ARCH.
- (INIT_EXPANDERS): sparc64_init_expanders renamed to sparc_init_....
- (FUNCTION_{,BLOCK_}PROFILER): Delete TARGET_EMBMEDANY support.
- (PRINT_OPERAND_PUNCT_VALID_P): Add '_'.
- * sparc/linux-aout.h (CPP_PREDEFINES): Take out stuff handled by
- CPP_SPEC.
- (CPP_SUBTARGET_SPEC): Renamed from CPP_SPEC.
- * sparc/linux.h: Likewise.
- * sparc/linux64.h (SPARC_V9,SPARC_ARCH64): Delete.
- (ASM_CPU_DEFAULT_SPEC): Renamed from ASM_DEFAULT_SPEC.
- (TARGET_DEFAULT): Delete MASK_LONG64, MASK_MEDANY, add MASK_64BIT.
- (SPARC_DEFAULT_CMODEL): Define.
- (CPP_PREDEFINES): Take out stuff handled by CPP_SPEC.
- (CPP_SUBTARGET_SPEC): Renamed from CPP_SPEC.
- (LONG_DOUBLE_TYPE_SIZE): Define.
- (ASM_SPEC): Add %(asm_arch).
- * sparc/sol2.h (CPP_PREDEFINES): Take out stuff handled by CPP_SPEC.
- (CPP_SUBTARGET_SPEC): Renamed from CPP_SPEC.
- (TARGET_CPU_DEFAULT): Add ultrasparc case.
- * sparc/sp64-aout.h (SPARC_V9,SPARC_ARCH64): Delete.
- (TARGET_DEFAULT): MASK_ARCH64 renamed to MASK_64BIT.
- (SPARC_DEFAULT_CMODEL): Define.
- * sparc/sp64-elf.h (SPARC_V9,SPARC_ARCH64): Delete.
- (TARGET_DEFAULT): MASK_ARCH64 renamed to MASK_64BIT. Delete
- MASK_LONG64, MASK_MEDANY.
- (SPARC_DEFAULT_CMODEL): Define.
- (CPP_PREDEFINES): Delete.
- (CPP_SUBTARGET_SPEC): Renamed from CPP_SPEC.
- (ASM_SPEC): Add %(asm_arch).
- (LONG_DOUBLE_TYPE_SIZE): Define.
- (DWARF2_DEBUGGING_INFO): Define.
- * sparc/splet.h (CPP_SPEC): Delete.
- * sparc/sysv4.h (CPP_PREDEFINES): Take out stuff handled by CPP_SPEC.
- (FUNCTION_BLOCK_PROFILER): Delete TARGET_EMBMEDANY support.
- (BLOCK_PROFILER): Likewise.
- * sparc/sparc.c (sparc_cmodel_string,sparc_cmodel): New globals.
- (sparc_override_options): Handle code model selection.
- (sparc_init_expanders): Renamed from sparc64_init_expanders.
- * sparc/sparc.md: TARGET_<code_model> renamed to TARGET_CM_....
- TARGET_MEDANY renamed to TARGET_CM_EMBMEDANY.
- (sethi_di_embmedany_{data,text}): Renamed from sethi_di_medany_....
- (sethi_di_fullany): Delete.
-
-Mon Oct 20 02:00:18 1997 Klaus Kaempf <kkaempf@progis.de>
- Jeff Law <law@cygnus.com>
- Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+Tue Sep 15 22:59:52 1998 Jeffrey A Law (law@cygnus.com)
- * alpha/vms.h (DIVSI3_LIBCALL): OTS$ functions are upper case.
- (DIVDI3_LIBCALL, UDIVSI3_LIBCALL, UDIVDI3_LIBVALL): Likewise.
- (MODSI3_LIBCALL, MODDI3_LIBCALL): Likewise.
- (UMODSI3_LIBCALL, UMODDI3_LIBCALL): Likewise.
- * alpha/alpha.md (arg_home): Likewise.
+ * rs6000.c (output_epilogue): Handle Chill.
- * alpha/alpha.c (vmskrunch): Delete
- * alpha/vms.h (ENCODE_SECTION_INFO, ASM_DECLARE_FUNCTION_NAME): Delete.
- * alpha.c (output_prolog, VMS): Use alloca for entry_label and don't
- truncate to 64 characters.
+ * mn10200.h (ASM_OUTPUT_DWARF2_ADDR_CONST): Define.
+ * mn10300.h (ASM_OUTPUT_DWARF2_ADDR_CONST): Define.
- * make-l2.com: Support openVMS/Alpha.
+ * combine.c (make_extraction): If no mode is specified for
+ an operand of insv, extv, or extzv, default it to word_mode.
+ (simplify_comparison): Similarly.
+ * expmed.c (store_bit_field): Similarly.
+ (extract_bit_field): Similarly.
+ * function.c (fixup_var_regs_1): Similarly.
+ * recog.c (validate_replace_rtx_1): Similarly.
+ * mips.md (extv, extzv, insv expanders): Default modes for most
+ operands. Handle TARGET_64BIT.
+ (movdi_uld, movdi_usd): New patterns.
- * vmsconfig.com: Fix to work on openVMS/Alpha and openVMS/VAX.
+ * pa.c (emit_move_sequence): Do not replace a pseudo with its
+ equivalent memory location unless we have been provided a scratch
+ register. Similarly do not call find_replacement unless a
+ scratch register has been provided.
-Sun Oct 19 19:00:35 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Tue Sep 15 19:23:01 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * longlong.h (count_leading_zeros): Add missing casts to USItype.
+ * i386.h (PREFERRED_RELOAD_CLASS): For standard 387 constants,
+ return FLOAT_REGS.
-Sun Oct 19 18:44:06 1997 Jeffrey A Law (law@cygnus.com)
+Tue Sep 15 19:09:06 1998 Richard Henderson <rth@cygnus.com>
- * i386/bsd386.h (ASM_COMMENT_START): Define.
+ * tree.h (BUILT_IN_CALLER_RETURN_ADDRESS): Unused. Kill.
+ (BUILT_IN_FP, BUILT_IN_SP, BUILT_IN_SET_RETURN_ADDR_REG): Kill.
+ (BUILT_IN_EH_STUB_OLD, BUILT_IN_EH_STUB, BUILT_IN_SET_EH_REGS): Kill.
+ (BUILT_IN_EH_RETURN, BUILT_IN_DWARF_CFA): New.
+ * c-decl.c (init_decl_processing): Update accordingly.
+ * expr.c (expand_builtin): Likewise.
-Sat Oct 18 13:47:15 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * rtl.h (global_rtl): Add cfa entry.
+ (virtual_cfa_rtx, VIRTUAL_CFA_REGNUM): New.
+ (LAST_VIRTUAL_REGISTER): Update.
+ * emit-rtl.c (global_rtl): Add cfa entry.
+ (init_emit): Initialize it.
+ * function.c (cfa_offset): New.
+ (instantiate_virtual_regs): Initialize it.
+ (instantiate_virtual_regs_1): Instantiate virtual_cfa_rtx.
+ (expand_function_end): Call expand_eh_return.
+ * tm.texi (ARG_POINTER_CFA_OFFSET): New.
+
+ * except.c (current_function_eh_stub_label): Kill.
+ (current_function_eh_old_stub_label): Likwise; update all references.
+ (expand_builtin_set_return_addr_reg): Kill.
+ (expand_builtin_eh_stub_old, expand_builtin_eh_stub): Kill.
+ (expand_builtin_set_eh_regs): Kill.
+ (eh_regs): Produce a third reg for the actual handler address.
+ (eh_return_context, eh_return_stack_adjust): New.
+ (eh_return_handler, eh_return_stub_label): New.
+ (init_eh_for_function): Initialize them.
+ (expand_builtin_eh_return, expand_eh_return): New.
+ * except.h: Update prototypes.
+ * flow.c (find_basic_blocks_1): Update references to the stub label.
+ * function.h (struct function): Kill stub label elements.
+
+ * libgcc2.c (in_reg_window): For REG_SAVED_REG, check that the
+ register number is one that would be in the previous window.
+ Provide a dummy definition for non-windowed targets.
+ (get_reg_addr): New function.
+ (get_reg, put_reg, copy_reg): Use it.
+ (__throw): Rely on in_reg_window, not INCOMING_REGNO. Kill stub
+ generating code and use __builtin_eh_return. Use __builtin_dwarf_cfa.
+
+ * alpha.c (alpha_eh_epilogue_sp_ofs): New.
+ (alpha_init_expanders): Initialize it.
+ (alpha_expand_epilogue): Use it.
+ * alpha.h: Declare it.
+ * alpha.md (eh_epilogue): New.
+
+ * m68h.h (ARG_POINTER_CFA_OFFSET): New.
+ * sparc.h (ARG_POINTER_CFA_OFFSET): New.
+
+Tue Sep 15 19:31:58 1998 Michael Meissner <meissner@cygnus.com>
+
+ * i960.h (CONST_COSTS): Fix thinko. Test flag, not the constant
+ flag bit mask.
+
+Tue Sep 15 14:10:54 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * except.h (struct eh_entry): Add false_label field.
+ (end_catch_handler): Add prototype.
+ * except.c (push_eh_entry): Set false_label field to NULL_RTX.
+ (start_catch_handler): When using old style exceptions, issue
+ runtime typematch code before continuing with the handler.
+ (end_catch_handler): New function, generates label after handler
+ if needed by older style exceptions.
+ (expand_start_all_catch): No need to check for new style exceptions.
+ (output_exception_table_entry): Only output the first handler label
+ for old style exceptions.
+ * libgcc2.c (__eh_rtime_match): New routine to lump runtime matching
+ mechanism into one function, if a runtime matcher is provided.
+
+Tue Sep 15 13:53:59 1998 Andrew MacLeod <amacleod@cygnus.com>
+
+ * config/i960/i960.h (SLOW_BYTE_ACCESS): Change definition to 1.
+
+Tue Sep 15 09:59:01 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * integrate.c (copy_decl_list): Fix typo.
+
+Tue Sep 15 04:18:52 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * config/sparc/sparc.md (movdf_const_intreg_sp32): Fix length
+ attribute.
+
+Mon Sep 14 14:02:53 1998 Jeff Law (law@cygnus.com)
- * tree.c (restore_tree_status): Also free up temporary storage
- when we finish a toplevel function.
- (dump_tree_statistics): Print stats for backend obstacks.
+ * version.c: Bump for snapshot.
-Sat Oct 18 12:47:31 1997 Doug Evans <dje@canuck.cygnus.com>
+Mon Sep 14 10:33:56 1998 Jeff Law (law@cygnus.com)
- * expr.c (use_group_regs): Don't call use_reg for MEMs.
+ * version.c: Bump for snapshot.
-Sat Oct 18 09:49:46 1997 Jason Merrill <jason@yorick.cygnus.com>
-
- * libgcc2.c (__throw): Don't copy the return address.
- * dwarf2out.c (expand_builtin_dwarf_reg_size): Ignore return address.
-
- * except.c (exceptions_via_longjmp): Initialize to 2 (uninitialized).
- * toplev.c (main): Initialize exceptions_via_longjmp.
-
- * tree.c: Add extra_inline_obstacks.
- (save_tree_status): Use it.
- (restore_tree_status): If this is a toplevel inline obstack and we
- didn't want to save anything on it, recycle it.
- (print_inline_obstack_statistics): New fn.
- * function.c (pop_function_context_from): Pass context to
- restore_tree_status.
- * obstack.h (obstack_empty_p): New macro.
-
-Sat Oct 18 00:43:59 1997 Jeffrey A Law (law@cygnus.com)
-
- * i386/freebsd.h (ASM_COMMENT_START): Fix.
-
-Fri Oct 17 23:48:52 1997 Jim Wilson (wilson@cygnus.com)
-
- * v850.c (ep_memory_offset): New function.
- (ep_memory_operand, substitute_ep_register, v850_reorg): Call it.
-
- * v850.h (CONST_OK_FOR_*): Add and correct comments.
- (CONSTANT_ADDRESS_P): Add comment.
- (EXTRA_CONSTRAINT): Define 'U'.
- * v850.md: Add comments on bit field instructions.
- (addsi3): Delete &r/r/r alternative. Add r/r/U alternative.
- (lshrsi3): Use N not J constraint.
-
- * v850.md (v850_tst1+1): New define_split for tst1 instruction.
-
- * v850.c (reg_or_0_operand): Call register_operand.
- (reg_or_int5_operand): Likewise.
- * v850.h (MASK_BIG_SWITCH, TARGET_BIG_SWITCH): New macros.
- (TARGET_SWITCHES): Add "big-switch".
- (ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT, CASE_VECTOR_MODE,
- ASM_OUTPUT_BEFORE_BASE_LABEL): Add support for TARGET_BIG_SWITCH.
- (CASE_DROPS_THROUGH): Comment out.
- (CASE_VECTOR_PC_RELATIVE, JUMP_TABLES_IN_TEXT_SECTION): Define.
- * v850.md (cmpsi): Delete compare mode.
- (casesi): New pattern.
-
- * v850.h (CONST_OK_FOR_N): Delete redundant compare against zero.
- * v850.md (ashlsi3): Use SImode not QImode for shift count.
- (lshrsi3): Likewise.
-
- * v850.c (print_operand): Add 'c', 'C', and 'z' support. Delete
- unreachable switch statement after 'b' support. Remove "b" from
- strings for 'b' support.
- * v850.md (branch_normal, branch_invert): Change %b to b%b.
-
-Fri Oct 17 23:33:20 1997 Jeffrey A Law (law@cygnus.com)
-
- * Makefile.in (LIBGCC2_CFLAGS): Avoid a backslash then an
- empty line if @inhibit_libc@ is empty.
-
-Fri Oct 17 23:24:40 1997 Robert Lipe (robertl@dgii.com)
-
- * i386/sco5.h: Let ELF use dwarf2 unwinding. COFF uses sjlj.
- (EH_FRAME_SECTION_ASM_OP, EH_FRAME_SECTION_ASM_OP_ELF): Defined.
- (EH_FRAME_SECTION_ASM_OP_COFF): Likewise.
- (DWARF2_UNWIND_INFO): Let this track object file format.
- (EXTRA_SECTIONS): Add in_eh.
- (EH_FRAME_SECTION_ASM_OP, EH_FRAME_SECTION_ASM_OP_ELF): Define.
- (EH_FRAME_SECTION_ASM_OP_COFF): Likewise.
-
-Fri Oct 17 17:13:42 1997 David S. Miller <davem@tanya.rutgers.edu>
-
- * sparc/linux64.h (LINK_SPEC): Dynamic linker is ld-linux64.so.2.
- * sparc/sparc.h (FUNCTION_PROFILER): Fix format string when
- TARGET_MEDANY.
- * sparc/sparc.c (dwarf2out_cfi_label): Extern no longer needed.
- (output_double_int): Output DI mode values correctly when
- HOST_BITS_PER_WIDE_INT is 64.
- (output_fp_move_quad): If TARGET_V9 and not TARGET_HARD_QUAD, use
- fmovd so it works if a quad float ends up in one of the upper 32
- float regs.
- * sparc/sparc.md (pic_{lo_sum,sethi}_di): New patterns
- necessary for PIC support on sparc64.
-
-Fri Oct 17 13:39:56 1997 Doug Evans <dje@canuck.cygnus.com>
-
- * sparc/sp64-elf.h (TARGET_DEFAULT): Delete MASK_STACK_BIAS.
- * sparc/sparc.h (PROMOTE_MODE): Promote small ints if arch64.
- (PROMOTE_FUNCTION_ARGS,PROMOTE_FUNCTION_RETURN): Define.
- (SPARC_FIRST_FP_REG, SPARC_FP_REG_P): New macros.
- (SPARC_{OUTGOING,INCOMING}_INT_ARG_FIRST): New macros.
- (SPARC_FP_ARG_FIRST): New macro.
- (CONDITIONAL_REGISTER_USAGE): All v9 fp regs are volatile now.
- (REG_ALLOC_ORDER,REG_LEAF_ALLOC_ORDER): Reorganize fp regs.
- (NPARM_REGS): There are 32 fp argument registers now.
- (FUNCTION_ARG_REGNO_P): Likewise.
- (FIRST_PARM_OFFSET): Update to new v9 abi.
- (REG_PARM_STACK_SPACE): Define for arch64.
- (enum sparc_arg_class): Delete.
- (sparc_arg_count,sparc_n_named_args): Delete.
- (struct sparc_args): Redefine and use for arch32 as well as arch64.
- (GET_SPARC_ARG_CLASS,ROUND_REG,ROUND_ADVANCE): Delete.
- (FUNCTION_ARG_ADVANCE): Rewrite.
- (FUNCTION_ARG,FUNCTION_INCOMING_ARG): Rewrite.
- (FUNCTION_ARG_{PARTIAL_NREGS,PASS_BY_REFERENCE}): Rewrite.
- (FUNCTION_ARG_CALLEE_COPIES): Delete.
- (FUNCTION_ARG_{PADDING,BOUNDARY}): Define.
- (STRICT_ARGUMENT_NAMING): Define.
- (doublemove_string): Declare.
- * sparc/sparc.c (sparc_arg_count,sparc_n_named_args): Delete.
- (single_move_string): Use GEN_INT, and HOST_WIDE_INT.
- (doublemove_string): New function.
- (output_move_quad): Clean up some of the arch64 support.
- (compute_frame_size): Add REG_PARM_STACK_SPACE if arch64.
- Don't add 8 bytes of reserved space if arch64.
- (sparc_builtin_saveregs): Combine arch32/arch64 versions.
- (init_cumulative_args): New function.
- (function_arg_slotno): New static function.
- (function_arg,function_arg_partial_nregs): New functions.
- (function_arg_{pass_by_reference,advance}): New functions.
- (function_arg_padding): New function.
- * ginclude/va-sparc.h: Rewrite v9 support.
-
-Fri Oct 17 12:29:48 1997 Christian Iseli <Christian.Iseli@lslsun.epfl.ch>
-
- * regclass.c (record_address_regs): Look at REG_OK_FOR_{BASE,INDEX}_P
- for hard regs to determine base and index registers.
-
- * reload.c (debug_reload_to_stream): New function. Specify stream
- into which to write debug info.
- (debug_reload): Modify to call debug_reload_to_stream with stderr.
-
-Thu Oct 16 15:07:51 1997 Richard Henderson <rth@cygnus.com>
-
- * combine.c (can_combine_p): Don't combine with an asm whose
- output is a hard register.
-
-Thu Oct 16 15:43:26 1997 Mike Stump (mrs@wrs.com)
-
- * c-decl.c (start_struct): Ensure that structs with forward
- declarations are in fact packed when -fpack-struct is given.
-
- * stor-layout.c (layout_record): Ignore STRUCTURE_SIZE_BOUNDARY if
- we are packing a structure. This allows a structure with only
- bytes to be aligned on a byte boundary and have no padding on a
- m68k.
-
-Thu Oct 16 15:17:54 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-
- * rs6000.h (ROUND_TYPE_ALIGN): Don't blow up if no fields in record.
-
-Thu Oct 16 11:20:30 1997 Richard Henderson <rth@cygnus.com>
-
- * alpha.c (alpha_return_addr_rtx): New variable.
- (alpha_save_machine_status): New; save it.
- (alpha_restore_machine_status): New; restore it.
- (alpha_init_expanders): New; clear it.
- (alpha_return_addr): New; set it.
- (alpha_ra_ever_killed): New; if alpha_return_addr_rtx, regs_ever_live
- is overly conservative, so search the insns explicitly.
- (alpha_sa_mask [VMS]): Check alpha_ra_ever_killed.
- (alpha_sa_size [VMS && !VMS]): Likewise.
- * alpha.h (RETURN_ADDR_RTX): Call alpha_return_addr.
- (INIT_EXPANDERS): New definition.
-
- * alpha.c: Move REG_PV, REG_RA somewhere more visible in the file.
- (output_prolog [!VMS]): Use them.
-
- * alpha.c (output_prolog [!VMS]): Move gp detection to ...
- (alpha_does_function_need_gp): ... a new function. Refine the
- CALL_INSN test to just TYPE_JSR.
- * alpha.md (most call insns): Fix some jsr/ibr type transpositions.
-
-Thu Oct 16 09:36:47 1997 Jeffrey A Law (law@cygnus.com)
+Mon Sep 14 09:51:05 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Wed Oct 15 21:38:18 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+Sun Sep 13 22:10:18 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * invoke.texi (C Dialect Options): Put back missing @end itemize.
- * pa.c (move_operand): Respect -mdisable-indexing.
- * pa.h (GO_IF_LEGITIMATE_ADDRESS): Likewise.
+Mon Sep 14 02:33:46 1998 Alexandre Oliva <oliva@dcc.unicamp.br>
-Wed Oct 15 21:34:45 1997 David Edelsohn <edelsohn@mhpcc.edu>
+ * configure.in: Remove usage of `!' to negate the result of a
+ command; some common shells do not support it.
- * rs6000.md (udivsi3, divsi3): Split into MQ and non-MQ cases for
- PPC601.
- (umulsidi3,umulsi3_highpart): Ditto.
- (smulsi3_highpart_no_mq): Add !TARGET_POWER.
+Sun Sep 13 19:17:35 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Wed Oct 15 18:21:46 1997 Richard Henderson <rth@cygnus.com>
+ * configure.in: In sparc9-sol2 config, use 'if test' not
+ brackets.
+ * configure: Rebuilt.
- * alpha.c (final_prescan_insn): Gut, remove and transform to ...
- (alpha_handle_trap_shadows): ... a new function. Handle the entire
- function in one go. Emit RTL for trapb, instead of printf directly.
- (alpha_reorg): New function. Call alpha_handle_trap_shadows.
- (trap_pending): Kill global variable.
- (output_epilog): Don't call final_prescan_insn.
- (struct shadow_summary): Elide $31 and $f31; now it fits in a word.
- * alpha.h (FINAL_PRESCAN_INSN): Remove.
- (MACHINE_DEPENENT_REORG): Define.
- * alpha.md (jsr patterns with trapb): Stupid and useless. Kill.
- (trapb): New insn.
+ * config/sparc/sol2-sld-64.h (SPARC_DEFAULT_CMODEL): Change to
+ CM_MEDANY.
+ (CPP_CPU_SPEC): Do not define _LP64, header files do this.
+ (CPP_CPU_DEFAULT_SPEC): Likewise.
+ * config/sparc/sol2.h (INIT_SUBTARGET_OPTABS): Get the names right
+ for arch64 libfuncs.
-Wed Oct 15 18:16:05 1997 Richard Henderson <rth@cygnus.com>
+ * config/sparc/sparc.md (goto_handler_and_restore): Allow any mode
+ for operand zero.
- Tune Haifa scheduler for Alpha:
- * alpha.h (ISSUE_RATE): Define.
- * alpha.c (alpha_adjust_cost): Handle EV5 mult delay; don't apply
- EV4 adjustments to EV5.
- * alpha.md: Remove all scaling from function unit delays. Rework
- EV5 function units to match the CPU.
- (umuldi3_highpart): EV5 added the IMULH insn class.
+Sun Sep 13 09:11:59 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Wed Oct 15 17:42:41 1997 Jeffrey A Law (law@cygnus.com)
+ * acconfig.h (NEED_DECLARATION_STRSIGNAL): Provide a stub.
- * pa.c (following_call): Fail if the CALL_INSN is an indirect
- call.
+ * collect2.c: Don't declare `sys_siglist' here.
+ (my_strsignal): Prototype and define new function. Use it in
+ place of `sys_siglist' hacks.
-Tue Oct 14 12:01:00 1997 Mark Mitchell <mmitchell@usa.net>
+ * mips_tfile.c: Likewise.
- * cplus-dem.c (demangle_signature): Don't look for return types on
- constructors. Handle member template constructors.
+ * configure.in (AC_CHECK_FUNCS): Check for strsignal.
+ (GCC_NEED_DECLARATIONS): Likewise.
-Tue Oct 14 11:30:29 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * system.h (strsignal): Prototype it, if necessary.
+ (sys_siglist): Declare it, if necessary.
- * tree.c (expr_tree_cons, build_expr_list, expralloc): New fns.
- * tree.h: Declare them.
+Sun Sep 13 04:37:28 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Fri Oct 10 13:46:56 1997 Doug Evans <dje@canuck.cygnus.com>
+ * loop.c (move_movables): While removing insn sequences, preserve
+ the next pointer of the most recently deleted insn when we skip
+ over a NOTE.
- * configure.in: Handle --with-newlib.
- * Makefile.in (LIBGCC2_CFLAGS): Add @inhibit_libc@.
+Sun Sep 13 08:13:39 1998 Ben Elliston <bje@cygnus.com>
- * sparc/t-sp64 (LIBGCC2_CFLAGS): Delete.
+ * objc/config-lang.in: Do not output the name of the selected
+ thread file when building the front-end. The Makefile for the
+ runtime library will do this.
-Wed Oct 8 14:37:44 1997 Jeffrey A Law (law@cygnus.com)
+ * objc/Make-lang.in: Do not build the runtime library or install
+ the Objective C header files. The Makefile for the runtime
+ library will do this.
- * config/ptx4.h: Fix typo.
+ * objc/Makefile.in (all.indirect): Only build the front-end.
+ (compiler): Rename to `frontend'.
+ (obj-runtime): Remove target.
+ (copy-headers): Likewise.
+ (clean): No need to remove `libobjc.a' any longer.
-Wed Oct 8 08:57:20 1997 Jeffrey A Law (law@cygnus.com)
+Sat Sep 12 11:37:19 1998 Michael Meissner <meissner@cygnus.com>
- * version.c: Bump for snapshot.
+ * rs6000.h ({ASM,CPP}_CPU_SPEC): Add support for all machines
+ supported with -mcpu=xxx.
-Tue Oct 7 16:27:34 1997 Manfred Hollstein <manfred@s-direktnet.de>
+Fri Sep 11 23:55:54 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * aclocal.m4: Substitute INSTALL.
- * configure: Re-built.
+ * flow.c (mark_set_1): Recognize multi-register structure return
+ values in CALL insns.
+ (mark_used_regs): Likewise.
+ (count_reg_sets_1): Likewise.
+ (count_reg_references): Likewise.
+ * rtlanal.c (note_stores): Likewise.
+ (reg_overlap_mentioned_p): Likewise.
+ * haifa-sched.c (check_live_1): Likewise.
+ (update_live_1): Likewise.
+ (sched_analyze_1): Likewise.
+ (sched_note_set): Likewise.
+ (birthing_insn_p): Likewise.
+ (attach_deaths): Likewise.
-Tue Oct 7 15:37:35 1997 Jeffrey A Law (law@cygnus.com)
+ * config/sparc/sparc.md (movdf_const_intreg_sp64): Disable.
- * integrate.c (save_for_inline_copying): Avoid undefined pointer
- operations.
- (expand_inline_function): Likewise.
+Fri Sep 11 22:57:55 1998 Eric Dumazet <dumazet@cosmosbay.com>
- * dwarf2out.c (output_call_frame_info): Reinstate last change
- using flag_debug_asm check instead of flag_verbose_asm.
+ * config/i386/sco5.h (ASM_WEAKEN_LABEL): Defined as in svr4.h.
-Tue Oct 7 12:57:26 1997 Jim Wilson <wilson@cygnus.com>
+Thu Sep 10 22:02:04 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * dwarf2out.c (output_call_frame_info): Remove last change.
+ * glimits.h (__LONG_MAX__): Recognize __sparcv9 too.
-1997-10-04 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+Thu Sep 10 21:19:10 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
- * frame.c (__frame_state_for): Execute the FDE insns until the
- current pc value is strictly bigger than the target pc value.
+ * configure.in: Add check for GAS subsection -1 support.
+ * acconfig.h (HAVE_GAS_SUBSECTION_ORDERING): Add.
+ * configure config.in: Rebuilt.
+ * config/sparc/sparc.h (CASE_VECTOR_MODE): For V9 flag_pic, use
+ SImode is subsection -1 works, else use DImode.
+ (ASM_OUTPUT_ADDR_VEC_START, ASM_OUTPUT_ADDR_VEC_END): Define if
+ subsection -1 works.
+ * config/sparc/sparc.c (sparc_output_addr_vec,
+ sparc_output_addr_diff_vec): Use them if defined.
-Tue Oct 7 11:00:42 1997 Jason Merrill <jason@yorick.cygnus.com>
+Thu Sep 10 10:46:01 1998 Mark Mitchell <mark@markmitchell.com>
- * regclass.c (init_reg_modes): If we can't find a mode for the
- register, use the previous one.
+ * tree.h (DECL_ORIGIN): New macro.
+ * integrate.c (copy_and_set_decl_abstract_origin): New function.
+ (copy_decl_list): Use it.
+ (integrate_parm_decls): Likewise.
+ (integrate_decl_tree): Likewise.
+ * dwarf2out.c (decl_ultimate_origin): Simplify.
+ * dwarfout.c (decl_ultimate_origin): Likewise.
+ * c-decl.c (duplicate_decls): Use DECL_ORIGIN.
+ (pushdecl): Likewise.
-Tue Oct 7 10:55:34 1997 Richard Henderson <rth@cygnus.com>
+Thu Sep 10 08:01:31 1998 Anthony Green <green@cygnus.com>
- * haifa-sched.c (print_block_visualization): Call fprintf directly,
- don't sprintf through an alloca'ed buffer.
+ * config/rs6000/rs6000.c (output_epilog): Add Java support.
-Tue Oct 7 10:52:29 1997 Thomas Koenig (ig25@rz.uni-karlsruhe.de)
+Thu Sep 10 14:48:59 1998 Martin von Löwis <loewis@informatik.hu-berlin.de>
- * reload.c (decompose): Always initialize val.base.
+ * invoke.texi (C++ Dialect Options): Document -fhonor-std.
-Tue Oct 7 10:19:26 1997 Manfred Hollstein (manfred@lts.sel.alcatel.de)
+Thu Sep 10 01:38:05 1998 Jeffrey A Law (law@cygnus.com)
- * m68k/mot3300.h (ASM_OUTPUT_ALIGN): Accept any alignment
- instead of aborting.
- * dwarf2out.c (output_call_frame_info): Call app_enable and
- app_disable to let GNU as accept the generated comments.
+ * reg-stack.c (straighten_stack): Do nothing if the virtual stack is
+ empty or has a single entry.
-Tue Oct 7 11:41:21 1997 Michael Meissner <meissner@cygnus.com>
+ * toplev.c (rest_of_compilation): Open up the dump file for reg-stack
+ before calling reg_to_stack.
- * tree.h (get_file_function_name): Add declaration.
- * dwarf2out.c (output_call_frame_info): No need to cast
- get_file_function_name call anymore.
- * profile.c (toplevel): Remove get_file_function_name
- declaration.
- * c-lang.c (finish_file): Ditto.
+Thu Sep 10 00:03:34 1998 Richard Henderson <rth@cygnus.com>
-Tue Oct 7 10:01:45 1997 Chip Salzenberg <chip@rio.atlantic.net>
+ * alpha.c (alphaev5_insn_pipe): Abort on default case.
+ (alphaev5_next_group): Swallow CLOBBERs and USEs.
- * Makefile.in (program_transform_name): Let autoconf substitute
- the correct value.
+ * c-tree.h (warn_long_long): Declare it.
-Tue Oct 7 09:54:35 1997 Jeffrey A Law (law@cygnus.com)
+Wed Sep 9 23:31:36 1998 (Stephen L Moshier) <moshier@world.std.com>
- * haifa-sched.c (schedule_block): If the first real insn in a
- block has any special notes attached to it, remove them.
+ * emit-rtl.c (gen_lowpart_common): Disable optimization of
+ initialized float-int union if the value is a NaN.
-Tue Oct 7 09:48:51 1997 Richard Henderson <rth@cygnus.com>
+Wed Sep 9 23:00:48 1998 Nathan Sidwell <nathan@acm.org>
- * alpha.h (FLOAT_STORE_FLAG_VALUE): It's 2.0 not 0.5.
+ * c-lex.c (real_yylex): Don't warn about long long constants if
+ we're allowing long long
-Mon Oct 6 12:47:32 1997 Manfred Hollstein (manfred@lts.sel.alcatel.de)
+Wed Sep 9 21:58:41 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
- * m88k.c (m88k_begin_prologue): Remove superfluous backslash.
+ * except.h (current_function_eh_stub_label): Declare.
+ (current_function_eh_old_stub_label): Declare.
+ * function.h (struct function): New members eh_stub_label and
+ eh_old_stub_label.
+ * except.c (current_function_eh_stub_label): New variable.
+ (current_function_eh_old_stub_label): New variable.
+ (init_eh_for_function): Clear them.
+ (save_eh_status): Save them.
+ (restore_eh_status): Restore them.
+ (expand_builtin_eh_stub): Set current_function_eh_stub_label.
+ (expand_builtin_eh_stub_old): Set current_function_eh_old_stub_label.
+ * flow.c (find_basic_blocks_1): When handling a REG_LABEL note, don't
+ make an edge from the block that contains it to the block starting
+ with the label if this label is one of the eh stub labels.
+ If eh stub labels exist, show they are reachable from the last block
+ in the function.
-Mon Oct 6 12:04:24 1997 Jeffrey A Law (law@cygnus.com)
+ * reload1.c (reload): Break out several subroutines and make some
+ variables global.
+ (calculate_needs_all_insns): New function, broken out of reload.
+ (calculate_needs): Likewise.
+ (find_reload_regs): Likewise.
+ (find_group): Likewise.
+ (find_tworeg_group): Likewise.
+ (something_needs_reloads): New global variable, formerly in reload.
+ (something_needs_elimination): Likewise.
+ (caller_save_spill_class): Likewise.
+ (caller_save_group_size): Likewise.
+ (max_needs): Likewise.
+ (group_size): Likewise.
+ (max_groups): Likewise.
+ (max_nongroups): Likewise.
+ (group_mode): Likewise.
+ (max_needs_insn): Likewise.
+ (max_groups_insn): Likewise.
+ (max_nongroups_insn): Likewise.
+ (failure): Likewise.
- * Makefile.in (check-g77): New test target.
- (CHECK-TARGETS): Add check-g77.
+ * print-rtl.c (print_rtx): For MEMs, print MEM_ALIAS_SET.
-Fri Oct 3 11:56:36 1997 Jason Merrill <jason@yorick.cygnus.com>
+Wed Sep 9 13:14:41 1998 Richard Henderson <rth@cygnus.com>
- * toplev.c (rest_of_compilation): Defer all non-nested inlines.
+ * loop.c (load_mems): Copy rtx for output mem.
-Fri Oct 3 15:49:27 1997 Michael Meissner <meissner@cygnus.com>
+Wed Sep 9 15:16:58 1998 Gavin Romig-Koch <gavin@cygnus.com>
- * flow.c (print_rtl_with_bb): Cast alloca return value for
- in_bb_p.
+ * mips/abi64.h (LONG_MAX_SPEC): Don't set LONG_MAX for
+ mips1 or mips2 either.
-Thu Oct 2 21:15:03 1997 Richard Henderson <rth@cygnus.com>
+Wed Sep 9 12:31:35 1998 Jeffrey A Law (law@cygnus.com)
- * i386.h (RETURN_ADDR_RTX): New definition that works for
- __builtin_return_address(0) and -fomit-frame-pointer.
+ * pa.c (pa_reorg): New marking scheme for jumps inside switch
+ tables.
+ (pa_adjust_insn_length): Update to work with new marking scheme
+ for jumps inside switch tables.
+ * pa.md (switch_jump): Remove pattern.
+ (jump): Handle jumps inside jump tables.
-Wed Oct 1 13:43:53 1997 Jim Wilson <wilson@cygnus.com>
+ * Makefile.in (profile.o): Depend on insn-config.h
- Bring over from FSF.
- Tue Aug 5 16:10:45 1997 Jason Merrill <jason@yorick.cygnus.com>
+Wed Sep 9 09:36:51 1998 Jim Wilson <wilson@cygnus.com>
- * mips.c (function_arg): Handle passing a struct
- containing a double in a DFmode register without the PARALLEL.
+ * iris6.h (DWARF2_UNWIND_INFO): Undef.
-Wed Oct 1 11:13:25 1997 Ian Lance Taylor <ian@cygnus.com>
+Wed Sep 9 01:32:01 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * pexecute.c: Use spawn if __CYGWIN32__.
+ Add preliminary native sparcv9 Solaris support.
+ * configure.in: Recognize sparv9-*-solaris2*
+ * configure: Rebuilt.
+ * config.sub: Recognize sparcv9 just like sparc64.
+ * config/sparc/sol2-c1.asm config/sparc/sol2-ci.asm
+ config/sparc/sol2-cn.asm: Macroize so it can be shared between
+ 32-bit and 64-bit Solaris systems.
+ * config/sparc/t-sol2: Assemble those with cpp.
+ * config/sparc/sparc.h (TARGET_CPU_sparcv9): New alias for v9.
+ (*TF*_LIBCALL): If ARCH64 use V9 names.
+ * config/sparc/{xm-sysv4-64,sol2-sld-64}.h: New files.
+
+Wed Sep 9 01:07:30 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
+
+ * config/sparc/sparc.h (TARGET_CM_MEDMID): Fix documentation.
+ (CASE_VECTOR_MODE): Set to SImode even if PTR64, when MEDLOW and
+ not doing pic.
+ (ASM_OUTPUT_ADDR_{VEC,DIFF}_ELT): Check CASE_VECTOR_MODE not
+ Pmode.
+ * config/sparc/sparc.md (tablejump): Likewise, and sign extend op0
+ to Pmode if CASE_VECTOR_MODE is something else.
+
+Wed Sep 9 00:10:31 1998 Jeffrey A Law (law@cygnus.com)
+
+ * prefix.c (update_path): Correctly handle cases where PATH is
+ a substring of the builtin prefix, but specifies a different
+ directory location.
+
+Tue Sep 8 23:46:04 1998 Hans-Peter Nilsson <hp@axis.se>
+
+ * expr.c: Corrected comment about what MOVE_RATIO does.
+ * config/alpha/alpha.h: Likewise.
+ * config/1750a/1750a.h: Likewise.
+ * config/clipper/clipper.h: Likewise.
+ * config/i386/i386.h: Likewise.
+
+Tue Sep 8 22:56:12 1998 Jeffrey A Law (law@cygnus.com)
+
+ * configure.in (m68k-next-nextstep3*): Use collect2.
+ Similarly for x86 NeXT configurations.
+ * configure: Rebuilt.
- * pexecute.c: Include "config.h" first, as per autoconf manual
- (from Paul Eggert <eggert@twinsun.com>).
+Tue Sep 8 01:38:57 1998 Nathan Sidwell <nathan@acm.org>
-Wed Oct 1 01:44:36 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+ * configure.in: Don't assume srcdir is .../gcc.
+ * configure: Rebuilt.
- * m68k/x-mot3300 (XCFLAGS): Disable as's long/short jump
- optimisation for f/expr.o and f/stb.o.
+Sat Sep 5 16:34:34 1998 John Wehle (john@feith.com)
-Tue Sep 30 23:48:57 1997 Jeffrey A Law (law@cygnus.com)
+ * global.c: Update comments.
+ (global_alloc): Assign allocation-numbers
+ even for registers allocated by local_alloc in case
+ they are later spilled and retry_global_alloc is called.
+ (mark_reg_store, mark_reg_clobber,
+ mark_reg_conflicts, mark_reg_death): Always record a
+ conflict with a pseudo register even if it has been
+ assigned to a hard register.
+ (dump_conflicts): Don't list pseudo registers already assigned to
+ a hard register as needing to be allocated, but do list their
+ conflicts.
+ * local-alloc.c: Update comment.
- * cse.c (this_insn_cc0_mode): Initialize.
+Mon Sep 7 23:38:01 1998 Jeffrey A Law (law@cygnus.com)
-Tue Sep 30 23:09:40 1997 Thomas Koenig <ig25@mvmap66.ciw.uni-karlsruhe.de>
+ * configure.in: Check for bogus GCC_EXEC_PREFIX and LIBRARY_PATH.
+ * configure: Rebuilt.
- * cccp.c (expand_to_temp_buffer): Initialize all members of obuf.
+Mon Sep 7 22:41:46 1998 Michael Meissner <meissner@cygnus.com>
- * haifa-sched.c (get_block_head_tail): Remove unneeded initialization.
+ * rs6000.c (rs6000_override_options): Fix name for ec603e, to add
+ missing 'c'.
+ * t-ppccomm (MULTILIB_MATCHES_FLOAT): Add support for -mcpu=xxx
+ for all targets that set -msoft-float.
-Tue Sep 30 23:06:43 1997 Richard Henderson <rth@cygnus.com>
+Mon Sep 7 23:30:07 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * alpha.md (beq): For registers and ints 0-255, use cmpeq+bne, since
- that pair will dual-issue on the 21164 and plus+beq won't.
- (bne): Likewise for cmpeq+beq.
+ * toplev.c (print_switch_values): Make static to match prototype.
-Tue Sep 30 16:07:58 1997 Jim Wilson <wilson@cygnus.com>
+Mon Sep 7 19:13:59 1998 Jeffrey A Law (law@cygnus.com)
- * except.c (find_exception_handler_labels): Correct argument to free.
+ * configure.in: If we are unable to find the "gnatbind" program,
+ then do not configure the ada subdir.
+ * configure: Rebuilt.
-Tue Sep 30 11:00:00 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
+Sun Sep 6 14:03:58 1998 Jeff Law (law@cygnus.com)
- * except.c (find_exception_handler_labels): Free LABELS when we're
- done.
+ * version.c: Bump for snapshot.
-Mon Sep 29 14:04:35 1997 Jeffrey A Law (law@cygnus.com)
+Sun Sep 6 13:28:07 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
-Mon Sep 29 10:51:53 1997 Jason Merrill <jason@yorick.cygnus.com>
+Sun Sep 6 08:54:14 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (toplev.o): Depend on $(EXPR_H).
+ (insn-extract.o, insn-attrtab.o): Depend on toplev.h.
+
+ * gansidecl.h: Define ATTRIBUTE_NORETURN.
+
+ * genattrtab.c: Have insn-attrtab.c include toplev.h.
+
+ * genextract.c: Have insn-extract.c include toplev.h.
+
+ * rtl.h: Don't prototype `fatal_insn_not_found' and `fatal_insn'.
+
+ * toplev.c: Include expr.h.
+ (really_sorry, fancy_abort): Remove prototypes.
+ (set_target_switch): Add argument in prototype.
+ (vfatal): Mark prototype with ATTRIBUTE_NORETURN.
+ (v_really_sorry): Likewise.
+ (print_version, print_single_switch, print_switch_values): Make
+ static and add prototype arguments.
+ (decl_printable_name): Add prototype arguments.
+ (lang_expand_expr_t): New typedef.
+ (lang_expand_expr): Declare as a lang_expand_expr_t.
+ (incomplete_decl_finalize_hook): Add prototype argument.
+ (decl_name): Mark variable `verbosity' with ATTRIBUTE_UNUSED.
+ (botch): Likewise for variable `s'.
+ (rest_of_type_compilation): Mark variables `type' and `toplev'
+ with ATTRIBUTE_UNUSED if none of DBX_DEBUGGING_INFO,
+ XCOFF_DEBUGGING_INFO or SDB_DEBUGGING_INFO are defined.
+ (display_help): Make variable `i' an `unsigned long'.
+ (main): Remove unused parameter `envp'.
+ Cast assignment to `lang_expand_expr' to a `lang_expand_expr_t'.
+ Cast -1 when comparing it with a `size_t'.
+
+ * toplev.h (fatal, fatal_io_error, pfatal_with_name): Mark
+ prototype with ATTRIBUTE_NORETURN.
+ (fatal_insn_not_found, fatal_insn, really_sorry,
+ push_float_handler, pop_float_handler): Add prototypes.
+ (fancy_abort): Mark prototype with ATTRIBUTE_NORETURN.
+ (do_abort, botch): Add prototypes.
+
+Sat Sep 6 12:05:18 1998 John Carr <jfc@mit.edu>
+
+ * final.c (final): If a label is reached only from a single jump,
+ call NOTICE_UPDATE_CC on the jump and its predecessor before
+ emitting the insn after the label.
+
+ * i386.h: Add AMD K6 support.
+ Change TARGET_* macros to use table lookup.
+ (INITIALIZE_TRAMPOLINE): Improve trampoline code.
+ (ADJUST_COST): Change definition to call function in i386.c.
+ (ISSUE_RATE): Define as 2 for anything newer than an 80486.
+ * i386.c: Add AMD K6 support.
+ Add constants for feature tests used by TARGET_* macros.
+ (split_di): If before reload, call gen_lowpart and gen_highpart.
+ (x86_adjust_cost): New function.
+ (put_jump_code): New function.
+ (print_operand): New codes 'D' and 'd'.
+ * i386.md: New insn types. New insn attribute "memory".
+ Redefine scheduling parameters to use new types and add AMD K6
+ support. Explicitly set type of most insns.
+ (move insns): K6 prefers movl $0,reg to xorl reg,reg. Pentium
+ Pro and K6 prefer movl $1,reg to incl reg.
+ (adddi3, subdi3): Set cc_status.
+ (DImode shift patterns): Change label counters from HOST_WIDE_INT
+ to int; x86 can't have more than 2^31 DImode shifts per file.
+ (setcc): Combine all setcc patterns. Allow writing memory.
+ Combine all jump patterns using match_operator.
+ (*bzero): Name pattern. Emit multiple stos instructions when that
+ is faster than rep stos.
+ (xordi3, anddi3, iordi3): Simplify DImode logical patterns and
+ add define_split.
+
+Sun Sep 6 11:17:20 1998 Dave Love <d.love@dl.ac.uk>
+
+ * config/m68k/x-next (BOOT_LDFLAGS): Define suitably for f771
+ linking.
+
+Sat Sep 5 22:05:25 1998 Richard Henderson <rth@cygnus.com>
- * flow.c (find_basic_blocks): Mark calls as potentially jumping
- to the EH labels.
+ * alpha.c (alpha_ra_ever_killed): Inspect the topmost sequence,
+ not whatever we're generating now.
-Mon Sep 29 09:58:06 1997 Jeffrey A Law (law@cygnus.com)
+ * alpha.c (set_frame_related_p, FRP): New.
+ (alpha_expand_prologue): Mark frame related insns.
+ (alpha_expand_epilogue): Likewise, but with a null FRP.
+ * alpha.h (INCOMING_RETURN_ADDR_RTX): New.
+ * alpha.md (exception_receiver): New.
+ * alpha/crtbegin.asm (.eh_frame): New beginning.
+ (__do_frame_setup, __do_frame_takedown): New.
+ * alpha/crtend.asm (.eh_frame): New ending.
+ * alpha/elf.h (DWARF2_DEBUGGING_INFO): Define.
+ (ASM_SPEC): Don't emit both dwarf2 and mdebug.
+ (ASM_FILE_START): Don't emit .file for dwarf2.
- * configure.in: Substitute for "install" too.
- * configure: Rebuilt.
+ * rtl.h (enum reg_note): Add REG_FRAME_RELATED_EXPR.
+ * rtl.c (reg_note_name): Likewise.
+ * rtl.texi (REG_NOTES): Likewise.
+ * dwarf2out.c (dwarf2out_frame_debug): Use it. Recognize a store
+ without an offset.
-Mon Sep 29 00:38:42 1997 Aaron Jackson <jackson@negril.msrce.howard.edu>
+Sat Sep 5 14:47:17 1998 Richard Henderson <rth@cygnus.com>
- * Makefile.in (bootstrap-lean, compare-lean): New targets.
+ * i386.h (PREFERRED_RELOAD_CLASS): Standard fp constants load to TOS.
+ * i386.md (movsf, movdf, movxf): Validate memory address returned
+ from force_const_mem. Kill useless REG_EQUAL setting code.
-Mon Sep 29 00:18:16 1997 Richard Henderson (rth@cygnus.com)
+Sat Sep 5 14:23:31 1998 Torbjorn Granlund <tege@matematik.su.se>
- * alias.c (base_alias_check): Two symbols can conflict if they
- are accessed via AND.
- (memrefs_conflict_p): Likewise.
+ * m68k.md (zero_extendsidi2): Fix typo.
- * alpha.h (SETUP_INCOMING_VARARGS): Emit a blockage insn
- after flushing argument registers to the stack.
+Sat Sep 5 13:40:24 1998 Krister Walfridsson <cato@df.lth.se>
- * Makefile.in (mostlyclean): Remove .regmove files.
+ * configure.in: Removed references to the removed file.
+ * config/xm-netbsd.h: Use ${cpu_type}/xm-netbsd.h for
+ arm*-*-netbsd* and ns32k-*-netbsd*.
+ * config/i386/xm-netbsd.h: Removed unnecessary file.
+ * config/m68k/xm-netbsd.h: Likewise.
+ * config/sparc/xm-netbsd.h: Likewise.
+ * config/mips/xm-netbsd.h: Likewise.
-Sun Sep 28 18:59:58 1997 Jason Merrill <jason@yorick.cygnus.com>
+Sat Aug 29 13:32:58 1998 Mumit Khan <khan@xraylith.wisc.edu>
- * libgcc2.c (__throw): Fix thinko.
+ * i386/cygwin32.h (BIGGEST_ALIGNMENT): Define.
+ (PCC_BITFIELD_TYPE_MATTERS): Define to be 0.
-Sun Sep 28 12:00:52 1997 Mark Mitchell <mmitchell@usa.net>
+ * i386/cygwin32.h (ASM_OUTPUT_SECTION_NAME): Don't check for
+ for exact section attributions.
- * cplus-dem.c (demangle_template): Add new parameter. Handle new
- template-function mangling.
- (consume_count_with_underscores): New function.
- (demangle_signature): Handle new name-mangling scheme.
+ * i386/mingw32.h (CPP_PREDEFINES): Add __MSVCRT__ for msvc
+ runtime.
+ * i386/crtdll.h (CPP_PREDEFINES): Define.
-Sun Sep 28 01:55:04 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+Sat Sep 5 03:23:05 1998 Jeffrey A Law (law@cygnus.com)
- * flow.c (print_rtl_with_bb): Cast alloca return values for variables
- start and end.
+ * m68k.md (5200 movqi): Do not allow byte sized memory references
+ using address regs.
+ * m68k.c (output_move_qimode): Do not use byte sized operations on
+ address registers.
-Sun Sep 28 01:05:16 1997 Jeffrey A Law (law@cygnus.com)
+ * Makefile.in (pexecute.o): Use pexecute.c from libiberty. Provide
+ explicit rules for building. Similarly for alloca, vfprintf,
+ choose-temp and mkstemp, getopt, getopt1, and obstack.
+ (INCLUDES): Add $(srcdir)/../include.
+ * pexecute.c, alloca.c, vfprintf.c, choose-temp.c, mkstemp.c: Delete.
+ * getopt.h, getopt.c getopt1.c, obstack.c, obstack.h: Likewise.
- * frame.c: Remove last change.
- * dwarf2.h: Remove last change.
- * tree.h: Add declarations of DWARF2 unwind info support
- functions.
+Fri Sep 4 11:57:50 1998 Tom Tromey <tromey@cygnus.com>
-Sat Sep 27 11:02:38 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * gcc.c (do_spec_1): [case 'o'] Account for
+ lang_specific_extra_outfiles.
+ (main): Correctly clear all slots in outfiles for
+ lang_specific_extra_outfiles. Set input_file_number before
+ calling lang_specific_pre_link.
- * c-decl.c (init_decl_processing): Add __builtin_dwarf_reg_size.
- * tree.h (built_in_function): Likewise.
- * expr.c (expand_builtin): Likewise.
- * except.h: Likewise.
- * dwarf2out.c (expand_builtin_dwarf_reg_size): New fn.
- * libgcc2.c (copy_reg): New fn.
- (__throw): Use it.
+Fri Sep 4 10:37:07 1998 Jim Wilson <wilson@cygnus.com>
-Fri Sep 26 08:54:59 1997 Paul Eggert <eggert@twinsun.com>
+ * loop.c (load_mems): Fix JUMP_LABEL field after for_each_rtx call.
- * c-typeck.c (build_binary_op): Warn about comparing signed vs
- unsigned if -W is specified and -Wno-sign-compare is not.
- * c-decl.c (warn_sign_compare): Initialize to -1.
- (c_decode_option): -Wall no longer implies -Wsign-compare.
+Fri Sep 4 02:01:05 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Fri Sep 26 09:00:13 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * config/sparc/sparc.c (output_double_int): In all V9 symbolic
+ cases, use xword.
+ (sparc_output_deferred_case_vectors): If no work to do, return.
+ Fix thinko in Sept 1 change.
- * frame.c: Include gansidecl.h for PROTO.
- * dwarf2out.c: Move inclusion of dwarf2.h down so that PROTO is
- defined. Don't declare dwarf2out_cfi_label here.
- * dwarf2.h: Add declarations of DWARF2 unwind info support
- functions.
- * m68k.c: Include dwarf2.h.
- (output_function_prologue): Add dwarf2 support.
- * m68k.h (INCOMING_RETURN_ADDR_RTX, DWARF_FRAME_REGNUM): New macros.
- (INCOMING_FRAME_SP_OFFSET): Likewise.
+1998-09-03 SL Baur <steve@altair.xemacs.org>
- * integrate.c (expand_inline_function): Make sure there is at
- least one insn that can be used as an insertion point.
+ * Makefile.in: Add semicolon in BISON definition for portability.
-Wed Sep 24 21:34:06 1997 Jason Merrill <jason@yorick.cygnus.com>
+Thu Sep 3 13:34:41 1998 Toon Moene <toon@moene.indiv.nluug.nl>
- * dwarf2out.c: s/flag_verbose_asm/flag_debug_asm/
+ * config/nextstep.c (handle_pragma): Correct name of third
+ argument.
-Wed Sep 24 22:05:30 1997 Jeffrey A Law (law@cygnus.com)
+Tue Sep 1 11:30:33 1998 Nick Clifton <nickc@cygnus.com>
- * version.c: Bump for snapshot.
+ * config/m32r/m32r.md: Change (reg:CC 17) to (reg:SI 17).
+ * config/m32r/m32r.h: Make register 17 be fixed.
+ * config/m32r/m32r.c: Use SImode for cc operations.
-Wed Sep 24 17:36:23 1997 Doug Evans <dje@canuck.cygnus.com>
-
- Bring over from FSF.
-
- Wed Sep 24 19:17:08 1997 Doug Evans <dje@cygnus.com>
-
- * sparc/sparc.md (get_pc_via_call): Renamed from get_pc_sp32.
- (get_pc_via_rdpc): Renamed from get_pc_sp64.
- * sparc/sparc.c (finalize_pic): Update call to gen_get_pc_via_call.
-
- Wed Sep 24 18:38:22 1997 David S. Miller <davem@tanya.rutgers.edu>
-
- * sparc/sparc.h (ASM_CPU_SPEC): Pass -Av9a for v8plus, ultrasparc.
- (TARGET_OPTIONS): Add -malign-loops=, -malign-jumps=,
- -malign-functions=.
- (sparc_align_{loops,jumps,funcs}_string): Declare.
- (sparc_align_{loops,jumps,funcs}): Declare.
- (DEFAULT_SPARC_ALIGN_FUNCS): New macro.
- (FUNCTION_BOUNDARY): Use sparc_align_funcs.
- (STACK_BIAS): Define.
- (SPARC_SIMM*_P): Cast to unsigned HOST_WIDE_INT first, then perform
- test.
- (SPARC_SETHI_P): New macro.
- (CONST_OK_FOR_LETTER_P): Use it.
- (ASM_OUTPUT_ALIGN_CODE): Define.
- (ASM_OUTPUT_LOOP_ALIGN): Define.
- * sparc/sparc.c (sparc_align_{loops,jumps,funcs}_string): New globals.
- (sparc_align_{loops,jumps,funcs}): New globals.
- (sparc_override_options): Handle -malign-loops=, -malign-jumps=,
- -malign-functions=.
- (move_operand): Use SPARC_SETHI_P.
- (arith_double_operand): Cast to unsigned HOST_WIDE_INT first, then
- perform test.
- (arith11_double_operand): Likewise.
- (arith10_double_operand): Likewise.
- (finalize_pic): Finish sparc64 support.
- (emit_move_sequence): Use SPARC_SETHI_P. Simplify low part of
- 64 bit constants if able.
- (output_fp_move_quad): Don't use fmovq unless TARGET_HARD_QUAD.
- (sparc_builtin_saveregs, sparc64 case): Don't save fp regs if
- ! TARGET_FPU.
- * sparc/sparc.md (*): Use GEN_INT instead of gen_rtx.
- (get_pc_sp32): Use for sparc64 as well.
- (lo_sum_di_sp{32,64}): Fix handling on 64 bit hosts.
- (sethi_di_sp64_const): Likewise.
- (movtf_cc_sp64): Check TARGET_HARD_QUAD.
- (cmp_zero_extract_sp64): Use unsigned HOST_WIDE_INT in cast.
- (ashlsi3, ashldi3, ashrsi3, ashrdi3, lshrsi3, lshrdi3): Likewise.
+Thu Sep 3 18:17:34 1998 Benjamin Kosnik <bkoz@cygnus.com>
- Tue Sep 23 19:02:46 1997 Doug Evans <dje@cygnus.com>
+ * invoke.texi (Warning Options): Add -Wnon-template-friend
+ documentation.
- * sparc/linux-aout.h (COMMENT_BEGIN): Delete.
- * sparc/linux.h (COMMENT_BEGIN): Likewise.
- * sparc/linux64.h (COMMENT_BEGIN): Likewise.
+Thu Sep 3 18:16:16 1998 Michael Meissner <meissner@cygnus.com>
- Tue Sep 23 14:48:18 1997 David S. Miller <davem@tanya.rutgers.edu>
+ * rs6000.c (rs6000_override_options): Add -mcpu={401,e603e}.
- Add sparc64 linux support.
- * configure.in (sparc64-*-linux*): Recognize. Add sparc/xm-sparc.h
- to xm_file list on 32-bit sparc-linux.
- * sparc/xm-sp64.h: New file.
- * sparc/linux64.h: New file.
- * sparc/xm-linux.h: Include some standard headers if not inhibit_libc.
- Don't include xm-sparc.h.
- * config/xm-linux.h (HAVE_PUTENV, HAVE_ATEXIT): Define.
- * glimits.h (LONG_MAX): Handle sparc64.
+Thu Sep 3 18:05:16 1998 David Edelsohn <edelsohn@gnu.org>
- Sat Sep 20 03:07:54 1997 Doug Evans <dje@cygnus.com>
+ * rs6000.md (movsf): Disable explicit secondary-reload-like
+ functionality if TARGET_POWERPC64.
+ (movdf): Remove TARGET_POWERPC64 explicit secondary-reload-like
+ functionality.
- * sparc/sysv4.h (ASM_COMMENT_START): Delete.
- * sparc.h (ASM_COMMENT_START): Define.
- * sparc.c (output_function_prologue): Use it.
- (sparc_flat_output_function_{epi,pro}logue): Likewise.
+Thu Sep 3 11:41:40 1998 Robert Lipe <robertl@dgii.com>
- Wed Sep 17 15:04:19 1997 Doug Evans <dje@cygnus.com>
-
- * sparc/sysv4.h (ASM_OUTPUT_{FLOAT,DOUBLE,LONG_DOUBLE}): Delete,
- use sparc.h's copies.
- * sparc/sparc.h (ASM_OUTPUT_{FLOAT,DOUBLE,LONG_DOUBLE}): Print
- ascii form as well.
+ * fixinc.sco: Borrow code to wrap 'bool' typedefs from tinfo.h
+ and term.h from fixinc.wrap.
- Mon Sep 8 08:45:19 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+Thu Sep 3 09:47:31 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * sparc.c (dwarf2out_cfi_label): Add declaration.
- (save_regs, output_function_prologue): Remove cast for it.
- (sparc_flat_{save_restore,output_function_prologue): Likewise.
- ({save,restore}_regs): No longer inline.
+ * aclocal.m4 (GCC_HEADER_STRING): New macro to detect if it is
+ safe to include both string.h and strings.h together.
+ (GCC_NEED_DECLARATION): Test STRING_WITH_STRINGS when deciding
+ which headers to search for function declarations. Continue to
+ prefer string.h over strings.h when both are not acceptable.
-Tue Sep 23 12:34:51 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * acconfig.h (STRING_WITH_STRINGS): Add stub.
- * fold-const.c (make_range): Correctly handle cases of converting
- from unsigned to signed type.
+ * configure.in: Call GCC_HEADER_STRING.
-Tue Sep 23 12:34:51 1997 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+ * system.h: Test STRING_WITH_STRINGS when deciding which headers
+ to include. Continue to prefer string.h over strings.h when both
+ are not acceptable.
- * fold-const.c (merge_ranges): Make sure that if one range is subset
- of another, it will always be the second range. Correct (+,-) case to
- account for this.
+Wed Sep 2 23:56:29 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Tue Sep 23 08:32:51 1997 Jason Merrill <jason@yorick.cygnus.com>
-
- * final.c (final_end_function): Also do dwarf2 thing if
- DWARF2_DEBUGGING_INFO.
- (final_start_function): Likewise.
-
-Tue Sep 23 01:15:50 1997 David S. Miller <davem@tanya.rutgers.edu>
-
- * expmed.c (expand_divmod): If compute_mode is not the same as
- mode, handle the case where convert_modes() causes op1 to no
- longer be a CONST_INT.
-
- * reorg.c (dbr_schedule): At end of this pass, add REG_BR_PRED
- note holding get_jump_flags() calculation to all JUMP_INSNs.
- * rtl.h (enum reg_note): New note types REG_BR_PRED and REG_SAVE_AREA.
- * rtl.c (reg_note_name): Add new note types.
-
-Tue Sep 23 00:59:54 1997 Jeffrey A Law (law@cygnus.com)
-
- * rtlanal.c (computed_jump_p): Fix typo in last change.
-
-Tue Sep 23 00:42:44 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+ * config/sparc/sparc.c (output_double_int): If V9 and MEDLOW, do
+ not assume top 32-bits of symbolic addresses are zero if
+ flag_pic.
- * loop.c (indirect_jump_in_function_p): Return 0
- by default.
+Thu Sep 3 00:23:21 1998 Richard Henderson <rth@cygnus.com>
-Tue Sep 23 00:33:55 1997 Jeffrey A Law (law@cygnus.com)
+ * ginclude/va-alpha.h: Protect entire second portion of the
+ file against double inclusion.
- * rs6000/xm-rs6000.h: Fix thinko in last change.
- * rs6000/xm-sysv4.h: Likewise.
+Thu Sep 3 00:37:55 1998 Ovidiu Predescu <ovidiu@aracnet.com>
-Mon Sep 22 19:33:53 1997 Jim Wilson <wilson@cygnus.com>
+ Added support for the Boehm's garbage collector.
+ * configure.in: Handle --enable-objc-gc.
+ * configure: Rebuilt.
+ * Makefile.in (CHECK_TARGETS): Add check-objc.
+ (check-objc): New rule.
+ * objc/Make-lang.in: Build a different Objective-C library that
+ runs with the Boehm's collector.
+ * objc/encoding.c (objc_round_acc_size_for_types): New function.
+ * objc/encoding.c: Correctly compute the size of compound types in
+ the presence of bitfields. Skip the variable name of the type if
+ any. Added support for long long.
+ * objc/encoding.h (_C_GCINVISIBLE): New specifier.
+ (_F_GCINVISIBLE): New mask.
+ * objc/gc.c: New file. Compute the type memory mask associated with
+ a class based on the runtime information.
+ * objc/misc.c: Added the hooks that use the Boehm's collector
+ allocation functions.
+ * objc/objc-act.c (build_class_template): Generate a new class
+ member (gc_object_type) to hold the class' type memory mask.
+ (build_shared_structure_initializer): Initialize the new member to
+ NULL.
+ (encode_complete_bitfield): New function. Generate the new
+ encoding.
+ (encode_field_decl): Generate the new encoding only for the GNU
+ runtime.
+ * objc/objc-api.h (_C_LNG_LNG, _C_ULNG_LNG): New specifiers for the
+ long long types.
+ (class_get_gc_object_type): New function to mark a pointer instance
+ variable as a weak pointer.
+ * objc/objc-features.texi: New file.
+ * objc/objc.h (gc_object_type): New class member.
+ * objc/objects.c (class_create_instance): Create a typed memory
+ object when compiled with Boehm's collector support.
+ * objc/sendmsg.c (__objc_init_install_dtable): Call
+ __objc_send_initialize instead of setting the initialize flag.
+ (__objc_send_initialize): Call __objc_generate_gc_type_description
+ to generate the class type memory mask. Rewrite the code that
+ sends the +initialize so that it is called only once (bug report
+ and fix from Ronald Pijnacker <Ronald.Pijnacker@best.ms.philips.com>).
+ * testsuite/objc: New testsuite for Objective-C type encoding.
+ * testsuite/lib/objc-torture.exp: New file.
+ * testsuite/lib/objc.exp: New file.
- * mips.c (save_restore_insns): Only set RTX_FRAME_RELATED_P if store_p.
+Wed Sep 2 14:47:36 1998 Jim Wilson <wilson@cygnus.com>
-Mon Sep 22 14:41:00 1997 Jeffrey A Law (law@cygnus.com)
+ * jump.c (jump_optimize): In if/then/else transformations, add
+ another call to modified_between_p for the jump insn.
- * reg-stack.c (find_blocks): Fix thinko in last change.
+Wed Sep 2 14:16:49 1998 Jeffrey A Law (law@cygnus.com)
-1997-09-21 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * fix-header.c (symlink): Treat like readlink.
- * m68k.c (output_function_prologue): Add dwarf2 support.
+Wed Sep 2 19:30:06 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * m68k.h (INCOMING_RETURN_ADDR_RTX, DWARF_FRAME_REGNUM,
- INCOMING_FRAME_SP_OFFSET): New definitions.
+ * dwarfout.c (fundamental_type_code): Encode 32 bit floats/doubles
+ as FT_float.
-Mon Sep 22 11:36:42 1997 David S. Miller <davem@tanya.rutgers.edu>
+Wed Sep 2 10:06:07 1998 Nick Clifton <nickc@cygnus.com>
- * combine.c (try_combine): Use NULL_RTX instead of '0' where
- appropriate in calls to gen_rtx().
- * cse.c (cse_main): Likewise.
- * emit-rtl.c (gen_label_rtx): Likewise.
- * expr.c (init_expr_once): Likewise.
- * haifa-sched.c (flush_pending_lists, sched_analyze_insn,
- sched_analyze, init_rgn_data_dependences,
- compute_block_backward_dependences): Likewise.
- * sched.c (schedule_insns): Likewise.
- * varasm.c (immed_double_const): Likewise.
+ * config/nextstep.h: Update HANDLE_PRAGMA macro.
+ * config/h8300/h8300.h: Update HANDLE_PRAGMA macro.
+ * config/i960/i960.h: Update HANDLE_PRAGMA macro.
- * sparc.h (INCOMING_FRAME_SP_OFFSET): Define to
- SPARC_STACK_BIAS for sake of dwarf2 on sparc64.
+ * config/nextstep.c (handle_pragma): Take three arguments, as per
+ the new HANDLE_PRAGMA macro specification.
+ * config/h8300/h8300.c (handle_pragma): Take three arguments, as
+ per the new HANDLE_PRAGMA macro specification.
+ * config/i960/i960.c (process_pragma): Take three arguments, as
+ per the new HANDLE_PRAGMA macro specification.
-Mon Sep 22 11:21:33 1997 J. Kean Johnston <jkj@sco.com>
+Wed Sep 2 09:25:29 1998 Nick Clifton <nickc@cygnus.com>
- * i386/sco5.h: Make ELF default file format and add -mcoff/-melf..
- (MULTILIB_DEFAULTS): Define.
- (ASM_SPEC, CPP_SPEC): Handle -mcoff.
- (STARTFILE_SPEC, ENDFILE_SPEC, LINK_SPEC): Likewise.
- (LIBGCC_SPEC): Likewise.
- (MASK_COFF, TARGET_COFF, TARGET_ELF): Define.
- (SUBTARGET_SWITCHES): Add -mcoff and -melf.
- * i386/t-sco5 (CRTSTUFF_T_CFLAGS): Add -fPIC.
- (CRTSTUFF_T_CFLAGS_S): Tweak for COFF.
- (EXTRA_PARTS, TAROUTOPTS): Delete.
- (libgcc1-elf, libgcc2-elf, libgcc-elf targets): Delete.
- (MULTILIB_OPTIONS): Define.
- (MULTILIB_DIRNAMES, MULTILIB_EXCEPTIONS): Likewise.
- (MULTILIB_MATCHE, MULTILIB_EXTRA_OPTS): Likewise.
+ * c-lex.c (check_newline): Call HANDLE_PRAGMA before
+ HANDLE_SYSV_PRAGMA if both are defined. Generate warning messages
+ if unknown pragmas are encountered.
+ (handle_sysv_pragma): Interpret return code from
+ handle_pragma_token (). Return success/failure indication rather
+ than next unprocessed character.
+ (pragma_getc): New function: retrieves characters from the
+ input stream. Defined when HANDLE_PRAGMA is enabled.
+ (pragma_ungetc): New function: replaces characters back into the
+ input stream. Defined when HANDLE_PRAGMA is enabled.
-Mon Sep 22 02:10:43 1997 Jeffrey A Law (law@cygnus.com)
+ * c-pragma.c (handle_pragma_token): Return success/failure status
+ of the parse.
- * version.c: Bump for snapshot.
+ * c-pragma.h: Change prototype of handle_pragma_token().
-Sun Sep 21 17:45:45 1997 Jeffrey A Law (law@cygnus.com)
+ * varasm.c (handle_pragma_weak): Only create this function if
+ HANDLE_PRAGMA_WEAK is defined.
- * loop.c (loop_number): Delete function. Change all references
- to use uid_loop_num array.
- * loop.h (loop_number): Delete declaration.
- * unroll.c (unroll_loop): Change "loop_number" references to
- use uid_loop_num instead.
+ * c-common,c (decl_attributes): If defined call the expression
+ contained within the INSERT_ATTRIBUTES macro before adding
+ attributes to a decl.
- * loop.c (loop_unroll_factor): Move outside #ifdef HAIFA
- conditional.
- (loop_unroll_iter): Remove unused variable and all references.
- (loop_optimize): Always allocate and clear space for loop_unroll_factor.
- (insert_bct): Fix minor formatting problems.
- * loop.h (loop_unroll_factor): Move decl outside #ifdef HAIFA.
- (loop_unroll_iter): Removed unused decl.
- * unroll.c (unroll_loop): Remove code to set loop_unroll_iter.
- Always record the unrolling factor.
+ * tm.texi (HANDLE_PRAGMA): Document the new version of
+ HANDLE_PRAGMA, which takes three arguments.
+ (INSERT_ATTRIBUTES): Document this new macro.
- * cse.c (simplify_relational_operation): Set h0u just like h0s.
- Similarly for h1u and h1s.
+ * LANGUAGES: Document the new version of HANDLE_PRAGMA and the
+ new INSERT_ATTRIBUTES macro.
- * flow.c (jmp_uses_reg_or_mem): Deleted unused function.
- (find_basic_blocks): Use computed_jump_p to determine if a
- particular JUMP_INSN is a computed jump.
- * reg-stack.c (find_blocks): Use computed_jump_p to determine
- if a particular JUMP_INSN is a computed jump.
- * rtlanal.c (jmp_uses_reg_or_mem): New function.
- (computed_jump_p): Likewise.
- * rtl.h (computed_jump_p): Declare.
- * genattrtab.c (pc_rtx): Define and initialize.
- * loop.c (loop_optimize): Always determine if the current
- function has a computed jump.
- (indirect_jump_in_function_p): Use computed_jump_p to determine
- if a particular JUMP_INSN is a computed jump.
+Wed Sep 2 02:03:23 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * loop.c (fix_bct_param): Delete unused function.
- (check_bct_param): Likewise.
+ * config/sparc/sparc.md (movdf): Only generate special RTL for
+ LABEL_REFs when PIC.
+ (move_label_di): Remove.
+ (movdi_pic_label_ref, movdi_high_pic_label_ref,
+ movdi_lo_sum_pic_label_ref): New patterns for 64-bit label
+ references when PIC.
+ * config/sparc/sparc.h (ASM_OUTPUT_ADDR_VEC_ELT,
+ ASM_OUTPUT_ADDR_DIFF_ELT): Don't do anything special for MEDLOW,
+ output an .xword for all 64-bit cases.
-Sat Sep 20 16:22:06 1997 Jason Merrill <jason@yorick.cygnus.com>
+Tue Sep 1 15:55:17 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * frame.c (__deregister_frame): Check properly for initialized object.
+ * config/sparc/sparc.c (finalize_pic): Don't output arbitrary
+ alignment, use FUNCTION_BOUNDARY instead.
+ (sparc_output_deferred_case_vectors): Likewise.
-Fri Sep 19 20:51:03 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+Mon Aug 31 17:25:41 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * alpha/linux.h (HANDLE_SYSV_PRAGMA): Defined.
+ * config/sparc/sparc.md (movsf_const_intreg): Kill warning.
+ (movtf_insn_sp64, movtf_no_e_insn_sp64): Reorder alternatives.
-Fri Sep 19 18:53:50 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Mon Aug 31 13:57:55 1998 Richard Henderson <rth@cygnus.com>
- * jump.c (thread_jumps): check can_reverse_comparison_p before
- threading a reversed-condition jump.
+ * alpha/va_list.h: New file.
+ * alpha/x-alpha (EXTRA_HEADERS): New. Add va_list.h.
- * sched.c (update_flow_info): Don't pass SCRATCH to dead_or_set_p.
- * haifa-sched.c (update_flow_info): Likewise.
+Mon Aug 31 14:55:02 1998 Jeffrey A Law (law@cygnus.com)
-Thu Sep 18 21:13:40 1997 Jeffrey A Law (law@cygnus.com)
+ * NEWS: Add SCO Openserver and Unixware 7 notes.
- * Makefile.in (BOOT_CFLAGS): Use -O2.
+ * NEWS: Fix typos.
- * configure.in (strtoul, bsearch): Have autoconf check for these
- functions.
- * configure, config.in: Rebuilt.
+Mon Aug 31 15:42:18 1998 Dave Brolley <brolley@cygnus.com>
- * m68k/xm-mot3300.h (alloca): Properly declare if __STDC__.
- * mips/mips.h (alloca): Likewise.
- * rs6000/xm-rs6000.h (alloca): Likewise.
- * rs6000/xm-sysv4.h: Likewise.
+ * varasm.c (compare_constant_1): Handle RANGE_EXPR.
+ (record_constant_1): Handle RANGE_EXPR.
-Thu Sep 18 14:22:22 1997 Jason Merrill <jason@yorick.cygnus.com>
+Mon Aug 31 10:54:03 1998 Richard Henderson <rth@cygnus.com>
- * final.c (final_scan_insn): Hand BARRIERs off to the dwarf2 code.
- * dwarf2out.c (dwarf2out_frame_debug): Pass the whole insn along.
- (dwarf2out_stack_adjust): A BARRIER resets the args space to 0.
+ * print-rtl.c (print_rtx): NOTE_INSN_LIVE has an rtx not a bitmap.
+ * haifa-sched.c (sched_analyze): Handle NOTE_INSN_RANGE_START
+ and NOTE_INSN_RANGE_END specially.
+ (reemit_notes): Likewise.
- * except.c (end_eh_unwinder): Subtract 1 from return address.
- * libgcc2.c (__throw): Likewise.
- (find_exception_handler): Don't change PC here. Compare end with >.
+Mon Aug 31 10:18:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Thu Sep 18 10:43:07 1997 Nick Clifton <nickc@cygnus.com>
+ * sparc.c (TMASK, UMASK): Use `(unsigned)1' not `1U'.
+ (ultrasparc_sched_init): Remove unneeded &.
- * v850.c (compute_register_save_size): Correct register
- number.
- * v850.md (save_interrupt, return_interrupt): Correct
- register number.
- * v850/lib1funcs.asm (save_interrupt): Correct register number.
- (return_interrupt): Use stack pointer, not element pointer.
+Mon Aug 31 10:47:16 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-1997-09-18 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * config/m68k/m68k.h (TARGET_SWITCHES): Don't remove MASK_68040
+ for m68020-60, to prevent the use of fintrz.
- * configure.in, configure: Make sure to create the stage* and include
- symbolic links in each subdirectory.
+Sun Aug 30 22:17:20 1998 Mark Mitchell <mark@markmitchell.com>
-Thu Sep 18 01:47:06 1997 Jeffrey A Law (law@cygnus.com)
+ * configure.in: If the native compiler is GCC use $(WARN_CFLAGS)
+ even in stage1.
+ * Makefile.in: Likewise.
+ * configure: Regenerated.
- * pa.md (reload_peepholes): Don't allow addresses with side
- effects for the memory operand.
+Sun Aug 30 22:15:41 1998 H.J. Lu (hjl@gnu.org)
-Wed Sep 17 18:19:53 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * configure.in (gxx_include_dir): Changed to
+ '${prefix}/include/g++'-${libstdcxx_interface}.
+ * configure: Rebuilt.
- * libgcc2.c (find_exception_handler): Subtract one from our PC when
- looking for a handler, to avoid hitting the beginning of the next
- region.
+Sun Aug 30 20:19:43 1998 Hans-Peter Nilsson <hp@axis.se>
- * except.c (expand_builtin_set_return_addr_reg): Use force_operand.
+ * expr.c (expand_expr): Change ">" to ">=" making MOVE_RATIO use
+ consistent.
+ * tm.texi (Costs): Say MOVE_RATIO is number of mem-mem move
+ *sequences* *below* which scalar moves will be used.
-Wed Sep 17 18:33:59 1997 Jeffrey A Law (law@cygnus.com)
+Sun Aug 30 17:18:43 1998 Jeffrey A Law (law@cygnus.com)
- * mips/abi64.h (LONG_MAX_SPEC): Define.
- * mips.h (LONG_MAX_SPEC): Define.
- (CPP_SPEC): Include long_max_spec.
- (EXTRA_SPECS): Include long_max_spec.
+ * collect2.c (mktemp): Delete unused declaration.
-Wed Sep 17 14:11:38 1997 Jeffrey A Law (law@cygnus.com)
+ * config/xm-netbsd.h: Remove unnecessary file.
+ * config/*/xm-netbsd.h: Do not include the generic xm-netbsd.h
+ file anymore, it is not needed.
- * v850.c (construct_save_jarl): Fix thinko in last change.
+Sun Aug 30 16:05:45 1998 Mark Mitchell <mark@markmitchell.com>
-Wed Sep 17 09:53:07 1997 Jeffrey A Law (law@cygnus.com)
+ * convert.c (convert_to_integer): Issue an error on conversions to
+ incomplete types.
- * version.c: Bump for snapshot.
+Sun Aug 30 16:47:20 1998 Martin von Lvwis <loewis@informatik.hu-berlin.de>
-Tue Sep 16 14:22:36 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * Makefile.in: Add lang_tree_files and gencheck.h.
+ * configure.in: Generate them.
+ * gencheck.c: Include gencheck.h.
- * libgcc2.c (find_exception_handler): Not found is -1.
+Sat Aug 29 21:38:24 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * integrate.c (expand_inline_function): Move expand_start_bindings
- after expanding the arguments.
+ * config/sparc/sparc.md (pic_lo_sum_di, pic_sethi_di): Rename to
+ movdi_lo_sum_pic and movdi_high_pic and make visible.
+ * config/sparc/sparc.c (legitimize_pic_address): For -fPIC,
+ emit these when Pmode is not SImode.
+ * config/sparc/linux64.h (SPARC_DEFAULT_CMODEL): Make CM_MEDLOW.
-Tue Sep 16 11:13:46 1997 Jim Wilson <wilson@cygnus.com>
+Sat Aug 29 14:59:32 1998 Mumit Khan <khan@xraylith.wisc.edu>
- * expr.c (expand_expr): Remove previous incorrect change.
- If target and slot has no DECL_RTL, then call mark_addressable
- again for the slot after we give it RTL.
+ * i386/cygwin32.h (ASM_OUTPUT_SECTION_NAME): Don't emit
+ .linkonce directive after the first time.
-Tue Sep 16 09:18:52 1997 Jason Merrill (jason@cygnus.com)
+Sat Aug 29 12:39:56 1998 Jeffrey A Law (law@cygnus.com)
- * expr.c (expand_expr, case TARGET_EXPR): Call mark_addressable
- again for the slot after we give it RTL.
+ * m68k.md (beq0_di): Generate correct (and more efficient) code when
+ the clobbered operand overlaps with an input.
+ (bne0_di): Similarly.
-Tue Sep 16 00:13:20 1997 Nick Clifton <nickc@cygnus.com>
+ * Makefile.in (INSTALL): Remove "--no-header" argument.
- * v850.c (register_is_ok_for_epilogue,
- pattern_is_ok_for_epilogue, construct_restore_jr,
- pattern_is_ok_for_prologue, construct_save_jarl): New functions.
+ * NEWS: Various updates.
- * v850.h (pattern_is_ok_for_prologue,
- pattern_is_ok_for_epilogue, register_is_ok_for_epilogue): New
- predicates.
+Fri Aug 28 19:00:44 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * v850.md: Replace prologue and epilogue patterns with a
- match_parallel pattern.
+ * config/sparc/sparc.c (arith_operand, const64_operand,
+ const64_high_operand, arith_double_4096_operand): Mark mode as
+ unused.
+ (create_simple_focus_bits): Remove unused arg highest_bit_set, all
+ callers changed.
+ (sparc_emit_set_const64): Remove unused variable i.
+ (sparc_splitdi_legitimate): Likewise for addr_part.
+ (ultra_code_from_mask): Likewise for mask.
+ (ultra_cmove_results_ready_p): Fixup entry modulo calc. and
+ reverse return values so it matches usage and comments.
+ (ultra_flush_pipeline): Likewise.
+ (ultra_fpmode_conflict_exists): Likewise, remove unused variable
+ this_type, and allow loads and stores of differing FP modes as
+ they do not create a conflict.
+ (ultra_find_type): Initialize fpmode to SFmode, fix
+ parenthesization thinkos in large conditional.
+ (ultrasparc_sched_init): Mark dump and sched_verbose as unused.
+ Init free_slot_mask after ultra_cur_hist is reset, not before.
+ (ultrasparc_rescan_pipeline_state): Remove unused variable ucode.
+ (ultrasparc_sched_reorder): Don't bzero current pipeline state,
+ use ultra_flush_pipeline instead, then re-init group pointer.
+ Fix statement with no effect. If no progress made in, and no
+ instructions scheduled at all, advance to new pipeline cycle else
+ we get into an endless loop.
+ (ultrasparc_adjust_cost): Remove previous arg.
+ * config/sparc/sparc.h (ADJUST_COST): Update to reflect that.
-Mon Sep 15 22:53:01 1997 Jeffrey A Law (law@cygnus.com)
+Fri Aug 28 13:52:35 1998 Jim Wilson <wilson@cygnus.com>
- * aclocal.m4: Add replacement for AC_PROG_INSTALL.
- * configure.in: Use EGCS_PROG_INSTALL.
+ * sparc.md (DImode, DFmode, TFmode splits): Delete self_reference
+ code. Use reg_overlap_mentioned_p to detect when source and
+ destination overlap.
+ (negtf2_notv9+1): Use DFmode instead of SFmode in last two operands.
-Mon Sep 15 22:40:55 1997 Jim Wilson (wilson@cygnus.com)
+1998-08-28 Brendan Kehoe <brendan@cygnus.com>
- * dwarf2out.c (gen_subprogram_die): Handle redefinition of an
- extern inline function.
+ * loop.c (check_dbra_loop): Pass COMPARISON_VALUE, not
+ COMPARISON_VAL, into invariant_p.
-Mon Sep 15 22:40:55 1997 Richard Henderson (rth@cygnus.com)
+Fri Aug 28 15:13:25 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * dwarf2out.c (reg_loc_descriptor): Fix prototype.
- (concat_loc_descriptor): New function.
- (loc_descriptor): Call it.
- (add_AT_location_description): Also elide the descriptor if both
- halves of a CONCAT are pseudos.
- (add_location_or_const_value_attribute): Recognize CONCAT too.
+ * regmove.c (regclass_compatible_p): New function.
+ (regmove_optimize): Use it.
-Mon Sep 15 15:24:00 1997 Richard Henderson <rth@cygnus.com>
+ Use NREGS parameter instead of calling max_reg_num.
- * alpha.md (movdi): Handle CONST_DOUBLE for TARGET_BUILD_CONSTANTS.
+ (fixup_match_1): Don't use code = MINUS when later tieing with
+ a hard register is likely.
- * alpha/alpha.c (output_prolog): New variable sa_reg. Use it for
- out-or-range reg_offset.
- (output_epilog): Likewise.
+Fri Aug 28 14:54:07 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Mon Sep 15 15:39:26 1997 Jeffrey A Law (law@cygnus.com)
+ * loop.c (check_dbra_loop): Fix calculation of FINAL_VALUE when
+ COMPARISON_VAL was normalized.
- * cse.c (simplify_relational_operation): If MODE specifies a
- mode wider than HOST_WIDE_INT, then the high word of a CONST_INT
- is derived from the sign bit of the low word.
+Thu Aug 27 20:10:46 1998 Jeffrey A Law (law@cygnus.com)
-Mon Sep 15 11:43:38 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * loop.c (check_dbra_loop): The loop ending comparison value
+ must be an invariant or we can not reverse the loop.
- Support dwarf2 unwinding on PUSH_ROUNDING targets like the x86.
+ * loop.c (scan_loop): Count down from max_reg_num - 1 to
+ FIRST_PSEUDO_REGISTER to avoid calling max_reg_num each iteration
+ of the loop.
+ (load_mems_and_recount_loop_regs_set): Likewise.
- * dwarf2.h: Add DW_CFA_GNU_args_size.
- * frame.c (execute_cfa_insn): Likewise.
- * dwarf2out.c (dwarf_cfi_name, output_cfi): Likewise.
- (dwarf2out_args_size, dwarf2out_stack_adjust): New fns.
- (dwarf2out_frame_debug): If this isn't a prologue or epilogue
- insn, hand it off to dwarf2out_stack_adjust.
- (dwarf2out_begin_prologue): Initialize args_size.
- * frame.h (struct frame_state): Add args_size.
- * libgcc2.c (__throw): Use args_size.
- * final.c (final_scan_insn): If we push args, hand off all insns
- to dwarf2out_frame_debug.
- * defaults.h (DWARF2_UNWIND_INFO): OK for !ACCUMULATE_OUTGOING_ARGS.
+ * i386.c (print_operand): Remove obsolete 'c' docs.
- * dwarf2out.c dwarf2out_frame_debug): Fix typo.
- Handle epilogue restore of SP from FP.
- * emit-rtl.c (gen_sequence): Still generate a sequence if the
- lone insn has RTX_FRAME_RELATED_P set.
+Wed Aug 26 17:13:37 1998 Tom Tromey <tromey@cygnus.com>
- * frame.c (extract_cie_info): Handle "e" augmentation.
- * dwarf2out.c (ASM_OUTPUT_DWARF_*): Provide definitions in the
- absence of UNALIGNED_*_ASM_OP.
- (UNALIGNED_*_ASM_OP): Only provide defaults if OBJECT_FORMAT_ELF.
- (output_call_frame_info): Use "e" instead of "z" for augmentation.
- Don't emit augmentation fields length.
- (dwarf2out_do_frame): Move outside of #ifdefs.
- * defaults.h (DWARF2_UNWIND_INFO): Don't require unaligned data
- opcodes.
+ * gthr.h: Document __GTHREAD_MUTEX_INIT_FUNCTION.
+ * frame.c (init_object_mutex): New function.
+ (init_object_mutex_once): Likewise.
+ (find_fde): Call it.
+ (__register_frame_info): Likewise.
+ (__register_frame_info_table): Likewise.
+ (__deregister_frame_info): Likewise.
- * sparc.h (UNALIGNED_INT_ASM_OP et al): Don't define here after all.
- * sparc/sysv4.h (UNALIGNED_INT_ASM_OP): Define here.
- * sparc/sunos4.h (DWARF2_UNWIND_INFO): Define to 0.
- * sparc/sun4gas.h: New file.
- * configure.in: Use sun4gas.h if SunOS 4 --with-gnu-as.
+Thu Aug 27 15:14:18 1998 Jeffrey A Law (law@cygnus.com)
- * collect2.c (write_c_file_stat, write_c_file_glob): Declare
- __register_frame_table and __deregister_frame.
+ * haifa-sched.c (sched_analyze_insn): Fix thinko in last change.
-1997-09-15 Brendan Kehoe <brendan@cygnus.com>
+Thu Aug 27 16:34:51 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * except.c (find_exception_handler_labels): Use xmalloc instead of
- alloca, since MAX_LABELNO - MIN_LABELNO can be more than 1 million
- in some cases.
+ * loop.c (check_dbra_loop): Enable code for reversal
+ of some loops without a known constant loop end.
-Sun Sep 14 21:01:23 1997 Jeffrey A Law (law@cygnus.com)
+Wed Aug 26 18:38:15 1998 Richard Henderson <rth@cygnus.com>
- * Makefile.in: Various changes to build info files
- in the object tree rather than the source tree.
+ * haifa-sched.c (last_clock_var): New.
+ (schedule_block): Initialize it.
+ (schedule_insn): Use it to fill insn modes with issue information.
-Sun Sep 14 12:24:30 1997 Jeffrey A Law (law@cygnus.com)
+ * alpha.c (alpha_handle_trap_shadows): Remove do-nothing exit.
+ Tag trapb and next insn with TImode.
+ (alphaev5_insn_pipe, alphaev5_next_group, alphaev5_align_insns): New.
+ (alpha_reorg): Add conditional for alpha_handle_trap_shadows.
+ Invoke alphaev5_align_insns as appropriate.
+ * alpha.h (LABEL_ALIGN_AFTER_BARRIER): Was ALIGN_LABEL_AFTER_BARRIER.
+ (MD_SCHED_VARIABLE_ISSUE): New.
+ * alpha.md (attr type): Add multi.
+ (define_asm_attributes): New.
+ (prologue_stack_probe_loop, builtin_setjmp_receiver): Set type multi.
+ (arg_home): Likewise.
+ (fnop, unop, realign): New.
- * fixinc.math: New file to fix math.h on some systems.
- * configure.in (freebsd, netbsd): Use fixinc.math on these
- systems.
- * configure: Rebuilt.
+Wed Aug 26 15:55:41 1998 Jim Wilson <wilson@cygnus.com>
-Sun Sep 14 11:11:05 1997 Jeffrey A Law (law@cygnus.com)
+ * iris5.h (PREFERRED_DEBUGGING_TYPE): Undef.
+ * iris5gas.h (PREFERRED_DEBUGGING_TYPE): Define.
- * regmove.c (regmove_optimize): If we end up moving the
- original insn due to lifetime overlaps, make sure to move
- REG_NOTES too.
+ * configure.in (powerpc-ibm-aix4.[12]*): Change from 4.[12].*.
+ (rs6000-ibm-aix4.[12]*): Likewise.
+ * configure: Regenerate.
-Sat Sep 13 15:51:11 1997 Manfred Hollstein <manfred@s-direktnet.de>
+Wed Aug 26 09:30:59 1998 Nick Clifton <nickc@cygnus.com>
- * Makefile.in (INSTALL_{PROGRAM,DATA}): Use value found by configure.
+ * config/arm/thumb.c (thumb_exit): Do not move a4 into lr if it
+ already contains the return address.
-Sat Sep 13 12:57:26 1997 Jeffrey A Law (law@cygnus.com)
+Wed Aug 26 12:57:09 1998 Jeffrey A Law (law@cygnus.com)
- * haifa-sched.c (add_branch_dependences): Make each insn in
- a SCHED_GROUP_P block explicitly depend on the previous insn.
+ * calls.c (expand_call): Use bitfield instructions to extract/deposit
+ word sized hunks when loading unaligned args into registers.
-Fri Sep 12 13:49:58 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * haifa-sched.c (sched_analyze_insn): Only create scheduling
+ barriers for LOOP, EH and SETJMP notes on the loop_notes list.
- * except.h: Prototype dwarf2 hooks.
- * expr.c: Adjust.
+ * mn10300.h (RTX_COSTS): Handle UDIV and UMOD too.
-Thu Sep 11 17:43:55 1997 Jim Wilson <wilson@cygnus.com>
+Wed Aug 26 16:35:37 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
- * configure.in (native_prefix): Delete.
- (mips-dec-netbsd): Don't set prefix.
- (*linux*): Don't set prefix.
+ * loop.c (check_dbra_loop): Add some code that would allow reversal
+ of some loops without a known constant loop end if it were enabled.
-Thu Sep 11 15:48:32 1997 Fred Fish <fnf@ninemoons.com>
+Wed Aug 26 11:08:44 1998 Gavin Romig-Koch <gavin@cygnus.com>
- * protoize.c: Include <varargs.h> only if HAVE_VARARGS_H is
- defined. If not defined, include <sys/varargs.h> if
- HAVE_SYS_VARARGS_H is defined.
- * configure.in: Test for varargs.h and sys/varargs.h.
- * configure: Regenerate with autoconf.
- * config.in: Regenerate with autoheader.
+ * mips.md (lshrsi3_internal2+2): Fix type-o.
- * cpplib.c (quote_string): Cast first arg of sprintf call
- from "unsigned char *" to "char *".
- (output_line_command): Ditto.
- (macroexpand): Ditto.
- (do_line): Cast atoi arg from "unsigned char *" to "char *".
+Wed Aug 26 10:53:03 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Wed Sep 10 21:37:30 1997 Jeffrey A Law (law@cygnus.com)
+ * system.h: Include stdarg.h/varargs.h, make sure they are ordered
+ correctly with regards to stdio.h.
- * version.c: Bump for snapshot.
+ * calls.c: Remove stdarg.h/varargs.h.
+ * cccp.c: Likewise.
+ * cexp.y: Likewise.
+ * combine.c: Likewise.
+ * cpperror.c: Likewise.
+ * cpplib.c: Likewise.
+ * cpplib.h: Likewise.
+ * doprint.c: Likewise.
+ * emit-rtl.c: Likewise.
+ * final.c: Likewise.
+ * fix-header.c: Likewise.
+ * gcc.c: Likewise.
+ * genattr.c: Likewise.
+ * genattrtab.c: Likewise.
+ * gencodes.c: Likewise.
+ * genconfig.c: Likewise.
+ * genemit.c: Likewise.
+ * genextract.c: Likewise.
+ * genflags.c: Likewise.
+ * genopinit.c: Likewise.
+ * genoutput.c: Likewise.
+ * genpeep.c: Likewise.
+ * genrecog.c: Likewise.
+ * mips-tfile.c: Likewise.
+ * prefix.c: Likewise.
+ * protoize.c: Likewise.
+ * regmove.c: Likewise.
+ * toplev.c: Likewise.
+ * tree.c: Likewise.
+
+Wed Aug 26 05:09:27 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
+
+ * config/sparc/sparc.c (sparc_override_options): If not
+ TARGET_FPU, turn off TARGET_VIS.
+ * config/sparc/sparc.h (TARGET_SWITCHES): Add no-vis.
+ (LEGITIMATE_CONSTANT_P): Allow SF/DF mode zero when TARGET_VIS.
+ * config/sparc/sparc.md (movsi_insn): Use fzeros not fzero.
+ (movdi_insn_sp64): Add VIS fzero alternative.
+ (clear_sf, clear_df): New VIS patterns.
+ (movsf, movdf expanders): Allow fp_zero_operand flat out when
+ TARGET_VIS.
+ (one_cmpldi2_sp64): Provide new fnot1 VIS alternative.
+
+Tue Aug 25 10:57:41 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * loop.c (n_times_set, n_times_used, may_not_optimize,
+ reg_single_usage): Convert to varrays. All uses changed.
+ (insert_loop_mem): Return a value.
+ (scan_loop): Tweak AVOID_CC_MODE_COPIES code.
+ (load_mems_and_recount_loop_regs_set): Likewise. Grow the arrays, if
+ necessary.
- * Makefile.in (compare): Exit with nonzero status if there
- are comparison failures. Note which files failed the
- comparison test in .bad_compare.
+Tue Aug 25 23:57:12 1998 Jeffrey A Law (law@cygnus.com)
-Wed Sep 10 17:05:46 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+ * From Alexandre:
+ * configure.in: Do not set thread_file to "irix" since no such
+ support exists yet.
- * config/alpha/elf.h (CPP_PREDEFINES): Remove -D__PIC__ -D__pic__.
+ * sparc.md (float abs/neg splits): Check reload_completed before
+ calling alter_subreg.
-Wed Sep 10 16:37:28 1997 Fred Fish <fnf@ninemoons.com>
+Tue Aug 25 19:17:59 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * Makefile.in (LN, LN_S): New macros, use where appropriate.
- * aclocal.m4 (GCC_PROG_LN_S, GCC_PROG_LN): New tests.
- * configure.in: Use GCC_PROG_LN_S and GCC_PROG_LN.
- * configure: Regenerated.
+ * config/sparc/sparc.c (sparc_absnegfloat_split_legitimate): New
+ function.
+ * config/sparc/sparc.h: Declare it.
+ * config/sparc/sparc.md (float abs/neg splits): Use it.
+ (all other splits): Handle SUBREGs properly where necessary.
+ (unnamed (1<<x)-1 V8PLUS pattern): Disable for now.
-Thu Sep 11 11:09:43 1997 Jeffrey A Law (law@cygnus.com)
+Tue Aug 25 19:48:46 1998 Jeffrey A Law (law@cygnus.com)
- * loop.c (strength_reduce): Fix typo.
+ * reorg.c (fill_simple_delay_slots): Do not abort if we encounter
+ an insn on the unfilled_slots_list that has no delay slots.
+ (fill_eager_delay_slots): Similarly.
-Wed Sep 10 16:01:15 1997 Jim Wilson <wilson@cygnus.com>
+Tue Aug 25 13:35:20 1998 Nick Clifton <nickc@cygnus.com>
- * m88k/m88k.c (struct option): Rename to struct options.
- * m88k/dolph.h (INITIALIZE_TRAMPOLINE): Delete here.
- * m88k/sysv3.h (INITIALIZE_TRAMPOLINE): Delete ifdef and comments.
- * libgcc2.c (__enable_execute_stack): Check for __sysV88__ not
- __DOLPHIN__ or sysV88.
+ * config/v850/v850.c (movsi_source_operand): Treat CONSTANT_P_RTX
+ as an ordinary operand.
-Wed Sep 10 14:58:40 1997 Jim Wilson <wilson@cygnus.com>
+Tue Aug 25 12:54:57 1998 Jason Merrill <jason@yorick.cygnus.com>
- * emit-rtl.c (gen_lowpart_common): For a SUBREG, add in word when
- create new subreg.
+ * tree.c (valid_machine_attribute): Don't apply attributes to both
+ decl and type.
-Wed Sep 10 15:19:22 1997 Jeffrey A Law (law@cygnus.com)
+Tue Aug 25 12:23:20 1998 Richard Henderson <rth@cygnus.com>
- * config.sub: Accept 'amigados' for backward compatability.
+ * reload.c (operands_match_p): Handle rtvecs.
-Wed Sep 10 14:05:08 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+ * i386.c (legitimate_pic_address_disp_p): New.
+ (legitimate_address_p): Use it.
+ (legitimize_pic_address): Use unspecs to represent @GOT and @GOTOFF.
+ Handle constant pool symbols just like statics.
+ (emit_pic_move): Use Pmode not SImode for clarity.
+ (output_pic_addr_const) [SYMBOL_REF]: Remove @GOT and @GOTOFF hacks.
+ [UNSPEC]: New, handling what we killed above.
+ [PLUS]: Detect and abort on invalid symbol arithmetic.
+ * i386.h (CONSTANT_ADDRESS_P): Remove HIGH.
- * Makefile.in (testsuite/site.exp): New target.
- (check-gcc, check-g++): Depend on testsuite/site.exp.
- Don't stop for failure.
+Tue Aug 25 12:02:23 1998 Mark Mitchell <mark@markmitchell.com>
-Wed Sep 10 12:59:57 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * alias.c: Include output.h.
+ (DIFFERENT_ALIAS_SETS_P): Don't treat alias sets as
+ different if we're in a varargs function.
+ * Makefile.in (alias.o): Depend on output.h
- * expr.c (expand_builtin): Only support __builtin_dwarf_fp_regnum()
- if DWARF2_UNWIND_INFO.
+Tue Aug 25 19:20:12 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Wed Sep 10 11:49:20 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * sh.h (GIV_SORT_CRITERION): Delete.
- Add support for exception handling using DWARF 2 frame unwind info.
- Currently works on SPARC and MIPS, and almost on x86.
+Tue Aug 25 13:19:46 1998 Dave Brolley <brolley@cygnus.com>
- * libgcc2.c (get_reg, put_reg, get_return_addr, put_return_addr,
- next_stack_level, in_reg_window): Helper fns.
- (__throw): Implement for DWARF2_UNWIND_INFO.
+ * regclass.c (regclass): Use xmalloc/free instead of alloca.
+ * stupid.c (stupid_life_analysis): Likewise.
+ * reload1.c (reload): Likewise.
- * expr.c (expand_builtin): Handle builtins used by __throw.
- * tree.h (enum built_in_function): Add builtins used by __throw.
- * c-decl.c (init_decl_processing): Declare builtins used by __throw.
- * dwarf2out.c (expand_builtin_dwarf_fp_regnum): Used by __throw.
- * except.c (expand_builtin_unwind_init): Hook for dwarf2 __throw.
- (expand_builtin_extract_return_addr): Likewise.
- (expand_builtin_frob_return_addr): Likewise.
- (expand_builtin_set_return_addr_reg): Likewise.
- (expand_builtin_eh_stub): Likewise.
- (expand_builtin_set_eh_regs): Likewise.
- (eh_regs): Choose two call-clobbered registers for passing back values.
+Tue Aug 25 05:48:18 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
- * frame.c, frame.h: New files for parsing dwarf 2 frame info.
- * Makefile.in (LIB2ADD): New variable. Add $(srcdir)/frame.c.
- (libgcc2.a): Use it instead of $(LIB2FUNCS_EXTRA) $(LANG_LIB2FUNCS)
- (stmp-multilib): Likewise.
- ($(T)crtbegin.o, $(T)crtend.o): Add -fno-exceptions.
+ * config/sparc/sparc.c (arith_4096_operand, arith_add_operand,
+ arith_double_4096_operand, arith_double_add_operand): New
+ predicates.
+ * config/sparc/sparc.h (PREDICATE_CODES): Add them, declare them.
+ * config/sparc/sparc.md (adddi3, addsi3, subdi3, subsi3): Use
+ them to transform add/sub 4096 into add/sub -4096.
- * except.c: #include "defaults.h".
- (exceptions_via_longjmp): Default depends on DWARF2_UNWIND_INFO.
- (emit_throw): Don't defeat assemble_external if DWARF2_UNWIND_INFO.
- (register_exception_table_p): New fn.
- (start_eh_unwinder): Don't do anything if DWARF2_UNWIND_INFO.
- (end_eh_unwinder): Likewise.
+Mon Aug 24 23:31:03 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * crtstuff.c: Wrap .eh_frame section, use EH_FRAME_SECTION_ASM_OP,
- call __register_frame and __deregister_frame as needed.
- * varasm.c (eh_frame_section): New fn if EH_FRAME_SECTION_ASM_OP.
- * dwarf2out.c (EH_FRAME_SECTION): Now a function-like macro. Check
- EH_FRAME_SECTION_ASM_OP.
- * sparc/sysv4.h (EH_FRAME_SECTION_ASM_OP): Define.
- * mips/iris6.h: (EH_FRAME_SECTION_ASM_OP): Define.
- (LINK_SPEC): Add __EH_FRAME_BEGIN__ to hidden symbols.
+ * loop.c (scan_loop): Allocate some slop to handle pseudos
+ generated by move_movables.
+ (load_mems_and_recount_loop_regs_set): Honor AVOID_CC_MODE_COPIES
+ here too.
- * dwarf2out.c (output_call_frame_info): If no support for
- EXCEPTION_SECTION, mark the start of the frame info with a
- collectable tag.
- * collect2.c (frame_tables): New list.
- (is_ctor_dtor): Recognise frame entries.
- (scan_prog_file): Likewise.
- (main): Pass -fno-exceptions to sub-compile. Also do collection
- if there are any frame entries.
- (write_c_file_stat): Call __register_frame_table and
- __deregister_frame as needed.
- (write_c_file_glob): Likewise.
-
- * defaults.h (DWARF2_UNWIND_INFO): Default to 1 if supported.
- Also require unaligned reloc support.
- * sparc.h (UNALIGNED_SHORT_ASM_OP, UNALIGNED_INT_ASM_OP,
- UNALIGNED_DOUBLE_INT_ASM_OP): Define here.
- * sparc/sysv4.h: Not here.
-
- * toplev.c (compile_file): Call dwarf2out_frame_{init,finish}.
- * dwarf2out.c (dwarf2out_init): Don't call dwarf2out_frame_init.
- (dwarf2out_finish): Don't call dwarf2out_frame_finish.
-
- * libgcc2.c (L_eh): Reorganize, moving code shared by different
- EH implementations to the top.
- (find_exception_handler): Split out. Start from 0. Compare against
- end with >=.
- (__find_first_exception_table_match): Use it.
- * except.c (output_exception_table): Don't do anything if there's
- no table. Don't output a first entry of zeroes.
- (eh_outer_context): Adjust properly.
- (add_eh_table_entry): Use xrealloc.
- * toplev.c (compile_file): Just call output_exception_table.
-
-Wed Sep 10 11:30:36 1997 Jason Merrill <jason@cygnus.com>
-
- * i386.c (ix86_prologue): Add dwarf2 support for !do_rtl case.
-
-Wed Sep 10 08:17:10 1997 Torbjorn Granlund <tege@pdc.kth..se>
-
- * except.c (eh_outer_context): Do masking using expand_and.
-
-Wed Sep 10 01:38:30 1997 Doug Evans <dje@cygnus.com>
-
- Add port done awhile ago for the ARC cpu.
- * arc/arc.h: New file.
- * arc/arc.c: New file.
- * arc/arc.md: New file.
- * arc/initfini.c: New file.
- * arc/lib1funcs.asm: New file.
- * arc/t-arc: New file.
- * arc/xm-arc.h: New file.
- * ginclude/va-arc.h: New file.
- * ginclude/stdarg.h: Include va-arc.h ifdef __arc__.
- * ginclude/varargs.h: Likewise.
- * Makefile.in (USER_H): Add va-arc.h.
- * configure.in (arc-*-elf*): Recognize.
- * longlong.h: Add ARC support.
+Mon Aug 24 19:45:40 1998 Jim Wilson <wilson@cygnus.com>
-Wed Sep 10 01:32:54 1997 Jeffrey A Law (law@cygnus.com)
+ * tree.def (DECL_RESULT): Correct documentation.
- * expr.c (clear_storage): Use CONST0_RTX instead of const0_rtx.
- when clearing non-BLKmode data.
+Tue Aug 25 01:15:27 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Wed Sep 10 00:29:29 1997 Manfred Hollstein <manfred@s-direktnet.de>
+ * reload1.c (reload_reg_free_before_p): New argument EQUIV; Changed
+ all callers. Abort for RELOAD_FOR_INSN. RELOAD_FOR_OUTADDR_ADDR:
+ conflicts will all RELOAD_FOR_OUTPUT reloads.
- * m88k/sysv3.h (INITIALIZE_TRAMPOLINE) Define.
- * libgcc2.c (__enable_execute_stack): Provide for sysV88 too.
+ * reload1.c (reload_cse_regs_1): When deleting a no-op move that
+ loads the function result, substitute with a USE.
- * xm-m88k.h (USG): Only define if it hasn't already been defined.
+Mon Aug 24 15:20:19 1998 David Edelsohn <edelsohn@gnu.org>
- * Makefile.in (risky-stage1): Delete gratutious whitespace.
+ * rs6000.h (GO_IF_LEGITIMATE_ADDRESS): Use TARGET_POWERPC64
+ when testing LEGITIMATE_INDEXED_ADDRESS_P DFmode and DImode.
+ (LEGITIMIZE_ADDRESS): Use TARGET_POWERPC64 for INDEXED fixup.
+ * rs6000.c (print_operand, case 'L'): Add UNITS_PER_WORD, not 4.
+ (print_operand, cases 'O' and 'T'): Fix typos in lossage strings.
+ * rs6000.md (fix_truncdfsi2_store): Remove %w from non-CONST_INT
+ operand.
+ (movdf_softfloat32, movdf_hardfloat64, movdf_softfloat64): Change
+ 'o' to 'm' for GPR variant constraints.
- * Makefile.in (clean): Delete libgcc1-test.
+Mon Aug 24 10:25:46 1998 Jeffrey A Law (law@cygnus.com)
- * Makefile.in (INSTALL): cd to $(srcdir) before running texinfo.
+ * loop.c (scan_loop): Honor AVOID_CC_MODE_COPIES.
-Tue Sep 9 17:07:36 1997 Stan Cox <coxs@dg-rtp.dg.com>
+ * h8300.h (STRIP_NAME_ENCODING): Fix typo.
- * m88k.c (m88k_expand_prologue): Set MEM_IN_STRUCT_P of va_list
- template.
+ * sparc.md (TFmode splits): Use reg_overlap_mentioned_p to detect
+ when the source and destination overlap.
-Tue Sep 9 09:50:02 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * stmt.c (emit_case_nodes): Change rtx_function to rtx_fn to avoid
+ clash with global type.
- * dwarf2out.c (output_call_frame_info): Call named_section.
+Mon Aug 24 00:53:53 1998 Jason Merrill <jason@yorick.cygnus.com>
-Tue Sep 9 09:12:17 1997 Jeffrey A Law (law@cygnus.com)
+ * fixinc.irix: Add curses.h handling from fixinc.wrap.
- * haifa-sched.c (print_value): Fix last change.
+ * c-common.c (combine_strings): Also set TREE_READONLY.
+ Change warn_write_strings to flag_const_strings.
+ * c-decl.c, c-tree.h: Likewise.
-Tue Sep 9 01:30:37 1997 Jason Merrill <jason@yorick.cygnus.com>
+Sun Aug 23 18:39:11 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * mips.h (DWARF_FRAME_REGNUM): Use the same numbering regardless of
- write_symbols.
+ * config/sparc/sparc.c (sparc_emit_set_const32): If outputting a
+ CONST_INT, not a symbolic reference, don't use a HIGH/LO_SUM
+ sequence, use SET/IOR instead so CSE can see it.
+ * config/sparc/sparc.md (movhi_const64_special,
+ movsi_const64_special): New patterns necessitated by that change.
+ (movhi_high): Remove.
+ (movhi_lo_sum): Change to match an IOR.
+ (movdf_insn_sp32): Test TARGET_V9 not TARGET_ARCH64.
+ (movdf_insn_v9only): New pattern for when V9 but not ARCH64.
+ (movdf_insn_sp64): Test both TARGET_V9 and TARGET_ARCH64.
+ (movdf splits): Allow when not V9 or when not ARCH64 and integer
+ registers are involved.
+ (snesi_zero_extend split): Remove reload_completed test.
+ (unnamed plus and minus zero_extend sidi splits): Add it.
-Mon Sep 8 16:32:43 1997 Jason Merrill <jason@yorick.cygnus.com>
+Sun Aug 23 11:56:08 1998 Mark Mitchell <mark@markmitchell.com>
- * mips.c (function_prologue): Set up the CFA when ABI_32.
+ * extend.texi: Remove description of extension to explicit
+ instantiation that is now endorsed by standard C++.
- * sparc.c (save_regs): Check dwarf2out_do_frame instead of DWARF2_DEBUG
- for dwarf2 unwind info.
- (output_function_prologue, sparc_flat_output_function_prologue): Same.
+Sun Aug 23 09:39:09 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * final.c (final_end_function): Check dwarf2out_do_frame instead
- of DWARF2_DEBUG for dwarf2 unwind info.
- (final_scan_insn): Likewise.
- (final_start_function): Likewise. Initialize dwarf2 frame debug here.
- (final): Not here.
+ * config/arc/arc.c (arc_initialize_pic): Remove.
+ * config/arc/arc.h (INITIALIZE_PIC): Similarly, this routine does
+ nothing on any platform and is invoked by no-one, it does not even
+ appear in the documentation.
+ * config/sparc/sparc.h (INITIALIZE_PIC): Likewise.
+ * config/sparc/sparc.c (initialize_pic): Likewise.
+ (find_addr_reg): Remove this as well, no longer referenced after
+ my rewrite.
- * expr.c (expand_builtin_return_addr): Only SETUP_FRAME_ADDRESSES if
- count > 0.
+Sun Aug 23 00:17:14 1998 Jeffrey A Law (law@cygnus.com)
- * varasm.c (exception_section): Check EXCEPTION_SECTION first.
+ * recog.c (validate_replace_rtx_group): New function.
+ * recog.h (validate_replace_rtx_group): Declare it.
+ * regmove.c (optimize_reg_copy_3): If any substitution fails, then undo
+ the entire group of substitutions.
-Mon Sep 8 15:15:11 1997 Nick Clifton <nickc@cygnus.com>
+Sat Aug 22 23:31:00 1998 Klaus-Georg Adams (Klaus-Georg.Adams@chemie.uni-karlsruhe.de)
- * v850.h (ASM_SPEC): Pass on target processor.
- (CPP_PREDEFINES): Only define if not already specified.
- (TARGET_VERSION): Only define if not already specified.
- (MASK_CPU, MASK_V850, MASK_DEFAULT): Bits to specify target
- processor.
- (EXTRA_SWITCHES): Extra entries in the switches array.
- (TARGET_DEFAULT): Set default target processor.
+ * loop.c (load_mems): Fix initializers.
-Mon Sep 8 18:26:35 1997 Jim Wilson <wilson@cygnus.com>
+Fri Aug 21 23:07:46 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * m68k.h (MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): In MOTOROLA
- cases, add %# and %/, and add : to make them into extended asms.
+ * config/sparc/sparc.md (TFmode splits): Handle destination
+ registers being referenced in the address correctly.
-Sun Sep 7 23:57:50 1997 Weiwen Liu <liu@hepunix.physics.yale.edu>
+ * expmed.c (make_tree) [CONST_INT]: Sign extend even if
+ TREE_UNSIGNED, when bitsize of type's mode is larger than
+ HOST_BITS_PER_WIDE_INT.
- * alias.c (init_alias_analysis): Clean up incompatible pointer
- type warning in bzero.
- * regmove.c (regmove_optimize): Ditto.
- * haifa-sched.c (find_rgns): Ditto.
+Fri Aug 21 19:31:31 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
- * haifa-sched.c (print_value): Clean up ptr->int cast
- warnings.
+ * tree.def (LABELED_BLOCK_EXPR, EXIT_BLOCK_EXPR): New tree nodes.
+ * tree.h (LABELED_BLOCK_LABEL, LABELED_BLOCK_BODY,
+ EXIT_BLOCK_LABELED_BLOCK, EXIT_BLOCK_RETURN, LOOP_EXPR_BODY): New
+ macros.
+ * expr.c (expand_expr): Handle LABELED_BLOCK_EXPR and
+ EXIT_BLOCK_EXPR.
-Sun Sep 7 23:18:32 1997 Fred Fish <fnf@ninemoons.com>
+Thu Aug 20 19:43:44 1998 Jeffrey A Law (law@cygnus.com)
- * INSTALL: Change 'amigados' to 'amigaos' to match current usage.
- * install.texi (Configurations): Ditto.
- * config.sub: Ditto.
+ * h8300.c (h8300_encode_label): Use '&' for tiny data items.
+ * h8300.h (TINY_DATA_NAME_P): Likewise.
+ (STRIP_NAME_ENCODING): Handle '&'.
-Sun Sep 7 22:56:56 1997 Weiwen Liu (liu@hepvms.physics.yale.edu)
+ * mn10200.h (REG_OK_FOR_INDEX_P): Do not check the mode of the
+ register (it could be accessed via an outer SUBREG).
+ (REG_OK_FOR_BASE_P): Likewise.
+ (GO_IF_LEGITIMATE_ADDRESS): Consistently use REGNO_OK_FOR_BASE_P.
- * Makefile.in (sdbout.o): Depend on insn-config.h.
+ * remove.c (optimize_reg_copy_3): Abort instead of silently generating
+ bogus rtl.
-Sun Sep 7 18:44:50 1997 Jim Wilson <wilson@cygnus.com>
+ * jump.c (rtx_renumbered_equal_p): Do not consider PLUS commutative.
- * m68k/m68k.h (TARGET_SWITCHES): For 68000, 68302, subtract MASK_68881.
- For 68303, 68332, cpu32, subtract MASK_68040_ONLY.
+Thu Aug 20 17:35:20 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Sun Sep 7 18:30:46 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * config/sparc/sparc.md (movtf_insn_sp32): All memory operands
+ must be offsettable so the splits can be made.
- * dwarf2out.c (dwarf2out_frame_debug): Assume that in a PARALLEL
- prologue insn, only the first elt is significant.
- (output_call_frame_info): For exception handling, always use 4-byte
- fields as specified by the dwarf2 spec.
- Don't skip trivial FDEs.
+Thu Aug 20 13:56:53 1998 Michael Meissner <meissner@cygnus.com>
-Sun Sep 7 14:19:39 1997 Jeffrey A Law (law@cygnus.com)
+ * config/i386/winnt.c: Include system.h, not stdio.h to get
+ sys/param.h pulled in before rtl.h in case the system defines MIN
+ and MAX.
- * version.c: Bump for snapshot.
+Thu Aug 20 13:44:20 1998 David Edelsohn <edelsohn@gnu.org>
-Sun Sep 7 14:17:36 1997 Torbjorn Granlund (tege@pdc.kth.se)
+ * rs6000.md (movqi, movhi): Add CONSTANT_P_RTX.
- * expmed.c (expand_divmod): Make op1_is_pow2 depend on unsignedp
- for negative constants. Promote EXACT_DIV_EXPR to TRUNC_DIV_EXPR
- when op1_is_pow2.
+Thu Aug 20 13:15:11 1998 Dave Brolley <brolley@cygnus.com>
-Sun Sep 7 13:46:46 1997 Jeffrey A Law (law@cygnus.com)
+ * stor-layout.c (layout_type): Compute TYPE_SIZE_UNIT correctly for
+ arrays of bits.
+ * cpplib.c (cpp_define): Handle macros with parameters.
- * final.c (shorten_branches): During first pass, assume worst
- possible alignment for ADDR_VEC and ADDR_VEC_DIFF insns.
+Wed Aug 19 21:33:19 1998 David Edelsohn <edelsohn@gnu.org>
- * Makefile.in (distclean): Remove various things left around
- by running the testsuite.
+ * rs6000.c (rs6000_output_load_toc_table): Use ld for 64-bit.
+ (output_toc): Use single TOC slot or llong minimal-toc for DFmode
+ and DImode 64-bit. Use llong for minimal-toc SFmode and
+ SYMBOL_REF / LABEL_REF 64-bit.
+ (output_function_profiler): Use llong for profiler label and ld to
+ load 64-bit label address.
-Sun Sep 7 13:16:06 1997 Manfred Hollstein <manfred@s-direktnet.de>
+Wed Aug 19 17:52:27 1998 Nick Clifton (nickc@cygnus.com)
- * configure.in (out_file): Emit definition to config.status in order
- to have a defined value for configure.lang.
- * configure: Re-built.
+ * config/arm/thumb.md (extendqisi2_insn): Cope with REG +
+ OFFSET addressing.
-Sun Sep 7 09:59:08 1997 Jan-Jaap van der Heijden (J.J.vanderHeijden@student.utwente.nl)
+Wed Aug 19 14:13:31 1998 Jeff Law (law@cygnus.com)
- * configure.in: Make symlink to as-new rather than as.new. Similarly
- for ld-new.
- * configure: Rebuilt.
+ * version.c: Bump for snapshot.
-Fri Sep 5 16:54:55 1997 Jim Wilson <wilson@cygnus.com>
+Wed Aug 19 13:10:30 1998 Jeff Law (law@cygnus.com)
- * profile.c (output_func_start_profiler): Set DECL_EXTERNAL to zero.
+ * version.c: Bump for snapshot.
-Fri Sep 5 16:16:44 1997 Christian Kuehnke <Christian.Kuehnke@arbi.Informatik.Uni-Oldenburg.DE>
+Wed Aug 19 13:06:47 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * collect2.c (extract_init_priority): Use atoi instead of strtoul.
+
+Wed Aug 19 13:51:35 1998 Hans-Peter Nilsson <hp@axis.se>
+
+ * tm.texi (Misc): Fix typo "teh".
+
+ * tm.texi (PIC): Fix typo "PPIC".
+
+ * tm.texi (Caller Saves): Say that DEFAULT_CALLER_SAVES has no
+ effect when -O2 and higher.
+ * invoke.texi (Optimize Options): Likewise for -fcaller-saves.
+
+1998-08-19 Michael Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * regclass.c: Changed register set documentation to be consistent
+ with GCC behavior.
+
+ * final.c (final_start_function): Removed redundant test for
+ call_fixed_regs.
+
+Wed Aug 19 13:28:41 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * rtl.h (rtx_function): New type.
+ (for_each_rtx): New function.
+ * rtlanal.c (for_each_rtx): Define it.
+
+ * recog.c (change_t): New type.
+ (change_objects, change_old_codes, change_locs, change_olds):
+ Replace with ...
+ (changes): New variable.
+ (validate_change): Dynamically allocate room for more changes, if
+ necessary. Uses changes array instead of change_objects, etc.
+ (apply_change_group): Use changes array instead of
+ change_objects, etc.
+
+ * loop.c (loop_mem_info): New type.
+ (loop_mems): New variable.
+ (loop_mems_idx): Likewise.
+ (looop_mems_allocated): Likewise.
+ (scan_loop): Remove nregs parameter.
+ (next_insn_in_loop): New function.
+ (load_mems_and_recount_loop_regs_set): Likewise.
+ (load_mems): Likewise.
+ (insert_loop_mem): Likewise.
+ (replace_loop_mem): Likewise.
+ (replace_label): Likewise.
+ (INSN_IN_RANGE_P): New macro.
+ (loop_optimize): Don't pass max_reg_num() to scan_loop.
+ (scan_loop): Remove nregs parameter, compute it after any new
+ registers are created by load_mems. Use INSN_IN_RANGE_P and
+ next_insn_in_loop rather than expanding them inline. Call
+ load_mems to load memory into pseudos, if appropriate.
+ (prescan_loop): Figure out whether or not there are jumps from the
+ loop to targets other than the label immediately following the
+ loop. Call insert_loop_mem to notice all the MEMs used in the
+ loop, if it could be safe to pull MEMs into REGs for the duration
+ of the loop.
+ (strength_reduce): Use next_insn_in_loop. Tweak comments.
+
+Wed Aug 19 08:29:44 1998 Richard Earnshaw (rearnsha@arm.com)
- * sparc/sparc.md: Add ultrasparc scheduling support.
- * sparc/sparc.h (RTX_COSTS): For MULT give v9 a cost of 25 insns.
+ * arm.c (arm_override_options): Remove lie about ignoring PIC flag.
-Fri Sep 5 14:04:59 1997 Philippe De Muyter <phdm@info.ucl.ac.be>
+Wed Aug 19 07:08:15 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * integrate.c (save_for_inline_copying): Use 0, not NULL_PTR,
- as initial value for real_label_map.
- (copy_for_inline): Likewise.
+ * config/sparc/sparc.c (finalize_pic): Check for the correct
+ nonlocal_goto_receiver UNSPEC number.
+ * config/sparc/sparc.md (nonlocal_goto_receiver): Add comment
+ making note of this dependency existing in sparc.c.
+ (negtf2_notv9 split): Give NEG SFmode.
+ (negsf2): Fix insn output string.
-Fri Sep 5 13:36:44 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Tue Aug 18 12:40:27 1998 Richard Henderson <rth@cygnus.com>
- * sched.c (update_flow_info) When looking if to set found_split_dest
- or found_orig_dest, look at all parts of a PARALLEL.
- * haifa-sched.c (update_flow_info): Likewise.
+ * c-common.c (decl_attributes): Issue an error if the argument
+ to alias is not a string.
-Fri Sep 5 10:08:44 1997 Jeffrey A Law (law@cygnus.com)
+Tue Aug 18 10:33:30 1998 Jeffrey A Law (law@cygnus.com)
- * v850: New directory for v850 port.
- * v850/lib1funcs.asm: New file.
- * t-v850, v850.c, v850.h, v850.md, xm-v850.h: New files.
- * ginclude/va-v850.h: New file.
- * ginclude/varargs.h, ginclude/stdarg.h: Include va-mn10200.h.
- * configure.in (mn10200-*-*): New target.
- * configure: Rebuilt.
- * config.sub: Handle v850-elf.
- * Makefile.in (USER_H): Add va-mn10200.h.
- * invoke.texi: Document v850 stuff.
+ * haifa-sched.c (sched_analyze): Put all JUMP_INSNs on the last
+ pending memory flush list.
-Fri Sep 5 09:37:50 1997 Jim Wilson (wilson@cygnus.com)
+ * combine.c (can_combine_p): Allow combining insns with REG_RETVAL
+ notes.
+ (try_combine): Allow combining insns with REG_LIBCALL notes.
- * sdbout.c (plain_type_1, case ARRAY_TYPE): Verify that TYPE_DOMAIN
- has integer TYPE_{MAX,MIN}_VALUE before using them.
+ * expr.c (emit_block_move): Do not call memcpy as a libcall
+ instead build up a CALL_EXPR and call it like any other
+ function.
+ (clear_storage): Similarly for memset.
- * m68k/m68k.h (MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): Add
- __HPUX_ASM__ versions.
+ * regmove.c (fixup_match_2): Do not call reg_overlap_mentioned_p
+ on notes.
-Fri Sep 5 09:08:44 1997 Jeffrey A Law (law@cygnus.com)
+ * Makefile.in (cplus-dem.o): Provide explicit rules for building
+ cplus-dem.o.
- * install.sh: Delete duplicate install script.
+ * regmove.c (optimize_reg_copy_1): Update REG_N_CALLS_CROSSED
+ and REG_LIVE_LENGTH as successful substitutions are made.
-Thu Sep 4 23:14:27 1997 Stan Cox (coxs@dg-rtp.dg.com)
+Tue Aug 18 07:15:27 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * reg-stack.c (subst_stack_regs): Pop the stack register for a
- computed goto which sets the same stack register.
+ * config/sparc/sparc.c (ultra_find_type): Add empty semicolon
+ statement after end of loop label.
- * reg-stack.c (compare_for_stack_reg): Swap only if the source and
- destination are both on the regstack.
- (subst_stack_regs_pat): Put the destination at the top of the regstack.
+Tue Aug 18 07:13:27 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Thu Sep 4 15:02:27 1997 Jim Wilson <wilson@cygnus.com>
+ * config/sparc/sparc.c (ultra_types_avail): New variable.
+ (ultra_build_types_avail): New function to record mask of insn
+ types in ready list at this cycle.
+ (ultrasparc_sched_reorder): Call it.
+ (ultra_find_type): Use it to quicken the search. Also simplif
+ dependency check, don't use rtx_equal_p because we know exactly
+ what we are looking for.
- * mips.md (nonlocal_goto_receiver): Define.
+Tue Aug 18 03:20:53 1998 Richard Earnshaw (rearnsha@arm.com)
- * profile.c (output_arc_profiler): Check next_insert_after for non
- NULL before deferencing it.
+ * arm.h (SECONDARY_INPUT_RELOAD_CLASS): Return NO_REGS if compiling
+ for architecture v4.
- * i386/t-sol2 (TARGET_LIBGCC2_CFLAGS): Define to -fPIC.
+Mon Aug 17 21:26:38 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Thu Sep 4 14:51:57 1997 Jeffrey A Law (law@cygnus.com)
+ * config/sparc/sparc.md (sltu, sgeu): Don't FAIL, call
+ gen_compare_reg.
+ (movsf_const_intreg, movsf_const_high, movsf_const_lo,
+ movdf_const_intreg and helper splits): New patterns to move float
+ constants into integer registers.
+ (negtf2, negdf2, abstf2, absdf2): Rework using new patterns and
+ splits.
- * i386.h (CPP_CPU_DEFAULT): Avoid using #elif.
+Mon Aug 17 11:46:19 1998 Jeffrey A Law (law@cygnus.com)
-Thu Sep 4 15:01:49 1997 Michael Meissner <meissner@cygnus.com>
+ * From Graham
+ * tree.c (build_index_type): Copy TYPE_SIZE_UNIT from sizetype
+ to itype.
+ * c-decl.c (finish_enum): Copy TYPE_SIZ_UNIT from enumtype to tem.
- * toplev.c (rest_of_compilation): For passes starting with
- flow_analysis, use print_rtl_with_bb instead of print_rtl.
+ * rs6000.c (secondary_reload_class): For TARGET_ELF, indicate that
+ a BASE_REGS register is needed as an intermediate when copying
+ a symbolic value into any register class other than BASE_REGS.
- * print-rtl.c (print_rtl_single): Print a single rtl value to a
- file.
+ * expr.c (move_by_pieces): No longer static. Remove prototype.
+ * rtl.h (move_by_pieces): Add extern prototype.
+ * mips.c (expand_block_move): Handle aligned straight line copy by
+ calling move_by_pieces.
- * flow.c (print_rtl_with_bb): Print which insns start and end
- basic blocks. For the start of a basic block, also print the live
- information.
+ * expr.c (expand_expr): Allow assignments from TImode PARM_DECLs
+ and VAR_DECLs.
-Thu Sep 4 11:51:43 1997 Jim Wilson <wilson@cygnus.com>
+Mon Aug 17 10:28:52 1998 Mark Mitchell <mark@markmitchell.com>
- * toplev.c (main): Change #elif to #else/#ifdef
+ * stmt.c (expand_end_loop): Tidy. Allow unconditional
+ jumps out of the loop to be treated as part of the exit test.
- * tlink.c: Include ctype.h.
- * ginclude/va-mips.h: Add _VA_MIPS_H_ENUM ifdef/define/endif.
+Mon Aug 17 10:06:11 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ Jeff Law <law@cygnus.com>
-Thu Sep 4 11:17:16 1997 Mikeael Meissner (meissner@cygnus.com)
+ * Makefile.in (cplus-dep.o): Use cplus-dem.c from libiberty.
+ * cplus-dem.c: Delete.
- * bitmap.c: Conditionally include stdlib.h.
- (free): Provide a declaration if NEED_DECLARATION_FREE.
+ * Makefile.in (fold-const.o): Depend on $(RTL_H).
-Thu Sep 4 09:58:53 1997 Joel Sherrill (joel@OARcorp.com)
+ * fold-const.c: Include rtl.h to get the prototype for
+ `set_identifier_local_value'.
- * i960/i960.h: Added default for SUBTARGET_SWITCHES macro.
+ * loop.c (express_from_1): Remove unused variable `tmp'.
+ (combine_givs): Cast the first argument of bzero to char *.
-Thu Sep 4 09:53:20 1997 Jim Wilson (wilson@cygnus.com)
+ * toplev.c (display_help): Remove unused variable `looking_for_start'.
- * profile.c (output_arc_profiler): Verify next_insert_after is an
- INSN before and after skipping a stack pop.
+ * c-decl.c (init_decl_processing): Remove unneeded &.
-Thu Sep 4 07:39:19 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+ * alpha.h (alpha_initialize_trampoline): Provide prototype.
- * final.c (shorten_branches): Don't count the lengths of deleted
- instructions.
+ * except.c (set_exception_lang_code, set_exception_version_code):
+ Change parameter from `short' to `int' to avoid using a gcc
+ extension.
-Thu Sep 4 09:43:01 1997 Jeffrey A Law (law@cygnus.com)
+ * except.h (set_exception_lang_code, set_exception_version_code):
+ Likewise for prototypes.
- * version.c: Bump for snapshot.
+ * flow.c (count_reg_references): Remove unused variables `regno'
+ and `i'.
-Thu Sep 4 11:04:21 1997 Michael Meissner <meissner@cygnus.com>
+ * gcse.c (hash_scan_insn): Declare parameter `in_libcall_block'.
- * bitmap.h (EXECUTE_IF_AND_IN_BITMAP): New macro, to iterate over
- two bitmaps ANDed together.
- (bitmap_print): Declare.
+ * prefix.c (translate_name): Cast the result of `alloca'.
- * bitmap.c (function_obstack): Don't declare any more.
- (bitmap_obstack): Obstack for allocating links from.
- (bitmap_obstack_init): New static to say whether to initialize
- bitmap_obstack.
- (bitmap_element_allocate): Use bitmap_obstack to allocate from.
- (bitmap_release_memory): Free all memory allocated from
- bitmap_obstack.
+ * varray.h (VARRAY_FREE): Reimplement as a `do-while(0)' statement.
- * basic-block.h (EXECUTE_IF_AND_IN_REG_SET): New macro, invoke
- EXECUTE_IF_AND_IN_BITMAP.
+Mon Aug 17 09:23:42 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
-Wed Sep 3 10:39:42 1997 Jim Wilson <wilson@cygnus.com>
+ * config/m68k/m68k.c: Include "system.h" instead of <stdio.h>.
+ Include "toplev.h".
+ (valid_dbcc_comparison_p): Mark mode argument as unused.
+ (symbolic_operand): Likewise.
+ (legitimize_pic_address): Likewise.
+ (const_uint32_operand): Likewise.
+ (const_sint32_operand): Likewise.
+ * sched.c [!INSN_SCHEDULING]: Define only dummy function
+ schedule_insns and comment out rest of file.
- * alias.c (true_dependence): Address with AND can alias scalars.
- (anti_dependence, output_dependence): Likewise.
+ * m68k.c (output_move_simode_const): Use subl to move a zero into an
+ address register.
+ (output_move_[hq]imode): Likewise.
- * alias.c (true_dependence): Test x for BLKmode, in addition to mem.
+Mon Aug 17 09:15:47 1998 Jeffrey A Law (law@cygnus.com)
-Wed Sep 3 09:28:50 CDT 1997 Joel Sherrill (joel@OARcorp.com)
+ * toplev.c (main): Enable -fstrict-aliasing for -O2 and above.
+ * invoke.texi: Corresponding changes.
- * i386/go32-rtems.h, i386/rtems.h, i960/rtems.h, m68k/rtems.h,
- mips/rtems64.h, pa/rtems.h, rs6000/rtems.h, sh/rtems.h,
- sparc/rtems.h (subtarget_switches): Removed SUBTARGET_SWITCHES
- definitions. Use -qrtems instead of -mrtems.
+Mon Aug 17 02:03:55 1998 Richard Henderson <rth@cygnus.com>
-Wed Sep 3 09:05:41 1997 Robert Lipe (robert@dgii.com)
+ * regclass.c (allocate_reg_info): Respect MIN when clearing data.
- * xm-sco5.h (sys_siglist): Define.
- (SYS_SIGLIST_DECLARED): Likewise.
+Sun Aug 16 17:37:06 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * config/sparc/sparc.c (ultra_code_from_mask,
+ ultra_cmove_results_ready_p, ultra_fpmode_conflict_exists,
+ ultra_find_type, ultra_schedule_insn, ultra_flush_pipeline,
+ ultrasparc_sched_init, ultrasparc_variable_issue,
+ ultra_rescan_pipeline_state, ultrasparc_sched_reorder): New
+ functions to describe UltraSPARC pipeline exactly to Haifa.
+ (ultrasparc_adjust_cost): Indicate IMUL type insns have zero cost,
+ as there is nothing the scheduler can do about it. Indicate that
+ REG_DEP_OUTPUT's collide. Fixup formatting.
+ * config/sparc/sparc.h (RTX_COSTS): Fixup integer multiply and
+ divide costs on Ultra for DImode.
+ (MD_SCHED_INIT, MD_SCHED_REORDER, MD_SCHED_VARIABLE_ISSUE):
+ Define.
+ * config/sparc/sparc.md (ieu_unnamed function unit): Rename to
+ ieuN and add call_no_delay_slot to type list.
+ (cti function unit): New unit for branches on UltraSPARC.
+ (subx/addx insns): Set type to misc.
+ (sidi zero/sign extension insns on arch64): Set type to shift.
+ (sign_extendhidi2_insn): Set type to sload.
+
+Sun Aug 16 13:52:00 1998 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.c (rs6000_stack_info): Use if == 0 for sizes.
+ (output_epilog): Use if != 0 for offset.
+ (rs6000_fatal_bad_address): Prepare for Intl.
+ * rs6000.h (rs6000_fatal_bad_address): Declare.
+ * rs6000.md (movsfcc, movdfcc): Use else if.
+ (elf_high): Use {liu|lis}.
+ (elf_low): Use {cal|la}. Remove %a template from old mnemonics.
+ (movsi): Use rs6000_fatal_bad_address.
-Tue Sep 2 23:33:33 1997 Jeffrey A Law (law@cygnus.com)
+Sun Aug 16 01:53:21 1998 Richard Henderson <rth@cygnus.com>
- * expr.c (convert_move): Handle truncation from TQFmode to QFmode.
+ * reload.c (find_equiv_reg): Reject equivalences separated
+ by a volatile instruction.
-Wed Sep 3 02:09:30 1997 Torbjorn Granlund <tege@pdc.kth..se>
+Sun Aug 16 00:21:44 1998 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * except.c (eh_outer_context): Expand masking operation using
- expand_binop.
+ * rs6000/linux.h (CPP_OS_DEFAULT_SPEC): Define.
-Tue Sep 2 18:09:39 1997 Jim Wilson <wilson@cygnus.com>
+Sat Aug 15 20:51:35 1998 Richard Henderson <rth@cygnus.com>
- * alpha.md (floatdisf2-1): New pattern.
+ * alpha.md (movsicc): Fix mode mismatch.
-Tue Sep 2 18:41:55 1997 Jeffrey A Law (law@cygnus.com)
+Sat Aug 15 20:22:33 1998 H.J. Lu (hjl@gnu.org)
- * xm-svr4.h (SYS_SIGLIST_DECLARED): Define.
- * xm-news.h (SYS_SIGLIST_DECLARED): Likewise.
- * xm-sysv4.h (SYS_SIGLIST_DECLARED): Likewise.
- * gcc.texi: Note that if you define sys_siglist that you should
- also define SYS_SIGLIST_DECLARED.
+ * config/alpha/alpha.h (ASM_OUTPUT_MI_THUNK): Handle aggregated
+ return type.
+ * config/alpha/win-nt.h (ASM_OUTPUT_MI_THUNK): Likewise.
- * mn10200.h (INITIALIZE_TRAMPOLINE): PC relative instructions
- are relative to the next instruction, not the current instruction.
+Sat Aug 15 08:39:49 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Tue Sep 2 14:22:43 1997 Jim Wilson <wilson@cygnus.com>
+ * config/sparc/sparc.md (movsi_lo_sum_pic_label_reg): Remove
+ write-only modifier from operand 1 constraint.
- * local-alloc.c (contains_replace_regs): New function.
- (update_equiv_regs): When adding a REG_EQUIV note for a set of a MEM,
- verify that there is no existing REG_EQUIV note, and add a call to
- contains_place_regs.
+Sat Aug 15 06:28:19 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Tue Sep 2 12:48:11 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+ * config/sparc/sparc.c (sparc_emit_set_const64_quick1): If
+ emitting a XOR of -1 at the end, emit a NOT instead for combine's
+ sake.
+ (sparc_emit_set_const64): Likewise, also when computing trailing
+ bits do not negate low_bits and make fast_int an int.
- * config/alpha/elf.h (CPP_PREDEFINES): Add -D__PIC__ -D__pic__.
- (STARTFILE_SPEC): Always use crtbegin.o%s
- (ENDFILE_SPEC): Always use crtend.o%s.
+Fri Aug 14 21:07:03 1998 Jeffrey A Law (law@cygnus.com)
-Tue Sep 2 12:00:36 1997 Jim Wilson <wilson@cygnus.com>
+ * loop.c (add_label_notes): Do not ignore references to labels
+ before dispatch tables. Mirrors Apr 8 change to mark_jump_label.
+ * gcse.c (add_label_notes): Similarly.
- * alpha/alpha.h (PREFERRED_RELOAD_CLASS): Return NO_REGS if NO_REGS
- is passed in.
- * emit-rtl.c (gen_lowpart_common): Add code to convert CONST_INT to
- SFmode for 64 bit hosts.
+ * pa.h (ASM_OUTPUT_MI_THUNK): Strip name encoding.
-Tue Sep 2 13:42:38 1997 Paul N. Hilfinger <hilfingr@CS.Berkeley.EDU>
+ * m68k.md (adddi_dilshr32): One of the operands must be a register.
+ (adddi_dishl32): Similarly.
- * fixincludes: Permits spaces between # and define. Discard C++
- comments in sys/pci.h on HP/UX 10.20.
+Fri Aug 14 14:12:59 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * i386.h (MODES_TIEABLE_P): Reorganize to shut up warnings.
+ * alias.c (memrefs_conflict_p): Add braces to shut up warnings.
+ * cse.c (cse_basic_block): Add parens to shut up warnings.
+
+Fri Aug 14 12:58:21 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * config/sparc/sparc.c (sparc_emit_set_const64_quick2,
+ sparc_emit_set_const64_longway, const64_is_2insns,
+ create_simple_focus_bits, sparc_emit_set_const64): Fix more bugs
+ in 64-bit constant formation.
+ * config/sparc/sparc.md (snesi_zero_extend split): Generate
+ rtl for addx not subx.
+ (define_insn movdi_const64_special): Make available even when
+ HOST_BITS_PER_WIDE_INT is not 64.
+ (movdi_lo_sum_sp64_cint, movdi_high_sp64_cint): Remove.
+ (losum_di_medlow, sethm, setlo): Make op2 symbolic_operand.
+ (cmp_siqi_trunc_set, cmp_diqi_trunc_set): Encapsulate both
+ instances of operand 1 inside a QI subreg.
+ (xordi3_sp64_dbl): Remove '%' constraint for op1.
+ (one_cmpldi2_sp64): Fix output string.
+ (one_cmplsi2_not_liveg0): Rewrite to remove unneeded extra
+ alternative case.
+ (unnamed arch64 ashift DI): Truncate shift count if greater than
+ 63, not 31.
+
+Fri Aug 14 21:52:53 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
-Mon Sep 1 22:13:18 1997 Jeffrey A Law (law@cygnus.com)
+ * expr.c (store_expr): Don't optimize away load-store pair
+ when either source or destination have a side effect.
- * version.c: Bump for snapshot.
+Fri Aug 14 16:50:10 1998 John Carr <jfc@mit.edu>
- * pa.c (restore_unscaled_index_insn_codes): New function.
- (record_unscaled_index_insn_codes): Likewise.
- (output_function_prologue): Call restore_unscaled_index_insn_codes.
- (output_function_epilogue): Free memory for unscaled_index_insn_codes.
- (pa_reorg): Call record_unscaled_index_insn_codes.
+ * genrecog.c (add_to_sequence): Fatal error if the modes of the
+ operands of SET are incompatible.
- * haifa-sched.c (move_insn): Handle notes correctly for insns
- with SCHED_GROUP_P set.
+ * alpha.md: Fix max and min patterns so modes of SET operands match.
-Mon Sep 1 16:58:57 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+Fri Aug 14 12:22:55 1998 Ian Lance Taylor <ian@cygnus.com>
- * alpha/xm-linux.h (USE_BFD): Undef before define.
+ * configure.in: Avoid [[ by using test and changequote.
+ * configure: Rebuild.
-Mon Sep 1 16:25:34 1997 Jim Wilson <wilson@cygnus.com>
+Fri Aug 14 01:22:31 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * rtl.def (CONSTANT_P_RTX): Fix typo in string name.
+
+ * config/sparc/sparc.md (seqdi_special_trunc, snedi_special_trunc,
+ seqsi_special_extend, snesi_special_extend, snesi_zero_extend and
+ split, snedi_zero_trunc and split, seqsi_zero_extend and split,
+ seqdi_zero_trunc and split, pic_lo_sum_di, pic_sethi_di,
+ movdi_cc_sp64_trunc, movdi_cc_reg_sp64_trunc, addx_extend_sp32 and
+ split, addx_extend_sp64, subx_extend_sp64, subx_extend and split):
+ Fix mismatching modes in SET operands.
+ (conditional move patterns): Fix formatting.
+ (unnamed subx arch64 pattern): Remove duplicate insn.
+
+Fri Aug 14 00:34:34 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * config/sparc/sparc.c (const64_operand, const64_high_operand):
+ Get it right when HOST_BITS_PER_WIDE_INT is not 64.
+ (input_operand): Fixup test for what we accept for constant
+ integers.
+ (sparc_emit_set_const32, sparc_emit_set_symbolic_const64): Give
+ set VOIDmode.
+ (safe_constDI): Remove.
+ (sparc_emit_set_safe_HIGH64, gen_safe_SET64, gen_safe_OR64,
+ gen_safe_XOR64): New functions.
+ (sparc_emit_set_const64_quick1, sparc_emit_set_const64_quick2,
+ sparc_emit_set_const64_longway, sparc_emit_set_const64): Use
+ them.
+ * config/sparc/sparc.md (define_insn xordi3_sp64_dbl): Only make
+ available when HOST_BITS_PER_WIDE_INT is not 64.
+ (define_insn movdi_sp64_dbl, movdi_const64_special): Likewise and
+ move before movdi_insn_sp64 pattern.
+ (define_insn movdi_lo_sum_sp64_dbl, movdi_high_sp64_dbl): Remove.
+ (define_insn sethi_di_medlow, seth44, setm44, sethh): Use
+ symbolic_operand as predicate for second operand.
+ (DImode minus split on arch32, negsi2 expander, one_cmplsi2
+ expander): Give set VOIDmode.
- * cse.c (cse_insn): Don't record BLKmode values.
+Fri Aug 14 01:45:06 1998 Mumit Khan <khan@xraylith.wisc.edu>
-Mon Sep 1 11:25:47 1997 Stephen Williams (steve@icarus.icarus.com)
+ * i386/cygwin32 (DEFAULT_PCC_STRUCT_RETURN): Define.
- * i960.h (LINK_SPEC): Handle "-mjX" and "-mrp" switches.
+Fri Aug 14 01:40:21 1998 Geoffrey Keating <geoffk@ozemail.com.au>
-Mon Sep 1 08:29:46 1997 Jeffrey A Law (law@cygnus.com)
+ * rs6000/linux.h (LINK_SPEC): Pass -G args to the linker.
- * cccp.c (sys_errlist): Remove special 4.4bsd declaration.
- * collect2.c (sys_errlist): Likewise.
- * cpplib.c (sys_errlist): Likewise.
- * gcc.c (sys_errlist): Likewise.
- * protoize (sys_errlist): Likewise.
- * configure.in: Check for strerror.
- * xm-freebsd.h (HAVE_STRERROR): Remove definition.
- * xm-gnu.h (HAVE_STRERROR): Likewise.
- * xm-linux.h (HAVE_STRERROR): Likewise.
- * xm-netbsd.h (HAVE_STRERROR): Likewise.
- * xm-bsd386.h (HAVE_STRERROR): Likewise.
- * xm-cygwin32.h (HAVE_STRERROR): Likewise.
- * xm-dos.h (HAVE_STRERROR): Likewise.
- * xm-mingw32.h (HAVE_STRERROR): Likewise.
- * xm-pa.h (HAVE_STRERROR): Likewise.
- * xm-papro.h (HAVE_STRERROR): Likewise.
- * xm-sysv4.h (HAVE_STRERROR): Likewise.
- * configure, config.in: Rebuilt.
+Fri Aug 14 01:23:23 1998 Richard Earnshaw (rearnsha@arm.com)
- * Makefile.in: Add several missing "else true" clauses.
+ * arm/netbsd.h (TARGET_DEFAULT): Default includes software floating
+ point.
+ (CPP_FLOAT_DEFAULT_SPEC): Re-define accordingly.
- * collect2.c: Change DONT_DECLARE_SYS_SIGLIST to SYS_SIGLIST_DECLARED.
- * mips-tfile.c: Likewise.
- * gcc.texi: DONT_DECLARE_SYS_SIGLIST: Remove docs.
- * xm-linux.h (DONT_DECLARE_SYS_SIGLIST): Delete definition.
- * xm-freebsd.h, xm-bsd386.h, xm-sysv4.h, xm-sol2.h: Likewise.
- * configure.in: Check for sys_siglist declaration.
- * configure, config.in: Rebuilt.
-
-Mon Sep 1 08:04:07 1997 Joel Sherrill (joel@OARcorp.com)
-
- * i386/go32-rtems.h, i386/rtems.h, i960/rtems.h,
- m68k/rtems.h, mips/rtems64.h, pa/rtems.h, rs6000/rtems.h,
- sparc/rtems.h (subtarget_switches): Added -mrtems as a switch.
- * i960/i960.h: Added SUBTARGET_SWITCHES macro.
- * rs6000/sysv4.h (extra_subtarget_switches): Added new
- macro EXTRA_SUBTARGET_SWITCHES.
- * configure.in (sh*-*-rtems*): New target.
- * sh/rtems.h: New file.
- * sh/sh.h: Added SUBTARGET_SWITCHES macro.
- * configure: Rebuilt.
+Fri Aug 14 01:19:08 1998 Robert Lipe <robertl@dgii.com>
-Sat Aug 30 22:54:26 1997 Jim Wilson <wilson@cygnus.com>
+ * install.texi: Various SCO OpenServer tweaks.
- * unroll.c (calculate_giv_inc): Handle increment with code PLUS.
+Thu Aug 13 20:14:40 1998 Jim Wilson <wilson@cygnus.com>
-Sat Aug 30 10:49:46 1997 David Edelsohn <edelsohn@mhpcc.edu>
+ * reload1.c (eliminate_regs_in_insn): Handle another case when
+ eliminating the frame pointer to the hard frame pointer. Add
+ missing ep->to_rtx check to one existing case.
- * rs6000.md: Make DF fused-add operations pay attention to
- -mno-fused-add.
+ * mips/mips.md (movhi_internal2+2): Fix typo mem:SI -> mem:HI.
-Fri Aug 29 19:19:54 1997 Jim Wilson <wilson@cygnus.com>
+Thu Aug 13 17:08:11 1998 Jason Merrill <jason@yorick.cygnus.com>
- * i386/xm-sysv4.h (DONT_DECLARE_SYS_SIGLIST): Define.
+ * tree.h: De-conditionalize init_priority code.
-Fri Aug 29 16:13:51 1997 Jeffrey A Law (law@cygnus.com)
+ * mips.h (NM_FLAGS): Change from -Bp to -Bn.
+ * collect2.c (NM_FLAGS): Change from -p to -n.
- * pa.md (reload_peepholes): Make sure operand is a REG before
- examining REGNO. Allow general registers too.
+ * configure.in: Turn on collect2 for mipstx39-elf.
+ Handle use_collect2=no properly.
-Fri Aug 29 11:42:04 1997 Jim Wilson <wilson@cygnus.com>
+ * c-common.c: De-conditionalize init_priority code.
+ * collect2.c (extract_init_priority, sort_ids): New fns.
+ (main): Call sort_ids.
+ Move sequence_number to file scope.
- * varasm.c (mark_constants): Don't look inside CONST_DOUBLEs.
+ * configure.in: Handle --enable-init-priority.
+ * c-common.c (attrs): Add A_INIT_PRIORITY.
+ (init_attributes, decl_attributes): Likewise.
+ * tree.h (DEFAULT_INIT_PRIORITY, MAX_INIT_PRIORITY): New macros.
+ * tree.c (get_file_function_name_long): Split out...
+ (get_file_function_name): ...from here.
-Fri Aug 29 09:33:20 1997 Philipp Thomas (kthomas@lxi165.gwdg.de)
+Thu Aug 13 16:09:53 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
- * dwarf2out.c (build_abbrev_table): Use xrealloc, not xmalloc
- to reallocate abbrev_die_table.
+ * expr.c (safe_from_p): Change code to ERROR_MARK only when not
+ accessing nodes.
-Thu Aug 28 15:14:46 1997 Jim Wilson <wilson@cygnus.com>
+Thu Aug 13 15:24:48 1998 Jason Merrill <jason@yorick.cygnus.com>
- * m68k/m68k.md (iorsi_zexthi_ashl16): Disable.
+ * toplev.c (display_help): Add braces to shut up warnings.
+ * tree.c (simple_cst_equal): Likewise.
-1997-08-27 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+ * fold-const.c (non_lvalue): Don't deal with null pointer
+ constants here.
+ (fold, case COMPOUND_EXPR): Wrap a constant 0 in a NOP_EXPR.
- * Makefile.in (config.status): Depend on version.c
+ * c-typeck.c (initializer_constant_valid_p): Allow conversion of 0
+ of any size to a pointer.
- * expr.h (insn_gen_function): Reenable prototype.
+Thu Aug 13 12:53:13 1998 Jim Wilson <wilson@cygnus.com>
- * expr.c (move_by_pieces_1, clear_by_pieces_1): Fix prototype of
- first parameter.
+ * i386/winnt.c (i386_pe_asm_file_end): Check TREE_SYMBOL_REFERENCED.
-Thu Aug 28 13:01:43 1997 Jim Wilson <wilson@cygnus.com>
+Wed Aug 12 17:25:18 1998 Jeffrey A Law (law@cygnus.com)
- * i386.c (ix86_expand_epilogue): Emit blockage instruction when pic.
+ * mn10300.c (REG_SAVE_BYTES): Only reserve space for registers
+ which will be saved.
+ * mn10300.md (prologue insn): Only save registers which need saving.
+ (epilogue insn): Similarly.
-Thu Aug 28 07:03:15 1997 Jeffrey A Law (law@cygnus.com)
+ * mn10300.c, mn10300.h, mn10300.md: Remove "global zero register"
+ optimizations.
- * version.c: Bump for latest snapshot.
+Wed Aug 12 12:39:16 1998 Gavin Romig-Koch <gavin@cygnus.com>
- * bc-optab.c: Conditionally include stdlib.h.
- (free): Provide a declaration if NEED_DECLARATION_FREE.
- * tree.c (free): Provide a declaration if NEED_DECLARATION_FREE.
- * rtl.h (free): Remove declaration.
- * tree.h (free): Remvoe declaration.
+ * mips/mips.h (ENCODE_SECTION_INFO): Set SYMBOL_REF_FLAG for
+ VAR_DECL's in gp addressable sections.
- * configure: Rebuilt.
+Tue Aug 11 23:02:31 1998 John Carr <jfc@mit.edu>
-Wed Aug 27 21:32:20 1997 Jeffrey A Law (law@cygnus.com)
+ * sparc.c: Change return <exp> to <exp>; return; in functions
+ returning void.
+ * sparc.md: Add empty semicolon statement after final label in
+ move expanders.
- * flags.h (flag_move_all_movables): Declare.
- (flag_reduce_all_givs): Likewise.
- * loop.c (move_movables): Handle flag_move_all_movables.
- (strength_reduce): Handle flag_reduce_all_givs.
- * toplev.c (flag_move_all_movables): Define.
- (flag_reduce_all_givs): Likewise.
- (f_options): Add -fmove-all-movables and -freduce-all-givs.
- * invoke.texi: Document new options, including alias stuff that
- wasn't included last time.
+Tue Aug 11 22:42:01 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
-Wed Aug 27 18:08:51 1997 Bob Manson (manson@cygnus.com)
+ * config/sparc/sparc.md (define_insn addx_extend): Rename to
+ addx_extend_sp64, only allow when TARGET_ARCH64.
+ (define_insn addx_extend_sp32 and split): Version that works when
+ not TARGET_ARCH64.
+ (define_insn subx_extend): Likewise.
+ (define_split adddi3 and subdi3 with zero extension): Fixup and
+ correct bugs when not TARGET_ARCH64.
- * t-h8300: Use TARGET_LIBGCC2_CFLAGS instead of LIBGCC2_CFLAGS.
- * t-mn10200: Ditto.
- * t-vxsparc: Ditto.
- * t-vxworks68: Ditto.
- * t-vxworks960: Ditto.
- * t-vx29k: Ditto.
+Tue Aug 11 16:04:34 1998 John Carr <jfc@mit.edu>
-Wed Aug 27 16:35:29 1997 Richard Henderson <rth@cygnus.com>
+ * except.c (set_exception_lang_code, set_exception_version_code):
+ Use prototype-style definition if __STDC__, to match declaration
+ in except.h.
- * alpha/xm-alpha.h (alloca): Define alloca to builtin_alloca for GNUC
- if not already defined, and USE_C_ALLOCA not defined.
+ * genemit.c: Change FAIL and DONE macros not to use loops.
-Wed Aug 27 16:08:43 1997 Jim Wilson <wilson@cygnus.com>
+Tue Aug 11 12:27:03 1998 Jim Wilson <wilson@cygnus.com>
- * config.guess: Replace with script that uses ../config.guess.
+ * dwarf2out.c (ASM_OUTPUT_DWARF_ADDR_CONST): Use
+ ASM_OUTPUT_DWARF2_ADDR_CONST if defined.
- * config/alpha/elf.h (DEFAULT_VTABLE_THUNKS): New. Defined as 1
- if USE_GNULIBC_1 is not defined.
+ * mips/mips.md (reload_outsi): Use M16_REG_P when TARGET_MIPS16.
-Wed Aug 27 15:49:12 1997 Richard Henderson <rth@cygnus.com>
+Tue Aug 11 18:12:53 1998 Dave Love <d.love@dl.ac.uk>
- * alpha/elf.h (LINK_SPEC): Conditionalize on USE_GNULIBC_1.
- * config.guess: Recognize alpha-linux-gnulibc1.
- * configure.in (alpha-*-linux-gnulibc1): New target.
- (alpha-*-linux-gnu*): Don't build crtbegin/end.
+ * README.g77: Update from Craig.
-Wed Aug 27 11:52:58 1997 Jim Wilson <wilson@cygnus.com>
+Tue Aug 11 04:46:01 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * config/sparc/sparc.c (sparc_emit_set_const32): INTVAL is of
+ type HOST_WIDE_INT.
+ (safe_constDI sparc_emit_set_const64_quick1,
+ sparc_emit_set_const64_quick2, sparc_emit_set_const64_longway,
+ analyze_64bit_constant, const64_is_2insns,
+ create_simple_focus_bits): Fix some bugs when compiled on real
+ 64-bit hosts.
+ (function_arg_record_value_3, function_arg_record_value_2,
+ function_arg_record_value): Add fully prototyped forward decls.
+ * config/sparc/sparc.md (define_insn cmpsi_insn_sp32): Rename back
+ to cmpsi_insn and use on both 64 and 32 bit targets.
+ (define_insn cmpsi_insn_sp64): Remove.
+ (define_expand zero_extendsidi2): Allow for 32-bit target too.
+ (define_insn zero_extendsidi2_insn): Rename to
+ zero_extendsidi2_insn_sp64.
+ (define_insn zero_extendsidi2_insn_sp32): New pattern and
+ associated forced split for it.
+
+ * config/sparc/sparc.c (const64_operand, const64_high_operand):
+ New predicates.
+ * config/sparc/sparc.h: Declare them.
+ (PREDICATE_CODES): Add them.
+ * config/sparc/sparc.md (movdi_lo_sum_sp64_dbl,
+ movdi_high_sp64_dbl, xordi3_sp64_dbl): Use them.
+
+Mon Aug 10 22:57:24 1998 John Carr <jfc@mit.edu>
+
+ * config/sparc/sparc.md (define_insn jump): Output ba,pt not b,pt
+ in v9 case as the latter makes the Solaris assembler crash.
+
+Mon Aug 10 22:39:09 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * config/sparc/sparc.c (input_operand): Do not accept a LO_SUM MEM
+ for TFmode when !v9. We require offsettable memory addresses.
+ * config/sparc/sparc.h (ALTER_HARD_SUBREG): Handle TFmode to
+ DFmode register number conversions.
+ * config/sparc/sparc.md (define_split DFmode moves): If register
+ is a SUBREG do alter_subreg on it before using.
+ (define_expand movtf): Fixup comment about alignment on v9.
+ (define_split TFmode moves): Don't use gen_{high,low}part, create
+ explicit SUBREGs instead.
+
+Mon Aug 10 19:02:55 1998 John Carr <jfc@mit.edu>
+
+ * Makefile.in (mbchar.o): Depend on mbchar.c.
+
+Mon Aug 10 04:28:13 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+ Richard Henderson <rth@cygnus.com>
+
+ Rewrite Sparc backend for better code generation and
+ improved sparc64 support.
+ * config/sparc/sp64-elf.h: Set JUMP_TABLES_IN_TEXT_SECTION to
+ zero.
+ * config/sparc/sysv4.h: Likewise.
+ * config/sparc/sparc.c (v8plus_regcmp_p, sparc_operand,
+ move_operand, v8plus_regcmp_op, emit_move_sequence,
+ singlemove_string, doublemove_string, mem_aligned_8,
+ output_move_double, output_move_quad, output_fp_move_double,
+ move_quad_direction, output_fp_move_quad, output_scc_insn):
+ Remove.
+ (small_int_or_double): New predicate.
+ (gen_compare_reg): Remove TARGET_V8PLUS cmpdi_v8plus emission.
+ (legitimize_pic_address): Emit movsi_{high,lo_sum}_pic instead of
+ old pic_{sethi,lo_sum}_si patterns.
+ (mem_min_alignment): New generic function to replace
+ mem_aligned_8, which uses REGNO_POINTER_ALIGN information when
+ available and can test for arbitrary alignments. All callers
+ changed.
+ (save_regs, restore_regs, build_big_number,
+ output_function_prologue, output_cbranch, output_return,
+ sparc_flat_save_restore, sparc_flat_output_function_prologue,
+ sparc_flat_output_function_epilogue): Prettify
+ insn output.
+ (output_function_epilogue): Likewise and add code to output
+ deferred case vectors.
+ (output_v9branch): Likewise, add new arg INSN and use it to tack
+ on branch prediction settings. All callers changed.
+ (print_operand): Likewise and output %l44 for LO_SUMs when
+ TARGET_CM_MEDMID.
+ (sparc_splitdi_legitimate): New function to make sure DImode
+ splits can be run properly when !arch64.
+ (sparc_initialize_trampoline, sparc64_initialize_trampoline):
+ Reformat example code in comments.
+ (set_extends): Remove UNSPEC/v8plus_clear_high case.
+ (sparc_addr_diff_list, sparc_addr_list): New statics to keep track
+ of deferred case vectors we need to output.
+ (sparc_defer_case_vector): Record a case vector.
+ (sparc_output_addr_vec, sparc_output_addr_diff_vec,
+ sparc_output_deferred_case_vectors): New functions to output them.
+ (sparc_emit_set_const32): New function to form 32-bit constants in
+ registers when that requires more than one instruction.
+ (safe_constDI, sparc_emit_set_const64_quick1,
+ sparc_emit_set_const64_quick2, sparc_emit_set_const64_longway,
+ analyze_64bit_constant, const64_is_2insns,
+ create_simple_focus_bits, sparc_emit_set_const64): New functions
+ which do the same for 64-bit constants when arch64.
+ (sparc_emit_set_symbolic_const64): New function to emit address
+ loading for all code models on v9.
+ * config/sparc/sparc.h (CONDITIONAL_REGISTER_USAGE): Do not make
+ %g1 fixed when arch64, unfix %g0 when TARGET_LIVE_G0.
+ (ALTER_HARD_SUBREG): Fix thinko, return REGNO + 1 not 1.
+ (SECONDARY_INPUT_RELOAD_CLASS, SECONDARY_OUTPUT_RELOAD_CLASS): Fix
+ inaccuracies in comments, add symbolic and text_segment operands
+ when TARGET_CM_MEDANY and TARGET_CM_EMBMEDANY respectively. Use
+ GENERAL_REGS in these cases as a temp REG is needed to load these
+ addresses into a register properly.
+ (EXTRA_CONSTRAINT): Document more accurately, remove Q case as it
+ is no longer used.
+ (GO_IF_LEGITIMATE_ADDRESS): Allow TFmode for LO_SUM on v9 since fp
+ quads are guaranteed to have 16-byte alignment.
+ (LEGITIMIZE_ADDRESS): For SYMBOL_REF, CONST, and LABEL_REF use
+ copy_to_suggested_reg instead of explicit LO_SUM and HIGH.
+ (ASM_OUTPUT_ADDR_VEC, ASM_OUTPUT_ADDR_DIFF_VEC): New macros for
+ deferred case vector implementation.
+ (ASM_OUTPUT_ADDR_VEC_ELT): Use fputc to output newline.
+ (ASM_OUTPUT_ADDR_DIFF_ELT): Parenthesize LABEL in macro calls.
+ Generate "internal label - label" instead of "label - 1b".
+ (PRINT_OPERAND_ADDRESS): For LO_SUM use %l44 on TARGET_CM_MEDMID.
+ (PREDICATE_CODES): Remove sparc_operand, move_operand,
+ v8plus_regcmp_op. Add small_int_or_double, input_operand, and
+ zero_operand.
+ (doublemove_string, output_block_move, output_fp_move_double,
+ output_fp_move_quad, output_move_double, output_move_quad,
+ output_scc_insn, singlemove_string, mem_aligned_8, move_operand,
+ sparc_operand, v8plus_regcmp_op, v8plus_regcmp_p): Remove externs.
+ (sparc_emit_set_const32, sparc_emit_set_const64,
+ sparc_emit_set_symbolic_const64, input_operand, zero_operand,
+ mem_min_alignment, small_int_or_double): Add externs.
+ * config/sparc/sparc.md: Document the many uses of UNSPEC and
+ UNSPEC_VOLATILE in this backend.
+ (define_function_unit ieu): Rename to ieu_unnamed. Add move and
+ unary to types which execute in it.
+ (define_function_unit ieu_shift): Rename to ieu0.
+ (define_function_unit ieu1): New, executes compare, call, and
+ uncond_branch type insns.
+ (define_function_units for type fdivs, fdivd, fsqrt): These
+ execute in the fpu multiply unit not the adder on UltraSparc.
+ (define_expand cmpdi): Disallow TARGET_V8PLUS.
+ (define_insn cmpsi_insn): Rename to cmpsi_insn_sp32.
+ (define_insn cmpsi_insn_sp64): New, same as sp32 variant except it
+ allows the arith_double_operand predicate and rHI constraint when
+ TARGET_ARCH64.
+ (define_insn cmpdi_sp64, cmpsf_fpe, cmpdf_fpe, cmptf_fpe,
+ cmpsf_fp, cmpdf_fp, cmptf_fp, sltu_insn, neg_sltu_insn,
+ neg_sltu_minux_x, neg_sltu_plus_x, sgeu_insn, neg_sgeu_insn,
+ sltu_plus_x, sltu_plus_x, sltu_plus_x_plus_y, x_minus_sltu,
+ sgeu_plus_x, x_minus_sgeu, movqi_cc_sp64, movhi_cc_sp64,
+ movsi_cc_sp64, movdi_cc_sp64, movsf_cc_sp64, movdf_cc_sp64,
+ movtf_cc_sp64, movqi_cc_reg_sp64, movhi_cc_reg_sp64,
+ movsi_cc_reg_sp64, movdi_cc_reg_sp64, movsf_cc_reg_sp64,
+ movdf_cc_reg_sp64, movtf_cc_reg_sp64, zero_extendhisi2_insn,
+ cmp_siqi_trunc, cmp_siqi_trunc_set, sign_extendhisi2_insn,
+ sign_extendqihi2_insn, sign_extendqisi2_insn,
+ sign_extendqidi2_insn, sign_extendhidi2_insn,
+ extendsfdf2, extendsftf2, extenddftf2, truncdfsf2, trunctfsf2,
+ trunctfdf2, floatsisf2, floatsidf2, floatsitf2, floatdisf2,
+ floatdidf2, floatditf2, fix_truncsfsi2, fix_truncdfsi2,
+ fix_trunctfsi2, fix_truncsfdi2, fix_truncdfdi2, fix_trunctfdi2,
+ adddi3_sp64, addsi3, cmp_ccx_plus, cmp_cc_plus_set, subdi_sp64,
+ subsi3, cmp_minus_ccx, cmp_minus_ccx_set, mulsi3, muldi3,
+ muldi3_v8plus, cmp_mul_set, mulsidi3, mulsidi3_v8plus,
+ const_mulsidi3_v8plus, mulsidi3_sp32, const_mulsidi3,
+ smulsi3_highpart_v8plus, unnamed subreg mult,
+ const_smulsi3_highpart_v8plus, smulsi3_highpart_sp32,
+ const_smulsi3_highpart, umulsidi3_v8plus, umulsidi3_sp32,
+ const_umulsidi3, const_umulsidi3_v8plus, umulsi3_highpart_v8plus,
+ const_umulsi3_highpart_v8plus, umulsi3_highpart_sp32,
+ const_umulsi3_highpart, divsi3, divdi3, cmp_sdiv_cc_set, udivsi3,
+ udivdi3, cmp_udiv_cc_set, smacsi, smacdi, umacdi, anddi3_sp64,
+ andsi3, and_not_di_sp64, and_not_si, iordi3_sp64, iorsi3,
+ or_not_di_sp64, or_not_si, xordi3_sp64, xorsi3, xor_not_di_sp64,
+ xor_not_si, cmp_cc_arith_op, cmp_ccx_arith_op,
+ cmp_cc_arith_op_set, cmp_ccx_arith_op_set, cmp_ccx_xor_not,
+ cmp_cc_xor_not_set, cmp_ccx_xor_not_set, cmp_cc_arith_op_not,
+ cmp_ccx_arith_op_not, cmp_cc_arith_op_not_set,
+ cmp_ccx_arith_op_not_set, negdi2_sp64, cmp_cc_neg, cmp_ccx_neg,
+ cmp_cc_set_neg, cmp_ccx_set_neg, one_cmpldi2_sp64, cmp_cc_not,
+ cmp_ccx_not, cmp_cc_set_not, cmp_ccx_set_not, addtf3, adddf3,
+ addsf3, subtf3, subdf3, subsf3, multf3, muldf3, mulsf3,
+ muldf3_extend, multf3_extend, divtf3, divdf3, divsf3, negtf2,
+ negdf2, negsf2, abstf2, absdf2, abssf2, sqrttf2, sqrtdf2, sqrtsf2,
+ ashlsi3, ashldi3, unnamed DI ashift, cmp_cc_ashift_1,
+ cmp_cc_set_ashift_1, ashrsi3, ashrdi3, unnamed DI ashiftrt,
+ ashrdi3_v8plus, lshrsi3, lshrdi3, unnamed DI lshiftrt,
+ lshrdi3_v8plus, tablejump_sp32, tablejump_sp64, call_address_sp32,
+ call_symbolic_sp32, call_address_sp64, call_symbolic_sp64,
+ call_address_struct_value_sp32, call_symbolic_struct_value_sp32,
+ call_address_untyped_struct_value_sp32,
+ call_symbolic_untyped_struct_value_sp32, call_value_address_sp32,
+ call_value_symbolic_sp32, call_value_address_sp64,
+ call_value_symbolic_sp64, branch_sp32, branch_sp64,
+ flush_register_windows, goto_handler_and_restore,
+ goto_handler_and_restore_v9, goto_handler_and_restore_v9_sp64,
+ flush, all ldd/std peepholes, return_qi, return_hi, return_si,
+ return_addsi, return_di, return_adddi, return_sf, all call+jump
+ peepholes, trap, unnamed trap insns): Prettify output strings.
+ (define_insn anddi3_sp32, and_not_di_sp32, iordi3_sp32,
+ or_not_di_sp32, xordi3_sp32, xor_not_di_sp32, one_cmpldi2):
+ Likewise and force + implement splits for integer cases.
+ (define_insn return_sf_no_fpu): Likewise and allow to match when
+ no-fpu because of our subreg SFmode splits.
+ (define_insn zero_extendqihi2, zero_extendqisi2_insn,
+ zero_extendqidi2_insn, zero_extendhidi2_insn,
+ zero_extendsidi2_insn, sign_extendsidi2_insn): Likewise and use
+ input_operand for second operand.
+ (cmp_minus_cc, cmp_minus_cc_set): Likewise and use
+ reg_or_0_operand for operand 2 so new splits can use it.
+ (cmp_zero_extendqisi2, cmp_zero_extendqisi2_set, cmp_cc_plus,
+ cmp_cc_xor_not): Likewise and don't forget to check TARGET_LIVE_G0
+ too.
+ (cmp_zero_extract, cmp_zero_extract_sp64): Likewise and allow
+ CONST_DOUBLEs for operand 2.
+ (define_insn move_label_di): Likewise and label distance
+ optimization because it no longer works with new deferred case
+ vector scheme. To be revisited.
+ (define_insn x_minus_y_minus_sltu, x_minus_sltu_plus_y): Likewise
+ and allow reg_or_0_operand and J constraint for second operand.
+ (define_insn jump): Set branch predict taken on V9.
+ (define_insn tablejump): Emit LABEL_REF + PLUS memory address for
+ new deferred case vector scheme.
+ (define_insn pic_tablejump_32, pic_tablejump_64): Remove.
+ (define_insn negdi2_sp32): Force + implement splits.
+ (define_insn negsi2, one_cmplsi2): Rename to negsi2_not_liveg0 and
+ one_cmplsi2_not_liveg0 respectively, and create expander of original
+ names which emit special rtl for TARGET_LIVE_G0.
+ (define_insn cmpdi_v8plus, scc_si, scc_di): Remove.
+ (define_insn seq, sne, slt, sge, sle, sltu, sgeu): Don't do
+ gen_compare_reg, FAIL instead.
+ (define_insn sgtu, sleu): Likewise and check gen_s*() return
+ values when trying to reverse condition codes, if they FAIL then
+ do likewise.
+ (define_insn snesi_zero, neg_snesi_zero, snesi_zero_extend,
+ snedi_zero, neg_snedi_zero, snedi_zero_trunc, seqsi_zero,
+ neg_seqsi_zero, seqsi_zero_extend, seqdi_zero, neg_seqdi_zero,
+ seqdi_zero_trunc, x_plus_i_ne_0, x_minus_i_ne_0, x_plus_i_eq_0,
+ x_minus_i_eq_0): Add new splits to perform these multi-insn cases,
+ set output string to # to indicate they are mandatory splits.
+ (define_insn pic_lo_sum_si, pic_sethi_si, pic_lo_sum_di,
+ pic_sethi_di, move_pic_label_si): Remove.
+ (define_insn movsi_low_sum, movsi_high, movsi_lo_sum_pic,
+ movsi_high_pic, movsi_pic_label_reg): New patterns to take their
+ place.
+ (define_expand movsi_pic_label_ref, define_insn
+ movsi_high_pic_label_ref, movsi_lo_sum_pic_label_ref): New
+ expander and insns to handle PIC label references and deferred
+ case vectors.
+ (define_insn get_pc_via_rdpc): Comment out as it is no longer
+ used.
+ (define_expand movqi, movhi, movsi, movdi, movsf, movdf, movtf):
+ Rewrite to not use emit_move_sequence, make use of new constant
+ formation code, and new splits for all multi-insn cases.
+ (define_insn movqi_insn): Remove sethi case, it can never happen.
+ Use reg_or_zero_operand instead of const0_rtx explicit test,
+ use input_operand instead of move_operand for source, and use
+ general_operand now for dest.
+ (define_insn movhi_insn): Similar but leave sethi case.
+ (define_insn lo_sum_qi, store_qi, store_hi): Remove.
+ (define_insn sethi_hi lo_sum_hi): Rename to movhi_high and
+ movhi_lo_sum respectively, prettify output string.
+ (define_insn movsi_zero_liveg0): New pattern to put zero into a
+ register when needed on TARGET_LIVE_G0.
+ (define_insn movsi_insn): Use general_operand and input_operand
+ for dest and src respectively. Simplify applicability test.
+ Prettify output strings, and add clr alternative for J
+ constraint.
+ (define_insn movdi_sp32_v9, movdi_sp32, define_splits for
+ deprecated std and reg-reg DI moves): Remove and...
+ (define_insn movdi_insn_sp32, movdi_insn_sp64): Replace with new
+ implementation which uses forced splits for all non-single insn
+ cases.
+ (define_split DI move cases on !arch64): New splits to handle all
+ situations of 64-bit double register DImode on 32bit, and
+ unaligned registers and memory addresses for all subtargets.
+ (define_insn movsf_const_insn, movdf_const_insn, store_sf):
+ Remove.
+ (define_insn movsf_insn, movsf_no_f_insn): Use general_operand and
+ input_operand for dest and src respectively, prettify output
+ strings.
+ (define_insn movdf_insn, movdf_no_e_insn, store_df,
+ movtf_const_insn, movtf_insn, movtf_no_e_insn, store_tf): Remove
+ and...
+ (define_insn movdf_insn_sp32, movdf_no_e_insn_sp32,
+ movdf_insn_sp64, movdf_no_e_insn_sp64, movtf_insn,
+ movtf_no_e_insn_sp32, movtf_insn_hq_sp64, movtf_insn_sp64,
+ movtf_no_e_insn_sp64): Replace with new
+ implementation which uses forced splits for all non-single insn
+ cases.
+ (define_split DF move cases): New splits in similar vein to DI
+ move counterparts.
+ (define_insn sethi_di_medlow, sethi_di_medium_pic,
+ sethi_di_embmedany_data, sethi_di_embmedany_text, sethi_di_sp64,
+ movdi_sp64_insn): Remove old v9 code model and constant loading
+ support insns and..
+ (define_insn pic_lo_sum_di, pic_sethi_di,
+ sethi_di_medlow_embmedany_pic, sethi_di_medlow, losum_di_medlow,
+ seth44, setm44, setl44, sethh, setlm, sethm, setlo,
+ embmedany_sethi, embmedany_losum, embmedany_brsum,
+ embmedany_textuhi, embmedany_texthi, embmedany_textulo,
+ embmedany_textlo, movdi_lo_sum_sp64_cint, movdi_lo_sum_sp64_dbl,
+ movdi_high_sp64_cint, movdi_high_sp64_dbl): Replace with new
+ scheme, using unspecs, secondary reloads, and one to one sparc
+ insn to rtl insn mapping for better scheduling and code gen.
+ (define_expand reload_indi, reload_outdi): Reload helpers for
+ MEDANY and EMBMEDANY symbol address loading cases which require a
+ temporary register.
+ (define_expand movsicc): Remove v8plus_regcmp cases.
+ (define_insn movdi_cc_sp64_trunc, movdi_cc_reg_sp64_trunc,
+ cmp_zero_extendqidi2, cmp_zero_extendqidi2_set, cmp_qidi_trunc,
+ cmp_diqi_trunc_set): New patterns used by some of the new scc
+ splits on arch64.
+ (define_insn xordi3_sp64_dbl): New pattern used for constant
+ formation when crossing from 32-bit targets.
+ (define_insn movsi_cc_reg_v8plus, v8plus_clear_high, and helper
+ split): Remove.
+ (define_insn addx, subx): Make visible and prettify.
+ (define_insn adddi3_insn_sp32): Likewise and force split.
+ (define_insn addx_extend, subx_extend, unnamed): New patterns for
+ 64bit scc split usage.
+ (define_insn unnamed plusDI zero_extend, unnamed minusDI
+ zero_extend, subdi3): Force and implement splits.
+
+ * final.c (final_scan_insn): Don't output labels if target
+ specifies ASM_OUTPUT_ADDR_{DIFF}_VEC. Do these macro operations
+ instead.
- * m68k.md (iorsi3_internal): Readd ! TARGET_5200 check lost in
- last change.
+ * reorg.c (dbr_schedule): When taking on BR_PRED notes at the end,
+ don't forget to walk inside SEQUENCESs too as these are what the
+ delay slot scheduler will create.
-Wed Aug 27 01:56:18 1997 Doug Evans <dje@seba.cygnus.com>
+Mon Aug 10 01:21:01 1998 Richard Henderson <rth@cygnus.com>
- * loop.c (combine_movables): Earlier insns don't match later ones.
+ * alpha.md (extxl+1,+2): New patterns to work around
+ combine lossage.
-Wed Aug 27 01:24:25 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+Sat Aug 8 19:20:22 1998 Gary Thomas (gdt@linuxppc.org)
- * config/linux.h (CC1_SPEC): Define it only if not defined.
+ * rs6000.c (rs6000_allocate_stack_space): Fix typo which
+ caused bad assembly code to be generated.
- * config/m68k/linux.h (CC1_SPEC): Undefine it before include
- <linux.h>
+Sat Aug 8 18:53:28 1998 Jeffrey A Law (law@cygnus.com)
- * config/linux.h (DEFAULT_VTABLE_THUNKS): New. Defined as 1 if
- USE_GNULIBC_1 is not defined.
+ * netbsd.h: Fix typo.
- * config/rs6000/linux.h (DEFAULT_VTABLE_THUNKS): New. Defined as 1.
+Mon Aug 3 00:06:42 1998 Robert Lipe <robertl@dgii.com>
- * config/sparc/linux.h (DEFAULT_VTABLE_THUNKS): New. Defined
- as 1 if USE_GNULIBC_1 is not defined.
+ * config.sub: Fix typo.
-Wed Aug 27 00:49:14 1997 Jeffrey A Law (law@cygnus.com)
+Sun Aug 2 22:39:08 1998 Hans-Peter Nilsson <hp@axis.se>
- * reorg.c (dbr_schedule): Allow current_function_return_rtx
- to be something other than a REG.
- * function.c (expand_function_end): Fix current_function_return_rtx
- if it was a pseudo.
+ * invoke.texi (Environment Variables): Typo: Change "ascpects"
+ into "aspects".
+ (Running Protoize): Typo: Change "ther" into "other".
- * t-freebsd (USER_H): Include EXTRA_HEADERS and LANG_EXTRA_HEADERS.
- * x-netbsd: Likewise
- * x-dgux (USER_H): Include EXTRA_HEADERS and LANG_EXTRA_HEADERS
- (INSTALL_HEADERS): Delete.
- * x-dguxbcs: Likewise.
- * x-hp3bsd44: Likewise
- * x-pa: Likewise.
+Sun Aug 2 00:42:50 1998 Jeffrey A Law (law@cygnus.com)
-Wed Aug 27 00:30:00 1997 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+ * i386/netbsd.h: Undo previous change to DWARF2_UNWIND_INFO.
+ * m68k/netbsd.h: Likewise.
+ * ns32k/netbsd.h: Likewise.
+ * sparc/netbsd.h: Likewise.
- * i386.md (pop): pop increments the stack pointer.
- (prologue_set_stack_ptr): New pattern.
- * i386.c (ix86_expand_prologue): Use prologue_set_stack_ptr
- instead of subsi3.
+Sat Aug 1 17:59:30 1998 Richard Henderson <rth@cygnus.com>
-Tue Aug 26 18:50:32 1997 Jim Wilson <wilson@cygnus.com>
+ * ginclude/va-alpha.h (va_list): Use a typedef, not a define.
+ * ginclude/va-clipper.h (va_list): Likewise.
- * reload.c (find_reloads, case '0'): Reject matching a non-offsettable
- address where an offsettable address is required.
+Fri Jul 31 20:22:02 1998 Michael Meissner <meissner@cygnus.com>
-Tue Aug 26 17:54:56 1997 Michael P. Hayes (michaelh@ongaonga.chch.cri.nz>
+ * rs6000.c (rs6000_override_options): If big endian and -Os, use
+ load/store multiple instructions unless user overrides.
- * loop.c (check_final_value): Don't miss a biv increment in a
- parallel.
+Fri Jul 31 17:08:59 1998 Jeffrey A Law (law@cygnus.com)
-Tue Aug 26 12:03:49 1997 Jim Wilson (wilson@cygnus.com)
+ * ns32k/netbsd.h: Fix typo.
- * dwarfout.c (dwarfout_file_scope_decl, case TYPE_DECL): Check
- TYPE_DECL_IS_STUB instead of DECL_NAME.
+Fri Jul 31 10:23:55 1998 Doug Evans <devans@canuck.cygnus.com>
-Mon Aug 25 23:27:10 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+ * m32r/m32r.h (ASM_OUTPUT_SOURCE_LINE): Always output line number
+ labels with .debugsym if no parallel insns.
- * objc/Make-lang.in ($(OBJC_O)): Also depend on cc1obj.
+Thu Jul 30 19:15:53 1998 Richard Henderson <rth@cygnus.com>
-Mon Aug 25 23:27:10 1997 Jim Meyering <meyering@eng.ascend.com>
+ * alpha.md (fp cmp): Replicate patterns for ALPHA_TP_INSN.
+ (fcmov): Remove ALPHA_TP_INSN patterns -- fcmov doesn't trap.
- * objc/Make-lang.in ($(OBJC_O)): Also depend on $(GCC_PASSES).
+Thu Jul 30 19:50:15 1998 David Edelsohn <edelsohn@gnu.org>
-Mon Aug 25 13:12:24 1997 Jeffrey A Law (law@cygnus.com)
+ * rs6000/x-aix43 (AR_FOR_TARGET_FLAGS): Delete.
+ (AR_FOR_TARGET): Define.
- * haifa-sched.c (find_pre_sched_live): Remove #if 0 code.
- (find_post_sched_live): Likewise.
+Thu Jul 30 12:29:12 1998 Mark Mitchell <mark@markmitchell.com>
- * haifa-sched.c (schedule_block): Remove old code to get arguments
- from hard regs into pseudos early.
+ * dyn-string.h: New file.
+ * dyn-string.c: Likewise.
+ * Makefile.in (OBJS): Add dyn-string.o.
+ (dwarf2out.o): Add dyn-string.h dependency.
+ (dyn-string.o): List dependencies.
+ * dwarf2out.c: Include dyn-string.h.
+ (ASM_NAME_TO_STRING): Use dyn_string_append, rather than strcpy.
+ (addr_const_to_string): Take a dyn_string_t, not a char* as a
+ prototype. Use dyn_string_append rather than strcat, throughout.
+ (addr_to_string): Use dyn_string_t.
-Mon Aug 25 08:55:00 1997 Jeffrey A Law (law@cygnus.com)
+Thu Jul 30 13:08:07 1998 Ken Raeburn <raeburn@cygnus.com>
+
+ Function entry/exit profiling instrumentation:
+ * expr.h (profile_function_entry_libfunc,
+ profile_function_exit_libfunc): Declare new variables.
+ * optabs.c: Define them here.
+ (init_optabs): Initialize them.
+ * tree.h (struct tree_decl): New flag
+ no_instrument_function_entry_exit.
+ (DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT): New accessor macro.
+ * c-decl.c (duplicate_decls): Merge it.
+ * c-common.c (enum attrs): New value A_NO_INSTRUMENT_FUNCTION.
+ (init_attributes): Use it for "no_instrument_function".
+ (decl_attributes): Handle it, for functions that have not yet been
+ compiled. Set decl flag.
+ * flags.h (flag_instrument_function_entry_exit): Declare new
+ variable.
+ * toplev.c (flag_instrument_function_entry_exit): Define it here.
+ (f_options): New option "instrument-functions".
+ * function.h (struct function): New field instrument_entry_exit.
+ * function.c (current_function_instrument_entry_exit): New
+ variable.
+ (push_function_context_to, pop_function_context_from): Save and
+ restore.
+ (expand_function_start): Set current_ variable, maybe emit return
+ label and entry profile call.
+ (expand_function_end): Maybe emit exit profile call.
- * version.c: Bump for new snapshot.
+Thu Jul 30 00:58:34 1998 Jeffrey A Law (law@cygnus.com)
- * local-alloc.c (update_equiv_regs): All the target to reject
- promotion of some REG_EQUAL to REG_EQUIV notes.
- * pa.h (DONT_RECORD_EQUIVALENCE): Define.
+ * i386.md (movqi): When optimizing a load of (const_int 1) into a
+ NON_QI_REG_P, pretend the register is SImode.
- * pa.c (secondary_reload_class): (mem (mem ... )) does not need
- secondary reloads.
+Wed Jul 29 23:49:23 1998 Todd Vierling <tv@netbsd.org>
- * pa.c (hppa_builtin_saveregs): Emit a blockage insn after the
- store of the argument registers.
+ * configure.in: Use xm-netbsd.h as the NetBSD xm file (not xm-siglist).
+ Accept arm32 as arm, m68k4k as m68k, mipsle as mips-dec, and any
+ manufacturer id for ns32k.
+ * configure: Regenerated.
+ * config/netbsd.h: When using ASM_WEAKEN_LABEL, make it global too.
+ * config/t-netbsd: Don't compile libgcc1-test as the fns are in libc.
+ * config/i386/netbsd.h: Undefine DWARF2_UNWIND_INFO, not define as 0.
+ * config/m68k/netbsd.h: Same.
+ * config/ns32k/netbsd.h: Same.
+ * config/sparc/netbsd.h: Same.
-Mon Aug 25 08:39:02 1997 Craig Burley (burley@gnu.ai.mit.edu)
+Wed Jul 29 22:39:21 1998 Jeffrey A Law (law@cygnus.com)
- * fold-const.c (multiple_of_p): New function.
- (fold): Turn some cases of *_DIV_EXPR into EXACT_DIV_EXPR.
+ * unroll.c (unroll_loop): Do not abort for an UNROLL_MODULO
+ or UNROLL_COMPLETELY loop that starts with a jump to its
+ exit code.
-Mon Aug 25 01:47:41 1997 Jeffrey A Law (law@cygnus.com)
+Wed Jul 29 22:18:14 1998 David Edelsohn <edelsohn@gnu.org>
- * expr.h (insn_gen_function): Temporarily remove prototype.
+ * rs6000/rs6000.md (absdi2 define_split): Swap operands of MINUS.
+ * rs6000/rs6000.c (mask64_operand): Use HOST_BITS_PER_WIDE_INT.
+ (print_operand, case 'B'): Don't fall through.
+ (print_operand, case 'S'): Correct mask begin/end computation.
+ Use HOST_BITS_PER_WIDE_INT.
+ * rs6000/rs6000.h (CPP_PREDEFINES): Define _LONG_LONG.
+ (CONDITIONAL_REGISTER_USAGE): GPR13 fixed if TARGET_64BIT.
+ * rs6000/aix41.h (CPP_PREDEFINES): Same.
+ * rs6000/aix43.h (CPP_PREDEFINES): Same.
-Sun Aug 24 17:22:21 1997 Jim Wilson <wilson@cygnus.com>
+Wed Jul 29 11:47:10 1998 Nick Clifton <nickc@cygnus.com>
- * Makefile.in (install-info): Don't cd into srcdir. Add srcdir to
- filenames. Use sed to extract base filename for install.
+ * config/arm/thumb.md (extendqisi2_insn): Remove earlyclobber
+ constraint from second alternative.
-Sat Aug 23 18:19:40 1997 John F. Carr <jfc@mit.edu>
+Tue Jul 28 23:29:04 1998 Jason Merrill <jason@yorick.cygnus.com>
- * unroll.c (find_splittable_givs): Only share if two givs have the
- same add and multiply values.
+ * configure.in: Fix --without/--disable cases for local-prefix,
+ gxx-include-dir and checking.
-Sat Aug 23 14:36:27 1997 Jim Wilson <wilson@cygnus.com>
+Tue Jul 28 22:01:23 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * m68k/next.h (GO_IF_INDEXABLE_BASE): Fix typo in undef.
- * m68k/m68kemb.h (LIB_SPEC): Add missing comment end before it.
+ * configure.in (enable_haifa): Set by default for sparc64 too.
+ configure: Rebuilt.
-Sat Aug 23 00:18:22 1997 Jeffrey A Law (law@cygnus.com)
+Tue Jul 28 23:29:04 1998 Jason Merrill <jason@yorick.cygnus.com>
- * pa.c (pa_reorg): Always put begin_brtab and end_brtab insns
- around branch tables.
- * pa.md (begin_brtab, end_brtab): Only emit the .begin_brtab
- and .end_brtab directives if TARGET_GAS.
+ * i386/cygwin32.h (VALID_MACHINE_TYPE_ATTRIBUTE): New macro.
+ * i386/winnt.c (associated_type): New fn.
+ (i386_pe_valid_type_attribute_p): New fn.
+ (i386_pe_check_vtable_importexport): Remove.
+ (i386_pe_dllexport_p): Use associated_type.
+ (i386_pe_dllimport_p): Likewise.
-Fri Aug 22 14:05:55 1997 Jim Wilson <wilson@cygnus.com>
+ From Antonio M. O. Neto <anmendes@cruzeironet.com.br>:
+ * i386.c (i386_valid_type_attribute_p): Also accept
+ attributes for METHOD_TYPEs.
- * alias.c (true_dependence): Pass x_addr not x to varies.
+Tue Jul 28 23:17:39 1998 Peter Gerwinski <peter@gerwinski.de>
- * acconfig.h (NEED_DECLARATION_CALLOC): Add.
- * configure.in: Add GCC_NEED_DECLARATION call for calloc.
- * rs6000/xm-rs6000.h (malloc, realloc, calloc, free): Delete
- declarations.
- * config.in, configure: Regenerate.
+ * tree.c (build_range_type): Copy TYPE_SIZE_UNIT.
-Thu Aug 21 23:52:16 1997 John F. Carr <jfc@mit.edu>
+Tue Jul 28 22:31:12 1998 Craig Burley <burley@gnu.org>
- * alias.c (find_base_value): Improve handling of PLUS, MINUS, and
- LO_SUM.
- (record_set): Handle LO_SUM like PLUS.
- (init_alias_analysis): When following chains of base addresses,
- do not stop on reaching a hard register.
+ * gcc.c: Fix commentary describing %g, %u, %U, and %O.
-Thu Aug 21 20:17:37 1997 Jeffrey A Law (law@cygnus.com)
+ * gcc.c (do_spec_1): Fix handling of %g%O and %U%O to prevent
+ them from generating a new base name for each occurrence of
+ a specific suffix.
- * version.c: Bump for new snapshot.
+1998-07-28 Vladimir N. Makarov <vmakarov@cygnus.com>
-Thu Aug 21 17:28:00 1997 Jim Wilson <wilson@cygnus.com>
+ * cse.c (cse_insn): Enable substitution inside libcall only for REG,
+ SUBREG, MEM.
+ * rtlanal.c (replace_rtx): Prohibit replaces in CONST_DOUBLE.
- * alpha.h (ARCH_ASM_FILE_START): Define.
- (ASM_FILE_START): Use ARCH_ASM_FILE_START.
- * osf12.h, osf2or3.h (ARCH_ASM_FILE_START): Redefine to null string.
+ * cplus-dem.c (type_kind_t): New type.
+ (demangle_template_value_parm): Add type_kind_t parameter. Rely
+ on this parameter, rather than demangling the type again.
+ (demangle_integral_value): Pass tk_integral.
+ (demangle_template_: Pass the value returned from do_type.
+ (do_type): Return a type_kind_t. Pass tk_integral to
+ demangle_template_value_parm for array bounds.
+ (demangle_fund_type): Likewise.
-Thu Aug 21 10:22:19 1997 Jeffrey A Law (law@cygnus.com)
+Mon Jul 27 00:54:41 1998 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (install-common): Put gcov comment at start of line.
+ * tree.c (simple_cst_equal, case CONSTRUCTOR): OK if the elts are
+ identical.
-Wed Aug 20 22:47:33 1997 Jeffrey A Law (law@cygnus.com)
+Mon Jul 27 22:18:36 1998 Jeffrey A Law (law@cygnus.com)
- * alias.c (init_alias_analysis): When simplifying the reg_base_value
- array, simplify entries for hard registers too.
+ * pa.c (move_operand): Accept CONSTANT_P_RTX.
-Wed Aug 20 12:35:47 1997 Dave Love <d.love@dl.ac.uk>
+Mon Jul 27 17:18:52 1998 Dave Brolley <brolley@cygnus.com>
- * dwarf2.h (enum dwarf_call_frame_info): Remove trailing comma from
- list.
+ * stor-layout.c (layout_type): Handle arrays of bits, for Chill.
-Wed Aug 20 11:58:33 1997 Jim Wilson <wilson@cygnus.com>
+ * expr.c (get_inner_reference): Handle zero-based, unsigned, array
+ index conversion.
- * stmt.c (start_cleanup_deferal, end_cleanup_deferal): Test
- block_stack before dereferencing it.
+Mon Jul 27 14:51:33 1998 Jeffrey A Law (law@cygnus.com)
-Wed Aug 20 11:57:11 1997 Michael Meissner <meissner@cygnus.com>
+ * mn10300.h (DEBUGGER_AUTO_OFFSET): Define.
+ (DEBUGGER_ARG_OFFSET): Likewise.
- * rs6000.h (ISSUE_RATE): Define instead of MACHINE_issue_rate.
+ * mn10300.md (movsf): Remove last change. Not needed.
-Tue Aug 19 17:10:56 1997 Jason Merrill <jason@yorick.cygnus.com>
+Mon Jul 27 14:22:36 1998 Dave Brolley <brolley@cygnus.com>
- * cplus-dem.c: Add 'extern' to prepends_underscore.
+ * c-lex.c (yylex): Fix boundary conditions in character literal and
+ string literal loops.
-Tue Aug 19 09:34:57 1997 Jeffrey A Law (law@cygnus.com)
+Mon Jul 27 11:43:54 1998 Stan Cox <scox@cygnus.com>
- * haifa-sched.c (ISSUE_RATE): Renamed from MACHINE_issue_rate.
- (get_issue_rate): Delete.
- * pa.h (ISSUE_RATE): Define.
+ * longlong.h (count_leading_zeros): Sparclite scan instruction was
+ being invoked incorrectly.
- * configure.in: Turn on haifa by default for the PA.
+ * i386.c (ix86_prologue): Added SUBTARGET_PROLOGUE invocation.
+ * i386/cygwin32.h (STARTFILE_SPEC, LIB_SPEC, SUBTARGET_PROLOGUE):
+ Add -pg support.
+ * i386/win32.h: New file. Hybrid mingw32.h/cygwin32.h configuration.
+ * configure.in: Added i[34567]86-*-win32.
+ * config.sub: Likewise.
* configure: Rebuilt.
- * pa.c (override_options): Accept -mschedule=7200 option.
- (pa_adjust_cost): No longer need to scale costs for newer
- processors.
- * pa.h (enum processor_type): Add PROCESSOR_7200.
- * pa.md: Revamp scheduling parameters to work better with
- haifa. Add scheduling parameters for the 7200.
- * haifa-sched.c (move_insn): Reemit notes for SCHED_GROUP_P
- insns too.
- (schedule_block): When adjusting basic_block_{head,end}, account
- for movement of SCHED_GROUP_P insns too.
+Sun Jul 26 01:11:12 1998 H.J. Lu (hjl@gnu.org)
+
+ * i386.h (CONST_DOUBLE_OK_FOR_LETTER_P): Return 0 when eliminating
+ the frame pointer and compiling PIC code and reload has not completed.
+
+ * i386.c (output_to_reg): Add code to emulate non-popping DImode
+ case.
+
+Sun Jul 26 01:01:32 1998 Jeffrey A Law (law@cygnus.com)
- * haifa-sched.c (debug_dependencies): Fix thinko.
+ * regmove.c (regmove_optimize): Fix typo initializing regmove_bb_head.
- * Makefile.in (EXPECT, RUNTEST, RUNTESTFLAGS): Define.
- (site.exp, check, check-g++, check-gcc): New targets.
+Sat Jul 25 23:29:23 1998 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- * haifa-sched.c: Make lots of variables static.
+ * Makefile.in (install-info): Only try to update the info
+ directory file if it exists in the first place.
-Tue Aug 19 07:18:34 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+Fri Jul 24 18:58:37 1998 Klaus Espenlaub <kespenla@student.informatik.uni-ulm.de>
- * expr.h, real.h: Finish prototyping.
+ * rs6000.h (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): Delete.
-Mon Aug 18 21:49:02 1997 Jim Wilson <wilson@cygnus.com>
+Fri Jul 24 14:20:26 1998 Jeffrey A Law (law@cygnus.com)
- * reload.c (find_reloads): Add code to convert RELOAD_FOR_OPADDR_ADDR
- reloads to RELOAD_FOR_OPERAND_ADDRESS reloads.
- * reload1.c: Undo bugfix from Aug 11.
+ * mn10300.md (movqi, movhi, movsi, movsf): Correctly handle
+ CONST_DOUBLE source.
-Mon Aug 18 17:39:02 1997 Mike Meissner <meissner@cygnus.com>
+Fri Jul 24 11:17:04 1998 Nick Clifton <nickc@cygnus.com>
- * configure.in ({powerpc,rs6000}*-*-*, --with-cpu): Remove single
- quotes around the name.
- * configure: Regenerate.
+ * config/arm/thumb.c (thumb_print_operand): Decode %_ in asm
+ strings as the insertion of USER_LABEL_PREFIX.
+ * config/arm/thumb.h (PRINT_OPERAND_PUNCT_VALID_P): Accept _ as a
+ valid code.
+ * config/arm/thumb.md: Use %_ as a prefix to gcc library function
+ calls.
+
+Thu Jul 23 18:53:20 1998 Jim Wilson <wilson@cygnus.com>
-Mon Aug 18 13:46:47 1997 Jim Wilson <wilson@cygnus.com>
+ * dbxout.c (dbxout_range_type): Only call dbxout_type_index for
+ already defined type.
- * Makefile.in (stmp-multilib-sub): Fix typo in last change.
+Thu Jul 23 13:49:41 1998 Jeffrey A Law (law@cygnus.com)
-Thu Aug 7 10:33:13 1997 Manfred Hollstein <manfred@s-direktnet.de>
+ * expr.c (check_max_integer_computation_mode): Allow conversions
+ of constant integers to MAX_INTEGER_COMPUTATION_MODE.
+ (expand_expr): Likewise.
- * Makefile.in (sub-makes): Pass the current value of LANGUAGES down
- to sub-makes to avoid building more passes than the user might have
- requested on the command line.
+Thu Jul 23 11:12:06 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
-Sun Aug 17 15:42:17 1997 Dave Love (d.love@dl.ac.uk)
+ * expr.c (expand_expr): Expand RETURN_EXPR.
- * configure.in: Expurgate `broken_install' (install is
- autoconfed).
+Thu Jul 23 11:00:29 1998 Jim Wilson <wilson@cygnus.com>
- * configure.lang: Substitute autoconfed ${INSTALL} (not currently
- relevant).
+ * dwarf2out.c (dwarf2out_finish): Call stripattributes on TEXT_SECTION.
-Sat Aug 16 01:08:12 1997 Jeffrey A Law (law@cygnus.com)
+Wed Jul 22 19:10:00 1998 Catherine Moore <clm@cygnus.com>
- * loop.c (is_power_of_2, is_conditional_branch): Delete unused
- functions and declarations.
- (analyze_loop_iterations): Use condjump_p.
- (insert_bct): Likewise. Use exact_log2.
+ * dwarf2out.c (output_aranges): Call stripattributes
+ for TEXT_SECTION references.
+ (output_line_info): Likewise.
-Fri Aug 15 23:48:32 1997 Jeffrey A Law (law@cygnus.com)
+Wed Jul 22 14:08:54 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
- * haifa-sched.c (find_post_sched_live): Call FREE_REG_SET as needed.
- (schedule_region): Likewise.
- (schedule_insns): Likewise.
+ * profile.c (branch_prob): Call allocate_reg_info after outputting
+ profile rtl in instrument_arcs.
- * PROJECTS: Update with Haifa stuff.
+Wed Jul 22 12:47:49 1998 Jim Wilson <wilson@cygnus.com>
-Fri Aug 15 12:49:56 1997 Jeffrey A Law (law@cygnus.com)
+ * fixinc.irix (math.h): Install wrapper instead of copying.
- * version.c: Change the version string to look like:
- egcs-2.90.00 970814 (gcc2-970802 experimental).
+Wed Jul 22 12:37:14 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
- * loop.c (is_conditional_branch): Make definition match declaration.
+ * tree.def (EXPR_WITH_FILE_LOCATION): Defined as an 'e' expression
+ so WFL are expanded correctly when contained in a COMPOUND_EXPR.
+ * tree.h (EXPR_WFL_EMIT_LINE_NOTE): Change macro not to use
+ lang_flag_0. Added documentation in the flag table.
- * gcc.c: Take out experimental snapshot warning message.
+Tue Jul 21 23:28:35 1998 Klaus Kaempf <kkaempf@rmi.de>
-Fri Aug 15 13:43:39 1997 Michael Meissner <meissner@cygnus.com>
+ * cccp.c (do_include): Fix vax c style include handling.
- * haifa-sched.c (debug_dependencies): Use GET_NOTE_INSN_NAME to
- print out the names of the notes. Print out the name of the insn
- that is not a note, and not an {,CALL_,JUMP_}INSN.
+Tue Jul 21 13:28:19 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Aug 13 17:32:38 1997 Jason Merrill <jason@yorick.cygnus.com>
+ * cplus-dem.c (do_type): Use demangle_template_value_parm for arrays.
- * expr.c (expand_expr, case TARGET_EXPR): Call mark_addressable
- again for the slot after we give it RTL.
+Sun Jul 12 01:27:05 1998 Jason Merrill <jason@yorick.cygnus.com>
-Wed Aug 13 01:03:37 1997 Doug Evans <dje@canuck.cygnus.com>
+ * fold-const.c (non_lvalue): Don't deal with null pointer
+ constants here.
+ (fold, case COMPOUND_EXPR): Wrap a constant 0 in a NOP_EXPR.
- * configure.in (haifa configury): Fix typo.
- * configure: Regenerate.
+Tue Jul 21 15:49:31 1998 David Edelsohn <edelsohn@gnu.org>
-Tue Aug 12 10:20:36 1997 Jeffrey A Law (law@cygnus.com)
+ * rs6000.h (PREDICATE_CODES): Add CONSTANT_P_RTX.
+ * rs6000.md (movsi, movdi): Add CONSTANT_P_RTX.
+ * rs6000.c (short_cint_operand): Add CONSTANT_P_RTX.
+ (u_short_cint_operand): Same.
+ (reg_or_cint_operand): Same.
+ (logical_operand): Same.
+ (input_operand): Same.
+ (reg_or_short_operand): Use u_short_cint_operand.
- * version.c: Bump version to "gcc-3.0.0 970802 experimental".
+Tue Jul 21 08:56:42 1998 Richard Henderson <rth@cygnus.com>
- * gcc.info*: Rebuilt.
+ * alpha.md (fix_truncdfsi2, fix_truncsfsi2): Remove the define_expands,
+ but keep the insns and splits. Adjust so when the ultimate destination
+ is memory, use cvtql.
- * COPYING.g77, README.g77: New files.
- * real.c (ereal_unto_float, ereal_unto_double): New functions.
- * real.h (ereal_unto_float, ereal_unto_double): Declare them.
- (REAL_VALUE_UNTO_TARGET_DOUBLE, REAL_VALUE_UNTO_TARGET_SINGLE): Define.
+Tue Jul 21 08:55:09 1998 Richard Henderson <rth@cygnus.com>
-Mon Aug 11 14:50:55 1997 Jeffrey A Law (law@cygnus.com)
+ * flow.c (regno_uninitialized): Fixed regs are never uninitialized.
- * Integrate Haifa instruction scheduler.
- * Makefile.in (ALL_CFLAGS): Add SCHED_CFLAGS. Prefix all references
- to sched with $(SCHED_CFLAGS.
- * configure.in: Handle --enable-haifa.
+Tue Jul 21 00:31:01 1998 Jeffrey A Law (law@cygnus.com)
+
+ * gcc.c (do_spec): Call "error" not "warning".
+
+ * configure.in: Fix minor problems with gas feature detection code.
* configure: Rebuilt.
- * flags.h: Add new flags for haifa instruction scheduler.
- * genattrtab.c (expand_units): For haifa, don't subtract one
- when computing blockage.
- * toplev.h (flag_schedule_interblock): Haifa scheduler flag.
- (flag_schedule_speculative): Ditto.
- (flag_schedule_speculative_load): Ditto.
- (flag_schedule_speculative_load_dangerous): Ditto.
- (flag_schedule_reverse_before_reload): Ditto.
- (flag_schedule_reverse_after_reload): Ditto.
- (flag_branch_on_count_reg): Ditto.
- (f_options): Add Haifa switches.
- (main): Turn off some Haifa options if appropriate macro is
- defined. Process Haifa switches.
- * unroll.c (iteration_info): No longer static, since Haifa
- scheduler uses it.
- (unroll_loop): Inform HAIFA scheduler about loop unrolling factor.
- * unroll.c (unroll_loop): Set loop_unroll_iter, loop_start_value.
- * loop.h (loop_unroll_factor, loop_number): Add HAIFA decls.
- * loop.h (loop_initial_value,loop_unroll_iter): New globals.
- * loop.c (loop_optimize): If HAIFA is defined, allocate additional
- storage for the Haifa scheduler.
- (mark_loop_jump): If HAIFA defined, set LABEL_OUTSIDE_LOOP_P and
- LABEL_NEXTREF.
- (strength_reduce): If HAIFA and HAVE_decrement_and_branch_on_count
- are defined, call analyze_loop_iterations and insert_bct to use
- countdown loops.
- (record_giv): Refine test for jumps out of loops if HAIFA is
- defined.
- (analyze_loop_iterations): New function to identify if we can use
- a countdown loop.
- (insert_bct): Insert countdown loop.
- (instrument_loop_bct): Low level code to insert countdown loop.
- (loop_number): Calculate UID of loop.
- (indirect_jump_in_function_p): Return true if an indirect jump is
- in the function.
- (is_power_of_2): Return true if value is a power of 2.
- (is_conditional_branch): Return true if insn is a conditional
- jump.
- (fix_bct_param): Process -fbct-{min,max}-N switches.
- (check_bct_param): Return true if loop should be instrumented.
- * loop.c (loop_initial_value,loop_unroll_iter): New globals.
- (loop_optimize): Initialize.
- (get_condition_for_loop): Ditto.
- * loop.c (strength_reduce): Inside of code that uses #ifdef
- HAVE_decrement_and_branch_on_count code, test it to make sure the
- condition is true.
- (instrument_loop_bct): Ditto.
- * haifa-sched.c: New file.
-
-
- * Integrate regmove pass.
- * Makefile.in (OBJS): Add regmove.o
- (regmove.o): Add dependencies.
- * flow.c (find_use_as_address): No longer static.
- * rtl.h (find_use_as_address): Declare.
- * toplev.c (regmove_dump, flag_regmove): Define.
- (f_options): Add -fregmove.
- (regmove_dump_file, regmove_time): Define.
- (fatal_insn): Close the regmove dump file.
- (compile_file): Initialize regmove_time; open/close the regmove dump
- file as needed. Print regmove time as needed.
- (rest_of_compilation): Run regmove pass if requested, dump
- RTL after regmove if requested.
- (main): If -O2 or more, turn on regmove. Handle dump switches.
- * regmove.c: New file.
-
-Mon Aug 11 14:15:02 1997 Jeffrey A Law (law@cygnus.com)
-
- * Integrate tlink patch from jason@cygnus.com
- * gcc.c (SWITCH_TAKES_ARG): Add 'V', 'B' and 'b'.
- (process_command): Increment n_switches for them. Don't discard
- their args. Validate them.
- (main): Escape " marks when creating COLLECT_GCC_OPTIONS.
- From Rohan Lenard.
- (process_command): Set include_prefixes from COMPILER_PATH.
- (main): Set COLLECT_GCC_OPTIONS sooner.
- * confiugre.in: Link ../ld/ld.new to collect-ld rather than real-ld.
- * tlink.c, hash.c, hash.h: New files.
- * Makefile.in (USE_COLLECT2): Always use collect2.
- (collect2): Depend on and link in hash.o and tlink.o.
- (tlink.o, hash.o): Add dependencies.
-
-Mon Aug 11 10:04:49 1997 Jeffrey A Law (law@cygnus.com)
-
- * Integrate alias analysis changes from jfc@mit.edu
- * Makefile.in (OBJS): Add alias.o
- (alias.o): Add dependencies.
- * alias.c: New file.
- * sched.c: Remove alias analysis code. It lives in alias.c now.
- (sched_analyze_2): Add new arguments to true_dependence.
- (schedule_insns): Always call init_alias_analysis.
- * calls.c (expand_call): Note calls to malloc, calloc, and realloc;
- mark return value from such functions as a pointer and keep track of
- them for alias analysis. If a return value from a function is a
- pointer, mark it as such.
- * combine.c (distribute_notes): Handle REG_NOALIAS.
- * cse.c (struct write_data): Delete. No longer needed.
- (invalidate): Don't call set_nonvarying_address_components anymore.
- Use true_dependence to decide if an entry should be removed from
- the hash table.
- (invalidate_memory): Remove WRITES argument, simplify appropriately.
- Fix all callers.
- (note_mem_written): Similarly for WRITE_PTR argument.
- (invalidate_from_clobbers): Similarly for W argument.
- (invalidate_for_call): Remove memory elements from the hash table.
- (refers_to_mem_p, cse_rtx_addr_varies_p): Deleted.
- (cse_rtx_varies_p): New function. Derived from old
- cse_rtx_addr_varies_p.
- (cse_insn): Remove WRITES_MEMORY and INIT variables and all references.
- Don't call note_mem_written anymore. Stack pushes invalidate the stack
- pointer if PUSH_ROUNDING is defined. No longer need to call
- cse_rtx_addr_varies_p to decide if a MEM should be invalidated.
- (skipped_writes_memory): Remove variable.
- (invalidate_skipped_set): Simplify and wewrite to use invalidate_memory.
- (invalidate_skipped_block): Simplify for new alias analysis code.
- (cse_set_around_loop): Likewise.
- (cse_main): Call init_alias_analysis.
- * flags.h (flag_alias_check, flag_argument_noalias): Declare.
- * toplev.c (flag_alias_check, flag_argument_noalias): Define.
- (f_options): Add new alias checking arguments.
- (main): Set flag_alias_check when optimizing.
- * local_alloc (validate_equiv_mem_from_store): Add new arguments
- to true_dependence.
- (memref_referenced_p): Likewise.
- * loop.c (NUM_STORES): Increase to 30.
- (prescan_loop): Only non-constant calls set unknown_address_altered.
- (invariant_p): Add new arguments to true_dependence.
- (record_giv): Initialize unrolled and shared fields.
- (emit_iv_add_mult): Call record_base_value as needed.
- * loop.h (struct induction): Add unrolled and shared fields.
- * unroll.c (unroll_loop): Call record_base_value as needed.
- (copy_loop_body): Likewise.
- (final_biv_value): Likewise.
- (final_giv_value): Likewise.
- (find_splittable_regs): Likewise. Only create one new pseudo
- if we have multiple address GIVs that were combined with the same
- dst_reg GIV. Note when a new register is created due to unrolling.
- * rtl.c (reg_note_name): Add REG_NOALIAS.
- * rtl.h (enum reg_note): Similarly.
- (rtx_varies_p, may_trap_p, side_effects_p): Declare.
- (volatile_refs_p, volatile_insn_p, remove_note): Likewise.
- (note_stores, refers_to_regno_p, reg_overlap_mentioned_p): Likewise.
- (true_dependence, read_dependence, anti_dependence): Likewise.
- (output_dependence, init_alias_analysis, end_alias_analysis): Likewise.
- (mark_user_reg, mark_reg_pointer): Likewise.
-
-
- * Integrate reload bugfix from Wilon which enables the PA port
- to bootstrap again.
- * reload1.c (reload): Sum needs for both OPADDR_ADDR and
- OPERAND_ADDRESS when computing how many registers an insn needs.
- (reload_reg_free_p): OPADDR_ADDR and OPERAND_ADDRESS reloads do
- conflict.
- (reload_reg_free_before_p): Treat OPERAND_ADDRESS reloads just like
- OPADDR_ADDR reload.
- (reload_reg_reaches_end_p): For RELOAD_FOR_OPADDR_ADDR insns, registers
- in reload_reg_use_in_op_addr do not reach the end.
- do not reach the end.
- (reloads_conflict): RELOAD_FOR_OPADDR_ADDR conflicts with
- RELOAD_FOR_OPERAND_ADDRESS.
-
-Sun Aug 10 12:00:20 1997 Jeffrey A Law (law@cygnus.com)
-
- * egcs project officially starts.
+
+ * gcc.c (do_spec): Issue a warning for '%[]' usage.
+
+ * Undo this change.
+ * gcc.c: Delete %[spec] support.
+ (do_spec_1, case '('): Likewise.
+ (do_spec_1, case '['): Call error.
+
+Mon Jul 20 22:34:17 1998 Richard Henderson <rth@cygnus.com>
+
+ * alpha.h (CPP_SPEC): Tidy. Hook to cpp_cpu and cpp_subtarget.
+ (CPP_SUBTARGET_SPEC): Default to empty string.
+ (CPP_AM_*, CPP_IM_*, CPP_CPU_*, CPP_CPU_SPEC): New.
+ (EXTRA_SPECS, SUBTARGET_EXTRA_SPECS): New.
+ * alpha/elf.h (LD_SPEC): Use %(elf_dynamic_linker).
+ * alpha/linux-elf.h (SUBTARGET_EXTRA_SPECS): New.
+ (LIB_SPEC): Tidy.
+ * alpha/linux.h (CPP_PREDEFINES): Tidy.
+ * alpha/netbsd-elf.h (SUBTARGET_EXTRA_SPECS): New.
+ * alpha/netbsd.h (CPP_PREDEFINES): Tidy.
+ * alpha/osf.h (CPP_PREDEFINES): Remove bits subsumed by CPP_CPU_SPEC.
+ * alpha/win-nt.h (CPP_PREDEFINES): Likewise.
+ * alpha/vsf.h (CPP_PREDEFINES): Likewise.
+ (CPP_SUBTARGET_SPEC): New. Do this instead of overriding CPP_SPEC.
+ * alpha/vxworks.h: Likewise.
+
+Mon Jul 20 22:51:57 1998 Ken Raeburn <raeburn@cygnus.com>
+
+ * mips.md (reload_outsi): Added missing REGNO call.
+ (smulsi3_highpart, umulsi3_highpart): Provide prototype for
+ function pointer.
+ (mul_acc_di, mul_acc_64bit_di): Don't use match_op_dup, use
+ another match_operator and compare the codes.
+
+ * mips.h (MASK_DEBUG_E, MASK_DEBUG_I): Set to zero.
+
+ * MIPS multiply pattern fixes:
+ * mips.h (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS):
+ Add union classes for HI, LO, or HILO plus general registers.
+ (GENERATE_MADD): Deleted.
+ * mips.md (mulsi3_mult3): Don't disparage output-LO alternative.
+ Add TARGET_MAD to condition.
+ (mulsi3): Test HAVE_mulsi3_mult3, not specific flags.
+ (mul_acc_si): Expand GENERATE_MADD here; it's the only use. Use
+ "*d" for accumulator, to give preference to LO initially but not
+ during reload.
+
+Mon Jul 20 16:16:38 1998 Dave Brolley <brolley@cygnus.com>
+
+ * configure.in (enable_c_mbchar): New configure option.
+ (extra_cpp_objs): Always available now.
+
+ * cexp.y (mbchar.h): #include it.
+ (yylex): Handle Multibyte characters in character literals.
+
+ * cccp.c (mbchar.h): #include it.
+ (main): Set character set based on LANG environment variable.
+ (rescan): Handle multibyte characters in comments.
+ (skip_if_group): See above.
+ (validate_else): See above.
+ (skip_to_end_of_comment): See above.
+ (macarg1): See above.
+ (discard_comments): See above.
+ (rescan): Handle multibyte characters in string and character literals.
+ (collect_expansion): See above.
+ (skip_quoted_string): See above.
+ (macroexpand): See above.
+ (macarg1): See above.
+ (discard_comments): See above.
+ (change_newlines): See above.
+
+ * c-lex.c (mbchar.h): #include it.
+ (GET_ENVIRONMENT): New macro.
+ (init_lex): Set character set based on LANG environment variable.
+ (yylex): Handle multibyte characters in character literals.
+ (yylex): Handle multibyte characters in string literals.
+
+ * Makefile.in (mbchar.o): New target.
+ (cccp$(exeext)): @extra_cpp_objs@ is always available.
+ (cppmain$(exeext)): @extra_cpp_objs@ is always available.
+
+ * mbchar.[ch]: New files for multibyte character handling.
+
+Mon Jul 20 01:11:11 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * jump.c (jump_optimize): When simplifying noop moves and
+ PUSH_ROUNDING, fix thinko so we use same criterion for identifying
+ the PUSHes to rewrite in second loop as we did in the first.
+
+Sun Jul 19 08:23:53 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cplus-dem.c (demangle_nested_args): Make function definition
+ static to match the prototype.
+
+Fri Jul 17 14:58:44 1998 Richard Henderson <rth@cygnus.com>
+
+ * alloca.c: Respect USE_C_ALLOCA.
+ * gencheck.c (xmalloc): Ignore __GNUC__ for definition.
+ * gengenrtl.c (xmalloc): Likewise.
+
+Fri Jul 17 14:18:14 1998 Richard Henderson <rth@cygnus.com>
+
+ * loop.h (struct induction): Add no_const_addval.
+ * loop.c (the_movables, reg_address_cost): New variables.
+ (init_loop): Init reg_address_cost.
+ (loop_optimize): Call end_alias_analysis.
+ (scan_loop): Init the_movables.
+ (record_giv): Init induction->no_const_addval.
+ (basic_induction_var) [PLUS]: Use rtx_equal_p instead of ==.
+ [REG]: Rearrange loop search test to catch more cases.
+ (general_induction_var): Return success not benefit; take an extra
+ argument for that. Change all callers.
+ (simplify_giv_expr) [PLUS]: Always combine invariants. Use sge_plus.
+ [MULT]: Use rtx_equal_p instead of ==. Combine simple invariants.
+ [default]: Search the_movables for additional combinations.
+ (sge_plus_constant, sge_plus): New functions.
+ (express_from_1): New function.
+ (express_from): Always define. Rewrite using express_from_1.
+ (combine_givs_p): Handle more cases. Ignore address cost.
+ (cmp_combine_givs_stats): New function.
+ (combine_givs_used_once, combine_givs_benefit_from): New functions.
+ (combine_givs): Rewrite to do best-fit combination.
+
+ * fold-const.c (operand_equal_p): Handle RTL_EXPR.
+ (fold): Do a complete (A*C)+(B*C) association check.
+
+Fri Jul 17 11:21:55 1998 Jim Wilson <wilson@cygnus.com>
+
+ * function.c (fixup_var_refs_insns): Handle CLOBBER of a CONCAT.
+
+Fri Jul 17 11:48:55 1998 Jeffrey A Law (law@cygnus.com)
+
+ * mn10300.c (MODES_TIEABLE_P): Fix typo.
+
+Fri Jul 17 03:26:12 1998 Rihcard Earnshaw (rearnsha@arm.com)
+
+ * tree.c (valid_machine_attribute): Only create a new type variant if
+ there is a decl to use it.
+
+Thu Jul 16 14:48:04 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gcc.c (do_spec_1): Cope with %g/%u/%U options which do not have
+ a suffix.
+
+Fri Jul 17 03:24:40 1998 Hans-Peter Nilsson <hp@axis.se>
+
+ * extend.texi (Explicit Reg Vars): Typo: change "may deleted" into "may
+ be deleted"
+
+Thu Jul 16 14:48:47 1998 Jeffrey A Law (law@cygnus.com)
+
+ * mn10300.c (count_tst_insns): New arg oreg_countp. Callers changed.
+ Simplify tests for clearing an address register.
+ (expand_prologue): Corresponding changes.
+
+ * mn10300.md (movXX patterns): Make sure the destination is an
+ ADDRESS_REG when substituting "zero_areg" for (const_int 0).
+ (logical patterns): Split into expanders + patterns.
+ (zero and sign extension patterns): Similarly.
+ (shift patterns): Similarly.
+
+Thu Jul 16 01:17:44 1998 Richard Henderson <rth@cygnus.com>
+
+ * loop.c (emit_iv_add_mult): Scan the entire insn list generated
+ for the sequence, recording base values.
+
+Wed Jul 15 10:49:55 1998 Richard Henderson <rth@cygnus.com>
+
+ * i386.h (CPP_CPU_SPEC): Remove -Asystem(unix).
+
+Tue Jul 14 14:15:30 1998 Nick Clifton <nickc@cygnus.com>
+
+ * gcc.c: Remove ANSI-C ism from --help code.
+
+ * toplev.c: Support --help with USE_CPPLIB.
+
+Tue Jul 14 14:46:08 1998 Jeffrey A Law (law@cygnus.com)
+
+ * configure.in: Rework gas feature code to work with symlink based
+ source trees.
+
+ * extend.texi: Clarify some issues related to local variables
+ assigned to explicit registers.
+
+ * mn10300.md (mulsi): Turn into expander + pattern.
+
+ * mn10300.md (movsi, movsf, movdi, movdf): Remove "x" from I -> a
+ alternative.
+
+Tue Jul 14 07:41:59 1998 Richard Earnshaw (rearnsha@arm.com)
+
+ * arm/tcoff.h (USER_LABEL_PREFIX): Make it empty to match coff.h.
+
+Tue Jul 14 03:02:44 1998 Jeffrey A Law (law@cygnus.com)
+
+ * version.c: Bump again to distinguish mainline tree from the
+ egcs-1.1 branch.
+
+See ChangeLog.0 for earlier changes.
Local Variables:
add-log-time-format: current-time-string
diff --git a/contrib/gcc/FSFChangeLog b/contrib/gcc/FSFChangeLog
new file mode 100644
index 0000000..9a0e7f8
--- /dev/null
+++ b/contrib/gcc/FSFChangeLog
@@ -0,0 +1,2154 @@
+Wed Sep 30 14:27:49 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * function.c (assign_parms): Undo change of June 9.
+
+Tue Sep 29 09:57:26 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (get_inner_reference): Fix typo in last change.
+
+Mon Sep 27 21:34:00 1998 Paul Eggert <eggert@twinsun.com>
+
+ * po/en_UK.po (Project-Id-Version): Set to cc 2.8.1.19980813 for now.
+ (PO-Revision-Date): Set to the current date.
+
+Sun Sep 27 07:33:18 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * m68k/vxm68k.h (LINK_SPEC): Always use -r.
+ (WIDEST_HARDWARE_FP_SIZE): Define.
+
+ * reload.c (push_reload): If in STRICT_LOW_PART, always reload
+ inside even if SUBREG_WORD is not zero.
+
+ * flow.c (print_rtl_with_bb): Don't say not in basic block if we
+ aren't making basic blocks.8
+
+Sat Sep 26 10:57:09 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * function.c (optimize_bit_field): Don't remove SUBREG from dest
+ if SUBREG_REG is multi-word.
+
+Wed Sep 23 05:43:23 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload.c (find_reloads_address): Deal with address which is
+ an AND; clean up return values some more.
+
+Fri Sep 11 13:02:26 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * function.c (purge_addressof_1): Properly copy flags when making MEM.
+
+Mon Sep 7 18:33:06 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (get_inner_reference): If not COMPONENT_REF or BITFIELD_REF
+ and mode is BLKmode, set size_tree.
+
+ * expr.c (expand_builtin, case BUILT_IN_LONGJMP): Fix typo in
+ last change.
+
+Wed Sep 2 15:38:01 1998 Paul Eggert <eggert@twinsun.com>
+
+ * libgcc2.c (__floatdisf): Use signed comparison to test
+ whether u is close to zero; unsigned comparison is not what's
+ wanted here.
+
+Mon Aug 17 02:19:30 1998 David Edelsohn <edelsohn@mhpcc.edu>
+
+ * xcoffout.c (UNKNOWN_STAB): Fix typo in previous change; missing
+ backslash before newline.
+
+Mon Aug 17 00:12:42 1998 Paul Eggert <eggert@twinsun.com>
+
+ * reorg.c (check_annul_list_true_false): Fix typo in Jul 17 change.
+
+Sun Aug 2 01:10:15 1998 Paul Eggert <eggert@twinsun.com>
+
+ Add Native Language Support.
+
+ * intl/, ABOUT-NLS, mkinstalldirs, po/Makefile.in.in: New
+ subdirectory and files. They should be kept identical to the
+ corresponding items from the GNU gettext distribution.
+
+ * ABOUT-GCC-NLS, exgettext, intl.c, intl.h, po/POTFILES.in,
+ po/en_UK.po: New files.
+
+ * Makefile.in (AWK, datadir, localedir, top_builddir, USE_NLS,
+ INTLLIBS, POSUB, INTL_SUBDIRS, HOST_INTLLIBS,
+ PREPEND_DOTDOT_TO_RELATIVE_PATHS, SUBDIR_FLAGS_TO_PASS, GCC_OBJS,
+ COLLECT2_OBJS, CCCP_OBJS, CPPMAIN_OBJS, PROTO_OBJS, GCOV_OBJS,
+ INTL_DISTCLEAN, GEN_PROTOS_OBJS): New vars.
+ (LIBDEPS, LIBS): Add $(INTLLIBS).
+ (HOST_LIBDEPS, HOST_LIBS): Add $(HOST_INTLLIBS).
+ (LIBS): Add @LIBS@.
+ (ORDINARY_FLAGS_TO_PASS): New var, containing all the old values
+ from FLAGS_TO_PASS, except for CC.
+ (FLAGS_TO_PASS): Pass datadir, distdir, localedir.
+ (OBJS): Add intl.o.
+ (GEN): Add gencheck.
+ (STAGESTUFF): Add tree-check.h, gencheck$(exeext).
+ (native): Depend on intl.all.
+ (xgcc, collect2, cccp, cppmain, protoize, unprotoize, gcov): Link
+ intl.o.
+ (c-typeck.o, c-lex.o, collect2.o, gcc.o, toplev.o, integrate.o,
+ final.o, cccp.o, cppmain.o, cpplib.o, cpperror.o, s-proto,
+ gcov.o): Depend on intl.h.
+ (gencheck): Depend on $(HOST_LIBDEPS) instead of tree.h and
+ tree.def.
+ (gencheck.o, intl.o, $(top_builddir)/intl/libintl.a,
+ $(srcdir)/cp/parse.c, intl.all, intl.install, intl.uninstall,
+ intl.distdir, intl.mostlyclean, intl.clean, intl.distclean,
+ intl.maintainer-clean, intl.distdir-fixup, distdir-check): New
+ rules.
+ (gen-protos): Link cpperror.o, cppexp.o, cpphash.o, cpplib.o,
+ prefix.o, version.o; needed for `cpp_notice'.
+ (mostlyclean): Depend on intl.mostlyclean.
+ (clean): Depend on intl.clean.
+ (distclean): Depend on intl.disclean, unless the invoker defines
+ INTL_DISTCLEAN to be empty. Remove intl/libintl.h and libintl.h
+ (created by configure).
+ (maintainer-clean): Make intl.maintainer-clean, but define
+ INTL_DISTCLEAN to be empty.
+ (install-normal): Depend on intl.install.
+ (uninstall): Depend on intl.uninstall.
+ (distdir-start): Make sure invoker configured with --enable-nls.
+ Use $(AWK), not awk. Make tmp/intl and tmp/po directories.
+ (distdir-finish): Make distdir-check at the end.
+ (distdir): Depend on intl.distdir, intl.distdir-fixup.
+ (compare, compare3, gnucompare, gnucompare3, stage1-start,
+ stage2-start, stage3-start, stage4-start): Handle intl
+ subdirectory.
+
+ * acconfig.h (ENABLE_NLS, HAVE_CATGETS, HAVE_GETTEXT,
+ HAVE_LC_MESSAGES, HAVE_STPCPY, PACKAGE, VERSION): New macros.
+
+ * aclocal.m4 (AC_ISC_POSIX, AM_WITH_NLS, AM_GNU_GETTEXT,
+ AM_LC_MESSAGES, AM_PATH_PROG_WITH_TEST): New functions; taken from
+ gettext distribution.
+
+ * bi-arity.c, bi-opcode.c, bi-opname.c: Include config file first.
+
+ * c-common.c: Don't include <ctype.h>.
+ (tfaff): Now a function, not a string. All users changed.
+ (check_format_info): Use is_C_digit, not isdigit.
+ Reword messages to ease localization.
+
+ * c-decl.c (redeclaration_error_message): Now returns int, not
+ message.
+ (poplevel, duplicate_decls, pushdecl): Revamp to pass explicit
+ strings to diagnostic generators.
+ (duplicate_decls, parmlist_tags_warning, finish_struct): Reword
+ messages to ease localization.
+
+ * c-iterate.c (prdecl): Reword messages so that they do not require
+ localization.
+
+ * c-lex.c: Include limits.h if available.
+ Include intl.h.
+ Include ctype.h only if MAP_CHARACTER is defined.
+ (UCHAR_MAX): Define if limits.h doesn't.
+ (C_alnum_array): New var.
+ (init_lex): Initialize it.
+ (yyerror): Localize msgid arg.
+ (yylex): Use is_C_alnum and is_C_digit, not isalnum and isdigit.
+
+ * c-lex.h (C_alnum_array): New decl.
+ (is_C_alnum, is_C_digit): New macros.
+
+ * c-typeck.c: Include intl.h.
+ (warning_init): Now takes just one arg.
+ (incomplete_type_error, build_unary_op, lvalue_or_else,
+ readonly_warning, build_modify_expr): Reword messages to ease
+ localization.
+ (build_unary_op, readonly_warning): Revamp to pass explicit
+ strings to diagnostic generators.
+ (build_modify_expr, warn_for_assignment, c_expand_return):
+ Translate strings passed to functions expecting translated
+ strings.
+ (get_spelling): Remove; it was a no-op. All callers changed.
+ (error_init, pedwarn_init): Now takes just one arg. All callers
+ and decls changed. This makes it easier to localize.
+
+ * cccp.c: Include intl.h.
+ (char_name): Remove.
+ (check_macro_name): Now takes int 2nd arg, not char *. All
+ callers changed.
+ (macarg): Now returns int, not char *. All callers changed.
+ (notice, vnotice, pedwarn_strange_white_space): New functions.
+ (verror): Now extern; used by cexp.y.
+ (main): Set message locale, and defer memory allocation until
+ after.
+ (main, do_include, print_containing_files): Invoke `notice' to
+ localize notices.
+ (handle_directive): Invoke pedwarn_strange_white_space instead of
+ using char_name.
+ (do_include, check_macro_name): Reword messages to ease
+ localization.
+ (my_strerror): Reword message so that it does not require
+ localization.
+ (verror, vwarning, verror_with_line, vwarning_with_line,
+ pedwarn_with_file_and_line, fatal): Invoke vnotice to localize
+ msgid.
+ (initialize_char_syntax): No need to initialize char_name.
+
+ * cexp.y (yyerror): Now takes msgid format and args, not just string.
+ (verror): New decl.
+ (parse_number, yylex): Reword messages to ease
+ localization.
+ (verror): New test function.
+ (pedwarn, warning): Translate msgid arg.
+
+ * collect2.c: Include intl.h.
+ (my_strerror, main, collect_execute, scan_prog_file,
+ scan_libraries, read_file, end_file): Reword messages so that they
+ do not require localization.
+ (notice): Nwe function.
+ (fatal, error, main, collect_execute, maybe_unlink,
+ write_c_file_stat, locatelib, scan_libraries, scan_prog_file,
+ add_func_table): Use it to translate msgid strings.
+ (main): Set message locale, and defer memory allocation until
+ after.
+ (collect_wait): Reword messages to ease localization.
+ (bad_header): Revamp to pass explicit strings to diagnostic
+ generators.
+
+ * combine.c (dump_combine_stats, dump_combine_total_stats):
+ Use fnotice to translate diagnostic messages.
+
+ * config/1750a/1750a.c (memop_valid): Don't use `valid' as an
+ identifier; it runs afoul of SunOS 4.1.4 <locale.h>.
+
+ * config/arc/initfini.c (__do_global_dtors): Put backslash before
+ newline in strings, to pacify xgettext.
+
+ * config/dsp16xx/dsp16xx.c, config/dsp16xx/dsp16xx.h
+ (dsp16xx_invalid_register_for_compare): New function.
+ * config/dsp16xx/dsp16xx.md: Use it to report invalid registers.
+
+ * config/i370/i370.h: Include <ctype.h>.
+
+ * config/i386/i386.c: Include config.h first.
+
+ * config/m32r/initfini.c (__do_global_dtors): Put backslash before
+ newline in strings, to pacify xgettext.
+ * config/m88k/dguxbcs.h (CPP_SPEC): Likewise.
+
+ * config/rs6000/rs6000.c: Include config.h first.
+ * config/rs6000/rs6000.c, config/rs6000/rs6000.h
+ (rs6000_fatal_bad_address): New function.
+ * config/rs6000/rs6000.md: Use it to report bad addresses.
+
+ * config/v850/v850.c: Include config.h first.
+
+ * configure.in: When generating config.h and mentioning a file
+ taken from the config directory, surround it with #ifdef IN_GCC,
+ so that programs compiled without IN_GCC -- notably in the intl
+ subdirectory -- don't need to be compiled with -Iconfig.
+ (PACKAGE, VERSION, ALL_LINGUAS): New vars.
+ (AC_ARG_ENABLE): Add --enable-nls.
+ (AM_GNU_GETTEXT): Add. Override XGETTEXT so that we use exgettext
+ instead of xgettext to extract strings.
+ (all_outputs): Add intl/Makefile, po/Makefile.in.
+ Do not use the shell variable 'l'; it runs afoul of gettext's
+ aclocal mechanism!
+ If libintl.h is created, echo '#include "intl/libintl.h"'
+ >libintl.h so that we don't have to futz with our include paths.
+
+ * cp/Make-lang.in (g++.o): Depend on gansidecl.h, intl.h, Makefile;
+ do not depend on config.status.
+ (GXX_OBJS): New var.
+ (g++$(exeext)): Link intl.o.
+
+ * cp/Makefile.in (top_builddir, INTLLIBS): New vars.
+ (LIBS): Add $(INTLLIBS).
+
+ * cppalloc.c (memory_full): Use `cpp_notice' to print diagnostic.
+
+ * cpperror.c: Include intl.h.
+ (cpp_print_containing_files): Use cpp_notice to translate messages.
+ (cpp_message): is_error is -1 for notices. Translate "warning:".
+ (cpp_fatal): Translate msgid arg.
+
+ * cppexp.c (cpp_lex): Revamp to pass explicit strings to
+ diagnostic generators.
+ (cpp_parse_expr): Use cpp_error, not fprintf, to report
+ unimplemented operators.
+
+ * cpplib.c: Include intl.h.
+ (check_macro_name): Now takes int 2nd arg, not char *. All
+ callers changed.
+ (check_macro_name, do_define): Reword messages to ease
+ localization.
+ (do_define): Revamp to pass explicit strings to diagnostic
+ generators.
+ (do_define, cpp_start_read, cpp_handle_options): Use cpp_notice to
+ translate messages.
+ (cpp_error, cpp_warning, cpp_warning_with_line,
+ cpp_pedwarn_with_file_and_line): Translate msgid arg.
+ (cpp_notice): New function.
+ (my_strerror): Reword message so that it does not require
+ localization.
+
+ * cpplib.h (cpp_notice): New decl.
+
+ * cppmain.c: Include intl.h.
+ (main): Set message locale.
+
+ * cse.c (cse_main): Use fnotice to print diagnostic.
+
+ * final.c: Include intl.h; do not include ctype.h.
+ (output_operand_lossage): Translate msgid arg.
+
+ * fold-const.c (optimize_bit_field_compare, fold_truthop): Reword
+ messages to ease localization.
+
+ * gcc.c: Include intl.h.
+ (my_strerror, snapshot_warning): Reword messages so that they do
+ not require localization.
+ (init_spec, set_spec, read_specs, execute, do_spec_1, main,
+ snapshot_warning): Invoke `notice' to localize notices.
+ (struct switchstr): Don't use `valid' as an identifier; it runs
+ afoul of SunOS 4.1.4 <locale.h>. All uses changed.
+ (do_spec_1): Treat %e string as msgid format, which needs
+ translation.
+ (main): Set message locale.
+ (pfatal_with_name): Invoke perror_with_name, not fatal, so that we
+ don't have to translate "%s: %s".
+ (perror_with_name): Invoke printf, not error, so that we don't
+ have to translate "%s: %s".
+ (pfatal_pexecute): Invoke pfatal_with_name, not fatal, so that we
+ don't have to translate "%s: %s".
+ (fatal, error): Translate msgid arg.
+ (notice): New function.
+
+ * gcov.c: Include intl.h; include stdarg.h if __STDC__ is defined.
+ (main): Set message locale.
+ (fnotice): New function.
+ (xmalloc, fancy_abort, print_usage, open_files, read_files,
+ function_summary, output_data): Use it to to print diagnostics.
+
+ * install.texi: Explain new configure options --enable-nls,
+ --with-included-gettext, --with-catgets.
+
+ * integrate.c: Include intl.h.
+ (function_cannot_inline_p): Mark msgids with N_.
+
+ * invoke.texi: Describe environment variables affecting locale.
+
+ * pexecute.c: Include libintl.h if ENABLE_NLS, otherwise define
+ gettext to be a noop.
+ (_, N_): New macros.
+ (install_error_msg): Wrap inside N_.
+ (pexecute): Translate diagnostics.
+
+ * protoize.c: Include intl.h.
+ (__attribute__): New macro.
+ (notice): New function.
+ (my_strerror): Reword message so that it does not require
+ localization.
+ (xmalloc, xrealloc, fancy_abort, safe_write, usage,
+ file_normally_convertible, abspath, find_file, aux_info_corrupted,
+ save_def_or_dec, gen_aux_info_file, process_aux_info_file,
+ rename_c_file, find_extern_def, find_static_definition,
+ declare_source_confusing, edit_fn_declaration, edit_formals_lists,
+ add_local_decl, add_global_decls, edit_fn_definition,
+ scan_for_missed_items, edit_file, main): Use `notice' to print
+ diagnostic.
+ (main): Set message locale.
+
+ * real.c (NMSGS, ermsg): Remove.
+ (mtherr): Revamp to pass explicit strings to diagnostic
+ generators. Abort on invalid operations.
+
+ * regclass.c (fix_register): Reword messages to ease localization.
+
+ * toplev.c: Include intl.h; do not include ctype.h.
+ (v_really_sorry, really_sorry): Remove unused functions.
+ (count_error, fatal_io_error): Translate strings.
+ (default_print_error_function, report_error_function, main,
+ print_version): Reword messages to ease localization. Use
+ `notice' to translate diagnostics.
+ (vnotice, notice, fnotice): New functions.
+ (vmessage): Remove.
+ (v_message_with_file_and_line, vsorry): Translate msgid with
+ vnotice.
+ (v_message_with_file_and_line, v_message_with_decl): Use
+ report_file_and_line. Now takes int warning flag, not prefix;
+ this is easier to localize. All callers changed.
+ (v_message_with_decl): Abort if first format spec is neither %%
+ nor %s. Translate "((anonymous))".
+ (main): Set message locale.
+ (set_target_switch): Don't use `valid' as an identifier; it runs
+ afoul of SunOS 4.1.4 <locale.h>.
+ (__VERSION__): Reword message so that it does not require
+ localization.
+ (print_switch_values): Translate "options passed" and "options
+ enabled".
+
+ * tree.c (valid_machine_attribute): Don't use `valid' as an
+ identifier; it runs afoul of SunOS 4.1.4 <locale.h>.
+
+ * xcoffout.c (xcoff_output_standard_types): Use `error' to
+ output diagnostic, so that it gets translated.
+
+ * patch-apollo-includes: Remove; this is part of README.APOLLO.
+
+Mon Jul 27 18:28:58 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload.c (find_reloads): If no_input_reloads, abort if
+ reloads were made for addresses.
+ * m68k.md (sxx): Operand 0 cannot be memory.
+
+Fri Jul 17 07:31:04 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k.c (output_move_simode_const): Use subl to move 0 into addr reg.
+ (output_move_[hq]imode): Likewise.
+
+ * m68k.md (extend[sd]fxf2): Accept constants and general reg as
+ source operand if the destination is a floating point register.
+
+Fri Jul 17 07:23:49 1998 Herman ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * reorg.c (check_annul_list_true_false): New function.
+ (steal_delay_list_from_{target,fallthrough}): Call it and also
+ refine tests for when we may annul if already filled a slot.
+ (fill_slots_from_thread): Likewise.
+ (delete_from_delay_slot): Return newly-created thread.
+ (try_merge_delay_isns): Use its new return value.
+
+Sat Jul 4 11:07:33 1998 Eberhard Mattes <mattes@azu.informatik.uni-stuttgart.de>
+
+ * function.c (assign_parms): Handle PARALLEL which include stack.
+
+Sat Jul 4 09:44:29 1998 Paul Edwards <avon@matra.com.au>
+
+ * tree.c, print-tree.c, c-lang.c: Include stdio.h before tree.h.
+ * expr.c (bc_expand_component_address): Correct args to
+ bc_push_offset_and_size.
+ * reload1.c (reload_cse_simplify_operands): Add missing return value.
+
+Fri Jul 3 07:17:19 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * alpha.c (normal_memory_operand): Handle case when REG will be
+ eliminated by reload.
+
+Thu Jul 2 18:43:53 1998 James Carlson <carlson@ironbridgenetworks.com>
+
+ * floatlib.c (HIDDEND_LL, MANTD_LL, PACKD_LL): New macros.
+ (__addsf3): Fixed cases returning wrong type and causing unintended
+ conversions and data corruption.
+ (__mulsf3): Fixed rounding flaws caused wrong scaling.
+ (__float{didf,sisf,disf},__fix{,uns}dfdi): New functions.
+ (__{gt,ge,lt,le,eq,ne}df2): Likewise.
+ (__truncdfsf2): Fixed normalization problems
+ (__fixunsdfsi): Fixed compiler warning
+ (__{add,sub,mul}df3): Rewrite to do real DP math.
+ (__divdf3): Removed previous version by Barrett Richardson.
+
+Thu Jul 2 17:57:20 1998 Douglas B. Rupp <rupp@gnat.com>
+
+ * cpperror.c: Include errno.h.
+
+Thu Jul 2 16:46:36 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * c-decl.c (grokdeclarator): Don't warn about implicit int in
+ `typedef foo = bar'.
+
+Tue Jun 30 18:32:49 1998 Geert Bosch <bosch@gnat.com>
+
+ * alpha/vxworks.h (LINK_SPEC): Add -taso -T 0.
+
+Tue Jun 30 09:39:32 1998 David Edelsohn <edelsohn@mhpcc.edu>
+
+ * expr.c (expand_builtin_{set,long}jmp): If STACK_SAVEAREA_MODE
+ defined, override sa_mode using its value.
+ * explow.c (emit_stack_save): Likewise.
+
+ * rs6000/aix41.h (ASM_CPU_SPEC): Define relative to ASM_DEFAULT_SPEC.
+ (CPP_CPU_SPEC): Define relative to CPU_DEFAULT_SPEC.
+ * rs6000.c (processor_target_table, 620): Don't affect MASK_POWERPC64.
+ (rs6000_override_options): Ignore flag_pic for AIX.
+ (rs6000_immed_double_const): Delete.
+ ({reg_or_u_short,u_short_cint}_operand): Don't assume 32-bit CONST_INT.
+ ({non_logical_cint,logical}_operand): Likewise.
+ (num_insns_constant): mask64_operand is 2 insns.
+ (easy_fp_constant): Any CONST_DOUBLE_HIGH is okay for 64-bit.
+ (mask_constant): HOST_WIDE_INT parameter.
+ (non_and_cint_operand): Delete.
+ ({mask,and}64_operand): New functions.
+ (function_arg{,_advance}): DImode arguments don't need special
+ alignment when 64-bit.
+ (setup_incoming_varargs): Reverse reg_size assignment.
+ (print_operand): HOST_WIDE_INT second parameter.
+ (print_operand, case 'B', 'S'): New cases.
+ (print_operand, case 'M'): Fix typo in lossage string.
+ (rs6000_stack_info): Reverse reg_size assignment. Use total_raw_size
+ to compute AIX push_p. Use reg_size to compute {cr,lr}_save_offset.
+ (rs6000_output_load_toc_table): Reverse init_ptr assignment. Use
+ TARGET_64BIT not TARGET_POWERPC64. Convert fprintf to fputs.
+ Load GOT highpart, don't add it. Add lowpart with {cal|la}.
+ (rs6000_allocate_stack_space): Use {cal|la}.
+ (output_epilog): Use {cal|la}
+ (output_function_profiler): Add call glue to mcount call.
+ Load GOT highpart, don't add it. Add lowpart with {cal|la}.
+ Use asm_fprintf and convert fprintf to fputs.
+
+ * rs6000.h (TARGET_SWITCHES): Add powerpc64.
+ (STACK_BOUNDARY): Depend on TARGET_32BIT.
+ (ADJUST_FIELD_ALIGN): Calculate array alignment using innermost type.
+ (CONST_OK_FOR_LETTER_P): Don't assume 32-bit CONST_INT.
+ (EXTRA_CONSTRAINTS): Remove 'S' and 'T'. Replace 'S' with
+ 64-bit mask operand.
+ (RS6000_SAVE_TOC): Depend on TARGET_32BIT.
+ (STACK_SAVEAREA_MODE): New macro.
+ (LEGITIMATE_CONSTANT_P): DImode okay for 64bit.
+ (RTX_COSTS, AND/IOR/XOR): Reflect current machine description.
+ (ASM_FILE_START): Emit 64-bit ABI directive.
+ (ASM_DECLARE_FUNCTION_NAME): Align CSECT on doubleword in 64-bit mode.
+ (ASM_OUTPUT_SPECIAL_POOL_ENTRY): DImode okay for 64-bit.
+ (PREDICATE_CODES): Add "and64_operand" and "mask64_operand".
+ Delete "non_and_cint_operand". "input_operand" includes CONST_DOUBLE.
+
+ * rs6000.md (iorsi3, xorsi3): Use HOST_WIDE_INT for mask.
+ Restore define_split.
+ (floatsidf2, floatunssidf2): Remove !TARGET_POWERPC64 final constraint.
+ (floatsidf2_internal, floatunssidf2_internal2): Likewise.
+ Do not specify base register operand mode.
+ (floatsidf2_loadaddr): Don't specify base register operand mode.
+ (floatsidf2_store1, floatsidf2_store2): Operand 1 must be base
+ register; do not specify mode. Remove !TARGET_POWERPC64 final
+ constraint.
+ (floatsidf2_load): Don't specify base register operand mode.
+ Remove !TARGET_POWERPC64 final constraint.
+ (fix_truncdfsi2_internal, fix_truncdfsi2_{store,load}): Don't specify
+ base register operand mode.
+ (mulsidi3): Add !TARGET_POWERPC64 constraint.
+ (adddi3): Split large constants early.
+ (absdi3): Shift by 63, not 31.
+ (rotldi3): Add masking combiner patterns.
+ (anddi3): Add rldic{r,l} masking. Remove split of large constants.
+ (iordi3, xordi3): Split large constants early.
+ (movsi matcher): Remove S and T constraints.
+ (movsf const_double): create SImode constant from TARGET_DOUBLE.
+ (movdf_hardfloat32): Add default abort case.
+ (movdf easy_fp_const): create DImode constant from TARGET_DOUBLE.
+ (movdi): Remove 64-bit constant generator. Try to convert
+ CONST_DOUBLE to CONST_INT. Handle TOC memory constants.
+ (movdi_32): Add default abort case.
+ (movdi_64): Add numerous ways to split 64-bit constants.
+ Make catch-all define_split more optimal and never FAIL.
+ (movti_ppc64): Add default abort case.
+ (allocate_stack): Remove operand modes; use Pmode.
+ (restore_stack_block): Remove operand modes. Generate Pmode
+ temporary. Generate MEM and specify mode.
+ (save_stack_nonlocal, restore_stack_nonlocal): Generate Pmode
+ temporary. Save area is double Pmode.
+ (call_indirect_aix64, call_value_indirect_aix64): New patterns.
+ (call, call_value): Do not specify address operand mode. Choose
+ appropriate AIX ABI.
+ (*call_local64, *ret_call_local64): New patterns.
+ (*call_nonlocal_aix64, *ret_call_nonlocal_aix64): New patterns.
+ (*ret_call_nonlocal_aix32): Use call_value_indirect for REG.
+ (compare): Materialize DImode truthvalues.
+
+Tue Jun 30 06:31:40 1998 Richard Henderson <rth@dot.cygnus.com>
+
+ * alpha.h (PRINT_OPERAND_PUNCT_VALID_P): Add '`'.
+ * alpha.c (print_operand): Handle it.
+ * alpha.md (fix_truncdfsi2, fix_truncsfsi2): New patterns and
+ related define_splits.
+
+Tue Jun 30 06:02:07 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * calls.c (emit_library_call{,_value}): Pass null
+ to REG_PARM_STACK_SPACE.
+
+ * alpha.c (normal_memory_operand): New function.
+ * alpha.h (EXTRA_CONSTRAINT, case 'Q'): Call it.
+
+ * fold-const.c (count_cond): New function.
+ (fold): Don't try to build COND_EXPR from binary op when both sides
+ are COND_EXPR unless not nested too deeply.
+
+Thu Jun 25 09:54:55 1998 Nick Clifton <nickc@cygnus.com>
+
+ * arm.h (REG_ALLOC_ORDER): Add ARG_POINTER_REGNUM, noticed by
+ grahams@rcp.co.uk.
+
+Mon Jun 15 17:41:33 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload1.c (reload): Issue guidance message on stack frame too large
+ for reliable stack check.
+
+ * fold-const.c (fold_range_test): Prevent falling through with no ret.
+
+Sat Jun 13 15:49:53 1998 Carol LePage <carolo@kemah.hal.com>
+
+ * configure.in (sparc-hal-solaris2*): New target.
+ * sparc/hal.h, sparc/t-halos: New files.
+
+Sat Jun 13 14:30:25 1998 David W. Schuler <schuld@btv.ibm.com>
+
+ * i386/aix386ng.h (CPP_SPEC): Remove bogus quote.
+
+Sat Jun 13 14:16:34 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * regmove.c (try_auto_increment): Fix typo.
+
+ * c-common.c (truthvalue_conversion): Protect side effects in the
+ expression when splitting a complex value.
+ * fold-const.c (fold): Likewise.
+
+ * expr.c (do_jump, case EQ_EXPR, NE_EXPR): When comparing complex
+ prevent operands from being evaluated twice.
+
+Sat Jun 13 12:53:22 1998 Richard Earnshaw (rearnsha@arm.com)
+
+ * unroll.c (verify_addresses): Use validate_replace_rtx to undo
+ changes; abort if undo fails.
+
+Sat Jun 13 11:46:38 1998 Anders Blomdell <anders.blomdell@control.lth.se>
+
+ * flags.h (flag_volatile_static): Declare.
+ * toplev.c (flag_volatile_static): Define.
+ (f_options): Include -fvolatile-static.
+ * varasm.c (make_decl_rtl): Support -fvolatile-static.
+
+Sat Jun 13 08:26:21 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload1.c (reload_cse_regno_equal_p): If -ffloat-store, don't
+ consider a MEM in FP mode as equal.
+
+ * varasm.c (assemble_variable): Never put decl with specified section
+ name into bss.
+
+ * output.h (current_function_addresses_labels): Declare.
+ * function.h (struct function): New field `addresses_labels'.
+ * function.c (current_function_addresses_labels): Define.
+ ({push,pop}_function_context): Save/restore it.
+ (init_function_start): Initialize it.
+ * rtl.h (FUNCTION_FLAGS_ADDRESSES_LABELS): New flag.
+ * expr.c (expand_expr, case LABEL_DECL): Show addresses labels.
+ * integrate.c (function_cannot_inline_p): Can't if addresses labels.
+ (initialize_for_inline): Save current_function_addresses_labels.
+ (output_inline_function): Restore it.
+
+ * reload.c (find_reloads, case 'o'): All reloaded addresses
+ are offsettable.
+ (find_reloads_address): If replacing address, don't return 1.
+
+ * profile.c (output_func_start_profiler): Add missing steps in
+ defining function.
+
+Fri Jun 12 17:10:16 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * m68k.md (extendqidi2): Operand 1 must be in data register.
+
+Tue Jun 9 07:24:01 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * cccp.c (handle_directive): If -dM, also include #undef.
+ * cpplib.c (handle_directive): Likewise.
+
+ * calls.c (expand_call): Allow function pointer to be a REFERENCE_TYPE.
+
+ * function.c (assign_parms): Use proper mode for location of arg
+ on stack when promotions are occurring.
+
+ * regmove.c ({next,prev}_insn_for_regmove): Properly handle end of
+ function.
+
+Mon Jun 8 15:26:49 1998 Juha Sarlin <juha@c3l.tyreso.se>
+
+ * h8300.c (get_shift_alg): Add special cases for shifts of 8 and 24.
+
+Mon Jun 8 14:40:02 1998 John Wehle (john@feith.com)
+
+ * i386.md (movsf_push, movsf_mem): Remove.
+ (movsf_push): Rename from movsf_push_nomove and move in front of
+ movsf; allow memory operands during and after reload.
+ (movsf_push_memory): New pattern.
+ (movsf): Don't bother checking for push_operand. If TARGET_MOVE and
+ both operands refer to memory then force operand[1] into a register.
+ (movsf_normal): Change to unnamed pattern.
+ Likewise for movdf, movxf, and friends.
+
+Mon Jun 8 13:18:04 1998 Martin v. Loewis <loewis@informatik.hu-berlin.de>
+
+ * Makefile.in (TREE_H): Add tree-check.h.
+ (tree-check.h, s-check, gencheck): New targets.
+ (STAGESTUFF): Add s-check.
+ * gencheck.c: New file.
+ * tree.c (tree_check, tree_class_check, expr_check): New functions.
+ * tree.h (TREE_CHECK, TREE_CLASS_CHECK): Define.
+ (TYPE_CHECK, DECL_CHECK): Define.
+ Modify all access macros to use generated checking macros.
+ * acconfig.h (ENABLE_CHECKING): Undefine.
+ * configure.in (--enable-checking): New option.
+
+Mon Jun 8 12:13:25 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.ed>
+
+ * regmove.c: Remove include for varargs or stdarg.
+
+Mon Jun 8 07:49:41 1998 Andris Pavenis <pavenis@lanet.lv>
+
+ * gcc.c (link_command_spec): Support LINK_COMMAND_SPEC.
+
+Sun Jun 7 18:00:28 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * fold-const.c (fold, case EQ_EXPR): When folding VAR++ == CONST
+ or VAR-- == CONST construct a proper mask if VAR is a bitfield.
+ Cope with CONST being out of range for the bitfield.
+
+Sun Jun 7 17:19:35 1998 Tom Quiggle <quiggle@sgi.com>
+
+ * mips/iris6.h (DWARF2_FRAME_INFO): Define.
+ * dwarf2out.c (dwarf2out_do_frame): Do something if DWARF2_FRAME_INFO.
+
+Sun Jun 7 15:29:04 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * regmove.c: New file.
+ * Makefile.in (OBJS): Add regmove.o.
+ (regmove.o): New rules.
+ (mostlyclean): Remove regmove dumps.
+ * toplev.c (regmove_{dump,dump_file,time}, flag_regmove): New vars.
+ (f_options): Add -foptimize-register-move.
+ (compile_file): Run regmove pass after combine pass and do its dump.
+ (main): Enable regmove dump when -dN or -da.
+ (fatal_insn): Flush regmove dump file.
+ * flags.h (flag_regmove): Declare.
+ * flow.c (find_use_as_address): Export.
+ * rtl.h (find_use_as_address): Declare.
+ * local-alloc.c (optimize_reg_copy_{1,2}): Removed, all calls deleted.
+ * reload1.c (count_occurrences): Export.
+ * reload.h (count_occurrences): Declare.
+
+Sun Jun 7 09:30:31 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Makefile.in (uninstall): Uninstall gcov.
+
+ * alpha.h (ASM_COMMENT_START): Define.
+
+ * alpha.h (EXTRA_CONSTRAINT, case 'S'): New case.
+ * alpha.md ({ashl,ashr,lshr}di3): Use 'S' for constraint.
+
+ * i386.md (cmpxf): Add missing extend pattern from SFmode and fix
+ operand numbers in one extend pattern from DFmode.
+
+ * pa.md ({pre,post}_{ld,st}wm and similar): When operand is being
+ incremented, use '+', not '=', for constraint.
+
+ * reload.c (find_reloads): Give preference to pseudo that was the
+ reloaded output of previous insn.
+
+ * emit-rtl.c (init_emit_once): Provide default for DOUBLE_TYPE_SIZE.
+
+ * expr.c (init_expr_once): Free all RTL we generate here.
+ * expmed.c (init_expmed): Allocate all RTX in memory we'll free.
+
+ * genemit.c (main): Generate #include "reload.h".
+
+ * expr.c (expand_expr, case INDIRECT_EXPR): A dereference of
+ a REFERENCE_TYPE is always considered in a structure. Likewise for
+ a dereference of a NOP_EXPR whose input is a pointer to aggregate.
+
+Sat Jun 6 17:25:14 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * mips.md (reload_{in,out}di): Allow other operand to be invalid
+ MEM and get any reload replacement before using address.
+
+Tue May 26 18:52:23 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload1.c (reload): Get MEM_IN_STRUCT_P and RTX_UNCHANGING_P
+ from reg_equiv_memory_loc; set the latter when changing REG to MEM.
+ (alter_reg): Don't set RTX_UNCHANGING_P for shared slots.
+
+Mon May 25 12:07:12 1998 Hans-Peter Nilsson <hp@axis.se>
+
+ * cplus-dem.c (MBUF_SIZE): Bumped from 512 to 32767.
+
+Sun May 24 21:50:12 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * i386/linux{,-aout,oldld}.h (ASM_COMMENT_START): Define.
+
+Sun May 24 11:58:37 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k.md (adddi3, subdi3): Properly negate the DImode constant.
+
+Sun May 24 11:30:08 1998 Torbjorn Granlund <tege@matematik.su.se>
+
+ * m68k/lb1sf68.asm (__addsf3): Fix typo in exg on coldfire.
+
+Sun May 24 09:38:17 1998 John Wehle (john@feith.com)
+
+ * i386.md (movsi): Remove redundant integer push patterns.
+ Don't check for TARGET_PUSH_MEMORY when pushing constants or registers.
+
+Sun May 24 08:59:27 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * fold-const.c (fold, case EQ_EXPR): Split COMPLEX_TYPE operands
+ if either is COMPLEX_CST in addition to COMPLEX_EXPR.
+
+ * expr.c (do_jump, case EQ_EXPR, case NE_EXPR): Check for COMPLEX
+ before testing for operand 1 being zero.
+
+ * genattrtab.c (optimize): Define.
+
+ * configure.lang: Fix substitution of target_alias.
+
+Sat May 23 22:31:17 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * emit_rtl.c (double_mode): New variable.
+ (init_emit_once): Set and use it.
+ * real.c (ereal_atof, real_value_truncate): Handle double_mode not
+ being DFmode for C4x.
+
+Sat May 23 22:19:55 1998 Mike Stump <mrs@wrs.com>
+
+ * expr.c (expand_builtin_setjmp): Handle BUILTIN_SETJMP_FRAME_VALUE.
+ * i960.h (SETUP_FRAME_ADDRESSES, BUILTIN_SETJMP_FRAME_VALUE): Define.
+ * i960.md (ret, flush_register_windows): Define.
+ (nonlocal_goto): Likewise. Nested function nonlocal gotos don't
+ work yet.
+
+Sat May 23 18:45:59 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k/t-linux: Remove stuff already included in config/t-linux.
+
+Sat May 23 18:35:07 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * final.c: Select <stab.h> and "gstab.h" with NO_STAB_H.
+
+ * gcc.c (default_compilers): Remove ".ada" extension.
+
+ * combine.c (rtx_equal_for_field_assignment): Remove code that
+ checks get_last_value.
+
+ * Makefile.in (uninstall): Delete info files.
+
+Sat May 23 18:28:27 1998 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * c-decl.c (start_decl): Use new macro SET_DEFAULT_DECL_ATTRIBUTES.
+ * c-lex.c (check_newline): Put last read character back on input
+ stream.
+
+Sat May 23 18:13:53 1998 David Edelsohn <edelsohn@mhpcc.edu>
+
+ * rs6000.md (floatsidf2_loadaddr): rs6000_fpmem_offset will be
+ negative in a stackless frame.
+ * rs6000.c (rs6000_stack_info): Don't include fixed-size link area
+ in stackless frame size. Support 64-bit stackless frame size.
+ Combine fpmem offset calculations and don't add total_size to
+ offset if not pushing a stack frame.
+
+ * tree.c (get_inner_array_type): New function.
+ * tree.h (get_inner_array_type): Likewise.
+
+Wed May 20 15:42:22 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expmed.c (expand_divmod): Save last divison constant and
+ if rem is same as div, don't adjust rem cost.
+
+Thu May 14 14:11:37 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * alpha/vxworks.h: New file.
+ * configure.in (alpha*-*-vxworks*): New target.
+
+ * alpha.c (tree.h): Include earlier.
+ (alpha_initialize_trampoline): New function.
+ * alpha.h (INITIALIZE_TRAMPOLINE): Call it.
+ * alpha/linux.h (INITIALIZE_TRAMPOLINE): Don't redefine.
+
+Thu May 14 13:35:53 1998 Cyrille Comar <comar@gnat.com>
+
+ * Makefile.in (STAGESTUFF): Add s-under.
+
+Wed May 13 17:38:35 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * combine.c (simplify_comparison, case AND): Don't commute AND
+ with SUBREG if constant is whole mode and don't do if lowpart
+ and not WORD_REGISTER_OPERATIONS.
+
+ * expmed.c (expand_mult): Use 0 as add_target if should preserve
+ subexpressions.
+
+Mon May 11 17:26:06 1998 Paul Eggert <eggert@twinsun.com>
+
+ * dwarf2out.c: Undo most recent change.
+
+Sun May 10 17:09:20 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * fold-const.c (fold_range_test, fold): If need to make SAVE_EXPR
+ to do optimization, suppress if contains_placeholder_p.
+
+Thu May 7 18:14:31 Paul Eggert <eggert@twinsun.com>
+
+ * dwarf2out.c: Don't assume `.section ".text"' causes assembler to
+ treat .text as label for start of section; instead, output
+ `.section ".text"; .LLtext0:' and use .LLtext0 in label contexts.
+ (ABBREV_LABEL, DEBUG_INFO_LABEL, DEBUG_LINE_LABEL, TEXT_LABEL): New.
+ (abbrev_label, debug_info_label, debug_line_label, text_label): New.
+ (dwarf2out_init): Initialize the vars. Output defn for text_label.
+ (dwarf2out_finish): Output defns for the other 3 vars.
+ (dw_val_node): Rename val_section to val_section_label, as it's
+ now a label, not a section.
+ (add_AT_section_offset): Arg is now a label, not a section.
+ (print_die): In label contexts, output section label, not section.
+ (output_die, output_compilation_unit_header): Likewise.
+ (output_{pubnames,aranges,line_info}, dwarf2out_finish): Likewise.
+
+ * fixinc.wrap: Renamed from fixinc.math. Put wrapper around
+ curses.h if it contains `typedef char bool;'.
+
+ * configure.in (arm-*-netbsd*): Rename fixinc.math to fixinc.wrap.
+ (i[34567]86-*-freebsdelf*, i[34567]86-*-freebsd*): Likewise.
+ (i[34567]86-*-netbsd*, i[34567]86-*-solaris2*): Likewise.
+ (m68k-*-netbsd*, mips-dec-netbsd*, ns32k-pc532-netbsd*): Likewise.
+ (powerpcle-*-solaris2*, sparc-*-netbsd*, sparc-*-solaris2*): Likewise.
+ (vax-*-netbsd*): Likewie.
+
+Wed May 6 06:44:28 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * combine.c (simplify_rtx, case TRUNCATE): Reflect that it sign-extends
+ instead of zero-extending.
+
+Sat May 2 20:39:22 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * fold-const.c (fold): When commutting COND_EXPR and binary operation,
+ avoid quadratic behavior if have nested COND_EXPRs.
+
+Tue Apr 28 17:30:05 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * mips.h (HOST_WIDE_INT): Define if not already.
+ (compute_frame_size, mips_debugger_offset): Return HOST_WIDE_INT.
+ (DEBUGGER_{AUTO,ARG}_OFFSET): Cast second arg to HOST_WIDE_INT.
+ * mips.c (mips_debugger_offset): Now returns HOST_WIDE_INT.
+ Likewise for internal variable frame_size.
+
+ * final.c (alter_subreg): Make new SUBREG if reload replacement
+ scheduled inside it.
+
+ * dwarf2out.c (add_bound_info, case SAVE_EXPR): Pass
+ SAVE_EXPR_RTL address through fix_lexical_addr.
+
+Mon Apr 27 18:57:18 1998 Jim Wilson <wilson@cygnus.com>
+
+ * mips/sni-svr4.h (CPP_PREDEFINES): Add -Dsinix and -DSNI.
+
+Mon Apr 20 14:48:29 1998 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000.md (mov{sf,df} define_splits): When splitting move of
+ constant to int reg, don't split insns that do simple AND and OR
+ operations; just split each word and let normal movsi define split
+ handle it further.
+
+Sun Apr 19 20:21:19 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * real.h (C4X_FLOAT_FORMAT): New macro.
+ * real.c (c4xtoe, etoc4x, toc4x): New functions.
+
+Sun Apr 19 20:17:32 1998 Niklas Hallqvist <niklas@petra.appli.se>
+
+ * m68k.c (notice_update_cc): Use modified_in_p to check for update.
+
+Sun Apr 19 18:48:07 1998 K. Richard Pixley <rich@kyoto.noir.com>
+
+ * fixincludes: Discard empty C++ comments.
+ Special case more files with C++ comments nested in C comments.
+
+Sun Apr 19 18:30:11 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k.md ({add,sub}di3): Optimize for constant operand.
+
+Sun Apr 19 18:27:11 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * i386.c (output_387_binary_op): Swap operands when popping if result
+ is st(0).
+
+Sun Apr 19 17:58:01 1998 Peter Jeremy <peter.jeremy@alcatel.com.au>
+
+ * expr.c (do_jump_by_parts_equality_rtx): Now public.
+ * expmed.c (do_cmp_and_jump): New function.
+ (expand_divmod): Use do_cmp_and_jmp instead of emit_cmp_insn and
+ emit_jump_insn.
+
+Sun Apr 19 07:48:37 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * c-typeck.c (build_c_cast): Check underlying type when seeing
+ if discarding const or volatile.
+
+ * c-decl.c (pushdecl): Avoid duplicate warning about implicit redecl.
+
+ * configure.in (stab.h): Check for it.
+ (i386-*-vsta): Include xm-i386.h too.
+ * dbxout.c (stab.h): Include based on autoconf results.
+ * vax/xm-vms.h (NO_STAB_H): Deleted.
+ * alpha/xm-vms.h, xm-mips.h, i386/xm-mingw32.h, i386/go32.h: Likewise.
+ * i386/xm-cygwin32.h: Likewise.
+ * i386/xm-vsta.h (NO_STAB_H): Likewise.
+ (i386/xm-i386.h): No longer include.
+
+ * mips.c: Cleanups and reformatting throughout.
+ ({expand,output}_block_move): Use HOST_WIDE_INT for sizes.
+ (mips_debugger_offset, compute_frame_size): Likewise.
+ (save_restore_insns, mips_expand_{pro,epi}logue): Likewise.
+ (siginfo): Deleted.
+ (override_options): Don't set up to call it; don't call setvbuf.
+
+Mon Apr 13 06:40:17 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * configure.in (sparc-*-vxsim*): Include xm-siglist.h and
+ define USG and POSIX.
+
+Sun Apr 12 21:59:27 1998 Jeffrey A. Law <law@cygnus.com>
+
+ * calls.c (expand_call): Fix typo in STRICT_ARGUMENT_NAMING.
+
+Sun Apr 12 21:42:23 1998 D. Karthikeyan <karthik@cdotd.ernet.in>
+
+ * m68k.h (TARGET_SWITCHES): Add missing comma.
+
+Sun Apr 12 21:33:33 1998 Eric Valette <valette@crf.canon.fr>
+
+ * configure.in (i[34567]86-*-rtemself*): New configuration.
+ * i386/rtemself.h: New file.
+
+Sun Apr 12 21:08:28 1998 Jim Wilson <wilson@cygnus.com>
+
+ * loop.c (loop_optimize): Reset max_uid_for_loop after
+ find_and_verify_loops call.
+ (strength_reduce): In auto_inc_opt code, verify v->insn has valid
+ INSN_LUID.
+
+Sun Apr 12 20:54:59 1998 Richard Earnshaw (rearnsha@arm.com)
+
+ * configure.in (sparc-*-solaris2*): Add xm-siglist.h to xm_file.
+ Add USG and POSIX to xm_defines.
+
+Sun Apr 12 20:47:37 1998 Pat Rankin <rankin@eql.caltech.edu>
+
+ * cccp.c (eprint_string): New function.
+ (do_elif, do_else, verror): Use it instead of fwrite(,,,stderr).
+ (error_from_errno, vwarning): Likewise.
+ ({verror,vwarning,pedwarn}_with_line): Likewise.
+ (pedwarn_with_file_and_line, print_containing_files): Likewise.
+
+Sun Apr 12 20:40:44 1998 Richard Henderson <rth@dot.cygnus.com>
+
+ * configure.in (alpha*-*-linux-gnu*): Add alpha/t-crtbe.
+ Add crt{begin,end}.o in extra_parts and delete crt{begin,end}S.o.o
+ * alpha/t-crtbe, alpha/crt{begin,end}.asm: New files.
+
+ * alpha.h (PRINT_OPERAND_PUNCT_VALID_P): Accept '(' for s/sv/svi.
+ * alpha.c (print_operand): Handle it.
+ * alpha.md (fix_trunc[ds]fdi2): Use it. Add earlyclobber pattern
+ for ALPHA_TP_INSN.
+
+Sun Apr 12 13:09:46 1998 Scott Christley <scottc@net-community.com>
+
+ * objc/encoding.c (objc_sizeof_type, _C_VOID): New case.
+
+Sun Apr 12 13:04:55 1998 Nikolay Yatsenko (nikolay@osf.org)
+
+ * configure.in (i[34567]86-*-osf1*): New entry.
+ * i386/osf1-c[in].asm: New files for OSF/1.
+ * i386/osf1elf{,gdb}.h, i386/[xt]-osf1elf, i386/xm-osf1elf.h: Likewise.
+
+Sun Apr 12 10:03:51 1998 Noel Cragg <noel@red-bean.com>
+
+ * fixincludes: Remove specification of parameters when renaming
+ functions in Alpha DEC Unix include files.
+
+Sun Apr 12 07:33:46 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * mips.c (large_int): Use HOST_WIDE_INT, not int.
+ (print_operand): Use HOST_WIDE_INT_PRINT_* macros.
+
+ * toplev.c (main): Sort order of handling of -d letters.
+ Use `F' instead of `D' for addressof_dump.
+
+ * libgcc2.c (_eh_compat): Deleted.
+ * Makefile.in (LIB2FUNCS): Delete _eh_compat.
+
+ * configure.in (alpha*-*-linux-gnu*): Don't include alpha/xm-linux.h.
+
+ * c-common.c (check_format_info): Properly test for nested pointers.
+
+ * pa.md (casesi0): Add missing mode for operand 0.
+
+ * function.c (purge_addressof_1, case MEM): If BLKmode, put ADDRESSOF
+ into stack.
+
+ * c-parse.in (label): Give warning if pedantic and label not integral.
+
+ * c-decl.c (grokdeclarator): Don't warn about return type if in
+ system header.
+
+ * reload.c (reload_nongroup): New variable.
+ (push{_secondary,}_reload): Initialize it.
+ (find_reloads): Compute it.
+ (debug_reload): Print it.
+ * reload.h (reload_nongroup): Declare.
+ * reload1.c (reload): Use reload_nongroup instead of local computation.
+ Check caller_save_spill_class against any nongroup reloads.
+ (reloads_conflict): No longer static.
+
+Sun Apr 12 05:52:18 1998 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * vax.md (call patterns): Operand 1 is always a CONST_INT.
+
+Sat Apr 11 16:01:11 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * convert.c (convert_to_{pointer,integer,real,complex}): Use switch.
+ Add missing integer-like types.
+ Simplify return of zero in error case.
+ (convert_to_pointer): Remove dubious abort.
+ (convert_to_integer, case POINTER_TYPE): Make recursive call.
+ (convert_to_integer, case COND_EXPR): Always convert arms.
+ * tree.c (type_precision): Deleted.
+
+ * cccp.c (do_warning): Give pedantic warning if -pedantic and not
+ in system file.
+ * cpplib.c (do_warning): Likewise.
+
+ * function.c (target_temp_slot_level): Define here.
+ (push_temp_slots_for_target, {get,set}_target_temp_slot_level): New.
+ * stmt.c (target_temp_slot_level): Don't define here.
+ * expr.h (temp_slot_level): New declaration.
+
+Fri Apr 10 16:35:48 1998 Paul Eggert <eggert@twinsun.com>
+
+ * c-common.c (decl_attributes): Support strftime format checking.
+ (record_function_format, {check,init_function}_format_info): Likewise.
+ (enum format_type): New type.
+ (record_function_format): Now static; takes value of type
+ enum format_type instead of int.
+ (time_char_table): New constant.
+ (struct function_format_info): format_type member renamed from is_scan.
+ (check_format_info): Use `warning' rather than sprintf followed by
+ `warning', to avoid mishandling `%' in warnings.
+ Change a `pedwarn' to `warning'.
+ * c-tree.h (record_function_format): Remove decl.
+
+Thu Apr 2 17:34:27 1998 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * regclass.c (memory_move_secondary_cost): Protect uses of
+ SECONDARY_{INPUT,OUTPUT}_RELOAD_CLASS with #ifdef tests.
+
+Thu Apr 2 07:06:57 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k.c (standard_68881_constant_p): Don't use fmovecr on 68060.
+
+Thu Apr 2 06:19:25 1998 Ken Raeburn <raeburn@cygnus.com>
+
+ * Makefile.in (version.c): Put "cvs log" output in build directory.
+
+ * reload.h (MEMORY_MOVE_COST): Define here if not already defined.
+ (memory_move_secondary_cost): Declare.
+ * regclass.c (MEMORY_MOVE_COST): Don't define default here.
+ (memory_move_secondary_cost) [HAVE_SECONDARY_RELOADS]: New function.
+ (regclass, record_reg_classes, copy_cost, record_address_regs):
+ Pass register class and direction of move to MEMORY_MOVE_COST.
+ (top_of_stack) [HAVE_SECONDARY_RELOADS]: New static array.
+ (init_regs) [HAVE_SECONDARY_RELOADS]: Initialize it.
+ * reload1.c (MEMORY_MOVE_COST): Don't define default here.
+ (emit_reload_insns, reload_cse_simplify_set): Pass register class
+ and direction of move to MEMORY_MOVE_COST.
+ * 1750a.h (MEMORY_MOVE_COST): Add extra ignored arguments.
+ * a29k.h, alpha.h, arc.h, arm.h, dsp16xx.h, i386.h, m32r.h: Likewise.
+ * m88k.h, rs6000.h: Likewise.
+ * mips.h (MEMORY_MOVE_COST): Likewise.
+ Add memory_move_secondary_cost result to cpu-specific cost.
+
+Mon Mar 30 13:56:30 1998 Jim Wilson <wilson@cygnus.com>
+
+ * mips/ultrix.h (SUBTARGET_CPP_SPEC): Define.
+
+Wed Mar 25 16:09:01 1998 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000.h (FUNCTION_ARG_PADDING): Cast result to be enum direction.
+ (function_arg_padding): Declare.
+
+ * rs6000.c: Include stdlib.h if we have it.
+ (function_arg_padding): Change return type to int, cast enum's to int.
+
+ (From Kaveh R. Ghazi <ghazi@caip.rutgers.edu>)
+ * rs6000.c (rs6000_override_options): Change type of `i', `j' and
+ `ptt_size' from int to size_t.
+ (rs6000_file_start): Likewise for `i'.
+ (rs6000_replace_regno): Add default case in enumeration switch.
+ (output_epilog): Remove unused variable `i'.
+ (rs6000_longcall_ref): Remove unused variables `len', `p', `reg[12]'.
+
+ * rs6000.h (ADDITIONAL_REGISTER_NAMES): Add missing braces around
+ initializer.
+ (get_issue_rate, non_logical_cint_operand): Add prototype.
+ (rs6000_output_load_toc_table): Likewise.
+
+ * rs6000.md (udivmodsi4): Add explicit braces to avoid ambiguous
+ `else'.
+
+Wed Mar 25 02:39:01 1998 Paul Eggert <eggert@twinsun.com>
+
+ * configure.in (i[34567]86-*-solaris2*, powerpcle-*-solaris2*,
+ sparc-*-solaris2*): Use fixinc.svr4 if Solaris 2.0 through 2.4.
+
+Mon Mar 23 07:27:19 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * m68k.md (ashldi_const): Allow shift count in range ]32,63].
+ (ashldi3): Allow constant shift count in range ]32,63].
+ (ashrdi_const, ashrid3, lshrdi_const, lshrdi3): Likewise.
+
+ * m68k.md (zero_extend[qh]idi2, iordi_zext): New patterns.
+ (zero_extendsidi2): Avoid useless copy.
+ (iorsi_zexthi_ashl16): Avoid "0" constraint for operand 2.
+ (iorsi_zext): New name for old unnamed pattern; indentation fixes.
+
+Mon Mar 23 07:12:05 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * final.c (only_leaf_regs_used): If pic_offset_table_rtx used,
+ make sure it is a permitted register.
+
+Sun Mar 22 06:57:04 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expmed.c (extract_bit_field): Don't confuse SUBREG_WORD with
+ endian adjustment in SUBREG case.
+ Don't abort if can't make SUBREG needed for extv/extzv.
+
+Sat Mar 21 08:02:17 1998 Richard Gorton <gorton@amt.tay1.dec.com>
+
+ * alpha.md (zero_extendqi[hsd]i2): Use "and", not "zapnot".
+
+Sat Mar 21 07:47:04 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * unroll.c (verify_addresses): Use validate_replace_rtx.
+ (find_splittable_givs): If invalid address, show nothing same_insn.
+
+Fri Mar 20 10:24:12 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * fold-const.c (fold, case CONVERT_EXPR): Replace sign-extension of
+ a zero-extended value by a single zero-extension.
+
+Thu Mar 19 14:59:32 1998 Andrew Pochinsky <avp@ctp.mit.edu>
+
+ * sparc.h (ASM_OUTPUT_LOOP_ALIGN): Fix error in last change.
+
+Thu Mar 19 14:48:35 1998 Michael Meissner <meissner@cygnus.com>
+
+ * gcc.c (default_arg): Don't wander off the end of allocated memory.
+
+ * rs6000/sysv4.h (RELATIVE_PREFIX_NOT_LINKDIR): Undef for System V
+ and EABI.
+
+Thu Mar 19 06:17:59 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Makefile.in (toplev.o): Depend on Makefile.
+
+Wed Mar 18 17:40:09 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * expr.c (convert_move): Add [QH]Imode/P[QH]Imode conversions.
+ * machmode.def (PQImode, PHImode): New modes.
+
+Wed Mar 18 17:11:18 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k.md (movsf+1): Optimize moving a CONST_DOUBLE zero.
+
+Wed Mar 18 17:07:54 1998 Ken Raeburn <raeburn@cygnus.com>
+
+ * regclass.c (init_reg_sets): Delete init of reg-move cost tables.
+ (init_reg_sets_1): Put it here.
+
+Wed Mar 18 16:43:11 1998 Jim Wilson <wilson@cygnus.com>
+
+ * i960.md (tablejump): Handle flag_pic.
+
+ * profile.c (branch_prob): If see computed goto, call fatal.
+
+ * calls.c (expand_call): Fix typos in n_named_args computation.
+
+Wed Mar 18 05:54:25 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * fold-const.c (operand_equal_for_comparison_p): See if equal
+ when nop conversions are removed.
+
+ * expr.c (expand_expr, case COND_EXPR): If have conditional move,
+ don't use ORIGINAL_TARGET unless REG.
+
+ * function.c (fixup_var_refs_insns): Also delete insn storing pseudo
+ back into arg list.
+
+ * combine.c (gen_binary): Don't make AND that does nothing.
+ (simplify_comparison, case AND): Commute AND and SUBREG.
+ * i386.h (CONST_CONSTS, case CONST_INT): One-byte integers are cost 0.
+
+Mon Mar 16 15:57:17 1998 Geoffrey Keating <geoffk@ozemail.com.au>
+
+ * rs6000.c (small_data_operand): Ensure any address referenced
+ relative to small data area is inside SDA.
+
+Sun Mar 15 16:01:19 1998 Andrew Pochinsky <avp@ctp.mit.edu>
+
+ * sparc.h (ASM_OUTPUT_LOOP_ALIGN): Write nop's.
+
+Sun Mar 15 15:53:39 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * libgcc2.c (exit): Don't call __bb_exit_func if HAVE_ATEXIT.
+
+Sun Mar 15 15:44:41 1998 Paul Eggert <eggert@twinsun.com>
+
+ * cccp.c: Fix bugs relating to NUL in input file name,
+ e.g. with `#line 2 "x\0y"'.
+ (PRINTF_PROTO_4): New macro.
+ (struct {file_buf,definition,if_stack}): New member nominal_fname_len.
+ (main, expand_to_temp_buffer): Store length of input file names.
+ (finclude, create_definition, do_line, conditional_skip): Likewise.
+ (skip_if_group, macroexpand): Likewise.
+ (make_{definition,undef,assertion}): Likewise.
+ (special_symbol, do_include): Use stored length of input file names.
+ (do_define, do_elif, do_else, output_line_directive, verror): Likewise.
+ (error_from_errno, vwarning, verror_with_line): Likewise.
+ (vwarning_with_line, pedwarn_with_file_and_line): Likewise.
+ (print_containing_files): Likewise.
+ (do_line): Fix off-by-1 problem: 1 too many bytes were being allocated.
+ (quote_string, pedwarn_with_file_and_line): New arg specifies length.
+ All callers changed.
+
+Sun Mar 15 15:38:16 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * c-typeck.c: Collect pending initializers in AVL tree instead of list.
+ (add_pending_init, pending_init_member): New functions.
+ (output_init_element): Use them.
+ (output_pending_init_elements): Rewritten to exploit AVL order.
+
+Sun Mar 15 05:10:49 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * gnu.h (GNU_CPP_PREDEFINES): Deleted; not valid in traditional C.
+ * {i386,mips}/gnu.h (CPP_PREDEFINES): Don't call GNU_CPP_PREDEFINES.
+
+ * flow.c (insn_dead_p): A CLOBBER of a dead pseudo is dead.
+
+ * alpha.h (REG_ALLOC_ORDER): Put $f1 after other nonsaved.
+
+ * sparc.c (sparc_type_code): Fix error in previous change.
+
+Sat Mar 14 05:45:21 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * i386/xm-aix.h, i386/xm-osf.h (i386/xm-i386.h): Don't include.
+ (USG): Don't define.
+ * i386/xm-isc.h (i386/xm-sysv3.h): Don't include.
+ * i386/xm-sco.h (i386/xm-sysv3.h): Likewise.
+ (BROKEN_LDEXP, SMALL_ARG_MAX, NO_SYS_SIGLIST): Don't define.
+ * m68k/xm-3b1.h (m68k/xm-m68k.h): Don't include.
+ (USG): Don't define.
+ * m68k/xm-atari.h (m68k/xm-m68kv.h): Don't include.
+ (HAVE_VPRINTF, FULL_PROTOTYPES): Don't define.
+ * m68k/xm-crds.h (m68k/xm-m68k.h): Don't include.
+ (USE_C_ALLOCA, unos, USG): Don't define.
+ * m68k/xm-mot3300.h (m68k/xm-m68k.h): Don't include.
+ (USE_C_ALLOCA, NO_SYS_SIGLIST): Don't define.
+ * m68k/xm-plexus.h (m68k/xm-m68k.h): Don't include.
+ (USE_C_ALLOCA, USG): Don't define.
+ * m88k/xm-sysv3.h (m88k/xm-m88k.h): Don't include.
+ * m68k/xm-next.h (m68k/xm-m68k.h): Don't include.
+ * ns32k/xm-pc532-min.h (ns32k/xm-ns32k.h): Don't include.
+ (USG): Don't define.
+ * rs6000/xm-mach.h: Don't include xm-rs6000.h.
+ * rs6000/xm-cygwin32.h (rs6000/xm-rs6000.h): Don't include.
+ (NO_STAB_H): Don't define.
+ * sparc/xm-linux.h (xm-linux.h): Don't include.
+ * sparc/xm-sol2.h (sparc/xm-sysv4.h): Don't include.
+ * a29k/xm-unix.h, alpha/xm-linux.h, arm/xm-linux.h: Deleted.
+ * arm/xm-netbsd.h, i386/xm-bsd386.h, i386/xm-gnu.h: Deleted.
+ * i386/xm-linux.h, i386/xm-sun.h, i386/xm-sysv3.h: Deleted.
+ * i386/xm-winnt.h, m68k/xm-altos3068.h, m68k/xm-amix.h: Deleted.
+ * m68k/xm-amix.h, m68k/xm-hp320.h, m68k/xm-linux.h: Deleted.
+ * m68k/xm-m68kv.h, mips/xm-iris5.h, ns32k/xm-genix.h: Deleted.
+ * sparc/xm-pbd.h, vax/xm-vaxv.h, xm-svr3.h, xm-linux.h: Deleted.
+ * configure.in: Reflect above changes.
+
+ * xm-siglist.h, xm-alloca.h: New files.
+ * i386/xm-sysv4.h (i386/xm-i386.h, xm-svr4.h): Don't include.
+ (USE_C_ALLOCA, SMALL_ARG_MAX): Don't define.
+ * i386/xm-sco5.h (i386/xm-sysv3.h): Don't include.
+ (SYS_SIGLIST_DECLARED, USE_C_ALLOCA): Don't define.
+ * rs6000/xm-sysv4.h, sparc/xm-sysv4.h: Don't include xm-svr4.h.
+ * xm-svr4.h, i386/xm-dgux.h, mips/xm-news.h, mips/xm-sysv4.h: Deleted.
+ * configure.in: Reflect above changes.
+
+ * configure.in ({,host_,build_}xm_defines): New variables.
+ Set to USG instead of including xm-usg.h.
+ Write #define lines in config.h files from xm_defines vars.
+ * xm-usg.h: Deleted.
+
+Fri Mar 13 07:10:59 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * calls.c (expand_call): Fix typo in previous change.
+
+ * sparc.c (sparc_type_code): Avoid infinite loop when have
+ pointer to array of same pointer.
+ (sparc_type_code, case REAL_TYPE): Process subtypes here too.
+
+ * mips/bsd-4.h, mips/iris3.h, mips/news{4,5}.h: Don't include mips.h.
+ * mips/news5.h, mips/osfrose.h, mips/svr{3,4}-4.h: Likewise.
+ * mips/ultrix.h: Likewise.
+ * mips/cross64.h: Don't include iris6.h.
+ * mips/ecoff.h: Don't include mips.h or gofast.h.
+ * mips/elforion.h: Don't include elf64.h.
+ * mips/iris4.h: Don't include iris3.h.
+ * mips/iris4loser.h: Don't include iris4.h.
+ * mips/iris5gas.h: Don't include iris5.h.
+ * mips/elflorion.h, mips/nws3250v4.h, mips/xm-iris{3,4}.h: Deleted.
+ * mips/xm-nws3250v4.h, mips/xm-sysv.h: Deleted.
+ * mips/rtems64.h: Don't include elflorion.h.
+ * mips/sni-gas.h: Don't include sni-svr4.h.
+ * mips/svr4-t.h: Don't include svr4-5.h.
+ * mips/dec-osf1.h: Also include mips.h.
+ * mips/ecoffl.h, mips/elf.h: Also include mips.h and gofast.h.
+ * mips/iris5.h: Also include iris3.h and mips.h.
+ * xm-usg.h: New file.
+ * mips/xm-iris5.h: Don't include xm-mips.h; don't define USG.
+ * mips/xm-news.h, mips/xm-sysv4.h: Don't include xm-sysv.h.
+ * configure.in: Reflect above changes.
+
+Thu Mar 12 07:18:48 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.h (STRICT_ARGUMENT_NAMING): Provide default value of 0.
+ * calls.c (expand_call): Use value of STRICT_ARGUMENT_NAMING.
+ * function.c (assign_parm): Likewise.
+ * mips/abi64.h (STRICT_ARGUMENT_NAMING): Return 0 for ABI_32.
+ * sparc.h (STRICT_ARGUMENT_NAMING): Only nonzero for V9.
+
+ * calls.c (expand_call, expand_library_call{,_value}, store_one_arg):
+ Rework handling of REG_PARM_STACK_SPACE to treat return value of
+ zero as if macro not defined; add new arg to emit_push_insn.
+ * expr.c (emit_push_insn): New arg, REG_PARM_STACK_SPACE.
+ * expr.h (emit_push_insn): Likewise.
+ * mips/abi64.h (REG_PARM_STACK_SPACE): Define.
+
+Wed Mar 11 06:58:13 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k.h (CONST_OK_FOR_LETTER_P, case 'M'): Correct range check.
+
+Wed Mar 11 06:15:52 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (emit_push_insn): Use loop to find movstr patterns
+ instead of explicit tests.
+
+ * Makefile.in (extraclean): Don't delete install1.texi.
+
+Tue Mar 10 14:27:51 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * combine.c (make_field_assignment): Don't get confused if OTHER
+ has VOIDmode and don't do anything if DEST is wider than a host word.
+
+ * vax.c (check_float_value): Cast bcopy args to char *.
+
+Tue Mar 10 13:56:12 1998 Jim Wilson <wilson@cygnus.com>
+
+ * mips/abi64.h (LONG_MAX_SPEC): Check MIPS_ABI_DEFAULT and
+ TARGET_DEFAULT and define __LONG_MAX__ appropriately.
+ Add support for -mabi=X, -mlong64, and -mgp{32,64} options.
+ * mips.c (mips_abi): Change type to int.
+ * mips.h (enum mips_abi_type): Delete.
+ (ABI_32, ABI_N32, ABI_64, ABI_EABI): Define as constants.
+ (mips_abi): Change type to int.
+
+Mon Mar 2 08:06:58 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Version 2.8.1 released.
+
+ * Makefile.in (mostlyclean): Remove duplicate deletion of temp
+ files. Delete more stamp files and [df]p-bit.c
+ (clean): Don't delete stamp files here.
+ (VERSION_DEP): New variable.
+ (distdir-finish): Pass a value of null for it.
+ (version.c): Use it.
+ Avoid broken pipe with cvs log.
+
+ * objc/Make-lang.in (objc/runtime-info.h): Rename emptyfile to
+ tmp-runtime and delete at end.
+
+Sun Mar 1 05:50:25 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * tree.c (build_reference_type): Handle obstacks like
+ build_pointer_type.
+
+ * Makefile.in (tmp-gcc.xtar): Renamed from gcc.xtar.
+ (gcc.xtar.gz): Deleted; merged with `dist'.
+ (diff): Create gcc-$(oldversion)-$(version).diff.
+ (distdir): Depend on distdir-cvs.
+ (distdir-cvs): New rule.
+ (distdir-start): Depend on version.c and TAGS.
+ (TAGS): Use tmp-tags instead of temp.
+ (dist): Create gcc-$(version).tar.gz.
+
+ * varasm.c (compare_constant_1): Fix typo in previous change.
+
+ * objc/Make-lang.in (objc-distdir): Properly rebuild objc-parse.c.
+
+Sat Feb 28 16:58:08 1998 Tristan Gingold <gingold@rossini.enst.fr>
+
+ * stmt.c (expand_decl): If -fcheck-memory-usage, put vars in memory.
+ * expr.c (get_memory_usage_from_modifier): Convert
+ EXPAND_{CONST_ADDRESS, INITIALIZER} to MEMORY_USE_DONT.
+
+Sat Feb 28 08:13:43 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * i860/fx2800.h (DATA_ALIGNMENT): Use POINTER_TYPE_P.
+ * m68k/a-ux.h (FUNCTION_VALUE): Likewise.
+ * expr.c (get_pointer_alignment, compare, do_store_flag): Likewise.
+ (expand_builtin): Likewise.
+ * fold-const.c (force_fit_type, fold_convert, fold): Likewise.
+ * function.c (assign_parms): Likewise.
+ * integrate.c (expand_inline_function): Likewise.
+ * sdbout.c (sdbout_field_types): Likewise.
+ * tree.c (integer_pow2p, tree_log2, valid_machine_attribute): Likewise.
+ * stmt.c (expand_decl): Likewise.
+ ({,bc_}expand_decl_init): Also test for REFERENCE_TYPE.
+
+ * configure.in (version_dep): New variable; if srcdir is CVS working
+ directory, set to ChangeLog.
+ (version): Supply default if no version.c.
+ * Makefile.in (version.c): New rule.
+
+ * gcc.c (snapshot_warning): New function.
+ (main): Call it for snapshots.
+
+ * dwarf2out.c (expand_builtin_dwarf_reg_size): If reg_raw_mode
+ not valid for reg, use last size. Also refine range assertion.
+
+Sat Feb 28 05:04:47 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * enquire.c (cprop): Don't perform exhaustive search for char_min
+ and char_max when bits_per_byte > 16.
+
+Thu Feb 26 15:12:03 1998 Christopher Taylor <cit@ckshq.com>
+
+ * fixincludes: Avoid using '0-~' in egrep.
+
+Thu Feb 26 08:04:05 1998 Tristan Gingold <gingold@messiaen.enst.fr>
+
+ * function.c (assign_parms): Call 'chkr_set_right' when DECL_RTL
+ is stack_parm.
+ * expr.c (get_memory_usage_from_modifier): Convert
+ EXPAND_{SUM, CONST_ADDRESS, INITIALIZER} to MEMORY_USE_RO.
+
+Thu Feb 26 07:33:53 1998 Paul Eggert <eggert@twinsun.com>
+
+ * c-lex.c (yylex): Don't munge errno before using it.
+ * cccp.c (error_from_errno, perror_with_name): Likewise.
+ * cpplib.c (cpp_error_from_errno): Likewise.
+ * gcc.c (pfatal_pexecute): Likewise.
+ * protoize.c (safe_write, find_file, process_aux_info_file): Likewise.
+ (rename_c_file, edit_file): Likewise.
+
+ * c-lex.c (yylex): Remove unused variable exceeds_double.
+
+Thu Feb 26 07:05:14 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * reorg.c (fill_slots_from_thread): Don't steal delay list from target
+ if condition code of jump conflicts with opposite_needed.
+
+Thu Feb 26 06:45:23 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Makefile.in (distdir-start): Don't copy CVS subdirectory of config.
+
+ * varasm.c ({compare,record}_constant_1, case CONSTRUCTOR):
+ Handle the case when we have TREE_PURPOSE values.
+
+Thu Feb 26 05:59:01 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * fixincludes (sys/limits.h): Fix a nested comment problem with
+ HUGE_VAL definition on sysV68 R3V7.1.
+
+Wed Feb 25 21:09:38 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * toplev.c (TICKS_PER_SECOND): Renamed from CLOCKS_PER_SECOND.
+
+Wed Feb 25 20:50:08 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * reorg.c (fill_slots_from_thread): Mark resources referenced in
+ opposite_needed thread. Return delay_list even when cannot get
+ any more delay insns from end of subroutine.
+
+Wed Feb 25 19:50:01 1998 Mikael Pettersson <Mikael.Pettersson@sophia.inria.fr>
+
+ * gcc.c (lookup_compiler): Remove redundant test.
+
+Wed Feb 25 07:24:22 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * vax.md (call insns): Second operand to CALL rtl is SImode.
+
+ * configure.in (i[34567]86-*-mingw32): Support msv and crt suffix.
+ * i386/crtdll.h: New file.
+
+ * sparc.c (pic_setup_code): If -O0, write USE of pic_offset_table_rtx.
+
+ * expr.c (safe_from_p): Add new arg, TOP_P; all callers changed.
+
+Sat Feb 21 07:02:39 1998 Jim Wilson <wilson@cygnus.com>
+
+ * mips/iris5.h (DWARF2_UNWIND_INFO): Define to 0.
+ * mips/iris5gas.h (DWARF2_UNWIND_INFO): Define to 1.
+
+Fri Feb 20 08:27:46 1998 Paul Eggert <eggert@twinsun.com>
+
+ * sparc/sol2-sld.h: New file.
+ * configure.in (sparc-*-solaris2*): Use it when using system linker.
+ * toplev.c (main): Don't default to DWARF2_DEBUG with -ggdb
+ if LINKER_DOES_NOT_WORK_WITH_DWARF2 is defined.
+
+Fri Feb 20 08:21:49 1998 H.J. Lu (hjl@gnu.org)
+
+ * alpha/elf.h (STARTFILE_SPEC, ENDFILE_SPEC): Support shared library.
+ (LIB_SPEC, DEFAULT_VTABLE_THUNKS): Defined #ifndef USE_GNULIBC_1.
+ * sparc/linux.h (DEFAULT_VTABLE_THUNKS): Likewise.
+ (LIB_SPEC): Add -lc for -shared #ifndef USE_GNULIBC_1.
+ * linux.h (LIB_SPEC): Likewise.
+ * sparc/linux64.h (LIB_SPEC): Likewise; also updated for glibc 2.
+ (LIBGCC_SPEC): Removed.
+ (CPP_SUBTARGET_SPEC): Add %{pthread:-D_REENTRANT}.
+
+Fri Feb 20 05:22:12 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Makefile.in (distdir-start): Add dependence on bi-parser.[ch].
+
+Thu Feb 19 18:07:11 1998 Jim Wilson <wilson@cygnus.com>
+
+ * m68k.h (TARGET_SWITCHES): For 68000, 68302, subtract MASK_68881.
+ For 68303, 68332, cpu32, subtract MASK_68040_ONLY.
+
+Wed Feb 18 09:37:29 1998 Paul Eggert <eggert@twinsun.com>
+
+ * fixincludes (stdlib.h): Do not double-wrap the size_t typedef.
+
+Wed Feb 18 07:32:11 1998 Jim Wilson <wilson@cygnus.com>
+
+ * i960.c (emit_move_sequence): Handle unaligned stores to pseudos.
+ * i960.md (store_unaligned_[dt]i_reg): Handle register dest.
+ (store_unaligned_ti_reg): Likewise.
+
+ * m68k.h (MACHINE_STATE_{SAVE,RESTORE} [MOTOROLA]): Add %# and %/;
+ add : to make them into extended asms.
+
+Wed Feb 18 07:08:05 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reg-stack.c (compare_for_stack_reg): Only handle FP conditional
+ move as next insn specially.
+
+ * reload.c (find_reloads): Always convert address reload for
+ non-reloaded operand to RELOAD_FOR_OPERAND_ADDRESS.
+
+ * emit-rtl.c (hard-reg-set.h): Include.
+ (get_lowpart_common): Don't make new REG for hard reg in a
+ class that cannot change size.
+ * Makefile.in (emit-rtl.o): Depend on hard-reg-set.h.
+
+Sat Feb 14 09:59:00 1998 Richard Earnshaw (rearnsha@arm.com)
+
+ * arm.md (movsfcc): Also validate operands[3] for hard float.
+ (movdfcc): Only accept fpu_add_operand for operands[3].8
+
+Sat Feb 14 09:32:34 1998 Jim Wilson <wilson@cygnus.com>
+
+ * dwarf2out.c (expand_builtin_dwarf_reg_size): New variable mode.
+ Convert CCmode to word_mode before calling GET_MODE_SIZE.
+
+Sat Feb 14 09:27:42 1998 David Edelsohn <edelsohn@mhpcc.edu>
+
+ * rs6000.h (MY_ISCOFF): Check for U803XTOCMAGIC.
+
+Sat Feb 14 08:29:43 1998 Arvind Sankar <arvind@cse.iitb.ernet.in>
+
+ * t-svr4 (TARGET_LIBGCC_CFLAGS): New definition.
+
+Sat Feb 14 07:45:16 1998 Ken Rose (rose@acm.org)
+
+ * reorg.c (fill_slots_from_thread): New parameter, delay_list.
+ All callers changed.
+
+Sat Feb 14 07:14:02 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload.c (debug_reload): Properly output insn codes.
+
+ * pa.c (emit_move_sequence): If in reload, call find_replacement.
+
+ * gansidecl.h (bcopy, bzero, {,r}index): Don't define if IN_LIBGCC2.
+
+ * combine.c (distribute_notes, case REG_DEAD): When seeing if place
+ to put new note sets register, use reg_bitfield_target_p, as in
+ original code.
+
+ * gcc.c (process_command): If file is for linker, set lang to "*".
+ (lookup_compiler): Return 0 for language of "*".
+
+ * sched.c (attach_deaths, case SUBREG): Fix error in last change.
+
+ * i386.md (mov[sdx]fcc): Disable for now.
+ (mov[sd]fcc_1): Add earlyclobber for output on last alternative.
+
+Sat Feb 14 06:42:50 1998 Jason Merrill <jason@yorick.cygnus.com>
+
+ * except.c (get_dynamic_handler_chain): Only make call once per func.
+ (expand_fixup_region_{start,end}): New functions.
+ (expand_eh_region_start_tree): Store cleanup into finalization here.
+ * stmt.c (expand_cleanups): Use new functions to protect fixups.
+
+ * except.c (get_dynamic_handler_chain): Build up a FUNCTION_DECL.
+ * optabs.c (init_optabs): Don't init get_dynamic_handler_chain_libfunc.
+ * expr.h (get_dynamic_handler_chain_libfunc): Deleted.
+
+Sat Feb 14 06:34:41 1998 Peter Lawrence <Peter.Lawrence@Eng.Sun.COM>
+
+ * optabs.c (emit_conditional_move): Don't reverse condition for FP.
+
+Fri Feb 13 07:22:04 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Makefile.in (mostlyclean): Only use s-* convention for stamp
+ files in main dir.
+
+ * configure.in: Add support for i786 (Pentium II); same as i686.
+
+Thu Feb 12 20:16:35 1998 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000.md: Replace gen_rtx (CONST_INT,...) with GEN_INT.
+
+Thu Feb 12 10:08:14 1998 John Hassey <hassey@dg-rtp.dg.com>
+
+ * configure.in (i[3456]86-dg-dgux*): Don't need fixincludes.
+
+Thu Feb 12 07:27:39 1998 Mumit Khan <khan@xraylith.wisc.edu>
+
+ * i386/cygwin32.h (NO_IMPLICIT_EXTERN_C): Define.
+ about system headers.
+ (LIB_SPEC): Add -ladvapi32 -lshell32.
+
+Thu Feb 12 07:19:31 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (expand_assignment): Fix typo in checking OFFSET.
+
+ * gbl-ctors.h (atexit): Don't define unless needed.
+
+ * combine.c (distribute_notes): Completely check for note operand being
+ only partially set on potential note target; adjust what notes
+ we make in that case.
+
+ * i386/xm-go32.h (HAVE_{BCOPY,BZERO,INDEX,RINDEX}): Deleted.
+
+Wed Feb 11 08:53:27 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * calls.c (emit_call_1): Size args now HOST_WIDE_INT.
+ (expand_call): struct_value_size now HOST_WIDE_INT.
+
+Tue Feb 10 09:04:39 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * integrate.c (initialize_for_inline): Ensure DECL_INCOMING_RTL
+ is always copied.
+
+Tue Feb 10 06:10:49 1998 Paul Eggert <eggert@twinsun.com>
+
+ * cccp.c (rescan): Fix bug with macro name appearing
+ immediately after L'x'.
+
+Mon Feb 9 20:45:32 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * c-common.c (format_char_info): Add new field zlen.
+ (print_char_table): Remove entry for 'Z' as a format character.
+ Initialize zlen field as appropriate.
+ (scan_char_table): Set zlen field to NULL in each entry.
+ (check_format_info): Recognize 'Z' as a length modifier, with a
+ warning in pedantic mode.
+ Avoid infinite loop when a repeated flag character is detected.
+
+Mon Feb 9 09:24:04 1998 Paul Eggert <eggert@twinsun.com>
+
+ * c-parse.in (primary): Minor wording fix in diagnostic.
+
+Mon Feb 9 07:50:19 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * c-decl.c (grokdeclarator): Remove warning on inline of varargs.
+
+ * reload.c (find_reloads): Check for const_to_mem case before
+ checking for invalid reload; use force_const_mem if no_input_reloads.
+
+ * function.c (push_function_context_to): Call init_emit last.
+
+ * protoize.c (my_link): Define as -1 in mingw32.
+ (link): Remove declaration.
+
+ * rs6000.c (setup_incoming_varargs): Always set rs6000_sysv_varargs_p.
+
+ * integrate.c (expand_inline_function): Clear label_map with bzero.
+
+ * unroll.c (copy_loop_body, case JUMP_INSN): Correct error in last
+ change: call single_set on COPY, not INSN.
+
+Sun Feb 8 08:07:37 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * msdos/top.sed, winnt/config-nt.sed: Change version number to 2.8.1.
+
+ * configure.in (i[3456]86-*-sco3.2v5*): Use cpio for headers.
+
+Sat Feb 7 07:32:46 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * i386/mingw32.h (LIBGCC_SPEC, STARTFILE_SPEC, MATH_LIBRARY):
+ Use msvcrt, not crtdll.
+
+Fri Feb 6 20:32:06 1998 Geert Bosch <bosch@gnat.com>
+
+ * i386/xm-os2.h (EMX, USG, BSTRING, HAVE_{PUTENV,VPRINTF,STRERROR}):
+ Define ifdef __EMX__.
+ (strcasecmp): Define to be stricmp if __EMX__.
+ (spawnv{,p}): Don't define if EMX.
+ (OBJECT_SUFFIX): Don't define if EMX.
+ (MKTEMP_EACH_FILE): Define.
+
+Fri Feb 6 16:37:29 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * objc/Make-lang.in (objc.stage1): Depend on stage1-start.
+ (objc.stage2, objc.stage3, objc.stage4): Likewise for the
+ respective stageN-start targets.
+ (objc/sendmsg.o): Depend on objc/runtime-info.h.
+
+Fri Feb 6 16:27:09 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
+
+ * stmt.c (expand_asm_operands): Properly treat asm statement
+ statements with no operands as volatile.
+
+Fri Feb 6 16:03:25 1998 Greg McGary <gkm@gnu.org>
+
+ * c-decl.c (pushdecl): Set DECL_ORIGINAL_TYPE once only.
+
+Fri Feb 6 15:57:36 1998 Mumit Khan <khan@xraylith.wisc.edu>
+
+ * i386/cygwin32.h (STRIP_NAME_ENCODING): New macro.
+
+Fri Feb 6 15:50:42 1998 Paul Eggert <eggert@twinsun.com>
+
+ * libgcc2.c (__floatdi[xtds]f): Round properly even when rounding
+ large negative integer to plus or minus infinity.
+
+Fri Feb 6 15:45:16 1998 Philippe De Muyter <phdm@macqel.be>
+
+ * sdbout.c (plain_type_1): Return T_DOUBLE, not T_VOID, for
+ long double #ifndef EXTENDED_SDB_BASIC_TYPES.
+
+Fri Feb 6 15:23:49 1998 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * vax/ultrix.h (HAVE_ATEXIT): Define.
+ * x-vax: File deleted.
+
+Fri Feb 6 14:34:19 1998 Douglas Rupp <rupp@gnat.com>
+
+ * gcc.c (process_command, case "-dumpversion"): Print spec_version.
+
+Fri Feb 6 11:01:13 1998 Josh Littlefield <josh@american.com>
+
+ * i386/gmon-sol2.c (internal_mcount): Do set-up when program starts
+ and install hook to do clean-up when it exits.
+ * i386/sol2-c1.asm (_mcount): Make a weak instead of global symbol.
+ * i386/sol2dbg.h (ASM_SPEC): Support Solaris bundled assembler's -V
+ argument; pass -s argument to assembler.
+
+Fri Feb 6 09:13:21 1998 Jim Wilson (wilson@cygnus.com)
+
+ * function.c (assign_parms): New variable named_arg, with value
+ depending on STRICT_ARGUMENT_NAMING. Use instead of ! last_named.
+
+ * crtstuff.c (__frame_dummy): New function for irix6.
+ (__do_global_ctors): Call __frame_dummy for irix6.
+ * mips/iris6.h (LINK_SPEC): Hide __frame_dummy too.
+
+Fri Feb 6 09:08:21 1998 Mike Stump <mrs@wrs.com>
+
+ * rtlanal.c (dead_or_set_regno_p): Ignore REG_DEAD notes after reload.
+ * genattrtab.c (reload_completed): Define.
+
+ * configure.in (i960-wrs-vxworks): Same as i960-wrs-vxworks5*.
+
+Fri Feb 6 08:47:38 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Makefile.in (diff): Add INSTALL, configure, and config.in;
+ remove objc-*.
+ * objc/config-lang.in (diff_excludes): Add objc-parse.[cy].
+
+ * i386/xm-mingw32.h (link): Delete macro.
+
+ * alpha.c (output_prolog): Write out frame sizes as longs and
+ print too large sizes as zero.
+
+ * function.c (combine_temp_slots): No need to allocate and free rtx.
+ Don't do anything if too many slots in the list.
+ (put_var_into_stack): Don't use ADDRESSOF if not optimizing.
+
+ * function.c (purge_addressof_1): Force into mem if VOLATILE reference.
+
+ * calls.c (expand_call): Show VAR_DECL made for structure return
+ address is used; remove bogus set of MEM_IN_STRUCT_P.
+ * expr.c (expand_expr, case SAVE_EXPR, case TARGET_EXPR): Show used.
+ (expand_builtin, case BUILT_IN_LONGJMP): Show __dummy used.
+ * function.c (put_reg_into_stack): New arg USED_P; all callers changed.
+
+ * expr.c (expand_expr, case SAVE_EXPR): assign_temp with KEEP of 3.
+ * function.c (var_temp_slot_level): New variable.
+ (push_function_context_to, pop_function_context_from): Save/restore
+ it and target_temp_slot_level.
+ (assign_stack_temp): Implement KEEP of 3.
+ (push_temp_slots_for_block): New function.
+ (init_temp_slots): Initialize var_temp_slot_level.
+ * function.h (struct function, fields {var,target}_temp_slot_level):
+ New fields.
+ * stmt.c (expand_start_bindings): Call push_temp_slots_for_block.
+
+ * function.c (struct temp_slot): SIZE, BASE_OFF_SET, and FULL_SIZE
+ now HOST_WIDE_INT.
+ (assign_{,outer_}stack_local, assign_{,stack_}temp): Size arg is
+ now HOST_WIDE_INT.
+ (assign_stack_temp): Do size computations in HOST_WIDE_INT.
+ (fixup_var_refs_1, optimize_bit_field, instantiate_decls): Likewise.
+ (instantiate_virtual_regs_1, fix_lexical_address): Likewise.
+ * rtl.h (assign_stack_{local,temp}): Size arg is HOST_WIDE_INT.
+ (assign_temp): Likewise.
+ * expr.h (struct args_size): Field CONSTANT is now HOST_WIDE_INT.
+
+ * sched.c (attach_deaths, case REG): Don't check for REG_UNUSED.
+ (attach_deaths, case SUBREG, STRICT_LOW_PART, {ZERO,SIGN}_EXTRACT):
+ Don't pass set_p of 1 if partial assignment.
+
+ * tree.h (size_in_bytes): Returns HOST_WIDE_INT.
+ * tree.c (size_in_bytes): Likewise.
+ Tighen up logic some to avoid returning a bogus value instead of -1.
+
+ * expr.c (get_inner_reference, case ARRAY_EXPR): Make WITH_RECORD_EXPR
+ just for index.
+ (expand_expr, case PLACEHOLDER_EXPR): Refine search again; look
+ at each expression and look for pointer to type.
+
+ * expr.c (safe_from_p, case ADDR_EXPR): If TREE_STATIC, no trampoline.
+ (expand_expr, case ADDR_EXPR): Likewise.
+
+ * expr.c (emit_block_move): Use conservative range for movstr mode.
+
+ * configure.in: See if "cp -p" works if "ln -s" doesn't; else "cp".
+
+ * combine.c (try_combine.c): Pass elim_i2 and elim_i1 to
+ distribute_notes for i3dest_killed REG_DEAD note.
+
+ * configure.in (mips-dec-netbsd*): Remove bogus setting of prefix.
+
+ * c-decl.c (duplicate_decls): Set DECL_IGNORED_P in newdecl if
+ different bindings levels.
+
+ * configure.in: Test ln -s by symlinking gcc.c.
+
+ * configure.in (i[3456]86-dg-dgux): Add wildcard for version.
+
+ * crtstuff.c (__do_global_ctors_aux): Switch back to text section
+ in proper place.
+
+ * rtlanal.c (rtx_varies_p, case REG): pic_offset_table_rtx is fixed.
+ * genattrtab.c (pic_offset_table_rtx): Define (dummy).
+ * cse.c (set_nonvarying_address_components): Understand PIC refs.
+
+ * loop.c (strength_reduce): When placing increment for auto-inc
+ case, do comparison in loop order.
+
+ * i860.c (output_delayed_branch): Add missing arg to recog.
+ (output_delay_insn): Add missing arg to constrain_operands.
+
+ * configure.in: Truncate target after finished comparing it with host.
+
+ * i386.h (MAX_FIXED_MODE_SIZE): Delete.
+
+ * c-parse.in (expr_no_comma): Clarify undefined error.
+
+ * prefix.c (get_key_value): Don't default to PREFIX here.
+ (translate_name): Remove bogus addition of "$" if getenv fails;
+ clean up application of default value of PREFIX.
+
+ * fold-const.c (fold_convert): Call force_fit_type even if input
+ already overflows.
+
+Fri Feb 6 07:45:01 1998 Robert Hoehne <robert.hoehne@gmx.net>
+
+ * i386/xm-go32.h (HAVE_{BCOPY,BZERO,BCMP,RINDEX,INDEX}): Define.
+
+ * gcc.c (main): Treat paths starting with '$' or DOS drives
+ as absolute in standard_startfile_prefix.
+
+Thu Feb 5 21:07:12 1998 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * cpplib.c (IS_INCLUDE_DIRECTIVE_TYPE): Add casts from enum to int.
+ * cccp.c (IS_INCLUDE_DIRECTIVE_TYPE, handle_directive): Likewise.
+
+Thu Feb 5 19:00:44 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (expand_expr, case CONSTRUCTOR): Correct shift count
+ when making signed bit field; use EXPAND_NORMAL, not 0.
+
+Thu Feb 5 17:42:43 1998 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * libgcc2.c (__clear_insn_cache): On sysV68 enable the memctl
+ stuff only if MCT_TEXT is #define'd.
+
+Thu Feb 5 17:32:01 1998 Robert Hoehne <robert.hoehne@gmx.net>
+
+ * Makefile.in: Changed most stamp-* to s-*.
+
+Tue Feb 3 19:45:50 1998 James Hawtin <oolon@ankh.org>
+
+ * i386/sol2.h (STARTFILE_SPEC, LIB_SPEC): Update -pg files.
+ * configure.in (i[3456]86-*-solaris2*): Add gcrt1.o and gmon.o
+ to extra_parts.
+
+Tue Feb 3 17:28:48 1998 Christopher C Chimelis <chris@classnet.med.miami.edu>
+
+ * configure.in (alpha*-*-linux-gnu*): Add extra_parts for crtstuff.
+
+Tue Feb 3 17:18:19 1998 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.c (find_barrier): Fix one-too-many bug if fail to find barrier.
+
+ * arm.c (arm_reload_in_hi): Handle cases where the MEM is too
+ complex for a simple offset.
+
+Tue Feb 3 16:14:21 1998 Robert Hoehne <robert.hoehne@gmx.net>
+
+ * i386/xm-go32.h (EXECUTABLE_SUFFIX): Define.
+
+ * configure.in (i[3456]86-pc-msdosdjgpp*): New entry.
+
+Tue Feb 3 07:33:58 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * explow.c (probe_stack_range): Properly check for small
+ number of probes.
+
+ * gcc.c (process_command, case 'V'): Validate arg.
+
+ * configure.in (sbrk): Add check for needed declaration.
+ * acconfig.h (NEED_DECLARATION_SBRK): New entry.
+ * toplev.c (sbrk): Update declaration conditional.
+ * mips-tfile.c (sbrk, free): Likewise.
+
+ * sparc/sysv4.h (DBX_REGISTER_NUMBER): Remove abort.
+
+ * mips.c (mips_expand_prologue): Pass reg 25 to gen_loadgp.
+ * mips.md (loadgp): Add second operand for register number to add.
+ (builtin_setjmp_receiver): Pass new label and reg 31 to loadgp.
+
+ * toplev.c: Include insn-codes.h, insn-config.h, and recog.h.
+ (compile_file): Try to emit nop to separate gcc_compiled symbol.
+ * Makefile.in (toplev.o): Depends on insn-{codes,config}.h, recog.h.
+
+Tue Feb 3 06:58:46 1998 Mark Mitchell <mmitchell@usa.net>
+
+ * integrate.c (get_label_from_map): New function.
+ (expand_inline_function): Use it.
+ Initialize label_map to NULL_RTX instead of gen_label_rtx.
+ (copy_rtx_and_substitute): Use get_label_from_map.
+ * integrate.h (get_label_from_map): New function.
+ (set_label_from_map): New macro.
+ * unroll.c (unroll_loop, copy_loop_body): Use them.
+
+Mon Feb 2 16:33:01 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * i386.md (mov{si,hi,sf,df,xf}cc{,_1}): Remove cases with branches.
+
+ * rs6000/x-aix31 (INSTALL): Deleted.
+ * mips/x-dec-osf1, mips/x-osfrose, i386/x-osfrose: Likewise.
+ * arm/x-riscix: Likewise.
+
+ * c-typeck.c (signed_or_unsigned_type): Properly handle pointer types.
+
+Mon Feb 2 15:33:58 1998 Michael P. Hayes <michaelh@ongaonga.chch.cri.nz>
+
+ * unroll.c (copy_loop_body): Use single_set instead of
+ PATTERN to detect increment of an iv inside a PARALLEL.
+
+Fri Jan 16 20:29:50 1998 Paul Eggert <eggert@twinsun.com>
+
+ * toplev.c (<unistd.h>): New include.
+ (get_run_time): Prefer CLK_TCK (if available) to HZ, and
+ prefer sysconf (_SC_CLK_TCK) (if available) to CLK_TCK.
+ * configure.in (sysconf): Call AC_CHECK_FUNCS.
+
+Wed Jan 14 20:10:51 1998 Paul Eggert <eggert@twinsun.com>
+
+ * cccp.c: (rescan): Don't report line 0 as the possible real start
+ of an unterminated string constant.
+ Don't mishandle backslash-newlines that in are the output of
+ a macro expansion. Properly skip // style comments between a function
+ macro name and '(', as well as backslash-newlines in comments there.
+ (handle_directive): Handle / \ newline * between # and directive name.
+ In #include directives, \ does not escape ".
+ (do_include): For `#include "file', do not bother expanding into temp
+ buffer. When error encountered when expanding, do not try result.
+ (skip_if_group): When skipping an include directive, use include
+ tokenization, not normal tokenization. Backslash-newline is still
+ special when skipping. Handle * \ newline / correctly in comments
+ when skipping.
+ (skip_quoted_string): After \ newline, set *backslash_newlines_p
+ even if count_newlines is 0.
+ (macroexpand): Newline space is not a special marker inside a string.
+ (macroexpand, macarg): Do not generate \ddd for control characters
+ when stringifying; the C Standard does not allow this.
+ (macarg1): New arg MACRO. All callers changed.
+ Do not treat /*, //, or backslash-newline specially when processing
+ the output of a macro.
+ (discard_comments): Don't go past limit if looking for end of comment.
+ Discard backslash-newline properly when discarding comments.
+ (change_newlines): \" does not end a string.
+ (make_definition): Do not treat backslash-newline specially, as it
+ has already been removed before we get here.
+
+ * profile.c (output_func_start_profiler): Don't fflush output
+ if -quiet.
+ * toplev.c (rest_of_compilation): Likewise.
+
+ * i386/x-sco5 (CC): Remove trailing white space.
+ * x-convex (CCLIBFLAGS): Likewise.
+ * arm/t-semi (LIBGCC2_CFLAGS): Likewise.
+
+Wed Jan 7 18:02:42 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * Version 2.8.0 released.
+
+Wed Jan 7 17:54:41 1998 J. Kean Johnston <jkj@sco.com>
+
+ * i386/sco5.h ({END,START}FILE_SPEC): Link with correct crtbegin.o
+ and crtend.o when using -static.
+
+Wed Jan 7 17:49:14 1998 Jan Christiaan van Winkel <Jan.Christiaan.van.Winkel@ATComputing.nl>
+
+ * cppexp.c (gansidecl.h): Include.
+
+Wed Jan 7 17:45:07 1998 Tristan Gingold <gingold@puccini.enst.fr>
+
+ * expr.c (get_push_address): Use copy_to_reg instead of force_operand.
+ (emit_push_insn): Avoid null pointer deference if aggregate has no
+ types.
+ (expand_expr): Avoid finite but useless recursion.
+ (expand_builtin): Fix typo in calling function.
+ * function.c (assign_parms): Avoid useless call to chkr_set_right.
+
+Wed Jan 7 17:31:13 1998 Christian Iseli <Christian.Iseli@lslsun.epfl.ch>
+
+ * combine.c (force_to_mode): Return if operand is a CLOBBER.
+
+Wed Jan 7 17:23:24 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * x-rs6000 (INSTALL): Remove.
+
+ * jump.c (jump_optimize): Don't use a hard reg as an operand
+ of a conditional move if small register classes.
+
+Wed Jan 7 17:09:28 1998 Jim Wilson <wilson@cygnus.com>
+
+ * cse.c (max_insn_uid): New variable.
+ (cse_around_loop): Use it.
+ (cse_main): Set it.
+
+See ChangeLog.11 for earlier changes.
+
+Use a consistent time stamp format in ChangeLog entries.
+Not everyone has Emacs 20 yet, so stick with Emacs 19 format for now.
+
+Local Variables:
+add-log-time-format: current-time-string
+End:
diff --git a/contrib/gcc/LANGUAGES b/contrib/gcc/LANGUAGES
index bce134c..c3d4223 100644
--- a/contrib/gcc/LANGUAGES
+++ b/contrib/gcc/LANGUAGES
@@ -6,6 +6,18 @@ time as we can formally start documenting the interface this file will
serve as a repository for information on these interface and any incompatable
changes we've made.
+Aug 31, 1998:
+ The interface to HANDLE_PRAGMA has changed. It now takes three arguments.
+ The first two are pointers to functions that should be used to read characters
+ from the input stream, and to push them back into the input stream respectively.
+ The third argument is a pointer to a null terminate string which is the first
+ word after #pragma. The expression supplied by HANDLE_PRAGMA should return
+ non-zero if it parsed and implemented the pragma. Otherwise it should return
+ zero, and leave the input stream as it was before the expression was evaluated.
+
+ A new back-end definable macro has been added: INSERT_ATTRIBUTES. This macro
+ allows backend to add attributes to decls as they are created.
+
Jun 10, 1998:
The interface to lang_decode_option has changed. It now uses and argc/argv
interface to allow for options that use more than one input string. The new
diff --git a/contrib/gcc/Makefile.in b/contrib/gcc/Makefile.in
index 15a789e..0240f72 100644
--- a/contrib/gcc/Makefile.in
+++ b/contrib/gcc/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for GNU C compiler.
-# Copyright (C) 1987, 88, 90-97, 1998 Free Software Foundation, Inc.
+# Copyright (C) 1987, 88, 90-98, 1999 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -39,7 +39,13 @@ SUBDIRS =@subdirs@
# Selection of languages to be made.
# This is overridden by configure.
-LANGUAGES = c proto gcov$(exeext) @all_languages@
+CONFIG_LANGUAGES = @all_languages@
+LANGUAGES = c proto gcov$(exeext) $(CONFIG_LANGUAGES)
+
+# Languages should create dependencies of $(INTL_TARGETS) on generated
+# sources in Make-lang.in. Example:
+# $(INTL_TARGETS): $(srcdir)/cp/parse.c
+INTL_TARGETS = intl.all intl.install intl.distdir
# Selection of languages to be made during stage1 build.
# This is overridden by configure.
@@ -53,7 +59,8 @@ ALLOCA_FINISH = true
# CFLAGS is for the user to override to, e.g., do a bootstrap with -O2.
# BOOT_CFLAGS is the value of CFLAGS to pass
# to the stage2 and stage3 compilations
-# WARN_CFLAGS are the warning flags to pass to stage2 and stage3. It is
+# WARN_CFLAGS are the warning flags to pass to stage2 and stage3.
+# (And for stage 1 if the native compiler is GCC.) It is
# separate from BOOT_CFLAGS because people tend to override optimization
# flags and we'd like them to still have warnings turned on. They are free
# to explicitly turn warnings off if they wish.
@@ -61,9 +68,10 @@ ALLOCA_FINISH = true
# TCFLAGS is used for compilations with the GCC just built.
XCFLAGS =
TCFLAGS =
+# -W -Wall warnings are disabled for releases.
CFLAGS = -g
BOOT_CFLAGS = -O2 $(CFLAGS)
-WARN_CFLAGS =
+#WARN_CFLAGS = -W -Wall
# These exists to be overridden by the x-* and t-* files, respectively.
X_CFLAGS =
T_CFLAGS =
@@ -71,6 +79,7 @@ T_CFLAGS =
X_CPPFLAGS =
T_CPPFLAGS =
+AWK = @AWK@
CC = @CC@
# srcdir might be a relative pathname which won't be valid in a subdirectory,
# so we must use objdir/srcdir instead to make it safe. objdir is always
@@ -78,7 +87,7 @@ CC = @CC@
BISON = `if [ -f $(objdir)/../bison/bison ] ; then case $(srcdir) in \
/*) echo $(objdir)/../bison/bison -L $(srcdir)/../bison/ ;; \
*) echo $(objdir)/../bison/bison -L $(objdir)/$(srcdir)/../bison/ ;; \
- esac else echo bison ; fi`
+ esac; else echo bison ; fi`
BISONFLAGS =
LEX = `if [ -f $(objdir)/../flex/flex ] ; then echo $(objdir)/../flex/flex ; else echo flex ; fi`
LEXFLAGS =
@@ -96,7 +105,9 @@ LN_S=@LN_S@
# These permit overriding just for certain files.
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
-MAKEINFO = makeinfo
+MAKEINFO = `if [ -f $(objdir)/../texinfo/makeinfo/Makefile ] ; \
+ then echo $(objdir)/../texinfo/makeinfo/makeinfo ; \
+ else echo makeinfo ; fi`
MAKEINFOFLAGS =
TEXI2DVI = texi2dvi
# For GNUmake: let us decide what gets passed to recursive makes.
@@ -111,7 +122,9 @@ P =
# How to invoke ranlib.
RANLIB = ranlib
# Test to use to see whether ranlib exists on the system.
-RANLIB_TEST = [ -f /usr/bin/ranlib -o -f /bin/ranlib ]
+RANLIB_TEST = \
+ [ -f $(RANLIB) ] \
+ || [ -f /usr/bin/ranlib -o -f /bin/ranlib ]
# Compiler to use for compiling libgcc1.a.
# OLDCC should not be the GNU C compiler,
@@ -144,7 +157,7 @@ USER_H = $(srcdir)/ginclude/stdarg.h $(srcdir)/ginclude/stddef.h \
$(srcdir)/ginclude/va-m32r.h $(srcdir)/ginclude/va-sh.h \
$(srcdir)/ginclude/va-v850.h $(srcdir)/ginclude/va-arc.h \
$(srcdir)/ginclude/iso646.h $(srcdir)/ginclude/va-ppc.h \
- $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) \
+ $(srcdir)/ginclude/va-c4x.h $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) \
$(srcdir)/ginclude/proto.h $(srcdir)/ginclude/stdbool.h
# Target to use whe installing assert.h. Some systems may
@@ -154,7 +167,7 @@ INSTALL_ASSERT_H = install-assert-h
# The GCC to use for compiling libgcc2.a, enquire, and libgcc1-test.
# Usually the one we just built.
# Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS).
-GCC_FOR_TARGET = ./xgcc -B./
+GCC_FOR_TARGET = ./xgcc -B$(build_tooldir)/bin/ -B./ -I$(build_tooldir)/include
# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
# It omits XCFLAGS, and specifies -B./.
@@ -187,7 +200,7 @@ AR_FOR_TARGET = ` \
t='$(program_transform_name)'; echo ar | sed -e $$t ; \
fi; \
fi`
-AR_FOR_TARGET_FLAGS = rc
+AR_FLAGS_FOR_TARGET = rc
RANLIB_FOR_TARGET = ` \
if [ -f $(objdir)/../binutils/ranlib ] ; then \
echo $(objdir)/../binutils/ranlib ; \
@@ -203,18 +216,6 @@ RANLIB_TEST_FOR_TARGET = \
|| ( [ "$(host_canonical)" = "$(target)" ] \
&& [ -f /usr/bin/ranlib -o -f /bin/ranlib ] )
-# We always act like a cross-compiler, even when we're
-# compiling native. This is because we want to use our own tools if
-# we can. We don't just set RANLIB to a complicated expression,
-# because the top level Makefile.in might override RANLIB_FOR_TARGET.
-# These are from the FSF file "cross-make".
-AR = $(AR_FOR_TARGET)
-AR_FLAGS = $(AR_FOR_TARGET_FLAGS)
-OLDAR = $(AR_FOR_TARGET)
-OLDAR_FLAGS = $(AR_FOR_TARGET_FLAGS)
-RANLIB = $(RANLIB_FOR_TARGET)
-RANLIB_TEST = $(RANLIB_TEST_FOR_TARGET)
-
# Dir to search for system headers. Overridden by cross-make.
SYSTEM_HEADER_DIR = /usr/include
@@ -243,7 +244,10 @@ build_xm_file=@build_xm_file_list@
host_xm_file=@host_xm_file_list@
lang_specs_files=@lang_specs_files@
lang_options_files=@lang_options_files@
+lang_tree_files=@lang_tree_files@
GCC_THREAD_FILE=@thread_file@
+OBJC_BOEHM_GC=@objc_boehm_gc@
+JAVAGC=@JAVAGC@
GTHREAD_FLAGS=@gthread_flags@
# Be prepared for gcc2 merges.
gcc_version=@gcc_version@
@@ -267,21 +271,28 @@ bindir = @bindir@
libdir = @libdir@
# Directory in which the compiler finds executables, libraries, etc.
libsubdir = $(libdir)/gcc-lib/$(target_alias)/$(version)
+# Used to produce a relative $(gcc_tooldir) in gcc.o
+unlibsubdir = ../../..
+# Directory in which to find other cross-compilation tools and headers.
+dollar = @dollar@
+# Used in install-cross.
+gcc_tooldir = @gcc_tooldir@
+# Since tooldir does not exist at build-time, use -B$(build_tooldir)/bin/
+build_tooldir = $(exec_prefix)/$(target_alias)
# Directory in which the compiler finds g++ includes.
-gxx_include_dir= @gxx_include_dir@
-# Directory in which the old g++ header files may be found.
-# The reason we use $(libdir)/g++-include rather than using libsubdir
-# is for compatibility with older versions of libg++.
-old_gxx_include_dir= $(libdir)/g++-include
+gcc_gxx_include_dir= @gcc_gxx_include_dir@
# Directory to search for site-specific includes.
includedir = $(local_prefix)/include
# assertdir is overridden in cross-make.
# (But this currently agrees with what is in cross-make.)
-assertdir = $(tooldir)/include
+assertdir = $(gcc_tooldir)/include
# where the info files go
infodir = @infodir@
# Where cpp should go besides $prefix/bin if necessary
cpp_install_dir = @cpp_install_dir@
+# where the locale files go
+datadir = $(prefix)/@DATADIRNAME@
+localedir = $(datadir)/locale
# Extension (if any) to put in installed man-page filename.
manext = .1
objext = .o
@@ -289,13 +300,24 @@ exeext = @host_exeext@
build_exeext = @build_exeext@
# Directory in which to put man pages.
-mandir = @mandir@/man1
-# Directory in which to find other cross-compilation tools and headers.
-# Used in install-cross.
-tooldir = $(exec_prefix)/$(target_alias)
+mandir = @mandir@
+man1dir = $(mandir)/man1
# Dir for temp files.
tmpdir = /tmp
+# Top build directory, relative to here.
+top_builddir = .
+
+# Whether we were configured with NLS.
+USE_NLS = @USE_NLS@
+
+# Internationalization library.
+INTLLIBS = @INTLLIBS@
+
+# List of internationalization subdirectories.
+POSUB = @POSUB@
+INTL_SUBDIRS = intl $(POSUB)
+
# Additional system libraries to link with.
CLIB=
@@ -372,6 +394,9 @@ EXTRA_HEADERS =@extra_headers_list@
# Set this to `collect2' to enable use of collect2.
USE_COLLECT2 = @will_use_collect2@
+# If we might be using collect2, then this variable will be set to
+# -DUSE_COLLECT2. toplev.c, collect2.c and libgcc2.c all need to
+# if we may be using collect2.
MAYBE_USE_COLLECT2 = @maybe_use_collect2@
# It is convenient for configure to add the assignment at the beginning,
# so don't override it here.
@@ -389,13 +414,9 @@ LIB2FUNCS_EXTRA =
INSTALL_CPP=
UNINSTALL_CPP=
-# Default float.h source to use for cross-compiler.
-# This is overridden by configure.
-CROSS_FLOAT_H=$(srcdir)/config/float-@float_format@.h
-
# We do not try to build float.h anymore. Let configure select the
# appropriate pre-built float.h file for the target.
-FLOAT_H=$(srcdir)/config/float-@float_format@.h
+FLOAT_H=@float_h_file@
# Program to convert libraries.
LIBCONVERT =
@@ -406,10 +427,6 @@ INSTALL_HEADERS=install-headers
# Options for tar when copying trees. So HPUX can override it.
TAROUTOPTS = xpBf
-# Select which version of fixincludes to use (I.E. regular versus SVR4)
-# This value is overridden directly by configure.
-FIXINCLUDES = @fixincludes@
-
# Additional directories of header files to run fixincludes on.
# These should be directories searched automatically by default
# just as /usr/include is.
@@ -449,6 +466,7 @@ HOST_PREFIX_1=loser-
HOST_CC=$(CC)
HOST_CFLAGS=$(ALL_CFLAGS)
HOST_CLIB=$(CLIB)
+HOST_INTLLIBS=$(INTLLIBS)
HOST_LDFLAGS=$(LDFLAGS)
HOST_CPPFLAGS=$(ALL_CPPFLAGS)
HOST_ALLOCA=$(ALLOCA)
@@ -459,8 +477,10 @@ HOST_DOPRINT=$(DOPRINT)
# Actual name to use when installing a native compiler.
GCC_INSTALL_NAME = `t='$(program_transform_name)'; echo gcc | sed -e $$t`
+CPP_INSTALL_NAME = `t='$(program_transform_name)'; echo cpp | sed -e $$t`
PROTOIZE_INSTALL_NAME = `t='$(program_transform_name)'; echo protoize | sed -e $$t`
UNPROTOIZE_INSTALL_NAME = `t='$(program_transform_name)'; echo unprotoize | sed -e $$t`
+GCOV_INSTALL_NAME = `t='$(program_transform_name)'; echo gcov | sed -e $$t`
# Actual name to use when installing a cross-compiler.
GCC_CROSS_NAME = `t='$(program_transform_cross_name)'; echo gcc | sed -e $$t`
@@ -524,13 +544,14 @@ all: all.indirect
all.indirect: $(ALL)
-# IN_GCC tells obstack.h that we are using gcc's <stddef.h> file.
-# ??? IN_GCC should be obsolete now.
-INTERNAL_CFLAGS = $(CROSS) -DIN_GCC @extra_c_flags@
+# IN_GCC tells various files that system.h, toplev.c, etc are available.
+INTERNAL_CFLAGS = $(CROSS) -DIN_GCC $(SCHED_CFLAGS) @extra_c_flags@
# This is the variable actually used when we compile.
+# If you change this line, you probably also need to change the definition
+# of HOST_CFLAGS in build-make to match.
ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS) \
- @DEFS@ $(SCHED_CFLAGS)
+ @DEFS@
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
@@ -546,21 +567,22 @@ USE_HOST_DOPRINT= ` case "${HOST_DOPRINT}" in ?*) echo ${HOST_PREFIX}${HOST_DOPR
# Dependency on obstack, alloca, malloc or whatever library facilities
# are not installed in the system libraries.
# We don't use USE_ALLOCA because backquote expansion doesn't work in deps.
-LIBDEPS= $(OBSTACK) $(ALLOCA) $(MALLOC) $(VFPRINTF) $(DOPRINT)
+LIBDEPS= $(INTLLIBS) $(OBSTACK) $(ALLOCA) $(MALLOC) $(VFPRINTF) $(DOPRINT)
# Likewise, for use in the tools that must run on this machine
# even if we are cross-building GCC.
# We don't use USE_ALLOCA because backquote expansion doesn't work in deps.
-HOST_LIBDEPS= $(HOST_PREFIX)$(HOST_OBSTACK) $(HOST_PREFIX)$(HOST_ALLOCA) $(HOST_PREFIX)$(HOST_MALLOC) $(HOST_PREFIX)$(HOST_VFPRINTF) $(HOST_PREFIX)$(HOST_DOPRINT)
+HOST_LIBDEPS= $(HOST_PREFIX)$(HOST_INTLLIBS) $(HOST_PREFIX)$(HOST_OBSTACK) $(HOST_PREFIX)$(HOST_ALLOCA) $(HOST_PREFIX)$(HOST_MALLOC) $(HOST_PREFIX)$(HOST_VFPRINTF) $(HOST_PREFIX)$(HOST_DOPRINT)
# How to link with both our special library facilities
# and the system's installed libraries.
-LIBS = $(OBSTACK) $(USE_ALLOCA) $(MALLOC) $(VFPRINTF) $(DOPRINT) $(CLIB)
+LIBS = $(OBSTACK) $(USE_ALLOCA) $(MALLOC) $(INTLLIBS) @LIBS@ $(VFPRINTF) $(DOPRINT) $(CLIB) ../libiberty/libiberty.a
# Likewise, for use in the tools that must run on this machine
# even if we are cross-building GCC.
HOST_LIBS = $(USE_HOST_OBSTACK) $(USE_HOST_ALLOCA) $(USE_HOST_MALLOC) \
- $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) $(HOST_CLIB)
+ $(HOST_INTLLIBS) $(USE_HOST_VFPRINTF) $(USE_HOST_DOPRINT) \
+ $(HOST_CLIB)
HOST_RTL = $(HOST_PREFIX)rtl.o $(HOST_PREFIX)bitmap.o
HOST_RTLANAL = $(HOST_PREFIX)rtlanal.o
@@ -570,7 +592,7 @@ HOST_PRINT = $(HOST_PREFIX)print-rtl.o
# Both . and srcdir are used, in that order,
# so that tm.h and config.h will be found in the compilation
# subdirectory rather than in the source directory.
-INCLUDES = -I. -I$(srcdir) -I$(srcdir)/config
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/config -I$(srcdir)/../include
# Always use -I$(srcdir)/config when compiling.
.c.o:
@@ -595,12 +617,11 @@ LANG_EXTRA_HEADERS = @all_headers@
# because we need CC="stage1/xgcc -Bstage1/" to work in the language
# subdirectories.
# ??? The choices here will need some experimenting with.
-FLAGS_TO_PASS = \
- "AR_FLAGS=$(AR_FOR_TARGET_FLAGS)" \
+ORDINARY_FLAGS_TO_PASS = \
+ "AR_FLAGS_FOR_TARGET=$(AR_FLAGS_FOR_TARGET)" \
"AR_FOR_TARGET=$(AR_FOR_TARGET)" \
"BISON=$(BISON)" \
"BISONFLAGS=$(BISONFLAGS)" \
- "CC=@cc_set_by_configure@" \
"CFLAGS=$(CFLAGS)" \
"CLIB=$(CLIB)" \
"GCC_FOR_TARGET=$(GCC_FOR_TARGET)" \
@@ -621,10 +642,23 @@ FLAGS_TO_PASS = \
"exec_prefix=$(exec_prefix)" \
"prefix=$(prefix)" \
"local_prefix=$(local_prefix)" \
- "gxx_include_dir=$(gxx_include_dir)" \
+ "gxx_include_dir=$(gcc_gxx_include_dir)" \
"tooldir=$(tooldir)" \
+ "gcc_tooldir=$(gcc_tooldir)" \
"bindir=$(bindir)" \
- "libsubdir=$(libsubdir)"
+ "libsubdir=$(libsubdir)" \
+ "datadir=$(datadir)" \
+ "distdir=../tmp/\$$(subdir)" \
+ "localedir=$(localedir)"
+FLAGS_TO_PASS = $(ORDINARY_FLAGS_TO_PASS) "CC=@cc_set_by_configure@"
+PREPEND_DOTDOT_TO_RELATIVE_PATHS = sed \
+ -e 's|^ *[^ /][^ /]*/|%&|' \
+ -e 's| -B| -B%|g' \
+ -e 's|% *[^- /]|%&|g' \
+ -e 's|%% *|../|g' \
+ -e 's|%||g'
+SUBDIR_FLAGS_TO_PASS = $(ORDINARY_FLAGS_TO_PASS) \
+ "CC=`echo @quoted_cc_set_by_configure@ | $(PREPEND_DOTDOT_TO_RELATIVE_PATHS)`"
#
# Lists of files for various purposes.
@@ -641,14 +675,14 @@ SCHED_CFLAGS = @sched_cflags@
# Language-independent object files.
OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \
function.o stmt.o except.o expr.o calls.o expmed.o explow.o optabs.o \
- varasm.o rtl.o print-rtl.o rtlanal.o emit-rtl.o genrtl.o real.o regmove.o \
- dbxout.o sdbout.o dwarfout.o dwarf2out.o xcoffout.o bitmap.o alias.o \
+ intl.o varasm.o rtl.o print-rtl.o rtlanal.o emit-rtl.o genrtl.o real.o \
+ dbxout.o sdbout.o dwarfout.o dwarf2out.o xcoffout.o bitmap.o alias.o gcse.o \
integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.o combine.o varray.o \
- regclass.o local-alloc.o global.o reload.o reload1.o caller-save.o gcse.o \
+ regclass.o regmove.o local-alloc.o global.o reload.o reload1.o caller-save.o \
insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \
- insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o \
+ insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \
profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \
- dyn-string.o
+ mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o
# GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
@@ -661,7 +695,7 @@ CCCP=@cpp_main@
# Files to be copied away after each stage in building.
STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
- insn-attr.h insn-attrtab.c insn-opinit.c genrtl.c genrtl.h tree-check.h \
+ insn-attr.h insn-attrtab.c insn-opinit.c tree-check.h \
s-flags s-config s-codes s-mlib s-under\
s-output s-recog s-emit s-extract s-peep s-check \
s-attr s-attrtab s-opinit s-crt s-crtS s-crt0 \
@@ -670,15 +704,15 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
genconfig$(build_exeext) genpeep$(build_exeext) genattrtab$(build_exeext) \
genattr$(build_exeext) genopinit$(build_exeext) gengenrtl$(build_exeext) \
gencheck$(build_exeext) \
- xgcc$(exeext) cc1$(exeext) cpp$(exeext) $(EXTRA_PASSES) \
+ xgcc$(exeext) xcpp$(exeext) cc1$(exeext) cpp$(exeext) $(EXTRA_PASSES) \
$(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
$(CCCP)$(exeext) cc1obj$(exeext) enquire$(exeext) \
protoize$(exeext) unprotoize$(exeext) \
specs collect2$(exeext) $(USE_COLLECT2) underscore.c \
gcov$(exeext) *.bp \
*.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop \
- *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.gcse \
- *.[si] \
+ *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.gcse *.flow2 \
+ *.[si] libcpp.a \
$(LANG_STAGESTUFF)
# Members of libgcc1.a.
@@ -721,14 +755,14 @@ DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \
# If it is, rm *.o is an easy way to do it.
# CONFIG_H = $(host_xm_file) $(tm_file)
CONFIG_H =
-RTL_BASE_H = rtl.h rtl.def gansidecl.h machmode.h machmode.def
+RTL_BASE_H = rtl.h rtl.def machmode.h machmode.def
RTL_H = $(RTL_BASE_H) genrtl.h
-TREE_H = tree.h real.h tree.def gansidecl.h machmode.h machmode.def tree-check.h
-BASIC_BLOCK_H = basic-block.h bitmap.h
-DEMANGLE_H = demangle.h gansidecl.h
-RECOG_H = recog.h gansidecl.h
+TREE_H = tree.h real.h tree.def machmode.h machmode.def tree-check.h
+BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h
+DEMANGLE_H = $(srcdir)/../include/demangle.h
+RECOG_H = recog.h
EXPR_H = expr.h insn-codes.h
-REGS_H = regs.h varray.h machmode.h machmode.def gansidecl.h
+REGS_H = regs.h varray.h machmode.h machmode.def
#
# Language makefile fragments.
@@ -764,7 +798,7 @@ Makefile: $(srcdir)/Makefile.in config.status $(srcdir)/version.c \
$(SHELL) $(srcdir)/configure.frag $(srcdir) "$(SUBDIRS)" \
"$(xmake_file)" "$(tmake_file)"
cp config.status config.run
- $(SHELL) config.run
+ LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.run
rm -f config.run
$(srcdir)/configure: $(srcdir)/configure.in
@@ -786,7 +820,7 @@ $(srcdir)/cstamp-h.in: $(srcdir)/configure.in $(srcdir)/acconfig.h
echo timestamp > $(srcdir)/cstamp-h.in
auto-host.h: cstamp-h ; @true
cstamp-h: config.in config.status
- CONFIG_HEADERS=auto-host.h:config.in $(SHELL) config.status
+ CONFIG_HEADERS=auto-host.h:config.in LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status
# Really, really stupid make features, such as SUN's KEEP_STATE, may force
# a target to build even if it is up-to-date. So we must verify that
@@ -796,24 +830,25 @@ config.status: configure version.c
echo You must configure gcc. Look at the INSTALL file for details.; \
false; \
else \
- $(SHELL) config.status --recheck; \
+ LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status --recheck; \
fi
-all.internal: start.encap rest.encap
+all.internal: start.encap rest.encap doc
# This is what to compile if making a cross-compiler.
# Note that we can compile enquire using the cross-compiler just built,
# although we can't run it on this machine.
all.cross: native gcc-cross specs stmp-headers $(STMP_FIXPROTO) $(LIBGCC) \
- $(LIBGCC1_TEST) $(EXTRA_PARTS) lang.all.cross
+ $(LIBGCC1_TEST) $(EXTRA_PARTS) lang.all.cross doc
# This is what to compile if making gcc with a cross-compiler.
-all.build: native xgcc$(exeext) $(EXTRA_PARTS) lang.all.build
+all.build: native xgcc$(exeext) xcpp$(exeext) $(EXTRA_PARTS) lang.all.build
# This is what must be made before installing GCC and converting libraries.
-start.encap: native xgcc$(exeext) specs $(LIBGCC1) xlimits.h lang.start.encap
+start.encap: native xgcc$(exeext) xcpp$(exeext) specs $(LIBGCC1) \
+ xlimits.h lang.start.encap
# These can't be made until after GCC can run.
rest.encap: stmp-headers $(STMP_FIXPROTO) $(LIBGCC) $(EXTRA_PARTS) lang.rest.encap
# This is what is made with the host's compiler
# whether making a cross compiler or not.
-native: config.status auto-host.h cpp$(exeext) $(LANGUAGES) \
+native: config.status auto-host.h cpp$(exeext) intl.all $(LANGUAGES) \
$(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2)
# Define the names for selecting languages in LANGUAGES.
@@ -825,7 +860,7 @@ PROTO: proto
# On the target machine, finish building a cross compiler.
# This does the things that can't be done on the host machine.
-rest.cross: $(LIBGCC) gfloat.h specs
+rest.cross: $(LIBGCC) specs
# Verify that it works to compile and link libgcc1-test.
# If it does, then there are sufficient replacements for libgcc1.a.
@@ -848,10 +883,20 @@ stamp-objlist: $(OBJS)
# We call this executable `xgcc' rather than `gcc'
# to avoid confusion if the current directory is in the path
# and CC is `gcc'. It is renamed to `gcc' when it is installed.
-xgcc$(exeext): gcc.o version.o choose-temp.o pexecute.o prefix.o version.o \
- mkstemp.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o prefix.o version.o \
- choose-temp.o pexecute.o mkstemp.o $(EXTRA_GCC_OBJS) $(LIBS)
+xgcc$(exeext): gcc.o gccspec.o version.o intl.o prefix.o \
+ version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o gccspec.o intl.o \
+ prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+
+# We call this executable `xcpp' rather than `cpp'
+# since the real preprocessor is named `cpp'. It too is renamed
+# when it is installed.
+# The only difference from xgcc is that it's linked with cppspec.o
+# instead of gccspec.o.
+xcpp$(exeext): gcc.o cppspec.o version.o intl.o prefix.o \
+ version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o cppspec.o intl.o \
+ prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
# Dump a specs file to make -B./ read these specs over installed ones.
specs: xgcc$(exeext)
@@ -864,13 +909,8 @@ specs: xgcc$(exeext)
gcc-cross: xgcc$(exeext)
cp xgcc$(exeext) gcc-cross$(exeext)
-cc1$(exeext): $(P) $(C_OBJS) $(OBJS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(OBJS) $(LIBS)
-
-# Copy float.h from its source.
-gfloat.h: $(FLOAT_H)
- -rm -f gfloat.h
- cp $(FLOAT_H) gfloat.h
+cc1$(exeext): $(P) $(OBJS) $(C_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(C_OBJS) $(LIBS)
# Build the version of limits.h that we will install.
xlimits.h: glimits.h limitx.h limity.h
@@ -897,7 +937,7 @@ libgcc1.conv: libgcc1.a
libgcc1.null: $(GCC_PASSES)
echo "void __foo () {}" > dummy.c
$(GCC_FOR_TARGET) $(GCC_CFLAGS) -c dummy.c
- $(OLDAR) $(OLDAR_FLAGS) libgcc1.null dummy$(objext)
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) libgcc1.null dummy$(objext)
rm -f dummy$(objext) dummy.c
# This is $(LIBGCC1) for a cross-compiler.
@@ -957,7 +997,9 @@ libgcc1.a: libgcc1.c $(CONFIG_H) $(LIB1FUNCS_EXTRA) config.status
else true; \
fi; \
done
- -if $(RANLIB_TEST) ; then $(RANLIB) tmplibgcc1.a; else true; fi
+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
+ $(RANLIB_FOR_TARGET) tmplibgcc1.a; \
+ else true; fi
mv tmplibgcc1.a libgcc1.a
# Build libgcc1.a from assembler source. LIB1ASMFUNCS is the list of
@@ -980,7 +1022,7 @@ libgcc1-asm.a: libgcc2.ready config.status $(srcdir)/config/$(LIB1ASMSRC)
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c -DL$${name} libgcc1.S; \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
mv libgcc1$(objext) $${name}$(objext); \
- $(AR) $(AR_FLAGS) tmplibgcc1.a $${name}$(objext); \
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc1.a $${name}$(objext); \
rm -f $${name}$(objext); \
done
-rm -f libgcc1.S
@@ -1015,7 +1057,7 @@ libgcc2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs $(STMP_FIXPROTO)
LIB2ADD = $(srcdir)/frame.c $(LIB2FUNCS_EXTRA) $(LANG_LIB2FUNCS)
libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
- machmode.h longlong.h frame.h gansidecl.h gbl-ctors.h config.status
+ machmode.h longlong.h frame.h gbl-ctors.h config.status
# Actually build it in tmplibgcc2.a, then rename at end,
# so that libgcc2.a itself remains nonexistent if compilation is aborted.
-rm -f tmplibgcc2.a
@@ -1029,9 +1071,9 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
do \
echo $${name}; \
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c -DL$${name} \
- $(srcdir)/libgcc2.c -o $${name}$(objext); \
+ $(MAYBE_USE_COLLECT2) $(srcdir)/libgcc2.c -o $${name}$(objext); \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
- $(AR) $(AR_FLAGS) tmplibgcc2.a $${name}$(objext); \
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${name}$(objext); \
rm -f $${name}$(objext); \
done
for name in $(LIB2FUNCS_EH); \
@@ -1040,7 +1082,7 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -fexceptions $(INCLUDES) -c \
-DL$${name} $(srcdir)/libgcc2.c -o $${name}$(objext); \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
- $(AR) $(AR_FLAGS) tmplibgcc2.a $${name}$(objext); \
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${name}$(objext); \
rm -f $${name}$(objext); \
done
if [ x$(FPBIT) != x ]; then \
@@ -1050,7 +1092,7 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c -DL$${name} \
-DFINE_GRAINED_LIBRARIES $(FPBIT) -o $${name}$(objext); \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
- $(AR) $(AR_FLAGS) tmplibgcc2.a $${name}$(objext); \
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${name}$(objext); \
rm -f $${name}$(objext); \
done; \
else true; fi;
@@ -1061,7 +1103,7 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c -DL$${name} \
-DFINE_GRAINED_LIBRARIES $(DPBIT) -o $${name}$(objext); \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
- $(AR) $(AR_FLAGS) tmplibgcc2.a $${name}$(objext); \
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${name}$(objext); \
rm -f $${name}$(objext); \
done; \
else true; fi;
@@ -1077,13 +1119,14 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
if [ $${name}.txt = $${file} ]; then \
for f in .. `cat $${file}`; do if [ x$${f} != x.. ]; then \
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" CC="$(CC)" \
+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" CC="$(CC)" \
CFLAGS="$(CFLAGS)" HOST_PREFIX="$(HOST_PREFIX)" \
HOST_PREFIX_1="$(HOST_PREFIX_1)" \
LANGUAGES="$(LANGUAGES)" \
LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" $${f}; \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
- $(AR) $(AR_FLAGS) tmplibgcc2.a $${f}; \
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${f}; \
rm -f $${f}; \
else true; \
fi; done; \
@@ -1094,7 +1137,7 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
else true; fi; \
$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c $${file}; \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
- $(AR) $(AR_FLAGS) tmplibgcc2.a $${oname}$(objext); \
+ $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${oname}$(objext); \
rm -f $${name}.s $${oname}$(objext); \
fi; \
done
@@ -1102,7 +1145,9 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
# These lines were deleted from above the mv command
# because ranlibing libgcc.a itself should suffice.
# -if [ x${HPUX_GAS} = x ] ; then \
-# if $(RANLIB_TEST) ; then $(RANLIB) tmplibgcc2.a; else true; fi; \
+# if $(RANLIB_TEST_FOR_TARGET) ; then \
+# $(RANLIB_FOR_TARGET) tmplibgcc2.a;
+# else true; fi; \
# else true; fi
# Combine the various libraries into a single library, libgcc.a.
@@ -1110,7 +1155,7 @@ libgcc.a: $(LIBGCC1) $(LIBGCC2)
-rm -rf tmplibgcc.a libgcc.a tmpcopy
mkdir tmpcopy
-if [ x$(LIBGCC1) != x ]; \
- then (cd tmpcopy; $(AR) x ../$(LIBGCC1)); \
+ then (cd tmpcopy; $(AR_FOR_TARGET) x ../$(LIBGCC1)); \
else true; \
fi
# Some versions of ar (specifically the one in RISC/os 5.x), create an
@@ -1118,10 +1163,12 @@ libgcc.a: $(LIBGCC1) $(LIBGCC2)
# the second ar command tries to overwrite this file. To avoid the error
# message from ar, we make sure all files are writable.
-(cd tmpcopy; chmod +w * > /dev/null 2>&1)
- (cd tmpcopy; $(AR) x ../$(LIBGCC2))
- (cd tmpcopy; $(AR) $(AR_FLAGS) ../tmplibgcc.a *$(objext))
+ (cd tmpcopy; $(AR_FOR_TARGET) x ../$(LIBGCC2))
+ (cd tmpcopy; $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) ../tmplibgcc.a *$(objext))
rm -rf tmpcopy
- -if $(RANLIB_TEST) ; then $(RANLIB) tmplibgcc.a; else true; fi
+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
+ $(RANLIB_FOR_TARGET) tmplibgcc.a; \
+ else true; fi
# Actually build it in tmplibgcc.a, then rename at end,
# so that libgcc.a itself remains nonexistent if compilation is aborted.
mv tmplibgcc.a libgcc.a
@@ -1142,14 +1189,17 @@ s-mlib: $(srcdir)/genmultilib Makefile
# Build multiple copies of libgcc.a, one for each target switch.
stmp-multilib: $(LIBGCC1) libgcc2.c libgcc2.ready $(CONFIG_H) \
- frame.h gansidecl.h \
+ frame.h \
$(LIB2ADD) machmode.h longlong.h gbl-ctors.h config.status
for i in `$(GCC_FOR_TARGET) --print-multi-lib`; do \
dir=`echo $$i | sed -e 's/;.*$$//'`; \
flags=`echo $$i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" CC="$(CC)" CFLAGS="$(CFLAGS)" \
- RANLIB="$(RANLIB)" RANLIB_TEST="$(RANLIB_TEST)" \
+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
+ CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)" \
+ RANLIB_TEST_FOR_TARGET="$(RANLIB_TEST_FOR_TARGET)" \
LANGUAGES="$(LANGUAGES)" \
HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS) $${flags}" \
@@ -1169,7 +1219,9 @@ stmp-multilib-sub:
else true; \
fi
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
+ CC="$(CC)" CFLAGS="$(CFLAGS)" \
HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
LANGUAGES="$(LANGUAGES)" \
LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" $(LIBGCC2)
@@ -1181,7 +1233,9 @@ stmp-multilib-sub:
then true; \
else \
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
+ CC="$(CC)" CFLAGS="$(CFLAGS)" \
HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
LANGUAGES="$(LANGUAGES)" \
LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" $(LIBGCC1); \
@@ -1189,18 +1243,27 @@ stmp-multilib-sub:
rm -rf tmplibgcc.a tmpcopy
mkdir tmpcopy
if [ x$(LIBGCC1) != x ]; \
- then (cd tmpcopy; $(AR) x ../$(LIBGCC1)); \
+ then (cd tmpcopy; $(AR_FOR_TARGET) x ../$(LIBGCC1)); \
else true; \
fi
- (cd tmpcopy; $(AR) x ../$(LIBGCC2))
- (cd tmpcopy; $(AR) $(AR_FLAGS) ../tmplibgcc.a *$(objext))
+# Some versions of ar (specifically the one in RISC/os 5.x), create an
+# unwritable table of contents file, and then print an error message when
+# the second ar command tries to overwrite this file. To avoid the error
+# message from ar, we make sure all files are writable.
+ -(cd tmpcopy; chmod +w * > /dev/null 2>&1)
+ (cd tmpcopy; $(AR_FOR_TARGET) x ../$(LIBGCC2))
+ (cd tmpcopy; $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) ../tmplibgcc.a *$(objext))
rm -rf libgcc2.a tmpcopy
- if $(RANLIB_TEST) ; then $(RANLIB) tmplibgcc.a; else true; fi
+ if $(RANLIB_TEST_FOR_TARGET) ; then \
+ $(RANLIB_FOR_TARGET) tmplibgcc.a; \
+ else true; fi
if [ -d $(dir) ]; then true; else mkdir $(dir); fi
mv tmplibgcc.a $(dir)/libgcc.a
for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" CC="$(CC)" CFLAGS="$(CFLAGS)" \
+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
+ CC="$(CC)" CFLAGS="$(CFLAGS)" \
HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
LANGUAGES="$(LANGUAGES)" \
MULTILIB_CFLAGS="$(MULTILIB_CFLAGS)" T="t" t$${f}; \
@@ -1261,7 +1324,7 @@ c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) c-lex.h \
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c $(srcdir)/c-parse.c
$(srcdir)/c-parse.h: $(srcdir)/c-parse.c
$(srcdir)/c-parse.c: $(srcdir)/c-parse.y
- cd $(srcdir); $(BISON) $(BISONFLAGS) -d c-parse.y -o c-parse.c
+ cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o c-parse.c c-parse.y
$(srcdir)/c-parse.y: c-parse.in
echo '/*WARNING: This file is automatically generated!*/' >tmp-c-parse.y
sed -e "/^ifobjc$$/,/^end ifobjc$$/d" \
@@ -1270,42 +1333,56 @@ $(srcdir)/c-parse.y: c-parse.in
$(srcdir)/move-if-change tmp-c-parse.y $(srcdir)/c-parse.y
$(srcdir)/c-gperf.h: c-parse.gperf
- gperf -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$$ \
- $(srcdir)/c-parse.gperf >tmp-gperf.h
+ gperf -L C -F ', 0, 0' -p -j1 -i 1 -g -o -t -G -N is_reserved_word \
+ -k1,3,$$ $(srcdir)/c-parse.gperf >tmp-gperf.h
$(srcdir)/move-if-change tmp-gperf.h $(srcdir)/c-gperf.h
c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-lex.h flags.h \
output.h toplev.h
c-typeck.o : c-typeck.c $(CONFIG_H) system.h $(TREE_H) c-tree.h flags.h \
- output.h $(EXPR_H) $(RTL_H) toplev.h
+ intl.h output.h $(EXPR_H) $(RTL_H) toplev.h
c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-lex.h toplev.h \
output.h
c-lex.o : c-lex.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-lex.h c-tree.h \
- $(srcdir)/c-parse.h input.h flags.h $(srcdir)/c-gperf.h c-pragma.h \
- toplev.h output.h
-c-aux-info.o : c-aux-info.c $(CONFIG_H) system.h $(TREE_H) c-tree.h flags.h
+ $(srcdir)/c-parse.h input.h intl.h flags.h $(srcdir)/c-gperf.h c-pragma.h \
+ toplev.h output.h mbchar.h
+c-aux-info.o : c-aux-info.c $(CONFIG_H) system.h $(TREE_H) c-tree.h flags.h \
+ toplev.h
c-convert.o : c-convert.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h
c-pragma.o: c-pragma.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) except.h \
function.h defaults.h c-pragma.h toplev.h
c-iterate.o: c-iterate.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-tree.h \
flags.h toplev.h $(EXPR_H)
+mbchar.o: mbchar.c $(CONFIG_H) system.h mbchar.h
+graph.o: graph.c $(CONFIG_H) system.h toplev.h flags.h output.h $(RTL_H) \
+ hard-reg-set.h $(BASIC_BLOCK_H)
+sbitmap.o: sbitmap.c $(CONFIG_H) system.h $(RTL_H) flags.h $(BASIC_BLOCK_H)
-collect2$(exeext): collect2.o tlink.o hash.o cplus-dem.o underscore.o \
- version.o choose-temp.o mkstemp.o $(LIBDEPS)
+COLLECT2_OBJS = collect2.o tlink.o hash.o intl.o underscore.o version.o
+collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
# Don't try modifying collect2 (aka ld) in place--it might be linking this.
-rm -f collect2$(exeext)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ collect2.o tlink.o hash.o \
- cplus-dem.o underscore.o version.o choose-temp.o mkstemp.o $(LIBS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(COLLECT2_OBJS) $(LIBS)
-collect2.o : collect2.c $(CONFIG_H) system.h gansidecl.h gstab.h obstack.h \
- $(DEMANGLE_H)
+collect2.o : collect2.c $(CONFIG_H) system.h gstab.h intl.h \
+ $(srcdir)/../include/obstack.h $(DEMANGLE_H) collect2.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DTARGET_MACHINE=\"$(target_alias)\" $(MAYBE_USE_COLLECT2) \
-c `echo $(srcdir)/collect2.c | sed 's,^\./,,'`
-tlink.o: tlink.c $(DEMANGLE_H) hash.h $(CONFIG_H) system.h toplev.h
+tlink.o: tlink.c $(DEMANGLE_H) hash.h $(CONFIG_H) system.h toplev.h collect2.h
hash.o: hash.c hash.h system.h toplev.h
-cplus-dem.o: cplus-dem.c $(DEMANGLE_H)
+
+vfprintf.o: $(srcdir)/../libiberty/vfprintf.c $(CONFIG_H) system.h
+ rm -f vfprintf.c
+ $(LN_S) $(srcdir)/../libiberty/vfprintf.c vfprintf.c
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) vfprintf.c
+
+splay-tree.o: $(srcdir)/../libiberty/splay-tree.c \
+ $(srcdir)/../include/splay-tree.h $(srcdir)/../include/libiberty.h
+ rm -f splay-tree.c
+ $(LN_S) $(srcdir)/../libiberty/splay-tree.c splay-tree.c
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) splay-tree.c
underscore.c: s-under ; @true
@@ -1325,7 +1402,7 @@ s-under: $(GCC_PASSES)
# A file used by all variants of C.
c-common.o : c-common.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-lex.h \
- flags.h toplev.h output.h
+ flags.h toplev.h output.h c-pragma.h $(RTL_H)
# Language-independent files.
@@ -1335,33 +1412,38 @@ DRIVER_DEFINES = \
-DDEFAULT_TARGET_VERSION=\"$(version)\" \
-DDEFAULT_TARGET_MACHINE=\"$(target_alias)\" \
-DTOOLDIR_BASE_PREFIX=\"$(exec_prefix)/\"
-gcc.o: gcc.c $(CONFIG_H) system.h gansidecl.h multilib.h Makefile \
- $(lang_specs_files)
+gcc.o: gcc.c $(CONFIG_H) system.h intl.h multilib.h \
+ Makefile $(lang_specs_files) prefix.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(DRIVER_DEFINES) \
-c `echo $(srcdir)/gcc.c | sed 's,^\./,,'`
+gccspec.o: gccspec.c $(CONFIG_H) system.h
+cppspec.o: cppspec.c $(CONFIG_H) system.h
+
tree-check.h: s-check ; @true
s-check : gencheck $(srcdir)/move-if-change
./gencheck > tmp-check.h
$(srcdir)/move-if-change tmp-check.h tree-check.h
touch s-check
-gencheck : gencheck.o tree.def $(HOST_LIBDEPS)
+gencheck : gencheck.o $(lang_tree_files) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
gencheck.o $(HOST_LIBS)
-gencheck.o : gencheck.c hconfig.h system.h
- $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencheck.c
+gencheck.o : gencheck.c tree.def $(CONFIG_H) hconfig.h system.h
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/gencheck.c
dumpvers: dumpvers.c
version.o: version.c
-obstack.o: obstack.c $(CONFIG_H)
-choose-temp.o: choose-temp.c $(CONFIG_H) gansidecl.h system.h
-mkstemp.o: mkstemp.c $(CONFIG_H) gansidecl.h system.h
-pexecute.o: pexecute.c $(CONFIG_H) system.h gansidecl.h
-prefix.o: prefix.c $(CONFIG_H) system.h gansidecl.h Makefile
+obstack.o: $(srcdir)/../libiberty/obstack.c $(CONFIG_H)
+ rm -f obstack.c
+ $(LN_S) $(srcdir)/../libiberty/obstack.c obstack.c
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) obstack.c
+
+prefix.o: prefix.c $(CONFIG_H) system.h Makefile prefix.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DPREFIX=\"$(prefix)\" \
-c `echo $(srcdir)/prefix.c | sed 's,^\./,,'`
@@ -1372,11 +1454,12 @@ tree.o : tree.c $(CONFIG_H) system.h $(TREE_H) flags.h function.h toplev.h excep
print-tree.o : print-tree.c $(CONFIG_H) system.h $(TREE_H)
stor-layout.o : stor-layout.c $(CONFIG_H) system.h $(TREE_H) flags.h \
function.h $(EXPR_H) $(RTL_H) toplev.h except.h
-fold-const.o : fold-const.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h
+fold-const.o : fold-const.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h \
+ $(RTL_H)
toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) \
flags.h input.h insn-attr.h xcoffout.h defaults.h output.h \
- insn-codes.h insn-config.h $(RECOG_H) Makefile toplev.h dwarfout.h \
- dwarf2out.h sdbout.h dbxout.h \
+ insn-codes.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h dwarfout.h \
+ dwarf2out.h sdbout.h dbxout.h $(EXPR_H) $(BASIC_BLOCK_H) \
$(lang_options_files)
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(MAYBE_USE_COLLECT2) \
-DTARGET_NAME=\"$(target_alias)\" \
@@ -1384,7 +1467,7 @@ toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) \
rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
-print-rtl.o : print-rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
+print-rtl.o : print-rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h basic-block.h
rtlanal.o : rtlanal.c $(CONFIG_H) system.h $(RTL_H)
varasm.o : varasm.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h \
@@ -1392,30 +1475,33 @@ varasm.o : varasm.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h \
xcoffout.h output.h c-pragma.h toplev.h except.h dbxout.h sdbout.h
function.o : function.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
function.h insn-flags.h insn-codes.h $(EXPR_H) $(REGS_H) hard-reg-set.h \
- insn-config.h $(RECOG_H) output.h toplev.h except.h
+ insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h
stmt.o : stmt.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h function.h \
insn-flags.h insn-config.h insn-codes.h hard-reg-set.h $(EXPR_H) except.h \
- loop.h $(RECOG_H) toplev.h output.h
+ loop.h $(RECOG_H) toplev.h output.h varray.h
except.o : except.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
function.h insn-flags.h $(EXPR_H) $(REGS_H) hard-reg-set.h \
- insn-config.h $(RECOG_H) output.h except.h toplev.h
+ insn-config.h $(RECOG_H) output.h except.h toplev.h intl.h
expr.o : expr.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h function.h \
- $(REGS_H) insn-flags.h insn-codes.h $(EXPR_H) insn-config.h $(RECOG_H) output.h \
- typeclass.h hard-reg-set.h toplev.h hard-reg-set.h except.h
+ $(REGS_H) insn-flags.h insn-codes.h $(EXPR_H) insn-config.h $(RECOG_H) \
+ output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h except.h
calls.o : calls.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h $(EXPR_H) \
insn-flags.h $(REGS_H) toplev.h output.h
expmed.o : expmed.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
- insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) real.h
+ insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) real.h toplev.h
explow.o : explow.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
- hard-reg-set.h insn-config.h $(EXPR_H) $(RECOG_H) insn-flags.h insn-codes.h
+ hard-reg-set.h insn-config.h $(EXPR_H) $(RECOG_H) insn-flags.h \
+ insn-codes.h toplev.h
optabs.o : optabs.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
- insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) reload.h
+ insn-flags.h insn-config.h insn-codes.h $(EXPR_H) $(RECOG_H) reload.h \
+ toplev.h
dbxout.o : dbxout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h $(REGS_H) \
insn-config.h reload.h gstab.h xcoffout.h defaults.h output.h dbxout.h \
toplev.h
sdbout.o : sdbout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) flags.h except.h \
function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) defaults.h real.h \
- insn-config.h obstack.h xcoffout.h c-pragma.h sdbout.h toplev.h
+ insn-config.h $(srcdir)/../include/obstack.h xcoffout.h c-pragma.h \
+ sdbout.h toplev.h
dwarfout.o : dwarfout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) dwarf.h \
flags.h insn-config.h reload.h output.h defaults.h toplev.h dwarfout.h
dwarf2out.o : dwarf2out.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) dwarf2.h \
@@ -1425,33 +1511,40 @@ xcoffout.o : xcoffout.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) xcoffout.h \
flags.h toplev.h output.h dbxout.h
emit-rtl.o : emit-rtl.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
except.h function.h $(REGS_H) insn-config.h $(RECOG_H) real.h \
- $(EXPR_H) obstack.h hard-reg-set.h bitmap.h
+ $(EXPR_H) $(srcdir)/../include/obstack.h hard-reg-set.h bitmap.h toplev.h
real.o : real.c $(CONFIG_H) system.h $(TREE_H) toplev.h
getpwd.o : getpwd.c $(CONFIG_H) system.h
integrate.o : integrate.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
integrate.h insn-flags.h insn-config.h $(EXPR_H) real.h $(REGS_H) \
- function.h output.h $(RECOG_H) except.h toplev.h
+ intl.h function.h output.h $(RECOG_H) except.h toplev.h
jump.o : jump.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
insn-config.h insn-flags.h $(RECOG_H) $(EXPR_H) real.h except.h \
toplev.h insn-attr.h
stupid.o : stupid.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
- flags.h toplev.h
+ $(BASIC_BLOCK_H) insn-config.h reload.h flags.h toplev.h
cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
- real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h
-gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
- real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h
+ real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h \
+ $(srcdir)/../include/splay-tree.h
+gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
+ flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
+ output.h toplev.h
+resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h system.h \
+ $(BASIC_BLOCK_H) $(REGS_H) flags.h output.h resource.h toplev.h
+lcm.o : lcm.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
+ real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H)
profile.o : profile.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-flags.h \
- gcov-io.h $(TREE_H) output.h $(REGS_H) toplev.h
+ gcov-io.h $(TREE_H) output.h $(REGS_H) toplev.h insn-config.h
loop.o : loop.c $(CONFIG_H) system.h $(RTL_H) flags.h loop.h insn-config.h \
insn-flags.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) real.h \
- toplev.h
+ toplev.h varray.h
unroll.o : unroll.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
- integrate.h $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) loop.h toplev.h
+ integrate.h $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) loop.h toplev.h varray.h
flow.o : flow.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-config.h \
- $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h
+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h recog.h \
+ insn-flags.h
combine.o : combine.c $(CONFIG_H) system.h $(RTL_H) flags.h \
insn-config.h insn-flags.h insn-codes.h insn-attr.h $(REGS_H) $(EXPR_H) \
$(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h
@@ -1463,7 +1556,7 @@ local-alloc.o : local-alloc.c $(CONFIG_H) system.h $(RTL_H) flags.h \
insn-attr.h toplev.h
bitmap.o : bitmap.c $(CONFIG_H) system.h $(RTL_H) flags.h $(BASIC_BLOCK_H) \
$(REGS_H)
-global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h \
+global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h reload.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h
varray.o : varray.c $(CONFIG_H) system.h varray.h $(RTL_H) $(TREE_H) bitmap.h
@@ -1477,26 +1570,26 @@ caller-save.o : caller-save.c $(CONFIG_H) system.h $(RTL_H) flags.h \
$(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) \
$(RECOG_H) reload.h $(EXPR_H) toplev.h
reorg.o : reorg.c $(CONFIG_H) system.h $(RTL_H) conditions.h hard-reg-set.h \
- $(BASIC_BLOCK_H) $(REGS_H) insn-config.h insn-attr.h \
- insn-flags.h $(RECOG_H) flags.h output.h $(EXPR_H)
+ $(BASIC_BLOCK_H) $(REGS_H) insn-config.h insn-attr.h insn-flags.h \
+ $(RECOG_H) flags.h output.h $(EXPR_H) toplev.h
alias.o : alias.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h \
- $(REGS_H) toplev.h $(EXPR_H)
+ $(REGS_H) toplev.h output.h $(EXPR_H)
regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \
$(RECOG_H) output.h reload.h $(REGS_H) hard-reg-set.h flags.h \
$(EXPR_H) insn-flags.h $(BASIC_BLOCK_H) toplev.h
$(SCHED_PREFIX)sched.o : $(SCHED_PREFIX)sched.c $(CONFIG_H) system.h $(RTL_H) \
- $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
- toplev.h
-final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h $(REGS_H) \
- $(RECOG_H) conditions.h insn-config.h insn-attr.h except.h real.h output.h \
- hard-reg-set.h insn-flags.h insn-codes.h gstab.h xcoffout.h defaults.h \
- toplev.h reload.h dwarfout.h dwarf2out.h sdbout.h dbxout.h
+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h \
+ insn-attr.h toplev.h recog.h
+final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h intl.h \
+ $(REGS_H) $(RECOG_H) conditions.h insn-config.h insn-attr.h except.h real.h \
+ output.h hard-reg-set.h insn-flags.h insn-codes.h gstab.h xcoffout.h \
+ defaults.h toplev.h reload.h dwarfout.h dwarf2out.h sdbout.h dbxout.h
recog.o : recog.c $(CONFIG_H) system.h $(RTL_H) \
$(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \
- insn-flags.h insn-codes.h real.h
-reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) \
+ insn-flags.h insn-codes.h real.h toplev.h
+reg-stack.o : reg-stack.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) recog.h \
$(REGS_H) hard-reg-set.h flags.h insn-config.h insn-flags.h toplev.h
-dyn-string.o: dyn-string.c dyn-string.h $(CONFIG_H) system.h gansidecl.h
+dyn-string.o: dyn-string.c dyn-string.h $(CONFIG_H) system.h
$(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \
@@ -1520,9 +1613,11 @@ halfpic.o: halfpic.c $(CONFIG_H) $(RTL_H) $(TREE_H) system.h
# Normally this target is not used; but it is used if you
# define ALLOCA=alloca.o. In that case, you must get a suitable alloca.c
# from the GNU Emacs distribution.
-alloca.o: alloca.c
+alloca.o: $(srcdir)/../libiberty/alloca.c
+ rm -f alloca.c
+ $(LN_S) $(srcdir)/../libiberty/alloca.c alloca.c
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(ALLOCA_FLAGS) \
- -c `echo $(srcdir)/alloca.c | sed 's,^\./,,'`
+ -c `echo alloca.c | sed 's,^\./,,'`
$(ALLOCA_FINISH)
#
# Generate header and source files from the machine description,
@@ -1570,7 +1665,7 @@ s-codes : $(md_file) gencodes $(srcdir)/move-if-change
touch s-codes
insn-emit.o : insn-emit.c $(CONFIG_H) $(RTL_H) $(EXPR_H) real.h output.h \
- insn-config.h insn-flags.h insn-codes.h system.h reload.h
+ insn-config.h insn-flags.h insn-codes.h system.h reload.h recog.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-emit.c
insn-emit.c: s-emit ; @true
@@ -1599,7 +1694,8 @@ s-opinit : $(md_file) genopinit $(srcdir)/move-if-change
$(srcdir)/move-if-change tmp-opinit.c insn-opinit.c
touch s-opinit
-insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) system.h
+insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) system.h toplev.h \
+ insn-config.h recog.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-extract.c
insn-extract.c: s-extract ; @true
@@ -1608,7 +1704,8 @@ s-extract : $(md_file) genextract $(srcdir)/move-if-change
$(srcdir)/move-if-change tmp-extract.c insn-extract.c
touch s-extract
-insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) $(REGS_H) output.h real.h system.h
+insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) $(REGS_H) output.h real.h \
+ system.h insn-config.h recog.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-peep.c
insn-peep.c: s-peep ; @true
@@ -1617,8 +1714,8 @@ s-peep : $(md_file) genpeep $(srcdir)/move-if-change
$(srcdir)/move-if-change tmp-peep.c insn-peep.c
touch s-peep
-insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(RTL_H) $(REGS_H) real.h output.h \
- insn-attr.h insn-config.h system.h
+insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(RTL_H) $(REGS_H) real.h \
+ output.h insn-attr.h insn-config.h system.h toplev.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-attrtab.c
insn-attr.h: s-attr ; @true
@@ -1771,7 +1868,8 @@ $(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(HOST_PREFIX)rtl.c
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtl.c
-$(HOST_PREFIX_1)print-rtl.o: $(srcdir)/print-rtl.c $(CONFIG_H) $(RTL_H)
+$(HOST_PREFIX_1)print-rtl.o: $(srcdir)/print-rtl.c $(CONFIG_H) $(RTL_H) \
+ bitmap.h basic-block.h
rm -f $(HOST_PREFIX)print-rtl.c
sed -e 's/config[.]h/hconfig.h/' $(srcdir)/print-rtl.c > $(HOST_PREFIX)print-rtl.c
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)print-rtl.c
@@ -1787,19 +1885,19 @@ $(HOST_PREFIX_1)rtlanal.o: $(srcdir)/rtlanal.c $(CONFIG_H) $(RTL_H)
sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtlanal.c > $(HOST_PREFIX)rtlanal.c
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtlanal.c
-$(HOST_PREFIX_1)alloca.o: alloca.c
+$(HOST_PREFIX_1)alloca.o: $(srcdir)/../libiberty/alloca.c
rm -f $(HOST_PREFIX)alloca.c
- cp $(srcdir)/alloca.c $(HOST_PREFIX)alloca.c
+ $(LN_S) $(srcdir)/../libiberty/alloca.c $(HOST_PREFIX)alloca.c
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)alloca.c
-$(HOST_PREFIX_1)obstack.o: obstack.c
+$(HOST_PREFIX_1)obstack.o: $(srcdir)/../libiberty/obstack.c
rm -f $(HOST_PREFIX)obstack.c
- sed -e 's/config[.]h/hconfig.h/' $(srcdir)/obstack.c > $(HOST_PREFIX)obstack.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/../libiberty/obstack.c > $(HOST_PREFIX)obstack.c
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)obstack.c
-$(HOST_PREFIX_1)vfprintf.o: vfprintf.c
+$(HOST_PREFIX_1)vfprintf.o: $(srcdir)/../libiberty/vfprintf.c
rm -f $(HOST_PREFIX)vfprintf.c
- sed -e 's/config[.]h/hconfig.h/' $(srcdir)/vfprintf.c > $(HOST_PREFIX)vfprintf.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/../libiberty/vfprintf.c > $(HOST_PREFIX)vfprintf.c
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)vfprintf.c
$(HOST_PREFIX_1)doprint.o: doprint.c
@@ -1817,6 +1915,40 @@ $(HOST_PREFIX_1)malloc.o: malloc.c
$(HOST_PREFIX_1):
touch $(HOST_PREFIX_1)
+
+#
+# Remake internationalization support.
+
+intl.o: intl.c intl.h gansidecl.h Makefile
+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ -DLOCALEDIR=\"$(localedir)\" \
+ -c `echo $(srcdir)/intl.c | sed 's,^\./,,'`
+
+# This is needed to when doing a partial build after a `make clean'.
+# libintl.a does not depend on intl.all,
+# as that would force a lot of recompiling.
+$(top_builddir)/intl/libintl.a:
+ @echo "$(MAKE) intl.all"
+ @$(MAKE) $(FLAGS_TO_PASS) intl.all
+
+# Make sure all the headers are there for xgettext to scan.
+$(INTL_TARGETS): $(srcdir)/c-gperf.h \
+ $(srcdir)/c-parse.c $(srcdir)/c-parse.h $(srcdir)/cexp.c
+
+intl.all intl.install intl.uninstall intl.distdir \
+ intl.mostlyclean intl.clean intl.distclean intl.maintainer-clean:
+ @for d in $(INTL_SUBDIRS); do \
+ target=`expr $@ : 'intl.\(.*\)'` && \
+ echo "(cd $$d && $(MAKE) $$target)" && \
+ (cd $$d && AWK='$(AWK)' $(MAKE) $(SUBDIR_FLAGS_TO_PASS) $$target); \
+ done
+
+# intl.distdir doesn't copy the intl makefiles (since they aren't distributed),
+# but we need them for the `make extraclean' in distdir-finish.
+intl.distdir-fixup:
+ for d in $(INTL_SUBDIRS); do \
+ ln $$d/Makefile tmp/$$d || cp $$d/Makefile tmp/$$d || exit; \
+ done
#
# Remake cpp and protoize.
@@ -1824,92 +1956,95 @@ $(HOST_PREFIX_1):
cpp$(exeext): $(CCCP)$(exeext)
-rm -f cpp$(exeext)
$(LN) $(CCCP)$(exeext) cpp$(exeext)
-cccp$(exeext): cccp.o cexp.o version.o prefix.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ cccp.o cexp.o prefix.o \
- version.o $(LIBS)
-cexp.o: $(srcdir)/cexp.c $(CONFIG_H) system.h gansidecl.h
+CCCP_OBJS = cccp.o cexp.o intl.o prefix.o version.o @extra_cpp_objs@ mbchar.o
+cccp$(exeext): $(CCCP_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(CCCP_OBJS) $(LIBS)
+cexp.o: $(srcdir)/cexp.c $(CONFIG_H) system.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c $(srcdir)/cexp.c
$(srcdir)/cexp.c: $(srcdir)/cexp.y
cd $(srcdir); $(BISON) -o cexp.c cexp.y
-cccp.o: cccp.c $(CONFIG_H) pcp.h version.c config.status system.h gansidecl.h
+# We use $(libsubdir)/$(unlibsubdir) to match the
+# -iprefix argument which gcc will pass if GCC_EXEC_PREFIX is used.
+cccp.o: cccp.c $(CONFIG_H) intl.h pcp.h version.c config.status system.h \
+ mbchar.h prefix.h Makefile.in
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
- -DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \
- -DOLD_GPLUSPLUS_INCLUDE_DIR=\"$(old_gxx_include_dir)\" \
+ -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \
-DLOCAL_INCLUDE_DIR=\"$(includedir)\" \
- -DCROSS_INCLUDE_DIR=\"$(tooldir)/sys-include\" \
- -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \
+ -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
+ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
-c `echo $(srcdir)/cccp.c | sed 's,^\./,,'`
-cppmain$(exeext): cppmain.o cpplib.o cpphash.o cppalloc.o cpperror.o cppexp.o \
- prefix.o version.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ cppmain.o cpplib.o cpphash.o \
- cppalloc.o cpperror.o cppexp.o prefix.o version.o $(LIBS)
-
-cppmain.o: cppmain.c $(CONFIG_H) cpplib.h system.h gansidecl.h
+LIBCPP_OBJS = cpplib.o cpphash.o cppalloc.o cpperror.o cppexp.o cppfiles.o \
+ cppinit.o cppulp.o prefix.o version.o mbchar.o @extra_cpp_objs@
-cpplib.o: cpplib.c $(CONFIG_H) cpplib.h cpphash.h config.status system.h \
- gansidecl.h
+# All the other archives built/used by this makefile are for targets. This
+# one is strictly for the host.
+#
+libcpp.a: $(LIBCPP_OBJS)
+ $(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS)
+ if $(RANLIB_TEST) ; then $(RANLIB) libcpp.a ; else true ; fi
+
+cppmain$(exeext): cppmain.o intl.o libcpp.a $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cppmain$(exeext) cppmain.o \
+ intl.o libcpp.a $(LIBS)
+
+cppmain.o: cppmain.c $(CONFIG_H) cpplib.h intl.h system.h
+
+cppulp.o: cppulp.c $(CONFIG_H) system.h output.h
+cpplib.o: cpplib.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
+cpphash.o: cpphash.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
+cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h system.h
+cpperror.o: cpperror.c $(CONFIG_H) cpplib.h intl.h system.h
+cppexp.o: cppexp.c $(CONFIG_H) cpplib.h intl.h system.h
+cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h intl.h system.h
+
+cppinit.o: cppinit.c $(CONFIG_H) cpplib.h intl.h system.h \
+ cpphash.h prefix.h output.h Makefile
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
- -DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \
- -DOLD_GPLUSPLUS_INCLUDE_DIR=\"$(old_gxx_include_dir)\" \
+ -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \
-DLOCAL_INCLUDE_DIR=\"$(includedir)\" \
- -DCROSS_INCLUDE_DIR=\"$(tooldir)/sys-include\" \
- -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \
- -c `echo $(srcdir)/cpplib.c | sed 's,^\./,,'`
-
-cpperror.o: cpperror.c $(CONFIG_H) cpplib.h system.h gansidecl.h
-
-cppexp.o: cppexp.c $(CONFIG_H) cpplib.h system.h gansidecl.h
-
-cpphash.o: cpphash.c cpplib.h cpphash.h $(CONFIG_H) system.h gansidecl.h
-
-cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h system.h gansidecl.h
+ -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
+ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
+ -c `echo $(srcdir)/cppinit.c | sed 's,^\./,,'`
# Note for the stamp targets, we run the program `true' instead of
# having an empty command (nothing following the semicolon).
proto: config.status protoize$(exeext) unprotoize$(exeext) SYSCALLS.c.X
-protoize$(exeext): protoize.o getopt.o getopt1.o getpwd.o version.o \
- pexecute.o choose-temp.o mkstemp.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
- protoize.o getopt.o getopt1.o getpwd.o version.o \
- pexecute.o choose-temp.o mkstemp.o $(LIBS)
+PROTO_OBJS = getpwd.o intl.o version.o
-unprotoize$(exeext): unprotoize.o getopt.o getopt1.o getpwd.o version.o \
- pexecute.o choose-temp.o mkstemp.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
- unprotoize.o getopt.o getopt1.o getpwd.o version.o \
- pexecute.o choose-temp.o mkstemp.o $(LIBS)
+protoize$(exeext): protoize.o $(PROTO_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ protoize.o $(PROTO_OBJS) $(LIBS)
-protoize.o: protoize.c getopt.h $(CONFIG_H) system.h
+unprotoize$(exeext): unprotoize.o $(PROTO_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ unprotoize.o $(PROTO_OBJS) $(LIBS)
+
+protoize.o: protoize.c $(srcdir)/../include/getopt.h $(CONFIG_H) system.h \
+ Makefile
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
- -DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \
- -DCROSS_INCLUDE_DIR=\"$(tooldir)/sys-include\" \
- -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \
+ -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \
+ -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
+ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
-DLOCAL_INCLUDE_DIR=\"$(includedir)\" \
-DSTD_PROTO_DIR=\"$(libsubdir)\" \
$(srcdir)/protoize.c
-unprotoize.o: unprotoize.c protoize.c getopt.h $(CONFIG_H) system.h
+unprotoize.o: unprotoize.c protoize.c $(srcdir)/../include/getopt.h \
+ $(CONFIG_H) system.h Makefile
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
- -DGPLUSPLUS_INCLUDE_DIR=\"$(gxx_include_dir)\" \
- -DCROSS_INCLUDE_DIR=\"$(tooldir)/sys-include\" \
- -DTOOL_INCLUDE_DIR=\"$(tooldir)/include\" \
+ -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \
+ -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
+ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
-DLOCAL_INCLUDE_DIR=\"$(includedir)\" \
-DSTD_PROTO_DIR=\"$(libsubdir)\" \
$(srcdir)/unprotoize.c
-getopt.o: getopt.c getopt.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/getopt.c
-getopt1.o: getopt1.c getopt.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/getopt1.c
-
# This info describes the target machine, so compile with GCC just built.
SYSCALLS.c.X: $(srcdir)/sys-types.h $(srcdir)/sys-protos.h $(GCC_PASSES) \
stmp-int-hdrs
@@ -1945,12 +2080,13 @@ test-protoize-simple: ./protoize ./unprotoize $(GCC_PASSES)
diff $(srcdir)/protoize.c tmp-proto.c | cat
-rm -f tmp-proto.[cs] tmp-proto$(objext)
-gcov.o: gcov.c gcov-io.h system.h
+gcov.o: gcov.c gcov-io.h intl.h system.h
# Only one of 'gcov' or 'gcov.exe' is actually built, depending
# upon whether $(exeext) is empty or not.
-gcov$(exeext): gcov.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) gcov.o $(LIBS) -o $@
+GCOV_OBJS = gcov.o intl.o
+gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(GCOV_OBJS) $(LIBS) -o $@
#
# Build the include directory. The stamp files are stmp-* rather than
# s-* so that mostlyclean does not force the include directory to
@@ -1958,7 +2094,7 @@ gcov$(exeext): gcov.o $(LIBDEPS)
# Build the include directory including float.h (which no longer depends upon
# enquire).
-stmp-int-hdrs: stmp-fixinc $(USER_H) xlimits.h gfloat.h
+stmp-int-hdrs: stmp-fixinc $(USER_H) xlimits.h
# Copy in the headers provided with gcc.
# The sed command gets just the last file name component;
# this is necessary because VPATH could add a dirname.
@@ -1977,8 +2113,8 @@ stmp-int-hdrs: stmp-fixinc $(USER_H) xlimits.h gfloat.h
cp xlimits.h include/limits.h
chmod a+r include/limits.h
rm -f include/float.h
- if [ -s gfloat.h ]; then \
- cp gfloat.h include/float.h && \
+ if [ x$(FLOAT_H) != xMakefile.in ]; then \
+ cp $(srcdir)/config/$(FLOAT_H) include/float.h && \
chmod a+r include/float.h; \
else :; fi
# Install the README
@@ -1987,37 +2123,46 @@ stmp-int-hdrs: stmp-fixinc $(USER_H) xlimits.h gfloat.h
chmod a+r include/README
touch $@
-# Now that gfloat.h no longer depends upon enquire, this is actually a no-op.
+# Now that float.h no longer depends upon enquire, this is actually a no-op.
stmp-headers:
touch $@
-fixinc.sh :
- DEST=`cd $(srcdir) ; pwd`/$@ CC=$(CC) MAKE=$(MAKE) CFLAGS="$(CFLAGS)" \
- export DEST CC MAKE CFLAGS ; \
- echo DEST=$$DEST CC=$$CC MAKE=$$MAKE CFLAGS=$$CFLAGS ; \
- cd ../contrib/fixinc ; \
- $(SHELL) mkfixinc.sh $(target) $$DEST
+FIXINCSRCDIR=$(srcdir)/fixinc
+fixinc.sh: $(FIXINCSRCDIR)/mkfixinc.sh $(FIXINCSRCDIR)/fixincl.c \
+ $(FIXINCSRCDIR)/procopen.c $(FIXINCSRCDIR)/gnu-regex.c \
+ $(FIXINCSRCDIR)/server.c $(FIXINCSRCDIR)/gnu-regex.h \
+ $(FIXINCSRCDIR)/server.h $(FIXINCSRCDIR)/inclhack.def
+ MAKE="$(MAKE)"; srcdir=`cd $(srcdir)/fixinc; pwd` ; \
+ export MAKE srcdir ; \
+ cd ./fixinc; $(SHELL) $${srcdir}/mkfixinc.sh $(target)
+
+##stmp-fixinc: $(FIXINCLUDES) gsyslimits.h
+## rm -rf include
+## mkdir include
+## if [ x$(FIXINCLUDES) != xMakefile.in ]; \
+## then \
+## for dir in $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS); do \
+## if [ -d $$dir ]; \
+## then \
+## $(SHELL) $(srcdir)/$(FIXINCLUDES) include $$dir; \
+## else true; fi; \
+## done; \
+## if [ x$(INSTALL_ASSERT_H) != x ] ; \
+## then \
+## rm -f include/assert.h; \
+## cp $(srcdir)/assert.h include/assert.h; \
+## chmod a+r include/assert.h; \
+## fi \
+## else true; \
+## fi
# Build fixed copies of system files.
-stmp-fixinc: $(FIXINCLUDES) gsyslimits.h
- rm -rf include
- mkdir include
- if [ x$(FIXINCLUDES) != xMakefile.in ]; \
- then \
- for dir in $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS); do \
- if [ -d $$dir ]; \
- then \
- $(SHELL) $(srcdir)/$(FIXINCLUDES) include $$dir; \
- else true; fi; \
- done; \
- if [ x$(INSTALL_ASSERT_H) != x ] ; \
- then \
- rm -f include/assert.h; \
- cp $(srcdir)/assert.h include/assert.h; \
- chmod a+r include/assert.h; \
- fi \
- else true; \
- fi
+stmp-fixinc: fixinc.sh gsyslimits.h
+ rm -rf include; mkdir include
+ TARGET_MACHINE=$(target); srcdir=`cd $(srcdir); pwd`; \
+ INSTALL_ASSERT_H=$(INSTALL_ASSERT_H); SHELL=$(SHELL) ;\
+ export TARGET_MACHINE srcdir INSTALL_ASSERT_H SHELL ; \
+ $(SHELL) ./fixinc.sh `pwd`/include $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS)
rm -f include/syslimits.h
if [ -f include/limits.h ]; then \
mv include/limits.h include/syslimits.h; \
@@ -2025,6 +2170,21 @@ stmp-fixinc: $(FIXINCLUDES) gsyslimits.h
cp $(srcdir)/gsyslimits.h include/syslimits.h; \
fi
chmod a+r include/syslimits.h
+# If $(SYSTEM_HEADER_DIR) is $(tooldir)/sys-include, and
+# that directory exists, then make sure that $(libsubdir) exists.
+# This is because cpp is compiled to find $(tooldir)/include via
+# $(libsubdir)/$(unlibsubdir), which will only work if $(libsubdir)
+# exists.
+# We deliberately use tooldir instead of gcc_tooldir here. gcc_tooldir
+# won't work because libsubdir doesn't exist yet.
+ if [ "$(SYSTEM_HEADER_DIR)" = "$(tooldir)/sys-include" ] \
+ && [ -d $(tooldir)/sys-include ]; then \
+ if [ -d $(libdir) ] ; then true ; else mkdir $(libdir) ; fi; \
+ if [ -d $(libdir)/gcc-lib ] ; then true ; else mkdir $(libdir)/gcc-lib; fi; \
+ if [ -d $(libdir)/gcc-lib/$(target_alias) ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target_alias) ; fi; \
+ if [ -d $(libdir)/gcc-lib/$(target_alias)/$(version) ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target_alias)/$(version) ; fi; \
+ else true; fi
+
touch stmp-fixinc
# Files related to the fixproto script.
@@ -2040,9 +2200,10 @@ deduced.h: $(GCC_PASSES) $(srcdir)/scan-types.sh stmp-int-hdrs
touch deduced.h; \
fi
-gen-protos: gen-protos.o scan.o cppalloc.o $(HOST_LIBDEPS)
- ${HOST_CC} $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- gen-protos.o scan.o cppalloc.o $(HOST_LIBS)
+GEN_PROTOS_OBJS = gen-protos.o scan.o libcpp.a
+gen-protos: $(GEN_PROTOS_OBJS) $(HOST_LIBDEPS)
+ ${HOST_CC} $(HOST_CFLAGS) $(HOST_LDFLAGS) -o gen-protos \
+ $(GEN_PROTOS_OBJS) $(HOST_LIBS)
gen-protos.o: gen-protos.c scan.h $(build_xm_file) system.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gen-protos.c
@@ -2060,16 +2221,15 @@ xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h gen-protos Makefil
rm -rf fixtmp.c
fix-header: fix-header.o scan-decls.o scan.o xsys-protos.h $(HOST_LIBDEPS) \
- cpplib.o cpphash.o cppalloc.o cppexp.o prefix.o version.o
+ libcpp.a
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ fix-header.o \
- scan-decls.o scan.o cpplib.o cpphash.o cppalloc.o prefix.o \
- version.o cppexp.o $(HOST_LIBS)
+ scan-decls.o scan.o libcpp.a $(HOST_LIBS)
-fix-header.o: fix-header.c obstack.h scan.h xsys-protos.h $(build_xm_file) \
- system.h cpplib.h cpphash.h
+fix-header.o: fix-header.c $(srcdir)/../include/obstack.h scan.h \
+ xsys-protos.h $(build_xm_file) system.h cpplib.h cpphash.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/fix-header.c
-scan-decls.o: scan-decls.c scan.h cpplib.h $(build_xm_file) system.h gansidecl.h
+scan-decls.o: scan-decls.c scan.h cpplib.h $(build_xm_file) system.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/scan-decls.c
# stmp-fixproto depends on this, not on fix-header directly.
@@ -2093,6 +2253,8 @@ stmp-fixproto: fixhdr.ready fixproto stmp-headers
else \
: This line works around a 'make' bug in BSDI 1.1.; \
FIXPROTO_DEFINES="$(FIXPROTO_DEFINES)"; export FIXPROTO_DEFINES; \
+ mkinstalldirs="$(SHELL) $(srcdir)/mkinstalldirs"; \
+ export mkinstalldirs; \
if [ -d $(SYSTEM_HEADER_DIR) ] ; then \
$(SHELL) ${srcdir}/fixproto include include $(SYSTEM_HEADER_DIR); \
else true; fi; \
@@ -2130,7 +2292,7 @@ cpp.dvi: $(srcdir)/cpp.texi
INSTALL: $(srcdir)/install1.texi $(srcdir)/install.texi
- cd $(srcdir); $(MAKEINFO) -D INSTALLONLY --no-header \
+ cd $(srcdir); $(MAKEINFO) -D INSTALLONLY \
--no-split -o INSTALL install1.texi
#
# Deletion of files made during compilation.
@@ -2147,7 +2309,7 @@ INSTALL: $(srcdir)/install1.texi $(srcdir)/install.texi
# (less duplicated code).
-mostlyclean: lang.mostlyclean
+mostlyclean: intl.mostlyclean lang.mostlyclean
-rm -f $(STAGESTUFF)
# Delete the temporary source copies for cross compilation.
-rm -f $(HOST_PREFIX_1)rtl.c $(HOST_PREFIX_1)rtlanal.c
@@ -2164,12 +2326,12 @@ mostlyclean: lang.mostlyclean
# Delete debugging dump files.
-rm -f *.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop
-rm -f *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.addressof
- -rm -f *.regmove *.mach *.bp *.gcse
+ -rm -f *.regmove *.mach *.bp *.gcse *.flow2
-rm -f */*.greg */*.lreg */*.combine */*.flow */*.cse */*.jump */*.rtl
-rm -f */*.tree */*.loop */*.dbr */*.jump2 */*.sched */*.cse2
- -rm -f */*.sched2 */*.stack */*.regmove */*.gcse
+ -rm -f */*.sched2 */*.stack */*.regmove */*.gcse */*.flow2
# Delete some files made during installation.
- -rm -f specs gfloat.h float.h-* enquire SYSCALLS.c.X SYSCALLS.c
+ -rm -f specs float.h-* enquire SYSCALLS.c.X SYSCALLS.c
-rm -f collect collect2 mips-tfile mips-tdump alloca.s
# Delete files generated for fixproto
-rm -rf fix-header xsys-protos.h deduced.h tmp-deduced.h \
@@ -2185,7 +2347,7 @@ mostlyclean: lang.mostlyclean
# Delete all files made by compilation
# that don't exist in the distribution.
-clean: mostlyclean lang.clean
+clean: mostlyclean intl.clean lang.clean
# It may not be quite desirable to delete unprotoize.c here,
# but the spec for `make clean' requires it.
# Using unprotoize.c is not quite right in the first place,
@@ -2210,12 +2372,13 @@ clean: mostlyclean lang.clean
# Delete all files that users would normally create
# while building and installing GCC.
-distclean: clean lang.distclean
+INTL_DISTCLEAN = intl.distclean
+distclean: clean $(INTL_DISTCLEAN) lang.distclean
-rm -f tm.h config.h auto-host.h auto-build.h tconfig.h hconfig.h
-rm -f md cstamp-h
-rm -f config.status config.run config.cache config.bak
-rm -f Make-lang Make-hooks Make-host Make-target
- -rm -f Makefile specs.h options.h *.oaux
+ -rm -f Makefile specs.h options.h gencheck.h *.oaux
-rm -f gthr-default.h
-rm -f */stage1 */stage2 */stage3 */stage4 */include
-rm -f c-parse.output
@@ -2223,6 +2386,7 @@ distclean: clean lang.distclean
-rm -f float.h
-rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak
-rm -f testsuite/{gcc,g++}.{log,sum}
+ -rm -f intl/libintl.h libintl.h
# Delete anything likely to be found in the source directory
# that shouldn't be in the distribution.
@@ -2235,6 +2399,7 @@ extraclean: distclean lang.extraclean
-rm -f *.tar *.xtar *diff *.diff.* *.tar.* *.xtar.* *diffs
-rm -f *lose config/*lose config/*/*lose
-rm -f *.s *.s[0-9] *.i config/ChangeLog
+ -rm -f y.tab.c yacc.*
-rm -f */=* */"#"* */*~*
-rm -f */patch* */*.orig */*.rej
-rm -f */*.dvi */*.oaux */*.d */*.[zZ] */*.gz
@@ -2243,10 +2408,13 @@ extraclean: distclean lang.extraclean
# Get rid of every file that's generated from some other file, except for `configure'.
# Most of these files ARE PRESENT in the GCC distribution.
+# We define INTL_DISTCLEAN to be empty in the submake, so that
+# we don't descend into intl after its makefile has been removed.
maintainer-clean:
@echo 'This command is intended for maintainers to use; it'
@echo 'deletes files that may need special tools to rebuild.'
- $(MAKE) distclean lang.maintainer-clean
+ $(MAKE) INTL_DISTCLEAN= distclean \
+ intl.maintainer-clean lang.maintainer-clean
-rm -f c-parse.y c-gperf.h
-rm -f c-parse.c c-parse.h c-parse.output
-rm -f cexp.c cexp.output TAGS
@@ -2265,7 +2433,7 @@ install: $(INSTALL_TARGET) ; @true
# Install the driver last so that the window when things are
# broken is small.
install-normal: install-common $(INSTALL_HEADERS) $(INSTALL_LIBGCC) \
- $(INSTALL_CPP) install-man install-info lang.install-normal \
+ $(INSTALL_CPP) install-man install-info intl.install lang.install-normal \
install-driver
# Do nothing while making gcc with a cross-compiler. The person who
@@ -2276,29 +2444,27 @@ install-build: force
# Run this on the target machine
# to finish installation of cross compiler.
+# This is not used anymore now that float.h does not depend on enquire.
install-cross-rest: install-float-h-cross
# Handle cpp installation.
-install-cpp: cpp.sh
- -rm -f $(bindir)/cpp
- $(INSTALL_PROGRAM) -m 755 cpp.sh $(bindir)/cpp
+install-cpp: xcpp$(exeext)
+ -rm -f $(bindir)/$(CPP_INSTALL_NAME)$(exeext)
+ $(INSTALL_PROGRAM) -m 755 xcpp$(exeext) $(bindir)/$(CPP_INSTALL_NAME)$(exeext)
if [ x$(cpp_install_dir) != x ]; then \
- rm -f $(cpp_install_dir)/cpp; \
- $(INSTALL_PROGRAM) -m 755 cpp.sh $(cpp_install_dir)/cpp; \
+ rm -f $(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) -m 755 xcpp$(exeext) $(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
else true; fi
-cpp.sh: $(srcdir)/cpp.in Makefile
- sed -e 's%@GCC@%'$(GCC_INSTALL_NAME)'%' $(srcdir)/cpp.in > xcpp.T
- mv -f xcpp.T cpp.sh
-
uninstall-cpp:
-rm -f $(bindir)/cpp
-if [ x$(cpp_install_dir) != x ]; then \
- rm -f $(cpp_install_dir)/cpp; \
+ rm -f $(prefix)/$(cpp_install_dir)/cpp; \
else true; fi
# Install float.h for cross compiler.
# Run this on the target machine!
+# This is not used anymore now that float.h does not depend on enquire.
install-float-h-cross: installdirs
# if [ -f enquire ] ; then true; else false; fi
# Note: don't use -. We should fail right away if enquire was not made.
@@ -2322,15 +2488,15 @@ installdirs:
done
-if [ -d $(bindir) ] ; then true ; else mkdir $(bindir) ; chmod a+rx $(bindir) ; fi
-if [ -d $(includedir) ] ; then true ; else mkdir $(includedir) ; chmod a+rx $(includedir) ; fi
- -if [ -d $(tooldir) ] ; then true ; else mkdir $(tooldir) ; chmod a+rx $(tooldir) ; fi
+ -if [ -d $(gcc_tooldir) ] ; then true ; else mkdir $(gcc_tooldir) ; chmod a+rx $(gcc_tooldir) ; fi
-if [ -d $(assertdir) ] ; then true ; else mkdir $(assertdir) ; chmod a+rx $(assertdir) ; fi
-if [ -d $(infodir) ] ; then true ; else mkdir $(infodir) ; chmod a+rx $(infodir) ; fi
-# We don't use mkdir -p to create the parents of mandir,
+# We don't use mkdir -p to create the parents of man1dir,
# because some systems don't support it.
-# Instead, we use this technique to create the immediate parent of mandir.
- -parent=`echo $(mandir)|sed -e 's@/[^/]*$$@@'`; \
+# Instead, we use this technique to create the immediate parent of man1dir.
+ -parent=`echo $(man1dir)|sed -e 's@/[^/]*$$@@'`; \
if [ -d $$parent ] ; then true ; else mkdir $$parent ; chmod a+rx $$parent ; fi
- -if [ -d $(mandir) ] ; then true ; else mkdir $(mandir) ; chmod a+rx $(mandir) ; fi
+ -if [ -d $(man1dir) ] ; then true ; else mkdir $(man1dir) ; chmod a+rx $(man1dir) ; fi
# Install the compiler executables built during cross compilation.
install-common: native installdirs $(EXTRA_PARTS) lang.install-common
@@ -2384,19 +2550,18 @@ install-common: native installdirs $(EXTRA_PARTS) lang.install-common
-if [ -f gcov$(exeext) ]; \
then \
rm -f $(bindir)/gcov$(exeext); \
- $(INSTALL_PROGRAM) gcov$(exeext) $(bindir)/gcov$(exeext); \
- chmod a+x $(bindir)/gcov$(exeext); \
+ $(INSTALL_PROGRAM) gcov$(exeext) $(bindir)/$(GCOV_INSTALL_NAME)$(exeext); \
fi
# Install the driver program as $(target_alias)-gcc
-# and also as either gcc (if native) or $(tooldir)/bin/gcc.
+# and also as either gcc (if native) or $(gcc_tooldir)/bin/gcc.
install-driver: xgcc$(exeext)
-if [ -f gcc-cross$(exeext) ] ; then \
rm -f $(bindir)/$(GCC_CROSS_NAME)$(exeext); \
$(INSTALL_PROGRAM) gcc-cross$(exeext) $(bindir)/$(GCC_CROSS_NAME)$(exeext); \
- if [ -d $(tooldir)/bin/. ] ; then \
- rm -f $(tooldir)/bin/gcc$(exeext); \
- $(INSTALL_PROGRAM) gcc-cross$(exeext) $(tooldir)/bin/gcc$(exeext); \
+ if [ -d $(gcc_tooldir)/bin/. ] ; then \
+ rm -f $(gcc_tooldir)/bin/gcc$(exeext); \
+ $(INSTALL_PROGRAM) gcc-cross$(exeext) $(gcc_tooldir)/bin/gcc$(exeext); \
else true; fi; \
else \
rm -f $(bindir)/$(GCC_INSTALL_NAME)$(exeext); \
@@ -2426,25 +2591,25 @@ install-info: doc installdirs lang.install-info
# Install the man pages.
install-man: installdirs $(srcdir)/gcc.1 $(srcdir)/cccp.1 lang.install-man
-if [ -f gcc-cross$(exeext) ] ; then \
- rm -f $(mandir)/$(GCC_CROSS_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/gcc.1 $(mandir)/$(GCC_CROSS_NAME)$(manext); \
- chmod a-x $(mandir)/$(GCC_CROSS_NAME)$(manext); \
+ rm -f $(man1dir)/$(GCC_CROSS_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/gcc.1 $(man1dir)/$(GCC_CROSS_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(GCC_CROSS_NAME)$(manext); \
else \
- rm -f $(mandir)/$(GCC_INSTALL_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/gcc.1 $(mandir)/$(GCC_INSTALL_NAME)$(manext); \
- chmod a-x $(mandir)/$(GCC_INSTALL_NAME)$(manext); \
+ rm -f $(man1dir)/$(GCC_INSTALL_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/gcc.1 $(man1dir)/$(GCC_INSTALL_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(GCC_INSTALL_NAME)$(manext); \
fi
- -rm -f $(mandir)/cccp$(manext)
- -$(INSTALL_DATA) $(srcdir)/cccp.1 $(mandir)/cccp$(manext)
- -chmod a-x $(mandir)/cccp$(manext)
+ -rm -f $(man1dir)/cccp$(manext)
+ -$(INSTALL_DATA) $(srcdir)/cccp.1 $(man1dir)/cccp$(manext)
+ -chmod a-x $(man1dir)/cccp$(manext)
# Install the library.
install-libgcc: libgcc.a installdirs
-if [ -f libgcc.a ] ; then \
rm -f $(libsubdir)/libgcc.a; \
$(INSTALL_DATA) libgcc.a $(libsubdir)/libgcc.a; \
- if $(RANLIB_TEST) ; then \
- (cd $(libsubdir); $(RANLIB) libgcc.a); else true; fi; \
+ if $(RANLIB_TEST_FOR_TARGET) ; then \
+ (cd $(libsubdir); $(RANLIB_FOR_TARGET) libgcc.a); else true; fi; \
chmod a-x $(libsubdir)/libgcc.a; \
else true; fi
@@ -2457,8 +2622,9 @@ install-multilib: stmp-multilib installdirs
rm -f $(libsubdir)/$${dir}/$${f}; \
$(INSTALL_DATA) $${dir}/$${f} $(libsubdir)/$${dir}/$${f}; \
done; \
- if $(RANLIB_TEST); then \
- (cd $(libsubdir)/$${dir}; $(RANLIB) libgcc.a); else true; fi; \
+ if $(RANLIB_TEST_FOR_TARGET); then \
+ (cd $(libsubdir)/$${dir}; $(RANLIB_FOR_TARGET) libgcc.a); \
+ else true; fi; \
chmod a-x $(libsubdir)/$${dir}/libgcc.a; \
done
@@ -2487,7 +2653,11 @@ install-include-dir: installdirs
# Install the include directory using tar.
install-headers-tar: stmp-headers $(STMP_FIXPROTO) install-include-dir
- (cd include; \
+# We use `pwd`/include instead of just include to problems with CDPATH
+# Unless a full pathname is provided, some shells would print the new CWD,
+# found in CDPATH, corrupting the output. We could just redirect the
+# output of `cd', but some shells lose on redirection within `()'s
+ (cd `pwd`/include ; \
tar -cf - .; exit 0) | (cd $(libsubdir)/include; tar $(TAROUTOPTS) - )
# /bin/sh on some systems returns the status of the first tar,
# and that can lose with GNU tar which always writes a full block.
@@ -2495,7 +2665,9 @@ install-headers-tar: stmp-headers $(STMP_FIXPROTO) install-include-dir
# Install the include directory using cpio.
install-headers-cpio: stmp-headers $(STMP_FIXPROTO) install-include-dir
- (cd include; find . -print) | (cd include; cpio -pdum $(libsubdir)/include)
+# See discussion about the use of `pwd` above
+ cd `pwd`/include ; \
+ find . -print | cpio -pdum $(libsubdir)/include
# Put assert.h where it won't override GNU libc's assert.h.
# It goes in a dir that is searched after GNU libc's headers;
@@ -2527,18 +2699,20 @@ install-collect2: collect2 installdirs
$(INSTALL_PROGRAM) xgcc$(exeext) $(libsubdir)/gcc$(exeext)
# Cancel installation by deleting the installed files.
-uninstall: lang.uninstall $(UNINSTALL_CPP)
+uninstall: intl.uninstall lang.uninstall $(UNINSTALL_CPP)
-rm -rf $(libsubdir)
-rm -rf $(bindir)/$(GCC_INSTALL_NAME)$(exeext)
-rm -rf $(bindir)/$(GCC_CROSS_NAME)$(exeext)
- -rm -rf $(bindir)/protoize$(exeext)
- -rm -rf $(bindir)/unprotoize$(exeext)
- -rm -rf $(bindir)/gcov$(exeext)
- -rm -rf $(mandir)/$(GCC_INSTALL_NAME)$(manext)
- -rm -rf $(mandir)/$(GCC_CROSS_NAME)$(manext)
- -rm -rf $(mandir)/cccp$(manext)
- -rm -rf $(mandir)/protoize$(manext)
- -rm -rf $(mandir)/unprotoize$(manext)
+ -rm -rf $(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext)
+ -rm -rf $(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext)
+ -rm -rf $(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext)
+ -rm -rf $(bindir)/$(UNPROTOIZE_CROSS_NAME)$(exeext)
+ -rm -rf $(bindir)/$(GCOV_INSTALL_NAME)$(exeext)
+ -rm -rf $(man1dir)/$(GCC_INSTALL_NAME)$(manext)
+ -rm -rf $(man1dir)/$(GCC_CROSS_NAME)$(manext)
+ -rm -rf $(man1dir)/cccp$(manext)
+ -rm -rf $(man1dir)/protoize$(manext)
+ -rm -rf $(man1dir)/unprotoize$(manext)
-rm -f $(infodir)/cpp.info* $(infodir)/gcc.info*
#
# These targets are for the dejagnu testsuites. The file site.exp
@@ -2593,7 +2767,7 @@ site.exp: ./config.status Makefile
-e '1,/^## All variables above are.*##/ d' >> site.exp
-@rm -f ./tmp?
-CHECK_TARGETS = check-gcc check-g++ check-g77
+CHECK_TARGETS = check-gcc check-g++ check-g77 check-objc
check: $(CHECK_TARGETS)
@@ -2612,7 +2786,7 @@ check-g++: testsuite/site.exp
cd testsuite; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=$${srcdir}/../tcl/library ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool g++ $(RUNTESTFLAGS)
@@ -2622,7 +2796,7 @@ check-gcc: testsuite/site.exp
cd testsuite; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=$${srcdir}/../tcl/library ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool gcc $(RUNTESTFLAGS)
@@ -2632,10 +2806,20 @@ check-g77: testsuite/site.exp
cd testsuite; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=$${srcdir}/../tcl/library ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool g77 $(RUNTESTFLAGS)
+check-objc: testsuite/site.exp
+ -rootme=`pwd`; export rootme; \
+ srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ cd testsuite; \
+ EXPECT=${EXPECT} ; export EXPECT ; \
+ if [ -f $${rootme}/../expect/expect ] ; then \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
+ export TCL_LIBRARY ; fi ; \
+ $(RUNTEST) --tool objc $(RUNTESTFLAGS)
+
# These exist for maintenance purposes.
# Update the tags table.
@@ -2657,22 +2841,27 @@ tmp-gcc.xtar: distdir
tar -chf tmp-gcc.xtar gcc-$(version)
distdir-cvs: force
- if [ -d $(srcdir)/CVS ]; then cvs -r update; fi
+ if [ -d $(srcdir)/CVS ]; then cd $(srcdir) && cvs -r update; fi
# This target exists to do the initial work before the language specific
# stuff gets done.
distdir-start: doc $(srcdir)/INSTALL $(srcdir)/c-parse.y $(srcdir)/c-gperf.h \
$(srcdir)/c-parse.c $(srcdir)/cexp.c $(srcdir)/config.in \
$(srcdir)/version.c TAGS
+ @case '$(USE_NLS)' in \
+ yes) ;; \
+ *) echo "configure with --enable-nls before making a distribution"; \
+ exit 1;; \
+ esac
@if grep -s "for version ${mainversion}" gcc.texi > /dev/null; \
then true; \
else echo "You must update the version number in \`gcc.texi'"; sleep 10;\
fi
# Update the version number in README
- awk '$$1 " " $$2 " " $$3 == "This directory contains" \
+ $(AWK) '$$1 " " $$2 " " $$3 == "This directory contains" \
{ $$6 = version; print $$0 } \
$$1 " " $$2 " " $$3 != "This directory contains"' \
- version=$(version) README > tmp.README
+ version=$(version) $(srcdir)/README > tmp.README
mv tmp.README README
-rm -rf gcc-$(version) tmp
# Put all the files in a temporary subdirectory
@@ -2680,31 +2869,35 @@ distdir-start: doc $(srcdir)/INSTALL $(srcdir)/c-parse.y $(srcdir)/c-gperf.h \
mkdir tmp
mkdir tmp/config
mkdir tmp/ginclude
- for file in *[0-9a-zA-Z+]; do \
- $(LN) $$file tmp; \
+ mkdir tmp/objc
+ mkdir tmp/intl
+ mkdir tmp/po
+ for file in `(cd $(srcdir) && echo *[0-9a-zA-Z+])`; do \
+ test -f $(srcdir)/$$file && $(LN_S) $(srcdir)/$$file tmp; \
done
- cd config; \
- for file in *[0-9a-zA-Z+]; do \
- if test -d $$file && test "$$file" != RCS && test "$$file" != CVS; then \
- mkdir ../tmp/config/$$file; \
- cd $$file; \
- for subfile in *[0-9a-zA-Z+]; do \
- $(LN) $$subfile ../../tmp/config/$$file; \
+ if test "$(srcdir)" != "." ; then \
+ for file in c-parse.c cexp.c ; do \
+ test -f ./$$file && $(LN_S) ../$$file tmp; \
+ done; \
+ fi
+ for file in `(cd $(srcdir)/config && echo *[0-9a-zA-Z+])`; do \
+ if test -d $(srcdir)/config/$$file \
+ && test "$$file" != RCS && test "$$file" != CVS; then \
+ mkdir tmp/config/$$file; \
+ for subfile in `(cd $(srcdir)/config/$$file && echo *[0-9a-zA-Z+])`; do \
+ $(LN_S) $(srcdir)/config/$$file/$$subfile tmp/config/$$file; \
done; \
- cd ..; \
else \
- $(LN) $$file ../tmp/config; \
+ $(LN_S) $(srcdir)/config/$$file tmp/config; \
fi; \
done
- cd ginclude; \
- for file in *[0-9a-zA-Z+]; do \
- $(LN) $$file ../tmp/ginclude; \
+ for file in `(cd $(srcdir)/ginclude && echo *[0-9a-zA-Z+])`; do \
+ $(LN_S) $(srcdir)/ginclude/$$file tmp/ginclude; \
done
- cd objc; \
- for file in *[0-9a-zA-Z+]; do \
- $(LN) $$file ../tmp/objc; \
+ for file in `(cd $(srcdir)/objc && echo *[0-9a-zA-Z+])`; do \
+ $(LN_S) $(srcdir)/objc/$$file tmp/objc; \
done
- $(LN) .gdbinit tmp
+ $(LN_S) .gdbinit tmp
# Finish making `distdir', after the languages have done their thing.
distdir-finish:
@@ -2712,9 +2905,21 @@ distdir-finish:
# Get rid of everything we don't want in the distribution. We'd want
# this to use Makefile.in, but it doesn't have the `lang.foo' targets
# expanded.
- cd gcc-$(version); make extraclean VERSION_DEP=
+ cd gcc-$(version); make extraclean distdir-check VERSION_DEP=
+
+distdir-check:
+ ($(AWK) '/^[^#]/{print} /^#[A-Za-z]/{print substr($$1, 2)}' | sort) \
+ < po/POTFILES.in > tmp.POTFILES
+ ls [A-Za-z]*.[ch] [a-z]*/[A-Za-z]*.[ch] \
+ [a-z]*/[a-z]*/[A-Za-z]*.[ch] | sort > tmp.src
+ diff tmp.POTFILES tmp.src || { \
+ echo "po/POTFILES.in and sources do not match -- please fix"; \
+ exit 1; \
+ }
+ rm -f tmp.*
-distdir: distdir-cvs distdir-start lang.distdir distdir-finish
+distdir: distdir-cvs distdir-start intl.distdir intl.distdir-fixup \
+ lang.distdir distdir-finish
# make diff oldversion=M.N
# creates a diff file between an older distribution and this one.
@@ -2739,22 +2944,22 @@ bootstrap bootstrap-lean: force
# To prevent `make install' from compiling alloca.o and then relinking cc1
# because alloca.o is newer, we permit these recursive makes to compile
# alloca.o. Then cc1 is newer, so it won't have to be relinked.
- $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage1/ LANGUAGES="$(LANGUAGES)"
+ $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage1/ LANGUAGES="$(LANGUAGES)"
$(MAKE) stage2
-if test $@ = bootstrap-lean; then rm -rf stage1; else true; fi
- $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)"
+ $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)"
bootstrap2 bootstrap2-lean: force
- $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage1/ LANGUAGES="$(LANGUAGES)"
+ $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage1/ LANGUAGES="$(LANGUAGES)"
$(MAKE) stage2
-if test $@ = bootstrap2-lean; then rm -rf stage1; else true; fi
- $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)"
+ $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)"
bootstrap3 bootstrap3-lean: force
- $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)"
+ $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage2/ LANGUAGES="$(LANGUAGES)"
bootstrap4 bootstrap4-lean: force
- $(MAKE) CC="stage3/xgcc$(exeext) -Bstage3/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage3/ LANGUAGES="$(LANGUAGES)"
+ $(MAKE) CC="stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" CFLAGS="$(WARN_CFLAGS) $(BOOT_CFLAGS)" LDFLAGS="$(BOOT_LDFLAGS)" libdir=$(libdir) STAGE_PREFIX=stage3/ LANGUAGES="$(LANGUAGES)"
# Compare the object files in the current directory with those in the
# stage2 directory.
@@ -2769,16 +2974,14 @@ compare compare3 compare4 compare-lean compare3-lean compare4-lean: force
&& (cmp tmp-foo1 tmp-foo2 > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
done
case "$@" in compare | compare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^compare\([0-9][0-9]*\).*,\1,'` ;; esac; \
- for dir in tmp-foo $(SUBDIRS); do \
+ for dir in tmp-foo intl $(SUBDIRS); do \
if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \
for file in $$dir/*$(objext); do \
- if [ $$file != objc/NXConstStr.o -a $$file != objc/Object.o -a $$file != objc/Protocol.o -a $$file != objc/linking.o ] ; then \
- tail +16c ./$$file > tmp-foo1; \
- tail +16c stage$$stage/$$file > tmp-foo2 \
- && (cmp tmp-foo1 tmp-foo2 > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
- else true; fi; \
+ tail +16c ./$$file > tmp-foo1; \
+ tail +16c stage$$stage/$$file > tmp-foo2 \
+ && (cmp tmp-foo1 tmp-foo2 > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
done; \
- fi; \
+ else true; fi; \
done
-rm -f tmp-foo*
case "$@" in compare | compare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^compare\([0-9][0-9]*\).*,\1,'` ;; esac; \
@@ -2804,14 +3007,12 @@ gnucompare gnucompare3 gnucompare4 gnucompare-lean gnucompare3-lean gnucompare4-
(cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
done
case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \
- for dir in tmp-foo $(SUBDIRS); do \
+ for dir in tmp-foo intl $(SUBDIRS); do \
if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \
for file in $$dir/*$(objext); do \
- if [ $$file != objc/NXConstStr.o -a $$file != objc/Object.o -a $$file != objc/Protocol.o -a $$file != objc/linking.o ] ; then \
- (cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
- else true; fi; \
+ (cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
done; \
- fi; \
+ else true; fi; \
done
case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \
if [ -f .bad_compare ]; then \
@@ -2827,11 +3028,12 @@ gnucompare gnucompare3 gnucompare4 gnucompare-lean gnucompare3-lean gnucompare4-
# Copy the object files from a particular stage into a subdirectory.
stage1-start:
-if [ -d stage1 ] ; then true ; else mkdir stage1 ; fi
- -for dir in . $(SUBDIRS) ; \
+ -for dir in intl $(SUBDIRS) ; \
do \
if [ -d stage1/$$dir ] ; then true ; else mkdir stage1/$$dir ; fi ; \
done
-mv $(STAGESTUFF) stage1
+ -mv intl/*$(objext) stage1/intl
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage1 ; else true ; fi
@@ -2839,7 +3041,9 @@ stage1-start:
-if [ -f collect-ld$(exeext) ] ; then $(LN_S) ../collect-ld$(exeext) stage1 ; else true ; fi
-rm -f stage1/libgcc.a
-cp libgcc.a stage1
- -if $(RANLIB_TEST) ; then $(RANLIB) stage1/libgcc.a; else true; fi
+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
+ $(RANLIB_FOR_TARGET) stage1/libgcc.a; \
+ else true; fi
-for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
cp stage1/$${f} . ; \
else true; \
@@ -2848,11 +3052,12 @@ stage1: force stage1-start lang.stage1
stage2-start:
-if [ -d stage2 ] ; then true ; else mkdir stage2 ; fi
- -for dir in . $(SUBDIRS) ; \
+ -for dir in intl $(SUBDIRS) ; \
do \
if [ -d stage2/$$dir ] ; then true ; else mkdir stage2/$$dir ; fi ; \
done
-mv $(STAGESTUFF) stage2
+ -mv intl/*$(objext) stage2/intl
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage2 ; else true ; fi
@@ -2860,7 +3065,9 @@ stage2-start:
-if [ -f collect-ld ] ; then $(LN_S) ../collect-ld$(exeext) stage2 ; else true ; fi
-rm -f stage2/libgcc.a
-cp libgcc.a stage2
- -if $(RANLIB_TEST) ; then $(RANLIB) stage2/libgcc.a; else true; fi
+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
+ $(RANLIB_FOR_TARGET) stage2/libgcc.a; \
+ else true; fi
-for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
cp stage2/$${f} . ; \
else true; \
@@ -2869,11 +3076,12 @@ stage2: force stage2-start lang.stage2
stage3-start:
-if [ -d stage3 ] ; then true ; else mkdir stage3 ; fi
- -for dir in . $(SUBDIRS) ; \
+ -for dir in intl $(SUBDIRS) ; \
do \
if [ -d stage3/$$dir ] ; then true ; else mkdir stage3/$$dir ; fi ; \
done
-mv $(STAGESTUFF) stage3
+ -mv intl/*$(objext) stage3/intl
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage3 ; else true ; fi
@@ -2881,7 +3089,9 @@ stage3-start:
-if [ -f collect-ld$(exeext) ] ; then $(LN_S) ../collect-ld$(exeext) stage3 ; else true ; fi
-rm -f stage3/libgcc.a
-cp libgcc.a stage3
- -if $(RANLIB_TEST) ; then $(RANLIB) stage3/libgcc.a; else true; fi
+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
+ $(RANLIB_FOR_TARGET) stage3/libgcc.a; \
+ else true; fi
-for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
cp stage3/$${f} . ; \
else true; \
@@ -2890,11 +3100,12 @@ stage3: force stage3-start lang.stage3
stage4-start:
-if [ -d stage4 ] ; then true ; else mkdir stage4 ; fi
- -for dir in . $(SUBDIRS) ; \
+ -for dir in intl $(SUBDIRS) ; \
do \
if [ -d stage4/$$dir ] ; then true ; else mkdir stage4/$$dir ; fi ; \
done
-mv $(STAGESTUFF) stage4
+ -mv intl/*$(objext) stage4/intl
# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
# dir will work properly.
-if [ -f as$(exeext) ] ; then $(LN_S) ../as$(exeext) stage4 ; else true ; fi
@@ -2902,7 +3113,9 @@ stage4-start:
-if [ -f collect-ld$(exeext) ] ; then $(LN_S) ../collect-ld$(exeext) stage4 ; else true ; fi
-rm -f stage4/libgcc.a
-cp libgcc.a stage4
- -if $(RANLIB_TEST) ; then $(RANLIB) stage4/libgcc.a; else true; fi
+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
+ $(RANLIB_FOR_TARGET) stage4/libgcc.a; \
+ else true; fi
-for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
cp stage4/$${f} . ; \
else true; \
diff --git a/contrib/gcc/NEWS b/contrib/gcc/NEWS
index 628b03c..427df25 100644
--- a/contrib/gcc/NEWS
+++ b/contrib/gcc/NEWS
@@ -1,3 +1,11 @@
+Noteworthy changes in GCC after EGCS 1.1.
+-----------------------------------------
+
+Target specific NEWS
+
+ RS6000/PowerPC: -mcpu=401 was added as an alias for -mcpu=403. -mcpu=e603e
+ was added to do -mcpu=603e and -msoft-float.
+
Noteworthy changes in GCC for EGCS 1.1.
---------------------------------------
diff --git a/contrib/gcc/README b/contrib/gcc/README
index c606f65..a12bf75 100644
--- a/contrib/gcc/README
+++ b/contrib/gcc/README
@@ -1,8 +1,8 @@
-This directory contains the egcs version 1.1.2 release of the GNU C
-compiler. It includes all of the support for compiling C++ and
-Objective C, including a run-time library for Objective C.
+This directory contains the GNU Compiler Collection (GCC) version 2.95.
+It includes all of the support for compiling C, C++, Objective C, Fortran,
+Java, and Chill.
-The GNU C compiler is free software. See the file COPYING for copying
+The GNU Compiler Collection is free software. See the file COPYING for copying
permission.
See the file gcc.texi (together with other files that it includes) for
diff --git a/contrib/gcc/acconfig.h b/contrib/gcc/acconfig.h
index e1ac384..d702b0e 100644
--- a/contrib/gcc/acconfig.h
+++ b/contrib/gcc/acconfig.h
@@ -1,9 +1,21 @@
+/* Define if you can safely include both <string.h> and <strings.h>. */
+#undef STRING_WITH_STRINGS
+
/* Define if printf supports "%p". */
#undef HAVE_PRINTF_PTR
/* Define if you want expensive run-time checks. */
#undef ENABLE_CHECKING
+/* Define to 1 if NLS is requested. */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have catgets and don't want to use GNU gettext. */
+#undef HAVE_CATGETS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+#undef HAVE_GETTEXT
+
/* Define if your cpp understands the stringify operator. */
#undef HAVE_CPP_STRINGIFY
@@ -17,9 +29,22 @@
/* Define if your assembler supports .balign and .p2align. */
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
+/* Define if your assembler supports .subsection and .subsection -1 starts
+ emitting at the beginning of your section */
+#undef HAVE_GAS_SUBSECTION_ORDERING
+
+/* Define if your assembler uses the old HImode fild and fist notation. */
+#undef HAVE_GAS_FILDS_FISTS
+
/* Define if you have a working <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
+/* Define if your locale.h file contains LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define as 1 if you have the stpcpy function. */
+#undef HAVE_STPCPY
+
/* Whether malloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_MALLOC
@@ -53,6 +78,9 @@
/* Whether atol must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_ATOL
+/* Whether atof must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_ATOF
+
/* Whether sbrk must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_SBRK
@@ -62,6 +90,12 @@
/* Whether strerror must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRERROR
+/* Whether strsignal must be declared even if <string.h> is included. */
+#undef NEED_DECLARATION_STRSIGNAL
+
+/* Whether strstr must be declared even if <string.h> is included. */
+#undef NEED_DECLARATION_STRSTR
+
/* Whether getcwd must be declared even if <unistd.h> is included. */
#undef NEED_DECLARATION_GETCWD
@@ -74,6 +108,24 @@
/* Whether setrlimit must be declared even if <sys/resource.h> is included. */
#undef NEED_DECLARATION_SETRLIMIT
-/* Define if you want expensive run-time checks. */
-#undef ENABLE_CHECKING
+/* Whether putc_unlocked must be declared even if <stdio.h> is included. */
+#undef NEED_DECLARATION_PUTC_UNLOCKED
+
+/* Whether fputs_unlocked must be declared even if <stdio.h> is included. */
+#undef NEED_DECLARATION_FPUTS_UNLOCKED
+
+/* Define to enable the use of a default assembler. */
+#undef DEFAULT_ASSEMBLER
+
+/* Define to enable the use of a default linker. */
+#undef DEFAULT_LINKER
+
+/* Define if host mkdir takes a single argument. */
+#undef MKDIR_TAKES_ONE_ARG
+
+/* Define to the name of the distribution. */
+#undef PACKAGE
+
+/* Define to the version of the distribution. */
+#undef VERSION
@TOP@
diff --git a/contrib/gcc/aclocal.m4 b/contrib/gcc/aclocal.m4
index febe8a7..fe4d832 100644
--- a/contrib/gcc/aclocal.m4
+++ b/contrib/gcc/aclocal.m4
@@ -1,3 +1,14 @@
+dnl See whether we can include both string.h and strings.h.
+AC_DEFUN(GCC_HEADER_STRING,
+[AC_CACHE_CHECK([whether string.h and strings.h may both be included],
+ gcc_cv_header_string,
+[AC_TRY_COMPILE([#include <string.h>
+#include <strings.h>], , gcc_cv_header_string=yes, gcc_cv_header_string=no)])
+if test $gcc_cv_header_string = yes; then
+ AC_DEFINE(STRING_WITH_STRINGS)
+fi
+])
+
dnl See whether we need a declaration for a function.
dnl GCC_NEED_DECLARATION(FUNCTION [, EXTRA-HEADER-FILES])
AC_DEFUN(GCC_NEED_DECLARATION,
@@ -5,12 +16,17 @@ AC_DEFUN(GCC_NEED_DECLARATION,
AC_CACHE_VAL(gcc_cv_decl_needed_$1,
[AC_TRY_COMPILE([
#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
+#ifdef STRING_WITH_STRINGS
+# include <string.h>
+# include <strings.h>
#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
+# ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
+# endif
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -156,6 +172,27 @@ if test $gcc_cv_c_volatile = yes ; then
fi
])
+dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
+dnl of the usual 2.
+AC_DEFUN(GCC_FUNC_MKDIR_TAKES_ONE_ARG,
+[AC_CACHE_CHECK([if mkdir takes one argument], gcc_cv_mkdir_takes_one_arg,
+[AC_TRY_COMPILE([
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#endif], [mkdir ("foo", 0);],
+ gcc_cv_mkdir_takes_one_arg=no, gcc_cv_mkdir_takes_one_arg=yes)])
+if test $gcc_cv_mkdir_takes_one_arg = yes ; then
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG)
+fi
+])
+
AC_DEFUN(EGCS_PROG_INSTALL,
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
# Find a good install program. We prefer a C program (faster),
@@ -219,3 +256,404 @@ AC_SUBST(INSTALL_PROGRAM)dnl
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
AC_SUBST(INSTALL_DATA)dnl
])
+
+#serial 1
+dnl This test replaces the one in autoconf.
+dnl Currently this macro should have the same name as the autoconf macro
+dnl because gettext's gettext.m4 (distributed in the automake package)
+dnl still uses it. Otherwise, the use in gettext.m4 makes autoheader
+dnl give these diagnostics:
+dnl configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX
+dnl configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX
+
+undefine([AC_ISC_POSIX])
+AC_DEFUN(AC_ISC_POSIX,
+ [
+ dnl This test replaces the obsolescent AC_ISC_POSIX kludge.
+ AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"])
+ ]
+)
+
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file can be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 5
+
+AC_DEFUN(AM_WITH_NLS,
+ [AC_MSG_CHECKING([whether NLS is requested])
+ dnl Default is enabled NLS
+ AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+ AC_MSG_RESULT($USE_NLS)
+ AC_SUBST(USE_NLS)
+
+ USE_INCLUDED_LIBINTL=no
+
+ dnl If we use NLS figure out what method
+ if test "$USE_NLS" = "yes"; then
+ AC_DEFINE(ENABLE_NLS)
+ AC_MSG_CHECKING([whether included gettext is requested])
+ AC_ARG_WITH(included-gettext,
+ [ --with-included-gettext use the GNU gettext library included here],
+ nls_cv_force_use_gnu_gettext=$withval,
+ nls_cv_force_use_gnu_gettext=no)
+ AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ dnl User does not insist on using GNU NLS library. Figure out what
+ dnl to use. If gettext or catgets are available (in this order) we
+ dnl use this. Else we have to fall back to GNU NLS library.
+ dnl catgets is only used if permitted by option --with-catgets.
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ AC_CHECK_HEADER(libintl.h,
+ [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
+ [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
+ gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ AC_CHECK_LIB(intl, bindtextdomain,
+ [AC_CACHE_CHECK([for gettext in libintl],
+ gt_cv_func_gettext_libintl,
+ [AC_CHECK_LIB(intl, gettext,
+ gt_cv_func_gettext_libintl=yes,
+ gt_cv_func_gettext_libintl=no)],
+ gt_cv_func_gettext_libintl=no)])
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ AC_DEFINE(HAVE_GETTEXT)
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+ if test "$MSGFMT" != "no"; then
+ AC_CHECK_FUNCS(dcgettext)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr],
+ [CATOBJEXT=.gmo
+ DATADIRNAME=share],
+ [CATOBJEXT=.mo
+ DATADIRNAME=lib])
+ INSTOBJEXT=.mo
+ fi
+ fi
+ ])
+
+ if test "$CATOBJEXT" = "NONE"; then
+ AC_MSG_CHECKING([whether catgets can be used])
+ AC_ARG_WITH(catgets,
+ [ --with-catgets use catgets functions if available],
+ nls_cv_use_catgets=$withval, nls_cv_use_catgets=no)
+ AC_MSG_RESULT($nls_cv_use_catgets)
+
+ if test "$nls_cv_use_catgets" = "yes"; then
+ dnl No gettext in C library. Try catgets next.
+ AC_CHECK_LIB(i, main)
+ AC_CHECK_FUNC(catgets,
+ [AC_DEFINE(HAVE_CATGETS)
+ INTLOBJS="\$(CATOBJS)"
+ AC_PATH_PROG(GENCAT, gencat, no)dnl
+ if test "$GENCAT" != "no"; then
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, no)
+ if test "$GMSGFMT" = "no"; then
+ AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)
+ fi
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.cat
+ INSTOBJEXT=.cat
+ DATADIRNAME=lib
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi])
+ fi
+ fi
+
+ if test "$CATOBJEXT" = "NONE"; then
+ dnl Neither gettext nor catgets in included in the C library.
+ dnl Fall back on GNU gettext library.
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ dnl Mark actions used to generate GNU NLS library.
+ INTLOBJS="\$(GETTOBJS)"
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_SUBST(MSGFMT)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+
+ dnl Test whether we really found GNU xgettext.
+ if test "$XGETTEXT" != ":"; then
+ dnl If it is no GNU xgettext we define it as : so that the
+ dnl Makefiles still can work.
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ AC_MSG_RESULT(
+ [found xgettext program is not GNU xgettext; ignore it])
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+ AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl)
+ AC_OUTPUT_COMMANDS(
+ [case "$CONFIG_FILES" in *po/Makefile.in*)
+ sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+ esac])
+
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ dnl These rules are solely for the distribution goal. While doing this
+ dnl we only have to keep exactly one list of the available catalogs
+ dnl in configure.in.
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+ dnl Make all variables we use known to autoconf.
+ AC_SUBST(USE_INCLUDED_LIBINTL)
+ AC_SUBST(CATALOGS)
+ AC_SUBST(CATOBJEXT)
+ AC_SUBST(DATADIRNAME)
+ AC_SUBST(GMOFILES)
+ AC_SUBST(INSTOBJEXT)
+ AC_SUBST(INTLDEPS)
+ AC_SUBST(INTLLIBS)
+ AC_SUBST(INTLOBJS)
+ AC_SUBST(POFILES)
+ AC_SUBST(POSUB)
+ ])
+
+AC_DEFUN(AM_GNU_GETTEXT,
+ [AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_RANLIB])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+ AC_REQUIRE([AC_C_CONST])dnl
+ AC_REQUIRE([AC_C_INLINE])dnl
+ AC_REQUIRE([AC_TYPE_OFF_T])dnl
+ AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+ AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+ AC_REQUIRE([AC_FUNC_MMAP])dnl
+
+ AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h sys/param.h])
+ AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
+strdup __argz_count __argz_stringify __argz_next])
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ AC_CHECK_FUNCS(stpcpy)
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ AC_DEFINE(HAVE_STPCPY)
+ fi
+
+ AM_LC_MESSAGES
+ AM_WITH_NLS
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ AC_MSG_CHECKING(for catalogs to be installed)
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ AC_MSG_RESULT($LINGUAS)
+ fi
+
+ dnl Construct list of names of catalog files to be constructed.
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ dnl The reference to <locale.h> in the installed <libintl.h> file
+ dnl must be resolved because we cannot expect the users of this
+ dnl to define HAVE_LOCALE_H.
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+ AC_SUBST(INCLUDE_LOCALE_H)
+
+ dnl Determine which catalog format we have (if any is needed)
+ dnl For now we know about two different formats:
+ dnl Linux libc-5 and the normal X/Open format
+ test -d intl || mkdir intl
+ if test "$CATOBJEXT" = ".cat"; then
+ AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
+
+ dnl Transform the SED scripts while copying because some dumb SEDs
+ dnl cannot handle comments.
+ sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
+ fi
+ dnl po2tbl.sed is always needed.
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed
+
+ dnl In the intl/Makefile.in we have a special dependency which makes
+ dnl only sense for gettext. We comment this out for non-gettext
+ dnl packages.
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+ AC_SUBST(GT_NO)
+ AC_SUBST(GT_YES)
+
+ dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
+ dnl find the mkinstalldirs script in another subdir but ($top_srcdir).
+ dnl Try to locate is.
+ MKINSTALLDIRS=
+ if test -n "$ac_aux_dir"; then
+ MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
+ fi
+ if test -z "$MKINSTALLDIRS"; then
+ MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+ fi
+ AC_SUBST(MKINSTALLDIRS)
+
+ dnl *** For now the libtool support in intl/Makefile is not for real.
+ l=
+ AC_SUBST(l)
+
+ dnl Generate list of files to be processed by xgettext which will
+ dnl be included in po/Makefile.
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+ ])
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file can be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+AC_DEFUN(AM_LC_MESSAGES,
+ [if test $ac_cv_header_locale_h = yes; then
+ AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+ [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+ am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ AC_DEFINE(HAVE_LC_MESSAGES)
+ fi
+ fi])
+
+# Search path for a program which passes the given test.
+# Ulrich Drepper <drepper@cygnus.com>, 1996.
+#
+# This file can be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AM_PATH_PROG_WITH_TEST,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+ /*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in ifelse([$5], , $PATH, [$5]); do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if [$3]; then
+ ac_cv_path_$1="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+ AC_MSG_RESULT([$]$1)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
diff --git a/contrib/gcc/alias.c b/contrib/gcc/alias.c
index 172b676..9d8aac7 100644
--- a/contrib/gcc/alias.c
+++ b/contrib/gcc/alias.c
@@ -1,5 +1,5 @@
/* Alias analysis for GNU C
- Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
Contributed by John Carr (jfc@mit.edu).
This file is part of GNU CC.
@@ -26,7 +26,51 @@ Boston, MA 02111-1307, USA. */
#include "regs.h"
#include "hard-reg-set.h"
#include "flags.h"
+#include "output.h"
#include "toplev.h"
+#include "splay-tree.h"
+
+/* The alias sets assigned to MEMs assist the back-end in determining
+ which MEMs can alias which other MEMs. In general, two MEMs in
+ different alias sets to not alias each other. There is one
+ exception, however. Consider something like:
+
+ struct S {int i; double d; };
+
+ a store to an `S' can alias something of either type `int' or type
+ `double'. (However, a store to an `int' cannot alias a `double'
+ and vice versa.) We indicate this via a tree structure that looks
+ like:
+ struct S
+ / \
+ / \
+ |/_ _\|
+ int double
+
+ (The arrows are directed and point downwards.) If, when comparing
+ two alias sets, we can hold one set fixed, and trace the other set
+ downwards, and at some point find the first set, the two MEMs can
+ alias one another. In this situation we say the alias set for
+ `struct S' is the `superset' and that those for `int' and `double'
+ are `subsets'.
+
+ Alias set zero is implicitly a superset of all other alias sets.
+ However, this is no actual entry for alias set zero. It is an
+ error to attempt to explicitly construct a subset of zero. */
+
+typedef struct alias_set_entry {
+ /* The alias set number, as stored in MEM_ALIAS_SET. */
+ int alias_set;
+
+ /* The children of the alias set. These are not just the immediate
+ children, but, in fact, all children. So, if we have:
+
+ struct T { struct S s; float f; }
+
+ continuing our example above, the children here will be all of
+ `int', `double', `float', and `struct S'. */
+ splay_tree children;
+}* alias_set_entry;
static rtx canon_rtx PROTO((rtx));
static int rtx_equal_for_memref_p PROTO((rtx, rtx));
@@ -35,34 +79,27 @@ static int memrefs_conflict_p PROTO((int, rtx, int, rtx,
HOST_WIDE_INT));
static void record_set PROTO((rtx, rtx));
static rtx find_base_term PROTO((rtx));
-static int base_alias_check PROTO((rtx, rtx));
+static int base_alias_check PROTO((rtx, rtx, enum machine_mode,
+ enum machine_mode));
static rtx find_base_value PROTO((rtx));
+static int mems_in_disjoint_alias_sets_p PROTO((rtx, rtx));
+static int insert_subset_children PROTO((splay_tree_node,
+ void*));
+static alias_set_entry get_alias_set_entry PROTO((int));
+static rtx fixed_scalar_and_varying_struct_p PROTO((rtx, rtx, int (*)(rtx)));
+static int aliases_everything_p PROTO((rtx));
+static int write_dependence_p PROTO((rtx, rtx, int));
/* Set up all info needed to perform alias analysis on memory references. */
#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
-/* Perform a basic sanity check. Namely, that there are
- no alias sets if we're not doing strict aliasing. This helps
- to catch bugs whereby someone uses PUT_CODE, but doesn't clear
- MEM_ALIAS_SET, or where a MEM is allocated in some way other
- than by the use of gen_rtx_MEM, and the MEM_ALIAS_SET is not
- cleared. */
-#ifdef ENABLE_CHECKING
-#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) \
- (!flag_strict_aliasing \
- && (MEM_ALIAS_SET (MEM1) || MEM_ALIAS_SET (MEM2)) \
- ? (abort (), 0) : 0)
-#else
-#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) ((void)0)
-#endif
-
/* Returns nonzero if MEM1 and MEM2 do not alias because they are in
- different alias sets. */
-#define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \
- (CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2), \
- MEM_ALIAS_SET (MEM1) && MEM_ALIAS_SET (MEM2) \
- && MEM_ALIAS_SET (MEM1) != MEM_ALIAS_SET (MEM2))
+ different alias sets. We ignore alias sets in functions making use
+ of variable arguments because the va_arg macros on some systems are
+ not legal ANSI C. */
+#define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \
+ mems_in_disjoint_alias_sets_p (MEM1, MEM2)
/* Cap the number of passes we make over the insns propagating alias
information through set chains.
@@ -89,7 +126,7 @@ rtx *reg_base_value;
rtx *new_reg_base_value;
unsigned int reg_base_value_size; /* size of reg_base_value array */
#define REG_BASE_VALUE(X) \
- (REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
+ ((unsigned) REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
/* Vector of known invariant relationships between registers. Set in
loop unrolling. Indexed by register number, if nonzero the value
@@ -126,6 +163,148 @@ char *reg_known_equiv_p;
static int copying_arguments;
+/* The splay-tree used to store the various alias set entries. */
+
+static splay_tree alias_sets;
+
+/* Returns a pointer to the alias set entry for ALIAS_SET, if there is
+ such an entry, or NULL otherwise. */
+
+static alias_set_entry
+get_alias_set_entry (alias_set)
+ int alias_set;
+{
+ splay_tree_node sn =
+ splay_tree_lookup (alias_sets, (splay_tree_key) alias_set);
+
+ return sn ? ((alias_set_entry) sn->value) : ((alias_set_entry) 0);
+}
+
+/* Returns nonzero value if the alias sets for MEM1 and MEM2 are such
+ that the two MEMs cannot alias each other. */
+
+static int
+mems_in_disjoint_alias_sets_p (mem1, mem2)
+ rtx mem1;
+ rtx mem2;
+{
+ alias_set_entry ase;
+
+#ifdef ENABLE_CHECKING
+/* Perform a basic sanity check. Namely, that there are no alias sets
+ if we're not using strict aliasing. This helps to catch bugs
+ whereby someone uses PUT_CODE, but doesn't clear MEM_ALIAS_SET, or
+ where a MEM is allocated in some way other than by the use of
+ gen_rtx_MEM, and the MEM_ALIAS_SET is not cleared. If we begin to
+ use alias sets to indicate that spilled registers cannot alias each
+ other, we might need to remove this check. */
+ if (!flag_strict_aliasing &&
+ (MEM_ALIAS_SET (mem1) || MEM_ALIAS_SET (mem2)))
+ abort ();
+#endif
+
+ /* The code used in varargs macros are often not conforming ANSI C,
+ which can trick the compiler into making incorrect aliasing
+ assumptions in these functions. So, we don't use alias sets in
+ such a function. FIXME: This should be moved into the front-end;
+ it is a language-dependent notion, and there's no reason not to
+ still use these checks to handle globals. */
+ if (current_function_stdarg || current_function_varargs)
+ return 0;
+
+ if (!MEM_ALIAS_SET (mem1) || !MEM_ALIAS_SET (mem2))
+ /* We have no alias set information for one of the MEMs, so we
+ have to assume it can alias anything. */
+ return 0;
+
+ if (MEM_ALIAS_SET (mem1) == MEM_ALIAS_SET (mem2))
+ /* The two alias sets are the same, so they may alias. */
+ return 0;
+
+ /* Iterate through each of the children of the first alias set,
+ comparing it with the second alias set. */
+ ase = get_alias_set_entry (MEM_ALIAS_SET (mem1));
+ if (ase && splay_tree_lookup (ase->children,
+ (splay_tree_key) MEM_ALIAS_SET (mem2)))
+ return 0;
+
+ /* Now do the same, but with the alias sets reversed. */
+ ase = get_alias_set_entry (MEM_ALIAS_SET (mem2));
+ if (ase && splay_tree_lookup (ase->children,
+ (splay_tree_key) MEM_ALIAS_SET (mem1)))
+ return 0;
+
+ /* The two MEMs are in distinct alias sets, and neither one is the
+ child of the other. Therefore, they cannot alias. */
+ return 1;
+}
+
+/* Insert the NODE into the splay tree given by DATA. Used by
+ record_alias_subset via splay_tree_foreach. */
+
+static int
+insert_subset_children (node, data)
+ splay_tree_node node;
+ void *data;
+{
+ splay_tree_insert ((splay_tree) data,
+ node->key,
+ node->value);
+
+ return 0;
+}
+
+/* Indicate that things in SUBSET can alias things in SUPERSET, but
+ not vice versa. For example, in C, a store to an `int' can alias a
+ structure containing an `int', but not vice versa. Here, the
+ structure would be the SUPERSET and `int' the SUBSET. This
+ function should be called only once per SUPERSET/SUBSET pair. At
+ present any given alias set may only be a subset of one superset.
+
+ It is illegal for SUPERSET to be zero; everything is implicitly a
+ subset of alias set zero. */
+
+void
+record_alias_subset (superset, subset)
+ int superset;
+ int subset;
+{
+ alias_set_entry superset_entry;
+ alias_set_entry subset_entry;
+
+ if (superset == 0)
+ abort ();
+
+ superset_entry = get_alias_set_entry (superset);
+ if (!superset_entry)
+ {
+ /* Create an entry for the SUPERSET, so that we have a place to
+ attach the SUBSET. */
+ superset_entry =
+ (alias_set_entry) xmalloc (sizeof (struct alias_set_entry));
+ superset_entry->alias_set = superset;
+ superset_entry->children
+ = splay_tree_new (splay_tree_compare_ints, 0, 0);
+ splay_tree_insert (alias_sets,
+ (splay_tree_key) superset,
+ (splay_tree_value) superset_entry);
+
+ }
+
+ subset_entry = get_alias_set_entry (subset);
+ if (subset_entry)
+ /* There is an entry for the subset. Enter all of its children
+ (if they are not already present) as children of the SUPERSET. */
+ splay_tree_foreach (subset_entry->children,
+ insert_subset_children,
+ superset_entry->children);
+
+ /* Enter the SUBSET itself as a child of the SUPERSET. */
+ splay_tree_insert (superset_entry->children,
+ (splay_tree_key) subset,
+ /*value=*/0);
+}
+
/* Inside SRC, the source of a SET, find a base address. */
static rtx
@@ -153,7 +332,7 @@ find_base_value (src)
The test above is not sufficient because the scheduler may move
a copy out of an arg reg past the NOTE_INSN_FUNCTION_BEGIN. */
if (REGNO (src) >= FIRST_PSEUDO_REGISTER
- && REGNO (src) < reg_base_value_size
+ && (unsigned) REGNO (src) < reg_base_value_size
&& reg_base_value[REGNO (src)])
return reg_base_value[REGNO (src)];
@@ -336,7 +515,7 @@ record_base_value (regno, val, invariant)
rtx val;
int invariant;
{
- if (regno >= reg_base_value_size)
+ if ((unsigned) regno >= reg_base_value_size)
return;
/* If INVARIANT is true then this value also describes an invariant
@@ -347,7 +526,7 @@ record_base_value (regno, val, invariant)
if (GET_CODE (val) == REG)
{
- if (REGNO (val) < reg_base_value_size)
+ if ((unsigned) REGNO (val) < reg_base_value_size)
{
reg_base_value[regno] = reg_base_value[REGNO (val)];
}
@@ -391,9 +570,8 @@ canon_rtx (x)
if (addr != XEXP (x, 0))
{
rtx new = gen_rtx_MEM (GET_MODE (x), addr);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
x = new;
}
@@ -568,10 +746,55 @@ find_base_term (x)
case PLUS:
case MINUS:
{
- rtx tmp = find_base_term (XEXP (x, 0));
- if (tmp)
- return tmp;
- return find_base_term (XEXP (x, 1));
+ rtx tmp1 = XEXP (x, 0);
+ rtx tmp2 = XEXP (x, 1);
+
+ /* This is a litle bit tricky since we have to determine which of
+ the two operands represents the real base address. Otherwise this
+ routine may return the index register instead of the base register.
+
+ That may cause us to believe no aliasing was possible, when in
+ fact aliasing is possible.
+
+ We use a few simple tests to guess the base register. Additional
+ tests can certainly be added. For example, if one of the operands
+ is a shift or multiply, then it must be the index register and the
+ other operand is the base register. */
+
+ /* If either operand is known to be a pointer, then use it
+ to determine the base term. */
+ if (REG_P (tmp1) && REGNO_POINTER_FLAG (REGNO (tmp1)))
+ return find_base_term (tmp1);
+
+ if (REG_P (tmp2) && REGNO_POINTER_FLAG (REGNO (tmp2)))
+ return find_base_term (tmp2);
+
+ /* Neither operand was known to be a pointer. Go ahead and find the
+ base term for both operands. */
+ tmp1 = find_base_term (tmp1);
+ tmp2 = find_base_term (tmp2);
+
+ /* If either base term is named object or a special address
+ (like an argument or stack reference), then use it for the
+ base term. */
+ if (tmp1
+ && (GET_CODE (tmp1) == SYMBOL_REF
+ || GET_CODE (tmp1) == LABEL_REF
+ || (GET_CODE (tmp1) == ADDRESS
+ && GET_MODE (tmp1) != VOIDmode)))
+ return tmp1;
+
+ if (tmp2
+ && (GET_CODE (tmp2) == SYMBOL_REF
+ || GET_CODE (tmp2) == LABEL_REF
+ || (GET_CODE (tmp2) == ADDRESS
+ && GET_MODE (tmp2) != VOIDmode)))
+ return tmp2;
+
+ /* We could not determine which of the two operands was the
+ base register and which was the index. So we can determine
+ nothing from the base alias check. */
+ return 0;
}
case AND:
@@ -592,8 +815,9 @@ find_base_term (x)
objects, 1 if they might be pointers to the same object. */
static int
-base_alias_check (x, y)
+base_alias_check (x, y, x_mode, y_mode)
rtx x, y;
+ enum machine_mode x_mode, y_mode;
{
rtx x_base = find_base_term (x);
rtx y_base = find_base_term (y);
@@ -625,17 +849,25 @@ base_alias_check (x, y)
if (rtx_equal_p (x_base, y_base))
return 1;
- /* The base addresses of the read and write are different
- expressions. If they are both symbols and they are not accessed
- via AND, there is no conflict. */
- /* XXX: We can bring knowledge of object alignment and offset into
- play here. For example, on alpha, "char a, b;" can alias one
- another, though "char a; long b;" cannot. Similarly, offsets
- into strutures may be brought into play. Given "char a, b[40];",
- a and b[1] may overlap, but a and b[20] do not. */
+ /* The base addresses of the read and write are different expressions.
+ If they are both symbols and they are not accessed via AND, there is
+ no conflict. We can bring knowledge of object alignment into play
+ here. For example, on alpha, "char a, b;" can alias one another,
+ though "char a; long b;" cannot. */
if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS)
{
- return GET_CODE (x) == AND || GET_CODE (y) == AND;
+ if (GET_CODE (x) == AND && GET_CODE (y) == AND)
+ return 1;
+ if (GET_CODE (x) == AND
+ && (GET_CODE (XEXP (x, 1)) != CONST_INT
+ || GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
+ return 1;
+ if (GET_CODE (y) == AND
+ && (GET_CODE (XEXP (y, 1)) != CONST_INT
+ || GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
+ return 1;
+ /* Differing symbols never alias. */
+ return 0;
}
/* If one address is a stack reference there can be no alias:
@@ -656,6 +888,45 @@ base_alias_check (x, y)
return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
}
+/* Return the address of the (N_REFS + 1)th memory reference to ADDR
+ where SIZE is the size in bytes of the memory reference. If ADDR
+ is not modified by the memory reference then ADDR is returned. */
+
+rtx
+addr_side_effect_eval (addr, size, n_refs)
+ rtx addr;
+ int size;
+ int n_refs;
+{
+ int offset = 0;
+
+ switch (GET_CODE (addr))
+ {
+ case PRE_INC:
+ offset = (n_refs + 1) * size;
+ break;
+ case PRE_DEC:
+ offset = -(n_refs + 1) * size;
+ break;
+ case POST_INC:
+ offset = n_refs * size;
+ break;
+ case POST_DEC:
+ offset = -n_refs * size;
+ break;
+
+ default:
+ return addr;
+ }
+
+ if (offset)
+ addr = gen_rtx_PLUS (GET_MODE (addr), XEXP (addr, 0), GEN_INT (offset));
+ else
+ addr = XEXP (addr, 0);
+
+ return addr;
+}
+
/* Return nonzero if X and Y (memory addresses) could reference the
same location in memory. C is an offset accumulator. When
C is nonzero, we are testing aliases between X and Y + C.
@@ -685,13 +956,13 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
else if (GET_CODE (x) == LO_SUM)
x = XEXP (x, 1);
else
- x = canon_rtx (x);
+ x = canon_rtx (addr_side_effect_eval (x, xsize, 0));
if (GET_CODE (y) == HIGH)
y = XEXP (y, 0);
else if (GET_CODE (y) == LO_SUM)
y = XEXP (y, 1);
else
- y = canon_rtx (y);
+ y = canon_rtx (addr_side_effect_eval (y, ysize, 0));
if (rtx_equal_for_memref_p (x, y))
{
@@ -726,11 +997,14 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
if (rtx_equal_for_memref_p (x0, y0))
return memrefs_conflict_p (xsize, x1, ysize, y1, c);
if (GET_CODE (x1) == CONST_INT)
- if (GET_CODE (y1) == CONST_INT)
- return memrefs_conflict_p (xsize, x0, ysize, y0,
- c - INTVAL (x1) + INTVAL (y1));
- else
- return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
+ {
+ if (GET_CODE (y1) == CONST_INT)
+ return memrefs_conflict_p (xsize, x0, ysize, y0,
+ c - INTVAL (x1) + INTVAL (y1));
+ else
+ return memrefs_conflict_p (xsize, x0, ysize, y,
+ c - INTVAL (x1));
+ }
else if (GET_CODE (y1) == CONST_INT)
return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
@@ -784,7 +1058,7 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
/* Are these registers known not to be equal? */
if (alias_invariant)
{
- int r_x = REGNO (x), r_y = REGNO (y);
+ unsigned int r_x = REGNO (x), r_y = REGNO (y);
rtx i_x, i_y; /* invariant relationships of X and Y */
i_x = r_x >= reg_base_value_size ? 0 : alias_invariant[r_x];
@@ -804,18 +1078,24 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
}
/* Treat an access through an AND (e.g. a subword access on an Alpha)
- as an access with indeterminate size.
- ??? Could instead convert an n byte reference at (and x y) to an
- n-y byte reference at (plus x y). */
+ as an access with indeterminate size. Assume that references
+ besides AND are aligned, so if the size of the other reference is
+ at least as large as the alignment, assume no other overlap. */
if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT)
- return memrefs_conflict_p (-1, XEXP (x, 0), ysize, y, c);
+ {
+ if (GET_CODE (y) == AND || ysize < -INTVAL (XEXP (x, 1)))
+ xsize = -1;
+ return memrefs_conflict_p (xsize, XEXP (x, 0), ysize, y, c);
+ }
if (GET_CODE (y) == AND && GET_CODE (XEXP (y, 1)) == CONST_INT)
{
- /* XXX: If we are indexing far enough into the array/structure, we
+ /* ??? If we are indexing far enough into the array/structure, we
may yet be able to determine that we can not overlap. But we
also need to that we are far enough from the end not to overlap
- a following reference, so we do nothing for now. */
- return memrefs_conflict_p (xsize, x, -1, XEXP (y, 0), c);
+ a following reference, so we do nothing with that for now. */
+ if (GET_CODE (x) == AND || xsize < -INTVAL (XEXP (y, 1)))
+ ysize = -1;
+ return memrefs_conflict_p (xsize, x, ysize, XEXP (y, 0), c);
}
if (CONSTANT_P (x))
@@ -883,6 +1163,56 @@ read_dependence (mem, x)
return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);
}
+/* Returns MEM1 if and only if MEM1 is a scalar at a fixed address and
+ MEM2 is a reference to a structure at a varying address, or returns
+ MEM2 if vice versa. Otherwise, returns NULL_RTX. If a non-NULL
+ value is returned MEM1 and MEM2 can never alias. VARIES_P is used
+ to decide whether or not an address may vary; it should return
+ nozero whenever variation is possible. */
+
+static rtx
+fixed_scalar_and_varying_struct_p (mem1, mem2, varies_p)
+ rtx mem1;
+ rtx mem2;
+ int (*varies_p) PROTO((rtx));
+{
+ rtx mem1_addr = XEXP (mem1, 0);
+ rtx mem2_addr = XEXP (mem2, 0);
+
+ if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
+ && !varies_p (mem1_addr) && varies_p (mem2_addr))
+ /* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
+ varying address. */
+ return mem1;
+
+ if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
+ && varies_p (mem1_addr) && !varies_p (mem2_addr))
+ /* MEM2 is a scalar at a fixed address; MEM1 is a struct at a
+ varying address. */
+ return mem2;
+
+ return NULL_RTX;
+}
+
+/* Returns nonzero if something about the mode or address format MEM1
+ indicates that it might well alias *anything*. */
+
+static int
+aliases_everything_p (mem)
+ rtx mem;
+{
+ if (GET_MODE (mem) == QImode)
+ /* ANSI C says that a `char*' can point to anything. */
+ return 1;
+
+ if (GET_CODE (XEXP (mem, 0)) == AND)
+ /* If the address is an AND, its very hard to know at what it is
+ actually pointing. */
+ return 1;
+
+ return 0;
+}
+
/* True dependence: X is read after store in MEM takes place. */
int
@@ -910,59 +1240,46 @@ true_dependence (mem, mem_mode, x, varies)
if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
return 0;
- if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
+ if (mem_mode == VOIDmode)
+ mem_mode = GET_MODE (mem);
+
+ if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x), mem_mode))
return 0;
x_addr = canon_rtx (XEXP (x, 0));
mem_addr = canon_rtx (XEXP (mem, 0));
- if (mem_mode == VOIDmode)
- mem_mode = GET_MODE (mem);
-
if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
SIZE_FOR_MODE (x), x_addr, 0))
return 0;
- /* If both references are struct references, or both are not, nothing
- is known about aliasing.
-
- If either reference is QImode or BLKmode, ANSI C permits aliasing.
-
- If both addresses are constant, or both are not, nothing is known
- about aliasing. */
- if (MEM_IN_STRUCT_P (x) == MEM_IN_STRUCT_P (mem)
- || mem_mode == QImode || mem_mode == BLKmode
- || GET_MODE (x) == QImode || GET_MODE (x) == BLKmode
- || GET_CODE (x_addr) == AND || GET_CODE (mem_addr) == AND
- || varies (x_addr) == varies (mem_addr))
+ if (aliases_everything_p (x))
return 1;
- /* One memory reference is to a constant address, one is not.
- One is to a structure, the other is not.
-
- If either memory reference is a variable structure the other is a
- fixed scalar and there is no aliasing. */
+ /* We cannot use aliases_everyting_p to test MEM, since we must look
+ at MEM_MODE, rather than GET_MODE (MEM). */
+ if (mem_mode == QImode || GET_CODE (mem_addr) == AND)
+ return 1;
- /* Disabled by default for egcs 1.1.x as alias analysis isn't good
- enough yet to discover all cases where this doesn't apply. */
- if (flag_structure_noalias)
- {
- if ((MEM_IN_STRUCT_P (mem) && varies (mem_addr))
- || (MEM_IN_STRUCT_P (x) && varies (x_addr)))
- return 0;
- }
+ /* In true_dependence we also allow BLKmode to alias anything. Why
+ don't we do this in anti_dependence and output_dependence? */
+ if (mem_mode == BLKmode || GET_MODE (x) == BLKmode)
+ return 1;
- return 1;
+ return !fixed_scalar_and_varying_struct_p (mem, x, varies);
}
-/* Anti dependence: X is written after read in MEM takes place. */
+/* Returns non-zero if a write to X might alias a previous read from
+ (or, if WRITEP is non-zero, a write to) MEM. */
-int
-anti_dependence (mem, x)
+static int
+write_dependence_p (mem, x, writep)
rtx mem;
rtx x;
+ int writep;
{
rtx x_addr, mem_addr;
+ rtx fixed_scalar;
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
return 1;
@@ -970,10 +1287,11 @@ anti_dependence (mem, x)
/* If MEM is an unchanging read, then it can't possibly conflict with
the store to X, because there is at most one store to MEM, and it must
have occurred somewhere before MEM. */
- if (RTX_UNCHANGING_P (mem))
+ if (!writep && RTX_UNCHANGING_P (mem))
return 0;
- if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
+ if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x),
+ GET_MODE (mem)))
return 0;
x = canon_rtx (x);
@@ -985,16 +1303,25 @@ anti_dependence (mem, x)
x_addr = XEXP (x, 0);
mem_addr = XEXP (mem, 0);
- return (memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
- SIZE_FOR_MODE (x), x_addr, 0)
- && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
- && GET_MODE (mem) != QImode
- && GET_CODE (mem_addr) != AND
- && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
- && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
- && GET_MODE (x) != QImode
- && GET_CODE (x_addr) != AND
- && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
+ if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
+ SIZE_FOR_MODE (x), x_addr, 0))
+ return 0;
+
+ fixed_scalar
+ = fixed_scalar_and_varying_struct_p (mem, x, rtx_addr_varies_p);
+
+ return (!(fixed_scalar == mem && !aliases_everything_p (x))
+ && !(fixed_scalar == x && !aliases_everything_p (mem)));
+}
+
+/* Anti dependence: X is written after read in MEM takes place. */
+
+int
+anti_dependence (mem, x)
+ rtx mem;
+ rtx x;
+{
+ return write_dependence_p (mem, x, /*writep=*/0);
}
/* Output dependence: X is written after store in MEM takes place. */
@@ -1004,28 +1331,7 @@ output_dependence (mem, x)
register rtx mem;
register rtx x;
{
- if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
- return 1;
-
- if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
- return 0;
-
- x = canon_rtx (x);
- mem = canon_rtx (mem);
-
- if (DIFFERENT_ALIAS_SETS_P (x, mem))
- return 0;
-
- return (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
- SIZE_FOR_MODE (x), XEXP (x, 0), 0)
- && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
- && GET_MODE (mem) != QImode
- && GET_CODE (XEXP (mem, 0)) != AND
- && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
- && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
- && GET_MODE (x) != QImode
- && GET_CODE (XEXP (x, 0)) != AND
- && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
+ return write_dependence_p (mem, x, /*writep=*/1);
}
@@ -1046,6 +1352,8 @@ init_alias_once ()
if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
&& HARD_REGNO_MODE_OK (i, Pmode))
SET_HARD_REG_BIT (argument_registers, i);
+
+ alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
}
void
@@ -1054,6 +1362,7 @@ init_alias_analysis ()
int maxreg = max_reg_num ();
int changed, pass;
register int i;
+ register unsigned int ui;
register rtx insn;
reg_known_value_size = maxreg;
@@ -1194,13 +1503,13 @@ init_alias_analysis ()
}
/* Now propagate values from new_reg_base_value to reg_base_value. */
- for (i = 0; i < reg_base_value_size; i++)
+ for (ui = 0; ui < reg_base_value_size; ui++)
{
- if (new_reg_base_value[i]
- && new_reg_base_value[i] != reg_base_value[i]
- && ! rtx_equal_p (new_reg_base_value[i], reg_base_value[i]))
+ if (new_reg_base_value[ui]
+ && new_reg_base_value[ui] != reg_base_value[ui]
+ && ! rtx_equal_p (new_reg_base_value[ui], reg_base_value[ui]))
{
- reg_base_value[i] = new_reg_base_value[i];
+ reg_base_value[ui] = new_reg_base_value[ui];
changed = 1;
}
}
@@ -1227,16 +1536,16 @@ init_alias_analysis ()
{
changed = 0;
pass++;
- for (i = 0; i < reg_base_value_size; i++)
+ for (ui = 0; ui < reg_base_value_size; ui++)
{
- rtx base = reg_base_value[i];
+ rtx base = reg_base_value[ui];
if (base && GET_CODE (base) == REG)
{
- int base_regno = REGNO (base);
- if (base_regno == i) /* register set from itself */
- reg_base_value[i] = 0;
+ unsigned int base_regno = REGNO (base);
+ if (base_regno == ui) /* register set from itself */
+ reg_base_value[ui] = 0;
else
- reg_base_value[i] = reg_base_value[base_regno];
+ reg_base_value[ui] = reg_base_value[base_regno];
changed = 1;
}
}
diff --git a/contrib/gcc/basic-block.h b/contrib/gcc/basic-block.h
index 552f74a..fa3d56f 100644
--- a/contrib/gcc/basic-block.h
+++ b/contrib/gcc/basic-block.h
@@ -1,5 +1,5 @@
/* Define control and data flow tables, and regsets.
- Copyright (C) 1987, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,8 @@ Boston, MA 02111-1307, USA. */
#include "bitmap.h"
+#include "sbitmap.h"
+#include "varray.h"
typedef bitmap regset; /* Head of register set linked list. */
@@ -94,29 +96,65 @@ do { \
/* Grow any tables needed when the number of registers is calculated
or extended. For the linked list allocation, nothing needs to
be done, other than zero the statistics on the first allocation. */
-#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
+#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
-/* Number of basic blocks in the current function. */
+/* Control flow edge information. */
+typedef struct edge_def {
+ /* Links through the predecessor and successor lists. */
+ struct edge_def *pred_next, *succ_next;
-extern int n_basic_blocks;
+ /* The two blocks at the ends of the edge. */
+ struct basic_block_def *src, *dest;
+
+ /* Instructions queued on the edge. */
+ rtx insns;
+
+ /* Auxiliary info specific to a pass. */
+ void *aux;
+
+ int flags; /* see EDGE_* below */
+ int probability; /* biased by REG_BR_PROB_BASE */
+} *edge;
+
+#define EDGE_FALLTHRU 1
+#define EDGE_CRITICAL 2
+#define EDGE_ABNORMAL 4
+#define EDGE_ABNORMAL_CALL 8
+#define EDGE_EH 16
+#define EDGE_FAKE 32
+
+
+/* Basic block information indexed by block number. */
+typedef struct basic_block_def {
+ /* The first and last insns of the block. */
+ rtx head, end;
+
+ /* The edges into and out of the block. */
+ edge pred, succ;
-/* Index by basic block number, get first insn in the block. */
+ /* Liveness info. */
+ regset local_set;
+ regset global_live_at_start;
+ regset global_live_at_end;
-extern rtx *basic_block_head;
+ /* Auxiliary info specific to a pass. */
+ void *aux;
-/* Index by basic block number, get last insn in the block. */
+ /* The index of this block. */
+ int index;
+ /* The loop depth of this block plus one. */
+ int loop_depth;
+} *basic_block;
-extern rtx *basic_block_end;
+/* Number of basic blocks in the current function. */
-/* Index by basic block number, determine whether the block can be reached
- through a computed jump. */
+extern int n_basic_blocks;
-extern char *basic_block_computed_jump_target;
+/* Index by basic block number, get basic block struct info. */
-/* Index by basic block number, get address of regset
- describing the registers live at the start of that block. */
+extern varray_type basic_block_info;
-extern regset *basic_block_live_at_start;
+#define BASIC_BLOCK(N) (VARRAY_BB (basic_block_info, (N)))
/* What registers are live at the setjmp call. */
@@ -176,91 +214,49 @@ extern void free_int_list PROTO ((int_list_block **));
/* Stuff for recording basic block info. */
-#define BLOCK_HEAD(B) basic_block_head[(B)]
-#define BLOCK_END(B) basic_block_end[(B)]
+#define BLOCK_HEAD(B) (BASIC_BLOCK (B)->head)
+#define BLOCK_END(B) (BASIC_BLOCK (B)->end)
/* Special block numbers [markers] for entry and exit. */
#define ENTRY_BLOCK (-1)
#define EXIT_BLOCK (-2)
+/* Similarly, block pointers for the edge list. */
+extern struct basic_block_def entry_exit_blocks[2];
+#define ENTRY_BLOCK_PTR (&entry_exit_blocks[0])
+#define EXIT_BLOCK_PTR (&entry_exit_blocks[1])
+
/* from flow.c */
-extern void free_regset_vector PROTO ((regset *, int nelts));
-extern int *uid_block_number;
-#define BLOCK_NUM(INSN) uid_block_number[INSN_UID (INSN)]
-
-extern void compute_preds_succs PROTO ((int_list_ptr *, int_list_ptr *,
- int *, int *));
-extern void dump_bb_data PROTO ((FILE *, int_list_ptr *, int_list_ptr *));
-extern void free_bb_mem PROTO ((void));
-extern void free_basic_block_vars PROTO ((int));
+extern void free_regset_vector PROTO ((regset *, int nelts));
-
-/* Simple bitmaps.
- It's not clear yet whether using bitmap.[ch] will be a win.
- It should be straightforward to convert so for now we keep things simple
- while more important issues are dealt with. */
-
-#define SBITMAP_ELT_BITS HOST_BITS_PER_WIDE_INT
-#define SBITMAP_ELT_TYPE unsigned HOST_WIDE_INT
-
-typedef struct simple_bitmap_def {
- /* Number of bits. */
- int n_bits;
- /* Size in elements. */
- int size;
- /* Size in bytes. */
- int bytes;
- /* The elements. */
- SBITMAP_ELT_TYPE elms[1];
-} *sbitmap;
-
-typedef SBITMAP_ELT_TYPE *sbitmap_ptr;
-
-/* Return the set size needed for N elements. */
-#define SBITMAP_SET_SIZE(n) (((n) + SBITMAP_ELT_BITS - 1) / SBITMAP_ELT_BITS)
-
-/* set bit number bitno in the bitmap */
-#define SET_BIT(bitmap, bitno) \
-do { \
- (bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] |= (SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS; \
-} while (0)
+extern varray_type basic_block_for_insn;
+#define BLOCK_FOR_INSN(INSN) VARRAY_BB (basic_block_for_insn, INSN_UID (INSN))
+#define BLOCK_NUM(INSN) (BLOCK_FOR_INSN (INSN)->index + 0)
-/* test if bit number bitno in the bitmap is set */
-#define TEST_BIT(bitmap, bitno) \
-((bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] & ((SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS))
+extern void set_block_for_insn PROTO ((rtx, basic_block));
-/* reset bit number bitno in the bitmap */
-#define RESET_BIT(bitmap, bitno) \
-do { \
- (bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] &= ~((SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS); \
-} while (0)
+extern void dump_bb_data PROTO ((FILE *, int_list_ptr *,
+ int_list_ptr *, int));
+extern void free_bb_mem PROTO ((void));
+extern void free_basic_block_vars PROTO ((int));
+
+extern basic_block split_edge PROTO ((edge));
+extern void insert_insn_on_edge PROTO ((rtx, edge));
+extern void commit_edge_insertions PROTO ((void));
-extern void dump_sbitmap PROTO ((FILE *, sbitmap));
-extern void dump_sbitmap_vector PROTO ((FILE *, char *, char *,
- sbitmap *, int));
-extern sbitmap sbitmap_alloc PROTO ((int));
-extern sbitmap *sbitmap_vector_alloc PROTO ((int, int));
-extern void sbitmap_copy PROTO ((sbitmap, sbitmap));
-extern void sbitmap_zero PROTO ((sbitmap));
-extern void sbitmap_ones PROTO ((sbitmap));
-extern void sbitmap_vector_zero PROTO ((sbitmap *, int));
-extern void sbitmap_vector_ones PROTO ((sbitmap *, int));
-extern int sbitmap_union_of_diff PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
-extern void sbitmap_difference PROTO ((sbitmap, sbitmap, sbitmap));
-extern void sbitmap_not PROTO ((sbitmap, sbitmap));
-extern int sbitmap_a_or_b_and_c PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
-extern int sbitmap_a_and_b_or_c PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
-extern int sbitmap_a_and_b PROTO ((sbitmap, sbitmap, sbitmap));
-extern int sbitmap_a_or_b PROTO ((sbitmap, sbitmap, sbitmap));
-extern void sbitmap_intersect_of_predsucc PROTO ((sbitmap, sbitmap *,
- int, int_list_ptr *));
-extern void sbitmap_intersect_of_predecessors PROTO ((sbitmap, sbitmap *, int,
- int_list_ptr *));
-extern void sbitmap_intersect_of_successors PROTO ((sbitmap, sbitmap *, int,
- int_list_ptr *));
-extern void sbitmap_union_of_predecessors PROTO ((sbitmap, sbitmap *, int,
- int_list_ptr *));
-extern void sbitmap_union_of_successors PROTO ((sbitmap, sbitmap *, int,
+extern void compute_preds_succs PROTO ((int_list_ptr *, int_list_ptr *,
+ int *, int *));
+extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
+ int_list_ptr *,
int_list_ptr *));
-extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
- int_list_ptr *, int_list_ptr *));
+extern void compute_immediate_dominators PROTO ((int *, sbitmap *));
+
+/* In lcm.c */
+extern void pre_lcm PROTO ((int, int, int_list_ptr *,
+ int_list_ptr *,
+ sbitmap *, sbitmap *,
+ sbitmap *, sbitmap *));
+extern void pre_rev_lcm PROTO ((int, int, int_list_ptr *,
+ int_list_ptr *,
+ sbitmap *, sbitmap *,
+ sbitmap *, sbitmap *));
diff --git a/contrib/gcc/bitmap.c b/contrib/gcc/bitmap.c
index a5aa2e7..b4fc097 100644
--- a/contrib/gcc/bitmap.c
+++ b/contrib/gcc/bitmap.c
@@ -613,10 +613,10 @@ void
bitmap_print (file, head, prefix, suffix)
FILE *file;
bitmap head;
- char *prefix;
- char *suffix;
+ const char *prefix;
+ const char *suffix;
{
- char *comma = "";
+ const char *comma = "";
int i;
fputs (prefix, file);
diff --git a/contrib/gcc/bitmap.h b/contrib/gcc/bitmap.h
index 2941574..4ff0bf4 100644
--- a/contrib/gcc/bitmap.h
+++ b/contrib/gcc/bitmap.h
@@ -1,5 +1,5 @@
/* Functions to support general ended bitmaps.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -48,7 +48,7 @@ typedef struct bitmap_element_def
typedef struct bitmap_head_def {
bitmap_element *first; /* First element in linked list. */
bitmap_element *current; /* Last element looked at. */
- int indx; /* Index of last element looked at. */
+ unsigned int indx; /* Index of last element looked at. */
} bitmap_head, *bitmap;
/* Enumeration giving the various operations we support. */
@@ -89,7 +89,7 @@ extern void bitmap_debug PROTO((bitmap));
extern void bitmap_debug_file PROTO((FILE *, bitmap));
/* Print a bitmap */
-extern void bitmap_print PROTO((FILE *, bitmap, char *, char *));
+extern void bitmap_print PROTO((FILE *, bitmap, const char *, const char *));
/* Initialize a bitmap header. */
extern bitmap bitmap_initialize PROTO((bitmap));
diff --git a/contrib/gcc/c-aux-info.c b/contrib/gcc/c-aux-info.c
index 3e2edde..9a66350 100644
--- a/contrib/gcc/c-aux-info.c
+++ b/contrib/gcc/c-aux-info.c
@@ -1,7 +1,7 @@
/* Generate information regarding function declarations and definitions based
on information stored in GCC's tree structure. This code implements the
-aux-info option.
- Copyright (C) 1989, 91, 94, 95, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 91, 94, 95, 97-98, 1999 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@segfault.us.com).
This file is part of GNU CC.
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "toplev.h"
#include "flags.h"
#include "tree.h"
#include "c-tree.h"
@@ -35,67 +36,75 @@ enum formals_style_enum {
typedef enum formals_style_enum formals_style;
-static char *data_type;
+static const char *data_type;
-static char *concat PROTO((char *, char *));
-static char *concat3 PROTO((char *, char *, char *));
-static char *affix_data_type PROTO((char *));
-static char *gen_formal_list_for_type PROTO((tree, formals_style));
+static char *affix_data_type PROTO((const char *));
+static const char *gen_formal_list_for_type PROTO((tree, formals_style));
static int deserves_ellipsis PROTO((tree));
-static char *gen_formal_list_for_func_def PROTO((tree, formals_style));
-static char *gen_type PROTO((char *, tree, formals_style));
-static char *gen_decl PROTO((tree, int, formals_style));
+static const char *gen_formal_list_for_func_def PROTO((tree, formals_style));
+static const char *gen_type PROTO((const char *, tree, formals_style));
+static const char *gen_decl PROTO((tree, int, formals_style));
-/* Take two strings and mash them together into a newly allocated area. */
+/* Concatenate a sequence of strings, returning the result.
-static char *
-concat (s1, s2)
- char *s1;
- char *s2;
+ This function is based on the one in libiberty. */
+
+/* This definition will conflict with the one from prefix.c in
+ libcpp.a when linking cc1 and cc1obj. So only provide it if we are
+ not using libcpp.a */
+#ifndef USE_CPPLIB
+char *
+concat VPROTO((const char *first, ...))
{
- int size1, size2;
- char *ret_val;
-
- if (!s1)
- s1 = "";
- if (!s2)
- s2 = "";
-
- size1 = strlen (s1);
- size2 = strlen (s2);
- ret_val = xmalloc (size1 + size2 + 1);
- strcpy (ret_val, s1);
- strcpy (&ret_val[size1], s2);
- return ret_val;
-}
+ register int length;
+ register char *newstr;
+ register char *end;
+ register const char *arg;
+ va_list args;
+#ifndef ANSI_PROTOTYPES
+ const char *first;
+#endif
+
+ /* First compute the size of the result and get sufficient memory. */
+
+ VA_START (args, first);
+#ifndef ANSI_PROTOTYPES
+ first = va_arg (args, const char *);
+#endif
+
+ arg = first;
+ length = 0;
+
+ while (arg != 0)
+ {
+ length += strlen (arg);
+ arg = va_arg (args, const char *);
+ }
-/* Take three strings and mash them together into a newly allocated area. */
+ newstr = (char *) malloc (length + 1);
+ va_end (args);
-static char *
-concat3 (s1, s2, s3)
- char *s1;
- char *s2;
- char *s3;
-{
- int size1, size2, size3;
- char *ret_val;
-
- if (!s1)
- s1 = "";
- if (!s2)
- s2 = "";
- if (!s3)
- s3 = "";
-
- size1 = strlen (s1);
- size2 = strlen (s2);
- size3 = strlen (s3);
- ret_val = xmalloc (size1 + size2 + size3 + 1);
- strcpy (ret_val, s1);
- strcpy (&ret_val[size1], s2);
- strcpy (&ret_val[size1+size2], s3);
- return ret_val;
+ /* Now copy the individual pieces to the result string. */
+
+ VA_START (args, first);
+#ifndef ANSI_PROTOTYPES
+ first = va_arg (args, char *);
+#endif
+
+ end = newstr;
+ arg = first;
+ while (arg != 0)
+ {
+ while (*arg)
+ *end++ = *arg++;
+ arg = va_arg (args, const char *);
+ }
+ *end = '\000';
+ va_end (args);
+
+ return (newstr);
}
+#endif /* ! USE_CPPLIB */
/* Given a string representing an entire type or an entire declaration
which only lacks the actual "data-type" specifier (at its left end),
@@ -112,13 +121,16 @@ concat3 (s1, s2, s3)
that look as expected. */
static char *
-affix_data_type (type_or_decl)
- char *type_or_decl;
+affix_data_type (param)
+ const char *param;
{
+ char *type_or_decl = (char *) alloca (strlen (param) + 1);
char *p = type_or_decl;
char *qualifiers_then_data_type;
char saved;
+ strcpy (type_or_decl, param);
+
/* Skip as many leading const's or volatile's as there are. */
for (;;)
@@ -140,13 +152,13 @@ affix_data_type (type_or_decl)
add a blank after the data-type of course. */
if (p == type_or_decl)
- return concat3 (data_type, " ", type_or_decl);
+ return concat (data_type, " ", type_or_decl, NULL_PTR);
saved = *p;
*p = '\0';
- qualifiers_then_data_type = concat (type_or_decl, data_type);
+ qualifiers_then_data_type = concat (type_or_decl, data_type, NULL_PTR);
*p = saved;
- return concat3 (qualifiers_then_data_type, " ", p);
+ return concat (qualifiers_then_data_type, " ", p, NULL_PTR);
}
/* Given a tree node which represents some "function type", generate the
@@ -156,12 +168,12 @@ affix_data_type (type_or_decl)
we are currently aiming for is non-ansi, then we just return a pair
of empty parens here. */
-static char *
+static const char *
gen_formal_list_for_type (fntype, style)
tree fntype;
formals_style style;
{
- char *formal_list = "";
+ const char *formal_list = "";
tree formal_type;
if (style != ansi)
@@ -170,16 +182,16 @@ gen_formal_list_for_type (fntype, style)
formal_type = TYPE_ARG_TYPES (fntype);
while (formal_type && TREE_VALUE (formal_type) != void_type_node)
{
- char *this_type;
+ const char *this_type;
if (*formal_list)
- formal_list = concat (formal_list, ", ");
+ formal_list = concat (formal_list, ", ", NULL_PTR);
this_type = gen_type ("", TREE_VALUE (formal_type), ansi);
formal_list
= ((strlen (this_type))
- ? concat (formal_list, affix_data_type (this_type))
- : concat (formal_list, data_type));
+ ? concat (formal_list, affix_data_type (this_type), NULL_PTR)
+ : concat (formal_list, data_type, NULL_PTR));
formal_type = TREE_CHAIN (formal_type);
}
@@ -228,10 +240,10 @@ gen_formal_list_for_type (fntype, style)
petered out to a NULL (i.e. without being terminated by a
void_type_node) then we need to tack on an ellipsis. */
if (!formal_type)
- formal_list = concat (formal_list, ", ...");
+ formal_list = concat (formal_list, ", ...", NULL_PTR);
}
- return concat3 (" (", formal_list, ")");
+ return concat (" (", formal_list, ")", NULL_PTR);
}
/* For the generation of an ANSI prototype for a function definition, we have
@@ -276,37 +288,37 @@ deserves_ellipsis (fntype)
This routine returns a string which is the source form for the entire
function formal parameter list. */
-static char *
+static const char *
gen_formal_list_for_func_def (fndecl, style)
tree fndecl;
formals_style style;
{
- char *formal_list = "";
+ const char *formal_list = "";
tree formal_decl;
formal_decl = DECL_ARGUMENTS (fndecl);
while (formal_decl)
{
- char *this_formal;
+ const char *this_formal;
if (*formal_list && ((style == ansi) || (style == k_and_r_names)))
- formal_list = concat (formal_list, ", ");
+ formal_list = concat (formal_list, ", ", NULL_PTR);
this_formal = gen_decl (formal_decl, 0, style);
if (style == k_and_r_decls)
- formal_list = concat3 (formal_list, this_formal, "; ");
+ formal_list = concat (formal_list, this_formal, "; ", NULL_PTR);
else
- formal_list = concat (formal_list, this_formal);
+ formal_list = concat (formal_list, this_formal, NULL_PTR);
formal_decl = TREE_CHAIN (formal_decl);
}
if (style == ansi)
{
if (!DECL_ARGUMENTS (fndecl))
- formal_list = concat (formal_list, "void");
+ formal_list = concat (formal_list, "void", NULL_PTR);
if (deserves_ellipsis (TREE_TYPE (fndecl)))
- formal_list = concat (formal_list, ", ...");
+ formal_list = concat (formal_list, ", ...", NULL_PTR);
}
if ((style == ansi) || (style == k_and_r_names))
- formal_list = concat3 (" (", formal_list, ")");
+ formal_list = concat (" (", formal_list, ")", NULL_PTR);
return formal_list;
}
@@ -351,9 +363,9 @@ gen_formal_list_for_func_def (fndecl, style)
to do at this point is for the initial caller to prepend the "data_type"
string onto the returned "seed". */
-static char *
+static const char *
gen_type (ret_val, t, style)
- char *ret_val;
+ const char *ret_val;
tree t;
formals_style style;
{
@@ -368,14 +380,14 @@ gen_type (ret_val, t, style)
{
case POINTER_TYPE:
if (TYPE_READONLY (t))
- ret_val = concat ("const ", ret_val);
+ ret_val = concat ("const ", ret_val, NULL_PTR);
if (TYPE_VOLATILE (t))
- ret_val = concat ("volatile ", ret_val);
+ ret_val = concat ("volatile ", ret_val, NULL_PTR);
- ret_val = concat ("*", ret_val);
+ ret_val = concat ("*", ret_val, NULL_PTR);
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
- ret_val = concat3 ("(", ret_val, ")");
+ ret_val = concat ("(", ret_val, ")", NULL_PTR);
ret_val = gen_type (ret_val, TREE_TYPE (t), style);
@@ -383,21 +395,26 @@ gen_type (ret_val, t, style)
case ARRAY_TYPE:
if (TYPE_SIZE (t) == 0 || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
- ret_val = gen_type (concat (ret_val, "[]"), TREE_TYPE (t), style);
+ ret_val = gen_type (concat (ret_val, "[]", NULL_PTR),
+ TREE_TYPE (t), style);
else if (int_size_in_bytes (t) == 0)
- ret_val = gen_type (concat (ret_val, "[0]"), TREE_TYPE (t), style);
+ ret_val = gen_type (concat (ret_val, "[0]", NULL_PTR),
+ TREE_TYPE (t), style);
else
{
int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));
char buff[10];
sprintf (buff, "[%d]", size);
- ret_val = gen_type (concat (ret_val, buff),
+ ret_val = gen_type (concat (ret_val, buff, NULL_PTR),
TREE_TYPE (t), style);
}
break;
case FUNCTION_TYPE:
- ret_val = gen_type (concat (ret_val, gen_formal_list_for_type (t, style)), TREE_TYPE (t), style);
+ ret_val = gen_type (concat (ret_val,
+ gen_formal_list_for_type (t, style),
+ NULL_PTR),
+ TREE_TYPE (t), style);
break;
case IDENTIFIER_NODE:
@@ -424,13 +441,14 @@ gen_type (ret_val, t, style)
chain_p = TYPE_FIELDS (t);
while (chain_p)
{
- data_type = concat (data_type, gen_decl (chain_p, 0, ansi));
+ data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
+ NULL_PTR);
chain_p = TREE_CHAIN (chain_p);
- data_type = concat (data_type, "; ");
+ data_type = concat (data_type, "; ", NULL_PTR);
}
- data_type = concat3 ("{ ", data_type, "}");
+ data_type = concat ("{ ", data_type, "}", NULL_PTR);
}
- data_type = concat ("struct ", data_type);
+ data_type = concat ("struct ", data_type, NULL_PTR);
break;
case UNION_TYPE:
@@ -442,13 +460,14 @@ gen_type (ret_val, t, style)
chain_p = TYPE_FIELDS (t);
while (chain_p)
{
- data_type = concat (data_type, gen_decl (chain_p, 0, ansi));
+ data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
+ NULL_PTR);
chain_p = TREE_CHAIN (chain_p);
- data_type = concat (data_type, "; ");
+ data_type = concat (data_type, "; ", NULL_PTR);
}
- data_type = concat3 ("{ ", data_type, "}");
+ data_type = concat ("{ ", data_type, "}", NULL_PTR);
}
- data_type = concat ("union ", data_type);
+ data_type = concat ("union ", data_type, NULL_PTR);
break;
case ENUMERAL_TYPE:
@@ -461,14 +480,14 @@ gen_type (ret_val, t, style)
while (chain_p)
{
data_type = concat (data_type,
- IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)));
+ IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL_PTR);
chain_p = TREE_CHAIN (chain_p);
if (chain_p)
- data_type = concat (data_type, ", ");
+ data_type = concat (data_type, ", ", NULL_PTR);
}
- data_type = concat3 ("{ ", data_type, " }");
+ data_type = concat ("{ ", data_type, " }", NULL_PTR);
}
- data_type = concat ("enum ", data_type);
+ data_type = concat ("enum ", data_type, NULL_PTR);
break;
case TYPE_DECL:
@@ -478,9 +497,9 @@ gen_type (ret_val, t, style)
case INTEGER_TYPE:
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
/* Normally, `unsigned' is part of the deal. Not so if it comes
- with `const' or `volatile'. */
- if (TREE_UNSIGNED (t) && (TYPE_READONLY (t) || TYPE_VOLATILE (t)))
- data_type = concat ("unsigned ", data_type);
+ with a type qualifier. */
+ if (TREE_UNSIGNED (t) && TYPE_QUALS (t))
+ data_type = concat ("unsigned ", data_type, NULL_PTR);
break;
case REAL_TYPE:
@@ -500,9 +519,11 @@ gen_type (ret_val, t, style)
}
}
if (TYPE_READONLY (t))
- ret_val = concat ("const ", ret_val);
+ ret_val = concat ("const ", ret_val, NULL_PTR);
if (TYPE_VOLATILE (t))
- ret_val = concat ("volatile ", ret_val);
+ ret_val = concat ("volatile ", ret_val, NULL_PTR);
+ if (TYPE_RESTRICT (t))
+ ret_val = concat ("restrict ", ret_val, NULL_PTR);
return ret_val;
}
@@ -516,13 +537,13 @@ gen_type (ret_val, t, style)
associated with a function definition. In this case, we can assume that
an attached list of DECL nodes for function formal arguments is present. */
-static char *
+static const char *
gen_decl (decl, is_func_definition, style)
tree decl;
int is_func_definition;
formals_style style;
{
- char *ret_val;
+ const char *ret_val;
if (DECL_NAME (decl))
ret_val = IDENTIFIER_POINTER (DECL_NAME (decl));
@@ -544,9 +565,9 @@ gen_decl (decl, is_func_definition, style)
generate the qualifiers here. */
if (TREE_THIS_VOLATILE (decl))
- ret_val = concat ("volatile ", ret_val);
+ ret_val = concat ("volatile ", ret_val, NULL_PTR);
if (TREE_READONLY (decl))
- ret_val = concat ("const ", ret_val);
+ ret_val = concat ("const ", ret_val, NULL_PTR);
data_type = "";
@@ -564,7 +585,8 @@ gen_decl (decl, is_func_definition, style)
if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition)
{
- ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi));
+ ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi),
+ NULL_PTR);
/* Since we have already added in the formals list stuff, here we don't
add the whole "type" of the function we are considering (which
@@ -581,11 +603,11 @@ gen_decl (decl, is_func_definition, style)
ret_val = affix_data_type (ret_val);
if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
- ret_val = concat ("register ", ret_val);
+ ret_val = concat ("register ", ret_val, NULL_PTR);
if (TREE_PUBLIC (decl))
- ret_val = concat ("extern ", ret_val);
+ ret_val = concat ("extern ", ret_val, NULL_PTR);
if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl))
- ret_val = concat ("static ", ret_val);
+ ret_val = concat ("static ", ret_val, NULL_PTR);
return ret_val;
}
diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c
index 61600fb..1ec3842 100644
--- a/contrib/gcc/c-common.c
+++ b/contrib/gcc/c-common.c
@@ -1,5 +1,5 @@
/* Subroutines shared by all languages that are variants of C.
- Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,6 +27,8 @@ Boston, MA 02111-1307, USA. */
#include "obstack.h"
#include "toplev.h"
#include "output.h"
+#include "c-pragma.h"
+#include "rtl.h"
#if USE_CPPLIB
#include "cpplib.h"
@@ -50,19 +52,22 @@ extern struct obstack permanent_obstack;
int skip_evaluation;
enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
+ A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS};
enum format_type { printf_format_type, scanf_format_type,
strftime_format_type };
-static void declare_hidden_char_array PROTO((char *, char *));
-static void add_attribute PROTO((enum attrs, char *,
+static void declare_hidden_char_array PROTO((const char *, const char *));
+static void add_attribute PROTO((enum attrs, const char *,
int, int, int));
static void init_attributes PROTO((void));
static void record_function_format PROTO((tree, tree, enum format_type,
int, int));
static void record_international_format PROTO((tree, tree, int));
+static tree c_find_base_decl PROTO((tree));
+static int default_valid_lang_attribute PROTO ((tree, tree, tree, tree));
/* Keep a stack of if statements. We record the number of compound
statements seen up to the if keyword, as well as the line number
@@ -73,9 +78,10 @@ typedef struct
{
int compstmt_count;
int line;
- char *file;
+ const char *file;
int needs_warning;
} if_elt;
+static void tfaff PROTO((void));
static if_elt *if_stack;
@@ -153,12 +159,12 @@ c_expand_start_else ()
expand_start_else ();
}
-/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
+/* Make bindings for __FUNCTION__, __PRETTY_FUNCTION__, and __func__. */
void
declare_function_name ()
{
- char *name, *printable_name;
+ const char *name, *printable_name;
if (current_function_decl == NULL)
{
@@ -177,11 +183,14 @@ declare_function_name ()
declare_hidden_char_array ("__FUNCTION__", name);
declare_hidden_char_array ("__PRETTY_FUNCTION__", printable_name);
+ /* The ISO C people "of course" couldn't use __FUNCTION__ in the
+ ISO C 9x standard; instead a new variable is invented. */
+ declare_hidden_char_array ("__func__", name);
}
static void
declare_hidden_char_array (name, value)
- char *name, *value;
+ const char *name, *value;
{
tree decl, type, init;
int vlen;
@@ -262,7 +271,7 @@ combine_strings (strings)
? wchar_bytes : 1));
if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
{
- bcopy (TREE_STRING_POINTER (t), q, len);
+ memcpy (q, TREE_STRING_POINTER (t), len);
q += len;
}
else
@@ -290,7 +299,6 @@ combine_strings (strings)
value = make_node (STRING_CST);
TREE_STRING_POINTER (value) = p;
TREE_STRING_LENGTH (value) = length;
- TREE_CONSTANT (value) = 1;
}
else
{
@@ -305,8 +313,9 @@ combine_strings (strings)
/* Create the array type for the string constant.
-Wwrite-strings says make the string constant an array of const char
- so that copying it to a non-const pointer will get a warning. */
- if (warn_write_strings
+ so that copying it to a non-const pointer will get a warning.
+ For C++, this is the standard behavior. */
+ if (flag_const_strings
&& (! flag_traditional && ! flag_writable_strings))
{
tree elements
@@ -320,7 +329,8 @@ combine_strings (strings)
TREE_TYPE (value)
= build_array_type (wide_flag ? wchar_type_node : char_type_node,
build_index_type (build_int_2 (nchars - 1, 0)));
- TREE_CONSTANT (value) = 1;
+
+ TREE_READONLY (value) = TREE_CONSTANT (value) = ! flag_writable_strings;
TREE_STATIC (value) = 1;
return value;
}
@@ -339,7 +349,7 @@ static int attrtab_idx = 0;
static void
add_attribute (id, string, min_len, max_len, decl_req)
enum attrs id;
- char *string;
+ const char *string;
int min_len, max_len;
int decl_req;
{
@@ -382,8 +392,29 @@ init_attributes ()
add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1);
add_attribute (A_WEAK, "weak", 0, 0, 1);
add_attribute (A_ALIAS, "alias", 1, 1, 1);
+ add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
+ add_attribute (A_NO_CHECK_MEMORY_USAGE, "no_check_memory_usage", 0, 0, 1);
}
+/* Default implementation of valid_lang_attribute, below. By default, there
+ are no language-specific attributes. */
+
+static int
+default_valid_lang_attribute (attr_name, attr_args, decl, type)
+ tree attr_name ATTRIBUTE_UNUSED;
+ tree attr_args ATTRIBUTE_UNUSED;
+ tree decl ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
+/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid language-specific
+ attribute for either declaration DECL or type TYPE and 0 otherwise. */
+
+int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree))
+ = default_valid_lang_attribute;
+
/* Process the attributes listed in ATTRIBUTES and PREFIX_ATTRIBUTES
and install them in NODE, which is either a DECL (including a TYPE_DECL)
or a TYPE. PREFIX_ATTRIBUTES can appear after the declaration specifiers
@@ -409,6 +440,18 @@ decl_attributes (node, attributes, prefix_attributes)
else if (TREE_CODE_CLASS (TREE_CODE (node)) == 't')
type = node, is_type = 1;
+#ifdef PRAGMA_INSERT_ATTRIBUTES
+ /* If the code in c-pragma.c wants to insert some attributes then
+ allow it to do so. Do this before allowing machine back ends to
+ insert attributes, so that they have the opportunity to override
+ anything done here. */
+ PRAGMA_INSERT_ATTRIBUTES (node, & attributes, & prefix_attributes);
+#endif
+
+#ifdef INSERT_ATTRIBUTES
+ INSERT_ATTRIBUTES (node, & attributes, & prefix_attributes);
+#endif
+
attributes = chainon (prefix_attributes, attributes);
for (a = attributes; a; a = TREE_CHAIN (a))
@@ -424,7 +467,8 @@ decl_attributes (node, attributes, prefix_attributes)
if (i == attrtab_idx)
{
- if (! valid_machine_attribute (name, args, decl, type))
+ if (! valid_machine_attribute (name, args, decl, type)
+ && ! (* valid_lang_attribute) (name, args, decl, type))
warning ("`%s' attribute directive ignored",
IDENTIFIER_POINTER (name));
else if (decl != 0)
@@ -491,7 +535,8 @@ decl_attributes (node, attributes, prefix_attributes)
TREE_USED (type) = 1;
else if (TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL)
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == LABEL_DECL)
TREE_USED (decl) = 1;
else
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
@@ -555,7 +600,7 @@ decl_attributes (node, attributes, prefix_attributes)
else
{
int j;
- char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
+ const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
int len = strlen (p);
enum machine_mode mode = VOIDmode;
tree typefm;
@@ -633,7 +678,7 @@ decl_attributes (node, attributes, prefix_attributes)
= (args ? TREE_VALUE (args)
: size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
int align;
-
+
/* Strip any NOPs of any kind. */
while (TREE_CODE (align_expr) == NOP_EXPR
|| TREE_CODE (align_expr) == CONVERT_EXPR
@@ -687,7 +732,7 @@ decl_attributes (node, attributes, prefix_attributes)
}
else
{
- char *p = IDENTIFIER_POINTER (format_type_id);
+ const char *p = IDENTIFIER_POINTER (format_type_id);
if (!strcmp (p, "printf") || !strcmp (p, "__printf__"))
format_type = printf_format_type;
@@ -698,7 +743,7 @@ decl_attributes (node, attributes, prefix_attributes)
format_type = strftime_format_type;
else
{
- error ("`%s' is an unrecognized format function type", p);
+ warning ("`%s' is an unrecognized format function type", p);
continue;
}
}
@@ -864,6 +909,40 @@ decl_attributes (node, attributes, prefix_attributes)
else
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
break;
+
+ case A_NO_CHECK_MEMORY_USAGE:
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error_with_decl (decl,
+ "can't set `%s' attribute after definition",
+ IDENTIFIER_POINTER (name));
+ }
+ else
+ DECL_NO_CHECK_MEMORY_USAGE (decl) = 1;
+ break;
+
+ case A_NO_INSTRUMENT_FUNCTION:
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error_with_decl (decl,
+ "can't set `%s' attribute after definition",
+ IDENTIFIER_POINTER (name));
+ }
+ else
+ DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
+ break;
}
}
}
@@ -983,7 +1062,7 @@ strip_attrs (specs_attrs)
#define T_ST &sizetype
typedef struct {
- char *format_chars;
+ const char *format_chars;
int pointer_count;
/* Type of argument if no length modifier is used. */
tree *nolen;
@@ -1006,7 +1085,7 @@ typedef struct {
If NULL, then this modifier is not allowed. */
tree *zlen;
/* List of other modifier characters allowed with these options. */
- char *flag_chars;
+ const char *flag_chars;
} format_char_info;
static format_char_info print_char_table[] = {
@@ -1022,7 +1101,7 @@ static format_char_info print_char_table[] = {
{ "S", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "-wp" },
{ "p", 1, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "-w" },
{ "n", 1, T_I, NULL, T_S, T_L, T_LL, NULL, NULL, "" },
- { NULL }
+ { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static format_char_info scan_char_table[] = {
@@ -1036,7 +1115,7 @@ static format_char_info scan_char_table[] = {
{ "S", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "*a" },
{ "p", 2, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "*" },
{ "n", 1, T_I, T_C, T_S, T_L, T_LL, NULL, NULL, "" },
- { NULL }
+ { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
/* Handle format characters recognized by glibc's strftime.c.
@@ -1061,7 +1140,7 @@ static format_char_info time_char_table[] = {
{ "p", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "#" },
{ "bh", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "^" },
{ "CY", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0EOw" },
- { NULL }
+ { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
typedef struct function_format_info
@@ -1206,7 +1285,11 @@ record_international_format (name, assembler_name, format_num)
info->format_num = format_num;
}
-static char tfaff[] = "too few arguments for format";
+static void
+tfaff ()
+{
+ warning ("too few arguments for format");
+}
/* Check the argument list of a call to printf, scanf, etc.
NAME is the function identifier.
@@ -1256,7 +1339,7 @@ check_format_info (info, params)
tree cur_type;
tree wanted_type;
tree first_fillin_param;
- char *format_chars;
+ const char *format_chars;
format_char_info *fci = NULL;
char flag_chars[8];
int has_operand_number = 0;
@@ -1420,7 +1503,7 @@ check_format_info (info, params)
it is an operand number, so set PARAMS to that operand. */
if (*format_chars >= '0' && *format_chars <= '9')
{
- char *p = format_chars;
+ const char *p = format_chars;
while (*p >= '0' && *p++ <= '9')
;
@@ -1473,7 +1556,7 @@ check_format_info (info, params)
++format_chars;
if (params == 0)
{
- warning (tfaff);
+ tfaff ();
return;
}
if (info->first_arg_num != 0)
@@ -1516,7 +1599,7 @@ check_format_info (info, params)
++format_chars;
if (params == 0)
{
- warning (tfaff);
+ tfaff ();
return;
}
cur_param = TREE_VALUE (params);
@@ -1686,7 +1769,7 @@ check_format_info (info, params)
if (precise && index (flag_chars, '0') != 0
&& (format_char == 'd' || format_char == 'i'
|| format_char == 'o' || format_char == 'u'
- || format_char == 'x' || format_char == 'x'))
+ || format_char == 'x' || format_char == 'X'))
warning ("`0' flag ignored with precision specifier and `%c' format",
format_char);
switch (length_char)
@@ -1711,7 +1794,7 @@ check_format_info (info, params)
continue;
if (params == 0)
{
- warning (tfaff);
+ tfaff ();
return;
}
cur_param = TREE_VALUE (params);
@@ -1737,9 +1820,9 @@ check_format_info (info, params)
continue;
}
if (TREE_CODE (cur_type) != ERROR_MARK)
- warning ("format argument is not a %s (arg %d)",
- ((fci->pointer_count + aflag == 1)
- ? "pointer" : "pointer to a pointer"),
+ warning ((fci->pointer_count + aflag == 1
+ ? "format argument is not a pointer (arg %d)"
+ : "format argument is not a pointer to a pointer (arg %d)"),
arg_num);
break;
}
@@ -1779,8 +1862,8 @@ check_format_info (info, params)
&& (TYPE_MAIN_VARIANT (cur_type) == signed_char_type_node
|| TYPE_MAIN_VARIANT (cur_type) == unsigned_char_type_node)))
{
- register char *this;
- register char *that;
+ register const char *this;
+ register const char *that;
this = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (wanted_type)));
that = 0;
@@ -2049,8 +2132,10 @@ type_for_mode (mode, unsignedp)
if (mode == TYPE_MODE (intDI_type_node))
return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
if (mode == TYPE_MODE (intTI_type_node))
return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+#endif
if (mode == TYPE_MODE (float_type_node))
return float_type_node;
@@ -2108,7 +2193,7 @@ void
binary_op_error (code)
enum tree_code code;
{
- register char *opname;
+ register const char *opname;
switch (code)
{
@@ -2399,18 +2484,18 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
/* This is the case of (char)x >?< 0x80, which people used to use
expecting old C compilers to change the 0x80 into -0x80. */
if (val == boolean_false_node)
- warning ("comparison is always 0 due to limited range of data type");
+ warning ("comparison is always false due to limited range of data type");
if (val == boolean_true_node)
- warning ("comparison is always 1 due to limited range of data type");
+ warning ("comparison is always true due to limited range of data type");
}
if (!min_lt && unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
{
/* This is the case of (unsigned char)x >?< -1 or < 0. */
if (val == boolean_false_node)
- warning ("comparison is always 0 due to limited range of data type");
+ warning ("comparison is always false due to limited range of data type");
if (val == boolean_true_node)
- warning ("comparison is always 1 due to limited range of data type");
+ warning ("comparison is always true due to limited range of data type");
}
if (val != 0)
@@ -2476,7 +2561,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
&& ! (TREE_CODE (primop0) == INTEGER_CST
&& ! TREE_OVERFLOW (convert (signed_type (type),
primop0))))
- warning ("unsigned value >= 0 is always 1");
+ warning ("comparison of unsigned expression >= 0 is always true");
value = boolean_true_node;
break;
@@ -2485,7 +2570,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
&& ! (TREE_CODE (primop0) == INTEGER_CST
&& ! TREE_OVERFLOW (convert (signed_type (type),
primop0))))
- warning ("unsigned value < 0 is always 0");
+ warning ("comparison of unsigned expression < 0 is always false");
value = boolean_false_node;
break;
@@ -2710,7 +2795,7 @@ truthvalue_conversion (expr)
unsigned char *yy_cur, *yy_lim;
#define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ())
-#define UNGETC(c) ((c), yy_cur--)
+#define UNGETC(c) ((c) == EOF ? 0 : yy_cur--)
int
yy_get_token ()
@@ -2884,15 +2969,134 @@ get_directive_line (finput)
down to the element type of an array. */
tree
-c_build_type_variant (type, constp, volatilep)
+c_build_qualified_type (type, type_quals)
tree type;
- int constp, volatilep;
+ int type_quals;
{
+ /* A restrict-qualified pointer type must be a pointer to object or
+ incomplete type. Note that the use of POINTER_TYPE_P also allows
+ REFERENCE_TYPEs, which is appropriate for C++. Unfortunately,
+ the C++ front-end also use POINTER_TYPE for pointer-to-member
+ values, so even though it should be illegal to use `restrict'
+ with such an entity we don't flag that here. Thus, special case
+ code for that case is required in the C++ front-end. */
+ if ((type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+ {
+ error ("invalid use of `restrict'");
+ type_quals &= ~TYPE_QUAL_RESTRICT;
+ }
+
if (TREE_CODE (type) == ARRAY_TYPE)
- return build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ return build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
- return build_type_variant (type, constp, volatilep);
+ return build_qualified_type (type, type_quals);
+}
+
+/* Apply the TYPE_QUALS to the new DECL. */
+
+void
+c_apply_type_quals_to_decl (type_quals, decl)
+ int type_quals;
+ tree decl;
+{
+ if (type_quals & TYPE_QUAL_CONST)
+ TREE_READONLY (decl) = 1;
+ if (type_quals & TYPE_QUAL_VOLATILE)
+ {
+ TREE_SIDE_EFFECTS (decl) = 1;
+ TREE_THIS_VOLATILE (decl) = 1;
+ }
+ if (type_quals & TYPE_QUAL_RESTRICT)
+ {
+ if (!TREE_TYPE (decl)
+ || !POINTER_TYPE_P (TREE_TYPE (decl))
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl))))
+ error ("invalid use of `restrict'");
+ else if (flag_strict_aliasing)
+ {
+ /* No two restricted pointers can point at the same thing.
+ However, a restricted pointer can point at the same thing
+ as an unrestricted pointer, if that unrestricted pointer
+ is based on the restricted pointer. So, we make the
+ alias set for the restricted pointer a subset of the
+ alias set for the type pointed to by the type of the
+ decl. */
+
+ int pointed_to_alias_set
+ = get_alias_set (TREE_TYPE (TREE_TYPE (decl)));
+
+ if (!pointed_to_alias_set)
+ /* It's not legal to make a subset of alias set zero. */
+ ;
+ else
+ {
+ DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
+ record_alias_subset (pointed_to_alias_set,
+ DECL_POINTER_ALIAS_SET (decl));
+ }
+ }
+ }
+}
+
+/* T is an expression with pointer type. Find the DECL on which this
+ expression is based. (For example, in `a[i]' this would be `a'.)
+ If there is no such DECL, or a unique decl cannot be determined,
+ NULL_TREE is retured. */
+
+static tree
+c_find_base_decl (t)
+ tree t;
+{
+ int i;
+ tree decl;
+
+ if (t == NULL_TREE || t == error_mark_node)
+ return NULL_TREE;
+
+ if (!POINTER_TYPE_P (TREE_TYPE (t)))
+ return NULL_TREE;
+
+ decl = NULL_TREE;
+
+ if (TREE_CODE (t) == FIELD_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == VAR_DECL)
+ /* Aha, we found a pointer-typed declaration. */
+ return t;
+
+ /* It would be nice to deal with COMPONENT_REFs here. If we could
+ tell that `a' and `b' were the same, then `a->f' and `b->f' are
+ also the same. */
+
+ /* Handle general expressions. */
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case '1':
+ case '2':
+ case '3':
+ for (i = tree_code_length [(int) TREE_CODE (t)]; --i >= 0;)
+ {
+ tree d = c_find_base_decl (TREE_OPERAND (t, i));
+ if (d)
+ {
+ if (!decl)
+ decl = d;
+ else if (d && d != decl)
+ /* Two different declarations. That's confusing; let's
+ just assume we don't know what's going on. */
+ decl = NULL_TREE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return decl;
}
/* Return the typed-based alias set for T, which may be an expression
@@ -2902,21 +3106,20 @@ int
c_get_alias_set (t)
tree t;
{
- static int next_set = 0;
tree type;
+ tree u;
if (t == error_mark_node)
return 0;
type = (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
- ? t : TREE_TYPE (t);
+ ? t : TREE_TYPE (t);
if (type == error_mark_node)
return 0;
- if (TYPE_ALIAS_SET_KNOWN_P (type))
- /* If we've already calculated the value, just return it. */
- return TYPE_ALIAS_SET (type);
+ /* Deal with special cases first; for certain kinds of references
+ we're interested in more than just the type. */
if (TREE_CODE (t) == BIT_FIELD_REF)
/* Perhaps reads and writes to this piece of data alias fields
@@ -2924,22 +3127,48 @@ c_get_alias_set (t)
let's just assume that bitfields can alias everything, which is
the conservative assumption. */
return 0;
- if (TREE_CODE (t) == COMPONENT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
- /* Permit type-punning when accessing a union, provided the
- access is directly through the union. For example, this code does
- not permit taking the address of a union member and then
- storing through it. Even the type-punning allowed here is a
- GCC extension, albeit a common and useful one; the C standard
- says that such accesses have implementation-defined behavior. */
- return 0;
- else if (TYPE_MAIN_VARIANT (type) != type)
+
+ /* Permit type-punning when accessing a union, provided the access
+ is directly through the union. For example, this code does not
+ permit taking the address of a union member and then storing
+ through it. Even the type-punning allowed here is a GCC
+ extension, albeit a common and useful one; the C standard says
+ that such accesses have implementation-defined behavior. */
+ for (u = t;
+ TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
+ u = TREE_OPERAND (u, 0))
+ if (TREE_CODE (u) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
+ return 0;
+
+ if (TREE_CODE (t) == INDIRECT_REF)
{
- /* The C standard specifically allows aliasing between
- cv-qualified variants of types. */
- TYPE_ALIAS_SET (type) = c_get_alias_set (TYPE_MAIN_VARIANT (type));
- return TYPE_ALIAS_SET (type);
+ /* Check for accesses through restrict-qualified pointers. */
+ tree decl = c_find_base_decl (TREE_OPERAND (t, 0));
+
+ if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
+ /* We use the alias set indicated in the declaration. */
+ return DECL_POINTER_ALIAS_SET (decl);
}
+
+ /* From here on, only the type matters. */
+
+ if (TREE_CODE (t) == COMPONENT_REF
+ && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)))
+ /* Since build_modify_expr calls get_unwidened for stores to
+ component references, the type of a bit field can be changed
+ from (say) `unsigned int : 16' to `unsigned short' or from
+ `enum E : 16' to `short'. We want the real type of the
+ bit-field in this case, not some the integral equivalent. */
+ type = DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1));
+
+ if (TYPE_ALIAS_SET_KNOWN_P (type))
+ /* If we've already calculated the value, just return it. */
+ return TYPE_ALIAS_SET (type);
+ else if (TYPE_MAIN_VARIANT (type) != type)
+ /* The C standard specifically allows aliasing between
+ cv-qualified variants of types. */
+ TYPE_ALIAS_SET (type) = c_get_alias_set (TYPE_MAIN_VARIANT (type));
else if (TREE_CODE (type) == INTEGER_TYPE)
{
tree signed_variant;
@@ -2950,34 +3179,37 @@ c_get_alias_set (t)
signed_variant = signed_type (type);
if (signed_variant != type)
- {
- TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant);
- return TYPE_ALIAS_SET (type);
- }
+ TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant);
else if (signed_variant == signed_char_type_node)
/* The C standard guarantess that any object may be accessed
via an lvalue that has character type. We don't have to
check for unsigned_char_type_node or char_type_node because
we are specifically looking at the signed variant. */
- {
- TYPE_ALIAS_SET (type) = 0;
- return TYPE_ALIAS_SET (type);
- }
+ TYPE_ALIAS_SET (type) = 0;
}
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ /* Anything that can alias one of the array elements can alias
+ the entire array as well. */
+ TYPE_ALIAS_SET (type) = c_get_alias_set (TREE_TYPE (type));
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ /* There are no objects of FUNCTION_TYPE, so there's no point in
+ using up an alias set for them. (There are, of course,
+ pointers and references to functions, but that's
+ different.) */
+ TYPE_ALIAS_SET (type) = 0;
else if (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
- {
- /* If TYPE is a struct or union type then we're reading or
- writing an entire struct. Thus, we don't know anything about
- aliasing. (In theory, such an access can only alias objects
- whose type is the same as one of the fields, recursively, but
- we don't yet make any use of that information.) */
- TYPE_ALIAS_SET (type) = 0;
- return TYPE_ALIAS_SET (type);
- }
+ /* If TYPE is a struct or union type then we're reading or
+ writing an entire struct. Thus, we don't know anything about
+ aliasing. (In theory, such an access can only alias objects
+ whose type is the same as one of the fields, recursively, but
+ we don't yet make any use of that information.) */
+ TYPE_ALIAS_SET (type) = 0;
+
+ if (!TYPE_ALIAS_SET_KNOWN_P (type))
+ /* TYPE is something we haven't seen before. Put it in a new
+ alias set. */
+ TYPE_ALIAS_SET (type) = new_alias_set ();
- /* TYPE is something we haven't seen before. Put it in a new alias
- set. */
- TYPE_ALIAS_SET (type) = ++next_set;
return TYPE_ALIAS_SET (type);
}
diff --git a/contrib/gcc/c-convert.c b/contrib/gcc/c-convert.c
index 6f58e76..9cb9416 100644
--- a/contrib/gcc/c-convert.c
+++ b/contrib/gcc/c-convert.c
@@ -1,5 +1,5 @@
/* Language-level data type conversion for GNU C.
- Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c
index ccaa7d2..a232217 100644
--- a/contrib/gcc/c-decl.c
+++ b/contrib/gcc/c-decl.c
@@ -1,5 +1,5 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -37,9 +37,7 @@ Boston, MA 02111-1307, USA. */
#if USE_CPPLIB
#include "cpplib.h"
-extern cpp_reader parse_in;
-extern cpp_options parse_options;
-static int cpp_initialized;
+extern cpp_reader parse_in;
#endif
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
@@ -151,13 +149,17 @@ tree intQI_type_node;
tree intHI_type_node;
tree intSI_type_node;
tree intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
tree intTI_type_node;
+#endif
tree unsigned_intQI_type_node;
tree unsigned_intHI_type_node;
tree unsigned_intSI_type_node;
tree unsigned_intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
tree unsigned_intTI_type_node;
+#endif
/* a VOID_TYPE node. */
@@ -424,7 +426,7 @@ tree static_ctors, static_dtors;
static struct binding_level * make_binding_level PROTO((void));
static void clear_limbo_values PROTO((tree));
static int duplicate_decls PROTO((tree, tree, int));
-static char *redeclaration_error_message PROTO((tree, tree));
+static int redeclaration_error_message PROTO((tree, tree));
static void storedecls PROTO((tree));
static void storetags PROTO((tree));
static tree lookup_tag PROTO((enum tree_code, tree,
@@ -464,6 +466,10 @@ int flag_no_nonansi_builtin;
int flag_traditional;
+/* Nonzero means use the ISO C9x dialect of C. */
+
+int flag_isoc9x = 0;
+
/* Nonzero means that we have builtin functions, and main is an int */
int flag_hosted = 1;
@@ -477,10 +483,6 @@ int flag_allow_single_precision = 0;
int flag_signed_bitfields = 1;
int explicit_flag_signed_bitfields = 0;
-/* Nonzero means handle `#ident' directives. 0 means ignore them. */
-
-int flag_no_ident = 0;
-
/* Nonzero means warn about use of implicit int. */
int warn_implicit_int;
@@ -498,7 +500,7 @@ int mesg_implicit_function_declaration;
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
-int warn_write_strings;
+int flag_const_strings;
/* Nonzero means warn about pointer casts that can drop a type qualifier
from the pointer target type. */
@@ -511,6 +513,10 @@ int warn_cast_qual;
int warn_bad_function_cast;
+/* Warn about functions which might be candidates for attribute noreturn. */
+
+int warn_missing_noreturn;
+
/* Warn about traditional constructs whose meanings changed in ANSI C. */
int warn_traditional;
@@ -597,19 +603,12 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
int
c_decode_option (argc, argv)
- int argc;
+ int argc ATTRIBUTE_UNUSED;
char **argv;
{
int strings_processed;
char *p = argv[0];
#if USE_CPPLIB
- if (! cpp_initialized)
- {
- cpp_reader_init (&parse_in);
- parse_in.data = &parse_options;
- cpp_options_init (&parse_options);
- cpp_initialized = 1;
- }
strings_processed = cpp_handle_option (&parse_in, argc, argv);
#else
strings_processed = 0;
@@ -640,6 +639,63 @@ c_decode_option (argc, argv)
flag_traditional = 0;
flag_writable_strings = 0;
}
+ else if (!strncmp (p, "-std=", 5))
+ {
+ /* Select the appropriate language standard. We currently
+ recognize:
+ -std=iso9899:1990 same as -ansi
+ -std=iso9899:199409 ISO C as modified in amend. 1
+ -std=iso9899:199x ISO C 9x
+ -std=c89 same as -std=iso9899:1990
+ -std=c9x same as -std=iso9899:199x
+ -std=gnu89 default, iso9899:1990 + gnu extensions
+ -std=gnu9x iso9899:199x + gnu extensions
+ */
+ const char *argstart = &p[5];
+
+ if (!strcmp (argstart, "iso9899:1990")
+ || !strcmp (argstart, "c89"))
+ {
+ iso_1990:
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 1;
+ flag_no_nonansi_builtin = 1;
+ flag_isoc9x = 0;
+ }
+ else if (!strcmp (argstart, "iso9899:199409"))
+ {
+ /* ??? The changes since ISO C 1990 are not supported. */
+ goto iso_1990;
+ }
+ else if (!strcmp (argstart, "iso9899:199x")
+ || !strcmp (argstart, "c9x"))
+ {
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 1;
+ flag_no_nonansi_builtin = 1;
+ flag_isoc9x = 1;
+ }
+ else if (!strcmp (argstart, "gnu89"))
+ {
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 0;
+ flag_no_nonansi_builtin = 0;
+ flag_isoc9x = 0;
+ }
+ else if (!strcmp (argstart, "gnu9x"))
+ {
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 0;
+ flag_no_nonansi_builtin = 0;
+ flag_isoc9x = 1;
+ }
+ else
+ error ("unknown C standard `%s'", argstart);
+ }
else if (!strcmp (p, "-fdollars-in-identifiers"))
dollars_in_ident = 1;
else if (!strcmp (p, "-fno-dollars-in-identifiers"))
@@ -684,12 +740,8 @@ c_decode_option (argc, argv)
flag_no_builtin = 0;
else if (!strcmp (p, "-fno-builtin"))
flag_no_builtin = 1;
- else if (!strcmp (p, "-fno-ident"))
- flag_no_ident = 1;
- else if (!strcmp (p, "-fident"))
- flag_no_ident = 0;
else if (!strcmp (p, "-ansi"))
- flag_no_asm = 1, flag_no_nonansi_builtin = 1;
+ goto iso_1990;
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
mesg_implicit_function_declaration = 2;
else if (!strcmp (p, "-Wimplicit-function-declaration"))
@@ -713,9 +765,9 @@ c_decode_option (argc, argv)
else if (!strcmp (p, "-Wno-long-long"))
warn_long_long = 0;
else if (!strcmp (p, "-Wwrite-strings"))
- warn_write_strings = 1;
+ flag_const_strings = 1;
else if (!strcmp (p, "-Wno-write-strings"))
- warn_write_strings = 0;
+ flag_const_strings = 0;
else if (!strcmp (p, "-Wcast-qual"))
warn_cast_qual = 1;
else if (!strcmp (p, "-Wno-cast-qual"))
@@ -724,6 +776,10 @@ c_decode_option (argc, argv)
warn_bad_function_cast = 1;
else if (!strcmp (p, "-Wno-bad-function-cast"))
warn_bad_function_cast = 0;
+ else if (!strcmp (p, "-Wmissing-noreturn"))
+ warn_missing_noreturn = 1;
+ else if (!strcmp (p, "-Wno-missing-noreturn"))
+ warn_missing_noreturn = 0;
else if (!strcmp (p, "-Wpointer-arith"))
warn_pointer_arith = 1;
else if (!strcmp (p, "-Wno-pointer-arith"))
@@ -799,7 +855,7 @@ c_decode_option (argc, argv)
else if (!strcmp (p, "-Wmain"))
warn_main = 1;
else if (!strcmp (p, "-Wno-main"))
- warn_main = 0;
+ warn_main = -1;
else if (!strcmp (p, "-Wsign-compare"))
warn_sign_compare = 1;
else if (!strcmp (p, "-Wno-sign-compare"))
@@ -942,7 +998,7 @@ kept_level_p ()
void
declare_parm_level (definition_flag)
- int definition_flag;
+ int definition_flag ATTRIBUTE_UNUSED;
{
current_binding_level->parm_flag = 1;
}
@@ -1059,24 +1115,22 @@ poplevel (keep, reverse, functionbody)
if (TYPE_SIZE (TREE_VALUE (link)) == 0)
{
tree type = TREE_VALUE (link);
- char *errmsg;
+ tree type_name = TYPE_NAME (type);
+ char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE
+ ? type_name
+ : DECL_NAME (type_name));
switch (TREE_CODE (type))
{
case RECORD_TYPE:
- errmsg = "`struct %s' incomplete in scope ending here";
+ error ("`struct %s' incomplete in scope ending here", id);
break;
case UNION_TYPE:
- errmsg = "`union %s' incomplete in scope ending here";
+ error ("`union %s' incomplete in scope ending here", id);
break;
case ENUMERAL_TYPE:
- errmsg = "`enum %s' incomplete in scope ending here";
+ error ("`enum %s' incomplete in scope ending here", id);
break;
}
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
- else
- /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */
- error (errmsg, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
}
#endif /* 0 */
@@ -1456,7 +1510,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
&& DECL_INITIAL (newdecl) != 0);
tree oldtype = TREE_TYPE (olddecl);
tree newtype = TREE_TYPE (newdecl);
- char *errmsg = 0;
+ int errmsg = 0;
if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
DECL_MACHINE_ATTRIBUTES (newdecl)
@@ -1683,16 +1737,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
- error ("A parameter list with an ellipsis can't match");
- error ("an empty parameter name list declaration.");
+ error ("A parameter list with an ellipsis can't match an empty parameter name list declaration.");
break;
}
if (TYPE_MAIN_VARIANT (type) == float_type_node
|| C_PROMOTING_INTEGER_TYPE_P (type))
{
- error ("An argument type that has a default promotion");
- error ("can't match an empty parameter name list declaration.");
+ error ("An argument type that has a default promotion can't match an empty parameter name list declaration.");
break;
}
}
@@ -1704,7 +1756,21 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
- error_with_decl (newdecl, errmsg);
+ switch (errmsg)
+ {
+ case 1:
+ error_with_decl (newdecl, "redefinition of `%s'");
+ break;
+ case 2:
+ error_with_decl (newdecl, "redeclaration of `%s'");
+ break;
+ case 3:
+ error_with_decl (newdecl, "conflicting declarations of `%s'");
+ break;
+ default:
+ abort ();
+ }
+
error_with_decl (olddecl,
((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
@@ -1736,14 +1802,22 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
type = TYPE_ARG_TYPES (newtype),
nargs = 1;
- (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) != void_type_node
- || TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node);
+ ;
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
{
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
+ && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+ {
+ warning_with_decl (newdecl, "prototype for `%s' follows");
+ warning_with_decl (olddecl, "non-prototype definition here");
+ break;
+ }
+ if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
- errmsg = "prototype for `%s' follows and number of arguments";
+ error_with_decl (newdecl, "prototype for `%s' follows and number of arguments doesn't match");
+ error_with_decl (olddecl, "non-prototype definition here");
+ errmsg = 1;
break;
}
/* Type for passing arg must be consistent
@@ -1755,21 +1829,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
&& TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
{
- errmsg = "prototype for `%s' follows and argument %d";
+ error_with_decl (newdecl,
+ "prototype for `%s' follows and argument %d doesn't match",
+ nargs);
+ error_with_decl (olddecl, "non-prototype definition here");
+ errmsg = 1;
break;
}
}
- if (errmsg)
- {
- error_with_decl (newdecl, errmsg, nargs);
- error_with_decl (olddecl,
- "doesn't match non-prototype definition here");
- }
- else
- {
- warning_with_decl (newdecl, "prototype for `%s' follows");
- warning_with_decl (olddecl, "non-prototype definition here");
- }
}
/* Warn about mismatches in various flags. */
else
@@ -1794,6 +1861,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
&& !TREE_PUBLIC (newdecl))
warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
+ /* If warn_traditional, warn when a non-static function
+ declaration follows a static one. */
+ if (warn_traditional
+ && TREE_CODE (olddecl) == FUNCTION_DECL
+ && !TREE_PUBLIC (olddecl)
+ && TREE_PUBLIC (newdecl))
+ warning_with_decl (newdecl, "non-static declaration for `%s' follows static");
+
/* Warn when const declaration follows a non-const
declaration, but not for functions. */
if (TREE_CODE (olddecl) != FUNCTION_DECL
@@ -1931,6 +2006,11 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
{
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+
+ DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
+ |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+ DECL_NO_CHECK_MEMORY_USAGE (newdecl)
+ |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
}
pop_obstacks ();
@@ -2017,7 +2097,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
if (DECL_INLINE (newdecl))
- DECL_ABSTRACT_ORIGIN (newdecl) = olddecl;
+ DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
}
}
if (different_binding_level)
@@ -2381,7 +2461,7 @@ pushdecl (x)
DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
DECL_RESULT (x) = DECL_RESULT (oldglobal);
TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
- DECL_ABSTRACT_ORIGIN (x) = oldglobal;
+ DECL_ABSTRACT_ORIGIN (x) = DECL_ORIGIN (oldglobal);
}
/* Inner extern decl is built-in if global one is. */
if (DECL_BUILT_IN (oldglobal))
@@ -2454,7 +2534,7 @@ pushdecl (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
- char *warnstring = 0;
+ char *id = IDENTIFIER_POINTER (name);
if (TREE_CODE (x) == PARM_DECL
&& current_binding_level->level_chain->parm_flag)
@@ -2465,15 +2545,12 @@ pushdecl (x)
but there is no way to tell it's not a definition. */
;
else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
- warnstring = "declaration of `%s' shadows a parameter";
+ warning ("declaration of `%s' shadows a parameter", id);
else if (oldlocal != 0)
- warnstring = "declaration of `%s' shadows previous local";
+ warning ("declaration of `%s' shadows previous local", id);
else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
&& IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
- warnstring = "declaration of `%s' shadows global declaration";
-
- if (warnstring)
- warning (warnstring, IDENTIFIER_POINTER (name));
+ warning ("declaration of `%s' shadows global declaration", id);
}
/* If storing a local value, there may already be one (inherited).
@@ -2584,10 +2661,10 @@ implicitly_declare (functionid)
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
- Otherwise return an error message format string with a %s
- where the identifier should go. */
+ Otherwise return 1 if NEWDECL is a redefinition, 2 if it is a redeclaration,
+ and 3 if it is a conflicting declaration. */
-static char *
+static int
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
@@ -2606,7 +2683,7 @@ redeclaration_error_message (newdecl, olddecl)
return 0;
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
return 0;
- return "redefinition of `%s'";
+ return 1;
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
@@ -2619,7 +2696,7 @@ redeclaration_error_message (newdecl, olddecl)
time in another way is ok. */
&& !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
&& !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
- return "redefinition of `%s'";
+ return 1;
return 0;
}
else if (current_binding_level == global_binding_level)
@@ -2630,11 +2707,11 @@ redeclaration_error_message (newdecl, olddecl)
return 0;
/* Reject two definitions. */
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0)
- return "redefinition of `%s'";
+ return 1;
/* Now we have two tentative defs, or one tentative and one real def. */
/* Insist that the linkage match. */
if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
- return "conflicting declarations of `%s'";
+ return 3;
return 0;
}
else if (current_binding_level->parm_flag
@@ -2648,7 +2725,7 @@ redeclaration_error_message (newdecl, olddecl)
be an extern reference to olddecl. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
&& DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
- return "redeclaration of `%s'";
+ return 2;
return 0;
}
}
@@ -3038,8 +3115,10 @@ init_decl_processing ()
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
+#endif
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
@@ -3053,8 +3132,10 @@ init_decl_processing ()
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+#endif
float_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -3288,8 +3369,8 @@ init_decl_processing ()
builtin_function ("__builtin_unwind_init",
build_function_type (void_type_node, endlink),
BUILT_IN_UNWIND_INIT, NULL_PTR);
- builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
- builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
+ builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
+ BUILT_IN_DWARF_CFA, NULL_PTR);
builtin_function ("__builtin_dwarf_fp_regnum",
build_function_type (unsigned_type_node, endlink),
BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
@@ -3299,24 +3380,16 @@ init_decl_processing ()
BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
- builtin_function ("__builtin_set_return_addr_reg",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink)),
- BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
- builtin_function ("__builtin_eh_stub_old", ptr_ftype_void,
- BUILT_IN_EH_STUB_OLD, NULL_PTR);
- builtin_function ("__builtin_eh_stub", ptr_ftype_void,
- BUILT_IN_EH_STUB, NULL_PTR);
builtin_function
- ("__builtin_set_eh_regs",
+ ("__builtin_eh_return",
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
type_for_mode (ptr_mode, 0),
- endlink))),
- BUILT_IN_SET_EH_REGS, NULL_PTR);
+ tree_cons (NULL_TREE,
+ ptr_type_node,
+ endlink)))),
+ BUILT_IN_EH_RETURN, NULL_PTR);
builtin_function ("__builtin_alloca",
build_function_type (ptr_type_node,
@@ -3530,7 +3603,7 @@ init_decl_processing ()
incomplete_decl_finalize_hook = finish_incomplete_decl;
- lang_get_alias_set = &c_get_alias_set;
+ lang_get_alias_set = c_get_alias_set;
}
/* Return a definition for a builtin function named NAME and whose data type
@@ -3543,10 +3616,10 @@ init_decl_processing ()
tree
builtin_function (name, type, function_code, library_name)
- char *name;
+ const char *name;
tree type;
enum built_in_function function_code;
- char *library_name;
+ const char *library_name;
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
@@ -3718,7 +3791,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
/* The corresponding pop_obstacks is in finish_decl. */
push_obstacks_nochange ();
- if (warn_main && TREE_CODE (decl) != FUNCTION_DECL
+ if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
warning_with_decl (decl, "`%s' is usually a function");
@@ -4309,13 +4382,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
tree type = NULL_TREE;
int longlong = 0;
int constp;
+ int restrictp;
int volatilep;
+ int type_quals = TYPE_UNQUALIFIED;
int inlinep;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
tree typedef_decl = 0;
- char *name;
+ const char *name;
tree typedef_type = 0;
int funcdef_flag = 0;
enum tree_code innermost_code = ERROR_MARK;
@@ -4471,13 +4546,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
&& ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
&& ! (in_system_header && ! allocation_temporary_p ()))
{
- /* C9x will probably require a diagnostic here.
- For now, issue a warning if -Wreturn-type and this is a function,
- or if -Wimplicit; prefer the former warning since it is more
- explicit. */
+ /* Issue a warning if this is an ISO C 9x program or if -Wreturn-type
+ and this is a function, or if -Wimplicit; prefer the former
+ warning since it is more explicit. */
if ((warn_implicit_int || warn_return_type) && funcdef_flag)
warn_about_return_type = 1;
- else if (warn_implicit_int)
+ else if (warn_implicit_int || flag_isoc9x)
warning ("type defaults to `int' in declaration of `%s'", name);
}
@@ -4619,19 +4693,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = build_complex_type (type);
}
- /* Set CONSTP if this declaration is `const', whether by
- explicit specification or via a typedef.
- Likewise for VOLATILEP. */
-
+ /* Figure out the type qualifiers for the declaration. There are
+ two ways a declaration can become qualified. One is something
+ like `const int i' where the `const' is explicit. Another is
+ something like `typedef const int CI; CI i' where the type of the
+ declaration contains the `const'. */
constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type);
+ restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
inlinep = !! (specbits & (1 << (int) RID_INLINE));
if (constp > 1)
pedwarn ("duplicate `const'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
- if (! flag_gen_aux_info && (TYPE_READONLY (type) || TYPE_VOLATILE (type)))
+ if (! flag_gen_aux_info && (TYPE_QUALS (type)))
type = TYPE_MAIN_VARIANT (type);
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
/* Warn if two storage classes are given. Default to `auto'. */
@@ -4865,13 +4946,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
is set correctly. */
type = build_array_type (type, itype);
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
#if 0 /* don't clear these; leave them set so that the array type
or the variable is itself const or volatile. */
- constp = 0;
- volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
if (size_varies)
@@ -4936,12 +5016,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
flag_traditional
? NULL_TREE : arg_types);
#endif
- /* ANSI seems to say that `const int foo ();'
- does not make the function foo const. */
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
- constp = 0;
- volatilep = 0;
+ /* Type qualifiers before the return type of the function
+ qualify the return type, not the function type. */
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+ type_quals = TYPE_UNQUALIFIED;
type = build_function_type (type, arg_types);
declarator = TREE_OPERAND (declarator, 0);
@@ -4965,12 +5044,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
for the pointer. */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
- constp = 0;
- volatilep = 0;
+ && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+ type_quals = TYPE_UNQUALIFIED;
size_varies = 0;
type = build_pointer_type (type);
@@ -4982,13 +5060,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{
register tree typemodlist;
int erred = 0;
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
- if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+ tree qualifier = TREE_VALUE (typemodlist);
+
+ if (qualifier == ridpointers[(int) RID_CONST])
constp++;
- else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+ else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++;
+ else if (qualifier == ridpointers[(int) RID_RESTRICT])
+ restrictp++;
else if (!erred)
{
erred = 1;
@@ -4999,6 +5085,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
+
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
}
declarator = TREE_OPERAND (declarator, 0);
@@ -5025,10 +5117,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Note that the grammar rejects storage classes
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator, type);
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
@@ -5060,10 +5152,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Note that the grammar rejects storage classes
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
+ && type_quals)
pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
pop_obstacks ();
return type;
}
@@ -5103,20 +5195,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{
/* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type);
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- volatilep = constp = 0;
+ type_quals = TYPE_UNQUALIFIED;
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (pedantic && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (pedantic && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- volatilep = constp = 0;
+ type_quals = TYPE_UNQUALIFIED;
}
decl = build_decl (PARM_DECL, declarator, type);
@@ -5164,13 +5256,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = error_mark_node;
}
/* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+ if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
- type = build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
#if 0 /* Leave the field const or volatile as well. */
- constp = volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
}
decl = build_decl (FIELD_DECL, declarator, type);
@@ -5209,18 +5301,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_machine_attr);
- if (pedantic && (constp || volatilep)
- && ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids const or volatile functions");
+ if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+ pedwarn ("ANSI C forbids qualified function types");
if (pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
- && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl)))
- || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
+ && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids const or volatile void function return type");
+ pedwarn ("ANSI C forbids qualified void function return type");
- if (volatilep
+ /* GNU C interprets a `volatile void' return type to indicate
+ that the function does not return. */
+ if ((type_quals & TYPE_QUAL_VOLATILE)
&& TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
warning ("`noreturn' function returns non-void value");
@@ -5250,13 +5342,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
/* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+ if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
- type = build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
#if 0 /* Leave the variable const or volatile as well. */
- constp = volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
}
@@ -5303,14 +5395,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
DECL_REGISTER (decl) = 1;
/* Record constancy and volatility. */
+ c_apply_type_quals_to_decl (type_quals, decl);
- if (constp)
- TREE_READONLY (decl) = 1;
- if (volatilep)
- {
- TREE_SIDE_EFFECTS (decl) = 1;
- TREE_THIS_VOLATILE (decl) = 1;
- }
/* If a type has volatile components, it should be stored in memory.
Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler. */
@@ -5570,8 +5656,7 @@ parmlist_tags_warning ()
if (! already)
{
- warning ("its scope is only this definition or declaration,");
- warning ("which is probably not what you want.");
+ warning ("its scope is only this definition or declaration, which is probably not what you want.");
already = 1;
}
}
@@ -5685,8 +5770,8 @@ start_struct (code, name)
tree
grokfield (filename, line, declarator, declspecs, width)
- char *filename;
- int line;
+ const char *filename ATTRIBUTE_UNUSED;
+ int line ATTRIBUTE_UNUSED;
tree declarator, declspecs, width;
{
tree value;
@@ -5768,9 +5853,10 @@ finish_struct (t, fieldlist, attributes)
break;
if (x == 0)
- pedwarn ("%s has no %smembers",
- (TREE_CODE (t) == UNION_TYPE ? "union" : "structure"),
- (fieldlist ? "named " : ""));
+ pedwarn ((fieldlist
+ ? "%s has no named members"
+ : "%s has no members"),
+ TREE_CODE (t) == UNION_TYPE ? "union" : "struct");
}
/* Install struct as DECL_CONTEXT of each field decl.
@@ -6428,6 +6514,10 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
except for defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
+#endif
+
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
@@ -6437,7 +6527,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
TREE_PUBLIC (decl1) = 0;
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
- if (warn_main
+ if (warn_main > 0
&& strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
{
tree args;
@@ -7154,12 +7244,8 @@ finish_function (nested)
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
{
- /* You would expect the sense of this test to be the other way
- around, but if warn_main is set, we will already have warned,
- so this would be a duplicate. This is the warning you get
- in some environments even if you *don't* ask for it, because
- these are environments where it may be more of a problem than
- usual. */
+ /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
+ If warn_main is -1 (-Wno-main) we don't want to be warned. */
if (! warn_main)
pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
}
@@ -7183,6 +7269,12 @@ finish_function (nested)
current_function_returns_null |= can_reach_end;
+ if (warn_missing_noreturn
+ && !TREE_THIS_VOLATILE (fndecl)
+ && !current_function_returns_null
+ && !current_function_returns_value)
+ warning ("function might be possible candidate for attribute `noreturn'");
+
if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
warning ("`noreturn' function does return");
else if (warn_return_type && can_reach_end
diff --git a/contrib/gcc/c-iterate.c b/contrib/gcc/c-iterate.c
index b8f51d0..dc0cc8a 100644
--- a/contrib/gcc/c-iterate.c
+++ b/contrib/gcc/c-iterate.c
@@ -1,5 +1,5 @@
/* Build expressions with type checking for C compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92, 93, 96, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -539,10 +539,10 @@ prdecl (d)
fprintf (stderr, dname);
}
else
- fprintf (stderr, "<<Not a Decl!!!>>");
+ fprintf (stderr, "<<?>>");
}
else
- fprintf (stderr, "<<NULL!!>>");
+ fprintf (stderr, "<<0>>");
}
/* Print Iterator List -- names only */
diff --git a/contrib/gcc/c-lang.c b/contrib/gcc/c-lang.c
index 8a5fd6b..4c55411 100644
--- a/contrib/gcc/c-lang.c
+++ b/contrib/gcc/c-lang.c
@@ -28,6 +28,13 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "output.h"
+#if USE_CPPLIB
+#include "cpplib.h"
+extern char *yy_cur;
+extern cpp_reader parse_in;
+extern cpp_options parse_options;
+#endif
+
/* Each of the functions defined here
is an alternative to a function in objc-actions.c. */
@@ -42,17 +49,25 @@ lang_decode_option (argc, argv)
void
lang_init_options ()
{
+#if USE_CPPLIB
+ cpp_reader_init (&parse_in);
+ parse_in.opts = &parse_options;
+ cpp_options_init (&parse_options);
+#endif
}
void
lang_init ()
{
-#if !USE_CPPLIB
/* the beginning of the file is a new line; check for # */
/* With luck, we discover the real source file's name from that
and put it in input_filename. */
+#if !USE_CPPLIB
ungetc (check_newline (), finput);
-#endif
+#else
+ check_newline ();
+ yy_cur--;
+#endif
}
void
@@ -134,7 +149,7 @@ recognize_objc_keyword ()
tree
build_objc_string (len, str)
int len ATTRIBUTE_UNUSED;
- char *str ATTRIBUTE_UNUSED;
+ const char *str ATTRIBUTE_UNUSED;
{
abort ();
return NULL_TREE;
diff --git a/contrib/gcc/c-lex.c b/contrib/gcc/c-lex.c
index f82ad76..27c65f3 100644
--- a/contrib/gcc/c-lex.c
+++ b/contrib/gcc/c-lex.c
@@ -20,7 +20,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include <setjmp.h>
#include "rtl.h"
#include "tree.h"
@@ -32,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "c-parse.h"
#include "c-pragma.h"
#include "toplev.h"
+#include "intl.h"
/* MULTIBYTE_CHARS support only works for native compilers.
??? Ideally what we want is to model widechar support after
@@ -41,8 +41,9 @@ Boston, MA 02111-1307, USA. */
#endif
#ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
#include <locale.h>
-#endif
+#endif /* MULTIBYTE_CHARS */
#if USE_CPPLIB
#include "cpplib.h"
@@ -65,11 +66,11 @@ tree ridpointers[(int) RID_MAX];
#if USE_CPPLIB
extern unsigned char *yy_cur, *yy_lim;
-
+
extern int yy_get_token ();
-
+
#define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ())
-#define UNGETC(c) ((c), yy_cur--)
+#define UNGETC(c) ((c) == EOF ? 0 : yy_cur--)
#else
#define GETC() getc (finput)
#define UNGETC(c) ungetc (c, finput)
@@ -116,14 +117,15 @@ static int end_of_file;
static int nextchar = -1;
#endif
-#ifdef HANDLE_SYSV_PRAGMA
-static int handle_sysv_pragma PROTO((int));
-#endif /* HANDLE_SYSV_PRAGMA */
+#ifdef HANDLE_GENERIC_PRAGMAS
+static int handle_generic_pragma PROTO((int));
+#endif /* HANDLE_GENERIC_PRAGMAS */
static int whitespace_cr PROTO((int));
static int skip_white_space PROTO((int));
static int skip_white_space_on_line PROTO((void));
-static char *extend_token_buffer PROTO((char *));
+static char *extend_token_buffer PROTO((const char *));
static int readescape PROTO((int *));
+static void parse_float PROTO((PTR));
/* Do not insert generated code into the source, instead, include it.
This allows us to build gcc automatically even for targets that
@@ -170,8 +172,10 @@ remember_protocol_qualifiers ()
wordlist[i].name = "inout";
else if (wordlist[i].rid == RID_BYCOPY)
wordlist[i].name = "bycopy";
+ else if (wordlist[i].rid == RID_BYREF)
+ wordlist[i].name = "byref";
else if (wordlist[i].rid == RID_ONEWAY)
- wordlist[i].name = "oneway";
+ wordlist[i].name = "oneway";
}
char *
@@ -193,19 +197,22 @@ init_parse (filename)
#ifdef IO_BUFFER_SIZE
setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
#endif
-#endif /* !USE_CPPLIB */
-
- init_lex ();
-
-#if USE_CPPLIB
- yy_cur = "\n";
- yy_lim = yy_cur+1;
-
+#else /* !USE_CPPLIB */
parse_in.show_column = 1;
if (! cpp_start_read (&parse_in, filename))
abort ();
+
+ if (filename == 0 || !strcmp (filename, "-"))
+ filename = "stdin";
+
+ /* cpp_start_read always puts at least one line directive into the
+ token buffer. We must arrange to read it out here. */
+ yy_cur = parse_in.token_buffer;
+ yy_lim = CPP_PWRITTEN (&parse_in);
#endif
+ init_lex ();
+
return filename;
}
@@ -232,6 +239,7 @@ init_lex ()
#ifdef MULTIBYTE_CHARS
/* Change to the native locale for multibyte conversions. */
setlocale (LC_CTYPE, "");
+ literal_codeset = getenv ("LANG");
#endif
maxtoken = 40;
@@ -248,6 +256,7 @@ init_lex ()
ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
ridpointers[(int) RID_INLINE] = get_identifier ("inline");
ridpointers[(int) RID_CONST] = get_identifier ("const");
+ ridpointers[(int) RID_RESTRICT] = get_identifier ("restrict");
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
ridpointers[(int) RID_STATIC] = get_identifier ("static");
@@ -261,6 +270,7 @@ init_lex ()
ridpointers[(int) RID_OUT] = get_identifier ("out");
ridpointers[(int) RID_INOUT] = get_identifier ("inout");
ridpointers[(int) RID_BYCOPY] = get_identifier ("bycopy");
+ ridpointers[(int) RID_BYREF] = get_identifier ("byref");
ridpointers[(int) RID_ONEWAY] = get_identifier ("oneway");
forget_protocol_qualifiers();
@@ -276,6 +286,7 @@ init_lex ()
if (flag_traditional)
{
UNSET_RESERVED_WORD ("const");
+ UNSET_RESERVED_WORD ("restrict");
UNSET_RESERVED_WORD ("volatile");
UNSET_RESERVED_WORD ("typeof");
UNSET_RESERVED_WORD ("signed");
@@ -283,6 +294,9 @@ init_lex ()
UNSET_RESERVED_WORD ("iterator");
UNSET_RESERVED_WORD ("complex");
}
+ else if (!flag_isoc9x)
+ UNSET_RESERVED_WORD ("restrict");
+
if (flag_no_asm)
{
UNSET_RESERVED_WORD ("asm");
@@ -470,7 +484,7 @@ skip_white_space_on_line ()
static char *
extend_token_buffer (p)
- char *p;
+ const char *p;
{
int offset = p - token_buffer;
@@ -480,6 +494,22 @@ extend_token_buffer (p)
return token_buffer + offset;
}
+#if defined HANDLE_PRAGMA
+/* Local versions of these macros, that can be passed as function pointers. */
+static int
+pragma_getc ()
+{
+ return GETC();
+}
+
+static void
+pragma_ungetc (arg)
+ int arg;
+{
+ UNGETC (arg);
+}
+#endif
+
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
@@ -531,34 +561,46 @@ check_newline ()
c = GETC ();
if (c == '\n')
return c;
-#ifdef HANDLE_SYSV_PRAGMA
+
+#if defined HANDLE_PRAGMA || defined HANDLE_GENERIC_PRAGMAS
UNGETC (c);
token = yylex ();
if (token != IDENTIFIER)
goto skipline;
- return handle_sysv_pragma (token);
-#else /* !HANDLE_SYSV_PRAGMA */
+#endif /* HANDLE_PRAGMA || HANDLE_GENERIC_PRAGMAS */
+
#ifdef HANDLE_PRAGMA
+ /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS (if
+ both are defined), in order to give the back end a chance to
+ override the interpretation of generic style pragmas. */
#if !USE_CPPLIB
- UNGETC (c);
- token = yylex ();
- if (token != IDENTIFIER)
- goto skipline;
if (nextchar >= 0)
- c = nextchar, nextchar = -1;
- else
- c = GETC ();
- ungetc (c, finput);
- if (HANDLE_PRAGMA (finput, yylval.ttype))
{
- c = GETC ();
- return c;
+ c = nextchar, nextchar = -1;
+ UNGETC (c);
}
-#else
- ??? do not know what to do ???;
#endif /* !USE_CPPLIB */
+
+ if (TREE_CODE (yylval.ttype) != IDENTIFIER_NODE)
+ goto skipline;
+
+ if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc,
+ IDENTIFIER_POINTER (yylval.ttype)))
+ return GETC ();
#endif /* HANDLE_PRAGMA */
-#endif /* !HANDLE_SYSV_PRAGMA */
+
+#ifdef HANDLE_GENERIC_PRAGMAS
+ if (handle_generic_pragma (token))
+ return GETC ();
+#endif /* HANDLE_GENERIC_PRAGMAS */
+
+ /* Issue a warning message if we have been asked to do so.
+ Ignoring unknown pragmas in system header file unless
+ an explcit -Wunknown-pragmas has been given. */
+ if (warn_unknown_pragmas > 1
+ || (warn_unknown_pragmas && ! in_system_header))
+ warning ("ignoring pragma: %s", token_buffer);
+
goto skipline;
}
}
@@ -748,7 +790,7 @@ linenum:
struct file_stack *p = input_file_stack;
if (indent_level != p->indent_level)
{
- warning_with_file_and_line
+ warning_with_file_and_line
(p->name, old_lineno,
"This file contains more `%c's than `%c's.",
indent_level > p->indent_level ? '{' : '}',
@@ -817,17 +859,17 @@ linenum:
return c;
}
-#ifdef HANDLE_SYSV_PRAGMA
+#ifdef HANDLE_GENERIC_PRAGMAS
/* Handle a #pragma directive.
TOKEN is the token we read after `#pragma'. Processes the entire input
- line and returns a character for the caller to reread: either \n or EOF. */
+ line and return non-zero iff the pragma has been successfully parsed. */
/* This function has to be in this file, in order to get at
the token types. */
static int
-handle_sysv_pragma (token)
+handle_generic_pragma (token)
register int token;
{
register int c;
@@ -843,7 +885,7 @@ handle_sysv_pragma (token)
handle_pragma_token (token_buffer, yylval.ttype);
break;
default:
- handle_pragma_token (token_buffer, 0);
+ handle_pragma_token (token_buffer, NULL);
}
#if !USE_CPPLIB
if (nextchar >= 0)
@@ -854,17 +896,16 @@ handle_sysv_pragma (token)
while (c == ' ' || c == '\t')
c = GETC ();
- if (c == '\n' || c == EOF)
- {
- handle_pragma_token (0, 0);
- return c;
- }
UNGETC (c);
+
+ if (c == '\n' || c == EOF)
+ return handle_pragma_token (NULL, NULL);
+
token = yylex ();
}
}
-#endif /* HANDLE_SYSV_PRAGMA */
+#endif /* HANDLE_GENERIC_PRAGMAS */
#define ENDFILE -1 /* token that represents end-of-file */
@@ -925,7 +966,7 @@ readescape (ignore_ptr)
;
else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
|| (count > 1
- && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
+ && (((unsigned)1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
<= firstdig)))
pedwarn ("hex escape out of range");
return code;
@@ -1007,30 +1048,25 @@ readescape (ignore_ptr)
}
void
-yyerror (string)
- char *string;
+yyerror (msgid)
+ const char *msgid;
{
- char buf[200];
-
- strcpy (buf, string);
+ const char *string = _(msgid);
/* We can't print string and character constants well
because the token_buffer contains the result of processing escapes. */
if (end_of_file)
- strcat (buf, " at end of input");
+ error ("%s at end of input", string);
else if (token_buffer[0] == 0)
- strcat (buf, " at null character");
+ error ("%s at null character", string);
else if (token_buffer[0] == '"')
- strcat (buf, " before string constant");
+ error ("%s before string constant", string);
else if (token_buffer[0] == '\'')
- strcat (buf, " before character constant");
+ error ("%s before character constant", string);
else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
- sprintf (buf + strlen (buf), " before character 0%o",
- (unsigned char) token_buffer[0]);
+ error ("%s before character 0%o", string, (unsigned char) token_buffer[0]);
else
- strcat (buf, " before `%s'");
-
- error (buf, token_buffer);
+ error ("%s before `%s'", string, token_buffer);
}
#if 0
@@ -1043,7 +1079,7 @@ struct try_type
char long_long_flag;
};
-struct try_type type_sequence[] =
+struct try_type type_sequence[] =
{
{ &integer_type_node, 0, 0, 0},
{ &unsigned_type_node, 1, 0, 0},
@@ -1054,6 +1090,120 @@ struct try_type type_sequence[] =
};
#endif /* 0 */
+struct pf_args
+{
+ /* Input */
+ int base;
+ char * p;
+ /* I/O */
+ int c;
+ int imag;
+ tree type;
+ int conversion_errno;
+ /* Output */
+ REAL_VALUE_TYPE value;
+};
+
+static void
+parse_float (data)
+ PTR data;
+{
+ struct pf_args * args = (struct pf_args *) data;
+ int fflag = 0, lflag = 0;
+ /* Copy token_buffer now, while it has just the number
+ and not the suffixes; once we add `f' or `i',
+ REAL_VALUE_ATOF may not work any more. */
+ char *copy = (char *) alloca (args->p - token_buffer + 1);
+ bcopy (token_buffer, copy, args->p - token_buffer + 1);
+
+ while (1)
+ {
+ int lose = 0;
+
+ /* Read the suffixes to choose a data type. */
+ switch (args->c)
+ {
+ case 'f': case 'F':
+ if (fflag)
+ error ("more than one `f' in numeric constant");
+ fflag = 1;
+ break;
+
+ case 'l': case 'L':
+ if (lflag)
+ error ("more than one `l' in numeric constant");
+ lflag = 1;
+ break;
+
+ case 'i': case 'I':
+ if (args->imag)
+ error ("more than one `i' or `j' in numeric constant");
+ else if (pedantic)
+ pedwarn ("ANSI C forbids imaginary numeric constants");
+ args->imag = 1;
+ break;
+
+ default:
+ lose = 1;
+ }
+
+ if (lose)
+ break;
+
+ if (args->p >= token_buffer + maxtoken - 3)
+ args->p = extend_token_buffer (args->p);
+ *(args->p++) = args->c;
+ *(args->p) = 0;
+ args->c = GETC();
+ }
+
+ /* The second argument, machine_mode, of REAL_VALUE_ATOF
+ tells the desired precision of the binary result
+ of decimal-to-binary conversion. */
+
+ if (fflag)
+ {
+ if (lflag)
+ error ("both `f' and `l' in floating constant");
+
+ args->type = float_type_node;
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
+ /* A diagnostic is required here by some ANSI C testsuites.
+ This is not pedwarn, because some people don't want
+ an error for this. */
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `float'");
+ }
+ else if (lflag)
+ {
+ args->type = long_double_type_node;
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `long double'");
+ }
+ else
+ {
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `double'");
+ }
+}
+
int
yylex ()
{
@@ -1164,8 +1314,6 @@ yylex ()
while (ISALNUM (c) || c == '_' || c == '$' || c == '@')
{
/* Make sure this char really belongs in an identifier. */
- if (c == '@' && ! doing_objc_thang)
- break;
if (c == '$')
{
if (! dollars_in_ident)
@@ -1245,7 +1393,7 @@ yylex ()
&& TREE_CODE (DECL_INITIAL (lastiddecl)) == STRING_CST)
{
tree stringval = DECL_INITIAL (lastiddecl);
-
+
/* Copy the string value so that we won't clobber anything
if we put something in the TREE_CHAIN of this one. */
yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
@@ -1300,8 +1448,8 @@ yylex ()
int parts[TOTAL_PARTS];
int overflow = 0;
- enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
- = NOT_FLOAT;
+ enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON}
+ floatflag = NOT_FLOAT;
for (count = 0; count < TOTAL_PARTS; count++)
parts[count] = 0;
@@ -1337,12 +1485,12 @@ yylex ()
{
if (c == '.')
{
- if (base == 16)
+ if (base == 16 && pedantic)
error ("floating constant may not be in radix 16");
if (floatflag == TOO_MANY_POINTS)
/* We have already emitted an error. Don't need another. */
;
- else if (floatflag == AFTER_POINT)
+ else if (floatflag == AFTER_POINT || floatflag == AFTER_EXPON)
{
error ("malformed floating constant");
floatflag = TOO_MANY_POINTS;
@@ -1353,7 +1501,8 @@ yylex ()
else
floatflag = AFTER_POINT;
- base = 10;
+ if (base == 8)
+ base = 10;
*p++ = c = GETC();
/* Accept '.' as the start of a floating-point number
only when it is followed by a digit.
@@ -1392,12 +1541,17 @@ yylex ()
if (c == 'e' || c == 'E')
{
base = 10;
- floatflag = AFTER_POINT;
+ floatflag = AFTER_EXPON;
break; /* start of exponent */
}
error ("nondigits in number and not hexadecimal");
c = 0;
}
+ else if (base == 16 && (c == 'p' || c == 'P'))
+ {
+ floatflag = AFTER_EXPON;
+ break; /* start of exponent */
+ }
else if (c >= 'a')
{
c = c - 'a' + 10;
@@ -1450,11 +1604,12 @@ yylex ()
int imag = 0;
int conversion_errno = 0;
REAL_VALUE_TYPE value;
- jmp_buf handler;
+ struct pf_args args;
/* Read explicit exponent if any, and put it in tokenbuf. */
- if ((c == 'e') || (c == 'E'))
+ if ((base == 10 && ((c == 'e') || (c == 'E')))
+ || (base == 16 && (c == 'p' || c == 'P')))
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
@@ -1465,9 +1620,10 @@ yylex ()
*p++ = c;
c = GETC();
}
+ /* Exponent is decimal, even if string is a hex float. */
if (! ISDIGIT (c))
error ("floating constant exponent has no digits");
- while (ISDIGIT (c))
+ while (ISDIGIT (c))
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
@@ -1475,106 +1631,38 @@ yylex ()
c = GETC();
}
}
+ if (base == 16 && floatflag != AFTER_EXPON)
+ error ("hexadecimal floating constant has no exponent");
*p = 0;
+ /* Setup input for parse_float() */
+ args.base = base;
+ args.p = p;
+ args.c = c;
+ args.imag = imag;
+ args.type = type;
+ args.conversion_errno = conversion_errno;
+
/* Convert string to a double, checking for overflow. */
- if (setjmp (handler))
+ if (do_float_handler (parse_float, (PTR) &args))
{
- error ("floating constant out of range");
- value = dconst0;
+ /* Receive output from parse_float() */
+ value = args.value;
}
else
{
- int fflag = 0, lflag = 0;
- /* Copy token_buffer now, while it has just the number
- and not the suffixes; once we add `f' or `i',
- REAL_VALUE_ATOF may not work any more. */
- char *copy = (char *) alloca (p - token_buffer + 1);
- bcopy (token_buffer, copy, p - token_buffer + 1);
-
- set_float_handler (handler);
-
- while (1)
- {
- int lose = 0;
-
- /* Read the suffixes to choose a data type. */
- switch (c)
- {
- case 'f': case 'F':
- if (fflag)
- error ("more than one `f' in numeric constant");
- fflag = 1;
- break;
-
- case 'l': case 'L':
- if (lflag)
- error ("more than one `l' in numeric constant");
- lflag = 1;
- break;
-
- case 'i': case 'I':
- if (imag)
- error ("more than one `i' or `j' in numeric constant");
- else if (pedantic)
- pedwarn ("ANSI C forbids imaginary numeric constants");
- imag = 1;
- break;
-
- default:
- lose = 1;
- }
-
- if (lose)
- break;
-
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- *p = 0;
- c = GETC();
- }
-
- /* The second argument, machine_mode, of REAL_VALUE_ATOF
- tells the desired precision of the binary result
- of decimal-to-binary conversion. */
-
- if (fflag)
- {
- if (lflag)
- error ("both `f' and `l' in floating constant");
-
- type = float_type_node;
- errno = 0;
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- conversion_errno = errno;
- /* A diagnostic is required here by some ANSI C testsuites.
- This is not pedwarn, become some people don't want
- an error for this. */
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `float'");
- }
- else if (lflag)
- {
- type = long_double_type_node;
- errno = 0;
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- conversion_errno = errno;
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `long double'");
- }
- else
- {
- errno = 0;
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- conversion_errno = errno;
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `double'");
- }
+ /* We got an exception from parse_float() */
+ error ("floating constant out of range");
+ value = dconst0;
+ }
- set_float_handler (NULL_PTR);
- }
+ /* Receive output from parse_float() */
+ c = args.c;
+ imag = args.imag;
+ type = args.type;
+ conversion_errno = args.conversion_errno;
+
#ifdef ERANGE
/* ERANGE is also reported for underflow,
so test the value to distinguish overflow from that. */
@@ -1606,7 +1694,7 @@ yylex ()
int spec_long = 0;
int spec_long_long = 0;
int spec_imag = 0;
- int bytes, warn, i;
+ int warn, i;
traditional_type = ansi_type = type = NULL_TREE;
while (1)
@@ -1623,7 +1711,7 @@ yylex ()
{
if (spec_long_long)
error ("three `l's in integer constant");
- else if (pedantic)
+ else if (pedantic && ! in_system_header && warn_long_long)
pedwarn ("ANSI C forbids long long integer constants");
spec_long_long = 1;
}
@@ -1645,20 +1733,10 @@ yylex ()
c = GETC();
}
- /* If the constant won't fit in an unsigned long long,
- then warn that the constant is out of range. */
-
- /* ??? This assumes that long long and long integer types are
- a multiple of 8 bits. This better than the original code
- though which assumed that long was exactly 32 bits and long
- long was exactly 64 bits. */
-
- bytes = TYPE_PRECISION (long_long_integer_type_node) / 8;
+ /* If it won't fit in the host's representation for integers,
+ then pedwarn. */
warn = overflow;
- for (i = bytes; i < TOTAL_PARTS; i++)
- if (parts[i])
- warn = 1;
if (warn)
pedwarn ("integer constant out of range");
@@ -1674,7 +1752,7 @@ yylex ()
<< (i * HOST_BITS_PER_CHAR));
low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
}
-
+
yylval.ttype = build_int_2 (low, high);
TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
@@ -1749,7 +1827,10 @@ yylex ()
if (pedantic && !flag_traditional && !spec_long_long && !warn
&& (TYPE_PRECISION (long_integer_type_node)
< TYPE_PRECISION (type)))
- pedwarn ("integer constant out of range");
+ {
+ warn = 1;
+ pedwarn ("integer constant out of range");
+ }
if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
warning ("decimal constant is so large that it is unsigned");
@@ -1777,6 +1858,15 @@ yylex ()
}
else
TREE_TYPE (yylval.ttype) = type;
+
+
+ /* If it's still an integer (not a complex), and it doesn't
+ fit in the type we choose for it, then pedwarn. */
+
+ if (! warn
+ && TREE_CODE (TREE_TYPE (yylval.ttype)) == INTEGER_TYPE
+ && ! int_fits_type_p (yylval.ttype, TREE_TYPE (yylval.ttype)))
+ pedwarn ("integer constant out of range");
}
UNGETC (c);
@@ -1795,30 +1885,27 @@ yylex ()
{
register int result = 0;
register int num_chars = 0;
+ int chars_seen = 0;
unsigned width = TYPE_PRECISION (char_type_node);
int max_chars;
-
- if (wide_flag)
- {
- width = WCHAR_TYPE_SIZE;
#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif
- }
- else
- max_chars = TYPE_PRECISION (integer_type_node) / width;
+
+ max_chars = TYPE_PRECISION (integer_type_node) / width;
+ if (wide_flag)
+ width = WCHAR_TYPE_SIZE;
while (1)
{
tryagain:
-
c = GETC();
if (c == '\'' || c == EOF)
break;
+ ++chars_seen;
if (c == '\\')
{
int ignore = 0;
@@ -1826,7 +1913,7 @@ yylex ()
if (ignore)
goto tryagain;
if (width < HOST_BITS_PER_INT
- && (unsigned) c >= (1 << width))
+ && (unsigned) c >= ((unsigned)1 << width))
pedwarn ("escape sequence out of range for character");
#ifdef MAP_CHARACTER
if (ISPRINT (c))
@@ -1839,18 +1926,76 @@ yylex ()
pedwarn ("ANSI C forbids newline in character constant");
lineno++;
}
-#ifdef MAP_CHARACTER
else
- c = MAP_CHARACTER (c);
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 1; i <= longest_char; ++i)
+ {
+ if (i > maxtoken - 4)
+ extend_token_buffer (token_buffer);
+
+ token_buffer[i] = c;
+ char_len = local_mbtowc (& wc,
+ token_buffer + 1,
+ i);
+ if (char_len != -1)
+ break;
+ c = GETC ();
+ }
+ if (char_len > 1)
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len < i)
+ UNGETC (c);
+ if (! wide_flag)
+ {
+ /* Merge character into result; ignore excess chars. */
+ for (i = 1; i <= char_len; ++i)
+ {
+ if (i > max_chars)
+ break;
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width)
+ | (token_buffer[i]
+ & ((1 << width) - 1));
+ else
+ result = token_buffer[i];
+ }
+ num_chars += char_len;
+ goto tryagain;
+ }
+ c = wc;
+ }
+ else
+ {
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ if (wide_flag)
+ c = wc;
+#ifdef MAP_CHARACTER
+ else
+ c = MAP_CHARACTER (c);
#endif
+ }
+#else /* ! MULTIBYTE_CHARS */
+#ifdef MAP_CHARACTER
+ c = MAP_CHARACTER (c);
+#endif
+#endif /* ! MULTIBYTE_CHARS */
+ }
- num_chars++;
- if (num_chars > maxtoken - 4)
- extend_token_buffer (token_buffer);
-
- token_buffer[num_chars] = c;
+ if (wide_flag)
+ {
+ if (chars_seen == 1) /* only keep the first one */
+ result = c;
+ goto tryagain;
+ }
/* Merge character into result; ignore excess chars. */
+ num_chars += (width / TYPE_PRECISION (char_type_node));
if (num_chars < max_chars + 1)
{
if (width < HOST_BITS_PER_INT)
@@ -1860,19 +2005,16 @@ yylex ()
}
}
- token_buffer[num_chars + 1] = '\'';
- token_buffer[num_chars + 2] = 0;
-
if (c != '\'')
error ("malformatted character constant");
- else if (num_chars == 0)
+ else if (chars_seen == 0)
error ("empty character constant");
else if (num_chars > max_chars)
{
num_chars = max_chars;
error ("character constant too long");
}
- else if (num_chars != 1 && ! flag_traditional && warn_multichar)
+ else if (chars_seen != 1 && ! flag_traditional && warn_multichar)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
@@ -1897,22 +2039,6 @@ yylex ()
}
else
{
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[1] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL_PTR, NULL_PTR, 0);
- if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
- result = wc;
- else
- warning ("Ignoring invalid multibyte character");
- }
-#endif
yylval.ttype = build_int_2 (result, 0);
TREE_TYPE (yylval.ttype) = wchar_type_node;
}
@@ -1924,7 +2050,13 @@ yylex ()
case '"':
string_constant:
{
- c = GETC();
+ unsigned width = wide_flag ? WCHAR_TYPE_SIZE
+ : TYPE_PRECISION (char_type_node);
+#ifdef MULTIBYTE_CHARS
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
+#endif
+ c = GETC ();
p = token_buffer + 1;
while (c != '"' && c >= 0)
@@ -1935,9 +2067,8 @@ yylex ()
c = readescape (&ignore);
if (ignore)
goto skipnewline;
- if (!wide_flag
- && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
- && c >= (1 << TYPE_PRECISION (char_type_node)))
+ if (width < HOST_BITS_PER_INT
+ && (unsigned) c >= ((unsigned)1 << width))
pedwarn ("escape sequence out of range for character");
}
else if (c == '\n')
@@ -1946,15 +2077,92 @@ yylex ()
pedwarn ("ANSI C forbids newline in string constant");
lineno++;
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 0; i < longest_char; ++i)
+ {
+ if (p + i >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ p[i] = c;
- if (p == token_buffer + maxtoken)
- p = extend_token_buffer (p);
- *p++ = c;
+ char_len = local_mbtowc (& wc, p, i + 1);
+ if (char_len != -1)
+ break;
+ c = GETC ();
+ }
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ else
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len <= i)
+ UNGETC (c);
+ if (! wide_flag)
+ {
+ p += (i + 1);
+ c = GETC ();
+ continue;
+ }
+ c = wc;
+ }
+#endif /* MULTIBYTE_CHARS */
+ }
+
+ /* Add this single character into the buffer either as a wchar_t
+ or as a single byte. */
+ if (wide_flag)
+ {
+ unsigned width = TYPE_PRECISION (char_type_node);
+ unsigned bytemask = (1 << width) - 1;
+ int byte;
+
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+
+ for (byte = 0; byte < WCHAR_BYTES; ++byte)
+ {
+ int value;
+ if (byte >= (int) sizeof (c))
+ value = 0;
+ else
+ value = (c >> (byte * width)) & bytemask;
+ if (BYTES_BIG_ENDIAN)
+ p[WCHAR_BYTES - byte - 1] = value;
+ else
+ p[byte] = value;
+ }
+ p += WCHAR_BYTES;
+ }
+ else
+ {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = c;
+ }
skipnewline:
- c = GETC();
+ c = GETC ();
+ }
+
+ /* Terminate the string value, either with a single byte zero
+ or with a wide zero. */
+ if (wide_flag)
+ {
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ bzero (p, WCHAR_BYTES);
+ p += WCHAR_BYTES;
+ }
+ else
+ {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = 0;
}
- *p = 0;
if (c < 0)
error ("Unterminated string constant");
@@ -1964,52 +2172,27 @@ yylex ()
if (wide_flag)
{
- /* If this is a L"..." wide-string, convert the multibyte string
- to a wide character string. */
- char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
- int len;
-
-#ifdef MULTIBYTE_CHARS
- len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
- if (len < 0 || len >= (p - token_buffer))
- {
- warning ("Ignoring invalid multibyte string");
- len = 0;
- }
- bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
-#else
- {
- char *wp, *cp;
-
- wp = widep + (BYTES_BIG_ENDIAN ? WCHAR_BYTES - 1 : 0);
- bzero (widep, (p - token_buffer) * WCHAR_BYTES);
- for (cp = token_buffer + 1; cp < p; cp++)
- *wp = *cp, wp += WCHAR_BYTES;
- len = p - token_buffer - 1;
- }
-#endif
- yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
+ yylval.ttype = build_string (p - (token_buffer + 1),
+ token_buffer + 1);
TREE_TYPE (yylval.ttype) = wchar_array_type_node;
value = STRING;
}
else if (objc_flag)
{
/* Return an Objective-C @"..." constant string object. */
- yylval.ttype = build_objc_string (p - token_buffer,
+ yylval.ttype = build_objc_string (p - (token_buffer + 1),
token_buffer + 1);
TREE_TYPE (yylval.ttype) = char_array_type_node;
value = OBJC_STRING;
}
else
{
- yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
+ yylval.ttype = build_string (p - (token_buffer + 1),
+ token_buffer + 1);
TREE_TYPE (yylval.ttype) = char_array_type_node;
value = STRING;
}
- *p++ = '"';
- *p = 0;
-
break;
}
diff --git a/contrib/gcc/c-lex.h b/contrib/gcc/c-lex.h
index bd0b9d4..7d73ab5 100644
--- a/contrib/gcc/c-lex.h
+++ b/contrib/gcc/c-lex.h
@@ -1,5 +1,5 @@
/* Define constants for communication with c-parse.y.
- Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1992, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -40,6 +40,7 @@ enum rid
RID_TYPEDEF,
RID_SIGNED,
RID_CONST,
+ RID_RESTRICT,
RID_VOLATILE,
RID_INLINE,
RID_NOALIAS,
@@ -50,6 +51,7 @@ enum rid
RID_OUT,
RID_INOUT,
RID_BYCOPY,
+ RID_BYREF,
RID_ONEWAY,
RID_ID,
@@ -79,7 +81,7 @@ extern void position_after_white_space PROTO((void));
extern int check_newline PROTO((void));
extern int yylex PROTO((void));
-extern void yyerror PROTO((char *));
+extern void yyerror PROTO((const char *));
extern void forget_protocol_qualifiers PROTO((void));
extern void remember_protocol_qualifiers PROTO((void));
diff --git a/contrib/gcc/c-parse.gperf b/contrib/gcc/c-parse.gperf
index 90cab6a..888eee9 100644
--- a/contrib/gcc/c-parse.gperf
+++ b/contrib/gcc/c-parse.gperf
@@ -1,7 +1,7 @@
%{
-/* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
+/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
%}
-struct resword { char *name; short token; enum rid rid; };
+struct resword { const char *name; short token; enum rid rid; };
%%
@class, CLASS, NORID
@compatibility_alias, ALIAS, NORID
@@ -35,6 +35,8 @@ __iterator__, SCSPEC, RID_ITERATOR
__label__, LABEL, NORID
__real, REALPART, NORID
__real__, REALPART, NORID
+__restrict, TYPE_QUAL, RID_RESTRICT
+__restrict__, TYPE_QUAL, RID_RESTRICT
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
__typeof, TYPEOF, NORID
@@ -45,6 +47,7 @@ asm, ASM_KEYWORD, NORID
auto, SCSPEC, RID_AUTO
break, BREAK, NORID
bycopy, TYPE_QUAL, RID_BYCOPY
+byref, TYPE_QUAL, RID_BYREF
case, CASE, NORID
char, TYPESPEC, RID_CHAR
const, TYPE_QUAL, RID_CONST
@@ -68,6 +71,7 @@ long, TYPESPEC, RID_LONG
oneway, TYPE_QUAL, RID_ONEWAY
out, TYPE_QUAL, RID_OUT
register, SCSPEC, RID_REGISTER
+restrict, TYPE_QUAL, RID_RESTRICT
return, RETURN, NORID
short, TYPESPEC, RID_SHORT
signed, TYPESPEC, RID_SIGNED
diff --git a/contrib/gcc/c-parse.in b/contrib/gcc/c-parse.in
index 16500c5..6757c4d 100644
--- a/contrib/gcc/c-parse.in
+++ b/contrib/gcc/c-parse.in
@@ -1,5 +1,5 @@
/* YACC parser for C syntax and for Objective C. -*-c-*-
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,7 +31,7 @@ ifobjc
%expect 66
end ifobjc
ifc
-%expect 46
+%expect 51
/* These are the 23 conflicts you should get in parse.output;
the state numbers may vary if minor changes in the grammar are made.
@@ -116,7 +116,7 @@ end ifc
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPESPEC
-/* Reserved words that qualify type: "const" or "volatile".
+/* Reserved words that qualify type: "const", "volatile", or "restrict".
yylval contains an IDENTIFIER_NODE which indicates which one. */
%token TYPE_QUAL
@@ -525,7 +525,7 @@ cast_expr:
tree type = $2;
finish_init ();
- if (pedantic)
+ if (pedantic && ! flag_isoc9x)
pedwarn ("ANSI C forbids constructor expressions");
if (TYPE_NAME (type) != 0)
{
@@ -604,12 +604,22 @@ expr_no_commas:
{ skip_evaluation -= $1 == boolean_true_node;
$$ = build_conditional_expr ($1, $<ttype>2, $5); }
| expr_no_commas '=' expr_no_commas
- { $$ = build_modify_expr ($1, NOP_EXPR, $3);
- C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
+ { char class;
+ $$ = build_modify_expr ($1, NOP_EXPR, $3);
+ class = TREE_CODE_CLASS (TREE_CODE ($$));
+ if (class == 'e' || class == '1'
+ || class == '2' || class == '<')
+ C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
+ }
| expr_no_commas ASSIGN expr_no_commas
- { $$ = build_modify_expr ($1, $2, $3);
+ { char class;
+ $$ = build_modify_expr ($1, $2, $3);
/* This inhibits warnings in truthvalue_conversion. */
- C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
+ class = TREE_CODE_CLASS (TREE_CODE ($$));
+ if (class == 'e' || class == '1'
+ || class == '2' || class == '<')
+ C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
+ }
;
primary:
@@ -1275,33 +1285,41 @@ initlist1:
/* `initelt' is a single element of an initializer.
It may use braces. */
initelt:
- expr_no_commas
- { process_init_element ($1); }
- | '{'
+ designator_list '=' initval
+ | designator initval
+ | identifier ':'
+ { set_init_label ($1); }
+ initval
+ | initval
+ ;
+
+initval:
+ '{'
{ push_init_level (0); }
initlist_maybe_comma '}'
{ process_init_element (pop_init_level (0)); }
+ | expr_no_commas
+ { process_init_element ($1); }
| error
+ ;
+
+designator_list:
+ designator
+ | designator_list designator
+ ;
+
+designator:
+ '.' identifier
+ { set_init_label ($2); }
/* These are for labeled elements. The syntax for an array element
initializer conflicts with the syntax for an Objective-C message,
so don't include these productions in the Objective-C grammar. */
ifc
- | '[' expr_no_commas ELLIPSIS expr_no_commas ']' '='
+ | '[' expr_no_commas ELLIPSIS expr_no_commas ']'
{ set_init_index ($2, $4); }
- initelt
- | '[' expr_no_commas ']' '='
- { set_init_index ($2, NULL_TREE); }
- initelt
| '[' expr_no_commas ']'
{ set_init_index ($2, NULL_TREE); }
- initelt
end ifc
- | identifier ':'
- { set_init_label ($1); }
- initelt
- | '.' identifier '='
- { set_init_label ($2); }
- initelt
;
nested_function:
@@ -1398,6 +1416,13 @@ parm_declarator:
/* | parm_declarator '(' error ')' %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
poplevel (0, 0, 0); } */
+ifc
+ | parm_declarator '[' '*' ']' %prec '.'
+ { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+ if (! flag_isoc9x)
+ error ("`[*]' in parameter declaration only allowed in ISO C 9x");
+ }
+end ifc
| parm_declarator '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| parm_declarator '[' ']' %prec '.'
@@ -1427,6 +1452,13 @@ notype_declarator:
{ $$ = $2; }
| '*' type_quals notype_declarator %prec UNARY
{ $$ = make_pointer_declarator ($2, $3); }
+ifc
+ | notype_declarator '[' '*' ']' %prec '.'
+ { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+ if (! flag_isoc9x)
+ error ("`[*]' in parameter declaration only allowed in ISO C 9x");
+ }
+end ifc
| notype_declarator '[' expr ']' %prec '.'
{ $$ = build_nt (ARRAY_REF, $1, $3); }
| notype_declarator '[' ']' %prec '.'
@@ -1509,7 +1541,8 @@ maybecomma:
maybecomma_warn:
/* empty */
| ','
- { if (pedantic) pedwarn ("comma at end of enumerator list"); }
+ { if (pedantic && ! flag_isoc9x)
+ pedwarn ("comma at end of enumerator list"); }
;
component_decl_list:
@@ -1676,6 +1709,8 @@ absdcl1: /* a nonempty absolute declarator */
{ $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
/* ??? It appears we have to support attributes here, however
using prefix_attributes is wrong. */
+ | attributes setattrs absdcl1
+ { $$ = $3; }
;
/* at least one statement, the first of which parses without error. */
@@ -2191,12 +2226,15 @@ label: CASE expr_no_commas ':'
error_with_decl (duplicate, "this is the first default label");
}
position_after_white_space (); }
- | identifier ':'
+ | identifier ':' maybe_attribute
{ tree label = define_label (input_filename, lineno, $1);
stmt_count++;
emit_nop ();
if (label)
- expand_label (label);
+ {
+ expand_label (label);
+ decl_attributes (label, $3, NULL_TREE);
+ }
position_after_white_space (); }
;
diff --git a/contrib/gcc/c-pragma.c b/contrib/gcc/c-pragma.c
index 3d01925..5aa8d9f 100644
--- a/contrib/gcc/c-pragma.c
+++ b/contrib/gcc/c-pragma.c
@@ -1,5 +1,5 @@
/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
- Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -29,147 +29,464 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "toplev.h"
-#ifdef HANDLE_SYSV_PRAGMA
+#ifdef HANDLE_GENERIC_PRAGMAS
+#ifdef HANDLE_PRAGMA_PACK
/* When structure field packing is in effect, this variable is the
number of bits to use as the maximum alignment. When packing is not
in effect, this is zero. */
extern int maximum_field_alignment;
+#endif
-/* File used for outputting assembler code. */
-extern FILE *asm_out_file;
-/* Handle one token of a pragma directive. TOKEN is the
- current token, and STRING is its printable form. */
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
+typedef struct align_stack
+{
+ int alignment;
+ unsigned int num_pushes;
+ tree id;
+ struct align_stack * prev;
+} align_stack;
+
+static struct align_stack * alignment_stack = NULL;
+
+static int push_alignment PROTO((int, tree));
+static int pop_alignment PROTO((tree));
+
+/* Push an alignment value onto the stack. */
+static int
+push_alignment (alignment, id)
+ int alignment;
+ tree id;
+{
+ switch (alignment)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ break;
+ default:
+ warning ("\
+Alignment must be a small power of two, not %d, in #pragma pack",
+ alignment);
+ return 0;
+ }
+
+ if (alignment_stack == NULL
+ || alignment_stack->alignment != alignment
+ || id != NULL_TREE)
+ {
+ align_stack * entry;
+
+ entry = (align_stack *) xmalloc (sizeof (* entry));
+
+ if (entry == NULL)
+ {
+ warning ("Out of memory pushing #pragma pack");
+ return 0;
+ }
+ entry->alignment = alignment;
+ entry->num_pushes = 1;
+ entry->id = id;
+ entry->prev = alignment_stack;
+
+ alignment_stack = entry;
+
+ maximum_field_alignment = alignment * 8;
+ }
+ else
+ alignment_stack->num_pushes ++;
+
+ return 1;
+}
+
+/* Undo a push of an alignment onto the stack. */
+static int
+pop_alignment (id)
+ tree id;
+{
+ align_stack * entry;
+
+ if (alignment_stack == NULL)
+ {
+ warning ("\
+#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
+ );
+ return 0;
+ }
+
+ /* If we got an identifier, strip away everything above the target
+ entry so that the next step will restore the state just below it. */
+ if (id)
+ {
+ for (entry = alignment_stack; entry; entry = entry->prev)
+ if (entry->id == id)
+ {
+ entry->num_pushes = 1;
+ alignment_stack = entry;
+ break;
+ }
+ if (entry == NULL)
+ warning ("\
+#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
+ , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
+ }
+
+ if (-- alignment_stack->num_pushes == 0)
+ {
+ entry = alignment_stack->prev;
+
+ if (entry == NULL)
+ maximum_field_alignment = 0;
+ else
+ maximum_field_alignment = entry->alignment * 8;
+
+ free (alignment_stack);
+
+ alignment_stack = entry;
+ }
+
+ return 1;
+}
+
+/* Generate 'packed' and 'aligned' attributes for decls whilst a
+ #pragma pack(push... is in effect. */
void
+insert_pack_attributes (node, attributes, prefix)
+ tree node;
+ tree * attributes;
+ tree * prefix;
+{
+ tree a;
+ int field_alignment;
+
+ /* If we are not packing, then there is nothing to do. */
+ if (maximum_field_alignment == 0
+ || alignment_stack == NULL)
+ return;
+
+ /* We are only interested in fields. */
+ if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
+ || TREE_CODE (node) != FIELD_DECL)
+ return;
+
+ field_alignment = TYPE_ALIGN (TREE_TYPE (node));
+ if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
+ field_alignment = maximum_field_alignment;
+
+ /* Add a 'packed' attribute. */
+ * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
+
+ /* If the alignment is > 8 then add an alignment attribute as well. */
+ if (field_alignment > 8)
+ {
+ /* If the aligned attribute is already present then do not override it. */
+ for (a = * attributes; a; a = TREE_CHAIN (a))
+ {
+ tree name = TREE_PURPOSE (a);
+ if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
+ break;
+ }
+
+ if (a == NULL)
+ for (a = * prefix; a; a = TREE_CHAIN (a))
+ {
+ tree name = TREE_PURPOSE (a);
+ if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
+ break;
+ }
+
+ if (a == NULL)
+ {
+ * attributes = tree_cons
+ (get_identifier ("aligned"),
+ tree_cons (NULL,
+ build_int_2 (field_alignment / 8, 0),
+ NULL),
+ * attributes);
+ }
+ }
+
+ return;
+}
+#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
+
+/* Handle one token of a pragma directive. TOKEN is the current token, and
+ STRING is its printable form. Some front ends do not support generating
+ tokens, and will only pass in a STRING. Also some front ends will reuse
+ the buffer containing STRING, so it must be copied to a local buffer if
+ it needs to be preserved.
+
+ If STRING is non-NULL, then the return value will be ignored, and there
+ will be futher calls to handle_pragma_token() in order to handle the rest of
+ the line containing the #pragma directive. If STRING is NULL, the entire
+ line has now been presented to handle_pragma_token() and the return value
+ should be zero if the pragma flawed in some way, or if the pragma was not
+ recognised, and non-zero if it was successfully handled. */
+
+int
handle_pragma_token (string, token)
- char *string;
+ const char * string;
tree token;
{
- static enum pragma_state state = ps_start, type;
- static char *name;
- static char *value;
+ static enum pragma_state state = ps_start;
+ static enum pragma_state type;
+ static char * name;
+ static char * value;
static int align;
+ static tree id;
- if (string == 0)
+ /* If we have reached the end of the #pragma directive then
+ determine what value we should return. */
+
+ if (string == NULL)
{
- if (type == ps_pack)
+ int ret_val = 0;
+
+ switch (type)
{
+ default:
+ abort ();
+ break;
+
+ case ps_done:
+ /* The pragma was not recognised. */
+ break;
+
+#ifdef HANDLE_PRAGMA_PACK
+ case ps_pack:
if (state == ps_right)
- maximum_field_alignment = align * 8;
+ {
+ maximum_field_alignment = align * 8;
+ ret_val = 1;
+ }
else
warning ("malformed `#pragma pack'");
- }
- else if (type == ps_weak)
- {
+ break;
+#endif /* HANDLE_PRAGMA_PACK */
+
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
+ case ps_push:
+ if (state == ps_right)
+ ret_val = push_alignment (align, id);
+ else
+ warning ("malformed '#pragma pack(push[,id],<n>)'");
+ break;
+
+ case ps_pop:
+ if (state == ps_right)
+ ret_val = pop_alignment (id);
+ else
+ warning ("malformed '#pragma pack(pop[,id])'");
+ break;
+#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
+
#ifdef HANDLE_PRAGMA_WEAK
+ case ps_weak:
if (HANDLE_PRAGMA_WEAK)
- handle_pragma_weak (state, name, value);
-
+ {
+ if (state == ps_name)
+ ret_val = add_weak (name, NULL);
+ else if (state == ps_value)
+ ret_val = add_weak (name, value);
+ else
+ warning ("malformed `#pragma weak'");
+ }
+ else
+ ret_val = 1; /* Ignore the pragma. */
+ break;
#endif /* HANDLE_PRAGMA_WEAK */
}
type = state = ps_start;
- return;
+ id = NULL_TREE;
+
+ return ret_val;
}
+ /* If we have been given a token, but it is not an identifier,
+ or a small constant, then something has gone wrong. */
+ if (token)
+ {
+ switch (TREE_CODE (token))
+ {
+ case IDENTIFIER_NODE:
+ break;
+
+ case INTEGER_CST:
+ if (TREE_INT_CST_HIGH (token) != 0)
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+
switch (state)
{
case ps_start:
- if (token && TREE_CODE (token) == IDENTIFIER_NODE)
+ type = state = ps_done;
+#ifdef HANDLE_PRAGMA_PACK
+ if (strcmp (string, "pack") == 0)
+ type = state = ps_pack;
+#endif
+#ifdef HANDLE_PRAGMA_WEAK
+ if (strcmp (string, "weak") == 0)
+ type = state = ps_weak;
+#endif
+ break;
+
+#ifdef HANDLE_PRAGMA_WEAK
+ case ps_weak:
+ name = permalloc (strlen (string) + 1);
+ if (name == NULL)
{
- if (strcmp (IDENTIFIER_POINTER (token), "pack") == 0)
- type = state = ps_pack;
- else if (strcmp (IDENTIFIER_POINTER (token), "weak") == 0)
- type = state = ps_weak;
- else
- {
- type = state = ps_done;
-
- /* Issue a warning message if we have been asked to do so.
- Ignoring unknown pragmas in system header file unless
- an explcit -Wunknown-pragmas has been given. */
- if (warn_unknown_pragmas > 1
- || (warn_unknown_pragmas && ! in_system_header))
- warning ("ignoring pragma: %s", string);
- }
+ warning ("Out of memory parsing #pragma weak");
+ state = ps_bad;
}
else
- type = state = ps_done;
- break;
-
- case ps_weak:
- if (token && TREE_CODE (token) == IDENTIFIER_NODE)
{
- name = IDENTIFIER_POINTER (token);
+ strcpy (name, string);
state = ps_name;
}
- else
- state = ps_bad;
break;
-
+
case ps_name:
state = (strcmp (string, "=") ? ps_bad : ps_equals);
break;
case ps_equals:
- if (token && TREE_CODE (token) == IDENTIFIER_NODE)
+ value = permalloc (strlen (string) + 1);
+ if (value == NULL)
{
- value = IDENTIFIER_POINTER (token);
- state = ps_value;
+ warning ("Out of memory parsing #pragma weak");
+ state = ps_bad;
}
else
- state = ps_bad;
+ {
+ strcpy (value, string);
+ state = ps_value;
+ }
break;
case ps_value:
state = ps_bad;
break;
-
+#endif /* HANDLE_PRAGMA_WEAK */
+
+#ifdef HANDLE_PRAGMA_PACK
case ps_pack:
- if (strcmp (string, "(") == 0)
- state = ps_left;
- else
- state = ps_bad;
+ state = (strcmp (string, "(") ? ps_bad : ps_left);
break;
case ps_left:
- if (token && TREE_CODE (token) == INTEGER_CST
- && TREE_INT_CST_HIGH (token) == 0)
- switch (TREE_INT_CST_LOW (token))
- {
- case 1:
- case 2:
- case 4:
- align = TREE_INT_CST_LOW (token);
- state = ps_align;
- break;
- default:
+ if (token == NULL_TREE)
+ {
+ /* #pragma pack () resets packing rules to their
+ defaults. */
+ if (strcmp (string, ")") == 0)
+ {
+ align = 0;
+ state = ps_right;
+ }
+ else
state = ps_bad;
- }
- else if (! token && strcmp (string, ")") == 0)
+ }
+ else if (TREE_CODE (token) == INTEGER_CST)
+ goto handle_align;
+
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
+ else if (TREE_CODE (token) == IDENTIFIER_NODE)
{
- align = 0;
- state = ps_right;
+ if (strcmp (string, "push") == 0)
+ type = state = ps_push;
+ else if (strcmp (string, "pop") == 0)
+ type = state = ps_pop;
+ else
+ state = ps_bad;
}
+#endif
else
state = ps_bad;
break;
+ handle_align:
+ align = TREE_INT_CST_LOW (token);
+ switch (align)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ state = ps_align;
+ break;
+
+ default:
+ state = ps_bad;
+ break;
+ }
+ break;
+
case ps_align:
- if (strcmp (string, ")") == 0)
- state = ps_right;
- else
- state = ps_bad;
+ state = (strcmp (string, ")") ? ps_bad : ps_right);
break;
case ps_right:
state = ps_bad;
break;
+#endif /* HANDLE_PRAGMA_PACK */
+
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
+ case ps_push:
+ state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
+ break;
+
+ case ps_pushid:
+ state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
+ break;
+
+ case ps_pushcomma:
+ if (token && TREE_CODE (token) == IDENTIFIER_NODE)
+ {
+ id = token;
+ state = ps_pushid;
+ break;
+ }
+
+ /* else fall through */
+ case ps_pushcomma2:
+ if (token && TREE_CODE (token) == INTEGER_CST)
+ goto handle_align;
+ else
+ state = ps_bad;
+ break;
+ case ps_pop:
+ if (strcmp (string, ",") == 0)
+ state = ps_popcomma;
+ else
+ state = (strcmp (string, ")") ? ps_bad : ps_right);
+ break;
+
+ case ps_popcomma:
+ if (token && TREE_CODE (token) == IDENTIFIER_NODE)
+ {
+ id = token;
+ state = ps_align;
+ }
+ else
+ state = ps_bad;
+ break;
+#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
+
case ps_bad:
case ps_done:
break;
@@ -177,5 +494,7 @@ handle_pragma_token (string, token)
default:
abort ();
}
+
+ return 1;
}
-#endif /* HANDLE_SYSV_PRAGMA */
+#endif /* HANDLE_GENERIC_PRAGMAS */
diff --git a/contrib/gcc/c-pragma.h b/contrib/gcc/c-pragma.h
index 49c39fa..f94ee9f 100644
--- a/contrib/gcc/c-pragma.h
+++ b/contrib/gcc/c-pragma.h
@@ -1,5 +1,5 @@
/* Pragma related interfaces.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,29 +18,84 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#ifndef _C_PRAGMA_H
+#define _C_PRAGMA_H
+
+#ifdef HANDLE_SYSV_PRAGMA
/* Support #pragma weak iff ASM_WEAKEN_LABEL and ASM_OUTPUT_DEF are
defined. */
#if defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_DEF)
#define HANDLE_PRAGMA_WEAK SUPPORTS_WEAK
#endif
+/* We always support #pragma pack for SYSV pragmas. */
+#ifndef HANDLE_PRAGMA_PACK
+#define HANDLE_PRAGMA_PACK 1
+#endif
+#endif /* HANDLE_SYSV_PRAGMA */
+
+
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
+/* If we are supporting #pragma pack(push... then we automatically
+ support #pragma pack(<n>) */
+#define HANDLE_PRAGMA_PACK 1
+#define PRAGMA_INSERT_ATTRIBUTES(node, pattr, prefix_attr) \
+ insert_pack_attributes (node, pattr, prefix_attr)
+extern void insert_pack_attributes PROTO((tree, tree *, tree *));
+#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
+
+
+#ifdef HANDLE_PRAGMA_WEAK
+/* This structure contains any weak symbol declarations waiting to be emitted. */
+struct weak_syms
+{
+ struct weak_syms * next;
+ char * name;
+ char * value;
+};
+
+/* Declared in varasm.c */
+extern struct weak_syms * weak_decls;
+
+extern int add_weak PROTO((char *, char *));
+#endif /* HANDLE_PRAGMA_WEAK */
+
+
+#if defined HANDLE_PRAGMA_PACK || defined HANDLE_PRAGMA_WEAK
+/* Define HANDLE_GENERIC_PRAGMAS if any kind of front-end pragma
+ parsing is to be done. The code in GCC's generic C source files
+ will only look for the definition of this constant. They will
+ ignore definitions of HANDLE_PRAGMA_PACK and so on. */
+#define HANDLE_GENERIC_PRAGMAS 1
+#endif
+
+
+#ifdef HANDLE_GENERIC_PRAGMAS
enum pragma_state
{
ps_start,
ps_done,
- ps_bad,
+#ifdef HANDLE_PRAGMA_WEAK
ps_weak,
ps_name,
ps_equals,
ps_value,
+#endif
+#ifdef HANDLE_PRAGMA_PACK
ps_pack,
ps_left,
ps_align,
- ps_right
+ ps_right,
+#endif
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
+ ps_push, ps_pushcomma, ps_pushid, ps_pushcomma2,
+ ps_pop, ps_popcomma,
+#endif
+ ps_bad
};
-/* Output asm to handle ``#pragma weak'' */
-extern void handle_pragma_weak PROTO((enum pragma_state, char *, char *));
-
/* Handle a C style pragma */
-extern void handle_pragma_token PROTO((char *, tree));
+extern int handle_pragma_token PROTO((const char *, tree));
+
+#endif /* HANDLE_GENERIC_PRAGMAS */
+#endif /* _C_PRAGMA_H */
diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h
index 7605cfe..bcf325b 100644
--- a/contrib/gcc/c-tree.h
+++ b/contrib/gcc/c-tree.h
@@ -1,5 +1,5 @@
/* Definitions for C parsing and type checking.
- Copyright (C) 1987, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 93, 94, 95, 97, 98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -80,6 +80,22 @@ extern int pedantic;
nonzero if the definition of the type has already started. */
#define C_TYPE_BEING_DEFINED(type) TYPE_LANG_FLAG_0 (type)
+/* C types are partitioned into three subsets: object, function, and
+ incomplete types. */
+#define C_TYPE_OBJECT_P(type) \
+ (TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type))
+
+#define C_TYPE_FUNCTION_P(type) \
+ (TREE_CODE (type) == FUNCTION_TYPE)
+
+#define C_TYPE_INCOMPLETE_P(type) \
+ (TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type) == 0)
+
+/* For convenience we define a single macro to identify the class of
+ object or incomplete types. */
+#define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \
+ (!C_TYPE_FUNCTION_P (type))
+
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type
{
@@ -154,7 +170,7 @@ extern int maybe_objc_comptypes PROTO((tree, tree, int));
extern tree maybe_building_objc_message_expr PROTO((void));
extern tree maybe_objc_method_name PROTO((tree));
extern int recognize_objc_keyword PROTO((void));
-extern tree build_objc_string PROTO((int, char *));
+extern tree build_objc_string PROTO((int, const char *));
/* in c-aux-info.c */
extern void gen_aux_info_record PROTO((tree, int, int, int));
@@ -165,6 +181,7 @@ extern void decl_attributes PROTO((tree, tree, tree));
extern void init_function_format_info PROTO((void));
extern void check_function_format PROTO((tree, tree, tree));
extern int c_get_alias_set PROTO((tree));
+extern void c_apply_type_quals_to_decl PROTO((int, tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
@@ -213,7 +230,9 @@ extern tree double_ftype_double;
extern tree double_ftype_double_double;
extern tree double_type_node;
extern tree float_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
extern tree intTI_type_node;
+#endif
extern tree intDI_type_node;
extern tree intHI_type_node;
extern tree intQI_type_node;
@@ -243,7 +262,9 @@ extern tree signed_wchar_type_node;
extern tree string_ftype_ptr_ptr;
extern tree string_type_node;
extern tree unsigned_char_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
extern tree unsigned_intTI_type_node;
+#endif
extern tree unsigned_intDI_type_node;
extern tree unsigned_intHI_type_node;
extern tree unsigned_intQI_type_node;
@@ -261,9 +282,13 @@ extern tree boolean_false_node;
extern tree build_enumerator PROTO((tree, tree));
/* Declare a predefined function. Return the declaration. */
-extern tree builtin_function PROTO((char *, tree, enum built_in_function function_, char *));
+extern tree builtin_function PROTO((const char *, tree, enum built_in_function function_, const char *));
/* Add qualifiers to a type, in the fashion for C. */
-extern tree c_build_type_variant PROTO((tree, int, int));
+extern tree c_build_qualified_type PROTO((tree, int));
+#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
+ c_build_qualified_type (TYPE, \
+ ((CONST_P) ? TYPE_QUAL_CONST : 0) | \
+ ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
extern int c_decode_option PROTO((int, char **));
extern void c_mark_varargs PROTO((void));
extern tree check_identifier PROTO((tree, tree));
@@ -282,7 +307,7 @@ extern tree get_parm_info PROTO((int));
extern tree getdecls PROTO((void));
extern tree gettags PROTO((void));
extern int global_bindings_p PROTO((void));
-extern tree grokfield PROTO((char *, int, tree, tree, tree));
+extern tree grokfield PROTO((const char *, int, tree, tree, tree));
extern tree groktypename PROTO((tree));
extern tree groktypename_in_parm_context PROTO((tree));
extern tree implicitly_declare PROTO((tree));
@@ -340,7 +365,7 @@ extern tree c_alignof PROTO((tree));
extern tree c_alignof_expr PROTO((tree));
extern tree default_conversion PROTO((tree));
extern tree build_component_ref PROTO((tree, tree));
-extern tree build_indirect_ref PROTO((tree, char *));
+extern tree build_indirect_ref PROTO((tree, const char *));
extern tree build_array_ref PROTO((tree, tree));
extern tree build_function_call PROTO((tree, tree));
extern tree parser_build_binary_op PROTO((enum tree_code,
@@ -350,8 +375,8 @@ extern tree build_binary_op PROTO((enum tree_code,
extern tree build_unary_op PROTO((enum tree_code,
tree, int));
extern int lvalue_p PROTO((tree));
-extern int lvalue_or_else PROTO((tree, char *));
-extern void readonly_warning PROTO((tree, char *));
+extern int lvalue_or_else PROTO((tree, const char *));
+extern void readonly_warning PROTO((tree, const char *));
extern int mark_addressable PROTO((tree));
extern tree build_conditional_expr PROTO((tree, tree, tree));
extern tree build_compound_expr PROTO((tree));
@@ -360,10 +385,8 @@ extern tree build_modify_expr PROTO((tree, enum tree_code,
tree));
extern tree initializer_constant_valid_p PROTO((tree, tree));
extern void store_init_value PROTO((tree, tree));
-extern void error_init PROTO((char *, char *,
- char *));
-extern void pedwarn_init PROTO((char *, char *,
- char *));
+extern void error_init PROTO((const char *));
+extern void pedwarn_init PROTO((const char *));
extern void start_init PROTO((tree, tree, int));
extern void finish_init PROTO((void));
extern void really_start_incremental_init PROTO((tree));
@@ -418,10 +441,6 @@ extern int flag_no_asm;
extern int flag_hosted;
-/* Nonzero means ignore `#ident' directives. */
-
-extern int flag_no_ident;
-
/* Nonzero means warn about implicit declarations. */
extern int warn_implicit;
@@ -430,7 +449,7 @@ extern int warn_implicit;
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
-extern int warn_write_strings;
+extern int flag_const_strings;
/* Nonzero means warn about sizeof (function) or addition/subtraction
of function pointers. */
@@ -465,6 +484,10 @@ extern int warn_cast_qual;
extern int warn_bad_function_cast;
+/* Warn about functions which might be candidates for attribute noreturn. */
+
+extern int warn_missing_noreturn;
+
/* Warn about traditional constructs whose meanings changed in ANSI C. */
extern int warn_traditional;
@@ -489,6 +512,10 @@ extern int warn_main;
extern int flag_traditional;
+/* Nonzero means use the ISO C9x dialect of C. */
+
+extern int flag_isoc9x;
+
/* Nonzero means to allow single precision math even if we're generally
being traditional. */
extern int flag_allow_single_precision;
@@ -509,6 +536,10 @@ extern int warn_sign_compare;
extern int warn_multichar;
+/* Warn about long long. */
+
+extern int warn_long_long;
+
/* Nonzero means we are reading code that came from a system header file. */
extern int system_header_p;
diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c
index 4ccc1a3..854baf8 100644
--- a/contrib/gcc/c-typeck.c
+++ b/contrib/gcc/c-typeck.c
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "expr.h"
#include "toplev.h"
+#include "intl.h"
/* Nonzero if we've already printed a "missing braces around initializer"
message within this initializer. */
@@ -55,18 +56,17 @@ static tree pointer_diff PROTO((tree, tree));
static tree unary_complex_lvalue PROTO((enum tree_code, tree));
static void pedantic_lvalue_warning PROTO((enum tree_code));
static tree internal_build_compound_expr PROTO((tree, int));
-static tree convert_for_assignment PROTO((tree, tree, char *, tree,
+static tree convert_for_assignment PROTO((tree, tree, const char *, tree,
+ tree, int));
+static void warn_for_assignment PROTO((const char *, const char *,
tree, int));
-static void warn_for_assignment PROTO((char *, char *, tree, int));
static tree valid_compound_expr_initializer PROTO((tree, tree));
-static void push_string PROTO((char *));
+static void push_string PROTO((const char *));
static void push_member_name PROTO((tree));
static void push_array_bounds PROTO((int));
static int spelling_length PROTO((void));
static char *print_spelling PROTO((char *));
-static char *get_spelling PROTO((char *));
-static void warning_init PROTO((char *, char *,
- char *));
+static void warning_init PROTO((const char *));
static tree digest_init PROTO((tree, tree, int, int));
static void check_init_type_bitfields PROTO((tree));
static void output_init_element PROTO((tree, tree, tree, int));
@@ -83,6 +83,9 @@ require_complete_type (value)
{
tree type = TREE_TYPE (value);
+ if (TREE_CODE (value) == ERROR_MARK)
+ return error_mark_node;
+
/* First, detect a valid value with a complete type. */
if (TYPE_SIZE (type) != 0
&& type != void_type_node)
@@ -101,7 +104,7 @@ incomplete_type_error (value, type)
tree value;
tree type;
{
- char *errmsg;
+ const char *type_code_string;
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
@@ -119,15 +122,15 @@ incomplete_type_error (value, type)
switch (TREE_CODE (type))
{
case RECORD_TYPE:
- errmsg = "invalid use of undefined type `struct %s'";
+ type_code_string = "struct";
break;
case UNION_TYPE:
- errmsg = "invalid use of undefined type `union %s'";
+ type_code_string = "union";
break;
case ENUMERAL_TYPE:
- errmsg = "invalid use of undefined type `enum %s'";
+ type_code_string = "enum";
break;
case VOID_TYPE:
@@ -148,7 +151,8 @@ incomplete_type_error (value, type)
}
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
+ error ("invalid use of undefined type `%s %s'",
+ type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type)));
else
/* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */
error ("invalid use of incomplete typedef `%s'",
@@ -163,9 +167,7 @@ static tree
qualify_type (type, like)
tree type, like;
{
- int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
- int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
- return c_build_type_variant (type, constflag, volflag);
+ return c_build_qualified_type (type, TYPE_QUALS (like));
}
/* Return the common type of two types.
@@ -283,14 +285,14 @@ common_type (t1, t2)
But ANSI C specifies doing this with the qualifiers.
So I turned it on again. */
{
- tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
- TYPE_MAIN_VARIANT (TREE_TYPE (t2)));
- int constp
- = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
- int volatilep
- = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
- t1 = build_pointer_type (c_build_type_variant (target, constp,
- volatilep));
+ tree pointed_to_1 = TREE_TYPE (t1);
+ tree pointed_to_2 = TREE_TYPE (t2);
+ tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
+ TYPE_MAIN_VARIANT (pointed_to_2));
+ t1 = build_pointer_type (c_build_qualified_type
+ (target,
+ TYPE_QUALS (pointed_to_1) |
+ TYPE_QUALS (pointed_to_2)));
return build_type_attribute_variant (t1, attributes);
}
#if 0
@@ -447,9 +449,7 @@ comptypes (type1, type2)
/* Qualifiers must match. */
- if (TYPE_READONLY (t1) != TYPE_READONLY (t2))
- return 0;
- if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
+ if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
return 0;
/* Allow for two different type nodes which have essentially the same
@@ -1084,11 +1084,12 @@ default_conversion (exp)
volatilep = TREE_THIS_VOLATILE (exp);
}
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
- || constp || volatilep)
- restype = c_build_type_variant (restype,
- TYPE_READONLY (type) || constp,
- TYPE_VOLATILE (type) || volatilep);
+ if (TYPE_QUALS (type) || constp || volatilep)
+ restype
+ = c_build_qualified_type (restype,
+ TYPE_QUALS (type)
+ | (constp * TYPE_QUAL_CONST)
+ | (volatilep * TYPE_QUAL_VOLATILE));
if (TREE_CODE (exp) == INDIRECT_REF)
return convert (TYPE_POINTER_TO (restype),
@@ -1324,7 +1325,7 @@ build_component_ref (datum, component)
tree
build_indirect_ref (ptr, errorstring)
tree ptr;
- char *errorstring;
+ const char *errorstring;
{
register tree pointer = default_conversion (ptr);
register tree type = TREE_TYPE (pointer);
@@ -2793,7 +2794,6 @@ build_unary_op (code, xarg, noconvert)
register tree arg = xarg;
register tree argtype = 0;
register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
- char *errstring = NULL;
tree val;
if (typecode == ERROR_MARK)
@@ -2809,7 +2809,10 @@ build_unary_op (code, xarg, noconvert)
associativity, but won't generate any code. */
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
- errstring = "wrong type argument to unary plus";
+ {
+ error ("wrong type argument to unary plus");
+ return error_mark_node;
+ }
else if (!noconvert)
arg = default_conversion (arg);
break;
@@ -2817,7 +2820,10 @@ build_unary_op (code, xarg, noconvert)
case NEGATE_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
- errstring = "wrong type argument to unary minus";
+ {
+ error ("wrong type argument to unary minus");
+ return error_mark_node;
+ }
else if (!noconvert)
arg = default_conversion (arg);
break;
@@ -2830,7 +2836,10 @@ build_unary_op (code, xarg, noconvert)
arg = default_conversion (arg);
}
else if (typecode != INTEGER_TYPE)
- errstring = "wrong type argument to bit-complement";
+ {
+ error ("wrong type argument to bit-complement");
+ return error_mark_node;
+ }
else if (!noconvert)
arg = default_conversion (arg);
break;
@@ -2838,7 +2847,10 @@ build_unary_op (code, xarg, noconvert)
case ABS_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
- errstring = "wrong type argument to abs";
+ {
+ error ("wrong type argument to abs");
+ return error_mark_node;
+ }
else if (!noconvert)
arg = default_conversion (arg);
break;
@@ -2847,7 +2859,10 @@ build_unary_op (code, xarg, noconvert)
/* Conjugating a real value is a no-op, but allow it anyway. */
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
- errstring = "wrong type argument to conjugation";
+ {
+ error ("wrong type argument to conjugation");
+ return error_mark_node;
+ }
else if (!noconvert)
arg = default_conversion (arg);
break;
@@ -2859,8 +2874,8 @@ build_unary_op (code, xarg, noconvert)
/* These will convert to a pointer. */
&& typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
{
- errstring = "wrong type argument to unary exclamation mark";
- break;
+ error ("wrong type argument to unary exclamation mark");
+ return error_mark_node;
}
arg = truthvalue_conversion (arg);
return invert_truthvalue (arg);
@@ -2913,11 +2928,10 @@ build_unary_op (code, xarg, noconvert)
if (typecode != POINTER_TYPE
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
{
- if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
- errstring ="wrong type argument to increment";
- else
- errstring ="wrong type argument to decrement";
- break;
+ error (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
+ ? "wrong type argument to increment"
+ : "wrong type argument to decrement");
+ return error_mark_node;
}
{
@@ -2934,17 +2948,15 @@ build_unary_op (code, xarg, noconvert)
/* If pointer target is an undefined struct,
we just cannot know how to do the arithmetic. */
if (TYPE_SIZE (TREE_TYPE (result_type)) == 0)
- error ("%s of pointer to unknown structure",
- ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement"));
+ error (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
+ ? "increment of pointer to unknown structure"
+ : "decrement of pointer to unknown structure");
else if ((pedantic || warn_pointer_arith)
&& (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
- pedwarn ("wrong type argument to %s",
- ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement"));
+ pedwarn (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
+ ? "wrong type argument to increment"
+ : "wrong type argument to decrement");
inc = c_size_in_bytes (TREE_TYPE (result_type));
}
else
@@ -3001,7 +3013,8 @@ build_unary_op (code, xarg, noconvert)
/* Complain about anything else that is not a true lvalue. */
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement")))
+ ? "invalid lvalue in increment"
+ : "invalid lvalue in decrement")))
return error_mark_node;
/* Report a read-only lvalue. */
@@ -3075,13 +3088,16 @@ build_unary_op (code, xarg, noconvert)
;
/* Anything not already handled and not a true memory reference
is an error. */
- else if (typecode != FUNCTION_TYPE && !lvalue_or_else (arg, "unary `&'"))
+ else if (typecode != FUNCTION_TYPE
+ && !lvalue_or_else (arg, "invalid lvalue in unary `&'"))
return error_mark_node;
/* Ordinary case; arg is a COMPONENT_REF or a decl. */
argtype = TREE_TYPE (arg);
- /* If the lvalue is const or volatile,
- merge that into the type that the address will point to. */
+ /* If the lvalue is const or volatile, merge that into the type
+ to which the address will point. Note that you can't get a
+ restricted pointer by taking the address of something, so we
+ only have to deal with `const' and `volatile' here. */
if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
|| TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
{
@@ -3141,15 +3157,9 @@ build_unary_op (code, xarg, noconvert)
break;
}
- if (!errstring)
- {
- if (argtype == 0)
- argtype = TREE_TYPE (arg);
- return fold (build1 (code, argtype, arg));
- }
-
- error (errstring);
- return error_mark_node;
+ if (argtype == 0)
+ argtype = TREE_TYPE (arg);
+ return fold (build1 (code, argtype, arg));
}
#if 0
@@ -3223,13 +3233,13 @@ lvalue_p (ref)
otherwise, print an error message and return zero. */
int
-lvalue_or_else (ref, string)
+lvalue_or_else (ref, msgid)
tree ref;
- char *string;
+ const char *msgid;
{
int win = lvalue_p (ref);
if (! win)
- error ("invalid lvalue in %s", string);
+ error (msgid);
return win;
}
@@ -3282,47 +3292,38 @@ pedantic_lvalue_warning (code)
enum tree_code code;
{
if (pedantic)
- pedwarn ("ANSI C forbids use of %s expressions as lvalues",
- code == COND_EXPR ? "conditional"
- : code == COMPOUND_EXPR ? "compound" : "cast");
+ pedwarn (code == COND_EXPR
+ ? "ANSI C forbids use of conditional expressions as lvalues"
+ : code == COMPOUND_EXPR
+ ? "ANSI C forbids use of compound expressions as lvalues"
+ : "ANSI C forbids use of cast expressions as lvalues");
}
/* Warn about storing in something that is `const'. */
void
-readonly_warning (arg, string)
+readonly_warning (arg, msgid)
tree arg;
- char *string;
+ const char *msgid;
{
- char buf[80];
- strcpy (buf, string);
-
/* Forbid assignments to iterators. */
if (TREE_CODE (arg) == VAR_DECL && ITERATOR_P (arg))
- {
- strcat (buf, " of iterator `%s'");
- pedwarn (buf, IDENTIFIER_POINTER (DECL_NAME (arg)));
- }
+ pedwarn ("%s of iterator `%s'", _(msgid),
+ IDENTIFIER_POINTER (DECL_NAME (arg)));
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- readonly_warning (TREE_OPERAND (arg, 0), string);
+ readonly_warning (TREE_OPERAND (arg, 0), msgid);
else
- {
- strcat (buf, " of read-only member `%s'");
- pedwarn (buf, IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
- }
+ pedwarn ("%s of read-only member `%s'", _(msgid),
+ IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
}
else if (TREE_CODE (arg) == VAR_DECL)
- {
- strcat (buf, " of read-only variable `%s'");
- pedwarn (buf, IDENTIFIER_POINTER (DECL_NAME (arg)));
- }
+ pedwarn ("%s of read-only variable `%s'", _(msgid),
+ IDENTIFIER_POINTER (DECL_NAME (arg)));
else
- {
- pedwarn ("%s of read-only location", buf);
- }
+ pedwarn ("%s of read-only location", _(msgid));
}
/* Mark EXP saying that we need to be able to take the
@@ -3726,7 +3727,7 @@ build_c_cast (type, expr)
if (field)
{
- char *name;
+ const char *name;
tree t;
if (pedantic)
@@ -3779,11 +3780,11 @@ build_c_cast (type, expr)
in_type = TREE_TYPE (in_type);
while (TREE_CODE (in_otype) == POINTER_TYPE)
in_otype = TREE_TYPE (in_otype);
-
- if (TYPE_VOLATILE (in_otype) && ! TYPE_VOLATILE (in_type))
- pedwarn ("cast discards `volatile' from pointer target type");
- if (TYPE_READONLY (in_otype) && ! TYPE_READONLY (in_type))
- pedwarn ("cast discards `const' from pointer target type");
+
+ if (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type))
+ /* There are qualifiers present in IN_OTYPE that are not
+ present in IN_TYPE. */
+ pedwarn ("cast discards qualifiers from pointer target type");
}
/* Warn about possible alignment problems. */
@@ -3964,7 +3965,7 @@ build_modify_expr (lhs, modifycode, rhs)
/* Now we have handled acceptable kinds of LHS that are not truly lvalues.
Reject anything strange now. */
- if (!lvalue_or_else (lhs, "assignment"))
+ if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
return error_mark_node;
/* Warn about storing in something that is `const'. */
@@ -3997,7 +3998,7 @@ build_modify_expr (lhs, modifycode, rhs)
/* Convert new value to destination type. */
- newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
+ newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"),
NULL_TREE, NULL_TREE, 0);
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
@@ -4012,7 +4013,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (olhstype == TREE_TYPE (result))
return result;
- return convert_for_assignment (olhstype, result, "assignment",
+ return convert_for_assignment (olhstype, result, _("assignment"),
NULL_TREE, NULL_TREE, 0);
}
@@ -4023,9 +4024,7 @@ build_modify_expr (lhs, modifycode, rhs)
for assignments that are not allowed in C.
ERRTYPE is a string to use in error messages:
"assignment", "return", etc. If it is null, this is parameter passing
- for a function call (and different error messages are output). Otherwise,
- it may be a name stored in the spelling stack and interpreted by
- get_spelling.
+ for a function call (and different error messages are output).
FUNNAME is the name of the function being called,
as an IDENTIFIER_NODE, or null.
@@ -4034,7 +4033,7 @@ build_modify_expr (lhs, modifycode, rhs)
static tree
convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
tree type, rhs;
- char *errtype;
+ const char *errtype;
tree fundecl, funname;
int parmnum;
{
@@ -4114,12 +4113,13 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
|| comp_target_types (memb_type, rhstype))
{
/* If this type won't generate any warnings, use it. */
- if ((TREE_CODE (ttr) == FUNCTION_TYPE
- && TREE_CODE (ttl) == FUNCTION_TYPE)
- ? ((! TYPE_READONLY (ttl) | TYPE_READONLY (ttr))
- & (! TYPE_VOLATILE (ttl) | TYPE_VOLATILE (ttr)))
- : ((TYPE_READONLY (ttl) | ! TYPE_READONLY (ttr))
- & (TYPE_VOLATILE (ttl) | ! TYPE_VOLATILE (ttr))))
+ if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
+ || ((TREE_CODE (ttr) == FUNCTION_TYPE
+ && TREE_CODE (ttl) == FUNCTION_TYPE)
+ ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
+ == TYPE_QUALS (ttr))
+ : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
+ == TYPE_QUALS (ttl))))
break;
/* Keep looking for a better type, but remember this one. */
@@ -4157,26 +4157,14 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
certain things, it is okay to use a const or volatile
function where an ordinary one is wanted, but not
vice-versa. */
- if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
- warn_for_assignment ("%s makes `const *' function pointer from non-const",
- get_spelling (errtype), funname,
- parmnum);
- if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
- get_spelling (errtype), funname,
- parmnum);
- }
- else
- {
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s discards `const' from pointer target type",
- get_spelling (errtype), funname,
- parmnum);
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s discards `volatile' from pointer target type",
- get_spelling (errtype), funname,
- parmnum);
+ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+ warn_for_assignment ("%s makes qualified function pointer from unqualified",
+ errtype, funname, parmnum);
}
+ else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+ warn_for_assignment ("%s discards qualifiers from pointer target type",
+ errtype, funname,
+ parmnum);
}
if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
@@ -4211,18 +4199,15 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
&& (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
warn_for_assignment ("ANSI forbids %s between function pointer and `void *'",
- get_spelling (errtype), funname, parmnum);
+ errtype, funname, parmnum);
/* Const and volatile mean something different for function types,
so the usual warnings are not appropriate. */
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s discards `const' from pointer target type",
- get_spelling (errtype), funname, parmnum);
- else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s discards `volatile' from pointer target type",
- get_spelling (errtype), funname, parmnum);
+ if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+ warn_for_assignment ("%s discards qualifiers from pointer target type",
+ errtype, funname, parmnum);
/* If this is not a case of ignoring a mismatch in signedness,
no warning. */
else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
@@ -4232,7 +4217,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
/* If there is a mismatch, do warn. */
else if (pedantic)
warn_for_assignment ("pointer targets in %s differ in signedness",
- get_spelling (errtype), funname, parmnum);
+ errtype, funname, parmnum);
}
else if (TREE_CODE (ttl) == FUNCTION_TYPE
&& TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -4241,17 +4226,14 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
that say the function will not do certain things,
it is okay to use a const or volatile function
where an ordinary one is wanted, but not vice-versa. */
- if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
- warn_for_assignment ("%s makes `const *' function pointer from non-const",
- get_spelling (errtype), funname, parmnum);
- if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
- get_spelling (errtype), funname, parmnum);
+ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+ warn_for_assignment ("%s makes qualified function pointer from unqualified",
+ errtype, funname, parmnum);
}
}
else
warn_for_assignment ("%s from incompatible pointer type",
- get_spelling (errtype), funname, parmnum);
+ errtype, funname, parmnum);
return convert (type, rhs);
}
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
@@ -4267,7 +4249,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
&& integer_zerop (TREE_OPERAND (rhs, 0))))
{
warn_for_assignment ("%s makes pointer from integer without a cast",
- get_spelling (errtype), funname, parmnum);
+ errtype, funname, parmnum);
return convert (type, rhs);
}
return null_pointer_node;
@@ -4275,7 +4257,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
warn_for_assignment ("%s makes integer from pointer without a cast",
- get_spelling (errtype), funname, parmnum);
+ errtype, funname, parmnum);
return convert (type, rhs);
}
@@ -4297,30 +4279,28 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
parmnum);
}
else
- error ("incompatible types in %s", get_spelling (errtype));
+ error ("incompatible types in %s", errtype);
return error_mark_node;
}
-/* Print a warning using MSG.
+/* Print a warning using MSGID.
It gets OPNAME as its one parameter.
If OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'".
FUNCTION and ARGNUM are handled specially if we are building an
Objective-C selector. */
static void
-warn_for_assignment (msg, opname, function, argnum)
- char *msg;
- char *opname;
+warn_for_assignment (msgid, opname, function, argnum)
+ const char *msgid;
+ const char *opname;
tree function;
int argnum;
{
- static char argstring[] = "passing arg %d of `%s'";
- static char argnofun[] = "passing arg %d";
-
if (opname == 0)
{
tree selector = maybe_building_objc_message_expr ();
+ char * new_opname;
if (selector && argnum > 2)
{
@@ -4330,18 +4310,23 @@ warn_for_assignment (msg, opname, function, argnum)
if (function)
{
/* Function name is known; supply it. */
- opname = (char *) alloca (IDENTIFIER_LENGTH (function)
- + sizeof (argstring) + 25 /*%d*/ + 1);
- sprintf (opname, argstring, argnum, IDENTIFIER_POINTER (function));
+ const char *argstring = _("passing arg %d of `%s'");
+ new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
+ + strlen (argstring) + 1 + 25
+ /*%d*/ + 1);
+ sprintf (new_opname, argstring, argnum,
+ IDENTIFIER_POINTER (function));
}
else
{
- /* Function name unknown (call through ptr); just give arg number. */
- opname = (char *) alloca (sizeof (argnofun) + 25 /*%d*/ + 1);
- sprintf (opname, argnofun, argnum);
+ /* Function name unknown (call through ptr); just give arg number.*/
+ const char *argnofun = _("passing arg %d of pointer to function");
+ new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1);
+ sprintf (new_opname, argnofun, argnum);
}
+ opname = new_opname;
}
- pedwarn (msg, opname);
+ pedwarn (msgid, opname);
}
/* Return nonzero if VALUE is a valid constant-valued expression
@@ -4423,13 +4408,18 @@ initializer_constant_valid_p (value, endtype)
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
- /* Likewise conversions from int to pointers. */
+ /* Likewise conversions from int to pointers, but also allow
+ conversions from 0. */
if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (value))
- <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
+ {
+ if (integer_zerop (TREE_OPERAND (value, 0)))
+ return null_pointer_node;
+ else if (TYPE_PRECISION (TREE_TYPE (value))
+ <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
+ return initializer_constant_valid_p (TREE_OPERAND (value, 0),
+ endtype);
+ }
/* Allow conversions to union types if the value inside is okay. */
if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
@@ -4575,7 +4565,7 @@ struct spelling
union
{
int i;
- char *s;
+ const char *s;
} u;
};
@@ -4631,7 +4621,7 @@ static int spelling_size; /* Size of the spelling stack. */
static void
push_string (string)
- char *string;
+ const char *string;
{
PUSH_SPELLING (SPELLING_STRING, string, u.s);
}
@@ -4643,7 +4633,7 @@ push_member_name (decl)
tree decl;
{
- char *string
+ const char *string
= DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
}
@@ -4683,7 +4673,6 @@ print_spelling (buffer)
register char *buffer;
{
register char *d = buffer;
- register char *s;
register struct spelling *p;
for (p = spelling_base; p < spelling; p++)
@@ -4694,6 +4683,7 @@ print_spelling (buffer)
}
else
{
+ register const char *s;
if (p->kind == SPELLING_MEMBER)
*d++ = '.';
for (s = p->u.s; (*d = *s++); d++)
@@ -4703,115 +4693,52 @@ print_spelling (buffer)
return buffer;
}
-/* Provide a means to pass component names derived from the spelling stack. */
-
-char initialization_message;
-
-/* Interpret the spelling of the given ERRTYPE message. */
-
-static char *
-get_spelling (errtype)
- char *errtype;
-{
- static char *buffer;
- static int size = -1;
-
- if (errtype == &initialization_message)
- {
- /* Avoid counting chars */
- static char message[] = "initialization of `%s'";
- register int needed = sizeof (message) + spelling_length () + 1;
- char *temp;
-
- if (size < 0)
- buffer = (char *) xmalloc (size = needed);
- if (needed > size)
- buffer = (char *) xrealloc (buffer, size = needed);
-
- temp = (char *) alloca (needed);
- sprintf (buffer, message, print_spelling (temp));
- return buffer;
- }
-
- return errtype;
-}
-
/* Issue an error message for a bad initializer component.
- FORMAT describes the message. OFWHAT is the name for the component.
- LOCAL is a format string for formatting the insertion of the name
- into the message.
-
- If OFWHAT is null, the component name is stored on the spelling stack.
- If the component name is a null string, then LOCAL is omitted entirely. */
+ MSGID identifies the message.
+ The component name is taken from the spelling stack. */
void
-error_init (format, local, ofwhat)
- char *format, *local, *ofwhat;
+error_init (msgid)
+ const char *msgid;
{
- char *buffer;
-
- if (ofwhat == 0)
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+ char *ofwhat;
+ error (msgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
- sprintf (buffer, local, ofwhat);
- else
- buffer[0] = 0;
-
- error (format, buffer);
+ error ("(near initialization for `%s')", ofwhat);
}
/* Issue a pedantic warning for a bad initializer component.
- FORMAT describes the message. OFWHAT is the name for the component.
- LOCAL is a format string for formatting the insertion of the name
- into the message.
-
- If OFWHAT is null, the component name is stored on the spelling stack.
- If the component name is a null string, then LOCAL is omitted entirely. */
+ MSGID identifies the message.
+ The component name is taken from the spelling stack. */
void
-pedwarn_init (format, local, ofwhat)
- char *format, *local, *ofwhat;
+pedwarn_init (msgid)
+ const char *msgid;
{
- char *buffer;
-
- if (ofwhat == 0)
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+ char *ofwhat;
+ pedwarn (msgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
- sprintf (buffer, local, ofwhat);
- else
- buffer[0] = 0;
-
- pedwarn (format, buffer);
+ pedwarn ("(near initialization for `%s')", ofwhat);
}
/* Issue a warning for a bad initializer component.
- FORMAT describes the message. OFWHAT is the name for the component.
- LOCAL is a format string for formatting the insertion of the name
- into the message.
-
- If OFWHAT is null, the component name is stored on the spelling stack.
- If the component name is a null string, then LOCAL is omitted entirely. */
+ MSGID identifies the message.
+ The component name is taken from the spelling stack. */
static void
-warning_init (format, local, ofwhat)
- char *format, *local, *ofwhat;
+warning_init (msgid)
+ const char *msgid;
{
- char *buffer;
-
- if (ofwhat == 0)
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+ char *ofwhat;
+ warning (msgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
- sprintf (buffer, local, ofwhat);
- else
- buffer[0] = 0;
-
- warning (format, buffer);
+ warning ("(near initialization for `%s')", ofwhat);
}
/* Digest the parser output INIT as an initializer for type TYPE.
@@ -4859,16 +4786,14 @@ digest_init (type, init, require_constant, constructor_constant)
!= char_type_node)
&& TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
{
- error_init ("char-array%s initialized from wide string",
- " `%s'", NULL);
+ error_init ("char-array initialized from wide string");
return error_mark_node;
}
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
== char_type_node)
&& TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
{
- error_init ("int-array%s initialized from non-wide string",
- " `%s'", NULL);
+ error_init ("int-array initialized from non-wide string");
return error_mark_node;
}
@@ -4885,9 +4810,7 @@ digest_init (type, init, require_constant, constructor_constant)
- (TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)
? TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT
: 1))
- pedwarn_init (
- "initializer-string for array of chars%s is too long",
- " `%s'", NULL);
+ pedwarn_init ("initializer-string for array of chars is too long");
}
return inside_init;
}
@@ -4914,8 +4837,7 @@ digest_init (type, init, require_constant, constructor_constant)
else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
&& TREE_CODE (inside_init) != CONSTRUCTOR)
{
- error_init ("array%s initialized from non-constant array expression",
- " `%s'", NULL);
+ error_init ("array initialized from non-constant array expression");
return error_mark_node;
}
@@ -4932,25 +4854,21 @@ digest_init (type, init, require_constant, constructor_constant)
= valid_compound_expr_initializer (inside_init,
TREE_TYPE (inside_init));
if (inside_init == error_mark_node)
- error_init ("initializer element%s is not constant",
- " for `%s'", NULL);
+ error_init ("initializer element is not constant");
else
- pedwarn_init ("initializer element%s is not constant",
- " for `%s'", NULL);
+ pedwarn_init ("initializer element is not constant");
if (flag_pedantic_errors)
inside_init = error_mark_node;
}
else if (require_constant && ! TREE_CONSTANT (inside_init))
{
- error_init ("initializer element%s is not constant",
- " for `%s'", NULL);
+ error_init ("initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
- error_init ("initializer element%s is not computable at load time",
- " for `%s'", NULL);
+ error_init ("initializer element is not computable at load time");
inside_init = error_mark_node;
}
@@ -4966,20 +4884,18 @@ digest_init (type, init, require_constant, constructor_constant)
for arrays and functions. We must not call it in the
case where inside_init is a null pointer constant. */
inside_init
- = convert_for_assignment (type, init, "initialization",
+ = convert_for_assignment (type, init, _("initialization"),
NULL_TREE, NULL_TREE, 0);
if (require_constant && ! TREE_CONSTANT (inside_init))
{
- error_init ("initializer element%s is not constant",
- " for `%s'", NULL);
+ error_init ("initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
- error_init ("initializer element%s is not computable at load time",
- " for `%s'", NULL);
+ error_init ("initializer element is not computable at load time");
inside_init = error_mark_node;
}
@@ -4990,8 +4906,7 @@ digest_init (type, init, require_constant, constructor_constant)
if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
- error_init ("variable-sized object%s may not be initialized",
- " `%s'", NULL);
+ error_init ("variable-sized object may not be initialized");
return error_mark_node;
}
@@ -5017,7 +4932,7 @@ digest_init (type, init, require_constant, constructor_constant)
type = TREE_TYPE (TYPE_FIELDS (type));
else
{
- error_init ("invalid initializer%s", " for `%s'", NULL);
+ error_init ("invalid initializer");
return error_mark_node;
}
}
@@ -5033,7 +4948,7 @@ digest_init (type, init, require_constant, constructor_constant)
else
return error_mark_node;
}
- error_init ("invalid initializer%s", " for `%s'", NULL);
+ error_init ("invalid initializer");
return error_mark_node;
}
@@ -5196,7 +5111,7 @@ start_init (decl, asmspec_tree, top_level)
tree asmspec_tree;
int top_level;
{
- char *locus;
+ const char *locus;
struct initializer_stack *p
= (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
char *asmspec = 0;
@@ -5510,8 +5425,7 @@ push_init_level (implicit)
if (constructor_type == 0)
{
- error_init ("extra brace group at end of initializer%s",
- " for `%s'", NULL);
+ error_init ("extra brace group at end of initializer");
constructor_fields = 0;
constructor_unfilled_fields = 0;
return;
@@ -5523,7 +5437,7 @@ push_init_level (implicit)
if (implicit && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
- warning_init ("missing braces around initializer%s", " for `%s'", NULL);
+ warning_init ("missing braces around initializer");
}
if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -5554,7 +5468,7 @@ push_init_level (implicit)
}
else
{
- warning_init ("braces around scalar initializer%s", " for `%s'", NULL);
+ warning_init ("braces around scalar initializer");
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
@@ -5574,9 +5488,7 @@ check_init_type_bitfields (type)
for (tail = TYPE_FIELDS (type); tail;
tail = TREE_CHAIN (tail))
{
- if (DECL_C_BIT_FIELD (tail)
- /* This catches cases like `int foo : 8;'. */
- || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
+ if (DECL_C_BIT_FIELD (tail))
{
constructor_incremental = 0;
break;
@@ -5586,6 +5498,17 @@ check_init_type_bitfields (type)
}
}
+ else if (TREE_CODE (type) == UNION_TYPE)
+ {
+ tree tail = TYPE_FIELDS (type);
+ if (tail && DECL_C_BIT_FIELD (tail))
+ /* We also use the nonincremental algorithm for initiliazation
+ of unions whose first member is a bitfield, becuase the
+ incremental algorithm has no code for dealing with
+ bitfields. */
+ constructor_incremental = 0;
+ }
+
else if (TREE_CODE (type) == ARRAY_TYPE)
check_init_type_bitfields (TREE_TYPE (type));
}
@@ -5626,7 +5549,7 @@ pop_init_level (implicit)
&& constructor_unfilled_fields)
{
push_member_name (constructor_unfilled_fields);
- warning_init ("missing initializer%s", " for `%s'", NULL);
+ warning_init ("missing initializer");
RESTORE_SPELLING_DEPTH (constructor_depth);
}
@@ -5639,7 +5562,7 @@ pop_init_level (implicit)
&& (TREE_CODE (constructor_type) == ARRAY_TYPE
? integer_zerop (constructor_unfilled_index)
: constructor_unfilled_fields == TYPE_FIELDS (constructor_type)))
- pedwarn_init ("empty braces in initializer%s", " for `%s'", NULL);
+ pedwarn_init ("empty braces in initializer");
#endif
/* Pad out the end of the structure. */
@@ -5703,14 +5626,12 @@ pop_init_level (implicit)
the element, after verifying there is just one. */
if (constructor_elements == 0)
{
- error_init ("empty scalar initializer%s",
- " for `%s'", NULL);
+ error_init ("empty scalar initializer");
constructor = error_mark_node;
}
else if (TREE_CHAIN (constructor_elements) != 0)
{
- error_init ("extra elements in scalar initializer%s",
- " for `%s'", NULL);
+ error_init ("extra elements in scalar initializer");
constructor = TREE_VALUE (constructor_elements);
}
else
@@ -5844,20 +5765,20 @@ set_init_index (first, last)
(last) = TREE_OPERAND (last, 0);
if (TREE_CODE (first) != INTEGER_CST)
- error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
+ error_init ("nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
- error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
+ error_init ("nonconstant array index in initializer");
else if (! constructor_unfilled_index)
- error_init ("array index in non-array initializer%s", " for `%s'", NULL);
+ error_init ("array index in non-array initializer");
else if (tree_int_cst_lt (first, constructor_unfilled_index))
- error_init ("duplicate array index in initializer%s", " for `%s'", NULL);
+ error_init ("duplicate array index in initializer");
else
{
TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (first);
TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (first);
if (last != 0 && tree_int_cst_lt (last, first))
- error_init ("empty index range in initializer%s", " for `%s'", NULL);
+ error_init ("empty index range in initializer");
else
{
if (pedantic)
@@ -6188,15 +6109,13 @@ output_init_element (value, type, field, pending)
if (require_constant_value && ! TREE_CONSTANT (value))
{
- error_init ("initializer element%s is not constant",
- " for `%s'", NULL);
+ error_init ("initializer element is not constant");
value = error_mark_node;
}
else if (require_constant_elements
&& initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
{
- error_init ("initializer element%s is not computable at load time",
- " for `%s'", NULL);
+ error_init ("initializer element is not computable at load time");
value = error_mark_node;
}
@@ -6212,7 +6131,7 @@ output_init_element (value, type, field, pending)
{
if (pending_init_member (field))
{
- error_init ("duplicate initializer%s", " for `%s'", NULL);
+ error_init ("duplicate initializer");
duplicate = 1;
}
}
@@ -6565,8 +6484,7 @@ process_init_element (value)
if (constructor_stack->replacement_value != 0)
{
- error_init ("excess elements in struct initializer%s",
- " after `%s'", NULL_PTR);
+ error_init ("excess elements in struct initializer");
return;
}
@@ -6601,8 +6519,7 @@ process_init_element (value)
if (constructor_fields == 0)
{
- pedwarn_init ("excess elements in struct initializer%s",
- " after `%s'", NULL_PTR);
+ pedwarn_init ("excess elements in struct initializer");
break;
}
@@ -6666,8 +6583,7 @@ process_init_element (value)
if (constructor_fields == 0)
{
- pedwarn_init ("excess elements in union initializer%s",
- " after `%s'", NULL_PTR);
+ pedwarn_init ("excess elements in union initializer");
break;
}
@@ -6741,8 +6657,7 @@ process_init_element (value)
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index, constructor_index))
{
- pedwarn_init ("excess elements in array initializer%s",
- " after `%s'", NULL_PTR);
+ pedwarn_init ("excess elements in array initializer");
break;
}
@@ -6753,8 +6668,7 @@ process_init_element (value)
&& tree_int_cst_lt (constructor_max_index,
constructor_range_end))
{
- pedwarn_init ("excess elements in array initializer%s",
- " after `%s'", NULL_PTR);
+ pedwarn_init ("excess elements in array initializer");
TREE_INT_CST_HIGH (constructor_range_end)
= TREE_INT_CST_HIGH (constructor_max_index);
TREE_INT_CST_LOW (constructor_range_end)
@@ -6805,8 +6719,7 @@ process_init_element (value)
for a scalar variable. */
if (constructor_fields == 0)
{
- pedwarn_init ("excess elements in scalar initializer%s",
- " after `%s'", NULL_PTR);
+ pedwarn_init ("excess elements in scalar initializer");
break;
}
@@ -6923,7 +6836,7 @@ c_expand_return (retval)
}
else
{
- tree t = convert_for_assignment (valtype, retval, "return",
+ tree t = convert_for_assignment (valtype, retval, _("return"),
NULL_TREE, NULL_TREE, 0);
tree res = DECL_RESULT (current_function_decl);
tree inner;
diff --git a/contrib/gcc/caller-save.c b/contrib/gcc/caller-save.c
index 4a2deb6..7c390a5 100644
--- a/contrib/gcc/caller-save.c
+++ b/contrib/gcc/caller-save.c
@@ -1,5 +1,5 @@
/* Save and restore call-clobbered registers which are live across a call.
- Copyright (C) 1989, 1992, 94-95, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1992, 94-95, 97, 98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -39,6 +39,8 @@ Boston, MA 02111-1307, USA. */
#define MIN_UNITS_PER_WORD UNITS_PER_WORD
#endif
+#define MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD)
+
/* Modes for each hard register that we can save. The smallest mode is wide
enough to save the entire contents of the register. When saving the
register because it is live we first try to save in multi-register modes.
@@ -64,27 +66,31 @@ static enum insn_code
static enum insn_code
reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
-/* Set of hard regs currently live (during scan of all insns). */
-
-static HARD_REG_SET hard_regs_live;
-
/* Set of hard regs currently residing in save area (during insn scan). */
static HARD_REG_SET hard_regs_saved;
-/* Set of hard regs which need to be restored before referenced. */
+/* Number of registers currently in hard_regs_saved. */
-static HARD_REG_SET hard_regs_need_restore;
+static int n_regs_saved;
-/* Number of registers currently in hard_regs_saved. */
+/* Computed by mark_referenced_regs, all regs referenced in a given
+ insn. */
+static HARD_REG_SET referenced_regs;
-int n_regs_saved;
+/* Computed in mark_set_regs, holds all registers set by the current
+ instruction. */
+static HARD_REG_SET this_insn_sets;
-static void set_reg_live PROTO((rtx, rtx));
-static void clear_reg_live PROTO((rtx));
-static void restore_referenced_regs PROTO((rtx, rtx, enum machine_mode));
-static int insert_save_restore PROTO((rtx, int, int,
- enum machine_mode, int));
+
+static void mark_set_regs PROTO((rtx, rtx));
+static void mark_referenced_regs PROTO((rtx));
+static int insert_save PROTO((struct insn_chain *, int, int,
+ HARD_REG_SET *));
+static int insert_restore PROTO((struct insn_chain *, int, int,
+ int));
+static void insert_one_insn PROTO((struct insn_chain *, int,
+ enum insn_code, rtx));
/* Initialize for caller-save.
@@ -113,9 +119,9 @@ init_caller_save ()
{
if (call_used_regs[i] && ! call_fixed_regs[i])
{
- for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
+ for (j = 1; j <= MOVE_MAX_WORDS; j++)
{
- regno_save_mode[i][j] = choose_hard_reg_mode (i, j);
+ regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j);
if (regno_save_mode[i][j] == VOIDmode && j == 1)
{
call_fixed_regs[i] = 1;
@@ -170,7 +176,7 @@ init_caller_save ()
start_sequence ();
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
+ for (j = 1; j <= MOVE_MAX_WORDS; j++)
if (regno_save_mode[i][j] != VOIDmode)
{
rtx mem = gen_rtx_MEM (regno_save_mode[i][j], address);
@@ -186,13 +192,14 @@ init_caller_save ()
/* Now extract both insns and see if we can meet their
constraints. */
- ok = (reg_save_code[i][j] != -1 && reg_restore_code[i][j] != -1);
+ ok = (reg_save_code[i][j] != (enum insn_code)-1
+ && reg_restore_code[i][j] != (enum insn_code)-1);
if (ok)
{
- insn_extract (saveinsn);
- ok = constrain_operands (reg_save_code[i][j], 1);
- insn_extract (restinsn);
- ok &= constrain_operands (reg_restore_code[i][j], 1);
+ extract_insn (saveinsn);
+ ok = constrain_operands (1);
+ extract_insn (restinsn);
+ ok &= constrain_operands (1);
}
if (! ok)
@@ -219,7 +226,7 @@ init_save_areas ()
int i, j;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
+ for (j = 1; j <= MOVE_MAX_WORDS; j++)
regno_save_mem[i][j] = 0;
}
@@ -229,13 +236,6 @@ init_save_areas ()
overestimate slightly (especially if some of these registers are later
used as spill registers), but it should not be significant.
- Then perform register elimination in the addresses of the save area
- locations; return 1 if all eliminated addresses are strictly valid.
- We assume that our caller has set up the elimination table to the
- worst (largest) possible offsets.
-
- Set *PCHANGED to 1 if we had to allocate some memory for the save area.
-
Future work:
In the fallback case we should iterate backwards across all possible
@@ -248,14 +248,11 @@ init_save_areas ()
machine independent since they might be saving non-consecutive
registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */
-int
-setup_save_areas (pchanged)
- int *pchanged;
+void
+setup_save_areas ()
{
int i, j, k;
HARD_REG_SET hard_regs_used;
- int ok = 1;
-
/* Allocate space in the save area for the largest multi-register
pseudos first, then work backwards to single register
@@ -283,10 +280,9 @@ setup_save_areas (pchanged)
in a manner which allows multi-register saves/restores to be done. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- for (j = MOVE_MAX / UNITS_PER_WORD; j > 0; j--)
+ for (j = MOVE_MAX_WORDS; j > 0; j--)
{
- int ok = 1;
- int do_save;
+ int do_save = 1;
/* If no mode exists for this size, try another. Also break out
if we have already saved this hard register. */
@@ -294,7 +290,6 @@ setup_save_areas (pchanged)
continue;
/* See if any register in this group has been saved. */
- do_save = 1;
for (k = 0; k < j; k++)
if (regno_save_mem[i + k][1])
{
@@ -305,207 +300,171 @@ setup_save_areas (pchanged)
continue;
for (k = 0; k < j; k++)
+ if (! TEST_HARD_REG_BIT (hard_regs_used, i + k))
{
- int regno = i + k;
- ok &= (TEST_HARD_REG_BIT (hard_regs_used, regno) != 0);
+ do_save = 0;
+ break;
}
+ if (! do_save)
+ continue;
/* We have found an acceptable mode to store in. */
- if (ok)
+ regno_save_mem[i][j]
+ = assign_stack_local (regno_save_mode[i][j],
+ GET_MODE_SIZE (regno_save_mode[i][j]), 0);
+
+ /* Setup single word save area just in case... */
+ for (k = 0; k < j; k++)
{
+ /* This should not depend on WORDS_BIG_ENDIAN.
+ The order of words in regs is the same as in memory. */
+ rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1],
+ XEXP (regno_save_mem[i][j], 0));
- regno_save_mem[i][j]
- = assign_stack_local (regno_save_mode[i][j],
- GET_MODE_SIZE (regno_save_mode[i][j]), 0);
-
- /* Setup single word save area just in case... */
- for (k = 0; k < j; k++)
- {
- /* This should not depend on WORDS_BIG_ENDIAN.
- The order of words in regs is the same as in memory. */
- rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1],
- XEXP (regno_save_mem[i][j], 0));
-
- regno_save_mem[i+k][1]
- = adj_offsettable_operand (temp, k * UNITS_PER_WORD);
- }
- *pchanged = 1;
+ regno_save_mem[i+k][1]
+ = adj_offsettable_operand (temp, k * UNITS_PER_WORD);
}
}
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
- if (regno_save_mem[i][j] != 0)
- ok &= strict_memory_address_p (GET_MODE (regno_save_mem[i][j]),
- XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX), 0));
-
- return ok;
}
-/* Find the places where hard regs are live across calls and save them.
-
- INSN_MODE is the mode to assign to any insns that we add. This is used
- by reload to determine whether or not reloads or register eliminations
- need be done on these insns. */
-
+/* Find the places where hard regs are live across calls and save them. */
void
-save_call_clobbered_regs (insn_mode)
- enum machine_mode insn_mode;
+save_call_clobbered_regs ()
{
- rtx insn;
- int b;
+ struct insn_chain *chain, *next;
+
+ CLEAR_HARD_REG_SET (hard_regs_saved);
+ n_regs_saved = 0;
- for (b = 0; b < n_basic_blocks; b++)
+ for (chain = reload_insn_chain; chain != 0; chain = next)
{
- regset regs_live = basic_block_live_at_start[b];
- rtx prev_block_last = PREV_INSN (basic_block_head[b]);
- int i, j;
- int regno;
-
- /* Compute hard regs live at start of block -- this is the
- real hard regs marked live, plus live pseudo regs that
- have been renumbered to hard regs. No registers have yet been
- saved because we restore all of them before the end of the basic
- block. */
-
- REG_SET_TO_HARD_REG_SET (hard_regs_live, regs_live);
- CLEAR_HARD_REG_SET (hard_regs_saved);
- CLEAR_HARD_REG_SET (hard_regs_need_restore);
- n_regs_saved = 0;
-
- EXECUTE_IF_SET_IN_REG_SET (regs_live, 0, i,
- {
- if ((regno = reg_renumber[i]) >= 0)
- for (j = regno;
- j < regno + HARD_REGNO_NREGS (regno,
- PSEUDO_REGNO_MODE (i));
- j++)
- SET_HARD_REG_BIT (hard_regs_live, j);
- });
-
- /* Now scan the insns in the block, keeping track of what hard
- regs are live as we go. When we see a call, save the live
- call-clobbered hard regs. */
-
- for (insn = basic_block_head[b]; ; insn = NEXT_INSN (insn))
+ rtx insn = chain->insn;
+ enum rtx_code code = GET_CODE (insn);
+
+ next = chain->next;
+
+ if (chain->is_caller_save_insn)
+ abort ();
+
+ if (GET_RTX_CLASS (code) == 'i')
{
- RTX_CODE code = GET_CODE (insn);
+ /* If some registers have been saved, see if INSN references
+ any of them. We must restore them before the insn if so. */
- if (GET_RTX_CLASS (code) == 'i')
+ if (n_regs_saved)
{
- rtx link;
-
- /* If some registers have been saved, see if INSN references
- any of them. We must restore them before the insn if so. */
-
- if (n_regs_saved)
- restore_referenced_regs (PATTERN (insn), insn, insn_mode);
-
- /* NB: the normal procedure is to first enliven any
- registers set by insn, then deaden any registers that
- had their last use at insn. This is incorrect now,
- since multiple pseudos may have been mapped to the
- same hard reg, and the death notes are ambiguous. So
- it must be done in the other, safe, order. */
-
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_DEAD)
- clear_reg_live (XEXP (link, 0));
-
- /* When we reach a call, we need to save all registers that are
- live, call-used, not fixed, and not already saved. We must
- test at this point because registers that die in a CALL_INSN
- are not live across the call and likewise for registers that
- are born in the CALL_INSN.
-
- If registers are filled with parameters for this function,
- and some of these are also being set by this function, then
- they will not appear to die (no REG_DEAD note for them),
- to check if in fact they do, collect the set registers in
- hard_regs_live first. */
-
- if (code == CALL_INSN)
- {
- HARD_REG_SET this_call_sets;
- {
- HARD_REG_SET old_hard_regs_live;
-
- /* Save the hard_regs_live information. */
- COPY_HARD_REG_SET (old_hard_regs_live, hard_regs_live);
-
- /* Now calculate hard_regs_live for this CALL_INSN
- only. */
- CLEAR_HARD_REG_SET (hard_regs_live);
- note_stores (PATTERN (insn), set_reg_live);
- COPY_HARD_REG_SET (this_call_sets, hard_regs_live);
-
- /* Restore the hard_regs_live information. */
- COPY_HARD_REG_SET (hard_regs_live, old_hard_regs_live);
- }
-
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (call_used_regs[regno] && ! call_fixed_regs[regno]
- && TEST_HARD_REG_BIT (hard_regs_live, regno)
- /* It must not be set by this instruction. */
- && ! TEST_HARD_REG_BIT (this_call_sets, regno)
- && ! TEST_HARD_REG_BIT (hard_regs_saved, regno))
- regno += insert_save_restore (insn, 1, regno,
- insn_mode, 0);
-
- /* Put the information for this CALL_INSN on top of what
- we already had. */
- IOR_HARD_REG_SET (hard_regs_live, this_call_sets);
- COPY_HARD_REG_SET (hard_regs_need_restore, hard_regs_saved);
-
- /* Must recompute n_regs_saved. */
- n_regs_saved = 0;
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
- n_regs_saved++;
- }
+ int regno;
+
+ if (code == JUMP_INSN)
+ /* Restore all registers if this is a JUMP_INSN. */
+ COPY_HARD_REG_SET (referenced_regs, hard_regs_saved);
else
{
- note_stores (PATTERN (insn), set_reg_live);
-#ifdef AUTO_INC_DEC
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_INC)
- set_reg_live (XEXP (link, 0), NULL_RTX);
-#endif
+ CLEAR_HARD_REG_SET (referenced_regs);
+ mark_referenced_regs (PATTERN (insn));
+ AND_HARD_REG_SET (referenced_regs, hard_regs_saved);
}
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_UNUSED)
- clear_reg_live (XEXP (link, 0));
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (referenced_regs, regno))
+ regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS);
}
- if (insn == basic_block_end[b])
- break;
- }
-
- /* At the end of the basic block, we must restore any registers that
- remain saved. If the last insn in the block is a JUMP_INSN, put
- the restore before the insn, otherwise, put it after the insn. */
+ if (code == CALL_INSN)
+ {
+ rtx x;
+ int regno, nregs;
+ HARD_REG_SET hard_regs_to_save;
+
+ /* Use the register life information in CHAIN to compute which
+ regs are live before the call. */
+ REG_SET_TO_HARD_REG_SET (hard_regs_to_save, chain->live_before);
+ compute_use_by_pseudos (&hard_regs_to_save, chain->live_before);
+
+ /* Record all registers set in this call insn. These don't need
+ to be saved. */
+ CLEAR_HARD_REG_SET (this_insn_sets);
+ note_stores (PATTERN (insn), mark_set_regs);
+
+ /* Compute which hard regs must be saved before this call. */
+ AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set);
+ AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets);
+ AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved);
+ AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set);
+
+ /* Registers used for function parameters need not be saved. */
+ for (x = CALL_INSN_FUNCTION_USAGE (insn); x != 0;
+ x = XEXP (x, 1))
+ {
+ rtx y;
+
+ if (GET_CODE (XEXP (x, 0)) != USE)
+ continue;
+ y = XEXP (XEXP (x, 0), 0);
+ if (GET_CODE (y) != REG)
+ abort ();
+ regno = REGNO (y);
+ if (REGNO (y) >= FIRST_PSEUDO_REGISTER)
+ abort ();
+ nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
+ while (nregs-- > 0)
+ CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);
+ }
- if (n_regs_saved)
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
- regno += insert_save_restore ((GET_CODE (insn) == JUMP_INSN
- ? insn : NEXT_INSN (insn)), 0,
- regno, insn_mode, MOVE_MAX / UNITS_PER_WORD);
+ /* Neither do registers for which we find a death note. */
+ for (x = REG_NOTES (insn); x != 0; x = XEXP (x, 1))
+ {
+ rtx y = XEXP (x, 0);
+
+ if (REG_NOTE_KIND (x) != REG_DEAD)
+ continue;
+ if (GET_CODE (y) != REG)
+ abort ();
+ regno = REGNO (y);
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ regno = reg_renumber[regno];
+ if (regno < 0)
+ continue;
+ nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
+ while (nregs-- > 0)
+ CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);
+ }
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
+ regno += insert_save (chain, 1, regno, &hard_regs_to_save);
+
+ /* Must recompute n_regs_saved. */
+ n_regs_saved = 0;
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
+ n_regs_saved++;
+ }
+ }
- /* If we added any insns at the start of the block, update the start
- of the block to point at those insns. */
- basic_block_head[b] = NEXT_INSN (prev_block_last);
- }
+ if (chain->next == 0 || chain->next->block > chain->block)
+ {
+ int regno;
+ /* At the end of the basic block, we must restore any registers that
+ remain saved. If the last insn in the block is a JUMP_INSN, put
+ the restore before the insn, otherwise, put it after the insn. */
+
+ if (n_regs_saved)
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
+ regno += insert_restore (chain, GET_CODE (insn) == JUMP_INSN,
+ regno, MOVE_MAX_WORDS);
+ }
+ }
}
/* Here from note_stores when an insn stores a value in a register.
- Set the proper bit or bits in hard_regs_live. All pseudos that have
+ Set the proper bit or bits in this_insn_sets. All pseudos that have
been assigned hard regs have had their register number changed already,
so we can ignore pseudos. */
-
static void
-set_reg_live (reg, setter)
+mark_set_regs (reg, setter)
rtx reg;
rtx setter ATTRIBUTE_UNUSED;
{
@@ -526,105 +485,71 @@ set_reg_live (reg, setter)
endregno = regno + HARD_REGNO_NREGS (regno, mode);
for (i = regno; i < endregno; i++)
- {
- SET_HARD_REG_BIT (hard_regs_live, i);
- CLEAR_HARD_REG_BIT (hard_regs_saved, i);
- CLEAR_HARD_REG_BIT (hard_regs_need_restore, i);
- }
+ SET_HARD_REG_BIT (this_insn_sets, i);
}
-/* Here when a REG_DEAD note records the last use of a reg. Clear
- the appropriate bit or bits in hard_regs_live. Again we can ignore
- pseudos. */
-
-static void
-clear_reg_live (reg)
- rtx reg;
-{
- register int regno, endregno, i;
-
- if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
- return;
-
- regno = REGNO (reg);
- endregno= regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
-
- for (i = regno; i < endregno; i++)
- {
- CLEAR_HARD_REG_BIT (hard_regs_live, i);
- CLEAR_HARD_REG_BIT (hard_regs_need_restore, i);
- CLEAR_HARD_REG_BIT (hard_regs_saved, i);
- }
-}
-
-/* If any register currently residing in the save area is referenced in X,
- which is part of INSN, emit code to restore the register in front of INSN.
- INSN_MODE is the mode to assign to any insns that we add. */
-
+/* Walk X and record all referenced registers in REFERENCED_REGS. */
static void
-restore_referenced_regs (x, insn, insn_mode)
+mark_referenced_regs (x)
rtx x;
- rtx insn;
- enum machine_mode insn_mode;
{
enum rtx_code code = GET_CODE (x);
char *fmt;
int i, j;
- if (code == CLOBBER)
- return;
+ if (code == SET)
+ mark_referenced_regs (SET_SRC (x));
+ if (code == SET || code == CLOBBER)
+ {
+ x = SET_DEST (x);
+ code = GET_CODE (x);
+ if (code == REG || code == PC || code == CC0
+ || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
+ return;
+ }
+ if (code == MEM || code == SUBREG)
+ {
+ x = XEXP (x, 0);
+ code = GET_CODE (x);
+ }
if (code == REG)
{
int regno = REGNO (x);
+ int hardregno = (regno < FIRST_PSEUDO_REGISTER ? regno
+ : reg_renumber[regno]);
- /* If this is a pseudo, scan its memory location, since it might
- involve the use of another register, which might be saved. */
-
- if (regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_mem[regno] != 0)
- restore_referenced_regs (XEXP (reg_equiv_mem[regno], 0),
- insn, insn_mode);
- else if (regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_address[regno] != 0)
- restore_referenced_regs (reg_equiv_address[regno],
- insn, insn_mode);
-
- /* Otherwise if this is a hard register, restore any piece of it that
- is currently saved. */
-
- else if (regno < FIRST_PSEUDO_REGISTER)
+ if (hardregno >= 0)
{
- int numregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
- /* Save at most SAVEREGS at a time. This can not be larger than
- MOVE_MAX, because that causes insert_save_restore to fail. */
- int saveregs = MIN (numregs, MOVE_MAX / UNITS_PER_WORD);
- int endregno = regno + numregs;
-
- for (i = regno; i < endregno; i++)
- if (TEST_HARD_REG_BIT (hard_regs_need_restore, i))
- i += insert_save_restore (insn, 0, i, insn_mode, saveregs);
+ int nregs = HARD_REGNO_NREGS (hardregno, GET_MODE (x));
+ while (nregs-- > 0)
+ SET_HARD_REG_BIT (referenced_regs, hardregno + nregs);
}
-
+ /* If this is a pseudo that did not get a hard register, scan its
+ memory location, since it might involve the use of another
+ register, which might be saved. */
+ else if (reg_equiv_mem[regno] != 0)
+ mark_referenced_regs (XEXP (reg_equiv_mem[regno], 0));
+ else if (reg_equiv_address[regno] != 0)
+ mark_referenced_regs (reg_equiv_address[regno]);
return;
}
-
+
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- restore_referenced_regs (XEXP (x, i), insn, insn_mode);
+ mark_referenced_regs (XEXP (x, i));
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode);
+ mark_referenced_regs (XVECEXP (x, i, j));
}
}
-/* Insert a sequence of insns to save or restore, SAVE_P says which,
- REGNO. Place these insns in front of INSN. INSN_MODE is the mode
- to assign to these insns. MAXRESTORE is the maximum number of registers
- which should be restored during this call (when SAVE_P == 0). It should
- never be less than 1 since we only work with entire registers.
+/* Insert a sequence of insns to restore. Place these insns in front of
+ CHAIN if BEFORE_P is nonzero, behind the insn otherwise. MAXRESTORE is
+ the maximum number of registers which should be restored during this call.
+ It should never be less than 1 since we only work with entire registers.
Note that we have verified in init_caller_save that we can do this
with a simple SET, so use it. Set INSN_CODE to what we save there
@@ -635,13 +560,13 @@ restore_referenced_regs (x, insn, insn_mode)
Return the extra number of registers saved. */
static int
-insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
- rtx insn;
- int save_p;
+insert_restore (chain, before_p, regno, maxrestore)
+ struct insn_chain *chain;
+ int before_p;
int regno;
- enum machine_mode insn_mode;
int maxrestore;
{
+ int i;
rtx pat = NULL_RTX;
enum insn_code code = CODE_FOR_nothing;
int numregs = 0;
@@ -656,108 +581,177 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
if (regno_save_mem[regno][1] == 0)
abort ();
-#ifdef HAVE_cc0
- /* If INSN references CC0, put our insns in front of the insn that sets
- CC0. This is always safe, since the only way we could be passed an
- insn that references CC0 is for a restore, and doing a restore earlier
- isn't a problem. We do, however, assume here that CALL_INSNs don't
- reference CC0. Guard against non-INSN's like CODE_LABEL. */
-
- if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
- && reg_referenced_p (cc0_rtx, PATTERN (insn)))
- insn = prev_nonnote_insn (insn);
-#endif
+ /* Get the pattern to emit and update our status.
- /* Get the pattern to emit and update our status. */
- if (save_p)
+ See if we can restore `maxrestore' registers at once. Work
+ backwards to the single register case. */
+ for (i = maxrestore; i > 0; i--)
{
- int i, j, k;
- int ok;
+ int j, k;
+ int ok = 1;
- /* See if we can save several registers with a single instruction.
- Work backwards to the single register case. */
- for (i = MOVE_MAX / UNITS_PER_WORD; i > 0; i--)
- {
- ok = 1;
- if (regno_save_mem[regno][i] != 0)
- for (j = 0; j < i; j++)
- {
- if (! call_used_regs[regno + j] || call_fixed_regs[regno + j]
- || ! TEST_HARD_REG_BIT (hard_regs_live, regno + j)
- || TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
- ok = 0;
- }
- else
- continue;
-
- /* Must do this one save at a time */
- if (! ok)
- continue;
+ if (regno_save_mem[regno][i] == 0)
+ continue;
- pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
- gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
- regno));
- code = reg_save_code[regno][i];
+ for (j = 0; j < i; j++)
+ if (! TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
+ {
+ ok = 0;
+ break;
+ }
+ /* Must do this one restore at a time */
+ if (! ok)
+ continue;
- /* Set hard_regs_saved for all the registers we saved. */
- for (k = 0; k < i; k++)
- {
- SET_HARD_REG_BIT (hard_regs_saved, regno + k);
- SET_HARD_REG_BIT (hard_regs_need_restore, regno + k);
- n_regs_saved++;
- }
+ pat = gen_rtx_SET (VOIDmode,
+ gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
+ regno),
+ regno_save_mem[regno][i]);
+ code = reg_restore_code[regno][i];
- numregs = i;
- break;
- }
+ /* Clear status for all registers we restored. */
+ for (k = 0; k < i; k++)
+ {
+ CLEAR_HARD_REG_BIT (hard_regs_saved, regno + k);
+ n_regs_saved--;
+ }
+
+ numregs = i;
+ break;
}
- else
+
+ insert_one_insn (chain, before_p, code, pat);
+
+ /* Tell our callers how many extra registers we saved/restored */
+ return numregs - 1;
+}
+
+/* Like insert_restore above, but save registers instead. */
+static int
+insert_save (chain, before_p, regno, to_save)
+ struct insn_chain *chain;
+ int before_p;
+ int regno;
+ HARD_REG_SET *to_save;
+{
+ int i;
+ rtx pat = NULL_RTX;
+ enum insn_code code = CODE_FOR_nothing;
+ int numregs = 0;
+
+ /* A common failure mode if register status is not correct in the RTL
+ is for this routine to be called with a REGNO we didn't expect to
+ save. That will cause us to write an insn with a (nil) SET_DEST
+ or SET_SRC. Instead of doing so and causing a crash later, check
+ for this common case and abort here instead. This will remove one
+ step in debugging such problems. */
+
+ if (regno_save_mem[regno][1] == 0)
+ abort ();
+
+ /* Get the pattern to emit and update our status.
+
+ See if we can save several registers with a single instruction.
+ Work backwards to the single register case. */
+ for (i = MOVE_MAX_WORDS; i > 0; i--)
{
- int i, j, k;
- int ok;
+ int j, k;
+ int ok = 1;
+ if (regno_save_mem[regno][i] == 0)
+ continue;
- /* See if we can restore `maxrestore' registers at once. Work
- backwards to the single register case. */
- for (i = maxrestore; i > 0; i--)
- {
- ok = 1;
- if (regno_save_mem[regno][i])
- for (j = 0; j < i; j++)
- {
- if (! TEST_HARD_REG_BIT (hard_regs_need_restore, regno + j))
- ok = 0;
- }
- else
- continue;
-
- /* Must do this one restore at a time */
- if (! ok)
- continue;
-
- pat = gen_rtx_SET (VOIDmode,
- gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
- regno),
- regno_save_mem[regno][i]);
- code = reg_restore_code[regno][i];
+ for (j = 0; j < i; j++)
+ if (! TEST_HARD_REG_BIT (*to_save, regno + j))
+ {
+ ok = 0;
+ break;
+ }
+ /* Must do this one save at a time */
+ if (! ok)
+ continue;
+ pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
+ gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
+ regno));
+ code = reg_save_code[regno][i];
- /* Clear status for all registers we restored. */
- for (k = 0; k < i; k++)
- {
- CLEAR_HARD_REG_BIT (hard_regs_need_restore, regno + k);
- n_regs_saved--;
- }
+ /* Set hard_regs_saved for all the registers we saved. */
+ for (k = 0; k < i; k++)
+ {
+ SET_HARD_REG_BIT (hard_regs_saved, regno + k);
+ n_regs_saved++;
+ }
- numregs = i;
- break;
- }
+ numregs = i;
+ break;
}
- /* Emit the insn and set the code and mode. */
- insn = emit_insn_before (pat, insn);
- PUT_MODE (insn, insn_mode);
- INSN_CODE (insn) = code;
+ insert_one_insn (chain, before_p, code, pat);
/* Tell our callers how many extra registers we saved/restored */
return numregs - 1;
}
+
+/* Emit a new caller-save insn and set the code. */
+static void
+insert_one_insn (chain, before_p, code, pat)
+ struct insn_chain *chain;
+ int before_p;
+ enum insn_code code;
+ rtx pat;
+{
+ rtx insn = chain->insn;
+ struct insn_chain *new;
+
+#ifdef HAVE_cc0
+ /* If INSN references CC0, put our insns in front of the insn that sets
+ CC0. This is always safe, since the only way we could be passed an
+ insn that references CC0 is for a restore, and doing a restore earlier
+ isn't a problem. We do, however, assume here that CALL_INSNs don't
+ reference CC0. Guard against non-INSN's like CODE_LABEL. */
+
+ if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
+ && before_p
+ && reg_referenced_p (cc0_rtx, PATTERN (insn)))
+ chain = chain->prev, insn = chain->insn;
+#endif
+
+ new = new_insn_chain ();
+ if (before_p)
+ {
+ new->prev = chain->prev;
+ if (new->prev != 0)
+ new->prev->next = new;
+ else
+ reload_insn_chain = new;
+
+ chain->prev = new;
+ new->next = chain;
+ new->insn = emit_insn_before (pat, insn);
+ /* ??? It would be nice if we could exclude the already / still saved
+ registers from the live sets. */
+ COPY_REG_SET (new->live_before, chain->live_before);
+ COPY_REG_SET (new->live_after, chain->live_before);
+ if (chain->insn == BLOCK_HEAD (chain->block))
+ BLOCK_HEAD (chain->block) = new->insn;
+ }
+ else
+ {
+ new->next = chain->next;
+ if (new->next != 0)
+ new->next->prev = new;
+ chain->next = new;
+ new->prev = chain;
+ new->insn = emit_insn_after (pat, insn);
+ /* ??? It would be nice if we could exclude the already / still saved
+ registers from the live sets, and observe REG_UNUSED notes. */
+ COPY_REG_SET (new->live_before, chain->live_after);
+ COPY_REG_SET (new->live_after, chain->live_after);
+ if (chain->insn == BLOCK_END (chain->block))
+ BLOCK_END (chain->block) = new->insn;
+ }
+ new->block = chain->block;
+ new->is_caller_save_insn = 1;
+
+ INSN_CODE (new->insn) = code;
+}
diff --git a/contrib/gcc/calls.c b/contrib/gcc/calls.c
index 8b14019..d0153a3 100644
--- a/contrib/gcc/calls.c
+++ b/contrib/gcc/calls.c
@@ -1,5 +1,5 @@
/* Convert function calls to rtl insns, for GNU C compiler.
- Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 92-97, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,11 +19,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "tree.h"
@@ -34,6 +29,10 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "output.h"
+#if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
+#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
+#endif
+
/* Decide whether a function's arguments should be processed
from first to last or from last to first.
@@ -48,8 +47,8 @@ Boston, MA 02111-1307, USA. */
#endif
-/* Like STACK_BOUNDARY but in units of bytes, not bits. */
-#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
+/* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */
+#define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
/* Data structure and subroutines used within expand_call. */
@@ -125,13 +124,44 @@ static int highest_outgoing_arg_in_use;
int stack_arg_under_construction;
#endif
-static int calls_function PROTO((tree, int));
-static int calls_function_1 PROTO((tree, int));
-static void emit_call_1 PROTO((rtx, tree, tree, HOST_WIDE_INT,
- HOST_WIDE_INT, rtx, rtx,
- int, rtx, int));
+static int calls_function PROTO ((tree, int));
+static int calls_function_1 PROTO ((tree, int));
+static void emit_call_1 PROTO ((rtx, tree, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, HOST_WIDE_INT, rtx,
+ rtx, int, rtx, int));
+static void special_function_p PROTO ((char *, tree, int *, int *,
+ int *, int *));
+static void precompute_register_parameters PROTO ((int, struct arg_data *,
+ int *));
static void store_one_arg PROTO ((struct arg_data *, rtx, int, int,
- tree, int));
+ int));
+static void store_unaligned_arguments_into_pseudos PROTO ((struct arg_data *,
+ int));
+static int finalize_must_preallocate PROTO ((int, int,
+ struct arg_data *,
+ struct args_size *));
+static void precompute_arguments PROTO ((int, int, int,
+ struct arg_data *,
+ struct args_size *));
+static int compute_argument_block_size PROTO ((int,
+ struct args_size *));
+static void initialize_argument_information PROTO ((int,
+ struct arg_data *,
+ struct args_size *,
+ int, tree, tree,
+ CUMULATIVE_ARGS *,
+ int, rtx *, int *,
+ int *, int *));
+static void compute_argument_addresses PROTO ((struct arg_data *,
+ rtx, int));
+static rtx rtx_for_function_call PROTO ((tree, tree));
+static void load_register_parameters PROTO ((struct arg_data *,
+ int, rtx *));
+
+#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
+static rtx save_fixed_argument_area PROTO ((int, rtx, int *, int *));
+static void restore_fixed_argument_area PROTO ((rtx, rtx, int, int));
+#endif
/* If WHICH is 1, return 1 if EXP contains a call to the built-in function
`alloca'.
@@ -316,7 +346,7 @@ prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen)
says that the pointer to this aggregate is to be popped by the callee.
STACK_SIZE is the number of bytes of arguments on the stack,
- rounded up to STACK_BOUNDARY; zero if the size is variable.
+ rounded up to PREFERRED_STACK_BOUNDARY; zero if the size is variable.
This is both to put into the call insn and
to generate explicit popping code if necessary.
@@ -344,13 +374,14 @@ prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen)
IS_CONST is true if this is a `const' call. */
static void
-emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size,
- next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
- is_const)
+emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
+ struct_value_size, next_arg_reg, valreg, old_inhibit_defer_pop,
+ call_fusage, is_const)
rtx funexp;
- tree fndecl;
- tree funtype;
+ tree fndecl ATTRIBUTE_UNUSED;
+ tree funtype ATTRIBUTE_UNUSED;
HOST_WIDE_INT stack_size;
+ HOST_WIDE_INT rounded_stack_size;
HOST_WIDE_INT struct_value_size;
rtx next_arg_reg;
rtx valreg;
@@ -358,11 +389,12 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size,
rtx call_fusage;
int is_const;
{
- rtx stack_size_rtx = GEN_INT (stack_size);
+ rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
rtx struct_value_size_rtx = GEN_INT (struct_value_size);
rtx call_insn;
#ifndef ACCUMULATE_OUTGOING_ARGS
int already_popped = 0;
+ HOST_WIDE_INT n_popped = RETURN_POPS_ARGS (fndecl, funtype, stack_size);
#endif
/* Ensure address is valid. SYMBOL_REF is already valid, so no need,
@@ -373,11 +405,9 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size,
#ifndef ACCUMULATE_OUTGOING_ARGS
#if defined (HAVE_call_pop) && defined (HAVE_call_value_pop)
- if (HAVE_call_pop && HAVE_call_value_pop
- && (RETURN_POPS_ARGS (fndecl, funtype, stack_size) > 0
- || stack_size == 0))
+ if (HAVE_call_pop && HAVE_call_value_pop && n_popped > 0)
{
- rtx n_pop = GEN_INT (RETURN_POPS_ARGS (fndecl, funtype, stack_size));
+ rtx n_pop = GEN_INT (n_popped);
rtx pat;
/* If this subroutine pops its own args, record that in the call insn
@@ -386,10 +416,10 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size,
if (valreg)
pat = gen_call_value_pop (valreg,
gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg, n_pop);
+ rounded_stack_size_rtx, next_arg_reg, n_pop);
else
pat = gen_call_pop (gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg, n_pop);
+ rounded_stack_size_rtx, next_arg_reg, n_pop);
emit_call_insn (pat);
already_popped = 1;
@@ -404,11 +434,11 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size,
if (valreg)
emit_call_insn (gen_call_value (valreg,
gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg,
+ rounded_stack_size_rtx, next_arg_reg,
NULL_RTX));
else
emit_call_insn (gen_call (gen_rtx_MEM (FUNCTION_MODE, funexp),
- stack_size_rtx, next_arg_reg,
+ rounded_stack_size_rtx, next_arg_reg,
struct_value_size_rtx));
}
else
@@ -455,25 +485,1030 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, struct_value_size,
If returning from the subroutine does pop the args, indicate that the
stack pointer will be changed. */
- if (stack_size != 0 && RETURN_POPS_ARGS (fndecl, funtype, stack_size) > 0)
+ if (n_popped > 0)
{
if (!already_popped)
CALL_INSN_FUNCTION_USAGE (call_insn)
= gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx),
CALL_INSN_FUNCTION_USAGE (call_insn));
- stack_size -= RETURN_POPS_ARGS (fndecl, funtype, stack_size);
- stack_size_rtx = GEN_INT (stack_size);
+ rounded_stack_size -= n_popped;
+ rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
}
- if (stack_size != 0)
+ if (rounded_stack_size != 0)
{
if (flag_defer_pop && inhibit_defer_pop == 0 && !is_const)
- pending_stack_adjust += stack_size;
+ pending_stack_adjust += rounded_stack_size;
else
- adjust_stack (stack_size_rtx);
+ adjust_stack (rounded_stack_size_rtx);
+ }
+#endif
+}
+
+/* Determine if the function identified by NAME and FNDECL is one with
+ special properties we wish to know about.
+
+ For example, if the function might return more than one time (setjmp), then
+ set RETURNS_TWICE to a nonzero value.
+
+ Similarly set IS_LONGJMP for if the function is in the longjmp family.
+
+ Set IS_MALLOC for any of the standard memory allocation functions which
+ allocate from the heap.
+
+ Set MAY_BE_ALLOCA for any memory allocation function that might allocate
+ space from the stack such as alloca. */
+
+static void
+special_function_p (name, fndecl, returns_twice, is_longjmp,
+ is_malloc, may_be_alloca)
+ char *name;
+ tree fndecl;
+ int *returns_twice;
+ int *is_longjmp;
+ int *is_malloc;
+ int *may_be_alloca;
+{
+ *returns_twice = 0;
+ *is_longjmp = 0;
+ *is_malloc = 0;
+ *may_be_alloca = 0;
+
+ if (name != 0 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
+ /* Exclude functions not at the file scope, or not `extern',
+ since they are not the magic functions we would otherwise
+ think they are. */
+ && DECL_CONTEXT (fndecl) == NULL_TREE && TREE_PUBLIC (fndecl))
+ {
+ char *tname = name;
+
+ /* We assume that alloca will always be called by name. It
+ makes no sense to pass it as a pointer-to-function to
+ anything that does not understand its behavior. */
+ *may_be_alloca
+ = (((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
+ && name[0] == 'a'
+ && ! strcmp (name, "alloca"))
+ || (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
+ && name[0] == '_'
+ && ! strcmp (name, "__builtin_alloca"))));
+
+ /* Disregard prefix _, __ or __x. */
+ if (name[0] == '_')
+ {
+ if (name[1] == '_' && name[2] == 'x')
+ tname += 3;
+ else if (name[1] == '_')
+ tname += 2;
+ else
+ tname += 1;
+ }
+
+ if (tname[0] == 's')
+ {
+ *returns_twice
+ = ((tname[1] == 'e'
+ && (! strcmp (tname, "setjmp")
+ || ! strcmp (tname, "setjmp_syscall")))
+ || (tname[1] == 'i'
+ && ! strcmp (tname, "sigsetjmp"))
+ || (tname[1] == 'a'
+ && ! strcmp (tname, "savectx")));
+ if (tname[1] == 'i'
+ && ! strcmp (tname, "siglongjmp"))
+ *is_longjmp = 1;
+ }
+ else if ((tname[0] == 'q' && tname[1] == 's'
+ && ! strcmp (tname, "qsetjmp"))
+ || (tname[0] == 'v' && tname[1] == 'f'
+ && ! strcmp (tname, "vfork")))
+ *returns_twice = 1;
+
+ else if (tname[0] == 'l' && tname[1] == 'o'
+ && ! strcmp (tname, "longjmp"))
+ *is_longjmp = 1;
+ /* XXX should have "malloc" attribute on functions instead
+ of recognizing them by name. */
+ else if (! strcmp (tname, "malloc")
+ || ! strcmp (tname, "calloc")
+ || ! strcmp (tname, "realloc")
+ /* Note use of NAME rather than TNAME here. These functions
+ are only reserved when preceded with __. */
+ || ! strcmp (name, "__vn") /* mangled __builtin_vec_new */
+ || ! strcmp (name, "__nw") /* mangled __builtin_new */
+ || ! strcmp (name, "__builtin_new")
+ || ! strcmp (name, "__builtin_vec_new"))
+ *is_malloc = 1;
+ }
+}
+
+/* Precompute all register parameters as described by ARGS, storing values
+ into fields within the ARGS array.
+
+ NUM_ACTUALS indicates the total number elements in the ARGS array.
+
+ Set REG_PARM_SEEN if we encounter a register parameter. */
+
+static void
+precompute_register_parameters (num_actuals, args, reg_parm_seen)
+ int num_actuals;
+ struct arg_data *args;
+ int *reg_parm_seen;
+{
+ int i;
+
+ *reg_parm_seen = 0;
+
+ for (i = 0; i < num_actuals; i++)
+ if (args[i].reg != 0 && ! args[i].pass_on_stack)
+ {
+ *reg_parm_seen = 1;
+
+ if (args[i].value == 0)
+ {
+ push_temp_slots ();
+ args[i].value = expand_expr (args[i].tree_value, NULL_RTX,
+ VOIDmode, 0);
+ preserve_temp_slots (args[i].value);
+ pop_temp_slots ();
+
+ /* ANSI doesn't require a sequence point here,
+ but PCC has one, so this will avoid some problems. */
+ emit_queue ();
+ }
+
+ /* If we are to promote the function arg to a wider mode,
+ do it now. */
+
+ if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value)))
+ args[i].value
+ = convert_modes (args[i].mode,
+ TYPE_MODE (TREE_TYPE (args[i].tree_value)),
+ args[i].value, args[i].unsignedp);
+
+ /* If the value is expensive, and we are inside an appropriately
+ short loop, put the value into a pseudo and then put the pseudo
+ into the hard reg.
+
+ For small register classes, also do this if this call uses
+ register parameters. This is to avoid reload conflicts while
+ loading the parameters registers. */
+
+ if ((! (GET_CODE (args[i].value) == REG
+ || (GET_CODE (args[i].value) == SUBREG
+ && GET_CODE (SUBREG_REG (args[i].value)) == REG)))
+ && args[i].mode != BLKmode
+ && rtx_cost (args[i].value, SET) > 2
+ && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
+ || preserve_subexpressions_p ()))
+ args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
+ }
+}
+
+#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
+
+ /* The argument list is the property of the called routine and it
+ may clobber it. If the fixed area has been used for previous
+ parameters, we must save and restore it. */
+static rtx
+save_fixed_argument_area (reg_parm_stack_space, argblock,
+ low_to_save, high_to_save)
+ int reg_parm_stack_space;
+ rtx argblock;
+ int *low_to_save;
+ int *high_to_save;
+{
+ int i;
+ rtx save_area = NULL_RTX;
+
+ /* Compute the boundary of the that needs to be saved, if any. */
+#ifdef ARGS_GROW_DOWNWARD
+ for (i = 0; i < reg_parm_stack_space + 1; i++)
+#else
+ for (i = 0; i < reg_parm_stack_space; i++)
+#endif
+ {
+ if (i >= highest_outgoing_arg_in_use
+ || stack_usage_map[i] == 0)
+ continue;
+
+ if (*low_to_save == -1)
+ *low_to_save = i;
+
+ *high_to_save = i;
}
+
+ if (*low_to_save >= 0)
+ {
+ int num_to_save = *high_to_save - *low_to_save + 1;
+ enum machine_mode save_mode
+ = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
+ rtx stack_area;
+
+ /* If we don't have the required alignment, must do this in BLKmode. */
+ if ((*low_to_save & (MIN (GET_MODE_SIZE (save_mode),
+ BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
+ save_mode = BLKmode;
+
+#ifdef ARGS_GROW_DOWNWARD
+ stack_area = gen_rtx_MEM (save_mode,
+ memory_address (save_mode,
+ plus_constant (argblock,
+ - *high_to_save)));
+#else
+ stack_area = gen_rtx_MEM (save_mode,
+ memory_address (save_mode,
+ plus_constant (argblock,
+ *low_to_save)));
#endif
+ if (save_mode == BLKmode)
+ {
+ save_area = assign_stack_temp (BLKmode, num_to_save, 0);
+ emit_block_move (validize_mem (save_area), stack_area,
+ GEN_INT (num_to_save),
+ PARM_BOUNDARY / BITS_PER_UNIT);
+ }
+ else
+ {
+ save_area = gen_reg_rtx (save_mode);
+ emit_move_insn (save_area, stack_area);
+ }
+ }
+ return save_area;
+}
+
+static void
+restore_fixed_argument_area (save_area, argblock, high_to_save, low_to_save)
+ rtx save_area;
+ rtx argblock;
+ int high_to_save;
+ int low_to_save;
+{
+ enum machine_mode save_mode = GET_MODE (save_area);
+#ifdef ARGS_GROW_DOWNWARD
+ rtx stack_area
+ = gen_rtx_MEM (save_mode,
+ memory_address (save_mode,
+ plus_constant (argblock,
+ - high_to_save)));
+#else
+ rtx stack_area
+ = gen_rtx_MEM (save_mode,
+ memory_address (save_mode,
+ plus_constant (argblock,
+ low_to_save)));
+#endif
+
+ if (save_mode != BLKmode)
+ emit_move_insn (stack_area, save_area);
+ else
+ emit_block_move (stack_area, validize_mem (save_area),
+ GEN_INT (high_to_save - low_to_save + 1),
+ PARM_BOUNDARY / BITS_PER_UNIT);
+}
+#endif
+
+/* If any elements in ARGS refer to parameters that are to be passed in
+ registers, but not in memory, and whose alignment does not permit a
+ direct copy into registers. Copy the values into a group of pseudos
+ which we will later copy into the appropriate hard registers.
+
+ Pseudos for each unaligned argument will be stored into the array
+ args[argnum].aligned_regs. The caller is responsible for deallocating
+ the aligned_regs array if it is nonzero. */
+
+static void
+store_unaligned_arguments_into_pseudos (args, num_actuals)
+ struct arg_data *args;
+ int num_actuals;
+{
+ int i, j;
+
+ for (i = 0; i < num_actuals; i++)
+ if (args[i].reg != 0 && ! args[i].pass_on_stack
+ && args[i].mode == BLKmode
+ && (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
+ < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
+ {
+ int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
+ int big_endian_correction = 0;
+
+ args[i].n_aligned_regs
+ = args[i].partial ? args[i].partial
+ : (bytes + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
+
+ args[i].aligned_regs = (rtx *) xmalloc (sizeof (rtx)
+ * args[i].n_aligned_regs);
+
+ /* Structures smaller than a word are aligned to the least
+ significant byte (to the right). On a BYTES_BIG_ENDIAN machine,
+ this means we must skip the empty high order bytes when
+ calculating the bit offset. */
+ if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
+ big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
+
+ for (j = 0; j < args[i].n_aligned_regs; j++)
+ {
+ rtx reg = gen_reg_rtx (word_mode);
+ rtx word = operand_subword_force (args[i].value, j, BLKmode);
+ int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
+ int bitalign = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
+
+ args[i].aligned_regs[j] = reg;
+
+ /* There is no need to restrict this code to loading items
+ in TYPE_ALIGN sized hunks. The bitfield instructions can
+ load up entire word sized registers efficiently.
+
+ ??? This may not be needed anymore.
+ We use to emit a clobber here but that doesn't let later
+ passes optimize the instructions we emit. By storing 0 into
+ the register later passes know the first AND to zero out the
+ bitfield being set in the register is unnecessary. The store
+ of 0 will be deleted as will at least the first AND. */
+
+ emit_move_insn (reg, const0_rtx);
+
+ bytes -= bitsize / BITS_PER_UNIT;
+ store_bit_field (reg, bitsize, big_endian_correction, word_mode,
+ extract_bit_field (word, bitsize, 0, 1,
+ NULL_RTX, word_mode,
+ word_mode,
+ bitalign / BITS_PER_UNIT,
+ BITS_PER_WORD),
+ bitalign / BITS_PER_UNIT, BITS_PER_WORD);
+ }
+ }
+}
+
+/* Fill in ARGS_SIZE and ARGS array based on the parameters found in
+ ACTPARMS.
+
+ NUM_ACTUALS is the total number of parameters.
+
+ N_NAMED_ARGS is the total number of named arguments.
+
+ FNDECL is the tree code for the target of this call (if known)
+
+ ARGS_SO_FAR holds state needed by the target to know where to place
+ the next argument.
+
+ REG_PARM_STACK_SPACE is the number of bytes of stack space reserved
+ for arguments which are passed in registers.
+
+ OLD_STACK_LEVEL is a pointer to an rtx which olds the old stack level
+ and may be modified by this routine.
+
+ OLD_PENDING_ADJ, MUST_PREALLOCATE and IS_CONST are pointers to integer
+ flags which may may be modified by this routine. */
+
+static void
+initialize_argument_information (num_actuals, args, args_size, n_named_args,
+ actparms, fndecl, args_so_far,
+ reg_parm_stack_space, old_stack_level,
+ old_pending_adj, must_preallocate, is_const)
+ int num_actuals ATTRIBUTE_UNUSED;
+ struct arg_data *args;
+ struct args_size *args_size;
+ int n_named_args ATTRIBUTE_UNUSED;
+ tree actparms;
+ tree fndecl;
+ CUMULATIVE_ARGS *args_so_far;
+ int reg_parm_stack_space;
+ rtx *old_stack_level;
+ int *old_pending_adj;
+ int *must_preallocate;
+ int *is_const;
+{
+ /* 1 if scanning parms front to back, -1 if scanning back to front. */
+ int inc;
+
+ /* Count arg position in order args appear. */
+ int argpos;
+
+ int i;
+ tree p;
+
+ args_size->constant = 0;
+ args_size->var = 0;
+
+ /* In this loop, we consider args in the order they are written.
+ We fill up ARGS from the front or from the back if necessary
+ so that in any case the first arg to be pushed ends up at the front. */
+
+#ifdef PUSH_ARGS_REVERSED
+ i = num_actuals - 1, inc = -1;
+ /* In this case, must reverse order of args
+ so that we compute and push the last arg first. */
+#else
+ i = 0, inc = 1;
+#endif
+
+ /* I counts args in order (to be) pushed; ARGPOS counts in order written. */
+ for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++)
+ {
+ tree type = TREE_TYPE (TREE_VALUE (p));
+ int unsignedp;
+ enum machine_mode mode;
+
+ args[i].tree_value = TREE_VALUE (p);
+
+ /* Replace erroneous argument with constant zero. */
+ if (type == error_mark_node || TYPE_SIZE (type) == 0)
+ 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.
+
+ args[i].reg is nonzero if all or part is passed in registers.
+
+ args[i].partial is nonzero if part but not all is passed in registers,
+ and the exact value says how many words are passed in registers.
+
+ args[i].pass_on_stack is nonzero if the argument must at least be
+ computed on the stack. It may then be loaded back into registers
+ if args[i].reg is nonzero.
+
+ These decisions are driven by the FUNCTION_... macros and must agree
+ with those made by function.c. */
+
+ /* See if this argument should be passed by invisible reference. */
+ if ((TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
+ && contains_placeholder_p (TYPE_SIZE (type)))
+ || TREE_ADDRESSABLE (type)
+#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
+ || FUNCTION_ARG_PASS_BY_REFERENCE (*args_so_far, TYPE_MODE (type),
+ type, argpos < n_named_args)
+#endif
+ )
+ {
+ /* If we're compiling a thunk, pass through invisible
+ references instead of making a copy. */
+ if (current_function_is_thunk
+#ifdef FUNCTION_ARG_CALLEE_COPIES
+ || (FUNCTION_ARG_CALLEE_COPIES (*args_so_far, TYPE_MODE (type),
+ type, argpos < n_named_args)
+ /* If it's in a register, we must make a copy of it too. */
+ /* ??? Is this a sufficient test? Is there a better one? */
+ && !(TREE_CODE (args[i].tree_value) == VAR_DECL
+ && REG_P (DECL_RTL (args[i].tree_value)))
+ && ! TREE_ADDRESSABLE (type))
+#endif
+ )
+ {
+ /* C++ uses a TARGET_EXPR to indicate that we want to make a
+ new object from the argument. If we are passing by
+ invisible reference, the callee will do that for us, so we
+ can strip off the TARGET_EXPR. This is not always safe,
+ but it is safe in the only case where this is a useful
+ optimization; namely, when the argument is a plain object.
+ In that case, the frontend is just asking the backend to
+ make a bitwise copy of the argument. */
+
+ if (TREE_CODE (args[i].tree_value) == TARGET_EXPR
+ && (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND
+ (args[i].tree_value, 1)))
+ == 'd')
+ && ! REG_P (DECL_RTL (TREE_OPERAND (args[i].tree_value, 1))))
+ args[i].tree_value = TREE_OPERAND (args[i].tree_value, 1);
+
+ args[i].tree_value = build1 (ADDR_EXPR,
+ build_pointer_type (type),
+ args[i].tree_value);
+ type = build_pointer_type (type);
+ }
+ else
+ {
+ /* We make a copy of the object and pass the address to the
+ function being called. */
+ rtx copy;
+
+ if (TYPE_SIZE (type) == 0
+ || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
+ || (flag_stack_check && ! STACK_CHECK_BUILTIN
+ && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0
+ || (TREE_INT_CST_LOW (TYPE_SIZE (type))
+ > STACK_CHECK_MAX_VAR_SIZE * BITS_PER_UNIT))))
+ {
+ /* This is a variable-sized object. Make space on the stack
+ for it. */
+ rtx size_rtx = expr_size (TREE_VALUE (p));
+
+ if (*old_stack_level == 0)
+ {
+ emit_stack_save (SAVE_BLOCK, old_stack_level, NULL_RTX);
+ *old_pending_adj = pending_stack_adjust;
+ pending_stack_adjust = 0;
+ }
+
+ copy = gen_rtx_MEM (BLKmode,
+ allocate_dynamic_stack_space (size_rtx,
+ NULL_RTX,
+ TYPE_ALIGN (type)));
+ }
+ else
+ {
+ int size = int_size_in_bytes (type);
+ copy = assign_stack_temp (TYPE_MODE (type), size, 0);
+ }
+
+ MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
+
+ store_expr (args[i].tree_value, copy, 0);
+ *is_const = 0;
+
+ args[i].tree_value = build1 (ADDR_EXPR,
+ build_pointer_type (type),
+ make_tree (type, copy));
+ type = build_pointer_type (type);
+ }
+ }
+
+ mode = TYPE_MODE (type);
+ unsignedp = TREE_UNSIGNED (type);
+
+#ifdef PROMOTE_FUNCTION_ARGS
+ mode = promote_mode (type, mode, &unsignedp, 1);
+#endif
+
+ args[i].unsignedp = unsignedp;
+ args[i].mode = mode;
+ args[i].reg = FUNCTION_ARG (*args_so_far, mode, type,
+ argpos < n_named_args);
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ if (args[i].reg)
+ args[i].partial
+ = FUNCTION_ARG_PARTIAL_NREGS (*args_so_far, mode, type,
+ argpos < n_named_args);
+#endif
+
+ args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type);
+
+ /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
+ it means that we are to pass this arg in the register(s) designated
+ by the PARALLEL, but also to pass it in the stack. */
+ if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL
+ && XEXP (XVECEXP (args[i].reg, 0, 0), 0) == 0)
+ args[i].pass_on_stack = 1;
+
+ /* If this is an addressable type, we must preallocate the stack
+ since we must evaluate the object into its final location.
+
+ If this is to be passed in both registers and the stack, it is simpler
+ to preallocate. */
+ if (TREE_ADDRESSABLE (type)
+ || (args[i].pass_on_stack && args[i].reg != 0))
+ *must_preallocate = 1;
+
+ /* If this is an addressable type, we cannot pre-evaluate it. Thus,
+ we cannot consider this function call constant. */
+ if (TREE_ADDRESSABLE (type))
+ *is_const = 0;
+
+ /* Compute the stack-size of this argument. */
+ if (args[i].reg == 0 || args[i].partial != 0
+ || reg_parm_stack_space > 0
+ || args[i].pass_on_stack)
+ locate_and_pad_parm (mode, type,
+#ifdef STACK_PARMS_IN_REG_PARM_AREA
+ 1,
+#else
+ args[i].reg != 0,
+#endif
+ fndecl, args_size, &args[i].offset,
+ &args[i].size);
+
+#ifndef ARGS_GROW_DOWNWARD
+ args[i].slot_offset = *args_size;
+#endif
+
+ /* If a part of the arg was put into registers,
+ don't include that part in the amount pushed. */
+ if (reg_parm_stack_space == 0 && ! args[i].pass_on_stack)
+ args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD)
+ / (PARM_BOUNDARY / BITS_PER_UNIT)
+ * (PARM_BOUNDARY / BITS_PER_UNIT));
+
+ /* Update ARGS_SIZE, the total stack space for args so far. */
+
+ args_size->constant += args[i].size.constant;
+ if (args[i].size.var)
+ {
+ ADD_PARM_SIZE (*args_size, args[i].size.var);
+ }
+
+ /* Since the slot offset points to the bottom of the slot,
+ we must record it after incrementing if the args grow down. */
+#ifdef ARGS_GROW_DOWNWARD
+ args[i].slot_offset = *args_size;
+
+ args[i].slot_offset.constant = -args_size->constant;
+ if (args_size->var)
+ {
+ SUB_PARM_SIZE (args[i].slot_offset, args_size->var);
+ }
+#endif
+
+ /* Increment ARGS_SO_FAR, which has info about which arg-registers
+ have been used, etc. */
+
+ FUNCTION_ARG_ADVANCE (*args_so_far, TYPE_MODE (type), type,
+ argpos < n_named_args);
+ }
+}
+
+/* Update ARGS_SIZE to contain the total size for the argument block.
+ Return the original constant component of the argument block's size.
+
+ REG_PARM_STACK_SPACE holds the number of bytes of stack space reserved
+ for arguments passed in registers. */
+
+static int
+compute_argument_block_size (reg_parm_stack_space, args_size)
+ int reg_parm_stack_space;
+ struct args_size *args_size;
+{
+ int unadjusted_args_size = args_size->constant;
+
+ /* Compute the actual size of the argument block required. The variable
+ and constant sizes must be combined, the size may have to be rounded,
+ and there may be a minimum required size. */
+
+ if (args_size->var)
+ {
+ args_size->var = ARGS_SIZE_TREE (*args_size);
+ args_size->constant = 0;
+
+#ifdef PREFERRED_STACK_BOUNDARY
+ if (PREFERRED_STACK_BOUNDARY != BITS_PER_UNIT)
+ args_size->var = round_up (args_size->var, STACK_BYTES);
+#endif
+
+ if (reg_parm_stack_space > 0)
+ {
+ args_size->var
+ = size_binop (MAX_EXPR, args_size->var,
+ size_int (reg_parm_stack_space));
+
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+ /* The area corresponding to register parameters is not to count in
+ the size of the block we need. So make the adjustment. */
+ args_size->var
+ = size_binop (MINUS_EXPR, args_size->var,
+ size_int (reg_parm_stack_space));
+#endif
+ }
+ }
+ else
+ {
+#ifdef PREFERRED_STACK_BOUNDARY
+ args_size->constant = (((args_size->constant
+ + pending_stack_adjust
+ + STACK_BYTES - 1)
+ / STACK_BYTES * STACK_BYTES)
+ - pending_stack_adjust);
+#endif
+
+ args_size->constant = MAX (args_size->constant,
+ reg_parm_stack_space);
+
+#ifdef MAYBE_REG_PARM_STACK_SPACE
+ if (reg_parm_stack_space == 0)
+ args_size->constant = 0;
+#endif
+
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+ args_size->constant -= reg_parm_stack_space;
+#endif
+ }
+ return unadjusted_args_size;
+}
+
+/* Precompute parameters has needed for a function call.
+
+ IS_CONST indicates the target function is a pure function.
+
+ MUST_PREALLOCATE indicates that we must preallocate stack space for
+ any stack arguments.
+
+ NUM_ACTUALS is the number of arguments.
+
+ ARGS is an array containing information for each argument; this routine
+ fills in the INITIAL_VALUE and VALUE fields for each precomputed argument.
+
+ ARGS_SIZE contains information about the size of the arg list. */
+
+static void
+precompute_arguments (is_const, must_preallocate, num_actuals, args, args_size)
+ int is_const;
+ int must_preallocate;
+ int num_actuals;
+ struct arg_data *args;
+ struct args_size *args_size;
+{
+ int i;
+
+ /* If this function call is cse'able, precompute all the parameters.
+ Note that if the parameter is constructed into a temporary, this will
+ cause an additional copy because the parameter will be constructed
+ into a temporary location and then copied into the outgoing arguments.
+ If a parameter contains a call to alloca and this function uses the
+ stack, precompute the parameter. */
+
+ /* If we preallocated the stack space, and some arguments must be passed
+ on the stack, then we must precompute any parameter which contains a
+ function call which will store arguments on the stack.
+ Otherwise, evaluating the parameter may clobber previous parameters
+ which have already been stored into the stack. */
+
+ for (i = 0; i < num_actuals; i++)
+ if (is_const
+ || ((args_size->var != 0 || args_size->constant != 0)
+ && calls_function (args[i].tree_value, 1))
+ || (must_preallocate
+ && (args_size->var != 0 || args_size->constant != 0)
+ && calls_function (args[i].tree_value, 0)))
+ {
+ /* If this is an addressable type, we cannot pre-evaluate it. */
+ if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
+ abort ();
+
+ push_temp_slots ();
+
+ args[i].initial_value = args[i].value
+ = expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
+
+ preserve_temp_slots (args[i].value);
+ pop_temp_slots ();
+
+ /* ANSI doesn't require a sequence point here,
+ but PCC has one, so this will avoid some problems. */
+ emit_queue ();
+
+ args[i].initial_value = args[i].value
+ = protect_from_queue (args[i].initial_value, 0);
+
+ if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
+ args[i].value
+ = convert_modes (args[i].mode,
+ TYPE_MODE (TREE_TYPE (args[i].tree_value)),
+ args[i].value, args[i].unsignedp);
+ }
+}
+
+/* Given the current state of MUST_PREALLOCATE and information about
+ arguments to a function call in NUM_ACTUALS, ARGS and ARGS_SIZE,
+ compute and return the final value for MUST_PREALLOCATE. */
+
+static int
+finalize_must_preallocate (must_preallocate, num_actuals, args, args_size)
+ int must_preallocate;
+ int num_actuals;
+ struct arg_data *args;
+ struct args_size *args_size;
+{
+ /* See if we have or want to preallocate stack space.
+
+ If we would have to push a partially-in-regs parm
+ before other stack parms, preallocate stack space instead.
+
+ If the size of some parm is not a multiple of the required stack
+ alignment, we must preallocate.
+
+ If the total size of arguments that would otherwise create a copy in
+ a temporary (such as a CALL) is more than half the total argument list
+ size, preallocation is faster.
+
+ Another reason to preallocate is if we have a machine (like the m88k)
+ where stack alignment is required to be maintained between every
+ pair of insns, not just when the call is made. However, we assume here
+ that such machines either do not have push insns (and hence preallocation
+ would occur anyway) or the problem is taken care of with
+ PUSH_ROUNDING. */
+
+ if (! must_preallocate)
+ {
+ int partial_seen = 0;
+ int copy_to_evaluate_size = 0;
+ int i;
+
+ for (i = 0; i < num_actuals && ! must_preallocate; i++)
+ {
+ if (args[i].partial > 0 && ! args[i].pass_on_stack)
+ partial_seen = 1;
+ else if (partial_seen && args[i].reg == 0)
+ must_preallocate = 1;
+
+ if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
+ && (TREE_CODE (args[i].tree_value) == CALL_EXPR
+ || TREE_CODE (args[i].tree_value) == TARGET_EXPR
+ || TREE_CODE (args[i].tree_value) == COND_EXPR
+ || TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value))))
+ copy_to_evaluate_size
+ += int_size_in_bytes (TREE_TYPE (args[i].tree_value));
+ }
+
+ if (copy_to_evaluate_size * 2 >= args_size->constant
+ && args_size->constant > 0)
+ must_preallocate = 1;
+ }
+ return must_preallocate;
+}
+
+/* If we preallocated stack space, compute the address of each argument
+ and store it into the ARGS array.
+
+ We need not ensure it is a valid memory address here; it will be
+ validized when it is used.
+
+ ARGBLOCK is an rtx for the address of the outgoing arguments. */
+
+static void
+compute_argument_addresses (args, argblock, num_actuals)
+ struct arg_data *args;
+ rtx argblock;
+ int num_actuals;
+{
+ if (argblock)
+ {
+ rtx arg_reg = argblock;
+ int i, arg_offset = 0;
+
+ if (GET_CODE (argblock) == PLUS)
+ arg_reg = XEXP (argblock, 0), arg_offset = INTVAL (XEXP (argblock, 1));
+
+ for (i = 0; i < num_actuals; i++)
+ {
+ rtx offset = ARGS_SIZE_RTX (args[i].offset);
+ rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset);
+ rtx addr;
+
+ /* Skip this parm if it will not be passed on the stack. */
+ if (! args[i].pass_on_stack && args[i].reg != 0)
+ continue;
+
+ if (GET_CODE (offset) == CONST_INT)
+ addr = plus_constant (arg_reg, INTVAL (offset));
+ else
+ addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
+
+ addr = plus_constant (addr, arg_offset);
+ args[i].stack = gen_rtx_MEM (args[i].mode, addr);
+ MEM_SET_IN_STRUCT_P
+ (args[i].stack,
+ AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value)));
+
+ if (GET_CODE (slot_offset) == CONST_INT)
+ addr = plus_constant (arg_reg, INTVAL (slot_offset));
+ else
+ addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
+
+ addr = plus_constant (addr, arg_offset);
+ args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
+ }
+ }
+}
+
+/* Given a FNDECL and EXP, return an rtx suitable for use as a target address
+ in a call instruction.
+
+ FNDECL is the tree node for the target function. For an indirect call
+ FNDECL will be NULL_TREE.
+
+ EXP is the CALL_EXPR for this call. */
+
+static rtx
+rtx_for_function_call (fndecl, exp)
+ tree fndecl;
+ tree exp;
+{
+ rtx funexp;
+
+ /* Get the function to call, in the form of RTL. */
+ if (fndecl)
+ {
+ /* If this is the first use of the function, see if we need to
+ make an external definition for it. */
+ if (! TREE_USED (fndecl))
+ {
+ assemble_external (fndecl);
+ TREE_USED (fndecl) = 1;
+ }
+
+ /* Get a SYMBOL_REF rtx for the function address. */
+ funexp = XEXP (DECL_RTL (fndecl), 0);
+ }
+ else
+ /* Generate an rtx (probably a pseudo-register) for the address. */
+ {
+ rtx funaddr;
+ push_temp_slots ();
+ funaddr = funexp =
+ expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+ pop_temp_slots (); /* FUNEXP can't be BLKmode */
+
+ /* Check the function is executable. */
+ if (current_function_check_memory_usage)
+ {
+#ifdef POINTERS_EXTEND_UNSIGNED
+ /* It might be OK to convert funexp in place, but there's
+ a lot going on between here and when it happens naturally
+ that this seems safer. */
+ funaddr = convert_memory_address (Pmode, funexp);
+#endif
+ emit_library_call (chkr_check_exec_libfunc, 1,
+ VOIDmode, 1,
+ funaddr, Pmode);
+ }
+ emit_queue ();
+ }
+ return funexp;
+}
+
+/* Do the register loads required for any wholly-register parms or any
+ parms which are passed both on the stack and in a register. Their
+ expressions were already evaluated.
+
+ Mark all register-parms as living through the call, putting these USE
+ insns in the CALL_INSN_FUNCTION_USAGE field. */
+
+static void
+load_register_parameters (args, num_actuals, call_fusage)
+ struct arg_data *args;
+ int num_actuals;
+ rtx *call_fusage;
+{
+ int i, j;
+
+#ifdef LOAD_ARGS_REVERSED
+ for (i = num_actuals - 1; i >= 0; i--)
+#else
+ for (i = 0; i < num_actuals; i++)
+#endif
+ {
+ rtx reg = args[i].reg;
+ int partial = args[i].partial;
+ int nregs;
+
+ if (reg)
+ {
+ /* Set to non-negative if must move a word at a time, even if just
+ one word (e.g, partial == 1 && mode == DFmode). Set to -1 if
+ we just use a normal move insn. This value can be zero if the
+ argument is a zero size structure with no fields. */
+ nregs = (partial ? partial
+ : (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
+ ? ((int_size_in_bytes (TREE_TYPE (args[i].tree_value))
+ + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
+ : -1));
+
+ /* Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+
+ if (GET_CODE (reg) == PARALLEL)
+ {
+ emit_group_load (reg, args[i].value,
+ int_size_in_bytes (TREE_TYPE (args[i].tree_value)),
+ (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
+ / BITS_PER_UNIT));
+ }
+
+ /* If simple case, just do move. If normal partial, store_one_arg
+ has already loaded the register for us. In all other cases,
+ load the register(s) from memory. */
+
+ else if (nregs == -1)
+ emit_move_insn (reg, args[i].value);
+
+ /* If we have pre-computed the values to put in the registers in
+ the case of non-aligned structures, copy them in now. */
+
+ else if (args[i].n_aligned_regs != 0)
+ for (j = 0; j < args[i].n_aligned_regs; j++)
+ emit_move_insn (gen_rtx_REG (word_mode, REGNO (reg) + j),
+ args[i].aligned_regs[j]);
+
+ else if (partial == 0 || args[i].pass_on_stack)
+ move_block_to_reg (REGNO (reg),
+ validize_mem (args[i].value), nregs,
+ args[i].mode);
+
+ /* Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+ if (GET_CODE (reg) == PARALLEL)
+ use_group_regs (call_fusage, reg);
+ else if (nregs == -1)
+ use_reg (call_fusage, reg);
+ else
+ use_regs (call_fusage, REGNO (reg), nregs == 0 ? 1 : nregs);
+ }
+ }
}
/* Generate all the code for a function call
@@ -522,8 +1557,6 @@ expand_call (exp, target, ignore)
/* Number of named args. Args after this are anonymous ones
and they must all go on the stack. */
int n_named_args;
- /* Count arg position in order args appear. */
- int argpos;
/* Vector of information about each argument.
Arguments are numbered in the order they will be pushed,
@@ -533,7 +1566,7 @@ expand_call (exp, target, ignore)
/* Total size in bytes of all the stack-parms scanned so far. */
struct args_size args_size;
/* Size of arguments before any adjustments (such as rounding). */
- struct args_size original_args_size;
+ int unadjusted_args_size;
/* Data on reg parms scanned so far. */
CUMULATIVE_ARGS args_so_far;
/* Nonzero if a reg parm has been scanned. */
@@ -555,8 +1588,6 @@ expand_call (exp, target, ignore)
/* Size of the stack reserved for parameter registers. */
int reg_parm_stack_space = 0;
- /* 1 if scanning parms front to back, -1 if scanning back to front. */
- int inc;
/* Address of space preallocated for stack parms
(on machines that lack push insns), or 0 if space not preallocated. */
rtx argblock = 0;
@@ -594,13 +1625,13 @@ expand_call (exp, target, ignore)
int old_inhibit_defer_pop = inhibit_defer_pop;
rtx call_fusage = 0;
register tree p;
- register int i, j;
+ register int i;
/* The value of the function call can be put in a hard register. But
if -fcheck-memory-usage, code which invokes functions (and thus
damages some hard registers) can be inserted before using the value.
So, target is always a pseudo-register in that case. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
target = 0;
/* See if we can find a DECL-node for the actual function.
@@ -818,103 +1849,30 @@ expand_call (exp, target, ignore)
mark_addressable (fndecl);
}
- /* When calling a const function, we must pop the stack args right away,
- so that the pop is deleted or moved with the call. */
- if (is_const)
- NO_DEFER_POP;
-
function_call_count++;
if (fndecl && DECL_NAME (fndecl))
name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
-#if 0
- /* Unless it's a call to a specific function that isn't alloca,
- if it has one argument, we must assume it might be alloca. */
-
- may_be_alloca
- = (!(fndecl != 0 && strcmp (name, "alloca"))
- && actparms != 0
- && TREE_CHAIN (actparms) == 0);
-#else
- /* We assume that alloca will always be called by name. It
- makes no sense to pass it as a pointer-to-function to
- anything that does not understand its behavior. */
- may_be_alloca
- = (name && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
- && name[0] == 'a'
- && ! strcmp (name, "alloca"))
- || (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
- && name[0] == '_'
- && ! strcmp (name, "__builtin_alloca"))));
-#endif
-
/* See if this is a call to a function that can return more than once
- or a call to longjmp. */
-
- returns_twice = 0;
- is_longjmp = 0;
- is_malloc = 0;
-
- if (name != 0 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
- /* Exclude functions not at the file scope, or not `extern',
- since they are not the magic functions we would otherwise
- think they are. */
- && DECL_CONTEXT (fndecl) == NULL_TREE && TREE_PUBLIC (fndecl))
- {
- char *tname = name;
-
- /* Disregard prefix _, __ or __x. */
- if (name[0] == '_')
- {
- if (name[1] == '_' && name[2] == 'x')
- tname += 3;
- else if (name[1] == '_')
- tname += 2;
- else
- tname += 1;
- }
-
- if (tname[0] == 's')
- {
- returns_twice
- = ((tname[1] == 'e'
- && (! strcmp (tname, "setjmp")
- || ! strcmp (tname, "setjmp_syscall")))
- || (tname[1] == 'i'
- && ! strcmp (tname, "sigsetjmp"))
- || (tname[1] == 'a'
- && ! strcmp (tname, "savectx")));
- if (tname[1] == 'i'
- && ! strcmp (tname, "siglongjmp"))
- is_longjmp = 1;
- }
- else if ((tname[0] == 'q' && tname[1] == 's'
- && ! strcmp (tname, "qsetjmp"))
- || (tname[0] == 'v' && tname[1] == 'f'
- && ! strcmp (tname, "vfork")))
- returns_twice = 1;
-
- else if (tname[0] == 'l' && tname[1] == 'o'
- && ! strcmp (tname, "longjmp"))
- is_longjmp = 1;
- /* XXX should have "malloc" attribute on functions instead
- of recognizing them by name. */
- else if (! strcmp (tname, "malloc")
- || ! strcmp (tname, "calloc")
- || ! strcmp (tname, "realloc")
- /* Note use of NAME rather than TNAME here. These functions
- are only reserved when preceded with __. */
- || ! strcmp (name, "__vn") /* mangled __builtin_vec_new */
- || ! strcmp (name, "__nw") /* mangled __builtin_new */
- || ! strcmp (name, "__builtin_new")
- || ! strcmp (name, "__builtin_vec_new"))
- is_malloc = 1;
- }
+ or a call to longjmp or malloc. */
+ special_function_p (name, fndecl, &returns_twice, &is_longjmp,
+ &is_malloc, &may_be_alloca);
if (may_be_alloca)
current_function_calls_alloca = 1;
+ /* Operand 0 is a pointer-to-function; get the type of the function. */
+ funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
+ if (! POINTER_TYPE_P (funtype))
+ abort ();
+ funtype = TREE_TYPE (funtype);
+
+ /* When calling a const function, we must pop the stack args right away,
+ so that the pop is deleted or moved with the call. */
+ if (is_const)
+ NO_DEFER_POP;
+
/* Don't let pending stack adjusts add up to too much.
Also, do all pending adjustments now
if there is any chance this might be a call to alloca. */
@@ -923,12 +1881,6 @@ expand_call (exp, target, ignore)
|| (pending_stack_adjust > 0 && may_be_alloca))
do_pending_stack_adjust ();
- /* Operand 0 is a pointer-to-function; get the type of the function. */
- funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
- if (TREE_CODE (funtype) != POINTER_TYPE)
- abort ();
- funtype = TREE_TYPE (funtype);
-
/* Push the temporary stack slot level so that we can free any temporaries
we make. */
push_temp_slots ();
@@ -976,21 +1928,18 @@ expand_call (exp, target, ignore)
(If no anonymous args follow, the result of list_length is actually
one too large. This is harmless.)
- If SETUP_INCOMING_VARARGS is defined and STRICT_ARGUMENT_NAMING is zero,
- this machine will be able to place unnamed args that were passed in
+ If PRETEND_OUTGOING_VARARGS_NAMED is set and STRICT_ARGUMENT_NAMING is
+ zero, this machine will be able to place unnamed args that were passed in
registers into the stack. So treat all args as named. This allows the
insns emitting for a specific argument list to be independent of the
function declaration.
- If SETUP_INCOMING_VARARGS is not defined, we do not have any reliable
+ If PRETEND_OUTGOING_VARARGS_NAMED is not set, we do not have any reliable
way to pass unnamed args in registers, so we must force them into
memory. */
if ((STRICT_ARGUMENT_NAMING
-#ifndef SETUP_INCOMING_VARARGS
- || 1
-#endif
- )
+ || ! PRETEND_OUTGOING_VARARGS_NAMED)
&& TYPE_ARG_TYPES (funtype) != 0)
n_named_args
= (list_length (TYPE_ARG_TYPES (funtype))
@@ -1006,232 +1955,19 @@ expand_call (exp, target, ignore)
args = (struct arg_data *) alloca (num_actuals * sizeof (struct arg_data));
bzero ((char *) args, num_actuals * sizeof (struct arg_data));
- args_size.constant = 0;
- args_size.var = 0;
-
- /* In this loop, we consider args in the order they are written.
- We fill up ARGS from the front or from the back if necessary
- so that in any case the first arg to be pushed ends up at the front. */
-
-#ifdef PUSH_ARGS_REVERSED
- i = num_actuals - 1, inc = -1;
- /* In this case, must reverse order of args
- so that we compute and push the last arg first. */
-#else
- i = 0, inc = 1;
-#endif
-
- /* I counts args in order (to be) pushed; ARGPOS counts in order written. */
- for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++)
- {
- tree type = TREE_TYPE (TREE_VALUE (p));
- int unsignedp;
- enum machine_mode mode;
-
- args[i].tree_value = TREE_VALUE (p);
-
- /* Replace erroneous argument with constant zero. */
- if (type == error_mark_node || TYPE_SIZE (type) == 0)
- 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.
-
- args[i].reg is nonzero if all or part is passed in registers.
-
- args[i].partial is nonzero if part but not all is passed in registers,
- and the exact value says how many words are passed in registers.
-
- args[i].pass_on_stack is nonzero if the argument must at least be
- computed on the stack. It may then be loaded back into registers
- if args[i].reg is nonzero.
-
- These decisions are driven by the FUNCTION_... macros and must agree
- with those made by function.c. */
-
- /* See if this argument should be passed by invisible reference. */
- if ((TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
- && contains_placeholder_p (TYPE_SIZE (type)))
- || TREE_ADDRESSABLE (type)
-#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
- || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, TYPE_MODE (type),
- type, argpos < n_named_args)
-#endif
- )
- {
- /* If we're compiling a thunk, pass through invisible
- references instead of making a copy. */
- if (current_function_is_thunk
-#ifdef FUNCTION_ARG_CALLEE_COPIES
- || (FUNCTION_ARG_CALLEE_COPIES (args_so_far, TYPE_MODE (type),
- type, argpos < n_named_args)
- /* If it's in a register, we must make a copy of it too. */
- /* ??? Is this a sufficient test? Is there a better one? */
- && !(TREE_CODE (args[i].tree_value) == VAR_DECL
- && REG_P (DECL_RTL (args[i].tree_value)))
- && ! TREE_ADDRESSABLE (type))
-#endif
- )
- {
- args[i].tree_value = build1 (ADDR_EXPR,
- build_pointer_type (type),
- args[i].tree_value);
- type = build_pointer_type (type);
- }
- else
- {
- /* We make a copy of the object and pass the address to the
- function being called. */
- rtx copy;
-
- if (TYPE_SIZE (type) == 0
- || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
- || (flag_stack_check && ! STACK_CHECK_BUILTIN
- && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0
- || (TREE_INT_CST_LOW (TYPE_SIZE (type))
- > STACK_CHECK_MAX_VAR_SIZE * BITS_PER_UNIT))))
- {
- /* This is a variable-sized object. Make space on the stack
- for it. */
- rtx size_rtx = expr_size (TREE_VALUE (p));
-
- if (old_stack_level == 0)
- {
- emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
- old_pending_adj = pending_stack_adjust;
- pending_stack_adjust = 0;
- }
-
- copy = gen_rtx_MEM (BLKmode,
- allocate_dynamic_stack_space (size_rtx,
- NULL_RTX,
- TYPE_ALIGN (type)));
- }
- else
- {
- int size = int_size_in_bytes (type);
- copy = assign_stack_temp (TYPE_MODE (type), size, 0);
- }
-
- MEM_IN_STRUCT_P (copy) = AGGREGATE_TYPE_P (type);
-
- store_expr (args[i].tree_value, copy, 0);
- is_const = 0;
-
- args[i].tree_value = build1 (ADDR_EXPR,
- build_pointer_type (type),
- make_tree (type, copy));
- type = build_pointer_type (type);
- }
- }
-
- mode = TYPE_MODE (type);
- unsignedp = TREE_UNSIGNED (type);
-
-#ifdef PROMOTE_FUNCTION_ARGS
- mode = promote_mode (type, mode, &unsignedp, 1);
-#endif
-
- args[i].unsignedp = unsignedp;
- args[i].mode = mode;
- args[i].reg = FUNCTION_ARG (args_so_far, mode, type,
- argpos < n_named_args);
-#ifdef FUNCTION_ARG_PARTIAL_NREGS
- if (args[i].reg)
- args[i].partial
- = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, type,
- argpos < n_named_args);
-#endif
-
- args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type);
-
- /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
- it means that we are to pass this arg in the register(s) designated
- by the PARALLEL, but also to pass it in the stack. */
- if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL
- && XEXP (XVECEXP (args[i].reg, 0, 0), 0) == 0)
- args[i].pass_on_stack = 1;
-
- /* If this is an addressable type, we must preallocate the stack
- since we must evaluate the object into its final location.
-
- If this is to be passed in both registers and the stack, it is simpler
- to preallocate. */
- if (TREE_ADDRESSABLE (type)
- || (args[i].pass_on_stack && args[i].reg != 0))
- must_preallocate = 1;
-
- /* If this is an addressable type, we cannot pre-evaluate it. Thus,
- we cannot consider this function call constant. */
- if (TREE_ADDRESSABLE (type))
- is_const = 0;
-
- /* Compute the stack-size of this argument. */
- if (args[i].reg == 0 || args[i].partial != 0
- || reg_parm_stack_space > 0
- || args[i].pass_on_stack)
- locate_and_pad_parm (mode, type,
-#ifdef STACK_PARMS_IN_REG_PARM_AREA
- 1,
-#else
- args[i].reg != 0,
-#endif
- fndecl, &args_size, &args[i].offset,
- &args[i].size);
-
-#ifndef ARGS_GROW_DOWNWARD
- args[i].slot_offset = args_size;
-#endif
-
- /* If a part of the arg was put into registers,
- don't include that part in the amount pushed. */
- if (reg_parm_stack_space == 0 && ! args[i].pass_on_stack)
- args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD)
- / (PARM_BOUNDARY / BITS_PER_UNIT)
- * (PARM_BOUNDARY / BITS_PER_UNIT));
-
- /* Update ARGS_SIZE, the total stack space for args so far. */
-
- args_size.constant += args[i].size.constant;
- if (args[i].size.var)
- {
- ADD_PARM_SIZE (args_size, args[i].size.var);
- }
-
- /* Since the slot offset points to the bottom of the slot,
- we must record it after incrementing if the args grow down. */
-#ifdef ARGS_GROW_DOWNWARD
- args[i].slot_offset = args_size;
-
- args[i].slot_offset.constant = -args_size.constant;
- if (args_size.var)
- {
- SUB_PARM_SIZE (args[i].slot_offset, args_size.var);
- }
-#endif
-
- /* Increment ARGS_SO_FAR, which has info about which arg-registers
- have been used, etc. */
-
- FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type,
- argpos < n_named_args);
- }
+ /* Build up entries inthe ARGS array, compute the size of the arguments
+ into ARGS_SIZE, etc. */
+ initialize_argument_information (num_actuals, args, &args_size, n_named_args,
+ actparms, fndecl, &args_so_far,
+ reg_parm_stack_space, &old_stack_level,
+ &old_pending_adj, &must_preallocate,
+ &is_const);
#ifdef FINAL_REG_PARM_STACK_SPACE
reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
args_size.var);
#endif
- /* Compute the actual size of the argument block required. The variable
- and constant sizes must be combined, the size may have to be rounded,
- and there may be a minimum required size. */
-
- original_args_size = args_size;
if (args_size.var)
{
/* If this function requires a variable-sized argument list, don't try to
@@ -1241,94 +1977,17 @@ expand_call (exp, target, ignore)
is_const = 0;
must_preallocate = 1;
-
- args_size.var = ARGS_SIZE_TREE (args_size);
- args_size.constant = 0;
-
-#ifdef STACK_BOUNDARY
- if (STACK_BOUNDARY != BITS_PER_UNIT)
- args_size.var = round_up (args_size.var, STACK_BYTES);
-#endif
-
- if (reg_parm_stack_space > 0)
- {
- args_size.var
- = size_binop (MAX_EXPR, args_size.var,
- size_int (reg_parm_stack_space));
-
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
- /* The area corresponding to register parameters is not to count in
- the size of the block we need. So make the adjustment. */
- args_size.var
- = size_binop (MINUS_EXPR, args_size.var,
- size_int (reg_parm_stack_space));
-#endif
- }
}
- else
- {
-#ifdef STACK_BOUNDARY
- args_size.constant = (((args_size.constant + (STACK_BYTES - 1))
- / STACK_BYTES) * STACK_BYTES);
-#endif
-
- args_size.constant = MAX (args_size.constant,
- reg_parm_stack_space);
-
-#ifdef MAYBE_REG_PARM_STACK_SPACE
- if (reg_parm_stack_space == 0)
- args_size.constant = 0;
-#endif
-
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
- args_size.constant -= reg_parm_stack_space;
-#endif
- }
-
- /* See if we have or want to preallocate stack space.
-
- If we would have to push a partially-in-regs parm
- before other stack parms, preallocate stack space instead.
-
- If the size of some parm is not a multiple of the required stack
- alignment, we must preallocate.
-
- If the total size of arguments that would otherwise create a copy in
- a temporary (such as a CALL) is more than half the total argument list
- size, preallocation is faster.
- Another reason to preallocate is if we have a machine (like the m88k)
- where stack alignment is required to be maintained between every
- pair of insns, not just when the call is made. However, we assume here
- that such machines either do not have push insns (and hence preallocation
- would occur anyway) or the problem is taken care of with
- PUSH_ROUNDING. */
-
- if (! must_preallocate)
- {
- int partial_seen = 0;
- int copy_to_evaluate_size = 0;
-
- for (i = 0; i < num_actuals && ! must_preallocate; i++)
- {
- if (args[i].partial > 0 && ! args[i].pass_on_stack)
- partial_seen = 1;
- else if (partial_seen && args[i].reg == 0)
- must_preallocate = 1;
-
- if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
- && (TREE_CODE (args[i].tree_value) == CALL_EXPR
- || TREE_CODE (args[i].tree_value) == TARGET_EXPR
- || TREE_CODE (args[i].tree_value) == COND_EXPR
- || TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value))))
- copy_to_evaluate_size
- += int_size_in_bytes (TREE_TYPE (args[i].tree_value));
- }
+ /* Compute the actual size of the argument block required. The variable
+ and constant sizes must be combined, the size may have to be rounded,
+ and there may be a minimum required size. */
+ unadjusted_args_size
+ = compute_argument_block_size (reg_parm_stack_space, &args_size);
- if (copy_to_evaluate_size * 2 >= args_size.constant
- && args_size.constant > 0)
- must_preallocate = 1;
- }
+ /* Now make final decision about preallocating stack space. */
+ must_preallocate = finalize_must_preallocate (must_preallocate,
+ num_actuals, args, &args_size);
/* If the structure value address will reference the stack pointer, we must
stabilize it. We don't need to do this if we know that we are not going
@@ -1344,51 +2003,9 @@ expand_call (exp, target, ignore)
))
structure_value_addr = copy_to_reg (structure_value_addr);
- /* If this function call is cse'able, precompute all the parameters.
- Note that if the parameter is constructed into a temporary, this will
- cause an additional copy because the parameter will be constructed
- into a temporary location and then copied into the outgoing arguments.
- If a parameter contains a call to alloca and this function uses the
- stack, precompute the parameter. */
-
- /* If we preallocated the stack space, and some arguments must be passed
- on the stack, then we must precompute any parameter which contains a
- function call which will store arguments on the stack.
- Otherwise, evaluating the parameter may clobber previous parameters
- which have already been stored into the stack. */
-
- for (i = 0; i < num_actuals; i++)
- if (is_const
- || ((args_size.var != 0 || args_size.constant != 0)
- && calls_function (args[i].tree_value, 1))
- || (must_preallocate && (args_size.var != 0 || args_size.constant != 0)
- && calls_function (args[i].tree_value, 0)))
- {
- /* If this is an addressable type, we cannot pre-evaluate it. */
- if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
- abort ();
-
- push_temp_slots ();
-
- args[i].initial_value = args[i].value
- = expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
-
- preserve_temp_slots (args[i].value);
- pop_temp_slots ();
-
- /* ANSI doesn't require a sequence point here,
- but PCC has one, so this will avoid some problems. */
- emit_queue ();
-
- args[i].initial_value = args[i].value
- = protect_from_queue (args[i].initial_value, 0);
-
- if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
- args[i].value
- = convert_modes (args[i].mode,
- TYPE_MODE (TREE_TYPE (args[i].tree_value)),
- args[i].value, args[i].unsignedp);
- }
+ /* Precompute any arguments as needed. */
+ precompute_arguments (is_const, must_preallocate, num_actuals,
+ args, &args_size);
/* Now we are about to start emitting insns that can be deleted
if a libcall is deleted. */
@@ -1551,55 +2168,14 @@ expand_call (exp, target, ignore)
}
#endif
+ compute_argument_addresses (args, argblock, num_actuals);
- /* If we preallocated stack space, compute the address of each argument.
- We need not ensure it is a valid memory address here; it will be
- validized when it is used. */
- if (argblock)
- {
- rtx arg_reg = argblock;
- int arg_offset = 0;
-
- if (GET_CODE (argblock) == PLUS)
- arg_reg = XEXP (argblock, 0), arg_offset = INTVAL (XEXP (argblock, 1));
-
- for (i = 0; i < num_actuals; i++)
- {
- rtx offset = ARGS_SIZE_RTX (args[i].offset);
- rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset);
- rtx addr;
-
- /* Skip this parm if it will not be passed on the stack. */
- if (! args[i].pass_on_stack && args[i].reg != 0)
- continue;
-
- if (GET_CODE (offset) == CONST_INT)
- addr = plus_constant (arg_reg, INTVAL (offset));
- else
- addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
-
- addr = plus_constant (addr, arg_offset);
- args[i].stack = gen_rtx_MEM (args[i].mode, addr);
- MEM_IN_STRUCT_P (args[i].stack)
- = AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value));
-
- if (GET_CODE (slot_offset) == CONST_INT)
- addr = plus_constant (arg_reg, INTVAL (slot_offset));
- else
- addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
-
- addr = plus_constant (addr, arg_offset);
- args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
- }
- }
-
#ifdef PUSH_ARGS_REVERSED
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
/* If we push args individually in reverse order, perform stack alignment
before the first push (the last arg). */
if (argblock == 0)
- anti_adjust_stack (GEN_INT (args_size.constant
- - original_args_size.constant));
+ anti_adjust_stack (GEN_INT (args_size.constant - unadjusted_args_size));
#endif
#endif
@@ -1608,34 +2184,7 @@ expand_call (exp, target, ignore)
if (argblock)
NO_DEFER_POP;
- /* Get the function to call, in the form of RTL. */
- if (fndecl)
- {
- /* If this is the first use of the function, see if we need to
- make an external definition for it. */
- if (! TREE_USED (fndecl))
- {
- assemble_external (fndecl);
- TREE_USED (fndecl) = 1;
- }
-
- /* Get a SYMBOL_REF rtx for the function address. */
- funexp = XEXP (DECL_RTL (fndecl), 0);
- }
- else
- /* Generate an rtx (probably a pseudo-register) for the address. */
- {
- push_temp_slots ();
- funexp = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
- pop_temp_slots (); /* FUNEXP can't be BLKmode */
-
- /* Check the function is executable. */
- if (flag_check_memory_usage)
- emit_library_call (chkr_check_exec_libfunc, 1,
- VOIDmode, 1,
- funexp, ptr_mode);
- emit_queue ();
- }
+ funexp = rtx_for_function_call (fndecl, exp);
/* Figure out the register where the value, if any, will come back. */
valreg = 0;
@@ -1651,115 +2200,16 @@ expand_call (exp, target, ignore)
/* Precompute all register parameters. It isn't safe to compute anything
once we have started filling any specific hard regs. */
- reg_parm_seen = 0;
- for (i = 0; i < num_actuals; i++)
- if (args[i].reg != 0 && ! args[i].pass_on_stack)
- {
- reg_parm_seen = 1;
-
- if (args[i].value == 0)
- {
- push_temp_slots ();
- args[i].value = expand_expr (args[i].tree_value, NULL_RTX,
- VOIDmode, 0);
- preserve_temp_slots (args[i].value);
- pop_temp_slots ();
-
- /* ANSI doesn't require a sequence point here,
- but PCC has one, so this will avoid some problems. */
- emit_queue ();
- }
-
- /* If we are to promote the function arg to a wider mode,
- do it now. */
-
- if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value)))
- args[i].value
- = convert_modes (args[i].mode,
- TYPE_MODE (TREE_TYPE (args[i].tree_value)),
- args[i].value, args[i].unsignedp);
-
- /* If the value is expensive, and we are inside an appropriately
- short loop, put the value into a pseudo and then put the pseudo
- into the hard reg.
-
- For small register classes, also do this if this call uses
- register parameters. This is to avoid reload conflicts while
- loading the parameters registers. */
-
- if ((! (GET_CODE (args[i].value) == REG
- || (GET_CODE (args[i].value) == SUBREG
- && GET_CODE (SUBREG_REG (args[i].value)) == REG)))
- && args[i].mode != BLKmode
- && rtx_cost (args[i].value, SET) > 2
- && ((SMALL_REGISTER_CLASSES && reg_parm_seen)
- || preserve_subexpressions_p ()))
- args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
- }
+ precompute_register_parameters (num_actuals, args, &reg_parm_seen);
#if defined(ACCUMULATE_OUTGOING_ARGS) && defined(REG_PARM_STACK_SPACE)
- /* The argument list is the property of the called routine and it
- may clobber it. If the fixed area has been used for previous
- parameters, we must save and restore it.
-
- Here we compute the boundary of the that needs to be saved, if any. */
-
-#ifdef ARGS_GROW_DOWNWARD
- for (i = 0; i < reg_parm_stack_space + 1; i++)
-#else
- for (i = 0; i < reg_parm_stack_space; i++)
-#endif
- {
- if (i >= highest_outgoing_arg_in_use
- || stack_usage_map[i] == 0)
- continue;
-
- if (low_to_save == -1)
- low_to_save = i;
-
- high_to_save = i;
- }
-
- if (low_to_save >= 0)
- {
- int num_to_save = high_to_save - low_to_save + 1;
- enum machine_mode save_mode
- = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
- rtx stack_area;
-
- /* If we don't have the required alignment, must do this in BLKmode. */
- if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode),
- BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
- save_mode = BLKmode;
-
-#ifdef ARGS_GROW_DOWNWARD
- stack_area = gen_rtx_MEM (save_mode,
- memory_address (save_mode,
- plus_constant (argblock,
- - high_to_save)));
-#else
- stack_area = gen_rtx_MEM (save_mode,
- memory_address (save_mode,
- plus_constant (argblock,
- low_to_save)));
-#endif
- if (save_mode == BLKmode)
- {
- save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- MEM_IN_STRUCT_P (save_area) = 0;
- emit_block_move (validize_mem (save_area), stack_area,
- GEN_INT (num_to_save),
- PARM_BOUNDARY / BITS_PER_UNIT);
- }
- else
- {
- save_area = gen_reg_rtx (save_mode);
- emit_move_insn (save_area, stack_area);
- }
- }
+ /* Save the fixed argument area if it's part of the caller's frame and
+ is clobbered by argument setup for this call. */
+ save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
+ &low_to_save, &high_to_save);
#endif
-
+
/* Now store (and compute if necessary) all non-register parms.
These come before register parms, since they can require block-moves,
@@ -1770,75 +2220,14 @@ expand_call (exp, target, ignore)
for (i = 0; i < num_actuals; i++)
if (args[i].reg == 0 || args[i].pass_on_stack)
store_one_arg (&args[i], argblock, may_be_alloca,
- args_size.var != 0, fndecl, reg_parm_stack_space);
+ args_size.var != 0, reg_parm_stack_space);
/* If we have a parm that is passed in registers but not in memory
and whose alignment does not permit a direct copy into registers,
make a group of pseudos that correspond to each register that we
will later fill. */
-
if (STRICT_ALIGNMENT)
- for (i = 0; i < num_actuals; i++)
- if (args[i].reg != 0 && ! args[i].pass_on_stack
- && args[i].mode == BLKmode
- && (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
- < MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
- {
- int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
- int big_endian_correction = 0;
-
- args[i].n_aligned_regs
- = args[i].partial ? args[i].partial
- : (bytes + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
-
- args[i].aligned_regs = (rtx *) alloca (sizeof (rtx)
- * args[i].n_aligned_regs);
-
- /* Structures smaller than a word are aligned to the least
- significant byte (to the right). On a BYTES_BIG_ENDIAN machine,
- this means we must skip the empty high order bytes when
- calculating the bit offset. */
- if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
- big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
-
- for (j = 0; j < args[i].n_aligned_regs; j++)
- {
- rtx reg = gen_reg_rtx (word_mode);
- rtx word = operand_subword_force (args[i].value, j, BLKmode);
- int bitsize = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
- int bitpos;
-
- args[i].aligned_regs[j] = reg;
-
- /* Clobber REG and move each partword into it. Ensure we don't
- go past the end of the structure. Note that the loop below
- works because we've already verified that padding
- and endianness are compatible.
-
- We use to emit a clobber here but that doesn't let later
- passes optimize the instructions we emit. By storing 0 into
- the register later passes know the first AND to zero out the
- bitfield being set in the register is unnecessary. The store
- of 0 will be deleted as will at least the first AND. */
-
- emit_move_insn (reg, const0_rtx);
-
- for (bitpos = 0;
- bitpos < BITS_PER_WORD && bytes > 0;
- bitpos += bitsize, bytes -= bitsize / BITS_PER_UNIT)
- {
- int xbitpos = bitpos + big_endian_correction;
-
- store_bit_field (reg, bitsize, xbitpos, word_mode,
- extract_bit_field (word, bitsize, bitpos, 1,
- NULL_RTX, word_mode,
- word_mode,
- bitsize / BITS_PER_UNIT,
- BITS_PER_WORD),
- bitsize / BITS_PER_UNIT, BITS_PER_WORD);
- }
- }
- }
+ store_unaligned_arguments_into_pseudos (args, num_actuals);
/* Now store any partially-in-registers parm.
This is the last place a block-move can happen. */
@@ -1846,15 +2235,14 @@ expand_call (exp, target, ignore)
for (i = 0; i < num_actuals; i++)
if (args[i].partial != 0 && ! args[i].pass_on_stack)
store_one_arg (&args[i], argblock, may_be_alloca,
- args_size.var != 0, fndecl, reg_parm_stack_space);
+ args_size.var != 0, reg_parm_stack_space);
#ifndef PUSH_ARGS_REVERSED
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
/* If we pushed args in forward order, perform stack alignment
after pushing the last arg. */
if (argblock == 0)
- anti_adjust_stack (GEN_INT (args_size.constant
- - original_args_size.constant));
+ anti_adjust_stack (GEN_INT (args_size.constant - unadjusted_args_size));
#endif
#endif
@@ -1875,10 +2263,10 @@ expand_call (exp, target, ignore)
NULL_RTX)));
/* Mark the memory for the aggregate as write-only. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1,
VOIDmode, 3,
- structure_value_addr, ptr_mode,
+ structure_value_addr, Pmode,
GEN_INT (struct_value_size), TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
@@ -1889,76 +2277,7 @@ expand_call (exp, target, ignore)
funexp = prepare_call_address (funexp, fndecl, &call_fusage, reg_parm_seen);
- /* Now do the register loads required for any wholly-register parms or any
- parms which are passed both on the stack and in a register. Their
- expressions were already evaluated.
-
- Mark all register-parms as living through the call, putting these USE
- insns in the CALL_INSN_FUNCTION_USAGE field. */
-
-#ifdef LOAD_ARGS_REVERSED
- for (i = num_actuals - 1; i >= 0; i--)
-#else
- for (i = 0; i < num_actuals; i++)
-#endif
- {
- rtx reg = args[i].reg;
- int partial = args[i].partial;
- int nregs;
-
- if (reg)
- {
- /* Set to non-negative if must move a word at a time, even if just
- one word (e.g, partial == 1 && mode == DFmode). Set to -1 if
- we just use a normal move insn. This value can be zero if the
- argument is a zero size structure with no fields. */
- nregs = (partial ? partial
- : (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
- ? ((int_size_in_bytes (TREE_TYPE (args[i].tree_value))
- + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
- : -1));
-
- /* Handle calls that pass values in multiple non-contiguous
- locations. The Irix 6 ABI has examples of this. */
-
- if (GET_CODE (reg) == PARALLEL)
- {
- emit_group_load (reg, args[i].value,
- int_size_in_bytes (TREE_TYPE (args[i].tree_value)),
- (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
- / BITS_PER_UNIT));
- }
-
- /* If simple case, just do move. If normal partial, store_one_arg
- has already loaded the register for us. In all other cases,
- load the register(s) from memory. */
-
- else if (nregs == -1)
- emit_move_insn (reg, args[i].value);
-
- /* If we have pre-computed the values to put in the registers in
- the case of non-aligned structures, copy them in now. */
-
- else if (args[i].n_aligned_regs != 0)
- for (j = 0; j < args[i].n_aligned_regs; j++)
- emit_move_insn (gen_rtx_REG (word_mode, REGNO (reg) + j),
- args[i].aligned_regs[j]);
-
- else if (partial == 0 || args[i].pass_on_stack)
- move_block_to_reg (REGNO (reg),
- validize_mem (args[i].value), nregs,
- args[i].mode);
-
- /* Handle calls that pass values in multiple non-contiguous
- locations. The Irix 6 ABI has examples of this. */
- if (GET_CODE (reg) == PARALLEL)
- use_group_regs (&call_fusage, reg);
- else if (nregs == -1)
- use_reg (&call_fusage, reg);
- else
- use_regs (&call_fusage, REGNO (reg), nregs == 0 ? 1 : nregs);
- }
- }
+ load_register_parameters (args, num_actuals, &call_fusage);
/* Perform postincrements before actually calling the function. */
emit_queue ();
@@ -1966,7 +2285,8 @@ expand_call (exp, target, ignore)
/* All arguments and registers used for the call must be set up by now! */
/* Generate the actual call instruction. */
- emit_call_1 (funexp, fndecl, funtype, args_size.constant, struct_value_size,
+ emit_call_1 (funexp, fndecl, funtype, unadjusted_args_size,
+ args_size.constant, struct_value_size,
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
valreg, old_inhibit_defer_pop, call_fusage, is_const);
@@ -2078,7 +2398,8 @@ expand_call (exp, target, ignore)
target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
memory_address (TYPE_MODE (TREE_TYPE (exp)),
structure_value_addr));
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
+ MEM_SET_IN_STRUCT_P (target,
+ AGGREGATE_TYPE_P (TREE_TYPE (exp)));
}
}
else if (pcc_struct_value)
@@ -2088,7 +2409,7 @@ expand_call (exp, target, ignore)
never use this value more than once in one expression. */
target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
copy_to_reg (valreg));
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
+ MEM_SET_IN_STRUCT_P (target, AGGREGATE_TYPE_P (TREE_TYPE (exp)));
}
/* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */
@@ -2099,7 +2420,7 @@ expand_call (exp, target, ignore)
if (target == 0)
{
target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), bytes, 0);
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
+ MEM_SET_IN_STRUCT_P (target, AGGREGATE_TYPE_P (TREE_TYPE (exp)));
preserve_temp_slots (target);
}
@@ -2116,75 +2437,7 @@ expand_call (exp, target, ignore)
when function inlining is being done. */
emit_move_insn (target, valreg);
else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
- {
- /* Some machines (the PA for example) want to return all small
- structures in registers regardless of the structure's alignment.
-
- Deal with them explicitly by copying from the return registers
- into the target MEM locations. */
- int bytes = int_size_in_bytes (TREE_TYPE (exp));
- rtx src = NULL, dst = NULL;
- int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (exp)), BITS_PER_WORD);
- int bitpos, xbitpos, big_endian_correction = 0;
-
- if (target == 0)
- {
- target = assign_stack_temp (BLKmode, bytes, 0);
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
- preserve_temp_slots (target);
- }
-
- /* This code assumes valreg is at least a full word. If it isn't,
- copy it into a new pseudo which is a full word. */
- if (GET_MODE (valreg) != BLKmode
- && GET_MODE_SIZE (GET_MODE (valreg)) < UNITS_PER_WORD)
- valreg = convert_to_mode (word_mode, valreg,
- TREE_UNSIGNED (TREE_TYPE (exp)));
-
- /* Structures whose size is not a multiple of a word are aligned
- to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
- machine, this means we must skip the empty high order bytes when
- calculating the bit offset. */
- if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
- big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
- * BITS_PER_UNIT));
-
- /* Copy the structure BITSIZE bites at a time.
-
- We could probably emit more efficient code for machines
- which do not use strict alignment, but it doesn't seem
- worth the effort at the current time. */
- for (bitpos = 0, xbitpos = big_endian_correction;
- bitpos < bytes * BITS_PER_UNIT;
- bitpos += bitsize, xbitpos += bitsize)
- {
-
- /* We need a new source operand each time xbitpos is on a
- word boundary and when xbitpos == big_endian_correction
- (the first time through). */
- if (xbitpos % BITS_PER_WORD == 0
- || xbitpos == big_endian_correction)
- src = operand_subword_force (valreg,
- xbitpos / BITS_PER_WORD,
- BLKmode);
-
- /* We need a new destination operand each time bitpos is on
- a word boundary. */
- if (bitpos % BITS_PER_WORD == 0)
- dst = operand_subword (target, bitpos / BITS_PER_WORD, 1, BLKmode);
-
- /* Use xbitpos for the source extraction (right justified) and
- xbitpos for the destination store (left justified). */
- store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
- extract_bit_field (src, bitsize,
- xbitpos % BITS_PER_WORD, 1,
- NULL_RTX, word_mode,
- word_mode,
- bitsize / BITS_PER_UNIT,
- BITS_PER_WORD),
- bitsize / BITS_PER_UNIT, BITS_PER_WORD);
- }
- }
+ target = copy_blkmode_from_reg (target, valreg, TREE_TYPE (exp));
else
target = copy_to_reg (valreg);
@@ -2227,31 +2480,10 @@ expand_call (exp, target, ignore)
{
#ifdef REG_PARM_STACK_SPACE
if (save_area)
- {
- enum machine_mode save_mode = GET_MODE (save_area);
-#ifdef ARGS_GROW_DOWNWARD
- rtx stack_area
- = gen_rtx_MEM (save_mode,
- memory_address (save_mode,
- plus_constant (argblock,
- - high_to_save)));
-#else
- rtx stack_area
- = gen_rtx_MEM (save_mode,
- memory_address (save_mode,
- plus_constant (argblock,
- low_to_save)));
+ restore_fixed_argument_area (save_area, argblock,
+ high_to_save, low_to_save);
#endif
- if (save_mode != BLKmode)
- emit_move_insn (stack_area, save_area);
- else
- emit_block_move (stack_area, validize_mem (save_area),
- GEN_INT (high_to_save - low_to_save + 1),
- PARM_BOUNDARY / BITS_PER_UNIT);
- }
-#endif
-
/* If we saved any argument areas, restore them. */
for (i = 0; i < num_actuals; i++)
if (args[i].save_area)
@@ -2279,11 +2511,16 @@ expand_call (exp, target, ignore)
Check for the handler slots since we might not have a save area
for non-local gotos. */
- if (may_be_alloca && nonlocal_goto_handler_slot != 0)
+ if (may_be_alloca && nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
pop_temp_slots ();
+ /* Free up storage we no longer need. */
+ for (i = 0; i < num_actuals; ++i)
+ if (args[i].aligned_regs)
+ free (args[i].aligned_regs);
+
return target;
}
@@ -2311,7 +2548,7 @@ void
emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
int nargs, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
rtx orgfun;
int no_queue;
enum machine_mode outmode;
@@ -2352,13 +2589,13 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
#ifdef MAYBE_REG_PARM_STACK_SPACE
reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
#else
- reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
+ reg_parm_stack_space = REG_PARM_STACK_SPACE ((tree) 0);
#endif
#endif
VA_START (p, nargs);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
orgfun = va_arg (p, rtx);
no_queue = va_arg (p, int);
outmode = va_arg (p, enum machine_mode);
@@ -2465,7 +2702,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
assemble_external_libcall (fun);
original_args_size = args_size;
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
args_size.constant = (((args_size.constant + (STACK_BYTES - 1))
/ STACK_BYTES) * STACK_BYTES);
#endif
@@ -2533,7 +2770,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
#endif
#ifdef PUSH_ARGS_REVERSED
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
/* If we push args individually in reverse order, perform stack alignment
before the first push (the last arg). */
if (argblock == 0)
@@ -2599,7 +2836,6 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
if (save_mode == BLKmode)
{
save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- MEM_IN_STRUCT_P (save_area) = 0;
emit_block_move (validize_mem (save_area), stack_area,
GEN_INT (num_to_save),
PARM_BOUNDARY / BITS_PER_UNIT);
@@ -2678,7 +2914,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
}
#ifndef PUSH_ARGS_REVERSED
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
/* If we pushed args in forward order, perform stack alignment
after pushing the last arg. */
if (argblock == 0)
@@ -2735,7 +2971,7 @@ emit_library_call VPROTO((rtx orgfun, int no_queue, enum machine_mode outmode,
get_identifier (XSTR (orgfun, 0)),
build_function_type (outmode == VOIDmode ? void_type_node
: type_for_mode (outmode, 0), NULL_TREE),
- args_size.constant, 0,
+ original_args_size.constant, args_size.constant, 0,
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX,
old_inhibit_defer_pop + 1, call_fusage, no_queue);
@@ -2802,7 +3038,7 @@ rtx
emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
enum machine_mode outmode, int nargs, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
rtx orgfun;
rtx value;
int no_queue;
@@ -2851,13 +3087,13 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
#ifdef MAYBE_REG_PARM_STACK_SPACE
reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
#else
- reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
+ reg_parm_stack_space = REG_PARM_STACK_SPACE ((tree) 0);
#endif
#endif
VA_START (p, nargs);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
orgfun = va_arg (p, rtx);
value = va_arg (p, rtx);
no_queue = va_arg (p, int);
@@ -3029,7 +3265,7 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
assemble_external_libcall (fun);
original_args_size = args_size;
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
args_size.constant = (((args_size.constant + (STACK_BYTES - 1))
/ STACK_BYTES) * STACK_BYTES);
#endif
@@ -3097,7 +3333,7 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
#endif
#ifdef PUSH_ARGS_REVERSED
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
/* If we push args individually in reverse order, perform stack alignment
before the first push (the last arg). */
if (argblock == 0)
@@ -3163,7 +3399,6 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
if (save_mode == BLKmode)
{
save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- MEM_IN_STRUCT_P (save_area) = 0;
emit_block_move (validize_mem (save_area), stack_area,
GEN_INT (num_to_save),
PARM_BOUNDARY / BITS_PER_UNIT);
@@ -3243,7 +3478,7 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
}
#ifndef PUSH_ARGS_REVERSED
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
/* If we pushed args in forward order, perform stack alignment
after pushing the last arg. */
if (argblock == 0)
@@ -3309,7 +3544,8 @@ emit_library_call_value VPROTO((rtx orgfun, rtx value, int no_queue,
emit_call_1 (fun,
get_identifier (XSTR (orgfun, 0)),
build_function_type (type_for_mode (outmode, 0), NULL_TREE),
- args_size.constant, struct_value_size,
+ original_args_size.constant, args_size.constant,
+ struct_value_size,
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
mem_value == 0 ? hard_libcall_value (outmode) : NULL_RTX,
old_inhibit_defer_pop + 1, call_fusage, is_const);
@@ -3436,13 +3672,12 @@ target_for_arg (type, size, args_addr, offset)
FNDECL is the declaration of the function we are calling. */
static void
-store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
+store_one_arg (arg, argblock, may_be_alloca, variable_size,
reg_parm_stack_space)
struct arg_data *arg;
rtx argblock;
int may_be_alloca;
- int variable_size;
- tree fndecl;
+ int variable_size ATTRIBUTE_UNUSED;
int reg_parm_stack_space;
{
register tree pval = arg->tree_value;
@@ -3504,8 +3739,9 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
{
arg->save_area = assign_stack_temp (BLKmode,
arg->size.constant, 0);
- MEM_IN_STRUCT_P (arg->save_area)
- = AGGREGATE_TYPE_P (TREE_TYPE (arg->tree_value));
+ MEM_SET_IN_STRUCT_P (arg->save_area,
+ AGGREGATE_TYPE_P (TREE_TYPE
+ (arg->tree_value)));
preserve_temp_slots (arg->save_area);
emit_block_move (validize_mem (arg->save_area), stack_area,
GEN_INT (arg->size.constant),
@@ -3518,6 +3754,14 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
}
}
}
+
+ /* Now that we have saved any slots that will be overwritten by this
+ store, mark all slots this store will use. We must do this before
+ we actually expand the argument since the expansion itself may
+ trigger library calls which might need to use the same stack slot. */
+ if (argblock && ! variable_size && arg->stack)
+ for (i = lower_bound; i < upper_bound; i++)
+ stack_usage_map[i] = 1;
#endif
/* If this isn't going to be placed on both the stack and in registers,
@@ -3587,15 +3831,13 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
if (arg->value == arg->stack)
{
- /* If the value is already in the stack slot, we are done. */
- if (flag_check_memory_usage && GET_CODE (arg->stack) == MEM)
+ /* If the value is already in the stack slot, we are done moving
+ data. */
+ if (current_function_check_memory_usage && GET_CODE (arg->stack) == MEM)
{
- if (arg->mode == BLKmode)
- abort ();
-
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- XEXP (arg->stack, 0), ptr_mode,
- GEN_INT (GET_MODE_SIZE (arg->mode)),
+ XEXP (arg->stack, 0), Pmode,
+ ARGS_SIZE_RTX (arg->size),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));
@@ -3695,11 +3937,4 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
preserve_temp_slots (NULL_RTX);
free_temp_slots ();
pop_temp_slots ();
-
-#ifdef ACCUMULATE_OUTGOING_ARGS
- /* Now mark the segment we just used. */
- if (argblock && ! variable_size && arg->stack)
- for (i = lower_bound; i < upper_bound; i++)
- stack_usage_map[i] = 1;
-#endif
}
diff --git a/contrib/gcc/cccp.c b/contrib/gcc/cccp.c
index 2e87c36..6e2d519 100644
--- a/contrib/gcc/cccp.c
+++ b/contrib/gcc/cccp.c
@@ -1,5 +1,5 @@
/* C Compatible Compiler Preprocessor (CCCP)
- Copyright (C) 1986, 87, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1986, 87, 89, 92-98, 1999 Free Software Foundation, Inc.
Written by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -19,21 +19,8 @@ Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
-#ifdef __STDC__
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
-
-#define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n)
-
-#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
-#define PRINTF_PROTO_2(ARGS) PRINTF_PROTO(ARGS, 2, 3)
-#define PRINTF_PROTO_3(ARGS) PRINTF_PROTO(ARGS, 3, 4)
-#define PRINTF_PROTO_4(ARGS) PRINTF_PROTO(ARGS, 4, 5)
#include "system.h"
-#include <sys/stat.h>
#include <signal.h>
#ifdef HAVE_SYS_RESOURCE_H
@@ -42,11 +29,17 @@ Boston, MA 02111-1307, USA. */
typedef unsigned char U_CHAR;
-#include "gansidecl.h"
#include "pcp.h"
+#include "intl.h"
+#include "prefix.h"
+
+#ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
+#include <locale.h>
+#endif /* MULTIBYTE_CHARS */
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
#ifndef STANDARD_INCLUDE_DIR
@@ -58,6 +51,11 @@ typedef unsigned char U_CHAR;
# define PATH_SEPARATOR ':'
#endif
+/* By default, a slash separates directory names. */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+#endif
+
/* By default, the suffix for object files is ".o". */
#ifdef OBJECT_SUFFIX
# define HAVE_OBJECT_SUFFIX
@@ -85,43 +83,11 @@ static int hack_vms_include_specification ();
#endif /* VMS */
/* Windows does not natively support inodes, and neither does MSDOS. */
-#if (defined (_WIN32) && ! defined (CYGWIN32)) || defined (__MSDOS__)
+#if (defined (_WIN32) && ! defined (__CYGWIN__) && ! defined (_UWIN)) \
+ || defined (__MSDOS__)
#define INO_T_EQ(a, b) 0
#endif
-#undef MIN
-#undef MAX
-#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-
-/* Find the largest host integer type and set its size and type.
- Watch out: on some crazy hosts `long' is shorter than `int'. */
-
-#ifndef HOST_WIDE_INT
-# if HAVE_INTTYPES_H
-# include <inttypes.h>
-# define HOST_WIDE_INT intmax_t
-# else
-# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
-# define HOST_WIDE_INT int
-# else
-# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
-# define HOST_WIDE_INT long
-# else
-# define HOST_WIDE_INT long long
-# endif
-# endif
-# endif
-#endif
-
-#ifndef S_ISREG
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
#ifndef INO_T_EQ
#define INO_T_EQ(a, b) ((a) == (b))
#endif
@@ -137,9 +103,8 @@ static int hack_vms_include_specification ();
/* External declarations. */
extern char *version_string;
-extern char *update_path PROTO((char *, char *));
-HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
-HOST_WIDE_INT parse_c_expression PROTO((char *, int));
+HOST_WIDEST_INT parse_escape PROTO((char **, HOST_WIDEST_INT));
+HOST_WIDEST_INT parse_c_expression PROTO((char *, int));
/* Name under which this program was invoked. */
@@ -294,6 +259,10 @@ int traditional;
int c89;
+/* Nonzero for the 199x C Standard. */
+
+int c9x;
+
/* Nonzero causes output not to be done,
but directives such as #define that have side effects
are still obeyed. */
@@ -414,49 +383,49 @@ static struct default_include {
int cxx_aware; /* Includes in this directory don't need to
be wrapped in extern "C" when compiling
C++. */
+ int included; /* Set if the directory is acceptable. */
} include_defaults_array[]
#ifdef INCLUDE_DEFAULTS
= INCLUDE_DEFAULTS;
#else
= {
/* Pick up GNU C++ specific include files. */
- { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
- { OLD_GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 },
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0 },
#ifdef CROSS_COMPILE
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
- { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+ { GCC_INCLUDE_DIR, "GCC", 0, 0, 0 },
/* For cross-compilation, this dir name is generated
automatically in Makefile.in. */
- { CROSS_INCLUDE_DIR, "GCC", 0, 0 },
+ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 },
#ifdef TOOL_INCLUDE_DIR
/* This is another place that the target system's headers might be. */
- { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0, 0 },
#endif
#else /* not CROSS_COMPILE */
#ifdef LOCAL_INCLUDE_DIR
/* This should be /usr/local/include and should come before
the fixincludes-fixed header files. */
- { LOCAL_INCLUDE_DIR, 0, 0, 1 },
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 0 },
#endif
#ifdef TOOL_INCLUDE_DIR
/* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
- { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0, 0 },
#endif
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
- { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+ { GCC_INCLUDE_DIR, "GCC", 0, 0, 0 },
/* Some systems have an extra dir of include files. */
#ifdef SYSTEM_INCLUDE_DIR
- { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
+ { SYSTEM_INCLUDE_DIR, 0, 0, 0, 0 },
#endif
#ifndef STANDARD_INCLUDE_COMPONENT
#define STANDARD_INCLUDE_COMPONENT 0
#endif
- { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
+ { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 0 },
#endif /* not CROSS_COMPILE */
- { 0, 0, 0, 0 }
+ { 0, 0, 0, 0, 0 }
};
#endif /* no INCLUDE_DEFAULTS */
@@ -614,6 +583,11 @@ union hashval {
static char rest_extension[] = "...";
#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
+/* This is the implicit parameter name when using variable number of
+ parameters for macros using the ISO C 9x extension. */
+static char va_args_name[] = "__VA_ARGS__";
+#define VA_ARGS_NAME_LENGTH (sizeof (va_args_name) - 1)
+
/* The structure of a node in the hash table. The hash table
has entries for all tokens defined by #define directives (type T_MACRO),
plus some special tokens like __LINE__ (these each have their own
@@ -689,13 +663,6 @@ static HASHNODE *hashtab[HASHSIZE];
#define HASHSTEP(old, c) ((old << 2) + c)
#define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
-/* Symbols to predefine. */
-
-#ifdef CPP_PREDEFINES
-static char *predefs = CPP_PREDEFINES;
-#else
-static char *predefs = "";
-#endif
/* We let tm.h override the types used here, to handle trivial differences
such as the choice of unsigned int or long unsigned int for size_t.
@@ -728,6 +695,8 @@ char * wchar_type = WCHAR_TYPE;
#ifndef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
#endif
+char * user_label_prefix = USER_LABEL_PREFIX;
+#undef USER_LABEL_PREFIX
/* The string value for __REGISTER_PREFIX__ */
@@ -856,8 +825,6 @@ U_CHAR is_idstart[256];
static U_CHAR is_hor_space[256];
/* table to tell if c is horizontal or vertical space. */
U_CHAR is_space[256];
-/* names of some characters */
-static char *char_name[256];
#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
@@ -867,6 +834,10 @@ static int errors = 0; /* Error counter for exit code */
/* Name of output file, for error messages. */
static char *out_fname;
+/* Nonzero to ignore \ in string constants. Use to treat #line 1 "A:\file.h
+ as a non-form feed. If you want it to be a form feed, you must use
+ # 1 "\f". */
+static int ignore_escape_flag = 1;
/* Stack of conditionals currently in progress
(including both successful and failing conditionals). */
@@ -903,7 +874,7 @@ static int ignore_srcdir;
static int safe_read PROTO((int, char *, int));
static void safe_write PROTO((int, char *, int));
-static void eprint_string PROTO((char *, size_t));
+static void eprint_string PROTO((const char *, size_t));
int main PROTO((int, char **));
@@ -943,14 +914,14 @@ static void record_control_macro PROTO((struct include_file *, U_CHAR *));
static char *check_precompiled PROTO((int, struct stat *, char *, char **));
static int check_preconditions PROTO((char *));
-static void pcfinclude PROTO((U_CHAR *, U_CHAR *, U_CHAR *, FILE_BUF *));
+static void pcfinclude PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
static void pcstring_used PROTO((HASHNODE *));
static void write_output PROTO((void));
static void pass_thru_directive PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *));
static MACRODEF create_definition PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
-static int check_macro_name PROTO((U_CHAR *, char *));
+static int check_macro_name PROTO((U_CHAR *, int));
static int compare_defs PROTO((DEFINITION *, DEFINITION *));
static int comp_def_part PROTO((int, U_CHAR *, int, U_CHAR *, int, int));
@@ -968,7 +939,7 @@ static void delete_assertion PROTO((ASSERTION_HASHNODE *));
static void do_once PROTO((void));
-static HOST_WIDE_INT eval_if_expression PROTO((U_CHAR *, int));
+static HOST_WIDEST_INT eval_if_expression PROTO((U_CHAR *, int));
static void conditional_skip PROTO((FILE_BUF *, int, enum node_type, U_CHAR *, FILE_BUF *));
static void skip_if_group PROTO((FILE_BUF *, int, FILE_BUF *));
static void validate_else PROTO((U_CHAR *, U_CHAR *));
@@ -985,7 +956,7 @@ static void output_line_directive PROTO((FILE_BUF *, FILE_BUF *, int, enum file_
static void macroexpand PROTO((HASHNODE *, FILE_BUF *));
struct argdata;
-static char *macarg PROTO((struct argdata *, int));
+static int macarg PROTO((struct argdata *, int));
static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, struct hashnode *, int *, int *, int *, int));
@@ -994,18 +965,21 @@ static int discard_comments PROTO((U_CHAR *, int, int));
static int change_newlines PROTO((U_CHAR *, int));
static char *my_strerror PROTO((int));
-void error PRINTF_PROTO_1((char *, ...));
-static void verror PROTO((char *, va_list));
+static void notice PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+static void vnotice PROTO((const char *, va_list));
+void error PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void verror PROTO((const char *, va_list));
static void error_from_errno PROTO((char *));
-void warning PRINTF_PROTO_1((char *, ...));
-static void vwarning PROTO((char *, va_list));
-static void error_with_line PRINTF_PROTO_2((int, char *, ...));
-static void verror_with_line PROTO((int, char *, va_list));
-static void vwarning_with_line PROTO((int, char *, va_list));
-static void warning_with_line PRINTF_PROTO_2((int, char *, ...));
-void pedwarn PRINTF_PROTO_1((char *, ...));
-void pedwarn_with_line PRINTF_PROTO_2((int, char *, ...));
-static void pedwarn_with_file_and_line PRINTF_PROTO_4((char *, size_t, int, char *, ...));
+void warning PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+static void vwarning PROTO((const char *, va_list));
+static void error_with_line PVPROTO((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
+static void verror_with_line PROTO((int, const char *, va_list));
+static void vwarning_with_line PROTO((int, const char *, va_list));
+static void warning_with_line PVPROTO((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
+void pedwarn PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void pedwarn_with_line PVPROTO((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
+static void pedwarn_with_file_and_line PVPROTO((const char *, size_t, int, const char *, ...)) ATTRIBUTE_PRINTF_4;
+static void pedwarn_strange_white_space PROTO((int));
static void print_containing_files PROTO((void));
@@ -1025,28 +999,24 @@ static void dump_arg_n PROTO((DEFINITION *, int, FILE *));
static void initialize_char_syntax PROTO((void));
static void initialize_builtins PROTO((FILE_BUF *, FILE_BUF *));
-static void make_definition PROTO((char *, FILE_BUF *));
+static void make_definition PROTO((char *));
static void make_undef PROTO((char *, FILE_BUF *));
-static void make_assertion PROTO((char *, char *));
+static void make_assertion PROTO((const char *, const char *));
-static struct file_name_list *new_include_prefix PROTO((struct file_name_list *, char *, char *, char *));
+static struct file_name_list *new_include_prefix PROTO((struct file_name_list *, const char *, const char *, const char *));
static void append_include_chain PROTO((struct file_name_list *, struct file_name_list *));
-static int quote_string_for_make PROTO((char *, char *));
-static void deps_output PROTO((char *, int));
+static int quote_string_for_make PROTO((char *, const char *));
+static void deps_output PROTO((const char *, int));
-static void fatal PRINTF_PROTO_1((char *, ...)) __attribute__ ((noreturn));
-void fancy_abort PROTO((void)) __attribute__ ((noreturn));
+void fatal PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
static void perror_with_name PROTO((char *));
-static void pfatal_with_name PROTO((char *)) __attribute__ ((noreturn));
-static void pipe_closed PROTO((int)) __attribute__ ((noreturn));
-
-static void memory_full PROTO((void)) __attribute__ ((noreturn));
-GENERIC_PTR xmalloc PROTO((size_t));
-static GENERIC_PTR xrealloc PROTO((GENERIC_PTR, size_t));
-static GENERIC_PTR xcalloc PROTO((size_t, size_t));
-static char *savestring PROTO((char *));
+static void pfatal_with_name PROTO((char *)) ATTRIBUTE_NORETURN;
+static void pipe_closed PROTO((int)) ATTRIBUTE_NORETURN;
+
+static void memory_full PROTO((void)) ATTRIBUTE_NORETURN;
static void print_help PROTO((void));
/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
@@ -1128,7 +1098,7 @@ safe_write (desc, ptr, len)
static void
eprint_string (string, length)
- char *string;
+ const char *string;
size_t length;
{
size_t segment_length;
@@ -1167,12 +1137,15 @@ print_help ()
printf (" -traditional Follow K&R pre-processor behaviour\n");
printf (" -trigraphs Support ANSI C trigraphs\n");
printf (" -lang-c Assume that the input sources are in C\n");
- printf (" -lang-c89 Assume that the input sources are in C89\n");
+ printf (" -lang-c89 Assume that the input is C89; depricated\n");
printf (" -lang-c++ Assume that the input sources are in C++\n");
printf (" -lang-objc Assume that the input sources are in ObjectiveC\n");
printf (" -lang-objc++ Assume that the input sources are in ObjectiveC++\n");
printf (" -lang-asm Assume that the input sources are in assembler\n");
printf (" -lang-chill Assume that the input sources are in Chill\n");
+ printf (" -std=<std name> Specify the conformance standard; one of:\n");
+ printf (" gnu89, gnu9x, c89, c9x, iso9899:1990,\n");
+ printf (" iso9899:199409, iso9899:199x\n");
printf (" -+ Allow parsing of C++ style features\n");
printf (" -w Inhibit warning messages\n");
printf (" -Wtrigraphs Warn if trigraphs are encountered\n");
@@ -1180,10 +1153,10 @@ print_help ()
printf (" -Wcomment{s} Warn if one comment starts inside another\n");
printf (" -Wno-comment{s} Do not warn about comments\n");
printf (" -Wtraditional Warn if a macro argument is/would be turned into\n");
- printf (" a string if -tradtional is specified\n");
+ printf (" a string if -traditional is specified\n");
printf (" -Wno-traditional Do not warn about stringification\n");
printf (" -Wundef Warn if an undefined macro is used by #if\n");
- printf (" -Wno-undef Do not warn about testing udefined macros\n");
+ printf (" -Wno-undef Do not warn about testing undefined macros\n");
printf (" -Wimport Warn about the use of the #import directive\n");
printf (" -Wno-import Do not warn about the use of #import\n");
printf (" -Werror Treat all warnings as errors\n");
@@ -1224,17 +1197,17 @@ main (argc, argv)
char *cp;
int f, i;
FILE_BUF *fp;
- char **pend_files = (char **) xmalloc (argc * sizeof (char *));
- char **pend_defs = (char **) xmalloc (argc * sizeof (char *));
- char **pend_undefs = (char **) xmalloc (argc * sizeof (char *));
- char **pend_assertions = (char **) xmalloc (argc * sizeof (char *));
- char **pend_includes = (char **) xmalloc (argc * sizeof (char *));
+
+ char **pend_files;
+ char **pend_defs;
+ char **pend_undefs;
+ char **pend_assertions;
+ char **pend_includes;
/* Record the option used with each element of pend_assertions.
This is preparation for supporting more than one option for making
an assertion. */
- char **pend_assertion_options = (char **) xmalloc (argc * sizeof (char *));
- int inhibit_predefs = 0;
+ char **pend_assertion_options;
int no_standard_includes = 0;
int no_standard_cplusplus_includes = 0;
int missing_newline = 0;
@@ -1271,13 +1244,19 @@ main (argc, argv)
signal (SIGPIPE, pipe_closed);
#endif
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
progname = base_name (argv[0]);
#ifdef VMS
{
/* Remove extension from PROGNAME. */
char *p;
- char *s = progname = savestring (progname);
+ char *s = progname = xstrdup (progname);
if ((p = rindex (s, ';')) != 0) *p = '\0'; /* strip version number */
if ((p = rindex (s, '.')) != 0 /* strip type iff ".exe" */
@@ -1289,6 +1268,16 @@ main (argc, argv)
}
#endif
+ /* Do not invoke xmalloc before this point, since locale and
+ progname need to be set first, in case a diagnostic is issued. */
+
+ pend_files = (char **) xmalloc (argc * sizeof (char *));
+ pend_defs = (char **) xmalloc (argc * sizeof (char *));
+ pend_undefs = (char **) xmalloc (argc * sizeof (char *));
+ pend_assertions = (char **) xmalloc (argc * sizeof (char *));
+ pend_includes = (char **) xmalloc (argc * sizeof (char *));
+ pend_assertion_options = (char **) xmalloc (argc * sizeof (char *));
+
in_fname = NULL;
out_fname = NULL;
@@ -1308,6 +1297,12 @@ main (argc, argv)
bzero ((char *) pend_assertions, argc * sizeof (char *));
bzero ((char *) pend_includes, argc * sizeof (char *));
+#ifdef MULTIBYTE_CHARS
+ /* Change to the native locale for multibyte conversions. */
+ setlocale (LC_CTYPE, "");
+ literal_codeset = getenv ("LANG");
+#endif
+
/* Process switches and find input file name. */
for (i = 1; i < argc; i++) {
@@ -1373,7 +1368,7 @@ main (argc, argv)
if (include_prefix != 0)
prefix = include_prefix;
else {
- prefix = savestring (GCC_INCLUDE_DIR);
+ prefix = xstrdup (GCC_INCLUDE_DIR);
/* Remove the `include' from /usr/local/lib/gcc.../include. */
if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
prefix[strlen (prefix) - 7] = 0;
@@ -1398,7 +1393,7 @@ main (argc, argv)
if (include_prefix != 0)
prefix = include_prefix;
else {
- prefix = savestring (GCC_INCLUDE_DIR);
+ prefix = xstrdup (GCC_INCLUDE_DIR);
/* Remove the `include' from /usr/local/lib/gcc.../include. */
if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
prefix[strlen (prefix) - 7] = 0;
@@ -1465,18 +1460,18 @@ main (argc, argv)
case 'l':
if (! strcmp (argv[i], "-lang-c"))
- cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 0;
- if (! strcmp (argv[i], "-lang-c89"))
- cplusplus = 0, cplusplus_comments = 0, c89 = 1, objc = 0;
- if (! strcmp (argv[i], "-lang-c++"))
- cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 0;
- if (! strcmp (argv[i], "-lang-objc"))
- cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 1;
- if (! strcmp (argv[i], "-lang-objc++"))
- cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 1;
- if (! strcmp (argv[i], "-lang-asm"))
+ cplusplus = 0, cplusplus_comments = 1, c89 = 0, c9x = 1, objc = 0;
+ else if (! strcmp (argv[i], "-lang-c89"))
+ cplusplus = 0, cplusplus_comments = 0, c89 = 1, c9x = 0, objc = 0;
+ else if (! strcmp (argv[i], "-lang-c++"))
+ cplusplus = 1, cplusplus_comments = 1, c89 = 0, c9x = 0, objc = 0;
+ else if (! strcmp (argv[i], "-lang-objc"))
+ cplusplus = 0, cplusplus_comments = 1, c89 = 0, c9x = 0, objc = 1;
+ else if (! strcmp (argv[i], "-lang-objc++"))
+ cplusplus = 1, cplusplus_comments = 1, c89 = 0, c9x = 0, objc = 1;
+ else if (! strcmp (argv[i], "-lang-asm"))
lang_asm = 1;
- if (! strcmp (argv[i], "-lint"))
+ else if (! strcmp (argv[i], "-lint"))
for_lint = 1;
break;
@@ -1484,6 +1479,18 @@ main (argc, argv)
cplusplus = 1, cplusplus_comments = 1;
break;
+ case 's':
+ if (!strcmp (argv[i], "-std=iso9899:1990")
+ || !strcmp (argv[i], "-std=iso9899:199409")
+ || !strcmp (argv[i], "-std=c89")
+ || !strcmp (argv[i], "-std=gnu89"))
+ cplusplus = 0, cplusplus_comments = 0, c89 = 1, c9x = 0, objc = 0;
+ else if (!strcmp (argv[i], "-std=iso9899:199x")
+ || !strcmp (argv[i], "-std=c9x")
+ || !strcmp (argv[i], "-std=gnu9x"))
+ cplusplus = 0, cplusplus_comments = 1, c89 = 0, c9x = 1, objc = 0;
+ break;
+
case 'w':
inhibit_warnings = 1;
break;
@@ -1524,6 +1531,13 @@ main (argc, argv)
}
break;
+ case 'f':
+ if (!strcmp (argv[i], "-fleading-underscore"))
+ user_label_prefix = "_";
+ else if (!strcmp (argv[i], "-fno-leading-underscore"))
+ user_label_prefix = "";
+ break;
+
case 'M':
/* The style of the choices here is a bit mixed.
The chosen scheme is a hybrid of keeping all options in one string
@@ -1604,7 +1618,7 @@ main (argc, argv)
break;
case 'v':
- fprintf (stderr, "GNU CPP version %s", version_string);
+ notice ("GNU CPP version %s", version_string);
#ifdef TARGET_VERSION
TARGET_VERSION;
#endif
@@ -1642,7 +1656,6 @@ main (argc, argv)
on the command line. That way we can get rid of any
that were passed automatically in from GCC. */
int j;
- inhibit_predefs = 1;
for (j = 0; j < i; j++)
pend_defs[j] = pend_assertions[j] = 0;
} else {
@@ -1710,12 +1723,6 @@ main (argc, argv)
remap = 1;
break;
- case 'u':
- /* Sun compiler passes undocumented switch "-undef".
- Let's assume it means to inhibit the predefined symbols. */
- inhibit_predefs = 1;
- break;
-
case '\0': /* JF handle '-' as file name meaning stdin or stdout */
if (in_fname == NULL) {
in_fname = "";
@@ -1737,7 +1744,7 @@ main (argc, argv)
/* Some people say that CPATH should replace the standard include dirs,
but that seems pointless: it comes before them, so it overrides them
anyway. */
- GET_ENVIRONMENT (cp, "CPATH");
+ GET_ENV_PATH_LIST (cp, "CPATH");
if (cp && ! no_standard_includes)
path_include (cp);
@@ -1766,135 +1773,6 @@ main (argc, argv)
and option processing. */
initialize_builtins (fp, &outbuf);
- /* Do standard #defines and assertions
- that identify system and machine type. */
-
- if (!inhibit_predefs) {
- char *p = (char *) alloca (strlen (predefs) + 1);
-
-#ifdef VMS
- struct dsc$descriptor_s lcl_name;
- struct item_list {
- unsigned short length; /* input length */
- unsigned short code; /* item code */
- unsigned long dptr; /* data ptr */
- unsigned long lptr; /* output length ptr */
- };
-
- unsigned long syi_length;
- char syi_data[16];
-
- struct item_list items[] = {
- { 16, SYI$_VERSION, 0, 0 },
- { 0, 0, 0, 0 }
- };
-
- items[0].dptr = (unsigned long)syi_data;
- items[0].lptr = (unsigned long)(&syi_length);
-
- if (SYS$GETSYIW (0, 0, 0, items, NULL, NULL, NULL, NULL) == SS$_NORMAL)
- {
- unsigned long vms_version_value;
- char *vers;
-
- vers = syi_data;
- vms_version_value = 0;
-
- if (*vers == 'V')
- vers++;
- if (ISDIGIT (*vers))
- {
- vms_version_value = (*vers - '0') * 10000000;
- }
- vers++;
- if (*vers == '.')
- {
- vers++;
- if (ISDIGIT (*vers))
- {
- vms_version_value += (*vers - '0') * 100000;
- }
- }
-
- if (vms_version_value > 0)
- {
- char versbuf[32];
-
- sprintf (versbuf, "__VMS_VER=%08ld", vms_version_value);
- if (debug_output)
- output_line_directive (fp, &outbuf, 0, same_file);
- make_definition (versbuf, &outbuf);
- }
- }
-#endif
-
- strcpy (p, predefs);
- while (*p) {
- char *q;
- while (*p == ' ' || *p == '\t')
- p++;
- /* Handle -D options. */
- if (p[0] == '-' && p[1] == 'D') {
- q = &p[2];
- while (*p && *p != ' ' && *p != '\t')
- p++;
- if (*p != 0)
- *p++= 0;
- if (debug_output)
- output_line_directive (fp, &outbuf, 0, same_file);
- make_definition (q, &outbuf);
- while (*p == ' ' || *p == '\t')
- p++;
- } else if (p[0] == '-' && p[1] == 'A') {
- /* Handle -A options (assertions). */
- char *assertion;
- char *past_name;
- char *value;
- char *past_value;
- char *termination;
- int save_char;
-
- assertion = &p[2];
- past_name = assertion;
- /* Locate end of name. */
- while (*past_name && *past_name != ' '
- && *past_name != '\t' && *past_name != '(')
- past_name++;
- /* Locate `(' at start of value. */
- value = past_name;
- while (*value && (*value == ' ' || *value == '\t'))
- value++;
- if (*value++ != '(')
- abort ();
- while (*value && (*value == ' ' || *value == '\t'))
- value++;
- past_value = value;
- /* Locate end of value. */
- while (*past_value && *past_value != ' '
- && *past_value != '\t' && *past_value != ')')
- past_value++;
- termination = past_value;
- while (*termination && (*termination == ' ' || *termination == '\t'))
- termination++;
- if (*termination++ != ')')
- abort ();
- if (*termination && *termination != ' ' && *termination != '\t')
- abort ();
- /* Temporarily null-terminate the value. */
- save_char = *termination;
- *termination = '\0';
- /* Install the assertion. */
- make_assertion ("-A", assertion);
- *termination = (char) save_char;
- p = termination;
- while (*p == ' ' || *p == '\t')
- p++;
- } else {
- abort ();
- }
- }
- }
-
/* Now handle the command line options. */
/* Do -U's, -D's and -A's in the order they were seen. */
@@ -1907,7 +1785,7 @@ main (argc, argv)
if (pend_defs[i]) {
if (debug_output)
output_line_directive (fp, &outbuf, 0, same_file);
- make_definition (pend_defs[i], &outbuf);
+ make_definition (pend_defs[i]);
}
if (pend_assertions[i])
make_assertion (pend_assertion_options[i], pend_assertions[i]);
@@ -1921,16 +1799,16 @@ main (argc, argv)
switch ((objc << 1) + cplusplus)
{
case 0:
- GET_ENVIRONMENT (epath, "C_INCLUDE_PATH");
+ GET_ENV_PATH_LIST (epath, "C_INCLUDE_PATH");
break;
case 1:
- GET_ENVIRONMENT (epath, "CPLUS_INCLUDE_PATH");
+ GET_ENV_PATH_LIST (epath, "CPLUS_INCLUDE_PATH");
break;
case 2:
- GET_ENVIRONMENT (epath, "OBJC_INCLUDE_PATH");
+ GET_ENV_PATH_LIST (epath, "OBJC_INCLUDE_PATH");
break;
case 3:
- GET_ENVIRONMENT (epath, "OBJCPLUS_INCLUDE_PATH");
+ GET_ENV_PATH_LIST (epath, "OBJCPLUS_INCLUDE_PATH");
break;
}
/* If the environment var for this language is set,
@@ -1953,7 +1831,7 @@ main (argc, argv)
if (c == PATH_SEPARATOR || !c) {
endp[-1] = 0;
include_defaults[num_dirs].fname
- = startp == endp ? "." : savestring (startp);
+ = startp == endp ? "." : xstrdup (startp);
endp[-1] = c;
include_defaults[num_dirs].component = 0;
include_defaults[num_dirs].cplusplus = cplusplus;
@@ -1979,7 +1857,7 @@ main (argc, argv)
if (!no_standard_includes) {
struct default_include *p = include_defaults;
char *specd_prefix = include_prefix;
- char *default_prefix = savestring (GCC_INCLUDE_DIR);
+ char *default_prefix = xstrdup (GCC_INCLUDE_DIR);
int default_len = 0;
/* Remove the `include' from /usr/local/lib/gcc.../include. */
if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
@@ -2003,6 +1881,7 @@ main (argc, argv)
append_include_chain (new, new);
if (first_system_include == 0)
first_system_include = new;
+ p->included = 1;
}
}
}
@@ -2018,6 +1897,7 @@ main (argc, argv)
append_include_chain (new, new);
if (first_system_include == 0)
first_system_include = new;
+ p->included = 1;
}
}
}
@@ -2031,10 +1911,10 @@ main (argc, argv)
/* With -v, print the list of dirs to search. */
if (verbose) {
struct file_name_list *p;
- fprintf (stderr, "#include \"...\" search starts here:\n");
+ notice ("#include \"...\" search starts here:\n");
for (p = include; p; p = p->next) {
if (p == first_bracket_include)
- fprintf (stderr, "#include <...> search starts here:\n");
+ notice ("#include <...> search starts here:\n");
if (!p->fname[0])
fprintf (stderr, " .\n");
else if (!strcmp (p->fname, "/") || !strcmp (p->fname, "//"))
@@ -2043,7 +1923,15 @@ main (argc, argv)
/* Omit trailing '/'. */
fprintf (stderr, " %.*s\n", (int) strlen (p->fname) - 1, p->fname);
}
- fprintf (stderr, "End of search list.\n");
+ notice ("End of search list.\n");
+ {
+ struct default_include * d;
+ notice ("The following default directories have been omitted from the search path:\n");
+ for (d = include_defaults; d->fname; d++)
+ if (! d->included)
+ fprintf (stderr, " %s\n", d->fname);
+ notice ("End of omitted list.\n");
+ }
}
/* -MG doesn't select the form of output and must be specified with one of
@@ -2528,7 +2416,7 @@ get_lintcmd (ibp, limit, argstart, arglen, cmdlen)
U_CHAR **argstart; /* point to command arg */
int *arglen, *cmdlen; /* how long they are */
{
- HOST_WIDE_INT linsize;
+ HOST_WIDEST_INT linsize;
register U_CHAR *numptr; /* temp for arg parsing */
*arglen = 0;
@@ -2774,9 +2662,27 @@ do { ip = &instack[indepth]; \
bp += 2;
else if (*bp == '/' && bp[1] == '*') {
bp += 2;
- while (!(*bp == '*' && bp[1] == '/'))
- bp++;
- bp += 2;
+ while (1)
+ {
+ if (*bp == '*')
+ {
+ if (bp[1] == '/')
+ {
+ bp += 2;
+ break;
+ }
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, limit - bp);
+ if (length > 1)
+ bp += (length - 1);
+#endif
+ }
+ bp++;
+ }
}
/* There is no point in trying to deal with C++ // comments here,
because if there is one, then this # must be part of the
@@ -2937,6 +2843,24 @@ do { ip = &instack[indepth]; \
if (ibp[-1] == c)
goto while2end;
break;
+#ifdef MULTIBYTE_CHARS
+ default:
+ {
+ int length;
+ --ibp;
+ length = local_mblen (ibp, limit - ibp);
+ if (length > 0)
+ {
+ --obp;
+ bcopy (ibp, obp, length);
+ obp += length;
+ ibp += length;
+ }
+ else
+ ++ibp;
+ }
+ break;
+#endif
}
}
while2end:
@@ -2965,24 +2889,39 @@ do { ip = &instack[indepth]; \
U_CHAR *before_bp = ibp;
while (++ibp < limit) {
- if (*ibp == '\n') {
- if (ibp[-1] != '\\') {
+ if (*ibp == '\n')
+ {
if (put_out_comments) {
bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
obp += ibp - before_bp;
}
break;
}
- if (warn_comments)
- warning ("multiline `//' comment");
- ++ip->lineno;
- /* Copy the newline into the output buffer, in order to
- avoid the pain of a #line every time a multiline comment
- is seen. */
- if (!put_out_comments)
- *obp++ = '\n';
- ++op->lineno;
- }
+ if (*ibp == '\\')
+ {
+ if (ibp + 1 < limit && ibp[1] == '\n')
+ {
+ if (warn_comments)
+ warning ("multiline `//' comment");
+ ++ip->lineno;
+ /* Copy the newline into the output buffer, in order to
+ avoid the pain of a #line every time a multiline comment
+ is seen. */
+ if (!put_out_comments)
+ *obp++ = '\n';
+ ++op->lineno;
+ ++ibp;
+ }
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ ibp += (length - 1);
+#endif
+ }
}
break;
}
@@ -3071,6 +3010,16 @@ do { ip = &instack[indepth]; \
goto limit_reached;
}
break;
+#ifdef MULTIBYTE_CHARS
+ default:
+ {
+ int length;
+ length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ ibp += (length - 1);
+ }
+ break;
+#endif
}
}
comment_end:
@@ -3433,11 +3382,27 @@ randomchar:
break;
}
}
- if (*ibp == '\n') {
+ else if (*ibp == '\n') {
/* Newline in a file. Count it. */
++ip->lineno;
++op->lineno;
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ {
+ if (put_out_comments)
+ {
+ bcopy (ibp, obp, length - 1);
+ obp += length - 1;
+ }
+ ibp += (length - 1);
+ }
+#endif
+ }
if (put_out_comments)
*obp++ = *ibp;
}
@@ -3448,9 +3413,34 @@ randomchar:
} else if (! traditional) {
*obp++ = ' ';
}
- for (ibp += 2; *ibp != '\n' || ibp[-1] == '\\'; ibp++)
- if (put_out_comments)
- *obp++ = *ibp;
+ for (ibp += 2; ; ibp++)
+ {
+ if (*ibp == '\n')
+ break;
+ if (*ibp == '\\' && ibp[1] == '\n')
+ {
+ if (put_out_comments)
+ *obp++ = *ibp++;
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ {
+ if (put_out_comments)
+ {
+ bcopy (ibp, obp, length - 1);
+ obp += length - 1;
+ }
+ ibp += (length - 1);
+ }
+#endif
+ }
+ if (put_out_comments)
+ *obp++ = *ibp;
+ }
} else
break;
}
@@ -3679,11 +3669,13 @@ handle_directive (ip, op)
/* Record where the directive started. do_xifdef needs this. */
directive_start = bp - 1;
+ ignore_escape_flag = 1;
+
/* Skip whitespace and \-newline. */
while (1) {
if (is_hor_space[*bp]) {
if (*bp != ' ' && *bp != '\t' && pedantic)
- pedwarn ("%s in preprocessing directive", char_name[*bp]);
+ pedwarn_strange_white_space (*bp);
bp++;
} else if (*bp == '/') {
if (bp[1] == '\\' && bp[2] == '\n')
@@ -3741,6 +3733,7 @@ handle_directive (ip, op)
pedwarn ("`#' followed by integer");
after_ident = ident;
kt = line_directive_table;
+ ignore_escape_flag = 0;
goto old_linenum;
}
@@ -3885,7 +3878,7 @@ handle_directive (ip, op)
case '\r':
case '\v':
if (pedantic)
- pedwarn ("%s in preprocessing directive", char_name[c]);
+ pedwarn_strange_white_space (c);
break;
case '\n':
@@ -3905,7 +3898,8 @@ handle_directive (ip, op)
/* If a directive should be copied through, and -C was given,
pass it through before removing comments. */
if (!no_output && put_out_comments
- && (kt->type == T_DEFINE ? dump_macros == dump_definitions
+ && ((kt->type == T_DEFINE || kt->type == T_UNDEF)
+ ? dump_macros == dump_definitions
: IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
: kt->type == T_PRAGMA)) {
int len;
@@ -3987,11 +3981,33 @@ handle_directive (ip, op)
case '\'':
case '\"':
{
+ int backslash_newlines_p;
+
register U_CHAR *bp1
= skip_quoted_string (xp - 1, bp, ip->lineno,
- NULL_PTR, NULL_PTR, NULL_PTR);
- while (xp != bp1)
- *cp++ = *xp++;
+ NULL_PTR, &backslash_newlines_p,
+ NULL_PTR);
+ if (backslash_newlines_p)
+ while (xp != bp1)
+ {
+ /* With something like:
+
+ #define X "a\
+ b"
+
+ we should still remove the backslash-newline
+ pair as part of phase two. */
+ if (xp[0] == '\\' && xp[1] == '\n')
+ xp += 2;
+ else
+ *cp++ = *xp++;
+ }
+ else
+ /* This is the same as the loop above, but taking
+ advantage of the fact that we know there are no
+ backslash-newline pairs. */
+ while (xp != bp1)
+ *cp++ = *xp++;
}
break;
@@ -4175,7 +4191,7 @@ special_symbol (hp, op)
break;
case T_USER_LABEL_PREFIX_TYPE:
- buf = USER_LABEL_PREFIX;
+ buf = user_label_prefix;
break;
case T_REGISTER_PREFIX_TYPE:
@@ -4326,16 +4342,18 @@ do_include (buf, limit, op, keyword)
&& !instack[indepth].system_header_p && !import_warning) {
import_warning = 1;
warning ("using `#import' is not recommended");
- fprintf (stderr, "The fact that a certain header file need not be processed more than once\n");
- fprintf (stderr, "should be indicated in the header file, not where it is used.\n");
- fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n");
- fprintf (stderr, " #ifndef _FOO_H_INCLUDED\n");
- fprintf (stderr, " #define _FOO_H_INCLUDED\n");
- fprintf (stderr, " ... <real contents of file> ...\n");
- fprintf (stderr, " #endif /* Not _FOO_H_INCLUDED */\n\n");
- fprintf (stderr, "Then users can use `#include' any number of times.\n");
- fprintf (stderr, "GNU C automatically avoids processing the file more than once\n");
- fprintf (stderr, "when it is equipped with such a conditional.\n");
+ notice ("The fact that a certain header file need not be processed more than once\n\
+should be indicated in the header file, not where it is used.\n\
+The best way to do this is with a conditional of this form:\n\
+\n\
+ #ifndef _FOO_H_INCLUDED\n\
+ #define _FOO_H_INCLUDED\n\
+ ... <real contents of file> ...\n\
+ #endif /* Not _FOO_H_INCLUDED */\n\
+\n\
+Then users can use `#include' any number of times.\n\
+GNU C automatically avoids processing the file more than once\n\
+when it is equipped with such a conditional.\n");
}
get_filename:
@@ -4707,8 +4725,7 @@ get_filename:
if (pcfbuf) {
pcfname = xmalloc (strlen (pcftry) + 1);
strcpy (pcfname, pcftry);
- pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) pcfbuflimit,
- (U_CHAR *) fname, op);
+ pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) fname, op);
}
else
finclude (f, inc, op, is_system_include (fname), searchptr);
@@ -4774,10 +4791,11 @@ static int
absolute_filename (filename)
char *filename;
{
-#if defined (__MSDOS__) || (defined (_WIN32) && !defined (__CYGWIN32__))
+#if defined (__MSDOS__) \
+ || (defined (_WIN32) && !defined (__CYGWIN__) && !defined (_UWIN))
if (ISALPHA (filename[0]) && filename[1] == ':') filename += 2;
#endif
-#if defined (__CYGWIN32__)
+#if defined (__CYGWIN__)
/* At present, any path that begins with a drive spec is absolute. */
if (ISALPHA (filename[0]) && filename[1] == ':') return 1;
#endif
@@ -4791,6 +4809,20 @@ absolute_filename (filename)
return 0;
}
+/* Returns whether or not a given character is a directory separator.
+ Used by simplify_filename. */
+static inline
+int
+is_dir_separator(ch)
+ char ch;
+{
+ return (ch == DIR_SEPARATOR)
+#if defined (DIR_SEPARATOR_2)
+ || (ch == DIR_SEPARATOR_2)
+#endif
+ ;
+}
+
/* Remove unnecessary characters from FILENAME in place,
to avoid unnecessary filename aliasing.
Return the length of the resulting string.
@@ -4808,55 +4840,59 @@ simplify_filename (filename)
char *to0;
/* Remove redundant initial /s. */
- if (*from == '/') {
- *to++ = '/';
- if (*++from == '/') {
- if (*++from == '/') {
- /* 3 or more initial /s are equivalent to 1 /. */
- while (*++from == '/')
- continue;
- } else {
- /* On some hosts // differs from /; Posix allows this. */
- static int slashslash_vs_slash;
- if (slashslash_vs_slash == 0) {
- struct stat s1, s2;
- slashslash_vs_slash = ((stat ("/", &s1) == 0 && stat ("//", &s2) == 0
- && INO_T_EQ (s1.st_ino, s2.st_ino)
- && s1.st_dev == s2.st_dev)
- ? 1 : -1);
- }
- if (slashslash_vs_slash < 0)
- *to++ = '/';
- }
+ if (is_dir_separator (*from))
+ {
+ *to++ = DIR_SEPARATOR;
+ if (is_dir_separator (*++from))
+ {
+ if (is_dir_separator (*++from))
+ {
+ /* 3 or more initial /s are equivalent to 1 /. */
+ while (is_dir_separator (*++from))
+ continue;
+ }
+ else
+ {
+ /* On some hosts // differs from /; Posix allows this. */
+ *to++ = DIR_SEPARATOR;
+ }
+ }
}
- }
+
to0 = to;
- for (;;) {
+ for (;;)
+ {
#ifndef VMS
- if (from[0] == '.' && from[1] == '/')
- from += 2;
- else
+ if (from[0] == '.' && from[1] == '/')
+ from += 2;
+ else
#endif
- {
- /* Copy this component and trailing /, if any. */
- while ((*to++ = *from++) != '/') {
- if (!to[-1]) {
- /* Trim . component at end of nonempty name. */
- to -= filename <= to - 3 && to[-3] == '/' && to[-2] == '.';
-
- /* Trim unnecessary trailing /s. */
- while (to0 < --to && to[-1] == '/')
- continue;
-
- *to = 0;
- return to - filename;
- }
- }
- }
+ {
+ /* Copy this component and trailing DIR_SEPARATOR, if any. */
+ while (!is_dir_separator (*to++ = *from++))
+ {
+ if (!to[-1])
+ {
+ /* Trim . component at end of nonempty name. */
+ to -= filename <= to - 3 && to[-3] == DIR_SEPARATOR && to[-2] == '.';
+
+ /* Trim unnecessary trailing /s. */
+ while (to0 < --to && to[-1] == DIR_SEPARATOR)
+ continue;
+
+ *to = 0;
+ return to - filename;
+ }
+ }
+#if defined(DIR_SEPARATOR_2)
+ /* Simplify to one directory separator. */
+ to[-1] = DIR_SEPARATOR;
+#endif
+ }
/* Skip /s after a /. */
- while (*from == '/')
+ while (is_dir_separator (*from))
from++;
}
}
@@ -4939,7 +4975,7 @@ read_name_map (dirname)
map_list_ptr = ((struct file_name_map_list *)
xmalloc (sizeof (struct file_name_map_list)));
- map_list_ptr->map_list_name = savestring (dirname);
+ map_list_ptr->map_list_name = xstrdup (dirname);
map_list_ptr->map_list_map = NULL;
dirlen = strlen (dirname);
@@ -5415,8 +5451,8 @@ check_preconditions (prec)
in. OP is the main output buffer. */
static void
-pcfinclude (buf, limit, name, op)
- U_CHAR *buf, *limit, *name;
+pcfinclude (buf, name, op)
+ U_CHAR *buf, *name;
FILE_BUF *op;
{
FILE_BUF tmpbuf;
@@ -5603,7 +5639,7 @@ pass_thru_directive (buf, limit, op, keyword)
FILE_BUF *op;
struct directive *keyword;
{
- register unsigned keyword_length = keyword->length;
+ register int keyword_length = keyword->length;
check_expand (op, 1 + keyword_length + (limit - buf));
*op->bufp++ = '#';
@@ -5667,7 +5703,7 @@ create_definition (buf, limit, op)
bp++;
symname = bp; /* remember where it starts */
- sym_length = check_macro_name (bp, "macro");
+ sym_length = check_macro_name (bp, 0);
bp += sym_length;
/* Lossage will occur if identifiers or control keywords are broken
@@ -5697,13 +5733,24 @@ create_definition (buf, limit, op)
rest_extension);
if (!is_idstart[*bp])
+ {
+ if (c9x && limit - bp > (long) REST_EXTENSION_LENGTH
+ && bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)
+ {
+ /* This is the ISO C 9x way to write macros with variable
+ number of arguments. */
+ rest_args = 1;
+ temp->rest_args = 1;
+ }
+ else
pedwarn ("invalid character in macro parameter name");
+ }
/* Find the end of the arg name. */
while (is_idchar[*bp]) {
bp++;
/* do we have a "special" rest-args extension here? */
- if (limit - bp > REST_EXTENSION_LENGTH
+ if (limit - bp > (long) REST_EXTENSION_LENGTH
&& bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
if (pedantic && !instack[indepth].system_header_p)
pedwarn ("ANSI C does not allow macro with variable arguments");
@@ -5712,6 +5759,13 @@ create_definition (buf, limit, op)
break;
}
}
+ if (bp == temp->name && rest_args == 1)
+ {
+ /* This is the ISO C 9x style. */
+ temp->name = (U_CHAR *) va_args_name;
+ temp->length = VA_ARGS_NAME_LENGTH;
+ }
+ else
temp->length = bp - temp->name;
if (rest_args == 1)
bp += REST_EXTENSION_LENGTH;
@@ -5725,7 +5779,9 @@ create_definition (buf, limit, op)
bp++;
SKIP_WHITE_SPACE (bp);
/* A comma at this point can only be followed by an identifier. */
- if (!is_idstart[*bp]) {
+ if (!is_idstart[*bp]
+ && !(c9x && limit - bp > (long) REST_EXTENSION_LENGTH
+ && bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)) {
error ("badly punctuated parameter list in `#define'");
goto nope;
}
@@ -5739,11 +5795,19 @@ create_definition (buf, limit, op)
for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
if (temp->length == otemp->length
- && bcmp (temp->name, otemp->name, temp->length) == 0) {
+ && bcmp (temp->name, otemp->name, temp->length) == 0)
+ {
error ("duplicate argument name `%.*s' in `#define'",
temp->length, temp->name);
goto nope;
}
+ if (rest_args == 0 && temp->length == VA_ARGS_NAME_LENGTH
+ && bcmp (temp->name, va_args_name, VA_ARGS_NAME_LENGTH) == 0)
+ {
+ error ("\
+reserved name `%s' used as argument name in `#define'", va_args_name);
+ goto nope;
+ }
}
}
@@ -5890,12 +5954,12 @@ nope:
}
/* Check a purported macro name SYMNAME, and yield its length.
- USAGE is the kind of name this is intended for. */
+ ASSERTION is nonzero if this is really for an assertion name. */
static int
-check_macro_name (symname, usage)
+check_macro_name (symname, assertion)
U_CHAR *symname;
- char *usage;
+ int assertion;
{
U_CHAR *p;
int sym_length;
@@ -5905,10 +5969,13 @@ check_macro_name (symname, usage)
sym_length = p - symname;
if (sym_length == 0
|| (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
- error ("invalid %s name", usage);
+ error (assertion ? "invalid assertion name" : "invalid macro name");
else if (!is_idstart[*symname]
|| (sym_length == 7 && ! bcmp (symname, "defined", 7)))
- error ("invalid %s name `%.*s'", usage, sym_length, symname);
+ error ((assertion
+ ? "invalid assertion name `%.*s'"
+ : "invalid macro name `%.*s'"),
+ sym_length, symname);
return sym_length;
}
@@ -6186,6 +6253,25 @@ collect_expansion (buf, end, nargs, arglist)
}
}
+#ifdef MULTIBYTE_CHARS
+ /* Handle multibyte characters inside string and character literals. */
+ if (expected_delimiter != '\0')
+ {
+ int length;
+ --p;
+ length = local_mblen (p, limit - p);
+ if (length > 1)
+ {
+ --exp_p;
+ bcopy (p, exp_p, length);
+ p += length;
+ exp_p += length;
+ continue;
+ }
+ ++p;
+ }
+#endif
+
/* Handle the start of a symbol. */
if (is_idchar[c] && nargs > 0) {
U_CHAR *id_beg = p - 1;
@@ -6315,7 +6401,7 @@ do_assert (buf, limit, op, keyword)
bp++;
symname = bp; /* remember where it starts */
- sym_length = check_macro_name (bp, "assertion");
+ sym_length = check_macro_name (bp, 1);
bp += sym_length;
/* #define doesn't do this, but we should. */
SKIP_WHITE_SPACE (bp);
@@ -6394,7 +6480,7 @@ do_unassert (buf, limit, op, keyword)
bp++;
symname = bp; /* remember where it starts */
- sym_length = check_macro_name (bp, "assertion");
+ sym_length = check_macro_name (bp, 1);
bp += sym_length;
/* #define doesn't do this, but we should. */
SKIP_WHITE_SPACE (bp);
@@ -6767,15 +6853,16 @@ do_line (buf, limit, op, keyword)
return 0;
case '\\':
- {
- char *bpc = (char *) bp;
- HOST_WIDE_INT c = parse_escape (&bpc, (HOST_WIDE_INT) (U_CHAR) (-1));
- bp = (U_CHAR *) bpc;
- if (c < 0)
- p--;
- else
- p[-1] = c;
- }
+ if (! ignore_escape_flag)
+ {
+ char *bpc = (char *) bp;
+ HOST_WIDEST_INT c = parse_escape (&bpc, (HOST_WIDEST_INT) (U_CHAR) (-1));
+ bp = (U_CHAR *) bpc;
+ if (c < 0)
+ p--;
+ else
+ p[-1] = c;
+ }
break;
case '\"':
@@ -6868,7 +6955,7 @@ do_undef (buf, limit, op, keyword)
pass_thru_directive (buf, limit, op, keyword);
SKIP_WHITE_SPACE (buf);
- sym_length = check_macro_name (buf, "macro");
+ sym_length = check_macro_name (buf, 0);
while ((hp = lookup (buf, sym_length, -1)) != NULL) {
/* If we are generating additional info for debugging (with -g) we
@@ -7082,7 +7169,7 @@ do_if (buf, limit, op, keyword)
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
- HOST_WIDE_INT value;
+ HOST_WIDEST_INT value;
FILE_BUF *ip = &instack[indepth];
value = eval_if_expression (buf, limit - buf);
@@ -7099,7 +7186,7 @@ do_elif (buf, limit, op, keyword)
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
- HOST_WIDE_INT value;
+ HOST_WIDEST_INT value;
FILE_BUF *ip = &instack[indepth];
if (if_stack == instack[indepth].if_stack) {
@@ -7137,14 +7224,14 @@ do_elif (buf, limit, op, keyword)
/* Evaluate a #if expression in BUF, of length LENGTH, then parse the
result as a C expression and return the value as an int. */
-static HOST_WIDE_INT
+static HOST_WIDEST_INT
eval_if_expression (buf, length)
U_CHAR *buf;
int length;
{
FILE_BUF temp_obuf;
HASHNODE *save_defined;
- HOST_WIDE_INT value;
+ HOST_WIDEST_INT value;
save_defined = install ((U_CHAR *) "defined", -1, T_SPEC_DEFINED,
NULL_PTR, -1);
@@ -7412,9 +7499,27 @@ skip_if_group (ip, any, op)
bp += 2;
else if (*bp == '/' && bp[1] == '*') {
bp += 2;
- while (!(*bp == '*' && bp[1] == '/'))
- bp++;
- bp += 2;
+ while (1)
+ {
+ if (*bp == '*')
+ {
+ if (bp[1] == '/')
+ {
+ bp += 2;
+ break;
+ }
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, endb - bp);
+ if (length > 1)
+ bp += (length - 1);
+#endif
+ }
+ bp++;
+ }
}
/* There is no point in trying to deal with C++ // comments here,
because if there is one, then this # must be part of the
@@ -7458,17 +7563,37 @@ skip_if_group (ip, any, op)
if (bp[1] == '/')
break;
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, endb - bp);
+ if (length > 1)
+ bp += (length - 1);
+#endif
+ }
}
bp += 2;
} else if (bp[1] == '/' && cplusplus_comments) {
for (bp += 2; ; bp++) {
- if (*bp == '\n') {
- if (bp[-1] != '\\')
- break;
- if (warn_comments)
- warning ("multiline `//' comment");
- ip->lineno++;
- }
+ if (*bp == '\n')
+ break;
+ if (*bp == '\\' && bp[1] == '\n')
+ {
+ if (warn_comments)
+ warning ("multiline `//' comment");
+ ip->lineno++;
+ bp++;
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, endb - bp);
+ if (length > 1)
+ bp += (length - 1);
+#endif
+ }
}
} else
break;
@@ -7764,6 +7889,15 @@ validate_else (p, limit)
break;
}
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (p, limit - p);
+ if (length > 1)
+ p += (length - 1);
+#endif
+ }
}
}
else if (cplusplus_comments && p[1] == '/')
@@ -7807,16 +7941,37 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
}
if (cplusplus_comments && bp[-1] == '/') {
for (; bp < limit; bp++) {
- if (*bp == '\n') {
- if (bp[-1] != '\\')
- break;
- if (!nowarn && warn_comments)
- warning ("multiline `//' comment");
- if (line_counter)
- ++*line_counter;
- if (op)
- ++op->lineno;
- }
+ if (*bp == '\n')
+ break;
+ if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
+ {
+ if (!nowarn && warn_comments)
+ warning ("multiline `//' comment");
+ if (line_counter)
+ ++*line_counter;
+ if (op)
+ {
+ ++op->lineno;
+ *op->bufp++ = *bp;
+ }
+ ++bp;
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, limit - bp);
+ if (length > 1)
+ {
+ if (op)
+ {
+ bcopy (bp, op->bufp, length - 1);
+ op->bufp += (length - 1);
+ }
+ bp += (length - 1);
+ }
+#endif
+ }
if (op)
*op->bufp++ = *bp;
}
@@ -7854,6 +8009,23 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
return bp;
}
break;
+#ifdef MULTIBYTE_CHARS
+ default:
+ {
+ int length;
+ bp--;
+ length = local_mblen (bp, limit - bp);
+ if (length <= 0)
+ length = 1;
+ if (op)
+ {
+ op->bufp--;
+ bcopy (bp, op->bufp, length);
+ op->bufp += length;
+ }
+ bp += length;
+ }
+#endif
}
}
@@ -7944,6 +8116,16 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
}
} else if (c == match)
break;
+#ifdef MULTIBYTE_CHARS
+ {
+ int length;
+ --bp;
+ length = local_mblen (bp, limit - bp);
+ if (length <= 0)
+ length = 1;
+ bp += length;
+ }
+#endif
}
return bp;
}
@@ -8171,7 +8353,7 @@ macroexpand (hp, op)
if (nargs >= 0) {
register int i;
struct argdata *args;
- char *parse_error = 0;
+ int parse_error = 0;
args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
@@ -8205,7 +8387,8 @@ macroexpand (hp, op)
else
parse_error = macarg (NULL_PTR, 0);
if (parse_error) {
- error_with_line (line_for_error (start_line), parse_error);
+ error_with_line (line_for_error (start_line),
+ "unterminated macro call");
break;
}
i++;
@@ -8381,9 +8564,23 @@ macroexpand (hp, op)
else {
if (c == '\\')
escaped = 1;
- if (in_string) {
+ else if (in_string) {
if (c == in_string)
in_string = 0;
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (arg->raw + i, arglen - i);
+ if (length > 1)
+ {
+ bcopy (arg->raw + i, xbuf + totlen, length);
+ i += length - 1;
+ totlen += length;
+ continue;
+ }
+#endif
+ }
} else if (c == '\"' || c == '\'')
in_string = c;
}
@@ -8536,7 +8733,7 @@ macroexpand (hp, op)
REST_ARGS is passed to macarg1 to make it absorb the rest of the args.
Return nonzero to indicate a syntax error. */
-static char *
+static int
macarg (argptr, rest_args)
register struct argdata *argptr;
int rest_args;
@@ -8545,7 +8742,7 @@ macarg (argptr, rest_args)
int paren = 0;
int newlines = 0;
int comments = 0;
- char *result = 0;
+ int result = 0;
/* Try to parse as much of the argument as exists at this
input stack level. */
@@ -8578,7 +8775,7 @@ macarg (argptr, rest_args)
while (bp == ip->buf + ip->length) {
if (instack[indepth].macro == 0) {
- result = "unterminated macro call";
+ result = 1;
break;
}
ip->macro->type = T_MACRO;
@@ -8717,17 +8914,39 @@ macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
break;
}
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, limit - bp);
+ if (length > 1)
+ bp += (length - 1);
+#endif
+ }
}
} else if (bp[1] == '/' && cplusplus_comments) {
*comments = 1;
for (bp += 2; bp < limit; bp++) {
if (*bp == '\n') {
++*newlines;
- if (bp[-1] != '\\')
- break;
- if (warn_comments)
- warning ("multiline `//' comment");
+ break;
}
+ if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
+ {
+ ++*newlines;
+ if (warn_comments)
+ warning ("multiline `//' comment");
+ ++bp;
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, limit - bp);
+ if (length > 1)
+ bp += (length - 1);
+#endif
+ }
}
}
break;
@@ -8751,6 +8970,15 @@ macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
if (quotec == '\'')
break;
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ length = local_mblen (bp, limit - bp);
+ if (length > 1)
+ bp += (length - 1);
+#endif
+ }
}
}
break;
@@ -8828,8 +9056,22 @@ discard_comments (start, length, newlines)
/* Comments are equivalent to spaces. */
obp[-1] = ' ';
ibp++;
- while (ibp < limit && (*ibp != '\n' || ibp[-1] == '\\'))
- ibp++;
+ while (ibp < limit)
+ {
+ if (*ibp == '\n')
+ break;
+ if (*ibp == '\\' && ibp + 1 < limit && ibp[1] == '\n')
+ ibp++;
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ ibp += (length - 1);
+#endif
+ }
+ ibp++;
+ }
break;
}
if (ibp[0] != '*' || ibp + 1 >= limit)
@@ -8849,6 +9091,14 @@ discard_comments (start, length, newlines)
break;
}
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ ibp += (length - 1);
+#endif
+ }
}
break;
@@ -8863,9 +9113,12 @@ discard_comments (start, length, newlines)
*obp++ = c = *ibp++;
if (c == quotec)
break;
- if (c == '\n' && quotec == '\'')
- break;
- if (c == '\\') {
+ if (c == '\n')
+ {
+ if (quotec == '\'')
+ break;
+ }
+ else if (c == '\\') {
if (ibp < limit && *ibp == '\n') {
ibp++;
obp--;
@@ -8876,6 +9129,23 @@ discard_comments (start, length, newlines)
*obp++ = *ibp++;
}
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ ibp--;
+ length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ {
+ obp--;
+ bcopy (ibp, obp, length);
+ ibp += length;
+ obp += length;
+ }
+ else
+ ibp++;
+#endif
+ }
}
}
break;
@@ -8925,10 +9195,32 @@ change_newlines (start, length)
int quotec = c;
while (ibp < limit) {
*obp++ = c = *ibp++;
- if (c == quotec && ibp[-2] != '\\')
- break;
- if (c == '\n' && quotec == '\'')
+ if (c == quotec)
break;
+ else if (c == '\\' && ibp < limit && *ibp == '\n')
+ *obp++ = *ibp++;
+ else if (c == '\n')
+ {
+ if (quotec == '\'')
+ break;
+ }
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ int length;
+ ibp--;
+ length = local_mblen (ibp, limit - ibp);
+ if (length > 1)
+ {
+ obp--;
+ bcopy (ibp, obp, length);
+ ibp += length;
+ obp += length;
+ }
+ else
+ ibp++;
+#endif
+ }
}
}
break;
@@ -8965,34 +9257,62 @@ my_strerror (errnum)
#endif
if (!result)
- result = "undocumented I/O error";
+ result = "errno = ?";
return result;
}
+/* notice - output message to stderr */
+
+static void
+notice VPROTO ((const char * msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ const char * msgid;
+#endif
+ va_list args;
+
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, const char *);
+#endif
+
+ vnotice (msgid, args);
+ va_end (args);
+}
+
+static void
+vnotice (msgid, args)
+ const char *msgid;
+ va_list args;
+{
+ vfprintf (stderr, _(msgid), args);
+}
+
/* error - print error message and increment count of errors. */
void
-error VPROTO ((char * msg, ...))
+error VPROTO ((const char * msgid, ...))
{
-#ifndef __STDC__
- char * msg;
+#ifndef ANSI_PROTOTYPES
+ const char * msgid;
#endif
va_list args;
- VA_START (args, msg);
+ VA_START (args, msgid);
-#ifndef __STDC__
- msg = va_arg (args, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, const char *);
#endif
-
- verror (msg, args);
+
+ verror (msgid, args);
va_end (args);
}
-static void
-verror (msg, args)
- char *msg;
+void
+verror (msgid, args)
+ const char *msgid;
va_list args;
{
int i;
@@ -9010,7 +9330,7 @@ verror (msg, args)
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d: ", ip->lineno);
}
- vfprintf (stderr, msg, args);
+ vnotice (msgid, args);
fprintf (stderr, "\n");
errors++;
}
@@ -9046,26 +9366,26 @@ error_from_errno (name)
/* Print error message but don't count it. */
void
-warning VPROTO ((char * msg, ...))
+warning VPROTO ((const char * msgid, ...))
{
-#ifndef __STDC__
- char * msg;
+#ifndef ANSI_PROTOTYPES
+ const char * msgid;
#endif
va_list args;
- VA_START (args, msg);
+ VA_START (args, msgid);
-#ifndef __STDC__
- msg = va_arg (args, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, const char *);
#endif
- vwarning (msg, args);
+ vwarning (msgid, args);
va_end (args);
}
static void
-vwarning (msg, args)
- char *msg;
+vwarning (msgid, args)
+ const char *msgid;
va_list args;
{
int i;
@@ -9089,35 +9409,36 @@ vwarning (msg, args)
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d: ", ip->lineno);
}
- fprintf (stderr, "warning: ");
- vfprintf (stderr, msg, args);
+ notice ("warning: ");
+ vnotice (msgid, args);
fprintf (stderr, "\n");
}
static void
-error_with_line VPROTO ((int line, char * msg, ...))
+error_with_line VPROTO ((int line, const char * msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
int line;
- char * msg;
+ const char * msgid;
#endif
va_list args;
- VA_START (args, msg);
+ VA_START (args, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
line = va_arg (args, int);
- msg = va_arg (args, char *);
+ msgid = va_arg (args, const char *);
#endif
- verror_with_line (line, msg, args);
+ verror_with_line (line, msgid, args);
va_end (args);
}
+
static void
-verror_with_line (line, msg, args)
+verror_with_line (line, msgid, args)
int line;
- char *msg;
+ const char *msgid;
va_list args;
{
int i;
@@ -9135,35 +9456,35 @@ verror_with_line (line, msg, args)
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d: ", line);
}
- vfprintf (stderr, msg, args);
+ vnotice (msgid, args);
fprintf (stderr, "\n");
errors++;
}
static void
-warning_with_line VPROTO ((int line, char * msg, ...))
+warning_with_line VPROTO ((int line, const char * msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
int line;
- char * msg;
+ const char * msgid;
#endif
va_list args;
- VA_START (args, msg);
+ VA_START (args, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
line = va_arg (args, int);
- msg = va_arg (args, char *);
+ msgid = va_arg (args, const char *);
#endif
- vwarning_with_line (line, msg, args);
+ vwarning_with_line (line, msgid, args);
va_end (args);
}
static void
-vwarning_with_line (line, msg, args)
+vwarning_with_line (line, msgid, args)
int line;
- char *msg;
+ const char *msgid;
va_list args;
{
int i;
@@ -9187,54 +9508,54 @@ vwarning_with_line (line, msg, args)
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, line ? ":%d: " : ": ", line);
}
- fprintf (stderr, "warning: ");
- vfprintf (stderr, msg, args);
+ notice ("warning: ");
+ vnotice (msgid, args);
fprintf (stderr, "\n");
}
/* Print an error message and maybe count it. */
void
-pedwarn VPROTO ((char * msg, ...))
+pedwarn VPROTO ((const char * msgid, ...))
{
-#ifndef __STDC__
- char * msg;
+#ifndef ANSI_PROTOTYPES
+ const char * msgid;
#endif
va_list args;
- VA_START (args, msg);
-
-#ifndef __STDC__
- msg = va_arg (args, char *);
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, const char *);
#endif
-
+
if (pedantic_errors)
- verror (msg, args);
+ verror (msgid, args);
else
- vwarning (msg, args);
+ vwarning (msgid, args);
va_end (args);
}
void
-pedwarn_with_line VPROTO ((int line, char * msg, ...))
+pedwarn_with_line VPROTO ((int line, const char * msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
int line;
- char * msg;
+ const char * msgid;
#endif
va_list args;
- VA_START (args, msg);
-
-#ifndef __STDC__
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
line = va_arg (args, int);
- msg = va_arg (args, char *);
+ msgid = va_arg (args, const char *);
#endif
-
+
if (pedantic_errors)
- verror_with_line (line, msg, args);
+ verror_with_line (line, msgid, args);
else
- vwarning_with_line (line, msg, args);
+ vwarning_with_line (line, msgid, args);
va_end (args);
}
@@ -9242,19 +9563,29 @@ pedwarn_with_line VPROTO ((int line, char * msg, ...))
giving specified file name and line number, not current. */
static void
-pedwarn_with_file_and_line VPROTO ((char *file, size_t file_len, int line,
- char * msg, ...))
+pedwarn_with_file_and_line VPROTO ((const char *file, size_t file_len, int line,
+ const char * msgid, ...))
{
-#ifndef __STDC__
- char *file;
+#ifndef ANSI_PROTOTYPES
+ const char *file;
size_t file_len;
int line;
- char * msg;
+ const char * msgid;
#endif
va_list args;
if (!pedantic_errors && inhibit_warnings)
return;
+
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ file = va_arg (args, const char *);
+ file_len = va_arg (args, size_t);
+ line = va_arg (args, int);
+ msgid = va_arg (args, const char *);
+#endif
+
if (file) {
eprint_string (file, file_len);
fprintf (stderr, ":%d: ", line);
@@ -9262,20 +9593,24 @@ pedwarn_with_file_and_line VPROTO ((char *file, size_t file_len, int line,
if (pedantic_errors)
errors++;
if (!pedantic_errors)
- fprintf (stderr, "warning: ");
- VA_START (args, msg);
-
-#ifndef __STDC__
- file = va_arg (args, char *);
- file_len = va_arg (args, size_t);
- line = va_arg (args, int);
- msg = va_arg (args, char *);
-#endif
-
- vfprintf (stderr, msg, args);
+ notice ("warning: ");
+ vnotice (msgid, args);
va_end (args);
fprintf (stderr, "\n");
}
+
+static void
+pedwarn_strange_white_space (ch)
+ int ch;
+{
+ switch (ch)
+ {
+ case '\f': pedwarn ("formfeed in preprocessing directive"); break;
+ case '\r': pedwarn ("carriage return in preprocessing directive"); break;
+ case '\v': pedwarn ("vertical tab in preprocessing directive"); break;
+ default: abort ();
+ }
+}
/* Print the file names and line numbers of the #include
directives which led to the current file. */
@@ -9308,12 +9643,11 @@ print_containing_files ()
ip = &instack[i];
if (first) {
first = 0;
- fprintf (stderr, "In file included");
+ notice ( "In file included from ");
} else {
- fprintf (stderr, ",\n ");
+ notice (",\n from ");
}
- fprintf (stderr, " from ");
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d", ip->lineno);
}
@@ -9751,10 +10085,6 @@ initialize_char_syntax ()
is_space['\f'] = 1;
is_space['\n'] = 1;
is_space['\r'] = 1;
-
- char_name['\v'] = "vertical tab";
- char_name['\f'] = "formfeed";
- char_name['\r'] = "carriage return";
}
/* Initialize the built-in macros. */
@@ -9788,8 +10118,6 @@ initialize_builtins (inp, outp)
install ((U_CHAR *) "__STDC__", -1, T_CONST, "1", -1);
install ((U_CHAR *) "__STDC_VERSION__", -1, T_CONST, "199409L", -1);
}
- if (objc)
- install ((U_CHAR *) "__OBJC__", -1, T_CONST, "1", -1);
/* This is supplied using a -D by the compiler driver
so that it is present only when truly compiling with GNU C. */
/* install ((U_CHAR *) "__GNUC__", -1, T_CONST, "2", -1); */
@@ -9870,9 +10198,8 @@ initialize_builtins (inp, outp)
*/
static void
-make_definition (str, op)
+make_definition (str)
char *str;
- FILE_BUF *op;
{
FILE_BUF *ip;
struct directive *kt;
@@ -9986,8 +10313,8 @@ make_undef (str, op)
static void
make_assertion (option, str)
- char *option;
- char *str;
+ const char *option;
+ const char *str;
{
FILE_BUF *ip;
struct directive *kt;
@@ -10040,10 +10367,6 @@ make_assertion (option, str)
--indepth;
}
-#ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
-#endif
-
/* The previous include prefix, if any, is PREV_FILE_NAME.
Translate any pathnames with COMPONENT.
Allocate a new include prefix whose name is the
@@ -10055,9 +10378,9 @@ make_assertion (option, str)
static struct file_name_list *
new_include_prefix (prev_file_name, component, prefix, name)
struct file_name_list *prev_file_name;
- char *component;
- char *prefix;
- char *name;
+ const char *component;
+ const char *prefix;
+ const char *name;
{
if (name == 0)
fatal ("Directory name missing after command line option");
@@ -10182,9 +10505,9 @@ append_include_chain (first, last)
static int
quote_string_for_make (dst, src)
char *dst;
- char *src;
+ const char *src;
{
- char *p = src;
+ const char *p = src;
int i = 0;
for (;;)
{
@@ -10201,7 +10524,7 @@ quote_string_for_make (dst, src)
preceded by 2N backslashes represents N backslashes at
the end of a file name; and backslashes in other
contexts should not be doubled. */
- char *q;
+ const char *q;
for (q = p - 1; src < q && q[-1] == '\\'; q--)
{
if (dst)
@@ -10244,7 +10567,7 @@ quote_string_for_make (dst, src)
static void
deps_output (string, spacer)
- char *string;
+ const char *string;
int spacer;
{
int size = quote_string_for_make ((char *) 0, string);
@@ -10282,22 +10605,21 @@ deps_output (string, spacer)
deps_buffer[deps_size] = 0;
}
-static void
-fatal VPROTO ((char * msg, ...))
+void
+fatal VPROTO ((const char * msgid, ...))
{
-#ifndef __STDC__
- char * msg;
+#ifndef ANSI_PROTOTYPES
+ const char * msgid;
#endif
va_list args;
fprintf (stderr, "%s: ", progname);
- VA_START (args, msg);
-
-#ifndef __STDC__
- msg = va_arg (args, char *);
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, const char *);
#endif
-
- vfprintf (stderr, msg, args);
+ vnotice (msgid, args);
va_end (args);
fprintf (stderr, "\n");
exit (FATAL_EXIT_CODE);
@@ -10348,47 +10670,50 @@ memory_full ()
fatal ("Memory exhausted.");
}
-
-GENERIC_PTR
+PTR
xmalloc (size)
- size_t size;
+ size_t size;
{
- register GENERIC_PTR ptr = (GENERIC_PTR) malloc (size);
+ register PTR ptr = (PTR) malloc (size);
if (!ptr)
memory_full ();
return ptr;
}
-static GENERIC_PTR
+PTR
xrealloc (old, size)
- GENERIC_PTR old;
- size_t size;
+ PTR old;
+ size_t size;
{
- register GENERIC_PTR ptr = (GENERIC_PTR) realloc (old, size);
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
if (!ptr)
memory_full ();
return ptr;
}
-static GENERIC_PTR
+PTR
xcalloc (number, size)
- size_t number, size;
+ size_t number, size;
{
register size_t total = number * size;
- register GENERIC_PTR ptr = (GENERIC_PTR) malloc (total);
+ register PTR ptr = (PTR) malloc (total);
if (!ptr)
memory_full ();
bzero (ptr, total);
return ptr;
}
-static char *
-savestring (input)
- char *input;
+char *
+xstrdup (input)
+ const char *input;
{
- size_t size = strlen (input);
- char *output = xmalloc (size + 1);
- strcpy (output, input);
+ register size_t len = strlen (input) + 1;
+ register char *output = xmalloc (len);
+ memcpy (output, input, len);
return output;
}
diff --git a/contrib/gcc/cexp.y b/contrib/gcc/cexp.y
index 6280aed..9364ac3 100644
--- a/contrib/gcc/cexp.y
+++ b/contrib/gcc/cexp.y
@@ -1,5 +1,5 @@
/* Parse C expressions for CCCP.
- Copyright (C) 1987, 1992, 94 - 97, 1998 Free Software Foundation.
+ Copyright (C) 1987, 92, 94-98, 1999 Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -26,25 +26,16 @@ Boston, MA 02111-1307, USA.
%{
#include "config.h"
-#ifdef __STDC__
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
-
-#define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n)
-
-#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
#include "system.h"
+#include "intl.h"
#include <setjmp.h>
/* #define YYDEBUG 1 */
#ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
#include <locale.h>
-#endif
-
-#include "gansidecl.h"
+#endif /* MULTIBYTE_CHARS */
typedef unsigned char U_CHAR;
@@ -56,44 +47,12 @@ struct arglist {
int argno;
};
-/* Find the largest host integer type and set its size and type.
- Watch out: on some crazy hosts `long' is shorter than `int'. */
-
-#ifndef HOST_WIDE_INT
-# if HAVE_INTTYPES_H
-# include <inttypes.h>
-# define HOST_WIDE_INT intmax_t
-# define unsigned_HOST_WIDE_INT uintmax_t
-# else
-# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
-# define HOST_WIDE_INT int
-# else
-# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
-# define HOST_WIDE_INT long
-# else
-# define HOST_WIDE_INT long long
-# endif
-# endif
-# endif
-#endif
-
-#ifndef unsigned_HOST_WIDE_INT
-#define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT
-#endif
-
-#ifndef CHAR_BIT
-#define CHAR_BIT 8
-#endif
-
-#ifndef HOST_BITS_PER_WIDE_INT
-#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
-#endif
-
-HOST_WIDE_INT parse_c_expression PROTO((char *, int));
+HOST_WIDEST_INT parse_c_expression PROTO((char *, int));
static int yylex PROTO((void));
-static void yyerror PROTO((char *)) __attribute__ ((noreturn));
-static HOST_WIDE_INT expression_value;
+static void yyerror PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+static HOST_WIDEST_INT expression_value;
#ifdef TEST_EXP_READER
static int expression_signedp;
#endif
@@ -154,13 +113,13 @@ extern int c89;
#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
#endif
-#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \
- ? (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
- : ~ (HOST_WIDE_INT) 0)
+#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
+ ? (~ (~ (HOST_WIDEST_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
+ : ~ (HOST_WIDEST_INT) 0)
-#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \
- ? ~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
- : ~ (HOST_WIDE_INT) 0)
+#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
+ ? ~ (~ (HOST_WIDEST_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
+ : ~ (HOST_WIDEST_INT) 0)
/* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
@@ -174,17 +133,17 @@ extern int c89;
struct constant;
-GENERIC_PTR xmalloc PROTO((size_t));
-HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
+HOST_WIDEST_INT parse_escape PROTO((char **, HOST_WIDEST_INT));
int check_assertion PROTO((U_CHAR *, int, int, struct arglist *));
struct hashnode *lookup PROTO((U_CHAR *, int, int));
-void error PRINTF_PROTO_1((char *, ...));
-void pedwarn PRINTF_PROTO_1((char *, ...));
-void warning PRINTF_PROTO_1((char *, ...));
+void error PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void verror PROTO((const char *, va_list));
+void pedwarn PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void warning PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
static int parse_number PROTO((int));
-static HOST_WIDE_INT left_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT));
-static HOST_WIDE_INT right_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT));
+static HOST_WIDEST_INT left_shift PROTO((struct constant *, unsigned HOST_WIDEST_INT));
+static HOST_WIDEST_INT right_shift PROTO((struct constant *, unsigned HOST_WIDEST_INT));
static void integer_overflow PROTO((void));
/* `signedp' values */
@@ -193,7 +152,7 @@ static void integer_overflow PROTO((void));
%}
%union {
- struct constant {HOST_WIDE_INT value; int signedp;} integer;
+ struct constant {HOST_WIDEST_INT value; int signedp;} integer;
struct name {U_CHAR *address; int length;} name;
struct arglist *keywords;
}
@@ -280,7 +239,7 @@ exp : exp '*' exp
integer_overflow ();
}
else
- $$.value = ((unsigned_HOST_WIDE_INT) $1.value
+ $$.value = ((unsigned HOST_WIDEST_INT) $1.value
* $3.value); }
| exp '/' exp
{ if ($3.value == 0)
@@ -297,7 +256,7 @@ exp : exp '*' exp
integer_overflow ();
}
else
- $$.value = ((unsigned_HOST_WIDE_INT) $1.value
+ $$.value = ((unsigned HOST_WIDEST_INT) $1.value
/ $3.value); }
| exp '%' exp
{ if ($3.value == 0)
@@ -310,7 +269,7 @@ exp : exp '*' exp
if ($$.signedp)
$$.value = $1.value % $3.value;
else
- $$.value = ((unsigned_HOST_WIDE_INT) $1.value
+ $$.value = ((unsigned HOST_WIDEST_INT) $1.value
% $3.value); }
| exp '+' exp
{ $$.value = $1.value + $3.value;
@@ -347,28 +306,28 @@ exp : exp '*' exp
if ($1.signedp & $3.signedp)
$$.value = $1.value <= $3.value;
else
- $$.value = ((unsigned_HOST_WIDE_INT) $1.value
+ $$.value = ((unsigned HOST_WIDEST_INT) $1.value
<= $3.value); }
| exp GEQ exp
{ $$.signedp = SIGNED;
if ($1.signedp & $3.signedp)
$$.value = $1.value >= $3.value;
else
- $$.value = ((unsigned_HOST_WIDE_INT) $1.value
+ $$.value = ((unsigned HOST_WIDEST_INT) $1.value
>= $3.value); }
| exp '<' exp
{ $$.signedp = SIGNED;
if ($1.signedp & $3.signedp)
$$.value = $1.value < $3.value;
else
- $$.value = ((unsigned_HOST_WIDE_INT) $1.value
+ $$.value = ((unsigned HOST_WIDEST_INT) $1.value
< $3.value); }
| exp '>' exp
{ $$.signedp = SIGNED;
if ($1.signedp & $3.signedp)
$$.value = $1.value > $3.value;
else
- $$.value = ((unsigned_HOST_WIDE_INT) $1.value
+ $$.value = ((unsigned HOST_WIDEST_INT) $1.value
> $3.value); }
| exp '&' exp
{ $$.value = $1.value & $3.value;
@@ -451,7 +410,7 @@ parse_number (olen)
{
register char *p = lexptr;
register int c;
- register unsigned_HOST_WIDE_INT n = 0, nd, max_over_base;
+ register unsigned HOST_WIDEST_INT n = 0, nd, max_over_base;
register int base = 10;
register int len = olen;
register int overflow = 0;
@@ -469,7 +428,7 @@ parse_number (olen)
}
}
- max_over_base = (unsigned_HOST_WIDE_INT) -1 / base;
+ max_over_base = (unsigned HOST_WIDEST_INT) -1 / base;
for (; len > 0; len--) {
c = *p++;
@@ -498,12 +457,9 @@ parse_number (olen)
else {
if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P')
yyerror ("Floating point numbers not allowed in #if expressions");
- else {
- char *buf = (char *) alloca (p - lexptr + 40);
- sprintf (buf, "missing white space after number `%.*s'",
+ else
+ yyerror ("missing white space after number `%.*s'",
(int) (p - lexptr - 1), lexptr);
- yyerror (buf);
- }
}
if (--len == 0)
@@ -527,7 +483,7 @@ parse_number (olen)
pedwarn ("integer constant out of range");
/* If too big to be signed, consider it unsigned. */
- if (((HOST_WIDE_INT) n & yylval.integer.signedp) < 0)
+ if (((HOST_WIDEST_INT) n & yylval.integer.signedp) < 0)
{
if (base == 10)
warning ("integer constant is so large that it is unsigned");
@@ -540,7 +496,7 @@ parse_number (olen)
}
struct token {
- char *operator;
+ const char *operator;
int token;
};
@@ -568,7 +524,7 @@ yylex ()
register unsigned char *tokstart;
register struct token *toktab;
int wide_flag;
- HOST_WIDE_INT mask;
+ HOST_WIDEST_INT mask;
retry:
@@ -580,11 +536,7 @@ yylex ()
if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
lexptr += 2;
if (toktab->token == ERROR)
- {
- char *buf = (char *) alloca (40);
- sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator);
- yyerror (buf);
- }
+ yyerror ("`%s' not allowed in operand of `#if'", toktab->operator);
return toktab->token;
}
@@ -639,25 +591,20 @@ yylex ()
handles multicharacter constants and wide characters.
It is mostly copied from c-lex.c. */
{
- register HOST_WIDE_INT result = 0;
+ register HOST_WIDEST_INT result = 0;
register int num_chars = 0;
+ int chars_seen = 0;
unsigned width = MAX_CHAR_TYPE_SIZE;
int max_chars;
- char *token_buffer;
-
- if (wide_flag)
- {
- width = MAX_WCHAR_TYPE_SIZE;
#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
+ int longest_char = local_mb_cur_max ();
+ char *token_buffer = (char *) alloca (longest_char);
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif
- }
- else
- max_chars = MAX_LONG_TYPE_SIZE / width;
- token_buffer = (char *) alloca (max_chars + 1);
+ max_chars = MAX_LONG_TYPE_SIZE / width;
+ if (wide_flag)
+ width = MAX_WCHAR_TYPE_SIZE;
while (1)
{
@@ -666,72 +613,108 @@ yylex ()
if (c == '\'' || c == EOF)
break;
+ ++chars_seen;
if (c == '\\')
{
c = parse_escape (&lexptr, mask);
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 1; i <= longest_char; ++i)
+ {
+ token_buffer[i - 1] = c;
+ char_len = local_mbtowc (& wc, token_buffer, i);
+ if (char_len != -1)
+ break;
+ c = *lexptr++;
+ }
+ if (char_len > 1)
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len < i)
+ lexptr--;
+ if (! wide_flag)
+ {
+ /* Merge character into result; ignore excess chars. */
+ for (i = 1; i <= char_len; ++i)
+ {
+ if (i > max_chars)
+ break;
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width)
+ | (token_buffer[i - 1]
+ & ((1 << width) - 1));
+ else
+ result = token_buffer[i - 1];
+ }
+ num_chars += char_len;
+ continue;
+ }
+ }
+ else
+ {
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ }
+ if (wide_flag)
+ c = wc;
+#endif /* ! MULTIBYTE_CHARS */
+ }
- num_chars++;
+ if (wide_flag)
+ {
+ if (chars_seen == 1) /* only keep the first one */
+ result = c;
+ continue;
+ }
/* Merge character into result; ignore excess chars. */
+ num_chars++;
if (num_chars <= max_chars)
{
- if (width < HOST_BITS_PER_WIDE_INT)
- result = (result << width) | c;
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width) | (c & ((1 << width) - 1));
else
result = c;
- token_buffer[num_chars - 1] = c;
}
}
- token_buffer[num_chars] = 0;
-
if (c != '\'')
error ("malformatted character constant");
- else if (num_chars == 0)
+ else if (chars_seen == 0)
error ("empty character constant");
else if (num_chars > max_chars)
{
num_chars = max_chars;
error ("character constant too long");
}
- else if (num_chars != 1 && ! traditional)
+ else if (chars_seen != 1 && ! traditional)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
if (! wide_flag)
{
int num_bits = num_chars * width;
-
- if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__",
+ if (num_bits == 0)
+ /* We already got an error; avoid invalid shift. */
+ yylval.integer.value = 0;
+ else if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__",
sizeof ("__CHAR_UNSIGNED__") - 1, -1)
|| ((result >> (num_bits - 1)) & 1) == 0)
yylval.integer.value
- = result & (~ (unsigned_HOST_WIDE_INT) 0
- >> (HOST_BITS_PER_WIDE_INT - num_bits));
+ = result & (~ (unsigned HOST_WIDEST_INT) 0
+ >> (HOST_BITS_PER_WIDEST_INT - num_bits));
else
yylval.integer.value
- = result | ~(~ (unsigned_HOST_WIDE_INT) 0
- >> (HOST_BITS_PER_WIDE_INT - num_bits));
+ = result | ~(~ (unsigned HOST_WIDEST_INT) 0
+ >> (HOST_BITS_PER_WIDEST_INT - num_bits));
}
else
{
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[0] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL_PTR, NULL_PTR, 0);
- if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
- result = wc;
- else
- pedwarn ("Ignoring invalid multibyte character");
- }
-#endif
yylval.integer.value = result;
}
}
@@ -854,10 +837,10 @@ yylex ()
If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */
-HOST_WIDE_INT
+HOST_WIDEST_INT
parse_escape (string_ptr, result_mask)
char **string_ptr;
- HOST_WIDE_INT result_mask;
+ HOST_WIDEST_INT result_mask;
{
register int c = *(*string_ptr)++;
switch (c)
@@ -896,7 +879,7 @@ parse_escape (string_ptr, result_mask)
case '6':
case '7':
{
- register HOST_WIDE_INT i = c - '0';
+ register HOST_WIDEST_INT i = c - '0';
register int count = 0;
while (++count < 3)
{
@@ -918,7 +901,7 @@ parse_escape (string_ptr, result_mask)
}
case 'x':
{
- register unsigned_HOST_WIDE_INT i = 0, overflow = 0;
+ register unsigned HOST_WIDEST_INT i = 0, overflow = 0;
register int digits_found = 0, digit;
for (;;)
{
@@ -953,46 +936,37 @@ parse_escape (string_ptr, result_mask)
}
static void
-yyerror (s)
- char *s;
-{
- error ("%s", s);
- skip_evaluation = 0;
- longjmp (parse_return_error, 1);
-}
-
-static void
integer_overflow ()
{
if (!skip_evaluation && pedantic)
pedwarn ("integer overflow in preprocessor expression");
}
-static HOST_WIDE_INT
+static HOST_WIDEST_INT
left_shift (a, b)
struct constant *a;
- unsigned_HOST_WIDE_INT b;
+ unsigned HOST_WIDEST_INT b;
{
/* It's unclear from the C standard whether shifts can overflow.
The following code ignores overflow; perhaps a C standard
interpretation ruling is needed. */
- if (b >= HOST_BITS_PER_WIDE_INT)
+ if (b >= HOST_BITS_PER_WIDEST_INT)
return 0;
else
- return (unsigned_HOST_WIDE_INT) a->value << b;
+ return (unsigned HOST_WIDEST_INT) a->value << b;
}
-static HOST_WIDE_INT
+static HOST_WIDEST_INT
right_shift (a, b)
struct constant *a;
- unsigned_HOST_WIDE_INT b;
+ unsigned HOST_WIDEST_INT b;
{
- if (b >= HOST_BITS_PER_WIDE_INT)
- return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0;
+ if (b >= HOST_BITS_PER_WIDEST_INT)
+ return a->signedp ? a->value >> (HOST_BITS_PER_WIDEST_INT - 1) : 0;
else if (a->signedp)
return a->value >> b;
else
- return (unsigned_HOST_WIDE_INT) a->value >> b;
+ return (unsigned HOST_WIDEST_INT) a->value >> b;
}
/* This page contains the entry point to this file. */
@@ -1005,7 +979,7 @@ right_shift (a, b)
We do not support C comments. They should be removed before
this function is called. */
-HOST_WIDE_INT
+HOST_WIDEST_INT
parse_c_expression (string, warn_undefined)
char *string;
int warn_undefined;
@@ -1027,6 +1001,27 @@ parse_c_expression (string, warn_undefined)
return expression_value; /* set by yyparse () */
}
+
+static void
+yyerror VPROTO ((const char * msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ const char * msgid;
+#endif
+ va_list args;
+
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, const char *);
+#endif
+
+ verror (msgid, args);
+ va_end (args);
+ skip_evaluation = 0;
+ longjmp (parse_return_error, 1);
+}
+
#ifdef TEST_EXP_READER
@@ -1036,10 +1031,11 @@ extern int yydebug;
int pedantic;
int traditional;
+int c89;
int main PROTO((int, char **));
static void initialize_random_junk PROTO((void));
-static void print_unsigned_host_wide_int PROTO((unsigned_HOST_WIDE_INT));
+static void print_unsigned_host_widest_int PROTO((unsigned HOST_WIDEST_INT));
/* Main program for testing purposes. */
int
@@ -1049,12 +1045,13 @@ main (argc, argv)
{
int n, c;
char buf[1024];
- unsigned_HOST_WIDE_INT u;
+ unsigned HOST_WIDEST_INT u;
pedantic = 1 < argc;
traditional = 2 < argc;
+ c89 = 3 < argc;
#if YYDEBUG
- yydebug = 3 < argc;
+ yydebug = 4 < argc;
#endif
initialize_random_junk ();
@@ -1067,7 +1064,7 @@ main (argc, argv)
break;
parse_c_expression (buf, 1);
printf ("parser returned ");
- u = (unsigned_HOST_WIDE_INT) expression_value;
+ u = (unsigned HOST_WIDEST_INT) expression_value;
if (expression_value < 0 && expression_signedp) {
u = -u;
printf ("-");
@@ -1075,7 +1072,7 @@ main (argc, argv)
if (u == 0)
printf ("0");
else
- print_unsigned_host_wide_int (u);
+ print_unsigned_host_widest_int (u);
if (! expression_signedp)
printf("u");
printf ("\n");
@@ -1085,11 +1082,11 @@ main (argc, argv)
}
static void
-print_unsigned_host_wide_int (u)
- unsigned_HOST_WIDE_INT u;
+print_unsigned_host_widest_int (u)
+ unsigned HOST_WIDEST_INT u;
{
if (u) {
- print_unsigned_host_wide_int (u / 10);
+ print_unsigned_host_widest_int (u / 10);
putchar ('0' + (int) (u % 10));
}
}
@@ -1137,65 +1134,66 @@ initialize_random_junk ()
}
void
-error VPROTO ((char * msg, ...))
+error VPROTO ((char * msgid, ...))
{
-#ifndef __STDC__
- char * msg;
+#ifndef ANSI_PROTOTYPES
+ char * msgid;
#endif
va_list args;
- VA_START (args, msg);
-
-#ifndef __STDC__
- msg = va_arg (args, char *);
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, char *);
#endif
-
+
fprintf (stderr, "error: ");
- vfprintf (stderr, msg, args);
+ vfprintf (stderr, _(msgid), args);
fprintf (stderr, "\n");
va_end (args);
}
void
-pedwarn VPROTO ((char * msg, ...))
+pedwarn VPROTO ((char * msgid, ...))
{
-#ifndef __STDC__
- char * msg;
+#ifndef ANSI_PROTOTYPES
+ char * msgid;
#endif
va_list args;
- VA_START (args, msg);
-
-#ifndef __STDC__
- msg = va_arg (args, char *);
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, char *);
#endif
-
+
fprintf (stderr, "pedwarn: ");
- vfprintf (stderr, msg, args);
+ vfprintf (stderr, _(msgid), args);
fprintf (stderr, "\n");
va_end (args);
}
void
-warning VPROTO ((char * msg, ...))
+warning VPROTO ((char * msgid, ...))
{
-#ifndef __STDC__
- char * msg;
+#ifndef ANSI_PROTOTYPES
+ char * msgid;
#endif
va_list args;
- VA_START (args, msg);
-
-#ifndef __STDC__
- msg = va_arg (args, char *);
+ VA_START (args, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (args, char *);
#endif
-
+
fprintf (stderr, "warning: ");
- vfprintf (stderr, msg, args);
+ vfprintf (stderr, _(msgid), args);
fprintf (stderr, "\n");
va_end (args);
}
+
int
check_assertion (name, sym_length, tokens_specified, tokens)
U_CHAR *name;
@@ -1215,10 +1213,10 @@ lookup (name, len, hash)
return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
}
-GENERIC_PTR
+PTR
xmalloc (size)
- size_t size;
+ size_t size;
{
- return (GENERIC_PTR) malloc (size);
+ return (PTR) malloc (size);
}
#endif
diff --git a/contrib/gcc/collect2.c b/contrib/gcc/collect2.c
index 4fcbe73..121ad39 100644
--- a/contrib/gcc/collect2.c
+++ b/contrib/gcc/collect2.c
@@ -1,6 +1,6 @@
/* Collect static initialization info into data structures that can be
traversed by C++ initialization and finalization routines.
- Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Chris Smith (csmith@convex.com).
Heavily modified by Michael Meissner (meissner@cygnus.com),
Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
@@ -28,38 +28,31 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include <signal.h>
-#include <sys/stat.h>
+
+#ifdef vfork /* Autoconf may define this to fork for us. */
+# define VFORK_STRING "fork"
+#else
+# define VFORK_STRING "vfork"
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+#ifdef VMS
+#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
+ lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
+#endif /* VMS */
#define COLLECT
+#include "collect2.h"
#include "demangle.h"
#include "obstack.h"
-#include "gansidecl.h"
-#ifdef __CYGWIN32__
-#include <process.h>
-#endif
+#include "intl.h"
/* Obstack allocation and deallocation routines. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-#ifdef USG
-#define vfork fork
-#endif
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(S) ((S) & 0x7f)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(S) (((S) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
-#endif
-
extern char *make_temp_file PROTO ((char *));
/* On certain systems, we have code that works by scanning the object file
@@ -137,7 +130,7 @@ extern char *make_temp_file PROTO ((char *));
/* Default flags to pass to nm. */
#ifndef NM_FLAGS
-#define NM_FLAGS "-p"
+#define NM_FLAGS "-n"
#endif
#endif /* OBJECT_FORMAT_NONE */
@@ -151,6 +144,9 @@ extern char *make_temp_file PROTO ((char *));
#define SYMBOL__MAIN __main
#endif
+/* This must match tree.h. */
+#define DEFAULT_INIT_PRIORITY 65535
+
#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES
#define SCAN_LIBRARIES
#endif
@@ -186,11 +182,6 @@ enum pass {
PASS_SECOND /* with constructors linked in */
};
-#ifndef NO_SYS_SIGLIST
-#ifndef SYS_SIGLIST_DECLARED
-extern char *sys_siglist[];
-#endif
-#endif
extern char *version_string;
int vflag; /* true if -v */
@@ -234,14 +225,16 @@ struct obstack temporary_obstack;
struct obstack permanent_obstack;
char * temporary_firstobj;
+/* Holds the return value of pexecute. */
+int pexecute_pid;
+
/* Defined in the automatically-generated underscore.c. */
extern int prepends_underscore;
-extern char *mktemp ();
extern FILE *fdopen ();
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
/* Structure to hold all the directories in which to search for files to
@@ -270,7 +263,13 @@ static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
static char *libexts[3] = {"a", "so", NULL}; /* possible library extentions */
#endif
+void error PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
+void fatal PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fatal_perror PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
static char *my_strerror PROTO((int));
+static const char *my_strsignal PROTO((int));
static void handler PROTO((int));
static int is_ctor_dtor PROTO((char *));
static char *find_a_file PROTO((struct path_prefix *, char *));
@@ -281,6 +280,8 @@ static void do_wait PROTO((char *));
static void fork_execute PROTO((char *, char **));
static void maybe_unlink PROTO((char *));
static void add_to_list PROTO((struct head *, char *));
+static int extract_init_priority PROTO((char *));
+static void sort_ids PROTO((struct head *));
static void write_list PROTO((FILE *, char *, struct id *));
#ifdef COLLECT_EXPORT_LIST
static void dump_list PROTO((FILE *, char *, struct id *));
@@ -302,10 +303,6 @@ static char *resolve_lib_name PROTO((char *));
static int use_import_list PROTO((char *));
static int ignore_library PROTO((char *));
#endif
-
-char *xcalloc ();
-char *xmalloc ();
-
#ifdef NO_DUP2
int
@@ -339,17 +336,38 @@ my_strerror (e)
#else
- static char buffer[30];
if (!e)
return "";
if (e > 0 && e < sys_nerr)
return sys_errlist[e];
- sprintf (buffer, "Unknown error %d", e);
- return buffer;
+ return "errno = ?";
#endif
}
+
+static const char *
+my_strsignal (s)
+ int s;
+{
+#ifdef HAVE_STRSIGNAL
+ return strsignal (s);
+#else
+ if (s >= 0 && s < NSIG)
+ {
+# ifdef NO_SYS_SIGLIST
+ static char buffer[30];
+
+ sprintf (buffer, "Unknown signal %d", s);
+ return buffer;
+# else
+ return sys_siglist[s];
+# endif
+ }
+ else
+ return NULL;
+#endif /* HAVE_STRSIGNAL */
+}
/* Delete tempfiles and exit function. */
@@ -384,41 +402,94 @@ collect_exit (status)
}
+/* Notify user of a non-error. */
+void
+notice VPROTO((char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, char *);
+#endif
+
+ vfprintf (stderr, _(msgid), ap);
+ va_end (ap);
+}
+
/* Die when sys call fails. */
void
-fatal_perror (string, arg1, arg2, arg3)
- char *string, *arg1, *arg2, *arg3;
+fatal_perror VPROTO((const char * msgid, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
+#endif
int e = errno;
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+#endif
fprintf (stderr, "collect2: ");
- fprintf (stderr, string, arg1, arg2, arg3);
+ vfprintf (stderr, _(msgid), ap);
fprintf (stderr, ": %s\n", my_strerror (e));
+ va_end (ap);
+
collect_exit (FATAL_EXIT_CODE);
}
/* Just die. */
void
-fatal (string, arg1, arg2, arg3)
- char *string, *arg1, *arg2, *arg3;
+fatal VPROTO((const char * msgid, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+#endif
+
fprintf (stderr, "collect2: ");
- fprintf (stderr, string, arg1, arg2, arg3);
+ vfprintf (stderr, _(msgid), ap);
fprintf (stderr, "\n");
+ va_end (ap);
+
collect_exit (FATAL_EXIT_CODE);
}
/* Write error message. */
void
-error (string, arg1, arg2, arg3, arg4)
- char *string, *arg1, *arg2, *arg3, *arg4;
+error VPROTO((const char * msgid, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char * msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+#endif
+
fprintf (stderr, "collect2: ");
- fprintf (stderr, string, arg1, arg2, arg3, arg4);
+ vfprintf (stderr, _(msgid), ap);
fprintf (stderr, "\n");
+ va_end(ap);
}
/* In case obstack is linked in, and abort is defined to fancy_abort,
@@ -429,7 +500,6 @@ fancy_abort ()
{
fatal ("internal error");
}
-
static void
handler (signo)
@@ -457,39 +527,39 @@ handler (signo)
}
-char *
+PTR
xcalloc (size1, size2)
- int size1, size2;
+ size_t size1, size2;
{
- char *ptr = (char *) calloc (size1, size2);
- if (ptr)
- return ptr;
-
- fatal ("out of memory");
- return (char *) 0;
+ PTR ptr = (PTR) calloc (size1, size2);
+ if (!ptr)
+ fatal ("out of memory");
+ return ptr;
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- char *ptr = (char *) malloc (size);
- if (ptr)
- return ptr;
-
- fatal ("out of memory");
- return (char *) 0;
+ PTR ptr = (PTR) malloc (size);
+ if (!ptr)
+ fatal ("out of memory");
+ return ptr;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- register char *value = (char *) realloc (ptr, size);
- if (value == 0)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (ptr == 0)
fatal ("virtual memory exhausted");
- return value;
+ return ptr;
}
int
@@ -502,13 +572,12 @@ file_exists (name)
/* Make a copy of a string INPUT with size SIZE. */
char *
-savestring (input, size)
- char *input;
- int size;
+xstrdup (input)
+ const char *input;
{
- char *output = (char *) xmalloc (size + 1);
- bcopy (input, output, size);
- output[size] = 0;
+ register size_t len = strlen (input) + 1;
+ register char *output = xmalloc (len);
+ memcpy (output, input, len);
return output;
}
@@ -754,9 +823,8 @@ find_a_file (pprefix, name)
/* Determine the filename to execute (special case for absolute paths). */
if (*name == '/'
-#ifdef DIR_SEPARATOR
- || (DIR_SEPARATOR == '\\' && name[1] == ':'
- && (name[2] == DIR_SEPARATOR || name[2] == '/'))
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ || (*name && name[1] == ':')
#endif
)
{
@@ -770,6 +838,16 @@ find_a_file (pprefix, name)
return temp;
}
+#ifdef EXECUTABLE_SUFFIX
+ /* Some systems have a suffix for executable files.
+ So try appending that. */
+ strcpy (temp, name);
+ strcat (temp, EXECUTABLE_SUFFIX);
+
+ if (access (temp, X_OK) == 0)
+ return temp;
+#endif
+
if (debug)
fprintf (stderr, " - failed to locate using absolute path\n");
}
@@ -825,7 +903,7 @@ add_prefix (pprefix, prefix)
pprefix->max_len = len;
pl = (struct prefix_list *) xmalloc (sizeof (struct prefix_list));
- pl->prefix = savestring (prefix, len);
+ pl->prefix = xstrdup (prefix);
if (*prev)
pl->next = *prev;
@@ -843,7 +921,7 @@ prefix_from_env (env, pprefix)
struct path_prefix *pprefix;
{
char *p;
- GET_ENVIRONMENT (p, env);
+ GET_ENV_PATH_LIST (p, env);
if (p)
prefix_from_string (p, pprefix);
@@ -924,15 +1002,33 @@ main (argc, argv)
char *p;
char **c_argv;
char **c_ptr;
- char **ld1_argv = (char **) xcalloc (sizeof (char *), argc+3);
- char **ld1 = ld1_argv;
- char **ld2_argv = (char **) xcalloc (sizeof (char *), argc+6);
- char **ld2 = ld2_argv;
- char **object_lst = (char **) xcalloc (sizeof (char *), argc);
- char **object = object_lst;
+ char **ld1_argv;
+ char **ld1;
+ char **ld2_argv;
+ char **ld2;
+ char **object_lst;
+ char **object;
int first_file;
int num_c_args = argc+9;
+#if defined (COLLECT2_HOST_INITIALIZATION)
+ /* Perform system dependant initialization, if neccessary. */
+ COLLECT2_HOST_INITIALIZATION;
+#endif
+
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
+ /* Do not invoke xcalloc before this point, since locale needs to be
+ set first, in case a diagnostic is issued. */
+
+ ld1 = ld1_argv = (char **) xcalloc (sizeof (char *), argc+3);
+ ld2 = ld2_argv = (char **) xcalloc (sizeof (char *), argc+6);
+ object = object_lst = (char **) xcalloc (sizeof (char *), argc);
+
#ifdef DEBUG
debug = 1;
#endif
@@ -1056,6 +1152,12 @@ main (argc, argv)
/* Try to discover a valid linker/nm/strip to use. */
/* Maybe we know the right file to use (if not cross). */
+ ld_file_name = 0;
+#ifdef DEFAULT_LINKER
+ if (access (DEFAULT_LINKER, X_OK) == 0)
+ ld_file_name = DEFAULT_LINKER;
+ if (ld_file_name == 0)
+#endif
#ifdef REAL_LD_FILE_NAME
ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME);
if (ld_file_name == 0)
@@ -1164,6 +1266,8 @@ main (argc, argv)
char *q = extract_string (&p);
if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
*c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+ if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
+ *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
if (strncmp (q, "-shared", sizeof ("-shared") - 1) == 0)
shared_obj = 1;
}
@@ -1195,7 +1299,7 @@ main (argc, argv)
case 'b':
if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0)
export_flag = 1;
- if (arg[2] == '6' && arg[3] == '4')
+ else if (arg[2] == '6' && arg[3] == '4')
aix64_flag = 1;
break;
#endif
@@ -1342,16 +1446,16 @@ main (argc, argv)
*ld2++ = buf2;
exportf = fopen (export_file, "w");
if (exportf == (FILE *) 0)
- fatal_perror ("%s", export_file);
+ fatal_perror ("fopen %s", export_file);
write_export_file (exportf);
if (fclose (exportf))
- fatal_perror ("closing %s", export_file);
+ fatal_perror ("fclose %s", export_file);
importf = fopen (import_file, "w");
if (importf == (FILE *) 0)
fatal_perror ("%s", import_file);
write_import_file (importf);
if (fclose (importf))
- fatal_perror ("closing %s", import_file);
+ fatal_perror ("fclose %s", import_file);
}
#endif
@@ -1360,7 +1464,7 @@ main (argc, argv)
if (vflag)
{
- fprintf (stderr, "collect2 version %s", version_string);
+ notice ("collect2 version %s", version_string);
#ifdef TARGET_VERSION
TARGET_VERSION;
#endif
@@ -1449,8 +1553,9 @@ main (argc, argv)
if (debug)
{
- fprintf (stderr, "%d constructor(s) found\n", constructors.number);
- fprintf (stderr, "%d destructor(s) found\n", destructors.number);
+ notice ("%d constructor(s) found\n", constructors.number);
+ notice ("%d destructor(s) found\n", destructors.number);
+ notice ("%d frame table(s) found\n", frame_tables.number);
}
if (constructors.number == 0 && destructors.number == 0
@@ -1486,15 +1591,19 @@ main (argc, argv)
return 0;
}
+ /* Sort ctor and dtor lists by priority. */
+ sort_ids (&constructors);
+ sort_ids (&destructors);
+
maybe_unlink(output_file);
outf = fopen (c_file, "w");
if (outf == (FILE *) 0)
- fatal_perror ("%s", c_file);
+ fatal_perror ("fopen %s", c_file);
write_c_file (outf, c_file);
if (fclose (outf))
- fatal_perror ("closing %s", c_file);
+ fatal_perror ("fclose %s", c_file);
/* Tell the linker that we have initializer and finalizer functions. */
#ifdef LD_INIT_SWITCH
@@ -1514,10 +1623,10 @@ main (argc, argv)
add_to_list (&exports, "_GLOBAL__DD");
exportf = fopen (export_file, "w");
if (exportf == (FILE *) 0)
- fatal_perror ("%s", export_file);
+ fatal_perror ("fopen %s", export_file);
write_export_file (exportf);
if (fclose (exportf))
- fatal_perror ("closing %s", export_file);
+ fatal_perror ("fclose %s", export_file);
}
#endif
@@ -1570,25 +1679,18 @@ collect_wait (prog)
{
int status;
- wait (&status);
+ pwait (pexecute_pid, &status, 0);
if (status)
{
if (WIFSIGNALED (status))
{
int sig = WTERMSIG (status);
-#ifdef NO_SYS_SIGLIST
- error ("%s terminated with signal %d %s",
+ error ((status & 0200
+ ? "%s terminated with signal %d [%s]"
+ : "%s terminated with signal %d [%s], core dumped"),
prog,
sig,
- (status & 0200) ? ", core dumped" : "");
-#else
- error ("%s terminated with signal %d [%s]%s",
- prog,
- sig,
- sys_siglist[sig],
- (status & 0200) ? ", core dumped" : "");
-#endif
-
+ my_strsignal(sig));
collect_exit (FATAL_EXIT_CODE);
}
@@ -1611,7 +1713,7 @@ do_wait (prog)
}
-/* Fork and execute a program, and wait for the reply. */
+/* Execute a program, and wait for the reply. */
void
collect_execute (prog, argv, redir)
@@ -1619,7 +1721,11 @@ collect_execute (prog, argv, redir)
char **argv;
char *redir;
{
- int pid;
+ char *errmsg_fmt;
+ char *errmsg_arg;
+ int redir_handle = -1;
+ int stdout_save = -1;
+ int stderr_save = -1;
if (vflag || debug)
{
@@ -1629,7 +1735,7 @@ collect_execute (prog, argv, redir)
if (argv[0])
fprintf (stderr, "%s", argv[0]);
else
- fprintf (stderr, "[cannot find %s]", prog);
+ notice ("[cannot find %s]", prog);
for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
fprintf (stderr, " %s", str);
@@ -1646,36 +1752,41 @@ collect_execute (prog, argv, redir)
if (argv[0] == 0)
fatal ("cannot find `%s'", prog);
-#ifndef __CYGWIN32__
- pid = vfork ();
- if (pid == -1)
+ if (redir)
{
-#ifdef vfork
- fatal_perror ("fork");
-#else
- fatal_perror ("vfork");
-#endif
+ /* Open response file. */
+ redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
+
+ /* Duplicate the stdout and stderr file handles
+ so they can be restored later. */
+ stdout_save = dup (STDOUT_FILENO);
+ if (stdout_save == -1)
+ fatal_perror ("redirecting stdout: %s", redir);
+ stderr_save = dup (STDERR_FILENO);
+ if (stderr_save == -1)
+ fatal_perror ("redirecting stdout: %s", redir);
+
+ /* Redirect stdout & stderr to our response file. */
+ dup2 (redir_handle, STDOUT_FILENO);
+ dup2 (redir_handle, STDERR_FILENO);
}
- if (pid == 0) /* child context */
+ pexecute_pid = pexecute (argv[0], argv, argv[0], NULL,
+ &errmsg_fmt, &errmsg_arg,
+ (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
+
+ if (redir)
{
- if (redir)
- {
- unlink (redir);
- if (freopen (redir, "a", stdout) == NULL)
- fatal_perror ("redirecting stdout: %s", redir);
- if (freopen (redir, "a", stderr) == NULL)
- fatal_perror ("redirecting stderr: %s", redir);
- }
+ /* Restore stdout and stderr to their previous settings. */
+ dup2 (stdout_save, STDOUT_FILENO);
+ dup2 (stderr_save, STDERR_FILENO);
- execvp (argv[0], argv);
- fatal_perror ("executing %s", prog);
+ /* Close reponse file. */
+ close (redir_handle);
}
-#else
- pid = _spawnvp (_P_NOWAIT, argv[0], argv);
- if (pid == -1)
- fatal ("spawnvp failed");
-#endif
+
+ if (pexecute_pid == -1)
+ fatal_perror (errmsg_fmt, errmsg_arg);
}
static void
@@ -1696,10 +1807,12 @@ maybe_unlink (file)
if (!debug)
unlink (file);
else
- fprintf (stderr, "[Leaving %s]\n", file);
+ notice ("[Leaving %s]\n", file);
}
+static long sequence_number = 0;
+
/* Add a name to a linked list. */
static void
@@ -1710,7 +1823,6 @@ add_to_list (head_ptr, name)
struct id *newid
= (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
struct id *p;
- static long sequence_number = 0;
strcpy (newid->name, name);
if (head_ptr->first)
@@ -1735,6 +1847,67 @@ add_to_list (head_ptr, name)
head_ptr->number++;
}
+/* Grab the init priority number from an init function name that
+ looks like "_GLOBAL_.I.12345.foo". */
+
+static int
+extract_init_priority (name)
+ char *name;
+{
+ int pos = 0, pri;
+
+ while (name[pos] == '_')
+ ++pos;
+ pos += 10; /* strlen ("GLOBAL__X_") */
+
+ /* Extract init_p number from ctor/dtor name. */
+ pri = atoi (name + pos);
+ return pri ? pri : DEFAULT_INIT_PRIORITY;
+}
+
+/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
+ ctors will be run from right to left, dtors from left to right. */
+
+static void
+sort_ids (head_ptr)
+ struct head *head_ptr;
+{
+ /* id holds the current element to insert. id_next holds the next
+ element to insert. id_ptr iterates through the already sorted elements
+ looking for the place to insert id. */
+ struct id *id, *id_next, **id_ptr;
+
+ id = head_ptr->first;
+
+ /* We don't have any sorted elements yet. */
+ head_ptr->first = NULL;
+
+ for (; id; id = id_next)
+ {
+ id_next = id->next;
+ id->sequence = extract_init_priority (id->name);
+
+ for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
+ if (*id_ptr == NULL
+ /* If the sequence numbers are the same, we put the id from the
+ file later on the command line later in the list. */
+ || id->sequence > (*id_ptr)->sequence
+ /* Hack: do lexical compare, too.
+ || (id->sequence == (*id_ptr)->sequence
+ && strcmp (id->name, (*id_ptr)->name) > 0) */
+ )
+ {
+ id->next = *id_ptr;
+ *id_ptr = id;
+ break;
+ }
+ }
+
+ /* Now set the sequence numbers properly so write_c_file works. */
+ for (id = head_ptr->first; id; id = id->next)
+ id->sequence = ++sequence_number;
+}
+
/* Write: `prefix', the names on list LIST, `suffix'. */
static void
@@ -1853,11 +2026,11 @@ write_c_file_stat (stream, name)
strncpy (prefix, p, q - p);
prefix[q - p] = 0;
for (q = prefix; *q; q++)
- if (!ISALNUM (*q))
+ if (!ISALNUM ((unsigned char)*q))
*q = '_';
if (debug)
- fprintf (stderr, "\nwrite_c_file - output name is %s, prefix is %s\n",
- output_file, prefix);
+ notice ("\nwrite_c_file - output name is %s, prefix is %s\n",
+ output_file, prefix);
#define INIT_NAME_FORMAT "_GLOBAL__FI_%s"
initname = xmalloc (strlen (prefix) + sizeof (INIT_NAME_FORMAT) - 2);
@@ -2114,28 +2287,22 @@ scan_prog_file (prog_name, which_pass)
/* Spawn child nm on pipe */
pid = vfork ();
if (pid == -1)
- {
-#ifdef vfork
- fatal_perror ("fork");
-#else
- fatal_perror ("vfork");
-#endif
- }
+ fatal_perror (VFORK_STRING);
if (pid == 0) /* child context */
{
/* setup stdout */
if (dup2 (pipe_fd[1], 1) < 0)
- fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
+ fatal_perror ("dup2 %d 1", pipe_fd[1]);
if (close (pipe_fd[0]) < 0)
- fatal_perror ("close (%d)", pipe_fd[0]);
+ fatal_perror ("close %d", pipe_fd[0]);
if (close (pipe_fd[1]) < 0)
- fatal_perror ("close (%d)", pipe_fd[1]);
+ fatal_perror ("close %d", pipe_fd[1]);
execv (nm_file_name, nm_argv);
- fatal_perror ("executing %s", nm_file_name);
+ fatal_perror ("execvp %s", nm_file_name);
}
/* Parent context from here on. */
@@ -2145,7 +2312,7 @@ scan_prog_file (prog_name, which_pass)
#endif
if (close (pipe_fd[1]) < 0)
- fatal_perror ("close (%d)", pipe_fd[1]);
+ fatal_perror ("close %d", pipe_fd[1]);
if (debug)
fprintf (stderr, "\nnm output with constructors/destructors.\n");
@@ -2206,6 +2373,7 @@ scan_prog_file (prog_name, which_pass)
case 5:
if (which_pass != PASS_LIB)
add_to_list (&frame_tables, name);
+ break;
default: /* not a constructor or destructor */
continue;
@@ -2219,7 +2387,7 @@ scan_prog_file (prog_name, which_pass)
fprintf (stderr, "\n");
if (fclose (inf) != 0)
- fatal_perror ("fclose of pipe");
+ fatal_perror ("fclose");
do_wait (nm_file_name);
@@ -2421,7 +2589,7 @@ locatelib (name)
if (*pp == 0)
{
if (debug)
- fprintf (stderr, "not found\n");
+ notice ("not found\n");
else
fatal ("dynamic dependency %s not found", name);
}
@@ -2465,7 +2633,7 @@ scan_libraries (prog_name)
}
if (debug)
- fprintf (stderr, "dynamic dependencies.\n");
+ notice ("dynamic dependencies.\n");
ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base);
for (lo = (struct link_object *) ld_2->ld_need; lo;
@@ -2556,28 +2724,22 @@ scan_libraries (prog_name)
/* Spawn child ldd on pipe */
pid = vfork ();
if (pid == -1)
- {
-#ifdef vfork
- fatal_perror ("fork");
-#else
- fatal_perror ("vfork");
-#endif
- }
+ fatal_perror (VFORK_STRING);
if (pid == 0) /* child context */
{
/* setup stdout */
if (dup2 (pipe_fd[1], 1) < 0)
- fatal_perror ("dup2 (%d, 1)", pipe_fd[1]);
+ fatal_perror ("dup2 %d 1", pipe_fd[1]);
if (close (pipe_fd[0]) < 0)
- fatal_perror ("close (%d)", pipe_fd[0]);
+ fatal_perror ("close %d", pipe_fd[0]);
if (close (pipe_fd[1]) < 0)
- fatal_perror ("close (%d)", pipe_fd[1]);
+ fatal_perror ("close %d", pipe_fd[1]);
execv (ldd_file_name, ldd_argv);
- fatal_perror ("executing %s", ldd_file_name);
+ fatal_perror ("execv %s", ldd_file_name);
}
/* Parent context from here on. */
@@ -2587,10 +2749,10 @@ scan_libraries (prog_name)
#endif
if (close (pipe_fd[1]) < 0)
- fatal_perror ("close (%d)", pipe_fd[1]);
+ fatal_perror ("close %d", pipe_fd[1]);
if (debug)
- fprintf (stderr, "\nldd output with constructors/destructors.\n");
+ notice ("\nldd output with constructors/destructors.\n");
/* Read each line of ldd output. */
while (fgets (buf, sizeof buf, inf) != (char *) 0)
@@ -2626,7 +2788,7 @@ scan_libraries (prog_name)
fprintf (stderr, "\n");
if (fclose (inf) != 0)
- fatal_perror ("fclose of pipe");
+ fatal_perror ("fclose");
do_wait (ldd_file_name);
@@ -2656,7 +2818,7 @@ scan_libraries (prog_name)
#if defined(EXTENDED_COFF)
# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
# define GCC_SYMENT SYMR
-# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)
+# define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal)
# define GCC_SYMINC(X) (1)
# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
@@ -2796,6 +2958,11 @@ scan_prog_file (prog_name, which_pass)
break;
#endif
+ case 5:
+ if (! is_shared)
+ add_to_list (&frame_tables, name);
+ break;
+
default: /* not a constructor or destructor */
#ifdef COLLECT_EXPORT_LIST
/* If we are building a shared object on AIX we need
@@ -3059,7 +3226,7 @@ scan_prog_file (prog_name, which_pass)
prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY);
if (prog_fd < 0)
- fatal_perror ("cannot read %s", prog_name);
+ fatal_perror ("open %s", prog_name);
obj_file = read_file (prog_name, prog_fd, rw);
obj = obj_file->start;
@@ -3155,8 +3322,8 @@ scan_prog_file (prog_name, which_pass)
case SYMC_STABS: kind = "stabs"; break;
}
- fprintf (stderr, "\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
- symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
+ notice ("\nProcessing symbol table #%d, offset = 0x%.8lx, kind = %s\n",
+ symbol_load_cmds, load_hdr->hdr.ldci_section_off, kind);
}
if (load_hdr->sym.symc_kind != SYMC_DEFINED_SYMBOLS)
@@ -3240,15 +3407,15 @@ scan_prog_file (prog_name, which_pass)
add_func_table (&hdr, load_array, main_sym, FNTC_INITIALIZATION);
if (debug)
- fprintf (stderr, "\nUpdating header and load commands.\n\n");
+ notice ("\nUpdating header and load commands.\n\n");
hdr.moh_n_load_cmds++;
size = sizeof (load_cmd_map_command_t) + (sizeof (mo_offset_t) * (hdr.moh_n_load_cmds - 1));
/* Create new load command map. */
if (debug)
- fprintf (stderr, "load command map, %d cmds, new size %ld.\n",
- (int)hdr.moh_n_load_cmds, (long)size);
+ notice ("load command map, %d cmds, new size %ld.\n",
+ (int) hdr.moh_n_load_cmds, (long) size);
load_map = (load_union_t *) xcalloc (1, size);
load_map->map.ldc_header.ldci_cmd_type = LDC_CMD_MAP;
@@ -3278,7 +3445,7 @@ scan_prog_file (prog_name, which_pass)
bad_header (status);
if (debug)
- fprintf (stderr, "writing load commands.\n\n");
+ notice ("writing load commands.\n\n");
/* Write load commands */
offset = hdr.moh_first_cmd_off;
@@ -3298,7 +3465,7 @@ scan_prog_file (prog_name, which_pass)
end_file (obj_file);
if (close (prog_fd))
- fatal_perror ("closing %s", prog_name);
+ fatal_perror ("close %s", prog_name);
if (debug)
fprintf (stderr, "\n");
@@ -3376,12 +3543,11 @@ add_func_table (hdr_p, load_array, sym, type)
}
if (debug)
- fprintf (stderr,
- "%s function, region %d, offset = %ld (0x%.8lx)\n",
- (type == FNTC_INITIALIZATION) ? "init" : "term",
- (int)ptr->func.fntc_entry_loc[i].adr_lcid,
- (long)ptr->func.fntc_entry_loc[i].adr_sctoff,
- (long)ptr->func.fntc_entry_loc[i].adr_sctoff);
+ notice ("%s function, region %d, offset = %ld (0x%.8lx)\n",
+ type == FNTC_INITIALIZATION ? "init" : "term",
+ (int) ptr->func.fntc_entry_loc[i].adr_lcid,
+ (long) ptr->func.fntc_entry_loc[i].adr_sctoff,
+ (long) ptr->func.fntc_entry_loc[i].adr_sctoff);
}
@@ -3502,22 +3668,17 @@ static void
bad_header (status)
int status;
{
- char *msg = (char *) 0;
-
switch (status)
{
- case MO_ERROR_BAD_MAGIC: msg = "bad magic number"; break;
- case MO_ERROR_BAD_HDR_VERS: msg = "bad header version"; break;
- case MO_ERROR_BAD_RAW_HDR_VERS: msg = "bad raw header version"; break;
- case MO_ERROR_BUF2SML: msg = "raw header buffer too small"; break;
- case MO_ERROR_OLD_RAW_HDR_FILE: msg = "old raw header file"; break;
- case MO_ERROR_UNSUPPORTED_VERS: msg = "unsupported version"; break;
+ case MO_ERROR_BAD_MAGIC: fatal ("bad magic number");
+ case MO_ERROR_BAD_HDR_VERS: fatal ("bad header version");
+ case MO_ERROR_BAD_RAW_HDR_VERS: fatal ("bad raw header version");
+ case MO_ERROR_BUF2SML: fatal ("raw header buffer too small");
+ case MO_ERROR_OLD_RAW_HDR_FILE: fatal ("old raw header file");
+ case MO_ERROR_UNSUPPORTED_VERS: fatal ("unsupported version");
+ default:
+ fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
}
-
- if (msg == (char *) 0)
- fatal ("unknown {de,en}code_mach_o_hdr return value %d", status);
- else
- fatal ("%s", msg);
}
@@ -3573,7 +3734,7 @@ read_file (name, fd, rw)
p->use_mmap = 0;
p->start = xmalloc (p->size);
if (lseek (fd, 0L, SEEK_SET) < 0)
- fatal_perror ("lseek to 0 on %s", name);
+ fatal_perror ("lseek %s 0", name);
len = read (fd, p->start, p->size);
if (len < 0)
@@ -3621,7 +3782,7 @@ end_file (ptr)
fprintf (stderr, "write %s\n", ptr->name);
if (lseek (ptr->fd, 0L, SEEK_SET) < 0)
- fatal_perror ("lseek to 0 on %s", ptr->name);
+ fatal_perror ("lseek %s 0", ptr->name);
len = write (ptr->fd, ptr->start, ptr->size);
if (len < 0)
diff --git a/contrib/gcc/collect2.h b/contrib/gcc/collect2.h
new file mode 100644
index 0000000..04844bc
--- /dev/null
+++ b/contrib/gcc/collect2.h
@@ -0,0 +1,36 @@
+/* Header file for collect/tlink routines.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef __COLLECT2_H__
+#define __COLLECT2_H__
+
+extern void do_tlink PARAMS ((char **, char **));
+
+extern void collect_execute PARAMS ((char *, char **, char *));
+
+extern void collect_exit PARAMS ((int)) ATTRIBUTE_NORETURN;
+
+extern int collect_wait PARAMS ((char *));
+
+extern void dump_file PARAMS ((char *));
+
+extern int file_exists PARAMS ((char *));
+
+#endif /* ! __COLLECT2_H__ */
diff --git a/contrib/gcc/combine.c b/contrib/gcc/combine.c
index db9bb38..0b64a86 100644
--- a/contrib/gcc/combine.c
+++ b/contrib/gcc/combine.c
@@ -75,16 +75,8 @@ Boston, MA 02111-1307, USA. */
combine anyway. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-/* stdio.h must precede rtl.h for FFS. */
#include "system.h"
-
-#include "rtl.h"
+#include "rtl.h" /* stdio.h must precede rtl.h for FFS. */
#include "flags.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -434,7 +426,7 @@ static int merge_outer_ops PROTO((enum rtx_code *, HOST_WIDE_INT *,
enum machine_mode, int *));
static rtx simplify_shift_const PROTO((rtx, enum rtx_code, enum machine_mode,
rtx, int));
-static int recog_for_combine PROTO((rtx *, rtx, rtx *, int *));
+static int recog_for_combine PROTO((rtx *, rtx, rtx *));
static rtx gen_lowpart_for_combine PROTO((enum machine_mode, rtx));
static rtx gen_rtx_combine PVPROTO((enum rtx_code code, enum machine_mode mode,
...));
@@ -581,7 +573,7 @@ combine_instructions (f, nregs)
/* If INSN starts a new basic block, update our basic block number. */
if (this_basic_block + 1 < n_basic_blocks
- && basic_block_head[this_basic_block + 1] == insn)
+ && BLOCK_HEAD (this_basic_block + 1) == insn)
this_basic_block++;
if (GET_CODE (insn) == CODE_LABEL)
@@ -682,6 +674,9 @@ combine_instructions (f, nregs)
total_successes += combine_successes;
nonzero_sign_valid = 0;
+
+ /* Make recognizer allow volatile MEMs again. */
+ init_recog ();
}
/* Wipe the reg_last_xxx arrays in preparation for another pass. */
@@ -749,7 +744,7 @@ set_nonzero_bits_and_sign_copies (x, set)
&& REGNO (x) >= FIRST_PSEUDO_REGISTER
/* If this register is undefined at the start of the file, we can't
say what its contents were. */
- && ! REGNO_REG_SET_P (basic_block_live_at_start[0], REGNO (x))
+ && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, REGNO (x))
&& GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
{
if (set == 0 || GET_CODE (set) == CLOBBER)
@@ -824,7 +819,8 @@ static int
can_combine_p (insn, i3, pred, succ, pdest, psrc)
rtx insn;
rtx i3;
- rtx pred, succ;
+ rtx pred ATTRIBUTE_UNUSED;
+ rtx succ;
rtx *pdest, *psrc;
{
int i;
@@ -958,8 +954,14 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
/* Don't substitute into an incremented register. */
|| FIND_REG_INC_NOTE (i3, dest)
|| (succ && FIND_REG_INC_NOTE (succ, dest))
+#if 0
/* Don't combine the end of a libcall into anything. */
+ /* ??? This gives worse code, and appears to be unnecessary, since no
+ pass after flow uses REG_LIBCALL/REG_RETVAL notes. Local-alloc does
+ use REG_RETVAL notes for noconflict blocks, but other code here
+ makes sure that those insns don't disappear. */
|| find_reg_note (insn, REG_RETVAL, NULL_RTX)
+#endif
/* Make sure that DEST is not used after SUCC but before I3. */
|| (succ && ! all_adjacent
&& reg_used_between_p (dest, succ, i3))
@@ -1354,8 +1356,6 @@ try_combine (i3, i2, i1)
int i3_subst_into_i2 = 0;
/* Notes that I1, I2 or I3 is a MULT operation. */
int have_mult = 0;
- /* Number of clobbers of SCRATCH we had to add. */
- int i3_scratches = 0, i2_scratches = 0, other_scratches = 0;
int maxreg;
rtx temp;
@@ -1371,7 +1371,12 @@ try_combine (i3, i2, i1)
if (GET_RTX_CLASS (GET_CODE (i3)) != 'i'
|| GET_RTX_CLASS (GET_CODE (i2)) != 'i'
|| (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i')
- || find_reg_note (i3, REG_LIBCALL, NULL_RTX))
+#if 0
+ /* ??? This gives worse code, and appears to be unnecessary, since no
+ pass after flow uses REG_LIBCALL/REG_RETVAL notes. */
+ || find_reg_note (i3, REG_LIBCALL, NULL_RTX)
+#endif
+)
return 0;
combine_attempts++;
@@ -1827,8 +1832,7 @@ try_combine (i3, i2, i1)
mark_used_regs_combine (newpat);
/* Is the result of combination a valid instruction? */
- insn_code_number
- = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+ insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
/* If the result isn't valid, see if it is a PARALLEL of two SETs where
the second SET's destination is a register that is unused. In that case,
@@ -1849,8 +1853,7 @@ try_combine (i3, i2, i1)
&& asm_noperands (newpat) < 0)
{
newpat = XVECEXP (newpat, 0, 0);
- insn_code_number
- = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+ insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
}
else if (insn_code_number < 0 && GET_CODE (newpat) == PARALLEL
@@ -1863,8 +1866,7 @@ try_combine (i3, i2, i1)
&& asm_noperands (newpat) < 0)
{
newpat = XVECEXP (newpat, 0, 1);
- insn_code_number
- = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+ insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
}
/* If we were combining three insns and the result is a simple SET
@@ -1933,8 +1935,7 @@ try_combine (i3, i2, i1)
if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest);
- i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes,
- &i2_scratches);
+ i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
/* If I2 or I3 has multiple SETs, we won't know how to track
register status, so don't use these insns. If I2's destination
@@ -1943,8 +1944,8 @@ try_combine (i3, i2, i1)
if (i2_code_number >= 0 && i2set && i3set
&& (next_real_insn (i2) == i3
|| ! reg_used_between_p (SET_DEST (i2set), i2, i3)))
- insn_code_number = recog_for_combine (&newi3pat, i3, &new_i3_notes,
- &i3_scratches);
+ insn_code_number = recog_for_combine (&newi3pat, i3,
+ &new_i3_notes);
if (insn_code_number >= 0)
newpat = newi3pat;
@@ -2031,14 +2032,12 @@ try_combine (i3, i2, i1)
newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split);
SUBST (*split, newdest);
- i2_code_number
- = recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
+ i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
/* 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, &i3_scratches);
+ insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
}
}
@@ -2092,12 +2091,10 @@ try_combine (i3, i2, i1)
newpat = XVECEXP (newpat, 0, 1);
SUBST (SET_SRC (newpat),
gen_lowpart_for_combine (GET_MODE (SET_SRC (newpat)), ni2dest));
- i2_code_number
- = recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
+ i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
if (i2_code_number >= 0)
- insn_code_number
- = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+ insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
if (insn_code_number >= 0)
{
@@ -2127,7 +2124,7 @@ try_combine (i3, i2, i1)
for (insn = NEXT_INSN (i3);
insn && (this_basic_block == n_basic_blocks - 1
- || insn != basic_block_head[this_basic_block + 1]);
+ || insn != BLOCK_HEAD (this_basic_block + 1));
insn = NEXT_INSN (insn))
{
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
@@ -2184,12 +2181,10 @@ try_combine (i3, i2, i1)
newpat = XVECEXP (newpat, 0, 0);
}
- i2_code_number
- = recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
+ i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
if (i2_code_number >= 0)
- insn_code_number
- = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+ insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
}
/* If it still isn't recognized, fail and change things back the way they
@@ -2211,9 +2206,8 @@ try_combine (i3, i2, i1)
CLEAR_HARD_REG_SET (newpat_used_regs);
- other_code_number
- = recog_for_combine (&other_pat, undobuf.other_insn,
- &new_other_notes, &other_scratches);
+ other_code_number = recog_for_combine (&other_pat, undobuf.other_insn,
+ &new_other_notes);
if (other_code_number < 0 && ! check_asm_operands (other_pat))
{
@@ -2316,7 +2310,7 @@ try_combine (i3, i2, i1)
SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
for (temp = NEXT_INSN (i2);
temp && (this_basic_block == n_basic_blocks - 1
- || basic_block_head[this_basic_block] != temp);
+ || BLOCK_HEAD (this_basic_block) != temp);
temp = NEXT_INSN (temp))
if (temp != i3 && GET_RTX_CLASS (GET_CODE (temp)) == 'i')
for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
@@ -2496,7 +2490,8 @@ try_combine (i3, i2, i1)
regno = REGNO (i2dest);
REG_N_SETS (regno)--;
if (REG_N_SETS (regno) == 0
- && ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
+ && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
+ regno))
REG_N_REFS (regno) = 0;
}
}
@@ -2518,7 +2513,8 @@ try_combine (i3, i2, i1)
{
REG_N_SETS (regno)--;
if (REG_N_SETS (regno) == 0
- && ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
+ && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
+ regno))
REG_N_REFS (regno) = 0;
}
}
@@ -2530,12 +2526,6 @@ try_combine (i3, i2, i1)
if (newi2pat)
note_stores (newi2pat, set_nonzero_bits_and_sign_copies);
- /* If we added any (clobber (scratch)), add them to the max for a
- block. This is a very pessimistic calculation, since we might
- have had them already and this might not be the worst block, but
- it's not worth doing any better. */
- max_scratch += i3_scratches + i2_scratches + other_scratches;
-
/* If I3 is now an unconditional jump, ensure that it has a
BARRIER following it since it may have initially been a
conditional jump. It may also be the last nonnote insn. */
@@ -2747,7 +2737,7 @@ find_split_point (loc, insn)
if (BITS_BIG_ENDIAN)
pos = GET_MODE_BITSIZE (mode) - len - pos;
- if (src == mask)
+ if ((unsigned HOST_WIDE_INT) src == mask)
SUBST (SET_SRC (x),
gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
else
@@ -3514,9 +3504,8 @@ simplify_rtx (x, op0_mode, last, in_dest)
plus_constant (XEXP (inner, 0),
(SUBREG_WORD (x) * UNITS_PER_WORD
+ endian_offset)));
- MEM_VOLATILE_P (x) = MEM_VOLATILE_P (inner);
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (inner);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (inner);
+ MEM_COPY_ATTRIBUTES (x, inner);
return x;
}
@@ -3821,9 +3810,12 @@ simplify_rtx (x, op0_mode, last, in_dest)
return SUBREG_REG (XEXP (x, 0));
/* If we know that the value is already truncated, we can
- replace the TRUNCATE with a SUBREG. */
- if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
- >= GET_MODE_BITSIZE (mode) + 1)
+ replace the TRUNCATE with a SUBREG if TRULY_NOOP_TRUNCATION is
+ nonzero for the corresponding modes. */
+ if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
+ && num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
+ >= GET_MODE_BITSIZE (mode) + 1)
return gen_lowpart_for_combine (mode, XEXP (x, 0));
/* A truncate of a comparison can be replaced with a subreg if
@@ -4164,7 +4156,7 @@ simplify_rtx (x, op0_mode, last, in_dest)
if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
- == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
+ == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE(mode)-1))
&& op1 == const0_rtx
&& mode == GET_MODE (op0)
&& (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
@@ -4692,9 +4684,8 @@ simplify_set (x)
&& exact_log2 (mask = nonzero_bits (op0, GET_MODE (op0))) >= 0)
{
rtx pat = PATTERN (other_insn), note = 0;
- int scratches;
- if ((recog_for_combine (&pat, other_insn, &note, &scratches) < 0
+ if ((recog_for_combine (&pat, other_insn, &note) < 0
&& ! check_asm_operands (pat)))
{
PUT_CODE (*cc_use, old_code);
@@ -5131,7 +5122,7 @@ simplify_logical (x, last)
when STORE_FLAG_VALUE is the sign bit. */
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
- == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
+ == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
&& op1 == const_true_rtx
&& GET_RTX_CLASS (GET_CODE (op0)) == '<'
&& reversible_comparison_p (op0))
@@ -5432,6 +5423,24 @@ expand_field_assignment (x)
compute_mode = GET_MODE (inner);
+ /* Don't attempt bitwise arithmetic on non-integral modes. */
+ if (! INTEGRAL_MODE_P (compute_mode))
+ {
+ enum machine_mode imode;
+
+ /* Something is probably seriously wrong if this matches. */
+ if (! FLOAT_MODE_P (compute_mode))
+ break;
+
+ /* Try to find an integral mode to pun with. */
+ imode = mode_for_size (GET_MODE_BITSIZE (compute_mode), MODE_INT, 0);
+ if (imode == BLKmode)
+ break;
+
+ compute_mode = imode;
+ inner = gen_lowpart_for_combine (imode, inner);
+ }
+
/* Compute a mask of LEN bits, if we can do this on the host machine. */
if (len < HOST_BITS_PER_WIDE_INT)
mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
@@ -5588,8 +5597,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
new = gen_rtx_MEM (tmode, plus_constant (XEXP (inner, 0), offset));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (inner);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (inner);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (inner);
+ MEM_COPY_ATTRIBUTES (new, inner);
}
else if (GET_CODE (inner) == REG)
{
@@ -5653,27 +5661,45 @@ make_extraction (mode, inner, pos, pos_rtx, len,
#ifdef HAVE_insv
if (in_dest)
{
- wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_insv][0];
- pos_mode = insn_operand_mode[(int) CODE_FOR_insv][2];
- extraction_mode = insn_operand_mode[(int) CODE_FOR_insv][3];
+ wanted_inner_reg_mode
+ = (insn_operand_mode[(int) CODE_FOR_insv][0] == VOIDmode
+ ? word_mode
+ : insn_operand_mode[(int) CODE_FOR_insv][0]);
+ pos_mode = (insn_operand_mode[(int) CODE_FOR_insv][2] == VOIDmode
+ ? word_mode : insn_operand_mode[(int) CODE_FOR_insv][2]);
+ extraction_mode = (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode
+ ? word_mode
+ : insn_operand_mode[(int) CODE_FOR_insv][3]);
}
#endif
#ifdef HAVE_extzv
if (! in_dest && unsignedp)
{
- wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
- pos_mode = insn_operand_mode[(int) CODE_FOR_extzv][3];
- extraction_mode = insn_operand_mode[(int) CODE_FOR_extzv][0];
+ wanted_inner_reg_mode
+ = (insn_operand_mode[(int) CODE_FOR_extzv][1] == VOIDmode
+ ? word_mode
+ : insn_operand_mode[(int) CODE_FOR_extzv][1]);
+ pos_mode = (insn_operand_mode[(int) CODE_FOR_extzv][3] == VOIDmode
+ ? word_mode : insn_operand_mode[(int) CODE_FOR_extzv][3]);
+ extraction_mode = (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode
+ ? word_mode
+ : insn_operand_mode[(int) CODE_FOR_extzv][0]);
}
#endif
#ifdef HAVE_extv
if (! in_dest && ! unsignedp)
{
- wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
- pos_mode = insn_operand_mode[(int) CODE_FOR_extv][3];
- extraction_mode = insn_operand_mode[(int) CODE_FOR_extv][0];
+ wanted_inner_reg_mode
+ = (insn_operand_mode[(int) CODE_FOR_extv][1] == VOIDmode
+ ? word_mode
+ : insn_operand_mode[(int) CODE_FOR_extv][1]);
+ pos_mode = (insn_operand_mode[(int) CODE_FOR_extv][3] == VOIDmode
+ ? word_mode : insn_operand_mode[(int) CODE_FOR_extv][3]);
+ extraction_mode = (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode
+ ? word_mode
+ : insn_operand_mode[(int) CODE_FOR_extv][0]);
}
#endif
@@ -5763,8 +5789,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
rtx newmem = gen_rtx_MEM (wanted_inner_mode,
plus_constant (XEXP (inner, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (inner);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (inner);
+ MEM_COPY_ATTRIBUTES (newmem, inner);
inner = newmem;
}
}
@@ -6328,7 +6353,7 @@ force_to_mode (x, mode, mask, reg, just_select)
need it. */
if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) == mask)
+ && (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) == mask)
x = XEXP (x, 0);
/* If it remains an AND, try making another AND with the bits
@@ -6390,20 +6415,21 @@ force_to_mode (x, mode, mask, reg, just_select)
unsigned HOST_WIDE_INT sp_mask = GET_MODE_MASK (mode);
sp_mask &= ~ (sp_alignment - 1);
- if ((sp_mask & ~ mask) == 0
- && ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~ mask) != 0)
+ if ((sp_mask & ~ smask) == 0
+ && ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~ smask) != 0)
return force_to_mode (plus_constant (XEXP (x, 0),
((INTVAL (XEXP (x, 1)) -
- STACK_BIAS) & mask)
+ STACK_BIAS) & smask)
+ STACK_BIAS),
- mode, mask, reg, next_select);
+ mode, smask, reg, next_select);
}
#endif
- if ((nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0
- && (INTVAL (XEXP (x, 1)) & ~ mask) != 0)
+ if ((nonzero_bits (XEXP (x, 0), mode) & ~ smask) == 0
+ && (INTVAL (XEXP (x, 1)) & ~ smask) != 0)
return force_to_mode (plus_constant (XEXP (x, 0),
- INTVAL (XEXP (x, 1)) & mask),
- mode, mask, reg, next_select);
+ (INTVAL (XEXP (x, 1))
+ & smask)),
+ mode, smask, reg, next_select);
}
}
@@ -6549,7 +6575,7 @@ force_to_mode (x, mode, mask, reg, just_select)
/* If we are just looking for the sign bit, we don't need this shift at
all, even if it has a variable count. */
if (GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
- && (mask == ((HOST_WIDE_INT) 1
+ && (mask == ((unsigned HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
return force_to_mode (XEXP (x, 0), mode, mask, reg, next_select);
@@ -7376,7 +7402,7 @@ simplify_and_const_int (x, mode, varop, constop)
else
{
if (GET_CODE (XEXP (x, 1)) != CONST_INT
- || INTVAL (XEXP (x, 1)) != constop)
+ || (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) != constop)
SUBST (XEXP (x, 1), GEN_INT (constop));
SUBST (XEXP (x, 0), varop);
@@ -8292,7 +8318,8 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
op0 = NIL;
else if (const0 == 0 && op0 == AND)
op0 = SET;
- else if (const0 == GET_MODE_MASK (mode) && op0 == AND)
+ else if ((unsigned HOST_WIDE_INT) const0 == GET_MODE_MASK (mode)
+ && op0 == AND)
op0 = NIL;
/* If this would be an entire word for the target, but is not for
@@ -8475,8 +8502,7 @@ simplify_shift_const (x, code, result_mode, varop, count)
plus_constant (XEXP (varop, 0),
count / BITS_PER_UNIT));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (varop);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (varop);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (varop);
+ MEM_COPY_ATTRIBUTES (new, varop);
varop = gen_rtx_combine (code == ASHIFTRT ? SIGN_EXTEND
: ZERO_EXTEND, mode, new);
count = 0;
@@ -9066,18 +9092,14 @@ simplify_shift_const (x, code, result_mode, varop, count)
PNOTES is a pointer to a location where any REG_UNUSED notes added for
the CLOBBERs are placed.
- PADDED_SCRATCHES is set to the number of (clobber (scratch)) patterns
- we had to add.
-
The value is the final insn code from the pattern ultimately matched,
or -1. */
static int
-recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
+recog_for_combine (pnewpat, insn, pnotes)
rtx *pnewpat;
rtx insn;
rtx *pnotes;
- int *padded_scratches;
{
register rtx pat = *pnewpat;
int insn_code_number;
@@ -9085,8 +9107,6 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
int i;
rtx notes = 0;
- *padded_scratches = 0;
-
/* If PAT is a PARALLEL, check to see if it contains the CLOBBER
we use to indicate that something didn't match. If we find such a
thing, force rejection. */
@@ -9148,8 +9168,6 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
if (GET_CODE (XEXP (XVECEXP (newpat, 0, i), 0)) == REG
&& ! reg_dead_at_p (XEXP (XVECEXP (newpat, 0, i), 0), insn))
return -1;
- else if (GET_CODE (XEXP (XVECEXP (newpat, 0, i), 0)) == SCRATCH)
- (*padded_scratches)++;
notes = gen_rtx_EXPR_LIST (REG_UNUSED,
XEXP (XVECEXP (newpat, 0, i), 0), notes);
}
@@ -9243,8 +9261,7 @@ gen_lowpart_for_combine (mode, x)
}
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
return new;
}
@@ -9279,7 +9296,7 @@ gen_lowpart_for_combine (mode, x)
static rtx
gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
enum rtx_code code;
enum machine_mode mode;
#endif
@@ -9293,7 +9310,7 @@ gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...))
VA_START (p, mode);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
code = va_arg (p, enum rtx_code);
mode = va_arg (p, enum machine_mode);
#endif
@@ -9553,7 +9570,7 @@ simplify_comparison (code, pop0, pop1)
for (tmode = GET_CLASS_NARROWEST_MODE
(GET_MODE_CLASS (GET_MODE (op0)));
tmode != GET_MODE (op0); tmode = GET_MODE_WIDER_MODE (tmode))
- if (c0 == GET_MODE_MASK (tmode))
+ if ((unsigned HOST_WIDE_INT) c0 == GET_MODE_MASK (tmode))
{
op0 = gen_lowpart_for_combine (tmode, inner_op0);
op1 = gen_lowpart_for_combine (tmode, inner_op1);
@@ -9628,7 +9645,7 @@ simplify_comparison (code, pop0, pop1)
|| code == LT || code == LTU)
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& exact_log2 (const_op) >= 0
- && nonzero_bits (op0, mode) == const_op)
+ && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op)
{
code = (code == EQ || code == GE || code == GEU ? NE : EQ);
op1 = const0_rtx, const_op = 0;
@@ -9820,12 +9837,16 @@ simplify_comparison (code, pop0, pop1)
&& (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0)
{
if (BITS_BIG_ENDIAN)
+ {
#ifdef HAVE_extzv
- i = (GET_MODE_BITSIZE
- (insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i);
+ mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
+ if (mode == VOIDmode)
+ mode = word_mode;
+ i = (GET_MODE_BITSIZE (mode) - 1 - i);
#else
- i = BITS_PER_WORD - 1 - i;
+ i = BITS_PER_WORD - 1 - i;
#endif
+ }
op0 = XEXP (op0, 2);
op1 = GEN_INT (i);
@@ -9953,7 +9974,7 @@ simplify_comparison (code, pop0, pop1)
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
<= HOST_BITS_PER_WIDE_INT)
&& ((unsigned HOST_WIDE_INT) const_op
- < (((HOST_WIDE_INT) 1
+ < (((unsigned HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) - 1)))))
{
op0 = XEXP (op0, 0);
@@ -9977,7 +9998,7 @@ simplify_comparison (code, pop0, pop1)
&& GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT
&& INTVAL (XEXP (SUBREG_REG (op0), 1)) < 0
&& (- INTVAL (XEXP (SUBREG_REG (op0), 1))
- < GET_MODE_MASK (mode) / 2)
+ < (HOST_WIDE_INT)(GET_MODE_MASK (mode) / 2))
&& (unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (mode) / 2
&& (0 == (nonzero_bits (XEXP (SUBREG_REG (op0), 0),
GET_MODE (SUBREG_REG (op0)))
@@ -10181,7 +10202,7 @@ simplify_comparison (code, pop0, pop1)
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode))
- == (HOST_WIDE_INT) 1 << (mode_width - 1)))
+ == (unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
{
op0 = XEXP (op0, 0);
code = (code == EQ ? GE : LT);
@@ -10232,8 +10253,8 @@ simplify_comparison (code, pop0, pop1)
&& (INTVAL (XEXP (op0, 1)) & ~ mask) == 0
&& 0 == (~ GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
& INTVAL (XEXP (op0, 1)))
- && INTVAL (XEXP (op0, 1)) != mask
- && (INTVAL (XEXP (op0, 1))
+ && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
+ && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
!= GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
{
@@ -11012,7 +11033,7 @@ reg_dead_at_p (reg, insn)
else
{
for (block = 0; block < n_basic_blocks; block++)
- if (insn == basic_block_head[block])
+ if (insn == BLOCK_HEAD (block))
break;
if (block == n_basic_blocks)
@@ -11020,7 +11041,7 @@ reg_dead_at_p (reg, insn)
}
for (i = reg_dead_regno; i < reg_dead_endregno; i++)
- if (REGNO_REG_SET_P (basic_block_live_at_start[block], i))
+ if (REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start, i))
return 0;
return 1;
@@ -11413,6 +11434,17 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
place = i3;
break;
+ case REG_EH_REGION:
+ /* This note must remain with the call. It should not be possible
+ for both I2 and I3 to be a call. */
+ if (GET_CODE (i3) == CALL_INSN)
+ place = i3;
+ else if (i2 && GET_CODE (i2) == CALL_INSN)
+ place = i2;
+ else
+ abort ();
+ break;
+
case REG_UNUSED:
/* Any clobbers for i3 may still exist, and so we must process
REG_UNUSED notes from that insn.
@@ -11476,7 +11508,6 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
case REG_INC:
case REG_NO_CONFLICT:
- case REG_LABEL:
/* These notes say something about how a register is used. They must
be present on any use of the register in I2 or I3. */
if (reg_mentioned_p (XEXP (note, 0), PATTERN (i3)))
@@ -11491,6 +11522,30 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
}
break;
+ case REG_LABEL:
+ /* This can show up in several ways -- either directly in the
+ pattern, or hidden off in the constant pool with (or without?)
+ a REG_EQUAL note. */
+ /* ??? Ignore the without-reg_equal-note problem for now. */
+ if (reg_mentioned_p (XEXP (note, 0), PATTERN (i3))
+ || ((tem = find_reg_note (i3, REG_EQUAL, NULL_RTX))
+ && GET_CODE (XEXP (tem, 0)) == LABEL_REF
+ && XEXP (XEXP (tem, 0), 0) == XEXP (note, 0)))
+ place = i3;
+
+ if (i2
+ && (reg_mentioned_p (XEXP (note, 0), PATTERN (i2))
+ || ((tem = find_reg_note (i2, REG_EQUAL, NULL_RTX))
+ && GET_CODE (XEXP (tem, 0)) == LABEL_REF
+ && XEXP (XEXP (tem, 0), 0) == XEXP (note, 0))))
+ {
+ if (place)
+ place2 = i2;
+ else
+ place = i2;
+ }
+ break;
+
case REG_WAS_0:
/* It is too much trouble to try to see if this note is still
correct in all situations. It is better to simply delete it. */
@@ -11578,6 +11633,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
{
rtx set = single_set (tem);
rtx inner_dest = 0;
+#ifdef HAVE_cc0
+ rtx cc0_setter = NULL_RTX;
+#endif
if (set != 0)
for (inner_dest = SET_DEST (set);
@@ -11588,10 +11646,21 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
;
/* Verify that it was the set, and not a clobber that
- modified the register. */
+ modified the register.
+
+ CC0 targets must be careful to maintain setter/user
+ pairs. If we cannot delete the setter due to side
+ effects, mark the user with an UNUSED note instead
+ of deleting it. */
if (set != 0 && ! side_effects_p (SET_SRC (set))
- && rtx_equal_p (XEXP (note, 0), inner_dest))
+ && rtx_equal_p (XEXP (note, 0), inner_dest)
+#ifdef HAVE_cc0
+ && (! reg_mentioned_p (cc0_rtx, SET_SRC (set))
+ || ((cc0_setter = prev_cc0_setter (tem)) != NULL
+ && sets_cc0_p (PATTERN (cc0_setter)) > 0))
+#endif
+ )
{
/* Move the notes and links of TEM elsewhere.
This might delete other dead insns recursively.
@@ -11607,6 +11676,23 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
PUT_CODE (tem, NOTE);
NOTE_LINE_NUMBER (tem) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (tem) = 0;
+
+#ifdef HAVE_cc0
+ /* Delete the setter too. */
+ if (cc0_setter)
+ {
+ PATTERN (cc0_setter) = pc_rtx;
+
+ distribute_notes (REG_NOTES (cc0_setter),
+ cc0_setter, cc0_setter,
+ NULL_RTX, NULL_RTX, NULL_RTX);
+ distribute_links (LOG_LINKS (cc0_setter));
+
+ PUT_CODE (cc0_setter, NOTE);
+ NOTE_LINE_NUMBER (cc0_setter) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (cc0_setter) = 0;
+ }
+#endif
}
/* If the register is both set and used here, put the
REG_DEAD note here, but place a REG_UNUSED note
@@ -11672,9 +11758,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
tem);
/* If this insn was emitted between blocks, then update
- basic_block_head of the current block to include it. */
- if (basic_block_end[this_basic_block - 1] == tem)
- basic_block_head[this_basic_block] = place;
+ BLOCK_HEAD of the current block to include it. */
+ if (BLOCK_END (this_basic_block - 1) == tem)
+ BLOCK_HEAD (this_basic_block) = place;
}
}
@@ -11873,7 +11959,7 @@ distribute_links (links)
for (insn = NEXT_INSN (XEXP (link, 0));
(insn && (this_basic_block == n_basic_blocks - 1
- || basic_block_head[this_basic_block + 1] != insn));
+ || BLOCK_HEAD (this_basic_block + 1) != insn));
insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
&& reg_overlap_mentioned_p (reg, PATTERN (insn)))
@@ -11935,7 +12021,7 @@ void
dump_combine_stats (file)
FILE *file;
{
- fprintf
+ fnotice
(file,
";; Combiner statistics: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n\n",
combine_attempts, combine_merges, combine_extras, combine_successes);
@@ -11945,7 +12031,7 @@ void
dump_combine_total_stats (file)
FILE *file;
{
- fprintf
+ fnotice
(file,
"\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n",
total_attempts, total_merges, total_extras, total_successes);
diff --git a/contrib/gcc/config.in b/contrib/gcc/config.in
index b4e9898..c804a2b 100644
--- a/contrib/gcc/config.in
+++ b/contrib/gcc/config.in
@@ -1,10 +1,22 @@
/* config.in. Generated automatically from configure.in by autoheader. */
+/* Define if you can safely include both <string.h> and <strings.h>. */
+#undef STRING_WITH_STRINGS
+
/* Define if printf supports "%p". */
#undef HAVE_PRINTF_PTR
/* Define if you want expensive run-time checks. */
#undef ENABLE_CHECKING
+/* Define to 1 if NLS is requested. */
+#undef ENABLE_NLS
+
+/* Define as 1 if you have catgets and don't want to use GNU gettext. */
+#undef HAVE_CATGETS
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+#undef HAVE_GETTEXT
+
/* Define if your cpp understands the stringify operator. */
#undef HAVE_CPP_STRINGIFY
@@ -18,9 +30,22 @@
/* Define if your assembler supports .balign and .p2align. */
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
+/* Define if your assembler supports .subsection and .subsection -1 starts
+ emitting at the beginning of your section */
+#undef HAVE_GAS_SUBSECTION_ORDERING
+
+/* Define if your assembler uses the old HImode fild and fist notation. */
+#undef HAVE_GAS_FILDS_FISTS
+
/* Define if you have a working <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
+/* Define if your locale.h file contains LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define as 1 if you have the stpcpy function. */
+#undef HAVE_STPCPY
+
/* Whether malloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_MALLOC
@@ -54,6 +79,9 @@
/* Whether atol must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_ATOL
+/* Whether atof must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_ATOF
+
/* Whether sbrk must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_SBRK
@@ -63,6 +91,12 @@
/* Whether strerror must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRERROR
+/* Whether strsignal must be declared even if <string.h> is included. */
+#undef NEED_DECLARATION_STRSIGNAL
+
+/* Whether strstr must be declared even if <string.h> is included. */
+#undef NEED_DECLARATION_STRSTR
+
/* Whether getcwd must be declared even if <unistd.h> is included. */
#undef NEED_DECLARATION_GETCWD
@@ -75,15 +109,79 @@
/* Whether setrlimit must be declared even if <sys/resource.h> is included. */
#undef NEED_DECLARATION_SETRLIMIT
-/* Define if you want expensive run-time checks. */
-#undef ENABLE_CHECKING
+/* Whether putc_unlocked must be declared even if <stdio.h> is included. */
+#undef NEED_DECLARATION_PUTC_UNLOCKED
+
+/* Whether fputs_unlocked must be declared even if <stdio.h> is included. */
+#undef NEED_DECLARATION_FPUTS_UNLOCKED
+
+/* Define to enable the use of a default assembler. */
+#undef DEFAULT_ASSEMBLER
+
+/* Define to enable the use of a default linker. */
+#undef DEFAULT_LINKER
+
+/* Define if host mkdir takes a single argument. */
+#undef MKDIR_TAKES_ONE_ARG
+
+/* Define to the name of the distribution. */
+#undef PACKAGE
+
+/* Define to the version of the distribution. */
+#undef VERSION
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
/* Define if you don't have vprintf but do have _doprnt. */
#undef HAVE_DOPRNT
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if you have <vfork.h>. */
+#undef HAVE_VFORK_H
+
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
@@ -93,6 +191,18 @@
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
+/* Define vfork as fork if vfork does not work. */
+#undef vfork
+
+/* Define if you have the __argz_count function. */
+#undef HAVE___ARGZ_COUNT
+
+/* Define if you have the __argz_next function. */
+#undef HAVE___ARGZ_NEXT
+
+/* Define if you have the __argz_stringify function. */
+#undef HAVE___ARGZ_STRINGIFY
+
/* Define if you have the atoll function. */
#undef HAVE_ATOLL
@@ -111,6 +221,21 @@
/* Define if you have the bzero function. */
#undef HAVE_BZERO
+/* Define if you have the dcgettext function. */
+#undef HAVE_DCGETTEXT
+
+/* Define if you have the fputc_unlocked function. */
+#undef HAVE_FPUTC_UNLOCKED
+
+/* Define if you have the fputs_unlocked function. */
+#undef HAVE_FPUTS_UNLOCKED
+
+/* Define if you have the getcwd function. */
+#undef HAVE_GETCWD
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
/* Define if you have the getrlimit function. */
#undef HAVE_GETRLIMIT
@@ -126,39 +251,78 @@
/* Define if you have the kill function. */
#undef HAVE_KILL
+/* Define if you have the munmap function. */
+#undef HAVE_MUNMAP
+
/* Define if you have the popen function. */
#undef HAVE_POPEN
+/* Define if you have the putc_unlocked function. */
+#undef HAVE_PUTC_UNLOCKED
+
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if you have the rindex function. */
#undef HAVE_RINDEX
+/* Define if you have the setenv function. */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function. */
+#undef HAVE_SETLOCALE
+
/* Define if you have the setrlimit function. */
#undef HAVE_SETRLIMIT
+/* Define if you have the stpcpy function. */
+#undef HAVE_STPCPY
+
+/* Define if you have the strcasecmp function. */
+#undef HAVE_STRCASECMP
+
/* Define if you have the strchr function. */
#undef HAVE_STRCHR
+/* Define if you have the strdup function. */
+#undef HAVE_STRDUP
+
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the strrchr function. */
#undef HAVE_STRRCHR
+/* Define if you have the strsignal function. */
+#undef HAVE_STRSIGNAL
+
/* Define if you have the strtoul function. */
#undef HAVE_STRTOUL
/* Define if you have the sysconf function. */
#undef HAVE_SYSCONF
+/* Define if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <direct.h> header file. */
+#undef HAVE_DIRECT_H
+
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
+/* Define if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
/* Define if you have the <stab.h> header file. */
#undef HAVE_STAB_H
@@ -183,20 +347,20 @@
/* Define if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
+/* Define if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/times.h> header file. */
#undef HAVE_SYS_TIMES_H
-/* Define if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
-
/* Define if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
-/* Define if you have the <wait.h> header file. */
-#undef HAVE_WAIT_H
+/* Define if you have the i library (-li). */
+#undef HAVE_LIBI
diff --git a/contrib/gcc/config/alpha/alpha-interix.h b/contrib/gcc/config/alpha/alpha-interix.h
new file mode 100644
index 0000000..668fe93
--- /dev/null
+++ b/contrib/gcc/config/alpha/alpha-interix.h
@@ -0,0 +1,252 @@
+/* Definitions of target machine for GNU compiler, for DEC Alpha
+ running Windows/NT.
+ Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc.
+
+ Donn Terry, Softway Systems, Inc.
+ From code
+ Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* cpp handles __STDC__ */
+/* The three "Alpha" defines on the first such line are from the CLAXP spec */
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES " \
+ -D__INTERIX \
+ -D__OPENNT \
+ -D__Alpha_AXP -D_M_ALPHA -D_ALPHA_ \
+ -D__alpha -D__alpha__\
+ -D__stdcall= \
+ -D__cdecl= \
+ -Asystem(unix) -Asystem(interix) -Asystem(interix) -Acpu(alpha) -Amachine(alpha)"
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "\
+-remap \
+%{posix:-D_POSIX_SOURCE} \
+-idirafter %$INTERIX_ROOT/usr/include"
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (alpha Interix)");
+
+/* alpha.h sets this, but it doesn't apply to us */
+#undef OBJECT_FORMAT_ECOFF
+#undef OBJECT_FORMAT_COFF
+
+/* LINK_SPEC */
+
+/* MD_STARTFILE_PREFIX */
+
+/* ASM_OUTPUT_LOOP_ALIGN; ASM_OUTPUT_ALIGN_CODE */
+
+/* Codegen macro overrides for NT internal conventions */
+
+/* the below are ecoff specific... we don't need them, so
+ undef them (they'll get a default later) */
+
+#undef PUT_SDB_BLOCK_START
+#undef PUT_SDB_BLOCK_END
+
+/* the following are OSF linker (not gld) specific... we don't want them */
+#undef HAS_INIT_SECTION
+#undef LD_INIT_SWITCH
+#undef LD_FINI_SWITCH
+
+
+/* The following are needed for C++, but also needed for profiling */
+
+/* Support const sections and the ctors and dtors sections for g++.
+ Note that there appears to be two different ways to support const
+ sections at the moment. You can either #define the symbol
+ READONLY_DATA_SECTION (giving it some code which switches to the
+ readonly data section) or else you can #define the symbols
+ EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
+ SELECT_RTX_SECTION. We do both here just to be on the safe side. */
+
+#define USE_CONST_SECTION 1
+
+#define CONST_SECTION_ASM_OP ".rdata"
+
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+
+ Note that we want to give these sections the SHF_WRITE attribute
+ because these sections will actually contain data (i.e. tables of
+ addresses of functions in the current root executable or shared library
+ file) and, in the case of a shared library, the relocatable addresses
+ will have to be properly resolved/relocated (and then written into) by
+ the dynamic linker when it actually attaches the given shared library
+ to the executing process. (Note that on SVR4, you may wish to use the
+ `-z text' option to the ELF linker, when building a shared library, as
+ an additional check that you are doing everything right. But if you do
+ use the `-z text' option when building a shared library, you will get
+ errors unless the .ctors and .dtors sections are marked as writable
+ via the SHF_WRITE attribute.) */
+
+#define CTORS_SECTION_ASM_OP ".ctors"
+#define DTORS_SECTION_ASM_OP ".dtors"
+
+/* A default list of other sections which we might be "in" at any given
+ time. For targets that use additional sections (e.g. .tdesc) you
+ should override this definition in the target-specific file which
+ includes this file. */
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
+
+/* A default list of extra section function definitions. For targets
+ that use additional sections (e.g. .tdesc) you should override this
+ definition in the target-specific file which includes this file. */
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CONST_SECTION_FUNCTION \
+ CTORS_SECTION_FUNCTION \
+ DTORS_SECTION_FUNCTION
+
+#undef READONLY_DATA_SECTION
+#define READONLY_DATA_SECTION() const_section ()
+
+extern void text_section ();
+
+#define CONST_SECTION_FUNCTION \
+void \
+const_section () \
+{ \
+ if (!USE_CONST_SECTION) \
+ text_section(); \
+ else if (in_section != in_const) \
+ { \
+ fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
+ in_section = in_const; \
+ } \
+}
+
+#define CTORS_SECTION_FUNCTION \
+void \
+ctors_section () \
+{ \
+ if (in_section != in_ctors) \
+ { \
+ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
+ in_section = in_ctors; \
+ } \
+}
+
+#define DTORS_SECTION_FUNCTION \
+void \
+dtors_section () \
+{ \
+ if (in_section != in_dtors) \
+ { \
+ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
+ in_section = in_dtors; \
+ } \
+}
+
+#define INT_ASM_OP ".long"
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global constructors. */
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global destructors. */
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* The linker will take care of this, and having them causes problems with
+ ld -r (specifically -rU). */
+#define CTOR_LISTS_DEFINED_EXTERNALLY 1
+
+#define SET_ASM_OP ".set"
+/* Output a definition (implements alias) */
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+do \
+{ \
+ fprintf ((FILE), "\t"); \
+ assemble_name (FILE, LABEL1); \
+ fprintf (FILE, "="); \
+ assemble_name (FILE, LABEL2); \
+ fprintf (FILE, "\n"); \
+ } \
+while (0)
+
+/* We use the defaults, so undef the null definitions */
+#undef PUT_SDB_FUNCTION_START
+#undef PUT_SDB_FUNCTION_END
+#undef PUT_SDB_EPILOGUE_END
+
+#define HOST_PTR_PRINTF "%p"
+#define HOST_PTR_AS_INT unsigned long
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+#define PCC_BITFIELD_TYPE_TEST TYPE_NATIVE(rec)
+#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
+
+/* DWARF2 Unwinding doesn't work with exception handling yet. */
+#undef DWARF2_UNWIND_INFO
+
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+/* The definition of this macro implies that there are cases where
+ a scalar value cannot be returned in registers.
+
+ On NT (according to the spec) anything except strings/array that fits
+ in 64 bits is returned in the registers (this appears to differ from
+ the rest of the Alpha family). */
+
+#undef RETURN_IN_MEMORY
+#define RETURN_IN_MEMORY(TYPE) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE || int_size_in_bytes(TYPE) > 8)
+
+#define ASM_LOAD_ADDR(loc, reg) " lda " #reg "," #loc "\n"
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+{ \
+ alpha_write_verstamp (FILE); \
+ fprintf (FILE, "\t.set noreorder\n"); \
+ fprintf (FILE, "\t.set volatile\n"); \
+ fprintf (FILE, "\t.set noat\n"); \
+ fprintf (FILE, "\t.globl\t__fltused\n"); \
+ ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \
+}
+
+/* The current Interix assembler (consistent with the DEC documentation)
+ uses a=b NOT .set a,b; .set is for assembler options. */
+#undef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \
+ do { \
+ assemble_name (FILE, SY); \
+ fputc ('=', FILE); \
+ assemble_name (FILE, HI); \
+ fputc ('-', FILE); \
+ assemble_name (FILE, LO); \
+ } while (0)
diff --git a/contrib/gcc/config/alpha/alpha.c b/contrib/gcc/config/alpha/alpha.c
index 0b72289..2d62693 100644
--- a/contrib/gcc/config/alpha/alpha.c
+++ b/contrib/gcc/config/alpha/alpha.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on the DEC Alpha.
- Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -48,7 +48,7 @@ extern int rtx_equal_function_value_matters;
/* Specify which cpu to schedule for. */
enum processor_type alpha_cpu;
-static char* const alpha_cpu_name[] =
+static const char * const alpha_cpu_name[] =
{
"ev4", "ev5", "ev6"
};
@@ -67,11 +67,11 @@ enum alpha_fp_trap_mode alpha_fptm;
/* Strings decoded into the above options. */
-char *alpha_cpu_string; /* -mcpu= */
-char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */
-char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */
-char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */
-char *alpha_mlat_string; /* -mmemory-latency= */
+const char *alpha_cpu_string; /* -mcpu= */
+const char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */
+const char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */
+const char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */
+const char *alpha_mlat_string; /* -mmemory-latency= */
/* Save information from a "cmpxx" operation until the branch or scc is
emitted. */
@@ -79,6 +79,10 @@ char *alpha_mlat_string; /* -mmemory-latency= */
rtx alpha_compare_op0, alpha_compare_op1;
int alpha_compare_fp_p;
+/* Define the information needed to modify the epilogue for EH. */
+
+rtx alpha_eh_epilogue_sp_ofs;
+
/* Non-zero if inside of a function, because the Alpha asm can't
handle .files inside of functions. */
@@ -96,6 +100,10 @@ int alpha_memory_latency = 3;
static int alpha_function_needs_gp;
+/* The alias set for prologue/epilogue register save/restore. */
+
+static int alpha_sr_alias_set;
+
/* Declarations of static functions. */
static void alpha_set_memflags_1
PROTO((rtx, int, int, int));
@@ -126,49 +134,6 @@ static int alpha_does_function_need_gp
void
override_options ()
{
- alpha_cpu
- = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
- : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
-
- if (alpha_cpu_string)
- {
- if (! strcmp (alpha_cpu_string, "ev4")
- || ! strcmp (alpha_cpu_string, "21064"))
- {
- alpha_cpu = PROCESSOR_EV4;
- target_flags &= ~ (MASK_BWX | MASK_CIX | MASK_MAX);
- }
- else if (! strcmp (alpha_cpu_string, "ev5")
- || ! strcmp (alpha_cpu_string, "21164"))
- {
- alpha_cpu = PROCESSOR_EV5;
- target_flags &= ~ (MASK_BWX | MASK_CIX | MASK_MAX);
- }
- else if (! strcmp (alpha_cpu_string, "ev56")
- || ! strcmp (alpha_cpu_string, "21164a"))
- {
- alpha_cpu = PROCESSOR_EV5;
- target_flags |= MASK_BWX;
- target_flags &= ~ (MASK_CIX | MASK_MAX);
- }
- else if (! strcmp (alpha_cpu_string, "pca56")
- || ! strcmp (alpha_cpu_string, "21164PC")
- || ! strcmp (alpha_cpu_string, "21164pc"))
- {
- alpha_cpu = PROCESSOR_EV5;
- target_flags |= MASK_BWX | MASK_MAX;
- target_flags &= ~ MASK_CIX;
- }
- else if (! strcmp (alpha_cpu_string, "ev6")
- || ! strcmp (alpha_cpu_string, "21264"))
- {
- alpha_cpu = PROCESSOR_EV6;
- target_flags |= MASK_BWX | MASK_CIX | MASK_MAX;
- }
- else
- error ("bad value `%s' for -mcpu switch", alpha_cpu_string);
- }
-
alpha_tp = ALPHA_TP_PROG;
alpha_fprm = ALPHA_FPRM_NORM;
alpha_fptm = ALPHA_FPTM_N;
@@ -226,10 +191,54 @@ override_options ()
error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
}
- /* Do some sanity checks on the above option. */
+ alpha_cpu
+ = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
+ : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
+
+ if (alpha_cpu_string)
+ {
+ if (! strcmp (alpha_cpu_string, "ev4")
+ || ! strcmp (alpha_cpu_string, "21064"))
+ {
+ alpha_cpu = PROCESSOR_EV4;
+ target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX);
+ }
+ else if (! strcmp (alpha_cpu_string, "ev5")
+ || ! strcmp (alpha_cpu_string, "21164"))
+ {
+ alpha_cpu = PROCESSOR_EV5;
+ target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX);
+ }
+ else if (! strcmp (alpha_cpu_string, "ev56")
+ || ! strcmp (alpha_cpu_string, "21164a"))
+ {
+ alpha_cpu = PROCESSOR_EV5;
+ target_flags |= MASK_BWX;
+ target_flags &= ~ (MASK_MAX | MASK_FIX | MASK_CIX);
+ }
+ else if (! strcmp (alpha_cpu_string, "pca56")
+ || ! strcmp (alpha_cpu_string, "21164PC")
+ || ! strcmp (alpha_cpu_string, "21164pc"))
+ {
+ alpha_cpu = PROCESSOR_EV5;
+ target_flags |= MASK_BWX | MASK_MAX;
+ target_flags &= ~ (MASK_FIX | MASK_CIX);
+ }
+ else if (! strcmp (alpha_cpu_string, "ev6")
+ || ! strcmp (alpha_cpu_string, "21264"))
+ {
+ alpha_cpu = PROCESSOR_EV6;
+ target_flags |= MASK_BWX | MASK_MAX | MASK_FIX;
+ target_flags &= ~ (MASK_CIX);
+ }
+ else
+ error ("bad value `%s' for -mcpu switch", alpha_cpu_string);
+ }
+
+ /* Do some sanity checks on the above options. */
if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
- && alpha_tp != ALPHA_TP_INSN)
+ && alpha_tp != ALPHA_TP_INSN && alpha_cpu != PROCESSOR_EV6)
{
warning ("fp software completion requires -mtrap-precision=i");
alpha_tp = ALPHA_TP_INSN;
@@ -256,11 +265,11 @@ override_options ()
if (!alpha_mlat_string)
alpha_mlat_string = "L1";
- if (isdigit (alpha_mlat_string[0])
+ if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
&& (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
;
else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
- && isdigit (alpha_mlat_string[1])
+ && ISDIGIT ((unsigned char)alpha_mlat_string[1])
&& alpha_mlat_string[2] == '\0')
{
static int const cache_latency[][4] =
@@ -298,6 +307,9 @@ override_options ()
/* Default the definition of "small data" to 8 bytes. */
if (!g_switch_set)
g_switch_value = 8;
+
+ /* Acquire a unique set number for our register saves and restores. */
+ alpha_sr_alias_set = new_alias_set ();
}
/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
@@ -337,7 +349,6 @@ reg_or_6bit_operand (op, mode)
{
return ((GET_CODE (op) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
- || GET_CODE (op) == CONSTANT_P_RTX
|| register_operand (op, mode));
}
@@ -351,7 +362,6 @@ reg_or_8bit_operand (op, mode)
{
return ((GET_CODE (op) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
- || GET_CODE (op) == CONSTANT_P_RTX
|| register_operand (op, mode));
}
@@ -363,8 +373,7 @@ cint8_operand (op, mode)
enum machine_mode mode ATTRIBUTE_UNUSED;
{
return ((GET_CODE (op) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
- || GET_CODE (op) == CONSTANT_P_RTX);
+ && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));
}
/* Return 1 if the operand is a valid second operand to an add insn. */
@@ -375,11 +384,9 @@ add_operand (op, mode)
enum machine_mode mode;
{
if (GET_CODE (op) == CONST_INT)
+ /* Constraints I, J, O and P are covered by K. */
return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
- || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')
- || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
- else if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
+ || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
return register_operand (op, mode);
}
@@ -393,10 +400,8 @@ sext_add_operand (op, mode)
enum machine_mode mode;
{
if (GET_CODE (op) == CONST_INT)
- return ((unsigned HOST_WIDE_INT) INTVAL (op) < 255
- || (unsigned HOST_WIDE_INT) (- INTVAL (op)) < 255);
- else if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
+ return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
return register_operand (op, mode);
}
@@ -427,8 +432,6 @@ and_operand (op, mode)
return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
|| (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
|| zap_mask (INTVAL (op)));
- else if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
return register_operand (op, mode);
}
@@ -443,8 +446,6 @@ or_operand (op, mode)
if (GET_CODE (op) == CONST_INT)
return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
|| (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);
- else if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
return register_operand (op, mode);
}
@@ -483,9 +484,9 @@ mode_mask_operand (op, mode)
return (GET_CODE (op) == CONST_INT
&& (INTVAL (op) == 0xff
|| INTVAL (op) == 0xffff
- || INTVAL (op) == 0xffffffff
+ || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
#if HOST_BITS_PER_WIDE_INT == 64
- || INTVAL (op) == 0xffffffffffffffff
+ || INTVAL (op) == -1
#endif
));
}
@@ -544,7 +545,6 @@ reg_or_cint_operand (op, mode)
enum machine_mode mode;
{
return (GET_CODE (op) == CONST_INT
- || GET_CODE (op) == CONSTANT_P_RTX
|| register_operand (op, mode));
}
@@ -562,7 +562,7 @@ some_operand (op, mode)
switch (GET_CODE (op))
{
case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF:
- case SYMBOL_REF: case CONST: case CONSTANT_P_RTX:
+ case SYMBOL_REF: case CONST:
return 1;
case SUBREG:
@@ -611,9 +611,11 @@ input_operand (op, mode)
return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
case CONST_INT:
- case CONSTANT_P_RTX:
return mode == QImode || mode == HImode || add_operand (op, mode);
+ case CONSTANT_P_RTX:
+ return 1;
+
default:
break;
}
@@ -726,40 +728,49 @@ divmod_operator (op, mode)
a constant. It must be a valid address. This means that we can do
this as an aligned reference plus some offset.
- Take into account what reload will do.
-
- We could say that out-of-range stack slots are alignable, but that would
- complicate get_aligned_mem and it isn't worth the trouble since few
- functions have large stack space. */
+ Take into account what reload will do. */
int
aligned_memory_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
- if (GET_CODE (op) == SUBREG)
+ rtx base;
+
+ if (reload_in_progress)
{
- if (GET_MODE (op) != mode)
- return 0;
- op = SUBREG_REG (op);
- mode = GET_MODE (op);
+ rtx tmp = op;
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG
+ && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
+ {
+ op = reg_equiv_memory_loc[REGNO (tmp)];
+ if (op == 0)
+ return 0;
+ }
}
- if (reload_in_progress && GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)
- op = reg_equiv_mem[REGNO (op)];
-
- if (GET_CODE (op) != MEM || GET_MODE (op) != mode
- || ! memory_address_p (mode, XEXP (op, 0)))
+ if (GET_CODE (op) != MEM
+ || GET_MODE (op) != mode)
return 0;
-
op = XEXP (op, 0);
- if (GET_CODE (op) == PLUS)
- op = XEXP (op, 0);
+ /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
+ sorts of constructs. Dig for the real base register. */
+ if (reload_in_progress
+ && GET_CODE (op) == PLUS
+ && GET_CODE (XEXP (op, 0)) == PLUS)
+ base = XEXP (XEXP (op, 0), 0);
+ else
+ {
+ if (! memory_address_p (mode, op))
+ return 0;
+ base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
+ }
- return (GET_CODE (op) == REG
- && REGNO_POINTER_ALIGN (REGNO (op)) >= 4);
+ return (GET_CODE (base) == REG
+ && REGNO_POINTER_ALIGN (REGNO (base)) >= 4);
}
/* Similar, but return 1 if OP is a MEM which is not alignable. */
@@ -769,31 +780,42 @@ unaligned_memory_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
- if (GET_CODE (op) == SUBREG)
+ rtx base;
+
+ if (reload_in_progress)
{
- if (GET_MODE (op) != mode)
- return 0;
- op = SUBREG_REG (op);
- mode = GET_MODE (op);
+ rtx tmp = op;
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG
+ && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
+ {
+ op = reg_equiv_memory_loc[REGNO (tmp)];
+ if (op == 0)
+ return 0;
+ }
}
- if (reload_in_progress && GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)
- op = reg_equiv_mem[REGNO (op)];
-
- if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
+ if (GET_CODE (op) != MEM
+ || GET_MODE (op) != mode)
return 0;
-
op = XEXP (op, 0);
- if (! memory_address_p (mode, op))
- return 1;
-
- if (GET_CODE (op) == PLUS)
- op = XEXP (op, 0);
+ /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
+ sorts of constructs. Dig for the real base register. */
+ if (reload_in_progress
+ && GET_CODE (op) == PLUS
+ && GET_CODE (XEXP (op, 0)) == PLUS)
+ base = XEXP (XEXP (op, 0), 0);
+ else
+ {
+ if (! memory_address_p (mode, op))
+ return 0;
+ base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
+ }
- return (GET_CODE (op) != REG
- || REGNO_POINTER_ALIGN (REGNO (op)) < 4);
+ return (GET_CODE (base) == REG
+ && REGNO_POINTER_ALIGN (REGNO (base)) < 4);
}
/* Return 1 if OP is either a register or an unaligned memory location. */
@@ -822,6 +844,74 @@ any_memory_operand (op, mode)
&& REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
}
+/* Returns 1 if OP is not an eliminable register.
+
+ This exists to cure a pathological abort in the s8addq (et al) patterns,
+
+ long foo () { long t; bar(); return (long) &t * 26107; }
+
+ which run afoul of a hack in reload to cure a (presumably) similar
+ problem with lea-type instructions on other targets. But there is
+ one of us and many of them, so work around the problem by selectively
+ preventing combine from making the optimization. */
+
+int
+reg_not_elim_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ rtx inner = op;
+ if (GET_CODE (op) == SUBREG)
+ inner = SUBREG_REG (op);
+ if (inner == frame_pointer_rtx || inner == arg_pointer_rtx)
+ return 0;
+
+ return register_operand (op, mode);
+}
+
+/* Return 1 is OP is a memory location that is not a reference (using
+ an AND) to an unaligned location. Take into account what reload
+ will do. */
+
+int
+normal_memory_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (reload_in_progress)
+ {
+ rtx tmp = op;
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG
+ && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
+ {
+ op = reg_equiv_memory_loc[REGNO (tmp)];
+
+ /* This may not have been assigned an equivalent address if it will
+ be eliminated. In that case, it doesn't matter what we do. */
+ if (op == 0)
+ return 1;
+ }
+ }
+
+ return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) != AND;
+}
+
+/* Accept a register, but not a subreg of any kind. This allows us to
+ avoid pathological cases in reload wrt data movement common in
+ int->fp conversion. */
+
+int
+reg_no_subreg_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == SUBREG)
+ return 0;
+ return register_operand (op, mode);
+}
+
/* Return 1 if this function can directly return via $26. */
int
@@ -835,7 +925,8 @@ direct_return ()
/* REF is an alignable memory location. Place an aligned SImode
reference into *PALIGNED_MEM and the number of bits to shift into
- *PBITNUM. */
+ *PBITNUM. SCRATCH is a free register for use in reloading out
+ of range stack slots. */
void
get_aligned_mem (ref, paligned_mem, pbitnum)
@@ -845,33 +936,33 @@ get_aligned_mem (ref, paligned_mem, pbitnum)
rtx base;
HOST_WIDE_INT offset = 0;
- if (GET_CODE (ref) == SUBREG)
- {
- offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
- - MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
- ref = SUBREG_REG (ref);
- }
+ if (GET_CODE (ref) != MEM)
+ abort ();
- if (GET_CODE (ref) == REG)
- ref = reg_equiv_mem[REGNO (ref)];
+ if (reload_in_progress
+ && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
+ {
+ base = find_replacement (&XEXP (ref, 0));
- if (reload_in_progress)
- base = find_replacement (&XEXP (ref, 0));
+ if (! memory_address_p (GET_MODE (ref), base))
+ abort ();
+ }
else
- base = XEXP (ref, 0);
+ {
+ base = XEXP (ref, 0);
+ }
if (GET_CODE (base) == PLUS)
offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
- *paligned_mem = gen_rtx_MEM (SImode,
- plus_constant (base, offset & ~3));
- MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref);
- MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref);
+ *paligned_mem = gen_rtx_MEM (SImode, plus_constant (base, offset & ~3));
+ MEM_COPY_ATTRIBUTES (*paligned_mem, ref);
RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref);
+ /* Sadly, we cannot use alias sets here because we may overlap other
+ data in a different alias set. */
+ /* MEM_ALIAS_SET (*paligned_mem) = MEM_ALIAS_SET (ref); */
+
*pbitnum = GEN_INT ((offset & 3) * 8);
}
@@ -886,23 +977,21 @@ get_unaligned_address (ref, extra_offset)
rtx base;
HOST_WIDE_INT offset = 0;
- if (GET_CODE (ref) == SUBREG)
- {
- offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
- - MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
- ref = SUBREG_REG (ref);
- }
+ if (GET_CODE (ref) != MEM)
+ abort ();
- if (GET_CODE (ref) == REG)
- ref = reg_equiv_mem[REGNO (ref)];
+ if (reload_in_progress
+ && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
+ {
+ base = find_replacement (&XEXP (ref, 0));
- if (reload_in_progress)
- base = find_replacement (&XEXP (ref, 0));
+ if (! memory_address_p (GET_MODE (ref), base))
+ abort ();
+ }
else
- base = XEXP (ref, 0);
+ {
+ base = XEXP (ref, 0);
+ }
if (GET_CODE (base) == PLUS)
offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
@@ -945,6 +1034,12 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
MEM_IN_STRUCT_P (x) = in_struct_p;
MEM_VOLATILE_P (x) = volatile_p;
RTX_UNCHANGING_P (x) = unchanging_p;
+ /* Sadly, we cannot use alias sets because the extra aliasing
+ produced by the AND interferes. Given that two-byte quantities
+ are the only thing we would be able to differentiate anyway,
+ there does not seem to be any point in convoluting the early
+ out of the alias check. */
+ /* MEM_ALIAS_SET (x) = alias_set; */
break;
default:
@@ -963,14 +1058,19 @@ alpha_set_memflags (insn, ref)
rtx insn;
rtx ref;
{
- /* Note that it is always safe to get these flags, though they won't
- be what we think if REF is not a MEM. */
- int in_struct_p = MEM_IN_STRUCT_P (ref);
- int volatile_p = MEM_VOLATILE_P (ref);
- int unchanging_p = RTX_UNCHANGING_P (ref);
-
- if (GET_CODE (ref) != MEM
- || (! in_struct_p && ! volatile_p && ! unchanging_p))
+ int in_struct_p, volatile_p, unchanging_p;
+
+ if (GET_CODE (ref) != MEM)
+ return;
+
+ in_struct_p = MEM_IN_STRUCT_P (ref);
+ volatile_p = MEM_VOLATILE_P (ref);
+ unchanging_p = RTX_UNCHANGING_P (ref);
+
+ /* This is only called from alpha.md, after having had something
+ generated from one of the insn patterns. So if everything is
+ zero, the pattern is already up-to-date. */
+ if (! in_struct_p && ! volatile_p && ! unchanging_p)
return;
alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
@@ -1128,7 +1228,7 @@ alpha_emit_set_const_1 (target, mode, c, n)
for (; bits > 0; bits--)
if ((temp = (alpha_emit_set_const
(subtarget, mode,
- (unsigned HOST_WIDE_INT) c >> bits, i))) != 0
+ (unsigned HOST_WIDE_INT) (c >> bits), i))) != 0
|| ((temp = (alpha_emit_set_const
(subtarget, mode,
((unsigned HOST_WIDE_INT) c) >> bits, i)))
@@ -1176,70 +1276,66 @@ alpha_emit_set_const_1 (target, mode, c, n)
return 0;
}
-#if HOST_BITS_PER_WIDE_INT == 64
/* Having failed to find a 3 insn sequence in alpha_emit_set_const,
fall back to a straight forward decomposition. We do this to avoid
exponential run times encountered when looking for longer sequences
with alpha_emit_set_const. */
rtx
-alpha_emit_set_long_const (target, c)
+alpha_emit_set_long_const (target, c1, c2)
rtx target;
- HOST_WIDE_INT c;
+ HOST_WIDE_INT c1, c2;
{
- /* Use a pseudo if highly optimizing and still generating RTL. */
- rtx subtarget
- = (flag_expensive_optimizations && rtx_equal_function_value_matters
- ? 0 : target);
HOST_WIDE_INT d1, d2, d3, d4;
- rtx r1, r2;
/* Decompose the entire word */
- d1 = ((c & 0xffff) ^ 0x8000) - 0x8000;
- c -= d1;
- d2 = ((c & 0xffffffff) ^ 0x80000000) - 0x80000000;
- c = (c - d2) >> 32;
- d3 = ((c & 0xffff) ^ 0x8000) - 0x8000;
- c -= d3;
- d4 = ((c & 0xffffffff) ^ 0x80000000) - 0x80000000;
-
- if (c - d4 != 0)
- abort();
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (c2 != -(c1 < 0))
+ abort ();
+ d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
+ c1 -= d1;
+ d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ c1 = (c1 - d2) >> 32;
+ d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
+ c1 -= d3;
+ d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ if (c1 != d4)
+ abort ();
+#else
+ d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
+ c1 -= d1;
+ d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ if (c1 != d2)
+ abort ();
+ c2 += (d2 < 0);
+ d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
+ c2 -= d3;
+ d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ if (c2 != d4)
+ abort ();
+#endif
/* Construct the high word */
- if (d3 == 0)
- r1 = copy_to_suggested_reg (GEN_INT (d4), subtarget, DImode);
- else if (d4 == 0)
- r1 = copy_to_suggested_reg (GEN_INT (d3), subtarget, DImode);
+ if (d4)
+ {
+ emit_move_insn (target, GEN_INT (d4));
+ if (d3)
+ emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3)));
+ }
else
- r1 = expand_binop (DImode, add_optab, GEN_INT (d3), GEN_INT (d4),
- subtarget, 0, OPTAB_WIDEN);
+ emit_move_insn (target, GEN_INT (d3));
/* Shift it into place */
- r2 = expand_binop (DImode, ashl_optab, r1, GEN_INT (32),
- subtarget, 0, OPTAB_WIDEN);
-
- if (subtarget == 0 && d1 == d3 && d2 == d4)
- r1 = expand_binop (DImode, add_optab, r1, r2, subtarget, 0, OPTAB_WIDEN);
- else
- {
- r1 = r2;
-
- /* Add in the low word */
- if (d2 != 0)
- r1 = expand_binop (DImode, add_optab, r1, GEN_INT (d2),
- subtarget, 0, OPTAB_WIDEN);
- if (d1 != 0)
- r1 = expand_binop (DImode, add_optab, r1, GEN_INT (d1),
- subtarget, 0, OPTAB_WIDEN);
- }
+ emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
- if (subtarget == 0)
- r1 = copy_to_suggested_reg(r1, target, DImode);
+ /* Add in the low bits. */
+ if (d2)
+ emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2)));
+ if (d1)
+ emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1)));
- return r1;
+ return target;
}
-#endif /* HOST_BITS_PER_WIDE_INT == 64 */
/* Generate the comparison for a conditional branch. */
@@ -1416,7 +1512,7 @@ alpha_emit_conditional_move (cmp, mode)
abort ();
}
- /* ??? We mark the the branch mode to be CCmode to prevent the compare
+ /* ??? We mark the branch mode to be CCmode to prevent the compare
and cmov from being combined, since the compare insn follows IEEE
rules that the cmov does not. */
if (alpha_compare_fp_p && !flag_fast_math)
@@ -1517,6 +1613,8 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
emit_insn (gen_extqh (exth, memh, addr));
mode = DImode;
break;
+ default:
+ abort();
}
addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
@@ -1790,7 +1888,8 @@ alpha_expand_block_move (operands)
{
rtx bytes_rtx = operands[2];
rtx align_rtx = operands[3];
- HOST_WIDE_INT bytes = INTVAL (bytes_rtx);
+ HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
+ HOST_WIDE_INT bytes = orig_bytes;
HOST_WIDE_INT src_align = INTVAL (align_rtx);
HOST_WIDE_INT dst_align = src_align;
rtx orig_src = operands[1];
@@ -1863,17 +1962,24 @@ alpha_expand_block_move (operands)
enum machine_mode mode;
tmp = XEXP (XEXP (orig_src, 0), 0);
- mode = mode_for_size (bytes, MODE_INT, 1);
+ /* Don't use the existing register if we're reading more than
+ is held in the register. Nor if there is not a mode that
+ handles the exact size. */
+ mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
if (mode != BLKmode
- && GET_MODE_SIZE (GET_MODE (tmp)) <= bytes)
+ && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes)
{
- /* Whee! Optimize the load to use the existing register. */
- data_regs[nregs++] = gen_lowpart (mode, tmp);
+ if (mode == TImode)
+ {
+ data_regs[nregs] = gen_lowpart (DImode, tmp);
+ data_regs[nregs+1] = gen_highpart (DImode, tmp);
+ nregs += 2;
+ }
+ else
+ data_regs[nregs++] = gen_lowpart (mode, tmp);
goto src_done;
}
- /* ??? We could potentially be copying 3 bytes or whatnot from
- a wider reg. Probably not worth worrying about. */
/* No appropriate mode; fall back on memory. */
orig_src = change_address (orig_src, GET_MODE (orig_src),
copy_addr_to_reg (XEXP (orig_src, 0)));
@@ -1890,9 +1996,9 @@ alpha_expand_block_move (operands)
for (i = 0; i < words; ++i)
{
emit_move_insn (data_regs[nregs+i],
- change_address(orig_src, DImode,
- plus_constant (XEXP (orig_src, 0),
- ofs + i*8)));
+ change_address (orig_src, DImode,
+ plus_constant (XEXP (orig_src, 0),
+ ofs + i*8)));
}
nregs += words;
@@ -1909,9 +2015,9 @@ alpha_expand_block_move (operands)
for (i = 0; i < words; ++i)
{
emit_move_insn (data_regs[nregs+i],
- change_address(orig_src, SImode,
- plus_constant (XEXP (orig_src, 0),
- ofs + i*4)));
+ change_address (orig_src, SImode,
+ plus_constant (XEXP (orig_src, 0),
+ ofs + i*4)));
}
nregs += words;
@@ -1925,7 +2031,8 @@ alpha_expand_block_move (operands)
for (i = 0; i < words+1; ++i)
data_regs[nregs+i] = gen_reg_rtx(DImode);
- alpha_expand_unaligned_load_words(data_regs+nregs, orig_src, words, ofs);
+ alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
+ words, ofs);
nregs += words;
bytes -= words * 8;
@@ -1979,7 +2086,7 @@ alpha_expand_block_move (operands)
}
src_done:
- if (nregs > sizeof(data_regs)/sizeof(*data_regs))
+ if (nregs > (int)(sizeof(data_regs)/sizeof(*data_regs)))
abort();
/*
@@ -1993,19 +2100,51 @@ alpha_expand_block_move (operands)
enum machine_mode mode;
tmp = XEXP (XEXP (orig_dst, 0), 0);
- mode = mode_for_size (bytes, MODE_INT, 1);
- if (GET_MODE (tmp) == mode && nregs == 1)
+ mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
+ if (GET_MODE (tmp) == mode)
{
- emit_move_insn (tmp, data_regs[0]);
- i = 1;
- goto dst_done;
+ if (nregs == 1)
+ {
+ emit_move_insn (tmp, data_regs[0]);
+ i = 1;
+ goto dst_done;
+ }
+ else if (nregs == 2 && mode == TImode)
+ {
+ /* Undo the subregging done above when copying between
+ two TImode registers. */
+ if (GET_CODE (data_regs[0]) == SUBREG
+ && GET_MODE (SUBREG_REG (data_regs[0])) == TImode)
+ {
+ emit_move_insn (tmp, SUBREG_REG (data_regs[0]));
+ }
+ else
+ {
+ rtx seq;
+
+ start_sequence ();
+ emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]);
+ emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]);
+ seq = get_insns ();
+ end_sequence ();
+
+ emit_no_conflict_block (seq, tmp, data_regs[0],
+ data_regs[1], NULL_RTX);
+ }
+
+ i = 2;
+ goto dst_done;
+ }
}
/* ??? If nregs > 1, consider reconstructing the word in regs. */
/* ??? Optimize mode < dst_mode with strict_low_part. */
- /* No appropriate mode; fall back on memory. */
+
+ /* No appropriate mode; fall back on memory. We can speed things
+ up by recognizing extra alignment information. */
orig_dst = change_address (orig_dst, GET_MODE (orig_dst),
copy_addr_to_reg (XEXP (orig_dst, 0)));
+ dst_align = GET_MODE_SIZE (GET_MODE (tmp));
}
/* Write out the data in whatever chunks reading the source allowed. */
@@ -2013,9 +2152,9 @@ alpha_expand_block_move (operands)
{
while (i < nregs && GET_MODE (data_regs[i]) == DImode)
{
- emit_move_insn (change_address(orig_dst, DImode,
- plus_constant (XEXP (orig_dst, 0),
- ofs)),
+ emit_move_insn (change_address (orig_dst, DImode,
+ plus_constant (XEXP (orig_dst, 0),
+ ofs)),
data_regs[i]);
ofs += 8;
i++;
@@ -2030,13 +2169,13 @@ alpha_expand_block_move (operands)
tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
NULL_RTX, 1, OPTAB_WIDEN);
- emit_move_insn (change_address(orig_dst, SImode,
- plus_constant (XEXP (orig_dst, 0),
- ofs)),
+ emit_move_insn (change_address (orig_dst, SImode,
+ plus_constant (XEXP (orig_dst, 0),
+ ofs)),
gen_lowpart (SImode, data_regs[i]));
- emit_move_insn (change_address(orig_dst, SImode,
- plus_constant (XEXP (orig_dst, 0),
- ofs+4)),
+ emit_move_insn (change_address (orig_dst, SImode,
+ plus_constant (XEXP (orig_dst, 0),
+ ofs+4)),
gen_lowpart (SImode, tmp));
ofs += 8;
i++;
@@ -2155,6 +2294,22 @@ alpha_expand_block_clear (operands)
align = 2;
}
}
+ else if (GET_CODE (tmp) == ADDRESSOF)
+ {
+ enum machine_mode mode;
+
+ mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
+ if (GET_MODE (XEXP (tmp, 0)) == mode)
+ {
+ emit_move_insn (XEXP (tmp, 0), const0_rtx);
+ return 1;
+ }
+
+ /* No appropriate mode; fall back on memory. */
+ orig_dst = change_address (orig_dst, GET_MODE (orig_dst),
+ copy_addr_to_reg (tmp));
+ align = GET_MODE_SIZE (GET_MODE (XEXP (tmp, 0)));
+ }
/* Handle a block of contiguous words first. */
@@ -2179,9 +2334,9 @@ alpha_expand_block_clear (operands)
for (i = 0; i < words; ++i)
{
- emit_move_insn (change_address(orig_dst, SImode,
- plus_constant (XEXP (orig_dst, 0),
- ofs + i*4)),
+ emit_move_insn (change_address (orig_dst, SImode,
+ plus_constant (XEXP (orig_dst, 0),
+ ofs + i*4)),
const0_rtx);
}
@@ -2431,6 +2586,7 @@ void
alpha_init_expanders ()
{
alpha_return_addr_rtx = NULL_RTX;
+ alpha_eh_epilogue_sp_ofs = NULL_RTX;
/* Arrange to save and restore machine status around nested functions. */
save_machine_status = alpha_save_machine_status;
@@ -2454,7 +2610,7 @@ alpha_return_addr (count, frame)
/* No rtx yet. Invent one, and initialize it from $26 in the prologue. */
alpha_return_addr_rtx = gen_reg_rtx (Pmode);
- init = gen_rtx_SET (Pmode, alpha_return_addr_rtx,
+ init = gen_rtx_SET (VOIDmode, alpha_return_addr_rtx,
gen_rtx_REG (Pmode, REG_RA));
/* Emit the insn to the prologue with the other argument copies. */
@@ -2478,9 +2634,9 @@ alpha_ra_ever_killed ()
return regs_ever_live[REG_RA];
push_topmost_sequence ();
- top = get_insns();
+ top = get_insns ();
pop_topmost_sequence ();
-
+
return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX);
}
@@ -2729,7 +2885,7 @@ print_operand (file, x, code)
&& CONST_DOUBLE_LOW (x) == -1)
fprintf (file, "q");
#else
- else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffffffffffff)
+ else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1)
fprintf (file, "q");
else if (GET_CODE (x) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (x) == 0
@@ -2826,6 +2982,37 @@ print_operand (file, x, code)
output_operand_lossage ("invalid %%xn code");
}
}
+
+void
+print_operand_address (file, addr)
+ FILE *file;
+ rtx addr;
+{
+ int basereg = 31;
+ HOST_WIDE_INT offset = 0;
+
+ if (GET_CODE (addr) == AND)
+ addr = XEXP (addr, 0);
+
+ if (GET_CODE (addr) == PLUS
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ {
+ offset = INTVAL (XEXP (addr, 1));
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) == REG)
+ basereg = REGNO (addr);
+ else if (GET_CODE (addr) == SUBREG
+ && GET_CODE (SUBREG_REG (addr)) == REG)
+ basereg = REGNO (SUBREG_REG (addr)) + SUBREG_WORD (addr);
+ else if (GET_CODE (addr) == CONST_INT)
+ offset = INTVAL (addr);
+ else
+ abort ();
+
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
+ fprintf (file, "($%d)", basereg);
+}
/* Emit RTL insns to initialize the variable parts of a trampoline at
TRAMP. FNADDR is an RTX for the address of the function's pure
@@ -2846,10 +3033,14 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
int fnofs, cxtofs, jmpofs;
{
rtx temp, temp1, addr;
- /* ??? Something is wrong with VMS codegen in that we get aborts when
- using ptr_mode. Hack around it for now. */
+ /* VMS really uses DImode pointers in memory at this point. */
enum machine_mode mode = TARGET_OPEN_VMS ? Pmode : ptr_mode;
+#ifdef POINTERS_EXTEND_UNSIGNED
+ fnaddr = convert_memory_address (mode, fnaddr);
+ cxt = convert_memory_address (mode, cxt);
+#endif
+
/* Store function address and CXT. */
addr = memory_address (mode, plus_constant (tramp, fnofs));
emit_move_insn (gen_rtx (MEM, mode, addr), fnaddr);
@@ -2953,7 +3144,7 @@ alpha_builtin_saveregs (arglist)
dest = change_address (block, ptr_mode, XEXP (block, 0));
emit_move_insn (dest, addr);
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
dest, ptr_mode,
GEN_INT (GET_MODE_SIZE (ptr_mode)),
@@ -2967,7 +3158,7 @@ alpha_builtin_saveregs (arglist)
POINTER_SIZE/BITS_PER_UNIT));
emit_move_insn (dest, argsize);
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
dest, ptr_mode,
GEN_INT (GET_MODE_SIZE
@@ -3190,13 +3381,39 @@ alpha_does_function_need_gp ()
void
alpha_write_verstamp (file)
- FILE *file;
+ FILE *file ATTRIBUTE_UNUSED;
{
#ifdef MS_STAMP
fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
#endif
}
+/* Helper function to set RTX_FRAME_RELATED_P on instructions, including
+ sequences. */
+
+static rtx
+set_frame_related_p ()
+{
+ rtx seq = gen_sequence ();
+ end_sequence ();
+
+ if (GET_CODE (seq) == SEQUENCE)
+ {
+ int i = XVECLEN (seq, 0);
+ while (--i >= 0)
+ RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1;
+ return emit_insn (seq);
+ }
+ else
+ {
+ seq = emit_insn (seq);
+ RTX_FRAME_RELATED_P (seq) = 1;
+ return seq;
+ }
+}
+
+#define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
+
/* Write function prologue. */
/* On vms we have two kinds of functions:
@@ -3226,7 +3443,7 @@ alpha_expand_prologue ()
HOST_WIDE_INT frame_size;
/* Offset from base reg to register save area. */
HOST_WIDE_INT reg_offset;
- rtx sa_reg;
+ rtx sa_reg, mem;
int i;
sa_size = alpha_sa_size ();
@@ -3276,8 +3493,8 @@ alpha_expand_prologue ()
if (frame_size != 0)
{
- emit_move_insn (stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, -frame_size));
+ FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (-frame_size))));
}
}
else
@@ -3292,9 +3509,10 @@ alpha_expand_prologue ()
HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
rtx ptr = gen_rtx_REG (DImode, 22);
rtx count = gen_rtx_REG (DImode, 23);
+ rtx seq;
emit_move_insn (count, GEN_INT (blocks));
- emit_move_insn (ptr, plus_constant (stack_pointer_rtx, 4096));
+ emit_insn (gen_adddi3 (ptr, stack_pointer_rtx, GEN_INT (4096)));
/* Because of the difficulty in emitting a new basic block this
late in the compilation, generate the loop as a single insn. */
@@ -3307,7 +3525,42 @@ alpha_expand_prologue ()
emit_move_insn (last, const0_rtx);
}
- emit_move_insn (stack_pointer_rtx, plus_constant (ptr, -leftover));
+ if (TARGET_WINDOWS_NT)
+ {
+ /* For NT stack unwind (done by 'reverse execution'), it's
+ not OK to take the result of a loop, even though the value
+ is already in ptr, so we reload it via a single operation
+ and subtract it to sp.
+
+ Yes, that's correct -- we have to reload the whole constant
+ into a temporary via ldah+lda then subtract from sp. To
+ ensure we get ldah+lda, we use a special pattern. */
+
+ HOST_WIDE_INT lo, hi;
+ lo = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
+ hi = frame_size - lo;
+
+ emit_move_insn (ptr, GEN_INT (hi));
+ emit_insn (gen_nt_lda (ptr, GEN_INT (lo)));
+ seq = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
+ ptr));
+ }
+ else
+ {
+ seq = emit_insn (gen_adddi3 (stack_pointer_rtx, ptr,
+ GEN_INT (-leftover)));
+ }
+
+ /* This alternative is special, because the DWARF code cannot
+ possibly intuit through the loop above. So we invent this
+ note it looks at instead. */
+ RTX_FRAME_RELATED_P (seq) = 1;
+ REG_NOTES (seq)
+ = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ GEN_INT (-frame_size))),
+ REG_NOTES (seq));
}
/* Cope with very large offsets to the register save area. */
@@ -3323,21 +3576,23 @@ alpha_expand_prologue ()
bias = reg_offset, reg_offset = 0;
sa_reg = gen_rtx_REG (DImode, 24);
- emit_move_insn (sa_reg, plus_constant (stack_pointer_rtx, bias));
+ FRP (emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, GEN_INT (bias))));
}
/* Save regs in stack order. Beginning with VMS PV. */
if (TARGET_OPEN_VMS && vms_is_stack_procedure)
{
- emit_move_insn (gen_rtx_MEM (DImode, stack_pointer_rtx),
- gen_rtx_REG (DImode, REG_PV));
+ mem = gen_rtx_MEM (DImode, stack_pointer_rtx);
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV)));
}
/* Save register RA next. */
if (imask & (1L << REG_RA))
{
- emit_move_insn (gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)),
- gen_rtx_REG (DImode, REG_RA));
+ mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
imask &= ~(1L << REG_RA);
reg_offset += 8;
}
@@ -3346,18 +3601,18 @@ alpha_expand_prologue ()
for (i = 0; i < 32; i++)
if (imask & (1L << i))
{
- emit_move_insn (gen_rtx_MEM (DImode,
- plus_constant (sa_reg, reg_offset)),
- gen_rtx_REG (DImode, i));
+ mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
reg_offset += 8;
}
for (i = 0; i < 32; i++)
if (fmask & (1L << i))
{
- emit_move_insn (gen_rtx_MEM (DFmode,
- plus_constant (sa_reg, reg_offset)),
- gen_rtx_REG (DFmode, i+32));
+ mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
reg_offset += 8;
}
@@ -3366,25 +3621,25 @@ alpha_expand_prologue ()
if (!vms_is_stack_procedure)
{
/* Register frame procedures fave the fp. */
- emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
- hard_frame_pointer_rtx);
+ FRP (emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
+ hard_frame_pointer_rtx));
}
if (vms_base_regno != REG_PV)
- emit_move_insn (gen_rtx_REG (DImode, vms_base_regno),
- gen_rtx_REG (DImode, REG_PV));
+ FRP (emit_move_insn (gen_rtx_REG (DImode, vms_base_regno),
+ gen_rtx_REG (DImode, REG_PV)));
if (vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
{
- emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
}
/* If we have to allocate space for outgoing args, do it now. */
if (current_function_outgoing_args_size != 0)
{
- emit_move_insn (stack_pointer_rtx,
- plus_constant (hard_frame_pointer_rtx,
- - ALPHA_ROUND (current_function_outgoing_args_size)));
+ FRP (emit_move_insn (stack_pointer_rtx,
+ plus_constant (hard_frame_pointer_rtx,
+ - ALPHA_ROUND (current_function_outgoing_args_size))));
}
}
else
@@ -3393,13 +3648,13 @@ alpha_expand_prologue ()
if (frame_pointer_needed)
{
if (TARGET_CAN_FAULT_IN_PROLOGUE)
- emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
else
{
/* This must always be the last instruction in the
prologue, thus we emit a special move + clobber. */
- emit_insn (gen_init_fp (hard_frame_pointer_rtx,
- stack_pointer_rtx, sa_reg));
+ FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx,
+ stack_pointer_rtx, sa_reg)));
}
}
}
@@ -3616,6 +3871,12 @@ output_end_prologue (file)
/* Write function epilogue. */
+/* ??? At some point we will want to support full unwind, and so will
+ need to mark the epilogue as well. At the moment, we just confuse
+ dwarf2out. */
+#undef FRP
+#define FRP(exp) exp
+
void
alpha_expand_epilogue ()
{
@@ -3630,7 +3891,7 @@ alpha_expand_epilogue ()
HOST_WIDE_INT reg_offset;
int fp_is_frame_pointer, fp_offset;
rtx sa_reg, sa_reg_exp = NULL;
- rtx sp_adj1, sp_adj2;
+ rtx sp_adj1, sp_adj2, mem;
int i;
sa_size = alpha_sa_size ();
@@ -3664,7 +3925,7 @@ alpha_expand_epilogue ()
&& vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
|| (!TARGET_OPEN_VMS && frame_pointer_needed))
{
- emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
+ FRP (emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx));
}
/* Cope with very large offsets to the register save area. */
@@ -3682,13 +3943,17 @@ alpha_expand_epilogue ()
sa_reg = gen_rtx_REG (DImode, 22);
sa_reg_exp = plus_constant (stack_pointer_rtx, bias);
- emit_move_insn (sa_reg, sa_reg_exp);
+ FRP (emit_move_insn (sa_reg, sa_reg_exp));
}
/* Restore registers in order, excepting a true frame pointer. */
- emit_move_insn (gen_rtx_REG (DImode, REG_RA),
- gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset)));
+ if (! alpha_eh_epilogue_sp_ofs)
+ {
+ mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
+ }
reg_offset += 8;
imask &= ~(1L << REG_RA);
@@ -3699,10 +3964,9 @@ alpha_expand_epilogue ()
fp_offset = reg_offset;
else
{
- emit_move_insn (gen_rtx_REG (DImode, i),
- gen_rtx_MEM (DImode,
- plus_constant(sa_reg,
- reg_offset)));
+ mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
}
reg_offset += 8;
}
@@ -3710,54 +3974,57 @@ alpha_expand_epilogue ()
for (i = 0; i < 32; ++i)
if (fmask & (1L << i))
{
- emit_move_insn (gen_rtx_REG (DFmode, i+32),
- gen_rtx_MEM (DFmode,
- plus_constant(sa_reg, reg_offset)));
+ mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
reg_offset += 8;
}
}
- if (frame_size)
+ if (frame_size || alpha_eh_epilogue_sp_ofs)
{
+ sp_adj1 = stack_pointer_rtx;
+
+ if (alpha_eh_epilogue_sp_ofs)
+ {
+ sp_adj1 = gen_rtx_REG (DImode, 23);
+ emit_move_insn (sp_adj1,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ alpha_eh_epilogue_sp_ofs));
+ }
+
/* If the stack size is large, begin computation into a temporary
register so as not to interfere with a potential fp restore,
which must be consecutive with an SP restore. */
if (frame_size < 32768)
- {
- sp_adj1 = stack_pointer_rtx;
- sp_adj2 = GEN_INT (frame_size);
- }
+ sp_adj2 = GEN_INT (frame_size);
else if (frame_size < 0x40007fffL)
{
int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
- sp_adj2 = plus_constant (stack_pointer_rtx, frame_size - low);
+ sp_adj2 = plus_constant (sp_adj1, frame_size - low);
if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2))
sp_adj1 = sa_reg;
else
{
sp_adj1 = gen_rtx_REG (DImode, 23);
- emit_move_insn (sp_adj1, sp_adj2);
+ FRP (emit_move_insn (sp_adj1, sp_adj2));
}
sp_adj2 = GEN_INT (low);
}
else
{
- sp_adj2 = gen_rtx_REG (DImode, 23);
- sp_adj1 = alpha_emit_set_const (sp_adj2, DImode, frame_size, 3);
- if (!sp_adj1)
+ rtx tmp = gen_rtx_REG (DImode, 23);
+ FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3));
+ if (!sp_adj2)
{
/* We can't drop new things to memory this late, afaik,
so build it up by pieces. */
-#if HOST_BITS_PER_WIDE_INT == 64
- sp_adj1 = alpha_emit_set_long_const (sp_adj2, frame_size);
- if (!sp_adj1)
+ FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size,
+ -(frame_size < 0)));
+ if (!sp_adj2)
abort ();
-#else
- abort ();
-#endif
}
- sp_adj2 = stack_pointer_rtx;
}
/* From now on, things must be in order. So emit blockages. */
@@ -3766,29 +4033,29 @@ alpha_expand_epilogue ()
if (fp_is_frame_pointer)
{
emit_insn (gen_blockage ());
- emit_move_insn (hard_frame_pointer_rtx,
- gen_rtx_MEM (DImode,
- plus_constant(sa_reg, fp_offset)));
+ mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, fp_offset));
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
}
else if (TARGET_OPEN_VMS)
{
emit_insn (gen_blockage ());
- emit_move_insn (hard_frame_pointer_rtx,
- gen_rtx_REG (DImode, vms_save_fp_regno));
+ FRP (emit_move_insn (hard_frame_pointer_rtx,
+ gen_rtx_REG (DImode, vms_save_fp_regno)));
}
/* Restore the stack pointer. */
emit_insn (gen_blockage ());
- emit_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (DImode, sp_adj1, sp_adj2));
+ FRP (emit_move_insn (stack_pointer_rtx,
+ gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
}
else
{
if (TARGET_OPEN_VMS && !vms_is_stack_procedure)
{
emit_insn (gen_blockage ());
- emit_move_insn (hard_frame_pointer_rtx,
- gen_rtx_REG (DImode, vms_save_fp_regno));
+ FRP (emit_move_insn (hard_frame_pointer_rtx,
+ gen_rtx_REG (DImode, vms_save_fp_regno)));
}
}
@@ -3817,10 +4084,10 @@ alpha_end_function (file, fnname, decl)
Don't do this for global functions in object files destined for a
shared library because the function may be overridden by the application
- or other libraries.
- ??? Is this just ELF? */
+ or other libraries. Similarly, don't do this for weak functions. */
- if (!flag_pic || !TREE_PUBLIC (current_function_decl))
+ if (!DECL_WEAK (current_function_decl)
+ && (!flag_pic || !TREE_PUBLIC (current_function_decl)))
SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
}
@@ -3843,7 +4110,7 @@ static int num_source_filenames = 0;
/* Name of the file containing the current function. */
-static char *current_function_file = "";
+static const char *current_function_file = "";
/* Offsets to alpha virtual arg/local debugging pointers. */
@@ -4095,10 +4362,7 @@ alpha_handle_trap_shadows (insns)
{
struct shadow_summary shadow;
int trap_pending, exception_nesting;
- rtx i;
-
- if (alpha_tp == ALPHA_TP_PROG && !flag_exceptions)
- return;
+ rtx i, n;
trap_pending = 0;
exception_nesting = 0;
@@ -4201,7 +4465,9 @@ alpha_handle_trap_shadows (insns)
else
{
close_shadow:
- emit_insn_before (gen_trapb (), i);
+ n = emit_insn_before (gen_trapb (), i);
+ PUT_MODE (n, TImode);
+ PUT_MODE (i, TImode);
trap_pending = 0;
shadow.used.i = 0;
shadow.used.fp = 0;
@@ -4223,14 +4489,572 @@ alpha_handle_trap_shadows (insns)
}
}
}
+
+#ifdef HAIFA
+/* Alpha can only issue instruction groups simultaneously if they are
+ suitibly aligned. This is very processor-specific. */
+
+enum alphaev4_pipe {
+ EV4_STOP = 0,
+ EV4_IB0 = 1,
+ EV4_IB1 = 2,
+ EV4_IBX = 4
+};
+
+enum alphaev5_pipe {
+ EV5_STOP = 0,
+ EV5_NONE = 1,
+ EV5_E01 = 2,
+ EV5_E0 = 4,
+ EV5_E1 = 8,
+ EV5_FAM = 16,
+ EV5_FA = 32,
+ EV5_FM = 64
+};
+
+static enum alphaev4_pipe alphaev4_insn_pipe PROTO((rtx));
+static enum alphaev5_pipe alphaev5_insn_pipe PROTO((rtx));
+static rtx alphaev4_next_group PROTO((rtx, int*, int*));
+static rtx alphaev5_next_group PROTO((rtx, int*, int*));
+static rtx alphaev4_next_nop PROTO((int*));
+static rtx alphaev5_next_nop PROTO((int*));
+
+static void alpha_align_insns
+ PROTO((rtx, int, rtx (*)(rtx, int*, int*), rtx (*)(int*), int));
+
+static enum alphaev4_pipe
+alphaev4_insn_pipe (insn)
+ rtx insn;
+{
+ if (recog_memoized (insn) < 0)
+ return EV4_STOP;
+ if (get_attr_length (insn) != 4)
+ return EV4_STOP;
+
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ILD:
+ case TYPE_FLD:
+ return EV4_IBX;
+
+ case TYPE_LDSYM:
+ case TYPE_IADD:
+ case TYPE_ILOG:
+ case TYPE_ICMOV:
+ case TYPE_ICMP:
+ case TYPE_IST:
+ case TYPE_FST:
+ case TYPE_SHIFT:
+ case TYPE_IMUL:
+ case TYPE_FBR:
+ return EV4_IB0;
+
+ case TYPE_MISC:
+ case TYPE_IBR:
+ case TYPE_JSR:
+ case TYPE_FCPYS:
+ case TYPE_FCMOV:
+ case TYPE_FADD:
+ case TYPE_FDIV:
+ case TYPE_FMUL:
+ return EV4_IB1;
+
+ default:
+ abort();
+ }
+}
+
+static enum alphaev5_pipe
+alphaev5_insn_pipe (insn)
+ rtx insn;
+{
+ if (recog_memoized (insn) < 0)
+ return EV5_STOP;
+ if (get_attr_length (insn) != 4)
+ return EV5_STOP;
+
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ILD:
+ case TYPE_FLD:
+ case TYPE_LDSYM:
+ case TYPE_IADD:
+ case TYPE_ILOG:
+ case TYPE_ICMOV:
+ case TYPE_ICMP:
+ return EV5_E01;
+
+ case TYPE_IST:
+ case TYPE_FST:
+ case TYPE_SHIFT:
+ case TYPE_IMUL:
+ case TYPE_MISC:
+ case TYPE_MVI:
+ return EV5_E0;
+
+ case TYPE_IBR:
+ case TYPE_JSR:
+ return EV5_E1;
+
+ case TYPE_FCPYS:
+ return EV5_FAM;
+
+ case TYPE_FBR:
+ case TYPE_FCMOV:
+ case TYPE_FADD:
+ case TYPE_FDIV:
+ return EV5_FA;
+
+ case TYPE_FMUL:
+ return EV5_FM;
+
+ default:
+ abort();
+ }
+}
+
+/* IN_USE is a mask of the slots currently filled within the insn group.
+ The mask bits come from alphaev4_pipe above. If EV4_IBX is set, then
+ the insn in EV4_IB0 can be swapped by the hardware into EV4_IB1.
+
+ LEN is, of course, the length of the group in bytes. */
+
+static rtx
+alphaev4_next_group (insn, pin_use, plen)
+ rtx insn;
+ int *pin_use, *plen;
+{
+ int len, in_use;
+
+ len = in_use = 0;
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i'
+ || GET_CODE (PATTERN (insn)) == CLOBBER
+ || GET_CODE (PATTERN (insn)) == USE)
+ goto next_and_done;
+
+ while (1)
+ {
+ enum alphaev4_pipe pipe;
+
+ pipe = alphaev4_insn_pipe (insn);
+ switch (pipe)
+ {
+ case EV4_STOP:
+ /* Force complex instructions to start new groups. */
+ if (in_use)
+ goto done;
+
+ /* If this is a completely unrecognized insn, its an asm.
+ We don't know how long it is, so record length as -1 to
+ signal a needed realignment. */
+ if (recog_memoized (insn) < 0)
+ len = -1;
+ else
+ len = get_attr_length (insn);
+ goto next_and_done;
+
+ case EV4_IBX:
+ if (in_use & EV4_IB0)
+ {
+ if (in_use & EV4_IB1)
+ goto done;
+ in_use |= EV4_IB1;
+ }
+ else
+ in_use |= EV4_IB0 | EV4_IBX;
+ break;
+
+ case EV4_IB0:
+ if (in_use & EV4_IB0)
+ {
+ if (!(in_use & EV4_IBX) || (in_use & EV4_IB1))
+ goto done;
+ in_use |= EV4_IB1;
+ }
+ in_use |= EV4_IB0;
+ break;
+
+ case EV4_IB1:
+ if (in_use & EV4_IB1)
+ goto done;
+ in_use |= EV4_IB1;
+ break;
+
+ default:
+ abort();
+ }
+ len += 4;
+
+ /* Haifa doesn't do well scheduling branches. */
+ if (GET_CODE (insn) == JUMP_INSN)
+ goto next_and_done;
+
+ next:
+ insn = next_nonnote_insn (insn);
+
+ if (!insn || GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ goto done;
+
+ /* Let Haifa tell us where it thinks insn group boundaries are. */
+ if (GET_MODE (insn) == TImode)
+ goto done;
+
+ if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
+ goto next;
+ }
+
+ next_and_done:
+ insn = next_nonnote_insn (insn);
+
+ done:
+ *plen = len;
+ *pin_use = in_use;
+ return insn;
+}
+
+/* IN_USE is a mask of the slots currently filled within the insn group.
+ The mask bits come from alphaev5_pipe above. If EV5_E01 is set, then
+ the insn in EV5_E0 can be swapped by the hardware into EV5_E1.
+
+ LEN is, of course, the length of the group in bytes. */
+
+static rtx
+alphaev5_next_group (insn, pin_use, plen)
+ rtx insn;
+ int *pin_use, *plen;
+{
+ int len, in_use;
+
+ len = in_use = 0;
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i'
+ || GET_CODE (PATTERN (insn)) == CLOBBER
+ || GET_CODE (PATTERN (insn)) == USE)
+ goto next_and_done;
+
+ while (1)
+ {
+ enum alphaev5_pipe pipe;
+
+ pipe = alphaev5_insn_pipe (insn);
+ switch (pipe)
+ {
+ case EV5_STOP:
+ /* Force complex instructions to start new groups. */
+ if (in_use)
+ goto done;
+
+ /* If this is a completely unrecognized insn, its an asm.
+ We don't know how long it is, so record length as -1 to
+ signal a needed realignment. */
+ if (recog_memoized (insn) < 0)
+ len = -1;
+ else
+ len = get_attr_length (insn);
+ goto next_and_done;
+
+ /* ??? Most of the places below, we would like to abort, as
+ it would indicate an error either in Haifa, or in the
+ scheduling description. Unfortunately, Haifa never
+ schedules the last instruction of the BB, so we don't
+ have an accurate TI bit to go off. */
+ case EV5_E01:
+ if (in_use & EV5_E0)
+ {
+ if (in_use & EV5_E1)
+ goto done;
+ in_use |= EV5_E1;
+ }
+ else
+ in_use |= EV5_E0 | EV5_E01;
+ break;
+
+ case EV5_E0:
+ if (in_use & EV5_E0)
+ {
+ if (!(in_use & EV5_E01) || (in_use & EV5_E1))
+ goto done;
+ in_use |= EV5_E1;
+ }
+ in_use |= EV5_E0;
+ break;
+
+ case EV5_E1:
+ if (in_use & EV5_E1)
+ goto done;
+ in_use |= EV5_E1;
+ break;
+
+ case EV5_FAM:
+ if (in_use & EV5_FA)
+ {
+ if (in_use & EV5_FM)
+ goto done;
+ in_use |= EV5_FM;
+ }
+ else
+ in_use |= EV5_FA | EV5_FAM;
+ break;
+
+ case EV5_FA:
+ if (in_use & EV5_FA)
+ goto done;
+ in_use |= EV5_FA;
+ break;
+
+ case EV5_FM:
+ if (in_use & EV5_FM)
+ goto done;
+ in_use |= EV5_FM;
+ break;
+
+ case EV5_NONE:
+ break;
+
+ default:
+ abort();
+ }
+ len += 4;
+
+ /* Haifa doesn't do well scheduling branches. */
+ /* ??? If this is predicted not-taken, slotting continues, except
+ that no more IBR, FBR, or JSR insns may be slotted. */
+ if (GET_CODE (insn) == JUMP_INSN)
+ goto next_and_done;
+
+ next:
+ insn = next_nonnote_insn (insn);
+
+ if (!insn || GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ goto done;
+
+ /* Let Haifa tell us where it thinks insn group boundaries are. */
+ if (GET_MODE (insn) == TImode)
+ goto done;
+
+ if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
+ goto next;
+ }
+
+ next_and_done:
+ insn = next_nonnote_insn (insn);
+
+ done:
+ *plen = len;
+ *pin_use = in_use;
+ return insn;
+}
+
+static rtx
+alphaev4_next_nop (pin_use)
+ int *pin_use;
+{
+ int in_use = *pin_use;
+ rtx nop;
+
+ if (!(in_use & EV4_IB0))
+ {
+ in_use |= EV4_IB0;
+ nop = gen_nop ();
+ }
+ else if ((in_use & (EV4_IBX|EV4_IB1)) == EV4_IBX)
+ {
+ in_use |= EV4_IB1;
+ nop = gen_nop ();
+ }
+ else if (TARGET_FP && !(in_use & EV4_IB1))
+ {
+ in_use |= EV4_IB1;
+ nop = gen_fnop ();
+ }
+ else
+ nop = gen_unop ();
+
+ *pin_use = in_use;
+ return nop;
+}
+
+static rtx
+alphaev5_next_nop (pin_use)
+ int *pin_use;
+{
+ int in_use = *pin_use;
+ rtx nop;
+ if (!(in_use & EV5_E1))
+ {
+ in_use |= EV5_E1;
+ nop = gen_nop ();
+ }
+ else if (TARGET_FP && !(in_use & EV5_FA))
+ {
+ in_use |= EV5_FA;
+ nop = gen_fnop ();
+ }
+ else if (TARGET_FP && !(in_use & EV5_FM))
+ {
+ in_use |= EV5_FM;
+ nop = gen_fnop ();
+ }
+ else
+ nop = gen_unop ();
+
+ *pin_use = in_use;
+ return nop;
+}
+
+/* The instruction group alignment main loop. */
+
+static void
+alpha_align_insns (insns, max_align, next_group, next_nop, gp_in_use)
+ rtx insns;
+ int max_align;
+ rtx (*next_group) PROTO((rtx, int*, int*));
+ rtx (*next_nop) PROTO((int*));
+ int gp_in_use;
+{
+ /* ALIGN is the known alignment for the insn group. */
+ int align;
+ /* OFS is the offset of the current insn in the insn group. */
+ int ofs;
+ int prev_in_use, in_use, len;
+ rtx i, next;
+
+ /* Let shorten branches care for assigning alignments to code labels. */
+ shorten_branches (insns);
+
+ align = (FUNCTION_BOUNDARY/BITS_PER_UNIT < max_align
+ ? FUNCTION_BOUNDARY/BITS_PER_UNIT : max_align);
+
+ /* Account for the initial GP load, which happens before the scheduled
+ prologue we emitted as RTL. */
+ ofs = prev_in_use = 0;
+ if (alpha_does_function_need_gp())
+ {
+ ofs = 8 & (align - 1);
+ prev_in_use = gp_in_use;
+ }
+
+ i = insns;
+ if (GET_CODE (i) == NOTE)
+ i = next_nonnote_insn (i);
+
+ while (i)
+ {
+ next = (*next_group)(i, &in_use, &len);
+
+ /* When we see a label, resync alignment etc. */
+ if (GET_CODE (i) == CODE_LABEL)
+ {
+ int new_align = 1 << label_to_alignment (i);
+ if (new_align >= align)
+ {
+ align = new_align < max_align ? new_align : max_align;
+ ofs = 0;
+ }
+ else if (ofs & (new_align-1))
+ ofs = (ofs | (new_align-1)) + 1;
+ if (len != 0)
+ abort();
+ }
+
+ /* Handle complex instructions special. */
+ else if (in_use == 0)
+ {
+ /* Asms will have length < 0. This is a signal that we have
+ lost alignment knowledge. Assume, however, that the asm
+ will not mis-align instructions. */
+ if (len < 0)
+ {
+ ofs = 0;
+ align = 4;
+ len = 0;
+ }
+ }
+
+ /* If the known alignment is smaller than the recognized insn group,
+ realign the output. */
+ else if (align < len)
+ {
+ int new_log_align = len > 8 ? 4 : 3;
+ rtx where;
+
+ where = prev_nonnote_insn (i);
+ if (!where || GET_CODE (where) != CODE_LABEL)
+ where = i;
+
+ emit_insn_before (gen_realign (GEN_INT (new_log_align)), where);
+ align = 1 << new_log_align;
+ ofs = 0;
+ }
+
+ /* If the group won't fit in the same INT16 as the previous,
+ we need to add padding to keep the group together. Rather
+ than simply leaving the insn filling to the assembler, we
+ can make use of the knowledge of what sorts of instructions
+ were issued in the previous group to make sure that all of
+ the added nops are really free. */
+ else if (ofs + len > align)
+ {
+ int nop_count = (align - ofs) / 4;
+ rtx where;
+
+ /* Insert nops before labels and branches to truely merge the
+ execution of the nops with the previous instruction group. */
+ where = prev_nonnote_insn (i);
+ if (where)
+ {
+ if (GET_CODE (where) == CODE_LABEL)
+ {
+ rtx where2 = prev_nonnote_insn (where);
+ if (where2 && GET_CODE (where2) == JUMP_INSN)
+ where = where2;
+ }
+ else if (GET_CODE (where) != JUMP_INSN)
+ where = i;
+ }
+ else
+ where = i;
+
+ do
+ emit_insn_before ((*next_nop)(&prev_in_use), where);
+ while (--nop_count);
+ ofs = 0;
+ }
+
+ ofs = (ofs + len) & (align - 1);
+ prev_in_use = in_use;
+ i = next;
+ }
+}
+#endif /* HAIFA */
+
/* Machine dependant reorg pass. */
void
alpha_reorg (insns)
rtx insns;
{
- alpha_handle_trap_shadows (insns);
+ if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
+ alpha_handle_trap_shadows (insns);
+
+#ifdef HAIFA
+ /* Due to the number of extra trapb insns, don't bother fixing up
+ alignment when trap precision is instruction. Moreover, we can
+ only do our job when sched2 is run and Haifa is our scheduler. */
+ if (optimize && !optimize_size
+ && alpha_tp != ALPHA_TP_INSN
+ && flag_schedule_insns_after_reload)
+ {
+ if (alpha_cpu == PROCESSOR_EV4)
+ alpha_align_insns (insns, 8, alphaev4_next_group,
+ alphaev4_next_nop, EV4_IB0);
+ else if (alpha_cpu == PROCESSOR_EV5)
+ alpha_align_insns (insns, 16, alphaev5_next_group,
+ alphaev5_next_nop, EV5_E01 | EV5_E0);
+ }
+#endif
}
diff --git a/contrib/gcc/config/alpha/alpha.h b/contrib/gcc/config/alpha/alpha.h
index 43b0dee..e9c3f6d 100644
--- a/contrib/gcc/config/alpha/alpha.h
+++ b/contrib/gcc/config/alpha/alpha.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for DEC Alpha.
- Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -95,73 +95,76 @@ extern enum alpha_fp_trap_mode alpha_fptm;
/* This means that floating-point support exists in the target implementation
of the Alpha architecture. This is usually the default. */
-
-#define MASK_FP 1
+#define MASK_FP (1 << 0)
#define TARGET_FP (target_flags & MASK_FP)
/* This means that floating-point registers are allowed to be used. Note
that Alpha implementations without FP operations are required to
provide the FP registers. */
-#define MASK_FPREGS 2
+#define MASK_FPREGS (1 << 1)
#define TARGET_FPREGS (target_flags & MASK_FPREGS)
/* This means that gas is used to process the assembler file. */
-#define MASK_GAS 4
+#define MASK_GAS (1 << 2)
#define TARGET_GAS (target_flags & MASK_GAS)
/* This means that we should mark procedures as IEEE conformant. */
-#define MASK_IEEE_CONFORMANT 8
+#define MASK_IEEE_CONFORMANT (1 << 3)
#define TARGET_IEEE_CONFORMANT (target_flags & MASK_IEEE_CONFORMANT)
/* This means we should be IEEE-compliant except for inexact. */
-#define MASK_IEEE 16
+#define MASK_IEEE (1 << 4)
#define TARGET_IEEE (target_flags & MASK_IEEE)
/* This means we should be fully IEEE-compliant. */
-#define MASK_IEEE_WITH_INEXACT 32
+#define MASK_IEEE_WITH_INEXACT (1 << 5)
#define TARGET_IEEE_WITH_INEXACT (target_flags & MASK_IEEE_WITH_INEXACT)
/* This means we must construct all constants rather than emitting
them as literal data. */
-#define MASK_BUILD_CONSTANTS 128
+#define MASK_BUILD_CONSTANTS (1 << 6)
#define TARGET_BUILD_CONSTANTS (target_flags & MASK_BUILD_CONSTANTS)
/* This means we handle floating points in VAX F- (float)
or G- (double) Format. */
-#define MASK_FLOAT_VAX 512
+#define MASK_FLOAT_VAX (1 << 7)
#define TARGET_FLOAT_VAX (target_flags & MASK_FLOAT_VAX)
/* This means that the processor has byte and half word loads and stores
(the BWX extension). */
-#define MASK_BWX 1024
+#define MASK_BWX (1 << 8)
#define TARGET_BWX (target_flags & MASK_BWX)
-/* This means that the processor has the CIX extension. */
-#define MASK_CIX 2048
-#define TARGET_CIX (target_flags & MASK_CIX)
-
/* This means that the processor has the MAX extension. */
-#define MASK_MAX 4096
+#define MASK_MAX (1 << 9)
#define TARGET_MAX (target_flags & MASK_MAX)
+/* This means that the processor has the FIX extension. */
+#define MASK_FIX (1 << 10)
+#define TARGET_FIX (target_flags & MASK_FIX)
+
+/* This means that the processor has the CIX extension. */
+#define MASK_CIX (1 << 11)
+#define TARGET_CIX (target_flags & MASK_CIX)
+
/* This means that the processor is an EV5, EV56, or PCA56. This is defined
only in TARGET_CPU_DEFAULT. */
-#define MASK_CPU_EV5 8192
+#define MASK_CPU_EV5 (1 << 28)
/* Likewise for EV6. */
-#define MASK_CPU_EV6 16384
+#define MASK_CPU_EV6 (1 << 29)
/* This means we support the .arch directive in the assembler. Only
defined in TARGET_CPU_DEFAULT. */
-#define MASK_SUPPORT_ARCH 32768
+#define MASK_SUPPORT_ARCH (1 << 30)
#define TARGET_SUPPORT_ARCH (target_flags & MASK_SUPPORT_ARCH)
/* These are for target os support and cannot be changed at runtime. */
@@ -185,26 +188,32 @@ extern enum alpha_fp_trap_mode alpha_fptm;
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 \
- { {"no-soft-float", MASK_FP}, \
- {"soft-float", - MASK_FP}, \
- {"fp-regs", MASK_FPREGS}, \
- {"no-fp-regs", - (MASK_FP|MASK_FPREGS)}, \
- {"alpha-as", -MASK_GAS}, \
- {"gas", MASK_GAS}, \
- {"ieee-conformant", MASK_IEEE_CONFORMANT}, \
- {"ieee", MASK_IEEE|MASK_IEEE_CONFORMANT}, \
- {"ieee-with-inexact", MASK_IEEE_WITH_INEXACT|MASK_IEEE_CONFORMANT}, \
- {"build-constants", MASK_BUILD_CONSTANTS}, \
- {"float-vax", MASK_FLOAT_VAX}, \
- {"float-ieee", -MASK_FLOAT_VAX}, \
- {"bwx", MASK_BWX}, \
- {"no-bwx", -MASK_BWX}, \
- {"cix", MASK_CIX}, \
- {"no-cix", -MASK_CIX}, \
- {"max", MASK_MAX}, \
- {"no-max", -MASK_MAX}, \
- {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT} }
+#define TARGET_SWITCHES \
+ { {"no-soft-float", MASK_FP, "Use hardware fp"}, \
+ {"soft-float", - MASK_FP, "Do not use hardware fp"}, \
+ {"fp-regs", MASK_FPREGS, "Use fp registers"}, \
+ {"no-fp-regs", - (MASK_FP|MASK_FPREGS), "Do not use fp registers"}, \
+ {"alpha-as", -MASK_GAS, "Do not assume GAS"}, \
+ {"gas", MASK_GAS, "Assume GAS"}, \
+ {"ieee-conformant", MASK_IEEE_CONFORMANT, \
+ "Request IEEE-conformant math library routines (OSF/1)"}, \
+ {"ieee", MASK_IEEE|MASK_IEEE_CONFORMANT, \
+ "Emit IEEE-conformant code, without inexact exceptions"}, \
+ {"ieee-with-inexact", MASK_IEEE_WITH_INEXACT|MASK_IEEE_CONFORMANT, \
+ "Emit IEEE-conformant code, with inexact exceptions"}, \
+ {"build-constants", MASK_BUILD_CONSTANTS, \
+ "Do not emit complex integer constants to read-only memory"}, \
+ {"float-vax", MASK_FLOAT_VAX, "Use VAX fp"}, \
+ {"float-ieee", -MASK_FLOAT_VAX, "Do not use VAX fp"}, \
+ {"bwx", MASK_BWX, "Emit code for the byte/word ISA extension"}, \
+ {"no-bwx", -MASK_BWX, ""}, \
+ {"max", MASK_MAX, "Emit code for the motion video ISA extension"}, \
+ {"no-max", -MASK_MAX, ""}, \
+ {"fix", MASK_FIX, "Emit code for the fp move and sqrt ISA extension"}, \
+ {"no-fix", -MASK_FIX, ""}, \
+ {"cix", MASK_CIX, "Emit code for the counting ISA extension"}, \
+ {"no-cix", -MASK_CIX, ""}, \
+ {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT, ""} }
#define TARGET_DEFAULT MASK_FP|MASK_FPREGS
@@ -229,19 +238,24 @@ extern enum alpha_fp_trap_mode alpha_fptm;
extern char *m88k_short_data;
#define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */
-extern char *alpha_cpu_string; /* For -mcpu= */
-extern char *alpha_fprm_string; /* For -mfp-rounding-mode=[n|m|c|d] */
-extern char *alpha_fptm_string; /* For -mfp-trap-mode=[n|u|su|sui] */
-extern char *alpha_tp_string; /* For -mtrap-precision=[p|f|i] */
-extern char *alpha_mlat_string; /* For -mmemory-latency= */
-
-#define TARGET_OPTIONS \
-{ \
- {"cpu=", &alpha_cpu_string}, \
- {"fp-rounding-mode=", &alpha_fprm_string}, \
- {"fp-trap-mode=", &alpha_fptm_string}, \
- {"trap-precision=", &alpha_tp_string}, \
- {"memory-latency=", &alpha_mlat_string}, \
+extern const char *alpha_cpu_string; /* For -mcpu= */
+extern const char *alpha_fprm_string; /* For -mfp-rounding-mode=[n|m|c|d] */
+extern const char *alpha_fptm_string; /* For -mfp-trap-mode=[n|u|su|sui] */
+extern const char *alpha_tp_string; /* For -mtrap-precision=[p|f|i] */
+extern const char *alpha_mlat_string; /* For -mmemory-latency= */
+
+#define TARGET_OPTIONS \
+{ \
+ {"cpu=", &alpha_cpu_string, \
+ "Generate code for a given CPU"}, \
+ {"fp-rounding-mode=", &alpha_fprm_string, \
+ "Control the generated fp rounding mode"}, \
+ {"fp-trap-mode=", &alpha_fptm_string, \
+ "Control the IEEE trap mode"}, \
+ {"trap-precision=", &alpha_tp_string, \
+ "Control the precision given to fp exceptions"}, \
+ {"memory-latency=", &alpha_mlat_string, \
+ "Tune expected memory latency"}, \
}
/* Attempt to describe CPU characteristics to the preprocessor. */
@@ -249,6 +263,7 @@ extern char *alpha_mlat_string; /* For -mmemory-latency= */
/* Corresponding to amask... */
#define CPP_AM_BWX_SPEC "-D__alpha_bwx__ -Acpu(bwx)"
#define CPP_AM_MAX_SPEC "-D__alpha_max__ -Acpu(max)"
+#define CPP_AM_FIX_SPEC "-D__alpha_fix__ -Acpu(fix)"
#define CPP_AM_CIX_SPEC "-D__alpha_cix__ -Acpu(cix)"
/* Corresponding to implver... */
@@ -261,7 +276,7 @@ extern char *alpha_mlat_string; /* For -mmemory-latency= */
#define CPP_CPU_EV5_SPEC "%(cpp_im_ev5)"
#define CPP_CPU_EV56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx)"
#define CPP_CPU_PCA56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx) %(cpp_am_max)"
-#define CPP_CPU_EV6_SPEC "%(cpp_im_ev6) %(cpp_am_bwx) %(cpp_am_max) %(cpp_am_cix)"
+#define CPP_CPU_EV6_SPEC "%(cpp_im_ev6) %(cpp_am_bwx) %(cpp_am_max) %(cpp_am_fix)"
#ifndef CPP_CPU_DEFAULT_SPEC
# if TARGET_CPU_DEFAULT & MASK_CPU_EV6
@@ -311,6 +326,7 @@ extern char *alpha_mlat_string; /* For -mmemory-latency= */
#define EXTRA_SPECS \
{ "cpp_am_bwx", CPP_AM_BWX_SPEC }, \
{ "cpp_am_max", CPP_AM_MAX_SPEC }, \
+ { "cpp_am_fix", CPP_AM_FIX_SPEC }, \
{ "cpp_am_cix", CPP_AM_CIX_SPEC }, \
{ "cpp_im_ev4", CPP_IM_EV4_SPEC }, \
{ "cpp_im_ev5", CPP_IM_EV5_SPEC }, \
@@ -483,7 +499,7 @@ extern void override_options ();
Alpha we'll get better performance by aligning on an octaword
boundary. */
-#define ALIGN_LABEL_AFTER_BARRIER(FILE) \
+#define LABEL_ALIGN_AFTER_BARRIER(FILE) \
(optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0)
/* No data type wants to be aligned rounder than this. */
@@ -613,17 +629,20 @@ extern void override_options ();
registers can hold 32-bit and 64-bit integers as well, but not 16-bit
or 8-bit values. */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- ((REGNO) < 32 || ((MODE) != QImode && (MODE) != HImode))
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ ((REGNO) >= 32 && (REGNO) <= 62 \
+ ? GET_MODE_UNIT_SIZE (MODE) == 8 || GET_MODE_UNIT_SIZE (MODE) == 4 \
+ : 1)
+
+/* A C expression that is nonzero if a value of mode
+ MODE1 is accessible in mode MODE2 without copying.
-/* Value is 1 if it is a good idea to tie two pseudo registers
- when one has mode MODE1 and one has mode MODE2.
- If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
- for any hard reg, then this must be 0 for correct output. */
+ This asymmetric test is true when MODE1 could be put
+ in an FP register but MODE2 could not. */
#define MODES_TIEABLE_P(MODE1, MODE2) \
- ((MODE1) == QImode || (MODE1) == HImode \
- ? (MODE2) == QImode || (MODE2) == HImode \
+ (HARD_REGNO_MODE_OK (32, (MODE1)) \
+ ? HARD_REGNO_MODE_OK (32, (MODE2)) \
: 1)
/* Specify the registers used for certain standard purposes.
@@ -771,11 +790,12 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
'S' is a 6-bit constant (valid for a shift insn). */
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) != AND \
+ ((C) == 'Q' ? normal_memory_operand (OP, VOIDmode) \
: (C) == 'R' ? current_file_function_operand (OP, Pmode) \
: (C) == 'S' ? (GET_CODE (OP) == CONST_INT \
&& (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \
: 0)
+extern int normal_memory_operand ();
/* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
@@ -807,7 +827,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
&& (((CLASS) == FLOAT_REGS \
&& ((MODE) == SImode || (MODE) == HImode || (MODE) == QImode)) \
|| (((MODE) == QImode || (MODE) == HImode) \
- && ! TARGET_BWX && unaligned_memory_operand (IN, MODE)))) \
+ && ! TARGET_BWX && ! aligned_memory_operand (IN, MODE)))) \
? GENERAL_REGS \
: ((CLASS) == FLOAT_REGS && GET_CODE (IN) == MEM \
&& GET_CODE (XEXP (IN, 0)) == AND) ? GENERAL_REGS \
@@ -835,10 +855,10 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
: NO_REGS)
/* If we are copying between general and FP registers, we need a memory
- location unless the CIX extension is available. */
+ location unless the FIX extension is available. */
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
- (! TARGET_CIX && (CLASS1) != (CLASS2))
+ (! TARGET_FIX && (CLASS1) != (CLASS2))
/* Specify the mode to be used for memory when a secondary memory
location is needed. If MODE is floating-point, use it. Otherwise,
@@ -871,7 +891,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
(((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) \
? 2 \
- : TARGET_CIX ? 3 : 4+2*alpha_memory_latency)
+ : TARGET_FIX ? 3 : 4+2*alpha_memory_latency)
/* A C expressions returning the cost of moving data of MODE from a register to
or from memory.
@@ -989,26 +1009,25 @@ extern int alpha_memory_latency;
On Alpha the value is found in $0 for integer functions and
$f0 for floating-point functions. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx (REG, \
- ((INTEGRAL_TYPE_P (VALTYPE) \
- && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
- || POINTER_TYPE_P (VALTYPE)) \
- ? word_mode : TYPE_MODE (VALTYPE), \
- ((TARGET_FPREGS \
- && (TREE_CODE (VALTYPE) == REAL_TYPE \
- || TREE_CODE (VALTYPE) == COMPLEX_TYPE)) \
- ? 32 : 0))
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx_REG (((INTEGRAL_TYPE_P (VALTYPE) \
+ && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
+ || POINTER_TYPE_P (VALTYPE)) \
+ ? word_mode : TYPE_MODE (VALTYPE), \
+ ((TARGET_FPREGS \
+ && (TREE_CODE (VALTYPE) == REAL_TYPE \
+ || TREE_CODE (VALTYPE) == COMPLEX_TYPE)) \
+ ? 32 : 0))
/* Define how to find the value returned by a library function
assuming the value has mode MODE. */
-#define LIBCALL_VALUE(MODE) \
- gen_rtx (REG, MODE, \
- (TARGET_FPREGS \
- && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
- || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
- ? 32 : 0))
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx_REG (MODE, \
+ (TARGET_FPREGS \
+ && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
+ ? 32 : 0))
/* The definition of this macro implies that there are cases where
a scalar value cannot be returned in registers.
@@ -1182,6 +1201,10 @@ extern struct rtx_def *alpha_builtin_saveregs ();
extern struct rtx_def *alpha_compare_op0, *alpha_compare_op1;
extern int alpha_compare_fp_p;
+/* Define the information needed to modify the epilogue for EH. */
+
+extern struct rtx_def *alpha_eh_epilogue_sp_ofs;
+
/* Make (or fake) .linkage entry for function call.
IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */
extern void alpha_need_linkage ();
@@ -1293,6 +1316,7 @@ do { \
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 16, 24, 8)
+extern void alpha_initialize_trampoline ();
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame.
@@ -1302,6 +1326,9 @@ do { \
#define RETURN_ADDR_RTX alpha_return_addr
extern struct rtx_def *alpha_return_addr ();
+/* Before the prologue, RA lives in $26. */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 26)
+
/* Initialize data used by insn expanders. This is called from insn_emit,
once for every function before code is generated. */
@@ -1310,11 +1337,11 @@ extern void alpha_init_expanders ();
/* Addressing modes, and classification of registers for them. */
-/* #define HAVE_POST_INCREMENT */
-/* #define HAVE_POST_DECREMENT */
+/* #define HAVE_POST_INCREMENT 0 */
+/* #define HAVE_POST_DECREMENT 0 */
-/* #define HAVE_PRE_DECREMENT */
-/* #define HAVE_PRE_INCREMENT */
+/* #define HAVE_PRE_DECREMENT 0 */
+/* #define HAVE_PRE_INCREMENT 0 */
/* Macros to check register numbers against specific register classes. */
@@ -1365,18 +1392,32 @@ extern void alpha_init_expanders ();
/* Nonzero if X is a hard reg that can be used as an index
or if it is a pseudo reg. */
#define REG_OK_FOR_INDEX_P(X) 0
+
/* Nonzero if X is a hard reg that can be used as a base reg
or if it is a pseudo reg. */
#define REG_OK_FOR_BASE_P(X) \
(REGNO (X) < 32 || REGNO (X) == 63 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+/* ??? Nonzero if X is the frame pointer, or some virtual register
+ that may eliminate to the frame pointer. These will be allowed to
+ have offsets greater than 32K. This is done because register
+ elimination offsets will change the hi/lo split, and if we split
+ before reload, we will require additional instructions. */
+#define REG_OK_FP_BASE_P(X) \
+ (REGNO (X) == 31 || REGNO (X) == 63 \
+ || (REGNO (X) >= FIRST_PSEUDO_REGISTER \
+ && REGNO (X) < LAST_VIRTUAL_REGISTER))
+
#else
/* Nonzero if X is a hard reg that can be used as an index. */
#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (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_FP_BASE_P(X) 0
+
#endif
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -1391,16 +1432,34 @@ extern void alpha_init_expanders ();
First define the basic valid address. */
-#define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \
-{ if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \
- goto ADDR; \
- if (CONSTANT_ADDRESS_P (X)) \
- goto ADDR; \
- if (GET_CODE (X) == PLUS \
- && REG_P (XEXP (X, 0)) \
- && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
- goto ADDR; \
+#define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \
+{ \
+ rtx tmp = (X); \
+ if (GET_CODE (tmp) == SUBREG \
+ && (GET_MODE_SIZE (GET_MODE (tmp)) \
+ < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tmp))))) \
+ tmp = SUBREG_REG (tmp); \
+ if (REG_P (tmp) && REG_OK_FOR_BASE_P (tmp)) \
+ goto ADDR; \
+ if (CONSTANT_ADDRESS_P (X)) \
+ goto ADDR; \
+ if (GET_CODE (X) == PLUS) \
+ { \
+ tmp = XEXP (X, 0); \
+ if (GET_CODE (tmp) == SUBREG \
+ && (GET_MODE_SIZE (GET_MODE (tmp)) \
+ < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tmp))))) \
+ tmp = SUBREG_REG (tmp); \
+ if (REG_P (tmp)) \
+ { \
+ if (REG_OK_FP_BASE_P (tmp) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT) \
+ goto ADDR; \
+ if (REG_OK_FOR_BASE_P (tmp) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ goto ADDR; \
+ } \
+ } \
}
/* Now accept the simple address, or, for DImode only, an AND of a simple
@@ -1596,9 +1655,11 @@ do { \
#define MOVE_MAX 8
-/* Controls how many units are moved by expr.c before resorting to movstr.
- Without byte/word accesses, we want no more than one; with, several single
- byte accesses are better. */
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+ move-instruction pairs, we will do a movstr or libcall instead.
+
+ Without byte/word accesses, we want no more than four instructions;
+ with, several single byte accesses are better. */
#define MOVE_RATIO (TARGET_BWX ? 7 : 2)
@@ -1693,6 +1754,12 @@ do { \
/* The EV4 is dual issue; EV5/EV6 are quad issue. */
#define ISSUE_RATE (alpha_cpu == PROCESSOR_EV4 ? 2 : 4)
+/* Describe the fact that MULTI instructions are multiple instructions
+ and so to assume they don't pair with anything. */
+#define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \
+ if (recog_memoized (INSN) < 0 || get_attr_type (INSN) == TYPE_MULTI) \
+ (CAN_ISSUE_MORE) = 0
+
/* Compute the cost of computing a constant rtl expression RTX
whose rtx-code is CODE. The body of this macro is a portion
of a switch statement. If the code is computed here,
@@ -1970,7 +2037,7 @@ literal_section () \
This is suitable for output with `assemble_name'. */
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*$%s%d", PREFIX, NUM)
+ sprintf ((LABEL), "*$%s%ld", (PREFIX), (long)(NUM))
/* Check a floating-point value for validity for a particular machine mode. */
@@ -2078,6 +2145,11 @@ literal_section () \
} \
while (0)
+/* To get unaligned data, we have to turn off auto alignment. */
+#define UNALIGNED_SHORT_ASM_OP ".align 0\n\t.word"
+#define UNALIGNED_INT_ASM_OP ".align 0\n\t.long"
+#define UNALIGNED_DOUBLE_INT_ASM_OP ".align 0\n\t.quad"
+
/* This is how to output an insn to push a register on the stack.
It need not be very fast code. */
@@ -2237,41 +2309,22 @@ do { \
/* Print a memory address as an operand to reference that memory location. */
-#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
-{ rtx addr = (ADDR); \
- int basereg = 31; \
- HOST_WIDE_INT offset = 0; \
- \
- if (GET_CODE (addr) == AND) \
- addr = XEXP (addr, 0); \
- \
- if (GET_CODE (addr) == REG) \
- basereg = REGNO (addr); \
- else if (GET_CODE (addr) == CONST_INT) \
- offset = INTVAL (addr); \
- else if (GET_CODE (addr) == PLUS \
- && GET_CODE (XEXP (addr, 0)) == REG \
- && GET_CODE (XEXP (addr, 1)) == CONST_INT) \
- basereg = REGNO (XEXP (addr, 0)), offset = INTVAL (XEXP (addr, 1)); \
- else \
- abort (); \
- \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, offset); \
- fprintf (FILE, "($%d)", basereg); \
-}
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+ print_operand_address((FILE), (ADDR))
+
/* Define the codes that are matched by predicates in alpha.c. */
#define PREDICATE_CODES \
{"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
- {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
- {"cint8_operand", {CONST_INT, CONSTANT_P_RTX}}, \
- {"reg_or_cint_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
- {"add_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
- {"sext_add_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
+ {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}}, \
+ {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \
+ {"cint8_operand", {CONST_INT}}, \
+ {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
+ {"add_operand", {SUBREG, REG, CONST_INT}}, \
+ {"sext_add_operand", {SUBREG, REG, CONST_INT}}, \
{"const48_operand", {CONST_INT}}, \
- {"and_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
- {"or_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
+ {"and_operand", {SUBREG, REG, CONST_INT}}, \
+ {"or_operand", {SUBREG, REG, CONST_INT}}, \
{"mode_mask_operand", {CONST_INT}}, \
{"mul8_operand", {CONST_INT}}, \
{"mode_width_operand", {CONST_INT}}, \
@@ -2284,14 +2337,16 @@ do { \
{"current_file_function_operand", {SYMBOL_REF}}, \
{"call_operand", {REG, SYMBOL_REF}}, \
{"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
- SYMBOL_REF, CONST, LABEL_REF, CONSTANT_P_RTX}}, \
+ SYMBOL_REF, CONST, LABEL_REF}}, \
{"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
- SYMBOL_REF, CONST, LABEL_REF, CONSTANT_P_RTX}}, \
+ SYMBOL_REF, CONST, LABEL_REF}}, \
{"aligned_memory_operand", {MEM}}, \
{"unaligned_memory_operand", {MEM}}, \
{"reg_or_unaligned_mem_operand", {SUBREG, REG, MEM}}, \
{"any_memory_operand", {MEM}}, \
- {"hard_fp_register_operand", {SUBREG, REG}},
+ {"hard_fp_register_operand", {SUBREG, REG}}, \
+ {"reg_not_elim_operand", {SUBREG, REG}}, \
+ {"reg_no_subreg_operand", {REG}},
/* Tell collect that the object format is ECOFF. */
#define OBJECT_FORMAT_COFF
@@ -2462,6 +2517,7 @@ extern int current_file_function_operand ();
extern int alpha_sa_size ();
extern int alpha_adjust_cost ();
extern void print_operand ();
+extern void print_operand_address ();
extern int reg_or_0_operand ();
extern int reg_or_8bit_operand ();
extern int mul8_operand ();
@@ -2482,6 +2538,7 @@ extern int divmod_operator ();
extern int call_operand ();
extern int reg_or_cint_operand ();
extern int hard_fp_register_operand ();
+extern int reg_not_elim_operand ();
extern void alpha_set_memflags ();
extern int aligned_memory_operand ();
extern void get_aligned_mem ();
diff --git a/contrib/gcc/config/alpha/alpha.md b/contrib/gcc/config/alpha/alpha.md
index 87ebf95..6d075e9 100644
--- a/contrib/gcc/config/alpha/alpha.md
+++ b/contrib/gcc/config/alpha/alpha.md
@@ -1,5 +1,5 @@
;; Machine description for DEC Alpha for GNU C compiler
-;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;; This file is part of GNU CC.
@@ -29,6 +29,7 @@
;; 3 mskxh
;; 4 cvtlq
;; 5 cvtql
+;; 6 nt_lda
;;
;; UNSPEC_VOLATILE:
;;
@@ -38,6 +39,8 @@
;; 3 builtin_longjmp
;; 4 trapb
;; 5 prologue_stack_probe_loop
+;; 6 realign
+;; 7 exception_receiver
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in alpha.h.
@@ -51,9 +54,13 @@
;; separately.
(define_attr "type"
- "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof"
+ "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(const_string "iadd"))
+;; Describe a user's asm statement.
+(define_asm_attributes
+ [(set_attr "type" "multi")])
+
;; Define the operand size an insn operates on. Used primarily by mul
;; and div operations that have size dependant timings.
@@ -149,13 +156,18 @@
; Memory takes at least 2 clocks. Return one from here and fix up with
; user-defined latencies in adjust_cost.
-; ??? How to: "An instruction of class LD cannot be issued in the _second_
-; cycle after an instruction of class ST is issued."
(define_function_unit "ev5_ebox" 2 0
(and (eq_attr "cpu" "ev5")
(eq_attr "type" "ild,fld,ldsym"))
1 1)
+; Loads can dual issue with one another, but loads and stores do not mix.
+(define_function_unit "ev5_e0" 1 0
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "ild,fld,ldsym"))
+ 1 1
+ [(eq_attr "type" "ist,fst")])
+
; Stores, shifts, multiplies can only issue to E0
(define_function_unit "ev5_e0" 1 0
(and (eq_attr "cpu" "ev5")
@@ -420,12 +432,23 @@
(match_operand:SI 2 "add_operand" "")))]
""
"
-{ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (DImode, operands[0]),
- gen_rtx_PLUS (DImode,
- gen_lowpart (DImode, operands[1]),
- gen_lowpart (DImode, operands[2]))));
- DONE;
-} ")
+{
+ if (optimize)
+ {
+ rtx op1 = gen_lowpart (DImode, operands[1]);
+ rtx op2 = gen_lowpart (DImode, operands[2]);
+
+ if (! cse_not_expected)
+ {
+ rtx tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_adddi3 (tmp, op1, op2));
+ emit_move_insn (gen_lowpart (DImode, operands[0]), tmp);
+ }
+ else
+ emit_insn (gen_adddi3 (gen_lowpart (DImode, operands[0]), op1, op2));
+ DONE;
+ }
+}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
@@ -470,7 +493,7 @@
(sign_extend:DI
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" ""))))
- (clobber (match_operand:SI 3 "register_operand" ""))]
+ (clobber (match_operand:SI 3 "reg_not_elim_operand" ""))]
"! sext_add_operand (operands[2], SImode) && INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) % 4 == 0"
[(set (match_dup 3) (match_dup 4))
@@ -512,20 +535,57 @@
(plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ")
(match_operand:DI 2 "add_operand" "rI,O,K,L")))]
""
- "@
- addq %r1,%2,%0
- subq %r1,%n2,%0
- lda %0,%2(%r1)
- ldah %0,%h2(%r1)")
+ "*
+{
+ const char * const pattern[4] = {
+ \"addq %r1,%2,%0\",
+ \"subq %r1,%n2,%0\",
+ \"lda %0,%2(%r1)\",
+ \"ldah %0,%h2(%r1)\"
+ };
+
+ /* The NT stack unwind code can't handle a subq to adjust the stack
+ (that's a bug, but not one we can do anything about). As of NT4.0 SP3,
+ the exception handling code will loop if a subq is used and an
+ exception occurs.
+
+ The 19980616 change to emit prologues as RTL also confused some
+ versions of GDB, which also interprets prologues. This has been
+ fixed as of GDB 4.18, but it does not harm to unconditionally
+ use lda here. */
+
+ int which = which_alternative;
+
+ if (operands[0] == stack_pointer_rtx
+ && GET_CODE (operands[2]) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))
+ which = 2;
+
+ return pattern[which];
+}")
+
+;; ??? Allow large constants when basing off the frame pointer or some
+;; virtual register that may eliminate to the frame pointer. This is
+;; done because register elimination offsets will change the hi/lo split,
+;; and if we split before reload, we will require additional instructions.
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "reg_no_subreg_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "n")))]
+ "REG_OK_FP_BASE_P (operands[1])"
+ "#")
-;; Don't do this if we are adjusting SP since we don't want to do
-;; it in two steps.
+;; Don't do this if we are adjusting SP since we don't want to do it
+;; in two steps. Don't split FP sources for the reason listed above.
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "const_int_operand" "")))]
"! add_operand (operands[2], DImode)
- && REGNO (operands[0]) != STACK_POINTER_REGNUM"
+ && operands[0] != stack_pointer_rtx
+ && operands[1] != frame_pointer_rtx
+ && operands[1] != arg_pointer_rtx"
[(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3)))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
"
@@ -540,24 +600,24 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,rJ")
+ (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r")
(match_operand:SI 2 "const48_operand" "I,I"))
(match_operand:SI 3 "sext_add_operand" "rI,O")))]
""
"@
- s%2addl %r1,%3,%0
- s%2subl %r1,%n3,%0")
+ s%2addl %1,%3,%0
+ s%2subl %1,%n3,%0")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r,r")
(sign_extend:DI
- (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,rJ")
+ (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r")
(match_operand:SI 2 "const48_operand" "I,I"))
(match_operand:SI 3 "sext_add_operand" "rI,O"))))]
""
"@
- s%2addl %r1,%3,%0
- s%2subl %r1,%n3,%0")
+ s%2addl %1,%3,%0
+ s%2subl %1,%n3,%0")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -567,7 +627,7 @@
(match_operand 3 "" "")])
(match_operand:SI 4 "const48_operand" ""))
(match_operand:SI 5 "add_operand" ""))))
- (clobber (match_operand:DI 6 "register_operand" ""))]
+ (clobber (match_operand:DI 6 "reg_not_elim_operand" ""))]
""
[(set (match_dup 6) (match_dup 7))
(set (match_dup 0)
@@ -582,12 +642,12 @@
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ")
+ (plus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r,r")
(match_operand:DI 2 "const48_operand" "I,I"))
- (match_operand:DI 3 "reg_or_8bit_operand" "rI,O")))]
+ (match_operand:DI 3 "sext_add_operand" "rI,O")))]
""
"@
- s%2addq %r1,%3,%0
+ s%2addq %1,%3,%0
s%2subq %1,%n3,%0")
;; These variants of the above insns can occur if the third operand
@@ -656,9 +716,7 @@
[(set (match_dup 5)
(plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
(set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
- "
-{ operands[5] = gen_lowpart (SImode, operands[0]);
-}")
+ "operands[5] = gen_lowpart (SImode, operands[0]);")
(define_insn ""
[(set (match_operand:DI 0 "some_operand" "=&r")
@@ -706,11 +764,22 @@
(match_operand:SI 2 "reg_or_8bit_operand" "")))]
""
"
-{ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (DImode, operands[0]),
- gen_rtx_MINUS (DImode,
- gen_lowpart (DImode, operands[1]),
- gen_lowpart (DImode, operands[2]))));
- DONE;
+{
+ if (optimize)
+ {
+ rtx op1 = gen_lowpart (DImode, operands[1]);
+ rtx op2 = gen_lowpart (DImode, operands[2]);
+
+ if (! cse_not_expected)
+ {
+ rtx tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_subdi3 (tmp, op1, op2));
+ emit_move_insn (gen_lowpart (DImode, operands[0]), tmp);
+ }
+ else
+ emit_insn (gen_subdi3 (gen_lowpart (DImode, operands[0]), op1, op2));
+ DONE;
+ }
} ")
(define_insn ""
@@ -736,64 +805,67 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r")
(match_operand:SI 2 "const48_operand" "I"))
(match_operand:SI 3 "reg_or_8bit_operand" "rI")))]
""
- "s%2subl %r1,%3,%0")
+ "s%2subl %1,%3,%0")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI
- (minus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r")
(match_operand:SI 2 "const48_operand" "I"))
(match_operand:SI 3 "reg_or_8bit_operand" "rI"))))]
""
- "s%2subl %r1,%3,%0")
+ "s%2subl %1,%3,%0")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (minus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r")
(match_operand:DI 2 "const48_operand" "I"))
(match_operand:DI 3 "reg_or_8bit_operand" "rI")))]
""
- "s%2subq %r1,%3,%0")
+ "s%2subq %1,%3,%0")
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
- (match_operand:SI 2 "reg_or_0_operand" "rJ")))]
+ (match_operand:SI 2 "reg_or_8bit_operand" "rI")))]
""
- "mull %r1,%r2,%0"
+ "mull %r1,%2,%0"
[(set_attr "type" "imul")
(set_attr "opsize" "si")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
- (sign_extend:DI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
- (match_operand:SI 2 "reg_or_0_operand" "rJ"))))]
+ (sign_extend:DI
+ (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+ (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))]
""
- "mull %r1,%r2,%0"
+ "mull %r1,%2,%0"
[(set_attr "type" "imul")
(set_attr "opsize" "si")])
(define_insn "muldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
- (match_operand:DI 2 "reg_or_0_operand" "rJ")))]
+ (match_operand:DI 2 "reg_or_8bit_operand" "rI")))]
""
- "mulq %r1,%r2,%0"
+ "mulq %r1,%2,%0"
[(set_attr "type" "imul")])
(define_insn "umuldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=r")
(truncate:DI
(lshiftrt:TI
- (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
- (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "reg_or_0_operand" "%rJ"))
+ (zero_extend:TI
+ (match_operand:DI 2 "reg_or_8bit_operand" "rI")))
(const_int 64))))]
""
- "umulh %1,%2,%0"
+ "umulh %r1,%2,%0"
[(set_attr "type" "imul")
(set_attr "opsize" "udi")])
@@ -816,6 +888,7 @@
;; do the right thing if the inputs are not properly sign-extended.
;; But Linux, for instance, does not have this problem. Is it worth
;; the complication here to eliminate the sign extension?
+;; Interix/NT has the same sign-extension problem.
(define_expand "divsi3"
[(set (reg:DI 24)
@@ -1146,7 +1219,15 @@
"eqv %r1,%2,%0"
[(set_attr "type" "ilog")])
-;; Handle the FFS insn if we support CIX.
+;; Handle the FFS insn iff we support CIX.
+;;
+;; These didn't make it into EV6 pass 2 as planned. Instead they
+;; cropped cttz/ctlz/ctpop from the old CIX and renamed it FIX for
+;; "Square Root and Floating Point Convert Extension".
+;;
+;; I'm assured that these insns will make it into EV67 (first pass
+;; due Summer 1999), presumably with a new AMASK bit, and presumably
+;; will still be named CIX.
(define_expand "ffsdi2"
[(set (match_dup 2)
@@ -1168,7 +1249,7 @@
(unspec [(match_operand:DI 1 "register_operand" "r")] 1))]
"TARGET_CIX"
"cttz %1,%0"
- ; ev6 calls all mvi and cttz/ctlz/popc class imisc, so just
+ ; EV6 calls all mvi and cttz/ctlz/popc class imisc, so just
; reuse the existing type name.
[(set_attr "type" "mvi")])
@@ -1495,6 +1576,29 @@
"ext%M2l %r1,%3,%0"
[(set_attr "type" "shift")])
+;; Combine has some strange notion of preserving existing undefined behaviour
+;; in shifts larger than a word size. So capture these patterns that it
+;; should have turned into zero_extracts.
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3)))
+ (match_operand:DI 3 "mode_mask_operand" "n")))]
+ ""
+ "ext%U3l %1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3))))]
+ ""
+ "extql %1,%2,%0"
+ [(set_attr "type" "shift")])
+
(define_insn "extqh"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI
@@ -1639,22 +1743,22 @@
"HOST_BITS_PER_WIDE_INT == 64
&& GET_CODE (operands[3]) == CONST_INT
&& (((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2])
- == INTVAL (operands[3]))
+ == (unsigned HOST_WIDE_INT) INTVAL (operands[3]))
|| ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2])
- == INTVAL (operands[3]))
+ == (unsigned HOST_WIDE_INT) INTVAL (operands[3]))
|| ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2])
- == INTVAL (operands[3])))"
+ == (unsigned HOST_WIDE_INT) INTVAL (operands[3])))"
"*
{
#if HOST_BITS_PER_WIDE_INT == 64
if ((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2])
- == INTVAL (operands[3]))
+ == (unsigned HOST_WIDE_INT) INTVAL (operands[3]))
return \"insbl %1,%s2,%0\";
if ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2])
- == INTVAL (operands[3]))
+ == (unsigned HOST_WIDE_INT) INTVAL (operands[3]))
return \"inswl %1,%s2,%0\";
if ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2])
- == INTVAL (operands[3]))
+ == (unsigned HOST_WIDE_INT) INTVAL (operands[3]))
return \"insll %1,%s2,%0\";
#endif
abort();
@@ -1794,60 +1898,62 @@
;; instruction. To allow combine et al to do useful things, we keep the
;; operation as a unit until after reload, at which point we split the
;; instructions.
+;;
+;; Note that we (attempt to) only consider this optimization when the
+;; ultimate destination is memory. If we will be doing further integer
+;; processing, it is cheaper to do the truncation in the int regs.
+
+(define_insn "*cvtql"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")] 5))]
+ "TARGET_FP"
+ "cvtql%` %R1,%0"
+ [(set_attr "type" "fadd")
+ (set_attr "trap" "yes")])
(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "")))
- (clobber (match_scratch:DI 2 ""))]
+ [(set (match_operand:SI 0 "memory_operand" "")
+ (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:SI 3 ""))]
"TARGET_FP && reload_completed"
[(set (match_dup 2) (fix:DI (match_dup 1)))
- (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
+ (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+ (set (match_dup 0) (match_dup 3))]
"")
-;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here.
(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "")))]
+ [(set (match_operand:SI 0 "memory_operand" "")
+ (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0))
+ (clobber (match_scratch:DI 2 ""))]
"TARGET_FP && reload_completed"
[(set (match_dup 2) (fix:DI (match_dup 1)))
- (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
- "operands[2] = gen_rtx_REG (DImode, REGNO (operands[0]));")
+ (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+ (set (match_dup 0) (match_dup 3))]
+ ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG.
+ "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));")
(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=f")
- (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")] 5))]
- "TARGET_FP"
- "cvtql%` %R1,%0"
- [(set_attr "type" "fadd")
- (set_attr "trap" "yes")])
-
-(define_insn "fix_truncdfsi2_tp"
- [(set (match_operand:SI 0 "register_operand" "=&f")
- (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))
- (clobber (match_scratch:DI 2 "=&f"))]
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0))
+ (clobber (match_scratch:DI 2 "=&f"))
+ (clobber (match_scratch:SI 3 "=&f"))]
"TARGET_FP && alpha_tp == ALPHA_TP_INSN"
"#"
[(set_attr "type" "fadd")
(set_attr "trap" "yes")])
(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0))
+ (clobber (match_scratch:DI 2 "=f"))]
"TARGET_FP && alpha_tp != ALPHA_TP_INSN"
"#"
[(set_attr "type" "fadd")
(set_attr "trap" "yes")])
-(define_expand "fix_truncdfsi2"
- [(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
- "TARGET_FP"
- "{ if (alpha_tp == ALPHA_TP_INSN)
- { emit_insn(gen_fix_truncdfsi2_tp(operands[0], operands[1])); DONE; }
- }")
-
(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=&f")
+ [(set (match_operand:DI 0 "reg_no_subreg_operand" "=&f")
(fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
"TARGET_FP && alpha_tp == ALPHA_TP_INSN"
"cvt%-q%(c %R1,%0"
@@ -1855,7 +1961,7 @@
(set_attr "trap" "yes")])
(define_insn "fix_truncdfdi2"
- [(set (match_operand:DI 0 "register_operand" "=f")
+ [(set (match_operand:DI 0 "reg_no_subreg_operand" "=f")
(fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
"TARGET_FP"
"cvt%-q%(c %R1,%0"
@@ -1865,55 +1971,52 @@
;; Likewise between SFmode and SImode.
(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (fix:SI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" ""))))
- (clobber (match_scratch:DI 2 ""))]
+ [(set (match_operand:SI 0 "memory_operand" "")
+ (subreg:SI (fix:DI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:SI 3 ""))]
"TARGET_FP && reload_completed"
[(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1))))
- (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
+ (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+ (set (match_dup 0) (match_dup 3))]
"")
-;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here.
(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (fix:SI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" ""))))]
+ [(set (match_operand:SI 0 "memory_operand" "")
+ (subreg:SI (fix:DI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0))
+ (clobber (match_scratch:DI 2 ""))]
"TARGET_FP && reload_completed"
[(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1))))
- (set (match_dup 0) (unspec:SI [(match_dup 2)] 5))]
- "operands[2] = gen_rtx_REG (DImode, REGNO (operands[0]));")
-
-(define_insn "fix_truncsfsi2_tp"
- [(set (match_operand:SI 0 "register_operand" "=&f")
- (fix:SI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))
- (clobber (match_scratch:DI 2 "=&f"))]
+ (set (match_dup 3) (unspec:SI [(match_dup 2)] 5))
+ (set (match_dup 0) (match_dup 3))]
+ ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG.
+ "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (subreg:SI (fix:DI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0))
+ (clobber (match_scratch:DI 2 "=&f"))
+ (clobber (match_scratch:SI 3 "=&f"))]
"TARGET_FP && alpha_tp == ALPHA_TP_INSN"
"#"
[(set_attr "type" "fadd")
(set_attr "trap" "yes")])
(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (subreg:SI (fix:DI (float_extend:DF
+ (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0))
+ (clobber (match_scratch:DI 2 "=f"))]
"TARGET_FP && alpha_tp != ALPHA_TP_INSN"
"#"
[(set_attr "type" "fadd")
(set_attr "trap" "yes")])
-(define_expand "fix_truncsfsi2"
- [(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
- "TARGET_FP"
- "{ if (alpha_tp == ALPHA_TP_INSN)
- { emit_insn(gen_fix_truncsfsi2_tp(operands[0], operands[1])); DONE; }
- }")
-
(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=&f")
+ [(set (match_operand:DI 0 "reg_no_subreg_operand" "=&f")
(fix:DI (float_extend:DF
(match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
"TARGET_FP && alpha_tp == ALPHA_TP_INSN"
@@ -1922,7 +2025,7 @@
(set_attr "trap" "yes")])
(define_insn "fix_truncsfdi2"
- [(set (match_operand:DI 0 "register_operand" "=f")
+ [(set (match_operand:DI 0 "reg_no_subreg_operand" "=f")
(fix:DI (float_extend:DF
(match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
"TARGET_FP"
@@ -1932,7 +2035,7 @@
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=&f")
- (float:SF (match_operand:DI 1 "register_operand" "f")))]
+ (float:SF (match_operand:DI 1 "reg_no_subreg_operand" "f")))]
"TARGET_FP && alpha_tp == ALPHA_TP_INSN"
"cvtq%,%+%& %1,%0"
[(set_attr "type" "fadd")
@@ -1940,7 +2043,7 @@
(define_insn "floatdisf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (float:SF (match_operand:DI 1 "register_operand" "f")))]
+ (float:SF (match_operand:DI 1 "reg_no_subreg_operand" "f")))]
"TARGET_FP"
"cvtq%,%+%& %1,%0"
[(set_attr "type" "fadd")
@@ -1948,7 +2051,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=&f")
- (float:DF (match_operand:DI 1 "register_operand" "f")))]
+ (float:DF (match_operand:DI 1 "reg_no_subreg_operand" "f")))]
"TARGET_FP && alpha_tp == ALPHA_TP_INSN"
"cvtq%-%+%& %1,%0"
[(set_attr "type" "fadd")
@@ -1956,7 +2059,7 @@
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (float:DF (match_operand:DI 1 "register_operand" "f")))]
+ (float:DF (match_operand:DI 1 "reg_no_subreg_operand" "f")))]
"TARGET_FP"
"cvtq%-%+%& %1,%0"
[(set_attr "type" "fadd")
@@ -1990,7 +2093,7 @@
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m,f")))]
"TARGET_FP && alpha_tp != ALPHA_TP_INSN"
"@
- cpys %1,%1,%0
+ fmov %1,%0
ld%, %0,%1
st%- %1,%0"
[(set_attr "type" "fcpys,fld,fst")
@@ -2205,7 +2308,7 @@
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=&f")
(sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
- "TARGET_FP && TARGET_CIX && alpha_tp == ALPHA_TP_INSN"
+ "TARGET_FP && TARGET_FIX && alpha_tp == ALPHA_TP_INSN"
"sqrt%,%)%& %R1,%0"
[(set_attr "type" "fsqrt")
(set_attr "opsize" "si")
@@ -2214,7 +2317,7 @@
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
- "TARGET_FP && TARGET_CIX"
+ "TARGET_FP && TARGET_FIX"
"sqrt%,%)%& %R1,%0"
[(set_attr "type" "fsqrt")
(set_attr "opsize" "si")
@@ -2223,7 +2326,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=&f")
(sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
- "TARGET_FP && TARGET_CIX && alpha_tp == ALPHA_TP_INSN"
+ "TARGET_FP && TARGET_FIX && alpha_tp == ALPHA_TP_INSN"
"sqrt%-%)%& %R1,%0"
[(set_attr "type" "fsqrt")
(set_attr "trap" "yes")])
@@ -2231,7 +2334,7 @@
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
- "TARGET_FP && TARGET_CIX"
+ "TARGET_FP && TARGET_FIX"
"sqrt%-%)%& %1,%0"
[(set_attr "type" "fsqrt")
(set_attr "trap" "yes")])
@@ -2262,7 +2365,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (if_then_else:DI
+ (if_then_else:SI
(match_operator 2 "signed_comparison_operator"
[(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J")
(match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")])
@@ -2322,69 +2425,6 @@
cmovlbc %r2,%3,%0"
[(set_attr "type" "icmov")])
-;; This form is added since combine thinks that an IF_THEN_ELSE with both
-;; arms constant is a single insn, so it won't try to form it if combine
-;; knows they are really two insns. This occurs in divides by powers
-;; of two.
-
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=r")
- (if_then_else:DI
- (match_operator 2 "signed_comparison_operator"
- [(match_operand:DI 3 "reg_or_0_operand" "rJ")
- (const_int 0)])
- (plus:DI (match_dup 0)
- (match_operand:DI 1 "reg_or_8bit_operand" "rI"))
- (match_dup 0)))
- (clobber (match_scratch:DI 4 "=&r"))]
- ""
- "addq %0,%1,%4\;cmov%C2 %r3,%4,%0"
- [(set_attr "type" "icmov")
- (set_attr "length" "8")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (if_then_else:DI
- (match_operator 2 "signed_comparison_operator"
- [(match_operand:DI 3 "reg_or_0_operand" "")
- (const_int 0)])
- (plus:DI (match_dup 0)
- (match_operand:DI 1 "reg_or_8bit_operand" ""))
- (match_dup 0)))
- (clobber (match_operand:DI 4 "register_operand" ""))]
- ""
- [(set (match_dup 4) (plus:DI (match_dup 0) (match_dup 1)))
- (set (match_dup 0) (if_then_else:DI (match_op_dup 2
- [(match_dup 3)
- (const_int 0)])
- (match_dup 4) (match_dup 0)))]
- "")
-
-(define_split
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (if_then_else:DI
- (match_operator 1 "comparison_operator"
- [(zero_extract:DI (match_operand:DI 2 "register_operand" "")
- (const_int 1)
- (match_operand:DI 3 "const_int_operand" ""))
- (const_int 0)])
- (match_operand:DI 4 "reg_or_8bit_operand" "")
- (match_operand:DI 5 "reg_or_8bit_operand" "")))
- (clobber (match_operand:DI 6 "register_operand" ""))])]
- "INTVAL (operands[3]) != 0"
- [(set (match_dup 6)
- (lshiftrt:DI (match_dup 2) (match_dup 3)))
- (set (match_dup 0)
- (if_then_else:DI (match_op_dup 1
- [(zero_extract:DI (match_dup 6)
- (const_int 1)
- (const_int 0))
- (const_int 0)])
- (match_dup 4)
- (match_dup 5)))]
- "")
-
;; For ABS, we have two choices, depending on whether the input and output
;; registers are the same or not.
(define_expand "absdi2"
@@ -2460,7 +2500,7 @@
(define_insn "sminqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (smin:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+ (smin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
(match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"minsb8 %r1,%2,%0"
@@ -2468,7 +2508,7 @@
(define_insn "uminqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (umin:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+ (umin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
(match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"minub8 %r1,%2,%0"
@@ -2476,7 +2516,7 @@
(define_insn "smaxqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (smax:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+ (smax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
(match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"maxsb8 %r1,%2,%0"
@@ -2484,7 +2524,7 @@
(define_insn "umaxqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (umax:SI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
+ (umax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ")
(match_operand:QI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"maxub8 %r1,%2,%0"
@@ -2492,7 +2532,7 @@
(define_insn "sminhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (smin:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+ (smin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
(match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"minsw4 %r1,%2,%0"
@@ -2500,7 +2540,7 @@
(define_insn "uminhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (umin:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+ (umin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
(match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"minuw4 %r1,%2,%0"
@@ -2508,7 +2548,7 @@
(define_insn "smaxhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (smax:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+ (smax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
(match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"maxsw4 %r1,%2,%0"
@@ -2516,7 +2556,7 @@
(define_insn "umaxhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (umax:SI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
+ (umax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ")
(match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"maxuw4 %r1,%2,%0"
@@ -3197,7 +3237,7 @@
(define_expand "movsicc"
[(set (match_operand:SI 0 "register_operand" "")
- (if_then_else:DI (match_operand 1 "comparison_operator" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
(match_operand:SI 2 "reg_or_8bit_operand" "")
(match_operand:SI 3 "reg_or_8bit_operand" "")))]
""
@@ -3610,7 +3650,7 @@
abort ();
operands[1] = XEXP (operands[1], 0);
- if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG)
+ if (GET_CODE (operands[1]) != SYMBOL_REF && GET_CODE (operands[1]) != REG)
operands[1] = force_reg (DImode, operands[1]);
}")
@@ -3675,7 +3715,7 @@
bsr $26,$%0..ng
jsr $26,%0\;ldgp $29,0($26)"
[(set_attr "type" "jsr")
- (set_attr "length" "12,*,12")])
+ (set_attr "length" "12,*,16")])
(define_insn ""
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i"))
@@ -3698,7 +3738,7 @@
(clobber (reg:DI 27))]
"TARGET_OPEN_VMS"
"@
- bis %2,%2,$27\;jsr $26,0\;ldq $27,0($29)
+ mov %2,$27\;jsr $26,0\;ldq $27,0($29)
ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)"
[(set_attr "type" "jsr")
(set_attr "length" "12,16")])
@@ -3715,7 +3755,7 @@
bsr $26,$%1..ng
jsr $26,%1\;ldgp $29,0($26)"
[(set_attr "type" "jsr")
- (set_attr "length" "12,*,12")])
+ (set_attr "length" "12,*,16")])
(define_insn ""
[(set (match_operand 0 "register_operand" "=rf,rf,rf")
@@ -3740,7 +3780,7 @@
(clobber (reg:DI 27))]
"TARGET_OPEN_VMS"
"@
- bis %3,%3,$27\;jsr $26,0\;ldq $27,0($29)
+ mov %3,$27\;jsr $26,0\;ldq $27,0($29)
ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)"
[(set_attr "type" "jsr")
(set_attr "length" "12,16")])
@@ -3811,12 +3851,6 @@
"jmp $31,(%0),0"
[(set_attr "type" "ibr")])
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nop"
- [(set_attr "type" "ilog")])
-
(define_expand "tablejump"
[(use (match_operand:SI 0 "register_operand" ""))
(use (match_operand:SI 1 "" ""))]
@@ -3987,72 +4021,68 @@
;; they are simpler.
(define_insn ""
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m")
- (match_operand:SF 1 "input_operand" "rG,m,rG,f,G,m,fG"))]
- "! TARGET_CIX
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,r,r,m,m")
+ (match_operand:SF 1 "input_operand" "fG,m,rG,m,fG,r"))]
+ "! TARGET_FIX
&& (register_operand (operands[0], SFmode)
|| reg_or_fp0_operand (operands[1], SFmode))"
"@
- bis %r1,%r1,%0
- ldl %0,%1
- stl %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ld%, %0,%1
- st%, %R1,%0"
- [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")])
+ mov %r1,%0
+ ldl %0,%1
+ st%, %R1,%0
+ stl %r1,%0"
+ [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist")])
(define_insn ""
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m,f,*r")
- (match_operand:SF 1 "input_operand" "rG,m,rG,f,G,m,fG,r,*f"))]
- "TARGET_CIX
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,r,r,m,m,f,*r")
+ (match_operand:SF 1 "input_operand" "fG,m,rG,m,fG,r,r,*f"))]
+ "TARGET_FIX
&& (register_operand (operands[0], SFmode)
|| reg_or_fp0_operand (operands[1], SFmode))"
"@
- bis %r1,%r1,%0
- ldl %0,%1
- stl %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ld%, %0,%1
+ mov %r1,%0
+ ldl %0,%1
st%, %R1,%0
+ stl %r1,%0
itofs %1,%0
ftois %1,%0"
- [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,itof,ftoi")])
+ [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist,itof,ftoi")])
(define_insn ""
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m")
- (match_operand:DF 1 "input_operand" "rG,m,rG,f,G,m,fG"))]
- "! TARGET_CIX
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,r,r,m,m")
+ (match_operand:DF 1 "input_operand" "fG,m,rG,m,fG,r"))]
+ "! TARGET_FIX
&& (register_operand (operands[0], DFmode)
|| reg_or_fp0_operand (operands[1], DFmode))"
"@
- bis %r1,%r1,%0
- ldq %0,%1
- stq %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ld%- %0,%1
- st%- %R1,%0"
- [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")])
+ mov %r1,%0
+ ldq %0,%1
+ st%- %R1,%0
+ stq %r1,%0"
+ [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist")])
(define_insn ""
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m,f,*r")
- (match_operand:DF 1 "input_operand" "rG,m,rG,f,G,m,fG,r,*f"))]
- "TARGET_CIX
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,r,r,m,m,f,*r")
+ (match_operand:DF 1 "input_operand" "fG,m,rG,m,fG,r,r,*f"))]
+ "TARGET_FIX
&& (register_operand (operands[0], DFmode)
|| reg_or_fp0_operand (operands[1], DFmode))"
"@
- bis %r1,%r1,%0
- ldq %0,%1
- stq %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ld%- %0,%1
+ mov %r1,%0
+ ldq %0,%1
st%- %R1,%0
+ stq %r1,%0
itoft %1,%0
ftoit %1,%0"
- [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,itof,ftoi")])
+ [(set_attr "type" "fcpys,fld,ilog,ild,fst,ist,itof,ftoi")])
(define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "")
@@ -4077,131 +4107,110 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,f,f,f,m")
- (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,f,J,m,fG"))]
- "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && ! TARGET_CIX
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,f,f,m")
+ (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,fJ,m,f"))]
+ "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && ! TARGET_FIX
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%1
ldah %0,%h1
ldl %0,%1
stl %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ld%, %0,%1
st%, %R1,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ild,ist,fcpys,fcpys,fld,fst")])
+ [(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,f,f,f,m,r,*f")
- (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,f,J,m,fG,f,*r"))]
- "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && TARGET_CIX
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,f,f,m,r,*f")
+ (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,fJ,m,f,f,*r"))]
+ "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && TARGET_FIX
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%1
ldah %0,%h1
ldl %0,%1
stl %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ld%, %0,%1
st%, %R1,%0
ftois %1,%0
itofs %1,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ild,ist,fcpys,fcpys,fld,fst,ftoi,itof")])
+ [(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst,ftoi,itof")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,f,f,f,m")
- (match_operand:SI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,m,fG"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f,m")
+ (match_operand:SI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,m,f"))]
"(TARGET_WINDOWS_NT || TARGET_OPEN_VMS)
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %1,%0
lda %0,%1
ldah %0,%h1
lda %0,%1
ldl %0,%1
stl %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ld%, %0,%1
st%, %R1,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst")])
+ [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
(define_insn ""
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,f,f")
- (match_operand:HI 1 "input_operand" "r,J,I,n,f,J"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,f")
+ (match_operand:HI 1 "input_operand" "rJ,n,fJ"))]
"! TARGET_BWX
&& (register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%L1
- cpys %1,%1,%0
- cpys $f31,$f31,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,fcpys")])
+ fmov %R1,%0"
+ [(set_attr "type" "ilog,iadd,fcpys")])
(define_insn ""
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f")
- (match_operand:HI 1 "input_operand" "r,J,I,n,m,rJ,f,J"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,f")
+ (match_operand:HI 1 "input_operand" "rJ,n,m,rJ,fJ"))]
"TARGET_BWX
&& (register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%L1
ldwu %0,%1
stw %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,fcpys")])
+ fmov %R1,%0"
+ [(set_attr "type" "ilog,iadd,ild,ist,fcpys")])
(define_insn ""
- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,f,f")
- (match_operand:QI 1 "input_operand" "r,J,I,n,f,J"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,f")
+ (match_operand:QI 1 "input_operand" "rJ,n,fJ"))]
"! TARGET_BWX
&& (register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%L1
- cpys %1,%1,%0
- cpys $f31,$f31,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,fcpys")])
+ fmov %R1,%0"
+ [(set_attr "type" "ilog,iadd,fcpys")])
(define_insn ""
- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f")
- (match_operand:QI 1 "input_operand" "r,J,I,n,m,rJ,f,J"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m,f")
+ (match_operand:QI 1 "input_operand" "rJ,n,m,rJ,fJ"))]
"TARGET_BWX
&& (register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%L1
ldbu %0,%1
stb %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,fcpys")])
+ fmov %R1,%0"
+ [(set_attr "type" "ilog,iadd,ild,ist,fcpys")])
;; We do two major things here: handle mem->mem and construct long
;; constants.
@@ -4247,48 +4256,42 @@
}")
(define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,Q")
- (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,Q,fG"))]
- "! TARGET_CIX
+ [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,m,f,f,Q")
+ (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,Q,f"))]
+ "! TARGET_FIX
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%1
ldah %0,%h1
lda %0,%1
ldq%A1 %0,%1
stq%A0 %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ldt %0,%1
stt %R1,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst")])
+ [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
(define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,Q,r,*f")
- (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,Q,fG,f,*r"))]
- "TARGET_CIX
+ [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,m,f,f,Q,r,*f")
+ (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,fJ,Q,f,f,*r"))]
+ "TARGET_FIX
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
"@
- bis %1,%1,%0
- bis $31,$31,%0
- bis $31,%1,%0
+ mov %r1,%0
lda %0,%1
ldah %0,%h1
lda %0,%1
ldq%A1 %0,%1
stq%A0 %r1,%0
- cpys %1,%1,%0
- cpys $f31,$f31,%0
+ fmov %R1,%0
ldt %0,%1
stt %R1,%0
ftoit %1,%0
itoft %1,%0"
- [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst,ftoi,itof")])
+ [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")])
;; We do three major things here: handle mem->mem, put 64-bit constants in
;; memory, and construct long 32-bit constants.
@@ -4320,24 +4323,31 @@
{
if (TARGET_BUILD_CONSTANTS)
{
-#if HOST_BITS_PER_WIDE_INT == 64
- HOST_WIDE_INT i;
+ HOST_WIDE_INT i0, i1;
if (GET_CODE (operands[1]) == CONST_INT)
- i = INTVAL (operands[1]);
+ {
+ i0 = INTVAL (operands[1]);
+ i1 = -(i0 < 0);
+ }
else if (GET_CODE (operands[1]) == CONST_DOUBLE)
- i = CONST_DOUBLE_LOW (operands[1]);
+ {
+#if HOST_BITS_PER_WIDE_INT >= 64
+ i0 = CONST_DOUBLE_LOW (operands[1]);
+ i1 = -(i0 < 0);
+#else
+ i0 = CONST_DOUBLE_LOW (operands[1]);
+ i1 = CONST_DOUBLE_HIGH (operands[1]);
+#endif
+ }
else
abort();
- tem = alpha_emit_set_long_const (operands[0], i);
+ tem = alpha_emit_set_long_const (operands[0], i0, i1);
if (rtx_equal_p (tem, operands[0]))
DONE;
else
operands[1] = tem;
-#else
- abort();
-#endif
}
else
{
@@ -4553,15 +4563,22 @@
{
if (aligned_memory_operand (operands[1], QImode))
{
- rtx aligned_mem, bitnum;
- rtx scratch = (reload_in_progress
- ? gen_rtx_REG (SImode, REGNO (operands[0]))
- : gen_reg_rtx (SImode));
+ if (reload_in_progress)
+ {
+ emit_insn (gen_reload_inqi_help
+ (operands[0], operands[1],
+ gen_rtx_REG (SImode, REGNO (operands[0]))));
+ }
+ else
+ {
+ rtx aligned_mem, bitnum;
+ rtx scratch = gen_reg_rtx (SImode);
- get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+ get_aligned_mem (operands[1], &aligned_mem, &bitnum);
- emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
- scratch));
+ emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
+ scratch));
+ }
}
else
{
@@ -4610,7 +4627,7 @@
rtx temp3 = gen_reg_rtx (DImode);
rtx seq
= gen_unaligned_storeqi (get_unaligned_address (operands[0], 0),
- operands[1], temp1, temp2, temp3);
+ operands[1], temp1, temp2, temp3);
alpha_set_memflags (seq, operands[0]);
emit_insn (seq);
@@ -4664,15 +4681,22 @@
{
if (aligned_memory_operand (operands[1], HImode))
{
- rtx aligned_mem, bitnum;
- rtx scratch = (reload_in_progress
- ? gen_rtx_REG (SImode, REGNO (operands[0]))
- : gen_reg_rtx (SImode));
+ if (reload_in_progress)
+ {
+ emit_insn (gen_reload_inhi_help
+ (operands[0], operands[1],
+ gen_rtx_REG (SImode, REGNO (operands[0]))));
+ }
+ else
+ {
+ rtx aligned_mem, bitnum;
+ rtx scratch = gen_reg_rtx (SImode);
- get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+ get_aligned_mem (operands[1], &aligned_mem, &bitnum);
- emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
- scratch));
+ emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
+ scratch));
+ }
}
else
{
@@ -4738,48 +4762,76 @@
(define_expand "reload_inqi"
[(parallel [(match_operand:QI 0 "register_operand" "=r")
- (match_operand:QI 1 "unaligned_memory_operand" "m")
+ (match_operand:QI 1 "any_memory_operand" "m")
(match_operand:TI 2 "register_operand" "=&r")])]
"! TARGET_BWX"
"
{
- rtx addr = get_unaligned_address (operands[1], 0);
+ rtx scratch, seq;
- /* It is possible that one of the registers we got for operands[2]
- might coincide with that of operands[0] (which is why we made
- it TImode). Pick the other one to use as our scratch. */
- rtx scratch = gen_rtx_REG (DImode,
- REGNO (operands[0]) == REGNO (operands[2])
- ? REGNO (operands[2]) + 1 : REGNO (operands[2]));
+ if (GET_CODE (operands[1]) != MEM)
+ abort ();
- rtx seq = gen_unaligned_loadqi (operands[0], addr, scratch,
- gen_rtx_REG (DImode, REGNO (operands[0])));
+ if (aligned_memory_operand (operands[1], QImode))
+ {
+ seq = gen_reload_inqi_help (operands[0], operands[1],
+ gen_rtx_REG (SImode, REGNO (operands[2])));
+ }
+ else
+ {
+ rtx addr;
+
+ /* It is possible that one of the registers we got for operands[2]
+ might coincide with that of operands[0] (which is why we made
+ it TImode). Pick the other one to use as our scratch. */
+ if (REGNO (operands[0]) == REGNO (operands[2]))
+ scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
+ else
+ scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- alpha_set_memflags (seq, operands[1]);
+ addr = get_unaligned_address (operands[1], 0);
+ seq = gen_unaligned_loadqi (operands[0], addr, scratch,
+ gen_rtx_REG (DImode, REGNO (operands[0])));
+ alpha_set_memflags (seq, operands[1]);
+ }
emit_insn (seq);
DONE;
}")
(define_expand "reload_inhi"
[(parallel [(match_operand:HI 0 "register_operand" "=r")
- (match_operand:HI 1 "unaligned_memory_operand" "m")
+ (match_operand:HI 1 "any_memory_operand" "m")
(match_operand:TI 2 "register_operand" "=&r")])]
"! TARGET_BWX"
"
{
- rtx addr = get_unaligned_address (operands[1], 0);
+ rtx scratch, seq;
- /* It is possible that one of the registers we got for operands[2]
- might coincide with that of operands[0] (which is why we made
- it TImode). Pick the other one to use as our scratch. */
- rtx scratch = gen_rtx_REG (DImode,
- REGNO (operands[0]) == REGNO (operands[2])
- ? REGNO (operands[2]) + 1 : REGNO (operands[2]));
+ if (GET_CODE (operands[1]) != MEM)
+ abort ();
- rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch,
- gen_rtx_REG (DImode, REGNO (operands[0])));
+ if (aligned_memory_operand (operands[1], HImode))
+ {
+ seq = gen_reload_inhi_help (operands[0], operands[1],
+ gen_rtx_REG (SImode, REGNO (operands[2])));
+ }
+ else
+ {
+ rtx addr;
+
+ /* It is possible that one of the registers we got for operands[2]
+ might coincide with that of operands[0] (which is why we made
+ it TImode). Pick the other one to use as our scratch. */
+ if (REGNO (operands[0]) == REGNO (operands[2]))
+ scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
+ else
+ scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- alpha_set_memflags (seq, operands[1]);
+ addr = get_unaligned_address (operands[1], 0);
+ seq = gen_unaligned_loadhi (operands[0], addr, scratch,
+ gen_rtx_REG (DImode, REGNO (operands[0])));
+ alpha_set_memflags (seq, operands[1]);
+ }
emit_insn (seq);
DONE;
}")
@@ -4791,16 +4843,15 @@
"! TARGET_BWX"
"
{
+ if (GET_CODE (operands[0]) != MEM)
+ abort ();
+
if (aligned_memory_operand (operands[0], QImode))
{
- rtx aligned_mem, bitnum;
-
- get_aligned_mem (operands[0], &aligned_mem, &bitnum);
-
- emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
- gen_rtx_REG (SImode, REGNO (operands[2])),
- gen_rtx_REG (SImode,
- REGNO (operands[2]) + 1)));
+ emit_insn (gen_reload_outqi_help
+ (operands[0], operands[1],
+ gen_rtx_REG (SImode, REGNO (operands[2])),
+ gen_rtx_REG (SImode, REGNO (operands[2]) + 1)));
}
else
{
@@ -4818,7 +4869,6 @@
alpha_set_memflags (seq, operands[0]);
emit_insn (seq);
}
-
DONE;
}")
@@ -4829,16 +4879,15 @@
"! TARGET_BWX"
"
{
+ if (GET_CODE (operands[0]) != MEM)
+ abort ();
+
if (aligned_memory_operand (operands[0], HImode))
{
- rtx aligned_mem, bitnum;
-
- get_aligned_mem (operands[0], &aligned_mem, &bitnum);
-
- emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
- gen_rtx_REG (SImode, REGNO (operands[2])),
- gen_rtx_REG (SImode,
- REGNO (operands[2]) + 1)));
+ emit_insn (gen_reload_outhi_help
+ (operands[0], operands[1],
+ gen_rtx_REG (SImode, REGNO (operands[2])),
+ gen_rtx_REG (SImode, REGNO (operands[2]) + 1)));
}
else
{
@@ -4856,7 +4905,102 @@
alpha_set_memflags (seq, operands[0]);
emit_insn (seq);
}
+ DONE;
+}")
+
+;; Helpers for the above. The way reload is structured, we can't
+;; always get a proper address for a stack slot during reload_foo
+;; expansion, so we must delay our address manipulations until after.
+
+(define_insn "reload_inqi_help"
+ [(set (match_operand:QI 0 "register_operand" "r")
+ (match_operand:QI 1 "memory_operand" "m"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ "! TARGET_BWX && (reload_in_progress || reload_completed)"
+ "#")
+
+(define_insn "reload_inhi_help"
+ [(set (match_operand:HI 0 "register_operand" "r")
+ (match_operand:HI 1 "memory_operand" "m"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ "! TARGET_BWX && (reload_in_progress || reload_completed)"
+ "#")
+(define_insn "reload_outqi_help"
+ [(set (match_operand:QI 0 "memory_operand" "m")
+ (match_operand:QI 1 "register_operand" "r"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))
+ (clobber (match_operand:SI 3 "register_operand" "r"))]
+ "! TARGET_BWX && (reload_in_progress || reload_completed)"
+ "#")
+
+(define_insn "reload_outhi_help"
+ [(set (match_operand:HI 0 "memory_operand" "m")
+ (match_operand:HI 1 "register_operand" "r"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))
+ (clobber (match_operand:SI 3 "register_operand" "r"))]
+ "! TARGET_BWX && (reload_in_progress || reload_completed)"
+ "#")
+
+(define_split
+ [(set (match_operand:QI 0 "register_operand" "r")
+ (match_operand:QI 1 "memory_operand" "m"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ "! TARGET_BWX && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx aligned_mem, bitnum;
+ get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+ emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
+ operands[2]));
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:HI 0 "register_operand" "r")
+ (match_operand:HI 1 "memory_operand" "m"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ "! TARGET_BWX && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx aligned_mem, bitnum;
+ get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+ emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
+ operands[2]));
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:QI 0 "memory_operand" "m")
+ (match_operand:QI 1 "register_operand" "r"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))
+ (clobber (match_operand:SI 3 "register_operand" "r"))]
+ "! TARGET_BWX && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx aligned_mem, bitnum;
+ get_aligned_mem (operands[0], &aligned_mem, &bitnum);
+ emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
+ operands[2], operands[3]));
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:HI 0 "memory_operand" "m")
+ (match_operand:HI 1 "register_operand" "r"))
+ (clobber (match_operand:SI 2 "register_operand" "r"))
+ (clobber (match_operand:SI 3 "register_operand" "r"))]
+ "! TARGET_BWX && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx aligned_mem, bitnum;
+ get_aligned_mem (operands[0], &aligned_mem, &bitnum);
+ emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
+ operands[2], operands[3]));
DONE;
}")
@@ -5080,29 +5224,14 @@
""
"*
{
- static int label_no;
- int count_regno = REGNO (operands[0]);
- int ptr_regno = REGNO (operands[1]);
- char label[64];
-
- /* Ho hum, output the hard way to get the label at the beginning of
- the line. Wish there were a magic char you could get
- asm_output_printf to do that. Then we could use %= as well and
- get rid of the label_no bits here too. */
-
- ASM_GENERATE_INTERNAL_LABEL (label, \"LSC\", label_no);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LSC\", label_no++);
-
- fprintf (asm_out_file, \"\\tstq $31,-8192($%d)\\n\", ptr_regno);
- fprintf (asm_out_file, \"\\tsubq $%d,1,$%d\\n\", count_regno, count_regno);
- fprintf (asm_out_file, \"\\tlda $%d,-8192($%d)\\n\", ptr_regno, ptr_regno);
- fprintf (asm_out_file, \"\\tbne $%d,\", count_regno);
- assemble_name (asm_out_file, label);
- putc ('\\n', asm_out_file);
-
- return \"\";
+ operands[2] = gen_label_rtx ();
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (operands[2]));
+
+ return \"stq $31,-8192(%1)\;subq %0,1,%0\;lda %1,-8192(%1)\;bne %0,%l2\";
}"
- [(set_attr "length" "16")])
+ [(set_attr "length" "16")
+ (set_attr "type" "multi")])
(define_expand "prologue"
[(clobber (const_int 0))]
@@ -5114,13 +5243,39 @@
(match_operand:DI 1 "register_operand" "r"))
(clobber (mem:BLK (match_operand:DI 2 "register_operand" "r")))]
""
- "bis %1,%1,%0")
+ "mov %1,%0")
(define_expand "epilogue"
[(clobber (const_int 0))]
""
"alpha_expand_epilogue (); DONE;")
+(define_expand "eh_epilogue"
+ [(use (match_operand:DI 0 "register_operand" "r"))
+ (use (match_operand:DI 1 "register_operand" "r"))
+ (use (match_operand:DI 2 "register_operand" "r"))]
+ "! TARGET_OPEN_VMS"
+ "
+{
+ alpha_eh_epilogue_sp_ofs = operands[1];
+ if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 26)
+ {
+ rtx ra = gen_rtx_REG (Pmode, 26);
+ emit_move_insn (ra, operands[2]);
+ operands[2] = ra;
+ }
+}")
+
+;; In creating a large stack frame, NT _must_ use ldah+lda to load
+;; the frame size into a register. We use this pattern to ensure
+;; we get lda instead of addq.
+(define_insn "nt_lda"
+ [(set (match_operand:DI 0 "register_operand" "r")
+ (unspec:DI [(match_dup 0)
+ (match_operand:DI 1 "const_int_operand" "n")] 6))]
+ ""
+ "lda %0,%1(%0)")
+
(define_expand "builtin_longjmp"
[(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
@@ -5143,19 +5298,29 @@
where to look for it when we get back to setjmp's function for
restoring the gp. */
emit_indirect_jump (pv);
+ DONE;
}")
(define_insn "builtin_setjmp_receiver"
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
+ [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT && TARGET_AS_CAN_SUBTRACT_LABELS"
"\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)"
- [(set_attr "length" "8")])
+ [(set_attr "length" "8")
+ (set_attr "type" "multi")])
(define_insn ""
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
+ [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
- "br $27,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($27)"
- [(set_attr "length" "12")])
+ "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
+
+(define_insn "exception_receiver"
+ [(unspec_volatile [(const_int 0)] 7)]
+ "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
+ "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
(define_expand "nonlocal_goto_receiver"
[(unspec_volatile [(const_int 0)] 1)
@@ -5187,7 +5352,8 @@
(clobber (reg:DI 0))]
"TARGET_OPEN_VMS"
"lda $0,OTS$HOME_ARGS\;ldq $0,8($0)\;jsr $0,OTS$HOME_ARGS"
- [(set_attr "length" "16")])
+ [(set_attr "length" "16")
+ (set_attr "type" "multi")])
;; Close the trap shadow of preceeding instructions. This is generated
;; by alpha_reorg.
@@ -5197,6 +5363,31 @@
""
"trapb"
[(set_attr "type" "misc")])
+
+;; No-op instructions used by machine-dependant reorg to preserve
+;; alignment for instruction issue.
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ [(set_attr "type" "ilog")])
+
+(define_insn "fnop"
+ [(const_int 1)]
+ "TARGET_FP"
+ "fnop"
+ [(set_attr "type" "fcpys")])
+
+(define_insn "unop"
+ [(const_int 2)]
+ ""
+ "unop")
+
+(define_insn "realign"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 6)]
+ ""
+ ".align %0 #realign")
;; Peepholes go at the end.
@@ -5220,5 +5411,5 @@
; (match_operand:SI 1 "hard_fp_register_operand" "f"))
; (set (match_operand:DI 2 "register_operand" "=r")
; (sign_extend:DI (match_dup 0)))]
-; "TARGET_CIX && dead_or_set_p (insn, operands[0])"
+; "TARGET_FIX && dead_or_set_p (insn, operands[0])"
; "ftois %1,%2")
diff --git a/contrib/gcc/config/alpha/alpha32.h b/contrib/gcc/config/alpha/alpha32.h
new file mode 100644
index 0000000..3cbcfe1
--- /dev/null
+++ b/contrib/gcc/config/alpha/alpha32.h
@@ -0,0 +1,104 @@
+/* Definitions of target machine for GNU compiler, for DEC Alpha
+ running Windows/NT.
+ Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
+
+ Derived from code
+ Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+ Donn Terry, Softway Systems, Inc.
+
+ This file contains the code-generation stuff common to the 32-bit
+ versions of the DEC/Compaq Alpha architecture. It is shared by
+ Interix and NT/Win32 ports. It should not contain compile-time
+ or run-time dependent environment values (such as compiler options
+ or anything containing a file or pathname.)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef TARGET_WINDOWS_NT
+#define TARGET_WINDOWS_NT 1
+
+/* WinNT (and thus Interix) use unsigned int */
+#define SIZE_TYPE "unsigned int"
+
+/* Pointer is 32 bits but the hardware has 64-bit addresses, sign extended. */
+#undef POINTER_SIZE
+#define POINTER_SIZE 32
+#define POINTERS_EXTEND_UNSIGNED 0
+
+/* We don't change Pmode to the "obvious" SI mode... the above appears
+ to affect the in-memory size; we want the registers to stay DImode
+ to match the md file */
+
+/* "long" is 32 bits. */
+#undef LONG_TYPE_SIZE
+#define LONG_TYPE_SIZE 32
+
+
+/* Output assembler code for a block containing the constant parts
+ of a trampoline, leaving space for the variable parts.
+
+ The trampoline should set the static chain pointer to value placed
+ into the trampoline and should branch to the specified routine. */
+
+#undef TRAMPOLINE_TEMPLATE
+#define TRAMPOLINE_TEMPLATE(FILE) \
+{ \
+ fprintf (FILE, "\tbr $27,$LTRAMPP\n"); \
+ fprintf (FILE, "$LTRAMPP:\n\tldl $1,12($27)\n"); \
+ fprintf (FILE, "\tldl $27,16($27)\n"); \
+ fprintf (FILE, "\tjmp $31,($27),0\n"); \
+ fprintf (FILE, "\t.long 0,0\n"); \
+}
+
+/* Length in units of the trampoline for entering a nested function. */
+
+#undef TRAMPOLINE_SIZE
+#define TRAMPOLINE_SIZE 24
+
+/* Emit RTL insns to initialize the variable parts of a trampoline.
+ FNADDR is an RTX for the address of the function's pure code.
+ CXT is an RTX for the static chain value for the function. */
+
+#undef INITIALIZE_TRAMPOLINE
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+ alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 20, 16, 12)
+
+/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
+ Used for C++ multiple inheritance. */
+
+#undef ASM_OUTPUT_MI_THUNK
+#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
+do { \
+ char *op, *fn_name = XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0); \
+ int reg; \
+ \
+ /* Mark end of prologue. */ \
+ output_end_prologue (FILE); \
+ \
+ /* Rely on the assembler to macro expand a large delta. */ \
+ reg = aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) ? 17 : 16; \
+ fprintf (FILE, "\tlda $%d,%ld($%d)\n", reg, (long)(DELTA), reg); \
+ \
+ op = "jsr"; \
+ if (current_file_function_operand (XEXP (DECL_RTL (FUNCTION), 0))) \
+ op = "br"; \
+ fprintf (FILE, "\t%s $31,", op); \
+ assemble_name (FILE, fn_name); \
+ fputc ('\n', FILE); \
+} while (0)
diff --git a/contrib/gcc/config/alpha/crtbegin.asm b/contrib/gcc/config/alpha/crtbegin.asm
index c28440d..f954f1a 100644
--- a/contrib/gcc/config/alpha/crtbegin.asm
+++ b/contrib/gcc/config/alpha/crtbegin.asm
@@ -50,6 +50,8 @@ __CTOR_LIST__:
__DTOR_LIST__:
.quad -1
+.section .eh_frame,"aw"
+__EH_FRAME_BEGIN__:
#
# Fragment of the ELF _fini routine that invokes our dtor cleanup.
@@ -67,18 +69,33 @@ __DTOR_LIST__:
1: ldgp $29,0($29)
jsr $26,__do_global_dtors_aux
+ # Ideally this call would go in crtend.o, except that we can't
+ # get hold of __EH_FRAME_BEGIN__ there.
+
+ jsr $26,__do_frame_takedown
+
# Must match the alignment we got from crti.o else we get
# zero-filled holes in our _fini function and then SIGILL.
.align 3
#
+ # Fragment of the ELF _init routine that sets up the frame info.
+ #
+
+.section .init,"ax"
+ br $29,1f
+1: ldgp $29,0($29)
+ jsr $26,__do_frame_setup
+ .align 3
+
+ #
# Invoke our destructors in order.
#
.data
# Support recursive calls to exit.
-9: .quad __DTOR_LIST__
+$ptr: .quad __DTOR_LIST__
.text
@@ -86,15 +103,14 @@ __DTOR_LIST__:
.ent __do_global_dtors_aux
__do_global_dtors_aux:
- ldgp $29,0($27)
lda $30,-16($30)
.frame $30,16,$26,0
stq $9,8($30)
stq $26,0($30)
.mask 0x4000200,-16
- .prologue 1
+ .prologue 0
- lda $9,9b
+ lda $9,$ptr
br 1f
0: stq $1,0($9)
jsr $26,($27)
@@ -109,3 +125,68 @@ __do_global_dtors_aux:
ret
.end __do_global_dtors_aux
+
+ #
+ # Install our frame info.
+ #
+
+ # ??? How can we rationally keep this size correct?
+
+.section .bss
+ .type $object,@object
+ .align 3
+$object:
+ .zero 48
+ .size $object, 48
+
+.text
+
+ .align 3
+ .ent __do_frame_setup
+
+__do_frame_setup:
+ ldgp $29,0($27)
+ lda $30,-16($30)
+ .frame $30,16,$26,0
+ stq $26,0($30)
+ .mask 0x4000000,-16
+ .prologue 1
+
+ lda $1,__register_frame_info
+ beq $1,0f
+ lda $16,__EH_FRAME_BEGIN__
+ lda $17,$object
+ jsr $26,__register_frame_info
+ ldq $26,0($30)
+0: lda $30,16($30)
+ ret
+
+ .end __do_frame_setup
+
+ #
+ # Remove our frame info.
+ #
+
+ .align 3
+ .ent __do_frame_takedown
+
+__do_frame_takedown:
+ ldgp $29,0($27)
+ lda $30,-16($30)
+ .frame $30,16,$26,0
+ stq $26,0($30)
+ .mask 0x4000000,-16
+ .prologue 1
+
+ lda $1,__deregister_frame_info
+ beq $1,0f
+ lda $16,__EH_FRAME_BEGIN__
+ jsr $26,__deregister_frame_info
+ ldq $26,0($30)
+0: lda $30,16($30)
+ ret
+
+ .end __do_frame_takedown
+
+.weak __register_frame_info
+.weak __deregister_frame_info
diff --git a/contrib/gcc/config/alpha/crtend.asm b/contrib/gcc/config/alpha/crtend.asm
index 36f11b9..4a0cc5e 100644
--- a/contrib/gcc/config/alpha/crtend.asm
+++ b/contrib/gcc/config/alpha/crtend.asm
@@ -50,6 +50,9 @@ __CTOR_END__:
__DTOR_END__:
.quad 0
+.section .eh_frame,"aw"
+__FRAME_END__:
+ .quad 0
#
# Fragment of the ELF _init routine that invokes our ctor startup
diff --git a/contrib/gcc/config/alpha/elf.h b/contrib/gcc/config/alpha/elf.h
index 4f4703c..6cea3da 100644
--- a/contrib/gcc/config/alpha/elf.h
+++ b/contrib/gcc/config/alpha/elf.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for DEC Alpha w/ELF.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Contributed by Richard Henderson (rth@tamu.edu).
This file is part of GNU CC.
@@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */
#define OBJECT_FORMAT_ELF
#define DBX_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
@@ -34,7 +35,7 @@ Boston, MA 02111-1307, USA. */
#define CC1_SPEC "%{G*}"
#undef ASM_SPEC
-#define ASM_SPEC "%{G*} %{relax:-relax}"
+#define ASM_SPEC "%{G*} %{relax:-relax} %{gdwarf*:-no-mdebug}"
#undef LINK_SPEC
#define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \
@@ -49,18 +50,21 @@ Boston, MA 02111-1307, USA. */
/* Output at beginning of assembler file. */
#undef ASM_FILE_START
#define ASM_FILE_START(FILE) \
-{ \
- alpha_write_verstamp (FILE); \
- output_file_directive (FILE, main_input_filename); \
+do { \
+ if (write_symbols != DWARF2_DEBUG) \
+ { \
+ alpha_write_verstamp (FILE); \
+ output_file_directive (FILE, main_input_filename); \
+ } \
fprintf (FILE, "\t.set noat\n"); \
- fprintf (FILE, "\t.set noreorder\n"); \
- if (TARGET_BWX | TARGET_MAX | TARGET_CIX) \
+ fprintf (FILE, "\t.set noreorder\n"); \
+ if (TARGET_BWX | TARGET_MAX | TARGET_FIX | TARGET_CIX) \
{ \
fprintf (FILE, "\t.arch %s\n", \
(alpha_cpu == PROCESSOR_EV6 ? "ev6" \
: TARGET_MAX ? "pca56" : "ev56")); \
} \
-}
+} while (0)
extern void output_file_directive ();
@@ -79,8 +83,9 @@ extern void output_file_directive ();
#else
#define ASM_FILE_END(FILE) \
do { \
- fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
+ if (!flag_no_ident) \
+ fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
+ IDENT_ASM_OP, version_string); \
} while (0)
#endif
@@ -434,20 +439,23 @@ void FN () \
size_directive_output was set
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
-#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
-do { \
- char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
- && ! AT_END && TOP_LEVEL \
- && DECL_INITIAL (DECL) == error_mark_node \
- && !size_directive_output) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
- } \
- } while (0)
+#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
+do { \
+ char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
+ && ! AT_END && TOP_LEVEL \
+ && DECL_INITIAL (DECL) == error_mark_node \
+ && !size_directive_output) \
+ { \
+ size_directive_output = 1; \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, name); \
+ putc (',', FILE); \
+ fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
+ int_size_in_bytes (TREE_TYPE (DECL))); \
+ putc ('\n', FILE); \
+ } \
+} while (0)
/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
@@ -518,3 +526,9 @@ do { \
/* We support #pragma. */
#define HANDLE_SYSV_PRAGMA
+
+/* Undo the auto-alignment stuff from alpha.h. ELF has unaligned data
+ pseudos natively. */
+#undef UNALIGNED_SHORT_ASM_OP
+#undef UNALIGNED_INT_ASM_OP
+#undef UNALIGNED_DOUBLE_INT_ASM_OP
diff --git a/contrib/gcc/config/alpha/lib1funcs.asm b/contrib/gcc/config/alpha/lib1funcs.asm
new file mode 100644
index 0000000..e63180a
--- /dev/null
+++ b/contrib/gcc/config/alpha/lib1funcs.asm
@@ -0,0 +1,325 @@
+/* DEC Alpha division and remainder support.
+ Copyright (C) 1994, 1999 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/* This had to be written in assembler because the division functions
+ use a non-standard calling convention.
+
+ This file provides an implementation of __divqu, __divq, __divlu,
+ __divl, __remqu, __remq, __remlu and __reml. CPP macros control
+ the exact operation.
+
+ Operation performed: $27 := $24 o $25, clobber $28, return address to
+ caller in $23, where o one of the operations.
+
+ The following macros need to be defined:
+
+ SIZE, the number of bits, 32 or 64.
+
+ TYPE, either UNSIGNED or SIGNED
+
+ OPERATION, either DIVISION or REMAINDER
+
+ SPECIAL_CALLING_CONVENTION, 0 or 1. It is useful for debugging to
+ define this to 0. That removes the `__' prefix to make the function
+ name not collide with the existing libc.a names, and uses the
+ standard Alpha procedure calling convention.
+*/
+
+#ifndef SPECIAL_CALLING_CONVENTION
+#define SPECIAL_CALLING_CONVENTION 1
+#endif
+
+#ifdef L_divl
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __divl
+#else
+#define FUNCTION_NAME divl
+#endif
+#define SIZE 32
+#define TYPE SIGNED
+#define OPERATION DIVISION
+#endif
+
+#ifdef L_divlu
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __divlu
+#else
+#define FUNCTION_NAME divlu
+#endif
+#define SIZE 32
+#define TYPE UNSIGNED
+#define OPERATION DIVISION
+#endif
+
+#ifdef L_divq
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __divq
+#else
+#define FUNCTION_NAME divq
+#endif
+#define SIZE 64
+#define TYPE SIGNED
+#define OPERATION DIVISION
+#endif
+
+#ifdef L_divqu
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __divqu
+#else
+#define FUNCTION_NAME divqu
+#endif
+#define SIZE 64
+#define TYPE UNSIGNED
+#define OPERATION DIVISION
+#endif
+
+#ifdef L_reml
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __reml
+#else
+#define FUNCTION_NAME reml
+#endif
+#define SIZE 32
+#define TYPE SIGNED
+#define OPERATION REMAINDER
+#endif
+
+#ifdef L_remlu
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __remlu
+#else
+#define FUNCTION_NAME remlu
+#endif
+#define SIZE 32
+#define TYPE UNSIGNED
+#define OPERATION REMAINDER
+#endif
+
+#ifdef L_remq
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __remq
+#else
+#define FUNCTION_NAME remq
+#endif
+#define SIZE 64
+#define TYPE SIGNED
+#define OPERATION REMAINDER
+#endif
+
+#ifdef L_remqu
+#if SPECIAL_CALLING_CONVENTION
+#define FUNCTION_NAME __remqu
+#else
+#define FUNCTION_NAME remqu
+#endif
+#define SIZE 64
+#define TYPE UNSIGNED
+#define OPERATION REMAINDER
+#endif
+
+#define tmp0 $3
+#define tmp1 $28
+#define cnt $1
+#define result_sign $2
+
+#if SPECIAL_CALLING_CONVENTION
+#define N $24
+#define D $25
+#define Q RETREG
+#define RETREG $27
+#else
+#define N $16
+#define D $17
+#define Q RETREG
+#define RETREG $0
+#endif
+
+/* Misc symbols to make alpha assembler easier to read. */
+#define zero $31
+#define sp $30
+
+/* Symbols to make interface nicer. */
+#define UNSIGNED 0
+#define SIGNED 1
+#define DIVISION 0
+#define REMAINDER 1
+
+ .set noreorder
+ .set noat
+.text
+ .align 3
+ .globl FUNCTION_NAME
+ .ent FUNCTION_NAME
+FUNCTION_NAME:
+
+ .frame $30,0,$26,0
+ .prologue 0
+
+/* Under the special calling convention, we have to preserve all register
+ values but $23 and $28. */
+#if SPECIAL_CALLING_CONVENTION
+ lda sp,-64(sp)
+#if OPERATION == DIVISION
+ stq N,0(sp)
+#endif
+ stq D,8(sp)
+ stq cnt,16(sp)
+ stq result_sign,24(sp)
+ stq tmp0,32(sp)
+#endif
+
+/* If we are computing the remainder, move N to the register that is used
+ for the return value, and redefine what register is used for N. */
+#if OPERATION == REMAINDER
+ bis N,N,RETREG
+#undef N
+#define N RETREG
+#endif
+
+/* Perform conversion from 32 bit types to 64 bit types. */
+#if SIZE == 32
+#if TYPE == SIGNED
+ /* If there are problems with the signed case, add these instructions.
+ The caller should already have done this.
+ addl N,0,N # sign extend N
+ addl D,0,D # sign extend D
+ */
+#else /* UNSIGNED */
+ zap N,0xf0,N # zero extend N (caller required to sign extend)
+ zap D,0xf0,D # zero extend D
+#endif
+#endif
+
+/* Check for divide by zero. */
+ bne D,$34
+ lda $16,-2(zero)
+ call_pal 0xaa
+$34:
+
+#if TYPE == SIGNED
+#if OPERATION == DIVISION
+ xor N,D,result_sign
+#else
+ bis N,N,result_sign
+#endif
+/* Get the absolute values of N and D. */
+ subq zero,N,tmp0
+ cmovlt N,tmp0,N
+ subq zero,D,tmp0
+ cmovlt D,tmp0,D
+#endif
+
+/* Compute CNT = ceil(log2(N)) - ceil(log2(D)). This is the number of
+ divide iterations we will have to perform. Should you wish to optimize
+ this, check a few bits at a time, preferably using zap/zapnot. Be
+ careful though, this code runs fast fro the most common cases, when the
+ quotient is small. */
+ bge N,$35
+ bis zero,1,cnt
+ blt D,$40
+ .align 3
+$39: addq D,D,D
+ addl cnt,1,cnt
+ bge D,$39
+ br zero,$40
+$35: cmpult N,D,tmp0
+ bis zero,zero,cnt
+ bne tmp0,$42
+ .align 3
+$44: addq D,D,D
+ cmpult N,D,tmp0
+ addl cnt,1,cnt
+ beq tmp0,$44
+$42: srl D,1,D
+$40:
+ subl cnt,1,cnt
+
+
+/* Actual divide. Could be optimized with unrolling. */
+#if OPERATION == DIVISION
+ bis zero,zero,Q
+#endif
+ blt cnt,$46
+ .align 3
+$49: cmpule D,N,tmp1
+ subq N,D,tmp0
+ srl D,1,D
+ subl cnt,1,cnt
+ cmovne tmp1,tmp0,N
+#if OPERATION == DIVISION
+ addq Q,Q,Q
+ bis Q,tmp1,Q
+#endif
+ bge cnt,$49
+$46:
+
+
+/* The result is now in RETREG. NOTE! It was written to RETREG using
+ either N or Q as a synonym! */
+
+
+/* Change the sign of the result as needed. */
+#if TYPE == SIGNED
+ subq zero,RETREG,tmp0
+ cmovlt result_sign,tmp0,RETREG
+#endif
+
+
+/* Restore clobbered registers. */
+#if SPECIAL_CALLING_CONVENTION
+#if OPERATION == DIVISION
+ ldq N,0(sp)
+#endif
+ ldq D,8(sp)
+ ldq cnt,16(sp)
+ ldq result_sign,24(sp)
+ ldq tmp0,32(sp)
+
+ lda sp,64(sp)
+#endif
+
+
+/* Sign extend an *unsigned* 32 bit result, as required by the Alpha
+ conventions. */
+#if TYPE == UNSIGNED && SIZE == 32
+ /* This could be avoided by adding some CPP hair to the divide loop.
+ It is probably not worth the added complexity. */
+ addl RETREG,0,RETREG
+#endif
+
+
+#if SPECIAL_CALLING_CONVENTION
+ ret zero,($23),1
+#else
+ ret zero,($26),1
+#endif
+ .end FUNCTION_NAME
diff --git a/contrib/gcc/config/alpha/linux-ecoff.h b/contrib/gcc/config/alpha/linux-ecoff.h
index a6cd5b2..824d028 100644
--- a/contrib/gcc/config/alpha/linux-ecoff.h
+++ b/contrib/gcc/config/alpha/linux-ecoff.h
@@ -17,13 +17,14 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ECOFF)");
-#undef SUB_CPP_PREDEFINES
-#define SUB_CPP_PREDEFINES "-D__ECOFF__"
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "-D__ECOFF__"
#undef LINK_SPEC
#define LINK_SPEC "-G 8 %{O*:-O3} %{!O*:-O1}"
diff --git a/contrib/gcc/config/alpha/linux-elf.h b/contrib/gcc/config/alpha/linux-elf.h
index 90009f1..fc07127 100644
--- a/contrib/gcc/config/alpha/linux-elf.h
+++ b/contrib/gcc/config/alpha/linux-elf.h
@@ -17,7 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ELF)");
diff --git a/contrib/gcc/config/alpha/linux.h b/contrib/gcc/config/alpha/linux.h
index 3791c89..b8eb9e9 100644
--- a/contrib/gcc/config/alpha/linux.h
+++ b/contrib/gcc/config/alpha/linux.h
@@ -17,14 +17,16 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS)
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
-"-Dlinux -Dunix -Asystem(linux) -D_LONGLONG -D__alpha__ " SUB_CPP_PREDEFINES
+"-Dlinux -Dunix -Asystem(linux) -D_LONGLONG -D__alpha__ " \
+SUB_CPP_PREDEFINES
#undef LIB_SPEC
#define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}"
diff --git a/contrib/gcc/config/alpha/netbsd-elf.h b/contrib/gcc/config/alpha/netbsd-elf.h
index 17d7bb0..6e4f4da 100644
--- a/contrib/gcc/config/alpha/netbsd-elf.h
+++ b/contrib/gcc/config/alpha/netbsd-elf.h
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (Alpha NetBSD/ELF)");
diff --git a/contrib/gcc/config/alpha/netbsd.h b/contrib/gcc/config/alpha/netbsd.h
index 054e9e0..5189064 100644
--- a/contrib/gcc/config/alpha/netbsd.h
+++ b/contrib/gcc/config/alpha/netbsd.h
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS)
diff --git a/contrib/gcc/config/alpha/osf.h b/contrib/gcc/config/alpha/osf.h
index 956961f..5054444 100644
--- a/contrib/gcc/config/alpha/osf.h
+++ b/contrib/gcc/config/alpha/osf.h
@@ -30,9 +30,19 @@ Boston, MA 02111-1307, USA. */
-Dunix -D__osf__ -D_LONGLONG -DSYSTYPE_BSD \
-D_SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4)"
+/* Accept DEC C flags for multithreaded programs. We use _PTHREAD_USE_D4
+ instead of PTHREAD_USE_D4 since both have the same effect and the former
+ doesn't invade the users' namespace. */
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC \
+"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4}"
+
/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */
-#define LIB_SPEC "%{p:-lprof1 -lpdf} %{pg:-lprof1 -lpdf} %{a:-lprof2} -lc"
+#define LIB_SPEC \
+"%{p|pg:-lprof1%{pthread|threads:_r} -lpdf} %{a:-lprof2} \
+ %{threads: -lpthreads} %{pthread|threads: -lpthread -lmach -lexc} -lc"
/* Pass "-G 8" to ld because Alpha's CC does. Pass -O3 if we are
optimizing, -O1 if we are not. Pass -shared, -non_shared or
diff --git a/contrib/gcc/config/alpha/t-ieee b/contrib/gcc/config/alpha/t-ieee
new file mode 100644
index 0000000..a1f93db
--- /dev/null
+++ b/contrib/gcc/config/alpha/t-ieee
@@ -0,0 +1,6 @@
+# All alphas get an IEEE complaint set of libraries.
+MULTILIB_OPTIONS = mieee
+MULTILIB_DIRNAMES = ieee
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/alpha/t-interix b/contrib/gcc/config/alpha/t-interix
new file mode 100644
index 0000000..d6d80e9
--- /dev/null
+++ b/contrib/gcc/config/alpha/t-interix
@@ -0,0 +1,16 @@
+# t-interix
+
+# System headers will track gcc's needs.
+# Even LANG_EXTRA_HEADERS may be temporary.
+USER_H=$(LANG_EXTRA_HEADERS)
+
+# We don't want this one either.
+INSTALL_ASSERT_H=
+
+
+
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIBGCC1 = libgcc1-asm.a
+
+LIB1ASMSRC = alpha/lib1funcs.asm
+LIB1ASMFUNCS = _divqu _divq _divlu _divl _remqu _remq _remlu _reml
diff --git a/contrib/gcc/config/alpha/vms.h b/contrib/gcc/config/alpha/vms.h
index 44cf5bf..44388b2 100644
--- a/contrib/gcc/config/alpha/vms.h
+++ b/contrib/gcc/config/alpha/vms.h
@@ -439,10 +439,6 @@ extern int vms_valid_decl_attribute_p ();
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
fprintf (FILE, "\t.align %d\n", LOG);
-#define UNALIGNED_SHORT_ASM_OP ".word"
-#define UNALIGNED_INT_ASM_OP ".long"
-#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
-
#define ASM_OUTPUT_SECTION(FILE,SECTION) \
(strcmp (SECTION, ".text") == 0) \
? text_section () \
diff --git a/contrib/gcc/config/alpha/vxworks.h b/contrib/gcc/config/alpha/vxworks.h
index 6dee4b3..7ef1fee 100644
--- a/contrib/gcc/config/alpha/vxworks.h
+++ b/contrib/gcc/config/alpha/vxworks.h
@@ -36,11 +36,11 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
#define LIB_SPEC ""
-/* VxWorks uses object files, not loadable images. make linker just
- combine objects. */
+/* VxWorks uses object files, not loadable images. Make linker just combine
+ objects. Also show using 32 bit mode and set start of text to 0. */
#undef LINK_SPEC
-#define LINK_SPEC "-r"
+#define LINK_SPEC "-r -taso -T 0"
/* VxWorks provides the functionality of crt0.o and friends itself. */
diff --git a/contrib/gcc/config/alpha/xm-alpha-interix.h b/contrib/gcc/config/alpha/xm-alpha-interix.h
new file mode 100644
index 0000000..02c53b8
--- /dev/null
+++ b/contrib/gcc/config/alpha/xm-alpha-interix.h
@@ -0,0 +1,45 @@
+/* Configuration for GNU compiler
+ for an DEC/Compaq Alpha
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Donn Terry, Softway Systems, Inc.
+ derived from code by Douglas B. Rupp (drupp@cs.washington.edu)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <alpha/xm-alpha.h>
+
+#undef HOST_BITS_PER_LONG
+#define HOST_BITS_PER_LONG 32
+
+#define HOST_BITS_PER_WIDE_INT 64
+#ifdef __GNUC__
+# define HOST_WIDE_INT long long
+#else
+# define HOST_WIDE_INT __int64
+#endif
+
+
+#define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG
+#ifdef __GNUC__
+# define HOST_WIDEST_INT long long
+#else
+# define HOST_WIDEST_INT __int64
+#endif
+#define HOST_WIDEST_INT_PRINT_DEC "%lld"
+#define HOST_WIDEST_INT_PRINT_UNSIGNED "%llu"
+#define HOST_WIDEST_INT_PRINT_HEX "0x%llx"
diff --git a/contrib/gcc/config/alpha/xm-alpha.h b/contrib/gcc/config/alpha/xm-alpha.h
index 7665127..c04844f 100644
--- a/contrib/gcc/config/alpha/xm-alpha.h
+++ b/contrib/gcc/config/alpha/xm-alpha.h
@@ -46,7 +46,7 @@ Boston, MA 02111-1307, USA. */
#if defined(__GNUC__) && !defined(USE_C_ALLOCA)
#define alloca __builtin_alloca
#else
-#if !defined(_WIN32) && !defined(USE_C_ALLOCA) && !defined(OPEN_VMS)
+#if !defined(_WIN32) && !defined(USE_C_ALLOCA) && !defined(OPEN_VMS) && !defined(__INTERIX)
#include <alloca.h>
#else
extern void *alloca ();
diff --git a/contrib/gcc/config/dbxcoff.h b/contrib/gcc/config/dbxcoff.h
index 9497a70..1d5b448 100644
--- a/contrib/gcc/config/dbxcoff.h
+++ b/contrib/gcc/config/dbxcoff.h
@@ -49,8 +49,8 @@ Boston, MA 02111-1307, USA. */
#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
- fprintf (FILE, \
- "\t.text\n\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO)
+ asm_fprintf (FILE, \
+ "\t.text\n\t.stabs \"\",%d,0,0,%LLetext\n%LLetext:\n", N_SO)
/* Like block addresses, stabs line numbers are relative to the
current function. */
diff --git a/contrib/gcc/config/dbxelf.h b/contrib/gcc/config/dbxelf.h
new file mode 100644
index 0000000..3971bc1
--- /dev/null
+++ b/contrib/gcc/config/dbxelf.h
@@ -0,0 +1,109 @@
+/* Definitions needed when using stabs embedded in ELF sections.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This file may be included by any ELF target which wishes to
+ support -gstabs generating stabs in sections, as produced by gas
+ and understood by gdb. */
+
+#ifndef __DBX_ELF_H
+#define __DBX_ELF_H
+
+/* Output DBX (stabs) debugging information if doing -gstabs. */
+
+#undef DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO
+
+/* Make LBRAC and RBRAC addresses relative to the start of the
+ function. The native Solaris stabs debugging format works this
+ way, gdb expects it, and it reduces the number of relocation
+ entries... */
+
+#undef DBX_BLOCKS_FUNCTION_RELATIVE
+#define DBX_BLOCKS_FUNCTION_RELATIVE 1
+
+/* ... but, to make this work, functions must appear prior to line info. */
+
+#undef DBX_FUNCTION_FIRST
+#define DBX_FUNCTION_FIRST
+
+/* When generating stabs debugging, use N_BINCL entries. */
+
+#undef DBX_USE_BINCL
+#define DBX_USE_BINCL
+
+/* There is no limit to the length of stabs strings. */
+
+#ifndef DBX_CONTIN_LENGTH
+#define DBX_CONTIN_LENGTH 0
+#endif
+
+/* When using stabs, gcc2_compiled must be a stabs entry, not an
+ ordinary symbol, or gdb won't see it. Furthermore, since gdb reads
+ the input piecemeal, starting with each N_SO, it's a lot easier if
+ the gcc2 flag symbol is *after* the N_SO rather than before it. So
+ we emit an N_OPT stab there. */
+
+#define ASM_IDENTIFY_GCC(FILE) \
+do \
+ { \
+ if (write_symbols != DBX_DEBUG) \
+ fputs ("gcc2_compiled.:\n", FILE); \
+ } \
+while (0)
+
+#define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) \
+do \
+ { \
+ if (write_symbols == DBX_DEBUG) \
+ fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \
+ } \
+while (0)
+
+/* Like block addresses, stabs line numbers are relative to the
+ current function. */
+
+#undef ASM_OUTPUT_SOURCE_LINE
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \
+do \
+ { \
+ static int sym_lineno = 1; \
+ char temp[256]; \
+ ASM_GENERATE_INTERNAL_LABEL (temp, "LM", sym_lineno); \
+ fprintf (FILE, ".stabn 68,0,%d,", LINE); \
+ assemble_name (FILE, temp); \
+ putc ('-', FILE); \
+ assemble_name (FILE, \
+ XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
+ putc ('\n', FILE); \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, "LM", sym_lineno); \
+ sym_lineno += 1; \
+ } \
+while (0)
+
+/* Generate a blank trailing N_SO to mark the end of the .o file, since
+ we can't depend upon the linker to mark .o file boundaries with
+ embedded stabs. */
+
+#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
+#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
+ asm_fprintf (FILE, \
+ "\t.text\n\t.stabs \"\",%d,0,0,%LLetext\n%LLetext:\n", N_SO)
+
+#endif /* __DBX_ELF_H */
diff --git a/contrib/gcc/config/elfos.h b/contrib/gcc/config/elfos.h
new file mode 100644
index 0000000..6c10731
--- /dev/null
+++ b/contrib/gcc/config/elfos.h
@@ -0,0 +1,704 @@
+/* elfos.h -- operating system specific defines to be used when
+ targeting GCC for some generic ELF system
+ Copyright (C) 1991, 1994, 1995, 1999 Free Software Foundation, Inc.
+ Based on svr4.h contributed by Ron Guilmette (rfg@netcom.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* For the sake of libgcc2.c, indicate target supports atexit. */
+#define HAVE_ATEXIT
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared: \
+ %{!symbolic: \
+ %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\
+ crtbegin.o%s"
+
+/* Attach a special .ident directive to the end of the file to identify
+ the version of GCC which compiled this code. The format of the
+ .ident string is patterned after the ones produced by native svr4
+ C compilers. */
+
+#define IDENT_ASM_OP ".ident"
+
+#define ASM_FILE_END(FILE) \
+do { \
+ if (!flag_no_ident) \
+ fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
+ IDENT_ASM_OP, version_string); \
+ } while (0)
+
+/* Output #ident as a .ident. */
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) \
+ fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME);
+
+/* Use periods rather than dollar signs in special g++ assembler names. */
+
+#define NO_DOLLAR_IN_LABEL
+
+/* Writing `int' for a bitfield forces int alignment for the structure. */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Implicit library calls should use memcpy, not bcopy, etc. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* Handle #pragma weak and #pragma pack. */
+
+#define HANDLE_SYSV_PRAGMA
+
+/* System V Release 4 uses DWARF debugging info. */
+
+#define DWARF_DEBUGGING_INFO
+
+/* All ELF targets can support DWARF-2. */
+
+#define DWARF2_DEBUGGING_INFO
+
+/* Also allow them to support STABS debugging. */
+
+#include "dbxelf.h"
+
+/* The GNU tools operate better with stabs. Since we don't have
+ any native tools to be compatible with, default to stabs. */
+
+#ifndef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#endif
+
+#undef ASM_BYTE_OP
+#define ASM_BYTE_OP ".byte"
+
+#undef SET_ASM_OP
+#define SET_ASM_OP ".set"
+
+/* This is how to begin an assembly language file. Most svr4 assemblers want
+ at least a .file directive to come first, and some want to see a .version
+ directive come right after that. Here we just establish a default
+ which generates only the .file directive. If you need a .version
+ directive for any specific target, you should override this definition
+ in the target-specific file which includes this one. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ output_file_directive ((FILE), main_input_filename)
+
+/* This is how to allocate empty space in some section. The .zero
+ pseudo-op is used for this on most svr4 assemblers. */
+
+#define SKIP_ASM_OP ".zero"
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE))
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this.
+
+ For System V Release 4 the convention is *not* to prepend a leading
+ underscore onto user-level symbol names. */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+
+ For most svr4 systems, the convention is that any symbol which begins
+ with a period is not put into the linker symbol table by the assembler. */
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \
+do { \
+ fprintf (FILE, ".%s%d:\n", PREFIX, NUM); \
+} while (0)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'.
+
+ For most svr4 systems, the convention is that any symbol which begins
+ with a period is not put into the linker symbol table by the assembler. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+do { \
+ sprintf (LABEL, "*.%s%d", PREFIX, NUM); \
+} while (0)
+
+/* Output the label which precedes a jumptable. Note that for all svr4
+ systems where we actually generate jumptables (which is to say every
+ svr4 target except i386, where we use casesi instead) we put the jump-
+ tables into the .rodata section and since other stuff could have been
+ put into the .rodata section prior to any given jumptable, we have to
+ make sure that the location counter for the .rodata section gets pro-
+ perly re-aligned prior to the actual beginning of the jump table. */
+
+#define ALIGN_ASM_OP ".align"
+
+#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ ASM_OUTPUT_ALIGN ((FILE), 2);
+#endif
+
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
+ do { \
+ ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
+ } while (0)
+
+/* The standard SVR4 assembler seems to require that certain builtin
+ library routines (e.g. .udiv) be explicitly declared as .globl
+ in each assembly file where they are referenced. */
+
+#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
+ ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0))
+
+/* This says how to output assembler code to declare an
+ uninitialized external linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here. */
+
+#define COMMON_ASM_OP ".comm"
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+do { \
+ fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
+} while (0)
+
+/* This says how to output assembler code to declare an
+ uninitialized internal linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here. */
+
+#define LOCAL_ASM_OP ".local"
+
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+do { \
+ fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), "\n"); \
+ ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \
+} while (0)
+
+/* This is the pseudo-op used to generate a 32-bit word of data with a
+ specific value in some section. This is the same for all known svr4
+ assemblers. */
+
+#define INT_ASM_OP ".long"
+
+/* This is the pseudo-op used to generate a contiguous sequence of byte
+ values from a double-quoted string WITHOUT HAVING A TERMINATING NUL
+ AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */
+
+#undef ASCII_DATA_ASM_OP
+#define ASCII_DATA_ASM_OP ".ascii"
+
+/* Support const sections and the ctors and dtors sections for g++.
+ Note that there appears to be two different ways to support const
+ sections at the moment. You can either #define the symbol
+ READONLY_DATA_SECTION (giving it some code which switches to the
+ readonly data section) or else you can #define the symbols
+ EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
+ SELECT_RTX_SECTION. We do both here just to be on the safe side. */
+
+#define USE_CONST_SECTION 1
+
+#define CONST_SECTION_ASM_OP ".section\t.rodata"
+
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+
+ Note that we want to give these sections the SHF_WRITE attribute
+ because these sections will actually contain data (i.e. tables of
+ addresses of functions in the current root executable or shared library
+ file) and, in the case of a shared library, the relocatable addresses
+ will have to be properly resolved/relocated (and then written into) by
+ the dynamic linker when it actually attaches the given shared library
+ to the executing process. (Note that on SVR4, you may wish to use the
+ `-z text' option to the ELF linker, when building a shared library, as
+ an additional check that you are doing everything right. But if you do
+ use the `-z text' option when building a shared library, you will get
+ errors unless the .ctors and .dtors sections are marked as writable
+ via the SHF_WRITE attribute.) */
+
+#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\""
+#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
+
+/* On svr4, we *do* have support for the .init and .fini sections, and we
+ can put stuff in there to be executed before and after `main'. We let
+ crtstuff.c and other files know this by defining the following symbols.
+ The definitions say how to change sections to the .init and .fini
+ sections. This is the same for all known svr4 assemblers. */
+
+#define INIT_SECTION_ASM_OP ".section\t.init"
+#define FINI_SECTION_ASM_OP ".section\t.fini"
+
+/* A default list of other sections which we might be "in" at any given
+ time. For targets that use additional sections (e.g. .tdesc) you
+ should override this definition in the target-specific file which
+ includes this file. */
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
+
+/* A default list of extra section function definitions. For targets
+ that use additional sections (e.g. .tdesc) you should override this
+ definition in the target-specific file which includes this file. */
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CONST_SECTION_FUNCTION \
+ CTORS_SECTION_FUNCTION \
+ DTORS_SECTION_FUNCTION
+
+#define READONLY_DATA_SECTION() const_section ()
+
+extern void text_section ();
+
+#define CONST_SECTION_FUNCTION \
+void \
+const_section () \
+{ \
+ if (!USE_CONST_SECTION) \
+ text_section(); \
+ else if (in_section != in_const) \
+ { \
+ fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
+ in_section = in_const; \
+ } \
+}
+
+#define CTORS_SECTION_FUNCTION \
+void \
+ctors_section () \
+{ \
+ if (in_section != in_ctors) \
+ { \
+ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
+ in_section = in_ctors; \
+ } \
+}
+
+#define DTORS_SECTION_FUNCTION \
+void \
+dtors_section () \
+{ \
+ if (in_section != in_dtors) \
+ { \
+ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
+ in_section = in_dtors; \
+ } \
+}
+
+/* Switch into a generic section.
+ This is currently only used to support section attributes. */
+
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
+do { \
+ static struct section_info \
+ { \
+ struct section_info *next; \
+ char *name; \
+ enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \
+ } *sections; \
+ struct section_info *s; \
+ char *mode; \
+ enum sect_enum type; \
+ \
+ for (s = sections; s; s = s->next) \
+ if (!strcmp (NAME, s->name)) \
+ break; \
+ \
+ if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
+ type = SECT_EXEC, mode = "ax"; \
+ else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
+ type = SECT_RO, mode = "a"; \
+ else \
+ type = SECT_RW, mode = "aw"; \
+ \
+ if (s == 0) \
+ { \
+ s = (struct section_info *) xmalloc (sizeof (struct section_info)); \
+ s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \
+ strcpy (s->name, NAME); \
+ s->type = type; \
+ s->next = sections; \
+ sections = s; \
+ fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, mode); \
+ } \
+ else \
+ { \
+ if (DECL && s->type != type) \
+ error_with_decl (DECL, "%s causes a section type conflict"); \
+ \
+ fprintf (FILE, ".section\t%s\n", NAME); \
+ } \
+} while (0)
+
+#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
+#define UNIQUE_SECTION(DECL,RELOC) \
+do { \
+ int len; \
+ char *name, *string, *prefix; \
+ \
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
+ \
+ if (! DECL_ONE_ONLY (DECL)) \
+ { \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ prefix = ".text."; \
+ else if (DECL_READONLY_SECTION (DECL, RELOC)) \
+ prefix = ".rodata."; \
+ else \
+ prefix = ".data."; \
+ } \
+ else if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ prefix = ".gnu.linkonce.t."; \
+ else if (DECL_READONLY_SECTION (DECL, RELOC)) \
+ prefix = ".gnu.linkonce.r."; \
+ else \
+ prefix = ".gnu.linkonce.d."; \
+ \
+ len = strlen (name) + strlen (prefix); \
+ string = alloca (len + 1); \
+ sprintf (string, "%s%s", prefix, name); \
+ \
+ DECL_SECTION_NAME (DECL) = build_string (len, string); \
+} while (0)
+/* A C statement (sans semicolon) to output an element in the table of
+ global constructors. */
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global destructors. */
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* A C statement or statements to switch to the appropriate
+ section for output of DECL. DECL is either a `VAR_DECL' node
+ or a constant of some sort. RELOC indicates whether forming
+ the initial value of DECL requires link-time relocations. */
+
+#define SELECT_SECTION(DECL,RELOC) \
+{ \
+ if (TREE_CODE (DECL) == STRING_CST) \
+ { \
+ if (! flag_writable_strings) \
+ const_section (); \
+ else \
+ data_section (); \
+ } \
+ else if (TREE_CODE (DECL) == VAR_DECL) \
+ { \
+ if ((flag_pic && RELOC) \
+ || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
+ || !DECL_INITIAL (DECL) \
+ || (DECL_INITIAL (DECL) != error_mark_node \
+ && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
+ data_section (); \
+ else \
+ const_section (); \
+ } \
+ else \
+ const_section (); \
+}
+
+/* A C statement or statements to switch to the appropriate
+ section for output of RTX in mode MODE. RTX is some kind
+ of constant in RTL. The argument MODE is redundant except
+ in the case of a `const_int' rtx. Currently, these always
+ go into the const section. */
+
+#undef SELECT_RTX_SECTION
+#define SELECT_RTX_SECTION(MODE,RTX) const_section()
+
+/* Define the strings used for the special svr4 .type and .size directives.
+ These strings generally do not vary from one system running svr4 to
+ another, but if a given system (e.g. m88k running svr) needs to use
+ different pseudo-op names for these, they may be overridden in the
+ file which includes this one. */
+
+#define TYPE_ASM_OP ".type"
+#define SIZE_ASM_OP ".size"
+
+/* This is how we tell the assembler that a symbol is weak. */
+
+#define ASM_WEAKEN_LABEL(FILE,NAME) \
+ do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); } while (0)
+
+/* The following macro defines the format used to output the second
+ operand of the .type assembler directive. Different svr4 assemblers
+ expect various different forms for this operand. The one given here
+ is just a default. You may need to override it in your machine-
+ specific tm.h file (depending upon the particulars of your assembler). */
+
+#define TYPE_OPERAND_FMT "@%s"
+
+/* Write the extra assembler code needed to declare a function's result.
+ Most svr4 assemblers don't require any special declaration of the
+ result value, but there are exceptions. */
+
+#ifndef ASM_DECLARE_RESULT
+#define ASM_DECLARE_RESULT(FILE, RESULT)
+#endif
+
+/* These macros generate the special .type and .size directives which
+ are used to set the corresponding fields of the linker symbol table
+ entries in an ELF object file under SVR4. These macros also output
+ the starting labels for the relevant functions/objects. */
+
+/* Write the extra assembler code needed to declare a function properly.
+ Some svr4 assemblers need to also have something extra said about the
+ function's return value. We allow for that here. */
+
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do { \
+ fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ putc (',', FILE); \
+ fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
+ putc ('\n', FILE); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL(FILE, NAME); \
+ } while (0)
+
+/* Write the extra assembler code needed to declare an object properly. */
+
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do { \
+ fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ putc (',', FILE); \
+ fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
+ putc ('\n', FILE); \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
+ } \
+ ASM_OUTPUT_LABEL(FILE, NAME); \
+ } while (0)
+
+/* Output the size directive for a decl in rest_of_decl_compilation
+ in the case where we did not do so before the initializer.
+ Once we find the error_mark_node, we know that the value of
+ size_directive_output was set
+ by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
+
+#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
+do { \
+ char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
+ && ! AT_END && TOP_LEVEL \
+ && DECL_INITIAL (DECL) == error_mark_node \
+ && !size_directive_output) \
+ { \
+ size_directive_output = 1; \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, name); \
+ fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
+ } \
+ } while (0)
+
+/* This is how to declare the size of a function. */
+
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do { \
+ if (!flag_inhibit_size_directive) \
+ { \
+ char label[256]; \
+ static int labelno; \
+ labelno++; \
+ ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, (FNAME)); \
+ fprintf (FILE, ","); \
+ assemble_name (FILE, label); \
+ fprintf (FILE, "-"); \
+ assemble_name (FILE, (FNAME)); \
+ putc ('\n', FILE); \
+ } \
+ } while (0)
+
+/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
+ ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
+ corresponds to a particular byte value [0..255]. For any
+ given byte value, if the value in the corresponding table
+ position is zero, the given character can be output directly.
+ If the table value is 1, the byte must be output as a \ooo
+ octal escape. If the tables value is anything else, then the
+ byte value should be output as a \ followed by the value
+ in the table. Note that we can use standard UN*X escape
+ sequences for many control characters, but we don't use
+ \a to represent BEL because some svr4 assemblers (e.g. on
+ the i386) don't know about that. Also, we don't use \v
+ since some versions of gas, such as 2.2 did not accept it. */
+
+#define ESCAPES \
+"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
+
+/* Some svr4 assemblers have a limit on the number of characters which
+ can appear in the operand of a .string directive. If your assembler
+ has such a limitation, you should define STRING_LIMIT to reflect that
+ limit. Note that at least some svr4 assemblers have a limit on the
+ actual number of bytes in the double-quoted string, and that they
+ count each character in an escape sequence as one byte. Thus, an
+ escape sequence like \377 would count as four bytes.
+
+ If your target assembler doesn't support the .string directive, you
+ should define this to zero.
+*/
+
+#define STRING_LIMIT ((unsigned) 256)
+
+#define STRING_ASM_OP ".string"
+
+/* The routine used to output NUL terminated strings. We use a special
+ version of this for most svr4 targets because doing so makes the
+ generated assembly code more compact (and thus faster to assemble)
+ as well as more readable, especially for targets like the i386
+ (where the only alternative is to output character sequences as
+ comma separated lists of numbers). */
+
+#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
+ do \
+ { \
+ register unsigned char *_limited_str = (unsigned char *) (STR); \
+ register unsigned ch; \
+ fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \
+ for (; ch = *_limited_str; _limited_str++) \
+ { \
+ register int escape; \
+ switch (escape = ESCAPES[ch]) \
+ { \
+ case 0: \
+ putc (ch, (FILE)); \
+ break; \
+ case 1: \
+ fprintf ((FILE), "\\%03o", ch); \
+ break; \
+ default: \
+ putc ('\\', (FILE)); \
+ putc (escape, (FILE)); \
+ break; \
+ } \
+ } \
+ fprintf ((FILE), "\"\n"); \
+ } \
+ while (0)
+
+/* The routine used to output sequences of byte values. We use a special
+ version of this for most svr4 targets because doing so makes the
+ generated assembly code more compact (and thus faster to assemble)
+ as well as more readable. Note that if we find subparts of the
+ character sequence which end with NUL (and which are shorter than
+ STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
+ do \
+ { \
+ register unsigned char *_ascii_bytes = (unsigned char *) (STR); \
+ register unsigned char *limit = _ascii_bytes + (LENGTH); \
+ register unsigned bytes_in_chunk = 0; \
+ for (; _ascii_bytes < limit; _ascii_bytes++) \
+ { \
+ register unsigned char *p; \
+ if (bytes_in_chunk >= 60) \
+ { \
+ fprintf ((FILE), "\"\n"); \
+ bytes_in_chunk = 0; \
+ } \
+ for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
+ continue; \
+ if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \
+ { \
+ if (bytes_in_chunk > 0) \
+ { \
+ fprintf ((FILE), "\"\n"); \
+ bytes_in_chunk = 0; \
+ } \
+ ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \
+ _ascii_bytes = p; \
+ } \
+ else \
+ { \
+ register int escape; \
+ register unsigned ch; \
+ if (bytes_in_chunk == 0) \
+ fprintf ((FILE), "\t%s\t\"", ASCII_DATA_ASM_OP); \
+ switch (escape = ESCAPES[ch = *_ascii_bytes]) \
+ { \
+ case 0: \
+ putc (ch, (FILE)); \
+ bytes_in_chunk++; \
+ break; \
+ case 1: \
+ fprintf ((FILE), "\\%03o", ch); \
+ bytes_in_chunk += 4; \
+ break; \
+ default: \
+ putc ('\\', (FILE)); \
+ putc (escape, (FILE)); \
+ bytes_in_chunk += 2; \
+ break; \
+ } \
+ } \
+ } \
+ if (bytes_in_chunk > 0) \
+ fprintf ((FILE), "\"\n"); \
+ } \
+ while (0)
+
+/* All SVR4 targets use the ELF object file format. */
+#define OBJECT_FORMAT_ELF
diff --git a/contrib/gcc/config/float-sh.h b/contrib/gcc/config/float-sh.h
index 9a94298..4466924 100644
--- a/contrib/gcc/config/float-sh.h
+++ b/contrib/gcc/config/float-sh.h
@@ -37,7 +37,7 @@
#undef FLT_MAX_10_EXP
#define FLT_MAX_10_EXP 38
-#ifdef __SH3E__
+#if defined (__SH3E__) || defined (__SH4_SINGLE_ONLY__)
/* Number of base-FLT_RADIX digits in the significand of a double */
#undef DBL_MANT_DIG
diff --git a/contrib/gcc/config/fp-bit.c b/contrib/gcc/config/fp-bit.c
index f4a1e2a..6b8bd70 100644
--- a/contrib/gcc/config/fp-bit.c
+++ b/contrib/gcc/config/fp-bit.c
@@ -156,8 +156,8 @@ __floatsixf (){ abort(); }
#else /* !EXTENDED_FLOAT_STUBS, rest of file */
-typedef SFtype __attribute__ ((mode (SF)));
-typedef DFtype __attribute__ ((mode (DF)));
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
typedef int HItype __attribute__ ((mode (HI)));
typedef int SItype __attribute__ ((mode (SI)));
@@ -460,7 +460,6 @@ pack_d ( fp_number_type * src)
else if (fraction == 0)
{
exp = 0;
- sign = 0;
}
else
{
@@ -735,7 +734,7 @@ _fpadd_parts (fp_number_type * a,
{
tfraction = a_fraction - b_fraction;
}
- if (tfraction > 0)
+ if (tfraction >= 0)
{
tmp->sign = 0;
tmp->normal_exp = a_normal_exp;
@@ -1000,8 +999,7 @@ multiply (FLO_type arg_a, FLO_type arg_b)
#if defined(L_div_sf) || defined(L_div_df)
static INLINE fp_number_type *
_fpdiv_parts (fp_number_type * a,
- fp_number_type * b,
- fp_number_type * tmp)
+ fp_number_type * b)
{
fractype bit;
fractype numerator;
@@ -1093,13 +1091,12 @@ divide (FLO_type arg_a, FLO_type arg_b)
{
fp_number_type a;
fp_number_type b;
- fp_number_type tmp;
fp_number_type *res;
unpack_d ((FLO_union_type *) & arg_a, &a);
unpack_d ((FLO_union_type *) & arg_b, &b);
- res = _fpdiv_parts (&a, &b, &tmp);
+ res = _fpdiv_parts (&a, &b);
return pack_d (res);
}
@@ -1332,7 +1329,7 @@ si_to_float (SItype arg_a)
{
/* Special case for minint, since there is no +ve integer
representation for it */
- if (arg_a == 0x80000000)
+ if (arg_a == (SItype) 0x80000000)
{
return -2147483648.0;
}
diff --git a/contrib/gcc/config/i386/aix386ng.h b/contrib/gcc/config/i386/aix386ng.h
index a177b69..9a8dae6 100644
--- a/contrib/gcc/config/i386/aix386ng.h
+++ b/contrib/gcc/config/i386/aix386ng.h
@@ -1,5 +1,5 @@
/* Definitions for IBM PS2 running AIX/386.
- Copyright (C) 1988, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1996, 1998 Free Software Foundation, Inc.
Contributed by Minh Tran-Le <TRANLE@intellicorp.com>.
This file is part of GNU CC.
@@ -58,9 +58,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_FILE_START
#define ASM_FILE_START(FILE) \
- do { fprintf (FILE, "\t.file\t"); \
- output_quoted_string (FILE, dump_base_name); \
- fprintf (FILE, "\n"); \
+ do { output_file_directive (FILE, main_input_filename); \
if (optimize) \
ASM_FILE_START_1 (FILE); \
else \
diff --git a/contrib/gcc/config/i386/bsd.h b/contrib/gcc/config/i386/bsd.h
index d50be36..34db79a 100644
--- a/contrib/gcc/config/i386/bsd.h
+++ b/contrib/gcc/config/i386/bsd.h
@@ -49,9 +49,7 @@ Boston, MA 02111-1307, USA. */
??? I am skeptical of this -- RMS. */
#define ASM_FILE_START(FILE) \
- do { fprintf (FILE, "\t.file\t"); \
- output_quoted_string (FILE, dump_base_name); \
- fprintf (FILE, "\n"); \
+ do { output_file_directive (FILE, main_input_filename); \
} while (0)
/* This was suggested, but it shouldn't be right for DBX output. -- RMS
diff --git a/contrib/gcc/config/i386/crtdll.h b/contrib/gcc/config/i386/crtdll.h
index f7eaf2b..3202af8 100644
--- a/contrib/gcc/config/i386/crtdll.h
+++ b/contrib/gcc/config/i386/crtdll.h
@@ -3,7 +3,7 @@
as distinct from winnt.h, which is used to build GCC for use with a
windows style library and tool set and uses the Microsoft tools.
This variant uses CRTDLL.DLL insted of MSVCRTDLL.DLL.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Di386 -D_WIN32 -DWIN32 -D__WIN32__ \
- -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1\
+ -D__MINGW32__=0.2 -DWINNT -D_X86_=1 -D__STDC__=1\
-D__stdcall=__attribute__((__stdcall__)) \
-D_stdcall=__attribute__((__stdcall__)) \
-D__cdecl=__attribute__((__cdecl__)) \
@@ -38,5 +38,3 @@ Boston, MA 02111-1307, USA. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{mdll:dllcrt1%O%s} %{!mdll:crt1%O%s}"
-#undef MATH_LIBRARY
-#define MATH_LIBRARY "-lcrtdll"
diff --git a/contrib/gcc/config/i386/cygwin.asm b/contrib/gcc/config/i386/cygwin.asm
new file mode 100644
index 0000000..4ac4c91
--- /dev/null
+++ b/contrib/gcc/config/i386/cygwin.asm
@@ -0,0 +1,32 @@
+/* stuff needed for libgcc1 on win32. */
+
+#ifdef L_chkstk
+
+ .global ___chkstk
+ .global __alloca
+___chkstk:
+__alloca:
+ pushl %ecx /* save temp */
+ movl %esp,%ecx /* get sp */
+ addl $0x8,%ecx /* and point to return addr */
+
+probe: cmpl $0x1000,%eax /* > 4k ?*/
+ jb done
+
+ subl $0x1000,%ecx /* yes, move pointer down 4k*/
+ orl $0x0,(%ecx) /* probe there */
+ subl $0x1000,%eax /* decrement count */
+ jmp probe /* and do it again */
+
+done: subl %eax,%ecx
+ orl $0x0,(%ecx) /* less that 4k, just peek here */
+
+ movl %esp,%eax
+ movl %ecx,%esp /* decrement stack */
+
+ movl (%eax),%ecx /* recover saved temp */
+ movl 4(%eax),%eax /* get return address */
+ jmp *%eax
+
+
+#endif
diff --git a/contrib/gcc/config/i386/cygwin.h b/contrib/gcc/config/i386/cygwin.h
new file mode 100644
index 0000000..dbea466
--- /dev/null
+++ b/contrib/gcc/config/i386/cygwin.h
@@ -0,0 +1,525 @@
+/* Operating system specific defines to be used when targeting GCC for
+ hosting on Windows NT 3.x, using a Unix style C library and tools,
+ as distinct from winnt.h, which is used to build GCC for use with a
+ windows style library and tool set and uses the Microsoft tools.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define YES_UNDERSCORES
+
+#define DBX_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#include "i386/gas.h"
+#include "dbxcoff.h"
+
+/* Augment TARGET_SWITCHES with the cygwin/no-cygwin options. */
+#define MASK_WIN32 0x40000000 /* Use -lming32 interface */
+#define MASK_CYGWIN 0x20000000 /* Use -lcygwin interface */
+#define MASK_WINDOWS 0x10000000 /* Use windows interface */
+#define MASK_DLL 0x08000000 /* Use dll interface */
+#define MASK_NOP_FUN_DLLIMPORT 0x20000 /* Ignore dllimport for functions */
+
+#define TARGET_WIN32 (target_flags & MASK_WIN32)
+#define TARGET_CYGWIN (target_flags & MASK_CYGWIN)
+#define TARGET_WINDOWS (target_flags & MASK_WINDOWS)
+#define TARGET_DLL (target_flags & MASK_DLL)
+#define TARGET_NOP_FUN_DLLIMPORT (target_flags & MASK_NOP_FUN_DLLIMPORT)
+
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+{ "cygwin", MASK_CYGWIN, "Use the Cygwin interface" }, \
+{ "no-cygwin", MASK_WIN32, "Use the Mingw32 interface" }, \
+{ "windows", MASK_WINDOWS, "Create GUI application" }, \
+{ "console", -MASK_WINDOWS, "Create console application" }, \
+{ "dll", MASK_DLL, "Generate code for a DLL" }, \
+{ "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, "Ignore dllimport for functions" }, \
+{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" },
+
+
+/* Support the __declspec keyword by turning them into attributes.
+ We currently only support: dllimport and dllexport.
+ Note that the current way we do this may result in a collision with
+ predefined attributes later on. This can be solved by using one attribute,
+ say __declspec__, and passing args to it. The problem with that approach
+ is that args are not accumulated: each new appearance would clobber any
+ existing args. */
+
+#ifdef CPP_PREDEFINES
+#undef CPP_PREDEFINES
+#endif
+
+#define CPP_PREDEFINES "-Di386 -D_WIN32 \
+ -DWINNT -D_X86_=1 -D__STDC__=1\
+ -D__stdcall=__attribute__((__stdcall__)) \
+ -D__cdecl=__attribute__((__cdecl__)) \
+ -D__declspec(x)=__attribute__((x)) \
+ -Asystem(winnt) -Acpu(i386) -Amachine(i386)"
+
+/* Normally, -lgcc is not needed since everything in it is in the DLL, but we
+ want to allow things to be added to it when installing new versions of
+ GCC without making a new CYGWIN.DLL, so we leave it. Profiling is handled
+ by calling the init function from the prologue. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{mdll: %{mno-cygwin:dllcrt1%O%s}} \
+ %{!mdll: %{!mno-cygwin:crt0%O%s} \
+ %{mno-cygwin:crt1%O%s} %{pg:gcrt0%O%s}}"
+
+#undef CPP_SPEC
+#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
+ %{!mno-cygwin:-D__CYGWIN32__ -D__CYGWIN__} \
+ %{mno-cygwin:-iwithprefixbefore \
+ ../../../../%(mingw_include_path)/include/mingw32 -D__MINGW32__=0.2}"
+
+/* This macro defines names of additional specifications to put in the specs
+ that can be used in various specifications like CC1_SPEC. Its definition
+ is an initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ specification name, and a string constant that used by the GNU CC driver
+ program.
+
+ Do not define this macro if it does not need to do anything. */
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "mingw_include_path", DEFAULT_TARGET_MACHINE }
+
+/* We have to dynamic link to get to the system DLLs. All of libc, libm and
+ the Unix stuff is in cygwin.dll. The import library is called
+ 'libcygwin.a'. For Windows applications, include more libraries, but
+ always include kernel32. We'd like to specific subsystem windows to
+ ld, but that doesn't work just yet. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{pg:-lgmon} \
+ %{!mno-cygwin:-lcygwin} \
+ %{mno-cygwin:-lmingw32 -lmoldname -lcrtdll} \
+ %{mwindows:-lgdi32 -lcomdlg32} \
+ -luser32 -lkernel32 -ladvapi32 -lshell32"
+
+#define LINK_SPEC "%{mwindows:--subsystem windows} \
+ %{mconsole:--subsystem console} \
+ %{mdll:--dll -e _DllMainCRTStartup@12}"
+
+
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
+#define WCHAR_UNSIGNED 1
+#define WCHAR_TYPE_SIZE 16
+#define WCHAR_TYPE "short unsigned int"
+
+#define HAVE_ATEXIT 1
+
+
+/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
+#define HANDLE_PRAGMA_PACK_PUSH_POP 1
+
+/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+ is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+extern int i386_pe_valid_decl_attribute_p ();
+
+#undef VALID_MACHINE_DECL_ATTRIBUTE
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+ i386_pe_valid_decl_attribute_p (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+
+/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+ is a valid machine specific attribute for TYPE.
+ The attributes in ATTRIBUTES have previously been assigned to TYPE. */
+
+#undef VALID_MACHINE_TYPE_ATTRIBUTE
+#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) \
+ i386_pe_valid_type_attribute_p (TYPE, ATTRIBUTES, IDENTIFIER, ARGS)
+extern int i386_pe_valid_type_attribute_p ();
+
+extern union tree_node *i386_pe_merge_decl_attributes ();
+#define MERGE_MACHINE_DECL_ATTRIBUTES(OLD, NEW) \
+ i386_pe_merge_decl_attributes ((OLD), (NEW))
+
+/* Used to implement dllexport overriding dllimport semantics. It's also used
+ to handle vtables - the first pass won't do anything because
+ DECL_CONTEXT (DECL) will be 0 so i386_pe_dll{ex,im}port_p will return 0.
+ It's also used to handle dllimport override semantics. */
+#if 0
+#define REDO_SECTION_INFO_P(DECL) \
+ ((DECL_MACHINE_ATTRIBUTES (DECL) != NULL_TREE) \
+ || (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
+#else
+#define REDO_SECTION_INFO_P(DECL) 1
+#endif
+
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_ctor, in_dtor, in_drectve
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CTOR_SECTION_FUNCTION \
+ DTOR_SECTION_FUNCTION \
+ DRECTVE_SECTION_FUNCTION \
+ SWITCH_TO_SECTION_FUNCTION
+
+#define CTOR_SECTION_FUNCTION \
+void \
+ctor_section () \
+{ \
+ if (in_section != in_ctor) \
+ { \
+ fprintf (asm_out_file, "\t.section .ctor\n"); \
+ in_section = in_ctor; \
+ } \
+}
+
+#define DTOR_SECTION_FUNCTION \
+void \
+dtor_section () \
+{ \
+ if (in_section != in_dtor) \
+ { \
+ fprintf (asm_out_file, "\t.section .dtor\n"); \
+ in_section = in_dtor; \
+ } \
+}
+
+#define DRECTVE_SECTION_FUNCTION \
+void \
+drectve_section () \
+{ \
+ if (in_section != in_drectve) \
+ { \
+ fprintf (asm_out_file, "%s\n", "\t.section .drectve\n"); \
+ in_section = in_drectve; \
+ } \
+}
+
+/* Switch to SECTION (an `enum in_section').
+
+ ??? This facility should be provided by GCC proper.
+ The problem is that we want to temporarily switch sections in
+ ASM_DECLARE_OBJECT_NAME and then switch back to the original section
+ afterwards. */
+#define SWITCH_TO_SECTION_FUNCTION \
+void \
+switch_to_section (section, decl) \
+ enum in_section section; \
+ tree decl; \
+{ \
+ switch (section) \
+ { \
+ case in_text: text_section (); break; \
+ case in_data: data_section (); break; \
+ case in_named: named_section (decl, NULL, 0); break; \
+ case in_ctor: ctor_section (); break; \
+ case in_dtor: dtor_section (); break; \
+ case in_drectve: drectve_section (); break; \
+ default: abort (); break; \
+ } \
+}
+
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctor_section (); \
+ fprintf (FILE, "%s\t", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtor_section (); \
+ fprintf (FILE, "%s\t", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* Don't allow flag_pic to propagate since gas may produce invalid code
+ otherwise. */
+
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS \
+do { \
+ if (flag_pic) \
+ { \
+ warning ("-f%s ignored for target (all code is position independent)",\
+ (flag_pic > 1) ? "PIC" : "pic"); \
+ flag_pic = 0; \
+ } \
+} while (0) \
+
+/* Define this macro if references to a symbol must be treated
+ differently depending on something about the variable or
+ function named by the symbol (such as what section it is in).
+
+ On i386 running Windows NT, modify the assembler name with a suffix
+ consisting of an atsign (@) followed by string of digits that represents
+ the number of bytes of arguments passed to the function, if it has the
+ attribute STDCALL.
+
+ In addition, we must mark dll symbols specially. Definitions of
+ dllexport'd objects install some info in the .drectve section.
+ References to dllimport'd objects are fetched indirectly via
+ _imp__. If both are declared, dllexport overrides. This is also
+ needed to implement one-only vtables: they go into their own
+ section and we need to set DECL_SECTION_NAME so we do that here.
+ Note that we can be called twice on the same decl. */
+
+extern void i386_pe_encode_section_info ();
+
+#ifdef ENCODE_SECTION_INFO
+#undef ENCODE_SECTION_INFO
+#endif
+#define ENCODE_SECTION_INFO(DECL) i386_pe_encode_section_info (DECL)
+
+/* Utility used only in this file. */
+#define I386_PE_STRIP_ENCODING(SYM_NAME) \
+ ((SYM_NAME) + ((SYM_NAME)[0] == '@' ? 3 : 0))
+
+/* This macro gets just the user-specified name
+ out of the string in a SYMBOL_REF. Discard
+ trailing @[NUM] encoded by ENCODE_SECTION_INFO. */
+#undef STRIP_NAME_ENCODING
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+do { \
+ char *_p; \
+ char *_name = I386_PE_STRIP_ENCODING (SYMBOL_NAME); \
+ for (_p = _name; *_p && *_p != '@'; ++_p) \
+ ; \
+ if (*_p == '@') \
+ { \
+ int _len = _p - _name; \
+ (VAR) = (char *) alloca (_len + 1); \
+ strncpy ((VAR), _name, _len); \
+ (VAR)[_len] = '\0'; \
+ } \
+ else \
+ (VAR) = _name; \
+} while (0)
+
+
+/* Output a reference to a label. */
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+ fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, \
+ I386_PE_STRIP_ENCODING (NAME)) \
+
+/* Output a common block. */
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
+do { \
+ if (i386_pe_dllexport_name_p (NAME)) \
+ i386_pe_record_exported_symbol (NAME); \
+ if (! i386_pe_dllimport_name_p (NAME)) \
+ { \
+ fprintf ((STREAM), "\t.comm\t"); \
+ assemble_name ((STREAM), (NAME)); \
+ fprintf ((STREAM), ", %d\t%s %d\n", \
+ (ROUNDED), ASM_COMMENT_START, (SIZE)); \
+ } \
+} while (0)
+
+/* Output the label for an initialized variable. */
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
+do { \
+ if (i386_pe_dllexport_name_p (NAME)) \
+ i386_pe_record_exported_symbol (NAME); \
+ ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
+} while (0)
+
+
+/* Emit code to check the stack when allocating more that 4000
+ bytes in one go. */
+
+#define CHECK_STACK_LIMIT 4000
+
+/* By default, target has a 80387, uses IEEE compatible arithmetic,
+ and returns float values in the 387 and needs stack probes */
+#undef TARGET_DEFAULT
+
+#define TARGET_DEFAULT \
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+
+/* Define this macro if in some cases global symbols from one translation
+ unit may not be bound to undefined symbols in another translation unit
+ without user intervention. For instance, under Microsoft Windows
+ symbols must be explicitly imported from shared libraries (DLLs). */
+#define MULTIPLE_SYMBOL_SPACES
+
+#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL)
+extern void i386_pe_unique_section ();
+#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
+
+#define SUPPORTS_ONE_ONLY 1
+
+/* A C statement to output something to the assembler file to switch to section
+ NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
+ NULL_TREE. Some target formats do not support arbitrary sections. Do not
+ define this macro in such cases. */
+#undef ASM_OUTPUT_SECTION_NAME
+#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
+do { \
+ static struct section_info \
+ { \
+ struct section_info *next; \
+ char *name; \
+ enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \
+ } *sections; \
+ struct section_info *s; \
+ char *mode; \
+ enum sect_enum type; \
+ \
+ for (s = sections; s; s = s->next) \
+ if (!strcmp (NAME, s->name)) \
+ break; \
+ \
+ if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
+ type = SECT_EXEC, mode = "x"; \
+ else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
+ type = SECT_RO, mode = ""; \
+ else \
+ type = SECT_RW, mode = "w"; \
+ \
+ if (s == 0) \
+ { \
+ s = (struct section_info *) xmalloc (sizeof (struct section_info)); \
+ s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \
+ strcpy (s->name, NAME); \
+ s->type = type; \
+ s->next = sections; \
+ sections = s; \
+ fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
+ /* Functions may have been compiled at various levels of \
+ optimization so we can't use `same_size' here. Instead, \
+ have the linker pick one. */ \
+ if ((DECL) && DECL_ONE_ONLY (DECL)) \
+ fprintf (STREAM, "\t.linkonce %s\n", \
+ TREE_CODE (DECL) == FUNCTION_DECL \
+ ? "discard" : "same_size"); \
+ } \
+ else \
+ { \
+ fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
+ } \
+} while (0)
+
+/* Write the extra assembler code needed to declare a function
+ properly. If we are generating SDB debugging information, this
+ will happen automatically, so we only need to handle other cases. */
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ if (i386_pe_dllexport_name_p (NAME)) \
+ i386_pe_record_exported_symbol (NAME); \
+ if (write_symbols != SDB_DEBUG) \
+ i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
+ while (0)
+
+/* Add an external function to the list of functions to be declared at
+ the end of the file. */
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+ do \
+ { \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ i386_pe_record_external_function (NAME); \
+ } \
+ while (0)
+
+/* Declare the type properly for any external libcall. */
+#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
+ i386_pe_declare_function_type (FILE, XSTR (FUN, 0), 1)
+
+/* Output function declarations at the end of the file. */
+#define ASM_FILE_END(FILE) \
+ i386_pe_asm_file_end (FILE)
+
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START " #"
+
+/* DWARF2 Unwinding doesn't work with exception handling yet. */
+#define DWARF2_UNWIND_INFO 0
+
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+#define SUBTARGET_PROLOGUE \
+ if (profile_flag \
+ && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),\
+ "main") == 0) \
+ { \
+ rtx xops[1]; \
+ xops[0] = gen_rtx_MEM (FUNCTION_MODE, \
+ gen_rtx (SYMBOL_REF, Pmode, "_monstartup")); \
+ if (do_rtl) \
+ emit_call_insn (gen_rtx (CALL, VOIDmode, xops[0], const0_rtx)); \
+ else \
+ output_asm_insn (AS1 (call,%P1), xops); \
+ }
+
+/* External function declarations. */
+
+#ifndef PROTO
+#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
+#define PROTO(ARGS) ARGS
+#else
+#define PROTO(ARGS) ()
+#endif
+#endif
+
+#ifdef BUFSIZ /* stdio.h has been included, ok to use FILE * */
+#define STDIO_PROTO(ARGS) PROTO(ARGS)
+#else
+#define STDIO_PROTO(ARGS) ()
+#endif
+
+extern void i386_pe_record_external_function PROTO((char *));
+extern void i386_pe_declare_function_type STDIO_PROTO((FILE *, char *, int));
+extern void i386_pe_record_exported_symbol PROTO((char *));
+extern void i386_pe_asm_file_end STDIO_PROTO((FILE *));
+
+/* For Win32 ABI compatibility */
+#undef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* No data type wants to be aligned rounder than this. */
+#undef BIGGEST_ALIGNMENT
+#define BIGGEST_ALIGNMENT 128
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#undef PCC_BITFIELDS_TYPE_MATTERS
+#define PCC_BITFIELDS_TYPE_MATTERS 0
+
+/* Enable alias attribute support. */
+#ifndef SET_ASM_OP
+#define SET_ASM_OP "\t.set"
+#endif
+
diff --git a/contrib/gcc/config/i386/dgux.c b/contrib/gcc/config/i386/dgux.c
index ff36135..638d1e0 100644
--- a/contrib/gcc/config/i386/dgux.c
+++ b/contrib/gcc/config/i386/dgux.c
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#include <time.h>
#include "i386/i386.c"
@@ -29,6 +30,7 @@ struct option
char *string;
int *variable;
int on_value;
+ char *description;
};
static int
diff --git a/contrib/gcc/config/i386/dgux.h b/contrib/gcc/config/i386/dgux.h
index dae050f..9e41d65 100644
--- a/contrib/gcc/config/i386/dgux.h
+++ b/contrib/gcc/config/i386/dgux.h
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* for now, we are just like the sysv4 version with a
few hacks
@@ -25,7 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "i386/sysv4.h"
#ifndef VERSION_INFO2
-#define VERSION_INFO2 "$Revision: 1.3 $"
+#define VERSION_INFO2 "$Revision: 1.6 $"
#endif
#ifndef VERSION_STRING
@@ -46,7 +47,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define MASK_NOLEGEND 0x20000000 /* Discard legend information */
#define MASK_EXTERNAL_LEGEND 0x10000000 /* Make external legends */
#define MASK_IDENTIFY_REVISION 0x08000000 /* Emit 'ident' to .s */
-#define MASK_WARN_PASS_STRUCT 0x04000000 /* Emit 'ident' to .s */
+#define MASK_WARN_PASS_STRUCT 0x04000000 /* Warn when structures are passed */
#define TARGET_STANDARD (target_flags & MASK_STANDARD)
#define TARGET_NOLEGEND (target_flags & MASK_NOLEGEND)
@@ -56,12 +57,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
- { "standard", MASK_STANDARD }, \
- { "legend", -MASK_NOLEGEND }, \
- { "no-legend", MASK_NOLEGEND }, \
- { "external-legend", MASK_EXTERNAL_LEGEND }, \
- { "identify-revision", MASK_IDENTIFY_REVISION }, \
- { "warn-passed-structs", MASK_WARN_PASS_STRUCT },
+ { "standard", MASK_STANDARD, "Retain standard MXDB information" }, \
+ { "legend", -MASK_NOLEGEND, "Retain legend information" }, \
+ { "no-legend", MASK_NOLEGEND, "" }, \
+ { "external-legend", MASK_EXTERNAL_LEGEND, "Generate external legend information" }, \
+ { "identify-revision", MASK_IDENTIFY_REVISION, "Emit identifying info in .s file" }, \
+ { "warn-passed-structs", MASK_WARN_PASS_STRUCT, "Warn when a function arg is a structure" },
#undef DWARF_DEBUGGING_INFO
#define DWARF_DEBUGGING_INFO
@@ -123,7 +124,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
do { \
extern int flag_signed_bitfields; \
flag_signed_bitfields = 0; \
- abort_helper (); \
optimization_options (LEVEL,SIZE); \
} while (0)
@@ -219,23 +219,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif /* CROSS_COMPILE */
-#if !defined (no_abort) || defined (CRT_BEGIN) || defined (CRT_END)
-#undef abort
-
-char insn; int insn_; char * file_; int line_;
-#define abort() \
- (insn_ = (int) insn, \
- file_ = __FILE__, \
- line_ = __LINE__, \
- fancy_abort ())
-#define abort_helper() \
- do { \
- extern void abort_aux (); \
- atexit (abort_aux); \
- } while (0)
-#define _abort_aux
-#endif /* no abort */
-
/* The maximum alignment which the object file format can support.
page alignment would seem to be enough */
#undef MAX_OFILE_ALIGNMENT
diff --git a/contrib/gcc/config/i386/djgpp-rtems.h b/contrib/gcc/config/i386/djgpp-rtems.h
new file mode 100644
index 0000000..b355cc5
--- /dev/null
+++ b/contrib/gcc/config/i386/djgpp-rtems.h
@@ -0,0 +1,41 @@
+/* Configuration for an i386 running RTEMS on top of MS-DOS with
+ DJGPP v2.x.
+
+ Copyright (C) 1996,1999 Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel@OARcorp.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "i386/djgpp.h"
+
+/* Specify predefined symbols in preprocessor. */
+
+#ifdef CPP_PREDEFINES
+#undef CPP_PREDEFINES
+#endif
+#define CPP_PREDEFINES "-Dunix -Di386 -DGO32 -DDJGPP=2 -DMSDOS \
+ -Asystem(unix) -Asystem(msdos) -Acpu(i386) -Amachine(i386) \
+ -Asystem(rtems)"
+
+/* Generate calls to memcpy, memcmp and memset. */
+#ifndef TARGET_MEM_FUNCTIONS
+#define TARGET_MEM_FUNCTIONS
+#endif
+
+/* end of i386/djgpp-rtems.h */
+
diff --git a/contrib/gcc/config/i386/djgpp.h b/contrib/gcc/config/i386/djgpp.h
new file mode 100644
index 0000000..5727b0a
--- /dev/null
+++ b/contrib/gcc/config/i386/djgpp.h
@@ -0,0 +1,161 @@
+/* Configuration for an i386 running MS-DOS with DJGPP.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#include "dbxcoff.h"
+
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+#define HANDLE_SYSV_PRAGMA
+
+/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
+#define HANDLE_PRAGMA_PACK_PUSH_POP 1
+
+#define YES_UNDERSCORES
+
+#include "i386/gas.h"
+
+/* Enable alias attribute support. */
+#ifndef SET_ASM_OP
+#define SET_ASM_OP "\t.set"
+#endif
+
+/* Search for as.exe and ld.exe in DJGPP's binary directory. */
+#define MD_EXEC_PREFIX "$DJDIR/bin/"
+
+/* Correctly handle absolute filename detection in cp/xref.c */
+#define FILE_NAME_ABSOLUTE_P(NAME) \
+ (((NAME)[0] == '/') || ((NAME)[0] == '\\') || \
+ (((NAME)[0] >= 'A') && ((NAME)[0] <= 'z') && ((NAME)[1] == ':')))
+
+#ifdef CPP_PREDEFINES
+#undef CPP_PREDEFINES
+#endif
+#define CPP_PREDEFINES "-Dunix -Di386 -DGO32 -DDJGPP=2 -DMSDOS \
+ -Asystem(unix) -Asystem(msdos) -Acpu(i386) -Amachine(i386)"
+
+/* We need to override link_command_spec in gcc.c so support -Tdjgpp.djl.
+ This cannot be done in LINK_SPECS as that LINK_SPECS is processed
+ before library search directories are known by the linker.
+ This avoids problems when specs file is not available. An alternate way,
+ suggested by Robert Hoehne, is to use SUBTARGET_EXTRA_SPECS instead.
+*/
+
+#undef LINK_COMMAND_SPEC
+#define LINK_COMMAND_SPEC \
+"%{!fsyntax-only: \
+%{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
+\t%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
+\t%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
+\t%{static:} %{L*} %D %o\
+\t%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
+\t%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
+\t-Tdjgpp.djl %{T*}}}}}}}\n\
+%{!c:%{!M:%{!MM:%{!E:%{!S:stubify %{v} %{o*:%*} %{!o*:a.out} }}}}}"
+
+/* Always just link in 'libc.a'. */
+#undef LIB_SPEC
+#define LIB_SPEC "-lc"
+
+/* Pick the right startup code depending on the -pg flag. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:crt0.o%s}"
+
+/* Make sure that gcc will not look for .h files in /usr/local/include
+ unless user explicitly requests it. */
+#undef LOCAL_INCLUDE_DIR
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_ctor, in_dtor
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CTOR_SECTION_FUNCTION \
+ DTOR_SECTION_FUNCTION
+
+#define CTOR_SECTION_FUNCTION \
+void \
+ctor_section () \
+{ \
+ if (in_section != in_ctor) \
+ { \
+ fprintf (asm_out_file, "\t.section .ctor\n"); \
+ in_section = in_ctor; \
+ } \
+}
+
+#define DTOR_SECTION_FUNCTION \
+void \
+dtor_section () \
+{ \
+ if (in_section != in_dtor) \
+ { \
+ fprintf (asm_out_file, "\t.section .dtor\n"); \
+ in_section = in_dtor; \
+ } \
+}
+
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctor_section (); \
+ fprintf (FILE, "%s\t", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* Allow (eg) __attribute__((section "locked")) to work */
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC)\
+ do { \
+ fprintf (FILE, "\t.section %s\n", NAME); \
+ } while (0)
+
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtor_section (); \
+ fprintf (FILE, "%s\t", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* Output at beginning of assembler file. */
+/* The .file command should always begin the output. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ do { \
+ output_file_directive (FILE, main_input_filename); \
+ } while (0)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) fprintf ((FILE), "\t.p2align %d\n", LOG)
+
+/* djgpp has atexit (). */
+#undef HAVE_ATEXIT
+#define HAVE_ATEXIT
+
+/* djgpp automatically calls its own version of __main, so don't define one
+ in libgcc, nor call one in main(). */
+#define HAS_INIT_SECTION
diff --git a/contrib/gcc/config/i386/freebsd-elf.h b/contrib/gcc/config/i386/freebsd-elf.h
index 0a556fe..e97d4ca 100644
--- a/contrib/gcc/config/i386/freebsd-elf.h
+++ b/contrib/gcc/config/i386/freebsd-elf.h
@@ -3,6 +3,7 @@
Contributed by Eric Youngdale.
Modified for stabs-in-ELF by H.J. Lu.
Adapted from GNU/Linux version by John Polstra.
+ Continued development by David O'Brien <obrien@freebsd.org>
This file is part of GNU CC.
@@ -34,6 +35,23 @@ Boston, MA 02111-1307, USA. */
libraries compiled with the native cc, so undef it. */
#undef NO_DOLLAR_IN_LABEL
+/* Use more efficient ``thunks'' to implement C++ vtables. */
+#undef DEFAULT_VTABLE_THUNKS
+#define DEFAULT_VTABLE_THUNKS 1
+
+/* Override the default comment-starter of "/". */
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START "#"
+
+#undef ASM_APP_ON
+#define ASM_APP_ON "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF "#NO_APP\n"
+
+#undef SET_ASM_OP
+#define SET_ASM_OP ".set"
+
/* This is how to output an element of a case-vector that is relative.
This is only used for PIC code. See comments by the `casesi' insn in
i386.md for an explanation of the expression this outputs. */
@@ -45,6 +63,10 @@ Boston, MA 02111-1307, USA. */
necessary when compiling PIC code. */
#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
+/* Use stabs instead of DWARF debug format. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
/* Copy this from the svr4 specifications... */
/* Define the register numbers to be used in Dwarf debugging information.
The SVR4 reference port C compiler uses the following register numbers
@@ -113,23 +135,15 @@ Boston, MA 02111-1307, USA. */
: ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \
: (-1))
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
+/* Tell final.c that we don't need a label passed to mcount. */
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE, LABELNO) \
{ \
if (flag_pic) \
- { \
- fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \
- LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \
- } \
+ fprintf (FILE, "\tcall *.mcount@GOT(%%ebx)\n"); \
else \
- { \
- fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall mcount\n"); \
- } \
+ fprintf (FILE, "\tcall .mcount\n"); \
}
#undef SIZE_TYPE
@@ -140,6 +154,9 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE
#define WCHAR_TYPE "int"
+
+#undef WCHAR_UNSIGNED
+#define WCHAR_UNSIGNED 0
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
@@ -150,21 +167,53 @@ Boston, MA 02111-1307, USA. */
#undef CPP_SPEC
#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
-#undef LIB_SPEC
-#if 1
-/* We no longer link with libc_p.a or libg.a by default. If you
- * want to profile or debug the C library, please add
- * -lc_p or -ggdb to LDFLAGS at the link time, respectively.
- */
-#define LIB_SPEC \
- "%{!shared: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \
- %{!ggdb:-lc} %{ggdb:-lg}}"
-#else
-#define LIB_SPEC \
+/* This defines which switch letters take arguments. On FreeBSD, most of
+ the normal cases (defined in gcc.c) apply, and we also have -h* and
+ -z* options (for the linker) (comming from svr4).
+ We also have -R (alias --rpath), no -z, --soname (-h), --assert etc. */
+
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) \
+ || (CHAR) == 'h' \
+ || (CHAR) == 'z' \
+ || (CHAR) == 'R')
+
+/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add
+ the magical crtbegin.o file (see crtstuff.c) which provides part
+ of the support for getting C++ file-scope static object constructed
+ before entering `main'. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
"%{!shared: \
- %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \
- %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}"
-#endif
+ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
+ %{!p:%{profile:gcrt1.o%s} \
+ %{!profile:crt1.o%s}}}} \
+ crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+
+/* Provide a ENDFILE_SPEC appropriate for FreeBSD. Here we tack on
+ the magical crtend.o file (see crtstuff.c) which provides part of
+ the support for getting C++ file-scope static object constructed
+ before entering `main', followed by a normal "finalizer" file,
+ `crtn.o'. */
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+
+/* Provide a LIB_SPEC appropriate for FreeBSD. Just select the appropriate
+ libc, depending on whether we're doing profiling or need threads support.
+ (simular to the default, except no -lg, and no -p. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shared: \
+ %{!pg:%{!pthread:%{!kthread:-lc} \
+ %{kthread:-lpthread -lc}} \
+ %{pthread:-lc_r}} \
+ %{pg:%{!pthread:%{!kthread:-lc_p} \
+ %{kthread:-lpthread_p -lc_p}} \
+ %{pthread:-lc_r_p}}}"
/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support
for the special GCC options -static and -shared, which allow us to
@@ -181,15 +230,17 @@ Boston, MA 02111-1307, USA. */
done. */
#undef LINK_SPEC
-#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
- %{!shared: \
- %{!ibcs: \
+#define LINK_SPEC "-m elf_i386 \
+ %{Wl,*:%*} \
+ %{v:-V} \
+ %{assert*} %{R*} %{rpath*} %{defsym*} \
+ %{shared:-Bshareable %{h*} %{soname*}} \
+ %{!shared: \
%{!static: \
- %{rdynamic:-export-dynamic} \
+ %{rdynamic:-export-dynamic} \
%{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \
- %{static:-static}}}"
-
-/* Get perform_* macros to build libgcc.a. */
+ %{static:-Bstatic}} \
+ %{symbolic:-Bsymbolic}"
/* A C statement to output to the stdio stream FILE an assembler
command to advance the location counter to a multiple of 1<<LOG
@@ -199,7 +250,8 @@ Boston, MA 02111-1307, USA. */
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
- if ((LOG)!=0) \
- if ((MAX_SKIP)==0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
- else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP))
+ if ((LOG) != 0) {\
+ if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ }
#endif
diff --git a/contrib/gcc/config/i386/gas.h b/contrib/gcc/config/i386/gas.h
index 173bf19..4ce1891 100644
--- a/contrib/gcc/config/i386/gas.h
+++ b/contrib/gcc/config/i386/gas.h
@@ -94,9 +94,10 @@ Boston, MA 02111-1307, USA. */
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
# define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
- if ((LOG)!=0) \
- if ((MAX_SKIP)==0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
- else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP))
+ if ((LOG) != 0) {\
+ if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ }
#endif
/* A C statement or statements which output an assembler instruction
diff --git a/contrib/gcc/config/i386/gnu.h b/contrib/gcc/config/i386/gnu.h
index 971a5f8..cd32b92 100644
--- a/contrib/gcc/config/i386/gnu.h
+++ b/contrib/gcc/config/i386/gnu.h
@@ -3,13 +3,24 @@
/* This does it mostly for us. */
#include <i386/linux.h>
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Di386 -Acpu(i386) -Amachine(i386) \
--Dunix -Asystem(unix) -DMACH -Asystem(mach) -D__GNU__ -Asystem(gnu)"
+/* Get machine-independent configuration parameters for the GNU system. */
+#include <gnu.h>
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 GNU)");
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__ELF__ -D__i386__ -DMACH -Asystem(mach) \
+ -Dunix -Asystem(unix) -Asystem(posix) -D__GNU__ -Asystem(gnu)"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%(cpp_cpu) \
+ %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} \
+ %{posix:-D_POSIX_SOURCE} %{bsd:-D_BSD_SOURCE}"
+
+#undef CC1_SPEC
+#define CC1_SPEC "%(cc1_cpu)"
+
#undef LINK_SPEC
#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
%{!shared: \
@@ -18,6 +29,10 @@
%{!dynamic-linker:-dynamic-linker /lib/ld.so}} \
%{static:-static}}"
-
-/* Get machine-independent configuration parameters for the GNU system. */
-#include <gnu.h>
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: \
+ %{!static: \
+ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \
+ %{static:crt0.o%s}} \
+ crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
diff --git a/contrib/gcc/config/i386/i386-coff.h b/contrib/gcc/config/i386/i386-coff.h
index 915e307..2e00b7a 100644
--- a/contrib/gcc/config/i386/i386-coff.h
+++ b/contrib/gcc/config/i386/i386-coff.h
@@ -22,14 +22,20 @@ Boston, MA 02111-1307, USA. */
#include "i386/gas.h"
+#include "dbxcoff.h"
/* Specify predefined symbols in preprocessor. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Di386"
+/* We want to be able to get DBX debugging information via -gstabs. */
+
#undef DBX_DEBUGGING_INFO
-#define SDB_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO
+
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
/* Support the ctors and dtors sections for g++. */
diff --git a/contrib/gcc/config/i386/i386-interix.h b/contrib/gcc/config/i386/i386-interix.h
new file mode 100644
index 0000000..8e9f443
--- /dev/null
+++ b/contrib/gcc/config/i386/i386-interix.h
@@ -0,0 +1,575 @@
+/* Target definitions for GNU compiler for Intel 80386 running Interix
+ Parts Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+
+ Parts:
+ by Douglas B. Rupp (drupp@cs.washington.edu).
+ by Ron Guilmette (rfg@netcom.com).
+ by Donn Terry (donn@softway.com).
+ by Mumit Khan (khan@xraylith.wisc.edu).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define YES_UNDERSCORES
+
+/* YES_UNDERSCORES must preceed gas.h */
+#include <i386/gas.h>
+/* The rest must follow. */
+
+#define DBX_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#define HANDLE_SYSV_PRAGMA
+#undef HANDLE_PRAGMA_WEAK /* until the link format can handle it */
+
+/* By default, target has a 80387, uses IEEE compatible arithmetic,
+ and returns float values in the 387 and needs stack probes
+ We also align doubles to 64-bits for MSVC default compatability */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE | \
+ MASK_ALIGN_DOUBLE)
+
+#undef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT 2 /* 486 */
+
+#define WCHAR_UNSIGNED 1
+#define WCHAR_TYPE_SIZE 16
+#define WCHAR_TYPE "short unsigned int"
+
+/* WinNT (and thus Interix) use unsigned int */
+#define SIZE_TYPE "unsigned int"
+
+#define ASM_LOAD_ADDR(loc, reg) " leal " #loc "," #reg "\n"
+
+/* For the sake of libgcc2.c, indicate target supports atexit. */
+#define HAVE_ATEXIT
+
+/* cpp handles __STDC__ */
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES " \
+ -D__INTERIX \
+ -D__OPENNT \
+ -D_M_IX86=300 -D_X86_=1 \
+ -D__stdcall=__attribute__((__stdcall__)) \
+ -D__cdecl=__attribute__((__cdecl__)) \
+ -Asystem(unix) -Asystem(interix) -Asystem(interix) -Acpu(i386) -Amachine(i386)"
+
+#undef CPP_SPEC
+/* Write out the correct language type definition for the header files.
+ Unless we have assembler language, write out the symbols for C.
+ cpp_cpu is an Intel specific variant. See i386.h
+ mieee is an Alpha specific variant. Cross polination a bad idea.
+ */
+#define CPP_SPEC "\
+%{!.S: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \
+%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
+%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
+%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
+%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
+%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
+-remap \
+%(cpp_cpu) \
+%{posix:-D_POSIX_SOURCE} \
+-idirafter %$INTERIX_ROOT/usr/include"
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (i386 Interix)");
+
+/* The global __fltused is necessary to cause the printf/scanf routines
+ for outputting/inputting floating point numbers to be loaded. Since this
+ is kind of hard to detect, we just do it all the time. */
+
+#ifdef ASM_FILE_START
+#undef ASM_FILE_START
+#endif
+#define ASM_FILE_START(FILE) \
+ do { fprintf (FILE, "\t.file\t"); \
+ output_quoted_string (FILE, dump_base_name); \
+ fprintf (FILE, "\n"); \
+ fprintf (FILE, ".global\t__fltused\n"); \
+ } while (0)
+
+/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
+ ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
+ corresponds to a particular byte value [0..255]. For any
+ given byte value, if the value in the corresponding table
+ position is zero, the given character can be output directly.
+ If the table value is 1, the byte must be output as a \ooo
+ octal escape. If the tables value is anything else, then the
+ byte value should be output as a \ followed by the value
+ in the table. Note that we can use standard UN*X escape
+ sequences for many control characters, but we don't use
+ \a to represent BEL because some svr4 assemblers (e.g. on
+ the i386) don't know about that. Also, we don't use \v
+ since some versions of gas, such as 2.2 did not accept it. */
+
+#define ESCAPES \
+"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
+
+/* Some svr4 assemblers have a limit on the number of characters which
+ can appear in the operand of a .string directive. If your assembler
+ has such a limitation, you should define STRING_LIMIT to reflect that
+ limit. Note that at least some svr4 assemblers have a limit on the
+ actual number of bytes in the double-quoted string, and that they
+ count each character in an escape sequence as one byte. Thus, an
+ escape sequence like \377 would count as four bytes.
+
+ If your target assembler doesn't support the .string directive, you
+ should define this to zero.
+*/
+
+#define STRING_LIMIT ((unsigned) 256)
+
+#define STRING_ASM_OP ".string"
+
+/* The routine used to output NUL terminated strings. We use a special
+ version of this for most svr4 targets because doing so makes the
+ generated assembly code more compact (and thus faster to assemble)
+ as well as more readable, especially for targets like the i386
+ (where the only alternative is to output character sequences as
+ comma separated lists of numbers). */
+
+#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
+ do \
+ { \
+ register unsigned char *_limited_str = (unsigned char *) (STR); \
+ register unsigned ch; \
+ fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \
+ for (; (ch = *_limited_str); _limited_str++) \
+ { \
+ register int escape = ESCAPES[ch]; \
+ switch (escape) \
+ { \
+ case 0: \
+ putc (ch, (FILE)); \
+ break; \
+ case 1: \
+ fprintf ((FILE), "\\%03o", ch); \
+ break; \
+ default: \
+ putc ('\\', (FILE)); \
+ putc (escape, (FILE)); \
+ break; \
+ } \
+ } \
+ fprintf ((FILE), "\"\n"); \
+ } \
+ while (0)
+
+/* The routine used to output sequences of byte values. We use a special
+ version of this for most svr4 targets because doing so makes the
+ generated assembly code more compact (and thus faster to assemble)
+ as well as more readable. Note that if we find subparts of the
+ character sequence which end with NUL (and which are shorter than
+ STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
+ do \
+ { \
+ register unsigned char *_ascii_bytes = (unsigned char *) (STR); \
+ register unsigned char *limit = _ascii_bytes + (LENGTH); \
+ register unsigned bytes_in_chunk = 0; \
+ for (; _ascii_bytes < limit; _ascii_bytes++) \
+ { \
+ register unsigned char *p; \
+ if (bytes_in_chunk >= 64) \
+ { \
+ fputc ('\n', (FILE)); \
+ bytes_in_chunk = 0; \
+ } \
+ for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
+ continue; \
+ if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \
+ { \
+ if (bytes_in_chunk > 0) \
+ { \
+ fputc ('\n', (FILE)); \
+ bytes_in_chunk = 0; \
+ } \
+ ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \
+ _ascii_bytes = p; \
+ } \
+ else \
+ { \
+ if (bytes_in_chunk == 0) \
+ fprintf ((FILE), "\t.byte\t"); \
+ else \
+ fputc (',', (FILE)); \
+ fprintf ((FILE), "0x%02x", *_ascii_bytes); \
+ bytes_in_chunk += 5; \
+ } \
+ } \
+ if (bytes_in_chunk > 0) \
+ fprintf ((FILE), "\n"); \
+ } \
+ while (0)
+
+/* This is how to output an element of a case-vector that is relative.
+ This is only used for PIC code. See comments by the `casesi' insn in
+ i386.md for an explanation of the expression this outputs.
+ PE format differs on what PC-relative offsets look like (see
+ coff_i386_rtype_to_howto), and we need to compensate (by one word) here. */
+
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ fprintf (FILE, "\t.long __GLOBAL_OFFSET_TABLE_+[.-%s%d+4]\n", LPREFIX, VALUE)
+
+/* Indicate that jump tables go in the text section. This is
+ necessary when compiling PIC code. */
+
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Emit code to check the stack when allocating more that 4000
+ bytes in one go. */
+
+#define CHECK_STACK_LIMIT 0x1000
+
+/* the following are OSF linker (not gld) specific... we don't want them */
+#undef HAS_INIT_SECTION
+#undef LD_INIT_SWITCH
+#undef LD_FINI_SWITCH
+
+
+/* The following are needed for C++, but also needed for profiling */
+
+/* Support const sections and the ctors and dtors sections for g++.
+ Note that there appears to be two different ways to support const
+ sections at the moment. You can either #define the symbol
+ READONLY_DATA_SECTION (giving it some code which switches to the
+ readonly data section) or else you can #define the symbols
+ EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
+ SELECT_RTX_SECTION. We do both here just to be on the safe side. */
+
+#define USE_CONST_SECTION 1
+
+#define CONST_SECTION_ASM_OP ".section\t.rdata,\"r\""
+
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+
+ Note that we want to give these sections the SHF_WRITE attribute
+ because these sections will actually contain data (i.e. tables of
+ addresses of functions in the current root executable or shared library
+ file) and, in the case of a shared library, the relocatable addresses
+ will have to be properly resolved/relocated (and then written into) by
+ the dynamic linker when it actually attaches the given shared library
+ to the executing process. (Note that on SVR4, you may wish to use the
+ `-z text' option to the ELF linker, when building a shared library, as
+ an additional check that you are doing everything right. But if you do
+ use the `-z text' option when building a shared library, you will get
+ errors unless the .ctors and .dtors sections are marked as writable
+ via the SHF_WRITE attribute.) */
+
+#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\""
+#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"x\""
+
+/* A default list of other sections which we might be "in" at any given
+ time. For targets that use additional sections (e.g. .tdesc) you
+ should override this definition in the target-specific file which
+ includes this file. */
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
+
+/* A default list of extra section function definitions. For targets
+ that use additional sections (e.g. .tdesc) you should override this
+ definition in the target-specific file which includes this file. */
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CONST_SECTION_FUNCTION \
+ CTORS_SECTION_FUNCTION \
+ DTORS_SECTION_FUNCTION
+
+#undef READONLY_DATA_SECTION
+#define READONLY_DATA_SECTION() const_section ()
+
+extern void text_section ();
+
+#define CONST_SECTION_FUNCTION \
+void \
+const_section () \
+{ \
+ if (!USE_CONST_SECTION) \
+ text_section(); \
+ else if (in_section != in_const) \
+ { \
+ fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
+ in_section = in_const; \
+ } \
+}
+
+#define CTORS_SECTION_FUNCTION \
+void \
+ctors_section () \
+{ \
+ if (in_section != in_ctors) \
+ { \
+ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
+ in_section = in_ctors; \
+ } \
+}
+
+#define DTORS_SECTION_FUNCTION \
+void \
+dtors_section () \
+{ \
+ if (in_section != in_dtors) \
+ { \
+ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
+ in_section = in_dtors; \
+ } \
+}
+
+#if 0
+/* Currently gas chokes on this; that's not too hard to fix, but there's
+ not a lot of impeteus to do it, either. If it is done, gas will have
+ to handle long section name escapes (which are defined in the COFF/PE
+ document as /nnn where nnn is a string table index). The benefit:
+ section attributes and -ffunction-sections, neither of which seem to
+ be critical. */
+/* gas may have been fixed? bfd was. */
+
+/* Switch into a generic section.
+ This is currently only used to support section attributes.
+
+ We make the section read-only and executable for a function decl,
+ read-only for a const data decl, and writable for a non-const data decl. */
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+ fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \
+ (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \
+ (DECL) && TREE_READONLY (DECL) ? "a" : "aw")
+#endif
+
+#define INT_ASM_OP ".long"
+
+/* The MS compilers take alignment as a number of bytes, so we do as well */
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG))
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global constructors. */
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global destructors. */
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* The linker will take care of this, and having them causes problems with
+ ld -r (specifically -rU). */
+#define CTOR_LISTS_DEFINED_EXTERNALLY 1
+
+#define SET_ASM_OP ".set"
+/* Output a definition (implements alias) */
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+do \
+{ \
+ fprintf ((FILE), "\t%s\t", SET_ASM_OP); \
+ assemble_name (FILE, LABEL1); \
+ fprintf (FILE, ","); \
+ assemble_name (FILE, LABEL2); \
+ fprintf (FILE, "\n"); \
+ } \
+while (0)
+
+#define HOST_PTR_PRINTF "%p"
+#define HOST_PTR_AS_INT unsigned long
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+#define PCC_BITFIELD_TYPE_TEST TYPE_NATIVE(rec)
+#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
+
+/* The following two flags are usually "off" for i386, because some non-gnu
+ tools (for the i386) don't handle them. However, we don't have that
+ problem, so.... */
+
+/* Forward references to tags are allowed. */
+#define SDB_ALLOW_FORWARD_REFERENCES
+
+/* Unknown tags are also allowed. */
+#define SDB_ALLOW_UNKNOWN_REFERENCES
+
+/* The integer half of this list needs to be constant. However, there's
+ a lot of disagreement about what the floating point adjustments should
+ be. We pick one that works with gdb. (The underlying problem is
+ what to do about the segment registers. Since we have access to them
+ from /proc, we'll allow them to be accessed in gdb, even tho the
+ gcc compiler can't generate them. (There's some evidence that
+ MSVC does, but possibly only for certain special "canned" sequences.) */
+
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) \
+((n) == 0 ? 0 \
+ : (n) == 1 ? 2 \
+ : (n) == 2 ? 1 \
+ : (n) == 3 ? 3 \
+ : (n) == 4 ? 6 \
+ : (n) == 5 ? 7 \
+ : (n) == 6 ? 5 \
+ : (n) == 7 ? 4 \
+ : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+8 \
+ : (-1))
+
+/* Define this macro if references to a symbol must be treated
+ differently depending on something about the variable or
+ function named by the symbol (such as what section it is in).
+
+ Apply stddef, handle (as yet unimplemented) pic.
+
+ stddef renaming does NOT apply to Alpha. */
+
+char *gen_stdcall_suffix ();
+
+#undef ENCODE_SECTION_INFO
+#define ENCODE_SECTION_INFO(DECL) \
+do \
+ { \
+ if (flag_pic) \
+ { \
+ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
+ = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ || ! TREE_PUBLIC (DECL)); \
+ } \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ if (lookup_attribute ("stdcall", \
+ TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \
+ XEXP (DECL_RTL (DECL), 0) = \
+ gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (DECL)); \
+ } \
+while (0)
+
+/* This macro gets just the user-specified name
+ out of the string in a SYMBOL_REF. Discard
+ trailing @[NUM] encoded by ENCODE_SECTION_INFO. */
+#undef STRIP_NAME_ENCODING
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+do { \
+ char *_p; \
+ char *_name = SYMBOL_NAME; \
+ for (_p = _name; *_p && *_p != '@'; ++_p) \
+ ; \
+ if (*_p == '@') \
+ { \
+ int _len = _p - _name; \
+ (VAR) = (char *) alloca (_len + 1); \
+ strncpy ((VAR), _name, _len); \
+ (VAR)[_len] = '\0'; \
+ } \
+ else \
+ (VAR) = _name; \
+} while (0)
+
+#if 0
+/* Turn this back on when the linker is updated to handle grouped
+ .data$ sections correctly. See corresponding note in i386/interix.c.
+ MK. */
+
+/* Define this macro if in some cases global symbols from one translation
+ unit may not be bound to undefined symbols in another translation unit
+ without user intervention. For instance, under Microsoft Windows
+ symbols must be explicitly imported from shared libraries (DLLs). */
+#define MULTIPLE_SYMBOL_SPACES
+
+#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL)
+extern void i386_pe_unique_section ();
+#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
+
+#define SUPPORTS_ONE_ONLY 1
+
+/* A C statement to output something to the assembler file to switch to section
+ NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
+ NULL_TREE. Some target formats do not support arbitrary sections. Do not
+ define this macro in such cases. */
+#undef ASM_OUTPUT_SECTION_NAME
+#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
+do { \
+ static struct section_info \
+ { \
+ struct section_info *next; \
+ char *name; \
+ enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \
+ } *sections; \
+ struct section_info *s; \
+ char *mode; \
+ enum sect_enum type; \
+ \
+ for (s = sections; s; s = s->next) \
+ if (!strcmp (NAME, s->name)) \
+ break; \
+ \
+ if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
+ type = SECT_EXEC, mode = "x"; \
+ else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
+ type = SECT_RO, mode = "r"; \
+ else \
+ type = SECT_RW, mode = "w"; \
+ \
+ if (s == 0) \
+ { \
+ s = (struct section_info *) xmalloc (sizeof (struct section_info)); \
+ s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \
+ strcpy (s->name, NAME); \
+ s->type = type; \
+ s->next = sections; \
+ sections = s; \
+ fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
+ /* Functions may have been compiled at various levels of \
+ optimization so we can't use `same_size' here. Instead, \
+ have the linker pick one. */ \
+ if ((DECL) && DECL_ONE_ONLY (DECL)) \
+ fprintf (STREAM, "\t.linkonce %s\n", \
+ TREE_CODE (DECL) == FUNCTION_DECL \
+ ? "discard" : "same_size"); \
+ } \
+ else \
+ { \
+ fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
+ } \
+} while (0)
+
+#endif /* 0 */
+
+/* DWARF2 Unwinding doesn't work with exception handling yet. */
+#define DWARF2_UNWIND_INFO 0
+
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
diff --git a/contrib/gcc/config/i386/i386.c b/contrib/gcc/config/i386/i386.c
index b2512a0..3efedb6 100644
--- a/contrib/gcc/config/i386/i386.c
+++ b/contrib/gcc/config/i386/i386.c
@@ -100,8 +100,42 @@ struct processor_costs pentiumpro_cost = {
17 /* cost of a divide/mod */
};
+/* We use decoding time together with execution time.
+ To get correct vale add 1 for short decodable, 2 for long decodable
+ and 4 for vector decodable instruction to execution time and divide
+ by two (because CPU is able to do two insns at a time). */
+
+struct processor_costs k6_cost = {
+ 1, /* cost of an add instruction */
+ 1, /* cost of a lea instruction */
+ 1, /* variable shift costs */
+ 1, /* constant shift costs */
+ 3, /* cost of starting a multiply */
+ 0, /* cost of multiply per each bit set */
+ 20 /* cost of a divide/mod */
+};
+
struct processor_costs *ix86_cost = &pentium_cost;
+/* Processor feature/optimization bitmasks. */
+#define m_386 (1<<PROCESSOR_I386)
+#define m_486 (1<<PROCESSOR_I486)
+#define m_PENT (1<<PROCESSOR_PENTIUM)
+#define m_PPRO (1<<PROCESSOR_PENTIUMPRO)
+#define m_K6 (1<<PROCESSOR_K6)
+
+const int x86_use_leave = m_386 | m_K6;
+const int x86_push_memory = m_386 | m_K6;
+const int x86_zero_extend_with_and = m_486 | m_PENT;
+const int x86_movx = m_386 | m_PPRO | m_K6;
+const int x86_double_with_add = ~(m_386 | m_PENT | m_PPRO);
+const int x86_use_bit_test = m_386;
+const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO;
+const int x86_use_q_reg = m_PENT | m_PPRO | m_K6;
+const int x86_use_any_reg = m_486;
+const int x86_cmove = m_PPRO;
+const int x86_deep_branch = m_PPRO| m_K6;
+
#define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx))
extern FILE *asm_out_file;
@@ -169,6 +203,12 @@ char *i386_align_loops_string;
/* Power of two alignment for non-loop jumps. */
char *i386_align_jumps_string;
+/* Power of two alignment for stack boundary in bytes. */
+char *i386_preferred_stack_boundary_string;
+
+/* Preferred alignment for stack boundary in bits. */
+int i386_preferred_stack_boundary;
+
/* Values 1-5: see jump.c */
int i386_branch_cost;
char *i386_branch_cost_string;
@@ -205,15 +245,16 @@ override_options ()
struct processor_costs *cost; /* Processor costs */
int target_enable; /* Target flags to enable. */
int target_disable; /* Target flags to disable. */
- } processor_target_table[]
- = {{PROCESSOR_I386_STRING, PROCESSOR_I386, &i386_cost, 0, 0},
- {PROCESSOR_I486_STRING, PROCESSOR_I486, &i486_cost, 0, 0},
- {PROCESSOR_I586_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0},
- {PROCESSOR_PENTIUM_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0},
- {PROCESSOR_I686_STRING, PROCESSOR_PENTIUMPRO, &pentiumpro_cost,
- 0, 0},
- {PROCESSOR_PENTIUMPRO_STRING, PROCESSOR_PENTIUMPRO,
- &pentiumpro_cost, 0, 0}};
+ } processor_target_table[] = {
+ {PROCESSOR_I386_STRING, PROCESSOR_I386, &i386_cost, 0, 0},
+ {PROCESSOR_I486_STRING, PROCESSOR_I486, &i486_cost, 0, 0},
+ {PROCESSOR_I586_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0},
+ {PROCESSOR_PENTIUM_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0},
+ {PROCESSOR_I686_STRING, PROCESSOR_PENTIUMPRO, &pentiumpro_cost, 0, 0},
+ {PROCESSOR_PENTIUMPRO_STRING, PROCESSOR_PENTIUMPRO,
+ &pentiumpro_cost, 0, 0},
+ {PROCESSOR_K6_STRING, PROCESSOR_K6, &k6_cost, 0, 0}
+ };
int ptt_size = sizeof (processor_target_table) / sizeof (struct ptt);
@@ -279,7 +320,7 @@ override_options ()
{
ix86_cpu = processor_target_table[j].processor;
ix86_cost = processor_target_table[j].cost;
- if (i > j && (int) ix86_arch >= (int) PROCESSOR_PENTIUMPRO)
+ if (i > j && (int) ix86_arch >= (int) PROCESSOR_K6)
error ("-mcpu=%s does not support -march=%s",
ix86_cpu_string, ix86_arch_string);
@@ -311,6 +352,11 @@ override_options ()
def_align = (TARGET_486) ? 4 : 2;
/* Validate -malign-loops= value, or provide default. */
+#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+ i386_align_loops = 4;
+#else
+ i386_align_loops = 2;
+#endif
if (i386_align_loops_string)
{
i386_align_loops = atoi (i386_align_loops_string);
@@ -318,14 +364,13 @@ override_options ()
fatal ("-malign-loops=%d is not between 0 and %d",
i386_align_loops, MAX_CODE_ALIGN);
}
- else
+
+ /* Validate -malign-jumps= value, or provide default. */
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
- i386_align_loops = 4;
+ i386_align_jumps = 4;
#else
- i386_align_loops = 2;
+ i386_align_jumps = def_align;
#endif
-
- /* Validate -malign-jumps= value, or provide default. */
if (i386_align_jumps_string)
{
i386_align_jumps = atoi (i386_align_jumps_string);
@@ -333,14 +378,9 @@ override_options ()
fatal ("-malign-jumps=%d is not between 0 and %d",
i386_align_jumps, MAX_CODE_ALIGN);
}
- else
-#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
- i386_align_jumps = 4;
-#else
- i386_align_jumps = def_align;
-#endif
/* Validate -malign-functions= value, or provide default. */
+ i386_align_funcs = def_align;
if (i386_align_funcs_string)
{
i386_align_funcs = atoi (i386_align_funcs_string);
@@ -348,19 +388,26 @@ override_options ()
fatal ("-malign-functions=%d is not between 0 and %d",
i386_align_funcs, MAX_CODE_ALIGN);
}
- else
- i386_align_funcs = def_align;
+
+ /* Validate -mpreferred_stack_boundary= value, or provide default.
+ The default of 128 bits is for Pentium III's SSE __m128. */
+ i386_preferred_stack_boundary = 128;
+ if (i386_preferred_stack_boundary_string)
+ {
+ i = atoi (i386_preferred_stack_boundary_string);
+ if (i < 2 || i > 31)
+ fatal ("-mpreferred_stack_boundary=%d is not between 2 and 31", i);
+ i386_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT;
+ }
/* Validate -mbranch-cost= value, or provide default. */
+ i386_branch_cost = 1;
if (i386_branch_cost_string)
{
i386_branch_cost = atoi (i386_branch_cost_string);
if (i386_branch_cost < 0 || i386_branch_cost > 5)
- fatal ("-mbranch-cost=%d is not between 0 and 5",
- i386_branch_cost);
+ fatal ("-mbranch-cost=%d is not between 0 and 5", i386_branch_cost);
}
- else
- i386_branch_cost = 1;
/* Keep nonleaf frame pointers. */
if (TARGET_OMIT_LEAF_FRAME_POINTER)
@@ -592,9 +639,19 @@ i386_valid_type_attribute_p (type, attributes, identifier, args)
int
i386_comp_type_attributes (type1, type2)
- tree type1 ATTRIBUTE_UNUSED;
- tree type2 ATTRIBUTE_UNUSED;
+ tree type1;
+ tree type2;
{
+ /* Check for mismatch of non-default calling convention. */
+ char *rtdstr = TARGET_RTD ? "cdecl" : "stdcall";
+
+ if (TREE_CODE (type1) != FUNCTION_TYPE)
+ return 1;
+
+ /* Check for mismatched return types (cdecl vs stdcall). */
+ if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
+ != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
+ return 0;
return 1;
}
@@ -814,150 +871,6 @@ function_arg_partial_nregs (cum, mode, type, named)
return 0;
}
-/* Output an insn whose source is a 386 integer register. SRC is the
- rtx for the register, and TEMPLATE is the op-code template. SRC may
- be either SImode or DImode.
-
- The template will be output with operands[0] as SRC, and operands[1]
- as a pointer to the top of the 386 stack. So a call from floatsidf2
- would look like this:
-
- output_op_from_reg (operands[1], AS1 (fild%z0,%1));
-
- where %z0 corresponds to the caller's operands[1], and is used to
- emit the proper size suffix.
-
- ??? Extend this to handle HImode - a 387 can load and store HImode
- values directly. */
-
-void
-output_op_from_reg (src, template)
- rtx src;
- char *template;
-{
- rtx xops[4];
- int size = GET_MODE_SIZE (GET_MODE (src));
-
- xops[0] = src;
- xops[1] = AT_SP (Pmode);
- xops[2] = GEN_INT (size);
- xops[3] = stack_pointer_rtx;
-
- if (size > UNITS_PER_WORD)
- {
- rtx high;
-
- if (size > 2 * UNITS_PER_WORD)
- {
- high = gen_rtx_REG (SImode, REGNO (src) + 2);
- output_asm_insn (AS1 (push%L0,%0), &high);
- }
-
- high = gen_rtx_REG (SImode, REGNO (src) + 1);
- output_asm_insn (AS1 (push%L0,%0), &high);
- }
-
- output_asm_insn (AS1 (push%L0,%0), &src);
- output_asm_insn (template, xops);
- output_asm_insn (AS2 (add%L3,%2,%3), xops);
-}
-
-/* Output an insn to pop an value from the 387 top-of-stack to 386
- register DEST. The 387 register stack is popped if DIES is true. If
- the mode of DEST is an integer mode, a `fist' integer store is done,
- otherwise a `fst' float store is done. */
-
-void
-output_to_reg (dest, dies, scratch_mem)
- rtx dest;
- int dies;
- rtx scratch_mem;
-{
- rtx xops[4];
- int size = GET_MODE_SIZE (GET_MODE (dest));
-
- if (! scratch_mem)
- xops[0] = AT_SP (Pmode);
- else
- xops[0] = scratch_mem;
-
- xops[1] = stack_pointer_rtx;
- xops[2] = GEN_INT (size);
- xops[3] = dest;
-
- if (! scratch_mem)
- output_asm_insn (AS2 (sub%L1,%2,%1), xops);
-
- if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
- {
- if (dies)
- output_asm_insn (AS1 (fistp%z3,%y0), xops);
- else if (GET_MODE (xops[3]) == DImode && ! dies)
- {
- /* There is no DImode version of this without a stack pop, so
- we must emulate it. It doesn't matter much what the second
- instruction is, because the value being pushed on the FP stack
- is not used except for the following stack popping store.
- This case can only happen without optimization, so it doesn't
- matter that it is inefficient. */
- output_asm_insn (AS1 (fistp%z3,%0), xops);
- output_asm_insn (AS1 (fild%z3,%0), xops);
- }
- else
- output_asm_insn (AS1 (fist%z3,%y0), xops);
- }
-
- else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT)
- {
- if (dies)
- output_asm_insn (AS1 (fstp%z3,%y0), xops);
- else
- {
- if (GET_MODE (dest) == XFmode)
- {
- output_asm_insn (AS1 (fstp%z3,%y0), xops);
- output_asm_insn (AS1 (fld%z3,%y0), xops);
- }
- else
- output_asm_insn (AS1 (fst%z3,%y0), xops);
- }
- }
-
- else
- abort ();
-
- if (! scratch_mem)
- output_asm_insn (AS1 (pop%L0,%0), &dest);
- else
- output_asm_insn (AS2 (mov%L0,%0,%3), xops);
-
-
- if (size > UNITS_PER_WORD)
- {
- dest = gen_rtx_REG (SImode, REGNO (dest) + 1);
- if (! scratch_mem)
- output_asm_insn (AS1 (pop%L0,%0), &dest);
- else
- {
- xops[0] = adj_offsettable_operand (xops[0], 4);
- xops[3] = dest;
- output_asm_insn (AS2 (mov%L0,%0,%3), xops);
- }
-
- if (size > 2 * UNITS_PER_WORD)
- {
- dest = gen_rtx_REG (SImode, REGNO (dest) + 1);
- if (! scratch_mem)
- output_asm_insn (AS1 (pop%L0,%0), &dest);
- else
- {
- xops[0] = adj_offsettable_operand (xops[0], 4);
- output_asm_insn (AS2 (mov%L0,%0,%3), xops);
- }
- }
- }
-}
-
char *
singlemove_string (operands)
rtx *operands;
@@ -983,32 +896,6 @@ singlemove_string (operands)
}
}
-/* Return a REG that occurs in ADDR with coefficient 1.
- ADDR can be effectively incremented by incrementing REG. */
-
-static rtx
-find_addr_reg (addr)
- rtx addr;
-{
- while (GET_CODE (addr) == PLUS)
- {
- if (GET_CODE (XEXP (addr, 0)) == REG)
- addr = XEXP (addr, 0);
- else if (GET_CODE (XEXP (addr, 1)) == REG)
- addr = XEXP (addr, 1);
- else if (CONSTANT_P (XEXP (addr, 0)))
- addr = XEXP (addr, 1);
- else if (CONSTANT_P (XEXP (addr, 1)))
- addr = XEXP (addr, 0);
- else
- abort ();
- }
-
- if (GET_CODE (addr) == REG)
- return addr;
- abort ();
-}
-
/* Output an insn to add the constant N to the register X. */
static void
@@ -1046,7 +933,6 @@ output_move_double (operands)
rtx latehalf[2];
rtx middlehalf[2];
rtx xops[2];
- rtx addreg0 = 0, addreg1 = 0;
int dest_overlapped_low = 0;
int size = GET_MODE_SIZE (GET_MODE (operands[0]));
@@ -1083,11 +969,14 @@ output_move_double (operands)
else
optype1 = RNDOP;
- /* Check for the cases that the operand constraints are not
- supposed to allow to happen. Abort if we get one,
- because generating code for these cases is painful. */
+ /* Check for the cases that are not supposed to happen
+ either due to the operand constraints or the fact
+ that all memory operands on the x86 are offsettable.
+ Abort if we get one, because generating code for these
+ cases is painful. */
- if (optype0 == RNDOP || optype1 == RNDOP)
+ if (optype0 == RNDOP || optype1 == RNDOP
+ || optype0 == MEMOP || optype1 == MEMOP)
abort ();
/* If one operand is decrementing and one is incrementing
@@ -1122,15 +1011,6 @@ output_move_double (operands)
optype1 = OFFSOP;
}
- /* If an operand is an unoffsettable memory ref, find a register
- we can increment temporarily to make it refer to the second word. */
-
- if (optype0 == MEMOP)
- addreg0 = find_addr_reg (XEXP (operands[0], 0));
-
- if (optype1 == MEMOP)
- addreg1 = find_addr_reg (XEXP (operands[1], 0));
-
/* Ok, we can do one word at a time.
Normally we do the low-numbered word first,
but if either operand is autodecrementing then we
@@ -1227,8 +1107,7 @@ output_move_double (operands)
emit the move late-half first. Otherwise, compute the MEM address
into the upper part of N and use that as a pointer to the memory
operand. */
- if (optype0 == REGOP
- && (optype1 == OFFSOP || optype1 == MEMOP))
+ if (optype0 == REGOP && optype1 == OFFSOP)
{
if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
&& reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
@@ -1260,10 +1139,6 @@ output_move_double (operands)
|| reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
goto compadr;
- /* JRV says this can't happen: */
- if (addreg0 || addreg1)
- abort ();
-
/* Only the middle reg conflicts; simply put it last. */
output_asm_insn (singlemove_string (operands), operands);
output_asm_insn (singlemove_string (latehalf), latehalf);
@@ -1298,29 +1173,11 @@ output_move_double (operands)
|| REGNO (operands[0]) == REGNO (latehalf[1])))
|| dest_overlapped_low)
{
- /* Make any unoffsettable addresses point at high-numbered word. */
- if (addreg0)
- asm_add (size-4, addreg0);
- if (addreg1)
- asm_add (size-4, addreg1);
-
- /* Do that word. */
+ /* Do the high-numbered word. */
output_asm_insn (singlemove_string (latehalf), latehalf);
- /* Undo the adds we just did. */
- if (addreg0)
- asm_add (-4, addreg0);
- if (addreg1)
- asm_add (-4, addreg1);
-
if (size == 12)
- {
- output_asm_insn (singlemove_string (middlehalf), middlehalf);
- if (addreg0)
- asm_add (-4, addreg0);
- if (addreg1)
- asm_add (-4, addreg1);
- }
+ output_asm_insn (singlemove_string (middlehalf), middlehalf);
/* Do low-numbered word. */
return singlemove_string (operands);
@@ -1332,30 +1189,11 @@ output_move_double (operands)
/* Do the middle one of the three words for long double */
if (size == 12)
- {
- if (addreg0)
- asm_add (4, addreg0);
- if (addreg1)
- asm_add (4, addreg1);
+ output_asm_insn (singlemove_string (middlehalf), middlehalf);
- output_asm_insn (singlemove_string (middlehalf), middlehalf);
- }
-
- /* Make any unoffsettable addresses point at high-numbered word. */
- if (addreg0)
- asm_add (4, addreg0);
- if (addreg1)
- asm_add (4, addreg1);
-
- /* Do that word. */
+ /* Do the high-numbered word. */
output_asm_insn (singlemove_string (latehalf), latehalf);
- /* Undo the adds we just did. */
- if (addreg0)
- asm_add (4-size, addreg0);
- if (addreg1)
- asm_add (4-size, addreg1);
-
return "";
}
@@ -1440,125 +1278,6 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands)
return "";
}
-/* Output the appropriate code to move data between two memory locations */
-
-char *
-output_move_memory (operands, insn, length, tmp_start, n_operands)
- rtx operands[];
- rtx insn;
- int length;
- int tmp_start;
- int n_operands;
-{
- struct
- {
- char *load;
- char *store;
- rtx xops[3];
- } tmp_info[MAX_TMPS];
-
- rtx dest = operands[0];
- rtx src = operands[1];
- rtx qi_tmp = NULL_RTX;
- int max_tmps = 0;
- int offset = 0;
- int i, num_tmps;
- rtx xops[3];
-
- if (GET_CODE (dest) == MEM
- && GET_CODE (XEXP (dest, 0)) == PRE_INC
- && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
- return output_move_pushmem (operands, insn, length, tmp_start, n_operands);
-
- if (! offsettable_memref_p (src))
- fatal_insn ("Source is not offsettable", insn);
-
- if (! offsettable_memref_p (dest))
- fatal_insn ("Destination is not offsettable", insn);
-
- /* Figure out which temporary registers we have available */
- for (i = tmp_start; i < n_operands; i++)
- {
- if (GET_CODE (operands[i]) == REG)
- {
- if ((length & 1) != 0 && qi_tmp == 0 && QI_REG_P (operands[i]))
- qi_tmp = operands[i];
-
- if (reg_overlap_mentioned_p (operands[i], dest))
- fatal_insn ("Temporary register overlaps the destination", insn);
-
- if (reg_overlap_mentioned_p (operands[i], src))
- fatal_insn ("Temporary register overlaps the source", insn);
-
- tmp_info[max_tmps++].xops[2] = operands[i];
- if (max_tmps == MAX_TMPS)
- break;
- }
- }
-
- if (max_tmps == 0)
- fatal_insn ("No scratch registers were found to do memory->memory moves",
- insn);
-
- if ((length & 1) != 0)
- {
- if (qi_tmp == 0)
- fatal_insn ("No byte register found when moving odd # of bytes.",
- insn);
- }
-
- while (length > 1)
- {
- for (num_tmps = 0; num_tmps < max_tmps; num_tmps++)
- {
- if (length >= 4)
- {
- tmp_info[num_tmps].load = AS2(mov%L0,%1,%2);
- tmp_info[num_tmps].store = AS2(mov%L0,%2,%0);
- tmp_info[num_tmps].xops[0]
- = adj_offsettable_operand (dest, offset);
- tmp_info[num_tmps].xops[1]
- = adj_offsettable_operand (src, offset);
-
- offset += 4;
- length -= 4;
- }
-
- else if (length >= 2)
- {
- tmp_info[num_tmps].load = AS2(mov%W0,%1,%2);
- tmp_info[num_tmps].store = AS2(mov%W0,%2,%0);
- tmp_info[num_tmps].xops[0]
- = adj_offsettable_operand (dest, offset);
- tmp_info[num_tmps].xops[1]
- = adj_offsettable_operand (src, offset);
-
- offset += 2;
- length -= 2;
- }
- else
- break;
- }
-
- for (i = 0; i < num_tmps; i++)
- output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
-
- for (i = 0; i < num_tmps; i++)
- output_asm_insn (tmp_info[i].store, tmp_info[i].xops);
- }
-
- if (length == 1)
- {
- xops[0] = adj_offsettable_operand (dest, offset);
- xops[1] = adj_offsettable_operand (src, offset);
- xops[2] = qi_tmp;
- output_asm_insn (AS2(mov%B0,%1,%2), xops);
- output_asm_insn (AS2(mov%B0,%2,%0), xops);
- }
-
- return "";
-}
-
int
standard_80387_constant_p (x)
rtx x;
@@ -1586,6 +1305,7 @@ standard_80387_constant_p (x)
/* Note that on the 80387, other constants, such as pi,
are much slower to load as standard constants
than to load from doubles in memory! */
+ /* ??? Not true on K6: all constants are equal cost. */
#endif
return 0;
@@ -1646,6 +1366,17 @@ symbolic_operand (op, mode)
}
}
+/* Return nonzero if OP is a constant shift count small enough to
+ encode into an lea instruction. */
+
+int
+small_shift_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return (GET_CODE (op) == CONST_INT && INTVAL (op) > 0 && INTVAL (op) < 4);
+}
+
/* Test for a valid operand for a call instruction.
Don't allow the arg pointer register or virtual regs
since they may change into reg + const, which the patterns
@@ -1994,14 +1725,19 @@ load_pic_register (do_rtl)
{
emit_insn (gen_prologue_get_pc (xops[0], xops[1]));
emit_insn (gen_prologue_set_got (xops[0],
- gen_rtx (SYMBOL_REF, Pmode,
- "$_GLOBAL_OFFSET_TABLE_"),
+#ifdef YES_UNDERSCORES
+ gen_rtx_SYMBOL_REF (Pmode,
+ "$__GLOBAL_OFFSET_TABLE_"),
+#else
+ gen_rtx_SYMBOL_REF (Pmode,
+ "$_GLOBAL_OFFSET_TABLE_"),
+#endif
xops[1]));
}
else
{
output_asm_insn (AS1 (call,%X1), xops);
- output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_,%0", xops);
+ output_asm_insn ("addl $%__GLOBAL_OFFSET_TABLE_,%0", xops);
pic_label_rtx = 0;
}
}
@@ -2024,7 +1760,7 @@ load_pic_register (do_rtl)
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
CODE_LABEL_NUMBER (xops[1]));
output_asm_insn (AS1 (pop%L0,%0), xops);
- output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);
+ output_asm_insn ("addl $%__GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);
}
}
@@ -2036,6 +1772,67 @@ load_pic_register (do_rtl)
emit_insn (gen_blockage ());
}
+/* Compute the size of local storage taking into consideration the
+ desired stack alignment which is to be maintained. Also determine
+ the number of registers saved below the local storage. */
+
+HOST_WIDE_INT
+ix86_compute_frame_size (size, nregs_on_stack)
+ HOST_WIDE_INT size;
+ int *nregs_on_stack;
+{
+ int limit;
+ int nregs;
+ int regno;
+ int padding;
+ int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
+ || current_function_uses_const_pool);
+ HOST_WIDE_INT total_size;
+
+ limit = frame_pointer_needed
+ ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM;
+
+ nregs = 0;
+
+ for (regno = limit - 1; regno >= 0; regno--)
+ if ((regs_ever_live[regno] && ! call_used_regs[regno])
+ || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
+ nregs++;
+
+ padding = 0;
+ total_size = size + (nregs * UNITS_PER_WORD);
+
+#ifdef PREFERRED_STACK_BOUNDARY
+ {
+ int offset;
+ int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
+
+ offset = 4;
+ if (frame_pointer_needed)
+ offset += UNITS_PER_WORD;
+
+ total_size += offset;
+
+ padding = ((total_size + preferred_alignment - 1)
+ & -preferred_alignment) - total_size;
+
+ if (padding < (((offset + preferred_alignment - 1)
+ & -preferred_alignment) - offset))
+ padding += preferred_alignment;
+
+ /* Don't bother aligning the stack of a leaf function
+ which doesn't allocate any stack slots. */
+ if (size == 0 && current_function_is_leaf)
+ padding = 0;
+ }
+#endif
+
+ if (nregs_on_stack)
+ *nregs_on_stack = nregs;
+
+ return size + padding;
+}
+
static void
ix86_prologue (do_rtl)
int do_rtl;
@@ -2045,7 +1842,7 @@ ix86_prologue (do_rtl)
rtx xops[4];
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|| current_function_uses_const_pool);
- long tsize = get_frame_size ();
+ HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), (int *)0);
rtx insn;
int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
@@ -2180,6 +1977,10 @@ ix86_prologue (do_rtl)
}
}
+#ifdef SUBTARGET_PROLOGUE
+ SUBTARGET_PROLOGUE;
+#endif
+
if (pic_reg_used)
load_pic_register (do_rtl);
@@ -2254,32 +2055,18 @@ ix86_epilogue (do_rtl)
int do_rtl;
{
register int regno;
- register int nregs, limit;
- int offset;
+ register int limit;
+ int nregs;
rtx xops[3];
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|| current_function_uses_const_pool);
- long tsize = get_frame_size ();
-
- /* Compute the number of registers to pop */
-
- limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
+ int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), &nregs);
- nregs = 0;
+ /* sp is often unreliable so we may have to go off the frame pointer. */
- for (regno = limit - 1; regno >= 0; regno--)
- if ((regs_ever_live[regno] && ! call_used_regs[regno])
- || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
- nregs++;
-
- /* sp is often unreliable so we must go off the frame pointer.
-
- In reality, we may not care if sp is unreliable, because we can restore
- the register relative to the frame pointer. In theory, since each move
- is the same speed as a pop, and we don't need the leal, this is faster.
- For now restore multiple registers the old way. */
-
- offset = - tsize - (nregs * UNITS_PER_WORD);
+ offset = -(tsize + nregs * UNITS_PER_WORD);
xops[2] = stack_pointer_rtx;
@@ -2294,9 +2081,17 @@ ix86_epilogue (do_rtl)
if (flag_pic || profile_flag || profile_block_flag)
emit_insn (gen_blockage ());
- if (nregs > 1 || ! frame_pointer_needed)
+ /* If we're only restoring one register and sp is not valid then
+ using a move instruction to restore the register since it's
+ less work than reloading sp and popping the register. Otherwise,
+ restore sp (if necessary) and pop the registers. */
+
+ limit = frame_pointer_needed
+ ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM;
+
+ if (nregs > 1 || sp_valid)
{
- if (frame_pointer_needed)
+ if ( !sp_valid )
{
xops[0] = adj_offsettable_operand (AT_BP (QImode), offset);
if (do_rtl)
@@ -2504,6 +2299,37 @@ do { \
} while (0)
int
+legitimate_pic_address_disp_p (disp)
+ register rtx disp;
+{
+ if (GET_CODE (disp) != CONST)
+ return 0;
+ disp = XEXP (disp, 0);
+
+ if (GET_CODE (disp) == PLUS)
+ {
+ if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
+ return 0;
+ disp = XEXP (disp, 0);
+ }
+
+ if (GET_CODE (disp) != UNSPEC
+ || XVECLEN (disp, 0) != 1)
+ return 0;
+
+ /* Must be @GOT or @GOTOFF. */
+ if (XINT (disp, 1) != 6
+ && XINT (disp, 1) != 7)
+ return 0;
+
+ if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
+ && GET_CODE (XVECEXP (disp, 0, 0)) != LABEL_REF)
+ return 0;
+
+ return 1;
+}
+
+int
legitimate_address_p (mode, addr, strict)
enum machine_mode mode;
register rtx addr;
@@ -2524,7 +2350,7 @@ legitimate_address_p (mode, addr, strict)
}
if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
- base = addr;
+ base = addr;
else if (GET_CODE (addr) == PLUS)
{
@@ -2614,6 +2440,12 @@ legitimate_address_p (mode, addr, strict)
return FALSE;
}
+ if (GET_MODE (base) != Pmode)
+ {
+ ADDR_INVALID ("Base is not in Pmode.\n", base);
+ return FALSE;
+ }
+
if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base))
|| (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base)))
{
@@ -2635,6 +2467,12 @@ legitimate_address_p (mode, addr, strict)
return FALSE;
}
+ if (GET_MODE (indx) != Pmode)
+ {
+ ADDR_INVALID ("Index is not in Pmode.\n", indx);
+ return FALSE;
+ }
+
if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (indx))
|| (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
{
@@ -2664,20 +2502,10 @@ legitimate_address_p (mode, addr, strict)
}
}
- /* Validate displacement
- Constant pool addresses must be handled special. They are
- considered legitimate addresses, but only if not used with regs.
- When printed, the output routines know to print the reference with the
- PIC reg, even though the PIC reg doesn't appear in the RTL. */
+ /* Validate displacement. */
if (disp)
{
- if (GET_CODE (disp) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (disp)
- && base == 0
- && indx == 0)
- ;
-
- else if (!CONSTANT_ADDRESS_P (disp))
+ if (!CONSTANT_ADDRESS_P (disp))
{
ADDR_INVALID ("Displacement is not valid.\n", disp);
return FALSE;
@@ -2689,20 +2517,32 @@ legitimate_address_p (mode, addr, strict)
return FALSE;
}
- else if (flag_pic && SYMBOLIC_CONST (disp)
- && base != pic_offset_table_rtx
- && (indx != pic_offset_table_rtx || scale != NULL_RTX))
+ if (flag_pic && SYMBOLIC_CONST (disp))
{
- ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
- return FALSE;
+ if (! legitimate_pic_address_disp_p (disp))
+ {
+ ADDR_INVALID ("Displacement is an invalid PIC construct.\n",
+ disp);
+ return FALSE;
+ }
+
+ if (base != pic_offset_table_rtx
+ && (indx != pic_offset_table_rtx || scale != NULL_RTX))
+ {
+ ADDR_INVALID ("PIC displacement against invalid base.\n", disp);
+ return FALSE;
+ }
}
- else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
- && (base != NULL_RTX || indx != NULL_RTX))
+ else if (HALF_PIC_P ())
{
- ADDR_INVALID ("Displacement is an invalid half-pic reference.\n",
- disp);
- return FALSE;
+ if (! HALF_PIC_ADDRESS_P (disp)
+ || (base != NULL_RTX || indx != NULL_RTX))
+ {
+ ADDR_INVALID ("Displacement is an invalid half-pic reference.\n",
+ disp);
+ return FALSE;
+ }
}
}
@@ -2716,29 +2556,20 @@ legitimate_address_p (mode, addr, strict)
/* Return a legitimate reference for ORIG (an address) using the
register REG. If REG is 0, a new pseudo is generated.
- There are three types of references that must be handled:
+ There are two types of references that must be handled:
1. Global data references must load the address from the GOT, via
the PIC reg. An insn is emitted to do this load, and the reg is
returned.
- 2. Static data references must compute the address as an offset
- from the GOT, whose base is in the PIC reg. An insn is emitted to
- compute the address into a reg, and the reg is returned. Static
- data objects have SYMBOL_REF_FLAG set to differentiate them from
- global data objects.
-
- 3. Constant pool addresses must be handled special. They are
- considered legitimate addresses, but only if not used with regs.
- When printed, the output routines know to print the reference with the
- PIC reg, even though the PIC reg doesn't appear in the RTL.
+ 2. Static data references, constant pool addresses, and code labels
+ compute the address as an offset from the GOT, whose base is in
+ the PIC reg. Static data objects have SYMBOL_REF_FLAG set to
+ differentiate them from global data objects. The returned
+ address is the PIC reg + an unspec constant.
GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
- reg also appears in the address (except for constant pool references,
- noted above).
-
- "switch" statements also require special handling when generating
- PIC code. See comments by the `casesi' insn in i386.md for details. */
+ reg also appears in the address. */
rtx
legitimize_pic_address (orig, reg)
@@ -2747,60 +2578,99 @@ legitimize_pic_address (orig, reg)
{
rtx addr = orig;
rtx new = orig;
+ rtx base;
- if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
+ if (GET_CODE (addr) == LABEL_REF
+ || (GET_CODE (addr) == SYMBOL_REF
+ && (CONSTANT_POOL_ADDRESS_P (addr)
+ || SYMBOL_REF_FLAG (addr))))
{
- if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
- reg = new = orig;
- else
- {
- if (reg == 0)
- reg = gen_reg_rtx (Pmode);
+ /* This symbol may be referenced via a displacement from the PIC
+ base address (@GOTOFF). */
- if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
- || GET_CODE (addr) == LABEL_REF)
- new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
- else
- new = gen_rtx_MEM (Pmode,
- gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig));
+ current_function_uses_pic_offset_table = 1;
+ new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 7);
+ new = gen_rtx_CONST (VOIDmode, new);
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+ if (reg != 0)
+ {
emit_move_insn (reg, new);
+ new = reg;
}
- current_function_uses_pic_offset_table = 1;
- return reg;
}
-
- else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
+ else if (GET_CODE (addr) == SYMBOL_REF)
{
- rtx base;
+ /* This symbol must be referenced via a load from the
+ Global Offset Table (@GOT). */
+
+ current_function_uses_pic_offset_table = 1;
+ new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 6);
+ new = gen_rtx_CONST (VOIDmode, new);
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+ new = gen_rtx_MEM (Pmode, new);
+ RTX_UNCHANGING_P (new) = 1;
+ if (reg == 0)
+ reg = gen_reg_rtx (Pmode);
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ else
+ {
if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
- if (GET_CODE (addr) != PLUS)
- abort ();
+ if (GET_CODE (addr) == UNSPEC)
+ {
+ /* Check that the unspec is one of the ones we generate? */
+ }
+ else if (GET_CODE (addr) != PLUS)
+ abort();
}
+ if (GET_CODE (addr) == PLUS)
+ {
+ rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
+
+ /* Check first to see if this is a constant offset from a @GOTOFF
+ symbol reference. */
+ if ((GET_CODE (op0) == LABEL_REF
+ || (GET_CODE (op0) == SYMBOL_REF
+ && (CONSTANT_POOL_ADDRESS_P (op0)
+ || SYMBOL_REF_FLAG (op0))))
+ && GET_CODE (op1) == CONST_INT)
+ {
+ current_function_uses_pic_offset_table = 1;
+ new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, op0), 7);
+ new = gen_rtx_PLUS (VOIDmode, new, op1);
+ new = gen_rtx_CONST (VOIDmode, new);
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
- if (XEXP (addr, 0) == pic_offset_table_rtx)
- return orig;
-
- if (reg == 0)
- reg = gen_reg_rtx (Pmode);
-
- base = legitimize_pic_address (XEXP (addr, 0), reg);
- addr = legitimize_pic_address (XEXP (addr, 1),
- base == reg ? NULL_RTX : reg);
-
- if (GET_CODE (addr) == CONST_INT)
- return plus_constant (base, INTVAL (addr));
+ if (reg != 0)
+ {
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ }
+ else
+ {
+ base = legitimize_pic_address (XEXP (addr, 0), reg);
+ new = legitimize_pic_address (XEXP (addr, 1),
+ base == reg ? NULL_RTX : reg);
- if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
- {
- base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
- addr = XEXP (addr, 1);
+ if (GET_CODE (new) == CONST_INT)
+ new = plus_constant (base, INTVAL (new));
+ else
+ {
+ if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))
+ {
+ base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));
+ new = XEXP (new, 1);
+ }
+ new = gen_rtx_PLUS (Pmode, base, new);
+ }
+ }
}
-
- return gen_rtx (PLUS, Pmode, base, addr);
}
return new;
}
@@ -2815,7 +2685,7 @@ emit_pic_move (operands, mode)
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
- operands[1] = force_reg (SImode, operands[1]);
+ operands[1] = force_reg (Pmode, operands[1]);
else
operands[1] = legitimize_pic_address (operands[1], temp);
}
@@ -2866,8 +2736,8 @@ legitimize_address (x, oldx, mode)
&& (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
{
changed = 1;
- x = gen_rtx (MULT, Pmode, force_reg (Pmode, XEXP (x, 0)),
- GEN_INT (1 << log));
+ x = gen_rtx_MULT (Pmode, force_reg (Pmode, XEXP (x, 0)),
+ GEN_INT (1 << log));
}
if (GET_CODE (x) == PLUS)
@@ -3028,31 +2898,14 @@ output_pic_addr_const (file, x, code)
break;
case SYMBOL_REF:
- case LABEL_REF:
- if (GET_CODE (x) == SYMBOL_REF)
- assemble_name (file, XSTR (x, 0));
- else
- {
- ASM_GENERATE_INTERNAL_LABEL (buf, "L",
- CODE_LABEL_NUMBER (XEXP (x, 0)));
- assemble_name (asm_out_file, buf);
- }
-
- if (code == 'X')
- ; /* No suffix, dammit. */
- else if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
- fprintf (file, "@GOTOFF(%%ebx)");
- else if (code == 'P')
- fprintf (file, "@PLT");
- else if (GET_CODE (x) == LABEL_REF)
- fprintf (file, "@GOTOFF");
- else if (! SYMBOL_REF_FLAG (x))
- fprintf (file, "@GOT");
- else
- fprintf (file, "@GOTOFF");
-
+ assemble_name (file, XSTR (x, 0));
+ if (code == 'P' && ! SYMBOL_REF_FLAG (x))
+ fputs ("@PLT", file);
break;
+ case LABEL_REF:
+ x = XEXP (x, 0);
+ /* FALLTHRU */
case CODE_LABEL:
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
assemble_name (asm_out_file, buf);
@@ -3090,17 +2943,17 @@ output_pic_addr_const (file, x, code)
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
{
output_pic_addr_const (file, XEXP (x, 0), code);
- if (INTVAL (XEXP (x, 1)) >= 0)
- fprintf (file, "+");
+ fprintf (file, "+");
output_pic_addr_const (file, XEXP (x, 1), code);
}
- else
+ else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
{
output_pic_addr_const (file, XEXP (x, 1), code);
- if (INTVAL (XEXP (x, 0)) >= 0)
- fprintf (file, "+");
+ fprintf (file, "+");
output_pic_addr_const (file, XEXP (x, 0), code);
}
+ else
+ abort ();
break;
case MINUS:
@@ -3109,11 +2962,141 @@ output_pic_addr_const (file, x, code)
output_pic_addr_const (file, XEXP (x, 1), code);
break;
+ case UNSPEC:
+ if (XVECLEN (x, 0) != 1)
+ abort ();
+ output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
+ switch (XINT (x, 1))
+ {
+ case 6:
+ fputs ("@GOT", file);
+ break;
+ case 7:
+ fputs ("@GOTOFF", file);
+ break;
+ case 8:
+ fputs ("@PLT", file);
+ break;
+ default:
+ output_operand_lossage ("invalid UNSPEC as operand");
+ break;
+ }
+ break;
+
default:
output_operand_lossage ("invalid expression as operand");
}
}
+static void
+put_jump_code (code, reverse, file)
+ enum rtx_code code;
+ int reverse;
+ FILE *file;
+{
+ int flags = cc_prev_status.flags;
+ int ieee = (TARGET_IEEE_FP && (flags & CC_IN_80387)
+ && !(cc_prev_status.flags & CC_FCOMI));
+ const char *suffix;
+
+ if (flags & CC_Z_IN_NOT_C)
+ switch (code)
+ {
+ case EQ:
+ fputs (reverse ? "c" : "nc", file);
+ return;
+
+ case NE:
+ fputs (reverse ? "nc" : "c", file);
+ return;
+
+ default:
+ abort ();
+ }
+ if (ieee)
+ {
+ switch (code)
+ {
+ case LE:
+ suffix = reverse ? "ae" : "b";
+ break;
+ case GT:
+ case LT:
+ case GE:
+ suffix = reverse ? "ne" : "e";
+ break;
+ case EQ:
+ suffix = reverse ? "ne" : "e";
+ break;
+ case NE:
+ suffix = reverse ? "e" : "ne";
+ break;
+ default:
+ abort ();
+ }
+ fputs (suffix, file);
+ return;
+ }
+ if (flags & CC_TEST_AX)
+ abort();
+ if ((flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
+ abort ();
+ if (reverse)
+ code = reverse_condition (code);
+ switch (code)
+ {
+ case EQ:
+ suffix = "e";
+ break;
+
+ case NE:
+ suffix = "ne";
+ break;
+
+ case GT:
+ suffix = flags & CC_IN_80387 ? "a" : "g";
+ break;
+
+ case GTU:
+ suffix = "a";
+ break;
+
+ case LT:
+ if (flags & CC_NO_OVERFLOW)
+ suffix = "s";
+ else
+ suffix = flags & CC_IN_80387 ? "b" : "l";
+ break;
+
+ case LTU:
+ suffix = "b";
+ break;
+
+ case GE:
+ if (flags & CC_NO_OVERFLOW)
+ suffix = "ns";
+ else
+ suffix = flags & CC_IN_80387 ? "ae" : "ge";
+ break;
+
+ case GEU:
+ suffix = "ae";
+ break;
+
+ case LE:
+ suffix = flags & CC_IN_80387 ? "be" : "le";
+ break;
+
+ case LEU:
+ suffix = "be";
+ break;
+
+ default:
+ abort ();
+ }
+ fputs (suffix, file);
+}
+
/* Append the correct conditional move suffix which corresponds to CODE. */
static void
@@ -3230,12 +3213,13 @@ put_condition_code (code, reverse_cc, mode, file)
C -- print opcode suffix for set/cmov insn.
c -- like C, but print reversed condition
F -- print opcode suffix for fcmov insn.
- f -- like C, but print reversed condition
+ f -- like F, but print reversed condition
+ D -- print the opcode suffix for a jump
+ d -- like D, but print reversed condition
R -- print the prefix for register names.
z -- print the opcode suffix for the size of the current operand.
* -- print a star (in certain assembler syntax)
w -- print the operand as if it's a "word" (HImode) even if it isn't.
- c -- don't print special prefixes before constant operands.
J -- print the appropriate jump operand.
s -- print a shift double count, followed by the assemblers argument
delimiter.
@@ -3245,7 +3229,8 @@ put_condition_code (code, reverse_cc, mode, file)
k -- likewise, print the SImode name of the register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
y -- print "st(0)" instead of "st" as a register.
- P -- print as a PIC constant */
+ P -- print as a PIC constant
+ _ -- output "_" if YES_UNDERSCORES */
void
print_operand (file, x, code)
@@ -3262,6 +3247,12 @@ print_operand (file, x, code)
putc ('*', file);
return;
+ case '_':
+#ifdef YES_UNDERSCORES
+ putc ('_', file);
+#endif
+ return;
+
case 'L':
PUT_OP_SIZE (code, 'l', file);
return;
@@ -3296,12 +3287,10 @@ print_operand (file, x, code)
/* this is the size of op from size of operand */
switch (GET_MODE_SIZE (GET_MODE (x)))
{
- case 1:
- PUT_OP_SIZE ('B', 'b', file);
- return;
-
case 2:
- PUT_OP_SIZE ('W', 'w', file);
+#ifdef HAVE_GAS_FILDS_FISTS
+ PUT_OP_SIZE ('W', 's', file);
+#endif
return;
case 4:
@@ -3331,6 +3320,9 @@ print_operand (file, x, code)
PUT_OP_SIZE ('Q', 'l', file);
return;
+
+ default:
+ abort ();
}
case 'b':
@@ -3373,6 +3365,14 @@ print_operand (file, x, code)
return;
+ case 'D':
+ put_jump_code (GET_CODE (x), 0, file);
+ return;
+
+ case 'd':
+ put_jump_code (GET_CODE (x), 1, file);
+ return;
+
/* This is used by the conditional move instructions. */
case 'C':
put_condition_code (GET_CODE (x), 0, MODE_INT, file);
@@ -3481,6 +3481,11 @@ print_operand_address (file, addr)
switch (GET_CODE (addr))
{
case REG:
+ /* ESI addressing makes instruction vector decoded on the K6. We can
+ avoid this by ESI+0 addressing. */
+ if (REGNO_REG_CLASS (REGNO (addr)) == SIREG
+ && ix86_cpu == PROCESSOR_K6 && !optimize_size)
+ output_addr_const (file, const0_rtx);
ADDR_BEG (file);
fprintf (file, "%se", RP);
fputs (hi_reg_name[REGNO (addr)], file);
@@ -3596,8 +3601,16 @@ print_operand_address (file, addr)
ireg = XEXP (addr, 0);
}
- output_addr_const (file, const0_rtx);
- PRINT_B_I_S (NULL_RTX, ireg, scale, file);
+ /* (reg,reg,) is shorter than (,reg,2). */
+ if (scale == 2)
+ {
+ PRINT_B_I_S (ireg, ireg, 1, file);
+ }
+ else
+ {
+ output_addr_const (file, const0_rtx);
+ PRINT_B_I_S (NULL_RTX, ireg, scale, file);
+ }
}
break;
@@ -3646,8 +3659,7 @@ notice_update_cc (exp)
if (REG_P (SET_DEST (exp))
&& (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
|| GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'
- || (GET_CODE (SET_SRC (exp)) == IF_THEN_ELSE
- && GET_MODE_CLASS (GET_MODE (SET_DEST (exp))) == MODE_INT)))
+ || GET_CODE (SET_SRC (exp)) == IF_THEN_ELSE))
{
if (cc_status.value1
&& reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
@@ -3749,7 +3761,7 @@ notice_update_cc (exp)
if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
{
cc_status.flags |= CC_IN_80387;
- if (0 && TARGET_CMOVE && stack_regs_mentioned_p
+ if (TARGET_CMOVE && stack_regs_mentioned_p
(XEXP (SET_SRC (XVECEXP (exp, 0, 0)), 1)))
cc_status.flags |= CC_FCOMI;
}
@@ -3781,7 +3793,12 @@ split_di (operands, num, lo_half, hi_half)
while (num--)
{
rtx op = operands[num];
- if (GET_CODE (op) == REG)
+ if (! reload_completed)
+ {
+ lo_half[num] = gen_lowpart (SImode, op);
+ hi_half[num] = gen_highpart (SImode, op);
+ }
+ else if (GET_CODE (op) == REG)
{
lo_half[num] = gen_rtx_REG (SImode, REGNO (op));
hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1);
@@ -3879,35 +3896,19 @@ output_387_binary_op (insn, operands)
switch (GET_CODE (operands[3]))
{
case PLUS:
- if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- base_op = "fiadd";
- else
- base_op = "fadd";
+ base_op = "fadd";
break;
case MINUS:
- if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- base_op = "fisub";
- else
- base_op = "fsub";
+ base_op = "fsub";
break;
case MULT:
- if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- base_op = "fimul";
- else
- base_op = "fmul";
+ base_op = "fmul";
break;
case DIV:
- if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
- base_op = "fidiv";
- else
- base_op = "fdiv";
+ base_op = "fdiv";
break;
default:
@@ -3930,17 +3931,8 @@ output_387_binary_op (insn, operands)
if (GET_CODE (operands[2]) == MEM)
return strcat (buf, AS1 (%z2,%2));
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
- return "";
- }
-
- else if (NON_STACK_REG_P (operands[2]))
- {
- output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
- return "";
- }
+ if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
+ abort ();
if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
{
@@ -3963,18 +3955,6 @@ output_387_binary_op (insn, operands)
if (GET_CODE (operands[2]) == MEM)
return strcat (buf, AS1 (%z2,%2));
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
- return "";
- }
-
- else if (NON_STACK_REG_P (operands[2]))
- {
- output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
- return "";
- }
-
if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
abort ();
@@ -4012,10 +3992,10 @@ output_387_binary_op (insn, operands)
}
/* Output code for INSN to convert a float to a signed int. OPERANDS
- are the insn operands. The output may be SFmode or DFmode and the
- input operand may be SImode or DImode. As a special case, make sure
- that the 387 stack top dies if the output mode is DImode, because the
- hardware requires this. */
+ are the insn operands. The input may be SFmode, DFmode, or XFmode
+ and the output operand may be SImode or DImode. As a special case,
+ make sure that the 387 stack top dies if the output mode is DImode,
+ because the hardware requires this. */
char *
output_fix_trunc (insn, operands)
@@ -4028,40 +4008,98 @@ output_fix_trunc (insn, operands)
if (! STACK_TOP_P (operands[1]))
abort ();
- xops[0] = GEN_INT (12);
- xops[1] = operands[4];
+ if (GET_MODE (operands[0]) == DImode && ! stack_top_dies)
+ abort ();
+
+ xops[0] = GEN_INT (0x0c00);
+ xops[1] = operands[5];
output_asm_insn (AS1 (fnstc%W2,%2), operands);
- output_asm_insn (AS2 (mov%L2,%2,%4), operands);
- output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
- output_asm_insn (AS2 (mov%L4,%4,%3), operands);
+ output_asm_insn (AS2 (mov%W5,%2,%w5), operands);
+ output_asm_insn (AS2 (or%W1,%0,%w1), xops);
+ output_asm_insn (AS2 (mov%W3,%w5,%3), operands);
output_asm_insn (AS1 (fldc%W3,%3), operands);
+ xops[0] = NON_STACK_REG_P (operands[0]) ? operands[4] : operands[0];
+
+ if (stack_top_dies)
+ output_asm_insn (AS1 (fistp%z0,%y0), xops);
+ else
+ output_asm_insn (AS1 (fist%z0,%y0), xops);
+
if (NON_STACK_REG_P (operands[0]))
- output_to_reg (operands[0], stack_top_dies, operands[3]);
+ {
+ if (GET_MODE (operands[0]) == SImode)
+ output_asm_insn (AS2 (mov%L0,%4,%0), operands);
+ else
+ {
+ xops[0] = operands[0];
+ xops[1] = operands[4];
+ output_asm_insn (output_move_double (xops), xops);
+ }
+ }
- else if (GET_CODE (operands[0]) == MEM)
+ return AS1 (fldc%W2,%2);
+}
+
+/* Output code for INSN to extend a float. OPERANDS are the insn
+ operands. The output may be DFmode or XFmode and the input operand
+ may be SFmode or DFmode. Operands 2 and 3 are scratch memory and
+ are only necessary if operands 0 or 1 are non-stack registers. */
+
+void
+output_float_extend (insn, operands)
+ rtx insn;
+ rtx *operands;
+{
+ int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+ rtx xops[2];
+
+ if (! STACK_TOP_P (operands[0]) && ! STACK_TOP_P (operands[1]))
+ abort ();
+
+ if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]) && stack_top_dies)
+ return;
+
+ if (STACK_TOP_P (operands[0]) )
{
- if (stack_top_dies)
- output_asm_insn (AS1 (fistp%z0,%0), operands);
- else if (GET_MODE (operands[0]) == DImode && ! stack_top_dies)
+ if (NON_STACK_REG_P (operands[1]))
{
- /* There is no DImode version of this without a stack pop, so
- we must emulate it. It doesn't matter much what the second
- instruction is, because the value being pushed on the FP stack
- is not used except for the following stack popping store.
- This case can only happen without optimization, so it doesn't
- matter that it is inefficient. */
- output_asm_insn (AS1 (fistp%z0,%0), operands);
- output_asm_insn (AS1 (fild%z0,%0), operands);
+ if (GET_MODE (operands[1]) == SFmode)
+ output_asm_insn (AS2 (mov%L0,%1,%2), operands);
+ else
+ {
+ xops[0] = operands[2];
+ xops[1] = operands[1];
+ output_asm_insn (output_move_double (xops), xops);
+ }
}
- else
- output_asm_insn (AS1 (fist%z0,%0), operands);
+
+ xops[0] = NON_STACK_REG_P (operands[1]) ? operands[2] : operands[1];
+
+ output_asm_insn (AS1 (fld%z0,%y0), xops);
}
else
- abort ();
+ {
+ xops[0] = NON_STACK_REG_P (operands[0]) ? operands[3] : operands[0];
- return AS1 (fldc%W2,%2);
+ if (stack_top_dies
+ || (GET_CODE (xops[0]) == MEM && GET_MODE (xops[0]) == XFmode))
+ {
+ output_asm_insn (AS1 (fstp%z0,%y0), xops);
+ if (! stack_top_dies)
+ output_asm_insn (AS1 (fld%z0,%y0), xops);
+ }
+ else
+ output_asm_insn (AS1 (fst%z0,%y0), xops);
+
+ if (NON_STACK_REG_P (operands[0]))
+ {
+ xops[0] = operands[0];
+ xops[1] = operands[3];
+ output_asm_insn (output_move_double (xops), xops);
+ }
+ }
}
/* Output code for INSN to compare OPERANDS. The two operands might
@@ -4078,8 +4116,11 @@ output_float_compare (insn, operands)
rtx body = XVECEXP (PATTERN (insn), 0, 0);
int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
rtx tmp;
+ int cc0_set = 1;
+ int i;
- if (0 && TARGET_CMOVE && STACK_REG_P (operands[1]))
+ if (TARGET_CMOVE && STACK_REG_P (operands[1])
+ && STACK_REG_P (operands[0]))
{
cc_status.flags |= CC_FCOMI;
cc_prev_status.flags &= ~CC_TEST_AX;
@@ -4101,7 +4142,7 @@ output_float_compare (insn, operands)
if (STACK_REG_P (operands[1])
&& stack_top_dies
&& find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
- && REGNO (operands[1]) != FIRST_STACK_REG)
+ && REGNO (operands[1]) == FIRST_STACK_REG + 1)
{
/* If both the top of the 387 stack dies, and the other operand
is also a stack register that dies, then this must be a
@@ -4113,7 +4154,8 @@ output_float_compare (insn, operands)
{
output_asm_insn (AS2 (fucomip,%y1,%0), operands);
output_asm_insn (AS1 (fstp, %y0), operands);
- return "";
+ if (!TARGET_IEEE_FP)
+ cc0_set = 0;
}
else
output_asm_insn ("fucompp", operands);
@@ -4124,7 +4166,8 @@ output_float_compare (insn, operands)
{
output_asm_insn (AS2 (fcomip, %y1,%0), operands);
output_asm_insn (AS1 (fstp, %y0), operands);
- return "";
+ if (!TARGET_IEEE_FP)
+ cc0_set = 0;
}
else
output_asm_insn ("fcompp", operands);
@@ -4134,35 +4177,55 @@ output_float_compare (insn, operands)
{
static char buf[100];
- /* Decide if this is the integer or float compare opcode, or the
- unordered float compare. */
+ /* Decide if this is a float compare or an unordered float compare. */
if (unordered_compare)
strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fucomi" : "fucom");
- else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
- strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fcomi" : "fcom");
else
- strcpy (buf, "ficom");
+ strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fcomi" : "fcom");
/* Modify the opcode if the 387 stack is to be popped. */
if (stack_top_dies)
strcat (buf, "p");
- if (NON_STACK_REG_P (operands[1]))
- output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
- else if (cc_status.flags & CC_FCOMI)
+ if (cc_status.flags & CC_FCOMI)
{
output_asm_insn (strcat (buf, AS2 (%z1,%y1,%0)), operands);
- return "";
+ if (!TARGET_IEEE_FP)
+ cc0_set = 0;
}
else
output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
}
/* Now retrieve the condition code. */
+ if (cc0_set)
+ {
+ char *r = output_fp_cc0_set (insn);
+ if (r[0]) output_asm_insn (r, operands);
+ }
+
+
+ /* We emit fstp instruction after integer comparsions to improve
+ scheduling. */
+ for (i = 0; i < 2 ; i++)
+ {
+ if (STACK_REG_P (operands[i])
+ && find_regno_note (insn, REG_DEAD, REGNO (operands[i]))
+ && REGNO (operands[i]) != FIRST_STACK_REG
+ && (!stack_top_dies || REGNO (operands[i]) != FIRST_STACK_REG + 1))
+ {
+ rtx xexp[2];
+ xexp[0] = gen_rtx_REG (DFmode,
+ REGNO (operands[i]) - (stack_top_dies != 0));
+ output_asm_insn (AS1 (fstp, %y0), xexp);
+ }
+ }
+
+ return "";
+
- return output_fp_cc0_set (insn);
}
/* Output opcodes to transfer the results of FP compare or test INSN
@@ -4178,17 +4241,19 @@ output_fp_cc0_set (insn)
rtx next;
enum rtx_code code;
- xops[0] = gen_rtx_REG (HImode, 0);
- output_asm_insn (AS1 (fnsts%W0,%0), xops);
+ if (!(cc_status.flags & CC_FCOMI))
+ {
+ xops[0] = gen_rtx_REG (HImode, 0);
+ output_asm_insn (AS1 (fnsts%W0,%0), xops);
+ }
if (! TARGET_IEEE_FP)
{
if (!(cc_status.flags & CC_REVERSED))
{
next = next_cc0_user (insn);
-
- if (GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == SET
+
+ if (GET_CODE (PATTERN (next)) == SET
&& SET_DEST (PATTERN (next)) == pc_rtx
&& GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
@@ -4213,8 +4278,7 @@ output_fp_cc0_set (insn)
if (next == NULL_RTX)
abort ();
- if (GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == SET
+ if (GET_CODE (PATTERN (next)) == SET
&& SET_DEST (PATTERN (next)) == pc_rtx
&& GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
@@ -4237,61 +4301,103 @@ output_fp_cc0_set (insn)
else
abort ();
- xops[0] = gen_rtx_REG (QImode, 0);
+ if (cc_status.flags & CC_FCOMI)
+ {
+ /* It is very tricky. We have to do it right. */
- switch (code)
+ xops [0] = gen_rtx_REG (QImode, 0);
+
+ switch (code)
+ {
+ case GT:
+ case GE:
+ break;
+
+ case LT:
+ output_asm_insn (AS1 (setb,%b0), xops);
+ output_asm_insn (AS1 (setp,%h0), xops);
+ output_asm_insn (AS2 (cmp%B0,%b0,%h0), xops);
+ break;
+
+ case LE:
+ output_asm_insn (AS1 (setbe,%b0), xops);
+ output_asm_insn (AS1 (setnp,%h0), xops);
+ output_asm_insn (AS2 (xor%B0,%b0,%h0), xops);
+ break;
+
+ case EQ:
+ case NE:
+ output_asm_insn (AS1 (setne,%b0), xops);
+ output_asm_insn (AS1 (setp,%h0), xops);
+ output_asm_insn (AS2 (or%B0,%b0,%h0), xops);
+ break;
+
+ case GTU:
+ case LTU:
+ case GEU:
+ case LEU:
+ default:
+ abort ();
+ }
+ }
+ else
{
- case GT:
- xops[1] = GEN_INT (0x45);
- output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- /* je label */
- break;
+ xops[0] = gen_rtx_REG (QImode, 0);
- case LT:
- xops[1] = GEN_INT (0x45);
- xops[2] = GEN_INT (0x01);
- output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- /* je label */
- break;
+ switch (code)
+ {
+ case GT:
+ xops[1] = GEN_INT (0x45);
+ output_asm_insn (AS2 (and%B0,%1,%h0), xops);
+ /* je label */
+ break;
- case GE:
- xops[1] = GEN_INT (0x05);
- output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- /* je label */
- break;
+ case LT:
+ xops[1] = GEN_INT (0x45);
+ xops[2] = GEN_INT (0x01);
+ output_asm_insn (AS2 (and%B0,%1,%h0), xops);
+ output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
+ /* je label */
+ break;
- case LE:
- xops[1] = GEN_INT (0x45);
- xops[2] = GEN_INT (0x40);
- output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- output_asm_insn (AS1 (dec%B0,%h0), xops);
- output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- /* jb label */
- break;
+ case GE:
+ xops[1] = GEN_INT (0x05);
+ output_asm_insn (AS2 (and%B0,%1,%h0), xops);
+ /* je label */
+ break;
- case EQ:
- xops[1] = GEN_INT (0x45);
- xops[2] = GEN_INT (0x40);
- output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
- /* je label */
- break;
+ case LE:
+ xops[1] = GEN_INT (0x45);
+ xops[2] = GEN_INT (0x40);
+ output_asm_insn (AS2 (and%B0,%1,%h0), xops);
+ output_asm_insn (AS1 (dec%B0,%h0), xops);
+ output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
+ /* jb label */
+ break;
- case NE:
- xops[1] = GEN_INT (0x44);
- xops[2] = GEN_INT (0x40);
- output_asm_insn (AS2 (and%B0,%1,%h0), xops);
- output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
- /* jne label */
- break;
+ case EQ:
+ xops[1] = GEN_INT (0x45);
+ xops[2] = GEN_INT (0x40);
+ output_asm_insn (AS2 (and%B0,%1,%h0), xops);
+ output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
+ /* je label */
+ break;
- case GTU:
- case LTU:
- case GEU:
- case LEU:
- default:
- abort ();
+ case NE:
+ xops[1] = GEN_INT (0x44);
+ xops[2] = GEN_INT (0x40);
+ output_asm_insn (AS2 (and%B0,%1,%h0), xops);
+ output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
+ /* jne label */
+ break;
+
+ case GTU:
+ case LTU:
+ case GEU:
+ case LEU:
+ default:
+ abort ();
+ }
}
return "";
@@ -4927,16 +5033,36 @@ int
agi_dependent (insn, dep_insn)
rtx insn, dep_insn;
{
+ int push = 0, push_dep = 0;
if (GET_CODE (dep_insn) == INSN
&& GET_CODE (PATTERN (dep_insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG)
- return reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn);
+ && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG
+ && reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn))
+ return 1;
+
+ if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
+ && push_operand (SET_DEST (PATTERN (insn)),
+ GET_MODE (SET_DEST (PATTERN (insn)))))
+ push = 1;
if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET
&& GET_CODE (SET_DEST (PATTERN (dep_insn))) == MEM
&& push_operand (SET_DEST (PATTERN (dep_insn)),
GET_MODE (SET_DEST (PATTERN (dep_insn)))))
- return reg_mentioned_in_mem (stack_pointer_rtx, insn);
+ push_dep = 1;
+
+ /* CPUs contain special hardware to allow two pushes. */
+ if (push && push_dep)
+ return 0;
+
+ /* Push operation implicitly change stack pointer causing AGI stalls. */
+ if (push_dep && reg_mentioned_in_mem (stack_pointer_rtx, insn))
+ return 1;
+
+ /* Push also implicitly read stack pointer. */
+ if (push && modified_in_p (stack_pointer_rtx, dep_insn))
+ return 1;
return 0;
}
@@ -5196,6 +5322,13 @@ output_fp_conditional_move (which_alternative, operands)
int which_alternative;
rtx operands[];
{
+ enum rtx_code code = GET_CODE (operands[1]);
+
+ /* This should never happen. */
+ if (!(cc_prev_status.flags & CC_IN_80387)
+ && (code == GT || code == LE || code == GE || code == LT))
+ abort ();
+
switch (which_alternative)
{
case 0:
@@ -5220,9 +5353,7 @@ output_int_conditional_move (which_alternative, operands)
int which_alternative;
rtx operands[];
{
- int code = GET_CODE (operands[1]);
- enum machine_mode mode;
- rtx xops[4];
+ enum rtx_code code = GET_CODE (operands[1]);
/* This is very tricky. We have to do it right. For a code segement
like:
@@ -5242,29 +5373,16 @@ output_int_conditional_move (which_alternative, operands)
&& (cc_prev_status.flags & CC_NO_OVERFLOW))
return NULL_PTR;
- mode = GET_MODE (operands [0]);
- if (mode == DImode)
- {
- xops [0] = gen_rtx_SUBREG (SImode, operands [0], 1);
- xops [1] = operands [1];
- xops [2] = gen_rtx_SUBREG (SImode, operands [2], 1);
- xops [3] = gen_rtx_SUBREG (SImode, operands [3], 1);
- }
-
switch (which_alternative)
{
case 0:
/* r <- cond ? arg : r */
output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
- if (mode == DImode)
- output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
break;
case 1:
/* r <- cond ? r : arg */
output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
- if (mode == DImode)
- output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
break;
default:
@@ -5273,3 +5391,346 @@ output_int_conditional_move (which_alternative, operands)
return "";
}
+
+int
+x86_adjust_cost (insn, link, dep_insn, cost)
+ rtx insn, link, dep_insn;
+ int cost;
+{
+ rtx next_inst;
+
+ if (GET_CODE (dep_insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
+ return 0;
+
+ if (GET_CODE (dep_insn) == INSN
+ && GET_CODE (PATTERN (dep_insn)) == SET
+ && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG
+ && GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && !reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)),
+ SET_SRC (PATTERN (insn))))
+ return 0; /* ??? */
+
+
+ switch (ix86_cpu)
+ {
+ case PROCESSOR_PENTIUM:
+ if (cost != 0 && is_fp_insn (insn) && is_fp_insn (dep_insn)
+ && !is_fp_dest (dep_insn))
+ return 0;
+
+ if (agi_dependent (insn, dep_insn))
+ return cost ? cost + 1 : 2;
+
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && SET_DEST (PATTERN (insn)) == cc0_rtx
+ && (next_inst = next_nonnote_insn (insn))
+ && GET_CODE (next_inst) == JUMP_INSN)
+ /* compare probably paired with jump */
+ return 0;
+
+ /* Stores stalls one cycle longer than other insns. */
+ if (is_fp_insn (insn) && cost && is_fp_store (dep_insn))
+ cost++;
+ break;
+ case PROCESSOR_K6:
+ default:
+ if (!is_fp_dest (dep_insn))
+ {
+ if(!agi_dependent (insn, dep_insn))
+ return 0;
+ if (TARGET_486)
+ return 2;
+ }
+ else
+ if (is_fp_store (insn) && is_fp_insn (dep_insn)
+ && NEXT_INSN (insn) && NEXT_INSN (NEXT_INSN (insn))
+ && NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))
+ && (GET_CODE (NEXT_INSN (insn)) == INSN)
+ && (GET_CODE (NEXT_INSN (NEXT_INSN (insn))) == JUMP_INSN)
+ && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) == NOTE)
+ && (NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn))))
+ == NOTE_INSN_LOOP_END))
+ return 3;
+ break;
+ }
+
+ return cost;
+}
+
+/* Output assembly code for a left shift.
+
+ Always use "sal" when shifting a memory operand or for a non constant
+ shift count.
+
+ When optimizing for size, we know that src == dest, and we should always
+ use "sal". If src != dest, then copy src to dest and use "sal".
+
+ Pentium and PPro (speed):
+
+ When src == dest, use "add" for a shift counts of one, else use
+ "sal". If we modeled Pentium AGI stalls and U/V pipelining better we
+ would want to generate lea for some shifts on the Pentium.
+
+ When src != dest, use "lea" for small shift counts. Otherwise,
+ copy src to dest and use the normal shifting code. Exception for
+ TARGET_DOUBLE_WITH_ADD. */
+
+char *
+output_ashl (insn, operands)
+ rtx insn, *operands;
+{
+ /* Handle case where srcreg != dstreg. */
+ if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
+ {
+ if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
+ switch (GET_MODE (operands[0]))
+ {
+ case SImode:
+ output_asm_insn (AS2 (mov%L0,%1,%0), operands);
+ return AS2 (add%L0,%1,%0);
+ case HImode:
+ output_asm_insn (AS2 (mov%L0,%k1,%k0), operands);
+ if (i386_cc_probably_useless_p (insn))
+ {
+ CC_STATUS_INIT;
+ return AS2 (add%L0,%k1,%k0);
+ }
+ return AS2 (add%W0,%k1,%k0);
+ case QImode:
+ output_asm_insn (AS2 (mov%B0,%1,%0), operands);
+ return AS2 (add%B0,%1,%0);
+ default:
+ abort ();
+ }
+ else
+ {
+ CC_STATUS_INIT;
+
+ /* This should be extremely rare (impossible?). We can not encode a
+ shift of the stack pointer using an lea instruction. So copy the
+ stack pointer into the destination register and use an lea. */
+ if (operands[1] == stack_pointer_rtx)
+ {
+ output_asm_insn (AS2 (mov%L0,%k1,%k0), operands);
+ operands[1] = operands[0];
+ }
+
+ /* For shifts up to and including 3 bits, use lea. */
+ operands[1] = gen_rtx_MULT (SImode,
+ gen_rtx_REG (SImode, REGNO (operands[1])),
+ GEN_INT (1 << INTVAL (operands[2])));
+ return AS2 (lea%L0,%a1,%k0);
+ }
+ }
+
+ /* Source and destination match. */
+
+ /* Handle variable shift. */
+ if (REG_P (operands[2]))
+ switch (GET_MODE (operands[0]))
+ {
+ case SImode:
+ return AS2 (sal%L0,%b2,%0);
+ case HImode:
+ if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
+ {
+ CC_STATUS_INIT;
+ return AS2 (sal%L0,%b2,%k0);
+ }
+ else
+ return AS2 (sal%W0,%b2,%0);
+ case QImode:
+ return AS2 (sal%B0,%b2,%0);
+ default:
+ abort ();
+ }
+
+ /* Always perform shift by 1 using an add instruction. */
+ if (REG_P (operands[0]) && operands[2] == const1_rtx)
+ switch (GET_MODE (operands[0]))
+ {
+ case SImode:
+ return AS2 (add%L0,%0,%0);
+ case HImode:
+ if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
+ {
+ CC_STATUS_INIT;
+ return AS2 (add%L0,%k0,%k0);
+ }
+ else
+ return AS2 (add%W0,%0,%0);
+ case QImode:
+ return AS2 (add%B0,%0,%0);
+ default:
+ abort ();
+ }
+
+#if 0
+ /* ??? Currently disabled. Because our model of Pentium is far from being
+ exact, this change will need some benchmarking. */
+ /* Shift reg by 2 or 3 use an lea instruction for Pentium if this is
+ insn is expected to issue into the V pipe (the insn's mode will be
+ TImode for a U pipe, and !TImode for a V pipe instruction). */
+ if (! optimize_size
+ && REG_P (operands[0])
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) <= 3
+ && (int)ix86_cpu == (int)PROCESSOR_PENTIUM
+ && GET_MODE (insn) != TImode)
+ {
+ CC_STATUS_INIT;
+ operands[1] = gen_rtx_MULT (SImode, gen_rtx_REG (SImode, REGNO (operands[1])),
+ GEN_INT (1 << INTVAL (operands[2])));
+ return AS2 (lea%L0,%a1,%0);
+ }
+#endif
+
+ /* Otherwise use a shift instruction. */
+ switch (GET_MODE (operands[0]))
+ {
+ case SImode:
+ return AS2 (sal%L0,%2,%0);
+ case HImode:
+ if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
+ {
+ CC_STATUS_INIT;
+ return AS2 (sal%L0,%2,%k0);
+ }
+ else
+ return AS2 (sal%W0,%2,%0);
+ case QImode:
+ return AS2 (sal%B0,%2,%0);
+ default:
+ abort ();
+ }
+}
+
+/* Given the memory address ADDR, calculate the length of the address or
+ the length of just the displacement (controlled by DISP_LENGTH).
+
+ The length returned does not include the one-byte modrm, opcode,
+ or prefix. */
+
+int
+memory_address_info (addr, disp_length)
+ rtx addr;
+ int disp_length;
+{
+ rtx base, index, disp, scale;
+ rtx op0, op1;
+ int len;
+
+ if (GET_CODE (addr) == PRE_DEC
+ || GET_CODE (addr) == POST_INC)
+ return 0;
+
+ /* Register Indirect. */
+ if (register_operand (addr, Pmode))
+ {
+ /* Special cases: ebp and esp need the two-byte modrm form.
+
+ We change [ESI] to [ESI+0] on the K6 when not optimizing
+ for size. */
+ if (addr == stack_pointer_rtx
+ || addr == arg_pointer_rtx
+ || addr == frame_pointer_rtx
+ || (REGNO_REG_CLASS (REGNO (addr)) == SIREG
+ && ix86_cpu == PROCESSOR_K6 && !optimize_size))
+ return 1;
+ else
+ return 0;
+ }
+
+ /* Direct Addressing. */
+ if (CONSTANT_P (addr))
+ return 4;
+
+ index = base = disp = scale = NULL_RTX;
+ op0 = XEXP (addr, 0);
+ op1 = XEXP (addr, 1);
+
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (register_operand (op0, Pmode))
+ {
+ if (register_operand (op1, Pmode))
+ index = op0, base = op1;
+ else
+ base = op0, disp = op1;
+ }
+ else if (GET_CODE (op0) == MULT)
+ {
+ index = XEXP (op0, 0);
+ scale = XEXP (op0, 1);
+ if (register_operand (op1, Pmode))
+ base = op1;
+ else
+ disp = op1;
+ }
+ else if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
+ {
+ index = XEXP (XEXP (op0, 0), 0);
+ scale = XEXP (XEXP (op0, 0), 1);
+ base = XEXP (op0, 1);
+ disp = op1;
+ }
+ else if (GET_CODE (op0) == PLUS)
+ {
+ index = XEXP (op0, 0);
+ base = XEXP (op0, 1);
+ disp = op1;
+ }
+ else
+ abort ();
+ }
+ else if (GET_CODE (addr) == MULT
+ /* We're called for lea too, which implements ashift on occasion. */
+ || GET_CODE (addr) == ASHIFT)
+ {
+ index = XEXP (addr, 0);
+ scale = XEXP (addr, 1);
+ }
+ else
+ abort ();
+
+ /* Allow arg pointer and stack pointer as index if there is not scaling */
+ if (base && index && !scale
+ && (index == stack_pointer_rtx
+ || index == arg_pointer_rtx
+ || index == frame_pointer_rtx))
+ {
+ rtx tmp = base;
+ base = index;
+ index = tmp;
+ }
+
+ /* Special case: ebp cannot be encoded as a base without a displacement. */
+ if (base == frame_pointer_rtx && !disp)
+ disp = const0_rtx;
+
+ /* Scaling can not be encoded without base or displacement.
+ Except for scale == 1 where we can encode reg + reg instead of reg * 2. */
+ if (!base && index
+ && (!scale || GET_CODE (scale) != CONST_INT || (INTVAL (scale) != 1)))
+ disp = const0_rtx;
+
+ /* Find the length of the displacement constant. */
+ len = 0;
+ if (disp)
+ {
+ if (GET_CODE (disp) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (disp), 'K'))
+ len = 1;
+ else
+ len = 4;
+ }
+
+ /* An index requires the two-byte modrm form. Not important
+ if we are computing just length of the displacement. */
+ if (index && ! disp_length)
+ len += 1;
+
+ return len;
+}
diff --git a/contrib/gcc/config/i386/i386.h b/contrib/gcc/config/i386/i386.h
index b8fef11..5e27fd8 100644
--- a/contrib/gcc/config/i386/i386.h
+++ b/contrib/gcc/config/i386/i386.h
@@ -155,62 +155,67 @@ extern int target_flags;
#define TARGET_486 (ix86_cpu == PROCESSOR_I486)
#define TARGET_PENTIUM (ix86_cpu == PROCESSOR_PENTIUM)
#define TARGET_PENTIUMPRO (ix86_cpu == PROCESSOR_PENTIUMPRO)
-#define TARGET_USE_LEAVE (ix86_cpu == PROCESSOR_I386)
-#define TARGET_PUSH_MEMORY (ix86_cpu == PROCESSOR_I386)
-#define TARGET_ZERO_EXTEND_WITH_AND (ix86_cpu != PROCESSOR_I386 \
- && ix86_cpu != PROCESSOR_PENTIUMPRO)
-#define TARGET_DOUBLE_WITH_ADD (ix86_cpu != PROCESSOR_I386)
-#define TARGET_USE_BIT_TEST (ix86_cpu == PROCESSOR_I386)
-#define TARGET_UNROLL_STRLEN (ix86_cpu != PROCESSOR_I386)
-#define TARGET_USE_Q_REG (ix86_cpu == PROCESSOR_PENTIUM \
- || ix86_cpu == PROCESSOR_PENTIUMPRO)
-#define TARGET_USE_ANY_REG (ix86_cpu == PROCESSOR_I486)
-#define TARGET_CMOVE (ix86_arch == PROCESSOR_PENTIUMPRO)
-#define TARGET_DEEP_BRANCH_PREDICTION (ix86_cpu == PROCESSOR_PENTIUMPRO)
+#define TARGET_K6 (ix86_cpu == PROCESSOR_K6)
+
+#define CPUMASK (1 << ix86_cpu)
+extern const int x86_use_leave, x86_push_memory, x86_zero_extend_with_and;
+extern const int x86_use_bit_test, x86_cmove, x86_deep_branch;
+extern const int x86_unroll_strlen, x86_use_q_reg, x86_use_any_reg;
+extern const int x86_double_with_add;
+
+#define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
+#define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
+#define TARGET_ZERO_EXTEND_WITH_AND (x86_zero_extend_with_and & CPUMASK)
+#define TARGET_USE_BIT_TEST (x86_use_bit_test & CPUMASK)
+#define TARGET_UNROLL_STRLEN (x86_unroll_strlen & CPUMASK)
+#define TARGET_USE_Q_REG (x86_use_q_reg & CPUMASK)
+#define TARGET_USE_ANY_REG (x86_use_any_reg & CPUMASK)
+#define TARGET_CMOVE (x86_cmove & (1 << ix86_arch))
+#define TARGET_DEEP_BRANCH_PREDICTION (x86_deep_branch & CPUMASK)
+#define TARGET_DOUBLE_WITH_ADD (x86_double_with_add & CPUMASK)
+
#define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE)
#define TARGET_SWITCHES \
-{ { "80387", MASK_80387 }, \
- { "no-80387", -MASK_80387 }, \
- { "hard-float", MASK_80387 }, \
- { "soft-float", -MASK_80387 }, \
- { "no-soft-float", MASK_80387 }, \
- { "386", 0 }, \
- { "no-386", 0 }, \
- { "486", 0 }, \
- { "no-486", 0 }, \
- { "pentium", 0 }, \
- { "pentiumpro", 0 }, \
- { "rtd", MASK_RTD }, \
- { "no-rtd", -MASK_RTD }, \
- { "align-double", MASK_ALIGN_DOUBLE }, \
- { "no-align-double", -MASK_ALIGN_DOUBLE }, \
- { "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 }, \
- { "omit-leaf-frame-pointer", MASK_OMIT_LEAF_FRAME_POINTER }, \
- { "no-omit-leaf-frame-pointer",-MASK_OMIT_LEAF_FRAME_POINTER }, \
- { "no-wide-multiply", MASK_NO_WIDE_MULTIPLY }, \
- { "wide-multiply", -MASK_NO_WIDE_MULTIPLY }, \
- { "schedule-prologue", MASK_SCHEDULE_PROLOGUE }, \
- { "no-schedule-prologue", -MASK_SCHEDULE_PROLOGUE }, \
- { "debug-addr", MASK_DEBUG_ADDR }, \
- { "no-debug-addr", -MASK_DEBUG_ADDR }, \
- { "move", -MASK_NO_MOVE }, \
- { "no-move", MASK_NO_MOVE }, \
- { "debug-arg", MASK_DEBUG_ARG }, \
- { "no-debug-arg", -MASK_DEBUG_ARG }, \
- { "stack-arg-probe", MASK_STACK_PROBE }, \
- { "no-stack-arg-probe", -MASK_STACK_PROBE }, \
- { "windows", 0 }, \
- { "dll", 0 }, \
+{ { "80387", MASK_80387, "Use hardware fp" }, \
+ { "no-80387", -MASK_80387, "Do not use hardware fp" },\
+ { "hard-float", MASK_80387, "Use hardware fp" }, \
+ { "soft-float", -MASK_80387, "Do not use hardware fp" },\
+ { "no-soft-float", MASK_80387, "Use hardware fp" }, \
+ { "386", 0, "Same as -mcpu=i386" }, \
+ { "486", 0, "Same as -mcpu=i486" }, \
+ { "pentium", 0, "Same as -mcpu=pentium" }, \
+ { "pentiumpro", 0, "Same as -mcpu=pentiumpro" }, \
+ { "rtd", MASK_RTD, "Alternate calling convention" },\
+ { "no-rtd", -MASK_RTD, "Use normal calling convention" },\
+ { "align-double", MASK_ALIGN_DOUBLE, "Align some doubles on dword boundary" },\
+ { "no-align-double", -MASK_ALIGN_DOUBLE, "Align doubles on word boundary" }, \
+ { "svr3-shlib", MASK_SVR3_SHLIB, "Uninitialized locals in .bss" }, \
+ { "no-svr3-shlib", -MASK_SVR3_SHLIB, "Uninitialized locals in .data" }, \
+ { "ieee-fp", MASK_IEEE_FP, "Use IEEE math for fp comparisons" }, \
+ { "no-ieee-fp", -MASK_IEEE_FP, "Do not use IEEE math for fp comparisons" }, \
+ { "fp-ret-in-387", MASK_FLOAT_RETURNS, "Return values of functions in FPU registers" }, \
+ { "no-fp-ret-in-387", -MASK_FLOAT_RETURNS , "Do not return values of functions in FPU registers"}, \
+ { "no-fancy-math-387", MASK_NO_FANCY_MATH_387, "Do not generate sin, cos, sqrt for 387" }, \
+ { "fancy-math-387", -MASK_NO_FANCY_MATH_387, "Generate sin, cos, sqrt for FPU"}, \
+ { "omit-leaf-frame-pointer", MASK_OMIT_LEAF_FRAME_POINTER, "Omit the frame pointer in leaf functions" }, \
+ { "no-omit-leaf-frame-pointer",-MASK_OMIT_LEAF_FRAME_POINTER, "" }, \
+ { "no-wide-multiply", MASK_NO_WIDE_MULTIPLY, "multiplies of 32 bits constrained to 32 bits" }, \
+ { "wide-multiply", -MASK_NO_WIDE_MULTIPLY, "multiplies of 32 bits are 64 bits" }, \
+ { "schedule-prologue", MASK_SCHEDULE_PROLOGUE, "Schedule function prologues" }, \
+ { "no-schedule-prologue", -MASK_SCHEDULE_PROLOGUE, "" }, \
+ { "debug-addr", MASK_DEBUG_ADDR, 0 /* intentionally undoc */ }, \
+ { "no-debug-addr", -MASK_DEBUG_ADDR, 0 /* intentionally undoc */ }, \
+ { "move", -MASK_NO_MOVE, "Generate mem-mem moves" }, \
+ { "no-move", MASK_NO_MOVE, "Don't generate mem-mem moves" }, \
+ { "debug-arg", MASK_DEBUG_ARG, 0 /* intentionally undoc */ }, \
+ { "no-debug-arg", -MASK_DEBUG_ARG, 0 /* intentionally undoc */ }, \
+ { "stack-arg-probe", MASK_STACK_PROBE, "Enable stack probing" }, \
+ { "no-stack-arg-probe", -MASK_STACK_PROBE, "" }, \
+ { "windows", 0, 0 /* intentionally undoc */ }, \
+ { "dll", 0, 0 /* intentionally undoc */ }, \
SUBTARGET_SWITCHES \
- { "", MASK_SCHEDULE_PROLOGUE | TARGET_DEFAULT}}
+ { "", MASK_SCHEDULE_PROLOGUE | TARGET_DEFAULT, 0 }}
/* Which processor to schedule for. The cpu attribute defines a list that
mirrors this list, so changes to i386.md must be made at the same time. */
@@ -219,7 +224,8 @@ enum processor_type
{PROCESSOR_I386, /* 80386 */
PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */
PROCESSOR_PENTIUM,
- PROCESSOR_PENTIUMPRO};
+ PROCESSOR_PENTIUMPRO,
+ PROCESSOR_K6};
#define PROCESSOR_I386_STRING "i386"
#define PROCESSOR_I486_STRING "i486"
@@ -227,28 +233,20 @@ enum processor_type
#define PROCESSOR_PENTIUM_STRING "pentium"
#define PROCESSOR_I686_STRING "i686"
#define PROCESSOR_PENTIUMPRO_STRING "pentiumpro"
+#define PROCESSOR_K6_STRING "k6"
extern enum processor_type ix86_cpu;
extern int ix86_arch;
/* Define the default processor. This is overridden by other tm.h files. */
-#define PROCESSOR_DEFAULT \
- ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \
- ? PROCESSOR_I486 \
- : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \
- ? PROCESSOR_PENTIUM \
- : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \
- ? PROCESSOR_PENTIUMPRO \
- : PROCESSOR_I386
+#define PROCESSOR_DEFAULT (enum processor_type) TARGET_CPU_DEFAULT
#define PROCESSOR_DEFAULT_STRING \
- ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \
- ? PROCESSOR_I486_STRING \
- : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \
- ? PROCESSOR_PENTIUM_STRING \
- : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \
- ? PROCESSOR_PENTIUMPRO_STRING \
- : PROCESSOR_I386_STRING
+ (PROCESSOR_DEFAULT == PROCESSOR_I486 ? PROCESSOR_I486_STRING \
+ : PROCESSOR_DEFAULT == PROCESSOR_PENTIUM ? PROCESSOR_PENTIUM_STRING \
+ : PROCESSOR_DEFAULT == PROCESSOR_PENTIUMPRO ? PROCESSOR_PENTIUMPRO_STRING \
+ : PROCESSOR_DEFAULT == PROCESSOR_K6 ? PROCESSOR_K6_STRING \
+ : PROCESSOR_I386_STRING)
/* This macro is similar to `TARGET_SWITCHES' but defines names of
command options that have values. Its definition is an
@@ -260,14 +258,15 @@ extern int ix86_arch;
option if the fixed part matches. The actual option name is made
by appending `-m' to the specified name. */
#define TARGET_OPTIONS \
-{ { "cpu=", &ix86_cpu_string}, \
- { "arch=", &ix86_arch_string}, \
- { "reg-alloc=", &i386_reg_alloc_order }, \
- { "regparm=", &i386_regparm_string }, \
- { "align-loops=", &i386_align_loops_string }, \
- { "align-jumps=", &i386_align_jumps_string }, \
- { "align-functions=", &i386_align_funcs_string }, \
- { "branch-cost=", &i386_branch_cost_string }, \
+{ { "cpu=", &ix86_cpu_string, "Schedule code for given CPU"}, \
+ { "arch=", &ix86_arch_string, "Generate code for given CPU"}, \
+ { "reg-alloc=", &i386_reg_alloc_order, "Control allocation order of integer registers" }, \
+ { "regparm=", &i386_regparm_string, "Number of registers used to pass integer arguments" }, \
+ { "align-loops=", &i386_align_loops_string, "Loop code aligned to this power of 2" }, \
+ { "align-jumps=", &i386_align_jumps_string, "Jump targets are aligned to this power of 2" }, \
+ { "align-functions=", &i386_align_funcs_string, "Function starts are aligned to this power of 2" }, \
+ { "preferred-stack-boundary=", &i386_preferred_stack_boundary_string, "Attempt to keep stack aligned to this power of 2" }, \
+ { "branch-cost=", &i386_branch_cost_string, "Branches are this expensive (1-5, arbitrary units)" }, \
SUBTARGET_OPTIONS \
}
@@ -295,44 +294,45 @@ extern int ix86_arch;
#define CC1_CPU_SPEC "\
%{!mcpu*: \
%{m386:-mcpu=i386 -march=i386} \
-%{mno-486:-mcpu=i386 -march=i386} \
%{m486:-mcpu=i486 -march=i486} \
-%{mno-386:-mcpu=i486 -march=i486} \
-%{mno-pentium:-mcpu=i486 -march=i486} \
%{mpentium:-mcpu=pentium} \
-%{mno-pentiumpro:-mcpu=pentium} \
%{mpentiumpro:-mcpu=pentiumpro}}"
#endif
#define CPP_486_SPEC "%{!ansi:-Di486} -D__i486 -D__i486__"
#define CPP_586_SPEC "%{!ansi:-Di586 -Dpentium} \
-D__i586 -D__i586__ -D__pentium -D__pentium__"
+#define CPP_K6_SPEC "%{!ansi:-Di586 -Dk6} \
+ -D__i586 -D__i586__ -D__k6 -D__k6__"
#define CPP_686_SPEC "%{!ansi:-Di686 -Dpentiumpro} \
-D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__"
#ifndef CPP_CPU_DEFAULT_SPEC
#if TARGET_CPU_DEFAULT == 1
#define CPP_CPU_DEFAULT_SPEC "%(cpp_486)"
-#else
+#endif
#if TARGET_CPU_DEFAULT == 2
#define CPP_CPU_DEFAULT_SPEC "%(cpp_586)"
-#else
+#endif
#if TARGET_CPU_DEFAULT == 3
#define CPP_CPU_DEFAULT_SPEC "%(cpp_686)"
-#else
-#define CPP_CPU_DEFAULT_SPEC ""
#endif
+#if TARGET_CPU_DEFAULT == 4
+#define CPP_CPU_DEFAULT_SPEC "%(cpp_k6)"
#endif
+#ifndef CPP_CPU_DEFAULT_SPEC
+#define CPP_CPU_DEFAULT_SPEC ""
#endif
#endif /* CPP_CPU_DEFAULT_SPEC */
#ifndef CPP_CPU_SPEC
#define CPP_CPU_SPEC "\
--Asystem(unix) -Acpu(i386) -Amachine(i386) \
+-Acpu(i386) -Amachine(i386) \
%{!ansi:-Di386} -D__i386 -D__i386__ \
%{mcpu=i486:%(cpp_486)} %{m486:%(cpp_486)} \
%{mpentium:%(cpp_586)} %{mcpu=pentium:%(cpp_586)} \
%{mpentiumpro:%(cpp_686)} %{mcpu=pentiumpro:%(cpp_686)} \
+%{mcpu=k6:%(cpp_k6)} \
%{!mcpu*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}}"
#endif
@@ -357,6 +357,7 @@ extern int ix86_arch;
#define EXTRA_SPECS \
{ "cpp_486", CPP_486_SPEC}, \
{ "cpp_586", CPP_586_SPEC}, \
+ { "cpp_k6", CPP_K6_SPEC}, \
{ "cpp_686", CPP_686_SPEC}, \
{ "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
{ "cpp_cpu", CPP_CPU_SPEC }, \
@@ -407,9 +408,13 @@ extern int ix86_arch;
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
#define PARM_BOUNDARY 32
-/* Boundary (in *bits*) on which stack pointer should be aligned. */
+/* Boundary (in *bits*) on which the stack pointer must be aligned. */
#define STACK_BOUNDARY 32
+/* Boundary (in *bits*) on which the stack pointer preferrs to be
+ aligned; the compiler cannot rely on having this alignment. */
+#define PREFERRED_STACK_BOUNDARY i386_preferred_stack_boundary
+
/* Allocation boundary (in *bits*) for the code of a function.
For i486, we get better performance by aligning to a cache
line (i.e. 16 byte) boundary. */
@@ -502,6 +507,46 @@ extern int ix86_arch;
: (ALIGN)) \
: (ALIGN))
+/* If defined, a C expression to compute the alignment for a local
+ variable. TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this macro is used
+ instead of that alignment to align the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ One use of this macro is to increase alignment of medium-size
+ data to make it all fit in fewer cache lines. */
+
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ ? ((TYPE_MODE (TREE_TYPE (TYPE)) == DFmode && (ALIGN) < 64) \
+ ? 64 \
+ : (TYPE_MODE (TREE_TYPE (TYPE)) == XFmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : TREE_CODE (TYPE) == COMPLEX_TYPE \
+ ? ((TYPE_MODE (TYPE) == DCmode && (ALIGN) < 64) \
+ ? 64 \
+ : (TYPE_MODE (TYPE) == XCmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : ((TREE_CODE (TYPE) == RECORD_TYPE \
+ || TREE_CODE (TYPE) == UNION_TYPE \
+ || TREE_CODE (TYPE) == QUAL_UNION_TYPE) \
+ && TYPE_FIELDS (TYPE)) \
+ ? ((DECL_MODE (TYPE_FIELDS (TYPE)) == DFmode && (ALIGN) < 64) \
+ ? 64 \
+ : (DECL_MODE (TYPE_FIELDS (TYPE)) == XFmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : TREE_CODE (TYPE) == REAL_TYPE \
+ ? ((TYPE_MODE (TYPE) == DFmode && (ALIGN) < 64) \
+ ? 64 \
+ : (TYPE_MODE (TYPE) == XFmode && (ALIGN) < 128) \
+ ? 128 \
+ : (ALIGN)) \
+ : (ALIGN))
+
/* Set this non-zero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 0
@@ -664,8 +709,8 @@ extern int ix86_arch;
#define MODES_TIEABLE_P(MODE1, MODE2) \
((MODE1) == (MODE2) \
- || ((MODE1) == SImode && (MODE2) == HImode \
- || (MODE1) == HImode && (MODE2) == SImode))
+ || ((MODE1) == SImode && (MODE2) == HImode) \
+ || ((MODE1) == HImode && (MODE2) == SImode))
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
@@ -834,11 +879,6 @@ enum reg_class
#define STACK_TOP_P(xop) (REG_P (xop) && REGNO (xop) == FIRST_STACK_REG)
-/* Try to maintain the accuracy of the death notes for regs satisfying the
- following. Important for stack like regs, to know when to pop. */
-
-/* #define PRESERVE_DEATH_INFO_REGNO_P(x) FP_REGNO_P(x) */
-
/* 1 if register REGNO can magically overlap other regs.
Note that nonzero values work only in very special circumstances. */
@@ -896,19 +936,10 @@ enum reg_class
/* Similar, but for floating constants, and defining letters G and H.
Here VALUE is the CONST_DOUBLE rtx itself. We allow constants even if
TARGET_387 isn't set, because the stack register converter may need to
- load 0.0 into the function value register.
-
- We disallow these constants when -fomit-frame-pointer and compiling
- PIC code since reload might need to force the constant to memory.
- Forcing the constant to memory changes the elimination offsets after
- the point where they must stay constant.
-
- However, we must allow them after reload as completed as reg-stack.c
- will create insns which use these constants. */
+ load 0.0 into the function value register. */
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- (((reload_completed || !flag_pic || !flag_omit_frame_pointer) && (C) == 'G') \
- ? standard_80387_constant_p (VALUE) : 0)
+ ((C) == 'G' ? standard_80387_constant_p (VALUE) : 0)
/* Place additional restrictions on the register class to use when it
is necessary to be able to hold a value of mode MODE in a reload
@@ -931,8 +962,11 @@ enum reg_class
Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and
movdf to do mem-to-mem moves through integer regs. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode ? NO_REGS \
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode \
+ ? (standard_80387_constant_p (X) \
+ ? reg_class_subset_p (CLASS, FLOAT_REGS) ? CLASS : FLOAT_REGS \
+ : NO_REGS) \
: GET_MODE (X) == QImode && ! reg_class_subset_p (CLASS, Q_REGS) ? Q_REGS \
: ((CLASS) == ALL_REGS \
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) ? GENERAL_REGS \
@@ -1532,25 +1566,16 @@ do { \
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts. */
-/* On the 386, the trampoline contains three instructions:
+/* On the 386, the trampoline contains two instructions:
mov #STATIC,ecx
- mov #FUNCTION,eax
- jmp @eax */
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb9)); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb8)); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_CHAR (FILE, GEN_INT (0xff)); \
- ASM_OUTPUT_CHAR (FILE, GEN_INT (0xe0)); \
-}
+ jmp FUNCTION
+ The trampoline is generated entirely at runtime. The operand of JMP
+ is the address of FUNCTION relative to the instruction following the
+ JMP (which is 5 bytes long). */
/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 12
+#define TRAMPOLINE_SIZE 10
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
@@ -1558,8 +1583,14 @@ do { \
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
+ /* Compute offset from the end of the jmp to the target function. */ \
+ rtx disp = expand_binop (SImode, sub_optab, FNADDR, \
+ plus_constant (TRAMP, 10), \
+ NULL_RTX, 1, OPTAB_DIRECT); \
+ emit_move_insn (gen_rtx_MEM (QImode, TRAMP), GEN_INT (0xb9)); \
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 1)), CXT); \
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), FNADDR); \
+ emit_move_insn (gen_rtx_MEM (QImode, plus_constant (TRAMP, 5)), GEN_INT (0xe9));\
+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), disp); \
}
/* Definitions for register eliminations.
@@ -1601,30 +1632,33 @@ do { \
(OFFSET) = 8; /* Skip saved PC and previous frame pointer */ \
else \
{ \
- int regno; \
- int offset = 0; \
+ int nregs; \
+ int offset; \
+ int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; \
+ HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), \
+ &nregs); \
\
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if ((regs_ever_live[regno] && ! call_used_regs[regno]) \
- || ((current_function_uses_pic_offset_table \
- || current_function_uses_const_pool) \
- && flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)) \
- offset += 4; \
+ (OFFSET) = (tsize + nregs * UNITS_PER_WORD); \
\
- (OFFSET) = offset + get_frame_size (); \
+ offset = 4; \
+ if (frame_pointer_needed) \
+ offset += UNITS_PER_WORD; \
\
- if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
- (OFFSET) += 4; /* Skip saved PC */ \
+ if ((FROM) == ARG_POINTER_REGNUM) \
+ (OFFSET) += offset; \
+ else \
+ (OFFSET) -= ((offset + preferred_alignment - 1) \
+ & -preferred_alignment) - offset; \
} \
}
/* Addressing modes, and classification of registers for them. */
-/* #define HAVE_POST_INCREMENT */
-/* #define HAVE_POST_DECREMENT */
+/* #define HAVE_POST_INCREMENT 0 */
+/* #define HAVE_POST_DECREMENT 0 */
-/* #define HAVE_PRE_DECREMENT */
-/* #define HAVE_PRE_INCREMENT */
+/* #define HAVE_PRE_DECREMENT 0 */
+/* #define HAVE_PRE_INCREMENT 0 */
/* Macros to check register numbers against specific register classes. */
@@ -1703,15 +1737,15 @@ do { \
#define MAX_REGS_PER_ADDRESS 2
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
- || GET_CODE (X) == HIGH)
+#define CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST)
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-#define LEGITIMATE_CONSTANT_P(X) 1
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_CODE (X) == CONST_DOUBLE ? standard_80387_constant_p (X) : 1)
#ifdef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
@@ -1764,8 +1798,7 @@ do { \
that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
#define LEGITIMATE_PIC_OPERAND_P(X) \
- (! SYMBOLIC_CONST (X) \
- || (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X)))
+ (! SYMBOLIC_CONST (X) || legitimate_pic_address_disp_p (X))
#define SYMBOLIC_CONST(X) \
(GET_CODE (X) == SYMBOL_REF \
@@ -1893,10 +1926,10 @@ while (0)
in one reasonably fast instruction. */
#define MOVE_MAX 4
-/* The number of scalar move insns which should be generated instead
- of a string move insn or a library call. Increasing the value
- will always make code faster, but eventually incurs high cost in
- increased code size.
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+ move-instruction pairs, we will do a movstr or libcall instead.
+ Increasing the value will always make code faster, but eventually
+ incurs high cost in increased code size.
If you don't define this, a reasonable default is used.
@@ -2243,70 +2276,7 @@ while (0)
the same cost as a data-dependence. */
#define ADJUST_COST(insn,link,dep_insn,cost) \
- { \
- rtx next_inst; \
- if (GET_CODE (dep_insn) == CALL_INSN) \
- (cost) = 0; \
- \
- else if (GET_CODE (dep_insn) == INSN \
- && GET_CODE (PATTERN (dep_insn)) == SET \
- && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG \
- && GET_CODE (insn) == INSN \
- && GET_CODE (PATTERN (insn)) == SET \
- && !reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)), \
- SET_SRC (PATTERN (insn)))) \
- { \
- (cost) = 0; \
- } \
- \
- else if (GET_CODE (insn) == JUMP_INSN) \
- { \
- (cost) = 0; \
- } \
- \
- if (TARGET_PENTIUM) \
- { \
- if (cost !=0 && is_fp_insn (insn) && is_fp_insn (dep_insn) \
- && !is_fp_dest (dep_insn)) \
- { \
- (cost) = 0; \
- } \
- \
- if (agi_dependent (insn, dep_insn)) \
- { \
- (cost) = 3; \
- } \
- else if (GET_CODE (insn) == INSN \
- && GET_CODE (PATTERN (insn)) == SET \
- && SET_DEST (PATTERN (insn)) == cc0_rtx \
- && (next_inst = next_nonnote_insn (insn)) \
- && GET_CODE (next_inst) == JUMP_INSN) \
- { /* compare probably paired with jump */ \
- (cost) = 0; \
- } \
- } \
- else \
- if (!is_fp_dest (dep_insn)) \
- { \
- if(!agi_dependent (insn, dep_insn)) \
- (cost) = 0; \
- else if (TARGET_486) \
- (cost) = 2; \
- } \
- else \
- if (is_fp_store (insn) && is_fp_insn (dep_insn) \
- && NEXT_INSN (insn) && NEXT_INSN (NEXT_INSN (insn)) \
- && NEXT_INSN (NEXT_INSN (NEXT_INSN (insn))) \
- && (GET_CODE (NEXT_INSN (insn)) == INSN) \
- && (GET_CODE (NEXT_INSN (NEXT_INSN (insn))) == JUMP_INSN) \
- && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) == NOTE) \
- && (NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) \
- == NOTE_INSN_LOOP_END)) \
- { \
- (cost) = 3; \
- } \
- }
-
+ (cost) = x86_adjust_cost(insn, link, dep_insn, cost)
#define ADJUST_BLOCKAGE(last_insn,insn,blockage) \
{ \
@@ -2323,6 +2293,8 @@ while (0)
} \
}
+#define ISSUE_RATE ((int)ix86_cpu > (int)PROCESSOR_I486 ? 2 : 1)
+
/* Add any extra modes needed to represent the condition code.
@@ -2606,7 +2578,7 @@ do { long l; \
F,f -- likewise, but for floating-point. */
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
- ((CODE) == '*')
+ ((CODE) == '*' || (CODE) == '_')
/* Print the name of a register based on its machine mode and number.
If CODE is 'w', pretend the mode is HImode.
@@ -2741,11 +2713,8 @@ extern void function_arg_advance ();
extern struct rtx_def *function_arg ();
extern int function_arg_partial_nregs ();
extern char *output_strlen_unroll ();
-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 ();
@@ -2773,6 +2742,7 @@ extern int shift_op ();
extern int VOIDmode_compare_op ();
extern char *output_387_binary_op ();
extern char *output_fix_trunc ();
+extern void output_float_extend ();
extern char *output_float_compare ();
extern char *output_fp_cc0_set ();
extern void save_386_machine_status ();
@@ -2793,6 +2763,9 @@ extern int reg_mentioned_in_mem ();
extern char *output_int_conditional_move ();
extern char *output_fp_conditional_move ();
extern int ix86_can_use_return_insn_p ();
+extern int small_shift_operand ();
+extern char *output_ashl ();
+extern int memory_address_info ();
#ifdef NOTYET
extern struct rtx_def *copy_all_rtx ();
@@ -2807,11 +2780,13 @@ extern char *i386_regparm_string; /* # registers to use to pass args */
extern char *i386_align_loops_string; /* power of two alignment for loops */
extern char *i386_align_jumps_string; /* power of two alignment for non-loop jumps */
extern char *i386_align_funcs_string; /* power of two alignment for functions */
+extern char *i386_preferred_stack_boundary_string;/* power of two alignment for stack boundary */
extern char *i386_branch_cost_string; /* values 1-5: see jump.c */
extern int i386_regparm; /* i386_regparm_string as a number */
extern int i386_align_loops; /* power of two alignment for loops */
extern int i386_align_jumps; /* power of two alignment for non-loop jumps */
extern int i386_align_funcs; /* power of two alignment for functions */
+extern int i386_preferred_stack_boundary; /* preferred stack boundary alignment in bits */
extern int i386_branch_cost; /* values 1-5: see jump.c */
extern char *hi_reg_name[]; /* names for 16 bit regs */
extern char *qi_reg_name[]; /* names for 8 bit regs (low) */
diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md
index f85992f..fb3e1b2 100644
--- a/contrib/gcc/config/i386/i386.md
+++ b/contrib/gcc/config/i386/i386.md
@@ -64,13 +64,50 @@
;; prevent insns referencing it being scheduled across the initial
;; decrement of the stack pointer.
;; 5 This is a `bsf' operation.
+;; 6 This is the @GOT offset of a PIC address.
+;; 7 This is the @GOTOFF offset of a PIC address.
+;; 8 This is a reference to a symbol's @PLT address.
;; This shadows the processor_type enumeration, so changes must be made
;; to i386.h at the same time.
-(define_attr "type" "integer,idiv,imul,fld,fpop,fpdiv,fpmul"
+(define_attr "type"
+ "integer,binary,memory,test,compare,fcompare,idiv,imul,lea,fld,fpop,fpdiv,fpmul"
(const_string "integer"))
+(define_attr "memory" "none,load,store"
+ (cond [(eq_attr "type" "idiv,lea")
+ (const_string "none")
+
+ (eq_attr "type" "fld")
+ (const_string "load")
+
+ (eq_attr "type" "test")
+ (if_then_else (match_operand 0 "memory_operand" "")
+ (const_string "load")
+ (const_string "none"))
+
+ (eq_attr "type" "compare,fcompare")
+ (if_then_else (ior (match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" ""))
+ (const_string "load")
+ (const_string "none"))
+
+ (and (eq_attr "type" "integer,memory,fpop")
+ (match_operand 0 "memory_operand" ""))
+ (const_string "store")
+
+ (and (eq_attr "type" "integer,memory,fpop")
+ (match_operand 1 "memory_operand" ""))
+ (const_string "load")
+
+ (and (eq_attr "type" "binary,imul,fpmul,fpdiv")
+ (ior (match_operand 1 "memory_operand" "")
+ (match_operand 2 "memory_operand" "")))
+ (const_string "load")]
+
+ (const_string "none")))
+
;; Functional units
; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
@@ -89,11 +126,11 @@
;; Floating point
(define_function_unit "fp" 1 0
- (and (eq_attr "type" "fpop") (eq_attr "cpu" "i386,i486"))
+ (and (eq_attr "type" "fpop,fcompare") (eq_attr "cpu" "i386,i486"))
5 5)
(define_function_unit "fp" 1 0
- (and (eq_attr "type" "fpop") (eq_attr "cpu" "pentium,pentiumpro"))
+ (and (eq_attr "type" "fpop,fcompare") (eq_attr "cpu" "pentium,pentiumpro"))
3 0)
(define_function_unit "fp" 1 0
@@ -117,12 +154,69 @@
10 10)
(define_function_unit "fp" 1 0
- (eq_attr "type" "fld")
+ (and (eq_attr "type" "fld") (eq_attr "cpu" "!pentiumpro,k6"))
1 0)
-(define_function_unit "integer" 1 0
- (and (eq_attr "type" "integer") (eq_attr "cpu" "!i386"))
- 2 0)
+;; K6 FPU is not pipelined.
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fpop,fpmul,fcompare") (eq_attr "cpu" "k6"))
+ 2 2)
+
+;; i386 and i486 have one integer unit, which need not be modeled
+
+(define_function_unit "integer" 2 0
+ (and (eq_attr "type" "integer,binary,test,compare,lea") (eq_attr "cpu" "pentium,pentiumpro"))
+ 1 0)
+
+(define_function_unit "integer" 2 0
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "integer,binary,test,compare")
+ (eq_attr "memory" "!load")))
+ 1 0)
+
+;; Internally, K6 converts REG OP MEM instructions into a load (2 cycles)
+;; and a register operation (1 cycle).
+(define_function_unit "integer" 2 0
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "integer,binary,test,compare")
+ (eq_attr "memory" "load")))
+ 3 0)
+
+;; Multiplies use one of the integer units
+(define_function_unit "integer" 2 0
+ (and (eq_attr "cpu" "pentium") (eq_attr "type" "imul"))
+ 11 11)
+
+(define_function_unit "integer" 2 0
+ (and (eq_attr "cpu" "k6") (eq_attr "type" "imul"))
+ 2 2)
+
+(define_function_unit "integer" 2 0
+ (and (eq_attr "cpu" "pentium") (eq_attr "type" "idiv"))
+ 25 25)
+
+(define_function_unit "integer" 2 0
+ (and (eq_attr "cpu" "k6") (eq_attr "type" "idiv"))
+ 17 17)
+
+;; Pentium Pro and K6 have a separate load unit.
+(define_function_unit "load" 1 0
+ (and (eq_attr "cpu" "pentiumpro") (eq_attr "memory" "load"))
+ 3 0)
+
+(define_function_unit "load" 1 0
+ (and (eq_attr "cpu" "k6") (eq_attr "memory" "load"))
+ 2 0)
+
+;; Pentium Pro and K6 have a separate store unit.
+(define_function_unit "store" 1 0
+ (and (eq_attr "cpu" "pentiumpro,k6") (eq_attr "memory" "store"))
+ 1 0)
+
+;; lea executes in the K6 store unit with 1 cycle latency
+(define_function_unit "store" 1 0
+ (and (eq_attr "cpu" "k6") (eq_attr "type" "lea"))
+ 1 0)
;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".
@@ -140,7 +234,7 @@
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in i386.h.
-(define_attr "cpu" "i386,i486,pentium,pentiumpro"
+(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6"
(const (symbol_ref "ix86_cpu")))
(define_insn "tstsi_1"
@@ -154,7 +248,8 @@
operands[1] = const0_rtx;
return AS2 (cmp%L0,%1,%0);
-}")
+}"
+ [(set_attr "type" "test")])
(define_expand "tstsi"
[(set (cc0)
@@ -179,7 +274,8 @@
operands[1] = const0_rtx;
return AS2 (cmp%W0,%1,%0);
-}")
+}"
+ [(set_attr "type" "test")])
(define_expand "tsthi"
[(set (cc0)
@@ -204,7 +300,8 @@
operands[1] = const0_rtx;
return AS2 (cmp%B0,%1,%0);
-}")
+}"
+ [(set_attr "type" "test")])
(define_expand "tstqi"
[(set (cc0)
@@ -234,7 +331,8 @@
output_asm_insn (AS1 (fstp,%y0), operands);
return output_fp_cc0_set (insn);
-}")
+}"
+ [(set_attr "type" "test")])
;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
;; isn't IEEE compliant.
@@ -268,7 +366,8 @@
output_asm_insn (AS1 (fstp,%y0), operands);
return output_fp_cc0_set (insn);
-}")
+}"
+ [(set_attr "type" "test")])
;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
;; isn't IEEE compliant.
@@ -302,7 +401,8 @@
output_asm_insn (AS1 (fstp,%y0), operands);
return output_fp_cc0_set (insn);
-}")
+}"
+ [(set_attr "type" "test")])
;; Don't generate tstxf if generating IEEE code, since the `ftst' opcode
;; isn't IEEE compliant.
@@ -328,7 +428,8 @@
(compare (match_operand:SI 0 "nonimmediate_operand" "mr,r")
(match_operand:SI 1 "general_operand" "ri,mr")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
- "* return AS2 (cmp%L0,%1,%0);")
+ "* return AS2 (cmp%L0,%1,%0);"
+ [(set_attr "type" "compare")])
(define_expand "cmpsi"
[(set (cc0)
@@ -351,7 +452,8 @@
(compare (match_operand:HI 0 "nonimmediate_operand" "mr,r")
(match_operand:HI 1 "general_operand" "ri,mr")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
- "* return AS2 (cmp%W0,%1,%0);")
+ "* return AS2 (cmp%W0,%1,%0);"
+ [(set_attr "type" "compare")])
(define_expand "cmphi"
[(set (cc0)
@@ -374,7 +476,8 @@
(compare (match_operand:QI 0 "nonimmediate_operand" "q,mq")
(match_operand:QI 1 "general_operand" "qm,nq")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
- "* return AS2 (cmp%B0,%1,%0);")
+ "* return AS2 (cmp%B0,%1,%0);"
+ [(set_attr "type" "compare")])
(define_expand "cmpqi"
[(set (cc0)
@@ -403,27 +506,8 @@
(match_operand:XF 1 "register_operand" "f")]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
-
-(define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "register_operand" "f")
- (float:XF
- (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- "* return output_float_compare (insn, operands);")
-
-(define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(float:XF
- (match_operand:SI 0 "nonimmediate_operand" "rm"))
- (match_operand:XF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -433,7 +517,8 @@
(match_operand:DF 1 "nonimmediate_operand" "fm"))]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -443,7 +528,8 @@
(match_operand:XF 1 "register_operand" "f")]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -453,7 +539,8 @@
(match_operand:SF 1 "nonimmediate_operand" "fm"))]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -463,7 +550,8 @@
(match_operand:XF 1 "register_operand" "f")]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -471,7 +559,8 @@
(match_operand:XF 1 "register_operand" "f")))
(clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -481,27 +570,8 @@
(clobber (match_scratch:HI 3 "=a,a"))]
"TARGET_80387
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "* return output_float_compare (insn, operands);")
-
-(define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:DF 0 "register_operand" "f")
- (float:DF
- (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- "* return output_float_compare (insn, operands);")
-
-(define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(float:DF
- (match_operand:SI 0 "nonimmediate_operand" "rm"))
- (match_operand:DF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -511,7 +581,8 @@
(match_operand:SF 1 "nonimmediate_operand" "fm"))]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -521,7 +592,8 @@
(match_operand:DF 1 "register_operand" "f")]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -531,7 +603,8 @@
(match_operand:DF 1 "nonimmediate_operand" "fm")]))
(clobber (match_scratch:HI 3 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -539,7 +612,8 @@
(match_operand:DF 1 "register_operand" "f")))
(clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
;; These two insns will never be generated by combine due to the mode of
;; the COMPARE.
@@ -561,7 +635,7 @@
; "TARGET_80387"
; "* return output_float_compare (insn, operands);")
-(define_insn "cmpsf_cc_1"
+(define_insn "*cmpsf_cc_1"
[(set (cc0)
(match_operator 2 "VOIDmode_compare_op"
[(match_operand:SF 0 "nonimmediate_operand" "f,fm")
@@ -569,27 +643,8 @@
(clobber (match_scratch:HI 3 "=a,a"))]
"TARGET_80387
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
- "* return output_float_compare (insn, operands);")
-
-(define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(match_operand:SF 0 "register_operand" "f")
- (float:SF
- (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- "* return output_float_compare (insn, operands);")
-
-(define_insn ""
- [(set (cc0)
- (match_operator 2 "VOIDmode_compare_op"
- [(float:SF
- (match_operand:SI 0 "nonimmediate_operand" "rm"))
- (match_operand:SF 1 "register_operand" "f")]))
- (clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_insn ""
[(set (cc0)
@@ -597,7 +652,8 @@
(match_operand:SF 1 "register_operand" "f")))
(clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387"
- "* return output_float_compare (insn, operands);")
+ "* return output_float_compare (insn, operands);"
+ [(set_attr "type" "fcompare")])
(define_expand "cmpxf"
[(set (cc0)
@@ -711,7 +767,10 @@
/* For small integers, we may actually use testb. */
if (GET_CODE (operands[1]) == CONST_INT
&& ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
- && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
+ && (! REG_P (operands[0]) || QI_REG_P (operands[0]))
+ /* A Pentium test is pairable only with eax. Not with ah or al. */
+ && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM
+ || optimize_size))
{
/* We may set the sign bit spuriously. */
@@ -757,7 +816,8 @@
return AS2 (test%L0,%1,%0);
return AS2 (test%L1,%0,%1);
-}")
+}"
+ [(set_attr "type" "compare")])
(define_insn ""
[(set (cc0)
@@ -805,7 +865,8 @@
return AS2 (test%W0,%1,%0);
return AS2 (test%W1,%0,%1);
-}")
+}"
+ [(set_attr "type" "compare")])
(define_insn ""
[(set (cc0)
@@ -818,7 +879,8 @@
return AS2 (test%B0,%1,%0);
return AS2 (test%B1,%0,%1);
-}")
+}"
+ [(set_attr "type" "compare")])
;; move instructions.
;; There is one for each machine mode,
@@ -829,13 +891,15 @@
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "nonmemory_operand" "rn"))]
"flag_pic"
- "* return AS1 (push%L0,%1);")
+ "* return AS1 (push%L0,%1);"
+ [(set_attr "memory" "store")])
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "nonmemory_operand" "ri"))]
"!flag_pic"
- "* return AS1 (push%L0,%1);")
+ "* return AS1 (push%L0,%1);"
+ [(set_attr "memory" "store")])
;; On a 386, it is faster to push MEM directly.
@@ -843,7 +907,9 @@
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "memory_operand" "m"))]
"TARGET_PUSH_MEMORY"
- "* return AS1 (push%L0,%1);")
+ "* return AS1 (push%L0,%1);"
+ [(set_attr "type" "memory")
+ (set_attr "memory" "load")])
;; General case of fullword move.
@@ -863,7 +929,7 @@
/* Don't generate memory->memory moves, go through a register */
else if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -874,18 +940,24 @@
;; On i486, incl reg is faster than movl $1,reg.
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=g,r")
- (match_operand:SI 1 "general_operand" "rn,im"))]
+ [(set (match_operand:SI 0 "general_operand" "=g,r,r")
+ (match_operand:SI 1 "general_operand" "rn,i,m"))]
"((!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
|| (GET_CODE (operands[1]) != MEM))
&& flag_pic"
"*
{
rtx link;
- if (operands[1] == const0_rtx && REG_P (operands[0]))
+
+ /* K6: mov reg,0 is slightly faster than xor reg,reg but is 3 bytes
+ longer. */
+ if ((ix86_cpu != PROCESSOR_K6 || optimize_size)
+ && operands[1] == const0_rtx && REG_P (operands[0]))
return AS2 (xor%L0,%0,%0);
if (operands[1] == const1_rtx
+ /* PPRO and K6 prefer mov to inc to reduce dependencies. */
+ && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
&& (link = find_reg_note (insn, REG_WAS_0, 0))
/* Make sure the insn that stored the 0 is still present. */
&& ! INSN_DELETED_P (XEXP (link, 0))
@@ -901,7 +973,9 @@
return AS2 (lea%L0,%a1,%0);
return AS2 (mov%L0,%1,%0);
-}")
+}"
+ [(set_attr "type" "integer,integer,memory")
+ (set_attr "memory" "*,*,load")])
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g,r")
@@ -912,10 +986,18 @@
"*
{
rtx link;
+
+ /* Use of xor was disabled for AMD K6 as recommended by the Optimization
+ Manual. My test shows, that this generally hurts the performance, because
+ mov is longer and takes longer to decode and decoding is the main
+ bottleneck of K6 when executing GCC code. */
+
if (operands[1] == const0_rtx && REG_P (operands[0]))
return AS2 (xor%L0,%0,%0);
if (operands[1] == const1_rtx
+ /* PPRO and K6 prefer mov to inc to reduce dependencies. */
+ && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
&& (link = find_reg_note (insn, REG_WAS_0, 0))
/* Make sure the insn that stored the 0 is still present. */
&& ! INSN_DELETED_P (XEXP (link, 0))
@@ -928,19 +1010,25 @@
return AS1 (inc%L0,%0);
return AS2 (mov%L0,%1,%0);
-}")
+}"
+ [(set_attr "type" "integer,memory")
+ (set_attr "memory" "*,load")])
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "nonmemory_operand" "ri"))]
""
- "* return AS1 (push%W0,%1);")
+ "* return AS1 (push%W0,%1);"
+ [(set_attr "type" "memory")
+ (set_attr "memory" "store")])
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "memory_operand" "m"))]
"TARGET_PUSH_MEMORY"
- "* return AS1 (push%W0,%1);")
+ "* return AS1 (push%W0,%1);"
+ [(set_attr "type" "memory")
+ (set_attr "memory" "load")])
;; On i486, an incl and movl are both faster than incw and movw.
@@ -952,7 +1040,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -971,6 +1059,8 @@
return AS2 (xor%L0,%k0,%k0);
if (REG_P (operands[0]) && operands[1] == const1_rtx
+ /* PPRO and K6 prefer mov to inc to reduce dependencies. */
+ && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
&& (link = find_reg_note (insn, REG_WAS_0, 0))
/* Make sure the insn that stored the 0 is still present. */
&& ! INSN_DELETED_P (XEXP (link, 0))
@@ -989,7 +1079,7 @@
operands[1] = i386_sext16_if_const (operands[1]);
return AS2 (mov%L0,%k1,%k0);
}
- if (TARGET_PENTIUMPRO)
+ if (! TARGET_ZERO_EXTEND_WITH_AND)
{
/* movzwl is faster than movw on the Pentium Pro,
* although not as fast as an aligned movl. */
@@ -1002,7 +1092,9 @@
}
return AS2 (mov%W0,%1,%0);
-}")
+}"
+ [(set_attr "type" "integer,memory")
+ (set_attr "memory" "*,load")])
(define_expand "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
@@ -1012,7 +1104,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -1027,10 +1119,18 @@
"*
{
rtx link;
+
+ /* Use of xor was disabled for AMD K6 as recommended by the Optimization
+ Manual. My test shows, that this generally hurts the performance, because
+ mov is longer and takes longer to decode and decoding is the main
+ bottleneck of K6 when executing GCC code. */
+
if (operands[1] == const0_rtx && REG_P (operands[0]))
return AS2 (xor%W0,%0,%0);
if (operands[1] == const1_rtx
+ /* PPRO and K6 prefer mov to inc to reduce dependencies. */
+ && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
&& (link = find_reg_note (insn, REG_WAS_0, 0))
/* Make sure the insn that stored the 0 is still present. */
&& ! INSN_DELETED_P (XEXP (link, 0))
@@ -1043,7 +1143,8 @@
return AS1 (inc%W0,%0);
return AS2 (mov%W0,%1,%0);
-}")
+}"
+ [(set_attr "type" "integer,memory")])
;; emit_push_insn when it calls move_by_pieces
;; requires an insn to "push a byte".
@@ -1078,7 +1179,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -1093,10 +1194,12 @@
"*
{
rtx link;
- if (operands[1] == const0_rtx && REG_P (operands[0]))
- return AS2 (xor%L0,%k0,%k0);
+
+ /* movb $0,reg8 is 2 bytes, the same as xorl reg8,reg8.
+ It is at least as fast as xor on any processor except a Pentium. */
if (operands[1] == const1_rtx
+ && TARGET_PENTIUM
&& (link = find_reg_note (insn, REG_WAS_0, 0))
/* Make sure the insn that stored the 0 is still present. */
&& ! INSN_DELETED_P (XEXP (link, 0))
@@ -1138,7 +1241,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -1153,10 +1256,11 @@
"*
{
rtx link;
- if (operands[1] == const0_rtx && REG_P (operands[0]))
- return AS2 (xor%B0,%0,%0);
+
+ /* movb $0,reg8 is 2 bytes, the same as xorl reg8,reg8. */
if (operands[1] == const1_rtx
+ && TARGET_PENTIUM
&& ! NON_QI_REG_P (operands[0])
&& (link = find_reg_note (insn, REG_WAS_0, 0))
/* Make sure the insn that stored the 0 is still present. */
@@ -1182,7 +1286,8 @@
(define_insn "movsf_push"
[(set (match_operand:SF 0 "push_operand" "=<,<")
(match_operand:SF 1 "general_operand" "*rfF,m"))]
- "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
+ "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM
+ || reload_in_progress || reload_completed"
"*
{
if (STACK_REG_P (operands[1]))
@@ -1209,11 +1314,15 @@
return AS1 (push%L0,%1);
}")
-(define_insn "movsf_push_memory"
- [(set (match_operand:SF 0 "push_operand" "=<")
- (match_operand:SF 1 "memory_operand" "m"))]
- "TARGET_PUSH_MEMORY"
- "* return AS1 (push%L0,%1);")
+(define_split
+ [(set (match_operand:SF 0 "push_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ "reload_completed && STACK_REG_P (operands[1])"
+ [(set (reg:SI 7)
+ (minus:SI (reg:SI 7) (const_int 4)))
+ (set (mem:SF (reg:SI 7))
+ (match_dup 1))]
+ "")
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
@@ -1223,7 +1332,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -1231,34 +1340,21 @@
}
/* 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. */
+ into a register, force the value to memory now, since we'll
+ get better code out the back end. */
else if ((reload_in_progress | reload_completed) == 0
- && GET_CODE (operands[0]) != MEM
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && !standard_80387_constant_p (operands[1]))
+ && GET_CODE (operands[0]) != MEM
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && !standard_80387_constant_p (operands[1]))
{
- rtx insn, note, fp_const;
-
- fp_const = force_const_mem (SFmode, operands[1]);
- if (flag_pic)
- current_function_uses_pic_offset_table = 1;
-
- insn = emit_insn (gen_rtx_SET (SFmode, operands[0], fp_const));
- note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-
- if (note)
- XEXP (note, 0) = operands[1];
- else
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
}
}")
;; For the purposes of regclass, prefer FLOAT_REGS.
(define_insn ""
- [(set (match_operand:SF 0 "nonimmediate_operand" "=*rfm,*rf,f,!*rm")
- (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r,!m")
+ (match_operand:SF 1 "general_operand" "fmG,f,*rmF,*rF"))]
"(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
"*
{
@@ -1274,20 +1370,6 @@
return AS1 (fld,%y0);
}
- /* Handle a transfer between the 387 and a 386 register */
-
- if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
- RET;
- }
-
- if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
- {
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
-
/* Handle other kinds of writes from the 387 */
if (STACK_TOP_P (operands[1]))
@@ -1327,10 +1409,12 @@
return AS1 (fxch,%0);
}")
+
(define_insn "movdf_push"
[(set (match_operand:DF 0 "push_operand" "=<,<")
(match_operand:DF 1 "general_operand" "*rfF,o"))]
- "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
+ "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM
+ || reload_in_progress || reload_completed"
"*
{
if (STACK_REG_P (operands[1]))
@@ -1357,11 +1441,15 @@
return output_move_double (operands);
}")
-(define_insn "movdf_push_memory"
- [(set (match_operand:DF 0 "push_operand" "=<")
- (match_operand:DF 1 "memory_operand" "o"))]
- "TARGET_PUSH_MEMORY"
- "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode),0,0);")
+(define_split
+ [(set (match_operand:DF 0 "push_operand" "")
+ (match_operand:DF 1 "register_operand" ""))]
+ "reload_completed && STACK_REG_P (operands[1])"
+ [(set (reg:SI 7)
+ (minus:SI (reg:SI 7) (const_int 8)))
+ (set (mem:DF (reg:SI 7))
+ (match_dup 1))]
+ "")
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
@@ -1371,7 +1459,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -1383,30 +1471,18 @@
optimized into stores of constants if the target eventually moves to
memory, but better safe than sorry. */
else if ((reload_in_progress | reload_completed) == 0
- && GET_CODE (operands[0]) != MEM
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && !standard_80387_constant_p (operands[1]))
+ && GET_CODE (operands[0]) != MEM
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && !standard_80387_constant_p (operands[1]))
{
- rtx insn, note, fp_const;
-
- fp_const = force_const_mem (DFmode, operands[1]);
- if (flag_pic)
- current_function_uses_pic_offset_table = 1;
-
- insn = emit_insn (gen_rtx_SET (DFmode, operands[0], fp_const));
- note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-
- if (note)
- XEXP (note, 0) = operands[1];
- else
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
+ operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
}
}")
;; For the purposes of regclass, prefer FLOAT_REGS.
(define_insn ""
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm")
- (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r,!o")
+ (match_operand:DF 1 "general_operand" "fmG,f,*roF,*rF"))]
"(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
|| (GET_CODE (operands[1]) != MEM)"
"*
@@ -1423,20 +1499,6 @@
return AS1 (fld,%y0);
}
- /* Handle a transfer between the 387 and a 386 register */
-
- if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
- RET;
- }
-
- if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
- {
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
-
/* Handle other kinds of writes from the 387 */
if (STACK_TOP_P (operands[1]))
@@ -1480,7 +1542,8 @@
(define_insn "movxf_push"
[(set (match_operand:XF 0 "push_operand" "=<,<")
(match_operand:XF 1 "general_operand" "*rfF,o"))]
- "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
+ "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM
+ || reload_in_progress || reload_completed"
"*
{
if (STACK_REG_P (operands[1]))
@@ -1506,11 +1569,15 @@
return output_move_double (operands);
}")
-(define_insn "movxf_push_memory"
- [(set (match_operand:XF 0 "push_operand" "=<")
- (match_operand:XF 1 "memory_operand" "o"))]
- "TARGET_PUSH_MEMORY"
- "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode),0,0);")
+(define_split
+ [(set (match_operand:XF 0 "push_operand" "")
+ (match_operand:XF 1 "register_operand" ""))]
+ "reload_completed && STACK_REG_P (operands[1])"
+ [(set (reg:SI 7)
+ (minus:SI (reg:SI 7) (const_int 12)))
+ (set (mem:XF (reg:SI 7))
+ (match_dup 1))]
+ "")
(define_expand "movxf"
[(set (match_operand:XF 0 "general_operand" "")
@@ -1520,7 +1587,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -1532,30 +1599,18 @@
be optimized into stores of constants if the target eventually moves
to memory, but better safe than sorry. */
else if ((reload_in_progress | reload_completed) == 0
- && GET_CODE (operands[0]) != MEM
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && !standard_80387_constant_p (operands[1]))
+ && GET_CODE (operands[0]) != MEM
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && !standard_80387_constant_p (operands[1]))
{
- rtx insn, note, fp_const;
-
- fp_const = force_const_mem (XFmode, operands[1]);
- if (flag_pic)
- current_function_uses_pic_offset_table = 1;
-
- insn = emit_insn (gen_rtx_SET (XFmode, operands[0], fp_const));
- note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-
- if (note)
- XEXP (note, 0) = operands[1];
- else
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
+ operands[1] = validize_mem (force_const_mem (XFmode, operands[1]));
}
}")
(define_insn ""
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm")
- (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!*r,!o")
+ (match_operand:XF 1 "general_operand" "fmG,f,*roF,*rF"))]
"(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
|| (GET_CODE (operands[1]) != MEM)"
"*
@@ -1572,20 +1627,6 @@
return AS1 (fld,%y0);
}
- /* Handle a transfer between the 387 and a 386 register */
-
- if (STACK_TOP_P (operands[0]) && NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
- RET;
- }
-
- if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
- {
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
-
/* Handle other kinds of writes from the 387 */
if (STACK_TOP_P (operands[1]))
@@ -1644,7 +1685,7 @@
{
/* Don't generate memory->memory moves, go through a register */
if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
+ && no_new_pseudos == 0
&& GET_CODE (operands[0]) == MEM
&& GET_CODE (operands[1]) == MEM)
{
@@ -1657,8 +1698,44 @@
(match_operand:DI 1 "general_operand" "riF,m"))]
"(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
|| (GET_CODE (operands[1]) != MEM)"
- "* return output_move_double (operands);")
+ "* return output_move_double (operands);"
+ [(set_attr "type" "integer,memory")
+ (set_attr "memory" "*,load")])
+
+(define_split
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ "reload_completed
+ && (offsettable_memref_p (operands[0])
+ || nonmemory_operand (operands[0], DImode))
+ && (offsettable_memref_p (operands[1])
+ || nonmemory_operand (operands[1], DImode))
+ && (! reg_overlap_mentioned_p (gen_lowpart (SImode, operands[0]),
+ operands[1])
+ || ! reg_overlap_mentioned_p (gen_highpart (SImode, operands[0]),
+ operands[1]))"
+ [(set (match_dup 2)
+ (match_dup 4))
+ (set (match_dup 3)
+ (match_dup 5))]
+ "
+{
+ split_di (&operands[0], 1, &operands[2], &operands[3]);
+ split_di (&operands[1], 1, &operands[4], &operands[5]);
+
+ if (reg_overlap_mentioned_p (operands[2], operands[1]))
+ {
+ rtx tmp;
+ tmp = operands[2];
+ operands[2] = operands[3];
+ operands[3] = tmp;
+
+ tmp = operands[4];
+ operands[4] = operands[5];
+ operands[5] = tmp;
+ }
+}")
;;- conversion instructions
;;- NONE
@@ -1666,10 +1743,25 @@
;;- zero extension instructions
;; See comments by `andsi' for when andl is faster than movzx.
-(define_insn "zero_extendhisi2"
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
+ ""
+ "")
+
+;; When optimizing for the PPro/PII or code size, always use movzwl.
+;; We want to use a different pattern so we can use different constraints
+;; than the generic pattern.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
+ "(optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
+ "* return AS2 (movz%W0%L0,%1,%0);")
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,&r,?r")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))]
- ""
+ "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
"*
{
rtx xops[2];
@@ -1730,10 +1822,23 @@
(const_int 65535)))]
"operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));")
-(define_insn "zero_extendqihi2"
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ "optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO"
+
+ "* return AS2 (movz%B0%W0,%1,%0);")
+
+(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=q,&q,?r")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
- ""
+ "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
"*
{
rtx xops[2];
@@ -1811,10 +1916,22 @@
FAIL;
operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
-(define_insn "zero_extendqisi2"
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ "optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO"
+ "* return AS2 (movz%B0%L0,%1,%0);")
+
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=q,&q,?r")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
- ""
+ "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
"*
{
rtx xops[2];
@@ -1899,58 +2016,105 @@
"operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));")
(define_insn "zero_extendsidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m")
- (zero_extend:DI (match_operand:SI 1 "register_operand" "0,rm,r")))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o")
+ (zero_extend:DI (match_operand:SI 1 "general_operand" "0,rm,r")))]
""
- "*
- {
- rtx high[2], low[2], xops[4];
-
- if (REG_P (operands[0]) && REG_P (operands[1])
- && REGNO (operands[0]) == REGNO (operands[1]))
- {
- operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- return AS2 (xor%L0,%0,%0);
- }
-
- split_di (operands, 1, low, high);
- xops[0] = low[0];
- xops[1] = operands[1];
- xops[2] = high[0];
- xops[3] = const0_rtx;
-
- output_asm_insn (AS2 (mov%L0,%1,%0), xops);
- if (GET_CODE (low[0]) == MEM)
- output_asm_insn (AS2 (mov%L2,%3,%2), xops);
- else
- output_asm_insn (AS2 (xor%L2,%2,%2), xops);
+ "#")
- RET;
-}")
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
+ "reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])"
+ [(set (match_dup 4) (const_int 0))]
+ "split_di (&operands[0], 1, &operands[3], &operands[4]);")
+
+(define_split
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (zero_extend:DI (match_operand:SI 1 "general_operand" "")))]
+ "reload_completed"
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 4) (const_int 0))]
+ "split_di (&operands[0], 1, &operands[3], &operands[4]);")
;;- sign extension instructions
(define_insn "extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (sign_extend:DI (match_operand:SI 1 "register_operand" "0")))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=A,?r,?Ar,*o")
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,*r")))
+ (clobber (match_scratch:SI 2 "=X,X,X,&r"))]
""
- "*
+ "#")
+
+;; Extend to memory case when source register does die.
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_operand:SI 2 "register_operand" ""))]
+ "(flow2_completed
+ && dead_or_set_p (insn, operands[1])
+ && !reg_mentioned_p (operands[1], operands[0]))"
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
+ (set (match_dup 4) (match_dup 1))]
+ "split_di (&operands[0], 1, &operands[3], &operands[4]);")
+
+;; Extend to memory case when source register does not die.
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_operand:SI 2 "register_operand" ""))]
+ "flow2_completed"
+ [(const_int 0)]
+ "
{
- if (REGNO (operands[0]) == 0)
+ split_di (&operands[0], 1, &operands[3], &operands[4]);
+
+ emit_move_insn (operands[3], operands[1]);
+
+ /* Generate a cltd if possible and doing so it profitable. */
+ if (true_regnum (operands[1]) == 0
+ && true_regnum (operands[2]) == 1
+ && (optimize_size || !TARGET_PENTIUM))
{
- /* This used to be cwtl, but that extends HI to SI somehow. */
-#ifdef INTEL_SYNTAX
- return \"cdq\";
-#else
- return \"cltd\";
-#endif
+ emit_insn (gen_ashrsi3_31 (operands[2], operands[1]));
+ }
+ else
+ {
+ emit_move_insn (operands[2], operands[1]);
+ emit_insn (gen_ashrsi3_31 (operands[2], operands[2]));
}
+ emit_move_insn (operands[4], operands[2]);
+ DONE;
+}")
- operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- output_asm_insn (AS2 (mov%L0,%0,%1), operands);
+;; Extend to register case. Optimize case where source and destination
+;; registers match and cases where we can use cltd.
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_scratch:SI 2 ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "
+{
+ split_di (&operands[0], 1, &operands[3], &operands[4]);
- operands[0] = GEN_INT (31);
- return AS2 (sar%L1,%0,%1);
+ if (true_regnum (operands[3]) != true_regnum (operands[1]))
+ emit_move_insn (operands[3], operands[1]);
+
+ /* Generate a cltd if possible and doing so it profitable. */
+ if (true_regnum (operands[3]) == 0
+ && (optimize_size || !TARGET_PENTIUM))
+ {
+ emit_insn (gen_ashrsi3_31 (operands[4], operands[3]));
+ DONE;
+ }
+
+ if (true_regnum (operands[4]) != true_regnum (operands[1]))
+ emit_move_insn (operands[4], operands[1]);
+
+ emit_insn (gen_ashrsi3_31 (operands[4], operands[4]));
+ DONE;
}")
;; Note that the i386 programmers' manual says that the opcodes
@@ -1964,7 +2128,8 @@
"*
{
if (REGNO (operands[0]) == 0
- && REG_P (operands[1]) && REGNO (operands[1]) == 0)
+ && REG_P (operands[1]) && REGNO (operands[1]) == 0
+ && (optimize_size || ix86_cpu != PROCESSOR_K6))
#ifdef INTEL_SYNTAX
return \"cwde\";
#else
@@ -1985,7 +2150,8 @@
"*
{
if (REGNO (operands[0]) == 0
- && REG_P (operands[1]) && REGNO (operands[1]) == 0)
+ && REG_P (operands[1]) && REGNO (operands[1]) == 0
+ && (optimize_size || ix86_cpu != PROCESSOR_K6))
return \"cbtw\";
#ifdef INTEL_SYNTAX
@@ -2069,110 +2235,237 @@
;; Conversions between float and double.
-(define_insn "extendsfdf2"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=fm,f")
- (float_extend:DF
- (match_operand:SF 1 "nonimmediate_operand" "f,fm")))]
+(define_expand "extendsfdf2"
+ [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (float_extend:DF
+ (match_operand:SF 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))
+ (clobber (match_dup 3))])]
"TARGET_80387"
+ "
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ operands[1] = force_reg (SFmode, operands[1]);
+
+ operands[2] = assign_386_stack_local (SFmode, 0);
+ operands[3] = assign_386_stack_local (DFmode, 0);
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!f,!*r")
+ (float_extend:DF
+ (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m"))
+ (clobber (match_operand:DF 3 "memory_operand" "m,m,m,o"))]
+ "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != MEM)"
"*
{
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+ output_float_extend (insn, operands);
+ return \"\";
+}"
+ [(set_attr "type" "fld,fpop,fld,fpop")])
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
- RET;
- }
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))
+ (clobber (match_operand:DF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float_extend:DF (match_dup 2)))]
+ "")
- if (NON_STACK_REG_P (operands[0]))
- {
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))
+ (clobber (match_operand:DF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
+ [(set (match_dup 3)
+ (float_extend:DF (match_dup 1)))
+ (set (match_dup 0)
+ (match_dup 3))]
+ "")
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
+(define_split
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))
+ (clobber (match_operand:DF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float_extend:DF (match_dup 1)))]
+ "")
- if (GET_CODE (operands[0]) == MEM)
- {
- if (stack_top_dies)
- return AS1 (fstp%z0,%y0);
- else
- return AS1 (fst%z0,%y0);
- }
+(define_insn ""
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != MEM)"
+ "*
+{
+ output_float_extend (insn, operands);
+ return \"\";
+}"
+ [(set_attr "type" "fld,fpop")])
+
+(define_expand "extenddfxf2"
+ [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (float_extend:XF
+ (match_operand:DF 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))
+ (clobber (match_dup 3))])]
+ "TARGET_80387"
+ "
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ operands[1] = force_reg (DFmode, operands[1]);
- abort ();
+ operands[2] = assign_386_stack_local (DFmode, 0);
+ operands[3] = assign_386_stack_local (XFmode, 0);
}")
-(define_insn "extenddfxf2"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r")
(float_extend:XF
- (match_operand:DF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
- "TARGET_80387"
+ (match_operand:DF 1 "nonimmediate_operand" "fm,f,*r,f")))
+ (clobber (match_operand:DF 2 "memory_operand" "m,m,o,m"))
+ (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))]
+ "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != MEM)"
"*
{
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+ output_float_extend (insn, operands);
+ return \"\";
+}"
+ [(set_attr "type" "fld,fpop,fld,fpop")])
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
- RET;
- }
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (clobber (match_operand:DF 2 "memory_operand" ""))
+ (clobber (match_operand:XF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float_extend:XF (match_dup 2)))]
+ "")
- if (NON_STACK_REG_P (operands[0]))
- {
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float_extend:XF (match_operand:DF 1 "register_operand" "")))
+ (clobber (match_operand:DF 2 "memory_operand" ""))
+ (clobber (match_operand:XF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
+ [(set (match_dup 3)
+ (float_extend:XF (match_dup 1)))
+ (set (match_dup 0)
+ (match_dup 3))]
+ "")
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
+(define_split
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))
+ (clobber (match_operand:DF 2 "memory_operand" ""))
+ (clobber (match_operand:XF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float_extend:XF (match_dup 1)))]
+ "")
- if (GET_CODE (operands[0]) == MEM)
- {
- output_asm_insn (AS1 (fstp%z0,%y0), operands);
- if (! stack_top_dies)
- return AS1 (fld%z0,%y0);
- RET;
- }
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
+ (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != MEM)"
+ "*
+{
+ output_float_extend (insn, operands);
+ return \"\";
+}"
+ [(set_attr "type" "fld,fpop")])
+
+(define_expand "extendsfxf2"
+ [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (float_extend:XF
+ (match_operand:SF 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))
+ (clobber (match_dup 3))])]
+ "TARGET_80387"
+ "
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ operands[1] = force_reg (SFmode, operands[1]);
- abort ();
+ operands[2] = assign_386_stack_local (SFmode, 0);
+ operands[3] = assign_386_stack_local (XFmode, 0);
}")
-(define_insn "extendsfxf2"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r")
(float_extend:XF
- (match_operand:SF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
- "TARGET_80387"
+ (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m"))
+ (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))]
+ "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != MEM)"
"*
{
- int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
-
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fld%z0,%y1));
- RET;
- }
+ output_float_extend (insn, operands);
+ return \"\";
+}"
+ [(set_attr "type" "fld,fpop,fld,fpop")])
- if (NON_STACK_REG_P (operands[0]))
- {
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))
+ (clobber (match_operand:XF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float_extend:XF (match_dup 2)))]
+ "")
- if (STACK_TOP_P (operands[0]))
- return AS1 (fld%z1,%y1);
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float_extend:XF (match_operand:SF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))
+ (clobber (match_operand:XF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
+ [(set (match_dup 3)
+ (float_extend:XF (match_dup 1)))
+ (set (match_dup 0)
+ (match_dup 3))]
+ "")
- if (GET_CODE (operands[0]) == MEM)
- {
- output_asm_insn (AS1 (fstp%z0,%y0), operands);
- if (! stack_top_dies)
- return AS1 (fld%z0,%y0);
- RET;
- }
+(define_split
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))
+ (clobber (match_operand:XF 3 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float_extend:XF (match_dup 1)))]
+ "")
- abort ();
-}")
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
+ (float_extend:XF
+ (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_80387 && (GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != MEM)"
+ "*
+{
+ output_float_extend (insn, operands);
+ return \"\";
+}"
+ [(set_attr "type" "fld,fpop")])
(define_expand "truncdfsf2"
[(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
@@ -2185,480 +2478,764 @@
operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
}")
-;; This cannot output into an f-reg because there is no way to be sure
-;; of truncating in that case. Otherwise this is just like a simple move
-;; insn. So we pretend we can output to a reg in order to get better
-;; register preferencing, but we really use a stack slot.
-
(define_insn ""
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
(float_truncate:SF
- (match_operand:DF 1 "register_operand" "0,f")))
- (clobber (match_operand:SF 2 "memory_operand" "m,m"))]
+ (match_operand:DF 1 "register_operand" "0,f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
"TARGET_80387"
"*
{
int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+ rtx xops[1];
- if (GET_CODE (operands[0]) == MEM)
- {
- if (stack_top_dies)
- return AS1 (fstp%z0,%0);
- else
- return AS1 (fst%z0,%0);
- }
- else if (STACK_TOP_P (operands[0]))
- {
- output_asm_insn (AS1 (fstp%z2,%y2), operands);
- return AS1 (fld%z2,%y2);
- }
+ xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
+
+ if (stack_top_dies || STACK_REG_P (operands[0]))
+ output_asm_insn (AS1 (fstp%z0,%0), xops);
else
- abort ();
-}")
+ output_asm_insn (AS1 (fst%z0,%0), xops);
-(define_insn "truncxfsf2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,!*r")
- (float_truncate:SF
- (match_operand:XF 1 "register_operand" "f,f")))]
+ if (STACK_REG_P (operands[0]))
+ return AS1 (fld%z2,%2);
+ else if (NON_STACK_REG_P (operands[0]))
+ return AS2 (mov%L0,%2,%0);
+
+ return \"\";
+}"
+ [(set_attr "type" "fpop")])
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (float_truncate:SF (match_dup 1)))
+ (set (match_dup 0)
+ (match_dup 2))]
+ "")
+
+(define_split
+ [(set (match_operand:SF 0 "memory_operand" "")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float_truncate:SF (match_dup 1)))]
+ "")
+
+;; This cannot output into an f-reg because there is no way to be sure
+;; of truncating in that case.
+
+(define_insn ""
+ [(set (match_operand:SF 0 "memory_operand" "=m")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
"TARGET_80387"
"*
{
int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
- if (NON_STACK_REG_P (operands[0]))
- {
- if (stack_top_dies == 0)
- {
- output_asm_insn (AS1 (fld,%y1), operands);
- stack_top_dies = 1;
- }
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
- else if (GET_CODE (operands[0]) == MEM)
- {
- if (stack_top_dies)
- return AS1 (fstp%z0,%0);
- else
- {
- output_asm_insn (AS1 (fld,%y1), operands);
- return AS1 (fstp%z0,%0);
- }
- }
+ if (stack_top_dies)
+ return AS1 (fstp%z0,%0);
else
- abort ();
+ return AS1 (fst%z0,%0);
+}"
+ [(set_attr "type" "fpop")])
+
+(define_expand "truncxfsf2"
+ [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (float_truncate:SF
+ (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_dup 2))])]
+ "TARGET_80387"
+ "
+{
+ operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
}")
-(define_insn "truncxfdf2"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!*r")
- (float_truncate:DF
- (match_operand:XF 1 "register_operand" "f,f")))]
+(define_insn ""
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
+ (float_truncate:SF
+ (match_operand:XF 1 "register_operand" "0,f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
"TARGET_80387"
"*
{
int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+ rtx xops[1];
- if (NON_STACK_REG_P (operands[0]))
- {
- if (stack_top_dies == 0)
- {
- output_asm_insn (AS1 (fld,%y1), operands);
- stack_top_dies = 1;
- }
- output_to_reg (operands[0], stack_top_dies, 0);
- RET;
- }
- else if (GET_CODE (operands[0]) == MEM)
- {
- if (stack_top_dies)
- return AS1 (fstp%z0,%0);
- else
- {
- output_asm_insn (AS1 (fld,%y1), operands);
- return AS1 (fstp%z0,%0);
- }
- }
+ xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
+
+ if (stack_top_dies || STACK_REG_P (operands[0]))
+ output_asm_insn (AS1 (fstp%z0,%0), xops);
else
- abort ();
-}")
+ output_asm_insn (AS1 (fst%z0,%0), xops);
-
-;; The 387 requires that the stack top dies after converting to DImode.
+ if (STACK_REG_P (operands[0]))
+ return AS1 (fld%z2,%2);
+ else if (NON_STACK_REG_P (operands[0]))
+ return AS2 (mov%L0,%2,%0);
-;; Represent an unsigned conversion from SImode to MODE_FLOAT by first
-;; doing a signed conversion to DImode, and then taking just the low
-;; part.
+ return \"\";
+}"
+ [(set_attr "type" "fpop")])
-(define_expand "fixuns_truncxfsi2"
- [(set (match_dup 4)
- (match_operand:XF 1 "register_operand" ""))
- (parallel [(set (match_dup 2)
- (fix:DI (fix:XF (match_dup 4))))
- (clobber (match_dup 4))
- (clobber (match_dup 5))
- (clobber (match_dup 6))
- (clobber (match_scratch:SI 7 ""))])
- (set (match_operand:SI 0 "general_operand" "")
- (match_dup 3))]
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (float_truncate:SF (match_dup 1)))
+ (set (match_dup 0)
+ (match_dup 2))]
+ "")
+
+(define_split
+ [(set (match_operand:SF 0 "memory_operand" "")
+ (float_truncate:SF (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_operand:SF 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float_truncate:SF (match_dup 1)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "memory_operand" "=m")
+ (float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
"TARGET_80387"
- "
+ "*
{
- operands[2] = gen_reg_rtx (DImode);
- operands[3] = gen_lowpart (SImode, operands[2]);
- operands[4] = gen_reg_rtx (XFmode);
- operands[5] = (rtx) assign_386_stack_local (SImode, 0);
- operands[6] = (rtx) assign_386_stack_local (DImode, 1);
-}")
+ int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
-(define_expand "fixuns_truncdfsi2"
- [(set (match_dup 4)
- (match_operand:DF 1 "register_operand" ""))
- (parallel [(set (match_dup 2)
- (fix:DI (fix:DF (match_dup 4))))
- (clobber (match_dup 4))
- (clobber (match_dup 5))
- (clobber (match_dup 6))
- (clobber (match_scratch:SI 7 ""))])
- (set (match_operand:SI 0 "general_operand" "")
- (match_dup 3))]
+ if (stack_top_dies)
+ return AS1 (fstp%z0,%0);
+ else
+ return AS1 (fst%z0,%0);
+}"
+ [(set_attr "type" "fpop")])
+
+(define_expand "truncxfdf2"
+ [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (float_truncate:DF
+ (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_dup 2))])]
"TARGET_80387"
"
{
- operands[2] = gen_reg_rtx (DImode);
- operands[3] = gen_lowpart (SImode, operands[2]);
- operands[4] = gen_reg_rtx (DFmode);
- operands[5] = (rtx) assign_386_stack_local (SImode, 0);
- operands[6] = (rtx) assign_386_stack_local (DImode, 1);
+ operands[2] = (rtx) assign_386_stack_local (DFmode, 0);
}")
-(define_expand "fixuns_truncsfsi2"
- [(set (match_dup 4)
- (match_operand:SF 1 "register_operand" ""))
- (parallel [(set (match_dup 2)
- (fix:DI (fix:SF (match_dup 4))))
- (clobber (match_dup 4))
- (clobber (match_dup 5))
- (clobber (match_dup 6))
- (clobber (match_scratch:SI 7 ""))])
- (set (match_operand:SI 0 "general_operand" "")
- (match_dup 3))]
+(define_insn ""
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r")
+ (float_truncate:DF
+ (match_operand:XF 1 "register_operand" "0,f,f")))
+ (clobber (match_operand:DF 2 "memory_operand" "m,m,o"))]
"TARGET_80387"
- "
+ "*
{
- operands[2] = gen_reg_rtx (DImode);
- operands[3] = gen_lowpart (SImode, operands[2]);
- operands[4] = gen_reg_rtx (SFmode);
- operands[5] = (rtx) assign_386_stack_local (SImode, 0);
- operands[6] = (rtx) assign_386_stack_local (DImode, 1);
-}")
+ int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
+ rtx xops[2];
-;; Signed conversion to DImode.
+ xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
-(define_expand "fix_truncxfdi2"
+ if (stack_top_dies || STACK_REG_P (operands[0]))
+ output_asm_insn (AS1 (fstp%z0,%0), xops);
+ else
+ output_asm_insn (AS1 (fst%z0,%0), xops);
+
+ if (STACK_REG_P (operands[0]))
+ return AS1 (fld%z2,%2);
+ else if (NON_STACK_REG_P (operands[0]))
+ {
+ xops[0] = operands[0];
+ xops[1] = operands[2];
+ output_asm_insn (output_move_double (xops), xops);
+ }
+
+ return \"\";
+}"
+ [(set_attr "type" "fpop")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_operand:DF 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
[(set (match_dup 2)
- (match_operand:XF 1 "register_operand" ""))
- (parallel [(set (match_operand:DI 0 "general_operand" "")
- (fix:DI (fix:XF (match_dup 2))))
- (clobber (match_dup 2))
- (clobber (match_dup 3))
- (clobber (match_dup 4))
- (clobber (match_scratch:SI 5 ""))])]
+ (float_truncate:DF (match_dup 1)))
+ (set (match_dup 0)
+ (match_dup 2))]
+ "")
+
+(define_split
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (float_truncate:DF (match_operand:XF 1 "register_operand" "")))
+ (clobber (match_operand:DF 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float_truncate:DF (match_dup 1)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "memory_operand" "=m")
+ (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
"TARGET_80387"
- "
+ "*
{
- operands[1] = copy_to_mode_reg (XFmode, operands[1]);
- operands[2] = gen_reg_rtx (XFmode);
- operands[3] = (rtx) assign_386_stack_local (SImode, 0);
- operands[4] = (rtx) assign_386_stack_local (DImode, 1);
-}")
+ int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
-(define_expand "fix_truncdfdi2"
- [(set (match_dup 2)
- (match_operand:DF 1 "register_operand" ""))
- (parallel [(set (match_operand:DI 0 "general_operand" "")
- (fix:DI (fix:DF (match_dup 2))))
+ if (stack_top_dies)
+ return AS1 (fstp%z0,%0);
+ else
+ return AS1 (fst%z0,%0);
+}"
+ [(set_attr "type" "fpop")])
+
+;; Conversions between floating point and fix point.
+
+(define_expand "fix_truncsfsi2"
+ [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
- (clobber (match_scratch:SI 5 ""))])]
+ (clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
- operands[1] = copy_to_mode_reg (DFmode, operands[1]);
- operands[2] = gen_reg_rtx (DFmode);
- operands[3] = (rtx) assign_386_stack_local (SImode, 0);
- operands[4] = (rtx) assign_386_stack_local (DImode, 1);
+ operands[2] = (rtx) assign_386_stack_local (HImode, 0);
+ operands[3] = (rtx) assign_386_stack_local (HImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (SImode, 0);
}")
+(define_insn ""
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!r")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))
+ (clobber (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:SI 4 "memory_operand" "m,m"))
+ (clobber (match_scratch:HI 5 "=&r,&r"))]
+ "TARGET_80387"
+ "* return output_fix_trunc (insn, operands);"
+ [(set_attr "type" "fpop")])
+
(define_expand "fix_truncsfdi2"
- [(set (match_dup 2)
- (match_operand:SF 1 "register_operand" ""))
- (parallel [(set (match_operand:DI 0 "general_operand" "")
- (fix:DI (fix:SF (match_dup 2))))
+ [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
+ (clobber (match_dup 1))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
- (clobber (match_scratch:SI 5 ""))])]
+ (clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
operands[1] = copy_to_mode_reg (SFmode, operands[1]);
- operands[2] = gen_reg_rtx (SFmode);
- operands[3] = (rtx) assign_386_stack_local (SImode, 0);
- operands[4] = (rtx) assign_386_stack_local (DImode, 1);
+ operands[2] = (rtx) assign_386_stack_local (HImode, 0);
+ operands[3] = (rtx) assign_386_stack_local (HImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (DImode, 0);
}")
-;; These match a signed conversion of either DFmode or SFmode to DImode.
-
(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "+f"))))
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!r")
+ (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
(clobber (match_dup 1))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:DI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))
+ (clobber (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:DI 4 "memory_operand" "m,o"))
+ (clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
- "* return output_fix_trunc (insn, operands);")
+ "* return output_fix_trunc (insn, operands);"
+ [(set_attr "type" "fpop")])
-(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "+f"))))
- (clobber (match_dup 1))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:DI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
+(define_expand "fix_truncdfsi2"
+ [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" ""))))
+ (clobber (match_dup 2))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))
+ (clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
- "* return output_fix_trunc (insn, operands);")
+ "
+{
+ operands[2] = (rtx) assign_386_stack_local (HImode, 0);
+ operands[3] = (rtx) assign_386_stack_local (HImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (SImode, 0);
+}")
(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "+f"))))
- (clobber (match_dup 1))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:DI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!r")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))
+ (clobber (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:SI 4 "memory_operand" "m,m"))
+ (clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
- "* return output_fix_trunc (insn, operands);")
-
-;; Signed MODE_FLOAT conversion to SImode.
+ "* return output_fix_trunc (insn, operands);"
+ [(set_attr "type" "fpop")])
-(define_expand "fix_truncxfsi2"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- (fix:SI
- (fix:XF (match_operand:XF 1 "register_operand" ""))))
+(define_expand "fix_truncdfdi2"
+ [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
+ (clobber (match_dup 1))
(clobber (match_dup 2))
(clobber (match_dup 3))
- (clobber (match_scratch:SI 4 ""))])]
+ (clobber (match_dup 4))
+ (clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
- operands[2] = (rtx) assign_386_stack_local (SImode, 0);
- operands[3] = (rtx) assign_386_stack_local (DImode, 1);
+ operands[1] = copy_to_mode_reg (DFmode, operands[1]);
+ operands[2] = (rtx) assign_386_stack_local (HImode, 0);
+ operands[3] = (rtx) assign_386_stack_local (HImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (DImode, 0);
}")
-(define_expand "fix_truncdfsi2"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- (fix:SI
- (fix:DF (match_operand:DF 1 "register_operand" ""))))
+(define_insn ""
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!r")
+ (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
+ (clobber (match_dup 1))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))
+ (clobber (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:DI 4 "memory_operand" "m,o"))
+ (clobber (match_scratch:HI 5 "=&r,&r"))]
+ "TARGET_80387"
+ "* return output_fix_trunc (insn, operands);"
+ [(set_attr "type" "fpop")])
+
+(define_expand "fix_truncxfsi2"
+ [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (fix:SI (fix:XF (match_operand:XF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))
- (clobber (match_scratch:SI 4 ""))])]
+ (clobber (match_dup 4))
+ (clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
- operands[2] = (rtx) assign_386_stack_local (SImode, 0);
- operands[3] = (rtx) assign_386_stack_local (DImode, 1);
+ operands[2] = (rtx) assign_386_stack_local (HImode, 0);
+ operands[3] = (rtx) assign_386_stack_local (HImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (SImode, 0);
}")
-(define_expand "fix_truncsfsi2"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- (fix:SI
- (fix:SF (match_operand:SF 1 "register_operand" ""))))
+(define_insn ""
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!r")
+ (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f,f"))))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))
+ (clobber (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:SI 4 "memory_operand" "m,m"))
+ (clobber (match_scratch:HI 5 "=&r,&r"))]
+ "TARGET_80387"
+ "* return output_fix_trunc (insn, operands);"
+ [(set_attr "type" "fpop")])
+
+(define_expand "fix_truncxfdi2"
+ [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (fix:DI (fix:XF (match_operand:XF 1 "register_operand" ""))))
+ (clobber (match_dup 1))
(clobber (match_dup 2))
(clobber (match_dup 3))
- (clobber (match_scratch:SI 4 ""))])]
+ (clobber (match_dup 4))
+ (clobber (match_scratch:HI 5 ""))])]
"TARGET_80387"
"
{
- operands[2] = (rtx) assign_386_stack_local (SImode, 0);
- operands[3] = (rtx) assign_386_stack_local (DImode, 1);
+ operands[1] = copy_to_mode_reg (XFmode, operands[1]);
+ operands[2] = (rtx) assign_386_stack_local (HImode, 0);
+ operands[3] = (rtx) assign_386_stack_local (HImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (DImode, 0);
}")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:DI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!r")
+ (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f,f"))))
+ (clobber (match_dup 1))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))
+ (clobber (match_operand:HI 3 "memory_operand" "m,m"))
+ (clobber (match_operand:DI 4 "memory_operand" "m,o"))
+ (clobber (match_scratch:HI 5 "=&r,&r"))]
"TARGET_80387"
- "* return output_fix_trunc (insn, operands);")
+ "* return output_fix_trunc (insn, operands);"
+ [(set_attr "type" "fpop")])
+
+;; Conversion between fixed point and floating point.
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:DI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
+;; ??? Possibly represent floatunssidf2 here in gcc2.
+
+(define_expand "floatsisf2"
+ [(parallel [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
"TARGET_80387"
- "* return output_fix_trunc (insn, operands);")
+ "operands[2] = assign_386_stack_local (SImode, 0);")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
- (clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:DI 3 "memory_operand" "m"))
- (clobber (match_scratch:SI 4 "=&q"))]
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:SI 2 "memory_operand" "m,m"))]
"TARGET_80387"
- "* return output_fix_trunc (insn, operands);")
-
-;; Conversion between fixed point and floating point.
-;; The actual pattern that matches these is at the end of this file.
+ "#")
-;; ??? Possibly represent floatunssidf2 here in gcc2.
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:SI 1 "memory_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:SF (match_dup 1)))]
+ "")
-(define_expand "floatsisf2"
+(define_split
[(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ (float:SF (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:SF (match_dup 2)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:SI 1 "memory_operand" "m")))]
+ "TARGET_80387"
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
+
+(define_expand "floathisf2"
+ [(parallel [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:HI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
"TARGET_80387"
+ "operands[2] = assign_386_stack_local (HImode, 0);")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))]
+ "TARGET_80387"
+ "#")
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:HI 1 "memory_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:SF (match_dup 1)))]
"")
-(define_expand "floatdisf2"
+(define_split
[(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))]
+ (float:SF (match_operand:HI 1 "register_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:SF (match_dup 2)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_80387"
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
+
+(define_expand "floatdisf2"
+ [(parallel [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
"TARGET_80387"
+ "operands[2] = assign_386_stack_local (DImode, 0);")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:DI 2 "memory_operand" "m,o"))]
+ "TARGET_80387"
+ "#")
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:DI 1 "memory_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:SF (match_dup 1)))]
+ "")
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:DI 1 "register_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:SF (match_dup 2)))]
"")
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:DI 1 "memory_operand" "m")))]
+ "TARGET_80387"
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
+
(define_expand "floatsidf2"
+ [(parallel [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
+ "TARGET_80387"
+ "operands[2] = assign_386_stack_local (SImode, 0);")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:SI 2 "memory_operand" "m,m"))]
+ "TARGET_80387"
+ "#")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:SI 1 "memory_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:DF (match_dup 1)))]
+ "")
+
+(define_split
[(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ (float:DF (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:DF (match_dup 2)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:SI 1 "memory_operand" "m")))]
+ "TARGET_80387"
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
+
+(define_expand "floathidf2"
+ [(parallel [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:HI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
+ "TARGET_80387"
+ "operands[2] = assign_386_stack_local (HImode, 0);")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))]
"TARGET_80387"
+ "#")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:HI 1 "memory_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:DF (match_dup 1)))]
"")
-(define_expand "floatdidf2"
+(define_split
[(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))]
+ (float:DF (match_operand:HI 1 "register_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:DF (match_dup 2)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_80387"
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
+
+(define_expand "floatdidf2"
+ [(parallel [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
+ "TARGET_80387"
+ "operands[2] = assign_386_stack_local (DImode, 0);")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:DI 2 "memory_operand" "m,o"))]
"TARGET_80387"
+ "#")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:DI 1 "memory_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:DF (match_dup 1)))]
"")
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:DI 1 "register_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:DF (match_dup 2)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:DI 1 "memory_operand" "m")))]
+ "TARGET_80387"
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
+
(define_expand "floatsixf2"
- [(set (match_operand:XF 0 "register_operand" "")
- (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))]
+ [(parallel [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
"TARGET_80387"
- "")
+ "operands[2] = assign_386_stack_local (SImode, 0);")
-(define_expand "floatdixf2"
+(define_insn ""
+ [(set (match_operand:XF 0 "register_operand" "=f,f")
+ (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:SI 2 "memory_operand" "m,m"))]
+ "TARGET_80387"
+ "#")
+
+(define_split
[(set (match_operand:XF 0 "register_operand" "")
- (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_80387 && LONG_DOUBLE_TYPE_SIZE == 96"
+ (float:XF (match_operand:SI 1 "memory_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:XF (match_dup 1)))]
"")
-;; This will convert from SImode or DImode to MODE_FLOAT.
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:SI 1 "register_operand" "")))
+ (clobber (match_operand:SI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:XF (match_dup 2)))]
+ "")
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f")
- (float:XF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
+ (float:XF (match_operand:SI 1 "memory_operand" "m")))]
"TARGET_80387"
- "*
-{
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fild%z0,%1));
- RET;
- }
- else if (GET_CODE (operands[1]) == MEM)
- return AS1 (fild%z1,%1);
- else
- abort ();
-}")
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
-(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
+(define_expand "floathixf2"
+ [(parallel [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:HI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
"TARGET_80387"
- "*
-{
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fild%z0,%1));
- RET;
- }
- else if (GET_CODE (operands[1]) == MEM)
- return AS1 (fild%z1,%1);
- else
- abort ();
-}")
+ "operands[2] = assign_386_stack_local (HImode, 0);")
(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
+ [(set (match_operand:XF 0 "register_operand" "=f,f")
+ (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:HI 2 "memory_operand" "m,m"))]
"TARGET_80387"
- "*
-{
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fild%z0,%1));
- RET;
- }
- else if (GET_CODE (operands[1]) == MEM)
- return AS1 (fild%z1,%1);
- else
- abort ();
-}")
+ "#")
+
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:HI 1 "memory_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:XF (match_dup 1)))]
+ "")
+
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:HI 1 "register_operand" "")))
+ (clobber (match_operand:HI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:XF (match_dup 2)))]
+ "")
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (float:XF (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_80387"
- "*
-{
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fild%z0,%1));
- RET;
- }
- else if (GET_CODE (operands[1]) == MEM)
- return AS1 (fild%z1,%1);
- else
- abort ();
-}")
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
+
+(define_expand "floatdixf2"
+ [(parallel [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))
+ (clobber (match_dup 2))])]
+ "TARGET_80387"
+ "operands[2] = assign_386_stack_local (DImode, 0);")
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))]
+ (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,!r")))
+ (clobber (match_operand:DI 2 "memory_operand" "m,o"))]
"TARGET_80387"
- "*
-{
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fild%z0,%1));
- RET;
- }
- else if (GET_CODE (operands[1]) == MEM)
- return AS1 (fild%z1,%1);
- else
- abort ();
-}")
+ "#")
+
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:DI 1 "memory_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0)
+ (float:XF (match_dup 1)))]
+ "")
+
+(define_split
+ [(set (match_operand:XF 0 "register_operand" "")
+ (float:XF (match_operand:DI 1 "register_operand" "")))
+ (clobber (match_operand:DI 2 "memory_operand" ""))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (float:XF (match_dup 2)))]
+ "")
(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (float:XF (match_operand:DI 1 "memory_operand" "m")))]
"TARGET_80387"
- "*
-{
- if (NON_STACK_REG_P (operands[1]))
- {
- output_op_from_reg (operands[1], AS1 (fild%z0,%1));
- RET;
- }
- else if (GET_CODE (operands[1]) == MEM)
- return AS1 (fild%z1,%1);
- else
- abort ();
-}")
+ "* return AS1 (fild%z1,%1);"
+ [(set_attr "type" "fpop")])
;;- add instructions
-(define_insn "addsidi3_1"
+(define_insn "*addsidi3_1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,!&r,!r,o,!o")
(plus:DI (match_operand:DI 1 "general_operand" "0,0,0,o,riF,riF,o")
(zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,roi,roi,ri,ri"))))
@@ -2666,7 +3243,7 @@
""
"*
{
- rtx low[3], high[3], xops[7], temp;
+ rtx low[3], high[3], xops[7];
CC_STATUS_INIT;
@@ -2703,8 +3280,11 @@
output_asm_insn (AS2 (add%L0,%2,%0), low);
output_asm_insn (AS2 (adc%L0,%2,%0), high);
+ cc_status.value1 = high[0];
+ cc_status.flags = CC_NO_OVERFLOW;
RET;
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "addsidi3_2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o")
@@ -2714,7 +3294,7 @@
""
"*
{
- rtx low[3], high[3], xops[7], temp;
+ rtx low[3], high[3], xops[7];
CC_STATUS_INIT;
@@ -2781,8 +3361,11 @@
output_asm_insn (AS2 (add%L0,%2,%0), low);
output_asm_insn (AS2 (adc%L0,%2,%0), high);
+ cc_status.value1 = high[0];
+ cc_status.flags = CC_NO_OVERFLOW;
RET;
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "adddi3"
[(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
@@ -2831,6 +3414,9 @@
}
}
+ cc_status.value1 = high[0];
+ cc_status.flags = CC_NO_OVERFLOW;
+
if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
{
xops[0] = high[0];
@@ -2855,7 +3441,8 @@
output_asm_insn (AS2 (add%L0,%2,%0), high);
RET;
-}")
+}"
+ [(set_attr "type" "binary")])
;; On a 486, it is faster to do movl/addl than to do a single leal if
;; operands[1] and operands[2] are both registers.
@@ -2875,7 +3462,7 @@
"*
{
if (REG_P (operands[0]) && REG_P (operands[1])
- && (REG_P (operands[2]) || GET_CODE (operands[2]) == CONST_INT)
+ && (REG_P (operands[2]) || CONSTANT_P (operands[2]))
&& REGNO (operands[0]) != REGNO (operands[1]))
{
if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
@@ -2920,7 +3507,8 @@
}
return AS2 (add%L0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
;; addsi3 is faster, so put this after.
@@ -2949,7 +3537,8 @@
CC_STATUS_INIT;
return AS2 (lea%L0,%a1,%0);
-}")
+}"
+ [(set_attr "type" "lea")])
;; ??? `lea' here, for three operand add? If leaw is used, only %bx,
;; %si and %di can appear in SET_SRC, and output_asm_insn might not be
@@ -2963,12 +3552,30 @@
"IX86_EXPAND_BINARY_OPERATOR (PLUS, HImode, operands);")
(define_insn ""
- [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
- (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "ri,rm")))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,?r")
+ (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
+ (match_operand:HI 2 "general_operand" "ri,rm,ri")))]
"ix86_binary_operator_ok (PLUS, HImode, operands)"
"*
{
+ if (REG_P (operands[0]) && REG_P (operands[1])
+ && (REG_P (operands[2]) || CONSTANT_P (operands[2]))
+ && REGNO (operands[0]) != REGNO (operands[1]))
+ {
+ if (operands[2] == stack_pointer_rtx)
+ abort ();
+
+ CC_STATUS_INIT;
+ operands[1]
+ = gen_rtx_PLUS (SImode,
+ gen_rtx_REG (SImode, REGNO (operands[1])),
+ (! REG_P (operands[2])
+ ? operands[2]
+ : gen_rtx_REG (SImode, REGNO (operands[2]))));
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+ return AS2 (lea%L0,%a1,%0);
+ }
+
/* ??? what about offsettable memory references? */
if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */
&& QI_REG_P (operands[0])
@@ -3019,7 +3626,8 @@
return AS1 (dec%W0,%0);
return AS2 (add%W0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_expand "addqi3"
[(set (match_operand:QI 0 "general_operand" "")
@@ -3029,12 +3637,31 @@
"IX86_EXPAND_BINARY_OPERATOR (PLUS, QImode, operands);")
(define_insn ""
- [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
- (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "qn,qmn")))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,?q")
+ (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,q")
+ (match_operand:QI 2 "general_operand" "qn,qmn,qn")))]
"ix86_binary_operator_ok (PLUS, QImode, operands)"
"*
{
+ if (REG_P (operands[0]) && REG_P (operands[1])
+ && (REG_P (operands[2]) || CONSTANT_P (operands[2]))
+ && (REGNO (operands[0]) != REGNO (operands[1])
+ || NON_QI_REG_P (operands[1])
+ || (REG_P (operands[2]) && NON_QI_REG_P (operands[2]))))
+ {
+ if (operands[2] == stack_pointer_rtx)
+ abort ();
+
+ CC_STATUS_INIT;
+ operands[1]
+ = gen_rtx_PLUS (SImode,
+ gen_rtx_REG (SImode, REGNO (operands[1])),
+ (! REG_P (operands[2])
+ ? operands[2]
+ : gen_rtx_REG (SImode, REGNO (operands[2]))));
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+ return AS2 (lea%L0,%a1,%0);
+ }
if (operands[2] == const1_rtx)
return AS1 (inc%B0,%0);
@@ -3044,7 +3671,8 @@
return AS1 (dec%B0,%0);
return AS2 (add%B0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
;Lennart Augustsson <augustss@cs.chalmers.se>
;says this pattern just makes slower code:
@@ -3141,8 +3769,12 @@
output_asm_insn (AS2 (sub%L0,%2,%0), low);
output_asm_insn (AS2 (sbb%L0,%2,%0), high);
+ cc_status.value1 = high[0];
+ cc_status.flags = CC_NO_OVERFLOW;
+
RET;
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "subdi3"
[(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,o,!&r,!o")
@@ -3185,6 +3817,9 @@
}
}
+ cc_status.value1 = high[0];
+ cc_status.flags = CC_NO_OVERFLOW;
+
if (GET_CODE (operands[3]) == REG)
{
xops[0] = high[0];
@@ -3206,10 +3841,12 @@
}
else
- output_asm_insn (AS2 (sub%L0,%2,%0), high);
+ output_asm_insn (AS2 (sub%L0,%2,%0), high);
+
RET;
-}")
+}"
+ [(set_attr "type" "binary")])
(define_expand "subsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
@@ -3223,7 +3860,8 @@
(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
(match_operand:SI 2 "general_operand" "ri,rm")))]
"ix86_binary_operator_ok (MINUS, SImode, operands)"
- "* return AS2 (sub%L0,%2,%0);")
+ "* return AS2 (sub%L0,%2,%0);"
+ [(set_attr "type" "binary")])
(define_expand "subhi3"
[(set (match_operand:HI 0 "general_operand" "")
@@ -3248,7 +3886,8 @@
return AS2 (sub%L0,%k2,%k0);
}
return AS2 (sub%W0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_expand "subqi3"
[(set (match_operand:QI 0 "general_operand" "")
@@ -3262,7 +3901,8 @@
(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
(match_operand:QI 2 "general_operand" "qn,qmn")))]
"ix86_binary_operator_ok (MINUS, QImode, operands)"
- "* return AS2 (sub%B0,%2,%0);")
+ "* return AS2 (sub%B0,%2,%0);"
+ [(set_attr "type" "binary")])
;; The patterns that match these are at the end of this file.
@@ -3688,7 +4328,8 @@ word_zero_and_operation:
}
return AS2 (and%L0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "andhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
@@ -3766,14 +4407,16 @@ word_zero_and_operation:
}
return AS2 (and%W0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "andqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qn,qmn")))]
""
- "* return AS2 (and%B0,%2,%0);")
+ "* return AS2 (and%B0,%2,%0);"
+ [(set_attr "type" "binary")])
/* I am nervous about these two.. add them later..
;I presume this means that we have something in say op0= eax which is small
@@ -3889,7 +4532,8 @@ byte_or_operation:
}
return AS2 (or%L0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "iorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
@@ -3973,14 +4617,16 @@ byte_or_operation:
}
return AS2 (or%W0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "iorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qn,qmn")))]
""
- "* return AS2 (or%B0,%2,%0);")
+ "* return AS2 (or%B0,%2,%0);"
+ [(set_attr "type" "binary")])
;;- xor instructions
@@ -4016,7 +4662,10 @@ byte_or_operation:
byte_xor_operation:
CC_STATUS_INIT;
- if (intval == 0xff)
+ if (intval == 0xff
+ && (!TARGET_PENTIUM || optimize_size
+ || (GET_CODE (operands[0]) == MEM
+ && memory_address_info (XEXP (operands[0], 0), 1))))
return AS1 (not%B0,%b0);
if (intval != INTVAL (operands[2]))
@@ -4032,7 +4681,10 @@ byte_xor_operation:
if (REG_P (operands[0]))
{
CC_STATUS_INIT;
- if (intval == 0xff)
+ if (intval == 0xff
+ && (!TARGET_PENTIUM || optimize_size
+ || (GET_CODE (operands[0]) == MEM
+ && memory_address_info (XEXP (operands[0], 0), 1))))
return AS1 (not%B0,%h0);
operands[2] = GEN_INT (intval);
@@ -4068,7 +4720,8 @@ byte_xor_operation:
}
return AS2 (xor%L0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "xorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
@@ -4088,7 +4741,10 @@ byte_xor_operation:
if (INTVAL (operands[2]) & 0xffff0000)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
- if (INTVAL (operands[2]) == 0xff)
+ if (INTVAL (operands[2]) == 0xff
+ && (!TARGET_PENTIUM || optimize_size
+ || (GET_CODE (operands[0]) == MEM
+ && memory_address_info (XEXP (operands[0], 0), 1))))
return AS1 (not%B0,%b0);
return AS2 (xor%B0,%2,%b0);
@@ -4102,7 +4758,10 @@ byte_xor_operation:
CC_STATUS_INIT;
operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
- if (INTVAL (operands[2]) == 0xff)
+ if (INTVAL (operands[2]) == 0xff
+ && (!TARGET_PENTIUM || optimize_size
+ || (GET_CODE (operands[0]) == MEM
+ && memory_address_info (XEXP (operands[0], 0), 1))))
return AS1 (not%B0,%h0);
return AS2 (xor%B0,%2,%h0);
@@ -4129,115 +4788,55 @@ byte_xor_operation:
}
return AS2 (xor%W0,%2,%0);
-}")
+}"
+ [(set_attr "type" "binary")])
(define_insn "xorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
(match_operand:QI 2 "general_operand" "qn,qm")))]
""
- "* return AS2 (xor%B0,%2,%0);")
+ "* return AS2 (xor%B0,%2,%0);"
+ [(set_attr "type" "binary")])
;; logical operations for DImode
-
(define_insn "anddi3"
- [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
- (and:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
- (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
- (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro")
+ (and:DI (match_operand:DI 1 "general_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "oriF,riF")))]
""
- "#")
+ "#"
+ [(set_attr "type" "binary")])
+
(define_insn "iordi3"
- [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
- (ior:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
- (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
- (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro")
+ (ior:DI (match_operand:DI 1 "general_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "oriF,riF")))]
""
- "#")
-
+ "#"
+ [(set_attr "type" "binary")])
+
(define_insn "xordi3"
- [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
- (xor:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
- (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
- (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro")
+ (xor:DI (match_operand:DI 1 "general_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "oriF,riF")))]
""
- "#")
+ "#"
+ [(set_attr "type" "binary")])
(define_split
- [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
- (match_operator:DI 4 "ix86_logical_operator"
- [(match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
- (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")]))
- (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
- "reload_completed"
- [(const_int 0)]
- "
-{
- rtx low[3], high[3], xops[7], temp;
- rtx (*genfunc)() = (GET_CODE (operands[4]) == AND ? gen_andsi3
- : GET_CODE (operands[4]) == IOR ? gen_iorsi3
- : GET_CODE (operands[4]) == XOR ? gen_xorsi3
- : 0);
-
- if (rtx_equal_p (operands[0], operands[2]))
- {
- temp = operands[1];
- operands[1] = operands[2];
- operands[2] = temp;
- }
-
- split_di (operands, 3, low, high);
- if (!rtx_equal_p (operands[0], operands[1]))
- {
- xops[0] = high[0];
- xops[1] = low[0];
- xops[2] = high[1];
- xops[3] = low[1];
-
- if (GET_CODE (operands[0]) != MEM)
- {
- emit_insn (gen_movsi (xops[1], xops[3]));
- emit_insn (gen_movsi (xops[0], xops[2]));
- }
- else
- {
- xops[4] = high[2];
- xops[5] = low[2];
- xops[6] = operands[3];
- emit_insn (gen_movsi (xops[6], xops[3]));
- emit_insn ((*genfunc) (xops[6], xops[6], xops[5]));
- emit_insn (gen_movsi (xops[1], xops[6]));
- emit_insn (gen_movsi (xops[6], xops[2]));
- emit_insn ((*genfunc) (xops[6], xops[6], xops[4]));
- emit_insn (gen_movsi (xops[0], xops[6]));
- DONE;
- }
- }
-
- if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
- {
- xops[0] = high[0];
- xops[1] = low[0];
- xops[2] = high[2];
- xops[3] = low[2];
- xops[4] = operands[3];
-
- emit_insn (gen_movsi (xops[4], xops[3]));
- emit_insn ((*genfunc) (xops[1], xops[1], xops[4]));
- emit_insn (gen_movsi (xops[4], xops[2]));
- emit_insn ((*genfunc) (xops[0], xops[0], xops[4]));
- }
-
- else
- {
- emit_insn ((*genfunc) (low[0], low[0], low[2]));
- emit_insn ((*genfunc) (high[0], high[0], high[2]));
- }
-
- DONE;
-}")
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operator:DI 3 "ix86_logical_operator"
+ [(match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")]))]
+ ""
+ [(set (match_dup 4) (match_op_dup:SI 3 [(match_dup 6) (match_dup 8)]))
+ (set (match_dup 5) (match_op_dup:SI 3 [(match_dup 7) (match_dup 9)]))]
+ "split_di (&operands[0], 1, &operands[4], &operands[5]);
+ split_di (&operands[1], 1, &operands[6], &operands[7]);
+ split_di (&operands[2], 1, &operands[8], &operands[9]);")
;;- negation instructions
@@ -4271,7 +4870,13 @@ byte_xor_operation:
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
""
- "neg%W0 %0")
+ "*
+ if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
+ {
+ CC_STATUS_INIT;
+ return AS1(neg%L0,%k0);
+ }
+ return AS1(neg%W0,%0);")
(define_insn "negqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
@@ -4283,31 +4888,36 @@ byte_xor_operation:
[(set (match_operand:SF 0 "register_operand" "=f")
(neg:SF (match_operand:SF 1 "register_operand" "0")))]
"TARGET_80387"
- "fchs")
+ "fchs"
+ [(set_attr "type" "fpop")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(neg:DF (match_operand:DF 1 "register_operand" "0")))]
"TARGET_80387"
- "fchs")
+ "fchs"
+ [(set_attr "type" "fpop")])
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
(neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
"TARGET_80387"
- "fchs")
+ "fchs"
+ [(set_attr "type" "fpop")])
(define_insn "negxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
(neg:XF (match_operand:XF 1 "register_operand" "0")))]
"TARGET_80387"
- "fchs")
+ "fchs"
+ [(set_attr "type" "fpop")])
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f")
(neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
"TARGET_80387"
- "fchs")
+ "fchs"
+ [(set_attr "type" "fpop")])
;; Absolute value instructions
@@ -4443,19 +5053,88 @@ byte_xor_operation:
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
""
- "not%L0 %0")
+ "*
+{
+ /* A Pentium NOT is not pariable. Output it only in case of complex
+ memory address, because XOR will be inpariable anyway because
+ of immediate/displacement rule. */
+
+ if (TARGET_PENTIUM && !optimize_size
+ && (GET_CODE (operands[0]) != MEM
+ || memory_address_info (XEXP (operands[0], 0), 1) == 0))
+ {
+ rtx xops[2];
+ xops[0] = operands[0];
+ xops[1] = GEN_INT (0xffffffff);
+ output_asm_insn (AS2 (xor%L0,%1,%0), xops);
+ RET;
+ }
+ else
+ return AS1 (not%L0,%0);
+}")
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
""
- "not%W0 %0")
+ "*
+{
+ /* A Pentium NOT is not pariable. Output it only in case of complex
+ memory address, because XOR will be inpariable anyway because
+ of immediate/displacement rule. */
+
+ if (TARGET_PENTIUM && !optimize_size
+ && (GET_CODE (operands[0]) != MEM
+ || memory_address_info (XEXP (operands[0], 0), 1) == 0))
+ {
+ rtx xops[2];
+ xops[0] = operands[0];
+ xops[1] = GEN_INT (0xffff);
+ if (REG_P (operands[0])
+ && i386_cc_probably_useless_p (insn))
+ {
+ CC_STATUS_INIT;
+ output_asm_insn (AS2 (xor%L0,%1,%k0), xops);
+ }
+ else
+ output_asm_insn (AS2 (xor%W0,%1,%0), xops);
+ RET;
+ }
+ else
+ {
+ if (REG_P (operands[0])
+ && i386_cc_probably_useless_p (insn))
+ {
+ CC_STATUS_INIT;
+ return AS1 (not%L0,%k0);
+ }
+ return AS1 (not%W0,%0);
+ }
+}")
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
""
- "not%B0 %0")
+ "*
+{
+ /* A Pentium NOT is not pariable. Output it only in case of complex
+ memory address, because XOR will be inpariable anyway because
+ of immediate/displacement rule. */
+
+ if (TARGET_PENTIUM && !optimize_size
+ && (GET_CODE (operands[0]) != MEM
+ || memory_address_info (XEXP (operands[0], 0), 1) == 0))
+ {
+ rtx xops[2];
+ xops[0] = operands[0];
+ xops[1] = GEN_INT (0xff);
+ output_asm_insn (AS2 (xor%B0,%1,%0), xops);
+ RET;
+ }
+ else
+ return AS1 (not%B0,%0);
+}")
;;- arithmetic shift instructions
@@ -4566,79 +5245,79 @@ byte_xor_operation:
RET;
}")
-;; On i386 and i486, "addl reg,reg" is faster than "sall $1,reg"
-;; On i486, movl/sall appears slightly faster than leal, but the leal
-;; is smaller - use leal for now unless the shift count is 1.
+(define_expand "ashlsi3"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "")
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,0")
- (match_operand:SI 2 "nonmemory_operand" "M,cI")))]
+(define_expand "ashlhi3"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
+ (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
+ (match_operand:HI 2 "nonmemory_operand" "")))]
""
- "*
-{
- if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
- {
- if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
- {
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
- return AS2 (add%L0,%1,%0);
- }
- else
- {
- CC_STATUS_INIT;
+ "")
- if (operands[1] == stack_pointer_rtx)
- {
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
- operands[1] = operands[0];
- }
- operands[1] = gen_rtx_MULT (SImode, operands[1],
- GEN_INT (1 << INTVAL (operands[2])));
- return AS2 (lea%L0,%a1,%0);
- }
- }
+(define_expand "ashlqi3"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
+ ""
+ "")
- if (REG_P (operands[2]))
- return AS2 (sal%L0,%b2,%0);
+;; Pattern for shifts which can be encoded into an lea instruction.
+;; This is kept as a separate pattern so that regmove can optimize cases
+;; where we know the source and destination must match.
+;;
+;; Do not expose this pattern when optimizing for size since we never want
+;; to use lea when optimizing for size since mov+sal is smaller than lea.
- if (REG_P (operands[0]) && operands[2] == const1_rtx)
- return AS2 (add%L0,%0,%0);
+(define_insn ""
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r")
+ (match_operand:SI 2 "small_shift_operand" "M,M")))]
+ "! optimize_size"
+ "* return output_ashl (insn, operands);")
- return AS2 (sal%L0,%2,%0);
-}")
+;; Generic left shift pattern to catch all cases not handled by the
+;; shift pattern above.
+(define_insn ""
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "cI")))]
+ ""
+ "* return output_ashl (insn, operands);")
-(define_insn "ashlhi3"
+(define_insn ""
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
+ (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r")
+ (match_operand:HI 2 "small_shift_operand" "M,M")))]
+ "! optimize_size"
+ "* return output_ashl (insn, operands);")
+
+(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "cI")))]
""
- "*
-{
- if (REG_P (operands[2]))
- return AS2 (sal%W0,%b2,%0);
+ "* return output_ashl (insn, operands);")
- if (REG_P (operands[0]) && operands[2] == const1_rtx)
- return AS2 (add%W0,%0,%0);
-
- return AS2 (sal%W0,%2,%0);
-}")
+(define_insn ""
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q")
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,q")
+ (match_operand:QI 2 "small_shift_operand" "M,M")))]
+ "! optimize_size"
+ "* return output_ashl (insn, operands);")
-(define_insn "ashlqi3"
+;; Generic left shift pattern to catch all cases not handled by the
+;; shift pattern above.
+(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))]
""
- "*
-{
- if (REG_P (operands[2]))
- return AS2 (sal%B0,%b2,%0);
-
- if (REG_P (operands[0]) && operands[2] == const1_rtx)
- return AS2 (add%B0,%0,%0);
-
- return AS2 (sal%B0,%2,%0);
-}")
+ "* return output_ashl (insn, operands);")
;; See comment above `ashldi3' about how this works.
@@ -4755,6 +5434,15 @@ byte_xor_operation:
RET;
}")
+(define_insn "ashrsi3_31"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,d")
+ (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,a")
+ (const_int 31)))]
+ "!TARGET_PENTIUM || optimize_size"
+ "@
+ sar%L0 $31,%0
+ cltd")
+
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
@@ -5177,7 +5865,10 @@ byte_xor_operation:
mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
operands[1] = GEN_INT (mask);
- if (QI_REG_P (operands[0]))
+ if (QI_REG_P (operands[0])
+ /* A Pentium test is pairable only with eax. Not with ah or al. */
+ && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM
+ || optimize_size))
{
if ((mask & ~0xff) == 0)
{
@@ -5211,7 +5902,10 @@ byte_xor_operation:
mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
operands[1] = GEN_INT (mask);
- if (! REG_P (operands[0]) || QI_REG_P (operands[0]))
+ if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
+ /* A Pentium test is pairable only with eax. Not with ah or al. */
+ && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM
+ || optimize_size))
{
if ((mask & ~0xff) == 0)
{
@@ -5261,10 +5955,6 @@ byte_xor_operation:
;; For all sCOND expanders, also expand the compare or test insn that
;; generates cc0. Generate an equality comparison if `seq' or `sne'.
-;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may
-;; not have any input reloads. A MEM write might need an input reload
-;; for the address of the MEM. So don't allow MEM as the SET_DEST.
-
(define_expand "seq"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5279,18 +5969,6 @@ byte_xor_operation:
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (eq:QI (cc0) (const_int 0)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return AS1 (setnb,%0);
- else
- return AS1 (sete,%0);
-}")
-
(define_expand "sne"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5305,19 +5983,6 @@ byte_xor_operation:
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (ne:QI (cc0) (const_int 0)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return AS1 (setb,%0);
- else
- return AS1 (setne,%0);
-}
-")
-
(define_expand "sgt"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5325,19 +5990,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (gt:QI (cc0) (const_int 0)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (sete,%0);
-
- OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR);
-}")
-
(define_expand "sgtu"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5345,12 +5997,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (gtu:QI (cc0) (const_int 0)))]
- ""
- "* return \"seta %0\"; ")
-
(define_expand "slt"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5358,19 +6004,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (lt:QI (cc0) (const_int 0)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (sete,%0);
-
- OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
-}")
-
(define_expand "sltu"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5378,12 +6011,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (ltu:QI (cc0) (const_int 0)))]
- ""
- "* return \"setb %0\"; ")
-
(define_expand "sge"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5391,19 +6018,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (ge:QI (cc0) (const_int 0)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (sete,%0);
-
- OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
-}")
-
(define_expand "sgeu"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5411,12 +6025,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (geu:QI (cc0) (const_int 0)))]
- ""
- "* return \"setae %0\"; ")
-
(define_expand "sle"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5424,19 +6032,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (le:QI (cc0) (const_int 0)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (setb,%0);
-
- OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR);
-}")
-
(define_expand "sleu"
[(match_dup 1)
(set (match_operand:QI 0 "register_operand" "")
@@ -5444,11 +6039,69 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=q")
- (leu:QI (cc0) (const_int 0)))]
- ""
- "* return \"setbe %0\"; ")
+;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may
+;; not have any input reloads. A MEM write might need an input reload
+;; for the address of the MEM. So don't allow MEM as the SET_DEST.
+
+(define_insn "*setcc"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (match_operator:QI 1 "comparison_operator" [(cc0) (const_int 0)]))]
+ "reload_completed || register_operand (operands[0], QImode)"
+ "*
+{
+ enum rtx_code code = GET_CODE (operands[1]);
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ int eq;
+ HOST_WIDE_INT c;
+ operands[2] = gen_rtx_REG (SImode, 0);
+ switch (code)
+ {
+ case EQ:
+ c = 0x4000;
+ eq = 0;
+ break;
+ case NE:
+ c = 0x4000;
+ eq = 1;
+ break;
+ case GT:
+ c = 0x4100;
+ eq = 1;
+ break;
+ case LT:
+ c = 0x100;
+ eq = 0;
+ break;
+ case GE:
+ c = 0x100;
+ eq = 1;
+ break;
+ case LE:
+ c = 0x4100;
+ eq = 0;
+ break;
+ default:
+ abort ();
+ }
+ if (!TARGET_PENTIUM || optimize_size)
+ {
+ operands[3] = GEN_INT (c >> 8);
+ output_asm_insn (AS2 (test%B0,%3,%h2), operands);
+ }
+ else
+ {
+ operands[3] = GEN_INT (c);
+ output_asm_insn (AS2 (test%L0,%3,%2), operands);
+ }
+ return eq ? AS1 (sete,%0) : AS1 (setne, %0);
+ }
+
+ if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
+ return (char *)0;
+ return AS1(set%D1,%0);
+}")
+
;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions.
@@ -5473,29 +6126,6 @@ byte_xor_operation:
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
-(define_insn ""
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jnc %l0\";
- else
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4000);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (jne,%l0);
- }
-
- return \"je %l0\";
-}")
-
(define_expand "bne"
[(match_dup 1)
(set (pc)
@@ -5513,28 +6143,6 @@ byte_xor_operation:
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
-(define_insn ""
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jc %l0\";
- else
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4000);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (je,%l0);
- }
-
- return \"jne %l0\";
-}")
(define_expand "bgt"
[(match_dup 1)
@@ -5546,29 +6154,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (je,%l0);
-
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (je,%l0);
- }
- OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
-}")
-
(define_expand "bgtu"
[(match_dup 1)
(set (pc)
@@ -5579,15 +6164,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "ja %l0")
-
(define_expand "blt"
[(match_dup 1)
(set (pc)
@@ -5598,28 +6174,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (je,%l0);
-
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (jne,%l0);
- }
- OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
-}")
(define_expand "bltu"
[(match_dup 1)
@@ -5631,15 +6185,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "jb %l0")
-
(define_expand "bge"
[(match_dup 1)
(set (pc)
@@ -5650,28 +6195,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (je,%l0);
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (je,%l0);
- }
- OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
-}")
-
(define_expand "bgeu"
[(match_dup 1)
(set (pc)
@@ -5682,15 +6205,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "jae %l0")
-
(define_expand "ble"
[(match_dup 1)
(set (pc)
@@ -5701,29 +6215,6 @@ byte_xor_operation:
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
-(define_insn ""
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (jb,%l0);
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (jne,%l0);
- }
-
- OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
-}")
-
(define_expand "bleu"
[(match_dup 1)
(set (pc)
@@ -5736,184 +6227,127 @@ byte_xor_operation:
(define_insn ""
[(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
(pc)))]
""
- "jbe %l0")
-
-;; Negated conditional jump instructions.
-
-(define_insn ""
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jc %l0\";
- else
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4000);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (je,%l0);
- }
- return \"jne %l0\";
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
"*
{
- if (cc_prev_status.flags & CC_Z_IN_NOT_C)
- return \"jnc %l0\";
- else
+ enum rtx_code code = GET_CODE (operands[0]);
if (cc_prev_status.flags & CC_TEST_AX)
{
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4000);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (jne,%l0);
+ int eq;
+ HOST_WIDE_INT c;
+ operands[2] = gen_rtx_REG (SImode, 0);
+ switch (code)
+ {
+ case EQ:
+ c = 0x4000;
+ eq = 0;
+ break;
+ case NE:
+ c = 0x4000;
+ eq = 1;
+ break;
+ case GT:
+ c = 0x4100;
+ eq = 1;
+ break;
+ case LT:
+ c = 0x100;
+ eq = 0;
+ break;
+ case GE:
+ c = 0x100;
+ eq = 1;
+ break;
+ case LE:
+ c = 0x4100;
+ eq = 0;
+ break;
+ default:
+ abort ();
+ }
+ if (!TARGET_PENTIUM || optimize_size)
+ {
+ operands[3] = GEN_INT (c >> 8);
+ output_asm_insn (AS2 (test%B0,%3,%h2), operands);
+ }
+ else
+ {
+ operands[3] = GEN_INT (c);
+ output_asm_insn (AS2 (test%L0,%3,%2), operands);
+ }
+ return eq ? AS1 (je,%l1) : AS1 (jne, %l1);
}
- return \"je %l0\";
-}")
+ if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
+ return (char *)0;
-(define_insn ""
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (jne,%l0);
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (jne,%l0);
- }
- OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
+ return AS1(j%D0,%l1);
}")
(define_insn ""
[(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "jbe %l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(cc0) (const_int 0)])
(pc)
- (label_ref (match_operand 0 "" ""))))]
+ (label_ref (match_operand 1 "" ""))))]
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (jne,%l0);
+ enum rtx_code code = GET_CODE (operands[0]);
if (cc_prev_status.flags & CC_TEST_AX)
{
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (je,%l0);
+ int eq;
+ HOST_WIDE_INT c;
+ operands[2] = gen_rtx_REG (SImode, 0);
+ switch (code)
+ {
+ case EQ:
+ c = 0x4000;
+ eq = 1;
+ break;
+ case NE:
+ c = 0x4000;
+ eq = 0;
+ break;
+ case GT:
+ c = 0x4100;
+ eq = 0;
+ break;
+ case LT:
+ c = 0x100;
+ eq = 1;
+ break;
+ case GE:
+ c = 0x100;
+ eq = 0;
+ break;
+ case LE:
+ c = 0x4100;
+ eq = 1;
+ break;
+ default:
+ abort ();
+ }
+ if (!TARGET_PENTIUM || optimize_size)
+ {
+ operands[3] = GEN_INT (c >> 8);
+ output_asm_insn (AS2 (test%B0,%3,%h2), operands);
+ }
+ else
+ {
+ operands[3] = GEN_INT (c);
+ output_asm_insn (AS2 (test%L0,%3,%2), operands);
+ }
+ return eq ? AS1 (je,%l1) : AS1 (jne, %l1);
}
+ if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
+ return (char *)0;
- OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "jae %l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (jne,%l0);
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (jne,%l0);
- }
- OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
+ return AS1(j%d0,%l1);
}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "jb %l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
- && ! (cc_prev_status.flags & CC_FCOMI))
- return AS1 (jae,%l0);
-
- if (cc_prev_status.flags & CC_TEST_AX)
- {
- operands[1] = gen_rtx_REG (SImode, 0);
- operands[2] = GEN_INT (0x4100);
- output_asm_insn (AS2 (testl,%2,%1), operands);
- return AS1 (je,%l0);
- }
- OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "ja %l0")
;; Unconditional and other jump instructions
@@ -5921,7 +6355,8 @@ byte_xor_operation:
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
- "jmp %l0")
+ "jmp %l0"
+ [(set_attr "memory" "none")])
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
@@ -5931,7 +6366,8 @@ byte_xor_operation:
CC_STATUS_INIT;
return AS1 (jmp,%*%0);
-}")
+}"
+ [(set_attr "memory" "none")])
;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i);
;; if S does not change i
@@ -5952,7 +6388,7 @@ byte_xor_operation:
(define_insn ""
[(set (pc)
(if_then_else (match_operator 0 "arithmetic_comparison_operator"
- [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m")
+ [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+c*r,m")
(match_operand:SI 2 "general_operand" "rmi,ri"))
(const_int 0)])
(label_ref (match_operand 3 "" ""))
@@ -5964,6 +6400,11 @@ byte_xor_operation:
"*
{
CC_STATUS_INIT;
+
+ if (GET_CODE (operands[1]) == REG && REGNO (operands[2]) == 2 &&
+ operands[2] == constm1_rtx && ix86_cpu == PROCESSOR_K6)
+ return \"loop %l3\";
+
if (operands[2] == constm1_rtx)
output_asm_insn (AS1 (dec%L1,%1), operands);
@@ -6228,6 +6669,12 @@ byte_xor_operation:
{
rtx addr;
+ if (operands[3] == const0_rtx)
+ {
+ emit_insn (gen_call (operands[0], operands[1]));
+ DONE;
+ }
+
if (flag_pic)
current_function_uses_pic_offset_table = 1;
@@ -6330,6 +6777,12 @@ byte_xor_operation:
{
rtx addr;
+ if (operands[4] == const0_rtx)
+ {
+ emit_insn (gen_call_value (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+
if (flag_pic)
current_function_uses_pic_offset_table = 1;
@@ -6469,7 +6922,8 @@ byte_xor_operation:
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 0)]
""
- "")
+ ""
+ [(set_attr "memory" "none")])
;; Insn emitted into the body of a function to return from a function.
;; This is only done if the function's epilogue is known to be simple.
@@ -6483,18 +6937,21 @@ byte_xor_operation:
(define_insn "return_internal"
[(return)]
"reload_completed"
- "ret")
+ "ret"
+ [(set_attr "memory" "none")])
(define_insn "return_pop_internal"
[(return)
(use (match_operand:SI 0 "const_int_operand" ""))]
"reload_completed"
- "ret %0")
+ "ret %0"
+ [(set_attr "memory" "none")])
(define_insn "nop"
[(const_int 0)]
""
- "nop")
+ "nop"
+ [(set_attr "memory" "none")])
(define_expand "prologue"
[(const_int 1)]
@@ -6521,7 +6978,8 @@ byte_xor_operation:
xops[1] = stack_pointer_rtx;
output_asm_insn (AS2 (sub%L1,%0,%1), xops);
RET;
-}")
+}"
+ [(set_attr "memory" "none")])
(define_insn "prologue_set_got"
[(set (match_operand:SI 0 "" "")
@@ -6553,15 +7011,14 @@ byte_xor_operation:
""
"*
{
- char buffer[64];
-
output_asm_insn (AS1 (call,%X1), operands);
if (! TARGET_DEEP_BRANCH_PREDICTION)
{
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1]));
}
RET;
-}")
+}"
+ [(set_attr "memory" "none")])
(define_insn "prologue_get_pc_and_set_got"
[(unspec_volatile [(match_operand:SI 0 "" "")] 3)]
@@ -6573,9 +7030,10 @@ byte_xor_operation:
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (operands[1]));
output_asm_insn (AS1 (pop%L0,%0), operands);
- output_asm_insn (\"addl $_GLOBAL_OFFSET_TABLE_+[.-%X1],%0\", operands);
+ output_asm_insn (\"addl $%__GLOBAL_OFFSET_TABLE_+[.-%X1],%0\", operands);
RET;
-}")
+}"
+ [(set_attr "memory" "none")])
(define_expand "epilogue"
[(const_int 1)]
@@ -6598,14 +7056,16 @@ byte_xor_operation:
xops[1] = stack_pointer_rtx;
output_asm_insn (AS2 (mov%L0,%0,%1), xops);
RET;
-}")
+}"
+ [(set_attr "memory" "none")])
(define_insn "leave"
[(const_int 2)
(clobber (reg:SI 6))
(clobber (reg:SI 7))]
""
- "leave")
+ "leave"
+ [(set_attr "memory" "none")])
(define_insn "pop"
[(set (match_operand:SI 0 "register_operand" "r")
@@ -6616,7 +7076,8 @@ byte_xor_operation:
{
output_asm_insn (AS1 (pop%L0,%P0), operands);
RET;
-}")
+}"
+ [(set_attr "memory" "load")])
(define_expand "movstrsi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
@@ -6698,7 +7159,7 @@ byte_xor_operation:
""
"
{
- rtx addr0, addr1;
+ rtx addr0;
if (GET_CODE (operands[1]) != CONST_INT)
FAIL;
@@ -6715,7 +7176,7 @@ byte_xor_operation:
;; But strength reduction might offset the MEM expression. So we let
;; reload put the address into %edi.
-(define_insn ""
+(define_insn "*bzero"
[(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
(const_int 0))
(use (match_operand:SI 1 "const_int_operand" "n"))
@@ -6731,17 +7192,35 @@ byte_xor_operation:
output_asm_insn (\"cld\", operands);
if (GET_CODE (operands[1]) == CONST_INT)
{
- if (INTVAL (operands[1]) & ~0x03)
+ unsigned int count = INTVAL (operands[1]) & 0xffffffff;
+ if (count & ~0x03)
{
- xops[0] = GEN_INT ((INTVAL (operands[1]) >> 2) & 0x3fffffff);
+ xops[0] = GEN_INT (count / 4);
xops[1] = operands[4];
- output_asm_insn (AS2 (mov%L1,%0,%1), xops);
+ /* K6: stos takes 1 cycle, rep stos takes 8 + %ecx cycles.
+ 80386: 4/5+5n (+2 for set of ecx)
+ 80486: 5/7+5n (+1 for set of ecx)
+ */
+ if (count / 4 < ((int) ix86_cpu < (int)PROCESSOR_PENTIUM ? 4 : 6))
+ {
+ do
+#ifdef INTEL_SYNTAX
+ output_asm_insn (\"stosd\", xops);
+#else
+ output_asm_insn (\"stosl\", xops);
+#endif
+ while ((count -= 4) > 3);
+ }
+ else
+ {
+ output_asm_insn (AS2 (mov%L1,%0,%1), xops);
#ifdef INTEL_SYNTAX
- output_asm_insn (\"rep stosd\", xops);
+ output_asm_insn (\"rep stosd\", xops);
#else
- output_asm_insn (\"rep\;stosl\", xops);
+ output_asm_insn (\"rep\;stosl\", xops);
#endif
+ }
}
if (INTVAL (operands[1]) & 0x02)
output_asm_insn (\"stosw\", operands);
@@ -6910,9 +7389,7 @@ byte_xor_operation:
;; mulM3 and divM3. There are three patterns for each of DFmode and
;; SFmode. The first is the normal insn, the second the same insn but
;; with one operand a conversion, and the third the same insn but with
-;; the other operand a conversion. The conversion may be SFmode or
-;; SImode if the target mode DFmode, but only SImode if the target mode
-;; is SFmode.
+;; the other operand a conversion.
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f,f")
@@ -6932,23 +7409,6 @@ byte_xor_operation:
)])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (match_operator:DF 3 "binary_387_op"
- [(float:DF (match_operand:SI 1 "nonimmediate_operand" "rm"))
- (match_operand:DF 2 "register_operand" "0")]))]
- "TARGET_80387"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (cond [(match_operand:DF 3 "is_mul" "")
- (const_string "fpmul")
- (match_operand:DF 3 "is_div" "")
- (const_string "fpdiv")
- ]
- (const_string "fpop")
- )
- )])
-
-(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_387_op"
[(match_operand:XF 1 "register_operand" "0,f")
@@ -6966,23 +7426,6 @@ byte_xor_operation:
)])
(define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- (match_operator:XF 3 "binary_387_op"
- [(float:XF (match_operand:SI 1 "nonimmediate_operand" "rm"))
- (match_operand:XF 2 "register_operand" "0")]))]
- "TARGET_80387"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (cond [(match_operand:DF 3 "is_mul" "")
- (const_string "fpmul")
- (match_operand:DF 3 "is_div" "")
- (const_string "fpdiv")
- ]
- (const_string "fpop")
- )
- )])
-
-(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_387_op"
[(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
@@ -7000,23 +7443,6 @@ byte_xor_operation:
)])
(define_insn ""
- [(set (match_operand:XF 0 "register_operand" "=f")
- (match_operator:XF 3 "binary_387_op"
- [(match_operand:XF 1 "register_operand" "0")
- (float:XF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
- "TARGET_80387"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (cond [(match_operand:DF 3 "is_mul" "")
- (const_string "fpmul")
- (match_operand:DF 3 "is_div" "")
- (const_string "fpdiv")
- ]
- (const_string "fpop")
- )
- )])
-
-(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f,f")
(match_operator:XF 3 "binary_387_op"
[(match_operand:XF 1 "register_operand" "0,f")
@@ -7052,23 +7478,6 @@ byte_xor_operation:
)])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (match_operator:DF 3 "binary_387_op"
- [(match_operand:DF 1 "register_operand" "0")
- (float:DF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
- "TARGET_80387"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (cond [(match_operand:DF 3 "is_mul" "")
- (const_string "fpmul")
- (match_operand:DF 3 "is_div" "")
- (const_string "fpdiv")
- ]
- (const_string "fpop")
- )
- )])
-
-(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f,f")
(match_operator:DF 3 "binary_387_op"
[(match_operand:DF 1 "register_operand" "0,f")
@@ -7102,40 +7511,6 @@ byte_xor_operation:
(const_string "fpop")
)
)])
-
-(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- (match_operator:SF 3 "binary_387_op"
- [(float:SF (match_operand:SI 1 "nonimmediate_operand" "rm"))
- (match_operand:SF 2 "register_operand" "0")]))]
- "TARGET_80387"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (cond [(match_operand:DF 3 "is_mul" "")
- (const_string "fpmul")
- (match_operand:DF 3 "is_div" "")
- (const_string "fpdiv")
- ]
- (const_string "fpop")
- )
- )])
-
-(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- (match_operator:SF 3 "binary_387_op"
- [(match_operand:SF 1 "register_operand" "0")
- (float:SF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
- "TARGET_80387"
- "* return output_387_binary_op (insn, operands);"
- [(set (attr "type")
- (cond [(match_operand:DF 3 "is_mul" "")
- (const_string "fpmul")
- (match_operand:DF 3 "is_div" "")
- (const_string "fpdiv")
- ]
- (const_string "fpop")
- )
- )])
(define_expand "strlensi"
[(parallel [(set (match_dup 4)
@@ -7258,12 +7633,12 @@ byte_xor_operation:
"#")
(define_split
- [(set (match_operand:SI 0 "register_operand" "=r,r")
+ [(set (match_operand:SI 0 "register_operand" "")
(if_then_else:SI (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(const_int 0)])
- (match_operand:SI 3 "nonimmediate_operand" "rm,0")
- (match_operand:SI 4 "nonimmediate_operand" "0,rm")))]
+ (match_operand:SI 3 "nonimmediate_operand" "")
+ (match_operand:SI 4 "nonimmediate_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0)
(match_dup 2))
@@ -7273,12 +7648,12 @@ byte_xor_operation:
"")
(define_split
- [(set (match_operand:SI 0 "register_operand" "=r,r")
+ [(set (match_operand:SI 0 "register_operand" "")
(if_then_else:SI (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(match_operand 3 "general_operand" "")])
- (match_operand:SI 4 "nonimmediate_operand" "rm,0")
- (match_operand:SI 5 "nonimmediate_operand" "0,rm")))]
+ (match_operand:SI 4 "nonimmediate_operand" "")
+ (match_operand:SI 5 "nonimmediate_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0) (compare (match_dup 2) (match_dup 3)))
(set (match_dup 0)
@@ -7332,12 +7707,12 @@ byte_xor_operation:
"#")
(define_split
- [(set (match_operand:HI 0 "register_operand" "=r,r")
+ [(set (match_operand:HI 0 "register_operand" "")
(if_then_else:HI (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(const_int 0)])
- (match_operand:HI 3 "nonimmediate_operand" "rm,0")
- (match_operand:HI 4 "nonimmediate_operand" "0,rm")))]
+ (match_operand:HI 3 "nonimmediate_operand" "")
+ (match_operand:HI 4 "nonimmediate_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0)
(match_dup 2))
@@ -7347,12 +7722,12 @@ byte_xor_operation:
"")
(define_split
- [(set (match_operand:HI 0 "register_operand" "=r,r")
+ [(set (match_operand:HI 0 "register_operand" "")
(if_then_else:HI (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(match_operand 3 "general_operand" "")])
- (match_operand:HI 4 "nonimmediate_operand" "rm,0")
- (match_operand:HI 5 "nonimmediate_operand" "0,rm")))]
+ (match_operand:HI 4 "nonimmediate_operand" "")
+ (match_operand:HI 5 "nonimmediate_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0)
(compare (match_dup 2) (match_dup 3)))
@@ -7435,12 +7810,12 @@ byte_xor_operation:
"#")
(define_split
- [(set (match_operand:SF 0 "register_operand" "=f,f")
+ [(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "")
+ (match_operand:SF 4 "register_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0)
(match_dup 2))
@@ -7450,12 +7825,12 @@ byte_xor_operation:
"")
(define_split
- [(set (match_operand:SF 0 "register_operand" "=f,f")
+ [(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(match_operand 3 "general_operand" "")])
- (match_operand:SF 4 "register_operand" "f,0")
- (match_operand:SF 5 "register_operand" "0,f")))]
+ (match_operand:SF 4 "register_operand" "")
+ (match_operand:SF 5 "register_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0) (compare (match_dup 2) (match_dup 3)))
(set (match_dup 0)
@@ -7537,12 +7912,12 @@ byte_xor_operation:
"#")
(define_split
- [(set (match_operand:DF 0 "register_operand" "=f,f")
+ [(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "f,0")
- (match_operand:DF 4 "register_operand" "0,f")))]
+ (match_operand:DF 3 "register_operand" "")
+ (match_operand:DF 4 "register_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0)
(match_dup 2))
@@ -7552,12 +7927,12 @@ byte_xor_operation:
"")
(define_split
- [(set (match_operand:DF 0 "register_operand" "=f,f")
+ [(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(match_operand 3 "general_operand" "")])
- (match_operand:DF 4 "register_operand" "f,0")
- (match_operand:DF 5 "register_operand" "0,f")))]
+ (match_operand:DF 4 "register_operand" "")
+ (match_operand:DF 5 "register_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0) (compare (match_dup 2) (match_dup 3)))
(set (match_dup 0)
@@ -7639,12 +8014,12 @@ byte_xor_operation:
"#")
(define_split
- [(set (match_operand:XF 0 "register_operand" "=f,f")
+ [(set (match_operand:XF 0 "register_operand" "")
(if_then_else:XF (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(const_int 0)])
- (match_operand:XF 3 "register_operand" "f,0")
- (match_operand:XF 4 "register_operand" "0,f")))]
+ (match_operand:XF 3 "register_operand" "")
+ (match_operand:XF 4 "register_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0)
(match_dup 2))
@@ -7654,12 +8029,12 @@ byte_xor_operation:
"")
(define_split
- [(set (match_operand:XF 0 "register_operand" "=f,f")
+ [(set (match_operand:XF 0 "register_operand" "")
(if_then_else:XF (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(match_operand 3 "general_operand" "")])
- (match_operand:XF 4 "register_operand" "f,0")
- (match_operand:XF 5 "register_operand" "0,f")))]
+ (match_operand:XF 4 "register_operand" "")
+ (match_operand:XF 5 "register_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0) (compare (match_dup 2) (match_dup 3)))
(set (match_dup 0)
@@ -7713,42 +8088,43 @@ byte_xor_operation:
"#")
(define_split
- [(set (match_operand:DI 0 "register_operand" "=&r,&r")
+ [(set (match_operand:DI 0 "register_operand" "")
(if_then_else:DI (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(const_int 0)])
- (match_operand:DI 3 "nonimmediate_operand" "ro,0")
- (match_operand:DI 4 "nonimmediate_operand" "0,ro")))]
+ (match_operand:DI 3 "nonimmediate_operand" "")
+ (match_operand:DI 4 "nonimmediate_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0)
(match_dup 2))
- (set (match_dup 0)
- (if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)])
- (match_dup 3) (match_dup 4)))]
- "")
+ (set (match_dup 5)
+ (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
+ (match_dup 7) (match_dup 9)))
+ (set (match_dup 6)
+ (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
+ (match_dup 8) (match_dup 10)))]
+ "split_di (&operands[0], 1, &operands[5], &operands[6]);
+ split_di (&operands[3], 1, &operands[7], &operands[8]);
+ split_di (&operands[4], 1, &operands[9], &operands[10]);")
(define_split
- [(set (match_operand:DI 0 "register_operand" "=&r,&r")
+ [(set (match_operand:DI 0 "register_operand" "")
(if_then_else:DI (match_operator 1 "comparison_operator"
[(match_operand 2 "nonimmediate_operand" "")
(match_operand 3 "general_operand" "")])
- (match_operand:DI 4 "nonimmediate_operand" "ro,0")
- (match_operand:DI 5 "nonimmediate_operand" "0,ro")))]
+ (match_operand:DI 4 "nonimmediate_operand" "")
+ (match_operand:DI 5 "nonimmediate_operand" "")))]
"TARGET_CMOVE && reload_completed"
[(set (cc0) (compare (match_dup 2) (match_dup 3)))
- (set (match_dup 0)
- (if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)])
- (match_dup 4) (match_dup 5)))]
- "")
-
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=&r,&r")
- (if_then_else:DI (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:DI 2 "nonimmediate_operand" "ro,0")
- (match_operand:DI 3 "nonimmediate_operand" "0,ro")))]
- "TARGET_CMOVE && reload_completed"
- "* return output_int_conditional_move (which_alternative, operands);")
+ (set (match_dup 6)
+ (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
+ (match_dup 8) (match_dup 10)))
+ (set (match_dup 7)
+ (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
+ (match_dup 9) (match_dup 11)))]
+ "split_di (&operands[0], 1, &operands[6], &operands[7]);
+ split_di (&operands[4], 1, &operands[8], &operands[9]);
+ split_di (&operands[5], 1, &operands[10], &operands[11]);")
(define_insn "strlensi_unroll"
[(set (match_operand:SI 0 "register_operand" "=&r,&r")
@@ -7785,7 +8161,8 @@ byte_xor_operation:
(set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0)))
(clobber (match_dup 0))]
"TARGET_STACK_PROBE"
- "* return AS1(call,__alloca);")
+ "* return AS1(call,__alloca);"
+ [(set_attr "memory" "none")])
(define_expand "allocate_stack"
[(set (match_operand:SI 0 "register_operand" "=r")
diff --git a/contrib/gcc/config/i386/interix.c b/contrib/gcc/config/i386/interix.c
new file mode 100644
index 0000000..40062c7
--- /dev/null
+++ b/contrib/gcc/config/i386/interix.c
@@ -0,0 +1,110 @@
+/* Subroutines for insn-output.c for Windows NT.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "tree.h"
+#include "flags.h"
+
+/* Return string which is the former assembler name modified with a
+ suffix consisting of an atsign (@) followed by the number of bytes of
+ arguments */
+
+char *
+gen_stdcall_suffix (decl)
+ tree decl;
+{
+ int total = 0;
+ /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
+ of DECL_ASSEMBLER_NAME. */
+ char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ char *newsym;
+
+ if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
+ if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
+ == void_type_node)
+ {
+ tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
+
+ while (TREE_VALUE (formal_type) != void_type_node)
+ {
+ int parm_size
+ = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
+ /* Must round up to include padding. This is done the same
+ way as in store_one_arg. */
+ parm_size = ((parm_size + PARM_BOUNDARY - 1)
+ / PARM_BOUNDARY * PARM_BOUNDARY);
+ total += parm_size;
+ formal_type = TREE_CHAIN (formal_type);
+ }
+ }
+
+ newsym = xmalloc (strlen (asmname) + 10);
+ sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
+ return IDENTIFIER_POINTER (get_identifier (newsym));
+}
+
+#if 0
+/* Turn this back on when the linker is updated to handle grouped
+ .data$ sections correctly. See corresponding note in i386/interix.h.
+ MK. */
+
+/* Cover function for UNIQUE_SECTION. */
+
+void
+i386_pe_unique_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ int len;
+ char *name,*string,*prefix;
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ /* Strip off any encoding in fnname. */
+ STRIP_NAME_ENCODING (name, name);
+
+ /* The object is put in, for example, section .text$foo.
+ The linker will then ultimately place them in .text
+ (everything from the $ on is stripped). Don't put
+ read-only data in .rdata section to avoid a PE linker
+ bug when .rdata$* grouped sections are used in code
+ without a .rdata section. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ prefix = ".text$";
+ else if (DECL_READONLY_SECTION (decl, reloc))
+#ifdef READONLY_DATA_SECTION
+ prefix = ".rdata$";
+#else
+ prefix = ".text$";
+#endif
+ else
+ prefix = ".data$";
+ len = strlen (name) + strlen (prefix);
+ string = alloca (len + 1);
+ sprintf (string, "%s%s", prefix, name);
+
+ DECL_SECTION_NAME (decl) = build_string (len, string);
+}
+
+#endif /* 0 */
diff --git a/contrib/gcc/config/i386/isc.h b/contrib/gcc/config/i386/isc.h
index 5c39896..6c1c4c7 100644
--- a/contrib/gcc/config/i386/isc.h
+++ b/contrib/gcc/config/i386/isc.h
@@ -59,7 +59,7 @@
So don't make TARGET_IEEE_FP default for ISC. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0201
+#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
/* The ISC 2.0.2 software FPU emulator apparently can't handle
80-bit XFmode insns, so don't generate them. */
@@ -72,20 +72,23 @@
message. */
#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- char c; \
- int max = 0; \
- char *string = dump_base_name; \
- \
- fputs ("\t.file\t\"", FILE); \
- \
- while ((c = *string++) != 0 && max++ < 14) { \
- if (c == '\"' || c == '\\') \
- putc ('\\', FILE); \
- putc (c, FILE); \
- } \
- fputs ("\"\n", FILE); \
+#define ASM_FILE_START(FILE) \
+ do { \
+ int len = strlen (main_input_filename); \
+ char *na = main_input_filename + len; \
+ char shorter[15]; \
+ /* NA gets MAIN_INPUT_FILENAME sans directory names. */\
+ while (na > main_input_filename) \
+ { \
+ if (na[-1] == '/') \
+ break; \
+ na--; \
+ } \
+ strncpy (shorter, na, 14); \
+ shorter[14] = 0; \
+ fprintf (FILE, "\t.file\t"); \
+ output_quoted_string (FILE, shorter); \
+ fprintf (FILE, "\n"); \
} while (0)
/* Work around assembler forward label references generated in exception
diff --git a/contrib/gcc/config/i386/isccoff.h b/contrib/gcc/config/i386/isccoff.h
index 383b981..595c7d9 100644
--- a/contrib/gcc/config/i386/isccoff.h
+++ b/contrib/gcc/config/i386/isccoff.h
@@ -1,8 +1,8 @@
/* Definitions for Intel 386 running Interactive Unix System V.
Specifically, this is for recent versions that support POSIX;
for version 2.0.2, use configuration option i386-sysv instead.
- (But set TARGET_DEFAULT to 0201 if you do that,
- if you don't have a real 80387.) */
+ (But set TARGET_DEFAULT to (MASK_80307 | MASK_FLOAT_RETURNS)
+ if you do that, if you don't have a real 80387.) */
/* Mostly it's like AT&T Unix System V. */
diff --git a/contrib/gcc/config/i386/linux.h b/contrib/gcc/config/i386/linux.h
index 8e84bb5..7b368f8 100644
--- a/contrib/gcc/config/i386/linux.h
+++ b/contrib/gcc/config/i386/linux.h
@@ -150,9 +150,8 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-/* The egcs-1.1 branch is the last time we will have -Di386. -D__i386__ is the thing to use. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -Asystem(posix)"
+#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__i386__ -Dlinux -Asystem(posix)"
#undef CPP_SPEC
#ifdef USE_GNULIBC_1
@@ -227,8 +226,11 @@ Boston, MA 02111-1307, USA. */
This is used to align code labels according to Intel recommendations. */
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
-#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
- if ((LOG)!=0) \
- if ((MAX_SKIP)==0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
- else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP))
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ do { \
+ if ((LOG) != 0) { \
+ if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ } \
+ } while (0)
#endif
diff --git a/contrib/gcc/config/i386/mingw32.h b/contrib/gcc/config/i386/mingw32.h
index cd4d3e6..552cbcd 100644
--- a/contrib/gcc/config/i386/mingw32.h
+++ b/contrib/gcc/config/i386/mingw32.h
@@ -2,7 +2,7 @@
hosting on Windows32, using GNU tools and the Windows32 API Library,
as distinct from winnt.h, which is used to build GCC for use with a
windows style library and tool set and uses the Microsoft tools.
- Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,17 +21,17 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Most of this is the same as for Cygwin32, except for changing some
+/* Most of this is the same as for cygwin, except for changing some
specs. */
-#include "i386/cygwin32.h"
+#include "i386/cygwin.h"
/* Please keep changes to CPP_PREDEFINES in sync with i386/crtdll. The
only difference between the two should be __MSVCRT__ needed to
distinguish MSVC from CRTDLL runtime in mingw headers. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Di386 -D_WIN32 -DWIN32 -D__WIN32__ \
- -D__MINGW32__ -D__MSVCRT__ -DWINNT -D_X86_=1 -D__STDC__=1\
+ -D__MINGW32__=0.2 -D__MSVCRT__ -DWINNT -D_X86_=1 -D__STDC__=1\
-D__stdcall=__attribute__((__stdcall__)) \
-D_stdcall=__attribute__((__stdcall__)) \
-D__cdecl=__attribute__((__cdecl__)) \
@@ -44,25 +44,24 @@ Boston, MA 02111-1307, USA. */
#define STANDARD_INCLUDE_COMPONENT "MINGW32"
+#undef CPP_SPEC
+#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE}"
+
/* For Windows applications, include more libraries, but always include
kernel32. */
#undef LIB_SPEC
-#define LIB_SPEC \
-"%{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32 -ladvapi32 -lshell32"
+#define LIB_SPEC "%{mwindows:-lgdi32 -lcomdlg32} \
+ -luser32 -lkernel32 -ladvapi32 -lshell32"
/* Include in the mingw32 libraries with libgcc */
#undef LIBGCC_SPEC
#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lmsvcrt"
-/* Specify a different entry point when linking a DLL */
-#undef LINK_SPEC
-#define LINK_SPEC \
-"%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMainCRTStartup@12}"
-
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{mdll:dllcrt2%O%s} %{!mdll:crt2%O%s}"
-#define MATH_LIBRARY "-lmsvcrt"
+/* MS runtime does not need a separate math library. */
+#define MATH_LIBRARY ""
/* Output STRING, a string representing a filename, to FILE. We canonicalize
it to be in MS-DOS format. */
diff --git a/contrib/gcc/config/i386/moss.h b/contrib/gcc/config/i386/moss.h
index dadf3d8..d2548e3 100644
--- a/contrib/gcc/config/i386/moss.h
+++ b/contrib/gcc/config/i386/moss.h
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* I believe in reuse... */
#include "i386/linux.h"
diff --git a/contrib/gcc/config/i386/netbsd.h b/contrib/gcc/config/i386/netbsd.h
index 5978aec..d9f0646 100644
--- a/contrib/gcc/config/i386/netbsd.h
+++ b/contrib/gcc/config/i386/netbsd.h
@@ -1,6 +1,3 @@
-/* This goes away when the math-emulator is fixed */
-#define TARGET_CPU_DEFAULT 0400 /* TARGET_NO_FANCY_MATH_387 */
-
/* This is tested by i386gas.h. */
#define YES_UNDERSCORES
@@ -12,6 +9,11 @@
/* Get generic NetBSD definitions. */
#include <netbsd.h>
+/* This goes away when the math-emulator is fixed */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
+
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dunix -Di386 -D__NetBSD__ -Asystem(unix) -Asystem(NetBSD) -Acpu(i386) -Amachine(i386)"
diff --git a/contrib/gcc/config/i386/next.h b/contrib/gcc/config/i386/next.h
index 65f7402..bbc0e6b 100644
--- a/contrib/gcc/config/i386/next.h
+++ b/contrib/gcc/config/i386/next.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for Intel x86 CPU running NeXTSTEP
- Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
/* By default, target has a 80387, with IEEE FP. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (1|0100)
+#define TARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP)
/* Implicit library calls should use memcpy, not bcopy, etc. */
diff --git a/contrib/gcc/config/i386/openbsd.h b/contrib/gcc/config/i386/openbsd.h
index 1b56262..dc84f89 100644
--- a/contrib/gcc/config/i386/openbsd.h
+++ b/contrib/gcc/config/i386/openbsd.h
@@ -31,6 +31,11 @@ Boston, MA 02111-1307, USA. */
#define OBSD_OLD_GAS
#include <openbsd.h>
+/* This goes away when the math-emulator is fixed */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
+
/* Run-time target specifications */
#define CPP_PREDEFINES "-D__unix__ -D__i386__ -D__OpenBSD__ -Asystem(unix) -Asystem(OpenBSD) -Acpu(i386) -Amachine(i386)"
@@ -120,9 +125,10 @@ Boston, MA 02111-1307, USA. */
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
do { \
- if ((LOG) != 0) \
+ if ((LOG) != 0) { \
if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ } \
} while (0)
#endif
diff --git a/contrib/gcc/config/i386/osf1elf.h b/contrib/gcc/config/i386/osf1elf.h
index da61e8b..003400b 100644
--- a/contrib/gcc/config/i386/osf1elf.h
+++ b/contrib/gcc/config/i386/osf1elf.h
@@ -121,8 +121,8 @@ extern char *sys_siglist[];
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
- { "mcount", -MASK_NO_MCOUNT}, \
- { "no-mcount", MASK_NO_MCOUNT},
+ { "mcount", -MASK_NO_MCOUNT, "Profiling uses mcount" }, \
+ { "no-mcount", MASK_NO_MCOUNT, "" },
/* This macro generates the assembly code for function entry.
FILE is a stdio stream to output the code to.
diff --git a/contrib/gcc/config/i386/osfrose.h b/contrib/gcc/config/i386/osfrose.h
index 9cfe187..9ad9f95 100644
--- a/contrib/gcc/config/i386/osfrose.h
+++ b/contrib/gcc/config/i386/osfrose.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Intel 386 (OSF/1 with OSF/rose) version.
- Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1993, 1996, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -43,7 +43,6 @@ Boston, MA 02111-1307, USA. */
#define MASK_HALF_PIC 010000000000 /* Mask for half-pic code */
#define MASK_HALF_PIC_DEBUG 004000000000 /* Debug flag */
#define MASK_ELF 002000000000 /* ELF not rose */
-#define MASK_NO_IDENT 001000000000 /* suppress .ident */
#define MASK_NO_UNDERSCORES 000400000000 /* suppress leading _ */
#define MASK_LARGE_ALIGN 000200000000 /* align to >word boundaries */
#define MASK_NO_MCOUNT 000100000000 /* profiling uses mcount_ptr */
@@ -53,28 +52,25 @@ Boston, MA 02111-1307, USA. */
#define HALF_PIC_DEBUG TARGET_DEBUG
#define TARGET_ELF (target_flags & MASK_ELF)
#define TARGET_ROSE ((target_flags & MASK_ELF) == 0)
-#define TARGET_IDENT ((target_flags & MASK_NO_IDENT) == 0)
#define TARGET_UNDERSCORES ((target_flags & MASK_NO_UNDERSCORES) == 0)
#define TARGET_LARGE_ALIGN (target_flags & MASK_LARGE_ALIGN)
#define TARGET_MCOUNT ((target_flags & MASK_NO_MCOUNT) == 0)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
- { "half-pic", MASK_HALF_PIC}, \
- { "no-half-pic", -MASK_HALF_PIC}, \
- { "debug-half-pic", MASK_HALF_PIC_DEBUG}, \
- { "debugb", MASK_HALF_PIC_DEBUG}, \
- { "elf", MASK_ELF}, \
- { "rose", -MASK_ELF}, \
- { "ident", -MASK_NO_IDENT}, \
- { "no-ident", MASK_NO_IDENT}, \
- { "underscores", -MASK_NO_UNDERSCORES}, \
- { "no-underscores", MASK_NO_UNDERSCORES}, \
- { "large-align", MASK_LARGE_ALIGN}, \
- { "no-large-align", -MASK_LARGE_ALIGN}, \
- { "mcount", -MASK_NO_MCOUNT}, \
- { "mcount-ptr", MASK_NO_MCOUNT}, \
- { "no-mcount", MASK_NO_MCOUNT},
+ { "half-pic", MASK_HALF_PIC, "Emit half-PIC code" }, \
+ { "no-half-pic", -MASK_HALF_PIC, "" } \
+ { "debug-half-pic", MASK_HALF_PIC_DEBUG, 0 /* intentionally undoc */ }, \
+ { "debugb", MASK_HALF_PIC_DEBUG, 0 /* intentionally undoc */ }, \
+ { "elf", MASK_ELF, "Emit ELF object code" }, \
+ { "rose", -MASK_ELF, "Emit ROSE object code" }, \
+ { "underscores", -MASK_NO_UNDERSCORES, "Symbols have a leading underscore" }, \
+ { "no-underscores", MASK_NO_UNDERSCORES, "" }, \
+ { "large-align", MASK_LARGE_ALIGN, "Align to >word boundaries" }, \
+ { "no-large-align", -MASK_LARGE_ALIGN, "" }, \
+ { "mcount", -MASK_NO_MCOUNT, "Use mcount for profiling" }, \
+ { "mcount-ptr", MASK_NO_MCOUNT, "Use mcount_ptr for profiling" }, \
+ { "no-mcount", MASK_NO_MCOUNT, "" },
/* OSF/rose uses stabs, not dwarf. */
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
@@ -752,7 +748,7 @@ do \
if (HALF_PIC_P ()) \
HALF_PIC_FINISH (STREAM); \
\
- if (TARGET_IDENT) \
+ if (!flag_no_ident) \
{ \
char *fstart = main_input_filename; \
char *fname; \
diff --git a/contrib/gcc/config/i386/sco.h b/contrib/gcc/config/i386/sco.h
index 016e0a0..55af641 100644
--- a/contrib/gcc/config/i386/sco.h
+++ b/contrib/gcc/config/i386/sco.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running SCO Unix System V.
- Copyright (C) 1988, 1992, 1994, 1995 Free, 1996 Software Foundation, Inc.
+ Copyright (C) 1988, 92, 94, 95, 96, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,7 +31,7 @@ Boston, MA 02111-1307, USA. */
So don't make TARGET_IEEE_FP default for SCO. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0201
+#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
/* Let's guess that the SCO software FPU emulator can't handle
80-bit XFmode insns, so don't generate them. */
diff --git a/contrib/gcc/config/i386/sco5.h b/contrib/gcc/config/i386/sco5.h
index 74fb891..ac4e7e1 100644
--- a/contrib/gcc/config/i386/sco5.h
+++ b/contrib/gcc/config/i386/sco5.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running SCO Unix System V 3.2 Version 5.
- Copyright (C) 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 95-98, 1999 Free Software Foundation, Inc.
Contributed by Kean Johnston (hug@netcom.com)
This file is part of GNU CC.
@@ -211,8 +211,9 @@ do { \
#undef ASM_FILE_END
#define ASM_FILE_END(FILE) \
do { \
- fprintf ((FILE), "%s\t\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
+ if (!flag_no_ident) \
+ fprintf ((FILE), "%s\t\"GCC: (GNU) %s\"\n", \
+ IDENT_ASM_OP, version_string); \
} while (0)
#undef ASM_FINISH_DECLARE_OBJECT
@@ -689,7 +690,9 @@ dtors_section () \
#undef SELECT_SECTION
#define SELECT_SECTION(DECL,RELOC) \
{ \
- if (TREE_CODE (DECL) == STRING_CST) \
+ if (TARGET_ELF && flag_pic && RELOC) \
+ data_section (); \
+ else if (TREE_CODE (DECL) == STRING_CST) \
{ \
if (! flag_writable_strings) \
const_section (); \
@@ -698,11 +701,7 @@ dtors_section () \
} \
else if (TREE_CODE (DECL) == VAR_DECL) \
{ \
- if ((TARGET_ELF && flag_pic && RELOC) \
- || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
- || !DECL_INITIAL (DECL) \
- || (DECL_INITIAL (DECL) != error_mark_node \
- && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
+ if (! DECL_READONLY_SECTION (DECL, RELOC)) \
data_section (); \
else \
const_section (); \
@@ -726,11 +725,19 @@ dtors_section () \
&& strcmp (STR, "Tbss"))
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0301
+#define TARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
#undef HANDLE_SYSV_PRAGMA
#define HANDLE_SYSV_PRAGMA 1
+/* Though OpenServer support .weak in COFF, g++ doesn't play nice with it
+ * so we'll punt on it for now
+ */
+#define SUPPORTS_WEAK (TARGET_ELF)
+#define ASM_WEAKEN_LABEL(FILE,NAME) \
+ do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); } while (0)
+
#undef SCCS_DIRECTIVE
#define SCCS_DIRECTIVE 1
@@ -904,11 +911,23 @@ dtors_section () \
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
- { "coff", MASK_COFF }, \
- { "elf", -MASK_COFF },
+ { "coff", MASK_COFF, "Generate COFF output" }, \
+ { "elf", -MASK_COFF, "Generate ELF output" },
#define NO_DOLLAR_IN_LABEL
+/* Implicit library calls should use memcpy, not bcopy, etc. They are
+ faster on OpenServer libraries. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* Biggest alignment supported by the object file format of this
+ machine. Use this macro to limit the alignment which can be
+ specified using the `__attribute__ ((aligned (N)))' construct. If
+ not defined, the default value is `BIGGEST_ALIGNMENT'. */
+
+#define MAX_OFILE_ALIGNMENT (32768*8)
+
/*
Here comes some major hackery to get the crt stuff to compile properly.
Since we can (and do) compile for both COFF and ELF environments, we
diff --git a/contrib/gcc/config/i386/scodbx.h b/contrib/gcc/config/i386/scodbx.h
index a2581d4..d7d03f8 100644
--- a/contrib/gcc/config/i386/scodbx.h
+++ b/contrib/gcc/config/i386/scodbx.h
@@ -1,6 +1,6 @@
/* Definitions for Intel 386 running SCO Unix System V,
using dbx-in-coff encapsulation.
- Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1995, 1996, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
So don't make TARGET_IEEE_FP default for SCO. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0201
+#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
/* Use crt1.o as a startup file and crtn.o as a closing file. */
diff --git a/contrib/gcc/config/i386/sequent.h b/contrib/gcc/config/i386/sequent.h
index 4d76c38..8613ad7 100644
--- a/contrib/gcc/config/i386/sequent.h
+++ b/contrib/gcc/config/i386/sequent.h
@@ -1,5 +1,5 @@
/* Definitions for Sequent Intel 386.
- Copyright (C) 1988, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1994, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -26,11 +26,10 @@ Boston, MA 02111-1307, USA. */
/* By default, don't use IEEE compatible arithmetic comparisons
because the assembler can't handle the fucom insn.
- Return float values in the 387.
- (TARGET_80387 | TARGET_FLOAT_RETURNS_IN_80387) */
+ Return float values in the 387. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0201
+#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
/* Specify predefined symbols in preprocessor. */
diff --git a/contrib/gcc/config/i386/sol2.h b/contrib/gcc/config/i386/sol2.h
index 8fc3e61..cc5a089 100644
--- a/contrib/gcc/config/i386/sol2.h
+++ b/contrib/gcc/config/i386/sol2.h
@@ -93,3 +93,6 @@ Boston, MA 02111-1307, USA. */
|| (CHAR) == 'z')
#define STDC_0_IN_SYSTEM_HEADERS
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
diff --git a/contrib/gcc/config/i386/sun386.h b/contrib/gcc/config/i386/sun386.h
index 4d4d66c..4302ec4 100644
--- a/contrib/gcc/config/i386/sun386.h
+++ b/contrib/gcc/config/i386/sun386.h
@@ -59,11 +59,11 @@ do \
do { \
extern char *version_string, *language_string; \
{ \
- int len = strlen (dump_base_name); \
- char *na = dump_base_name + len; \
+ int len = strlen (main_input_filename); \
+ char *na = main_input_filename + len; \
char shorter[15]; \
- /* NA gets DUMP_BASE_NAME sans directory names. */\
- while (na > dump_base_name) \
+ /* NA gets MAIN_INPUT_FILENAME sans directory names. */\
+ while (na > main_input_filename) \
{ \
if (na[-1] == '/') \
break; \
diff --git a/contrib/gcc/config/i386/sysv5.h b/contrib/gcc/config/i386/sysv5.h
new file mode 100644
index 0000000..09a3bbe
--- /dev/null
+++ b/contrib/gcc/config/i386/sysv5.h
@@ -0,0 +1,35 @@
+/* Definitions for Intel 386 running System V Release 5 (i.e. UnixWare 7)
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Robert Lipe (robertlipe@usa.net)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#include "i386/sysv4.h"
+
+/* Dwarf2 is supported by native debuggers */
+
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Add -lcrt for Dwarf2 abbreviation table */
+#undef LIB_SPEC
+#define LIB_SPEC "%{pthread:-lthread} %{!shared:%{!symbolic:-lc -lcrt}}"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{pthread:-D_REENTRANT}"
diff --git a/contrib/gcc/config/i386/t-cygwin b/contrib/gcc/config/i386/t-cygwin
new file mode 100644
index 0000000..175f66b
--- /dev/null
+++ b/contrib/gcc/config/i386/t-cygwin
@@ -0,0 +1,16 @@
+LIBGCC1 = libgcc1-asm.a
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = i386/cygwin.asm
+LIB1ASMFUNCS = _chkstk
+
+# cygwin always has a limits.h, but, depending upon how we are doing
+# the build, it may not be installed yet.
+LIMITS_H_TEST = true
+
+# If we are building next to winsup, this will let us find the real
+# limits.h when building libgcc2. Otherwise, winsup must be installed
+# first.
+LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/include
+
+winnt.o: $(srcdir)/config/i386/winnt.c
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c
diff --git a/contrib/gcc/config/i386/t-dgux b/contrib/gcc/config/i386/t-dgux
index 292331f..1bf024a 100644
--- a/contrib/gcc/config/i386/t-dgux
+++ b/contrib/gcc/config/i386/t-dgux
@@ -1,4 +1,8 @@
#
# target makefile for dgux
#
-EXTRA_PARTS=crtbegin.o crtend.o
+EXTRA_PARTS=crti.o crtbegin.o crtend.o
+
+crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES)
+ sed -e '/^!/d' <$(srcdir)/config/i386/sol2-ci.asm >crti.s
+ $(GCC_FOR_TARGET) -c -o crti.o crti.s
diff --git a/contrib/gcc/config/i386/t-djgpp b/contrib/gcc/config/i386/t-djgpp
new file mode 100644
index 0000000..6160b7e
--- /dev/null
+++ b/contrib/gcc/config/i386/t-djgpp
@@ -0,0 +1,2 @@
+LIBGCC1 = libgcc1.null
+CROSS_LIBGCC1 = libgcc1.null
diff --git a/contrib/gcc/config/i386/t-interix b/contrib/gcc/config/i386/t-interix
new file mode 100644
index 0000000..4c6d84f
--- /dev/null
+++ b/contrib/gcc/config/i386/t-interix
@@ -0,0 +1,16 @@
+# t-interix
+LIBGCC1 = libgcc1-asm.a
+CROSS_LIBGCC1 = libgcc1-asm.a
+
+LIB1ASMSRC = i386/cygwin.asm
+LIB1ASMFUNCS = _chkstk
+
+interix.o: $(srcdir)/config/i386/interix.c
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/interix.c
+
+# System headers will track gcc's needs.
+# Even LANG_EXTRA_HEADERS may be temporary.
+USER_H=$(LANG_EXTRA_HEADERS)
+
+# We don't want this one either.
+INSTALL_ASSERT_H=
diff --git a/contrib/gcc/config/i386/t-udk b/contrib/gcc/config/i386/t-udk
new file mode 100644
index 0000000..96e1864
--- /dev/null
+++ b/contrib/gcc/config/i386/t-udk
@@ -0,0 +1,2 @@
+# Tell fixincludes to work on this set of headers
+SYSTEM_HEADER_DIR = /udk/usr/include
diff --git a/contrib/gcc/config/i386/t-uwin b/contrib/gcc/config/i386/t-uwin
new file mode 100644
index 0000000..8e59868
--- /dev/null
+++ b/contrib/gcc/config/i386/t-uwin
@@ -0,0 +1,5 @@
+#
+# This is included *after* t-cygwin to override LIB1ASMSRC.
+#
+LIB1ASMSRC = i386/uwin.asm
+
diff --git a/contrib/gcc/config/i386/udk.h b/contrib/gcc/config/i386/udk.h
new file mode 100644
index 0000000..8e03abf
--- /dev/null
+++ b/contrib/gcc/config/i386/udk.h
@@ -0,0 +1,30 @@
+/* Configuration for i386 interfacing with SCO's Universal Development Kit
+ probably running on OpenServer 5, Unixware 2, or Unixware 5
+ */
+
+
+/* We're very much the SVR4 target with "/udk" prepended to everything that's
+ interesting */
+
+#include "i386/sysv5.h"
+
+#undef MD_EXEC_PREFIX
+#define MD_EXEC_PREFIX "/udk/usr/ccs/bin/"
+
+#undef MD_STARTFILE_PREFIX
+#define MD_STARTFILE_PREFIX "/udk/usr/ccs/lib/"
+
+#define STANDARD_INCLUDE_DIR "/udk/usr/include"
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{h*} %{v:-V} \
+ %{b} %{Wl,*:%*} \
+ %{static:-dn -Bstatic} \
+ %{shared:-G -dy -z text} \
+ %{symbolic:-Bsymbolic -G -dy -z text} \
+ %{G:-G} \
+ %{YP,*} \
+ %{!YP,*:%{p:-Y P,/udk/usr/ccs/lib/libp:/udk/usr/lib/libp:/udk/usr/ccs/lib:/udk/usr/lib} \
+ %{!p:-Y P,/udk/usr/ccs/lib:/udk/usr/lib}} \
+ %{Qy:} %{!Qn:-Qy}"
+
diff --git a/contrib/gcc/config/i386/unix.h b/contrib/gcc/config/i386/unix.h
index 47440dd..771d802 100644
--- a/contrib/gcc/config/i386/unix.h
+++ b/contrib/gcc/config/i386/unix.h
@@ -1,5 +1,5 @@
/* Definitions for Unix assembler syntax for the Intel 80386.
- Copyright (C) 1988, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1994, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -131,10 +131,9 @@ Boston, MA 02111-1307, USA. */
(fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
/* By default, target has a 80387, uses IEEE compatible arithmetic,
- and returns float values in the 387, ie,
- (TARGET_80387 | TARGET_IEEE_FP | TARGET_FLOAT_RETURNS_IN_80387) */
+ and returns float values in the 387. */
-#define TARGET_DEFAULT 0301
+#define TARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
/* Floating-point return values come in the FP register. */
@@ -177,7 +176,7 @@ do { \
output_asm_insn (AS1 (call,%P1), xops); \
ASM_OUTPUT_INTERNAL_LABEL (FILE, "L", CODE_LABEL_NUMBER (xops[1])); \
output_asm_insn (AS1 (pop%L0,%0), xops); \
- output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops); \
+ output_asm_insn ("addl $%__GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops); \
fprintf (FILE, "\tmovl "); \
assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
fprintf (FILE, "@GOT(%%ebx),%%ecx\n\tpopl %%ebx\n\tjmp *%%ecx\n"); \
diff --git a/contrib/gcc/config/i386/uwin.asm b/contrib/gcc/config/i386/uwin.asm
new file mode 100644
index 0000000..6268343
--- /dev/null
+++ b/contrib/gcc/config/i386/uwin.asm
@@ -0,0 +1,32 @@
+/* stuff needed for libgcc1 on win32. */
+
+#ifdef L_chkstk
+
+ .global __chkstk
+ .global __alloca
+__chkstk:
+__alloca:
+ pushl %ecx /* save temp */
+ movl %esp,%ecx /* get sp */
+ addl $0x8,%ecx /* and point to return addr */
+
+probe: cmpl $0x1000,%eax /* > 4k ?*/
+ jb done
+
+ subl $0x1000,%ecx /* yes, move pointer down 4k*/
+ orl $0x0,(%ecx) /* probe there */
+ subl $0x1000,%eax /* decrement count */
+ jmp probe /* and do it again */
+
+done: subl %eax,%ecx
+ orl $0x0,(%ecx) /* less that 4k, just peek here */
+
+ movl %esp,%eax
+ movl %ecx,%esp /* decrement stack */
+
+ movl (%eax),%ecx /* recover saved temp */
+ movl 4(%eax),%eax /* get return address */
+ jmp *%eax
+
+
+#endif
diff --git a/contrib/gcc/config/i386/uwin.h b/contrib/gcc/config/i386/uwin.h
new file mode 100644
index 0000000..73e04ad
--- /dev/null
+++ b/contrib/gcc/config/i386/uwin.h
@@ -0,0 +1,93 @@
+/* Operating system specific defines to be used when targeting GCC for
+ hosting on U/WIN (Windows32), using GNU tools and the Windows32 API
+ Library, as distinct from winnt.h, which is used to build GCC for use
+ with a windows style library and tool set and uses the Microsoft tools.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Most of this is the same as for Cygwin32, except for changing some
+ specs. */
+
+#include "i386/cygwin.h"
+
+#define STANDARD_INCLUDE_COMPONENT "UWIN"
+#define SYSTEM_INCLUDE_DIR "/usr/gnu/include"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__i386__ -D_WIN32 -D__WIN32__ \
+ -D_UWIN -DWINNT -D_X86_=1 -D__STDC__=1 \
+ -D__UWIN__ -D__MSVCRT__ \
+ -D_STD_INCLUDE_DIR=mingw32 \
+ -D__stdcall=__attribute__((__stdcall__)) \
+ _D_stdcall=__attribute__((__stdcall__)) \
+ -D__cdecl=__attribute__((__cdecl__)) \
+ -D__declspec(x)=__attribute__((x)) \
+ -Asystem(winnt) -Acpu(i386) -Amachine(i386)"
+
+#undef CPP_SPEC
+#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
+ -include /usr/include/astwin32.h \
+ -idirafter /usr/gnu/include/mingw32"
+
+/* For Windows applications, include more libraries, but always include
+ kernel32. */
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32 -ladvapi32"
+
+/* This is needed in g77spec.c for now. Will be removed in the future. */
+#define WIN32_UWIN_TARGET 1
+
+/* Include in the mingw32 libraries with libgcc */
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "-lgnuwin -lposix -lgcc -last -lmoldname -lmsvcrt"
+
+/* Specify a different entry point when linking a DLL */
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMainCRTStartup@12}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{mdll:dllcrt2%O%s} %{!mdll:crt2%O%s}"
+
+/* These are PE BFD bug workarounds. Should go away eventually. */
+
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ if (i386_pe_dllexport_name_p (NAME)) \
+ { \
+ drectve_section (); \
+ fprintf ((FILE), "\t.ascii \" -export:%s\"\n", \
+ I386_PE_STRIP_ENCODING (NAME)); \
+ function_section (DECL); \
+ } \
+ /* disable i386_pe_declare_function_type for UWIN */ \
+ if (0 && write_symbols != SDB_DEBUG) \
+ i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
+ while (0)
+
+#undef ASM_OUTPUT_EXTERNAL
+#undef ASM_OUTPUT_EXTERNAL_LIBCALL
+#undef ASM_FILE_END
+
diff --git a/contrib/gcc/config/i386/vxi386.h b/contrib/gcc/config/i386/vxi386.h
index 1044286..0bd27b4 100644
--- a/contrib/gcc/config/i386/vxi386.h
+++ b/contrib/gcc/config/i386/vxi386.h
@@ -18,6 +18,45 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#undef CPP_CPU_SPEC
+#define CPP_CPU_SPEC "\
+-Asystem(unix) -Acpu(i386) -Amachine(i386) \
+%{!ansi:-Di386} -D__i386 -D__i386__ \
+%{march=i386:-DCPU=I80386} \
+%{march=i486:-DCPU=I80486 %(cpp_486)} \
+%{march=pentium:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUM %(cpp_586)} \
+%{march=pentiumpro:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUMPRO %(cpp_686)} \
+%{!march=*: \
+ %{mcpu=i386:-DCPU=I80386} \
+ %{mcpu=i486:-DCPU=I80486 %(cpp_486)} %{m486:-DCPU=I80486 %(cpp_486)} \
+ %{mpentium:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUM %(cpp_586)} \
+ %{mcpu=pentium:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUM %(cpp_586)} \
+ %{mpentiumpro:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUMPRO %(cpp_686)} \
+ %{mcpu=pentiumpro:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUMPRO %(cpp_686)} \
+ %{!mcpu*:%{!m486:%{!mpentium*:-DCPU=I80386 %(cpp_cpu_default)}}}}"
+
#include "i386/i386-aout.h"
#define HANDLE_SYSV_PRAGMA
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__vxworks -D__i386__"
+
+/* VxWorks does all the library stuff itself. */
+
+#undef LIB_SPEC
+#define LIB_SPEC ""
+
+/* VxWorks uses object files, not loadable images. make linker just
+ combine objects. */
+
+#undef LINK_SPEC
+#define LINK_SPEC "-r"
+
+/* VxWorks provides the functionality of crt0.o and friends itself. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC ""
diff --git a/contrib/gcc/config/i386/win-nt.h b/contrib/gcc/config/i386/win-nt.h
index 60c0bb6..97f10c3 100644
--- a/contrib/gcc/config/i386/win-nt.h
+++ b/contrib/gcc/config/i386/win-nt.h
@@ -131,9 +131,7 @@ while (0)
#undef ASM_FILE_START
#endif
#define ASM_FILE_START(FILE) \
- do { fprintf (FILE, "\t.file\t"); \
- output_quoted_string (FILE, dump_base_name); \
- fprintf (FILE, "\n"); \
+ do { output_file_directive (FILE, main_input_filename); \
fprintf (FILE, ".global\t__fltused\n"); \
} while (0)
diff --git a/contrib/gcc/config/i386/win32.h b/contrib/gcc/config/i386/win32.h
new file mode 100644
index 0000000..d62abbf
--- /dev/null
+++ b/contrib/gcc/config/i386/win32.h
@@ -0,0 +1,280 @@
+/* Operating system specific defines to be used when targeting GCC for
+ hosting on Windows NT 3.x, using a Unix style C library and tools,
+ as distinct from winnt.h, which is used to build GCC for use with a
+ windows style library and tool set and uses the Microsoft tools.
+ Copyright (C) 1995-1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define YES_UNDERSCORES
+
+/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
+#define HANDLE_PRAGMA_PACK_PUSH_POP 1
+
+#define DBX_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#include "i386/gas.h"
+#include "dbxcoff.h"
+
+/* Augment TARGET_SWITCHES with the cygwin/win32 options. */
+#define MASK_WIN32 0x40000000 /* Use -lming32 interface */
+#define MASK_CYGWIN 0x20000000 /* Use -lcygwin interface */
+#define MASK_WINDOWS 0x10000000 /* Use windows interface */
+#define MASK_DLL 0x08000000 /* Use dll interface */
+#define MASK_NOP_FUN_DLLIMPORT 0x20000 /* Ignore dllimport for functions */
+
+#define TARGET_WIN32 (target_flags & MASK_WIN32)
+#define TARGET_CYGWIN (target_flags & MASK_CYGWIN)
+#define TARGET_WINDOWS (target_flags & MASK_WINDOWS)
+#define TARGET_DLL (target_flags & MASK_DLL)
+#define TARGET_NOP_FUN_DLLIMPORT (target_flags & MASK_NOP_FUN_DLLIMPORT)
+
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+ { "win32", MASK_WIN32, "Use Mingw32 interface" }, \
+ { "cygwin", MASK_CYGWIN, "Use Cygwin interface" }, \
+ { "windows", MASK_WINDOWS, "Use bare Windows interface" }, \
+ { "dll", MASK_DLL, "Generate code for a DLL" }, \
+ { "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, "Ignore dllimport for functions" }, \
+ { "no-nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, "" },
+
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D_WIN32 \
+ -DWINNT -D_X86_=1 -D__STDC__=1\
+ -D__stdcall=__attribute__((__stdcall__)) \
+ -D__cdecl=__attribute__((__cdecl__)) \
+ -Asystem(winnt)"
+
+#undef STARTFILE_SPEC
+
+#define STARTFILE_SPEC "%{mdll:dllcrt0%O%s} %{!mdll: %{!mcygwin:mcrt0%O%s} \
+ %{mcygwin:crt0%O%s} %{pg:gcrt0%O%s}}"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
+ %{!mcygwin:-iwithprefixbefore include/mingw32 -D__MINGW32__} \
+ %{mcygwin:-D__CYGWIN32__ -D__CYGWIN__}"
+
+/* We have to dynamic link to get to the system DLLs. All of libc, libm and
+ the Unix stuff is in cygwin.dll. The import library is called
+ 'libcygwin.a'. For Windows applications, include more libraries, but
+ always include kernel32. We'd like to specific subsystem windows to
+ ld, but that doesn't work just yet. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{pg:-lgmon} \
+ %{!mcygwin:-lmingw32 -lmoldname -lmsvcrt -lcrtdll} \
+ %{mcygwin:-lcygwin} %{mwindows:-luser32 -lgdi32 -lcomdlg32} \
+ -lkernel32 -ladvapi32 -lshell32"
+
+#define LINK_SPEC "%{mwindows:--subsystem windows} \
+ %{mdll:--dll -e _DllMainCRTStartup@12}"
+
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
+#define WCHAR_UNSIGNED 1
+#define WCHAR_TYPE_SIZE 16
+#define WCHAR_TYPE "short unsigned int"
+/* Currently we do not have the atexit() function,
+ so take that from libgcc2.c */
+
+#define NEED_ATEXIT 1
+#define HAVE_ATEXIT 1
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_ctor, in_dtor
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CTOR_SECTION_FUNCTION \
+ DTOR_SECTION_FUNCTION
+
+#define CTOR_SECTION_FUNCTION \
+void \
+ctor_section () \
+{ \
+ if (in_section != in_ctor) \
+ { \
+ fprintf (asm_out_file, "\t.section .ctor\n"); \
+ in_section = in_ctor; \
+ } \
+}
+
+#define DTOR_SECTION_FUNCTION \
+void \
+dtor_section () \
+{ \
+ if (in_section != in_dtor) \
+ { \
+ fprintf (asm_out_file, "\t.section .dtor\n"); \
+ in_section = in_dtor; \
+ } \
+}
+
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctor_section (); \
+ fprintf (FILE, "%s\t", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtor_section (); \
+ fprintf (FILE, "%s\t", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* Define this macro if references to a symbol must be treated
+ differently depending on something about the variable or
+ function named by the symbol (such as what section it is in).
+
+ On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol
+ so that we may access it directly in the GOT.
+
+ On i386 running Windows NT, modify the assembler name with a suffix
+ consisting of an atsign (@) followed by string of digits that represents
+ the number of bytes of arguments passed to the function, if it has the
+ attribute STDCALL. */
+
+#ifdef ENCODE_SECTION_INFO
+#undef ENCODE_SECTION_INFO
+#define ENCODE_SECTION_INFO(DECL) \
+do \
+ { \
+ if (flag_pic) \
+ { \
+ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
+ = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ || ! TREE_PUBLIC (DECL)); \
+ } \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ if (lookup_attribute ("stdcall", \
+ TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \
+ XEXP (DECL_RTL (DECL), 0) = \
+ gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (DECL)); \
+ } \
+while (0)
+#endif
+
+/* This macro gets just the user-specified name
+ out of the string in a SYMBOL_REF. Discard
+ trailing @[NUM] encoded by ENCODE_SECTION_INFO.
+ Do we need the stripping of leading '*'? */
+#undef STRIP_NAME_ENCODING
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+do { \
+ char *_p; \
+ char *_name = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*')); \
+ for (_p = _name; *_p && *_p != '@'; ++_p) \
+ ; \
+ if (*_p == '@') \
+ { \
+ int _len = _p - _name; \
+ (VAR) = (char *) alloca (_len + 1); \
+ strncpy ((VAR), _name, _len); \
+ (VAR)[_len] = '\0'; \
+ } \
+ else \
+ (VAR) = _name; \
+} while (0)
+
+
+/* Emit code to check the stack when allocating more that 4000
+ bytes in one go. */
+
+#define CHECK_STACK_LIMIT 4000
+
+/* By default, target has a 80387, uses IEEE compatible arithmetic,
+ and returns float values in the 387 and needs stack probes */
+#undef TARGET_DEFAULT
+
+#define TARGET_DEFAULT \
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+
+/* Define this macro if in some cases global symbols from one translation
+ unit may not be bound to undefined symbols in another translation unit
+ without user intervention. For instance, under Microsoft Windows
+ symbols must be explicitly imported from shared libraries (DLLs). */
+#define MULTIPLE_SYMBOL_SPACES
+
+#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL)
+extern void i386_pe_unique_section ();
+#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
+
+#define SUPPORTS_ONE_ONLY 1
+
+/* A C statement to output something to the assembler file to switch to section
+ NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
+ NULL_TREE. Some target formats do not support arbitrary sections. Do not
+ define this macro in such cases. */
+#undef ASM_OUTPUT_SECTION_NAME
+#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
+do { \
+ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
+ fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \
+ else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
+ fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \
+ else \
+ fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \
+ /* Functions may have been compiled at various levels of \
+ optimization so we can't use `same_size' here. Instead, \
+ have the linker pick one. */ \
+ if ((DECL) && DECL_ONE_ONLY (DECL)) \
+ fprintf (STREAM, "\t.linkonce %s\n", \
+ TREE_CODE (DECL) == FUNCTION_DECL \
+ ? "discard" : "same_size"); \
+} while (0)
+
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START " #"
+
+/* DWARF2 Unwinding doesn't work with exception handling yet. */
+#define DWARF2_UNWIND_INFO 0
+
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+#define SUBTARGET_PROLOGUE \
+ if (profile_flag \
+ && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),\
+ "main") == 0) \
+ { \
+ rtx xops[1]; \
+ xops[0] = gen_rtx_MEM (FUNCTION_MODE, \
+ gen_rtx (SYMBOL_REF, Pmode, "_monstartup")); \
+ if (do_rtl) \
+ emit_call_insn (gen_rtx (CALL, VOIDmode, xops[0], const0_rtx)); \
+ else \
+ output_asm_insn (AS1 (call,%P1), xops); \
+ }
diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c
index 0058eb7..24d8617 100644
--- a/contrib/gcc/config/i386/winnt.c
+++ b/contrib/gcc/config/i386/winnt.c
@@ -1,6 +1,6 @@
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
- Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -493,7 +493,7 @@ i386_pe_unique_section (decl, reloc)
}
/* The Microsoft linker requires that every function be marked as
- DT_FCN. When using gas on cygwin32, we must emit appropriate .type
+ DT_FCN. When using gas on cygwin, we must emit appropriate .type
directives. */
#include "gsyms.h"
@@ -545,8 +545,29 @@ i386_pe_record_external_function (name)
extern_head = p;
}
+static struct extern_list *exports_head;
+
+/* Assemble an export symbol entry. We need to keep a list of
+ these, so that we can output the export list at the end of the
+ assembly. We used to output these export symbols in each function,
+ but that causes problems with GNU ld when the sections are
+ linkonce. */
+
+void
+i386_pe_record_exported_symbol (name)
+ char *name;
+{
+ struct extern_list *p;
+
+ p = (struct extern_list *) permalloc (sizeof *p);
+ p->next = exports_head;
+ p->name = name;
+ exports_head = p;
+}
+
/* This is called at the end of assembly. For each external function
- which has not been defined, we output a declaration now. */
+ which has not been defined, we output a declaration now. We also
+ output the .drectve section. */
void
i386_pe_asm_file_end (file)
@@ -567,4 +588,13 @@ i386_pe_asm_file_end (file)
i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl));
}
}
+
+ if (exports_head)
+ drectve_section ();
+ for (p = exports_head; p != NULL; p = p->next)
+ {
+ fprintf (file, "\t.ascii \" -export:%s\"\n",
+ I386_PE_STRIP_ENCODING (p->name));
+ }
}
+
diff --git a/contrib/gcc/config/i386/x-cygwin b/contrib/gcc/config/i386/x-cygwin
new file mode 100644
index 0000000..f251835
--- /dev/null
+++ b/contrib/gcc/config/i386/x-cygwin
@@ -0,0 +1,4 @@
+# Don't run fixproto
+STMP_FIXPROTO =
+# prefix.c wants to poke around the Registry
+CLIB = -ladvapi32
diff --git a/contrib/gcc/config/i386/x-djgpp b/contrib/gcc/config/i386/x-djgpp
new file mode 100644
index 0000000..89f31ff
--- /dev/null
+++ b/contrib/gcc/config/i386/x-djgpp
@@ -0,0 +1,24 @@
+# translate the version string, so it can be used on DJGPP, where only
+# one dot in filename is allowed
+
+# to avoid recursion when redefining $(version)
+_version:=$(version)
+__version=$(subst ., ,$(_version))
+version=$(word 1,$(__version))$(word 2,$(__version)).$(word 3,$(__version))
+
+SYSTEM_HEADER_DIR=$(DJDIR)/include
+X_CPPFLAGS=-DSTANDARD_INCLUDE_DIR=\"\$$DJDIR/include\" \
+ -DSTANDARD_INCLUDE_COMPONENT=\"\"
+
+# when building a native compiler for DJGPP, make the target_alias
+# a shorter name, since otherwise it will produce some problems, when
+# using the same gcc once with long filenames and once with short (8+3)
+# filenames
+ifeq ($(findstring -pc-msdosdjgpp,$(target_alias)),-pc-msdosdjgpp)
+target_alias=djgpp
+endif
+
+# on DJGPP the 'ln -s' does not work correctly
+LN = cp -p
+LN_S = cp -p
+
diff --git a/contrib/gcc/config/i386/xm-cygwin.h b/contrib/gcc/config/i386/xm-cygwin.h
new file mode 100644
index 0000000..ab59627
--- /dev/null
+++ b/contrib/gcc/config/i386/xm-cygwin.h
@@ -0,0 +1,58 @@
+/* Configuration for GNU C-compiler for hosting on Windows NT.
+ using a unix style C library.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define EXECUTABLE_SUFFIX ".exe"
+#define NO_SYS_SIGLIST 1
+
+/* We support both "/" and "\" since everybody tests both but we
+ default to "/". This is important because if gcc produces Win32
+ paths containing backslashes, make and configure may treat the
+ backslashes as escape characters. Many Win32 programs use forward
+ slashes so using a forward slash shouldn't be problematic from the
+ perspective of wanting gcc to produce native Win32 paths. */
+#define DIR_SEPARATOR '/'
+#define DIR_SEPARATOR_2 '\\'
+
+/* Convert win32 style path lists to POSIX style for consistency. */
+#undef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME) \
+do { \
+ char *_epath; \
+ char *_posixepath; \
+ _epath = _posixepath = getenv (NAME); \
+ /* if we have a posix path list, convert to posix path list */ \
+ if (_epath != NULL && *_epath != 0 \
+ && ! cygwin_posix_path_list_p (_epath)) \
+ { \
+ char *p; \
+ _posixepath = (char *) xmalloc \
+ (cygwin_win32_to_posix_path_list_buf_size (_epath)); \
+ cygwin_win32_to_posix_path_list (_epath, _posixepath); \
+ } \
+ (VAR) = _posixepath; \
+} while (0)
+
+#define PATH_SEPARATOR ':'
+
+/* This is needed so that protoize will compile. */
+#ifndef POSIX
+#define POSIX
+#endif
diff --git a/contrib/gcc/config/i386/xm-djgpp.h b/contrib/gcc/config/i386/xm-djgpp.h
new file mode 100644
index 0000000..ccf6e3c
--- /dev/null
+++ b/contrib/gcc/config/i386/xm-djgpp.h
@@ -0,0 +1,44 @@
+/* Configuration for GNU C-compiler for Intel 80386 running DJGPP.
+ Copyright (C) 1988, 1996, 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define __MSDOS__ 1
+
+#include "i386/xm-i386.h"
+
+/* Use semicolons to separate elements of a path. */
+#define PATH_SEPARATOR ';'
+
+#define EXECUTABLE_SUFFIX ".exe"
+
+/* Even though we support "/", allow "\" since everybody tests both. */
+#define DIR_SEPARATOR '/'
+#define DIR_SEPARATOR_2 '\\'
+
+/* Allow test for DOS drive names. */
+#define HAVE_DOS_BASED_FILESYSTEM
+
+#define LIBSTDCXX "-lstdcxx"
+
+/* System dependant initialization for collect2
+ to tell system() to act like Unix. */
+#define COLLECT2_HOST_INITIALIZATION \
+ do { __system_flags |= (__system_allow_multiple_cmds \
+ | __system_emulate_chdir); } while (0)
+
diff --git a/contrib/gcc/config/i386/xm-dos.h b/contrib/gcc/config/i386/xm-dos.h
index a734a81..4e1cb42 100644
--- a/contrib/gcc/config/i386/xm-dos.h
+++ b/contrib/gcc/config/i386/xm-dos.h
@@ -1,3 +1,23 @@
+/* Configuration for GNU C-compiler for Intel 80386 running DOS.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
#include "i386/xm-i386.h"
/* Use semicolons to separate elements of a path. */
@@ -5,6 +25,10 @@
/* Use backslashs to separate levels of directory. */
#define DIR_SEPARATOR '\\'
+#define DIR_SEPARATOR_2 '/'
+
+/* Allow checks for drive names. */
+#define HAVE_DOS_BASED_FILE_SYSTEM
/* Suffix for executable file names. */
#define EXECUTABLE_SUFFIX ".exe"
diff --git a/contrib/gcc/config/i386/xm-i386-interix.h b/contrib/gcc/config/i386/xm-i386-interix.h
new file mode 100644
index 0000000..8bfd5e2
--- /dev/null
+++ b/contrib/gcc/config/i386/xm-i386-interix.h
@@ -0,0 +1,34 @@
+/* Configuration for GNU compiler
+ for an Intel i386 or later processor running Interix.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Donn Terry (donn@interix.com)
+ Derived from code by Douglas B. Rupp (drupp@cs.washington.edu)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <i386/xm-i386.h>
+
+#define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG
+#ifdef __GNUC__
+# define HOST_WIDEST_INT long long
+#else
+# define HOST_WIDEST_INT __int64
+#endif
+#define HOST_WIDEST_INT_PRINT_DEC "%lld"
+#define HOST_WIDEST_INT_PRINT_UNSIGNED "%llu"
+#define HOST_WIDEST_INT_PRINT_HEX "0x%llx"
diff --git a/contrib/gcc/config/i386/xm-mingw32.h b/contrib/gcc/config/i386/xm-mingw32.h
index d818142..6872580 100644
--- a/contrib/gcc/config/i386/xm-mingw32.h
+++ b/contrib/gcc/config/i386/xm-mingw32.h
@@ -1,6 +1,6 @@
/* Configuration for GNU C-compiler for hosting on Windows32.
using GNU tools and the Windows32 API Library.
- Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -36,6 +36,12 @@ Boston, MA 02111-1307, USA. */
/* Even though we support "/", allow "\" since everybody tests both. */
#define DIR_SEPARATOR '\\'
+#define DIR_SEPARATOR_2 '/'
+
+/* Mingw32 does not try to hide the underlying DOS-based file system
+ like Cygwin does. */
+#define HAVE_DOS_BASED_FILE_SYSTEM
+
#define EXECUTABLE_SUFFIX ".exe"
#undef PATH_SEPARATOR
diff --git a/contrib/gcc/config/i386/xm-os2.h b/contrib/gcc/config/i386/xm-os2.h
index aed925e..b8a5ad0 100644
--- a/contrib/gcc/config/i386/xm-os2.h
+++ b/contrib/gcc/config/i386/xm-os2.h
@@ -1,6 +1,6 @@
/* Configuration for GNU compiler
for an Intel i386 or later processor running OS/2 2.x.
- Copyright (C) 1993, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
Contributed by Samuel Figueroa (figueroa@apple.com)
This file is part of GNU CC.
@@ -54,6 +54,12 @@ int spawnvp (int modeflag, char *path, char *argv[]);
#ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '\\'
#endif
+#ifndef DIR_SEPARATOR_2
+#define DIR_SEPARATOR_2 '/'
+#endif
+
+/* Allow handling of drive names. */
+#define HAVE_DOS_BASED_FILE_SYSTEM
#define EXECUTABLE_SUFFIX ".exe"
diff --git a/contrib/gcc/config/i386/xm-uwin.h b/contrib/gcc/config/i386/xm-uwin.h
new file mode 100644
index 0000000..2e1ecde
--- /dev/null
+++ b/contrib/gcc/config/i386/xm-uwin.h
@@ -0,0 +1,39 @@
+/* Configuration for GNU C-compiler for hosting on Windows32.
+ using GNU tools and the Windows32 API Library.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef ONLY_INT_FIELD
+#define ONLY_INT_FIELDS 1
+#endif
+
+#ifndef USE_PROTOTYPES
+#define USE_PROTOTYPES 1
+#endif
+
+/* U/WIN system calls only support '/' */
+#undef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#undef EXECUTABLE_SUFFIX
+#define EXECUTABLE_SUFFIX ".exe"
+
+#undef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
+
diff --git a/contrib/gcc/config/interix.h b/contrib/gcc/config/interix.h
new file mode 100644
index 0000000..9cef8b3
--- /dev/null
+++ b/contrib/gcc/config/interix.h
@@ -0,0 +1,107 @@
+/* Operating system specific defines to be used when targeting GCC for
+ Interix
+ Copyright (C) 1994, 1995, 1999 Free Software Foundation, Inc.
+ Donn Terry, Softway Systems, Inc. (donn@softway.com)
+ Modified from code
+ Contributed by Douglas B. Rupp (drupp@cs.washington.edu).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* POSIX/Uni-thread only for now. Look at the winnt version
+for windows/multi thread */
+
+/* We need multiple -lc -lcpsx because they mutually refer;
+ that should go away someday */
+
+#undef LIB_SPEC
+#define LIB_SPEC "\
+ %{!shared:%{!dynamic:-lc -lcpsx -lc -lcpsx %$INTERIX_ROOT/usr/lib/psxdll.a \
+ %$INTERIX_ROOT/usr/lib/psxdll2.a \
+ }} \
+ %{!G:%{!dynamic:-lc -lcpsx -lc -lcpsx %$INTERIX_ROOT/usr/lib/psxdll.a \
+ %$INTERIX_ROOT/usr/lib/psxdll2.a \
+ }} \
+ %{dynamic:-lc %$INTERIX_ROOT/usr/lib/psxdll.a \
+ %$INTERIX_ROOT/usr/lib/psxdll2.a \
+ } \
+ %{v}"
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{!shared:-stack 0x400000,0x10000} \
+ -subsystem posix \
+ %{g} \
+ %{dynamic:-Bdynamic} \
+ %{static:-Bstatic} \
+ %{shared:--shared -Bdynamic} \
+ %{G:--shared -Bdynamic} \
+ %{symbolic:--shared -Bsymbolic -Bdynamic} \
+ %{soname*:--soname %*} \
+ %{rpath*:--rpath %*} \
+ "
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}} %{shared:crti%O%s}"
+
+#undef WORD_SWITCH_TAKES_ARG
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ ((DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
+ || !strcmp(STR, "rpath")) \
+ && strcmp (STR, "Tdata") && strcmp (STR, "Ttext") \
+ && strcmp (STR, "Tbss"))
+
+
+#if 0
+/* don't do this until we can sort out the default path issues. MK */
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX ""
+
+#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX ""
+
+#undef TOOLDIR_BASE_PREFIX
+#define TOOLDIR_BASE_PREFIX ""
+
+#endif /* 0 */
+
+#undef STDC_VALUE
+#define STDC_VALUE 0
+
+#define HANDLE_SYSV_PRAGMA
+#undef HANDLE_PRAGMA_WEAK /* until the link format can handle it */
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define DBX_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+
+/* TARGET_DEFAULT from configure */
+
+#undef WCHAR_TYPE
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_UNSIGNED 1
+#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE_SIZE 16
+
+/* For the sake of libgcc2.c, indicate target supports atexit. */
+#define HAVE_ATEXIT
diff --git a/contrib/gcc/config/nextstep.c b/contrib/gcc/config/nextstep.c
index e909a94..1c658fb 100644
--- a/contrib/gcc/config/nextstep.c
+++ b/contrib/gcc/config/nextstep.c
@@ -45,12 +45,12 @@ extern char *get_directive_line ();
The result is 1 if the pragma was handled. */
int
-handle_pragma (finput, node)
- FILE *finput;
- tree node;
+handle_pragma (p_getc, p_ungetc, pname)
+ int (* p_getc) PROTO ((void));
+ void (* p_ungetc) PROTO ((int));
+ char * pname;
{
int retval = 0;
- register char *pname;
/* Record initial setting of optimize flag, so we can restore it. */
if (!pragma_initialized)
@@ -59,11 +59,6 @@ handle_pragma (finput, node)
initial_optimize_flag = optimize;
}
- if (TREE_CODE (node) != IDENTIFIER_NODE)
- return 0;
-
- pname = IDENTIFIER_POINTER (node);
-
if (strcmp (pname, "CC_OPT_ON") == 0)
{
optimize = 1, obey_regdecls = 0;
diff --git a/contrib/gcc/config/nextstep.h b/contrib/gcc/config/nextstep.h
index 96435fc..59050a1 100644
--- a/contrib/gcc/config/nextstep.h
+++ b/contrib/gcc/config/nextstep.h
@@ -167,7 +167,12 @@ Boston, MA 02111-1307, USA. */
%{!p:-lcrt0.o}}}\
%{posix*:%{pg:-lgposixcrt0.o}%{!pg: \
%{p:%e-p profiling is no longer supported. Use -pg instead.} \
- %{!p:-lposixcrt0.o}}}"
+ %{!p:-lposixcrt0.o}}} \
+ -lcrtbegin.o"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "-lcrtend.o"
/* Allow #sscs (but don't do anything). */
@@ -203,6 +208,9 @@ Boston, MA 02111-1307, USA. */
"\t.text\n\t.stabs \"%s\",%d,0,0,Letext\nLetext:\n", \
"" , N_SO)
+/* Define our object format type for crtstuff.c */
+#define OBJECT_FORMAT_MACHO
+
/* Don't use .gcc_compiled symbols to communicate with GDB;
They interfere with numerically sorted symbol lists. */
@@ -232,6 +240,8 @@ Boston, MA 02111-1307, USA. */
fprintf (FILE, ".reference .destructors_used\n"); \
} while (0)
+#define EH_FRAME_SECTION_ASM_OP ".section __TEXT,__eh_frame,regular"
+
/* Don't output a .file directive. That is only used by the assembler for
error reporting. */
#undef ASM_FILE_START
@@ -252,7 +262,8 @@ Boston, MA 02111-1307, USA. */
/* How to parse #pragma's */
#undef HANDLE_PRAGMA
-#define HANDLE_PRAGMA(FINPUT, NODE) handle_pragma (FINPUT, NODE)
+#define HANDLE_PRAGMA(GETC, UNGETC, NAME) handle_pragma (GETC, UNGETC, NAME)
+extern int handle_pragma ();
/* Give methods pretty symbol names on NeXT. */
@@ -280,7 +291,7 @@ Boston, MA 02111-1307, USA. */
else if (!strncmp (NAME, "_OBJC_", 6)) fprintf (FILE, "L%s", NAME); \
else if (!strncmp (NAME, ".objc_class_name_", 17)) \
fprintf (FILE, "%s", NAME); \
- else fprintf (FILE, "%s%s", USER_LABEL_PREFIX, NAME); } while (0)
+ else asm_fprintf (FILE, "%U%s", NAME); } while (0)
#undef ALIGN_ASM_OP
#define ALIGN_ASM_OP ".align"
diff --git a/contrib/gcc/config/openbsd.h b/contrib/gcc/config/openbsd.h
index af8358e..30f2494 100644
--- a/contrib/gcc/config/openbsd.h
+++ b/contrib/gcc/config/openbsd.h
@@ -300,3 +300,9 @@ do { \
#pragma weak. */
#define GTHREAD_USE_WEAK 0
+/* bug work around: we don't want to support #pragma weak, but the current
+ code layout needs HANDLE_PRAGMA_WEAK asserted for __attribute((weak)) to
+ work. On the other hand, we don't define HANDLE_PRAGMA_WEAK directly,
+ as this depends on a few other details as well... */
+#define HANDLE_SYSV_PRAGMA
+
diff --git a/contrib/gcc/config/ptx4.h b/contrib/gcc/config/ptx4.h
index aa31924..b1eaabe 100644
--- a/contrib/gcc/config/ptx4.h
+++ b/contrib/gcc/config/ptx4.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for some
generic System V Release 4 system.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
Renamed and changed to suit Dynix/ptx v4 and later.
Modified by Tim Wright (timw@sequent.com).
@@ -183,8 +183,9 @@ Boston, MA 02111-1307, USA.
#define ASM_FILE_END(FILE) \
do { \
- fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
+ if (!flag_no_ident) \
+ fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
+ IDENT_ASM_OP, version_string); \
} while (0)
/* Allow #sccs in preprocessor. */
diff --git a/contrib/gcc/config/sparc/elf.h b/contrib/gcc/config/sparc/elf.h
index 70cb26a..635238f 100644
--- a/contrib/gcc/config/sparc/elf.h
+++ b/contrib/gcc/config/sparc/elf.h
@@ -40,3 +40,19 @@ Boston, MA 02111-1307, USA. */
/* FIXME: until fixed */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* This solaris2 define does not apply. */
+#undef STDC_0_IN_SYSTEM_HEADERS
+
+/* We don't want to use the Solaris2 specific long long int conversion
+ routines. */
+#undef INIT_SUBTARGET_OPTABS
+#define INIT_SUBTARGET_OPTABS
+
+/* ??? We haven't added Solaris2 equivalent 64 bit library routines to
+ lb1sp*.asm, so we need to avoid using them. */
+#undef MULDI3_LIBCALL
+#undef DIVDI3_LIBCALL
+#undef UDIVDI3_LIBCALL
+#undef MODDI3_LIBCALL
+#undef UMODDI3_LIBCALL
diff --git a/contrib/gcc/config/sparc/gmon-sol2.c b/contrib/gcc/config/sparc/gmon-sol2.c
index 2a5b898..a6abcab 100644
--- a/contrib/gcc/config/sparc/gmon-sol2.c
+++ b/contrib/gcc/config/sparc/gmon-sol2.c
@@ -35,16 +35,8 @@
* for Cygnus Support, July 1992.
*/
-#ifndef lint
-static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
+#include "config.h"
+#include "system.h"
#if 0
#include "sparc/gmon.h"
@@ -96,7 +88,9 @@ static int s_scale;
#define MSG "No space for profiling buffer(s)\n"
-static void moncontrol();
+static void moncontrol PROTO ((int));
+extern void monstartup PROTO ((char *, char *));
+extern void _mcleanup PROTO ((void));
void monstartup(lowpc, highpc)
char *lowpc;
@@ -185,7 +179,7 @@ _mcleanup()
int toindex;
struct rawarc rawarc;
char *profdir;
- char *proffile;
+ const char *proffile;
char *progname;
char buf[PATH_MAX];
extern char **___Argv;
@@ -275,6 +269,8 @@ _mcleanup()
* -- [eichin:19920702.1107EST]
*/
+static void internal_mcount PROTO((char *, unsigned short *)) ATTRIBUTE_UNUSED;
+
/* i7 == last ret, -> frompcindex */
/* o7 == current ret, -> selfpc */
/* Solaris 2 libraries use _mcount. */
@@ -297,9 +293,9 @@ static void internal_mcount(selfpc, frompcindex)
*/
if(!already_setup) {
- extern etext();
+ extern char etext[];
already_setup = 1;
- monstartup(0, etext);
+ monstartup(0, (char *)etext);
#ifdef USE_ONEXIT
on_exit(_mcleanup, 0);
#else
diff --git a/contrib/gcc/config/sparc/hal.h b/contrib/gcc/config/sparc/hal.h
new file mode 100644
index 0000000..0222b81
--- /dev/null
+++ b/contrib/gcc/config/sparc/hal.h
@@ -0,0 +1,33 @@
+/* Definitions of target machine for GNU compiler, for HAL
+ SPARC running Solaris 2 HALOS
+ Copyright 1998 Free Software Foundation, Inc.
+ Contributed by Carol LePage (carolo@hal.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Need different command line for assembler */
+
+#undef ASM_SPEC
+#define ASM_SPEC \
+ "%{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -e1 \
+ %{fpic:-K PIC} %{fPIC:-K PIC}"
+
+/* Need DWARF for debuggers. */
+
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG
diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h
index 7bbbfa4..d967b01 100644
--- a/contrib/gcc/config/sparc/linux.h
+++ b/contrib/gcc/config/sparc/linux.h
@@ -103,7 +103,7 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE_SIZE BITS_PER_WORD
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -Dsparc -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)"
+#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)"
#undef CPP_SUBTARGET_SPEC
#ifdef USE_GNULIBC_1
diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h
index 77bc668..705b5ca 100644
--- a/contrib/gcc/config/sparc/linux64.h
+++ b/contrib/gcc/config/sparc/linux64.h
@@ -19,9 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* ??? bi-architecture support will require changes to the linker
- related specs, among perhaps other things (multilibs). */
-/* #define SPARC_BI_ARCH */
+#define SPARC_BI_ARCH
#define LINUX_DEFAULT_ELF
@@ -36,6 +34,16 @@ Boston, MA 02111-1307, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+/* A 64 bit v9 compiler with stack-bias,
+ in a Medium/Low code model environment. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ \
+ + MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
+#endif
+
/* Output at beginning of assembler file. */
/* The .file command should always begin the output. */
#undef ASM_FILE_START
@@ -54,11 +62,37 @@ Boston, MA 02111-1307, USA. */
object constructed before entering `main'. */
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
+
+#define STARTFILE_SPEC32 \
"%{!shared: \
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+#define STARTFILE_SPEC64 \
+ "%{!shared: \
+ %{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} %{!p:/usr/lib64/crt1.o%s}}}\
+ /usr/lib64/crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+
+#ifdef SPARC_BI_ARCH
+
+#if DEFAULT_ARCH32_P
+#define STARTFILE_SPEC "\
+%{m32:" STARTFILE_SPEC32 "} \
+%{m64:" STARTFILE_SPEC64 "} \
+%{!m32:%{!m64:" STARTFILE_SPEC32 "}}"
+#else
+#define STARTFILE_SPEC "\
+%{m32:" STARTFILE_SPEC32 "} \
+%{m64:" STARTFILE_SPEC64 "} \
+%{!m32:%{!m64:" STARTFILE_SPEC64 "}}"
+#endif
+
+#else
+
+#define STARTFILE_SPEC STARTFILE_SPEC64
+
+#endif
+
/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
the GNU/Linux magical crtend.o file (see crtstuff.c) which
provides part of the support for getting C++ file-scope static
@@ -66,23 +100,39 @@ Boston, MA 02111-1307, USA. */
GNU/Linux "finalizer" file, `crtn.o'. */
#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
+
+#define ENDFILE_SPEC32 \
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (sparc64 GNU/Linux with ELF)");
+#define ENDFILE_SPEC64 \
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib64/crtn.o%s"
+
+#ifdef SPARC_BI_ARCH
-/* A 64 bit v9 compiler with stack-bias,
- in a Medium/Anywhere code model environment. */
+#if DEFAULT_ARCH32_P
+#define ENDFILE_SPEC "\
+%{m32:" ENDFILE_SPEC32 "} \
+%{m64:" ENDFILE_SPEC64 "} \
+%{!m32:%{!m64:" ENDFILE_SPEC32 "}}"
+#else
+#define ENDFILE_SPEC "\
+%{m32:" ENDFILE_SPEC32 "} \
+%{m64:" ENDFILE_SPEC64 "} \
+%{!m32:%{!m64:" ENDFILE_SPEC64 "}}"
+#endif
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT \
- (MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ \
- + MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
+#else
+
+#define ENDFILE_SPEC ENDFILE_SPEC64
+
+#endif
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparc64 GNU/Linux with ELF)");
/* The default code model. */
#undef SPARC_DEFAULT_CMODEL
-#define SPARC_DEFAULT_CMODEL CM_MEDANY
+#define SPARC_DEFAULT_CMODEL CM_MEDLOW
#undef WCHAR_TYPE
#define WCHAR_TYPE "long int"
@@ -92,9 +142,9 @@ Boston, MA 02111-1307, USA. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 128
-
+
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D_LONGLONG -Dsparc -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)"
+#define CPP_PREDEFINES "-D__ELF__ -Dunix -D_LONGLONG -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)"
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
@@ -126,17 +176,88 @@ Boston, MA 02111-1307, USA. */
/* If ELF is the default format, we should not use /lib/elf. */
+#ifdef SPARC_BI_ARCH
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "link_arch32", LINK_ARCH32_SPEC }, \
+ { "link_arch64", LINK_ARCH64_SPEC }, \
+ { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC },
+
+#define LINK_ARCH32_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}}} \
+"
+
+#define LINK_ARCH64_SPEC "-m elf64_sparc -Y P,/usr/lib64 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib64/ld-linux.so.2}} \
+ %{static:-static}}} \
+"
+
+#define LINK_ARCH_SPEC "\
+%{m32:%(link_arch32)} \
+%{m64:%(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+
+#define LINK_ARCH_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? LINK_ARCH32_SPEC : LINK_ARCH64_SPEC)
+
#undef LINK_SPEC
-#define LINK_SPEC "-m elf64_sparc -Y P,/usr/lib %{shared:-shared} \
+#define LINK_SPEC "\
+%(link_arch) \
+%{mlittle-endian:-EL} \
+"
+
+#undef CC1_SPEC
+#if DEFAULT_ARCH32_P
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m64:-mptr64 -mcpu=ultrasparc -mstack-bias} \
+"
+#else
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m32:-mptr32 -mcpu=cypress -mno-stack-bias} \
+"
+#endif
+
+#if DEFAULT_ARCH32_P
+#define MULTILIB_DEFAULTS { "m32" }
+#else
+#define MULTILIB_DEFAULTS { "m64" }
+#endif
+
+#else /* !SPARC_BI_ARCH */
+
+#undef LINK_SPEC
+#define LINK_ARCH_SPEC "-m elf64_sparc -Y P,/usr/lib64 %{shared:-shared} \
%{!shared: \
%{!ibcs: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux64.so.2}} \
+ %{!dynamic-linker:-dynamic-linker /lib64/ld-linux.so.2}} \
%{static:-static}}} \
%{mlittle-endian:-EL} \
"
+#endif /* !SPARC_BI_ARCH */
+
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
diff --git a/contrib/gcc/config/sparc/pbd.h b/contrib/gcc/config/sparc/pbd.h
index 459bffd..b70fdcb 100644
--- a/contrib/gcc/config/sparc/pbd.h
+++ b/contrib/gcc/config/sparc/pbd.h
@@ -144,35 +144,7 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
fprintf (FILE, "\t.word .L%d\n", VALUE)
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- fprintf (FILE, "\tsethi %%hi(.LP%d),%%o0\n\tcall mcount\n\tor %%lo(.LP%d),%%o0,%%o0\n", \
- (LABELNO), (LABELNO))
-
-/* Output assembler code to FILE to initialize this source file's
- basic block profiling info, if that has not already been done. */
-
-#undef FUNCTION_BLOCK_PROFILER
-#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
- fprintf (FILE, "\tsethi %%hi(.LPBX0),%%o0\n\tld [%%lo(.LPBX0)+%%o0],%%o1\n\ttst %%o1\n\tbne .LPY%d\n\tnop\n\tcall ___bb_init_func\n\tnop\n.LPY%d:\n", \
- (LABELNO), (LABELNO))
-
-/* Output assembler code to FILE to increment the entry-count for
- the BLOCKNO'th basic block in this source file. */
-
-#undef BLOCK_PROFILER
-#define BLOCK_PROFILER(FILE, BLOCKNO) \
-{ \
- int blockn = (BLOCKNO); \
- fprintf (FILE, "\tsethi %%hi(.LPBX2+%d),%%g1\n\tld [%%lo(.LPBX2+%d)+%%g1],%%g2\n\
-\tadd %%g2,1,%%g2\n\tst %%g2,[%%lo(.LPBX2+%d)+%%g1]\n", \
- 4 * blockn, 4 * blockn, 4 * blockn); \
- CC_STATUS_INIT; /* We have clobbered %g1. Also %g2. */ \
-}
-/* This is needed for SunOS 4.0, and should not hurt for 3.2
+/* This is needed for SunOS 4.0, and should not hurt for 3.2
versions either. */
#undef ASM_OUTPUT_SOURCE_LINE(file, line)
#define ASM_OUTPUT_SOURCE_LINE(file, line) \
diff --git a/contrib/gcc/config/sparc/sol2-c1.asm b/contrib/gcc/config/sparc/sol2-c1.asm
index 618d698..894a8c3 100644
--- a/contrib/gcc/config/sparc/sol2-c1.asm
+++ b/contrib/gcc/config/sparc/sol2-c1.asm
@@ -1,4 +1,4 @@
-! crt1.s for solaris 2.0.
+! crt1.s for sparc & sparcv9 (SunOS 5)
! Copyright (C) 1992 Free Software Foundation, Inc.
! Written By David Vinayak Henkel-Wallace, June 1992
@@ -37,43 +37,67 @@
! in section 3 of the SVr4 ABI.
! This file is the first thing linked into any executable.
+#ifdef __sparcv9
+#define CPTRSIZE 8
+#define CPTRSHIFT 3
+#define STACK_BIAS 2047
+#define ldn ldx
+#define stn stx
+#define setn(s, scratch, dst) setx s, scratch, dst
+#else
+#define CPTRSIZE 4
+#define CPTRSHIFT 2
+#define STACK_BIAS 0
+#define ldn ld
+#define stn st
+#define setn(s, scratch, dst) set s, dst
+#endif
+
.section ".text"
.proc 022
.global _start
_start:
mov 0, %fp ! Mark bottom frame pointer
- ld [%sp + 64], %l0 ! argc
- add %sp, 68, %l1 ! argv
+ ldn [%sp + (16 * CPTRSIZE) + STACK_BIAS], %l0 ! argc
+ add %sp, (17 * CPTRSIZE) + STACK_BIAS, %l1 ! argv
! Leave some room for a call. Sun leaves 32 octets (to sit on
! a cache line?) so we do too.
+#ifdef __sparcv9
+ sub %sp, 48, %sp
+#else
sub %sp, 32, %sp
+#endif
! %g1 may contain a function to be registered w/atexit
orcc %g0, %g1, %g0
+#ifdef __sparcv9
+ be %xcc, .nope
+#else
be .nope
+#endif
mov %g1, %o0
call atexit
nop
.nope:
! Now make sure constructors and destructors are handled.
- set _fini, %o0
+ setn(_fini, %o1, %o0)
call atexit, 1
nop
call _init, 0
nop
- ! We ignore the auxiliary vector; there's no defined way to
+ ! We ignore the auxiliary vector; there is no defined way to
! access those data anyway. Instead, go straight to main:
mov %l0, %o0 ! argc
mov %l1, %o1 ! argv
! Skip argc words past argv, to env:
- sll %l0, 2, %o2
- add %o2, 4, %o2
+ sll %l0, CPTRSHIFT, %o2
+ add %o2, CPTRSIZE, %o2
add %l1, %o2, %o2 ! env
- set _environ, %o3
- st %o2, [%o3] ! *_environ
+ setn(_environ, %o4, %o3)
+ stn %o2, [%o3] ! *_environ
call main, 4
nop
call exit, 0
diff --git a/contrib/gcc/config/sparc/sol2-ci.asm b/contrib/gcc/config/sparc/sol2-ci.asm
index dd09a34..3dc793c 100644
--- a/contrib/gcc/config/sparc/sol2-ci.asm
+++ b/contrib/gcc/config/sparc/sol2-ci.asm
@@ -48,7 +48,11 @@
.type _init,#function
.align 4
_init:
+#ifdef __sparcv9
+ save %sp, -176, %sp
+#else
save %sp, -96, %sp
+#endif
.section ".fini"
@@ -57,4 +61,8 @@ _init:
.type _fini,#function
.align 4
_fini:
+#ifdef __sparcv9
+ save %sp, -176, %sp
+#else
save %sp, -96, %sp
+#endif
diff --git a/contrib/gcc/config/sparc/sol2-cn.asm b/contrib/gcc/config/sparc/sol2-cn.asm
index 3c5d508..49e070f 100644
--- a/contrib/gcc/config/sparc/sol2-cn.asm
+++ b/contrib/gcc/config/sparc/sol2-cn.asm
@@ -51,4 +51,4 @@
ret
restore
-! Th-th-th-that's all folks!
+! Th-th-th-that is all folks!
diff --git a/contrib/gcc/config/sparc/sol2-sld-64.h b/contrib/gcc/config/sparc/sol2-sld-64.h
new file mode 100644
index 0000000..c2518d8
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol2-sld-64.h
@@ -0,0 +1,363 @@
+/* Definitions of target machine for GNU compiler, for 64-bit SPARC
+ running Solaris 2 using the system linker. */
+
+#define SPARC_BI_ARCH
+
+#include "sparc/sol2.h"
+
+/* At least up through Solaris 2.6,
+ the system linker does not work with DWARF or DWARF2,
+ since it does not have working support for relocations
+ to unaligned data. */
+
+#define LINKER_DOES_NOT_WORK_WITH_DWARF2
+
+/* A 64 bit v9 compiler with stack-bias */
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ + \
+ MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
+#endif
+
+/* The default code model. */
+#undef SPARC_DEFAULT_CMODEL
+#define SPARC_DEFAULT_CMODEL CM_MEDANY
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 128
+
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC ""
+#undef ASM_CPU64_DEFAULT_SPEC
+#define ASM_CPU64_DEFAULT_SPEC "-xarch=v9"
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC ""
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plus"
+#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC ""
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plusa"
+#undef ASM_CPU64_DEFAULT_SPEC
+#define ASM_CPU64_DEFAULT_SPEC "-xarch=v9a"
+#endif
+
+/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
+ It's safe to pass -s always, even if -g is not used. */
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
+%{fpic:-K PIC} %{fPIC:-K PIC} \
+%(asm_cpu)\
+"
+
+#if DEFAULT_ARCH32_P
+#define DEF_ARCH32_SPEC(__str) "%{!m64:" __str "}"
+#define DEF_ARCH64_SPEC(__str) "%{m64:" __str "}"
+#else
+#define DEF_ARCH32_SPEC(__str) "%{m32:" __str "}"
+#define DEF_ARCH64_SPEC(__str) "%{!m32:" __str "}"
+#endif
+
+#undef CPP_CPU_SPEC
+#define CPP_CPU_SPEC "\
+%{mcypress:} \
+%{msparclite:-D__sparclite__} \
+%{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \
+%{mv8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{msupersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=sparclet:-D__sparclet__} %{mcpu=tsc701:-D__sparclet__} \
+%{mcpu=sparclite:-D__sparclite__} \
+%{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \
+%{mcpu=v8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=supersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=v9:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
+"
+
+#undef ASM_CPU_SPEC
+#define ASM_CPU_SPEC "\
+%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-xarch=v8plusa") DEF_ARCH64_SPEC("-xarch=v9a") "} \
+%{mcpu=v9:" DEF_ARCH32_SPEC("-xarch=v8plus") DEF_ARCH64_SPEC("-xarch=v9") "} \
+%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC("-xarch=v9") "}}} \
+%{!mcpu*:%(asm_cpu_default)} \
+"
+
+#define STARTFILE_SPEC32 "\
+%{ansi:values-Xc.o%s} \
+%{!ansi: \
+ %{traditional:values-Xt.o%s} \
+ %{!traditional:values-Xa.o%s}}"
+
+#define STARTFILE_SPEC64 "\
+%{ansi:/usr/lib/sparcv9/values-Xc.o%s} \
+%{!ansi: \
+ %{traditional:/usr/lib/sparcv9/values-Xt.o%s} \
+ %{!traditional:/usr/lib/sparcv9/values-Xa.o%s}}"
+
+#ifdef SPARC_BI_ARCH
+
+#if DEFAULT_ARCH32_P
+#define STARTFILE_ARCH_SPEC "\
+%{m32:" STARTFILE_SPEC32 "} \
+%{m64:" STARTFILE_SPEC64 "} \
+%{!m32:%{!m64:" STARTFILE_SPEC32 "}}"
+#else
+#define STARTFILE_ARCH_SPEC "\
+%{m32:" STARTFILE_SPEC32 "} \
+%{m64:" STARTFILE_SPEC64 "} \
+%{!m32:%{!m64:" STARTFILE_SPEC64 "}}"
+#endif
+
+#else /* !SPARC_BI_ARCH */
+
+/* In this case we define MD_STARTFILE_PREFIX to /usr/lib/sparcv9/ */
+#define STARTFILE_ARCH_SPEC STARTFILE_SPEC32
+
+#endif /* !SPARC_BI_ARCH */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared: \
+ %{!symbolic: \
+ %{p:mcrt1.o%s} \
+ %{!p: \
+ %{pg:gcrt1.o%s gmon.o%s} \
+ %{!pg:crt1.o%s}}}} \
+ crti.o%s" STARTFILE_ARCH_SPEC " \
+ crtbegin.o%s"
+
+#ifdef SPARC_BI_ARCH
+
+#undef CPP_CPU_DEFAULT_SPEC
+#define CPP_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" CPP_CPU64_DEFAULT_SPEC "} \
+%{!m64:" CPP_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" CPP_CPU32_DEFAULT_SPEC "} \
+%{!m32:" CPP_CPU64_DEFAULT_SPEC "} \
+")
+
+#undef ASM_CPU_DEFAULT_SPEC
+#define ASM_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" ASM_CPU64_DEFAULT_SPEC "} \
+%{!m64:" ASM_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" ASM_CPU32_DEFAULT_SPEC "} \
+%{!m32:" ASM_CPU64_DEFAULT_SPEC "} \
+")
+
+#undef CPP_ARCH32_SPEC
+#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)"
+#undef CPP_ARCH64_SPEC
+#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
+-D__arch64__ -Acpu(sparc64) -Amachine(sparcv9) -D__sparcv9"
+
+#undef CPP_ARCH_SPEC
+#define CPP_ARCH_SPEC "\
+%{m32:%(cpp_arch32)} \
+%{m64:%(cpp_arch64)} \
+%{!m32:%{!m64:%(cpp_arch_default)}} \
+"
+
+#undef ASM_ARCH_SPEC
+#define ASM_ARCH_SPEC ""
+
+#undef ASM_ARCH32_SPEC
+#define ASM_ARCH32_SPEC ""
+
+#undef ASM_ARCH64_SPEC
+#define ASM_ARCH64_SPEC ""
+
+#undef ASM_ARCH_DEFAULT_SPEC
+#define ASM_ARCH_DEFAULT_SPEC ""
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "link_arch32", LINK_ARCH32_SPEC }, \
+ { "link_arch64", LINK_ARCH64_SPEC }, \
+ { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC },
+
+/* This should be the same as in svr4.h, except with -R added. */
+#define LINK_ARCH32_SPEC \
+ "%{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:%{!pg:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
+ -R /usr/ucblib} \
+ %{!compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:%{!pg:-Y P,/usr/ccs/lib:/usr/lib}}}}"
+
+#define LINK_ARCH64_SPEC \
+ "%{mcmodel=medlow:-M /usr/lib/ld/sparcv9/map.below4G} \
+ %{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!p:%{!pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/sparcv9}}} \
+ -R /usr/ucblib} \
+ %{!compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{pg:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!p:%{!pg:-Y P,/usr/lib/sparcv9}}}}"
+
+#define LINK_ARCH_SPEC "\
+%{m32:%(link_arch32)} \
+%{m64:%(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+
+#define LINK_ARCH_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? LINK_ARCH32_SPEC : LINK_ARCH64_SPEC)
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{h*} %{v:-V} \
+ %{b} %{Wl,*:%*} \
+ %{static:-dn -Bstatic} \
+ %{shared:-G -dy %{!mimpure-text:-z text}} \
+ %{symbolic:-Bsymbolic -G -dy -z text} \
+ %(link_arch) \
+ %{Qy:} %{!Qn:-Qy}"
+
+#undef CC1_SPEC
+#if DEFAULT_ARCH32_P
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m64:-mptr64 -mcpu=v9 -mstack-bias -mno-v8plus} \
+"
+#else
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m32:-mptr32 -mcpu=cypress -mno-stack-bias} \
+%{mv8plus:-m32 -mptr32 -mcpu=cypress -mno-stack-bias} \
+"
+#endif
+
+#if DEFAULT_ARCH32_P
+#define MULTILIB_DEFAULTS { "m32" }
+#else
+#define MULTILIB_DEFAULTS { "m64" }
+#endif
+
+#else /* !SPARC_BI_ARCH */
+
+/*
+ * This should be the same as in sol2-sld.h, except with "/sparcv9"
+ * appended to the paths and /usr/ccs/lib is no longer necessary
+ */
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{h*} %{v:-V} \
+ %{b} %{Wl,*:%*} \
+ %{static:-dn -Bstatic} \
+ %{shared:-G -dy %{!mimpure-text:-z text}} \
+ %{symbolic:-Bsymbolic -G -dy -z text} \
+ %{mcmodel=medlow:-M /usr/lib/ld/sparcv9/map.below4G} \
+ %{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!p:%{!pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/sparcv9}}} \
+ -R /usr/ucblib} \
+ %{!compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{pg:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!p:%{!pg:-Y P,/usr/lib/sparcv9}}}} \
+ %{Qy:} %{!Qn:-Qy}"
+
+#undef MD_STARTFILE_PREFIX
+#define MD_STARTFILE_PREFIX "/usr/lib/sparcv9/"
+
+#endif /* ! SPARC_BI_ARCH */
+
+/*
+ * Attempt to turn on access permissions for the stack.
+ *
+ * This code must be defined when compiling gcc but not when compiling
+ * libgcc2.a, unless we're generating code for 64 bits SPARC
+ *
+ * _SC_STACK_PROT is only defined for post 2.6, but we want this code
+ * to run always. 2.6 can change the stack protection but has no way to
+ * query it.
+ *
+ */
+
+#define TRANSFER_FROM_TRAMPOLINE \
+static int need_enable_exec_stack; \
+ \
+static void check_enabling(void) __attribute__ ((constructor)); \
+static void check_enabling(void) \
+{ \
+ extern long sysconf(int); \
+ \
+ int prot = (int) sysconf(515 /*_SC_STACK_PROT */); \
+ if (prot != 7) \
+ need_enable_exec_stack = 1; \
+} \
+ \
+void \
+__enable_execute_stack (addr) \
+ void *addr; \
+{ \
+ if (!need_enable_exec_stack) \
+ return; \
+ else { \
+ long size = getpagesize (); \
+ long mask = ~(size-1); \
+ char *page = (char *) (((long) addr) & mask); \
+ char *end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
+ \
+ /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */ \
+ if (mprotect (page, end - page, 7) < 0) \
+ perror ("mprotect of trampoline code"); \
+ } \
+}
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global constructors. */
+#undef ASM_OUTPUT_CONSTRUCTOR
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", TARGET_ARCH64 ? ASM_LONGLONG : INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global destructors. */
+#undef ASM_OUTPUT_DESTRUCTOR
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", TARGET_ARCH64 ? ASM_LONGLONG : INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
diff --git a/contrib/gcc/config/sparc/sol2.h b/contrib/gcc/config/sparc/sol2.h
index a0fa4a8..9274f9d 100644
--- a/contrib/gcc/config/sparc/sol2.h
+++ b/contrib/gcc/config/sparc/sol2.h
@@ -195,10 +195,14 @@ Boston, MA 02111-1307, USA. */
#undef INIT_SUBTARGET_OPTABS
#define INIT_SUBTARGET_OPTABS \
- fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ftoll"); \
- fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__ftoull"); \
- fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__dtoll"); \
- fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__dtoull")
+ fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
+ TARGET_ARCH64 ? "__ftol" : "__ftoll"); \
+ fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
+ TARGET_ARCH64 ? "__ftoul" : "__ftoull"); \
+ fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
+ TARGET_ARCH64 ? "__dtol" : "__dtoll"); \
+ fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
+ TARGET_ARCH64 ? "__dtoul" : "__dtoull")
/* No weird SPARC variants on Solaris */
#undef TARGET_LIVE_G0
diff --git a/contrib/gcc/config/sparc/sp64-elf.h b/contrib/gcc/config/sparc/sp64-elf.h
index 2482866..4fd81c5 100644
--- a/contrib/gcc/config/sparc/sp64-elf.h
+++ b/contrib/gcc/config/sparc/sp64-elf.h
@@ -80,8 +80,8 @@ crtbegin.o%s \
/* V9 chips can handle either endianness. */
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
-{"big-endian", -MASK_LITTLE_ENDIAN}, \
-{"little-endian", MASK_LITTLE_ENDIAN},
+{"big-endian", -MASK_LITTLE_ENDIAN, "Generate code for big endian" }, \
+{"little-endian", MASK_LITTLE_ENDIAN, "Generate code for little endian" },
#undef BYTES_BIG_ENDIAN
#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
@@ -102,9 +102,10 @@ crtbegin.o%s \
/* The medium/anywhere code model practically requires us to put jump tables
in the text section as gcc is unable to distinguish LABEL_REF's of jump
tables from other label refs (when we need to). */
-/* ??? Revisit this. */
+/* But we now defer the tables to the end of the function, so we make
+ this 0 to not confuse the branch shortening code. */
#undef JUMP_TABLES_IN_TEXT_SECTION
-#define JUMP_TABLES_IN_TEXT_SECTION 1
+#define JUMP_TABLES_IN_TEXT_SECTION 0
/* System V Release 4 uses DWARF debugging info.
GDB doesn't support 64 bit stabs yet and the desired debug format is DWARF
diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c
index e350729..ad12ec3 100644
--- a/contrib/gcc/config/sparc/sparc.c
+++ b/contrib/gcc/config/sparc/sparc.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Sun SPARC.
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
@@ -98,20 +98,28 @@ char leaf_reg_remap[] =
this is "%sp+something". We record "something" separately as it may be
too big for reg+constant addressing. */
-static char *frame_base_name;
+static const char *frame_base_name;
static int frame_base_offset;
static rtx pic_setup_code PROTO((void));
-static rtx find_addr_reg PROTO((rtx));
static void sparc_init_modes PROTO((void));
-static int save_regs PROTO((FILE *, int, int, char *,
+static int save_regs PROTO((FILE *, int, int, const char *,
int, int, int));
-static int restore_regs PROTO((FILE *, int, int, char *, int, int));
-static void build_big_number PROTO((FILE *, int, char *));
+static int restore_regs PROTO((FILE *, int, int, const char *, int, int));
+static void build_big_number PROTO((FILE *, int, const char *));
static int function_arg_slotno PROTO((const CUMULATIVE_ARGS *,
enum machine_mode, tree, int, int,
int *, int *));
+static int supersparc_adjust_cost PROTO((rtx, rtx, rtx, int));
+static int hypersparc_adjust_cost PROTO((rtx, rtx, rtx, int));
+static int ultrasparc_adjust_cost PROTO((rtx, rtx, rtx, int));
+
+static void sparc_output_addr_vec PROTO((rtx));
+static void sparc_output_addr_diff_vec PROTO((rtx));
+static void sparc_output_deferred_case_vectors PROTO((void));
+
+
#ifdef DWARF2_DEBUGGING_INFO
extern char *dwarf2out_cfi_label ();
#endif
@@ -119,14 +127,14 @@ extern char *dwarf2out_cfi_label ();
/* Option handling. */
/* Code model option as passed by user. */
-char *sparc_cmodel_string;
+const char *sparc_cmodel_string;
/* Parsed value. */
enum cmodel sparc_cmodel;
/* Record alignment options as passed by user. */
-char *sparc_align_loops_string;
-char *sparc_align_jumps_string;
-char *sparc_align_funcs_string;
+const char *sparc_align_loops_string;
+const char *sparc_align_jumps_string;
+const char *sparc_align_funcs_string;
/* Parsed values, as a power of two. */
int sparc_align_loops;
@@ -152,7 +160,7 @@ void
sparc_override_options ()
{
static struct code_model {
- char *name;
+ const char *name;
int value;
} cmodels[] = {
{ "32", CM_32 },
@@ -166,13 +174,15 @@ sparc_override_options ()
/* Map TARGET_CPU_DEFAULT to value for -m{arch,tune}=. */
static struct cpu_default {
int cpu;
- char *name;
+ const char *name;
} cpu_default[] = {
/* There must be one entry here for each TARGET_CPU value. */
{ TARGET_CPU_sparc, "cypress" },
{ TARGET_CPU_sparclet, "tsc701" },
{ TARGET_CPU_sparclite, "f930" },
{ TARGET_CPU_v8, "v8" },
+ { TARGET_CPU_hypersparc, "hypersparc" },
+ { TARGET_CPU_sparclite86x, "sparclite86x" },
{ TARGET_CPU_supersparc, "supersparc" },
{ TARGET_CPU_v9, "v9" },
{ TARGET_CPU_ultrasparc, "ultrasparc" },
@@ -181,7 +191,7 @@ sparc_override_options ()
struct cpu_default *def;
/* Table of values for -m{cpu,tune}=. */
static struct cpu_table {
- char *name;
+ const char *name;
enum processor_type processor;
int disable;
int enable;
@@ -196,6 +206,8 @@ sparc_override_options ()
The Fujitsu MB86934 is the recent sparclite chip, with an fpu. */
{ "f930", PROCESSOR_F930, MASK_ISA|MASK_FPU, MASK_SPARCLITE },
{ "f934", PROCESSOR_F934, MASK_ISA, MASK_SPARCLITE|MASK_FPU },
+ { "hypersparc", PROCESSOR_HYPERSPARC, MASK_ISA, MASK_V8|MASK_FPU },
+ { "sparclite86x", PROCESSOR_SPARCLITE86X, MASK_ISA|MASK_FPU, MASK_V8 },
{ "sparclet", PROCESSOR_SPARCLET, MASK_ISA, MASK_SPARCLET },
/* TEMIC sparclet */
{ "tsc701", PROCESSOR_TSC701, MASK_ISA, MASK_SPARCLET },
@@ -207,7 +219,7 @@ sparc_override_options ()
struct cpu_table *cpu;
struct sparc_cpu_select *sel;
int fpu;
-
+
#ifndef SPARC_BI_ARCH
/* Check for unsupported architecture size. */
if (! TARGET_64BIT != DEFAULT_ARCH32_P)
@@ -217,8 +229,25 @@ sparc_override_options ()
}
#endif
+ /* At the moment we don't allow different pointer size and architecture */
+ if (! TARGET_64BIT != ! TARGET_PTR64)
+ {
+ error ("-mptr%d not allowed on -m%d",
+ TARGET_PTR64 ? 64 : 32, TARGET_64BIT ? 64 : 32);
+ if (TARGET_64BIT)
+ target_flags |= MASK_PTR64;
+ else
+ target_flags &= ~MASK_PTR64;
+ }
+
/* Code model selection. */
sparc_cmodel = SPARC_DEFAULT_CMODEL;
+
+#ifdef SPARC_BI_ARCH
+ if (TARGET_ARCH32)
+ sparc_cmodel = CM_32;
+#endif
+
if (sparc_cmodel_string != NULL)
{
if (TARGET_ARCH64)
@@ -277,13 +306,17 @@ sparc_override_options ()
if (TARGET_V9 && TARGET_ARCH32)
target_flags |= MASK_DEPRECATED_V8_INSNS;
- /* V8PLUS requires V9 */
- if (! TARGET_V9)
+ /* V8PLUS requires V9, makes no sense in 64 bit mode. */
+ if (! TARGET_V9 || TARGET_ARCH64)
target_flags &= ~MASK_V8PLUS;
/* Don't use stack biasing in 32 bit mode. */
if (TARGET_ARCH32)
target_flags &= ~MASK_STACK_BIAS;
+
+ /* Don't allow -mvis if FPU is disabled. */
+ if (! TARGET_FPU)
+ target_flags &= ~MASK_VIS;
/* Validate -malign-loops= value, or provide default. */
if (sparc_align_loops_string)
@@ -332,6 +365,12 @@ sparc_override_options ()
/* Do various machine dependent initializations. */
sparc_init_modes ();
+
+ if ((profile_flag || profile_block_flag)
+ && sparc_cmodel != CM_MEDLOW)
+ {
+ error ("profiling does not support code models other than medlow");
+ }
}
/* Miscellaneous utilities. */
@@ -347,14 +386,6 @@ v9_regcmp_p (code)
|| code == LE || code == GT);
}
-/* 32 bit registers are zero extended so only zero/non-zero comparisons
- work. */
-int
-v8plus_regcmp_p (code)
- enum rtx_code code;
-{
- return (code == EQ || code == NE);
-}
/* Operand constraints. */
@@ -637,56 +668,6 @@ reg_or_nonsymb_mem_operand (op, mode)
}
int
-sparc_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
- if (GET_CODE (op) == CONST_INT)
- return SMALL_INT (op);
- if (GET_MODE (op) != mode)
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) != MEM)
- return 0;
-
- op = XEXP (op, 0);
- if (GET_CODE (op) == LO_SUM)
- return (GET_CODE (XEXP (op, 0)) == REG
- && symbolic_operand (XEXP (op, 1), Pmode));
- return memory_address_p (mode, op);
-}
-
-int
-move_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (mode == DImode && arith_double_operand (op, mode))
- return 1;
- if (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
- if (GET_CODE (op) == CONST_INT)
- return SMALL_INT (op) || SPARC_SETHI_P (INTVAL (op));
-
- if (GET_MODE (op) != mode)
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- if (GET_CODE (op) == LO_SUM)
- return (register_operand (XEXP (op, 0), Pmode)
- && CONSTANT_P (XEXP (op, 1)));
- return memory_address_p (mode, op);
-}
-
-int
splittable_symbolic_memory_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
@@ -775,17 +756,6 @@ v9_regcmp_op (op, mode)
return v9_regcmp_p (code);
}
-/* ??? Same as eq_or_neq. */
-int
-v8plus_regcmp_op (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- enum rtx_code code = GET_CODE (op);
-
- return (code == EQ || code == NE);
-}
-
/* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */
int
@@ -837,8 +807,7 @@ arith_operand (op, mode)
enum machine_mode mode;
{
int val;
- if (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX)
+ if (register_operand (op, mode))
return 1;
if (GET_CODE (op) != CONST_INT)
return 0;
@@ -846,6 +815,72 @@ arith_operand (op, mode)
return SPARC_SIMM13_P (val);
}
+/* Return true if OP is a constant 4096 */
+
+int
+arith_4096_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ int val;
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ val = INTVAL (op) & 0xffffffff;
+ return val == 4096;
+}
+
+/* Return true if OP is suitable as second operand for add/sub */
+
+int
+arith_add_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return arith_operand (op, mode) || arith_4096_operand (op, mode);
+}
+
+/* Return true if OP is a CONST_INT or a CONST_DOUBLE which can fit in the
+ immediate field of OR and XOR instructions. Used for 64-bit
+ constant formation patterns. */
+int
+const64_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return ((GET_CODE (op) == CONST_INT
+ && SPARC_SIMM13_P (INTVAL (op)))
+#if HOST_BITS_PER_WIDE_INT != 64
+ || (GET_CODE (op) == CONST_DOUBLE
+ && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
+ && (CONST_DOUBLE_HIGH (op) ==
+ ((CONST_DOUBLE_LOW (op) & 0x80000000) != 0 ?
+ (HOST_WIDE_INT)0xffffffff : 0)))
+#endif
+ );
+}
+
+/* The same, but only for sethi instructions. */
+int
+const64_high_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return ((GET_CODE (op) == CONST_INT
+ && (INTVAL (op) & 0xfffffc00) != 0
+ && SPARC_SETHI_P (INTVAL (op))
+#if HOST_BITS_PER_WIDE_INT != 64
+ /* Must be positive on non-64bit host else the
+ optimizer is fooled into thinking that sethi
+ sign extends, even though it does not. */
+ && INTVAL (op) >= 0
+#endif
+ )
+ || (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (op) == 0
+ && (CONST_DOUBLE_LOW (op) & 0xfffffc00) != 0
+ && SPARC_SETHI_P (CONST_DOUBLE_LOW (op))));
+}
+
/* Return true if OP is a register, or is a CONST_INT that can fit in a
signed 11 bit immediate field. This is an acceptable SImode operand for
the movcc instructions. */
@@ -856,7 +891,6 @@ arith11_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));
}
@@ -870,7 +904,6 @@ arith10_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));
}
@@ -887,7 +920,6 @@ arith_double_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_INT && SMALL_INT (op))
|| (! TARGET_ARCH64
&& GET_CODE (op) == CONST_DOUBLE
@@ -902,6 +934,30 @@ arith_double_operand (op, mode)
&& (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
}
+/* Return true if OP is a constant 4096 for DImode on ARCH64 */
+
+int
+arith_double_4096_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return (TARGET_ARCH64 &&
+ ((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) ||
+ (GET_CODE (op) == CONST_DOUBLE &&
+ CONST_DOUBLE_LOW (op) == 4096 &&
+ CONST_DOUBLE_HIGH (op) == 0)));
+}
+
+/* Return true if OP is suitable as second operand for add/sub in DImode */
+
+int
+arith_double_add_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);
+}
+
/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
can fit in an 11 bit immediate field. This is an acceptable DImode
operand for the movcc instructions. */
@@ -913,7 +969,6 @@ arith11_double_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_DOUBLE
&& (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
&& (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800
@@ -937,7 +992,6 @@ arith10_double_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
- || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_DOUBLE
&& (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
&& (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400
@@ -959,8 +1013,18 @@ small_int (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
+ return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
+}
+
+int
+small_int_or_double (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))
- || GET_CODE (op) == CONSTANT_P_RTX);
+ || (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (op) == 0
+ && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))));
}
/* Recognize operand values for the umul instruction. That instruction sign
@@ -974,16 +1038,15 @@ uns_small_int (op, mode)
{
#if HOST_BITS_PER_WIDE_INT > 32
/* All allowed constants will fit a CONST_INT. */
- return ((GET_CODE (op) == CONST_INT
- && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
- || (INTVAL (op) >= 0xFFFFF000 && INTVAL (op) < 0x100000000L)))
- || GET_CODE (op) == CONSTANT_P_RTX);
+ return (GET_CODE (op) == CONST_INT
+ && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
+ || (INTVAL (op) >= 0xFFFFF000
+ && INTVAL (op) < 0x100000000)));
#else
- return (((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000))
- || GET_CODE (op) == CONSTANT_P_RTX);
+ return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
+ || (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (op) == 0
+ && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));
#endif
}
@@ -1003,7 +1066,947 @@ clobbered_register (op, mode)
{
return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
}
+
+/* Return 1 if OP is const0_rtx, used for TARGET_LIVE_G0 insns. */
+
+int
+zero_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return op == const0_rtx;
+}
+
+/* Return 1 if OP is a valid operand for the source of a move insn. */
+
+int
+input_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* If both modes are non-void they must be the same. */
+ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+ return 0;
+
+ /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */
+ if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == CONSTANT_P_RTX)
+ return 1;
+
+ /* Allow any one instruction integer constant, and all CONST_INT
+ variants when we are working in DImode and !arch64. */
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && ((GET_CODE (op) == CONST_INT
+ && ((SPARC_SETHI_P (INTVAL (op))
+ && (! TARGET_ARCH64
+ || (INTVAL (op) >= 0)
+ || mode == SImode))
+ || SPARC_SIMM13_P (INTVAL (op))
+ || (mode == DImode
+ && ! TARGET_ARCH64)))
+ || (TARGET_ARCH64
+ && GET_CODE (op) == CONST_DOUBLE
+ && ((CONST_DOUBLE_HIGH (op) == 0
+ && SPARC_SETHI_P (CONST_DOUBLE_LOW (op)))
+ ||
+#if HOST_BITS_PER_WIDE_INT == 64
+ (CONST_DOUBLE_HIGH (op) == 0
+ && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)))
+#else
+ (SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
+ && (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0
+ && CONST_DOUBLE_HIGH (op) == 0)
+ || (CONST_DOUBLE_HIGH (op) == -1)))
+#endif
+ ))))
+ return 1;
+
+ /* If !arch64 and this is a DImode const, allow it so that
+ the splits can be generated. */
+ if (! TARGET_ARCH64
+ && mode == DImode
+ && GET_CODE (op) == CONST_DOUBLE)
+ return 1;
+
+ if (register_operand (op, mode))
+ return 1;
+
+ /* If this is a SUBREG, look inside so that we handle
+ paradoxical ones. */
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ /* Check for valid MEM forms. */
+ if (GET_CODE (op) == MEM)
+ {
+ rtx inside = XEXP (op, 0);
+
+ if (GET_CODE (inside) == LO_SUM)
+ {
+ /* We can't allow these because all of the splits
+ (eventually as they trickle down into DFmode
+ splits) require offsettable memory references. */
+ if (! TARGET_V9
+ && GET_MODE (op) == TFmode)
+ return 0;
+
+ return (register_operand (XEXP (inside, 0), Pmode)
+ && CONSTANT_P (XEXP (inside, 1)));
+ }
+ return memory_address_p (mode, inside);
+ }
+
+ return 0;
+}
+
+/* We know it can't be done in one insn when we get here,
+ the movsi expander guarentees this. */
+void
+sparc_emit_set_const32 (op0, op1)
+ rtx op0;
+ rtx op1;
+{
+ enum machine_mode mode = GET_MODE (op0);
+ rtx temp;
+
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ HOST_WIDE_INT value = INTVAL (op1);
+
+ if (SPARC_SETHI_P (value)
+ || SPARC_SIMM13_P (value))
+ abort ();
+ }
+
+ /* Full 2-insn decomposition is needed. */
+ if (reload_in_progress || reload_completed)
+ temp = op0;
+ else
+ temp = gen_reg_rtx (mode);
+
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ /* Emit them as real moves instead of a HIGH/LO_SUM,
+ this way CSE can see everything and reuse intermediate
+ values if it wants. */
+ if (TARGET_ARCH64
+ && HOST_BITS_PER_WIDE_INT != 64
+ && (INTVAL (op1) & 0x80000000) != 0)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode,
+ temp,
+ gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,
+ INTVAL (op1) & 0xfffffc00, 0)));
+ }
+ else
+ {
+ emit_insn (gen_rtx_SET (VOIDmode,
+ temp,
+ GEN_INT (INTVAL (op1) & 0xfffffc00)));
+ }
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_rtx_IOR (mode,
+ temp,
+ GEN_INT (INTVAL (op1) & 0x3ff))));
+ }
+ else
+ {
+ /* A symbol, emit in the traditional way. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ temp,
+ gen_rtx_HIGH (mode,
+ op1)));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_rtx_LO_SUM (mode,
+ temp,
+ op1)));
+
+ }
+}
+
+
+/* Sparc-v9 code-model support. */
+void
+sparc_emit_set_symbolic_const64 (op0, op1, temp1)
+ rtx op0;
+ rtx op1;
+ rtx temp1;
+{
+ switch (sparc_cmodel)
+ {
+ case CM_MEDLOW:
+ /* The range spanned by all instructions in the object is less
+ than 2^31 bytes (2GB) and the distance from any instruction
+ to the location of the label _GLOBAL_OFFSET_TABLE_ is less
+ than 2^31 bytes (2GB).
+
+ The executable must be in the low 4TB of the virtual address
+ space.
+
+ sethi %hi(symbol), %temp
+ or %temp, %lo(symbol), %reg */
+ emit_insn (gen_rtx_SET (VOIDmode, temp1, gen_rtx_HIGH (DImode, op1)));
+ emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_LO_SUM (DImode, temp1, op1)));
+ break;
+
+ case CM_MEDMID:
+ /* The range spanned by all instructions in the object is less
+ than 2^31 bytes (2GB) and the distance from any instruction
+ to the location of the label _GLOBAL_OFFSET_TABLE_ is less
+ than 2^31 bytes (2GB).
+
+ The executable must be in the low 16TB of the virtual address
+ space.
+
+ sethi %h44(symbol), %temp1
+ or %temp1, %m44(symbol), %temp2
+ sllx %temp2, 12, %temp3
+ or %temp3, %l44(symbol), %reg */
+ emit_insn (gen_seth44 (op0, op1));
+ emit_insn (gen_setm44 (op0, op0, op1));
+ emit_insn (gen_rtx_SET (VOIDmode, temp1,
+ gen_rtx_ASHIFT (DImode, op0, GEN_INT (12))));
+ emit_insn (gen_setl44 (op0, temp1, op1));
+ break;
+
+ case CM_MEDANY:
+ /* The range spanned by all instructions in the object is less
+ than 2^31 bytes (2GB) and the distance from any instruction
+ to the location of the label _GLOBAL_OFFSET_TABLE_ is less
+ than 2^31 bytes (2GB).
+
+ The executable can be placed anywhere in the virtual address
+ space.
+
+ sethi %hh(symbol), %temp1
+ sethi %lm(symbol), %temp2
+ or %temp1, %hm(symbol), %temp3
+ or %temp2, %lo(symbol), %temp4
+ sllx %temp3, 32, %temp5
+ or %temp4, %temp5, %reg */
+
+ /* Getting this right wrt. reloading is really tricky.
+ We _MUST_ have a seperate temporary at this point,
+ if we don't barf immediately instead of generating
+ incorrect code. */
+ if (temp1 == op0)
+ abort ();
+
+ emit_insn (gen_sethh (op0, op1));
+ emit_insn (gen_setlm (temp1, op1));
+ emit_insn (gen_sethm (op0, op0, op1));
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_PLUS (DImode, op0, temp1)));
+ emit_insn (gen_setlo (op0, op0, op1));
+ break;
+
+ case CM_EMBMEDANY:
+ /* Old old old backwards compatibility kruft here.
+ Essentially it is MEDLOW with a fixed 64-bit
+ virtual base added to all data segment addresses.
+ Text-segment stuff is computed like MEDANY, we can't
+ reuse the code above because the relocation knobs
+ look different.
+
+ Data segment: sethi %hi(symbol), %temp1
+ or %temp1, %lo(symbol), %temp2
+ add %temp2, EMBMEDANY_BASE_REG, %reg
+
+ Text segment: sethi %uhi(symbol), %temp1
+ sethi %hi(symbol), %temp2
+ or %temp1, %ulo(symbol), %temp3
+ or %temp2, %lo(symbol), %temp4
+ sllx %temp3, 32, %temp5
+ or %temp4, %temp5, %reg */
+ if (data_segment_operand (op1, GET_MODE (op1)))
+ {
+ emit_insn (gen_embmedany_sethi (temp1, op1));
+ emit_insn (gen_embmedany_brsum (op0, temp1));
+ emit_insn (gen_embmedany_losum (op0, op0, op1));
+ }
+ else
+ {
+ /* Getting this right wrt. reloading is really tricky.
+ We _MUST_ have a seperate temporary at this point,
+ so we barf immediately instead of generating
+ incorrect code. */
+ if (temp1 == op0)
+ abort ();
+
+ emit_insn (gen_embmedany_textuhi (op0, op1));
+ emit_insn (gen_embmedany_texthi (temp1, op1));
+ emit_insn (gen_embmedany_textulo (op0, op0, op1));
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_PLUS (DImode, op0, temp1)));
+ emit_insn (gen_embmedany_textlo (op0, op0, op1));
+ }
+ break;
+
+ default:
+ abort();
+ }
+}
+
+/* These avoid problems when cross compiling. If we do not
+ go through all this hair then the optimizer will see
+ invalid REG_EQUAL notes or in some cases none at all. */
+static void sparc_emit_set_safe_HIGH64 PROTO ((rtx, HOST_WIDE_INT));
+static rtx gen_safe_SET64 PROTO ((rtx, HOST_WIDE_INT));
+static rtx gen_safe_OR64 PROTO ((rtx, HOST_WIDE_INT));
+static rtx gen_safe_XOR64 PROTO ((rtx, HOST_WIDE_INT));
+
+#if HOST_BITS_PER_WIDE_INT == 64
+#define GEN_HIGHINT64(__x) GEN_INT ((__x) & 0xfffffc00)
+#define GEN_INT64(__x) GEN_INT (__x)
+#else
+#define GEN_HIGHINT64(__x) \
+ gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx, \
+ (__x) & 0xfffffc00, 0)
+#define GEN_INT64(__x) \
+ gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx, \
+ (__x) & 0xffffffff, \
+ ((__x) & 0x80000000 \
+ ? 0xffffffff : 0))
+#endif
+
+/* The optimizer is not to assume anything about exactly
+ which bits are set for a HIGH, they are unspecified.
+ Unfortunately this leads to many missed optimizations
+ during CSE. We mask out the non-HIGH bits, and matches
+ a plain movdi, to alleviate this problem. */
+static void
+sparc_emit_set_safe_HIGH64 (dest, val)
+ rtx dest;
+ HOST_WIDE_INT val;
+{
+ emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_HIGHINT64 (val)));
+}
+
+static rtx
+gen_safe_SET64 (dest, val)
+ rtx dest;
+ HOST_WIDE_INT val;
+{
+ return gen_rtx_SET (VOIDmode, dest, GEN_INT64 (val));
+}
+
+static rtx
+gen_safe_OR64 (src, val)
+ rtx src;
+ HOST_WIDE_INT val;
+{
+ return gen_rtx_IOR (DImode, src, GEN_INT64 (val));
+}
+
+static rtx
+gen_safe_XOR64 (src, val)
+ rtx src;
+ HOST_WIDE_INT val;
+{
+ return gen_rtx_XOR (DImode, src, GEN_INT64 (val));
+}
+
+/* Worker routines for 64-bit constant formation on arch64.
+ One of the key things to be doing in these emissions is
+ to create as many temp REGs as possible. This makes it
+ possible for half-built constants to be used later when
+ such values are similar to something required later on.
+ Without doing this, the optimizer cannot see such
+ opportunities. */
+
+static void sparc_emit_set_const64_quick1
+ PROTO((rtx, rtx, unsigned HOST_WIDE_INT, int));
+
+static void
+sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
+ rtx op0;
+ rtx temp;
+ unsigned HOST_WIDE_INT low_bits;
+ int is_neg;
+{
+ unsigned HOST_WIDE_INT high_bits;
+
+ if (is_neg)
+ high_bits = (~low_bits) & 0xffffffff;
+ else
+ high_bits = low_bits;
+
+ sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ if (!is_neg)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_safe_OR64 (temp, (high_bits & 0x3ff))));
+ }
+ else
+ {
+ /* If we are XOR'ing with -1, then we should emit a one's complement
+ instead. This way the combiner will notice logical operations
+ such as ANDN later on and substitute. */
+ if ((low_bits & 0x3ff) == 0x3ff)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_NOT (DImode, temp)));
+ }
+ else
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_safe_XOR64 (temp,
+ (-0x400 | (low_bits & 0x3ff)))));
+ }
+ }
+}
+
+static void sparc_emit_set_const64_quick2
+ PROTO((rtx, rtx, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, int));
+
+static void
+sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count)
+ rtx op0;
+ rtx temp;
+ unsigned HOST_WIDE_INT high_bits;
+ unsigned HOST_WIDE_INT low_immediate;
+ int shift_count;
+{
+ rtx temp2 = op0;
+
+ if ((high_bits & 0xfffffc00) != 0)
+ {
+ sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ if ((high_bits & ~0xfffffc00) != 0)
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_safe_OR64 (temp, (high_bits & 0x3ff))));
+ else
+ temp2 = temp;
+ }
+ else
+ {
+ emit_insn (gen_safe_SET64 (temp, high_bits));
+ temp2 = temp;
+ }
+
+ /* Now shift it up into place. */
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_ASHIFT (DImode, temp2,
+ GEN_INT (shift_count))));
+
+ /* If there is a low immediate part piece, finish up by
+ putting that in as well. */
+ if (low_immediate != 0)
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_safe_OR64 (op0, low_immediate)));
+}
+
+static void sparc_emit_set_const64_longway
+ PROTO((rtx, rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
+
+/* Full 64-bit constant decomposition. Even though this is the
+ 'worst' case, we still optimize a few things away. */
+static void
+sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits)
+ rtx op0;
+ rtx temp;
+ unsigned HOST_WIDE_INT high_bits;
+ unsigned HOST_WIDE_INT low_bits;
+{
+ rtx sub_temp;
+
+ if (reload_in_progress || reload_completed)
+ sub_temp = op0;
+ else
+ sub_temp = gen_reg_rtx (DImode);
+
+ if ((high_bits & 0xfffffc00) != 0)
+ {
+ sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ if ((high_bits & ~0xfffffc00) != 0)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ sub_temp,
+ gen_safe_OR64 (temp, (high_bits & 0x3ff))));
+ else
+ sub_temp = temp;
+ }
+ else
+ {
+ emit_insn (gen_safe_SET64 (temp, high_bits));
+ sub_temp = temp;
+ }
+
+ if (!reload_in_progress && !reload_completed)
+ {
+ rtx temp2 = gen_reg_rtx (DImode);
+ rtx temp3 = gen_reg_rtx (DImode);
+ rtx temp4 = gen_reg_rtx (DImode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, temp4,
+ gen_rtx_ASHIFT (DImode, sub_temp,
+ GEN_INT (32))));
+
+ sparc_emit_set_safe_HIGH64 (temp2, low_bits);
+ if ((low_bits & ~0xfffffc00) != 0)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, temp3,
+ gen_safe_OR64 (temp2, (low_bits & 0x3ff))));
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_PLUS (DImode, temp4, temp3)));
+ }
+ else
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_PLUS (DImode, temp4, temp2)));
+ }
+ }
+ else
+ {
+ rtx low1 = GEN_INT ((low_bits >> (32 - 12)) & 0xfff);
+ rtx low2 = GEN_INT ((low_bits >> (32 - 12 - 12)) & 0xfff);
+ rtx low3 = GEN_INT ((low_bits >> (32 - 12 - 12 - 8)) & 0x0ff);
+ int to_shift = 12;
+
+ /* We are in the middle of reload, so this is really
+ painful. However we do still make an attempt to
+ avoid emitting truly stupid code. */
+ if (low1 != const0_rtx)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_ASHIFT (DImode, sub_temp,
+ GEN_INT (to_shift))));
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_IOR (DImode, op0, low1)));
+ sub_temp = op0;
+ to_shift = 12;
+ }
+ else
+ {
+ to_shift += 12;
+ }
+ if (low2 != const0_rtx)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_ASHIFT (DImode, sub_temp,
+ GEN_INT (to_shift))));
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_IOR (DImode, op0, low2)));
+ sub_temp = op0;
+ to_shift = 8;
+ }
+ else
+ {
+ to_shift += 8;
+ }
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_ASHIFT (DImode, sub_temp,
+ GEN_INT (to_shift))));
+ if (low3 != const0_rtx)
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_IOR (DImode, op0, low3)));
+ /* phew... */
+ }
+}
+
+/* Analyze a 64-bit constant for certain properties. */
+static void analyze_64bit_constant
+ PROTO((unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ int *, int *, int *));
+
+static void
+analyze_64bit_constant (high_bits, low_bits, hbsp, lbsp, abbasp)
+ unsigned HOST_WIDE_INT high_bits, low_bits;
+ int *hbsp, *lbsp, *abbasp;
+{
+ int lowest_bit_set, highest_bit_set, all_bits_between_are_set;
+ int i;
+
+ lowest_bit_set = highest_bit_set = -1;
+ i = 0;
+ do
+ {
+ if ((lowest_bit_set == -1)
+ && ((low_bits >> i) & 1))
+ lowest_bit_set = i;
+ if ((highest_bit_set == -1)
+ && ((high_bits >> (32 - i - 1)) & 1))
+ highest_bit_set = (64 - i - 1);
+ }
+ while (++i < 32
+ && ((highest_bit_set == -1)
+ || (lowest_bit_set == -1)));
+ if (i == 32)
+ {
+ i = 0;
+ do
+ {
+ if ((lowest_bit_set == -1)
+ && ((high_bits >> i) & 1))
+ lowest_bit_set = i + 32;
+ if ((highest_bit_set == -1)
+ && ((low_bits >> (32 - i - 1)) & 1))
+ highest_bit_set = 32 - i - 1;
+ }
+ while (++i < 32
+ && ((highest_bit_set == -1)
+ || (lowest_bit_set == -1)));
+ }
+ /* If there are no bits set this should have gone out
+ as one instruction! */
+ if (lowest_bit_set == -1
+ || highest_bit_set == -1)
+ abort ();
+ all_bits_between_are_set = 1;
+ for (i = lowest_bit_set; i <= highest_bit_set; i++)
+ {
+ if (i < 32)
+ {
+ if ((low_bits & (1 << i)) != 0)
+ continue;
+ }
+ else
+ {
+ if ((high_bits & (1 << (i - 32))) != 0)
+ continue;
+ }
+ all_bits_between_are_set = 0;
+ break;
+ }
+ *hbsp = highest_bit_set;
+ *lbsp = lowest_bit_set;
+ *abbasp = all_bits_between_are_set;
+}
+
+static int const64_is_2insns
+ PROTO((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
+
+static int
+const64_is_2insns (high_bits, low_bits)
+ unsigned HOST_WIDE_INT high_bits, low_bits;
+{
+ int highest_bit_set, lowest_bit_set, all_bits_between_are_set;
+
+ if (high_bits == 0
+ || high_bits == 0xffffffff)
+ return 1;
+
+ analyze_64bit_constant (high_bits, low_bits,
+ &highest_bit_set, &lowest_bit_set,
+ &all_bits_between_are_set);
+
+ if ((highest_bit_set == 63
+ || lowest_bit_set == 0)
+ && all_bits_between_are_set != 0)
+ return 1;
+
+ if ((highest_bit_set - lowest_bit_set) < 21)
+ return 1;
+
+ return 0;
+}
+
+static unsigned HOST_WIDE_INT create_simple_focus_bits
+ PROTO((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+ int, int));
+
+static unsigned HOST_WIDE_INT
+create_simple_focus_bits (high_bits, low_bits, lowest_bit_set, shift)
+ unsigned HOST_WIDE_INT high_bits, low_bits;
+ int lowest_bit_set, shift;
+{
+ HOST_WIDE_INT hi, lo;
+
+ if (lowest_bit_set < 32)
+ {
+ lo = (low_bits >> lowest_bit_set) << shift;
+ hi = ((high_bits << (32 - lowest_bit_set)) << shift);
+ }
+ else
+ {
+ lo = 0;
+ hi = ((high_bits >> (lowest_bit_set - 32)) << shift);
+ }
+ if (hi & lo)
+ abort ();
+ return (hi | lo);
+}
+
+/* Here we are sure to be arch64 and this is an integer constant
+ being loaded into a register. Emit the most efficient
+ insn sequence possible. Detection of all the 1-insn cases
+ has been done already. */
+void
+sparc_emit_set_const64 (op0, op1)
+ rtx op0;
+ rtx op1;
+{
+ unsigned HOST_WIDE_INT high_bits, low_bits;
+ int lowest_bit_set, highest_bit_set;
+ int all_bits_between_are_set;
+ rtx temp;
+
+ /* Sanity check that we know what we are working with. */
+ if (! TARGET_ARCH64
+ || GET_CODE (op0) != REG
+ || (REGNO (op0) >= SPARC_FIRST_FP_REG
+ && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
+ abort ();
+
+ if (reload_in_progress || reload_completed)
+ temp = op0;
+ else
+ temp = gen_reg_rtx (DImode);
+
+ if (GET_CODE (op1) != CONST_DOUBLE
+ && GET_CODE (op1) != CONST_INT)
+ {
+ sparc_emit_set_symbolic_const64 (op0, op1, temp);
+ return;
+ }
+
+ if (GET_CODE (op1) == CONST_DOUBLE)
+ {
+#if HOST_BITS_PER_WIDE_INT == 64
+ high_bits = (CONST_DOUBLE_LOW (op1) >> 32) & 0xffffffff;
+ low_bits = CONST_DOUBLE_LOW (op1) & 0xffffffff;
+#else
+ high_bits = CONST_DOUBLE_HIGH (op1);
+ low_bits = CONST_DOUBLE_LOW (op1);
+#endif
+ }
+ else
+ {
+#if HOST_BITS_PER_WIDE_INT == 64
+ high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
+ low_bits = (INTVAL (op1) & 0xffffffff);
+#else
+ high_bits = ((INTVAL (op1) < 0) ?
+ 0xffffffff :
+ 0x00000000);
+ low_bits = INTVAL (op1);
+#endif
+ }
+
+ /* low_bits bits 0 --> 31
+ high_bits bits 32 --> 63 */
+
+ analyze_64bit_constant (high_bits, low_bits,
+ &highest_bit_set, &lowest_bit_set,
+ &all_bits_between_are_set);
+
+ /* First try for a 2-insn sequence. */
+
+ /* These situations are preferred because the optimizer can
+ * do more things with them:
+ * 1) mov -1, %reg
+ * sllx %reg, shift, %reg
+ * 2) mov -1, %reg
+ * srlx %reg, shift, %reg
+ * 3) mov some_small_const, %reg
+ * sllx %reg, shift, %reg
+ */
+ if (((highest_bit_set == 63
+ || lowest_bit_set == 0)
+ && all_bits_between_are_set != 0)
+ || ((highest_bit_set - lowest_bit_set) < 12))
+ {
+ HOST_WIDE_INT the_const = -1;
+ int shift = lowest_bit_set;
+
+ if ((highest_bit_set != 63
+ && lowest_bit_set != 0)
+ || all_bits_between_are_set == 0)
+ {
+ the_const =
+ create_simple_focus_bits (high_bits, low_bits,
+ lowest_bit_set, 0);
+ }
+ else if (lowest_bit_set == 0)
+ shift = -(63 - highest_bit_set);
+
+ if (! SPARC_SIMM13_P (the_const))
+ abort ();
+
+ emit_insn (gen_safe_SET64 (temp, the_const));
+ if (shift > 0)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_rtx_ASHIFT (DImode,
+ temp,
+ GEN_INT (shift))));
+ else if (shift < 0)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_rtx_LSHIFTRT (DImode,
+ temp,
+ GEN_INT (-shift))));
+ else
+ abort ();
+ return;
+ }
+
+ /* Now a range of 22 or less bits set somewhere.
+ * 1) sethi %hi(focus_bits), %reg
+ * sllx %reg, shift, %reg
+ * 2) sethi %hi(focus_bits), %reg
+ * srlx %reg, shift, %reg
+ */
+ if ((highest_bit_set - lowest_bit_set) < 21)
+ {
+ unsigned HOST_WIDE_INT focus_bits =
+ create_simple_focus_bits (high_bits, low_bits,
+ lowest_bit_set, 10);
+
+ if (! SPARC_SETHI_P (focus_bits))
+ abort ();
+
+ sparc_emit_set_safe_HIGH64 (temp, focus_bits);
+
+ /* If lowest_bit_set == 10 then a sethi alone could have done it. */
+ if (lowest_bit_set < 10)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_rtx_LSHIFTRT (DImode, temp,
+ GEN_INT (10 - lowest_bit_set))));
+ else if (lowest_bit_set > 10)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_rtx_ASHIFT (DImode, temp,
+ GEN_INT (lowest_bit_set - 10))));
+ else
+ abort ();
+ return;
+ }
+
+ /* 1) sethi %hi(low_bits), %reg
+ * or %reg, %lo(low_bits), %reg
+ * 2) sethi %hi(~low_bits), %reg
+ * xor %reg, %lo(-0x400 | (low_bits & 0x3ff)), %reg
+ */
+ if (high_bits == 0
+ || high_bits == 0xffffffff)
+ {
+ sparc_emit_set_const64_quick1 (op0, temp, low_bits,
+ (high_bits == 0xffffffff));
+ return;
+ }
+
+ /* Now, try 3-insn sequences. */
+
+ /* 1) sethi %hi(high_bits), %reg
+ * or %reg, %lo(high_bits), %reg
+ * sllx %reg, 32, %reg
+ */
+ if (low_bits == 0)
+ {
+ sparc_emit_set_const64_quick2 (op0, temp, high_bits, 0, 32);
+ return;
+ }
+
+ /* We may be able to do something quick
+ when the constant is negated, so try that. */
+ if (const64_is_2insns ((~high_bits) & 0xffffffff,
+ (~low_bits) & 0xfffffc00))
+ {
+ /* NOTE: The trailing bits get XOR'd so we need the
+ non-negated bits, not the negated ones. */
+ unsigned HOST_WIDE_INT trailing_bits = low_bits & 0x3ff;
+
+ if ((((~high_bits) & 0xffffffff) == 0
+ && ((~low_bits) & 0x80000000) == 0)
+ || (((~high_bits) & 0xffffffff) == 0xffffffff
+ && ((~low_bits) & 0x80000000) != 0))
+ {
+ int fast_int = (~low_bits & 0xffffffff);
+
+ if ((SPARC_SETHI_P (fast_int)
+ && (~high_bits & 0xffffffff) == 0)
+ || SPARC_SIMM13_P (fast_int))
+ emit_insn (gen_safe_SET64 (temp, fast_int));
+ else
+ sparc_emit_set_const64 (temp, GEN_INT64 (fast_int));
+ }
+ else
+ {
+ rtx negated_const;
+#if HOST_BITS_PER_WIDE_INT == 64
+ negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
+ (((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
+#else
+ negated_const = gen_rtx_CONST_DOUBLE (DImode, const0_rtx,
+ (~low_bits) & 0xfffffc00,
+ (~high_bits) & 0xffffffff);
+#endif
+ sparc_emit_set_const64 (temp, negated_const);
+ }
+
+ /* If we are XOR'ing with -1, then we should emit a one's complement
+ instead. This way the combiner will notice logical operations
+ such as ANDN later on and substitute. */
+ if (trailing_bits == 0x3ff)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, op0,
+ gen_rtx_NOT (DImode, temp)));
+ }
+ else
+ {
+ emit_insn (gen_rtx_SET (VOIDmode,
+ op0,
+ gen_safe_XOR64 (temp,
+ (-0x400 | trailing_bits))));
+ }
+ return;
+ }
+
+ /* 1) sethi %hi(xxx), %reg
+ * or %reg, %lo(xxx), %reg
+ * sllx %reg, yyy, %reg
+ *
+ * ??? This is just a generalized version of the low_bits==0
+ * thing above, FIXME...
+ */
+ if ((highest_bit_set - lowest_bit_set) < 32)
+ {
+ unsigned HOST_WIDE_INT focus_bits =
+ create_simple_focus_bits (high_bits, low_bits,
+ lowest_bit_set, 0);
+
+ /* We can't get here in this state. */
+ if (highest_bit_set < 32
+ || lowest_bit_set >= 32)
+ abort ();
+
+ /* So what we know is that the set bits straddle the
+ middle of the 64-bit word. */
+ sparc_emit_set_const64_quick2 (op0, temp,
+ focus_bits, 0,
+ lowest_bit_set);
+ return;
+ }
+
+ /* 1) sethi %hi(high_bits), %reg
+ * or %reg, %lo(high_bits), %reg
+ * sllx %reg, 32, %reg
+ * or %reg, low_bits, %reg
+ */
+ if (SPARC_SIMM13_P(low_bits)
+ && ((int)low_bits > 0))
+ {
+ sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_bits, 32);
+ return;
+ }
+
+ /* The easiest way when all else fails, is full decomposition. */
+#if 0
+ printf ("sparc_emit_set_const64: Hard constant [%08lx%08lx] neg[%08lx%08lx]\n",
+ high_bits, low_bits, ~high_bits, ~low_bits);
+#endif
+ sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
+}
+
/* X and Y are two things to compare using CODE. Emit the compare insn and
return the rtx for the cc reg in the proper mode. */
@@ -1061,15 +2064,8 @@ gen_compare_reg (code, x, y)
else
cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG);
- if (TARGET_V8PLUS && mode == CCXmode)
- {
- emit_insn (gen_cmpdi_v8plus (x, y));
- }
- else
- {
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
+ emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
gen_rtx_COMPARE (mode, x, y)));
- }
return cc_reg;
}
@@ -1240,7 +2236,7 @@ eligible_for_epilogue_delay (trial, slot)
/* In the case of a true leaf function, anything can go into the delay slot.
A delay slot only exists however if the frame size is zero, otherwise
we will put an insn to adjust the stack after the return. */
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
{
if (leaf_return_peephole_ok ())
return ((get_attr_in_uncond_branch_delay (trial)
@@ -1267,9 +2263,14 @@ eligible_for_epilogue_delay (trial, slot)
src = SET_SRC (pat);
- /* This matches "*return_[qhs]i". */
+ /* This matches "*return_[qhs]i" or even "*return_di" on TARGET_ARCH64. */
if (arith_operand (src, GET_MODE (src)))
- return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
+ {
+ if (TARGET_ARCH64)
+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
+ else
+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
+ }
/* This matches "*return_di". */
else if (arith_double_operand (src, GET_MODE (src)))
@@ -1449,8 +2450,7 @@ legitimize_pic_address (orig, mode, reg)
enum machine_mode mode ATTRIBUTE_UNUSED;
rtx reg;
{
- if (GET_CODE (orig) == SYMBOL_REF
- || GET_CODE (orig) == LABEL_REF)
+ if (GET_CODE (orig) == SYMBOL_REF)
{
rtx pic_ref, address;
rtx insn;
@@ -1475,9 +2475,16 @@ legitimize_pic_address (orig, mode, reg)
won't get confused into thinking that these two instructions
are loading in the true address of the symbol. If in the
future a PIC rtx exists, that should be used instead. */
- emit_insn (gen_pic_sethi_si (temp_reg, orig));
- emit_insn (gen_pic_lo_sum_si (temp_reg, temp_reg, orig));
-
+ if (Pmode == SImode)
+ {
+ emit_insn (gen_movsi_high_pic (temp_reg, orig));
+ emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
+ }
+ else
+ {
+ emit_insn (gen_movdi_high_pic (temp_reg, orig));
+ emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
+ }
address = temp_reg;
}
else
@@ -1532,18 +2539,15 @@ legitimize_pic_address (orig, mode, reg)
}
return gen_rtx_PLUS (Pmode, base, offset);
}
+ else if (GET_CODE (orig) == LABEL_REF)
+ /* ??? Why do we do this? */
+ /* Now movsi_pic_label_ref uses it, but we ought to be checking that
+ the register is live instead, in case it is eliminated. */
+ current_function_uses_pic_offset_table = 1;
return orig;
}
-/* Set up PIC-specific rtl. This should not cause any insns
- to be emitted. */
-
-void
-initialize_pic ()
-{
-}
-
/* Return the RTX for insns to set the PIC register. */
static rtx
@@ -1578,10 +2582,14 @@ finalize_pic ()
/* If we havn't emitted the special get_pc helper function, do so now. */
if (get_pc_symbol_name[0] == 0)
{
- ASM_GENERATE_INTERNAL_LABEL (get_pc_symbol_name, "LGETPC", 0);
+ int align;
+ ASM_GENERATE_INTERNAL_LABEL (get_pc_symbol_name, "LGETPC", 0);
text_section ();
- ASM_OUTPUT_ALIGN (asm_out_file, 3);
+
+ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ if (align > 0)
+ ASM_OUTPUT_ALIGN (asm_out_file, align);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0);
fputs ("\tretl\n\tadd %o7,%l7,%l7\n", asm_out_file);
}
@@ -1594,10 +2602,13 @@ finalize_pic ()
emit_insn_after (pic_setup_code (), get_insns ());
- /* Insert the code in each nonlocal goto receiver. */
+ /* Insert the code in each nonlocal goto receiver.
+ If you make changes here or to the nonlocal_goto_receiver
+ pattern, make sure the unspec_volatile numbers still
+ match. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == 4)
+ && XINT (PATTERN (insn), 1) == 5)
emit_insn_after (pic_setup_code (), insn);
flag_pic = orig_flag_pic;
@@ -1609,275 +2620,36 @@ finalize_pic ()
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
}
-/* Emit insns to move operands[1] into operands[0].
-
- Return 1 if we have written out everything that needs to be done to
- do the move. Otherwise, return 0 and the caller will emit the move
- normally. */
+/* Return 1 if RTX is a MEM which is known to be aligned to at
+ least an 8 byte boundary. */
int
-emit_move_sequence (operands, mode)
- rtx *operands;
- enum machine_mode mode;
-{
- register rtx operand0 = operands[0];
- register rtx operand1 = operands[1];
-
- if (CONSTANT_P (operand1) && flag_pic
- && pic_address_needs_scratch (operand1))
- operands[1] = operand1 = legitimize_pic_address (operand1, mode, 0);
-
- /* Handle most common case first: storing into a register. */
- if (register_operand (operand0, mode))
- {
- /* Integer constant to FP register. */
- if (GET_CODE (operand0) == REG
- && REGNO (operand0) >= 32
- && REGNO (operand0) < FIRST_PSEUDO_REGISTER
- && CONSTANT_P (operand1))
- {
- operand1 = validize_mem (force_const_mem (GET_MODE (operand0), operand1));
- }
-
- if (register_operand (operand1, mode)
- || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
- || (GET_CODE (operand1) == CONST_DOUBLE
- && arith_double_operand (operand1, DImode))
- || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) != DImode)
- /* Only `general_operands' can come here, so MEM is ok. */
- || GET_CODE (operand1) == MEM)
- {
- /* Run this case quickly. */
- emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
- return 1;
- }
- }
- else if (GET_CODE (operand0) == MEM)
- {
- if (register_operand (operand1, mode)
- || (operand1 == const0_rtx && ! TARGET_LIVE_G0))
- {
- /* Run this case quickly. */
- emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
- return 1;
- }
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operand0);
- operands[1] = operand1 = force_reg (mode, operand1);
- }
- }
-
- /* DImode HIGH values in sparc64 need a clobber added. */
- if (TARGET_ARCH64
- && GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode)
- {
- emit_insn (gen_sethi_di_sp64 (operand0, XEXP (operand1, 0)));
- return 1;
- }
- /* Simplify the source if we need to. */
- else if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
- {
- if (flag_pic && symbolic_operand (operand1, mode))
- {
- rtx temp_reg = reload_in_progress ? operand0 : 0;
-
- operands[1] = legitimize_pic_address (operand1, mode, temp_reg);
- }
- else if (GET_CODE (operand1) == CONST_INT
- ? (! SMALL_INT (operand1)
- && INTVAL (operand1) != -4096
- && ! SPARC_SETHI_P (INTVAL (operand1)))
- : GET_CODE (operand1) == CONST_DOUBLE
- ? ! arith_double_operand (operand1, DImode)
- : 1)
- {
- /* For DImode values, temp must be operand0 because of the way
- HI and LO_SUM work. The LO_SUM operator only copies half of
- the LSW from the dest of the HI operator. If the LO_SUM dest is
- not the same as the HI dest, then the MSW of the LO_SUM dest will
- never be set.
-
- ??? The real problem here is that the ...(HI:DImode pattern emits
- multiple instructions, and the ...(LO_SUM:DImode pattern emits
- one instruction. This fails, because the compiler assumes that
- LO_SUM copies all bits of the first operand to its dest. Better
- would be to have the HI pattern emit one instruction and the
- LO_SUM pattern multiple instructions. Even better would be
- to use four rtl insns. */
- rtx temp = ((reload_in_progress || mode == DImode)
- ? operand0 : gen_reg_rtx (mode));
-
- if (mode == SImode)
- {
- if (GET_CODE (operand1) == CONST_INT)
- operand1 = GEN_INT (INTVAL (operand1) & 0xffffffff);
- else if (GET_CODE (operand1) == CONST_DOUBLE)
- operand1 = GEN_INT (CONST_DOUBLE_LOW (operand1) & 0xffffffff);
- }
-
- if (TARGET_ARCH64 && mode == DImode)
- emit_insn (gen_sethi_di_sp64 (temp, operand1));
- else
- emit_insn (gen_rtx_SET (VOIDmode, temp,
- gen_rtx_HIGH (mode, operand1)));
-
- operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
- }
- }
-
- /* Now have insn-emit do whatever it normally does. */
- return 0;
-}
-
-/* Return the best assembler insn template
- for moving operands[1] into operands[0] as a 4 byte quantity.
-
- This isn't intended to be very smart. It is up to the caller to
- choose the best way to do things.
-
- Note that OPERANDS may be modified to suit the returned string. */
-
-char *
-singlemove_string (operands)
- rtx *operands;
+mem_min_alignment (mem, desired)
+ rtx mem;
+ int desired;
{
- if (GET_CODE (operands[0]) == MEM)
- {
- if (GET_CODE (operands[1]) != MEM)
- return "st %r1,%0";
- else
- abort ();
- }
- else if (GET_CODE (operands[1]) == MEM)
- return "ld %1,%0";
- else if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- REAL_VALUE_TYPE r;
- long i;
-
- /* Must be SFmode, otherwise this doesn't make sense. */
- if (GET_MODE (operands[1]) != SFmode)
- abort ();
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- operands[1] = GEN_INT (i);
-
- if (CONST_OK_FOR_LETTER_P (i, 'I'))
- return "mov %1,%0";
- else if ((i & 0x000003FF) != 0)
- return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
- else
- return "sethi %%hi(%a1),%0";
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- /* Only consider the low 32 bits of the constant. */
- int i = INTVAL (operands[1]) & 0xffffffff;
-
- if (SPARC_SIMM13_P (i))
- return "mov %1,%0";
-
- if (i == 4096)
- return "sub %%g0,-4096,%0";
-
- /* If all low order 10 bits are clear, then we only need a single
- sethi insn to load the constant. */
- /* FIXME: Use SETHI_P. */
- if ((i & 0x000003FF) != 0)
- return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
- else
- return "sethi %%hi(%a1),%0";
- }
- /* Operand 1 must be a register, or a 'I' type CONST_INT. */
- return "mov %1,%0";
-}
-
-/* Return the best assembler insn template
- for moving operands[1] into operands[0] as an 8 byte quantity.
-
- This isn't intended to be very smart. It is up to the caller to
- choose the best way to do things.
-
- Note that OPERANDS may be modified to suit the returned string. */
-
-char *
-doublemove_string (operands)
- rtx *operands;
-{
- rtx op0 = operands[0], op1 = operands[1];
-
- if (GET_CODE (op0) == MEM)
- {
- if (GET_CODE (op1) == REG)
- {
- if (FP_REG_P (op1))
- return "std %1,%0";
- return TARGET_ARCH64 ? "stx %1,%0" : "std %1,%0";
- }
- if (TARGET_ARCH64
- && (op1 == const0_rtx
- || (GET_MODE (op1) != VOIDmode
- && op1 == CONST0_RTX (GET_MODE (op1)))))
- return "stx %r1,%0";
- abort ();
- }
- else if (GET_CODE (op1) == MEM)
- {
- if (GET_CODE (op0) != REG)
- abort ();
- if (FP_REG_P (op0))
- return "ldd %1,%0";
- return TARGET_ARCH64 ? "ldx %1,%0" : "ldd %1,%0";
- }
- else if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- /* ??? Unfinished, and maybe not needed. */
- abort ();
- }
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* ??? Unfinished, and maybe not needed. */
- abort ();
- }
- /* Operand 1 must be a register, or a 'I' type CONST_INT. */
- return "mov %1,%0";
-}
-
-/* Return non-zero if it is OK to assume that the given memory operand is
- aligned at least to a 8-byte boundary. This should only be called
- for memory accesses whose size is 8 bytes or larger. */
-
-int
-mem_aligned_8 (mem)
- register rtx mem;
-{
- register rtx addr;
- register rtx base;
- register rtx offset;
+ rtx addr, base, offset;
+ /* If it's not a MEM we can't accept it. */
if (GET_CODE (mem) != MEM)
- return 0; /* It's gotta be a MEM! */
+ return 0;
addr = XEXP (mem, 0);
-
- /* Now that all misaligned double parms are copied on function entry,
- we can assume any 64-bit object is 64-bit aligned except those which
- are at unaligned offsets from the stack or frame pointer. If the
- TARGET_UNALIGNED_DOUBLES switch is given, we do not make this
- assumption. */
-
- /* See what register we use in the address. */
- base = offset = 0;
+ base = offset = NULL_RTX;
if (GET_CODE (addr) == PLUS)
{
- if (GET_CODE (XEXP (addr, 0)) == REG
- && GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ if (GET_CODE (XEXP (addr, 0)) == REG)
{
base = XEXP (addr, 0);
- offset = XEXP (addr, 1);
+
+ /* What we are saying here is that if the base
+ REG is aligned properly, the compiler will make
+ sure any REG based index upon it will be so
+ as well. */
+ if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ offset = XEXP (addr, 1);
+ else
+ offset = const0_rtx;
}
}
else if (GET_CODE (addr) == REG)
@@ -1886,862 +2658,42 @@ mem_aligned_8 (mem)
offset = const0_rtx;
}
- /* If it's the stack or frame pointer, check offset alignment.
- We can have improper alignment in the function entry code. */
- if (base
- && (REGNO (base) == FRAME_POINTER_REGNUM
- || REGNO (base) == STACK_POINTER_REGNUM))
- {
- if (((INTVAL (offset) - SPARC_STACK_BIAS) & 0x7) == 0)
- return 1;
- }
- /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES
- is true, in which case we can only assume that an access is aligned if
- it is to a constant address, or the address involves a LO_SUM.
-
- We used to assume an address was aligned if MEM_IN_STRUCT_P was true.
- That assumption was deleted so that gcc generated code can be used with
- memory allocators that only guarantee 4 byte alignment. */
- else if (! TARGET_UNALIGNED_DOUBLES || CONSTANT_P (addr)
- || GET_CODE (addr) == LO_SUM)
- return 1;
-
- /* An obviously unaligned address. */
- return 0;
-}
-
-enum optype { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP };
-
-/* Output assembler code to perform a doubleword move insn
- with operands OPERANDS. This is very similar to the following
- output_move_quad function. */
-
-char *
-output_move_double (operands)
- rtx *operands;
-{
- register rtx op0 = operands[0];
- register rtx op1 = operands[1];
- register enum optype optype0;
- register enum optype optype1;
- rtx latehalf[2];
- rtx addreg0 = 0;
- rtx addreg1 = 0;
- int highest_first = 0;
- int no_addreg1_decrement = 0;
-
- /* First classify both operands. */
-
- if (REG_P (op0))
- optype0 = REGOP;
- else if (offsettable_memref_p (op0))
- optype0 = OFFSOP;
- else if (GET_CODE (op0) == MEM)
- optype0 = MEMOP;
- else
- optype0 = RNDOP;
-
- if (REG_P (op1))
- optype1 = REGOP;
- else if (CONSTANT_P (op1))
- optype1 = CNSTOP;
- else if (offsettable_memref_p (op1))
- optype1 = OFFSOP;
- else if (GET_CODE (op1) == MEM)
- optype1 = MEMOP;
- else
- optype1 = RNDOP;
-
- /* Check for the cases that the operand constraints are not
- supposed to allow to happen. Abort if we get one,
- because generating code for these cases is painful. */
-
- if (optype0 == RNDOP || optype1 == RNDOP
- || (optype0 == MEM && optype1 == MEM))
- abort ();
-
- /* If an operand is an unoffsettable memory ref, find a register
- we can increment temporarily to make it refer to the second word. */
-
- if (optype0 == MEMOP)
- addreg0 = find_addr_reg (XEXP (op0, 0));
-
- if (optype1 == MEMOP)
- addreg1 = find_addr_reg (XEXP (op1, 0));
-
- /* Ok, we can do one word at a time.
- Set up in LATEHALF the operands to use for the
- high-numbered (least significant) word and in some cases alter the
- operands in OPERANDS to be suitable for the low-numbered word. */
-
- if (optype0 == REGOP)
- latehalf[0] = gen_rtx_REG (SImode, REGNO (op0) + 1);
- else if (optype0 == OFFSOP)
- latehalf[0] = adj_offsettable_operand (op0, 4);
- else
- latehalf[0] = op0;
-
- if (optype1 == REGOP)
- latehalf[1] = gen_rtx_REG (SImode, REGNO (op1) + 1);
- else if (optype1 == OFFSOP)
- latehalf[1] = adj_offsettable_operand (op1, 4);
- else if (optype1 == CNSTOP)
- {
- if (TARGET_ARCH64)
- {
- if (arith_double_operand (op1, DImode))
- {
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
- return "mov %1,%0";
- }
- else
- {
- /* The only way to handle CONST_DOUBLEs or other 64 bit
- constants here is to use a temporary, such as is done
- for the V9 DImode sethi insn pattern. This is not
- a practical solution, so abort if we reach here.
- The md file should always force such constants to
- memory. */
- abort ();
- }
- }
- else
- split_double (op1, &operands[1], &latehalf[1]);
- }
- else
- latehalf[1] = op1;
-
- /* Easy case: try moving both words at once. Check for moving between
- an even/odd register pair and a memory location. */
- if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
- && (TARGET_ARCH64 || (REGNO (op0) & 1) == 0))
- || (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
- && (TARGET_ARCH64 || (REGNO (op1) & 1) == 0)))
- {
- register rtx mem,reg;
-
- if (optype0 == REGOP)
- mem = op1, reg = op0;
- else
- mem = op0, reg = op1;
-
- /* In v9, ldd can be used for word aligned addresses, so technically
- some of this logic is unneeded. We still avoid ldd if the address
- is obviously unaligned though.
-
- Integer ldd/std are deprecated in V9 and are slow on UltraSPARC.
- Use them only if the access is volatile or not offsettable. */
-
- if ((mem_aligned_8 (mem)
- && (REGNO (reg) >= 32
- || MEM_VOLATILE_P (mem)
- || ! ((optype0 == OFFSOP || optype1 == OFFSOP)
- && (sparc_cpu == PROCESSOR_ULTRASPARC
- || sparc_cpu == PROCESSOR_V9))))
- /* If this is a floating point register higher than %f31,
- then we *must* use an aligned load, since `ld' will not accept
- the register number. */
- || (TARGET_V9 && REGNO (reg) >= 64)
- /* Even if two instructions would otherwise be better than ldd/std,
- if this insn was put in a delay slot because reorg thought it
- was only one machine instruction, make sure it is only one
- instruction. */
- || dbr_sequence_length () != 0)
- {
- if (FP_REG_P (reg) || ! TARGET_ARCH64)
- return (mem == op1 ? "ldd %1,%0" : "std %1,%0");
- else
- return (mem == op1 ? "ldx %1,%0" : "stx %1,%0");
- }
- }
-
- if (TARGET_ARCH64)
- {
- if (optype0 == REGOP && optype1 == REGOP)
- {
- if (FP_REG_P (op0))
- return "fmovd %1,%0";
- else
- return "mov %1,%0";
- }
- }
-
- /* If the first move would clobber the source of the second one,
- do them in the other order. */
-
- /* Overlapping registers. */
- if (optype0 == REGOP && optype1 == REGOP
- && REGNO (op0) == REGNO (latehalf[1]))
- {
- /* Do that word. */
- output_asm_insn (singlemove_string (latehalf), latehalf);
- /* Do low-numbered word. */
- return singlemove_string (operands);
- }
- /* Loading into a register which overlaps a register used in the address. */
- else if (optype0 == REGOP && optype1 != REGOP
- && reg_overlap_mentioned_p (op0, op1))
- {
- /* If both halves of dest are used in the src memory address,
- add the two regs and put them in the low reg (op0).
- Then it works to load latehalf first. */
- if (reg_mentioned_p (op0, XEXP (op1, 0))
- && reg_mentioned_p (latehalf[0], XEXP (op1, 0)))
- {
- rtx xops[2];
- xops[0] = latehalf[0];
- xops[1] = op0;
- output_asm_insn ("add %1,%0,%1", xops);
- operands[1] = gen_rtx_MEM (DImode, op0);
- latehalf[1] = adj_offsettable_operand (operands[1], 4);
- addreg1 = 0;
- highest_first = 1;
- }
- /* Only one register in the dest is used in the src memory address,
- and this is the first register of the dest, so we want to do
- the late half first here also. */
- else if (! reg_mentioned_p (latehalf[0], XEXP (op1, 0)))
- highest_first = 1;
- /* Only one register in the dest is used in the src memory address,
- and this is the second register of the dest, so we want to do
- the late half last. If addreg1 is set, and addreg1 is the same
- register as latehalf, then we must suppress the trailing decrement,
- because it would clobber the value just loaded. */
- else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0]))
- no_addreg1_decrement = 1;
- }
-
- /* Normal case: do the two words, low-numbered first.
- Overlap case (highest_first set): do high-numbered word first. */
-
- if (! highest_first)
- output_asm_insn (singlemove_string (operands), operands);
-
- /* Make any unoffsettable addresses point at high-numbered word. */
- if (addreg0)
- output_asm_insn ("add %0,0x4,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,0x4,%0", &addreg1);
-
- /* Do that word. */
- output_asm_insn (singlemove_string (latehalf), latehalf);
-
- /* Undo the adds we just did. */
- if (addreg0)
- output_asm_insn ("add %0,-0x4,%0", &addreg0);
- if (addreg1 && ! no_addreg1_decrement)
- output_asm_insn ("add %0,-0x4,%0", &addreg1);
-
- if (highest_first)
- output_asm_insn (singlemove_string (operands), operands);
-
- return "";
-}
-
-/* Output assembler code to perform a quadword move insn
- with operands OPERANDS. This is very similar to the preceding
- output_move_double function. */
-
-char *
-output_move_quad (operands)
- rtx *operands;
-{
- register rtx op0 = operands[0];
- register rtx op1 = operands[1];
- register enum optype optype0;
- register enum optype optype1;
- rtx wordpart[4][2];
- rtx load_late[4];
- int load_late_half[2];
- rtx addreg0 = 0;
- rtx addreg1 = 0;
-
- load_late_half[0] = 0; load_late_half[1] = 0;
- load_late[0] = 0; load_late[1] = 0; load_late[2] = 0;
- load_late[3] = 0;
-
- wordpart[0][0] = NULL; wordpart[1][0] = NULL; wordpart[2][0] = NULL;
- wordpart[3][0] = NULL;
-
- /* First classify both operands. */
-
- if (REG_P (op0))
- optype0 = REGOP;
- else if (offsettable_memref_p (op0))
- optype0 = OFFSOP;
- else if (GET_CODE (op0) == MEM)
- optype0 = MEMOP;
- else
- optype0 = RNDOP;
-
- if (REG_P (op1))
- optype1 = REGOP;
- else if (CONSTANT_P (op1))
- optype1 = CNSTOP;
- else if (offsettable_memref_p (op1))
- optype1 = OFFSOP;
- else if (GET_CODE (op1) == MEM)
- optype1 = MEMOP;
- else
- optype1 = RNDOP;
-
- /* Check for the cases that the operand constraints are not
- supposed to allow to happen. Abort if we get one,
- because generating code for these cases is painful. */
-
- if (optype0 == RNDOP || optype1 == RNDOP
- || (optype0 == MEM && optype1 == MEM))
- abort ();
-
- if (optype0 == REGOP)
- {
- wordpart[0][0] = gen_rtx_REG (word_mode, REGNO (op0) + 0);
- if (TARGET_ARCH64 && FP_REG_P (op0)
- && REGNO (op0) < SPARC_FIRST_V9_FP_REG)
- wordpart[1][0] = gen_rtx_REG (word_mode, REGNO (op0) + 2);
- else
- wordpart[1][0] = gen_rtx_REG (word_mode, REGNO (op0) + 1);
-
- if (TARGET_ARCH32)
- {
- wordpart[2][0] = gen_rtx_REG (word_mode, REGNO (op0) + 2);
- wordpart[3][0] = gen_rtx_REG (word_mode, REGNO (op0) + 3);
- }
-
- /* Loading into a register which overlaps a register used in the
- address. */
- if (optype1 != REGOP && reg_overlap_mentioned_p (op0, op1))
- {
- int i;
- int count;
-
- count = 0;
-
- for (i = 0; i < 4 && wordpart[i][0] != NULL; i++)
- {
- if (reg_mentioned_p (wordpart[i][0], op1))
- {
- load_late[i] = wordpart[i][0];
- load_late_half[TARGET_ARCH64 ? i : i/2] = 1;
- count++;
- }
- }
- if (count > 2)
- {
- /* Not sure what to do here. Multiple adds? Can't happen. */
- abort ();
- }
- else if (count == 2)
- {
- /* We have a two-address source operand, and both registers
- overlap with the dest quad. Add them together and
- store the result into the last register of the quad being
- loaded, then generate an appropriate MEM insn. */
- rtx temp[3];
- int place = 0;
-
- for (i = 0; i < 4; i++)
- {
- if (load_late[i])
- {
- temp[place++] = load_late[i];
- load_late[i] = 0;
- }
- }
- temp[2] = wordpart[3][0];
- output_asm_insn ("add %0, %1, %2", temp);
- load_late_half[0] = 0;
- load_late_half[1] = 1;
- op1 = gen_rtx_MEM (TFmode, wordpart[3][0]);
- operands[1] = op1;
- optype1 = OFFSOP;
- }
- }
- }
-
- /* If an operand is an unoffsettable memory ref, find a register
- we can increment temporarily to make it refer to the later words. */
-
- if (optype0 == MEMOP)
- addreg0 = find_addr_reg (XEXP (op0, 0));
-
- if (optype1 == MEMOP)
- addreg1 = find_addr_reg (XEXP (op1, 0));
-
- /* Ok, we can do one word at a time.
- Set up in wordpart the operands to use for each word of the arguments. */
-
- if (optype0 == OFFSOP)
- {
- wordpart[0][0] = adj_offsettable_operand (op0, 0);
- if (TARGET_ARCH32)
- {
- wordpart[1][0] = adj_offsettable_operand (op0, 4);
- wordpart[2][0] = adj_offsettable_operand (op0, 8);
- wordpart[3][0] = adj_offsettable_operand (op0, 12);
- }
- else
- wordpart[1][0] = adj_offsettable_operand (op0, 8);
- }
- else if (optype0 != REGOP)
- {
- wordpart[0][0] = op0;
- wordpart[1][0] = op0;
- wordpart[2][0] = op0;
- wordpart[3][0] = op0;
- }
-
- if (optype1 == REGOP)
+ if (base != NULL_RTX)
{
- wordpart[0][1] = gen_rtx_REG (word_mode, REGNO (op1) + 0);
- if (TARGET_ARCH64 && FP_REG_P (op1)
- && REGNO (op1) < SPARC_FIRST_V9_FP_REG)
- wordpart[1][1] = gen_rtx_REG (word_mode, REGNO (op1) + 2);
- else
- wordpart[1][1] = gen_rtx_REG (word_mode, REGNO (op1) + 1);
+ int regno = REGNO (base);
- if (TARGET_ARCH32)
- {
- wordpart[2][1] = gen_rtx_REG (word_mode, REGNO (op1) + 2);
- wordpart[3][1] = gen_rtx_REG (word_mode, REGNO (op1) + 3);
- }
- }
- else if (optype1 == OFFSOP)
- {
- wordpart[0][1] = adj_offsettable_operand (op1, 0);
- if (TARGET_ARCH32)
+ if (regno != FRAME_POINTER_REGNUM
+ && regno != STACK_POINTER_REGNUM)
{
- wordpart[1][1] = adj_offsettable_operand (op1, 4);
- wordpart[2][1] = adj_offsettable_operand (op1, 8);
- wordpart[3][1] = adj_offsettable_operand (op1, 12);
+ /* Check if the compiler has recorded some information
+ about the alignment of the base REG. If reload has
+ completed, we already matched with proper alignments. */
+ if (((regno_pointer_align != NULL
+ && REGNO_POINTER_ALIGN (regno) >= desired)
+ || reload_completed)
+ && ((INTVAL (offset) & (desired - 1)) == 0))
+ return 1;
}
else
- wordpart[1][1] = adj_offsettable_operand (op1, 8);
- }
- else if (optype1 == CNSTOP)
- {
- REAL_VALUE_TYPE r;
- long l[4];
-
- /* This only works for TFmode floating point constants. */
- if (GET_CODE (op1) != CONST_DOUBLE || GET_MODE (op1) != TFmode)
- abort ();
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op1);
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
-
- wordpart[0][1] = GEN_INT (l[0]);
- wordpart[1][1] = GEN_INT (l[1]);
- wordpart[2][1] = GEN_INT (l[2]);
- wordpart[3][1] = GEN_INT (l[3]);
- }
- else
- {
- wordpart[0][1] = op1;
- wordpart[1][1] = op1;
- wordpart[2][1] = op1;
- wordpart[3][1] = op1;
- }
-
- /* Easy case: try moving the quad as two pairs. Check for moving between
- an even/odd register pair and a memory location.
- Also handle new v9 fp regs here. */
- /* ??? Should also handle the case of non-offsettable addresses here.
- We can at least do the first pair as a ldd/std, and then do the third
- and fourth words individually. */
- if ((optype0 == REGOP && optype1 == OFFSOP && (REGNO (op0) & 1) == 0)
- || (optype0 == OFFSOP && optype1 == REGOP && (REGNO (op1) & 1) == 0))
- {
- rtx mem, reg;
- int use_ldx;
-
- if (optype0 == REGOP)
- mem = op1, reg = op0;
- else
- mem = op0, reg = op1;
-
- if (mem_aligned_8 (mem)
- /* If this is a floating point register higher than %f31,
- then we *must* use an aligned load, since `ld' will not accept
- the register number. */
- || (TARGET_V9 && REGNO (reg) >= SPARC_FIRST_V9_FP_REG))
- {
- static char * const mov_by_64[2][2][2] = {
- { { "std %S1,%2;std %1,%0", "stx %R1,%2;stx %1,%0" },
- { "ldd %2,%S0;ldd %1,%0", "ldx %2,%R0;ldx %1,%0" } },
- { { "std %1,%0;std %S1,%2", "stx %1,%0;stx %R1,%2" },
- { "ldd %1,%0;ldd %2,%S0", "ldx %1,%0;ldx %2,%R0" } }
- };
-
- if (TARGET_V9 && FP_REG_P (reg) && TARGET_HARD_QUAD)
- {
- /* Only abort if the register # requires that we use ldq. */
- if ((REGNO (reg) & 3) == 0)
- {
- /* ??? Can `mem' have an inappropriate alignment here? */
- return (mem == op1 ? "ldq %1,%0" : "stq %1,%0");
- }
- else
- {
- if (REGNO (reg) >= SPARC_FIRST_V9_FP_REG)
- abort();
- }
- }
- operands[2] = adj_offsettable_operand (mem, 8);
-
- /* Do the loads in the right order; can't overwrite our address
- register. */
- use_ldx = TARGET_ARCH64 && !FP_REG_P (reg);
- return mov_by_64[!load_late_half[0]][mem == op1][use_ldx];
- }
- }
-
- /* If the first move would clobber the source of the second one,
- do them in the other order. */
-
- /* Overlapping registers? */
- if (TARGET_ARCH32)
- {
- if (optype0 == REGOP && optype1 == REGOP
- && (REGNO (op0) == REGNO (wordpart[1][3])
- || REGNO (op0) == REGNO (wordpart[1][2])
- || REGNO (op0) == REGNO (wordpart[1][1])))
{
- /* Do fourth word. */
- output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
- /* Do the third word. */
- output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
- /* Do the second word. */
- output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
- /* Do lowest-numbered word. */
- output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]);
- return "";
- }
- }
- else /* TARGET_ARCH64 */
- {
- if (optype0 == REGOP && optype1 == REGOP
- && REGNO (op0) == REGNO (wordpart[1][1]))
- {
- output_asm_insn ("mov %1,%0", wordpart[1]);
- output_asm_insn ("mov %1,%0", wordpart[0]);
- return "";
- }
- }
-
- /* Normal case: move the words in lowest to highest address order.
- There may have an overlapping register; in that case, skip and go
- back. */
-
- if (TARGET_ARCH32)
- {
- int i;
- int offset = 0xc;
- rtx temp[2];
-
- for (i = 0; i < 4; i++)
- {
- if (! load_late[i])
- output_asm_insn (singlemove_string (wordpart[i]), wordpart[i]);
-
- if (i != 3)
- {
- /* Make any unoffsettable addresses point at the next word. */
- if (addreg0)
- output_asm_insn ("add %0,0x4,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,0x4,%0", &addreg1);
- }
- }
- for (i = 0; i < 4; i++)
- {
- if (load_late[i])
- {
- int fix = offset - i * 4;
-
- /* Back up to the appropriate place. */
- temp[1] = GEN_INT (-fix);
- if (addreg0)
- {
- temp[0] = addreg0;
- output_asm_insn ("add %0,%1,%0", temp);
- }
- if (addreg1)
- {
- temp[0] = addreg1;
- output_asm_insn ("add %0,%1,%0", temp);
- }
- output_asm_insn (singlemove_string (wordpart[i]),
- wordpart[i]);
- /* Don't modify the register that's the destination of the
- move. */
- temp[0] = GEN_INT (-(offset - fix));
- if (addreg0 && REGNO (addreg0) != REGNO (wordpart[i][0]))
- {
- temp[1] = addreg0;
- output_asm_insn("add %0,%1,%0", temp);
- }
- if (addreg1 && REGNO (addreg1) != REGNO (wordpart[i][0]))
- {
- temp[1] = addreg1;
- output_asm_insn("add %0,%1,%0",temp);
- }
- offset = 0;
- break;
- }
- }
- if (offset)
- {
- temp[1] = GEN_INT (-offset);
- /* Undo the adds we just did. */
- if (addreg0)
- {
- temp[0] = addreg0;
- output_asm_insn ("add %0,%1,%0", temp);
- }
- if (addreg1)
- {
- temp[0] = addreg1;
- output_asm_insn ("add %0,%1,%0", temp);
- }
+ if (((INTVAL (offset) - SPARC_STACK_BIAS) & (desired - 1)) == 0)
+ return 1;
}
}
- else /* TARGET_ARCH64 */
+ else if (! TARGET_UNALIGNED_DOUBLES
+ || CONSTANT_P (addr)
+ || GET_CODE (addr) == LO_SUM)
{
- if (load_late_half[0])
- {
- /* Load the second half first. */
- if (addreg0)
- output_asm_insn ("add %0,0x8,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,0x8,%0", &addreg1);
-
- output_asm_insn (doublemove_string (wordpart[1]), wordpart[1]);
-
- /* Undo the adds we just did. */
- if (addreg0)
- output_asm_insn ("add %0,-0x8,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,-0x8,%0", &addreg1);
-
- output_asm_insn (doublemove_string (wordpart[0]), wordpart[0]);
- }
- else
- {
- output_asm_insn (doublemove_string (wordpart[0]), wordpart[0]);
-
- if (addreg0)
- output_asm_insn ("add %0,0x8,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,0x8,%0", &addreg1);
-
- /* Do the second word. */
- output_asm_insn (doublemove_string (wordpart[1]), wordpart[1]);
-
- /* Undo the adds we just did. But don't modify the dest of
- the move. */
- if (addreg0 && REGNO (addreg0) != REGNO (wordpart[1][0]))
- output_asm_insn ("add %0,-0x8,%0", &addreg0);
- if (addreg1 && REGNO (addreg1) != REGNO (wordpart[1][0]))
- output_asm_insn ("add %0,-0x8,%0", &addreg1);
- }
+ /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES
+ is true, in which case we can only assume that an access is aligned if
+ it is to a constant address, or the address involves a LO_SUM. */
+ return 1;
}
- return "";
-}
-
-/* Output assembler code to perform a doubleword move insn with operands
- OPERANDS, one of which must be a floating point register. */
-
-char *
-output_fp_move_double (operands)
- rtx *operands;
-{
- if (FP_REG_P (operands[0]))
- {
- if (FP_REG_P (operands[1]))
- {
- if (TARGET_V9)
- return "fmovd %1,%0";
- else
- return "fmovs %1,%0\n\tfmovs %R1,%R0";
- }
- else if (GET_CODE (operands[1]) == REG)
- abort ();
- else
- return output_move_double (operands);
- }
- else if (FP_REG_P (operands[1]))
- {
- if (GET_CODE (operands[0]) == REG)
- abort ();
- else
- return output_move_double (operands);
- }
- else abort ();
-}
-
-/* When doing a quad-register move, determine the drection in which
- the move needs to be performed. SRC and DST are the source and
- destination registers.
-
- A value of -1 indicates that the move needs to be done from the
- highest register to the lowest. */
-
-static int
-move_quad_direction (src, dst)
- rtx src, dst;
-{
- if ((REGNO (dst) > REGNO (src))
- && (REGNO (dst) < (REGNO (src) + 4)))
- return -1;
- else
- return 1;
-}
-
-/* Output assembler code to perform a quadword move insn with operands
- OPERANDS, one of which must be a floating point register. */
-
-char *
-output_fp_move_quad (operands)
- rtx *operands;
-{
- register rtx op0 = operands[0];
- register rtx op1 = operands[1];
-
- if (FP_REG_P (op0))
- {
- if (FP_REG_P (op1))
- {
- if (TARGET_V9 && TARGET_HARD_QUAD)
- return "fmovq %1,%0";
- else if (TARGET_V9)
- {
- int dir = move_quad_direction (op1, op0);
- if (dir > 0)
- return "fmovd %1,%0\n\tfmovd %S1,%S0";
- else
- return "fmovd %S1,%S0\n\tfmovd %1,%0";
- }
- else
- {
- int dir = move_quad_direction (op0, op1);
- if (dir > 0)
- return "fmovs %1,%0\n\tfmovs %R1,%R0\n\tfmovs %S1,%S0\n\tfmovs %T1,%T0";
- else
- return "fmovs %T1,%T0\n\tfmovs %S1,%S0\n\tfmovs %R1,%R0\n\tfmovs %1,%0";
- }
- }
- else if (GET_CODE (op1) == REG)
- abort ();
- else
- return output_move_quad (operands);
- }
- else if (FP_REG_P (op1))
- {
- if (GET_CODE (op0) == REG)
- abort ();
- else
- return output_move_quad (operands);
- }
- else
- abort ();
-}
-
-/* Return a REG that occurs in ADDR with coefficient 1.
- ADDR can be effectively incremented by incrementing REG. */
-
-static rtx
-find_addr_reg (addr)
- rtx addr;
-{
- while (GET_CODE (addr) == PLUS)
- {
- /* We absolutely can not fudge the frame pointer here, because the
- frame pointer must always be 8 byte aligned. It also confuses
- debuggers. */
- if (GET_CODE (XEXP (addr, 0)) == REG
- && REGNO (XEXP (addr, 0)) != FRAME_POINTER_REGNUM)
- addr = XEXP (addr, 0);
- else if (GET_CODE (XEXP (addr, 1)) == REG
- && REGNO (XEXP (addr, 1)) != FRAME_POINTER_REGNUM)
- addr = XEXP (addr, 1);
- else if (CONSTANT_P (XEXP (addr, 0)))
- addr = XEXP (addr, 1);
- else if (CONSTANT_P (XEXP (addr, 1)))
- addr = XEXP (addr, 0);
- else
- abort ();
- }
- if (GET_CODE (addr) == REG)
- return addr;
- abort ();
+ /* An obviously unaligned address. */
+ return 0;
}
-
-/* Output reasonable peephole for set-on-condition-code insns.
- Note that these insns assume a particular way of defining
- labels. Therefore, *both* sparc.h and this function must
- be changed if a new syntax is needed. */
-char *
-output_scc_insn (operands, insn)
- rtx operands[];
- rtx insn;
-{
- static char string[100];
- rtx label = 0, next = insn;
- int need_label = 0;
-
- /* This code used to be called with final_sequence nonzero (for fpcc
- delay slots), but that is no longer allowed. */
- if (final_sequence)
- abort ();
-
- /* On UltraSPARC a conditional moves blocks until 3 cycles after prior loads
- complete. It might be beneficial here to use branches if any recent
- instructions were loads. */
- if (TARGET_V9 && REGNO (operands[1]) == SPARC_ICC_REG)
- return "mov 0,%0\n\tmov%C2 %x1,1,%0";
-
- /* Try doing a jump optimization which jump.c can't do for us
- because we did not expose that setcc works by using branches.
-
- If this scc insn is followed by an unconditional branch, then have
- the jump insn emitted here jump to that location, instead of to
- the end of the scc sequence as usual. */
-
- do
- {
- if (GET_CODE (next) == CODE_LABEL)
- label = next;
- next = NEXT_INSN (next);
- }
- while (next && (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL));
-
- if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next))
- label = JUMP_LABEL (next);
-
- /* If not optimizing, jump label fields are not set. To be safe, always
- check here to whether label is still zero. */
- if (label == 0)
- {
- label = gen_label_rtx ();
- need_label = 1;
- }
-
- LABEL_NUSES (label) += 1;
-
- /* operands[3] is an unused slot. */
- operands[3] = label;
-
- strcpy (string, output_cbranch (operands[2], 3, 0, 1, 0, 0));
- strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
-
- if (need_label)
- strcat (string, "\n%l3:");
-
- return string;
-}
/* Vectors to keep interesting information about registers where it can easily
be got. We use to use the actual mode value as the bit number, but there
@@ -2940,7 +2892,7 @@ static int
save_regs (file, low, high, base, offset, n_regs, real_offset)
FILE *file;
int low, high;
- char *base;
+ const char *base;
int offset;
int n_regs;
int real_offset;
@@ -2953,7 +2905,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
{
if (regs_ever_live[i] && ! call_used_regs[i])
{
- fprintf (file, "\tstx %s,[%s+%d]\n",
+ fprintf (file, "\tstx\t%s, [%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
@@ -2969,7 +2921,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
{
if (regs_ever_live[i+1] && ! call_used_regs[i+1])
{
- fprintf (file, "\tstd %s,[%s+%d]\n",
+ fprintf (file, "\tstd\t%s, [%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
if (dwarf2out_do_frame ())
{
@@ -2981,7 +2933,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
}
else
{
- fprintf (file, "\tst %s,[%s+%d]\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n",
reg_names[i], base, offset + 4 * n_regs);
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
@@ -2992,7 +2944,7 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
{
if (regs_ever_live[i+1] && ! call_used_regs[i+1])
{
- fprintf (file, "\tst %s,[%s+%d]\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n",
reg_names[i+1], base, offset + 4 * n_regs + 4);
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", i + 1, real_offset + 4 * n_regs + 4);
@@ -3013,7 +2965,7 @@ static int
restore_regs (file, low, high, base, offset, n_regs)
FILE *file;
int low, high;
- char *base;
+ const char *base;
int offset;
int n_regs;
{
@@ -3024,7 +2976,7 @@ restore_regs (file, low, high, base, offset, n_regs)
for (i = low; i < high; i++)
{
if (regs_ever_live[i] && ! call_used_regs[i])
- fprintf (file, "\tldx [%s+%d], %s\n",
+ fprintf (file, "\tldx\t[%s+%d], %s\n",
base, offset + 4 * n_regs, reg_names[i]),
n_regs += 2;
}
@@ -3035,15 +2987,15 @@ restore_regs (file, low, high, base, offset, n_regs)
{
if (regs_ever_live[i] && ! call_used_regs[i])
if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tldd [%s+%d], %s\n",
+ fprintf (file, "\tldd\t[%s+%d], %s\n",
base, offset + 4 * n_regs, reg_names[i]),
n_regs += 2;
else
- fprintf (file, "\tld [%s+%d],%s\n",
+ fprintf (file, "\tld\t[%s+%d],%s\n",
base, offset + 4 * n_regs, reg_names[i]),
n_regs += 2;
else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tld [%s+%d],%s\n",
+ fprintf (file, "\tld\t[%s+%d],%s\n",
base, offset + 4 * n_regs + 4, reg_names[i+1]),
n_regs += 2;
}
@@ -3128,13 +3080,13 @@ static void
build_big_number (file, num, reg)
FILE *file;
int num;
- char *reg;
+ const char *reg;
{
if (num >= 0 || ! TARGET_ARCH64)
{
- fprintf (file, "\tsethi %%hi(%d),%s\n", num, reg);
+ fprintf (file, "\tsethi\t%%hi(%d), %s\n", num, reg);
if ((num & 0x3ff) != 0)
- fprintf (file, "\tor %s,%%lo(%d),%s\n", reg, num, reg);
+ fprintf (file, "\tor\t%s, %%lo(%d), %s\n", reg, num, reg);
}
else /* num < 0 && TARGET_ARCH64 */
{
@@ -3147,7 +3099,7 @@ build_big_number (file, num, reg)
int inv = ~asize;
int low = -0x400 + (asize & 0x3FF);
- fprintf (file, "\tsethi %%hi(%d),%s\n\txor %s,%d,%s\n",
+ fprintf (file, "\tsethi\t%%hi(%d), %s\n\txor\t%s, %d, %s\n",
inv, reg, reg, low, reg);
}
}
@@ -3183,16 +3135,16 @@ output_function_prologue (file, size, leaf_function)
else if (! leaf_function && ! TARGET_BROKEN_SAVERESTORE)
{
if (actual_fsize <= 4096)
- fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);
+ fprintf (file, "\tsave\t%%sp, -%d, %%sp\n", actual_fsize);
else if (actual_fsize <= 8192)
{
- fprintf (file, "\tsave %%sp,-4096,%%sp\n");
- fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
+ fprintf (file, "\tsave\t%%sp, -4096, %%sp\n");
+ fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
}
else
{
build_big_number (file, -actual_fsize, "%g1");
- fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
+ fprintf (file, "\tsave\t%%sp, %%g1, %%sp\n");
}
}
else if (! leaf_function && TARGET_BROKEN_SAVERESTORE)
@@ -3203,31 +3155,31 @@ output_function_prologue (file, size, leaf_function)
fprintf (file, "\tsave\n");
if (actual_fsize <= 4096)
- fprintf (file, "\tadd %%fp,-%d,%%sp\n", actual_fsize);
+ fprintf (file, "\tadd\t%%fp, -%d, %%sp\n", actual_fsize);
else if (actual_fsize <= 8192)
{
- fprintf (file, "\tadd %%fp,-4096,%%sp\n");
- fprintf (file, "\tadd %%fp,-%d,%%sp\n", actual_fsize - 4096);
+ fprintf (file, "\tadd\t%%fp, -4096, %%sp\n");
+ fprintf (file, "\tadd\t%%fp, -%d, %%sp\n", actual_fsize - 4096);
}
else
{
build_big_number (file, -actual_fsize, "%g1");
- fprintf (file, "\tadd %%fp,%%g1,%%sp\n");
+ fprintf (file, "\tadd\t%%fp, %%g1, %%sp\n");
}
}
else /* leaf function */
{
if (actual_fsize <= 4096)
- fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
+ fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize);
else if (actual_fsize <= 8192)
{
- fprintf (file, "\tadd %%sp,-4096,%%sp\n");
- fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
+ fprintf (file, "\tadd\t%%sp, -4096, %%sp\n");
+ fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
}
else
{
build_big_number (file, -actual_fsize, "%g1");
- fprintf (file, "\tadd %%sp,%%g1,%%sp\n");
+ fprintf (file, "\tadd\t%%sp, %%g1, %%sp\n");
}
}
@@ -3260,7 +3212,7 @@ output_function_prologue (file, size, leaf_function)
if (num_gfregs)
{
int offset, real_offset, n_regs;
- char *base;
+ const char *base;
real_offset = -apparent_fsize;
offset = -apparent_fsize + frame_base_offset;
@@ -3273,7 +3225,7 @@ output_function_prologue (file, size, leaf_function)
output_function_epilogue will lose (the result will get
clobbered). */
build_big_number (file, offset, "%g1");
- fprintf (file, "\tadd %s,%%g1,%%g1\n", frame_base_name);
+ fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
base = "%g1";
offset = 0;
}
@@ -3311,7 +3263,7 @@ output_function_epilogue (file, size, leaf_function)
int size ATTRIBUTE_UNUSED;
int leaf_function;
{
- char *ret;
+ const char *ret;
if (leaf_label)
{
@@ -3328,25 +3280,26 @@ output_function_epilogue (file, size, leaf_function)
else if (current_function_epilogue_delay_list == 0)
{
- /* If code does not drop into the epilogue, do nothing. */
+ /* If code does not drop into the epilogue, we need
+ do nothing except output pending case vectors. */
rtx insn = get_last_insn ();
if (GET_CODE (insn) == NOTE)
insn = prev_nonnote_insn (insn);
if (insn && GET_CODE (insn) == BARRIER)
- return;
+ goto output_vectors;
}
/* Restore any call saved registers. */
if (num_gfregs)
{
int offset, n_regs;
- char *base;
+ const char *base;
offset = -apparent_fsize + frame_base_offset;
if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 /*double*/)
{
build_big_number (file, offset, "%g1");
- fprintf (file, "\tadd %s,%%g1,%%g1\n", frame_base_name);
+ fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
base = "%g1";
offset = 0;
}
@@ -3368,9 +3321,9 @@ output_function_epilogue (file, size, leaf_function)
/* Work out how to skip the caller's unimp instruction if required. */
if (leaf_function)
- ret = (SKIP_CALLERS_UNIMP_P ? "jmp %o7+12" : "retl");
+ ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%o7+12" : "retl");
else
- ret = (SKIP_CALLERS_UNIMP_P ? "jmp %i7+12" : "ret");
+ ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
if (TARGET_EPILOGUE || leaf_label)
{
@@ -3391,7 +3344,7 @@ output_function_epilogue (file, size, leaf_function)
final_scan_insn (insn, file, 1, 0, 1);
}
else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
- fputs ("\treturn %i7+8\n\tnop\n", file);
+ fputs ("\treturn\t%i7+8\n\tnop\n", file);
else
fprintf (file, "\t%s\n\trestore\n", ret);
}
@@ -3413,18 +3366,21 @@ output_function_epilogue (file, size, leaf_function)
else if (actual_fsize == 0)
fprintf (file, "\t%s\n\tnop\n", ret);
else if (actual_fsize <= 4096)
- fprintf (file, "\t%s\n\tsub %%sp,-%d,%%sp\n", ret, actual_fsize);
+ fprintf (file, "\t%s\n\tsub\t%%sp, -%d, %%sp\n", ret, actual_fsize);
else if (actual_fsize <= 8192)
- fprintf (file, "\tsub %%sp,-4096,%%sp\n\t%s\n\tsub %%sp,-%d,%%sp\n",
+ fprintf (file, "\tsub\t%%sp, -4096, %%sp\n\t%s\n\tsub\t%%sp, -%d, %%sp\n",
ret, actual_fsize - 4096);
else if ((actual_fsize & 0x3ff) == 0)
- fprintf (file, "\tsethi %%hi(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
+ fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
actual_fsize, ret);
else
- fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
+ fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\tor\t%%g1, %%lo(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
actual_fsize, actual_fsize, ret);
target_flags |= old_target_epilogue;
}
+
+ output_vectors:
+ sparc_output_deferred_case_vectors ();
}
/* Functions for handling argument passing.
@@ -3661,6 +3617,13 @@ struct function_arg_record_value_parms
int nregs, intoffset;
};
+static void function_arg_record_value_3
+ PROTO((int, struct function_arg_record_value_parms *));
+static void function_arg_record_value_2
+ PROTO((tree, int, struct function_arg_record_value_parms *));
+static rtx function_arg_record_value
+ PROTO((tree, enum machine_mode, int, int, int));
+
static void
function_arg_record_value_1 (type, startbitpos, parms)
tree type;
@@ -3902,7 +3865,7 @@ function_arg_record_value (type, mode, slotno, named, regbase)
nregs = SPARC_INT_ARG_MAX - slotno;
}
if (nregs == 0)
- abort();
+ abort ();
parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs));
@@ -4278,6 +4241,12 @@ function_value (type, mode, incoming_p)
mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
}
}
+
+ if (TARGET_ARCH64
+ && GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) < UNITS_PER_WORD
+ && type && TREE_CODE (type) != UNION_TYPE)
+ mode = DImode;
if (incoming_p)
regno = BASE_RETURN_VALUE_REG (mode);
@@ -4314,7 +4283,7 @@ sparc_builtin_saveregs (arglist)
GEN_INT (STACK_POINTER_OFFSET
+ UNITS_PER_WORD * first_reg));
- if (flag_check_memory_usage
+ if (current_function_check_memory_usage
&& first_reg < NPARM_REGS (word_mode))
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
address, ptr_mode,
@@ -4346,16 +4315,16 @@ output_cbranch (op, label, reversed, annul, noop, insn)
int reversed, annul, noop;
rtx insn;
{
- static char string[20];
+ static char string[32];
enum rtx_code code = GET_CODE (op);
rtx cc_reg = XEXP (op, 0);
enum machine_mode mode = GET_MODE (cc_reg);
- static char v8_labelno[] = " %lX";
- static char v9_icc_labelno[] = " %%icc,%lX";
- static char v9_xcc_labelno[] = " %%xcc,%lX";
- static char v9_fcc_labelno[] = " %%fccX,%lY";
+ static char v8_labelno[] = "%lX";
+ static char v9_icc_labelno[] = "%%icc, %lX";
+ static char v9_xcc_labelno[] = "%%xcc, %lX";
+ static char v9_fcc_labelno[] = "%%fccX, %lY";
char *labelno;
- int labeloff;
+ int labeloff, spaces = 8;
/* ??? !v9: FP branches cannot be preceded by another floating point insn.
Because there is currently no concept of pre-delay slots, we can fix
@@ -4376,16 +4345,28 @@ output_cbranch (op, label, reversed, annul, noop, insn)
{
case NE:
if (mode == CCFPmode || mode == CCFPEmode)
- strcat (string, "fbne");
+ {
+ strcat (string, "fbne");
+ spaces -= 4;
+ }
else
- strcpy (string, "bne");
+ {
+ strcpy (string, "bne");
+ spaces -= 3;
+ }
break;
case EQ:
if (mode == CCFPmode || mode == CCFPEmode)
- strcat (string, "fbe");
+ {
+ strcat (string, "fbe");
+ spaces -= 3;
+ }
else
- strcpy (string, "be");
+ {
+ strcpy (string, "be");
+ spaces -= 2;
+ }
break;
case GE:
@@ -4395,23 +4376,39 @@ output_cbranch (op, label, reversed, annul, noop, insn)
strcat (string, "fbul");
else
strcat (string, "fbge");
+ spaces -= 4;
}
else if (mode == CC_NOOVmode)
- strcpy (string, "bpos");
+ {
+ strcpy (string, "bpos");
+ spaces -= 4;
+ }
else
- strcpy (string, "bge");
+ {
+ strcpy (string, "bge");
+ spaces -= 3;
+ }
break;
case GT:
if (mode == CCFPmode || mode == CCFPEmode)
{
if (reversed)
- strcat (string, "fbule");
+ {
+ strcat (string, "fbule");
+ spaces -= 5;
+ }
else
- strcat (string, "fbg");
+ {
+ strcat (string, "fbg");
+ spaces -= 3;
+ }
}
else
- strcpy (string, "bg");
+ {
+ strcpy (string, "bg");
+ spaces -= 2;
+ }
break;
case LE:
@@ -4421,52 +4418,75 @@ output_cbranch (op, label, reversed, annul, noop, insn)
strcat (string, "fbug");
else
strcat (string, "fble");
+ spaces -= 4;
}
else
- strcpy (string, "ble");
+ {
+ strcpy (string, "ble");
+ spaces -= 3;
+ }
break;
case LT:
if (mode == CCFPmode || mode == CCFPEmode)
{
if (reversed)
- strcat (string, "fbuge");
+ {
+ strcat (string, "fbuge");
+ spaces -= 5;
+ }
else
- strcat (string, "fbl");
+ {
+ strcat (string, "fbl");
+ spaces -= 3;
+ }
}
else if (mode == CC_NOOVmode)
- strcpy (string, "bneg");
+ {
+ strcpy (string, "bneg");
+ spaces -= 4;
+ }
else
- strcpy (string, "bl");
+ {
+ strcpy (string, "bl");
+ spaces -= 2;
+ }
break;
case GEU:
strcpy (string, "bgeu");
+ spaces -= 4;
break;
case GTU:
strcpy (string, "bgu");
+ spaces -= 3;
break;
case LEU:
strcpy (string, "bleu");
+ spaces -= 4;
break;
case LTU:
strcpy (string, "blu");
+ spaces -= 3;
break;
default:
- break;
+ abort ();
}
/* Now add the annulling, the label, and a possible noop. */
if (annul)
- strcat (string, ",a");
+ {
+ strcat (string, ",a");
+ spaces -= 2;
+ }
if (! TARGET_V9)
{
- labeloff = 3;
+ labeloff = 2;
labelno = v8_labelno;
}
else
@@ -4474,7 +4494,11 @@ output_cbranch (op, label, reversed, annul, noop, insn)
rtx note;
if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
- strcat (string, INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
+ {
+ strcat (string,
+ INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
+ spaces -= 3;
+ }
labeloff = 9;
if (mode == CCFPmode || mode == CCFPEmode)
@@ -4482,7 +4506,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
labeloff = 10;
labelno = v9_fcc_labelno;
/* Set the char indicating the number of the fcc reg to use. */
- labelno[6] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
+ labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
}
else if (mode == CCXmode || mode == CCX_NOOVmode)
labelno = v9_xcc_labelno;
@@ -4492,6 +4516,10 @@ output_cbranch (op, label, reversed, annul, noop, insn)
/* Set the char indicating the number of the operand containing the
label_ref. */
labelno[labeloff] = label + '0';
+ if (spaces > 0)
+ strcat (string, "\t");
+ else
+ strcat (string, " ");
strcat (string, labelno);
if (noop)
@@ -4512,15 +4540,18 @@ output_cbranch (op, label, reversed, annul, noop, insn)
NOOP is non-zero if we have to follow this branch by a noop. */
char *
-output_v9branch (op, reg, label, reversed, annul, noop)
+output_v9branch (op, reg, label, reversed, annul, noop, insn)
rtx op;
int reg, label;
int reversed, annul, noop;
+ rtx insn;
{
static char string[20];
enum rtx_code code = GET_CODE (op);
enum machine_mode mode = GET_MODE (XEXP (op, 0));
- static char labelno[] = " %X,%lX";
+ static char labelno[] = "%X, %lX";
+ rtx note;
+ int spaces = 8;
/* If not floating-point or if EQ or NE, we can just reverse the code. */
if (reversed)
@@ -4536,26 +4567,32 @@ output_v9branch (op, reg, label, reversed, annul, noop)
{
case NE:
strcpy (string, "brnz");
+ spaces -= 4;
break;
case EQ:
strcpy (string, "brz");
+ spaces -= 3;
break;
case GE:
strcpy (string, "brgez");
+ spaces -= 5;
break;
case LT:
strcpy (string, "brlz");
+ spaces -= 4;
break;
case LE:
strcpy (string, "brlez");
+ spaces -= 5;
break;
case GT:
strcpy (string, "brgz");
+ spaces -= 4;
break;
default:
@@ -4564,12 +4601,24 @@ output_v9branch (op, reg, label, reversed, annul, noop)
/* Now add the annulling, reg, label, and nop. */
if (annul)
- strcat (string, ",a");
+ {
+ strcat (string, ",a");
+ spaces -= 2;
+ }
- /* ??? Optional prediction bit ",pt" or ",pf" goes here. */
+ if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
+ {
+ strcat (string,
+ INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
+ spaces -= 3;
+ }
- labelno[2] = reg + '0';
+ labelno[1] = reg + '0';
labelno[6] = label + '0';
+ if (spaces > 0)
+ strcat (string, "\t");
+ else
+ strcat (string, " ");
strcat (string, labelno);
if (noop)
@@ -4626,13 +4675,13 @@ epilogue_renumber (where)
default:
debug_rtx (*where);
- abort();
+ abort ();
}
}
/* Output assembler code to return from a function. */
-char *
+const char *
output_return (operands)
rtx *operands;
{
@@ -4643,7 +4692,7 @@ output_return (operands)
operands[0] = leaf_label;
return "b%* %l0%(";
}
- else if (leaf_function)
+ else if (current_function_uses_only_leaf_regs)
{
/* No delay slot in a leaf function. */
if (delay)
@@ -4661,24 +4710,24 @@ output_return (operands)
if (actual_fsize <= 4096)
{
if (SKIP_CALLERS_UNIMP_P)
- return "jmp %%o7+12\n\tsub %%sp,-%0,%%sp";
+ return "jmp\t%%o7+12\n\tsub\t%%sp, -%0, %%sp";
else
- return "retl\n\tsub %%sp,-%0,%%sp";
+ return "retl\n\tsub\t%%sp, -%0, %%sp";
}
else if (actual_fsize <= 8192)
{
operands[0] = GEN_INT (actual_fsize - 4096);
if (SKIP_CALLERS_UNIMP_P)
- return "sub %%sp,-4096,%%sp\n\tjmp %%o7+12\n\tsub %%sp,-%0,%%sp";
+ return "sub\t%%sp, -4096, %%sp\n\tjmp\t%%o7+12\n\tsub\t%%sp, -%0, %%sp";
else
- return "sub %%sp,-4096,%%sp\n\tretl\n\tsub %%sp,-%0,%%sp";
+ return "sub\t%%sp, -4096, %%sp\n\tretl\n\tsub\t%%sp, -%0, %%sp";
}
else if (SKIP_CALLERS_UNIMP_P)
{
if ((actual_fsize & 0x3ff) != 0)
- return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
+ return "sethi\t%%hi(%a0), %%g1\n\tor\t%%g1, %%lo(%a0), %%g1\n\tjmp\t%%o7+12\n\tadd\t%%sp, %%g1, %%sp";
else
- return "sethi %%hi(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
+ return "sethi\t%%hi(%a0), %%g1\n\tjmp\t%%o7+12\n\tadd\t%%sp, %%g1, %%sp";
}
else
{
@@ -4696,16 +4745,16 @@ output_return (operands)
epilogue_renumber (&SET_SRC (PATTERN (delay)));
}
if (SKIP_CALLERS_UNIMP_P)
- return "return %%i7+12%#";
+ return "return\t%%i7+12%#";
else
- return "return %%i7+8%#";
+ return "return\t%%i7+8%#";
}
else
{
if (delay)
abort ();
if (SKIP_CALLERS_UNIMP_P)
- return "jmp %%i7+12\n\trestore";
+ return "jmp\t%%i7+12\n\trestore";
else
return "ret\n\trestore";
}
@@ -4736,6 +4785,53 @@ order_regs_for_local_alloc ()
}
}
+/* Return 1 if REG and MEM are legitimate enough to allow the various
+ mem<-->reg splits to be run. */
+
+int
+sparc_splitdi_legitimate (reg, mem)
+ rtx reg;
+ rtx mem;
+{
+ /* Punt if we are here by mistake. */
+ if (! reload_completed)
+ abort ();
+
+ /* We must have an offsettable memory reference. */
+ if (! offsettable_memref_p (mem))
+ return 0;
+
+ /* If we have legitimate args for ldd/std, we do not want
+ the split to happen. */
+ if ((REGNO (reg) % 2) == 0
+ && mem_min_alignment (mem, 8))
+ return 0;
+
+ /* Success. */
+ return 1;
+}
+
+/* Return 1 if x and y are some kind of REG and they refer to
+ different hard registers. This test is guarenteed to be
+ run after reload. */
+
+int
+sparc_absnegfloat_split_legitimate (x, y)
+ rtx x, y;
+{
+ if (GET_CODE (x) == SUBREG)
+ x = alter_subreg (x);
+ if (GET_CODE (x) != REG)
+ return 0;
+ if (GET_CODE (y) == SUBREG)
+ y = alter_subreg (y);
+ if (GET_CODE (y) != REG)
+ return 0;
+ if (REGNO (x) == REGNO (y))
+ return 0;
+ return 1;
+}
+
/* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
This makes them candidates for using ldd and std insns.
@@ -4866,7 +4962,7 @@ print_operand (file, x, code)
case '#':
/* Output a 'nop' if there's nothing for the delay slot. */
if (dbr_sequence_length () == 0)
- fputs ("\n\tnop", file);
+ fputs ("\n\t nop", file);
return;
case '*':
/* Output an annul flag if there's nothing for the delay slot and we
@@ -4884,7 +4980,7 @@ print_operand (file, x, code)
not optimizing. This is always used with '*' above. */
if (dbr_sequence_length () == 0
&& ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
- fputs ("\n\tnop", file);
+ fputs ("\n\t nop", file);
return;
case '_':
/* Output the Embedded Medium/Anywhere code model base register. */
@@ -5086,7 +5182,10 @@ print_operand (file, x, code)
else if (GET_CODE (x) == LO_SUM)
{
print_operand (file, XEXP (x, 0), 0);
- fputs ("+%lo(", file);
+ if (TARGET_CM_MEDMID)
+ fputs ("+%l44(", file);
+ else
+ fputs ("+%lo(", file);
output_addr_const (file, XEXP (x, 1));
fputc (')', file);
}
@@ -5152,7 +5251,7 @@ output_double_int (file, value)
|| GET_CODE (value) == CODE_LABEL
|| GET_CODE (value) == MINUS)))
{
- if (!TARGET_V9 || TARGET_CM_MEDLOW)
+ if (! TARGET_V9)
{
ASM_OUTPUT_INT (file, const0_rtx);
ASM_OUTPUT_INT (file, value);
@@ -5335,14 +5434,18 @@ sparc_initialize_trampoline (tramp, fnaddr, cxt)
{
/* SPARC 32 bit trampoline:
- sethi %hi(fn),%g1
- sethi %hi(static),%g2
- jmp %g1+%lo(fn)
- or %g2,%lo(static),%g2
+ sethi %hi(fn), %g1
+ sethi %hi(static), %g2
+ jmp %g1+%lo(fn)
+ or %g2, %lo(static), %g2
SETHI i,r = 00rr rrr1 00ii iiii iiii iiii iiii iiii
JMPL r+i,d = 10dd ddd1 1100 0rrr rr1i iiii iiii iiii
*/
+#ifdef TRANSFER_FROM_TRAMPOLINE
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+ 0, VOIDmode, 1, tramp, Pmode);
+#endif
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 0)),
expand_binop (SImode, ior_optab,
@@ -5386,11 +5489,16 @@ void
sparc64_initialize_trampoline (tramp, fnaddr, cxt)
rtx tramp, fnaddr, cxt;
{
+#ifdef TRANSFER_FROM_TRAMPOLINE
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+ 0, VOIDmode, 1, tramp, Pmode);
+#endif
+
/*
- rd %pc,%g1
- ldx [%g1+24],%g5
- jmp %g5
- ldx [%g1+16],%g5
+ rd %pc, %g1
+ ldx [%g1+24], %g5
+ jmp %g5
+ ldx [%g1+16], %g5
+16 bytes data
*/
@@ -5399,12 +5507,13 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
GEN_INT (0xca586018));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
- GEN_INT (0x81c04000));
+ GEN_INT (0x81c14000));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
GEN_INT (0xca586010));
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 16)), cxt);
- emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 20)), fnaddr);
+ emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 24)), fnaddr);
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (DImode, tramp))));
+
if (sparc_cpu != PROCESSOR_ULTRASPARC)
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
}
@@ -5525,18 +5634,23 @@ sparc_flat_compute_frame_size (size)
/* This is the size of the 16 word reg save area, 1 word struct addr
area, and 4 word fp/alu register copy area. */
- extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0);
- var_size = size;
- /* Also include the size needed for the 6 parameter registers. */
- args_size = current_function_outgoing_args_size + 24;
- total_size = var_size + args_size + extra_size;
- gp_reg_size = 0;
- fp_reg_size = 0;
- gmask = 0;
- fmask = 0;
- reg_offset = 0;
+ extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0);
+ var_size = size;
+ gp_reg_size = 0;
+ fp_reg_size = 0;
+ gmask = 0;
+ fmask = 0;
+ reg_offset = 0;
need_aligned_p = 0;
+ args_size = 0;
+ if (!leaf_function_p ())
+ {
+ /* Also include the size needed for the 6 parameter registers. */
+ args_size = current_function_outgoing_args_size + 24;
+ }
+ total_size = var_size + args_size;
+
/* Calculate space needed for gp registers. */
for (regno = 1; regno <= 31; regno++)
{
@@ -5585,9 +5699,13 @@ sparc_flat_compute_frame_size (size)
total_size += gp_reg_size + fp_reg_size;
}
- /* ??? This looks a little suspicious. Clarify. */
- if (total_size == extra_size)
- total_size = extra_size = 0;
+ /* If we must allocate a stack frame at all, we must also allocate
+ room for register window spillage, so as to be binary compatible
+ with libraries and operating systems that do not use -mflat. */
+ if (total_size > 0)
+ total_size += extra_size;
+ else
+ extra_size = 0;
total_size = SPARC_STACK_ALIGN (total_size);
@@ -5656,7 +5774,7 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
if (word_op[0] == 's')
{
- fprintf (file, "\t%s %s,[%s+%d]\n",
+ fprintf (file, "\t%s\t%s, [%s+%d]\n",
doubleword_op, reg_names[regno],
base_reg, offset);
if (dwarf2out_do_frame ())
@@ -5668,7 +5786,7 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
}
}
else
- fprintf (file, "\t%s [%s+%d],%s\n",
+ fprintf (file, "\t%s\t[%s+%d], %s\n",
doubleword_op, base_reg, offset,
reg_names[regno]);
@@ -5679,14 +5797,14 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
{
if (word_op[0] == 's')
{
- fprintf (file, "\t%s %s,[%s+%d]\n",
+ fprintf (file, "\t%s\t%s, [%s+%d]\n",
word_op, reg_names[regno],
base_reg, offset);
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", regno, offset + base_offset);
}
else
- fprintf (file, "\t%s [%s+%d],%s\n",
+ fprintf (file, "\t%s\t[%s+%d], %s\n",
word_op, base_reg, offset, reg_names[regno]);
offset += UNITS_PER_WORD;
@@ -5703,14 +5821,14 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
{
if (word_op[0] == 's')
{
- fprintf (file, "\t%s %s,[%s+%d]\n",
+ fprintf (file, "\t%s\t%s, [%s+%d]\n",
word_op, reg_names[regno],
base_reg, offset);
if (dwarf2out_do_frame ())
dwarf2out_reg_save ("", regno, offset + base_offset);
}
else
- fprintf (file, "\t%s [%s+%d],%s\n",
+ fprintf (file, "\t%s\t[%s+%d], %s\n",
word_op, base_reg, offset, reg_names[regno]);
offset += UNITS_PER_WORD;
@@ -5764,7 +5882,7 @@ sparc_flat_output_function_prologue (file, size)
{
unsigned int reg_offset = current_frame_info.reg_offset;
char *fp_str = reg_names[FRAME_POINTER_REGNUM];
- char *t1_str = "%g1";
+ const char *t1_str = "%g1";
/* Things get a little tricky if local variables take up more than ~4096
bytes and outgoing arguments take up more than ~4096 bytes. When that
@@ -5782,26 +5900,26 @@ sparc_flat_output_function_prologue (file, size)
{
if (size <= 4096)
{
- fprintf (file, "\tadd %s,%d,%s\n",
+ fprintf (file, "\tadd\t%s, %d, %s\n",
sp_str, -size, sp_str);
if (gmask & FRAME_POINTER_MASK)
{
- fprintf (file, "\tst %s,[%s+%d]\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n",
fp_str, sp_str, reg_offset);
- fprintf (file, "\tsub %s,%d,%s\t%s# set up frame pointer\n",
+ fprintf (file, "\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
sp_str, -size, fp_str, ASM_COMMENT_START);
reg_offset += 4;
}
}
else
{
- fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
+ fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
size, t1_str, sp_str, t1_str, sp_str);
if (gmask & FRAME_POINTER_MASK)
{
- fprintf (file, "\tst %s,[%s+%d]\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n",
fp_str, sp_str, reg_offset);
- fprintf (file, "\tadd %s,%s,%s\t%s# set up frame pointer\n",
+ fprintf (file, "\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
sp_str, t1_str, fp_str, ASM_COMMENT_START);
reg_offset += 4;
}
@@ -5820,7 +5938,7 @@ sparc_flat_output_function_prologue (file, size)
}
if (gmask & RETURN_ADDR_MASK)
{
- fprintf (file, "\tst %s,[%s+%d]\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset);
if (dwarf2out_do_frame ())
dwarf2out_return_save ("", reg_offset - size);
@@ -5842,11 +5960,11 @@ sparc_flat_output_function_prologue (file, size)
if (size1 <= 4096)
{
- fprintf (file, "\tadd %s,%d,%s\n",
+ fprintf (file, "\tadd\t%s, %d, %s\n",
sp_str, -size1, sp_str);
if (gmask & FRAME_POINTER_MASK)
{
- fprintf (file, "\tst %s,[%s+%d]\n\tsub %s,%d,%s\t%s# set up frame pointer\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
fp_str, sp_str, offset, sp_str, -size1, fp_str,
ASM_COMMENT_START);
offset += 4;
@@ -5854,11 +5972,11 @@ sparc_flat_output_function_prologue (file, size)
}
else
{
- fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
+ fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
size1, t1_str, sp_str, t1_str, sp_str);
if (gmask & FRAME_POINTER_MASK)
{
- fprintf (file, "\tst %s,[%s+%d]\n\tadd %s,%s,%s\t%s# set up frame pointer\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
fp_str, sp_str, offset, sp_str, t1_str, fp_str,
ASM_COMMENT_START);
offset += 4;
@@ -5878,7 +5996,7 @@ sparc_flat_output_function_prologue (file, size)
}
if (gmask & RETURN_ADDR_MASK)
{
- fprintf (file, "\tst %s,[%s+%d]\n",
+ fprintf (file, "\tst\t%s, [%s+%d]\n",
reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
if (dwarf2out_do_frame ())
/* offset - size1 == reg_offset - size
@@ -5890,7 +6008,7 @@ sparc_flat_output_function_prologue (file, size)
gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
"st", "std", -size1);
- fprintf (file, "\tset %d,%s\n\tsub %s,%s,%s\n",
+ fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
size - size1, t1_str, sp_str, t1_str, sp_str);
if (dwarf2out_do_frame ())
if (! (gmask & FRAME_POINTER_MASK))
@@ -5943,22 +6061,22 @@ sparc_flat_output_function_epilogue (file, size)
unsigned int size1;
char *sp_str = reg_names[STACK_POINTER_REGNUM];
char *fp_str = reg_names[FRAME_POINTER_REGNUM];
- char *t1_str = "%g1";
+ const char *t1_str = "%g1";
/* In the reload sequence, we don't need to fill the load delay
slots for most of the loads, also see if we can fill the final
delay slot if not otherwise filled by the reload sequence. */
if (size > 4095)
- fprintf (file, "\tset %d,%s\n", size, t1_str);
+ fprintf (file, "\tset\t%d, %s\n", size, t1_str);
if (frame_pointer_needed)
{
if (size > 4095)
- fprintf (file,"\tsub %s,%s,%s\t\t%s# sp not trusted here\n",
+ fprintf (file,"\tsub\t%s, %s, %s\t\t%s# sp not trusted here\n",
fp_str, t1_str, sp_str, ASM_COMMENT_START);
else
- fprintf (file,"\tsub %s,%d,%s\t\t%s# sp not trusted here\n",
+ fprintf (file,"\tsub\t%s, %d, %s\t\t%s# sp not trusted here\n",
fp_str, size, sp_str, ASM_COMMENT_START);
}
@@ -5976,7 +6094,7 @@ sparc_flat_output_function_epilogue (file, size)
/* Offset to register save area from %sp. */
reg_offset = size1 - reg_offset;
- fprintf (file, "\tset %d,%s\n\tadd %s,%s,%s\n",
+ fprintf (file, "\tset\t%d, %s\n\tadd\t%s, %s, %s\n",
size1, t1_str, sp_str, t1_str, sp_str);
}
@@ -5984,13 +6102,13 @@ sparc_flat_output_function_epilogue (file, size)
because they are treated specially by the prologue output code. */
if (current_frame_info.gmask & FRAME_POINTER_MASK)
{
- fprintf (file, "\tld [%s+%d],%s\n",
+ fprintf (file, "\tld\t[%s+%d], %s\n",
sp_str, reg_offset, fp_str);
reg_offset += 4;
}
if (current_frame_info.gmask & RETURN_ADDR_MASK)
{
- fprintf (file, "\tld [%s+%d],%s\n",
+ fprintf (file, "\tld\t[%s+%d], %s\n",
sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]);
reg_offset += 4;
}
@@ -6007,12 +6125,12 @@ sparc_flat_output_function_epilogue (file, size)
{
size -= size1;
if (size > 4095)
- fprintf (file, "\tset %d,%s\n",
+ fprintf (file, "\tset\t%d, %s\n",
size, t1_str);
}
if (current_function_returns_struct)
- fprintf (file, "\tjmp %%o7+12\n");
+ fprintf (file, "\tjmp\t%%o7+12\n");
else
fprintf (file, "\tretl\n");
@@ -6029,10 +6147,10 @@ sparc_flat_output_function_epilogue (file, size)
}
else if (size > 4095)
- fprintf (file, "\tadd %s,%s,%s\n", sp_str, t1_str, sp_str);
+ fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
else if (size > 0)
- fprintf (file, "\tadd %s,%d,%s\n", sp_str, size, sp_str);
+ fprintf (file, "\tadd\t%s, %d, %s\n", sp_str, size, sp_str);
else
fprintf (file, "\tnop\n");
@@ -6040,6 +6158,8 @@ sparc_flat_output_function_epilogue (file, size)
/* Reset state info for each function. */
current_frame_info = zero_frame_info;
+
+ sparc_output_deferred_case_vectors ();
}
/* Define the number of delay slots needed for the function epilogue.
@@ -6089,7 +6209,7 @@ sparc_flat_eligible_for_epilogue_delay (trial, slot)
/* Adjust the cost of a scheduling dependency. Return the new cost of
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
-int
+static int
supersparc_adjust_cost (insn, link, dep_insn, cost)
rtx insn;
rtx link;
@@ -6109,8 +6229,8 @@ supersparc_adjust_cost (insn, link, dep_insn, cost)
cycles later. */
/* if a load, then the dependence must be on the memory address;
- add an extra 'cycle'. Note that the cost could be two cycles
- if the reg was written late in an instruction group; we can't tell
+ add an extra "cycle". Note that the cost could be two cycles
+ if the reg was written late in an instruction group; we ca not tell
here. */
if (insn_type == TYPE_LOAD || insn_type == TYPE_FPLOAD)
return cost + 3;
@@ -6122,7 +6242,7 @@ supersparc_adjust_cost (insn, link, dep_insn, cost)
rtx dep_pat = PATTERN (dep_insn);
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
- return cost; /* This shouldn't happen! */
+ return cost; /* This should not happen! */
/* The dependency between the two instructions was on the data that
is being stored. Assume that this implies that the address of the
@@ -6154,67 +6274,161 @@ supersparc_adjust_cost (insn, link, dep_insn, cost)
return cost;
}
-int
+static int
+hypersparc_adjust_cost (insn, link, dep_insn, cost)
+ rtx insn;
+ rtx link;
+ rtx dep_insn;
+ int cost;
+{
+ enum attr_type insn_type, dep_type;
+ rtx pat = PATTERN(insn);
+ rtx dep_pat = PATTERN (dep_insn);
+
+ if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
+ return cost;
+
+ insn_type = get_attr_type (insn);
+ dep_type = get_attr_type (dep_insn);
+
+ switch (REG_NOTE_KIND (link))
+ {
+ case 0:
+ /* Data dependency; DEP_INSN writes a register that INSN reads some
+ cycles later. */
+
+ switch (insn_type)
+ {
+ case TYPE_STORE:
+ case TYPE_FPSTORE:
+ /* Get the delay iff the address of the store is the dependence. */
+ if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
+ return cost;
+
+ if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
+ return cost;
+ return cost + 3;
+
+ case TYPE_LOAD:
+ case TYPE_SLOAD:
+ case TYPE_FPLOAD:
+ /* If a load, then the dependence must be on the memory address. If
+ the addresses aren't equal, then it might be a false dependency */
+ if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
+ {
+ if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
+ || GET_CODE (SET_DEST (dep_pat)) != MEM
+ || GET_CODE (SET_SRC (pat)) != MEM
+ || ! rtx_equal_p (XEXP (SET_DEST (dep_pat), 0),
+ XEXP (SET_SRC (pat), 0)))
+ return cost + 2;
+
+ return cost + 8;
+ }
+ break;
+
+ case TYPE_BRANCH:
+ /* Compare to branch latency is 0. There is no benefit from
+ separating compare and branch. */
+ if (dep_type == TYPE_COMPARE)
+ return 0;
+ /* Floating point compare to branch latency is less than
+ compare to conditional move. */
+ if (dep_type == TYPE_FPCMP)
+ return cost - 1;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case REG_DEP_ANTI:
+ /* Anti-dependencies only penalize the fpu unit. */
+ if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
+ return 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return cost;
+}
+
+static int
ultrasparc_adjust_cost (insn, link, dep_insn, cost)
- rtx insn;
- rtx link;
- rtx dep_insn;
- int cost;
+ rtx insn;
+ rtx link;
+ rtx dep_insn;
+ int cost;
{
enum attr_type insn_type, dep_type;
- rtx pat = PATTERN(insn);
- rtx dep_pat = PATTERN (dep_insn);
+ rtx pat = PATTERN(insn);
+ rtx dep_pat = PATTERN (dep_insn);
+
+ if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
+ return cost;
- if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
- return cost;
+ insn_type = get_attr_type (insn);
+ dep_type = get_attr_type (dep_insn);
- insn_type = get_attr_type (insn);
- dep_type = get_attr_type (dep_insn);
+ /* Nothing issues in parallel with integer multiplies, so
+ mark as zero cost since the scheduler can not do anything
+ about it. */
+ if (insn_type == TYPE_IMUL)
+ return 0;
#define SLOW_FP(dep_type) \
(dep_type == TYPE_FPSQRT || dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD)
switch (REG_NOTE_KIND (link))
- {
- case 0:
+ {
+ case 0:
/* Data dependency; DEP_INSN writes a register that INSN reads some
- cycles later. */
+ cycles later. */
+
+ if (dep_type == TYPE_CMOVE)
+ {
+ /* Instructions that read the result of conditional moves cannot
+ be in the same group or the following group. */
+ return cost + 1;
+ }
switch (insn_type)
- {
- /* UltraSPARC can dual issue a store and an instruction setting
- the value stored, except for divide and square root. */
+ {
+ /* UltraSPARC can dual issue a store and an instruction setting
+ the value stored, except for divide and square root. */
case TYPE_FPSTORE:
- if (! SLOW_FP (dep_type))
- return 0;
+ if (! SLOW_FP (dep_type))
+ return 0;
return cost;
- case TYPE_STORE:
+ case TYPE_STORE:
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
- return cost;
+ return cost;
if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
- /* The dependency between the two instructions is on the data
- that is being stored. Assume that the address of the store
- is not also dependent. */
- return 0;
- return cost;
-
- case TYPE_LOAD:
- case TYPE_SLOAD:
- case TYPE_FPLOAD:
- /* A load does not return data until at least 11 cycles after
+ /* The dependency between the two instructions is on the data
+ that is being stored. Assume that the address of the store
+ is not also dependent. */
+ return 0;
+ return cost;
+
+ case TYPE_LOAD:
+ case TYPE_SLOAD:
+ case TYPE_FPLOAD:
+ /* A load does not return data until at least 11 cycles after
a store to the same location. 3 cycles are accounted for
in the load latency; add the other 8 here. */
if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
- {
+ {
/* If the addresses are not equal this may be a false
dependency because pointer aliasing could not be
determined. Add only 2 cycles in that case. 2 is
an arbitrary compromise between 8, which would cause
the scheduler to generate worse code elsewhere to
- compensate for a dependency which might not really
- exist, and 0. */
+ compensate for a dependency which might not really
+ exist, and 0. */
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
|| GET_CODE (SET_SRC (pat)) != MEM
|| GET_CODE (SET_DEST (dep_pat)) != MEM
@@ -6222,72 +6436,831 @@ ultrasparc_adjust_cost (insn, link, dep_insn, cost)
XEXP (SET_DEST (dep_pat), 0)))
return cost + 2;
- return cost + 8;
- }
+ return cost + 8;
+ }
return cost;
- case TYPE_BRANCH:
+ case TYPE_BRANCH:
/* Compare to branch latency is 0. There is no benefit from
separating compare and branch. */
- if (dep_type == TYPE_COMPARE)
- return 0;
- /* Floating point compare to branch latency is less than
- compare to conditional move. */
- if (dep_type == TYPE_FPCMP)
- return cost - 1;
+ if (dep_type == TYPE_COMPARE)
+ return 0;
+ /* Floating point compare to branch latency is less than
+ compare to conditional move. */
+ if (dep_type == TYPE_FPCMP)
+ return cost - 1;
return cost;
- case TYPE_FPCMOVE:
+ case TYPE_FPCMOVE:
/* FMOVR class instructions can not issue in the same cycle
or the cycle after an instruction which writes any
integer register. Model this as cost 2 for dependent
- instructions. */
+ instructions. */
if ((dep_type == TYPE_IALU || dep_type == TYPE_UNARY
|| dep_type == TYPE_BINARY)
- && cost < 2)
+ && cost < 2)
return 2;
/* Otherwise check as for integer conditional moves. */
- case TYPE_CMOVE:
+ case TYPE_CMOVE:
/* Conditional moves involving integer registers wait until
3 cycles after loads return data. The interlock applies
to all loads, not just dependent loads, but that is hard
- to model. */
- if (dep_type == TYPE_LOAD || dep_type == TYPE_SLOAD)
- return cost + 3;
+ to model. */
+ if (dep_type == TYPE_LOAD || dep_type == TYPE_SLOAD)
+ return cost + 3;
return cost;
default:
break;
}
- break;
+ break;
- case REG_DEP_ANTI:
+ case REG_DEP_ANTI:
/* Divide and square root lock destination registers for full latency. */
- if (! SLOW_FP (dep_type))
- return 0;
- break;
+ if (! SLOW_FP (dep_type))
+ return 0;
+ break;
+
+ case REG_DEP_OUTPUT:
+ /* IEU and FPU instruction that have the same destination
+ register cannot be grouped together. */
+ return cost + 1;
default:
break;
}
- /* Other costs not accounted for:
- - Multiply should be modeled as having no latency because there is
- nothing the scheduler can do about it.
- - Single precision floating point loads lock the other half of
- the even/odd register pair.
+ /* Other costs not accounted for:
+ - Single precision floating point loads lock the other half of
+ the even/odd register pair.
- Several hazards associated with ldd/std are ignored because these
- instructions are rarely generated for V9.
- - A shift following an integer instruction which does not set the
- condition codes can not issue in the same cycle.
+ instructions are rarely generated for V9.
- The floating point pipeline can not have both a single and double
precision operation active at the same time. Format conversions
and graphics instructions are given honorary double precision status.
- call and jmpl are always the first instruction in a group. */
- return cost;
-}
+ return cost;
+
+#undef SLOW_FP
+}
+
+int
+sparc_adjust_cost(insn, link, dep, cost)
+ rtx insn;
+ rtx link;
+ rtx dep;
+ int cost;
+{
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_SUPERSPARC:
+ cost = supersparc_adjust_cost (insn, link, dep, cost);
+ break;
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ cost = hypersparc_adjust_cost (insn, link, dep, cost);
+ break;
+ case PROCESSOR_ULTRASPARC:
+ cost = ultrasparc_adjust_cost (insn, link, dep, cost);
+ break;
+ default:
+ break;
+ }
+ return cost;
+}
+
+/* This describes the state of the UltraSPARC pipeline during
+ instruction scheduling. */
+
+#define TMASK(__x) ((unsigned)1 << ((int)(__x)))
+#define UMASK(__x) ((unsigned)1 << ((int)(__x)))
+
+enum ultra_code { NONE=0, /* no insn at all */
+ IEU0, /* shifts and conditional moves */
+ IEU1, /* condition code setting insns, calls+jumps */
+ IEUN, /* all other single cycle ieu insns */
+ LSU, /* loads and stores */
+ CTI, /* branches */
+ FPM, /* FPU pipeline 1, multiplies and divides */
+ FPA, /* FPU pipeline 2, all other operations */
+ SINGLE, /* single issue instructions */
+ NUM_ULTRA_CODES };
+
+static const char *ultra_code_names[NUM_ULTRA_CODES] = {
+ "NONE", "IEU0", "IEU1", "IEUN", "LSU", "CTI",
+ "FPM", "FPA", "SINGLE" };
+
+struct ultrasparc_pipeline_state {
+ /* The insns in this group. */
+ rtx group[4];
+
+ /* The code for each insn. */
+ enum ultra_code codes[4];
+
+ /* Which insns in this group have been committed by the
+ scheduler. This is how we determine how many more
+ can issue this cycle. */
+ char commit[4];
+
+ /* How many insns in this group. */
+ char group_size;
+
+ /* Mask of free slots still in this group. */
+ char free_slot_mask;
+
+ /* The slotter uses the following to determine what other
+ insn types can still make their way into this group. */
+ char contents [NUM_ULTRA_CODES];
+ char num_ieu_insns;
+};
+
+#define ULTRA_NUM_HIST 8
+static struct ultrasparc_pipeline_state ultra_pipe_hist[ULTRA_NUM_HIST];
+static int ultra_cur_hist;
+static int ultra_cycles_elapsed;
+
+#define ultra_pipe (ultra_pipe_hist[ultra_cur_hist])
+
+/* Given TYPE_MASK compute the ultra_code it has. */
+static enum ultra_code
+ultra_code_from_mask (type_mask)
+ int type_mask;
+{
+ if (type_mask & (TMASK (TYPE_SHIFT) | TMASK (TYPE_CMOVE)))
+ return IEU0;
+ else if (type_mask & (TMASK (TYPE_COMPARE) |
+ TMASK (TYPE_CALL) |
+ TMASK (TYPE_UNCOND_BRANCH)))
+ return IEU1;
+ else if (type_mask & (TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
+ TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY)))
+ return IEUN;
+ else if (type_mask & (TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
+ TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
+ TMASK (TYPE_FPSTORE)))
+ return LSU;
+ else if (type_mask & (TMASK (TYPE_FPMUL) | TMASK (TYPE_FPDIVS) |
+ TMASK (TYPE_FPDIVD) | TMASK (TYPE_FPSQRT)))
+ return FPM;
+ else if (type_mask & (TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPCMOVE) |
+ TMASK (TYPE_FP) | TMASK (TYPE_FPCMP)))
+ return FPA;
+ else if (type_mask & TMASK (TYPE_BRANCH))
+ return CTI;
+
+ return SINGLE;
+}
+
+/* Check INSN (a conditional move) and make sure that it's
+ results are available at this cycle. Return 1 if the
+ results are in fact ready. */
+static int
+ultra_cmove_results_ready_p (insn)
+ rtx insn;
+{
+ struct ultrasparc_pipeline_state *up;
+ int entry, slot;
+
+ /* If this got dispatched in the previous
+ group, the results are not ready. */
+ entry = (ultra_cur_hist - 1) % (ULTRA_NUM_HIST - 1);
+ up = &ultra_pipe_hist[entry];
+ slot = 4;
+ while (--slot >= 0)
+ if (up->group[slot] == insn)
+ return 0;
+
+ return 1;
+}
+
+/* Walk backwards in pipeline history looking for FPU
+ operations which use a mode different than FPMODE and
+ will create a stall if an insn using FPMODE were to be
+ dispatched this cycle. */
+static int
+ultra_fpmode_conflict_exists (fpmode)
+ enum machine_mode fpmode;
+{
+ int hist_ent;
+ int hist_lim;
+
+ hist_ent = (ultra_cur_hist - 1) % (ULTRA_NUM_HIST - 1);
+ if (ultra_cycles_elapsed < 4)
+ hist_lim = ultra_cycles_elapsed;
+ else
+ hist_lim = 4;
+ while (hist_lim > 0)
+ {
+ struct ultrasparc_pipeline_state *up = &ultra_pipe_hist[hist_ent];
+ int slot = 4;
+
+ while (--slot >= 0)
+ {
+ rtx insn = up->group[slot];
+ enum machine_mode this_mode;
+ rtx pat;
+
+ if (! insn
+ || GET_CODE (insn) != INSN
+ || (pat = PATTERN (insn)) == 0
+ || GET_CODE (pat) != SET)
+ continue;
+
+ this_mode = GET_MODE (SET_DEST (pat));
+ if ((this_mode != SFmode
+ && this_mode != DFmode)
+ || this_mode == fpmode)
+ continue;
+
+ /* If it is not FMOV, FABS, FNEG, FDIV, or FSQRT then
+ we will get a stall. Loads and stores are independant
+ of these rules. */
+ if (GET_CODE (SET_SRC (pat)) != ABS
+ && GET_CODE (SET_SRC (pat)) != NEG
+ && ((TMASK (get_attr_type (insn)) &
+ (TMASK (TYPE_FPDIVS) | TMASK (TYPE_FPDIVD) |
+ TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPSQRT) |
+ TMASK (TYPE_LOAD) | TMASK (TYPE_STORE))) == 0))
+ return 1;
+ }
+ hist_lim--;
+ hist_ent = (hist_ent - 1) % (ULTRA_NUM_HIST - 1);
+ }
+
+ /* No conflicts, safe to dispatch. */
+ return 0;
+}
+
+/* Find an instruction in LIST which has one of the
+ type attributes enumerated in TYPE_MASK. START
+ says where to begin the search.
+
+ NOTE: This scheme depends upon the fact that we
+ have less than 32 distinct type attributes. */
+
+static int ultra_types_avail;
+
+static rtx *
+ultra_find_type (type_mask, list, start)
+ int type_mask;
+ rtx *list;
+ int start;
+{
+ int i;
+
+ /* Short circuit if no such insn exists in the ready
+ at the moment. */
+ if ((type_mask & ultra_types_avail) == 0)
+ return 0;
+
+ for (i = start; i >= 0; i--)
+ {
+ rtx insn = list[i];
+
+ if (recog_memoized (insn) >= 0
+ && (TMASK(get_attr_type (insn)) & type_mask))
+ {
+ enum machine_mode fpmode = SFmode;
+ rtx pat = 0;
+ int slot;
+ int check_depend = 0;
+ int check_fpmode_conflict = 0;
+
+ if (GET_CODE (insn) == INSN
+ && (pat = PATTERN(insn)) != 0
+ && GET_CODE (pat) == SET
+ && !(type_mask & (TMASK (TYPE_STORE) |
+ TMASK (TYPE_FPSTORE))))
+ {
+ check_depend = 1;
+ if (GET_MODE (SET_DEST (pat)) == SFmode
+ || GET_MODE (SET_DEST (pat)) == DFmode)
+ {
+ fpmode = GET_MODE (SET_DEST (pat));
+ check_fpmode_conflict = 1;
+ }
+ }
+
+ slot = 4;
+ while(--slot >= 0)
+ {
+ rtx slot_insn = ultra_pipe.group[slot];
+ rtx slot_pat;
+
+ /* Already issued, bad dependency, or FPU
+ mode conflict. */
+ if (slot_insn != 0
+ && (slot_pat = PATTERN (slot_insn)) != 0
+ && ((insn == slot_insn)
+ || (check_depend == 1
+ && GET_CODE (slot_insn) == INSN
+ && GET_CODE (slot_pat) == SET
+ && ((GET_CODE (SET_DEST (slot_pat)) == REG
+ && GET_CODE (SET_SRC (pat)) == REG
+ && REGNO (SET_DEST (slot_pat)) ==
+ REGNO (SET_SRC (pat)))
+ || (GET_CODE (SET_DEST (slot_pat)) == SUBREG
+ && GET_CODE (SET_SRC (pat)) == SUBREG
+ && REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
+ REGNO (SUBREG_REG (SET_SRC (pat)))
+ && SUBREG_WORD (SET_DEST (slot_pat)) ==
+ SUBREG_WORD (SET_SRC (pat)))))
+ || (check_fpmode_conflict == 1
+ && GET_CODE (slot_insn) == INSN
+ && GET_CODE (slot_pat) == SET
+ && (GET_MODE (SET_DEST (slot_pat)) == SFmode
+ || GET_MODE (SET_DEST (slot_pat)) == DFmode)
+ && GET_MODE (SET_DEST (slot_pat)) != fpmode)))
+ goto next;
+ }
+
+ /* Check for peculiar result availability and dispatch
+ interference situations. */
+ if (pat != 0
+ && ultra_cycles_elapsed > 0)
+ {
+ rtx link;
+
+ for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
+ {
+ rtx link_insn = XEXP (link, 0);
+ if (GET_CODE (link_insn) == INSN
+ && recog_memoized (link_insn) >= 0
+ && (TMASK (get_attr_type (link_insn)) &
+ (TMASK (TYPE_CMOVE) | TMASK (TYPE_FPCMOVE)))
+ && ! ultra_cmove_results_ready_p (link_insn))
+ goto next;
+ }
+
+ if (check_fpmode_conflict
+ && ultra_fpmode_conflict_exists (fpmode))
+ goto next;
+ }
+
+ return &list[i];
+ }
+ next:
+ ;
+ }
+ return 0;
+}
+
+static void
+ultra_build_types_avail (ready, n_ready)
+ rtx *ready;
+ int n_ready;
+{
+ int i = n_ready - 1;
+
+ ultra_types_avail = 0;
+ while(i >= 0)
+ {
+ rtx insn = ready[i];
+
+ if (recog_memoized (insn) >= 0)
+ ultra_types_avail |= TMASK (get_attr_type (insn));
+
+ i -= 1;
+ }
+}
+
+/* Place insn pointed to my IP into the pipeline.
+ Make element THIS of READY be that insn if it
+ is not already. TYPE indicates the pipeline class
+ this insn falls into. */
+static void
+ultra_schedule_insn (ip, ready, this, type)
+ rtx *ip;
+ rtx *ready;
+ int this;
+ enum ultra_code type;
+{
+ int pipe_slot;
+ char mask = ultra_pipe.free_slot_mask;
+
+ /* Obtain free slot. */
+ for (pipe_slot = 0; pipe_slot < 4; pipe_slot++)
+ if ((mask & (1 << pipe_slot)) != 0)
+ break;
+ if (pipe_slot == 4)
+ abort ();
+
+ /* In it goes, and it hasn't been committed yet. */
+ ultra_pipe.group[pipe_slot] = *ip;
+ ultra_pipe.codes[pipe_slot] = type;
+ ultra_pipe.contents[type] = 1;
+ if (UMASK (type) &
+ (UMASK (IEUN) | UMASK (IEU0) | UMASK (IEU1)))
+ ultra_pipe.num_ieu_insns += 1;
+
+ ultra_pipe.free_slot_mask = (mask & ~(1 << pipe_slot));
+ ultra_pipe.group_size += 1;
+ ultra_pipe.commit[pipe_slot] = 0;
+
+ /* Update ready list. */
+ if (ip != &ready[this])
+ {
+ rtx temp = *ip;
+
+ *ip = ready[this];
+ ready[this] = temp;
+ }
+}
+
+/* Advance to the next pipeline group. */
+static void
+ultra_flush_pipeline ()
+{
+ ultra_cur_hist = (ultra_cur_hist + 1) % (ULTRA_NUM_HIST - 1);
+ ultra_cycles_elapsed += 1;
+ bzero ((char *) &ultra_pipe, sizeof ultra_pipe);
+ ultra_pipe.free_slot_mask = 0xf;
+}
+
+static int ultra_reorder_called_this_block;
+
+/* Init our data structures for this current block. */
+void
+ultrasparc_sched_init (dump, sched_verbose)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int sched_verbose ATTRIBUTE_UNUSED;
+{
+ bzero ((char *) ultra_pipe_hist, sizeof ultra_pipe_hist);
+ ultra_cur_hist = 0;
+ ultra_cycles_elapsed = 0;
+ ultra_reorder_called_this_block = 0;
+ ultra_pipe.free_slot_mask = 0xf;
+}
+
+/* INSN has been scheduled, update pipeline commit state
+ and return how many instructions are still to be
+ scheduled in this group. */
+int
+ultrasparc_variable_issue (insn)
+ rtx insn;
+{
+ struct ultrasparc_pipeline_state *up = &ultra_pipe;
+ int i, left_to_fire;
+
+ left_to_fire = 0;
+ for (i = 0; i < 4; i++)
+ {
+ if (up->group[i] == 0)
+ continue;
+
+ if (up->group[i] == insn)
+ {
+ up->commit[i] = 1;
+ }
+ else if (! up->commit[i])
+ left_to_fire++;
+ }
+
+ return left_to_fire;
+}
+
+/* In actual_hazard_this_instance, we may have yanked some
+ instructions from the ready list due to conflict cost
+ adjustments. If so, and such an insn was in our pipeline
+ group, remove it and update state. */
+static void
+ultra_rescan_pipeline_state (ready, n_ready)
+ rtx *ready;
+ int n_ready;
+{
+ struct ultrasparc_pipeline_state *up = &ultra_pipe;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ rtx insn = up->group[i];
+ int j;
+
+ if (! insn)
+ continue;
+
+ /* If it has been committed, then it was removed from
+ the ready list because it was actually scheduled,
+ and that is not the case we are searching for here. */
+ if (up->commit[i] != 0)
+ continue;
+
+ for (j = n_ready - 1; j >= 0; j--)
+ if (ready[j] == insn)
+ break;
+
+ /* If we didn't find it, toss it. */
+ if (j < 0)
+ {
+ enum ultra_code ucode = up->codes[i];
+
+ up->group[i] = 0;
+ up->codes[i] = NONE;
+ up->contents[ucode] = 0;
+ if (UMASK (ucode) &
+ (UMASK (IEUN) | UMASK (IEU0) | UMASK (IEU1)))
+ up->num_ieu_insns -= 1;
+
+ up->free_slot_mask |= (1 << i);
+ up->group_size -= 1;
+ up->commit[i] = 0;
+ }
+ }
+}
+
+void
+ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
+ FILE *dump;
+ int sched_verbose;
+ rtx *ready;
+ int n_ready;
+{
+ struct ultrasparc_pipeline_state *up = &ultra_pipe;
+ int i, this_insn;
+
+ /* We get called once unnecessarily per block of insns
+ scheduled. */
+ if (ultra_reorder_called_this_block == 0)
+ {
+ ultra_reorder_called_this_block = 1;
+ return;
+ }
+
+ if (sched_verbose)
+ {
+ int n;
+
+ fprintf (dump, "\n;;\tUltraSPARC Looking at [");
+ for (n = n_ready - 1; n >= 0; n--)
+ {
+ rtx insn = ready[n];
+ enum ultra_code ucode;
+
+ if (recog_memoized (insn) < 0)
+ continue;
+ ucode = ultra_code_from_mask (TMASK (get_attr_type (insn)));
+ if (n != 0)
+ fprintf (dump, "%s(%d) ",
+ ultra_code_names[ucode],
+ INSN_UID (insn));
+ else
+ fprintf (dump, "%s(%d)",
+ ultra_code_names[ucode],
+ INSN_UID (insn));
+ }
+ fprintf (dump, "]\n");
+ }
+
+ this_insn = n_ready - 1;
+
+ /* Skip over junk we don't understand. */
+ while ((this_insn >= 0)
+ && recog_memoized (ready[this_insn]) < 0)
+ this_insn--;
+
+ ultra_build_types_avail (ready, this_insn + 1);
+
+ while (this_insn >= 0) {
+ int old_group_size = up->group_size;
+
+ if (up->group_size != 0)
+ {
+ int num_committed;
+
+ num_committed = (up->commit[0] + up->commit[1] +
+ up->commit[2] + up->commit[3]);
+ /* If nothing has been commited from our group, or all of
+ them have. Clear out the (current cycle's) pipeline
+ state and start afresh. */
+ if (num_committed == 0
+ || num_committed == up->group_size)
+ {
+ ultra_flush_pipeline ();
+ up = &ultra_pipe;
+ old_group_size = 0;
+ }
+ else
+ {
+ /* OK, some ready list insns got requeued and thus removed
+ from the ready list. Account for this fact. */
+ ultra_rescan_pipeline_state (ready, n_ready);
+
+ /* Something "changed", make this look like a newly
+ formed group so the code at the end of the loop
+ knows that progress was in fact made. */
+ if (up->group_size != old_group_size)
+ old_group_size = 0;
+ }
+ }
+
+ if (up->group_size == 0)
+ {
+ /* If the pipeline is (still) empty and we have any single
+ group insns, get them out now as this is a good time. */
+ rtx *ip = ultra_find_type ((TMASK (TYPE_RETURN) | TMASK (TYPE_ADDRESS) |
+ TMASK (TYPE_IMUL) | TMASK (TYPE_CMOVE) |
+ TMASK (TYPE_MULTI) | TMASK (TYPE_MISC)),
+ ready, this_insn);
+ if (ip)
+ {
+ ultra_schedule_insn (ip, ready, this_insn, SINGLE);
+ break;
+ }
+
+ /* If we are not in the process of emptying out the pipe, try to
+ obtain an instruction which must be the first in it's group. */
+ ip = ultra_find_type ((TMASK (TYPE_CALL) |
+ TMASK (TYPE_CALL_NO_DELAY_SLOT) |
+ TMASK (TYPE_UNCOND_BRANCH)),
+ ready, this_insn);
+ if (ip)
+ {
+ ultra_schedule_insn (ip, ready, this_insn, IEU1);
+ this_insn--;
+ }
+ else if ((ip = ultra_find_type ((TMASK (TYPE_FPDIVS) |
+ TMASK (TYPE_FPDIVD) |
+ TMASK (TYPE_FPSQRT)),
+ ready, this_insn)) != 0)
+ {
+ ultra_schedule_insn (ip, ready, this_insn, FPM);
+ this_insn--;
+ }
+ }
+
+ /* Try to fill the integer pipeline. First, look for an IEU0 specific
+ operation. We can't do more IEU operations if the first 3 slots are
+ all full or we have dispatched two IEU insns already. */
+ if ((up->free_slot_mask & 0x7) != 0
+ && up->num_ieu_insns < 2
+ && up->contents[IEU0] == 0
+ && up->contents[IEUN] == 0)
+ {
+ rtx *ip = ultra_find_type (TMASK(TYPE_SHIFT), ready, this_insn);
+ if (ip)
+ {
+ ultra_schedule_insn (ip, ready, this_insn, IEU0);
+ this_insn--;
+ }
+ }
+
+ /* If we can, try to find an IEU1 specific or an unnamed
+ IEU instruction. */
+ if ((up->free_slot_mask & 0x7) != 0
+ && up->num_ieu_insns < 2)
+ {
+ rtx *ip = ultra_find_type ((TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
+ TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY) |
+ (up->contents[IEU1] == 0 ? TMASK (TYPE_COMPARE) : 0)),
+ ready, this_insn);
+ if (ip)
+ {
+ rtx insn = *ip;
+
+ ultra_schedule_insn (ip, ready, this_insn,
+ (!up->contents[IEU1]
+ && get_attr_type (insn) == TYPE_COMPARE)
+ ? IEU1 : IEUN);
+ this_insn--;
+ }
+ }
+
+ /* If only one IEU insn has been found, try to find another unnamed
+ IEU operation or an IEU1 specific one. */
+ if ((up->free_slot_mask & 0x7) != 0
+ && up->num_ieu_insns < 2)
+ {
+ rtx *ip;
+ int tmask = (TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
+ TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY));
+
+ if (!up->contents[IEU1])
+ tmask |= TMASK (TYPE_COMPARE);
+ ip = ultra_find_type (tmask, ready, this_insn);
+ if (ip)
+ {
+ rtx insn = *ip;
+
+ ultra_schedule_insn (ip, ready, this_insn,
+ (!up->contents[IEU1]
+ && get_attr_type (insn) == TYPE_COMPARE)
+ ? IEU1 : IEUN);
+ this_insn--;
+ }
+ }
+
+ /* Try for a load or store, but such an insn can only be issued
+ if it is within' one of the first 3 slots. */
+ if ((up->free_slot_mask & 0x7) != 0
+ && up->contents[LSU] == 0)
+ {
+ rtx *ip = ultra_find_type ((TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
+ TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
+ TMASK (TYPE_FPSTORE)), ready, this_insn);
+ if (ip)
+ {
+ ultra_schedule_insn (ip, ready, this_insn, LSU);
+ this_insn--;
+ }
+ }
+
+ /* Now find FPU operations, first FPM class. But not divisions or
+ square-roots because those will break the group up. Unlike all
+ the previous types, these can go in any slot. */
+ if (up->free_slot_mask != 0
+ && up->contents[FPM] == 0)
+ {
+ rtx *ip = ultra_find_type (TMASK (TYPE_FPMUL), ready, this_insn);
+ if (ip)
+ {
+ ultra_schedule_insn (ip, ready, this_insn, FPM);
+ this_insn--;
+ }
+ }
+
+ /* Continue on with FPA class if we have not filled the group already. */
+ if (up->free_slot_mask != 0
+ && up->contents[FPA] == 0)
+ {
+ rtx *ip = ultra_find_type ((TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPCMOVE) |
+ TMASK (TYPE_FP) | TMASK (TYPE_FPCMP)),
+ ready, this_insn);
+ if (ip)
+ {
+ ultra_schedule_insn (ip, ready, this_insn, FPA);
+ this_insn--;
+ }
+ }
+
+ /* Finally, maybe stick a branch in here. */
+ if (up->free_slot_mask != 0
+ && up->contents[CTI] == 0)
+ {
+ rtx *ip = ultra_find_type (TMASK (TYPE_BRANCH), ready, this_insn);
+
+ /* Try to slip in a branch only if it is one of the
+ next 2 in the ready list. */
+ if (ip && ((&ready[this_insn] - ip) < 2))
+ {
+ ultra_schedule_insn (ip, ready, this_insn, CTI);
+ this_insn--;
+ }
+ }
+
+ up->group_size = 0;
+ for (i = 0; i < 4; i++)
+ if ((up->free_slot_mask & (1 << i)) == 0)
+ up->group_size++;
+
+ /* See if we made any progress... */
+ if (old_group_size != up->group_size)
+ break;
+
+ /* Clean out the (current cycle's) pipeline state
+ and try once more. If we placed no instructions
+ into the pipeline at all, it means a real hard
+ conflict exists with some earlier issued instruction
+ so we must advance to the next cycle to clear it up. */
+ if (up->group_size == 0)
+ {
+ ultra_flush_pipeline ();
+ up = &ultra_pipe;
+ }
+ else
+ {
+ bzero ((char *) &ultra_pipe, sizeof ultra_pipe);
+ ultra_pipe.free_slot_mask = 0xf;
+ }
+ }
+
+ if (sched_verbose)
+ {
+ int n, gsize;
+
+ fprintf (dump, ";;\tUltraSPARC Launched [");
+ gsize = up->group_size;
+ for (n = 0; n < 4; n++)
+ {
+ rtx insn = up->group[n];
+
+ if (! insn)
+ continue;
+
+ gsize -= 1;
+ if (gsize != 0)
+ fprintf (dump, "%s(%d) ",
+ ultra_code_names[up->codes[n]],
+ INSN_UID (insn));
+ else
+ fprintf (dump, "%s(%d)",
+ ultra_code_names[up->codes[n]],
+ INSN_UID (insn));
+ }
+ fprintf (dump, "]\n");
+ }
+}
int
sparc_issue_rate ()
@@ -6301,6 +7274,9 @@ sparc_issue_rate ()
return 2;
case PROCESSOR_SUPERSPARC:
return 3;
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ return 2;
case PROCESSOR_ULTRASPARC:
return 4;
}
@@ -6322,8 +7298,6 @@ set_extends(x, insn)
/* LO_SUM is used with sethi. sethi cleared the high
bits and the values used with lo_sum are positive */
case LO_SUM:
- /* UNSPEC is v8plus_clear_high */
- case UNSPEC:
/* Store flag stores 0 or 1 */
case LT: case LTU:
case GT: case GTU:
@@ -6360,6 +7334,110 @@ set_extends(x, insn)
}
}
+/* We _ought_ to have only one kind per function, but... */
+static rtx sparc_addr_diff_list;
+static rtx sparc_addr_list;
+
+void
+sparc_defer_case_vector (lab, vec, diff)
+ rtx lab, vec;
+ int diff;
+{
+ vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
+ if (diff)
+ sparc_addr_diff_list
+ = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_diff_list);
+ else
+ sparc_addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_list);
+}
+
+static void
+sparc_output_addr_vec (vec)
+ rtx vec;
+{
+ rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
+ int idx, vlen = XVECLEN (body, 0);
+
+#ifdef ASM_OUTPUT_ADDR_VEC_START
+ ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
+#endif
+
+#ifdef ASM_OUTPUT_CASE_LABEL
+ ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
+ NEXT_INSN (lab));
+#else
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
+#endif
+
+ for (idx = 0; idx < vlen; idx++)
+ {
+ ASM_OUTPUT_ADDR_VEC_ELT
+ (asm_out_file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
+ }
+
+#ifdef ASM_OUTPUT_ADDR_VEC_END
+ ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
+#endif
+}
+
+static void
+sparc_output_addr_diff_vec (vec)
+ rtx vec;
+{
+ rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
+ rtx base = XEXP (XEXP (body, 0), 0);
+ int idx, vlen = XVECLEN (body, 1);
+
+#ifdef ASM_OUTPUT_ADDR_VEC_START
+ ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
+#endif
+
+#ifdef ASM_OUTPUT_CASE_LABEL
+ ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
+ NEXT_INSN (lab));
+#else
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
+#endif
+
+ for (idx = 0; idx < vlen; idx++)
+ {
+ ASM_OUTPUT_ADDR_DIFF_ELT
+ (asm_out_file,
+ body,
+ CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
+ CODE_LABEL_NUMBER (base));
+ }
+
+#ifdef ASM_OUTPUT_ADDR_VEC_END
+ ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
+#endif
+}
+
+static void
+sparc_output_deferred_case_vectors ()
+{
+ rtx t;
+ int align;
+
+ if (sparc_addr_list == NULL_RTX
+ && sparc_addr_diff_list == NULL_RTX)
+ return;
+
+ /* Align to cache line in the function's code section. */
+ function_section (current_function_decl);
+
+ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ if (align > 0)
+ ASM_OUTPUT_ALIGN (asm_out_file, align);
+
+ for (t = sparc_addr_list; t ; t = XEXP (t, 1))
+ sparc_output_addr_vec (XEXP (t, 0));
+ for (t = sparc_addr_diff_list; t ; t = XEXP (t, 1))
+ sparc_output_addr_diff_vec (XEXP (t, 0));
+
+ sparc_addr_list = sparc_addr_diff_list = NULL_RTX;
+}
+
/* Return 0 if the high 32 bits of X (the low word of X, if DImode) are
unknown. Return 1 if the high bits are zero, -1 if the register is
sign extended. */
@@ -6452,10 +7530,314 @@ sparc_return_peephole_ok (dest, src)
{
if (! TARGET_V9)
return 0;
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
return 0;
if (GET_CODE (src) != CONST_INT
&& (GET_CODE (src) != REG || ! IN_OR_GLOBAL_P (src)))
return 0;
return IN_OR_GLOBAL_P (dest);
}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry.
+
+ 32 bit sparc uses %g2 as the STATIC_CHAIN_REGNUM which gets clobbered
+ during profiling so we need to save/restore it around the call to mcount.
+ We're guaranteed that a save has just been done, and we use the space
+ allocated for intreg/fpreg value passing. */
+
+void
+sparc_function_profiler (file, labelno)
+ FILE *file;
+ int labelno;
+{
+ char buf[32];
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
+
+ if (! TARGET_ARCH64)
+ fputs ("\tst\t%g2,[%fp-4]\n", file);
+
+ fputs ("\tsethi\t%hi(", file);
+ assemble_name (file, buf);
+ fputs ("),%o0\n", file);
+
+ fputs ("\tcall\t", file);
+ assemble_name (file, MCOUNT_FUNCTION);
+ putc ('\n', file);
+
+ fputs ("\t or\t%o0,%lo(", file);
+ assemble_name (file, buf);
+ fputs ("),%o0\n", file);
+
+ if (! TARGET_ARCH64)
+ fputs ("\tld\t[%fp-4],%g2\n", file);
+}
+
+
+/* The following macro shall output assembler code to FILE
+ to initialize basic-block profiling.
+
+ If profile_block_flag == 2
+
+ Output code to call the subroutine `__bb_init_trace_func'
+ and pass two parameters to it. The first parameter is
+ the address of a block allocated in the object module.
+ The second parameter is the number of the first basic block
+ of the function.
+
+ 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 number of the first basic block of the function is
+ passed to the macro in BLOCK_OR_LABEL.
+
+ If described in a virtual assembler language the code to be
+ output looks like:
+
+ parameter1 <- LPBX0
+ parameter2 <- BLOCK_OR_LABEL
+ call __bb_init_trace_func
+
+ else if profile_block_flag != 0
+
+ Output code to call the subroutine `__bb_init_func'
+ and pass one single parameter to it, which is the same
+ as the first parameter to `__bb_init_trace_func'.
+
+ The first word of this parameter 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.
+ Note: When profile_block_flag == 2 the test need not be done
+ but `__bb_init_trace_func' *must* be called.
+
+ BLOCK_OR_LABEL may be used to generate a label number as a
+ branch destination in case `__bb_init_func' will not be called.
+
+ If described in a virtual assembler language the code to be
+ output looks like:
+
+ cmp (LPBX0),0
+ jne local_label
+ parameter1 <- LPBX0
+ call __bb_init_func
+ local_label:
+
+*/
+
+void
+sparc_function_block_profiler(file, block_or_label)
+ FILE *file;
+ int block_or_label;
+{
+ char LPBX[32];
+ ASM_GENERATE_INTERNAL_LABEL (LPBX, "LPBX", 0);
+
+ if (profile_block_flag == 2)
+ {
+ fputs ("\tsethi\t%hi(", file);
+ assemble_name (file, LPBX);
+ fputs ("),%o0\n", file);
+
+ fprintf (file, "\tsethi\t%%hi(%d),%%o1\n", block_or_label);
+
+ fputs ("\tor\t%o0,%lo(", file);
+ assemble_name (file, LPBX);
+ fputs ("),%o0\n", file);
+
+ fprintf (file, "\tcall\t%s__bb_init_trace_func\n", user_label_prefix);
+
+ fprintf (file, "\t or\t%%o1,%%lo(%d),%%o1\n", block_or_label);
+ }
+ else if (profile_block_flag != 0)
+ {
+ char LPBY[32];
+ ASM_GENERATE_INTERNAL_LABEL (LPBY, "LPBY", block_or_label);
+
+ fputs ("\tsethi\t%hi(", file);
+ assemble_name (file, LPBX);
+ fputs ("),%o0\n", file);
+
+ fputs ("\tld\t[%lo(", file);
+ assemble_name (file, LPBX);
+ fputs (")+%o0],%o1\n", file);
+
+ fputs ("\ttst\t%o1\n", file);
+
+ if (TARGET_V9)
+ {
+ fputs ("\tbne,pn\t%icc,", file);
+ assemble_name (file, LPBY);
+ putc ('\n', file);
+ }
+ else
+ {
+ fputs ("\tbne\t", file);
+ assemble_name (file, LPBY);
+ putc ('\n', file);
+ }
+
+ fputs ("\t or\t%o0,%lo(", file);
+ assemble_name (file, LPBX);
+ fputs ("),%o0\n", file);
+
+ fprintf (file, "\tcall\t%s__bb_init_func\n\t nop\n", user_label_prefix);
+
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LPBY", block_or_label);
+ }
+}
+
+/* The following macro shall output assembler code to FILE
+ to increment a counter associated with basic block number BLOCKNO.
+
+ If profile_block_flag == 2
+
+ Output code to initialize the global structure `__bb' and
+ call the function `__bb_trace_func' which will increment the
+ counter.
+
+ `__bb' consists of two words. In the first word the number
+ of the basic block has to be stored. In the second word
+ the address of a block allocated in the object module
+ has to be stored.
+
+ The basic block number is given by BLOCKNO.
+
+ The address of the block is given by the label created with
+
+ ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
+
+ by FUNCTION_BLOCK_PROFILER.
+
+ 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.
+
+ If described in a virtual assembler language the code to be
+ output looks like:
+
+ move BLOCKNO -> (__bb)
+ move LPBX0 -> (__bb+4)
+ call __bb_trace_func
+
+ Note that function `__bb_trace_func' must not change the
+ machine state, especially the flag register. To grant
+ this, you must output code to save and restore registers
+ either in this macro or in the macros MACHINE_STATE_SAVE
+ and MACHINE_STATE_RESTORE. The last two macros will be
+ used in the function `__bb_trace_func', so you must make
+ sure that the function prologue does not change any
+ register prior to saving it with MACHINE_STATE_SAVE.
+
+ else if profile_block_flag != 0
+
+ Output code to increment the counter directly.
+ Basic blocks are numbered separately from zero within each
+ compiled object module. The count associated with block number
+ BLOCKNO is at index BLOCKNO in an array 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.
+
+ If described in a virtual assembler language, the code to be
+ output looks like:
+
+ inc (LPBX2+4*BLOCKNO)
+
+*/
+
+void
+sparc_block_profiler(file, blockno)
+ FILE *file;
+ int blockno;
+{
+ char LPBX[32];
+
+ if (profile_block_flag == 2)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (LPBX, "LPBX", 0);
+
+ fprintf (file, "\tsethi\t%%hi(%s__bb),%%g1\n", user_label_prefix);
+ fprintf (file, "\tsethi\t%%hi(%d),%%g2\n", blockno);
+ fprintf (file, "\tor\t%%g1,%%lo(%s__bb),%%g1\n", user_label_prefix);
+ fprintf (file, "\tor\t%%g2,%%lo(%d),%%g2\n", blockno);
+
+ fputs ("\tst\t%g2,[%g1]\n", file);
+
+ fputs ("\tsethi\t%hi(", file);
+ assemble_name (file, LPBX);
+ fputs ("),%g2\n", file);
+
+ fputs ("\tor\t%o2,%lo(", file);
+ assemble_name (file, LPBX);
+ fputs ("),%g2\n", file);
+
+ fputs ("\tst\t%g2,[%g1+4]\n", file);
+ fputs ("\tmov\t%o7,%g2\n", file);
+
+ fprintf (file, "\tcall\t%s__bb_trace_func\n\t nop\n", user_label_prefix);
+
+ fputs ("\tmov\t%g2,%o7\n", file);
+ }
+ else if (profile_block_flag != 0)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (LPBX, "LPBX", 2);
+
+ fputs ("\tsethi\t%hi(", file);
+ assemble_name (file, LPBX);
+ fprintf (file, "+%d),%%g1\n", blockno*4);
+
+ fputs ("\tld\t[%g1+%lo(", file);
+ assemble_name (file, LPBX);
+ fprintf (file, "+%d)],%%g2\n", blockno*4);
+
+ fputs ("\tadd\t%g2,1,%g2\n", file);
+
+ fputs ("\tst\t%g2,[%g1+%lo(", file);
+ assemble_name (file, LPBX);
+ fprintf (file, "+%d)]\n", blockno*4);
+ }
+}
+
+/* The following macro shall output assembler code to FILE
+ to indicate a return from function during basic-block profiling.
+
+ If profile_block_flag == 2:
+
+ Output assembler code to call function `__bb_trace_ret'.
+
+ Note that function `__bb_trace_ret' must not change the
+ machine state, especially the flag register. To grant
+ this, you must output code to save and restore registers
+ either in this macro or in the macros MACHINE_STATE_SAVE_RET
+ and MACHINE_STATE_RESTORE_RET. The last two macros will be
+ used in the function `__bb_trace_ret', so you must make
+ sure that the function prologue does not change any
+ register prior to saving it with MACHINE_STATE_SAVE_RET.
+
+ else if profile_block_flag != 0:
+
+ The macro will not be used, so it need not distinguish
+ these cases.
+*/
+
+void
+sparc_function_block_profiler_exit(file)
+ FILE *file;
+{
+ if (profile_block_flag == 2)
+ fprintf (file, "\tcall\t%s__bb_trace_ret\n\t nop\n", user_label_prefix);
+ else
+ abort ();
+}
diff --git a/contrib/gcc/config/sparc/sparc.h b/contrib/gcc/config/sparc/sparc.h
index e66f5e6..ad11d74 100644
--- a/contrib/gcc/config/sparc/sparc.h
+++ b/contrib/gcc/config/sparc/sparc.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for Sun SPARC.
- Copyright (C) 1987, 88, 89, 92, 94-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92, 94-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
@@ -34,10 +34,18 @@ Boston, MA 02111-1307, USA. */
architectures to compile for. We allow targets to choose compile time or
runtime selection. */
#ifdef SPARC_BI_ARCH
+#ifdef IN_LIBGCC2
+#if defined(__sparcv9) || defined(__sparcv_v9) || defined(__arch64__)
+#define TARGET_ARCH32 0
+#else
+#define TARGET_ARCH32 1
+#endif /* V9 sparc */
+#else
#define TARGET_ARCH32 (! TARGET_64BIT)
+#endif /* IN_LIBGCC2 */
#else
#define TARGET_ARCH32 (DEFAULT_ARCH32_P)
-#endif
+#endif /* SPARC_BI_ARCH */
#define TARGET_ARCH64 (! TARGET_ARCH32)
/* Code model selection.
@@ -55,7 +63,8 @@ Boston, MA 02111-1307, USA. */
TARGET_CM_MEDMID: 64 bit address space.
The executable must be in the low 16 TB of memory.
This corresponds to the low 44 bits, and the %[hml]44
- relocs are used.
+ relocs are used. The text segment has a maximum size
+ of 31 bits.
TARGET_CM_MEDANY: 64 bit address space.
The text and data segments have a maximum size of 31
@@ -78,7 +87,7 @@ enum cmodel {
};
/* Value of -mcmodel specified by user. */
-extern char *sparc_cmodel_string;
+extern const char *sparc_cmodel_string;
/* One of CM_FOO. */
extern enum cmodel sparc_cmodel;
@@ -97,44 +106,109 @@ extern enum cmodel sparc_cmodel;
/* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile,
and specified by the user via --with-cpu=foo.
This specifies the cpu implementation, not the architecture size. */
+/* Note that TARGET_CPU_v9 is assumed to start the list of 64-bit
+ capable cpu's. */
#define TARGET_CPU_sparc 0
#define TARGET_CPU_v7 0 /* alias for previous */
#define TARGET_CPU_sparclet 1
#define TARGET_CPU_sparclite 2
#define TARGET_CPU_v8 3 /* generic v8 implementation */
#define TARGET_CPU_supersparc 4
-#define TARGET_CPU_v9 5 /* generic v9 implementation */
-#define TARGET_CPU_sparc64 5 /* alias */
-#define TARGET_CPU_ultrasparc 6
+#define TARGET_CPU_hypersparc 5
+#define TARGET_CPU_sparc86x 6
+#define TARGET_CPU_sparclite86x 6
+#define TARGET_CPU_v9 7 /* generic v9 implementation */
+#define TARGET_CPU_sparcv9 7 /* alias */
+#define TARGET_CPU_sparc64 7 /* alias */
+#define TARGET_CPU_ultrasparc 8
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+
+#define CPP_CPU32_DEFAULT_SPEC ""
+#define ASM_CPU32_DEFAULT_SPEC ""
-#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc || TARGET_CPU_DEFAULT == TARGET_CPU_v8 || TARGET_CPU_DEFAULT == TARGET_CPU_supersparc
-#define CPP_CPU_DEFAULT_SPEC ""
-#define ASM_CPU_DEFAULT_SPEC ""
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclet
-#define CPP_CPU_DEFAULT_SPEC "-D__sparclet__"
-#define ASM_CPU_DEFAULT_SPEC "-Asparclet"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite
-#define CPP_CPU_DEFAULT_SPEC "-D__sparclite__"
-#define ASM_CPU_DEFAULT_SPEC "-Asparclite"
-#endif
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9
/* ??? What does Sun's CC pass? */
-#define CPP_CPU_DEFAULT_SPEC "-D__sparc_v9__"
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
/* ??? It's not clear how other assemblers will handle this, so by default
use GAS. Sun's Solaris assembler recognizes -xarch=v8plus, but this case
is handled in sol2.h. */
-#define ASM_CPU_DEFAULT_SPEC "-Av9"
+#define ASM_CPU64_DEFAULT_SPEC "-Av9"
#endif
#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
-#define CPP_CPU_DEFAULT_SPEC "-D__sparc_v9__"
-#define ASM_CPU_DEFAULT_SPEC "-Av9a"
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
+#define ASM_CPU64_DEFAULT_SPEC "-Av9a"
+#endif
+
+#else
+
+#define CPP_CPU64_DEFAULT_SPEC ""
+#define ASM_CPU64_DEFAULT_SPEC ""
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_v8
+#define CPP_CPU32_DEFAULT_SPEC ""
+#define ASM_CPU32_DEFAULT_SPEC ""
+#endif
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclet
+#define CPP_CPU32_DEFAULT_SPEC "-D__sparclet__"
+#define ASM_CPU32_DEFAULT_SPEC "-Asparclet"
#endif
-#ifndef CPP_CPU_DEFAULT_SPEC
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite
+#define CPP_CPU32_DEFAULT_SPEC "-D__sparclite__"
+#define ASM_CPU32_DEFAULT_SPEC "-Asparclite"
+#endif
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_supersparc
+#define CPP_CPU32_DEFAULT_SPEC "-D__supersparc__ -D__sparc_v8__"
+#define ASM_CPU32_DEFAULT_SPEC ""
+#endif
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_hypersparc
+#define CPP_CPU32_DEFAULT_SPEC "-D__hypersparc__ -D__sparc_v8__"
+#define ASM_CPU32_DEFAULT_SPEC ""
+#endif
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite86x
+#define CPP_CPU32_DEFAULT_SPEC "-D__sparclite86x__ -D__sparc_v8__"
+#define ASM_CPU32_DEFAULT_SPEC "-Av8"
+#endif
+
+#endif
+
+#if !defined(CPP_CPU32_DEFAULT_SPEC) || !defined(CPP_CPU64_DEFAULT_SPEC)
Unrecognized value in TARGET_CPU_DEFAULT.
#endif
+#ifdef SPARC_BI_ARCH
+
+#define CPP_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" CPP_CPU64_DEFAULT_SPEC "} \
+%{!m64:" CPP_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" CPP_CPU32_DEFAULT_SPEC "} \
+%{!m32:" CPP_CPU64_DEFAULT_SPEC "} \
+")
+#define ASM_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" ASM_CPU64_DEFAULT_SPEC "} \
+%{!m64:" ASM_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" ASM_CPU32_DEFAULT_SPEC "} \
+%{!m32:" ASM_CPU64_DEFAULT_SPEC "} \
+")
+
+#else /* !SPARC_BI_ARCH */
+
+#define CPP_CPU_DEFAULT_SPEC (DEFAULT_ARCH32_P ? CPP_CPU32_DEFAULT_SPEC : CPP_CPU64_DEFAULT_SPEC)
+#define ASM_CPU_DEFAULT_SPEC (DEFAULT_ARCH32_P ? ASM_CPU32_DEFAULT_SPEC : ASM_CPU64_DEFAULT_SPEC)
+
+#endif /* !SPARC_BI_ARCH */
+
/* Names to predefine in the preprocessor for this target machine.
??? It would be nice to not include any subtarget specific values here,
however there's no way to portably provide subtarget values to
@@ -158,6 +232,8 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \
%{mcpu=v8:-D__sparc_v8__} \
%{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \
+%{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \
+%{mcpu=sparclite86x:-D__sparclite86x__ -D__sparc_v8__} \
%{mcpu=v9:-D__sparc_v9__} \
%{mcpu=ultrasparc:-D__sparc_v9__} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
@@ -169,8 +245,20 @@ Unrecognized value in TARGET_CPU_DEFAULT.
sparc64 in 32 bit environments, so for now we only use `sparc64' in
64 bit environments. */
+#ifdef SPARC_BI_ARCH
+
+#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)"
+#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
+-D__arch64__ -Acpu(sparc64) -Amachine(sparc64)"
+
+#else
+
#define CPP_ARCH32_SPEC "-D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)"
#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu(sparc64) -Amachine(sparc64)"
+
+#endif
+
#define CPP_ARCH_DEFAULT_SPEC \
(DEFAULT_ARCH32_P ? CPP_ARCH32_SPEC : CPP_ARCH64_SPEC)
@@ -181,7 +269,9 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"
/* Macros to distinguish endianness. */
-#define CPP_ENDIAN_SPEC "%{mlittle-endian:-D__LITTLE_ENDIAN__}"
+#define CPP_ENDIAN_SPEC "\
+%{mlittle-endian:-D__LITTLE_ENDIAN__} \
+%{mlittle-endian-data:-D__LITTLE_ENDIAN_DATA__}"
/* Macros to distinguish the particular subtarget. */
#define CPP_SUBTARGET_SPEC ""
@@ -254,20 +344,20 @@ Unrecognized value in TARGET_CPU_DEFAULT.
Do not define this macro if it does not need to do anything. */
#define EXTRA_SPECS \
- { "cpp_cpu", CPP_CPU_SPEC }, \
- { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
- { "cpp_arch32", CPP_ARCH32_SPEC }, \
- { "cpp_arch64", CPP_ARCH64_SPEC }, \
- { "cpp_arch_default", CPP_ARCH_DEFAULT_SPEC }, \
- { "cpp_arch", CPP_ARCH_SPEC }, \
- { "cpp_endian", CPP_ENDIAN_SPEC }, \
- { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \
- { "asm_cpu", ASM_CPU_SPEC }, \
- { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
- { "asm_arch32", ASM_ARCH32_SPEC }, \
- { "asm_arch64", ASM_ARCH64_SPEC }, \
- { "asm_arch_default", ASM_ARCH_DEFAULT_SPEC }, \
- { "asm_arch", ASM_ARCH_SPEC }, \
+ { "cpp_cpu", CPP_CPU_SPEC }, \
+ { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
+ { "cpp_arch32", CPP_ARCH32_SPEC }, \
+ { "cpp_arch64", CPP_ARCH64_SPEC }, \
+ { "cpp_arch_default", CPP_ARCH_DEFAULT_SPEC },\
+ { "cpp_arch", CPP_ARCH_SPEC }, \
+ { "cpp_endian", CPP_ENDIAN_SPEC }, \
+ { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \
+ { "asm_cpu", ASM_CPU_SPEC }, \
+ { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
+ { "asm_arch32", ASM_ARCH32_SPEC }, \
+ { "asm_arch64", ASM_ARCH64_SPEC }, \
+ { "asm_arch_default", ASM_ARCH_DEFAULT_SPEC },\
+ { "asm_arch", ASM_ARCH_SPEC }, \
SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS
@@ -299,7 +389,7 @@ void sparc_override_options ();
{ \
if (flag_pic) \
{ \
- char *pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC"; \
+ const char *pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC";\
warning ("%s and profiling conflict: disabling %s", \
pic_string, pic_string); \
flag_pic = 0; \
@@ -411,8 +501,7 @@ extern int target_flags;
/* 0x2000, 0x4000 are unused */
/* Nonzero if pointers are 64 bits.
- This is not a user selectable option, though it may be one day -
- so it is used to determine pointer size instead of an architecture flag. */
+ At the moment it must follow architecture size flag. */
#define MASK_PTR64 0x8000
#define TARGET_PTR64 (target_flags & MASK_PTR64)
@@ -480,44 +569,44 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
- { {"fpu", MASK_FPU | MASK_FPU_SET}, \
- {"no-fpu", -MASK_FPU}, \
- {"no-fpu", MASK_FPU_SET}, \
- {"hard-float", MASK_FPU | MASK_FPU_SET}, \
- {"soft-float", -MASK_FPU}, \
- {"soft-float", MASK_FPU_SET}, \
- {"epilogue", MASK_EPILOGUE}, \
- {"no-epilogue", -MASK_EPILOGUE}, \
- {"unaligned-doubles", MASK_UNALIGNED_DOUBLES}, \
- {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES}, \
- {"impure-text", MASK_IMPURE_TEXT}, \
- {"no-impure-text", -MASK_IMPURE_TEXT}, \
- {"flat", MASK_FLAT}, \
- {"no-flat", -MASK_FLAT}, \
- {"app-regs", MASK_APP_REGS}, \
- {"no-app-regs", -MASK_APP_REGS}, \
- {"hard-quad-float", MASK_HARD_QUAD}, \
- {"soft-quad-float", -MASK_HARD_QUAD}, \
- {"v8plus", MASK_V8PLUS}, \
- {"no-v8plus", -MASK_V8PLUS}, \
- {"vis", MASK_VIS}, \
+ { {"fpu", MASK_FPU | MASK_FPU_SET, "Use hardware fp" }, \
+ {"no-fpu", -MASK_FPU, "Do not use hardware fp" }, \
+ {"no-fpu", MASK_FPU_SET, "Do not use hardware fp" }, \
+ {"hard-float", MASK_FPU | MASK_FPU_SET, "Use hardware fp" }, \
+ {"soft-float", -MASK_FPU, "Do not use hardware fp" }, \
+ {"soft-float", MASK_FPU_SET, "Do not use hardware fp" }, \
+ {"epilogue", MASK_EPILOGUE, "Use FUNCTION_EPILOGUE" }, \
+ {"no-epilogue", -MASK_EPILOGUE, "Do not use FUNCTION_EPILOGUE" }, \
+ {"unaligned-doubles", MASK_UNALIGNED_DOUBLES, "Assume possible double misalignment" },\
+ {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES, "Assume all doubles are aligned" }, \
+ {"impure-text", MASK_IMPURE_TEXT, "Pass -assert pure-text to linker" }, \
+ {"no-impure-text", -MASK_IMPURE_TEXT, "Do not pass -assert pure-text to linker" }, \
+ {"flat", MASK_FLAT, "Use flat register window model" }, \
+ {"no-flat", -MASK_FLAT, "Do not use flat register window model" }, \
+ {"app-regs", MASK_APP_REGS, "Use ABI reserved registers" }, \
+ {"no-app-regs", -MASK_APP_REGS, "Do not use ABI reserved registers" }, \
+ {"hard-quad-float", MASK_HARD_QUAD, "Use hardware quad fp instructions" }, \
+ {"soft-quad-float", -MASK_HARD_QUAD, "Do not use hardware quad fp instructions" }, \
+ {"v8plus", MASK_V8PLUS, "Compile for v8plus ABI" }, \
+ {"no-v8plus", -MASK_V8PLUS, "Do not compile for v8plus ABI" }, \
+ {"vis", MASK_VIS, "Utilize Visual Instruction Set" }, \
+ {"no-vis", -MASK_VIS, "Do not utilize Visual Instruction Set" }, \
/* ??? These are deprecated, coerced to -mcpu=. Delete in 2.9. */ \
- {"cypress", 0}, \
- {"sparclite", 0}, \
- {"f930", 0}, \
- {"f934", 0}, \
- {"v8", 0}, \
- {"supersparc", 0}, \
+ {"cypress", 0, "Optimize for Cypress processors" }, \
+ {"sparclite", 0, "Optimize for SparcLite processors" }, \
+ {"f930", 0, "Optimize for F930 processors" }, \
+ {"f934", 0, "Optimize for F934 processors" }, \
+ {"v8", 0, "Use V8 Sparc ISA" }, \
+ {"supersparc", 0, "Optimize for SuperSparc processors" }, \
/* End of deprecated options. */ \
- /* -mptrNN exists for *experimental* purposes. */ \
-/* {"ptr64", MASK_PTR64}, */ \
-/* {"ptr32", -MASK_PTR64}, */ \
- {"32", -MASK_64BIT}, \
- {"64", MASK_64BIT}, \
- {"stack-bias", MASK_STACK_BIAS}, \
- {"no-stack-bias", -MASK_STACK_BIAS}, \
+ {"ptr64", MASK_PTR64, "Pointers are 64-bit" }, \
+ {"ptr32", -MASK_PTR64, "Pointers are 32-bit" }, \
+ {"32", -MASK_64BIT, "Use 32-bit ABI" }, \
+ {"64", MASK_64BIT, "Use 64-bit ABI" }, \
+ {"stack-bias", MASK_STACK_BIAS, "Use stack bias" }, \
+ {"no-stack-bias", -MASK_STACK_BIAS, "Do not use stack bias" }, \
SUBTARGET_SWITCHES \
- { "", TARGET_DEFAULT}}
+ { "", TARGET_DEFAULT, ""}}
/* MASK_APP_REGS must always be the default because that's what
FIXED_REGISTERS is set to and -ffixed- is processed before
@@ -537,6 +626,8 @@ enum processor_type {
PROCESSOR_SPARCLITE,
PROCESSOR_F930,
PROCESSOR_F934,
+ PROCESSOR_HYPERSPARC,
+ PROCESSOR_SPARCLITE86X,
PROCESSOR_SPARCLET,
PROCESSOR_TSC701,
PROCESSOR_V9,
@@ -569,12 +660,12 @@ extern enum processor_type sparc_cpu;
#define TARGET_OPTIONS \
{ \
- { "cpu=", &sparc_select[1].string }, \
- { "tune=", &sparc_select[2].string }, \
- { "cmodel=", &sparc_cmodel_string }, \
- { "align-loops=", &sparc_align_loops_string }, \
- { "align-jumps=", &sparc_align_jumps_string }, \
- { "align-functions=", &sparc_align_funcs_string }, \
+ { "cpu=", &sparc_select[1].string, "Use features of and schedule code for given CPU" }, \
+ { "tune=", &sparc_select[2].string, "Schedule code for given CPU" }, \
+ { "cmodel=", &sparc_cmodel_string, "Use given Sparc code model" }, \
+ { "align-loops=", &sparc_align_loops_string, "Loop code aligned to this power of 2" }, \
+ { "align-jumps=", &sparc_align_jumps_string, "Jump targets are aligned to this power of 2" }, \
+ { "align-functions=", &sparc_align_funcs_string, "Function starts are aligned to this power of 2" }, \
SUBTARGET_OPTIONS \
}
@@ -584,8 +675,8 @@ extern enum processor_type sparc_cpu;
/* sparc_select[0] is reserved for the default cpu. */
struct sparc_cpu_select
{
- char *string;
- char *name;
+ const char *string;
+ const char *name;
int set_tune_p;
int set_arch_p;
};
@@ -593,9 +684,9 @@ struct sparc_cpu_select
extern struct sparc_cpu_select sparc_select[];
/* Variables to record values the user passes. */
-extern char *sparc_align_loops_string;
-extern char *sparc_align_jumps_string;
-extern char *sparc_align_funcs_string;
+extern const char *sparc_align_loops_string;
+extern const char *sparc_align_jumps_string;
+extern const char *sparc_align_funcs_string;
/* Parsed values as a power of two. */
extern int sparc_align_loops;
extern int sparc_align_jumps;
@@ -623,7 +714,7 @@ extern int sparc_align_funcs;
/* Define this to set the endianness to use in libgcc2.c, which can
not depend on target_flags. */
-#if defined (__LITTLE_ENDIAN__)
+#if defined (__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN_DATA__)
#define LIBGCC2_WORDS_BIG_ENDIAN 0
#else
#define LIBGCC2_WORDS_BIG_ENDIAN 1
@@ -912,14 +1003,17 @@ if (TARGET_ARCH64 \
#define CONDITIONAL_REGISTER_USAGE \
do \
{ \
- if (TARGET_ARCH32) \
+ if (flag_pic) \
{ \
- fixed_regs[5] = 1; \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
} \
- else \
+ if (TARGET_ARCH32) \
{ \
- fixed_regs[1] = 1; \
+ fixed_regs[5] = 1; \
} \
+ if (TARGET_LIVE_G0) \
+ fixed_regs[0] = 0; \
if (! TARGET_V9) \
{ \
int regno; \
@@ -959,11 +1053,6 @@ do \
fixed_regs[1] = 1; \
fixed_regs[2] = 1; \
} \
- if (flag_pic != 0) \
- { \
- fixed_regs[23] = 1; \
- call_used_regs[23] = 1; \
- } \
} \
while (0)
@@ -987,9 +1076,18 @@ while (0)
/* A subreg in 64 bit mode will have the wrong offset for a floating point
register. The least significant part is at offset 1, compared to 0 for
- integer registers. */
+ integer registers. This only applies when FMODE is a larger mode.
+ We also need to handle a special case of TF-->DF conversions. */
#define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO) \
- (TARGET_ARCH64 && (REGNO) >= 32 && (REGNO) < 96 && (TMODE) == SImode ? 1 : ((REGNO) + (WORD)))
+ (TARGET_ARCH64 \
+ && (REGNO) >= SPARC_FIRST_FP_REG \
+ && (REGNO) <= SPARC_LAST_V9_FP_REG \
+ && (TMODE) == SImode \
+ && !((FMODE) == QImode || (FMODE) == HImode) \
+ ? ((REGNO) + 1) \
+ : ((TMODE) == DFmode && (FMODE) == TFmode) \
+ ? ((REGNO) + ((WORD) * 2)) \
+ : ((REGNO) + (WORD)))
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
See sparc.c for how we initialize this. */
@@ -1080,7 +1178,6 @@ extern int sparc_mode_class[];
#define PIC_OFFSET_TABLE_REGNUM 23
-#define INITIALIZE_PIC initialize_pic ()
#define FINALIZE_PIC finalize_pic ()
/* Pick a default value we can notice from override_options:
@@ -1348,37 +1445,60 @@ extern char leaf_reg_remap[];
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class. */
-/* We can't load constants into FP registers. We can't load any FP constant
- if an 'E' constraint fails to match it. */
+/* - We can't load constants into FP registers. We can't load any FP
+ constant if an 'E' constraint fails to match it.
+ - Try and reload integer constants (symbolic or otherwise) back into
+ registers directly, rather than having them dumped to memory. */
+
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
(CONSTANT_P (X) \
- && (FP_REG_CLASS_P (CLASS) \
+ ? ((FP_REG_CLASS_P (CLASS) \
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
&& (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT \
|| HOST_BITS_PER_INT != BITS_PER_WORD))) \
- ? NO_REGS : (CLASS))
+ ? NO_REGS \
+ : (!FP_REG_CLASS_P (CLASS) \
+ && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \
+ ? GENERAL_REGS \
+ : (CLASS)) \
+ : (CLASS))
/* Return the register class of a scratch register needed to load IN into
a register of class CLASS in MODE.
- On the SPARC, when PIC, we need a temporary when loading some addresses
- into a register.
-
- Also, we need a temporary when loading/storing a HImode/QImode value
+ We need a temporary when loading/storing a HImode/QImode value
between memory and the FPU registers. This can happen when combine puts
a paradoxical subreg in a float/fix conversion insn. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
- ((FP_REG_CLASS_P (CLASS) && ((MODE) == HImode || (MODE) == QImode) \
+ ((FP_REG_CLASS_P (CLASS) \
+ && ((MODE) == HImode || (MODE) == QImode) \
&& (GET_CODE (IN) == MEM \
- || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
- && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS)
+ || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
+ && true_regnum (IN) == -1))) \
+ ? GENERAL_REGS \
+ : (((TARGET_CM_MEDANY \
+ && symbolic_operand ((IN), (MODE))) \
+ || (TARGET_CM_EMBMEDANY \
+ && text_segment_operand ((IN), (MODE)))) \
+ && !flag_pic) \
+ ? GENERAL_REGS \
+ : NO_REGS)
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, IN) \
- ((FP_REG_CLASS_P (CLASS) && ((MODE) == HImode || (MODE) == QImode) \
- && (GET_CODE (IN) == MEM \
- || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
- && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS)
+ ((FP_REG_CLASS_P (CLASS) \
+ && ((MODE) == HImode || (MODE) == QImode) \
+ && (GET_CODE (IN) == MEM \
+ || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
+ && true_regnum (IN) == -1))) \
+ ? GENERAL_REGS \
+ : (((TARGET_CM_MEDANY \
+ && symbolic_operand ((IN), (MODE))) \
+ || (TARGET_CM_EMBMEDANY \
+ && text_segment_operand ((IN), (MODE)))) \
+ && !flag_pic) \
+ ? GENERAL_REGS \
+ : NO_REGS)
/* On SPARC it is not possible to directly move data between
GENERAL_REGS and FP_REGS. */
@@ -1459,6 +1579,10 @@ extern char leaf_reg_remap[];
(TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \
: (STRUCT_VALUE_OFFSET + UNITS_PER_WORD))
+/* Offset from the argument pointer register value to the CFA. */
+
+#define ARG_POINTER_CFA_OFFSET SPARC_STACK_BIAS
+
/* When a parameter is passed in a register, stack space is still
allocated for it.
!v9: All 6 possible integer registers have backing store allocated.
@@ -1714,246 +1838,38 @@ do { \
to do a "save" insn. The decision about whether or not
to do this is made in regclass.c. */
-extern int leaf_function;
#define FUNCTION_PROLOGUE(FILE, SIZE) \
(TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, (int)SIZE) \
- : output_function_prologue (FILE, (int)SIZE, leaf_function))
+ : output_function_prologue (FILE, (int)SIZE, \
+ current_function_uses_only_leaf_regs))
/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry.
-
- 32 bit sparc uses %g2 as the STATIC_CHAIN_REGNUM which gets clobbered
- during profiling so we need to save/restore it around the call to mcount.
- We're guaranteed that a save has just been done, and we use the space
- allocated for intreg/fpreg value passing. */
-
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- do { \
- char buf[20]; \
- ASM_GENERATE_INTERNAL_LABEL (buf, "LP", (LABELNO)); \
- if (! TARGET_ARCH64) \
- fputs ("\tst %g2,[%fp-4]\n", FILE); \
- fputs ("\tsethi %hi(", FILE); \
- assemble_name (FILE, buf); \
- fputs ("),%o0\n", FILE); \
- fputs ("\tcall mcount\n\tadd %o0,%lo(", FILE); \
- assemble_name (FILE, buf); \
- fputs ("),%o0\n", FILE); \
- if (! TARGET_ARCH64) \
- fputs ("\tld [%fp-4],%g2\n", FILE); \
- } while (0)
-
-/* There are three profiling modes for basic blocks available.
- The modes are selected at compile time by using the options
- -a or -ax of the gnu compiler.
- The variable `profile_block_flag' will be set according to the
- selected option.
+ for profiling a function entry. */
- profile_block_flag == 0, no option used:
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ sparc_function_profiler(FILE, LABELNO)
- No profiling done.
+/* Set the name of the mcount function for the system. */
- profile_block_flag == 1, -a option used.
-
- Count frequency of execution of every basic block.
-
- profile_block_flag == 2, -ax option used.
-
- Generate code to allow several different profiling modes at run time.
- Available modes are:
- Produce a trace of all basic blocks.
- Count frequency of jump instructions executed.
- In every mode it is possible to start profiling upon entering
- certain functions and to disable profiling of some other functions.
-
- The result of basic-block profiling will be written to a file `bb.out'.
- If the -ax option is used parameters for the profiling will be read
- from file `bb.in'.
-
-*/
+#define MCOUNT_FUNCTION "*mcount"
/* The following macro shall output assembler code to FILE
- to initialize basic-block profiling.
-
- If profile_block_flag == 2
-
- Output code to call the subroutine `__bb_init_trace_func'
- and pass two parameters to it. The first parameter is
- the address of a block allocated in the object module.
- The second parameter is the number of the first basic block
- of the function.
+ to initialize basic-block profiling. */
- 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 number of the first basic block of the function is
- passed to the macro in BLOCK_OR_LABEL.
-
- If described in a virtual assembler language the code to be
- output looks like:
-
- parameter1 <- LPBX0
- parameter2 <- BLOCK_OR_LABEL
- call __bb_init_trace_func
-
- else if profile_block_flag != 0
-
- Output code to call the subroutine `__bb_init_func'
- and pass one single parameter to it, which is the same
- as the first parameter to `__bb_init_trace_func'.
-
- The first word of this parameter 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.
- Note: When profile_block_flag == 2 the test need not be done
- but `__bb_init_trace_func' *must* be called.
-
- BLOCK_OR_LABEL may be used to generate a label number as a
- branch destination in case `__bb_init_func' will not be called.
-
- If described in a virtual assembler language the code to be
- output looks like:
-
- cmp (LPBX0),0
- jne local_label
- parameter1 <- LPBX0
- call __bb_init_func
-local_label:
-
-*/
-
-#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \
-do \
- { \
- int bol = (BLOCK_OR_LABEL); \
- switch (profile_block_flag) \
- { \
- case 2: \
- fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tor %%o0,%%lo(LPBX0),%%o0\n\tsethi %%hi(%d),%%o1\n\tcall ___bb_init_trace_func\n\tor %%o1,%%lo(%d),%%o1\n",\
- bol, bol); \
- break; \
- default: \
- fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tld [%%lo(LPBX0)+%%o0],%%o1\n\ttst %%o1\n\tbne LPY%d\n\tadd %%o0,%%lo(LPBX0),%%o0\n\tcall ___bb_init_func\n\tnop\nLPY%d:\n",\
- bol, bol); \
- break; \
- } \
- } \
-while (0)
+#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \
+ sparc_function_block_profiler(FILE, BLOCK_OR_LABEL)
/* The following macro shall output assembler code to FILE
- to increment a counter associated with basic block number BLOCKNO.
-
- If profile_block_flag == 2
-
- Output code to initialize the global structure `__bb' and
- call the function `__bb_trace_func' which will increment the
- counter.
-
- `__bb' consists of two words. In the first word the number
- of the basic block has to be stored. In the second word
- the address of a block allocated in the object module
- has to be stored.
+ to increment a counter associated with basic block number BLOCKNO. */
- The basic block number is given by BLOCKNO.
-
- The address of the block is given by the label created with
-
- ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
-
- by FUNCTION_BLOCK_PROFILER.
-
- 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.
-
- If described in a virtual assembler language the code to be
- output looks like:
-
- move BLOCKNO -> (__bb)
- move LPBX0 -> (__bb+4)
- call __bb_trace_func
-
- Note that function `__bb_trace_func' must not change the
- machine state, especially the flag register. To grant
- this, you must output code to save and restore registers
- either in this macro or in the macros MACHINE_STATE_SAVE
- and MACHINE_STATE_RESTORE. The last two macros will be
- used in the function `__bb_trace_func', so you must make
- sure that the function prologue does not change any
- register prior to saving it with MACHINE_STATE_SAVE.
-
- else if profile_block_flag != 0
-
- Output code to increment the counter directly.
- Basic blocks are numbered separately from zero within each
- compiled object module. The count associated with block number
- BLOCKNO is at index BLOCKNO in an array 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.
-
- If described in a virtual assembler language, the code to be
- output looks like:
-
- inc (LPBX2+4*BLOCKNO)
-
-*/
-
-#define BLOCK_PROFILER(FILE, BLOCKNO) \
-do \
- { \
- int blockn = (BLOCKNO); \
- switch (profile_block_flag) \
- { \
- case 2: \
- fprintf (FILE, "\tsethi %%hi(___bb),%%g1\n\tsethi %%hi(%d),%%g2\n\tor %%g2,%%lo(%d),%%g2\n\tst %%g2,[%%lo(___bb)+%%g1]\n\tsethi %%hi(LPBX0),%%g2\n\tor %%g2,%%lo(LPBX0),%%g2\n\tadd 4,%%g1,%%g1\n\tst %%g2,[%%lo(___bb)+%%g1]\n\tmov %%o7,%%g2\n\tcall ___bb_trace_func\n\tnop\n\tmov %%g2,%%o7\n",\
- blockn, blockn); \
- break; \
- default: \
- fprintf (FILE, "\tsethi %%hi(LPBX2+%d),%%g1\n\tld [%%lo(LPBX2+%d)+%%g1],%%g2\n\
-\tadd %%g2,1,%%g2\n\tst %%g2,[%%lo(LPBX2+%d)+%%g1]\n", \
- 4 * blockn, 4 * blockn, 4 * blockn); \
- break; \
- } \
- } \
-while(0)
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+ sparc_block_profiler (FILE, BLOCKNO)
/* The following macro shall output assembler code to FILE
- to indicate a return from function during basic-block profiling.
-
- If profiling_block_flag == 2:
-
- Output assembler code to call function `__bb_trace_ret'.
-
- Note that function `__bb_trace_ret' must not change the
- machine state, especially the flag register. To grant
- this, you must output code to save and restore registers
- either in this macro or in the macros MACHINE_STATE_SAVE_RET
- and MACHINE_STATE_RESTORE_RET. The last two macros will be
- used in the function `__bb_trace_ret', so you must make
- sure that the function prologue does not change any
- register prior to saving it with MACHINE_STATE_SAVE_RET.
-
- else if profiling_block_flag != 0:
-
- The macro will not be used, so it need not distinguish
- these cases.
-*/
+ to indicate a return from function during basic-block profiling. */
#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \
- fprintf (FILE, "\tcall ___bb_trace_ret\n\tnop\n" );
+ sparc_function_block_profiler_exit(FILE)
/* The function `__bb_trace_func' is called in every basic block
and is not allowed to change the machine state. Saving (restoring)
@@ -2092,7 +2008,8 @@ extern union tree_node *current_function_decl;
#define FUNCTION_EPILOGUE(FILE, SIZE) \
(TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, (int)SIZE) \
- : output_function_epilogue (FILE, (int)SIZE, leaf_function))
+ : output_function_epilogue (FILE, (int)SIZE, \
+ current_function_uses_only_leaf_regs))
#define DELAY_SLOTS_FOR_EPILOGUE \
(TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
@@ -2190,11 +2107,11 @@ extern struct rtx_def *sparc_builtin_saveregs ();
/* Addressing modes, and classification of registers for them. */
-/* #define HAVE_POST_INCREMENT */
-/* #define HAVE_POST_DECREMENT */
+/* #define HAVE_POST_INCREMENT 0 */
+/* #define HAVE_POST_DECREMENT 0 */
-/* #define HAVE_PRE_DECREMENT */
-/* #define HAVE_PRE_INCREMENT */
+/* #define HAVE_PRE_DECREMENT 0 */
+/* #define HAVE_PRE_INCREMENT 0 */
/* Macros to check register numbers against specific register classes. */
@@ -2250,10 +2167,13 @@ extern struct rtx_def *sparc_builtin_saveregs ();
#define LEGITIMATE_PIC_OPERAND_P(X) (! pic_address_needs_scratch (X))
/* Nonzero if the constant value X is a legitimate general operand.
- Anything can be made to work except floating point constants. */
+ Anything can be made to work except floating point constants.
+ If TARGET_VIS, 0.0 can be made to work as well. */
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode)
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode || \
+ (TARGET_VIS && (GET_MODE (X) == SFmode || GET_MODE (X) == DFmode) && \
+ fp_zero_operand (X)))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
@@ -2268,15 +2188,13 @@ extern struct rtx_def *sparc_builtin_saveregs ();
After reload, it makes no difference, since pseudo regs have
been eliminated by then. */
-/* Optional extra constraints for this machine. Borrowed from romp.h.
+/* Optional extra constraints for this machine.
- For the SPARC, `Q' means that this is a memory operand but not a
- symbolic memory operand. Note that an unassigned pseudo register
- is such a memory operand. Needed because reload will generate
- these things in insns and then not re-recognize the insns, causing
- constrain_operands to fail.
+ 'T' handles memory addresses where the alignment is known to
+ be at least 8 bytes.
- `S' handles constraints for calls. ??? So where is it? */
+ `U' handles all pseudo registers or a hard even numbered
+ integer register, needed for ldd/std instructions. */
#ifndef REG_OK_STRICT
@@ -2292,17 +2210,11 @@ extern struct rtx_def *sparc_builtin_saveregs ();
/* 'T', 'U' are for aligned memory loads which aren't needed for v9. */
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' \
- ? ((GET_CODE (OP) == MEM \
- && memory_address_p (GET_MODE (OP), XEXP (OP, 0)) \
- && ! symbolic_memory_operand (OP, VOIDmode)) \
- || (reload_in_progress && GET_CODE (OP) == REG \
- && REGNO (OP) >= FIRST_PSEUDO_REGISTER)) \
- : (! TARGET_ARCH64 && (C) == 'T') \
- ? (mem_aligned_8 (OP)) \
- : (! TARGET_ARCH64 && (C) == 'U') \
- ? (register_ok_for_ldd (OP)) \
- : 0)
+ ((! TARGET_ARCH64 && (C) == 'T') \
+ ? (mem_min_alignment (OP, 8)) \
+ : ((! TARGET_ARCH64 && (C) == 'U') \
+ ? (register_ok_for_ldd (OP)) \
+ : 0))
#else
@@ -2312,19 +2224,14 @@ extern struct rtx_def *sparc_builtin_saveregs ();
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' \
- ? (GET_CODE (OP) == REG \
- ? (REGNO (OP) >= FIRST_PSEUDO_REGISTER \
- && reg_renumber[REGNO (OP)] < 0) \
- : GET_CODE (OP) == MEM) \
- : (! TARGET_ARCH64 && (C) == 'T') \
- ? mem_aligned_8 (OP) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
- : (! TARGET_ARCH64 && (C) == 'U') \
- ? (GET_CODE (OP) == REG \
- && (REGNO (OP) < FIRST_PSEUDO_REGISTER \
- || reg_renumber[REGNO (OP)] >= 0) \
- && register_ok_for_ldd (OP)) \
- : 0)
+ ((! TARGET_ARCH64 && (C) == 'T') \
+ ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
+ : ((! TARGET_ARCH64 && (C) == 'U') \
+ ? (GET_CODE (OP) == REG \
+ && (REGNO (OP) < FIRST_PSEUDO_REGISTER \
+ || reg_renumber[REGNO (OP)] >= 0) \
+ && register_ok_for_ldd (OP)) \
+ : 0))
#endif
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -2373,13 +2280,32 @@ extern struct rtx_def *sparc_builtin_saveregs ();
} \
else if (RTX_OK_FOR_BASE_P (op0)) \
{ \
- if (RTX_OK_FOR_INDEX_P (op1) \
+ if ((RTX_OK_FOR_INDEX_P (op1) \
+ /* We prohibit REG + REG for TFmode when \
+ there are no instructions which accept \
+ REG+REG instructions. We do this \
+ because REG+REG is not an offsetable \
+ address. If we get the situation \
+ in reload where source and destination \
+ of a movtf pattern are both MEMs with \
+ REG+REG address, then only one of them \
+ gets converted to an offsetable \
+ address. */ \
+ && (MODE != TFmode \
+ || (TARGET_FPU && TARGET_ARCH64 \
+ && TARGET_V9 \
+ && TARGET_HARD_QUAD))) \
|| RTX_OK_FOR_OFFSET_P (op1)) \
goto ADDR; \
} \
else if (RTX_OK_FOR_BASE_P (op1)) \
{ \
- if (RTX_OK_FOR_INDEX_P (op0) \
+ if ((RTX_OK_FOR_INDEX_P (op0) \
+ /* See the previous comment. */ \
+ && (MODE != TFmode \
+ || (TARGET_FPU && TARGET_ARCH64 \
+ && TARGET_V9 \
+ && TARGET_HARD_QUAD))) \
|| RTX_OK_FOR_OFFSET_P (op0)) \
goto ADDR; \
} \
@@ -2392,8 +2318,8 @@ extern struct rtx_def *sparc_builtin_saveregs ();
&& CONSTANT_P (op1) \
/* We can't allow TFmode, because an offset \
greater than or equal to the alignment (8) \
- may cause the LO_SUM to overflow. */ \
- && MODE != TFmode) \
+ may cause the LO_SUM to overflow if !v9. */\
+ && (MODE != TFmode || TARGET_V9)) \
goto ADDR; \
} \
else if (GET_CODE (X) == CONST_INT && SMALL_INT (X)) \
@@ -2440,11 +2366,43 @@ extern struct rtx_def *legitimize_pic_address ();
copy_to_mode_reg (Pmode, XEXP (X, 0))); \
else if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
|| GET_CODE (X) == LABEL_REF) \
- (X) = gen_rtx_LO_SUM (Pmode, \
- copy_to_mode_reg (Pmode, gen_rtx_HIGH (Pmode, X)), X); \
+ (X) = copy_to_suggested_reg (X, NULL_RTX, Pmode); \
if (memory_address_p (MODE, X)) \
goto WIN; }
+/* Try a machine-dependent way of reloading an illegitimate address
+ operand. If we find one, push the reload and jump to WIN. This
+ macro is used in only one place: `find_reloads_address' in reload.c.
+
+ For Sparc 32, we wish to handle addresses by splitting them into
+ HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference.
+ This cuts the number of extra insns by one.
+
+ Do nothing when generating PIC code and the address is a
+ symbolic operand or requires a scratch register. */
+
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
+do { \
+ /* Decompose SImode constants into hi+lo_sum. We do have to \
+ rerecognize what we produce, so be careful. */ \
+ if (CONSTANT_P (X) \
+ && (MODE != TFmode || TARGET_V9) \
+ && GET_MODE (X) == SImode \
+ && GET_CODE (X) != LO_SUM && GET_CODE (X) != HIGH \
+ && ! (flag_pic \
+ && (symbolic_operand (X, Pmode) \
+ || pic_address_needs_scratch (X)))) \
+ { \
+ X = gen_rtx_LO_SUM (GET_MODE (X), \
+ gen_rtx_HIGH (GET_MODE (X), X), X); \
+ push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
+ BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
+ OPNUM, TYPE); \
+ goto WIN; \
+ } \
+ /* ??? 64-bit reloads. */ \
+} while (0)
+
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for.
On the SPARC this is never true. */
@@ -2463,7 +2421,17 @@ extern struct rtx_def *legitimize_pic_address ();
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE Pmode
+/* If we ever implement any of the full models (such as CM_FULLANY),
+ this has to be DImode in that case */
+#ifdef HAVE_GAS_SUBSECTION_ORDERING
+#define CASE_VECTOR_MODE \
+(! TARGET_PTR64 ? SImode : flag_pic ? SImode : TARGET_CM_MEDLOW ? SImode : DImode)
+#else
+/* If assembler does not have working .subsection -1, we use DImode for pic, as otherwise
+ we have to sign extend which slows things down. */
+#define CASE_VECTOR_MODE \
+(! TARGET_PTR64 ? SImode : flag_pic ? DImode : TARGET_CM_MEDLOW ? SImode : DImode)
+#endif
/* Define as C expression which evaluates to nonzero if the tablejump
instruction expects the table to contain offsets from the address of the
@@ -2597,25 +2565,26 @@ extern struct rtx_def *legitimize_pic_address ();
#define MULSI3_LIBCALL "*.umul"
/* Define library calls for quad FP operations. These are all part of the
- SPARC ABI. */
-#define ADDTF3_LIBCALL "_Q_add"
-#define SUBTF3_LIBCALL "_Q_sub"
-#define NEGTF2_LIBCALL "_Q_neg"
-#define MULTF3_LIBCALL "_Q_mul"
-#define DIVTF3_LIBCALL "_Q_div"
-#define FLOATSITF2_LIBCALL "_Q_itoq"
-#define FIX_TRUNCTFSI2_LIBCALL "_Q_qtoi"
-#define FIXUNS_TRUNCTFSI2_LIBCALL "_Q_qtou"
-#define EXTENDSFTF2_LIBCALL "_Q_stoq"
-#define TRUNCTFSF2_LIBCALL "_Q_qtos"
-#define EXTENDDFTF2_LIBCALL "_Q_dtoq"
-#define TRUNCTFDF2_LIBCALL "_Q_qtod"
-#define EQTF2_LIBCALL "_Q_feq"
-#define NETF2_LIBCALL "_Q_fne"
-#define GTTF2_LIBCALL "_Q_fgt"
-#define GETF2_LIBCALL "_Q_fge"
-#define LTTF2_LIBCALL "_Q_flt"
-#define LETF2_LIBCALL "_Q_fle"
+ SPARC ABI.
+ ??? ARCH64 still does not work as the _Qp_* routines take pointers. */
+#define ADDTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_add" : "_Q_add")
+#define SUBTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_sub" : "_Q_sub")
+#define NEGTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_neg" : "_Q_neg")
+#define MULTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_mul" : "_Q_mul")
+#define DIVTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_div" : "_Q_div")
+#define FLOATSITF2_LIBCALL (TARGET_ARCH64 ? "_Qp_itoq" : "_Q_itoq")
+#define FIX_TRUNCTFSI2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtoi" : "_Q_qtoi")
+#define FIXUNS_TRUNCTFSI2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtoui" : "_Q_qtou")
+#define EXTENDSFTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_stoq" : "_Q_stoq")
+#define TRUNCTFSF2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtos" : "_Q_qtos")
+#define EXTENDDFTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_dtoq" : "_Q_dtoq")
+#define TRUNCTFDF2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtod" : "_Q_qtod")
+#define EQTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_feq" : "_Q_feq")
+#define NETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fne" : "_Q_fne")
+#define GTTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fgt" : "_Q_fgt")
+#define GETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fge" : "_Q_fge")
+#define LTTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_flt" : "_Q_flt")
+#define LETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fle" : "_Q_fle")
/* We can define the TFmode sqrt optab only if TARGET_FPU. This is because
with soft-float, the SFmode and DFmode sqrt instructions will be absent,
@@ -2681,9 +2650,6 @@ extern struct rtx_def *legitimize_pic_address ();
return 0; \
return 8;
-/* Compute the cost of an address. For the sparc, all valid addresses are
- the same cost. */
-
#define ADDRESS_COST(RTX) 1
/* Compute extra cost of moving data between one register class
@@ -2704,11 +2670,17 @@ extern struct rtx_def *legitimize_pic_address ();
#define RTX_COSTS(X,CODE,OUTER_CODE) \
case MULT: \
+ if (sparc_cpu == PROCESSOR_ULTRASPARC) \
+ return (GET_MODE (X) == DImode ? \
+ COSTS_N_INSNS (34) : COSTS_N_INSNS (19)); \
return TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \
case DIV: \
case UDIV: \
case MOD: \
case UMOD: \
+ if (sparc_cpu == PROCESSOR_ULTRASPARC) \
+ return (GET_MODE (X) == DImode ? \
+ COSTS_N_INSNS (68) : COSTS_N_INSNS (37)); \
return COSTS_N_INSNS (25); \
/* Make FLOAT and FIX more expensive than CONST_DOUBLE,\
so that cse will favor the latter. */ \
@@ -2719,12 +2691,26 @@ extern struct rtx_def *legitimize_pic_address ();
#define ISSUE_RATE sparc_issue_rate()
/* Adjust the cost of dependencies. */
-#define ADJUST_COST(INSN,LINK,DEP,COST) \
- if (sparc_cpu == PROCESSOR_SUPERSPARC) \
- (COST) = supersparc_adjust_cost (INSN, LINK, DEP, COST); \
- else if (sparc_cpu == PROCESSOR_ULTRASPARC) \
- (COST) = ultrasparc_adjust_cost (INSN, LINK, DEP, COST); \
- else
+#define ADJUST_COST(INSN,LINK,DEP,COST) \
+ sparc_adjust_cost(INSN, LINK, DEP, COST)
+
+extern void ultrasparc_sched_reorder ();
+extern void ultrasparc_sched_init ();
+extern int ultrasparc_variable_issue ();
+
+#define MD_SCHED_INIT(DUMP, SCHED_VERBOSE) \
+ if (sparc_cpu == PROCESSOR_ULTRASPARC) \
+ ultrasparc_sched_init (DUMP, SCHED_VERBOSE)
+
+#define MD_SCHED_REORDER(DUMP, SCHED_VERBOSE, READY, N_READY) \
+ if (sparc_cpu == PROCESSOR_ULTRASPARC) \
+ ultrasparc_sched_reorder (DUMP, SCHED_VERBOSE, READY, N_READY)
+
+#define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \
+ if (sparc_cpu == PROCESSOR_ULTRASPARC) \
+ (CAN_ISSUE_MORE) = ultrasparc_variable_issue (INSN); \
+ else \
+ (CAN_ISSUE_MORE)--
/* Conditional branches with empty delay slots have a length of two. */
#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
@@ -2925,13 +2911,23 @@ extern struct rtx_def *legitimize_pic_address ();
#define ASM_OUTPUT_BYTE(FILE,VALUE) \
fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE))
+/* This is how we hook in and defer the case-vector until the end of
+ the function. */
+extern void sparc_defer_case_vector ();
+
+#define ASM_OUTPUT_ADDR_VEC(LAB,VEC) \
+ sparc_defer_case_vector ((LAB),(VEC), 0)
+
+#define ASM_OUTPUT_ADDR_DIFF_VEC(LAB,VEC) \
+ sparc_defer_case_vector ((LAB),(VEC), 1)
+
/* This is how to output an element of a case-vector that is absolute. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
do { \
char label[30]; \
ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
- if (Pmode == SImode) \
+ if (CASE_VECTOR_MODE == SImode) \
fprintf (FILE, "\t.word\t"); \
else \
fprintf (FILE, "\t.xword\t"); \
@@ -2945,8 +2941,8 @@ do { \
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
do { \
char label[30]; \
- ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
- if (Pmode == SImode) \
+ ASM_GENERATE_INTERNAL_LABEL (label, "L", (VALUE)); \
+ if (CASE_VECTOR_MODE == SImode) \
fprintf (FILE, "\t.word\t"); \
else \
fprintf (FILE, "\t.xword\t"); \
@@ -2957,6 +2953,20 @@ do { \
fputc ('\n', FILE); \
} while (0)
+/* This is what to output before and after case-vector (both
+ relative and absolute). If .subsection -1 works, we put case-vectors
+ at the beginning of the current section. */
+
+#ifdef HAVE_GAS_SUBSECTION_ORDERING
+
+#define ASM_OUTPUT_ADDR_VEC_START(FILE) \
+ fprintf(FILE, "\t.subsection\t-1\n")
+
+#define ASM_OUTPUT_ADDR_VEC_END(FILE) \
+ fprintf(FILE, "\t.previous\n")
+
+#endif
+
/* This is how to output an assembler line
that says to advance the location counter
to a multiple of 2**LOG bytes. */
@@ -3105,7 +3115,6 @@ do { \
else if (GET_CODE (index) == REG) \
fprintf (FILE, "+%s", reg_names[REGNO (index)]); \
else if (GET_CODE (index) == SYMBOL_REF \
- || GET_CODE (index) == LABEL_REF \
|| GET_CODE (index) == CONST) \
fputc ('+', FILE), output_addr_const (FILE, index); \
else abort (); \
@@ -3121,7 +3130,10 @@ do { \
else if (GET_CODE (addr) == LO_SUM) \
{ \
output_operand (XEXP (addr, 0), 0); \
- fputs ("+%lo(", FILE); \
+ if (TARGET_CM_MEDMID) \
+ fputs ("+%l44(", FILE); \
+ else \
+ fputs ("+%lo(", FILE); \
output_address (XEXP (addr, 1)); \
fputc (')', FILE); \
} \
@@ -3148,46 +3160,49 @@ do { \
/* Define the codes that are matched by predicates in sparc.c. */
-#define PREDICATE_CODES \
-{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
-{"fp_zero_operand", {CONST_DOUBLE}}, \
-{"intreg_operand", {SUBREG, REG}}, \
-{"fcc_reg_operand", {REG}}, \
-{"icc_or_fcc_reg_operand", {REG}}, \
-{"restore_operand", {REG}}, \
-{"call_operand", {MEM}}, \
-{"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE, ADDRESSOF, \
- SUBREG, REG, PLUS, LO_SUM, CONST_INT}}, \
-{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE}}, \
-{"symbolic_memory_operand", {SUBREG, MEM}}, \
-{"label_ref_operand", {LABEL_REF}}, \
-{"sp64_medium_pic_operand", {CONST}}, \
-{"data_segment_operand", {SYMBOL_REF, PLUS, CONST}}, \
-{"text_segment_operand", {LABEL_REF, SYMBOL_REF, PLUS, CONST}}, \
-{"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}}, \
-{"sparc_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, MEM}}, \
-{"move_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE, MEM}}, \
-{"splittable_symbolic_memory_operand", {MEM}}, \
-{"splittable_immediate_memory_operand", {MEM}}, \
-{"eq_or_neq", {EQ, NE}}, \
-{"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}}, \
-{"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}}, \
-{"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}}, \
-{"v8plus_regcmp_op", {EQ, NE}}, \
-{"extend_op", {SIGN_EXTEND, ZERO_EXTEND}}, \
-{"cc_arithop", {AND, IOR, XOR}}, \
-{"cc_arithopn", {AND, IOR}}, \
-{"arith_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
-{"arith11_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
-{"arith10_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
-{"arith_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
-{"arith11_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
-{"arith10_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
-{"small_int", {CONST_INT, CONSTANT_P_RTX}}, \
-{"uns_small_int", {CONST_INT, CONSTANT_P_RTX}}, \
-{"uns_arith_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{"clobbered_register", {REG}},
-
+#define PREDICATE_CODES \
+{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+{"fp_zero_operand", {CONST_DOUBLE}}, \
+{"intreg_operand", {SUBREG, REG}}, \
+{"fcc_reg_operand", {REG}}, \
+{"icc_or_fcc_reg_operand", {REG}}, \
+{"restore_operand", {REG}}, \
+{"call_operand", {MEM}}, \
+{"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE, \
+ ADDRESSOF, SUBREG, REG, PLUS, LO_SUM, CONST_INT}}, \
+{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE}}, \
+{"symbolic_memory_operand", {SUBREG, MEM}}, \
+{"label_ref_operand", {LABEL_REF}}, \
+{"sp64_medium_pic_operand", {CONST}}, \
+{"data_segment_operand", {SYMBOL_REF, PLUS, CONST}}, \
+{"text_segment_operand", {LABEL_REF, SYMBOL_REF, PLUS, CONST}}, \
+{"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}}, \
+{"splittable_symbolic_memory_operand", {MEM}}, \
+{"splittable_immediate_memory_operand", {MEM}}, \
+{"eq_or_neq", {EQ, NE}}, \
+{"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}}, \
+{"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}}, \
+{"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}}, \
+{"extend_op", {SIGN_EXTEND, ZERO_EXTEND}}, \
+{"cc_arithop", {AND, IOR, XOR}}, \
+{"cc_arithopn", {AND, IOR}}, \
+{"arith_operand", {SUBREG, REG, CONST_INT}}, \
+{"arith_add_operand", {SUBREG, REG, CONST_INT}}, \
+{"arith11_operand", {SUBREG, REG, CONST_INT}}, \
+{"arith10_operand", {SUBREG, REG, CONST_INT}}, \
+{"arith_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+{"arith_double_add_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+{"arith11_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+{"arith10_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+{"small_int", {CONST_INT}}, \
+{"small_int_or_double", {CONST_INT, CONST_DOUBLE}}, \
+{"uns_small_int", {CONST_INT}}, \
+{"uns_arith_operand", {SUBREG, REG, CONST_INT}}, \
+{"clobbered_register", {REG}}, \
+{"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}}, \
+{"zero_operand", {CONST_INT}}, \
+{"const64_operand", {CONST_INT, CONST_DOUBLE}}, \
+{"const64_high_operand", {CONST_INT, CONST_DOUBLE}},
/* The number of Pmode words for the setjmp buffer. */
#define JMP_BUF_SIZE 12
@@ -3196,17 +3211,15 @@ do { \
/* Declare functions defined in sparc.c and used in templates. */
-extern char *doublemove_string ();
-extern char *output_block_move ();
+extern void sparc_emit_set_const32 ();
+extern void sparc_emit_set_const64 ();
+extern void sparc_emit_set_symbolic_const64 ();
+extern int sparc_splitdi_legitimate ();
+extern int sparc_absnegfloat_split_legitimate ();
+
extern char *output_cbranch ();
-extern char *output_fp_move_double ();
-extern char *output_fp_move_quad ();
-extern char *output_move_double ();
-extern char *output_move_quad ();
-extern char *output_return ();
-extern char *output_scc_insn ();
+extern const char *output_return ();
extern char *output_v9branch ();
-extern char *singlemove_string ();
extern void emit_v9_brxx_insn ();
extern void finalize_pic ();
@@ -3224,8 +3237,16 @@ extern int arith10_operand ();
extern int arith11_double_operand ();
extern int arith11_operand ();
extern int arith_double_operand ();
+extern int arith_double_4096_operand ();
+extern int arith_double_add_operand ();
extern int arith_operand ();
+extern int arith_4096_operand ();
+extern int arith_add_operand ();
extern int call_operand_address ();
+extern int input_operand ();
+extern int zero_operand ();
+extern int const64_operand ();
+extern int const64_high_operand ();
extern int cc_arithop ();
extern int cc_arithopn ();
extern int check_pic ();
@@ -3239,8 +3260,7 @@ extern int fcc_reg_operand ();
extern int fp_zero_operand ();
extern int icc_or_fcc_reg_operand ();
extern int label_ref_operand ();
-extern int mem_aligned_8 ();
-extern int move_operand ();
+extern int mem_min_alignment ();
extern int noov_compare_op ();
extern int pic_address_needs_scratch ();
extern int reg_or_0_operand ();
@@ -3251,27 +3271,29 @@ extern int registers_ok_for_ldd_peep ();
extern int restore_operand ();
extern int short_branch ();
extern int small_int ();
+extern int small_int_or_double ();
extern int sp64_medium_pic_operand ();
extern int sparc_flat_eligible_for_epilogue_delay ();
extern int sparc_flat_epilogue_delay_slots ();
extern int sparc_issue_rate ();
-extern int sparc_operand ();
extern int splittable_immediate_memory_operand ();
extern int splittable_symbolic_memory_operand ();
-extern int supersparc_adjust_cost ();
+extern int sparc_adjust_cost ();
extern int symbolic_memory_operand ();
extern int symbolic_operand ();
extern int text_segment_operand ();
-extern int ultrasparc_adjust_cost ();
extern int uns_small_int ();
-extern int v8plus_regcmp_op ();
-extern int v8plus_regcmp_p ();
extern int v9_regcmp_op ();
extern int v9_regcmp_p ();
extern unsigned long sparc_flat_compute_frame_size ();
extern unsigned long sparc_type_code ();
+extern void sparc_function_profiler ();
+extern void sparc_function_block_profiler ();
+extern void sparc_block_profiler ();
+extern void sparc_function_block_profiler_exit ();
+
extern char *sparc_v8plus_shift ();
#ifdef __STDC__
diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md
index ccfde05..02170b7 100644
--- a/contrib/gcc/config/sparc/sparc.md
+++ b/contrib/gcc/config/sparc/sparc.md
@@ -1,5 +1,5 @@
;;- Machine description for SPARC chip for GNU C compiler
-;; Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
;; 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
;; at Cygnus Support.
@@ -23,6 +23,37 @@
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+;; Uses of UNSPEC and UNSPEC_VOLATILE in this file:
+;;
+;; UNSPEC: 0 movsi_{lo_sum,high}_pic
+;; pic_lo_sum_di
+;; pic_sethi_di
+;; 1 update_return
+;; 2 get_pc
+;; 5 movsi_{,lo_sum_,high_}pic_label_ref
+;; 6 seth44
+;; 7 setm44
+;; 8 setl44
+;; 9 sethh
+;; 10 setlm
+;; 11 embmedany_sethi, embmedany_brsum
+;; 12 movsf_const_high
+;; 13 embmedany_textuhi
+;; 14 embmedany_texthi
+;; 15 embmedany_textulo
+;; 16 embmedany_textlo
+;; 17 movsf_const_lo
+;; 18 sethm
+;; 19 setlo
+;;
+;; UNSPEC_VOLATILE: 0 blockage
+;; 1 flush_register_windows
+;; 2 goto_handler_and_restore
+;; 3 goto_handler_and_restore_v9*
+;; 4 flush
+;; 5 nonlocal_goto_receiver
+;;
+
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
@@ -34,7 +65,7 @@
;; Attribute for cpu type.
;; These must match the values for enum processor_type in sparc.h.
-(define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,sparclet,tsc701,v9,ultrasparc"
+(define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,hypersparc,sparclite86x,sparclet,tsc701,v9,ultrasparc"
(const (symbol_ref "sparc_cpu_attr")))
;; Attribute for the instruction set.
@@ -128,8 +159,7 @@
[(eq_attr "in_call_delay" "true") (nil) (nil)])
(define_attr "leaf_function" "false,true"
- (const (symbol_ref "leaf_function")))
-
+ (const (symbol_ref "current_function_uses_only_leaf_regs")))
(define_attr "in_return_delay" "false,true"
(if_then_else (and (and (and (eq_attr "type" "move,load,sload,store,binary,ialu")
@@ -315,6 +345,53 @@
(eq_attr "type" "imul"))
4 4)
+;; ----- hypersparc/sparclite86x scheduling
+;; The Hypersparc can issue 1 - 2 insns per cycle. The dual issue cases are:
+;; L-Ld/St I-Int F-Float B-Branch LI/LF/LB/II/IF/IB/FF/FB
+;; II/FF case is only when loading a 32 bit hi/lo constant
+;; Single issue insns include call, jmpl, u/smul, u/sdiv, lda, sta, fcmp
+;; Memory delivers its result in one cycle to IU
+
+(define_function_unit "memory" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "load,sload,fpload"))
+ 1 1)
+
+(define_function_unit "memory" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "store,fpstore"))
+ 2 1)
+
+(define_function_unit "fp_alu" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fp,fpmove,fpcmp"))
+ 1 1)
+
+(define_function_unit "fp_mds" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpmul"))
+ 1 1)
+
+(define_function_unit "fp_mds" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpdivs"))
+ 8 6)
+
+(define_function_unit "fp_mds" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpdivd"))
+ 12 10)
+
+(define_function_unit "fp_mds" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpsqrt"))
+ 17 15)
+
+(define_function_unit "fp_mds" 1 0
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "imul"))
+ 17 15)
+
;; ----- sparclet tsc701 scheduling
;; The tsc701 issues 1 insn per cycle.
;; Results may be written back out of order.
@@ -370,21 +447,31 @@
(eq_attr "type" "store,fpstore"))
1 1)
-(define_function_unit "ieu" 1 0
+(define_function_unit "ieuN" 2 0
(and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "ialu,binary,shift,compare,cmove,call"))
+ (eq_attr "type" "ialu,binary,move,unary,shift,compare,call,call_no_delay_slot,uncond_branch"))
1 1)
-(define_function_unit "ieu_shift" 1 0
+(define_function_unit "ieu0" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "shift"))
1 1)
-(define_function_unit "ieu_shift" 1 0
+(define_function_unit "ieu0" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "cmove"))
2 1)
+(define_function_unit "ieu1" 1 0
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "compare,call,call_no_delay_slot,uncond_branch"))
+ 1 1)
+
+(define_function_unit "cti" 1 0
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "branch"))
+ 1 1)
+
;; Timings; throughput/latency
;; FMOV 1/1 fmov, fabs, fneg
;; FMOVcc 1/2
@@ -395,6 +482,11 @@
;; FSQRTs 12/12
;; FSQRTd 22/22
;; FCMP takes 1 cycle to branch, 2 cycles to conditional move.
+;;
+;; ??? This is really bogus because the timings really depend upon
+;; who uses the result. We should record who the user is with
+;; more descriptive 'type' attribute names and account for these
+;; issues in ultrasparc_adjust_cost.
(define_function_unit "fadd" 1 0
(and (eq_attr "cpu" "ultrasparc")
@@ -426,17 +518,17 @@
(eq_attr "type" "fpcmove"))
2 1)
-(define_function_unit "fadd" 1 0
+(define_function_unit "fmul" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fpdivs"))
12 12)
-(define_function_unit "fadd" 1 0
+(define_function_unit "fmul" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fpdivd"))
22 22)
-(define_function_unit "fadd" 1 0
+(define_function_unit "fmul" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fpsqrt"))
12 12)
@@ -475,7 +567,7 @@
[(set (reg:CCX 100)
(compare:CCX (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "arith_double_operand" "")))]
- "TARGET_ARCH64 || TARGET_V8PLUS"
+ "TARGET_ARCH64"
"
{
sparc_compare_op0 = operands[0];
@@ -529,7 +621,7 @@
(compare:CC (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "arith_operand" "rI")))]
""
- "cmp %0,%1"
+ "cmp\\t%0, %1"
[(set_attr "type" "compare")])
(define_insn "*cmpdi_sp64"
@@ -537,42 +629,9 @@
(compare:CCX (match_operand:DI 0 "register_operand" "r")
(match_operand:DI 1 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "cmp %0,%1"
+ "cmp\\t%0, %1"
[(set_attr "type" "compare")])
-(define_insn "cmpdi_v8plus"
- [(set (reg:CCX 100)
- (compare:CCX (match_operand:DI 0 "register_operand" "r,r,r")
- (match_operand:DI 1 "arith_double_operand" "J,I,r")))
- (clobber (match_scratch:SI 2 "=&h,&h,&h"))
- (clobber (match_scratch:SI 3 "=X,X,&h"))]
- "TARGET_V8PLUS"
- "*
-{
- /* The srl can be omitted if the value in the %L0 or %L1 is already
- zero extended. */
-
- output_asm_insn (\"sllx %H0,32,%2\", operands);
-
- if (sparc_check_64 (operands[0], insn) <= 0)
- output_asm_insn (\"srl %L0,0,%L0\", operands);
-
- switch (which_alternative)
- {
- case 0:
- return \"orcc %L0,%2,%%g0\";
- case 1:
- return \"or %L0,%2,%2\;cmp %2,%1\";
- case 2:
- if (sparc_check_64 (operands[1], insn) <= 0)
- output_asm_insn (\"srl %L1,0,%L1\", operands);
- return \"sllx %H1,32,%3\;or %L0,%2,%2\;or %L1,%3,%3\;cmp %2,%3\";
- default:
- abort();
- }
-}"
- [(set_attr "length" "3,4,7")])
-
(define_insn "*cmpsf_fpe"
[(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
(compare:CCFPE (match_operand:SF 1 "register_operand" "f")
@@ -581,8 +640,8 @@
"*
{
if (TARGET_V9)
- return \"fcmpes %0,%1,%2\";
- return \"fcmpes %1,%2\";
+ return \"fcmpes\\t%0, %1, %2\";
+ return \"fcmpes\\t%1, %2\";
}"
[(set_attr "type" "fpcmp")])
@@ -594,8 +653,8 @@
"*
{
if (TARGET_V9)
- return \"fcmped %0,%1,%2\";
- return \"fcmped %1,%2\";
+ return \"fcmped\\t%0, %1, %2\";
+ return \"fcmped\\t%1, %2\";
}"
[(set_attr "type" "fpcmp")])
@@ -607,8 +666,8 @@
"*
{
if (TARGET_V9)
- return \"fcmpeq %0,%1,%2\";
- return \"fcmpeq %1,%2\";
+ return \"fcmpeq\\t%0, %1, %2\";
+ return \"fcmpeq\\t%1, %2\";
}"
[(set_attr "type" "fpcmp")])
@@ -620,8 +679,8 @@
"*
{
if (TARGET_V9)
- return \"fcmps %0,%1,%2\";
- return \"fcmps %1,%2\";
+ return \"fcmps\\t%0, %1, %2\";
+ return \"fcmps\\t%1, %2\";
}"
[(set_attr "type" "fpcmp")])
@@ -633,8 +692,8 @@
"*
{
if (TARGET_V9)
- return \"fcmpd %0,%1,%2\";
- return \"fcmpd %1,%2\";
+ return \"fcmpd\\t%0, %1, %2\";
+ return \"fcmpd\\t%1, %2\";
}"
[(set_attr "type" "fpcmp")])
@@ -646,8 +705,8 @@
"*
{
if (TARGET_V9)
- return \"fcmpq %0,%1,%2\";
- return \"fcmpq %1,%2\";
+ return \"fcmpq\\t%0, %1, %2\";
+ return \"fcmpq\\t%1, %2\";
}"
[(set_attr "type" "fpcmp")])
@@ -704,7 +763,7 @@
(xor:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "register_operand" "")))
(set (match_operand:SI 0 "register_operand" "")
- (eq:DI (match_dup 3) (const_int 0)))]
+ (eq:SI (match_dup 3) (const_int 0)))]
"TARGET_ARCH64"
"{ operands[3] = gen_reg_rtx (DImode); }")
@@ -713,7 +772,7 @@
(xor:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "register_operand" "")))
(set (match_operand:SI 0 "register_operand" "")
- (ne:DI (match_dup 3) (const_int 0)))]
+ (ne:SI (match_dup 3) (const_int 0)))]
"TARGET_ARCH64"
"{ operands[3] = gen_reg_rtx (DImode); }")
@@ -722,7 +781,7 @@
(xor:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" "")))
(parallel [(set (match_operand:DI 0 "register_operand" "")
- (eq:SI (match_dup 3) (const_int 0)))
+ (eq:DI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
"TARGET_ARCH64"
"{ operands[3] = gen_reg_rtx (SImode); }")
@@ -732,7 +791,7 @@
(xor:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" "")))
(parallel [(set (match_operand:DI 0 "register_operand" "")
- (ne:SI (match_dup 3) (const_int 0)))
+ (ne:DI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
"TARGET_ARCH64"
"{ operands[3] = gen_reg_rtx (SImode); }")
@@ -787,7 +846,7 @@
DONE;
/* fall through */
}
- operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
@@ -840,7 +899,7 @@
DONE;
/* fall through */
}
- operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
(define_expand "sgt"
@@ -861,7 +920,7 @@
DONE;
/* fall through */
}
- operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
(define_expand "slt"
@@ -882,7 +941,7 @@
DONE;
/* fall through */
}
- operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
(define_expand "sge"
@@ -903,7 +962,7 @@
DONE;
/* fall through */
}
- operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
(define_expand "sle"
@@ -924,7 +983,7 @@
DONE;
/* fall through */
}
- operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
(define_expand "sgtu"
@@ -935,7 +994,7 @@
{
if (! TARGET_V9)
{
- rtx tem;
+ rtx tem, pat;
/* We can do ltu easily, so if both operands are registers, swap them and
do a LTU. */
@@ -947,7 +1006,10 @@
tem = sparc_compare_op0;
sparc_compare_op0 = sparc_compare_op1;
sparc_compare_op1 = tem;
- emit_insn (gen_sltu (operands[0]));
+ pat = gen_sltu (operands[0]);
+ if (pat == NULL_RTX)
+ FAIL;
+ emit_insn (pat);
DONE;
}
}
@@ -956,7 +1018,7 @@
if (gen_v9_scc (GTU, operands))
DONE;
}
- operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
(define_expand "sltu"
@@ -995,7 +1057,7 @@
{
if (! TARGET_V9)
{
- rtx tem;
+ rtx tem, pat;
/* We can do geu easily, so if both operands are registers, swap them and
do a GEU. */
@@ -1007,7 +1069,10 @@
tem = sparc_compare_op0;
sparc_compare_op0 = sparc_compare_op1;
sparc_compare_op1 = tem;
- emit_insn (gen_sgeu (operands[0]));
+ pat = gen_sgeu (operands[0]);
+ if (pat == NULL_RTX)
+ FAIL;
+ emit_insn (pat);
DONE;
}
}
@@ -1016,13 +1081,15 @@
if (gen_v9_scc (LEU, operands))
DONE;
}
- operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
+ FAIL;
}")
;; Now the DEFINE_INSNs for the scc cases.
;; The SEQ and SNE patterns are special because they can be done
-;; without any branching and do not involve a COMPARE.
+;; without any branching and do not involve a COMPARE. We want
+;; them to always use the splitz below so the results can be
+;; scheduled.
(define_insn "*snesi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1030,9 +1097,19 @@
(const_int 0)))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ "#"
+ [(set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ne:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0)))
+ (clobber (reg:CC 100))]
+ ""
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
+ "")
(define_insn "*neg_snesi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1040,56 +1117,126 @@
(const_int 0))))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ "#"
+ [(set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0))))
+ (clobber (reg:CC 100))]
+ ""
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
+ "")
(define_insn "*snesi_zero_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
- (ne:SI (match_operand:SI 1 "register_operand" "r")
+ (ne:DI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
"TARGET_ARCH64"
- "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
+ "#"
[(set_attr "type" "unary")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ne:DI (match_operand:SI 1 "register_operand" "")
+ (const_int 0)))
+ (clobber (reg:CC 100))]
+ "TARGET_ARCH64"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0)
+ (const_int 0))
+ (ltu:SI (reg:CC_NOOV 100)
+ (const_int 0)))))]
+ "")
+
(define_insn "*snedi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(ne:DI (match_operand:DI 1 "register_operand" "r")
(const_int 0)))]
"TARGET_ARCH64"
- "mov 0,%0\;movrnz %1,1,%0"
+ "#"
[(set_attr "type" "cmove")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ne:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ [(set (match_dup 0) (const_int 0))
+ (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
+ (const_int 0))
+ (const_int 1)
+ (match_dup 0)))]
+ "")
+
(define_insn "*neg_snedi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
(const_int 0))))]
"TARGET_ARCH64"
- "mov 0,%0\;movrnz %1,-1,%0"
+ "#"
[(set_attr "type" "cmove")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 0))))]
+ "TARGET_ARCH64"
+ [(set (match_dup 0) (const_int 0))
+ (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
+ (const_int 0))
+ (const_int -1)
+ (match_dup 0)))]
+ "")
+
(define_insn "*snedi_zero_trunc"
[(set (match_operand:SI 0 "register_operand" "=&r")
- (ne:DI (match_operand:DI 1 "register_operand" "r")
+ (ne:SI (match_operand:DI 1 "register_operand" "r")
(const_int 0)))]
"TARGET_ARCH64"
- "mov 0,%0\;movrnz %1,1,%0"
+ "#"
[(set_attr "type" "cmove")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ne:SI (match_operand:DI 1 "register_operand" "")
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ [(set (match_dup 0) (const_int 0))
+ (set (match_dup 0) (if_then_else:SI (ne:DI (match_dup 1)
+ (const_int 0))
+ (const_int 1)
+ (match_dup 0)))]
+ "")
+
(define_insn "*seqsi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ "#"
+ [(set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (eq:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0)))
+ (clobber (reg:CC 100))]
+ ""
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
+ "")
(define_insn "*neg_seqsi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1097,47 +1244,107 @@
(const_int 0))))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ "#"
+ [(set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0))))
+ (clobber (reg:CC 100))]
+ ""
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
+ "")
(define_insn "*seqsi_zero_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
- (eq:SI (match_operand:SI 1 "register_operand" "r")
+ (eq:DI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
"TARGET_ARCH64"
- "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
+ "#"
[(set_attr "type" "unary")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (eq:DI (match_operand:SI 1 "register_operand" "")
+ (const_int 0)))
+ (clobber (reg:CC 100))]
+ "TARGET_ARCH64"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0)
+ (const_int -1))
+ (ltu:SI (reg:CC_NOOV 100)
+ (const_int 0)))))]
+ "")
+
(define_insn "*seqdi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(eq:DI (match_operand:DI 1 "register_operand" "r")
(const_int 0)))]
"TARGET_ARCH64"
- "mov 0,%0\;movrz %1,1,%0"
+ "#"
[(set_attr "type" "cmove")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (eq:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ [(set (match_dup 0) (const_int 0))
+ (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
+ (const_int 0))
+ (const_int 1)
+ (match_dup 0)))]
+ "")
+
(define_insn "*neg_seqdi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
(const_int 0))))]
"TARGET_ARCH64"
- "mov 0,%0\;movrz %1,-1,%0"
+ "#"
[(set_attr "type" "cmove")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "")
+ (const_int 0))))]
+ "TARGET_ARCH64"
+ [(set (match_dup 0) (const_int 0))
+ (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
+ (const_int 0))
+ (const_int -1)
+ (match_dup 0)))]
+ "")
+
(define_insn "*seqdi_zero_trunc"
[(set (match_operand:SI 0 "register_operand" "=&r")
- (eq:DI (match_operand:DI 1 "register_operand" "r")
+ (eq:SI (match_operand:DI 1 "register_operand" "r")
(const_int 0)))]
"TARGET_ARCH64"
- "mov 0,%0\;movrz %1,1,%0"
+ "#"
[(set_attr "type" "cmove")
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (eq:SI (match_operand:DI 1 "register_operand" "")
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ [(set (match_dup 0) (const_int 0))
+ (set (match_dup 0) (if_then_else:SI (eq:DI (match_dup 1)
+ (const_int 0))
+ (const_int 1)
+ (match_dup 0)))]
+ "")
+
;; We can also do (x + (i == 0)) and related, so put them in.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
;; versions for v9.
@@ -1149,9 +1356,22 @@
(match_operand:SI 2 "register_operand" "r")))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;addx %2,0,%0"
+ "#"
[(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0))
+ (match_operand:SI 2 "register_operand" "")))
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
+ (match_dup 2)))]
+ "")
+
(define_insn "*x_minus_i_ne_0"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 2 "register_operand" "r")
@@ -1159,9 +1379,22 @@
(const_int 0))))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;subx %2,0,%0"
+ "#"
[(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (minus:SI (match_operand:SI 2 "register_operand" "")
+ (ne:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0))))
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (minus:SI (match_dup 2)
+ (ltu:SI (reg:CC 100) (const_int 0))))]
+ "")
+
(define_insn "*x_plus_i_eq_0"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
@@ -1169,9 +1402,22 @@
(match_operand:SI 2 "register_operand" "r")))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
+ "#"
[(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0))
+ (match_operand:SI 2 "register_operand" "")))
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
+ (match_dup 2)))]
+ "")
+
(define_insn "*x_minus_i_eq_0"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 2 "register_operand" "r")
@@ -1179,9 +1425,22 @@
(const_int 0))))
(clobber (reg:CC 100))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
+ "#"
[(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (minus:SI (match_operand:SI 2 "register_operand" "")
+ (eq:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 0))))
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (minus:SI (match_dup 2)
+ (geu:SI (reg:CC 100) (const_int 0))))]
+ "")
+
;; We can also do GEU and LTU directly, but these operate after a compare.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
;; versions for v9.
@@ -1190,15 +1449,17 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(ltu:SI (reg:CC 100) (const_int 0)))]
"! TARGET_LIVE_G0"
- "addx %%g0,0,%0"
- [(set_attr "type" "misc")])
+ "addx\\t%%g0, 0, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*neg_sltu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
"! TARGET_LIVE_G0"
- "subx %%g0,0,%0"
- [(set_attr "type" "misc")])
+ "subx\\t%%g0, 0, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*neg_sltu_minus_x"
@@ -1206,30 +1467,34 @@
(minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
(match_operand:SI 1 "arith_operand" "rI")))]
"! TARGET_LIVE_G0"
- "subx %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "subx\\t%%g0, %1, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*neg_sltu_plus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "arith_operand" "rI"))))]
"! TARGET_LIVE_G0"
- "subx %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "subx\\t%%g0, %1, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(geu:SI (reg:CC 100) (const_int 0)))]
"! TARGET_LIVE_G0"
- "subx %%g0,-1,%0"
- [(set_attr "type" "misc")])
+ "subx\\t%%g0, -1, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*neg_sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
"! TARGET_LIVE_G0"
- "addx %%g0,-1,%0"
- [(set_attr "type" "misc")])
+ "addx\\t%%g0, -1, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
@@ -1240,8 +1505,9 @@
(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "arith_operand" "rI")))]
"! TARGET_LIVE_G0"
- "addx %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "addx\\t%%g0, %1, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*sltu_plus_x_plus_y"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1249,64 +1515,57 @@
(plus:SI (match_operand:SI 1 "arith_operand" "%r")
(match_operand:SI 2 "arith_operand" "rI"))))]
""
- "addx %1,%2,%0")
+ "addx\\t%1, %2, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*x_minus_sltu"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "r")
(ltu:SI (reg:CC 100) (const_int 0))))]
""
- "subx %1,0,%0"
- [(set_attr "type" "unary")])
+ "subx\\t%1, 0, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*x_minus_y_minus_sltu"
[(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC 100) (const_int 0))))]
""
- "subx %1,%2,%0")
+ "subx\\t%r1, %2, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*x_minus_sltu_plus_y"
[(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 2 "arith_operand" "rI"))))]
""
- "subx %1,%2,%0")
+ "subx\\t%r1, %2, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*sgeu_plus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (geu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "register_operand" "r")))]
""
- "subx %1,-1,%0"
- [(set_attr "type" "unary")])
+ "subx\\t%1, -1, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "*x_minus_sgeu"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "r")
(geu:SI (reg:CC 100) (const_int 0))))]
""
- "addx %1,-1,%0"
- [(set_attr "type" "unary")])
-
-;; Now we have the generic scc insns.
-;; !v9: These will be done using a jump.
-;; v9: Use conditional moves which are defined elsewhere.
-;; We have to exclude the cases above, since we will not want combine to
-;; turn something that does not require a jump into something that does.
-
-(define_insn "*scc_si"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 2 "noov_compare_op"
- [(match_operand 1 "icc_or_fcc_reg_operand" "")
- (const_int 0)]))]
- ""
- "* return output_scc_insn (operands, insn); "
- [(set_attr "type" "multi")
- (set_attr "length" "3")])
+ "addx\\t%1, -1, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_split
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1324,15 +1583,6 @@
(match_dup 0)))]
"")
-(define_insn "*scc_di"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operator:DI 2 "noov_compare_op"
- [(match_operand 1 "icc_or_fcc_reg_operand" "")
- (const_int 0)]))]
- "TARGET_ARCH64"
- "* return output_scc_insn (operands, insn); "
- [(set_attr "type" "multi")
- (set_attr "length" "3")])
;; These control RTL generation for conditional jump insns
@@ -1526,6 +1776,7 @@
;; Now match both normal and inverted jump.
+;; XXX fpcmp nop braindamage
(define_insn "*normal_branch"
[(set (pc)
(if_then_else (match_operator 0 "noov_compare_op"
@@ -1541,6 +1792,7 @@
}"
[(set_attr "type" "branch")])
+;; XXX fpcmp nop braindamage
(define_insn "*inverted_branch"
[(set (pc)
(if_then_else (match_operator 0 "noov_compare_op"
@@ -1556,6 +1808,7 @@
}"
[(set_attr "type" "branch")])
+;; XXX fpcmp nop braindamage
(define_insn "*normal_fp_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
@@ -1572,6 +1825,7 @@
}"
[(set_attr "type" "branch")])
+;; XXX fpcmp nop braindamage
(define_insn "*inverted_fp_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
@@ -1588,6 +1842,7 @@
}"
[(set_attr "type" "branch")])
+;; XXX fpcmp nop braindamage
(define_insn "*normal_fpe_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
@@ -1604,6 +1859,7 @@
}"
[(set_attr "type" "branch")])
+;; XXX fpcmp nop braindamage
(define_insn "*inverted_fpe_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
@@ -1625,6 +1881,7 @@
;; There are no 32 bit brreg insns.
+;; XXX
(define_insn "*normal_int_branch_sp64"
[(set (pc)
(if_then_else (match_operator 0 "v9_regcmp_op"
@@ -1637,10 +1894,11 @@
{
return output_v9branch (operands[0], 1, 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence);
+ ! final_sequence, insn);
}"
[(set_attr "type" "branch")])
+;; XXX
(define_insn "*inverted_int_branch_sp64"
[(set (pc)
(if_then_else (match_operator 0 "v9_regcmp_op"
@@ -1653,673 +1911,972 @@
{
return output_v9branch (operands[0], 1, 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence);
+ ! final_sequence, insn);
}"
[(set_attr "type" "branch")])
-;; Esoteric move insns (lo_sum, high, pic).
-
-(define_insn "*lo_sum_si"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "immediate_operand" "in")))]
- ""
- ;; V9 needs "add" because of the code models. We still use "or" for v8
- ;; so we can compare the old compiler with the new.
- "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
- ;; Need to set length for this arith insn because operand2
- ;; is not an "arith_operand".
- [(set_attr "length" "1")])
-
-;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
-;; confuse them with real addresses.
-(define_insn "pic_lo_sum_si"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
- "flag_pic"
- ;; V9 needs "add" because of the code models. We still use "or" for v8
- ;; so we can compare the old compiler with the new.
- "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
- ;; Need to set length for this arith insn because operand2
- ;; is not an "arith_operand".
- [(set_attr "length" "1")])
-
-;; The PIC version of sethi must appear before the non-pic case so that
-;; the unspec will not be matched as part of the operand.
-;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
-;; confuse them with real addresses.
-(define_insn "pic_sethi_si"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
- "flag_pic && check_pic (1)"
- "sethi %%hi(%a1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
-
-(define_insn "pic_lo_sum_di"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:DI 1 "register_operand" "r")
- (unspec:SI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
- "TARGET_ARCH64 && flag_pic"
- "add %1,%%lo(%a2),%0"
- [(set_attr "length" "1")])
-
-(define_insn "pic_sethi_di"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
- "TARGET_ARCH64 && flag_pic && check_pic (1)"
- "sethi %%hi(%a1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+;; Load program counter insns.
(define_insn "get_pc"
[(clobber (reg:SI 15))
(set (match_operand 0 "register_operand" "=r")
(unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
"flag_pic && REGNO (operands[0]) == 23"
- "sethi %%hi(%a1-4),%0\;call %a2\;add %0,%%lo(%a1+4),%0"
+ "sethi\\t%%hi(%a1-4), %0\\n\\tcall\\t%a2\\n\\tadd\\t%0, %%lo(%a1+4), %0"
[(set_attr "length" "3")])
-(define_insn "get_pc_via_rdpc"
- [(set (match_operand 0 "register_operand" "=r") (pc))]
- "TARGET_V9"
- "rd %%pc,%0"
- [(set_attr "type" "move")])
-
-(define_insn "*sethi_hi"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (high:HI (match_operand 1 "" "")))]
- "check_pic (1)"
- "sethi %%hi(%a1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+;; Currently unused...
+;; (define_insn "get_pc_via_rdpc"
+;; [(set (match_operand 0 "register_operand" "=r") (pc))]
+;; "TARGET_V9"
+;; "rd\\t%%pc, %0"
+;; [(set_attr "type" "move")])
-;; This must appear after the PIC sethi so that the PIC unspec will not
-;; be matched as part of the operand.
-(define_insn "*sethi_si"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (match_operand 1 "" "")))]
- "check_pic (1)"
- "sethi %%hi(%a1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+
+;; Move instructions
-(define_insn "*lo_sum_di_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "immediate_operand" "in")))]
- "! TARGET_ARCH64"
- "*
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
{
- /* Don't output a 64 bit constant, since we can't trust the assembler to
- handle it correctly. */
- if (GET_CODE (operands[2]) == CONST_DOUBLE)
- operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
- else if (GET_CODE (operands[2]) == CONST_INT
- && HOST_BITS_PER_WIDE_INT > 32
- && INTVAL (operands[2]) > 0xffffffff)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
+ /* Working with CONST_INTs is easier, so convert
+ a double if needed. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xff);
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ /* And further, we know for all QI cases that only the
+ low byte is significant, which we can always process
+ in a single insn. So mask it now. */
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
+ }
- return \"or %L1,%%lo(%a2),%L0\";
-}"
- ;; Need to set length for this arith insn because operand2
- ;; is not an "arith_operand".
- [(set_attr "length" "1")])
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ /* This checks TARGET_LIVE_G0 for us. */
+ if (reg_or_0_operand (operands[1], QImode))
+ goto movqi_is_ok;
-;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add?
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (QImode, operands[1]);
+ }
+ }
-(define_insn "*lo_sum_di_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "immediate_operand" "in")))]
- "TARGET_ARCH64"
- "*
-{
- /* Don't output a 64 bit constant, since we can't trust the assembler to
- handle it correctly. */
- if (GET_CODE (operands[2]) == CONST_DOUBLE)
- operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
- else if (GET_CODE (operands[2]) == CONST_INT
- && HOST_BITS_PER_WIDE_INT > 32
- && INTVAL (operands[2]) > 0xffffffff)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
-
- /* Note that we use add here. This is important because Medium/Anywhere
- code model support depends on it. */
- return \"add %1,%%lo(%a2),%0\";
-}"
- ;; Need to set length for this arith insn because operand2
- ;; is not an "arith_operand".
- [(set_attr "length" "1")])
+ /* Fixup PIC cases. */
+ if (flag_pic)
+ {
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], QImode, 0);
-(define_insn "*sethi_di_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand 1 "" "")))]
- "! TARGET_ARCH64 && check_pic (1)"
- "*
+ if (symbolic_operand (operands[1], QImode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ QImode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ goto movqi_is_ok;
+ }
+ }
+
+ /* All QI constants require only one insn, so proceed. */
+
+ movqi_is_ok:
+ ;
+}")
+
+(define_insn "*movqi_insn"
+ [(set (match_operand:QI 0 "general_operand" "=r,r,m")
+ (match_operand:QI 1 "input_operand" "rI,m,rJ"))]
+ "(register_operand (operands[0], QImode)
+ || reg_or_0_operand (operands[1], QImode))"
+ "@
+ mov\\t%1, %0
+ ldub\\t%1, %0
+ stb\\t%r1, %0"
+ [(set_attr "type" "move,load,store")
+ (set_attr "length" "1")])
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
{
- rtx op0 = operands[0];
- rtx op1 = operands[1];
+ /* Working with CONST_INTs is easier, so convert
+ a double if needed. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- if (GET_CODE (op1) == CONST_INT)
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
{
- operands[0] = operand_subword (op0, 1, 0, DImode);
- output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
+ /* This checks TARGET_LIVE_G0 for us. */
+ if (reg_or_0_operand (operands[1], HImode))
+ goto movhi_is_ok;
- operands[0] = operand_subword (op0, 0, 0, DImode);
- if (INTVAL (op1) < 0)
- return \"mov -1,%0\";
- else
- return \"mov 0,%0\";
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (HImode, operands[1]);
+ }
}
- else if (GET_CODE (op1) == CONST_DOUBLE)
+
+ /* Fixup PIC cases. */
+ if (flag_pic)
{
- operands[0] = operand_subword (op0, 1, 0, DImode);
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
- output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], HImode, 0);
- operands[0] = operand_subword (op0, 0, 0, DImode);
- operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
- return singlemove_string (operands);
+ if (symbolic_operand (operands[1], HImode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ HImode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ goto movhi_is_ok;
+ }
}
- else
- abort ();
- return \"\";
-}"
- [(set_attr "type" "move")
- (set_attr "length" "2")])
-;;; ??? This pattern originally clobbered a scratch register. However, this
-;;; is invalid, the movdi pattern may not use a temp register because it
-;;; may be called from reload to reload a DImode value. In that case, we
-;;; end up with a scratch register that never gets allocated. To avoid this,
-;;; we use global register 1 which is never otherwise used by gcc as a temp.
-;;; The correct solution here might be to force DImode constants to memory,
-;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg
-;;; 1 will then no longer need to be considered a fixed reg.
-
-(define_expand "sethi_di_sp64"
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (high:DI (match_operand 1 "general_operand" "")))
- (clobber (reg:DI 1))])]
+ /* This makes sure we will not get rematched due to splittage. */
+ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], HImode))
+ ;
+ else if (CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && GET_CODE (operands[1]) != LO_SUM)
+ {
+ sparc_emit_set_const32 (operands[0], operands[1]);
+ DONE;
+ }
+ movhi_is_ok:
+ ;
+}")
+
+(define_insn "*movhi_const64_special"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (match_operand:HI 1 "const64_high_operand" ""))]
"TARGET_ARCH64"
- "")
+ "sethi\\t%%hi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
-(define_insn "*sethi_di_sp64_const"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand 1 "const_double_operand" "")))
- (clobber (reg:DI 1))]
- "TARGET_ARCH64 && check_pic (1)"
- "*
+(define_insn "*movhi_insn"
+ [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
+ (match_operand:HI 1 "input_operand" "rI,K,m,rJ"))]
+ "(register_operand (operands[0], HImode)
+ || reg_or_0_operand (operands[1], HImode))"
+ "@
+ mov\\t%1, %0
+ sethi\\t%%hi(%a1), %0
+ lduh\\t%1, %0
+ sth\\t%r1, %0"
+ [(set_attr "type" "move,move,load,store")
+ (set_attr "length" "1")])
+
+;; We always work with constants here.
+(define_insn "*movhi_lo_sum"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (ior:HI (match_operand:HI 1 "arith_operand" "%r")
+ (match_operand:HI 2 "arith_operand" "I")))]
+ ""
+ "or\\t%1, %2, %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
{
-#if HOST_BITS_PER_WIDE_INT == 32
- rtx high, low;
-
- split_double (operands[1], &high, &low);
+ /* Working with CONST_INTs is easier, so convert
+ a double if needed. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- if (high == const0_rtx)
- {
- operands[1] = low;
- output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
- }
- else
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
{
- operands[1] = high;
- output_asm_insn (singlemove_string (operands), operands);
+ /* This checks TARGET_LIVE_G0 for us. */
+ if (reg_or_0_operand (operands[1], SImode))
+ goto movsi_is_ok;
- operands[1] = low;
- output_asm_insn (\"sllx %0,32,%0\", operands);
- if (low != const0_rtx)
- output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (SImode, operands[1]);
+ }
}
-#else
- rtx op = operands[1];
- if (! SPARC_SETHI_P (INTVAL(op)))
+ /* Fixup PIC cases. */
+ if (flag_pic)
{
- operands[1] = GEN_INT (INTVAL (op) >> 32);
- output_asm_insn (singlemove_string (operands), operands);
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], SImode, 0);
+
+ if (GET_CODE (operands[1]) == LABEL_REF)
+ {
+ /* shit */
+ emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
+ DONE;
+ }
- output_asm_insn (\"sllx %0,32,%0\", operands);
- if (INTVAL (op) & 0xffffffff)
+ if (symbolic_operand (operands[1], SImode))
{
- operands[1] = GEN_INT (INTVAL (op) & 0xffffffff);
- output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
+ operands[1] = legitimize_pic_address (operands[1],
+ SImode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ goto movsi_is_ok;
}
}
- else
+
+ /* If we are trying to toss an integer constant into the
+ FPU registers, force it into memory. */
+ if (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
+ && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
+ && CONSTANT_P (operands[1]))
+ operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+ operands[1]));
+
+ /* This makes sure we will not get rematched due to splittage. */
+ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
+ ;
+ else if (CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && GET_CODE (operands[1]) != LO_SUM)
{
- output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
+ sparc_emit_set_const32 (operands[0], operands[1]);
+ DONE;
}
-#endif
+ movsi_is_ok:
+ ;
+}")
- return \"\";
-}"
- [(set_attr "type" "move")
- (set_attr "length" "5")])
-
-;; Most of the required support for the various code models is here.
-;; We can do this because sparcs need the high insn to load the address. We
-;; just need to get high to do the right thing for each code model. Then each
-;; uses the same "%X+%lo(...)" in the load/store insn, though in the case of
-;; the medium/middle code model "%lo" is written "%l44".
-
-;; When TARGET_CM_MEDLOW, assume that the upper 32 bits of symbol addresses are
-;; always 0.
-;; When TARGET_CM_MEDMID, the executable must be in the low 16 TB of memory.
-;; This corresponds to the low 44 bits, and the %[hml]44 relocs are used.
-;; ??? Not implemented yet.
-;; When TARGET_CM_EMBMEDANY, the text and data segments have a maximum size of
-;; 31 bits and may be located anywhere. EMBMEDANY_BASE_REG contains the start
-;; address of the data segment, currently %g4.
-;; When TARGET_CM_MEDANY, the text and data segments have a maximum size of 31
-;; bits and may be located anywhere. The maximum offset from any instruction
-;; to the label _GLOBAL_OFFSET_TABLE_ is 31 bits.
+;; Special LIVE_G0 pattern to obtain zero in a register.
+(define_insn "*movsi_zero_liveg0"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "zero_operand" "J"))]
+ "TARGET_LIVE_G0"
+ "and\\t%0, 0, %0"
+ [(set_attr "type" "binary")
+ (set_attr "length" "1")])
-(define_insn "*sethi_di_medlow"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand 1 "" "")))
- ;; The clobber is here because emit_move_sequence assumes the worst case.
- (clobber (reg:DI 1))]
- "TARGET_CM_MEDLOW && check_pic (1)"
- "sethi %%hi(%a1),%0"
+;; This is needed to show CSE exactly which bits are set
+;; in a 64-bit register by sethi instructions.
+(define_insn "*movsi_const64_special"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "const64_high_operand" ""))]
+ "TARGET_ARCH64"
+ "sethi\\t%%hi(%a1), %0"
[(set_attr "type" "move")
(set_attr "length" "1")])
-(define_insn "*sethi_di_medium_pic"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand 1 "sp64_medium_pic_operand" "")))]
- "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
- "sethi %%hi(%a1),%0"
- [(set_attr "type" "move")
+(define_insn "*movsi_insn"
+ [(set (match_operand:SI 0 "general_operand" "=r,f,r,r,r,f,m,m,d")
+ (match_operand:SI 1 "input_operand" "rI,!f,K,J,m,!m,rJ,!f,J"))]
+ "(register_operand (operands[0], SImode)
+ || reg_or_0_operand (operands[1], SImode))"
+ "@
+ mov\\t%1, %0
+ fmovs\\t%1, %0
+ sethi\\t%%hi(%a1), %0
+ clr\\t%0
+ ld\\t%1, %0
+ ld\\t%1, %0
+ st\\t%r1, %0
+ st\\t%1, %0
+ fzeros\\t%0"
+ [(set_attr "type" "move,fpmove,move,move,load,fpload,store,fpstore,fpmove")
(set_attr "length" "1")])
-;; WARNING: %0 gets %hi(%1)+%g4.
-;; You cannot OR in %lo(%1), it must be added in.
+(define_insn "*movsi_lo_sum"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "in")))]
+ ""
+ "or\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
-(define_insn "*sethi_di_embmedany_data"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand 1 "data_segment_operand" "")))
- ;; The clobber is here because emit_move_sequence assumes the worst case.
- (clobber (reg:DI 1))]
- "TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi %%hi(%a1),%0; add %0,%_,%0"
+(define_insn "*movsi_high"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (match_operand:SI 1 "immediate_operand" "in")))]
+ ""
+ "sethi\\t%%hi(%a1), %0"
[(set_attr "type" "move")
- (set_attr "length" "2")])
+ (set_attr "length" "1")])
-(define_insn "*sethi_di_embmedany_text"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand 1 "text_segment_operand" "")))
- ;; The clobber is here because emit_move_sequence assumes the worst case.
- (clobber (reg:DI 1))]
- "TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
+;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
+;; so that CSE won't optimize the address computation away.
+(define_insn "movsi_lo_sum_pic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
+ "flag_pic"
+ "or\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "movsi_high_pic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
+ "flag_pic && check_pic (1)"
+ "sethi\\t%%hi(%a1), %0"
[(set_attr "type" "move")
- (set_attr "length" "5")])
-
-;; Move instructions
+ (set_attr "length" "1")])
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
+(define_expand "movsi_pic_label_ref"
+ [(set (match_dup 3) (high:SI
+ (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+ (match_dup 2)] 5)))
+ (set (match_dup 4) (lo_sum:SI (match_dup 3)
+ (unspec:SI [(match_dup 1) (match_dup 2)] 5)))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_dup 5) (match_dup 4)))]
+ "flag_pic"
"
{
- if (emit_move_sequence (operands, QImode))
- DONE;
+ current_function_uses_pic_offset_table = 1;
+ operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
+ operands[3] = gen_reg_rtx (SImode);
+ operands[4] = gen_reg_rtx (SImode);
+ operands[5] = pic_offset_table_rtx;
}")
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
- (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
- "! TARGET_LIVE_G0
- && (register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)
- || operands[1] == const0_rtx)"
- "@
- mov %1,%0
- sethi %%hi(%a1),%0
- ldub %1,%0
- stb %r1,%0"
- [(set_attr "type" "move,move,load,store")
+(define_insn "*movsi_high_pic_label_ref"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI
+ (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+ (match_operand:SI 2 "" "")] 5)))]
+ "flag_pic"
+ "sethi\\t%%hi(%a2-(%a1-.)), %0"
+ [(set_attr "type" "move")
(set_attr "length" "1")])
-(define_insn "*movqi_insn_liveg0"
- [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
- (match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))]
- "TARGET_LIVE_G0
- && (register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode))"
- "@
- mov %1,%0
- and %0,0,%0
- and %0,0,%0\;or %0,%1,%0
- sethi %%hi(%a1),%0
- ldub %1,%0
- stb %1,%0"
- [(set_attr "type" "move,move,move,move,load,store")
- (set_attr "length" "1,1,2,1,1,1")])
-
-(define_insn "*lo_sum_qi"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
- (match_operand 2 "immediate_operand" "in")) 0))]
- ""
- "or %1,%%lo(%a2),%0"
- [(set_attr "length" "1")])
-
-(define_insn "*store_qi"
- [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
- (match_operand:QI 1 "reg_or_0_operand" "rJ"))
- (clobber (match_scratch:SI 2 "=&r"))]
- "(reload_completed || reload_in_progress)
- && ! TARGET_PTR64"
- "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
- [(set_attr "type" "store")
- (set_attr "length" "2")])
+(define_insn "*movsi_lo_sum_pic_label_ref"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
+ (match_operand:SI 3 "" "")] 5)))]
+ "flag_pic"
+ "or\\t%1, %%lo(%a3-(%a2-.)), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
""
"
{
- if (emit_move_sequence (operands, HImode))
- DONE;
+ /* Where possible, convert CONST_DOUBLE into a CONST_INT. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE
+#if HOST_BITS_PER_WIDE_INT == 32
+ && ((CONST_DOUBLE_HIGH (operands[1]) == 0
+ && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
+ || (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
+ && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
+#endif
+ )
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+
+ /* Handle MEM cases first. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ /* If it's a REG, we can always do it.
+ The const zero case is more complex, on v9
+ we can always perform it. */
+ if (register_operand (operands[1], DImode)
+ || (TARGET_ARCH64
+ && (operands[1] == const0_rtx)))
+ goto movdi_is_ok;
+
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (DImode, operands[1]);
+ }
+ }
+
+ if (flag_pic)
+ {
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], DImode, 0);
+
+ if (GET_CODE (operands[1]) == LABEL_REF)
+ {
+ if (! TARGET_ARCH64)
+ abort ();
+ emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
+ DONE;
+ }
+
+ if (symbolic_operand (operands[1], DImode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ DImode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ goto movdi_is_ok;
+ }
+ }
+
+ /* If we are trying to toss an integer constant into the
+ FPU registers, force it into memory. */
+ if (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
+ && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
+ && CONSTANT_P (operands[1]))
+ operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+ operands[1]));
+
+ /* This makes sure we will not get rematched due to splittage. */
+ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
+ ;
+ else if (TARGET_ARCH64
+ && CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && GET_CODE (operands[1]) != LO_SUM)
+ {
+ sparc_emit_set_const64 (operands[0], operands[1]);
+ DONE;
+ }
+
+ movdi_is_ok:
+ ;
}")
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
- (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
- "! TARGET_LIVE_G0
- && (register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)
- || operands[1] == const0_rtx)"
+;; Be careful, fmovd does not exist when !arch64.
+;; We match MEM moves directly when we have correct even
+;; numbered registers, but fall into splits otherwise.
+;; The constraint ordering here is really important to
+;; avoid insane problems in reload, especially for patterns
+;; of the form:
+;;
+;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
+;; (const_int -5016)))
+;; (reg:DI 2 %g2))
+;;
+(define_insn "*movdi_insn_sp32"
+ [(set (match_operand:DI 0 "general_operand" "=T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ (match_operand:DI 1 "input_operand" "U,T,r,o,i,r,f,T,o,f,f"))]
+ "! TARGET_ARCH64 &&
+ (register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
"@
- mov %1,%0
- sethi %%hi(%a1),%0
- lduh %1,%0
- sth %r1,%0"
- [(set_attr "type" "move,move,load,store")
+ std\\t%1, %0
+ ldd\\t%1, %0
+ #
+ #
+ #
+ #
+ std\\t%1, %0
+ ldd\\t%1, %0
+ #
+ #
+ #"
+ [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "1,1,2,2,2,2,1,1,2,2,2")])
+
+;; The following are generated by sparc_emit_set_const64
+(define_insn "*movdi_sp64_dbl"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (match_operand:DI 1 "const64_operand" ""))]
+ "(TARGET_ARCH64
+ && HOST_BITS_PER_WIDE_INT != 64)"
+ "mov\\t%1, %0"
+ [(set_attr "type" "move")
(set_attr "length" "1")])
-(define_insn "*movhi_insn_liveg0"
- [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
- (match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))]
- "TARGET_LIVE_G0
- && (register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode))"
- "@
- mov %1,%0
- and %0,0,%0
- and %0,0,%0\;or %0,%1,%0
- sethi %%hi(%a1),%0
- lduh %1,%0
- sth %1,%0"
- [(set_attr "type" "move,move,move,move,load,store")
- (set_attr "length" "1,1,2,1,1,1")])
-
-(define_insn "*lo_sum_hi"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
- (match_operand 2 "immediate_operand" "in")))]
- ""
- "or %1,%%lo(%a2),%0"
- [(set_attr "length" "1")])
+;; This is needed to show CSE exactly which bits are set
+;; in a 64-bit register by sethi instructions.
+(define_insn "*movdi_const64_special"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (match_operand:DI 1 "const64_high_operand" ""))]
+ "TARGET_ARCH64"
+ "sethi\\t%%hi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
-(define_insn "*store_hi"
- [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
- (match_operand:HI 1 "reg_or_0_operand" "rJ"))
- (clobber (match_scratch:SI 2 "=&r"))]
- "(reload_completed || reload_in_progress)
- && ! TARGET_PTR64"
- "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
- [(set_attr "type" "store")
- (set_attr "length" "2")])
+(define_insn "*movdi_insn_sp64"
+ [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,m,?e,?e,?m,b")
+ (match_operand:DI 1 "input_operand" "rI,K,J,m,rJ,e,m,e,J"))]
+ "TARGET_ARCH64 &&
+ (register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))"
+ "@
+ mov\\t%1, %0
+ sethi\\t%%hi(%a1), %0
+ clr\\t%0
+ ldx\\t%1, %0
+ stx\\t%r1, %0
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0
+ fzero\\t%0"
+ [(set_attr "type" "move,move,move,load,store,fpmove,fpload,fpstore,fpmove")
+ (set_attr "length" "1")])
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
+(define_expand "movdi_pic_label_ref"
+ [(set (match_dup 3) (high:DI
+ (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
+ (match_dup 2)] 5)))
+ (set (match_dup 4) (lo_sum:DI (match_dup 3)
+ (unspec:DI [(match_dup 1) (match_dup 2)] 5)))
+ (set (match_operand:DI 0 "register_operand" "=r")
+ (minus:DI (match_dup 5) (match_dup 4)))]
+ "TARGET_ARCH64 && flag_pic"
"
{
- if (emit_move_sequence (operands, SImode))
- DONE;
+ current_function_uses_pic_offset_table = 1;
+ operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+ operands[5] = pic_offset_table_rtx;
}")
-;; We must support both 'r' and 'f' registers here, because combine may
-;; convert SFmode hard registers to SImode hard registers when simplifying
-;; subreg sets.
+(define_insn "*movdi_high_pic_label_ref"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI
+ (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
+ (match_operand:DI 2 "" "")] 5)))]
+ "TARGET_ARCH64 && flag_pic"
+ "sethi\\t%%hi(%a2-(%a1-.)), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
-;; We cannot combine the similar 'r' and 'f' constraints, because it causes
-;; problems with register allocation. Reload might try to put an integer
-;; in an fp register, or an fp number is an integer register.
+(define_insn "*movdi_lo_sum_pic_label_ref"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
+ (match_operand:DI 3 "" "")] 5)))]
+ "TARGET_ARCH64 && flag_pic"
+ "or\\t%1, %%lo(%a3-(%a2-.)), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q,d")
- (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f,J"))]
- "! TARGET_LIVE_G0
- && (register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)
- || operands[1] == const0_rtx)
- && (GET_CODE (operands[0]) != REG || ! CONSTANT_P (operands[1])
- || REGNO (operands[0]) < 32
- || REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)"
- "@
- mov %1,%0
- fmovs %1,%0
- sethi %%hi(%a1),%0
- ld %1,%0
- ld %1,%0
- st %r1,%0
- st %1,%0
- fzeros %0"
- [(set_attr "type" "move,fpmove,move,load,fpload,store,fpstore,fpmove")
- (set_attr "length" "1")])
-
-(define_insn "*movsi_insn_liveg0"
- [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q")
- (match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))]
- "TARGET_LIVE_G0
- && (register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode))"
- "@
- mov %1,%0
- and %0,0,%0
- and %0,0,%0\;or %0,%1,%0
- fmovs %1,%0
- sethi %%hi(%a1),%0
- ld %1,%0
- ld %1,%0
- st %1,%0
- st %1,%0"
- [(set_attr "type" "move,move,move,fpmove,move,load,fpload,store,fpstore")
- (set_attr "length" "1,1,2,1,1,1,1,1,1")])
-
-(define_insn "*store_si"
- [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
- (match_operand:SI 1 "reg_or_0_operand" "rJ"))
- (clobber (match_scratch:SI 2 "=&r"))]
- "(reload_completed || reload_in_progress)
- && ! TARGET_PTR64"
- "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
- [(set_attr "type" "store")
- (set_attr "length" "2")])
+;; Sparc-v9 code model support insns. See sparc_emit_set_symbolic_const64
+;; in sparc.c to see what is going on here... PIC stuff comes first.
-(define_expand "movdi"
- [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
+(define_insn "movdi_lo_sum_pic"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
+ "TARGET_ARCH64 && flag_pic"
+ "or\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "movdi_high_pic"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand 1 "" "")] 0)))]
+ "TARGET_ARCH64 && flag_pic && check_pic (1)"
+ "sethi\\t%%hi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "*sethi_di_medlow_embmedany_pic"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
+ "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
+ "sethi\\t%%lo(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "*sethi_di_medlow"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
+ "TARGET_CM_MEDLOW && check_pic (1)"
+ "sethi\\t%%hi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "*losum_di_medlow"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "symbolic_operand" "")))]
+ "TARGET_CM_MEDLOW"
+ "or\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "seth44"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 6)))]
+ "TARGET_CM_MEDMID"
+ "sethi\\t%%h44(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "setm44"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 7)))]
+ "TARGET_CM_MEDMID"
+ "or\\t%1, %%m44(%a2), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "setl44"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "symbolic_operand" "")))]
+ "TARGET_CM_MEDMID"
+ "or\\t%1, %%l44(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "sethh"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 9)))]
+ "TARGET_CM_MEDANY"
+ "sethi\\t%%hh(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "setlm"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 10)))]
+ "TARGET_CM_MEDANY"
+ "sethi\\t%%lm(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "sethm"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 18)))]
+ "TARGET_CM_MEDANY"
+ "or\\t%1, %%hm(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "setlo"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "symbolic_operand" "")))]
+ "TARGET_CM_MEDANY"
+ "or\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "embmedany_sethi"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] 11)))]
+ "TARGET_CM_EMBMEDANY && check_pic (1)"
+ "sethi\\t%%hi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "embmedany_losum"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "data_segment_operand" "")))]
+ "TARGET_CM_EMBMEDANY"
+ "add\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "embmedany_brsum"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")] 11))]
+ "TARGET_CM_EMBMEDANY"
+ "add\\t%1, %_, %0"
+ [(set_attr "length" "1")])
+
+(define_insn "embmedany_textuhi"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 13)))]
+ "TARGET_CM_EMBMEDANY && check_pic (1)"
+ "sethi\\t%%uhi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "embmedany_texthi"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 14)))]
+ "TARGET_CM_EMBMEDANY && check_pic (1)"
+ "sethi\\t%%hi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "embmedany_textulo"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] 15)))]
+ "TARGET_CM_EMBMEDANY"
+ "or\\t%1, %%ulo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+(define_insn "embmedany_textlo"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "text_segment_operand" "")))]
+ "TARGET_CM_EMBMEDANY"
+ "or\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
+
+;; Now some patterns to help reload out a bit.
+(define_expand "reload_indi"
+ [(parallel [(match_operand:DI 0 "register_operand" "=r")
+ (match_operand:DI 1 "immediate_operand" "")
+ (match_operand:TI 2 "register_operand" "=&r")])]
+ "(TARGET_CM_MEDANY
+ || TARGET_CM_EMBMEDANY)
+ && ! flag_pic"
"
{
- if (emit_move_sequence (operands, DImode))
- DONE;
+ sparc_emit_set_symbolic_const64 (operands[0], operands[1],
+ gen_rtx_REG (DImode, REGNO (operands[2])));
+ DONE;
}")
-;; 32 bit V9 movdi is like regular 32 bit except: a 64 bit zero can be stored
-;; to aligned memory with a single instruction, the ldd/std instructions
-;; are not used, and constants can not be moved to floating point registers.
-
-(define_insn "*movdi_sp32_v9"
- [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,Q,r,r,?e,?e,?Q,?b")
- (match_operand:DI 1 "general_operand" "r,J,r,Q,i,e,Q,e,J"))]
- "TARGET_V9 && ! TARGET_ARCH64
- && (register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)
- || operands[1] == const0_rtx)
- && (GET_CODE (operands[0]) != REG || ! CONSTANT_P (operands[1])
- || REGNO (operands[0]) < 32
- || REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)"
- "*
+(define_expand "reload_outdi"
+ [(parallel [(match_operand:DI 0 "register_operand" "=r")
+ (match_operand:DI 1 "immediate_operand" "")
+ (match_operand:TI 2 "register_operand" "=&r")])]
+ "(TARGET_CM_MEDANY
+ || TARGET_CM_EMBMEDANY)
+ && ! flag_pic"
+ "
{
- if (which_alternative == 1)
- return \"stx %%g0,%0\";
- if (which_alternative == 8)
- return \"fzero %0\";
- if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
- return output_fp_move_double (operands);
- return output_move_double (operands);
-}"
- [(set_attr "type" "move,store,store,load,multi,fp,fpload,fpstore,fpmove")
- (set_attr "length" "2,1,3,3,3,2,3,3,1")])
+ sparc_emit_set_symbolic_const64 (operands[0], operands[1],
+ gen_rtx_REG (DImode, REGNO (operands[2])));
+ DONE;
+}")
-;; SPARC V9 deprecates std. Split it here.
+;; Split up putting CONSTs and REGs into DI regs when !arch64
(define_split
- [(set (match_operand:DI 0 "memory_operand" "=m")
- (match_operand:DI 1 "register_operand" "r"))]
- "TARGET_V9 && ! TARGET_ARCH64 && reload_completed
- && REGNO (operands[1]) < 32 && ! MEM_VOLATILE_P (operands[0])
- && offsettable_memref_p (operands[0])"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
- "operands[3] = gen_highpart (SImode, operands[1]);
- operands[5] = gen_lowpart (SImode, operands[1]);
- operands[4] = adj_offsettable_operand (operands[0], 4);
- PUT_MODE (operands[4], SImode);
- operands[2] = copy_rtx (operands[0]);
- PUT_MODE (operands[2], SImode);")
-
-;; Split register to register moves.
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "const_int_operand" ""))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(clobber (const_int 0))]
+ "
+{
+ emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
+ (INTVAL (operands[1]) < 0) ?
+ constm1_rtx :
+ const0_rtx));
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ operands[1]));
+ DONE;
+}")
+
(define_split
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "arith_double_operand" "rIN"))]
- "! TARGET_ARCH64
- && REGNO (operands[0]) < 32
- && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 32
- && ! reg_overlap_mentioned_p (operands[0], operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
- "operands[2] = gen_highpart (SImode, operands[0]);
- operands[3] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);
- operands[5] = gen_lowpart (SImode, operands[1]);")
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "const_double_operand" ""))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(clobber (const_int 0))]
+ "
+{
+ emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
+ GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
-(define_insn "*movdi_sp32"
- [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")
- (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]
- "! TARGET_V9
- && (register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)
- || operands[1] == const0_rtx)"
- "*
+ /* Slick... but this trick loses if this subreg constant part
+ can be done in one insn. */
+ if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
+ && !(SPARC_SETHI_P (CONST_DOUBLE_HIGH (operands[1]))
+ || SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
+ {
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[0])));
+ }
+ else
+ {
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
+ }
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" ""))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(clobber (const_int 0))]
+ "
{
- if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
- return output_fp_move_double (operands);
- return output_move_double (operands);
-}"
- [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")
- (set_attr "length" "2,1,1,3,3,3,2,3,3")])
-
-;;; ??? The trick used below can be extended to load any negative 32 bit
-;;; constant in two instructions. Currently the compiler will use HIGH/LO_SUM
-;;; for anything not matching the HIK constraints, which results in 5
-;;; instructions. Positive 32 bit constants can be loaded in the obvious way
-;;; with sethi/ori. To extend the trick, in the xor instruction, use
-;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0
-;;; This needs the original value of operands[1], not the inverted value.
-
-(define_insn "*movdi_sp64_insn"
- [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?e,?e,?Q")
- (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,e,Q,e"))]
- "TARGET_ARCH64
- && (register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)
- || operands[1] == const0_rtx)"
- "*
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ if (GET_CODE (set_dest) == SUBREG)
+ set_dest = alter_subreg (set_dest);
+ if (GET_CODE (set_src) == SUBREG)
+ set_src = alter_subreg (set_src);
+
+ dest1 = gen_highpart (SImode, set_dest);
+ dest2 = gen_lowpart (SImode, set_dest);
+ src1 = gen_highpart (SImode, set_src);
+ src2 = gen_lowpart (SImode, set_src);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movsi (dest2, src2));
+ emit_insn (gen_movsi (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_movsi (dest1, src1));
+ emit_insn (gen_movsi (dest2, src2));
+ }
+ DONE;
+}")
+
+;; Now handle the cases of memory moves from/to non-even
+;; DI mode register pairs.
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "memory_operand" ""))]
+ "(! TARGET_ARCH64
+ && reload_completed
+ && sparc_splitdi_legitimate (operands[0], operands[1]))"
+ [(clobber (const_int 0))]
+ "
{
- switch (which_alternative)
+ rtx word0 = change_address (operands[1], SImode, NULL_RTX);
+ rtx word1 = change_address (operands[1], SImode,
+ plus_constant_for_output (XEXP (word0, 0), 4));
+ rtx high_part = gen_highpart (SImode, operands[0]);
+ rtx low_part = gen_lowpart (SImode, operands[0]);
+
+ if (reg_overlap_mentioned_p (high_part, word1))
{
- case 0:
- return \"mov %1,%0\";
- case 1:
- /* Sethi does not sign extend, so we must use a little trickery
- to use it for negative numbers. Invert the constant before
- loading it in, then use a xor immediate to invert the loaded bits
- (along with the upper 32 bits) to the desired constant. This
- works because the sethi and immediate fields overlap. */
-
- if ((INTVAL (operands[1]) & 0x80000000) == 0)
- return \"sethi %%hi(%a1),%0\";
- else
- {
- operands[1] = GEN_INT (~INTVAL (operands[1]));
- output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
- /* The low 10 bits are already zero, but invert the rest.
- Assemblers don't accept 0x1c00, so use -0x400 instead. */
- return \"xor %0,-0x400,%0\";
- }
- case 2:
- return \"ldx %1,%0\";
- case 3:
- return \"stx %r1,%0\";
- case 4:
- return \"fmovd %1,%0\";
- case 5:
- return \"ldd %1,%0\";
- case 6:
- return \"std %1,%0\";
- default:
- abort ();
+ emit_insn (gen_movsi (low_part, word1));
+ emit_insn (gen_movsi (high_part, word0));
}
-}"
- [(set_attr "type" "move,move,load,store,fp,fpload,fpstore")
- (set_attr "length" "1,2,1,1,1,1,1")])
+ else
+ {
+ emit_insn (gen_movsi (high_part, word0));
+ emit_insn (gen_movsi (low_part, word1));
+ }
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (match_operand:DI 1 "register_operand" ""))]
+ "(! TARGET_ARCH64
+ && reload_completed
+ && sparc_splitdi_legitimate (operands[1], operands[0]))"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx word0 = change_address (operands[0], SImode, NULL_RTX);
+ rtx word1 = change_address (operands[0], SImode,
+ plus_constant_for_output (XEXP (word0, 0), 4));
+ rtx high_part = gen_highpart (SImode, operands[1]);
+ rtx low_part = gen_lowpart (SImode, operands[1]);
+
+ emit_insn (gen_movsi (word0, high_part));
+ emit_insn (gen_movsi (word1, low_part));
+ DONE;
+}")
-;; ??? There's no symbolic (set (mem:DI ...) ...).
-;; Experimentation with v9 suggested one isn't needed.
;; Floating point move insns
-;; This pattern forces (set (reg:SF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory.
-;; It must come before the more general movsf pattern.
-(define_insn "*movsf_const_insn"
- [(set (match_operand:SF 0 "general_operand" "=f,d,m,?r")
- (match_operand:SF 1 "" "m,G,G,?F"))]
+(define_insn "*clear_sf"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (match_operand:SF 1 "" ""))]
+ "TARGET_VIS
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && GET_CODE (operands[0]) == REG
+ && fp_zero_operand (operands[1])"
+ "fzeros\\t%0"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1")])
+
+(define_insn "*movsf_const_intreg"
+ [(set (match_operand:SF 0 "general_operand" "=f,r")
+ (match_operand:SF 1 "" "m,F"))]
"TARGET_FPU
&& GET_CODE (operands[1]) == CONST_DOUBLE
- && (GET_CODE (operands[0]) == REG
- || fp_zero_operand (operands[1]))"
+ && GET_CODE (operands[0]) == REG"
"*
{
- switch (which_alternative)
+ REAL_VALUE_TYPE r;
+ long i;
+
+ if (which_alternative == 0)
+ return \"ld\\t%1, %0\";
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ if (SPARC_SIMM13_P (i) || SPARC_SETHI_P (i))
{
- case 0:
- return \"ld %1,%0\";
- case 1:
- return \"fzeros %0\";
- case 2:
- return \"st %%g0,%0\";
- case 3:
- return singlemove_string (operands);
- default:
- abort ();
+ operands[1] = GEN_INT (i);
+ if (SPARC_SIMM13_P (INTVAL (operands[1])))
+ return \"mov\\t%1, %0\";
+ else if (SPARC_SETHI_P (INTVAL (operands[1])))
+ return \"sethi\\t%%hi(%a1), %0\";
+ else
+ abort ();
}
+ else
+ return \"#\";
}"
- [(set_attr "type" "fpload,fpmove,store,load")
- (set_attr "length" "1,1,1,2")])
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+;; There isn't much I can do about this, if I change the
+;; mode then flow info gets really confused because the
+;; destination no longer looks the same. Ho hum...
+(define_insn "*movsf_const_high"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (unspec:SF [(match_operand 1 "const_int_operand" "")] 12))]
+ ""
+ "sethi\\t%%hi(%a1), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "*movsf_const_lo"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (unspec:SF [(match_operand 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand" "")] 17))]
+ ""
+ "or\\t%1, %%lo(%a2), %0"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "const_double_operand" ""))]
+ "TARGET_FPU
+ && (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)"
+ [(set (match_dup 0) (unspec:SF [(match_dup 1)] 12))
+ (set (match_dup 0) (unspec:SF [(match_dup 0) (match_dup 1)] 17))]
+ "
+{
+ REAL_VALUE_TYPE r;
+ long i;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ operands[1] = GEN_INT (i);
+}")
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
@@ -2327,88 +2884,193 @@
""
"
{
- if (emit_move_sequence (operands, SFmode))
- DONE;
+ /* Force SFmode constants into memory. */
+ if (GET_CODE (operands[0]) == REG
+ && CONSTANT_P (operands[1]))
+ {
+ if (TARGET_VIS
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && fp_zero_operand (operands[1]))
+ goto movsf_is_ok;
+
+ /* emit_group_store will send such bogosity to us when it is
+ not storing directly into memory. So fix this up to avoid
+ crashes in output_constant_pool. */
+ if (operands [1] == const0_rtx)
+ operands[1] = CONST0_RTX (SFmode);
+ operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+ operands[1]));
+ }
+
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (register_operand (operands[1], SFmode))
+ goto movsf_is_ok;
+
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (SFmode, operands[1]);
+ }
+ }
+
+ /* Fixup PIC cases. */
+ if (flag_pic)
+ {
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], SFmode, 0);
+
+ if (symbolic_operand (operands[1], SFmode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ SFmode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ }
+ }
+
+ movsf_is_ok:
+ ;
}")
(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,f,Q,r,r,Q")
- (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,Q,f,r,Q,r"))]
+ [(set (match_operand:SF 0 "general_operand" "=f,f,m,r,r,m")
+ (match_operand:SF 1 "input_operand" "f,m,f,r,m,r"))]
"TARGET_FPU
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
"@
- fmovs %1,%0
- ld %1,%0
- st %1,%0
- mov %1,%0
- ld %1,%0
- st %1,%0"
- [(set_attr "type" "fpmove,fpload,fpstore,move,load,store")])
+ fmovs\\t%1, %0
+ ld\\t%1, %0
+ st\\t%1, %0
+ mov\\t%1, %0
+ ld\\t%1, %0
+ st\\t%1, %0"
+ [(set_attr "type" "fpmove,fpload,fpstore,move,load,store")
+ (set_attr "length" "1")])
;; Exactly the same as above, except that all `f' cases are deleted.
;; This is necessary to prevent reload from ever trying to use a `f' reg
;; when -mno-fpu.
(define_insn "*movsf_no_f_insn"
- [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
- (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
+ [(set (match_operand:SF 0 "general_operand" "=r,r,m")
+ (match_operand:SF 1 "input_operand" "r,m,r"))]
"! TARGET_FPU
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
"@
- mov %1,%0
- ld %1,%0
- st %1,%0"
- [(set_attr "type" "move,load,store")])
-
-(define_insn "*store_sf"
- [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
- (match_operand:SF 1 "reg_or_0_operand" "rfG"))
- (clobber (match_scratch:SI 2 "=&r"))]
- "(reload_completed || reload_in_progress)
- && ! TARGET_PTR64"
- "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
- [(set_attr "type" "store")
- (set_attr "length" "2")])
+ mov\\t%1, %0
+ ld\\t%1, %0
+ st\\t%1, %0"
+ [(set_attr "type" "move,load,store")
+ (set_attr "length" "1")])
-;; This pattern forces (set (reg:DF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory.
-;; It must come before the more general movdf pattern.
+(define_insn "*clear_df"
+ [(set (match_operand:DF 0 "general_operand" "=e")
+ (match_operand:DF 1 "" ""))]
+ "TARGET_VIS
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && GET_CODE (operands[0]) == REG
+ && fp_zero_operand (operands[1])"
+ "fzero\\t%0"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1")])
+
+(define_insn "*movdf_const_intreg_sp32"
+ [(set (match_operand:DF 0 "general_operand" "=e,e,r")
+ (match_operand:DF 1 "" "T,o,F"))]
+ "TARGET_FPU && ! TARGET_ARCH64
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && GET_CODE (operands[0]) == REG"
+ "*
+{
+ if (which_alternative == 0)
+ return \"ldd\\t%1, %0\";
+ else
+ return \"#\";
+}"
+ [(set_attr "type" "move")
+ (set_attr "length" "1,2,2")])
-(define_insn "*movdf_const_insn"
- [(set (match_operand:DF 0 "general_operand" "=?r,e,o,d")
- (match_operand:DF 1 "" "?F,m,G,G"))]
+;; Now that we redo life analysis with a clean slate after
+;; instruction splitting for sched2 this can work.
+(define_insn "*movdf_const_intreg_sp64"
+ [(set (match_operand:DF 0 "general_operand" "=e,e,r")
+ (match_operand:DF 1 "" "m,o,F"))]
"TARGET_FPU
+ && TARGET_ARCH64
&& GET_CODE (operands[1]) == CONST_DOUBLE
- && (GET_CODE (operands[0]) == REG
- || fp_zero_operand (operands[1]))"
+ && GET_CODE (operands[0]) == REG"
"*
{
- switch (which_alternative)
+ if (which_alternative == 0)
+ return \"ldd\\t%1, %0\";
+ else
+ return \"#\";
+}"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_double_operand" ""))]
+ "TARGET_FPU
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ && reload_completed"
+ [(clobber (const_int 0))]
+ "
+{
+ REAL_VALUE_TYPE r;
+ long l[2];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+ if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
+
+ if (TARGET_ARCH64)
{
- case 0:
- return output_move_double (operands);
- case 1:
- return output_fp_move_double (operands);
- case 2:
- if (TARGET_ARCH64 || (TARGET_V9 && mem_aligned_8 (operands[0])))
- {
- return \"stx %%g0,%0\";
- }
+#if HOST_BITS_PER_WIDE_INT == 64
+ HOST_WIDE_INT val;
+
+ val = ((HOST_WIDE_INT)l[1] |
+ ((HOST_WIDE_INT)l[0] << 32));
+ emit_insn (gen_movdi (operands[0], GEN_INT (val)));
+#else
+ emit_insn (gen_movdi (operands[0],
+ gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,
+ l[1], l[0])));
+#endif
+ }
+ else
+ {
+ emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
+ GEN_INT (l[0])));
+
+ /* Slick... but this trick loses if this subreg constant part
+ can be done in one insn. */
+ if (l[1] == l[0]
+ && !(SPARC_SETHI_P (l[0])
+ || SPARC_SIMM13_P (l[0])))
+ {
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[0])));
+ }
else
- {
- operands[1] = adj_offsettable_operand (operands[0], 4);
- return \"st %%g0,%0\;st %%g0,%1\";
- }
- case 3:
- return \"fzero %0\";
- default:
- abort ();
+ {
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ GEN_INT (l[1])));
+ }
}
-}"
- [(set_attr "type" "load,fpload,store,fpmove")
- (set_attr "length" "3,3,3,1")])
+ DONE;
+}")
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
@@ -2416,126 +3078,271 @@
""
"
{
- if (emit_move_sequence (operands, DFmode))
- DONE;
+ /* Force DFmode constants into memory. */
+ if (GET_CODE (operands[0]) == REG
+ && CONSTANT_P (operands[1]))
+ {
+ if (TARGET_VIS
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && fp_zero_operand (operands[1]))
+ goto movdf_is_ok;
+
+ /* emit_group_store will send such bogosity to us when it is
+ not storing directly into memory. So fix this up to avoid
+ crashes in output_constant_pool. */
+ if (operands [1] == const0_rtx)
+ operands[1] = CONST0_RTX (DFmode);
+ operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+ operands[1]));
+ }
+
+ /* Handle MEM cases first. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (register_operand (operands[1], DFmode))
+ goto movdf_is_ok;
+
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (DFmode, operands[1]);
+ }
+ }
+
+ /* Fixup PIC cases. */
+ if (flag_pic)
+ {
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], DFmode, 0);
+
+ if (symbolic_operand (operands[1], DFmode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ DFmode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ }
+ }
+
+ movdf_is_ok:
+ ;
}")
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=e,Q,e,T,U,r,Q,r")
- (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "e,e,Q,U,T,r,r,Q"))]
+;; Be careful, fmovd does not exist when !v9.
+(define_insn "*movdf_insn_sp32"
+ [(set (match_operand:DF 0 "general_operand" "=e,T,U,T,e,r,r,o,e,o")
+ (match_operand:DF 1 "input_operand" "T,e,T,U,e,r,o,r,o,e"))]
"TARGET_FPU
+ && ! TARGET_V9
&& (register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode))"
- "*
-{
- if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
- return output_fp_move_double (operands);
- return output_move_double (operands);
-}"
- [(set_attr "type" "fp,fpstore,fpload,fpstore,fpload,move,store,load")
- (set_attr "length" "2,3,3,1,1,2,2,2")])
-
-;; Exactly the same as above, except that all `e' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `e' reg
-;; when -mno-fpu.
-
-(define_insn "*movdf_no_e_insn"
- [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
- (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
+ "@
+ ldd\\t%1, %0
+ std\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0
+ #
+ #
+ #
+ #
+ #
+ #"
+ [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
+ (set_attr "length" "1,1,1,1,2,2,2,2,2,2")])
+
+(define_insn "*movdf_no_e_insn_sp32"
+ [(set (match_operand:DF 0 "general_operand" "=U,T,r,r,o")
+ (match_operand:DF 1 "input_operand" "T,U,r,o,r"))]
"! TARGET_FPU
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode))"
+ "@
+ ldd\\t%1, %0
+ std\\t%1, %0
+ #
+ #
+ #"
+ [(set_attr "type" "load,store,*,*,*")
+ (set_attr "length" "1,1,2,2,2")])
+
+;; We have available v9 double floats but not 64-bit
+;; integer registers.
+(define_insn "*movdf_insn_v9only"
+ [(set (match_operand:DF 0 "general_operand" "=e,e,m,U,T,r,r,o")
+ (match_operand:DF 1 "input_operand" "e,m,e,T,U,r,o,r"))]
+ "TARGET_FPU
+ && TARGET_V9
+ && ! TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode))"
- "* return output_move_double (operands);"
- [(set_attr "type" "store,load,move,store,load")
- (set_attr "length" "1,1,2,3,3")])
+ "@
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0
+ #
+ #
+ #"
+ [(set_attr "type" "fpmove,load,store,load,store,*,*,*")
+ (set_attr "length" "1,1,1,1,1,2,2,2")])
+
+;; We have available both v9 double floats and 64-bit
+;; integer registers.
+(define_insn "*movdf_insn_sp64"
+ [(set (match_operand:DF 0 "general_operand" "=e,e,m,r,r,m")
+ (match_operand:DF 1 "input_operand" "e,m,e,r,m,r"))]
+ "TARGET_FPU
+ && TARGET_V9
+ && TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode))"
+ "@
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0
+ mov\\t%1, %0
+ ldx\\t%1, %0
+ stx\\t%1, %0"
+ [(set_attr "type" "fpmove,load,store,move,load,store")
+ (set_attr "length" "1")])
-;; Must handle overlapping registers here, since parameters can be unaligned
-;; in registers.
+(define_insn "*movdf_no_e_insn_sp64"
+ [(set (match_operand:DF 0 "general_operand" "=r,r,m")
+ (match_operand:DF 1 "input_operand" "r,m,r"))]
+ "! TARGET_FPU
+ && TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode))"
+ "@
+ mov\\t%1, %0
+ ldx\\t%1, %0
+ stx\\t%1, %0"
+ [(set_attr "type" "move,load,store")
+ (set_attr "length" "1")])
+;; Ok, now the splits to handle all the multi insn and
+;; mis-aligned memory address cases.
+;; In these splits please take note that we must be
+;; careful when V9 but not ARCH64 because the integer
+;; register DFmode cases must be handled.
(define_split
[(set (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" ""))]
- "! TARGET_ARCH64 && reload_completed
- && REGNO (operands[0]) < SPARC_FIRST_V9_FP_REG
- && REGNO (operands[1]) < SPARC_FIRST_V9_FP_REG"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
+ (match_operand:DF 1 "register_operand" ""))]
+ "(! TARGET_V9
+ || (! TARGET_ARCH64
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))))
+ && reload_completed"
+ [(clobber (const_int 0))]
"
{
- rtx first_set = operand_subword (operands[0], 0, 0, DFmode);
- rtx second_use = operand_subword (operands[1], 1, 0, DFmode);
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
- if (REGNO (first_set) == REGNO (second_use))
+ if (GET_CODE (set_dest) == SUBREG)
+ set_dest = alter_subreg (set_dest);
+ if (GET_CODE (set_src) == SUBREG)
+ set_src = alter_subreg (set_src);
+
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ src1 = gen_highpart (SFmode, set_src);
+ src2 = gen_lowpart (SFmode, set_src);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
{
- operands[2] = operand_subword (operands[0], 1, 0, DFmode);
- operands[3] = second_use;
- operands[4] = first_set;
- operands[5] = operand_subword (operands[1], 0, 0, DFmode);
+ emit_insn (gen_movsf (dest2, src2));
+ emit_insn (gen_movsf (dest1, src1));
}
else
{
- operands[2] = first_set;
- operands[3] = operand_subword (operands[1], 0, 0, DFmode);
- operands[4] = operand_subword (operands[0], 1, 0, DFmode);
- operands[5] = second_use;
+ emit_insn (gen_movsf (dest1, src1));
+ emit_insn (gen_movsf (dest2, src2));
}
+ DONE;
}")
-(define_insn "*store_df"
- [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
- (match_operand:DF 1 "reg_or_0_operand" "re,G"))
- (clobber (match_scratch:SI 2 "=&r,&r"))]
- "(reload_completed || reload_in_progress)
- && ! TARGET_PTR64"
- "*
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "memory_operand" ""))]
+ "((! TARGET_V9
+ || (! TARGET_ARCH64
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))))
+ && (reload_completed
+ && (((REGNO (operands[0])) % 2) != 0
+ || ! mem_min_alignment (operands[1], 8))
+ && offsettable_memref_p (operands[1])))"
+ [(clobber (const_int 0))]
+ "
{
- output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
- if (which_alternative == 0)
- return \"std %1,[%2+%%lo(%a0)]\";
+ rtx word0 = change_address (operands[1], SFmode, NULL_RTX);
+ rtx word1 = change_address (operands[1], SFmode,
+ plus_constant_for_output (XEXP (word0, 0), 4));
+
+ if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+
+ if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
+ {
+ emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
+ word1));
+ emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
+ word0));
+ }
else
- return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
-}"
- [(set_attr "type" "store")
- (set_attr "length" "3")])
-
-;; This pattern forces (set (reg:TF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory.
-;; It must come before the more general movtf pattern.
-(define_insn "*movtf_const_insn"
- [(set (match_operand:TF 0 "general_operand" "=?r,e,o")
- (match_operand:TF 1 "" "?F,m,G"))]
- "TARGET_FPU
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && (GET_CODE (operands[0]) == REG
- || fp_zero_operand (operands[1]))"
- "*
-{
- switch (which_alternative)
{
- case 0:
- return output_move_quad (operands);
- case 1:
- return output_fp_move_quad (operands);
- case 2:
- if (TARGET_ARCH64 || (TARGET_V9 && mem_aligned_8 (operands[0])))
- {
- operands[1] = adj_offsettable_operand (operands[0], 8);
- return \"stx %%g0,%0\;stx %%g0,%1\";
- }
- else
- {
- /* ??? Do we run off the end of the array here? */
- operands[1] = adj_offsettable_operand (operands[0], 4);
- operands[2] = adj_offsettable_operand (operands[0], 8);
- operands[3] = adj_offsettable_operand (operands[0], 12);
- return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
- }
- default:
- abort ();
+ emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
+ word0));
+ emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
+ word1));
}
-}"
- [(set_attr "type" "load,fpload,store")
- (set_attr "length" "5,5,5")])
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "register_operand" ""))]
+ "((! TARGET_V9
+ || (! TARGET_ARCH64
+ && ((GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) < 32)
+ || (GET_CODE (operands[1]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[1])) == REG
+ && REGNO (SUBREG_REG (operands[1])) < 32))))
+ && (reload_completed
+ && (((REGNO (operands[1])) % 2) != 0
+ || ! mem_min_alignment (operands[0], 8))
+ && offsettable_memref_p (operands[0])))"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx word0 = change_address (operands[0], SFmode, NULL_RTX);
+ rtx word1 = change_address (operands[0], SFmode,
+ plus_constant_for_output (XEXP (word0, 0), 4));
+
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = alter_subreg (operands[1]);
+ emit_insn (gen_movsf (word0,
+ gen_highpart (SFmode, operands[1])));
+ emit_insn (gen_movsf (word1,
+ gen_lowpart (SFmode, operands[1])));
+ DONE;
+}")
(define_expand "movtf"
[(set (match_operand:TF 0 "general_operand" "")
@@ -2543,63 +3350,219 @@
""
"
{
- if (emit_move_sequence (operands, TFmode))
- DONE;
+ /* Force TFmode constants into memory. */
+ if (GET_CODE (operands[0]) == REG
+ && CONSTANT_P (operands[1]))
+ {
+ /* emit_group_store will send such bogosity to us when it is
+ not storing directly into memory. So fix this up to avoid
+ crashes in output_constant_pool. */
+ if (operands [1] == const0_rtx)
+ operands[1] = CONST0_RTX (TFmode);
+ operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
+ operands[1]));
+ }
+
+ /* Handle MEM cases first, note that only v9 guarentees
+ full 16-byte alignment for quads. */
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (register_operand (operands[1], TFmode))
+ goto movtf_is_ok;
+
+ if (! reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (TFmode, operands[1]);
+ }
+ }
+
+ /* Fixup PIC cases. */
+ if (flag_pic)
+ {
+ if (CONSTANT_P (operands[1])
+ && pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], TFmode, 0);
+
+ if (symbolic_operand (operands[1], TFmode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ TFmode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ }
+ }
+
+ movtf_is_ok:
+ ;
}")
-(define_insn "*movtf_insn"
- [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,Q,e,r,Q,r")
- (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,e,Q,r,r,Q"))]
+;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
+;; we must split them all. :-(
+(define_insn "*movtf_insn_sp32"
+ [(set (match_operand:TF 0 "general_operand" "=e,o,U,o,e,r,r,o")
+ (match_operand:TF 1 "input_operand" "o,e,o,U,e,r,o,r"))]
"TARGET_FPU
+ && ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
|| register_operand (operands[1], TFmode))"
- "*
-{
- if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
- return output_fp_move_quad (operands);
- return output_move_quad (operands);
-}"
- [(set_attr "type" "fp,fpstore,fpload,move,store,load")
- (set_attr "length" "5,4,4,5,4,4")])
+ "#"
+ [(set_attr "length" "4")])
;; Exactly the same as above, except that all `e' cases are deleted.
;; This is necessary to prevent reload from ever trying to use a `e' reg
;; when -mno-fpu.
-(define_insn "*movtf_no_e_insn"
- [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
- (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
+(define_insn "*movtf_no_e_insn_sp32"
+ [(set (match_operand:TF 0 "general_operand" "=U,o,r,r,o")
+ (match_operand:TF 1 "input_operand" "o,U,r,o,r"))]
"! TARGET_FPU
+ && ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
|| register_operand (operands[1], TFmode))"
- "*
+ "#"
+ [(set_attr "length" "4")])
+
+;; Now handle the float reg cases directly when arch64,
+;; hard_quad, and proper reg number alignment are all true.
+(define_insn "*movtf_insn_hq_sp64"
+ [(set (match_operand:TF 0 "general_operand" "=e,e,m,r,r,o")
+ (match_operand:TF 1 "input_operand" "e,m,e,r,o,r"))]
+ "TARGET_FPU
+ && TARGET_ARCH64
+ && TARGET_V9
+ && TARGET_HARD_QUAD
+ && (register_operand (operands[0], TFmode)
+ || register_operand (operands[1], TFmode))"
+ "@
+ fmovq\\t%1, %0
+ ldq\\t%1, %0
+ stq\\t%1, %0
+ #
+ #
+ #"
+ [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
+ (set_attr "length" "1,1,1,2,2,2")])
+
+;; Now we allow the integer register cases even when
+;; only arch64 is true.
+(define_insn "*movtf_insn_sp64"
+ [(set (match_operand:TF 0 "general_operand" "=e,o,r,o,e,r")
+ (match_operand:TF 1 "input_operand" "o,e,o,r,e,r"))]
+ "TARGET_FPU
+ && TARGET_ARCH64
+ && ! TARGET_HARD_QUAD
+ && (register_operand (operands[0], TFmode)
+ || register_operand (operands[1], TFmode))"
+ "#"
+ [(set_attr "length" "2")])
+
+(define_insn "*movtf_no_e_insn_sp64"
+ [(set (match_operand:TF 0 "general_operand" "=r,o,r")
+ (match_operand:TF 1 "input_operand" "o,r,r"))]
+ "! TARGET_FPU
+ && TARGET_ARCH64
+ && (register_operand (operands[0], TFmode)
+ || register_operand (operands[1], TFmode))"
+ "#"
+ [(set_attr "length" "2")])
+
+;; Now all the splits to handle multi-insn TF mode moves.
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "register_operand" ""))]
+ "reload_completed
+ && (! TARGET_ARCH64
+ || (TARGET_FPU
+ && ! TARGET_HARD_QUAD))"
+ [(clobber (const_int 0))]
+ "
{
- if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
- return output_fp_move_quad (operands);
- return output_move_quad (operands);
-}"
- [(set_attr "type" "move,store,load")
- (set_attr "length" "4,5,5")])
-
-;; This is disabled because it does not work. Long doubles have only 8
-;; byte alignment. Adding an offset of 8 or 12 to an 8 byte aligned %lo may
-;; cause it to overflow. See also GO_IF_LEGITIMATE_ADDRESS.
-(define_insn "*store_tf"
- [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
- (match_operand:TF 1 "reg_or_0_operand" "re,G"))
- (clobber (match_scratch:SI 2 "=&r,&r"))]
- "0 && (reload_completed || reload_in_progress)
- && ! TARGET_PTR64"
- "*
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ if (GET_CODE (set_dest) == SUBREG)
+ set_dest = alter_subreg (set_dest);
+ if (GET_CODE (set_src) == SUBREG)
+ set_src = alter_subreg (set_src);
+
+ /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
+ dest1 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN == 0);
+ dest2 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN != 0);
+ src1 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN == 0);
+ src2 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN != 0);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movdf (dest2, src2));
+ emit_insn (gen_movdf (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_movdf (dest1, src1));
+ emit_insn (gen_movdf (dest2, src2));
+ }
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "memory_operand" ""))]
+ "(reload_completed
+ && offsettable_memref_p (operands[1]))"
+ [(clobber (const_int 0))]
+ "
{
- output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
- if (which_alternative == 0)
- return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
+ rtx word0 = change_address (operands[1], DFmode, NULL_RTX);
+ rtx word1 = change_address (operands[1], DFmode,
+ plus_constant_for_output (XEXP (word0, 0), 8));
+ rtx dest1, dest2;
+
+ /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
+ dest1 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN == 0);
+ dest2 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN != 0);
+
+ /* Now output, ordering such that we don't clobber any registers
+ mentioned in the address. */
+ if (reg_overlap_mentioned_p (dest1, word1))
+
+ {
+ emit_insn (gen_movdf (dest2, word1));
+ emit_insn (gen_movdf (dest1, word0));
+ }
else
- return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
-}"
- [(set_attr "type" "store")
- (set_attr "length" "5")])
+ {
+ emit_insn (gen_movdf (dest1, word0));
+ emit_insn (gen_movdf (dest2, word1));
+ }
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:TF 0 "memory_operand" "")
+ (match_operand:TF 1 "register_operand" ""))]
+ "(reload_completed
+ && offsettable_memref_p (operands[0]))"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx word0 = change_address (operands[0], DFmode, NULL_RTX);
+ rtx word1 = change_address (operands[0], DFmode,
+ plus_constant_for_output (XEXP (word0, 0), 8));
+ rtx src1, src2;
+
+ /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
+ src1 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN == 0);
+ src2 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN != 0);
+ emit_insn (gen_movdf (word0, src1));
+ emit_insn (gen_movdf (word1, src2));
+ DONE;
+}")
;; Sparc V9 conditional move instructions.
@@ -2682,8 +3645,7 @@
if (sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
- && ((TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code))
- || (op0_mode == SImode && v8plus_regcmp_p (code))))
+ && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
{
operands[1] = gen_rtx_fmt_ee (code, op0_mode,
sparc_compare_op0, sparc_compare_op1);
@@ -2821,39 +3783,42 @@
(if_then_else:QI (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
(const_int 0)])
- (match_operand:QI 3 "arith11_operand" "rL,0")
- (match_operand:QI 4 "arith11_operand" "0,rL")))]
+ (match_operand:QI 3 "arith11_operand" "rL,0")
+ (match_operand:QI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
"@
- mov%C1 %x2,%3,%0
- mov%c1 %x2,%4,%0"
- [(set_attr "type" "cmove")])
+ mov%C1\\t%x2, %3, %0
+ mov%c1\\t%x2, %4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
(define_insn "*movhi_cc_sp64"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(if_then_else:HI (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
(const_int 0)])
- (match_operand:HI 3 "arith11_operand" "rL,0")
- (match_operand:HI 4 "arith11_operand" "0,rL")))]
+ (match_operand:HI 3 "arith11_operand" "rL,0")
+ (match_operand:HI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
"@
- mov%C1 %x2,%3,%0
- mov%c1 %x2,%4,%0"
- [(set_attr "type" "cmove")])
+ mov%C1\\t%x2, %3, %0
+ mov%c1\\t%x2, %4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
(define_insn "*movsi_cc_sp64"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(if_then_else:SI (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
(const_int 0)])
- (match_operand:SI 3 "arith11_operand" "rL,0")
- (match_operand:SI 4 "arith11_operand" "0,rL")))]
+ (match_operand:SI 3 "arith11_operand" "rL,0")
+ (match_operand:SI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
"@
- mov%C1 %x2,%3,%0
- mov%c1 %x2,%4,%0"
- [(set_attr "type" "cmove")])
+ mov%C1\\t%x2, %3, %0
+ mov%c1\\t%x2, %4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
;; ??? The constraints of operands 3,4 need work.
(define_insn "*movdi_cc_sp64"
@@ -2861,142 +3826,112 @@
(if_then_else:DI (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
(const_int 0)])
- (match_operand:DI 3 "arith11_double_operand" "rLH,0")
- (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
+ (match_operand:DI 3 "arith11_double_operand" "rLH,0")
+ (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
"TARGET_ARCH64"
"@
- mov%C1 %x2,%3,%0
- mov%c1 %x2,%4,%0"
- [(set_attr "type" "cmove")])
+ mov%C1\\t%x2, %3, %0
+ mov%c1\\t%x2, %4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
+
+(define_insn "*movdi_cc_sp64_trunc"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (if_then_else:SI (match_operator 1 "comparison_operator"
+ [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ (const_int 0)])
+ (match_operand:SI 3 "arith11_double_operand" "rLH,0")
+ (match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
+ "TARGET_ARCH64"
+ "@
+ mov%C1\\t%x2, %3, %0
+ mov%c1\\t%x2, %4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
(define_insn "*movsf_cc_sp64"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "f,0")
+ (match_operand:SF 4 "register_operand" "0,f")))]
"TARGET_V9 && TARGET_FPU"
"@
- fmovs%C1 %x2,%3,%0
- fmovs%c1 %x2,%4,%0"
- [(set_attr "type" "fpcmove")])
+ fmovs%C1\\t%x2, %3, %0
+ fmovs%c1\\t%x2, %4, %0"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "1")])
(define_insn "*movdf_cc_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
+ (match_operand:DF 3 "register_operand" "e,0")
+ (match_operand:DF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU"
"@
- fmovd%C1 %x2,%3,%0
- fmovd%c1 %x2,%4,%0"
- [(set_attr "type" "fpcmove")])
+ fmovd%C1\\t%x2, %3, %0
+ fmovd%c1\\t%x2, %4, %0"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "1")])
(define_insn "*movtf_cc_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"@
- fmovq%C1 %x2,%3,%0
- fmovq%c1 %x2,%4,%0"
- [(set_attr "type" "fpcmove")])
+ fmovq%C1\\t%x2, %3, %0
+ fmovq%c1\\t%x2, %4, %0"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "1")])
(define_insn "*movqi_cc_reg_sp64"
[(set (match_operand:QI 0 "register_operand" "=r,r")
(if_then_else:QI (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:QI 3 "arith10_operand" "rM,0")
- (match_operand:QI 4 "arith10_operand" "0,rM")))]
+ (match_operand:QI 3 "arith10_operand" "rM,0")
+ (match_operand:QI 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
- movr%D1 %2,%r3,%0
- movr%d1 %2,%r4,%0"
- [(set_attr "type" "cmove")])
+ movr%D1\\t%2, %r3, %0
+ movr%d1\\t%2, %r4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
(define_insn "*movhi_cc_reg_sp64"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(if_then_else:HI (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:HI 3 "arith10_operand" "rM,0")
- (match_operand:HI 4 "arith10_operand" "0,rM")))]
+ (match_operand:HI 3 "arith10_operand" "rM,0")
+ (match_operand:HI 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
- movr%D1 %2,%r3,%0
- movr%d1 %2,%r4,%0"
- [(set_attr "type" "cmove")])
+ movr%D1\\t%2, %r3, %0
+ movr%d1\\t%2, %r4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
(define_insn "*movsi_cc_reg_sp64"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(if_then_else:SI (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:SI 3 "arith10_operand" "rM,0")
- (match_operand:SI 4 "arith10_operand" "0,rM")))]
+ (match_operand:SI 3 "arith10_operand" "rM,0")
+ (match_operand:SI 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
- movr%D1 %2,%r3,%0
- movr%d1 %2,%r4,%0"
- [(set_attr "type" "cmove")])
-
-;; On UltraSPARC this is slightly worse than cmp/mov %icc if the register
-;; needs to be zero extended but better on average.
-(define_insn "*movsi_cc_reg_v8plus"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "v8plus_regcmp_op"
- [(match_operand:SI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:SI 3 "arith10_operand" "rM,0")
- (match_operand:SI 4 "arith10_operand" "0,rM")))]
- "TARGET_V9"
- "*
-{
- if (! sparc_check_64 (operands[2], insn))
- output_asm_insn (\"srl %2,0,%2\", operands);
- if (which_alternative == 0)
- return \"movr%D1 %2,%r3,%0\";
- return \"movr%d1 %2,%r4,%0\";
-}"
+ movr%D1\\t%2, %r3, %0
+ movr%d1\\t%2, %r4, %0"
[(set_attr "type" "cmove")
- (set_attr "length" "2")])
-
-;; To work well this needs to know the current insn, but that is not an
-;; argument to gen_split_*.
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "v8plus_regcmp_op"
- [(match_operand:SI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:SI 3 "arith10_operand" "rM,0")
- (match_operand:SI 4 "arith10_operand" "0,rM")))]
- "reload_completed"
- [(set (match_dup 0)
- (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 4)] 9))]
- "if (! sparc_check_64 (operands[2], NULL_RTX))
- emit_insn (gen_v8plus_clear_high (operands[2], operands[2]));")
-
-;; A conditional move with the condition argument known to be zero extended
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (unspec:SI [(match_operator 1 "v8plus_regcmp_op"
- [(match_operand:SI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:SI 3 "arith10_operand" "rM,0")
- (match_operand:SI 4 "arith10_operand" "0,rM")] 9))]
- "TARGET_V9"
- "@
- movr%D1 %2,%r3,%0
- movr%d1 %2,%r4,%0"
- [(set_attr "type" "cmove")])
+ (set_attr "length" "1")])
;; ??? The constraints of operands 3,4 need work.
(define_insn "*movdi_cc_reg_sp64"
@@ -3004,52 +3939,70 @@
(if_then_else:DI (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:DI 3 "arith10_double_operand" "rMH,0")
- (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
+ (match_operand:DI 3 "arith10_double_operand" "rMH,0")
+ (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
"TARGET_ARCH64"
"@
- movr%D1 %2,%r3,%0
- movr%d1 %2,%r4,%0"
- [(set_attr "type" "cmove")])
+ movr%D1\\t%2, %r3, %0
+ movr%d1\\t%2, %r4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
+
+(define_insn "*movdi_cc_reg_sp64_trunc"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (if_then_else:SI (match_operator 1 "v9_regcmp_op"
+ [(match_operand:DI 2 "register_operand" "r,r")
+ (const_int 0)])
+ (match_operand:SI 3 "arith10_double_operand" "rMH,0")
+ (match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
+ "TARGET_ARCH64"
+ "@
+ movr%D1\\t%2, %r3, %0
+ movr%d1\\t%2, %r4, %0"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "1")])
(define_insn "*movsf_cc_reg_sp64"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "f,0")
+ (match_operand:SF 4 "register_operand" "0,f")))]
"TARGET_ARCH64 && TARGET_FPU"
"@
- fmovrs%D1 %2,%3,%0
- fmovrs%d1 %2,%4,%0"
- [(set_attr "type" "fpcmove")])
+ fmovrs%D1\\t%2, %3, %0
+ fmovrs%d1\\t%2, %4, %0"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "1")])
(define_insn "*movdf_cc_reg_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
+ (match_operand:DF 3 "register_operand" "e,0")
+ (match_operand:DF 4 "register_operand" "0,e")))]
"TARGET_ARCH64 && TARGET_FPU"
"@
- fmovrd%D1 %2,%3,%0
- fmovrd%d1 %2,%4,%0"
- [(set_attr "type" "fpcmove")])
+ fmovrd%D1\\t%2, %3, %0
+ fmovrd%d1\\t%2, %4, %0"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "1")])
(define_insn "*movtf_cc_reg_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_ARCH64 && TARGET_FPU"
"@
- fmovrq%D1 %2,%3,%0
- fmovrq%d1 %2,%4,%0"
- [(set_attr "type" "fpcmove")])
+ fmovrq%D1\\t%2, %3, %0
+ fmovrq%d1\\t%2, %4, %0"
+ [(set_attr "type" "fpcmove")
+ (set_attr "length" "1")])
;;- zero extension instructions
@@ -3084,8 +4037,9 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
""
- "lduh %1,%0"
- [(set_attr "type" "load")])
+ "lduh\\t%1, %0"
+ [(set_attr "type" "load")
+ (set_attr "length" "1")])
(define_expand "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
@@ -3095,11 +4049,11 @@
(define_insn "*zero_extendqihi2_insn"
[(set (match_operand:HI 0 "register_operand" "=r,r")
- (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
+ (zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
"GET_CODE (operands[1]) != CONST_INT"
"@
- and %1,0xff,%0
- ldub %1,%0"
+ and\\t%1, 0xff, %0
+ ldub\\t%1, %0"
[(set_attr "type" "unary,load")
(set_attr "length" "1")])
@@ -3111,11 +4065,11 @@
(define_insn "*zero_extendqisi2_insn"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
+ (zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
"GET_CODE (operands[1]) != CONST_INT"
"@
- and %1,0xff,%0
- ldub %1,%0"
+ and\\t%1, 0xff, %0
+ ldub\\t%1, %0"
[(set_attr "type" "unary,load")
(set_attr "length" "1")])
@@ -3127,11 +4081,11 @@
(define_insn "*zero_extendqidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))]
+ (zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
"TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
"@
- and %1,0xff,%0
- ldub %1,%0"
+ and\\t%1, 0xff, %0
+ ldub\\t%1, %0"
[(set_attr "type" "unary,load")
(set_attr "length" "1")])
@@ -3162,8 +4116,9 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
- "lduh %1,%0"
- [(set_attr "type" "load")])
+ "lduh\\t%1, %0"
+ [(set_attr "type" "load")
+ (set_attr "length" "1")])
;; ??? Write truncdisi pattern using sra?
@@ -3171,32 +4126,59 @@
(define_expand "zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
- "TARGET_ARCH64"
+ ""
"")
-(define_insn "*zero_extendsidi2_insn"
+(define_insn "*zero_extendsidi2_insn_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
+ (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
"TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
"@
- srl %1,0,%0
- lduw %1,%0"
- [(set_attr "type" "unary,load")
+ srl\\t%1, 0, %0
+ lduw\\t%1, %0"
+ [(set_attr "type" "shift,load")
(set_attr "length" "1")])
-;; Zero extend a 32 bit value in a 64 bit register.
-(define_insn "v8plus_clear_high"
- [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,Q")
- (unspec:SI [(match_operand:SI 1 "register_operand" "r,r")] 10))]
- "TARGET_V9"
- "*
-if (which_alternative == 1)
- return \"st %1,%0\";
-if (sparc_check_64 (operands[1], insn) > 0)
- return final_sequence ? \"nop\" : \"\";
-return \"srl %1,0,%0\";
-"
- [(set_attr "type" "shift,store")])
+(define_insn "*zero_extendsidi2_insn_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
+ "! TARGET_ARCH64"
+ "#"
+ [(set_attr "type" "unary")
+ (set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (match_dup 5))]
+ "
+{
+ rtx dest1, dest2;
+
+ if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+
+ dest1 = gen_highpart (SImode, operands[0]);
+ dest2 = gen_lowpart (SImode, operands[0]);
+
+ /* Swap the order in case of overlap. */
+ if (REGNO (dest1) == REGNO (operands[1]))
+ {
+ operands[2] = dest2;
+ operands[3] = operands[1];
+ operands[4] = dest1;
+ operands[5] = const0_rtx;
+ }
+ else
+ {
+ operands[2] = dest1;
+ operands[3] = const0_rtx;
+ operands[4] = dest2;
+ operands[5] = operands[1];
+ }
+}")
;; Simplify comparisons of extended values.
@@ -3204,9 +4186,10 @@ return \"srl %1,0,%0\";
[(set (reg:CC 100)
(compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
(const_int 0)))]
- ""
- "andcc %0,0xff,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "andcc\\t%0, 0xff, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_zero_extendqisi2_set"
[(set (reg:CC 100)
@@ -3215,28 +4198,71 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_dup 1)))]
""
- "andcc %1,0xff,%0"
- [(set_attr "type" "unary")])
+ "andcc\\t%1, 0xff, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmp_zero_extendqidi2"
+ [(set (reg:CCX 100)
+ (compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ "andcc\\t%0, 0xff, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmp_zero_extendqidi2_set"
+ [(set (reg:CCX 100)
+ (compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (match_dup 1)))]
+ "TARGET_ARCH64"
+ "andcc\\t%1, 0xff, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
-;; Similarly, handle SI->QI mode truncation followed by a compare.
+;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
(define_insn "*cmp_siqi_trunc"
[(set (reg:CC 100)
(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
(const_int 0)))]
- ""
- "andcc %0,0xff,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "andcc\\t%0, 0xff, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_siqi_trunc_set"
[(set (reg:CC 100)
(compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
(const_int 0)))
(set (match_operand:QI 0 "register_operand" "=r")
- (match_dup 1))]
+ (subreg:QI (match_dup 1) 0))]
""
- "andcc %1,0xff,%0"
- [(set_attr "type" "unary")])
+ "andcc\\t%1, 0xff, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmp_diqi_trunc"
+ [(set (reg:CC 100)
+ (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 0)
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ "andcc\\t%0, 0xff, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
+
+(define_insn "*cmp_diqi_trunc_set"
+ [(set (reg:CC 100)
+ (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 0)
+ (const_int 0)))
+ (set (match_operand:QI 0 "register_operand" "=r")
+ (subreg:QI (match_dup 1) 0))]
+ "TARGET_ARCH64"
+ "andcc\\t%1, 0xff, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
;;- sign extension instructions
@@ -3271,8 +4297,9 @@ return \"srl %1,0,%0\";
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
""
- "ldsh %1,%0"
- [(set_attr "type" "sload")])
+ "ldsh\\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "length" "1")])
(define_expand "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
@@ -3308,8 +4335,9 @@ return \"srl %1,0,%0\";
[(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
""
- "ldsb %1,%0"
- [(set_attr "type" "sload")])
+ "ldsb\\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "length" "1")])
(define_expand "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -3338,8 +4366,9 @@ return \"srl %1,0,%0\";
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
""
- "ldsb %1,%0"
- [(set_attr "type" "sload")])
+ "ldsb\\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "length" "1")])
(define_expand "extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -3368,8 +4397,9 @@ return \"srl %1,0,%0\";
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
- "ldsb %1,%0"
- [(set_attr "type" "sload")])
+ "ldsb\\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "length" "1")])
(define_expand "extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -3398,8 +4428,9 @@ return \"srl %1,0,%0\";
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
- "ldsh %1,%0"
- [(set_attr "type" "load")])
+ "ldsh\\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "length" "1")])
(define_expand "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -3409,12 +4440,12 @@ return \"srl %1,0,%0\";
(define_insn "*sign_extendsidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
+ (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
"TARGET_ARCH64"
"@
- sra %1,0,%0
- ldsw %1,%0"
- [(set_attr "type" "unary,sload")
+ sra\\t%1, 0, %0
+ ldsw\\t%1, %0"
+ [(set_attr "type" "shift,sload")
(set_attr "length" "1")])
;; Special pattern for optimizing bit-field compares. This is needed
@@ -3424,37 +4455,59 @@ return \"srl %1,0,%0\";
[(set (reg:CC 100)
(compare:CC
(zero_extract:SI (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "small_int" "n")
- (match_operand:SI 2 "small_int" "n"))
+ (match_operand:SI 1 "small_int_or_double" "n")
+ (match_operand:SI 2 "small_int_or_double" "n"))
(const_int 0)))]
- "INTVAL (operands[2]) > 19"
+ "! TARGET_LIVE_G0
+ && ((GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 19)
+ || (GET_CODE (operands[2]) == CONST_DOUBLE
+ && CONST_DOUBLE_LOW (operands[2]) > 19))"
"*
{
- int len = INTVAL (operands[1]);
- int pos = 32 - INTVAL (operands[2]) - len;
- unsigned mask = ((1 << len) - 1) << pos;
+ int len = (GET_CODE (operands[1]) == CONST_INT
+ ? INTVAL (operands[1])
+ : CONST_DOUBLE_LOW (operands[1]));
+ int pos = 32 -
+ (GET_CODE (operands[2]) == CONST_INT
+ ? INTVAL (operands[2])
+ : CONST_DOUBLE_LOW (operands[2])) - len;
+ HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
operands[1] = GEN_INT (mask);
- return \"andcc %0,%1,%%g0\";
-}")
+ return \"andcc\\t%0, %1, %%g0\";
+}"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_zero_extract_sp64"
[(set (reg:CCX 100)
(compare:CCX
(zero_extract:DI (match_operand:DI 0 "register_operand" "r")
- (match_operand:SI 1 "small_int" "n")
- (match_operand:SI 2 "small_int" "n"))
+ (match_operand:SI 1 "small_int_or_double" "n")
+ (match_operand:SI 2 "small_int_or_double" "n"))
(const_int 0)))]
- "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
+ "TARGET_ARCH64
+ && ((GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 51)
+ || (GET_CODE (operands[2]) == CONST_DOUBLE
+ && CONST_DOUBLE_LOW (operands[2]) > 51))"
"*
{
- int len = INTVAL (operands[1]);
- int pos = 64 - INTVAL (operands[2]) - len;
- unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
+ int len = (GET_CODE (operands[1]) == CONST_INT
+ ? INTVAL (operands[1])
+ : CONST_DOUBLE_LOW (operands[1]));
+ int pos = 64 -
+ (GET_CODE (operands[2]) == CONST_INT
+ ? INTVAL (operands[2])
+ : CONST_DOUBLE_LOW (operands[2])) - len;
+ HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
operands[1] = GEN_INT (mask);
- return \"andcc %0,%1,%%g0\";
-}")
+ return \"andcc\\t%0, %1, %%g0\";
+}"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
;; Conversions between float, double and long double.
@@ -3463,48 +4516,54 @@ return \"srl %1,0,%0\";
(float_extend:DF
(match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fstod %1,%0"
- [(set_attr "type" "fp")])
+ "fstod\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "extendsftf2"
[(set (match_operand:TF 0 "register_operand" "=e")
(float_extend:TF
(match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fstoq %1,%0"
- [(set_attr "type" "fp")])
+ "fstoq\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "extenddftf2"
[(set (match_operand:TF 0 "register_operand" "=e")
(float_extend:TF
(match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fdtoq %1,%0"
- [(set_attr "type" "fp")])
+ "fdtoq\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(float_truncate:SF
(match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU"
- "fdtos %1,%0"
- [(set_attr "type" "fp")])
+ "fdtos\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "trunctfsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(float_truncate:SF
(match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fqtos %1,%0"
- [(set_attr "type" "fp")])
+ "fqtos\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "trunctfdf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(float_truncate:DF
(match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fqtod %1,%0"
- [(set_attr "type" "fp")])
+ "fqtod\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
;; Conversion between fixed point and floating point.
@@ -3512,22 +4571,25 @@ return \"srl %1,0,%0\";
[(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:SI 1 "register_operand" "f")))]
"TARGET_FPU"
- "fitos %1,%0"
- [(set_attr "type" "fp")])
+ "fitos\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(float:DF (match_operand:SI 1 "register_operand" "f")))]
"TARGET_FPU"
- "fitod %1,%0"
- [(set_attr "type" "fp")])
+ "fitod\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "floatsitf2"
[(set (match_operand:TF 0 "register_operand" "=e")
(float:TF (match_operand:SI 1 "register_operand" "f")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fitoq %1,%0"
- [(set_attr "type" "fp")])
+ "fitoq\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
;; Now the same for 64 bit sources.
@@ -3535,22 +4597,25 @@ return \"srl %1,0,%0\";
[(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:DI 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU"
- "fxtos %1,%0"
- [(set_attr "type" "fp")])
+ "fxtos\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(float:DF (match_operand:DI 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU"
- "fxtod %1,%0"
- [(set_attr "type" "fp")])
+ "fxtod\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "floatditf2"
[(set (match_operand:TF 0 "register_operand" "=e")
(float:TF (match_operand:DI 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fxtoq %1,%0"
- [(set_attr "type" "fp")])
+ "fxtoq\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
;; Convert a float to an actual integer.
;; Truncation is performed as part of the conversion.
@@ -3559,22 +4624,25 @@ return \"srl %1,0,%0\";
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
"TARGET_FPU"
- "fstoi %1,%0"
- [(set_attr "type" "fp")])
+ "fstoi\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
"TARGET_FPU"
- "fdtoi %1,%0"
- [(set_attr "type" "fp")])
+ "fdtoi\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "fix_trunctfsi2"
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fqtoi %1,%0"
- [(set_attr "type" "fp")])
+ "fqtoi\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
;; Now the same, for V9 targets
@@ -3582,29 +4650,32 @@ return \"srl %1,0,%0\";
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
"TARGET_V9 && TARGET_FPU"
- "fstox %1,%0"
- [(set_attr "type" "fp")])
+ "fstox\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
"TARGET_V9 && TARGET_FPU"
- "fdtox %1,%0"
- [(set_attr "type" "fp")])
+ "fdtox\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "fix_trunctfdi2"
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fqtox %1,%0"
- [(set_attr "type" "fp")])
+ "fqtox\\t%1, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
;;- arithmetic instructions
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
""
"
{
@@ -3618,41 +4689,24 @@ return \"srl %1,0,%0\";
gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
DONE;
}
+ if (arith_double_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (DImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
}")
-(define_insn "*adddi3_sp32"
+(define_insn "adddi3_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
- "*
-{
- rtx op2 = operands[2];
-
- if (GET_CODE (op2) == CONST_INT
- || GET_CODE (op2) == CONST_DOUBLE)
- {
- rtx xoperands[4];
- xoperands[0] = operands[0];
- xoperands[1] = operands[1];
- if (WORDS_BIG_ENDIAN)
- split_double (op2, &xoperands[2], &xoperands[3]);
- else
- split_double (op2, &xoperands[3], &xoperands[2]);
- if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
- output_asm_insn (\"add %H1,%2,%H0\", xoperands);
- else
- output_asm_insn (\"addcc %L1,%3,%L0\;addx %H1,%2,%H0\", xoperands);
- return \"\";
- }
- return \"addcc %L1,%L2,%L0\;addx %H1,%H2,%H0\";
-}"
+ "#"
[(set_attr "length" "2")])
-
-;; Split DImode arithmetic
-
(define_split
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
@@ -3722,58 +4776,163 @@ return \"srl %1,0,%0\";
}")
;; LTU here means "carry set"
-(define_insn "*addx"
+(define_insn "addx"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (plus:SI (match_operand:SI 1 "arith_operand" "%r")
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
""
- "addx %1,%2,%0"
- [(set_attr "type" "unary")])
+ "addx\\t%1, %2, %0"
+ [(set_attr "type" "unary")
+ (set_attr "length" "1")])
-(define_insn "*subx"
+(define_insn "*addx_extend_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "! TARGET_ARCH64"
+ "#"
+ [(set_attr "type" "unary")
+ (set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "")
+ (match_operand:SI 2 "arith_operand" ""))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(set (match_dup 3) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
+ (set (match_dup 4) (const_int 0))]
+ "operands[3] = gen_lowpart (SImode, operands[0]);
+ operands[4] = gen_highpart (SImode, operands[1]);")
+
+(define_insn "*addx_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "TARGET_ARCH64"
+ "addx\\t%r1, %2, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
+
+(define_insn "subx"
[(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
""
- "subx %1,%2,%0"
- [(set_attr "type" "unary")])
+ "subx\\t%r1, %2, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
+
+(define_insn "*subx_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "TARGET_ARCH64"
+ "subx\\t%r1, %2, %0"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
+
+(define_insn "*subx_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "! TARGET_ARCH64"
+ "#"
+ [(set_attr "type" "unary")
+ (set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
+ (set (match_dup 4) (const_int 0))]
+ "operands[3] = gen_lowpart (SImode, operands[0]);
+ operands[4] = gen_highpart (SImode, operands[0]);")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))
+ (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:DI 2 "register_operand" "r")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
- "addcc %L2,%1,%L0\;addx %H2,0,%H0"
- [(set_attr "type" "multi")])
+ "#"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (match_operand:DI 2 "register_operand" "")))
+ (clobber (reg:CC 100))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(parallel [(set (reg:CC_NOOV 100)
+ (compare:CC_NOOV (plus:SI (match_dup 3) (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 5) (plus:SI (match_dup 3) (match_dup 1)))])
+ (set (match_dup 6)
+ (plus:SI (plus:SI (match_dup 4) (const_int 0))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+ "operands[3] = gen_lowpart (SImode, operands[2]);
+ operands[4] = gen_highpart (SImode, operands[2]);
+ operands[5] = gen_lowpart (SImode, operands[0]);
+ operands[6] = gen_highpart (SImode, operands[0]);")
(define_insn "*adddi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "add %1,%2,%0")
+ "add\\t%1, %2, %0"
+ [(set_attr "type" "binary")
+ (set_attr "length" "1")])
-(define_insn "addsi3"
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,d")
+ (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
+ (match_operand:SI 2 "arith_add_operand" "rI,d")))]
+ ""
+ "
+{
+ if (arith_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (SImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
+}")
+
+(define_insn "*addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
(plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- add %1,%2,%0
- fpadd32s %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ add\\t%1, %2, %0
+ fpadd32s\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_plus"
[(set (reg:CC_NOOV 100)
(compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
(match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))]
- ""
- "addcc %0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "addcc\\t%0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_plus"
[(set (reg:CCX_NOOV 100)
@@ -3781,8 +4940,9 @@ return \"srl %1,0,%0\";
(match_operand:DI 1 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "addcc %0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "addcc\\t%0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_plus_set"
[(set (reg:CC_NOOV 100)
@@ -3792,7 +4952,9 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "addcc %1,%2,%0")
+ "addcc\\t%1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_plus_set"
[(set (reg:CCX_NOOV 100)
@@ -3802,12 +4964,14 @@ return \"srl %1,0,%0\";
(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
- "addcc %1,%2,%0")
+ "addcc\\t%1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_expand "subdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
""
"
{
@@ -3821,6 +4985,13 @@ return \"srl %1,0,%0\";
gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
DONE;
}
+ if (arith_double_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_PLUS (DImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
}")
(define_insn "*subdi3_sp32"
@@ -3829,29 +5000,64 @@ return \"srl %1,0,%0\";
(match_operand:DI 2 "arith_double_operand" "rHI")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
- "*
+ "#"
+ [(set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))
+ (clobber (reg:CC 100))]
+ "! TARGET_ARCH64
+ && reload_completed
+ && (GET_CODE (operands[2]) == CONST_INT
+ || GET_CODE (operands[2]) == CONST_DOUBLE)"
+ [(clobber (const_int 0))]
+ "
{
- rtx op2 = operands[2];
+ rtx highp, lowp;
- if (GET_CODE (op2) == CONST_INT
- || GET_CODE (op2) == CONST_DOUBLE)
+ highp = gen_highpart (SImode, operands[2]);
+ lowp = gen_lowpart (SImode, operands[2]);
+ if ((lowp == const0_rtx)
+ && (operands[0] == operands[1]))
{
- rtx xoperands[4];
- xoperands[0] = operands[0];
- xoperands[1] = operands[1];
- if (WORDS_BIG_ENDIAN)
- split_double (op2, &xoperands[2], &xoperands[3]);
- else
- split_double (op2, &xoperands[3], &xoperands[2]);
- if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
- output_asm_insn (\"sub %H1,%2,%H0\", xoperands);
- else
- output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands);
- return \"\";
+ emit_insn (gen_rtx_SET (VOIDmode,
+ gen_highpart (SImode, operands[0]),
+ gen_rtx_MINUS (SImode,
+ gen_highpart (SImode, operands[1]),
+ highp)));
}
- return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\";
-}"
- [(set_attr "length" "2")])
+ else
+ {
+ emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, operands[1]),
+ lowp));
+ emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1]),
+ highp));
+ }
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))
+ (clobber (reg:CC 100))]
+ "! TARGET_ARCH64
+ && reload_completed"
+ [(clobber (const_int 0))]
+ "
+{
+ emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, operands[1]),
+ gen_lowpart (SImode, operands[2])));
+ emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1]),
+ gen_highpart (SImode, operands[2])));
+ DONE;
+}")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -3859,34 +5065,73 @@ return \"srl %1,0,%0\";
(zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
- "subcc %L1,%2,%L0\;addx %H1,0,%H0"
- [(set_attr "type" "multi")])
+ "#"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))
+ (clobber (reg:CC 100))]
+ "! TARGET_ARCH64 && reload_completed"
+ [(parallel [(set (reg:CC_NOOV 100)
+ (compare:CC_NOOV (minus:SI (match_dup 3) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 5) (minus:SI (match_dup 3) (match_dup 2)))])
+ (set (match_dup 6)
+ (minus:SI (minus:SI (match_dup 4) (const_int 0))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+ "operands[3] = gen_lowpart (SImode, operands[1]);
+ operands[4] = gen_highpart (SImode, operands[1]);
+ operands[5] = gen_lowpart (SImode, operands[0]);
+ operands[6] = gen_highpart (SImode, operands[0]);")
(define_insn "*subdi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "sub %1,%2,%0")
+ "sub\\t%1, %2, %0"
+ [(set_attr "type" "binary")
+ (set_attr "length" "1")])
-(define_insn "subsi3"
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,d")
+ (minus:SI (match_operand:SI 1 "register_operand" "r,d")
+ (match_operand:SI 2 "arith_add_operand" "rI,d")))]
+ ""
+ "
+{
+ if (arith_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_PLUS (SImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
+}")
+
+(define_insn "*subsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
(minus:SI (match_operand:SI 1 "register_operand" "r,d")
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- sub %1,%2,%0
- fpsub32s %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ sub\\t%1, %2, %0
+ fpsub32s\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1")])
(define_insn "*cmp_minus_cc"
[(set (reg:CC_NOOV 100)
- (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
+ (compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
(match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))]
- ""
- "subcc %0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "subcc\\t%r0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_minus_ccx"
[(set (reg:CCX_NOOV 100)
@@ -3894,18 +5139,21 @@ return \"srl %1,0,%0\";
(match_operand:DI 1 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "subcc %0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "subcc\\t%0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
-(define_insn "*cmp_minus_cc_set"
+(define_insn "cmp_minus_cc_set"
[(set (reg:CC_NOOV 100)
- (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (compare:CC_NOOV (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_dup 1) (match_dup 2)))]
""
- "subcc %1,%2,%0")
+ "subcc\\t%r1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_minus_ccx_set"
[(set (reg:CCX_NOOV 100)
@@ -3915,7 +5163,9 @@ return \"srl %1,0,%0\";
(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
- "subcc %1,%2,%0")
+ "subcc\\t%1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
;; Integer Multiply/Divide.
@@ -3928,8 +5178,9 @@ return \"srl %1,0,%0\";
(mult:SI (match_operand:SI 1 "arith_operand" "%r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_HARD_MUL"
- "smul %1,%2,%0"
- [(set_attr "type" "imul")])
+ "smul\\t%1, %2, %0"
+ [(set_attr "type" "imul")
+ (set_attr "length" "1")])
(define_expand "muldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -3950,9 +5201,12 @@ return \"srl %1,0,%0\";
(mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "mulx %1,%2,%0")
+ "mulx\\t%1, %2, %0"
+ [(set_attr "type" "imul")
+ (set_attr "length" "1")])
;; V8plus wide multiply.
+;; XXX
(define_insn "muldi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=r,h")
(mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
@@ -3963,15 +5217,15 @@ return \"srl %1,0,%0\";
"*
{
if (sparc_check_64 (operands[1], insn) <= 0)
- output_asm_insn (\"srl %L1,0,%L1\", operands);
+ output_asm_insn (\"srl\\t%L1, 0, %L1\", operands);
if (which_alternative == 1)
- output_asm_insn (\"sllx %H1,32,%H1\", operands);
+ output_asm_insn (\"sllx\\t%H1, 32, %H1\", operands);
if (sparc_check_64 (operands[2], insn) <= 0)
- output_asm_insn (\"srl %L2,0,%L2\", operands);
+ output_asm_insn (\"srl\\t%L2, 0, %L2\", operands);
if (which_alternative == 1)
- return \"or %L1,%H1,%H1\;sllx %H2,32,%L1\;or %L2,%L1,%L1\;mulx %H1,%L1,%L0\;srlx %L0,32,%H0\";
+ return \"or\\t%L1, %H1, %H1\\n\\tsllx\\t%H2, 32, %L1\\n\\tor\\t%L2, %L1, %L1\\n\\tmulx\\t%H1, %L1, %L0\;srlx\\t%L0, 32, %H0\";
else
- return \"sllx %H1,32,%3\;sllx %H2,32,%4\;or %L1,%3,%3\;or %L2,%4,%4\;mulx %3,%4,%3\;srlx %3,32,%H0\;mov %3,%L0\";
+ return \"sllx\\t%H1, 32, %3\\n\\tsllx\\t%H2, 32, %4\\n\\tor\\t%L1, %3, %3\\n\\tor\\t%L2, %4, %4\\n\\tmulx\\t%3, %4, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
}"
[(set_attr "length" "9,8")])
@@ -3985,8 +5239,9 @@ return \"srl %1,0,%0\";
(compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
(const_int 0)))]
"TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
- "smulcc %1,%2,%0"
- [(set_attr "type" "imul")])
+ "smulcc\\t%1, %2, %0"
+ [(set_attr "type" "imul")
+ (set_attr "length" "1")])
(define_expand "mulsidi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4015,6 +5270,7 @@ return \"srl %1,0,%0\";
;; V9 puts the 64 bit product in a 64 bit register. Only out or global
;; registers can hold 64 bit values in the V8plus environment.
+;; XXX
(define_insn "mulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4022,10 +5278,11 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 3 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul %1,%2,%L0\;srlx %L0,32,%H0
- smul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+ smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+ smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
[(set_attr "length" "2,3")])
+;; XXX
(define_insn "const_mulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4033,10 +5290,11 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 3 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul %1,%2,%L0\;srlx %L0,32,%H0
- smul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+ smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+ smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
[(set_attr "length" "2,3")])
+;; XXX
(define_insn "*mulsidi3_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4044,7 +5302,7 @@ return \"srl %1,0,%0\";
"TARGET_HARD_MUL32"
"*
{
- return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
+ return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
[(set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
@@ -4052,6 +5310,7 @@ return \"srl %1,0,%0\";
;; Extra pattern, because sign_extend of a constant isn't valid.
+;; XXX
(define_insn "const_mulsidi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4059,7 +5318,7 @@ return \"srl %1,0,%0\";
"TARGET_HARD_MUL"
"*
{
- return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
+ return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
[(set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
@@ -4095,6 +5354,7 @@ return \"srl %1,0,%0\";
}
}")
+;; XXX
(define_insn "smulsi3_highpart_v8plus"
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
@@ -4109,6 +5369,7 @@ return \"srl %1,0,%0\";
[(set_attr "length" "2")])
;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
+;; XXX
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=h,r")
(subreg:SI
@@ -4120,10 +5381,11 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul %1,%2,%0\;srlx %0,%3,%0
- smul %1,%2,%4\;srlx %4,%3,%0"
+ smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+ smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
[(set_attr "length" "2")])
+;; XXX
(define_insn "const_smulsi3_highpart_v8plus"
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
@@ -4133,28 +5395,32 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul %1,%2,%0\;srlx %0,%3,%0
- smul %1,%2,%4\;srlx %4,%3,%0"
+ smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+ smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
[(set_attr "length" "2")])
+;; XXX
(define_insn "*smulsi3_highpart_sp32"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
- "TARGET_HARD_MUL32"
- "smul %1,%2,%%g0\;rd %%y,%0"
+ "TARGET_HARD_MUL32
+ && ! TARGET_LIVE_G0"
+ "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
[(set_attr "length" "2")])
+;; XXX
(define_insn "const_smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "register_operand" "r"))
(const_int 32))))]
- "TARGET_HARD_MUL32"
- "smul %1,%2,%%g0\;rd %%y,%0"
+ "TARGET_HARD_MUL32
+ && ! TARGET_LIVE_G0"
+ "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
[(set_attr "length" "2")])
(define_expand "umulsidi3"
@@ -4182,6 +5448,7 @@ return \"srl %1,0,%0\";
}
}")
+;; XXX
(define_insn "umulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4189,10 +5456,11 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 3 "=X,&h"))]
"TARGET_V8PLUS"
"@
- umul %1,%2,%L0\;srlx %L0,32,%H0
- umul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+ umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+ umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
[(set_attr "length" "2,3")])
+;; XXX
(define_insn "*umulsidi3_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4200,7 +5468,7 @@ return \"srl %1,0,%0\";
"TARGET_HARD_MUL32"
"*
{
- return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
+ return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
[(set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
@@ -4208,6 +5476,7 @@ return \"srl %1,0,%0\";
;; Extra pattern, because sign_extend of a constant isn't valid.
+;; XXX
(define_insn "const_umulsidi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4215,12 +5484,13 @@ return \"srl %1,0,%0\";
"TARGET_HARD_MUL32"
"*
{
- return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
+ return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
[(set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
(const_int 1) (const_int 2)))])
+;; XXX
(define_insn "const_umulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
@@ -4228,8 +5498,8 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 3 "=X,h"))]
"TARGET_V8PLUS"
"@
- umul %1,%2,%L0\;srlx %L0,32,%H0
- umul %1,%2,%3\;srlx %3,32,%H0\;mov %3,%L0"
+ umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
+ umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
[(set_attr "length" "2,3")])
(define_expand "umulsi3_highpart"
@@ -4262,6 +5532,7 @@ return \"srl %1,0,%0\";
}
}")
+;; XXX
(define_insn "umulsi3_highpart_v8plus"
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
@@ -4271,10 +5542,11 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 4 "=X,h"))]
"TARGET_V8PLUS"
"@
- umul %1,%2,%0\;srlx %0,%3,%0
- umul %1,%2,%4\;srlx %4,%3,%0"
+ umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+ umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
[(set_attr "length" "2")])
+;; XXX
(define_insn "const_umulsi3_highpart_v8plus"
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
@@ -4284,51 +5556,58 @@ return \"srl %1,0,%0\";
(clobber (match_scratch:SI 4 "=X,h"))]
"TARGET_V8PLUS"
"@
- umul %1,%2,%0\;srlx %0,%3,%0
- umul %1,%2,%4\;srlx %4,%3,%0"
+ umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
+ umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
[(set_attr "length" "2")])
+;; XXX
(define_insn "*umulsi3_highpart_sp32"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
- "TARGET_HARD_MUL32"
- "umul %1,%2,%%g0\;rd %%y,%0"
+ "TARGET_HARD_MUL32
+ && ! TARGET_LIVE_G0"
+ "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
[(set_attr "length" "2")])
+;; XXX
(define_insn "const_umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "uns_small_int" ""))
(const_int 32))))]
- "TARGET_HARD_MUL32"
- "umul %1,%2,%%g0\;rd %%y,%0"
+ "TARGET_HARD_MUL32
+ && ! TARGET_LIVE_G0"
+ "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
[(set_attr "length" "2")])
;; The v8 architecture specifies that there must be 3 instructions between
;; a y register write and a use of it for correct results.
+;; XXX SHEESH
(define_insn "divsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(div:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "move_operand" "rI,m")))
+ (match_operand:SI 2 "input_operand" "rI,m")))
(clobber (match_scratch:SI 3 "=&r,&r"))]
- "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ "(TARGET_V8
+ || TARGET_DEPRECATED_V8_INSNS)
+ && ! TARGET_LIVE_G0"
"*
{
if (which_alternative == 0)
if (TARGET_V9)
- return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdiv %1,%2,%0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tsdiv\\t%1, %2, %0\";
else
- return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %2, %0\";
else
if (TARGET_V9)
- return \"sra %1,31,%3\;wr %%g0,%3,%%y\;ld %2,%3\;sdiv %1,%3,%0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tld\\t%2, %3\\n\\tsdiv\\t%1, %3, %0\";
else
- return \"sra %1,31,%3\;wr %%g0,%3,%%y\;ld %2,%3\;nop\;nop\;sdiv %1,%3,%0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tld\\t%2, %3\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %3, %0\";
}"
[(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
@@ -4339,10 +5618,11 @@ return \"srl %1,0,%0\";
(div:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "sdivx %1,%2,%0")
+ "sdivx\\t%1, %2, %0")
;; It is not known whether this will match.
+;; XXX I hope it doesn't fucking match...
(define_insn "*cmp_sdiv_cc_set"
[(set (match_operand:SI 0 "register_operand" "=r")
(div:SI (match_operand:SI 1 "register_operand" "r")
@@ -4351,36 +5631,41 @@ return \"srl %1,0,%0\";
(compare:CC (div:SI (match_dup 1) (match_dup 2))
(const_int 0)))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ "(TARGET_V8
+ || TARGET_DEPRECATED_V8_INSNS)
+ && ! TARGET_LIVE_G0"
"*
{
if (TARGET_V9)
- return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdivcc %1,%2,%0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tsdivcc\\t%1, %2, %0\";
else
- return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdivcc\\t%1, %2, %0\";
}"
[(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
(const_int 3) (const_int 6)))])
+;; XXX
(define_insn "udivsi3"
[(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
(udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
- (match_operand:SI 2 "move_operand" "rI,m,r")))]
- "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ (match_operand:SI 2 "input_operand" "rI,m,r")))]
+ "(TARGET_V8
+ || TARGET_DEPRECATED_V8_INSNS)
+ && ! TARGET_LIVE_G0"
"*
{
- output_asm_insn (\"wr %%g0,%%g0,%%y\", operands);
+ output_asm_insn (\"wr\\t%%g0, %%g0, %%y\", operands);
switch (which_alternative)
{
default:
if (TARGET_V9)
- return \"udiv %1,%2,%0\";
- return \"nop\;nop\;nop\;udiv %1,%2,%0\";
+ return \"udiv\\t%1, %2, %0\";
+ return \"nop\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %2, %0\";
case 1:
- return \"ld %2,%0\;nop\;nop\;udiv %1,%0,%0\";
+ return \"ld\\t%2, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %0, %0\";
case 2:
- return \"ld %1,%0\;nop\;nop\;udiv %0,%2,%0\";
+ return \"ld\\t%1, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%0, %2, %0\";
}
}"
[(set (attr "length")
@@ -4393,10 +5678,11 @@ return \"srl %1,0,%0\";
(udiv:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "udivx %1,%2,%0")
+ "udivx\\t%1, %2, %0")
;; It is not known whether this will match.
+;; XXX I hope it doesn't fucking match...
(define_insn "*cmp_udiv_cc_set"
[(set (match_operand:SI 0 "register_operand" "=r")
(udiv:SI (match_operand:SI 1 "register_operand" "r")
@@ -4404,13 +5690,15 @@ return \"srl %1,0,%0\";
(set (reg:CC 100)
(compare:CC (udiv:SI (match_dup 1) (match_dup 2))
(const_int 0)))]
- "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ "(TARGET_V8
+ || TARGET_DEPRECATED_V8_INSNS)
+ && ! TARGET_LIVE_G0"
"*
{
if (TARGET_V9)
- return \"wr %%g0,%%g0,%%y\;udivcc %1,%2,%0\";
+ return \"wr\\t%%g0, %%g0, %%y\\n\\tudivcc\\t%1, %2, %0\";
else
- return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0\";
+ return \"wr\\t%%g0, %%g0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tudivcc\\t%1, %2, %0\";
}"
[(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
@@ -4424,8 +5712,9 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "arith_operand" "rI"))
(match_operand:SI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
- "smac %1,%2,%0"
- [(set_attr "type" "imul")])
+ "smac\\t%1, %2, %0"
+ [(set_attr "type" "imul")
+ (set_attr "length" "1")])
(define_insn "*smacdi"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -4435,8 +5724,9 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "register_operand" "r")))
(match_operand:DI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
- "smacd %1,%2,%L0"
- [(set_attr "type" "imul")])
+ "smacd\\t%1, %2, %L0"
+ [(set_attr "type" "imul")
+ (set_attr "length" "1")])
(define_insn "*umacdi"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -4446,8 +5736,9 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "register_operand" "r")))
(match_operand:DI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
- "umacd %1,%2,%L0"
- [(set_attr "type" "imul")])
+ "umacd\\t%1, %2, %L0"
+ [(set_attr "type" "imul")
+ (set_attr "length" "1")])
;;- Boolean instructions
;; We define DImode `and' so with DImode `not' we can get
@@ -4465,36 +5756,22 @@ return \"srl %1,0,%0\";
(and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"! TARGET_ARCH64"
- "*
-{
- rtx op2 = operands[2];
-
- if (which_alternative == 1)
- return \"fand %1,%2,%0\";
-
- if (GET_CODE (op2) == CONST_INT
- || GET_CODE (op2) == CONST_DOUBLE)
- {
- rtx xoperands[4];
- xoperands[0] = operands[0];
- xoperands[1] = operands[1];
- if (WORDS_BIG_ENDIAN)
- split_double (op2, &xoperands[2], &xoperands[3]);
- else
- split_double (op2, &xoperands[3], &xoperands[2]);
- output_asm_insn (\"and %L1,%3,%L0\;and %H1,%2,%H0\", xoperands);
- return \"\";
- }
- return \"and %1,%2,%0\;and %R1,%R2,%R0\";
-}"
- [(set_attr "length" "2,1")])
+ "@
+ #
+ fand\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "2,1")])
(define_insn "*anddi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,b")
+ (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
+ (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
- "and %1,%2,%0")
+ "@
+ and\\t%1, %2, %0
+ fand\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4502,9 +5779,10 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- and %1,%2,%0
- fands %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ and\\t%1, %2, %0
+ fands\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4527,12 +5805,19 @@ return \"srl %1,0,%0\";
(match_operator:DI 1 "cc_arithop" ; AND, IOR, XOR
[(match_operand:DI 2 "register_operand" "")
(match_operand:DI 3 "arith_double_operand" "")]))]
- "! TARGET_ARCH64 && reload_completed
- && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < 32"
+ "! TARGET_ARCH64
+ && reload_completed
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))"
[(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
(set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
"
{
+ if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
operands[4] = gen_highpart (SImode, operands[0]);
operands[5] = gen_lowpart (SImode, operands[0]);
operands[6] = gen_highpart (SImode, operands[2]);
@@ -4555,16 +5840,43 @@ return \"srl %1,0,%0\";
(match_operand:DI 2 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
- andn %2,%1,%0\;andn %R2,%R1,%R0
- fandnot1 %1,%2,%0"
- [(set_attr "length" "2,1")])
+ #
+ fandnot1\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "2,1")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" ""))
+ (match_operand:DI 2 "register_operand" "")))]
+ "! TARGET_ARCH64
+ && reload_completed
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))"
+ [(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
+ (set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ operands[3] = gen_highpart (SImode, operands[0]);
+ operands[4] = gen_highpart (SImode, operands[1]);
+ operands[5] = gen_highpart (SImode, operands[2]);
+ operands[6] = gen_lowpart (SImode, operands[0]);
+ operands[7] = gen_lowpart (SImode, operands[1]);
+ operands[8] = gen_lowpart (SImode, operands[2]);")
(define_insn "*and_not_di_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,b")
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
+ (match_operand:DI 2 "register_operand" "r,b")))]
"TARGET_ARCH64"
- "andn %2,%1,%0")
+ "@
+ andn\\t%2, %1, %0
+ fandnot1\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_insn "*and_not_si"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4572,9 +5884,10 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "register_operand" "r,d")))]
""
"@
- andn %2,%1,%0
- fandnot1s %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ andn\\t%2, %1, %0
+ fandnot1s\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_expand "iordi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4588,36 +5901,22 @@ return \"srl %1,0,%0\";
(ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"! TARGET_ARCH64"
- "*
-{
- rtx op2 = operands[2];
-
- if (which_alternative == 1)
- return \"for %1,%2,%0\";
-
- if (GET_CODE (op2) == CONST_INT
- || GET_CODE (op2) == CONST_DOUBLE)
- {
- rtx xoperands[4];
- xoperands[0] = operands[0];
- xoperands[1] = operands[1];
- if (WORDS_BIG_ENDIAN)
- split_double (op2, &xoperands[2], &xoperands[3]);
- else
- split_double (op2, &xoperands[3], &xoperands[2]);
- output_asm_insn (\"or %L1,%3,%L0\;or %H1,%2,%H0\", xoperands);
- return \"\";
- }
- return \"or %1,%2,%0\;or %R1,%R2,%R0\";
-}"
- [(set_attr "length" "2,1")])
+ "@
+ #
+ for\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "2,1")])
(define_insn "*iordi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,b")
+ (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
+ (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
- "or %1,%2,%0")
+ "@
+ or\\t%1, %2, %0
+ for\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4625,9 +5924,10 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- or %1,%2,%0
- fors %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ or\\t%1, %2, %0
+ fors\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4650,16 +5950,43 @@ return \"srl %1,0,%0\";
(match_operand:DI 2 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
- orn %2,%1,%0\;orn %R2,%R1,%R0
- fornot1 %1,%2,%0"
- [(set_attr "length" "2,1")])
+ #
+ fornot1\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "2,1")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ior:DI (not:DI (match_operand:DI 1 "register_operand" ""))
+ (match_operand:DI 2 "register_operand" "")))]
+ "! TARGET_ARCH64
+ && reload_completed
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))"
+ [(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
+ (set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ operands[3] = gen_highpart (SImode, operands[0]);
+ operands[4] = gen_highpart (SImode, operands[1]);
+ operands[5] = gen_highpart (SImode, operands[2]);
+ operands[6] = gen_lowpart (SImode, operands[0]);
+ operands[7] = gen_lowpart (SImode, operands[1]);
+ operands[8] = gen_lowpart (SImode, operands[2]);")
(define_insn "*or_not_di_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,b")
+ (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
+ (match_operand:DI 2 "register_operand" "r,b")))]
"TARGET_ARCH64"
- "orn %2,%1,%0")
+ "@
+ orn\\t%2, %1, %0
+ fornot1\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_insn "*or_not_si"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4667,9 +5994,10 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "register_operand" "r,d")))]
""
"@
- orn %2,%1,%0
- fornot1s %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ orn\\t%2, %1, %0
+ fornot1s\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_expand "xordi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4683,37 +6011,32 @@ return \"srl %1,0,%0\";
(xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"! TARGET_ARCH64"
- "*
-{
- rtx op2 = operands[2];
-
- if (which_alternative == 1)
- return \"fxor %1,%2,%0\";
-
- if (GET_CODE (op2) == CONST_INT
- || GET_CODE (op2) == CONST_DOUBLE)
- {
- rtx xoperands[4];
- xoperands[0] = operands[0];
- xoperands[1] = operands[1];
- if (WORDS_BIG_ENDIAN)
- split_double (op2, &xoperands[2], &xoperands[3]);
- else
- split_double (op2, &xoperands[3], &xoperands[2]);
- output_asm_insn (\"xor %L1,%3,%L0\;xor %H1,%2,%H0\", xoperands);
- return \"\";
- }
- return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
-}"
+ "@
+ #
+ fxor\\t%1, %2, %0"
[(set_attr "length" "2,1")
(set_attr "type" "ialu,fp")])
(define_insn "*xordi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,b")
+ (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ,b")
+ (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
- "xor %r1,%2,%0")
+ "@
+ xor\\t%r1, %2, %0
+ fxor\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
+
+(define_insn "*xordi3_sp64_dbl"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (xor:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "const64_operand" "")))]
+ "(TARGET_ARCH64
+ && HOST_BITS_PER_WIDE_INT != 64)"
+ "xor\\t%1, %2, %0"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4721,9 +6044,10 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- xor %r1,%2,%0
- fxors %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ xor\\t%r1, %2, %0
+ fxors\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4763,18 +6087,43 @@ return \"srl %1,0,%0\";
(match_operand:DI 2 "register_operand" "r,b"))))]
"! TARGET_ARCH64"
"@
- xnor %1,%2,%0\;xnor %R1,%R2,%R0
- fxnor %1,%2,%0"
+ #
+ fxnor\\t%1, %2, %0"
[(set_attr "length" "2,1")
(set_attr "type" "ialu,fp")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (not:DI (xor:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" ""))))]
+ "! TARGET_ARCH64
+ && reload_completed
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))"
+ [(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
+ (set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ operands[3] = gen_highpart (SImode, operands[0]);
+ operands[4] = gen_highpart (SImode, operands[1]);
+ operands[5] = gen_highpart (SImode, operands[2]);
+ operands[6] = gen_lowpart (SImode, operands[0]);
+ operands[7] = gen_lowpart (SImode, operands[1]);
+ operands[8] = gen_lowpart (SImode, operands[2]);")
+
(define_insn "*xor_not_di_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
- (match_operand:DI 2 "arith_double_operand" "rHI"))))]
+ [(set (match_operand:DI 0 "register_operand" "=r,b")
+ (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,b")
+ (match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
"TARGET_ARCH64"
- "xnor %r1,%2,%0"
- [(set_attr "type" "ialu")])
+ "@
+ xnor\\t%r1, %2, %0
+ fxnor\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
(define_insn "*xor_not_si"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4782,9 +6131,10 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "arith_operand" "rI,d"))))]
""
"@
- xnor %r1,%2,%0
- fxnors %1,%2,%0"
- [(set_attr "type" "ialu,fp")])
+ xnor\\t%r1, %2, %0
+ fxnors\\t%1, %2, %0"
+ [(set_attr "type" "ialu,fp")
+ (set_attr "length" "1,1")])
;; These correspond to the above in the case where we also (or only)
;; want to set the condition code.
@@ -4796,9 +6146,10 @@ return \"srl %1,0,%0\";
[(match_operand:SI 0 "arith_operand" "%r")
(match_operand:SI 1 "arith_operand" "rI")])
(const_int 0)))]
- ""
- "%A2cc %0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "%A2cc\\t%0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_arith_op"
[(set (reg:CCX 100)
@@ -4808,8 +6159,9 @@ return \"srl %1,0,%0\";
(match_operand:DI 1 "arith_double_operand" "rHI")])
(const_int 0)))]
"TARGET_ARCH64"
- "%A2cc %0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "%A2cc\\t%0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_arith_op_set"
[(set (reg:CC 100)
@@ -4821,7 +6173,9 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(match_dup 3))]
""
- "%A3cc %1,%2,%0")
+ "%A3cc\\t%1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_arith_op_set"
[(set (reg:CCX 100)
@@ -4833,7 +6187,9 @@ return \"srl %1,0,%0\";
(set (match_operand:DI 0 "register_operand" "=r")
(match_dup 3))]
"TARGET_ARCH64"
- "%A3cc %1,%2,%0")
+ "%A3cc\\t%1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_xor_not"
[(set (reg:CC 100)
@@ -4841,9 +6197,10 @@ return \"srl %1,0,%0\";
(not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
(match_operand:SI 1 "arith_operand" "rI")))
(const_int 0)))]
- ""
- "xnorcc %r0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "xnorcc\\t%r0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_xor_not"
[(set (reg:CCX 100)
@@ -4852,8 +6209,9 @@ return \"srl %1,0,%0\";
(match_operand:DI 1 "arith_double_operand" "rHI")))
(const_int 0)))]
"TARGET_ARCH64"
- "xnorcc %r0,%1,%%g0"
- [(set_attr "type" "compare")])
+ "xnorcc\\t%r0, %1, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_xor_not_set"
[(set (reg:CC 100)
@@ -4864,7 +6222,9 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (xor:SI (match_dup 1) (match_dup 2))))]
""
- "xnorcc %r1,%2,%0")
+ "xnorcc\\t%r1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_xor_not_set"
[(set (reg:CCX 100)
@@ -4875,7 +6235,9 @@ return \"srl %1,0,%0\";
(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (xor:DI (match_dup 1) (match_dup 2))))]
"TARGET_ARCH64"
- "xnorcc %r1,%2,%0")
+ "xnorcc\\t%r1, %2, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_arith_op_not"
[(set (reg:CC 100)
@@ -4884,9 +6246,10 @@ return \"srl %1,0,%0\";
[(not:SI (match_operand:SI 0 "arith_operand" "rI"))
(match_operand:SI 1 "reg_or_0_operand" "rJ")])
(const_int 0)))]
- ""
- "%B2cc %r1,%0,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "%B2cc\\t%r1, %0, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_arith_op_not"
[(set (reg:CCX 100)
@@ -4896,8 +6259,9 @@ return \"srl %1,0,%0\";
(match_operand:DI 1 "reg_or_0_operand" "rJ")])
(const_int 0)))]
"TARGET_ARCH64"
- "%B2cc %r1,%0,%%g0"
- [(set_attr "type" "compare")])
+ "%B2cc\\t%r1, %0, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_arith_op_not_set"
[(set (reg:CC 100)
@@ -4909,7 +6273,9 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(match_dup 3))]
""
- "%B3cc %r2,%1,%0")
+ "%B3cc\\t%r2, %1, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_arith_op_not_set"
[(set (reg:CCX 100)
@@ -4921,7 +6287,9 @@ return \"srl %1,0,%0\";
(set (match_operand:DI 0 "register_operand" "=r")
(match_dup 3))]
"TARGET_ARCH64"
- "%B3cc %r2,%1,%0")
+ "%B3cc\\t%r2, %1, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
;; We cannot use the "neg" pseudo insn because the Sun assembler
;; does not know how to make it work for constants.
@@ -4947,54 +6315,81 @@ return \"srl %1,0,%0\";
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))
(clobber (reg:CC 100))]
- "! TARGET_ARCH64"
- "*
-{
- if (TARGET_LIVE_G0)
- output_asm_insn (\"and %%g0,0,%%g0\", operands);
- return \"subcc %%g0,%L1,%L0\;subx %%g0,%H1,%H0\";
-}"
+ "! TARGET_ARCH64
+ && ! TARGET_LIVE_G0"
+ "#"
[(set_attr "type" "unary")
- ;; ??? This is wrong for TARGET_LIVE_G0 but it's not critical.
(set_attr "length" "2")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (neg:DI (match_operand:DI 1 "register_operand" "")))
+ (clobber (reg:CC 100))]
+ "! TARGET_ARCH64
+ && ! TARGET_LIVE_G0
+ && reload_completed"
+ [(parallel [(set (reg:CC_NOOV 100)
+ (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
+ (const_int 0)))
+ (set (match_dup 4) (minus:SI (const_int 0) (match_dup 5)))])
+ (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
+ (ltu:SI (reg:CC 100) (const_int 0))))]
+ "operands[2] = gen_highpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[1]);
+ operands[4] = gen_lowpart (SImode, operands[0]);
+ operands[5] = gen_lowpart (SImode, operands[1]);")
+
(define_insn "*negdi2_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))]
"TARGET_ARCH64"
- "sub %%g0,%1,%0"
+ "sub\\t%%g0, %1, %0"
[(set_attr "type" "unary")
(set_attr "length" "1")])
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+(define_expand "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (neg:SI (match_operand:SI 1 "arith_operand" "")))]
""
- "*
+ "
{
if (TARGET_LIVE_G0)
- return \"and %%g0,0,%%g0\;sub %%g0,%1,%0\";
- return \"sub %%g0,%1,%0\";
-}"
+ {
+ rtx zero_reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, zero_reg, const0_rtx));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (SImode, zero_reg,
+ operands[1])));
+ DONE;
+ }
+}")
+
+(define_insn "*negsi2_not_liveg0"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ "! TARGET_LIVE_G0"
+ "sub\\t%%g0, %1, %0"
[(set_attr "type" "unary")
- (set (attr "length")
- (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1)))])
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_neg"
[(set (reg:CC_NOOV 100)
(compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
(const_int 0)))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%0,%%g0"
- [(set_attr "type" "compare")])
+ "subcc\\t%%g0, %0, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_neg"
[(set (reg:CCX_NOOV 100)
(compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "subcc %%g0,%0,%%g0"
- [(set_attr "type" "compare")])
+ "subcc\\t%%g0, %0, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_set_neg"
[(set (reg:CC_NOOV 100)
@@ -5003,8 +6398,9 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_dup 1)))]
"! TARGET_LIVE_G0"
- "subcc %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "subcc\\t%%g0, %1, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_set_neg"
[(set (reg:CCX_NOOV 100)
@@ -5013,8 +6409,9 @@ return \"srl %1,0,%0\";
(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_dup 1)))]
"TARGET_ARCH64"
- "subcc %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "subcc\\t%%g0, %1, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
;; We cannot use the "not" pseudo insn because the Sun assembler
;; does not know how to make it work for constants.
@@ -5029,53 +6426,99 @@ return \"srl %1,0,%0\";
(not:DI (match_operand:DI 1 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
- xnor %1,0,%0\;xnor %R1,0,%R0
- fnot1 %1,%0"
+ #
+ fnot1\\t%1, %0"
[(set_attr "type" "unary,fp")
(set_attr "length" "2,1")])
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (not:DI (match_operand:DI 1 "register_operand" "")))]
+ "! TARGET_ARCH64
+ && reload_completed
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))"
+ [(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
+ (set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[1]);
+ operands[4] = gen_lowpart (SImode, operands[0]);
+ operands[5] = gen_lowpart (SImode, operands[1]);")
+
(define_insn "*one_cmpldi2_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,b")
+ (not:DI (match_operand:DI 1 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
- "xnor %1,0,%0"
- [(set_attr "type" "unary")])
+ "@
+ xnor\\t%%g0, %1, %0
+ fnot1\\t%1, %0"
+ [(set_attr "type" "unary,fp")
+ (set_attr "length" "1")])
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r,d")
- (not:SI (match_operand:SI 1 "arith_operand" "r,I,d")))]
+(define_expand "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (not:SI (match_operand:SI 1 "arith_operand" "")))]
""
- "*
+ "
{
- if (which_alternative == 0)
- return \"xnor %1,0,%0\";
- if (which_alternative == 2)
- return \"fnot1s %1,%0\";
- if (TARGET_LIVE_G0)
- output_asm_insn (\"and %%g0,0,%%g0\", operands);
- return \"xnor %%g0,%1,%0\";
-}"
- [(set_attr "type" "unary,unary,fp")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1))
- (const_int 1)])])
+ if (TARGET_LIVE_G0
+ && GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx zero_reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, zero_reg, const0_rtx));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ operands[0],
+ gen_rtx_NOT (SImode,
+ gen_rtx_XOR (SImode,
+ zero_reg,
+ operands[1]))));
+ DONE;
+ }
+}")
+
+(define_insn "*one_cmplsi2_not_liveg0"
+ [(set (match_operand:SI 0 "register_operand" "=r,d")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
+ "! TARGET_LIVE_G0"
+ "@
+ xnor\\t%%g0, %1, %0
+ fnot1s\\t%1, %0"
+ [(set_attr "type" "unary,fp")
+ (set_attr "length" "1,1")])
+
+(define_insn "*one_cmplsi2_liveg0"
+ [(set (match_operand:SI 0 "register_operand" "=r,d")
+ (not:SI (match_operand:SI 1 "arith_operand" "r,d")))]
+ "TARGET_LIVE_G0"
+ "@
+ xnor\\t%1, 0, %0
+ fnot1s\\t%1, %0"
+ [(set_attr "type" "unary,fp")
+ (set_attr "length" "1,1")])
(define_insn "*cmp_cc_not"
[(set (reg:CC 100)
(compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
(const_int 0)))]
"! TARGET_LIVE_G0"
- "xnorcc %%g0,%0,%%g0"
- [(set_attr "type" "compare")])
+ "xnorcc\\t%%g0, %0, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_not"
[(set (reg:CCX 100)
(compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "xnorcc %%g0,%0,%%g0"
- [(set_attr "type" "compare")])
+ "xnorcc\\t%%g0, %0, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_set_not"
[(set (reg:CC 100)
@@ -5084,8 +6527,9 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_dup 1)))]
"! TARGET_LIVE_G0"
- "xnorcc %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "xnorcc\\t%%g0, %1, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_ccx_set_not"
[(set (reg:CCX 100)
@@ -5094,8 +6538,9 @@ return \"srl %1,0,%0\";
(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (match_dup 1)))]
"TARGET_ARCH64"
- "xnorcc %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "xnorcc\\t%%g0, %1, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
;; Floating point arithmetic instructions.
@@ -5104,88 +6549,99 @@ return \"srl %1,0,%0\";
(plus:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "faddq %1,%2,%0"
- [(set_attr "type" "fp")])
+ "faddq\\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "adddf3"
[(set (match_operand:DF 0 "register_operand" "=e")
(plus:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "faddd %1,%2,%0"
- [(set_attr "type" "fp")])
+ "faddd\\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(plus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fadds %1,%2,%0"
- [(set_attr "type" "fp")])
+ "fadds\\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "subtf3"
[(set (match_operand:TF 0 "register_operand" "=e")
(minus:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fsubq %1,%2,%0"
- [(set_attr "type" "fp")])
+ "fsubq\\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "subdf3"
[(set (match_operand:DF 0 "register_operand" "=e")
(minus:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "fsubd %1,%2,%0"
- [(set_attr "type" "fp")])
+ "fsubd\\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "subsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(minus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fsubs %1,%2,%0"
- [(set_attr "type" "fp")])
+ "fsubs\\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "length" "1")])
(define_insn "multf3"
[(set (match_operand:TF 0 "register_operand" "=e")
(mult:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fmulq %1,%2,%0"
- [(set_attr "type" "fpmul")])
+ "fmulq\\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "length" "1")])
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=e")
(mult:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "fmuld %1,%2,%0"
- [(set_attr "type" "fpmul")])
+ "fmuld\\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "length" "1")])
(define_insn "mulsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(mult:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fmuls %1,%2,%0"
- [(set_attr "type" "fpmul")])
+ "fmuls\\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "length" "1")])
(define_insn "*muldf3_extend"
[(set (match_operand:DF 0 "register_operand" "=e")
(mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
(float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
"(TARGET_V8 || TARGET_V9) && TARGET_FPU"
- "fsmuld %1,%2,%0"
- [(set_attr "type" "fpmul")])
+ "fsmuld\\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "length" "1")])
(define_insn "*multf3_extend"
[(set (match_operand:TF 0 "register_operand" "=e")
(mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
(float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
"(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
- "fdmulq %1,%2,%0"
- [(set_attr "type" "fpmul")])
+ "fdmulq\\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "length" "1")])
;; don't have timing for quad-prec. divide.
(define_insn "divtf3"
@@ -5193,133 +6649,295 @@ return \"srl %1,0,%0\";
(div:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fdivq %1,%2,%0"
- [(set_attr "type" "fpdivd")])
+ "fdivq\\t%1, %2, %0"
+ [(set_attr "type" "fpdivd")
+ (set_attr "length" "1")])
(define_insn "divdf3"
[(set (match_operand:DF 0 "register_operand" "=e")
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "fdivd %1,%2,%0"
- [(set_attr "type" "fpdivd")])
+ "fdivd\\t%1, %2, %0"
+ [(set_attr "type" "fpdivd")
+ (set_attr "length" "1")])
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(div:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fdivs %1,%2,%0"
- [(set_attr "type" "fpdivs")])
+ "fdivs\\t%1, %2, %0"
+ [(set_attr "type" "fpdivs")
+ (set_attr "length" "1")])
-(define_insn "negtf2"
+(define_expand "negtf2"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
- ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
"TARGET_FPU"
- "*
-{
- /* v9: can't use fnegs, won't work with upper regs. */
- if (which_alternative == 0)
- return TARGET_V9 ? \"fnegd %0,%0\" : \"fnegs %0,%0\";
- else
- return TARGET_V9 ? \"fnegd %1,%0\;fmovd %S1,%S0\"
- : \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
-}"
+ "")
+
+(define_insn "*negtf2_notv9"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
+ "TARGET_FPU
+ && ! TARGET_V9"
+ "@
+ fnegs\\t%0, %0
+ #"
[(set_attr "type" "fpmove")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
+ (set_attr "length" "1,2")])
-(define_insn "negdf2"
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (neg:TF (match_operand:TF 1 "register_operand" "")))]
+ "TARGET_FPU
+ && ! TARGET_V9
+ && reload_completed
+ && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
+ [(set (match_dup 2) (neg:SF (match_dup 3)))
+ (set (match_dup 4) (match_dup 5))
+ (set (match_dup 6) (match_dup 7))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = alter_subreg (operands[1]);
+ operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
+ operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
+ operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
+ operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
+ operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+
+(define_insn "*negtf2_v9"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
+ "TARGET_FPU && TARGET_V9"
+ "@
+ fnegd\\t%0, %0
+ #"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1,2")])
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (neg:TF (match_operand:TF 1 "register_operand" "")))]
+ "TARGET_FPU
+ && TARGET_V9
+ && reload_completed
+ && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
+ [(set (match_dup 2) (neg:DF (match_dup 3)))
+ (set (match_dup 4) (match_dup 5))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = alter_subreg (operands[1]);
+ operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
+ operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
+ operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
+ operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+
+(define_expand "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "")
+ (neg:DF (match_operand:DF 1 "register_operand" "")))]
+ "TARGET_FPU"
+ "")
+
+(define_insn "*negdf2_notv9"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
- "TARGET_FPU"
- "*
-{
- if (TARGET_V9)
- return \"fnegd %1,%0\";
- else if (which_alternative == 0)
- return \"fnegs %0,%0\";
- else
- return \"fnegs %1,%0\;fmovs %R1,%R0\";
-}"
+ "TARGET_FPU && ! TARGET_V9"
+ "@
+ fnegs\\t%0, %0
+ #"
[(set_attr "type" "fpmove")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])])
+ (set_attr "length" "1,2")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (neg:DF (match_operand:DF 1 "register_operand" "")))]
+ "TARGET_FPU
+ && ! TARGET_V9
+ && reload_completed
+ && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
+ [(set (match_dup 2) (neg:SF (match_dup 3)))
+ (set (match_dup 4) (match_dup 5))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = alter_subreg (operands[1]);
+ operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
+ operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
+ operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
+
+(define_insn "*negdf2_v9"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (neg:DF (match_operand:DF 1 "register_operand" "e")))]
+ "TARGET_FPU && TARGET_V9"
+ "fnegd\\t%1, %0"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(neg:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fnegs %1,%0"
- [(set_attr "type" "fpmove")])
+ "fnegs\\t%1, %0"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1")])
+
+(define_expand "abstf2"
+ [(set (match_operand:TF 0 "register_operand" "")
+ (abs:TF (match_operand:TF 1 "register_operand" "")))]
+ "TARGET_FPU"
+ "")
-(define_insn "abstf2"
+(define_insn "*abstf2_notv9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
+ "TARGET_FPU && ! TARGET_V9"
+ "@
+ fabss\\t%0, %0
+ #"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1,2")])
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ "TARGET_FPU
+ && ! TARGET_V9
+ && reload_completed
+ && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
+ [(set (match_dup 2) (abs:SF (match_dup 3)))
+ (set (match_dup 4) (match_dup 5))
+ (set (match_dup 6) (match_dup 7))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = alter_subreg (operands[1]);
+ operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
+ operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
+ operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
+ operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
+ operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+
+(define_insn "*abstf2_hq_v9"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ "TARGET_FPU && TARGET_V9 && TARGET_HARD_QUAD"
+ "@
+ fabsd\\t%0, %0
+ fabsq\\t%1, %0"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1")])
+
+(define_insn "*abstf2_v9"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ "TARGET_FPU && TARGET_V9 && !TARGET_HARD_QUAD"
+ "@
+ fabsd\\t%0, %0
+ #"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1,2")])
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ "TARGET_FPU
+ && TARGET_V9
+ && reload_completed
+ && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
+ [(set (match_dup 2) (abs:DF (match_dup 3)))
+ (set (match_dup 4) (match_dup 5))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = alter_subreg (operands[1]);
+ operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
+ operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
+ operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
+ operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+
+(define_expand "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "")
+ (abs:DF (match_operand:DF 1 "register_operand" "")))]
"TARGET_FPU"
- "*
-{
- /* v9: can't use fabss, won't work with upper regs. */
- if (which_alternative == 0)
- return TARGET_V9 ? \"fabsd %0,%0\" : \"fabss %0,%0\";
- else
- return TARGET_V9 ? \"fabsd %1,%0\;fmovd %S1,%S0\"
- : \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
-}"
+ "")
+
+(define_insn "*absdf2_notv9"
+ [(set (match_operand:DF 0 "register_operand" "=e,e")
+ (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
+ "TARGET_FPU && ! TARGET_V9"
+ "@
+ fabss\\t%0, %0
+ #"
[(set_attr "type" "fpmove")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
+ (set_attr "length" "1,2")])
-(define_insn "absdf2"
+(define_split
[(set (match_operand:DF 0 "register_operand" "=e,e")
(abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
- "TARGET_FPU"
- "*
-{
- if (TARGET_V9)
- return \"fabsd %1,%0\";
- else if (which_alternative == 0)
- return \"fabss %0,%0\";
- else
- return \"fabss %1,%0\;fmovs %R1,%R0\";
-}"
+ "TARGET_FPU
+ && ! TARGET_V9
+ && reload_completed
+ && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
+ [(set (match_dup 2) (abs:SF (match_dup 3)))
+ (set (match_dup 4) (match_dup 5))]
+ "if (GET_CODE (operands[0]) == SUBREG)
+ operands[0] = alter_subreg (operands[0]);
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = alter_subreg (operands[1]);
+ operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
+ operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
+ operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
+
+(define_insn "*absdf2_v9"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (abs:DF (match_operand:DF 1 "register_operand" "e")))]
+ "TARGET_FPU && TARGET_V9"
+ "fabsd\\t%1, %0"
[(set_attr "type" "fpmove")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])])
+ (set_attr "length" "1")])
(define_insn "abssf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(abs:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fabss %1,%0"
- [(set_attr "type" "fpmove")])
+ "fabss\\t%1, %0"
+ [(set_attr "type" "fpmove")
+ (set_attr "length" "1")])
(define_insn "sqrttf2"
[(set (match_operand:TF 0 "register_operand" "=e")
(sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fsqrtq %1,%0"
- [(set_attr "type" "fpsqrt")])
+ "fsqrtq\\t%1, %0"
+ [(set_attr "type" "fpsqrt")
+ (set_attr "length" "1")])
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU"
- "fsqrtd %1,%0"
- [(set_attr "type" "fpsqrt")])
+ "fsqrtd\\t%1, %0"
+ [(set_attr "type" "fpsqrt")
+ (set_attr "length" "1")])
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fsqrts %1,%0"
- [(set_attr "type" "fpsqrt")])
+ "fsqrts\\t%1, %0"
+ [(set_attr "type" "fpsqrt")
+ (set_attr "length" "1")])
;;- arithmetic shift instructions
@@ -5334,9 +6952,21 @@ return \"srl %1,0,%0\";
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
- return \"sll %1,%2,%0\";
+ return \"sll\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")])
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+
+;; We special case multiplication by two, as add can be done
+;; in both ALUs, while shift only in IEU0 on UltraSPARC.
+(define_insn "*ashlsi3_const1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 1)))]
+ ""
+ "add\\t%1, %1, %0"
+ [(set_attr "type" "binary")
+ (set_attr "length" "1")])
(define_expand "ashldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5354,7 +6984,18 @@ return \"srl %1,0,%0\";
}
}")
-(define_insn ""
+;; We special case multiplication by two, as add can be done
+;; in both ALUs, while shift only in IEU0 on UltraSPARC.
+(define_insn "*ashldi3_const1"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashift:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 1)))]
+ "TARGET_ARCH64"
+ "add\\t%1, %1, %0"
+ [(set_attr "type" "binary")
+ (set_attr "length" "1")])
+
+(define_insn "*ashldi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
@@ -5362,12 +7003,15 @@ return \"srl %1,0,%0\";
"*
{
if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
- return \"sllx %1,%2,%0\";
-}")
+ return \"sllx\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+;; XXX UGH!
(define_insn "ashldi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
(ashift:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
@@ -5378,12 +7022,14 @@ return \"srl %1,0,%0\";
[(set_attr "length" "5,5,6")])
;; Optimize (1LL<<x)-1
+;; XXX this also needs to be fixed to handle equal subregs
+;; XXX first before we could re-enable it.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=h")
(plus:DI (ashift:DI (const_int 1)
(match_operand:SI 2 "arith_operand" "rI"))
(const_int -1)))]
- "TARGET_V8PLUS"
+ "0 && TARGET_V8PLUS"
"*
{
if (GET_CODE (operands[2]) == REG && REGNO (operands[2]) == REGNO (operands[0]))
@@ -5397,9 +7043,10 @@ return \"srl %1,0,%0\";
(compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
(const_int 1))
(const_int 0)))]
- ""
- "addcc %0,%0,%%g0"
- [(set_attr "type" "compare")])
+ "! TARGET_LIVE_G0"
+ "addcc\\t%0, %0, %%g0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "*cmp_cc_set_ashift_1"
[(set (reg:CC_NOOV 100)
@@ -5409,7 +7056,9 @@ return \"srl %1,0,%0\";
(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (match_dup 1) (const_int 1)))]
""
- "addcc %1,%1,%0")
+ "addcc\\t%1, %1, %0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "1")])
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -5422,9 +7071,42 @@ return \"srl %1,0,%0\";
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
- return \"sra %1,%2,%0\";
+ return \"sra\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+
+(define_insn "*ashrsi3_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "r"))))]
+ "TARGET_ARCH64"
+ "sra\\t%1, %2, %0"
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+
+;; This handles the case as above, but with constant shift instead of
+;; register. Combiner "simplifies" it for us a little bit though.
+(define_insn "*ashrsi3_extend2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
+ (const_int 32))
+ (match_operand:SI 2 "small_int_or_double" "n")))]
+ "TARGET_ARCH64
+ && ((GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64)
+ || (GET_CODE (operands[2]) == CONST_DOUBLE
+ && !CONST_DOUBLE_HIGH (operands[2])
+ && CONST_DOUBLE_LOW (operands[2]) >= 32
+ && CONST_DOUBLE_LOW (operands[2]) < 64))"
+ "*
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+
+ return \"sra\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")])
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
(define_expand "ashrdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5432,13 +7114,15 @@ return \"srl %1,0,%0\";
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64 || TARGET_V8PLUS"
"
-if (! TARGET_ARCH64)
- {
- if (GET_CODE (operands[2]) == CONST_INT)
- FAIL; /* prefer generic code in this case */
- emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
- DONE;
- }")
+{
+ if (! TARGET_ARCH64)
+ {
+ if (GET_CODE (operands[2]) == CONST_INT)
+ FAIL; /* prefer generic code in this case */
+ emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+}")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5451,9 +7135,12 @@ if (! TARGET_ARCH64)
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
- return \"srax %1,%2,%0\";
-}")
+ return \"srax\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+;; XXX
(define_insn "ashrdi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
(ashiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
@@ -5474,9 +7161,54 @@ if (! TARGET_ARCH64)
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
- return \"srl %1,%2,%0\";
+ return \"srl\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+
+;; This handles the case where
+;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI))),
+;; but combiner "simplifies" it for us.
+(define_insn "*lshrsi3_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "r")) 0)
+ (match_operand 3 "" "")))]
+ "TARGET_ARCH64
+ && ((GET_CODE (operands[3]) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (operands[3]) == 0
+ && CONST_DOUBLE_LOW (operands[3]) == 0xffffffff)
+#if HOST_BITS_PER_WIDE_INT >= 64
+ || (GET_CODE (operands[3]) == CONST_INT
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff)
+#endif
+ )"
+ "srl\\t%1, %2, %0"
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+
+;; This handles the case where
+;; (lshiftrt:DI (zero_extend:DI (match_operand:SI)) (const_int >=0 < 32))
+;; but combiner "simplifies" it for us.
+(define_insn "*lshrsi3_extend2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
+ (match_operand 2 "small_int_or_double" "n")
+ (const_int 32)))]
+ "TARGET_ARCH64
+ && ((GET_CODE (operands[2]) == CONST_INT
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
+ || (GET_CODE (operands[2]) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (operands[2]) == 0
+ && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
+ "*
+{
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+
+ return \"srl\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")])
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5484,13 +7216,15 @@ if (! TARGET_ARCH64)
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64 || TARGET_V8PLUS"
"
-if (! TARGET_ARCH64)
- {
- if (GET_CODE (operands[2]) == CONST_INT)
- FAIL;
- emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
- DONE;
- }")
+{
+ if (! TARGET_ARCH64)
+ {
+ if (GET_CODE (operands[2]) == CONST_INT)
+ FAIL;
+ emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+}")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5503,9 +7237,12 @@ if (! TARGET_ARCH64)
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
- return \"srlx %1,%2,%0\";
-}")
+ return \"srlx\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")
+ (set_attr "length" "1")])
+;; XXX
(define_insn "lshrdi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
(lshiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
@@ -5524,19 +7261,19 @@ if (! TARGET_ARCH64)
""
"*
{
- /* Some implementations (e.g. TurboSparc) are reported to have problems
+ /* TurboSparc is reported to have problems with
with
foo: b,a foo
i.e. an empty loop with the annul bit set. The workaround is to use
foo: b foo; nop
instead. */
- if (flag_delayed_branch
+ if (! TARGET_V9 && flag_delayed_branch
&& (insn_addresses[INSN_UID (operands[0])]
== insn_addresses[INSN_UID (insn)]))
- return \"b %l0%#\";
+ return \"b\\t%l0%#\";
else
- return \"b%* %l0%(\";
+ return TARGET_V9 ? \"ba,pt%*\\t%%xcc, %l0%(\" : \"b%*\\t%l0%(\";
}"
[(set_attr "type" "uncond_branch")])
@@ -5546,7 +7283,7 @@ if (! TARGET_ARCH64)
""
"
{
- if (GET_MODE (operands[0]) != Pmode)
+ if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
abort ();
/* In pic mode, our address differences are against the base of the
@@ -5557,6 +7294,8 @@ if (! TARGET_ARCH64)
rtx tmp, tmp2;
tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
tmp2 = operands[0];
+ if (CASE_VECTOR_MODE != Pmode)
+ tmp2 = gen_rtx_SIGN_EXTEND (Pmode, tmp2);
tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
operands[0] = memory_address (Pmode, tmp);
}
@@ -5566,14 +7305,14 @@ if (! TARGET_ARCH64)
[(set (pc) (match_operand:SI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
"! TARGET_PTR64"
- "jmp %a0%#"
+ "jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
(define_insn "*tablejump_sp64"
[(set (pc) (match_operand:DI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_PTR64"
- "jmp %a0%#"
+ "jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
;; This pattern recognizes the "instruction" that appears in
@@ -5582,7 +7321,7 @@ if (! TARGET_ARCH64)
;(define_insn "*unimp_insn"
; [(match_operand:SI 0 "immediate_operand" "")]
; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
-; "unimp %0"
+; "unimp\\t%0"
; [(set_attr "type" "marker")])
;;- jump to subroutine
@@ -5681,7 +7420,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_PTR64"
- "call %a0,%1%#"
+ "call\\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_symbolic_sp32"
@@ -5690,7 +7429,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_PTR64"
- "call %a0,%1%#"
+ "call\\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_address_sp64"
@@ -5699,7 +7438,7 @@ if (! TARGET_ARCH64)
(clobber (reg:DI 15))]
;;- Do not use operand 1 for most machines.
"TARGET_PTR64"
- "call %a0,%1%#"
+ "call\\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_symbolic_sp64"
@@ -5708,7 +7447,7 @@ if (! TARGET_ARCH64)
(clobber (reg:DI 15))]
;;- Do not use operand 1 for most machines.
"TARGET_PTR64"
- "call %a0,%1%#"
+ "call\\t%a0, %1%#"
[(set_attr "type" "call")])
;; This is a call that wants a structure value.
@@ -5720,7 +7459,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
- "call %a0,%1\;nop\;unimp %2"
+ "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
[(set_attr "type" "call_no_delay_slot")])
;; This is a call that wants a structure value.
@@ -5732,7 +7471,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
- "call %a0,%1\;nop\;unimp %2"
+ "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
[(set_attr "type" "call_no_delay_slot")])
;; This is a call that may want a structure value. This is used for
@@ -5744,7 +7483,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
- "call %a0,%1\;nop\;nop"
+ "call\\t%a0, %1\\n\\tnop\\n\\tnop"
[(set_attr "type" "call_no_delay_slot")])
;; This is a call that wants a structure value.
@@ -5755,7 +7494,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
- "call %a0,%1\;nop\;nop"
+ "call\\t%a0, %1\\n\\tnop\\n\\tnop"
[(set_attr "type" "call_no_delay_slot")])
(define_expand "call_value"
@@ -5803,7 +7542,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 2 for most machines.
"! TARGET_PTR64"
- "call %a1,%2%#"
+ "call\\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_symbolic_sp32"
@@ -5813,7 +7552,7 @@ if (! TARGET_ARCH64)
(clobber (reg:SI 15))]
;;- Do not use operand 2 for most machines.
"! TARGET_PTR64"
- "call %a1,%2%#"
+ "call\\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_address_sp64"
@@ -5823,7 +7562,7 @@ if (! TARGET_ARCH64)
(clobber (reg:DI 15))]
;;- Do not use operand 2 for most machines.
"TARGET_PTR64"
- "call %a1,%2%#"
+ "call\\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_symbolic_sp64"
@@ -5833,7 +7572,7 @@ if (! TARGET_ARCH64)
(clobber (reg:DI 15))]
;;- Do not use operand 2 for most machines.
"TARGET_PTR64"
- "call %a1,%2%#"
+ "call\\t%a1, %2%#"
[(set_attr "type" "call")])
(define_expand "untyped_call"
@@ -5871,7 +7610,8 @@ if (! TARGET_ARCH64)
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 0)]
""
- "")
+ ""
+ [(set_attr "length" "0")])
;; Prepare to return any type including a structure value.
@@ -5887,7 +7627,8 @@ if (! TARGET_ARCH64)
if (! TARGET_ARCH64)
{
- rtx rtnreg = gen_rtx_REG (SImode, (leaf_function ? 15 : 31));
+ rtx rtnreg = gen_rtx_REG (SImode, (current_function_uses_only_leaf_regs
+ ? 15 : 31));
rtx value = gen_reg_rtx (SImode);
/* Fetch the instruction where we will return to and see if it's an unimp
@@ -5938,12 +7679,14 @@ if (! TARGET_ARCH64)
(parallel [(return)
(use (reg:SI 31))])]
"sparc_return_peephole_ok (operands[0], operands[1])"
- "return %%i7+8\;mov %Y1,%Y0")
+ "return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0")
(define_insn "nop"
[(const_int 0)]
""
- "nop")
+ "nop"
+ [(set_attr "type" "ialu")
+ (set_attr "length" "1")])
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "address_operand" "p"))]
@@ -5953,13 +7696,13 @@ if (! TARGET_ARCH64)
(define_insn "*branch_sp32"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))]
"! TARGET_PTR64"
- "jmp %a0%#"
+ "jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
(define_insn "*branch_sp64"
[(set (pc) (match_operand:DI 0 "address_operand" "p"))]
"TARGET_PTR64"
- "jmp %a0%#"
+ "jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
;; ??? Doesn't work with -mflat.
@@ -5971,7 +7714,9 @@ if (! TARGET_ARCH64)
""
"
{
+#if 0
rtx chain = operands[0];
+#endif
rtx fp = operands[1];
rtx stack = operands[2];
rtx lab = operands[3];
@@ -6001,6 +7746,8 @@ if (! TARGET_ARCH64)
really needed. */
/*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+
+#if 0
/* Return, restoring reg window and jumping to goto handler. */
if (TARGET_V9 && GET_CODE (chain) == CONST_INT
&& ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
@@ -6012,6 +7759,8 @@ if (! TARGET_ARCH64)
}
/* Put in the static chain register the nonlocal label address. */
emit_move_insn (static_chain_rtx, chain);
+#endif
+
emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
emit_insn (gen_goto_handler_and_restore (labreg));
emit_barrier ();
@@ -6022,37 +7771,38 @@ if (! TARGET_ARCH64)
(define_insn "flush_register_windows"
[(unspec_volatile [(const_int 0)] 1)]
""
- "* return TARGET_V9 ? \"flushw\" : \"ta 3\";"
- [(set_attr "type" "misc")])
+ "* return TARGET_V9 ? \"flushw\" : \"ta\\t3\";"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn "goto_handler_and_restore"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r")] 2)]
+ [(unspec_volatile [(match_operand 0 "register_operand" "=r")] 2)]
""
- "jmp %0+0\;restore"
+ "jmp\\t%0+0\\n\\trestore"
[(set_attr "type" "misc")
(set_attr "length" "2")])
-(define_insn "goto_handler_and_restore_v9"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
- (match_operand:SI 1 "register_operand" "=r,r")
- (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
- "TARGET_V9 && ! TARGET_ARCH64"
- "@
- return %0+0\;mov %2,%Y1
- sethi %%hi(%2),%1\;return %0+0\;or %Y1,%%lo(%2),%Y1"
- [(set_attr "type" "misc")
- (set_attr "length" "2,3")])
-
-(define_insn "*goto_handler_and_restore_v9_sp64"
- [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
- (match_operand:DI 1 "register_operand" "=r,r")
- (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
- "TARGET_V9 && TARGET_ARCH64"
- "@
- return %0+0\;mov %2,%Y1
- sethi %%hi(%2),%1\;return %0+0\;or %Y1,%%lo(%2),%Y1"
- [(set_attr "type" "misc")
- (set_attr "length" "2,3")])
+;;(define_insn "goto_handler_and_restore_v9"
+;; [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
+;; (match_operand:SI 1 "register_operand" "=r,r")
+;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
+;; "TARGET_V9 && ! TARGET_ARCH64"
+;; "@
+;; return\\t%0+0\\n\\tmov\\t%2, %Y1
+;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
+;; [(set_attr "type" "misc")
+;; (set_attr "length" "2,3")])
+;;
+;;(define_insn "*goto_handler_and_restore_v9_sp64"
+;; [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
+;; (match_operand:DI 1 "register_operand" "=r,r")
+;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
+;; "TARGET_V9 && TARGET_ARCH64"
+;; "@
+;; return\\t%0+0\\n\\tmov\\t%2, %Y1
+;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
+;; [(set_attr "type" "misc")
+;; (set_attr "length" "2,3")])
;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.
@@ -6086,10 +7836,11 @@ if (! TARGET_ARCH64)
;; Special pattern for the FLUSH instruction.
(define_insn "flush"
- [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 3)]
+ [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 4)]
""
- "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";"
- [(set_attr "type" "misc")])
+ "* return TARGET_V9 ? \"flush\\t%f0\" : \"iflush\\t%f0\";"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
;; find first set.
@@ -6098,6 +7849,7 @@ if (! TARGET_ARCH64)
;; zero also differ. It takes at least 7 instructions to get the proper
;; result. Here is an obvious 8 instruction sequence.
+;; XXX
(define_insn "ffssi2"
[(set (match_operand:SI 0 "register_operand" "=&r")
(ffs:SI (match_operand:SI 1 "register_operand" "r")))
@@ -6126,205 +7878,7 @@ if (! TARGET_ARCH64)
; "neg %1,%2\;xnor %1,%2,%2\;popc %2,%0\;movzr %1,0,%0"
; [(set_attr "type" "multi")
; (set_attr "length" "4")])
-
-;; Split up troublesome insns for better scheduling. */
-
-;; The following patterns are straightforward. They can be applied
-;; either before or after register allocation.
-
-(define_split
- [(set (match_operand 0 "splittable_symbolic_memory_operand" "")
- (match_operand 1 "reg_or_0_operand" ""))
- (clobber (match_operand:SI 2 "register_operand" ""))]
- "! flag_pic"
- [(set (match_dup 2) (high:SI (match_dup 3)))
- (set (match_dup 4) (match_dup 1))]
- "
-{
- operands[3] = XEXP (operands[0], 0);
- operands[4] = gen_rtx_MEM (GET_MODE (operands[0]),
- gen_rtx_LO_SUM (SImode, operands[2], operands[3]));
- MEM_IN_STRUCT_P (operands[4]) = MEM_IN_STRUCT_P (operands[0]);
- MEM_VOLATILE_P (operands[4]) = MEM_VOLATILE_P (operands[0]);
- RTX_UNCHANGING_P (operands[4]) = RTX_UNCHANGING_P (operands[0]);
-}")
-(define_split
- [(set (match_operand 0 "splittable_immediate_memory_operand" "")
- (match_operand 1 "general_operand" ""))
- (clobber (match_operand:SI 2 "register_operand" ""))]
- "flag_pic"
- [(set (match_dup 3) (match_dup 1))]
- "
-{
- rtx addr = legitimize_pic_address (XEXP (operands[0], 0),
- GET_MODE (operands[0]),
- operands[2]);
- operands[3] = gen_rtx_MEM (GET_MODE (operands[0]), addr);
- MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[0]);
- MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[0]);
- RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[0]);
-}")
-
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (match_operand 1 "splittable_immediate_memory_operand" ""))]
- "flag_pic"
- [(set (match_dup 0) (match_dup 2))]
- "
-{
- rtx addr = legitimize_pic_address (XEXP (operands[1], 0),
- GET_MODE (operands[1]),
- operands[0]);
- operands[2] = gen_rtx_MEM (GET_MODE (operands[1]), addr);
- MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
- MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]);
- RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
-}")
-
-;; Sign- and Zero-extend operations can have symbolic memory operands.
-
-(define_split
- [(set (match_operand 0 "register_operand" "")
- (match_operator 1 "extend_op" [(match_operand 2 "splittable_immediate_memory_operand" "")]))]
- "flag_pic"
- [(set (match_dup 0) (match_op_dup 1 [(match_dup 3)]))]
- "
-{
- rtx addr = legitimize_pic_address (XEXP (operands[2], 0),
- GET_MODE (operands[2]),
- operands[0]);
- operands[3] = gen_rtx_MEM (GET_MODE (operands[2]), addr);
- MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[2]);
- MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[2]);
- RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[2]);
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "immediate_operand" ""))]
- "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
- || GET_CODE (operands[1]) == CONST
- || GET_CODE (operands[1]) == LABEL_REF)"
- [(set (match_dup 0) (high:SI (match_dup 1)))
- (set (match_dup 0)
- (lo_sum:SI (match_dup 0) (match_dup 1)))]
- "")
-
-;; LABEL_REFs are not modified by `legitimize_pic_address'
-;; so do not recurse infinitely in the PIC case.
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "immediate_operand" ""))]
- "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
- || GET_CODE (operands[1]) == CONST)"
- [(set (match_dup 0) (match_dup 1))]
- "
-{
- operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]);
-}")
-
-;; These split sne/seq insns. The forms of the resulting insns are
-;; somewhat bogus, but they avoid extra patterns and show data dependency.
-;; Nothing will look at these in detail after splitting has occurred.
-
-;; ??? v9 DImode versions are missing because addc and subc use %icc.
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0)))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0)))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))
- (match_operand:SI 2 "register_operand" "")))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
- (match_dup 2)))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 2 "register_operand" "")
- (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (minus:SI (match_dup 2)
- (ltu:SI (reg:CC 100) (const_int 0))))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))
- (match_operand:SI 2 "register_operand" "")))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
- (match_dup 2)))]
- "")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 2 "register_operand" "")
- (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
- ""
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (minus:SI (match_dup 2)
- (geu:SI (reg:CC 100) (const_int 0))))]
- "")
;; Peepholes go at the end.
@@ -6338,9 +7892,10 @@ if (! TARGET_ARCH64)
(set (match_operand:SI 1 "memory_operand" "")
(const_int 0))]
"TARGET_V9
- && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[1])
+ && ! MEM_VOLATILE_P (operands[0])
+ && ! MEM_VOLATILE_P (operands[1])
&& addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[1], 0))"
- "stx %%g0,%0")
+ "stx\\t%%g0, %0")
(define_peephole
[(set (match_operand:SI 0 "memory_operand" "")
@@ -6348,89 +7903,98 @@ if (! TARGET_ARCH64)
(set (match_operand:SI 1 "memory_operand" "")
(const_int 0))]
"TARGET_V9
- && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[1])
+ && ! MEM_VOLATILE_P (operands[0])
+ && ! MEM_VOLATILE_P (operands[1])
&& addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[0], 0))"
- "stx %%g0,%1")
+ "stx\\t%%g0, %1")
(define_peephole
[(set (match_operand:SI 0 "register_operand" "=rf")
(match_operand:SI 1 "memory_operand" ""))
(set (match_operand:SI 2 "register_operand" "=rf")
(match_operand:SI 3 "memory_operand" ""))]
- "registers_ok_for_ldd_peep (operands[0], operands[2])
- && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
+ "registers_ok_for_ldd_peep (operands[0], operands[2])
+ && ! MEM_VOLATILE_P (operands[1])
+ && ! MEM_VOLATILE_P (operands[3])
&& addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
- "ldd %1,%0")
+ "ldd\\t%1, %0")
(define_peephole
[(set (match_operand:SI 0 "memory_operand" "")
(match_operand:SI 1 "register_operand" "rf"))
(set (match_operand:SI 2 "memory_operand" "")
(match_operand:SI 3 "register_operand" "rf"))]
- "registers_ok_for_ldd_peep (operands[1], operands[3])
- && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
+ "registers_ok_for_ldd_peep (operands[1], operands[3])
+ && ! MEM_VOLATILE_P (operands[0])
+ && ! MEM_VOLATILE_P (operands[2])
&& addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
- "std %1,%0")
+ "std\\t%1, %0")
(define_peephole
[(set (match_operand:SF 0 "register_operand" "=fr")
(match_operand:SF 1 "memory_operand" ""))
(set (match_operand:SF 2 "register_operand" "=fr")
(match_operand:SF 3 "memory_operand" ""))]
- "registers_ok_for_ldd_peep (operands[0], operands[2])
- && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
+ "registers_ok_for_ldd_peep (operands[0], operands[2])
+ && ! MEM_VOLATILE_P (operands[1])
+ && ! MEM_VOLATILE_P (operands[3])
&& addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
- "ldd %1,%0")
+ "ldd\\t%1, %0")
(define_peephole
[(set (match_operand:SF 0 "memory_operand" "")
(match_operand:SF 1 "register_operand" "fr"))
(set (match_operand:SF 2 "memory_operand" "")
(match_operand:SF 3 "register_operand" "fr"))]
- "registers_ok_for_ldd_peep (operands[1], operands[3])
- && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
- && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
- "std %1,%0")
+ "registers_ok_for_ldd_peep (operands[1], operands[3])
+ && ! MEM_VOLATILE_P (operands[0])
+ && ! MEM_VOLATILE_P (operands[2])
+ && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
+ "std\\t%1, %0")
(define_peephole
[(set (match_operand:SI 0 "register_operand" "=rf")
(match_operand:SI 1 "memory_operand" ""))
(set (match_operand:SI 2 "register_operand" "=rf")
(match_operand:SI 3 "memory_operand" ""))]
- "registers_ok_for_ldd_peep (operands[2], operands[0])
- && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
- && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
- "ldd %3,%2")
+ "registers_ok_for_ldd_peep (operands[2], operands[0])
+ && ! MEM_VOLATILE_P (operands[3])
+ && ! MEM_VOLATILE_P (operands[1])
+ && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
+ "ldd\\t%3, %2")
(define_peephole
[(set (match_operand:SI 0 "memory_operand" "")
(match_operand:SI 1 "register_operand" "rf"))
(set (match_operand:SI 2 "memory_operand" "")
(match_operand:SI 3 "register_operand" "rf"))]
- "registers_ok_for_ldd_peep (operands[3], operands[1])
- && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
- && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
- "std %3,%2")
+ "registers_ok_for_ldd_peep (operands[3], operands[1])
+ && ! MEM_VOLATILE_P (operands[2])
+ && ! MEM_VOLATILE_P (operands[0])
+ && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
+ "std\\t%3, %2")
(define_peephole
[(set (match_operand:SF 0 "register_operand" "=fr")
(match_operand:SF 1 "memory_operand" ""))
(set (match_operand:SF 2 "register_operand" "=fr")
(match_operand:SF 3 "memory_operand" ""))]
- "registers_ok_for_ldd_peep (operands[2], operands[0])
- && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
- && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
- "ldd %3,%2")
+ "registers_ok_for_ldd_peep (operands[2], operands[0])
+ && ! MEM_VOLATILE_P (operands[3])
+ && ! MEM_VOLATILE_P (operands[1])
+ && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
+ "ldd\\t%3, %2")
(define_peephole
[(set (match_operand:SF 0 "memory_operand" "")
(match_operand:SF 1 "register_operand" "fr"))
(set (match_operand:SF 2 "memory_operand" "")
(match_operand:SF 3 "register_operand" "fr"))]
- "registers_ok_for_ldd_peep (operands[3], operands[1])
- && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
- && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
- "std %3,%2")
+ "registers_ok_for_ldd_peep (operands[3], operands[1])
+ && ! MEM_VOLATILE_P (operands[2])
+ && ! MEM_VOLATILE_P (operands[0])
+ && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
+ "std\\t%3, %2")
;; Optimize the case of following a reg-reg move with a test
;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
@@ -6444,8 +8008,9 @@ if (! TARGET_ARCH64)
(const_int 0)))]
"(rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[2], operands[1]))
- && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
- "orcc %1,0,%0")
+ && ! FP_REG_P (operands[0])
+ && ! FP_REG_P (operands[1])"
+ "orcc\\t%1, 0, %0")
(define_peephole
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -6456,37 +8021,9 @@ if (! TARGET_ARCH64)
"TARGET_ARCH64
&& (rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[2], operands[1]))
- && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
- "orcc %1,0,%0")
-
-;; Floating-point move peepholes
-;; ??? v9: Do we want similar ones?
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_dup 0)
- (match_operand:SI 1 "immediate_operand" "i")))
- (set (match_operand:DF 2 "register_operand" "=er")
- (mem:DF (match_dup 0)))]
- "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
- "*
-{
- /* Go by way of output_move_double in case the register in operand 2
- is not properly aligned for ldd. */
- operands[1] = gen_rtx_MEM (DFmode,
- gen_rtx_LO_SUM (SImode, operands[0], operands[1]));
- operands[0] = operands[2];
- return output_move_double (operands);
-}")
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_dup 0)
- (match_operand:SI 1 "immediate_operand" "i")))
- (set (match_operand:SF 2 "register_operand" "=fr")
- (mem:SF (match_dup 0)))]
- "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
- "ld [%0+%%lo(%a1)],%2")
+ && ! FP_REG_P (operands[0])
+ && ! FP_REG_P (operands[1])"
+ "orcc\\t%1, 0, %0")
;; Return peepholes. First the "normal" ones.
;; These are necessary to catch insns ending up in the epilogue delay list.
@@ -6499,12 +8036,12 @@ if (! TARGET_ARCH64)
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+ return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[1])))
- return \"return %%i7+8\;mov %Y1,%Y0\";
+ return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
else
- return \"ret\;restore %%g0,%1,%Y0\";
+ return \"ret\\n\\trestore %%g0, %1, %Y0\";
}"
[(set_attr "type" "multi")])
@@ -6516,12 +8053,12 @@ if (! TARGET_ARCH64)
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+ return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[1])))
- return \"return %%i7+8\;mov %Y1,%Y0\";
+ return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
else
- return \"ret\;restore %%g0,%1,%Y0\";
+ return \"ret\;restore %%g0, %1, %Y0\";
}"
[(set_attr "type" "multi")])
@@ -6533,31 +8070,32 @@ if (! TARGET_ARCH64)
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+ return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[1])))
- return \"return %%i7+8\;mov %Y1,%Y0\";
+ return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
else
- return \"ret\;restore %%g0,%1,%Y0\";
+ return \"ret\;restore %%g0, %1, %Y0\";
}"
[(set_attr "type" "multi")])
;; The following pattern is only generated by delayed-branch scheduling,
-;; when the insn winds up in the epilogue. This can only happen when
-;; ! TARGET_FPU because otherwise fp return values are in %f0.
+;; when the insn winds up in the epilogue. This can happen not only when
+;; ! TARGET_FPU because we move complex types around by parts using
+;; SF mode SUBREGs.
(define_insn "*return_sf_no_fpu"
[(set (match_operand:SF 0 "restore_operand" "r")
(match_operand:SF 1 "register_operand" "r"))
(return)]
- "! TARGET_FPU && ! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
+ "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
+ return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
- return \"return %%i7+8\;mov %Y1,%Y0\";
+ return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
else
- return \"ret\;restore %%g0,%1,%Y0\";
+ return \"ret\;restore %%g0, %1, %Y0\";
}"
[(set_attr "type" "multi")])
@@ -6570,14 +8108,14 @@ if (! TARGET_ARCH64)
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
+ return \"jmp\\t%%i7+12\\n\\trestore %r1, %2, %Y0\";
/* If operands are global or in registers, can use return */
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
&& (GET_CODE (operands[2]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[2])))
- return \"return %%i7+8\;add %Y1,%Y2,%Y0\";
+ return \"return\\t%%i7+8\\n\\tadd\\t%Y1, %Y2, %Y0\";
else
- return \"ret\;restore %r1,%2,%Y0\";
+ return \"ret\;restore %r1, %2, %Y0\";
}"
[(set_attr "type" "multi")])
@@ -6586,7 +8124,7 @@ if (! TARGET_ARCH64)
(match_operand:DI 1 "arith_double_operand" "rHI"))
(return)]
"TARGET_ARCH64 && ! TARGET_EPILOGUE"
- "ret\;restore %%g0,%1,%Y0"
+ "ret\;restore %%g0, %1, %Y0"
[(set_attr "type" "multi")])
(define_insn "*return_adddi"
@@ -6595,7 +8133,7 @@ if (! TARGET_ARCH64)
(match_operand:DI 2 "arith_double_operand" "rHI")))
(return)]
"TARGET_ARCH64 && ! TARGET_EPILOGUE"
- "ret\;restore %r1,%2,%Y0"
+ "ret\;restore %r1, %2, %Y0"
[(set_attr "type" "multi")])
;; The following pattern is only generated by delayed-branch scheduling,
@@ -6605,7 +8143,7 @@ if (! TARGET_ARCH64)
(match_operand:SF 0 "register_operand" "f"))
(return)]
"! TARGET_EPILOGUE"
- "ret\;fmovs %0,%%f0"
+ "ret\;fmovs\\t%0, %%f0"
[(set_attr "type" "multi")])
;; Now peepholes to do a call followed by a jump.
@@ -6616,16 +8154,20 @@ if (! TARGET_ARCH64)
(match_operand 2 "" "")))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[3])) && in_same_eh_region (insn, operands[3]) && in_same_eh_region (insn, ins1)"
- "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
+ "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
+ && in_same_eh_region (insn, operands[3])
+ && in_same_eh_region (insn, ins1)"
+ "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
(define_peephole
[(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
(match_operand 1 "" ""))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[2])) && in_same_eh_region (insn, operands[2]) && in_same_eh_region (insn, ins1)"
- "call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
+ "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
+ && in_same_eh_region (insn, operands[2])
+ && in_same_eh_region (insn, ins1)"
+ "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
(define_peephole
[(parallel [(set (match_operand 0 "" "")
@@ -6633,31 +8175,40 @@ if (! TARGET_ARCH64)
(match_operand 2 "" "")))
(clobber (reg:DI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
- "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[3])) && in_same_eh_region (insn, operands[3]) && in_same_eh_region (insn, ins1)"
- "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
+ "TARGET_ARCH64
+ && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
+ && in_same_eh_region (insn, operands[3])
+ && in_same_eh_region (insn, ins1)"
+ "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
(define_peephole
[(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
(match_operand 1 "" ""))
(clobber (reg:DI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
- "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[2])) && in_same_eh_region (insn, operands[2]) && in_same_eh_region (insn, ins1)"
- "call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
+ "TARGET_ARCH64
+ && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
+ && in_same_eh_region (insn, operands[2])
+ && in_same_eh_region (insn, ins1)"
+ "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
;; After a nonlocal goto, we need to restore the PIC register, but only
;; if we need it. So do nothing much here, but we'll check for this in
;; finalize_pic.
+;; Make sure this unspec_volatile number agrees with finalize_pic.
(define_insn "nonlocal_goto_receiver"
- [(unspec_volatile [(const_int 0)] 4)]
+ [(unspec_volatile [(const_int 0)] 5)]
"flag_pic"
- "")
+ ""
+ [(set_attr "length" "0")])
(define_insn "trap"
[(trap_if (const_int 1) (const_int 5))]
""
- "ta 5"
- [(set_attr "type" "misc")])
+ "ta\\t5"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_expand "conditional_trap"
[(trap_if (match_operator 0 "noov_compare_op"
@@ -6672,13 +8223,14 @@ if (! TARGET_ARCH64)
[(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
(match_operand:SI 1 "arith_operand" "rM"))]
""
- "t%C0 %1"
- [(set_attr "type" "misc")])
+ "t%C0\\t%1"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
(define_insn ""
[(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
(match_operand:SI 1 "arith_operand" "rM"))]
"TARGET_V9"
- "t%C0 %%xcc,%1"
- [(set_attr "type" "misc")])
-
+ "t%C0\\t%%xcc, %1"
+ [(set_attr "type" "misc")
+ (set_attr "length" "1")])
diff --git a/contrib/gcc/config/sparc/splet.h b/contrib/gcc/config/sparc/splet.h
index 23c6414..d924e70 100644
--- a/contrib/gcc/config/sparc/splet.h
+++ b/contrib/gcc/config/sparc/splet.h
@@ -29,12 +29,12 @@ Boston, MA 02111-1307, USA. */
/* -mlive-g0 is only supported on the sparclet. */
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
-{"big-endian", -MASK_LITTLE_ENDIAN}, \
-{"little-endian", MASK_LITTLE_ENDIAN}, \
-{"live-g0", MASK_LIVE_G0}, \
-{"no-live-g0", -MASK_LIVE_G0}, \
-{"broken-saverestore", MASK_BROKEN_SAVERESTORE}, \
-{"no-broken-saverestore", -MASK_BROKEN_SAVERESTORE},
+{"big-endian", -MASK_LITTLE_ENDIAN, "Generate code for big endian" }, \
+{"little-endian", MASK_LITTLE_ENDIAN, "Generate code for little endian" }, \
+{"live-g0", MASK_LIVE_G0, "Use g0 as a normal register" }, \
+{"no-live-g0", -MASK_LIVE_G0, "Register g0 is fixed with a zero value" }, \
+{"broken-saverestore", MASK_BROKEN_SAVERESTORE, "Enable save/restore bug workarounds" }, \
+{"no-broken-saverestore", -MASK_BROKEN_SAVERESTORE, "Disable save/restore bug workarouns" },
#undef ASM_SPEC
#define ASM_SPEC "%{mlittle-endian:-EL} %(asm_cpu)"
@@ -51,3 +51,19 @@ Boston, MA 02111-1307, USA. */
#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
#undef WORDS_BIG_ENDIAN
#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
+
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS \
+ do { \
+ if (TARGET_LIVE_G0) \
+ { \
+ warning ("Option '-mlive-g0' deprecated."); \
+ target_flags &= ~MASK_LIVE_G0; \
+ } \
+ else if (TARGET_BROKEN_SAVERESTORE) \
+ { \
+ warning ("Option '-mbroken-saverestore' deprecated."); \
+ target_flags &= ~MASK_BROKEN_SAVERESTORE; \
+ } \
+ } while (0)
+
diff --git a/contrib/gcc/config/sparc/sun4o3.h b/contrib/gcc/config/sparc/sun4o3.h
index 10c7391..d2a53c1 100644
--- a/contrib/gcc/config/sparc/sun4o3.h
+++ b/contrib/gcc/config/sparc/sun4o3.h
@@ -1,9 +1,9 @@
#include "sparc/sparc.h"
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- fprintf (FILE, "\tsethi %%hi(LP%d),%%o0\n\tcall .mcount\n\tor %%lo(LP%d),%%o0,%%o0\n", \
- (LABELNO), (LABELNO))
+/* Override the name of the mcount profiling function. */
+
+#undef MCOUNT_FUNCTION
+#define MCOUNT_FUNCTION "*.mcount"
/* LINK_SPEC is needed only for SunOS 4. */
diff --git a/contrib/gcc/config/sparc/sysv4.h b/contrib/gcc/config/sparc/sysv4.h
index 7e90bdd..5f9bba9 100644
--- a/contrib/gcc/config/sparc/sysv4.h
+++ b/contrib/gcc/config/sparc/sysv4.h
@@ -66,7 +66,9 @@ Boston, MA 02111-1307, USA. */
/* The native assembler can't compute differences between symbols in different
sections when generating pic code, so we must put jump tables in the
text section. */
-#define JUMP_TABLES_IN_TEXT_SECTION 1
+/* But we now defer the tables to the end of the function, so we make
+ this 0 to not confuse the branch shortening code. */
+#define JUMP_TABLES_IN_TEXT_SECTION 0
/* Pass -K to the assembler when PIC. */
#undef ASM_SPEC
@@ -191,35 +193,13 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
do { \
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
- fprintf (FILE, ".section\t\"%s%s\",#alloc,#execinstr\n", \
- flag_function_sections ? ".text%" : "", (NAME)); \
+ fprintf (FILE, ".section\t\"%s\",#alloc,#execinstr\n", \
+ (NAME)); \
else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
fprintf (FILE, ".section\t\"%s\",#alloc\n", (NAME)); \
else \
fprintf (FILE, ".section\t\"%s\",#alloc,#write\n", (NAME)); \
} while (0)
-
-/* Output assembler code to FILE to initialize this source file's
- basic block profiling info, if that has not already been done. */
-
-#undef FUNCTION_BLOCK_PROFILER
-#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
- do { \
- fprintf (FILE, "\tsethi %%hi(.LLPBX0),%%o0\n\tld [%%lo(.LLPBX0)+%%o0],%%o1\n\ttst %%o1\n\tbne LPY%d\n\tadd %%o0,%%lo(.LLPBX0),%%o0\n\tcall __bb_init_func\n\tnop\nLPY%d:\n", \
- (LABELNO), (LABELNO)); \
- } while (0)
-
-/* Output assembler code to FILE to increment the entry-count for
- the BLOCKNO'th basic block in this source file. */
-
-#undef BLOCK_PROFILER
-#define BLOCK_PROFILER(FILE, BLOCKNO) \
-{ \
- int blockn = (BLOCKNO); \
- fprintf (FILE, "\tsethi %%hi(.LLPBX2+%d),%%g1\n\tld [%%lo(.LLPBX2+%d)+%%g1],%%g2\n\
-\tadd %%g2,1,%%g2\n\tst %%g2,[%%lo(.LLPBX2+%d)+%%g1]\n", \
- 4 * blockn, 4 * blockn, 4 * blockn); \
-}
/* A C statement (sans semicolon) to output to the stdio stream
FILE the assembler definition of uninitialized global DECL named
@@ -229,3 +209,8 @@ do { \
#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+/* Override the name of the mcount profiling function. */
+
+#undef MCOUNT_FUNCTION
+#define MCOUNT_FUNCTION "*_mcount"
diff --git a/contrib/gcc/config/sparc/t-halos b/contrib/gcc/config/sparc/t-halos
new file mode 100644
index 0000000..0bd5496
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-halos
@@ -0,0 +1,2 @@
+# For a native HALOS compile, we need to set -e1 for the assembler
+AS=as -e1
diff --git a/contrib/gcc/config/sparc/t-linux64 b/contrib/gcc/config/sparc/t-linux64
new file mode 100644
index 0000000..077cf69
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-linux64
@@ -0,0 +1,21 @@
+MULTILIB_OPTIONS = m64/m32
+MULTILIB_DIRNAMES = 64 32
+MULTILIB_MATCHES =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o
+
+tcrtbeginS.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) \
+ defaults.h frame.h gbl-ctors.h
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
+ -finhibit-size-directive -fno-inline-functions -fno-exceptions $(CRTSTUFF_T_CFLAGS_S) \
+ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -o tcrtbeginS$(objext)
+
+tcrtendS.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) \
+ defaults.h frame.h gbl-ctors.h
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
+ -finhibit-size-directive -fno-inline-functions -fno-exceptions $(CRTSTUFF_T_CFLAGS_S) \
+ -c $(srcdir)/crtstuff.c -DCRT_END -o tcrtendS$(objext)
+
diff --git a/contrib/gcc/config/sparc/t-sol2 b/contrib/gcc/config/sparc/t-sol2
index d41254a..a9b6ee1 100644
--- a/contrib/gcc/config/sparc/t-sol2
+++ b/contrib/gcc/config/sparc/t-sol2
@@ -6,19 +6,19 @@ CROSS_LIBGCC1 =
LIBGCC1_TEST =
# gmon build rule:
-gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) stmp-int-hdrs
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/config/sparc/gmon-sol2.c -o gmon.o
+$(T)gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) stmp-int-hdrs
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
+ -c $(srcdir)/config/sparc/gmon-sol2.c -o $(T)gmon.o
# Assemble startup files.
-crt1.o: $(srcdir)/config/sparc/sol2-c1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crt1.o -x assembler $(srcdir)/config/sparc/sol2-c1.asm
-crti.o: $(srcdir)/config/sparc/sol2-ci.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crti.o -x assembler $(srcdir)/config/sparc/sol2-ci.asm
-crtn.o: $(srcdir)/config/sparc/sol2-cn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crtn.o -x assembler $(srcdir)/config/sparc/sol2-cn.asm
-gcrt1.o: $(srcdir)/config/sparc/sol2-g1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o gcrt1.o -x assembler $(srcdir)/config/sparc/sol2-g1.asm
+$(T)crt1.o: $(srcdir)/config/sparc/sol2-c1.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sparc/sol2-c1.asm
+$(T)crti.o: $(srcdir)/config/sparc/sol2-ci.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sparc/sol2-ci.asm
+$(T)crtn.o: $(srcdir)/config/sparc/sol2-cn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sparc/sol2-cn.asm
+$(T)gcrt1.o: $(srcdir)/config/sparc/sol2-c1.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -DGCRT1 -o $(T)gcrt1.o -x assembler-with-cpp $(srcdir)/config/sparc/sol2-c1.asm
# We need to use -fPIC when we are using gcc to compile the routines in
# crtstuff.c. This is only really needed when we are going to use gcc/g++
diff --git a/contrib/gcc/config/sparc/t-sol2-64 b/contrib/gcc/config/sparc/t-sol2-64
new file mode 100644
index 0000000..8d42c44
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-sol2-64
@@ -0,0 +1,8 @@
+MULTILIB_OPTIONS = m32/m64
+MULTILIB_DIRNAMES = sparcv7 sparcv9
+MULTILIB_MATCHES =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o gmon.o crt1.o crti.o crtn.o gcrt1.o
diff --git a/contrib/gcc/config/sparc/t-splet b/contrib/gcc/config/sparc/t-splet
index 3409f5d..3329e0b 100644
--- a/contrib/gcc/config/sparc/t-splet
+++ b/contrib/gcc/config/sparc/t-splet
@@ -16,8 +16,7 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-MULTILIB_OPTIONS = mlittle-endian mlive-g0 mbroken-saverestore
-MULTILIB_DIRNAMES = little live-g0 brknsave
-
+MULTILIB_OPTIONS = mlittle-endian mflat
+MULTILIB_DIRNAMES = little flat
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/sparc/xm-sp64.h b/contrib/gcc/config/sparc/xm-sp64.h
index 5954aff..b673161 100644
--- a/contrib/gcc/config/sparc/xm-sp64.h
+++ b/contrib/gcc/config/sparc/xm-sp64.h
@@ -21,5 +21,7 @@ Boston, MA 02111-1307, USA. */
#include <sparc/xm-sparc.h>
/* This describes the machine the compiler is hosted on. */
+#if defined(__arch64__) || defined(__sparc_v9__) || defined(__sparcv9)
#undef HOST_BITS_PER_LONG
#define HOST_BITS_PER_LONG 64
+#endif
diff --git a/contrib/gcc/config/sparc/xm-sysv4-64.h b/contrib/gcc/config/sparc/xm-sysv4-64.h
new file mode 100644
index 0000000..c506d22
--- /dev/null
+++ b/contrib/gcc/config/sparc/xm-sysv4-64.h
@@ -0,0 +1,27 @@
+/* Configuration for GCC for Sparc v9 running 64-bit native.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <sparc/xm-sysv4.h>
+
+/* This describes the machine the compiler is hosted on. */
+#if defined(__arch64__) || defined(__sparc_v9__) || defined(__sparcv9)
+#undef HOST_BITS_PER_LONG
+#define HOST_BITS_PER_LONG 64
+#endif
diff --git a/contrib/gcc/config/svr4.h b/contrib/gcc/config/svr4.h
index 4737697..7fa30e8 100644
--- a/contrib/gcc/config/svr4.h
+++ b/contrib/gcc/config/svr4.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for some
generic System V Release 4 system.
- Copyright (C) 1991, 94-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1991, 94-98, 1999 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
This file is part of GNU CC.
@@ -212,8 +212,9 @@ Boston, MA 02111-1307, USA.
#define ASM_FILE_END(FILE) \
do { \
- fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
+ if (!flag_no_ident) \
+ fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
+ IDENT_ASM_OP, version_string); \
} while (0)
/* Allow #sccs in preprocessor. */
@@ -246,8 +247,9 @@ do { \
#define DWARF_DEBUGGING_INFO
/* All ELF targets can support DWARF-2. */
-
+#ifndef DWARF2_DEBUGGING_INFO
#define DWARF2_DEBUGGING_INFO
+#endif
/* The numbers used to denote specific machine registers in the System V
Release 4 DWARF debugging information are quite likely to be totally
@@ -260,83 +262,14 @@ do { \
#undef DBX_REGISTER_NUMBER
-/* gas on SVR4 supports the use of .stabs. Permit -gstabs to be used
- in general, although it will only work when using gas. */
-
-#define DBX_DEBUGGING_INFO
-
-/* When generating stabs debugging, use N_BINCL entries. */
-
-#define DBX_USE_BINCL
-
/* Use DWARF debugging info by default. */
#ifndef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG
#endif
-/* Make LBRAC and RBRAC addresses relative to the start of the
- function. The native Solaris stabs debugging format works this
- way, gdb expects it, and it reduces the number of relocation
- entries. */
-
-#define DBX_BLOCKS_FUNCTION_RELATIVE 1
-
-/* When using stabs, gcc2_compiled must be a stabs entry, not an
- ordinary symbol, or gdb won't see it. Furthermore, since gdb reads
- the input piecemeal, starting with each N_SO, it's a lot easier if
- the gcc2 flag symbol is *after* the N_SO rather than before it. So
- we emit an N_OPT stab there. */
-
-#define ASM_IDENTIFY_GCC(FILE) \
-do \
- { \
- if (write_symbols != DBX_DEBUG) \
- fputs ("gcc2_compiled.:\n", FILE); \
- } \
-while (0)
-
-#define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) \
-do \
- { \
- if (write_symbols == DBX_DEBUG) \
- fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \
- } \
-while (0)
-
-/* Like block addresses, stabs line numbers are relative to the
- current function. */
-
-#define ASM_OUTPUT_SOURCE_LINE(file, line) \
-do \
- { \
- static int sym_lineno = 1; \
- fprintf (file, ".stabn 68,0,%d,.LM%d-", \
- line, sym_lineno); \
- assemble_name (file, \
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
- fprintf (file, "\n.LM%d:\n", sym_lineno); \
- sym_lineno += 1; \
- } \
-while (0)
-
-/* In order for relative line numbers to work, we must output the
- stabs entry for the function name first. */
-
-#define DBX_FUNCTION_FIRST
-
-/* Generate a blank trailing N_SO to mark the end of the .o file, since
- we can't depend upon the linker to mark .o file boundaries with
- embedded stabs. */
-
-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
-do \
- { \
- text_section (); \
- fprintf (FILE, \
- "\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", N_SO); \
- } \
-while (0)
+/* But allow STABS to be supoorted as well. */
+#include "dbxelf.h"
/* Define the actual types of some ANSI-mandated types. (These
definitions should work for most SVR4 systems). */
@@ -655,7 +588,15 @@ do { \
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
\
if (! DECL_ONE_ONLY (DECL)) \
- prefix = "."; \
+ { \
+ prefix = "."; \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ prefix = ".text."; \
+ else if (DECL_READONLY_SECTION (DECL, RELOC)) \
+ prefix = ".rodata."; \
+ else \
+ prefix = ".data."; \
+ } \
else if (TREE_CODE (DECL) == FUNCTION_DECL) \
prefix = ".gnu.linkonce.t."; \
else if (DECL_READONLY_SECTION (DECL, RELOC)) \
@@ -669,7 +610,6 @@ do { \
\
DECL_SECTION_NAME (DECL) = build_string (len, string); \
} while (0)
-
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
@@ -943,7 +883,7 @@ do { \
} \
for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
continue; \
- if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \
+ if (p < limit && (p - _ascii_bytes) <= (long)STRING_LIMIT) \
{ \
if (bytes_in_chunk > 0) \
{ \
diff --git a/contrib/gcc/config/t-freebsd b/contrib/gcc/config/t-freebsd
index 5164669..9981686 100644
--- a/contrib/gcc/config/t-freebsd
+++ b/contrib/gcc/config/t-freebsd
@@ -2,4 +2,3 @@
STMP_FIXPROTO =
# Use only native include files
USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)
-
diff --git a/contrib/gcc/config/t-gnu b/contrib/gcc/config/t-gnu
index 58969f2..575f729 100644
--- a/contrib/gcc/config/t-gnu
+++ b/contrib/gcc/config/t-gnu
@@ -1,5 +1,8 @@
-LIBGCC1=libgcc1.null
-CROSS_LIBGCC1=libgcc1.null
+# In GNU, "/usr" is a four-letter word.
+SYSTEM_HEADER_DIR = /include
+
+LIBGCC1 = libgcc1.null
+CROSS_LIBGCC1 = libgcc1.null
# The pushl in CTOR initialization interferes with frame pointer elimination.
diff --git a/contrib/gcc/config/t-openbsd b/contrib/gcc/config/t-openbsd
index 6bd8123..14bebc1 100644
--- a/contrib/gcc/config/t-openbsd
+++ b/contrib/gcc/config/t-openbsd
@@ -5,5 +5,3 @@ STMP_FIXPROTO =
USER_H = ${LANG_EXTRA_HEADERS}
INSTALL_ASSERT_H =
-# We don't want collisions with our mkstemps
-T_CFLAGS=-Dmkstemps=my_mkstemps
diff --git a/contrib/gcc/config/t-rtems b/contrib/gcc/config/t-rtems
index aa0ca66..5d7d569 100644
--- a/contrib/gcc/config/t-rtems
+++ b/contrib/gcc/config/t-rtems
@@ -4,3 +4,10 @@ STMP_FIXPROTO =
# Don't install "assert.h" in gcc. RTEMS uses the one in newlib.
INSTALL_ASSERT_H =
+# RTEMS always has limits.h.
+LIMITS_H_TEST = true
+
+# If we are building next to newlib, this will let us find the RTEMS
+# limits.h when building libgcc2. Otherwise, newlib must be installed
+# first.
+LIBGCC2_INCLUDES = -I$(srcdir)/../newlib/libc/sys/rtems/include
diff --git a/contrib/gcc/config/tm-dwarf2.h b/contrib/gcc/config/tm-dwarf2.h
new file mode 100644
index 0000000..a580964
--- /dev/null
+++ b/contrib/gcc/config/tm-dwarf2.h
@@ -0,0 +1,4 @@
+/* Enable Dwarf2 debugging and make it the default */
+#define DWARF2_DEBUGGING_INFO 1
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
diff --git a/contrib/gcc/config/x-interix b/contrib/gcc/config/x-interix
new file mode 100644
index 0000000..afdfe76
--- /dev/null
+++ b/contrib/gcc/config/x-interix
@@ -0,0 +1,24 @@
+# These are host overrides
+# From config dir
+
+# Interix doesn't yet have alloca; it's better to use the portable C version for
+# bootstrapping. Do this by defining ALLOCA.
+
+ALLOCA = alloca.o
+
+# See all the declarations.
+FIXPROTO_DEFINES = -D_XOPEN_SOURCE
+
+# Don't run fixproto
+STMP_FIXPROTO =
+RANLIB = :
+RANLIB_TEST = false
+SHELL = sh
+
+# Existing CC/GCC may not define -D__INTERIX, so need this here.
+# Since we want to configure with _ALL_SOURCE, we need to build that way too
+X_CFLAGS= -D__INTERIX -D_ALL_SOURCE
+
+LIBGCC2_INCLUDES = -idirafter $${INTERIX_ROOT}/usr/include
+# Headers come from a funny place
+SYSTEM_HEADER_DIR=$${INTERIX_ROOT}/usr/include
diff --git a/contrib/gcc/config/xm-interix.h b/contrib/gcc/config/xm-interix.h
new file mode 100644
index 0000000..756fb5d
--- /dev/null
+++ b/contrib/gcc/config/xm-interix.h
@@ -0,0 +1,77 @@
+/* Configuration for GNU compiler for processor running Interix
+ Copyright (C) 1993, 1995, 1999 Free Software Foundation, Inc.
+ Donn Terry, Softway Systems, Inc,
+ from code
+ Contributed by Douglas B. Rupp (drupp@cs.washington.edu)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef USG
+#define USG 1
+#endif
+
+#ifndef ONLY_INT_FIELDS
+#ifndef __GNUC__
+#define ONLY_INT_FIELDS 1
+#endif
+#endif
+
+#ifndef USE_PROTOTYPES
+#define USE_PROTOTYPES 1
+#endif
+
+/* If not compiled with GNU C, use the portable alloca. */
+#ifndef __GNUC__
+#define USE_C_ALLOCA 1
+#endif
+
+#define NO_SYS_SIGLIST 1
+
+/* Our strategy for finding global constructors is a bit different, although
+ not a lot. */
+#define DO_GLOBAL_CTORS_BODY \
+do { \
+ int i; \
+ unsigned long nptrs; \
+ func_ptr *p; \
+ asm( \
+ " .section .ctor_head, \"rw\"\n" \
+ "1:\n" \
+ " .text \n" \
+ ASM_LOAD_ADDR(1b,%0) \
+ : "=r" (p) : : "cc"); \
+ for (nptrs = 0; p[nptrs] != 0; nptrs++); \
+ for (i = nptrs-1; i >= 0; i--) \
+ p[i] (); \
+} while (0)
+
+#define DO_GLOBAL_DTORS_BODY \
+do { \
+ func_ptr *p; \
+ asm( \
+ " .section .dtor_head, \"rw\"\n" \
+ "1:\n" \
+ " .text \n" \
+ ASM_LOAD_ADDR(1b,%0) \
+ : "=r" (p) : : "cc"); \
+ while (*p) \
+ { \
+ p++; \
+ (*(p-1)) (); \
+ } \
+} while (0)
diff --git a/contrib/gcc/configure b/contrib/gcc/configure
index d341217..5eeba77 100755
--- a/contrib/gcc/configure
+++ b/contrib/gcc/configure
@@ -14,8 +14,12 @@ ac_default_prefix=/usr/local
ac_help="$ac_help
--with-gnu-ld arrange to work with GNU ld."
ac_help="$ac_help
+ --with-ld arrange to use the specified ld (full pathname)."
+ac_help="$ac_help
--with-gnu-as arrange to work with GNU as."
ac_help="$ac_help
+ --with-as arrange to use the specified as (full pathname)."
+ac_help="$ac_help
--with-stabs arrange to use stabs instead of host debug format."
ac_help="$ac_help
--with-elf arrange to use ELF instead of host debug format."
@@ -27,16 +31,44 @@ ac_help="$ac_help
ac_help="$ac_help
--enable-checking enable expensive run-time checks."
ac_help="$ac_help
- --enable-c-cpplib Use cpplib for C."
+ --disable-cpp don't provide a user-visible C preprocessor."
ac_help="$ac_help
- --enable-haifa Use the experimental scheduler.
- --disable-haifa Don't use the experimental scheduler for the
- targets which normally enable it."
+ --with-cpp-install-dir=DIR
+ install the user visible C preprocessor in DIR
+ (relative to PREFIX) as well as PREFIX/bin."
+ac_help="$ac_help
+ --enable-cpplib use cpplib for the C preprocessor."
+ac_help="$ac_help
+ --enable-c-cpplib link cpplib directly into C and C++ compilers
+ (EXPERIMENTAL) (implies --enable-cpplib)."
+ac_help="$ac_help
+ --enable-c-mbchar enable multibyte characters for C and C++."
+ac_help="$ac_help
+ --disable-fast-fixincludes
+ Disable the new fast fixincludes.
+ Run the old fixincludes script unconditionally"
ac_help="$ac_help
- --with-fast-fixincludes Use a faster fixinclude program. Experimental"
+ --enable-haifa use the experimental scheduler.
+ --disable-haifa don't use the experimental scheduler for the
+ targets which normally enable it."
ac_help="$ac_help
--enable-threads enable thread usage for target GCC.
--enable-threads=LIB use LIB thread package for target GCC."
+ac_help="$ac_help
+ --enable-objc-gc enable the use of Boehm's garbage collector with
+ the GNU Objective-C runtime."
+ac_help="$ac_help
+ --enable-java-gc=TYPE choose garbage collector [boehm]"
+ac_help="$ac_help
+ --enable-dwarf2 enable DWARF2 debugging as default."
+ac_help="$ac_help
+ --enable-nls use Native Language Support (disabled by default)"
+ac_help="$ac_help
+ --disable-nls do not use Native Language Support"
+ac_help="$ac_help
+ --with-included-gettext use the GNU gettext library included here"
+ac_help="$ac_help
+ --with-catgets use catgets functions if available"
# Initialize some variables set by options.
# The variables have the same names as the options, with
@@ -554,6 +586,57 @@ hard_link=ln
symbolic_link='ln -s'
copy=cp
+# Check for bogus environment variables.
+# Test if LIBRARY_PATH contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# LIBRARY_PATH contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+echo $ac_n "checking LIBRARY_PATH variable""... $ac_c" 1>&6
+echo "configure:599: checking LIBRARY_PATH variable" >&5
+case ${LIBRARY_PATH} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ library_path_setting="contains current directory"
+ ;;
+ *)
+ library_path_setting="ok"
+ ;;
+esac
+echo "$ac_t""$library_path_setting" 1>&6
+if test "$library_path_setting" != "ok"; then
+{ echo "configure: error:
+*** LIBRARY_PATH shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again." 1>&2; exit 1; }
+fi
+
+# Test if GCC_EXEC_PREFIX contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# GCC_EXEC_PREFIX contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+echo $ac_n "checking GCC_EXEC_PREFIX variable""... $ac_c" 1>&6
+echo "configure:624: checking GCC_EXEC_PREFIX variable" >&5
+case ${GCC_EXEC_PREFIX} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ gcc_exec_prefix_setting="contains current directory"
+ ;;
+ *)
+ gcc_exec_prefix_setting="ok"
+ ;;
+esac
+echo "$ac_t""$gcc_exec_prefix_setting" 1>&6
+if test "$gcc_exec_prefix_setting" != "ok"; then
+{ echo "configure: error:
+*** GCC_EXEC_PREFIX shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again." 1>&2; exit 1; }
+fi
+
# Check for additional parameters
# With GNU ld
@@ -566,6 +649,25 @@ else
fi
+# With pre-defined ld
+# Check whether --with-ld or --without-ld was given.
+if test "${with_ld+set}" = set; then
+ withval="$with_ld"
+ DEFAULT_LINKER="$with_ld"
+fi
+
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_LINKER"; then
+ echo "configure: warning: cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER" 1>&2
+ elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gnu_ld_flag=yes
+ fi
+ cat >> confdefs.h <<EOF
+#define DEFAULT_LINKER "$DEFAULT_LINKER"
+EOF
+
+fi
+
# With GNU as
# Check whether --with-gnu-as or --without-gnu-as was given.
if test "${with_gnu_as+set}" = set; then
@@ -576,6 +678,24 @@ else
fi
+# Check whether --with-as or --without-as was given.
+if test "${with_as+set}" = set; then
+ withval="$with_as"
+ DEFAULT_ASSEMBLER="$with_as"
+fi
+
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_ASSEMBLER"; then
+ echo "configure: warning: cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER" 1>&2
+ elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gas_flag=yes
+ fi
+ cat >> confdefs.h <<EOF
+#define DEFAULT_ASSEMBLER "$DEFAULT_ASSEMBLER"
+EOF
+
+fi
+
# With stabs
# Check whether --with-stabs or --without-stabs was given.
if test "${with_stabs+set}" = set; then
@@ -610,11 +730,14 @@ fi
# Default local prefix if it is empty
-if [ x$local_prefix = x ]; then
+if test x$local_prefix = x; then
local_prefix=/usr/local
fi
-gxx_include_dir=
+# Don't set gcc_gxx_include_dir to gxx_include_dir since that's only
+# passed in by the toplevel make and thus we'd get different behavior
+# depending on where we built the sources.
+gcc_gxx_include_dir=
# Specify the g++ header file directory
# Check whether --with-gxx-include-dir or --without-gxx-include-dir was given.
if test "${with_gxx_include_dir+set}" = set; then
@@ -622,16 +745,17 @@ if test "${with_gxx_include_dir+set}" = set; then
case "${withval}" in
yes) { echo "configure: error: bad value ${withval} given for g++ include directory" 1>&2; exit 1; } ;;
no) ;;
-*) gxx_include_dir=$with_gxx_include_dir ;;
+*) gcc_gxx_include_dir=$with_gxx_include_dir ;;
esac
fi
-if test x${gxx_include_dir} = x; then
+if test x${gcc_gxx_include_dir} = x; then
if test x${enable_version_specific_runtime_libs} = xyes; then
- gxx_include_dir='${libsubdir}/include/g++'
+ gcc_gxx_include_dir='${libsubdir}/include/g++'
else
- gxx_include_dir='${prefix}/include/g++'
+ topsrcdir=${srcdir}/.. . ${srcdir}/../config.if
+ gcc_gxx_include_dir="\$(libsubdir)/\$(unlibsubdir)/..\`echo \$(exec_prefix) | sed -e 's|^\$(prefix)||' -e 's|/[^/]*|/..|g'\`/include/g++"-${libstdcxx_interface}
fi
fi
@@ -650,21 +774,70 @@ esac
fi
-# Enable use of cpplib for C.
+# Check whether --enable-cpp or --disable-cpp was given.
+if test "${enable_cpp+set}" = set; then
+ enableval="$enable_cpp"
+ :
+else
+ enable_cpp=yes
+fi
+
+
+# Check whether --with-cpp_install_dir or --without-cpp_install_dir was given.
+if test "${with_cpp_install_dir+set}" = set; then
+ withval="$with_cpp_install_dir"
+ if test x$withval = xyes; then
+ { echo "configure: error: option --with-cpp-install-dir requires an argument" 1>&2; exit 1; }
+elif test x$withval != xno; then
+ cpp_install_dir=$withval
+fi
+fi
+
+
+# Use cpplib+cppmain for the preprocessor, but don't link it with the compiler.
cpp_main=cccp
+# Check whether --enable-cpplib or --disable-cpplib was given.
+if test "${enable_cpplib+set}" = set; then
+ enableval="$enable_cpplib"
+ if test x$enable_cpplib != xno; then
+ cpp_main=cppmain
+fi
+fi
+
+
+# Link cpplib into the compiler proper, for C/C++/ObjC.
# Check whether --enable-c-cpplib or --disable-c-cpplib was given.
if test "${enable_c_cpplib+set}" = set; then
enableval="$enable_c_cpplib"
- if [ x$enable_c_cpplib != xno ]; then
- extra_c_objs="${extra_c_objs} cpplib.o cppexp.o cpphash.o cpperror.o"
- extra_c_objs="${extra_c_objs} prefix.o"
- extra_cxx_objs="${extra_cxx_objs} ../cpplib.o ../cppexp.o ../cpphash.o ../cpperror.o ../prefix.o"
- extra_c_flags=-DUSE_CPPLIB=1
+ if test x$enable_c_cpplib != xno; then
+ extra_c_objs="${extra_c_objs} libcpp.a"
+ extra_cxx_objs="${extra_cxx_objs} ../libcpp.a"
+ extra_c_flags="${extra_c_flags} -DUSE_CPPLIB=1"
cpp_main=cppmain
fi
fi
-
+
+# Enable Multibyte Characters for C/C++
+# Check whether --enable-c-mbchar or --disable-c-mbchar was given.
+if test "${enable_c_mbchar+set}" = set; then
+ enableval="$enable_c_mbchar"
+ if test x$enable_c_mbchar != xno; then
+ extra_c_flags=-DMULTIBYTE_CHARS=1
+fi
+fi
+
+
+# Disable fast fixincludes
+# Check whether --enable-fast-fixincludes or --disable-fast-fixincludes was given.
+if test "${enable_fast_fixincludes+set}" = set; then
+ enableval="$enable_fast_fixincludes"
+ if test x$enable_fast_fixincludes = xno ; then
+ cp $srcdir/fixincludes ./fixinc.sh
+fi
+fi
+
+
# Enable Haifa scheduler.
# Check whether --enable-haifa or --disable-haifa was given.
if test "${enable_haifa+set}" = set; then
@@ -672,17 +845,6 @@ if test "${enable_haifa+set}" = set; then
:
fi
-# Fast fixincludes
-#
-# This is a work in progress...
-# Check whether --with-fast-fixincludes or --without-fast-fixincludes was given.
-if test "${with_fast_fixincludes+set}" = set; then
- withval="$with_fast_fixincludes"
- fast_fixinc="$with_fast_fixincludes"
-else
- fast_fixinc=no
-fi
-
# Enable threads
# Pass with no value to take the default
@@ -690,7 +852,7 @@ fi
# Check whether --enable-threads or --disable-threads was given.
if test "${enable_threads+set}" = set; then
enableval="$enable_threads"
- if [ x$enable_threads = xno ]; then
+ if test x$enable_threads = xno; then
enable_threads=''
fi
else
@@ -719,6 +881,38 @@ case x${enable_threads_flag} in
;;
esac
+# Check whether --enable-objc-gc or --disable-objc-gc was given.
+if test "${enable_objc_gc+set}" = set; then
+ enableval="$enable_objc_gc"
+ if [ x$enable_objc_gc = xno ]; then
+ objc_boehm_gc=''
+else
+ objc_boehm_gc=1
+fi
+else
+ objc_boehm_gc=''
+fi
+
+
+# Check whether --enable-java-gc or --disable-java-gc was given.
+if test "${enable_java_gc+set}" = set; then
+ enableval="$enable_java_gc"
+
+ JAVAGC=$enableval
+else
+ JAVAGC=boehm
+fi
+
+
+# Check whether --with-dwarf2 or --without-dwarf2 was given.
+if test "${with_dwarf2+set}" = set; then
+ withval="$with_dwarf2"
+ dwarf2="$with_dwarf2"
+else
+ dwarf2=no
+fi
+
+
# Determine the host, build, and target systems
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
@@ -767,7 +961,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:771: checking host system type" >&5
+echo "configure:965: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@@ -788,7 +982,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
echo $ac_n "checking target system type""... $ac_c" 1>&6
-echo "configure:792: checking target system type" >&5
+echo "configure:986: checking target system type" >&5
target_alias=$target
case "$target_alias" in
@@ -806,7 +1000,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:810: checking build system type" >&5
+echo "configure:1004: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@@ -833,7 +1027,7 @@ test "$host_alias" != "$target_alias" &&
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:837: checking for $ac_word" >&5
+echo "configure:1031: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -863,7 +1057,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:867: checking for $ac_word" >&5
+echo "configure:1061: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -914,7 +1108,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:918: checking for $ac_word" >&5
+echo "configure:1112: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -946,7 +1140,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:950: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:1144: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -957,12 +1151,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF
-#line 961 "configure"
+#line 1155 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1160: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -988,12 +1182,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:992: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:1186: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:997: checking whether we are using GNU C" >&5
+echo "configure:1191: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1002,7 +1196,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1006: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1200: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -1021,7 +1215,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1025: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:1219: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1052,8 +1246,19 @@ else
fi
fi
+
+# If the native compiler is GCC, we can enable warnings even in stage1.
+# That's useful for people building cross-compilers, or just running a
+# quick `make'.
+if test "x$GCC" = "xyes"; then
+ stage1_warn_cflags='$(WARN_CFLAGS)'
+else
+ stage1_warn_cflags=""
+fi
+
+
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:1057: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:1262: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1080,13 +1285,37 @@ else
fi
+echo $ac_n "checking whether a default assembler was specified""... $ac_c" 1>&6
+echo "configure:1290: checking whether a default assembler was specified" >&5
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test x"$gas_flag" = x"no"; then
+ echo "$ac_t""yes ($DEFAULT_ASSEMBLER)" 1>&6
+ else
+ echo "$ac_t""yes ($DEFAULT_ASSEMBLER - GNU as)" 1>&6
+ fi
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking whether a default linker was specified""... $ac_c" 1>&6
+echo "configure:1302: checking whether a default linker was specified" >&5
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test x"$gnu_ld_flag" = x"no"; then
+ echo "$ac_t""yes ($DEFAULT_LINKER)" 1>&6
+ else
+ echo "$ac_t""yes ($DEFAULT_LINKER - GNU ld)" 1>&6
+ fi
+else
+ echo "$ac_t""no" 1>&6
+fi
+
# Find some useful tools
-for ac_prog in mawk gawk nawk awk
+for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1090: checking for $ac_word" >&5
+echo "configure:1319: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1118,7 +1347,7 @@ done
# Extract the first word of "flex", so it can be a program name with args.
set dummy flex; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1122: checking for $ac_word" >&5
+echo "configure:1351: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1152,7 +1381,7 @@ then
*) ac_lib=l ;;
esac
echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
-echo "configure:1156: checking for yywrap in -l$ac_lib" >&5
+echo "configure:1385: checking for yywrap in -l$ac_lib" >&5
ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1160,7 +1389,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-l$ac_lib $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1164 "configure"
+#line 1393 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1171,7 +1400,7 @@ int main() {
yywrap()
; return 0; }
EOF
-if { (eval echo configure:1175: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1194,7 +1423,7 @@ fi
fi
echo $ac_n "checking whether ln works""... $ac_c" 1>&6
-echo "configure:1198: checking whether ln works" >&5
+echo "configure:1427: checking whether ln works" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_LN'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1226,7 +1455,7 @@ else
fi
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:1230: checking whether ln -s works" >&5
+echo "configure:1459: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1258,19 +1487,19 @@ else
fi
echo $ac_n "checking for volatile""... $ac_c" 1>&6
-echo "configure:1262: checking for volatile" >&5
+echo "configure:1491: checking for volatile" >&5
if eval "test \"`echo '$''{'gcc_cv_c_volatile'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1267 "configure"
+#line 1496 "configure"
#include "confdefs.h"
int main() {
volatile int foo;
; return 0; }
EOF
-if { (eval echo configure:1274: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1503: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c_volatile=yes
else
@@ -1293,7 +1522,7 @@ fi
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1297: checking for $ac_word" >&5
+echo "configure:1526: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1325,7 +1554,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1329: checking for $ac_word" >&5
+echo "configure:1558: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1366,7 +1595,7 @@ test -n "$YACC" || YACC="yacc"
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1370: checking for a BSD compatible install" >&5
+echo "configure:1599: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1417,7 +1646,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1421: checking how to run the C preprocessor" >&5
+echo "configure:1650: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -1432,13 +1661,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 1436 "configure"
+#line 1665 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1442: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1671: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1449,13 +1678,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 1453 "configure"
+#line 1682 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1459: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1688: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1466,13 +1695,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 1470 "configure"
+#line 1699 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1476: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1705: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1497,12 +1726,12 @@ fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1501: checking for ANSI C header files" >&5
+echo "configure:1730: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1506 "configure"
+#line 1735 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -1510,7 +1739,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1514: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1743: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1527,7 +1756,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1531 "configure"
+#line 1760 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -1545,7 +1774,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1549 "configure"
+#line 1778 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -1566,7 +1795,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
-#line 1570 "configure"
+#line 1799 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1577,7 +1806,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
-if { (eval echo configure:1581: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1810: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@@ -1601,12 +1830,12 @@ EOF
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:1605: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:1834: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1610 "configure"
+#line 1839 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
@@ -1615,7 +1844,7 @@ int main() {
struct tm *tp;
; return 0; }
EOF
-if { (eval echo configure:1619: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1848: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
@@ -1635,21 +1864,97 @@ EOF
fi
-for ac_hdr in limits.h stddef.h string.h strings.h stdlib.h time.h fcntl.h unistd.h stab.h sys/file.h sys/time.h sys/resource.h sys/param.h sys/times.h wait.h sys/wait.h
+echo $ac_n "checking whether string.h and strings.h may both be included""... $ac_c" 1>&6
+echo "configure:1869: checking whether string.h and strings.h may both be included" >&5
+if eval "test \"`echo '$''{'gcc_cv_header_string'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1874 "configure"
+#include "confdefs.h"
+#include <string.h>
+#include <strings.h>
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1882: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gcc_cv_header_string=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gcc_cv_header_string=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gcc_cv_header_string" 1>&6
+if test $gcc_cv_header_string = yes; then
+ cat >> confdefs.h <<\EOF
+#define STRING_WITH_STRINGS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:1903: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1908 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:1924: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in limits.h stddef.h string.h strings.h stdlib.h time.h fcntl.h unistd.h stab.h sys/file.h sys/time.h sys/resource.h sys/param.h sys/times.h sys/stat.h direct.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1643: checking for $ac_hdr" >&5
+echo "configure:1948: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1648 "configure"
+#line 1953 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1653: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1958: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1679,17 +1984,17 @@ done
# Check for thread headers.
ac_safe=`echo "thread.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for thread.h""... $ac_c" 1>&6
-echo "configure:1683: checking for thread.h" >&5
+echo "configure:1988: checking for thread.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1688 "configure"
+#line 1993 "configure"
#include "confdefs.h"
#include <thread.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1693: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1998: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1713,17 +2018,17 @@ fi
ac_safe=`echo "pthread.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for pthread.h""... $ac_c" 1>&6
-echo "configure:1717: checking for pthread.h" >&5
+echo "configure:2022: checking for pthread.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1722 "configure"
+#line 2027 "configure"
#include "confdefs.h"
#include <pthread.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1727: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2032: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1746,15 +2051,47 @@ have_pthread_h=
fi
+# See if GNAT has been installed
+# Extract the first word of "gnatbind", so it can be a program name with args.
+set dummy gnatbind; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2059: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gnat'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$gnat"; then
+ ac_cv_prog_gnat="$gnat" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_gnat="yes"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_gnat" && ac_cv_prog_gnat="no"
+fi
+fi
+gnat="$ac_cv_prog_gnat"
+if test -n "$gnat"; then
+ echo "$ac_t""$gnat" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
# See if the system preprocessor understands the ANSI C preprocessor
# stringification operator.
echo $ac_n "checking whether cpp understands the stringify operator""... $ac_c" 1>&6
-echo "configure:1753: checking whether cpp understands the stringify operator" >&5
+echo "configure:2090: checking whether cpp understands the stringify operator" >&5
if eval "test \"`echo '$''{'gcc_cv_c_have_stringify'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1758 "configure"
+#line 2095 "configure"
#include "confdefs.h"
int main() {
@@ -1762,7 +2099,7 @@ int main() {
char *test = S(foo);
; return 0; }
EOF
-if { (eval echo configure:1766: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2103: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c_have_stringify=yes
else
@@ -1785,12 +2122,12 @@ fi
# Use <inttypes.h> only if it exists,
# doesn't clash with <sys/types.h>, and declares intmax_t.
echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6
-echo "configure:1789: checking for inttypes.h" >&5
+echo "configure:2126: checking for inttypes.h" >&5
if eval "test \"`echo '$''{'gcc_cv_header_inttypes_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1794 "configure"
+#line 2131 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <inttypes.h>
@@ -1798,7 +2135,7 @@ int main() {
intmax_t i = -1;
; return 0; }
EOF
-if { (eval echo configure:1802: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2139: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_header_inttypes_h=yes
else
@@ -1820,15 +2157,16 @@ fi
for ac_func in strtoul bsearch strerror putenv popen bcopy bzero bcmp \
index rindex strchr strrchr kill getrlimit setrlimit atoll atoq \
- sysconf isascii gettimeofday
+ sysconf isascii gettimeofday strsignal putc_unlocked fputc_unlocked \
+ fputs_unlocked
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1827: checking for $ac_func" >&5
+echo "configure:2165: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1832 "configure"
+#line 2170 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -1851,7 +2189,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1855: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2193: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1876,13 +2214,16 @@ fi
done
+# Make sure wchar_t is available
+#AC_CHECK_TYPE(wchar_t, unsigned int)
+
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:1881: checking for vprintf" >&5
+echo "configure:2222: checking for vprintf" >&5
if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1886 "configure"
+#line 2227 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
@@ -1905,7 +2246,7 @@ vprintf();
; return 0; }
EOF
-if { (eval echo configure:1909: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_vprintf=yes"
else
@@ -1929,12 +2270,12 @@ fi
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:1933: checking for _doprnt" >&5
+echo "configure:2274: checking for _doprnt" >&5
if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1938 "configure"
+#line 2279 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
@@ -1957,7 +2298,7 @@ _doprnt();
; return 0; }
EOF
-if { (eval echo configure:1961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2302: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func__doprnt=yes"
else
@@ -1993,7 +2334,7 @@ fi
echo $ac_n "checking whether the printf functions support %p""... $ac_c" 1>&6
-echo "configure:1997: checking whether the printf functions support %p" >&5
+echo "configure:2338: checking whether the printf functions support %p" >&5
if eval "test \"`echo '$''{'gcc_cv_func_printf_ptr'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2001,7 +2342,7 @@ else
gcc_cv_func_printf_ptr=no
else
cat > conftest.$ac_ext <<EOF
-#line 2005 "configure"
+#line 2346 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -2014,7 +2355,7 @@ main()
exit (p != q);
}
EOF
-if { (eval echo configure:2018: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
gcc_cv_func_printf_ptr=yes
else
@@ -2038,25 +2379,283 @@ EOF
fi
+case "${host}" in
+*-*-uwin*)
+ # Under some versions of uwin, vfork is notoriously buggy and the test
+ # can hang configure; on other versions, vfork exists just as a stub.
+ # FIXME: This should be removed once vfork in uwin's runtime is fixed.
+ ac_cv_func_vfork_works=no
+ ;;
+esac
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:2392: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2397 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
+echo "configure:2426: checking for vfork.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2431 "configure"
+#include "confdefs.h"
+#include <vfork.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2436: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_VFORK_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for working vfork""... $ac_c" 1>&6
+echo "configure:2461: checking for working vfork" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ echo $ac_n "checking for vfork""... $ac_c" 1>&6
+echo "configure:2467: checking for vfork" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2472 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vfork(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char vfork();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vfork) || defined (__stub___vfork)
+choke me
+#else
+vfork();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2495: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_vfork=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_vfork=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vfork`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2517 "configure"
+#include "confdefs.h"
+/* Thanks to Paul Eggert for this test. */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent.
+ The compiler is told about this with #include <vfork.h>,
+ but some compilers (e.g. gcc -O) don't grok <vfork.h>.
+ Test for this by using a static variable whose address
+ is put into a register that is clobbered by the vfork. */
+static
+#ifdef __cplusplus
+sparc_address_test (int arg)
+#else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+main() {
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test ();
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems.
+ This test uses lots of local variables, at least
+ as many local variables as main has allocated so far
+ including compiler temporaries. 4 locals are enough for
+ gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe.
+ A buggy compiler should reuse the register of parent
+ for one of the local variables, since it will think that
+ parent can't possibly be used any more in this routine.
+ Assigning to the local variable will thus munge parent
+ in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3),
+ vfork doesn't separate parent from child file descriptors.
+ If the child closes a descriptor before it execs or exits,
+ this munges the parent's descriptor as well.
+ Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ exit(
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+EOF
+if { (eval echo configure:2612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_vfork_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_vfork_works=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_vfork_works" 1>&6
+if test $ac_cv_func_vfork_works = no; then
+ cat >> confdefs.h <<\EOF
+#define vfork fork
+EOF
+
+fi
+
+
for ac_func in malloc realloc calloc free bcopy bzero bcmp \
- index rindex getenv atol sbrk abort atof strerror getcwd getwd
+ index rindex getenv atol sbrk abort atof strerror getcwd getwd \
+ strsignal putc_unlocked fputs_unlocked strstr
do
echo $ac_n "checking whether $ac_func must be declared""... $ac_c" 1>&6
-echo "configure:2046: checking whether $ac_func must be declared" >&5
+echo "configure:2640: checking whether $ac_func must be declared" >&5
if eval "test \"`echo '$''{'gcc_cv_decl_needed_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2051 "configure"
+#line 2645 "configure"
#include "confdefs.h"
#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
+#ifdef STRING_WITH_STRINGS
+# include <string.h>
+# include <strings.h>
#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
+# ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
+# endif
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -2075,7 +2674,7 @@ int main() {
char *(*pfn) = (char *(*)) $ac_func
; return 0; }
EOF
-if { (eval echo configure:2079: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2678: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "gcc_cv_decl_needed_$ac_func=no"
else
@@ -2104,21 +2703,26 @@ done
for ac_func in getrlimit setrlimit
do
echo $ac_n "checking whether $ac_func must be declared""... $ac_c" 1>&6
-echo "configure:2108: checking whether $ac_func must be declared" >&5
+echo "configure:2707: checking whether $ac_func must be declared" >&5
if eval "test \"`echo '$''{'gcc_cv_decl_needed_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2113 "configure"
+#line 2712 "configure"
#include "confdefs.h"
#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
+#ifdef STRING_WITH_STRINGS
+# include <string.h>
+# include <strings.h>
#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
+# ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
+# endif
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -2141,7 +2745,7 @@ int main() {
char *(*pfn) = (char *(*)) $ac_func
; return 0; }
EOF
-if { (eval echo configure:2145: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2749: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "gcc_cv_decl_needed_$ac_func=no"
else
@@ -2168,12 +2772,12 @@ done
echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6
-echo "configure:2172: checking for sys_siglist declaration in signal.h or unistd.h" >&5
+echo "configure:2776: checking for sys_siglist declaration in signal.h or unistd.h" >&5
if eval "test \"`echo '$''{'ac_cv_decl_sys_siglist'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2177 "configure"
+#line 2781 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -2185,7 +2789,7 @@ int main() {
char *msg = *(sys_siglist + 1);
; return 0; }
EOF
-if { (eval echo configure:2189: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2793: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_decl_sys_siglist=yes
else
@@ -2206,6 +2810,51 @@ EOF
fi
+# mkdir takes a single argument on some systems.
+echo $ac_n "checking if mkdir takes one argument""... $ac_c" 1>&6
+echo "configure:2816: checking if mkdir takes one argument" >&5
+if eval "test \"`echo '$''{'gcc_cv_mkdir_takes_one_arg'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2821 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#endif
+int main() {
+mkdir ("foo", 0);
+; return 0; }
+EOF
+if { (eval echo configure:2838: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gcc_cv_mkdir_takes_one_arg=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gcc_cv_mkdir_takes_one_arg=yes
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gcc_cv_mkdir_takes_one_arg" 1>&6
+if test $gcc_cv_mkdir_takes_one_arg = yes ; then
+ cat >> confdefs.h <<\EOF
+#define MKDIR_TAKES_ONE_ARG 1
+EOF
+
+fi
+
+
# File extensions
manext='.1'
objext='.o'
@@ -2221,7 +2870,6 @@ host_xm_defines=
host_xmake_file=
host_truncate_target=
host_exeext=
-cpp_install_dir=
# Decode the host machine, then the target machine.
# For the host machine, we save the xm_file variable as host_xm_file;
@@ -2245,10 +2893,6 @@ for machine in $build $host $target; do
use_collect2=
# Set this to override the default target model.
target_cpu_default=
- # Set this to control which fixincludes program to use.
- if [ x$fast_fixinc != xyes ] ; then
- fixincludes=fixincludes
- else fixincludes=fixinc.sh ; fi
# Set this to control how the header file directory is installed.
install_headers_dir=install-headers-tar
# Set this to a non-empty list of args to pass to cpp if the target
@@ -2315,11 +2959,11 @@ for machine in $build $host $target; do
;;
*-*-openbsd*)
tm_file=${cpu_type}/openbsd.h
- # On OpenBSD systems, the headers are okay
- fixincludes=Makefile.in
tmake_file="t-libc-ok t-openbsd"
# avoid surprises, always provide an xm-openbsd file
xm_file=${cpu_type}/xm-openbsd.h
+ # don't depend on processor x-fragments as well
+ xmake_file=none
if test x$enable_threads = xyes; then
thread_file='posix'
tmake_file="${tmake_file} t-openbsd-thread"
@@ -2334,11 +2978,11 @@ for machine in $build $host $target; do
rest=`echo $machine | sed -e "s/$cpu_type-//"`
xm_file=${cpu_type}/xm-$rest.h
tm_file=${cpu_type}/$rest.h
- if [ -f $srcdir/config/${cpu_type}/x-$rest ] ; \
+ if test -f $srcdir/config/${cpu_type}/x-$rest; \
then xmake_file=${cpu_type}/x-$rest; \
else true; \
fi
- if [ -f $srcdir/config/${cpu_type}/t-$rest ] ; \
+ if test -f $srcdir/config/${cpu_type}/t-$rest; \
then tmake_file=${cpu_type}/t-$rest; \
else true; \
fi
@@ -2364,9 +3008,31 @@ for machine in $build $host $target; do
a29k-*-*) # Default a29k environment.
use_collect2=yes
;;
+ alpha-*-interix)
+ tm_file="${tm_file} alpha/alpha32.h interix.h alpha/alpha-interix.h"
+
+ # GAS + IEEE_CONFORMANT+IEEE (no inexact);
+ #target_cpu_default="MASK_GAS|MASK_IEEE_CONFORMANT|MASK_IEEE"
+
+ # GAS + IEEE_CONFORMANT
+ target_cpu_default="MASK_GAS|MASK_IEEE_CONFORMANT"
+
+ xm_file="alpha/xm-alpha-interix.h xm-interix.h"
+ xmake_file="x-interix alpha/t-pe"
+ tmake_file="alpha/t-interix alpha/t-ieee"
+ if test x$enable_threads = xyes ; then
+ thread_file='posix'
+ fi
+ if test x$stabs = xyes ; then
+ tm_file="${tm_file} dbxcoff.h"
+ fi
+ #prefix='$$INTERIX_ROOT'/usr/contrib
+ #local_prefix='$$INTERIX_ROOT'/usr/contrib
+ ;;
alpha*-*-linux-gnuecoff*)
tm_file="${tm_file} alpha/linux-ecoff.h alpha/linux.h"
target_cpu_default="MASK_GAS"
+ tmake_file="alpha/t-ieee"
gas=no
xmake_file=none
gas=yes gnu_ld=yes
@@ -2374,54 +3040,51 @@ for machine in $build $host $target; do
alpha*-*-linux-gnulibc1*)
tm_file="${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h"
target_cpu_default="MASK_GAS"
- tmake_file="t-linux t-linux-gnulibc1 alpha/t-linux alpha/t-crtbe"
+ tmake_file="t-linux t-linux-gnulibc1 alpha/t-linux alpha/t-crtbe alpha/t-ieee"
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.wrap
xmake_file=none
gas=yes gnu_ld=yes
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
alpha*-*-linux-gnu*)
tm_file="${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h"
target_cpu_default="MASK_GAS"
- tmake_file="t-linux alpha/t-linux alpha/t-crtbe"
+ tmake_file="t-linux alpha/t-linux alpha/t-crtbe alpha/t-ieee"
extra_parts="crtbegin.o crtend.o"
xmake_file=none
- fixincludes=Makefile.in
gas=yes gnu_ld=yes
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
alpha*-*-netbsd*)
- tm_file="${tm_file} alpha/elf.h alpha/netbsd.h alpha/netbsdl-elf.h"
- xm_file="xm-netbsd.h ${xm_file}"
+ tm_file="${tm_file} alpha/elf.h alpha/netbsd.h alpha/netbsd-elf.h"
target_cpu_default="MASK_GAS"
- tmake_file="alpha/t-crtbe"
+ tmake_file="alpha/t-crtbe alpha/t-ieee"
extra_parts="crtbegin.o crtend.o"
xmake_file=none
- fixincludes=fixinc.wrap
gas=yes gnu_ld=yes
;;
alpha*-*-openbsd*)
# default x-alpha is only appropriate for dec-osf.
target_cpu_default="MASK_GAS"
- xmake_file=none
+ tmake_file="alpha/t-ieee"
;;
alpha*-dec-osf*)
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
- if [ x$gas != xyes ]
+ if test x$gas != xyes
then
extra_passes="mips-tfile mips-tdump"
fi
use_collect2=yes
+ tmake_file="alpha/t-ieee"
case $machine in
*-*-osf1*)
tm_file="${tm_file} alpha/osf.h alpha/osf12.h alpha/osf2or3.h"
@@ -2444,33 +3107,33 @@ for machine in $build $host $target; do
;;
alpha*-*-vxworks*)
tm_file="${tm_file} dbx.h alpha/vxworks.h"
+ tmake_file="alpha/t-ieee"
if x$gas != xyes
then
extra_passes="mips-tfile mips-tdump"
fi
use_collect2=yes
+ thread_file='vxworks'
;;
alpha*-*-winnt*)
- tm_file="${tm_file} alpha/win-nt.h"
+ tm_file="${tm_file} alpha/alpha32.h alpha/win-nt.h winnt/win-nt.h"
xm_file="${xm_file} config/winnt/xm-winnt.h alpha/xm-winnt.h"
- tmake_file=t-libc-ok
+ tmake_file="t-libc-ok alpha/t-ieee"
xmake_file=winnt/x-winnt
extra_host_objs=oldnames.o
extra_gcc_objs="spawnv.o oldnames.o"
- fixincludes=fixinc.winnt
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
extra_programs=ld.exe
fi
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
;;
alpha*-dec-vms*)
tm_file=alpha/vms.h
xm_file="${xm_file} alpha/xm-vms.h"
- tmake_file=alpha/t-vms
- fixincludes=Makefile.in
+ tmake_file="alpha/t-vms alpha/t-ieee"
;;
arc-*-elf*)
extra_parts="crtinit.o crtfini.o"
@@ -2479,12 +3142,17 @@ for machine in $build $host $target; do
tm_file=arm/coff.h
tmake_file=arm/t-bare
;;
+ arm-*-vxworks*)
+ tm_file=arm/vxarm.h
+ tmake_file=arm/t-bare
+ thread_file='vxworks'
+ ;;
arm-*-riscix1.[01]*) # Acorn RISC machine (early versions)
tm_file=arm/riscix1-1.h
use_collect2=yes
;;
arm-*-riscix*) # Acorn RISC machine
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=arm/rix-gas.h
else
@@ -2497,57 +3165,84 @@ for machine in $build $host $target; do
arm-semi-aout | armel-semi-aout)
tm_file=arm/semi.h
tmake_file=arm/t-semi
- fixincludes=Makefile.in # There is nothing to fix
;;
arm-semi-aof | armel-semi-aof)
tm_file=arm/semiaof.h
tmake_file=arm/t-semiaof
- fixincludes=Makefile.in # There is nothing to fix
;;
arm*-*-netbsd*)
tm_file=arm/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
+ xm_file="arm/xm-netbsd.h ${xm_file}"
tmake_file="t-netbsd arm/t-netbsd"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
+ use_collect2=yes
;;
- arm-*-linux-gnuaout*) # ARM GNU/Linux
+ arm*-*-linux-gnuaout*) # ARM GNU/Linux with a.out
cpu_type=arm
xmake_file=x-linux
- tm_file=arm/linux-gas.h
+ tm_file=arm/linux-aout.h
tmake_file=arm/t-linux
- fixincludes=Makefile.in
gnu_ld=yes
;;
- arm-*-aout)
+ arm*-*-linux-gnu*) # ARM GNU/Linux with ELF
+ xm_file=arm/xm-linux.h
+ xmake_file=x-linux
+ case $machine in
+ armv2*-*-*)
+ tm_file=arm/linux-elf26.h
+ ;;
+ *)
+ tm_file=arm/linux-elf.h
+ ;;
+ esac
+ tmake_file="t-linux arm/t-linux"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gnu_ld=yes
+ case x${enable_threads} in
+ x | xyes | xpthreads | xposix)
+ thread_file='posix'
+ ;;
+ esac
+ ;;
+ arm*-*-aout)
tm_file=arm/aout.h
tmake_file=arm/t-bare
;;
+ arm*-*-ecos-elf)
+ tm_file=arm/ecos-elf.h
+ tmake_file=arm/t-elf
+ ;;
+ arm*-*-elf)
+ tm_file=arm/unknown-elf.h
+ tmake_file=arm/t-arm-elf
+ ;;
+ arm*-*-oabi)
+ tm_file=arm/unknown-elf-oabi.h
+ tmake_file=arm/t-arm-elf
+ ;;
c1-convex-*) # Convex C1
target_cpu_default=1
use_collect2=yes
- fixincludes=Makefile.in
;;
c2-convex-*) # Convex C2
target_cpu_default=2
use_collect2=yes
- fixincludes=Makefile.in
;;
c32-convex-*)
target_cpu_default=4
use_collect2=yes
- fixincludes=Makefile.in
;;
c34-convex-*)
target_cpu_default=8
use_collect2=yes
- fixincludes=Makefile.in
;;
c38-convex-*)
target_cpu_default=16
use_collect2=yes
- fixincludes=Makefile.in
;;
+ c4x-*)
+ cpu_type=c4x
+ tmake_file=c4x/t-c4x
+ ;;
clipper-intergraph-clix*)
tm_file="${tm_file} svr3.h clipper/clix.h"
xm_file=clipper/xm-clix.h
@@ -2568,8 +3263,8 @@ for machine in $build $host $target; do
float_format=i32
;;
hppa*-*-openbsd*)
- target_cpu_default="MASK_SNAKE"
- tmake_file=pa/t-openbsd
+ target_cpu_default="MASK_PA_11"
+ tmake_file=pa/t-openbsd
;;
hppa1.1-*-pro*)
tm_file="pa/pa-pro.h ${tm_file} pa/pa-pro-end.h libgloss.h"
@@ -2577,10 +3272,9 @@ for machine in $build $host $target; do
tmake_file=pa/t-pro
;;
hppa1.1-*-osf*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-osf.h"
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.1-*-rtems*)
tm_file="pa/pa-pro.h ${tm_file} pa/pa-pro-end.h libgloss.h pa/rtems.h"
@@ -2590,22 +3284,19 @@ for machine in $build $host $target; do
hppa1.0-*-osf*)
tm_file="${tm_file} pa/pa-osf.h"
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.1-*-bsd*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.0-*-bsd*)
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.0-*-hpux7*)
tm_file="pa/pa-oldas.h ${tm_file} pa/pa-hpux7.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/gas.h"
fi
@@ -2616,7 +3307,7 @@ for machine in $build $host $target; do
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
else
@@ -2626,11 +3317,11 @@ for machine in $build $host $target; do
use_collect2=yes
;;
hppa1.1-*-hpux8.0[0-2]*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
else
@@ -2640,11 +3331,11 @@ for machine in $build $host $target; do
use_collect2=yes
;;
hppa1.1-*-hpux8*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -2655,27 +3346,27 @@ for machine in $build $host $target; do
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.1-*-hpux10*)
- target_cpu_default=1
+ hppa1.1-*-hpux10* | hppa2*-*-hpux10*)
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux10.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
tmake_file=pa/t-pa
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
- if [ x$enable_threads = x ]; then
+ if test x$enable_threads = x; then
enable_threads=$have_pthread_h
fi
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='dce'
tmake_file="${tmake_file} pa/t-dce-thr"
fi
@@ -2687,26 +3378,26 @@ for machine in $build $host $target; do
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
tmake_file=pa/t-pa
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
- if [ x$enable_threads = x ]; then
+ if test x$enable_threads = x; then
enable_threads=$have_pthread_h
fi
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='dce'
tmake_file="${tmake_file} pa/t-dce-thr"
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.1-*-hpux*)
- target_cpu_default=1
+ hppa1.1-*-hpux* | hppa2*-*-hpux*)
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux9.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -2717,19 +3408,19 @@ for machine in $build $host $target; do
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux9.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.1-*-hiux*)
- target_cpu_default=1
+ hppa1.1-*-hiux* | hppa2*-*-hiux*)
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hiux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -2740,7 +3431,7 @@ for machine in $build $host $target; do
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hiux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -2748,14 +3439,13 @@ for machine in $build $host $target; do
use_collect2=yes
;;
hppa*-*-lites*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
use_collect2=yes
- fixincludes=Makefile.in
;;
i370-*-mvs*)
;;
i[34567]86-ibm-aix*) # IBM PS/2 running AIX
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=i386/aix386.h
extra_parts="crtbegin.o crtend.o"
@@ -2768,11 +3458,11 @@ for machine in $build $host $target; do
xm_defines=USG
xmake_file=i386/x-aix
;;
- i[34567]86-ncr-sysv4*) # NCR 3000 - ix86 running system V.4
+ i[34567]86-ncr-sysv4*) # NCR 3000 - ix86 running system V.4
xm_file="xm-siglist.h xm-alloca.h ${xm_file}"
xm_defines="USG POSIX SMALL_ARG_MAX"
xmake_file=i386/x-ncr3000
- if [ x$stabs = xyes -a x$gas = xyes ]
+ if test x$stabs = xyes -a x$gas = xyes
then
tm_file=i386/sysv4gdb.h
else
@@ -2787,13 +3477,14 @@ for machine in $build $host $target; do
tmake_file=i386/t-next
xmake_file=i386/x-next
extra_objs=nextstep.o
- if [ x$enable_threads = xyes ]; then
+ extra_parts="crtbegin.o crtend.o"
+ if test x$enable_threads = xyes; then
thread_file='mach'
fi
;;
i[34567]86-sequent-bsd*) # 80386 from Sequent
use_collect2=yes
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=i386/seq-gas.h
else
@@ -2805,7 +3496,6 @@ for machine in $build $host $target; do
xmake_file=i386/x-sysv3
tm_file=i386/seq-sysv3.h
tmake_file=i386/t-crtstuff
- fixincludes=fixinc.ptx
extra_parts="crtbegin.o crtend.o"
install_headers_dir=install-headers-cpio
;;
@@ -2815,7 +3505,6 @@ for machine in $build $host $target; do
tm_file=i386/seq2-sysv3.h
tmake_file=i386/t-crtstuff
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.ptx
install_headers_dir=install-headers-cpio
;;
i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*)
@@ -2825,7 +3514,6 @@ for machine in $build $host $target; do
tm_file=i386/ptx4-i.h
tmake_file=t-svr4
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.ptx
install_headers_dir=install-headers-cpio
;;
i386-sun-sunos*) # Sun i386 roadrunner
@@ -2836,6 +3524,7 @@ for machine in $build $host $target; do
i[34567]86-wrs-vxworks*)
tm_file=i386/vxi386.h
tmake_file=i386/t-i386bare
+ thread_file='vxworks'
;;
i[34567]86-*-aout*)
tm_file=i386/i386-aout.h
@@ -2852,34 +3541,26 @@ for machine in $build $host $target; do
# use_collect2=yes
;;
i[34567]86-*-freebsdelf*)
- tm_file="i386/i386.h i386/att.h linux.h i386/freebsd-elf.h i386/perform.h"
- # On FreeBSD, the headers are already ok, except for math.h.
- fixincludes=fixinc.wrap
+ tm_file="i386/i386.h i386/att.h svr4.h i386/freebsd-elf.h i386/perform.h"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- tmake_file=i386/t-freebsd
+ tmake_file=t-freebsd
gas=yes
gnu_ld=yes
stabs=yes
;;
i[34567]86-*-freebsd*)
tm_file=i386/freebsd.h
- # On FreeBSD, the headers are already ok, except for math.h.
- fixincludes=fixinc.wrap
- tmake_file=i386/t-freebsd
+ tmake_file=t-freebsd
;;
i[34567]86-*-netbsd*)
tm_file=i386/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
+ use_collect2=yes
+ ;;
+ i[34567]86-*-openbsd*)
+ # we need collect2 until our bug is fixed...
+ use_collect2=yes
;;
- i[34567]86-*-openbsd*)
- # Remove when the math emulator is fixed
- target_cpu_default="MASK_NO_FANCY_MATH_387"
- # we need collect2 until our bug is fixed...
- use_collect2=yes
- ;;
i[34567]86-*-coff*)
tm_file=i386/i386-coff.h
tmake_file=i386/t-i386bare
@@ -2895,7 +3576,7 @@ for machine in $build $host $target; do
xmake_file=i386/x-isc
;;
esac
- if [ x$gas = xyes -a x$stabs = xyes ]
+ if test x$gas = xyes -a x$stabs = xyes
then
tm_file=i386/iscdbx.h
tmake_file=i386/t-svr3dbx
@@ -2908,49 +3589,41 @@ for machine in $build $host $target; do
install_headers_dir=install-headers-cpio
;;
i[34567]86-*-linux-gnuoldld*) # Intel 80386's running GNU/Linux
- # with a.out format using
# pre BFD linkers
xmake_file=x-linux-aout
tmake_file="t-linux-aout i386/t-crtstuff"
tm_file=i386/linux-oldld.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
;;
i[34567]86-*-linux-gnuaout*) # Intel 80386's running GNU/Linux
- # with a.out format
xmake_file=x-linux-aout
tmake_file="t-linux-aout i386/t-crtstuff"
tm_file=i386/linux-aout.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
;;
i[34567]86-*-linux-gnulibc1) # Intel 80386's running GNU/Linux
- # with ELF format using the
# GNU/Linux C library 5
xmake_file=x-linux
tm_file=i386/linux.h
tmake_file="t-linux t-linux-gnulibc1 i386/t-crtstuff"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='single'
fi
;;
i[34567]86-*-linux-gnu*) # Intel 80386's running GNU/Linux
- # with ELF format using glibc 2
# aka GNU/Linux C library 6
xmake_file=x-linux
tm_file=i386/linux.h
tmake_file="t-linux i386/t-crtstuff"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
@@ -2958,26 +3631,30 @@ for machine in $build $host $target; do
float_format=i386
;;
i[34567]86-go32-msdos | i[34567]86-*-go32*)
- xm_file=i386/xm-go32.h
- tm_file=i386/go32.h
- tmake_file=i386/t-go32
+ echo "GO32/DJGPP V1.X is no longer supported. Use *-pc-msdosdjgpp for DJGPP V2.X instead."
+ exit 1
;;
i[34567]86-pc-msdosdjgpp*)
- xm_file=i386/xm-go32.h
- tm_file=i386/go32.h
- tmake_file=i386/t-go32
+ xm_file=i386/xm-djgpp.h
+ tm_file=i386/djgpp.h
+ tmake_file=i386/t-djgpp
+ xmake_file=i386/x-djgpp
gnu_ld=yes
gas=yes
+ exeext=.exe
+ case $host in *pc-msdosdjgpp*)
+ target_alias=djgpp
+ ;;
+ esac
;;
i[34567]86-moss-msdos* | i[34567]86-*-moss*)
tm_file=i386/moss.h
tmake_file=t-libc-ok
- fixincludes=Makefile.in
gnu_ld=yes
gas=yes
;;
i[34567]86-*-lynxos*)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=i386/lynx.h
else
@@ -2993,7 +3670,7 @@ for machine in $build $host $target; do
use_collect2=yes
;;
i[34567]86-*-osfrose*) # 386 using OSF/rose
- if [ x$elf = xyes ]
+ if test x$elf = xyes
then
tm_file=i386/osfelf.h
use_collect2=
@@ -3026,10 +3703,9 @@ for machine in $build $host $target; do
xm_file="xm-siglist.h xm-alloca.h ${xm_file} i386/xm-sco5.h"
xm_defines="USG SVR3"
xmake_file=i386/x-sco5
- fixincludes=fixinc.sco
install_headers_dir=install-headers-cpio
tm_file=i386/sco5.h
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="i386/sco5gas.h ${tm_file}"
tmake_file=i386/t-sco5gas
@@ -3042,9 +3718,8 @@ for machine in $build $host $target; do
xm_file="${xm_file} i386/xm-sco.h"
xm_defines="USG SVR3 BROKEN_LDEXP SMALL_ARG_MAX NO_SYS_SIGLIST"
xmake_file=i386/x-sco4
- fixincludes=fixinc.sco
install_headers_dir=install-headers-cpio
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file=i386/sco4dbx.h
tmake_file=i386/t-svr3dbx
@@ -3060,7 +3735,7 @@ for machine in $build $host $target; do
xm_file=i386/xm-sco.h
xmake_file=i386/x-sco
install_headers_dir=install-headers-cpio
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file=i386/scodbx.h
tmake_file=i386/t-svr3dbx
@@ -3075,7 +3750,7 @@ for machine in $build $host $target; do
i[34567]86-*-solaris2*)
xm_file="xm-siglist.h xm-alloca.h ${xm_file}"
xm_defines="USG POSIX SMALL_ARG_MAX"
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file=i386/sol2dbg.h
else
@@ -3084,34 +3759,30 @@ for machine in $build $host $target; do
tmake_file=i386/t-sol2
extra_parts="crt1.o crti.o crtn.o gcrt1.o gmon.o crtbegin.o crtend.o"
xmake_file=x-svr4
- case $machine in
- *-*-solaris2.[0-4])
- fixincludes=fixinc.svr4;;
- *)
- fixincludes=fixinc.wrap;;
- esac
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='solaris'
fi
;;
i[34567]86-*-sysv5*) # Intel x86 on System V Release 5
xm_file="xm-alloca.h xm-siglist.h ${xm_file}"
xm_defines="USG POSIX"
- tm_file=i386/sysv4.h
- if [ x$stabs = xyes ]
+ tm_file=i386/sysv5.h
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
tmake_file=i386/t-crtpic
xmake_file=x-svr4
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.svr4
+ if test x$enable_threads = xyes; then
+ thread_file='posix'
+ fi
;;
i[34567]86-*-sysv4*) # Intel 80386's running system V.4
xm_file="xm-siglist.h xm-alloca.h ${xm_file}"
xm_defines="USG POSIX SMALL_ARG_MAX"
tm_file=i386/sysv4.h
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -3119,12 +3790,20 @@ for machine in $build $host $target; do
xmake_file=x-svr4
extra_parts="crtbegin.o crtend.o"
;;
+ i[34567]86-*-udk*) # Intel x86 on SCO UW/OSR5 Dev Kit
+ xm_file="xm-alloca.h xm-siglist.h ${xm_file}"
+ xm_defines="USG POSIX"
+ tm_file=i386/udk.h
+ tmake_file="i386/t-crtpic i386/t-udk"
+ xmake_file=x-svr4
+ extra_parts="crtbegin.o crtend.o"
+ install_headers_dir=install-headers-cpio
+ ;;
i[34567]86-*-osf1*) # Intel 80386's running OSF/1 1.3+
cpu_type=i386
xm_file="${xm_file} xm-svr4.h i386/xm-sysv4.h i386/xm-osf1elf.h"
xm_defines="USE_C_ALLOCA SMALL_ARG_MAX"
- fixincludes=Makefile.in #Don't do it on OSF/1
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file=i386/osf1elfgdb.h
else
@@ -3137,9 +3816,9 @@ for machine in $build $host $target; do
i[34567]86-*-sysv*) # Intel 80386's running system V
xm_defines="USG SVR3"
xmake_file=i386/x-sysv3
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file=i386/svr3dbx.h
tmake_file=i386/t-svr3dbx
@@ -3161,14 +3840,24 @@ for machine in $build $host $target; do
tmake_file=i386/t-vsta
xmake_file=i386/x-vsta
;;
- i[34567]86-*-pe | i[34567]86-*-cygwin32)
- xm_file="${xm_file} i386/xm-cygwin32.h"
- tmake_file=i386/t-cygwin32
- tm_file=i386/cygwin32.h
- xmake_file=i386/x-cygwin32
+ i[34567]86-*-win32)
+ xm_file="${xm_file} i386/xm-cygwin.h"
+ tmake_file=i386/t-cygwin
+ tm_file=i386/win32.h
+ xmake_file=i386/x-cygwin
+ extra_objs=winnt.o
+ if test x$enable_threads = xyes; then
+ thread_file='win32'
+ fi
+ exeext=.exe
+ ;;
+ i[34567]86-*-pe | i[34567]86-*-cygwin*)
+ xm_file="${xm_file} i386/xm-cygwin.h"
+ tmake_file=i386/t-cygwin
+ tm_file=i386/cygwin.h
+ xmake_file=i386/x-cygwin
extra_objs=winnt.o
- fixincludes=Makefile.in
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
exeext=.exe
@@ -3176,22 +3865,47 @@ for machine in $build $host $target; do
i[34567]86-*-mingw32*)
tm_file=i386/mingw32.h
xm_file="${xm_file} i386/xm-mingw32.h"
- tmake_file="i386/t-cygwin32 i386/t-mingw32"
+ tmake_file="i386/t-cygwin i386/t-mingw32"
extra_objs=winnt.o
- xmake_file=i386/x-cygwin32
- fixincludes=Makefile.in
- if [ x$enable_threads = xyes ]; then
+ xmake_file=i386/x-cygwin
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
exeext=.exe
case $machine in
*mingw32msv*)
;;
- *mingw32crt* | *mingw32*)
+ *minwg32crt* | *mingw32*)
tm_file="${tm_file} i386/crtdll.h"
;;
esac
;;
+ i[34567]86-*-uwin*)
+ tm_file=i386/uwin.h
+ xm_file="${xm_file} i386/xm-uwin.h"
+ xm_defines="USG NO_STAB_H NO_SYS_SIGLIST"
+ tmake_file="i386/t-cygwin i386/t-uwin"
+ extra_objs=winnt.o
+ xmake_file=i386/x-cygwin
+ if test x$enable_threads = xyes; then
+ thread_file='win32'
+ fi
+ exeext=.exe
+ ;;
+ i[34567]86-*-interix*)
+ tm_file="i386/i386-interix.h interix.h"
+ xm_file="i386/xm-i386-interix.h xm-interix.h"
+ xm_defines="USG NO_SYS_SIGLIST"
+ tmake_file="i386/t-interix"
+ extra_objs=interix.o
+ xmake_file=x-interix
+ if test x$enable_threads = xyes ; then
+ thread_file='posix'
+ fi
+ if test x$stabs = xyes ; then
+ tm_file="${tm_file} dbxcoff.h"
+ fi
+ ;;
i[34567]86-*-winnt3*)
tm_file=i386/win-nt.h
out_file=i386/i386.c
@@ -3200,12 +3914,11 @@ for machine in $build $host $target; do
tmake_file=i386/t-winnt
extra_host_objs="winnt.o oldnames.o"
extra_gcc_objs="spawnv.o oldnames.o"
- fixincludes=fixinc.winnt
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
extra_programs=ld.exe
fi
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
;;
@@ -3216,7 +3929,6 @@ for machine in $build $host $target; do
tm_file=i386/dgux.h
tmake_file=i386/t-dgux
xmake_file=i386/x-dgux
- fixincludes=fixinc.dgux
install_headers_dir=install-headers-cpio
;;
i860-alliant-*) # Alliant FX/2800
@@ -3228,7 +3940,7 @@ for machine in $build $host $target; do
;;
i860-*-bsd*)
tm_file="${tm_file} i860/bsd.h"
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="${tm_file} i860/bsd-gas.h"
fi
@@ -3306,7 +4018,7 @@ for machine in $build $host $target; do
m68000-hp-hpux*) # HP 9000 series 300
xm_file="xm_alloca.h ${xm_file}"
xm_defines="USG NO_SYS_SIGLIST"
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
xmake_file=m68k/x-hp320g
tm_file=m68k/hp310g.h
@@ -3331,7 +4043,7 @@ for machine in $build $host $target; do
m68000-att-sysv*)
xm_file="m68k/xm-3b1.h ${xm_file}"
xm_defines=USG
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=m68k/3b1g.h
else
@@ -3347,13 +4059,13 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
extra_parts="crt1.o mcrt1.o maccrt1.o crt2.o crtn.o"
tm_file=
- if [ "$gnu_ld" = yes ]
+ if test "$gnu_ld" = yes
then
tm_file="${tm_file} m68k/auxgld.h"
else
tm_file="${tm_file} m68k/auxld.h"
fi
- if [ "$gas" = yes ]
+ if test "$gas" = yes
then
tm_file="${tm_file} m68k/auxgas.h"
else
@@ -3370,7 +4082,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-altos-sysv*) # Altos 3068
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=m68k/altos3068.h
xm_defines=USG
@@ -3381,9 +4093,9 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
;;
m68k-bull-sysv*) # Bull DPX/2
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file=m68k/dpx2cdbx.h
else
@@ -3411,10 +4123,10 @@ for machine in $build $host $target; do
tm_file=m68k/mot3300.h
xm_file="xm-alloca.h m68k/xm-mot3300.h ${xm_file}"
xm_defines=NO_SYS_SIGLIST
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
xmake_file=m68k/x-mot3300-gas
- if [ x$gnu_ld = xyes ]
+ if test x$gnu_ld = xyes
then
tmake_file=m68k/t-mot3300-gald
else
@@ -3423,7 +4135,7 @@ for machine in $build $host $target; do
fi
else
xmake_file=m68k/x-mot3300
- if [ x$gnu_ld = xyes ]
+ if test x$gnu_ld = xyes
then
tmake_file=m68k/t-mot3300-gld
else
@@ -3483,7 +4195,6 @@ for machine in $build $host $target; do
;;
m68k-hp-bsd4.4*) # HP 9000/3xx running 4.4bsd
tm_file=m68k/hp3bsd44.h
- xmake_file=m68k/x-hp3bsd44
use_collect2=yes
extra_headers=math-68881.h
float_format=m68k
@@ -3495,7 +4206,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-isi-bsd*)
- if [ x$with_fp = xno ]
+ if test x$with_fp = xno
then
tm_file=m68k/isi-nfp.h
else
@@ -3508,7 +4219,7 @@ for machine in $build $host $target; do
m68k-hp-hpux7*) # HP 9000 series 300 running HPUX version 7.
xm_file="xm_alloca.h ${xm_file}"
xm_defines="USG NO_SYS_SIGLIST"
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
xmake_file=m68k/x-hp320g
tm_file=m68k/hp320g.h
@@ -3524,7 +4235,7 @@ for machine in $build $host $target; do
m68k-hp-hpux*) # HP 9000 series 300
xm_file="xm_alloca.h ${xm_file}"
xm_defines="USG NO_SYS_SIGLIST"
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
xmake_file=m68k/x-hp320g
tm_file=m68k/hp320g.h
@@ -3544,7 +4255,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-sony-newsos3*)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=m68k/news3gas.h
else
@@ -3555,7 +4266,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-sony-bsd* | m68k-sony-newsos*)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=m68k/newsgas.h
else
@@ -3581,14 +4292,15 @@ for machine in $build $host $target; do
tmake_file=m68k/t-next
xmake_file=m68k/x-next
extra_objs=nextstep.o
+ extra_parts="crtbegin.o crtend.o"
extra_headers=math-68881.h
float_format=m68k
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='mach'
fi
;;
m68k-sun-sunos3*)
- if [ x$with_fp = xno ]
+ if test x$with_fp = xno
then
tm_file=m68k/sun3n3.h
else
@@ -3599,7 +4311,7 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
;;
m68k-sun-sunos*) # For SunOS 4 (the default).
- if [ x$with_fp = xno ]
+ if test x$with_fp = xno
then
tm_file=m68k/sun3n.h
else
@@ -3628,8 +4340,14 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
float_format=m68k
;;
+ m68020-*-elf* | m68k-*-elf*)
+ tm_file="m68k/m68020-elf.h libgloss.h"
+ xm_file=m68k/xm-m68kv.h
+ tmake_file=m68k/t-m68kelf
+ header_files=math-68881.h
+ ;;
m68k-*-lynxos*)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=m68k/lynx.h
else
@@ -3643,11 +4361,9 @@ for machine in $build $host $target; do
;;
m68k*-*-netbsd*)
tm_file=m68k/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
float_format=m68k
+ use_collect2=yes
;;
m68k*-*-openbsd*)
float_format=m68k
@@ -3676,7 +4392,6 @@ for machine in $build $host $target; do
xmake_file=x-linux
tm_file=m68k/linux-aout.h
tmake_file="t-linux-aout m68k/t-linux-aout"
- fixincludes=Makefile.in # The headers are ok already.
extra_headers=math-68881.h
float_format=m68k
gnu_ld=yes
@@ -3688,7 +4403,6 @@ for machine in $build $host $target; do
tm_file=m68k/linux.h
tmake_file="t-linux t-linux-gnulibc1 m68k/t-linux"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in # The headers are ok already.
extra_headers=math-68881.h
float_format=m68k
gnu_ld=yes
@@ -3700,11 +4414,10 @@ for machine in $build $host $target; do
tm_file=m68k/linux.h
tmake_file="t-linux m68k/t-linux"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in # The headers are ok already.
extra_headers=math-68881.h
float_format=m68k
gnu_ld=yes
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
@@ -3734,18 +4447,17 @@ for machine in $build $host $target; do
esac
extra_parts="crtbegin.o bcscrtbegin.o crtend.o m88kdgux.ld"
xmake_file=m88k/x-dgux
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=m88k/t-dgux-gas
fi
- fixincludes=fixinc.dgux
;;
m88k-dolphin-sysv3*)
tm_file=m88k/dolph.h
extra_parts="crtbegin.o crtend.o"
xm_file="m88k/xm-sysv3.h ${xm_file}"
xmake_file=m88k/x-dolph
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=m88k/t-m88k-gas
fi
@@ -3755,7 +4467,7 @@ for machine in $build $host $target; do
extra_parts="crtbegin.o crtend.o"
xm_file="m88k/xm-sysv3.h ${xm_file}"
xmake_file=m88k/x-tekXD88
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=m88k/t-m88k-gas
fi
@@ -3770,7 +4482,7 @@ for machine in $build $host $target; do
m88k-*-luna*)
tm_file=m88k/luna.h
extra_parts="crtbegin.o crtend.o"
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=m88k/t-luna-gas
else
@@ -3785,7 +4497,7 @@ for machine in $build $host $target; do
extra_parts="crtbegin.o crtend.o"
xm_file="m88k/xm-sysv3.h ${xm_file}"
xmake_file=m88k/x-sysv3
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=m88k/t-m88k-gas
fi
@@ -3799,38 +4511,36 @@ for machine in $build $host $target; do
mips-sgi-irix6*) # SGI System V.4., IRIX 6
tm_file=mips/iris6.h
xm_file=mips/xm-iris6.h
- fixincludes=fixinc.irix
xmake_file=mips/x-iris6
tmake_file=mips/t-iris6
- if [ x$enable_threads = xyes ]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-wrs-vxworks)
- tm_file="mips/elf.h libgloss.h"
+ tm_file="mips/elf.h libgloss.h mips/vxworks.h"
tmake_file=mips/t-ecoff
gas=yes
gnu_ld=yes
extra_parts="crtbegin.o crtend.o"
-# thread_file='vxworks'
+ thread_file='vxworks'
;;
mips-sgi-irix5cross64) # Irix5 host, Irix 6 target, cross64
tm_file="mips/iris6.h mips/cross64.h"
xm_defines=USG
xm_file="mips/xm-iris5.h"
- fixincludes=Makefile.in
xmake_file=mips/x-iris
tmake_file=mips/t-cross64
# See comment in mips/iris[56].h files.
use_collect2=yes
- if [ x$enable_threads = xyes ]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sni-sysv4)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file=mips/iris5gdb.h
else
@@ -3842,16 +4552,16 @@ for machine in $build $host $target; do
xm_defines=USG
xmake_file=mips/x-sni-svr4
tmake_file=mips/t-mips-gas
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-sgi-irix5*) # SGI System V.4., IRIX 5
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file="mips/iris5.h mips/iris5gas.h"
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -3860,72 +4570,71 @@ for machine in $build $host $target; do
fi
xm_defines=USG
xm_file="mips/xm-iris5.h"
- fixincludes=fixinc.irix
xmake_file=mips/x-iris
# mips-tfile doesn't work yet
tmake_file=mips/t-mips-gas
# See comment in mips/iris5.h file.
use_collect2=yes
- if [ x$enable_threads = xyes ]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sgi-irix4loser*) # Mostly like a MIPS.
tm_file="mips/iris4loser.h mips/iris3.h ${tm_file} mips/iris4.h"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-iris
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
- if [ x$enable_threads = xyes ]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sgi-irix4*) # Mostly like a MIPS.
tm_file="mips/iris3.h ${tm_file} mips/iris4.h"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-iris
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
- if [ x$enable_threads = xyes ]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sgi-*) # Mostly like a MIPS.
tm_file="mips/iris3.h ${tm_file}"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-iris3
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -3939,66 +4648,72 @@ for machine in $build $host $target; do
;;
mips-dec-osf*) # Decstation running OSF/1 as shipped by DIGITAL
tm_file=mips/dec-osf1.h
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xmake_file=mips/x-dec-osf1
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
tmake_file=mips/t-ultrix
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-dec-bsd*) # Decstation running 4.4 BSD
tm_file=mips/dec-bsd.h
- fixincludes=
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
tmake_file=mips/t-ultrix
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mipsel-*-netbsd* | mips-dec-netbsd*) # Decstation running NetBSD
tm_file=mips/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
# On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
;;
+ mips*-*-linux*) # Linux MIPS, either endian.
+ xmake_file=x-linux
+ xm_file="xm-siglist.h ${xm_file}"
+ case $machine in
+ mipsel-*) tm_file="mips/elfl.h mips/linux.h" ;;
+ *) tm_file="mips/elf.h mips/linux.h" ;;
+ esac
+ extra_parts="crtbegin.o crtend.o"
+ gnu_ld=yes
+ gas=yes
+ ;;
mips*el-*-openbsd*) # mips little endian
target_cpu_default="MASK_GAS|MASK_ABICALLS"
tm_file=mips/openbsd.h
- xmake_file=none
;;
mips*-*-openbsd*) # mips big endian
target_cpu_default="MASK_GAS|MASK_ABICALLS"
tm_file=mips/openbsd-be.h
- xmake_file=none
;;
mips-sony-bsd* | mips-sony-newsos*) # Sony NEWS 3600 or risc/news.
tm_file="mips/news4.h ${tm_file}"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -4008,31 +4723,31 @@ for machine in $build $host $target; do
# That is based on svr4.
# t-svr4 is not right because this system doesn't use ELF.
tm_file="mips/news5.h ${tm_file}"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_file="xm-siglist.h ${xm_file}"
xm_defines=USG
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-tandem-sysv4*) # Tandem S2 running NonStop UX
tm_file="mips/svr4-5.h mips/svr4-t.h"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_file="xm-siglist.h ${xm_file}"
xm_defines=USG
xmake_file=mips/x-sysv
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
extra_parts="crtbegin.o crtend.o"
@@ -4040,151 +4755,151 @@ for machine in $build $host $target; do
tmake_file=mips/t-mips
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-ultrix* | mips-dec-mach3) # Decstation.
tm_file="mips/ultrix.h ${tm_file}"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xmake_file=mips/x-ultrix
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
tmake_file=mips/t-ultrix
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-riscos[56789]bsd*)
tm_file=mips/bsd-5.h # MIPS BSD 4.3, RISC-OS 5.0
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-bsd-gas
else
tmake_file=mips/t-bsd
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-bsd* | mips-*-riscosbsd* | mips-*-riscos[1234]bsd*)
tm_file="mips/bsd-4.h ${tm_file}" # MIPS BSD 4.3, RISC-OS 4.0
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-bsd-gas
else
tmake_file=mips/t-bsd
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-riscos[56789]sysv4*)
tm_file=mips/svr4-5.h # MIPS System V.4., RISC-OS 5.0
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_file="xm-siglist.h ${xm_file}"
xmake_file=mips/x-sysv
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr4-gas
else
tmake_file=mips/t-svr4
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-sysv4* | mips-*-riscos[1234]sysv4* | mips-*-riscossysv4*)
tm_file="mips/svr4-4.h ${tm_file}"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-sysv
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr4-gas
else
tmake_file=mips/t-svr4
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-riscos[56789]sysv*)
tm_file=mips/svr3-5.h # MIPS System V.3, RISC-OS 5.0
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-sysv
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr3-gas
else
tmake_file=mips/t-svr3
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-sysv* | mips-*-riscos*sysv*)
tm_file="mips/svr3-4.h ${tm_file}"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-sysv
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr3-gas
else
tmake_file=mips/t-svr3
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-riscos[56789]*) # Default MIPS RISC-OS 5.0.
tm_file=mips/mips-5.h
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -4193,65 +4908,65 @@ for machine in $build $host $target; do
;;
mipsel-*-ecoff*)
tm_file=mips/ecoffl.h
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
tmake_file=mips/t-ecoff
;;
mips-*-ecoff*)
tm_file="gofast.h mips/ecoff.h"
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
tmake_file=mips/t-ecoff
;;
mipsel-*-elf*)
tm_file="mips/elfl.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tmake_file=mips/t-elf
;;
mips-*-elf*)
- tm_file="mips/elf.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tm_file="mips/elf.h"
+ tmake_file=mips/t-elf
;;
mips64el-*-elf*)
- tm_file="mips/elfl64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tm_file="mips/elfl64.h"
+ tmake_file=mips/t-elf
;;
mips64orionel-*-elf*)
tm_file="mips/elforion.h mips/elfl64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tmake_file=mips/t-elf
;;
mips64-*-elf*)
- tm_file="mips/elf64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tm_file="mips/elf64.h"
+ tmake_file=mips/t-elf
;;
mips64orion-*-elf*)
tm_file="mips/elforion.h mips/elf64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tmake_file=mips/t-elf
;;
mips64orion-*-rtems*)
tm_file="mips/elforion.h mips/elf64.h mips/rtems64.h"
tmake_file="mips/t-ecoff t-rtems"
;;
mipstx39el-*-elf*)
- tm_file="mips/r3900.h mips/elfl.h mips/abi64.h libgloss.h"
+ tm_file="mips/r3900.h mips/elfl.h mips/abi64.h"
tmake_file=mips/t-r3900
;;
mipstx39-*-elf*)
- tm_file="mips/r3900.h mips/elf.h mips/abi64.h libgloss.h"
+ tm_file="mips/r3900.h mips/elf.h mips/abi64.h"
tmake_file=mips/t-r3900
;;
mips-*-*) # Default MIPS RISC-OS 4.0.
- if [ x$stabs = xyes ]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [ x$gnu_ld != xyes ]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -4259,7 +4974,7 @@ for machine in $build $host $target; do
mn10200-*-*)
cpu_type=mn10200
tm_file="mn10200/mn10200.h"
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -4268,7 +4983,7 @@ for machine in $build $host $target; do
mn10300-*-*)
cpu_type=mn10300
tm_file="mn10300/mn10300.h"
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -4313,10 +5028,10 @@ for machine in $build $host $target; do
;;
ns32k-*-netbsd*)
tm_file=ns32k/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
+ xm_file="ns32k/xm-netbsd.h ${xm_file}"
# On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
+ use_collect2=yes
;;
pdp11-*-bsd)
tm_file="${tm_file} pdp11/2bsd.h"
@@ -4343,7 +5058,6 @@ for machine in $build $host $target; do
;;
powerpc-*-openbsd*)
tmake_file="${tmake_file} rs6000/t-rs6000 rs6000/t-openbsd"
- xmake_file=none
;;
powerpc-*-beos*)
cpu_type=rs6000
@@ -4357,7 +5071,7 @@ for machine in $build $host $target; do
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG POSIX"
extra_headers=ppc-asm.h
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
else
@@ -4368,52 +5082,47 @@ for machine in $build $host $target; do
powerpc-*-eabiaix*)
tm_file=rs6000/eabiaix.h
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-eabisim*)
tm_file=rs6000/eabisim.h
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-eabi*)
tm_file=rs6000/eabi.h
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc rs6000/t-ppccomm"
fi
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-rtems*)
tm_file=rs6000/rtems.h
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcgas t-rtems rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc t-rtems rs6000/t-ppccomm"
fi
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-linux-gnulibc1)
tm_file=rs6000/linux.h
xm_file=rs6000/xm-sysv4.h
out_file=rs6000/rs6000.c
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos t-linux t-linux-gnulibc1 rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc t-linux t-linux-gnulibc1 rs6000/t-ppccomm"
fi
xmake_file=x-linux
- fixincludes=Makefile.in
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
extra_headers=ppc-asm.h
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
@@ -4422,17 +5131,16 @@ for machine in $build $host $target; do
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG ${xm_defines}"
out_file=rs6000/rs6000.c
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos t-linux rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc t-linux rs6000/t-ppccomm"
fi
xmake_file=x-linux
- fixincludes=Makefile.in
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
extra_headers=ppc-asm.h
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
@@ -4449,7 +5157,7 @@ for machine in $build $host $target; do
tm_file=rs6000/sysv4le.h
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG POSIX"
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
else
@@ -4461,38 +5169,34 @@ for machine in $build $host $target; do
powerpcle-*-eabisim*)
tm_file=rs6000/eabilesim.h
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpcle-*-eabi*)
tm_file=rs6000/eabile.h
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc rs6000/t-ppccomm"
fi
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpcle-*-winnt* )
tm_file=rs6000/win-nt.h
tmake_file=rs6000/t-winnt
# extra_objs=pe.o
- fixincludes=Makefile.in
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
extra_headers=ppc-asm.h
;;
- powerpcle-*-pe | powerpcle-*-cygwin32)
- tm_file=rs6000/cygwin32.h
- xm_file="rs6000/xm-cygwin32.h ${xm_file}"
+ powerpcle-*-pe | powerpcle-*-cygwin*)
+ tm_file=rs6000/cygwin.h
+ xm_file="rs6000/xm-cygwin.h ${xm_file}"
tmake_file=rs6000/t-winnt
- xmake_file=rs6000/x-cygwin32
+ xmake_file=rs6000/x-cygwin
# extra_objs=pe.o
- fixincludes=Makefile.in
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
exeext=.exe
@@ -4502,73 +5206,79 @@ for machine in $build $host $target; do
tm_file=rs6000/sol2.h
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG POSIX"
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc rs6000/t-ppccomm"
fi
xmake_file=rs6000/x-sysv4
- case $machine in
- *-*-solaris2.[0-4])
- fixincludes=fixinc.svr4;;
- *)
- fixincludes=fixinc.wrap;;
- esac
extra_headers=ppc-asm.h
;;
rs6000-ibm-aix3.[01]*)
tm_file=rs6000/aix31.h
xmake_file=rs6000/x-aix31
+ float_format=none
use_collect2=yes
;;
rs6000-ibm-aix3.2.[456789]* | powerpc-ibm-aix3.2.[456789]*)
tm_file=rs6000/aix3newas.h
- if [ x$host != x$target ]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xnewas
else
tmake_file=rs6000/t-newas
fi
+ float_format=none
use_collect2=yes
;;
rs6000-ibm-aix4.[12]* | powerpc-ibm-aix4.[12]*)
tm_file=rs6000/aix41.h
- if [ x$host != x$target ]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xnewas
else
tmake_file=rs6000/t-newas
fi
- xmake_file=rs6000/x-aix41
+ if test "$gnu_ld" = yes
+ then
+ xmake_file=rs6000/x-aix41-gld
+ else
+ xmake_file=rs6000/x-aix41
+ fi
+ float_format=none
use_collect2=yes
;;
- rs6000-ibm-aix4.[3456789].* | powerpc-ibm-aix4.[3456789].*)
+ rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
tm_file=rs6000/aix43.h
- if [ x$host != x$target ]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xaix43
else
tmake_file=rs6000/t-aix43
fi
xmake_file=rs6000/x-aix43
+ float_format=none
use_collect2=yes
;;
rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
tm_file=rs6000/aix43.h
- if [ x$host != x$target ]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xaix43
else
tmake_file=rs6000/t-aix43
fi
xmake_file=rs6000/x-aix43
+ float_format=none
use_collect2=yes
;;
rs6000-ibm-aix*)
+ float_format=none
use_collect2=yes
;;
rs6000-bull-bosx)
+ float_format=none
use_collect2=yes
;;
rs6000-*-mach*)
@@ -4618,10 +5328,8 @@ for machine in $build $host $target; do
;;
sparc-*-netbsd*)
tm_file=sparc/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
+ use_collect2=yes
;;
sparc-*-openbsd*)
# we need collect2 until our bug is fixed...
@@ -4641,7 +5349,6 @@ for machine in $build $host $target; do
xm_file="${xm_file} sparc/xm-linux.h"
tm_file=sparc/linux-aout.h
xmake_file=x-linux
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
;;
sparc-*-linux-gnulibc1*) # Sparc's running GNU/Linux, libc5
@@ -4650,7 +5357,6 @@ for machine in $build $host $target; do
tm_file=sparc/linux.h
tmake_file="t-linux t-linux-gnulibc1"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
;;
sparc-*-linux-gnu*) # Sparc's running GNU/Linux, libc6
@@ -4659,14 +5365,13 @@ for machine in $build $host $target; do
tm_file=sparc/linux.h
tmake_file="t-linux"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
- if [ x$enable_threads = xyes ]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
sparc-*-lynxos*)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
tm_file=sparc/lynx.h
else
@@ -4680,8 +5385,38 @@ for machine in $build $host $target; do
tmake_file="sparc/t-sparcbare t-rtems"
tm_file=sparc/rtems.h
;;
+ sparcv9-*-solaris2*)
+ tm_file=sparc/sol2-sld-64.h
+ xm_file="sparc/xm-sysv4-64.h sparc/xm-sol2.h"
+ xm_defines="USG POSIX"
+ tmake_file="sparc/t-sol2 sparc/t-sol2-64"
+ xmake_file=sparc/x-sysv4
+ extra_parts="crt1.o crti.o crtn.o gcrt1.o crtbegin.o crtend.o"
+ float_format=none
+ if test x${enable_threads} = x ; then
+ enable_threads=$have_pthread_h
+ if test x${enable_threads} = x ; then
+ enable_threads=$have_thread_h
+ fi
+ fi
+ if test x${enable_threads} = xyes ; then
+ if test x${have_pthread_h} = xyes ; then
+ thread_file='posix'
+ else
+ thread_file='solaris'
+ fi
+ fi
+ ;;
+ sparc-hal-solaris2*)
+ xm_file=sparc/xm-sol2.h
+ tm_file="sparc/sol2.h sparc/hal.h"
+ tmake_file="sparc/t-halos sparc/t-sol2"
+ xmake_file=sparc/x-sysv4
+ extra_parts="crt1.o crti.o crtn.o gmon.o crtbegin.o crtend.o"
+ broken_install=yes
+ ;;
sparc-*-solaris2*)
- if [ x$gnu_ld = xyes ]
+ if test x$gnu_ld = xyes
then
tm_file=sparc/sol2.h
else
@@ -4694,19 +5429,20 @@ for machine in $build $host $target; do
extra_parts="crt1.o crti.o crtn.o gcrt1.o gmon.o crtbegin.o crtend.o"
case $machine in
*-*-solaris2.[0-4])
- fixincludes=fixinc.svr4;;
+ float_format=i128
+ ;;
*)
- fixincludes=fixinc.wrap;;
+ float_format=none
+ ;;
esac
- float_format=i128
- if [ x${enable_threads} = x ]; then
+ if test x${enable_threads} = x; then
enable_threads=$have_pthread_h
- if [ x${enable_threads} = x ]; then
+ if test x${enable_threads} = x; then
enable_threads=$have_thread_h
fi
fi
- if [ x${enable_threads} = xyes ]; then
- if [ x${have_pthread_h} = xyes ]; then
+ if test x${enable_threads} = xyes; then
+ if test x${have_pthread_h} = xyes; then
thread_file='posix'
else
thread_file='solaris'
@@ -4722,7 +5458,7 @@ for machine in $build $host $target; do
tm_file=sparc/sunos4.h
tmake_file=sparc/t-sunos41
use_collect2=yes
- if [ x$gas = xyes ]; then
+ if test x$gas = xyes; then
tm_file="${tm_file} sparc/sun4gas.h"
fi
;;
@@ -4767,11 +5503,11 @@ for machine in $build $host $target; do
extra_parts="crtbegin.o crtend.o"
;;
sparc64-*-linux*) # 64-bit Sparc's running GNU/Linux
- tmake_file=sparc/t-sp64
+ tmake_file="t-linux sparc/t-linux64"
xm_file="sparc/xm-sp64.h sparc/xm-linux.h"
tm_file=sparc/linux64.h
xmake_file=x-linux
- fixincludes=Makefile.in # The headers are ok already.
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
gnu_ld=yes
;;
# This hasn't been upgraded to GCC 2.
@@ -4786,7 +5522,14 @@ for machine in $build $host $target; do
xm_file=arm/xm-thumb.h
md_file=arm/thumb.md
tmake_file=arm/t-thumb
- fixincludes=Makefile.in # There is nothing to fix
+ ;;
+ thumb-wrs-vxworks)
+ tm_file=arm/tcoff.h
+ out_file=arm/thumb.c
+ xm_file=arm/xm-thumb.h
+ md_file=arm/thumb.md
+ tmake_file=arm/t-thumb
+ thread_file='vxworks'
;;
# This hasn't been upgraded to GCC 2.
# tron-*-*)
@@ -4798,7 +5541,7 @@ for machine in $build $host $target; do
tm_file="v850/v850.h"
xm_file="v850/xm-v850.h"
tmake_file=v850/t-v850
- if [ x$stabs = xyes ]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -4815,14 +5558,12 @@ for machine in $build $host $target; do
;;
vax-*-netbsd*)
tm_file="${tm_file} netbsd.h vax/netbsd.h"
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
float_format=vax
+ use_collect2=yes
;;
vax-*-openbsd*)
- tmake_file="${tm_file} vax/t-openbsd"
+ tmake_file="${tmake_file} vax/t-openbsd"
;;
vax-*-ultrix*) # vaxen running ultrix
tm_file="${tm_file} vax/ultrix.h"
@@ -4862,13 +5603,10 @@ for machine in $build $host $target; do
# GNU tools are the only tools.
gnu_ld=yes
gas=yes
- # On GNU, the headers are already okay.
- fixincludes=Makefile.in
xmake_file=x-linux # These details are the same as Linux.
tmake_file=t-gnu # These are not.
;;
*-*-sysv4*)
- fixincludes=fixinc.svr4
xmake_try_sysv=x-sysv
install_headers_dir=install-headers-cpio
;;
@@ -4886,7 +5624,14 @@ for machine in $build $host $target; do
target_cpu_default2=1
;;
i586-*-*)
- target_cpu_default2=2
+ case $target_alias in
+ k6-*)
+ target_cpu_default2=4
+ ;;
+ *)
+ target_cpu_default2=2
+ ;;
+ esac
;;
i686-*-* | i786-*-*)
target_cpu_default2=3
@@ -4894,7 +5639,7 @@ for machine in $build $host $target; do
alpha*-*-*)
case $machine in
alphaev6*)
- target_cpu_default2="MASK_CPU_EV6|MASK_BWX|MASK_CIX|MASK_MAX"
+ target_cpu_default2="MASK_CPU_EV6|MASK_BWX|MASK_MAX|MASK_FIX"
;;
alphapca56*)
target_cpu_default2="MASK_CPU_EV5|MASK_BWX|MASK_MAX"
@@ -4907,9 +5652,9 @@ for machine in $build $host $target; do
;;
esac
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
- if [ "$target_cpu_default2" = "" ]
+ if test "$target_cpu_default2" = ""
then
target_cpu_default2="MASK_GAS"
else
@@ -4929,7 +5674,7 @@ for machine in $build $host $target; do
xarm23678 | xarm250 | xarm67010 \
| xarm7m | xarm7dm | xarm7dmi | xarm7tdmi \
| xarm7100 | xarm7500 | xarm7500fe | xarm810 \
- | xstrongarm | xstrongarm110)
+ | xstrongarm | xstrongarm110 | xstrongarm1100)
target_cpu_default2="TARGET_CPU_$with_cpu"
;;
@@ -4939,7 +5684,7 @@ for machine in $build $host $target; do
;;
*)
- if [ x$pass2done = xyes ]
+ if test x$pass2done = xyes
then
echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
exit 1
@@ -4949,9 +5694,9 @@ for machine in $build $host $target; do
;;
mips*-*-ecoff* | mips*-*-elf*)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
- if [ x$gnu_ld = xyes ]
+ if test x$gnu_ld = xyes
then
target_cpu_default2=20
else
@@ -4960,7 +5705,7 @@ for machine in $build $host $target; do
fi
;;
mips*-*-*)
- if [ x$gas = xyes ]
+ if test x$gas = xyes
then
target_cpu_default2=16
fi
@@ -4973,6 +5718,7 @@ for machine in $build $host $target; do
xcommon | xpower | xpower2 | xpowerpc | xrios \
| xrios1 | xrios2 | xrsc | xrsc1 \
| x601 | x602 | x603 | x603e | x604 | x604e | x620 \
+ | xec603e | x740 | x750 | x401 \
| x403 | x505 | x801 | x821 | x823 | x860)
target_cpu_default2="\"$with_cpu\""
;;
@@ -4983,7 +5729,7 @@ for machine in $build $host $target; do
;;
*)
- if [ x$pass2done = xyes ]
+ if test x$pass2done = xyes
then
echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
exit 1
@@ -4996,11 +5742,11 @@ for machine in $build $host $target; do
.)
target_cpu_default2=TARGET_CPU_"`echo $machine | sed 's/-.*$//'`"
;;
- .supersparc | .ultrasparc | .v7 | .v8 | .v9)
+ .supersparc | .hypersparc | .ultrasparc | .v7 | .v8 | .v9)
target_cpu_default2="TARGET_CPU_$with_cpu"
;;
*)
- if [ x$pass2done = xyes ]
+ if test x$pass2done = xyes
then
echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
exit 1
@@ -5010,9 +5756,9 @@ for machine in $build $host $target; do
;;
esac
- if [ "$target_cpu_default2" != "" ]
+ if test "$target_cpu_default2" != ""
then
- if [ "$target_cpu_default" != "" ]
+ if test "$target_cpu_default" != ""
then
target_cpu_default="(${target_cpu_default}|${target_cpu_default2})"
else
@@ -5031,9 +5777,9 @@ for machine in $build $host $target; do
# Save data on machine being used to compile GCC in build_xm_file.
# Save data on host machine in vars host_xm_file and host_xmake_file.
- if [ x$pass1done = x ]
+ if test x$pass1done = x
then
- if [ x"$xm_file" = x ]
+ if test x"$xm_file" = x
then build_xm_file=$cpu_type/xm-$cpu_type.h
else build_xm_file=$xm_file
fi
@@ -5042,14 +5788,14 @@ for machine in $build $host $target; do
build_exeext=$exeext
pass1done=yes
else
- if [ x$pass2done = x ]
+ if test x$pass2done = x
then
- if [ x"$xm_file" = x ]
+ if test x"$xm_file" = x
then host_xm_file=$cpu_type/xm-$cpu_type.h
else host_xm_file=$xm_file
fi
host_xm_defines=$xm_defines
- if [ x"$xmake_file" = x ]
+ if test x"$xmake_file" = x
then xmake_file=$cpu_type/x-$cpu_type
fi
host_xmake_file="$xmake_file"
@@ -5065,48 +5811,50 @@ done
extra_objs="${host_extra_objs} ${extra_objs}"
# Default the target-machine variables that were not explicitly set.
-if [ x"$tm_file" = x ]
+if test x"$tm_file" = x
then tm_file=$cpu_type/$cpu_type.h; fi
-if [ x$extra_headers = x ]
+if test x$extra_headers = x
then extra_headers=; fi
-if [ x"$xm_file" = x ]
+if test x"$xm_file" = x
then xm_file=$cpu_type/xm-$cpu_type.h; fi
-if [ x$md_file = x ]
+if test x$md_file = x
then md_file=$cpu_type/$cpu_type.md; fi
-if [ x$out_file = x ]
+if test x$out_file = x
then out_file=$cpu_type/$cpu_type.c; fi
-if [ x"$tmake_file" = x ]
+if test x"$tmake_file" = x
then tmake_file=$cpu_type/t-$cpu_type
fi
-if [ x$float_format = x ]
+if test x"$dwarf2" = xyes
+then tm_file="tm-dwarf2.h $tm_file"
+fi
+
+if test x$float_format = x
then float_format=i64
fi
-if [ x$enable_haifa = x ]
+if test $float_format = none
+then float_h_file=Makefile.in
+else float_h_file=float-$float_format.h
+fi
+
+if test x$enable_haifa = x
then
case $target in
- alpha*-* | hppa1.?-* | powerpc*-* | rs6000-* | *sparc*-* | m32r*-*)
+ alpha*-* | hppa*-* | powerpc*-* | rs6000-* | *sparc*-* | m32r*-*)
enable_haifa=yes;;
esac
fi
# Handle cpp installation.
-if [ x$enable_cpp != x ]
+if test x$enable_cpp != xno
then
tmake_file="$tmake_file t-install-cpp"
- case x$enable_cpp in
- xyes | xno) ;;
- x/*) cpp_install_dir=$enable_cpp ;;
- x.*) echo "alternate cpp script installation directory must be an absolute path" 1>&2
- exit 1
- ;;
- esac
fi
# Say what files are being used for the output code and MD file.
@@ -5117,7 +5865,7 @@ count=a
for f in $tm_file; do
count=${count}x
done
-if [ $count = ax ]; then
+if test $count = ax; then
echo "Using \`$srcdir/config/$tm_file' as target machine macro file."
else
echo "Using the following target machine macro files:"
@@ -5130,7 +5878,7 @@ count=a
for f in $host_xm_file; do
count=${count}x
done
-if [ $count = ax ]; then
+if test $count = ax; then
echo "Using \`$srcdir/config/$host_xm_file' as host machine macro file."
else
echo "Using the following host machine macro files:"
@@ -5139,12 +5887,12 @@ else
done
fi
-if [ "$host_xm_file" != "$build_xm_file" ]; then
+if test "$host_xm_file" != "$build_xm_file"; then
count=a
for f in $build_xm_file; do
count=${count}x
done
- if [ $count = ax ]; then
+ if test $count = ax; then
echo "Using \`$srcdir/config/$build_xm_file' as build machine macro file."
else
echo "Using the following build machine macro files:"
@@ -5154,8 +5902,8 @@ if [ "$host_xm_file" != "$build_xm_file" ]; then
fi
fi
-if [ x$thread_file = x ]; then
- if [ x$target_thread_file != x ]; then
+if test x$thread_file = x; then
+ if test x$target_thread_file != x; then
thread_file=$target_thread_file
else
thread_file='single'
@@ -5168,14 +5916,14 @@ fi
# auto-host.h is the file containing items generated by autoconf and is
# the first file included by config.h.
null_defines=
-host_xm_file="auto-host.h ${host_xm_file}"
+host_xm_file="auto-host.h gansidecl.h ${host_xm_file} hwint.h"
# If host=build, it is correct to have hconfig include auto-host.h
# as well. If host!=build, we are in error and need to do more
# work to find out the build config parameters.
-if [ x$host = x$build ]
+if test x$host = x$build
then
- build_xm_file="auto-host.h ${build_xm_file}"
+ build_xm_file="auto-host.h gansidecl.h ${build_xm_file} hwint.h"
else
# We create a subdir, then run autoconf in the subdir.
# To prevent recursion we set host and build for the new
@@ -5197,18 +5945,21 @@ else
mv auto-host.h ../auto-build.h
cd ..
rm -rf $tempdir
- build_xm_file="auto-build.h ${build_xm_file}"
+ build_xm_file="auto-build.h gansidecl.h ${build_xm_file} hwint.h"
fi
+xm_file="gansidecl.h ${xm_file}"
+tm_file="gansidecl.h ${tm_file}"
+
vars="host_xm_file tm_file xm_file build_xm_file"
links="config.h tm.h tconfig.h hconfig.h"
defines="host_xm_defines null_defines xm_defines build_xm_defines"
rm -f config.bak
-if [ -f config.status ]; then mv -f config.status config.bak; fi
+if test -f config.status; then mv -f config.status config.bak; fi
# Make the links.
-while [ -n "$vars" ]
+while test -n "$vars"
do
set $vars; var=$1; shift; vars=$*
set $links; link=$1; shift; links=$*
@@ -5218,13 +5969,27 @@ do
# Define TARGET_CPU_DEFAULT if the system wants one.
# This substitutes for lots of *.h files.
- if [ "$target_cpu_default" != "" -a $link = tm.h ]
+ if test "$target_cpu_default" != "" -a $link = tm.h
then
echo "#define TARGET_CPU_DEFAULT ($target_cpu_default)" >>$link
fi
for file in `eval echo '$'$var`; do
+ case $file in
+ auto-config.h)
+ ;;
+ *)
+ echo '#ifdef IN_GCC' >>$link
+ ;;
+ esac
echo "#include \"$file\"" >>$link
+ case $file in
+ auto-config.h)
+ ;;
+ *)
+ echo '#endif' >>$link
+ ;;
+ esac
done
for def in `eval echo '$'$define`; do
@@ -5235,18 +6000,1885 @@ do
done
# Truncate the target if necessary
-if [ x$host_truncate_target != x ]; then
+if test x$host_truncate_target != x; then
target=`echo $target | sed -e 's/\(..............\).*/\1/'`
fi
# Get the version trigger filename from the toplevel
-if [ "${with_gcc_version_trigger+set}" = set ]; then
+if test "${with_gcc_version_trigger+set}" = set; then
gcc_version_trigger=$with_gcc_version_trigger
else
gcc_version_trigger=${srcdir}/version.c
fi
gcc_version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < ${gcc_version_trigger}`
+# Internationalization
+PACKAGE=gcc
+VERSION="$gcc_version"
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+
+ALL_LINGUAS="en_UK"
+
+# NLS support is still experimental, so disable it by default for now.
+# Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+ enableval="$enable_nls"
+ :
+else
+ enable_nls=no
+fi
+
+
+
+ echo $ac_n "checking for strerror in -lcposix""... $ac_c" 1>&6
+echo "configure:6044: checking for strerror in -lcposix" >&5
+ac_lib_var=`echo cposix'_'strerror | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcposix $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 6052 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strerror();
+
+int main() {
+strerror()
+; return 0; }
+EOF
+if { (eval echo configure:6063: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lcposix"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:6086: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6091 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:6140: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:6161: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 6168 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:6175: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:6201: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6206 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_off_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+ cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:6234: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6239 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:6269: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6274 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:6281: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:6302: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6307 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:6335: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_func_alloca_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.${ac_objext}
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:6367: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6372 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6397: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6402 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6425: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:6452: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6460 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:6479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_stack_direction=1
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:6504: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6509 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:6514: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6543: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6548 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:6596: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6604 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize();
+
+ /*
+ * First, make a file with some known garbage in it.
+ */
+ data = malloc(pagesize);
+ if (!data)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand();
+ umask(0);
+ fd = creat("conftestmmap", 0600);
+ if (fd < 0)
+ exit(1);
+ if (write(fd, data, pagesize) != pagesize)
+ exit(1);
+ close(fd);
+
+ /*
+ * Next, try to mmap the file at a fixed address which
+ * already has something else allocated at it. If we can,
+ * also make sure that we see the same garbage.
+ */
+ fd = open("conftestmmap", O_RDWR);
+ if (fd < 0)
+ exit(1);
+ data2 = malloc(2 * pagesize);
+ if (!data2)
+ exit(1);
+ data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit(1);
+
+ /*
+ * Finally, make sure that changes to the mapped area
+ * do not percolate back to the file as seen by read().
+ * (This is a bug on some variants of i386 svr4.0.)
+ */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = malloc(pagesize);
+ if (!data3)
+ exit(1);
+ if (read(fd, data3, pagesize) != pagesize)
+ exit(1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit(1);
+ close(fd);
+ unlink("conftestmmap");
+ exit(0);
+}
+
+EOF
+if { (eval echo configure:6744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+
+ for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h sys/param.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:6772: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6777 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:6782: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \
+strdup __argz_count __argz_stringify __argz_next
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6812: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6817 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6840: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ for ac_func in stpcpy
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6869: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6874 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6897: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_STPCPY 1
+EOF
+
+ fi
+
+ if test $ac_cv_header_locale_h = yes; then
+ echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
+echo "configure:6931: checking for LC_MESSAGES" >&5
+if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6936 "configure"
+#include "confdefs.h"
+#include <locale.h>
+int main() {
+return LC_MESSAGES
+; return 0; }
+EOF
+if { (eval echo configure:6943: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ am_cv_val_LC_MESSAGES=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ am_cv_val_LC_MESSAGES=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LC_MESSAGES 1
+EOF
+
+ fi
+ fi
+ echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
+echo "configure:6964: checking whether NLS is requested" >&5
+ # Check whether --enable-nls or --disable-nls was given.
+if test "${enable_nls+set}" = set; then
+ enableval="$enable_nls"
+ USE_NLS=$enableval
+else
+ USE_NLS=yes
+fi
+
+ echo "$ac_t""$USE_NLS" 1>&6
+
+
+ USE_INCLUDED_LIBINTL=no
+
+ if test "$USE_NLS" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_NLS 1
+EOF
+
+ echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
+echo "configure:6984: checking whether included gettext is requested" >&5
+ # Check whether --with-included-gettext or --without-included-gettext was given.
+if test "${with_included_gettext+set}" = set; then
+ withval="$with_included_gettext"
+ nls_cv_force_use_gnu_gettext=$withval
+else
+ nls_cv_force_use_gnu_gettext=no
+fi
+
+ echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
+echo "configure:7003: checking for libintl.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7008 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:7013: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
+echo "configure:7030: checking for gettext in libc" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7035 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:7042: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ gt_cv_func_gettext_libc=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gt_cv_func_gettext_libc=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
+echo "configure:7058: checking for bindtextdomain in -lintl" >&5
+ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lintl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7066 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char bindtextdomain();
+
+int main() {
+bindtextdomain()
+; return 0; }
+EOF
+if { (eval echo configure:7077: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
+echo "configure:7093: checking for gettext in libintl" >&5
+if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo $ac_n "checking for gettext in -lintl""... $ac_c" 1>&6
+echo "configure:7098: checking for gettext in -lintl" >&5
+ac_lib_var=`echo intl'_'gettext | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lintl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7106 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gettext();
+
+int main() {
+gettext()
+; return 0; }
+EOF
+if { (eval echo configure:7117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ gt_cv_func_gettext_libintl=yes
+else
+ echo "$ac_t""no" 1>&6
+gt_cv_func_gettext_libintl=no
+fi
+
+fi
+
+echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GETTEXT 1
+EOF
+
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7156: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MSGFMT" in
+ /*)
+ ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+ ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no"
+ ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+ echo "$ac_t""$MSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ if test "$MSGFMT" != "no"; then
+ for ac_func in dcgettext
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:7190: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7195 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:7218: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7245: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7281: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XGETTEXT" in
+ /*)
+ ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+ ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+ ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+ echo "$ac_t""$XGETTEXT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ cat > conftest.$ac_ext <<EOF
+#line 7313 "configure"
+#include "confdefs.h"
+
+int main() {
+extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr
+; return 0; }
+EOF
+if { (eval echo configure:7321: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ CATOBJEXT=.gmo
+ DATADIRNAME=share
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CATOBJEXT=.mo
+ DATADIRNAME=lib
+fi
+rm -f conftest*
+ INSTOBJEXT=.mo
+ fi
+ fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ if test "$CATOBJEXT" = "NONE"; then
+ echo $ac_n "checking whether catgets can be used""... $ac_c" 1>&6
+echo "configure:7344: checking whether catgets can be used" >&5
+ # Check whether --with-catgets or --without-catgets was given.
+if test "${with_catgets+set}" = set; then
+ withval="$with_catgets"
+ nls_cv_use_catgets=$withval
+else
+ nls_cv_use_catgets=no
+fi
+
+ echo "$ac_t""$nls_cv_use_catgets" 1>&6
+
+ if test "$nls_cv_use_catgets" = "yes"; then
+ echo $ac_n "checking for main in -li""... $ac_c" 1>&6
+echo "configure:7357: checking for main in -li" >&5
+ac_lib_var=`echo i'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-li $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7365 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:7372: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo i | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-li $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for catgets""... $ac_c" 1>&6
+echo "configure:7400: checking for catgets" >&5
+if eval "test \"`echo '$''{'ac_cv_func_catgets'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7405 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char catgets(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char catgets();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_catgets) || defined (__stub___catgets)
+choke me
+#else
+catgets();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:7428: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_catgets=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_catgets=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'catgets`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_CATGETS 1
+EOF
+
+ INTLOBJS="\$(CATOBJS)"
+ # Extract the first word of "gencat", so it can be a program name with args.
+set dummy gencat; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7450: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GENCAT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GENCAT" in
+ /*)
+ ac_cv_path_GENCAT="$GENCAT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GENCAT="$GENCAT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GENCAT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GENCAT" && ac_cv_path_GENCAT="no"
+ ;;
+esac
+fi
+GENCAT="$ac_cv_path_GENCAT"
+if test -n "$GENCAT"; then
+ echo "$ac_t""$GENCAT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ if test "$GENCAT" != "no"; then
+ # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7486: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="no"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "$GMSGFMT" = "no"; then
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7523: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="no"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7558: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XGETTEXT" in
+ /*)
+ ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+ ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+ ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+ echo "$ac_t""$XGETTEXT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.cat
+ INSTOBJEXT=.cat
+ DATADIRNAME=lib
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ fi
+ fi
+
+ if test "$CATOBJEXT" = "NONE"; then
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ INTLOBJS="\$(GETTOBJS)"
+ # Extract the first word of "msgfmt", so it can be a program name with args.
+set dummy msgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7616: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MSGFMT" in
+ /*)
+ ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then
+ ac_cv_path_MSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt"
+ ;;
+esac
+fi
+MSGFMT="$ac_cv_path_MSGFMT"
+if test -n "$MSGFMT"; then
+ echo "$ac_t""$MSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "gmsgfmt", so it can be a program name with args.
+set dummy gmsgfmt; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7650: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GMSGFMT" in
+ /*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GMSGFMT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT"
+ ;;
+esac
+fi
+GMSGFMT="$ac_cv_path_GMSGFMT"
+if test -n "$GMSGFMT"; then
+ echo "$ac_t""$GMSGFMT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ # Extract the first word of "xgettext", so it can be a program name with args.
+set dummy xgettext; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:7686: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XGETTEXT" in
+ /*)
+ ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then
+ ac_cv_path_XGETTEXT="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":"
+ ;;
+esac
+fi
+XGETTEXT="$ac_cv_path_XGETTEXT"
+if test -n "$XGETTEXT"; then
+ echo "$ac_t""$XGETTEXT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+
+ if test "$XGETTEXT" != ":"; then
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ echo "$ac_t""found xgettext program is not GNU xgettext; ignore it" 1>&6
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+
+
+
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
+echo "configure:7779: checking for catalogs to be installed" >&5
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ echo "$ac_t""$LINGUAS" 1>&6
+ fi
+
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+
+
+ test -d intl || mkdir intl
+ if test "$CATOBJEXT" = ".cat"; then
+ ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6
+echo "configure:7807: checking for linux/version.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7812 "configure"
+#include "confdefs.h"
+#include <linux/version.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:7817: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ msgformat=linux
+else
+ echo "$ac_t""no" 1>&6
+msgformat=xopen
+fi
+
+
+ sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
+ fi
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed
+
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+
+
+
+ MKINSTALLDIRS=
+ if test -n "$ac_aux_dir"; then
+ MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
+ fi
+ if test -z "$MKINSTALLDIRS"; then
+ MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+ fi
+
+
+ l=
+
+
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+
+XGETTEXT="AWK='$AWK' \$(SHELL) \$(top_srcdir)/exgettext $XGETTEXT"
+
# Get an absolute path to the GCC top-level source directory
holddir=`pwd`
cd $srcdir
@@ -5260,7 +7892,7 @@ host_overrides=Make-host
dep_host_xmake_file=
for f in .. ${host_xmake_file}
do
- if [ -f ${srcdir}/config/$f ]
+ if test -f ${srcdir}/config/$f
then
dep_host_xmake_file="${dep_host_xmake_file} ${srcdir}/config/$f"
fi
@@ -5273,7 +7905,7 @@ target_overrides=Make-target
dep_tmake_file=
for f in .. ${tmake_file}
do
- if [ -f ${srcdir}/config/$f ]
+ if test -f ${srcdir}/config/$f
then
dep_tmake_file="${dep_tmake_file} ${srcdir}/config/$f"
fi
@@ -5286,6 +7918,7 @@ rm -f symtest.tem
if $symbolic_link $srcdir/gcc.c symtest.tem 2>/dev/null
then
cc_set_by_configure="\$(CC)"
+ quoted_cc_set_by_configure="\$(CC)"
stage_prefix_set_by_configure="\$(STAGE_PREFIX)"
else
rm -f symtest.tem
@@ -5296,6 +7929,7 @@ else
symbolic_link="cp"
fi
cc_set_by_configure="\`case '\$(CC)' in stage*) echo '\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\$(CC)';; esac\`"
+ quoted_cc_set_by_configure="\\\`case '\\\$(CC)' in stage*) echo '\\\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\\\$(CC)';; esac\\\`"
stage_prefix_set_by_configure="\`case '\$(STAGE_PREFIX)' in stage*) echo '\$(STAGE_PREFIX)' | sed -e 's|stage|../stage|g';; *) echo '\$(STAGE_PREFIX)';; esac\`"
fi
rm -f symtest.tem
@@ -5304,29 +7938,29 @@ out_object_file=`basename $out_file .c`.o
tm_file_list=
for f in $tm_file; do
- tm_file_list="${tm_file_list} \$(srcdir)/config/$f"
+ case $f in
+ gansidecl.h )
+ tm_file_list="${tm_file_list} $f" ;;
+ *) tm_file_list="${tm_file_list} \$(srcdir)/config/$f" ;;
+ esac
done
host_xm_file_list=
for f in $host_xm_file; do
- if test $f != "auto-host.h"; then
- host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f"
- else
- host_xm_file_list="${host_xm_file_list} auto-host.h"
- fi
+ case $f in
+ auto-host.h | gansidecl.h | hwint.h )
+ host_xm_file_list="${host_xm_file_list} $f" ;;
+ *) host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f" ;;
+ esac
done
build_xm_file_list=
for f in $build_xm_file; do
- if test $f != "auto-build.h"; then
- if test $f != "auto-host.h"; then
- build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f"
- else
- build_xm_file_list="${build_xm_file_list} auto-host.h"
- fi
- else
- build_xm_file_list="${build_xm_file_list} auto-build.h"
- fi
+ case $f in
+ auto-build.h | auto-host.h | gansidecl.h | hwint.h )
+ build_xm_file_list="${build_xm_file_list} $f" ;;
+ *) build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f" ;;
+ esac
done
# Define macro CROSS_COMPILE in compilation
@@ -5334,7 +7968,7 @@ done
# Also use all.cross instead of all.internal
# and add cross-make to Makefile.
cross_overrides="/dev/null"
-if [ x$host != x$target ]
+if test x$host != x$target
then
cross_defines="CROSS=-DCROSS_COMPILE"
cross_overrides="${topdir}/cross-make"
@@ -5344,7 +7978,7 @@ fi
# This must come after cross-make as we want all.build to override
# all.cross.
build_overrides="/dev/null"
-if [ x$build != x$host ]
+if test x$build != x$host
then
build_overrides="${topdir}/build-make"
fi
@@ -5352,7 +7986,7 @@ fi
# Expand extra_headers to include complete path.
# This substitutes for lots of t-* files.
extra_headers_list=
-if [ "x$extra_headers" = x ]
+if test "x$extra_headers" = x
then true
else
# Prepend ${srcdir}/ginclude/ to every entry in extra_headers.
@@ -5362,10 +7996,14 @@ else
done
fi
+if test x$use_collect2 = xno; then
+ use_collect2=
+fi
+
# Add a definition of USE_COLLECT2 if system wants one.
# Also tell toplev.c what to do.
# This substitutes for lots of t-* files.
-if [ x$use_collect2 = x ]
+if test x$use_collect2 = x
then
will_use_collect2=
maybe_use_collect2=
@@ -5381,7 +8019,7 @@ fi
# building gcc with a cross compiler, use the cross compiler just
# built. Otherwise, we can use the cpp just built.
md_file_sub=
-if [ "x$md_cppflags" = x ]
+if test "x$md_cppflags" = x
then
md_file_sub=$srcdir/config/$md_file
else
@@ -5389,18 +8027,18 @@ else
fi
# If we have gas in the build tree, make a link to it.
-if [ -f ../gas/Makefile ]; then
+if test -f ../gas/Makefile; then
rm -f as; $symbolic_link ../gas/as-new$host_exeext as$host_exeext 2>/dev/null
fi
# If we have nm in the build tree, make a link to it.
-if [ -f ../binutils/Makefile ]; then
+if test -f ../binutils/Makefile; then
rm -f nm; $symbolic_link ../binutils/nm-new$host_exeext nm$host_exeext 2>/dev/null
fi
# If we have ld in the build tree, make a link to it.
-if [ -f ../ld/Makefile ]; then
-# if [[ x$use_collect2 = x ]]; then
+if test -f ../ld/Makefile; then
+# if test x$use_collect2 = x; then
# rm -f ld; $symbolic_link ../ld/ld-new$host_exeext ld$host_exeext 2>/dev/null
# else
rm -f collect-ld; $symbolic_link ../ld/ld-new$host_exeext collect-ld$host_exeext 2>/dev/null
@@ -5409,28 +8047,32 @@ fi
# Figure out what assembler alignment features are present.
echo $ac_n "checking assembler alignment features""... $ac_c" 1>&6
-echo "configure:5413: checking assembler alignment features" >&5
+echo "configure:8051: checking assembler alignment features" >&5
gcc_cv_as=
gcc_cv_as_alignment_features=
-gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,gcc$,gas,'`
-if [ -x as$host_exeext ]; then
+gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gas
+if test -x "$DEFAULT_ASSEMBLER"; then
+ gcc_cv_as="$DEFAULT_ASSEMBLER"
+elif test -x "$AS"; then
+ gcc_cv_as="$AS"
+elif test -x as$host_exeext; then
# Build using assembler in the current directory.
gcc_cv_as=./as$host_exeext
-elif [ -f $gcc_cv_as_gas_srcdir/configure.in ]; then
+elif test -f $gcc_cv_as_gas_srcdir/configure.in -a -f ../gas/Makefile; then
# Single tree build which includes gas.
for f in $gcc_cv_as_gas_srcdir/configure $gcc_cv_as_gas_srcdir/configure.in $gcc_cv_as_gas_srcdir/Makefile.in
do
gcc_cv_gas_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f`
- if [ x$gcc_cv_gas_version != x ]; then
+ if test x$gcc_cv_gas_version != x; then
break
fi
done
gcc_cv_gas_major_version=`expr "$gcc_cv_gas_version" : "VERSION=\([0-9]*\)"`
gcc_cv_gas_minor_version=`expr "$gcc_cv_gas_version" : "VERSION=[0-9]*\.\([0-9]*\)"`
- if [ x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x ]; then
+ if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
# Gas version 2.6 and later support for .balign and .p2align.
# bytes to skip when using .p2align.
- if [ "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 6 -o "$gcc_cv_gas_major_version" -gt 2 ]; then
+ if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 6 -o "$gcc_cv_gas_major_version" -gt 2; then
gcc_cv_as_alignment_features=".balign and .p2align"
cat >> confdefs.h <<\EOF
#define HAVE_GAS_BALIGN_AND_P2ALIGN 1
@@ -5439,7 +8081,7 @@ EOF
fi
# Gas version 2.8 and later support specifying the maximum
# bytes to skip when using .p2align.
- if [ "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 8 -o "$gcc_cv_gas_major_version" -gt 2 ]; then
+ if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 8 -o "$gcc_cv_gas_major_version" -gt 2; then
gcc_cv_as_alignment_features=".p2align including maximum skip"
cat >> confdefs.h <<\EOF
#define HAVE_GAS_MAX_SKIP_P2ALIGN 1
@@ -5447,11 +8089,59 @@ EOF
fi
fi
-elif [ x$host = x$target ]; then
+elif test x$host = x$target; then
# Native build.
- gcc_cv_as=as$host_exeext
+ # Search the same directories that the installed compiler will
+ # search. Else we may find the wrong assembler and lose. If we
+ # do not find a suitable assembler binary, then try the user's
+ # path.
+ #
+ # Also note we have to check MD_EXEC_PREFIX before checking the
+ # user's path. Unfortunately, there is no good way to get at the
+ # value of MD_EXEC_PREFIX here. So we do a brute force search
+ # through all the known MD_EXEC_PREFIX values. Ugh. This needs
+ # to be fixed as part of the make/configure rewrite too.
+
+ if test "x$exec_prefix" = xNONE; then
+ if test "x$prefix" = xNONE; then
+ test_prefix=/usr/local
+ else
+ test_prefix=$prefix
+ fi
+ else
+ test_prefix=$exec_prefix
+ fi
+
+ # If the loop below does not find an assembler, then use whatever
+ # one we can find in the users's path.
+ # user's path.
+ as=as$host_exeext
+
+ test_dirs="$test_prefix/lib/gcc-lib/$target/$gcc_version \
+ $test_prefix/lib/gcc-lib/$target \
+ /usr/lib/gcc/$target/$gcc_version \
+ /usr/lib/gcc/$target \
+ $test_prefix/$target/bin/$target/$gcc_version \
+ $test_prefix/$target/bin \
+ /usr/libexec \
+ /usr/ccs/gcc \
+ /usr/ccs/bin \
+ /udk/usr/ccs/bin \
+ /bsd43/usr/lib/cmplrs/cc \
+ /usr/cross64/usr/bin \
+ /usr/lib/cmplrs/cc \
+ /sysv/usr/lib/cmplrs/cc \
+ /svr4/usr/lib/cmplrs/cc \
+ /usr/bin"
+
+ for dir in $test_dirs; do
+ if test -f $dir/as$host_exeext; then
+ gcc_cv_as=$dir/as$host_exeext
+ break;
+ fi
+ done
fi
-if [ x$gcc_cv_as != x ]; then
+if test x$gcc_cv_as != x; then
# Check if we have .balign and .p2align
echo ".balign 4" > conftest.s
echo ".p2align 2" >> conftest.s
@@ -5477,7 +8167,78 @@ EOF
fi
echo "$ac_t""$gcc_cv_as_alignment_features" 1>&6
+echo $ac_n "checking assembler subsection support""... $ac_c" 1>&6
+echo "configure:8172: checking assembler subsection support" >&5
+gcc_cv_as_subsections=
+if test x$gcc_cv_as != x; then
+ # Check if we have .subsection
+ echo ".subsection 1" > conftest.s
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_subsections=".subsection"
+ if test -x nm$host_exeext; then
+ gcc_cv_nm=./nm$host_exeext
+ elif test x$host = x$target; then
+ # Native build.
+ gcc_cv_nm=nm$host_exeext
+ fi
+ if test x$gcc_cv_nm != x; then
+ cat > conftest.s <<EOF
+conftest_label1: .word 0
+.subsection -1
+conftest_label2: .word 0
+.previous
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ $gcc_cv_nm conftest.o | grep conftest_label1 > conftest.nm1
+ $gcc_cv_nm conftest.o | grep conftest_label2 | sed -e 's/label2/label1/' > conftest.nm2
+ if cmp conftest.nm1 conftest.nm2 > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_as_subsections="working .subsection -1"
+ cat >> confdefs.h <<\EOF
+#define HAVE_GAS_SUBSECTION_ORDERING 1
+EOF
+
+ fi
+ fi
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest.nm1 conftest.nm2
+fi
+echo "$ac_t""$gcc_cv_as_subsections" 1>&6
+
+echo $ac_n "checking assembler instructions""... $ac_c" 1>&6
+echo "configure:8212: checking assembler instructions" >&5
+gcc_cv_as_instructions=
+if test x$gcc_cv_as != x; then
+ set "filds fists" "filds mem; fists mem"
+ while test $# -gt 0
+ do
+ echo "$2" > conftest.s
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_instructions=${gcc_cv_as_instructions}$1" "
+ cat >> confdefs.h <<EOF
+#define HAVE_GAS_`echo "$1" | tr 'a-z ' 'A-Z_'` 1
+EOF
+
+ fi
+ shift 2
+ done
+ rm -f conftest.s conftest.o
+fi
+echo "$ac_t""$gcc_cv_as_instructions" 1>&6
+
# Figure out what language subdirectories are present.
+# Look if the user specified --enable-languages="..."; if not, use
+# the environment variable $LANGUAGES if defined. $LANGUAGES might
+# go away some day.
+if test x"${enable_languages+set}" != xset; then
+ if test x"${LANGUAGES+set}" = xset; then
+ enable_languages="`echo ${LANGUAGES} | tr ' ' ','`"
+ else
+ enable_languages=all
+ fi
+fi
subdirs=
for lang in ${srcdir}/*/config-lang.in ..
do
@@ -5486,13 +8247,44 @@ do
# The odd quoting in the next line works around
# an apparent bug in bash 1.12 on linux.
${srcdir}/[*]/config-lang.in) ;;
- *) subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`" ;;
+ *)
+ lang_alias=`sed -n -e 's,^language=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^language=\([^ ]*\).*$,\1,p' $lang`
+ if test "x$lang_alias" = x
+ then
+ echo "$lang doesn't set \$language." 1>&2
+ exit 1
+ fi
+ if test x"${enable_languages}" = xall; then
+ add_this_lang=yes
+ else
+ case "${enable_languages}" in
+ ${lang_alias} | "${lang_alias},"* | *",${lang_alias},"* | *",${lang_alias}" )
+ add_this_lang=yes
+ ;;
+ * )
+ add_this_lang=no
+ ;;
+ esac
+ fi
+ if test x"${add_this_lang}" = xyes; then
+ case $lang in
+ ${srcdir}/ada/config-lang.in)
+ if test x$gnat = xyes ; then
+ subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
+ fi
+ ;;
+ *)
+ subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
+ ;;
+ esac
+ fi
+ ;;
esac
done
# Make gthr-default.h if we have a thread file.
gthread_flags=
-if [ $thread_file != single ]; then
+if test $thread_file != single; then
rm -f gthr-default.h
echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h
gthread_flags=-DHAVE_GTHR_DEFAULT
@@ -5504,18 +8296,23 @@ fi
lang_specs_files=
lang_options_files=
-rm -f specs.h options.h
-touch specs.h options.h
+lang_tree_files=
+rm -f specs.h options.h gencheck.h
+touch specs.h options.h gencheck.h
for subdir in . $subdirs
do
- if [ -f $srcdir/$subdir/lang-specs.h ]; then
+ if test -f $srcdir/$subdir/lang-specs.h; then
echo "#include \"$subdir/lang-specs.h\"" >>specs.h
lang_specs_files="$lang_specs_files $srcdir/$subdir/lang-specs.h"
fi
- if [ -f $srcdir/$subdir/lang-options.h ]; then
+ if test -f $srcdir/$subdir/lang-options.h; then
echo "#include \"$subdir/lang-options.h\"" >>options.h
lang_options_files="$lang_options_files $srcdir/$subdir/lang-options.h"
fi
+ if test -f $srcdir/$subdir/$subdir-tree.def; then
+ echo "#include \"$subdir/$subdir-tree.def\"" >>gencheck.h
+ lang_tree_files="$lang_tree_files $srcdir/$subdir/$subdir-tree.def"
+ fi
done
# These (without "all_") are set in each config-lang.in.
@@ -5525,7 +8322,7 @@ all_boot_languages=
all_compilers=
all_stagestuff=
all_diff_excludes=
-all_outputs=Makefile
+all_outputs='Makefile intl/Makefile po/Makefile.in fixinc/Makefile'
# List of language makefile fragments.
all_lang_makefiles=
all_headers=
@@ -5544,7 +8341,7 @@ oldstyle_subdirs=
for s in .. $subdirs
do
- if [ $s != ".." ]
+ if test $s != ".."
then
language=
boot_language=
@@ -5555,14 +8352,14 @@ do
outputs=
lib2funcs=
. ${srcdir}/$s/config-lang.in
- if [ "x$language" = x ]
+ if test "x$language" = x
then
echo "${srcdir}/$s/config-lang.in doesn't set \$language." 1>&2
exit 1
fi
all_lang_makefiles="$all_lang_makefiles ${srcdir}/$s/Make-lang.in ${srcdir}/$s/Makefile.in"
all_languages="$all_languages $language"
- if [ "x$boot_language" = xyes ]
+ if test "x$boot_language" = xyes
then
all_boot_languages="$all_boot_languages $language"
fi
@@ -5571,7 +8368,7 @@ do
all_diff_excludes="$all_diff_excludes $diff_excludes"
all_headers="$all_headers $headers"
all_outputs="$all_outputs $outputs"
- if [ x$outputs = x ]
+ if test x$outputs = x
then
oldstyle_subdirs="$oldstyle_subdirs $s"
fi
@@ -5593,10 +8390,10 @@ target_list="all.build all.cross start.encap rest.encap \
for t in $target_list
do
x=
- for l in .. $all_languages
+ for lang in .. $all_languages
do
- if [ $l != ".." ]; then
- x="$x $l.$t"
+ if test $lang != ".."; then
+ x="$x $lang.$t"
fi
done
echo "lang.$t: $x" >> Make-hooks
@@ -5604,14 +8401,14 @@ done
# If we're not building in srcdir, create .gdbinit.
-if [ ! -f Makefile.in ]; then
+if test ! -f Makefile.in; then
echo "dir ." > .gdbinit
echo "dir ${srcdir}" >> .gdbinit
- if [ x$gdb_needs_out_file_path = xyes ]
+ if test x$gdb_needs_out_file_path = xyes
then
echo "dir ${srcdir}/config/"`dirname ${out_file}` >> .gdbinit
fi
- if [ "x$subdirs" != x ]; then
+ if test "x$subdirs" != x; then
for s in $subdirs
do
echo "dir ${srcdir}/$s" >> .gdbinit
@@ -5625,7 +8422,7 @@ fi
build_canonical=${build}
host_canonical=${host}
target_subdir=
-if [ "${host}" != "${target}" ] ; then
+if test "${host}" != "${target}" ; then
target_subdir=${target}/
fi
@@ -5637,7 +8434,7 @@ fi
# libgcc.a, but that's OK because newib should have its own version of
# assert.h.
inhibit_libc=
-if [ x$with_newlib = xyes ]; then
+if test x$with_newlib = xyes; then
inhibit_libc=-Dinhibit_libc
fi
@@ -5645,23 +8442,60 @@ fi
# Override SCHED_OBJ and SCHED_CFLAGS to enable the Haifa scheduler.
sched_prefix=
sched_cflags=
-if [ x$enable_haifa = xyes ]; then
+if test x$enable_haifa = xyes; then
echo "Using the Haifa scheduler."
sched_prefix=haifa-
sched_cflags=-DHAIFA
fi
-if [ x$enable_haifa != x ]; then
+if test x$enable_haifa != x; then
# Explicitly remove files that need to be recompiled for the Haifa scheduler.
- for x in genattrtab.o toplev.o loop.o unroll.o *sched.o; do
- if [ -f $x ]; then
+ for x in genattrtab.o toplev.o *sched.o; do
+ if test -f $x; then
echo "Removing $x"
rm -f $x
fi
done
fi
+# If $(exec_prefix) exists and is not the same as $(prefix), then compute an
+# absolute path for gcc_tooldir based on inserting the number of up-directory
+# movements required to get from $(exec_prefix) to $(prefix) into the basic
+# $(libsubdir)/@(unlibsubdir) based path.
+# Don't set gcc_tooldir to tooldir since that's only passed in by the toplevel
+# make and thus we'd get different behavior depending on where we built the
+# sources.
+if test x$exec_prefix = xNONE -o x$exec_prefix = x$prefix; then
+ gcc_tooldir='$(libsubdir)/$(unlibsubdir)/../$(target_alias)'
+else
+# An explanation of the sed strings:
+# -e 's|^\$(prefix)||' matches and eliminates 'prefix' from 'exec_prefix'
+# -e 's|/$||' match a trailing forward slash and eliminates it
+# -e 's|^[^/]|/|' forces the string to start with a forward slash (*)
+# -e 's|/[^/]*|../|g' replaces each occurance of /<directory> with ../
+#
+# (*) Note this pattern overwrites the first character of the string
+# with a forward slash if one is not already present. This is not a
+# problem because the exact names of the sub-directories concerned is
+# unimportant, just the number of them matters.
+#
+# The practical upshot of these patterns is like this:
+#
+# prefix exec_prefix result
+# ------ ----------- ------
+# /foo /foo/bar ../
+# /foo/ /foo/bar ../
+# /foo /foo/bar/ ../
+# /foo/ /foo/bar/ ../
+# /foo /foo/bar/ugg ../../
+#
+ dollar='$$'
+ gcc_tooldir="\$(libsubdir)/\$(unlibsubdir)/\`echo \$(exec_prefix) | sed -e 's|^\$(prefix)||' -e 's|/\$(dollar)||' -e 's|^[^/]|/|' -e 's|/[^/]*|../|g'\`\$(target_alias)"
+fi
+
+
+
# Nothing to do for FLOAT_H, float_format already handled.
objdir=`pwd`
@@ -5726,8 +8560,13 @@ ${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xma
+
+
+
+
+
# Echo that links are built
-if [ x$host = x$target ]
+if test x$host = x$target
then
str1="native "
else
@@ -5735,25 +8574,25 @@ else
str2=" from $host"
fi
-if [ x$host != x$build ]
+if test x$host != x$build
then
str3=" on a $build system"
fi
-if [ "x$str2" != x ] || [ "x$str3" != x ]
+if test "x$str2" != x || test "x$str3" != x
then
str4=
fi
echo "Links are now set up to build a ${str1}compiler for ${target}$str4" 1>&2
-if [ "x$str2" != x ] || [ "x$str3" != x ]
+if test "x$str2" != x || test "x$str3" != x
then
echo " ${str2}${str3}." 1>&2
fi
# Truncate the target if necessary
-if [ x$host_truncate_target != x ]; then
+if test x$host_truncate_target != x; then
target=`echo $target | sed -e 's/\(..............\).*/\1/'`
fi
@@ -5910,6 +8749,7 @@ s%@build_cpu@%$build_cpu%g
s%@build_vendor@%$build_vendor%g
s%@build_os@%$build_os%g
s%@CC@%$CC%g
+s%@stage1_warn_cflags@%$stage1_warn_cflags%g
s%@SET_MAKE@%$SET_MAKE%g
s%@AWK@%$AWK%g
s%@LEX@%$LEX%g
@@ -5922,10 +8762,35 @@ s%@INSTALL@%$INSTALL%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@CPP@%$CPP%g
+s%@gnat@%$gnat%g
s%@vfprintf@%$vfprintf%g
s%@doprint@%$doprint%g
s%@manext@%$manext%g
s%@objext@%$objext%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ALLOCA@%$ALLOCA%g
+s%@USE_NLS@%$USE_NLS%g
+s%@MSGFMT@%$MSGFMT%g
+s%@GMSGFMT@%$GMSGFMT%g
+s%@XGETTEXT@%$XGETTEXT%g
+s%@GENCAT@%$GENCAT%g
+s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g
+s%@CATALOGS@%$CATALOGS%g
+s%@CATOBJEXT@%$CATOBJEXT%g
+s%@DATADIRNAME@%$DATADIRNAME%g
+s%@GMOFILES@%$GMOFILES%g
+s%@INSTOBJEXT@%$INSTOBJEXT%g
+s%@INTLDEPS@%$INTLDEPS%g
+s%@INTLLIBS@%$INTLLIBS%g
+s%@INTLOBJS@%$INTLOBJS%g
+s%@POFILES@%$POFILES%g
+s%@POSUB@%$POSUB%g
+s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g
+s%@GT_NO@%$GT_NO%g
+s%@GT_YES@%$GT_YES%g
+s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g
+s%@l@%$l%g
s%@gthread_flags@%$gthread_flags%g
s%@build_canonical@%$build_canonical%g
s%@host_canonical@%$host_canonical%g
@@ -5933,53 +8798,60 @@ s%@target_subdir@%$target_subdir%g
s%@inhibit_libc@%$inhibit_libc%g
s%@sched_prefix@%$sched_prefix%g
s%@sched_cflags@%$sched_cflags%g
+s%@gcc_tooldir@%$gcc_tooldir%g
+s%@dollar@%$dollar%g
s%@objdir@%$objdir%g
s%@subdirs@%$subdirs%g
-s%@all_languages@%$all_languages%g
s%@all_boot_languages@%$all_boot_languages%g
s%@all_compilers@%$all_compilers%g
-s%@all_lang_makefiles@%$all_lang_makefiles%g
-s%@all_stagestuff@%$all_stagestuff%g
s%@all_diff_excludes@%$all_diff_excludes%g
-s%@all_lib2funcs@%$all_lib2funcs%g
s%@all_headers@%$all_headers%g
+s%@all_lang_makefiles@%$all_lang_makefiles%g
+s%@all_languages@%$all_languages%g
+s%@all_lib2funcs@%$all_lib2funcs%g
+s%@all_stagestuff@%$all_stagestuff%g
+s%@build_exeext@%$build_exeext%g
+s%@build_install_headers_dir@%$build_install_headers_dir%g
+s%@build_xm_file_list@%$build_xm_file_list%g
+s%@cc_set_by_configure@%$cc_set_by_configure%g
+s%@quoted_cc_set_by_configure@%$quoted_cc_set_by_configure%g
+s%@cpp_install_dir@%$cpp_install_dir%g
s%@cpp_main@%$cpp_main%g
-s%@extra_passes@%$extra_passes%g
-s%@extra_programs@%$extra_programs%g
-s%@extra_parts@%$extra_parts%g
+s%@dep_host_xmake_file@%$dep_host_xmake_file%g
+s%@dep_tmake_file@%$dep_tmake_file%g
+s%@extra_c_flags@%$extra_c_flags%g
s%@extra_c_objs@%$extra_c_objs%g
+s%@extra_cpp_objs@%$extra_cpp_objs%g
s%@extra_cxx_objs@%$extra_cxx_objs%g
-s%@extra_c_flags@%$extra_c_flags%g
+s%@extra_headers_list@%$extra_headers_list%g
s%@extra_objs@%$extra_objs%g
+s%@extra_parts@%$extra_parts%g
+s%@extra_passes@%$extra_passes%g
+s%@extra_programs@%$extra_programs%g
+s%@fixinc_defs@%$fixinc_defs%g
+s%@float_h_file@%$float_h_file%g
+s%@gcc_gxx_include_dir@%$gcc_gxx_include_dir%g
+s%@gcc_version@%$gcc_version%g
+s%@gcc_version_trigger@%$gcc_version_trigger%g
+s%@host_exeext@%$host_exeext%g
s%@host_extra_gcc_objs@%$host_extra_gcc_objs%g
-s%@extra_headers_list@%$extra_headers_list%g
-s%@dep_host_xmake_file@%$dep_host_xmake_file%g
-s%@dep_tmake_file@%$dep_tmake_file%g
-s%@out_file@%$out_file%g
-s%@out_object_file@%$out_object_file%g
-s%@md_file@%$md_file%g
-s%@tm_file_list@%$tm_file_list%g
-s%@build_xm_file_list@%$build_xm_file_list%g
s%@host_xm_file_list@%$host_xm_file_list%g
-s%@lang_specs_files@%$lang_specs_files%g
+s%@install@%$install%g
+s%@JAVAGC@%$JAVAGC%g
s%@lang_options_files@%$lang_options_files%g
-s%@thread_file@%$thread_file%g
-s%@gcc_version@%$gcc_version%g
-s%@gcc_version_trigger@%$gcc_version_trigger%g
+s%@lang_specs_files@%$lang_specs_files%g
+s%@lang_tree_files@%$lang_tree_files%g
s%@local_prefix@%$local_prefix%g
-s%@gxx_include_dir@%$gxx_include_dir%g
-s%@fixincludes@%$fixincludes%g
-s%@build_install_headers_dir@%$build_install_headers_dir%g
-s%@build_exeext@%$build_exeext%g
-s%@host_exeext@%$host_exeext%g
-s%@float_format@%$float_format%g
-s%@will_use_collect2@%$will_use_collect2%g
s%@maybe_use_collect2@%$maybe_use_collect2%g
-s%@cc_set_by_configure@%$cc_set_by_configure%g
+s%@md_file@%$md_file%g
+s%@objc_boehm_gc@%$objc_boehm_gc%g
+s%@out_file@%$out_file%g
+s%@out_object_file@%$out_object_file%g
s%@stage_prefix_set_by_configure@%$stage_prefix_set_by_configure%g
-s%@install@%$install%g
s%@symbolic_link@%$symbolic_link%g
-s%@cpp_install_dir@%$cpp_install_dir%g
+s%@thread_file@%$thread_file%g
+s%@tm_file_list@%$tm_file_list%g
+s%@will_use_collect2@%$will_use_collect2%g
/@target_overrides@/r $target_overrides
s%@target_overrides@%%g
/@host_overrides@/r $host_overrides
@@ -6196,8 +9068,54 @@ cat >> $CONFIG_STATUS <<\EOF
fi; done
EOF
+
+cat >> $CONFIG_STATUS <<EOF
+ac_sources="$nls_cv_header_libgt"
+ac_dests="$nls_cv_header_intl"
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+srcdir=$ac_given_srcdir
+while test -n "$ac_sources"; do
+ set $ac_dests; ac_dest=$1; shift; ac_dests=$*
+ set $ac_sources; ac_source=$1; shift; ac_sources=$*
+
+ echo "linking $srcdir/$ac_source to $ac_dest"
+
+ if test ! -r $srcdir/$ac_source; then
+ { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; }
+ fi
+ rm -f $ac_dest
+
+ # Make relative symlinks.
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then
+ # The dest file is in a subdirectory.
+ test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir"
+ ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dest_dir_suffix.
+ ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dest_dir_suffix= ac_dots=
+ fi
+
+ case "$srcdir" in
+ [/$]*) ac_rel_source="$srcdir/$ac_source" ;;
+ *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;;
+ esac
+
+ # Make a symlink if possible; otherwise try a hard link.
+ if ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+ ln $srcdir/$ac_source $ac_dest; then :
+ else
+ { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; }
+ fi
+done
+EOF
cat >> $CONFIG_STATUS <<EOF
+
host='${host}'
build='${build}'
target='${target}'
@@ -6232,6 +9150,9 @@ cpp_install_dir='${cpp_install_dir}'
EOF
cat >> $CONFIG_STATUS <<\EOF
+case "$CONFIG_FILES" in *po/Makefile.in*)
+ sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+ esac
. $srcdir/configure.lang
case x$CONFIG_HEADERS in
@@ -6244,9 +9165,9 @@ esac
# FLAGS_TO_PASS has been modified to solve the problem there.
# This is virtually a duplicate of what happens in configure.lang; we do
# an extra check to make sure this only happens if ln -s can be used.
-if [ "$symbolic_link" = "ln -s" ]; then
+if test "$symbolic_link" = "ln -s"; then
for d in .. ${subdirs} ; do
- if [ $d != .. ]; then
+ if test $d != ..; then
STARTDIR=`pwd`
cd $d
for t in stage1 stage2 stage3 stage4 include
@@ -6258,6 +9179,11 @@ if [ "$symbolic_link" = "ln -s" ]; then
fi
done
else true ; fi
+# Avoid having to add intl to our include paths.
+if test -f intl/libintl.h; then
+ echo creating libintl.h
+ echo '#include "intl/libintl.h"' >libintl.h
+fi
exit 0
EOF
diff --git a/contrib/gcc/configure.in b/contrib/gcc/configure.in
index a943830..448e0f8 100644
--- a/contrib/gcc/configure.in
+++ b/contrib/gcc/configure.in
@@ -1,7 +1,7 @@
# configure.in for GNU CC
# Process this file with autoconf to generate a configuration script.
-# Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+# Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -21,6 +21,7 @@
#Boston, MA 02111-1307, USA.
# Initialization and defaults
+AC_PREREQ(2.12.1)
AC_INIT(tree.c)
AC_CONFIG_HEADER(auto-host.h:config.in)
@@ -29,6 +30,59 @@ hard_link=ln
symbolic_link='ln -s'
copy=cp
+# Check for bogus environment variables.
+# Test if LIBRARY_PATH contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# LIBRARY_PATH contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+AC_MSG_CHECKING(LIBRARY_PATH variable)
+changequote(,)dnl
+case ${LIBRARY_PATH} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ library_path_setting="contains current directory"
+ ;;
+ *)
+ library_path_setting="ok"
+ ;;
+esac
+changequote([,])dnl
+AC_MSG_RESULT($library_path_setting)
+if test "$library_path_setting" != "ok"; then
+AC_MSG_ERROR([
+*** LIBRARY_PATH shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again.])
+fi
+
+# Test if GCC_EXEC_PREFIX contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# GCC_EXEC_PREFIX contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+AC_MSG_CHECKING(GCC_EXEC_PREFIX variable)
+changequote(,)dnl
+case ${GCC_EXEC_PREFIX} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ gcc_exec_prefix_setting="contains current directory"
+ ;;
+ *)
+ gcc_exec_prefix_setting="ok"
+ ;;
+esac
+changequote([,])dnl
+AC_MSG_RESULT($gcc_exec_prefix_setting)
+if test "$gcc_exec_prefix_setting" != "ok"; then
+AC_MSG_ERROR([
+*** GCC_EXEC_PREFIX shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again.])
+fi
+
# Check for additional parameters
# With GNU ld
@@ -37,12 +91,37 @@ AC_ARG_WITH(gnu-ld,
gnu_ld_flag="$with_gnu_ld",
gnu_ld_flag=no)
+# With pre-defined ld
+AC_ARG_WITH(ld,
+[ --with-ld arrange to use the specified ld (full pathname).],
+DEFAULT_LINKER="$with_ld")
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_LINKER"; then
+ AC_MSG_WARN([cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER])
+ elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gnu_ld_flag=yes
+ fi
+ AC_DEFINE_UNQUOTED(DEFAULT_LINKER,"$DEFAULT_LINKER")
+fi
+
# With GNU as
AC_ARG_WITH(gnu-as,
[ --with-gnu-as arrange to work with GNU as.],
gas_flag="$with_gnu_as",
gas_flag=no)
+AC_ARG_WITH(as,
+[ --with-as arrange to use the specified as (full pathname).],
+DEFAULT_ASSEMBLER="$with_as")
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_ASSEMBLER"; then
+ AC_MSG_WARN([cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER])
+ elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gas_flag=yes
+ fi
+ AC_DEFINE_UNQUOTED(DEFAULT_ASSEMBLER,"$DEFAULT_ASSEMBLER")
+fi
+
# With stabs
AC_ARG_WITH(stabs,
[ --with-stabs arrange to use stabs instead of host debug format.],
@@ -66,11 +145,14 @@ no) ;;
esac])
# Default local prefix if it is empty
-if [[ x$local_prefix = x ]]; then
+if test x$local_prefix = x; then
local_prefix=/usr/local
fi
-gxx_include_dir=
+# Don't set gcc_gxx_include_dir to gxx_include_dir since that's only
+# passed in by the toplevel make and thus we'd get different behavior
+# depending on where we built the sources.
+gcc_gxx_include_dir=
# Specify the g++ header file directory
AC_ARG_WITH(gxx-include-dir,
[ --with-gxx-include-dir=DIR
@@ -78,14 +160,17 @@ AC_ARG_WITH(gxx-include-dir,
[case "${withval}" in
yes) AC_MSG_ERROR(bad value ${withval} given for g++ include directory) ;;
no) ;;
-*) gxx_include_dir=$with_gxx_include_dir ;;
+*) gcc_gxx_include_dir=$with_gxx_include_dir ;;
esac])
-if test x${gxx_include_dir} = x; then
+if test x${gcc_gxx_include_dir} = x; then
if test x${enable_version_specific_runtime_libs} = xyes; then
- gxx_include_dir='${libsubdir}/include/g++'
+ gcc_gxx_include_dir='${libsubdir}/include/g++'
else
- gxx_include_dir='${prefix}/include/g++'
+ topsrcdir=${srcdir}/.. . ${srcdir}/../config.if
+changequote(<<, >>)dnl
+ gcc_gxx_include_dir="\$(libsubdir)/\$(unlibsubdir)/..\`echo \$(exec_prefix) | sed -e 's|^\$(prefix)||' -e 's|/[^/]*|/..|g'\`/include/g++"-${libstdcxx_interface}
+changequote([, ])dnl
fi
fi
@@ -98,30 +183,60 @@ no) ;;
*) AC_MSG_ERROR(bad value ${enableval} given for checking option) ;;
esac])
-# Enable use of cpplib for C.
+AC_ARG_ENABLE(cpp,
+[ --disable-cpp don't provide a user-visible C preprocessor.],
+[], [enable_cpp=yes])
+
+AC_ARG_WITH(cpp_install_dir,
+[ --with-cpp-install-dir=DIR
+ install the user visible C preprocessor in DIR
+ (relative to PREFIX) as well as PREFIX/bin.],
+[if test x$withval = xyes; then
+ AC_MSG_ERROR([option --with-cpp-install-dir requires an argument])
+elif test x$withval != xno; then
+ cpp_install_dir=$withval
+fi])
+
+# Use cpplib+cppmain for the preprocessor, but don't link it with the compiler.
cpp_main=cccp
+AC_ARG_ENABLE(cpplib,
+[ --enable-cpplib use cpplib for the C preprocessor.],
+if test x$enable_cpplib != xno; then
+ cpp_main=cppmain
+fi)
+
+# Link cpplib into the compiler proper, for C/C++/ObjC.
AC_ARG_ENABLE(c-cpplib,
-[ --enable-c-cpplib Use cpplib for C.],
-if [[[ x$enable_c_cpplib != xno ]]]; then
- extra_c_objs="${extra_c_objs} cpplib.o cppexp.o cpphash.o cpperror.o"
- extra_c_objs="${extra_c_objs} prefix.o"
- extra_cxx_objs="${extra_cxx_objs} ../cpplib.o ../cppexp.o ../cpphash.o ../cpperror.o ../prefix.o"
- extra_c_flags=-DUSE_CPPLIB=1
+[ --enable-c-cpplib link cpplib directly into C and C++ compilers
+ (EXPERIMENTAL) (implies --enable-cpplib).],
+if test x$enable_c_cpplib != xno; then
+ extra_c_objs="${extra_c_objs} libcpp.a"
+ extra_cxx_objs="${extra_cxx_objs} ../libcpp.a"
+ extra_c_flags="${extra_c_flags} -DUSE_CPPLIB=1"
cpp_main=cppmain
fi)
-
+
+# Enable Multibyte Characters for C/C++
+AC_ARG_ENABLE(c-mbchar,
+[ --enable-c-mbchar enable multibyte characters for C and C++.],
+if test x$enable_c_mbchar != xno; then
+ extra_c_flags=-DMULTIBYTE_CHARS=1
+fi)
+
+# Disable fast fixincludes
+AC_ARG_ENABLE(fast-fixincludes,
+[ --disable-fast-fixincludes
+ Disable the new fast fixincludes.
+ Run the old fixincludes script unconditionally],
+if test x$enable_fast_fixincludes = xno ; then
+ cp $srcdir/fixincludes ./fixinc.sh
+fi)
+
# Enable Haifa scheduler.
AC_ARG_ENABLE(haifa,
-[ --enable-haifa Use the experimental scheduler.
- --disable-haifa Don't use the experimental scheduler for the
+[ --enable-haifa use the experimental scheduler.
+ --disable-haifa don't use the experimental scheduler for the
targets which normally enable it.])
-# Fast fixincludes
-#
-# This is a work in progress...
-AC_ARG_WITH(fast-fixincludes,
-[ --with-fast-fixincludes Use a faster fixinclude program. Experimental],
-fast_fixinc="$with_fast_fixincludes",
-fast_fixinc=no)
# Enable threads
# Pass with no value to take the default
@@ -129,7 +244,7 @@ fast_fixinc=no)
AC_ARG_ENABLE(threads,
[ --enable-threads enable thread usage for target GCC.
--enable-threads=LIB use LIB thread package for target GCC.],
-if [[[ x$enable_threads = xno ]]]; then
+if test x$enable_threads = xno; then
enable_threads=''
fi,
enable_threads='')
@@ -155,13 +270,68 @@ case x${enable_threads_flag} in
;;
esac
+AC_ARG_ENABLE(objc-gc,
+[ --enable-objc-gc enable the use of Boehm's garbage collector with
+ the GNU Objective-C runtime.],
+if [[[ x$enable_objc_gc = xno ]]]; then
+ objc_boehm_gc=''
+else
+ objc_boehm_gc=1
+fi,
+objc_boehm_gc='')
+
+AC_ARG_ENABLE(java-gc,
+changequote(<<,>>)dnl
+<< --enable-java-gc=TYPE choose garbage collector [boehm]>>,
+changequote([,])
+ JAVAGC=$enableval,
+ JAVAGC=boehm)
+
+AC_ARG_WITH(dwarf2,
+[ --enable-dwarf2 enable DWARF2 debugging as default.],
+dwarf2="$with_dwarf2",
+dwarf2=no)
+
# Determine the host, build, and target systems
AC_CANONICAL_SYSTEM
# Find the native compiler
AC_PROG_CC
+
+# If the native compiler is GCC, we can enable warnings even in stage1.
+# That's useful for people building cross-compilers, or just running a
+# quick `make'.
+if test "x$GCC" = "xyes"; then
+ stage1_warn_cflags='$(WARN_CFLAGS)'
+else
+ stage1_warn_cflags=""
+fi
+AC_SUBST(stage1_warn_cflags)
+
AC_PROG_MAKE_SET
+AC_MSG_CHECKING([whether a default assembler was specified])
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test x"$gas_flag" = x"no"; then
+ AC_MSG_RESULT([yes ($DEFAULT_ASSEMBLER)])
+ else
+ AC_MSG_RESULT([yes ($DEFAULT_ASSEMBLER - GNU as)])
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING([whether a default linker was specified])
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test x"$gnu_ld_flag" = x"no"; then
+ AC_MSG_RESULT([yes ($DEFAULT_LINKER)])
+ else
+ AC_MSG_RESULT([yes ($DEFAULT_LINKER - GNU ld)])
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
+
# Find some useful tools
AC_PROG_AWK
AC_PROG_LEX
@@ -174,12 +344,17 @@ EGCS_PROG_INSTALL
AC_HEADER_STDC
AC_HEADER_TIME
-AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h fcntl.h unistd.h stab.h sys/file.h sys/time.h sys/resource.h sys/param.h sys/times.h wait.h sys/wait.h)
+GCC_HEADER_STRING
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h fcntl.h unistd.h stab.h sys/file.h sys/time.h sys/resource.h sys/param.h sys/times.h sys/stat.h direct.h)
# Check for thread headers.
AC_CHECK_HEADER(thread.h, [have_thread_h=yes], [have_thread_h=])
AC_CHECK_HEADER(pthread.h, [have_pthread_h=yes], [have_pthread_h=])
+# See if GNAT has been installed
+AC_CHECK_PROG(gnat, gnatbind, yes, no)
+
# See if the system preprocessor understands the ANSI C preprocessor
# stringification operator.
AC_MSG_CHECKING(whether cpp understands the stringify operator)
@@ -210,13 +385,28 @@ fi
AC_CHECK_FUNCS(strtoul bsearch strerror putenv popen bcopy bzero bcmp \
index rindex strchr strrchr kill getrlimit setrlimit atoll atoq \
- sysconf isascii gettimeofday)
+ sysconf isascii gettimeofday strsignal putc_unlocked fputc_unlocked \
+ fputs_unlocked)
+
+# Make sure wchar_t is available
+#AC_CHECK_TYPE(wchar_t, unsigned int)
GCC_FUNC_VFPRINTF_DOPRNT
GCC_FUNC_PRINTF_PTR
+case "${host}" in
+*-*-uwin*)
+ # Under some versions of uwin, vfork is notoriously buggy and the test
+ # can hang configure; on other versions, vfork exists just as a stub.
+ # FIXME: This should be removed once vfork in uwin's runtime is fixed.
+ ac_cv_func_vfork_works=no
+ ;;
+esac
+AC_FUNC_VFORK
+
GCC_NEED_DECLARATIONS(malloc realloc calloc free bcopy bzero bcmp \
- index rindex getenv atol sbrk abort atof strerror getcwd getwd)
+ index rindex getenv atol sbrk abort atof strerror getcwd getwd \
+ strsignal putc_unlocked fputs_unlocked strstr)
GCC_NEED_DECLARATIONS(getrlimit setrlimit, [
#include <sys/types.h>
@@ -227,6 +417,9 @@ GCC_NEED_DECLARATIONS(getrlimit setrlimit, [
AC_DECL_SYS_SIGLIST
+# mkdir takes a single argument on some systems.
+GCC_FUNC_MKDIR_TAKES_ONE_ARG
+
# File extensions
manext='.1'
objext='.o'
@@ -242,7 +435,6 @@ host_xm_defines=
host_xmake_file=
host_truncate_target=
host_exeext=
-cpp_install_dir=
# Decode the host machine, then the target machine.
# For the host machine, we save the xm_file variable as host_xm_file;
@@ -266,10 +458,6 @@ for machine in $build $host $target; do
use_collect2=
# Set this to override the default target model.
target_cpu_default=
- # Set this to control which fixincludes program to use.
- if [[ x$fast_fixinc != xyes ]] ; then
- fixincludes=fixincludes
- else fixincludes=fixinc.sh ; fi
# Set this to control how the header file directory is installed.
install_headers_dir=install-headers-tar
# Set this to a non-empty list of args to pass to cpp if the target
@@ -303,7 +491,9 @@ for machine in $build $host $target; do
c*-convex-*)
cpu_type=convex
;;
- i[[34567]]86-*-*)
+changequote(,)dnl
+ i[34567]86-*-*)
+changequote([,])dnl
cpu_type=i386
;;
hppa*-*-*)
@@ -336,11 +526,11 @@ for machine in $build $host $target; do
;;
*-*-openbsd*)
tm_file=${cpu_type}/openbsd.h
- # On OpenBSD systems, the headers are okay
- fixincludes=Makefile.in
tmake_file="t-libc-ok t-openbsd"
# avoid surprises, always provide an xm-openbsd file
xm_file=${cpu_type}/xm-openbsd.h
+ # don't depend on processor x-fragments as well
+ xmake_file=none
if test x$enable_threads = xyes; then
thread_file='posix'
tmake_file="${tmake_file} t-openbsd-thread"
@@ -355,11 +545,11 @@ for machine in $build $host $target; do
rest=`echo $machine | sed -e "s/$cpu_type-//"`
xm_file=${cpu_type}/xm-$rest.h
tm_file=${cpu_type}/$rest.h
- if [[ -f $srcdir/config/${cpu_type}/x-$rest ]] ; \
+ if test -f $srcdir/config/${cpu_type}/x-$rest; \
then xmake_file=${cpu_type}/x-$rest; \
else true; \
fi
- if [[ -f $srcdir/config/${cpu_type}/t-$rest ]] ; \
+ if test -f $srcdir/config/${cpu_type}/t-$rest; \
then tmake_file=${cpu_type}/t-$rest; \
else true; \
fi
@@ -385,9 +575,31 @@ for machine in $build $host $target; do
a29k-*-*) # Default a29k environment.
use_collect2=yes
;;
+ alpha-*-interix)
+ tm_file="${tm_file} alpha/alpha32.h interix.h alpha/alpha-interix.h"
+
+ # GAS + IEEE_CONFORMANT+IEEE (no inexact);
+ #target_cpu_default="MASK_GAS|MASK_IEEE_CONFORMANT|MASK_IEEE"
+
+ # GAS + IEEE_CONFORMANT
+ target_cpu_default="MASK_GAS|MASK_IEEE_CONFORMANT"
+
+ xm_file="alpha/xm-alpha-interix.h xm-interix.h"
+ xmake_file="x-interix alpha/t-pe"
+ tmake_file="alpha/t-interix alpha/t-ieee"
+ if test x$enable_threads = xyes ; then
+ thread_file='posix'
+ fi
+ if test x$stabs = xyes ; then
+ tm_file="${tm_file} dbxcoff.h"
+ fi
+ #prefix='$$INTERIX_ROOT'/usr/contrib
+ #local_prefix='$$INTERIX_ROOT'/usr/contrib
+ ;;
alpha*-*-linux-gnuecoff*)
tm_file="${tm_file} alpha/linux-ecoff.h alpha/linux.h"
target_cpu_default="MASK_GAS"
+ tmake_file="alpha/t-ieee"
gas=no
xmake_file=none
gas=yes gnu_ld=yes
@@ -395,59 +607,58 @@ for machine in $build $host $target; do
alpha*-*-linux-gnulibc1*)
tm_file="${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h"
target_cpu_default="MASK_GAS"
- tmake_file="t-linux t-linux-gnulibc1 alpha/t-linux alpha/t-crtbe"
+ tmake_file="t-linux t-linux-gnulibc1 alpha/t-linux alpha/t-crtbe alpha/t-ieee"
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.wrap
xmake_file=none
gas=yes gnu_ld=yes
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
alpha*-*-linux-gnu*)
tm_file="${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h"
target_cpu_default="MASK_GAS"
- tmake_file="t-linux alpha/t-linux alpha/t-crtbe"
+ tmake_file="t-linux alpha/t-linux alpha/t-crtbe alpha/t-ieee"
extra_parts="crtbegin.o crtend.o"
xmake_file=none
- fixincludes=Makefile.in
gas=yes gnu_ld=yes
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
alpha*-*-netbsd*)
- tm_file="${tm_file} alpha/elf.h alpha/netbsd.h alpha/netbsdl-elf.h"
- xm_file="xm-netbsd.h ${xm_file}"
+ tm_file="${tm_file} alpha/elf.h alpha/netbsd.h alpha/netbsd-elf.h"
target_cpu_default="MASK_GAS"
- tmake_file="alpha/t-crtbe"
+ tmake_file="alpha/t-crtbe alpha/t-ieee"
extra_parts="crtbegin.o crtend.o"
xmake_file=none
- fixincludes=fixinc.wrap
gas=yes gnu_ld=yes
;;
alpha*-*-openbsd*)
# default x-alpha is only appropriate for dec-osf.
target_cpu_default="MASK_GAS"
- xmake_file=none
+ tmake_file="alpha/t-ieee"
;;
alpha*-dec-osf*)
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
- if [[ x$gas != xyes ]]
+ if test x$gas != xyes
then
extra_passes="mips-tfile mips-tdump"
fi
use_collect2=yes
+ tmake_file="alpha/t-ieee"
case $machine in
*-*-osf1*)
tm_file="${tm_file} alpha/osf.h alpha/osf12.h alpha/osf2or3.h"
;;
- *-*-osf[[23]]*)
+changequote(,)dnl
+ *-*-osf[23]*)
+changequote([,])dnl
tm_file="${tm_file} alpha/osf.h alpha/osf2or3.h"
;;
*-*-osf4*)
@@ -458,40 +669,42 @@ for machine in $build $host $target; do
;;
esac
case $machine in
- *-*-osf4.0[[b-z]] | *-*-osf4.[[1-9]]*)
+changequote(,)dnl
+ *-*-osf4.0[b-z] | *-*-osf4.[1-9]*)
+changequote([,])dnl
target_cpu_default=MASK_SUPPORT_ARCH
;;
esac
;;
alpha*-*-vxworks*)
tm_file="${tm_file} dbx.h alpha/vxworks.h"
+ tmake_file="alpha/t-ieee"
if [ x$gas != xyes ]
then
extra_passes="mips-tfile mips-tdump"
fi
use_collect2=yes
+ thread_file='vxworks'
;;
alpha*-*-winnt*)
- tm_file="${tm_file} alpha/win-nt.h"
+ tm_file="${tm_file} alpha/alpha32.h alpha/win-nt.h winnt/win-nt.h"
xm_file="${xm_file} config/winnt/xm-winnt.h alpha/xm-winnt.h"
- tmake_file=t-libc-ok
+ tmake_file="t-libc-ok alpha/t-ieee"
xmake_file=winnt/x-winnt
extra_host_objs=oldnames.o
extra_gcc_objs="spawnv.o oldnames.o"
- fixincludes=fixinc.winnt
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
extra_programs=ld.exe
fi
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
;;
alpha*-dec-vms*)
tm_file=alpha/vms.h
xm_file="${xm_file} alpha/xm-vms.h"
- tmake_file=alpha/t-vms
- fixincludes=Makefile.in
+ tmake_file="alpha/t-vms alpha/t-ieee"
;;
arc-*-elf*)
extra_parts="crtinit.o crtfini.o"
@@ -500,12 +713,19 @@ for machine in $build $host $target; do
tm_file=arm/coff.h
tmake_file=arm/t-bare
;;
- arm-*-riscix1.[[01]]*) # Acorn RISC machine (early versions)
+ arm-*-vxworks*)
+ tm_file=arm/vxarm.h
+ tmake_file=arm/t-bare
+ thread_file='vxworks'
+ ;;
+changequote(,)dnl
+ arm-*-riscix1.[01]*) # Acorn RISC machine (early versions)
+changequote([,])dnl
tm_file=arm/riscix1-1.h
use_collect2=yes
;;
arm-*-riscix*) # Acorn RISC machine
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=arm/rix-gas.h
else
@@ -518,57 +738,84 @@ for machine in $build $host $target; do
arm-semi-aout | armel-semi-aout)
tm_file=arm/semi.h
tmake_file=arm/t-semi
- fixincludes=Makefile.in # There is nothing to fix
;;
arm-semi-aof | armel-semi-aof)
tm_file=arm/semiaof.h
tmake_file=arm/t-semiaof
- fixincludes=Makefile.in # There is nothing to fix
;;
arm*-*-netbsd*)
tm_file=arm/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
+ xm_file="arm/xm-netbsd.h ${xm_file}"
tmake_file="t-netbsd arm/t-netbsd"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
+ use_collect2=yes
;;
- arm-*-linux-gnuaout*) # ARM GNU/Linux
+ arm*-*-linux-gnuaout*) # ARM GNU/Linux with a.out
cpu_type=arm
xmake_file=x-linux
- tm_file=arm/linux-gas.h
+ tm_file=arm/linux-aout.h
tmake_file=arm/t-linux
- fixincludes=Makefile.in
gnu_ld=yes
;;
- arm-*-aout)
+ arm*-*-linux-gnu*) # ARM GNU/Linux with ELF
+ xm_file=arm/xm-linux.h
+ xmake_file=x-linux
+ case $machine in
+ armv2*-*-*)
+ tm_file=arm/linux-elf26.h
+ ;;
+ *)
+ tm_file=arm/linux-elf.h
+ ;;
+ esac
+ tmake_file="t-linux arm/t-linux"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gnu_ld=yes
+ case x${enable_threads} in
+ x | xyes | xpthreads | xposix)
+ thread_file='posix'
+ ;;
+ esac
+ ;;
+ arm*-*-aout)
tm_file=arm/aout.h
tmake_file=arm/t-bare
;;
+ arm*-*-ecos-elf)
+ tm_file=arm/ecos-elf.h
+ tmake_file=arm/t-elf
+ ;;
+ arm*-*-elf)
+ tm_file=arm/unknown-elf.h
+ tmake_file=arm/t-arm-elf
+ ;;
+ arm*-*-oabi)
+ tm_file=arm/unknown-elf-oabi.h
+ tmake_file=arm/t-arm-elf
+ ;;
c1-convex-*) # Convex C1
target_cpu_default=1
use_collect2=yes
- fixincludes=Makefile.in
;;
c2-convex-*) # Convex C2
target_cpu_default=2
use_collect2=yes
- fixincludes=Makefile.in
;;
c32-convex-*)
target_cpu_default=4
use_collect2=yes
- fixincludes=Makefile.in
;;
c34-convex-*)
target_cpu_default=8
use_collect2=yes
- fixincludes=Makefile.in
;;
c38-convex-*)
target_cpu_default=16
use_collect2=yes
- fixincludes=Makefile.in
;;
+ c4x-*)
+ cpu_type=c4x
+ tmake_file=c4x/t-c4x
+ ;;
clipper-intergraph-clix*)
tm_file="${tm_file} svr3.h clipper/clix.h"
xm_file=clipper/xm-clix.h
@@ -589,8 +836,8 @@ for machine in $build $host $target; do
float_format=i32
;;
hppa*-*-openbsd*)
- target_cpu_default="MASK_SNAKE"
- tmake_file=pa/t-openbsd
+ target_cpu_default="MASK_PA_11"
+ tmake_file=pa/t-openbsd
;;
hppa1.1-*-pro*)
tm_file="pa/pa-pro.h ${tm_file} pa/pa-pro-end.h libgloss.h"
@@ -598,10 +845,9 @@ for machine in $build $host $target; do
tmake_file=pa/t-pro
;;
hppa1.1-*-osf*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-osf.h"
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.1-*-rtems*)
tm_file="pa/pa-pro.h ${tm_file} pa/pa-pro-end.h libgloss.h pa/rtems.h"
@@ -611,33 +857,32 @@ for machine in $build $host $target; do
hppa1.0-*-osf*)
tm_file="${tm_file} pa/pa-osf.h"
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.1-*-bsd*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.0-*-bsd*)
use_collect2=yes
- fixincludes=Makefile.in
;;
hppa1.0-*-hpux7*)
tm_file="pa/pa-oldas.h ${tm_file} pa/pa-hpux7.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/gas.h"
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.0-*-hpux8.0[[0-2]]*)
+changequote(,)dnl
+ hppa1.0-*-hpux8.0[0-2]*)
+changequote([,])dnl
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
else
@@ -646,12 +891,14 @@ for machine in $build $host $target; do
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.1-*-hpux8.0[[0-2]]*)
- target_cpu_default=1
+changequote(,)dnl
+ hppa1.1-*-hpux8.0[0-2]*)
+changequote([,])dnl
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
else
@@ -661,11 +908,11 @@ for machine in $build $host $target; do
use_collect2=yes
;;
hppa1.1-*-hpux8*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -676,27 +923,27 @@ for machine in $build $host $target; do
tm_file="${tm_file} pa/pa-hpux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.1-*-hpux10*)
- target_cpu_default=1
+ hppa1.1-*-hpux10* | hppa2*-*-hpux10*)
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux10.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
tmake_file=pa/t-pa
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
- if [[ x$enable_threads = x ]]; then
+ if test x$enable_threads = x; then
enable_threads=$have_pthread_h
fi
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='dce'
tmake_file="${tmake_file} pa/t-dce-thr"
fi
@@ -708,26 +955,26 @@ for machine in $build $host $target; do
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
tmake_file=pa/t-pa
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
- if [[ x$enable_threads = x ]]; then
+ if test x$enable_threads = x; then
enable_threads=$have_pthread_h
fi
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='dce'
tmake_file="${tmake_file} pa/t-dce-thr"
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.1-*-hpux*)
- target_cpu_default=1
+ hppa1.1-*-hpux* | hppa2*-*-hpux*)
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux9.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -738,19 +985,19 @@ for machine in $build $host $target; do
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hpux9.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
;;
- hppa1.1-*-hiux*)
- target_cpu_default=1
+ hppa1.1-*-hiux* | hppa2*-*-hiux*)
+ target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hiux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -761,7 +1008,7 @@ for machine in $build $host $target; do
tm_file="${tm_file} pa/pa-hpux.h pa/pa-hiux.h"
xm_file=pa/xm-pahpux.h
xmake_file=pa/x-pa-hpux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} pa/pa-gas.h"
fi
@@ -769,14 +1016,15 @@ for machine in $build $host $target; do
use_collect2=yes
;;
hppa*-*-lites*)
- target_cpu_default=1
+ target_cpu_default="MASK_PA_11"
use_collect2=yes
- fixincludes=Makefile.in
;;
i370-*-mvs*)
;;
- i[[34567]]86-ibm-aix*) # IBM PS/2 running AIX
- if [[ x$gas = xyes ]]
+changequote(,)dnl
+ i[34567]86-ibm-aix*) # IBM PS/2 running AIX
+changequote([,])dnl
+ if test x$gas = xyes
then
tm_file=i386/aix386.h
extra_parts="crtbegin.o crtend.o"
@@ -789,11 +1037,13 @@ for machine in $build $host $target; do
xm_defines=USG
xmake_file=i386/x-aix
;;
- i[[34567]]86-ncr-sysv4*) # NCR 3000 - ix86 running system V.4
+changequote(,)dnl
+ i[34567]86-ncr-sysv4*) # NCR 3000 - ix86 running system V.4
+changequote([,])dnl
xm_file="xm-siglist.h xm-alloca.h ${xm_file}"
xm_defines="USG POSIX SMALL_ARG_MAX"
xmake_file=i386/x-ncr3000
- if [[ x$stabs = xyes -a x$gas = xyes ]]
+ if test x$stabs = xyes -a x$gas = xyes
then
tm_file=i386/sysv4gdb.h
else
@@ -802,51 +1052,59 @@ for machine in $build $host $target; do
extra_parts="crtbegin.o crtend.o"
tmake_file=i386/t-crtpic
;;
- i[[34567]]86-next-*)
+changequote(,)dnl
+ i[34567]86-next-*)
+changequote([,])dnl
tm_file=i386/next.h
xm_file=i386/xm-next.h
tmake_file=i386/t-next
xmake_file=i386/x-next
extra_objs=nextstep.o
- if [[ x$enable_threads = xyes ]]; then
+ extra_parts="crtbegin.o crtend.o"
+ if test x$enable_threads = xyes; then
thread_file='mach'
fi
;;
- i[[34567]]86-sequent-bsd*) # 80386 from Sequent
+changequote(,)dnl
+ i[34567]86-sequent-bsd*) # 80386 from Sequent
+changequote([,])dnl
use_collect2=yes
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=i386/seq-gas.h
else
tm_file=i386/sequent.h
fi
;;
- i[[34567]]86-sequent-ptx1*)
+changequote(,)dnl
+ i[34567]86-sequent-ptx1*)
+changequote([,])dnl
xm_defines="USG SVR3"
xmake_file=i386/x-sysv3
tm_file=i386/seq-sysv3.h
tmake_file=i386/t-crtstuff
- fixincludes=fixinc.ptx
extra_parts="crtbegin.o crtend.o"
install_headers_dir=install-headers-cpio
;;
- i[[34567]]86-sequent-ptx2* | i[[34567]]86-sequent-sysv3*)
+changequote(,)dnl
+ i[34567]86-sequent-ptx2* | i[34567]86-sequent-sysv3*)
+changequote([,])dnl
xm_defines="USG SVR3"
xmake_file=i386/x-sysv3
tm_file=i386/seq2-sysv3.h
tmake_file=i386/t-crtstuff
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.ptx
install_headers_dir=install-headers-cpio
;;
- i[[34567]]86-sequent-ptx4* | i[[34567]]86-sequent-sysv4*)
+changequote(,)dnl
+ i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*)
+changequote([,])dnl
xm_file="xm-siglist.h xm-alloca.h ${xm_file}"
xm_defines="USG POSIX SMALL_ARG_MAX"
xmake_file=x-svr4
tm_file=i386/ptx4-i.h
tmake_file=t-svr4
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.ptx
install_headers_dir=install-headers-cpio
;;
i386-sun-sunos*) # Sun i386 roadrunner
@@ -854,69 +1112,84 @@ for machine in $build $host $target; do
tm_file=i386/sun.h
use_collect2=yes
;;
- i[[34567]]86-wrs-vxworks*)
+changequote(,)dnl
+ i[34567]86-wrs-vxworks*)
+changequote([,])dnl
tm_file=i386/vxi386.h
tmake_file=i386/t-i386bare
+ thread_file='vxworks'
;;
- i[[34567]]86-*-aout*)
+changequote(,)dnl
+ i[34567]86-*-aout*)
+changequote([,])dnl
tm_file=i386/i386-aout.h
tmake_file=i386/t-i386bare
;;
- i[[34567]]86-*-bsdi* | i[[34567]]86-*-bsd386*)
+changequote(,)dnl
+ i[34567]86-*-bsdi* | i[34567]86-*-bsd386*)
+changequote([,])dnl
tm_file=i386/bsd386.h
# tmake_file=t-libc-ok
;;
- i[[34567]]86-*-bsd*)
+changequote(,)dnl
+ i[34567]86-*-bsd*)
+changequote([,])dnl
tm_file=i386/386bsd.h
# tmake_file=t-libc-ok
# Next line turned off because both 386BSD and BSD/386 use GNU ld.
# use_collect2=yes
;;
- i[[34567]]86-*-freebsdelf*)
- tm_file="i386/i386.h i386/att.h linux.h i386/freebsd-elf.h i386/perform.h"
- # On FreeBSD, the headers are already ok, except for math.h.
- fixincludes=fixinc.wrap
+changequote(,)dnl
+ i[34567]86-*-freebsdelf*)
+changequote([,])dnl
+ tm_file="i386/i386.h i386/att.h svr4.h i386/freebsd-elf.h i386/perform.h"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- tmake_file=i386/t-freebsd
+ tmake_file=t-freebsd
gas=yes
gnu_ld=yes
stabs=yes
;;
- i[[34567]]86-*-freebsd*)
+changequote(,)dnl
+ i[34567]86-*-freebsd*)
+changequote([,])dnl
tm_file=i386/freebsd.h
- # On FreeBSD, the headers are already ok, except for math.h.
- fixincludes=fixinc.wrap
- tmake_file=i386/t-freebsd
+ tmake_file=t-freebsd
;;
- i[[34567]]86-*-netbsd*)
+changequote(,)dnl
+ i[34567]86-*-netbsd*)
+changequote([,])dnl
tm_file=i386/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
+ use_collect2=yes
;;
- i[[34567]]86-*-openbsd*)
- # Remove when the math emulator is fixed
- target_cpu_default="MASK_NO_FANCY_MATH_387"
- # we need collect2 until our bug is fixed...
- use_collect2=yes
- ;;
- i[[34567]]86-*-coff*)
+changequote(,)dnl
+ i[34567]86-*-openbsd*)
+changequote([,])dnl
+ # we need collect2 until our bug is fixed...
+ use_collect2=yes
+ ;;
+changequote(,)dnl
+ i[34567]86-*-coff*)
+changequote([,])dnl
tm_file=i386/i386-coff.h
tmake_file=i386/t-i386bare
;;
- i[[34567]]86-*-isc*) # 80386 running ISC system
+changequote(,)dnl
+ i[34567]86-*-isc*) # 80386 running ISC system
+changequote([,])dnl
xm_file="${xm_file} i386/xm-isc.h"
xm_defines="USG SVR3"
case $machine in
- i[[34567]]86-*-isc[[34]]*)
+changequote(,)dnl
+ i[34567]86-*-isc[34]*)
+changequote([,])dnl
xmake_file=i386/x-isc3
;;
*)
xmake_file=i386/x-isc
;;
esac
- if [[ x$gas = xyes -a x$stabs = xyes ]]
+ if test x$gas = xyes -a x$stabs = xyes
then
tm_file=i386/iscdbx.h
tmake_file=i386/t-svr3dbx
@@ -928,77 +1201,91 @@ for machine in $build $host $target; do
fi
install_headers_dir=install-headers-cpio
;;
- i[[34567]]86-*-linux-gnuoldld*) # Intel 80386's running GNU/Linux
- # with a.out format using
+changequote(,)dnl
+ i[34567]86-*-linux-gnuoldld*) # Intel 80386's running GNU/Linux
+changequote([,])dnl # with a.out format using
# pre BFD linkers
xmake_file=x-linux-aout
tmake_file="t-linux-aout i386/t-crtstuff"
tm_file=i386/linux-oldld.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
;;
- i[[34567]]86-*-linux-gnuaout*) # Intel 80386's running GNU/Linux
- # with a.out format
+changequote(,)dnl
+ i[34567]86-*-linux-gnuaout*) # Intel 80386's running GNU/Linux
+changequote([,])dnl # with a.out format
xmake_file=x-linux-aout
tmake_file="t-linux-aout i386/t-crtstuff"
tm_file=i386/linux-aout.h
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
;;
- i[[34567]]86-*-linux-gnulibc1) # Intel 80386's running GNU/Linux
- # with ELF format using the
+changequote(,)dnl
+ i[34567]86-*-linux-gnulibc1) # Intel 80386's running GNU/Linux
+changequote([,])dnl # with ELF format using the
# GNU/Linux C library 5
xmake_file=x-linux
tm_file=i386/linux.h
tmake_file="t-linux t-linux-gnulibc1 i386/t-crtstuff"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='single'
fi
;;
- i[[34567]]86-*-linux-gnu*) # Intel 80386's running GNU/Linux
- # with ELF format using glibc 2
+changequote(,)dnl
+ i[34567]86-*-linux-gnu*) # Intel 80386's running GNU/Linux
+changequote([,])dnl # with ELF format using glibc 2
# aka GNU/Linux C library 6
xmake_file=x-linux
tm_file=i386/linux.h
tmake_file="t-linux i386/t-crtstuff"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
float_format=i386
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
- i[[34567]]86-*-gnu*)
+changequote(,)dnl
+ i[34567]86-*-gnu*)
float_format=i386
+changequote([,])dnl
;;
- i[[34567]]86-go32-msdos | i[[34567]]86-*-go32*)
- xm_file=i386/xm-go32.h
- tm_file=i386/go32.h
- tmake_file=i386/t-go32
+changequote(,)dnl
+ i[34567]86-go32-msdos | i[34567]86-*-go32*)
+changequote([,])dnl
+ echo "GO32/DJGPP V1.X is no longer supported. Use *-pc-msdosdjgpp for DJGPP V2.X instead."
+ exit 1
;;
- i[[34567]]86-pc-msdosdjgpp*)
- xm_file=i386/xm-go32.h
- tm_file=i386/go32.h
- tmake_file=i386/t-go32
+changequote(,)dnl
+ i[34567]86-pc-msdosdjgpp*)
+changequote([,])dnl
+ xm_file=i386/xm-djgpp.h
+ tm_file=i386/djgpp.h
+ tmake_file=i386/t-djgpp
+ xmake_file=i386/x-djgpp
gnu_ld=yes
gas=yes
+ exeext=.exe
+ case $host in *pc-msdosdjgpp*)
+ target_alias=djgpp
+ ;;
+ esac
;;
- i[[34567]]86-moss-msdos* | i[[34567]]86-*-moss*)
+changequote(,)dnl
+ i[34567]86-moss-msdos* | i[34567]86-*-moss*)
+changequote([,])dnl
tm_file=i386/moss.h
tmake_file=t-libc-ok
- fixincludes=Makefile.in
gnu_ld=yes
gas=yes
;;
- i[[34567]]86-*-lynxos*)
- if [[ x$gas = xyes ]]
+changequote(,)dnl
+ i[34567]86-*-lynxos*)
+changequote([,])dnl
+ if test x$gas = xyes
then
tm_file=i386/lynx.h
else
@@ -1008,13 +1295,17 @@ for machine in $build $host $target; do
tmake_file=i386/t-i386bare
xmake_file=x-lynx
;;
- i[[34567]]86-*-mach*)
+changequote(,)dnl
+ i[34567]86-*-mach*)
+changequote([,])dnl
tm_file=i386/mach.h
# tmake_file=t-libc-ok
use_collect2=yes
;;
- i[[34567]]86-*-osfrose*) # 386 using OSF/rose
- if [[ x$elf = xyes ]]
+changequote(,)dnl
+ i[34567]86-*-osfrose*) # 386 using OSF/rose
+changequote([,])dnl
+ if test x$elf = xyes
then
tm_file=i386/osfelf.h
use_collect2=
@@ -1027,30 +1318,37 @@ for machine in $build $host $target; do
tmake_file=i386/t-osf
extra_objs=halfpic.o
;;
- i[[34567]]86-go32-rtems*)
+changequote(,)dnl
+ i[34567]86-go32-rtems*)
+changequote([,])dnl
cpu_type=i386
xm_file=i386/xm-go32.h
tm_file=i386/go32-rtems.h
tmake_file="i386/t-go32 t-rtems"
;;
- i[[34567]]86-*-rtemself*)
+changequote(,)dnl
+ i[34567]86-*-rtemself*)
+changequote([,])dnl
cpu_type=i386
tm_file=i386/rtemself.h
tmake_file="i386/t-i386bare t-rtems"
;;
- i[[34567]]86-*-rtems*)
+changequote(,)dnl
+ i[34567]86-*-rtems*)
+changequote([,])dnl
cpu_type=i386
tm_file=i386/rtems.h
tmake_file="i386/t-i386bare t-rtems"
;;
- i[[34567]]86-*-sco3.2v5*) # 80386 running SCO Open Server 5
+changequote(,)dnl
+ i[34567]86-*-sco3.2v5*) # 80386 running SCO Open Server 5
+changequote([,])dnl
xm_file="xm-siglist.h xm-alloca.h ${xm_file} i386/xm-sco5.h"
xm_defines="USG SVR3"
xmake_file=i386/x-sco5
- fixincludes=fixinc.sco
install_headers_dir=install-headers-cpio
tm_file=i386/sco5.h
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="i386/sco5gas.h ${tm_file}"
tmake_file=i386/t-sco5gas
@@ -1059,13 +1357,14 @@ for machine in $build $host $target; do
fi
extra_parts="crti.o crtbegin.o crtend.o crtbeginS.o crtendS.o"
;;
- i[[34567]]86-*-sco3.2v4*) # 80386 running SCO 3.2v4 system
+changequote(,)dnl
+ i[34567]86-*-sco3.2v4*) # 80386 running SCO 3.2v4 system
+changequote([,])dnl
xm_file="${xm_file} i386/xm-sco.h"
xm_defines="USG SVR3 BROKEN_LDEXP SMALL_ARG_MAX NO_SYS_SIGLIST"
xmake_file=i386/x-sco4
- fixincludes=fixinc.sco
install_headers_dir=install-headers-cpio
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file=i386/sco4dbx.h
tmake_file=i386/t-svr3dbx
@@ -1077,11 +1376,13 @@ for machine in $build $host $target; do
fi
truncate_target=yes
;;
- i[[34567]]86-*-sco*) # 80386 running SCO system
+changequote(,)dnl
+ i[34567]86-*-sco*) # 80386 running SCO system
+changequote([,])dnl
xm_file=i386/xm-sco.h
xmake_file=i386/x-sco
install_headers_dir=install-headers-cpio
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file=i386/scodbx.h
tmake_file=i386/t-svr3dbx
@@ -1093,10 +1394,12 @@ for machine in $build $host $target; do
fi
truncate_target=yes
;;
- i[[34567]]86-*-solaris2*)
+changequote(,)dnl
+ i[34567]86-*-solaris2*)
+changequote([,])dnl
xm_file="xm-siglist.h xm-alloca.h ${xm_file}"
xm_defines="USG POSIX SMALL_ARG_MAX"
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file=i386/sol2dbg.h
else
@@ -1105,34 +1408,34 @@ for machine in $build $host $target; do
tmake_file=i386/t-sol2
extra_parts="crt1.o crti.o crtn.o gcrt1.o gmon.o crtbegin.o crtend.o"
xmake_file=x-svr4
- case $machine in
- *-*-solaris2.[[0-4]])
- fixincludes=fixinc.svr4;;
- *)
- fixincludes=fixinc.wrap;;
- esac
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='solaris'
fi
;;
- i[[34567]]86-*-sysv5*) # Intel x86 on System V Release 5
+changequote(,)dnl
+ i[34567]86-*-sysv5*) # Intel x86 on System V Release 5
+changequote([,])dnl
xm_file="xm-alloca.h xm-siglist.h ${xm_file}"
xm_defines="USG POSIX"
- tm_file=i386/sysv4.h
- if [[ x$stabs = xyes ]]
+ tm_file=i386/sysv5.h
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
tmake_file=i386/t-crtpic
xmake_file=x-svr4
extra_parts="crtbegin.o crtend.o"
- fixincludes=fixinc.svr4
+ if test x$enable_threads = xyes; then
+ thread_file='posix'
+ fi
;;
- i[[34567]]86-*-sysv4*) # Intel 80386's running system V.4
+changequote(,)dnl
+ i[34567]86-*-sysv4*) # Intel 80386's running system V.4
+changequote([,])dnl
xm_file="xm-siglist.h xm-alloca.h ${xm_file}"
xm_defines="USG POSIX SMALL_ARG_MAX"
tm_file=i386/sysv4.h
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -1140,12 +1443,24 @@ for machine in $build $host $target; do
xmake_file=x-svr4
extra_parts="crtbegin.o crtend.o"
;;
- i[[34567]]86-*-osf1*) # Intel 80386's running OSF/1 1.3+
+changequote(,)dnl
+ i[34567]86-*-udk*) # Intel x86 on SCO UW/OSR5 Dev Kit
+changequote([,])dnl
+ xm_file="xm-alloca.h xm-siglist.h ${xm_file}"
+ xm_defines="USG POSIX"
+ tm_file=i386/udk.h
+ tmake_file="i386/t-crtpic i386/t-udk"
+ xmake_file=x-svr4
+ extra_parts="crtbegin.o crtend.o"
+ install_headers_dir=install-headers-cpio
+ ;;
+changequote(,)dnl
+ i[34567]86-*-osf1*) # Intel 80386's running OSF/1 1.3+
+changequote([,])dnl
cpu_type=i386
xm_file="${xm_file} xm-svr4.h i386/xm-sysv4.h i386/xm-osf1elf.h"
xm_defines="USE_C_ALLOCA SMALL_ARG_MAX"
- fixincludes=Makefile.in #Don't do it on OSF/1
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file=i386/osf1elfgdb.h
else
@@ -1155,12 +1470,14 @@ for machine in $build $host $target; do
xmake_file=i386/x-osf1elf
extra_parts="crti.o crtn.o crtbegin.o crtend.o"
;;
- i[[34567]]86-*-sysv*) # Intel 80386's running system V
+changequote(,)dnl
+ i[34567]86-*-sysv*) # Intel 80386's running system V
+changequote([,])dnl
xm_defines="USG SVR3"
xmake_file=i386/x-sysv3
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file=i386/svr3dbx.h
tmake_file=i386/t-svr3dbx
@@ -1182,38 +1499,85 @@ for machine in $build $host $target; do
tmake_file=i386/t-vsta
xmake_file=i386/x-vsta
;;
- i[[34567]]86-*-pe | i[[34567]]86-*-cygwin32)
- xm_file="${xm_file} i386/xm-cygwin32.h"
- tmake_file=i386/t-cygwin32
- tm_file=i386/cygwin32.h
- xmake_file=i386/x-cygwin32
+changequote(,)dnl
+ i[34567]86-*-win32)
+changequote([,])dnl
+ xm_file="${xm_file} i386/xm-cygwin.h"
+ tmake_file=i386/t-cygwin
+ tm_file=i386/win32.h
+ xmake_file=i386/x-cygwin
+ extra_objs=winnt.o
+ if test x$enable_threads = xyes; then
+ thread_file='win32'
+ fi
+ exeext=.exe
+ ;;
+changequote(,)dnl
+ i[34567]86-*-pe | i[34567]86-*-cygwin*)
+changequote([,])dnl
+ xm_file="${xm_file} i386/xm-cygwin.h"
+ tmake_file=i386/t-cygwin
+ tm_file=i386/cygwin.h
+ xmake_file=i386/x-cygwin
extra_objs=winnt.o
- fixincludes=Makefile.in
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
exeext=.exe
;;
- i[[34567]]86-*-mingw32*)
+changequote(,)dnl
+ i[34567]86-*-mingw32*)
+changequote([,])dnl
tm_file=i386/mingw32.h
xm_file="${xm_file} i386/xm-mingw32.h"
- tmake_file="i386/t-cygwin32 i386/t-mingw32"
+ tmake_file="i386/t-cygwin i386/t-mingw32"
extra_objs=winnt.o
- xmake_file=i386/x-cygwin32
- fixincludes=Makefile.in
- if [[ x$enable_threads = xyes ]]; then
+ xmake_file=i386/x-cygwin
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
exeext=.exe
case $machine in
*mingw32msv*)
;;
- *mingw32crt* | *mingw32*)
+ *minwg32crt* | *mingw32*)
tm_file="${tm_file} i386/crtdll.h"
;;
esac
;;
- i[[34567]]86-*-winnt3*)
+changequote(,)dnl
+ i[34567]86-*-uwin*)
+changequote([,])dnl
+ tm_file=i386/uwin.h
+ xm_file="${xm_file} i386/xm-uwin.h"
+ xm_defines="USG NO_STAB_H NO_SYS_SIGLIST"
+ tmake_file="i386/t-cygwin i386/t-uwin"
+ extra_objs=winnt.o
+ xmake_file=i386/x-cygwin
+ if test x$enable_threads = xyes; then
+ thread_file='win32'
+ fi
+ exeext=.exe
+ ;;
+changequote(,)dnl
+ i[34567]86-*-interix*)
+changequote([,])dnl
+ tm_file="i386/i386-interix.h interix.h"
+ xm_file="i386/xm-i386-interix.h xm-interix.h"
+ xm_defines="USG NO_SYS_SIGLIST"
+ tmake_file="i386/t-interix"
+ extra_objs=interix.o
+ xmake_file=x-interix
+ if test x$enable_threads = xyes ; then
+ thread_file='posix'
+ fi
+ if test x$stabs = xyes ; then
+ tm_file="${tm_file} dbxcoff.h"
+ fi
+ ;;
+changequote(,)dnl
+ i[34567]86-*-winnt3*)
+changequote([,])dnl
tm_file=i386/win-nt.h
out_file=i386/i386.c
xm_file="xm-winnt.h ${xm_file}"
@@ -1221,23 +1585,23 @@ for machine in $build $host $target; do
tmake_file=i386/t-winnt
extra_host_objs="winnt.o oldnames.o"
extra_gcc_objs="spawnv.o oldnames.o"
- fixincludes=fixinc.winnt
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
extra_programs=ld.exe
fi
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
;;
- i[[34567]]86-dg-dgux*)
+changequote(,)dnl
+ i[34567]86-dg-dgux*)
+changequote([,])dnl
xm_file="xm-alloca.h xm-siglist.h ${xm_file}"
xm_defines="USG POSIX"
out_file=i386/dgux.c
tm_file=i386/dgux.h
tmake_file=i386/t-dgux
xmake_file=i386/x-dgux
- fixincludes=fixinc.dgux
install_headers_dir=install-headers-cpio
;;
i860-alliant-*) # Alliant FX/2800
@@ -1249,7 +1613,7 @@ for machine in $build $host $target; do
;;
i860-*-bsd*)
tm_file="${tm_file} i860/bsd.h"
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="${tm_file} i860/bsd-gas.h"
fi
@@ -1327,7 +1691,7 @@ for machine in $build $host $target; do
m68000-hp-hpux*) # HP 9000 series 300
xm_file="xm_alloca.h ${xm_file}"
xm_defines="USG NO_SYS_SIGLIST"
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
xmake_file=m68k/x-hp320g
tm_file=m68k/hp310g.h
@@ -1352,7 +1716,7 @@ for machine in $build $host $target; do
m68000-att-sysv*)
xm_file="m68k/xm-3b1.h ${xm_file}"
xm_defines=USG
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=m68k/3b1g.h
else
@@ -1368,13 +1732,13 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
extra_parts="crt1.o mcrt1.o maccrt1.o crt2.o crtn.o"
tm_file=
- if [[ "$gnu_ld" = yes ]]
+ if test "$gnu_ld" = yes
then
tm_file="${tm_file} m68k/auxgld.h"
else
tm_file="${tm_file} m68k/auxld.h"
fi
- if [[ "$gas" = yes ]]
+ if test "$gas" = yes
then
tm_file="${tm_file} m68k/auxgas.h"
else
@@ -1391,7 +1755,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-altos-sysv*) # Altos 3068
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=m68k/altos3068.h
xm_defines=USG
@@ -1402,9 +1766,9 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
;;
m68k-bull-sysv*) # Bull DPX/2
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file=m68k/dpx2cdbx.h
else
@@ -1432,10 +1796,10 @@ for machine in $build $host $target; do
tm_file=m68k/mot3300.h
xm_file="xm-alloca.h m68k/xm-mot3300.h ${xm_file}"
xm_defines=NO_SYS_SIGLIST
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
xmake_file=m68k/x-mot3300-gas
- if [[ x$gnu_ld = xyes ]]
+ if test x$gnu_ld = xyes
then
tmake_file=m68k/t-mot3300-gald
else
@@ -1444,7 +1808,7 @@ for machine in $build $host $target; do
fi
else
xmake_file=m68k/x-mot3300
- if [[ x$gnu_ld = xyes ]]
+ if test x$gnu_ld = xyes
then
tmake_file=m68k/t-mot3300-gld
else
@@ -1504,7 +1868,6 @@ for machine in $build $host $target; do
;;
m68k-hp-bsd4.4*) # HP 9000/3xx running 4.4bsd
tm_file=m68k/hp3bsd44.h
- xmake_file=m68k/x-hp3bsd44
use_collect2=yes
extra_headers=math-68881.h
float_format=m68k
@@ -1516,7 +1879,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-isi-bsd*)
- if [[ x$with_fp = xno ]]
+ if test x$with_fp = xno
then
tm_file=m68k/isi-nfp.h
else
@@ -1529,7 +1892,7 @@ for machine in $build $host $target; do
m68k-hp-hpux7*) # HP 9000 series 300 running HPUX version 7.
xm_file="xm_alloca.h ${xm_file}"
xm_defines="USG NO_SYS_SIGLIST"
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
xmake_file=m68k/x-hp320g
tm_file=m68k/hp320g.h
@@ -1545,7 +1908,7 @@ for machine in $build $host $target; do
m68k-hp-hpux*) # HP 9000 series 300
xm_file="xm_alloca.h ${xm_file}"
xm_defines="USG NO_SYS_SIGLIST"
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
xmake_file=m68k/x-hp320g
tm_file=m68k/hp320g.h
@@ -1565,7 +1928,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-sony-newsos3*)
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=m68k/news3gas.h
else
@@ -1576,7 +1939,7 @@ for machine in $build $host $target; do
float_format=m68k
;;
m68k-sony-bsd* | m68k-sony-newsos*)
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=m68k/newsgas.h
else
@@ -1602,14 +1965,15 @@ for machine in $build $host $target; do
tmake_file=m68k/t-next
xmake_file=m68k/x-next
extra_objs=nextstep.o
+ extra_parts="crtbegin.o crtend.o"
extra_headers=math-68881.h
float_format=m68k
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='mach'
fi
;;
m68k-sun-sunos3*)
- if [[ x$with_fp = xno ]]
+ if test x$with_fp = xno
then
tm_file=m68k/sun3n3.h
else
@@ -1620,7 +1984,7 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
;;
m68k-sun-sunos*) # For SunOS 4 (the default).
- if [[ x$with_fp = xno ]]
+ if test x$with_fp = xno
then
tm_file=m68k/sun3n.h
else
@@ -1649,8 +2013,14 @@ for machine in $build $host $target; do
extra_headers=math-68881.h
float_format=m68k
;;
+ m68020-*-elf* | m68k-*-elf*)
+ tm_file="m68k/m68020-elf.h libgloss.h"
+ xm_file=m68k/xm-m68kv.h
+ tmake_file=m68k/t-m68kelf
+ header_files=math-68881.h
+ ;;
m68k-*-lynxos*)
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=m68k/lynx.h
else
@@ -1664,11 +2034,9 @@ for machine in $build $host $target; do
;;
m68k*-*-netbsd*)
tm_file=m68k/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
float_format=m68k
+ use_collect2=yes
;;
m68k*-*-openbsd*)
float_format=m68k
@@ -1697,7 +2065,6 @@ for machine in $build $host $target; do
xmake_file=x-linux
tm_file=m68k/linux-aout.h
tmake_file="t-linux-aout m68k/t-linux-aout"
- fixincludes=Makefile.in # The headers are ok already.
extra_headers=math-68881.h
float_format=m68k
gnu_ld=yes
@@ -1709,7 +2076,6 @@ for machine in $build $host $target; do
tm_file=m68k/linux.h
tmake_file="t-linux t-linux-gnulibc1 m68k/t-linux"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in # The headers are ok already.
extra_headers=math-68881.h
float_format=m68k
gnu_ld=yes
@@ -1721,11 +2087,10 @@ for machine in $build $host $target; do
tm_file=m68k/linux.h
tmake_file="t-linux m68k/t-linux"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in # The headers are ok already.
extra_headers=math-68881.h
float_format=m68k
gnu_ld=yes
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
@@ -1755,18 +2120,17 @@ for machine in $build $host $target; do
esac
extra_parts="crtbegin.o bcscrtbegin.o crtend.o m88kdgux.ld"
xmake_file=m88k/x-dgux
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=m88k/t-dgux-gas
fi
- fixincludes=fixinc.dgux
;;
m88k-dolphin-sysv3*)
tm_file=m88k/dolph.h
extra_parts="crtbegin.o crtend.o"
xm_file="m88k/xm-sysv3.h ${xm_file}"
xmake_file=m88k/x-dolph
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=m88k/t-m88k-gas
fi
@@ -1776,7 +2140,7 @@ for machine in $build $host $target; do
extra_parts="crtbegin.o crtend.o"
xm_file="m88k/xm-sysv3.h ${xm_file}"
xmake_file=m88k/x-tekXD88
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=m88k/t-m88k-gas
fi
@@ -1791,7 +2155,7 @@ for machine in $build $host $target; do
m88k-*-luna*)
tm_file=m88k/luna.h
extra_parts="crtbegin.o crtend.o"
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=m88k/t-luna-gas
else
@@ -1806,7 +2170,7 @@ for machine in $build $host $target; do
extra_parts="crtbegin.o crtend.o"
xm_file="m88k/xm-sysv3.h ${xm_file}"
xmake_file=m88k/x-sysv3
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=m88k/t-m88k-gas
fi
@@ -1820,38 +2184,36 @@ for machine in $build $host $target; do
mips-sgi-irix6*) # SGI System V.4., IRIX 6
tm_file=mips/iris6.h
xm_file=mips/xm-iris6.h
- fixincludes=fixinc.irix
xmake_file=mips/x-iris6
tmake_file=mips/t-iris6
- if [[ x$enable_threads = xyes ]]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-wrs-vxworks)
- tm_file="mips/elf.h libgloss.h"
+ tm_file="mips/elf.h libgloss.h mips/vxworks.h"
tmake_file=mips/t-ecoff
gas=yes
gnu_ld=yes
extra_parts="crtbegin.o crtend.o"
-# thread_file='vxworks'
+ thread_file='vxworks'
;;
mips-sgi-irix5cross64) # Irix5 host, Irix 6 target, cross64
tm_file="mips/iris6.h mips/cross64.h"
xm_defines=USG
xm_file="mips/xm-iris5.h"
- fixincludes=Makefile.in
xmake_file=mips/x-iris
tmake_file=mips/t-cross64
# See comment in mips/iris[56].h files.
use_collect2=yes
- if [[ x$enable_threads = xyes ]]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sni-sysv4)
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file=mips/iris5gdb.h
else
@@ -1863,16 +2225,16 @@ for machine in $build $host $target; do
xm_defines=USG
xmake_file=mips/x-sni-svr4
tmake_file=mips/t-mips-gas
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-sgi-irix5*) # SGI System V.4., IRIX 5
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file="mips/iris5.h mips/iris5gas.h"
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -1881,72 +2243,71 @@ for machine in $build $host $target; do
fi
xm_defines=USG
xm_file="mips/xm-iris5.h"
- fixincludes=fixinc.irix
xmake_file=mips/x-iris
# mips-tfile doesn't work yet
tmake_file=mips/t-mips-gas
# See comment in mips/iris5.h file.
use_collect2=yes
- if [[ x$enable_threads = xyes ]]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sgi-irix4loser*) # Mostly like a MIPS.
tm_file="mips/iris4loser.h mips/iris3.h ${tm_file} mips/iris4.h"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-iris
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
- if [[ x$enable_threads = xyes ]]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sgi-irix4*) # Mostly like a MIPS.
tm_file="mips/iris3.h ${tm_file} mips/iris4.h"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-iris
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
- if [[ x$enable_threads = xyes ]]; then
-: not ported yet thread_file='irix'
- fi
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
;;
mips-sgi-*) # Mostly like a MIPS.
tm_file="mips/iris3.h ${tm_file}"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-iris3
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -1960,66 +2321,72 @@ for machine in $build $host $target; do
;;
mips-dec-osf*) # Decstation running OSF/1 as shipped by DIGITAL
tm_file=mips/dec-osf1.h
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xmake_file=mips/x-dec-osf1
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
tmake_file=mips/t-ultrix
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-dec-bsd*) # Decstation running 4.4 BSD
tm_file=mips/dec-bsd.h
- fixincludes=
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
tmake_file=mips/t-ultrix
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mipsel-*-netbsd* | mips-dec-netbsd*) # Decstation running NetBSD
tm_file=mips/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
# On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
;;
+ mips*-*-linux*) # Linux MIPS, either endian.
+ xmake_file=x-linux
+ xm_file="xm-siglist.h ${xm_file}"
+ case $machine in
+ mipsel-*) tm_file="mips/elfl.h mips/linux.h" ;;
+ *) tm_file="mips/elf.h mips/linux.h" ;;
+ esac
+ extra_parts="crtbegin.o crtend.o"
+ gnu_ld=yes
+ gas=yes
+ ;;
mips*el-*-openbsd*) # mips little endian
target_cpu_default="MASK_GAS|MASK_ABICALLS"
tm_file=mips/openbsd.h
- xmake_file=none
;;
mips*-*-openbsd*) # mips big endian
target_cpu_default="MASK_GAS|MASK_ABICALLS"
tm_file=mips/openbsd-be.h
- xmake_file=none
;;
mips-sony-bsd* | mips-sony-newsos*) # Sony NEWS 3600 or risc/news.
tm_file="mips/news4.h ${tm_file}"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -2029,31 +2396,31 @@ for machine in $build $host $target; do
# That is based on svr4.
# t-svr4 is not right because this system doesn't use ELF.
tm_file="mips/news5.h ${tm_file}"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_file="xm-siglist.h ${xm_file}"
xm_defines=USG
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-tandem-sysv4*) # Tandem S2 running NonStop UX
tm_file="mips/svr4-5.h mips/svr4-t.h"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_file="xm-siglist.h ${xm_file}"
xm_defines=USG
xmake_file=mips/x-sysv
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
extra_parts="crtbegin.o crtend.o"
@@ -2061,151 +2428,163 @@ for machine in $build $host $target; do
tmake_file=mips/t-mips
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-ultrix* | mips-dec-mach3) # Decstation.
tm_file="mips/ultrix.h ${tm_file}"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xmake_file=mips/x-ultrix
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
tmake_file=mips/t-ultrix
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
- mips-*-riscos[[56789]]bsd*)
+changequote(,)dnl
+ mips-*-riscos[56789]bsd*)
+changequote([,])dnl
tm_file=mips/bsd-5.h # MIPS BSD 4.3, RISC-OS 5.0
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-bsd-gas
else
tmake_file=mips/t-bsd
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
- mips-*-bsd* | mips-*-riscosbsd* | mips-*-riscos[[1234]]bsd*)
+changequote(,)dnl
+ mips-*-bsd* | mips-*-riscosbsd* | mips-*-riscos[1234]bsd*)
+changequote([,])dnl
tm_file="mips/bsd-4.h ${tm_file}" # MIPS BSD 4.3, RISC-OS 4.0
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-bsd-gas
else
tmake_file=mips/t-bsd
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
- mips-*-riscos[[56789]]sysv4*)
+changequote(,)dnl
+ mips-*-riscos[56789]sysv4*)
+changequote([,])dnl
tm_file=mips/svr4-5.h # MIPS System V.4., RISC-OS 5.0
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_file="xm-siglist.h ${xm_file}"
xmake_file=mips/x-sysv
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr4-gas
else
tmake_file=mips/t-svr4
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
- mips-*-sysv4* | mips-*-riscos[[1234]]sysv4* | mips-*-riscossysv4*)
+changequote(,)dnl
+ mips-*-sysv4* | mips-*-riscos[1234]sysv4* | mips-*-riscossysv4*)
+changequote([,])dnl
tm_file="mips/svr4-4.h ${tm_file}"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-sysv
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr4-gas
else
tmake_file=mips/t-svr4
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
- mips-*-riscos[[56789]]sysv*)
+changequote(,)dnl
+ mips-*-riscos[56789]sysv*)
+changequote([,])dnl
tm_file=mips/svr3-5.h # MIPS System V.3, RISC-OS 5.0
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-sysv
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr3-gas
else
tmake_file=mips/t-svr3
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
mips-*-sysv* | mips-*-riscos*sysv*)
tm_file="mips/svr3-4.h ${tm_file}"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
xm_defines=USG
xmake_file=mips/x-sysv
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-svr3-gas
else
tmake_file=mips/t-svr3
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
;;
- mips-*-riscos[[56789]]*) # Default MIPS RISC-OS 5.0.
+changequote(,)dnl
+ mips-*-riscos[56789]*) # Default MIPS RISC-OS 5.0.
+changequote([,])dnl
tm_file=mips/mips-5.h
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -2214,65 +2593,65 @@ for machine in $build $host $target; do
;;
mipsel-*-ecoff*)
tm_file=mips/ecoffl.h
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
tmake_file=mips/t-ecoff
;;
mips-*-ecoff*)
tm_file="gofast.h mips/ecoff.h"
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
tmake_file=mips/t-ecoff
;;
mipsel-*-elf*)
tm_file="mips/elfl.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tmake_file=mips/t-elf
;;
mips-*-elf*)
- tm_file="mips/elf.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tm_file="mips/elf.h"
+ tmake_file=mips/t-elf
;;
mips64el-*-elf*)
- tm_file="mips/elfl64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tm_file="mips/elfl64.h"
+ tmake_file=mips/t-elf
;;
mips64orionel-*-elf*)
tm_file="mips/elforion.h mips/elfl64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tmake_file=mips/t-elf
;;
mips64-*-elf*)
- tm_file="mips/elf64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tm_file="mips/elf64.h"
+ tmake_file=mips/t-elf
;;
mips64orion-*-elf*)
tm_file="mips/elforion.h mips/elf64.h libgloss.h"
- tmake_file=mips/t-ecoff
+ tmake_file=mips/t-elf
;;
mips64orion-*-rtems*)
tm_file="mips/elforion.h mips/elf64.h mips/rtems64.h"
tmake_file="mips/t-ecoff t-rtems"
;;
mipstx39el-*-elf*)
- tm_file="mips/r3900.h mips/elfl.h mips/abi64.h libgloss.h"
+ tm_file="mips/r3900.h mips/elfl.h mips/abi64.h"
tmake_file=mips/t-r3900
;;
mipstx39-*-elf*)
- tm_file="mips/r3900.h mips/elf.h mips/abi64.h libgloss.h"
+ tm_file="mips/r3900.h mips/elf.h mips/abi64.h"
tmake_file=mips/t-r3900
;;
mips-*-*) # Default MIPS RISC-OS 4.0.
- if [[ x$stabs = xyes ]]; then
+ if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file=mips/t-mips-gas
else
extra_passes="mips-tfile mips-tdump"
fi
- if [[ x$gnu_ld != xyes ]]
+ if test x$gnu_ld != xyes
then
use_collect2=yes
fi
@@ -2280,7 +2659,7 @@ for machine in $build $host $target; do
mn10200-*-*)
cpu_type=mn10200
tm_file="mn10200/mn10200.h"
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -2289,7 +2668,7 @@ for machine in $build $host $target; do
mn10300-*-*)
cpu_type=mn10300
tm_file="mn10300/mn10300.h"
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -2334,10 +2713,10 @@ for machine in $build $host $target; do
;;
ns32k-*-netbsd*)
tm_file=ns32k/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
+ xm_file="ns32k/xm-netbsd.h ${xm_file}"
# On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
+ use_collect2=yes
;;
pdp11-*-bsd)
tm_file="${tm_file} pdp11/2bsd.h"
@@ -2364,7 +2743,6 @@ for machine in $build $host $target; do
;;
powerpc-*-openbsd*)
tmake_file="${tmake_file} rs6000/t-rs6000 rs6000/t-openbsd"
- xmake_file=none
;;
powerpc-*-beos*)
cpu_type=rs6000
@@ -2378,7 +2756,7 @@ for machine in $build $host $target; do
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG POSIX"
extra_headers=ppc-asm.h
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
else
@@ -2389,52 +2767,47 @@ for machine in $build $host $target; do
powerpc-*-eabiaix*)
tm_file=rs6000/eabiaix.h
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-eabisim*)
tm_file=rs6000/eabisim.h
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-eabi*)
tm_file=rs6000/eabi.h
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc rs6000/t-ppccomm"
fi
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-rtems*)
tm_file=rs6000/rtems.h
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcgas t-rtems rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc t-rtems rs6000/t-ppccomm"
fi
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpc-*-linux-gnulibc1)
tm_file=rs6000/linux.h
xm_file=rs6000/xm-sysv4.h
out_file=rs6000/rs6000.c
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos t-linux t-linux-gnulibc1 rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc t-linux t-linux-gnulibc1 rs6000/t-ppccomm"
fi
xmake_file=x-linux
- fixincludes=Makefile.in
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
extra_headers=ppc-asm.h
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
@@ -2443,17 +2816,16 @@ for machine in $build $host $target; do
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG ${xm_defines}"
out_file=rs6000/rs6000.c
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos t-linux rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc t-linux rs6000/t-ppccomm"
fi
xmake_file=x-linux
- fixincludes=Makefile.in
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
extra_headers=ppc-asm.h
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
@@ -2470,7 +2842,7 @@ for machine in $build $host $target; do
tm_file=rs6000/sysv4le.h
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG POSIX"
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
else
@@ -2482,38 +2854,34 @@ for machine in $build $host $target; do
powerpcle-*-eabisim*)
tm_file=rs6000/eabilesim.h
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpcle-*-eabi*)
tm_file=rs6000/eabile.h
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc rs6000/t-ppccomm"
fi
- fixincludes=Makefile.in
extra_headers=ppc-asm.h
;;
powerpcle-*-winnt* )
tm_file=rs6000/win-nt.h
tmake_file=rs6000/t-winnt
# extra_objs=pe.o
- fixincludes=Makefile.in
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
extra_headers=ppc-asm.h
;;
- powerpcle-*-pe | powerpcle-*-cygwin32)
- tm_file=rs6000/cygwin32.h
- xm_file="rs6000/xm-cygwin32.h ${xm_file}"
+ powerpcle-*-pe | powerpcle-*-cygwin*)
+ tm_file=rs6000/cygwin.h
+ xm_file="rs6000/xm-cygwin.h ${xm_file}"
tmake_file=rs6000/t-winnt
- xmake_file=rs6000/x-cygwin32
+ xmake_file=rs6000/x-cygwin
# extra_objs=pe.o
- fixincludes=Makefile.in
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='win32'
fi
exeext=.exe
@@ -2523,73 +2891,89 @@ for machine in $build $host $target; do
tm_file=rs6000/sol2.h
xm_file="xm-siglist.h rs6000/xm-sysv4.h"
xm_defines="USG POSIX"
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
else
tmake_file="rs6000/t-ppc rs6000/t-ppccomm"
fi
xmake_file=rs6000/x-sysv4
- case $machine in
- *-*-solaris2.[[0-4]])
- fixincludes=fixinc.svr4;;
- *)
- fixincludes=fixinc.wrap;;
- esac
extra_headers=ppc-asm.h
;;
- rs6000-ibm-aix3.[[01]]*)
+changequote(,)dnl
+ rs6000-ibm-aix3.[01]*)
+changequote([,])dnl
tm_file=rs6000/aix31.h
xmake_file=rs6000/x-aix31
+ float_format=none
use_collect2=yes
;;
- rs6000-ibm-aix3.2.[[456789]]* | powerpc-ibm-aix3.2.[[456789]]*)
+changequote(,)dnl
+ rs6000-ibm-aix3.2.[456789]* | powerpc-ibm-aix3.2.[456789]*)
+changequote([,])dnl
tm_file=rs6000/aix3newas.h
- if [[ x$host != x$target ]]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xnewas
else
tmake_file=rs6000/t-newas
fi
+ float_format=none
use_collect2=yes
;;
- rs6000-ibm-aix4.[[12]]* | powerpc-ibm-aix4.[[12]]*)
+changequote(,)dnl
+ rs6000-ibm-aix4.[12]* | powerpc-ibm-aix4.[12]*)
+changequote([,])dnl
tm_file=rs6000/aix41.h
- if [[ x$host != x$target ]]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xnewas
else
tmake_file=rs6000/t-newas
fi
- xmake_file=rs6000/x-aix41
+ if test "$gnu_ld" = yes
+ then
+ xmake_file=rs6000/x-aix41-gld
+ else
+ xmake_file=rs6000/x-aix41
+ fi
+ float_format=none
use_collect2=yes
;;
- rs6000-ibm-aix4.[[3456789]].* | powerpc-ibm-aix4.[[3456789]].*)
+changequote(,)dnl
+ rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
+changequote([,])dnl
tm_file=rs6000/aix43.h
- if [[ x$host != x$target ]]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xaix43
else
tmake_file=rs6000/t-aix43
fi
xmake_file=rs6000/x-aix43
+ float_format=none
use_collect2=yes
;;
- rs6000-ibm-aix[[56789]].* | powerpc-ibm-aix[[56789]].*)
+changequote(,)dnl
+ rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
+changequote([,])dnl
tm_file=rs6000/aix43.h
- if [[ x$host != x$target ]]
+ if test x$host != x$target
then
tmake_file=rs6000/t-xaix43
else
tmake_file=rs6000/t-aix43
fi
xmake_file=rs6000/x-aix43
+ float_format=none
use_collect2=yes
;;
rs6000-ibm-aix*)
+ float_format=none
use_collect2=yes
;;
rs6000-bull-bosx)
+ float_format=none
use_collect2=yes
;;
rs6000-*-mach*)
@@ -2639,10 +3023,8 @@ for machine in $build $host $target; do
;;
sparc-*-netbsd*)
tm_file=sparc/netbsd.h
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
+ use_collect2=yes
;;
sparc-*-openbsd*)
# we need collect2 until our bug is fixed...
@@ -2662,7 +3044,6 @@ for machine in $build $host $target; do
xm_file="${xm_file} sparc/xm-linux.h"
tm_file=sparc/linux-aout.h
xmake_file=x-linux
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
;;
sparc-*-linux-gnulibc1*) # Sparc's running GNU/Linux, libc5
@@ -2671,7 +3052,6 @@ for machine in $build $host $target; do
tm_file=sparc/linux.h
tmake_file="t-linux t-linux-gnulibc1"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
;;
sparc-*-linux-gnu*) # Sparc's running GNU/Linux, libc6
@@ -2680,14 +3060,13 @@ for machine in $build $host $target; do
tm_file=sparc/linux.h
tmake_file="t-linux"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- fixincludes=Makefile.in #On Linux, the headers are ok already.
gnu_ld=yes
- if [[ x$enable_threads = xyes ]]; then
+ if test x$enable_threads = xyes; then
thread_file='posix'
fi
;;
sparc-*-lynxos*)
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
tm_file=sparc/lynx.h
else
@@ -2701,8 +3080,38 @@ for machine in $build $host $target; do
tmake_file="sparc/t-sparcbare t-rtems"
tm_file=sparc/rtems.h
;;
+ sparcv9-*-solaris2*)
+ tm_file=sparc/sol2-sld-64.h
+ xm_file="sparc/xm-sysv4-64.h sparc/xm-sol2.h"
+ xm_defines="USG POSIX"
+ tmake_file="sparc/t-sol2 sparc/t-sol2-64"
+ xmake_file=sparc/x-sysv4
+ extra_parts="crt1.o crti.o crtn.o gcrt1.o crtbegin.o crtend.o"
+ float_format=none
+ if test x${enable_threads} = x ; then
+ enable_threads=$have_pthread_h
+ if test x${enable_threads} = x ; then
+ enable_threads=$have_thread_h
+ fi
+ fi
+ if test x${enable_threads} = xyes ; then
+ if test x${have_pthread_h} = xyes ; then
+ thread_file='posix'
+ else
+ thread_file='solaris'
+ fi
+ fi
+ ;;
+ sparc-hal-solaris2*)
+ xm_file=sparc/xm-sol2.h
+ tm_file="sparc/sol2.h sparc/hal.h"
+ tmake_file="sparc/t-halos sparc/t-sol2"
+ xmake_file=sparc/x-sysv4
+ extra_parts="crt1.o crti.o crtn.o gmon.o crtbegin.o crtend.o"
+ broken_install=yes
+ ;;
sparc-*-solaris2*)
- if [[ x$gnu_ld = xyes ]]
+ if test x$gnu_ld = xyes
then
tm_file=sparc/sol2.h
else
@@ -2714,20 +3123,23 @@ for machine in $build $host $target; do
xmake_file=sparc/x-sysv4
extra_parts="crt1.o crti.o crtn.o gcrt1.o gmon.o crtbegin.o crtend.o"
case $machine in
- *-*-solaris2.[[0-4]])
- fixincludes=fixinc.svr4;;
+changequote(,)dnl
+ *-*-solaris2.[0-4])
+changequote([,])dnl
+ float_format=i128
+ ;;
*)
- fixincludes=fixinc.wrap;;
+ float_format=none
+ ;;
esac
- float_format=i128
- if [[ x${enable_threads} = x ]]; then
+ if test x${enable_threads} = x; then
enable_threads=$have_pthread_h
- if [[ x${enable_threads} = x ]]; then
+ if test x${enable_threads} = x; then
enable_threads=$have_thread_h
fi
fi
- if [[ x${enable_threads} = xyes ]]; then
- if [[ x${have_pthread_h} = xyes ]]; then
+ if test x${enable_threads} = xyes; then
+ if test x${have_pthread_h} = xyes; then
thread_file='posix'
else
thread_file='solaris'
@@ -2743,7 +3155,7 @@ for machine in $build $host $target; do
tm_file=sparc/sunos4.h
tmake_file=sparc/t-sunos41
use_collect2=yes
- if [[ x$gas = xyes ]]; then
+ if test x$gas = xyes; then
tm_file="${tm_file} sparc/sun4gas.h"
fi
;;
@@ -2788,11 +3200,11 @@ for machine in $build $host $target; do
extra_parts="crtbegin.o crtend.o"
;;
sparc64-*-linux*) # 64-bit Sparc's running GNU/Linux
- tmake_file=sparc/t-sp64
+ tmake_file="t-linux sparc/t-linux64"
xm_file="sparc/xm-sp64.h sparc/xm-linux.h"
tm_file=sparc/linux64.h
xmake_file=x-linux
- fixincludes=Makefile.in # The headers are ok already.
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
gnu_ld=yes
;;
# This hasn't been upgraded to GCC 2.
@@ -2807,7 +3219,14 @@ for machine in $build $host $target; do
xm_file=arm/xm-thumb.h
md_file=arm/thumb.md
tmake_file=arm/t-thumb
- fixincludes=Makefile.in # There is nothing to fix
+ ;;
+ thumb-wrs-vxworks)
+ tm_file=arm/tcoff.h
+ out_file=arm/thumb.c
+ xm_file=arm/xm-thumb.h
+ md_file=arm/thumb.md
+ tmake_file=arm/t-thumb
+ thread_file='vxworks'
;;
# This hasn't been upgraded to GCC 2.
# tron-*-*)
@@ -2819,7 +3238,7 @@ for machine in $build $host $target; do
tm_file="v850/v850.h"
xm_file="v850/xm-v850.h"
tmake_file=v850/t-v850
- if [[ x$stabs = xyes ]]
+ if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
fi
@@ -2836,14 +3255,12 @@ for machine in $build $host $target; do
;;
vax-*-netbsd*)
tm_file="${tm_file} netbsd.h vax/netbsd.h"
- xm_file="xm-netbsd.h ${xm_file}"
- # On NetBSD, the headers are already okay, except for math.h.
- fixincludes=fixinc.wrap
tmake_file=t-netbsd
float_format=vax
+ use_collect2=yes
;;
vax-*-openbsd*)
- tmake_file="${tm_file} vax/t-openbsd"
+ tmake_file="${tmake_file} vax/t-openbsd"
;;
vax-*-ultrix*) # vaxen running ultrix
tm_file="${tm_file} vax/ultrix.h"
@@ -2883,13 +3300,10 @@ for machine in $build $host $target; do
# GNU tools are the only tools.
gnu_ld=yes
gas=yes
- # On GNU, the headers are already okay.
- fixincludes=Makefile.in
xmake_file=x-linux # These details are the same as Linux.
tmake_file=t-gnu # These are not.
;;
*-*-sysv4*)
- fixincludes=fixinc.svr4
xmake_try_sysv=x-sysv
install_headers_dir=install-headers-cpio
;;
@@ -2907,7 +3321,14 @@ for machine in $build $host $target; do
target_cpu_default2=1
;;
i586-*-*)
- target_cpu_default2=2
+ case $target_alias in
+ k6-*)
+ target_cpu_default2=4
+ ;;
+ *)
+ target_cpu_default2=2
+ ;;
+ esac
;;
i686-*-* | i786-*-*)
target_cpu_default2=3
@@ -2915,7 +3336,7 @@ for machine in $build $host $target; do
alpha*-*-*)
case $machine in
alphaev6*)
- target_cpu_default2="MASK_CPU_EV6|MASK_BWX|MASK_CIX|MASK_MAX"
+ target_cpu_default2="MASK_CPU_EV6|MASK_BWX|MASK_MAX|MASK_FIX"
;;
alphapca56*)
target_cpu_default2="MASK_CPU_EV5|MASK_BWX|MASK_MAX"
@@ -2928,9 +3349,9 @@ for machine in $build $host $target; do
;;
esac
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
- if [[ "$target_cpu_default2" = "" ]]
+ if test "$target_cpu_default2" = ""
then
target_cpu_default2="MASK_GAS"
else
@@ -2950,7 +3371,7 @@ for machine in $build $host $target; do
xarm[23678] | xarm250 | xarm[67][01]0 \
| xarm7m | xarm7dm | xarm7dmi | xarm7tdmi \
| xarm7100 | xarm7500 | xarm7500fe | xarm810 \
- | xstrongarm | xstrongarm110)
+ | xstrongarm | xstrongarm110 | xstrongarm1100)
target_cpu_default2="TARGET_CPU_$with_cpu"
;;
@@ -2960,7 +3381,7 @@ for machine in $build $host $target; do
;;
*)
- if [[ x$pass2done = xyes ]]
+ if test x$pass2done = xyes
then
echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
exit 1
@@ -2970,9 +3391,9 @@ for machine in $build $host $target; do
;;
mips*-*-ecoff* | mips*-*-elf*)
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
- if [[ x$gnu_ld = xyes ]]
+ if test x$gnu_ld = xyes
then
target_cpu_default2=20
else
@@ -2981,7 +3402,7 @@ for machine in $build $host $target; do
fi
;;
mips*-*-*)
- if [[ x$gas = xyes ]]
+ if test x$gas = xyes
then
target_cpu_default2=16
fi
@@ -2994,6 +3415,7 @@ for machine in $build $host $target; do
xcommon | xpower | xpower2 | xpowerpc | xrios \
| xrios1 | xrios2 | xrsc | xrsc1 \
| x601 | x602 | x603 | x603e | x604 | x604e | x620 \
+ | xec603e | x740 | x750 | x401 \
| x403 | x505 | x801 | x821 | x823 | x860)
target_cpu_default2="\"$with_cpu\""
;;
@@ -3004,7 +3426,7 @@ for machine in $build $host $target; do
;;
*)
- if [[ x$pass2done = xyes ]]
+ if test x$pass2done = xyes
then
echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
exit 1
@@ -3017,11 +3439,11 @@ for machine in $build $host $target; do
.)
target_cpu_default2=TARGET_CPU_"`echo $machine | sed 's/-.*$//'`"
;;
- .supersparc | .ultrasparc | .v7 | .v8 | .v9)
+ .supersparc | .hypersparc | .ultrasparc | .v7 | .v8 | .v9)
target_cpu_default2="TARGET_CPU_$with_cpu"
;;
*)
- if [[ x$pass2done = xyes ]]
+ if test x$pass2done = xyes
then
echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
exit 1
@@ -3031,9 +3453,9 @@ for machine in $build $host $target; do
;;
esac
- if [[ "$target_cpu_default2" != "" ]]
+ if test "$target_cpu_default2" != ""
then
- if [[ "$target_cpu_default" != "" ]]
+ if test "$target_cpu_default" != ""
then
target_cpu_default="(${target_cpu_default}|${target_cpu_default2})"
else
@@ -3052,9 +3474,9 @@ for machine in $build $host $target; do
# Save data on machine being used to compile GCC in build_xm_file.
# Save data on host machine in vars host_xm_file and host_xmake_file.
- if [[ x$pass1done = x ]]
+ if test x$pass1done = x
then
- if [[ x"$xm_file" = x ]]
+ if test x"$xm_file" = x
then build_xm_file=$cpu_type/xm-$cpu_type.h
else build_xm_file=$xm_file
fi
@@ -3063,14 +3485,14 @@ for machine in $build $host $target; do
build_exeext=$exeext
pass1done=yes
else
- if [[ x$pass2done = x ]]
+ if test x$pass2done = x
then
- if [[ x"$xm_file" = x ]]
+ if test x"$xm_file" = x
then host_xm_file=$cpu_type/xm-$cpu_type.h
else host_xm_file=$xm_file
fi
host_xm_defines=$xm_defines
- if [[ x"$xmake_file" = x ]]
+ if test x"$xmake_file" = x
then xmake_file=$cpu_type/x-$cpu_type
fi
host_xmake_file="$xmake_file"
@@ -3086,48 +3508,50 @@ done
extra_objs="${host_extra_objs} ${extra_objs}"
# Default the target-machine variables that were not explicitly set.
-if [[ x"$tm_file" = x ]]
+if test x"$tm_file" = x
then tm_file=$cpu_type/$cpu_type.h; fi
-if [[ x$extra_headers = x ]]
+if test x$extra_headers = x
then extra_headers=; fi
-if [[ x"$xm_file" = x ]]
+if test x"$xm_file" = x
then xm_file=$cpu_type/xm-$cpu_type.h; fi
-if [[ x$md_file = x ]]
+if test x$md_file = x
then md_file=$cpu_type/$cpu_type.md; fi
-if [[ x$out_file = x ]]
+if test x$out_file = x
then out_file=$cpu_type/$cpu_type.c; fi
-if [[ x"$tmake_file" = x ]]
+if test x"$tmake_file" = x
then tmake_file=$cpu_type/t-$cpu_type
fi
-if [[ x$float_format = x ]]
+if test x"$dwarf2" = xyes
+then tm_file="tm-dwarf2.h $tm_file"
+fi
+
+if test x$float_format = x
then float_format=i64
fi
-if [[ x$enable_haifa = x ]]
+if test $float_format = none
+then float_h_file=Makefile.in
+else float_h_file=float-$float_format.h
+fi
+
+if test x$enable_haifa = x
then
case $target in
- alpha*-* | hppa1.?-* | powerpc*-* | rs6000-* | *sparc*-* | m32r*-*)
+ alpha*-* | hppa*-* | powerpc*-* | rs6000-* | *sparc*-* | m32r*-*)
enable_haifa=yes;;
esac
fi
# Handle cpp installation.
-if [[ x$enable_cpp != x ]]
+if test x$enable_cpp != xno
then
tmake_file="$tmake_file t-install-cpp"
- case x$enable_cpp in
- xyes | xno) ;;
- x/*) cpp_install_dir=$enable_cpp ;;
- x.*) echo "alternate cpp script installation directory must be an absolute path" 1>&2
- exit 1
- ;;
- esac
fi
# Say what files are being used for the output code and MD file.
@@ -3138,7 +3562,7 @@ count=a
for f in $tm_file; do
count=${count}x
done
-if [[ $count = ax ]]; then
+if test $count = ax; then
echo "Using \`$srcdir/config/$tm_file' as target machine macro file."
else
echo "Using the following target machine macro files:"
@@ -3151,7 +3575,7 @@ count=a
for f in $host_xm_file; do
count=${count}x
done
-if [[ $count = ax ]]; then
+if test $count = ax; then
echo "Using \`$srcdir/config/$host_xm_file' as host machine macro file."
else
echo "Using the following host machine macro files:"
@@ -3160,12 +3584,12 @@ else
done
fi
-if [[ "$host_xm_file" != "$build_xm_file" ]]; then
+if test "$host_xm_file" != "$build_xm_file"; then
count=a
for f in $build_xm_file; do
count=${count}x
done
- if [[ $count = ax ]]; then
+ if test $count = ax; then
echo "Using \`$srcdir/config/$build_xm_file' as build machine macro file."
else
echo "Using the following build machine macro files:"
@@ -3175,8 +3599,8 @@ if [[ "$host_xm_file" != "$build_xm_file" ]]; then
fi
fi
-if [[ x$thread_file = x ]]; then
- if [[ x$target_thread_file != x ]]; then
+if test x$thread_file = x; then
+ if test x$target_thread_file != x; then
thread_file=$target_thread_file
else
thread_file='single'
@@ -3189,14 +3613,14 @@ fi
# auto-host.h is the file containing items generated by autoconf and is
# the first file included by config.h.
null_defines=
-host_xm_file="auto-host.h ${host_xm_file}"
+host_xm_file="auto-host.h gansidecl.h ${host_xm_file} hwint.h"
# If host=build, it is correct to have hconfig include auto-host.h
# as well. If host!=build, we are in error and need to do more
# work to find out the build config parameters.
-if [[ x$host = x$build ]]
+if test x$host = x$build
then
- build_xm_file="auto-host.h ${build_xm_file}"
+ build_xm_file="auto-host.h gansidecl.h ${build_xm_file} hwint.h"
else
# We create a subdir, then run autoconf in the subdir.
# To prevent recursion we set host and build for the new
@@ -3218,18 +3642,21 @@ else
mv auto-host.h ../auto-build.h
cd ..
rm -rf $tempdir
- build_xm_file="auto-build.h ${build_xm_file}"
+ build_xm_file="auto-build.h gansidecl.h ${build_xm_file} hwint.h"
fi
+xm_file="gansidecl.h ${xm_file}"
+tm_file="gansidecl.h ${tm_file}"
+
vars="host_xm_file tm_file xm_file build_xm_file"
links="config.h tm.h tconfig.h hconfig.h"
defines="host_xm_defines null_defines xm_defines build_xm_defines"
rm -f config.bak
-if [[ -f config.status ]]; then mv -f config.status config.bak; fi
+if test -f config.status; then mv -f config.status config.bak; fi
# Make the links.
-while [[ -n "$vars" ]]
+while test -n "$vars"
do
set $vars; var=$1; shift; vars=$*
set $links; link=$1; shift; links=$*
@@ -3239,13 +3666,27 @@ do
# Define TARGET_CPU_DEFAULT if the system wants one.
# This substitutes for lots of *.h files.
- if [[ "$target_cpu_default" != "" -a $link = tm.h ]]
+ if test "$target_cpu_default" != "" -a $link = tm.h
then
echo "#define TARGET_CPU_DEFAULT ($target_cpu_default)" >>$link
fi
for file in `eval echo '$'$var`; do
+ case $file in
+ auto-config.h)
+ ;;
+ *)
+ echo '#ifdef IN_GCC' >>$link
+ ;;
+ esac
echo "#include \"$file\"" >>$link
+ case $file in
+ auto-config.h)
+ ;;
+ *)
+ echo '#endif' >>$link
+ ;;
+ esac
done
for def in `eval echo '$'$define`; do
@@ -3256,17 +3697,37 @@ do
done
# Truncate the target if necessary
-if [[ x$host_truncate_target != x ]]; then
+if test x$host_truncate_target != x; then
target=`echo $target | sed -e 's/\(..............\).*/\1/'`
fi
# Get the version trigger filename from the toplevel
-if [[ "${with_gcc_version_trigger+set}" = set ]]; then
+if test "${with_gcc_version_trigger+set}" = set; then
gcc_version_trigger=$with_gcc_version_trigger
else
gcc_version_trigger=${srcdir}/version.c
fi
-gcc_version=`sed -e 's/.*\"\([[^ \"]]*\)[[ \"]].*/\1/' < ${gcc_version_trigger}`
+changequote(,)dnl
+gcc_version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < ${gcc_version_trigger}`
+changequote([,])dnl
+
+# Internationalization
+PACKAGE=gcc
+VERSION="$gcc_version"
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+ALL_LINGUAS="en_UK"
+
+# NLS support is still experimental, so disable it by default for now.
+AC_ARG_ENABLE(nls,
+ [ --enable-nls use Native Language Support (disabled by default)],
+ , enable_nls=no)
+
+AM_GNU_GETTEXT
+XGETTEXT="AWK='$AWK' \$(SHELL) \$(top_srcdir)/exgettext $XGETTEXT"
# Get an absolute path to the GCC top-level source directory
holddir=`pwd`
@@ -3281,7 +3742,7 @@ host_overrides=Make-host
dep_host_xmake_file=
for f in .. ${host_xmake_file}
do
- if [[ -f ${srcdir}/config/$f ]]
+ if test -f ${srcdir}/config/$f
then
dep_host_xmake_file="${dep_host_xmake_file} ${srcdir}/config/$f"
fi
@@ -3294,7 +3755,7 @@ target_overrides=Make-target
dep_tmake_file=
for f in .. ${tmake_file}
do
- if [[ -f ${srcdir}/config/$f ]]
+ if test -f ${srcdir}/config/$f
then
dep_tmake_file="${dep_tmake_file} ${srcdir}/config/$f"
fi
@@ -3307,6 +3768,7 @@ rm -f symtest.tem
if $symbolic_link $srcdir/gcc.c symtest.tem 2>/dev/null
then
cc_set_by_configure="\$(CC)"
+ quoted_cc_set_by_configure="\$(CC)"
stage_prefix_set_by_configure="\$(STAGE_PREFIX)"
else
rm -f symtest.tem
@@ -3317,6 +3779,7 @@ else
symbolic_link="cp"
fi
cc_set_by_configure="\`case '\$(CC)' in stage*) echo '\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\$(CC)';; esac\`"
+ quoted_cc_set_by_configure="\\\`case '\\\$(CC)' in stage*) echo '\\\$(CC)' | sed -e 's|stage|../stage|g';; *) echo '\\\$(CC)';; esac\\\`"
stage_prefix_set_by_configure="\`case '\$(STAGE_PREFIX)' in stage*) echo '\$(STAGE_PREFIX)' | sed -e 's|stage|../stage|g';; *) echo '\$(STAGE_PREFIX)';; esac\`"
fi
rm -f symtest.tem
@@ -3325,29 +3788,29 @@ out_object_file=`basename $out_file .c`.o
tm_file_list=
for f in $tm_file; do
- tm_file_list="${tm_file_list} \$(srcdir)/config/$f"
+ case $f in
+ gansidecl.h )
+ tm_file_list="${tm_file_list} $f" ;;
+ *) tm_file_list="${tm_file_list} \$(srcdir)/config/$f" ;;
+ esac
done
host_xm_file_list=
for f in $host_xm_file; do
- if test $f != "auto-host.h"; then
- host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f"
- else
- host_xm_file_list="${host_xm_file_list} auto-host.h"
- fi
+ case $f in
+ auto-host.h | gansidecl.h | hwint.h )
+ host_xm_file_list="${host_xm_file_list} $f" ;;
+ *) host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f" ;;
+ esac
done
build_xm_file_list=
for f in $build_xm_file; do
- if test $f != "auto-build.h"; then
- if test $f != "auto-host.h"; then
- build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f"
- else
- build_xm_file_list="${build_xm_file_list} auto-host.h"
- fi
- else
- build_xm_file_list="${build_xm_file_list} auto-build.h"
- fi
+ case $f in
+ auto-build.h | auto-host.h | gansidecl.h | hwint.h )
+ build_xm_file_list="${build_xm_file_list} $f" ;;
+ *) build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f" ;;
+ esac
done
# Define macro CROSS_COMPILE in compilation
@@ -3355,7 +3818,7 @@ done
# Also use all.cross instead of all.internal
# and add cross-make to Makefile.
cross_overrides="/dev/null"
-if [[ x$host != x$target ]]
+if test x$host != x$target
then
cross_defines="CROSS=-DCROSS_COMPILE"
cross_overrides="${topdir}/cross-make"
@@ -3365,7 +3828,7 @@ fi
# This must come after cross-make as we want all.build to override
# all.cross.
build_overrides="/dev/null"
-if [[ x$build != x$host ]]
+if test x$build != x$host
then
build_overrides="${topdir}/build-make"
fi
@@ -3373,7 +3836,7 @@ fi
# Expand extra_headers to include complete path.
# This substitutes for lots of t-* files.
extra_headers_list=
-if [[ "x$extra_headers" = x ]]
+if test "x$extra_headers" = x
then true
else
# Prepend ${srcdir}/ginclude/ to every entry in extra_headers.
@@ -3383,10 +3846,14 @@ else
done
fi
+if test x$use_collect2 = xno; then
+ use_collect2=
+fi
+
# Add a definition of USE_COLLECT2 if system wants one.
# Also tell toplev.c what to do.
# This substitutes for lots of t-* files.
-if [[ x$use_collect2 = x ]]
+if test x$use_collect2 = x
then
will_use_collect2=
maybe_use_collect2=
@@ -3402,7 +3869,7 @@ fi
# building gcc with a cross compiler, use the cross compiler just
# built. Otherwise, we can use the cpp just built.
md_file_sub=
-if [[ "x$md_cppflags" = x ]]
+if test "x$md_cppflags" = x
then
md_file_sub=$srcdir/config/$md_file
else
@@ -3410,18 +3877,18 @@ else
fi
# If we have gas in the build tree, make a link to it.
-if [[ -f ../gas/Makefile ]]; then
+if test -f ../gas/Makefile; then
rm -f as; $symbolic_link ../gas/as-new$host_exeext as$host_exeext 2>/dev/null
fi
# If we have nm in the build tree, make a link to it.
-if [[ -f ../binutils/Makefile ]]; then
+if test -f ../binutils/Makefile; then
rm -f nm; $symbolic_link ../binutils/nm-new$host_exeext nm$host_exeext 2>/dev/null
fi
# If we have ld in the build tree, make a link to it.
-if [[ -f ../ld/Makefile ]]; then
-# if [[ x$use_collect2 = x ]]; then
+if test -f ../ld/Makefile; then
+# if test x$use_collect2 = x; then
# rm -f ld; $symbolic_link ../ld/ld-new$host_exeext ld$host_exeext 2>/dev/null
# else
rm -f collect-ld; $symbolic_link ../ld/ld-new$host_exeext collect-ld$host_exeext 2>/dev/null
@@ -3432,40 +3899,96 @@ fi
AC_MSG_CHECKING(assembler alignment features)
gcc_cv_as=
gcc_cv_as_alignment_features=
-gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,gcc$,gas,'`
-if [[ -x as$host_exeext ]]; then
+gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gas
+if test -x "$DEFAULT_ASSEMBLER"; then
+ gcc_cv_as="$DEFAULT_ASSEMBLER"
+elif test -x "$AS"; then
+ gcc_cv_as="$AS"
+elif test -x as$host_exeext; then
# Build using assembler in the current directory.
gcc_cv_as=./as$host_exeext
-elif [[ -f $gcc_cv_as_gas_srcdir/configure.in ]]; then
+elif test -f $gcc_cv_as_gas_srcdir/configure.in -a -f ../gas/Makefile; then
# Single tree build which includes gas.
for f in $gcc_cv_as_gas_srcdir/configure $gcc_cv_as_gas_srcdir/configure.in $gcc_cv_as_gas_srcdir/Makefile.in
do
- gcc_cv_gas_version=`grep '^VERSION=[[0-9]]*\.[[0-9]]*' $f`
- if [[ x$gcc_cv_gas_version != x ]]; then
+changequote(,)dnl
+ gcc_cv_gas_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f`
+changequote([,])dnl
+ if test x$gcc_cv_gas_version != x; then
break
fi
done
- gcc_cv_gas_major_version=`expr "$gcc_cv_gas_version" : "VERSION=\([[0-9]]*\)"`
- gcc_cv_gas_minor_version=`expr "$gcc_cv_gas_version" : "VERSION=[[0-9]]*\.\([[0-9]]*\)"`
- if [[ x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x ]]; then
+changequote(,)dnl
+ gcc_cv_gas_major_version=`expr "$gcc_cv_gas_version" : "VERSION=\([0-9]*\)"`
+ gcc_cv_gas_minor_version=`expr "$gcc_cv_gas_version" : "VERSION=[0-9]*\.\([0-9]*\)"`
+changequote([,])dnl
+ if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
# Gas version 2.6 and later support for .balign and .p2align.
# bytes to skip when using .p2align.
- if [[ "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 6 -o "$gcc_cv_gas_major_version" -gt 2 ]]; then
+ if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 6 -o "$gcc_cv_gas_major_version" -gt 2; then
gcc_cv_as_alignment_features=".balign and .p2align"
AC_DEFINE(HAVE_GAS_BALIGN_AND_P2ALIGN)
fi
# Gas version 2.8 and later support specifying the maximum
# bytes to skip when using .p2align.
- if [[ "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 8 -o "$gcc_cv_gas_major_version" -gt 2 ]]; then
+ if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 8 -o "$gcc_cv_gas_major_version" -gt 2; then
gcc_cv_as_alignment_features=".p2align including maximum skip"
AC_DEFINE(HAVE_GAS_MAX_SKIP_P2ALIGN)
fi
fi
-elif [[ x$host = x$target ]]; then
+elif test x$host = x$target; then
# Native build.
- gcc_cv_as=as$host_exeext
+ # Search the same directories that the installed compiler will
+ # search. Else we may find the wrong assembler and lose. If we
+ # do not find a suitable assembler binary, then try the user's
+ # path.
+ #
+ # Also note we have to check MD_EXEC_PREFIX before checking the
+ # user's path. Unfortunately, there is no good way to get at the
+ # value of MD_EXEC_PREFIX here. So we do a brute force search
+ # through all the known MD_EXEC_PREFIX values. Ugh. This needs
+ # to be fixed as part of the make/configure rewrite too.
+
+ if test "x$exec_prefix" = xNONE; then
+ if test "x$prefix" = xNONE; then
+ test_prefix=/usr/local
+ else
+ test_prefix=$prefix
+ fi
+ else
+ test_prefix=$exec_prefix
+ fi
+
+ # If the loop below does not find an assembler, then use whatever
+ # one we can find in the users's path.
+ # user's path.
+ as=as$host_exeext
+
+ test_dirs="$test_prefix/lib/gcc-lib/$target/$gcc_version \
+ $test_prefix/lib/gcc-lib/$target \
+ /usr/lib/gcc/$target/$gcc_version \
+ /usr/lib/gcc/$target \
+ $test_prefix/$target/bin/$target/$gcc_version \
+ $test_prefix/$target/bin \
+ /usr/libexec \
+ /usr/ccs/gcc \
+ /usr/ccs/bin \
+ /udk/usr/ccs/bin \
+ /bsd43/usr/lib/cmplrs/cc \
+ /usr/cross64/usr/bin \
+ /usr/lib/cmplrs/cc \
+ /sysv/usr/lib/cmplrs/cc \
+ /svr4/usr/lib/cmplrs/cc \
+ /usr/bin"
+
+ for dir in $test_dirs; do
+ if test -f $dir/as$host_exeext; then
+ gcc_cv_as=$dir/as$host_exeext
+ break;
+ fi
+ done
fi
-if [[ x$gcc_cv_as != x ]]; then
+if test x$gcc_cv_as != x; then
# Check if we have .balign and .p2align
echo ".balign 4" > conftest.s
echo ".p2align 2" >> conftest.s
@@ -3485,7 +4008,70 @@ if [[ x$gcc_cv_as != x ]]; then
fi
AC_MSG_RESULT($gcc_cv_as_alignment_features)
+AC_MSG_CHECKING(assembler subsection support)
+gcc_cv_as_subsections=
+if test x$gcc_cv_as != x; then
+ # Check if we have .subsection
+ echo ".subsection 1" > conftest.s
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_subsections=".subsection"
+ if test -x nm$host_exeext; then
+ gcc_cv_nm=./nm$host_exeext
+ elif test x$host = x$target; then
+ # Native build.
+ gcc_cv_nm=nm$host_exeext
+ fi
+ if test x$gcc_cv_nm != x; then
+ cat > conftest.s <<EOF
+conftest_label1: .word 0
+.subsection -1
+conftest_label2: .word 0
+.previous
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ $gcc_cv_nm conftest.o | grep conftest_label1 > conftest.nm1
+ $gcc_cv_nm conftest.o | grep conftest_label2 | sed -e 's/label2/label1/' > conftest.nm2
+ if cmp conftest.nm1 conftest.nm2 > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_as_subsections="working .subsection -1"
+ AC_DEFINE(HAVE_GAS_SUBSECTION_ORDERING)
+ fi
+ fi
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest.nm1 conftest.nm2
+fi
+AC_MSG_RESULT($gcc_cv_as_subsections)
+
+AC_MSG_CHECKING(assembler instructions)
+gcc_cv_as_instructions=
+if test x$gcc_cv_as != x; then
+ set "filds fists" "filds mem; fists mem"
+ while test $# -gt 0
+ do
+ echo "$2" > conftest.s
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_instructions=${gcc_cv_as_instructions}$1" "
+ AC_DEFINE_UNQUOTED(HAVE_GAS_`echo "$1" | tr '[a-z ]' '[A-Z_]'`)
+ fi
+ shift 2
+ done
+ rm -f conftest.s conftest.o
+fi
+AC_MSG_RESULT($gcc_cv_as_instructions)
+
# Figure out what language subdirectories are present.
+# Look if the user specified --enable-languages="..."; if not, use
+# the environment variable $LANGUAGES if defined. $LANGUAGES might
+# go away some day.
+if test x"${enable_languages+set}" != xset; then
+ if test x"${LANGUAGES+set}" = xset; then
+ enable_languages="`echo ${LANGUAGES} | tr ' ' ','`"
+ else
+ enable_languages=all
+ fi
+fi
subdirs=
for lang in ${srcdir}/*/config-lang.in ..
do
@@ -3493,14 +4079,47 @@ do
..) ;;
# The odd quoting in the next line works around
# an apparent bug in bash 1.12 on linux.
- ${srcdir}/[[*]]/config-lang.in) ;;
- *) subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([[^/]]*\)/config-lang.in$,\1,'`" ;;
+changequote(,)dnl
+ ${srcdir}/[*]/config-lang.in) ;;
+ *)
+ lang_alias=`sed -n -e 's,^language=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^language=\([^ ]*\).*$,\1,p' $lang`
+ if test "x$lang_alias" = x
+ then
+ echo "$lang doesn't set \$language." 1>&2
+ exit 1
+ fi
+ if test x"${enable_languages}" = xall; then
+ add_this_lang=yes
+ else
+ case "${enable_languages}" in
+ ${lang_alias} | "${lang_alias},"* | *",${lang_alias},"* | *",${lang_alias}" )
+ add_this_lang=yes
+ ;;
+ * )
+ add_this_lang=no
+ ;;
+ esac
+ fi
+ if test x"${add_this_lang}" = xyes; then
+ case $lang in
+ ${srcdir}/ada/config-lang.in)
+ if test x$gnat = xyes ; then
+ subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
+ fi
+ ;;
+ *)
+ subdirs="$subdirs `echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
+ ;;
+ esac
+ fi
+ ;;
+changequote([,])dnl
esac
done
# Make gthr-default.h if we have a thread file.
gthread_flags=
-if [[ $thread_file != single ]]; then
+if test $thread_file != single; then
rm -f gthr-default.h
echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h
gthread_flags=-DHAVE_GTHR_DEFAULT
@@ -3512,18 +4131,23 @@ AC_SUBST(gthread_flags)
lang_specs_files=
lang_options_files=
-rm -f specs.h options.h
-touch specs.h options.h
+lang_tree_files=
+rm -f specs.h options.h gencheck.h
+touch specs.h options.h gencheck.h
for subdir in . $subdirs
do
- if [[ -f $srcdir/$subdir/lang-specs.h ]]; then
+ if test -f $srcdir/$subdir/lang-specs.h; then
echo "#include \"$subdir/lang-specs.h\"" >>specs.h
lang_specs_files="$lang_specs_files $srcdir/$subdir/lang-specs.h"
fi
- if [[ -f $srcdir/$subdir/lang-options.h ]]; then
+ if test -f $srcdir/$subdir/lang-options.h; then
echo "#include \"$subdir/lang-options.h\"" >>options.h
lang_options_files="$lang_options_files $srcdir/$subdir/lang-options.h"
fi
+ if test -f $srcdir/$subdir/$subdir-tree.def; then
+ echo "#include \"$subdir/$subdir-tree.def\"" >>gencheck.h
+ lang_tree_files="$lang_tree_files $srcdir/$subdir/$subdir-tree.def"
+ fi
done
# These (without "all_") are set in each config-lang.in.
@@ -3533,7 +4157,7 @@ all_boot_languages=
all_compilers=
all_stagestuff=
all_diff_excludes=
-all_outputs=Makefile
+all_outputs='Makefile intl/Makefile po/Makefile.in fixinc/Makefile'
# List of language makefile fragments.
all_lang_makefiles=
all_headers=
@@ -3552,7 +4176,7 @@ oldstyle_subdirs=
for s in .. $subdirs
do
- if [[ $s != ".." ]]
+ if test $s != ".."
then
language=
boot_language=
@@ -3563,14 +4187,14 @@ do
outputs=
lib2funcs=
. ${srcdir}/$s/config-lang.in
- if [[ "x$language" = x ]]
+ if test "x$language" = x
then
echo "${srcdir}/$s/config-lang.in doesn't set \$language." 1>&2
exit 1
fi
all_lang_makefiles="$all_lang_makefiles ${srcdir}/$s/Make-lang.in ${srcdir}/$s/Makefile.in"
all_languages="$all_languages $language"
- if [[ "x$boot_language" = xyes ]]
+ if test "x$boot_language" = xyes
then
all_boot_languages="$all_boot_languages $language"
fi
@@ -3579,7 +4203,7 @@ do
all_diff_excludes="$all_diff_excludes $diff_excludes"
all_headers="$all_headers $headers"
all_outputs="$all_outputs $outputs"
- if [[ x$outputs = x ]]
+ if test x$outputs = x
then
oldstyle_subdirs="$oldstyle_subdirs $s"
fi
@@ -3601,10 +4225,10 @@ target_list="all.build all.cross start.encap rest.encap \
for t in $target_list
do
x=
- for l in .. $all_languages
+ for lang in .. $all_languages
do
- if [[ $l != ".." ]]; then
- x="$x $l.$t"
+ if test $lang != ".."; then
+ x="$x $lang.$t"
fi
done
echo "lang.$t: $x" >> Make-hooks
@@ -3612,14 +4236,14 @@ done
# If we're not building in srcdir, create .gdbinit.
-if [[ ! -f Makefile.in ]]; then
+if test ! -f Makefile.in; then
echo "dir ." > .gdbinit
echo "dir ${srcdir}" >> .gdbinit
- if [[ x$gdb_needs_out_file_path = xyes ]]
+ if test x$gdb_needs_out_file_path = xyes
then
echo "dir ${srcdir}/config/"`dirname ${out_file}` >> .gdbinit
fi
- if [[ "x$subdirs" != x ]]; then
+ if test "x$subdirs" != x; then
for s in $subdirs
do
echo "dir ${srcdir}/$s" >> .gdbinit
@@ -3633,7 +4257,7 @@ fi
build_canonical=${build}
host_canonical=${host}
target_subdir=
-if [[ "${host}" != "${target}" ]] ; then
+if test "${host}" != "${target}" ; then
target_subdir=${target}/
fi
AC_SUBST(build_canonical)
@@ -3645,7 +4269,7 @@ AC_SUBST(target_subdir)
# libgcc.a, but that's OK because newib should have its own version of
# assert.h.
inhibit_libc=
-if [[ x$with_newlib = xyes ]]; then
+if test x$with_newlib = xyes; then
inhibit_libc=-Dinhibit_libc
fi
AC_SUBST(inhibit_libc)
@@ -3653,23 +4277,62 @@ AC_SUBST(inhibit_libc)
# Override SCHED_OBJ and SCHED_CFLAGS to enable the Haifa scheduler.
sched_prefix=
sched_cflags=
-if [[ x$enable_haifa = xyes ]]; then
+if test x$enable_haifa = xyes; then
echo "Using the Haifa scheduler."
sched_prefix=haifa-
sched_cflags=-DHAIFA
fi
AC_SUBST(sched_prefix)
AC_SUBST(sched_cflags)
-if [[ x$enable_haifa != x ]]; then
+if test x$enable_haifa != x; then
# Explicitly remove files that need to be recompiled for the Haifa scheduler.
- for x in genattrtab.o toplev.o loop.o unroll.o *sched.o; do
- if [[ -f $x ]]; then
+ for x in genattrtab.o toplev.o *sched.o; do
+ if test -f $x; then
echo "Removing $x"
rm -f $x
fi
done
fi
+# If $(exec_prefix) exists and is not the same as $(prefix), then compute an
+# absolute path for gcc_tooldir based on inserting the number of up-directory
+# movements required to get from $(exec_prefix) to $(prefix) into the basic
+# $(libsubdir)/@(unlibsubdir) based path.
+# Don't set gcc_tooldir to tooldir since that's only passed in by the toplevel
+# make and thus we'd get different behavior depending on where we built the
+# sources.
+if test x$exec_prefix = xNONE -o x$exec_prefix = x$prefix; then
+ gcc_tooldir='$(libsubdir)/$(unlibsubdir)/../$(target_alias)'
+else
+changequote(<<, >>)dnl
+# An explanation of the sed strings:
+# -e 's|^\$(prefix)||' matches and eliminates 'prefix' from 'exec_prefix'
+# -e 's|/$||' match a trailing forward slash and eliminates it
+# -e 's|^[^/]|/|' forces the string to start with a forward slash (*)
+# -e 's|/[^/]*|../|g' replaces each occurance of /<directory> with ../
+#
+# (*) Note this pattern overwrites the first character of the string
+# with a forward slash if one is not already present. This is not a
+# problem because the exact names of the sub-directories concerned is
+# unimportant, just the number of them matters.
+#
+# The practical upshot of these patterns is like this:
+#
+# prefix exec_prefix result
+# ------ ----------- ------
+# /foo /foo/bar ../
+# /foo/ /foo/bar ../
+# /foo /foo/bar/ ../
+# /foo/ /foo/bar/ ../
+# /foo /foo/bar/ugg ../../
+#
+ dollar='$$'
+ gcc_tooldir="\$(libsubdir)/\$(unlibsubdir)/\`echo \$(exec_prefix) | sed -e 's|^\$(prefix)||' -e 's|/\$(dollar)||' -e 's|^[^/]|/|' -e 's|/[^/]*|../|g'\`\$(target_alias)"
+changequote([, ])dnl
+fi
+AC_SUBST(gcc_tooldir)
+AC_SUBST(dollar)
+
# Nothing to do for FLOAT_H, float_format already handled.
objdir=`pwd`
AC_SUBST(objdir)
@@ -3679,51 +4342,56 @@ ${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xma
# Substitute configuration variables
AC_SUBST(subdirs)
-AC_SUBST(all_languages)
AC_SUBST(all_boot_languages)
AC_SUBST(all_compilers)
-AC_SUBST(all_lang_makefiles)
-AC_SUBST(all_stagestuff)
AC_SUBST(all_diff_excludes)
-AC_SUBST(all_lib2funcs)
AC_SUBST(all_headers)
+AC_SUBST(all_lang_makefiles)
+AC_SUBST(all_languages)
+AC_SUBST(all_lib2funcs)
+AC_SUBST(all_stagestuff)
+AC_SUBST(build_exeext)
+AC_SUBST(build_install_headers_dir)
+AC_SUBST(build_xm_file_list)
+AC_SUBST(cc_set_by_configure)
+AC_SUBST(quoted_cc_set_by_configure)
+AC_SUBST(cpp_install_dir)
AC_SUBST(cpp_main)
-AC_SUBST(extra_passes)
-AC_SUBST(extra_programs)
-AC_SUBST(extra_parts)
+AC_SUBST(dep_host_xmake_file)
+AC_SUBST(dep_tmake_file)
+AC_SUBST(extra_c_flags)
AC_SUBST(extra_c_objs)
+AC_SUBST(extra_cpp_objs)
AC_SUBST(extra_cxx_objs)
-AC_SUBST(extra_c_flags)
+AC_SUBST(extra_headers_list)
AC_SUBST(extra_objs)
+AC_SUBST(extra_parts)
+AC_SUBST(extra_passes)
+AC_SUBST(extra_programs)
+AC_SUBST(fixinc_defs)
+AC_SUBST(float_h_file)
+AC_SUBST(gcc_gxx_include_dir)
+AC_SUBST(gcc_version)
+AC_SUBST(gcc_version_trigger)
+AC_SUBST(host_exeext)
AC_SUBST(host_extra_gcc_objs)
-AC_SUBST(extra_headers_list)
-AC_SUBST(dep_host_xmake_file)
-AC_SUBST(dep_tmake_file)
-AC_SUBST(out_file)
-AC_SUBST(out_object_file)
-AC_SUBST(md_file)
-AC_SUBST(tm_file_list)
-AC_SUBST(build_xm_file_list)
AC_SUBST(host_xm_file_list)
-AC_SUBST(lang_specs_files)
+AC_SUBST(install)
+AC_SUBST(JAVAGC)
AC_SUBST(lang_options_files)
-AC_SUBST(thread_file)
-AC_SUBST(gcc_version)
-AC_SUBST(gcc_version_trigger)
+AC_SUBST(lang_specs_files)
+AC_SUBST(lang_tree_files)
AC_SUBST(local_prefix)
-AC_SUBST(gxx_include_dir)
-AC_SUBST(fixincludes)
-AC_SUBST(build_install_headers_dir)
-AC_SUBST(build_exeext)
-AC_SUBST(host_exeext)
-AC_SUBST(float_format)
-AC_SUBST(will_use_collect2)
AC_SUBST(maybe_use_collect2)
-AC_SUBST(cc_set_by_configure)
+AC_SUBST(md_file)
+AC_SUBST(objc_boehm_gc)
+AC_SUBST(out_file)
+AC_SUBST(out_object_file)
AC_SUBST(stage_prefix_set_by_configure)
-AC_SUBST(install)
AC_SUBST(symbolic_link)
-AC_SUBST(cpp_install_dir)
+AC_SUBST(thread_file)
+AC_SUBST(tm_file_list)
+AC_SUBST(will_use_collect2)
AC_SUBST_FILE(target_overrides)
@@ -3735,7 +4403,7 @@ AC_SUBST_FILE(language_fragments)
AC_SUBST_FILE(language_hooks)
# Echo that links are built
-if [[ x$host = x$target ]]
+if test x$host = x$target
then
str1="native "
else
@@ -3743,25 +4411,25 @@ else
str2=" from $host"
fi
-if [[ x$host != x$build ]]
+if test x$host != x$build
then
str3=" on a $build system"
fi
-if [[ "x$str2" != x ]] || [[ "x$str3" != x ]]
+if test "x$str2" != x || test "x$str3" != x
then
str4=
fi
echo "Links are now set up to build a ${str1}compiler for ${target}$str4" 1>&2
-if [[ "x$str2" != x ]] || [[ "x$str3" != x ]]
+if test "x$str2" != x || test "x$str3" != x
then
echo " ${str2}${str3}." 1>&2
fi
# Truncate the target if necessary
-if [[ x$host_truncate_target != x ]]; then
+if test x$host_truncate_target != x; then
target=`echo $target | sed -e 's/\(..............\).*/\1/'`
fi
@@ -3783,9 +4451,9 @@ esac
# FLAGS_TO_PASS has been modified to solve the problem there.
# This is virtually a duplicate of what happens in configure.lang; we do
# an extra check to make sure this only happens if ln -s can be used.
-if [[ "$symbolic_link" = "ln -s" ]]; then
+if test "$symbolic_link" = "ln -s"; then
for d in .. ${subdirs} ; do
- if [[ $d != .. ]]; then
+ if test $d != ..; then
STARTDIR=`pwd`
cd $d
for t in stage1 stage2 stage3 stage4 include
@@ -3797,6 +4465,11 @@ if [[ "$symbolic_link" = "ln -s" ]]; then
fi
done
else true ; fi
+# Avoid having to add intl to our include paths.
+if test -f intl/libintl.h; then
+ echo creating libintl.h
+ echo '#include "intl/libintl.h"' >libintl.h
+fi
],
[
host='${host}'
diff --git a/contrib/gcc/convert.c b/contrib/gcc/convert.c
index e03d39b..bfcb5db 100644
--- a/contrib/gcc/convert.c
+++ b/contrib/gcc/convert.c
@@ -121,6 +121,14 @@ convert_to_integer (type, expr)
int inprec = TYPE_PRECISION (intype);
int outprec = TYPE_PRECISION (type);
+ /* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can
+ be. Consider `enum E = { a, b = (enum E) 3 };'. */
+ if (!TYPE_SIZE (type))
+ {
+ error ("conversion to incomplete type");
+ return error_mark_node;
+ }
+
switch (TREE_CODE (intype))
{
case POINTER_TYPE:
diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog
index 5102e32..82d1a8b 100644
--- a/contrib/gcc/cp/ChangeLog
+++ b/contrib/gcc/cp/ChangeLog
@@ -1,6 +1,1724 @@
-Sun Mar 14 02:38:07 PST 1999 Jeff Law (law@cygnus.com)
+Mon Aug 16 01:29:24 PDT 1999 Jeff Law (law@cygnus.com)
- * egcs-1.1.2 Released.
+ * gcc-2.95.1 Released.
+
+1999-08-12 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (lang_decode_option): Deprecate signatures.
+
+1999-08-11 Martin v. Loewis <martin@mira.isdn.cs.tu-berlin.de>
+
+ * lex.c (do_identifier): If we find a hidden type after a global
+ was selected already, continue using the global.
+
+1999-08-10 Martin v. Loewis <martin@mira.isdn.cs.tu-berlin.de>
+
+ * decl2.c (set_decl_namespace): Do not complain about non-matching
+ decls if processing a template.
+
+1999-08-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (function_try_block): Call end_protect_partials
+ before expand_start_all_catch.
+
+1999-08-06 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (maybe_get_template_decl_from_type_decl): Make sure that
+ we're looking at a class.
+
+ * decl.c (lookup_name_real): Set the complain flag if we're
+ looking for a namespace member.
+
+ * decl.c (pushdecl): Only give an error for shadowing a parm
+ from *this* function.
+
+ * decl2.c (build_expr_from_tree, case METHOD_CALL_EXPR): Only
+ build_expr_from_tree on the args of a TEMPLATE_ID_EXPR.
+
+ * class.c (mark_overriders): Fix order of args to overrides.
+ (warn_hidden): Likewise. Fix for having virtual and non-virtual
+ functions with the same name.
+
+ * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro.
+ * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for
+ virtual functions and MI. Simplify.
+
+ * typeck.c (c_expand_return): Downgrade pedwarn about returning NULL
+ from op new to warning.
+
+ * decl2.c (reparse_absdcl_as_casts): Don't warn about old-style
+ casts in system headers or extern "C" blocks.
+
+ * pt.c (do_decl_instantiation): Downgrade duplicate instantiation
+ errors to pedwarn.
+
+ * error.c (dump_type_real): Handle TREE_LIST again.
+
+ * typeck.c (comp_target_parms): Don't complain about
+ converting from () to (...) if !flag_strict_prototype.
+
+ * class.c (instantiate_type): Downgrade errors for object-dependent
+ memfn refs to pedwarn.
+
+1999-08-06 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * pt.c (tsubst): Use build_index_type to build in-template array
+ index type. Fixes g++.oliva/dwarf1.C.
+ * decl.c (grokdeclarator): Likewise, just for consistency, as it
+ doesn't seem to trigger the bug without it.
+
+Thu Aug 5 02:40:42 1999 Jeffrey A Law (law@cygnus.com)
+
+ * typeck2.c: Update URLs and mail addresses.
+
+1999-08-03 Mumit Khan <khan@xraylith.wisc.edu>
+
+ * decl.c (start_decl): Set attributes before duplicate_decls call.
+
+Wed Jul 28 21:39:31 PDT 1999 Jeff Law (law@cygnus.com)
+
+ * gcc-2.95 Released.
+
+Sun Jul 25 15:24:21 1999 Jeffrey A Law (law@cygnus.com)
+
+ * g++FAQ.texi: Deleted per Joe Buck's request.
+ * Makefile.in: Corresponding changes.
+
+Sat Jul 17 23:50:47 1999 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (INTERFACE): Bump to 2.
+
+1999-07-17 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * typeck2.c (my_friendly_abort): Updated URL with bug reporting
+ instructions to gcc.gnu.org. Removed e-mail address.
+
+1999-07-15 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (check_default_tmpl_args): Handle friends defined in the
+ class just like member functions defined in the class.
+
+Thu Jul 15 01:26:49 1999 H.J. Lu <hjl@gnu.org>
+
+ * decl.c (duplicate_decls): Relax restriction for exception
+ checks on duplicate symbols.
+
+1999-07-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Update the names of all variants when
+ de-anonymizing.
+
+Wed Jul 7 01:26:47 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * decl2.c (mark_vtable_entries): Fix check for rtti offset.
+
+1999-06-26 Richard Henderson <rth@cygnus.com>
+
+ * decl.c (cp_finish_decl): Fix typo in cp_warning_at call.
+
+1999-06-21 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (expand_aggr_vbase_init): Rename to
+ construct_virtual_bases. Conditionalize construction here,
+ rather than ...
+ (emit_base_init): Here.
+
+1999-06-19 Mark Mitchell <mark@codesourcery.com>
+
+ * semantics.c (finish_asm_statement): Apply decay conversions to
+ input operands.
+
+ * decl.c (expand_static_init): When building an anonymous function
+ for use with atexit, compute its body before and after entering
+ the function.
+
+1999-06-18 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (expand_aggr_vbase_init): Add flag parameter.
+ (build_partial_cleanup_for): Remove, inlining into ..
+ (expand_cleanup_for_base): ... here. Take flag parameter.
+ (emit_base_init): Pass the in_chrg parameter to
+ emit_aggr_vbase_init.
+ (emit_aggr_vbase_init): Pass it to expand_cleanup_for_base.
+
+1999-06-16 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (import_export_decl): Use same_type_p, rather than
+ relying on pointer-equality for types.
+
+ * method.c (do_build_copy_constructor): Simplify.
+
+ * call.c (build_method_call): Remove bogus code for two-argument
+ delete.
+ * init.c (build_new_1): Expand on comment, and remove dead code.
+
+ * init.c (expand_cleanup_for_base): New function, split out
+ from ...
+ (emit_base_init): Here.
+ (expand_aggr_vbase_init): Use it.
+
+1999-06-15 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (class_cache_firstobj): Declare.
+ (maybe_push_cache_obstack): Rename to push_cache_obstack.
+ * class.c (permanent_obstack): Remove declaration.
+ (class_cache_firstobj): Make it global.
+ (add_method): Don't use permanent_obstack directly.
+ (pushclass): Only free the class_cache_obstack if we know how far
+ back to free it.
+ (maybe_push_cache_obstack): Rename to push_cache_obstack.
+ * decl.c: Remove dead comment.
+ (saved_scope): Add class_cache_firstobj.
+ (push_to_top_level): Save it.
+ (pop_from_top_level): Restore it.
+ (push_class_level_binding): Use push_cache_obstack, not
+ maybe_push_cache_obstack.
+ * search.c (push_class_decls): Likewise.
+
+1999-06-14 Nathan Sidwell <nathan@acm.org>
+
+ * call.c (build_new_op): Remove REF_BIND from all operands.
+
+1999-06-07 Mark Mitchell <mark@codesourcery.com>
+
+ * search.c (convert_pointer_to_single_level): Reimplement without
+ using get_binfo.
+
+1999-06-06 Mark Mitchell <mark@codesourcery.com>
+
+ * method.c (is_back_referenceable_type): Back-reference bools when
+ not squangling.
+
+1999-06-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (finish_if_stmt_cond): Copy cond to permanent_obstack.
+ (finish_while_stmt_cond, finish_do_stmt, finish_for_cond): Likewise.
+
+1999-05-30 Mark Mitchell <mark@codesourcery.com>
+
+ * lex.c (make_lang_type): Create TYPE_BINFO for
+ TEMPLATE_TYPE_PARMs just like for non-template types.
+
+1999-05-28 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (complete_array_type): Allocate off same obstack. Fix
+ DO_DEFAULT comment to match reality.
+
+1999-05-22 Mark Mitchell <mark@codesourcery.com>
+
+ * tree.c (mapcar): Handle NON_LVALUE_EXPR.
+
+1999-05-21 Mark Mitchell <mark@codesourcery.com>
+
+ * typeck.c (build_ptrmemfunc): Handle PTRMEM_CSTs carefully to
+ reveal optimization opportunities.
+
+1999-05-20 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (grokdeclarator): Don't treat [] as indicating a
+ zero-sized array in a typedef.
+
+ * call.c (build_object_call): Don't look at DECL_NAME for a type.
+ (pt.c): Or CP_TYPE_QUALS for an ERROR_MARK.
+ (typeck.c): Or TYPE_MAIN_VARIANT for a type.
+
+1999-05-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (lvalue_p_1): A NOP_EXPR can be an lvalue.
+ (build_cplus_new): Make sure that what we return is of the right type.
+
+1999-05-20 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (make_ptrmem_cst): New function.
+ * expr.c (cplus_expand_constant): Split out from ...
+ (cplus_expand_expr): Here. Use cplus_expand_constant.
+ (init_cplus_expand): Set lang_expand_constant.
+ * pt.c (convert_nontype_argument): Use make_ptrmem_cst.
+ * tree.c (make_ptrmem_cst): Define.
+ * typeck.c (unary_complex_lvalue): Use make_ptrmem_cst.
+ * typeck2.c (initializer_constant_valid_p): Use make_ptrmem_cst.
+
+1999-05-19 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (start_static_storage_duration_function): Fix comment.
+ (finish_file): Create static storage duration functions lazily.
+
+Wed May 19 02:50:53 1999 Arvind Sankar <arvinds@mit.edu>
+
+ * gxxint.texi: Fix typo.
+
+1999-05-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (joust): Compare the types of the conv ops, not the
+ target types of the conversions.
+
+Tue May 18 00:21:34 1999 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * lang-specs.h: Define __GNUC__ and __GNUC_MINOR__ only if -no-gcc
+ was not given.
+
+1999-05-17 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.def (TEMPLATE_ID_EXPR): Update documentation.
+ * decl.c (grokfndecl): Don't allow inline declarations of friend
+ template specializations, or friend template specializations with
+ default arguments.
+ * pt.c (tsubst): Handle substitution into array types that does
+ not yield a fixed upper bound, even when not processing a
+ template.
+ (tsubst_copy): Deal with the fact that the second operand to a
+ TEMPLATE_ID_EXPR may be NULL_TREE, a TREE_LIST, or a TREE_VEC.
+ * search.c (marked_pushdecls_p): Don't descend into
+ TEMPLATE_TYPE_PARMs and the like.
+ (unmarked_pushdecls_p): Likewise.
+
+ * call.c (build_over_call): Don't throw away
+ initializations/copies of empty classes; use MODIFY_EXPR and
+ INIT_EXPR as for non-empty classes.
+ * class.c (finish_struct_1): Put the padding byte for an empty
+ class on the TYPE_NONCOPIED_PARTS list for the class.
+
+1999-05-16 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (build_expr_from_tree): Handle COMPONENT_REFs that
+ indicate a reference to a field that is a qualified name.
+
+1999-05-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_objects): Don't use .?tors.* if we don't have
+ ASM_OUTPUT_CONSTRUCTOR.
+
+ * friend.c (do_friend): Add attrlist arg. Remove support for
+ getting a non-decl as 'decl'.
+ * decl.c (grokfndecl): Remove attrlist arg. Don't set attrs or
+ rtl.
+ (grokdeclarator): Adjust.
+ * cp-tree.h: Adjust.
+
+1999-05-16 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (permanent_p): New function.
+ * init.c (build_new_1): Use mapcar, not copy_node, to copy a
+ possibly complex tree node.
+ * tree.c (mapcar): Adjust comments, and follow coding standards in
+ conditional.
+ (permanent_p): New function.
+
+1999-05-13 Per Bothner <bothner@cygnus.com>
+
+ * class.c (push_lang_context): Turn off DECL_IGNORED_P for
+ primitive Java types, if we actually see `extern "Java"'.
+
+1999-05-10 18:21 -0400 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * lang-specs.h: Pass -$ to the preprocessor.
+
+1999-05-10 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (build_offset_ref): Wrap baselinks in OFFSET_REF, too.
+ Don't bother wrapping an OFFSET_TYPE around unknown_type_node.
+ (resolve_offset_ref): Don't handle a raw baselink.
+ * cvt.c (build_expr_type_conversion): Likewise.
+ * typeck.c (decay_conversion, build_c_cast, convert_for_assignment,
+ convert_for_initialization): Likewise.
+ * class.c (instantiate_type): Handle seeing a baselink under an
+ OFFSET_REF.
+ * error.c (dump_expr): Likewise.
+ * pt.c (for_each_template_parm): Likewise.
+ (resolve_overloaded_unification): Likewise.
+ * tree.c (is_overloaded_fn, really_overloaded_fn): Likewise.
+ * typeck.c (expr_sizeof): Also complain about other permutations
+ of overloaded functions.
+
+1999-05-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (resolve_offset_ref): Don't return a raw method.
+ Use BASELINK_P.
+ * typeck.c (decay_conversion): Don't handle a raw method.
+ Resolve all OFFSET_REFs.
+ (get_member_function_from_ptrfunc): 0 is a valid vtable index.
+ (build_binary_op_nodefault): Handle resolving overloaded fns. Use
+ same_type_p for pmf bits. Don't use build_binary_op to compare
+ raw pointers to methods.
+ (convert_for_assignment): Check for OFFSET_REF, not OFFSET_TYPE,
+ to decide when to call resolve_offset_ref.
+ (build_c_cast, convert_for_initialization): Likewise.
+ * cvt.c (build_expr_type_conversion): Likewise.
+
+1999-05-06 Nathan Sidwell <nathan@acm.org>
+
+ * call.c (build_new_method_call): Use TYPE_MAIN_VARIANT of class.
+
+1999-05-05 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (start_objects): Don't let static constructors and
+ destructors get inlined.
+
+ * parse.y (nested_name_specifier): Make sure ordinary types are
+ complete, just like template types.
+ * parse.c: Regenerated.
+
+ * pt.c (check_explicit_specialization): Improve error messages.
+
+1999-05-04 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * typeck.c (string_conv_p): Use same_type_p to check whether we
+ try to convert between char and wchar_t.
+
+1999-05-03 Mark Mitchell <mark@codesourcery.com>
+
+ * search.c (lookup_field_r): Set the TREE_TYPE of an ambiguous
+ lookup to error_mark_node here.
+ (lookup_member): Revise documentation. Add comments. Don't set
+ the TREE_TYPE to error_mark_node here, and don't build up an extra
+ TREE_LIST for ambiguous lookups.
+ (setup_class_bindings): Adjust accordingly.
+ (push_class_decls): Revise out-of-date comments.
+
+ * typeck.c (build_const_cast): Tighten checks for legality.
+
+1999-05-02 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * init.c (build_member_call): Lookup names coming from
+ namespace-scoped LOOKUP_EXPR.
+
+1999-05-03 Jim Blandy <jimb@zwingli.cygnus.com>
+
+ * gxxint.texi: Add documentation for 'I'.
+
+1999-05-02 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * tinfo.cc (operator==): Qualify type_info with std::.
+
+1999-05-02 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_decl_flags): Remove comdat. Updated dummy.
+ (DECL_COMDAT): Remove definition.
+
+1999-05-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (wrapup_globals_for_namespace): Fix thinko in previous
+ change.
+
+1999-04-30 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (build_vtable): Use build_lang_decl when building
+ vtables, not just build_decl.
+ (prepare_fresh_vtable): Likewise.
+ * decl.c (wrapup_globals_for_namespace): Mark vtables as
+ DECL_EXTERNAL when calling wrapup_global_declarations.
+ * decl2.c (priority_info_s): Add initializations_p and
+ destructions_p members.
+ (finish_vtable_vardecl): Use TREE_SYMBOL_REFERENCED, not TREE_USED,
+ when deciding what vtables to write out.
+ (ssdf_decls): New variable.
+ (ssdf_decls_used): Likewise.
+ (start_static_storage_duration_function): Deal with being called
+ multiple times. Avoid inlining this function.
+ (generate_inits_for_priority): Deal with reuse of priority map.
+ (get_priority_info): Clear initializations_p and destructions_p.
+ (do_static_initialization): Tweak comment.
+ (do_static_destruction): Likewise. Fix condition on sentries for
+ destruction.
+ (generate_ctor_or_dtor_function): Call all of the static storage
+ duration functions.
+ (generate_ctor_or_dtor_function_for_priority): Check
+ initializations_p and destructions_p to see what priorities need
+ initialization functions.
+ (finish_file): Rework to generate multiple static storage duration
+ functions, rather than just one.
+
+ * typeck.c (build_const_cast): Tweak last change to handle
+ templates correctly.
+
+ * typeck.c (build_const_cast): Disallow use of const_cast to
+ anything but a pointer or reference type.
+
+1999-04-30 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (cp_finish_decl): Don't permit arrays of abstract or
+ signature type.
+
+1999-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (do_static_destruction): Remove obsolete FIXME comment.
+ (finish_file): Indent comments properly.
+
+1999-04-29 Richard Henderson <rth@cygnus.com>
+
+ * decl2.c (do_static_initialization): Call do_pending_stack_adjust.
+ (do_static_destruction): Likewise.
+
+1999-04-29 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (TYPE_NOTHROW_P): New macro.
+ * decl2.c (delete_sanity): Warn on deleting void *.
+ * init.c (build_new_1): Use TYPE_NOTHROW_P.
+ * typeck.c (c_expand_return): cp_pedwarn on returning NULL from
+ throwing operator new.
+
+1999-04-28 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (build_component_addr): Remove prototype.
+ * typeck.c (build_component_addr): Make static. Remove MSG
+ argument.
+ (build_component_addr): Remove MSG parameter, clean up
+ comment.
+ (build_x_function_call): Use cp_error.
+ (build_unary_op): Adjust call of build_component_addr.
+
+1999-04-28 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (tsubst_friend_class): Check for NULL.
+
+Wed Apr 28 11:42:22 1999 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * search.c (binfo_for_vtable): Initialize bfvi.var.
+
+1999-04-27 Nathan Sidwell <nathan@acm.org>
+
+ * rtti.c (build_x_typeid): Check rtti is enabled.
+
+1999-04-26 Mark Mitchell <mark@codesourcery.com>
+
+ * search.c (is_subobject_of_p): Make sure we're looking at the
+ right baseclasses.
+
+1999-04-26 Marc Espie <espie@cvs.openbsd.org>
+
+ * Make-lang.in (cplib2.ready): Don't depend on phony targets.
+
+1999-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (finish_file): Tweak handling of extern inlines so that
+ they are not unnecessarily put out.
+
+ * search.c (is_subobject_of_p): Handle TEMPLATE_TYPE_PARMs and
+ such as base classes.
+
+1999-04-22 Brendan Kehoe <brendan@cygnus.com>
+
+ * tree.c (build_exception_variant): Fix typo: use the chain of U,
+ not trying V, while cycling through U.
+
+1999-04-22 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_decl_flags): Remove returns_first_arg and
+ preserves_first_arg. Enlarge dummy accordingly.
+ (DECL_TINFO_FN_P): New macro.
+ (SET_DECL_TINFO_FN_P): Likeiwse.
+ (DECL_RETURNS_FIRST_ARG): Remove.
+ (DECL_PRESERVES_THIS): Likewise.
+ (DECL_INIT_PRIORITY): New macro.
+ (finish_struct_1): Change prototype.
+ (cat_namespace_levels): Remove prototype.
+ (vtable_decl_p): New prototype.
+ (vtype_decl_p): Likewise.
+ (sigtable_decl_p): Likewise.
+ (walk_globals_pred): New typedef.
+ (walk_globals_fn): Likewise.
+ (walk_globals): New prototype.
+ (walk_namespaces_fn): New typedef.
+ (walk_namespaces): New prototype.
+ (wrapup_globals_for_namespace): Likewise.
+ (walk_vtables): Remove prototype.
+ (walk_sigtables): Likewise.
+ (instantiate_pending_templates): New prototype.
+ * class.c (finish_struct_1): Don't return a value.
+ * decl.h (pending_statics): Remove declaration.
+ * decl.c (walk_namespaces_r): New function.
+ (walk_globals_r): Likewise.
+ (vtable_decl_p): Likewise.
+ (vtype_decl_p): Likewise.
+ (sigtable_decl_p): Likewise.
+ (walk_namespaces): Likewise.
+ (walk_globals_data): New type.
+ (walk_globals): New function.
+ (wrapup_globals_for_namespace): Likewise.
+ (expand_static_init): Remove assertion. Remove redundancy in
+ conditional. Don't put static data members in static_aggregates
+ Tidy.
+ (finish_function): Remove redundancy in conditional. Don't set
+ DECL_RETURNS_FIRST_ARG.
+ (cat_namespace_levels): Remove.
+ * decl2.c: Include splay-tree.h and varray.h.
+ (priority_info_s): New structure.
+ (finish_vtable_vardecl): Change prototype. Adjust for new calling
+ conventions.
+ (prune_vtable_vardecl): Likewise.
+ (finish_sigtable_vardecl): Likewise.
+ (setup_initp): Remove.
+ (do_dtors): Remove.
+ (do_ctors): Remove.
+ (start_static_storage_duration_function): New function.
+ (generate_inits_for_priority): Likewise.
+ (finish_static_storage_duration_function): Likewise.
+ (get_priority_info): Likewise.
+ (do_static_initialization): Likewise.
+ (do_static_destruction): Likewise.
+ (do_static_initialization_and_destruction): Likewise.
+ (generate_ctor_or_dtor_function): Likewise.
+ (generate_ctor_and_dtor_functions_for_priority): Likewise.
+ (pending_statics): Make it a varray.
+ (pending_statics_used): New variable.
+ (saved_inlines): Make it a varray.
+ (saved_inlines_used): New variable.
+ (finish_static_data_member): Change method of updating
+ pending_statics.
+ (mark_inline_for_output): Remove #if 0'd code. Change method of
+ updating saved_inlines.
+ (walk_vtables): Remove.
+ (walk_sigtables): Likewise.
+ (import_export_decl): Use DECL_TINFO_FN_P.
+ (pending_templates): Remove declaration.
+ (maybe_templates): Likewise.
+ (static_aggregates_initp): Likewise.
+ (setup_initp): Likewise.
+ (finish_objects): Simplify.
+ (INITIALIZE_P_IDENTIFIER): New macro.
+ (PRIORITY_IDENTIFIER): New macro.
+ (SSDF_IDENTIFIER): New macro.
+ (initialize_p_decl): New variable.
+ (priority_decl): Likewise.
+ (ssdf_decl): Likewise.
+ (priority_info_map): Likewise.
+ (finish_file): Recode output of static intializers and other
+ file-scope finalization tasks.
+ * error.c (OB_END_TEMPLATE_ID): New macro.
+ (dump_type_real): Use it.
+ (dump_decl): Likewise.
+ (dump_function_name): Likewise.
+ * lex.c (set_typedecl_interface_info): Adjust for new walk_globals
+ interface.
+ (check_newline): Use walk_globals, not walk_vtables.
+ * pt.c (pending_tempalte_expansions): Remove.
+ (set_vardecl_interface_info): Likewise.
+ (pending_templates): Make static.
+ (maybe_templates): Likewise.
+ (instantiate_class_template): Adjust call to finish_struct_1.
+ (instantiate_pending_templates): New function.
+ * rtti.c (get_tinfo_fn): Use SET_DECL_TINFO_FN_P.
+ * tree.c (static_aggregates_initp): Remove.
+ (cp_valid_lang_attribute): Don't use it; use DECL_INIT_PRIORITY
+ instead.
+ * Makefile.in (decl2.o): Depend on varray.h and splay-tree.h.
+
+ * gxx.gperf (RETURN): Rename to RETURN_KEYWORD to avoid clashes
+ with the RTL code RETURN.
+ * hash.h: Regenerated.
+ * lex.c (reinit_parse_for_block): Use RETURN_KEYWORD.
+ * parse.y: Replace RETURN with RETURN_KEYWORD throughout.
+ * parse.c: Regenerated.
+ * pt.c: Include varray.h. Include rtl.h since varray.h requires
+ it.
+ (inline_parm_levels): New variable.
+ (inline_parm_levels_used): Likewise.
+ (maybe_begin_member_template_processing): Update them.
+ (maybe_end_member_template_processing): Use them, rather than
+ guessing how many levels to pop.
+
+ * decl.c (make_typename_type): Tighten error-checking.
+
+1999-04-20 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (build_binary_op): Remove unneeded parameter.
+ * class.c (build_vrable_entry_ref): Adjust call to
+ build_binary_op.
+ * decl.c (expand_static_init): Likewise.
+ (grokdeclarator): Likewise.
+ (finish_function): Likewise.
+ * decl2.c (delete_sanity): Likewise.
+ (do_dtors): Likewise.
+ (do_ctors): Likewise.
+ * error.c (dump_type_suffix): Likewise.
+ * expr.c (cplus_expand_expr): Likewise.
+ * init.c (resolve_offset_ref): Likewise.
+ (build_new): Likewise.
+ (build_new_1): Likewise.
+ (build_vec_delete_1): Likewise.
+ (expand_vec_init_catch_clause): Likewise.
+ (build_delete): Likewise.
+ * pt.c (tsubst): Likewise.
+ * rtti.c (synthesize_tinfo_fn): Likewise.
+ * search.c (expand_upcast_fixups): Likewise.
+ (expand_direct_vtbls_init): Likewise.
+ * typeck.c (get_member_function_from_ptrfunc): Likewise.
+ (build_binary_op_nodefault): Likewise.
+ (point_int_sum): Likewise.
+ (pointer_diff): Likewise.
+ (build_unary_op): Likewise.
+ (build_modify_expr): Likewise.
+ (get_delta_difference): Likewise.
+ (build_ptrmemfunc): Likewise.
+ (expand_ptrmemfunc_cst): Likewise.
+
+1999-04-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Always call cplus_decl_attributes.
+ * decl2.c (grokfield): Pass attrlist to grokdeclarator.
+
+1999-04-19 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (finish_static_data_member_decl): New function.
+ * decl2.c (finish_static_data_member_decl): Split out from ...
+ (grokfield): Here.
+ * pt.c (instantiate_class_template): Use it here instead of
+ trying to fake it.
+ (tsubst_decl): Don't set DECL_ASSEMBLER_NAME;
+ finish_static_data_member_decl will do that. Explicit set
+ DECL_EXTERNAL to match non-template processing.
+
+1999-04-18 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (finish_class_definition): Add parameter.
+ * parse.y (structsp): Use it. Don't call pop_scope here.
+ * parse.c: Regenerated.
+ * semantics.c (finish_class_definition): Pop it here.
+
+1999-04-17 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (xref_tag): Revise handling of nested template
+ declarations.
+ * pt.c (check_explicit_specialization): Tweak handling of friend
+ templates in template classes.
+ (tsubst_friend_class): Handle friend declarations for nested
+ member template classes.
+
+1999-04-16 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (finish_struct): Remove unused variable.
+ (pushclass): Likewise.
+ (invalidate_class_lookup_cache): Likewise.
+ * cp-tree.def (TYPENAME_TYPE): Improve documentation.
+ * decl.c (build_typename_type): Make sure TYPENAME_TYPE_FULLNAME
+ doesn't get obliterated.
+ (make_typename_type): Handle template classes correctly.
+
+ * cp-tree.h (TREE_NONLOCAL_FLAG): Remove.
+ (storetags): Declare.
+ * class.c (finish_struct): Don't use TREE_NONLOCAL_FLAG.
+ (pushclass): Likewise. Use storetags to install tag declarations,
+ not pushtag.
+ (invalidate_class_lookup_cache): Don't use TREE_NONLOCAL_FLAG.
+ * decl.c (storetags): Make it global.
+ (push_class_binding): Set INHERITED_VALUE_BINDING_P for an
+ implicit typename declaration.
+ (pushtag): Tidy. Don't use TREE_NONLOCAL_FLAG.
+ * method.c (hack_identifier): Likewise.
+ * search.c (lookup_member): Likewise.
+
+ * decl.c (warn_about_implicit_typename_lookup): New function.
+ (lookup_name_real): Use it. Rework handling of implicit typename
+ extension.
+
+1999-04-15 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lookup_nested_field): Remove.
+ * class.c (push_nested_class): Handle UNION_TYPEs.
+ (pop_nested_class): Likewise.
+ * decl.c (lookup_name_real): Don't call lookup_nested_field.
+ (start_decl): Use push_nested_class, not just pushclass.
+ (cp_finish_decl): Use pop_nested_class, not just popclass.
+ * search.c (lookup_nested_field): Remove.
+
+ * cp-tree.h (lang_type): Add documentation.
+ * decl2.c (handle_class_head): Create template declarations here,
+ as appropriate.
+ * parse.y (class_head): Return whether or not we entered a new
+ scope, as well as the type named.
+ (named_class_head): Likewise.
+ (named_complex_class_head_sans_basetype): Likewise.
+ (structsp): Adjust accordingly. Pop scope when required.
+ * parse.c: Regenerated.
+ * pt.c (check_default_tmpl_args): Robustify.
+ (redeclare_class_template): Likewise.
+ (instantiate_class_template): An instantiation of an
+ anonymous union is itself an anonymous union.
+ * semantics.c (begin_class_definition): Don't create template
+ declarations here.
+
+1999-04-15 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (after_type_declarator_intern): New nonterminal.
+ (after_type_declarator): Use it.
+ (direct_after_type_declarator): Likewise. Move above
+ nonnested_type to fix reduce/reduce conflict resolution.
+ (declmods): Reducing from just 'attributes' has EMPTY precedence.
+ * Makefile.in (CONFLICTS): Update.
+
+ * decl.c (define_label): Downgrade error for jumping over a
+ non-POD decl to pedwarn.
+
+1999-04-14 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (popclass): Change declaration.
+ (pop_nested_class): Likewise.
+ (poplevel_class): Remove declaration.
+ * call.c (convert_default_argument): Pass no arguments to
+ popclass.
+ * class.c (finish_struct_1): Likewise.
+ (finish_struct): Likewise.
+ (popclass): Remove argument. Simplify code accordingly.
+ (pop_nested_class): Likewise.
+ * decl.c (poplevel_class): Declare it here, and make it static.
+ (poplevel): Handle class scopes.
+ (poplevel_class): Don't take an rgument. Simplify.
+ (pop_everything): Pass no arguments to pop_nested_class.
+ (cp_finish_decl): Pass no arguments to popclass.
+ (grokdeclarator): Pass no arguments to pop_nested_class.
+ (finish_function): Likewise.
+ * decl2.c (grokfield): Likewise.
+ (pop_scope): Pass no arguments to popclass.
+ * lex.c (do_pending_defargs): Pass no arguments to pop_nested_class.
+ * pt.c (instantiate_class_template): Move call to pushclass, and
+ document. Pass no arguments to popclass.
+ (regenerate_decl_from_template): Likewise.
+
+1999-04-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (build_unary_op): Handle taking the address of a unique
+ bound non-static member function.
+
+1999-04-13 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * lang-options.h (-Wdeprecated): New flag.
+ * decl2.c (warn_deprecated): New flag.
+ (lang_decode_option): Deprecated this-is-variable,
+ external-templates, alt-external-templates.
+ Support -Wdeprecated.
+ * errfn.c (cp_deprecated): New function.
+
+1999-04-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (setup_initp): Compare DECL_ASSEMBLER_NAME instead
+ of the decls themselves.
+
+ * pt.c (tsubst_function_type): Copy attributes over.
+
+ * tree.c (cp_valid_lang_attribute): New fn. Handle init_priority
+ and com_interface.
+ * cp-tree.h: Add prototype.
+ * decl.c (init_decl_processing): Set valid_lang_attribute.
+
+1999-04-13 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (finish_struct_1): Look at the const-ness of the field's
+ type, not the TREE_READONLY-ness of the declaration.
+ * method.c (synthesize_method): Likewise.
+ * pt.c (tsubst_decl): Call c_apply_type_quals_to_decl when
+ creating new declarations.
+
+1999-04-13 Mike Stump <mrs@wrs.com>
+
+ * decl2.c (import_export_decl): Because vtables always reference
+ virtual functions, even if they are inlined, don't allow
+ -fno-implement-inlines to not emit them, instead, emit them with
+ the vtable.
+ * decl.c (start_function): Likewise.
+
+1999-04-12 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (struct lang_type): Add com_interface.
+ (CLASSTYPE_COM_INTERFACE): New macro.
+ * class.c (set_rtti_entry): COM interface classes have no RTTI
+ entries in their vtables; adjust.
+ (add_virtual_function, finish_base_struct, skip_rtti_stuff,
+ modify_one_vtable, fixup_vtable_deltas1, override_one_vtable,
+ finish_struct_1): Likewise.
+ * decl2.c (mark_vtable_entries): Likewise.
+ * rtti.c (build_headof, get_tinfo_fn_dynamic): Likewise.
+ * search.c (get_abstract_virtuals_1, get_abstract_virtuals,
+ expand_upcast_fixups): Likewise.
+ * tree.c (debug_binfo): Likewise.
+
+ * cp-tree.h (COMPARE_NO_ATTRIBUTES): New macro.
+ * typeck.c (comptypes): If we get it, ignore attributes.
+ * class.c (instantiate_type): Use BASELINK_P. Change complain
+ parameter to flags; 2 means ignore attributes.
+ * call.c (build_op_delete_call): Pass it.
+
+ * decl.c (xref_tag): Only complain once about using a typedef-name
+ with 'struct'. Downgrade to pedwarn.
+
+ * decl.c (grokdeclarator): Allow [] syntax for zero-length array.
+
+ * parse.y (absdcl_intern): New nonterminal.
+ (absdcl, direct_abstract_declarator): Use it.
+
+ * pt.c (lookup_template_class): Look through implict typename.
+
+1999-04-11 Mark Mitchell <mark@codesourcery.com>
+
+ * friend.c (add_friend): Deal gracefully with error_mark_node.
+ * method.c (build_overload_value): Handle pointers-to-members as
+ template parameters.
+
+ * decl.c (push_binding): Fix typo in comment.
+
+1999-04-10 Mark Mitchell <mark@codesourcery.com>
+
+ * error.c (dump_type_real): If a typename is a template-id, put
+ out the template arguments.
+ (dump_expr): Handle TEMPLATE_ID_EXPR.
+ * pt.c (lookup_template_class): Now that full arguments are
+ available everywhere, remove code that tried to guess them.
+
+1999-04-09 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (make_typename_type): Complain if we don't find a type
+ when trying to make a typename type for a non-template type.
+
+1999-04-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_decl): Pass attributes to grokdeclarator.
+ (grokdeclarator): Handle attributes on constructor-syntax
+ initializers.
+
+1999-04-08 Mark Mitchell <mark@codesourcery.com>
+
+ * error.c (dump_expr): Don't crash on INDIRECT_REFs whose operands
+ don't have types.
+
+ * search.c (template_self_reference_p): Tweak.
+
+1999-04-07 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_offset_ref): Don't build yet another weird data
+ structure to describe overloaded functions.
+
+1999-04-06 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (BASELINK_P): New macro.
+ (SET_BASELINK_P): Likewise.
+ * init.c (build_member_call): Remove needless assignment in if
+ statement.
+ * search.c (lookup_field_r): Fix handling when we are looking
+ specifically for a type; these are not hidden by functions and
+ variables.
+ (lookup_member): Use SET_BASELINK_P.
+ * tree.c (is_overloaded_fn): Use BASELINK_P.
+ (really_overloaed_fn): Likewise.
+ (get_first_fn): Likewise.
+
+1999-04-05 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (lookup_name_current_level): Tweak, and improve
+ documentation.
+
+ * class.c (maybe_fixup_vptrs): Remove declaration.
+ (build_class_init_list): Likewise.
+ * decl.c (pushdecl_class_level): Call check_template_shadow here
+ ...
+ (push_class_level_binding): ... not here.
+ * search.c (dfs_push_type_decls): Only avoid
+ template-self-reference TYPE_DECLs if they are from base classes.
+
+1999-04-04 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (check_template_shadow): Don't treat OVERLOADs as _DECL
+ nodes. Tidy.
+
+1999-04-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (maybe_fixup_vptrs, build_class_init_list): Lose.
+ (finish_struct_1): Don't call build_class_init_list.
+
+1999-04-02 Mark Mitchell <mark@codesourcery.com>
+
+ * tinfo.h (__class_type_info): Fix illegal declaration.
+
+ * cp-tree.def (TEMPLATE_ID_EXPR): Update comment.
+ * cp-tree.h (INHERITED_VALUE_BINDING_P): New macro.
+ (IDENTIFIER_CLASS_VALUE): Improve documentation.
+ (is_properly_derived_from): Declare.
+ (invalidate_class_lookup_cache): Likewise.
+ (maybe_maybe_note_name_used_in_class): Likewise.
+ (note_name_declared_in_class): Likewise.
+ (push_using_decl): Remove duplicate declaration.
+ (id_in_current_class): Remove declaration.
+ (push_class_binding): Change prototype.
+ (clear_identitifer_class_values): Declare.
+ * call.c (is_properly_derived_from): Make it global.
+ (build_new_function_call): Be careful about updating candidates.
+ (build_new_method_call): Handle COMPONENT_REFs. Don't crash when
+ asked to make illegal calls.
+ * class.c: Include splay-tree.h.
+ (class_stack_node): Add names_used slot.
+ (check_member_decl_is_same_in_complete_scope): Remove.
+ (add_method): Fix comment. Push the declaration into class
+ scope.
+ (finish_struct_1): When popping the class, pop the bindings too.
+ Remove check for data member/function member conflict.
+ (finish_struct): Remove calls to
+ check_member_decl_is_same_in_complete_scope. Change calls to
+ popclass.
+ (pushclass): Clear names_used in the class stack entry.
+ Use invalidate_class_lookup_cache to remove cached entries, rather
+ than magic values with popclass. Clear IDENTIFIER_CLASS_VALUE
+ before entering a new class. Remove dead code. Don't mess with
+ current_function_decl when pushing declarations.
+ (invalidate_class_lookup_cache): New function, split out from ...
+ (popclass): Here. Clean up names_used on our way out.
+ (instantiate_type): Adjust.
+ (build_self_reference): Don't push the declaration here.
+ (maybe_note_name_used_in_class): New function.
+ (note_name_declared_in_class): Likewise.
+ * decl.c (add_binding): Change prototype.
+ (find_class_binding_level): New function.
+ (innermost_nonclass_level): Likewise.
+ (current_binding_level): Update documentation.
+ (inner_binding_level): Remove. Replace with current_binding_level
+ throughout.
+ (push_binding_level): Remove special handling of
+ class_binding_level.
+ (pop_binding_level): Likewise. Use find_class_binding_level.
+ (suspend_binding_level): Likewise.
+ (global_bindings_p): Use innermost_nonclass_level.
+ (toplevel_bindings_p): Likewise.
+ (namespace_bindings_p): Likewise.
+ (pseudo_global_level_p): Likewise.
+ (push_binding): Clear INHERITED_VALUE_BINDING_P.
+ (add_binding): Check for illegal multiple declarations. Return a
+ value indicating whether or not the new binding was legal.
+ (push_local_binding): Skip over class binding levels. Check
+ return value from add_binding.
+ (push_class_binding): Set INHERITED_VALUE_BINDING_P. Call
+ note_name_declared_in_class.
+ (pushlevel_class): Remove "fake out the rest of the compiler"
+ code.
+ (poplevel_class): Reset IDENTIFIER_CLASS_VALUEs.
+ (clear_identifier_class_values): New function.
+ (pop_from_top_level): Use it.
+ (pop_everything): Tweak.
+ (maybe_process_template_type_declaration): Don't push the
+ declaration for the template here.
+ (pushtag): Don't push tag declarations into class scope here.
+ (pushdecl): Apply DeMorgan's law for readability.
+ (pushdecl_class_level): Remove special-case code for
+ TYPE_BEING_DEFINED. Handle OVERLOADs and anonymous unions.
+ (push_class_level_bindng): Deal with inherited bindings.
+ (lookup_name_real): Remove special-case code for
+ TYPE_BEING_DEFINED, and some implicit typename magic.
+ (grokdeclarator): Handle COMPONENT_REF for a template function.
+ (build_enumerator): Don't call pushdecl_class_level here.
+ (id_in_current_class): Remove.
+ * decl2.c (grokfield): Don't call pushdecl_class_level or
+ check_template_shadow.
+ * errfn.c (cp_file_of): Don't declare.
+ (cp_line_of): Likewise.
+ * error.c (dump_decl): Handle an OVERLOAD.
+ (cp_file_of): Likewise.
+ (cp_line_of): Likewise.
+ * init.c (build_member_call): Handle a COMPONENT_REF.
+ * lex.c (do_identifier): Call maybe_note_name_used_in_class, not
+ pushdecl_class_level.
+ * method.c (hack_identifier): Build COMPONENT_REFs for references
+ to member templates as well as member functions. Remove dead
+ code.
+ * parse.y (left_curly): Remove.
+ (nonnested_type): Call maybe_note_name_used_in_class, not
+ pushdecl_class_level.
+ * parse.c: Regenerated.
+ (nested_name_specifier_1): Likewise.
+ * pt.c (check_explicit_specialization): Adjust, for robustness.
+ (check_template_shadow): Handle OVERLOADs.
+ (build_template_decl): Set DECL_CONSTRUCTOR_P on the
+ TEMPLATE_DECL, if appropriate.
+ * search.c (envelope_add_decl): Remove.
+ (dfs_pushdecls): Likewise.
+ (dfs_compress_decls): Likewise.
+ (dfs_push_decls): New function.
+ (dfs_push_type_decls): Likewise.
+ (setup_class_bindings): Likewise.
+ (template_self_reference_p): Likewise.
+ (lookup_field_r): Use it.
+ (looup_member): Remove old comment. Deal with ambiguity.
+ (push_class_decls): Use dfs_push_decls and dfs_push_type_decls,
+ and remove envelope processing.
+ * semantics.c (begin_class_definition): Let pushclass push
+ declarations for base classes.
+ (finish_member_declaration): Push declarations into class scope.
+ * typeck.c (build_component_ref): Just put an OVERLOAD into the
+ COMPONENT_REF, not a TREE_LIST of an OVERLOAD.
+ (build_x_function_call): Deal with OVERLOAD. Handle template-ids.
+ * Makefile.in (class.o): Depend on splay-tree.h.
+
+Wed Mar 31 11:30:43 1999 Nathan Sidwell <nathan@acm.org>
+
+ * cvt.c (convert_pointer_to_real): Use same_type_p.
+ * typeck.c (comp_target_types): Use same_type_p.
+
+1999-03-31 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (begin_inline_definitions,
+ finish_inline_definitions): Rename from finish_default_args and
+ begin_inline_definitions, respectively, to something that isn't a
+ total lie. :)
+ * parse.y (structsp): Adjust.
+
+ * tree.c (hash_tree_cons): Remove obsolete via_* parms.
+ (list_hash_lookup): Likewise.
+ (hash_tree_chain): Adjust.
+ * pt.c (tsubst): Adjust.
+ (tsubst_arg_types): Use plain hash_tree_cons.
+ * cp-tree.h (hash_tree_cons_simple): Lose.
+ * parse.y (declmods, nonempty_cv_qualifiers): Use hash_tree_cons.
+
+Wed Mar 31 10:48:29 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (hash.h): Generate using gperf language 'C', not
+ 'KR-C', so gperf uses the `const' keyword on strings.
+
+ * gxx.gperf (resword): Const-ify a char*.
+
+1999-03-30 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (IDENTIFIER_AS_DESC, IDENTIFIER_AS_LIST,
+ CLASSTYPE_BASELINK_VEC, CLASSTYPE_N_SUPERCLASSES,
+ CLASSTYPE_N_BASECLASSES, CLASSTYPE_MAX_DEPTH,
+ CLASSTYPE_BASE_INIT_LIST, CLASSTYPE_AS_LIST, CLASSTYPE_ID_AS_LIST,
+ CLASSTYPE_BINFO_AS_LIST): Remove cruft.
+ * class.c, lex.c, parse.y, ptree.c, search.c, semantics.c,
+ tree.c: Adjust.
+
+1999-03-29 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (lang_decode_option): Remove -Wsign-promo from -Wall.
+
+1999-03-28 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (fn_type_unification): Ignore 'this' parm from conversion ops.
+
+1999-03-27 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (add_friend): Declare.
+ (add_friends): Likewise.
+ * friend.c (add_friend): Make it global. Don't add to
+ DECL_BEFRIENDING_CLASSES if the befriending class is a template.
+ (add_friends): Make it global.
+ (make_friend_class): Don't add to DECL_BEFRIENDING_CLASSES if the
+ befriending class is a template.
+ * parse.y (component_decl_1): Fix typo in comment.
+ * parse.c: Regenerated.
+ * pt.c (instantiate_class_template): Use add_friend and
+ add_friends rather that duplicating some of their functionality
+ here.
+
+1999-03-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (build_field_call): Unify 'this' and non-'this' cases.
+
+ * typeck.c (build_indirect_ref): Check for 'this' sooner.
+
+Fri Mar 26 10:20:34 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * call.c (op_error): Const-ify a char*.
+ (add_candidate, source_type, add_warning): Add static prototype.
+ (print_z_candidates): Const-ify a char*.
+
+ * class.c (resolve_address_of_overloaded_function,
+ fixed_type_or_null, build_vtable_entry_ref): Add static prototype.
+ (get_vtable_name, finish_struct_1): Const-ify a char*.
+
+ * cvt.c (convert_to_reference): Likewise.
+
+ * decl.c (redeclaration_error_message, record_builtin_type,
+ record_unknown_type, member_function_or_else, bad_specifiers):
+ Likewise.
+ (find_binding, select_decl, unqualified_namespace_lookup,
+ lookup_flags, qualify_lookup, record_builtin_java_type, tag_name):
+ Add static prototype.
+ (warn_extern_redeclared_static, duplicate_decls, pushdecl,
+ implicitly_declare, record_builtin_java_type, define_function,
+ grok_op_properties, tag_name): Const-ify a char*.
+
+ * cp-tree.h (FORMAT_VBASE_NAME): Allow parameter `BUF' to be const.
+ (define_function, finish_builtin_type): Const-ify a char*.
+ (cp_error, cp_error_at, cp_warning, cp_warning_at, cp_pedwarn,
+ cp_pedwarn_at, cp_compiler_error, cp_sprintf): Add prototype args.
+ (file_name_nondirectory): Const-ify a char*.
+ (init_filename_times): Don't prototype.
+ (compiler_error): Prototype.
+ (yyerror, init_repo): Const-ify a char*.
+ (build_srcloc): Don't prototype.
+ (build_x_indirect_ref, build_indirect_ref, build_component_addr):
+ Const-ify a char*.
+ (warn_for_assignment): Don't prototype.
+ (convert_for_initialization, readonly_error, check_for_new_type,
+ GNU_xref_begin, GNU_xref_file, GNU_xref_ref, GNU_xref_call):
+ Const-ify a char*.
+
+ * decl2.c (acceptable_java_type, output_vtable_inherit,
+ setup_initp, start_objects, finish_objects, do_dtors, do_ctors,
+ merge_functions, decl_namespace, validate_nonmember_using_decl,
+ do_nonmember_using_decl): Add static prototype.
+ (lang_f_options): Const-ify a char*.
+ (finish_builtin_type): Likewise.
+ (add_function, arg_assoc_namespace, arg_assoc_class): Add static
+ prototype.
+
+ * errfn.c: Include cp-tree.h.
+ (cp_thing): Add static prototype.
+ (compiler_error): Don't protoptype.
+ (cp_compiler_error): Cast `compiler_error' to `errorfn' before
+ passing it to `cp_thing'.
+
+ * error.c (interesting_scope_p): Add static prototype.
+
+ * except.c (build_eh_type_type, build_eh_type_type_ref): Const-ify
+ a char*.
+
+ * init.c (compiler_error): Don't prototype.
+ (member_init_ok_or_else): Const-ify a char*.
+ (build_java_class_ref): Add static prototype.
+
+ * lex.c (compiler_error): Don't prototype.
+ (get_time_identifier, interface_strcmp, extend_token_buffer,
+ handle_cp_pragma): Const-ify a char*.
+ (is_global, init_filename_times): Add static prototype.
+ (file_name_nondirectory, cplus_tree_code_name): Const-ify a char*.
+ (compiler_error): Change from fixed args to variable args.
+ (yyerror): Const-ify a char*.
+
+ * parse.y (cond_stmt_keyword): Const-ify a char*.
+ (parse_decl): Add static prototype.
+
+ * pt.c (template_args_equal, print_template_context): Likewise.
+ (print_candidates, check_default_tmpl_args): Const-ify a char*.
+ (instantiate_class_template): Likewise.
+
+ * repo.c (get_base_filename, open_repo_file, init_repo): Likewise.
+
+ * rtti.c (call_void_fn, expand_generic_desc, expand_si_desc,
+ expand_class_desc, expand_ptr_desc, expand_attr_desc): Likewise.
+
+ * search.c (lookup_field_info, lookup_member): Likewise.
+ (lookup_member): Cast the first argument of `bzero' to a PTR.
+
+ * sig.c (compiler_error): Don't prototype.
+ (build_signature_pointer_or_reference_nam): Const-ify a char*.
+ (get_sigtable_name, build_member_function_pointer): Likewise.
+
+ * tree.c (compiler_error): Don't prototype.
+ (no_linkage_helper, build_srcloc): Add static prototype.
+ (build_vbase_pointer_fields): Const-ify a char*.
+ (__eprintf): Don't unnecessarily handle `const' when !__STDC__.
+
+ * typeck.c (compiler_error): Don't prototype.
+ (convert_for_assignment): Const-ify a char*.
+ (comp_cv_target_types): Add static prototype.
+ (build_x_indirect_ref, build_indirect_ref, convert_arguments,
+ build_component_addr, build_unary_op, convert_for_initialization):
+ Const-ify a char*.
+
+ * typeck2.c (ack): Add static prototype and change from fixed args
+ to variable args.
+ (readonly_error, check_for_new_type): Const-ify a char*.
+
+ * xref.c (_XREF_FILE, find_file, filename, fctname, declname,
+ fixname, open_xref_file, classname, GNU_xref_begin): Likewise.
+ (GNU_xref_file): Likewise. Also use `xmalloc' instead of `malloc'.
+ (GNU_xref_end_scope, GNU_xref_ref, GNU_xref_decl, GNU_xref_call,
+ gen_assign, GNU_xref_member): Const-ify a char*.
+
+1999-03-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * gxxint.texi: Remove old discussion on copying virtual bases.
+
+1999-03-25 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * Make-lang.in: Remove all references to g++.o/g++.c.
+ Link g++ from gcc.o.
+
+1999-03-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (comdat_linkage): Treat vtables like functions.
+
+1999-03-25 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (tsubst_decl): tsubst into DECL_BEFRIENDING_CLASSES.
+
+1999-03-25 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (init_decl_processing): Add `signed' type as a synonym
+ for `int'.
+
+1999-03-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (common_type): Handle cv-qual unification for pointers
+ to members.
+
+ * decl.c (unqualified_namespace_lookup): Return error_mark_node
+ on error.
+ (lookup_name_real): Set LOOKUP_COMPLAIN when *not* parsing.
+ * lex.c (do_identifier): If we got error_mark_node, call
+ lookup_name again.
+
+1999-03-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * class.c (finish_struct_1): Always reset TYPE_FIELDS for empty
+ classes.
+
+1999-03-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (lookup_name_real): Do nested field lookup regardless of
+ TYPE_BEING_DEFINED.
+
+1999-03-24 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_type): Remove has_assignment and
+ has_real_assignment. Add befriending_classes.
+ (TYPE_HAS_ASSIGNMENT): Remove.
+ (TYPE_HAS_REAL_ASSIGNMENT): Likewise.
+ (CLASSTYPE_BEFRIENDING_CLASSES): New macro.
+ (lang_decl): Document.
+ (DECL_BEFRIENDING_CLASSES): New macro.
+ (FRIEND_NAME): Move declaration to more obvious location.
+ (FRIEND_DECLS): Likewise.
+ * class.c (finish_struct_1): Don't use TYPE_HAS_REAL_ASSIGNMENT.
+ * decl.c (duplicate_decls): Copy DECL_BEFRIENDING_CLASSES.
+ (fixup_anonymous_union): Don't use TYPE_HAS_ASSIGNMENT.
+ (grok_op_properties): Likewise.
+ * friend.c (is_friend): Use FRIEND_NAME and FRIEND_DECLS.
+ (add_friend): Likewise. Don't do weird things with assignment
+ operators. Update DECL_BEFRIENDING_CLASSES.
+ (add_friends): Don't do weird things with assignment operators.
+ (make_friend_class): Likewise. Update
+ CLASSTYPE_BEFRIENDING_CLASSES.
+ * pt.c (instantiate_class_template): Don't set
+ TYPE_HAS_ASSIGNMENT.
+ (tsubst_copy): Substitute the TREE_TYPE for more unary
+ expressions.
+ * ptree.c (print_lang_type): Don't look at TYPE_HAS_ASSIGNMENT.
+ * search.c (protected_accessible_p): New function.
+ (friend_accessible_p): Likewise.
+ (accessible_p): Use them.
+
+1999-03-23 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (convert_nontype_argument): Don't create things that aren't
+ PTRMEM_CSTs when applying a qualification conversion to a
+ PTRMEM_CST.
+
+1999-03-23 Mark Mitchell <mark@codesourcery.com>
+
+ * Makefile.in (OBJS): Don't mention hash.o.
+ (OBJDEPS): Likewise.
+
+1999-03-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_file): Set at_eof to 2 after expanding ctors.
+ * decl.c (expand_static_init): Make sure we don't add any after
+ then.
+
+ * decl.c (cp_finish_decl): Move intelligence about handling
+ DECL_COMDAT for variables from here...
+ * decl2.c (comdat_linkage): ...to here.
+ (maybe_make_one_only): Tweak.
+ (import_export_decl): Call comdat_linkage for variables, too.
+ (finish_file): Handle template statics properly.
+
+1999-03-22 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (TYPE_PTRMEMFUNC_P): Use TYPE_PTRMEMFUNC_FLAG.
+ Document internals of pointer-to-member-functions.
+ (DELTA2_FROM_PTRMEMFUNC): Make it call delta2_from_ptrmemfunc.
+ (PFN_FROM_PTRMEMFUNC): Likewise.
+ (build_type_conversion): Remove unused parameter.
+ (build_ptrmemfunc1): Declare.
+ (expand_ptrmemfunc_cst): New function.
+ (delta2_from_ptrmemfunc): Likewise.
+ (pfn_from_ptrmemfunc): Likewise.
+ * cvt.c (cp_convert_to_pointer): Remove unused parameter to
+ build_type_conversion. Use TYPE_PTRMEM_P for readability.
+ (convert_to_reference): Remove unused parameter to
+ build_type_conversion.
+ (ocp_convert): Likewise.
+ (build_user_type_conversion): Likewise.
+ * error.c (dump_expr): Handle NULL pointer-to-member functions.
+ * expr.c (cplus_expand_expr): Handle PTRMEM_CSTs for functions.
+ * method.c (build_overload_value): Don't go splitting CONSTRUCTORs
+ open when handling pointer-to-member functions.
+ * pt.c (convert_nontype_argument): Clean up error messages. Be
+ more stringent with pointers-to-members.
+ * typeck.c (build_ptrmemfunc1): Don't declare. Make it global.
+ (build_unary_op): Tidy ever-so-slightly.
+ (build_conditional_expr): Remove extra parameter to
+ build_type_conversion.
+ (build_ptrmemfunc): Build PTRMEM_CSTs if we know what function
+ we're using.
+ (expand_ptrmemfunc_cst): Define.
+ (delta2_from_ptrmemfunc): Likewise.
+ (pfn_from_ptrmemfunc): Likewise.
+
+1999-03-19 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_member_call): Handle template-id expressions
+ correctly.
+ * typeck.c (build_x_function_call): Likewise.
+
+1999-03-19 Chip Salzenberg <chip@perlsupport.com>
+
+ * friend.c (make_friend_class): Avoid core dump when
+ not-yet-defined friend type lacks TYPE_LANG_SPECIFIC().
+
+1999-03-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_function): Suppress normal linkage heuristics
+ for #pragma interface under MULTIPLE_SYMBOL_SPACES.
+
+1999-03-19 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * Make-lang.in: ($(INTL_TARGETS)): Depend on cp/parse.c.
+ ($(srcdir)/cp/parse.c): Moved from ../Makefile.in.
+
+1999-03-17 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * parse.y (named_complex_class_head_sans_basetype):
+ Do not push a scope for error_mark_node.
+ (maybe_base_class_list): Likewise.
+
+ * decl.c (start_decl): Check for error_mark_node as a type.
+ Detected by g++.brendan/array-refs.C.
+ (start_decl_1): Likewise. Detected by g++.bugs/900322_01.C.
+ (maybe_build_cleanup_1): Likewise. Detected by
+ g++.jason/incomplete1.C.
+
+ * tree.c (build_dummy_object): Use void_zero_node instead of the
+ error_mark_node.
+ (is_dummy_object): Check for such a node.
+ Detected by g++.bob/inherit1.C
+
+1999-03-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * method.c (old_backref_index): Split out...
+ (flush_repeats): From here. Rename back from try_old_backref.
+ (build_mangled_name): Put back some old-style repeat handling.
+
+Mon Mar 15 21:57:16 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * lex.c: Don't include setjmp.h.
+ (parse_float): New static function.
+ (pf_args): New struct.
+ (real_yylex): Use them in call to `do_float_handler'.
+
+1999-03-15 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (xref_basetypes): Set CLASSTYPE_VBASECLASSES here.
+ * tree.c (layout_basetypes): Not here.
+ * search.c (dfs_search): Remove; no longer used.
+
+1999-03-12 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (validate_nonmember_using_decl): Issue sensible
+ error-messages on bogus qualifiers.
+
+1999-03-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (add_function_candidate): Fix uninitialized variable.
+
+ * Makefile.in (search.o): Add dependency on varray.h.
+
+1999-03-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (duplicate_decls): Use same_type_p.
+ * method.c (try_old_backref): Renamed from flush_repeats. Use
+ same_type_p. Don't try to handle repeats. Return success.
+ (is_back_referenceable_type): Return 0 if TYPE_FOR_JAVA. Support
+ calls from old-style code, too.
+ (check_ktype): Use same_type_p.
+ (check_btype): Use same_type_p. Don't pull out TYPE_MAIN_VARIANT.
+ (build_qualified_name): Simplify logic.
+ (process_overload_item): Strip typedefs and quals at the top.
+ (build_mangled_name_for_type_with_Gcode): Remove call to
+ type_canonical_variant.
+ (build_mangled_name): Likewise. Remove support for old-style
+ repeats, which have been disabled since 2.7.2. Don't mess with
+ TREE_USED.
+ (build_decl_overload_real): Don't mess with TREE_USED.
+
+1999-03-13 Nathan Sidwell <nathan@acm.org>
+
+ * error.c (cp_printers): Add 'F' escape character.
+ (dump_type_real): Remove TREE_LIST (fnargs) printing.
+ Functionality moved to dump_parameters.
+ (dump_type_suffix): Use dump_parameters and dump_exception_spec.
+ (dump_function_decl): Extend meaning of V parameter. Use
+ dump_parameters and dump_exception_spec.
+ (dump_parameters): New static function.
+ (dump_exception_spec): New static function.
+ (fndecl_as_string): Change argument semantics. Use
+ dump_function_decl directly.
+
+ * sig.c (build_signature_table_constructor): Use cp_error.
+
+1999-03-13 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * semantics.c (finish_switch_cond): Handle error cases gracefully.
+ Detected by g++.law/enum5.C.
+
+ * typeck.c (build_modify_expr): Check for errors after resolving
+ offsets. Detected by g++.brendan/static1.C.
+
+ * decl.c (complete_array_type): Ignore initial_value if it is an
+ error. Detected by g++.benjamin/17930.C.
+
+ * typeck2.c (process_init_constructor): Return error if one argument
+ is in error. Detected by g++.benjamin/13478.C.
+
+1999-03-12 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (select_decl): Allow class templates when we need types.
+ * decl2.c (ambiguous_decl): Likewise.
+
+1999-03-12 Mark Mitchell <mark@markmitchell.com>
+
+ * lex.c (do_identifier): Correct call to enforce_access.
+ * search.c (accessible_p): Tweak comment.
+
+1999-03-10 Mark Mitchell <mark@markmitchell.com>
+
+ * semantics.c (begin_class_definition): Call build_self_reference.
+ (finish_member_declaration): Set DECL_CONTEXT for TYPE_DECLs.
+
+ * search.c (assert_canonical_unmarked): Fix typo in prototype.
+
+ * search.c (dfs_canonical_queue): New function.
+ (dfs_assert_unmarked_p): Likewise.
+ (assert_canonical_unmarked): Likewise.
+ (access_in_type): Use it.
+ (accessible_p): Likewise. Walk the whole tree when umarking.
+
+ * sig.c (build_signature_table_constructor): Use accessible_p
+ instead of compute_access.
+
+1999-03-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (add_builtin_candidates): Handle overloaded conversion ops.
+
+1999-03-09 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (flag_access_control): Declare.
+ (TREE_VIA_PPUBLIC): Document.
+ (DECL_NONSTATIC_MEMBER_P): New macro.
+ (enforce_access): Return an indication of whether or not access
+ was permitted.
+ (build_self_reference): Change prototype.
+ (compute_access): Replace with ...
+ (accessible_p): New function.
+ (dfs_walk): Change prototype.
+ (dfs_unmark): Likewise.
+ (markedp): Likewise.
+ * call.c (enforce_access): Use accessible_p.
+ * class.c (build_self_reference): Insert the declaration into the
+ list of members for this type, and make it public.
+ * decl.c (xref_basetypes): Avoid ill-timed recursion.
+ * init.c (build_offset_ref): Use lookup_member, not three separate
+ name-lookups. Call enforce_access rather than checking for
+ illegal accesses here.
+ (resolve_offset_ref): Likewise.
+ * lex.c (do_identifier): Likewise.
+ * method.c (hack_identifier): Likewise.
+ * parse.y (self_reference): Remove.
+ (opt_component_decl_list): Don't use it.
+ * parse.c: Regenerated.
+ * pt.c (print_candidates): Generalize to handle lists of
+ overloaded functions.
+ (instantiate_class_template): Don't rely on TREE_VIA_PRIVATE; it's
+ not set.
+ (get_template_base): Use new calling convention for dfs_walk.
+ * search.c: Include varray.h. Add prototypes.
+ (dfs_walk): Accept a data pointer to pass to the work functions.
+ All callers changed. All work functions changed.
+ (breadth_first_search): Rename to bfs_walk, and make consistent
+ with dfs_walk.
+ (dfs_walk_real): New function.
+ (canonical_binfo): New function.
+ (context_for_name_lookup): Likewise.
+ (shared_marked_p): Likewise.
+ (shared_unmarked_p): Likewise.
+ (lokup_field_queue_p): Likewise.
+ (lookup_field_r): Generalize to handle both functions and fields.
+ (lookup_field): Just call lookup_member.
+ (lookup_fnfields): Likewise.
+ (lookup_member): Move body of lookup_field here and generalize.
+ (dfs_accessible_queue_p): Likewise.
+ (dfs_accessible_p): Likewise.
+ (dfs_access_in_type): Likewise.
+ (access_in_type): Likewise.
+ (compute_access): Remove, and replace with ...
+ (accessible_p): New function.
+ (vbase_types): Remove.
+ (vbase_decl_ptr_intermediate): Likewise.
+ (vbase_decl_ptr): Likewise.
+ (vbase_init_result): Likewise.
+ (closed_envelopes): Likewise.
+ (bvtable): Likewise.
+
+1999-03-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (add_function_candidate): Check for proper number of args
+ before checking the validity of those args.
+
+1999-03-06 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (struct lang_type): Add anon_union field.
+ (ANON_UNION_TYPE_P): Use it instead of examining type.
+ (SET_ANON_UNION_TYPE_P): New macro.
+ * decl.c (check_tag_decl): Use it.
+
+ * search.c (compute_access): Handle non-type contexts earlier, and
+ handle NULL_TREE.
+
+ * tree.c (build_exception_variant): Use copy_to_permanent.
+
+ * decl2.c (setup_initp): Give statics with no priority the default
+ priority here.
+ (do_dtors, do_ctors, finish_file): Remove special handling of
+ non-prioritized statics.
+
+1999-03-05 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (ANON_UNION_TYPE_P): Robustify.
+ * decl.c (make_typename_type): Don't issue an error if an
+ immediate lookup fails; it migt be resolved later.
+ * friend.c (is_friend): Add comment.
+ * search.c (breadth_first_search): Add POSTFN and DATA
+ parameters. Tidy. All callers changed.
+ (lookup_field_queue_p): New function.
+ (lookup_field_r): Likewise.
+ (lookup_field_post): Likewise.
+ (lookup_field): Use them, via breadth_first_search, instead of
+ duplicating logic.
+ (compute_access): Robustify.
+ (lookup_fnfield_info): New structure.
+
+1999-03-05 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst, case ARRAY_REF): Use tsubst_expr again.
+
+1999-03-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c, decl2.c, method.c, pt.c: Add 'static' to make SunOS 4
+ cc happy.
+
+ * decl2.c (import_export_class): Also return if
+ CLASSTYPE_INTERFACE_ONLY is set.
+
+1999-03-03 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (push_overloaded_decl): Only overwrite the old binding if
+ there was one.
+ * decl2.c (do_local_using_decl): Fix loop termination.
+
+1999-03-02 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (determine_specialization): Don't declare.
+ * pt.c (determine_specialization): Make it static. Eliminate
+ complain parameter. Note that decl is always non-NULL now, and
+ simplify accordingly.
+
+ * decl.c (maybe_push_to_top_level): Always call
+ push_cp_function_context.
+ (pop_from_top_level): Always call pop_cp_function_context.
+
+1999-02-26 Nathan Sidwell <nathan@acm.org>
+
+ * typeck.c (complete_type_or_else): Add VALUE arg, for helpful
+ diagnostics.
+ * cp-tree.h (complete_type_or_else): Added VALUE parameter.
+ * init.c (build_new_1): Extra arg to complete_type_or_else.
+ (build_delete): Likewise.
+ * typeck.c (require_complete_type): Likewise.
+ (pointer_int_sum): Likewise.
+ (pointer_diff): Likewise.
+ (build_component_ref): Likewise.
+
+ * typeck2.c (incomplete_type_error): Always use cp_error.
+ Show declaration of undefined type, if appropriate.
+ Deal with UNKNOWN_TYPE nodes.
+
+ * typeck.c (require_complete_type): Use TYPE_SIZE as
+ size_zero_node to mean incomplete type.
+ (require_complete_type_in_void): New function.
+ (build_compound_expr): Call complete_type_in_void for LHS.
+ (build_c_cast): Call complete_type_in_void for void cast.
+ * cvt.c (ocp_convert): Call complete_type_in_void for void cast.
+ * decl.c (cplus_expand_expr_stmt): Void expression checks moved to
+ require_complete_type_in_void. Call it.
+ * cp-tree.h (require_complete_type_in_void): Prototype new function.
+
+ * typeck.c (convert_arguments): Use alternative format for
+ function decls. Don't require_complete_type here. Simplify
+ diagnostic printing.
+ (convert_for_initialization): Don't require_complete_type on RHS yet.
+ * call.c (convert_arg_to_ellipsis): Call require_complete_type.
+
+ * call.c (build_over_call): Cope with qualified void return type.
+ * semantics.c (finish_call_expr): Likewise.
+ * typeck.c (build_function_call_real): Likewise.
+ (c_expand_return): Likewise.
+ * decl2.c (reparse_absdcl_as_expr): Cope with qualified void type.
+
+ * call.c (print_z_candidates): Use alternate print format, to be
+ consistent with (pt.c) print_candidates.
+ * method.c (hack_identifier): List candidate members.
+ * search.c (lookup_field): Build ambiguous list, and show it, if
+ ambiguous.
+
+1999-02-26 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (decay_conversion): Don't confuse constant array
+ variables with their initializers.
+
+ * decl.c (duplicate_decls): Copy DECL_TEMPLATE_INSTANTIATED when
+ merging decls.
+ * pt.c (regenerate_decl_from_template): Tweak for clarity.
+ (instantiate_decl): Mark a decl instantiated before regenerating
+ it to avoid recursion.
+ * tree.c (mapcar): Don't call decl_constant_value unless we know
+ something is TREE_READONLY_DECL_P.
+
+ * class.c (check_for_override): Don't stop checking when we find
+ the first overridden function. Delete #if 0'd code.
+ * search.c (get_matching_virtual): Likewise.
+
+1999-02-25 Richard Henderson <rth@cygnus.com>
+
+ * lang-specs.h: Define __FAST_MATH__ when appropriate.
+
+1999-02-24 Mike Stump <mrs@wrs.com>
+
+ * typeck.c (convert_for_assignment): Allow boolean integral constant
+ expressions to convert to null pointer.
+
+1999-02-24 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (lookup_namespace_name): Resolve namespace aliases.
+
+ * class.c (push_nested_class): Allow namespaces.
+
+ * decl2.c (set_decl_namespace): Add friendp parameter.
+ * decl.c (grokfndecl): Pass it.
+ (grokvardecl): Likewise.
+ * cp-tree.h: Change declaration.
+
+1999-02-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Allow an array of explicit size zero.
+
+1999-02-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * errfn.c: Change varargs code to look like toplev.c.
+
+ * method.c (process_modifiers): Don't prepend 'U' for char or
+ wchar_t.
+
+1999-02-20 Craig Burley <craig@jcb-sc.com>
+
+ * Make-lang.in (cplib2.ready): Don't consider updating
+ cplib2 stuff if the current directory isn't writable, as
+ it won't work (such as during a `make install').
Sun Feb 21 20:38:00 1999 H.J. Lu (hjl@gnu.org)
@@ -8,42 +1726,1410 @@ Sun Feb 21 20:38:00 1999 H.J. Lu (hjl@gnu.org)
destructors local to the file if ASM_OUTPUT_CONSTRUCTOR and
ASM_OUTPUT_DESTRUCTOR are defined.
-Sat Feb 20 15:08:42 1999 Jeffrey A Law (law@cygnus.com)
+1999-02-19 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (CLASSTYPE_METHOD_VEC): Adjust comment.
+ (fn_type_unification): Adjust prototype.
+ (lookup_fnfields_1): Declare.
+ * call.c (add_template_candidate_real): Adjust call to
+ fn_type_unification.
+ * class.c (add_method): Don't allow duplicate declarations of
+ constructors or destructors.
+ (resolve_address_of_overloaded_function): Remove unused variable.
+ Adjust call to fn_type_unification.
+ * decl.c (grokfndecl): Be more robust in the face of illegal
+ specializations.
+ * decl2.c (check_classfn): Remove hokey handling of member
+ templates.
+ * pt.c (determine_specialization): Improve comments. Adjust to
+ handle template argument deduction as per the standard.
+ (check_explicit_specialization): Fix comment spacing. Handle
+ type-conversion operators correctly. Improve error-recovery.
+ (fn_type_unification): Remove EXTRA_FN_ARG parameter.
+ (get_bindings_real): Simplify handling of static members.
+ * search.c (lookup_fnfields_1): Make it have external linkage.
+ * typeck.c (compparms): Fix comment.
+ (build_unary_op): Don't try to figure out which template
+ specialization is being referred to when when the address-of
+ operator is used with a template function.
+
+Thu Feb 18 23:40:01 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (lvalue_or_else): Qualify a char* with the `const'
+ keyword to match an analogous change at the top level.
+
+ * tree.c (lvalue_or_else): Likewise.
+
+1999-02-17 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (xref_basetypes): Comment.
+ * pt.c (instantiate_class_template): Use xref_basetypes.
+
+1999-02-16 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (tsubst): Change prototype.
+ (tsubst_expr): Likewise.
+ (tsubst_copy): Likewise.
+ (type_unification): Remove prototype.
+ * call.c (convert_default_arg): Adjust call to tsubst_expr.
+ * class.c (resolve_address_of_overloaded_function): Just use
+ fn_type_unification.
+ * decl.c (grokdeclarator): Adjust call to tsubst.
+ * method.c (build_template_parm_names): Likewise.
+ * pt.c (GTB_VIA_VIRTUAL): New macro.
+ (GTB_IGNORE_TYPE): Likewise.
+ (resolve_overloaded_unification): Add `complain' parameter.
+ (try_one_overload): Likewise.
+ (tsubst_template_arg_vector): Likewise.
+ (tsubst_template_parms): Likewise.
+ (tsubst_aggr_type): Likewise.
+ (tsubst_arg_types): Likewise.
+ (tsubst_call_declarator_parms): Likewise.
+ (unify): Remove explicit_mask.
+ (type_unification_real): Likewise.
+ (get_template_base_recursive): Likewise.
+ (coerce_template_template_parms): Provide prototype.
+ (tsubst_function_type): Likewise.
+ (try_class_unification): New function.
+ All callers changed to use new complain parameter.
+ (get_template_base): Use try_class_unification.
+ (unify): Adjust handling of classes derived from template types.
+ (fn_type_unification): Substitute explicit arguments before
+ unification.
+
+1999-02-16 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * decl.c (pushdecl): Remove dead code.
+
+1999-02-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_objects): Fix code I missed in previous change.
+
+1999-02-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node.
+ (grokdeclarator): Don't expect error_mark_node from grokfndecl.
+
+ * pt.c (maybe_process_partial_specialization): Complain about
+ 'template <>' on non-specialization.
+
+1999-02-10 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Catch wierd declarators.
+ * decl2.c (finish_file): Don't abort because of namespace parsing
+ failure.
+ (check_decl_namespace): Remove.
+
+1999-02-09 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (get_template_base): Don't declare.
+ (dfs_walk): Declare.
+ (dfs_unmark): Likewise.
+ (markedp): Likewise.
+ * pt.c (unify): Remove duplicate declaration. Pass tparms and
+ targs to get_template_base.
+ (get_template_base_recursive): Move here from search.c. Check to
+ see that the base found can be instantiated to form the desired
+ type.
+ (get_template_base): Likewise.
+ (get_class_bindings): Simplify.
+ * search.c (get_template_base_recursive): Move to pt.c.
+ (get_template_base): Likewise.
+ (markedp): Make it global.
+ (dfs_walk): Likewise.
+ (dfs_unmark): Likewise.
+
+1999-02-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (maybe_process_partial_specialization): Complain about
+ specialization in wrong namespace.
+ * tree.c (decl_namespace_context): New fn.
+
+1999-02-06 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * decl2.c (arg_assoc_type): Handle TEMPLATE_TEMPLATE_PARM.
+ * pt.c (coerce_template_template_parms): Handle nested
+ template template parameters.
+
+Sat Feb 6 18:08:40 1999 Jeffrey A Law (law@cygnus.com)
+
+ * typeck2.c: Update email addresses.
+
+1999-02-04 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * pt.c (unify): Call coerce_template_parms with the COMPLAIN flag
+ turned off.
+
+1999-02-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (retrofit_lang_decl): Split out...
+ (build_lang_decl): From here.
+ * decl.c (pushdecl): Call it for functions generated by the middle
+ end that don't have DECL_LANG_SPECIFIC.
+ * cp-tree.h: Declare it.
+
+ * decl2.c: Remove flag_init_priority. Always enable initp stuff.
+ (start_objects, finish_objects): Only use special
+ init_priority code if the user specified a priority.
+ (do_ctors, do_dtors): Use DEFAULT_INIT_PRIORITY for the non-initp
+ objects.
+
+Wed Feb 3 22:50:17 1999 Marc Espie <Marc.Espie@liafa.jussieu.fr>
+
+ * Make-lang.in (GXX_OBJS): Remove choose-temp.o, pexecute.o and
+ mkstemp.o. Get them from libiberty now.
+ (DEMANGLER_PROG): Simlarly, remove getopt.o getopt1.o.
+
+Tue Feb 2 22:38:48 1999 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
+
+ * decl2.c (lang_decode_option): Use read_integral_parameter.
+
+1999-02-01 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (tsubst, case TYPENAME_TYPE): Check TYPE_BEING_DEFINED
+ before calling complete_type_or_else.
+
+Mon Feb 1 09:49:52 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * input.c (inline): Don't define, its handled by system.h.
+
+Sun Jan 31 20:34:29 1999 Zack Weinberg <zack@rabi.columbia.edu>
+
+ * decl2.c: Don't define flag_no_ident here. Don't process
+ -f(no-)ident here.
+ * cp-tree.h: Don't declare flag_no_ident here.
+ * lang-specs.h: Map -Qn to -fno-ident.
+
+1999-01-28 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (struct tree_binding): Replace scope field with a union.
+ (BINDING_SCOPE): Adjust.
+ * decl.c (BINDING_LEVEL): Adjust.
+
+1999-01-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_class_template): Set up the DECL_INITIAL of
+ member constants.
+
+ * init.c (expand_member_init): Pull out TYPE_MAIN_VARIANT in
+ a ctor initializer.
+
+ * tree.c (equal_functions): Fix name in prototype.
+
+ * decl.c (push_local_binding): Add FLAGS argument.
+ (pushdecl, push_overloaded_decl): Pass it.
+ * decl2.c (do_local_using_decl): Likewise.
+ * cp-tree.h: Adjust prototype.
+ * decl.c (poplevel): Fix logic.
+
+ * decl.c (push_local_binding): Also wrap used decls in a TREE_LIST.
+ (poplevel): Handle that. Fix logic for removing TREE_LISTs.
+ (cat_namespace_levels): Don't loop forever.
+
+1999-01-25 Richard Henderson <rth@cygnus.com>
+
+ * typeck.c (build_reinterpret_cast): Fix typo in duplicated test.
+
+1999-01-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (resolve_address_of_overloaded_function): Mark the
+ chosen function used.
+
+ * call.c (build_call): Make sure that a function coming in has
+ been marked used already.
+ * decl.c (expand_static_init): Call mark_used instead of
+ assemble_external.
+ * except.c (call_eh_info, do_pop_exception, expand_end_eh_spec,
+ alloc_eh_object, expand_throw): Likewise.
+ * init.c (build_builtin_delete_call): Likewise.
+ * rtti.c (call_void_fn, get_tinfo_fn, build_dynamic_cast_1,
+ expand_si_desc, expand_class_desc, expand_ptr_desc, expand_attr_desc,
+ expand_generic_desc): Likewise.
+
+1999-01-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
- 1999-01-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
* tree.c (equal_functions): New function.
(ovl_member): Call it.
-Sat Feb 6 17:00:48 1999 Jeffrey A Law (law@cygnus.com)
+1999-01-24 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c: Update email addresses.
+ * cvt.c (cp_convert_to_pointer): Fix conversion of 0 to pmf.
+
+1999-01-25 Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (decls_match): Return 1 if old and new are identical.
+ (push_overloaded_decl): Set OVL_USED when PUSH_USING.
+
+1999-01-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_function): Make member functions one_only on windows.
+ * decl2.c (import_export_decl): Likewise.
+
+ * decl.c (grokdeclarator): Don't complain about implicit int in
+ a system header. Change same-name field check to not complain in
+ a system header instead of within extern "C".
+
+1999-01-21 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (PUSH_GLOBAL): New macro.
+ (PUSH_LOCAL): Likewise.
+ (PUSH_USING): Likewise.
+ (namespace_bindings_p): Declare.
+ (push_overloaded_decl): Likewise.
+ * decl.c (push_overloaded_decl): Don't make it static. Check for
+ illegal declarations after using declarations here.
+ (namespace_bindings_p): Likewise.
+ (duplicate_decls): Don't consider declarations from different
+ namespaces to be the same.
+ (pushdecl): Use symbolic PUSH_ constants in calls to
+ push_overloaded_decl.
+ (push_overloaded_decl_1): Likewise.
+ * decl2.c (validate_nonmember_using_decl): Tweak `std' handling.
+ (do_nonmember_using_decl): Check for illegal using declarations
+ after ordinary declarations here.
+ (do_local_using_decl): Call pushdecl to insert declarations.
+
+1999-01-21 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Fix lang_c -> lang_name_c typo.
+
+1999-01-21 Mark Mitchell <mark@markmitchell.com>
+
+ * tree.c (build_cplus_array_type_1): Don't call build_array_type
+ for types involving template parameters.
+
+ * cp-tree.h (PARM_DECL_EXPR): Delete.
+ (convert_default_arg): Change prototype.
+ (check_default_argument): Declare.
+ (search_tree): Likewise.
+ * call.c (convert_default_arg): Take the function to which the
+ default argument belongs as a parameter, and do any necessary
+ instantiation here, instead of ...
+ (build_over_call): Here.
+ * decl.c (local_variable_p): New function.
+ (check_default_argument): Likewise, split out and tidied from ...
+ (grokparms): Here.
+ * error.c (dump_expr): Don't set PARM_DECL_EXPR.
+ * pt.c (tsubst_call_declarator_parms): New function.
+ (for_each_template_parm): Handle ARRAY_REFs. Do the obvious thing
+ with CALL_EXPRs, rather than trying to be clever.
+ (tsubst): Use tsubst_call_declarator_parms.
+ * tree.c (search_tree): Don't make it static.
+ * typeck.c (convert_arguments): Use new interface to
+ convert_default_arg.
+
+1999-01-20 Mark Mitchell <mark@markmitchell.com>
+
+ * error.c (dump_function_decl): Don't print the argument types for
+ a function when the verbosity level is negative.
+
+ * call.c (build_over_call): Check format attributes at call-time.
+
+ * pt.c (tsubst_copy): Fix comment.
+ (unify): Don't allow unification with variable-sized arrays.
+
+ * semantics.c (finish_stmt_expr): When processing a template make
+ the BIND_EXPR long-lived.
+
+1999-01-19 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (finish_vtable_vardecl): Make vtables comdat here.
+ (import_export_vtable): Not here.
+
+1999-01-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (build_component_ref): Wrap an OVERLOAD around a unique
+ non-static member function.
+
+1999-01-18 Nathan Sidwell <nathan@acm.org>
+
+ * class.c (instantiate_type): Only diagnose illegal address of member
+ function if complaining.
+
+ * decl.c (lookup_name_real): Remove duplicate code.
+
+1999-01-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (copy_template_template_parm): Use permanent_obstack.
+
+1999-01-18 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * pt.c (unify): Remove restrictions on deduction of argument
+ of template template parameters.
+
+1999-01-18 Nathan Sidwell <nathan@acm.org>
+
+ * rtti.c (build_dynamic_cast_1): Resolve OFFSET_REF exprs.
+
+ * class.c (resolve_address_of_overloaded_function): Show list of
+ all candidates, when none of them match.
+
+1999-01-18 Chip Salzenberg <chip@perlsupport.com>
+
+ * typeck.c (comp_ptr_ttypes_reinterpret): Per ANSI, tighten up
+ definition of 'casting away const' in reinterpret_cast<>.
+
+1999-01-18 Graham <grahams@rcp.co.uk>
+
+ * cvt.c: Add include for decl.h, remove extern for
+ static_aggregates which is now provided by decl.h.
+
+ * Makefile.in (cvt.o): Add dependency for decl.h and missing
+ dependencies for convert.h and flags.h.
+
+1999-01-18 Nathan Sidwell <nathan@acm.org>
+
+ * decl2.c (do_dtors): Set current location to that of the
+ decl, for sensible diagnostics and debugging.
+ (check_classfn): Issue `incomplete type' error, if
+ class is not defined.
+
+1999-01-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h: Add prototype for bound_pmf_p.
+
+1999-01-16 Jason Merrill <jason@yorick.cygnus.com>
+ Manfred Hollstein <manfred@s-direktnet.de>
+
+ * decl.c (grokdeclarator): Don't make 'main(){}' an error with only
+ -Wreturn-type.
+
+1999-01-16 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (struct lang_type): Added has_mutable flag.
+ (CLASSTYPE_HAS_MUTABLE): New macro to access it.
+ (TYPE_HAS_MUTABLE_P): New macro to read it.
+ (cp_has_mutable_p): Prototype for new function.
+ * class.c (finish_struct_1): Set has_mutable from members.
+ * decl.c (cp_finish_decl): Clear decl's TREE_READONLY flag, if
+ it contains a mutable.
+ * typeck.c (cp_has_mutable_p): New function.
+
+1999-01-15 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (process_template_parm): Ignore top-level qualifiers on
+ non-type parameters.
+
+ * decl.c (start_function): Use current_function_parms in the call
+ to require_complete_type_for_parms, not the probably empty
+ DECL_ARGUMENTS.
+
+1999-01-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (finish_asm_stmt): Don't warn about redundant volatile.
+
+ * decl2.c (import_export_class): MULTIPLE_SYMBOL_SPACES only means
+ that we don't suppress the other copies.
+ * lex.c (handle_cp_pragma): Likewise.
+
+1999-01-13 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Undo 1998-12-14 change.
+ * tree.c (build_cplus_array_type_1): Likewise.
+ * pt.c (instantiate_class_template): Remove misleading comment.
+ (tsubst_aggr_type): Substitute if there are template parameters,
+ regardless of whether or not they use template arguments.
+ (unify): Likewise, but for unification.
+
+1999-01-12 Richard Henderson <rth@cygnus.com>
+
+ * cp-tree.h (flag_permissive): Declare extern.
+
+1999-01-06 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (IDENTIFIER_TYPENAME_P): Use OPERATOR_TYPENAME_FORMAT
+ here.
+ (lang_type): Add is_partial_instantiation. Decrease width of
+ dummy.
+ (PARTIAL_INSTANTIATION_P): New macro.
+ (OPERATOR_TYPENAME_P): Remove.
+ * decl.c (unary_op_p): Use IDENTIFIER_TYPENAME_P, not
+ OPERATOR_TYPENAME_P.
+ (grok_op_properties): Likewise.
+ * friend.c (do_friend): Handle friends that are member functions
+ correctly.
+ * lex.c (init_parse): Use OPERATOR_TYPENAME_FORMAT.
+ * pt.c (instantiate_class_template): Rework for clarity. Avoid
+ leaving TYPE_BEING_DEFINED set in obscure cases. Don't do
+ any more partial instantiation than is absolutely necessary for
+ implicit typename. Set PARTIAL_INSTANTIATION_P.
+ (tsubst_decl): Use IDENTIFIER_TYPENAME_P.
+ * semantics.c (begin_class_definition): Handle partial
+ specializations of a type that was previously partially
+ instantiated.
+
+Wed Jan 6 03:18:53 1999 Mark Elbrecht <snowball3@usa.net.
+
+ * g++spec.c (LIBSTDCXX): Provide default definition.
+ (lang_specific_driver): Use LIBSTDCXX instead of "-lstdc++".
+
+Tue Jan 5 22:11:25 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Make-lang.in (g++.o): Depend on prefix.h.
+
+1999-01-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (bound_pmf_p): New fn.
+ * typeck.c (build_c_cast): Use it.
+
+ * decl.c (grok_op_properties): Use same_type_p.
+
+Tue Dec 22 15:09:25 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (cvt.o): Depend on toplev.h.
+
+ * cp-tree.h (check_template_shadow, pod_type_p): Add prototypes.
+
+ * cvt.c: Include toplev.h.
+
+ * except.c (get_eh_caught, get_eh_handlers): Hide prototypes and
+ definitions.
+
+ * init.c (expand_vec_init): Initialize variable `itype'.
+
+ * lex.c (yyerror): Cast the argument passed to a ctype function to
+ an unsigned char.
+
+ * method.c (build_mangled_C9x_name): Wrap prototype and definition
+ in "HOST_BITS_PER_WIDE_INT >= 64".
+
+ * typeck.c (build_binary_op): Mark parameter `convert_p' with
+ ATTRIBUTE_UNUSED.
+
+1998-12-22 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TYPE_RAISES_EXCEPTIONS): Improve documentation.
+ * tree.c (build_exception_variant): Don't crash on empty throw
+ specs.
+
+1998-12-18 DJ Delorie <dj@cygnus.com>
+
+ * cvt.c (convert_to_reference): Check for both error_mark_node
+ and NULL_NODE after call to convert_for_initialization.
+
+1998-12-17 Jason Merrill <jason@yorick.cygnus.com>
+
+ * error.c (interesting_scope_p): New fn.
+ (dump_simple_decl): Use it.
+ (dump_expr, case CONSTRUCTOR): Force a & for a PMF.
+ (dump_expr, case OFFSET_REF): Print ->* if appropriate.
+
+1998-12-16 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (resolve_address_of_overloaded_function): Do conversion
+ to correct type here, rather than ...
+ (instantiate_type): Here.
+
+ * cp-tree.h (DECL_TEMPLATE_PARM_P): New macro.
+ (DECL_TEMPLATE_TEMPLATE_PARM_P): Use it.
+ (decl_template_parm_p): Remove.
+ * decl.c (pushdecl): Don't set DECL_CONTEXT for a template
+ parameter.
+ * lex.c (do_identifier): Use DECL_TEMPLATE_PARM_P.
+ * pt.c (push_inline_template_parms_recursive): Set it.
+ (decl_template_parm_p): Remove.
+ (check_template_shadow): Use DECL_TEMPLATE_PARM_P.
+ (process_template_parm): Set it.
+
+Wed Dec 16 16:33:58 1998 Dave Brolley <brolley@cygnus.com>
+
+ * lang-specs.h (default_compilers): Pass -MD, -MMD and -MG to cc1plus
+ if configured with cpplib.
+
+1998-12-15 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (poplevel): Make sure ns_binding is initialized.
+
+ * decl.c (finish_function): Undo inadvertent change in previous
+ patch.
+
+1998-12-14 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (pushclass): Tweak handling of class-level bindings.
+ (resolve_address_of_overloaded_function): Update pointer-to-member
+ handling.
+ (instantiate_type): Likewise.
+ * cvt.c (cp_convert_to_pointer): Likewise.
+ * decl.c (pop_binding): Take the DECL to pop, not just the name.
+ Deal with `struct stat' hack.
+ (binding_level): Add to documentation.
+ (push_binding): Clear BINDING_TYPE.
+ (add_binding): New function.
+ (push_local_binding): Use it.
+ (push_class_binding): Likewise.
+ (poplevel): Adjust calls to pop_binding.
+ (poplevel_class): Likewise.
+ (pushdecl): Adjust handling of TYPE_DECLs; add bindings for hidden
+ declarations to current binding level.
+ (push_class_level_binding): Likewise.
+ (push_overloaded_decl): Adjust handling of OVERLOADs in local
+ bindings.
+ (lookup_namespace_name): Don't crash when confronted with a
+ TEMPLATE_DECL.
+ (lookup_name_real): Do `struct stat' hack in local binding
+ contexts.
+ (build_ptrmemfunc_type): Adjust documentation.
+ (grokdeclarator): Don't avoid building real array types when
+ processing templates unless really necessary.
+ (finish_method): Adjust calls to pop_binding.
+ * decl2.c (reparse_absdcl_as_expr): Recursively call ourselves,
+ not reparse_decl_as_expr.
+ (build_expr_from_tree): Deal with a template-id as the function to
+ call in a METHOD_CALL_EXPR.
+ * pt.c (convert_nontype_argument): Tweak pointer-to-member handling.
+ (maybe_adjust_types_For_deduction): Don't do peculiar things with
+ METHOD_TYPEs here.
+ (resolve_overloaded_unification): Handle COMPONENT_REFs. Build
+ pointer-to-member types where necessary.
+ * tree.c (build_cplus_array_type_1): Don't avoid building real
+ array types when processing templates unless really necessary.
+ (build_exception_variant): Compare the exception lists correctly.
+
+1998-12-13 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.def (CPLUS_BINDING): Update documentation.
+ * cp-tree.h (LOCAL_BINDING_P): New macro.
+ (lang_identifier): Rename local_value to bindings.
+ (tree_binding): Make `scope' of type `void*', not `tree'.
+ (BINDING_SCOPE): Update documentation.
+ (IDENTIFIER_LOCAL_VALUE): Remove.
+ (IDENTIFIER_CLASS_VALUE): Document.
+ (IDENTIFIER_BINDING): New macro.
+ (IDENTIFIER_VALUE): Likewise.
+ (TIME_IDENTIFIER_TIME): Likewise.
+ (TIME_IDENTIFIER_FILEINFO): Likewise.
+ (IMPLICIT_TYPENAME_P): Likewise.
+ (set_identifier_local_value): Remove.
+ (push_local_binding): New function.
+ (push_class_binding): Likewise.
+ * class.c (pushclass): Update comments; use push_class_binding.
+ * decl.c (set_identifier_local_value_with_scope): Remove.
+ (set_identifier_local_value): Likewise.
+ (push_binding): New function.
+ (pop_binding): Likewise.
+ (binding_level): Update documentation. Remove shadowed.
+ (BINDING_LEVEL): New macro.
+ (free_binding_nodes): New variable.
+ (poplevel): Adjust for new name-lookup scheme. Don't mess up
+ BLOCK_VARs when doing for-scope extension. Remove effectively
+ dead code.
+ (pushlevel_class): Tweak formatting.
+ (poplevel_class): Adjust for new name-lookup scheme.
+ (print_binding_level): Likewise.
+ (store_bindings): Likewise.
+ (pushdecl): Likewise.
+ (pushdecl_class_level): Likewise.
+ (push_class_level_binding): Likewise.
+ (push_overloaded_decl): Update comments. Adjust for new
+ name-lookup scheme.
+ (lookup_name_real): Likewise.
+ (lookup_name_current_level): Likewise.
+ (cp_finish_decl): Likewise.
+ (require_complete_types_for_parms): Likewise. Remove misleading
+ #if 0'd code.
+ (grok_parms): Likewise. Don't call
+ require_complete_types_for_parms here.
+ (grok_ctor_properties): Don't treat templates as copy
+ constructors.
+ (grop_op_properties): Or as assignment operators.
+ (start_function): Document. Adjust for new name-lookup scheme.
+ (finish_function): Likewise.
+ * decl2.c (do_local_using_decl): Use push_local_binding.
+ * lex.c (begin_definition_of_inclass_inline): New function, split
+ out from ...
+ (do_pending_inlines): Here, and ...
+ (process_next_inline): Here.
+ (get_time_identifier): Use TIME_IDENTIFIER_* macros.
+ (init_filename_times): Likewise.
+ (extract_interface_info): Likewise.
+ (ste_typedecl_interface_info): Likewise.
+ (check_newline): Likewise.
+ (dump_time_statistics): Likewise.
+ (handle_cp_pragma): Likewise.
+ (do_identifier): Adjust for new name-lookup scheme.
+ * parse.y (function_try_block): Return ctor_initializer_opt value.
+ (fndef): Use it.
+ (fn.defpen): Pass appropriate values to start_function.
+ (pending_inline): Use functor_try_block value, and pass
+ appropriate values to finish_function.
+ * pt.c (is_member_template): Update documentation; remove handling
+ of FUNCTION_DECLs. As per name, this function should deal only in
+ TEMPLATE_DECLs.
+ (decl_template_parm_p): Change name of olddecl parameter to decl.
+ (check_template_shadow): Adjust for new name-lookup scheme.
+ (lookup_template_class): Likewise.
+ (tsubst_decl): Tweak so as not to confuse member templates with
+ copy constructors and assignment operators.
+ (unify): Handle UNION_TYPEs.
+ * ptree.c (print_lang_identifier): Adjust for new name-lookup scheme.
+ (lang_print_xnode): Adjust for new name-lookup scheme.
+ * typeck.c (mark_addressable): Likewise.
+ (c_expand_return): Likewise.
+
+1998-12-08 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Allow field with same name as class
+ in extern "C".
+
+ * decl.c (lookup_name_real): Don't limit field lookup to types.
+ * class.c (check_member_decl_is_same_in_complete_scope): No error
+ if icv and x are the same.
+ * lex.c (do_identifier): Tweak error message.
+
+1998-12-10 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (start_enum): Use push_obstacks, not
+ end_temporary_allocation.
+ (finish_enum): Call pop_obstacks.
+
+1998-12-10 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (instantiate_type): Return error_mark_node rather than
+ junk.
+
+1998-12-09 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (most_specialized_instantiation): New function.
+ (print_candidates): Likewise.
+ * class.c (validate_lhs): Remove.
+ (resolve_address_of_overloaded_function): New function, split out
+ and then substantially reworked, from ...
+ (instantiate_type): Use it. Simplify.
+ * cvt.c (convert_to_reference): Complain when caller has indicated
+ that's the right thing to do. Don't crash if instantiate_type
+ fails.
+ * pt.c: Substitute `parameters' for `paramters' throughout.
+ (print_candidates): Don't make it static.
+ (most_specialized_instantiation): Split out from ...
+ (most_specialized): Here.
+
+Wed Dec 9 15:33:01 1998 Dave Brolley <brolley@cygnus.com>
+
+ * lex.c (lang_init_options): Initialize cpplib.
+ * decl2.c (parse_options,cpp_initialized): Removed.
+ (lang_decode_option): Move initialization of cpplib to
+ lang_init_options.
+
+1998-12-09 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Update the name of the TEMPLATE_DECL, as
+ well as the TYPE_DECL, when a typedef name is assigned to a
+ previously anonymous type.
+
+1998-12-08 Andrew MacLeod <amacleod@cygnus.com>
+
+ * cp/except.c (call_eh_info): Use __start_cp_handler instead of
+ __cp_eh_info for getting the eh info pointer. Add table_index to
+ field list.
+ (push_eh_cleanup): Don't increment 'handlers' data field.
+ (process_start_catch_block): Don't set the 'caught' field.
+
+ * cp/exception.cc (CP_EH_INFO): New macro for getting the
+ exception info pointer within library routines.
+ (__cp_eh_info): Use CP_EH_INFO.
+ (__start_cp_handler): Get exception info pointer, set caught field,
+ and increment the handlers field. Avoids this being done by handlers.
+ (__uncatch_exception, __check_eh_spec): Use CP_EH_INFO macro.
+ (uncaught_exception): Use CP_EH_INFO macro.
+
+Tue Dec 8 10:48:21 1998 Jeffrey A Law (law@cygnus.com)
+
+ * Make-lang.in (cxxmain.o): Depend on $(DEMANGLE_H), not demangle.h
+
+Mon Dec 7 17:56:06 1998 Mike Stump <mrs@wrs.com>
+
+ * lex.c (check_newline): Add support for \ as `natural'
+ characters in file names in #line to be consistent with #include
+ handling. We support escape processing in the # 1 "..." version of
+ the command. See also support in cp/lex.c.
+
+1998-12-07 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * cp/decl2.c: s/data/opts/ when initializing cpp_reader
+ structure.
+
+1998-12-07 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (build_typename_type): Set DECL_ARTIFICIAL.
+
+ * error.c (dump_simple_decl): Also print namespace context.
+ (dump_function_decl): Likewise.
+
+ * decl2.c (ambiguous_decl): Don't print old value if it's
+ error_mark_node.
+
+ * decl.c (lookup_name_real): Fix handling of local types shadowed
+ by a non-type decl. Remove obsolete code.
+ * cp-tree.h (DECL_FUNCTION_SCOPE_P): New macro.
+
+ * lang-options.h: Add -fpermissive.
+ * decl2.c: Likewise.
+ * cp-tree.h: Add flag_permissive.
+ * decl.c (init_decl_processing): If neither -fpermissive or -pedantic
+ were specified, set flag_pedantic_errors.
+ * call.c (build_over_call): Turn dropped qualifier messages
+ back into pedwarns.
+ * cvt.c (convert_to_reference): Likewise.
+ * typeck.c (convert_for_assignment): Likewise.
+
+1998-12-05 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (coerce_new_type): Use same_type_p.
+ (coerce_delete_type): Likewise.
+
+ * call.c (check_dtor_name): Return 1, not error_mark_node.
+
+1998-12-04 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (handle_cp_pragma): Disable #pragma interface/implementation
+ if MULTIPLE_SYMBOL_SPACES.
+
+ * pt.c (check_template_shadow): New fn.
+ * decl2.c (grokfield): Use it.
+ * decl.c (pushdecl): Likewise.
+ (pushdecl_class_level): Likewise.
+ (start_method): Likewise.
+ (xref_tag): Don't try to use 't' if we're defining.
+
+ * call.c (check_dtor_name): Just return an error_mark_node.
+ * pt.c (lookup_template_class): Complain about using non-template here.
+ * parse.y (apparent_template_type): Not here.
+
+ * pt.c (check_explicit_specialization): Complain about specialization
+ with C linkage.
+
+ * lang-options.h: Add -f{no-,}implicit-inline-templates.
+
+ * pt.c (convert_nontype_argument): Don't assume that any integer
+ argument is intended to be a constant-expression.
+
+1998-12-03 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (handle_using_decl): Fix comment. Don't lookup
+ constructors in base classes.
+ (validate_lhs): Fix typo in comment.
+ * search.c (lookup_field_1): Don't return a USING_DECL.
+
+ * cp-tree.h (DECL_ACCESS): Improve documentation.
+
+ * decl.c (expand_static_init): Don't set the initialization-done
+ flag until the initialization is done.
+
+1998-12-02 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (validate_nonmember_using_decl): Complain about using
+ declarations for class members.
+
+1998-11-29 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck2.c (process_init_constructor): Use same_type_p.
+
+ * decl.c (check_tag_decl): Don't warn about null decl inside a
+ class.
+
+ * pt.c (unify, case OFFSET_TYPE): Pass down 'strict' rather than
+ UNIFY_ALLOW_NONE.
+ (convert_nontype_argument): Use TYPE_PTRMEMFUNC_FN_TYPE.
+ (resolve_overloaded_unification): Strip baselinks.
+
+Fri Nov 27 13:07:23 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * g++spec.c: Don't prototype xmalloc.
+
+1998-11-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * except.c (expand_throw): Use TYPE_PTR_P to check for pointers.
+
+ * decl.c (check_tag_decl): Do complain about null friend decl at
+ file scope.
+
+1998-11-25 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
+
+ * lex.c (make_lang_type): Clear the whole struct lang_type, not
+ only the first multiple of sizeof (int).
+
+1998-11-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_decl): An explicit specialization of a static data
+ member is only a definition if it has an initializer.
+
+ * except.c (expand_throw): Use cp_finish_decl for the throw temp.
+ * cvt.c (build_up_reference): Pass DIRECT_BIND down into
+ cp_finish_decl.
+ * init.c (expand_default_init): Check for DIRECT_BIND instead of
+ DECL_ARTIFICIAL.
+
+ * call.c (build_over_call): Use build_decl.
+
+ * except.c (expand_throw): Just use convert, not
+ build_reinterpret_cast.
+
+ * lex.c (handle_generic_pragma): Use token_buffer.
+
+ * decl.c (check_tag_decl): Don't complain about null friend decl.
+
+1998-11-24 Dave Pitts <dpitts@cozx.com>
+
+ * Make-lang.in (DEMANGLER_PROG): Move the output arguments to the
+ first position.
+ * lex.c (check_newline): Use ISALPHA.
+ (readescape): Use ISGRAPH.
+ (yyerror): Use ISGRAPH.
+
+1998-11-24 Nathan Sidwell <nathan@acm.org>
+
+ * search.c (get_abstract_virtuals): Do not use initial
+ CLASSTYPE_ABSTRACT_VIRTUALS.
+ * typeck2.c (abstract_virtuals_error): Show location of abstract
+ declaration.
+ * call.c (build_new_method_call): Use
+ CLASSTYPE_ABSTRACT_VIRTUAL, rather than recalculate.
+ * class.c (finish_struct_bits): Don't bother working out whether
+ get_abstract_virtuals will do anything, just do it.
+
+1998-11-24 Graham <grahams@rcp.co.uk>
+
+ * typeck.c (build_component_ref): Remove unused statement.
+
+1998-11-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c (add_method): Catch invalid overloads.
+
+ * class.c (add_method): Build up OVERLOADs properly for conversion ops.
+ * search.c (lookup_conversions): Handle getting real OVERLOADs.
+ (add_conversions): Likewise. Revert last change.
+ * call.c (add_conv_candidate): Pass totype to add_candidate instead
+ of fn. Don't add a new candidate if the last one was for the same
+ type.
+ (print_z_candidates): Handle getting a type as a function.
+ (joust): If we got two conversion candidates to the same type,
+ just pick one.
+ (build_object_call): Lose 'templates'.
+ (build_user_type_conversion_1): Handle getting real OVERLOADs.
+
+1998-11-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck2.c (process_init_constructor): If there are elements
+ that don't have initializers and they need to have constructors
+ run, supply them with initializers.
+
+ * class.c (finish_struct_1): A class with a 0-width bitfield is
+ still empty.
+
+1998-11-23 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (instantiate_class_template): Don't try to figure out what
+ specialization to use for a partial instantiation. Correct
+ typos in a couple of comments. Avoid calling uses_template_parms
+ multiple times.
+
+1998-11-23 Benjamin Kosnik <bkoz@cygnus.com>
+
+ * method.c (process_overload_item): Add call to
+ build_mangled_C9x_name for intTI_type_nodes.
+ (build_mangled_C9x_name): Add prototype, define.
+ * decl.c (init_decl_processing): Add names for
+ TImode_type_node.
+
+1998-11-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (named_class_head): Update CLASSTYPE_DECLARED_CLASS.
+
+ * class.c (finish_struct_1): Set things up for 0-width bitfields
+ like we do for others.
+
+ * decl.c (check_tag_decl): New fn.
+ (shadow_tag): Split out from here.
+ * decl2.c (grok_x_components): Call it.
+
+1998-11-22 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c: Lose warn_about_return_type.
+ (grokdeclarator): Always complain about implicit int, except for
+ `main () { ... }'.
+
+ * decl.c (tag_name): New fn.
+ (xref_tag): Complain about using typedef-name after class-key.
+
+ * init.c (expand_vec_init): Also keep going if from_array.
+
+ * tree.c (is_overloaded_fn): Also handle the output of
+ build_offset_ref.
+
+ * decl.c (grokdeclarator): Use constructor_name when comparing
+ field name against enclosing class.
+ * class.c (finish_struct_anon): Likewise.
+
+1998-11-22 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (poplevel): Remove code to handle KEEP == 2.
+ (finish_function): Don't confuse BLOCK-order when
+ processing a destructor.
+
+1998-11-21 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (require_complete_types_for_parms): Call layout_decl
+ after we've completed the type.
+
+1998-11-21 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl2.c (validate_nonmember_using_decl): Allow using templates
+ from the global namespace.
+
+1998-11-21 Jason Merrill <jason@yorick.cygnus.com>
+
+ Handle specifying template args to member function templates.
+ * tree.c (build_overload): Always create an OVERLOAD for a template.
+ * search.c (add_conversions): Handle finding an OVERLOAD.
+ * decl2.c (check_classfn): Likewise.
+ * lex.c (identifier_type): See through a baselink.
+ * parse.y (do_id): Don't call do_identifier if we got a baselink.
+ * class.c (instantiate_type, case TREE_LIST): Recurse.
+
+ * decl.c (grokdeclarator): Allow a boolean constant for array
+ bounds, odd as that sounds.
+
+ * pt.c (unify): Be more strict about non-type parms, except for
+ array bounds.
+ (UNIFY_ALLOW_INTEGER): New macro.
+
+1998-11-19 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * Make-lang.in (mandir): Replace all uses of $(mandir) by $(man1dir).
+
+1998-11-19 Jason Merrill <jason@yorick.cygnus.com>
+
+ * semantics.c (begin_class_definition): Call
+ maybe_process_partial_specialization before push_template_decl.
+ Don't call push_template_decl for a specialization.
+ * search.c (lookup_field): Do return a member template class.
+ * decl2.c (handle_class_head): Handle member template classes.
+
+ * decl.c (grokdeclarator): A parm type need not be complete.
+
+ * pt.c (convert_nontype_argument): Fix thinko.
+
+1998-11-18 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (PTRMEM_CST_CLASS): Fix typo.
+ (global_delete_fndecl): New variable.
+ * decl.c (global_delete_fndecl): Define it.
+ (init_decl_processing): Set it.
+ * init.c (build_builtin_delete_call): Use it.
+ * tree.c (mapcar): Recursively call mapcar for the type of EXPR
+ nodes.
+
+1998-11-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (cplus_expand_expr_stmt): Always complain about unresolved
+ type.
+
+ * tree.c (lvalue_p_1): An INDIRECT_REF to a function is an lvalue.
+ * call.c (build_object_call): Also support references to functions.
+ * typeck.c (convert_for_initialization): Don't decay a function
+ if the target is a reference to function.
+
+ * search.c (add_conversions): Get all the overloads from a class.
+
+ * decl.c (grok_ctor_properties): Complain about any constructor
+ that will take a single arg of the class type by value.
+
+ * typeck2.c (build_functional_cast): Can't create objects of
+ abstract classes this way.
+ * cvt.c (ocp_convert): Likewise.
+
+ * decl.c (grokfndecl): Member functions of local classes are not
+ public.
+
+1998-11-18 Mark Mitchell <mark@markmitchell.com>
+
+ * Make-lang.in (cc1plus): Add dependency on hash.o.
+
+1998-11-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * search.c (get_abstract_virtuals): Complain about virtuals with
+ no final overrider.
+ * typeck2.c (abstract_virtuals_error): Remove handling for virtuals
+ with no final overrider.
+ * class.c (override_one_vtable): Don't set DECL_ABSTRACT_VIRTUAL_P
+ on virtuals with no final overrider.
+
+ * lex.c (reinit_parse_for_block): Add a space after the initial ':'.
+
+ * class.c (finish_struct_1): Don't remove zero-width bit-fields until
+ after layout_type.
+
+ * friend.c (do_friend): Don't set_mangled_name_for_decl.
+
+ * class.c (finish_struct_anon): Complain about non-fields.
+ * decl2.c (build_anon_union_vars): Likewise.
+
+ * decl.c (grokdeclarator): Normal data members can't have the same
+ name as the class, either.
+ * class.c (finish_struct_anon): Neither can members of an
+ anonymous union.
+
+1998-11-17 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TYPE_ALIAS_SET): Document language-dependent uses.
+ (TYPE_BINFO): Likewise.
+ (IS_AGGR_TYPE): Tweak.
+ (SET_IS_AGGR_TYPE): New macro.
+ (CLASS_TYPE_P): Tweak.
+ (lang_type): Group mark bitfields together. Remove linenum.
+ (CLASSTYPE_SOURCE_LINE): Remove macro.
+ (CLASSTYPE_MARKED_N): New macro.
+ (SET_CLASSTYPE_MARKED_N): Likewise.
+ (CLEAR_CLASSTYPE_MARKED_N): Likewise.
+ (CLASS_TYPE_MARKED_*): Use them.
+ (SET_CLASSTYPE_MARKED_*): Likewise.
+ (CLEAR_CLASSTYPE_MARKED_*): Likewise.
+ (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO): Likewise.
+ (TYPE_TEMPLATE_INFO): Handle TEMPLATE_TEMPLATE_PARMs as well.
+ (TYPENAME_TYPE_FULLNAME): Use TYPE_BINFO rather than CLASSTYPE_SIZE.
+ * class.c (class_cache_obstack): New variable.
+ (class_cache_firstobj): Likewise.
+ (finish_struct): Don't set CLASSTYPE_SOURCE_LINE.
+ (pushclass): Free the cache, when appropriate.
+ (popclass): Tidy.
+ (maybe_push_cache_obstack): Use class_cache_obstack.
+ * decl.c (include hash.h).
+ (typename_hash): New function.
+ (typename_compare): Likewise.
+ (build_typename_type): Check the hash table to avoid creating
+ duplicates.
+ (build_ptrmemfunc_type): Use SET_IS_AGGR_TYPE.
+ (grokdeclarator): Use CLASS_TYPE_P.
+ (xref_basetypes): Likewise.
+ (start_function): Likewise. Don't put current_class_ref on the
+ permanent obstack.
+ * error.c (dump_type_real): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO
+ and TYPE_TI_ARGS.
+ * lex.c (note_got_semicolon): Use CLASS_TYPE_P.
+ (make_lang_type): Don't create TYPE_LANG_SPECIFIC and associated
+ fields for types other than class types. Do clear TYPE_ALIAS_SET
+ for types other than class types, though.
+ * method.c (build_overload_identifier): Use CLASS_TYPE_P and
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+ * pt.c (process_template_parm): Don't set
+ CLASSTYPE_GOT_SEMICOLON.
+ (lookup_template_class): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+ Coerce arguments on the momentary obstack.
+ (for_each_template_parm): Use TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+ (instantiate_class_template): Calculate template arguments on the
+ momentary obstack. Tidy.
+ (tsubst_template_arg_vector): Use make_temp_vec.
+ (tsubst_aggr_type): Put template arguments on the momentary
+ obstack.
+ (tsubst_decl): Likewise.
+ (tsubst): Copy the array bounds index to the permanent obstack
+ before building index types. Use new macros.
+ (unify): Use new macros.
+ (do_type_instantiation): Likewise.
+ * search.c (lookup_fnfields_1): Use new macros.
+ (dfs_pushdecls): Build envelopes on the cache obstack.
+ (dfs_compress_decls): Use new macros.
+ (push_class_decls): Build on the cache obstack.
+ * semantics.c (finish_typeof): Don't set CLASSTYPE_GOT_SEMICOLON.
+ * sign.c (build_signature_pointer_or_reference_type): Use
+ SET_IS_AGGR_TYPE.
+ * tree.c (make_binfo): Check CLASS_TYPE_P.
+ (copy_template_template_parm): Adjust.
+ (make_temp_vec): Use push_expression_obstack.
+ * typeck.c (complete_type): Use new macros.
+ (comptypes): Likewise.
+
+1998-11-17 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Add diagnostics for invalid array, reference
+ and pointer to member types.
1998-11-16 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (my_friendly_abort): Don't fatal twice in a row.
+ * typeck.c (c_expand_start_case): Use build_expr_type_conversion.
+ Simplify.
+
+ * parse.y (structsp): Fix cut-and-paste error.
+
+ * init.c (build_new): Complain about non-integral size.
+
+ * parse.y (unary_expr): Complain about defining types in sizeof.
+
+ * typeck.c (expr_sizeof): Complain about sizeof an overloaded fn.
+
+ * rtti.c (build_x_typeid): Complain about typeid without
+ including <typeinfo>.
+ (get_typeid): Likewise. Complain about typeid of incomplete type.
+ (get_tinfo_fn_dynamic): Likewise.
+ (get_typeid_1): Not static anymore.
+ * except.c (build_eh_type_type): Use get_typeid_1.
+
+ * rtti.c (build_dynamic_cast_1): Give errors for dynamic_cast to
+ ambiguous or private bases. Fix warning for reference cast.
+
+1998-11-16 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro.
+ * decl.c (duplicate_decls): Remove special-case code to deal with
+ template friends, and just do the obvious thing.
+ * pt.c (register_specialization): Tweak for clarity, and also to
+ clear DECL_INITIAL for an instantiation before it is merged with a
+ specialization.
+ (check_explicit_specialization): Fix indentation.
+ (tsubst_friend_function): Handle both definitions in friend
+ declaration and outside friend declarations.
+ (tsubst_decl): Don't clear DECL_INITIAL for an instantiation.
+ (regenerate_decl_from_template): Tweak accordingly.
+ (instantiate_decl): Likewise.
+
+1998-11-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (cplus_expand_expr_stmt): Promote warning about naked
+ member function reference to error.
+ * cvt.c (ocp_convert): Complain about converting an overloaded
+ function to void.
+
+ * init.c (build_offset_ref): Just return a lone static member
+ function.
+
+ * decl.c (cp_finish_decl): Only complain about real CONSTRUCTORs,
+ not internal ones.
+
+ * typeck.c (build_binary_op_nodefault): Improve error handling.
+
+ * decl.c (grokfndecl): Complain about making 'main' a template.
+
+ * typeck.c (string_conv_p): Don't convert from wchar_t[] to char*.
+
+ * call.c (build_method_call): Handle a BIT_NOT_EXPR around a
+ TYPE_DECL in a template.
+
1998-11-15 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (my_friendly_abort): Add URL in the other case, too.
-1998-11-13 Jason Merrill <jason@yorick.cygnus.com>
+ * decl.c (struct cp_function): Add named_label_uses.
+ (push_cp_function_context): Save it.
+ (pop_cp_function_context): Restore it.
+ (define_label): Also complain about jumping into the scope of
+ non-POD objects that don't have constructors.
+ * tree.c (pod_type_p): New fn.
+ * pt.c (instantiate_class_template): Clear TYPE_BEING_DEFINED sooner.
* rtti.c (synthesize_tinfo_fn): Call import_export_decl here.
(get_tinfo_fn): Not here.
+ * repo.c (repo_get_id): Abort if we get called for an incomplete
+ type.
+
+1998-11-13 Mark Mitchell <mark@markmitchell.com>
+
+ * except.c (expand_throw): Make sure first argument to
+ __cp_push_exception is of type `void*' to avoid spurious error
+ messages.
+
+1998-11-11 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (try_one_overload): Take orig_targs again. Only check for
+ mismatches against them; we don't care what a previous call found.
+ (resolve_overloaded_unification): Adjust.
+
+ * search.c (lookup_field): Don't return anything for a non-type
+ field from a dependent type.
+ * decl.c (grokdeclarator): Resolve SCOPE_REFs of the current class
+ in an array declarator.
+ (start_decl): Push into the class before looking for the field.
1998-11-08 Mark Mitchell <mark@markmitchell.com>
- * decl.c (grokdeclarator): Tighten checks for invalid
- destructors. Improve error-messages and error-recovery.
- * decl2.c (check_classfn): Don't assume that mangled destructor
- names contain type information.
+ * method.c (build_overload_value): Handle REFERENCE_TYPE.
+
+1998-11-08 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (grokdeclarator): Allow namespace-scoped members if they
+ are friends.
+
+1998-11-08 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst_decl): Don't mess with the global value of an
+ un-mangled DECL_ASSEMBLER_NAME.
+
+1998-11-03 Christopher Faylor <cgf@cygnus.com>
+
+ * decl.c (init_decl_processing): Remove CYGWIN conditional
+ since CYGWIN is now able to deal with trapping signals.
+
+Sat Nov 7 15:48:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h: Don't include gansidecl.h.
+ * exception.cc: Include gansidecl.h (since we don't include config.h)
+ * g++spec.c: Don't include gansidecl.h.
+
+1998-11-06 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (lang_decl_flags): Add defined_in_class. Decrease
+ size of dummy.
+ (DECL_DEFINED_IN_CLASS_P): New macro.
+ (TEMPLATE_PARMS_FOR_INLINE): Document.
+ (check_static_variable_definition): New function.
+ * decl.c (cp_finish_decl): Set DECL_DEFINED_IN_CLASS_P, if
+ appropriate.
+ (check_static_variable_definition): Split out from ...
+ (grokdeclarator): Here.
+ * pt.c (check_default_tmpl_args): New function, split out from ...
+ (push_template_decl_real): Here.
+ (instantiate_template): Fix comment.
+
+1998-11-04 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (CP_TYPE_CONST_P): Make {0,1}-valued.
+ (CP_TYPE_VOLATILE_P): Likewise.
+ (CP_TYPE_RESTRICT_P): Likewise.
+
+1998-11-03 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (tsubst): Use build_index_type, not build_index_2_type.
1998-11-02 Jason Merrill <jason@yorick.cygnus.com>
+ * class.c (instantiate_type): Be more helpful.
+
* decl2.c (import_export_decl): Call import_export_class.
+ * cp-tree.h (EMPTY_CONSTRUCTOR_P): Check !TREE_HAS_CONSTRUCTOR.
+ * decl2.c (build_expr_from_tree): Propagate TREE_HAS_CONSTRUCTOR.
+ * pt.c (tsubst_copy): Likewise.
+
+1998-11-02 Mark Mitchell <mark@markmitchell.com>
+
+ * init.c (expand_vec_init): Fix off-by-one error.
+
+1998-11-02 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * parse.y (apparent_template_type): New type.
+ (named_complex_class_head_sans_basetype): Use it.
+ * Makefile.in (CONFLICTS): One new conflict.
+ * parse.c: Regenerated.
+
+1998-11-01 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (COMPARE_STRICT): New macro.
+ (COMPARE_BASE): Likewise.
+ (COMPARE_RELAXED): Likewise.
+ (COMPARE_REDECLARATION): Likewise.
+ (same_type_p): Likewise.
+ (same_or_base_type_p): Likewise.
+ * call.c (standard_conversion): Use them, in place of comptypes
+ with numeric arguments.
+ (reference_binding): Likewise.
+ (convert_like): Likewise.
+ (build_over_call): Likewise.
+ (is_subseq): Likewise.
+ (is_properly_derived_from): Likewise.
+ (compare_ics): Likewise.
+ (joust): Likewise.
+ * class.c (delete_duplicate_fields_1): Likewise.
+ (resolves_to_fixed_type_p): Likewise.
+ (instantiate_type): Likewise. Remove #if 0'd code.
+ * decl.c (decls_match): Likewise. Use COMPARE_REDECLARATION here.
+ (pushdecl): Likewise.
+ (lookup_name_real): Likewise.
+ (grokdeclarator): Likewise. Check for illegal array declarations.
+ (grokparms): Likewise.
+ (grok_op_properties): Likewise.
+ * decl2.c (check_classfn): Likewise.
+ * friend.c (is_friend): Likewise.
+ (make_friend_class): Likewise.
+ * init.c (expand_aggr_init): Likewise.
+ (expand_vec_init): Likewise.
+ * pt.c (is_member_template_class): Remove declaration.
+ (is_specialization_of): Use COMPARE_* and new macros.
+ (comp_template_parms): Likewise.
+ (convert_nontype_argument): Likewise.
+ (coerce_template_template_parms): Likewise.
+ (template_args_equal): Likewise.
+ (lookup_template_class): Likewise.
+ (type_unification_real): Likewise.
+ (unify): Likewise.
+ (get_bindings_real): Likewise.
+ * search.c (covariant_return_p): Likewise.
+ (get_matching_virtual): Likewise.
+ * sig.c (match_method_types): Likewise.
+ * tree.c (vec_binfo_member): Likewise.
+ (cp_tree_equal): Likewise.
+ * typeck.c (common_type): Likewise.
+ (comp_array_types): Likewise. Get issues involving unknown array
+ bounds right.
+ (comptypes): Update comments. Use new flags.
+ (comp_target_types): Use new macros.
+ (compparms): Likewise.
+ (comp_target_parms): Likewise.
+ (string_conv_p): Likewise.
+ (build_component_ref): Likewise.
+ (build_indirect_ref): Likewise.
+ (build_conditional_expr): Likewise.
+ (build_static_cast): Likewise.
+ (build_reinterpret_cast): Likewise.
+ (build_const_cast): Likewise.
+ (build_modify_expr): Likewise.
+ (convert_for_assignment): Likewise.
+ (comp_ptr_ttypes_real): Likewise.
+ (ptr_reasonably_similar): Likewise.
+ (comp_ptr_ttypes_const): Likewise.
+
+1998-10-31 Jason Merrill <jason@yorick.cygnus.com>
+
+ * rtti.c (build_dynamic_cast_1): Fix cut-and-paste error.
+
+1998-10-30 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (delete_sanity): Pass integer_zero_node, not
+ integer_two_node, to build_vec_delete.
+ * init.c (build_array_eh_cleanup): Remove.
+ (expand_vec_init_try_block): New function.
+ (expand_vec_init_catch_clause): Likewise.
+ (build_vec_delete_1): Don't deal with case that auto_delete_vec
+ might be integer_two_node anymore.
+ (expand_vec_init): Rework for initialization-correctness and
+ exception-correctness.
+ * typeck2.c (process_init_constructor): Make mutual exclusivity
+ of cases more obvious.
+
+1998-10-29 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (lookup_name_real): OK, only warn if not lexing.
+ Simplify suggested fix.
+
+ * cp-tree.h (IDENTIFIER_MARKED): New macro.
+ * search.c (lookup_conversions): Use breadth_first_search.
+ (add_conversions): Avoid adding two conversions to the same type.
+ (breadth_first_search): Work with base binfos, rather
+ than binfos and base indices.
+ (get_virtual_destructor): Adjust.
+ (tree_has_any_destructor_p): Adjust.
+ (get_matching_virtual): Adjust.
+
+ * pt.c (push_template_decl_real): Generalize check for incorrect
+ number of template parms.
+ (is_member_template_class): #if 0.
+
+1998-10-29 Richard Henderson <rth@cygnus.com>
+
+ * Makefile.in (cc1plus): Put CXX_OBJS, and thence @extra_cxx_objs@,
+ last.
+
+1998-10-28 Zack Weinberg <zack@rabi.phys.columbia.edu>
+
+ * lex.c: Call check_newline from lang_init always. After
+ calling cpp_start_read, set yy_cur and yy_lim to read from the
+ cpplib token buffer.
+
1998-10-28 Jason Merrill <jason@yorick.cygnus.com>
+ * class.c (instantiate_type): Don't consider templates for a normal
+ match.
+
* class.c (finish_struct_1): Don't complain about non-copy
assignment ops in union members.
@@ -54,99 +3140,1872 @@ Sat Feb 6 17:00:48 1999 Jeffrey A Law (law@cygnus.com)
(finish_prevtable_vardecl): Lose.
(finish_file): Don't call it.
* pt.c (instantiate_class_template): Likewise.
+ * cp-tree.h: Remove it.
+
+ * init.c (build_delete): Reset TYPE_HAS_DESTRUCTOR here.
+ * decl.c (finish_function): Not here.
+ (start_function): Do set DECL_INITIAL.
+
+ * pt.c (push_template_decl_real): Complain about default template
+ args for enclosing classes.
+
+ * call.c (add_function_candidate): Treat conversion functions
+ as coming from the argument's class.
+ * cp-tree.h (DECL_CONV_FN_P): New fn.
+ (DECL_DESTRUCTOR_P): Also check DECL_LANGUAGE.
+ * class.c (add_method): Use DECL_CONV_FN_P.
+ * decl2.c (check_classfn): Likewise.
+ * error.c (dump_function_name): Likewise.
+ (dump_function_decl): Likewise.
+ * pt.c (fn_type_unification): Likewise.
+ * search.c (add_conversions): Likewise.
+
+1998-10-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (do_identifier): Also generate LOOKUP_EXPR for RESULT_DECL.
+ * method.c (hack_identifier): Also check for using RESULT_DECL
+ from outer context.
+
+1998-10-27 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Use type_quals, rather than constp,
+ consistently.
+
+1998-10-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * call.c (standard_conversion): instantiate_type here.
+ (reference_binding): And here.
+ (implicit_conversion): Not here.
+ (build_op_delete_call): No need to cons up an OVERLOAD.
+ * cvt.c (cp_convert_to_pointer): instantiate_type here.
+ (convert_to_reference): And here.
+ * decl.c (grok_reference_init): Not here.
+ (grokparms): Or here.
+ * typeck2.c (digest_init): Or here.
+ * typeck.c (decay_conversion): Take the address of overloaded
+ functions, too.
+ (require_instantiated_type): Lose.
+ (convert_arguments): Don't handle unknown types here.
+ (build_c_cast): Likewise.
+ (build_binary_op): Gut.
+ (build_conditional_expr): Don't require_instantiated_type.
+ (build_modify_expr): Likewise.
+ (build_static_cast): Don't instantiate_type.
+ (build_reinterpret_cast): Likewise.
+ (build_const_cast): Likewise.
+ (convert_for_initialization): Likewise.
+ (build_ptrmemfunc): Use type_unknown_p.
+ (convert_for_assignment): Also do default_conversion on overloaded
+ functions. Hand them off to ocp_convert.
+
+1998-10-26 Mark Mitchell <mark@markmitchell.com>
+
+ * error.c (dump_decl): Deal with TEMPLATE_DECLs that are
+ VAR_DECLs. Handle vtables whose DECL_CONTEXT is not a type.
+
+ * class.c (finish_struct_1): Use build_cplus_array_type to build
+ array types.
+ * decl.c (init_decl_processing): Likewise.
+ * except.c (expand_end_eh_spec): Likewise.
+ * search.c (expand_upcast_fixups): Simplify very slightly.
+
+1998-10-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokdeclarator): Complain about a variable using
+ constructor syntax coming back null from start_decl.
+
+ * friend.c (make_friend_class): Complain about trying to make
+ a non-class type a friend.
+
+ * decl.c (grokfndecl): Set DECL_INITIAL for a defn here.
+ (start_function): Not here.
+
+1998-10-26 Brendan Kehoe <brendan@cygnus.com>
+
+ * decl.c (grokdeclarator): Disallow `explicit' in a friend declaration.
+
+1998-10-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck2.c (process_init_constructor): Only skip anonymous fields
+ if they are bitfields.
+
+ * cp-tree.def (TYPEOF_TYPE): New code.
+ * error.c (dump_type_real): Handle it.
+ * pt.c (tsubst): Likewise.
+ * tree.c (search_tree): Likewise.
+ * semantics.c (finish_typeof): New fn.
+ * parse.y (typespec): Use it.
+ * cp-tree.h: Declare it.
+
+1998-10-26 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * cp-tree.h (FORMAT_VBASE_NAME): Make definition unconditional.
+
+1998-10-26 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (convert_arguments): Don't handle pmf references
+ specially.
+
+ * init.c (build_member_call): Don't try to convert to the base type
+ if it's ambiguous or pedantic.
+
+ * typeck2.c (check_for_new_type): Only depend on pedantic for
+ C-style casts.
+
+1998-10-25 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Set DECL_NONCONVERTING_P for all
+ non-converting constructors.
+
+1998-10-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * gxxint.texi: Correct documentation for n, N, Q, and B.
1998-10-23 Martin von Löwis <loewis@informatik.hu-berlin.de>
* parse.y (condition): Convert VAR_DECL from reference to indirect
reference.
-1998-10-18 Jason Merrill <jason@yorick.cygnus.com>
+1998-10-23 Andrew MacLeod <amacleod@cygnus.com>
+
+ * exception.cc (__cp_pop_exception): Free the original exception
+ value, not the potentially coerced one.
+
+1998-10-23 Mark Mitchell <mark@markmitchell.com>
+
+ * Makefile.in (hash.h): Run gperf when necessary.
+
+ * cp-tree.h (CP_TYPE_READONLY): Remove.
+ (CP_TYPE_VOLATILE): Likewise.
+ (CP_TYPE_QUALS): New macro.
+ (CP_TYPE_CONST_P): Likewise.
+ (CP_TYPE_VOLATILE_P): Likewise.
+ (CP_TYPE_RESTRICT_P): Likewise.
+ (CP_TYPE_CONST_NON_VOLATILE_P): Likewise.
+ (cp_build_type_variant): Rename to ...
+ (cp_build_qualified_type): New function.
+ (c_apply_type_quals_to_decl): Declare.
+ (SIGNATURE_POINTER_NAME_FORMAT): Modify to allow `restrict'.
+ (SIGNATURE_REFERENCE_NAME_FORMAT): Likewise.
+ (cp_type_qual_from_rid): New function.
+ (compparms): Remove unused parameter. All callers changed.
+ (cp_type_quals): New function.
+ (at_least_as_qualified_p): Likewise.
+ (more_qualified_p): Likewise.
+
+ * call.c (standard_conversion): Replace calls to
+ cp_build_type_variant with cp_build_qualified_type. Use
+ CP_TYPE_QUALS to get qualifiers and at_least_as_qualified_p to
+ compare them. Use CP_TYPE_* macros to check qualifiers.
+ (reference_binding): Likewise.
+ (implicit_conversion): Likewise.
+ (add_builtin_candidates): Likewise.
+ (build_over_call): Likewise.
+ * class.c (overrides): Compare all qualifiers, not just `const',
+ on method declarations.
+ * cvt.c (convert_to_reference): More CP_TYPE_QUALS conversion, etc.
+ (convert_pointer_to_real): Likewise.
+ (type_promotes_to): Likewise.
+ * decl.c (check_for_uninitialized_const_var): New function.
+ (init_decl_processing): More CP_TYPE_QUALS conversion, etc.
+ (cp_finish_decl): Use check_for_uninitialized_const_var.
+ (grokdeclarator): More CP_TYPE_QUALS conversion, etc. Update to
+ handle `restrict'.
+ (grok_ctor_properties): Likewise.
+ (grok_op_properties): Likewise.
+ (start_function): Likewise.
+ (rever_static_member_fn): Likewise.
+ * decl2.c (grok_method_quals): Likewise.
+ (grokfield): Likewise.
+ * error.c (dump_readonly_or_volatile): Rename to ...
+ (dump_qualifiers): New function. Handle `restrict'.
+ (dump_type_real): Use it.
+ (dump_aggr_type): Likewise.
+ (dump_type_prefix): Likewise.
+ (dump_type_suffix): Likewise.
+ (dump_function_decl): Likewise.
+ (cv_as_string): Likewise.
+ * gxx.gperf: Add __restrict and __restrict__.
+ * gxxint.texi: Document `u' as used for `__restrict', and a few
+ other previously undocumented codes.
+ * hash.h: Regenerated.
+ * init.c (expand_aggr_init): More CP_TYPE_QUALS conversion, etc.
+ (build_member_call): Likewise.
+ (build_new_1): Likewise.
+ * lex.c (init_parse): Add entry for RID_RESTRICT.
+ (cons_up_default_function): More CP_TYPE_QUALS conversion, etc.
+ (cp_type_qual_from_rid): Define.
+ * lex.h (enum rid): Add RID_RESTRICT.
+ * method.c (process_modifiers): Deal with `restrict'.
+ * parse.y (primary): More CP_TYPE_QUALS conversion, etc.
+ * parse.c: Regenerated.
+ * pt.c (convert_nontype_argument): More CP_TYPE_QUALS conversion, etc.
+ (tsubst_aggr_type): Likewise.
+ (tsubst): Likewise.
+ (check_cv_quals_for_unify): Likewise.
+ (unify): Likewise.
+ * rtti.c (init_rtti_processing): Likewise.
+ (build_headof): Likewise.
+ (get_tinfo_var): Likewise.
+ (buidl_dynamic_cast_1): Likewise. Fix `volatile' handling.
+ (expand_class_desc): Likewise.
+ (expand_attr_desc): Likewise.
+ (synthesize_tinfo_fn): Likewise.
+ * search.c (covariant_return_p): Likewise. Fix `volatile' handling.
+ (get_matching_virtual): Likewise.
+ (expand_upcast_fixups): Likewise.
+ * sig.c (build_signature_pointer_or_reference_name): Take
+ type_quals, not constp and volatilep.
+ (build_signature_pointer_or_reference_type): Likewise.
+ (match_method_types): More CP_TYPE_QUALS conversion, etc.
+ (build_signature_pointer_constructor): Likewise.
+ (build_signature_method_call): Likewise.
+ * tree.c (build_cplus_array_type): Likewise.
+ (cp_build_type_variant): Rename to ...
+ (cp_build_qualified_type): New function. Deal with `__restrict'.
+ (canonical_type_variant): More CP_TYPE_QUALS conversion, etc.
+ (build_exception_variant): Likewise.
+ (mapcar): Likewise.
+ * typeck.c (qualif_type): Likewise.
+ (common_type): Likewise.
+ (comptypes): Likewise.
+ (comp_cv_target_types): Likewise.
+ (at_least_as_qualified_p): Define.
+ (more_qualified_p): Likewise.
+ (comp_cv_qualification): More CP_TYPE_QUALS conversion, etc.
+ (compparms): Likewise.
+ (inline_conversion): Likewise.
+ (string_conv_p): Likewise.
+ (build_component_ref): Likewise.
+ (build_indirect_ref): Likewise.
+ (build_array_ref): Likewise.
+ (build_unary_op): Likewise.
+ (build_conditional_expr): Likewise.
+ (build_static_cast): Likewise.
+ (build_c_cast): Likewise.
+ (build_modify_expr): Likewise.
+ (convert_For_assignment): Likewise.
+ (comp_ptr_ttypes_real): Likewise.
+ (cp_type_quals): New function.
+
+1998-10-23 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (CP_TYPE_READONLY): New macro to handle arrays.
+ (CP_TYPE_VOLATILE): Likewise.
+ * decl.c (grokdeclarator): Use them.
+ * tree.c (canonical_type_variant): Likewise.
+
+1998-10-22 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * parse.y (named_class_head): Push into class while parsing the
+ base class list.
+ * decl2.c (push_scope, pop_scope): New functions.
+ * cp-tree.h: Declare them.
+ * init.c (build_new_1): Delay cleanup until end of full expression.
+
+1998-10-21 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (hack_identifier): Just return a member function.
+ * typeck.c (build_component_ref): Use of a type here is an error.
+
+1998-10-19 Jason Merrill <jason@yorick.cygnus.com>
+
+ Revamp references to member functions.
+ * method.c (hack_identifier): Call build_component_ref for a
+ reference to a member function.
+ * typeck.c (build_component_ref): Only return a single function
+ if it's static. Otherwise, return a COMPONENT_REF.
+ (build_x_function_call): Handle a COMPONENT_REF.
+ (build_unary_op): Handle all unknown-type things.
+ * decl2.c (arg_assoc): Handle COMPONENT_REF.
+ * class.c (instantiate_type): Complain if the function we get is a
+ nonstatic member function. Remove code for finding "compatible"
+ functions.
+ * pt.c (tsubst_copy): Handle NOP_EXPR.
+ * tree.c (build_dummy_object): New fn.
+ (maybe_dummy_object): New fn.
+ (is_dummy_object): New fn.
+ * cp-tree.h: Declare them.
+ * cvt.c (cp_convert_to_pointer): Use maybe_dummy_object.
+ * error.c (dump_expr, case OFFSET_REF): Use is_dummy_object.
+ * init.c (build_member_call): Use maybe_dummy_object and
+ is_dummy_object.
+ (build_offset_ref): Use maybe_dummy_object.
+ (resolve_offset_ref): Use is_dummy_object.
+ * typeck.c (build_x_function_call): Call build_dummy_object.
+ (unary_complex_lvalue): Call is_dummy_object.
+
+ * typeck.c (build_component_addr): Make sure field is a field.
+
+ * call.c (build_new_op): Delete obsolete code.
+
+ * pt.c (tsubst, TEMPLATE*PARM*): Abort if we don't have any args.
1998-10-18 Martin von Löwis <loewis@informatik.hu-berlin.de>
* decl2.c (validate_nonmember_using_decl): Fix using-directives of
std if std is ignored.
-1998-10-14 Jason Merrill <jason@yorick.cygnus.com>
+1998-10-18 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokvardecl): Fix thinko.
+
+ * decl.c (grokdeclarator): Embedded attrs bind to the right,
+ not the left.
+
+ * parse.y (fn.def2): Fix 'attrs' format.
+
+1998-10-18 Alastair J. Houghton <ajh8@doc.ic.ac.uk>
+
+ * Makefile.in (CONFLICTS): Update.
+ * parse.y (expr_or_declarator_intern): New rule.
+ (expr_or_declarator, direct_notype_declarator, primary,
+ functional_cast): Use it.
+ (notype_declarator_intern): New rule.
+ (notype_declarator, complex_notype_declarator): Use it.
+
+1998-10-17 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Set DECL_CONTEXT to namespace if appropriate.
+ (grokvardecl): Likewise.
+
+Sat Oct 17 23:27:20 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * class.c (make_method_vec): Cast 1st argument of `bzero' to (PTR).
+ (add_method): Likewise for arguments 1 & 2 of `bcopy'.
+
+ * decl.c (signal_catch): Mark with ATTRIBUTE_NORETURN.
+
+ * pt.c (process_partial_specialization): Cast 1st argument of
+ `bzero' to (PTR).
+
+ * tree.c (build_base_fields): Cast `base_align' to (int) when
+ comparing against one.
+
+1998-10-16 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (lookup_name_real): Handle template parameters for member
+ templates where said parameters have the same name as the
+ surrounding class.
+
+ * decl.c (expand_static_init): Build cleanups before entering the
+ anonymous function used to do them to avoid access-checking
+ confusion.
+
+ * decl.c (grokfndecl): Add back call to cplus_decl_attributes
+ accidentally removed by previous change, and make DECL_RTL here.
+ * class.c (add_method): Don't make DECL_RTL here.
+
+ * pt.c (for_each_template_parm): Don't examine uninstantiated
+ default arguments.
+
+1998-10-16 Dave Brolley <brolley@cygnus.com>
+
+ * lex.c (real_yylex): Fix unaligned access of wchar_t.
+
+1998-10-16 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (add_method): Fix documentation to reflect previous
+ changes. Check for duplicate method declarations here.
+ * decl.c (decls_match): Handle FUNCTION_DECL vs TEMPLATE_DECL
+ correctly; such things never match.
+ (grokfndecl): Don't look for duplicate methods here.
+ * decl2.c (check_classfn): Don't assume names are mangled.
+ Don't add bogus member function declarations to a class before the
+ class type is complete.
+ (grokfield): Reformat error message.
+ * method.c (set_mangled_name_for_decl): Don't mangle names while
+ processing_template_decl.
+
+1998-10-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (build_indirect_ref): Complain about a pointer to data
+ member, too.
+ * typeck2.c (build_m_component_ref): Don't indirect a pointer to
+ data member.
+ * init.c (resolve_offset_ref): Don't undo the above.
+
+ * cp-tree.h (DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): New macros.
+ (struct lang_decl_flags): Add `bitfield'.
+ * class.c (finish_struct_1): Use DECL_C_BIT_FIELD instead of
+ DECL_BIT_FIELD.
+ * decl2.c (grokbitfield, grok_alignof): Likewise.
+ * init.c (build_offset_ref): Likewise.
+ * typeck.c (build_component_addr, expr_sizeof): Likewise.
+ * cvt.c (build_up_reference): Don't crash if taking the address
+ returns error_mark_node.
+
+ * decl.c (grokfndecl): Also check ctype when checking for ::main().
+
+1998-10-15 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): ::main and __builtin_* get C linkage.
+ Do mangling here.
+ (grokdeclarator): Instead of here.
+ * friend.c (do_friend): Lose special handling of ::main and
+ __builtin_*.
+ * cp-tree.h (DECL_MAIN_P): Check for C linkage.
* spew.c (yylex): Clear looking_for_typename if we got
'enum { ... };'.
+1998-10-15 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (maybe_warn_about_overly_private_class): Improve error
+ messages for class with only private constructors.
+
+ * cp-tree.def (TYPENAME_TYPE): Add to documentation.
+ * cp-tree.h (TYPENAME_TYPE_FULLNAME): Document.
+ (build_typename_type): New function.
+ * decl.c (build_typename_type): Broken out from ...
+ (make_typename_type): Use it.
+ * search.c (lookup_field): Likewise.
+
+1998-10-14 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+
+ * pt.c (convert_nontype_argument): Check against type_referred_to.
+ * decl.c (grokvardecl): Check for declarator name before building
+ DECL_ASSEMBLER_NAME.
+
+1998-10-14 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (lookup_template_class): Add comment.
+ (instantiate_class_template): Don't mark the _TYPE node for
+ member class templates as an instantiation.
+
+1998-10-14 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (grokfndecl): Fix my thinko.
+
1998-10-13 Jason Merrill <jason@yorick.cygnus.com>
* tinfo2.cc (fast_compare): Remove.
(before): Just use strcmp.
* tinfo.cc (operator==): Just use strcmp.
+1998-10-13 Klaus-Georg Adams <Klaus-Georg.Adams@chemie.uni-karlsruhe.de>
+
+ * decl.c (grokfndecl): Don't check for linkage in `extern "C"'
+ declarations.
+
+1998-10-13 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (specializations_of_same_template_p): Remove.
+ * search.c (get_template_base): Don't use it.
+ (get_template_base_recursive): Likewise.
+ * pt.c (specializations_of_same_template_p): Remove.
+ (unify): Don't use it.
+ (lookup_template_class): Find the correct parent when setting
+ CLASSTYPE_TI_TEMPLATE.
+
1998-10-12 Jason Merrill <jason@yorick.cygnus.com>
* tinfo.cc (operator==): Always compare names.
+1998-10-12 Herman ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * decl.c (start_function): Fix cut-and-paste error.
+
1998-10-12 Jason Merrill <jason@yorick.cygnus.com>
* inc/typeinfo: Add #pragma interface.
(operator!=): Just call operator==.
* tinfo.cc: Add #pragma implementation.
(operator==): Move from inc/typeinfo and tinfo2.cc.
+ Check __COMMON_UNRELIABLE instead of _WIN32.
* typeck2.c (my_friendly_abort): Add URL.
+1998-10-12 Alastair J. Houghton <ajh8@doc.ic.ac.uk>
+
+ * decl.c (start_method): Added extra parameter for attributes.
+ * cp-tree.h (start_method): Update prototype.
+ * parse.y (fn.def2): Update start_method parameter list.
+
+1998-10-11 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (specializations_of_same_template_p): Declare.
+ * pt.c (specializations_of_same_template_p): New function.
+ (unify): Use it.
+ * search.c (get_template_base): Use it.
+ (get_template_base_recursive): Likewise.
+
+1998-10-10 Manfred Hollstein <manfred@s-direktnet.de>
+
+ * decl2.c (start_objects): Add new variable `joiner' and
+ initialize it properly.
+
+1998-10-09 Mark Mitchell <mark@markmitchell.com>
+
+ * search.c (expand_upcast_fixups): Tweak to match 1998-10-07
+ change to vtable types.
+
+ * cvt.c (ocp_convert): Avoid infinite recursion caused by
+ 1998-10-03 change.
+
+1998-10-08 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (resolve_overloaded_unification): New fn.
+ (try_one_overload): Likewise.
+ (unify): Don't fail on unknown type.
+ (type_unification_real): Likewise. Use resolve_overloaded_unification
+ to handle an overloaded argument.
+ (template_args_equal): Split out...
+ (comp_template_args): From here.
+ (determine_specialization): Also allow a template with more
+ parms than were explicitly specified.
+ * cp-tree.h: Add template_args_equal.
+ * call.c (resolve_args): Remove TEMPLATE_ID_EXPR code.
+
+Thu Oct 8 15:58:30 1998 Anthony Green <green@cygnus.com>
+
+ * semantics.c (finish_asm_stmt): Revert my 1998-09-28
+ change.
+
+Thu Oct 8 06:00:19 1998 Jeffrey A Law (law@cygnus.com)
+
+ * typeck.c (unsigned_type): Only return TItype nodes when
+ HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ (signed_type): Likewise.
+ * decl.c (intTI_type_node, unsigned_intTI_type_node): Only declare
+ when HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ (init_decl_processing): Only create TItype nodes when
+ HOST_BITS_PER_WIDE_INT is >= 64 bits.
+ * cp-tree.h (intTI_type_node, unsigned_intTI_type_node): Only declare
+ when HOST_BITS_PER_WIDE_INT is >= 64 bits.
+
+Wed Oct 7 12:32:44 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (hash.h): Add -L KR-C -F ', 0, 0' flags to gperf.
+ (gxx.gperf): Update comments describing invocation flags.
+ (hash.h): Regenerate using gperf 2.7.1 (19981006 egcs).
+
+1998-10-07 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (finish_struct_1): Add commentary on previous change.
+
+ * cp-tree.h (vtbl_ptr_type_node): New variable.
+ * class.c (build_vtbl_ref): Don't indirect through the vptr; it's
+ already of the right type.
+ (finish_struct_1): Make the vptr be of type vtbl_ptr_type_node.
+ Simplify code to grow vtable.
+ * decl.c (vtbl_ptr_type_node): Define.
+ (init_decl_processing): Initialize it.
+
+1998-10-06 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.def (PTRMEM_CST): New tree node.
+ * cp-tree.h (ptrmem_cst): New type.
+ (lang_type): Remove local_typedecls.
+ (dummy): Increase to 12 bits from 11.
+ (CLASSTYPE_LOCAL_TYPEDECLS): Remove.
+ (PTRMEM_CST_CLASS): New macro.
+ (PTRMEM_CST_MEMBER): Likewise.
+ (current_access_specifier): New variable.
+ (current_class_type): Remove duplicate declaration.
+ (finish_struct): Change prototype.
+ (unreverse_member_declarations): New function.
+ (pushdecl_class_level): Change prototype.
+ (grok_enum_decls): Remove.
+ (fixup_anonymous_union): New function.
+ (grok_x_components): Change prototype.
+ (tsubst_chain): Remove.
+ (finish_member_template_decl): Likewise.
+ (check_explicit_specialization): Fix indentation.
+ (finish_class_definition): Change prototype.
+ (finish_member_class_template): Likewise.
+ (finish_member_declaration): New function.
+ (check_multiple_declarators): Likewise.
+ * class.c (class_stack_node_t): New type.
+ (current_class_base): Remove.
+ (current_class_stack): Change type.
+ (current_access_specifier): New variable.
+ (grow_method): Remove.
+ (check_member_decl_is_same_in_complete_scope): Break out from
+ finish_struct.
+ (make_method_vec): New function.
+ (free_method_vec): Likewise.
+ (add_implicitly_declared_members): Break out from finish_struct_1.
+ (free_method_vecs): New variable.
+ (add_method): Rework for direct use from parser.
+ (handle_using_decl): Watch for NULL_TREE while iterating through
+ CLASSTYPE_METHOD_VEC.
+ (finish_struct_methods): Don't build CLASSTYPE_METHOD_VEC here;
+ just do some error-checking.
+ (warn_hidden): Change iteration through CLASSTYPE_METHOD_VEC.
+ (finish_struct_1): Simplify. Use add_implicitly_declared_members.
+ (finish_struct): Change prototype. Simplify; fields and methods
+ are already set up at this point.
+ (init_class_processing): Set up current_class_stack.
+ (pushclass): Save current_access_specifier.
+ (popclass): Restore it.
+ (currently_open_class): Simplify.
+ (build_self_reference): Remove use of CLASSTYPE_LOCAL_TYPEDECLS.
+ * decl.c (saved_scope): Add access_specifier.
+ (maybe_push_to_top_level): Save it.
+ (pop_from_top_level): Restore it.
+ (maybe_process_template_type_declaration): Use
+ finish_member_declaration.
+ (pushtag): Likewise.
+ (pushdecl_class_level): Don't return a value.
+ (fixup_anonymous_union): Break out from grok_x_components.
+ (shadow_tag): Use it.
+ (xref_tag): Complain about using an elaborated type specifier to
+ reference a template type parameter or typedef name.
+ (xref_basetypes): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
+ (current_local_enum): Remove.
+ (build_enumerator): Call finish_member_declaration.
+ (grok_enum_decls): Remove.
+ * decl2.c (grok_x_components): Simplify.
+ (check_classfn): Change iteration through CLASSTYPE_METHOD_VEC.
+ (grokfield): Don't set CLASSTYPE_LOCAL_TYPEDECLS.
+ (merge_functions): Add to comment.
+ (arg_assoc_type): Prototype.
+ (arg_assoc): Pass as many arguments as there are parameters.
+ * error.c (dump_expr): Handle PTRMEM_CST. Improve handling of
+ OFFSET_REF.
+ * expr.c (cpls_expand_expr): Remove dead code. Handle
+ PTRMEM_CST.
+ * friend.c (do_friend): Lookup friends when in nested classes.
+ Change comments.
+ * init.c (build_offset_ref): Do lookup even for classes that are
+ only partially defined.
+ (decl_constant_value): Remove dead code.
+ * method.c (build_overload_value): Remove hack where by TYPE was
+ not a TYPE. Handle PTRMEM_CST.
+ (build_template_parm_names): Don't pass a PARM_DECL where a TYPE
+ should go.
+ * parse.y (components, notype_components, component_decl,
+ component_decl_1, component_declarator, component_declarator0):
+ Now all are itype rather than ttype. Rework to add members to
+ classes on the fly.
+ (typesqpecqual_reserved): Use check_multiple_declarators.
+ (structsp): Update class to finish_class_definition.
+ (do_xref_defn): Unsplit into named_class_head.
+ (access_specifier): Set current_access_specifier.
+ * pt.c (set_current_access_from_decl): New function.
+ (finish_member_template_decl): Don't take the parameters.
+ (comp_template_args): Make more robust.
+ (lookup_template_class): Don't use current_local_enum.
+ (for_each_template_parm): Handle PTRMEM_CST.
+ (instantiate_class_template): Use set_current_access_from_decl,
+ finish_member_declaration and unreverse_member_declarations. Set
+ lineno/input_filename before generating implicit member functions.
+ (type_unification_real): Don't assume back-unification happens
+ only for the last argument.
+ (regenerate_decl_from_template): Call pushclass a bit earlier.
+ (tsubst_chain): Remove.
+ (tsubst_enum): Use set_current_access_from_decl.
+ (set_mangled_name_for_template_decl): Fix indentation.
+ * search.c (lookup_fnfields_1): Change iteration through
+ CLASSTYPE_METHOD_VEC.
+ (dfs_pushdecls): Likewise.
+ (dfs_compress_decls): Likewise.
+ (add_conversions): Likewise.
+ * semantics.c (finish_class_definition): Don't take components.
+ Change call to finish_struct.
+ (finish_member_declaration): New function.
+ (finish_member_class_template): Don't take template parameters.
+ Change call to grok_x_components. Call finish_member_template_decl.
+ (check_multiple_declarators): New function.
+ * sig.c (append_signature_fields): Work from the TYPE_METHODS, not
+ a passed in fieldlist.
+ * tree.c (search_tree): Handle PTRMEM_CST.
+ (mapcar): Likewise.
+ * typeck.c (unary_complex_lvalue): Build PTRMEM_CSTs, not
+ INTEGER_CSTs, for pointer-to-data members.
+
+ * call.c (resolve_args): Resolve template specializations, if
+ possible.
+
+Tue Oct 6 07:57:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (spew.o): Depend on toplev.h.
+
+ * call.c (compare_ics): Initialize variables `deref_from_type2',
+ `deref_to_type1' and `deref_to_type2'.
+
+ * except.c (get_eh_type): Hide prototype and definition.
+ (process_start_catch_block_old): Remove unused static prototype.
+
+ * pt.c (tsubst_decl): Initialize variable `argvec'.
+
+ * spew.c: Include toplev.h.
+
+1998-10-05 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_decl): Do save and restore file position.
+
1998-10-05 Martin von Löwis <loewis@informatik.hu-berlin.de>
* method.c (build_decl_overload_real): Clear
numeric_output_need_bar after __.
+1998-10-05 Nathan Sidwell <nathan@acm.org>
+
+ * call.c (build_new_method_call): Issue 'incomplete type' error,
+ if class is not defined.
+
+1998-10-05 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * call.c (build_object_call): Move declaration of variable
+ `fn' into the scope where it is used. Don't access variable
+ `fn' when it is uninitialized, instead use `fns'.
+
+1998-10-04 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
+
+ * errfn.c (cp_thing): Print buf as a string not as a printf format
+ to avoid problems with the operator%. Consequently, `%%' sequences
+ in format are copied as `%' in buf.
+
1998-10-04 Jason Merrill <jason@yorick.cygnus.com>
+ * pt.c (pop_tinst_level): Call extract_interface_info.
+ (instantiate_decl): Don't save and restore file position.
+
* decl.c (cp_finish_decl): Make statics in extern inlines and
templates common, if possible and the target doesn't support weak
symbols.
+ * decl.c (grokdeclarator): Remove redundant calls to
+ build_type_variant and some duplicated code.
+ * sig.c (build_signature_reference_type): Only take the type parm.
+ (build_signature_pointer_type): Likewise.
+ * tree.c (build_cplus_method_type): Adjust.
+ * cp-tree.h: Update.
+
+1998-10-04 Mark Mitchell <mark@markmitchell.com>
+
+ * call.c (build_over_call): Make pedwarns about dropped qualifiers
+ into full-fledged errors.
+ * cvt.c (convert_to_reference): Likewise.
+ * typeck.c (convert_for_assignment): Likewise.
+
+ * search.c (expand_upcast_vtables): In addition to unsetting
+ TREE_READONLY, remove top-level const type qualifier.
+
+1998-10-03 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (current_class_ptr, current_class_ref): Clarify
+ documentation.
+ * cvt.c (ocp_convert): Don't expect fold to remove all trivial
+ NOP type conversions.
+ * decl.c (decls_match): Use comptypes directly; ignore
+ qualifiers on the DECL.
+ (duplicate_decls): Remove qualifier checks on DECL.
+ (grokdeclarator): Make the type built up include top-level
+ qualifiers.
+ * decl2.c (do_dtors): Fix spelling error.
+ * error.c (dump_simple_decl): Don't look at qualifiers on the decl
+ when printing type information.
+ * init.c (build_new_1): Add documentation. Deal with the fact
+ that type of allocated memory now contains qualifiers.
+ * lex.c (is_global): Improve error-recovery.
+ * sig.c (build_member_function_pointer): Don't cast away const
+ on fields of sigtable_entry_type.
+ * tree.c (lvalue_type): Don't look at top-level qualifiers on
+ expressions.
+ * typeck.c (decay_conversion): Likewise.
+ (build_component_ref): Make sure the type of the COMPONENT_REF
+ contains top-level qualifiers, as appropriate. Improve
+ error-handling.
+ (build_indirect_ref): Simplify. Don't strip top-level qualifiers.
+ (build_array_ref): Likewise.
+ (build_unary_op): Improve error-recovery.
+ (unary_complex_lvalue): Make taking the address a bound member
+ function an error, not a sorry.
+ (build_conditional_expr): Look at the type qualifiers, not the
+ qualifiers on the expression itself.
+
1998-10-03 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (merge_functions): Remove duplicates.
+ * decl2.c: Add -f{no-,}implicit-inline-templates.
+ (import_export_decl): Check it.
+
+ * decl.c (lookup_name_real): Template parms also take precedence
+ over implicit typename. Only warn if yylex.
+
* typeck.c (build_conditional_expr): Only fold if ifexp is an
INTEGER_CST.
-Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
+ * decl2.c (finish_vtable_vardecl): Check DECL_INTERFACE_KNOWN
+ instead of linkage.
+
+1998-10-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h (FORMAT_VBASE_NAME): New macro.
+ * class.c (build_vbase_pointer): Use it.
+ * rtti.c (expand_class_desc): Likewise.
+ * tree.c (build_vbase_pointer_fields): Likewise.
+
+Thu Oct 1 10:43:45 1998 Nick Clifton <nickc@cygnus.com>
+
+ * decl.c (start_decl): Add invocation of
+ SET_DEFAULT_DECL_ATTRIBUTES, if defined.
+ (start_function): Add invocation of
+ SET_DEFAULT_DECL_ATTRIBUTES, if defined.
+
+ * lex.c: Replace occurrences of HANDLE_SYSV_PRAGMA with
+ HANDLE_GENERIC_PRAGMAS.
+
+1998-09-28 Anthony Green <green@cygnus.com>
+
+ * semantics.c (finish_asm_stmt): Always permit volatile asms.
+
+1998-09-28 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Tighten checks for invalid
+ destructors. Improve error-messages and error-recovery.
+ * decl2.c (check_classfn): Don't assume that mangled destructor
+ names contain type information.
+
+1998-09-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * search.c (get_base_distance): Remove assert.
+
+ * decl2.c (build_anon_union_vars): Don't process a field with no
+ name.
+ (finish_anon_union): Also complain about local anon unions with no
+ members.
+
+1998-09-25 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (lookup_namespace_name): If the name is a namespace,
+ return it immediately.
+
+Fri Sep 25 11:45:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (define_case_label): Remove unused parameter.
+ (check_java_method): Likewise.
+ (grokclassfn): Likewise.
+ (expand_aggr_init): Likewise.
+ (build_x_delete): Likewise.
+ (maybe_end_member_template_processing): Likewise.
+ (unshare_base_binfos): Add prototype.
+ (string_conv_p): Likewise.
+ (my_friendly_abort): Mark with ATTRIBUTE_NORETURN.
+
+ * cvt.c (build_up_reference): Remove unused parameter
+ `checkconst', all callers changed.
+ (build_type_conversion): Mark parameter `code' with
+ ATTRIBUTE_UNUSED.
+ (build_expr_type_conversion): Initialize variable `conv'.
+
+ * decl.c (push_namespace): Initialize variable `d'.
+ (define_case_label): Remove unused parameter `decl', all callers
+ changed.
+
+ * decl2.c (lang_decode_option): If !USE_CPPLIB, mark parameter
+ `argc' with ATTRIBUTE_UNUSED.
+ (grokclassfn): Remove unused parameter `cname', all callers
+ changed.
+ (check_java_method): Likewise for parameter `ctype'.
+ (copy_assignment_arg_p): Mark parameter `virtualp' with
+ ATTRIBUTE_UNUSED.
+ (finish_prevtable_vardecl): Likewise for parameter `prev'.
+
+ * expr.c (extract_init): Likewise for parameters `decl' and `init'.
+
+ * init.c (expand_aggr_init_1): Remove unused parameter
+ `alias_this', all callers changed.
+ (expand_aggr_init): Likewise.
+ (expand_default_init): Likewise.
+ (build_new_1): Initialize variable `susp'.
+ (build_x_delete): Remove unused parameter `type', all callers
+ changed.
+
+ * lex.c (set_typedecl_interface_info): Mark parameter `prev' with
+ ATTRIBUTE_UNUSED.
+ (readescape): Use (unsigned) value in shift.
+ (real_yylex): Likewise. Likewise. Also cast `sizeof' to int when
+ comparing to a signed quantity.
+
+ * pt.c (maybe_end_member_template_processing): Remove unused
+ parameter `decl', all callers changed.
+ (check_explicit_specialization): Add braces around empty body in
+ an else-statement.
+ (current_template_args): Initialize variable `args'.
+ (lookup_template_class): Likewise for variable `prev_local_enum'.
+ (tsubst_decl): Likewise for variable `r'.
+ (set_mangled_name_for_template_decl): Initialize variable
+ `context'.
+
+ * spew.c (scan_tokens): Change type of parameter `n' to unsigned.
+ Likewise for variable `i'.
+ (yylex): Initialize variable `trrr'.
+
+ * typeck.c (compparms): Mark variable `strict' with
+ ATTRIBUTE_UNUSED.
+
+ * xref.c (simplify_type): Cast argument of ctype function to
+ `unsigned char'.
+
+1998-09-24 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (language_lvalue_valid): Remove.
+ * decl.c (grokdeclarator): Don't disallow references to functions.
+ * tree.c (lvalue_p_1): New function, combining duplicated
+ code from ...
+ (lvalue_p): Use it.
+ (real_lvalue_p): Likewise.
+ * typeck.c (language_lvalue_valid): Remove.
+ (build_modify_expr): Treat FUNCTION_TYPEs as readonly, even though
+ they don't have TREE_READONLY set.
+ * typeck2.c (readonly_error): Add case for FUNCTION_DECLs.
+
+1998-09-24 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * spew.c (yylex): Give diagnostic.
+ * hash.h (is_reserved_word): Add export.
+ * gxx.gperf: Likewise.
+ * lex.h (rid): Add RID_EXPORT.
+ * lex.c (init_parse): Likewise.
+
+Tue Sep 22 21:01:19 1998 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * friend.c (do_friend): Make warning a full sentence.
+
+1998-09-22 Mark Mitchell <mark@markmitchell.com>
+
+ * parse.y (component_decl_list): Improve error-recovery.
+
+1998-09-22 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * decl.c (make_typename_type): Move error to point where name
+ variable can be used by dump_type.
+
+1998-09-22 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokfndecl): Improve error-recovery.
+ * decl2.c (grokfield): Likewise.
+ * pt.c (finish_member_template_decl): Likewise.
+
+1998-09-20 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * method.c (hack_identifier): Finding multiple members is always
+ an error.
+
+1998-09-21 Per Bothner <bothner@cygnus.com>
+
+ * Make-lang.in (c++-filt): Link libiberty.a after cxxmain.o.
+
+Mon Sep 21 01:53:05 1998 Felix Lee <flee@cygnus.com>
+
+ * lex.c (init_lex): Use getenv ("LANG"), not GET_ENVIRONMENT ().
+
+1998-09-20 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (maybe_warn_about_overly_private_class): Reformat.
+
+1998-09-17 Andrew MacLeod <amacleod@cygnus.com>
+
+ * exception.cc (__cplus_type_matcher): Realign some code.
+
+1998-09-16 Mark Mitchell <mark@markmitchell.com>
+
+ * Make-lang.in (tinfo.o): Use CXXFLAGS when compiling.
+ (tinfo2.o): Likewise.
+ (exception.o): Likewise.
+ (new.o): Likewise.
+ (opnew.o): Likewise.
+ (opnewnt.o): Likewise.
+ (opvnew.o): Likewise.
+ (opvnewnt.o): Likewise.
+ (opdel.o): Likewise.
+ (opdelnt.o): Likewise.
+ (opvdel.o): Likewise.
+ (opvdelnt.o): Likewise.
+
+1998-09-16 Richard Henderson <rth@cygnus.com>
+
+ * decl.c (init_decl_processing): Kill __builtin_fp and __builtin_sp.
+
+1998-09-15 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * call.c (build_field_call): Handle static data members too.
+
+ * typeck.c (comptypes): When comparing pointer types, check
+ whether referred types match even in strictest modes.
+
+1998-09-15 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h: Revert previous change.
+ (finish_struct_methods): Remove declaration.
+ * class.c: Revert previous change.
+ (maybe_warn_about_overly_private_class): New function.
+ (finish_struct_methods): Declare here, and make static. Remove
+ unnecessary parameters. Tidy slightly. Use
+ maybe_warn_about_overly_private_class.
+ (finish_struct_1): Adjust. Remove check for private constructors,
+ now done elsewhere.
+ (finish_struct): Adjust.
+
+1998-09-15 Andrew MacLeod <amacleod@cygnus.com>
+
+ * except.c (expand_start_catch_block): No need to check for new
+ exception model.
+ (process_start_catch_block_old): Deleted.
+ (process_start_catch_block): Add call to start_decl_1().
+ (expand_end_catch_block): Add call to end_catch_handler().
+ * exception.cc (__cplus_type_matcher): Only check the exception
+ language if there is an exception table.
+
+1998-09-15 Andrew MacLeod <amacleod@cygnus.com>
+
+ * search.c (expand_indirect_vtbls_init): Mark temporary stack slots
+ as used to prevent conflicts with virtual function tables.
+
+1998-09-14 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (lang_type): Add has_non_private_static_mem_fn.
+ (CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN): New macro, to access it.
+ * class.c (maybe_class_too_private_p): New function.
+ (finish_struct_methods): Use it.
+ (finish_struct_1): Likewise.
+ (finish_struct): Set CLASSTYPE_HAS_NON_PRIVATE_STATIC_MEM_FN if
+ appropriate.
+
+ * pt.c (check_specialization_scope): Fix spelling error.
+ (check_explicit_specialization): Remove code to handle explicit
+ specializations in class scope; they are now correctly diagnosed
+ as errors.
+
+1998-09-10 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (pushdecl): Don't copy types if the
+ DECL_ABSTRACT_ORIGIN of the new decl matches the TYPE_NAME of the
+ type.
+
+1998-09-09 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+
+ * class.c (get_enclosing_class): New function.
+ (is_base_of_enclosing_class): Likewise.
+ * cp-tree.h (get_enclosing_class): Declare.
+ (is_base_of_enclosing_class): Likewise.
+ * pt.c (coerce_template_parms): Use them.
+
+1998-09-09 Jason Merrill <jason@yorick.cygnus.com>
+
+ * g++spec.c (lang_specific_driver): Check whether MATH_LIBRARY is
+ null to decide whether to use it.
+
+ * error.c (dump_type_real): Handle NAMESPACE_DECL.
+ * parse.y (base_class.1): Avoid crash on error.
+
+1998-09-08 Martin von Löwis <loewis@informatik.hu-berlin.de>
+
+ * decl.c (make_typename_type): If context is a namespace, the code
+ is in error.
+
+1998-09-08 Mumit Khan <khan@xraylith.wisc.edu>
* parse.y (nomods_initdcl0): Set up the parser stack correctly.
+1998-09-08 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (anonymous_namespace_name): Declare.
+ * decl.c: Define it.
+ (push_namespace): Use anonymous_namespace_name, rather than local
+ static anon_name.
+ * error.c (dump_decl): If a namespace is named
+ anonymous_namespace_name, call it {anonymous}.
+
+ * decl.c (grokparms): Distinguish between references and pointers
+ in error message.
+
+1998-09-08 Richard Henderson <rth@cygnus.com>
+ Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (process_partial_specialization): Consistently allocate
+ and zero tpd.parms based on ntparms. Use tpd2.parms, not
+ tpd.parms, where appropriate.
+
+Sun Sep 6 00:00:51 1998 Jeffrey A Law (law@cygnus.com)
+
+ * Makefile.in (INCLUDES): Update after recent toplevel gcc
+ reorganizations.
+
+1998-09-05 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TI_PENDING_SPECIALIZATION_FLAG): Remove.
+ * class.c (finish_struct): Remove hackery to deal with explicit
+ specializations in class scope.
+ * decl.c (grokfndecl): Improve error-recovery.
+ * decl2.c (grokfield): Likewise.
+ * pt.c (check_specialization_scope): New function.
+ (begin_specialization): Call it.
+ (process_partial_specialization): New function, split out from
+ push_template_decl. Check partial specializations more
+ stringently.
+ (push_template_decl): Call it.
+ (check_explicit_specialization): Don't attempt to handle explicit
+ specializations in class scope.
+ (template_parm_data): Document. Add current_arg and
+ arg_uses_template_parms.
+ (mark_template_parm): Set it.
+ (tsubst_arg_types): Remove unused variable.
+ * semantics.c (begin_class_definition): Tweak.
+
+1998-09-04 Mark Mitchell <mark@markmitchell.com>
+
+ * inc/typeinfo (type_info::type_info(const char*)): Make
+ `explicit'.
+
+ * cp-tree.h (hash_tree_cons_simple): New macro.
+ * pt.c (tsubst_arg_types): New function. Use hash_tree_cons.
+ (coerce_template_parms): Use make_temp_vec, instead of
+ make_tree_vec. Document this behavior.
+ (lookup_template_class): Likewise.
+ (tsubst, cases METHOD_TYPE, FUNCTION_TYPE): Use tsubst_arg_types.
+ Remove dead code (and add assertion to check its deadness). Fix
+ bug w.r.t. exception specifications.
+
+1998-09-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (import_export_vtable): Always make artificials comdat.
+ (import_export_decl): Likewise.
+ * pt.c (mark_decl_instantiated): Likewise.
+
+1998-09-03 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (finish_globally_qualified_member_call_expr):
+ Rename to ...
+ (finish_qualified_call_expr).
+ * semantics.c: Likewise.
+ * parse.y (primary): Use it.
+ * method.c (hack_identifier): Remove redundant code.
+
+ * init.c (resolve_offset_ref): Call convert_from_reference to
+ handle members of reference type. Improve error recovery.
+
+1998-09-03 Benjamin Kosnik <bkoz@cygnus.com>
+
+ * cp-tree.h: Declare warn_nontemplate_friend.
+ * decl2.c (lang_decode_option): Set.
+ * lang-options.h: Add -Wnon-template-friend.
+ * friend.c (do_friend): Use to toggle non-template function warning.
+
+1998-09-03 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (finish_enum): Don't resolve CONST_DECLs to their
+ corresponding INTEGER_CSTs when processing_template_decl.
+ * pt.c (tsubst_enum): Tweak accordingly.
+
+1998-09-03 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+
+ * decl.c (pushdecl_class_level): Add warning here.
+ (pushdecl): Tweak.
+
+1998-09-02 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cvt.c (convert_pointer_to_real): Tidy.
+ * search.c (get_base_distance_recursive): Simplify.
+ (get_base_distance): Likewise.
+
+ * pt.c (unify): Only special-case INTEGER_TYPE if it uses template
+ parms.
+
+Wed Sep 02 09:25:29 1998 Nick Clifton <nickc@cygnus.com>
+
+ * lex.c (check_newline): Call HANDLE_PRAGMA before
+ HANDLE_SYSV_PRAGMA if both are defined. Generate warning messages
+ if unknown pragmas are encountered.
+ (handle_sysv_pragma): Interpret return code from
+ handle_pragma_token (). Return success/failure indication rather
+ than next unprocessed character.
+ (pragma_getc): New function: retrieves characters from the
+ input stream. Defined when HANDLE_PRAGMA is defined.
+ (pragma_ungetc): New function: replaces characters back into the
+ input stream. Defined when HANDLE_PRAGMA is defined.
+
+1998-09-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (output_vtable_inherit): Use %cDIGIT in the operands.
+ * class.c (build_vtable_entry_ref): Likewise.
+
+1998-09-01 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION): New macro.
+ * decl2.c (import_export_decl): Likewise.
+ * pt.c (instantiate_decl): Use it.
+
+1998-09-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (lookup_name_real): Also do implicit typename thing for
+ artificial TYPE_DECLs.
+ * search.c (lookup_field): Likewise.
+ (lookup_fnfields, lookup_field): Adjust for implicit typename kludge.
+ * semantics.c (begin_constructor_declarator): Use enter_scope_of.
+ (enter_scope_of): Extract type from implicit typename.
+ (begin_class_definition): Likewise.
+ * lex.c (identifier_type): Handle implicit typename when checking
+ for SELFNAME.
+
+ * cp-tree.h: Declare flag_strict_prototype.
+ * lex.c (do_scoped_id, do_identifier): Don't implicitly_declare if
+ -fstrict-prototype.
+ * decl.c (init_decl_processing): If -f{no,-}strict-prototype wasn't
+ specified, set it to the value of pedantic.
+
+1998-09-01 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (arg_assoc): Handle template-id expressions as arguments.
+
+1998-08-31 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (finish_enum): Handle member enums of classes declared in
+ template functions.
+
+ * decl2.c (grok_x_components): Strip attributes before calling
+ groktypename.
+
+1998-08-31 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h, decl2.c: Remove support for -fall-virtual,
+ -fenum-int-equivalence and -fno-nonnull-objects.
+ * class.c (check_for_override): Remove support for -fall-virtual.
+ (finish_struct_1): Likewise.
+ * call.c (build_new_op): Remove support for -fenum-int-equivalence.
+ * typeck.c (build_binary_op_nodefault): Likewise.
+ * cvt.c (ocp_convert): Likewise.
+ * call.c (build_vfield_ref): Remove support for -fno-nonnull-objects.
+ * class.c (build_vbase_path): Likewise.
+
+Sun Aug 30 22:16:31 1998 H.J. Lu (hjl@gnu.org)
+
+ * Makefile.in (INTERFACE): New, set to 1.
+
+1998-08-30 Mark Mitchell <mark@markmitchell.com>
+
+ * error.c (dump_decl): Use CP_DECL_CONTEXT, not DECL_CONTEXT, when
+ comparing with global_namespace.
+ (dump_aggr_type): Likewise.
+
+ * decl.c (grokfndecl): Issue error on declaration of friend
+ templates with explicit template arguments.
+
+ * pt.c (convert_template_argument): New function, split out
+ from...
+ (coerce_template_parms): Here.
+ (tsubst): Attempt better error-recovery.
+
+1998-08-28 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * pt.c (decl_template_parm_p): Add checks for
+ TEMPLATE_TEMPLATE_PARM.
+
+1998-08-28 Mark Mitchell <mark@markmitchell.com>
+
+ * lex.c (do_identifier): Fix thinko in previous change.
+
+1998-08-28 Jason Merrill <jason@yorick.cygnus.com>
+
+ * search.c (dfs_search, binfo_for_vtable, dfs_bfv_helper): New fns.
+ * decl2.c (output_vtable_inherit): Call binfo_for_vtable.
+
+1998-08-28 Richard Henderson <rth@cygnus.com>
+
+ Add support for discarding unused virtual functions.
+ * lang-options.h: Add -fvtable-gc.
+ * cp-tree.h: Add flag_vtable_gc.
+ * decl2.c (output_vtable_inherit): New fn.
+ (finish_vtable_vardecl): Call it.
+ * class.c (build_vtable_entry_ref): New fn.
+ (build_vtbl_ref): Call it.
+
+1998-08-28 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (build_enumerator): Take the enumeration type as a
+ parameter.
+ * decl.c (finish_enum): Don't set the TREE_TYPE for the
+ enumeration constant values if we're processing_template_decls.
+ Don't set the type for the CONST_DECLs either; that's done in
+ build_enumerator.
+ (build_enumerator): Take the enumeration type as a
+ parameter.
+ * lex.c (do_identifier): Don't resolve enumeration constants while
+ processing template declarations, even if they happen to be
+ TEMPLATE_PARM_INDEXs.
+
+ * parse.y (current_enum_type): New variable.
+ (primary): Don't allow statement-expression in local classes just
+ as we don't in global classes.
+ (structsp): Use current_enum_type.
+ (enum_list): Likewise.
+ * pt.c (tsubst_enum): Don't check for NOP_EXPRs introduced by
+ finish_enum; they no longer occur.
+
+ * cp-tree.h (finish_base_specifier): New function.
+ * parse.y (base_class): Use it.
+ * semantics.c (finish_base_specifier): Define it.
+
+ * parse.y (structsp): Warn on use of typename outside of template
+ declarations.
+
+1998-08-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lex.c (handle_cp_pragma): Remove #pragma vtable.
+ * lang-options.h: Remove +e options.
+ * decl2.c (lang_decode_option): Likewise.
+ (import_export_vtable): Don't check write_virtuals.
+ (finish_vtable_vardecl, finish_file): Likewise.
+ * search.c (dfs_debug_mark): Likewise.
+ * semantics.c (begin_class_definition): Likewise.
+ * class.c (build_vtable, finish_vtbls, finish_struct_1): Likewise.
+
+ * call.c (build_over_call): Check flag_elide_constructors.
+ * decl2.c: flag_elide_constructors defaults to 1.
+ * typeck.c (convert_arguments): Remove return_loc parm.
+ (build_function_call_real): Adjust.
+
+ * search.c: Tear out all mi_matrix and memoize code.
+ (lookup_field, lookup_fnfields): Use scratch_tree_cons.
+ * lang-options.h: Remove documentation for -fhandle-exceptions,
+ -fmemoize-lookups and -fsave-memoized.
+ * cp-tree.h: Lose mi_matrix and memoize support.
+ * decl2.c: Ignore -fmemoize-lookups and -fsave-memoized.
+ * class.c: Lose struct class_level.
+ (pushclass, popclass): Lose memoize support.
+ * init.c (build_offset_ref): Likewise.
+
+ Never change BINFO_INHERITANCE_CHAIN.
+ * init.c (emit_base_init): Change modification of
+ BINFO_INHERITANCE_CHAIN to an assert.
+ * search.c (get_base_distance_recursive): Likewise.
+ (get_base_distance): Likewise.
+ (lookup_member): Likewise.
+ (convert_pointer_to_single_level): Likewise.
+ (lookup_field): Likewise. Lose setting TREE_VIA_* on TREE_LISTs.
+ (lookup_fnfields): Likewise.
+ * tree.c (propagate_binfo_offsets): Don't call unshare_base_binfos.
+ (unshare_base_binfos): Don't call propagate_binfo_offsets.
+ (layout_basetypes): Call propagate_binfo_offsets instead of
+ unshare_base_binfos.
+ * decl.c (xref_basetypes): Call unshare_base_binfos.
+ * pt.c (instantiate_class_template): Likewise.
+ * tree.c (reverse_path): Remove 'copy' parm; always make a
+ temporary copy.
+ * class.c (build_vbase_path): Just call it.
+ * search.c (compute_access): Likewise. Don't re-reverse.
+
+1998-08-27 Mark Mitchell <mark@markmitchell.com>
+
+ * class.c (build_vbase_path): Use reverse_path.
+ (finish_base_struct): Move warnings for inaccessible bases to
+ layout_basetypes.
+ (modify_one_vtable): Remove check of TREE_USED (binfo).
+ (fixup_vtable_deltas1): Likewise.
+ * cp-tree.h (BINFO_INHERITANCE_CHAIN): Document here.
+ (xref_tag): Remove binfos parameter.
+ (make_binfo): Remove chain parameter.
+ (reverse_path): Add copy parameter.
+ * decl.c (init_decl_processing): Change calls to xref_tag.
+ (xref_tag): Remove binfos parameter.
+ (xref_basetypes): Change calls to make_binfo.
+ * decl2.c (grok_x_components): Change calls to xref_tag.
+ (handle_class_head): Likewise.
+ * friend.c (do_friend): Likewise.
+ * lex.c (make_lang_type): Change calls to make_binfo.
+ * parse.y (structsp): Change calls to xref_tag.
+ (named_complex_class_head_sans_basetype): Likewise.
+ (named_class_head): Likewise.
+ * rtti.c (init_rtti_processing): Likewise.
+ * search.c (compute_access): Change calls to reverse_path.
+ (dfs_get_vbase_types): Change calls to make_binfo.
+ (get_vbase_types): Remove dead code.
+ * tree.c (unshare_base_binfos): Change calls to make_binfo.
+ (layout_basetypes): Warn here about inaccessible bases.
+ (make_binfo): Remove chain parameter.
+ (reverse_path): Add copy parameter.
+
+1998-08-27 Jason Merrill <jason@yorick.cygnus.com>
+
+ * class.c: #if 0 complete_type_p.
+ * init.c (build_java_class_ref, build_new_1): Remove unused locals.
+ * method.c (process_overload_item): Likewise.
+ * typeck.c (comp_target_types): Likewise.
+
+ Stop sharing binfos for indirect virtual bases.
+ * tree.c (propagate_binfo_offsets): Unshare vbases, too.
+ (layout_basetypes): Likewise.
+ (unshare_base_binfos): Copy vbases, too.
+ * cp-tree.h (BINFO_VIA_PUBLIC, BINFO_BASEINIT_MARKED,
+ BINFO_VBASE_INIT_MARKED): Remove obsolete macros.
+ (BINFO_PUSHDECLS_MARKED, SET_BINFO_PUSHDECLS_MARKED,
+ CLEAR_BINFO_PUSHDECLS_MARKED): New macros.
+ * search.c (lookup_field, lookup_fnfields, lookup_member): Remove
+ reference to BINFO_VIA_PUBLIC.
+ (marked_pushdecls_p, unmarked_pushdecls_p): New fns.
+ (push_class_decls): Use them.
+ (dfs_pushdecls): Use SET_BINFO_PUSHDECLS_MARKED.
+ (dfs_compress_decls): Use CLEAR_BINFO_PUSHDECLS_MARKED.
+
+1998-08-27 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (build_enumerator): Set DECL_CONTEXT for the
+ CONST_DECLs.
+
+1998-08-26 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (finish_enum): Change prototype.
+ * decl.c (finish_enum): Use TYPE_VALUES, rather than taking a
+ VALUES parameter. Don't try to compute mins/maxs if
+ processing_template_decl.
+ * parse.y (structsp): Use new calling sequence for finish_enum.
+ * pt.c (tsubst_enum): Likewise. Take the new type as input.
+ (lookup_template_class): Remove unused variables. Tweak.
+ Register enums on instantiation list before substituting
+ enumeration constants.
+ (tsubst_decl): Remove unused variables.
+ (regenerate_decl_from_template): Likewise.
+
+ * decl.c (duplicate_decls): Don't obliterate the
+ DECL_TEMPLATE_INFO for a template if we're not replacing it with
+ anything.
+
+ * lex.c (do_identifier): Fix typo in comment.
+
+Wed Aug 26 10:54:51 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * errfn.c: Remove stdarg.h/varargs.h.
+ * tree.c: Likewise.
+
+1998-08-25 Brendan Kehoe <brendan@cygnus.com>
+
+ * pt.c (tsubst_copy): Only do typename overloading on an
+ IDENTIFIER_NODE that happens to look like a typename if it actually
+ has a type for us to use.
+
+1998-08-25 Jason Merrill <jason@yorick.cygnus.com>
+
+ * typeck.c (comp_cv_target_types): Split out...
+ (comp_target_types): From here. Don't allow cv-qual changes under
+ a pointer if nptrs == 0. Fix OFFSET_TYPE handling.
+ (build_ptrmemfunc): Pass 1 to nptrs.
+ * cvt.c (perform_qualification_conversions): Use comp_ptr_ttypes.
+
+1998-08-25 Mark Mitchell <mark@markmitchell.com>
+
+ * search.c (dependent_base_p): Don't compare a binfo to
+ current_class_type; use the TREE_TYPE of the binfo instead.
+
+ * cp-tree.h (CLASS_TYPE_P): Revise definition.
+
1998-08-25 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (duplicate_decls): Don't complain about different
exceptions from an internal decl even if pedantic.
+ * typeck.c (convert_for_assignment): Converting from pm of vbase
+ to derived is an error, not a sorry.
+
+ * call.c (build_over_call): Use convert_pointer_to_real for 'this'.
+ * class.c (fixed_type_or_null): Rename from
+ resolves_to_fixed_type_p. Return the dynamic type of the
+ expression, if fixed, or null.
+ (resolves_to_fixed_type_p): Use it. Return 0 if the dynamic type
+ does not match the static type.
+ (build_vbase_path): Rename 'alias_this' to 'nonnull'. Use
+ resolves_to_fixed_type_p again.
+
+1998-08-24 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (tsubst_decl): Move special case code for dealing with
+ tricky friend templates here from ...
+ (regenerate_decl_from_template): Here.
+
+1998-08-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (start_decl): Remove redundant linkage check.
+
1998-08-24 Gavin Romig-Koch <gavin@cygnus.com>
* typeck.c (c_expand_return): Handle the case that valtype
is wider than the functions return type.
+1998-08-24 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (CLASS_TYPE_P): New macro.
+ * decl.c (grokdeclarator): Use it instead of IS_AGGR_TYPE.
+ * pt.c (process_template_parm): Undo previous change.
+
+1998-08-24 Benjamin Kosnik <bkoz@cygnus.com>
+
+ * cp-tree.h: Declare.
+ * pt.c (decl_template_parm_p): New function.
+ * decl.c (pushdecl): Check decls for redeclaring template parms.
+ (xref_tag): Make redeclaration an error, print decl.
+ * decl2.c (grokfield): Check field_decls for redeclaration as well.
+
+1998-08-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (primary): Fix up the type of string constants.
+
+1998-08-24 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (convert_for_initialization): Move check for odd uses
+ of NULL to avoid duplicate warnings.
+
+1998-08-24 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (lvalue_type): Fix for arrays.
+ * typeck.c (string_conv_p): New fn.
+ (convert_for_assignment): Use it.
+ (build_unary_op): Use lvalue_type.
+ * call.c (standard_conversion, convert_like): Use string_conv_p.
+ (add_function_candidate): Use lvalue_type.
+ * cvt.c (convert_to_reference): Likewise.
+ * decl2.c (lang_decode_option): Ignore -traditional.
+ * decl.c (init_decl_processing): flag_writable_strings inhibits
+ flag_const_strings.
+
+1998-08-24 Andrew MacLeod <amacleod@cygnus.com>
+
+ * lang-options.h (lang_options): Add fconst-strings to the list
+ of valid options.
+ * decl2.c (lang_f_options, lang_decode_option): Likewise.
+
+1998-08-24 Nathan Sidwell <nathan@acm.org>
+
+ * lex.c (real_yylex): Don't warn about long long constants if
+ we're allowing long long.
+
1998-08-24 Martin von Löwis <loewis@informatik.hu-berlin.de>
+ * decl.c (pushdecl): Use IDENTIFIER_NAMESPACE_VALUE instead of
+ accessing bindings directly.
+
* search.c (my_tree_cons): Reimplement.
+ * lang-specs.h: Remove __HONOR_STD.
+ * inc/exception, inc/new, inc/new.h, inc/typeinfo: Likewise.
+
+1998-08-23 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (grokdeclarator): Complain about in-class initialization
+ of aggregates and/or references.
+ * pt.c (process_template_parm): Clear IS_AGGR_TYPE for
+ TEMPLATE_TYPE_PARMs.
+
+ * decl2.c (grok_array_decl): Add comment.
+ (mark_used): Don't instantiate an explicit instantiation.
+ * friend.c (make_friend_class): Remove bogus comment. Fix check
+ for partial specializations.
+ * pt.c (check_explicit_specialization): Don't
+ SET_DECL_EXPLICIT_INSTANTIATION here.
+ (mark_decl_instantiated): Or here.
+ (do_decl_instantiation): Do it here, instead. Add checks for
+ duplicate explicit instantiations, etc. Tidy.
+ (do_type_instantiation): Likewise.
+ (instantiate_decl): Improve comments. Complain about explicit
+ instantiations where no definition is available.
+
+ * cp-tree.h (ansi_null_node): Remove.
+ * call.c (build_over_call): Warn about converting NULL to an
+ arithmetic type.
+ * cvt.c (build_expr_type_conversion): Likewise. Use
+ null_ptr_cst_p instead of expanding it inline.
+ * decl.c (ansi_null_node): Remove.
+ (init_decl_processing): Make null_node always have integral type.
+ * except.c (build_throw): Warn about converting NULL to an
+ arithmetic type.
+ * lex.c (init_parse): Remove handling of ansi_null_node.
+ * pt.c (type_unification_real): Don't convert NULL to void* type.
+ * typeck.c (build_binary_op_nodefault): Fix NULL warnings.
+ (convert_for_assignment): Warn about converting NULL to an
+ arithmetic type.
+ (convert_for_initialization): Likewise.
+
+1998-08-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (search_tree, no_linkage_helper, no_linkage_check): New fn.
+ * pt.c (coerce_template_parms): Use no_linkage_check.
+ * decl.c (grokvardecl): Likewise.
+ (grokfndecl): Likewise. Members of anonymous types have no linkage.
+
+ * method.c (process_overload_item): Remove useless code.
+
+1998-08-20 Per Bothner <bothner@cygnus.com>
+
+ Handle new'ing of Java classes.
+ * init.c (build_class_classref): New function.
+ (build_new_1): If type is TYPE_FOR_JAVA: Call _Jv_AllocObject;
+ constructor does not return this; don't need to exception-protect.
+
+ * pt.c (lookup_template_class): Copy TYPE_FOR_JAVA flag.
+ * decl2.c (acceptable_java_type): Handle template-derived types.
+
+1998-08-20 Per Bothner <bothner@cygnus.com>
+
+ * decl2.c (import_export_vtable): Suppress vtables for Java classes.
+
+1998-08-20 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (duplicate_decls): Always merge the old and new patterns
+ for templates, regardless of whether or not the new one has
+ DECL_INITIAL. Don't throw away specializations. Merge
+ DECL_SAVED_TREE.
+ * pt.c (tsubst_decl): Use the right pattern when calculating the
+ complete args for a new template instance.
+ (do_decl_instantiation): Fix typo in comment.
+ (regenerate_decl_from_template): Deal with tricky friend template
+ case.
+ (instantiate_decl): Likewise.
+
+Thu Aug 20 09:09:45 1998 Jeffrey A Law (law@cygnus.com)
+
+ * init.c (build_builtin_delete_call): Add missing assemble_external
+ call.
+
+1998-08-20 Jason Merrill <jason@yorick.cygnus.com>
+
+ * parse.y (notype_unqualified_id): Also accept ~A<int>.
+
+1998-08-19 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (build_binary_op_nodefault): Warn on use of NULL in
+ arithmetic.
+ * except.c (build_throw): Warn when NULL is thrown, even with
+ -ansi. Use ansi_null_node, rather than integer_zero_node, in the
+ thrown expression.
+
+ * cp-tree.h (ansi_null_node): New variable.
+ * decl.c (ansi_null_node): New variable.
+ (init_decl_processing): Initialize its type.
+ * lex.c (init_parse): Initialize its value. Use ansi_null_node
+ for null_node in non-ANSI mode.
+ * typeck.c (build_binary_op_nodefault): Use ansi_null_node in
+ place of null_node to avoid spurious errors.
+
+1998-08-17 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (enter_scope_of): New function.
+ * parse.y (complex_direct_notype_declarator): Use it.
+ * semantics.c (enter_scope_of): New function.
+
1998-08-17 Jason Merrill <jason@yorick.cygnus.com>
+ * decl.c (grokparms): No, here.
+
+ * decl.c (grokdeclarator): Catch parm with pointer to array of
+ unknown bound here...
+ * method.c (process_overload_item): ...not here.
+
+ * gxxint.texi: Remove obsolete documentation of overloading code.
+
* decl.c (finish_enum): Also set TYPE_SIZE_UNIT.
* class.c (finish_struct_bits): Likewise.
-1998-08-17 Mark Mitchell <mark@markmitchell.com>
+ * tree.c (lvalue_type): Fix for arrays.
+ * typeck.c (build_unary_op): Use lvalue_type.
+ * call.c (add_function_candidate): Likewise.
+ * cvt.c (convert_to_reference): Likewise.
+
+ * decl2.c (lang_decode_option): Ignore -traditional.
+
+ * init.c (build_offset_ref): Don't mess with error_mark_node.
+ * lex.c (do_scoped_id): Use cp_error.
+
+ * rtti.c (get_tinfo_fn): Don't mess with the context for now.
+
+1998-08-17 Benjamin Kosnik <bkoz@loony.cygnus.com>
+
+ * decl.c (grokdeclarator): Allow anonymous types to be cv-qualified.
+
+Mon Aug 17 10:40:18 1998 Jeffrey A Law (law@cygnus.com)
+
+ * cp-tree.h (set_identifier_local_value): Provide prototype.
+
+ * decl2.c (do_namespace_alias): Remove unused variables `binding'
+ and `old'.
+
+Fri Aug 14 16:42:27 1998 Nick Clifton <nickc@cygnus.com>
+
+ * Makefile.in: Rename BBISON to BISON so that it can be properly
+ inherited from the parent makefile.
+
+1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * lang-options.h: Add -finit-priority.
+ * decl2.c: Likewise. Check flag_init_priority instead of
+ USE_INIT_PRIORITY.
+
+ * decl2.c (setup_initp): New fn.
+ (start_objects, finish_objects, do_ctors): Handle init_priority.
+ (do_dtors, finish_file): Likewise.
+
+1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst_copy): Hush warning.
+
+ * rtti.c (get_tinfo_fn): Also set DECL_IGNORED_P.
+
+1998-08-12 Mark Mitchell <mark@markmitchell.com>
+
+ * pt.c (print_template_context): Don't abort when instantiating a
+ synthesized method.
+
+ * decl.c (grokdeclarator): Issue errors on namespace qualified
+ declarators in parameter lists or in class scope.
+
+1998-08-09 Mark Mitchell <mark@markmitchell.com>
* pt.c (check_explicit_specialization): Don't abort on bogus
explicit instantiations.
-1998-08-14 Jason Merrill <jason@yorick.cygnus.com>
+1998-08-07 Mark Mitchell <mark@markmitchell.com>
+
+ * typeck.c (require_complete_type): Use complete_type_or_else.
+ (complete_type_or_else): Always return NULL_TREE on failure, as
+ documented.
+
+ * pt.c (tsubst_aggr_type): Prototype.
+ (tsubst_decl): New function, split out from tsubst. Set
+ input_filename and lineno as appropriate.
+ (pop_tinst_level): Restore the file and line number saved in
+ push_tinst_level.
+ (instantiate_class_template): Set input_filename and lineno as
+ appropriate.
+ (tsubst): Move _DECL processing to tsubst_decl. Make sure the
+ context for a TYPENAME_TYPE is complete.
+
+ * decl2.c (grokbitfield): Issue errors on bitfields declared with
+ function type.
+ (do_dtors): As in do_ctors, pretend to be a member of the same
+ class as a static data member while generating a call to its
+ destructor.
- * rtti.c (get_tinfo_fn): Don't mess with the context for now.
+ * cvt.c (cp_convert_to_pointer): Handle NULL pointer
+ conversions, even in complex virtual base class hierarchies.
-1998-08-13 Mumit Khan <khan@xraylith.wisc.edu>
+1998-08-06 Mark Mitchell <mark@markmitchell.com>
- * decl2.c (import_export_class): Don't use dllexport
- attribute as a heuristic.
+ * cp-tree.h (ENUM_TEMPLATE_INFO): New macro.
+ (TYPE_TEMPLATE_INFO): Likewise.
+ (SET_TYPE_TEMPLATE_INFO): Likewise.
+ (ENUM_TI_TEMPLATE): Likewise.
+ (ENUM_TI_ARGS): Likewise.
+ (lookup_nested_type_by_name): Remove.
+ * decl.c (maybe_process_template_type_declaration): Handle enums.
+ (start_enum): Don't check for primary-template enum declarations
+ here.
+ (finish_enum): Clean up, document. Make sure template enum
+ constants get the correct type.
+ (build_enumerator): Copy initializers for template enumerations,
+ too.
+ (grok_enum_decls): Document.
+ * lex.c (do_identifier): Document use of LOOKUP_EXPR a bit
+ better. Build LOOKUP_EXPRs for local variables, even if they are
+ TREE_PERMANENT.
+ * pt.c (tsubst_enum): Remove field_chain parameter.
+ (template_class_depth): Include the depth of surrounding function
+ contexts.
+ (push_template_decl): Check for primary-template enum declarations
+ here. Deal with enumeration templates.
+ (lookup_template_class): Likewise.
+ (for_each_template_parm): Likewise.
+ (instantiate_class_template): Don't call tsubst_enum directly,
+ call tsubst instead, to instantiate enums. Deal with all
+ field_chain issues here, not in tsubst_enum.
+ (lookup_nested_type_by_name): Remove.
+ (tsubst_aggr_type): Revise handling of enumeration types.
+ (tsubst): Likewise.
+ (tsubst_copy): Likewise.
+ (tsubst_expr): Call tsubst, not tsubst_enum for TAG_DEFNs.
+
+1998-08-04 Mark Mitchell <mark@markmitchell.com>
+
+ * decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
+ uses template parameters.
+ * method.c (build_template_parm_names): Use the full set of
+ template arguments for tsubst'ing.
+ (build_overload_identifier): Pass the full set of template
+ arguments to build_template_parm_names, not just the
+ innermost_args.
+ * pt.c (TMPL_ARGS_DEPTH): Define using
+ TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity.
+ (NUM_TMPL_ARGS): New macro.
+ (add_outermost_template_args): Deal with the case where the outer
+ args will be completely discarded.
+ (coerce_template_parms): Use the full set of template arguments
+ for tsubst'ing. Simplify. Add some asserts. Improve
+ error messages.
+ (lookup_template_class): Pass the full set of template arguments
+ to coerce_template_parms.
+ (tsubst): Add assertion.
+ (do_type_instantiation): Don't instantiate member template
+ classes.
+
+ * init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose
+ name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE.
+
+1998-08-03 Jason Merrill <jason@yorick.cygnus.com>
+
+ * method.c (set_mangled_name_for_decl): Change return type to void.
+
+ * decl.c (lookup_name_real): A namespace-level decl takes priority
+ over implicit typename. Avoid doing the same lookup twice.
+
+ * search.c (dependent_base_p): New fn.
+ (dfs_pushdecls, dfs_compress_decls): Use it.
+
+ * typeck.c (get_member_function_from_ptrfunc): Don't try to handle
+ virtual functions if the type doesn't have any.
+
+1998-08-03 Mark Mitchell <mark@markmitchell.com>
+
+ * decl2.c (grokfield): Don't mangle the name of a TYPE_DECL if it
+ uses template parameters.
+
+1998-08-02 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.def (LOOKUP_EXPR): Document. Remove second argument.
+ * cp-tree.h (DECL_TI_TEMPLATE): Improve documentation.
+ * lex.c (do_identifier): Don't use a second argument, or a type,
+ when building LOOKUP_EXPRs.
+ (do_identifier): Likewise.
+ (do_scoped_id): Likewise.
+ * method.c (hack_identifier): Improve error message.
+ * pt.c (lookup_template_function): Don't needlessly call
+ copy_to_permanent or build_min.
+ (tsubst_copy): Remove #if 0'd code. tsubst into LOOKUP_EXPRs if
+ necessary.
+ (do_decl_instantiation): Improve error message.
+ * tree.c (mapcar, case LOOKUP_EXPR): Don't be sorry; make a copy.
+ (build_min): Copy the type to the permanent obstack, too.
+
+1998-08-01 Jason Merrill <jason@yorick.cygnus.com>
+
+ * init.c (init_init_processing): Remove BI* handling.
+ (build_builtin_call): Remove.
+ (build_builtin_delete_call): New fn.
+ (build_delete): Use it.
+
+1998-07-31 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (PROCESSING_REAL_TEMPLATE_DECL_P): New macro.
+ (maybe_check_template_type): New function.
+ * decl.c (maybe_process_template_type_declaration): New function,
+ split out from pushtag Call maybe_check_template_type.
+ (pushtag): Use it. Use PROCESSING_REAL_TEMPLATE_DECL_P.
+ (xref_tag): Use PROCESSING_REAL_TEMPLATE_DECL_P.
+ * friend.c (do_friend): Use PROCESSING_REAL_TEMPLATE_DECL_P.
+ * pt.c (template_class_depth_real): Generalization of ...
+ (template_class_depth): Use it.
+ (register_specialization): Use duplicate_decls for duplicate
+ declarations of specializations.
+ (maybe_check_template_type): New function.
+ (push_template_decl_real): Fix comment.
+ (convert_nontype_argument): Likewise.
+ (lookup_template_class): Likewise. Avoid an infinite loop on
+ erroneous code.
+ (tsubst_friend_function): Fix comment.
+ (tsubst, case FUNCTION_DECL): Deal with a DECL_TI_TEMPLATE that is
+ an IDENTIFIER_NODE.
+ * semantics.c (begin_function_definition): Use
+ reset_specialization to note that template headers don't apply
+ directly to declarations after the opening curly for a function.
1998-07-29 Jason Merrill <jason@yorick.cygnus.com>
@@ -155,13 +5014,141 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* decl.c (lookup_name_real): Fix typo.
+1998-07-28 Mark Mitchell <mark@markmitchell.com>
+
+ * friend.c (is_friend): Be lenient with member functions to deal
+ with nested friends.
+
1998-07-28 Jason Merrill <jason@yorick.cygnus.com>
* class.c (finish_struct_1): Convert integer_zero_node to
- ssizetype before passing it to set_rtti_entry.
+ ssizetype before passing it to set_rtti_entry.
* typeck2.c (initializer_constant_valid_p): Allow conversion of 0
of any size to a pointer.
+1998-07-27 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.h (TI_USES_TEMPLATE_PARMS): Remove.
+ (build_template_decl_overload): Remove.
+ (set_mangled_name_for_decl): New function.
+ (innermost_args): Remove is_spec parameter.
+ (most_specialized, most_specialized_class): Remove declarations.
+ (lookup_template_class): Add entering_scope parameter.
+ (maybe_process_partial_specialization): New function.
+ (finish_template_decl): Likewise.
+ (finish_template_type): Likewise.
+ * class.c (finish_struct): Clean up processing of member template
+ specializations.
+ * decl.c (pushtag): Fix formatting.
+ (lookup_tag): Improve handling of pseudo-global levels.
+ (make_typename_type): Adjust call to lookup_template_class.
+ (shadow_tag): Use maybe_process_partial_specialization.
+ (xref_tag): Improve handling of member friends.
+ (start_function): Call push_nested_class before
+ push_template_decl. Don't call push_template_decl for
+ specializations.
+ * decl2.c (grok_x_components): Don't call xref_tag for
+ template instantiations. Handle UNION_TYPEs like RECORD_TYPEs.
+ (grokclassfn): Use set_mangled_name_for_decl.
+ (arg_assoc_class): Adjust call to innermost_args.
+ (mark_used): Don't call instantiate_decl for a TEMPLATE_DECL.
+ * error.c (dump_function_name): Improve printing of template
+ function names.
+ * friend.c (is_friend): Don't compare types of decls to determine
+ friendship, unless flag_guiding_decls.
+ (make_friend_class): Partial specializations cannot be friends.
+ (do_friend): Use set_mangled_name_for_decl. Call
+ push_template_decl_real instead of push_template_decl.
+ * method.c (build_decl_overload_real): Remove prototype. Give it
+ external linkage.
+ (build_overload_identififer): Adjust call to innermost_args.
+ (build_template_decl_overload): Remove.
+ (set_mangled_name_for_decl): New function.
+ * parse.y (.finish_template_type): New non-terminal.
+ (template_def): Use finish_template_decl. Use template_extdef
+ instead of extdef.
+ (template_extdef, template_datadef): New non-terminals, containing
+ only those rules for things which can be templates.
+ (datadef): Tidy.
+ (template_type, self_template_type): Use .finish_template_type.
+ (named_class_head): Use maybe_process_partial_specialization.
+ * pt.c (mangle_class_name_for_template): Remove context parameter.
+ (get_class_bindings): Remove outer_args parameter.
+ (complete_template_args): Remove.
+ (add_outermost_template_args): New function.
+ (register_specialization): Return the specialization.
+ (unregister_specialization): New function.
+ (tsubst_template_parms): Likewise.
+ (most_specialized, most_specialized_class): Prototype here as
+ static.
+ (original_template): Rename to most_general_template.
+ (tsubst_template_parms): New function.
+ (set_mangled_name_for_template_decl): Likewise.
+ (TMPL_ARGS_DEPTH): New macro.
+ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Adjust.
+ (TMPL_ARGS_LEVEL): New macro.
+ (SET_TMPL_ARGS_LEVEL): Likewise.
+ (TMPL_ARG): Likewise.
+ (SET_TMPL_ARG): Likewise.
+ (TMPL_ARGS_DEPTH): Likewise.
+ (finish_member_template_decl): Use finish_template_decl.
+ (maybe_process_partial_specialization): New function, split out
+ from tsubst.
+ (inline_needs_template_parms): Use TMPL_PARMS_DEPTH.
+ (maybe_begin_member_template_processing): Use new macros.
+ (is_member_template): Likewise.
+ (is_member_template_class): Likewise.
+ (add_to_template_args): Likewise. Deal with multiple levels of
+ args.
+ (maybe_process_partial_specialization): New function.
+ (retrieve_specialization): Add consistency check.
+ (determine_specialization): Return full argument list.
+ (check_explicit_specialization): Tweak friend handling. Use full
+ argument lists. Simplify.
+ (current_template_args): Use new macros.
+ (push_template_decl_real): Change ill-named mainargs to specargs.
+ Check that a partial specialization actually specializes at least
+ one parameter. Improve friend handling. Modify for full
+ template arguments.
+ (classtype_mangled_name): Don't mangle the names of
+ specializations.
+ (lookup_template_class): Add entering_scope parameter. Use it to
+ avoid finding a template type when an instantiation is required.
+ Simplify. Use full template arguments.
+ (tsubst_friend_function): Use unregister_specialization. Use new
+ macros. Use full template arguments.
+ (tsubst_friend_class): Substitute, using tsubst_template_parms,
+ into the template parameters before passing them to
+ redeclare_class_template.
+ (instantiate_class_template): Simplify. Use full template
+ arguments. Adjust calls to get_class_bindings. Use
+ SET_IDENTIFIER_TYPE_VALUE where needed. Improve friend handling.
+ (innermost_args): Use new macros.
+ (tsubst_aggr_type): New function, split out from tsubst.
+ (tsubst): Use tsubst_aggr_type, tsubst_template_parms, new calling
+ conventions for lookup_template_class. Refine handling of partial
+ instantiations. Remove calls to complete_template_args.
+ Simplify. Add consistency checks. Use set_mangled_name_for_decl
+ and set_mangled_name_for_template_decl.
+ (tsubst_copy): Use tsubst_aggr_type.
+ (instantiate_template): Use full template arguments.
+ (more_specialized): Improve formatting.
+ (more_specialized_class): Adjust calls to get_class_bindings.
+ (get_bindings_real): Don't call complete_template_args.
+ (most_specialized): Don't overwrite input; create a new list.
+ (most_specialized_class): Use most_general_template.
+ (regenerate_decl_from_template): Use unregister_specialization.
+ Use full template arguments.
+ (instantiate_decl): Use full template arguments.
+ (set_mangled_name_for_template_decl): New function.
+ * semantics.c (begin_class_definition): Use
+ maybe_process_partial_specialization.
+ (finish_member_class_template): New function.
+ (finish_template_decl): Likewise.
+ (finish_template_type): Likewise.
+ (typeck.c): Don't crash after issuing a compiler_error.
+ * Makefile.in (CONFLICTS): Adjust; we removed a s/r conflict.
+
1998-07-27 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (build_functional_cast): Handle default-initialization.
@@ -174,6 +5161,11 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* tree.c (ovl_member): Fix for single function in OVL.
+1998-07-27 Dave Brolley <brolley@cygnus.com>
+
+ * c-lex.c (yylex): Fix boundary conditions in character literal and
+ string literal loops.
+
1998-07-24 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (lookup_name_real): OK, do return the from_obj value
@@ -217,7 +5209,7 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
(finish_prevtable_vardecl): From here.
* class.c (finish_struct_1): Call import_export_class if at_eof.
- * decl.c (start_function): #if 0 mysterious code I wrote and have
+ * decl.c (start_function): #if 0 mysterious code I wrote and have
forgotten why.
* rtti.c (get_tinfo_fn): If this is for a class type, set
DECL_CONTEXT.
@@ -237,6 +5229,14 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* method.c (process_overload_item): Use build_overload_value for
arrays.
+1998-07-20 Dave Brolley <brolley@cygnus.com>
+
+ * lex.c (mbchar.h): #include it.
+ (GET_ENVIRONMENT): New macro.
+ (init_parse): Set character set based on LANG environment variable.
+ (real_yylex): Handle multibyte characters in character literals.
+ (real_yylex): Handle multibyte characters in string literals.
+
1998-07-19 Jason Merrill <jason@yorick.cygnus.com>
* lex.c (do_identifier): Look for class value even if we don't
@@ -252,7 +5252,7 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* decl.c (pushtag): Don't put out debugging information for
compiler-generated typedefs.
-
+
* error.c (dump_type_real): Don't crash when presented with
intQI_type_node or the like.
@@ -369,7 +5369,7 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
(cat_namespace_levels): Ignore aliases.
(duplicate_decls): Ignore duplicate aliases.
* decl2.c (do_namespace_alias): Process block level namespace
- aliases. Store alias with pushdecl. Remove odr errors.
+ aliases. Store alias with pushdecl. Remove odr errors.
* parse.y (namespace_alias): New non-terminal.
(extdef): Use it.
@@ -405,6 +5405,12 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
* decl2.c (namespace_ancestor): Use CP_DECL_CONTEXT.
(arg_assoc): Don't skip the first argument of a function.
+Tue Jul 14 20:09:22 1998 Jeffrey A Law (law@cygnus.com)
+
+ * search.c (my_tree_cons): Clean up.
+
+1998-07-14 Jason Merrill <jason@yorick.cygnus.com>
+
* call.c (joust): Don't warn about "confusing" conversions to the
same type.
@@ -420,14 +5426,14 @@ Fri Oct 2 02:07:26 1998 Mumit Khan <khan@xraylith.wisc.edu>
of namespace-qualified ids to -1, enter the namespace.
* method.c (build_template_decl_overload): Expect _DECL as first
- parameter. Put context temporarily into current_namespace.
+ parameter. Put context temporarily into current_namespace.
* pt.c (check_explicit_specialization): Change caller.
(tsubst): Likewise.
* init.c (build_offset_ref): Call mark_used and
convert_from_reference for namespace members.
-Mon Jul 13 23:25:28 1998 Martin von Lvwis <loewis@informatik.hu-berlin.de>
+Mon Jul 13 23:25:28 1998 Martin von Löwis <loewis@informatik.hu-berlin.de>
* search.c (my_tree_cons): The bitfield is at index 2.
@@ -435,7 +5441,7 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
* lang-options.h: Format changed to work with new --help support
in gcc/toplev.c
-
+
1998-07-12 Martin von Löwis <loewis@informatik.hu-berlin.de>
* decl2.c (build_expr_from_tree): Change calls of do_identifier.
@@ -472,14 +5478,14 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
* decl.c (xref_baseypes): Change caller.
* friend.c (make_friend_class): Likewise.
-1998-07-12 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+1998-07-12 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
- * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter
+ * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter
comparison.
- * pt.c (for_each_template_parm, case TEMPLATE_DECL): If it is a
+ * pt.c (for_each_template_parm, case TEMPLATE_DECL): If it is a
template template parameter, record its use.
- (for_each_template_parm, case TEMPLATE_TEMPLATE_PARM): Traverse
+ (for_each_template_parm, case TEMPLATE_TEMPLATE_PARM): Traverse
its template arguments if exists.
* pt.c (coerce_template_template_parms): New function equivalent
@@ -493,17 +5499,17 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
current_class_type. Don't display error message when COMPLAIN is
false.
-1998-07-12 Klaus Kaempf (kkaempf@progis.de)
+1998-07-12 Klaus Kaempf (kkaempf@progis.de)
- * repo.c (get_base_filename): Use file_name_nondirectory.
- (open_repo_file): Ditto.
+ * repo.c (get_base_filename): Use file_name_nondirectory.
+ (open_repo_file): Likewise.
* cp-tree.h (file_name_nondirectory): Add prototype.
1998-07-12 Jason Merrill <jason@yorick.cygnus.com>
* friend.c (do_friend): Pull the identifier out of declarator.
Use cp_error and friends.
- * decl2.c (qualified_lookup_using_namespace): Fix call to
+ * decl2.c (qualified_lookup_using_namespace): Fix call to
purpose_member.
* decl.c (lookup_name_real): Don't call complete_type on a namespace.
(grokvardecl): Use DECL_CLASS_SCOPE_P.
@@ -511,7 +5517,7 @@ Mon Jul 13 17:21:01 1998 Nick Clifton <nickc@cygnus.com>
* class.c (warn_hidden): Fix for OVERLOAD.
From grahams@rcp.co.uk:
* cp-tree.h (DEFARG_NODE_CHECK): New macro.
- (DEFARG_LENGTH, DEFARG_POINTER): Use it.
+ (DEFARG_LENGTH, DEFARG_POINTER): Use it.
Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com)
@@ -577,7 +5583,7 @@ Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com)
* decl2.c: Define them.
(lang_decode_option): Handle them.
* lang-options.h: Add -foptional-diags.
- * class.c (finish_struct): Don't complain about multiple meanings of
+ * class.c (finish_struct): Don't complain about multiple meanings of
name if -fno-optional-diags.
* decl.c (pushdecl_class_level): Likewise.
* lex.c (real_yylex): Check warn_multichar.
@@ -590,8 +5596,8 @@ Sun Jul 12 01:20:57 1998 Jeffrey A Law (law@cygnus.com)
1998-06-30 Benjamin Kosnik <bkoz@bliss.nabi.net>
- * decl2.c (lang_decode_option): Remove warn_template_debugging.
- * lang-options.h: Ditto.
+ * decl2.c (lang_decode_option): Remove warn_template_debugging.
+ * lang-options.h: Likewise.
Mon Jun 29 20:17:40 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -613,7 +5619,7 @@ Sat Jun 27 23:34:18 1998 Fred Fish <fnf@ninemoons.com>
Sat Jun 27 12:22:56 1998 Jeffrey A Law (law@cygnus.com)
- * Make-lang.in (g++): Depend on mkstemp.o. Link in mkstemp.o
+ * Make-lang.in (g++): Depend on mkstemp.o. Link in mkstemp.o
Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -636,7 +5642,7 @@ Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* cp-tree.h (mark_all_runtime_matches): Add function prototype.
* except.c (mark_all_runtime_matches): Set TREE_SYMBOL_REFERENCED
- flag for all function decls which are in the exception table.
+ flag for all function decls which are in the exception table.
* exception.cc (__cplus_type_matcher): Check for CATCH_ALL_TYPE match.
* decl2.c (finish_file): Call mark_all_runtime_matches to make sure
code is emitted for any referenced rtti function.
@@ -704,7 +5710,7 @@ Sat Jun 27 07:36:09 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* exception.cc (struct cp_eh_info): Add original_value field.
(__cplus_type_matcher): Perform type matching on the original exception
value, and if we have a match, set the current value.
- (__cp_push_exception): Set the original expcetion value.
+ (__cp_push_exception): Set the original exception value.
1998-06-23 Jason Merrill <jason@yorick.cygnus.com>
@@ -739,8 +5745,8 @@ Mon Jun 22 08:50:26 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
Fri Jun 19 23:22:42 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * typeck2.c (pop_init_level): Warn about implicit zero initialization
- of struct members.
+ * typeck2.c (pop_init_level): Warn about implicit zero initialization
+ of struct members.
Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -785,7 +5791,7 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-06-16 Andrew MacLeod <amacleod@cygnus.com>
- * decl.c (grokvardecl): Don't build external assembler names for
+ * decl.c (grokvardecl): Don't build external assembler names for
TYPENAMEs in other namespaces as there is no declarator.
* error.c (cp_file_of, cp_line_of): Don't extract file or line number
info from DECL_CONTEXT if it is NULL.
@@ -821,7 +5827,7 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(pointer_diff): Likewise.
* pt.c (for_each_template_parm): Traverse the TYPE_CONTEXT for
- types.
+ types.
* search.c (get_matching_virtual): Note that member templates
cannot override virtual functions.
@@ -856,7 +5862,7 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-06-11 Benjamin Kosnik <bkoz@elmo.cygnus.com>
* friend.c (do_friend): Add support for nested classes using
- member functions of the enclosing class as friends.
+ member functions of the enclosing class as friends.
1998-06-10 Mark Mitchell <mark@markmitchell.com>
@@ -870,9 +5876,9 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(expand_member_init): Remove much of this code; it is dead.
* typeck.c (convert_arguments): Use convert_default_arg and
convert_arg_for_ellipsis, rather than duplicating here.
-
- * call.c (convert_like): Don't fail silently if
- build_user_type_conversion fails. Always return error_mark_node
+
+ * call.c (convert_like): Don't fail silently if
+ build_user_type_conversion fails. Always return error_mark_node
for failure.
1998-06-10 Jason Merrill <jason@yorick.cygnus.com>
@@ -931,8 +5937,8 @@ Thu Jun 18 09:32:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-06-10 Branko Cibej <branko.cibej@hermes.si>
- * typeck.c (c_expand_return): Don't warn about void expressions on
- return statements in functions returning void.
+ * typeck.c (c_expand_return): Don't warn about void expressions on
+ return statements in functions returning void.
1998-06-09 Mark Mitchell <mark@markmitchell.com>
@@ -959,26 +5965,26 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* Makefile.in (decl2.o): Depend on dwarf2out.h and dwarfout.h.
* cp-tree.h: Add prototype for `maybe_print_template_context' and
- `maybe_make_one_only'.
+ `maybe_make_one_only'.
* decl.c (auto_function): Remove unused variable `decl'.
* decl2.c: Include dwarf2out.h and dwarfout.h.
* lex.c: Remove redundant declarations of `set_float_handler' and
- `asm_out_file'.
+ `asm_out_file'.
1998-06-08 Andrew MacLeod <amacleod@cygnus.com>
- * except.c (init_exception_processing): Remove NEW_EH_MODEL compile
+ * except.c (init_exception_processing): Remove NEW_EH_MODEL compile
time flag. Call __cp_eh_info instead of __cp_exception_info.
* exception.cc (struct cp_eh_info): Remove NEW_EH_MODEL flag.
- (__cp_exception_info): Return offset into cp_eh_info structure to
+ (__cp_exception_info): Return offset into cp_eh_info structure to
match what use to be the start of this structure.
(__cp_eh_info): New function to return a pointer to cp_eh_info struct.
(__cplus_type_matcher, __cp_push_exception): Remove NEW_EH_MODEL
compile time flag.
- (__uncatch_exception, __check_eh_spec, std::uncaught_exception): Call
+ (__uncatch_exception, __check_eh_spec, std::uncaught_exception): Call
__cp_eh_info instead of __cp_exception_info.
1998-06-08 Jason Merrill <jason@yorick.cygnus.com>
@@ -1002,7 +6008,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* lex.c (lang_init_options): New function.
(lang_init): Remove flag_exceptions == 2 hack.
-
+
1998-06-05 Jason Merrill <jason@yorick.cygnus.com>
* search.c (envelope_add_decl): Tweak for implicit typename.
@@ -1044,7 +6050,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(begin_only_namespace_names, end_only_namespace_names): New functions.
* decl2.c (set_decl_namespace): Skip namespace aliases.
(do_using_directive): Likewise.
- (do_namespace_alias): Produce namespace aliases, fix alias
+ (do_namespace_alias): Produce namespace aliases, fix alias
redeclaration.
* error.c (dump_decl): Support SCOPE_REF.
* parse.y (extdef): Wrap lookup with namespace_only for namespace
@@ -1127,9 +6133,9 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* method.c (build_destructor_name): New fn.
* decl2.c (maybe_retrofit_in_chrg): Split out...
(grokclassfn): From here. Reorganize.
- * decl.c (grok_ctor_properties): Make sure ctors for types with
+ * decl.c (grok_ctor_properties): Make sure ctors for types with
vbases have the in_chrg parm.
- * pt.c (instantiate_class_template): Update
+ * pt.c (instantiate_class_template): Update
TYPE_USES_VIRTUAL_BASECLASSES from tsubsted bases. Don't call
grok_*_properties.
(tsubst): Call grok_ctor_properties and maybe_retrofit_in_chrg.
@@ -1141,7 +6147,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-05-28 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Always pedwarn about vacuously redeclaring
+ * decl.c (start_decl): Always pedwarn about vacuously redeclaring
a member.
(start_function): Call check_default_args.
* decl2.c (grokfield): Don't call check_default_args.
@@ -1170,7 +6176,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(maybe_push_to_top_level): Clear shadowed_labels.
* pt.c (instantiate_decl): Reset lineno and filename after calling
- regenerate_decl_from_template.
+ regenerate_decl_from_template.
* decl.c (grokdeclarator): Don't try to use TYPE_OBSTACK on an
error_mark_node.
@@ -1199,7 +6205,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
1998-05-26 Benjamin Kosnik <bkoz@loony.cygnus.com>
* decl.c (start_decl): Check for DECL_LANG_SPECIFIC before
- DECL_USE_TEMPLATE.
+ DECL_USE_TEMPLATE.
1998-05-26 Per Bothner <bothner@cygnus.com>
@@ -1244,7 +6250,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* cp-tree.h (processing_template_parmlist): Declare.
* decl.c (pushtag): Don't call push_template_decl when we
- shouldn't.
+ shouldn't.
* pt.c (processing_template_parmlist): New variable.
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
(complete_template_args): Use it.
@@ -1289,7 +6295,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* parse.y (xcond): Move call to condition_conversion ...
* semantics.c (finish_for_cond): Here.
* parse.c: Regenerated.
-
+
1998-05-24 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (push_namespace): Namespaces have type void.
@@ -1308,14 +6314,14 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* tree.c (build_srcloc, build_srcloc_here): New fns.
* pt.c (add_pending_template): Use build_srcloc_here.
(push_tinst_level): Update last_template_error_tick before erroring.
- (instantiate_decl): Restore lineno and input_filename before
+ (instantiate_decl): Restore lineno and input_filename before
calling add_pending_template.
* decl2.c (finish_file): Set up lineno and input_filename for
pending templates.
1998-05-22 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (lang_print_error_function): New fn.
+ * decl.c (lang_print_error_function): New fn.
(init_decl_processing): Set print_error_function to use it.
* errfn.c (cp_thing): Don't call maybe_print_template_context here.
@@ -1342,7 +6348,7 @@ Mon Jun 8 20:45:52 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* pt.c (determine_specialization): Just return an error_mark_node.
Also print the decl we want in error messages. If we complain,
return error_mark_node.
- (tsubst_friend_function): Set lineno and input_filename so
+ (tsubst_friend_function): Set lineno and input_filename so
error messages will be useful.
(instantiate_template): Just return an error_mark_node.
(check_explicit_specialization): Don't mess with a returned
@@ -1376,7 +6382,7 @@ Thu May 21 11:54:44 1998 Dave Brolley <brolley@cygnus.com>
* cp-tree.h: (get_directive_line): Different prototype for cpplib.
(GET_DIRECTIVE_LINE): Macro wrapper for get_directive_line.
- * Makefile.in (CXX_OBJS): add @extra_cxx_objs@ for cpplib.
+ * Makefile.in (CXX_OBJS): Add @extra_cxx_objs@ for cpplib.
1998-05-21 Jason Merrill <jason@yorick.cygnus.com>
@@ -1409,11 +6415,11 @@ Thu May 21 11:54:44 1998 Dave Brolley <brolley@cygnus.com>
CLASSTYPE_TAGS list, just as for ordinary member classes.
(pushdecl_class_level): Use DECL_DECLARES_TYPE_P.
(lookup_tag): Look for IDENTIFIER_CLASS_VALUEs, just as with
- IDENTIFIER_NAMESPACE_VALUEs.
+ IDENTIFIER_NAMESPACE_VALUEs.
* parse.y (component_decl): Move code to ...
- * semantics.c (finish_member_class_template): New function.
+ * semantics.c (finish_member_class_template): New function.
Don't put member class templates on the list of components for a
- class.
+ class.
* parse.c: Regenerated.
* pt.c (classtype_mangled_name): Don't try DECL_CONTEXT on types.
In fact, don't use DECL_CONTEXT at all here.
@@ -1492,7 +6498,7 @@ Tue May 19 10:05:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
definition.
* errfn.c (cp_error): Cast function pointer `error' to (errorfn *)
- in call to `cp_thing'.
+ in call to `cp_thing'.
(cp_warning): Likewise for function pointer `warning'.
* except.c (do_function_call): Remove prototype and definition.
@@ -1503,10 +6509,10 @@ Tue May 19 10:05:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* parse.y: Include toplev.h.
* pt.c (type_unification): Remove unused variable `arg'.
- (instantiate_decl): likewise for `save_ti'.
+ (instantiate_decl): Likewise for `save_ti'.
* tree.c (propagate_binfo_offsets): Likewise for `base_binfos'.
-
+
Tue May 19 02:43:25 1998 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_member_call): Handle template_ids.
@@ -1520,9 +6526,9 @@ Mon May 18 23:22:52 1998 Jason Merrill <jason@yorick.cygnus.com>
Mon May 18 12:28:44 1998 Mark Mitchell <mmitchell@usa.net>
* parse.y (.finish_new_placement): New non-terminal.
- (unary_expr, new_type_id): Use it.
+ (unary_expr, new_type_id): Use it.
* parse.c: Regenerated.
-
+
Mon May 18 12:20:27 1998 Brendan Kehoe <brendan@cygnus.com>
* pt.c (redeclare_class_template): Say where the original definition
@@ -1538,7 +6544,7 @@ Mon May 18 03:00:57 1998 Jason Merrill <jason@yorick.cygnus.com>
Mon May 18 01:43:01 1998 Martin v. Loewis <loewis@informatik.hu-berlin.de>
- * decl.c (lookup_name_real): Don't look at IDENTIFIER_LOCAL_VALUE
+ * decl.c (lookup_name_real): Don't look at IDENTIFIER_LOCAL_VALUE
for a type unless it is one.
* class.c (finish_struct_1): Use OVL_CURRENT in error message.
@@ -1548,7 +6554,7 @@ Mon May 18 01:24:08 1998 Jeffrey A Law (law@cygnus.com)
* Makefile.in (program_transform_name, objdir): Define.
* Makefile.in (BISON): Use bison from the build tree if it exists.
- (FLEX): Similarly.
+ (FLEX): Likewise.
Sun May 17 14:52:08 1998 Martin v. Loewis <loewis@informatik.hu-berlin.de>
@@ -1567,7 +6573,7 @@ Sun May 17 13:53:48 1998 Mark Mitchell <mmitchell@usa.net>
* parse.y (.build_new_placement): New non-terminal.
(unary_expr, new_placement): Use it.
* parse.c: Regenerated.
-
+
Sun May 17 12:32:08 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (duplicate_decls): Use CANONICAL_TYPE_VARIANT to compare
@@ -1586,7 +6592,7 @@ Fri May 15 20:28:00 1998 Jason Merrill <jason@yorick.cygnus.com>
Fri May 15 15:34:02 1998 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * decl.c (duplicate_decls): Clean up, add DECL_DATA_AREA bits.
+ * decl.c (duplicate_decls): Clean up, add DECL_DATA_AREA bits.
Fri May 15 00:46:05 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -1594,20 +6600,20 @@ Fri May 15 00:46:05 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (start_decl): Use 'tem'.
-Thu May 14 16:30:47 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Thu May 14 16:30:47 1998 Andrew MacLeod <amacleod@cygnus.com>
* exception.cc: Include eh-common.h.
- (struct cp_eh_info): add eh_info struct with NEW_EH_MODEL.
+ (struct cp_eh_info): Add eh_info struct with NEW_EH_MODEL.
(__cplus_type_matcher): First stab at new C++ runtime type matcher.
(__cp_push_exception): Initialize eh_info struct as well.
* except.c: Remove local structs and include eh-common.h.
(init_exception_processing): Set language and version codes.
- (call_eh_info): add presence of eh_info to runtime description of
+ (call_eh_info): Add presence of eh_info to runtime description of
struct cp_eh_info.
- (expand_end_eh_spec): call start_catch_block() and end_catch_block().
- * semantics.c (finish_try_block): call start_catch_block() and
+ (expand_end_eh_spec): Call start_catch_block() and end_catch_block().
+ * semantics.c (finish_try_block): Call start_catch_block() and
end_catch_block().
- * parse.y (function_try_block): call start_catch_block() and
+ * parse.y (function_try_block): Call start_catch_block() and
end_catch_block().
Thu May 14 12:27:34 1998 Brendan Kehoe <brendan@cygnus.com>
@@ -1620,11 +6626,11 @@ Thu May 14 12:27:34 1998 Brendan Kehoe <brendan@cygnus.com>
Wed May 13 12:54:30 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* Makefile.in (lex.o): Depend on output.h.
-
+
* call.c (add_function_candidate): Remove unused variable `cand'.
(add_conv_candidate): Likewise.
(build_builtin_candidate): Likewise.
-
+
* cp-tree.h: Add prototype for `types_overlap_p'.
* decl.c (signal_catch): Mark parameter `sig' with ATTRIBUTE_UNUSED.
@@ -1659,7 +6665,7 @@ Tue May 12 21:37:49 1998 Jason Merrill <jason@yorick.cygnus.com>
DECL_NAMESPACE_SCOPE_P.
(lang_decl_name): Likewise.
* pt.c (tsubst_friend_function, tsubst): Likewise.
- * decl.c (pushdecl, redeclaration_error_message, start_decl,
+ * decl.c (pushdecl, redeclaration_error_message, start_decl,
cp_finish_decl, start_function): Likewise.
* class.c (finish_struct_1): Likewise.
* call.c (build_over_call): Likewise.
@@ -1681,7 +6687,7 @@ Mon May 11 11:38:07 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (tsubst): Remove duplicate check for IDENTIFIER_NODE.
* call.c (add_template_candidate): Adjust for changes to
- fn_type_unification.
+ fn_type_unification.
(add_template_candidate_real): Likewise.
(add_template_conv_candidate): Likewise.
(build_user_type_conversion_1): Likewise.
@@ -1726,11 +6732,11 @@ Mon May 11 11:38:07 1998 Mark Mitchell <mmitchell@usa.net>
tsubst_template_argument_vector where appropriate.
(regenerate_decl_from_template): Break out from ...
(instantiate_decl): Here.
-
+
* lex.c (yyprint): Remove TYPENAME_ELLIPSIS.
* parse.h: Regenerated.
* parse.c: Really regenerated.
-
+
* cp-tree.h (finish_unary_op_expr): New function.
(finish_id_expr): Likewise.
(begin_new_placement): Likewise.
@@ -1792,7 +6798,7 @@ Sat May 9 14:44:37 1998 Jason Merrill <jason@yorick.cygnus.com>
Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
- * cp-tree.def (OVERLOAD): New node.
+ * cp-tree.def (OVERLOAD): New node.
* cp-tree.h (BINDING_TYPE, SET_IDENTIFIER_GLOBAL_VALUE,
SET_IDENTIFIER_NAMESPACE_VALUE): Define.
(NAMESPACE_BINDING): Remove.
@@ -1821,10 +6827,10 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* call.c (add_function_candidate): Special-case type of OVERLOAD node.
(build_user_conversions_1): Iterate using OVL_NEXT for ctors,
convs, fns.
- (build_new_function_call): Iterate using OVL_CHAIN.
+ (build_new_function_call): Iterate using OVL_CHAIN.
Print DECL_NAME in when reporting ambiguities.
(build_object_call): Iterate using OVL_NEXT for fns, convs.
- (build_new_op): Call lookup_function_nonclass.
+ (build_new_op): Call lookup_function_nonclass.
Iterate using OVL_NEXT.
(build_op_delete_call): Change detection of members.
Do not wrap TREE_LIST around fields and single global functions.
@@ -1842,7 +6848,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
fdecls that are OVERLOAD nodes.
(validate_lhs): New function.
(instantiate_type): Do not copy OVERLOAD nodes. Remove dead
- code. Use DECL_NAME in error messages. Split code between global
+ code. Use DECL_NAME in error messages. Split code between global
and member function processing.
* decl.c (global_type_node): New static variable.
(in_std): New global.
@@ -1869,7 +6875,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
(pushtag): If no context, use current_namespace.
(duplicate_decls): Don't process DECL_CHAIN.
(pushdecl): Set DECL_CONTEXT to current_namespace, if it is not
- already set. Never reset it to NULL_TREE. Lookup global variables
+ already set. Never reset it to NULL_TREE. Lookup global variables
in their namespace. Push overloaded templates if they are on
namespace level.
(pushdecl_namespace_level): New function.
@@ -1877,7 +6883,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
(pushdecl_using_decl): New function.
(overloaded_globals_p): Remove.
(push_overloaded_decl): Create OVERLOAD nodes, and iterate through
- them. Use namespace_binding and set_namespace_value.
+ them. Use namespace_binding and set_namespace_value.
(redeclaration_error_message): Complain if the declarations come
from different namespaces.
(lookup_tag): On namespace level, look in the BINDING_TYPE.
@@ -1903,7 +6909,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
(grokvardecl): Add namespace parameter.
(grokdeclarator): Process SCOPEs that are namespaces. For
mangling, temporarily set the DECL_CONTEXT on anonymous structs.
- (start_function): Check for contexts that are namespaces.
+ (start_function): Check for contexts that are namespaces.
Set context for declarations that have not been pushed.
(store_parm_decls): Check for ::main only.
(finish_function): Likewise.
@@ -1939,7 +6945,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* lang-specs.h (__HONOR_STD): Define if -fnew-abi or -fhonor-std.
* lex.c (identifier_type): Loop using OVL_CHAIN.
(see_typename): Set looking_for_typename to 2.
- (real_yylex): Likewise.
+ (real_yylex): Likewise.
(do_identifier): Expect OVERLOAD nodes instead of TREE_LISTs.
(do_scoped_id): Expect OVERLOAD nodes.
Change calling convention for qualified_lookup_using_namespace.
@@ -1966,7 +6972,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
Set DECL_CONTEXT to current_namespace if not set already.
Ignore real contexts that are namespaces.
(mangle_class_name_for_template): Skip global_namespace.
- Mangle other namepaces as declarations.
+ Mangle other namespaces as declarations.
(lookup_template_function): Set type of OVERLOAD nodes to unknown.
(lookup_template_class): Push into namespace of context.
If the context is a namespace, set it to global_namespace.
@@ -2008,7 +7014,7 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* decl.c (duplicate_decls): Check for namespace bindings instead
of global bindings.
(pushdecl, push_overloaded_decl, lookup_tag, lookup_name_real,
- lookup_name_current_level, start_decl, xref_tag,
+ lookup_name_current_level, start_decl, xref_tag,
finish_enum): Likewise.
* init.c (build_offset_ref): Likewise.
* search.c (lookup_field): Likewise.
@@ -2025,17 +7031,17 @@ Fri May 8 23:32:42 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* parse.y (make_thunk): Likewise.
* pt.c (tsubst): Likewise.
* tree.c (debug_binfo): Likewise.
- * exception.cc, new.cc, new1.cc, new2.cc, tinfo.cc, tinfo.h,
+ * exception.cc, new.cc, new1.cc, new2.cc, tinfo.cc, tinfo.h,
tinfo2.cc, inc/new.h: Add std qualifications.
* inc/new: Wrap with namespace std if __HONOR_STD.
* inc/typeinfo: Likewise.
Fri May 8 00:43:50 1998 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_user_type_conversion_1): Handle second_conv
+ * call.c (build_user_type_conversion_1): Handle second_conv
properly for templates.
-Thu May 7 17:09:25 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Thu May 7 17:09:25 1998 Andrew MacLeod <amacleod@cygnus.com>
* method.c (build_decl_overload_real): Set TREE_USED flag to
zero for build_type_variants nodes as well.
@@ -2048,7 +7054,7 @@ Wed May 6 16:49:48 1998 Jim Wilson <wilson@cygnus.com>
* Makefile.in (call.o, class.o, decl.o, decl2.o, errfn.o, error.o,
except.o, expr.o, friend.o, init.o, lex.o, method.o, pt.o, repo.o,
- rtti.o, search.o, semantics.o, sig.o, tree.o, typeck.o, typeck2.o,
+ rtti.o, search.o, semantics.o, sig.o, tree.o, typeck.o, typeck2.o,
xref.o): Add toplev.h dependencies.
Wed May 6 16:44:58 1998 Jeffrey A Law (law@cygnus.com)
@@ -2065,9 +7071,9 @@ Wed May 6 14:28:18 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
Wed May 6 06:36:41 1998 Robert Lipe <robertl@dgii.com>
- * call.c, class.c, decl.c, decl2.c, errfn.c, error.c, except.c,
- expr.c, friend.c, init.c, lex.c, method.c, pt.c, repo.c, rtti.c,
- search.c, semantics.c, sig.c, tree.c, typeck.c, typeck2.c,
+ * call.c, class.c, decl.c, decl2.c, errfn.c, error.c, except.c,
+ expr.c, friend.c, init.c, lex.c, method.c, pt.c, repo.c, rtti.c,
+ search.c, semantics.c, sig.c, tree.c, typeck.c, typeck2.c,
xref.c: Add include of toplev.h.
Wed May 6 02:33:39 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2080,9 +7086,9 @@ Tue May 5 23:54:04 1998 Jason Merrill <jason@yorick.cygnus.com>
* init.c (expand_vec_init): The initialization of each array
element is a full-expression.
-Tue May 5 18:24:13 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Tue May 5 18:24:13 1998 Andrew MacLeod <amacleod@cygnus.com>
- * method.c (build_mangled_name): Add a call to build_type_variant
+ * method.c (build_mangled_name): Add a call to build_type_variant
to get the right type.
Tue May 5 01:25:03 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2093,7 +7099,7 @@ Tue May 5 01:25:03 1998 Jason Merrill <jason@yorick.cygnus.com>
Sun May 3 01:32:14 1998 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_over_call): Do evaluate arg even if it has empty
+ * call.c (build_over_call): Do evaluate arg even if it has empty
class type.
* decl.c (start_function): Don't push a member function.
@@ -2101,7 +7107,7 @@ Thu Apr 30 18:59:23 1998 Jim Wilson <wilson@cygnus.com>
* Makefile.in (g++FAQ.info): Put -o option before input file.
-Thu Apr 30 13:05:33 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
+Thu Apr 30 13:05:33 1998 Andrew MacLeod <amacleod@cygnus.com>
* gxxint.texi: Add info for squangling codes K and B.
@@ -2130,7 +7136,7 @@ Sun Apr 26 12:10:18 1998 Mark Mitchell <mmitchell@usa.net>
(PRIMARY_TEMPLATE_P): Use it.
(push_template_decl_real): New function.
(redeclare_class_template): Take new template parameters as
- input.
+ input.
(is_specialization_of): New function.
(comp_template_args): Declare.
* decl.c (pushtag): Handle friend template classes.
@@ -2150,7 +7156,7 @@ Sun Apr 26 12:10:18 1998 Mark Mitchell <mmitchell@usa.net>
with friend templates.
* typeck.c (comptypes): Use comp_template_args, rather than
expanding it inline.
- * parse.y (component_decl): Handle a nested template type
+ * parse.y (component_decl): Handle a nested template type
like other component type declarations.
* pt.c (check_explicit_specialization): Handle overloaded
@@ -2168,14 +7174,14 @@ Thu Apr 23 21:19:06 1998 Jason Merrill <jason@yorick.cygnus.com>
Enforce access control here. Emit overload warnings here.
(add_warning): New fn.
(joust): Add WARN parm. If not set, call add_warning instead of
- printing a warning. Reenable some warnings.
+ printing a warning. Re-enable some warnings.
(tourney): Pass it.
(convert_like): Adjust.
(build_new_op): Adjust.
(build_new_function_call): Adjust.
(build_user_type_conversion_1): Adjust.
(USER_CONV_FN): Adjust.
- * tree.c (build_expr_wrapper, build_expr_ptr_wrapper,
+ * tree.c (build_expr_wrapper, build_expr_ptr_wrapper,
build_int_wrapper): New fns.
Thu Apr 23 18:27:53 1998 Mark P. Mitchell <mmitchell@usa.net>
@@ -2194,15 +7200,15 @@ Wed Apr 22 13:24:48 1998 Mark Mitchell <mmitchell@usa.net>
the DECL_RESULTs of a member TEMPLATE_DECL, not just the
TEMPLATE_DECL.
- * pt.c (tsubst): Decrease the template-level of
- TEMPLATE_TEMPLATE_PARMS. Likewise for the DECL_INITIAL of a
- TEMPLATE_PARM_INDEX.
- (template_decl_level): New function.
- (unify): Make sure to record unifications for template
- parameters, even when the parameters exactly match the arguments.
- Combine duplicated code for TEMPLATE_TEMPLATE_PARMs and
- TEMPLATE_TYPE_PARMS. Don't try to unify template parameters that
- aren't from the level we're currently working on.
+ * pt.c (tsubst): Decrease the template-level of
+ TEMPLATE_TEMPLATE_PARMS. Likewise for the DECL_INITIAL of a
+ TEMPLATE_PARM_INDEX.
+ (template_decl_level): New function.
+ (unify): Make sure to record unifications for template
+ parameters, even when the parameters exactly match the arguments.
+ Combine duplicated code for TEMPLATE_TEMPLATE_PARMs and
+ TEMPLATE_TYPE_PARMS. Don't try to unify template parameters that
+ aren't from the level we're currently working on.
Tue Apr 21 22:00:04 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2345,29 +7351,29 @@ Sun Apr 12 22:31:19 1998 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
Fri Apr 10 12:16:49 1998 Benjamin Kosnik <bkoz@loony.cygnus.com>
* decl.c (duplicate_decls): Don't warn for redundant decls if
- friend: let add_friend take care of it.
+ friend: let add_friend take care of it.
Thu Apr 9 02:40:48 1998 Jason Merrill <jason@yorick.cygnus.com>
* sig.c (build_signature_pointer_constructor): Don't set
TREE_HAS_CONSTRUCTOR for a signature pointer.
* cvt.c (ocp_convert): Don't force a temporary for internal structs.
- * init.c (resolve_offset_ref): Warn about implicit & on pmfs
+ * init.c (resolve_offset_ref): Warn about implicit & on pmfs
here, too.
- * typeck.c (build_unary_op): Only allow taking the address of a
+ * typeck.c (build_unary_op): Only allow taking the address of a
real constructor.
* typeck2.c (digest_init): Simplify.
(store_init_value): Don't pedwarn about using { } for pmfs.
Thu Apr 9 22:16:57 1998 Per Bothner <bothner@cygnus.com>
- * cp-tree.h (start_decl): Update prototype.
- * decl.c (start_decl): Like the C version, new parameters
- for the attributes. Call cplus_decl_attributes here,
- (pushdecl): Like C version, do build_type_copy if TYPE_DECL,
- (grokdeclarator): Pass NULL for new start_decl arguments.
- * pt.c (tsubst_expr): Likewise.
- * parse.y: Merge cplus_decl_attribute calls into start_decl calls.
+ * cp-tree.h (start_decl): Update prototype.
+ * decl.c (start_decl): Like the C version, new parameters
+ for the attributes. Call cplus_decl_attributes here,
+ (pushdecl): Like C version, do build_type_copy if TYPE_DECL,
+ (grokdeclarator): Pass NULL for new start_decl arguments.
+ * pt.c (tsubst_expr): Likewise.
+ * parse.y: Merge cplus_decl_attribute calls into start_decl calls.
* typeck.c (common_type): Check TYPE_MAIN_VARIANT.
* lex.c (build_lang_decl): Add lang_name_java.
* class.c (push_lang_context): Add lang_name_java.
@@ -2378,14 +7384,14 @@ Thu Apr 9 22:16:57 1998 Benjamin Kosnik <bkoz@loony.cygnus.com>
* decl.c (grokdeclarator): Check TYPE_MAIN_VARIANT.
* call.c (build_scoped_method_call): Check for TREE_CODE for
VOID_TYPE instead of type == void_type_node.
- (build_method_call): Ditto.
- * decl.c (lookup_name_real): Ditto.
- (grokdeclarator): Ditto.
- (start_decl): Ditto.
- (grokparms): Ditto.
- (start_function): Ditto.
- (finish_function): Ditto.
- (start_method): Ditto.
+ (build_method_call): Likewise.
+ * decl.c (lookup_name_real): Likewise.
+ (grokdeclarator): Likewise.
+ (start_decl): Likewise.
+ (grokparms): Likewise.
+ (start_function): Likewise.
+ (finish_function): Likewise.
+ (start_method): Likewise.
Thu Apr 9 00:18:44 1998 Dave Brolley (brolley@cygnus.com)
@@ -2419,7 +7425,7 @@ Sat Apr 4 12:52:35 1998 Jeffrey A Law (law@cygnus.com)
Fri Apr 3 02:22:59 1998 Jason Merrill <jason@yorick.cygnus.com>
Implement empty base optimization.
- * class.c (finish_struct_1): Add vbase fields earlier. Set
+ * class.c (finish_struct_1): Add vbase fields earlier. Set
CLASSTYPE_SIZE of an empty base to 0. Types with bases can be empty.
* search.c (dfs_check_overlap, dfs_no_overlap_yet): New fns.
(types_overlap_p): New fn.
@@ -2456,7 +7462,7 @@ Wed Apr 1 18:22:25 1998 Jeffrey A Law (law@cygnus.com)
* class.c, Make sure system.h is included just after config.h.
Delete lingering stdio and errno references too.
* decl.c, errfn.c, parse.y, ptree.c search.c, xref.c: Likewise.
-
+
Wed Apr 1 15:38:36 1998 Jason Merrill <jason@yorick.cygnus.com>
* friend.c (is_friend): Fix access control for local classes.
@@ -2483,7 +7489,7 @@ Tue Mar 31 13:43:57 1998 Jeffrey A Law (law@cygnus.com)
Mon Mar 30 12:15:00 1998 Mark Mitchell <mmitchell@usa.net>
- * pt.c (fn_type_unification): Allow incomplete unification without
+ * pt.c (fn_type_unification): Allow incomplete unification without
an immediate error message.
Mon Mar 30 08:55:42 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2561,7 +7567,7 @@ Fri Mar 27 20:23:18 1998 Mark Mitchell <mmitchell@usa.net>
* error.c (dump_decl): Be a bit more explicit with template
type arguments, when verbose.
-
+
Fri Mar 27 18:16:40 1998 Jason Merrill <jason@yorick.cygnus.com>
* inc/exception: Reorder closing braces.
@@ -2574,7 +7580,7 @@ Fri Mar 27 13:22:18 1998 Mark Mitchell <mmitchell@usa.net>
Thu Mar 26 11:16:30 1998 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_over_call): Check IS_AGGR_TYPE, not
+ * call.c (build_over_call): Check IS_AGGR_TYPE, not
TYPE_LANG_SPECIFIC.
* typeck.c (convert_arguments): Likewise.
@@ -2633,8 +7639,8 @@ Tue Mar 24 12:21:55 1998 Benjamin Kosnik <bkoz@lisa.cygnus.com>
Tue Mar 24 12:21:48 1998 Jim Wilson <wilson@cygnus.com>
- * decl.c (init_decl_processing): Initialize TYPE_MAX_VALUE for
- boolean_type_node to 1.
+ * decl.c (init_decl_processing): Initialize TYPE_MAX_VALUE for
+ boolean_type_node to 1.
Tue Mar 24 10:23:47 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2673,7 +7679,7 @@ Tue Mar 24 10:23:47 1998 Mark Mitchell <mmitchell@usa.net>
(fn_type_unification): Use new interfaces.
(type_unification): Likewise. Remove NOP_EXPR hack.
(type_unification_real): Likewise.
- (unify): Likewise. Deal with unification of complex expresions.
+ (unify): Likewise. Deal with unification of complex expressions.
Mon Mar 23 12:24:37 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2686,7 +7692,7 @@ Mon Mar 23 12:24:37 1998 Jason Merrill <jason@yorick.cygnus.com>
* search.c (lookup_field): Do implicit typename stuff.
Sun Mar 22 00:50:42 1998 Nick Clifton <nickc@cygnus.com>
- Geoff Noer <noer@cygnus.com>
+ Geoff Noer <noer@cygnus.com>
* Makefile.in: Various fixes for building cygwin32 native toolchains.
* Make-lang.in: Likewise.
@@ -2706,7 +7712,7 @@ Fri Mar 20 10:42:07 1998 Jason Merrill <jason@yorick.cygnus.com>
Fri Mar 20 08:12:43 1998 H.J. Lu (hjl@gnu.org)
- * semantics.c (finish_asm_stmt): Fix combine strings. Call
+ * semantics.c (finish_asm_stmt): Fix combine strings. Call
c_expand_asm_operands () if output_operands, input_operands or
clobbers is not NULL_TREE.
@@ -2714,7 +7720,7 @@ Fri Mar 20 00:10:19 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* pt.c (complete_template_args): New function.
(get_bindings): Deal with specializations of function templates
- with return type containing parameters from outer class
+ with return type containing parameters from outer class
templates.
(tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level,
substitute arguments and compose a new type.
@@ -2730,7 +7736,7 @@ Thu Mar 19 11:51:58 1998 Jason Merrill <jason@yorick.cygnus.com>
* call.c (standard_conversion): Handle A* -> const A* properly.
- * pt.c (get_bindings_real): Rename from get_bindings. Add
+ * pt.c (get_bindings_real): Rename from get_bindings. Add
check_rettype parm.
(get_bindings): Pass 1.
(get_bindings_overload): Pass 0.
@@ -2751,7 +7757,7 @@ Thu Mar 19 02:27:48 1998 Jason Merrill <jason@yorick.cygnus.com>
Wed Mar 18 12:41:43 1998 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (make_implicit_typename): Only change the type of a
+ * decl.c (make_implicit_typename): Only change the type of a
TYPENAME_TYPE.
Wed Mar 18 10:09:51 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2765,7 +7771,7 @@ Wed Mar 18 10:09:51 1998 Mark Mitchell <mmitchell@usa.net>
* cp-tree.def: Add ASM_STMT tree node.
* Makefile.in, Make-lang.in: Add dependencies on and for
semantics.c.
-
+
Wed Mar 18 00:24:10 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (push_template_decl): Only check primary templates.
@@ -2773,7 +7779,7 @@ Wed Mar 18 00:24:10 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (check_explicit_specialization): Complain about default args
in explicit specialization.
- * parse.y (nomods_initdcl0): Also call cp_finish_decl for a
+ * parse.y (nomods_initdcl0): Also call cp_finish_decl for a
constructor_declarator.
Tue Mar 17 14:44:54 1998 Mark Mitchell <mmitchell@usa.net>
@@ -2800,7 +7806,7 @@ Mon Mar 16 12:10:39 1998 Jason Merrill <jason@yorick.cygnus.com>
* class.c (pushclass): Only use the mi_matrix stuff #ifdef MI_MATRIX.
* search.c: Likewise.
- * lex.c (do_pending_defargs): Only call
+ * lex.c (do_pending_defargs): Only call
maybe_{begin,end}_member_template_processing for FUNCTION_DECLs.
* parse.y (initdcl0_innards): Move maybeasm back into initdcl0 et al.
@@ -2813,9 +7819,9 @@ Mon Mar 16 10:54:21 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (tsubst_copy): Deal with BIND_EXPR in a way that more
closely mimics the behavior in parse.y.
- (tsubst_expr): Return the resuting BLOCK when making a tsubst'ing
+ (tsubst_expr): Return the resulting BLOCK when making a tsubst'ing
into a compound statement.
-
+
Sun Mar 15 02:07:26 1998 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (TEMPLATE_PARMS_FOR_INLINE): New macro.
@@ -2832,13 +7838,13 @@ Sun Mar 15 01:14:22 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* lex.c (do_identifier): Handle TEMPLATE_DECL that was
added in the class scope to catch redefinition error.
- * pt.c (reduce_template_parm_level): Also copy
+ * pt.c (reduce_template_parm_level): Also copy
the DECL_TEMPLATE_PARMS field.
Sun Mar 15 10:54:08 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (tsubst): Clear TYPE_REFERENCE_TO when creating a
- reduced-level template type parameter.
+ reduced-level template type parameter.
Sun Mar 15 12:26:02 1998 Manfred Hollstein <manfred@s-direktnet.de>
@@ -2849,10 +7855,10 @@ Sun Mar 15 12:26:02 1998 Manfred Hollstein <manfred@s-direktnet.de>
* typeck2.c (abstract_virtuals_error): Use two loops to emit
abstract virtual functions and virtual functions which need a
final overrider separately.
-
+
Thu Mar 12 09:39:40 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * lang-specs.h: Properly put brackets around array elements in
+ * lang-specs.h: Properly put brackets around array elements in
initializer.
* typeck.c (build_binary_op_nodefault): Correctly place parens around
@@ -2870,7 +7876,7 @@ Thu Mar 12 09:26:04 1998 Manfred Hollstein <manfred@s-direktnet.de>
* except.c (do_unwind): #if 0 definition of unused variables fcall
and next_pc.
- * expr.c (extract_scalar_init): #if 0 prototype and function
+ * expr.c (extract_scalar_init): #if 0 prototype and function
definition.
* init.c (expand_aggr_init_1): Remove unused variable init_type.
@@ -2914,13 +7920,13 @@ Fri Mar 6 23:27:35 1998 Jeffrey A Law (law@cygnus.com)
Fri Mar 6 10:06:59 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * method.c: Include "system.h" to get stdlib.h, stdio.h,
- ctype.h, string.h, etc.
- (issue_nrepeats): Add default case in enumeration switch.
- (check_btype): Likewise.
- (process_overload_item): Likewise.
-
- * Makefile.in (method.o): Depend on system.h.
+ * method.c: Include "system.h" to get stdlib.h, stdio.h,
+ ctype.h, string.h, etc.
+ (issue_nrepeats): Add default case in enumeration switch.
+ (check_btype): Likewise.
+ (process_overload_item): Likewise.
+
+ * Makefile.in (method.o): Depend on system.h.
Wed Mar 4 22:26:53 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
@@ -2931,7 +7937,7 @@ Wed Mar 4 12:11:53 1998 Michael Tiemann <tiemann@axon.cygnus.com>
* rtti.c (get_tinfo_fn_dynamic): If this function is called an
FLAG_RTTI is unset, initialize type info machinery and continue
with FLAG_RTTI enabled.
- (get_typeid): Ditto.
+ (get_typeid): Likewise.
Wed Mar 4 11:47:55 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -2950,7 +7956,7 @@ Tue Mar 3 01:38:17 1998 Jason Merrill <jason@yorick.cygnus.com>
some formatting quirks.
* call.c, class.c, cp-tree.h, cvt.c, decl.c, init.c, lex.c,
- method.c, pt.c, ptree.c, typeck.c: Remove support for
+ method.c, pt.c, ptree.c, typeck.c: Remove support for
-fno-ansi-overloading and overloading METHOD_CALL_EXPR.
* class.h: Remove.
* Makefile.in: Adjust.
@@ -2966,7 +7972,7 @@ Mon Mar 2 12:11:06 1998 Jason Merrill <jason@yorick.cygnus.com>
(nested_name_specifier): And add it before this use.
(typename_sub0): And this use. Also add use without the keyword.
(typename_sub1): Likewise.
- * pt.c (instantiate_class_template): Don't actually instantiate
+ * pt.c (instantiate_class_template): Don't actually instantiate
anything if our type uses template parms.
Mon Mar 2 11:04:59 1998 Jim Wilson <wilson@cygnus.com>
@@ -2987,9 +7993,9 @@ Sat Feb 28 12:06:44 1998 Jason Merrill <jason@yorick.cygnus.com>
* lex.c (yyprint): Handle a PTYPENAME being a TEMPLATE_DECL.
* decl.c (make_typename_type): Handle template-id where the name
is a TEMPLATE_DECL.
- * call.c (build_scoped_method_call): Handle member template
+ * call.c (build_scoped_method_call): Handle member template
destructor call.
- * pt.c (tsubst_copy, METHOD_CALL_EXPR): Don't assume a member
+ * pt.c (tsubst_copy, METHOD_CALL_EXPR): Don't assume a member
destructor is represented by the type.
* cp-tree.h (TYPENAME_TYPE_FULLNAME): New macro.
@@ -3036,7 +8042,7 @@ Fri Feb 27 02:25:16 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (pushtag): Handle member templates.
* method.c (do_inline_function_hair): Don't touch
IDENTIFIER_GLOBAL_VALUE.
- * init.c (build_offset_ref): If name isn't an identifier, just
+ * init.c (build_offset_ref): If name isn't an identifier, just
return it.
* spew.c (yylex): Handle PTYPENAME like TYPENAME.
@@ -3067,43 +8073,43 @@ Wed Feb 25 00:35:33 1998 Jason Merrill <jason@yorick.cygnus.com>
Tue Feb 24 22:15:04 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* cp-tree.def: Add CPLUS_BINDING node.
- * cp-tree.h (tree_binding): new struct
- (BINDING_SCOPE, BINDING_VALUE): new macros
- (current_namespace, global_namespace): declare extern
- (struct lang_decl_flags): new field in_namespace
- (DECL_NAMESPACE_USING, DECL_NAMESPACE_USERS): new macros
- (DECL_NAMESPACE, SET_DECL_NAMESPACE): new macros
- (TREE_INDIRECT_USING): new macro
+ * cp-tree.h (tree_binding): New struct.
+ (BINDING_SCOPE, BINDING_VALUE): New macros.
+ (current_namespace, global_namespace): Declare extern.
+ (struct lang_decl_flags): New field in_namespace.
+ (DECL_NAMESPACE_USING, DECL_NAMESPACE_USERS): New macros.
+ (DECL_NAMESPACE, SET_DECL_NAMESPACE): New macros.
+ (TREE_INDIRECT_USING): New macro.
* decl2.c (current_namespace, global_namespace): Declare. The
value is a NAMESPACE_DECL now, not a TREE_LIST.
- (is_namespace_ancestor, namespace_ancestor):new static functions.
- (add_using_namespace, ambiguous_decl): likewise.
- (lookup_using_namespace): new support function for lookup_name.
- (qualified_lookup_using_namespace): new support function for
- do_scoped_id and lookup_namespace_name
- (get_namespace_id): mark as obsolete.
+ (is_namespace_ancestor, namespace_ancestor): New static functions.
+ (add_using_namespace, ambiguous_decl): Likewise.
+ (lookup_using_namespace): New support function for lookup_name.
+ (qualified_lookup_using_namespace): New support function for
+ do_scoped_id and lookup_namespace_name.
+ (get_namespace_id): Mark as obsolete.
(current_namespace_id): Likewise.
(do_namespace_alias): Implement.
(do_using_directive): Implement as call to add_using_namespace.
- * decl.c (binding_for_name): new function.
- (push_namespace, pop_namespace): implement.
- (push_decl): don't install a FUNCTION_DECL in the global branch.
- (lookup_namespace_name): implement using qualified lookup.
+ * decl.c (binding_for_name): New function.
+ (push_namespace, pop_namespace): Implement.
+ (push_decl): Don't install a FUNCTION_DECL in the global branch.
+ (lookup_namespace_name): Implement using qualified lookup.
(lookup_name_real): For global scoping, lookup in
- global_namespace. For namespace scoping, lookup in given
- namespace. For unscoped lookup, iterate over namespace,
+ global_namespace. For namespace scoping, lookup in given
+ namespace. For unscoped lookup, iterate over namespace,
considering using directives.
- (init_decl_processing): initialize global_namespace.
+ (init_decl_processing): Initialize global_namespace.
(grokvardecl): Build assembler name as static name for globals.
(grokdeclarator): Remove old namespace mangling.
(xref_tag): When installing a global binding for the
tag, make sure we have an identifier.
- * method.c (build_overload_nested_name): mangle namespaces.
+ * method.c (build_overload_nested_name): Mangle namespaces.
(build_qualified_name): Likewise.
(build_decl_overload_real): Likewise.
- * lex.c (build_lang_decl): set namespace for new declaration to
+ * lex.c (build_lang_decl): Set namespace for new declaration to
current_namespace.
- (do_scoped_id): find global names in global or current
+ (do_scoped_id): Find global names in global or current
namespace, or using qualified namespace lookup, depending on
context.
* init.c (build_member_call): When scope is namespace, use
@@ -3133,7 +8139,7 @@ Tue Feb 24 01:40:24 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (instantiate_class_template): Don't instantiate if pedantic
and the args use template parms.
- * pt.c (push_tinst_level): If the instantiaton uses template parms,
+ * pt.c (push_tinst_level): If the instantiation uses template parms,
fail silently.
* decl.c (xref_basetypes): Do call complete_type for basetypes
that involve template parameters.
@@ -3162,7 +8168,7 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
* Make-lang.in (cc1plus): Note that cc1plus depends on
cp/cp-tree.h and cp/cp-tree.def.
-
+
* cp-tree.def (TEMPLATE_CONST_PARM): Remove.
(TEMPLATE_PARM_INDEX): New tree code, used to indicate a
position in a template parameter list.
@@ -3197,7 +8203,7 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
two template functions with the same DECL_ASSEMBLER_NAME the same,
since the names are not yet mangled.
* error.c (dump_decl): Use TEMPLATE_PARM_INDEX instead of
- TEMPLATE_CONST_PARM.
+ TEMPLATE_CONST_PARM.
(dump_expr): Likewise. Use the TEMPLATE_PARM_DECL to get at the
decl for a non-type parameter, rather than printing `<tparm ...>'.
* friend.c (is_friend): Handle TEMPLATE_DECL friends.
@@ -3210,7 +8216,7 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
conditionally calling end_member_template_processing.
(do_pending_defargs): Likewise.
(do_identifier): Use TEMPLATE_PARM_INDEX instead of
- TEMPLATE_CONST_PARM.
+ TEMPLATE_CONST_PARM.
* method.c (build_mangled_template_parm_index): New function.
(build_overload_value): Use it.
(build_overload_name): Likewise.
@@ -3240,14 +8246,14 @@ Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
template.
(tsubst_copy): Tidy up slightly. Use TEMPLATE_PARM_INDEX instead
of TEMPLATE_CONST_PARM. Handle TYPE_DECLs by tsubsting into them.
- (unify): Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM.
+ (unify): Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM.
(get_bindings): Call add_to_template_args if necessary.
(instantiate_decl): Handle instantiations of friend templates.
* search.c (lookup_field_1): Don't treat the TYPE_FIELDS of a
TEMPLATE_TYPE_PARM as a list of fields; it's not!
- * spew.c (yylex): Do a little manual constant propogation to
+ * spew.c (yylex): Do a little manual constant propagation to
clarify the code.
-
+
Sun Feb 22 19:53:29 1998 Jeffrey A Law (law@cygnus.com)
* error.c: Include sys/types.h.
@@ -3260,20 +8266,20 @@ Thu Feb 19 10:36:48 1998 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (process_init_constructor): Sorry about non-trivial
labeled initializers.
- * parse.y (initlist): Reenable labeled initializers.
+ * parse.y (initlist): Re-enable labeled initializers.
Thu Feb 19 10:15:55 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
- * pt.c (coerce_template_parms) Add a new parameter, is_tmpl_parm,
- all callers changed. Rely on the new parameter instead of arg
+ * pt.c (coerce_template_parms): Add a new parameter, is_tmpl_parm,
+ all callers changed. Rely on the new parameter instead of arg
being a TREE_LIST when determine whether we are working inside
template template parameter. Clean up is_type test.
-
+
Thu Feb 19 10:04:12 1998 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (cp_convert_to_pointer): Preserve TREE_CONSTANT.
* typeck2.c (initializer_constant_valid_p): Allow conversions
- between pointers and refrerences.
+ between pointers and references.
1998-02-19 Brendan Kehoe <brendan@cygnus.com>
@@ -3304,14 +8310,14 @@ Tue Feb 17 14:07:52 1998 Mark Mitchell <mmitchell@usa.net>
(datadef): Remove redundant actions.
(initdcl0, notype_initdcl0, nomods_initdcl0): Use initdcl0_innards.
* parse.c: Regenerated.
-
+
Tue Feb 17 11:54:16 1998 Jason Merrill <jason@yorick.cygnus.com>
* parse.y (simple_stmt): Use getdecls() to check for decl.
Sat Feb 14 11:50:51 1998 Manfred Hollstein <manfred@s-direktnet.de>
- * Make-lang.in (DEMANGLER_INSTALL_NAME, DEMANGLER_CROSS_NAME): New
+ * Make-lang.in (DEMANGLER_INSTALL_NAME, DEMANGLER_CROSS_NAME): New
macros.
(c++.install-common): Install c++filt properly as native or as cross
variant.
@@ -3327,14 +8333,14 @@ Fri Feb 13 14:06:22 1998 Mike Stump <mrs@wrs.com>
Fri Feb 13 13:24:32 1998 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (simple_stmt): If the condition isn't a declaration,
+ * parse.y (simple_stmt): If the condition isn't a declaration,
start the controlled block after the test.
Fri Feb 13 02:26:10 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* call.c (build_over_call): Convert builtin abs, labs and fabs to
tree-codes.
- * decl.c (init_decl_processing): Reenable abs, labs and fabs as
+ * decl.c (init_decl_processing): Re-enable abs, labs and fabs as
builtins.
Fri Feb 13 01:36:42 1998 Jason Merrill <jason@yorick.cygnus.com>
@@ -3363,7 +8369,7 @@ Wed Feb 11 23:28:05 1998 Mark Mitchell <mmitchell@usa.net>
Wed Feb 11 16:42:04 1998 Mark Mitchell <mmitchell@usa.net>
* tree.c (is_overloaded_fn): Use really_overloaded_fn.
- (really_overloaded_fn): Move check here from is_overloaded_fn.
+ (really_overloaded_fn): Move check here from is_overloaded_fn.
(get_first_fn): Use really_overloaded_fn and is_overloaded_fn.
Wed Feb 11 15:54:18 1998 Mark Mitchell <mmitchell@usa.net>
@@ -3402,7 +8408,7 @@ Mon Feb 9 22:23:31 1998 Mark Mitchell <mmitchell@usa.net>
(uses_template_parms): Handle the DECL_INITIAL for a CONST_DECL.
* typeck.c (build_component_ref): Assign the correct type to the
result of build_vfn_ref.
-
+
Tue Feb 10 23:56:46 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (convert_nontype_argument): Fix typo.
@@ -3415,19 +8421,19 @@ Tue Feb 10 20:36:52 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Use DECL_USE_TEMPLATE instead
when deciding to override DECL_ASSEMBLER_NAME.
-Tue Feb 10 15:30:55 EST 1998 Andrew MacLeod <amacleod@torpedo.to.cygnus.com>
+Tue Feb 10 15:30:55 1998 Andrew MacLeod <amacleod@torpedo.to.cygnus.com>
* decl2.c (lang_f_options): Add -fsquangle to option processing list.
* cp-tree.h (flag_do_squangling): Add declaration.
* lang-options.h: Add -fsquangle and -fno-squangle.
* method.c: Add macros and static variables for squangling.
- (build_overload_name): Rename to build_mangled_name, add logic for B
- compression, and split into process_modifiers and
+ (build_overload_name): Rename to build_mangled_name, add logic for B
+ compression, and split into process_modifiers and
process_overload_item.
- (process_modifiers): New function, to handle constant, reference,
- and pointer types.
+ (process_modifiers): New function, to handle constant, reference,
+ and pointer types.
(process_overload_item): New function, handles issue of type codes.
- (build_overload_name): New function, start squangling and call
+ (build_overload_name): New function, start squangling and call
build_mangled_name.
(ALLOCATE_TYPEVEC, DEALLOCATE_TYPEVEC): Remove macro and expand inline.
(start_squangling): New function to initialize squangling structs.
@@ -3440,7 +8446,7 @@ Tue Feb 10 15:30:55 EST 1998 Andrew MacLeod <amacleod@torpedo.to.cygnus.com>
use DECL_ASSEMBLER_NAME when squangling is on.
(check_btype): New function, checks for B type compression.
(build_static_name, build_decl_overload_real): Initiate squangling.
- (build_typename_overload, build_overload_with_type): Initiate
+ (build_typename_overload, build_overload_with_type): Initiate
squangling
Sun Feb 8 23:47:38 1998 scott snyder <sss@d0linux01.fnal.gov>
@@ -3476,7 +8482,7 @@ Tue Feb 3 23:50:52 1998 Mark Mitchell <mmitchell@usa.net>
* cvt.c (ocp_convert): Obtain the constant values from constant
decls even if the destination type is the same as the type of the
- decl.
+ decl.
* decl2.c (finish_file): Make sure that static inlines with
definitions are not marked DECL_EXTERNAL before returning.
@@ -3485,7 +8491,7 @@ Tue Feb 3 22:43:42 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl.c: Lose arg_looking_for_template.
(lookup_name_real): Likewise.
- * parse.y: Lose processing_template_arg, template_arg1
+ * parse.y: Lose processing_template_arg, template_arg1.
(primary): Likewise.
* spew.c (yylex): Set lastiddecl for PTYPENAMEs, too.
@@ -3493,36 +8499,36 @@ Tue Feb 3 22:04:01 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* error.c (dump_decl): Fix type of default arguments for template
template parameters and nontype template parameters.
- * parse.y (template_parm): Handle invalid default template
+ * parse.y (template_parm): Handle invalid default template
template arguments here.
- * parse.y (template_parm): Use template_arg instead of PTYPENAME
+ * parse.y (template_parm): Use template_arg instead of PTYPENAME
for default template template argument.
- * pt.c (coerce_template_parms): Merge default template argument
+ * pt.c (coerce_template_parms): Merge default template argument
codes. Can treat RECORD_TYPE as template name if it is implicitly
created. Fix argument index in error message.
- * typeck.c (comptypes): Merge template argument comparison codes in
+ * typeck.c (comptypes): Merge template argument comparison codes in
TEMPLATE_TEMPLATE_PARM and RECORD_TYPE.
-Tue Jan 6 01:42:44 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Tue Jan 6 01:42:44 1998 Mumit Khan <khan@xraylith.wisc.edu>
* lex.c (file_name_nondirectory): Also check for '/'.
Mon Feb 2 11:24:22 1998 Mark Mitchell <mmitchell@usa.net>
* parse.y (primary): Deal with statement-expressions in
- templates.
+ templates.
* pt.c (tsubst_copy): Handle BIND_EXPR.
* tree.c (mapcar): Likewise.
* call.c (add_template_candidate_real): Pass extra parameter to
- fn_type_unification.
+ fn_type_unification.
* cp-tree.h (fn_type_unification): Add parameter.
* pt.c (fn_type_unification): Add additional parameter to deal with
static member functions.
(get_bindings): Deal with static member functions.
- * cp-tree.h (DECL_NONSTATIC_MEMBER_FUNCTION_P): New macro.
+ * cp-tree.h (DECL_NONSTATIC_MEMBER_FUNCTION_P): New macro.
(revert_static_member_fn): Declare.
* decl.c (revert_static_member_fn): Remove declaration. Change
linkage from internal to external.
@@ -3571,7 +8577,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(grokdeclarator): Add parentheses around && within ||. Add
explicit braces to avoid ambiguous `else'.
(grokparms): Initialize `type' to NULL_TREE.
- (xref_tag): Remove unused label `just_return'.
+ (xref_tag): Remove unused label `just_return'.
(finish_enum): Initialize `minnode' and `maxnode' to NULL_TREE.
(finish_function): Initialize `cond' and `thenclause' to NULL_TREE.
(hack_incomplete_structures): Add parentheses around assignment
@@ -3581,7 +8587,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* error.c: Include <stdlib.h>.
(dump_expr): Change the type of `i' to size_t. Remove unused
- label `error'.
+ label `error'.
* except.c (init_exception_processing): Remove unused variable `d'.
(expand_throw): Likewise for `label'.
@@ -3607,7 +8613,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
`look_for_semicolon' and `look_for_lbrac'.
(cons_up_default_function): Initialize `args' to NULL_TREE.
(readescape): Initialize `firstdig' to 0.
- (real_yylex): Add parentheses around assignment used as truth value.
+ (real_yylex): Add parentheses around assignment used as truth value.
* method.c: Include <strings.h> if we don't have <string.h>.
Protect declaration of `index' with autoconf macro.
@@ -3628,8 +8634,8 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* repo.c (init_repo): Add parentheses around assignment used as
truth value.
(finish_repo): Remove unused varable `p'.
-
- * search.c (get_binfo): Initiize `type' to NULL_TREE.
+
+ * search.c (get_binfo): Initialize `type' to NULL_TREE.
(get_base_distance): Likewise.
(lookup_field): Initialize `rval_binfo_h', `type', `basetype_path'
and `new_v' to NULL_TREE.
@@ -3649,7 +8655,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
(hash_tree_cons): Initialize hashcode to 0.
(can_free): Likewise for `size'.
(cp_tree_equal): Add explicit braces to avoid ambiguous `else'.
-
+
* typeck.c (convert_sequence): Hide prototype.
(common_type): Add explicit braces to avoid ambiguous `else'.
(comp_target_types): Likewise.
@@ -3665,7 +8671,7 @@ Mon Feb 2 00:57:38 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* xref.c (GNU_xref_decl): Initialize `cls' to 0.
-Sun Feb 1 12:45:34 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
+Sun Feb 1 12:45:34 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
* decl.c (init_decl_processing): Use set_sizetype.
* decl2.c (sizetype): Don't declare.
@@ -3688,13 +8694,13 @@ Thu Jan 29 10:39:30 1998 Mark Mitchell <mmitchell@usa.net>
Wed Jan 28 23:14:44 1998 Jason Merrill <jason@yorick.cygnus.com>
* class.c (instantiate_type): Don't just return a known type if
- it's wrong.
+ it's wrong.
Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
* class.c (instantiate_type): Remove handling of FUNCTION_DECL
since that code could never be reached.
-
+
* error.c (dump_decl): Avoid aborting in the midst of printing an
error message about an illegal template declaration.
@@ -3703,7 +8709,7 @@ Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (convert_nontype_argument): Allow REAL_TYPE and COMPLEX_TYPE
template arguments as a g++ extension.
-
+
* cp-tree.def (ALIGNOF_EXPR): New tree code.
* decl2.c (grok_alignof): If processing_template_decl, just store
the expression.
@@ -3715,7 +8721,7 @@ Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (uses_template_parms): Correctly determine whether or not a
SIZEOF_EXPR/ALIGNOF_EXPR uses template parameters so that constant
folding can be done.
-
+
* cp-tree.h (grok_enum_decls): Remove type parameter.
* decl.c (grok_enum_decls): Likewise.
* decl2.c (grok_x_components): Call grok_enum_decls
@@ -3727,7 +8733,7 @@ Wed Jan 28 11:04:07 1998 Mark Mitchell <mmitchell@usa.net>
* decl.c (start_function): Make member functions of local classes
in extern inline functions have comdat linkage here...
(grokdeclarator): Rather than here.
-
+
Wed Jan 28 10:55:47 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (convert_nontype_argument): Use decl_constant_value.
@@ -3755,18 +8761,18 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
(maybe_push_to_top_level): Save them.
(pop_from_top_level): Restore them.
(grokfndecl): Use new return value from
- check_explicit_specialization.
+ check_explicit_specialization.
(start_decl): Don't check flag_guiding_decls before pushing
- decls.
+ decls.
(cp_finish_decl): Remove previous (bogus) change.
(grok_declarator): Use decl_function_context rather than
- is_local_class.
+ is_local_class.
* decl2.c (finish_file): Pass extra argument to get_bindings.
- (build_expr_from_tree): Let build_x_component_ref check
+ (build_expr_from_tree): Let build_x_component_ref check
validity of arguments rather than doing it here.
* lex.c (cons_up_default_function): Remove code fooling with
processing_specialization, processing_explicit_instantiation
- flags, as that is now done in {maybe_push_top,pop_from}_top_level.
+ flags, as that is now done in {maybe_push_top,pop_from}_top_level.
* method.c (build_overload_identifier): Mangle local classes in
template functions correctly.
* parse.y (finish_member_template_decl): Move to pt.c.
@@ -3775,9 +8781,9 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
(determine_specialization): Change interface. Properly look for
most specialized versions of template candidates.
(check_explicit_specialization): Fully process explicit
- instantiations.
+ instantiations.
(push_template_decl): Avoid looking at CLASSTYPE fields in
- FUNCTION_DECLS.
+ FUNCTION_DECLS.
(determine_overloaded_function): Remove.
(convert_nontype_argument): Change name from
convert_nontype_parameter. Use determine_overloaded_function
@@ -3788,7 +8794,7 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
(lookup_template_class): Likewise.
(tsubst): Likewise.
(more_specialized): Take explict template arguments as a
- parameter.
+ parameter.
(most_specialized): Likewise.
(get_bindings): Likewise. Check that return types match before
proclaiming a function a match.
@@ -3801,7 +8807,7 @@ Tue Jan 27 16:42:21 1998 Mark Mitchell <mmitchell@usa.net>
Tue Jan 27 01:44:02 1998 Jason Merrill <jason@yorick.cygnus.com>
- * expr.c (cplus_expand_expr, AGGR_INIT_EXPR): Don't check that
+ * expr.c (cplus_expand_expr, AGGR_INIT_EXPR): Don't check that
return_target and call_target are equivalent.
* pt.c (type_unification_real): Just accept function parms that
@@ -3819,7 +8825,7 @@ Sat Jan 24 12:13:54 1998 Jason Merrill <jason@yorick.cygnus.com>
* error.c (dump_decl): Fix type default template args.
(dump_type): Hand TEMPLATE_DECL off to dump_decl.
-Fri Jan 23 18:34:37 1998 Mumit Khan <khan@xraylith.wisc.edu>
+Fri Jan 23 18:34:37 1998 Mumit Khan <khan@xraylith.wisc.edu>
* lex.c (DIR_SEPARATOR): Define to be '/' if not already defined.
(file_name_nondirectory): Use.
@@ -3827,10 +8833,10 @@ Fri Jan 23 18:34:37 1998 Mumit Khan <khan@xraylith.wisc.edu>
Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
* pt.c (coerce_template_parms): Don't access elements of ARGLIST
- that are not really present. Substitute default arguments in
- template template arguments. Correctly convert TEMPLATE_DECL to
+ that are not really present. Substitute default arguments in
+ template template arguments. Correctly convert TEMPLATE_DECL to
TEMPLATE_TEMPLATE_PARM.
- (comp_template_args): TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM
+ (comp_template_args): TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM
are no longer treated specially here.
* parse.y (template_template_parm): Fix copy error.
* decl.c (grokdeclarator): Warn about missing `typename' for nested
@@ -3851,15 +8857,15 @@ Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
(grokdeclarator): Handle TEMPLATE_DECL.
* decl2.c (constructor_name_full): Handle TEMPLATE_TEMPLATE_PARM.
* error.c (dump_type): Add TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM.
- (dump_type_prefix, dump_type_suffix) Handle TEMPLATE_TEMPLATE_PARM.
+ (dump_type_prefix, dump_type_suffix): Handle TEMPLATE_TEMPLATE_PARM.
(dump_decl): Handle unnamed template type parameters.
Handle template template parameters.
(dump_function_name): Handle template template parameters.
- * init.c (is_aggr_typedef, is_aggr_type, get_aggr_from_typedef):
+ * init.c (is_aggr_typedef, is_aggr_type, get_aggr_from_typedef):
Handle TEMPLATE_TEMPLATE_PARM.
* method.c (build_template_template_parm_names): New function.
(build_template_parm_names): Handle TEMPLATE_DECL.
- (build_overload_nested_name, build_overload_name):
+ (build_overload_nested_name, build_overload_name):
Handle TEMPLATE_TEMPLATE_PARM.
* parse.y (maybe_identifier): New nonterminal.
(template_type_parm): Use it.
@@ -3873,11 +8879,11 @@ Wed Jan 21 10:29:57 1998 Kriang Lerdsuwanakij <lerdsuwa@scf.usc.edu>
(process_template_parm): Handle template template parameters.
(coerce_template_parms, comp_template_args): Likewise.
(mangle_class_name_for_template, lookup_template_class): Likewise.
- (uses_template_parms): Handle TEMPLATE_DECL and
+ (uses_template_parms): Handle TEMPLATE_DECL and
TEMPLATE_TEMPLATE_PARM.
(current_template_args): Handle TEMPLATE_DECL.
(tsubst, tsubst_copy, unify): Handle TEMPLATE_TEMPLATE_PARM.
- * search.c (dfs_walk, dfs_record_inheritance):
+ * search.c (dfs_walk, dfs_record_inheritance):
Handle TEMPLATE_TEMPLATE_PARM.
* tree.c (copy_template_template_parm): New function.
(mapcar): Handle TEMPLATE_TEMPLATE_PARM.
@@ -3893,16 +8899,16 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* decl2.c (build_expr_from_tree): Issue an error message if the
object in a COMPONENT_REF is a TEMPLATE_DECL.
-
+
* typeck.c (incomplete_type_error): Handle TEMPLATE_TYPE_PARMs.
-
+
* class.c (is_local_class): New function.
* cp-tree.h (is_local_class): Declare it.
(last_tree): Likewise.
(begin_tree): Likewise.
(end_tree): Likewise.
(lookup_template_class): Change prototype.
- * decl.c (cp_finish_decl): Check for NULL where necesary.
+ * decl.c (cp_finish_decl): Check for NULL where necessary.
Consider FUNCTION_DECLS to declare objects with top-level binding,
when calling make_decl_rtl.
(grokdeclarator): Give members of local classes internal linkage.
@@ -3922,19 +8928,19 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* pt.c (saved_trees): New variable.
(mangle_class_name_for_template): Change prototype. Use
additional function context to name local classes in templates
- correctly.
+ correctly.
(classtype_mangled_name): Pass the context.
(push_template_decl): Handle local classes and templates, and
member functions for such classes.
(convert_nontype_parameter): Fix handling of pointer-to-member
- constants.
+ constants.
(lookup_template_class): Handle local classes in templates.
(tsubst): Likewise. Don't assume that template instantiations
- have external linkage; pay attention to the template declaration.
+ have external linkage; pay attention to the template declaration.
(mark_decl_instantiated): Likewise.
(begin_tree): New function.
(end_tree): Likewise.
-
+
* decl.c (xref_basetypes): Don't call complete_type for basetypes
that involve template parameters; that can lead to infinite
recursion unnecessarily.
@@ -3946,11 +8952,11 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
(build_template_decl): New function.
(push_template_delc): Handle out-of-class specializations of
member templates.
-
- * pt.c (check_explicit_specialization): Set up the template
- information before registering the specialization.
- (coerce_template_parms): Fix thinko.
- (tsubst): Handle specializations of member templates correctly.
+
+ * pt.c (check_explicit_specialization): Set up the template
+ information before registering the specialization.
+ (coerce_template_parms): Fix thinko.
+ (tsubst): Handle specializations of member templates correctly.
* class.c (finish_struct_methods): Remove calls to
check_explicit_specialization from here.
@@ -3960,7 +8966,7 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
(begin_explicit_instantiation): Likewise.
(end_explicit_instantiation): Likewise.
(determine_specialization): Renamed from
- determine_explicit_specialization.
+ determine_explicit_specialization.
(comp_template_parms): New function.
(processing_explicit_instantiation): New variable.
* cvt.c (perform_qualification_conversions): New function.
@@ -3970,7 +8976,7 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
instantiation/specialization mismatches.
(start_decl): Don't call pushdecl for template specializations,
since they don't affect overloading.
- (start_function): Likewise
+ (start_function): Likewise.
(grokfndecl): Call check_explicit_specialization a little later.
Don't call duplicate_decls for memberm template specializations.
(grokdeclarator): Don't update template_count for classes that are
@@ -3981,7 +8987,7 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
* parse.y (finish_member_template_decl): New function.
(component_decl_1): Use it.
(fn.def2): Likewise.
- (template_arg_list_opt): New nonterminal.
+ (template_arg_list_opt): New nonterminal.
(template_type): Use it.
(self_template_type): Likewise.
(template_id): Likewise.
@@ -4005,12 +9011,12 @@ Mon Jan 19 22:40:03 1998 Mark Mitchell <mmitchell@usa.net>
(comp_template_parms): New function.
(coerce_template_parms): Call convert_nontype_parameter.
(tsubst): Refine handling of member templates. Use
- register_specialization.
+ register_specialization.
(instantiate_template): Use retrieve_specialization.
(do_decl_instantiation): Likewise.
(instantiate_decl): Likewise.
(type_unification): Improve handling of explict template
- arguments.
+ arguments.
* tree.c (mapcar): Return error_mark_node, rather than aborting,
on VAR_DECLS, FUNCTION_DECLS, and CONST_DECLS.
* typeck.c (build_unary_op): Call determine_specialization, rather
@@ -4022,7 +9028,7 @@ Mon Jan 19 13:18:51 1998 Jason Merrill <jason@yorick.cygnus.com>
Fri Jan 16 11:40:50 1998 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * error.c (dump_decl): For enum tags, output the tag, not its value.
+ * error.c (dump_decl): For enum tags, output the tag, not its value.
1998-01-13 Brendan Kehoe <brendan@cygnus.com>
@@ -4052,11 +9058,11 @@ Wed Jan 7 23:47:13 1998 Jason Merrill <jason@yorick.cygnus.com>
(expand_exception_blocks): Likewise.
(alloc_eh_object): New fn.
(expand_throw): Use it. Protect exception init with terminate.
- * typeck.c (build_modify_expr): Remove code that ignores trivial
+ * typeck.c (build_modify_expr): Remove code that ignores trivial
methods.
Mon Dec 22 11:36:27 1997 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
+
* call.c (add_builtin_candidate): Add default case in enumeration
switch.
(build_new_op): Likewise.
@@ -4087,7 +9093,7 @@ Thu Dec 18 14:51:50 1997 Mark Mitchell <mmitchell@usa.net>
Thu Dec 18 14:43:19 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (unary_complex_lvalue): Ignore op0 when taking the
+ * typeck.c (unary_complex_lvalue): Ignore op0 when taking the
address of an OFFSET_REF.
* cp-tree.def: Add AGGR_INIT_EXPR.
@@ -4100,10 +9106,10 @@ Thu Dec 18 14:43:19 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Dec 17 17:08:52 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* pt.c (instantiate_class_template): Don't do injection when
- processing_template_decl is true, as pollutes current_binding_level
- for base classes.
+ processing_template_decl is true, as pollutes current_binding_level
+ for base classes.
-Wed Dec 17 21:17:39 1997 Peter Schmid <schmid@ltoi.iap.physik.tu-darmstadt.de>
+Wed Dec 17 21:17:39 1997 Peter Schmid <schmid@ltoi.iap.physik.tu-darmstadt.de>
* pt.c (maybe_fold_nontype_arg): Add prototype.
@@ -4123,21 +9129,21 @@ Sun Dec 14 22:34:20 1997 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (cp_convert_to_pointer): Fix base conversion of pm's.
- * pt.c (type_unification_real): Change __null to type void* with
+ * pt.c (type_unification_real): Change __null to type void* with
a warning.
Sun Dec 14 20:38:35 1997 Mark Mitchell <mmitchell@usa.net>
* call.c (implicit_conversion): Don't call
build_user_type_conversion_1 with a NULL expr, since it will
- crash.
+ crash.
* pt.c (unify): Don't try to unify array bounds if either array is
unbounded.
Fri Dec 12 16:09:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * errfn.c (cp_pedwarn, cp_pedwarn_at, cp_error_at, cp_warning_at):
+ * errfn.c (cp_pedwarn, cp_pedwarn_at, cp_error_at, cp_warning_at):
Replace extern decls with casts.
* decl.c (expand_start_early_try_stmts): Don't mess with a sequence.
@@ -4150,7 +9156,7 @@ Thu Dec 11 22:18:37 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (comdat_linkage): Also set DECL_COMDAT.
(finish_file): Check DECL_COMDAT instead of weak|one_only.
(import_export_vtable): Use make_decl_one_only instead of
- comdat_linkage for win32 tweak.
+ comdat_linkage for win32 tweak.
(import_export_decl): Likewise.
* pt.c (mark_decl_instantiated): Likewise.
@@ -4164,16 +9170,16 @@ Thu Dec 11 21:12:09 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c: Likewise.
Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
-
+
* decl.c (ptr_ptr_type_node): Define.
(init_decl_processing): Initialize it.
* cp-tree.h: Declare it.
* exception.cc (__cp_exception_info): Use __get_eh_info.
- (__cp_push_exception): Ditto.
- (__cp_pop_exception): Ditto.
+ (__cp_push_exception): Likewise.
+ (__cp_pop_exception): Likewise.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
- * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
+ * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
@@ -4186,8 +9192,8 @@ Mon Dec 8 23:17:13 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (expand_vec_init): Don't fold a list of parameters.
* decl.c (copy_args_p): Handle copy elision for types with virtual
- bases.
- * call.c (build_over_call): Likewise.
+ bases.
+ * call.c (build_over_call): Likewise.
Sun Dec 7 22:38:12 1997 Mark Mitchell <mmitchell@usa.net>
@@ -4242,8 +9248,8 @@ Fri Dec 5 01:17:34 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Dec 3 20:02:39 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_new): Use a TARGET_EXPR instead of SAVE_EXPR for
- alloc_expr.
- * call.c (build_op_delete_call): Adjust.
+ alloc_expr.
+ * call.c (build_op_delete_call): Adjust.
* except.c (expand_end_catch_block): Lose rethrow region.
(expand_start_catch_block): Likewise.
@@ -4252,7 +9258,7 @@ Wed Dec 3 20:02:39 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Dec 3 13:24:04 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* pt.c (tsubst): Remove tree_cons call (places redundant info into
- DECL_TEMPLATE_INSTANTIATION).
+ DECL_TEMPLATE_INSTANTIATION).
Wed Dec 3 11:44:52 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4294,7 +9300,7 @@ Tue Dec 2 01:37:19 1997 Jason Merrill <jason@yorick.cygnus.com>
Fri Nov 28 01:58:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (check_explicit_specialization): Complain about using a
+ * pt.c (check_explicit_specialization): Complain about using a
template-id for a non-specialization.
Fri Nov 28 12:35:19 1997 Scott Christley <scottc@net-community.com>
@@ -4304,7 +9310,7 @@ Fri Nov 28 12:35:19 1997 Scott Christley <scottc@net-community.com>
Fri Nov 28 01:56:35 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * error.c (dump_decl): Handle TEMPLATE_ID_EXPR.
+ * error.c (dump_decl): Handle TEMPLATE_ID_EXPR.
Thu Nov 27 00:59:46 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4312,9 +9318,9 @@ Thu Nov 27 00:59:46 1997 Jason Merrill <jason@yorick.cygnus.com>
handing off to convert_to_reference.
* except.c: Lose Unexpected, SetTerminate, SetUnexpected,
- TerminateFunctionCall.
+ TerminateFunctionCall.
(init_exception_processing): Likewise. Terminate et al are now
- the fns, not ADDR_EXPRs.
+ the fns, not ADDR_EXPRs.
(various): Lose redundant assemble_external calls.
(do_unwind): s/BuiltinReturnAddress/builtin_return_address_fndecl/.
@@ -4325,7 +9331,7 @@ Thu Nov 27 00:59:46 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (import_export_decl): Just set DECL_COMDAT on VAR_DECLs.
* class.c: Remove static pending_hard_virtuals.
- (add_virtual_function): Take pointers to pending_virtuals
+ (add_virtual_function): Take pointers to pending_virtuals
and pending_hard_virtuals.
(finish_struct_1): Pass them. Declare pending_hard_virtuals.
@@ -4334,7 +9340,7 @@ Wed Nov 26 20:28:49 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (import_export_vtable): If we support one_only but not
weak symbols, mark instantiated template vtables one_only.
(import_export_decl): Likewise for tinfo functions.
- (finish_vtable_vardecl): Also write out vtables from explicitly
+ (finish_vtable_vardecl): Also write out vtables from explicitly
instantiated template classes.
* pt.c (mark_class_instantiated): Revert last change.
@@ -4369,7 +9375,7 @@ Tue Nov 25 11:28:21 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_new): Copy size to the saveable obstack.
* init.c (build_new): Stick a CLEANUP_POINT_EXPR inside the
- TRY_CATCH_EXPR for now.
+ TRY_CATCH_EXPR for now.
Mon Nov 24 12:15:55 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4390,14 +9396,14 @@ Fri Nov 21 12:22:07 1997 Jason Merrill <jason@yorick.cygnus.com>
(expand_end_eh_spec): Likewise. Call __check_eh_spec instead of
doing everything inline.
(init_exception_processing): throw_type_match now takes
- const void pointers.
+ const void pointers.
* exception.cc (__check_eh_spec): New fn.
* inc/exception: Neither terminate nor unexpected return.
* decl.c: Make const_ptr_type_node public.
* tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly.
* except.c (expand_start_catch_block): We only need the rethrow
- region for non-sjlj exceptions.
+ region for non-sjlj exceptions.
(expand_end_catch_block): Likewise. Use outer_context_label_stack.
Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4412,7 +9418,7 @@ Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (init_decl_processing): Update exception specs on new and
delete.
- * method.c (build_decl_overload_real): Don't mess with global
+ * method.c (build_decl_overload_real): Don't mess with global
placement delete.
* init.c (build_new): Check for null throw spec, not nothrow_t.
@@ -4427,13 +9433,13 @@ Thu Nov 20 14:40:17 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 19 18:24:14 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Don't just complain about a mismatched
+ * decl.c (start_decl): Don't just complain about a mismatched
scope, fix it.
* decl.c (make_implicit_typename): Handle case where t is not
- actually from context.
+ actually from context.
* tree.c (get_type_decl): Lose identifier case.
- * spew.c (yylex): Lose useless call to identifer_typedecl_value.
+ * spew.c (yylex): Lose useless call to identifier_typedecl_value.
* parse.y (nonnested_type): Just use lookup_name.
(complex_type_name): Just use IDENTIFIER_GLOBAL_VALUE.
@@ -4448,7 +9454,7 @@ Wed Nov 19 10:39:27 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (make_implicit_typename): New fn.
(lookup_name_real): Use it. Use current_class_type as the context.
-Mon Nov 17 23:42:03 1997 Bruno Haible <haible@ilog.fr>
+Mon Nov 17 23:42:03 1997 Bruno Haible <haible@ilog.fr>
* pt.c (do_poplevel): Don't prohibit jumps into this contour.
@@ -4483,7 +9489,7 @@ Thu Nov 13 01:52:36 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 12 11:04:33 1997 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (do_type_instantiation): Fix typo.
- (mark_class_instantiated): If we support one_only but not weak
+ (mark_class_instantiated): If we support one_only but not weak
symbols, don't mark this as known.
* init.c (build_new): Handle vec delete in EH cleanup.
@@ -4491,7 +9497,7 @@ Wed Nov 12 11:04:33 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 12 08:11:55 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* call.c (build_method_call): Call complete_type before checking
- for destructor.
+ for destructor.
Sun Nov 9 01:29:55 1997 Jim Wilson (wilson@cygnus.com)
@@ -4524,32 +9530,32 @@ Tue Nov 11 02:53:44 1997 Jason Merrill <jason@lasher.cygnus.com>
Mon Nov 10 20:25:31 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_new_method_call): Handle getting a
- TEMPLATE_ID_EXPR around a TEMPLATE_DECL. Don't look for a field
- if we got template parms.
+ TEMPLATE_ID_EXPR around a TEMPLATE_DECL. Don't look for a field
+ if we got template parms.
* typeck.c (build_x_function_call): Remember the TEMPLATE_ID_EXPR,
- not just the args.
+ not just the args.
* decl2.c (build_expr_from_tree): Tweak last change.
* pt.c (tsubst_copy): Use get_first_fn instead of TREE_VALUE.
(maybe_fold_nontype_arg): Split out from tsubst_copy.
* tree.c (get_first_fn): Just return a TEMPLATE_ID_EXPR.
-Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
+Mon Nov 10 20:08:38 1997 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu>
- * pt.c (tsubst_copy): Handle explicit template arguments in
+ * pt.c (tsubst_copy): Handle explicit template arguments in
function calls.
* typeck.c (build_x_function_call): Likewise.
- * decl2.c (build_expr_from_tree): Lookup function name if it
+ * decl2.c (build_expr_from_tree): Lookup function name if it
hasn't been done.
- * pt.c (tsubst): Instantiate template functions properly when
- template parameter does not appear in function arguments and return
+ * pt.c (tsubst): Instantiate template functions properly when
+ template parameter does not appear in function arguments and return
type.
(comp_template_args): Handle member templates required by tsubst.
Mon Nov 10 20:08:38 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Tweak conditions for pedwarn in
- previous change.
+ previous change.
Mon Nov 10 20:08:29 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
@@ -4570,10 +9576,10 @@ Mon Nov 10 03:04:20 1997 Jason Merrill <jason@yorick.cygnus.com>
(expand_end_catch_block): Likewise. End the region for the eh_cleanup.
* exception.cc (__cp_pop_exception): Now takes two parms. Handle
popping off the middle of the stack.
- * tree.c (lvalue_p, real_lvalue_p): Handle TRY_CATCH_EXPR,
+ * tree.c (lvalue_p, real_lvalue_p): Handle TRY_CATCH_EXPR,
WITH_CLEANUP_EXPR, and UNSAVE_EXPR.
(build_cplus_new): Only wrap CALL_EXPRs.
- * init.c (expand_default_init): Handle a TRY_CATCH_EXPR around
+ * init.c (expand_default_init): Handle a TRY_CATCH_EXPR around
the constructor call.
Sun Nov 9 18:00:26 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
@@ -4642,7 +9648,7 @@ Fri Oct 31 01:47:57 1997 Jason Merrill <jason@yorick.cygnus.com>
(__cp_exception_info, __uncatch_exception): New fns.
(__cp_push_exception, __cp_pop_exception): New fns.
* except.c: Lose saved_throw_{type,value,cleanup,in_catch}.
- Lose empty_fndecl.
+ Lose empty_fndecl.
(init_exception_processing): Likewise. __eh_pc is now external.
(push_eh_info): New fn.
(get_eh_{info,value,type,caught}): New fns.
@@ -4670,21 +9676,21 @@ Thu Oct 23 02:01:30 1997 Jason Merrill <jason@yorick.cygnus.com>
Mon Oct 20 12:06:34 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (expand_exception_blocks): Call do_pending_stack_adust.
+ * except.c (expand_exception_blocks): Call do_pending_stack_adjust.
(expand_end_catch_block): Likewise.
(expand_end_eh_spec): Likewise.
Mon Oct 20 11:44:20 1997 Mark Mitchell <mmitchell@usa.net>
* decl.c (duplicate_decls): Handle template specializations
- correctly.
+ correctly.
* error.c (dump_function_name): Fix printing of specializations of
member functions that are not member templates.
* cp-tree.h (processing_specialization): Make global.
* pt.c (processing_specialization): Likewise.
* lex.c (cons_up_default_function): Save and restore
processing_specialization to avoid confusion.
-
+
Mon Oct 20 10:52:22 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (init_decl_processing): Give null_node unknown* type.
@@ -4701,7 +9707,7 @@ Sun Oct 19 09:13:01 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Make-lang.in (g++): Include prefix.o.
-Thu Oct 16 15:31:09 1997 Judy Goldberg <judygold@sanwafp.com>
+Thu Oct 16 15:31:09 1997 Judy Goldberg <judygold@sanwafp.com>
* pt.c (determine_explicit_specialization): Initialize "dummy"
to keep Purify quiet.
@@ -4727,19 +9733,19 @@ Tue Oct 14 12:01:00 1997 Mark Mitchell <mmitchell@usa.net>
so as to avoid incorrect manglings.
* method.c (build_decl_overload_real): Don't mangle return types
for constructors.
-
+
Tue Oct 14 11:46:14 1997 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (scratchalloc, build_scratch_list, make_scratch_vec,
scratch_tree_cons): Define as macros for now.
- * call.c, class.c, cvt.c, decl.c, decl2.c, except.c, expr.c, init.c,
+ * call.c, class.c, cvt.c, decl.c, decl2.c, except.c, expr.c, init.c,
lex.c, method.c, parse.y, pt.c, rtti.c, search.c, tree.c, typeck.c,
typeck2.c: Use them and the expression_obstack variants.
Mon Oct 13 17:41:26 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* decl.c (store_return_init): Allow classes with explicit ctors to
- be used with the named return values extension.
+ be used with the named return values extension.
Fri Oct 10 12:21:11 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -4753,7 +9759,7 @@ Thu Oct 9 12:08:21 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_new_method_call): Use simple constructor_name for
error messages.
-Wed Oct 8 22:44:42 1997 Jeffrey A Law (law@cygnus.com)
+Wed Oct 8 22:44:42 1997 Jeffrey A Law <law@cygnus.com>
* method.c (build_underscore_int): Don't use ANSI specific
features.
@@ -4774,9 +9780,9 @@ Tue Oct 7 22:52:10 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Oct 7 22:45:31 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
- * typeck.c (build_reinterpret_cast): converting a void pointer
+ * typeck.c (build_reinterpret_cast): Converting a void pointer
to function pointer with a reinterpret_cast produces a warning
- if -pedantic is issued
+ if -pedantic is issued.
Tue Oct 7 22:43:43 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
@@ -4803,7 +9809,7 @@ Tue Oct 7 00:48:36 1997 Jason Merrill <jason@yorick.cygnus.com>
non-templates.
* call.c (build_new_function_call): Fix handling of null explicit
- template args.
+ template args.
(build_new_method_call): Likewise.
Mon Oct 6 23:44:34 1997 Mark Mitchell <mmitchell@usa.net>
@@ -4855,7 +9861,7 @@ Tue Sep 30 00:18:26 1997 Jason Merrill <jason@yorick.cygnus.com>
-traditional and -ansi now do not mess with
dollars_in_ident.
-Mon Sep 29 19:57:51 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
+Mon Sep 29 19:57:51 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
* Makefile.in (parse.o, decl.o): Also depend on
$(srcdir)/../except.h $(srcdir)/../output.h.
@@ -4866,37 +9872,37 @@ Mon Sep 29 19:57:51 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
* call.c, cp-tree.h, decl.c, tree.c: Finish prototyping.
- * expr.c (cplus_expand_expr): Make it static.
+ * expr.c (cplus_expand_expr): Make it static.
* decl2.c, init.c, typeck.c: Include "expr.h".
(expand_expr): Use proper values when calling the function.
Mon Sep 29 11:05:54 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
- * lang-options.h: new -Wold-style-cast flag.
- * cp-tree.h (warn_old_style_cast): new variable.
- * decl2.c (warn_old_style_cast): ditto.
- (lang_decode_option): support -Wold-style-cast.
- (reparse_absdcl_as_casts): produce old-style-cast warning.
+ * lang-options.h: New -Wold-style-cast flag.
+ * cp-tree.h (warn_old_style_cast): New variable.
+ * decl2.c (warn_old_style_cast): Likewise.
+ (lang_decode_option): Support -Wold-style-cast.
+ (reparse_absdcl_as_casts): Produce old-style-cast warning.
Mon Sep 29 09:20:53 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
* decl.c (cp_finish_decl): Allow expand_aggr_init to set
- TREE_USED, reset value based on already_used.
+ TREE_USED, reset value based on already_used.
* init.c (expand_member_init): Revert change.
-
+
Mon Sep 29 08:57:53 1997 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h, decl.c, decl2.c, pt.c:
- Lose DECL_C_STATIC and DECL_PUBLIC. Don't pretend statics are public.
+ Lose DECL_C_STATIC and DECL_PUBLIC. Don't pretend statics are public.
* decl2.c (lang_decode_option): Add missing ;.
Sat Sep 27 16:22:48 1997 Jason Merrill <jason@yorick.cygnus.com>
* friend.c (do_friend): Disable injection for all template-derived
- decls.
+ decls.
* decl2.c (lang_decode_option): Handle -fguiding-decls.
* parse.y (notype_template_declarator): New nonterminal.
(direct_notype_declarator): Use it.
@@ -4906,112 +9912,112 @@ Sat Sep 27 16:22:48 1997 Jason Merrill <jason@yorick.cygnus.com>
Sat Sep 27 16:21:58 1997 Mark Mitchell <mmitchell@usa.net>
- * call.c (add_template_candidate): Add explicit_targs parameter.
- (build_scoped_method_call): Use it.
- (build_overload_call_real): Likewise.
- (build_user_type_conversion_1): Likewise.
- (build_new_function_call): Likewise.
- (build_object_call): Likewise.
- (build_new_op): Likewise.
- (build_new_method_call): Likewise.
- (build_new_function_call): Handle TEMPLATE_ID_EXPR.
- (build_new_method_call): Likewise.
+ * call.c (add_template_candidate): Add explicit_targs parameter.
+ (build_scoped_method_call): Use it.
+ (build_overload_call_real): Likewise.
+ (build_user_type_conversion_1): Likewise.
+ (build_new_function_call): Likewise.
+ (build_object_call): Likewise.
+ (build_new_op): Likewise.
+ (build_new_method_call): Likewise.
+ (build_new_function_call): Handle TEMPLATE_ID_EXPR.
+ (build_new_method_call): Likewise.
- * class.c (finish_struct_methods): Add specialization pass to
- determine which methods were specializing which other methods.
- (instantiate_type): Handle TEMPLATE_ID_EXPR.
+ * class.c (finish_struct_methods): Add specialization pass to
+ determine which methods were specializing which other methods.
+ (instantiate_type): Handle TEMPLATE_ID_EXPR.
- * cp-tree.def (TEMPLATE_ID_EXPR): New tree code.
+ * cp-tree.def (TEMPLATE_ID_EXPR): New tree code.
- * cp-tree.h (name_mangling_version): New variable.
+ * cp-tree.h (name_mangling_version): New variable.
(flag_guiding_decls): Likewise.
- (build_template_decl_overload): New function.
- (begin_specialization): Likewise.
- (reset_specialization): Likewise.
- (end_specialization): Likewise.
- (determine_explicit_specialization): Likewise.
- (check_explicit_specialization): Likewise.
- (lookup_template_function): Likewise.
- (fn_type_unification): Add explicit_targs parameter.
- (type_unification): Likewise.
-
- * decl.c (duplicate_decls): Add smarts for explicit
- specializations.
- (grokdeclarator): Handle TEMPLATE_ID_EXPR, and function
- specializations.
- (grokfndecl): Call check_explicit_specialization.
-
- * decl2.c (lang_decode_option): Handle -fname-mangling-version.
- (build_expr_from_tree): Handle TEMPLATE_ID_EXPR.
- (check_classfn): Handle specializations.
-
- * error.c (dump_function_name): Print specialization arguments.
-
- * friend.c (do_friend): Don't call pushdecl for template
- instantiations.
-
- * init.c (build_member_call): Handle TEMPLATE_ID_EXPR.
-
- * lang-options.h: Add -fname-mangling-version, -fguiding-decls,
+ (build_template_decl_overload): New function.
+ (begin_specialization): Likewise.
+ (reset_specialization): Likewise.
+ (end_specialization): Likewise.
+ (determine_explicit_specialization): Likewise.
+ (check_explicit_specialization): Likewise.
+ (lookup_template_function): Likewise.
+ (fn_type_unification): Add explicit_targs parameter.
+ (type_unification): Likewise.
+
+ * decl.c (duplicate_decls): Add smarts for explicit
+ specializations.
+ (grokdeclarator): Handle TEMPLATE_ID_EXPR, and function
+ specializations.
+ (grokfndecl): Call check_explicit_specialization.
+
+ * decl2.c (lang_decode_option): Handle -fname-mangling-version.
+ (build_expr_from_tree): Handle TEMPLATE_ID_EXPR.
+ (check_classfn): Handle specializations.
+
+ * error.c (dump_function_name): Print specialization arguments.
+
+ * friend.c (do_friend): Don't call pushdecl for template
+ instantiations.
+
+ * init.c (build_member_call): Handle TEMPLATE_ID_EXPR.
+
+ * lang-options.h: Add -fname-mangling-version, -fguiding-decls,
and -fno-guiding-decls.
- * lex.c (identifier_type): Return PFUNCNAME for template function
- names.
-
- * method.c (build_decl_overload_real): New function.
- (build_template_parm_names): New function.
- (build_overload_identifier): Use it.
- (build_underscore_int): New function.
- (build_overload_int): Use it. Add levels for template
- parameters.
- (build_overload_name): Likewise. Also, handle TYPENAME_TYPEs.
- (build_overload_nested_names): Handle template type parameters.
- (build_template_decl_overload): New function.
-
- * parse.y (YYSTYPE): New ntype member.
- (nested_name_specifier): Use it.
- (nested_name_specifier_1): Likewise.
- (PFUNCNAME): New token.
- (template_id, object_template_id): New non-terminals.
- (template_parm_list): Note specializations.
- (template_def): Likewise.
- (structsp): Likewise.
- (fn.def2): Handle member template specializations.
- (component_decl_1): Likewise.
- (direct_notype_declarator): Handle template-ids.
- (component_decl_1): Likewise.
- (direct_notype_declarator): Handle template-ids.
- (primary): Handle TEMPLATE_ID_EXPR, and template-ids.
-
- * pt.c (processing_specializations): New variable.
- (template_header_count): Likewise.
- (type_unification_real): New function.
- (processing_explicit_specialization): Likewise.
- (note_template_header): Likewise.
- (is_member_template): Handle specializations.
- (end_template_decl): Call reset_specialization.
- (push_template_decl): Handle member template specializations.
- (tsubst): Likewise.
- (tsubst_copy): Handle TEMPLATE_ID_EXPR.
- (instantiate_template): Handle specializations.
- (instantiate_decl): Likewise.
- (fn_type_unification): Handle explicit_targs.
- (type_unification): Likewise. Allow incomplete unification
- without an error message, if allow_incomplete.
- (get_bindings): Use new calling sequence for fn_type_unification.
-
- * spew.c (yylex): Handle PFUNCNAME.
-
- * tree.c (is_overloaded_fn): Handle TEMPLATE_ID_EXPR.
- (really_overloaded_fn): Likewise.
- (get_first_fn): Handle function templates.
-
- * typeck.c (build_x_function_call): Use really_overloaded_fn.
- Handle TEMPLATE_ID_EXPR.
- (build_x_unary_op): Likewise.
- (build_unary_op): Likewise.
- (mark_addressable): Templates whose address is taken are marked
- as used.
+ * lex.c (identifier_type): Return PFUNCNAME for template function
+ names.
+
+ * method.c (build_decl_overload_real): New function.
+ (build_template_parm_names): New function.
+ (build_overload_identifier): Use it.
+ (build_underscore_int): New function.
+ (build_overload_int): Use it. Add levels for template
+ parameters.
+ (build_overload_name): Likewise. Also, handle TYPENAME_TYPEs.
+ (build_overload_nested_names): Handle template type parameters.
+ (build_template_decl_overload): New function.
+
+ * parse.y (YYSTYPE): New ntype member.
+ (nested_name_specifier): Use it.
+ (nested_name_specifier_1): Likewise.
+ (PFUNCNAME): New token.
+ (template_id, object_template_id): New non-terminals.
+ (template_parm_list): Note specializations.
+ (template_def): Likewise.
+ (structsp): Likewise.
+ (fn.def2): Handle member template specializations.
+ (component_decl_1): Likewise.
+ (direct_notype_declarator): Handle template-ids.
+ (component_decl_1): Likewise.
+ (direct_notype_declarator): Handle template-ids.
+ (primary): Handle TEMPLATE_ID_EXPR, and template-ids.
+
+ * pt.c (processing_specializations): New variable.
+ (template_header_count): Likewise.
+ (type_unification_real): New function.
+ (processing_explicit_specialization): Likewise.
+ (note_template_header): Likewise.
+ (is_member_template): Handle specializations.
+ (end_template_decl): Call reset_specialization.
+ (push_template_decl): Handle member template specializations.
+ (tsubst): Likewise.
+ (tsubst_copy): Handle TEMPLATE_ID_EXPR.
+ (instantiate_template): Handle specializations.
+ (instantiate_decl): Likewise.
+ (fn_type_unification): Handle explicit_targs.
+ (type_unification): Likewise. Allow incomplete unification
+ without an error message, if allow_incomplete.
+ (get_bindings): Use new calling sequence for fn_type_unification.
+
+ * spew.c (yylex): Handle PFUNCNAME.
+
+ * tree.c (is_overloaded_fn): Handle TEMPLATE_ID_EXPR.
+ (really_overloaded_fn): Likewise.
+ (get_first_fn): Handle function templates.
+
+ * typeck.c (build_x_function_call): Use really_overloaded_fn.
+ Handle TEMPLATE_ID_EXPR.
+ (build_x_unary_op): Likewise.
+ (build_unary_op): Likewise.
+ (mark_addressable): Templates whose address is taken are marked
+ as used.
1997-09-25 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
@@ -5041,7 +10047,7 @@ Thu Sep 25 11:11:13 1997 Jason Merrill <jason@yorick.cygnus.com>
Rvalue conversions were removed in London.
* call.c (is_subseq): Don't consider lvalue transformations.
(build_conv): LVALUE_CONV and RVALUE_CONV get IDENTITY_RANK.
- (joust): Reenable ?: kludge.
+ (joust): Re-enable ?: kludge.
1997-09-22 Brendan Kehoe <brendan@lisa.cygnus.com>
@@ -5077,12 +10083,12 @@ Wed Sep 17 10:31:25 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Sep 16 14:06:56 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_new_op): Give better error for syntactically
- correct, but semantically invalid, use of undeclared template.
+ correct, but semantically invalid, use of undeclared template.
* call.c (compare_qual): Handle pmfs.
* decl.c (store_parm_decls): last_parm_cleanup_insn is the insn
- after the exception spec.
+ after the exception spec.
Mon Sep 15 11:52:13 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5118,9 +10124,9 @@ Thu Sep 11 10:08:45 1997 Mark Mitchell <mmitchell@usa.net>
* pt.c (coerce_template_parms): Avoid looking at the
TYPE_LANG_DECL portion of a typename type, since there won't be
- one.
+ one.
(tsubst): Do constant folding as necessary to make sure that
- arguments passed to lookup_template_class really are constants.
+ arguments passed to lookup_template_class really are constants.
Wed Sep 10 11:21:55 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5137,9 +10143,9 @@ Tue Sep 9 19:49:38 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Sep 9 17:57:25 1997 Mark Mitchell <mmitchell@usa.net>
* error.c (dump_decl): Avoid crashing when presented with a
- uninitialized constant, as can occur with a template parameter.
+ uninitialized constant, as can occur with a template parameter.
(dump_expr): Make sure that there are enough levels of
- current_template_parms before we start diving through them.
+ current_template_parms before we start diving through them.
1997-09-09 Brendan Kehoe <brendan@lisa.cygnus.com>
@@ -5148,7 +10154,7 @@ Tue Sep 9 17:57:25 1997 Mark Mitchell <mmitchell@usa.net>
Tue Sep 9 09:36:39 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * except.c (expand_throw): Call build_delete for all
+ * except.c (expand_throw): Call build_delete for all
exception types, not just objects with destructors.
Mon Sep 8 02:33:20 1997 Jody Goldberg <jodyg@idt.net>
@@ -5156,7 +10162,7 @@ Mon Sep 8 02:33:20 1997 Jody Goldberg <jodyg@idt.net>
* decl.c (current_local_enum): Remove static.
* pt.c (tsubst_enum): Save and restore value of current_local_enum
in case template is expanded in enum decl.
- (instantiate_class_template) : Use new tsubst_enum signature.
+ (instantiate_class_template): Use new tsubst_enum signature.
(tsubst_expr): Likewise.
Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
@@ -5168,7 +10174,7 @@ Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
member templates using the same parameter names can be declared.
(end_member_template_processing): Pop the binding level.
(push_template_decl): Mark member templates as static when
- appropriate.
+ appropriate.
* lex.c (do_pending_inlines): Pass the function, not its template
arguments, to begin_member_template_processing.
@@ -5176,17 +10182,17 @@ Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
(do_pending_defargs): Likewise.
* error.c (dump_expr): Obtain the correct declaration for a
- TEMPLATE_CONST_PARM.
+ TEMPLATE_CONST_PARM.
* call.c (add_template_conv_candidate): New function.
(build_object_call): Handle member templates, as done in the other
build_ functions.
-
+
Sat Sep 6 10:20:27 1997 Mark Mitchell <mmitchell@usa.net>
* decl.c (replace_defag): Undo previous change.
* lex.c (do_pending_defargs): Deal with member templates.
-
+
* pt.c (is_member_template): Avoid crashing when passed a
non-function argument.
@@ -5206,24 +10212,24 @@ Fri Sep 5 01:37:17 1997 Mark Mitchell <mmitchell@usa.net>
* pt.c (push_template_decl): Likewise.
(classtype_mangled_name): Likewise.
(lookup_template_class): Likewise.
-
+
* cp-tree.h (DECL_NTPARMS): Change name from DECL_NT_PARMS to
DECL_NTPARMS to conform to usage elsewhere.
* call.c (add_template_candidate): Likewise.
* class.c (instantiate_type): Likewise.
* pt.c (instantiate_template): Likewise.
(get_bindings): Likewise.
-
+
* class.c (grow_method): Use DECL_FUNCTION_TEMPLATE_P instead of
is_member_template.
* pt.c (unify): Undo changes to allow multiple levels of template
- parameters.
+ parameters.
(type_unification): Likewise.
(fn_type_unification): Likewise.
(get_class_bindings): Likewise.
* cp-tree.h (Likewise).
-
+
* decl.c (replace_defarg): Check that the type of the default
parameter does not invlove a template type before complaining
about the initialization.
@@ -5232,13 +10238,13 @@ Fri Sep 5 01:37:17 1997 Mark Mitchell <mmitchell@usa.net>
member templates correctly.
* pt.c (is_member_template): Deal with class specializations
- correctly.
+ correctly.
(tsubst): Handle "partial instantiation" of member templates
- correctly.
+ correctly.
Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
- * pt.c (type_unification): Change calling squence to allow for
+ * pt.c (type_unification): Change calling sequence to allow for
multiple levels of template parameters.
(tsubst_expr): Likewise.
(tsubst): Likewise.
@@ -5252,7 +10258,7 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
* decl.c (grokdeclarator): Use it.
* decl2.c (finish_file): Use it.
* method.c (build_overload_identifier): Use it.
-
+
* call.c (add_template_candidate): Add additional parameter for
the function return type. Call fn_type_unification istead of
type_unification.
@@ -5260,12 +10266,12 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(build_new_function_call): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.
-
+
* class.c (grow_method): Don't give an error message indicating
- that two member templates with the same name are ambiguous.
+ that two member templates with the same name are ambiguous.
(finish_struct): Treat member template functions just like member
- functions.
-
+ functions.
+
* cp-tree.h (check_member_template): Add declaration.
(begin_member_template_processing): Likewise.
(end_member_template_processing): Likewise.
@@ -5278,31 +10284,31 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(get_bindings): Likewise.
* decl.c (decls_match): Handle multiple levels of template
- parameters.
+ parameters.
(pushdecl): Handle template type params just like other type
- declarations.
+ declarations.
(push_class_level_binding): Return immediately if the
class_binding_level is NULL.
(grokfndecl): If check_classfn() returns a member_template, use
the result of the template, not the template itself.
-
+
* decl2.c (check_member_template): New function. Check to see
that the entity declared to be a member template can be one.
(check_classfn): Allow redeclaration of member template functions
with different types; the new functions can be specializations or
explicit instantiations.
-
+
* error.c (dump_decl): Handle multiple levels of template
- parameters.
- (dump_function_decl): Update to handle function templates.
+ parameters.
+ (dump_function_decl): Update to handle function templates.
* lex.c (do_pending_inlines): Set up template parameter context
for member templates.
(process_next_inline): Likewise.
- * method. (build_overload_identifier): Adjust for multiple levels
+ * method.c (build_overload_identifier): Adjust for multiple levels
of template parameters.
-
+
* parse.y (fn.def2): Add member templates.
(component_decl_1): Likewise.
@@ -5313,7 +10319,7 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(current_template_parms): Return a vector of all the template
parms, not just the innermost level of parms.
(push_template_decl): Deal with the possibility of member
- templates.
+ templates.
(lookup_template_class): Likewise.
(uses_template_parms): Likewise.
(tsubst): Modify processing to TEMPLATE_TYPE_PARM and
@@ -5323,7 +10329,7 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
(do_decl_instantiation): Handle member templates.
* search.c (lookup_fnfields_1): Handle member template conversion
- operators.
+ operators.
* tree.c (cp_tree_equal): Check the levels, as well as the
indices, of TEMPLATE_CONST_PARMs.
@@ -5331,12 +10337,12 @@ Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
* typeck.c (comptypes): Check the levels, as well as the indices,
fo TEMPLATE_TYPE_PARMs.
(build_x_function_call): Treat member templates like member
- functions.
-
+ functions.
+
Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (c_expand_return): Always convert_for_initialization
- before checking for returning a pointer to local.
+ before checking for returning a pointer to local.
* pt.c (type_unification): If strict and the function parm doesn't
use template parms, just compare types.
@@ -5349,7 +10355,7 @@ Wed Sep 3 10:35:49 1997 Klaus Espenlaub <kespenla@student.informatik.uni-ulm.
Wed Sep 3 00:02:53 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (convert_arguments): Don't arbitrarily choose the first
- of a set of overloaded functions.
+ of a set of overloaded functions.
Tue Sep 2 12:09:13 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5360,12 +10366,12 @@ Tue Sep 2 12:09:13 1997 Jason Merrill <jason@yorick.cygnus.com>
(build_overload_identifier): Pass it.
* decl.c (duplicate_decls): Don't bash a previous template
- definition with a redeclaration.
+ definition with a redeclaration.
* pt.c (unify): float doesn't match double.
* pt.c (do_type_instantiation): Handle getting a _TYPE or a
- TYPE_DECL. Handle getting non-template types.
+ TYPE_DECL. Handle getting non-template types.
* parse.y (explicit_instantiation): Use typespec instead of
aggr template_type.
@@ -5373,7 +10379,7 @@ Tue Sep 2 10:27:08 1997 Richard Henderson <rth@cygnus.com>
* typeck.c (build_ptrmemfunc1): Clean up ptr->int cast warnings.
-Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
+Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
* call.c (add_builtin_candidate): Add missing TREE_TYPE.
(compare_ics): Likewise.
@@ -5381,8 +10387,8 @@ Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
Mon Sep 1 13:19:04 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (joust): Warn about choosing one conversion op over
- another because of 'this' argument when the other return type is
- better.
+ another because of 'this' argument when the other return type is
+ better.
(source_type): New fn.
* call.c (build_new_op): Strip leading REF_BIND from first operand
@@ -5395,7 +10401,7 @@ Thu Aug 28 09:45:23 1997 Jason Merrill <jason@yorick.cygnus.com>
* call.c (null_ptr_cst_p): Remove support for (void*)0.
-Wed Aug 27 02:03:34 1997 Jeffrey A Law (law@cygnus.com)
+Wed Aug 27 02:03:34 1997 Jeffrey A Law <law@cygnus.com>
* typeck.c (expand_target_expr): Make definition match declaration.
@@ -5415,7 +10421,7 @@ Sat Aug 23 18:02:59 1997 Mark Mitchell <mmitchell@usa.net>
* error.c (type_as_string): Put const/volatile on template type
parameters where appropriate.
-Sat Aug 23 17:47:22 1997 Jeffrey A Law (law@cygnus.com)
+Sat Aug 23 17:47:22 1997 Jeffrey A Law <law@cygnus.com>
* call.c (strictly_better): Make arguments unsigned ints.
@@ -5423,7 +10429,7 @@ Thu Aug 21 18:48:44 1997 Jason Merrill <jason@yorick.cygnus.com>
* lex.c (real_yylex): Refer to __complex instead of complex.
-Thu Aug 21 22:25:46 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
+Thu Aug 21 22:25:46 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
* lex.c (real_yylex): Don't use getc directly.
@@ -5435,10 +10441,10 @@ Wed Aug 20 03:13:36 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
* parse.y, pt.c: Include "except.h".
* call.c, class.c, class.h, cp-tree.h, cvt.c, decl.c, decl2.c,
- error.c, except.c, expr.c, friend.c, g++spec.c, init.c, input.c,
- lex.c, lex.h, method.c, parse.y, pt.c, repo.c, rtti.c, search.c,
- sig.c, spew.c, tree.c, typeck.c, typeck2.c, xref.c: Finish
- prototyping.
+ error.c, except.c, expr.c, friend.c, g++spec.c, init.c, input.c,
+ lex.c, lex.h, method.c, parse.y, pt.c, repo.c, rtti.c, search.c,
+ sig.c, spew.c, tree.c, typeck.c, typeck2.c, xref.c: Finish
+ prototyping.
Wed Aug 20 01:34:40 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5461,7 +10467,7 @@ Tue Aug 19 02:26:07 1997 Jason Merrill <jason@yorick.cygnus.com>
* repo.c (finish_repo): Don't crash on no args.
* parse.y (named_complex_class_head_sans_basetype): Handle
- explicit global scope.
+ explicit global scope.
* decl2.c (handle_class_head): New fn.
* pt.c (unify): Add CONST_DECL case.
@@ -5494,13 +10500,13 @@ Wed Aug 13 10:46:19 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
Tue Aug 12 20:13:57 1997 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y: Don't clear the inlines from their obstack until they've
+ * parse.y: Don't clear the inlines from their obstack until they've
all been processed.
* decl.c (duplicate_decls): Don't complain about exception
- specification mismatch if flag_exceptions is off.
+ specification mismatch if flag_exceptions is off.
-Mon Aug 11 15:01:56 1997 Marc Lehmann <pcg@goof.com>
+Mon Aug 11 15:01:56 1997 Marc Lehmann <pcg@goof.com>
* Make-lang.in (c++.distclean): Remove g++.c on make distclean.
@@ -5508,10 +10514,10 @@ Sun Aug 10 12:06:09 1997 Paul Eggert <eggert@twinsun.com>
* cp-tree.h: Replace STDIO_PROTO with PROTO in include files.
* cvt.c, error.c, except.c, expr.c, friend.c, init.c, rtti.c:
- Include <stdio.h> before include files that formerly used STDIO_PROTO.
+ Include <stdio.h> before include files that formerly used STDIO_PROTO.
* decl.c, g++spec.c, lex.c, method.c, repo.c:
- Include "config.h" first, as per autoconf manual.
+ Include "config.h" first, as per autoconf manual.
Fri Aug 8 11:47:48 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5523,13 +10529,13 @@ Fri Aug 8 11:47:48 1997 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (lang_decode_option): Handle -fhandle-exceptions.
* lang-options.h: Add -fhandle-exceptions.
- * class.c (build_vtable): vtables are artificial.
+ * class.c (build_vtable): Vtables are artificial.
(prepare_fresh_vtable): Likewise.
Wed Aug 6 11:02:36 1997 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (ocp_convert): After converting to the target type, set
- LOOKUP_NO_CONVERSION.
+ LOOKUP_NO_CONVERSION.
* call.c (joust): Warn about potentially confusing promotion rules
with -Wsign-promo.
@@ -5607,18 +10613,18 @@ Fri Jul 18 17:56:08 1997 Jason Merrill <jason@yorick.cygnus.com>
Thu Jul 17 18:06:30 1997 Jason Merrill <jason@yorick.cygnus.com>
* method.c (build_overload_nested_name): Use static_labelno
- instead of var_labelno.
+ instead of var_labelno.
(build_qualified_name): New fn.
(build_overload_name): Split out from here.
(build_static_name): Use build_qualified_name.
- * decl.c (cp_finish_decl): Statics in extern inline functions
+ * decl.c (cp_finish_decl): Statics in extern inline functions
have comdat linkage.
(start_function): Initialize static_labelno.
Thu Jul 17 11:20:17 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * class.c (finish_struct_methods): add check of warn_ctor_dtor_privacy
- before "all member functions in class [] are private"
+ * class.c (finish_struct_methods): Add check of warn_ctor_dtor_privacy
+ before "all member functions in class [] are private".
Wed Jul 16 23:47:08 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5632,7 +10638,7 @@ Wed Jul 16 12:34:29 1997 Benjamin Kosnik <bkoz@lisa.cygnus.com>
Mon Jul 14 03:23:46 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (get_member_function_from_ptrfunc): Promote index
- before saving it.
+ before saving it.
Sun Jul 13 00:11:52 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5686,7 +10692,7 @@ Wed Jul 9 13:44:12 1997 Jason Merrill <jason@yorick.cygnus.com>
Wed Jul 9 13:04:38 1997 Geoffrey Noer <noer@cygnus.com>
- * decl.c (init_decl_processing): fix Jun 30 patch -- move
+ * decl.c (init_decl_processing): Fix Jun 30 patch -- move
ifndef for Cygwin32 to include SIGSEGV.
Thu Jul 3 01:44:05 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5697,17 +10703,17 @@ Thu Jul 3 01:44:05 1997 Jason Merrill <jason@yorick.cygnus.com>
* rtti.c (build_dynamic_cast): Call complete_type on the types.
* decl.c (grokfndecl): If the function we chose doesn't actually
- match, die.
+ match, die.
* decl2.c (grokclassfn): Don't specify 'const int' for the
- artificial destructor parm.
+ artificial destructor parm.
- * pt.c (type_unification): If we are called recursively, nothing
+ * pt.c (type_unification): If we are called recursively, nothing
decays.
Mon Jun 30 17:53:21 1997 Geoffrey Noer <noer@cygnus.com>
- * decl.c (init_decl_processing): Stop trying to catch signals
+ * decl.c (init_decl_processing): Stop trying to catch signals
other than SIGABRT since the Cygwin32 library doesn't support
them correctly yet. This fixes a situation in which g++ causes
a hang on SIGSEGVs and other such signals in our Win32-hosted
@@ -5719,11 +10725,11 @@ Mon Jun 30 14:50:01 1997 Jason Merrill <jason@yorick.cygnus.com>
Fri Jun 27 15:18:49 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (store_init_value): Always return the value if our
+ * typeck2.c (store_init_value): Always return the value if our
type needs constructing.
* method.c (hack_identifier): Convert class statics from
- reference, too.
+ reference, too.
Thu Jun 26 11:44:46 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5741,7 +10747,7 @@ Thu Jun 19 12:28:43 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
Tue Jun 17 18:35:57 1997 Mike Stump <mrs@cygnus.com>
* except.c (expand_builtin_throw): Add support
- -fno-sjlj-exceptions -fPIC exception handling on the SPARC.
+ -fno-sjlj-exceptions -fPIC exception handling on the SPARC.
Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5749,7 +10755,7 @@ Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (TI_SPEC_INFO): New macro.
(CLASSTYPE_TI_SPEC_INFO): New macro.
- * pt.c (push_template_decl): Correctly determine # of template parms
+ * pt.c (push_template_decl): Correctly determine # of template parms
for partial specs.
* call.c (compare_ics): Really fix 'this' conversions.
@@ -5758,20 +10764,20 @@ Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
non-template fn.
* pt.c (push_template_decl): Complain about mismatch in # of
- template parms between a class template and a member template.
+ template parms between a class template and a member template.
Sun Jun 15 02:38:20 1997 Jason Merrill <jason@yorick.cygnus.com>
* method.c (synthesize_method): You can't call
- function_cannot_inline_p after finish_function.
+ function_cannot_inline_p after finish_function.
* decl.c (finish_function): Turn on flag_inline_functions and turn
- off DECL_INLINE before handing a synthesized method to the
- backend.
+ off DECL_INLINE before handing a synthesized method to the
+ backend.
Thu Jun 12 17:35:28 1997 Jason Merrill <jason@yorick.cygnus.com>
* method.c (synthesize_method): Remove July 30 change to never set
- DECL_INLINE if at_eof.
+ DECL_INLINE if at_eof.
Thu Jun 12 15:25:08 1997 Mike Stump <mrs@cygnus.com>
@@ -5811,22 +10817,22 @@ Tue Jun 10 00:22:09 1997 Jason Merrill <jason@yorick.cygnus.com>
Mon Jun 9 14:25:30 1997 Mike Stump <mrs@cygnus.com>
* Makefile.in, Make-lang.in: Protect C-ls with a comment
- character, idea from Paul Eggert <eggert@twinsun.com>.
+ character, idea from Paul Eggert <eggert@twinsun.com>.
Mon Jun 9 01:52:03 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (c_expand_return): Be more persistent in looking for
- returned temps.
+ returned temps.
* cvt.c (build_up_reference): Use NOP_EXPR for switching from
- pointer to reference.
+ pointer to reference.
* class.c (build_vbase_path): Don't do anything if PATH has no steps.
Sun Jun 8 03:07:05 1997 Jason Merrill <jason@yorick.cygnus.com>
* init.c (build_member_call, build_offset_ref):
- Use do_scoped_id instead of do_identifier.
+ Use do_scoped_id instead of do_identifier.
* cvt.c (convert): Remove bogosity.
@@ -5840,13 +10846,13 @@ Fri Jun 6 17:36:39 1997 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (build_up_reference): Call get_binfo to get access control.
* decl2.c (import_export_decl): If we don't support weaks, leave
- statics undefined.
+ statics undefined.
Fri Jun 6 15:55:49 1997 Mike Stump <mrs@cygnus.com>
* except.c (expand_builtin_throw): Add support for machines that
- cannot access globals after throw's epilogue when
- -fno-sjlj-exceptions is used.
+ cannot access globals after throw's epilogue when
+ -fno-sjlj-exceptions is used.
Thu Jun 5 16:28:43 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -5863,14 +10869,14 @@ Thu Jun 5 16:28:43 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Jun 3 18:08:23 1997 Jason Merrill <jason@yorick.cygnus.com>
* search.c (push_class_decls): A name which ambiguously refers to
- several instantiations of the same template just refers to the
- template.
+ several instantiations of the same template just refers to the
+ template.
Tue Jun 3 12:30:40 1997 Benjamin Kosnik <bkoz@cirdan.cygnus.com>
- * decl.c (build_enumerator): fix problem with unsigned long
+ * decl.c (build_enumerator): Fix problem with unsigned long
enumerated values being smashed to ints, causing overflow
- when computing next enumerated value. (for enum values around
+ when computing next enumerated value (for enum values around
MAX_VAL).
Mon Jun 2 17:40:56 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -6003,7 +11009,7 @@ Wed May 14 19:08:28 1997 Mike Stump <mrs@cygnus.com>
(struct cp_function): Add last_parm_cleanup_insn.
(push_cp_function_context): Likewise.
(pop_cp_function_context): Likewise.
-
+
Tue May 13 15:51:20 1997 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst_copy): Handle BIT_NOT_EXPR.
@@ -6056,13 +11062,13 @@ Wed Apr 23 18:06:50 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (c_expand_return): Don't complain about returning void
to void in an artificial function.
- * method.c (make_thunk): Change settings of READONLY/VOLATILE,
+ * method.c (make_thunk): Change settings of READONLY/VOLATILE,
don't set DECL_RESULT, set DECL_ARTIFICIAL.
- (emit_thunk, generic code): Also set up DECL_LANG_SPECIFIC.
+ (emit_thunk, generic code): Also set up DECL_LANG_SPECIFIC.
Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
- * init.c (init_decl_processing): Add supoprt for setjmp/longjmp based
+ * init.c (init_decl_processing): Add support for setjmp/longjmp based
exception handling.
* except.c (init_exception_processing): Likewise.
(expand_end_catch_block): Likewise.
@@ -6080,7 +11086,7 @@ Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
(store_parm_decls): Likewise.
(cplus_expand_expr_stmt): Likewise.
* decl2.c (finish_file): Likewise.
-
+
* Make-lang.in (exception.o): Ok to compile with -O now.
* decl.c (maybe_build_cleanup_1): We no longer have to unsave, as
@@ -6088,7 +11094,7 @@ Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
* decl2.c (lang_f_options): Remove support for short temps.
* lang-options.h: Likewise.
-
+
Wed Apr 23 04:12:06 1997 Jason Merrill <jason@yorick.cygnus.com>
* tree.c (varargs_function_p): New fn.
@@ -6154,7 +11160,7 @@ Wed Apr 2 12:51:36 1997 Mike Stump <mrs@cygnus.com>
* exception.cc (__default_unexpected): Call terminate by default,
so that if the user overrides terminate, the correct function will
be called.
-
+
Wed Mar 19 14:14:45 1997 Mike Stump <mrs@cygnus.com>
* parse.y (left_curly): Avoid trying to use any fields of
@@ -6382,7 +11388,7 @@ Tue Feb 11 13:50:48 1997 Mike Stump <mrs@cygnus.com>
avoid lossing on systems that require one (ones that define malloc
in xm.h).
-Mon Feb 10 22:51:13 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
+Mon Feb 10 22:51:13 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
* decl2.c (max_tinst_depth): New variable.
(lang_decode_option): Parse "-ftemplate-depth-NN" command line
@@ -6551,7 +11557,7 @@ Thu Jan 23 16:39:06 1997 Jason Merrill <jason@yorick.cygnus.com>
Tue Jan 21 18:32:04 1997 Mike Stump <mrs@cygnus.com>
- * cvt.c (cp_convert): Pedwarn enum to pointer conversions.
+ * cvt.c (cp_convert): pedwarn enum to pointer conversions.
Mon Jan 20 17:59:51 1997 Jason Merrill <jason@yorick.cygnus.com>
@@ -6675,7 +11681,7 @@ Fri Dec 27 10:31:40 1996 Paul Eggert <eggert@twinsun.com>
* Make-lang.in (g++spec.o): Don't use $< with an explicit target;
this isn't portable to some versions of `make' (e.g. Solaris 2.5.1).
-Tue Dec 24 10:24:03 1996 Jeffrey A Law (law@cygnus.com)
+Tue Dec 24 10:24:03 1996 Jeffrey A Law <law@cygnus.com>
* decl.c (grokvardecl): Avoid ANSI style initialization.
@@ -6720,7 +11726,7 @@ Sat Dec 7 17:20:22 1996 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (TYPE_MAIN_DECL): Use TYPE_STUB_DECL.
* *.c: Use TYPE_MAIN_DECL instead of TYPE_NAME where appropriate.
-
+
Fri Dec 6 14:40:09 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): When giving an anonymous struct a name,
@@ -6866,7 +11872,7 @@ Wed Nov 13 12:32:07 1996 Jason Merrill <jason@yorick.cygnus.com>
Wed Nov 13 11:51:20 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* g++.c (main): Also set PEXECUTE_SEARCH, to make the invocation
- of GCC be path-relative.
+ of GCC be path-relative.
Wed Nov 13 11:27:16 1996 Michael Meissner <meissner@tiktok.cygnus.com>
@@ -6881,7 +11887,7 @@ Wed Nov 13 07:53:38 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
Wed Nov 13 02:00:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_default_init): Avoid calling constructors to
+ * init.c (expand_default_init): Avoid calling constructors to
initialize reference temps.
* cvt.c (convert_to_reference): Fix.
@@ -6974,7 +11980,7 @@ Fri Nov 8 17:38:44 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (finish_file): Don't emit debug info.
* decl.c (pushdecl): Lose obsolete code.
(grokdeclarator): Still do the long long thing after complaining.
- * search.c (note_debug_info_needed): Don't do anything if we're in a
+ * search.c (note_debug_info_needed): Don't do anything if we're in a
template.
* method.c (synthesize_method): For non-local classes,
push_to_top_level first.
@@ -7038,7 +12044,7 @@ Thu Oct 31 17:08:49 1996 Jason Merrill <jason@yorick.cygnus.com>
similar code in build_up_ref.
* cvt.c (build_up_reference): Drastically simplify.
-Mon Oct 28 12:45:05 1996 Jeffrey A Law (law@cygnus.com)
+Mon Oct 28 12:45:05 1996 Jeffrey A Law <law@cygnus.com>
* typeck.c (signed_or_unsigned_type): If the given type already
as the correct signedness, then just return it.
@@ -7163,7 +12169,7 @@ Fri Sep 27 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (build_expr_from_tree): Use it.
* cp-tree.h: Declare it.
- * decl.c (start_decl): variable-sized arrays cannot be initialized.
+ * decl.c (start_decl): Variable-sized arrays cannot be initialized.
* error.c (dump_type_suffix): Handle variable arrays.
Fri Sep 27 13:14:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
@@ -7187,7 +12193,7 @@ Thu Sep 26 10:59:00 1996 Jason Merrill <jason@yorick.cygnus.com>
calling them.
(get_tinfo_fn_dynamic): Extracted from build_typeid.
* tinfo2.cc (__dynamic_cast): Adjust.
-
+
* rtti.c (build_typeid): Use resolves_to_fixed_type_p.
(build_x_typeid): Likewise.
@@ -7266,7 +12272,7 @@ Sun Sep 22 05:31:22 1996 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (store_init_value): Oops.
- * new.{h,cc}, exception.{h,cc}, typeinfo.h, tinfo{2.cc,.cc,.h}:
+ * new.{h,cc}, exception.{h,cc}, typeinfo.h, tinfo{2.cc,.cc,.h}:
New files for C++ lang-support library.
* Make-lang.in (CXX_EXTRA_HEADERS): Define.
(CXX_LIB2FUNCS): Define.
@@ -7391,7 +12397,7 @@ Wed Sep 4 17:16:09 1996 Bob Manson <manson@charmed.cygnus.com>
* init.c (perform_member_init): Use add_partial_entry () instead
of directly manipulating lists.
- (emit_base_init): Ditto.
+ (emit_base_init): Likewise.
Wed Sep 4 12:14:36 1996 Mike Stump <mrs@cygnus.com>
@@ -7482,7 +12488,7 @@ Fri Aug 30 10:01:55 1996 Mike Stump <mrs@cygnus.com>
to start_function.
* parse.y (datadef): Remove non-winning optimization.
(decl): Likewise.
- (fndef): Remove ambiguous error productions uncovered by grammer
+ (fndef): Remove ambiguous error productions uncovered by grammar
fixing.
(constructor_declarator): Add exception_specification_opt here.
(component_constructor_declarator): Likewise.
@@ -7512,7 +12518,7 @@ Wed Aug 28 01:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* call.c (joust): Extend the previous change to all comparisons.
- * decl2.c, method.c, lex.c: Use MAKE_DECL_ONE_ONLY and
+ * decl2.c, method.c, lex.c: Use MAKE_DECL_ONE_ONLY and
NO_LINKAGE_HEURISTICS.
* decl2.c (finish_file): Emit any statics that weren't already.
@@ -7547,7 +12553,7 @@ Tue Aug 27 13:12:21 1996 Jason Merrill <jason@yorick.cygnus.com>
Tue Aug 27 13:14:58 1996 Bob Manson <manson@charmed.cygnus.com>
* rtti.c (build_dynamic_cast): Don't try to dereference exprtype
- too early. Make sure we explode if exprtype turns out to be a
+ too early. Make sure we explode if exprtype turns out to be a
NULL_TREE when it shouldn't be.
Tue Aug 27 10:56:21 1996 Mike Stump <mrs@cygnus.com>
@@ -7561,7 +12567,7 @@ Tue Aug 27 10:56:21 1996 Mike Stump <mrs@cygnus.com>
* lex.c (cons_up_default_function): Likewise.
* parse.y: Likewise.
* pt.c (tsubst): Likewise.
-
+
Mon Aug 26 17:40:03 1996 Mike Stump <mrs@cygnus.com>
* decl2.c (groktypefield): Remove unused code.
@@ -7573,11 +12579,11 @@ Mon Aug 26 17:00:33 1996 Mike Stump <mrs@cygnus.com>
Change type_quals into cv_qualifiers. Change nonempty_type_quals into
nonempty_cv_qualifiers.
* hash.h: Rebuild.
-
+
* lex.c (make_pointer_declarator): Change type_quals into
cv_qualifiers.
(make_reference_declarator): Likewise.
-
+
Thu Aug 22 01:09:22 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (start_function): Only check interface_* for templates
@@ -7594,7 +12600,7 @@ Wed Aug 21 00:13:15 1996 Jason Merrill <jason@yorick.cygnus.com>
* call.c (build_new_method_call): Add missing args to cp_error.
- * tree.c (error_type): Dont print reference-to-array.
+ * tree.c (error_type): Don't print reference-to-array.
* typeck.c (convert_for_assignment): Don't say contravariance for
removing const.
@@ -7810,7 +12816,7 @@ Sun Aug 4 15:29:11 1996 Jason Merrill <jason@yorick.cygnus.com>
(build_conditional_expr): If both operands are TARGET_EXPRs, wrap
the COND_EXPR in a TARGET_EXPR so they use the same slot.
- * cvt.c (build_up_reference): Propagate INDIRECT_BIND to
+ * cvt.c (build_up_reference): Propagate INDIRECT_BIND to
recursive calls.
* typeck.c (complete_type): Propagate
TYPE_NEEDS_{CONSTRUCTING,DESTRUCTOR}.
@@ -7907,7 +12913,7 @@ Thu Aug 1 15:18:00 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
Thu Aug 1 11:53:51 1996 Bob Manson <manson@charmed.cygnus.com>
- * pt.c (instantiate_class_template): Call complete_type. Also, if
+ * pt.c (instantiate_class_template): Call complete_type. Also, if
we're at the end of the file and we just instantiated a template
class with a vtable, call finish_prevtable_vardecl.
@@ -8063,12 +13069,12 @@ Tue Jul 23 12:46:30 1996 Jason Merrill <jason@yorick.cygnus.com>
* cvt.c (implicit_conversion): Do const-ref case first.
(add_conv_candidate, build_object_call, op_error): New fns.
(ptr_complete_ob, TYPE_PTROB_P): void is not an object type.
- ({add,build}_builtin_candidate{,s}, print_z_candidates): Display
+ ({add,build}_builtin_candidate{,s}, print_z_candidates): Display
builtin candidates.
(build_new_op): Handle CALL_EXPR. Don't try to decay void.
- Fall back on preincrement handling. Use op_error.
+ Fall back on preincrement handling. Use op_error.
Handle warn_synth.
- (convert_like): Pass INDIRECT_BIND. Don't try to do anything with
+ (convert_like): Pass INDIRECT_BIND. Don't try to do anything with
an error_mark_node.
(build_over_call): Handle PROMOTE_PROTOTYPES and ellipsis promotions
properly.
@@ -8087,7 +13093,7 @@ Mon Jul 22 12:18:54 1996 Jason Merrill <jason@yorick.cygnus.com>
* g++.c (main): Don't link with -lg++.
NEW_OVER changes:
- * cvt.c (convert_to_reference): Don't use convert_from_refeence on
+ * cvt.c (convert_to_reference): Don't use convert_from_reference on
result of build_type_conversion.
(cp_convert): Only call build_method_call for ctors if
build_type_conversion failed.
@@ -8095,7 +13101,7 @@ Mon Jul 22 12:18:54 1996 Jason Merrill <jason@yorick.cygnus.com>
(TYPE_PTR{,OB,MEM}_P): New macros.
({add,build}_builtin_candidate{,s}): New functions.
(print_z_candidates): Handle builtins.
- (build_user_type_conversion_1): Don't use conversion fns for
+ (build_user_type_conversion_1): Don't use conversion fns for
converting to a base type.
(build_user_type_conversion_1): Set ICS_USER_FLAG on AMBIG_CONVs.
(build_user_type_conversion): Use convert_from_reference.
@@ -8417,7 +13423,7 @@ Fri Jun 7 10:37:33 1996 Mike Stump <mrs@cygnus.com>
lifetime of the temporary, don't try it again.
* typeck.c (c_expand_return): Don't try and convert the return
value twice when we want a reference, once is enough.
-
+
Tue Jun 4 15:41:45 1996 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst_expr, case DECL_STMT): Don't pass
@@ -8494,8 +13500,8 @@ Thu May 23 12:13:08 1996 Bob Manson <manson@charmed.cygnus.com>
and cant_synth_asn_ref.
(finish_base_struct): Remove the code that tries to conditionalize
synthesis of copy constructors & assignment operators based on
- access permissions. Instead, let it fail when it tries to
- synthesize the copy constructor. This will give meaningful error
+ access permissions. Instead, let it fail when it tries to
+ synthesize the copy constructor. This will give meaningful error
messages instead of silently generating code to perform a bitcopy.
Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com>
@@ -8514,7 +13520,7 @@ Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com>
(init_decl_processing): Use NULL instead of NULL_TREE to initialize
named_label_uses.
(finish_function): Likewise.
-
+
(start_decl): Complain about defining a static data member
in a different type from which it was declared.
@@ -8794,11 +13800,11 @@ Wed Apr 24 15:41:15 1996 Bob Manson <manson@charmed.cygnus.com>
definition of flagged_type_tree is found before it is used.
* lex.c: Likewise.
* parse.y: Added the ftype member to the type union, and changed a
- number of rules to use it instead of ttype. Added calls to
+ number of rules to use it instead of ttype. Added calls to
check_for_new_type() as appropriate.
* typeck2.c (check_for_new_type): New function for checking
if a newly defined type appears in the specified tree.
- * cp-tree.h: Add new type flagged_type_tree. Add a prototype
+ * cp-tree.h: Add new type flagged_type_tree. Add a prototype
for check_for_new_type().
Wed Apr 24 00:36:21 1996 Jason Merrill <jason@yorick.cygnus.com>
@@ -8923,7 +13929,7 @@ Sun Apr 14 11:34:39 1996 Jason Merrill <jason@yorick.cygnus.com>
Fri Apr 12 09:08:27 1996 Bob Manson <manson@charmed.cygnus.com>
* call.c (build_method_call): Remember the original basetype we
- were called with. Give an error message instead of trying
+ were called with. Give an error message instead of trying
(incorrectly) to call a non-static member function through a
non-inherited class.
@@ -9052,7 +14058,7 @@ Sat Apr 6 13:56:27 1996 Jason Merrill <jason@yorick.cygnus.com>
Fri Apr 5 17:02:09 1996 Jason Merrill <jason@yorick.cygnus.com>
RTTI rewrite to initialize nodes as needed, not require that
- users #include <typeinfo>, complete functionality and reduce wasted
+ users #include <typeinfo>, complete functionality and reduce wasted
space.
* rtti.c (init_rtti_processing): New fn.
(build_typeid): The vtable entry is now a function.
@@ -9152,11 +14158,11 @@ Sat Mar 30 12:14:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
Fri Mar 29 15:51:36 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (base_info, finish_base_struct): Replace
+ * class.c (base_info, finish_base_struct): Replace
needs_virtual_dtor with base_has_virtual.
(finish_struct_1): Remove the old code that tried to make default
- destructors virtual. Use base_has_virtual when checking if we need
+ destructors virtual. Use base_has_virtual when checking if we need
to add a vtable entry for the rtti code.
Fri Mar 29 14:02:36 1996 Jason Merrill <jason@yorick.cygnus.com>
@@ -9269,7 +14275,7 @@ Fri Mar 22 17:57:55 1996 Mike Stump <mrs@cygnus.com>
Fri Mar 22 13:48:29 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Call bad_specifiers for typedefs. Also
- give an error if initialized. Pedwarn about nested type with the
+ give an error if initialized. pedwarn about nested type with the
same name as its enclosing class.
* pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT.
@@ -9500,7 +14506,7 @@ Wed Mar 13 14:03:34 1996 Jason Merrill <jason@yorick.cygnus.com>
Tue Mar 12 14:36:02 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_new): Pedwarn about init and array new.
+ * init.c (build_new): pedwarn about init and array new.
(expand_vec_init): Handle lists, use convert_for_initialization.
* typeck.c (convert_for_initialization): Pass LOOKUP_NO_CONVERSION
@@ -9622,7 +14628,7 @@ Mon Mar 4 20:03:33 1996 Jason Merrill <jason@yorick.cygnus.com>
* error.c (dump_expr): Support LOOKUP_EXPR and actually do
something for CAST_EXPR.
-
+
Mon Feb 19 14:49:18 1996 Rusty Russell <rusty@adelaide.maptek.com.au>
* cvt.c (cp_convert): Warn about implicit conversion of the
@@ -9892,7 +14898,7 @@ Thu Feb 22 15:30:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
(repo_compile_flags, repo_template_declared,
repo_template_defined, repo_class_defined, repo_inline_used,
repo_vtable_used, repo_tinfo_used): #if 0 unused fns.
- (repo_get_id, repo_vtable_used): Declare as static.
+ (repo_get_id, repo_vtable_used): Declare as static.
* cp-tree.h (mark_{decl,class}_instantiated, finish_repo): Add
prototypes.
@@ -9921,7 +14927,7 @@ Thu Feb 22 13:24:15 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
(init_lex): Don't set it.
(init_parse): Add decl before use.
(reduce_count): Only define #ifdef GATHER_STATISTICS && REDUCE_LENGTH.
- (current_unit_{name, language}): Delete unused vars.
+ (current_unit_{name, language}): Delete unused vars.
(check_newline): Don't bother setting them, just accept the #pragma.
* cp-tree.h (init_repo, peek_yylex): Add prototypes.
(current_unit_{name, language}): Delete decls.
@@ -10045,7 +15051,7 @@ Thu Feb 22 00:54:22 1996 Jason Merrill <jason@yorick.cygnus.com>
Wed Feb 21 16:57:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * init.c (expand_recursive_init{,_1}): Delete decls.
+ * init.c (expand_recursive_init{,_1}): Delete decls.
(sort_member_init): Delete unused var INIT.
(emit_base_init): Delete unused var X.
(build_offset_ref): Delete unused var CNAME.
@@ -10081,7 +15087,7 @@ Wed Feb 21 16:57:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* class.c (n_*): Wrap with #ifdef GATHER_STATISTICS.
- * class.c (get_vtable_entry): Diable unused function.
+ * class.c (get_vtable_entry): Disable unused function.
(doing_hard_virtuals): Delete unused static global var.
(finish_struct_1): Don't init DOING_HARD_VIRTUALS.
(prepare_fresh_vtable): Delete unused vars PATH and RESULT.
@@ -10112,7 +15118,7 @@ Wed Feb 21 16:57:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
(grokparms): Delete unused var SAW_VOID.
(start_function): Delete unused var OLDDECL.
(cplus_expand_expr_stmt): Delete unused var
- REMOVE_IMPLICIT_IMMEDIATELY.
+ REMOVE_IMPLICIT_IMMEDIATELY.
* cp-tree.h (pushdecl_nonclass_level): Fix prototype.
@@ -10127,7 +15133,7 @@ Wed Feb 21 00:06:17 1996 Jason Merrill <jason@yorick.cygnus.com>
(tsubst_expr): Set lineno from TREE_COMPLEXITY in stmt nodes.
* parse.y: Use do_pushlevel and do_poplevel.
* cp-tree.h: Declare do_poplevel.
-
+
* cp-tree.h: Declare at_eof.
* decl.c (cp_finish_decl): Pass it to rest_of_decl_compilation.
* decl2.c (import_export_decl): Renamed from import_export_inline.
@@ -10744,7 +15750,7 @@ Tue Dec 19 22:36:56 1995 Jason Merrill <jason@yorick.cygnus.com>
Mon Dec 18 15:51:33 1995 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h, decl2.c (flag_weak): New flag to control the use of
- weak symbols.
+ weak symbols.
* lang-options.h: Add -f{no-,}weak.
* decl.c (init_decl_processing): If the target does not support weak
symbols, don't use them.
@@ -10771,7 +15777,7 @@ Thu Dec 14 14:16:26 1995 Mike Stump <mrs@cygnus.com>
copy constructors well. The compiler would do bitwise copying,
instead of ctor calling in some cases.
-Wed Dec 13 17:05:54 PST 1995 Paul Eggert <eggert@twinsun.com>
+Wed Dec 13 17:05:54 1995 Paul Eggert <eggert@twinsun.com>
* g++.c (my_strerror): Return "cannot access" if errno is 0.
(pfatal_with_name, perror_exec): Don't assume that
@@ -10782,7 +15788,7 @@ Wed Dec 13 17:05:54 PST 1995 Paul Eggert <eggert@twinsun.com>
Wed Dec 13 16:22:38 1995 Jason Merrill <jason@yorick.cygnus.com>
Lose CLASSTYPE_METHODS/DECL_NEXT_METHOD chain; make
- TYPE_METHODS/TREE_CHAIN mean what they used to.
+ TYPE_METHODS/TREE_CHAIN mean what they used to.
* decl2.c (constructor_name_full): Refer to CLASSTYPE_METHOD_VEC
instead of TYPE_METHODS.
* decl.c (duplicate_decls): Lose references to DECL_NEXT_METHOD.
@@ -10823,7 +15829,7 @@ Mon Dec 11 18:56:14 1995 Mike Stump <mrs@cygnus.com>
* decl2.c (build_cleanup): New routine, taken from finish_file.
(finish_file): Use build_cleanup instead, and don't put function
local statics in global dtor list.
-
+
Wed Dec 6 14:34:29 1995 Mike Stump <mrs@cygnus.com>
* except.c (expand_throw): Ensure that we have cleanups, if we try
@@ -10862,7 +15868,7 @@ Wed Dec 6 11:48:21 1995 Mike Stump <mrs@cygnus.com>
* class.c (build_vfn_ref): Remove building_cleanup logic, as we now
use UNSAVE_EXPRs.
- typeck.c (get_member_function_from_ptrfunc): Remove remnants of
+ * typeck.c (get_member_function_from_ptrfunc): Remove remnants of
building_cleanup logic, as we now use UNSAVE_EXPRs.
* cp-tree.h (unsave_expr): Declare it.
* decl.c (building_cleanup): Remove.
@@ -10956,11 +15962,11 @@ Fri Nov 10 09:18:09 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
Mon Nov 6 18:36:13 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
* call.c (build_method_call): Make sure instance has a
- TYPE_LANG_SPECIFIC node before we dive into it.
+ TYPE_LANG_SPECIFIC node before we dive into it.
Sat Nov 4 20:01:52 1995 Jason Molenda <crash@phydeaux.cygnus.com>
- * method.c (make_thunk): use TREE_SET_CODE to set thunk's tree code.
+ * method.c (make_thunk): Use TREE_SET_CODE to set thunk's tree code.
Thu Nov 2 17:56:57 1995 Mike Stump <mrs@cygnus.com>
@@ -10995,7 +16001,7 @@ Tue Oct 31 11:56:55 1995 Jason Merrill <jason@yorick.cygnus.com>
(emit_thunk): Don't call assemble_external.
(make_thunk): Create thunk as a FUNCTION_DECL so that it
gets the right mode and ENCODE_SECTION_INFO works.
-
+
* parse.y: Use mark_used. Pass operator names to do_identifier.
* lex.c (do_identifier): Handle operator names.
diff --git a/contrib/gcc/cp/Make-lang.in b/contrib/gcc/cp/Make-lang.in
index be02cf1..d5d4e4d 100644
--- a/contrib/gcc/cp/Make-lang.in
+++ b/contrib/gcc/cp/Make-lang.in
@@ -1,5 +1,5 @@
# Top level makefile fragment for GNU C++.
-# Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -75,43 +75,38 @@ C++ c++: cc1plus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: C++ c++
-g++.c: $(srcdir)/gcc.c
- -rm -f $@
- $(LN_S) $(srcdir)/gcc.c $@
-
g++spec.o: $(srcdir)/cp/g++spec.c
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/cp/g++spec.c
-# N.B.: This is a copy of the gcc.o rule, with -DLANG_SPECIFIC_DRIVER added.
-# It'd be nice if we could find an easier way to do this---rather than have
-# to track changes to the toplevel gcc Makefile as well.
-# We depend on g++.c last, to make it obvious where it came from.
-g++.o: $(CONFIG_H) multilib.h config.status $(lang_specs_files) g++.c \
- system.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(DRIVER_DEFINES) \
- -DLANG_SPECIFIC_DRIVER \
- -c g++.c
+$(INTL_TARGETS): $(srcdir)/cp/parse.c
+$(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y
+ @cp_srcdir=`sed -n 's/^srcdir[ ]*=[ ]*//p' cp/Makefile` && \
+ echo "cd cp && $(MAKE) $$cp_srcdir/parse.c" && \
+ cd cp && \
+ $(MAKE) $(SUBDIR_FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) \
+ $$cp_srcdir/parse.c
# Create the compiler driver for g++.
-g++$(exeext): g++.o g++spec.o version.o choose-temp.o pexecute.o prefix.o mkstemp.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ g++.o g++spec.o prefix.o \
- version.o choose-temp.o pexecute.o mkstemp.o $(EXTRA_GCC_OBJS) $(LIBS)
+GXX_OBJS = gcc.o g++spec.o intl.o prefix.o version.o
+g++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBS)
# Create a version of the g++ driver which calls the cross-compiler.
g++-cross$(exeext): g++$(exeext)
-rm -f g++-cross$(exeext)
cp g++$(exeext) g++-cross$(exeext)
-cxxmain.o: cplus-dem.c demangle.h
+cxxmain.o: $(srcdir)/../libiberty/cplus-dem.c $(DEMANGLE_H)
rm -f cxxmain.c
- $(LN_S) $(srcdir)/cplus-dem.c cxxmain.c
+ $(LN_S) $(srcdir)/../libiberty/cplus-dem.c cxxmain.c
$(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DVERSION=\"$(version)\" cxxmain.c
-$(DEMANGLER_PROG): cxxmain.o underscore.o getopt.o getopt1.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LIBS) -o $@ \
- cxxmain.o underscore.o getopt.o getopt1.o
+# Apparently OpenVM needs the -o to be at the beginning of the link line.
+$(DEMANGLER_PROG): cxxmain.o underscore.o $(LIBDEPS)
+ $(CC) -o $@ $(ALL_CFLAGS) $(LDFLAGS) \
+ cxxmain.o underscore.o $(LIBS)
CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/except.c $(srcdir)/cp/input.c $(srcdir)/cp/pt.c \
@@ -125,7 +120,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
- $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
+ $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def hash.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext)
#
# Build hooks:
@@ -140,40 +135,40 @@ c++.dvi:
# C++ language-support library pieces for libgcc.
tinfo.o: cc1plus$(exeext) $(srcdir)/cp/tinfo.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/tinfo.cc
tinfo2.o: cc1plus$(exeext) $(srcdir)/cp/tinfo2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/tinfo2.cc
exception.o: cc1plus$(exeext) $(srcdir)/cp/exception.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c -fexceptions $(srcdir)/cp/exception.cc
new.o: cc1plus$(exeext) $(srcdir)/cp/new.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new.cc
opnew.o: cc1plus$(exeext) $(srcdir)/cp/new1.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new1.cc -DL_op_new -o opnew.o
opnewnt.o: cc1plus$(exeext) $(srcdir)/cp/new1.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new1.cc -DL_op_newnt -o opnewnt.o
opvnew.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new2.cc -DL_op_vnew -o opvnew.o
opvnewnt.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new2.cc -DL_op_vnewnt -o opvnewnt.o
opdel.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new2.cc -DL_op_delete -o opdel.o
opdelnt.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new2.cc -DL_op_delnt -o opdelnt.o
opvdel.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new2.cc -DL_op_vdel -o opvdel.o
opvdelnt.o: cc1plus$(exeext) $(srcdir)/cp/new2.cc
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(CXXFLAGS) $(INCLUDES) \
-c $(srcdir)/cp/new2.cc -DL_op_vdelnt -o opvdelnt.o
# We want to update cplib2.txt if any of the source files change...
@@ -187,8 +182,11 @@ cplib2.txt: $(CXX_LIB2SRCS) $(CXX_EXTRA_HEADERS) cplib2.ready
mv -f cplib2.new cplib2.txt
# Or if it would be different.
-cplib2.ready: $(GCC_PASSES) $(LANGUAGES) $(LIBGCC2_DEPS) stmp-int-hdrs
- @if [ -r cplib2.txt ]; then \
+# Don't try to do write if `.' is not writable;
+# in that case, we're installing from someone else's directory.
+# But go ahead and fail if that directory hasn't been properly built.
+cplib2.ready: $(GCC_PASSES) $(LIBGCC2_DEPS) stmp-int-hdrs
+ @if [ -r cplib2.txt -a -w . ]; then \
case " $(LANGUAGES) " in \
*" "[cC]"++ "*) \
echo $(CXX_LIB2FUNCS) > cplib2.new;; \
@@ -246,13 +244,13 @@ c++.install-info:
c++.install-man: $(srcdir)/cp/g++.1
-if [ -f cc1plus$(exeext) ] ; then \
if [ -f g++-cross$(exeext) ] ; then \
- rm -f $(mandir)/$(GXX_CROSS_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(mandir)/$(GXX_CROSS_NAME)$(manext); \
- chmod a-x $(mandir)/$(GXX_CROSS_NAME)$(manext); \
+ rm -f $(man1dir)/$(GXX_CROSS_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(man1dir)/$(GXX_CROSS_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(GXX_CROSS_NAME)$(manext); \
else \
- rm -f $(mandir)/$(GXX_INSTALL_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(mandir)/$(GXX_INSTALL_NAME)$(manext); \
- chmod a-x $(mandir)/$(GXX_INSTALL_NAME)$(manext); \
+ rm -f $(man1dir)/$(GXX_INSTALL_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/cp/g++.1 $(man1dir)/$(GXX_INSTALL_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(GXX_INSTALL_NAME)$(manext); \
fi; \
else true; fi
@@ -263,8 +261,8 @@ c++.uninstall:
-rm -rf $(bindir)/$(GXX_CROSS_NAME)$(exeext)
-rm -rf $(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext)
-rm -rf $(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext)
- -rm -rf $(mandir)/$(GXX_INSTALL_NAME)$(manext)
- -rm -rf $(mandir)/$(GXX_CROSS_NAME)$(manext)
+ -rm -rf $(man1dir)/$(GXX_INSTALL_NAME)$(manext)
+ -rm -rf $(man1dir)/$(GXX_CROSS_NAME)$(manext)
#
# Clean hooks:
# A lot of the ancillary files are deleted by the main makefile.
@@ -277,7 +275,6 @@ c++.clean:
c++.distclean:
-rm -f cp/config.status cp/Makefile
-rm -f cp/parse.output
- -rm -f g++.c
c++.extraclean:
c++.maintainer-clean:
-rm -f cp/parse.c cp/parse.h
diff --git a/contrib/gcc/cp/Makefile.in b/contrib/gcc/cp/Makefile.in
index 8d7098d..1a5b32c 100644
--- a/contrib/gcc/cp/Makefile.in
+++ b/contrib/gcc/cp/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for GNU C++ compiler.
-# Copyright (C) 1987, 88, 90-5, 1998 Free Software Foundation, Inc.
+# Copyright (C) 1987, 88, 90-5, 1998, 1999 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -34,6 +34,10 @@
# Suppress smart makes who think they know how to automake Yacc files
.y.c:
+# It defines the c++ interface name. It should be changed when the
+# c++ interface is changed.
+INTERFACE = 2
+
# Variables that exist for you to override.
# See below for how to change them for certain systems.
@@ -55,7 +59,7 @@ X_CPPFLAGS =
T_CPPFLAGS =
CC = @CC@
-BBISON = `if [ -f ../../bison/bison ] ; then echo ../../bison/bison -L $(srcdir)/../../bison/ ; else echo bison ; fi`
+BISON = `if [ -f ../../bison/bison ] ; then echo ../../bison/bison -L $(srcdir)/../../bison/ ; else echo bison ; fi`
BISONFLAGS =
LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi`
LEXFLAGS =
@@ -101,6 +105,12 @@ VPATH = @srcdir@
# Additional system libraries to link with.
CLIB=
+
+# Top build directory, relative to here.
+top_builddir = ..
+
+# Internationalization library.
+INTLLIBS = @INTLLIBS@
# Change this to a null string if obstacks are installed in the
# system library.
@@ -150,13 +160,14 @@ SUBDIR_MALLOC = `if [ x$(MALLOC) != x ]; then echo ../$(MALLOC); else true; fi`
# How to link with both our special library facilities
# and the system's installed libraries.
-LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) $(CLIB)
+LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) \
+ $(INTLLIBS) $(CLIB)
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
# so that tm.h and config.h will be found in the compilation
# subdirectory rather than in the source directory.
-INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
+INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config -I$(srcdir)/../../include
# Always use -I$(srcdir)/config when compiling.
.c.o:
@@ -184,9 +195,8 @@ OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
compiler: ../cc1plus$(exeext)
-../cc1plus$(exeext): $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
- $(CXX_OBJS) $(OBJS) $(LIBS)
+../cc1plus$(exeext): $(P) $(OBJDEPS) $(CXX_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(CXX_OBJS) $(LIBS)
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
@@ -215,7 +225,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
-CONFLICTS = expect 26 shift/reduce conflicts and 42 reduce/reduce conflicts.
+CONFLICTS = expect 30 shift/reduce conflicts and 42 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y
@echo $(CONFLICTS)
@@ -231,33 +241,35 @@ $(PARSE_C) : $(srcdir)/parse.y
# cp $(PARSE_C) y.tab.c
# touch stamp-parse
-# hash.h really depends on $(srcdir)/gxx.gperf.
-# But this would screw things for people that don't have gperf,
-# if gxx.gpref got touched, say.
-# Thus you have to remove hash.h to force it to be re-made.
-$(srcdir)/hash.h:
- gperf -p -j1 -g -o -t -N is_reserved_word '-k1,4,7,$$' \
- $(srcdir)/gxx.gperf >$(srcdir)/hash.h
+# We used to try to protect people from having to rerun gperf. But,
+# the C front-end already requires this if c-parse.gperf is changed,
+# so we should be consistent.
+$(srcdir)/hash.h: $(srcdir)/gxx.gperf
+ gperf -L C -F ', 0, 0' -p -j1 -g -o -t -N is_reserved_word \
+ '-k1,4,7,$$' $(srcdir)/gxx.gperf >$(srcdir)/hash.h
-spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) \
- $(PARSE_H) $(srcdir)/../flags.h lex.h $(srcdir)/../system.h
+spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) $(PARSE_H) $(srcdir)/../flags.h \
+ lex.h $(srcdir)/../system.h $(srcdir)/../toplev.h
lex.o : lex.c $(CONFIG_H) $(CXX_TREE_H) \
$(PARSE_H) input.c $(srcdir)/../flags.h hash.h lex.h \
$(srcdir)/../c-pragma.h $(srcdir)/../system.h $(srcdir)/../toplev.h \
- $(srcdir)/../output.h
+ $(srcdir)/../output.h $(srcdir)/../mbchar.h
decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h \
- $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h
+ $(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h \
+ $(srcdir)/../hash.h
decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
lex.h decl.h $(EXPR_H) $(srcdir)/../except.h \
$(srcdir)/../output.h $(srcdir)/../except.h $(srcdir)/../system.h \
- $(srcdir)/../toplev.h $(srcdir)/../dwarf2out.h $(srcdir)/../dwarfout.h
+ $(srcdir)/../toplev.h $(srcdir)/../dwarf2out.h $(srcdir)/../dwarfout.h \
+ $(srcdir)/../../include/splay-tree.h $(srcdir)/../varray.h
typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
$(srcdir)/../system.h $(srcdir)/../toplev.h
typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
$(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h
class.o : class.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
- $(srcdir)/../system.h $(srcdir)/../toplev.h
+ $(srcdir)/../system.h $(srcdir)/../toplev.h \
+ $(srcdir)/../../include/splay-tree.h
call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
$(srcdir)/../system.h $(srcdir)/../toplev.h
friend.o : friend.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
@@ -266,9 +278,11 @@ init.o : init.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
$(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h
method.o : method.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
$(srcdir)/../toplev.h
-cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
+cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h decl.h \
+ $(srcdir)/../flags.h $(srcdir)/../toplev.h $(srcdir)/../convert.h
search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
- $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h
+ $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h \
+ $(srcdir)/../varray.h
tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
$(srcdir)/../system.h $(srcdir)/../toplev.h
ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
@@ -308,32 +322,3 @@ TAGS: force
.PHONY: TAGS
force:
-
-g++FAQ.info: $(srcdir)/g++FAQ.texi
- $(MAKEINFO) --no-split -o ./g++FAQ.info $(srcdir)/g++FAQ.texi
-
-# Preprocess the texi file so that the final document will have
-# hyperlinks.
-# It would be nice if texi2html could do something like this itself.
-
-# Assumption 1: the FAQ puts all http: and ftp: links in a @file{...}.
-# Assumption 2: newsgroups are like @file{comp.foo}
-# Assumption 3: email addresses match the regexp shown.
-
-g++FAQ.html: $(srcdir)/g++FAQ.texi
- mkdir work
- sed -e 's?@file{\([fth]*p://[^}]*\)}?@strong{<A HREF="\1">\1</A>}?' \
- -e 's?@file{\(comp\.[-a-z+.]*\)}?<A HREF="news:\1">\1</A>?' \
- -e 's?@file{\(gnu\.[-a-z+.]*\)}?<A HREF="news:\1">\1</A>?' \
- -e 's?\([.+a-zA-Z0-9-]*@@[.a-zA-Z0-9-]*[a-zA-Z0-9]\)?<A HREF="mailto:\1">\1</A>?' \
- $(srcdir)/g++FAQ.texi > work/g++FAQ.texi
- cd work; texi2html g++FAQ.texi
- mv work/*.html .
- rm -r work
-
-# Make plain-text form.
-
-g++FAQ.txt: $(srcdir)/g++FAQ.texi
- $(MAKEINFO) --no-split --no-headers -o - $(srcdir)/g++FAQ.texi |\
- sed '/^Concept Index/,$$d' > g++FAQ.txt
-
diff --git a/contrib/gcc/cp/NEWS b/contrib/gcc/cp/NEWS
index 9cb7d5b..1a242ab 100644
--- a/contrib/gcc/cp/NEWS
+++ b/contrib/gcc/cp/NEWS
@@ -1,3 +1,39 @@
+*** Changes in GCC 2.95:
+
+* Messages about non-conformant code that we can still handle ("pedwarns")
+ are now errors by default, rather than warnings. This can be reverted
+ with -fpermissive, and is overridden by -pedantic or -pedantic-errors.
+
+* String constants are now of type `const char[n]', rather than `char[n]'.
+ This can be reverted with -fno-const-strings.
+
+* References to functions are now supported.
+
+* Lookup of class members during class definition now works in all cases.
+
+* In overload resolution, type conversion operators are now properly
+ treated as always coming from the most derived class.
+
+* C9x-style restricted pointers are supported, using the `__restrict'
+ keyword.
+
+* You can now use -fno-implicit-inline-templates to suppress writing out
+ implicit instantiations of inline templates. Normally we do write them
+ out, even with -fno-implicit-templates, so that optimization doesn't
+ affect which instantiations are needed.
+
+* -fstrict-prototype now also suppresses implicit declarations.
+
+* Many obsolete options have been removed: -fall-virtual, -fmemoize-lookups,
+ -fsave-memoized, +e?, -fenum-int-equivalence, -fno-nonnull-objects.
+
+* Unused virtual functions can be discarded on some targets by specifying
+ -ffunction-sections -fvtable-gc to the compiler and --gc-sections to the
+ linker. Unfortunately, this only works on Linux if you're linking
+ statically.
+
+* Lots of bugs stomped.
+
*** Changes in EGCS 1.1:
* Namespaces are fully supported. The library has not yet been converted
diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c
index e65898e..094a345 100644
--- a/contrib/gcc/cp/call.c
+++ b/contrib/gcc/cp/call.c
@@ -1,5 +1,5 @@
/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
@@ -49,7 +49,7 @@ static int compare_ics PROTO((tree, tree));
static tree build_over_call PROTO((struct z_candidate *, tree, int));
static tree convert_like PROTO((tree, tree));
static void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
- tree, char *));
+ tree, const char *));
static tree build_object_call PROTO((tree, tree));
static tree resolve_args PROTO((tree));
static struct z_candidate * build_user_type_conversion_1
@@ -87,22 +87,22 @@ static tree strip_top_quals PROTO((tree));
static tree non_reference PROTO((tree));
static tree build_conv PROTO((enum tree_code, tree, tree));
static int is_subseq PROTO((tree, tree));
-static int is_properly_derived_from PROTO((tree, tree));
static int maybe_handle_ref_bind PROTO((tree*, tree*));
static void maybe_handle_implicit_object PROTO((tree*));
+static struct z_candidate * add_candidate PROTO((struct z_candidate *,
+ tree, tree, int));
+static tree source_type PROTO((tree));
+static void add_warning PROTO((struct z_candidate *, struct z_candidate *));
tree
build_vfield_ref (datum, type)
tree datum, type;
{
tree rval;
- int old_assume_nonnull_objects = flag_assume_nonnull_objects;
if (datum == error_mark_node)
return error_mark_node;
- /* Vtable references are always made from non-null objects. */
- flag_assume_nonnull_objects = 1;
if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
datum = convert_from_reference (datum);
@@ -111,7 +111,6 @@ build_vfield_ref (datum, type)
datum, CLASSTYPE_VFIELD (type));
else
rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0);
- flag_assume_nonnull_objects = old_assume_nonnull_objects;
return rval;
}
@@ -128,91 +127,40 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (name == ctor_identifier || name == dtor_identifier)
return NULL_TREE;
- if (instance_ptr == current_class_ptr)
- {
- /* Check to see if we really have a reference to an instance variable
- with `operator()()' overloaded. */
- field = IDENTIFIER_CLASS_VALUE (name);
-
- if (field == NULL_TREE)
- {
- cp_error ("`this' has no member named `%D'", name);
- return error_mark_node;
- }
-
- if (TREE_CODE (field) == FIELD_DECL)
- {
- /* If it's a field, try overloading operator (),
- or calling if the field is a pointer-to-function. */
- instance = build_component_ref_1 (current_class_ref, field, 0);
- if (instance == error_mark_node)
- return error_mark_node;
-
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE);
-
- if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
- return build_function_call (instance, parms);
- else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)
- return build_function_call (instance, expr_tree_cons (NULL_TREE, current_class_ptr, parms));
- }
- }
- return NULL_TREE;
- }
+ /* Speed up the common case. */
+ if (instance_ptr == current_class_ptr
+ && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE)
+ return NULL_TREE;
- /* Check to see if this is not really a reference to an instance variable
- with `operator()()' overloaded. */
field = lookup_field (basetype_path, name, 1, 0);
- /* This can happen if the reference was ambiguous or for access
- violations. */
- if (field == error_mark_node)
- return error_mark_node;
+ if (field == error_mark_node || field == NULL_TREE)
+ return field;
- if (field && TREE_CODE (field) == FIELD_DECL)
+ if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL)
{
- tree basetype;
- tree ftype = TREE_TYPE (field);
+ /* If it's a field, try overloading operator (),
+ or calling if the field is a pointer-to-function. */
+ instance = build_indirect_ref (instance_ptr, NULL_PTR);
+ instance = build_component_ref_1 (instance, field, 0);
- if (TREE_CODE (ftype) == REFERENCE_TYPE)
- ftype = TREE_TYPE (ftype);
+ if (instance == error_mark_node)
+ return error_mark_node;
- if (TYPE_LANG_SPECIFIC (ftype))
+ if (IS_AGGR_TYPE (TREE_TYPE (instance)))
+ return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
+ instance, parms, NULL_TREE);
+ else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
{
- /* Make the next search for this field very short. */
- basetype = DECL_FIELD_CONTEXT (field);
- instance_ptr = convert_pointer_to (basetype, instance_ptr);
-
- instance = build_indirect_ref (instance_ptr, NULL_PTR);
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
- build_component_ref_1 (instance, field, 0),
- parms, NULL_TREE);
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
+ return build_function_call (instance, parms);
+ else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
+ == METHOD_TYPE)
+ return build_function_call
+ (instance, expr_tree_cons (NULL_TREE, instance_ptr, parms));
}
- if (TREE_CODE (ftype) == POINTER_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE)
- {
- /* This is a member which is a pointer to function. */
- tree ref
- = build_component_ref_1 (build_indirect_ref (instance_ptr,
- NULL_PTR),
- field, LOOKUP_COMPLAIN);
- if (ref == error_mark_node)
- return error_mark_node;
- return build_function_call (ref, parms);
- }
- }
- else if (TREE_CODE (ftype) == METHOD_TYPE)
- {
- error ("invalid call via pointer-to-member function");
- return error_mark_node;
- }
- else
- return NULL_TREE;
}
+
return NULL_TREE;
}
@@ -350,6 +298,10 @@ check_dtor_name (basetype, name)
{
name = TREE_OPERAND (name, 0);
+ /* Just accept something we've already complained about. */
+ if (name == error_mark_node)
+ return 1;
+
if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name);
else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
@@ -551,6 +503,9 @@ build_call (function, result_type, parms)
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
+ if (decl)
+ my_friendly_assert (TREE_USED (decl), 990125);
+
/* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution.
We don't need to handle other cases of copying empty classes. */
@@ -628,10 +583,15 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
/* We need to process template parm names here so that tsubst catches
them properly. Other type names can wait. */
- if (TREE_CODE (name) == BIT_NOT_EXPR
- && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+ tree type = NULL_TREE;
+
+ if (TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
+ type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+ else if (TREE_CODE (TREE_OPERAND (name, 0)) == TYPE_DECL)
+ type = TREE_TYPE (TREE_OPERAND (name, 0));
+
if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM)
name = build_min_nt (BIT_NOT_EXPR, type);
}
@@ -639,29 +599,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
}
- /* This is the logic that magically deletes the second argument to
- operator delete, if it is not needed. */
- if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
- {
- tree save_last = TREE_CHAIN (parms);
-
- /* get rid of unneeded argument */
- TREE_CHAIN (parms) = NULL_TREE;
- if (build_method_call (instance, name, parms, basetype_path,
- (LOOKUP_SPECULATIVELY|flags) & ~LOOKUP_COMPLAIN))
- {
- /* If it finds a match, return it. */
- return build_method_call (instance, name, parms, basetype_path, flags);
- }
- /* If it doesn't work, two argument delete must work */
- TREE_CHAIN (parms) = save_last;
- }
- /* We already know whether it's needed or not for vec delete. */
- else if (name == ansi_opname[(int) VEC_DELETE_EXPR]
- && TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
- && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance)))
- TREE_CHAIN (parms) = NULL_TREE;
-
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
if (parms)
@@ -806,6 +743,15 @@ standard_conversion (to, from, expr)
to = strip_top_quals (to);
from = strip_top_quals (from);
+ if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
+ && expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return NULL_TREE;
+ from = TREE_TYPE (expr);
+ }
+
fcode = TREE_CODE (from);
tcode = TREE_CODE (to);
@@ -839,16 +785,15 @@ standard_conversion (to, from, expr)
enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (from)),
- TYPE_MAIN_VARIANT (TREE_TYPE (to)), 1))
+ if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (from)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (to))))
;
else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
&& ufcode != FUNCTION_TYPE)
{
from = build_pointer_type
- (cp_build_type_variant (void_type_node,
- TYPE_READONLY (TREE_TYPE (from)),
- TYPE_VOLATILE (TREE_TYPE (from))));
+ (cp_build_qualified_type (void_type_node,
+ CP_TYPE_QUALS (TREE_TYPE (from))));
conv = build_conv (PTR_CONV, from, conv);
}
else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
@@ -857,9 +802,9 @@ standard_conversion (to, from, expr)
tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
if (DERIVED_FROM_P (fbase, tbase)
- && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
- TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))),
- 1)))
+ && (same_type_p
+ (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))))))
{
from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
from = build_pointer_type (from);
@@ -871,18 +816,21 @@ standard_conversion (to, from, expr)
{
if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
{
- from = cp_build_type_variant (TREE_TYPE (to),
- TYPE_READONLY (TREE_TYPE (from)),
- TYPE_VOLATILE (TREE_TYPE (from)));
+ from =
+ cp_build_qualified_type (TREE_TYPE (to),
+ CP_TYPE_QUALS (TREE_TYPE (from)));
from = build_pointer_type (from);
conv = build_conv (PTR_CONV, from, conv);
}
}
- if (comptypes (from, to, 1))
+ if (same_type_p (from, to))
/* OK */;
else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
conv = build_conv (QUAL_CONV, to, conv);
+ else if (expr && string_conv_p (to, expr, 0))
+ /* converting from string constant to char *. */
+ conv = build_conv (QUAL_CONV, to, conv);
else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
{
conv = build_conv (PTR_CONV, to, conv);
@@ -901,15 +849,13 @@ standard_conversion (to, from, expr)
tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
if (! DERIVED_FROM_P (fbase, tbase)
- || ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1)
+ || ! same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn))
|| ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
- TREE_CHAIN (TYPE_ARG_TYPES (tofn)), 1)
- || TYPE_READONLY (fbase) != TYPE_READONLY (tbase)
- || TYPE_VOLATILE (fbase) != TYPE_VOLATILE (tbase))
+ TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
+ || CP_TYPE_QUALS (fbase) != CP_TYPE_QUALS (tbase))
return 0;
- from = cp_build_type_variant (tbase, TYPE_READONLY (fbase),
- TYPE_VOLATILE (fbase));
+ from = cp_build_qualified_type (tbase, CP_TYPE_QUALS (fbase));
from = build_cplus_method_type (from, TREE_TYPE (fromfn),
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
from = build_ptrmemfunc_type (build_pointer_type (from));
@@ -971,24 +917,30 @@ reference_binding (rto, rfrom, expr, flags)
tree from = rfrom;
int related;
+ if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return NULL_TREE;
+ from = TREE_TYPE (expr);
+ }
+
if (TREE_CODE (from) == REFERENCE_TYPE)
from = TREE_TYPE (from);
else if (! expr || ! real_lvalue_p (expr))
lvalue = 0;
- related = (comptypes (TYPE_MAIN_VARIANT (to),
- TYPE_MAIN_VARIANT (from), 1)
+ related = (same_type_p (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from))
|| (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from)));
- if (lvalue && related
- && TYPE_READONLY (to) >= TYPE_READONLY (from)
- && TYPE_VOLATILE (to) >= TYPE_VOLATILE (from))
+ if (lvalue && related && at_least_as_qualified_p (to, from))
{
conv = build1 (IDENTITY_CONV, from, expr);
- if (comptypes (TYPE_MAIN_VARIANT (to),
- TYPE_MAIN_VARIANT (from), 1))
+ if (same_type_p (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from)))
conv = build_conv (REF_BIND, rto, conv);
else
{
@@ -1012,14 +964,12 @@ reference_binding (rto, rfrom, expr, flags)
TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0);
}
if (conv
- && ((! (TYPE_READONLY (to) && ! TYPE_VOLATILE (to)
+ && ((! (CP_TYPE_CONST_NON_VOLATILE_P (to)
&& (flags & LOOKUP_NO_TEMP_BIND) == 0))
/* If T1 is reference-related to T2, cv1 must be the same
cv-qualification as, or greater cv-qualification than,
cv2; otherwise, the program is ill-formed. */
- || (related
- && (TYPE_READONLY (to) < TYPE_READONLY (from)
- || TYPE_VOLATILE (to) < TYPE_VOLATILE (from)))))
+ || (related && !at_least_as_qualified_p (to, from))))
ICS_BAD_FLAG (conv) = 1;
}
@@ -1039,14 +989,6 @@ implicit_conversion (to, from, expr, flags)
tree conv;
struct z_candidate *cand;
- if (expr && type_unknown_p (expr))
- {
- expr = instantiate_type (to, expr, 0);
- if (expr == error_mark_node)
- return 0;
- from = TREE_TYPE (expr);
- }
-
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags);
else
@@ -1056,7 +998,7 @@ implicit_conversion (to, from, expr, flags)
;
else if (expr != NULL_TREE
&& (IS_AGGR_TYPE (non_reference (from))
- || IS_AGGR_TYPE (non_reference (to)))
+ || IS_AGGR_TYPE (non_reference (to)))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
cand = build_user_type_conversion_1
@@ -1071,8 +1013,7 @@ implicit_conversion (to, from, expr, flags)
(TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING);
if (cand)
{
- if (! TYPE_READONLY (TREE_TYPE (to))
- || TYPE_VOLATILE (TREE_TYPE (to)))
+ if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (to)))
ICS_BAD_FLAG (cand->second_conv) = 1;
if (!conv || (ICS_BAD_FLAG (conv)
> ICS_BAD_FLAG (cand->second_conv)))
@@ -1121,42 +1062,92 @@ add_function_candidate (candidates, fn, arglist, flags)
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
tree convs;
- tree parmnode = parmlist;
- tree argnode = arglist;
+ tree parmnode, argnode;
int viable = 1;
/* The `this' and `in_chrg' arguments to constructors are not considered
in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn))
{
- parmnode = TREE_CHAIN (parmnode);
- argnode = TREE_CHAIN (argnode);
+ parmlist = TREE_CHAIN (parmlist);
+ arglist = TREE_CHAIN (arglist);
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
{
- parmnode = TREE_CHAIN (parmnode);
- argnode = TREE_CHAIN (argnode);
+ parmlist = TREE_CHAIN (parmlist);
+ arglist = TREE_CHAIN (arglist);
}
}
- len = list_length (argnode);
+ len = list_length (arglist);
convs = make_scratch_vec (len);
+ /* 13.3.2 - Viable functions [over.match.viable]
+ First, to be a viable function, a candidate function shall have enough
+ parameters to agree in number with the arguments in the list.
+
+ We need to check this first; otherwise, checking the ICSes might cause
+ us to produce an ill-formed template instantiation. */
+
+ parmnode = parmlist;
+ for (i = 0; i < len; ++i)
+ {
+ if (parmnode == NULL_TREE || parmnode == void_list_node)
+ break;
+ parmnode = TREE_CHAIN (parmnode);
+ }
+
+ if (i < len && parmnode)
+ viable = 0;
+
+ /* Make sure there are default args for the rest of the parms. */
+ else for (; parmnode && parmnode != void_list_node;
+ parmnode = TREE_CHAIN (parmnode))
+ if (! TREE_PURPOSE (parmnode))
+ {
+ viable = 0;
+ break;
+ }
+
+ if (! viable)
+ goto out;
+
+ /* Second, for F to be a viable function, there shall exist for each
+ argument an implicit conversion sequence that converts that argument
+ to the corresponding parameter of F. */
+
+ parmnode = parmlist;
+ argnode = arglist;
+
for (i = 0; i < len; ++i)
{
tree arg = TREE_VALUE (argnode);
- tree argtype = TREE_TYPE (arg);
+ tree argtype = lvalue_type (arg);
tree t;
- /* An overloaded function does not have an argument type */
- if (TREE_CODE (arg) == OVERLOAD)
- argtype = unknown_type_node;
- argtype = cp_build_type_variant
- (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
-
if (parmnode == void_list_node)
break;
- else if (parmnode)
- t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
+
+ if (parmnode)
+ {
+ tree parmtype = TREE_VALUE (parmnode);
+
+ /* [over.match.funcs] For conversion functions, the function is
+ considered to be a member of the class of the implicit object
+ argument for the purpose of defining the type of the implicit
+ object parameter.
+
+ Since build_over_call ignores the ICS for the `this' parameter,
+ we can just change the parm type. */
+ if (DECL_CONV_FN_P (fn) && i == 0)
+ {
+ parmtype
+ = build_qualified_type (TREE_TYPE (argtype),
+ TYPE_QUALS (TREE_TYPE (parmtype)));
+ parmtype = build_pointer_type (parmtype);
+ }
+
+ t = implicit_conversion (parmtype, argtype, arg, flags);
+ }
else
{
t = build1 (IDENTITY_CONV, argtype, arg);
@@ -1169,7 +1160,10 @@ add_function_candidate (candidates, fn, arglist, flags)
TREE_VEC_ELT (convs, i) = t;
if (! t)
- break;
+ {
+ viable = 0;
+ break;
+ }
if (ICS_BAD_FLAG (t))
viable = -1;
@@ -1179,25 +1173,20 @@ add_function_candidate (candidates, fn, arglist, flags)
argnode = TREE_CHAIN (argnode);
}
- if (i < len)
- viable = 0;
-
- /* Make sure there are default args for the rest of the parms. */
- for (; parmnode && parmnode != void_list_node;
- parmnode = TREE_CHAIN (parmnode))
- if (! TREE_PURPOSE (parmnode))
- {
- viable = 0;
- break;
- }
-
+ out:
return add_candidate (candidates, fn, convs, viable);
}
/* Create an overload candidate for the conversion function FN which will
be invoked for expression OBJ, producing a pointer-to-function which
will in turn be called with the argument list ARGLIST, and add it to
- CANDIDATES. FLAGS is passed on to implicit_conversion. */
+ CANDIDATES. FLAGS is passed on to implicit_conversion.
+
+ Actually, we don't really care about FN; we care about the type it
+ converts to. There may be multiple conversion functions that will
+ convert to that type, and we rely on build_user_type_conversion_1 to
+ choose the best one; so when we create our candidate, we record the type
+ instead of the function. */
static struct z_candidate *
add_conv_candidate (candidates, fn, obj, arglist)
@@ -1213,6 +1202,10 @@ add_conv_candidate (candidates, fn, obj, arglist)
int viable = 1;
int flags = LOOKUP_NORMAL;
+ /* Don't bother looking up the same type twice. */
+ if (candidates && candidates->fn == totype)
+ return candidates;
+
for (i = 0; i < len; ++i)
{
tree arg = i == 0 ? obj : TREE_VALUE (argnode);
@@ -1257,7 +1250,7 @@ add_conv_candidate (candidates, fn, obj, arglist)
break;
}
- return add_candidate (candidates, fn, convs, viable);
+ return add_candidate (candidates, totype, convs, viable);
}
static struct z_candidate *
@@ -1803,7 +1796,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
;
else if (IS_AGGR_TYPE (argtypes[i]))
{
- tree convs = lookup_conversions (argtypes[i]);
+ tree convs;
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
return candidates;
@@ -1825,11 +1818,11 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
for (; convs; convs = TREE_CHAIN (convs))
{
- type = TREE_TYPE (TREE_TYPE (TREE_VALUE (convs)));
+ type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs))));
if (i == 0 && ref1
&& (TREE_CODE (type) != REFERENCE_TYPE
- || TYPE_READONLY (TREE_TYPE (type))))
+ || CP_TYPE_CONST_P (TREE_TYPE (type))))
continue;
if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE)
@@ -1911,7 +1904,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
tree fn;
i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
- return_type, strict, NULL_TREE);
+ return_type, strict);
if (i != 0)
return candidates;
@@ -2020,7 +2013,7 @@ static void
print_z_candidates (candidates)
struct z_candidate *candidates;
{
- char *str = "candidates are:";
+ const char *str = "candidates are:";
for (; candidates; candidates = candidates->next)
{
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
@@ -2038,8 +2031,10 @@ print_z_candidates (candidates)
cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
}
+ else if (TYPE_P (candidates->fn))
+ cp_error ("%s %T <conversion>", str, candidates->fn);
else
- cp_error_at ("%s %+D%s", str, candidates->fn,
+ cp_error_at ("%s %+#D%s", str, candidates->fn,
candidates->viable == -1 ? " <near match>" : "");
str = " ";
}
@@ -2123,7 +2118,7 @@ build_user_type_conversion_1 (totype, expr, flags)
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
- if (TREE_CODE (fns) != TEMPLATE_DECL)
+ if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
else
@@ -2293,6 +2288,8 @@ build_new_function_call (fn, args)
for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
{
tree t = OVL_FUNCTION (t1);
+ struct z_candidate *old_candidates = candidates;
+
if (TREE_CODE (t) == TEMPLATE_DECL)
{
templates = scratch_tree_cons (NULL_TREE, t, templates);
@@ -2303,6 +2300,9 @@ build_new_function_call (fn, args)
else if (! template_only)
candidates = add_function_candidate
(candidates, t, args, LOOKUP_NORMAL);
+
+ if (candidates != old_candidates)
+ candidates->basetype_path = DECL_REAL_CONTEXT (t);
}
if (! any_viable (candidates))
@@ -2349,7 +2349,6 @@ build_object_call (obj, args)
struct z_candidate *candidates = 0, *cand;
tree fns, convs, mem_args = NULL_TREE;
tree type = TREE_TYPE (obj);
- tree templates = NULL_TREE;
if (TYPE_PTRMEMFUNC_P (type))
{
@@ -2379,7 +2378,6 @@ build_object_call (obj, args)
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
- templates = scratch_tree_cons (NULL_TREE, fn, templates);
candidates
= add_template_candidate (candidates, fn, NULL_TREE,
mem_args, NULL_TREE,
@@ -2400,16 +2398,15 @@ build_object_call (obj, args)
{
tree fns = TREE_VALUE (convs);
tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
- tree fn;
- if (TREE_CODE (totype) == POINTER_TYPE
+ if ((TREE_CODE (totype) == POINTER_TYPE
+ || TREE_CODE (totype) == REFERENCE_TYPE)
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
- for (; fns; fns = OVL_NEXT (fn))
+ for (; fns; fns = OVL_NEXT (fns))
{
- fn = OVL_CURRENT (fn);
+ tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
- templates = scratch_tree_cons (NULL_TREE, fn, templates);
candidates = add_template_conv_candidate (candidates,
fn,
obj,
@@ -2441,7 +2438,11 @@ build_object_call (obj, args)
return error_mark_node;
}
- if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
+ /* Since cand->fn will be a type, not a function, for a conversion
+ function, we must be careful not to unconditionally look at
+ DECL_NAME here. */
+ if (TREE_CODE (cand->fn) == FUNCTION_DECL
+ && DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
return build_over_call (cand, mem_args, LOOKUP_NORMAL);
obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
@@ -2454,9 +2455,9 @@ static void
op_error (code, code2, arg1, arg2, arg3, problem)
enum tree_code code, code2;
tree arg1, arg2, arg3;
- char *problem;
+ const char *problem;
{
- char * opname
+ const char * opname
= (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]);
switch (code)
@@ -2520,73 +2521,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
{
case NEW_EXPR:
case VEC_NEW_EXPR:
- {
- tree rval;
-
- arglist = scratch_tree_cons (NULL_TREE, arg2, arg3);
- if (flags & LOOKUP_GLOBAL)
- return build_new_function_call
- (lookup_function_nonclass (fnname, arglist), arglist);
-
- /* FIXME */
- rval = build_method_call
- (build_indirect_ref (build1 (NOP_EXPR, arg1, error_mark_node),
- "new"),
- fnname, arglist, NULL_TREE, flags);
- if (rval == error_mark_node)
- /* User might declare fancy operator new, but invoke it
- like standard one. */
- return rval;
-
- TREE_TYPE (rval) = arg1;
- return rval;
- }
-
case VEC_DELETE_EXPR:
case DELETE_EXPR:
- {
- tree rval;
-
- if (flags & LOOKUP_GLOBAL)
- {
- arglist = build_scratch_list (NULL_TREE, arg1);
- return build_new_function_call
- (lookup_function_nonclass (fnname, arglist), arglist);
- }
-
- arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2));
-
- arg1 = TREE_TYPE (arg1);
-
- /* This handles the case where we're trying to delete
- X (*a)[10];
- a=new X[5][10];
- delete[] a; */
-
- if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
- {
- /* Strip off the pointer and the array. */
- arg1 = TREE_TYPE (TREE_TYPE (arg1));
-
- while (TREE_CODE (arg1) == ARRAY_TYPE)
- arg1 = (TREE_TYPE (arg1));
-
- arg1 = build_pointer_type (arg1);
- }
-
- /* FIXME */
- rval = build_method_call
- (build_indirect_ref (build1 (NOP_EXPR, arg1,
- error_mark_node),
- NULL_PTR),
- fnname, arglist, NULL_TREE, flags);
-#if 0
- /* This can happen when operator delete is protected. */
- my_friendly_assert (rval != error_mark_node, 250);
- TREE_TYPE (rval) = void_type_node;
-#endif
- return rval;
- }
+ /* Use build_op_new_call and build_op_delete_call instead. */
+ my_friendly_abort (981018);
case CALL_EXPR:
return build_object_call (arg1, arg2);
@@ -2798,8 +2736,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
case LE_EXPR:
case EQ_EXPR:
case NE_EXPR:
- if (flag_int_enum_equivalence == 0
- && TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
+ if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE
&& (TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
!= TYPE_MAIN_VARIANT (TREE_TYPE (arg2))))
@@ -2820,9 +2757,19 @@ build_new_op (code, flags, arg1, arg2, arg3)
conv = TREE_OPERAND (conv, 0);
arg1 = convert_like (conv, arg1);
if (arg2)
- arg2 = convert_like (TREE_VEC_ELT (cand->convs, 1), arg2);
+ {
+ conv = TREE_VEC_ELT (cand->convs, 1);
+ if (TREE_CODE (conv) == REF_BIND)
+ conv = TREE_OPERAND (conv, 0);
+ arg2 = convert_like (conv, arg2);
+ }
if (arg3)
- arg3 = convert_like (TREE_VEC_ELT (cand->convs, 2), arg3);
+ {
+ conv = TREE_VEC_ELT (cand->convs, 2);
+ if (TREE_CODE (conv) == REF_BIND)
+ conv = TREE_OPERAND (conv, 0);
+ arg3 = convert_like (conv, arg3);
+ }
builtin:
switch (code)
@@ -2906,10 +2853,8 @@ build_op_new_call (code, type, args, flags)
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
&& (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
{
- tree dummy = build1 (NOP_EXPR, build_pointer_type (type),
- error_mark_node);
- dummy = build_indirect_ref (dummy, "new");
- return build_method_call (dummy, fnname, args, NULL_TREE, flags);
+ return build_method_call (build_dummy_object (type),
+ fnname, args, NULL_TREE, flags);
}
else
return build_new_function_call
@@ -2988,12 +2933,7 @@ build_op_delete_call (code, addr, size, flags, placement)
if (type != TYPE_MAIN_VARIANT (type))
addr = cp_convert (build_pointer_type (TYPE_MAIN_VARIANT (type)), addr);
- /* instantiate_type will always return a plain function; pretend it's
- overloaded. */
- if (TREE_CODE (fns) == FUNCTION_DECL)
- fns = scratch_ovl_cons (fns, NULL_TREE);
-
- fn = instantiate_type (fntype, fns, 0);
+ fn = instantiate_type (fntype, fns, 2);
if (fn != error_mark_node)
{
@@ -3013,11 +2953,11 @@ build_op_delete_call (code, addr, size, flags, placement)
tree_cons (NULL_TREE, sizetype, void_list_node));
fntype = build_function_type (void_type_node, argtypes);
- fn = instantiate_type (fntype, fns, 0);
+ fn = instantiate_type (fntype, fns, 2);
if (fn != error_mark_node)
{
- if (TREE_CODE (fns) == TREE_LIST)
+ if (BASELINK_P (fns))
/* Member functions. */
enforce_access (TREE_PURPOSE (fns), fn);
return build_function_call
@@ -3036,28 +2976,30 @@ build_op_delete_call (code, addr, size, flags, placement)
}
/* If the current scope isn't allowed to access DECL along
- BASETYPE_PATH, give an error. */
+ BASETYPE_PATH, give an error. The most derived class in
+ BASETYPE_PATH is the one used to qualify DECL. */
-void
+int
enforce_access (basetype_path, decl)
- tree basetype_path, decl;
+ tree basetype_path;
+ tree decl;
{
- tree access = compute_access (basetype_path, decl);
+ int accessible;
- if (access == access_private_node)
- {
- cp_error_at ("`%+#D' is %s", decl,
- TREE_PRIVATE (decl) ? "private"
- : "from private base class");
- error ("within this context");
- }
- else if (access == access_protected_node)
+ accessible = accessible_p (basetype_path, decl);
+ if (!accessible)
{
- cp_error_at ("`%+#D' %s", decl,
- TREE_PROTECTED (decl) ? "is protected"
- : "has protected accessibility");
- error ("within this context");
+ if (TREE_PRIVATE (decl))
+ cp_error_at ("`%+#D' is private", decl);
+ else if (TREE_PROTECTED (decl))
+ cp_error_at ("`%+#D' is protected", decl);
+ else
+ cp_error_at ("`%+#D' is inaccessible", decl);
+ cp_error ("within this context");
+ return 0;
}
+
+ return 1;
}
/* Perform the conversions in CONVS on the expression EXPR. */
@@ -3156,7 +3098,7 @@ convert_like (convs, expr)
destination type takes a pointer argument. */
if (TYPE_SIZE (TREE_TYPE (expr)) == 0)
{
- if (comptypes (TREE_TYPE (expr), TREE_TYPE (convs), 1))
+ if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs)))
incomplete_type_error (expr, TREE_TYPE (expr));
else
cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
@@ -3178,6 +3120,11 @@ convert_like (convs, expr)
case LVALUE_CONV:
return decay_conversion (expr);
+ case QUAL_CONV:
+ /* Warn about deprecated conversion if appropriate. */
+ string_conv_p (TREE_TYPE (convs), expr, 1);
+ break;
+
default:
break;
}
@@ -3205,17 +3152,47 @@ convert_arg_to_ellipsis (arg)
/* Convert `short' and `char' to full-size `int'. */
arg = default_conversion (arg);
+ arg = require_complete_type (arg);
+
return arg;
}
/* ARG is a default argument expression being passed to a parameter of
- the indicated TYPE. Do any required conversions. Return the
- converted value. */
+ the indicated TYPE, which is a parameter to FN. Do any required
+ conversions. Return the converted value. */
tree
-convert_default_arg (type, arg)
- tree type, arg;
+convert_default_arg (type, arg, fn)
+ tree type;
+ tree arg;
+ tree fn;
{
+ if (fn && DECL_TEMPLATE_INFO (fn))
+ {
+ /* This default argument came from a template. Instantiate the
+ default argument here, not in tsubst. In the case of
+ something like:
+
+ template <class T>
+ struct S {
+ static T t();
+ void f(T = t());
+ };
+
+ we must be careful to do name lookup in the scope of S<T>,
+ rather than in the current class. */
+ if (DECL_CLASS_SCOPE_P (fn))
+ pushclass (DECL_REAL_CONTEXT (fn), 2);
+
+ arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
+
+ if (DECL_CLASS_SCOPE_P (fn))
+ popclass ();
+
+ /* Make sure the default argument is reasonable. */
+ arg = check_default_argument (type, arg);
+ }
+
arg = break_out_target_exprs (arg);
if (TREE_CODE (arg) == CONSTRUCTOR)
@@ -3289,21 +3266,23 @@ build_over_call (cand, args, flags)
{
tree parmtype = TREE_VALUE (parm);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
+ tree t;
if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
- {
- int dv = (TYPE_VOLATILE (TREE_TYPE (parmtype))
- < TYPE_VOLATILE (TREE_TYPE (argtype)));
- int dc = (TYPE_READONLY (TREE_TYPE (parmtype))
- < TYPE_READONLY (TREE_TYPE (argtype)));
- char *p = (dv && dc ? "const and volatile"
- : dc ? "const" : dv ? "volatile" : "");
-
- cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards %s",
- TREE_TYPE (argtype), fn, p);
- }
- converted_args = expr_tree_cons
- (NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST),
- converted_args);
+ cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
+ TREE_TYPE (argtype), fn);
+
+ /* [class.mfct.nonstatic]: If a nonstatic member function of a class
+ X is called for an object that is not of type X, or of a type
+ derived from X, the behavior is undefined.
+
+ So we can assume that anything passed as 'this' is non-null, and
+ optimize accordingly. */
+ if (TREE_CODE (parmtype) == POINTER_TYPE)
+ t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg));
+ else
+ /* This happens with signatures. */
+ t = convert_force (parmtype, TREE_VALUE (arg), CONV_C_CAST);
+ converted_args = expr_tree_cons (NULL_TREE, t, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
@@ -3337,7 +3316,14 @@ build_over_call (cand, args, flags)
"argument passing", fn, i - is_method);
}
else
- val = convert_like (conv, TREE_VALUE (arg));
+ {
+ /* Issue warnings about peculiar, but legal, uses of NULL. */
+ if (ARITHMETIC_TYPE_P (TREE_VALUE (parm))
+ && TREE_VALUE (arg) == null_node)
+ cp_warning ("converting NULL to non-pointer type");
+
+ val = convert_like (conv, TREE_VALUE (arg));
+ }
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
@@ -3350,34 +3336,12 @@ build_over_call (cand, args, flags)
/* Default arguments */
for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
- {
- tree arg = TREE_PURPOSE (parm);
-
- if (DECL_TEMPLATE_INFO (fn))
- {
- /* This came from a template. Instantiate the default arg here,
- not in tsubst. In the case of something like:
-
- template <class T>
- struct S {
- static T t();
- void f(T = t());
- };
-
- we must be careful to do name lookup in the scope of
- S<T>, rather than in the current class. */
- if (DECL_CLASS_SCOPE_P (fn))
- pushclass (DECL_REAL_CONTEXT (fn), 2);
-
- arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
-
- if (DECL_CLASS_SCOPE_P (fn))
- popclass (1);
- }
- converted_args = expr_tree_cons
- (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
- converted_args);
- }
+ converted_args
+ = expr_tree_cons (NULL_TREE,
+ convert_default_arg (TREE_VALUE (parm),
+ TREE_PURPOSE (parm),
+ fn),
+ converted_args);
/* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg))
@@ -3388,10 +3352,17 @@ build_over_call (cand, args, flags)
converted_args = nreverse (converted_args);
+ if (warn_format && (DECL_NAME (fn) || DECL_ASSEMBLER_NAME (fn)))
+ check_function_format (DECL_NAME (fn), DECL_ASSEMBLER_NAME (fn),
+ converted_args);
+
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
- if (DECL_CONSTRUCTOR_P (fn)
- && TREE_VEC_LENGTH (convs) == 1
+
+ if (! flag_elide_constructors)
+ /* Do things the hard way. */;
+ else if (DECL_CONSTRUCTOR_P (fn)
+ && TREE_VEC_LENGTH (convs) == 1
&& copy_args_p (fn))
{
tree targ;
@@ -3409,8 +3380,8 @@ build_over_call (cand, args, flags)
if (TREE_CODE (targ) == ADDR_EXPR)
{
targ = TREE_OPERAND (targ, 0);
- if (! comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))),
- TYPE_MAIN_VARIANT (TREE_TYPE (targ)), 1))
+ if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (targ))))
targ = NULL_TREE;
}
else
@@ -3437,8 +3408,7 @@ build_over_call (cand, args, flags)
return arg;
else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
- val = build (VAR_DECL, DECL_CONTEXT (fn));
- layout_decl (val, 0);
+ val = build_decl (VAR_DECL, NULL_TREE, DECL_CONTEXT (fn));
val = build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0);
TREE_SIDE_EFFECTS (val) = 1;
return val;
@@ -3447,20 +3417,34 @@ build_over_call (cand, args, flags)
else if (! real_lvalue_p (arg)
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
+ tree address;
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0));
- /* Don't copy the padding byte; it might not have been allocated
- if to is a base subobject. */
- if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
- return build_unary_op
- (ADDR_EXPR, build (COMPOUND_EXPR, TREE_TYPE (to),
- cp_convert (void_type_node, arg), to),
- 0);
-
- val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
+ /* If we're initializing an empty class, then we actually
+ have to use a MODIFY_EXPR rather than an INIT_EXPR. The
+ reason is that the dummy padding member in the target may
+ not actually be allocated if TO is a base class
+ subobject. Since we've set TYPE_NONCOPIED_PARTS on the
+ padding, a MODIFY_EXPR will preserve its value, which is
+ the right thing to do if it's not really padding at all.
+
+ It's not safe to just throw away the ARG if we're looking
+ at an empty class because the ARG might contain a
+ TARGET_EXPR which wants to be bound to TO. If it is not,
+ expand_expr will assign a dummy slot for the TARGET_EXPR,
+ and we will call a destructor for it, which is wrong,
+ because we will also destroy TO, but will never have
+ constructed it. */
+ val = build (is_empty_class (DECL_CLASS_CONTEXT (fn))
+ ? MODIFY_EXPR : INIT_EXPR,
+ DECL_CONTEXT (fn), to, arg);
TREE_SIDE_EFFECTS (val) = 1;
- return build_unary_op (ADDR_EXPR, val, 0);
+ address = build_unary_op (ADDR_EXPR, val, 0);
+ /* Avoid a warning about this expression, if the address is
+ never used. */
+ TREE_USED (address) = 1;
+ return address;
}
}
else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
@@ -3472,12 +3456,6 @@ build_over_call (cand, args, flags)
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
- /* Don't copy the padding byte; it might not have been allocated
- if to is a base subobject. */
- if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
- return build (COMPOUND_EXPR, TREE_TYPE (to),
- cp_convert (void_type_node, arg), to);
-
val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
TREE_SIDE_EFFECTS (val) = 1;
return val;
@@ -3524,7 +3502,7 @@ build_over_call (cand, args, flags)
}
fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
- if (TREE_TYPE (fn) == void_type_node)
+ if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
return fn;
fn = require_complete_type (fn);
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
@@ -3549,8 +3527,16 @@ build_new_method_call (instance, name, args, basetype_path, flags)
{
explicit_targs = TREE_OPERAND (name, 1);
name = TREE_OPERAND (name, 0);
- if (TREE_CODE (name) == TEMPLATE_DECL)
+ if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
name = DECL_NAME (name);
+ else
+ {
+ if (TREE_CODE (name) == COMPONENT_REF)
+ name = TREE_OPERAND (name, 1);
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (OVL_CURRENT (name));
+ }
+
template_only = 1;
}
@@ -3572,7 +3558,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
instance = resolve_offset_ref (instance);
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
instance = convert_from_reference (instance);
- basetype = TREE_TYPE (instance);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
/* XXX this should be handled before we get here. */
if (! IS_AGGR_TYPE (basetype)
@@ -3672,8 +3658,12 @@ build_new_method_call (instance, name, args, basetype_path, flags)
/* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
- cp_error ("no matching function for call to `%T::%D (%A)%V'", basetype,
- pretty_name, user_args, TREE_TYPE (TREE_TYPE (instance_ptr)));
+ if (TYPE_SIZE (basetype) == 0)
+ incomplete_type_error (instance_ptr, basetype);
+ else
+ cp_error ("no matching function for call to `%T::%D (%A)%V'",
+ basetype, pretty_name, user_args,
+ TREE_TYPE (TREE_TYPE (instance_ptr)));
print_z_candidates (candidates);
return error_mark_node;
}
@@ -3692,12 +3682,14 @@ build_new_method_call (instance, name, args, basetype_path, flags)
&& instance == current_class_ref
&& DECL_CONSTRUCTOR_P (current_function_decl)
&& ! (flags & LOOKUP_NONVIRTUAL)
- && value_member (cand->fn, get_abstract_virtuals (basetype)))
+ && value_member (cand->fn, CLASSTYPE_ABSTRACT_VIRTUALS (basetype)))
cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
- && TREE_CODE (instance_ptr) == NOP_EXPR
- && TREE_OPERAND (instance_ptr, 0) == error_mark_node)
- cp_error ("cannot call member function `%D' without object", cand->fn);
+ && is_dummy_object (instance_ptr))
+ {
+ cp_error ("cannot call member function `%D' without object", cand->fn);
+ return error_mark_node;
+ }
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
&& ((instance == current_class_ref && (dtor_label || ctor_label))
@@ -3750,9 +3742,9 @@ is_subseq (ics1, ics2)
ics2 = TREE_OPERAND (ics2, 0);
if (TREE_CODE (ics2) == TREE_CODE (ics1)
- && comptypes (TREE_TYPE (ics2), TREE_TYPE (ics1), 1)
- && comptypes (TREE_TYPE (TREE_OPERAND (ics2, 0)),
- TREE_TYPE (TREE_OPERAND (ics1, 0)), 1))
+ && same_type_p (TREE_TYPE (ics2), TREE_TYPE (ics1))
+ && same_type_p (TREE_TYPE (TREE_OPERAND (ics2, 0)),
+ TREE_TYPE (TREE_OPERAND (ics1, 0))))
return 1;
}
}
@@ -3760,7 +3752,7 @@ is_subseq (ics1, ics2)
/* Returns non-zero iff DERIVED is derived from BASE. The inputs may
be any _TYPE nodes. */
-static int
+int
is_properly_derived_from (derived, base)
tree derived;
tree base;
@@ -3771,8 +3763,8 @@ is_properly_derived_from (derived, base)
/* We only allow proper derivation here. The DERIVED_FROM_P macro
considers every class derived from itself. */
- return (!comptypes (TYPE_MAIN_VARIANT (derived),
- TYPE_MAIN_VARIANT (base), 1)
+ return (!same_type_p (TYPE_MAIN_VARIANT (derived),
+ TYPE_MAIN_VARIANT (base))
&& DERIVED_FROM_P (base, derived));
}
@@ -3879,9 +3871,9 @@ compare_ics (ics1, ics2)
tree to_type1;
tree to_type2;
tree deref_from_type1 = NULL_TREE;
- tree deref_from_type2;
- tree deref_to_type1;
- tree deref_to_type2;
+ tree deref_from_type2 = NULL_TREE;
+ tree deref_to_type1 = NULL_TREE;
+ tree deref_to_type2 = NULL_TREE;
/* REF_BINDING is non-zero if the result of the conversion sequence
is a reference type. In that case TARGET_TYPE is the
@@ -3985,7 +3977,7 @@ compare_ics (ics1, ics2)
from_type2 = TREE_TYPE (from_type2);
}
- if (comptypes (from_type1, from_type2, 1))
+ if (same_type_p (from_type1, from_type2))
{
if (is_subseq (ics1, ics2))
return 1;
@@ -4085,7 +4077,7 @@ compare_ics (ics1, ics2)
else if (TREE_CODE (deref_to_type1) == VOID_TYPE
|| TREE_CODE (deref_to_type2) == VOID_TYPE)
{
- if (comptypes (deref_from_type1, deref_from_type2, 1))
+ if (same_type_p (deref_from_type1, deref_from_type2))
{
if (TREE_CODE (deref_to_type2) == VOID_TYPE)
{
@@ -4112,7 +4104,7 @@ compare_ics (ics1, ics2)
--conversion of B* to A* is better than conversion of C* to
A* */
- if (comptypes (deref_from_type1, deref_from_type2, 1))
+ if (same_type_p (deref_from_type1, deref_from_type2))
{
if (is_properly_derived_from (deref_to_type1,
deref_to_type2))
@@ -4121,7 +4113,7 @@ compare_ics (ics1, ics2)
deref_to_type1))
return -1;
}
- else if (comptypes (deref_to_type1, deref_to_type2, 1))
+ else if (same_type_p (deref_to_type1, deref_to_type2))
{
if (is_properly_derived_from (deref_from_type2,
deref_from_type1))
@@ -4133,7 +4125,7 @@ compare_ics (ics1, ics2)
}
}
else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
- && comptypes (from_type1, from_type2, 1))
+ && same_type_p (from_type1, from_type2))
{
/* [over.ics.rank]
@@ -4152,7 +4144,7 @@ compare_ics (ics1, ics2)
}
}
else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
- && comptypes (to_type1, to_type2, 1))
+ && same_type_p (to_type1, to_type2))
{
/* [over.ics.rank]
@@ -4179,7 +4171,7 @@ compare_ics (ics1, ics2)
qualification signature of type T2 */
if (TREE_CODE (ics1) == QUAL_CONV
&& TREE_CODE (ics2) == QUAL_CONV
- && comptypes (from_type1, from_type2, 1))
+ && same_type_p (from_type1, from_type2))
return comp_cv_qual_signature (to_type1, to_type2);
/* [over.ics.rank]
@@ -4191,8 +4183,8 @@ compare_ics (ics1, ics2)
which the reference initialized by S1 refers */
if (ref_binding1 && ref_binding2
- && comptypes (TYPE_MAIN_VARIANT (to_type1),
- TYPE_MAIN_VARIANT (to_type2), 1))
+ && same_type_p (TYPE_MAIN_VARIANT (to_type1),
+ TYPE_MAIN_VARIANT (to_type2)))
return comp_cv_qualification (target_type2, target_type1);
/* Neither conversion sequence is better than the other. */
@@ -4250,6 +4242,11 @@ joust (cand1, cand2, warn)
if (cand1->viable < cand2->viable)
return -1;
+ /* If we have two pseudo-candidates for conversions to the same type,
+ arbitrarily pick one. */
+ if (TYPE_P (cand1->fn) && cand1->fn == cand2->fn)
+ return 1;
+
/* a viable function F1
is defined to be a better function than another viable function F2 if
for all arguments i, ICSi(F1) is not a worse conversion sequence than
@@ -4335,8 +4332,8 @@ joust (cand1, cand2, warn)
!= DECL_CONSTRUCTOR_P (cand2->fn))
/* Don't warn if the two conv ops convert to the same type... */
|| (! DECL_CONSTRUCTOR_P (cand1->fn)
- && ! comptypes (TREE_TYPE (cand1->second_conv),
- TREE_TYPE (cand2->second_conv), 1))))
+ && ! same_type_p (TREE_TYPE (TREE_TYPE (cand1->fn)),
+ TREE_TYPE (TREE_TYPE (cand2->fn))))))
{
int comp = compare_ics (cand1->second_conv, cand2->second_conv);
if (comp != winner)
@@ -4392,8 +4389,8 @@ joust (cand1, cand2, warn)
&& TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
{
for (i = 0; i < len; ++i)
- if (! comptypes (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
- TREE_TYPE (TREE_VEC_ELT (cand2->convs, i)), 1))
+ if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
+ TREE_TYPE (TREE_VEC_ELT (cand2->convs, i))))
break;
if (i == TREE_VEC_LENGTH (cand1->convs))
return 1;
@@ -4408,7 +4405,7 @@ joust (cand1, cand2, warn)
tree t1 = strip_top_quals (non_reference (TREE_TYPE (c1)));
tree t2 = strip_top_quals (non_reference (TREE_TYPE (c2)));
- if (comptypes (t1, t2, 1))
+ if (same_type_p (t1, t2))
{
if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND)
return 1;
diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c
index 8a61bf8..400c67d 100644
--- a/contrib/gcc/cp/class.c
+++ b/contrib/gcc/cp/class.c
@@ -1,5 +1,5 @@
/* Functions related to building classes and their related objects.
- Copyright (C) 1987, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -30,66 +30,71 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "output.h"
#include "toplev.h"
+#include "splay-tree.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern struct obstack permanent_obstack;
-
/* This is how we tell when two virtual member functions are really the
same. */
#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
extern void set_class_shadows PROTO ((tree));
-/* Way of stacking class types. */
-static tree *current_class_base, *current_class_stack;
-static int current_class_stacksize;
+/* The number of nested classes being processed. If we are not in the
+ scope of any class, this is zero. */
+
int current_class_depth;
-struct class_level
-{
- /* The previous class level. */
- struct class_level *level_chain;
-
- /* The class instance variable, as a PARM_DECL. */
- tree decl;
- /* The class instance variable, as an object. */
- tree object;
- /* The virtual function table pointer
- for the class instance variable. */
- tree vtable_decl;
-
- /* Name of the current class. */
+/* In order to deal with nested classes, we keep a stack of classes.
+ The topmost entry is the innermost class, and is the entry at index
+ CURRENT_CLASS_DEPTH */
+
+typedef struct class_stack_node {
+ /* The name of the class. */
tree name;
- /* Type of the current class. */
+
+ /* The _TYPE node for the class. */
tree type;
- /* Flags for this class level. */
- int this_is_variable;
- int memoized_lookups;
- int save_memoized;
- int unused;
-};
+ /* The access specifier pending for new declarations in the scope of
+ this class. */
+ tree access;
-/* The current_class_ptr is the pointer to the current class.
- current_class_ref is the actual current class. */
+ /* If were defining TYPE, the names used in this class. */
+ splay_tree names_used;
+}* class_stack_node_t;
+
+/* The stack itself. This is an dynamically resized array. The
+ number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
+static int current_class_stack_size;
+static class_stack_node_t current_class_stack;
+
+/* When we're processing a member function, current_class_ptr is the
+ PARM_DECL for the `this' pointer. The current_class_ref is an
+ expression for `*this'. */
tree current_class_ptr, current_class_ref;
/* The following two can be derived from the previous one */
tree current_class_name; /* IDENTIFIER_NODE: name of current class */
tree current_class_type; /* _TYPE: the type of the current class */
+tree current_access_specifier;
tree previous_class_type; /* _TYPE: the previous type that was a class */
-tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list
+tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list
when leaving an outermost class scope. */
+/* The obstack on which the cached class declarations are kept. */
+static struct obstack class_cache_obstack;
+/* The first object allocated on that obstack. We can use
+ obstack_free with tis value to free the entire obstack. */
+char *class_cache_firstobj;
+
struct base_info;
static tree get_vfield_name PROTO((tree));
static void finish_struct_anon PROTO((tree));
static tree build_vbase_pointer PROTO((tree, tree));
-static int complete_type_p PROTO((tree));
static tree build_vtable_entry PROTO((tree, tree));
static tree get_vtable_name PROTO((tree));
static tree get_derived_offset PROTO((tree, tree));
@@ -99,7 +104,6 @@ static tree build_vtable PROTO((tree, tree));
static void prepare_fresh_vtable PROTO((tree, tree));
static void fixup_vtable_deltas1 PROTO((tree, tree));
static void fixup_vtable_deltas PROTO((tree, int, tree));
-static void grow_method PROTO((tree, tree *));
static void finish_vtbls PROTO((tree, int, tree));
static void modify_vtable_entry PROTO((tree, tree, tree));
static tree get_vtable_entry_n PROTO((tree, unsigned HOST_WIDE_INT));
@@ -115,7 +119,6 @@ static void merge_overrides PROTO((tree, tree, int, tree));
static void override_one_vtable PROTO((tree, tree, tree));
static void mark_overriders PROTO((tree, tree));
static void check_for_override PROTO((tree, tree));
-static tree maybe_fixup_vptrs PROTO((tree, tree, tree));
static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
static tree get_class_offset PROTO((tree, tree, tree, tree));
static void modify_one_vtable PROTO((tree, tree, tree, tree));
@@ -124,8 +127,16 @@ static void modify_all_direct_vtables PROTO((tree, int, tree, tree,
tree));
static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
tree, tree));
-static void build_class_init_list PROTO((tree));
static int finish_base_struct PROTO((tree, struct base_info *));
+static void finish_struct_methods PROTO((tree));
+static void maybe_warn_about_overly_private_class PROTO ((tree));
+static tree make_method_vec PROTO((int));
+static void free_method_vec PROTO((tree));
+static tree add_implicitly_declared_members PROTO((tree, int, int, int));
+static tree fixed_type_or_null PROTO((tree, int *));
+static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
+ int, tree));
+static void build_vtable_entry_ref PROTO((tree, tree, tree));
/* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack;
@@ -170,12 +181,12 @@ build_vbase_pointer (exp, type)
tree exp, type;
{
char *name;
+ FORMAT_VBASE_NAME (name, type);
- name = (char *) alloca (TYPE_NAME_LENGTH (type) + sizeof (VBASE_NAME) + 1);
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (type));
return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
}
+#if 0
/* Is the type of the EXPR, the complete type of the object?
If we are going to be wrong, we must be conservative, and return 0. */
@@ -221,6 +232,7 @@ complete_type_p (expr)
}
return 0;
}
+#endif
/* Build multi-level access to EXPR using hierarchy path PATH.
CODE is PLUS_EXPR if we are going with the grain,
@@ -229,17 +241,17 @@ complete_type_p (expr)
TYPE is the type we want this path to have on exit.
- ALIAS_THIS is non-zero if EXPR in an expression involving `this'. */
+ NONNULL is non-zero if we know (for any reason) that EXPR is
+ not, in fact, zero. */
tree
-build_vbase_path (code, type, expr, path, alias_this)
+build_vbase_path (code, type, expr, path, nonnull)
enum tree_code code;
tree type, expr, path;
- int alias_this;
+ int nonnull;
{
register int changed = 0;
tree last = NULL_TREE, last_virtual = NULL_TREE;
- int nonnull = 0;
int fixed_type_p;
tree null_expr = 0, nonnull_expr;
tree basetype;
@@ -248,40 +260,23 @@ build_vbase_path (code, type, expr, path, alias_this)
if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE)
return build1 (NOP_EXPR, type, expr);
- if (nonnull == 0 && (alias_this && flag_this_is_variable <= 0))
- nonnull = 1;
+ /* If -fthis-is-variable, we might have set nonnull incorrectly. We
+ don't care enough to get this right, so just clear it. */
+ if (flag_this_is_variable > 0)
+ nonnull = 0;
-#if 0
- /* We need additional logic to convert back to the unconverted type
- (the static type of the complete object), and then convert back
- to the type we want. Until that is done, or until we can
- recognize when that is, we cannot do the short cut logic. (mrs) */
+ /* We could do better if we had additional logic to convert back to the
+ unconverted type (the static type of the complete object), and then
+ convert back to the type we want. Until that is done, we only optimize
+ if the complete type is the same type as expr has. */
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
-#else
- /* Do this, until we can undo any previous conversions. See net35.C
- for a testcase. */
- fixed_type_p = complete_type_p (expr);
-#endif
if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
nonnull_expr = expr;
if (BINFO_INHERITANCE_CHAIN (path))
- {
- tree reverse_path = NULL_TREE;
-
- push_expression_obstack ();
- while (path)
- {
- tree r = copy_node (path);
- BINFO_INHERITANCE_CHAIN (r) = reverse_path;
- reverse_path = r;
- path = BINFO_INHERITANCE_CHAIN (path);
- }
- path = reverse_path;
- pop_obstacks ();
- }
+ path = reverse_path (path);
basetype = BINFO_TYPE (path);
@@ -308,8 +303,7 @@ build_vbase_path (code, type, expr, path, alias_this)
ind = build_indirect_ref (nonnull_expr, NULL_PTR);
nonnull_expr = build_vbase_pointer (ind, last_virtual);
if (nonnull == 0
- && (TREE_CODE (type) == POINTER_TYPE
- || !flag_assume_nonnull_objects)
+ && TREE_CODE (type) == POINTER_TYPE
&& null_expr == NULL_TREE)
{
null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node);
@@ -382,12 +376,7 @@ build_vbase_path (code, type, expr, path, alias_this)
expr = build1 (NOP_EXPR, type, expr);
#endif
- /* For multiple inheritance: if `this' can be set by any
- function, then it could be 0 on entry to any function.
- Preserve such zeroness here. Otherwise, only in the
- case of constructors need we worry, and in those cases,
- it will be zero, or initialized to some valid value to
- which we may add. */
+ /* If expr might be 0, we need to preserve that zeroness. */
if (nonnull == 0)
{
if (null_expr)
@@ -475,6 +464,36 @@ build_vtable_entry (delta, pfn)
}
}
+/* We want to give the assembler the vtable identifier as well as
+ the offset to the function pointer. So we generate
+
+ __asm__ __volatile__ (".vtable_entry %c0, %c1"
+ : : "s"(&class_vtable),
+ "i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */
+
+static void
+build_vtable_entry_ref (basetype, vtbl, idx)
+ tree basetype, vtbl, idx;
+{
+ static char asm_stmt[] = ".vtable_entry %c0, %c1";
+ tree s, i, i2;
+
+ s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
+ s = build_tree_list (build_string (1, "s"), s);
+
+ i = build_array_ref (vtbl, idx);
+ if (!flag_vtable_thunks)
+ i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0);
+ i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));
+ i2 = build_array_ref (vtbl, build_int_2(0,0));
+ i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0));
+ i = build_binary_op (MINUS_EXPR, i, i2);
+ i = build_tree_list (build_string (1, "i"), i);
+
+ expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt),
+ NULL_TREE, chainon (s, i), NULL_TREE, 1, NULL, 0);
+}
+
/* Given an object INSTANCE, return an expression which yields the
virtual function vtable element corresponding to INDEX. There are
many special cases for INSTANCE which we take care of here, mainly
@@ -491,8 +510,7 @@ build_vtbl_ref (instance, idx)
basetype = TREE_TYPE (basetype);
if (instance == current_class_ref)
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
- NULL_PTR);
+ vtbl = build_vfield_ref (instance, basetype);
else
{
if (optimize)
@@ -532,10 +550,14 @@ build_vtbl_ref (instance, idx)
|| TREE_CODE (instance) == VAR_DECL))
vtbl = TYPE_BINFO_VTABLE (basetype);
else
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
- NULL_PTR);
+ vtbl = build_vfield_ref (instance, basetype);
}
+
assemble_external (vtbl);
+
+ if (flag_vtable_gc)
+ build_vtable_entry_ref (basetype, vtbl, idx);
+
aref = build_array_ref (vtbl, idx);
return aref;
@@ -585,7 +607,7 @@ get_vtable_name (type)
tree type_id = build_typename_overload (type);
char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)
+ IDENTIFIER_LENGTH (type_id) + 2);
- char *ptr = IDENTIFIER_POINTER (type_id);
+ const char *ptr = IDENTIFIER_POINTER (type_id);
int i;
for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
#if 0
@@ -647,6 +669,9 @@ set_rtti_entry (virtuals, offset, type)
{
tree vfn;
+ if (CLASSTYPE_COM_INTERFACE (type))
+ return;
+
if (flag_rtti)
vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
else
@@ -685,7 +710,7 @@ build_vtable (binfo, type)
tree offset;
virtuals = copy_list (BINFO_VIRTUALS (binfo));
- decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
+ decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
/* Now do rtti stuff. */
offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
@@ -695,7 +720,7 @@ build_vtable (binfo, type)
else
{
virtuals = NULL_TREE;
- decl = build_decl (VAR_DECL, name, void_type_node);
+ decl = build_lang_decl (VAR_DECL, name, void_type_node);
}
#ifdef GATHER_STATISTICS
@@ -724,9 +749,7 @@ build_vtable (binfo, type)
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (decl));
- /* Why is this conditional? (mrs) */
- if (binfo && write_virtuals >= 0)
- DECL_VIRTUAL_P (decl) = 1;
+ DECL_VIRTUAL_P (decl) = 1;
DECL_CONTEXT (decl) = type;
binfo = TYPE_BINFO (type);
@@ -847,7 +870,7 @@ prepare_fresh_vtable (binfo, for_type)
buf2 = new_buf2;
}
- new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
+ new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
/* Remember which class this vtable is really for. */
DECL_CONTEXT (new_decl) = for_type;
@@ -1013,10 +1036,14 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
CLASSTYPE_RTTI (t) = t;
/* If we are using thunks, use two slots at the front, one
- for the offset pointer, one for the tdesc pointer. */
- if (*has_virtual == 0 && flag_vtable_thunks)
+ for the offset pointer, one for the tdesc pointer.
+ For ARM-style vtables, use the same slot for both. */
+ if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
{
- *has_virtual = 1;
+ if (flag_vtable_thunks)
+ *has_virtual = 2;
+ else
+ *has_virtual = 1;
}
/* Build a new INT_CST for this DECL_VINDEX. */
@@ -1024,7 +1051,7 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
static tree index_table[256];
tree idx;
/* We skip a slot for the offset/tdesc entry. */
- int i = ++(*has_virtual);
+ int i = (*has_virtual)++;
if (i >= 256 || index_table[i] == 0)
{
@@ -1058,122 +1085,230 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
struct obstack class_obstack;
extern struct obstack *current_obstack;
-/* Add method METHOD to class TYPE. This is used when a method
- has been defined which did not initially appear in the class definition,
- and helps cut down on spurious error messages.
+/* These are method vectors that were too small for the number of
+ methods in some class, and so were abandoned. */
+static tree free_method_vecs;
+
+/* Returns a method vector with enough room for N methods. N should
+ be a power of two. */
+
+static tree
+make_method_vec (n)
+ int n;
+{
+ tree new_vec;
+ tree* t;
+
+ for (t = &free_method_vecs; *t; t = &(TREE_CHAIN (*t)))
+ /* Note that we don't use >= n here because we don't want to
+ allocate a very large vector where it isn't needed. */
+ if (TREE_VEC_LENGTH (*t) == n)
+ {
+ new_vec = *t;
+ *t = TREE_CHAIN (new_vec);
+ TREE_CHAIN (new_vec) = NULL_TREE;
+ bzero ((PTR) &TREE_VEC_ELT (new_vec, 0), n * sizeof (tree));
+ return new_vec;
+ }
+
+ new_vec = make_tree_vec (n);
+ return new_vec;
+}
+
+/* Free the method vector VEC. */
- FIELDS is the entry in the METHOD_VEC vector entry of the class type where
- the method should be added. */
+static void
+free_method_vec (vec)
+ tree vec;
+{
+ TREE_CHAIN (vec) = free_method_vecs;
+ free_method_vecs = vec;
+}
+
+/* Add method METHOD to class TYPE.
+
+ If non-NULL, FIELDS is the entry in the METHOD_VEC vector entry of
+ the class type where the method should be added. */
void
add_method (type, fields, method)
tree type, *fields, method;
{
- push_obstacks (&permanent_obstack, &permanent_obstack);
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
+ redundant. */
+ DECL_CONTEXT (method) = type;
+ DECL_CLASS_CONTEXT (method) = type;
+
if (fields && *fields)
- *fields = build_overload (method, *fields);
- else if (CLASSTYPE_METHOD_VEC (type) == 0)
- {
- tree method_vec = make_node (TREE_VEC);
- if (TYPE_IDENTIFIER (type) == DECL_NAME (method))
- {
- /* ??? Is it possible for there to have been enough room in the
- current chunk for the tree_vec structure but not a tree_vec
- plus a tree*? Will this work in that case? */
- obstack_free (current_obstack, method_vec);
- obstack_blank (current_obstack, sizeof (struct tree_vec) + sizeof (tree *));
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)))
- TREE_VEC_ELT (method_vec, 1) = method;
- else
- TREE_VEC_ELT (method_vec, 0) = method;
- TREE_VEC_LENGTH (method_vec) = 2;
- }
- else
- {
- /* ??? Is it possible for there to have been enough room in the
- current chunk for the tree_vec structure but not a tree_vec
- plus a tree*? Will this work in that case? */
- obstack_free (current_obstack, method_vec);
- obstack_blank (current_obstack, sizeof (struct tree_vec) + 2*sizeof (tree *));
- TREE_VEC_ELT (method_vec, 2) = method;
- TREE_VEC_LENGTH (method_vec) = 3;
- obstack_finish (current_obstack);
- }
- CLASSTYPE_METHOD_VEC (type) = method_vec;
- }
- else
- {
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
- int len = TREE_VEC_LENGTH (method_vec);
-
- /* Adding a new ctor or dtor. This is easy because our
- METHOD_VEC always has a slot for such entries. */
- if (TYPE_IDENTIFIER (type) == DECL_NAME (method))
- {
- int idx = !!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method));
- /* TREE_VEC_ELT (method_vec, idx) = method; */
- if (method != TREE_VEC_ELT (method_vec, idx))
- TREE_VEC_ELT (method_vec, idx) =
- build_overload (method, TREE_VEC_ELT (method_vec, idx));
- }
+ *fields = build_overload (method, *fields);
+ else
+ {
+ int len;
+ int slot;
+ tree method_vec;
+
+ if (!CLASSTYPE_METHOD_VEC (type))
+ /* Make a new method vector. We start with 8 entries. We must
+ allocate at least two (for constructors and destructors), and
+ we're going to end up with an assignment operator at some
+ point as well.
+
+ We could use a TREE_LIST for now, and convert it to a
+ TREE_VEC in finish_struct, but we would probably waste more
+ memory making the links in the list than we would by
+ over-allocating the size of the vector here. Furthermore,
+ we would complicate all the code that expects this to be a
+ vector. We keep a free list of vectors that we outgrew so
+ that we don't really waste any memory. */
+ CLASSTYPE_METHOD_VEC (type) = make_method_vec (8);
+
+ method_vec = CLASSTYPE_METHOD_VEC (type);
+ len = TREE_VEC_LENGTH (method_vec);
+
+ if (DECL_NAME (method) == constructor_name (type))
+ /* A new constructor or destructor. Constructors go in
+ slot 0; destructors go in slot 1. */
+ slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
else
{
- /* This is trickier. We try to extend the TREE_VEC in-place,
- but if that does not work, we copy all its data to a new
- TREE_VEC that's large enough. */
- struct obstack *ob = &class_obstack;
- tree *end = (tree *)obstack_next_free (ob);
-
- if (end != TREE_VEC_END (method_vec))
+ /* See if we already have an entry with this name. */
+ for (slot = 2; slot < len; ++slot)
+ if (!TREE_VEC_ELT (method_vec, slot)
+ || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
+ slot)))
+ == DECL_NAME (method)))
+ break;
+
+ if (slot == len)
{
- ob = current_obstack;
- TREE_VEC_LENGTH (method_vec) += 1;
- TREE_VEC_ELT (method_vec, len) = NULL_TREE;
- method_vec = copy_node (method_vec);
- TREE_VEC_LENGTH (method_vec) -= 1;
+ /* We need a bigger method vector. */
+ tree new_vec = make_method_vec (2 * len);
+ bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0),
+ (PTR) &TREE_VEC_ELT (new_vec, 0),
+ len * sizeof (tree));
+ free_method_vec (method_vec);
+ len = 2 * len;
+ method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
}
- else
+
+ if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
{
- tree tmp_vec = (tree) obstack_base (ob);
- if (obstack_room (ob) < sizeof (tree))
+ /* Type conversion operators have to come before
+ ordinary methods; add_conversions depends on this to
+ speed up looking for conversion operators. So, if
+ necessary, we slide some of the vector elements up.
+ In theory, this makes this algorithm O(N^2) but we
+ don't expect many conversion operators. */
+ for (slot = 2; slot < len; ++slot)
{
- obstack_blank (ob, sizeof (struct tree_common)
- + tree_code_length[(int) TREE_VEC]
- * sizeof (char *)
- + len * sizeof (tree));
- tmp_vec = (tree) obstack_base (ob);
- bcopy ((char *) method_vec, (char *) tmp_vec,
- (sizeof (struct tree_common)
- + tree_code_length[(int) TREE_VEC] * sizeof (char *)
- + (len-1) * sizeof (tree)));
- method_vec = tmp_vec;
+ tree fn = TREE_VEC_ELT (method_vec, slot);
+
+ if (!fn)
+ /* There are no more entries in the vector, so we
+ can insert the new conversion operator here. */
+ break;
+
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ /* We can insert the new function right at the
+ SLOTth position. */
+ break;
}
+
+ if (!TREE_VEC_ELT (method_vec, slot))
+ /* There is nothing in the Ith slot, so we can avoid
+ moving anything. */
+ ;
else
- obstack_blank (ob, sizeof (tree));
+ {
+ /* We know the last slot in the vector is empty
+ because we know that at this point there's room
+ for a new function. */
+ bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot),
+ (PTR) &TREE_VEC_ELT (method_vec, slot + 1),
+ (len - slot - 1) * sizeof (tree));
+ TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
+ }
}
+ }
+
+ if (template_class_depth (type))
+ /* TYPE is a template class. Don't issue any errors now; wait
+ until instantiation time to complain. */
+ ;
+ else
+ {
+ tree fns;
- obstack_finish (ob);
- TREE_VEC_ELT (method_vec, len) = method;
- TREE_VEC_LENGTH (method_vec) = len + 1;
- CLASSTYPE_METHOD_VEC (type) = method_vec;
-
- if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type))
+ /* Check to see if we've already got this method. */
+ for (fns = TREE_VEC_ELT (method_vec, slot);
+ fns;
+ fns = OVL_NEXT (fns))
{
- /* ??? May be better to know whether these can be extended? */
- tree baselink_vec = CLASSTYPE_BASELINK_VEC (type);
+ tree fn = OVL_CURRENT (fns);
+
+ if (TREE_CODE (fn) != TREE_CODE (method))
+ continue;
+
+ if (TREE_CODE (method) != TEMPLATE_DECL)
+ {
+ /* [over.load] Member function declarations with the
+ same name and the same parameter types cannot be
+ overloaded if any of them is a static member
+ function declaration. */
+ if (DECL_STATIC_FUNCTION_P (fn)
+ != DECL_STATIC_FUNCTION_P (method))
+ {
+ tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
- TREE_VEC_LENGTH (baselink_vec) += 1;
- CLASSTYPE_BASELINK_VEC (type) = copy_node (baselink_vec);
- TREE_VEC_LENGTH (baselink_vec) -= 1;
+ if (! DECL_STATIC_FUNCTION_P (fn))
+ parms1 = TREE_CHAIN (parms1);
+ else
+ parms2 = TREE_CHAIN (parms2);
+
+ if (compparms (parms1, parms2))
+ cp_error ("`%#D' and `%#D' cannot be overloaded",
+ fn, method);
+ }
+
+ /* Since this is an ordinary function in a
+ non-template class, it's mangled name can be used
+ as a unique identifier. This technique is only
+ an optimization; we would get the same results if
+ we just used decls_match here. */
+ if (DECL_ASSEMBLER_NAME (fn)
+ != DECL_ASSEMBLER_NAME (method))
+ continue;
+ }
+ else if (!decls_match (fn, method))
+ continue;
- TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), len) = 0;
+ /* There has already been a declaration of this method
+ or member template. */
+ cp_error_at ("`%D' has already been declared in `%T'",
+ method, type);
+
+ /* We don't call duplicate_decls here to merge the
+ declarations because that will confuse things if the
+ methods have inline definitions. In particular, we
+ will crash while processing the definitions. */
+ return;
}
}
- }
- DECL_CONTEXT (method) = type;
- DECL_CLASS_CONTEXT (method) = type;
+ /* Actually insert the new method. */
+ TREE_VEC_ELT (method_vec, slot)
+ = build_overload (method, TREE_VEC_ELT (method_vec, slot));
+
+ /* Add the new binding. */
+ if (!DECL_CONSTRUCTOR_P (method)
+ && !DECL_DESTRUCTOR_P (method))
+ push_class_level_binding (DECL_NAME (method),
+ TREE_VEC_ELT (method_vec, slot));
+ }
pop_obstacks ();
}
@@ -1240,7 +1375,7 @@ delete_duplicate_fields_1 (field, fields)
else if (DECL_DECLARES_TYPE_P (field)
&& DECL_DECLARES_TYPE_P (x))
{
- if (comptypes (TREE_TYPE (field), TREE_TYPE (x), 1))
+ if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
continue;
cp_error_at ("duplicate nested type `%D'", x);
}
@@ -1310,7 +1445,6 @@ alter_access (t, binfo, fdecl, access)
else
{
enforce_access (binfo, fdecl);
-
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
@@ -1318,10 +1452,9 @@ alter_access (t, binfo, fdecl, access)
}
/* Process the USING_DECL, which is a member of T. The METHOD_VEC, if
- non-NULL, is the methods of T. The FIELDS are the fields of T.
- Returns 1 if the USING_DECL was valid, 0 otherwise. */
+ non-NULL, is the methods of T. The FIELDS are the fields of T. */
-void
+static void
handle_using_decl (using_decl, t, method_vec, fields)
tree using_decl;
tree t;
@@ -1346,8 +1479,11 @@ handle_using_decl (using_decl, t, method_vec, fields)
if (name == constructor_name (ctype)
|| name == constructor_name_full (ctype))
- cp_error_at ("using-declaration for constructor", using_decl);
-
+ {
+ cp_error_at ("using-declaration for constructor", using_decl);
+ return;
+ }
+
fdecl = lookup_member (binfo, name, 0, 0);
if (!fdecl)
@@ -1372,7 +1508,7 @@ handle_using_decl (using_decl, t, method_vec, fields)
name = DECL_NAME (fdecl);
n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
- for (i = 2; i < n_methods; i++)
+ for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); i++)
if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
== name)
{
@@ -1408,174 +1544,11 @@ handle_using_decl (using_decl, t, method_vec, fields)
else
alter_access (t, binfo, fdecl, access);
}
-
-/* If FOR_TYPE needs to reinitialize virtual function table pointers
- for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
- Returns BASE_INIT_LIST appropriately modified. */
-
-static tree
-maybe_fixup_vptrs (for_type, binfo, base_init_list)
- tree for_type, binfo, base_init_list;
-{
- /* Now reinitialize any slots that don't fall under our virtual
- function table pointer. */
- tree vfields = CLASSTYPE_VFIELDS (BINFO_TYPE (binfo));
- while (vfields)
- {
- tree basetype = VF_NORMAL_VALUE (vfields)
- ? TYPE_MAIN_VARIANT (VF_NORMAL_VALUE (vfields))
- : VF_BASETYPE_VALUE (vfields);
-
- tree base_binfo = get_binfo (basetype, for_type, 0);
- /* Punt until this is implemented. */
- if (1 /* BINFO_MODIFIED (base_binfo) */)
- {
- tree base_offset = get_vfield_offset (base_binfo);
- if (! tree_int_cst_equal (base_offset, get_vfield_offset (TYPE_BINFO (for_type)))
- && ! tree_int_cst_equal (base_offset, get_vfield_offset (binfo)))
- base_init_list = tree_cons (error_mark_node, base_binfo,
- base_init_list);
- }
- vfields = TREE_CHAIN (vfields);
- }
- return base_init_list;
-}
-
-/* If TYPE does not have a constructor, then the compiler must
- manually deal with all of the initialization this type requires.
-
- If a base initializer exists only to fill in the virtual function
- table pointer, then we mark that fact with the TREE_VIRTUAL bit.
- This way, we avoid multiple initializations of the same field by
- each virtual function table up the class hierarchy.
-
- Virtual base class pointers are not initialized here. They are
- initialized only at the "top level" of object creation. If we
- initialized them here, we would have to skip a lot of work. */
-
-static void
-build_class_init_list (type)
- tree type;
-{
- tree base_init_list = NULL_TREE;
- tree member_init_list = NULL_TREE;
-
- /* Since we build member_init_list and base_init_list using
- tree_cons, backwards fields the all through work. */
- tree x;
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (x = TYPE_FIELDS (type); x; x = TREE_CHAIN (x))
- {
- if (TREE_CODE (x) != FIELD_DECL)
- continue;
-
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (x))
- || DECL_INITIAL (x) != NULL_TREE)
- member_init_list = tree_cons (x, type, member_init_list);
- }
- member_init_list = nreverse (member_init_list);
-
- /* We will end up doing this last. Need special marker
- to avoid infinite regress. */
- if (TYPE_VIRTUAL_P (type))
- {
- base_init_list = build_tree_list (error_mark_node, TYPE_BINFO (type));
- if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (type) == 0)
- TREE_VALUE (base_init_list) = NULL_TREE;
- TREE_ADDRESSABLE (base_init_list) = 1;
- }
-
- /* Each base class which needs to have initialization
- of some kind gets to make such requests known here. */
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree blist;
-
- /* Don't initialize virtual baseclasses this way. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- /* ...and the last shall come first... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- continue;
- }
-
- if ((blist = CLASSTYPE_BASE_INIT_LIST (BINFO_TYPE (base_binfo))) == NULL_TREE)
- /* Nothing to initialize. */
- continue;
-
- /* ...ditto... */
- base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list);
-
- /* This is normally true for single inheritance.
- The win is we can shrink the chain of initializations
- to be done by only converting to the actual type
- we are interested in. */
- if (TREE_VALUE (blist)
- && TREE_CODE (TREE_VALUE (blist)) == TREE_VEC
- && tree_int_cst_equal (BINFO_OFFSET (base_binfo),
- BINFO_OFFSET (TREE_VALUE (blist))))
- {
- if (base_init_list)
- {
- /* Does it do more than just fill in a
- virtual function table pointer? */
- if (! TREE_ADDRESSABLE (blist))
- base_init_list = build_tree_list (blist, base_init_list);
- /* Can we get by just with the virtual function table
- pointer that it fills in? */
- else if (TREE_ADDRESSABLE (base_init_list)
- && TREE_VALUE (base_init_list) == 0)
- base_init_list = blist;
- /* Maybe, but it is not obvious as the previous case. */
- else if (! CLASSTYPE_NEEDS_VIRTUAL_REINIT (type))
- {
- tree last = tree_last (base_init_list);
- while (TREE_VALUE (last)
- && TREE_CODE (TREE_VALUE (last)) == TREE_LIST)
- last = tree_last (TREE_VALUE (last));
- if (TREE_VALUE (last) == 0)
- base_init_list = build_tree_list (blist, base_init_list);
- }
- }
- else
- base_init_list = blist;
- }
- else
- {
- /* The function expand_aggr_init knows how to do the
- initialization of `basetype' without getting
- an explicit `blist'. */
- if (base_init_list)
- base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list);
- else
- base_init_list = CLASSTYPE_BINFO_AS_LIST (BINFO_TYPE (base_binfo));
- }
- }
-
- if (base_init_list)
- {
- if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) =
- build_tree_list (base_init_list, member_init_list);
- else
- CLASSTYPE_BASE_INIT_LIST (type) = base_init_list;
- }
- else if (member_init_list)
- CLASSTYPE_BASE_INIT_LIST (type) = member_init_list;
-}
struct base_info
{
int has_virtual;
int max_has_virtual;
- int n_ancestors;
tree vfield;
tree vfields;
tree rtti;
@@ -1658,7 +1631,6 @@ finish_base_struct (t, b)
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype))
b->no_const_asn_ref = 1;
- b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
@@ -1668,8 +1640,20 @@ finish_base_struct (t, b)
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
- if (! TREE_VIA_VIRTUAL (base_binfo))
- CLASSTYPE_N_SUPERCLASSES (t) += 1;
+ if (CLASSTYPE_COM_INTERFACE (basetype))
+ {
+ CLASSTYPE_COM_INTERFACE (t) = 1;
+ if (i > 0)
+ cp_error
+ ("COM interface type `%T' must be the leftmost base class",
+ basetype);
+ }
+ else if (CLASSTYPE_COM_INTERFACE (t))
+ {
+ cp_error ("COM interface type `%T' with non-COM base class `%T'",
+ t, basetype);
+ CLASSTYPE_COM_INTERFACE (t) = 0;
+ }
if (TYPE_VIRTUAL_P (basetype))
{
@@ -1766,35 +1750,6 @@ finish_base_struct (t, b)
}
}
- /* This comment said "Must come after offsets are fixed for all bases."
- Well, now this happens before the offsets are fixed, but it seems to
- work fine. Guess we'll see... */
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree basetype = BINFO_TYPE (base_binfo);
-
- if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
- {
- cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
- }
- }
- {
- tree v = get_vbase_types (t);
-
- for (; v; v = TREE_CHAIN (v))
- {
- tree basetype = BINFO_TYPE (v);
- if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
- {
- if (extra_warnings)
- cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
- }
- }
- }
-
{
tree vfields;
/* Find the base class with the largest number of virtual functions. */
@@ -1854,24 +1809,15 @@ finish_struct_bits (t, max_has_virtual)
if (n_baseclasses && max_has_virtual)
{
- /* Done by `finish_struct' for classes without baseclasses. */
- int might_have_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0;
- tree binfos = TYPE_BINFO_BASETYPES (t);
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- might_have_abstract_virtuals
- |= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0);
- if (might_have_abstract_virtuals)
- break;
- }
- if (might_have_abstract_virtuals)
- {
- /* We use error_mark_node from override_one_vtable to signal
- an artificial abstract. */
- if (CLASSTYPE_ABSTRACT_VIRTUALS (t) == error_mark_node)
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = NULL_TREE;
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
- }
+ /* For a class w/o baseclasses, `finish_struct' has set
+ CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition). Similarly
+ for a class who's base classes do not have vtables. When neither
+ of these is true, we might have removed abstract virtuals (by
+ providing a definition), added some (by declaring new ones), or
+ redeclared ones from a base class. We need to recalculate what's
+ really an abstract virtual at this point (by looking in the
+ vtables). */
+ CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
}
if (n_baseclasses)
@@ -1886,8 +1832,6 @@ finish_struct_bits (t, max_has_virtual)
basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype);
- if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t))
- CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1;
}
}
@@ -1913,39 +1857,157 @@ finish_struct_bits (t, max_has_virtual)
}
}
-/* Add FNDECL to the method_vec growing on the class_obstack. Used by
- finish_struct_methods. Note, FNDECL cannot be a constructor or
- destructor, those cases are handled by the caller. */
+/* Issue warnings about T having private constructors, but no friends,
+ and so forth.
+
+ HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or
+ static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any
+ non-private static member functions. */
static void
-grow_method (fndecl, method_vec_ptr)
- tree fndecl;
- tree *method_vec_ptr;
+maybe_warn_about_overly_private_class (t)
+ tree t;
{
- tree method_vec = (tree)obstack_base (&class_obstack);
+ int has_member_fn = 0;
+ int has_nonprivate_method = 0;
+ tree fn;
+
+ if (!warn_ctor_dtor_privacy
+ /* If the class has friends, those entities might create and
+ access instances, so we should not warn. */
+ || (CLASSTYPE_FRIEND_CLASSES (t)
+ || DECL_FRIENDLIST (TYPE_MAIN_DECL (t)))
+ /* We will have warned when the template was declared; there's
+ no need to warn on every instantiation. */
+ || CLASSTYPE_TEMPLATE_INSTANTIATION (t))
+ /* There's no reason to even consider warning about this
+ class. */
+ return;
+
+ /* We only issue one warning, if more than one applies, because
+ otherwise, on code like:
+
+ class A {
+ // Oops - forgot `public:'
+ A();
+ A(const A&);
+ ~A();
+ };
+
+ we warn several times about essentially the same problem. */
+
+ /* Check to see if all (non-constructor, non-destructor) member
+ functions are private. (Since there are no friends or
+ non-private statics, we can't ever call any of the private member
+ functions.) */
+ for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
+ /* We're not interested in compiler-generated methods; they don't
+ provide any way to call private members. */
+ if (!DECL_ARTIFICIAL (fn))
+ {
+ if (!TREE_PRIVATE (fn))
+ {
+ if (DECL_STATIC_FUNCTION_P (fn))
+ /* A non-private static member function is just like a
+ friend; it can create and invoke private member
+ functions, and be accessed without a class
+ instance. */
+ return;
+
+ has_nonprivate_method = 1;
+ break;
+ }
+ else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
+ has_member_fn = 1;
+ }
+
+ if (!has_nonprivate_method && has_member_fn)
+ {
+ /* There are no non-private methods, and there's at least one
+ private member function that isn't a constructor or
+ destructor. (If all the private members are
+ constructors/destructors we want to use the code below that
+ issues error messages specifically referring to
+ constructors/destructors.) */
+ int i;
+ tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++)
+ if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
+ || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))
+ {
+ has_nonprivate_method = 1;
+ break;
+ }
+ if (!has_nonprivate_method)
+ {
+ cp_warning ("all member functions in class `%T' are private", t);
+ return;
+ }
+ }
- /* Start off past the constructors and destructor. */
- tree *testp = &TREE_VEC_ELT (method_vec, 2);
+ /* Even if some of the member functions are non-private, the class
+ won't be useful for much if all the constructors or destructors
+ are private: such an object can never be created or destroyed. */
+ if (TYPE_HAS_DESTRUCTOR (t))
+ {
+ tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
- while (testp < (tree *) obstack_next_free (&class_obstack)
- && (*testp == NULL_TREE || DECL_NAME (OVL_CURRENT (*testp)) != DECL_NAME (fndecl)))
- testp++;
+ if (TREE_PRIVATE (dtor))
+ {
+ cp_warning ("`%#T' only defines a private destructor and has no friends",
+ t);
+ return;
+ }
+ }
- if (testp < (tree *) obstack_next_free (&class_obstack))
- *testp = build_overload (fndecl, *testp);
- else
+ if (TYPE_HAS_CONSTRUCTOR (t))
{
- obstack_ptr_grow (&class_obstack, fndecl);
- *method_vec_ptr = (tree)obstack_base (&class_obstack);
+ int nonprivate_ctor = 0;
+
+ /* If a non-template class does not define a copy
+ constructor, one is defined for it, enabling it to avoid
+ this warning. For a template class, this does not
+ happen, and so we would normally get a warning on:
+
+ template <class T> class C { private: C(); };
+
+ To avoid this asymmetry, we check TYPE_HAS_INIT_REF. All
+ complete non-template or fully instantiated classes have this
+ flag set. */
+ if (!TYPE_HAS_INIT_REF (t))
+ nonprivate_ctor = 1;
+ else
+ for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
+ fn;
+ fn = OVL_NEXT (fn))
+ {
+ tree ctor = OVL_CURRENT (fn);
+ /* Ideally, we wouldn't count copy constructors (or, in
+ fact, any constructor that takes an argument of the
+ class type as a parameter) because such things cannot
+ be used to construct an instance of the class unless
+ you already have one. But, for now at least, we're
+ more generous. */
+ if (! TREE_PRIVATE (ctor))
+ {
+ nonprivate_ctor = 1;
+ break;
+ }
+ }
+
+ if (nonprivate_ctor == 0)
+ {
+ cp_warning ("`%#T' only defines private constructors and has no friends",
+ t);
+ return;
+ }
}
}
+
/* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster.
- Algorithm: Outer loop builds lists by method name. Inner loop
- checks for redundant method names within a list.
-
Data Structure: List of method lists. The outer list is a
TREE_LIST, whose TREE_PURPOSE field is the field name and the
TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN
@@ -1961,35 +2023,20 @@ grow_method (fndecl, method_vec_ptr)
We also link each field which has shares a name with its baseclass
to the head of the list of fields for that base class. This allows
us to reduce search time in places like `build_method_call' to
- consider only reasonably likely functions. */
+ consider only reasonably likely functions. */
-tree
-finish_struct_methods (t, fn_fields, nonprivate_method)
+static void
+finish_struct_methods (t)
tree t;
- tree fn_fields;
- int nonprivate_method;
{
- tree method_vec;
- tree save_fn_fields = fn_fields;
+ tree fn_fields;
+ tree method_vec = CLASSTYPE_METHOD_VEC (t);
tree ctor_name = constructor_name (t);
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
-
- /* Now prepare to gather fn_fields into vector. */
- struct obstack *ambient_obstack = current_obstack;
- current_obstack = &class_obstack;
- method_vec = make_tree_vec (2);
- current_obstack = ambient_obstack;
-
- /* Now make this a live vector. */
- obstack_free (&class_obstack, method_vec);
-
- /* Save room for constructors and destructors. */
- obstack_blank (&class_obstack, sizeof (struct tree_vec) + sizeof (struct tree *));
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
-
- for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
+ for (fn_fields = TYPE_METHODS (t); fn_fields;
+ fn_fields = TREE_CHAIN (fn_fields))
{
tree fn_name = DECL_NAME (fn_fields);
@@ -2020,32 +2067,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
}
}
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields)))
- {
- /* Destructors go in slot 1. */
- TREE_VEC_ELT (method_vec, 1) =
- build_overload (fn_fields, TREE_VEC_ELT (method_vec, 1));
- }
- else
- {
- /* Constructors go in slot 0. */
- TREE_VEC_ELT (method_vec, 0) =
- build_overload (fn_fields, TREE_VEC_ELT (method_vec, 0));
- }
- }
- else if (IDENTIFIER_TYPENAME_P (fn_name))
- grow_method (fn_fields, &method_vec);
- }
-
- fn_fields = save_fn_fields;
- for (; fn_fields; fn_fields = TREE_CHAIN (fn_fields))
- {
- tree fn_name = DECL_NAME (fn_fields);
-
- if (fn_name == ctor_name || IDENTIFIER_TYPENAME_P (fn_name))
- continue;
-
- if (fn_name == ansi_opname[(int) MODIFY_EXPR])
+ }
+ else if (fn_name == ansi_opname[(int) MODIFY_EXPR])
{
tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
@@ -2057,75 +2080,16 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 2;
}
}
-
- grow_method (fn_fields, &method_vec);
}
- TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
- - (&TREE_VEC_ELT (method_vec, 0));
- obstack_finish (&class_obstack);
- CLASSTYPE_METHOD_VEC (t) = method_vec;
-
- if (nonprivate_method == 0
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE)
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
- for (i = 0; i < n_baseclasses; i++)
- if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))
- || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))
- {
- nonprivate_method = 1;
- break;
- }
- if (nonprivate_method == 0
- && warn_ctor_dtor_privacy)
- cp_warning ("all member functions in class `%T' are private", t);
- }
-
- /* Warn if all destructors are private (in which case this class is
- effectively unusable. */
- if (TYPE_HAS_DESTRUCTOR (t))
- {
- tree dtor = TREE_VEC_ELT (method_vec, 1);
-
- /* Wild parse errors can cause this to happen. */
- if (dtor == NULL_TREE)
- TYPE_HAS_DESTRUCTOR (t) = 0;
- else if (TREE_PRIVATE (dtor)
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE
- && warn_ctor_dtor_privacy)
- cp_warning ("`%#T' only defines a private destructor and has no friends",
- t);
- }
-
- /* Now for each member function (except for constructors and
- destructors), compute where member functions of the same
- name reside in base classes. */
- if (n_baseclasses != 0
- && TREE_VEC_LENGTH (method_vec) > 2)
- {
- int len = TREE_VEC_LENGTH (method_vec);
- tree baselink_vec = make_tree_vec (len);
- int any_links = 0;
- tree baselink_binfo = build_tree_list (NULL_TREE, TYPE_BINFO (t));
-
- for (i = 2; i < len; i++)
- {
- TREE_VEC_ELT (baselink_vec, i)
- = get_baselinks (baselink_binfo, t,
- DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))));
- if (TREE_VEC_ELT (baselink_vec, i) != 0)
- any_links = 1;
- }
- if (any_links != 0)
- CLASSTYPE_BASELINK_VEC (t) = baselink_vec;
- else
- obstack_free (current_obstack, baselink_vec);
- }
-
- return method_vec;
+ if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1))
+ /* We thought there was a destructor, but there wasn't. Some
+ parse errors cause this anomalous situation. */
+ TYPE_HAS_DESTRUCTOR (t) = 0;
+
+ /* Issue warnings about private constructors and such. If there are
+ no methods, then some public defaults are generated. */
+ maybe_warn_about_overly_private_class (t);
}
/* Emit error when a duplicate definition of a type is seen. Patch up. */
@@ -2164,18 +2128,14 @@ duplicate_tag_error (t)
if (TYPE_LANG_SPECIFIC (t))
{
- tree as_list = CLASSTYPE_AS_LIST (t);
tree binfo = TYPE_BINFO (t);
- tree binfo_as_list = CLASSTYPE_BINFO_AS_LIST (t);
int interface_only = CLASSTYPE_INTERFACE_ONLY (t);
int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t);
bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
- CLASSTYPE_AS_LIST (t) = as_list;
TYPE_BINFO (t) = binfo;
- CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
TYPE_REDEFINED (t) = 1;
@@ -2209,8 +2169,7 @@ finish_vtbls (binfo, do_self, t)
decl = BINFO_VTABLE (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
- if (write_virtuals >= 0
- && DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
+ if (DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
BINFO_VIRTUALS (binfo));
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
@@ -2255,9 +2214,9 @@ overrides (fndecl, base_fndecl)
#endif
types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
- if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (base_types)))
- == TYPE_READONLY (TREE_TYPE (TREE_VALUE (types))))
- && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types), 3))
+ if ((TYPE_QUALS (TREE_TYPE (TREE_VALUE (base_types)))
+ == TYPE_QUALS (TREE_TYPE (TREE_VALUE (types))))
+ && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types)))
return 1;
}
return 0;
@@ -2347,11 +2306,14 @@ get_class_offset (context, t, binfo, fndecl)
/* Skip RTTI information at the front of the virtual list. */
unsigned HOST_WIDE_INT
-skip_rtti_stuff (virtuals)
- tree *virtuals;
+skip_rtti_stuff (virtuals, t)
+ tree *virtuals, t;
{
int n;
+ if (CLASSTYPE_COM_INTERFACE (t))
+ return 0;
+
n = 0;
if (*virtuals)
{
@@ -2393,7 +2355,7 @@ modify_one_vtable (binfo, t, fndecl, pfn)
if (fndecl == NULL_TREE)
return;
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
@@ -2421,10 +2383,6 @@ modify_one_vtable (binfo, t, fndecl, pfn)
BINFO_OFFSET (binfo));
this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
- /* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (binfo))
- my_friendly_assert (0, 999);
-
if (binfo == TYPE_BINFO (t))
{
/* In this case, it is *type*'s vtable we are modifying.
@@ -2491,7 +2449,7 @@ fixup_vtable_deltas1 (binfo, t)
tree virtuals = BINFO_VIRTUALS (binfo);
unsigned HOST_WIDE_INT n;
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
@@ -2524,9 +2482,6 @@ fixup_vtable_deltas1 (binfo, t)
if (! tree_int_cst_equal (this_offset, delta))
{
/* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (binfo))
- my_friendly_assert (0, 999);
-
if (binfo == TYPE_BINFO (t))
{
/* In this case, it is *type*'s vtable we are modifying.
@@ -2667,8 +2622,8 @@ override_one_vtable (binfo, old, t)
if (BINFO_NEW_VTABLE_MARKED (binfo))
choose = NEITHER;
- skip_rtti_stuff (&virtuals);
- skip_rtti_stuff (&old_virtuals);
+ skip_rtti_stuff (&virtuals, t);
+ skip_rtti_stuff (&old_virtuals, t);
while (virtuals)
{
@@ -2729,13 +2684,11 @@ override_one_vtable (binfo, old, t)
}
{
/* This MUST be overridden, or the class is ill-formed. */
- /* For now, we just make it abstract. */
tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
tree vfn;
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
- DECL_ABSTRACT_VIRTUAL_P (fndecl) = 1;
DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1;
/* Make sure we search for it later. */
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
@@ -2832,18 +2785,18 @@ get_basefndecls (fndecl, t)
/* Mark the functions that have been hidden with their overriders.
Since we start out with all functions already marked with a hider,
- no need to mark functions that are just hidden. */
+ no need to mark functions that are just hidden.
+
+ Subroutine of warn_hidden. */
static void
mark_overriders (fndecl, base_fndecls)
tree fndecl, base_fndecls;
{
- while (base_fndecls)
+ for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
{
- if (overrides (TREE_VALUE (base_fndecls), fndecl))
+ if (overrides (fndecl, TREE_VALUE (base_fndecls)))
TREE_PURPOSE (base_fndecls) = fndecl;
-
- base_fndecls = TREE_CHAIN (base_fndecls);
}
}
@@ -2858,17 +2811,18 @@ check_for_override (decl, ctype)
tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int virtualp = DECL_VIRTUAL_P (decl);
+ int found_overriden_fn = 0;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
- || flag_all_virtual == 1)
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)))
{
tree tmp = get_matching_virtual
(base_binfo, decl,
DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
- if (tmp)
+
+ if (tmp && !found_overriden_fn)
{
/* If this function overrides some virtual in some base
class, then the function itself is also necessarily
@@ -2889,26 +2843,15 @@ check_for_override (decl, ctype)
}
virtualp = 1;
-#if 0 /* The signature of an overriding function is not changed. */
- {
- /* The argument types may have changed... */
- tree type = TREE_TYPE (decl);
- tree argtypes = TYPE_ARG_TYPES (type);
- tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
- tree raises = TYPE_RAISES_EXCEPTIONS (type);
-
- argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
- TREE_CHAIN (argtypes));
- /* But the return type has not. */
- type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
- if (raises)
- type = build_exception_variant (type, raises);
- TREE_TYPE (decl) = type;
- }
-#endif
DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
- break;
+
+ /* We now know that DECL overrides something,
+ which is all that is important. But, we must
+ continue to iterate through all the base-classes
+ in order to allow get_matching_virtual to check for
+ various illegal overrides. */
+ found_overriden_fn = 1;
}
}
}
@@ -2932,7 +2875,7 @@ warn_hidden (t)
int i;
/* We go through each separately named virtual function. */
- for (i = 2; i < n_methods; ++i)
+ for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i)
{
tree fns = TREE_VEC_ELT (method_vec, i);
tree fndecl;
@@ -2941,8 +2884,15 @@ warn_hidden (t)
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- fndecl = OVL_CURRENT (fns);
- if (DECL_VINDEX (fndecl) == NULL_TREE)
+ /* First see if we have any virtual functions in this batch. */
+ for (; fns; fns = OVL_NEXT (fns))
+ {
+ fndecl = OVL_CURRENT (fns);
+ if (DECL_VINDEX (fndecl))
+ break;
+ }
+
+ if (fns == NULL_TREE)
continue;
/* First we get a list of all possible functions that might be
@@ -2957,38 +2907,28 @@ warn_hidden (t)
}
fns = OVL_NEXT (fns);
- if (fns)
- fndecl = OVL_CURRENT (fns);
- else
- fndecl = NULL_TREE;
/* ...then mark up all the base functions with overriders, preferring
overriders to hiders. */
if (base_fndecls)
- while (fndecl)
+ for (; fns; fns = OVL_NEXT (fns))
{
- mark_overriders (fndecl, base_fndecls);
-
- fns = OVL_NEXT (fns);
- if (fns)
- fndecl = OVL_CURRENT (fns);
- else
- fndecl = NULL_TREE;
+ fndecl = OVL_CURRENT (fns);
+ if (DECL_VINDEX (fndecl))
+ mark_overriders (fndecl, base_fndecls);
}
/* Now give a warning for all base functions without overriders,
as they are hidden. */
- while (base_fndecls)
+ for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
{
- if (! overrides (TREE_VALUE (base_fndecls),
- TREE_PURPOSE (base_fndecls)))
+ if (! overrides (TREE_PURPOSE (base_fndecls),
+ TREE_VALUE (base_fndecls)))
{
/* Here we know it is a hider, and no overrider exists. */
cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls));
}
-
- base_fndecls = TREE_CHAIN (base_fndecls);
}
}
}
@@ -3014,9 +2954,20 @@ finish_struct_anon (t)
tree* uelt = &TYPE_FIELDS (TREE_TYPE (field));
for (; *uelt; uelt = &TREE_CHAIN (*uelt))
{
- if (TREE_CODE (*uelt) != FIELD_DECL)
+ if (DECL_ARTIFICIAL (*uelt))
continue;
+ if (DECL_NAME (*uelt) == constructor_name (t))
+ cp_pedwarn_at ("ANSI C++ forbids member `%D' with same name as enclosing class",
+ *uelt);
+
+ if (TREE_CODE (*uelt) != FIELD_DECL)
+ {
+ cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
+ *uelt);
+ continue;
+ }
+
if (TREE_PRIVATE (*uelt))
cp_pedwarn_at ("private member `%#D' in anonymous union",
*uelt);
@@ -3033,6 +2984,90 @@ finish_struct_anon (t)
extern int interface_only, interface_unknown;
+/* Create default constructors, assignment operators, and so forth for
+ the type indicated by T, if they are needed.
+ CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
+ CANT_HAVE_ASSIGNMENT are nonzero if, for whatever reason, the class
+ cannot have a default constructor, copy constructor taking a const
+ reference argument, or an assignment operator, respectively. If a
+ virtual destructor is created, its DECL is returned; otherwise the
+ return value is NULL_TREE. */
+
+static tree
+add_implicitly_declared_members (t, cant_have_default_ctor,
+ cant_have_const_cctor,
+ cant_have_assignment)
+ tree t;
+ int cant_have_default_ctor;
+ int cant_have_const_cctor;
+ int cant_have_assignment;
+{
+ tree default_fn;
+ tree implicit_fns = NULL_TREE;
+ tree name = TYPE_IDENTIFIER (t);
+ tree virtual_dtor = NULL_TREE;
+ tree *f;
+
+ /* Destructor. */
+ if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
+ && !IS_SIGNATURE (t))
+ {
+ default_fn = cons_up_default_function (t, name, 0);
+ check_for_override (default_fn, t);
+
+ /* If we couldn't make it work, then pretend we didn't need it. */
+ if (default_fn == void_type_node)
+ TYPE_NEEDS_DESTRUCTOR (t) = 0;
+ else
+ {
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+
+ if (DECL_VINDEX (default_fn))
+ virtual_dtor = default_fn;
+ }
+ }
+ TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
+
+ /* Default constructor. */
+ if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor
+ && ! IS_SIGNATURE (t))
+ {
+ default_fn = cons_up_default_function (t, name, 2);
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+ }
+
+ /* Copy constructor. */
+ if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
+ {
+ /* ARM 12.18: You get either X(X&) or X(const X&), but
+ not both. --Chip */
+ default_fn = cons_up_default_function (t, name,
+ 3 + cant_have_const_cctor);
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+ }
+
+ /* Assignment operator. */
+ if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
+ {
+ default_fn = cons_up_default_function (t, name,
+ 5 + cant_have_assignment);
+ TREE_CHAIN (default_fn) = implicit_fns;
+ implicit_fns = default_fn;
+ }
+
+ /* Now, hook all of the new functions on to TYPE_METHODS,
+ and add them to the CLASSTYPE_METHOD_VEC. */
+ for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
+ add_method (t, 0, *f);
+ *f = TYPE_METHODS (t);
+ TYPE_METHODS (t) = implicit_fns;
+
+ return virtual_dtor;
+}
+
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
@@ -3058,54 +3093,17 @@ extern int interface_only, interface_unknown;
inheritance. Additional virtual function tables have different
DELTAs, which tell how to adjust `this' to point to the right thing.
- LIST_OF_FIELDLISTS is just that. The elements of the list are
- TREE_LIST elements, whose TREE_PURPOSE field tells what access
- the list has, and the TREE_VALUE slot gives the actual fields.
-
- ATTRIBUTES is the set of decl attributes to be applied, if any.
-
- If flag_all_virtual == 1, then we lay all functions into
- the virtual function table, as though they were declared
- virtual. Constructors do not lay down in the virtual function table.
-
- If flag_all_virtual == 2, then we lay all functions into
- the virtual function table, such that virtual functions
- occupy a space by themselves, and then all functions
- of the class occupy a space by themselves. This is illustrated
- in the following diagram:
-
- class A; class B : A;
-
- Class A's vtbl: Class B's vtbl:
- --------------------------------------------------------------------
- | A's virtual functions| | B's virtual functions |
- | | | (may inherit some from A). |
- --------------------------------------------------------------------
- | All of A's functions | | All of A's functions |
- | (such as a->A::f). | | (such as b->A::f) |
- --------------------------------------------------------------------
- | B's new virtual functions |
- | (not defined in A.) |
- -------------------------------
- | All of B's functions |
- | (such as b->B::f) |
- -------------------------------
-
- this allows the program to make references to any function, virtual
- or otherwise in a type-consistent manner. */
+ ATTRIBUTES is the set of decl attributes to be applied, if any. */
-tree
+void
finish_struct_1 (t, warn_anon)
tree t;
int warn_anon;
{
int old;
- tree name = TYPE_IDENTIFIER (t);
enum tree_code code = TREE_CODE (t);
tree fields = TYPE_FIELDS (t);
- tree fn_fields = TYPE_METHODS (t);
tree x, last_x, method_vec;
- int all_virtual;
int has_virtual;
int max_has_virtual;
tree pending_virtuals = NULL_TREE;
@@ -3113,9 +3111,11 @@ finish_struct_1 (t, warn_anon)
tree abstract_virtuals = NULL_TREE;
tree vfield;
tree vfields;
+ tree virtual_dtor;
int cant_have_default_ctor;
int cant_have_const_ctor;
int no_const_asn_ref;
+ int has_mutable = 0;
/* The index of the first base class which has virtual
functions. Only applied to non-virtual baseclasses. */
@@ -3125,11 +3125,11 @@ finish_struct_1 (t, warn_anon)
int any_default_members = 0;
int const_sans_init = 0;
int ref_sans_init = 0;
- int nonprivate_method = 0;
tree access_decls = NULL_TREE;
int aggregate = 1;
int empty = 1;
int has_pointers = 0;
+ tree inline_friends;
if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
pedwarn ("anonymous class type not used to declare any objects");
@@ -3140,8 +3140,8 @@ finish_struct_1 (t, warn_anon)
cp_error ("redefinition of `%#T'", t);
else
my_friendly_abort (172);
- popclass (0);
- return t;
+ popclass ();
+ return;
}
GNU_xref_decl (current_function_decl, t);
@@ -3185,7 +3185,6 @@ finish_struct_1 (t, warn_anon)
CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
has_virtual = base_info.has_virtual;
max_has_virtual = base_info.max_has_virtual;
- CLASSTYPE_N_SUPERCLASSES (t) += base_info.n_ancestors;
vfield = base_info.vfield;
vfields = base_info.vfields;
CLASSTYPE_RTTI (t) = base_info.rtti;
@@ -3223,25 +3222,14 @@ finish_struct_1 (t, warn_anon)
CLASSTYPE_VFIELDS (t) = vfields;
CLASSTYPE_VFIELD (t) = vfield;
- if (IS_SIGNATURE (t))
- all_virtual = 0;
- else if (flag_all_virtual == 1)
- all_virtual = 1;
- else
- all_virtual = 0;
-
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
GNU_xref_member (current_class_name, x);
- nonprivate_method |= ! TREE_PRIVATE (x);
-
/* If this was an evil function, don't keep it in class. */
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
continue;
- DECL_CLASS_CONTEXT (x) = t;
-
/* Do both of these, even though they're in the same union;
if the insn `r' member and the size `i' member are
different sizes, as on the alpha, the larger of the two
@@ -3255,8 +3243,7 @@ finish_struct_1 (t, warn_anon)
/* The name of the field is the original field name
Save this in auxiliary field for later overloading. */
- if (DECL_VINDEX (x)
- || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x)))
+ if (DECL_VINDEX (x))
{
add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
&has_virtual, x, t);
@@ -3281,7 +3268,11 @@ finish_struct_1 (t, warn_anon)
if (TREE_CODE (x) == FIELD_DECL)
{
DECL_PACKED (x) |= TYPE_PACKED (t);
- empty = 0;
+
+ if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
+ /* A zero-width bitfield doesn't do the trick. */;
+ else
+ empty = 0;
}
if (TREE_CODE (x) == USING_DECL)
@@ -3387,8 +3378,11 @@ finish_struct_1 (t, warn_anon)
if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE)
has_pointers = 1;
+ if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (TREE_TYPE (x)))
+ has_mutable = 1;
+
/* If any field is const, the structure type is pseudo-const. */
- if (TREE_READONLY (x))
+ if (CP_TYPE_CONST_P (TREE_TYPE (x)))
{
C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
@@ -3426,12 +3420,10 @@ finish_struct_1 (t, warn_anon)
}
}
- /* We set DECL_BIT_FIELD tentatively in grokbitfield.
- If the type and width are valid, we'll keep it set.
- Otherwise, the flag is cleared. */
- if (DECL_BIT_FIELD (x))
+ /* We set DECL_C_BIT_FIELD in grokbitfield.
+ If the type and width are valid, we'll also set DECL_BIT_FIELD. */
+ if (DECL_C_BIT_FIELD (x))
{
- DECL_BIT_FIELD (x) = 0;
/* Invalid bit-field size done by grokfield. */
/* Detect invalid bit-field type. */
if (DECL_INITIAL (x)
@@ -3499,23 +3491,24 @@ finish_struct_1 (t, warn_anon)
x, TREE_TYPE (x));
}
- if (DECL_INITIAL (x) == NULL_TREE)
- ;
- else if (width == 0)
+ if (DECL_INITIAL (x))
{
+ DECL_INITIAL (x) = NULL_TREE;
+ DECL_FIELD_SIZE (x) = width;
+ DECL_BIT_FIELD (x) = 1;
+
+ if (width == 0)
+ {
#ifdef EMPTY_FIELD_BOUNDARY
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
+ DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+ EMPTY_FIELD_BOUNDARY);
#endif
#ifdef PCC_BITFIELD_TYPE_MATTERS
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
- TYPE_ALIGN (TREE_TYPE (x)));
+ if (PCC_BITFIELD_TYPE_MATTERS)
+ DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+ TYPE_ALIGN (TREE_TYPE (x)));
#endif
- }
- else
- {
- DECL_INITIAL (x) = NULL_TREE;
- DECL_FIELD_SIZE (x) = width;
- DECL_BIT_FIELD (x) = 1;
+ }
}
}
else
@@ -3543,7 +3536,7 @@ finish_struct_1 (t, warn_anon)
if (code == UNION_TYPE)
{
- char *fie = NULL;
+ const char *fie = NULL;
if (TYPE_NEEDS_CONSTRUCTING (type))
fie = "constructor";
else if (TYPE_NEEDS_DESTRUCTOR (type))
@@ -3604,36 +3597,7 @@ finish_struct_1 (t, warn_anon)
CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
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 (! fn_fields)
- nonprivate_method = 1;
-
- if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
- && !IS_SIGNATURE (t))
- {
- /* Here we must cons up a destructor on the fly. */
- tree dtor = cons_up_default_function (t, name, 0);
- check_for_override (dtor, t);
-
- /* If we couldn't make it work, then pretend we didn't need it. */
- if (dtor == void_type_node)
- TYPE_NEEDS_DESTRUCTOR (t) = 0;
- else
- {
- /* Link dtor onto end of fn_fields. */
-
- TREE_CHAIN (dtor) = fn_fields;
- fn_fields = dtor;
-
- if (DECL_VINDEX (dtor))
- add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
- &has_virtual, dtor, t);
- nonprivate_method = 1;
- }
- }
+ CLASSTYPE_HAS_MUTABLE (t) = has_mutable;
/* Effective C++ rule 11. */
if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
@@ -3650,9 +3614,9 @@ finish_struct_1 (t, warn_anon)
else if (! TYPE_HAS_ASSIGN_REF (t))
cp_warning (" but does not override `operator=(const %T&)'", t);
}
-
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
-
+
+ /* Do some bookkeeping that will guide the generation of implicitly
+ declared member functions. */
TYPE_HAS_COMPLEX_INIT_REF (t)
|= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
|| has_virtual || any_default_members);
@@ -3662,68 +3626,24 @@ finish_struct_1 (t, warn_anon)
if (! IS_SIGNATURE (t))
CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
-
- /* ARM $12.1: A default constructor will be generated for a class X
- only if no constructor has been declared for class X. So we
- check TYPE_HAS_CONSTRUCTOR also, to make sure we don't generate
- one if they declared a constructor in this class. */
- if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor
- && ! IS_SIGNATURE (t))
- {
- tree default_fn = cons_up_default_function (t, name, 2);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- }
-
- /* Create default copy constructor, if needed. */
- if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
- {
- /* ARM 12.18: You get either X(X&) or X(const X&), but
- not both. --Chip */
- tree default_fn = cons_up_default_function (t, name,
- 3 + cant_have_const_ctor);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- }
-
- TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t);
TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
- if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
- {
- tree default_fn = cons_up_default_function (t, name,
- 5 + no_const_asn_ref);
- TREE_CHAIN (default_fn) = fn_fields;
- fn_fields = default_fn;
- }
+ /* Synthesize any needed methods. Note that methods will be synthesized
+ for anonymous unions; grok_x_components undoes that. */
+ virtual_dtor
+ = add_implicitly_declared_members (t, cant_have_default_ctor,
+ cant_have_const_ctor,
+ no_const_asn_ref);
+ if (virtual_dtor)
+ add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
+ &has_virtual, virtual_dtor, t);
- if (fn_fields)
+ if (TYPE_METHODS (t))
{
- TYPE_METHODS (t) = fn_fields;
- method_vec = finish_struct_methods (t, fn_fields, nonprivate_method);
-
- if (TYPE_HAS_CONSTRUCTOR (t)
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_MAIN_DECL (t)) == NULL_TREE)
- {
- int nonprivate_ctor = 0;
- tree ctor;
-
- for (ctor = TREE_VEC_ELT (method_vec, 0);
- ctor;
- ctor = OVL_NEXT (ctor))
- if (! TREE_PRIVATE (OVL_CURRENT (ctor)))
- {
- nonprivate_ctor = 1;
- break;
- }
-
- if (nonprivate_ctor == 0 && warn_ctor_dtor_privacy)
- cp_warning ("`%#T' only defines private constructors and has no friends",
- t);
- }
+ finish_struct_methods (t);
+ method_vec = CLASSTYPE_METHOD_VEC (t);
}
else
{
@@ -3741,10 +3661,27 @@ finish_struct_1 (t, warn_anon)
if (vfield == NULL_TREE && has_virtual)
{
- /* We build this decl with ptr_type_node, and
- change the type when we know what it should be. */
+ /* We build this decl with vtbl_ptr_type_node, which is a
+ `vtable_entry_type*'. It might seem more precise to use
+ `vtable_entry_type (*)[N]' where N is the number of firtual
+ functions. However, that would require the vtable pointer in
+ base classes to have a different type than the vtable pointer
+ in derived classes. We could make that happen, but that
+ still wouldn't solve all the problems. In particular, the
+ type-based alias analysis code would decide that assignments
+ to the base class vtable pointer can't alias assignments to
+ the derived class vtable pointer, since they have different
+ types. Thus, in an derived class destructor, where the base
+ class constructor was inlined, we could generate bad code for
+ setting up the vtable pointer.
+
+ Therefore, we use one type for all vtable pointers. We still
+ use a type-correct type; it's just doesn't indicate the array
+ bounds. That's better than using `void*' or some such; it's
+ cleaner, and it let's the alias analysis code know that these
+ stores cannot alias stores to void*! */
vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t),
- ptr_type_node);
+ vtbl_ptr_type_node);
/* If you change any of the below, take a look at all the
other VFIELD_BASEs and VTABLE_BASEs in the code, and change
them too. */
@@ -3776,57 +3713,17 @@ finish_struct_1 (t, warn_anon)
fields = vfield;
#endif
empty = 0;
- vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
+ vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
}
/* Now DECL_INITIAL is null on all members except for zero-width bit-fields.
- And they have already done their work.
C++: maybe we will support default field initialization some day... */
- /* Delete all zero-width bit-fields from the front of the fieldlist */
- while (fields && DECL_BIT_FIELD (fields)
- && DECL_INITIAL (fields))
- fields = TREE_CHAIN (fields);
- /* Delete all such fields from the rest of the fields. */
- for (x = fields; x;)
- {
- if (TREE_CHAIN (x) && DECL_BIT_FIELD (TREE_CHAIN (x))
- && DECL_INITIAL (TREE_CHAIN (x)))
- TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
- else
- x = TREE_CHAIN (x);
- }
/* Delete all duplicate fields from the 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 = 2;
-
- if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
- continue;
-
- for (; i < n_methods; ++i)
- if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
- == name)
- {
- cp_error_at ("data member `%#D' conflicts with", x);
- cp_error_at ("function member `%#D'",
- OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
- break;
- }
- }
- }
-
- /* Now we have the final fieldlist for the data fields. Record it,
+ /* Now we have the nearly final fieldlist for the data fields. Record it,
then lay out the structure or union (including the fields). */
TYPE_FIELDS (t) = fields;
@@ -3840,6 +3737,13 @@ finish_struct_1 (t, warn_anon)
if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
}
+
+ /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
+ we have to save this before we start modifying
+ TYPE_NONCOPIED_PARTS. */
+ inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
+ CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
+
if (empty)
{
/* C++: do not let empty structures exist. */
@@ -3847,7 +3751,11 @@ finish_struct_1 (t, warn_anon)
(FIELD_DECL, NULL_TREE, char_type_node);
TREE_CHAIN (decl) = fields;
TYPE_FIELDS (t) = decl;
+ TYPE_NONCOPIED_PARTS (t)
+ = tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
+ TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
+
if (n_baseclasses)
TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
@@ -3880,15 +3788,31 @@ finish_struct_1 (t, warn_anon)
if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */
max_has_virtual = layout_basetypes (t, max_has_virtual);
- else if (empty)
+ if (empty)
TYPE_FIELDS (t) = fields;
+ my_friendly_assert (TYPE_FIELDS (t) == fields, 981117);
+
+ /* Delete all zero-width bit-fields from the front of the fieldlist */
+ while (fields && DECL_C_BIT_FIELD (fields)
+ && DECL_INITIAL (fields))
+ fields = TREE_CHAIN (fields);
+ /* Delete all such fields from the rest of the fields. */
+ for (x = fields; x;)
+ {
+ if (TREE_CHAIN (x) && DECL_C_BIT_FIELD (TREE_CHAIN (x))
+ && DECL_INITIAL (TREE_CHAIN (x)))
+ TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
+ else
+ x = TREE_CHAIN (x);
+ }
+ TYPE_FIELDS (t) = fields;
+
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree vbases;
vbases = CLASSTYPE_VBASECLASSES (t);
- CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
{
/* Now fixup overrides of all functions in vtables from all
@@ -3983,15 +3907,18 @@ finish_struct_1 (t, warn_anon)
/* We must enter these virtuals into the table. */
if (first_vfn_base_index < 0)
{
- /* The second slot is for the tdesc pointer when thunks are used. */
- if (flag_vtable_thunks)
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+ if (! CLASSTYPE_COM_INTERFACE (t))
+ {
+ /* The second slot is for the tdesc pointer when thunks are used. */
+ if (flag_vtable_thunks)
+ pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
- /* The first slot is for the rtti offset. */
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+ /* The first slot is for the rtti offset. */
+ pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
- set_rtti_entry (pending_virtuals,
- convert (ssizetype, integer_zero_node), t);
+ set_rtti_entry (pending_virtuals,
+ convert (ssizetype, integer_zero_node), t);
+ }
build_vtable (NULL_TREE, t);
}
else
@@ -4040,46 +3967,22 @@ finish_struct_1 (t, warn_anon)
else if (has_virtual)
{
TYPE_BINFO_VIRTUALS (t) = pending_virtuals;
- if (write_virtuals >= 0)
- DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1;
+ DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1;
}
}
/* Now lay out the virtual function table. */
if (has_virtual)
{
- tree atype, itype;
+ /* Use size_int so values are memoized in common cases. */
+ tree itype = build_index_type (size_int (has_virtual));
+ tree atype = build_cplus_array_type (vtable_entry_type, itype);
- if (TREE_TYPE (vfield) == ptr_type_node)
- {
- /* We must create a pointer to this table because
- the one inherited from base class does not exist.
- We will fill in the type when we know what it
- should really be. Use `size_int' so values are memoized
- in common cases. */
- itype = build_index_type (size_int (has_virtual));
- atype = build_array_type (vtable_entry_type, itype);
- layout_type (atype);
- TREE_TYPE (vfield) = build_pointer_type (atype);
- }
- else
- {
- atype = TREE_TYPE (TREE_TYPE (vfield));
-
- if (has_virtual != TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))))
- {
- /* We must extend (or create) the boundaries on this array,
- because we picked up virtual functions from multiple
- base classes. */
- itype = build_index_type (size_int (has_virtual));
- atype = build_array_type (vtable_entry_type, itype);
- layout_type (atype);
- vfield = copy_node (vfield);
- TREE_TYPE (vfield) = build_pointer_type (atype);
- }
- }
+ layout_type (atype);
CLASSTYPE_VFIELD (t) = vfield;
+
+ /* We may have to grow the vtable. */
if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype)
{
TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype;
@@ -4123,15 +4026,10 @@ finish_struct_1 (t, warn_anon)
TREE_ADDRESSABLE (vfields) = 1;
vfields = TREE_CHAIN (vfields);
}
- if (any_default_members != 0)
- build_class_init_list (t);
}
- else if (TYPE_NEEDS_CONSTRUCTING (t))
- build_class_init_list (t);
/* Write out inline function definitions. */
- do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t));
- CLASSTYPE_INLINE_FRIENDS (t) = 0;
+ do_inline_function_hair (t, inline_friends);
if (CLASSTYPE_VSIZE (t) != 0)
{
@@ -4158,7 +4056,9 @@ finish_struct_1 (t, warn_anon)
/* In addition to this one, all the other vfields should be listed. */
/* Before that can be done, we have to have FIELD_DECLs for them, and
a place to find them. */
- TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield);
+ TYPE_NONCOPIED_PARTS (t)
+ = tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)),
+ vfield, TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
@@ -4207,14 +4107,9 @@ finish_struct_1 (t, warn_anon)
references between translation units. */
if (CLASSTYPE_METHOD_VEC (t))
{
- extern tree pending_vtables;
-
/* Don't output full info about any type
which does not have its implementation defined here. */
- if (TYPE_VIRTUAL_P (t) && write_virtuals == 2)
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t))
- = (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0);
- else if (CLASSTYPE_INTERFACE_ONLY (t))
+ if (CLASSTYPE_INTERFACE_ONLY (t))
TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
#if 0
/* XXX do something about this. */
@@ -4230,23 +4125,50 @@ finish_struct_1 (t, warn_anon)
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel_bindings_p ());
- return t;
+ return;
+}
+
+/* When T was built up, the member declarations were added in reverse
+ order. Rearrange them to declaration order. */
+
+void
+unreverse_member_declarations (t)
+ tree t;
+{
+ tree next;
+ tree prev;
+ tree x;
+
+ /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in
+ reverse order. Put them in declaration order now. */
+ TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
+ CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t));
+
+ /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
+ reverse order, so we can't just use nreverse. */
+ prev = NULL_TREE;
+ for (x = TYPE_FIELDS (t);
+ x && TREE_CODE (x) != TYPE_DECL;
+ x = next)
+ {
+ next = TREE_CHAIN (x);
+ TREE_CHAIN (x) = prev;
+ prev = x;
+ }
+ if (prev)
+ {
+ TREE_CHAIN (TYPE_FIELDS (t)) = x;
+ if (prev)
+ TYPE_FIELDS (t) = prev;
+ }
}
tree
-finish_struct (t, list_of_fieldlists, attributes, warn_anon)
- tree t, list_of_fieldlists, attributes;
+finish_struct (t, attributes, warn_anon)
+ tree t, attributes;
int warn_anon;
{
- tree fields = NULL_TREE;
- tree *tail = &TYPE_METHODS (t);
- tree specializations = NULL_TREE;
- tree *specialization_tail = &specializations;
tree name = TYPE_NAME (t);
- tree x, last_x = NULL_TREE;
- tree access;
- tree dummy = NULL_TREE;
- tree next_x = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
@@ -4260,166 +4182,16 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
will fill in the right line number. (mrs) */
if (DECL_SOURCE_LINE (name))
DECL_SOURCE_LINE (name) = lineno;
- CLASSTYPE_SOURCE_LINE (t) = lineno;
name = DECL_NAME (name);
}
/* Append the fields we need for constructing signature tables. */
if (IS_SIGNATURE (t))
- append_signature_fields (list_of_fieldlists);
-
- /* Move our self-reference declaration to the end of the field list so
- any real field with the same name takes precedence. */
- if (list_of_fieldlists
- && TREE_VALUE (list_of_fieldlists)
- && DECL_ARTIFICIAL (TREE_VALUE (list_of_fieldlists)))
- {
- dummy = TREE_VALUE (list_of_fieldlists);
- list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
- }
-
- if (last_x && list_of_fieldlists)
- TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
-
- while (list_of_fieldlists)
- {
- access = TREE_PURPOSE (list_of_fieldlists);
-
- /* For signatures, we made all methods `public' in the parser and
- reported an error if a access specifier was used. */
- if (access == access_default_node)
- {
- if (CLASSTYPE_DECLARED_CLASS (t) == 0)
- access = access_public_node;
- else
- access = access_private_node;
- }
-
- for (x = TREE_VALUE (list_of_fieldlists); x; x = next_x)
- {
- next_x = TREE_CHAIN (x);
-
- TREE_PRIVATE (x) = access == access_private_node;
- TREE_PROTECTED (x) = access == access_protected_node;
-
- if (TREE_CODE (x) == TEMPLATE_DECL)
- {
- TREE_PRIVATE (DECL_RESULT (x)) = TREE_PRIVATE (x);
- TREE_PROTECTED (DECL_RESULT (x)) = TREE_PROTECTED (x);
- }
-
- /* A name N used in a class S shall refer to the same declaration
- in its context and when re-evaluated in the completed scope of S.
-
- Enums, types and static vars have already been checked. */
- if (TREE_CODE (x) != TYPE_DECL && TREE_CODE (x) != USING_DECL
- && ! (TREE_CODE (x) == TEMPLATE_DECL
- && TREE_CODE (DECL_RESULT (x)) == TYPE_DECL)
- && TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
- {
- tree name = DECL_NAME (x);
- tree icv;
-
- /* Don't get confused by access decls. */
- if (name && TREE_CODE (name) == IDENTIFIER_NODE)
- icv = IDENTIFIER_CLASS_VALUE (name);
- else
- icv = NULL_TREE;
-
- if (icv
- && flag_optional_diags
- /* Don't complain about constructors. */
- && name != constructor_name (current_class_type)
- /* Or inherited names. */
- && id_in_current_class (name)
- /* Or shadowed tags. */
- && !(TREE_CODE (icv) == TYPE_DECL
- && DECL_CONTEXT (icv) == t))
- {
- cp_pedwarn_at ("declaration of identifier `%D' as `%+#D'",
- name, x);
- cp_pedwarn_at ("conflicts with other use in class as `%#D'",
- icv);
- }
- }
-
- if (TREE_CODE (x) == FUNCTION_DECL
- || DECL_FUNCTION_TEMPLATE_P (x))
- {
- DECL_CLASS_CONTEXT (x) = t;
-
- if (last_x)
- TREE_CHAIN (last_x) = next_x;
-
- if (DECL_TEMPLATE_SPECIALIZATION (x))
- /* We don't enter the specialization into the class
- method vector since specializations don't affect
- overloading. Instead we keep track of the
- specializations, and process them after the method
- vector is complete. */
- {
- *specialization_tail = x;
- specialization_tail = &TREE_CHAIN (x);
- TREE_CHAIN (x) = NULL_TREE;
- continue;
- }
-
- /* Link x onto end of TYPE_METHODS. */
- *tail = x;
- tail = &TREE_CHAIN (x);
- continue;
- }
+ append_signature_fields (t);
- if (TREE_CODE (x) != TYPE_DECL)
- DECL_FIELD_CONTEXT (x) = t;
-
- if (! fields)
- fields = x;
- last_x = x;
- }
- list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
- /* link the tail while we have it! */
- if (last_x)
- {
- TREE_CHAIN (last_x) = NULL_TREE;
-
- if (list_of_fieldlists
- && TREE_VALUE (list_of_fieldlists)
- && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL)
- TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
- }
- }
-
- /* Now add the tags, if any, to the list of TYPE_DECLs
- defined for this type. */
- if (CLASSTYPE_TAGS (t) || dummy)
- {
- /* The list of tags was built up in pushtag in reverse order; we need
- to fix that so that enumerators will be processed in forward order
- in template instantiation. */
- CLASSTYPE_TAGS (t) = x = nreverse (CLASSTYPE_TAGS (t));
- while (x)
- {
- tree tag_type = TREE_VALUE (x);
- tree tag = TYPE_MAIN_DECL (TREE_VALUE (x));
-
- if (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
- && CLASSTYPE_IS_TEMPLATE (tag_type))
- tag = CLASSTYPE_TI_TEMPLATE (tag_type);
-
- TREE_NONLOCAL_FLAG (tag_type) = 0;
- x = TREE_CHAIN (x);
- last_x = chainon (last_x, tag);
- }
- if (dummy)
- last_x = chainon (last_x, dummy);
- if (fields == NULL_TREE)
- fields = last_x;
- CLASSTYPE_LOCAL_TYPEDECLS (t) = 1;
- }
-
- *tail = NULL_TREE;
- TYPE_FIELDS (t) = fields;
+ /* Now that we've got all the field declarations, reverse everything
+ as necessary. */
+ unreverse_member_declarations (t);
cplus_decl_attributes (t, attributes, NULL_TREE);
@@ -4443,80 +4215,31 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
= tree_cons (NULL_TREE, d,
DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)));
}
- CLASSTYPE_METHOD_VEC (t)
- = finish_struct_methods (t, TYPE_METHODS (t), 1);
+ finish_struct_methods (t);
TYPE_SIZE (t) = integer_zero_node;
}
else
- t = finish_struct_1 (t, warn_anon);
+ finish_struct_1 (t, warn_anon);
TYPE_BEING_DEFINED (t) = 0;
- /* Now, figure out which member templates we're specializing. */
- for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x))
- {
- tree spec_args;
- tree fn;
- int pending_specialization;
-
- if (uses_template_parms (t))
- /* If t is a template class, and x is a specialization, then x
- is itself really a template. Due to the vagaries of the
- parser, however, we will have a handle to a function
- declaration, rather than the template declaration, at this
- point. */
- {
- my_friendly_assert (DECL_TEMPLATE_INFO (x) != NULL_TREE, 0);
- my_friendly_assert (DECL_TI_TEMPLATE (x) != NULL_TREE, 0);
- fn = DECL_TI_TEMPLATE (x);
- }
- else
- fn = x;
-
- /* We want the specialization arguments, which will be the
- innermost ones. */
- if (DECL_TI_ARGS (fn) && TREE_CODE (DECL_TI_ARGS (fn)) == TREE_VEC)
- spec_args
- = TREE_VEC_ELT (DECL_TI_ARGS (fn), 0);
- else
- spec_args = DECL_TI_ARGS (fn);
-
- pending_specialization
- = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn));
- check_explicit_specialization
- (lookup_template_function (DECL_NAME (fn), spec_args),
- fn, 0, 1 | (8 * pending_specialization));
- TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)) = 0;
-
- /* Now, the assembler name will be correct for fn, so we
- make its RTL. */
- DECL_RTL (fn) = 0;
- make_decl_rtl (fn, NULL_PTR, 1);
-
- if (x != fn)
- {
- DECL_RTL (x) = 0;
- make_decl_rtl (x, NULL_PTR, 1);
- }
- }
-
if (current_class_type)
- popclass (0);
+ popclass ();
else
error ("trying to finish struct, but kicked out due to previous parse errors.");
return t;
}
-/* Return non-zero if the effective type of INSTANCE is static.
+/* Return the dynamic type of INSTANCE, if known.
Used to determine whether the virtual function table is needed
or not.
*NONNULL is set iff INSTANCE can be known to be nonnull, regardless
of our knowledge of its type. */
-int
-resolves_to_fixed_type_p (instance, nonnull)
+static tree
+fixed_type_or_null (instance, nonnull)
tree instance;
int *nonnull;
{
@@ -4534,9 +4257,9 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (instance);
}
- return 0;
+ return NULL_TREE;
case SAVE_EXPR:
/* This is a call to a constructor, hence it's never zero. */
@@ -4544,33 +4267,33 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (instance);
}
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case RTL_EXPR:
- return 0;
+ return NULL_TREE;
case PLUS_EXPR:
case MINUS_EXPR:
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
- resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
- return 0;
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
+ return NULL_TREE;
case NOP_EXPR:
case CONVERT_EXPR:
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case ADDR_EXPR:
if (nonnull)
*nonnull = 1;
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case COMPONENT_REF:
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull);
case VAR_DECL:
case FIELD_DECL:
@@ -4579,7 +4302,7 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (TREE_TYPE (instance));
}
/* fall through... */
case TARGET_EXPR:
@@ -4588,37 +4311,65 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
- return 1;
+ return TREE_TYPE (instance);
}
else if (nonnull)
{
if (instance == current_class_ptr
&& flag_this_is_variable <= 0)
{
- /* Some people still use `this = 0' inside destructors. */
- *nonnull = ! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (current_function_decl));
- /* In a constructor, we know our type. */
+ /* Normally, 'this' must be non-null. */
+ if (flag_this_is_variable == 0)
+ *nonnull = 1;
+
+ /* <0 means we're in a constructor and we know our type. */
if (flag_this_is_variable < 0)
- return 1;
+ return TREE_TYPE (TREE_TYPE (instance));
}
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
/* Reference variables should be references to objects. */
*nonnull = 1;
}
- return 0;
+ return NULL_TREE;
default:
- return 0;
+ return NULL_TREE;
}
}
+
+/* Return non-zero if the dynamic type of INSTANCE is known, and equivalent
+ to the static type. We also handle the case where INSTANCE is really
+ a pointer.
+
+ Used to determine whether the virtual function table is needed
+ or not.
+
+ *NONNULL is set iff INSTANCE can be known to be nonnull, regardless
+ of our knowledge of its type. */
+
+int
+resolves_to_fixed_type_p (instance, nonnull)
+ tree instance;
+ int *nonnull;
+{
+ tree t = TREE_TYPE (instance);
+ tree fixed = fixed_type_or_null (instance, nonnull);
+ if (fixed == NULL_TREE)
+ return 0;
+ if (POINTER_TYPE_P (t))
+ t = TREE_TYPE (t);
+ return same_type_p (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (fixed));
+}
+
void
init_class_processing ()
{
current_class_depth = 0;
- current_class_stacksize = 10;
- current_class_base = (tree *)xmalloc(current_class_stacksize * sizeof (tree));
- current_class_stack = current_class_base;
+ current_class_stack_size = 10;
+ current_class_stack
+ = (class_stack_node_t) xmalloc (current_class_stack_size
+ * sizeof (struct class_stack_node));
current_lang_stacksize = 10;
current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree));
@@ -4680,34 +4431,56 @@ pushclass (type, modify)
int modify;
{
type = TYPE_MAIN_VARIANT (type);
- push_memoized_context (type, modify);
- current_class_depth++;
- *current_class_stack++ = current_class_name;
- *current_class_stack++ = current_class_type;
- if (current_class_stack >= current_class_base + current_class_stacksize)
+ /* Make sure there is enough room for the new entry on the stack. */
+ if (current_class_depth + 1 >= current_class_stack_size)
{
- current_class_base
- = (tree *)xrealloc (current_class_base,
- sizeof (tree) * (current_class_stacksize + 10));
- current_class_stack = current_class_base + current_class_stacksize;
- current_class_stacksize += 10;
+ current_class_stack_size *= 2;
+ current_class_stack
+ = (class_stack_node_t) xrealloc (current_class_stack,
+ current_class_stack_size
+ * sizeof (struct class_stack_node));
}
+ /* Insert a new entry on the class stack. */
+ current_class_stack[current_class_depth].name = current_class_name;
+ current_class_stack[current_class_depth].type = current_class_type;
+ current_class_stack[current_class_depth].access = current_access_specifier;
+ current_class_stack[current_class_depth].names_used = 0;
+ current_class_depth++;
+
+ /* Now set up the new type. */
current_class_name = TYPE_NAME (type);
if (TREE_CODE (current_class_name) == TYPE_DECL)
current_class_name = DECL_NAME (current_class_name);
current_class_type = type;
+ /* By default, things in classes are private, while things in
+ structures or unions are public. */
+ current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type)
+ ? access_private_node
+ : access_public_node);
+
if (previous_class_type != NULL_TREE
- && (type != previous_class_type || TYPE_SIZE (previous_class_type) == NULL_TREE)
+ && (type != previous_class_type
+ || TYPE_SIZE (previous_class_type) == NULL_TREE)
&& current_class_depth == 1)
{
/* Forcibly remove any old class remnants. */
- popclass (-1);
- previous_class_type = NULL_TREE;
+ invalidate_class_lookup_cache ();
+
+ /* Now, free the obstack on which we cached all the values. */
+ if (class_cache_firstobj)
+ obstack_free (&class_cache_obstack, class_cache_firstobj);
+ class_cache_firstobj
+ = (char*) obstack_finish (&class_cache_obstack);
}
+ /* If we're about to enter a nested class, clear
+ IDENTIFIER_CLASS_VALUE for the enclosing classes. */
+ if (modify && current_class_depth > 1)
+ clear_identifier_class_values ();
+
pushlevel_class ();
#if 0
@@ -4717,122 +4490,70 @@ pushclass (type, modify)
if (modify)
{
- tree tags;
- tree this_fndecl = current_function_decl;
-
- if (current_function_decl
- && DECL_CONTEXT (current_function_decl)
- && TREE_CODE (DECL_CONTEXT (current_function_decl)) == FUNCTION_DECL)
- current_function_decl = DECL_CONTEXT (current_function_decl);
- else
- current_function_decl = NULL_TREE;
-
if (type != previous_class_type || current_class_depth > 1)
- {
-#ifdef MI_MATRIX
- build_mi_matrix (type);
- push_class_decls (type);
- free_mi_matrix ();
-#else
- push_class_decls (type);
-#endif
- }
+ push_class_decls (type);
else
{
tree item;
- /* Hooray, we successfully cached; let's just install the
- cached class_shadowed list, and walk through it to get the
- IDENTIFIER_TYPE_VALUEs correct. */
+ /* We are re-entering the same class we just left, so we
+ don't have to search the whole inheritance matrix to find
+ all the decls to bind again. Instead, we install the
+ cached class_shadowed list, and walk through it binding
+ names and setting up IDENTIFIER_TYPE_VALUEs. */
set_class_shadows (previous_class_values);
for (item = previous_class_values; item; item = TREE_CHAIN (item))
{
tree id = TREE_PURPOSE (item);
- tree decl = IDENTIFIER_CLASS_VALUE (id);
+ tree decl = TREE_TYPE (item);
+ push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
set_identifier_type_value (id, TREE_TYPE (decl));
}
unuse_fields (type);
}
- for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags))
- {
- tree tag_type = TREE_VALUE (tags);
+ storetags (CLASSTYPE_TAGS (type));
+ }
+}
- TREE_NONLOCAL_FLAG (tag_type) = 1;
- if (! TREE_PURPOSE (tags))
- continue;
- if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type))
- && CLASSTYPE_IS_TEMPLATE (tag_type)))
- pushtag (TREE_PURPOSE (tags), tag_type, 0);
- else
- pushdecl_class_level (CLASSTYPE_TI_TEMPLATE (tag_type));
- }
+/* When we exit a toplevel class scope, we save the
+ IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we
+ reenter the class. Here, we've entered some other class, so we
+ must invalidate our cache. */
- current_function_decl = this_fndecl;
- }
+void
+invalidate_class_lookup_cache ()
+{
+ tree t;
+
+ /* This code can be seen as a cache miss. When we've cached a
+ class' scope's bindings and we can't use them, we need to reset
+ them. This is it! */
+ for (t = previous_class_values; t; t = TREE_CHAIN (t))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
+
+ previous_class_type = NULL_TREE;
}
/* Get out of the current class scope. If we were in a class scope
- previously, that is the one popped to. The flag MODIFY tells whether
- the current scope declarations needs to be modified as a result of
- popping to the previous scope. 0 is used for class definitions. */
+ previously, that is the one popped to. */
void
-popclass (modify)
- int modify;
+popclass ()
{
- if (modify < 0)
- {
- /* Back this old class out completely. */
- tree tags = CLASSTYPE_TAGS (previous_class_type);
- tree t;
-
- /* This code can be seen as a cache miss. When we've cached a
- class' scope's bindings and we can't use them, we need to reset
- them. This is it! */
- for (t = previous_class_values; t; t = TREE_CHAIN (t))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
- while (tags)
- {
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
- tags = TREE_CHAIN (tags);
- }
- goto ret;
- }
-
- if (modify)
- {
- /* Just remove from this class what didn't make
- it into IDENTIFIER_CLASS_VALUE. */
- tree tags = CLASSTYPE_TAGS (current_class_type);
-
- while (tags)
- {
- TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0;
- tags = TREE_CHAIN (tags);
- }
- }
-
- /* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition,
- since not all class decls make it there currently. */
- poplevel_class (! modify);
-
+ poplevel (1, 0, 0);
/* Since poplevel_class does the popping of class decls nowadays,
- this really only frees the obstack used for these decls.
- That's why it had to be moved down here. */
- if (modify)
- pop_class_decls ();
+ this really only frees the obstack used for these decls. */
+ pop_class_decls ();
current_class_depth--;
- current_class_type = *--current_class_stack;
- current_class_name = *--current_class_stack;
-
- pop_memoized_context (modify);
-
- ret:
- ;
+ current_class_name = current_class_stack[current_class_depth].name;
+ current_class_type = current_class_stack[current_class_depth].type;
+ current_access_specifier = current_class_stack[current_class_depth].access;
+ if (current_class_stack[current_class_depth].names_used)
+ splay_tree_delete (current_class_stack[current_class_depth].names_used);
}
/* Returns 1 if current_class_type is either T or a nested type of T. */
@@ -4845,7 +4566,7 @@ currently_open_class (t)
if (t == current_class_type)
return 1;
for (i = 0; i < current_class_depth; ++i)
- if (current_class_stack [-i*2 - 1] == t)
+ if (current_class_stack [i].type == t)
return 1;
return 0;
}
@@ -4864,16 +4585,16 @@ push_nested_class (type, modify)
{
tree context;
- my_friendly_assert (!type || TREE_CODE (type) != NAMESPACE_DECL, 980711);
-
+ /* A namespace might be passed in error cases, like A::B:C. */
if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == NAMESPACE_DECL
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return;
context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
- if (context && TREE_CODE (context) == RECORD_TYPE)
+ if (context && CLASS_TYPE_P (context))
push_nested_class (context, 2);
pushclass (type, modify);
}
@@ -4881,14 +4602,13 @@ push_nested_class (type, modify)
/* Undoes a push_nested_class call. MODIFY is passed on to popclass. */
void
-pop_nested_class (modify)
- int modify;
+pop_nested_class ()
{
tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type));
- popclass (modify);
- if (context && TREE_CODE (context) == RECORD_TYPE)
- pop_nested_class (modify);
+ popclass ();
+ if (context && CLASS_TYPE_P (context))
+ pop_nested_class ();
}
/* Set global variables CURRENT_LANG_NAME to appropriate value
@@ -4908,10 +4628,27 @@ push_lang_context (name)
current_lang_stacksize += 10;
}
- if (name == lang_name_cplusplus || name == lang_name_java)
+ if (name == lang_name_cplusplus)
+ {
+ strict_prototype = strict_prototypes_lang_cplusplus;
+ current_lang_name = name;
+ }
+ else if (name == lang_name_java)
{
strict_prototype = strict_prototypes_lang_cplusplus;
current_lang_name = name;
+ /* DECL_IGNORED_P is initially set for these types, to avoid clutter.
+ (See record_builtin_java_type in decl.c.) However, that causes
+ incorrect debug entries if these types are actually used.
+ So we re-enable debug output after extern "Java". */
+ DECL_IGNORED_P (java_byte_type_node) = 0;
+ DECL_IGNORED_P (java_short_type_node) = 0;
+ DECL_IGNORED_P (java_int_type_node) = 0;
+ DECL_IGNORED_P (java_long_type_node) = 0;
+ DECL_IGNORED_P (java_float_type_node) = 0;
+ DECL_IGNORED_P (java_double_type_node) = 0;
+ DECL_IGNORED_P (java_char_type_node) = 0;
+ DECL_IGNORED_P (java_boolean_type_node) = 0;
}
else if (name == lang_name_c)
{
@@ -4937,46 +4674,273 @@ pop_lang_context ()
/* Type instantiation routines. */
+/* Given an OVERLOAD and a TARGET_TYPE, return the function that
+ matches the TARGET_TYPE. If there is no satisfactory match, return
+ error_mark_node, and issue an error message if COMPLAIN is
+ non-zero. If TEMPLATE_ONLY, the name of the overloaded function
+ was a template-id, and EXPLICIT_TARGS are the explicitly provided
+ template arguments. */
+
static tree
-validate_lhs (lhstype, complain)
- tree lhstype;
+resolve_address_of_overloaded_function (target_type,
+ overload,
+ complain,
+ template_only,
+ explicit_targs)
+ tree target_type;
+ tree overload;
int complain;
+ int template_only;
+ tree explicit_targs;
{
- if (TYPE_PTRMEMFUNC_P (lhstype))
- lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
+ /* Here's what the standard says:
+
+ [over.over]
+
+ If the name is a function template, template argument deduction
+ is done, and if the argument deduction succeeds, the deduced
+ arguments are used to generate a single template function, which
+ is added to the set of overloaded functions considered.
+
+ Non-member functions and static member functions match targets of
+ type "pointer-to-function" or "reference-to-function." Nonstatic
+ member functions match targets of type "pointer-to-member
+ function;" the function type of the pointer to member is used to
+ select the member function from the set of overloaded member
+ functions. If a nonstatic member function is selected, the
+ reference to the overloaded function name is required to have the
+ form of a pointer to member as described in 5.3.1.
+
+ If more than one function is selected, any template functions in
+ the set are eliminated if the set also contains a non-template
+ function, and any given template function is eliminated if the
+ set contains a second template function that is more specialized
+ than the first according to the partial ordering rules 14.5.5.2.
+ After such eliminations, if any, there shall remain exactly one
+ selected function. */
+
+ int is_ptrmem = 0;
+ int is_reference = 0;
+ /* We store the matches in a TREE_LIST rooted here. The functions
+ are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
+ interoperability with most_specialized_instantiation. */
+ tree matches = NULL_TREE;
+ tree fn;
+
+ /* By the time we get here, we should be seeing only real
+ pointer-to-member types, not the internal POINTER_TYPE to
+ METHOD_TYPE representation. */
+ my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (target_type))
+ == METHOD_TYPE)), 0);
+
+ /* Check that the TARGET_TYPE is reasonable. */
+ if (TYPE_PTRFN_P (target_type))
+ /* This is OK. */
+ ;
+ else if (TYPE_PTRMEMFUNC_P (target_type))
+ /* This is OK, too. */
+ is_ptrmem = 1;
+ else if (TREE_CODE (target_type) == FUNCTION_TYPE)
+ {
+ /* This is OK, too. This comes from a conversion to reference
+ type. */
+ target_type = build_reference_type (target_type);
+ is_reference = 1;
+ }
+ else
+ {
+ if (complain)
+ cp_error("cannot resolve overloaded function `%D' based on conversion to type `%T'",
+ DECL_NAME (OVL_FUNCTION (overload)), target_type);
+ return error_mark_node;
+ }
+
+ /* If we can find a non-template function that matches, we can just
+ use it. There's no point in generating template instantiations
+ if we're just going to throw them out anyhow. But, of course, we
+ can only do this when we don't *need* a template function. */
+ if (!template_only)
+ {
+ tree fns;
- if (TREE_CODE (lhstype) == POINTER_TYPE)
+ for (fns = overload; fns; fns = OVL_CHAIN (fns))
+ {
+ tree fn = OVL_FUNCTION (fns);
+ tree fntype;
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ /* We're not looking for templates just yet. */
+ continue;
+
+ if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ != is_ptrmem)
+ /* We're looking for a non-static member, and this isn't
+ one, or vice versa. */
+ continue;
+
+ /* See if there's a match. */
+ fntype = TREE_TYPE (fn);
+ if (is_ptrmem)
+ fntype = build_ptrmemfunc_type (build_pointer_type (fntype));
+ else if (!is_reference)
+ fntype = build_pointer_type (fntype);
+
+ if (can_convert_arg (target_type, fntype, fn))
+ matches = scratch_tree_cons (fn, NULL_TREE, matches);
+ }
+ }
+
+ /* Now, if we've already got a match (or matches), there's no need
+ to proceed to the template functions. But, if we don't have a
+ match we need to look at them, too. */
+ if (!matches)
{
- if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
- lhstype = TREE_TYPE (lhstype);
+ tree target_fn_type;
+ tree target_arg_types;
+ tree fns;
+
+ if (is_ptrmem)
+ target_fn_type
+ = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type));
else
+ target_fn_type = TREE_TYPE (target_type);
+ target_arg_types = TYPE_ARG_TYPES (target_fn_type);
+
+ for (fns = overload; fns; fns = OVL_CHAIN (fns))
{
- if (complain)
- error ("invalid type combination for overload");
- return error_mark_node;
+ tree fn = OVL_FUNCTION (fns);
+ tree instantiation;
+ tree instantiation_type;
+ tree targs;
+
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ /* We're only looking for templates. */
+ continue;
+
+ if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ != is_ptrmem)
+ /* We're not looking for a non-static member, and this is
+ one, or vice versa. */
+ continue;
+
+ /* Try to do argument deduction. */
+ targs = make_scratch_vec (DECL_NTPARMS (fn));
+ if (fn_type_unification (fn, explicit_targs, targs,
+ target_arg_types, NULL_TREE,
+ DEDUCE_EXACT) != 0)
+ /* Argument deduction failed. */
+ continue;
+
+ /* Instantiate the template. */
+ instantiation = instantiate_template (fn, targs);
+ if (instantiation == error_mark_node)
+ /* Instantiation failed. */
+ continue;
+
+ /* See if there's a match. */
+ instantiation_type = TREE_TYPE (instantiation);
+ if (is_ptrmem)
+ instantiation_type =
+ build_ptrmemfunc_type (build_pointer_type (instantiation_type));
+ else if (!is_reference)
+ instantiation_type = build_pointer_type (instantiation_type);
+ if (can_convert_arg (target_type, instantiation_type, instantiation))
+ matches = scratch_tree_cons (instantiation, fn, matches);
+ }
+
+ /* Now, remove all but the most specialized of the matches. */
+ if (matches)
+ {
+ tree match = most_specialized_instantiation (matches,
+ explicit_targs);
+
+ if (match != error_mark_node)
+ matches = scratch_tree_cons (match, NULL_TREE, NULL_TREE);
}
}
- return lhstype;
+
+ /* Now we should have exactly one function in MATCHES. */
+ if (matches == NULL_TREE)
+ {
+ /* There were *no* matches. */
+ if (complain)
+ {
+ cp_error ("no matches converting function `%D' to type `%#T'",
+ DECL_NAME (OVL_FUNCTION (overload)),
+ target_type);
+
+ /* print_candidates expects a chain with the functions in
+ TREE_VALUE slots, so we cons one up here (we're losing anyway,
+ so why be clever?). */
+ for (; overload; overload = OVL_NEXT (overload))
+ matches = scratch_tree_cons (NULL_TREE, OVL_CURRENT (overload),
+ matches);
+
+ print_candidates (matches);
+ }
+ return error_mark_node;
+ }
+ else if (TREE_CHAIN (matches))
+ {
+ /* There were too many matches. */
+
+ if (complain)
+ {
+ tree match;
+
+ cp_error ("converting overloaded function `%D' to type `%#T' is ambiguous",
+ DECL_NAME (OVL_FUNCTION (overload)),
+ target_type);
+
+ /* Since print_candidates expects the functions in the
+ TREE_VALUE slot, we flip them here. */
+ for (match = matches; match; match = TREE_CHAIN (match))
+ TREE_VALUE (match) = TREE_PURPOSE (match);
+
+ print_candidates (matches);
+ }
+
+ return error_mark_node;
+ }
+
+ /* Good, exactly one match. Now, convert it to the correct type. */
+ fn = TREE_PURPOSE (matches);
+
+ mark_used (fn);
+
+ if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
+ return build_unary_op (ADDR_EXPR, fn, 0);
+ else
+ {
+ /* The target must be a REFERENCE_TYPE. Above, build_unary_op
+ will mark the function as addressed, but here we must do it
+ explicitly. */
+ mark_addressable (fn);
+
+ return fn;
+ }
}
/* This function will instantiate the type of the expression given in
RHS to match the type of LHSTYPE. If errors exist, then return
- error_mark_node. If only complain is COMPLAIN is set. If we are
+ error_mark_node. We only complain is COMPLAIN is set. If we are
not complaining, never modify rhs, as overload resolution wants to
try many possible instantiations, in hopes that at least one will
work.
- This function is used in build_modify_expr, convert_arguments,
- build_c_cast, and compute_conversion_costs. */
+ FLAGS is a bitmask, as we see at the top of the function.
+
+ For non-recursive calls, LHSTYPE should be a function, pointer to
+ function, or a pointer to member function. */
tree
-instantiate_type (lhstype, rhs, complain)
+instantiate_type (lhstype, rhs, flags)
tree lhstype, rhs;
- int complain;
+ int flags;
{
- tree explicit_targs = NULL_TREE;
- int template_only = 0;
+ int complain = (flags & 1);
+ int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
@@ -4987,7 +4951,7 @@ instantiate_type (lhstype, rhs, complain)
if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs)))
{
- if (comptypes (lhstype, TREE_TYPE (rhs), 1))
+ if (comptypes (lhstype, TREE_TYPE (rhs), strict))
return rhs;
if (complain)
cp_error ("argument of type `%T' does not match `%T'",
@@ -5021,7 +4985,7 @@ instantiate_type (lhstype, rhs, complain)
tree new_rhs;
new_rhs = instantiate_type (build_pointer_type (lhstype),
- TREE_OPERAND (rhs, 0), complain);
+ TREE_OPERAND (rhs, 0), flags);
if (new_rhs == error_mark_node)
return error_mark_node;
@@ -5033,312 +4997,71 @@ instantiate_type (lhstype, rhs, complain)
case NOP_EXPR:
rhs = copy_node (TREE_OPERAND (rhs, 0));
TREE_TYPE (rhs) = unknown_type_node;
- return instantiate_type (lhstype, rhs, complain);
+ return instantiate_type (lhstype, rhs, flags);
case COMPONENT_REF:
{
tree field = TREE_OPERAND (rhs, 1);
- if (TREE_CODE (field) == TREE_LIST)
- {
- tree function = instantiate_type (lhstype, field, complain);
- if (function == error_mark_node)
- return error_mark_node;
- my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
- if (DECL_VINDEX (function))
- {
- tree base = TREE_OPERAND (rhs, 0);
- tree base_ptr = build_unary_op (ADDR_EXPR, base, 0);
- if (base_ptr == error_mark_node)
- return error_mark_node;
- base_ptr = convert_pointer_to (DECL_CONTEXT (function), base_ptr);
- if (base_ptr == error_mark_node)
- return error_mark_node;
- return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
- }
- mark_used (function);
- return function;
- }
+ tree r;
- /* I could not trigger this code. MvL */
- my_friendly_abort (980326);
-#if 0
- my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 178);
- my_friendly_assert (!(TREE_CODE (TREE_TYPE (field)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (field)) == METHOD_TYPE),
- 179);
-
- TREE_TYPE (rhs) = lhstype;
- /* First look for an exact match */
-
- while (field && TREE_TYPE (field) != lhstype)
- field = DECL_CHAIN (field);
- if (field)
- {
- TREE_OPERAND (rhs, 1) = field;
- mark_used (field);
- return rhs;
- }
+ r = instantiate_type (lhstype, field, flags);
- /* No exact match found, look for a compatible function. */
- field = TREE_OPERAND (rhs, 1);
- while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
- field = DECL_CHAIN (field);
- if (field)
+ if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype))
{
- TREE_OPERAND (rhs, 1) = field;
- field = DECL_CHAIN (field);
- while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
- field = DECL_CHAIN (field);
- if (field)
+ if (complain)
{
- if (complain)
- error ("ambiguous overload for COMPONENT_REF requested");
- return error_mark_node;
+ tree t = TYPE_PTRMEMFUNC_OBJECT_TYPE (lhstype);
+
+ if (TREE_CODE (field) == OVERLOAD)
+ field = OVL_FUNCTION (field);
+ if (TREE_CODE (field) == FUNCTION_DECL)
+ {
+ cp_pedwarn ("object-dependent reference `%E' can only be used in a call",
+ DECL_NAME (field));
+ cp_pedwarn (" to form a pointer to member function, say `&%T::%E'",
+ t, DECL_NAME (field));
+ }
+ else
+ cp_pedwarn ("object-dependent reference can only be used in a call");
}
+ return r;
}
- else
- {
- if (complain)
- error ("no appropriate overload exists for COMPONENT_REF");
- return error_mark_node;
- }
-#endif
- return rhs;
+
+ return r;
}
case OFFSET_REF:
+ rhs = TREE_OPERAND (rhs, 1);
+ if (BASELINK_P (rhs))
+ return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+
/* This can happen if we are forming a pointer-to-member for a
member template. */
- rhs = TREE_OPERAND (rhs, 1);
my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0);
-
+
/* Fall through. */
case TEMPLATE_ID_EXPR:
- {
- explicit_targs = TREE_OPERAND (rhs, 1);
- template_only = 1;
- rhs = TREE_OPERAND (rhs, 0);
- }
- /* fall through */
- my_friendly_assert (TREE_CODE (rhs) == OVERLOAD, 980401);
+ return
+ resolve_address_of_overloaded_function (lhstype,
+ TREE_OPERAND (rhs, 0),
+ complain,
+ /*template_only=*/1,
+ TREE_OPERAND (rhs, 1));
case OVERLOAD:
- {
- tree elem, elems;
-
- /* Check that the LHSTYPE and the RHS are reasonable. */
- lhstype = validate_lhs (lhstype, complain);
- if (lhstype == error_mark_node)
- return lhstype;
-
- if (TREE_CODE (lhstype) != FUNCTION_TYPE
- && TREE_CODE (lhstype) != METHOD_TYPE)
- {
- if (complain)
- cp_error("cannot resolve overloaded function `%D' "
- "based on non-function type",
- DECL_NAME (OVL_FUNCTION (rhs)));
- return error_mark_node;
- }
-
- /* Look for an exact match, by searching through the
- overloaded functions. */
- if (template_only)
- /* If we're processing a template-id, only a template
- function can match, so we don't look through the
- overloaded functions. */
- ;
- else for (elems = rhs; elems; elems = OVL_CHAIN (elems))
- {
- elem = OVL_FUNCTION (elems);
- if (comptypes (lhstype, TREE_TYPE (elem), 1))
- {
- mark_used (elem);
- return elem;
- }
- }
-
- /* No overloaded function was an exact match. See if we can
- instantiate some template to match. */
- {
- tree save_elem = 0;
- elems = rhs;
- if (TREE_CODE (elems) == TREE_LIST)
- elems = TREE_VALUE (rhs);
- for (; elems; elems = OVL_NEXT (elems))
- if (TREE_CODE (elem = OVL_CURRENT (elems)) == TEMPLATE_DECL)
- {
- int n = DECL_NTPARMS (elem);
- tree t = make_scratch_vec (n);
- int i;
- i = type_unification
- (DECL_INNERMOST_TEMPLATE_PARMS (elem), t,
- TYPE_ARG_TYPES (TREE_TYPE (elem)),
- TYPE_ARG_TYPES (lhstype), explicit_targs, DEDUCE_EXACT, 1);
- 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)
- {
- mark_used (save_elem);
- return save_elem;
- }
- }
-
- /* There's no exact match, and no templates can be
- instantiated to match. The last thing we try is to see if
- some ordinary overloaded function is close enough. If
- we're only looking for template functions, we don't do
- this. */
- if (!template_only)
- {
- for (elems = rhs; elems; elems = OVL_NEXT (elems))
- {
- elem = OVL_CURRENT (elems);
- if (comp_target_types (lhstype, TREE_TYPE (elem), 1) > 0)
- break;
- }
- if (elems)
- {
- tree save_elem = elem;
- for (elems = OVL_CHAIN (elems); elems;
- elems = OVL_CHAIN (elems))
- {
- elem = OVL_FUNCTION (elems);
- if (comp_target_types (lhstype, TREE_TYPE (elem), 0) > 0)
- break;
- }
- if (elems)
- {
- if (complain)
- {
- cp_error
- ("cannot resolve overload to target type `%#T'",
- lhstype);
- cp_error_at (" ambiguity between `%#D'", save_elem);
- cp_error_at (" and `%#D', at least", elem);
- }
- return error_mark_node;
- }
- mark_used (save_elem);
- return save_elem;
- }
- }
-
- /* We failed to find a match. */
- if (complain)
- {
- cp_error ("cannot resolve overload to target type `%#T'", lhstype);
- cp_error
- (" because no suitable overload of function `%D' exists",
- DECL_NAME (OVL_FUNCTION (rhs)));
- }
- return error_mark_node;
- }
+ return
+ resolve_address_of_overloaded_function (lhstype,
+ rhs,
+ complain,
+ /*template_only=*/0,
+ /*explicit_targs=*/NULL_TREE);
case TREE_LIST:
- {
- tree elem, baselink, name = NULL_TREE;
-
- if (TREE_PURPOSE (rhs) == error_mark_node)
- {
- /* Make sure we don't drop the non-local flag, as the old code
- would rely on it. */
- int nl = TREE_NONLOCAL_FLAG (rhs);
- /* We don't need the type of this node. */
- rhs = TREE_VALUE (rhs);
- my_friendly_assert (TREE_NONLOCAL_FLAG (rhs) == nl, 980331);
- }
-
- /* Now we should have a baselink. */
- my_friendly_assert (TREE_CODE (TREE_PURPOSE (rhs)) == TREE_VEC,
- 980331);
- /* First look for an exact match. Search member functions.
- May have to undo what `default_conversion' might do to
- lhstype. */
+ /* Now we should have a baselink. */
+ my_friendly_assert (BASELINK_P (rhs), 990412);
- lhstype = validate_lhs (lhstype, complain);
- if (lhstype == error_mark_node)
- return lhstype;
-
- my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181);
- my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (rhs)) == OVERLOAD,
- 182);
-
- for (baselink = rhs; baselink;
- baselink = next_baselink (baselink))
- {
- elem = TREE_VALUE (baselink);
- while (elem)
- if (comptypes (lhstype, TREE_TYPE (OVL_CURRENT (elem)), 1))
- {
- mark_used (OVL_CURRENT (elem));
- return OVL_CURRENT (elem);
- }
- else
- elem = OVL_NEXT (elem);
- }
-
- /* No exact match found, look for a compatible method. */
- for (baselink = rhs; baselink;
- baselink = next_baselink (baselink))
- {
- elem = TREE_VALUE (baselink);
- for (; elem; elem = OVL_NEXT (elem))
- if (comp_target_types (lhstype,
- TREE_TYPE (OVL_CURRENT (elem)), 1) > 0)
- break;
- if (elem)
- {
- tree save_elem = OVL_CURRENT (elem);
- for (elem = OVL_NEXT (elem); elem; elem = OVL_NEXT (elem))
- if (comp_target_types (lhstype,
- TREE_TYPE (OVL_CURRENT (elem)), 0) > 0)
- break;
- if (elem)
- {
- if (complain)
- error ("ambiguous overload for overloaded method requested");
- return error_mark_node;
- }
- mark_used (save_elem);
- return save_elem;
- }
- name = rhs;
- while (TREE_CODE (name) == TREE_LIST)
- name = TREE_VALUE (name);
- name = DECL_NAME (OVL_CURRENT (name));
-#if 0
- if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0)
- {
- /* Try to instantiate from non-member functions. */
- rhs = lookup_name_nonclass (name);
- if (rhs && TREE_CODE (rhs) == TREE_LIST)
- {
- /* This code seems to be missing a `return'. */
- my_friendly_abort (4);
- instantiate_type (lhstype, rhs, complain);
- }
- }
-#endif
- }
- if (complain)
- cp_error ("no compatible member functions named `%D'", name);
- return error_mark_node;
- }
+ return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
case CALL_EXPR:
/* This is too hard for now. */
@@ -5349,11 +5072,11 @@ instantiate_type (lhstype, rhs, complain)
case MINUS_EXPR:
case COMPOUND_EXPR:
TREE_OPERAND (rhs, 0)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
if (TREE_OPERAND (rhs, 0) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
@@ -5421,11 +5144,11 @@ instantiate_type (lhstype, rhs, complain)
return error_mark_node;
}
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
TREE_OPERAND (rhs, 2)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), flags);
if (TREE_OPERAND (rhs, 2) == error_mark_node)
return error_mark_node;
@@ -5434,7 +5157,7 @@ instantiate_type (lhstype, rhs, complain)
case MODIFY_EXPR:
TREE_OPERAND (rhs, 1)
- = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain);
+ = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
if (TREE_OPERAND (rhs, 1) == error_mark_node)
return error_mark_node;
@@ -5442,30 +5165,7 @@ instantiate_type (lhstype, rhs, complain)
return rhs;
case ADDR_EXPR:
- if (TYPE_PTRMEMFUNC_P (lhstype))
- lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
- else if (TREE_CODE (lhstype) != POINTER_TYPE)
- {
- if (complain)
- error ("type for resolving address of overloaded function must be pointer type");
- return error_mark_node;
- }
- {
- tree fn = instantiate_type (TREE_TYPE (lhstype), TREE_OPERAND (rhs, 0), complain);
- if (fn == error_mark_node)
- return error_mark_node;
- mark_addressable (fn);
- TREE_TYPE (rhs) = lhstype;
- TREE_OPERAND (rhs, 0) = fn;
- TREE_CONSTANT (rhs) = staticp (fn);
- if (TREE_CODE (lhstype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
- {
- build_ptrmemfunc_type (lhstype);
- rhs = build_ptrmemfunc (lhstype, rhs, 0);
- }
- }
- return rhs;
+ return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
case ENTRY_VALUE_EXPR:
my_friendly_abort (184);
@@ -5524,16 +5224,24 @@ print_class_statistics ()
}
/* Push an obstack which is sufficiently long-lived to hold such class
- decls that may be cached in the previous_class_values list. For now, let's
- use the permanent obstack, later we may create a dedicated obstack just
- for this purpose. The effect is undone by pop_obstacks. */
+ decls that may be cached in the previous_class_values list. The
+ effect is undone by pop_obstacks. */
void
-maybe_push_cache_obstack ()
+push_cache_obstack ()
{
+ static int cache_obstack_initialized;
+
+ if (!cache_obstack_initialized)
+ {
+ gcc_obstack_init (&class_cache_obstack);
+ class_cache_firstobj
+ = (char*) obstack_finish (&class_cache_obstack);
+ cache_obstack_initialized = 1;
+ }
+
push_obstacks_nochange ();
- if (current_class_depth == 1)
- current_obstack = &permanent_obstack;
+ current_obstack = &class_cache_obstack;
}
/* Build a dummy reference to ourselves so Derived::Base (and A::A) works,
@@ -5542,19 +5250,22 @@ maybe_push_cache_obstack ()
into the scope of the class itself. For purposes of access checking,
the inserted class name is treated as if it were a public member name. */
-tree
+void
build_self_reference ()
{
tree name = constructor_name (current_class_type);
tree value = build_lang_decl (TYPE_DECL, name, current_class_type);
+ tree saved_cas;
+
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
DECL_CLASS_CONTEXT (value) = current_class_type;
- CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
DECL_ARTIFICIAL (value) = 1;
- pushdecl_class_level (value);
- return value;
+ saved_cas = current_access_specifier;
+ current_access_specifier = access_public_node;
+ finish_member_declaration (value);
+ current_access_specifier = saved_cas;
}
/* Returns 1 if TYPE contains only padding bytes. */
@@ -5581,3 +5292,110 @@ is_empty_class (type)
t = TREE_CHAIN (t);
return (t == NULL_TREE);
}
+
+/* Find the enclosing class of the given NODE. NODE can be a *_DECL or
+ a *_TYPE node. NODE can also be a local class. */
+
+tree
+get_enclosing_class (type)
+ tree type;
+{
+ tree node = type;
+
+ while (node && TREE_CODE (node) != NAMESPACE_DECL)
+ {
+ switch (TREE_CODE_CLASS (TREE_CODE (node)))
+ {
+ case 'd':
+ node = DECL_CONTEXT (node);
+ break;
+
+ case 't':
+ if (node != type)
+ return node;
+ node = TYPE_CONTEXT (node);
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Return 1 if TYPE or one of its enclosing classes is derived from BASE. */
+
+int
+is_base_of_enclosing_class (base, type)
+ tree base, type;
+{
+ while (type)
+ {
+ if (get_binfo (base, type, 0))
+ return 1;
+
+ type = get_enclosing_class (type);
+ }
+ return 0;
+}
+
+/* Note that NAME was looked up while the current class was being
+ defined and that the result of that lookup was DECL. */
+
+void
+maybe_note_name_used_in_class (name, decl)
+ tree name;
+ tree decl;
+{
+ splay_tree names_used;
+
+ /* If we're not defining a class, there's nothing to do. */
+ if (!current_class_type || !TYPE_BEING_DEFINED (current_class_type))
+ return;
+
+ /* If there's already a binding for this NAME, then we don't have
+ anything to worry about. */
+ if (IDENTIFIER_CLASS_VALUE (name))
+ return;
+
+ if (!current_class_stack[current_class_depth - 1].names_used)
+ current_class_stack[current_class_depth - 1].names_used
+ = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+ names_used = current_class_stack[current_class_depth - 1].names_used;
+
+ splay_tree_insert (names_used,
+ (splay_tree_key) name,
+ (splay_tree_value) decl);
+}
+
+/* Note that NAME was declared (as DECL) in the current class. Check
+ to see that the declaration is legal. */
+
+void
+note_name_declared_in_class (name, decl)
+ tree name;
+ tree decl;
+{
+ splay_tree names_used;
+ splay_tree_node n;
+
+ /* Look to see if we ever used this name. */
+ names_used
+ = current_class_stack[current_class_depth - 1].names_used;
+ if (!names_used)
+ return;
+
+ n = splay_tree_lookup (names_used, (splay_tree_key) name);
+ if (n)
+ {
+ /* [basic.scope.class]
+
+ A name N used in a class S shall refer to the same declaration
+ in its context and when re-evaluated in the completed scope of
+ S. */
+ cp_error ("declaration of `%#D'", decl);
+ cp_error_at ("changes meaning of `%s' from `%+#D'",
+ IDENTIFIER_POINTER (DECL_NAME (decl)),
+ (tree) n->value);
+ }
+}
diff --git a/contrib/gcc/cp/config-lang.in b/contrib/gcc/cp/config-lang.in
index 9b39d51..dd31af4 100644
--- a/contrib/gcc/cp/config-lang.in
+++ b/contrib/gcc/cp/config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for GNU C++.
-# Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
#This file is part of GNU CC.
diff --git a/contrib/gcc/cp/cp-tree.def b/contrib/gcc/cp/cp-tree.def
index dbbdb66..70801fc 100644
--- a/contrib/gcc/cp/cp-tree.def
+++ b/contrib/gcc/cp/cp-tree.def
@@ -1,7 +1,7 @@
/* This file contains the definitions and documentation for the
additional tree codes used in the GNU C++ compiler (see tree.def
for the standard codes).
- Copyright (C) 1987, 1988, 1990, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -29,6 +29,11 @@ Boston, MA 02111-1307, USA. */
just won't work for us. */
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
+/* A pointer-to-member constant. For a pointer-to-member constant
+ `X::Y' The PTRMEM_CST_CLASS is the RECORD_TYPE for `X' and the
+ PTRMEM_CST_MEMBER is the _DECL for `Y'. */
+DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 1)
+
/* For NEW_EXPR, operand 0 is the placement list.
Operand 1 is the new-declarator.
Operand 2 is the initializer. */
@@ -138,9 +143,18 @@ DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX. */
DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
-/* A type designated by 'typename T::t'. */
+/* A type designated by `typename T::t'. TYPE_CONTEXT is `T',
+ TYPE_NAME is an IDENTIFIER_NODE for `t'. If the type was named via
+ template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
+ If TREE_TYPE is present, this type was generated by the implicit
+ typename extension, and the TREE_TYPE is a _TYPE from a baseclass
+ of `T'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
+/* A type designated by `__typeof (expr)'. TYPE_FIELDS is the
+ expression in question. */
+DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
+
/* A thunk is a stub function.
Thunks are used to implement multiple inheritance:
@@ -158,17 +172,16 @@ DEFTREECODE (USING_DECL, "using_decl", 'd', 0)
/* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */
DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2)
-/* A template-id, like foo<int>. The first operand is the template.
- The second is the list of explicitly specified arguments. The
- template will be a FUNCTION_DECL, TEMPLATE_DECL, or a list of
- overloaded functions and templates if the template-id refers to
- a global template. If the template-id refers to a member template,
- the template may be an IDENTIFIER_NODE. */
+/* A template-id, like foo<int>. The first operand is the template.
+ The second is the TREE_LIST or TREE_VEC of explicitly specified
+ arguments. The template will be a FUNCTION_DECL, TEMPLATE_DECL, or
+ an OVERLOAD. If the template-id refers to a member template, the
+ template may be an IDENTIFIER_NODE. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
-/* An association between namespace and entity. Parameters are the
- scope and the (non-type) value.
- TREE_TYPE indicates the type bound to the name. */
+/* An association between name and entity. Parameters are the scope
+ and the (non-type) value. TREE_TYPE indicates the type bound to
+ the name. */
DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
/* A list-like node for chaining overloading candidates. TREE_TYPE is
@@ -182,9 +195,14 @@ DEFTREECODE (WRAPPER, "wrapper", 'x', 1)
/* A node to remember a source position. */
DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
+/* Used to represent deferred name lookup for dependent names while
+ parsing a template declaration. The first argument is an
+ IDENTIFIER_NODE for the name in question. The TREE_TYPE is
+ unused. */
+DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 1)
+
/* A whole bunch of tree codes for the initial, superficial parsing of
templates. */
-DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 2)
DEFTREECODE (MODOP_EXPR, "modop_expr", 'e', 3)
DEFTREECODE (CAST_EXPR, "cast_expr", '1', 1)
DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", '1', 1)
diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h
index 7572921..7d64307 100644
--- a/contrib/gcc/cp/cp-tree.h
+++ b/contrib/gcc/cp/cp-tree.h
@@ -1,5 +1,5 @@
/* Definitions for C++ parsing and type checking.
- Copyright (C) 1987, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -22,38 +22,37 @@ Boston, MA 02111-1307, USA. */
#ifndef _CP_TREE_H
#define _CP_TREE_H
-#include "gansidecl.h"
-
/* Usage of TREE_LANG_FLAG_?:
- 0: TREE_NONLOCAL_FLAG (in TREE_LIST or _TYPE).
- BINFO_MARKED (BINFO nodes).
- TI_USES_TEMPLATE_PARMS.
+ 0: BINFO_MARKED (BINFO nodes).
COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
TREE_NEGATED_INT (in INTEGER_CST).
- (TREE_MANGLED) (in IDENTIFIER_NODE) (commented-out).
- 1: IDENTIFIER_VIRTUAL_P.
+ TREE_INDIRECT_USING (in NAMESPACE_DECL).
+ IDENTIFIER_MARKED (used by search routines).
+ LOCAL_BINDING_P (in CPLUS_BINDING)
+ 1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG.
- TI_PENDING_SPECIALIZATION_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
DELETE_EXPR_USE_VEC (in DELETE_EXPR).
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
TYPE_USES_COMPLEX_INHERITANCE (in _TYPE).
C_DECLARED_LABEL_FLAG.
+ INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
+ BASELINK_P (in TREE_LIST)
2: IDENTIFIER_OPNAME_P.
+ BINFO_VBASE_MARKED.
BINFO_FIELDS_MARKED.
TYPE_VIRTUAL_P.
- PARM_DECL_EXPR (in SAVE_EXPR).
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED.
+ BINFO_PUSHDECLS_MARKED.
(TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
- 5: BINFO_VIA_PUBLIC.
- BINFO_VBASE_INIT_MARKED.
+ 5: Not used.
6: Not used.
Usage of TYPE_LANG_FLAG_?:
@@ -67,13 +66,31 @@ Boston, MA 02111-1307, USA. */
Usage of DECL_LANG_FLAG_?:
0: DECL_ERROR_REPORTED (in VAR_DECL).
+ DECL_TEMPLATE_PARM_P (in CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
+ DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
3: DECL_IN_AGGR_P.
4: DECL_MAYBE_TEMPLATE.
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
+
+ Usage of language-independent fields in a language-dependent manner:
+
+ TYPE_ALIAS_SET
+ This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so
+ forth as a substitute for the mark bits provided in `lang_type'.
+ At present, only the six low-order bits are used.
+
+ TYPE_BINFO
+ For an ENUMERAL_TYPE, this is ENUM_TEMPLATE_INFO.
+ For a TYPENAME_TYPE, this is TYPENAME_TYPE_FULLNAME.
+ For a TEMPLATE_TEMPLATE_PARM, this is
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
+
+ DECL_SAVED_INSNS/DECL_FIELD_SIZE
+ For a static VAR_DECL, this is DECL_INIT_PRIORITY.
*/
/* Language-dependent contents of an identifier. */
@@ -81,7 +98,8 @@ Boston, MA 02111-1307, USA. */
struct lang_identifier
{
struct tree_identifier ignore;
- tree namespace_bindings, local_value;
+ tree namespace_bindings;
+ tree bindings;
tree class_value;
tree class_template_info;
struct lang_id2 *x;
@@ -90,7 +108,7 @@ struct lang_identifier
struct lang_id2
{
tree label_value, implicit_decl;
- tree type_desc, as_list, error_locus;
+ tree error_locus;
};
typedef struct
@@ -110,15 +128,34 @@ typedef struct
tree decl;
} template_parm_index;
-/* For a binding between a name and an entity, defines the scope
- where the binding is declared. Currently always points to a
- namespace declaration. */
-#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope)
+typedef struct ptrmem_cst
+{
+ char common[sizeof (struct tree_common)];
+ tree member;
+}* ptrmem_cst_t;
+
+/* Nonzero if this binding is for a local scope, as opposed to a class
+ or namespace scope. */
+#define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0(NODE)
+
+/* Nonzero if BINDING_VALUE is from a base class of the class which is
+ currently being defined. */
+#define INHERITED_VALUE_BINDING_P(NODE) TREE_LANG_FLAG_1(NODE)
+
+/* For a binding between a name and an entity at a non-local scope,
+ defines the scope where the binding is declared. (Either a class
+ _TYPE node, or a NAMESPACE_DECL.) This macro should be used only
+ for namespace-level bindings; on the IDENTIFIER_BINDING list
+ BINDING_LEVEL is used instead. */
+#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope.scope)
+
/* This is the declaration bound to the name. Possible values:
variable, overloaded function, namespace, template, enumerator. */
#define BINDING_VALUE(NODE) (((struct tree_binding*)NODE)->value)
+
/* If name is bound to a type, this is the type (struct, union, enum). */
#define BINDING_TYPE(NODE) TREE_TYPE(NODE)
+
#define IDENTIFIER_GLOBAL_VALUE(NODE) \
namespace_binding (NODE, global_namespace)
#define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VAL) \
@@ -131,7 +168,10 @@ typedef struct
struct tree_binding
{
char common[sizeof (struct tree_common)];
- tree scope;
+ union {
+ tree scope;
+ struct binding_level *level;
+ } scope;
tree value;
};
@@ -154,6 +194,14 @@ struct tree_overload
tree function;
};
+/* A `baselink' is a TREE_LIST whose TREE_PURPOSE is a BINFO
+ indicating a particular base class, and whose TREE_VALUE is a
+ (possibly overloaded) function from that base class. */
+#define BASELINK_P(NODE) \
+ (TREE_CODE ((NODE)) == TREE_LIST && TREE_LANG_FLAG_1 ((NODE)))
+#define SET_BASELINK_P(NODE) \
+ (TREE_LANG_FLAG_1 ((NODE)) = 1)
+
#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr)
#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i)
@@ -183,13 +231,43 @@ struct tree_srcloc
#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \
(((struct lang_identifier *)(NODE))->namespace_bindings)
-#define IDENTIFIER_CLASS_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->class_value)
-#define IDENTIFIER_LOCAL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->local_value)
#define IDENTIFIER_TEMPLATE(NODE) \
(((struct lang_identifier *)(NODE))->class_template_info)
+/* The IDENTIFIER_BINDING is the innermost CPLUS_BINDING for the
+ identifier. It's TREE_CHAIN is the next outermost binding. Each
+ BINDING_VALUE is a DECL for the associated declaration. Thus,
+ name lookup consists simply of pulling off the node at the front
+ of the list (modulo oddities for looking up the names of types,
+ and such.) You can use BINDING_SCOPE or BINDING_LEVEL to
+ determine the scope that bound the name. */
+#define IDENTIFIER_BINDING(NODE) \
+ (((struct lang_identifier*) (NODE))->bindings)
+
+/* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
+ NULL_TREE if there is no binding. */
+#define IDENTIFIER_VALUE(NODE) \
+ (IDENTIFIER_BINDING (NODE) \
+ ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) \
+ : NULL_TREE)
+
+/* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current
+ class, and IDENTIFIER_CLASS_VALUE is the value binding. This is
+ just a pointer to the BINDING_VALUE of one of the bindings in the
+ IDENTIFIER_BINDINGs list, so any time that this is non-NULL so is
+ IDENTIFIER_BINDING. */
+#define IDENTIFIER_CLASS_VALUE(NODE) \
+ (((struct lang_identifier *) (NODE))->class_value)
+
+/* The amount of time used by the file whose special "time identifier"
+ is NODE, represented as an INTEGER_CST. See get_time_identifier. */
+#define TIME_IDENTIFIER_TIME(NODE) IDENTIFIER_BINDING(NODE)
+
+/* For a "time identifier" this is a INTEGER_CST. The
+ TREE_INT_CST_LOW is 1 if the corresponding file is "interface only".
+ The TRE_INT_CST_HIGH is 1 if it is "interface unknown". */
+#define TIME_IDENTIFIER_FILEINFO(NODE) IDENTIFIER_CLASS_VALUE (NODE)
+
/* TREE_TYPE only indicates on local and class scope the current
type. For namespace scope, the presence of a type in any namespace
is indicated with global_type_node, and the real type behind must
@@ -216,14 +294,6 @@ struct tree_srcloc
#define SET_IDENTIFIER_IMPLICIT_DECL(NODE,VALUE) \
SET_LANG_ID(NODE, VALUE, implicit_decl)
-#define IDENTIFIER_AS_DESC(NODE) LANG_ID_FIELD(type_desc, NODE)
-#define SET_IDENTIFIER_AS_DESC(NODE,DESC) \
- SET_LANG_ID(NODE, DESC, type_desc)
-
-#define IDENTIFIER_AS_LIST(NODE) LANG_ID_FIELD(as_list, NODE)
-#define SET_IDENTIFIER_AS_LIST(NODE,LIST) \
- SET_LANG_ID(NODE, LIST, as_list)
-
#define IDENTIFIER_ERROR_LOCUS(NODE) LANG_ID_FIELD(error_locus, NODE)
#define SET_IDENTIFIER_ERROR_LOCUS(NODE,VALUE) \
SET_LANG_ID(NODE, VALUE, error_locus)
@@ -234,10 +304,12 @@ struct tree_srcloc
/* Nonzero if this identifier is the prefix for a mangled C++ operator name. */
#define IDENTIFIER_OPNAME_P(NODE) TREE_LANG_FLAG_2(NODE)
-#define IDENTIFIER_TYPENAME_P(NODE) \
- (! strncmp (IDENTIFIER_POINTER (NODE), \
- IDENTIFIER_POINTER (ansi_opname[(int) TYPE_EXPR]), \
- IDENTIFIER_LENGTH (ansi_opname[(int) TYPE_EXPR])))
+/* Nonzero if this identifier is the name of a type-conversion
+ operator. */
+#define IDENTIFIER_TYPENAME_P(NODE) \
+ (! strncmp (IDENTIFIER_POINTER (NODE), \
+ OPERATOR_TYPENAME_FORMAT, \
+ strlen (OPERATOR_TYPENAME_FORMAT)))
/* Nonzero means reject anything that ANSI standard C forbids. */
extern int pedantic;
@@ -278,7 +350,9 @@ extern tree intQI_type_node, unsigned_intQI_type_node;
extern tree intHI_type_node, unsigned_intHI_type_node;
extern tree intSI_type_node, unsigned_intSI_type_node;
extern tree intDI_type_node, unsigned_intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
extern tree intTI_type_node, unsigned_intTI_type_node;
+#endif
extern tree java_byte_type_node;
extern tree java_short_type_node;
@@ -321,10 +395,6 @@ extern int flag_gnu_xref;
extern int flag_gnu_binutils;
-/* Nonzero means ignore `#ident' directives. */
-
-extern int flag_no_ident;
-
/* Nonzero means warn about implicit declarations. */
extern int warn_implicit;
@@ -343,9 +413,13 @@ extern int warn_ctor_dtor_privacy;
extern int warn_return_type;
-/* Nonzero means give string constants the type `const char *'
- to get extra warnings from them. These warnings will be too numerous
- to be useful, except in thoroughly ANSIfied programs. */
+/* Nonzero means give string constants the type `const char *', as mandated
+ by the standard. */
+
+extern int flag_const_strings;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+ `char *'. */
extern int warn_write_strings;
@@ -472,6 +546,22 @@ extern int flag_do_squangling;
/* Nonzero if we want to issue diagnostics that the standard says are not
required. */
extern int flag_optional_diags;
+
+/* Nonzero means do not consider empty argument prototype to mean function
+ takes no arguments. */
+extern int flag_strict_prototype;
+
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
+extern int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+ The value of this flag is ignored if -pedantic is specified. */
+extern int flag_permissive;
+
+/* Nonzero if we want to obey access control semantics. */
+
+extern int flag_access_control;
+
/* C++ language-specific tree codes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@@ -495,7 +585,26 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* The _DECL for this _TYPE. */
#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
-#define IS_AGGR_TYPE(t) (TYPE_LANG_FLAG_5 (t))
+/* Nonzero if T is a class (or struct or union) type. Also nonzero
+ for template type parameters and typename types. Despite its name,
+ this macro has nothing to do with the definition of aggregate given
+ in the standard. Think of this macro as MAYBE_CLASS_TYPE_P. */
+#define IS_AGGR_TYPE(t) \
+ (TREE_CODE (t) == TEMPLATE_TYPE_PARM \
+ || TREE_CODE (t) == TYPENAME_TYPE \
+ || TREE_CODE (t) == TYPEOF_TYPE \
+ || TYPE_LANG_FLAG_5 (t))
+
+/* Set IS_AGGR_TYPE for T to VAL. T must be a class, struct, or
+ union type. */
+#define SET_IS_AGGR_TYPE(T, VAL) \
+ (TYPE_LANG_FLAG_5 (T) = (VAL))
+
+/* Nonzero if T is a class type. Zero for template type parameters,
+ typename types, and so forth. */
+#define CLASS_TYPE_P(t) \
+ (IS_AGGR_TYPE_CODE (TREE_CODE (t)) && IS_AGGR_TYPE (t))
+
#define IS_AGGR_TYPE_CODE(t) (t == RECORD_TYPE || t == UNION_TYPE)
#define IS_AGGR_TYPE_2(TYPE1,TYPE2) \
(TREE_CODE (TYPE1) == TREE_CODE (TYPE2) \
@@ -509,6 +618,32 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* True if this a "Java" type, defined in 'extern "Java"'. */
#define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3(NODE)
+/* The type qualifiers for this type, including the qualifiers on the
+ elements for an array type. */
+#define CP_TYPE_QUALS(NODE) \
+ ((TREE_CODE (NODE) != ARRAY_TYPE) \
+ ? TYPE_QUALS (NODE) : cp_type_quals (NODE))
+
+/* Nonzero if this type is const-qualified. */
+#define CP_TYPE_CONST_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_CONST) != 0)
+
+/* Nonzero if this type is volatile-qualified. */
+#define CP_TYPE_VOLATILE_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_VOLATILE) != 0)
+
+/* Nonzero if this type is restrict-qualified. */
+#define CP_TYPE_RESTRICT_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & TYPE_QUAL_RESTRICT) != 0)
+
+/* Nonzero if this type is const-qualified, but not
+ volatile-qualified. Other qualifiers are ignored. This macro is
+ used to test whether or not it is OK to bind an rvalue to a
+ reference. */
+#define CP_TYPE_CONST_NON_VOLATILE_P(NODE) \
+ ((CP_TYPE_QUALS (NODE) & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) \
+ == TYPE_QUAL_CONST)
+
#define DELTA_FROM_VTABLE_ENTRY(ENTRY) \
(!flag_vtable_thunks ? \
TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY)) \
@@ -537,23 +672,31 @@ enum languages { lang_c, lang_cplusplus, lang_java };
#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0)
#define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
-/* Statistics show that while the GNU C++ compiler may generate
- thousands of different types during a compilation run, it
- generates relatively few (tens) of classtypes. Because of this,
- it is not costly to store a generous amount of information
- in classtype nodes. This struct must fill out to a multiple of 4 bytes. */
+/* This structure provides additional information above and beyond
+ what is provide in the ordinary tree_type. In the past, we used it
+ for the types of class types, template parameters types, typename
+ types, and so forth. However, there can be many (tens to hundreds
+ of thousands) of template parameter types in a compilation, and
+ there's no need for this additional information in that case.
+ Therefore, we now use this data structure only for class types.
+
+ In the past, it was thought that there would be relatively few
+ class types. However, in the presence of heavy use of templates,
+ many (i.e., thousands) of classes can easily be generated.
+ Therefore, we should endeavor to keep the size of this structure to
+ a minimum. */
struct lang_type
{
struct
{
unsigned has_type_conversion : 1;
unsigned has_init_ref : 1;
- unsigned has_assignment : 1;
unsigned has_default_ctor : 1;
unsigned uses_multiple_inheritance : 1;
unsigned const_needs_init : 1;
unsigned ref_needs_init : 1;
unsigned has_const_assign_ref : 1;
+ unsigned anon_union : 1;
unsigned has_nonpublic_ctor : 2;
unsigned has_nonpublic_assign_ref : 2;
@@ -565,63 +708,54 @@ struct lang_type
unsigned has_call_overloaded : 1;
unsigned has_array_ref_overloaded : 1;
unsigned has_arrow_overloaded : 1;
- unsigned local_typedecls : 1;
unsigned interface_only : 1;
unsigned interface_unknown : 1;
-
unsigned needs_virtual_reinit : 1;
+
+ unsigned marks: 6;
unsigned vec_delete_takes_size : 1;
unsigned declared_class : 1;
+
unsigned being_defined : 1;
unsigned redefined : 1;
- unsigned marked : 1;
- unsigned marked2 : 1;
- unsigned marked3 : 1;
-
- unsigned marked4 : 1;
- unsigned marked5 : 1;
- unsigned marked6 : 1;
unsigned debug_requested : 1;
unsigned use_template : 2;
unsigned got_semicolon : 1;
unsigned ptrmemfunc_flag : 1;
-
unsigned is_signature : 1;
+
unsigned is_signature_pointer : 1;
unsigned is_signature_reference : 1;
unsigned has_opaque_typedecls : 1;
unsigned sigtable_has_been_generated : 1;
unsigned was_anonymous : 1;
- unsigned has_real_assignment : 1;
unsigned has_real_assign_ref : 1;
-
unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1;
+
unsigned has_complex_assign_ref : 1;
unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1;
+ unsigned is_partial_instantiation : 1;
+ unsigned has_mutable : 1;
+ unsigned com_interface : 1;
+ /* When adding a flag here, consider whether or not it ought to
+ apply to a template instance if it applies to the template.
+ If so, make sure to copy it in instantiate_class_template! */
/* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */
- unsigned dummy : 11;
+ unsigned dummy : 10;
} type_flags;
-#ifdef MI_MATRIX
- int cid;
-#endif
- int n_ancestors;
- int n_vancestors;
int vsize;
- int max_depth;
int vfield_parent;
- union tree_node *baselink_vec;
union tree_node *vfields;
union tree_node *vbases;
union tree_node *tags;
- char *memoized_table_entry;
union tree_node *search_slot;
@@ -630,17 +764,9 @@ struct lang_type
union tree_node *size;
- union tree_node *base_init_list;
union tree_node *abstract_virtuals;
- union tree_node *as_list;
- union tree_node *id_as_list;
- union tree_node *binfo_as_list;
union tree_node *friend_classes;
-#ifdef MI_MATRIX
- char *mi_matrix;
-#endif
-
union tree_node *rtti;
union tree_node *methods;
@@ -648,14 +774,10 @@ struct lang_type
union tree_node *signature;
union tree_node *signature_pointer_to;
union tree_node *signature_reference_to;
-
union tree_node *template_info;
-
- int linenum;
+ tree befriending_classes;
};
-#define CLASSTYPE_SOURCE_LINE(NODE) (TYPE_LANG_SPECIFIC(NODE)->linenum)
-
/* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class
1=implicit template instantiation
@@ -669,13 +791,6 @@ struct lang_type
/* List of friends which were defined inline in this class definition. */
#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
-/* Nonzero for _CLASSTYPE means that the _CLASSTYPE either has
- a special meaning for the assignment operator ("operator="),
- or one of its fields (or base members) has a special meaning
- defined. */
-#define TYPE_HAS_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assignment)
-#define TYPE_HAS_REAL_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assignment)
-
/* Nonzero for _CLASSTYPE means that operator new and delete are defined,
respectively. */
#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new)
@@ -690,9 +805,6 @@ struct lang_type
(TYPE_NEEDS_DESTRUCTOR (NODE) \
|| (TYPE_LANG_SPECIFIC (NODE) && TYPE_VEC_DELETE_TAKES_SIZE (NODE)))
-/* Nonzero for TREE_LIST or _TYPE node means that this node is class-local. */
-#define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE))
-
/* Nonzero means that this _CLASSTYPE node defines ways of converting
itself to other types. */
#define TYPE_HAS_CONVERSION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_type_conversion)
@@ -751,7 +863,7 @@ struct lang_type
signature reference type. */
#define SIGNATURE_REFERENCE_TO(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature_reference_to)
-/* The is the VAR_DECL that contains NODE's rtti. */
+/* The is the basetype that contains NODE's rtti. */
#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti)
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
@@ -773,7 +885,12 @@ struct lang_type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
-/* List of lists of member functions defined in this class. */
+/* Vector member functions defined in this class. Each element is
+ either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
+ functions with the same name end up in the same slot. The first
+ two elements are for constructors, and destructors, respectively.
+ These are followed by ordinary member functions. There may be
+ empty entries at the end of the vector. */
#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* The first type conversion operator in the class (the others can be
@@ -784,30 +901,46 @@ struct lang_type
? TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 2) \
: NULL_TREE;
-/* Pointer from any member function to the head of the list of
- member functions of the type that member function belongs to. */
-#define CLASSTYPE_BASELINK_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->baselink_vec)
-
/* Mark bits for depth-first and breath-first searches. */
-#define CLASSTYPE_MARKED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked)
-#define CLASSTYPE_MARKED2(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked2)
-#define CLASSTYPE_MARKED3(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked3)
-#define CLASSTYPE_MARKED4(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked4)
-#define CLASSTYPE_MARKED5(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked5)
-#define CLASSTYPE_MARKED6(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.marked6)
+
+/* Get the value of the Nth mark bit. */
+#define CLASSTYPE_MARKED_N(NODE, N) \
+ (((CLASS_TYPE_P (NODE) ? TYPE_LANG_SPECIFIC (NODE)->type_flags.marks \
+ : TYPE_ALIAS_SET (NODE)) & (1 << N)) != 0)
+
+/* Set the Nth mark bit. */
+#define SET_CLASSTYPE_MARKED_N(NODE, N) \
+ (CLASS_TYPE_P (NODE) \
+ ? (TYPE_LANG_SPECIFIC (NODE)->type_flags.marks |= (1 << (N))) \
+ : (TYPE_ALIAS_SET (NODE) |= (1 << (N))))
+
+/* Clear the Nth mark bit. */
+#define CLEAR_CLASSTYPE_MARKED_N(NODE, N) \
+ (CLASS_TYPE_P (NODE) \
+ ? (TYPE_LANG_SPECIFIC (NODE)->type_flags.marks &= ~(1 << (N))) \
+ : (TYPE_ALIAS_SET (NODE) &= ~(1 << (N))))
+
+/* Get the value of the mark bits. */
+#define CLASSTYPE_MARKED(NODE) CLASSTYPE_MARKED_N(NODE, 0)
+#define CLASSTYPE_MARKED2(NODE) CLASSTYPE_MARKED_N(NODE, 1)
+#define CLASSTYPE_MARKED3(NODE) CLASSTYPE_MARKED_N(NODE, 2)
+#define CLASSTYPE_MARKED4(NODE) CLASSTYPE_MARKED_N(NODE, 3)
+#define CLASSTYPE_MARKED5(NODE) CLASSTYPE_MARKED_N(NODE, 4)
+#define CLASSTYPE_MARKED6(NODE) CLASSTYPE_MARKED_N(NODE, 5)
+
/* Macros to modify the above flags */
-#define SET_CLASSTYPE_MARKED(NODE) (CLASSTYPE_MARKED(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED(NODE) (CLASSTYPE_MARKED(NODE) = 0)
-#define SET_CLASSTYPE_MARKED2(NODE) (CLASSTYPE_MARKED2(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED2(NODE) (CLASSTYPE_MARKED2(NODE) = 0)
-#define SET_CLASSTYPE_MARKED3(NODE) (CLASSTYPE_MARKED3(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED3(NODE) (CLASSTYPE_MARKED3(NODE) = 0)
-#define SET_CLASSTYPE_MARKED4(NODE) (CLASSTYPE_MARKED4(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED4(NODE) (CLASSTYPE_MARKED4(NODE) = 0)
-#define SET_CLASSTYPE_MARKED5(NODE) (CLASSTYPE_MARKED5(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED5(NODE) (CLASSTYPE_MARKED5(NODE) = 0)
-#define SET_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 1)
-#define CLEAR_CLASSTYPE_MARKED6(NODE) (CLASSTYPE_MARKED6(NODE) = 0)
+#define SET_CLASSTYPE_MARKED(NODE) SET_CLASSTYPE_MARKED_N(NODE, 0)
+#define CLEAR_CLASSTYPE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 0)
+#define SET_CLASSTYPE_MARKED2(NODE) SET_CLASSTYPE_MARKED_N(NODE, 1)
+#define CLEAR_CLASSTYPE_MARKED2(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 1)
+#define SET_CLASSTYPE_MARKED3(NODE) SET_CLASSTYPE_MARKED_N(NODE, 2)
+#define CLEAR_CLASSTYPE_MARKED3(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 2)
+#define SET_CLASSTYPE_MARKED4(NODE) SET_CLASSTYPE_MARKED_N(NODE, 3)
+#define CLEAR_CLASSTYPE_MARKED4(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 3)
+#define SET_CLASSTYPE_MARKED5(NODE) SET_CLASSTYPE_MARKED_N(NODE, 4)
+#define CLEAR_CLASSTYPE_MARKED5(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 4)
+#define SET_CLASSTYPE_MARKED6(NODE) SET_CLASSTYPE_MARKED_N(NODE, 5)
+#define CLEAR_CLASSTYPE_MARKED6(NODE) CLEAR_CLASSTYPE_MARKED_N(NODE, 5)
/* A list of the nested tag-types (class, struct, union, or enum)
found within this class. The TREE_PURPOSE of each node is the name
@@ -838,42 +971,15 @@ struct lang_type
#define CLASSTYPE_N_BASECLASSES(NODE) \
(TYPE_BINFO_BASETYPES (NODE) ? TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES(NODE)) : 0)
-/* Memoize the number of super classes (base classes) tha this node
- has. That way we can know immediately (albeit conservatively how
- large a multiple-inheritance matrix we need to build to find
- derivation information. */
-#define CLASSTYPE_N_SUPERCLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->n_ancestors)
-#define CLASSTYPE_N_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->n_vancestors)
-
-/* Record how deep the inheritance is for this class so `void*' conversions
- are less favorable than a conversion to the most base type. */
-#define CLASSTYPE_MAX_DEPTH(NODE) (TYPE_LANG_SPECIFIC(NODE)->max_depth)
-
/* Used for keeping search-specific information. Any search routine
which uses this must define what exactly this slot is used for. */
#define CLASSTYPE_SEARCH_SLOT(NODE) (TYPE_LANG_SPECIFIC(NODE)->search_slot)
-/* Entry for keeping memoization tables for this type to
- hopefully speed up search routines. Since it is a pointer,
- it can mean almost anything. */
-#define CLASSTYPE_MTABLE_ENTRY(NODE) (TYPE_LANG_SPECIFIC(NODE)->memoized_table_entry)
-
/* These are the size, mode and alignment of the type without its
virtual base classes, for when we use this type as a base itself. */
#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->size)
#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC(NODE)->align)
-/* A cons list of structure elements which either have constructors
- to be called, or virtual function table pointers which
- need initializing. Depending on what is being initialized,
- the TREE_PURPOSE and TREE_VALUE fields have different meanings:
-
- Member initialization: <FIELD_DECL, TYPE>
- Base class construction: <NULL_TREE, BASETYPE>
- Base class initialization: <BASE_INITIALIZATION, THESE_INITIALIZATIONS>
- Whole type: <MEMBER_INIT, BASE_INIT>. */
-#define CLASSTYPE_BASE_INIT_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->base_init_list)
-
/* A cons list of virtual functions which cannot be inherited by
derived classes. When deriving from this type, the derived
class must provide its own definition for each of these functions. */
@@ -892,9 +998,6 @@ struct lang_type
the virtual function table will be written out. */
#define CLASSTYPE_VTABLE_NEEDS_WRITING(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.vtable_needs_writing)
-/* Nonzero means that this type defines its own local type declarations. */
-#define CLASSTYPE_LOCAL_TYPEDECLS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.local_typedecls)
-
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_default_ctor)
@@ -906,26 +1009,22 @@ struct lang_type
/* Ditto, for operator=. */
#define TYPE_HAS_NONPUBLIC_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_nonpublic_assign_ref)
-/* Many routines need to cons up a list of basetypes for access
- checking. This field contains a TREE_LIST node whose TREE_VALUE
- is the main variant of the type, and whose TREE_VIA_PUBLIC
- and TREE_VIA_VIRTUAL bits are correctly set. */
-#define CLASSTYPE_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->as_list)
-/* Same, but cache a list whose value is the name of this type. */
-#define CLASSTYPE_ID_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->id_as_list)
-/* Same, but cache a list whose value is the binfo of this type. */
-#define CLASSTYPE_BINFO_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->binfo_as_list)
-
-/* A list of class types with which this type is a friend. The
+/* Nonzero means that this type contains a mutable member */
+#define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable)
+#define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
+
+/* Nonzero means that this type is meant for communication via COM. */
+#define CLASSTYPE_COM_INTERFACE(NODE) \
+ (TYPE_LANG_SPECIFIC(NODE)->type_flags.com_interface)
+
+/* A list of class types of which this type is a friend. The
TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
case of a template friend. */
#define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes)
-#ifdef MI_MATRIX
-/* Keep an inheritance lattice around so we can quickly tell whether
- a type is derived from another or not. */
-#define CLASSTYPE_MI_MATRIX(NODE) (TYPE_LANG_SPECIFIC(NODE)->mi_matrix)
-#endif
+/* A list of the classes which grant friendship to this class. */
+#define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE)->befriending_classes)
/* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
@@ -952,17 +1051,20 @@ struct lang_type
/* Additional macros for inheritance information. */
-/* When following an binfo-specific chain, this is the cumulative
- via-public flag. */
-#define BINFO_VIA_PUBLIC(NODE) TREE_LANG_FLAG_5 (NODE)
+/* The BINFO_INHERITANCE_CHAIN is used opposite to the description in
+ gcc/tree.h. In particular if D is derived from B then the BINFO
+ for B (in D) will have a BINFO_INHERITANCE_CHAIN pointing to
+ D. In tree.h, this pointer is described as pointing in other
+ direction. There is a different BINFO for each path to a virtual
+ base; BINFOs for virtual bases are not shared. In addition, shared
+ versions of each of the virtual class BINFOs are stored in
+ CLASSTYPE_VBASECLASSES.
-#ifdef MI_MATRIX
-/* When building a matrix to determine by a single lookup
- whether one class is derived from another or not,
- this field is the index of the class in the table. */
-#define CLASSTYPE_CID(NODE) (TYPE_LANG_SPECIFIC(NODE)->cid)
-#define BINFO_CID(NODE) CLASSTYPE_CID(BINFO_TYPE(NODE))
-#endif
+ We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private
+ inheritance is indicated by the absence of the other two flags, not
+ by TREE_VIAR_PRIVATE, which is unused.
+
+ The TREE_CHAIN is for scratch space in search.c. */
/* Nonzero means marked by DFS or BFS search, including searches
by `get_binfo' and `get_base_distance'. */
@@ -972,12 +1074,6 @@ struct lang_type
#define SET_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=1))
#define CLEAR_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=0))
-/* Nonzero means marked in building initialization list. */
-#define BINFO_BASEINIT_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-/* Modifier macros */
-#define SET_BINFO_BASEINIT_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-#define CLEAR_BINFO_BASEINIT_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-
/* Nonzero means marked in search through virtual inheritance hierarchy. */
#define BINFO_VBASE_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
/* Modifier macros */
@@ -1002,11 +1098,13 @@ struct lang_type
#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1))
#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0))
-/* Nonzero means this class has initialized its virtual baseclasses. */
-#define BINFO_VBASE_INIT_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):TREE_LANG_FLAG_5(NODE))
-#define SET_BINFO_VBASE_INIT_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_5(NODE)=1))
-#define CLEAR_BINFO_VBASE_INIT_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED5(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_5(NODE)=0))
+/* Nonzero means this class has done dfs_pushdecls. */
+#define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE)
+#define SET_BINFO_PUSHDECLS_MARKED(NODE) SET_BINFO_VTABLE_PATH_MARKED (NODE)
+#define CLEAR_BINFO_PUSHDECLS_MARKED(NODE) CLEAR_BINFO_VTABLE_PATH_MARKED (NODE)
+
+/* Used by various search routines. */
+#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
/* Accessor macros for the vfield slots in structures. */
@@ -1027,12 +1125,28 @@ struct lang_type
#define TREE_PARMLIST(NODE) ((NODE)->common.unsigned_flag) /* overloaded! */
/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
- this type can raise. */
+ this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE
+ will be NULL_TREE to indicate a throw specification of `(...)', or,
+ equivalently, no throw specification. */
#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE)
+/* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'. */
+#define TYPE_NOTHROW_P(NODE) \
+ (TYPE_RAISES_EXCEPTIONS (NODE) \
+ && TREE_VALUE (TYPE_RAISES_EXCEPTIONS (NODE)) == NULL_TREE)
+
/* The binding level associated with the namespace. */
#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
+
+/* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or
+ a lang_decl (which has lang_decl_flags as its initial prefix). A
+ FUNCTION_DECL, NAMESPACE_DECL, TYPE_DECL, or USING_DECL may have a
+ full lang_decl. A FIELD_DECL, or a static data member VAR_DECL,
+ will have only lang_decl_flags. Thus, one should only access the
+ members of lang_decl that are not in lang_decl_flags for DECLs that
+ are not FIELD_DECLs or VAR_DECLs. */
+
struct lang_decl_flags
{
#ifdef ONLY_INT_FIELDS
@@ -1043,8 +1157,6 @@ struct lang_decl_flags
unsigned operator_attr : 1;
unsigned constructor_attr : 1;
- unsigned returns_first_arg : 1;
- unsigned preserves_first_arg : 1;
unsigned friend_attr : 1;
unsigned static_function : 1;
unsigned const_memfunc : 1;
@@ -1061,9 +1173,10 @@ struct lang_decl_flags
unsigned nonconverting : 1;
unsigned declared_inline : 1;
unsigned not_really_extern : 1;
- unsigned comdat : 1;
unsigned needs_final_overrider : 1;
- unsigned dummy : 3;
+ unsigned bitfield : 1;
+ unsigned defined_in_class : 1;
+ unsigned dummy : 4;
tree access;
tree context;
@@ -1077,6 +1190,7 @@ struct lang_decl
struct lang_decl_flags decl_flags;
tree main_decl_variant;
+ tree befriending_classes;
struct pending_inline *pending_inline_info;
};
@@ -1098,26 +1212,34 @@ struct lang_decl
/* For FUNCTION_DECLs: nonzero means that this function is a constructor. */
#define DECL_CONSTRUCTOR_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_attr)
-#define DECL_DESTRUCTOR_P(NODE) (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME(NODE)))
+
+/* There ought to be a better way to find out whether or not something is
+ a destructor. */
+#define DECL_DESTRUCTOR_P(NODE) \
+ (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (NODE)) \
+ && DECL_LANGUAGE (NODE) == lang_cplusplus)
+
+#define DECL_CONV_FN_P(NODE) \
+ (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)) && TREE_TYPE (DECL_NAME (NODE)))
/* For FUNCTION_DECLs: nonzero means that this function is a constructor
for an object with virtual baseclasses. */
#define DECL_CONSTRUCTOR_FOR_VBASE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.constructor_for_vbase_attr)
+/* Non-zero for a FUNCTION_DECL that declares a type-info function. */
+#define DECL_TINFO_FN_P(NODE) \
+ (TREE_CODE (NODE) == FUNCTION_DECL \
+ && DECL_ARTIFICIAL (NODE) \
+ && DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag)
+
+/* Mark NODE as a type-info function. */
+#define SET_DECL_TINFO_FN_P(NODE) \
+ (DECL_LANG_SPECIFIC((NODE))->decl_flags.mutable_flag = 1)
+
/* For FUNCTION_DECLs: nonzero means that this function is a default
implementation of a signature method. */
#define IS_DEFAULT_IMPLEMENTATION(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.is_default_implementation)
-/* For FUNCTION_DECLs: nonzero means that the constructor
- is known to return a non-zero `this' unchanged. */
-#define DECL_RETURNS_FIRST_ARG(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.returns_first_arg)
-
-/* Nonzero for FUNCTION_DECL means that this constructor is known to
- not make any assignment to `this', and therefore can be trusted
- to return it unchanged. Otherwise, we must re-assign `current_class_ptr'
- after performing base initializations. */
-#define DECL_PRESERVES_THIS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.preserves_first_arg)
-
/* Nonzero for _DECL means that this decl appears in (or will appear
in) as a member in a RECORD_TYPE or UNION_TYPE node. It is also for
detecting circularity in case members are multiply defined. In the
@@ -1125,11 +1247,20 @@ struct lang_decl
should be allocated. */
#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3(NODE))
+/* Nonzero if the DECL was defined in the class definition itself,
+ rather than outside the class. */
+#define DECL_DEFINED_IN_CLASS_P(DECL) \
+ (DECL_LANG_SPECIFIC (DECL)->decl_flags.defined_in_class)
+
/* Nonzero for FUNCTION_DECL means that this decl is just a
friend declaration, and should not be added to the list of
member functions for this class. */
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.friend_attr)
+/* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */
+#define DECL_BEFRIENDING_CLASSES(NODE) \
+ (DECL_LANG_SPECIFIC(NODE)->befriending_classes)
+
/* Nonzero for FUNCTION_DECL means that this decl is a static
member function. */
#define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function)
@@ -1158,6 +1289,12 @@ struct lang_decl
has `this' as volatile X *const. */
#define DECL_VOLATILE_MEMFUNC_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.volatile_memfunc)
+/* Nonzero for a DECL means that this member is a non-static member. */
+#define DECL_NONSTATIC_MEMBER_P(NODE) \
+ ((TREE_CODE (NODE) == FUNCTION_DECL \
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE)) \
+ || TREE_CODE (NODE) == FIELD_DECL)
+
/* Nonzero for _DECL means that this member object type
is mutable. */
#define DECL_MUTABLE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag)
@@ -1190,6 +1327,10 @@ struct lang_decl
(DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE))
+/* For a virtual function, the base where we find its vtable entry.
+ For a non-virtual function, the base where it is defined. */
+#define DECL_VIRTUAL_CONTEXT(NODE) DECL_CONTEXT (NODE)
+
/* 1 iff NODE has namespace scope, including the global namespace. */
#define DECL_NAMESPACE_SCOPE_P(NODE) \
(DECL_CONTEXT (NODE) == NULL_TREE \
@@ -1200,6 +1341,11 @@ struct lang_decl
(DECL_CONTEXT (NODE) \
&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (NODE))) == 't')
+/* 1 iff NODE is function-local. */
+#define DECL_FUNCTION_SCOPE_P(NODE) \
+ (DECL_CONTEXT (NODE) \
+ && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL)
+
/* For a NAMESPACE_DECL: the list of using namespace directives
The PURPOSE is the used namespace, the value is the namespace
that is the common ancestor. */
@@ -1215,6 +1361,11 @@ struct lang_decl
#define ORIGINAL_NAMESPACE(NODE) \
(DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE))
+/* In a non-local VAR_DECL with static storage duration, this is the
+ initialization priority. If this value is zero, the NODE will be
+ initialized at the DEFAULT_INIT_PRIORITY. */
+#define DECL_INIT_PRIORITY(NODE) (DECL_FIELD_SIZE ((NODE)))
+
/* In a TREE_LIST concatenating using directives, indicate indirekt
directives */
#define TREE_INDIRECT_USING(NODE) ((NODE)->common.lang_flag_0)
@@ -1246,23 +1397,86 @@ struct lang_decl
/* For a VAR_DECL or FUNCTION_DECL: template-specific information. */
#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.template_info)
+
+/* Template information for a RECORD_TYPE or UNION_TYPE. */
#define CLASSTYPE_TEMPLATE_INFO(NODE) (TYPE_LANG_SPECIFIC(NODE)->template_info)
+
+/* Template information for an ENUMERAL_TYPE. Although an enumeration may
+ not be a primary template, it may be declared within the scope of a
+ primary template and the enumeration constants may depend on
+ non-type template parameters. */
+#define ENUM_TEMPLATE_INFO(NODE) (TYPE_BINFO (NODE))
+
+/* Template information for a template template parameter. */
+#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) (TYPE_BINFO (NODE))
+
+/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TEMPLATE_INFO(NODE) \
+ (TREE_CODE (NODE) == ENUMERAL_TYPE \
+ ? ENUM_TEMPLATE_INFO (NODE) : \
+ (TREE_CODE (NODE) == TEMPLATE_TEMPLATE_PARM \
+ ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) \
+ : CLASSTYPE_TEMPLATE_INFO (NODE)))
+
+/* Set the template information for an ENUMERAL_, RECORD_, or
+ UNION_TYPE to VAL. */
+#define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \
+ (TREE_CODE (NODE) == ENUMERAL_TYPE \
+ ? (ENUM_TEMPLATE_INFO (NODE) = VAL) \
+ : (CLASSTYPE_TEMPLATE_INFO (NODE) = VAL))
+
#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
#define TI_ARGS(NODE) (TREE_VALUE (NODE))
#define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE))
-#define TI_USES_TEMPLATE_PARMS(NODE) TREE_LANG_FLAG_0 (NODE)
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
-/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
- that the template is a specialization of a member template, but
- that we don't yet know which one. */
-#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+
+/* The TEMPLATE_DECL instantiated or specialized by NODE. This
+ TEMPLATE_DECL will be the immediate parent, not the most general
+ template. For example, in:
+
+ template <class T> struct S { template <class U> void f(U); }
+
+ the FUNCTION_DECL for S<int>::f<double> will have, as its
+ DECL_TI_TEMPLATE, `template <class U> S<int>::f<U>'.
+
+ As a special case, for a member friend template of a template
+ class, this value will not be a TEMPLATE_DECL, but rather a
+ LOOKUP_EXPR or IDENTIFIER_NODE indicating the name of the template
+ and any explicit template arguments provided. For example, in:
+
+ template <class T> struct S { friend void f<int>(int, double); }
+
+ the DECL_TI_TEMPLATE will be a LOOKUP_EXPR for `f' and the
+ DECL_TI_ARGS will be {int}. */
#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
+
+/* The template arguments used to obtain this decl from the most
+ general form of DECL_TI_TEMPLATE. For the example given for
+ DECL_TI_TEMPLATE, the DECL_TI_ARGS will be {int, double}. These
+ are always the full set of arguments required to instantiate this
+ declaration from the most general template specialized here. */
#define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE))
+#define ENUM_TI_TEMPLATE(NODE) \
+ TI_TEMPLATE (ENUM_TEMPLATE_INFO (NODE))
+#define ENUM_TI_ARGS(NODE) \
+ TI_ARGS (ENUM_TEMPLATE_INFO (NODE))
+
+/* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TI_TEMPLATE(NODE) \
+ (TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE)))
+
+/* Like DECL_TI_ARGS, , but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+#define TYPE_TI_ARGS(NODE) \
+ (TI_ARGS (TYPE_TEMPLATE_INFO (NODE)))
+
#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
+/* Nonzero if the NODE corresponds to the template parameters for a
+ member template, whose inline definition is being processed after
+ the class definition is complete. */
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
@@ -1281,7 +1495,15 @@ struct lang_decl
&& !CLASSTYPE_USE_TEMPLATE (NODE) \
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
-#define TYPENAME_TYPE_FULLNAME(NODE) CLASSTYPE_SIZE (NODE)
+/* The name used by the user to name the typename type. Typically,
+ this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
+ corresponding TYPE_DECL. However, this may also be a
+ TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */
+#define TYPENAME_TYPE_FULLNAME(NODE) TYPE_BINFO (NODE)
+
+/* Nonzero if NODE is an implicit typename. */
+#define IMPLICIT_TYPENAME_P(NODE) \
+ (TREE_CODE (NODE) == TYPENAME_TYPE && TREE_TYPE (NODE))
/* Nonzero in INTEGER_CST means that this int is negative by dint of
using a twos-complement negated operand. */
@@ -1302,7 +1524,7 @@ struct lang_decl
/* Nonzero in IDENTIFIER_NODE means that this name is not the name the user
gave; it's a DECL_NESTED_TYPENAME. Someone may want to set this on
mangled function names, too, but it isn't currently. */
-#define TREE_MANGLED(NODE) (TREE_LANG_FLAG_0 (NODE))
+#define TREE_MANGLED(NODE) (FOO)
#endif
#if 0 /* UNUSED */
@@ -1338,6 +1560,12 @@ extern int flag_new_for_scope;
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp))
+/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */
+#define DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_SPECIFIC (NODE) && DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield)
+#define SET_DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield = 1)
+
/* Nonzero if the type T promotes to itself.
ANSI C states explicitly the list of types that promote;
in particular, short promotes to int even if they have the same width. */
@@ -1377,8 +1605,9 @@ extern int flag_new_for_scope;
has been duly initialized in its constructor. */
#define TREE_HAS_CONSTRUCTOR(NODE) (TREE_LANG_FLAG_4(NODE))
-#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
- && CONSTRUCTOR_ELTS (NODE) == NULL_TREE)
+#define EMPTY_CONSTRUCTOR_P(NODE) (TREE_CODE (NODE) == CONSTRUCTOR \
+ && CONSTRUCTOR_ELTS (NODE) == NULL_TREE \
+ && ! TREE_HAS_CONSTRUCTOR (NODE))
#if 0
/* Indicates that a NON_LVALUE_EXPR came from a C++ reference.
@@ -1442,8 +1671,63 @@ extern int flag_new_for_scope;
/* Nonzero for _TYPE node means that this type is a pointer to member
function type. */
-#define TYPE_PTRMEMFUNC_P(NODE) (TREE_CODE(NODE) == RECORD_TYPE && TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag)
-#define TYPE_PTRMEMFUNC_FLAG(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag)
+#define TYPE_PTRMEMFUNC_P(NODE) \
+ (TREE_CODE(NODE) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (NODE))
+#define TYPE_PTRMEMFUNC_FLAG(NODE) \
+ (TYPE_LANG_SPECIFIC(NODE)->type_flags.ptrmemfunc_flag)
+
+/* A pointer-to-function member type looks like:
+
+ struct {
+ short __delta;
+ short __index;
+ union {
+ P __pfn;
+ short __delta2;
+ } __pfn_or_delta2;
+ };
+
+ where P is a POINTER_TYPE to a METHOD_TYPE appropriate for the
+ pointer to member. The fields are used as follows:
+
+ If __INDEX is -1, then the function to call is non-virtual, and
+ is located at the address given by __PFN.
+
+ If __INDEX is zero, then this a NULL pointer-to-member.
+
+ Otherwise, the function to call is virtual. Then, __DELTA2 gives
+ the offset from an instance of the object to the virtual function
+ table, and __INDEX - 1 is the index into the vtable to use to
+ find the function.
+
+ The value to use for the THIS parameter is the address of the
+ object plus __DELTA.
+
+ For example, given:
+
+ struct B1 {
+ int i;
+ };
+
+ struct B2 {
+ double d;
+ void f();
+ };
+
+ struct S : public B1, B2 {};
+
+ the pointer-to-member for `&S::f' looks like:
+
+ { 4, -1, { &f__2B2 } };
+
+ The `4' means that given an `S*' you have to add 4 bytes to get to
+ the address of the `B2*'. Then, the -1 indicates that this is a
+ non-virtual function. Of course, `&f__2B2' is the name of that
+ function.
+
+ (Of course, the exactl values may differ depending on the mangling
+ scheme, sizes of types, and such.). */
+
/* Get the POINTER_TYPE to the METHOD_TYPE associated with this
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
before using this macro. */
@@ -1458,8 +1742,19 @@ extern int flag_new_for_scope;
#define TYPE_GET_PTRMEMFUNC_TYPE(NODE) ((tree)TYPE_LANG_SPECIFIC(NODE))
#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) (TYPE_LANG_SPECIFIC(NODE) = ((struct lang_type *)(void*)(VALUE)))
/* These are to get the delta2 and pfn fields from a TYPE_PTRMEMFUNC_P. */
-#define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, NULL_TREE, 0), delta2_identifier, NULL_TREE, 0))
-#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, NULL_TREE, 0), pfn_identifier, NULL_TREE, 0))
+#define DELTA2_FROM_PTRMEMFUNC(NODE) delta2_from_ptrmemfunc ((NODE))
+#define PFN_FROM_PTRMEMFUNC(NODE) pfn_from_ptrmemfunc ((NODE))
+
+/* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for
+ `X'. */
+#define PTRMEM_CST_CLASS(NODE) \
+ (TYPE_PTRMEM_P (TREE_TYPE (NODE)) \
+ ? TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (NODE))) \
+ : TYPE_PTRMEMFUNC_OBJECT_TYPE (TREE_TYPE (NODE)))
+
+/* For a pointer-to-member constant `X::Y' this is the _DECL for
+ `Y'. */
+#define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t) NODE)->member)
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. */
@@ -1469,19 +1764,20 @@ extern int flag_new_for_scope;
specified in its declaration. */
#define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE))
-/* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
-#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
-
/* Nonzero in FUNCTION_DECL means it is really an operator.
Just used to communicate formatting information to dbxout.c. */
#define DECL_OPERATOR(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.operator_attr)
#define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0)
-/* Nonzero if TYPE is an anonymous union type. */
-#define ANON_UNION_TYPE_P(TYPE) \
- (TREE_CODE (TYPE) == UNION_TYPE \
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TYPE)))
+/* Nonzero if TYPE is an anonymous union type. We have to use a flag for
+ this because "A union for which objects or pointers are declared is not
+ an anonymous union" [class.union]. */
+#define ANON_UNION_TYPE_P(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE) \
+ && TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union)
+#define SET_ANON_UNION_TYPE_P(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union = 1)
#define UNKNOWN_TYPE LANG_TYPE
@@ -1515,9 +1811,15 @@ extern int flag_new_for_scope;
the TREE_PUROSE will be the class type, and the TREE_VALUE will be
NULL_TREE. */
#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
+#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
+#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
-/* The DECL_ACCESS is used to record under which context
- special access rules apply. */
+/* The DECL_ACCESS, if non-NULL, is a TREE_LIST. The TREE_PURPOSE of
+ each node is a type; the TREE_VALUE is the access granted for this
+ DECL in that type. The DECL_ACCESS is set by access declarations.
+ For example, if a member that would normally be public in a
+ derived class is made protected, then the derived class and the
+ protected_access_node will appear in the DECL_ACCESS for the node. */
#define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.access)
/* C++: all of these are overloaded!
@@ -1528,32 +1830,88 @@ extern int flag_new_for_scope;
/* Accessor macros for C++ template decl nodes. */
/* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node
- indicates the level of the template parameters, with 1 being the
- outermost set of template parameters. The TREE_VALUE is a vector,
- whose elements are the template parameters at each level. Each
- element in the vector is a TREE_LIST, whose TREE_VALUE is a
- PARM_DECL (if the parameter is a non-type parameter), or a
- TYPE_DECL (if the parameter is a type parameter). The TREE_PURPOSE
- is the default value, if any. The TEMPLATE_PARM_INDEX for the
- parameter is avilable as the DECL_INITIAL (for a PARM_DECL) or as
- the TREE_TYPE (for a TYPE_DECL). */
+ is a INT_CST whose TREE_INT_CST_HIGH indicates the level of the
+ template parameters, with 1 being the outermost set of template
+ parameters. The TREE_VALUE is a vector, whose elements are the
+ template parameters at each level. Each element in the vector is a
+ TREE_LIST, whose TREE_VALUE is a PARM_DECL (if the parameter is a
+ non-type parameter), or a TYPE_DECL (if the parameter is a type
+ parameter). The TREE_PURPOSE is the default value, if any. The
+ TEMPLATE_PARM_INDEX for the parameter is avilable as the
+ DECL_INITIAL (for a PARM_DECL) or as the TREE_TYPE (for a
+ TYPE_DECL). */
#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
#define DECL_NTPARMS(NODE) \
TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE))
-/* For class templates. */
-#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
/* For function, method, class-data templates. */
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
+/* For a static member variable template, the
+ DECL_TEMPLATE_INSTANTIATIONS list contains the explicitly and
+ implicitly generated instantiations of the variable. There are no
+ partial instantiations of static member variables, so all of these
+ will be full instantiations.
+
+ For a class template the DECL_TEMPLATE_INSTANTIATIONS lists holds
+ all instantiations and specializations of the class type, including
+ partial instantiations and partial specializations.
+
+ In both cases, the TREE_PURPOSE of each node contains the arguments
+ used; the TREE_VALUE contains the generated variable. The template
+ arguments are always complete. For example, given:
+
+ template <class T> struct S1 {
+ template <class U> struct S2 {};
+ template <class U> struct S2<U*> {};
+ };
+
+ the record for the partial specialization will contain, as its
+ argument list, { {T}, {U*} }, and will be on the
+ DECL_TEMPLATE_INSTANTIATIONS list for `template <class T> template
+ <class U> struct S1<T>::S2'.
+
+ This list is not used for function templates. */
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
+/* For a function template, the DECL_TEMPLATE_SPECIALIZATIONS lists
+ contains all instantiations and specializations of the function,
+ including partial instantiations. For a partial instantiation
+ which is a specialization, this list holds only full
+ specializations of the template that are instantiations of the
+ partial instantiation. For example, given:
+
+ template <class T> struct S {
+ template <class U> void f(U);
+ template <> void f(T);
+ };
+
+ the `S<int>::f<int>(int)' function will appear on the
+ DECL_TEMPLATE_SPECIALIZATIONS list for both `template <class T>
+ template <class U> void S<T>::f(U)' and `template <class T> void
+ S<int>::f(T)'. In the latter case, however, it will have only the
+ innermost set of arguments (T, in this case). The DECL_TI_TEMPLATE
+ for the function declaration will point at the specialization, not
+ the fully general template.
+
+ For a class template, this list contains the partial
+ specializations of this template. (Full specializations are not
+ recorded on this list.) The TREE_PURPOSE holds the innermost
+ arguments used in the partial specialization (e.g., for `template
+ <class T> struct S<T*, int>' this will be `T*'.) The TREE_VALUE
+ holds the innermost template parameters for the specialization
+ (e.g., `T' in the example above.) The TREE_TYPE is the _TYPE node
+ for the partial specialization.
+
+ This list is not used for static variable templates. */
+#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
-/* Nonzero for TEMPLATE_DECL nodes that represents template template
- parameters */
+/* Nonzero for a DECL which is actually a template parameter. */
+#define DECL_TEMPLATE_PARM_P(NODE) \
+ DECL_LANG_FLAG_0 (NODE)
+
#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \
- (TREE_CODE (NODE) == TEMPLATE_DECL && TREE_TYPE (NODE) \
- && TREE_CODE (TREE_TYPE (NODE)) == TEMPLATE_TEMPLATE_PARM)
+ (TREE_CODE (NODE) == TEMPLATE_DECL && DECL_TEMPLATE_PARM_P (NODE))
#define DECL_FUNCTION_TEMPLATE_P(NODE) \
(TREE_CODE (NODE) == TEMPLATE_DECL \
@@ -1616,8 +1974,36 @@ extern int flag_new_for_scope;
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 3)
+/* Non-zero if DECL is a friend function which is an instantiation
+ from the point of view of the compiler, but not from the point of
+ view of the language. For example given:
+ template <class T> struct S { friend void f(T) {}; };
+ the declaration of `void f(int)' generated when S<int> is
+ instantiated will not be a DECL_TEMPLATE_INSTANTIATION, but will be
+ a DECL_FRIEND_PSUEDO_TEMPLATE_INSTANTIATION. */
+#define DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION(DECL) \
+ (DECL_TEMPLATE_INFO (DECL) && !DECL_USE_TEMPLATE (DECL))
+
+/* Non-zero if TYPE is a partial instantiation of a template class,
+ i.e., an instantiation whose instantiation arguments involve
+ template types. */
+#define PARTIAL_INSTANTIATION_P(TYPE) \
+ (TYPE_LANG_SPECIFIC (TYPE)->type_flags.is_partial_instantiation)
+
+/* Non-zero iff we are currently processing a declaration for an
+ entity with its own template parameter list, and which is not a
+ full specialization. */
+#define PROCESSING_REAL_TEMPLATE_DECL_P() \
+ (processing_template_decl > template_class_depth (current_class_type))
+
/* This function may be a guiding decl for a template. */
#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
+
+/* Nonzero if this VAR_DECL or FUNCTION_DECL has already been
+ instantiated, i.e. its definition has been generated from the
+ pattern given in the the template. */
+#define DECL_TEMPLATE_INSTANTIATED(NODE) DECL_LANG_FLAG_1(NODE)
+
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
@@ -1636,10 +2022,6 @@ extern int flag_new_for_scope;
#define DECL_REALLY_EXTERN(NODE) \
(DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))
-/* Used to tell cp_finish_decl that it should approximate comdat linkage
- as best it can for this decl. */
-#define DECL_COMDAT(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.comdat)
-
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
/* ...and for unexpanded-parameterized-type nodes. */
@@ -1710,6 +2092,11 @@ extern int warn_overloaded_virtual;
/* Nonzero means warn about use of multicharacter literals. */
extern int warn_multichar;
+/* Non-zero means warn if a non-templatized friend function is
+ declared in a templatized class. This behavior is warned about with
+ flag_guiding_decls in do_friend. */
+extern int warn_nontemplate_friend;
+
/* in c-common.c */
extern void declare_function_name PROTO((void));
extern void decl_attributes PROTO((tree, tree, tree));
@@ -1719,7 +2106,7 @@ extern void check_function_format PROTO((tree, tree, tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PROTO((enum tree_code));
-extern tree cp_build_type_variant PROTO((tree, int, int));
+extern tree cp_build_qualified_type PROTO((tree, int));
extern tree canonical_type_variant PROTO((tree));
extern void c_expand_expr_stmt PROTO((tree));
/* Validate the expression after `case' and apply default promotions. */
@@ -1730,6 +2117,8 @@ extern void constant_expression_warning PROTO((tree));
extern tree convert_and_check PROTO((tree, tree));
extern void overflow_warning PROTO((tree));
extern void unsigned_conversion_warning PROTO((tree, tree));
+extern void c_apply_type_quals_to_decl PROTO((int, tree));
+
/* Read the rest of the current #-directive line. */
#if USE_CPPLIB
extern char *get_directive_line PROTO((void));
@@ -1789,8 +2178,10 @@ extern tree opaque_type_node, signature_type_node;
#define vfunc_ptr_type_node \
(flag_vtable_thunks ? vtable_entry_type : ptr_type_node)
-/* Array type `(void *)[]' */
+/* The type of a vtbl, i.e., an array of vtable entries. */
extern tree vtbl_type_node;
+/* The type of a class vtbl pointer, i.e., a pointer to a vtable entry. */
+extern tree vtbl_ptr_type_node;
extern tree delta_type_node;
extern tree std_node;
@@ -1801,6 +2192,12 @@ extern tree boolean_type_node, boolean_true_node, boolean_false_node;
extern tree null_node;
+extern tree anonymous_namespace_name;
+
+/* The FUNCTION_DECL for the default `::operator delete'. */
+
+extern tree global_delete_fndecl;
+
/* in pt.c */
/* These values are used for the `STRICT' parameter to type_unfication and
@@ -1832,6 +2229,13 @@ extern int minimal_parse_mode;
extern void maybe_print_template_context PROTO ((void));
/* in class.c */
+
+/* When parsing a class definition, the access specifier most recently
+ given by the user, or, if no access specifier was given, the
+ default value appropriate for the kind of class (i.e., struct,
+ class, or union). */
+extern tree current_access_specifier;
+
extern tree current_class_name;
extern tree current_class_type;
extern tree current_class_ptr;
@@ -1842,6 +2246,9 @@ extern int current_class_depth;
extern tree current_lang_name;
extern tree lang_name_cplusplus, lang_name_c, lang_name_java;
+/* The low-water mark on the class-cache obstack. */
+extern char *class_cache_firstobj;
+
/* Points to the name of that function. May not be the DECL_NAME
of CURRENT_FUNCTION_DECL due to overloading */
extern tree original_function_name;
@@ -1858,12 +2265,6 @@ extern int current_function_parms_stored;
#define OPERATOR_ASSIGN_FORMAT "__a%s"
#define OPERATOR_FORMAT "__%s"
#define OPERATOR_TYPENAME_FORMAT "__op"
-#define OPERATOR_TYPENAME_P(ID_NODE) \
- (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[1] == '_' \
- && IDENTIFIER_POINTER (ID_NODE)[2] == 'o' \
- && IDENTIFIER_POINTER (ID_NODE)[3] == 'p')
-
/* Cannot use '$' up front, because this confuses gdb
(names beginning with '$' are gdb-local identifiers).
@@ -1986,9 +2387,9 @@ extern int current_function_parms_stored;
#define SIGNATURE_OPTR_NAME "__optr"
#define SIGNATURE_SPTR_NAME "__sptr"
#define SIGNATURE_POINTER_NAME "__sp_"
-#define SIGNATURE_POINTER_NAME_FORMAT "__%s%ssp_%s"
+#define SIGNATURE_POINTER_NAME_FORMAT "__%s%s%ssp_%s"
#define SIGNATURE_REFERENCE_NAME "__sr_"
-#define SIGNATURE_REFERENCE_NAME_FORMAT "__%s%ssr_%s"
+#define SIGNATURE_REFERENCE_NAME_FORMAT "__%s%s%ssr_%s"
#define SIGTABLE_PTR_TYPE "__sigtbl_ptr_type"
#define SIGTABLE_NAME_FORMAT "__st_%s_%s"
@@ -2028,6 +2429,14 @@ extern int current_function_parms_stored;
&& IDENTIFIER_POINTER (ID_NODE)[1] <= '9')
#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */
+/* Store the vbase pointer field name for type TYPE into pointer BUF. */
+#define FORMAT_VBASE_NAME(BUF,TYPE) do { \
+ char *wbuf = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (TYPE) \
+ + sizeof (VBASE_NAME) + 1); \
+ sprintf (wbuf, VBASE_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (TYPE)); \
+ (BUF) = wbuf; \
+} while (0)
+
/* Returns non-zero iff ID_NODE is an IDENTIFIER_NODE whose name is
`main'. */
#define MAIN_NAME_P(ID_NODE) \
@@ -2037,7 +2446,7 @@ extern int current_function_parms_stored;
`main'. */
#define DECL_MAIN_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL \
- && DECL_CONTEXT (NODE) == NULL_TREE \
+ && DECL_LANGUAGE (NODE) == lang_c \
&& DECL_NAME (NODE) != NULL_TREE \
&& MAIN_NAME_P (DECL_NAME (NODE)))
@@ -2077,24 +2486,11 @@ struct pending_inline
/* in method.c */
extern struct pending_inline *pending_inlines;
-/* 1 for -fall-virtual: make every member function (except
- constructors) lay down in the virtual function table.
- Calls can then either go through the virtual function table or not,
- depending on whether we know what function will actually be called. */
-
-extern int flag_all_virtual;
-
/* Positive values means that we cannot make optimizing assumptions about
`this'. Negative values means we know `this' to be of static type. */
extern int flag_this_is_variable;
-/* Controls whether enums and ints freely convert.
- 1 means with complete freedom.
- 0 means enums can convert to ints, but not vice-versa. */
-
-extern int flag_int_enum_equivalence;
-
/* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_rtti;
@@ -2138,7 +2534,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
/* The following two can be derived from the previous one */
extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
-extern tree current_class_type; /* _TYPE: the type of the current class */
/* Some macros for char-based bitfields. */
#define B_SET(a,x) (a[x>>3] |= (1 << (x&7)))
@@ -2233,11 +2628,47 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define WANT_ENUM 4 /* enumerated types */
#define WANT_POINTER 8 /* pointer types */
#define WANT_NULL 16 /* null pointer constant */
-
#define WANT_ARITH (WANT_INT | WANT_FLOAT)
-#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
-#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
+/* Used with comptypes, and related functions, to guide type
+ comparison. */
+
+#define COMPARE_STRICT 0 /* Just check if the types are the
+ same. */
+#define COMPARE_BASE 1 /* Check to see if the second type is
+ derived from the first, or if both
+ are pointers (or references) and
+ the types pointed to by the second
+ type is derived from the pointed to
+ by the first. */
+#define COMPARE_RELAXED 2 /* Like COMPARE_DERIVED, but in
+ reverse. Also treat enmeration
+ types as the same as integer types
+ of the same width. */
+#define COMPARE_REDECLARATION 4 /* The comparsion is being done when
+ another declaration of an existing
+ entity is seen. */
+#define COMPARE_NO_ATTRIBUTES 8 /* The comparison should ignore
+ extra-linguistic type attributes. */
+
+/* Used with push_overloaded_decl. */
+#define PUSH_GLOBAL 0 /* Push the DECL into namespace scope,
+ regardless of the current scope. */
+#define PUSH_LOCAL 1 /* Push the DECL into the current
+ scope. */
+#define PUSH_USING 2 /* We are pushing this DECL as the
+ result of a using declaration. */
+
+/* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual
+ sense of `same'. */
+#define same_type_p(type1, type2) \
+ comptypes ((type1), (type2), COMPARE_STRICT)
+
+/* Returns nonzero iff TYPE1 and TYPE2 are the same type, or if TYPE2
+ is derived from TYPE1, or if TYPE2 is a pointer (reference) to a
+ class derived from the type pointed to (referred to) by TYPE1. */
+#define same_or_base_type_p(type1, type2) \
+ comptypes ((type1), (type2), COMPARE_BASE)
/* These macros are used to access a TEMPLATE_PARM_INDEX. */
#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index)
@@ -2283,9 +2714,10 @@ extern tree build_op_new_call PROTO((enum tree_code, tree, tree, int));
extern tree build_op_delete_call PROTO((enum tree_code, tree, tree, int, tree));
extern int can_convert PROTO((tree, tree));
extern int can_convert_arg PROTO((tree, tree, tree));
-extern void enforce_access PROTO((tree, tree));
-extern tree convert_default_arg PROTO((tree, tree));
+extern int enforce_access PROTO((tree, tree));
+extern tree convert_default_arg PROTO((tree, tree, tree));
extern tree convert_arg_to_ellipsis PROTO((tree));
+extern int is_properly_derived_from PROTO((tree, tree));
/* in class.c */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
@@ -2295,24 +2727,29 @@ extern void add_method PROTO((tree, tree *, tree));
extern int currently_open_class PROTO((tree));
extern tree get_vfield_offset PROTO((tree));
extern void duplicate_tag_error PROTO((tree));
-extern tree finish_struct PROTO((tree, tree, tree, int));
-extern tree finish_struct_1 PROTO((tree, int));
-extern tree finish_struct_methods PROTO((tree, tree, int));
+extern tree finish_struct PROTO((tree, tree, int));
+extern void finish_struct_1 PROTO((tree, int));
extern int resolves_to_fixed_type_p PROTO((tree, int *));
extern void init_class_processing PROTO((void));
extern int is_empty_class PROTO((tree));
extern void pushclass PROTO((tree, int));
-extern void popclass PROTO((int));
+extern void popclass PROTO((void));
extern void push_nested_class PROTO((tree, int));
-extern void pop_nested_class PROTO((int));
+extern void pop_nested_class PROTO((void));
extern void push_lang_context PROTO((tree));
extern void pop_lang_context PROTO((void));
extern tree instantiate_type PROTO((tree, tree, int));
extern void print_class_statistics PROTO((void));
-extern void maybe_push_cache_obstack PROTO((void));
-extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
-extern tree build_self_reference PROTO((void));
+extern void push_cache_obstack PROTO((void));
+extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *, tree));
+extern void build_self_reference PROTO((void));
extern void warn_hidden PROTO((tree));
+extern tree get_enclosing_class PROTO((tree));
+int is_base_of_enclosing_class PROTO((tree, tree));
+extern void unreverse_member_declarations PROTO((tree));
+extern void invalidate_class_lookup_cache PROTO((void));
+extern void maybe_note_name_used_in_class PROTO((tree, tree));
+extern void note_name_declared_in_class PROTO((tree, tree));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
@@ -2323,15 +2760,17 @@ extern tree ocp_convert PROTO((tree, tree, int, int));
extern tree cp_convert PROTO((tree, tree));
extern tree convert PROTO((tree, tree));
extern tree convert_force PROTO((tree, tree, int));
-extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
+extern tree build_type_conversion PROTO((tree, tree, int));
extern tree build_expr_type_conversion PROTO((int, tree, int));
extern tree type_promotes_to PROTO((tree));
extern tree perform_qualification_conversions PROTO((tree, tree));
/* decl.c */
/* resume_binding_level */
+extern void set_identifier_local_value PROTO((tree, tree));
extern int global_bindings_p PROTO((void));
extern int toplevel_bindings_p PROTO((void));
+extern int namespace_bindings_p PROTO((void));
extern void keep_next_level PROTO((void));
extern int kept_level_p PROTO((void));
extern void declare_parm_level PROTO((void));
@@ -2348,7 +2787,6 @@ extern void insert_block PROTO((tree));
extern void add_block_current_level PROTO((tree));
extern void set_block PROTO((tree));
extern void pushlevel_class PROTO((void));
-extern tree poplevel_class PROTO((int));
extern void print_binding_stack PROTO((void));
extern void print_binding_level PROTO((struct binding_level *));
extern void push_namespace PROTO((tree));
@@ -2358,7 +2796,6 @@ extern void push_to_top_level PROTO((void));
extern void pop_from_top_level PROTO((void));
extern tree identifier_type_value PROTO((tree));
extern void set_identifier_type_value PROTO((tree, tree));
-extern void set_identifier_local_value PROTO((tree, tree));
extern void pop_everything PROTO((void));
extern void pushtag PROTO((tree, tree, int));
extern tree make_anon_name PROTO((void));
@@ -2367,7 +2804,7 @@ extern int decls_match PROTO((tree, tree));
extern int duplicate_decls PROTO((tree, tree));
extern tree pushdecl PROTO((tree));
extern tree pushdecl_top_level PROTO((tree));
-extern tree pushdecl_class_level PROTO((tree));
+extern void pushdecl_class_level PROTO((tree));
#if 0
extern void pushdecl_nonclass_level PROTO((tree));
#endif
@@ -2375,14 +2812,13 @@ extern tree pushdecl_namespace_level PROTO((tree));
extern tree push_using_decl PROTO((tree, tree));
extern tree push_using_directive PROTO((tree));
extern void push_class_level_binding PROTO((tree, tree));
-extern tree push_using_decl PROTO((tree, tree));
extern tree implicitly_declare PROTO((tree));
extern tree lookup_label PROTO((tree));
extern tree shadow_label PROTO((tree));
extern tree define_label PROTO((char *, int, tree));
extern void push_switch PROTO((void));
extern void pop_switch PROTO((void));
-extern void define_case_label PROTO((tree));
+extern void define_case_label PROTO((void));
extern tree getdecls PROTO((void));
extern tree gettags PROTO((void));
#if 0
@@ -2392,6 +2828,7 @@ extern tree binding_for_name PROTO((tree, tree));
extern tree namespace_binding PROTO((tree, tree));
extern void set_namespace_binding PROTO((tree, tree, tree));
extern tree lookup_namespace_name PROTO((tree, tree));
+extern tree build_typename_type PROTO((tree, tree, tree, tree));
extern tree make_typename_type PROTO((tree, tree));
extern tree lookup_name_nonclass PROTO((tree));
extern tree lookup_function_nonclass PROTO((tree, tree));
@@ -2408,8 +2845,9 @@ extern tree auto_function PROTO((tree, tree, enum built_in_function));
extern void init_decl_processing PROTO((void));
extern int init_type_desc PROTO((void));
extern tree define_function
- PROTO((char *, tree, enum built_in_function,
- void (*) (tree), char *));
+ PROTO((const char *, tree, enum built_in_function,
+ void (*) (tree), const char *));
+extern tree check_tag_decl PROTO((tree));
extern void shadow_tag PROTO((tree));
extern tree groktypename PROTO((tree));
extern tree start_decl PROTO((tree, tree, int, tree, tree));
@@ -2424,44 +2862,60 @@ extern int parmlist_is_exprlist PROTO((tree));
extern int copy_args_p PROTO((tree));
extern int grok_ctor_properties PROTO((tree, tree));
extern void grok_op_properties PROTO((tree, int, int));
-extern tree xref_tag PROTO((tree, tree, tree, int));
+extern tree xref_tag PROTO((tree, tree, int));
extern tree xref_tag_from_type PROTO((tree, tree, int));
extern void xref_basetypes PROTO((tree, tree, tree, tree));
extern tree start_enum PROTO((tree));
-extern tree finish_enum PROTO((tree, tree));
-extern tree build_enumerator PROTO((tree, tree));
-extern tree grok_enum_decls PROTO((tree));
+extern tree finish_enum PROTO((tree));
+extern tree build_enumerator PROTO((tree, tree, tree));
extern int start_function PROTO((tree, tree, tree, int));
extern void expand_start_early_try_stmts PROTO((void));
extern void store_parm_decls PROTO((void));
extern void store_return_init PROTO((tree, tree));
extern void finish_function PROTO((int, int, int));
-extern tree start_method PROTO((tree, tree));
+extern tree start_method PROTO((tree, tree, tree));
extern tree finish_method PROTO((tree));
extern void hack_incomplete_structures PROTO((tree));
extern tree maybe_build_cleanup_and_delete PROTO((tree));
extern tree maybe_build_cleanup PROTO((tree));
extern void cplus_expand_expr_stmt PROTO((tree));
extern void finish_stmt PROTO((void));
-extern int id_in_current_class PROTO((tree));
extern void push_cp_function_context PROTO((tree));
extern void pop_cp_function_context PROTO((tree));
extern int in_function_p PROTO((void));
extern void replace_defarg PROTO((tree, tree));
extern void print_other_binding_stack PROTO((struct binding_level *));
extern void revert_static_member_fn PROTO((tree*, tree*, tree*));
-extern void cat_namespace_levels PROTO((void));
+extern void fixup_anonymous_union PROTO((tree));
+extern int check_static_variable_definition PROTO((tree, tree));
+extern void push_local_binding PROTO((tree, tree, int));
+extern int push_class_binding PROTO((tree, tree));
+extern tree check_default_argument PROTO((tree, tree));
+extern tree push_overloaded_decl PROTO((tree, int));
+extern void clear_identifier_class_values PROTO((void));
+extern void storetags PROTO((tree));
+extern int vtable_decl_p PROTO((tree, void *));
+extern int vtype_decl_p PROTO((tree, void *));
+extern int sigtable_decl_p PROTO((tree, void *));
+typedef int (*walk_globals_pred) PROTO((tree, void *));
+typedef int (*walk_globals_fn) PROTO((tree *, void *));
+extern int walk_globals PROTO((walk_globals_pred,
+ walk_globals_fn,
+ void *));
+typedef int (*walk_namespaces_fn) PROTO((tree, void *));
+extern int walk_namespaces PROTO((walk_namespaces_fn,
+ void *));
+extern int wrapup_globals_for_namespace PROTO((tree, void *));
/* in decl2.c */
-extern int check_java_method PROTO((tree, tree));
-extern int flag_assume_nonnull_objects;
+extern int check_java_method PROTO((tree));
extern int lang_decode_option PROTO((int, char **));
extern tree grok_method_quals PROTO((tree, tree, tree));
extern void warn_if_unknown_interface PROTO((tree));
-extern tree grok_x_components PROTO((tree, tree));
+extern void grok_x_components PROTO((tree));
extern void maybe_retrofit_in_chrg PROTO((tree));
extern void maybe_make_one_only PROTO((tree));
-extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree));
+extern void grokclassfn PROTO((tree, tree, enum overload_flags, tree));
extern tree grok_alignof PROTO((tree));
extern tree grok_array_decl PROTO((tree, tree));
extern tree delete_sanity PROTO((tree, tree, int, int));
@@ -2482,17 +2936,13 @@ extern tree get_temp_name PROTO((tree, int));
extern tree get_temp_regvar PROTO((tree, tree));
extern void finish_anon_union PROTO((tree));
extern tree finish_table PROTO((tree, tree, tree, int));
-extern void finish_builtin_type PROTO((tree, char *, tree *, int, tree));
+extern void finish_builtin_type PROTO((tree, const char *,
+ tree *, int, tree));
extern tree coerce_new_type PROTO((tree));
extern tree coerce_delete_type PROTO((tree));
extern void comdat_linkage PROTO((tree));
extern void import_export_class PROTO((tree));
extern void import_export_vtable PROTO((tree, tree, int));
-extern int finish_prevtable_vardecl PROTO((tree, tree));
-extern int walk_vtables PROTO((void (*)(tree, tree),
- int (*)(tree, tree)));
-extern void walk_sigtables PROTO((void (*)(tree, tree),
- void (*)(tree, tree)));
extern void import_export_decl PROTO((tree));
extern tree build_cleanup PROTO((tree));
extern void finish_file PROTO((void));
@@ -2502,10 +2952,12 @@ extern tree build_expr_from_tree PROTO((tree));
extern tree reparse_decl_as_expr PROTO((tree, tree));
extern tree finish_decl_parsing PROTO((tree));
extern tree check_cp_case_value PROTO((tree));
-extern void set_decl_namespace PROTO((tree, tree));
+extern void set_decl_namespace PROTO((tree, tree, int));
extern tree current_decl_namespace PROTO((void));
extern void push_decl_namespace PROTO((tree));
extern void pop_decl_namespace PROTO((void));
+extern void push_scope PROTO((tree));
+extern void pop_scope PROTO((tree));
extern void do_namespace_alias PROTO((tree, tree));
extern void do_toplevel_using_decl PROTO((tree));
extern void do_local_using_decl PROTO((tree));
@@ -2515,16 +2967,19 @@ extern void check_default_args PROTO((tree));
extern void mark_used PROTO((tree));
extern tree handle_class_head PROTO((tree, tree, tree));
extern tree lookup_arg_dependent PROTO((tree, tree, tree));
+extern void finish_static_data_member_decl PROTO((tree, tree, tree, int, int));
/* in errfn.c */
-extern void cp_error ();
-extern void cp_error_at ();
-extern void cp_warning ();
-extern void cp_warning_at ();
-extern void cp_pedwarn ();
-extern void cp_pedwarn_at ();
-extern void cp_compiler_error ();
-extern void cp_sprintf ();
+/* The cp_* functions aren't suitable for ATTRIBUTE_PRINTF. */
+extern void cp_error PVPROTO((const char *, ...));
+extern void cp_error_at PVPROTO((const char *, ...));
+extern void cp_warning PVPROTO((const char *, ...));
+extern void cp_warning_at PVPROTO((const char *, ...));
+extern void cp_pedwarn PVPROTO((const char *, ...));
+extern void cp_pedwarn_at PVPROTO((const char *, ...));
+extern void cp_compiler_error PVPROTO((const char *, ...));
+extern void cp_sprintf PVPROTO((const char *, ...));
+extern void cp_deprecated PROTO((const char*));
/* in error.c */
extern void init_error PROTO((void));
@@ -2566,7 +3021,9 @@ extern void do_case PROTO((tree, tree));
/* friend.c */
extern int is_friend PROTO((tree, tree));
extern void make_friend_class PROTO((tree, tree));
-extern tree do_friend PROTO((tree, tree, tree, tree, enum overload_flags, tree, int));
+extern void add_friend PROTO((tree, tree));
+extern void add_friends PROTO((tree, tree, tree));
+extern tree do_friend PROTO((tree, tree, tree, tree, tree, enum overload_flags, tree, int));
/* in init.c */
extern void init_init_processing PROTO((void));
@@ -2574,7 +3031,7 @@ extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
extern void emit_base_init PROTO((tree, int));
extern void check_base_init PROTO((tree));
extern void expand_member_init PROTO((tree, tree, tree));
-extern void expand_aggr_init PROTO((tree, tree, int, int));
+extern void expand_aggr_init PROTO((tree, tree, int));
extern int is_aggr_typedef PROTO((tree, int));
extern int is_aggr_type PROTO((tree, int));
extern tree get_aggr_from_typedef PROTO((tree, int));
@@ -2586,7 +3043,7 @@ extern tree decl_constant_value PROTO((tree));
extern tree build_new PROTO((tree, tree, tree, int));
extern tree build_new_1 PROTO((tree));
extern tree expand_vec_init PROTO((tree, tree, tree, tree, int));
-extern tree build_x_delete PROTO((tree, tree, int, tree));
+extern tree build_x_delete PROTO((tree, int, tree));
extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree));
extern tree build_vec_delete PROTO((tree, tree, tree, tree, int));
@@ -2594,7 +3051,7 @@ extern tree build_vec_delete PROTO((tree, tree, tree, tree, int));
/* in input.c */
/* in lex.c */
-extern char *file_name_nondirectory PROTO((char *));
+extern char *file_name_nondirectory PROTO((const char *));
extern tree make_pointer_declarator PROTO((tree, tree));
extern tree make_reference_declarator PROTO((tree, tree));
extern tree make_call_declarator PROTO((tree, tree, tree, tree));
@@ -2602,7 +3059,6 @@ extern void set_quals_and_spec PROTO((tree, tree, tree));
extern char *operator_name_string PROTO((tree));
extern void lang_init PROTO((void));
extern void lang_finish PROTO((void));
-extern void init_filename_times PROTO((void));
#if 0
extern void reinit_lang_specific PROTO((void));
#endif
@@ -2629,12 +3085,14 @@ extern tree identifier_typedecl_value PROTO((tree));
extern int real_yylex PROTO((void));
extern int is_rid PROTO((tree));
extern tree build_lang_decl PROTO((enum tree_code, tree, tree));
+extern void retrofit_lang_decl PROTO((tree));
extern tree build_lang_field_decl PROTO((enum tree_code, tree, tree));
extern void copy_lang_decl PROTO((tree));
extern tree make_lang_type PROTO((enum tree_code));
extern void dump_time_statistics PROTO((void));
-/* extern void compiler_error PROTO((char *, HOST_WIDE_INT, HOST_WIDE_INT)); */
-extern void yyerror PROTO((char *));
+extern void compiler_error PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
+extern void yyerror PROTO((const char *));
extern void clear_inline_text_obstack PROTO((void));
extern void maybe_snarf_defarg PROTO((void));
extern tree snarf_defarg PROTO((void));
@@ -2642,6 +3100,7 @@ extern void add_defarg_fn PROTO((tree));
extern void do_pending_defargs PROTO((void));
extern int identifier_type PROTO((tree));
extern void yyhook PROTO((int));
+extern int cp_type_qual_from_rid PROTO((tree));
/* in method.c */
extern void init_method PROTO((void));
@@ -2649,7 +3108,9 @@ extern void do_inline_function_hair PROTO((tree, tree));
extern char *build_overload_name PROTO((tree, int, int));
extern tree build_static_name PROTO((tree, tree));
extern tree build_decl_overload PROTO((tree, tree, int));
-extern tree build_template_decl_overload PROTO((tree, tree, tree, tree, tree, int));
+extern tree build_decl_overload_real PROTO((tree, tree, tree, tree,
+ tree, int));
+extern void set_mangled_name_for_decl PROTO((tree));
extern tree build_typename_overload PROTO((tree));
extern tree build_overload_with_type PROTO((tree, tree));
extern tree build_destructor_name PROTO((tree));
@@ -2661,22 +3122,21 @@ extern void synthesize_method PROTO((tree));
extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */
-extern tree innermost_args PROTO ((tree, int));
-extern tree tsubst PROTO ((tree, tree, tree));
-extern tree tsubst_expr PROTO ((tree, tree, tree));
-extern tree tsubst_copy PROTO ((tree, tree, tree));
-extern tree tsubst_chain PROTO((tree, tree));
+extern void check_template_shadow PROTO ((tree));
+extern tree innermost_args PROTO ((tree));
+extern tree tsubst PROTO ((tree, tree, int, tree));
+extern tree tsubst_expr PROTO ((tree, tree, int, tree));
+extern tree tsubst_copy PROTO ((tree, tree, int, tree));
extern void maybe_begin_member_template_processing PROTO((tree));
-extern void maybe_end_member_template_processing PROTO((tree));
-extern tree finish_member_template_decl PROTO((tree, tree));
+extern void maybe_end_member_template_processing PROTO((void));
+extern tree finish_member_template_decl PROTO((tree));
extern void begin_template_parm_list PROTO((void));
extern void begin_specialization PROTO((void));
extern void reset_specialization PROTO((void));
extern void end_specialization PROTO((void));
extern void begin_explicit_instantiation PROTO((void));
extern void end_explicit_instantiation PROTO((void));
-extern tree determine_specialization PROTO((tree, tree, tree *, int, int));
-extern tree check_explicit_specialization PROTO((tree, tree, int, int));
+extern tree check_explicit_specialization PROTO((tree, tree, int, int));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
extern void end_template_decl PROTO((void));
@@ -2684,14 +3144,13 @@ extern tree current_template_args PROTO((void));
extern tree push_template_decl PROTO((tree));
extern tree push_template_decl_real PROTO((tree, int));
extern void redeclare_class_template PROTO((tree, tree));
-extern tree lookup_template_class PROTO((tree, tree, tree, tree));
+extern tree lookup_template_class PROTO((tree, tree, tree, tree, int));
extern tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree));
extern tree instantiate_template PROTO((tree, tree));
extern void overload_template_name PROTO((tree));
-extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t, tree));
-extern int type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t, int));
+extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree, tree));
@@ -2699,7 +3158,6 @@ extern void mark_class_instantiated PROTO((tree, int));
extern void do_decl_instantiation PROTO((tree, tree, tree));
extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree));
-extern tree lookup_nested_type_by_name PROTO((tree, tree));
extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree, tree));
/* CONT ... */
@@ -2708,15 +3166,19 @@ extern void begin_tree PROTO((void));
extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void));
-extern tree most_specialized PROTO((tree, tree, tree));
-extern tree most_specialized_class PROTO((tree, tree, tree));
extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree));
+extern int template_parms_equal PROTO((tree, tree));
extern int comp_template_parms PROTO((tree, tree));
extern int template_class_depth PROTO((tree));
extern int is_specialization_of PROTO((tree, tree));
extern int comp_template_args PROTO((tree, tree));
+extern void maybe_process_partial_specialization PROTO((tree));
+extern void maybe_check_template_type PROTO((tree));
+extern tree most_specialized_instantiation PROTO((tree, tree));
+extern void print_candidates PROTO((tree));
+extern int instantiate_pending_templates PROTO((void));
extern int processing_specialization;
extern int processing_explicit_instantiation;
@@ -2725,7 +3187,7 @@ extern int processing_template_parmlist;
/* in repo.c */
extern void repo_template_used PROTO((tree));
extern void repo_template_instantiated PROTO((tree, int));
-extern void init_repo PROTO((char*));
+extern void init_repo PROTO((const char *));
extern void finish_repo PROTO((void));
/* in rtti.c */
@@ -2735,46 +3197,43 @@ extern tree build_typeid PROTO((tree));
extern tree build_x_typeid PROTO((tree));
extern tree get_tinfo_fn PROTO((tree));
extern tree get_typeid PROTO((tree));
+extern tree get_typeid_1 PROTO((tree));
extern tree build_dynamic_cast PROTO((tree, tree));
extern void synthesize_tinfo_fn PROTO((tree));
/* in search.c */
extern int types_overlap_p PROTO((tree, tree));
-extern void push_memoized_context PROTO((tree, int));
-extern void pop_memoized_context PROTO((int));
extern tree get_vbase PROTO((tree, tree));
extern tree get_binfo PROTO((tree, tree, int));
extern int get_base_distance PROTO((tree, tree, int, tree *));
-extern tree compute_access PROTO((tree, tree));
+extern int accessible_p PROTO((tree, tree));
extern tree lookup_field PROTO((tree, tree, int, int));
-extern tree lookup_nested_field PROTO((tree, int));
+extern int lookup_fnfields_1 PROTO((tree, tree));
extern tree lookup_fnfields PROTO((tree, tree, int));
extern tree lookup_member PROTO((tree, tree, int, int));
extern tree lookup_nested_tag PROTO((tree, tree));
extern tree get_matching_virtual PROTO((tree, tree, int));
extern tree get_abstract_virtuals PROTO((tree));
-extern tree get_baselinks PROTO((tree, tree, tree));
-extern tree next_baselink PROTO((tree));
extern tree init_vbase_pointers PROTO((tree, tree));
extern void expand_indirect_vtbls_init PROTO((tree, tree, tree));
extern void clear_search_slots PROTO((tree));
extern tree get_vbase_types PROTO((tree));
-extern void build_mi_matrix PROTO((tree));
-extern void free_mi_matrix PROTO((void));
-extern void build_mi_virtuals PROTO((int, int));
-extern void add_mi_virtuals PROTO((int, tree));
-extern void report_ambiguous_mi_virtuals PROTO((int, tree));
extern void note_debug_info_needed PROTO((tree));
extern void push_class_decls PROTO((tree));
extern void pop_class_decls PROTO((void));
extern void unuse_fields PROTO((tree));
-extern void unmark_finished_struct PROTO((tree));
extern void print_search_statistics PROTO((void));
extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void));
extern tree lookup_conversions PROTO((tree));
-extern tree get_template_base PROTO((tree, tree));
+extern tree binfo_for_vtable PROTO((tree));
+extern tree dfs_walk PROTO((tree,
+ tree (*)(tree, void *),
+ tree (*) (tree, void *),
+ void *));
+extern tree dfs_unmark PROTO((tree, void *));
+extern tree markedp PROTO((tree, void *));
/* in semantics.c */
extern void finish_expr_stmt PROTO((tree));
@@ -2821,7 +3280,7 @@ extern tree finish_this_expr PROTO((void));
extern tree finish_object_call_expr PROTO((tree, tree, tree));
extern tree finish_qualified_object_call_expr PROTO((tree, tree, tree));
extern tree finish_pseudo_destructor_call_expr PROTO((tree, tree, tree));
-extern tree finish_globally_qualified_member_call_expr PROTO ((tree, tree));
+extern tree finish_qualified_call_expr PROTO ((tree, tree));
extern tree finish_label_address_expr PROTO((tree));
extern tree finish_unary_op_expr PROTO((enum tree_code, tree));
extern tree finish_id_expr PROTO((tree));
@@ -2835,14 +3294,22 @@ extern tree finish_template_type_parm PROTO((tree, tree));
extern tree finish_template_template_parm PROTO((tree, tree));
extern tree finish_parmlist PROTO((tree, int));
extern tree begin_class_definition PROTO((tree));
-extern tree finish_class_definition PROTO((tree, tree, tree, int));
+extern tree finish_class_definition PROTO((tree, tree, int, int));
extern void finish_default_args PROTO((void));
extern void begin_inline_definitions PROTO((void));
-extern tree finish_member_class_template PROTO((tree, tree));
+extern void finish_inline_definitions PROTO((void));
+extern tree finish_member_class_template PROTO((tree));
+extern void finish_template_decl PROTO((tree));
+extern tree finish_template_type PROTO((tree, tree, int));
+extern void enter_scope_of PROTO((tree));
+extern tree finish_base_specifier PROTO((tree, tree, int));
+extern void finish_member_declaration PROTO((tree));
+extern void check_multiple_declarators PROTO((void));
+extern tree finish_typeof PROTO((tree));
/* in sig.c */
-extern tree build_signature_pointer_type PROTO((tree, int, int));
-extern tree build_signature_reference_type PROTO((tree, int, int));
+extern tree build_signature_pointer_type PROTO((tree));
+extern tree build_signature_reference_type PROTO((tree));
extern tree build_signature_pointer_constructor PROTO((tree, tree));
extern tree build_signature_method_call PROTO((tree, tree));
extern tree build_optr_ref PROTO((tree));
@@ -2855,13 +3322,15 @@ extern int yylex PROTO((void));
extern tree arbitrate_lookup PROTO((tree, tree, tree));
/* in tree.c */
+extern int pod_type_p PROTO((tree));
+extern void unshare_base_binfos PROTO((tree));
extern int member_p PROTO((tree));
extern int real_lvalue_p PROTO((tree));
extern tree build_min PVPROTO((enum tree_code, tree, ...));
extern tree build_min_nt PVPROTO((enum tree_code, ...));
extern tree min_tree_cons PROTO((tree, tree, tree));
extern int lvalue_p PROTO((tree));
-extern int lvalue_or_else PROTO((tree, char *));
+extern int lvalue_or_else PROTO((tree, const char *));
extern tree build_cplus_new PROTO((tree, tree));
extern tree get_target_expr PROTO((tree));
extern tree break_out_cleanups PROTO((tree));
@@ -2872,17 +3341,17 @@ extern tree build_cplus_array_type PROTO((tree, tree));
extern int layout_basetypes PROTO((tree, int));
extern tree build_vbase_pointer_fields PROTO((tree));
extern tree build_base_fields PROTO((tree));
-extern tree hash_tree_cons PROTO((int, int, int, tree, tree, tree));
+extern tree hash_tree_cons PROTO((tree, tree, tree));
extern tree hash_tree_chain PROTO((tree, tree));
extern tree hash_chainon PROTO((tree, tree));
-extern tree get_decl_list PROTO((tree));
-extern tree make_binfo PROTO((tree, tree, tree, tree, tree));
+extern tree make_binfo PROTO((tree, tree, tree, tree));
extern tree binfo_value PROTO((tree, tree));
extern tree reverse_path PROTO((tree));
extern int count_functions PROTO((tree));
extern int is_overloaded_fn PROTO((tree));
extern tree get_first_fn PROTO((tree));
extern tree binding_init PROTO((struct tree_binding*));
+extern int bound_pmf_p PROTO((tree));
extern tree ovl_cons PROTO((tree, tree));
extern tree scratch_ovl_cons PROTO((tree, tree));
extern int ovl_member PROTO((tree, tree));
@@ -2895,6 +3364,7 @@ extern char *lang_printable_name PROTO((tree, int));
extern tree build_exception_variant PROTO((tree, tree));
extern tree copy_template_template_parm PROTO((tree));
extern tree copy_to_permanent PROTO((tree));
+extern tree permanent_p PROTO((tree));
extern void print_lang_statistics PROTO((void));
extern void __eprintf
PROTO((const char *, const char *, unsigned, const char *));
@@ -2904,21 +3374,29 @@ extern tree break_out_target_exprs PROTO((tree));
extern tree get_type_decl PROTO((tree));
extern tree vec_binfo_member PROTO((tree, tree));
extern tree hack_decl_function_context PROTO((tree));
+extern tree decl_namespace_context PROTO((tree));
extern tree lvalue_type PROTO((tree));
extern tree error_type PROTO((tree));
extern tree make_temp_vec PROTO((int));
extern tree build_ptr_wrapper PROTO((void *));
extern tree build_expr_ptr_wrapper PROTO((void *));
extern tree build_int_wrapper PROTO((int));
-extern tree build_srcloc PROTO((char *, int));
extern tree build_srcloc_here PROTO((void));
extern int varargs_function_p PROTO((tree));
extern int really_overloaded_fn PROTO((tree));
extern int cp_tree_equal PROTO((tree, tree));
extern int can_free PROTO((struct obstack *, tree));
extern tree mapcar PROTO((tree, tree (*) (tree)));
+extern tree no_linkage_check PROTO((tree));
extern void debug_binfo PROTO((tree));
extern void push_expression_obstack PROTO((void));
+extern tree build_dummy_object PROTO((tree));
+extern tree maybe_dummy_object PROTO((tree, tree *));
+extern int is_dummy_object PROTO((tree));
+extern tree search_tree PROTO((tree, tree (*)(tree)));
+extern int cp_valid_lang_attribute PROTO((tree, tree, tree, tree));
+extern tree make_ptrmem_cst PROTO((tree, tree));
+
#define scratchalloc expralloc
#define scratch_tree_cons expr_tree_cons
#define build_scratch_list build_expr_list
@@ -2926,21 +3404,22 @@ extern void push_expression_obstack PROTO((void));
#define push_scratch_obstack push_expression_obstack
/* in typeck.c */
+extern int string_conv_p PROTO((tree, tree, int));
extern tree condition_conversion PROTO((tree));
extern tree target_type PROTO((tree));
extern tree require_complete_type PROTO((tree));
+extern tree require_complete_type_in_void PROTO((tree));
extern tree complete_type PROTO((tree));
-extern tree complete_type_or_else PROTO((tree));
+extern tree complete_type_or_else PROTO((tree, tree));
extern int type_unknown_p PROTO((tree));
extern int fntype_p PROTO((tree));
-extern tree require_instantiated_type PROTO((tree, tree, tree));
extern tree commonparms PROTO((tree, tree));
extern tree original_type PROTO((tree));
extern tree common_type PROTO((tree, tree));
extern int compexcepttypes PROTO((tree, tree));
extern int comptypes PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int));
-extern int compparms PROTO((tree, tree, int));
+extern int compparms PROTO((tree, tree));
extern int comp_target_types PROTO((tree, tree, int));
extern int comp_cv_qualification PROTO((tree, tree));
extern int comp_cv_qual_signature PROTO((tree, tree));
@@ -2959,19 +3438,18 @@ extern tree build_object_ref PROTO((tree, tree, tree));
extern tree build_component_ref_1 PROTO((tree, tree, int));
extern tree build_component_ref PROTO((tree, tree, tree, int));
extern tree build_x_component_ref PROTO((tree, tree, tree, int));
-extern tree build_x_indirect_ref PROTO((tree, char *));
-extern tree build_indirect_ref PROTO((tree, char *));
+extern tree build_x_indirect_ref PROTO((tree, const char *));
+extern tree build_indirect_ref PROTO((tree, const char *));
extern tree build_array_ref PROTO((tree, tree));
extern tree build_x_function_call PROTO((tree, tree, tree));
extern tree get_member_function_from_ptrfunc PROTO((tree *, tree));
extern tree build_function_call_real PROTO((tree, tree, int, int));
extern tree build_function_call PROTO((tree, tree));
extern tree build_function_call_maybe PROTO((tree, tree));
-extern tree convert_arguments PROTO((tree, tree, tree, tree, int));
+extern tree convert_arguments PROTO((tree, tree, tree, int));
extern tree build_x_binary_op PROTO((enum tree_code, tree, tree));
-extern tree build_binary_op PROTO((enum tree_code, tree, tree, int));
+extern tree build_binary_op PROTO((enum tree_code, tree, tree));
extern tree build_binary_op_nodefault PROTO((enum tree_code, tree, tree, enum tree_code));
-extern tree build_component_addr PROTO((tree, tree, char *));
extern tree build_x_unary_op PROTO((enum tree_code, tree));
extern tree build_unary_op PROTO((enum tree_code, tree, int));
extern tree unary_complex_lvalue PROTO((enum tree_code, tree));
@@ -2986,24 +3464,31 @@ extern tree build_const_cast PROTO((tree, tree));
extern tree build_c_cast PROTO((tree, tree));
extern tree build_x_modify_expr PROTO((tree, enum tree_code, tree));
extern tree build_modify_expr PROTO((tree, enum tree_code, tree));
-extern int language_lvalue_valid PROTO((tree));
-extern void warn_for_assignment PROTO((char *, char *, char *, tree, int, int));
-extern tree convert_for_initialization PROTO((tree, tree, tree, int, char *, tree, int));
+extern tree convert_for_initialization PROTO((tree, tree, tree, int, const char *, tree, int));
extern void c_expand_asm_operands PROTO((tree, tree, tree, tree, int, char *, int));
extern void c_expand_return PROTO((tree));
extern tree c_expand_start_case PROTO((tree));
extern int comp_ptr_ttypes PROTO((tree, tree));
extern int ptr_reasonably_similar PROTO((tree, tree));
extern tree build_ptrmemfunc PROTO((tree, tree, int));
+extern int cp_type_quals PROTO((tree));
+extern int cp_has_mutable_p PROTO((tree));
+extern int at_least_as_qualified_p PROTO((tree, tree));
+extern int more_qualified_p PROTO((tree, tree));
+extern tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree));
+extern void expand_ptrmemfunc_cst PROTO((tree, tree *, tree *, tree *, tree *));
+extern tree delta2_from_ptrmemfunc PROTO((tree));
+extern tree pfn_from_ptrmemfunc PROTO((tree));
/* in typeck2.c */
extern tree error_not_base_type PROTO((tree, tree));
extern tree binfo_or_else PROTO((tree, tree));
-extern void readonly_error PROTO((tree, char *, int));
+extern void readonly_error PROTO((tree, const char *, int));
extern void abstract_virtuals_error PROTO((tree, tree));
extern void signature_error PROTO((tree, tree));
extern void incomplete_type_error PROTO((tree, tree));
-extern void my_friendly_abort PROTO((int));
+extern void my_friendly_abort PROTO((int))
+ ATTRIBUTE_NORETURN;
extern void my_friendly_assert PROTO((int, int));
extern tree store_init_value PROTO((tree, tree));
extern tree digest_init PROTO((tree, tree, tree *));
@@ -3013,18 +3498,18 @@ extern tree build_m_component_ref PROTO((tree, tree));
extern tree build_functional_cast PROTO((tree, tree));
extern char *enum_name_string PROTO((tree, tree));
extern void report_case_error PROTO((int, tree, tree, tree));
-extern void check_for_new_type PROTO((char *,flagged_type_tree));
+extern void check_for_new_type PROTO((const char *, flagged_type_tree));
extern tree initializer_constant_valid_p PROTO((tree, tree));
/* in xref.c */
-extern void GNU_xref_begin PROTO((char *));
+extern void GNU_xref_begin PROTO((const char *));
extern void GNU_xref_end PROTO((int));
-extern void GNU_xref_file PROTO((char *));
+extern void GNU_xref_file PROTO((const char *));
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));
-extern void GNU_xref_ref PROTO((tree, char *));
+extern void GNU_xref_ref PROTO((tree, const char *));
extern void GNU_xref_decl PROTO((tree, tree));
-extern void GNU_xref_call PROTO((tree, char *));
+extern void GNU_xref_call PROTO((tree, const char *));
extern void GNU_xref_function PROTO((tree, tree));
extern void GNU_xref_assign PROTO((tree));
extern void GNU_xref_hier PROTO((tree, tree, int, int, int));
diff --git a/contrib/gcc/cp/cvt.c b/contrib/gcc/cp/cvt.c
index 18b7d8b..7082726 100644
--- a/contrib/gcc/cp/cvt.c
+++ b/contrib/gcc/cp/cvt.c
@@ -1,5 +1,5 @@
/* Language-level data type conversion for GNU C++.
- Copyright (C) 1987, 88, 92-96, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -31,12 +31,12 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "cp-tree.h"
#include "convert.h"
-
-extern tree static_aggregates;
+#include "toplev.h"
+#include "decl.h"
static tree cp_convert_to_pointer PROTO((tree, tree));
static tree convert_to_pointer_force PROTO((tree, tree));
-static tree build_up_reference PROTO((tree, tree, int, int));
+static tree build_up_reference PROTO((tree, tree, int));
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
@@ -85,7 +85,7 @@ cp_convert_to_pointer (type, expr)
return error_mark_node;
}
- rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
+ rval = build_type_conversion (type, expr, 1);
if (rval)
{
if (rval == error_mark_node)
@@ -95,9 +95,6 @@ cp_convert_to_pointer (type, expr)
}
}
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
-
/* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
if (TREE_CODE (type) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
@@ -107,21 +104,8 @@ cp_convert_to_pointer (type, expr)
functions. */
if (TYPE_PTRMEMFUNC_P (intype))
{
- tree decl, basebinfo;
tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
- tree t = TYPE_METHOD_BASETYPE (fntype);
-
- if (current_class_type == 0
- || get_base_distance (t, current_class_type, 0, &basebinfo)
- == -1)
- {
- decl = build1 (NOP_EXPR, t, error_mark_node);
- }
- else if (current_class_ptr == 0)
- decl = build1 (NOP_EXPR, t, error_mark_node);
- else
- decl = current_class_ref;
-
+ tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
expr = build (OFFSET_REF, fntype, decl, expr);
}
@@ -141,20 +125,26 @@ cp_convert_to_pointer (type, expr)
intype = TREE_TYPE (expr);
}
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
-
form = TREE_CODE (intype);
- if (form == POINTER_TYPE || form == REFERENCE_TYPE)
+ if (POINTER_TYPE_P (intype))
{
intype = TYPE_MAIN_VARIANT (intype);
if (TYPE_MAIN_VARIANT (type) != intype
+ && TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
&& IS_AGGR_TYPE (TREE_TYPE (type))
&& IS_AGGR_TYPE (TREE_TYPE (intype))
- && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
+ && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE
+ /* If EXPR is NULL, then we don't need to do any arithmetic
+ to convert it:
+
+ [conv.ptr]
+
+ The null pointer value is converted to the null pointer
+ value of the destination type. */
+ && !integer_zerop (expr))
{
enum tree_code code = PLUS_EXPR;
tree binfo = get_binfo (TREE_TYPE (type), TREE_TYPE (intype), 1);
@@ -186,13 +176,8 @@ cp_convert_to_pointer (type, expr)
}
}
}
- if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- return build_ptrmemfunc (type, expr, 1);
- if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
- && TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
{
tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype));
@@ -210,10 +195,7 @@ cp_convert_to_pointer (type, expr)
if (binfo && ! TREE_VIA_VIRTUAL (binfo))
expr = size_binop (code, expr, BINFO_OFFSET (binfo));
}
-
- if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
- || (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+ else if (TYPE_PTRMEMFUNC_P (type))
{
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
@@ -224,6 +206,14 @@ cp_convert_to_pointer (type, expr)
TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
return rval;
}
+ else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 1);
+ else if (TYPE_PTRMEMFUNC_P (intype))
+ {
+ cp_error ("cannot convert `%E' from type `%T' to type `%T'",
+ expr, intype, type);
+ return error_mark_node;
+ }
my_friendly_assert (form != OFFSET_TYPE, 186);
@@ -233,8 +223,8 @@ cp_convert_to_pointer (type, expr)
if (integer_zerop (expr))
{
- if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- return build_ptrmemfunc (type, expr, 0);
+ if (TYPE_PTRMEMFUNC_P (type))
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
expr = build_int_2 (0, 0);
TREE_TYPE (expr) = type;
return expr;
@@ -254,6 +244,9 @@ cp_convert_to_pointer (type, expr)
return convert_to_pointer (type, expr);
}
+ if (type_unknown_p (expr))
+ return instantiate_type (type, expr, 1);
+
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
return error_mark_node;
@@ -335,9 +328,9 @@ convert_to_pointer_force (type, expr)
DIRECT_BIND in FLAGS controls how any temporaries are generated. */
static tree
-build_up_reference (type, arg, flags, checkconst)
+build_up_reference (type, arg, flags)
tree type, arg;
- int flags, checkconst;
+ int flags;
{
tree rval;
tree argtype = TREE_TYPE (arg);
@@ -356,11 +349,13 @@ build_up_reference (type, arg, flags, checkconst)
DECL_ARTIFICIAL (arg) = 1;
}
DECL_INITIAL (arg) = targ;
- cp_finish_decl (arg, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+ cp_finish_decl (arg, targ, NULL_TREE, 0,
+ LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
{
tree slot = build_decl (VAR_DECL, NULL_TREE, argtype);
+ DECL_ARTIFICIAL (slot) = 1;
arg = build (TARGET_EXPR, argtype, slot, arg, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (arg) = 1;
}
@@ -369,6 +364,9 @@ build_up_reference (type, arg, flags, checkconst)
address, transform all occurrences of the register, into a memory
reference we could win better. */
rval = build_unary_op (ADDR_EXPR, arg, 1);
+ if (rval == error_mark_node)
+ return error_mark_node;
+
if ((flags & LOOKUP_PROTECT)
&& TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
&& IS_AGGR_TYPE (argtype)
@@ -409,6 +407,16 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
tree rval_as_conversion = NULL_TREE;
int i;
+ if (TREE_CODE (type) == FUNCTION_TYPE && intype == unknown_type_node)
+ {
+ expr = instantiate_type (type, expr,
+ (flags & LOOKUP_COMPLAIN) != 0);
+ if (expr == error_mark_node)
+ return error_mark_node;
+
+ intype = TREE_TYPE (expr);
+ }
+
if (TREE_CODE (intype) == REFERENCE_TYPE)
my_friendly_abort (364);
@@ -422,7 +430,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
/* Look for a user-defined conversion to lvalue that we can use. */
rval_as_conversion
- = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
+ = build_type_conversion (reftype, expr, 1);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
@@ -440,37 +448,35 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (flags & LOOKUP_COMPLAIN)
{
tree ttl = TREE_TYPE (reftype);
- tree ttr;
-
- {
- int r = TREE_READONLY (expr);
- int v = TREE_THIS_VOLATILE (expr);
- ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);
- }
+ tree ttr = lvalue_type (expr);
- if (! real_lvalue_p (expr) && ! TYPE_READONLY (ttl))
+ /* [dcl.init.ref] says that if an rvalue is used to
+ initialize a reference, then the reference must be to a
+ non-volatile const type. */
+ if (! real_lvalue_p (expr)
+ && !CP_TYPE_CONST_NON_VOLATILE_P (ttl))
{
- if (decl)
- /* Ensure semantics of [dcl.init.ref] */
- cp_pedwarn ("initialization of non-const reference `%#T' from rvalue `%T'",
- reftype, intype);
+ const char *msg;
+
+ if (CP_TYPE_VOLATILE_P (ttl) && decl)
+ msg = "initialization of volatile reference type `%#T'";
+ else if (CP_TYPE_VOLATILE_P (ttl))
+ msg = "conversion to volatile reference type `%#T'";
+ else if (decl)
+ msg = "initialization of non-const reference type `%#T'";
else
- cp_pedwarn ("conversion to non-const `%T' from rvalue `%T'",
- reftype, intype);
- }
- else if (! (convtype & CONV_CONST))
- {
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- cp_pedwarn ("conversion from `%T' to `%T' discards const",
- ttr, reftype);
- else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- cp_pedwarn ("conversion from `%T' to `%T' discards volatile",
- ttr, reftype);
+ msg = "conversion to non-const reference type `%#T'";
+
+ cp_pedwarn (msg, reftype);
+ cp_pedwarn ("from rvalue of type `%T'", intype);
}
+ else if (! (convtype & CONV_CONST)
+ && !at_least_as_qualified_p (ttl, ttr))
+ cp_pedwarn ("conversion from `%T' to `%T' discards qualifiers",
+ ttr, reftype);
}
- return build_up_reference (reftype, expr, flags,
- ! (convtype & CONV_CONST));
+ return build_up_reference (reftype, expr, flags);
}
else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
{
@@ -482,7 +488,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
/* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
meant. */
if (TREE_CODE (intype) == POINTER_TYPE
- && (comptypes (TREE_TYPE (intype), type, -1)))
+ && (comptypes (TREE_TYPE (intype), type,
+ COMPARE_BASE | COMPARE_RELAXED )))
cp_warning ("casting `%T' to `%T' does not dereference pointer",
intype, reftype);
@@ -497,11 +504,11 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
{
rval = convert_for_initialization (NULL_TREE, type, expr, flags,
"converting", 0, 0);
- if (rval == error_mark_node)
- return error_mark_node;
- rval = build_up_reference (reftype, rval, flags, 1);
+ if (rval == NULL_TREE || rval == error_mark_node)
+ return rval;
+ rval = build_up_reference (reftype, rval, flags);
- if (rval && ! TYPE_READONLY (TREE_TYPE (reftype)))
+ if (rval && ! CP_TYPE_CONST_P (TREE_TYPE (reftype)))
cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",
reftype, intype);
}
@@ -569,29 +576,29 @@ convert_pointer_to_real (binfo, expr)
binfo = NULL_TREE;
}
- ptr_type = cp_build_type_variant (type, TYPE_READONLY (TREE_TYPE (intype)),
- TYPE_VOLATILE (TREE_TYPE (intype)));
+ ptr_type = cp_build_qualified_type (type,
+ CP_TYPE_QUALS (TREE_TYPE (intype)));
ptr_type = build_pointer_type (ptr_type);
- if (ptr_type == TYPE_MAIN_VARIANT (intype))
+ if (same_type_p (ptr_type, TYPE_MAIN_VARIANT (intype)))
return expr;
my_friendly_assert (!integer_zerop (expr), 191);
+ intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));
if (TREE_CODE (type) == RECORD_TYPE
- && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE
- && type != TYPE_MAIN_VARIANT (TREE_TYPE (intype)))
+ && TREE_CODE (intype) == RECORD_TYPE
+ && type != intype)
{
tree path;
int distance
- = get_base_distance (binfo, TYPE_MAIN_VARIANT (TREE_TYPE (intype)),
- 0, &path);
+ = get_base_distance (binfo, intype, 0, &path);
/* This function shouldn't be called with unqualified arguments
but if it is, give them an error message that they can read. */
if (distance < 0)
{
cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'",
- TREE_TYPE (intype), type);
+ intype, type);
if (distance == -2)
cp_error ("because `%T' is an ambiguous base class", type);
@@ -663,11 +670,27 @@ ocp_convert (type, expr, convtype, flags)
&& TYPE_HAS_CONSTRUCTOR (type))
/* We need a new temporary; don't take this shortcut. */;
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
- /* Trivial conversion: cv-qualifiers do not matter on rvalues. */
- return fold (build1 (NOP_EXPR, type, e));
-
+ {
+ if (same_type_p (type, TREE_TYPE (e)))
+ /* The call to fold will not always remove the NOP_EXPR as
+ might be expected, since if one of the types is a typedef;
+ the comparsion in fold is just equality of pointers, not a
+ call to comptypes. We don't call fold in this case because
+ that can result in infinite recursion; fold will call
+ convert, which will call ocp_convert, etc. */
+ return e;
+ else
+ return fold (build1 (NOP_EXPR, type, e));
+ }
+
if (code == VOID_TYPE && (convtype & CONV_STATIC))
- return build1 (CONVERT_EXPR, type, e);
+ {
+ e = require_complete_type_in_void (e);
+ if (e != error_mark_node)
+ e = build1 (CONVERT_EXPR, void_type_node, e);
+
+ return e;
+ }
#if 0
/* This is incorrect. A truncation can't be stripped this way.
@@ -698,8 +721,7 @@ ocp_convert (type, expr, convtype, flags)
tree intype = TREE_TYPE (e);
/* enum = enum, enum = int, enum = float, (enum)pointer are all
errors. */
- if (flag_int_enum_equivalence == 0
- && TREE_CODE (type) == ENUMERAL_TYPE
+ if (TREE_CODE (type) == ENUMERAL_TYPE
&& ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC))
|| (TREE_CODE (intype) == POINTER_TYPE)))
{
@@ -711,7 +733,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (intype))
{
tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
+ rval = build_type_conversion (type, e, 1);
if (rval)
return rval;
if (flags & LOOKUP_COMPLAIN)
@@ -738,7 +760,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (TREE_TYPE (e)))
{
tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
+ rval = build_type_conversion (type, e, 1);
if (rval)
return rval;
else
@@ -794,6 +816,12 @@ ocp_convert (type, expr, convtype, flags)
ctor = e;
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
+ {
+ abstract_virtuals_error (NULL_TREE, type);
+ return error_mark_node;
+ }
+
if ((flags & LOOKUP_ONLYCONVERTING)
&& ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
/* For copy-initialization, first we create a temp of the proper type
@@ -918,8 +946,7 @@ convert_force (type, expr, convtype)
(jason 8/9/95) */
tree
-build_type_conversion (code, xtype, expr, for_sure)
- enum tree_code code;
+build_type_conversion (xtype, expr, for_sure)
tree xtype, expr;
int for_sure;
{
@@ -941,10 +968,15 @@ build_expr_type_conversion (desires, expr, complain)
int complain;
{
tree basetype = TREE_TYPE (expr);
- tree conv;
+ tree conv = NULL_TREE;
tree winner = NULL_TREE;
- if (TREE_CODE (basetype) == OFFSET_TYPE)
+ if (expr == null_node
+ && (desires & WANT_INT)
+ && !(desires & WANT_NULL))
+ cp_warning ("converting NULL to non-pointer type");
+
+ if (TREE_CODE (expr) == OFFSET_REF)
expr = resolve_offset_ref (expr);
expr = convert_from_reference (expr);
basetype = TREE_TYPE (expr);
@@ -953,8 +985,7 @@ build_expr_type_conversion (desires, expr, complain)
switch (TREE_CODE (basetype))
{
case INTEGER_TYPE:
- if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
- && integer_zerop (expr))
+ if ((desires & WANT_NULL) && null_ptr_cst_p (expr))
return expr;
/* else fall through... */
@@ -1045,13 +1076,12 @@ tree
type_promotes_to (type)
tree type;
{
- int constp, volatilep;
+ int type_quals;
if (type == error_mark_node)
return error_mark_node;
- constp = TYPE_READONLY (type);
- volatilep = TYPE_VOLATILE (type);
+ type_quals = CP_TYPE_QUALS (type);
type = TYPE_MAIN_VARIANT (type);
/* bool always promotes to int (not unsigned), even if it's the same
@@ -1085,10 +1115,9 @@ type_promotes_to (type)
else if (type == float_type_node)
type = double_type_node;
- return cp_build_type_variant (type, constp, volatilep);
+ return cp_build_qualified_type (type, type_quals);
}
-
/* The routines below this point are carefully written to conform to
the standard. They use the same terminology, and follow the rules
closely. Although they are used only in pt.c at the moment, they
@@ -1103,7 +1132,9 @@ perform_qualification_conversions (type, expr)
tree type;
tree expr;
{
- if (comp_target_types (type, TREE_TYPE (expr), 0) == 1)
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+ && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr))))
return build1 (NOP_EXPR, type, expr);
else
return error_mark_node;
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c
index 68f62ae..c60acc7 100644
--- a/contrib/gcc/cp/decl.c
+++ b/contrib/gcc/cp/decl.c
@@ -1,5 +1,5 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
+#include "../hash.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -60,9 +61,8 @@ extern tree current_namespace;
extern tree global_namespace;
extern void (*print_error_function) PROTO((char *));
+extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
-/* Stack of places to restore the search obstack back to. */
-
/* Obstack used for remembering local class declarations (like
enums and static (const) members. */
#include "stack.h"
@@ -133,8 +133,7 @@ static struct stack_level *decl_stack;
static tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
-static char *redeclaration_error_message PROTO((tree, tree));
-static tree push_overloaded_decl PROTO((tree, int));
+static const char *redeclaration_error_message PROTO((tree, tree));
static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *));
@@ -144,11 +143,9 @@ static void pop_binding_level PROTO((void));
static void suspend_binding_level PROTO((void));
static void resume_binding_level PROTO((struct binding_level *));
static struct binding_level *make_binding_level PROTO((void));
-static int namespace_bindings_p PROTO((void));
static void declare_namespace_level PROTO((void));
-static void signal_catch PROTO((int));
+static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
static void storedecls PROTO((tree));
-static void storetags PROTO((tree));
static void require_complete_types_for_parms PROTO((tree));
static void push_overloaded_decl_1 PROTO((tree));
static int ambi_op_p PROTO((tree));
@@ -162,20 +159,39 @@ static void warn_extern_redeclared_static PROTO((tree, tree));
static void grok_reference_init PROTO((tree, tree, tree));
static tree grokfndecl PROTO((tree, tree, tree, tree, int,
enum overload_flags, tree,
- tree, tree, int, int, int, int, int, int, tree));
+ tree, int, int, int, int, int, int, tree));
static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int));
static void set_identifier_type_value_with_scope
PROTO((tree, tree, struct binding_level *));
-static void set_identifier_local_value_with_scope
- PROTO((tree, tree, struct binding_level *));
-static void record_builtin_type PROTO((enum rid, char *, tree));
-static void record_unknown_type PROTO((tree, char *));
-static int member_function_or_else PROTO((tree, tree, char *));
-static void bad_specifiers PROTO((tree, char *, int, int, int, int,
+static void record_builtin_type PROTO((enum rid, const char *, tree));
+static void record_unknown_type PROTO((tree, const char *));
+static int member_function_or_else PROTO((tree, tree, const char *));
+static void bad_specifiers PROTO((tree, const char *, int, int, int, int,
int));
static void lang_print_error_function PROTO((char *));
+static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
+static void check_for_uninitialized_const_var PROTO((tree));
+static unsigned long typename_hash PROTO((hash_table_key));
+static boolean typename_compare PROTO((hash_table_key, hash_table_key));
+static void push_binding PROTO((tree, tree, struct binding_level*));
+static int add_binding PROTO((tree, tree));
+static void pop_binding PROTO((tree, tree));
+static tree local_variable_p PROTO((tree));
+static tree find_binding PROTO((tree, tree));
+static tree select_decl PROTO((tree, int));
+static tree unqualified_namespace_lookup PROTO((tree, int));
+static int lookup_flags PROTO((int, int));
+static tree qualify_lookup PROTO((tree, int));
+static tree record_builtin_java_type PROTO((const char *, int));
+static const char *tag_name PROTO((enum tag_types code));
+static void find_class_binding_level PROTO((void));
+static struct binding_level *innermost_nonclass_level PROTO((void));
+static tree poplevel_class PROTO((void));
+static void warn_about_implicit_typename_lookup PROTO((tree, tree));
+static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *));
+static int walk_globals_r PROTO((tree, void *));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -228,13 +244,17 @@ tree intQI_type_node;
tree intHI_type_node;
tree intSI_type_node;
tree intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
tree intTI_type_node;
+#endif
tree unsigned_intQI_type_node;
tree unsigned_intHI_type_node;
tree unsigned_intSI_type_node;
tree unsigned_intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
tree unsigned_intTI_type_node;
+#endif
tree java_byte_type_node;
tree java_short_type_node;
@@ -328,6 +348,7 @@ tree sigtable_entry_type;
/* Array type `vtable_entry_type[]' */
tree vtbl_type_node;
+tree vtbl_ptr_type_node;
/* namespace std */
tree std_node;
@@ -364,6 +385,10 @@ tree ctor_label;
tree abort_fndecl;
+/* A FUNCTION_DECL for the default `::operator delete'. */
+
+tree global_delete_fndecl;
+
extern rtx cleanup_label, return_label;
/* If original DECL_RESULT of current function was a register,
@@ -428,9 +453,8 @@ tree static_aggregates;
tree integer_zero_node;
tree null_pointer_node;
-/* The value for __null (NULL), either of type `void *' or, with -ansi,
- an integer type of the same size. */
-
+/* The value for __null (NULL), namely, a zero of an integer type with
+ the same number of bits as a pointer. */
tree null_node;
/* A node for the integer constants 1, 2, and 3. */
@@ -496,11 +520,6 @@ int current_function_returns_null;
tree current_function_return_value;
-/* Set to nonzero by `grokdeclarator' for a function
- whose return type is defaulted, if warnings for this are desired. */
-
-static int warn_about_return_type;
-
/* Nonzero means give `double' the same size as `float'. */
extern int flag_short_double;
@@ -559,6 +578,10 @@ extern tree previous_class_values;
node, but signed. */
tree signed_size_zero_node;
+/* The name of the anonymous namespace, throughout this translation
+ unit. */
+tree anonymous_namespace_name;
+
/* Allocate a level of searching. */
@@ -590,7 +613,10 @@ push_decl_level (stack, obstack)
to catch class-local declarations. It is otherwise nonexistent.
Also there may be binding levels that catch cleanups that must be
- run when exceptions occur. */
+ run when exceptions occur. Thus, to see whether a name is bound in
+ the current scope, it is not enough to look in the
+ CURRENT_BINDING_LEVEL. You should use lookup_name_current_level
+ instead. */
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
@@ -599,7 +625,8 @@ struct binding_level
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order
- supplied. */
+ supplied. There may be OVERLOADs on this list, too, but they
+ are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names;
/* A list of structure, union and enum definitions, for looking up
@@ -619,16 +646,17 @@ struct binding_level
VALUE the common ancestor with this binding_level's namespace. */
tree using_directives;
- /* For each level, a list of shadowed outer-level local definitions
- to be restored when this level is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* Same, for IDENTIFIER_CLASS_VALUE. */
+ /* If this binding level is the binding level for a class, then
+ class_shadowed is a TREE_LIST. The TREE_PURPOSE of each node
+ is the name of an entity bound in the class; the TREE_VALUE is
+ the IDENTIFIER_CLASS_VALUE before we entered the class. Thus,
+ when leaving class scope, we can restore the
+ IDENTIFIER_CLASS_VALUE by walking this list. The TREE_TYPE is
+ the DECL bound by this name in the class. */
tree class_shadowed;
- /* Same, for IDENTIFIER_TYPE_VALUE. */
+ /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
+ is used for all binding levels. */
tree type_shadowed;
/* For each level (except not the global one),
@@ -649,7 +677,8 @@ struct binding_level
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ANSI-conforming code, but might
- be referenced in ARM-era code. */
+ be referenced in ARM-era code. These are stored in a
+ TREE_LIST; the TREE_VALUE is the actual declaration. */
tree dead_vars_from_for;
/* 1 for the level that holds the parameters of a function.
@@ -691,7 +720,7 @@ struct binding_level
#define NULL_BINDING_LEVEL ((struct binding_level *) NULL)
-/* The (non-class) binding level currently in effect. */
+/* The binding level currently in effect. */
static struct binding_level *current_binding_level;
@@ -699,11 +728,6 @@ static struct binding_level *current_binding_level;
static struct binding_level *class_binding_level;
-/* The current (class or non-class) binding level currently in effect. */
-
-#define inner_binding_level \
- (class_binding_level ? class_binding_level : current_binding_level)
-
/* A chain of binding_level structures awaiting reuse. */
static struct binding_level *free_binding_level;
@@ -746,15 +770,7 @@ push_binding_level (newlevel, tag_transparent, keep)
/* Add this level to the front of the chain (stack) of levels that
are active. */
*newlevel = clear_binding_level;
- if (class_binding_level)
- {
- newlevel->level_chain = class_binding_level;
- class_binding_level = (struct binding_level *)0;
- }
- else
- {
- newlevel->level_chain = current_binding_level;
- }
+ newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
newlevel->more_cleanups_ok = 1;
@@ -769,12 +785,25 @@ push_binding_level (newlevel, tag_transparent, keep)
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
}
+/* Find the innermost enclosing class scope, and reset
+ CLASS_BINDING_LEVEL appropriately. */
+
+static void
+find_class_binding_level ()
+{
+ struct binding_level *level = current_binding_level;
+
+ while (level && level->parm_flag != 2)
+ level = level->level_chain;
+ if (level && level->parm_flag == 2)
+ class_binding_level = level;
+ else
+ class_binding_level = 0;
+}
+
static void
pop_binding_level ()
{
- if (class_binding_level)
- current_binding_level = class_binding_level;
-
if (global_binding_level)
{
/* Cannot pop a level, if there are none left to pop. */
@@ -803,13 +832,8 @@ pop_binding_level ()
if (level->binding_depth != binding_depth)
abort ();
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
- free_binding_level = level;
-
- class_binding_level = current_binding_level;
- if (class_binding_level->parm_flag != 2)
- class_binding_level = 0;
- while (current_binding_level->parm_flag == 2)
- current_binding_level = current_binding_level->level_chain;
+ free_binding_level = level;
+ find_class_binding_level ();
}
}
@@ -839,14 +863,8 @@ suspend_binding_level ()
}
is_class_level = 0;
#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
- {
- current_binding_level = current_binding_level->level_chain;
- class_binding_level = current_binding_level;
- if (class_binding_level->parm_flag != 2)
- class_binding_level = 0;
- while (current_binding_level->parm_flag == 2)
- current_binding_level = current_binding_level->level_chain;
- }
+ current_binding_level = current_binding_level->level_chain;
+ find_class_binding_level ();
}
static void
@@ -887,25 +905,44 @@ global_bindings_p ()
return current_binding_level == global_binding_level;
}
+/* Return the innermost binding level that is not for a class scope. */
+
+static struct binding_level *
+innermost_nonclass_level ()
+{
+ struct binding_level *b;
+
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
+
+ return b;
+}
+
/* Nonzero if we are currently in a toplevel binding level. This
means either the global binding level or a namespace in a toplevel
- binding level.
- Since there are no non-toplevel namespace levels, this really
- means any namespace or pseudo-global level. */
+ binding level. Since there are no non-toplevel namespace levels,
+ this really means any namespace or pseudo-global level. We also
+ include a class whose context is toplevel. */
int
toplevel_bindings_p ()
{
- return current_binding_level->namespace_p
- || current_binding_level->pseudo_global;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->namespace_p || b->pseudo_global;
}
-/* Nonzero if this is a namespace scope. */
+/* Nonzero if this is a namespace scope, or if we are defining a class
+ which is itself at namespace scope, or whose enclosing class is
+ such a class, etc. */
-static int
+int
namespace_bindings_p ()
{
- return current_binding_level->namespace_p;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->namespace_p;
}
void
@@ -949,7 +986,9 @@ declare_namespace_level ()
int
pseudo_global_level_p ()
{
- return current_binding_level->pseudo_global;
+ struct binding_level *b = innermost_nonclass_level ();
+
+ return b->pseudo_global;
}
void
@@ -1018,6 +1057,255 @@ pushlevel_temporary (tag_transparent)
expand_start_bindings (0);
}
+/* For a binding between a name and an entity at a block scope,
+ this is the `struct binding_level' for the block. */
+#define BINDING_LEVEL(NODE) \
+ (((struct tree_binding*)NODE)->scope.level)
+
+/* These are currently unused, but permanent, CPLUS_BINDING nodes.
+ They are kept here because they are allocated from the permanent
+ obstack and cannot be easily freed. */
+static tree free_binding_nodes;
+
+/* Make DECL the innermost binding for ID. The LEVEL is the binding
+ level at which this declaration is being bound. */
+
+static void
+push_binding (id, decl, level)
+ tree id;
+ tree decl;
+ struct binding_level* level;
+{
+ tree binding;
+
+ if (!free_binding_nodes)
+ {
+ /* There are no free nodes, so we must build one here. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ binding = make_node (CPLUS_BINDING);
+ pop_obstacks ();
+ }
+ else
+ {
+ /* There are nodes on the free list. Grab the first one. */
+ binding = free_binding_nodes;
+
+ /* And update the free list. */
+ free_binding_nodes = TREE_CHAIN (free_binding_nodes);
+ }
+
+ /* Now, fill in the binding information. */
+ BINDING_VALUE (binding) = decl;
+ BINDING_TYPE (binding) = NULL_TREE;
+ BINDING_LEVEL (binding) = level;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ LOCAL_BINDING_P (binding) = (level != class_binding_level);
+
+ /* And put it on the front of the list of bindings for ID. */
+ TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
+ IDENTIFIER_BINDING (id) = binding;
+}
+
+/* ID is already bound in the current scope. But, DECL is an
+ additional binding for ID in the same scope. This is the `struct
+ stat' hack whereby a non-typedef class-name or enum-name can be
+ bound at the same level as some other kind of entity. It's the
+ responsibility of the caller to check that inserting this name is
+ legal here. Returns nonzero if the new binding was successful. */
+static int
+add_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree binding = IDENTIFIER_BINDING (id);
+ int ok = 1;
+
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
+ /* The new name is the type name. */
+ BINDING_TYPE (binding) = decl;
+ else if (!BINDING_VALUE (binding))
+ /* This situation arises when push_class_level_binding moves an
+ inherited type-binding out of the way to make room for a new
+ value binding. */
+ BINDING_VALUE (binding) = decl;
+ else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding)))
+ {
+ /* The old binding was a type name. It was placed in
+ BINDING_VALUE because it was thought, at the point it was
+ declared, to be the only entity with such a name. Move the
+ type name into the type slot; it is now hidden by the new
+ binding. */
+ BINDING_TYPE (binding) = BINDING_VALUE (binding);
+ BINDING_VALUE (binding) = decl;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ else
+ {
+ cp_error ("declaration of `%#D'", decl);
+ cp_error_at ("conflicts with previous declaration `%#D'",
+ BINDING_VALUE (binding));
+ ok = 0;
+ }
+
+ return ok;
+}
+
+/* Bind DECL to ID in the current_binding_level.
+ If PUSH_USING is set in FLAGS, we know that DECL doesn't really belong
+ to this binding level, that it got here through a using-declaration. */
+
+void
+push_local_binding (id, decl, flags)
+ tree id;
+ tree decl;
+ int flags;
+{
+ struct binding_level *b;
+
+ /* Skip over any local classes. This makes sense if we call
+ push_local_binding with a friend decl of a local class. */
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
+
+ if (lookup_name_current_level (id))
+ {
+ /* Supplement the existing binding. */
+ if (!add_binding (id, decl))
+ /* It didn't work. Something else must be bound at this
+ level. Do not add DECL to the list of things to pop
+ later. */
+ return;
+ }
+ else
+ /* Create a new binding. */
+ push_binding (id, decl, b);
+
+ if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING))
+ /* We must put the OVERLOAD into a TREE_LIST since the
+ TREE_CHAIN of an OVERLOAD is already used. Similarly for
+ decls that got here through a using-declaration. */
+ decl = build_tree_list (NULL_TREE, decl);
+
+ /* And put DECL on the list of things declared by the current
+ binding level. */
+ TREE_CHAIN (decl) = b->names;
+ b->names = decl;
+}
+
+/* Bind DECL to ID in the class_binding_level. Returns nonzero if the
+ binding was successful. */
+
+int
+push_class_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ int result = 1;
+ tree binding = IDENTIFIER_BINDING (id);
+ tree context;
+
+ /* Note that we declared this value so that we can issue an error if
+ this an illegal redeclaration of a name already used for some
+ other purpose. */
+ note_name_declared_in_class (id, decl);
+
+ if (binding && BINDING_LEVEL (binding) == class_binding_level)
+ /* Supplement the existing binding. */
+ result = add_binding (id, decl);
+ else
+ /* Create a new binding. */
+ push_binding (id, decl, class_binding_level);
+
+ /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
+ class-level declaration. Note that we do not use DECL here
+ because of the possibility of the `struct stat' hack; if DECL is
+ a class-name or enum-name we might prefer a field-name, or some
+ such. */
+ IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
+
+ /* If this is a binding from a base class, mark it as such. */
+ binding = IDENTIFIER_BINDING (id);
+ if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST)
+ {
+ /* Any implicit typename must be from a base-class. The
+ context for an implicit typename declaration is always
+ the derived class in which the lookup was done, so the checks
+ based on the context of DECL below will not trigger. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (decl)))
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+ else
+ {
+ if (TREE_CODE (decl) == OVERLOAD)
+ context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
+ else
+ {
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
+ 0);
+ context = DECL_REAL_CONTEXT (decl);
+ }
+
+ if (is_properly_derived_from (current_class_type, context))
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+ else
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ }
+ else if (BINDING_VALUE (binding) == decl)
+ /* We only encounter a TREE_LIST when push_class_decls detects an
+ ambiguity. Such an ambiguity can be overridden by a definition
+ in this class. */
+ INHERITED_VALUE_BINDING_P (binding) = 1;
+
+ return result;
+}
+
+/* Remove the binding for DECL which should be the innermost binding
+ for ID. */
+
+static void
+pop_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree binding;
+
+ if (id == NULL_TREE)
+ /* It's easiest to write the loops that call this function without
+ checking whether or not the entities involved have names. We
+ get here for such an entity. */
+ return;
+
+ /* Get the innermost binding for ID. */
+ binding = IDENTIFIER_BINDING (id);
+
+ /* The name should be bound. */
+ my_friendly_assert (binding != NULL_TREE, 0);
+
+ /* The DECL will be either the ordinary binding or the type
+ binding for this identifier. Remove that binding. */
+ if (BINDING_VALUE (binding) == decl)
+ BINDING_VALUE (binding) = NULL_TREE;
+ else if (BINDING_TYPE (binding) == decl)
+ BINDING_TYPE (binding) = NULL_TREE;
+ else
+ my_friendly_abort (0);
+
+ if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
+ {
+ /* We're completely done with the innermost binding for this
+ identifier. Unhook it from the list of bindings. */
+ IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+ /* And place it on the free list. */
+ TREE_CHAIN (binding) = free_binding_nodes;
+ free_binding_nodes = binding;
+ }
+}
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
@@ -1026,12 +1314,6 @@ pushlevel_temporary (tag_transparent)
and create a "block" (a BLOCK node) for the level
to record its declarations and subblocks for symbol table output.
- If KEEP == 2, this level's subblocks go to the front,
- not the back of the current binding level. This happens,
- for instance, when code for constructors and destructors
- need to generate code at the end of a function which must
- be moved up to the front of the function.
-
If FUNCTIONBODY is nonzero, this level is the body of a function,
so create a block as if KEEP were set and also clear out all
label names.
@@ -1057,6 +1339,18 @@ poplevel (keep, reverse, functionbody)
tree block = NULL_TREE;
tree decl;
int block_previously_created;
+ int leaving_for_scope;
+
+ if (current_binding_level->parm_flag == 2)
+ return poplevel_class ();
+
+ my_friendly_assert (!current_binding_level->class_shadowed,
+ 19990414);
+
+ /* We used to use KEEP == 2 to indicate that the new block should go
+ at the beginning of the list of blocks at this binding level,
+ rather than the end. This hack is no longer used. */
+ my_friendly_assert (keep == 0 || keep == 1, 0);
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
@@ -1116,9 +1410,8 @@ poplevel (keep, reverse, functionbody)
if (decls || tags || subblocks)
{
if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
- {
- warning ("internal compiler error: debugging info corrupted");
- }
+ warning ("internal compiler error: debugging info corrupted");
+
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
@@ -1137,7 +1430,8 @@ poplevel (keep, reverse, functionbody)
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = subblocks;
- /* Otherwise, for a new block, install a new BLOCK_END_NOTE value. */
+ /* Otherwise, for a new block, install a new BLOCK_END_NOTE
+ value. */
remember_end_note (block);
}
}
@@ -1148,92 +1442,123 @@ poplevel (keep, reverse, functionbody)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
- /* Clear out the meanings of the local variables of this level. */
+ /* We still support the old for-scope rules, whereby the variables
+ in a for-init statement were in scope after the for-statement
+ ended. We only use the new rules in flag_new_for_scope is
+ nonzero. */
+ leaving_for_scope
+ = current_binding_level->is_for_scope && flag_new_for_scope == 1;
- if (current_binding_level->is_for_scope && flag_new_for_scope == 1)
+ /* Remove declarations for all the DECLs in this level. */
+ for (link = decls; link; link = TREE_CHAIN (link))
{
- struct binding_level *outer = current_binding_level->level_chain;
- for (link = decls; link; link = TREE_CHAIN (link))
+ if (leaving_for_scope && TREE_CODE (link) == VAR_DECL)
{
- if (TREE_CODE (link) == VAR_DECL)
- DECL_DEAD_FOR_LOCAL (link) = 1;
- else
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
- }
-
- /* Save declarations made in a 'for' statement so we can support pre-ANSI
- 'for' scoping semantics. */
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ tree ns_binding;
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- {
- tree id = TREE_PURPOSE (link);
- tree decl = IDENTIFIER_LOCAL_VALUE (id);
+ if (!outer_binding)
+ ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
+ else
+ ns_binding = NULL_TREE;
- if (decl && DECL_DEAD_FOR_LOCAL (decl))
- {
- /* In this case keep the dead for-decl visible,
- but remember what (if anything) it shadowed. */
- DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link);
- TREE_CHAIN (decl) = outer->dead_vars_from_for;
- outer->dead_vars_from_for = decl;
- }
+ if (outer_binding
+ && (BINDING_LEVEL (outer_binding)
+ == current_binding_level->level_chain))
+ /* We have something like:
+
+ int i;
+ for (int i; ;);
+
+ and we are leaving the `for' scope. There's no reason to
+ keep the binding of the inner `i' in this case. */
+ pop_binding (DECL_NAME (link), link);
+ else if ((outer_binding
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == TYPE_DECL))
+ || (ns_binding
+ && TREE_CODE (ns_binding) == TYPE_DECL))
+ /* Here, we have something like:
+
+ typedef int I;
+
+ void f () {
+ for (int I; ;);
+ }
+
+ We must pop the for-scope binding so we know what's a
+ type and what isn't. */
+ pop_binding (DECL_NAME (link), link);
else
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link);
- }
- }
- else /* Not special for scope. */
- {
- for (link = decls; link; link = TREE_CHAIN (link))
- {
- if (DECL_NAME (link) != NULL_TREE)
{
- /* If the ident. was used or addressed via a local extern decl,
- don't forget that fact. */
- if (DECL_EXTERNAL (link))
- {
- if (TREE_USED (link))
- TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1;
- if (TREE_ADDRESSABLE (link))
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
- }
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
- }
- }
-
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
- /* We first restore the regular decls and *then* the dead_vars_from_for
- to handle this case:
-
- int i; // i#1
- {
- for (int i; ; ) { ...} // i#2
- int i; // i#3
- } // we are here
+ /* Mark this VAR_DECL as dead so that we can tell we left it
+ there only for backward compatibility. */
+ DECL_DEAD_FOR_LOCAL (link) = 1;
+
+ /* Keep track of what should of have happenned when we
+ popped the binding. */
+ if (outer_binding && BINDING_VALUE (outer_binding))
+ DECL_SHADOWED_FOR_VAR (link)
+ = BINDING_VALUE (outer_binding);
+
+ /* Add it to the list of dead variables in the next
+ outermost binding to that we can remove these when we
+ leave that binding. */
+ current_binding_level->level_chain->dead_vars_from_for
+ = tree_cons (NULL_TREE, link,
+ current_binding_level->level_chain->
+ dead_vars_from_for);
+
+ /* Although we don't pop the CPLUS_BINDING, we do clear
+ its BINDING_LEVEL since the level is going away now. */
+ BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
+ = 0;
+ }
+ }
+ else
+ {
+ /* Remove the binding. */
+ decl = link;
+ if (TREE_CODE (decl) == TREE_LIST)
+ decl = TREE_VALUE (decl);
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ pop_binding (DECL_NAME (decl), decl);
+ else if (TREE_CODE (decl) == OVERLOAD)
+ pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
+ else
+ my_friendly_abort (0);
+ }
+ }
+
+ /* Remove declarations for any `for' variables from inner scopes
+ that we kept around. */
+ for (link = current_binding_level->dead_vars_from_for;
+ link; link = TREE_CHAIN (link))
+ pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
- In this case, we want remove the binding for i#3, restoring
- that of i#2. Then we want to remove the binding for i#2,
- and restore that of i#1. */
+ /* Restore the IDENTIFIER_TYPE_VALUEs. */
+ for (link = current_binding_level->type_shadowed;
+ link; link = TREE_CHAIN (link))
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
+
+ /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
+ list if a `using' declaration put them there. The debugging
+ back-ends won't understand OVERLOAD, so we remove them here.
+ Because the BLOCK_VARS are (temporarily) shared with
+ CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
+ popped all the bindings. */
+ if (block)
+ {
+ tree* d;
- link = current_binding_level->dead_vars_from_for;
- for (; link != NULL_TREE; link = TREE_CHAIN (link))
+ for (d = &BLOCK_VARS (block); *d; )
{
- tree id = DECL_NAME (link);
- if (IDENTIFIER_LOCAL_VALUE (id) == link)
- IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link);
+ if (TREE_CODE (*d) == TREE_LIST)
+ *d = TREE_CHAIN (*d);
+ else
+ d = &TREE_CHAIN (*d);
}
-
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
}
/* If the level being exited is the top level of a function,
@@ -1308,14 +1633,8 @@ poplevel (keep, reverse, functionbody)
must be carried forward so they will later become subblocks
of something else. */
else if (subblocks)
- {
- if (keep == 2)
- current_binding_level->blocks
- = chainon (subblocks, current_binding_level->blocks);
- else
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, subblocks);
- }
+ current_binding_level->blocks
+ = chainon (current_binding_level->blocks, subblocks);
/* Take care of compiler's internal binding structures. */
if (tmp == 2)
@@ -1402,9 +1721,7 @@ pushlevel_class ()
free_binding_level = free_binding_level->level_chain;
}
else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
@@ -1415,42 +1732,56 @@ pushlevel_class ()
decl_stack = push_decl_level (decl_stack, &decl_obstack);
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
- /* We have just pushed into a new binding level. Now, fake out the rest
- of the compiler. Set the `current_binding_level' back to point to
- the most closely containing non-class binding level. */
- do
- {
- current_binding_level = current_binding_level->level_chain;
- }
- while (current_binding_level->parm_flag == 2);
}
-/* ...and a poplevel for class declarations. FORCE is used to force
- clearing out of CLASS_VALUEs after a class definition. */
+/* ...and a poplevel for class declarations. */
-tree
-poplevel_class (force)
- int force;
+static tree
+poplevel_class ()
{
register struct binding_level *level = class_binding_level;
- tree block = NULL_TREE;
tree shadowed;
my_friendly_assert (level != 0, 354);
decl_stack = pop_stack_level (decl_stack);
- for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
/* If we're leaving a toplevel class, don't bother to do the setting
of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot
shouldn't even be used when current_class_type isn't set, and second,
if we don't touch it here, we're able to use the cache effect if the
next time we're entering a class scope, it is the same class. */
- if (current_class_depth != 1 || force)
- for (shadowed = level->class_shadowed;
- shadowed;
- shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
+ if (current_class_depth != 1)
+ {
+ struct binding_level* b;
+
+ /* Clear out our IDENTIFIER_CLASS_VALUEs. */
+ for (shadowed = level->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE;
+
+ /* Find the next enclosing class, and recreate
+ IDENTIFIER_CLASS_VALUEs appropriate for that class. */
+ b = level->level_chain;
+ while (b && b->parm_flag != 2)
+ b = b->level_chain;
+
+ if (b)
+ for (shadowed = b->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ {
+ tree t;
+
+ t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+ while (t && BINDING_LEVEL (t) != b)
+ t = TREE_CHAIN (t);
+
+ if (t)
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
+ = BINDING_VALUE (t);
+ }
+ }
else
/* Remember to save what IDENTIFIER's were bound in this scope so we
can recover from cache misses. */
@@ -1463,14 +1794,17 @@ poplevel_class (force)
shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
+ /* Remove the bindings for all of the class-level declarations. */
+ for (shadowed = level->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
+
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
class_binding_level->parm_flag,
class_binding_level->keep);
- if (class_binding_level->parm_flag != 2)
- class_binding_level = (struct binding_level *)0;
-
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
#if defined(DEBUG_CP_BINDING_LEVELS)
@@ -1479,8 +1813,224 @@ poplevel_class (force)
pop_binding_level ();
- return block;
+ return NULL_TREE;
+}
+
+/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
+ for any names in enclosing classes. */
+
+void
+clear_identifier_class_values ()
+{
+ tree t;
+
+ if (!class_binding_level)
+ return;
+
+ for (t = class_binding_level->class_shadowed;
+ t;
+ t = TREE_CHAIN (t))
+ IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
+}
+
+/* Returns non-zero if T is a virtual function table. */
+
+int
+vtable_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
+}
+
+/* Returns non-zero if T is a TYPE_DECL for a type with virtual
+ functions. */
+
+int
+vtype_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == TYPE_DECL
+ && TREE_TYPE (t) != error_mark_node
+ && TYPE_LANG_SPECIFIC (TREE_TYPE (t))
+ && CLASSTYPE_VSIZE (TREE_TYPE (t)));
+}
+
+/* Returns non-zero if T is a signature table. */
+
+int
+sigtable_decl_p (t, data)
+ tree t;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (TREE_CODE (t) == VAR_DECL
+ && TREE_TYPE (t) != error_mark_node
+ && IS_SIGNATURE (TREE_TYPE (t)));
+}
+
+/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
+ itself, calling F for each. The DATA is passed to F as well. */
+
+static int
+walk_namespaces_r (namespace, f, data)
+ tree namespace;
+ walk_namespaces_fn f;
+ void *data;
+{
+ tree current;
+ int result = 0;
+
+ result |= (*f) (namespace, data);
+
+ for (current = NAMESPACE_LEVEL (namespace)->names;
+ current;
+ current = TREE_CHAIN (current))
+ {
+ if (TREE_CODE (current) != NAMESPACE_DECL
+ || DECL_NAMESPACE_ALIAS (current))
+ continue;
+ if (!DECL_LANG_SPECIFIC (current))
+ {
+ /* Hmm. std. */
+ my_friendly_assert (current == std_node, 393);
+ continue;
+ }
+
+ /* We found a namespace. */
+ result |= walk_namespaces_r (current, f, data);
+ }
+
+ return result;
+}
+
+/* Walk all the namespaces, calling F for each. The DATA is passed to
+ F as well. */
+
+int
+walk_namespaces (f, data)
+ walk_namespaces_fn f;
+ void *data;
+{
+ return walk_namespaces_r (global_namespace, f, data);
+}
+
+struct walk_globals_data {
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+};
+
+/* Walk the global declarations in NAMESPACE. Whenever one is found
+ for which P returns non-zero, call F with its address. If any call
+ to F returns a non-zero value, return a non-zero value. */
+
+static int
+walk_globals_r (namespace, data)
+ tree namespace;
+ void *data;
+{
+ struct walk_globals_data* wgd = (struct walk_globals_data *) data;
+ walk_globals_pred p = wgd->p;
+ walk_globals_fn f = wgd->f;
+ void *d = wgd->data;
+ tree *t;
+ int result = 0;
+
+ t = &NAMESPACE_LEVEL (namespace)->names;
+
+ while (*t)
+ {
+ tree glbl = *t;
+
+ if ((*p) (glbl, d))
+ result |= (*f) (t, d);
+
+ /* If F changed *T, then *T still points at the next item to
+ examine. */
+ if (*t == glbl)
+ t = &TREE_CHAIN (*t);
+ }
+
+ return result;
+}
+
+/* Walk the global declarations. Whenever one is found for which P
+ returns non-zero, call F with its address. If any call to F
+ returns a non-zero value, return a non-zero value. */
+
+int
+walk_globals (p, f, data)
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+{
+ struct walk_globals_data wgd;
+ wgd.p = p;
+ wgd.f = f;
+ wgd.data = data;
+
+ return walk_namespaces (walk_globals_r, &wgd);
}
+
+/* Call wrapup_globals_declarations for the globals in NAMESPACE. If
+ DATA is non-NULL, this is the last time we will call
+ wrapup_global_declarations for this NAMESPACE. */
+
+int
+wrapup_globals_for_namespace (namespace, data)
+ tree namespace;
+ void *data;
+{
+ tree globals = NAMESPACE_LEVEL (namespace)->names;
+ int len = list_length (globals);
+ tree *vec = (tree *) alloca (sizeof (tree) * len);
+ int i;
+ int result;
+ tree decl;
+ int last_time = (data != 0);
+
+ if (last_time && namespace == global_namespace)
+ /* Let compile_file handle the global namespace. */
+ return 0;
+
+ /* Process the decls in reverse order--earliest first.
+ Put them into VEC from back to front, then take out from front. */
+
+ for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+ vec[len - i - 1] = decl;
+
+ if (last_time)
+ {
+ check_global_declarations (vec, len);
+ return 0;
+ }
+
+ /* Temporarily mark vtables as external. That prevents
+ wrapup_global_declarations from writing them out; we must process
+ them ourselves in finish_vtable_vardecl. */
+ for (i = 0; i < len; ++i)
+ if (vtable_decl_p (vec[i], /*data=*/0) && !DECL_EXTERNAL (vec[i]))
+ {
+ DECL_NOT_REALLY_EXTERN (vec[i]) = 1;
+ DECL_EXTERNAL (vec[i]) = 1;
+ }
+
+ /* Write out any globals that need to be output. */
+ result = wrapup_global_declarations (vec, len);
+
+ /* Undo the hack to DECL_EXTERNAL above. */
+ for (i = 0; i < len; ++i)
+ if (vtable_decl_p (vec[i], /*data=*/0)
+ && DECL_NOT_REALLY_EXTERN (vec[i]))
+ {
+ DECL_NOT_REALLY_EXTERN (vec[i]) = 0;
+ DECL_EXTERNAL (vec[i]) = 0;
+ }
+
+ return result;
+}
+
/* For debugging. */
static int no_print_functions = 0;
@@ -1569,15 +2119,6 @@ print_binding_level (lvl)
if (i)
fprintf (stderr, "\n");
}
- if (lvl->shadowed)
- {
- fprintf (stderr, " shadowed:");
- for (t = lvl->shadowed; t; t = TREE_CHAIN (t))
- {
- fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- fprintf (stderr, "\n");
- }
if (lvl->class_shadowed)
{
fprintf (stderr, " class-shadowed:");
@@ -1769,7 +2310,7 @@ void
push_namespace (name)
tree name;
{
- tree d;
+ tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
int global = 0;
@@ -1783,10 +2324,9 @@ push_namespace (name)
{
/* The name of anonymous namespace is unique for the translation
unit. */
- static tree anon_name = NULL_TREE;
- if (!anon_name)
- anon_name = get_file_function_name ('N');
- name = anon_name;
+ if (!anonymous_namespace_name)
+ anonymous_namespace_name = get_file_function_name ('N');
+ name = anonymous_namespace_name;
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d)
/* Reopening anonymous namespace. */
@@ -1854,34 +2394,6 @@ pop_namespace ()
suspend_binding_level ();
}
-/* Concatenate the binding levels of all namespaces. */
-
-void
-cat_namespace_levels()
-{
- tree current;
- tree last;
- struct binding_level *b;
-
- last = NAMESPACE_LEVEL (global_namespace) -> names;
- /* The nested namespaces appear in the names list of their ancestors. */
- for (current = last; current; current = TREE_CHAIN (current))
- {
- if (TREE_CODE (current) != NAMESPACE_DECL
- || DECL_NAMESPACE_ALIAS (current))
- continue;
- if (!DECL_LANG_SPECIFIC (current))
- {
- /* Hmm. std. */
- my_friendly_assert (current == std_node, 393);
- continue;
- }
- b = NAMESPACE_LEVEL (current);
- while (TREE_CHAIN (last))
- last = TREE_CHAIN (last);
- TREE_CHAIN (last) = NAMESPACE_LEVEL (current) -> names;
- }
-}
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
@@ -1893,7 +2405,9 @@ struct saved_scope {
tree old_bindings;
tree old_namespace;
struct saved_scope *prev;
- tree class_name, class_type, function_decl;
+ tree class_name, class_type;
+ tree access_specifier;
+ tree function_decl;
struct binding_level *class_bindings;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
@@ -1904,6 +2418,7 @@ struct saved_scope {
tree previous_class_type, previous_class_values;
int processing_specialization;
int processing_explicit_instantiation;
+ char *class_cache_firstobj;
};
static struct saved_scope *current_saved_scope;
@@ -1926,9 +2441,11 @@ store_bindings (names, old_bindings)
else
id = DECL_NAME (t);
- if (!id
- || (!IDENTIFIER_LOCAL_VALUE (id)
- && !IDENTIFIER_CLASS_VALUE (id)))
+ if (!id
+ /* Note that we may have an IDENTIFIER_CLASS_VALUE even when
+ we have no IDENTIFIER_BINDING if we have left the class
+ scope, but cached the class-level declarations. */
+ || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
@@ -1948,9 +2465,9 @@ store_bindings (names, old_bindings)
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id;
TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
+ TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
+ IDENTIFIER_BINDING (id) = NULL_TREE;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
TREE_CHAIN (binding) = old_bindings;
@@ -1968,11 +2485,10 @@ maybe_push_to_top_level (pseudo)
extern int current_lang_stacksize;
struct saved_scope *s
= (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
tree old_bindings = NULL_TREE;
- if (current_function_decl)
- push_cp_function_context (NULL_TREE);
+ push_cp_function_context (NULL_TREE);
if (previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
@@ -2007,6 +2523,7 @@ maybe_push_to_top_level (pseudo)
s->old_namespace = current_namespace;
s->class_name = current_class_name;
s->class_type = current_class_type;
+ s->access_specifier = current_access_specifier;
s->function_decl = current_function_decl;
s->class_bindings = class_binding_level;
s->lang_stack = current_lang_stack;
@@ -2019,6 +2536,7 @@ maybe_push_to_top_level (pseudo)
s->processing_template_decl = processing_template_decl;
s->previous_class_type = previous_class_type;
s->previous_class_values = previous_class_values;
+ s->class_cache_firstobj = class_cache_firstobj;
s->processing_specialization = processing_specialization;
s->processing_explicit_instantiation = processing_explicit_instantiation;
@@ -2034,6 +2552,7 @@ maybe_push_to_top_level (pseudo)
shadowed_labels = NULL_TREE;
minimal_parse_mode = 0;
previous_class_type = previous_class_values = NULL_TREE;
+ class_cache_firstobj = 0;
processing_specialization = 0;
processing_explicit_instantiation = 0;
current_template_parms = NULL_TREE;
@@ -2062,10 +2581,7 @@ pop_from_top_level ()
/* Clear out class-level bindings cache. */
if (previous_class_type)
- {
- popclass (-1);
- previous_class_type = NULL_TREE;
- }
+ invalidate_class_lookup_cache ();
pop_obstacks ();
@@ -2078,7 +2594,7 @@ pop_from_top_level ()
if (id)
{
SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
+ IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
}
t = TREE_CHAIN (t);
@@ -2088,6 +2604,7 @@ pop_from_top_level ()
current_namespace = s->old_namespace;
current_class_name = s->class_name;
current_class_type = s->class_type;
+ current_access_specifier = s->access_specifier;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
free (current_lang_base);
@@ -2107,11 +2624,11 @@ pop_from_top_level ()
previous_class_values = s->previous_class_values;
processing_specialization = s->processing_specialization;
processing_explicit_instantiation = s->processing_explicit_instantiation;
+ class_cache_firstobj = s->class_cache_firstobj;
free (s);
- if (current_function_decl)
- pop_cp_function_context (NULL_TREE);
+ pop_cp_function_context (NULL_TREE);
}
/* Push a definition of struct, union or enum tag "name".
@@ -2151,34 +2668,14 @@ set_identifier_type_value_with_scope (id, type, b)
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
-/* As set_identifier_type_value_with_scope, but using inner_binding_level. */
+/* As set_identifier_type_value_with_scope, but using current_binding_level. */
void
set_identifier_type_value (id, type)
tree id;
tree type;
{
- set_identifier_type_value_with_scope (id, type, inner_binding_level);
-}
-
-static void
-set_identifier_local_value_with_scope (id, val, b)
- tree id, val;
- struct binding_level *b;
-{
- tree oldlocal;
- my_friendly_assert (! b->namespace_p, 980716);
-
- oldlocal = IDENTIFIER_LOCAL_VALUE (id);
- b->shadowed = tree_cons (id, oldlocal, b->shadowed);
- IDENTIFIER_LOCAL_VALUE (id) = val;
-}
-
-void
-set_identifier_local_value (id, val)
- tree id, val;
-{
- set_identifier_local_value_with_scope (id, val, current_binding_level);
+ set_identifier_type_value_with_scope (id, type, current_binding_level);
}
/* Return the type associated with id. */
@@ -2211,10 +2708,10 @@ pop_everything ()
#ifdef DEBUG_CP_BINDING_LEVELS
fprintf (stderr, "XXX entering pop_everything ()\n");
#endif
- while (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+ while (!toplevel_bindings_p ())
{
- if (class_binding_level)
- pop_nested_class (1);
+ if (current_binding_level->parm_flag == 2)
+ pop_nested_class ();
else
poplevel (0, 0, 0);
}
@@ -2223,6 +2720,90 @@ pop_everything ()
#endif
}
+/* The type TYPE is being declared. If it is a class template, or a
+ specialization of a class template, do any processing required and
+ perform error-checking. If IS_FRIEND is non-zero, this TYPE is
+ being declared a friend. B is the binding level at which this TYPE
+ should be bound.
+
+ Returns the TYPE_DECL for TYPE, which may have been altered by this
+ processing. */
+
+static tree
+maybe_process_template_type_declaration (type, globalize, b)
+ tree type;
+ int globalize;
+ struct binding_level* b;
+{
+ tree decl = TYPE_NAME (type);
+
+ if (processing_template_parmlist)
+ /* You can't declare a new template type in a template parameter
+ list. But, you can declare a non-template type:
+
+ template <class A*> struct S;
+
+ is a forward-declaration of `A'. */
+ ;
+ else
+ {
+ maybe_check_template_type (type);
+
+ my_friendly_assert (IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == ENUMERAL_TYPE, 0);
+
+
+ if (/* If !GLOBALIZE then we are looking at a definition.
+ It may not be a primary template. (For example, in:
+
+ template <class T>
+ struct S1 { class S2 {}; }
+
+ we have to push_template_decl for S2.) */
+ (processing_template_decl && !globalize)
+ /* If we are declaring a friend template class, we will
+ have GLOBALIZE set, since something like:
+
+ template <class T>
+ struct S1 {
+ template <class U>
+ friend class S2;
+ };
+
+ declares S2 to be at global scope. */
+ || PROCESSING_REAL_TEMPLATE_DECL_P ())
+ {
+ /* This may change after the call to
+ push_template_decl_real, but we want the original value. */
+ tree name = DECL_NAME (decl);
+
+ decl = push_template_decl_real (decl, globalize);
+ /* If the current binding level is the binding level for the
+ template parameters (see the comment in
+ begin_template_parm_list) and the enclosing level is a class
+ scope, and we're not looking at a friend, push the
+ declaration of the member class into the class scope. In the
+ friend case, push_template_decl will already have put the
+ friend into global scope, if appropriate. */
+ if (TREE_CODE (type) != ENUMERAL_TYPE
+ && !globalize && b->pseudo_global
+ && b->level_chain->parm_flag == 2)
+ {
+ finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
+ /* Put this tag on the list of tags for the class, since
+ that won't happen below because B is not the class
+ binding level, but is instead the pseudo-global level. */
+ b->level_chain->tags =
+ saveable_tree_cons (name, type, b->level_chain->tags);
+ if (TYPE_SIZE (current_class_type) == NULL_TREE)
+ CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+ }
+ }
+ }
+
+ return decl;
+}
+
/* Push a tag name NAME for struct/class/union/enum type TYPE.
Normally put it into the inner-most non-tag-transparent scope,
but if GLOBALIZE is true, put it in the inner-most non-class scope.
@@ -2234,10 +2815,8 @@ pushtag (name, type, globalize)
int globalize;
{
register struct binding_level *b;
- tree context = 0;
- tree c_decl = 0;
- b = inner_binding_level;
+ b = current_binding_level;
while (b->tag_transparent
|| (globalize && b->parm_flag == 2))
b = b->level_chain;
@@ -2249,32 +2828,34 @@ pushtag (name, type, globalize)
if (name)
{
- context = type ? TYPE_CONTEXT (type) : NULL_TREE;
- if (! context)
- {
- tree cs = current_scope ();
-
- if (! globalize)
- context = cs;
- else if (cs != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
- /* When declaring a friend class of a local class, we want
- to inject the newly named class into the scope
- containing the local class, not the namespace scope. */
- context = hack_decl_function_context (get_type_decl (cs));
- }
- if (context)
- c_decl = TREE_CODE (context) == FUNCTION_DECL
- ? context : TYPE_MAIN_DECL (context);
-
- if (!context)
- context = current_namespace;
-
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
register tree d = NULL_TREE;
int newdecl = 0, in_class = 0;
+ tree context;
+ tree c_decl = NULL_TREE;
+
+ context = type ? TYPE_CONTEXT (type) : NULL_TREE;
+ if (! context)
+ {
+ tree cs = current_scope ();
+
+ if (! globalize)
+ context = cs;
+ else if (cs != NULL_TREE
+ && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
+ /* When declaring a friend class of a local class, we want
+ to inject the newly named class into the scope
+ containing the local class, not the namespace scope. */
+ context = hack_decl_function_context (get_type_decl (cs));
+ }
+ if (context)
+ c_decl = TREE_CODE (context) == FUNCTION_DECL
+ ? context : TYPE_MAIN_DECL (context);
+
+ if (!context)
+ context = current_namespace;
if ((b->pseudo_global && b->level_chain->parm_flag == 2)
|| b->parm_flag == 2)
@@ -2298,66 +2879,20 @@ pushtag (name, type, globalize)
TYPE_NAME (type) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
- if (processing_template_parmlist)
- /* You can't declare a new template type in a template
- parameter list. But, you can declare a non-template
- type:
-
- template <class A*> struct S;
-
- is a forward-declaration of `A'. */
- ;
- else if (IS_AGGR_TYPE (type)
- && (/* If !GLOBALIZE then we are looking at a
- definition. It may not be a primary template.
- (For example, in:
-
- template <class T>
- struct S1 { class S2 {}; }
-
- we have to push_template_decl for S2.) */
- (processing_template_decl && !globalize)
- /* If we are declaring a friend template class, we
- will have GLOBALIZE set, since something like:
-
- template <class T>
- struct S1 {
- template <class U>
- friend class S2;
- };
+ d = maybe_process_template_type_declaration (type,
+ globalize, b);
- declares S2 to be at global scope. */
- || (processing_template_decl >
- template_class_depth (current_class_type))))
+ if (b->parm_flag == 2)
{
- d = push_template_decl_real (d, globalize);
- /* If the current binding level is the binding level for
- the template parameters (see the comment in
- begin_template_parm_list) and the enclosing level is
- a class scope, and we're not looking at a friend,
- push the declaration of the member class into the
- class scope. In the friend case, push_template_decl
- will already have put the friend into global scope,
- if appropriate. */
- if (!globalize && b->pseudo_global &&
- b->level_chain->parm_flag == 2)
- {
- pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
- b->level_chain);
- /* Put this tag on the list of tags for the class,
- since that won't happen below because B is not
- the class binding level, but is instead the
- pseudo-global level. */
- b->level_chain->tags =
- saveable_tree_cons (name, type, b->level_chain->tags);
- TREE_NONLOCAL_FLAG (type) = 1;
- if (TYPE_SIZE (current_class_type) == NULL_TREE)
- CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
- }
+ if (newdecl && !PROCESSING_REAL_TEMPLATE_DECL_P ())
+ /* Put this TYPE_DECL on the TYPE_FIELDS list for the
+ class. But if it's a member template class, we
+ want the TEMPLATE_DECL, not the TYPE_DECL, so this
+ is done later. */
+ finish_member_declaration (d);
+ else
+ pushdecl_class_level (d);
}
-
- if (b->parm_flag == 2)
- d = pushdecl_class_level (d);
else
d = pushdecl_with_scope (d, b);
@@ -2368,13 +2903,13 @@ pushtag (name, type, globalize)
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
- DECL_ASSEMBLER_NAME (d)
- = get_identifier (build_overload_name (type, 1, 1));
+ if (!uses_template_parms (type))
+ DECL_ASSEMBLER_NAME (d)
+ = get_identifier (build_overload_name (type, 1, 1));
}
}
if (b->parm_flag == 2)
{
- TREE_NONLOCAL_FLAG (type) = 1;
if (TYPE_SIZE (current_class_type) == NULL_TREE)
CLASSTYPE_TAGS (current_class_type) = b->tags;
}
@@ -2458,8 +2993,15 @@ decls_match (newdecl, olddecl)
{
int types_match;
- if (TREE_CODE (newdecl) == FUNCTION_DECL
- && TREE_CODE (olddecl) == FUNCTION_DECL)
+ if (newdecl == olddecl)
+ return 1;
+
+ if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
+ /* If the two DECLs are not even the same kind of thing, we're not
+ interested in their types. */
+ return 0;
+
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
@@ -2494,7 +3036,7 @@ decls_match (newdecl, olddecl)
return 0;
}
- if (comptypes (TREE_TYPE (f1), TREE_TYPE (f2), 1))
+ if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
&& p2 == NULL_TREE)
@@ -2510,13 +3052,12 @@ decls_match (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
else
- types_match = compparms (p1, p2, 3);
+ types_match = compparms (p1, p2);
}
else
types_match = 0;
}
- else if (TREE_CODE (newdecl) == TEMPLATE_DECL
- && TREE_CODE (olddecl) == TEMPLATE_DECL)
+ else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
@@ -2536,20 +3077,10 @@ decls_match (newdecl, olddecl)
types_match = TREE_TYPE (newdecl) == NULL_TREE;
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
- /* Qualifiers must match, and they may be present on either, the type
- or the decl. */
- else if ((TREE_READONLY (newdecl)
- || TYPE_READONLY (TREE_TYPE (newdecl)))
- == (TREE_READONLY (olddecl)
- || TYPE_READONLY (TREE_TYPE (olddecl)))
- && (TREE_THIS_VOLATILE (newdecl)
- || TYPE_VOLATILE (TREE_TYPE (newdecl)))
- == (TREE_THIS_VOLATILE (olddecl)
- || TYPE_VOLATILE (TREE_TYPE (olddecl))))
- types_match = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (newdecl)),
- TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)), 1);
else
- types_match = 0;
+ types_match = comptypes (TREE_TYPE (newdecl),
+ TREE_TYPE (olddecl),
+ COMPARE_REDECLARATION);
}
return types_match;
@@ -2571,9 +3102,9 @@ warn_extern_redeclared_static (newdecl, olddecl)
{
tree name;
- static char *explicit_extern_static_warning
+ static const char *explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
- static char *implicit_extern_static_warning
+ static const char *implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
if (TREE_CODE (newdecl) == TYPE_DECL)
@@ -2709,6 +3240,11 @@ duplicate_decls (newdecl, olddecl)
}
else if (!types_match)
{
+ if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl))
+ /* These are certainly not duplicate declarations; they're
+ from different scopes. */
+ return 0;
+
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
/* The name of a class template may not be declared to refer to
@@ -2724,7 +3260,7 @@ duplicate_decls (newdecl, olddecl)
else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
- TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))), 3)
+ TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
{
@@ -2743,7 +3279,7 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration `%#D' here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
- TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 3))
+ TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@@ -2793,7 +3329,7 @@ duplicate_decls (newdecl, olddecl)
return 1;
else
{
- char *errmsg = redeclaration_error_message (newdecl, olddecl);
+ const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
cp_error (errmsg, newdecl);
@@ -2873,13 +3409,6 @@ duplicate_decls (newdecl, olddecl)
olddecl);
}
}
- /* These bits are logically part of the type for non-functions. */
- else if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
- || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
- {
- cp_pedwarn ("type qualifiers for `%#D'", newdecl);
- cp_pedwarn_at ("conflict with previous decl `%#D'", olddecl);
- }
}
/* If new decl is `static' and an `extern' was seen previously,
@@ -2945,17 +3474,13 @@ duplicate_decls (newdecl, olddecl)
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
- if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE)
- {
- if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl),
- DECL_TEMPLATE_RESULT (olddecl)))
- cp_error ("invalid redeclaration of %D", newdecl);
- TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
- DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
- DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
- }
- DECL_TEMPLATE_SPECIALIZATIONS (newdecl)
- = DECL_TEMPLATE_SPECIALIZATIONS (olddecl);
+ if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl),
+ DECL_TEMPLATE_RESULT (olddecl)))
+ cp_error ("invalid redeclaration of %D", newdecl);
+ TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
+ DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
+ = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
+ DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
return 1;
}
@@ -2991,7 +3516,8 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (olddecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
- if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
+ if ((pedantic || (! DECL_IN_SYSTEM_HEADER (olddecl)
+ && ! DECL_IN_SYSTEM_HEADER (newdecl)))
&& DECL_SOURCE_LINE (olddecl) != 0
&& flag_exceptions
&& ! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
@@ -3004,7 +3530,7 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (newtype != canonical_type_variant (oldtype)
+ if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
@@ -3030,6 +3556,9 @@ duplicate_decls (newdecl, olddecl)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
+ if (DECL_LANG_SPECIFIC (newdecl)
+ && DECL_LANG_SPECIFIC (olddecl))
+ DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
}
/* Merge the section attribute.
@@ -3076,17 +3605,22 @@ duplicate_decls (newdecl, olddecl)
DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+ DECL_TEMPLATE_INSTANTIATED (newdecl)
+ |= DECL_TEMPLATE_INSTANTIATED (olddecl);
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
- if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
- {
- DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
- DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
- }
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
+
+ /* Only functions have DECL_BEFRIENDING_CLASSES. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (newdecl))
+ DECL_BEFRIENDING_CLASSES (newdecl)
+ = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+ DECL_BEFRIENDING_CLASSES (olddecl));
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3292,23 +3826,30 @@ pushdecl (x)
{
register tree t;
register tree name = DECL_ASSEMBLER_NAME (x);
- register struct binding_level *b = current_binding_level;
+ int need_new_binding = 1;
- if (current_function_decl && x != current_function_decl
- /* A local declaration for a function doesn't constitute nesting. */
- && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
- /* Don't change DECL_CONTEXT of virtual methods. */
- && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
- && ! DECL_CONTEXT (x))
- DECL_CONTEXT (x) = current_function_decl;
- if (!DECL_CONTEXT (x))
- DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
+ if (DECL_TEMPLATE_PARM_P (x))
+ /* Template parameters have no context; they are not X::T even
+ when declared within a class or namespace. */
+ ;
+ else
+ {
+ if (current_function_decl && x != current_function_decl
+ /* A local declaration for a function doesn't constitute
+ nesting. */
+ && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
+ /* Don't change DECL_CONTEXT of virtual methods. */
+ && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
+ && !DECL_CONTEXT (x))
+ DECL_CONTEXT (x) = current_function_decl;
+ if (!DECL_CONTEXT (x))
+ DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
+ }
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
- || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM
- || TREE_CODE (x) == TEMPLATE_TEMPLATE_PARM)
+ || TREE_CODE (x) == NAMESPACE_DECL)
name = DECL_NAME (x);
if (name)
@@ -3422,14 +3963,30 @@ pushdecl (x)
}
}
+ check_template_shadow (x);
+
+ /* If this is a function conjured up by the backend, massage it
+ so it looks friendly. */
+ if (TREE_CODE (x) == FUNCTION_DECL
+ && ! DECL_LANG_SPECIFIC (x))
+ {
+ retrofit_lang_decl (x);
+ DECL_LANGUAGE (x) = lang_c;
+ }
+
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
- t = push_overloaded_decl (x, 1);
+ t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
+ if (!namespace_bindings_p ())
+ /* We do not need to create a binding for this name;
+ push_overloaded_decl will have already done so if
+ necessary. */
+ need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
- return push_overloaded_decl (x, 0);
+ return push_overloaded_decl (x, PUSH_GLOBAL);
/* If declaring a type as a typedef, copy the type (unless we're
at line 0), and install this TYPE_DECL as the new type's typedef
@@ -3442,7 +3999,12 @@ pushdecl (x)
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = x;
}
- else if (type != error_mark_node && TYPE_NAME (type) != x)
+ else if (type != error_mark_node && TYPE_NAME (type) != x
+ /* We don't want to copy the type when all we're
+ doing is making a TYPE_DECL for the purposes of
+ inlining. */
+ && (!TYPE_NAME (type)
+ || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
{
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
@@ -3458,7 +4020,9 @@ pushdecl (x)
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
- set_identifier_type_value_with_scope (DECL_NAME (x), type, b);
+ set_identifier_type_value_with_scope (DECL_NAME (x), type,
+ current_binding_level);
+
}
/* Multiple external decls of the same identifier ought to match.
@@ -3470,19 +4034,18 @@ pushdecl (x)
if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
{
tree decl;
- tree bindings = binding_for_name (name, current_namespace);
- if (BINDING_VALUE (bindings) != NULL_TREE
- && (DECL_EXTERNAL (BINDING_VALUE (bindings))
- || TREE_PUBLIC (BINDING_VALUE (bindings))))
- decl = BINDING_VALUE (bindings);
+ if (IDENTIFIER_NAMESPACE_VALUE (name) != NULL_TREE
+ && (DECL_EXTERNAL (IDENTIFIER_NAMESPACE_VALUE (name))
+ || TREE_PUBLIC (IDENTIFIER_NAMESPACE_VALUE (name))))
+ decl = IDENTIFIER_NAMESPACE_VALUE (name);
else
decl = NULL_TREE;
if (decl
/* If different sort of thing, we already gave an error. */
&& TREE_CODE (decl) == TREE_CODE (x)
- && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1))
+ && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
{
cp_pedwarn ("type mismatch with previous external decl", x);
cp_pedwarn_at ("previous external decl of `%#D'", decl);
@@ -3494,23 +4057,20 @@ pushdecl (x)
if (namespace_bindings_p ())
{
/* Install a global value. */
- tree bindings = binding_for_name (name, current_namespace);
/* If the first global decl has external linkage,
warn if we later see static one. */
- if (BINDING_VALUE (bindings) == NULL_TREE && TREE_PUBLIC (x))
+ if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- /* Don't install an artificial TYPE_DECL if we already have
- another _DECL with that name. */
- if (TREE_CODE (x) != TYPE_DECL
- || t == NULL_TREE
- || ! DECL_ARTIFICIAL (x))
+ if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && t != NULL_TREE))
{
if (TREE_CODE (x) == FUNCTION_DECL)
- my_friendly_assert ((BINDING_VALUE (bindings) == NULL_TREE)
- || BINDING_VALUE (bindings) == x, 378);
- BINDING_VALUE (bindings) = x;
+ my_friendly_assert
+ ((IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
+ || (IDENTIFIER_GLOBAL_VALUE (name) == x), 378);
+ SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
}
/* Don't forget if the function was used via an implicit decl. */
@@ -3539,61 +4099,65 @@ pushdecl (x)
else
{
/* Here to install a non-global value. */
- tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
- tree oldglobal = binding_for_name (name, current_namespace);
+ tree oldlocal = IDENTIFIER_VALUE (name);
+ tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
- /* Don't install an artificial TYPE_DECL if we already have
- another _DECL with that name. */
- if (TREE_CODE (x) != TYPE_DECL
- || t == NULL_TREE
- || ! DECL_ARTIFICIAL (x))
- set_identifier_local_value_with_scope (name, x, b);
+ if (need_new_binding)
+ {
+ push_local_binding (name, x, 0);
+ /* Because push_local_binding will hook X on to the
+ current_binding_level's name list, we don't want to
+ do that again below. */
+ need_new_binding = 0;
+ }
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
- set_identifier_type_value_with_scope (name, TREE_TYPE (x), b);
+ set_identifier_type_value_with_scope (name, TREE_TYPE (x),
+ current_binding_level);
/* Clear out any TYPE_DECL shadowed by a namespace so that
we won't think this is a type. The C struct hack doesn't
go through namespaces. */
if (TREE_CODE (x) == NAMESPACE_DECL)
- set_identifier_type_value_with_scope (name, NULL_TREE, b);
+ set_identifier_type_value_with_scope (name, NULL_TREE,
+ current_binding_level);
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
if (oldlocal == NULL_TREE
&& DECL_EXTERNAL (x)
- && BINDING_VALUE (oldglobal) != NULL_TREE
+ && oldglobal != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL
- && TREE_CODE (BINDING_VALUE (oldglobal)) == FUNCTION_DECL)
+ && TREE_CODE (oldglobal) == FUNCTION_DECL)
{
/* We have one. Their types must agree. */
- if (decls_match (x, BINDING_VALUE (oldglobal)))
+ if (decls_match (x, oldglobal))
/* OK */;
else
{
cp_warning ("extern declaration of `%#D' doesn't match", x);
- cp_warning_at ("global declaration `%#D'", BINDING_VALUE (oldglobal));
+ cp_warning_at ("global declaration `%#D'", oldglobal);
}
}
/* If we have a local external declaration,
and no file-scope declaration has yet been seen,
then if we later have a file-scope decl it must not be static. */
if (oldlocal == NULL_TREE
- && BINDING_VALUE (oldglobal) == NULL_TREE
+ && oldglobal == NULL_TREE
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
- {
- TREE_PUBLIC (name) = 1;
- }
+ TREE_PUBLIC (name) = 1;
if (DECL_FROM_INLINE (x))
/* Inline decls shadow nothing. */;
/* Warn if shadowing an argument at the top level of the body. */
else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
- && TREE_CODE (oldlocal) == PARM_DECL
- && TREE_CODE (x) != PARM_DECL)
+ && TREE_CODE (oldlocal) == PARM_DECL
+ /* Don't complain if it's from an enclosing function. */
+ && DECL_CONTEXT (oldlocal) == current_function_decl
+ && TREE_CODE (x) != PARM_DECL)
{
/* Go to where the parms should be and see if we
find them there. */
@@ -3606,7 +4170,8 @@ pushdecl (x)
if (b->parm_flag == 1)
cp_error ("declaration of `%#D' shadows a parameter", name);
}
- else if (warn_shadow && oldlocal != NULL_TREE && b->is_for_scope
+ else if (warn_shadow && oldlocal != NULL_TREE
+ && current_binding_level->is_for_scope
&& !DECL_DEAD_FOR_LOCAL (oldlocal))
{
warning ("variable `%s' shadows local",
@@ -3620,7 +4185,7 @@ pushdecl (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
- char *warnstring = NULL;
+ const char *warnstring = NULL;
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter";
@@ -3630,7 +4195,7 @@ pushdecl (x)
warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE)
warnstring = "declaration of `%s' shadows previous local";
- else if (BINDING_VALUE (oldglobal) != NULL_TREE)
+ else if (oldglobal != NULL_TREE)
/* XXX shadow warnings in outer-more namespaces */
warnstring = "declaration of `%s' shadows global declaration";
@@ -3650,15 +4215,20 @@ pushdecl (x)
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (TREE_TYPE (x)))))
- b->incomplete = tree_cons (NULL_TREE, x, b->incomplete);
+ current_binding_level->incomplete
+ = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
}
- /* Put decls on list in reverse order.
- We will reverse them later if necessary. */
- TREE_CHAIN (x) = b->names;
- b->names = x;
- if (! (b != global_binding_level || TREE_PERMANENT (x)))
- my_friendly_abort (124);
+ if (need_new_binding)
+ {
+ /* Put decls on list in reverse order.
+ We will reverse them later if necessary. */
+ TREE_CHAIN (x) = current_binding_level->names;
+ current_binding_level->names = x;
+ if (current_binding_level == global_binding_level
+ && !TREE_PERMANENT (x))
+ my_friendly_abort (124);
+ }
return x;
}
@@ -3700,7 +4270,7 @@ tree
pushdecl_namespace_level (x)
tree x;
{
- register struct binding_level *b = inner_binding_level;
+ register struct binding_level *b = current_binding_level;
register tree t;
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
@@ -3755,46 +4325,33 @@ pushdecl_top_level (x)
/* Make the declaration of X appear in CLASS scope. */
-tree
+void
pushdecl_class_level (x)
tree x;
{
/* Don't use DECL_ASSEMBLER_NAME here! Everything that looks in class
scope looks for the pre-mangled name. */
- register tree name = DECL_NAME (x);
+ register tree name;
+
+ if (TREE_CODE (x) == OVERLOAD)
+ x = OVL_CURRENT (x);
+ name = DECL_NAME (x);
if (name)
{
- if (TYPE_BEING_DEFINED (current_class_type))
- {
- /* A name N used in a class S shall refer to the same declaration
- in its context and when re-evaluated in the completed scope of S.
-
- Types, enums, and static vars are checked here; other
- members are checked in finish_struct. */
- tree icv = IDENTIFIER_CLASS_VALUE (name);
-
- if (icv && icv != x
- && flag_optional_diags
- /* Don't complain about inherited names. */
- && id_in_current_class (name)
- /* Or shadowed tags. */
- && !(DECL_DECLARES_TYPE_P (icv)
- && DECL_CONTEXT (icv) == current_class_type))
- {
- cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x);
- cp_pedwarn_at ("conflicts with previous use in class as `%#D'",
- icv);
- }
- }
-
push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
- {
- set_identifier_type_value (name, TREE_TYPE (x));
- }
+ set_identifier_type_value (name, TREE_TYPE (x));
+ }
+ else if (ANON_UNION_TYPE_P (TREE_TYPE (x)))
+ {
+ tree f;
+
+ for (f = TYPE_FIELDS (TREE_TYPE (x));
+ f;
+ f = TREE_CHAIN (f))
+ pushdecl_class_level (f);
}
- return x;
}
#if 0
@@ -3828,22 +4385,78 @@ push_class_level_binding (name, x)
tree name;
tree x;
{
+ tree binding;
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
return;
- if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
- && purpose_member (name, class_binding_level->class_shadowed))
- return;
+ /* Make sure that this new member does not have the same name
+ as a template parameter. */
+ if (TYPE_BEING_DEFINED (current_class_type))
+ check_template_shadow (x);
+
+ /* If this declaration shadows a declaration from an enclosing
+ class, then we will need to restore IDENTIFIER_CLASS_VALUE when
+ we leave this class. Record the shadowed declaration here. */
+ binding = IDENTIFIER_BINDING (name);
+ if (binding
+ && ((TREE_CODE (x) == OVERLOAD
+ && BINDING_VALUE (binding)
+ && is_overloaded_fn (BINDING_VALUE (binding)))
+ || INHERITED_VALUE_BINDING_P (binding)))
+ {
+ tree shadow;
+ tree old_decl;
+
+ /* If the old binding was from a base class, and was for a tag
+ name, slide it over to make room for the new binding. The
+ old binding is still visible if explicitly qualified with a
+ class-key. */
+ if (INHERITED_VALUE_BINDING_P (binding)
+ && BINDING_VALUE (binding)
+ && TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+ && DECL_ARTIFICIAL (BINDING_VALUE (binding))
+ && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+ {
+ old_decl = BINDING_TYPE (binding);
+ BINDING_TYPE (binding) = BINDING_VALUE (binding);
+ BINDING_VALUE (binding) = NULL_TREE;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ }
+ else
+ old_decl = BINDING_VALUE (binding);
+
+ /* There was already a binding for X containing fewer
+ functions than are named in X. Find the previous
+ declaration of X on the class-shadowed list, and update it. */
+ for (shadow = class_binding_level->class_shadowed;
+ shadow;
+ shadow = TREE_CHAIN (shadow))
+ if (TREE_PURPOSE (shadow) == name
+ && TREE_TYPE (shadow) == old_decl)
+ {
+ BINDING_VALUE (binding) = x;
+ INHERITED_VALUE_BINDING_P (binding) = 0;
+ TREE_TYPE (shadow) = x;
+ return;
+ }
+ }
- maybe_push_cache_obstack ();
- class_binding_level->class_shadowed
- = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
- class_binding_level->class_shadowed);
- pop_obstacks ();
- IDENTIFIER_CLASS_VALUE (name) = x;
- obstack_ptr_grow (&decl_obstack, x);
+ /* If we didn't replace an existing binding, put the binding on the
+ stack of bindings for the identifier, and update
+ IDENTIFIER_CLASS_VALUE. */
+ if (push_class_binding (name, x))
+ {
+ push_cache_obstack ();
+ class_binding_level->class_shadowed
+ = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+ class_binding_level->class_shadowed);
+ pop_obstacks ();
+ /* Record the value we are binding NAME to so that we can know
+ what to pop later. */
+ TREE_TYPE (class_binding_level->class_shadowed) = x;
+ }
}
/* Insert another USING_DECL into the current binding level,
@@ -3897,31 +4510,38 @@ push_using_directive (used)
return ud;
}
-/* DECL is a FUNCTION_DECL which may have other definitions already in
- place. We get around this by making the value of the identifier point
- to a list of all the things that want to be referenced by that name. It
- is then up to the users of that name to decide what to do with that
- list.
+/* DECL is a FUNCTION_DECL for a non-member function, which may have
+ other definitions already in place. We get around this by making
+ the value of the identifier point to a list of all the things that
+ want to be referenced by that name. It is then up to the users of
+ that name to decide what to do with that list.
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way.
+ FLAGS is a bitwise-or of the following values:
+ PUSH_LOCAL: Bind DECL in the current scope, rather than at
+ namespace scope.
+ PUSH_USING: DECL is being pushed as the result of a using
+ declaration.
+
The value returned may be a previous declaration if we guessed wrong
about what language DECL should belong to (C or C++). Otherwise,
it's always DECL (and never something that's not a _DECL). */
-static tree
-push_overloaded_decl (decl, forgettable)
+tree
+push_overloaded_decl (decl, flags)
tree decl;
- int forgettable;
+ int flags;
{
- tree orig_name = DECL_NAME (decl);
+ tree name = DECL_NAME (decl);
tree old;
- int doing_global = (namespace_bindings_p () || ! forgettable);
+ tree new_binding;
+ int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
if (doing_global)
{
- old = namespace_binding (orig_name, DECL_CONTEXT (decl));
+ old = namespace_binding (name, DECL_CONTEXT (decl));
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
@@ -3932,16 +4552,7 @@ push_overloaded_decl (decl, forgettable)
}
}
else
- {
- old = IDENTIFIER_LOCAL_VALUE (orig_name);
-
- if (! purpose_member (orig_name, current_binding_level->shadowed))
- {
- current_binding_level->shadowed
- = tree_cons (orig_name, old, current_binding_level->shadowed);
- old = NULL_TREE;
- }
- }
+ old = lookup_name_current_level (name);
if (old)
{
@@ -3959,9 +4570,19 @@ push_overloaded_decl (decl, forgettable)
tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
- if (decl == OVL_CURRENT (tmp)
- || duplicate_decls (decl, OVL_CURRENT (tmp)))
- return OVL_CURRENT (tmp);
+ {
+ tree fn = OVL_CURRENT (tmp);
+
+ if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
+ && !(flags & PUSH_USING)
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ TYPE_ARG_TYPES (TREE_TYPE (decl))))
+ cp_error ("`%#D' conflicts with previous using declaration `%#D'",
+ decl, fn);
+
+ if (duplicate_decls (decl, fn))
+ return fn;
+ }
}
else
{
@@ -3974,17 +4595,57 @@ push_overloaded_decl (decl, forgettable)
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
if (old && TREE_CODE (old) != OVERLOAD)
- old = ovl_cons (old, NULL_TREE);
- old = ovl_cons (decl, old);
+ new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
+ else
+ new_binding = ovl_cons (decl, old);
+ if (flags & PUSH_USING)
+ OVL_USED (new_binding) = 1;
}
else
- /* orig_name is not ambiguous. */
- old = decl;
+ /* NAME is not ambiguous. */
+ new_binding = decl;
if (doing_global)
- set_namespace_binding (orig_name, current_namespace, old);
+ set_namespace_binding (name, current_namespace, new_binding);
else
- IDENTIFIER_LOCAL_VALUE (orig_name) = old;
+ {
+ /* We only create an OVERLOAD if there was a previous binding at
+ this level, or if decl is a template. In the former case, we
+ need to remove the old binding and replace it with the new
+ binding. We must also run through the NAMES on the binding
+ level where the name was bound to update the chain. */
+
+ if (TREE_CODE (new_binding) == OVERLOAD && old)
+ {
+ tree *d;
+
+ for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+ *d;
+ d = &TREE_CHAIN (*d))
+ if (*d == old
+ || (TREE_CODE (*d) == TREE_LIST
+ && TREE_VALUE (*d) == old))
+ {
+ if (TREE_CODE (*d) == TREE_LIST)
+ /* Just replace the old binding with the new. */
+ TREE_VALUE (*d) = new_binding;
+ else
+ /* Build a TREE_LIST to wrap the OVERLOAD. */
+ *d = build_tree_list (NULL_TREE, new_binding);
+
+ /* And update the CPLUS_BINDING node. */
+ BINDING_VALUE (IDENTIFIER_BINDING (name))
+ = new_binding;
+ return decl;
+ }
+
+ /* We should always find a previous binding in this case. */
+ my_friendly_abort (0);
+ }
+
+ /* Install the new binding. */
+ push_local_binding (name, new_binding, flags);
+ }
return decl;
}
@@ -4040,7 +4701,7 @@ implicitly_declare (functionid)
Otherwise return an error message format string with a %s
where the identifier should go. */
-static char *
+static const char *
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
@@ -4049,7 +4710,7 @@ redeclaration_error_message (newdecl, olddecl)
/* Because C++ can put things into name space for free,
constructs like "typedef struct foo { ... } foo"
would look like an erroneous redeclaration. */
- if (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
+ if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return 0;
else
return "redefinition of `%#D'";
@@ -4279,20 +4940,42 @@ define_label (filename, line, name)
and they should be cleaned up
by the time we get to the label. */
&& ! DECL_ARTIFICIAL (new_decls)
- && ((DECL_INITIAL (new_decls) != NULL_TREE
- && DECL_INITIAL (new_decls) != error_mark_node)
- || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
+ && !(DECL_INITIAL (new_decls) == NULL_TREE
+ && pod_type_p (TREE_TYPE (new_decls))))
{
- if (! identified)
+ /* This is really only important if we're crossing
+ an initialization. The POD stuff is just
+ pedantry; why should it matter if the class
+ contains a field of pointer to member type? */
+ int problem = (DECL_INITIAL (new_decls)
+ || (TYPE_NEEDS_CONSTRUCTING
+ (TREE_TYPE (new_decls))));
+
+ if (! identified)
{
- cp_error ("jump to label `%D'", decl);
- error_with_file_and_line (uses->filename_o_goto,
- uses->lineno_o_goto,
- " from here");
+ if (problem)
+ {
+ cp_error ("jump to label `%D'", decl);
+ error_with_file_and_line
+ (uses->filename_o_goto,
+ uses->lineno_o_goto, " from here");
+ }
+ else
+ {
+ cp_pedwarn ("jump to label `%D'", decl);
+ pedwarn_with_file_and_line
+ (uses->filename_o_goto,
+ uses->lineno_o_goto, " from here");
+ }
identified = 1;
}
- cp_error_at (" crosses initialization of `%#D'",
- new_decls);
+
+ if (problem)
+ cp_error_at (" crosses initialization of `%#D'",
+ new_decls);
+ else
+ cp_pedwarn_at (" enters scope of non-POD `%#D'",
+ new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
@@ -4346,8 +5029,7 @@ pop_switch ()
/* XXX Note decl is never actually used. (bpk) */
void
-define_case_label (decl)
- tree decl;
+define_case_label ()
{
tree cleanup = last_cleanup_this_contour ();
struct binding_level *b = current_binding_level;
@@ -4429,7 +5111,7 @@ storedecls (decls)
/* Similarly, store the list of tags of the current level. */
-static void
+void
storetags (tags)
tree tags;
{
@@ -4455,6 +5137,9 @@ lookup_tag (form, name, binding_level, thislevel_only)
int thislevel_only;
{
register struct binding_level *level;
+ /* Non-zero if, we should look past a pseudo-global level, even if
+ THISLEVEL_ONLY. */
+ int allow_pseudo_global = 1;
for (level = binding_level; level; level = level->level_chain)
{
@@ -4469,10 +5154,21 @@ lookup_tag (form, name, binding_level, thislevel_only)
}
else if (level->namespace_p)
/* Do namespace lookup. */
- /* XXX: is this a real lookup, considering using-directives etc. ??? */
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
- tree old = BINDING_TYPE (binding_for_name (name, tail));
+ tree old = binding_for_name (name, tail);
+
+ /* If we just skipped past a pseudo global level, even
+ though THISLEVEL_ONLY, and we find a template class
+ declaration, then we use the _TYPE node for the
+ template. See the example below. */
+ if (thislevel_only && !allow_pseudo_global
+ && old && BINDING_VALUE (old)
+ && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
+ old = TREE_TYPE (BINDING_VALUE (old));
+ else
+ old = BINDING_TYPE (old);
+
/* If it has an original type, it is a typedef, and we
should not return it. */
if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
@@ -4509,16 +5205,24 @@ lookup_tag (form, name, binding_level, thislevel_only)
}
if (thislevel_only && ! level->tag_transparent)
{
- if (level->pseudo_global)
- {
- tree t = IDENTIFIER_CLASS_VALUE (name);
- if (t && DECL_CLASS_TEMPLATE_P (t))
- return TREE_TYPE (t);
- t = IDENTIFIER_NAMESPACE_VALUE (name);
- if (t && DECL_CLASS_TEMPLATE_P (t))
- return TREE_TYPE (t);
+ if (level->pseudo_global && allow_pseudo_global)
+ {
+ /* We must deal with cases like this:
+
+ template <class T> struct S;
+ template <class T> struct S {};
+
+ When looking up `S', for the second declaration, we
+ would like to find the first declaration. But, we
+ are in the pseudo-global level created for the
+ template parameters, rather than the (surrounding)
+ namespace level. Thus, we keep going one more level,
+ even though THISLEVEL_ONLY is non-zero. */
+ allow_pseudo_global = 0;
+ continue;
}
- return NULL_TREE;
+ else
+ return NULL_TREE;
}
if (current_class_type && level->level_chain->namespace_p)
{
@@ -4668,6 +5372,20 @@ lookup_namespace_name (namespace, name)
tree val;
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
+
+ if (TREE_CODE (name) == NAMESPACE_DECL)
+ /* This happens for A::B<int> when B is a namespace. */
+ return name;
+ else if (TREE_CODE (name) == TEMPLATE_DECL)
+ {
+ /* This happens for A::B where B is a template, and there are no
+ template arguments. */
+ cp_error ("invalid use of `%D'", name);
+ return error_mark_node;
+ }
+
+ namespace = ORIGINAL_NAMESPACE (namespace);
+
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
val = binding_init (&_b);
@@ -4688,15 +5406,130 @@ lookup_namespace_name (namespace, name)
return error_mark_node;
}
+/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
+
+static unsigned long
+typename_hash (k)
+ hash_table_key k;
+{
+ unsigned long hash;
+ tree t;
+
+ t = (tree) k;
+ hash = (((unsigned long) TYPE_CONTEXT (t))
+ ^ ((unsigned long) DECL_NAME (TYPE_NAME (t))));
+
+ return hash;
+}
+
+/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
+
+static boolean
+typename_compare (k1, k2)
+ hash_table_key k1;
+ hash_table_key k2;
+{
+ tree t1;
+ tree t2;
+ tree d1;
+ tree d2;
+
+ t1 = (tree) k1;
+ t2 = (tree) k2;
+ d1 = TYPE_NAME (t1);
+ d2 = TYPE_NAME (t2);
+
+ return (DECL_NAME (d1) == DECL_NAME (d2)
+ && same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2))
+ && ((TREE_TYPE (t1) != NULL_TREE)
+ == (TREE_TYPE (t2) != NULL_TREE))
+ && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+ && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+}
+
+/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
+ the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
+ is non-NULL, this type is being created by the implicit typename
+ extension, and BASE_TYPE is a type named `t' in some base class of
+ `T' which depends on template parameters.
+
+ Returns the new TYPENAME_TYPE. */
+
+tree
+build_typename_type (context, name, fullname, base_type)
+ tree context;
+ tree name;
+ tree fullname;
+ tree base_type;
+{
+ tree t;
+ tree d;
+ struct hash_entry* e;
+
+ static struct hash_table ht;
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ if (!ht.table
+ && !hash_table_init (&ht, &hash_newfunc, &typename_hash,
+ &typename_compare))
+ fatal ("virtual memory exhausted");
+
+ /* The FULLNAME needs to exist for the life of the hash table, i.e.,
+ for the entire compilation. */
+ if (!TREE_PERMANENT (fullname))
+ fullname = copy_to_permanent (fullname);
+
+ /* Build the TYPENAME_TYPE. */
+ t = make_lang_type (TYPENAME_TYPE);
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ TYPENAME_TYPE_FULLNAME (t) = fullname;
+ TREE_TYPE (t) = base_type;
+
+ /* Build the corresponding TYPE_DECL. */
+ d = build_decl (TYPE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+
+ /* See if we already have this type. */
+ e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
+ if (e)
+ {
+ /* This will free not only TREE_TYPE, but the lang-specific data
+ and the TYPE_DECL as well. */
+ obstack_free (&permanent_obstack, t);
+ t = (tree) e->key;
+ }
+ else
+ /* Insert the type into the table. */
+ hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
+
+ pop_obstacks ();
+
+ return t;
+}
+
tree
make_typename_type (context, name)
tree context, name;
{
- tree t, d;
+ tree t;
tree fullname;
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
- name = TYPE_IDENTIFIER (name);
+ {
+ if (!(TYPE_LANG_SPECIFIC (name)
+ && (CLASSTYPE_IS_TEMPLATE (name)
+ || CLASSTYPE_USE_TEMPLATE (name))))
+ name = TYPE_IDENTIFIER (name);
+ else
+ /* Create a TEMPLATE_ID_EXPR for the type. */
+ name = build_nt (TEMPLATE_ID_EXPR,
+ CLASSTYPE_TI_TEMPLATE (name),
+ CLASSTYPE_TI_ARGS (name));
+ }
else if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
@@ -4711,59 +5544,60 @@ make_typename_type (context, name)
if (TREE_CODE (name) != IDENTIFIER_NODE)
my_friendly_abort (2000);
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ {
+ /* We can get here from typename_sub0 in the explicit_template_type
+ expansion. Just fail. */
+ cp_error ("no class template named `%#T' in `%#T'",
+ name, context);
+ return error_mark_node;
+ }
+
if (! uses_template_parms (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
+ tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
- t = lookup_field (context, name, 0, 0);
- else
- t = NULL_TREE;
-
- if (t == NULL_TREE || TREE_CODE (t) != TEMPLATE_DECL
- || TREE_CODE (DECL_RESULT (t)) != TYPE_DECL)
+ tmpl = lookup_field (context, name, 0, 0);
+ if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
cp_error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
- return lookup_template_class (t, TREE_OPERAND (fullname, 1),
- NULL_TREE, context);
+ return lookup_template_class (tmpl,
+ TREE_OPERAND (fullname, 1),
+ NULL_TREE, context,
+ /*entering_scope=*/0);
}
else
{
if (IS_AGGR_TYPE (context))
t = lookup_field (context, name, 0, 1);
else
- t = NULL_TREE;
-
- if (t == NULL_TREE)
{
cp_error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
- return TREE_TYPE (t);
+ if (t)
+ return TREE_TYPE (t);
}
}
- if (processing_template_decl)
- push_obstacks (&permanent_obstack, &permanent_obstack);
- t = make_lang_type (TYPENAME_TYPE);
- TYPENAME_TYPE_FULLNAME (t) = fullname;
- d = build_decl (TYPE_DECL, name, t);
- if (processing_template_decl)
- pop_obstacks ();
-
- TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- TYPE_NAME (TREE_TYPE (d)) = d;
- TYPE_STUB_DECL (TREE_TYPE (d)) = d;
- DECL_CONTEXT (d) = FROB_CONTEXT (context);
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
-
- return t;
+ /* If the CONTEXT is not a template type, then either the field is
+ there now or its never going to be. */
+ if (!uses_template_parms (context) && !t)
+ {
+ cp_error ("no type named `%#T' in `%#T'", name, context);
+ return error_mark_node;
+ }
+
+
+ return build_typename_type (context, name, fullname, NULL_TREE);
}
/* Select the right _DECL from multiple choices. */
@@ -4791,7 +5625,8 @@ select_decl (binding, flags)
val = TYPE_STUB_DECL (BINDING_TYPE (binding));
/* Don't return non-types if we really prefer types. */
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
- && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
+ && (TREE_CODE (val) != TEMPLATE_DECL
+ || !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
return val;
@@ -4828,7 +5663,7 @@ unqualified_namespace_lookup (name, flags)
if (!lookup_using_namespace (name, b, level->using_directives,
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
/* Add all _DECLs seen through global using-directives. */
/* XXX local and global using lists should work equally. */
@@ -4838,7 +5673,7 @@ unqualified_namespace_lookup (name, flags)
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
scope, flags))
/* Give up because of error. */
- return NULL_TREE;
+ return error_mark_node;
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
@@ -4888,6 +5723,32 @@ qualify_lookup (val, flags)
return val;
}
+/* Any other BINDING overrides an implicit TYPENAME. Warn about
+ that. */
+
+static void
+warn_about_implicit_typename_lookup (typename, binding)
+ tree typename;
+ tree binding;
+{
+ tree subtype = TREE_TYPE (TREE_TYPE (typename));
+ tree name = DECL_NAME (typename);
+
+ if (! (TREE_CODE (binding) == TEMPLATE_DECL
+ && CLASSTYPE_TEMPLATE_INFO (subtype)
+ && CLASSTYPE_TI_TEMPLATE (subtype) == binding)
+ && ! (TREE_CODE (binding) == TYPE_DECL
+ && same_type_p (TREE_TYPE (binding), subtype)))
+ {
+ cp_warning ("lookup of `%D' finds `%#D'",
+ name, binding);
+ cp_warning (" instead of `%D' from dependent base class",
+ typename);
+ cp_warning (" (use `typename %T::%D' if that's what you meant)",
+ constructor_name (current_class_type), name);
+ }
+}
+
/* Look up NAME in the current binding level and its superiors in the
namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one
@@ -4907,11 +5768,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree name;
int prefer_type, nonclass, namespaces_only;
{
- register tree val;
+ tree t;
+ tree val = NULL_TREE;
int yylex = 0;
tree from_obj = NULL_TREE;
- tree locval, classval;
int flags;
+ int val_is_implicit_typename = 0;
/* Hack: copy flag set by parser, if set. */
if (only_namespace_names)
@@ -4926,8 +5788,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
prefer_type = looking_for_typename;
flags = lookup_flags (prefer_type, namespaces_only);
- /* During parsing, we need to complain. */
- flags |= LOOKUP_COMPLAIN;
/* If the next thing is '<', class templates are types. */
if (looking_for_template)
flags |= LOOKUP_TEMPLATES_EXPECTED;
@@ -4957,6 +5817,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
{
struct tree_binding b;
val = binding_init (&b);
+ flags |= LOOKUP_COMPLAIN;
if (!qualified_lookup_using_namespace (name, type, val, flags))
return NULL_TREE;
val = select_decl (val, flags);
@@ -4967,26 +5828,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
|| TREE_CODE (type) == TYPENAME_TYPE)
/* Someone else will give an error about this if needed. */
val = NULL_TREE;
- else if (TYPE_BEING_DEFINED (type))
- {
- val = IDENTIFIER_CLASS_VALUE (name);
- if (val && DECL_CONTEXT (val) != type)
- {
- struct binding_level *b = class_binding_level;
- for (val = NULL_TREE; b; b = b->level_chain)
- {
- tree t = purpose_member (name, b->class_shadowed);
- if (t && TREE_VALUE (t)
- && DECL_CONTEXT (TREE_VALUE (t)) == type)
- {
- val = TREE_VALUE (t);
- break;
- }
- }
- }
- if (val == NULL_TREE)
- val = lookup_field (type, name, 0, 1);
- }
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
@@ -5001,73 +5842,56 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
from_obj = val;
}
else
- flags = lookup_flags (prefer_type, namespaces_only);
-
- locval = classval = NULL_TREE;
-
- if (! namespace_bindings_p ())
- locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
-
- /* In C++ class fields are between local and global scope,
- just before the global scope. */
- if (current_class_type && ! nonclass)
{
- classval = IDENTIFIER_CLASS_VALUE (name);
- if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
- /* Try to find values from base classes if we are presently
- defining a type. We are presently only interested in
- TYPE_DECLs. */
- classval = lookup_field (current_class_type, name, 0, 1);
-
- /* Add implicit 'typename' to types from template bases. lookup_field
- will do this for us. If classval is actually from an enclosing
- scope, lookup_nested_field will get it for us. */
- if (processing_template_decl
- && classval && TREE_CODE (classval) == TYPE_DECL
- && ! currently_open_class (DECL_CONTEXT (classval))
- && uses_template_parms (current_class_type)
- && ! DECL_ARTIFICIAL (classval))
- classval = lookup_field (current_class_type, name, 0, 1);
+ flags = lookup_flags (prefer_type, namespaces_only);
+ /* If we're not parsing, we need to complain. */
+ flags |= LOOKUP_COMPLAIN;
+ }
- /* yylex() calls this with -2, since we should never start digging for
- the nested name at the point where we haven't even, for example,
- created the COMPONENT_REF or anything like that. */
- if (classval == NULL_TREE)
- classval = lookup_nested_field (name, ! yylex);
+ /* First, look in non-namespace scopes. */
+ for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
+ {
+ tree binding;
- classval = qualify_lookup (classval, flags);
+ if (!LOCAL_BINDING_P (t) && nonclass)
+ /* We're not looking for class-scoped bindings, so keep going. */
+ continue;
+
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (qualify_lookup (BINDING_VALUE (t), flags))
+ binding = BINDING_VALUE (t);
+ else if ((flags & LOOKUP_PREFER_TYPES)
+ && qualify_lookup (BINDING_TYPE (t), flags))
+ binding = BINDING_TYPE (t);
+ else
+ binding = NULL_TREE;
+
+ if (binding
+ && (!val || !(TREE_CODE (binding) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (binding)))))
+ {
+ if (val_is_implicit_typename && !yylex)
+ warn_about_implicit_typename_lookup (val, binding);
+ val = binding;
+ val_is_implicit_typename
+ = (TREE_CODE (val) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (val)));
+ if (!val_is_implicit_typename)
+ break;
+ }
}
- if (locval && classval)
+ /* Now lookup in namespace scopes. */
+ if (!val || val_is_implicit_typename)
{
- if (current_scope () == current_function_decl
- && ! hack_decl_function_context (current_function_decl))
- /* Not in a nested function. */
- val = locval;
- else
+ t = unqualified_namespace_lookup (name, flags);
+ if (t)
{
- /* This is incredibly horrible. The whole concept of
- IDENTIFIER_LOCAL_VALUE / IDENTIFIER_CLASS_VALUE /
- IDENTIFIER_GLOBAL_VALUE needs to be scrapped for local
- classes. */
- tree lctx = hack_decl_function_context (locval);
- tree cctx = hack_decl_function_context (classval);
-
- if (lctx == current_scope ())
- val = locval;
- else if (lctx == cctx)
- val = classval;
- else
- /* I don't know which is right; let's just guess for now. */
- val = locval;
+ if (val_is_implicit_typename && !yylex)
+ warn_about_implicit_typename_lookup (val, t);
+ val = t;
}
}
- else if (locval)
- val = locval;
- else if (classval)
- val = classval;
- else
- val = unqualified_namespace_lookup (name, flags);
done:
if (val)
@@ -5092,17 +5916,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
val = from_obj;
}
- if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
- || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
- ;
- /* Caller wants a class-or-namespace-name. */
- else if (prefer_type == 1 && TREE_CODE (val) == NAMESPACE_DECL)
- ;
- else if (IDENTIFIER_HAS_TYPE_VALUE (name))
- val = TYPE_MAIN_DECL (IDENTIFIER_TYPE_VALUE (name));
- else if (TREE_TYPE (val) == error_mark_node)
- val = error_mark_node;
-
/* If we have a single function from a using decl, pull it out. */
if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
val = OVL_FUNCTION (val);
@@ -5144,15 +5957,21 @@ lookup_name (name, prefer_type)
return lookup_name_real (name, prefer_type, 0, 0);
}
-/* Similar to `lookup_name' but look only at current binding level. */
+/* Similar to `lookup_name' but look only in the innermost non-class
+ binding level. */
tree
lookup_name_current_level (name)
tree name;
{
- register tree t = NULL_TREE;
+ struct binding_level *b;
+ tree t = NULL_TREE;
+
+ b = current_binding_level;
+ while (b->parm_flag == 2)
+ b = b->level_chain;
- if (current_binding_level->namespace_p)
+ if (b->namespace_p)
{
t = IDENTIFIER_NAMESPACE_VALUE (name);
@@ -5160,13 +5979,14 @@ lookup_name_current_level (name)
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
t = TREE_VALUE (t);
}
- else if (IDENTIFIER_LOCAL_VALUE (name) != NULL_TREE)
+ else if (IDENTIFIER_BINDING (name)
+ && LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
{
- struct binding_level *b = current_binding_level;
while (1)
{
- if (purpose_member (name, b->shadowed))
- return IDENTIFIER_LOCAL_VALUE (name);
+ if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
+ return IDENTIFIER_VALUE (name);
+
if (b->keep == 2)
b = b->level_chain;
else
@@ -5260,7 +6080,7 @@ static int builtin_type_tdescs_len, builtin_type_tdescs_max;
static void
record_builtin_type (rid_index, name, type)
enum rid rid_index;
- char *name;
+ const char *name;
tree type;
{
tree rname = NULL_TREE, tname = NULL_TREE;
@@ -5303,7 +6123,7 @@ record_builtin_type (rid_index, name, type)
static tree
record_builtin_java_type (name, size)
- char *name;
+ const char *name;
int size;
{
tree type, decl;
@@ -5322,7 +6142,12 @@ record_builtin_java_type (name, size)
}
record_builtin_type (RID_MAX, name, type);
decl = TYPE_NAME (type);
+
+ /* Suppress generate debug symbol entries for these types,
+ since for normal C++ they are just clutter.
+ However, push_lang_context undoes this if extern "Java" is seen. */
DECL_IGNORED_P (decl) = 1;
+
TYPE_FOR_JAVA (type) = 1;
return type;
}
@@ -5332,7 +6157,7 @@ record_builtin_java_type (name, size)
static void
record_unknown_type (type, name)
tree type;
- char *name;
+ const char *name;
{
tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
/* Make sure the "unknown type" typedecl gets ignored for debug info. */
@@ -5350,7 +6175,7 @@ static void
push_overloaded_decl_1 (x)
tree x;
{
- push_overloaded_decl (x, 0);
+ push_overloaded_decl (x, PUSH_GLOBAL);
}
#ifdef __GNUC__
@@ -5382,13 +6207,12 @@ init_decl_processing ()
int wchar_type_size;
tree temp;
tree array_domain_type;
- extern int flag_strict_prototype;
tree vb_off_identifier = NULL_TREE;
/* Function type `char *(char *, char *)' and similar ones */
tree string_ftype_ptr_ptr, int_ftype_string_string;
tree sizetype_endlink;
tree ptr_ftype, ptr_ftype_unsigned, ptr_ftype_sizetype;
- tree void_ftype, void_ftype_int, void_ftype_ptr, ptr_ftype_void;
+ tree void_ftype, void_ftype_int, void_ftype_ptr;
/* Have to make these distinct before we try using them. */
lang_name_cplusplus = get_identifier ("C++");
@@ -5404,12 +6228,11 @@ init_decl_processing ()
current_lang_name = NULL_TREE;
if (flag_strict_prototype == 2)
- {
- if (pedantic)
- strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
- }
- else
- strict_prototypes_lang_c = flag_strict_prototype;
+ flag_strict_prototype = pedantic;
+ if (! flag_permissive && ! pedantic)
+ flag_pedantic_errors = 1;
+
+ strict_prototypes_lang_c = flag_strict_prototype;
/* Initially, C. */
current_lang_name = lang_name_c;
@@ -5420,7 +6243,6 @@ init_decl_processing ()
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
-#ifndef __CYGWIN32__
/* Because most segmentation signals can be traced back into user
code, catch them and at least give the user a chance of working
around compiler bugs. */
@@ -5442,13 +6264,6 @@ init_decl_processing ()
#ifdef SIGBUS
signal (SIGBUS, signal_catch);
#endif
-#else /* ndef __CYGWIN32__ */
- /* Cygwin32 cannot handle catching signals other than
- SIGABRT yet. We hope this will cease to be the case soon. */
-#ifdef SIGABRT
- signal (SIGABRT, signal_catch);
-#endif
-#endif /* ndef __CYGWIN32__ */
gcc_obstack_init (&decl_obstack);
@@ -5496,6 +6311,9 @@ init_decl_processing ()
: make_unsigned_type (CHAR_TYPE_SIZE));
record_builtin_type (RID_CHAR, "char", char_type_node);
+ /* `signed' is the same as `int' */
+ record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node);
+
long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
record_builtin_type (RID_LONG, "long int", long_integer_type_node);
@@ -5545,8 +6363,10 @@ init_decl_processing ()
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
+#endif
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
@@ -5555,8 +6375,10 @@ init_decl_processing ()
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
+#endif
float_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -5652,7 +6474,8 @@ init_decl_processing ()
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
- = build_pointer_type (build_type_variant (char_type_node, 1, 0));
+ = build_pointer_type (build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
#endif
@@ -5682,7 +6505,8 @@ init_decl_processing ()
ptr_type_node = build_pointer_type (void_type_node);
const_ptr_type_node
- = build_pointer_type (build_type_variant (void_type_node, 1, 0));
+ = build_pointer_type (build_qualified_type (void_type_node,
+ TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
#endif
@@ -5779,10 +6603,6 @@ init_decl_processing ()
builtin_function ("__builtin_frame_address", ptr_ftype_unsigned,
BUILT_IN_FRAME_ADDRESS, NULL_PTR);
- ptr_ftype_void = build_function_type (ptr_type_node, endlink);
- builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
- builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
-
builtin_function ("__builtin_alloca", ptr_ftype_sizetype,
BUILT_IN_ALLOCA, "alloca");
builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
@@ -5951,10 +6771,7 @@ init_decl_processing ()
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TREE_TYPE (unknown_type_node) = unknown_type_node;
- if (flag_ansi)
- TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
- else
- TREE_TYPE (null_node) = build_pointer_type (unknown_type_node);
+ TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
/* Looking up TYPE_POINTER_TO and TYPE_REFERENCE_TO yield the same
result. */
@@ -6018,15 +6835,19 @@ init_decl_processing ()
DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
TREE_UNSIGNED (fields[3]) = 0;
TREE_CHAIN (fields[2]) = fields[3];
- vtable_entry_type = build_type_variant (vtable_entry_type, 1, 0);
+ vtable_entry_type = build_qualified_type (vtable_entry_type,
+ TYPE_QUAL_CONST);
}
record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
vtbl_type_node
- = build_array_type (vtable_entry_type, NULL_TREE);
+ = build_cplus_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
- vtbl_type_node = cp_build_type_variant (vtbl_type_node, 1, 0);
+ vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
+ vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
+ layout_type (vtbl_ptr_type_node);
+ record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node);
/* Simplify life by making a "sigtable_entry_type". Give its
fields names so that the debugger can use them. */
@@ -6061,7 +6882,8 @@ init_decl_processing ()
TREE_UNSIGNED (fields[5]) = 0;
TREE_CHAIN (fields[4]) = fields[5];
- sigtable_entry_type = build_type_variant (sigtable_entry_type, 1, 0);
+ sigtable_entry_type = build_qualified_type (sigtable_entry_type,
+ TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
@@ -6081,7 +6903,7 @@ init_decl_processing ()
if (flag_honor_std)
push_namespace (get_identifier ("std"));
bad_alloc_type_node = xref_tag
- (class_type_node, get_identifier ("bad_alloc"), NULL_TREE, 1);
+ (class_type_node, get_identifier ("bad_alloc"), 1);
if (flag_honor_std)
pop_namespace ();
newtype = build_exception_variant
@@ -6090,7 +6912,8 @@ init_decl_processing ()
(void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
- auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
+ global_delete_fndecl
+ = auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN);
}
@@ -6126,6 +6949,12 @@ init_decl_processing ()
print_error_function = lang_print_error_function;
lang_get_alias_set = &c_get_alias_set;
+ valid_lang_attribute = cp_valid_lang_attribute;
+
+ /* Maintain consistency. Perhaps we should just complain if they
+ say -fwritable-strings? */
+ if (flag_writable_strings)
+ flag_const_strings = 0;
}
/* Function to print any language-specific context for an error message. */
@@ -6148,11 +6977,11 @@ lang_print_error_function (file)
tree
define_function (name, type, function_code, pfn, library_name)
- char *name;
+ const char *name;
tree type;
enum built_in_function function_code;
void (*pfn) PROTO((tree));
- char *library_name;
+ const char *library_name;
{
tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
@@ -6177,52 +7006,80 @@ define_function (name, type, function_code, pfn, library_name)
return decl;
}
-/* Called when a declaration is seen that contains no names to declare.
- If its type is a reference to a structure, union or enum inherited
- from a containing scope, shadow that tag name for the current scope
- with a forward reference.
- If its type defines a new named structure or union
- or defines an enum, it is valid but we need not do anything here.
- Otherwise, it is an error.
+/* When we call finish_struct for an anonymous union, we create
+ default copy constructors and such. But, an anonymous union
+ shouldn't have such things; this function undoes the damage to the
+ anonymous union type T.
- C++: may have to grok the declspecs to learn about static,
- complain for anonymous unions. */
+ (The reason that we create the synthesized methods is that we don't
+ distinguish `union { int i; }' from `typedef union { int i; } U'.
+ The first is an anonymous union; the second is just an ordinary
+ union type.) */
void
-shadow_tag (declspecs)
+fixup_anonymous_union (t)
+ tree t;
+{
+ tree *q;
+
+ /* Wipe out memory of synthesized methods */
+ TYPE_HAS_CONSTRUCTOR (t) = 0;
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
+ TYPE_HAS_INIT_REF (t) = 0;
+ TYPE_HAS_CONST_INIT_REF (t) = 0;
+ TYPE_HAS_ASSIGN_REF (t) = 0;
+ TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
+
+ /* Splice the implicitly generated functions out of the TYPE_METHODS
+ list. */
+ q = &TYPE_METHODS (t);
+ while (*q)
+ {
+ if (DECL_ARTIFICIAL (*q))
+ *q = TREE_CHAIN (*q);
+ else
+ q = &TREE_CHAIN (*q);
+ }
+
+ /* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
+ function members. */
+ if (TYPE_METHODS (t))
+ error ("an anonymous union cannot have function members");
+}
+
+/* Make sure that a declaration with no declarator is well-formed, i.e.
+ just defines a tagged type or anonymous union.
+
+ Returns the type defined, if any. */
+
+tree
+check_tag_decl (declspecs)
tree declspecs;
{
- int found_tag = 0;
+ int found_type = 0;
tree ob_modifier = NULL_TREE;
register tree link;
- register enum tree_code code, ok_code = ERROR_MARK;
register tree t = NULL_TREE;
for (link = declspecs; link; link = TREE_CHAIN (link))
{
register tree value = TREE_VALUE (link);
- code = TREE_CODE (value);
- if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
+ if (TYPE_P (value))
{
- my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+ ++found_type;
- if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value))
+ if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
{
- if (CLASSTYPE_IMPLICIT_INSTANTIATION (value)
- && TYPE_SIZE (value) == NULL_TREE)
- {
- SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
- if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL (value));
- }
- else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value))
- cp_error ("specialization after instantiation of `%T'", value);
+ my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+ t = value;
}
-
- t = value;
- ok_code = code;
- found_tag++;
+ }
+ else if (value == ridpointers[(int) RID_FRIEND])
+ {
+ if (current_class_type == NULL_TREE
+ || current_scope () != current_class_type)
+ ob_modifier = value;
}
else if (value == ridpointers[(int) RID_STATIC]
|| value == ridpointers[(int) RID_EXTERN]
@@ -6230,47 +7087,77 @@ shadow_tag (declspecs)
|| value == ridpointers[(int) RID_REGISTER]
|| value == ridpointers[(int) RID_INLINE]
|| value == ridpointers[(int) RID_VIRTUAL]
+ || value == ridpointers[(int) RID_CONST]
+ || value == ridpointers[(int) RID_VOLATILE]
|| value == ridpointers[(int) RID_EXPLICIT])
ob_modifier = value;
}
+ if (found_type > 1)
+ error ("multiple types in one declaration");
+
+ /* Inside a class, we might be in a friend or access declaration.
+ Until we have a good way of detecting the latter, don't warn. */
+ if (t == NULL_TREE && ! current_class_type)
+ pedwarn ("declaration does not declare anything");
+
+ /* Check for an anonymous union. We're careful
+ accessing TYPE_IDENTIFIER because some built-in types, like
+ pointer-to-member types, do not have TYPE_NAME. */
+ else if (t && TREE_CODE (t) == UNION_TYPE
+ && TYPE_NAME (t)
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ {
+ /* Anonymous unions are objects, so they can have specifiers. */;
+ SET_ANON_UNION_TYPE_P (t);
+ }
+
+ else if (ob_modifier)
+ {
+ if (ob_modifier == ridpointers[(int) RID_INLINE]
+ || ob_modifier == ridpointers[(int) RID_VIRTUAL])
+ cp_error ("`%D' can only be specified for functions", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_FRIEND])
+ cp_error ("`%D' can only be specified inside a class", ob_modifier);
+ else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
+ cp_error ("`%D' can only be specified for constructors",
+ ob_modifier);
+ else
+ cp_error ("`%D' can only be specified for objects and functions",
+ ob_modifier);
+ }
+
+ return t;
+}
+
+/* Called when a declaration is seen that contains no names to declare.
+ If its type is a reference to a structure, union or enum inherited
+ from a containing scope, shadow that tag name for the current scope
+ with a forward reference.
+ If its type defines a new named structure or union
+ or defines an enum, it is valid but we need not do anything here.
+ Otherwise, it is an error.
+
+ C++: may have to grok the declspecs to learn about static,
+ complain for anonymous unions. */
+
+void
+shadow_tag (declspecs)
+ tree declspecs;
+{
+ tree t = check_tag_decl (declspecs);
+
+ if (t)
+ maybe_process_partial_specialization (t);
+
/* This is where the variables in an anonymous union are
declared. An anonymous union declaration looks like:
union { ... } ;
because there is no declarator after the union, the parser
sends that declaration here. */
- if (ok_code == UNION_TYPE
- && t != NULL_TREE
- && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (TYPE_NAME (t)))
- || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
- {
- /* See also grok_x_components. */
- tree *q;
-
- /* Wipe out memory of synthesized methods */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
- TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
- TYPE_HAS_INIT_REF (t) = 0;
- TYPE_HAS_CONST_INIT_REF (t) = 0;
- TYPE_HAS_ASSIGN_REF (t) = 0;
- TYPE_HAS_ASSIGNMENT (t) = 0;
- TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
-
- q = &TYPE_METHODS (t);
- while (*q)
- {
- if (DECL_ARTIFICIAL (*q))
- *q = TREE_CHAIN (*q);
- else
- q = &TREE_CHAIN (*q);
- }
-
- /* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have
- function members. */
- if (TYPE_METHODS (t))
- error ("an anonymous union cannot have function members");
+ if (t && ANON_UNION_TYPE_P (t))
+ {
+ fixup_anonymous_union (t);
if (TYPE_FIELDS (t))
{
@@ -6279,29 +7166,6 @@ shadow_tag (declspecs)
finish_anon_union (decl);
}
}
- else
- {
- /* Anonymous unions are objects, that's why we only check for
- inappropriate specifiers in this branch. */
-
- if (ob_modifier)
- {
- if (ob_modifier == ridpointers[(int) RID_INLINE]
- || ob_modifier == ridpointers[(int) RID_VIRTUAL])
- cp_error ("`%D' can only be specified for functions", ob_modifier);
- else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
- cp_error ("`%D' can only be specified for constructors",
- ob_modifier);
- else
- cp_error ("`%D' can only be specified for objects and functions",
- ob_modifier);
- }
-
- if (found_tag == 0)
- cp_error ("abstract declarator used as declaration");
- else if (found_tag > 1)
- pedwarn ("multiple types in one declaration");
- }
}
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
@@ -6347,6 +7211,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree context;
extern int have_extern_spec;
extern int used_extern_spec;
+ tree attrlist;
#if 0
/* See code below that used this. */
@@ -6361,13 +7226,22 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
used_extern_spec = 1;
}
+ if (attributes || prefix_attributes)
+ attrlist = build_scratch_list (attributes, prefix_attributes);
+ else
+ attrlist = NULL_TREE;
+
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
- NULL_TREE);
+ attrlist);
+
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
type = TREE_TYPE (decl);
+ if (type == error_mark_node)
+ return NULL_TREE;
+
/* Don't lose if destructors must be executed at file-level. */
if (! processing_template_decl && TREE_STATIC (decl)
&& TYPE_NEEDS_DESTRUCTOR (complete_type (type))
@@ -6468,8 +7342,17 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
DECL_INITIAL (decl) = error_mark_node;
}
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
+#endif
+
+ /* Set attributes here so if duplicate decl, will have proper attributes. */
+ cplus_decl_attributes (decl, attributes, prefix_attributes);
+
if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
{
+ push_nested_class (context, 2);
+
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
@@ -6506,18 +7389,23 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
DECL_IN_AGGR_P (decl) = 0;
if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
|| CLASSTYPE_USE_TEMPLATE (context))
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ {
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ /* [temp.expl.spec] An explicit specialization of a static data
+ member of a template is a definition if the declaration
+ includes an initializer; otherwise, it is a declaration.
+
+ We check for processing_specialization so this only applies
+ to the new specialization syntax. */
+ if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization)
+ DECL_EXTERNAL (decl) = 1;
+ }
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
cp_pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
-
- pushclass (context, 2);
}
- /* Set attributes here so if duplicate decl, will have proper attributes. */
- cplus_decl_attributes (decl, attributes, prefix_attributes);
-
/* Add this decl to the current binding level, but not if it
comes from another scope, e.g. a static member variable.
TEM may equal DECL or it may be a previous decl of the same name. */
@@ -6557,7 +7445,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
data segment. */
DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
#endif
-
+
if (! processing_template_decl)
start_decl_1 (tem);
@@ -6600,6 +7488,9 @@ start_decl_1 (decl)
tree type = TREE_TYPE (decl);
int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+ if (type == error_mark_node)
+ return;
+
/* If this type of object needs a cleanup, and control may
jump past it, make a new binding level so that it is cleaned
up only when it is initialized first. */
@@ -6614,9 +7505,7 @@ start_decl_1 (decl)
{
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (type == error_mark_node)
- ; /* Don't complain again. */
- else if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+ if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
@@ -6716,10 +7605,6 @@ grok_reference_init (decl, type, init)
return;
}
- if (TREE_TYPE (init) && TREE_CODE (TREE_TYPE (init)) == UNKNOWN_TYPE)
- /* decay_conversion is probably wrong for references to functions. */
- init = decay_conversion (instantiate_type (TREE_TYPE (type), init, 1));
-
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
@@ -6800,6 +7685,25 @@ obscure_complex_init (decl, init)
return init;
}
+/* Issue an error message if DECL is an uninitialized const variable. */
+
+static void
+check_for_uninitialized_const_var (decl)
+ tree decl;
+{
+ tree type = TREE_TYPE (decl);
+
+ /* ``Unless explicitly declared extern, a const object does not have
+ external linkage and must be initialized. ($8.4; $12.1)'' ARM
+ 7.1.6 */
+ if (TREE_CODE (decl) == VAR_DECL
+ && TREE_CODE (type) != REFERENCE_TYPE
+ && CP_TYPE_CONST_P (type)
+ && !TYPE_NEEDS_CONSTRUCTING (type)
+ && !DECL_INITIAL (decl))
+ cp_error ("uninitialized const `%D'", decl);
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@@ -6836,6 +7740,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
char *asmspec = NULL;
int was_readonly = 0;
int already_used = 0;
+ tree core_type;
/* If this is 0, then we did not change obstacks. */
if (! decl)
@@ -6856,6 +7761,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
init = NULL_TREE;
}
+ if (current_class_type
+ && DECL_REAL_CONTEXT (decl) == current_class_type
+ && TYPE_BEING_DEFINED (current_class_type)
+ && (DECL_INITIAL (decl) || init))
+ DECL_DEFINED_IN_CLASS_P (decl) = 1;
+
if (TREE_CODE (decl) == VAR_DECL
&& DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
@@ -6882,6 +7793,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
return;
}
+ if (TYPE_HAS_MUTABLE_P (type))
+ TREE_READONLY (decl) = 0;
+
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
@@ -6982,6 +7896,10 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
GNU_xref_decl (current_function_decl, decl);
+ core_type = type;
+ while (TREE_CODE (core_type) == ARRAY_TYPE)
+ core_type = TREE_TYPE (core_type);
+
if (TREE_CODE (decl) == FIELD_DECL)
;
else if (TREE_CODE (decl) == CONST_DECL)
@@ -7000,7 +7918,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0);
- else if (TREE_CODE (init) == CONSTRUCTOR)
+ else if (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
@@ -7029,44 +7948,25 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
&& (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
{
- tree ctype = type;
- while (TREE_CODE (ctype) == ARRAY_TYPE)
- ctype = TREE_TYPE (ctype);
- if (! TYPE_NEEDS_CONSTRUCTING (ctype))
+ if (! TYPE_NEEDS_CONSTRUCTING (core_type))
{
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype))
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized reference members",
decl);
}
- if (TREE_CODE (decl) == VAR_DECL
- && !DECL_INITIAL (decl)
- && !TYPE_NEEDS_CONSTRUCTING (type)
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- cp_error ("uninitialized const `%D'", decl);
+ check_for_uninitialized_const_var (decl);
if (TYPE_SIZE (type) != NULL_TREE
&& TYPE_NEEDS_CONSTRUCTING (type))
init = obscure_complex_init (decl, NULL_TREE);
- }
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_CODE (type) != REFERENCE_TYPE
- && (TYPE_READONLY (type) || TREE_READONLY (decl)))
- {
- /* ``Unless explicitly declared extern, a const object does not have
- external linkage and must be initialized. ($8.4; $12.1)'' ARM 7.1.6
- However, if it's `const int foo = 1; const int foo;', don't complain
- about the second decl, since it does have an initializer before.
- We deliberately don't complain about arrays, because they're
- supposed to be initialized by a constructor. */
- if (! DECL_INITIAL (decl)
- && TREE_CODE (type) != ARRAY_TYPE
- && (!pedantic || !current_class_type))
- cp_error ("uninitialized const `%#D'", decl);
- }
+ }
+ else
+ check_for_uninitialized_const_var (decl);
+
/* For top-level declaration, the initial value was read in
the temporary obstack. MAXINDEX, rtl, etc. to be made below
must go in the permanent obstack; but don't discard the
@@ -7234,7 +8134,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else if (! DECL_ARTIFICIAL (decl))
{
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
- cp_warning_at (" you can work around this by removing the initializer"), decl;
+ cp_warning_at (" you can work around this by removing the initializer", decl);
}
}
}
@@ -7242,31 +8142,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_LANG_SPECIFIC (decl)
&& DECL_COMDAT (decl))
- {
- /* Dynamically initialized vars go into common. */
- if (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
- DECL_COMMON (decl) = 1;
- else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
- {
- DECL_COMMON (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node;
- }
- else
- {
- /* Statically initialized vars are weak or comdat, if
- supported. */
- if (flag_weak)
- make_decl_one_only (decl);
- else
- {
- /* We can't do anything useful; leave vars for explicit
- instantiation. */
- DECL_EXTERNAL (decl) = 1;
- DECL_NOT_REALLY_EXTERN (decl) = 0;
- }
- }
- }
+ /* Set it up again; we might have set DECL_INITIAL since the
+ last time. */
+ comdat_linkage (decl);
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
make_decl_rtl (decl, NULL_PTR, toplev);
@@ -7343,17 +8221,17 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
resume_temporary_allocation ();
if (type != error_mark_node
- && TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_ABSTRACT_VIRTUALS (type))
- abstract_virtuals_error (decl, type);
+ && TYPE_LANG_SPECIFIC (core_type)
+ && CLASSTYPE_ABSTRACT_VIRTUALS (core_type))
+ abstract_virtuals_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type)))
abstract_virtuals_error (decl, TREE_TYPE (type));
- if (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE (type))
- signature_error (decl, type);
+ if (TYPE_LANG_SPECIFIC (core_type) && IS_SIGNATURE (core_type))
+ signature_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
@@ -7414,7 +8292,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (current_binding_level->is_for_scope)
{
- struct binding_level *outer = current_binding_level->level_chain;
+ struct binding_level *outer
+ = current_binding_level->level_chain;
/* Check to see if the same name is already bound at
the outer level, either because it was directly declared,
@@ -7426,36 +8305,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
Otherwise, we need to preserve the temp slot for decl
to last into the outer binding level. */
- int handling_dead_for_vars = 0;
- tree link = outer->names;
- for (; ; link = TREE_CHAIN (link))
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+
+ if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == VAR_DECL)
+ && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
- if (link == NULL && handling_dead_for_vars == 0)
- {
- link = outer->dead_vars_from_for;
- handling_dead_for_vars = 1;
- }
- if (link == NULL)
- {
- if (DECL_IN_MEMORY_P (decl))
- preserve_temp_slots (DECL_RTL (decl));
- break;
- }
- if (DECL_NAME (link) == DECL_NAME (decl))
- {
- if (handling_dead_for_vars)
- {
- tree shadowing
- = purpose_member (DECL_NAME (decl),
- current_binding_level->shadowed);
- if (shadowing && TREE_VALUE (shadowing) == link)
- TREE_VALUE (shadowing)
- = DECL_SHADOWED_FOR_VAR (link);
- }
- current_binding_level->is_for_scope = 0;
- break;
- }
+ BINDING_VALUE (outer_binding)
+ = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
+ current_binding_level->is_for_scope = 0;
}
+ else if (DECL_IN_MEMORY_P (decl))
+ preserve_temp_slots (DECL_RTL (decl));
}
expand_start_target_temps ();
@@ -7470,7 +8333,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
- expand_aggr_init (decl, init, 0, flags);
+ expand_aggr_init (decl, init, flags);
}
/* Set this to 0 so we can tell whether an aggregate which
@@ -7524,7 +8387,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
the binding level.. */
&& TYPE_SIZE (context) != NULL_TREE
&& context == current_class_type)
- popclass (1);
+ pop_nested_class ();
}
}
@@ -7582,7 +8445,7 @@ expand_static_init (decl, init)
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
cp_error ("multiple initializations given for `%D'", decl);
}
- else if (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+ else if (! toplevel_bindings_p ())
{
/* Emit code to perform this initialization but once. */
tree temp;
@@ -7590,30 +8453,65 @@ expand_static_init (decl, init)
/* Remember this information until end of file. */
push_obstacks (&permanent_obstack, &permanent_obstack);
- /* Emit code to perform this initialization but once. */
+ /* Emit code to perform this initialization but once. This code
+ looks like:
+
+ static int temp = 0;
+ if (!temp) {
+ // Do initialization.
+ temp = 1;
+ // Register variable for destruction at end of program.
+ }
+
+ Note that the `temp' variable is only set to 1 *after* the
+ initialization is complete. This ensures that an exception,
+ thrown during the construction, will cause the variable to
+ reinitialized when we pass through this code again, as per:
+
+ [stmt.dcl]
+
+ If the initialization exits by throwing an exception, the
+ initialization is not complete, so it will be tried again
+ the next time control enters the declaration.
+
+ In theory, this process should be thread-safe, too; multiple
+ threads should not be able to initialize the variable more
+ than once. We don't yet attempt to ensure thread-safety. */
temp = get_temp_name (integer_type_node, 1);
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
+
+ /* Begin the conditional initialization. */
expand_start_cond (build_binary_op (EQ_EXPR, temp,
- integer_zero_node, 1), 0);
+ integer_zero_node), 0);
expand_start_target_temps ();
- expand_assignment (temp, integer_one_node, 0, 0);
+ /* Do the initialization itself. */
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| (init && TREE_CODE (init) == TREE_LIST))
{
- expand_aggr_init (decl, init, 0, 0);
+ expand_aggr_init (decl, init, 0);
do_pending_stack_adjust ();
}
else if (init)
expand_assignment (decl, init, 0, 0);
- /* Cleanup any temporaries needed for the initial value. */
+ /* Set TEMP to 1. */
+ expand_assignment (temp, integer_one_node, 0, 0);
+
+ /* Cleanup any temporaries needed for the initial value. If
+ destroying one of the temporaries causes an exception to be
+ thrown, then the object itself has still been fully
+ constructed. */
expand_end_target_temps ();
+ /* Use atexit to register a function for destroying this static
+ variable. */
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{
tree cleanup, fcall;
static tree Atexit = 0;
+ int saved_flag_access_control;
+
if (Atexit == 0)
{
tree atexit_fndecl, PFV, pfvlist;
@@ -7630,38 +8528,55 @@ expand_static_init (decl, init)
build_function_type (void_type_node,
pfvlist),
NOT_BUILT_IN, NULL_PTR);
- assemble_external (atexit_fndecl);
+ mark_used (atexit_fndecl);
Atexit = default_conversion (atexit_fndecl);
pop_lang_context ();
pop_obstacks ();
}
+ /* Call build_cleanup before we enter the anonymous function
+ so that any access checks will be done relative to the
+ current scope, rather than the scope of the anonymous
+ function. */
+ build_cleanup (decl);
+
+ /* Now start the function. */
cleanup = start_anon_func ();
- expand_expr_stmt (build_cleanup (decl));
+
+ /* Now, recompute the cleanup. It may contain SAVE_EXPRs
+ that refer to the original function, rather than the
+ anonymous one. That will make the back-end think that
+ nested functions are in use, which causes confusion. */
+ saved_flag_access_control = flag_access_control;
+ flag_access_control = 0;
+ fcall = build_cleanup (decl);
+ flag_access_control = saved_flag_access_control;
+
+ /* Finish off the function. */
+ expand_expr_stmt (fcall);
end_anon_func ();
+
+ /* Call atexit with the cleanup function. */
mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
- fcall = build_function_call (Atexit, expr_tree_cons (NULL_TREE, cleanup, NULL_TREE));
+ fcall = build_function_call (Atexit,
+ expr_tree_cons (NULL_TREE,
+ cleanup,
+ NULL_TREE));
expand_expr_stmt (fcall);
}
expand_end_cond ();
- if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
- {
- static_aggregates = perm_tree_cons (temp, decl, static_aggregates);
- TREE_STATIC (static_aggregates) = 1;
- }
-
/* Resume old (possibly temporary) allocation. */
pop_obstacks ();
}
else
{
- /* This code takes into account memory allocation
- policy of `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING
- does not hold for this object, then we must make permanent
- the storage currently in the temporary obstack. */
- if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ /* This code takes into account memory allocation policy of
+ `start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING does not
+ hold for this object, then we must make permanent the storage
+ currently in the temporary obstack. */
+ if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
preserve_initializer ();
static_aggregates = perm_tree_cons (init, decl, static_aggregates);
}
@@ -7669,7 +8584,7 @@ expand_static_init (decl, init)
/* Make TYPE a complete type based on INITIAL_VALUE.
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 1 if DO_DEFAULT). */
+ 2 if there was no information (in which case assume 0 if DO_DEFAULT). */
int
complete_array_type (type, initial_value, do_default)
@@ -7678,7 +8593,10 @@ complete_array_type (type, initial_value, do_default)
{
register tree maxindex = NULL_TREE;
int value = 0;
-
+
+ /* Allocate on the same obstack as TYPE. */
+ push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+
if (initial_value)
{
/* Note MAXINDEX is really the maximum index,
@@ -7708,6 +8626,8 @@ complete_array_type (type, initial_value, do_default)
/* Make an error message unless that happened already. */
if (initial_value != error_mark_node)
value = 1;
+ else
+ initial_value = NULL_TREE;
/* Prevent further error messages. */
maxindex = build_int_2 (0, 0);
@@ -7724,23 +8644,28 @@ complete_array_type (type, initial_value, do_default)
if (maxindex)
{
tree itype;
+ tree domain;
+
+ domain = build_index_type (maxindex);
+ TYPE_DOMAIN (type) = domain;
- TYPE_DOMAIN (type) = build_index_type (maxindex);
if (! TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+ TREE_TYPE (maxindex) = domain;
if (initial_value)
itype = TREE_TYPE (initial_value);
else
itype = NULL;
if (itype && !TYPE_DOMAIN (itype))
- TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (itype) = domain;
/* The type of the main variant should never be used for arrays
of different sizes. It should only ever be completed with the
size of the array. */
if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
- TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = TYPE_DOMAIN (type);
+ TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
}
+ pop_obstacks();
+
/* Lay out the type now that we can get the real answer. */
layout_type (type);
@@ -7755,7 +8680,7 @@ complete_array_type (type, initial_value, do_default)
static int
member_function_or_else (ctype, cur_type, string)
tree ctype, cur_type;
- char *string;
+ const char *string;
{
if (ctype && ctype != cur_type)
{
@@ -7773,7 +8698,7 @@ member_function_or_else (ctype, cur_type, string)
static void
bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
tree object;
- char *type;
+ const char *type;
int virtualp, quals, friendp, raises, inlinep;
{
if (virtualp)
@@ -7799,23 +8724,27 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
or `volatile'.
RAISES is a list of exceptions that this function can raise.
CHECK is 1 if we must find this method in CTYPE, 0 if we should
- not look, and -1 if we should not call `grokclassfn' at all. */
+ not look, and -1 if we should not call `grokclassfn' at all.
+
+ Returns `NULL_TREE' if something goes wrong, after issuing
+ applicable error messages. */
static tree
grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
- raises, attrlist, check, friendp, publicp, inlinep, funcdef_flag,
+ raises, check, friendp, publicp, inlinep, funcdef_flag,
template_count, in_namespace)
tree ctype, type;
tree declarator;
tree orig_declarator;
int virtualp;
enum overload_flags flags;
- tree quals, raises, attrlist;
+ tree quals, raises;
int check, friendp, publicp, inlinep, funcdef_flag, template_count;
tree in_namespace;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
+ int has_default_arg = 0;
tree t;
if (ctype)
@@ -7834,9 +8763,23 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
- /* This decl is not from the current namespace. */
+ /* If this decl has namespace scope, set that up. */
if (in_namespace)
- set_decl_namespace (decl, in_namespace);
+ set_decl_namespace (decl, in_namespace, friendp);
+ else if (publicp && ! ctype)
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+
+ /* `main' and builtins have implicit 'C' linkage. */
+ if ((MAIN_NAME_P (declarator)
+ || (IDENTIFIER_LENGTH (declarator) > 10
+ && IDENTIFIER_POINTER (declarator)[0] == '_'
+ && IDENTIFIER_POINTER (declarator)[1] == '_'
+ && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
+ && current_lang_name == lang_name_cplusplus
+ && ctype == NULL_TREE
+ /* NULL_TREE means global namespace. */
+ && DECL_CONTEXT (decl) == NULL_TREE)
+ DECL_LANGUAGE (decl) = lang_c;
/* Should probably propagate const out from type to decl I bet (mrs). */
if (staticp)
@@ -7848,8 +8791,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype)
DECL_CLASS_CONTEXT (decl) = ctype;
- if (ctype == NULL_TREE && MAIN_NAME_P (declarator))
+ if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
+ if (processing_template_decl)
+ error ("cannot declare `main' to be a template");
if (inlinep)
error ("cannot declare `main' to be inline");
else if (! publicp)
@@ -7857,7 +8802,37 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
inlinep = 0;
publicp = 1;
}
-
+
+ /* Members of anonymous types and local classes have no linkage; make
+ them internal. */
+ if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype))
+ || hack_decl_function_context (TYPE_MAIN_DECL (ctype))))
+ publicp = 0;
+
+ if (publicp)
+ {
+ /* [basic.link]: A name with no linkage (notably, the name of a class
+ or enumeration declared in a local scope) shall not be used to
+ declare an entity with linkage.
+
+ Only check this for public decls for now. */
+ t = no_linkage_check (TREE_TYPE (decl));
+ if (t)
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ {
+ if (DECL_LANGUAGE (decl) == lang_c)
+ /* Allow this; it's pretty common in C. */;
+ else
+ cp_pedwarn ("non-local function `%#D' uses anonymous type",
+ decl);
+ }
+ else
+ cp_pedwarn ("non-local function `%#D' uses local type `%T'",
+ decl, t);
+ }
+ }
+
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
@@ -7886,7 +8861,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
{
- add_defarg_fn (decl);
+ has_default_arg = 1;
break;
}
@@ -7899,6 +8874,15 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
orig_declarator);
else
{
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ {
+ /* Something like `template <class T> friend void f<T>()'. */
+ cp_error ("template-id `%D' in declaration of primary template",
+ orig_declarator);
+ return NULL_TREE;
+ }
+
+
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
@@ -7906,9 +8890,37 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
= perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
TREE_OPERAND (orig_declarator, 1),
NULL_TREE);
+
+ if (has_default_arg)
+ {
+ cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
+
+ if (inlinep)
+ {
+ cp_error ("`inline' is not allowed in declaration of friend template specialization `%D'",
+ decl);
+ return NULL_TREE;
+ }
}
}
+ if (has_default_arg)
+ add_defarg_fn (decl);
+
+ /* Plain overloading: will not be grok'd by grokclassfn. */
+ if (! ctype && ! processing_template_decl
+ && DECL_LANGUAGE (decl) != lang_c
+ && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
+ set_mangled_name_for_decl (decl);
+
+ if (funcdef_flag)
+ /* Make the init_value nonzero so pushdecl knows this is not
+ tentative. error_mark_node is replaced later with the BLOCK. */
+ DECL_INITIAL (decl) = error_mark_node;
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
@@ -7926,14 +8938,16 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
the following calls is supposed to do. */
DECL_CONSTRUCTOR_P (decl) = 1;
- grokclassfn (ctype, declarator, decl, flags, quals);
+ grokclassfn (ctype, decl, flags, quals);
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
+ if (decl == error_mark_node)
+ return NULL_TREE;
- if ((! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ if ((! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
tmp = check_classfn (ctype, decl);
@@ -7948,22 +8962,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
}
if (! grok_ctor_properties (ctype, decl))
return NULL_TREE;
-
- if (check == 0 && ! current_function_decl)
- {
- /* Assembler names live in the global namespace. */
- tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
- if (tmp == NULL_TREE)
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- cp_error ("inconsistent declarations for `%D'", decl);
- else
- {
- duplicate_decls (decl, tmp);
- decl = tmp;
- }
- make_decl_rtl (decl, NULL_PTR, 1);
- }
}
else
{
@@ -7973,14 +8971,17 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
This call may change the type of the function (because
of default parameters)! */
if (ctype != NULL_TREE)
- grokclassfn (ctype, cname, decl, flags, quals);
+ grokclassfn (ctype, decl, flags, quals);
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
+ if (decl == error_mark_node)
+ return NULL_TREE;
+
if (ctype != NULL_TREE
- && (! TYPE_FOR_JAVA (ctype) || check_java_method (ctype, decl))
+ && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
tmp = check_classfn (ctype, decl);
@@ -8000,8 +9001,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp)
{
+ /* Attempt to merge the declarations. This can fail, in
+ the case of some illegal specialization declarations. */
if (!duplicate_decls (decl, tmp))
- my_friendly_abort (892);
+ cp_error ("no `%#D' member function declared in class `%T'",
+ decl, ctype);
return tmp;
}
}
@@ -8009,37 +9013,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (ctype == NULL_TREE || check)
return decl;
- /* Now install the declaration of this function so that others may
- find it (esp. its DECL_FRIENDLIST). Don't do this for local class
- methods, though. */
- if (! current_function_decl)
- {
- if (!DECL_TEMPLATE_SPECIALIZATION (decl))
- {
- /* We don't do this for specializations since the
- equivalent checks will be done later. Also, at this
- point the DECL_ASSEMBLER_NAME is not yet fully
- accurate. */
-
- /* FIXME: this should only need to look at
- IDENTIFIER_GLOBAL_VALUE. */
- tmp = lookup_name (DECL_ASSEMBLER_NAME (decl), 0);
- if (tmp == NULL_TREE)
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl), decl);
- else if (TREE_CODE (tmp) != TREE_CODE (decl))
- cp_error ("inconsistent declarations for `%D'", decl);
- else
- {
- duplicate_decls (decl, tmp);
- decl = tmp;
- }
- }
-
- if (attrlist)
- cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
- TREE_VALUE (attrlist));
- make_decl_rtl (decl, NULL_PTR, 1);
- }
if (virtualp)
{
DECL_VIRTUAL_P (decl) = 1;
@@ -8078,16 +9051,27 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
}
else
{
- tree context = in_namespace ? in_namespace : current_namespace;
+ tree context;
+
+ if (in_namespace)
+ context = in_namespace;
+ else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
+ context = current_namespace;
+ else
+ context = NULL_TREE;
+
decl = build_decl (VAR_DECL, declarator, complete_type (type));
- if (context != global_namespace && namespace_bindings_p ()
- && current_lang_name != lang_name_c)
- DECL_ASSEMBLER_NAME (decl) = build_static_name (context,
- declarator);
+
+ if (context)
+ set_decl_namespace (decl, context, 0);
+
+ context = DECL_CONTEXT (decl);
+ if (declarator && context && current_lang_name != lang_name_c)
+ DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator);
}
if (in_namespace)
- set_decl_namespace (decl, in_namespace);
+ set_decl_namespace (decl, in_namespace, 0);
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
@@ -8117,10 +9101,30 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits);
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
+
+ if (TREE_PUBLIC (decl))
+ {
+ /* [basic.link]: A name with no linkage (notably, the name of a class
+ or enumeration declared in a local scope) shall not be used to
+ declare an entity with linkage.
+
+ Only check this for public decls for now. */
+ tree t = no_linkage_check (TREE_TYPE (decl));
+ if (t)
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ /* Ignore for now; `enum { foo } e' is pretty common. */;
+ else
+ cp_pedwarn ("non-local variable `%#D' uses local type `%T'",
+ decl, t);
+ }
+ }
+
return decl;
}
-/* Create a canonical pointer to member function type. */
+/* Create and return a canonical pointer to member function type, for
+ TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
build_ptrmemfunc_type (type)
@@ -8140,7 +9144,7 @@ build_ptrmemfunc_type (type)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
u = make_lang_type (UNION_TYPE);
- IS_AGGR_TYPE (u) = 0;
+ SET_IS_AGGR_TYPE (u, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
delta_type_node);
@@ -8152,7 +9156,7 @@ build_ptrmemfunc_type (type)
/* Let the front-end know this is a pointer to member function... */
TYPE_PTRMEMFUNC_FLAG (t) = 1;
/* ... and not really an aggregate. */
- IS_AGGR_TYPE (t) = 0;
+ SET_IS_AGGR_TYPE (t, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
delta_type_node);
@@ -8174,6 +9178,41 @@ build_ptrmemfunc_type (type)
return t;
}
+/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
+ Check to see that the definition is valid. Issue appropriate error
+ messages. Return 1 if the definition is particularly bad, or 0
+ otherwise. */
+
+int
+check_static_variable_definition (decl, type)
+ tree decl;
+ tree type;
+{
+ /* Motion 10 at San Diego: If a static const integral data member is
+ initialized with an integral constant expression, the initializer
+ may appear either in the declaration (within the class), or in
+ the definition, but not both. If it appears in the class, the
+ member is a member constant. The file-scope definition is always
+ required. */
+ if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ cp_error ("in-class initialization of static data member of non-integral type `%T'",
+ type);
+ /* If we just return the declaration, crashes will sometimes
+ occur. We therefore return void_type_node, as if this was a
+ friend declaration, to cause callers to completely ignore
+ this declaration. */
+ return 1;
+ }
+ else if (!CP_TYPE_CONST_P (type))
+ cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+ decl);
+ else if (pedantic && !INTEGRAL_TYPE_P (type))
+ cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+
+ return 0;
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@@ -8201,6 +9240,9 @@ build_ptrmemfunc_type (type)
BITFIELD for a field with specified width.
INITIALIZED is 1 if the decl has an initializer.
+ ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
+ normal attributes in TREE_PURPOSE, or NULL_TREE.
+
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
argument type is specified but not the name.
@@ -8246,7 +9288,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree type = NULL_TREE;
int longlong = 0;
int constp;
+ int restrictp;
int volatilep;
+ int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
@@ -8279,6 +9323,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
+ tree inner_attrs;
+ int ignore_attrs;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@@ -8300,6 +9346,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
decl = *next;
switch (TREE_CODE (decl))
{
+ case TREE_LIST:
+ /* For attributes. */
+ next = &TREE_VALUE (decl);
+ break;
+
case COND_EXPR:
ctype = NULL_TREE;
next = &TREE_OPERAND (decl, 0);
@@ -8359,18 +9410,38 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
case CALL_EXPR:
if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
{
- /* This is actually a variable declaration using constructor
- syntax. We need to call start_decl and cp_finish_decl so we
- can get the variable initialized... */
+ /* This is actually a variable declaration using
+ constructor syntax. We need to call start_decl and
+ cp_finish_decl so we can get the variable
+ initialized... */
+
+ tree attributes, prefix_attributes;
*next = TREE_OPERAND (decl, 0);
init = TREE_OPERAND (decl, 1);
- decl = start_decl (declarator, declspecs, 1, NULL_TREE, NULL_TREE);
- /* Look for __unused__ attribute */
- if (TREE_USED (TREE_TYPE (decl)))
- TREE_USED (decl) = 1;
- finish_decl (decl, init, NULL_TREE);
+ if (attrlist)
+ {
+ attributes = TREE_PURPOSE (attrlist);
+ prefix_attributes = TREE_VALUE (attrlist);
+ }
+ else
+ {
+ attributes = NULL_TREE;
+ prefix_attributes = NULL_TREE;
+ }
+
+ decl = start_decl (declarator, declspecs, 1,
+ attributes, prefix_attributes);
+ if (decl)
+ {
+ /* Look for __unused__ attribute */
+ if (TREE_USED (TREE_TYPE (decl)))
+ TREE_USED (decl) = 1;
+ finish_decl (decl, init, NULL_TREE);
+ }
+ else
+ cp_error ("invalid declarator");
return 0;
}
innermost_code = TREE_CODE (decl);
@@ -8403,12 +9474,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (fns) == LOOKUP_EXPR)
fns = TREE_OPERAND (fns, 0);
- if (TREE_CODE (fns) == IDENTIFIER_NODE)
- dname = fns;
- else if (is_overloaded_fn (fns))
- dname = DECL_NAME (get_first_fn (fns));
- else
- my_friendly_abort (0);
+ dname = fns;
+ if (TREE_CODE (dname) == COMPONENT_REF)
+ dname = TREE_OPERAND (dname, 1);
+ if (TREE_CODE (dname) != IDENTIFIER_NODE)
+ {
+ my_friendly_assert (is_overloaded_fn (dname),
+ 19990331);
+ dname = DECL_NAME (get_first_fn (dname));
+ }
}
/* Fall through. */
@@ -8747,24 +9821,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else
{
- if (funcdef_flag)
- {
- if (warn_return_type
- && return_type == return_normal)
- /* Save warning until we know what is really going on. */
- warn_about_return_type = 1;
- }
- else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
- pedwarn ("ANSI C++ forbids typedef which does not specify a type");
- else if (innermost_code != CALL_EXPR || pedantic
- || (warn_return_type && return_type == return_normal))
- {
- if (innermost_code == CALL_EXPR)
- cp_pedwarn ("return-type of `%D' defaults to `int'", dname);
- else
- cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
- dname);
- }
+ /* We handle `main' specially here, because 'main () { }' is so
+ common. With no options, it is allowed. With -Wreturn-type,
+ it is a warning. It is only an error with -pedantic-errors. */
+ int is_main = (funcdef_flag
+ && MAIN_NAME_P (dname)
+ && ctype == NULL_TREE
+ && in_namespace == NULL_TREE
+ && current_namespace == global_namespace);
+
+ if (in_system_header)
+ /* Allow it, sigh. */;
+ else if (pedantic || ! is_main)
+ cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
+ dname);
+ else if (warn_return_type)
+ cp_warning ("ANSI C++ forbids declaration `%D' with no type",
+ dname);
+
type = integer_type_node;
}
}
@@ -8780,7 +9854,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (return_type == return_conversion)
{
- if (comptypes (type, ctor_return_type, 1) == 0)
+ if (!same_type_p (type, ctor_return_type))
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
@@ -8801,8 +9875,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
RIDBIT_RESET (RID_LONG, specbits);
- type = build_type_variant (long_double_type_node, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
+ type = build_qualified_type (long_double_type_node,
+ CP_TYPE_QUALS (type));
}
/* Check all other uses of type modifiers. */
@@ -8924,17 +9998,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (return_type == return_conversion
&& (RIDBIT_SETP (RID_CONST, specbits)
- || RIDBIT_SETP (RID_VOLATILE, specbits)))
- cp_error ("`operator %T' cannot be cv-qualified",
+ || RIDBIT_SETP (RID_VOLATILE, specbits)
+ || RIDBIT_SETP (RID_RESTRICT, specbits)))
+ cp_error ("qualifiers are not allowed on declaration of `operator %T'",
ctor_return_type);
/* Set CONSTP if this declaration is `const', whether by
explicit specification or via a typedef.
Likewise for VOLATILEP. */
- constp = !! RIDBIT_SETP (RID_CONST, specbits) + TYPE_READONLY (type);
- volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
- type = build_type_variant (type, 0, 0);
+ constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type);
+ restrictp =
+ !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type);
+ volatilep =
+ !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type);
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+ type = cp_build_qualified_type (type, type_quals);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
@@ -8954,6 +10035,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
friendp = RIDBIT_SETP (RID_FRIEND, specbits);
RIDBIT_RESET (RID_FRIEND, specbits);
+ /* $7.1.2, Function specifiers */
+ if (friendp && explicitp)
+ error ("only declarations of constructors can be `explicit'");
+
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (decl_context == PARM)
@@ -9011,16 +10096,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& IS_SIGNATURE (current_class_type)
&& RIDBIT_NOTSETP (RID_TYPEDEF, specbits))
{
- if (constp)
+ if (type_quals != TYPE_UNQUALIFIED)
{
- error ("`const' specified for signature member function `%s'", name);
- constp = 0;
- }
- if (volatilep)
- {
- error ("`volatile' specified for signature member function `%s'",
- name);
- volatilep = 0;
+ error ("type qualifiers specified for signature member function `%s'", name);
+ type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
@@ -9107,7 +10186,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
- if (! constp)
+ if (!(type_quals & TYPE_QUAL_CONST))
warning ("`%s' initialized and declared `extern'", name);
}
else
@@ -9129,6 +10208,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
Descend through it, creating more complex types, until we reach
the declared identifier (or NULL_TREE, in an absolute declarator). */
+ inner_attrs = NULL_TREE;
+ ignore_attrs = 0;
+
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
@@ -9175,8 +10257,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
quals = NULL_TREE;
}
}
+
+ /* See the comment for the TREE_LIST case, below. */
+ if (ignore_attrs)
+ ignore_attrs = 0;
+ else if (inner_attrs)
+ {
+ decl_attributes (type, inner_attrs, NULL_TREE);
+ inner_attrs = NULL_TREE;
+ }
+
switch (TREE_CODE (declarator))
{
+ case TREE_LIST:
+ {
+ /* We encode a declarator with embedded attributes using
+ a TREE_LIST. The attributes apply to the declarator
+ directly inside them, so we have to skip an iteration
+ before applying them to the type. If the declarator just
+ inside is the declarator-id, we apply the attrs to the
+ decl itself. */
+ inner_attrs = TREE_PURPOSE (declarator);
+ ignore_attrs = 1;
+ declarator = TREE_VALUE (declarator);
+ }
+ break;
+
case ARRAY_REF:
{
register tree itype = NULL_TREE;
@@ -9230,10 +10336,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (size == error_mark_node)
type = error_mark_node;
+ else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
+ {
+ /* [dcl.array]
+
+ the constant expressions that specify the bounds of
+ the arrays can be omitted only for the first member
+ of the sequence. */
+ cp_error ("declaration of `%D' as multidimensional array",
+ dname);
+ cp_error ("must have bounds for all dimensions except the first");
+ type = error_mark_node;
+ }
if (type == error_mark_node)
continue;
+ /* VC++ spells a zero-sized array with []. */
+ if (size == NULL_TREE && decl_context == FIELD && ! staticp
+ && ! RIDBIT_SETP (RID_TYPEDEF, specbits))
+ size = integer_zero_node;
+
if (size)
{
/* Must suspend_momentary here because the index
@@ -9248,19 +10371,33 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
size = TREE_OPERAND (size, 0);
- /* If this involves a template parameter, it'll be
- constant, but we don't know what the value is yet. */
+ /* If this involves a template parameter, it will be a
+ constant at instantiation time, but we don't know
+ what the value is yet. Even if no template
+ parameters are involved, we may an expression that
+ is not a constant; we don't even simplify `1 + 2'
+ when processing a template. */
if (processing_template_decl)
{
- itype = make_node (INTEGER_TYPE);
- TYPE_MIN_VALUE (itype) = size_zero_node;
- TYPE_MAX_VALUE (itype) = build_min
- (MINUS_EXPR, sizetype, size, integer_one_node);
+ /* Resolve a qualified reference to an enumerator or
+ static const data member of ours. */
+ if (TREE_CODE (size) == SCOPE_REF
+ && TREE_OPERAND (size, 0) == current_class_type)
+ {
+ tree t = lookup_field (current_class_type,
+ TREE_OPERAND (size, 1), 0, 0);
+ if (t)
+ size = t;
+ }
+
+ itype = build_index_type (build_min
+ (MINUS_EXPR, sizetype, size, integer_one_node));
goto dont_grok_size;
}
if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
+ && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
cp_error ("size of array `%D' has non-integer type",
dname);
@@ -9301,7 +10438,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
= fold (build_binary_op (MINUS_EXPR,
cp_convert (index_type, size),
cp_convert (index_type,
- integer_one_node), 1));
+ integer_one_node)));
if (! TREE_CONSTANT (itype))
itype = variable_size (itype);
else if (TREE_OVERFLOW (itype))
@@ -9328,15 +10465,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
resume_momentary (yes);
}
- /* Build the array type itself, then merge any constancy or
- volatility into the target type. We must do it in this order
- to ensure that the TYPE_MAIN_VARIANT field of the array type
- is set correctly. */
-
type = build_cplus_array_type (type, itype);
- if (constp || volatilep)
- type = cp_build_type_variant (type, constp, volatilep);
-
ctype = NULL_TREE;
}
break;
@@ -9350,23 +10479,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
-#if 0
- /* Is this an error? Should they be merged into TYPE here? */
- if (pedantic && (constp || volatilep))
- pedwarn ("function declared to return const or volatile result");
-#else
- /* Merge any constancy or volatility into the function return
- type. */
- if (constp || volatilep)
- {
- type = cp_build_type_variant (type, constp, volatilep);
- if (IS_AGGR_TYPE (type))
- build_pointer_type (type);
- constp = 0;
- volatilep = 0;
- }
-#endif
+ /* We now know that the TYPE_QUALS don't apply to the
+ decl, but to its return type. */
+ type_quals = TYPE_UNQUALIFIED;
/* Warn about some types functions can't return. */
@@ -9574,21 +10690,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Merge any constancy or volatility into the target type
for the pointer. */
- if (constp || volatilep)
- {
- /* A const or volatile signature pointer/reference is
- pointing to a const or volatile object, i.e., the
- `optr' is const or volatile, respectively, not the
- signature pointer/reference itself. */
- if (! IS_SIGNATURE (type))
- {
- type = cp_build_type_variant (type, constp, volatilep);
- if (IS_AGGR_TYPE (type))
- build_pointer_type (type);
- constp = 0;
- volatilep = 0;
- }
- }
+ /* We now know that the TYPE_QUALS don't apply to the decl,
+ but to the target of the pointer. */
+ type_quals = TYPE_UNQUALIFIED;
if (IS_SIGNATURE (type))
{
@@ -9599,8 +10703,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
cp_warning ("empty signature `%T' used in signature reference declaration",
type);
#if 0
- type = build_signature_reference_type (type,
- constp, volatilep);
+ type = build_signature_reference_type (type);
#else
sorry ("signature reference");
return NULL_TREE;
@@ -9612,31 +10715,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& TYPE_SIZE (type))
cp_warning ("empty signature `%T' used in signature pointer declaration",
type);
- type = build_signature_pointer_type (type,
- constp, volatilep);
+ type = build_signature_pointer_type (type);
}
- constp = 0;
- volatilep = 0;
}
else if (TREE_CODE (declarator) == ADDR_EXPR)
{
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("cannot declare references to functions; use pointer to function instead");
- type = build_pointer_type (type);
- }
+ if (TREE_CODE (type) == VOID_TYPE)
+ error ("invalid type: `void &'");
else
- {
- if (TREE_CODE (type) == VOID_TYPE)
- error ("invalid type: `void &'");
- else
- type = build_reference_type (type);
- }
+ type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
- {
- type = build_ptrmemfunc_type (build_pointer_type (type));
- }
+ type = build_ptrmemfunc_type (build_pointer_type (type));
else
type = build_pointer_type (type);
@@ -9647,25 +10737,37 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
register tree typemodlist;
int erred = 0;
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
- if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+ tree qualifier = TREE_VALUE (typemodlist);
+
+ if (qualifier == ridpointers[(int) RID_CONST])
constp++;
- else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+ else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++;
+ else if (qualifier == ridpointers[(int) RID_RESTRICT])
+ restrictp++;
else if (!erred)
{
erred = 1;
- error ("invalid type modifier within %s declarator",
- TREE_CODE (declarator) == ADDR_EXPR
- ? "reference" : "pointer");
+ error ("invalid type modifier within pointer declarator");
}
}
if (constp > 1)
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
+
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
if (TREE_CODE (declarator) == ADDR_EXPR
&& (constp || volatilep))
{
@@ -9673,8 +10775,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
pedwarn ("discarding `const' applied to a reference");
if (volatilep)
pedwarn ("discarding `volatile' applied to a reference");
- constp = volatilep = 0;
+ type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
+ type = cp_build_qualified_type (type, type_quals);
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
@@ -9718,14 +10821,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
- type = tsubst (type, args, NULL_TREE);
+ type = tsubst (type, args, /*complain=*/1, NULL_TREE);
}
/* This pop_nested_class corresponds to the
push_nested_class used to push into class scope for
parsing the argument list of a function decl, in
qualified_id. */
- pop_nested_class (1);
+ pop_nested_class ();
TREE_COMPLEXITY (declarator) = current_class_depth;
}
else
@@ -9743,7 +10846,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype = TREE_OPERAND (declarator, 0);
t = ctype;
- while (t != NULL_TREE)
+ while (t != NULL_TREE && CLASS_TYPE_P (t))
{
if (CLASSTYPE_TEMPLATE_INFO (t) &&
!CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
@@ -9779,8 +10882,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
if (current_class_type == NULL_TREE
|| friendp)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
else
{
cp_error ("cannot declare member function `%T::%s' within `%T'",
@@ -9808,10 +10911,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
if (TREE_CODE (type) == FUNCTION_TYPE)
type
- = build_cplus_method_type (build_type_variant (ctype,
- constp,
- volatilep),
- TREE_TYPE (type),
+ = build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
}
else
@@ -9834,7 +10934,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else
{
if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), TREE_TYPE (type), TYPE_ARG_TYPES (type));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
else
type = build_offset_type (ctype, type);
}
@@ -9861,19 +10962,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
- if (explicitp == 1)
+ /* See the comment for the TREE_LIST case, above. */
+ if (inner_attrs)
{
- error ("only constructors can be declared `explicit'");
- explicitp = 0;
+ if (! ignore_attrs)
+ decl_attributes (type, inner_attrs, NULL_TREE);
+ else if (attrlist)
+ TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
+ else
+ attrlist = build_decl_list (NULL_TREE, inner_attrs);
}
/* Now TYPE has the actual type. */
- /* If this is declaring a typedef name, return a TYPE_DECL. */
+ if (explicitp == 1)
+ {
+ error ("only constructors can be declared `explicit'");
+ explicitp = 0;
+ }
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
- if (constp)
+ if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
@@ -9885,20 +10995,35 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
+ if (declarator == NULL_TREE
+ || TREE_CODE (declarator) == IDENTIFIER_NODE
+ || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
+ && (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)))
+ /* OK */;
+ else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ {
+ cp_error ("template-id `%D' used as a declarator", declarator);
+ declarator = dname;
+ }
+ else
+ /* Unexpected declarator format. */
+ my_friendly_abort (990210);
+
+ /* If this is declaring a typedef name, return a TYPE_DECL. */
+
if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
{
tree decl;
/* Note that the grammar rejects storage classes
in typenames, fields or parameters. */
- if (constp || volatilep)
- type = cp_build_type_variant (type, constp, volatilep);
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
{
- if (declarator == current_class_name)
+ if (declarator == constructor_name (current_class_type))
cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type);
@@ -9921,18 +11046,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
refer to it, so nothing needs know about the name change.
The TYPE_NAME field was filled in by build_struct_xref. */
if (type != error_mark_node
- && !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
{
+ tree oldname = TYPE_NAME (type);
+ tree t;
+
+ /* FIXME: This is bogus; we should not be doing this for
+ cv-qualified types. */
+
/* Replace the anonymous name with the real name everywhere. */
lookup_tag_reverse (type, declarator);
- TYPE_NAME (type) = decl;
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ if (TYPE_NAME (t) == oldname)
+ TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
+ /* If this is a typedef within a template class, the nested
+ type is a (non-primary) template. The name for the
+ template needs updating as well. */
+ if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type))
+ DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
+ = TYPE_IDENTIFIER (type);
+
/* XXX Temporarily set the scope.
When returning, start_decl expects it as NULL_TREE,
and will then then set it using pushdecl. */
@@ -9946,6 +11085,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
DECL_ASSEMBLER_NAME (decl)
= get_identifier (build_overload_name (type, 1, 1));
DECL_CONTEXT (decl) = NULL_TREE;
+
+ /* FIXME remangle member functions; member functions of a
+ type with external linkage have external linkage. */
}
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
@@ -9971,9 +11113,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (RIDBIT_SETP (RID_MUTABLE, specbits))
- {
- error ("non-object member `%s' cannot be declared mutable", name);
- }
+ error ("non-object member `%s' cannot be declared mutable", name);
bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10003,21 +11143,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* Note that the grammar rejects storage classes
in typenames, fields or parameters. */
- if (constp || volatilep)
+ if (type_quals != TYPE_UNQUALIFIED)
{
if (IS_SIGNATURE (type))
- error ("`const' or `volatile' specified with signature type");
- else
- type = cp_build_type_variant (type, constp, volatilep);
+ error ("type qualifiers specified for signature type");
+ type_quals = TYPE_UNQUALIFIED;
}
/* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp)
{
- if (volatilep)
+ if (type_quals != TYPE_UNQUALIFIED)
{
- cp_error ("`volatile' specified for friend class declaration");
- volatilep = 0;
+ cp_error ("type qualifiers specified for friend class declaration");
+ type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
@@ -10084,36 +11223,38 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Now create the decl, which may be a VAR_DECL, a PARM_DECL
or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */
+ if (decl_context == PARM || decl_context == CATCHPARM)
+ {
+ if (ctype || in_namespace)
+ error ("cannot use `::' in parameter declaration");
+
+ /* A parameter declared as an array of T is really a pointer to T.
+ One declared as a function is really a pointer to a function.
+ One declared as a member is really a pointer to member. */
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ /* Transfer const-ness of array into that of type pointed to. */
+ type = build_pointer_type (TREE_TYPE (type));
+ type_quals = TYPE_UNQUALIFIED;
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ type = build_pointer_type (type);
+ else if (TREE_CODE (type) == OFFSET_TYPE)
+ type = build_pointer_type (type);
+ else if (TREE_CODE (type) == VOID_TYPE && declarator)
+ {
+ error ("declaration of `%s' as void", name);
+ return NULL_TREE;
+ }
+ }
+
{
register tree decl;
if (decl_context == PARM)
{
- if (ctype)
- error ("cannot use `::' in parameter declaration");
-
- /* A parameter declared as an array of T is really a pointer to T.
- One declared as a function is really a pointer to a function.
- One declared as a member is really a pointer to member. */
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- /* Transfer const-ness of array into that of type pointed to. */
- type = build_pointer_type
- (cp_build_type_variant (TREE_TYPE (type), constp, volatilep));
- volatilep = constp = 0;
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_pointer_type (type);
- else if (TREE_CODE (type) == OFFSET_TYPE)
- type = build_pointer_type (type);
- else if (TREE_CODE (type) == VOID_TYPE && declarator)
- {
- error ("declaration of `%s' as void", name);
- return NULL_TREE;
- }
-
- decl = build_decl (PARM_DECL, declarator, complete_type (type));
+ decl = build_decl (PARM_DECL, declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10143,6 +11284,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
are error_mark_node, for example. */
decl = NULL_TREE;
}
+ else if (in_namespace && !friendp)
+ {
+ /* Something like struct S { int N::j; }; */
+ cp_error ("invalid use of `::'");
+ decl = NULL_TREE;
+ }
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
int publicp = 0;
@@ -10191,8 +11338,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
}
else if (staticp < 2)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
@@ -10204,19 +11351,48 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
funcdef_flag, template_count, in_namespace);
if (decl == NULL_TREE)
- return NULL_TREE;
+ return decl;
#if 0
/* This clobbers the attrs stored in `decl' from `attrlist'. */
/* The decl and setting of decl_machine_attr is also turned off. */
decl = build_decl_attribute_variant (decl, decl_machine_attr);
#endif
+ /* [class.conv.ctor]
+
+ A constructor declared without the function-specifier
+ explicit that can be called with a single parameter
+ specifies a conversion from the type of its first
+ parameter to the type of its class. Such a constructor
+ is called a converting constructor. */
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
+ else if (DECL_CONSTRUCTOR_P (decl))
+ {
+ /* The constructor can be called with exactly one
+ parameter if there is at least one parameter, and
+ any subsequent parameters have default arguments.
+ We don't look at the first parameter, which is
+ really just the `this' parameter for the new
+ object. */
+ tree arg_types =
+ TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)));
+
+ /* Skip the `in_chrg' argument too, if present. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (decl)))
+ arg_types = TREE_CHAIN (arg_types);
+
+ if (arg_types == void_list_node
+ || (arg_types
+ && TREE_CHAIN (arg_types)
+ && TREE_CHAIN (arg_types) != void_list_node
+ && !TREE_PURPOSE (TREE_CHAIN (arg_types))))
+ DECL_NONCONVERTING_P (decl) = 1;
+ }
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
@@ -10225,7 +11401,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator, declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
template_count, in_namespace);
if (decl == NULL_TREE)
@@ -10273,9 +11449,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
tree t = NULL_TREE;
if (decl && DECL_NAME (decl))
- t = do_friend (ctype, declarator, decl,
- last_function_parms, flags, quals,
- funcdef_flag);
+ {
+ if (template_class_depth (current_class_type) == 0)
+ {
+ decl
+ = check_explicit_specialization
+ (declarator, decl,
+ template_count, 2 * (funcdef_flag != 0) + 4);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
+
+ t = do_friend (ctype, declarator, decl,
+ last_function_parms, attrlist, flags, quals,
+ funcdef_flag);
+ }
if (t && funcdef_flag)
return t;
@@ -10303,42 +11491,39 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
the rest of the compiler does not correctly
handle the initialization unless the member is
static so we make it static below. */
- cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
- constp ? "const member" : "member",
+ cp_pedwarn ("ANSI C++ forbids initialization of member `%D'",
declarator);
cp_pedwarn ("making `%D' static", declarator);
staticp = 1;
}
- /* Motion 10 at San Diego: If a static const integral data
- member is initialized with an integral constant
- expression, the initializer may appear either in the
- declaration (within the class), or in the definition,
- but not both. If it appears in the class, the member is
- a member constant. The file-scope definition is always
- required. */
- if (! constp)
- /* According to Mike Stump, we generate bad code for
- this case, so we might as well always make it an
- error. */
- cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
- declarator);
-
- if (pedantic && ! INTEGRAL_TYPE_P (type)
- && !uses_template_parms (type))
- cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", declarator, type);
+ if (uses_template_parms (type))
+ /* We'll check at instantiation time. */
+ ;
+ else if (check_static_variable_definition (declarator,
+ type))
+ /* If we just return the declaration, crashes
+ will sometimes occur. We therefore return
+ void_type_node, as if this was a friend
+ declaration, to cause callers to completely
+ ignore this declaration. */
+ return void_type_node;
}
+ /* 9.2p13 [class.mem] */
+ if (declarator == constructor_name (current_class_type)
+ /* Divergence from the standard: In extern "C", we
+ allow non-static data members here, because C does
+ and /usr/include/netinet/in.h uses that. */
+ && (staticp || ! in_system_header))
+ cp_pedwarn ("ANSI C++ forbids data member `%D' with same name as enclosing class",
+ declarator);
+
if (staticp)
{
- /* ANSI C++ Apr '95 wp 9.2 */
- if (declarator == current_class_name)
- cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class",
- declarator);
-
/* C++ allows static class members.
All other work for this is done by grokfield.
- This VAR_DECL is built by build_lang_field_decl.
+ This VAR_DCL is built by build_lang_field_decl.
All other VAR_DECLs are built by build_decl. */
decl = build_lang_field_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
@@ -10398,22 +11583,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
error ("virtual non-class function `%s'", name);
virtualp = 0;
}
-
- if (current_lang_name == lang_name_cplusplus
- && ! processing_template_decl
- && ! MAIN_NAME_P (original_name)
- && ! (IDENTIFIER_LENGTH (original_name) > 10
- && IDENTIFIER_POINTER (original_name)[0] == '_'
- && IDENTIFIER_POINTER (original_name)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (original_name)+2, "builtin_", 8) == 0))
- /* Plain overloading: will not be grok'd by grokclassfn. */
- if (name_mangling_version < 1
- || TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
- declarator = build_decl_overload (dname, TYPE_ARG_TYPES (type), 0);
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
- type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
- TREE_TYPE (type), TYPE_ARG_TYPES (type));
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
@@ -10421,23 +11594,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
|| !RIDBIT_SETP (RID_STATIC, specbits));
decl = grokfndecl (ctype, type, original_name, declarator,
- virtualp, flags, quals, raises, attrlist,
+ virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, funcdef_flag,
template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
- /* Among other times, could occur from check_explicit_specialization
- returning an error_mark_node. */
- if (decl == error_mark_node)
- return error_mark_node;
-
- if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
- && (! DECL_USE_TEMPLATE (decl) ||
- name_mangling_version < 1))
- DECL_ASSEMBLER_NAME (decl) = declarator;
-
if (staticp == 1)
{
int illegal_static = 0;
@@ -10467,35 +11630,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* It's a variable. */
- if (decl_context == CATCHPARM)
- {
- if (ctype)
- {
- ctype = NULL_TREE;
- error ("cannot use `::' in parameter declaration");
- }
-
- /* A parameter declared as an array of T is really a pointer to T.
- One declared as a function is really a pointer to a function.
- One declared as a member is really a pointer to member. */
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- /* Transfer const-ness of array into that of type
- pointed to. */
- type = build_pointer_type
- (cp_build_type_variant (TREE_TYPE (type), constp, volatilep));
- volatilep = constp = 0;
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_pointer_type (type);
- else if (TREE_CODE (type) == OFFSET_TYPE)
- type = build_pointer_type (type);
- }
-
/* An uninitialized decl with `extern' is a reference. */
decl = grokvardecl (type, declarator, &specbits,
- initialized, constp, in_namespace);
+ initialized,
+ (type_quals & TYPE_QUAL_CONST) != 0,
+ in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -10540,14 +11679,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. */
-
- if (constp)
- TREE_READONLY (decl) = TREE_CODE (type) != REFERENCE_TYPE;
- if (volatilep)
- {
- TREE_SIDE_EFFECTS (decl) = 1;
- TREE_THIS_VOLATILE (decl) = 1;
- }
+ /* FIXME: Disallow `restrict' pointer-to-member declarations. */
+ c_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
@@ -10580,18 +11713,14 @@ parmlist_is_exprlist (exprs)
return 1;
}
-/* Subroutine of `grokparms'. In a fcn definition, arg types must
- be complete.
-
- C++: also subroutine of `start_function'. */
+/* Subroutine of start_function. Ensure that each of the parameter
+ types (as listed in PARMS) is complete, as is required for a
+ function definition. */
static void
require_complete_types_for_parms (parms)
tree parms;
{
- if (processing_template_decl)
- return;
-
while (parms)
{
tree type = TREE_TYPE (parms);
@@ -10604,35 +11733,110 @@ require_complete_types_for_parms (parms)
error ("parameter has incomplete type");
TREE_TYPE (parms) = error_mark_node;
}
-#if 0
- /* If the arg types are incomplete in a declaration,
- they must include undefined tags.
- These tags can never be defined in the scope of the declaration,
- so the types can never be completed,
- and no call can be compiled successfully. */
- /* This is not the right behavior for C++, but not having
- it is also probably wrong. */
else
- {
- /* Now warn if is a pointer to an incomplete type. */
- while (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- type = TYPE_MAIN_VARIANT (type);
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- if (DECL_NAME (parm) != NULL_TREE)
- warning ("parameter `%s' points to incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- else
- warning ("parameter points to incomplete type");
- }
- }
-#endif
+ layout_decl (parms, 0);
+
parms = TREE_CHAIN (parms);
}
}
+/* Returns DECL if DECL is a local variable (or parameter). Returns
+ NULL_TREE otherwise. */
+
+static tree
+local_variable_p (t)
+ tree t;
+{
+ if ((TREE_CODE (t) == VAR_DECL
+ /* A VAR_DECL with a context that is a _TYPE is a static data
+ member. */
+ && !TYPE_P (CP_DECL_CONTEXT (t))
+ /* Any other non-local variable must be at namespace scope. */
+ && TREE_CODE (CP_DECL_CONTEXT (t)) != NAMESPACE_DECL)
+ || (TREE_CODE (t) == PARM_DECL))
+ return t;
+
+ return NULL_TREE;
+}
+
+/* Check that ARG, which is a default-argument expression for a
+ parameter DECL, is legal. Returns ARG, or ERROR_MARK_NODE, if
+ something goes wrong. DECL may also be a _TYPE node, rather than a
+ DECL, if there is no DECL available. */
+
+tree
+check_default_argument (decl, arg)
+ tree decl;
+ tree arg;
+{
+ tree var;
+ tree decl_type;
+
+ if (TREE_CODE (arg) == DEFAULT_ARG)
+ /* We get a DEFAULT_ARG when looking at an in-class declaration
+ with a default argument. Ignore the argument for now; we'll
+ deal with it after the class is complete. */
+ return arg;
+
+ if (processing_template_decl || uses_template_parms (arg))
+ /* We don't do anything checking until instantiation-time. Note
+ that there may be uninstantiated arguments even for an
+ instantiated function, since default arguments are not
+ instantiated until they are needed. */
+ return arg;
+
+ if (TYPE_P (decl))
+ {
+ decl_type = decl;
+ decl = NULL_TREE;
+ }
+ else
+ decl_type = TREE_TYPE (decl);
+
+ if (arg == error_mark_node
+ || decl == error_mark_node
+ || TREE_TYPE (arg) == error_mark_node
+ || decl_type == error_mark_node)
+ /* Something already went wrong. There's no need to check
+ further. */
+ return error_mark_node;
+
+ /* [dcl.fct.default]
+
+ A default argument expression is implicitly converted to the
+ parameter type. */
+ if (!TREE_TYPE (arg)
+ || !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
+ {
+ if (decl)
+ cp_error ("default argument for `%#D' has type `%T'",
+ decl, TREE_TYPE (arg));
+ else
+ cp_error ("default argument for paramter of type `%T' has type `%T'",
+ decl_type, TREE_TYPE (arg));
+
+ return error_mark_node;
+ }
+
+ /* [dcl.fct.default]
+
+ Local variables shall not be used in default argument
+ expressions.
+
+ The keyword `this' shall not be used in a default argument of a
+ member function. */
+ var = search_tree (arg, local_variable_p);
+ if (var)
+ {
+ cp_error ("default argument `%E' uses local variable `%D'",
+ arg, var);
+ return error_mark_node;
+ }
+
+ /* All is well. */
+ return arg;
+}
+
/* Decode the list of parameter types for a function type.
Given the list of things declared inside the parens,
return a list of types.
@@ -10725,9 +11929,13 @@ grokparms (first_parm, funcdef_flag)
TREE_PURPOSE (decl),
PARM, init != NULL_TREE,
NULL_TREE);
- if (! decl)
+ if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
- type = TREE_TYPE (decl);
+
+ /* Top-level qualifiers on the parameters are
+ ignored for function types. */
+ type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
+
if (TREE_CODE (type) == VOID_TYPE)
decl = void_type_node;
else if (TREE_CODE (type) == METHOD_TYPE)
@@ -10766,6 +11974,18 @@ grokparms (first_parm, funcdef_flag)
signature_error (decl, type);
any_error = 1; /* Seems like a good idea. */
}
+ else if (POINTER_TYPE_P (type))
+ {
+ tree t = type;
+ while (POINTER_TYPE_P (t)
+ || (TREE_CODE (t) == ARRAY_TYPE
+ && TYPE_DOMAIN (t) != NULL_TREE))
+ t = TREE_TYPE (t);
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ cp_error ("parameter type `%T' includes %s to array of unknown bound",
+ type,
+ TYPE_PTR_P (type) ? "pointer" : "reference");
+ }
}
if (TREE_CODE (decl) == VOID_TYPE)
@@ -10794,43 +12014,10 @@ grokparms (first_parm, funcdef_flag)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
#endif
- if (!any_error)
+ if (!any_error && init)
{
- if (init)
- {
- any_init++;
- if (TREE_CODE (init) == SAVE_EXPR)
- PARM_DECL_EXPR (init) = 1;
- else if (processing_template_decl)
- ;
- /* Unparsed default arg from in-class decl. */
- else if (TREE_CODE (init) == DEFAULT_ARG)
- ;
- else if (TREE_CODE (init) == VAR_DECL
- || TREE_CODE (init) == PARM_DECL)
- {
- if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
- {
- /* ``Local variables may not be used in default
- argument expressions.'' dpANSI C++ 8.2.6 */
- /* If extern int i; within a function is not
- considered a local variable, then this code is
- wrong. */
- cp_error ("local variable `%D' may not be used as a default argument", init);
- any_error = 1;
- }
- else if (TREE_READONLY_DECL_P (init))
- init = decl_constant_value (init);
- }
- else
- init = require_instantiated_type (type, init, integer_zero_node);
- if (! processing_template_decl
- && init != error_mark_node
- && TREE_CODE (init) != DEFAULT_ARG
- && ! can_convert_arg (type, TREE_TYPE (init), init))
- cp_pedwarn ("invalid type `%T' for default argument to `%#D'",
- TREE_TYPE (init), decl);
- }
+ any_init++;
+ init = check_default_argument (decl, init);
}
else
init = NULL_TREE;
@@ -10875,10 +12062,6 @@ grokparms (first_parm, funcdef_flag)
last_function_parms = decls;
- /* In a fcn definition, arg types must be complete. */
- if (funcdef_flag > 0)
- require_complete_types_for_parms (last_function_parms);
-
return result;
}
@@ -10943,19 +12126,45 @@ grok_ctor_properties (ctype, decl)
parmtype = TREE_VALUE (parmtypes);
}
+ /* [class.copy]
+
+ A non-template constructor for class X is a copy constructor if
+ its first parameter is of type X&, const X&, volatile X& or const
+ volatile X&, and either there are no other parameters or else all
+ other parameters have default arguments. */
if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
TYPE_HAS_INIT_REF (ctype) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
+ if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_INIT_REF (ctype) = 1;
}
+ /* [class.copy]
+
+ A declaration of a constructor for a class X is ill-formed if its
+ first parameter is of type (optionally cv-qualified) X and either
+ there are no other parameters or else all other parameters have
+ default arguments.
+
+ We *don't* complain about member template instantiations that
+ have this form, though; they can occur as we try to decide what
+ constructor to use during overload resolution. Since overload
+ resolution will never prefer such a constructor to the
+ non-template copy constructor (which is either explicitly or
+ implicitly defined), there's no need to worry about their
+ existence. Theoretically, they should never even be
+ instantiated, but that's hard to forestall. */
else if (TYPE_MAIN_VARIANT (parmtype) == ctype
- && TREE_CHAIN (parmtypes) != NULL_TREE
- && TREE_CHAIN (parmtypes) == void_list_node)
+ && (TREE_CHAIN (parmtypes) == NULL_TREE
+ || TREE_CHAIN (parmtypes) == void_list_node
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
@@ -10992,7 +12201,7 @@ unary_op_p (name)
return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
|| name == ansi_opname [(int) BIT_NOT_EXPR]
|| name == ansi_opname [(int) COMPONENT_REF]
- || OPERATOR_TYPENAME_P (name));
+ || IDENTIFIER_TYPENAME_P (name));
}
/* Do a little sanity-checking on how they declared their operator. */
@@ -11011,8 +12220,16 @@ grok_op_properties (decl, virtualp, friendp)
if (! friendp)
{
- if (name == ansi_opname[(int) MODIFY_EXPR])
- TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
+ /* [class.copy]
+
+ A user-declared copy assignment operator X::operator= is a
+ non-static non-template member function of class X with
+ exactly one parameter of type X, X&, const X&, volatile X& or
+ const volatile X&. */
+ if (name == ansi_opname[(int) MODIFY_EXPR]
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
+ ;
else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
else if (name == ansi_opname[(int) ARRAY_REF])
@@ -11075,7 +12292,7 @@ grok_op_properties (decl, virtualp, friendp)
an enumeration, or a reference to an enumeration. 13.4.0.6 */
if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
- if (OPERATOR_TYPENAME_P (name)
+ if (IDENTIFIER_TYPENAME_P (name)
|| name == ansi_opname[(int) CALL_EXPR]
|| name == ansi_opname[(int) MODIFY_EXPR]
|| name == ansi_opname[(int) COMPONENT_REF]
@@ -11121,7 +12338,7 @@ grok_op_properties (decl, virtualp, friendp)
else if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
- char *what = 0;
+ const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
@@ -11155,7 +12372,7 @@ grok_op_properties (decl, virtualp, friendp)
{
TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
if (TREE_CODE (parmtype) != REFERENCE_TYPE
- || TYPE_READONLY (TREE_TYPE (parmtype)))
+ || CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
}
}
@@ -11175,7 +12392,7 @@ grok_op_properties (decl, virtualp, friendp)
if ((name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR])
&& ! processing_template_decl
- && TREE_VALUE (TREE_CHAIN (argtypes)) != integer_type_node)
+ && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
cp_error ("postfix `%D' must take `int' as its argument",
@@ -11207,14 +12424,14 @@ grok_op_properties (decl, virtualp, friendp)
if (list_length (argtypes) == 2)
{
if (TREE_CODE (ret) != REFERENCE_TYPE
- || !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
- arg, 1))
+ || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
+ arg))
cp_warning ("prefix `%D' should return `%T'", decl,
build_reference_type (arg));
}
else
{
- if (!comptypes (TYPE_MAIN_VARIANT (ret), arg, 1))
+ if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
cp_warning ("postfix `%D' should return `%T'", decl, arg);
}
}
@@ -11276,6 +12493,27 @@ grok_op_properties (decl, virtualp, friendp)
}
}
+static const char *
+tag_name (code)
+ enum tag_types code;
+{
+ switch (code)
+ {
+ case record_type:
+ return "struct";
+ case class_type:
+ return "class";
+ case union_type:
+ return "union ";
+ case enum_type:
+ return "enum";
+ case signature_type:
+ return "signature";
+ default:
+ my_friendly_abort (981122);
+ }
+}
+
/* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
@@ -11287,18 +12525,19 @@ grok_op_properties (decl, virtualp, friendp)
scope.) */
tree
-xref_tag (code_type_node, name, binfo, globalize)
+xref_tag (code_type_node, name, globalize)
tree code_type_node;
- tree name, binfo;
+ tree name;
int globalize;
{
enum tag_types tag_code;
enum tree_code code;
int temp = 0;
register tree ref, t;
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
int got_type = 0;
tree attributes = NULL_TREE;
+ tree context = NULL_TREE;
/* If we are called from the parser, code_type_node will sometimes be a
TREE_LIST. This indicates that the user wrote
@@ -11338,37 +12577,41 @@ xref_tag (code_type_node, name, binfo, globalize)
}
else
t = IDENTIFIER_TYPE_VALUE (name);
+
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
&& TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM)
t = NULL_TREE;
if (! globalize)
{
- if (pedantic && t && (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM))
- {
- cp_pedwarn ("redeclaration of template type-parameter `%T'", name);
- cp_pedwarn_at (" previously declared here", t);
- }
- if (t && TYPE_CONTEXT (t) && got_type)
- ref = t;
- else
- {
- /* If we know we are defining this tag, only look it up in
- this scope and don't try to find it as a type. */
- ref = lookup_tag (code, name, b, 1);
- }
+ /* If we know we are defining this tag, only look it up in
+ this scope and don't try to find it as a type. */
+ ref = lookup_tag (code, name, b, 1);
}
else
{
if (t)
- ref = t;
- else
- ref = lookup_tag (code, name, b, 0);
+ {
+ /* [dcl.type.elab] If the identifier resolves to a
+ typedef-name or a template type-parameter, the
+ elaborated-type-specifier is ill-formed. */
+ if (t != TYPE_MAIN_VARIANT (t)
+ || (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t)))
+ cp_pedwarn ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (t), tag_name (tag_code));
+ else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ cp_error ("using template type parameter `%T' after `%s'",
+ t, tag_name (tag_code));
+ ref = t;
+ }
+ else
+ ref = lookup_tag (code, name, b, 0);
+
if (! ref)
{
- /* Try finding it as a type declaration. If that wins, use it. */
+ /* Try finding it as a type declaration. If that wins,
+ use it. */
ref = lookup_name (name, 1);
if (ref != NULL_TREE
@@ -11385,6 +12628,50 @@ xref_tag (code_type_node, name, binfo, globalize)
else
ref = NULL_TREE;
}
+
+ if (ref && current_class_type
+ && template_class_depth (current_class_type)
+ && PROCESSING_REAL_TEMPLATE_DECL_P ())
+ {
+ /* Since GLOBALIZE is non-zero, we are not looking at a
+ definition of this tag. Since, in addition, we are currently
+ processing a (member) template declaration of a template
+ class, we must be very careful; consider:
+
+ template <class X>
+ struct S1
+
+ template <class U>
+ struct S2
+ { template <class V>
+ friend struct S1; };
+
+ Here, the S2::S1 declaration should not be confused with the
+ outer declaration. In particular, the inner version should
+ have a template parameter of level 2, not level 1. This
+ would be particularly important if the member declaration
+ were instead:
+
+ template <class V = U> friend struct S1;
+
+ say, when we should tsubst into `U' when instantiating
+ S2. On the other hand, when presented with:
+
+ template <class T>
+ struct S1 {
+ template <class U>
+ struct S2 {};
+ template <class U>
+ friend struct S2;
+ };
+
+ we must find the inner binding eventually. We
+ accomplish this by making sure that the new type we
+ create to represent this declaration has the right
+ TYPE_CONTEXT. */
+ context = TYPE_CONTEXT (ref);
+ ref = NULL_TREE;
+ }
}
push_obstacks_nochange ();
@@ -11430,6 +12717,7 @@ xref_tag (code_type_node, name, binfo, globalize)
struct binding_level *old_b = class_binding_level;
ref = make_lang_type (code);
+ TYPE_CONTEXT (ref) = context;
if (tag_code == signature_type)
{
@@ -11466,9 +12754,6 @@ xref_tag (code_type_node, name, binfo, globalize)
redeclare_class_template (ref, current_template_parms);
}
- if (binfo)
- xref_basetypes (code_type_node, name, ref, binfo);
-
/* Until the type is defined, tentatively accept whatever
structure tag the user hands us. */
if (TYPE_SIZE (ref) == NULL_TREE
@@ -11505,9 +12790,15 @@ xref_tag_from_type (old, id, globalize)
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (code_type_node, id, NULL_TREE, globalize);
+ return xref_tag (code_type_node, id, globalize);
}
+/* REF is a type (named NAME), for which we have just seen some
+ baseclasses. BINFO is a list of those baseclasses; the
+ TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
+ the base-class. CODE_TYPE_NODE indicates whether REF is a class,
+ struct, or union. */
+
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
@@ -11517,6 +12808,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
/* In the declaration `A : X, Y, ... Z' we mark all the types
(A, X, Y, ..., Z) so we can check for duplicates. */
tree binfos;
+ tree base;
+
int i, len;
enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
@@ -11529,6 +12822,13 @@ xref_basetypes (code_type_node, name, ref, binfo)
len = list_length (binfo);
push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
+ /* First, make sure that any templates in base-classes are
+ instantiated. This ensures that if we call ourselves recursively
+ we do not get confused about which classes are marked and which
+ are not. */
+ for (base = binfo; base; base = TREE_CHAIN (base))
+ complete_type (TREE_VALUE (base));
+
SET_CLASSTYPE_MARKED (ref);
BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
@@ -11567,16 +12867,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
-#if 1
/* This code replaces similar code in layout_basetypes.
We put the complete_type first for implicit `typename'. */
- if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
+ if (TYPE_SIZE (basetype) == NULL_TREE
&& ! (current_template_parms && uses_template_parms (basetype)))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
}
-#endif
else
{
if (CLASSTYPE_MARKED (basetype))
@@ -11600,9 +12898,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
individual inheritance contains flags which say what
the `accessibility' of that particular inheritance is.) */
- base_binfo = make_binfo (integer_zero_node, basetype,
- TYPE_BINFO_VTABLE (basetype),
- TYPE_BINFO_VIRTUALS (basetype), NULL_TREE);
+ base_binfo
+ = make_binfo (integer_zero_node, basetype,
+ CLASS_TYPE_P (basetype)
+ ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
+ CLASS_TYPE_P (basetype)
+ ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
TREE_VEC_ELT (binfos, i) = base_binfo;
TREE_VIA_PUBLIC (base_binfo) = via_public;
@@ -11610,6 +12911,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
+ /* We need to unshare the binfos now so that lookups during class
+ definition work. */
+ unshare_base_binfos (base_binfo);
+
SET_CLASSTYPE_MARKED (basetype);
/* We are free to modify these bits because they are meaningless
@@ -11620,9 +12925,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
- TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
- TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
- CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
+ if (CLASS_TYPE_P (basetype))
+ {
+ TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+ TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+ }
+
i += 1;
}
}
@@ -11634,8 +12942,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
if (i > 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
else if (i == 1)
- TYPE_USES_MULTIPLE_INHERITANCE (ref)
- = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
+ {
+ tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, 0));
+
+ if (CLASS_TYPE_P (basetype))
+ TYPE_USES_MULTIPLE_INHERITANCE (ref)
+ = TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+ }
+
if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
@@ -11644,12 +12958,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
+ /* Now that we know all the base-classes, set up the list of virtual
+ bases. */
+ CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref);
+
pop_obstacks ();
}
-tree current_local_enum = NULL_TREE;
-
/* Begin compiling the definition of an enumeration type.
NAME is its name (or null if anonymous).
Returns the type object, as yet incomplete.
@@ -11661,15 +12977,11 @@ start_enum (name)
tree name;
{
register tree enumtype = NULL_TREE;
- struct binding_level *b = inner_binding_level;
+ struct binding_level *b = current_binding_level;
/* We are wasting space here and putting these on the permanent_obstack so
that typeid(local enum) will work correctly. */
-#if 0
- if (processing_template_decl && current_function_decl)
-#endif
-
- end_temporary_allocation ();
+ push_obstacks (&permanent_obstack, &permanent_obstack);
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
@@ -11686,14 +12998,9 @@ start_enum (name)
pushtag (name, enumtype, 0);
}
- if (b->pseudo_global)
- cp_error ("template declaration of `%#T'", enumtype);
-
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
- current_local_enum = NULL_TREE;
-
/* We don't copy this value because build_enumerator needs to do it. */
enum_next_value = integer_zero_node;
enum_overflow = 0;
@@ -11708,39 +13015,63 @@ start_enum (name)
Returns ENUMTYPE. */
tree
-finish_enum (enumtype, values)
- register tree enumtype, values;
+finish_enum (enumtype)
+ tree enumtype;
{
register tree minnode = NULL_TREE, maxnode = NULL_TREE;
/* Calculate the maximum value of any enumerator in this type. */
+ tree values = TYPE_VALUES (enumtype);
if (values)
{
- register tree pair;
- register tree value = DECL_INITIAL (TREE_VALUE (values));
+ tree pair;
- if (! processing_template_decl)
- {
- /* Speed up the main loop by performing some precalculations */
- TREE_TYPE (TREE_VALUE (values)) = enumtype;
- TREE_TYPE (value) = enumtype;
- minnode = maxnode = value;
- }
- TREE_VALUE (values) = value;
-
- for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
+ for (pair = values; pair; pair = TREE_CHAIN (pair))
{
- value = DECL_INITIAL (TREE_VALUE (pair));
- if (! processing_template_decl)
- {
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+ tree decl;
+ tree value;
+
+ /* The TREE_VALUE is a CONST_DECL for this enumeration
+ constant. */
+ decl = TREE_VALUE (pair);
+
+ /* The DECL_INITIAL will be NULL if we are processing a
+ template declaration and this enumeration constant had no
+ explicit initializer. */
+ value = DECL_INITIAL (decl);
+ if (value && !processing_template_decl)
+ {
+ /* Set the TREE_TYPE for the VALUE as well. That's so
+ that when we call decl_constant_value we get an
+ entity of the right type (but with the constant
+ value). Since we shouldn't ever call
+ decl_constant_value on a template type, there's no
+ reason to do that when processing_template_decl.
+ And, if the expression is something like a
+ TEMPLATE_PARM_INDEX or a CAST_EXPR doing so will
+ wreak havoc on the intended type of the expression.
+
+ Of course, there's also no point in trying to compute
+ minimum or maximum values if we're in a template. */
TREE_TYPE (value) = enumtype;
- if (tree_int_cst_lt (maxnode, value))
+
+ if (!minnode)
+ minnode = maxnode = value;
+ else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
}
- TREE_VALUE (pair) = value;
+
+ if (processing_template_decl)
+ /* If this is just a template, leave the CONST_DECL
+ alone. That way tsubst_copy will find CONST_DECLs for
+ CONST_DECLs, and not INTEGER_CSTs. */
+ ;
+ else
+ /* In the list we're building up, we want the enumeration
+ values, not the CONST_DECLs. */
+ TREE_VALUE (pair) = value;
}
}
else
@@ -11750,76 +13081,76 @@ finish_enum (enumtype, values)
if (processing_template_decl)
{
- if (current_function_decl)
- {
- add_tree (build_min (TAG_DEFN, enumtype));
- resume_temporary_allocation ();
- }
- return enumtype;
+ tree scope = current_scope ();
+ if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ add_tree (build_min (TAG_DEFN, enumtype));
}
+ else
+ {
+ int unsignedp = tree_int_cst_sgn (minnode) >= 0;
+ int lowprec = min_precision (minnode, unsignedp);
+ int highprec = min_precision (maxnode, unsignedp);
+ int precision = MAX (lowprec, highprec);
+ tree tem;
- {
- int unsignedp = tree_int_cst_sgn (minnode) >= 0;
- int lowprec = min_precision (minnode, unsignedp);
- int highprec = min_precision (maxnode, unsignedp);
- int precision = MAX (lowprec, highprec);
-
- TYPE_SIZE (enumtype) = NULL_TREE;
-
- /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
+ TYPE_SIZE (enumtype) = NULL_TREE;
- TYPE_PRECISION (enumtype) = precision;
- if (unsignedp)
- fixup_unsigned_type (enumtype);
- else
- fixup_signed_type (enumtype);
+ /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
- if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
- /* Use the width of the narrowest normal C type which is wide enough. */
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
- (precision, 1));
- else
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+ TYPE_PRECISION (enumtype) = precision;
+ if (unsignedp)
+ fixup_unsigned_type (enumtype);
+ else
+ fixup_signed_type (enumtype);
- TYPE_SIZE (enumtype) = 0;
- layout_type (enumtype);
- }
+ if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
+ /* Use the width of the narrowest normal C type which is wide
+ enough. */
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
+ (precision, 1));
+ else
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
- {
- register tree tem;
+ TYPE_SIZE (enumtype) = 0;
+ layout_type (enumtype);
- /* Fix up all variant types of this enum type. */
- for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
- tem = TYPE_NEXT_VARIANT (tem))
- {
- TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
- TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
- TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
- TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
- TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (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);
- }
- }
+ /* Fix up all variant types of this enum type. */
+ for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
+ tem = TYPE_NEXT_VARIANT (tem))
+ {
+ TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
+ TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
+ TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
+ TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+ TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (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. */
- rest_of_type_compilation (enumtype, namespace_bindings_p ());
+ /* Finish debugging output for this type. */
+ rest_of_type_compilation (enumtype, namespace_bindings_p ());
+ }
+
+ /* In start_enum we pushed obstacks. Here, we must pop them. */
+ pop_obstacks ();
return enumtype;
}
-/* Build and install a CONST_DECL for one value of the
- current enumeration type (one that was begun with start_enum).
- Return a tree-list containing the name and its value.
+/* Build and install a CONST_DECL for an enumeration constant of the
+ enumeration type TYPE whose NAME and VALUE (if any) are provided.
Assignment of sequential values by default is handled here. */
tree
-build_enumerator (name, value)
- tree name, value;
+build_enumerator (name, value, type)
+ tree name;
+ tree value;
+ tree type;
{
tree decl, result;
+ tree context;
/* Remove no-op casts from the value. */
if (value)
@@ -11856,41 +13187,43 @@ build_enumerator (name, value)
/* Remove no-op casts from the value. */
if (value)
STRIP_TYPE_NOPS (value);
-
- /* We have to always copy here; not all INTEGER_CSTs are unshared,
- and there's no wedding ring. Look at size_int()...*/
- value = copy_node (value);
#if 0
/* To fix MAX_VAL enum consts. (bkoz) */
TREE_TYPE (value) = integer_type_node;
#endif
}
- /* C++ associates enums with global, function, or class declarations. */
-
- decl = current_scope ();
- if (decl && decl == current_class_type)
- {
- /* This enum declaration is local to the class, so we must put
- it in that class's list of decls. */
- decl = build_lang_field_decl (CONST_DECL, name, integer_type_node);
- DECL_INITIAL (decl) = value;
- TREE_READONLY (decl) = 1;
- pushdecl_class_level (decl);
- TREE_CHAIN (decl) = current_local_enum;
- current_local_enum = decl;
- }
- else
- {
- /* It's a global enum, or it's local to a function. (Note local to
- a function could mean local to a class method. */
- decl = build_decl (CONST_DECL, name, integer_type_node);
- DECL_INITIAL (decl) = value;
- TREE_READONLY (decl) = 1;
+ /* We always have to copy here; not all INTEGER_CSTs are unshared.
+ Even in other cases, we will later (in finish_enum) be setting the
+ type of VALUE. */
+ if (value != NULL_TREE)
+ value = copy_node (value);
- pushdecl (decl);
- GNU_xref_decl (current_function_decl, decl);
- }
+ /* C++ associates enums with global, function, or class declarations. */
+
+ context = current_scope ();
+ if (context && context == current_class_type)
+ /* This enum declaration is local to the class. */
+ decl = build_lang_field_decl (CONST_DECL, name, type);
+ else
+ /* It's a global enum, or it's local to a function. (Note local to
+ a function could mean local to a class method. */
+ decl = build_decl (CONST_DECL, name, type);
+
+ DECL_CONTEXT (decl) = FROB_CONTEXT (context);
+ DECL_INITIAL (decl) = value;
+ TREE_READONLY (decl) = 1;
+
+ if (context && context == current_class_type)
+ /* In something like `struct S { enum E { i = 7 }; };' we put `i'
+ on the TYPE_FIELDS list for `S'. (That's so that you can say
+ things like `S::i' later.) */
+ finish_member_declaration (decl);
+ else
+ {
+ pushdecl (decl);
+ GNU_xref_decl (current_function_decl, decl);
+ }
if (! processing_template_decl)
{
@@ -11904,30 +13237,6 @@ build_enumerator (name, value)
return result;
}
-tree
-grok_enum_decls (decl)
- tree decl;
-{
- tree d = current_local_enum;
-
- if (d == NULL_TREE)
- return decl;
-
- while (1)
- {
- if (TREE_CHAIN (d) == NULL_TREE)
- {
- TREE_CHAIN (d) = decl;
- break;
- }
- d = TREE_CHAIN (d);
- }
-
- decl = current_local_enum;
- current_local_enum = NULL_TREE;
-
- return decl;
-}
static int function_depth;
@@ -11936,6 +13245,15 @@ static int function_depth;
they describe the function's name and the type it returns,
but twisted together in a fashion that parallels the syntax of C.
+ If PRE_PARSED_P is non-zero then DECLARATOR is really the DECL for
+ the function we are about to process; DECLSPECS are ignored. For
+ example, we set PRE_PARSED_P when processing the definition of
+ inline function that was defined in-class; the definition is
+ actually processed when the class is complete. In this case,
+ PRE_PARSED_P is 2. We also set PRE_PARSED_P when instanting the
+ body of a template function, and when constructing thunk functions
+ and such; in these cases PRE_PARSED_P is 1.
+
This function creates a binding context for the function body
as well as setting up the FUNCTION_DECL in current_function_decl.
@@ -11972,7 +13290,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
/* Assume, until we see it does. */
current_function_returns_value = 0;
current_function_returns_null = 0;
- warn_about_return_type = 0;
named_labels = 0;
shadowed_labels = 0;
current_function_assigns_this = 0;
@@ -12037,17 +13354,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
doing_friend = 1;
}
- /* In a fcn definition, arg types must be complete. */
- require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
-
- /* In case some arg types were completed since the declaration was
- parsed, fix up the decls. */
- {
- tree t = DECL_ARGUMENTS (decl1);
- for (; t; t = TREE_CHAIN (t))
- layout_decl (t, 0);
- }
-
last_function_parms = DECL_ARGUMENTS (decl1);
last_function_parm_tags = NULL_TREE;
}
@@ -12061,8 +13367,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
fntype = TREE_TYPE (decl1);
restype = TREE_TYPE (fntype);
- if (IS_AGGR_TYPE (restype) && ! TYPE_PTRMEMFUNC_P (restype)
- && ! CLASSTYPE_GOT_SEMICOLON (restype))
+ if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
{
cp_error ("semicolon missing after declaration of `%#T'", restype);
shadow_tag (build_expr_list (NULL_TREE, restype));
@@ -12088,7 +13393,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
pedwarn ("return type for `main' changed to `int'");
TREE_TYPE (decl1) = fntype = default_function_type;
}
- warn_about_return_type = 0;
}
}
@@ -12098,16 +13402,37 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
+ announce_function (decl1);
+
+ /* Set up current_class_type, and enter the scope of the class, if
+ appropriate. */
+ if (ctype)
+ push_nested_class (ctype, 1);
+ else if (DECL_STATIC_FUNCTION_P (decl1))
+ push_nested_class (DECL_CONTEXT (decl1), 2);
+
+ /* Now that we have entered the scope of the class, we must restore
+ the bindings for any template parameters surrounding DECL1, if it
+ is an inline member template. (Order is important; consider the
+ case where a template parameter has the same name as a field of
+ the class.) It is not until after this point that
+ PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly. */
+ if (pre_parsed_p == 2)
+ maybe_begin_member_template_processing (decl1);
+
+ /* We are now in the scope of the function being defined. */
current_function_decl = decl1;
+
/* Save the parm names or decls from this function's declarator
where store_parm_decls will find them. */
current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags;
- announce_function (decl1);
-
if (! processing_template_decl)
{
+ /* In a function definition, arg types must be complete. */
+ require_complete_types_for_parms (current_function_parms);
+
if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
{
cp_error ("return-type `%#T' is an incomplete type",
@@ -12128,8 +13453,10 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
TYPE_ARG_TYPES (TREE_TYPE (decl1)));
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
- TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype));
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype));
+ TREE_READONLY (DECL_RESULT (decl1))
+ = CP_TYPE_CONST_P (TREE_TYPE (fntype));
+ TREE_THIS_VOLATILE (DECL_RESULT (decl1))
+ = CP_TYPE_VOLATILE_P (TREE_TYPE (fntype));
}
if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
@@ -12137,9 +13464,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
- if (warn_about_return_type)
- pedwarn ("return-type defaults to `int'");
-
/* Effective C++ rule 15. See also c_expand_return. */
if (warn_ecpp
&& DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
@@ -12150,17 +13474,25 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
error_mark_node is replaced below (in poplevel) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
+#endif
+
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
+ /* We must call push_template_decl after current_class_type is set
+ up. (If we are processing inline definitions after exiting a
+ class scope, current_class_type will be NULL_TREE until set above
+ by push_nested_class.) */
+ if (processing_template_decl)
+ decl1 = push_template_decl (decl1);
+
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
-
- if (processing_template_decl)
- decl1 = push_template_decl (decl1);
- else if (pre_parsed_p == 0)
+ if (!processing_template_decl && pre_parsed_p == 0)
{
/* A specialization is not used to guide overload resolution. */
if ((flag_guiding_decls
@@ -12196,21 +13528,41 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
}
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
- It doesn't matter whether it's inline or not. */
+ This only affects inlines and template instantiations. */
else if (interface_unknown == 0
&& (! DECL_TEMPLATE_INSTANTIATION (decl1)
|| flag_alt_external_templates))
{
if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
- DECL_EXTERNAL (decl1)
- = (interface_only
- || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
+ {
+ DECL_EXTERNAL (decl1)
+ = (interface_only
+ || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines
+ && !DECL_VINDEX (decl1)));
+
+ /* For WIN32 we also want to put these in linkonce sections. */
+ maybe_make_one_only (decl1);
+ }
else
DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
+ else if (interface_unknown && interface_only
+ && (! DECL_TEMPLATE_INSTANTIATION (decl1)
+ || flag_alt_external_templates))
+ {
+ /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
+ interface, we will have interface_only set but not
+ interface_known. In that case, we don't want to use the normal
+ heuristics because someone will supply a #pragma implementation
+ elsewhere, and deducing it here would produce a conflict. */
+ comdat_linkage (decl1);
+ DECL_EXTERNAL (decl1) = 0;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ DECL_DEFER_OUTPUT (decl1) = 1;
+ }
else
{
/* This is a definition, not a reference.
@@ -12240,8 +13592,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (ctype)
{
- push_nested_class (ctype, 1);
-
/* If we're compiling a friend function, neither of the variables
current_class_ptr nor current_class_type will have values. */
if (! doing_friend)
@@ -12258,13 +13608,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
{
- int i = suspend_momentary ();
+ int i;
- /* Fool build_indirect_ref. */
+ if (! hack_decl_function_context (decl1))
+ temporary_allocation ();
+ i = suspend_momentary ();
+
+ /* Normally, build_indirect_ref returns
+ current_class_ref whenever current_class_ptr is
+ dereferenced. This time, however, we want it to
+ *create* current_class_ref, so we temporarily clear
+ current_class_ptr to fool it. */
current_class_ptr = NULL_TREE;
current_class_ref = build_indirect_ref (t, NULL_PTR);
current_class_ptr = t;
+
resume_momentary (i);
+ if (! hack_decl_function_context (decl1))
+ end_temporary_allocation ();
}
else
/* We're having a signature pointer here. */
@@ -12273,13 +13634,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
}
}
else
- {
- if (DECL_STATIC_FUNCTION_P (decl1))
- push_nested_class (DECL_CONTEXT (decl1), 2);
- else
- push_memoized_context (0, 1);
- current_class_ptr = current_class_ref = NULL_TREE;
- }
+ current_class_ptr = current_class_ref = NULL_TREE;
pushlevel (0);
current_binding_level->parm_flag = 1;
@@ -12288,6 +13643,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (attrs)
cplus_decl_attributes (decl1, NULL_TREE, attrs);
+
make_function_rtl (decl1);
/* Promote the value to int before returning it. */
@@ -12303,8 +13659,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
{
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
- TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (restype);
- TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype);
+ TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype);
+ TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype);
}
/* Allocate further tree nodes temporarily during compilation
@@ -12381,9 +13737,6 @@ store_parm_decls ()
/* Initialize RTL machinery. */
init_function_start (fndecl, input_filename, lineno);
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
- declare_function_name ();
-
/* Create a binding level for the parms. */
expand_start_bindings (0);
@@ -12469,6 +13822,9 @@ store_parm_decls ()
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
+ /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
+ declare_function_name ();
+
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = NULL_RTX;
if (! processing_template_decl)
@@ -12579,18 +13935,23 @@ store_return_init (return_id, init)
This is called after parsing the body of the function definition.
LINENO is the current line number.
- C++: CALL_POPLEVEL is non-zero if an extra call to poplevel
- (and expand_end_bindings) must be made to take care of the binding
- contour for the base initializers. This is only relevant for
- constructors.
+ FLAGS is a bitwise or of the following values:
+ 1 - CALL_POPLEVEL
+ An extra call to poplevel (and expand_end_bindings) must be
+ made to take care of the binding contour for the base
+ initializers. This is only relevant for constructors.
+ 2 - INCLASS_INLINE
+ We just finished processing the body of an in-class inline
+ function definition. (This processing will have taken place
+ after the class definition is complete.)
NESTED is nonzero if we were in the middle of compiling another function
when we started on this one. */
void
-finish_function (lineno, call_poplevel, nested)
+finish_function (lineno, flags, nested)
int lineno;
- int call_poplevel;
+ int flags;
int nested;
{
register tree fndecl = current_function_decl;
@@ -12599,13 +13960,16 @@ finish_function (lineno, call_poplevel, nested)
/* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE;
tree decls = NULL_TREE;
+ int call_poplevel = (flags & 1) != 0;
+ int inclass_inline = (flags & 2) != 0;
+ int in_template;
/* When we get some parse errors, we can end up without a
current_function_decl, so cope. */
if (fndecl == NULL_TREE)
return;
- if (! nested && function_depth > 1)
+ if (function_depth > 1)
nested = 1;
fntype = TREE_TYPE (fndecl);
@@ -12698,7 +14062,8 @@ finish_function (lineno, call_poplevel, nested)
pointer to represent the type of our base class. */
/* This side-effect makes call to `build_delete' generate the
- code we have to have at the end of this destructor. */
+ code we have to have at the end of this destructor.
+ `build_delete' will set the flag again. */
TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
/* These are two cases where we cannot delegate deletion. */
@@ -12757,8 +14122,6 @@ finish_function (lineno, call_poplevel, nested)
expand_end_cond ();
}
- TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
-
virtual_size = c_sizeof (current_class_type);
/* At the end, call delete if that's what's requested. */
@@ -12792,7 +14155,7 @@ finish_function (lineno, call_poplevel, nested)
/* End of destructor. */
expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0);
- poplevel (2, 0, 0); /* XXX change to 1 */
+ poplevel (getdecls () != NULL_TREE, 0, 0);
/* Back to the top of destructor. */
/* Don't execute destructor code if `this' is NULL. */
@@ -12822,7 +14185,7 @@ finish_function (lineno, call_poplevel, nested)
if (! ok_to_optimize_dtor)
{
cond = build_binary_op (NE_EXPR,
- current_class_ptr, integer_zero_node, 1);
+ current_class_ptr, integer_zero_node);
expand_start_cond (cond, 0);
}
@@ -12877,12 +14240,10 @@ finish_function (lineno, call_poplevel, nested)
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
- DECL_RETURNS_FIRST_ARG (fndecl) = 1;
-
if (flag_this_is_variable > 0)
{
cond = build_binary_op (EQ_EXPR,
- current_class_ptr, integer_zero_node, 1);
+ current_class_ptr, integer_zero_node);
thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
build_new (NULL_TREE, current_class_type, void_type_node, 0));
}
@@ -13005,6 +14366,20 @@ finish_function (lineno, call_poplevel, nested)
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
}
+
+ /* If we're processing a template, squirrel away the definition
+ until we do an instantiation. */
+ if (processing_template_decl)
+ {
+ --minimal_parse_mode;
+ DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
+ /* We have to save this value here in case
+ maybe_end_member_template_processing decides to pop all the
+ template parameters. */
+ in_template = 1;
+ }
+ else
+ in_template = 0;
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
@@ -13013,6 +14388,13 @@ finish_function (lineno, call_poplevel, nested)
my_friendly_abort (122);
poplevel (1, 0, 1);
+ /* If this is a in-class inline definition, we may have to pop the
+ bindings for the template parameters that we added in
+ maybe_begin_member_template_processing when start_function was
+ called. */
+ if (inclass_inline)
+ maybe_end_member_template_processing ();
+
/* Reset scope for C++: if we were in the scope of a class,
then when we finish this function, we are not longer so.
This cannot be done until we know for sure that no more
@@ -13021,10 +14403,8 @@ finish_function (lineno, call_poplevel, nested)
if (current_class_name)
{
ctype = current_class_type;
- pop_nested_class (1);
+ pop_nested_class ();
}
- else
- pop_memoized_context (1);
/* Must mark the RESULT_DECL as being in this function. */
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
@@ -13033,7 +14413,7 @@ finish_function (lineno, call_poplevel, nested)
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
- if (! processing_template_decl)
+ if (!in_template)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
@@ -13117,12 +14497,6 @@ finish_function (lineno, call_poplevel, nested)
/* Free all the tree nodes making up this function. */
/* Switch back to allocating nodes permanently
until we start another function. */
- if (processing_template_decl)
- {
- --minimal_parse_mode;
- DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
- }
-
if (! nested)
permanent_allocation (1);
@@ -13157,8 +14531,6 @@ finish_function (lineno, call_poplevel, nested)
}
/* Create the FUNCTION_DECL for a function definition.
- LINE1 is the line number that the definition absolutely begins on.
- LINE2 is the line number that the name of the function appears on.
DECLSPECS and DECLARATOR are the parts of the declaration;
they describe the return type and the name of the function,
but twisted together in a fashion that parallels the syntax of C.
@@ -13180,11 +14552,11 @@ finish_function (lineno, call_poplevel, nested)
CHANGES TO CODE IN `grokfield'. */
tree
-start_method (declspecs, declarator)
- tree declarator, declspecs;
+start_method (declspecs, declarator, attrlist)
+ tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
- NULL_TREE);
+ attrlist);
/* Something too ugly to handle. */
if (fndecl == NULL_TREE)
@@ -13213,12 +14585,15 @@ start_method (declspecs, declarator)
return void_type_node;
}
+ check_template_shadow (fndecl);
+
DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
- if (processing_template_decl)
+ /* We process method specializations in finish_struct_1. */
+ if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
fndecl = push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack,
@@ -13293,23 +14668,11 @@ finish_method (decl)
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
+ pop_binding (DECL_NAME (link), link);
my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE;
}
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
-
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag,
@@ -13390,7 +14753,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
tree decl, auto_delete;
{
tree type = TREE_TYPE (decl);
- if (TYPE_NEEDS_DESTRUCTOR (type))
+ if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
{
int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
@@ -13467,38 +14830,30 @@ cplus_expand_expr_stmt (exp)
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
- if (TREE_TYPE (exp) == unknown_type_node)
+ exp = require_complete_type_in_void (exp);
+
+ if (TREE_CODE (exp) == FUNCTION_DECL)
{
- if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
- error ("address of overloaded function with no contextual type information");
- else if (TREE_CODE (exp) == COMPONENT_REF)
- warning ("useless reference to a member function name, did you forget the ()?");
+ cp_warning ("reference, not call, to function `%D'", exp);
+ warning ("at this point in file");
}
- else
- {
- if (TREE_CODE (exp) == FUNCTION_DECL)
- {
- cp_warning ("reference, not call, to function `%D'", exp);
- warning ("at this point in file");
- }
#if 0
- /* We should do this eventually, but right now this causes regex.o from
- libg++ to miscompile, and tString to core dump. */
- exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+ /* We should do this eventually, but right now this causes regex.o from
+ libg++ to miscompile, and tString to core dump. */
+ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
#endif
- /* Strip unused implicit INDIRECT_REFs of references. */
- if (TREE_CODE (exp) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
- exp = TREE_OPERAND (exp, 0);
+ /* Strip unused implicit INDIRECT_REFs of references. */
+ if (TREE_CODE (exp) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
+ exp = TREE_OPERAND (exp, 0);
- /* If we don't do this, we end up down inside expand_expr
- trying to do TYPE_MODE on the ERROR_MARK, and really
- go outside the bounds of the type. */
- if (exp != error_mark_node)
- expand_expr_stmt (break_out_cleanups (exp));
- }
+ /* If we don't do this, we end up down inside expand_expr
+ trying to do TYPE_MODE on the ERROR_MARK, and really
+ go outside the bounds of the type. */
+ if (exp != error_mark_node)
+ expand_expr_stmt (break_out_cleanups (exp));
/* Clean up any pending cleanups. This happens when a function call
returns a cleanup-needing value that nobody uses. */
@@ -13547,15 +14902,14 @@ revert_static_member_fn (decl, fn, argtypes)
tree function = fn ? *fn : TREE_TYPE (*decl);
tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
- if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (args))))
- cp_error ("static member function `%#D' declared const", *decl);
- if (TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (args))))
- cp_error ("static member function `%#D' declared volatile", *decl);
+ if (CP_TYPE_QUALS (TREE_TYPE (TREE_VALUE (args)))
+ != TYPE_UNQUALIFIED)
+ cp_error ("static member function `%#D' declared with type qualifiers",
+ *decl);
args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args);
- tmp = build_type_variant (tmp, TYPE_READONLY (function),
- TYPE_VOLATILE (function));
+ tmp = build_qualified_type (tmp, CP_TYPE_QUALS (function));
tmp = build_exception_variant (tmp,
TYPE_RAISES_EXCEPTIONS (function));
TREE_TYPE (*decl) = tmp;
@@ -13568,23 +14922,16 @@ revert_static_member_fn (decl, fn, argtypes)
*argtypes = args;
}
-int
-id_in_current_class (id)
- tree id;
-{
- return !!purpose_member (id, class_binding_level->class_shadowed);
-}
-
struct cp_function
{
int returns_value;
int returns_null;
- int warn_about_return_type;
int assigns_this;
int just_assigned_this;
int parms_stored;
int temp_name_counter;
tree named_labels;
+ struct named_label_list *named_label_uses;
tree shadowed_labels;
tree ctor_label;
tree dtor_label;
@@ -13621,10 +14968,10 @@ push_cp_function_context (context)
cp_function_chain = p;
p->named_labels = named_labels;
+ p->named_label_uses = named_label_uses;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
- p->warn_about_return_type = warn_about_return_type;
p->binding_level = current_binding_level;
p->ctor_label = ctor_label;
p->dtor_label = dtor_label;
@@ -13663,10 +15010,10 @@ pop_cp_function_context (context)
cp_function_chain = p->next;
named_labels = p->named_labels;
+ named_label_uses = p->named_label_uses;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
- warn_about_return_type = p->warn_about_return_type;
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;
diff --git a/contrib/gcc/cp/decl.h b/contrib/gcc/cp/decl.h
index f55dca5..fcb247e 100644
--- a/contrib/gcc/cp/decl.h
+++ b/contrib/gcc/cp/decl.h
@@ -42,11 +42,6 @@ extern tree this_identifier, in_charge_identifier;
or a chain or parameter decls here. */
extern tree last_function_parms;
-/* A list of static class variables. This is needed, because a
- static class variable can be declared inside the class without
- an initializer, and then initialized, staticly, outside the class. */
-extern tree pending_statics;
-
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
the TREE_VALUE slot and the initializer is stored
diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c
index c87c607..84f491f 100644
--- a/contrib/gcc/cp/decl2.c
+++ b/contrib/gcc/cp/decl2.c
@@ -1,5 +1,5 @@
/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -42,26 +42,60 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "dwarf2out.h"
#include "dwarfout.h"
+#include "splay-tree.h"
+#include "varray.h"
#if USE_CPPLIB
#include "cpplib.h"
extern cpp_reader parse_in;
-extern cpp_options parse_options;
-static int cpp_initialized;
#endif
+/* This structure contains information about the initializations
+ and/or destructions required for a particular priority level. */
+typedef struct priority_info_s {
+ /* A label indicating where we should generate the next
+ initialization with this priority. */
+ rtx initialization_sequence;
+ /* A label indicating where we should generate the next destruction
+ with this priority. */
+ rtx destruction_sequence;
+ /* Non-zero if there have been any initializations at this priority
+ throughout the translation unit. */
+ int initializations_p;
+ /* Non-zero if there have been any destructions at this priority
+ throughout the translation unit. */
+ int destructions_p;
+} *priority_info;
+
static tree get_sentry PROTO((tree));
static void mark_vtable_entries PROTO((tree));
static void grok_function_init PROTO((tree, tree));
-static int finish_vtable_vardecl PROTO((tree, tree));
-static int prune_vtable_vardecl PROTO((tree, tree));
-static void finish_sigtable_vardecl PROTO((tree, tree));
+static int finish_vtable_vardecl PROTO((tree *, void *));
+static int prune_vtable_vardecl PROTO((tree *, void *));
+static int finish_sigtable_vardecl PROTO((tree *, void *));
static int is_namespace_ancestor PROTO((tree, tree));
static void add_using_namespace PROTO((tree, tree, int));
static tree ambiguous_decl PROTO((tree, tree, tree,int));
static tree build_anon_union_vars PROTO((tree, tree*, int, int));
-static void check_decl_namespace PROTO((void));
-
+static int acceptable_java_type PROTO((tree));
+static void output_vtable_inherit PROTO((tree));
+static void start_objects PROTO((int, int));
+static void finish_objects PROTO((int, int));
+static tree merge_functions PROTO((tree, tree));
+static tree decl_namespace PROTO((tree));
+static tree validate_nonmember_using_decl PROTO((tree, tree *, tree *));
+static void do_nonmember_using_decl PROTO((tree, tree, tree, tree,
+ tree *, tree *));
+static void start_static_storage_duration_function PROTO((void));
+static int generate_inits_for_priority PROTO((splay_tree_node, void *));
+static void finish_static_storage_duration_function PROTO((void));
+static priority_info get_priority_info PROTO((int));
+static void do_static_initialization PROTO((tree, tree, tree, int));
+static void do_static_destruction PROTO((tree, tree, int));
+static void do_static_initialization_and_destruction PROTO((tree, tree));
+static void generate_ctor_or_dtor_function PROTO((int, int));
+static int generate_ctor_and_dtor_functions_for_priority
+ PROTO((splay_tree_node, void *));
extern int current_class_depth;
/* A list of virtual function tables we must make sure to write out. */
@@ -70,11 +104,13 @@ tree pending_vtables;
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
an initializer, and then initialized, staticly, outside the class. */
-tree pending_statics;
+static varray_type pending_statics;
+static size_t pending_statics_used;
/* A list of functions which were declared inline, but which we
may need to emit outline anyway. */
-static tree saved_inlines;
+static varray_type saved_inlines;
+static size_t saved_inlines_used;
/* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */
@@ -144,10 +180,6 @@ int flag_traditional;
int flag_signed_bitfields = 1;
-/* Nonzero means handle `#ident' directives. 0 means ignore them. */
-
-int flag_no_ident;
-
/* Nonzero means enable obscure ANSI features and disable GNU extensions
that might cause ANSI-compliant code to be miscompiled. */
@@ -173,6 +205,12 @@ int flag_alt_external_templates;
int flag_implicit_templates = 1;
+/* Nonzero means that implicit instantiations of inline templates will be
+ emitted if needed, even if instantiations of non-inline templates
+ aren't. */
+
+int flag_implicit_inline_templates = 1;
+
/* Nonzero means warn about implicit declarations. */
int warn_implicit = 1;
@@ -203,9 +241,13 @@ int flag_use_repository;
int flag_optional_diags = 1;
-/* Nonzero means give string constants the type `const char *'
- to get extra warnings from them. These warnings will be too numerous
- to be useful, except in thoroughly ANSIfied programs. */
+/* Nonzero means give string constants the type `const char *', as mandated
+ by the standard. */
+
+int flag_const_strings = 1;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+ `char *'. */
int warn_write_strings;
@@ -295,6 +337,15 @@ int warn_unknown_pragmas; /* Tri state variable. */
int warn_multichar = 1;
+/* Nonzero means warn when non-templatized friend functions are
+ declared within a template */
+
+int warn_nontemplate_friend = 1;
+
+/* Nonzero means complain about deprecated features. */
+
+int warn_deprecated = 1;
+
/* Nonzero means `$' can be in an identifier. */
#ifndef DOLLARS_IN_IDENTIFIERS
@@ -318,40 +369,22 @@ int flag_labels_ok;
int flag_detailed_statistics;
/* C++ specific flags. */
-/* Nonzero for -fall-virtual: make every member function (except
- constructors) lay down in the virtual function table. Calls
- can then either go through the virtual function table or not,
- depending. */
-
-int flag_all_virtual;
-
/* Zero means that `this' is a *const. This gives nice behavior in the
2.0 world. 1 gives 1.2-compatible behavior. 2 gives Spring behavior.
-2 means we're constructing an object and it has fixed type. */
int flag_this_is_variable;
-/* Nonzero means memoize our member lookups. */
-
-int flag_memoize_lookups; int flag_save_memoized_contexts;
-
/* 3 means write out only virtuals function tables `defined'
in this implementation file.
- 2 means write out only specific virtual function tables
- and give them (C) public access.
- 1 means write out virtual function tables and give them
- (C) public access.
0 means write out virtual function tables and give them
- (C) static access (default).
- -1 means declare virtual function tables extern. */
+ (C) static access (default). */
int write_virtuals;
-/* Nonzero means we should attempt to elide constructors when possible.
- FIXME: This flag is obsolete, and should be torn out along with the
- old overloading code. */
+/* Nonzero means we should attempt to elide constructors when possible. */
-int flag_elide_constructors;
+int flag_elide_constructors = 1;
/* Nonzero means recognize and handle signature language constructs. */
@@ -362,11 +395,6 @@ int flag_handle_signatures;
int flag_default_inline = 1;
-/* Controls whether enums and ints freely convert.
- 1 means with complete freedom.
- 0 means enums can convert to ints, but not vice-versa. */
-int flag_int_enum_equivalence;
-
/* Controls whether compiler generates 'type descriptor' that give
run-time type information. */
int flag_rtti = 1;
@@ -375,18 +403,6 @@ int flag_rtti = 1;
for the GNU class browser. */
extern int flag_gnu_xref;
-/* Nonzero if compiler can make `reasonable' assumptions about
- references and objects. For example, the compiler must be
- conservative about the following and not assume that `a' is nonnull:
-
- obj &a = g ();
- a.f (2);
-
- In general, it is `reasonable' to assume that for many programs,
- and better code can be generated in that case. */
-
-int flag_assume_nonnull_objects = 1;
-
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
objects. */
@@ -453,6 +469,14 @@ int flag_guiding_decls;
and class qualifiers. */
int flag_do_squangling;
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
+
+int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+ The value of this flag is ignored if -pedantic is specified. */
+
+int flag_permissive;
/* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable.
@@ -460,8 +484,10 @@ int flag_do_squangling;
if `-fSTRING' is seen as an option.
(If `-fno-STRING' is seen as an option, the opposite value is stored.) */
-static struct { char *string; int *variable; int on_value;} lang_f_options[] =
+static struct { const char *string; int *variable; int on_value;}
+lang_f_options[] =
{
+ /* C/C++ options. */
{"signed-char", &flag_signed_char, 1},
{"unsigned-char", &flag_signed_char, 0},
{"signed-bitfields", &flag_signed_bitfields, 1},
@@ -469,41 +495,42 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"short-enums", &flag_short_enums, 1},
{"short-double", &flag_short_double, 1},
{"cond-mismatch", &flag_cond_mismatch, 1},
- {"squangle", &flag_do_squangling, 1},
{"asm", &flag_no_asm, 0},
{"builtin", &flag_no_builtin, 0},
- {"ident", &flag_no_ident, 0},
- {"labels-ok", &flag_labels_ok, 1},
- {"stats", &flag_detailed_statistics, 1},
- {"this-is-variable", &flag_this_is_variable, 1},
- {"strict-prototype", &flag_strict_prototype, 1},
- {"all-virtual", &flag_all_virtual, 1},
- {"memoize-lookups", &flag_memoize_lookups, 1},
+
+ /* C++-only options. */
+ {"access-control", &flag_access_control, 1},
+ {"check-new", &flag_check_new, 1},
+ {"conserve-space", &flag_conserve_space, 1},
+ {"const-strings", &flag_const_strings, 1},
+ {"default-inline", &flag_default_inline, 1},
+ {"dollars-in-identifiers", &dollars_in_ident, 1},
{"elide-constructors", &flag_elide_constructors, 1},
+ {"external-templates", &flag_external_templates, 1},
+ {"for-scope", &flag_new_for_scope, 2},
+ {"gnu-keywords", &flag_no_gnu_keywords, 0},
{"handle-exceptions", &flag_exceptions, 1},
{"handle-signatures", &flag_handle_signatures, 1},
- {"default-inline", &flag_default_inline, 1},
- {"dollars-in-identifiers", &dollars_in_ident, 1},
- {"enum-int-equiv", &flag_int_enum_equivalence, 1},
{"honor-std", &flag_honor_std, 1},
- {"rtti", &flag_rtti, 1},
- {"xref", &flag_gnu_xref, 1},
- {"nonnull-objects", &flag_assume_nonnull_objects, 1},
+ {"huge-objects", &flag_huge_objects, 1},
{"implement-inlines", &flag_implement_inlines, 1},
- {"external-templates", &flag_external_templates, 1},
+ {"implicit-inline-templates", &flag_implicit_inline_templates, 1},
{"implicit-templates", &flag_implicit_templates, 1},
- {"huge-objects", &flag_huge_objects, 1},
- {"conserve-space", &flag_conserve_space, 1},
- {"vtable-thunks", &flag_vtable_thunks, 1},
- {"access-control", &flag_access_control, 1},
+ {"labels-ok", &flag_labels_ok, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
- {"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1},
{"optional-diags", &flag_optional_diags, 1},
- {"check-new", &flag_check_new, 1},
+ {"permissive", &flag_permissive, 1},
{"repo", &flag_use_repository, 1},
- {"for-scope", &flag_new_for_scope, 2},
- {"weak", &flag_weak, 1}
+ {"rtti", &flag_rtti, 1},
+ {"squangle", &flag_do_squangling, 1},
+ {"stats", &flag_detailed_statistics, 1},
+ {"strict-prototype", &flag_strict_prototype, 1},
+ {"this-is-variable", &flag_this_is_variable, 1},
+ {"vtable-gc", &flag_vtable_gc, 1},
+ {"vtable-thunks", &flag_vtable_thunks, 1},
+ {"weak", &flag_weak, 1},
+ {"xref", &flag_gnu_xref, 1}
};
/* Decode the string P as a language-specific option.
@@ -512,44 +539,24 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
int
lang_decode_option (argc, argv)
- int argc;
+ int argc
+#if !USE_CPPLIB
+ ATTRIBUTE_UNUSED
+#endif
+ ;
char **argv;
{
int strings_processed;
char *p = argv[0];
#if USE_CPPLIB
- if (! cpp_initialized)
- {
- cpp_reader_init (&parse_in);
- parse_in.data = &parse_options;
- cpp_options_init (&parse_options);
- cpp_initialized = 1;
- }
strings_processed = cpp_handle_option (&parse_in, argc, argv);
#else
strings_processed = 0;
#endif /* ! USE_CPPLIB */
if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- flag_writable_strings = 1,
- flag_this_is_variable = 1, flag_new_for_scope = 0;
- /* The +e options are for cfront compatibility. They come in as
- `-+eN', to kludge around gcc.c's argument handling. */
- else if (p[0] == '-' && p[1] == '+' && p[2] == 'e')
- {
- int old_write_virtuals = write_virtuals;
- if (p[3] == '1')
- write_virtuals = 1;
- else if (p[3] == '0')
- write_virtuals = -1;
- else if (p[3] == '2')
- write_virtuals = 2;
- else error ("invalid +e option");
- if (old_write_virtuals != 0
- && write_virtuals != old_write_virtuals)
- error ("conflicting +e options given");
- }
+ /* ignore */;
else if (p[0] == '-' && p[1] == 'f')
{
/* Some kind of -f option.
@@ -565,16 +572,24 @@ lang_decode_option (argc, argv)
|| !strcmp (p, "no-handle-exceptions"))
warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
- if (!strcmp (p, "save-memoized"))
+ if (!strcmp (p, "memoize-lookups")
+ || !strcmp (p, "no-memoize-lookups")
+ || !strcmp (p, "save-memoized")
+ || !strcmp (p, "no-save-memoized")
+ || !strcmp (p, "no-all-virtual")
+ || !strcmp (p, "no-enum-int-equiv")
+ || !strcmp (p, "nonnull-objects")
+ || !strcmp (p, "ansi-overloading"))
{
- flag_memoize_lookups = 1;
- flag_save_memoized_contexts = 1;
+ /* ignore */
found = 1;
}
- else if (!strcmp (p, "no-save-memoized"))
+ else if (!strcmp (p, "all-virtual")
+ || !strcmp (p, "enum-int-equiv")
+ || !strcmp (p, "no-nonnull-objects")
+ || !strcmp (p, "no-ansi-overloading"))
{
- flag_memoize_lookups = 0;
- flag_save_memoized_contexts = 0;
+ warning ("-f%s is no longer supported", p);
found = 1;
}
else if (! strcmp (p, "alt-external-templates"))
@@ -582,6 +597,7 @@ lang_decode_option (argc, argv)
flag_external_templates = 1;
flag_alt_external_templates = 1;
found = 1;
+ cp_deprecated ("-falt-external-templates");
}
else if (! strcmp (p, "no-alt-external-templates"))
{
@@ -605,13 +621,24 @@ lang_decode_option (argc, argv)
flag_guiding_decls = 0;
found = 1;
}
- else if (!strcmp (p, "ansi-overloading"))
- found = 1;
- else if (!strcmp (p, "no-ansi-overloading"))
- {
- error ("-fno-ansi-overloading is no longer supported");
- found = 1;
- }
+ else if (!strcmp (p, "this-is-variable"))
+ {
+ flag_this_is_variable = 1;
+ found = 1;
+ cp_deprecated ("-fthis-is-variable");
+ }
+ else if (!strcmp (p, "external-templates"))
+ {
+ flag_external_templates = 1;
+ found = 1;
+ cp_deprecated ("-fexternal-templates");
+ }
+ else if (!strcmp (p, "handle-signatures"))
+ {
+ flag_handle_signatures = 1;
+ found = 1;
+ cp_deprecated ("-fhandle-signatures");
+ }
else if (!strcmp (p, "new-abi"))
{
flag_new_abi = 1;
@@ -627,35 +654,13 @@ lang_decode_option (argc, argv)
}
else if (!strncmp (p, "template-depth-", 15))
{
- char *endp = p + 15;
- while (*endp)
- {
- if (*endp >= '0' && *endp <= '9')
- endp++;
- else
- {
- error ("Invalid option `%s'", p - 2);
- goto template_depth_lose;
- }
- }
- max_tinst_depth = atoi (p + 15);
- template_depth_lose: ;
+ max_tinst_depth =
+ read_integral_parameter (p + 15, p - 2, max_tinst_depth);
}
else if (!strncmp (p, "name-mangling-version-", 22))
{
- char *endp = p + 22;
- while (*endp)
- {
- if (*endp >= '0' && *endp <= '9')
- endp++;
- else
- {
- error ("Invalid option `%s'", p - 2);
- goto mangling_version_lose;
- }
- }
- name_mangling_version = atoi (p + 22);
- mangling_version_lose: ;
+ name_mangling_version =
+ read_integral_parameter (p + 22, p - 2, name_mangling_version);
}
else for (j = 0;
!found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]);
@@ -741,6 +746,10 @@ lang_decode_option (argc, argv)
/* Set to greater than 1, so that even unknown pragmas in
system headers will be warned about. */
warn_unknown_pragmas = setting * 2;
+ else if (!strcmp (p, "non-template-friend"))
+ warn_nontemplate_friend = setting;
+ else if (!strcmp (p, "deprecated"))
+ warn_deprecated = setting;
else if (!strcmp (p, "comment"))
; /* cpp handles this one. */
else if (!strcmp (p, "comments"))
@@ -754,25 +763,26 @@ lang_decode_option (argc, argv)
warn_return_type = setting;
warn_unused = setting;
warn_implicit = setting;
- warn_ctor_dtor_privacy = setting;
warn_switch = setting;
warn_format = setting;
warn_parentheses = setting;
warn_missing_braces = setting;
warn_sign_compare = setting;
- warn_extern_inline = setting;
- warn_nonvdtor = setting;
warn_multichar = setting;
/* We save the value of warn_uninitialized, since if they put
-Wuninitialized on the command line, we need to generate a
warning about not using it without also specifying -O. */
if (warn_uninitialized != 1)
warn_uninitialized = (setting ? 2 : 0);
- warn_reorder = setting;
- warn_sign_promo = setting;
/* Only warn about unknown pragmas that are not in system
headers. */
- warn_unknown_pragmas = 1;
+ warn_unknown_pragmas = 1;
+
+ /* C++-specific warnings. */
+ warn_ctor_dtor_privacy = setting;
+ warn_nonvdtor = setting;
+ warn_reorder = setting;
+ warn_nontemplate_friend = setting;
}
else return strings_processed;
}
@@ -802,36 +812,27 @@ grok_method_quals (ctype, function, quals)
{
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
+ int type_quals = TYPE_UNQUALIFIED;
+ int dup_quals = TYPE_UNQUALIFIED;
do
{
- extern tree ridpointers[];
-
- if (TREE_VALUE (quals) == ridpointers[(int)RID_CONST])
- {
- if (TYPE_READONLY (ctype))
- error ("duplicate `%s' %s",
- IDENTIFIER_POINTER (TREE_VALUE (quals)),
- (TREE_CODE (function) == FUNCTION_DECL
- ? "for member function" : "in type declaration"));
- ctype = build_type_variant (ctype, 1, TYPE_VOLATILE (ctype));
- build_pointer_type (ctype);
- }
- else if (TREE_VALUE (quals) == ridpointers[(int)RID_VOLATILE])
- {
- if (TYPE_VOLATILE (ctype))
- error ("duplicate `%s' %s",
- IDENTIFIER_POINTER (TREE_VALUE (quals)),
- (TREE_CODE (function) == FUNCTION_DECL
- ? "for member function" : "in type declaration"));
- ctype = build_type_variant (ctype, TYPE_READONLY (ctype), 1);
- build_pointer_type (ctype);
- }
+ int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
+
+ if (type_quals & tq)
+ dup_quals |= tq;
else
- my_friendly_abort (20);
+ type_quals |= tq;
quals = TREE_CHAIN (quals);
- }
+ }
while (quals);
+
+ if (dup_quals != TYPE_UNQUALIFIED)
+ cp_error ("duplicate type qualifiers in %s declaration",
+ TREE_CODE (function) == FUNCTION_DECL
+ ? "member function" : "type");
+
+ ctype = cp_build_qualified_type (ctype, type_quals);
fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
@@ -878,121 +879,34 @@ warn_if_unknown_interface (decl)
/* A subroutine of the parser, to handle a component list. */
-tree
-grok_x_components (specs, components)
- tree specs, components;
+void
+grok_x_components (specs)
+ tree specs;
{
- register tree t, x, tcode;
-
- /* We just got some friends. They have been recorded elsewhere. */
- if (components == void_type_node)
- return NULL_TREE;
-
- if (components == NULL_TREE)
- {
- t = groktypename (build_decl_list (specs, NULL_TREE));
-
- if (t == NULL_TREE)
- {
- error ("error in component specification");
- return NULL_TREE;
- }
-
- switch (TREE_CODE (t))
- {
- case VAR_DECL:
- /* Static anonymous unions come out as VAR_DECLs. */
- if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
- return t;
-
- /* We return SPECS here, because in the parser it was ending
- up with not doing anything to $$, which is what SPECS
- represents. */
- return specs;
- break;
-
- case RECORD_TYPE:
- /* This code may be needed for UNION_TYPEs as
- well. */
- tcode = record_type_node;
- if (CLASSTYPE_DECLARED_CLASS (t))
- tcode = class_type_node;
- else if (IS_SIGNATURE (t))
- tcode = signature_type_node;
-
- if (CLASSTYPE_IS_TEMPLATE (t))
- /* In this case, the TYPE_IDENTIFIER will be something
- like S<T>, rather than S, so to get the correct name we
- look at the template. */
- x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
- else
- x = TYPE_IDENTIFIER (t);
-
- t = xref_tag (tcode, x, NULL_TREE, 0);
- return NULL_TREE;
- break;
+ struct pending_inline **p;
+ tree t;
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- if (TREE_CODE (t) == UNION_TYPE)
- tcode = union_type_node;
- else
- tcode = enum_type_node;
+ specs = strip_attrs (specs);
- t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
- if (ANON_UNION_TYPE_P (t))
- {
- /* See also shadow_tag. */
-
- struct pending_inline **p;
- tree *q;
- x = build_lang_field_decl (FIELD_DECL, NULL_TREE, t);
-
- /* Wipe out memory of synthesized methods */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
- TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
- TYPE_HAS_INIT_REF (t) = 0;
- TYPE_HAS_CONST_INIT_REF (t) = 0;
- TYPE_HAS_ASSIGN_REF (t) = 0;
- TYPE_HAS_ASSIGNMENT (t) = 0;
- TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
-
- q = &TYPE_METHODS (t);
- while (*q)
- {
- if (DECL_ARTIFICIAL (*q))
- *q = TREE_CHAIN (*q);
- else
- q = &TREE_CHAIN (*q);
- }
- if (TYPE_METHODS (t))
- error ("an anonymous union cannot have function members");
+ check_tag_decl (specs);
+ t = groktypename (build_decl_list (specs, NULL_TREE));
- p = &pending_inlines;
- for (; *p; *p = (*p)->next)
- if (DECL_CONTEXT ((*p)->fndecl) != t)
- break;
- }
- else if (TREE_CODE (t) == ENUMERAL_TYPE)
- x = grok_enum_decls (NULL_TREE);
- else
- x = NULL_TREE;
- return x;
- break;
+ /* The only case where we need to do anything additional here is an
+ anonymous union field, e.g.: `struct S { union { int i; }; };'. */
+ if (t == NULL_TREE || !ANON_UNION_TYPE_P (t))
+ return;
- default:
- if (t != void_type_node)
- error ("empty component declaration");
- return NULL_TREE;
- }
- }
- else
- /* There may or may not be any enum decls to grok, but
- grok_enum_decls will just return components, if there aren't
- any. We used to try to figure out whether or not there were
- any enum decls based on the type of components, but that's too
- hard; it might be something like `enum { a } *p;'. */
- return grok_enum_decls (components);
+ fixup_anonymous_union (t);
+ finish_member_declaration (build_lang_field_decl (FIELD_DECL,
+ NULL_TREE,
+ t));
+
+ /* Ignore any inline function definitions in the anonymous union
+ since an anonymous union may not have function members. */
+ p = &pending_inlines;
+ for (; *p; *p = (*p)->next)
+ if (DECL_CONTEXT ((*p)->fndecl) != t)
+ break;
}
/* Constructors for types with virtual baseclasses need an "in-charge" flag
@@ -1067,8 +981,8 @@ maybe_retrofit_in_chrg (fn)
QUALS are the qualifiers for the this pointer. */
void
-grokclassfn (ctype, cname, function, flags, quals)
- tree ctype, cname, function;
+grokclassfn (ctype, function, flags, quals)
+ tree ctype, function;
enum overload_flags flags;
tree quals;
{
@@ -1132,16 +1046,7 @@ grokclassfn (ctype, cname, function, flags, quals)
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
- {
- if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
- /* Only true for static member functions. */
- arg_types = hash_tree_chain (build_pointer_type (qualtype),
- arg_types);
-
- DECL_ASSEMBLER_NAME (function)
- = build_decl_overload (fn_name, arg_types,
- 1 + DECL_CONSTRUCTOR_P (function));
- }
+ set_mangled_name_for_decl (function);
}
/* Work on the expr used by alignof (this is only called by the parser). */
@@ -1157,7 +1062,7 @@ grok_alignof (expr)
return build_min (ALIGNOF_EXPR, sizetype, expr);
if (TREE_CODE (expr) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
error ("`__alignof__' applied to a bit-field");
if (TREE_CODE (expr) == INDIRECT_REF)
@@ -1223,7 +1128,9 @@ grok_array_decl (array_expr, index_exp)
return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
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. It
+ is a little-known fact that, if `a' is an array and `i' is an
+ int, you can write `i[a]', which means the same thing as `a[i]'. */
if (TREE_CODE (type) == ARRAY_TYPE)
p1 = array_expr;
@@ -1302,7 +1209,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
if (doing_vec == 2)
{
- maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
+ maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node);
pedwarn ("anachronistic use of array size in vector delete");
}
@@ -1317,6 +1224,10 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return error_mark_node;
}
+ /* Deleting ptr to void is undefined behaviour [expr.delete/3]. */
+ if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
+ cp_warning ("`%T' is not a pointer-to-object type", type);
+
/* An array can't have been allocated by new, so complain. */
if (TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
@@ -1329,7 +1240,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
if (doing_vec)
return build_vec_delete (t, maxindex, integer_one_node,
- integer_two_node, use_global_delete);
+ integer_zero_node, use_global_delete);
else
{
if (IS_AGGR_TYPE (TREE_TYPE (type))
@@ -1392,7 +1303,7 @@ check_member_template (tmpl)
/* Return true iff TYPE is a valid Java parameter or return type. */
-int
+static int
acceptable_java_type (type)
tree type;
{
@@ -1403,8 +1314,22 @@ acceptable_java_type (type)
type = TREE_TYPE (type);
if (TREE_CODE (type) == RECORD_TYPE)
{
- complete_type (type);
- return TYPE_FOR_JAVA (type);
+ tree args; int i;
+ if (! TYPE_FOR_JAVA (type))
+ return 0;
+ if (! CLASSTYPE_TEMPLATE_INFO (type))
+ return 1;
+ args = CLASSTYPE_TI_ARGS (type);
+ i = TREE_VEC_LENGTH (args);
+ while (--i >= 0)
+ {
+ type = TREE_VEC_ELT (args, i);
+ if (TREE_CODE (type) == POINTER_TYPE)
+ type = TREE_TYPE (type);
+ if (! TYPE_FOR_JAVA (type))
+ return 0;
+ }
+ return 1;
}
}
return 0;
@@ -1415,8 +1340,8 @@ acceptable_java_type (type)
Otherwise, print appropriate error messages, and return 0. */
int
-check_java_method (ctype, method)
- tree ctype, method;
+check_java_method (method)
+ tree method;
{
int jerr = 0;
tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
@@ -1453,8 +1378,21 @@ check_classfn (ctype, function)
tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0;
tree *end = 0;
- tree templates = NULL_TREE;
-
+
+ if (DECL_USE_TEMPLATE (function)
+ && is_member_template (DECL_TI_TEMPLATE (function)))
+ /* Since this is a specialization of a member template,
+ we're not going to find the declaration in the class.
+ For example, in:
+
+ struct S { template <typename T> void f(T); };
+ template <> void S::f(int);
+
+ we're not going to find `S::f(int)', but there's no
+ reason we should, either. We let our callers know we didn't
+ find the method, but we don't complain. */
+ return NULL_TREE;
+
if (method_vec != 0)
{
methods = &TREE_VEC_ELT (method_vec, 0);
@@ -1468,7 +1406,7 @@ check_classfn (ctype, function)
&& DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
goto got_it;
- while (++methods != end)
+ while (++methods != end && *methods)
{
fndecl = *methods;
if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
@@ -1478,14 +1416,19 @@ check_classfn (ctype, function)
fndecls = OVL_NEXT (fndecls))
{
fndecl = OVL_CURRENT (fndecls);
- /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
+ /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL, or
+ for a for member function of a template class, is
not mangled, so the check below does not work
- correctly in that case. Since mangled destructor names
- do not include the type of the arguments, we
- can't use this short-cut for them, either. */
- if (TREE_CODE (function) != TEMPLATE_DECL
- && TREE_CODE (fndecl) != TEMPLATE_DECL
- && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
+ correctly in that case. Since mangled destructor
+ names do not include the type of the arguments,
+ we can't use this short-cut for them, either.
+ (It's not legal to declare arguments for a
+ destructor, but some people try.) */
+ if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
+ && (DECL_ASSEMBLER_NAME (function)
+ != DECL_NAME (function))
+ && (DECL_ASSEMBLER_NAME (fndecl)
+ != DECL_NAME (fndecl))
&& (DECL_ASSEMBLER_NAME (function)
== DECL_ASSEMBLER_NAME (fndecl)))
return fndecl;
@@ -1505,48 +1448,23 @@ check_classfn (ctype, function)
&& TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
p1 = TREE_CHAIN (p1);
- if (comptypes (TREE_TYPE (TREE_TYPE (function)),
- TREE_TYPE (TREE_TYPE (fndecl)), 1)
- && compparms (p1, p2, 3)
+ if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
+ TREE_TYPE (TREE_TYPE (fndecl)))
+ && compparms (p1, p2)
&& (DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TEMPLATE_SPECIALIZATION (fndecl))
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
|| (DECL_TI_TEMPLATE (function)
== DECL_TI_TEMPLATE (fndecl))))
return fndecl;
-
- if (is_member_template (fndecl))
- /* This function might be an instantiation
- or specialization of fndecl. */
- templates =
- scratch_tree_cons (NULL_TREE, fndecl, templates);
}
}
break; /* loser */
}
- else if (TREE_CODE (fndecl) == TEMPLATE_DECL
- && IDENTIFIER_TYPENAME_P (DECL_NAME (fndecl))
- && IDENTIFIER_TYPENAME_P (fn_name))
- /* The method in the class is a member template
- conversion operator. We are declaring another
- conversion operator. It is possible that even though
- the names don't match, there is some specialization
- occurring. */
- templates =
- scratch_tree_cons (NULL_TREE, fndecl, templates);
}
}
- if (templates)
- /* This function might be an instantiation or a specialization.
- We should verify that this is possible. If it is, we must
- somehow add the new declaration to the method vector for the
- class. Perhaps we should use add_method? For now, we simply
- return NULL_TREE, which lets the caller know that this
- function is new, but we don't print an error message. */
- return NULL_TREE;
-
- if (methods != end)
+ if (methods != end && *methods)
{
tree fndecl = *methods;
cp_error ("prototype for `%#D' does not match any in class `%T'",
@@ -1559,16 +1477,86 @@ check_classfn (ctype, function)
else
{
methods = 0;
- cp_error ("no `%#D' member function declared in class `%T'",
- function, ctype);
+ if (TYPE_SIZE (ctype) == 0)
+ incomplete_type_error (function, ctype);
+ else
+ cp_error ("no `%#D' member function declared in class `%T'",
+ function, ctype);
}
/* If we did not find the method in the class, add it to avoid
- spurious errors. */
- add_method (ctype, methods, function);
+ spurious errors (unless the CTYPE is not yet defined, in which
+ case we'll only confuse ourselves when the function is declared
+ properly within the class. */
+ if (TYPE_SIZE (ctype))
+ add_method (ctype, methods, function);
return NULL_TREE;
}
+/* We have just processed the DECL, which is a static data member.
+ Its initializer, if present, is INIT. The ASMSPEC_TREE, if
+ present, is the assembly-language name for the data member.
+ NEED_POP and FLAGS are as for cp_finish_decl. */
+
+void
+finish_static_data_member_decl (decl, init, asmspec_tree, need_pop, flags)
+ tree decl;
+ tree init;
+ tree asmspec_tree;
+ int need_pop;
+ int flags;
+{
+ char* asmspec = 0;
+
+ if (asmspec_tree)
+ asmspec = TREE_STRING_POINTER (asmspec_tree);
+
+ my_friendly_assert (TREE_PUBLIC (decl), 0);
+
+ /* We cannot call pushdecl here, because that would fill in the
+ decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do
+ the right thing, namely, to put this decl out straight away. */
+ /* current_class_type can be NULL_TREE in case of error. */
+ if (!asmspec && current_class_type)
+ {
+ DECL_INITIAL (decl) = error_mark_node;
+ DECL_ASSEMBLER_NAME (decl)
+ = build_static_name (current_class_type, DECL_NAME (decl));
+ }
+ if (! processing_template_decl)
+ {
+ if (!pending_statics)
+ VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
+
+ if (pending_statics_used == pending_statics->num_elements)
+ VARRAY_GROW (pending_statics,
+ 2 * pending_statics->num_elements);
+ VARRAY_TREE (pending_statics, pending_statics_used) = decl;
+ ++pending_statics_used;
+ }
+
+ /* Static consts need not be initialized in the class definition. */
+ if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ {
+ static int explanation = 0;
+
+ error ("initializer invalid for static member with constructor");
+ if (explanation++ == 0)
+ error ("(you really want to initialize it separately)");
+ init = 0;
+ }
+ /* Force the compiler to know when an uninitialized static const
+ member is being used. */
+ if (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0)
+ TREE_USED (decl) = 1;
+ DECL_INITIAL (decl) = init;
+ DECL_IN_AGGR_P (decl) = 1;
+ DECL_CONTEXT (decl) = current_class_type;
+ DECL_CLASS_CONTEXT (decl) = current_class_type;
+
+ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags);
+}
+
/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
QUALS is a list of type qualifiers for this decl (such as for declaring
@@ -1618,7 +1606,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
;
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
- pop_nested_class (1);
+ pop_nested_class ();
return do_class_using_decl (declarator);
}
@@ -1628,9 +1616,10 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
- value = grokdeclarator (declarator, declspecs, FIELD, init != 0, NULL_TREE);
- if (! value)
- return value; /* friend or constructor went bad. */
+ value = grokdeclarator (declarator, declspecs, FIELD, init != 0, attrlist);
+ if (! value || value == error_mark_node)
+ /* friend or constructor went bad. */
+ return value;
/* Pass friendly classes back. */
if (TREE_CODE (value) == VOID_TYPE)
@@ -1648,15 +1637,14 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
DECL_CLASS_CONTEXT (value) = current_class_type;
- CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1;
/* Now that we've updated the context, we need to remangle the
name for this TYPE_DECL. */
DECL_ASSEMBLER_NAME (value) = DECL_NAME (value);
- DECL_ASSEMBLER_NAME (value) =
- get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
+ if (!uses_template_parms (value))
+ DECL_ASSEMBLER_NAME (value) =
+ get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
- pushdecl_class_level (value);
return value;
}
@@ -1669,8 +1657,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
if (DECL_IN_AGGR_P (value))
{
- cp_error ("`%D' is already defined in the class %T", value,
- DECL_CONTEXT (value));
+ cp_error ("`%D' is already defined in `%T'", value,
+ DECL_CONTEXT (value));
return void_type_node;
}
@@ -1748,44 +1736,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
if (TREE_CODE (value) == VAR_DECL)
{
- my_friendly_assert (TREE_PUBLIC (value), 0);
-
- /* We cannot call pushdecl here, because that would
- fill in the value of our TREE_CHAIN. Instead, we
- modify cp_finish_decl to do the right thing, namely, to
- put this decl out straight away. */
- /* current_class_type can be NULL_TREE in case of error. */
- if (asmspec == 0 && current_class_type)
- {
- TREE_PUBLIC (value) = 1;
- DECL_INITIAL (value) = error_mark_node;
- DECL_ASSEMBLER_NAME (value)
- = build_static_name (current_class_type, DECL_NAME (value));
- }
- if (! processing_template_decl)
- pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
-
- /* Static consts need not be initialized in the class definition. */
- if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
- {
- static int explanation = 0;
-
- error ("initializer invalid for static member with constructor");
- if (explanation++ == 0)
- error ("(you really want to initialize it separately)");
- init = 0;
- }
- /* Force the compiler to know when an uninitialized static
- const member is being used. */
- if (TYPE_READONLY (value) && init == 0)
- TREE_USED (value) = 1;
- DECL_INITIAL (value) = init;
- DECL_IN_AGGR_P (value) = 1;
- DECL_CONTEXT (value) = current_class_type;
- DECL_CLASS_CONTEXT (value) = current_class_type;
-
- cp_finish_decl (value, init, asmspec_tree, 1, flags);
- pushdecl_class_level (value);
+ finish_static_data_member_decl (value, init, asmspec_tree,
+ /*need_pop=*/1, flags);
return value;
}
if (TREE_CODE (value) == FIELD_DECL)
@@ -1855,6 +1807,17 @@ grokbitfield (declarator, declspecs, width)
return NULL_TREE;
}
+ /* Usually, finish_struct_1 catches bitifields with invalid types.
+ But, in the case of bitfields with function type, we confuse
+ ourselves into thinking they are member functions, so we must
+ check here. */
+ if (TREE_CODE (value) == FUNCTION_DECL)
+ {
+ cp_error ("cannot declare bitfield `%D' with funcion type",
+ DECL_NAME (value));
+ return NULL_TREE;
+ }
+
if (IS_SIGNATURE (current_class_type))
{
error ("field declaration not allowed in signature");
@@ -1881,7 +1844,7 @@ grokbitfield (declarator, declspecs, width)
{
constant_expression_warning (width);
DECL_INITIAL (value) = width;
- DECL_BIT_FIELD (value) = 1;
+ SET_DECL_C_BIT_FIELD (value);
}
DECL_IN_AGGR_P (value) = 1;
@@ -1934,7 +1897,7 @@ grokoptypename (declspecs, declarator)
int
copy_assignment_arg_p (parmtype, virtualp)
tree parmtype;
- int virtualp;
+ int virtualp ATTRIBUTE_UNUSED;
{
if (current_class_type == NULL_TREE)
return 0;
@@ -2093,28 +2056,14 @@ mark_inline_for_output (decl)
return;
my_friendly_assert (TREE_PERMANENT (decl), 363);
DECL_SAVED_INLINE (decl) = 1;
-#if 0
- if (DECL_PENDING_INLINE_INFO (decl) != 0
- && ! DECL_PENDING_INLINE_INFO (decl)->deja_vu)
- {
- struct pending_inline *t = pending_inlines;
- my_friendly_assert (DECL_SAVED_INSNS (decl) == 0, 198);
- while (t)
- {
- if (t == DECL_PENDING_INLINE_INFO (decl))
- break;
- t = t->next;
- }
- if (t == 0)
- {
- t = DECL_PENDING_INLINE_INFO (decl);
- t->next = pending_inlines;
- pending_inlines = t;
- }
- DECL_PENDING_INLINE_INFO (decl) = 0;
- }
-#endif
- saved_inlines = perm_tree_cons (NULL_TREE, decl, saved_inlines);
+ if (!saved_inlines)
+ VARRAY_TREE_INIT (saved_inlines, 32, "saved_inlines");
+
+ if (saved_inlines_used == saved_inlines->num_elements)
+ VARRAY_GROW (saved_inlines,
+ 2 * saved_inlines->num_elements);
+ VARRAY_TREE (saved_inlines, saved_inlines_used) = decl;
+ ++saved_inlines_used;
}
void
@@ -2198,7 +2147,7 @@ get_temp_regvar (type, init)
returns a VAR_DECL whose size is the same as the size of the
ANON_DECL, if one is available. */
-tree
+static tree
build_anon_union_vars (anon_decl, elems, static_p, external_p)
tree anon_decl;
tree* elems;
@@ -2214,8 +2163,15 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
field = TREE_CHAIN (field))
{
tree decl;
- if (TREE_CODE (field) != FIELD_DECL)
+
+ if (DECL_ARTIFICIAL (field))
continue;
+ if (TREE_CODE (field) != FIELD_DECL)
+ {
+ cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
+ field);
+ continue;
+ }
if (TREE_PRIVATE (field))
cp_pedwarn_at ("private member `%#D' in anonymous union", field);
@@ -2229,6 +2185,8 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
if (!decl)
continue;
}
+ else if (DECL_NAME (field) == NULL_TREE)
+ continue;
else
{
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
@@ -2297,18 +2255,16 @@ finish_anon_union (anon_union_decl)
main_decl = build_anon_union_vars (anon_union_decl, &elems,
static_p, external_p);
+ if (main_decl == NULL_TREE)
+ {
+ warning ("anonymous union with no members");
+ return;
+ }
+
if (static_p)
{
- if (main_decl)
- {
- make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
- DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
- }
- else
- {
- warning ("anonymous union with no members");
- return;
- }
+ make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
+ DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
}
/* The following call assumes that there are never any cleanups
@@ -2326,7 +2282,7 @@ finish_anon_union (anon_union_decl)
void
finish_builtin_type (type, name, fields, len, align_type)
tree type;
- char *name;
+ const char *name;
tree fields[];
int len;
tree align_type;
@@ -2365,15 +2321,14 @@ coerce_new_type (type)
if (TREE_CODE (type) == METHOD_TYPE)
type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type)));
- if (TREE_TYPE (type) != ptr_type_node)
+ if (! same_type_p (TREE_TYPE (type), ptr_type_node))
e1 = 1, error ("`operator new' must return type `void *'");
/* Technically the type must be `size_t', but we may not know
what that is. */
if (TYPE_ARG_TYPES (type) == NULL_TREE)
e1 = 1, error ("`operator new' takes type `size_t' parameter");
- else if (TREE_CODE (TREE_VALUE (TYPE_ARG_TYPES (type))) != INTEGER_TYPE
- || TYPE_PRECISION (TREE_VALUE (TYPE_ARG_TYPES (type))) != TYPE_PRECISION (sizetype))
+ else if (! same_type_p (TREE_VALUE (TYPE_ARG_TYPES (type)), sizetype))
e2 = 1, error ("`operator new' takes type `size_t' as first parameter");
if (e2)
type = build_function_type (ptr_type_node, tree_cons (NULL_TREE, sizetype, TREE_CHAIN (TYPE_ARG_TYPES (type))));
@@ -2402,7 +2357,7 @@ coerce_delete_type (type)
e1 = 1, error ("`operator delete' must return type `void'");
if (arg_types == NULL_TREE
- || TREE_VALUE (arg_types) != ptr_type_node)
+ || ! same_type_p (TREE_VALUE (arg_types), ptr_type_node))
e2 = 1, error ("`operator delete' takes type `void *' as first parameter");
#if 0
@@ -2413,8 +2368,7 @@ coerce_delete_type (type)
/* Again, technically this argument must be `size_t', but again
we may not know what that is. */
tree t2 = TREE_VALUE (TREE_CHAIN (arg_types));
- if (TREE_CODE (t2) != INTEGER_TYPE
- || TYPE_PRECISION (t2) != TYPE_PRECISION (sizetype))
+ if (! same_type_p (t2, sizetype))
e3 = 1, error ("second argument to `operator delete' must be of type `size_t'");
else if (TREE_CHAIN (TREE_CHAIN (arg_types)) != void_list_node)
{
@@ -2456,21 +2410,19 @@ mark_vtable_entries (decl)
{
tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
- if (flag_rtti)
- {
- tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (TREE_CHAIN (entries))
- : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
- tree fn = TREE_OPERAND (fnaddr, 0);
- TREE_ADDRESSABLE (fn) = 1;
- mark_used (fn);
- }
- skip_rtti_stuff (&entries);
-
for (; entries; entries = TREE_CHAIN (entries))
{
- tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries)
- : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
- tree fn = TREE_OPERAND (fnaddr, 0);
+ tree fnaddr;
+ tree fn;
+
+ fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries)
+ : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
+
+ if (TREE_CODE (fnaddr) == NOP_EXPR)
+ /* RTTI offset. */
+ continue;
+
+ fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1;
if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
{
@@ -2496,8 +2448,30 @@ comdat_linkage (decl)
{
if (flag_weak)
make_decl_one_only (decl);
- else
+ else if (TREE_CODE (decl) == FUNCTION_DECL || DECL_VIRTUAL_P (decl))
+ /* We can just emit functions and vtables statically; it doesn't really
+ matter if we have multiple copies. */
TREE_PUBLIC (decl) = 0;
+ else
+ {
+ /* Static data member template instantiations, however, cannot
+ have multiple copies. */
+ if (DECL_INITIAL (decl) == 0
+ || DECL_INITIAL (decl) == error_mark_node)
+ DECL_COMMON (decl) = 1;
+ else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
+ {
+ DECL_COMMON (decl) = 1;
+ DECL_INITIAL (decl) = error_mark_node;
+ }
+ else
+ {
+ /* We can't do anything useful; leave vars for explicit
+ instantiation. */
+ DECL_EXTERNAL (decl) = 1;
+ DECL_NOT_REALLY_EXTERN (decl) = 0;
+ }
+ }
if (DECL_LANG_SPECIFIC (decl))
DECL_COMDAT (decl) = 1;
@@ -2517,14 +2491,14 @@ maybe_make_one_only (decl)
return;
/* We can't set DECL_COMDAT on functions, or finish_file will think
- we can get away with not emitting them if they aren't used.
- We can't use make_decl_one_only for variables, because their
- DECL_INITIAL may not have been set properly yet. */
+ we can get away with not emitting them if they aren't used. We need
+ to for variables so that cp_finish_decl will update their linkage,
+ because their DECL_INITIAL may not have been set properly yet. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- make_decl_one_only (decl);
- else
- comdat_linkage (decl);
+ make_decl_one_only (decl);
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_LANG_SPECIFIC (decl))
+ DECL_COMDAT (decl) = 1;
}
/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
@@ -2541,12 +2515,10 @@ import_export_vtable (decl, type, final)
if (DECL_INTERFACE_KNOWN (decl))
return;
- /* +e0 or +e1 */
- if (write_virtuals < 2 && write_virtuals != 0)
+ if (TYPE_FOR_JAVA (type))
{
TREE_PUBLIC (decl) = 1;
- if (write_virtuals < 0)
- DECL_EXTERNAL (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 1;
}
else if (CLASSTYPE_INTERFACE_KNOWN (type))
@@ -2554,11 +2526,6 @@ import_export_vtable (decl, type, final)
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
DECL_INTERFACE_KNOWN (decl) = 1;
-
- /* For WIN32 we also want to put explicit instantiations in
- linkonce sections. */
- if (CLASSTYPE_EXPLICIT_INSTANTIATION (type))
- maybe_make_one_only (decl);
}
else
{
@@ -2567,7 +2534,6 @@ import_export_vtable (decl, type, final)
int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
-#ifndef MULTIPLE_SYMBOL_SPACES
if (! found && ! final)
{
tree method;
@@ -2581,7 +2547,6 @@ import_export_vtable (decl, type, final)
break;
}
}
-#endif
if (final || ! found)
{
@@ -2609,10 +2574,20 @@ import_export_class (ctype)
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
return;
+ /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma interface,
+ we will have CLASSTYPE_INTERFACE_ONLY set but not
+ CLASSTYPE_INTERFACE_KNOWN. In that case, we don't want to use this
+ heuristic because someone will supply a #pragma implementation
+ elsewhere, and deducing it here would produce a conflict. */
+ if (CLASSTYPE_INTERFACE_ONLY (ctype))
+ return;
+
#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
/* FIXME this should really use some sort of target-independent macro. */
if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
import_export = -1;
+ else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
+ import_export = 1;
#endif
/* If we got -fno-implicit-templates, we import template classes that
@@ -2622,7 +2597,6 @@ import_export_class (ctype)
&& ! flag_implicit_templates)
import_export = -1;
-#ifndef MULTIPLE_SYMBOL_SPACES
/* Base our import/export status on that of the first non-inline,
non-abstract virtual function, if any. */
if (import_export == 0
@@ -2642,6 +2616,10 @@ import_export_class (ctype)
}
}
}
+
+#ifdef MULTIPLE_SYMBOL_SPACES
+ if (import_export == -1)
+ import_export = 0;
#endif
if (import_export)
@@ -2652,18 +2630,45 @@ import_export_class (ctype)
}
}
+/* We need to describe to the assembler the relationship between
+ a vtable and the vtable of the parent class. */
+
+static void
+output_vtable_inherit (vars)
+ tree vars;
+{
+ tree parent;
+ rtx op[2];
+
+ op[0] = XEXP (DECL_RTL (vars), 0); /* strip the mem ref */
+
+ parent = binfo_for_vtable (vars);
+
+ if (parent == TYPE_BINFO (DECL_CONTEXT (vars)))
+ op[1] = const0_rtx;
+ else if (parent)
+ {
+ parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent));
+ op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */
+ }
+ else
+ my_friendly_abort (980826);
+
+ output_asm_insn (".vtable_inherit %c0, %c1", op);
+}
+
static int
-finish_vtable_vardecl (prev, vars)
- tree prev, vars;
+finish_vtable_vardecl (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
+ tree vars = *t;
tree ctype = DECL_CONTEXT (vars);
import_export_class (ctype);
import_export_vtable (vars, ctype, 1);
- if (write_virtuals >= 0
- && ! DECL_EXTERNAL (vars)
- && ((TREE_PUBLIC (vars) && ! DECL_WEAK (vars) && ! DECL_ONE_ONLY (vars))
- || CLASSTYPE_EXPLICIT_INSTANTIATION (DECL_CONTEXT (vars))
+ if (! DECL_EXTERNAL (vars)
+ && (DECL_INTERFACE_KNOWN (vars)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))
|| (hack_decl_function_context (vars) && TREE_USED (vars)))
&& ! TREE_ASM_WRITTEN (vars))
@@ -2699,101 +2704,46 @@ finish_vtable_vardecl (prev, vars)
DECL_IGNORED_P (vars) = 1;
}
+ /* Always make vtables weak. */
+ if (flag_weak)
+ comdat_linkage (vars);
+
rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
+
+ if (flag_vtable_gc)
+ output_vtable_inherit (vars);
+
return 1;
}
else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)))
/* We don't know what to do with this one yet. */
return 0;
- /* We know that PREV must be non-zero here. */
- TREE_CHAIN (prev) = TREE_CHAIN (vars);
+ *t = TREE_CHAIN (vars);
return 0;
}
static int
-prune_vtable_vardecl (prev, vars)
- tree prev, vars;
+prune_vtable_vardecl (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- /* We know that PREV must be non-zero here. */
- TREE_CHAIN (prev) = TREE_CHAIN (vars);
+ *t = TREE_CHAIN (*t);
return 1;
}
-int
-walk_vtables (typedecl_fn, vardecl_fn)
- register void (*typedecl_fn) PROTO ((tree, tree));
- register int (*vardecl_fn) PROTO ((tree, tree));
-{
- tree prev, vars;
- int flag = 0;
-
- for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars))
- {
- register tree type = TREE_TYPE (vars);
-
- if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars))
- {
- if (vardecl_fn)
- flag |= (*vardecl_fn) (prev, vars);
-
- if (prev && TREE_CHAIN (prev) != vars)
- continue;
- }
- else if (TREE_CODE (vars) == TYPE_DECL
- && type != error_mark_node
- && TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_VSIZE (type))
- {
- if (typedecl_fn) (*typedecl_fn) (prev, vars);
- }
-
- prev = vars;
- }
-
- return flag;
-}
-
-static void
-finish_sigtable_vardecl (prev, vars)
- tree prev, vars;
+static int
+finish_sigtable_vardecl (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
/* We don't need to mark sigtable entries as addressable here as is done
for vtables. Since sigtables, unlike vtables, are always written out,
that was already done in build_signature_table_constructor. */
- rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
-
- /* We know that PREV must be non-zero here. */
- TREE_CHAIN (prev) = TREE_CHAIN (vars);
-}
-
-void
-walk_sigtables (typedecl_fn, vardecl_fn)
- register void (*typedecl_fn) PROTO((tree, tree));
- register void (*vardecl_fn) PROTO((tree, tree));
-{
- tree prev, vars;
-
- for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars))
- {
- register tree type = TREE_TYPE (vars);
-
- if (TREE_CODE (vars) == TYPE_DECL
- && type != error_mark_node
- && IS_SIGNATURE (type))
- {
- if (typedecl_fn) (*typedecl_fn) (prev, vars);
- }
- else if (TREE_CODE (vars) == VAR_DECL
- && TREE_TYPE (vars) != error_mark_node
- && IS_SIGNATURE (TREE_TYPE (vars)))
- {
- if (vardecl_fn) (*vardecl_fn) (prev, vars);
- }
- else
- prev = vars;
- }
+ rest_of_decl_compilation (*t, NULL_PTR, 1, 1);
+ *t = TREE_CHAIN (*t);
+ return 1;
}
/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
@@ -2806,20 +2756,21 @@ import_export_decl (decl)
if (DECL_INTERFACE_KNOWN (decl))
return;
- if (DECL_TEMPLATE_INSTANTIATION (decl))
+ if (DECL_TEMPLATE_INSTANTIATION (decl)
+ || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
{
DECL_NOT_REALLY_EXTERN (decl) = 1;
- if (DECL_IMPLICIT_INSTANTIATION (decl)
- && (flag_implicit_templates || DECL_THIS_INLINE (decl)))
+ if ((DECL_IMPLICIT_INSTANTIATION (decl)
+ || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
+ && (flag_implicit_templates
+ || (flag_implicit_inline_templates && DECL_THIS_INLINE (decl))))
{
if (!TREE_PUBLIC (decl))
/* Templates are allowed to have internal linkage. See
[basic.link]. */
;
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- comdat_linkage (decl);
else
- DECL_COMDAT (decl) = 1;
+ comdat_linkage (decl);
}
else
DECL_NOT_REALLY_EXTERN (decl) = 0;
@@ -2833,13 +2784,19 @@ import_export_decl (decl)
{
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
- || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
+ || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
+ && !DECL_VINDEX (decl)));
+
+ /* Always make artificials weak. */
+ if (DECL_ARTIFICIAL (decl) && flag_weak)
+ comdat_linkage (decl);
+ else
+ maybe_make_one_only (decl);
}
else
comdat_linkage (decl);
}
- /* tinfo function */
- else if (DECL_ARTIFICIAL (decl) && DECL_MUTABLE_P (decl))
+ else if (DECL_TINFO_FN_P (decl))
{
tree ctype = TREE_TYPE (DECL_NAME (decl));
@@ -2853,18 +2810,19 @@ import_export_decl (decl)
since it will not be emitted when the vtable for the type
is output (which is when the unqualified version is
generated). */
- && ctype == TYPE_MAIN_VARIANT (ctype))
+ && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
{
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
- || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
+ || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
+ && !DECL_VINDEX (decl)));
- /* For WIN32 we also want to put explicit instantiations in
- linkonce sections. */
- if (CLASSTYPE_EXPLICIT_INSTANTIATION (ctype))
- maybe_make_one_only (decl);
+ /* Always make artificials weak. */
+ if (flag_weak)
+ comdat_linkage (decl);
}
- else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype))
+ else if (TYPE_BUILT_IN (ctype)
+ && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
DECL_NOT_REALLY_EXTERN (decl) = 0;
else
comdat_linkage (decl);
@@ -2896,8 +2854,6 @@ build_cleanup (decl)
}
extern int parse_time, varconst_time;
-extern tree pending_templates;
-extern tree maybe_templates;
static tree
get_sentry (base)
@@ -2929,14 +2885,30 @@ get_sentry (base)
or destructors. Subroutine of do_[cd]tors. */
static void
-start_objects (method_type)
- int method_type;
+start_objects (method_type, initp)
+ int method_type, initp;
{
tree fnname;
+ char type[10];
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
- fnname = get_file_function_name (method_type);
+ if (initp != DEFAULT_INIT_PRIORITY)
+ {
+ char joiner;
+
+#ifdef JOINER
+ joiner = JOINER;
+#else
+ joiner = '_';
+#endif
+
+ sprintf (type, "%c%c%.5u", method_type, joiner, initp);
+ }
+ else
+ sprintf (type, "%c", method_type);
+
+ fnname = get_file_function_name_long (type);
start_function (void_list_node,
make_call_declarator (fnname, void_list_node, NULL_TREE,
@@ -2954,29 +2926,23 @@ start_objects (method_type)
clear_last_expr ();
push_momentary ();
expand_start_bindings (0);
+
+ /* We cannot allow these functions to be elided, even if they do not
+ have external linkage. And, there's no point in deferring
+ copmilation of thes functions; they're all going to have to be
+ out anyhow. */
+ current_function_cannot_inline
+ = "static constructors and destructors cannot be inlined";
}
/* Finish the process of running a particular set of global constructors
or destructors. Subroutine of do_[cd]tors. */
static void
-finish_objects (method_type)
- int method_type;
+finish_objects (method_type, initp)
+ int method_type, initp;
{
- char *fnname;
-
- tree list = (method_type == 'I' ? static_ctors : static_dtors);
-
- if (! current_function_decl && list)
- start_objects (method_type);
-
- for (; list; list = TREE_CHAIN (list))
- expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE));
-
- if (! current_function_decl)
- return;
-
- fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ char *fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
/* Finish up. */
expand_end_bindings (getdecls (), 1, 0);
@@ -2984,422 +2950,790 @@ finish_objects (method_type)
pop_momentary ();
finish_function (lineno, 0, 0);
- if (method_type == 'I')
- assemble_constructor (fnname);
+ if (initp == DEFAULT_INIT_PRIORITY)
+ {
+ if (method_type == 'I')
+ assemble_constructor (fnname);
+ else
+ assemble_destructor (fnname);
+ }
+
+#if defined (ASM_OUTPUT_SECTION_NAME) && defined (ASM_OUTPUT_CONSTRUCTOR)
+ /* If we're using init priority we can't use assemble_*tor, but on ELF
+ targets we can stick the references into named sections for GNU ld
+ to collect. */
else
- assemble_destructor (fnname);
+ {
+ char buf[15];
+ sprintf (buf, ".%ctors.%.5u", method_type == 'I' ? 'c' : 'd',
+ /* invert the numbering so the linker puts us in the proper
+ order; constructors are run from right to left, and the
+ linker sorts in increasing order. */
+ MAX_INIT_PRIORITY - initp);
+ named_section (NULL_TREE, buf, 0);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname),
+ POINTER_SIZE / BITS_PER_UNIT, 1);
+ }
+#endif
}
-/* Generate a function to run a set of global destructors. Subroutine of
- finish_file. */
+/* The names of the parameters to the function created to handle
+ initializations and destructions for objects with static storage
+ duration. */
+#define INITIALIZE_P_IDENTIFIER "__initialize_p"
+#define PRIORITY_IDENTIFIER "__priority"
+
+/* The name of the function we create to handle initializations and
+ destructions for objects with static storage duration. */
+#define SSDF_IDENTIFIER "__static_initialization_and_destruction"
+
+/* The declaration for the __INITIALIZE_P argument. */
+static tree initialize_p_decl;
+
+/* The declaration for the __PRIORITY argument. */
+static tree priority_decl;
+
+/* The declaration for the static storage duration function. */
+static tree ssdf_decl;
+
+/* All the static storage duration functions created in this
+ translation unit. */
+static varray_type ssdf_decls;
+static size_t ssdf_decls_used;
+
+/* A map from priority levels to information about that priority
+ level. There may be many such levels, so efficient lookup is
+ important. */
+static splay_tree priority_info_map;
+
+/* Begins the generation of the function that will handle all
+ initialization and destruction of objects with static storage
+ duration. The function generated takes two parameters of type
+ `int': __INITIALIZE_P and __PRIORITY. If __INITIALIZE_P is
+ non-zero, it performs initializations. Otherwise, it performs
+ destructions. It only performs those initializations or
+ destructions with the indicated __PRIORITY. The generated function
+ returns no value.
+
+ It is assumed that this function will only be called once per
+ translation unit. */
static void
-do_dtors ()
+start_static_storage_duration_function ()
{
- tree vars = static_aggregates;
+ static unsigned ssdf_number;
+
+ tree parm_types;
+ tree type;
+ char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
- for (; vars; vars = TREE_CHAIN (vars))
+ /* Create the identifier for this function. It will be of the form
+ SSDF_IDENTIFIER_<number>. */
+ sprintf (id, "%s_%u", SSDF_IDENTIFIER, ssdf_number++);
+ if (ssdf_number == 0)
{
- tree decl = TREE_VALUE (vars);
- tree type = TREE_TYPE (decl);
- tree temp;
+ /* Overflow occurred. That means there are at least 4 billion
+ initialization functions. */
+ sorry ("too many initialization functions required");
+ my_friendly_abort (19990430);
+ }
- if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars)
- && ! DECL_EXTERNAL (decl))
- {
- int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
- || DECL_ONE_ONLY (decl)
- || DECL_WEAK (decl)));
+ /* Create the parameters. */
+ parm_types = void_list_node;
+ parm_types = perm_tree_cons (NULL_TREE, integer_type_node, parm_types);
+ parm_types = perm_tree_cons (NULL_TREE, integer_type_node, parm_types);
+ type = build_function_type (void_type_node, parm_types);
+
+ /* Create the FUNCTION_DECL itself. */
+ ssdf_decl = build_lang_decl (FUNCTION_DECL,
+ get_identifier (id),
+ type);
+ TREE_PUBLIC (ssdf_decl) = 0;
+ DECL_ARTIFICIAL (ssdf_decl) = 1;
+
+ /* Put this function in the list of functions to be called from the
+ static constructors and destructors. */
+ if (!ssdf_decls)
+ {
+ VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls");
+
+ /* Take this opportunity to initialize the map from priority
+ numbers to information about that priority level. */
+ priority_info_map = splay_tree_new (splay_tree_compare_ints,
+ /*delete_key_fn=*/0,
+ /*delete_value_fn=*/
+ (splay_tree_delete_value_fn) &free);
+
+ /* We always need to generate functions for the
+ DEFAULT_INIT_PRIORITY so enter it now. That way when we walk
+ priorities later, we'll be sure to find the
+ DEFAULT_INIT_PRIORITY. */
+ get_priority_info (DEFAULT_INIT_PRIORITY);
+ }
- if (! current_function_decl)
- start_objects ('D');
+ if (ssdf_decls_used == ssdf_decls->num_elements)
+ VARRAY_GROW (ssdf_decls, 2 * ssdf_decls_used);
+ VARRAY_TREE (ssdf_decls, ssdf_decls_used) = ssdf_decl;
+ ++ssdf_decls_used;
+
+ /* Create the argument list. */
+ initialize_p_decl = build_decl (PARM_DECL,
+ get_identifier (INITIALIZE_P_IDENTIFIER),
+ integer_type_node);
+ DECL_CONTEXT (initialize_p_decl) = ssdf_decl;
+ DECL_ARG_TYPE (initialize_p_decl) = integer_type_node;
+ TREE_USED (initialize_p_decl) = 1;
+ priority_decl = build_decl (PARM_DECL, get_identifier (PRIORITY_IDENTIFIER),
+ integer_type_node);
+ DECL_CONTEXT (priority_decl) = ssdf_decl;
+ DECL_ARG_TYPE (priority_decl) = integer_type_node;
+ TREE_USED (priority_decl) = 1;
+
+ TREE_CHAIN (initialize_p_decl) = priority_decl;
+ DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
+
+ /* Start the function itself. This is equivalent to declarating the
+ function as:
+
+ static void __ssdf (int __initialize_p, init __priority_p);
+
+ It is static because we only need to call this function from the
+ various constructor and destructor functions for this module. */
+ start_function (/*specs=*/NULL_TREE,
+ ssdf_decl,
+ /*attrs=*/NULL_TREE,
+ /*pre_parsed_p=*/1);
+
+ /* Set up the scope of the outermost block in the function. */
+ store_parm_decls ();
+ pushlevel (0);
+ clear_last_expr ();
+ push_momentary ();
+ expand_start_bindings (0);
- temp = build_cleanup (decl);
+ /* This function must not be deferred because we are depending on
+ its compilation to tell us what is TREE_SYMBOL_REFERENCED. */
+ current_function_cannot_inline
+ = "static storage duration functions cannot be inlined";
+}
- if (protect)
- {
- tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
- sentry = build_unary_op (PREDECREMENT_EXPR, sentry, 0);
- sentry = build_binary_op (EQ_EXPR, sentry, integer_zero_node, 1);
- expand_start_cond (sentry, 0);
- }
+/* Generate the initialization code for the priority indicated in N. */
- expand_expr_stmt (temp);
+static int
+generate_inits_for_priority (n, data)
+ splay_tree_node n;
+ void *data ATTRIBUTE_UNUSED;
+{
+ int priority = (int) n->key;
+ priority_info pi = (priority_info) n->value;
+
+ /* For each priority N which has been used generate code which looks
+ like:
+
+ if (__priority == N) {
+ if (__initialize_p)
+ ...
+ else
+ ...
+ }
+
+ We use the sequences we've accumulated to fill in the `...'s. */
+ expand_start_cond (build_binary_op (EQ_EXPR,
+ priority_decl,
+ build_int_2 (priority, 0)),
+ /*exit_flag=*/0);
+
+ /* Do the initializations. */
+ expand_start_cond (build_binary_op (NE_EXPR,
+ initialize_p_decl,
+ integer_zero_node),
+ /*exit_flag=*/0);
+ if (pi->initialization_sequence)
+ {
+ rtx insns;
- if (protect)
- expand_end_cond ();
- }
+ push_to_sequence (pi->initialization_sequence);
+ insns = gen_sequence ();
+ end_sequence ();
+
+ emit_insn (insns);
+ pi->initialization_sequence = NULL_RTX;
+ pi->initializations_p = 1;
+ }
+
+ /* Do the destructions. */
+ expand_start_else ();
+ if (pi->destruction_sequence)
+ {
+ rtx insns;
+
+ push_to_sequence (pi->destruction_sequence);
+ insns = gen_sequence ();
+ end_sequence ();
+
+ emit_insn (insns);
+ pi->destruction_sequence = NULL_RTX;
+ pi->destructions_p = 1;
}
+
+ /* Close out the conditionals. */
+ expand_end_cond ();
+ expand_end_cond ();
- finish_objects ('D');
+ /* Don't stop iterating. */
+ return 0;
}
-/* Generate a function to run a set of global constructors. Subroutine of
- finish_file. */
+/* Finish the generation of the function which performs initialization
+ and destruction of objects with static storage duration. After
+ this point, no more such objects can be created. */
static void
-do_ctors ()
+finish_static_storage_duration_function ()
{
- tree vars = static_aggregates;
+ splay_tree_foreach (priority_info_map,
+ generate_inits_for_priority,
+ /*data=*/0);
- /* Reverse the list so it's in the right order for ctors. */
- vars = nreverse (vars);
+ /* Close out the function. */
+ expand_end_bindings (getdecls (), 1, 0);
+ poplevel (1, 0, 0);
+ pop_momentary ();
+ finish_function (lineno, 0, 0);
+}
- for (; vars; vars = TREE_CHAIN (vars))
+/* Return the information about the indicated PRIORITY level. If no
+ code to handle this level has yet been generated, generate the
+ appropriate prologue. */
+
+static priority_info
+get_priority_info (priority)
+ int priority;
+{
+ priority_info pi;
+ splay_tree_node n;
+
+ n = splay_tree_lookup (priority_info_map,
+ (splay_tree_key) priority);
+ if (!n)
{
- tree decl = TREE_VALUE (vars);
- tree init = TREE_PURPOSE (vars);
-
- /* If this was a static attribute within some function's scope,
- then don't initialize it here. Also, don't bother
- with initializers that contain errors. */
- if (TREE_STATIC (vars)
- || DECL_EXTERNAL (decl)
- || (init && TREE_CODE (init) == TREE_LIST
- && value_member (error_mark_node, init)))
- continue;
+ /* Create a new priority information structure, and insert it
+ into the map. */
+ pi = (priority_info) xmalloc (sizeof (struct priority_info_s));
+ pi->initialization_sequence = NULL_RTX;
+ pi->destruction_sequence = NULL_RTX;
+ pi->initializations_p = 0;
+ pi->destructions_p = 0;
+ splay_tree_insert (priority_info_map,
+ (splay_tree_key) priority,
+ (splay_tree_value) pi);
+ }
+ else
+ pi = (priority_info) n->value;
- if (TREE_CODE (decl) == VAR_DECL)
- {
- int protect = (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
- || DECL_ONE_ONLY (decl)
- || DECL_WEAK (decl)));
-
- if (! current_function_decl)
- start_objects ('I');
-
- /* Set these global variables so that GDB at least puts
- us near the declaration which required the initialization. */
- input_filename = DECL_SOURCE_FILE (decl);
- lineno = DECL_SOURCE_LINE (decl);
- emit_note (input_filename, lineno);
-
- /* 9.5p5: The initializer of a static member of a class has
- the same access rights as a member function. */
- if (member_p (decl))
- {
- DECL_CLASS_CONTEXT (current_function_decl)
- = DECL_CONTEXT (decl);
- DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
- }
+ return pi;
+}
- if (protect)
- {
- tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
- sentry = build_unary_op (PREINCREMENT_EXPR, sentry, 0);
- sentry = build_binary_op
- (EQ_EXPR, sentry, integer_one_node, 1);
- expand_start_cond (sentry, 0);
- }
+/* Generate code to do the static initialization of DECL. The
+ initialization is INIT. If DECL may be initialized more than once
+ in different object files, SENTRY is the guard variable to
+ check. PRIORITY is the priority for the initialization. */
- expand_start_target_temps ();
+static void
+do_static_initialization (decl, init, sentry, priority)
+ tree decl;
+ tree init;
+ tree sentry;
+ int priority;
+{
+ priority_info pi;
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- expand_aggr_init (decl, init, 0, 0);
- else if (TREE_CODE (init) == TREE_VEC)
- {
- expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
- TREE_VEC_ELT (init, 1),
- TREE_VEC_ELT (init, 2), 0),
- const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
- else
- expand_assignment (decl, init, 0, 0);
-
- /* The expression might have involved increments and
- decrements. */
- emit_queue ();
+ /* Get the priority information for this PRIORITY, */
+ pi = get_priority_info (priority);
+ if (!pi->initialization_sequence)
+ start_sequence ();
+ else
+ push_to_sequence (pi->initialization_sequence);
+
+ /* Tell the debugger that we are at the location of the static
+ variable in question. */
+ emit_note (input_filename, lineno);
+
+ /* If there's a SENTRY, we only do the initialization if it is
+ zero, i.e., if we are the first to initialize it. */
+ if (sentry)
+ expand_start_cond (build_binary_op (EQ_EXPR,
+ build_unary_op (PREINCREMENT_EXPR,
+ sentry,
+ /*noconvert=*/0),
+ integer_one_node),
+ /*exit_flag=*/0);
+
+ /* Prepare a binding level for temporaries created during the
+ initialization. */
+ expand_start_target_temps ();
+
+ if (IS_AGGR_TYPE (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ expand_aggr_init (decl, init, 0);
+ else if (TREE_CODE (init) == TREE_VEC)
+ expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
+ TREE_VEC_ELT (init, 1),
+ TREE_VEC_ELT (init, 2), 0),
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
+ else
+ expand_assignment (decl, init, 0, 0);
+
+ /* The expression might have involved increments and decrements. */
+ emit_queue ();
- /* Cleanup any temporaries needed for the initial value. */
- expand_end_target_temps ();
+ /* Cleanup any temporaries needed for the initial value. */
+ expand_end_target_temps ();
- if (protect)
- expand_end_cond ();
+ /* Cleanup any deferred pops from function calls. This would be done
+ by expand_end_cond, but we also need it when !SENTRY, since we are
+ constructing these sequences by parts. */
+ do_pending_stack_adjust ();
- DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
- DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
- }
- else if (decl == error_mark_node)
- /* OK */;
- else
- my_friendly_abort (22);
- }
+ /* Close the conditional opened above. */
+ if (sentry)
+ expand_end_cond ();
- finish_objects ('I');
+ /* Save the sequence for later use. */
+ pi->initialization_sequence = get_insns ();
+ end_sequence ();
}
-/* This routine is called from the last rule in yyparse ().
- Its job is to create all the code needed to initialize and
- destroy the global aggregates. We do the destruction
- first, since that way we only need to reverse the decls once. */
+/* Generate code to do the static destruction of DECL. If DECL may be
+ initialized more than once in different object files, SENTRY is the
+ guard variable to check. PRIORITY is the priority for the
+ destruction. */
-void
-finish_file ()
+static void
+do_static_destruction (decl, sentry, priority)
+ tree decl;
+ tree sentry;
+ int priority;
{
- extern int lineno;
- int start_time, this_time;
+ rtx new_insns;
+ priority_info pi;
- tree fnname;
- tree vars;
- int needs_cleaning = 0, needs_messing_up = 0;
+ /* If we don't need a destructor, there's nothing to do. */
+ if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+ return;
+
+ /* Get the priority information for this PRIORITY, */
+ pi = get_priority_info (priority);
+ if (!pi->destruction_sequence)
+ start_sequence ();
+ else
+ push_to_sequence (pi->destruction_sequence);
- at_eof = 1;
+ /* Start a new sequence to handle just this destruction. */
+ start_sequence ();
- /* Bad parse errors. Just forget about it. */
- if (! global_bindings_p () || current_class_type)
- return;
+ /* Tell the debugger that we are at the location of the static
+ variable in question. */
+ emit_note (input_filename, lineno);
+
+ /* If there's a SENTRY, we only do the destruction if it is one,
+ i.e., if we are the last to destroy it. */
+ if (sentry)
+ expand_start_cond (build_binary_op (EQ_EXPR,
+ build_unary_op (PREDECREMENT_EXPR,
+ sentry,
+ /*nonconvert=*/1),
+ integer_zero_node),
+ /*exit_flag=*/0);
+
+ /* Actually to the destruction. */
+ expand_expr_stmt (build_cleanup (decl));
+
+ /* Cleanup any deferred pops from function calls. This would be done
+ by expand_end_cond, but we also need it when !SENTRY, since we are
+ constructing these sequences by parts. */
+ do_pending_stack_adjust ();
+
+ /* Close the conditional opened above. */
+ if (sentry)
+ expand_end_cond ();
+
+ /* Insert the NEW_INSNS before the current insns. (Destructions are
+ run in reverse order of initializations.) */
+ new_insns = gen_sequence ();
+ end_sequence ();
+ if (pi->destruction_sequence)
+ emit_insn_before (new_insns, pi->destruction_sequence);
+ else
+ emit_insn (new_insns);
- check_decl_namespace ();
+ /* Save the sequence for later use. */
+ pi->destruction_sequence = get_insns ();
+ end_sequence ();
+}
- start_time = get_run_time ();
+/* Add code to the static storage duration function that will handle
+ DECL (a static variable that needs initializing and/or destruction)
+ with the indicated PRIORITY. If DECL needs initializing, INIT is
+ the initializer. */
- /* Otherwise, GDB can get confused, because in only knows
- about source for LINENO-1 lines. */
- lineno -= 1;
+static void
+do_static_initialization_and_destruction (decl, init)
+ tree decl;
+ tree init;
+{
+ tree sentry = NULL_TREE;
+ int priority;
- interface_unknown = 1;
- interface_only = 0;
+ /* Deal gracefully with error. */
+ if (decl == error_mark_node)
+ return;
- for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname))
- {
- tree srcloc = TREE_PURPOSE (fnname);
- tree decl = TREE_VALUE (fnname);
+ /* The only things that can be initialized are variables. */
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
- input_filename = SRCLOC_FILE (srcloc);
- lineno = SRCLOC_LINE (srcloc);
+ /* If this object is not defined, we don't need to do anything
+ here. */
+ if (DECL_EXTERNAL (decl))
+ return;
- if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
- {
- instantiate_class_template (decl);
- if (CLASSTYPE_TEMPLATE_INSTANTIATION (decl))
- for (vars = TYPE_METHODS (decl); vars; vars = TREE_CHAIN (vars))
- if (! DECL_ARTIFICIAL (vars))
- instantiate_decl (vars);
- }
- else
- instantiate_decl (decl);
- }
+ /* Also, if the initializer already contains errors, we can bail out
+ now. */
+ if (init && TREE_CODE (init) == TREE_LIST
+ && value_member (error_mark_node, init))
+ return;
- for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
- {
- tree args, fn, decl = TREE_VALUE (fnname);
+ /* Trick the compiler into thinking we are at the file and line
+ where DECL was declared so that error-messages make sense, and so
+ that the debugger will show somewhat sensible file and line
+ information. */
+ input_filename = DECL_SOURCE_FILE (decl);
+ lineno = DECL_SOURCE_LINE (decl);
- if (DECL_INITIAL (decl))
- continue;
+ /* Because of:
- fn = TREE_PURPOSE (fnname);
- args = get_bindings (fn, decl, NULL_TREE);
- fn = instantiate_template (fn, args);
- instantiate_decl (fn);
- }
+ [class.access.spec]
- cat_namespace_levels();
+ Access control for implicit calls to the constructors,
+ the conversion functions, or the destructor called to
+ create and destroy a static data member is performed as
+ if these calls appeared in the scope of the member's
+ class.
- /* Push into C language context, because that's all
- we'll need here. */
- push_lang_context (lang_name_c);
+ we pretend we are in a static member function of the class of
+ which the DECL is a member. */
+ if (member_p (decl))
+ {
+ DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
+ }
+
+ /* We need a sentry if this is an object with external linkage that
+ might be initialized in more than one place. */
+ if (TREE_PUBLIC (decl) && (DECL_COMMON (decl)
+ || DECL_ONE_ONLY (decl)
+ || DECL_WEAK (decl)))
+ sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+
+ /* Generate the code to actually do the intialization and
+ destruction. */
+ priority = DECL_INIT_PRIORITY (decl);
+ if (!priority)
+ priority = DEFAULT_INIT_PRIORITY;
+ do_static_initialization (decl, init, sentry, priority);
+ do_static_destruction (decl, sentry, priority);
+
+ /* Now that we're done with DECL we don't need to pretend to be a
+ member of its class any longer. */
+ DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
+}
-#if 1
- /* The reason for pushing garbage onto the global_binding_level is to
- ensure that we can slice out _DECLs which pertain to virtual function
- tables. If the last thing pushed onto the global_binding_level was a
- virtual function table, then slicing it out would slice away all the
- decls (i.e., we lose the head of the chain).
-
- There are several ways of getting the same effect, from changing the
- way that iterators over the chain treat the elements that pertain to
- virtual function tables, moving the implementation of this code to
- decl.c (where we can manipulate global_binding_level directly),
- popping the garbage after pushing it and slicing away the vtable
- stuff, or just leaving it alone. */
-
- /* Make last thing in global scope not be a virtual function table. */
-#if 0 /* not yet, should get fixed properly later */
- vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node);
-#else
- vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
-#endif
- DECL_IGNORED_P (vars) = 1;
- SET_DECL_ARTIFICIAL (vars);
- pushdecl (vars);
-#endif
+/* Generate a static constructor (if CONSTRUCTOR_P) or destructor
+ (otherwise) that will initialize all gobal objects with static
+ storage duration having the indicated PRIORITY. */
- for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars))
- if (! TREE_ASM_WRITTEN (TREE_VALUE (vars)))
- rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
- vars = static_aggregates;
+static void
+generate_ctor_or_dtor_function (constructor_p, priority)
+ int constructor_p;
+ int priority;
+{
+ char function_key;
+ tree arguments;
+ size_t i;
+
+ /* We use `I' to indicate initialization and `D' to indicate
+ destruction. */
+ if (constructor_p)
+ function_key = 'I';
+ else
+ function_key = 'D';
- if (static_ctors || vars)
- needs_messing_up = 1;
- if (static_dtors || vars)
- needs_cleaning = 1;
+ /* Begin the function. */
+ start_objects (function_key, priority);
- /* The aggregates are listed in reverse declaration order, for cleaning. */
- if (needs_cleaning)
+ /* Call the static storage duration function with appropriate
+ arguments. */
+ for (i = 0; i < ssdf_decls_used; ++i)
{
- do_dtors ();
+ arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
+ NULL_TREE);
+ arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
+ arguments);
+ expand_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
+ arguments));
}
- /* do_ctors will reverse the lists for messing up. */
- if (needs_messing_up)
+ /* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
+ calls to any functions marked with attributes indicating that
+ they should be called at initialization- or destruction-time. */
+ if (priority == DEFAULT_INIT_PRIORITY)
{
- do_ctors ();
+ tree fns;
+
+ for (fns = constructor_p ? static_ctors : static_dtors;
+ fns;
+ fns = TREE_CHAIN (fns))
+ expand_expr_stmt (build_function_call (TREE_VALUE (fns), NULL_TREE));
}
- permanent_allocation (1);
+ /* Close out the function. */
+ finish_objects (function_key, priority);
+}
- /* Done with C language context needs. */
- pop_lang_context ();
+/* Generate constructor and destructor functions for the priority
+ indicated by N. */
- /* Now write out any static class variables (which may have since
- learned how to be initialized). */
- while (pending_statics)
- {
- tree decl = TREE_VALUE (pending_statics);
+static int
+generate_ctor_and_dtor_functions_for_priority (n, data)
+ splay_tree_node n;
+ void *data ATTRIBUTE_UNUSED;
+{
+ int priority = (int) n->key;
+ priority_info pi = (priority_info) n->value;
+
+ /* Generate the functions themselves, but only if they are really
+ needed. */
+ if (pi->initializations_p
+ || (priority == DEFAULT_INIT_PRIORITY && static_ctors))
+ generate_ctor_or_dtor_function (/*constructor_p=*/1,
+ priority);
+ if (pi->destructions_p
+ || (priority == DEFAULT_INIT_PRIORITY && static_dtors))
+ generate_ctor_or_dtor_function (/*constructor_p=*/0,
+ priority);
+
+ /* Keep iterating. */
+ return 0;
+}
- /* Output DWARF debug information. */
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- dwarfout_file_scope_decl (decl, 1);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_decl (decl);
-#endif
+/* This routine is called from the last rule in yyparse ().
+ Its job is to create all the code needed to initialize and
+ destroy the global aggregates. We do the destruction
+ first, since that way we only need to reverse the decls once. */
- DECL_DEFER_OUTPUT (decl) = 0;
- rest_of_decl_compilation
- (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1);
+void
+finish_file ()
+{
+ extern int lineno;
+ int start_time, this_time;
+ tree vars;
+ int reconsider;
+ size_t i;
- pending_statics = TREE_CHAIN (pending_statics);
- }
+ at_eof = 1;
- this_time = get_run_time ();
- parse_time -= this_time - start_time;
- varconst_time += this_time - start_time;
+ /* Bad parse errors. Just forget about it. */
+ if (! global_bindings_p () || current_class_type || decl_namespace_list)
+ return;
start_time = get_run_time ();
- if (flag_handle_signatures)
- walk_sigtables ((void (*) PROTO ((tree, tree))) 0,
- finish_sigtable_vardecl);
+ /* Otherwise, GDB can get confused, because in only knows
+ about source for LINENO-1 lines. */
+ lineno -= 1;
- for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname))
- {
- tree decl = TREE_VALUE (fnname);
- import_export_decl (decl);
- }
+ interface_unknown = 1;
+ interface_only = 0;
- mark_all_runtime_matches ();
+ /* We now have to write out all the stuff we put off writing out.
+ These include:
- /* Now write out inline functions which had their addresses taken and
- which were not declared virtual and which were not declared `extern
- inline'. */
- {
- int reconsider = 1; /* More may be referenced; check again */
+ o Template specializations that we have not yet instantiated,
+ but which are needed.
+ o Initialization and destruction for non-local objects with
+ static storage duration. (Local objects with static storage
+ duration are initialized when their scope is first entered,
+ and are cleaned up via atexit.)
+ o Virtual function tables.
- while (reconsider)
- {
- tree *p = &saved_inlines;
- reconsider = 0;
+ All of these may cause others to be needed. For example,
+ instantiating one function may cause another to be needed, and
+ generating the intiailzer for an object may cause templates to be
+ instantiated, etc., etc. */
- /* We need to do this each time so that newly completed template
- types don't wind up at the front of the list. Sigh. */
- vars = build_decl (TYPE_DECL, make_anon_name (), integer_type_node);
- DECL_IGNORED_P (vars) = 1;
- SET_DECL_ARTIFICIAL (vars);
- pushdecl (vars);
+ this_time = get_run_time ();
+ parse_time -= this_time - start_time;
+ varconst_time += this_time - start_time;
+ start_time = get_run_time ();
+ permanent_allocation (1);
- reconsider |= walk_vtables ((void (*) PROTO((tree, tree))) 0,
- finish_vtable_vardecl);
+ do
+ {
+ /* Non-zero if we need a static storage duration function on
+ this iteration through the loop. */
+ int need_ssdf_p = 0;
+
+ reconsider = 0;
+
+ /* If there are templates that we've put off instantiating, do
+ them now. */
+ instantiate_pending_templates ();
+
+ /* Write out signature-tables and virtual tables as required.
+ Note that writing out the virtual table for a template class
+ may cause the instantiation of members of that class. */
+ if (flag_handle_signatures
+ && walk_globals (sigtable_decl_p,
+ finish_sigtable_vardecl,
+ /*data=*/0))
+ reconsider = 1;
+ if (walk_globals (vtable_decl_p,
+ finish_vtable_vardecl,
+ /*data=*/0))
+ reconsider = 1;
+
+ /* The list of objects with static storage duration is built up
+ in reverse order, so we reverse it here. We also clear
+ STATIC_AGGREGATES so that any new aggregates added during the
+ initialization of these will be initialized in the correct
+ order when we next come around the loop. */
+ vars = nreverse (static_aggregates);
+ static_aggregates = NULL_TREE;
+ while (vars)
+ {
+ if (! TREE_ASM_WRITTEN (TREE_VALUE (vars)))
+ rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
+ if (!need_ssdf_p)
+ {
+ /* We need to start a new initialization function each
+ time through the loop. That's because we need to
+ know which vtables have been referenced, and
+ TREE_SYMBOL_REFERENCED isn't computed until a
+ function is finished, and written out. That's a
+ deficiency in the back-end. When this is fixed,
+ these initialization functions could all become
+ inline, with resulting performance improvements. */
+ start_static_storage_duration_function ();
+ need_ssdf_p = 1;
+ }
- while (*p)
- {
- tree decl = TREE_VALUE (*p);
+ do_static_initialization_and_destruction (TREE_VALUE (vars),
+ TREE_PURPOSE (vars));
+ reconsider = 1;
+ vars = TREE_CHAIN (vars);
+ }
+
+ /* Finish up the static storage duration function for this
+ round. */
+ if (need_ssdf_p)
+ finish_static_storage_duration_function ();
+
+ /* Go through the various inline functions, and see if any need
+ synthesizing. */
+ for (i = 0; i < saved_inlines_used; ++i)
+ {
+ tree decl = VARRAY_TREE (saved_inlines, i);
+ import_export_decl (decl);
+ if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
+ && TREE_USED (decl)
+ && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
+ {
+ /* Even though we're already at the top-level, we push
+ there again. That way, when we pop back a few lines
+ hence, all of our state is restored. Otherwise,
+ finish_function doesn't clean things up, and we end
+ up with CURRENT_FUNCTION_DECL set. */
+ push_to_top_level ();
+ if (DECL_TINFO_FN_P (decl))
+ synthesize_tinfo_fn (decl);
+ else
+ synthesize_method (decl);
+ pop_from_top_level ();
+ reconsider = 1;
+ }
+ }
- if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
- && TREE_USED (decl)
- && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
- {
- if (DECL_MUTABLE_P (decl))
- synthesize_tinfo_fn (decl);
- else
- synthesize_method (decl);
- reconsider = 1;
- }
+ /* Mark all functions that might deal with exception-handling as
+ referenced. */
+ mark_all_runtime_matches ();
- /* Catch new template instantiations. */
- if (decl != TREE_VALUE (*p))
- continue;
-
- if (TREE_ASM_WRITTEN (decl)
- || (DECL_SAVED_INSNS (decl) == 0 && ! DECL_ARTIFICIAL (decl)))
- *p = TREE_CHAIN (*p);
- else if (DECL_INITIAL (decl) == 0)
- p = &TREE_CHAIN (*p);
- else if ((TREE_PUBLIC (decl) && ! DECL_COMDAT (decl))
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
- || flag_keep_inline_functions)
- {
- if (DECL_NOT_REALLY_EXTERN (decl))
- {
- DECL_EXTERNAL (decl) = 0;
- reconsider = 1;
- /* We can't inline this function after it's been
- emitted. We want a variant of
- output_inline_function that doesn't prevent
- subsequent integration... */
- DECL_INLINE (decl) = 0;
- output_inline_function (decl);
- permanent_allocation (1);
- }
-
- *p = TREE_CHAIN (*p);
- }
- else
- p = &TREE_CHAIN (*p);
- }
- }
+ /* We lie to the back-end, pretending that some functions are
+ not defined when they really are. This keeps these functions
+ from being put out unncessarily. But, we must stop lying
+ when the functions are referenced, or if they are not comdat
+ since they need to be put out now. */
+ for (i = 0; i < saved_inlines_used; ++i)
+ {
+ tree decl = VARRAY_TREE (saved_inlines, i);
+
+ if (DECL_NOT_REALLY_EXTERN (decl)
+ && DECL_INITIAL (decl)
+ && (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
+ || !DECL_COMDAT (decl)))
+ DECL_EXTERNAL (decl) = 0;
+ }
- /* It's possible that some of the remaining inlines will still be
- needed. For example, a static inline whose address is used in
- the initializer for a file-scope static variable will be
- needed. Code in compile_file will handle this, but we mustn't
- pretend that there are no definitions for the inlines, or it
- won't be able to.
+ if (saved_inlines_used
+ && wrapup_global_declarations (&VARRAY_TREE (saved_inlines, 0),
+ saved_inlines_used))
+ reconsider = 1;
+ if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0))
+ reconsider = 1;
- FIXME: This won't catch member functions. We should really
- unify this stuff with the compile_file stuff. */
- for (vars = saved_inlines; vars != NULL_TREE; vars = TREE_CHAIN (vars))
- {
- tree decl = TREE_VALUE (vars);
+ /* Static data members are just like namespace-scope globals. */
+ for (i = 0; i < pending_statics_used; ++i)
+ {
+ tree decl = VARRAY_TREE (pending_statics, i);
+ if (TREE_ASM_WRITTEN (decl))
+ continue;
+ import_export_decl (decl);
+ if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl))
+ DECL_EXTERNAL (decl) = 0;
+ }
+ if (pending_statics
+ && wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
+ pending_statics_used))
+ reconsider = 1;
+ }
+ while (reconsider);
- if (DECL_NOT_REALLY_EXTERN (decl)
- && !DECL_COMDAT (decl)
- && DECL_INITIAL (decl) != NULL_TREE)
- DECL_EXTERNAL (decl) = 0;
- }
- }
+ /* We give C linkage to static constructors and destructors. */
+ push_lang_context (lang_name_c);
- /* Now delete from the chain of variables all virtual function tables.
- We output them all ourselves, because each will be treated specially. */
+ /* Generate initialization and destruction functions for all
+ priorities for which they are required. */
+ if (priority_info_map)
+ splay_tree_foreach (priority_info_map,
+ generate_ctor_and_dtor_functions_for_priority,
+ /*data=*/0);
- walk_vtables ((void (*) PROTO((tree, tree))) 0,
- prune_vtable_vardecl);
+ /* We're done with the splay-tree now. */
+ if (priority_info_map)
+ splay_tree_delete (priority_info_map);
- if (write_virtuals == 2)
- {
- /* Now complain about an virtual function tables promised
- but not delivered. */
- while (pending_vtables)
- {
- if (TREE_PURPOSE (pending_vtables) == NULL_TREE)
- error ("virtual function table for `%s' not defined",
- IDENTIFIER_POINTER (TREE_VALUE (pending_vtables)));
- pending_vtables = TREE_CHAIN (pending_vtables);
- }
- }
+ /* We're done with static constructors, so we can go back to "C++"
+ linkage now. */
+ pop_lang_context ();
+
+ /* Now delete from the chain of variables all virtual function tables.
+ We output them all ourselves, because each will be treated
+ specially. */
+ walk_globals (vtable_decl_p, prune_vtable_vardecl, /*data=*/0);
+
+ /* Now, issue warnings about static, but not defined, functions,
+ etc. */
+ walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
finish_repo ();
@@ -3432,11 +3766,13 @@ reparse_absdcl_as_expr (type, decl)
return build_functional_cast (type, NULL_TREE);
/* recurse */
- decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
+ decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
- if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
+ if (TREE_CODE (decl) == CALL_EXPR
+ && (! TREE_TYPE (decl)
+ || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE))
decl = require_complete_type (decl);
return decl;
@@ -3484,7 +3820,8 @@ reparse_absdcl_as_casts (decl, expr)
expr = build_c_cast (type, expr);
}
- if (warn_old_style_cast)
+ if (warn_old_style_cast && ! in_system_header
+ && current_lang_name != lang_name_c)
warning ("use of old-style cast");
return expr;
@@ -3655,11 +3992,30 @@ build_expr_from_tree (t)
TREE_OPERAND (ref, 1),
build_expr_from_tree (TREE_OPERAND (t, 2)));
}
- return build_method_call
- (build_expr_from_tree (TREE_OPERAND (t, 1)),
- TREE_OPERAND (t, 0),
- build_expr_from_tree (TREE_OPERAND (t, 2)),
- NULL_TREE, LOOKUP_NORMAL);
+ else
+ {
+ tree fn = TREE_OPERAND (t, 0);
+
+ /* We can get a TEMPLATE_ID_EXPR here on code like:
+
+ x->f<2>();
+
+ so we must resolve that. However, we can also get things
+ like a BIT_NOT_EXPR here, when referring to a destructor,
+ and things like that are not correctly resolved by
+ build_expr_from_tree. So, just use build_expr_from_tree
+ when we really need it. */
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ fn = lookup_template_function
+ (TREE_OPERAND (fn, 0),
+ build_expr_from_tree (TREE_OPERAND (fn, 1)));
+
+ return build_method_call
+ (build_expr_from_tree (TREE_OPERAND (t, 1)),
+ fn,
+ build_expr_from_tree (TREE_OPERAND (t, 2)),
+ NULL_TREE, LOOKUP_NORMAL);
+ }
case CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
@@ -3716,10 +4072,22 @@ build_expr_from_tree (t)
}
case COMPONENT_REF:
- return build_x_component_ref
- (build_expr_from_tree (TREE_OPERAND (t, 0)),
- TREE_OPERAND (t, 1), NULL_TREE, 1);
-
+ {
+ tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
+ tree field = TREE_OPERAND (t, 1);
+
+ /* We use a COMPONENT_REF to indicate things of the form `x.b'
+ and `x.A::b'. We must distinguish between those cases
+ here. */
+ if (TREE_CODE (field) == SCOPE_REF)
+ return build_object_ref (object,
+ TREE_OPERAND (field, 0),
+ TREE_OPERAND (field, 1));
+ else
+ return build_x_component_ref (object, field,
+ NULL_TREE, 1);
+ }
+
case THROW_EXPR:
return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
@@ -3733,6 +4101,7 @@ build_expr_from_tree (t)
r = build_nt (CONSTRUCTOR, NULL_TREE,
build_expr_from_tree (CONSTRUCTOR_ELTS (t)));
+ TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
if (TREE_TYPE (t))
return digest_init (TREE_TYPE (t), r, 0);
@@ -3800,6 +4169,10 @@ finish_decl_parsing (decl)
case ARRAY_REF:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
+ case TREE_LIST:
+ /* For attribute handling. */
+ TREE_VALUE (decl) = finish_decl_parsing (TREE_VALUE (decl));
+ return decl;
default:
my_friendly_abort (5);
return NULL_TREE;
@@ -3916,7 +4289,9 @@ add_using_namespace (user, used, indirect)
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
duplicates. The first list becomes the tail of the result.
- The algorithm is O(n^2). */
+ The algorithm is O(n^2). We could get this down to O(n log n) by
+ doing a sort on the addresses of the functions, if that becomes
+ necessary. */
static tree
merge_functions (s1, s2)
@@ -3958,8 +4333,7 @@ ambiguous_decl (name, old, new, flags)
/* If we expect types or namespaces, and not templates,
or this is not a template class. */
if (LOOKUP_QUALIFIERS_ONLY (flags)
- && (!(flags & LOOKUP_TEMPLATES_EXPECTED)
- || !DECL_CLASS_TEMPLATE_P (val)))
+ && !DECL_CLASS_TEMPLATE_P (val))
val = NULL_TREE;
break;
case TYPE_DECL:
@@ -3990,9 +4364,15 @@ ambiguous_decl (name, old, new, flags)
/* Some declarations are functions, some are not. */
if (flags & LOOKUP_COMPLAIN)
{
- cp_error ("use of `%D' is ambiguous", name);
- cp_error_at (" first declared as `%#D' here",
- BINDING_VALUE (old));
+ /* If we've already given this error for this lookup,
+ BINDING_VALUE (old) is error_mark_node, so let's not
+ repeat ourselves. */
+ if (BINDING_VALUE (old) != error_mark_node)
+ {
+ cp_error ("use of `%D' is ambiguous", name);
+ cp_error_at (" first declared as `%#D' here",
+ BINDING_VALUE (old));
+ }
cp_error_at (" also declared as `%#D' here", val);
}
return error_mark_node;
@@ -4086,9 +4466,10 @@ qualified_lookup_using_namespace (name, scope, result, flags)
outside scope. */
void
-set_decl_namespace (decl, scope)
+set_decl_namespace (decl, scope, friendp)
tree decl;
tree scope;
+ int friendp;
{
tree old;
if (scope == std_node)
@@ -4096,7 +4477,8 @@ set_decl_namespace (decl, scope)
/* Get rid of namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
- if (!is_namespace_ancestor (current_namespace, scope))
+ /* It is ok for friends to be qualified in parallel space. */
+ if (!friendp && !is_namespace_ancestor (current_namespace, scope))
cp_error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
@@ -4115,6 +4497,12 @@ set_decl_namespace (decl, scope)
/* Since decl is a function, old should contain a function decl. */
if (!is_overloaded_fn (old))
goto complain;
+ if (processing_template_decl || processing_specialization)
+ /* We have not yet called push_template_decl to turn the
+ FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
+ won't match. But, we'll check later, when we construct the
+ template. */
+ return;
for (; old; old = OVL_NEXT (old))
if (decls_match (decl, OVL_CURRENT (old)))
return;
@@ -4128,7 +4516,7 @@ set_decl_namespace (decl, scope)
/* Compute the namespace where a declaration is defined. */
-tree
+static tree
decl_namespace (decl)
tree decl;
{
@@ -4181,10 +4569,28 @@ pop_decl_namespace ()
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
-static void
-check_decl_namespace ()
+/* Enter a class or namespace scope. */
+
+void
+push_scope (t)
+ tree t;
{
- my_friendly_assert (decl_namespace_list == NULL_TREE, 980711);
+ if (TREE_CODE (t) == NAMESPACE_DECL)
+ push_decl_namespace (t);
+ else
+ pushclass (t, 2);
+}
+
+/* Leave scope pushed by push_scope. */
+
+void
+pop_scope (t)
+ tree t;
+{
+ if (TREE_CODE (t) == NAMESPACE_DECL)
+ pop_decl_namespace ();
+ else
+ popclass ();
}
/* [basic.lookup.koenig] */
@@ -4201,6 +4607,10 @@ struct arg_lookup
static int arg_assoc PROTO((struct arg_lookup*, tree));
static int arg_assoc_args PROTO((struct arg_lookup*, tree));
+static int arg_assoc_type PROTO((struct arg_lookup*, tree));
+static int add_function PROTO((struct arg_lookup *, tree));
+static int arg_assoc_namespace PROTO((struct arg_lookup *, tree));
+static int arg_assoc_class PROTO((struct arg_lookup *, tree));
/* Add a function to the lookup structure.
Returns 1 on error. */
@@ -4300,7 +4710,7 @@ arg_assoc_class (k, type)
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
- list = innermost_args (CLASSTYPE_TI_ARGS (type), 0);
+ list = innermost_args (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc (k, TREE_VEC_ELT (list, i));
}
@@ -4351,6 +4761,7 @@ arg_assoc_type (k, type)
/* Associate the return type. */
return arg_assoc_type (k, TREE_TYPE (type));
case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
return 0;
case LANG_TYPE:
if (type == unknown_type_node)
@@ -4393,14 +4804,80 @@ arg_assoc (k, n)
if (TREE_CODE (n) == ADDR_EXPR)
n = TREE_OPERAND (n, 0);
+ if (TREE_CODE (n) == COMPONENT_REF)
+ n = TREE_OPERAND (n, 1);
+ if (TREE_CODE (n) == OFFSET_REF)
+ n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
- my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
+ if (TREE_CODE (n) == FUNCTION_DECL)
+ return arg_assoc_type (k, TREE_TYPE (n));
+ if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
+ {
+ /* [basic.lookup.koenig]
+
+ If T is a template-id, its associated namespaces and classes
+ are the namespace in which the template is defined; for
+ member templates, the member template's class; the namespaces
+ and classes associated with the types of the template
+ arguments provided for template type parameters (excluding
+ template template parameters); the namespaces in which any
+ template template arguments are defined; and the classes in
+ which any member templates used as template template
+ arguments are defined. [Note: non-type template arguments do
+ not contribute to the set of associated namespaces. ] */
+ tree template = TREE_OPERAND (n, 0);
+ tree args = TREE_OPERAND (n, 1);
+ tree ctx;
+ tree arg;
+
+ /* First, the template. There may actually be more than one if
+ this is an overloaded function template. But, in that case,
+ we only need the first; all the functions will be in the same
+ namespace. */
+ template = OVL_CURRENT (template);
+
+ ctx = CP_DECL_CONTEXT (template);
+
+ if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ {
+ if (arg_assoc_namespace (k, ctx) == 1)
+ return 1;
+ }
+ /* It must be a member template. */
+ else if (arg_assoc_class (k, ctx) == 1)
+ return 1;
+
+ /* Now the arguments. */
+ for (arg = args; arg != NULL_TREE; arg = TREE_CHAIN (arg))
+ {
+ tree t = TREE_VALUE (arg);
- for (; n; n = TREE_CHAIN (n))
- if (arg_assoc (k, OVL_FUNCTION (n)))
- return 1;
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ ctx = CP_DECL_CONTEXT (t);
+ if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ {
+ if (arg_assoc_namespace (k, ctx) == 1)
+ return 1;
+ }
+ else if (arg_assoc_class (k, ctx) == 1)
+ return 1;
+ }
+ else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't'
+ && arg_assoc_type (k, t) == 1)
+ return 1;
+ }
+ }
+ else
+ {
+ my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
+
+ for (; n; n = OVL_CHAIN (n))
+ if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
+ return 1;
+ }
return 0;
}
@@ -4432,9 +4909,6 @@ void
do_namespace_alias (alias, namespace)
tree alias, namespace;
{
- tree binding;
- tree old;
-
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
/* The parser did not find it, so it's not there. */
@@ -4462,6 +4936,16 @@ validate_nonmember_using_decl (decl, scope, name)
if (TREE_CODE (decl) == SCOPE_REF
&& TREE_OPERAND (decl, 0) == std_node)
{
+ if (namespace_bindings_p ()
+ && current_namespace == global_namespace)
+ /* There's no need for a using declaration at all, here,
+ since `std' is the same as `::'. We can't just pass this
+ on because we'll complain later about declaring something
+ in the same scope as a using declaration with the same
+ name. We return NULL_TREE which indicates to the caller
+ that there's no need to do any further processing. */
+ return NULL_TREE;
+
*scope = global_namespace;
*name = TREE_OPERAND (decl, 1);
}
@@ -4469,9 +4953,23 @@ validate_nonmember_using_decl (decl, scope, name)
{
*scope = TREE_OPERAND (decl, 0);
*name = TREE_OPERAND (decl, 1);
+
+ /* [namespace.udecl]
+
+ A using-declaration for a class member shall be a
+ member-declaration. */
+ if (TREE_CODE (*scope) != NAMESPACE_DECL)
+ {
+ if (TYPE_P (*scope))
+ cp_error ("`%T' is not a namespace", *scope);
+ else
+ cp_error ("`%D' is not a namespace", *scope);
+ return NULL_TREE;
+ }
}
else if (TREE_CODE (decl) == IDENTIFIER_NODE
- || TREE_CODE (decl) == TYPE_DECL)
+ || TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == TEMPLATE_DECL)
{
*scope = global_namespace;
*name = decl;
@@ -4521,17 +5019,37 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
*newval = oldval;
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
{
- /* Compare each new function with each old one.
- If the old function was also used, there is no conflict. */
+ tree new_fn = OVL_CURRENT (tmp);
+
+ /* [namespace.udecl]
+
+ If a function declaration in namespace scope or block
+ scope has the same name and the same parameter types as a
+ function introduced by a using declaration the program is
+ ill-formed. */
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
- if (OVL_CURRENT (tmp) == OVL_CURRENT (tmp1))
- break;
- else if (OVL_USED (tmp1))
- continue;
- else if (duplicate_decls (OVL_CURRENT (tmp), OVL_CURRENT (tmp1)))
- return;
+ {
+ tree old_fn = OVL_CURRENT (tmp1);
+
+ if (!OVL_USED (tmp1)
+ && compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
+ TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
+ {
+ /* There was already a non-using declaration in
+ this scope with the same parameter types. */
+ cp_error ("`%D' is already declared in this scope",
+ name);
+ break;
+ }
+ else if (duplicate_decls (new_fn, old_fn))
+ /* We're re-using something we already used
+ before. We don't need to add it again. */
+ break;
+ }
- /* Duplicate use, ignore */
+ /* If we broke out of the loop, there's no reason to add
+ this function to the using declarations for this
+ scope. */
if (tmp1)
continue;
@@ -4604,7 +5122,27 @@ do_local_using_decl (decl)
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
- set_identifier_local_value (name, newval);
+ {
+ if (is_overloaded_fn (newval))
+ {
+ tree fn, term;
+
+ /* We only need to push declarations for those functions
+ that were not already bound in the current level.
+ The old value might be NULL_TREE, it might be a single
+ function, or an OVERLOAD. */
+ if (oldval && TREE_CODE (oldval) == OVERLOAD)
+ term = OVL_FUNCTION (oldval);
+ else
+ term = oldval;
+ for (fn = newval; fn && OVL_CURRENT (fn) != term;
+ fn = OVL_NEXT (fn))
+ push_overloaded_decl (OVL_CURRENT (fn),
+ PUSH_LOCAL | PUSH_USING);
+ }
+ else
+ push_local_binding (name, newval, PUSH_USING);
+ }
if (newtype)
set_identifier_type_value (name, newtype);
}
@@ -4694,31 +5232,61 @@ mark_used (decl)
if (processing_template_decl)
return;
assemble_external (decl);
+
/* Is it a synthesized method that needs to be synthesized? */
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl)
&& DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
/* Kludge: don't synthesize for default args. */
&& current_function_decl)
synthesize_method (decl);
- if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
+
+ /* If this is a function or variable that is an instance of some
+ template, we now know that we will need to actually do the
+ instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO,
+ if it's a partial instantiation, but there's no need to
+ instantiate such a thing. We check that DECL is not an explicit
+ instantiation because that is not checked in instantiate_decl. */
+ if (TREE_CODE (decl) != TEMPLATE_DECL
+ && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+ && !DECL_EXPLICIT_INSTANTIATION (decl))
instantiate_decl (decl);
}
-/* Helper function for named_class_head_sans_basetype nonterminal. */
+/* Helper function for named_class_head_sans_basetype nonterminal. We
+ have just seen something of the form `AGGR SCOPE::ID'. Return a
+ TYPE_DECL for the type declared by ID in SCOPE. */
tree
handle_class_head (aggr, scope, id)
tree aggr, scope, id;
{
+ tree decl;
+
if (TREE_CODE (id) == TYPE_DECL)
- return id;
+ decl = id;
+ else if (DECL_CLASS_TEMPLATE_P (id))
+ decl = DECL_TEMPLATE_RESULT (id);
+ else
+ {
+ if (scope)
+ cp_error ("`%T' does not have a nested type named `%D'", scope, id);
+ else
+ cp_error ("no file-scope type named `%D'", id);
+
+ decl = TYPE_MAIN_DECL (xref_tag (aggr, make_anon_name (), 1));
+ }
- if (scope)
- cp_error ("`%T' does not have a nested type named `%D'", scope, id);
- else
- cp_error ("no file-scope type named `%D'", id);
+ /* This syntax is only allowed when we're defining a type, so we
+ enter the SCOPE. */
+ push_scope (CP_DECL_CONTEXT (decl));
+
+ /* If we see something like:
- id = xref_tag
- (aggr, make_anon_name (), NULL_TREE, 1);
- return TYPE_MAIN_DECL (id);
+ template <typename T> struct S::I ....
+
+ we must create a TEMPLATE_DECL for the nested type. */
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ decl = push_template_decl (decl);
+
+ return decl;
}
diff --git a/contrib/gcc/cp/errfn.c b/contrib/gcc/cp/errfn.c
index 8d20682..b5d3eec 100644
--- a/contrib/gcc/cp/errfn.c
+++ b/contrib/gcc/cp/errfn.c
@@ -1,5 +1,5 @@
/* Provide a call-back mechanism for handling error output.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-98, 1999 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GNU CC.
@@ -22,14 +22,9 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
+#include "cp-tree.h"
#include "toplev.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
/* cp_printer is the type of a function which converts an argument into
a string for digestion by printf. The cp_printer function should deal
with all memory management; the functions in this file will not free
@@ -45,25 +40,19 @@ int cp_silent = 0;
typedef void errorfn (); /* deliberately vague */
-extern char* cp_file_of PROTO((tree));
-extern int cp_line_of PROTO((tree));
+static void cp_thing PROTO ((errorfn *, int, const char *, va_list));
#define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
/* This function supports only `%s', `%d', `%%', and the C++ print
codes. */
-#ifdef __STDC__
-static void
-cp_thing (errorfn *errfn, int atarg1, const char *format, va_list ap)
-#else
static void
cp_thing (errfn, atarg1, format, ap)
errorfn *errfn;
int atarg1;
const char *format;
va_list ap;
-#endif
{
static char *buf;
static long buflen;
@@ -155,18 +144,15 @@ cp_thing (errfn, atarg1, format, ap)
}
else if (*f == '%')
{
- /* A `%%' has occurred in the input string. Since the
- string we produce here will be passed to vprintf we must
- preserve both `%' characters. */
+ /* A `%%' has occurred in the input string. Replace it with
+ a `%' in the formatted message buf. */
- len += 2;
- if (len > buflen)
+ if (++len > buflen)
{
buflen = len;
buf = xrealloc (buf, len);
}
- strcpy (buf + offset, "%%");
- offset += 2;
+ buf[offset++] = '%';
}
else
{
@@ -196,88 +182,170 @@ cp_thing (errfn, atarg1, format, ap)
{
char *file = cp_file_of (atarg);
int line = cp_line_of (atarg);
- (*errfn) (file, line, buf);
+ (*errfn) (file, line, "%s", buf);
}
else
- (*errfn) (buf);
+ (*errfn) ("%s", buf);
}
-#ifdef __STDC__
-#define DECLARE(name) void name (const char *format, ...)
-#define INIT va_start (ap, format)
-#else
-#define DECLARE(name) void name (format, va_alist) char *format; va_dcl
-#define INIT va_start (ap)
-#endif
-
-DECLARE (cp_error)
+void
+cp_error VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) error, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_warning)
+void
+cp_warning VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) warning, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_pedwarn)
+void
+cp_pedwarn VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) pedwarn, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_compiler_error)
+void
+cp_compiler_error VPROTO((const char *format, ...))
{
- extern errorfn compiler_error;
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
- cp_thing (compiler_error, 0, format, ap);
+ cp_thing ((errorfn *) compiler_error, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_sprintf)
+void
+cp_deprecated (msg)
+ const char *msg;
{
+ extern int warn_deprecated;
+ if (!warn_deprecated)
+ return;
+ cp_warning ("%s is deprecated.", msg);
+ cp_warning ("Please see the documentation for details.");
+}
+
+void
+cp_sprintf VPROTO((const char *format, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
cp_thing ((errorfn *) sprintf, 0, format, ap);
va_end (ap);
}
-DECLARE (cp_error_at)
+void
+cp_error_at VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) error_with_file_and_line, 1, format, ap);
va_end (ap);
}
-DECLARE (cp_warning_at)
+void
+cp_warning_at VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) warning_with_file_and_line, 1, format, ap);
va_end (ap);
}
-DECLARE (cp_pedwarn_at)
+void
+cp_pedwarn_at VPROTO((const char *format, ...))
{
+#ifndef ANSI_PROTOTYPES
+ char *format;
+#endif
va_list ap;
- INIT;
+
+ VA_START (ap, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, char *);
+#endif
+
if (! cp_silent)
cp_thing ((errorfn *) pedwarn_with_file_and_line, 1, format, ap);
va_end (ap);
diff --git a/contrib/gcc/cp/error.c b/contrib/gcc/cp/error.c
index bb21bcb..4da1d2f 100644
--- a/contrib/gcc/cp/error.c
+++ b/contrib/gcc/cp/error.c
@@ -1,6 +1,6 @@
/* Call-backs for C++ error reporting.
This code is non-reentrant.
- Copyright (C) 1993, 94-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-97, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -32,6 +32,7 @@ typedef char* cp_printer ();
#define C code_as_string
#define D decl_as_string
#define E expr_as_string
+#define F fndecl_as_string
#define L language_as_string
#define O op_as_string
#define P parm_as_string
@@ -47,7 +48,7 @@ cp_printer * cp_printers[256] =
o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x10 */
o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x20 */
o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x30 */
- o, A, o, C, D, E, o, o, o, o, o, o, L, o, o, O, /* 0x40 */
+ o, A, o, C, D, E, F, o, o, o, o, o, L, o, o, O, /* 0x40 */
P, Q, o, o, T, o, V, o, o, o, o, o, o, o, o, o, /* 0x50 */
o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x60 */
o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x70 */
@@ -55,6 +56,7 @@ cp_printer * cp_printers[256] =
#undef C
#undef D
#undef E
+#undef F
#undef L
#undef O
#undef P
@@ -84,6 +86,11 @@ static char *scratch_firstobj;
OB_PUTCP (digit_buffer); } while (0)
# define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));
+# define OB_END_TEMPLATE_ID() \
+ ((obstack_next_free (&scratch_obstack) != obstack_base (&scratch_obstack) \
+ && obstack_next_free (&scratch_obstack)[-1] == '>') \
+ ? OB_PUTC2 (' ', '>') : OB_PUTC ('>'))
+
# define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
enum pad { none, before, after };
@@ -102,10 +109,13 @@ static void dump_type_suffix PROTO((tree, int, int));
static void dump_function_name PROTO((tree));
static void dump_expr_list PROTO((tree));
static void dump_global_iord PROTO((tree));
-static void dump_readonly_or_volatile PROTO((tree, enum pad));
+static void dump_qualifiers PROTO((tree, enum pad));
static void dump_char PROTO((int));
+static void dump_parameters PROTO((tree, int, int));
+static void dump_exception_spec PROTO((tree, int));
static char *aggr_variety PROTO((tree));
static tree ident_fndecl PROTO((tree));
+static int interesting_scope_p PROTO((tree));
void
init_error ()
@@ -114,20 +124,61 @@ init_error ()
scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
}
+/* Returns nonzero if SCOPE is something we want to print for random decls. */
+
+static int
+interesting_scope_p (scope)
+ tree scope;
+{
+ if (scope == NULL_TREE
+ || scope == global_namespace)
+ return 0;
+
+ return (TREE_CODE (scope) == NAMESPACE_DECL
+ || AGGREGATE_TYPE_P (scope));
+}
+
static void
-dump_readonly_or_volatile (t, p)
+dump_qualifiers (t, p)
tree t;
enum pad p;
{
- if (TYPE_READONLY (t) || TYPE_VOLATILE (t))
+ if (TYPE_QUALS (t))
{
if (p == before) OB_PUTC (' ');
- if (TYPE_READONLY (t))
- OB_PUTS ("const");
- if (TYPE_READONLY (t) && TYPE_VOLATILE (t))
- OB_PUTC (' ');
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile");
+ switch (TYPE_QUALS (t))
+ {
+ case TYPE_QUAL_CONST:
+ OB_PUTS ("const");
+ break;
+
+ case TYPE_QUAL_VOLATILE:
+ OB_PUTS ("volatile");
+ break;
+
+ case TYPE_QUAL_RESTRICT:
+ OB_PUTS ("__restrict");
+ break;
+
+ case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
+ OB_PUTS ("const volatile");
+ break;
+
+ case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
+ OB_PUTS ("const __restrict");
+ break;
+
+ case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
+ OB_PUTS ("volatile __restrict");
+ break;
+
+ case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
+ OB_PUTS ("const volatile __restrict");
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
if (p == after) OB_PUTC (' ');
}
}
@@ -161,26 +212,8 @@ dump_type_real (t, v, canonical_name)
break;
case TREE_LIST:
- /* i.e. function taking no arguments */
- if (t != void_list_node)
- {
- dump_type_real (TREE_VALUE (t), v, canonical_name);
- /* Can this happen other than for default arguments? */
- if (TREE_PURPOSE (t) && v)
- {
- OB_PUTS (" = ");
- dump_expr (TREE_PURPOSE (t), 0);
- }
- if (TREE_CHAIN (t))
- {
- if (TREE_CHAIN (t) != void_list_node)
- {
- OB_PUTC2 (',', ' ');
- dump_type_real (TREE_CHAIN (t), v, canonical_name);
- }
- }
- else OB_PUTS (" ...");
- }
+ /* A list of function parms. */
+ dump_parameters (t, 0, canonical_name);
break;
case IDENTIFIER_NODE:
@@ -197,8 +230,7 @@ dump_type_real (t, v, canonical_name)
if (TYPE_LANG_SPECIFIC (t)
&& (IS_SIGNATURE_POINTER (t) || IS_SIGNATURE_REFERENCE (t)))
{
- if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
dump_type_real (SIGNATURE_TYPE (t), v, canonical_name);
if (IS_SIGNATURE_POINTER (t))
OB_PUTC ('*');
@@ -211,6 +243,7 @@ dump_type_real (t, v, canonical_name)
case TYPE_DECL:
case TEMPLATE_DECL:
+ case NAMESPACE_DECL:
dump_decl (t, v);
break;
@@ -231,7 +264,7 @@ dump_type_real (t, v, canonical_name)
case BOOLEAN_TYPE:
{
tree type;
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
type = canonical_name ? TYPE_MAIN_VARIANT (t) : t;
if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
OB_PUTID (TYPE_IDENTIFIER (type));
@@ -244,7 +277,7 @@ dump_type_real (t, v, canonical_name)
break;
case TEMPLATE_TEMPLATE_PARM:
- if (!CLASSTYPE_TEMPLATE_INFO (t))
+ if (!TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
{
/* For parameters inside template signature. */
if (TYPE_IDENTIFIER (t))
@@ -255,7 +288,7 @@ dump_type_real (t, v, canonical_name)
else
{
int i;
- tree args = CLASSTYPE_TI_ARGS (t);
+ tree args = TYPE_TI_ARGS (t);
OB_PUTID (TYPE_IDENTIFIER (t));
OB_PUTC ('<');
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
@@ -269,12 +302,12 @@ dump_type_real (t, v, canonical_name)
if (i < TREE_VEC_LENGTH (args)-1)
OB_PUTC2 (',', ' ');
}
- OB_PUTC ('>');
+ OB_END_TEMPLATE_ID ();
}
break;
case TEMPLATE_TYPE_PARM:
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
if (TYPE_IDENTIFIER (t))
OB_PUTID (TYPE_IDENTIFIER (t));
else
@@ -298,7 +331,13 @@ dump_type_real (t, v, canonical_name)
OB_PUTS ("typename ");
dump_type_real (TYPE_CONTEXT (t), 0, canonical_name);
OB_PUTS ("::");
- OB_PUTID (TYPE_IDENTIFIER (t));
+ dump_decl (TYPENAME_TYPE_FULLNAME (t), v);
+ break;
+
+ case TYPEOF_TYPE:
+ OB_PUTS ("__typeof (");
+ dump_expr (TYPE_FIELDS (t), 1);
+ OB_PUTC (')');
break;
default:
@@ -342,7 +381,7 @@ dump_aggr_type (t, v, canonical_name)
tree name;
char *variety = aggr_variety (t);
- dump_readonly_or_volatile (t, after);
+ dump_qualifiers (t, after);
if (v > 0)
{
@@ -352,7 +391,7 @@ dump_aggr_type (t, v, canonical_name)
name = TYPE_NAME (canonical_name ? TYPE_MAIN_VARIANT (t) : t);
- if (name && DECL_CONTEXT (name) && DECL_CONTEXT (name) != global_namespace)
+ if (name && CP_DECL_CONTEXT (name) != global_namespace)
{
/* FUNCTION_DECL or RECORD_TYPE */
dump_decl (DECL_CONTEXT (name), 0);
@@ -403,13 +442,14 @@ dump_type_prefix (t, v, canonical_name)
switch (TREE_CODE (t))
{
case POINTER_TYPE:
+ case REFERENCE_TYPE:
{
tree sub = TREE_TYPE (t);
dump_type_prefix (sub, v, canonical_name);
/* A tree for a member pointer looks like pointer to offset,
so let the OFFSET_TYPE case handle it. */
- if (TREE_CODE (sub) != OFFSET_TYPE)
+ if (!TYPE_PTRMEM_P (t))
{
switch (TREE_CODE (sub))
{
@@ -424,42 +464,20 @@ dump_type_prefix (t, v, canonical_name)
case POINTER_TYPE:
/* We don't want "char * *" */
- if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
+ if (TYPE_QUALS (sub) == TYPE_UNQUALIFIED)
break;
/* But we do want "char *const *" */
default:
OB_PUTC (' ');
}
- OB_PUTC ('*');
- dump_readonly_or_volatile (t, none);
- }
- }
- break;
-
- case REFERENCE_TYPE:
- {
- tree sub = TREE_TYPE (t);
- dump_type_prefix (sub, v, canonical_name);
-
- switch (TREE_CODE (sub))
- {
- case ARRAY_TYPE:
- OB_PUTC2 (' ', '(');
- break;
-
- case POINTER_TYPE:
- /* We don't want "char * &" */
- if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
- break;
- /* But we do want "char *const &" */
-
- default:
- OB_PUTC (' ');
+ if (TREE_CODE (t) == POINTER_TYPE)
+ OB_PUTC ('*');
+ else
+ OB_PUTC ('&');
+ dump_qualifiers (t, none);
}
}
- OB_PUTC ('&');
- dump_readonly_or_volatile (t, none);
break;
case OFFSET_TYPE:
@@ -472,7 +490,7 @@ dump_type_prefix (t, v, canonical_name)
OB_PUTC2 (':', ':');
}
OB_PUTC ('*');
- dump_readonly_or_volatile (t, none);
+ dump_qualifiers (t, none);
break;
/* Can only be reached through function pointer -- this would not be
@@ -543,20 +561,20 @@ dump_type_suffix (t, v, canonical_name)
case METHOD_TYPE:
{
tree arg;
- OB_PUTC2 (')', '(');
+ OB_PUTC (')');
arg = TYPE_ARG_TYPES (t);
if (TREE_CODE (t) == METHOD_TYPE)
arg = TREE_CHAIN (arg);
- if (arg)
- dump_type (arg, v);
- else
- OB_PUTS ("...");
- OB_PUTC (')');
+ /* Function pointers don't have default args. Not in standard C++,
+ anyway; they may in g++, but we'll just pretend otherwise. */
+ dump_parameters (arg, 0, canonical_name);
+
if (TREE_CODE (t) == METHOD_TYPE)
- dump_readonly_or_volatile
+ dump_qualifiers
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
dump_type_suffix (TREE_TYPE (t), v, canonical_name);
+ dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), canonical_name);
break;
}
@@ -571,7 +589,7 @@ dump_type_suffix (t, v, canonical_name)
else
dump_expr (fold (build_binary_op
(PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
- integer_one_node, 1)), 0);
+ integer_one_node)), 0);
}
OB_PUTC (']');
dump_type_suffix (TREE_TYPE (t), v, canonical_name);
@@ -666,12 +684,11 @@ dump_simple_decl (t, type, v)
{
dump_type_prefix (type, v, 0);
OB_PUTC (' ');
- dump_readonly_or_volatile (t, after);
}
- if (DECL_CLASS_SCOPE_P (t))
+ if (interesting_scope_p (DECL_CONTEXT (t)))
{
- dump_type (DECL_CONTEXT (t), 0);
- OB_PUTC2 (':', ':');
+ dump_decl (DECL_CONTEXT (t), 0);
+ OB_PUTC2 (':',':');
}
if (DECL_NAME (t))
dump_decl (DECL_NAME (t), v);
@@ -718,7 +735,13 @@ dump_decl (t, v)
if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
{
OB_PUTS ("vtable for ");
- dump_type (DECL_CONTEXT (t), v);
+ if (TYPE_P (DECL_CONTEXT (t)))
+ dump_type (DECL_CONTEXT (t), v);
+ else
+ /* This case can arise with -fno-vtable-thunks. See
+ expand_upcast_fixups. It's not clear what to print
+ here. */
+ OB_PUTS ("{unknown type}");
break;
}
/* else fall through */
@@ -728,12 +751,15 @@ dump_decl (t, v)
break;
case NAMESPACE_DECL:
- if (DECL_CONTEXT (t) != global_namespace)
+ if (CP_DECL_CONTEXT (t) != global_namespace)
{
dump_decl (DECL_CONTEXT (t), v);
OB_PUTC2 (':',':');
}
- OB_PUTID (DECL_NAME (t));
+ if (DECL_NAME (t) == anonymous_namespace_name)
+ OB_PUTS ("{anonymous}");
+ else
+ OB_PUTID (DECL_NAME (t));
break;
case SCOPE_REF:
@@ -790,6 +816,10 @@ dump_decl (t, v)
}
break;
+ case OVERLOAD:
+ t = OVL_CURRENT (t);
+ /* Fall through. */
+
case FUNCTION_DECL:
if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t)))
dump_global_iord (DECL_ASSEMBLER_NAME (t));
@@ -843,12 +873,15 @@ dump_decl (t, v)
}
if (len != 0)
OB_UNPUT (2);
- OB_PUTC2 ('>', ' ');
+ OB_END_TEMPLATE_ID ();
+ OB_PUTC (' ');
}
nreverse(orig_args);
if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
dump_type (TREE_TYPE (t), v);
+ else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
+ dump_decl (DECL_TEMPLATE_RESULT (t), v);
else if (TREE_TYPE (t) == NULL_TREE)
my_friendly_abort (353);
else switch (NEXT_CODE (t))
@@ -883,7 +916,7 @@ dump_decl (t, v)
if (TREE_CHAIN (args))
OB_PUTC2 (',', ' ');
}
- OB_PUTC ('>');
+ OB_END_TEMPLATE_ID ();
}
break;
@@ -921,9 +954,15 @@ dump_decl (t, v)
}
}
-/* Pretty printing for announce_function. T is the declaration of the
- function we are interested in seeing. V is non-zero if we should print
- the type that this function returns. */
+/* Pretty print a function decl. There are several ways we want to print a
+ function declaration. We use V to tell us what.
+ V - 01 23
+ args - ++ ++
+ retval - -+ ++
+ default- -+ -+
+ throw - -- ++
+ As cp_error can only apply the '#' flag once to give 0 and 1 for V, there
+ is %D which doesn't print the throw specs, and %F which does. */
static void
dump_function_decl (t, v)
@@ -943,28 +982,28 @@ dump_function_decl (t, v)
parmtypes = TYPE_ARG_TYPES (fntype);
/* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */
- if (DECL_CONTEXT (t))
+ if (DECL_CLASS_SCOPE_P (t))
cname = DECL_CLASS_CONTEXT (t);
/* this is for partially instantiated template methods */
else if (TREE_CODE (fntype) == METHOD_TYPE)
cname = TREE_TYPE (TREE_VALUE (parmtypes));
- v = (v > 0);
-
- if (v)
+ /* Print the return type. */
+ if (v > 0)
{
if (DECL_STATIC_FUNCTION_P (t))
OB_PUTS ("static ");
- if (! IDENTIFIER_TYPENAME_P (name)
+ if (! DECL_CONV_FN_P (t)
&& ! DECL_CONSTRUCTOR_P (t)
- && ! DESTRUCTOR_NAME_P (name))
+ && ! DECL_DESTRUCTOR_P (t))
{
dump_type_prefix (TREE_TYPE (fntype), 1, 0);
OB_PUTC (' ');
}
}
+ /* Print the function name. */
if (cname)
{
dump_type (cname, 0);
@@ -975,34 +1014,98 @@ dump_function_decl (t, v)
/* Skip past "in_charge" identifier. */
parmtypes = TREE_CHAIN (parmtypes);
}
+ else if (CP_DECL_CONTEXT (t) != global_namespace)
+ {
+ dump_decl (DECL_CONTEXT (t), 0);
+ OB_PUTC2 (':',':');
+ }
if (DESTRUCTOR_NAME_P (name) && DECL_LANGUAGE (t) == lang_cplusplus)
parmtypes = TREE_CHAIN (parmtypes);
dump_function_name (t);
-
- OB_PUTC ('(');
-
- if (parmtypes)
- dump_type (parmtypes, v);
- else
- OB_PUTS ("...");
- OB_PUTC (')');
+ /* If V is negative, we don't print the argument types. */
+ if (v < 0)
+ return;
- if (v && ! IDENTIFIER_TYPENAME_P (name))
+ dump_parameters (parmtypes, v & 1, 0);
+
+ if (v && ! DECL_CONV_FN_P (t))
dump_type_suffix (TREE_TYPE (fntype), 1, 0);
if (TREE_CODE (fntype) == METHOD_TYPE)
{
if (IS_SIGNATURE (cname))
/* We look at the type pointed to by the `optr' field of `this.' */
- dump_readonly_or_volatile
+ dump_qualifiers
(TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (TYPE_ARG_TYPES (fntype))))), before);
else
- dump_readonly_or_volatile
+ dump_qualifiers
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), before);
}
+
+ if (v >= 2)
+ dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), 0);
+}
+
+/* Print a parameter list. V indicates if we show default values or not. If
+ these are for a member function, the member object ptr
+ (and any other hidden args) should have already been removed. */
+
+static void
+dump_parameters (parmtypes, v, canonical_name)
+ tree parmtypes;
+ int v;
+ int canonical_name;
+{
+ int first;
+ OB_PUTC ('(');
+
+ for (first = 1; parmtypes != void_list_node;
+ parmtypes = TREE_CHAIN (parmtypes))
+ {
+ if (!first)
+ OB_PUTC2 (',', ' ');
+ first = 0;
+ if (!parmtypes)
+ {
+ OB_PUTS ("...");
+ break;
+ }
+ dump_type_real (TREE_VALUE (parmtypes), 0, canonical_name);
+
+ if (TREE_PURPOSE (parmtypes) && v)
+ {
+ OB_PUTS (" = ");
+ dump_expr (TREE_PURPOSE (parmtypes), 0);
+ }
+ }
+
+ OB_PUTC (')');
+}
+
+/* Print an exception specification. T is the exception specification. */
+
+static void
+dump_exception_spec (t, canonical_name)
+ tree t;
+ int canonical_name;
+{
+ if (t)
+ {
+ OB_PUTS (" throw (");
+ if (TREE_VALUE (t) != NULL_TREE)
+ while (1)
+ {
+ dump_type_real (TREE_VALUE (t), 0, canonical_name);
+ t = TREE_CHAIN (t);
+ if (!t)
+ break;
+ OB_PUTC2 (',', ' ');
+ }
+ OB_PUTC (')');
+ }
}
/* Handle the function name for a FUNCTION_DECL node, grokking operators
@@ -1014,15 +1117,12 @@ dump_function_name (t)
{
tree name = DECL_NAME (t);
- /* There ought to be a better way to find out whether or not something is
- a destructor. */
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))
- && DECL_LANGUAGE (t) == lang_cplusplus)
+ if (DECL_DESTRUCTOR_P (t))
{
OB_PUTC ('~');
dump_decl (name, 0);
}
- else if (IDENTIFIER_TYPENAME_P (name))
+ else if (DECL_CONV_FN_P (t))
{
/* This cannot use the hack that the operator's return
type is stashed off of its name because it may be
@@ -1042,91 +1142,75 @@ dump_function_name (t)
else
dump_decl (name, 0);
- if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t))
+ if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
+ && DECL_TEMPLATE_INFO (t)
+ && (DECL_TEMPLATE_SPECIALIZATION (t)
+ || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
+ || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (t))
+ || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
{
tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE;
+ OB_PUTC ('<');
- if (args != NULL_TREE
- && DECL_CONTEXT (t) != NULL_TREE
- && uses_template_parms (DECL_CONTEXT (t))
- /* This next clause checks that there is only one level of
- template arguments. In that case, they are the
- arguments for the class context. */
- && (TREE_CODE (args) == TREE_LIST
- || (TREE_CODE (args) == TREE_VEC
- && TREE_VEC_ELT (args, 0) != NULL_TREE
- && TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)))
- /* We have something like this:
-
- template <class T> struct S { void f(); };
-
- and we are printing S<int>::f(). This is a template
- instantiation, but we don't print anything after the f. */
- ;
- else
+ /* Be careful only to print things when we have them, so as not
+ to crash producing error messages. */
+ if (args)
{
- OB_PUTC ('<');
-
- /* Be careful only to print things when we have them, so as not
- to crash producing error messages. */
- if (args)
+ if (TREE_CODE (args) == TREE_LIST)
{
- if (TREE_CODE (args) == TREE_LIST)
+ tree arg;
+ int need_comma = 0;
+
+ for (arg = args; arg; arg = TREE_CHAIN (arg))
{
- tree arg;
- int need_comma = 0;
-
- for (arg = args; arg; arg = TREE_CHAIN (arg))
- {
- tree a = TREE_VALUE (arg);
-
- if (need_comma)
- OB_PUTS (", ");
-
- if (a)
- {
- if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
- || TREE_CODE (a) == TEMPLATE_DECL)
- dump_type (a, 0);
- else
- dump_expr (a, 0);
- }
+ tree a = TREE_VALUE (arg);
+
+ if (need_comma)
+ OB_PUTS (", ");
- need_comma = 1;
+ if (a)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
+ || TREE_CODE (a) == TEMPLATE_DECL)
+ dump_type (a, 0);
+ else
+ dump_expr (a, 0);
}
+
+ need_comma = 1;
}
- else if (TREE_CODE (args) == TREE_VEC)
+ }
+ else if (TREE_CODE (args) == TREE_VEC)
+ {
+ int i;
+ int need_comma = 0;
+
+ if (TREE_VEC_LENGTH (args) > 0
+ && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+ args = TREE_VEC_ELT (args,
+ TREE_VEC_LENGTH (args) - 1);
+
+ for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
- int i;
- int need_comma = 0;
-
- if (TREE_VEC_LENGTH (args) > 0
- && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
- args = TREE_VEC_ELT (args,
- TREE_VEC_LENGTH (args) - 1);
-
- for (i = 0; i < TREE_VEC_LENGTH (args); i++)
- {
- tree a = TREE_VEC_ELT (args, i);
-
- if (need_comma)
- OB_PUTS (", ");
-
- if (a)
- {
- if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
- || TREE_CODE (a) == TEMPLATE_DECL)
- dump_type (a, 0);
- else
- dump_expr (a, 0);
- }
+ tree a = TREE_VEC_ELT (args, i);
+
+ if (need_comma)
+ OB_PUTS (", ");
- need_comma = 1;
+ if (a)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
+ || TREE_CODE (a) == TEMPLATE_DECL)
+ dump_type (a, 0);
+ else
+ dump_expr (a, 0);
}
+
+ need_comma = 1;
}
}
- OB_PUTC ('>');
}
+ OB_END_TEMPLATE_ID ();
}
}
@@ -1278,6 +1362,13 @@ dump_expr (t, nop)
OB_PUTCP (digit_buffer);
break;
+ case PTRMEM_CST:
+ OB_PUTC ('&');
+ dump_type (PTRMEM_CST_CLASS (t), 0);
+ OB_PUTS ("::");
+ OB_PUTID (DECL_NAME (PTRMEM_CST_MEMBER (t)));
+ break;
+
case STRING_CST:
{
char *p = TREE_STRING_POINTER (t);
@@ -1310,7 +1401,6 @@ dump_expr (t, nop)
{
OB_PUTS ("new ");
dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
- PARM_DECL_EXPR (t) = 1;
}
else
{
@@ -1485,6 +1575,7 @@ dump_expr (t, nop)
else
{
if (TREE_OPERAND (t,0) != NULL_TREE
+ && TREE_TYPE (TREE_OPERAND (t, 0))
&& NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
dump_expr (TREE_OPERAND (t, 0), nop);
else
@@ -1544,11 +1635,20 @@ dump_expr (t, nop)
if (integer_all_onesp (idx))
{
tree pfn = PFN_FROM_PTRMEMFUNC (t);
- dump_expr (pfn, 0);
+ dump_unary_op ("&", pfn, 0);
break;
}
- if (TREE_CODE (idx) == INTEGER_CST
- && TREE_INT_CST_HIGH (idx) == 0)
+ else if (TREE_CODE (idx) == INTEGER_CST
+ && tree_int_cst_equal (idx, integer_zero_node))
+ {
+ /* A NULL pointer-to-member constant. */
+ OB_PUTS ("((");
+ dump_type (TREE_TYPE (t), 0);
+ OB_PUTS (") 0)");
+ break;
+ }
+ else if (TREE_CODE (idx) == INTEGER_CST
+ && TREE_INT_CST_HIGH (idx) == 0)
{
tree virtuals;
unsigned HOST_WIDE_INT n;
@@ -1583,15 +1683,29 @@ dump_expr (t, nop)
case OFFSET_REF:
{
tree ob = TREE_OPERAND (t, 0);
- if (TREE_CODE (ob) == NOP_EXPR
- && TREE_OPERAND (ob, 0) == error_mark_node
- && TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
- /* A::f */
- dump_expr (TREE_OPERAND (t, 1), 0);
+ if (is_dummy_object (ob))
+ {
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ /* A::f */
+ dump_expr (t, 0);
+ else if (BASELINK_P (t))
+ dump_expr (OVL_CURRENT (TREE_VALUE (t)), 0);
+ else
+ dump_decl (t, 0);
+ }
else
{
- dump_expr (TREE_OPERAND (t, 0), 0);
- OB_PUTS (" .* ");
+ if (TREE_CODE (ob) == INDIRECT_REF)
+ {
+ dump_expr (TREE_OPERAND (ob, 0), 0);
+ OB_PUTS (" ->* ");
+ }
+ else
+ {
+ dump_expr (ob, 0);
+ OB_PUTS (" .* ");
+ }
dump_expr (TREE_OPERAND (t, 1), 0);
}
break;
@@ -1666,6 +1780,10 @@ dump_expr (t, nop)
dump_expr (TREE_OPERAND (t, 0), nop);
break;
+ case TEMPLATE_ID_EXPR:
+ dump_decl (t, 0);
+ break;
+
case TREE_LIST:
if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
{
@@ -1714,12 +1832,20 @@ dump_unary_op (opstring, t, nop)
if (!nop) OB_PUTC (')');
}
+/* Print a function decl with exception specification included. */
+
char *
-fndecl_as_string (fndecl, print_ret_type_p)
+fndecl_as_string (fndecl, print_default_args_p)
tree fndecl;
- int print_ret_type_p;
+ int print_default_args_p;
{
- return decl_as_string (fndecl, print_ret_type_p);
+ OB_INIT ();
+
+ dump_function_decl (fndecl, 2 + print_default_args_p);
+
+ OB_FINISH ();
+
+ return (char *)obstack_base (&scratch_obstack);
}
/* Same, but handle a _TYPE.
@@ -1825,6 +1951,8 @@ cp_file_of (t)
return DECL_SOURCE_FILE (DECL_CONTEXT (t));
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t));
+ else if (TREE_CODE (t) == OVERLOAD)
+ return DECL_SOURCE_FILE (OVL_FUNCTION (t));
else
return DECL_SOURCE_FILE (t);
}
@@ -1836,11 +1964,14 @@ cp_line_of (t)
int line = 0;
if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
- if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
+ if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
+ && TYPE_MAIN_DECL (TREE_TYPE (t)))
t = TREE_TYPE (t);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t));
+ else if (TREE_CODE (t) == OVERLOAD)
+ line = DECL_SOURCE_LINE (OVL_FUNCTION (t));
else
line = DECL_SOURCE_LINE (t);
@@ -1954,7 +2085,7 @@ cv_as_string (p, v)
{
OB_INIT ();
- dump_readonly_or_volatile (p, before);
+ dump_qualifiers (p, before);
OB_FINISH ();
diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c
index d294497..9e2d6af 100644
--- a/contrib/gcc/cp/except.c
+++ b/contrib/gcc/cp/except.c
@@ -1,5 +1,5 @@
/* Handle exceptional things in C++.
- Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann <tiemann@cygnus.com>
Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
initial re-implementation courtesy Tad Hunt.
@@ -52,12 +52,13 @@ static tree call_eh_info PROTO((void));
static void push_eh_info PROTO((void));
static tree get_eh_info PROTO((void));
static tree get_eh_value PROTO((void));
+#if 0
static tree get_eh_type PROTO((void));
static tree get_eh_caught PROTO((void));
static tree get_eh_handlers PROTO((void));
+#endif
static tree do_pop_exception PROTO((void));
static void process_start_catch_block PROTO((tree, tree));
-static void process_start_catch_block_old PROTO((tree, tree));
static tree build_eh_type_type_ref PROTO((tree));
static tree build_terminate_handler PROTO((void));
static tree alloc_eh_object PROTO((tree));
@@ -248,14 +249,14 @@ call_eh_info ()
{
tree fn;
- fn = get_identifier ("__cp_eh_info");
+ fn = get_identifier ("__start_cp_handler");
if (IDENTIFIER_GLOBAL_VALUE (fn))
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
tree t1, t, fields[7];
- /* Declare cp_eh_info * __cp_eh_info (void),
+ /* Declare cp_eh_info * __start_cp_handler (void),
as defined in exception.cc. */
push_obstacks_nochange ();
end_temporary_allocation ();
@@ -269,9 +270,11 @@ call_eh_info ()
get_identifier ("dynamic_handler_chain"), ptr_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL,
get_identifier ("info"), ptr_type_node);
+ fields[3] = build_lang_field_decl (FIELD_DECL,
+ get_identifier ("table_index"), ptr_type_node);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
- finish_builtin_type (t1, "eh_context", fields, 2, ptr_type_node);
+ finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
t1 = build_pointer_type (t1);
t1= make_lang_type (RECORD_TYPE);
@@ -315,9 +318,9 @@ call_eh_info ()
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
return build_function_call (fn, NULL_TREE);
}
@@ -360,6 +363,7 @@ get_eh_value ()
/* Returns a reference to the current exception type. */
+#if 0
static tree
get_eh_type ()
{
@@ -386,6 +390,7 @@ get_eh_handlers ()
return build_component_ref (get_eh_info (), get_identifier ("handlers"),
NULL_TREE, 0);
}
+#endif
/* Build a type value for use at runtime for a type that is matched
against by the exception handling system. */
@@ -394,7 +399,7 @@ static tree
build_eh_type_type (type)
tree type;
{
- char *typestring;
+ const char *typestring;
tree exp;
if (type == error_mark_node)
@@ -408,9 +413,7 @@ build_eh_type_type (type)
type = TYPE_MAIN_VARIANT (type);
if (flag_rtti)
- {
- return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
- }
+ return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
typestring = build_overload_name (type, 1, 1);
exp = combine_strings (build_string (strlen (typestring)+1, typestring));
@@ -424,7 +427,7 @@ static tree
build_eh_type_type_ref (type)
tree type;
{
- char *typestring;
+ const char *typestring;
tree exp;
if (type == error_mark_node)
@@ -528,10 +531,10 @@ do_pop_exception ()
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
/* Arrange to do a dynamically scoped cleanup upon exit from this region. */
cleanup = lookup_name (get_identifier ("__exception_info"), 0);
cleanup = build_function_call (fn, expr_tree_cons
@@ -546,9 +549,6 @@ push_eh_cleanup ()
{
int yes;
- expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
- const0_rtx, VOIDmode, EXPAND_NORMAL);
-
yes = suspend_momentary ();
/* All cleanups must last longer than normal. */
expand_decl_cleanup (NULL_TREE, do_pop_exception ());
@@ -597,135 +597,14 @@ expand_start_catch_block (declspecs, declarator)
if (! doing_eh (1))
return;
- if (flag_new_exceptions)
- process_start_catch_block (declspecs, declarator);
- else
- process_start_catch_block_old (declspecs, declarator);
+ process_start_catch_block (declspecs, declarator);
}
/* This function performs the expand_start_catch_block functionality for
- exceptions implemented in the old style, where catch blocks were all
- called, and had to check the runtime information themselves. */
-
-static void
-process_start_catch_block_old (declspecs, declarator)
- tree declspecs, declarator;
-{
- rtx false_label_rtx;
- tree decl = NULL_TREE;
- tree init;
-
- /* Create a binding level for the eh_info and the exception object
- cleanup. */
- pushlevel (0);
- expand_start_bindings (0);
-
- false_label_rtx = gen_label_rtx ();
- push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
-
- emit_line_note (input_filename, lineno);
-
- push_eh_info ();
-
- if (declspecs)
- {
- decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
-
- if (decl == NULL_TREE)
- error ("invalid catch parameter");
- }
-
- if (decl)
- {
- tree exp;
- rtx call_rtx, return_value_rtx;
- tree init_type;
-
- /* Make sure we mark the catch param as used, otherwise we'll get
- a warning about an unused ((anonymous)). */
- TREE_USED (decl) = 1;
-
- /* Figure out the type that the initializer is. */
- init_type = TREE_TYPE (decl);
- if (TREE_CODE (init_type) != REFERENCE_TYPE
- && TREE_CODE (init_type) != POINTER_TYPE)
- init_type = build_reference_type (init_type);
-
- exp = get_eh_value ();
-
- /* Since pointers are passed by value, initialize a reference to
- pointer catch parm with the address of the value slot. */
- if (TREE_CODE (init_type) == REFERENCE_TYPE
- && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
- exp = build_unary_op (ADDR_EXPR, exp, 1);
-
- exp = expr_tree_cons (NULL_TREE,
- build_eh_type_type (TREE_TYPE (decl)),
- expr_tree_cons (NULL_TREE,
- get_eh_type (),
- expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
- exp = build_function_call (CatchMatch, exp);
- call_rtx = expand_call (exp, NULL_RTX, 0);
-
- return_value_rtx = hard_function_value (ptr_type_node, exp);
-
- /* did the throw type match function return TRUE? */
- emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
- GET_MODE (return_value_rtx), 0, 0);
-
- /* if it returned FALSE, jump over the catch block, else fall into it */
- emit_jump_insn (gen_beq (false_label_rtx));
-
- push_eh_cleanup ();
-
- /* Create a binding level for the parm. */
- pushlevel (0);
- expand_start_bindings (0);
-
- init = convert_from_reference (make_tree (init_type, call_rtx));
-
- /* If the constructor for the catch parm exits via an exception, we
- must call terminate. See eh23.C. */
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
- {
- /* Generate the copy constructor call directly so we can wrap it.
- See also expand_default_init. */
- init = ocp_convert (TREE_TYPE (decl), init,
- CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
- init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
- build_terminate_handler ());
- }
-
- /* Let `cp_finish_decl' know that this initializer is ok. */
- DECL_INITIAL (decl) = init;
- decl = pushdecl (decl);
-
- start_decl_1 (decl);
- cp_finish_decl (decl, DECL_INITIAL (decl),
- NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
- }
- else
- {
- push_eh_cleanup ();
-
- /* Create a binding level for the parm. */
- pushlevel (0);
- expand_start_bindings (0);
-
- /* Fall into the catch all section. */
- }
-
- init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
- expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- emit_line_note (input_filename, lineno);
-}
-
-/* This function performs the expand_start_catch_block functionality for
exceptions implemented in the new style. __throw determines whether
a handler needs to be called or not, so the handler itself has to do
- nothing additionaal. */
+ nothing additional. */
static void
process_start_catch_block (declspecs, declarator)
@@ -806,7 +685,9 @@ process_start_catch_block (declspecs, declarator)
DECL_INITIAL (decl) = init;
decl = pushdecl (decl);
- cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
+ start_decl_1 (decl);
+ cp_finish_decl (decl, init, NULL_TREE, 0,
+ LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
else
{
@@ -819,14 +700,10 @@ process_start_catch_block (declspecs, declarator)
/* Fall into the catch all section. */
}
- init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
- expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
emit_line_note (input_filename, lineno);
}
-
/* Call this to end a catch block. Its responsible for emitting the
code to handle jumping back to the correct place, and for emitting
the label to jump to if this catch block didn't match. */
@@ -850,10 +727,7 @@ expand_end_catch_block ()
documentation. */
expand_goto (top_label_entry (&caught_return_label_stack));
- /* label we emit to jump to if this catch block didn't match. */
- /* This the closing } in the `if (eq) {' of the documentation. */
- if (! flag_new_exceptions)
- emit_label (pop_label_entry (&false_label_stack));
+ end_catch_handler ();
}
/* An exception spec is implemented more or less like:
@@ -895,7 +769,7 @@ expand_end_eh_spec (raises)
TREE_HAS_CONSTRUCTOR (types) = 1;
/* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
- tmp = build_array_type (const_ptr_type_node, NULL_TREE);
+ tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
decl = build_decl (VAR_DECL, NULL_TREE, tmp);
DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = types;
@@ -923,10 +797,10 @@ expand_end_eh_spec (raises)
TREE_THIS_VOLATILE (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
(NULL_TREE, decl, NULL_TREE));
tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
@@ -1065,10 +939,10 @@ alloc_eh_object (type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
exp = build_function_call (fn, expr_tree_cons
(NULL_TREE, size_in_bytes (type), NULL_TREE));
exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
@@ -1118,11 +992,8 @@ expand_throw (exp)
pop_obstacks ();
}
- if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
- {
- throw_type = build_eh_type (exp);
- exp = build_reinterpret_cast (ptr_type_node, exp);
- }
+ if (TYPE_PTR_P (TREE_TYPE (exp)))
+ throw_type = build_eh_type (exp);
else
{
tree object, ptr;
@@ -1153,13 +1024,11 @@ expand_throw (exp)
ourselves into expand_call. */
if (TREE_SIDE_EFFECTS (exp))
{
- tree temp = build (VAR_DECL, TREE_TYPE (exp));
+ tree temp = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
DECL_ARTIFICIAL (temp) = 1;
- layout_decl (temp, 0);
DECL_RTL (temp) = assign_temp (TREE_TYPE (exp), 2, 0, 1);
- expand_expr (build (INIT_EXPR, TREE_TYPE (exp), temp, exp),
- NULL_RTX, VOIDmode, 0);
- expand_decl_cleanup (NULL_TREE, maybe_build_cleanup (temp));
+ DECL_INITIAL (temp) = exp;
+ cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
exp = temp;
}
#endif
@@ -1196,6 +1065,10 @@ expand_throw (exp)
exp = ptr;
}
+ /* Cast EXP to `void *' so that it will match the prototype for
+ __cp_push_exception. */
+ exp = convert (ptr_type_node, exp);
+
if (cleanup == NULL_TREE)
{
cleanup = build_int_2 (0, 0);
@@ -1223,10 +1096,10 @@ expand_throw (exp)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
(NULL_TREE, throw_type, expr_tree_cons
(NULL_TREE, cleanup, NULL_TREE)));
@@ -1254,10 +1127,10 @@ expand_throw (exp)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
exp = build_function_call (fn, NULL_TREE);
expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
@@ -1277,11 +1150,8 @@ build_throw (e)
if (processing_template_decl)
return build_min (THROW_EXPR, void_type_node, e);
- if (! flag_ansi && e == null_node)
- {
- cp_warning ("throwing NULL");
- e = integer_zero_node;
- }
+ if (e == null_node)
+ cp_warning ("throwing NULL, which has integral, not pointer type");
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;
diff --git a/contrib/gcc/cp/exception.cc b/contrib/gcc/cp/exception.cc
index 4c10404..8e8f35f 100644
--- a/contrib/gcc/cp/exception.cc
+++ b/contrib/gcc/cp/exception.cc
@@ -1,5 +1,5 @@
// Functions for Exception Support for -*- C++ -*-
-// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation
+// Copyright (C) 1994, 95-97, 1998 Free Software Foundation
// This file is part of GNU CC.
@@ -30,6 +30,7 @@
#include "typeinfo"
#include "exception"
#include <stddef.h>
+#include "gansidecl.h" /* Needed to support macros used in eh-common.h. */
#include "eh-common.h"
/* Define terminate, unexpected, set_terminate, set_unexpected as
@@ -116,13 +117,29 @@ __cp_exception_info (void)
return &((*__get_eh_info ())->value);
}
-/* Compiler hook to return a pointer to the info for the current exception.
+#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ())
+
+/* Old Compiler hook to return a pointer to the info for the current exception.
Used by get_eh_info (). */
extern "C" cp_eh_info *
__cp_eh_info (void)
{
- return *__get_eh_info ();
+ cp_eh_info *p = CP_EH_INFO;
+ return p;
+}
+
+/* Compiler hook to return a pointer to the info for the current exception,
+ Set the caught bit, and increment the number of handlers that are
+ looking at this exception. This makes handlers smaller. */
+
+extern "C" cp_eh_info *
+__start_cp_handler (void)
+{
+ cp_eh_info *p = CP_EH_INFO;
+ p->caught = 1;
+ p->handlers++;
+ return p;
}
/* Allocate a buffer for a cp_eh_info and an exception object of size SIZE,
@@ -157,7 +174,9 @@ __cplus_type_matcher (cp_eh_info *info, rtimetype match_info,
{
void *ret;
- if (exception_table->lang.language != EH_LANG_C_plus_plus)
+ /* No exception table implies the old style mechanism, so don't check. */
+ if (exception_table != NULL
+ && exception_table->lang.language != EH_LANG_C_plus_plus)
return NULL;
if (match_info == CATCH_ALL_TYPE)
@@ -231,7 +250,7 @@ __cp_pop_exception (cp_eh_info *p)
p->cleanup (p->value, 2);
if (! __is_pointer (p->type))
- __eh_free (p->value);
+ __eh_free (p->original_value); // value may have been co-erced.
__eh_free (p);
}
@@ -239,7 +258,7 @@ __cp_pop_exception (cp_eh_info *p)
extern "C" void
__uncatch_exception (void)
{
- cp_eh_info *p = __cp_eh_info ();
+ cp_eh_info *p = CP_EH_INFO;
if (p == 0)
terminate ();
p->caught = false;
@@ -260,7 +279,7 @@ __uncatch_exception (void)
extern "C" void
__check_eh_spec (int n, const void **spec)
{
- cp_eh_info *p = __cp_eh_info ();
+ cp_eh_info *p = CP_EH_INFO;
for (int i = 0; i < n; ++i)
{
@@ -313,7 +332,7 @@ __throw_bad_typeid (void)
bool
std::uncaught_exception ()
{
- cp_eh_info *p = __cp_eh_info ();
+ cp_eh_info *p = CP_EH_INFO;
return p && ! p->caught;
}
diff --git a/contrib/gcc/cp/expr.c b/contrib/gcc/cp/expr.c
index 4c3d8b6..83bdff9 100644
--- a/contrib/gcc/cp/expr.c
+++ b/contrib/gcc/cp/expr.c
@@ -1,6 +1,6 @@
/* Convert language-specific tree expression to rtl instructions,
for GNU compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -36,6 +36,62 @@ static tree extract_scalar_init PROTO((tree, tree));
static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode,
enum expand_modifier));
+/* Hook used by output_constant to expand language-specific
+ constants. */
+
+static tree
+cplus_expand_constant (cst)
+ tree cst;
+{
+ switch (TREE_CODE (cst))
+ {
+ case PTRMEM_CST:
+ {
+ tree type = TREE_TYPE (cst);
+ tree member;
+ tree offset;
+
+ /* Find the member. */
+ member = PTRMEM_CST_MEMBER (cst);
+
+ if (TREE_CODE (member) == FIELD_DECL)
+ {
+ /* Find the offset for the field. */
+ offset = convert (sizetype,
+ size_binop (EASY_DIV_EXPR,
+ DECL_FIELD_BITPOS (member),
+ size_int (BITS_PER_UNIT)));
+
+ /* We offset all pointer to data members by 1 so that we
+ can distinguish between a null pointer to data member
+ and the first data member of a structure. */
+ offset = size_binop (PLUS_EXPR, offset, size_int (1));
+
+ cst = cp_convert (type, offset);
+ }
+ else
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ expand_ptrmemfunc_cst (cst, &delta, &idx, &pfn, &delta2);
+
+ cst = build_ptrmemfunc1 (type, delta, idx,
+ pfn, delta2);
+ }
+ }
+ break;
+
+ default:
+ /* There's nothing to do. */
+ break;
+ }
+
+ return cst;
+}
+
/* Hook used by expand_expr to expand language-specific tree codes. */
static rtx
@@ -148,7 +204,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
init = convert_from_reference (init);
flag_access_control = 0;
- expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
+ expand_aggr_init (slot, init, LOOKUP_ONLYCONVERTING);
flag_access_control = old_ac;
if (TYPE_NEEDS_DESTRUCTOR (type))
@@ -162,19 +218,14 @@ cplus_expand_expr (exp, target, tmode, modifier)
return DECL_RTL (slot);
}
+ case PTRMEM_CST:
+ return expand_expr (cplus_expand_constant (exp),
+ target, tmode, modifier);
+
case OFFSET_REF:
{
-#if 1
return expand_expr (default_conversion (resolve_offset_ref (exp)),
target, tmode, EXPAND_NORMAL);
-#else
- /* This is old crusty code, and does not handle all that the
- resolve_offset_ref function does. (mrs) */
- tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
- tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
- return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
- target, tmode, EXPAND_NORMAL);
-#endif
}
case THUNK_DECL:
@@ -189,7 +240,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
(expand_vec_init
(NULL_TREE, TREE_OPERAND (exp, 0),
build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
- integer_one_node, 1),
+ integer_one_node),
TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
case NEW_EXPR:
@@ -207,6 +258,7 @@ void
init_cplus_expand ()
{
lang_expand_expr = cplus_expand_expr;
+ lang_expand_constant = cplus_expand_constant;
}
/* If DECL had its rtl moved from where callers expect it
@@ -304,7 +356,7 @@ extract_scalar_init (decl, init)
int
extract_init (decl, init)
- tree decl, init;
+ tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
{
return 0;
@@ -405,8 +457,5 @@ do_case (start, end)
cp_error ("case label `%E' within scope of cleanup or variable array", start);
}
}
- if (start)
- define_case_label (label);
- else
- define_case_label (NULL_TREE);
+ define_case_label ();
}
diff --git a/contrib/gcc/cp/friend.c b/contrib/gcc/cp/friend.c
index 58747ef..5085ebc 100644
--- a/contrib/gcc/cp/friend.c
+++ b/contrib/gcc/cp/friend.c
@@ -1,5 +1,5 @@
/* Help friends in C++.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,11 +27,10 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "toplev.h"
-static void add_friend PROTO((tree, tree));
-static void add_friends PROTO((tree, tree, tree));
-
/* Friend data structures are described in cp-tree.h. */
+/* Returns non-zero if SUPPLICANT is a friend of TYPE. */
+
int
is_friend (type, supplicant)
tree type, supplicant;
@@ -59,32 +58,40 @@ is_friend (type, supplicant)
for (; list ; list = TREE_CHAIN (list))
{
- if (name == TREE_PURPOSE (list))
+ if (name == FRIEND_NAME (list))
{
- tree friends = TREE_VALUE (list);
+ tree friends = FRIEND_DECLS (list);
for (; friends ; friends = TREE_CHAIN (friends))
{
- if (comptypes (ctype, TREE_PURPOSE (friends), 1))
+ if (same_type_p (ctype, TREE_PURPOSE (friends)))
return 1;
if (TREE_VALUE (friends) == NULL_TREE)
continue;
- if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL)
- {
- if (is_specialization_of (supplicant,
- TREE_VALUE (friends)))
- return 1;
-
- continue;
- }
-
- /* FIXME: The use of comptypes here is bogus, since
- two specializations of a template with non-type
- parameters may have the same type, but be
- different. */
- if (comptypes (TREE_TYPE (supplicant),
- TREE_TYPE (TREE_VALUE (friends)), 1))
+ if (supplicant == TREE_VALUE (friends))
+ return 1;
+
+ /* With -fguiding-decls we are more lenient about
+ friendship. This is bogus in general since two
+ specializations of a template with non-type
+ template parameters may have the same type, but
+ be different.
+
+ Temporarily, we are also more lenient to deal
+ with nested friend functions, for which there can
+ be more than one FUNCTION_DECL, despite being the
+ same function. When that's fixed, the
+ FUNCTION_MEMBER_P bit can go. */
+ if ((flag_guiding_decls
+ || DECL_FUNCTION_MEMBER_P (supplicant))
+ && same_type_p (TREE_TYPE (supplicant),
+ TREE_TYPE (TREE_VALUE (friends))))
+ return 1;
+
+ if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL
+ && is_specialization_of (supplicant,
+ TREE_VALUE (friends)))
return 1;
}
break;
@@ -104,7 +111,7 @@ is_friend (type, supplicant)
if (TREE_CODE (t) == TEMPLATE_DECL ?
is_specialization_of (TYPE_MAIN_DECL (supplicant), t) :
- comptypes (supplicant, t, 1))
+ same_type_p (supplicant, t))
return 1;
}
}
@@ -130,19 +137,27 @@ is_friend (type, supplicant)
/* Add a new friend to the friends of the aggregate type TYPE.
DECL is the FUNCTION_DECL of the friend being added. */
-static void
+void
add_friend (type, decl)
tree type, decl;
{
- tree typedecl = TYPE_MAIN_DECL (type);
- tree list = DECL_FRIENDLIST (typedecl);
- tree name = DECL_NAME (decl);
+ tree typedecl;
+ tree list;
+ tree name;
+
+ if (decl == error_mark_node)
+ return;
+
+ typedecl = TYPE_MAIN_DECL (type);
+ list = DECL_FRIENDLIST (typedecl);
+ name = DECL_NAME (decl);
+ type = TREE_TYPE (typedecl);
while (list)
{
- if (name == TREE_PURPOSE (list))
+ if (name == FRIEND_NAME (list))
{
- tree friends = TREE_VALUE (list);
+ tree friends = FRIEND_DECLS (list);
for (; friends ; friends = TREE_CHAIN (friends))
{
if (decl == TREE_VALUE (friends))
@@ -160,27 +175,20 @@ add_friend (type, decl)
}
list = TREE_CHAIN (list);
}
+
DECL_FRIENDLIST (typedecl)
= tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
DECL_FRIENDLIST (typedecl));
- if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
- {
- tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- if (parmtypes && TREE_CHAIN (parmtypes))
- {
- tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
- TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
- }
- }
+ if (!uses_template_parms (type))
+ DECL_BEFRIENDING_CLASSES (decl)
+ = tree_cons (NULL_TREE, type,
+ DECL_BEFRIENDING_CLASSES (decl));
}
/* Declare that every member function NAME in FRIEND_TYPE
(which may be NULL_TREE) is a friend of type TYPE. */
-static void
+void
add_friends (type, name, friend_type)
tree type, name, friend_type;
{
@@ -189,9 +197,9 @@ add_friends (type, name, friend_type)
while (list)
{
- if (name == TREE_PURPOSE (list))
+ if (name == FRIEND_NAME (list))
{
- tree friends = TREE_VALUE (list);
+ tree friends = FRIEND_DECLS (list);
while (friends && TREE_PURPOSE (friends) != friend_type)
friends = TREE_CHAIN (friends);
if (friends)
@@ -216,13 +224,6 @@ add_friends (type, name, friend_type)
= tree_cons (name,
build_tree_list (friend_type, NULL_TREE),
DECL_FRIENDLIST (typedecl));
- if (! strncmp (IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
- strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
- {
- TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
- sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
- }
}
/* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
@@ -247,18 +248,31 @@ make_friend_class (type, friend_type)
error ("`friend' declaration in signature definition");
return;
}
- if (IS_SIGNATURE (friend_type))
+ if (IS_SIGNATURE (friend_type) || ! IS_AGGR_TYPE (friend_type))
{
- error ("signature type `%s' declared `friend'",
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
+ cp_error ("invalid type `%T' declared `friend'", friend_type);
return;
}
+
+ if (CLASS_TYPE_P (friend_type)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
+ && uses_template_parms (friend_type))
+ {
+ /* [temp.friend]
+
+ Friend declarations shall not declare partial
+ specializations. */
+ cp_error ("partial specialization `%T' declared `friend'",
+ friend_type);
+ return;
+ }
+
if (processing_template_decl > template_class_depth (type))
/* If the TYPE is a template then it makes sense for it to be
friends with itself; this means that each instantiation is
friends with all other instantiations. */
is_template_friend = 1;
- else if (comptypes (type, friend_type, 1))
+ else if (same_type_p (type, friend_type))
{
pedwarn ("class `%s' is implicitly friends with itself",
TYPE_NAME_STRING (type));
@@ -277,7 +291,7 @@ make_friend_class (type, friend_type)
/* Stop if we find the same type on the list. */
&& !(TREE_CODE (TREE_VALUE (classes)) == TEMPLATE_DECL ?
friend_type == TREE_VALUE (classes) :
- comptypes (TREE_VALUE (classes), friend_type, 1)))
+ same_type_p (TREE_VALUE (classes), friend_type)))
classes = TREE_CHAIN (classes);
if (classes)
cp_warning ("`%T' is already a friend of `%T'",
@@ -286,6 +300,12 @@ make_friend_class (type, friend_type)
{
CLASSTYPE_FRIEND_CLASSES (type)
= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
+ if (is_template_friend)
+ friend_type = TREE_TYPE (friend_type);
+ if (!uses_template_parms (type))
+ CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
+ = tree_cons (NULL_TREE, type,
+ CLASSTYPE_BEFRIENDING_CLASSES (friend_type));
}
}
@@ -310,13 +330,15 @@ make_friend_class (type, friend_type)
pointed to by `this'. */
tree
-do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
- tree ctype, declarator, decl, parmdecls;
+do_friend (ctype, declarator, decl, parmdecls, attrlist,
+ flags, quals, funcdef_flag)
+ tree ctype, declarator, decl, parmdecls, attrlist;
enum overload_flags flags;
tree quals;
int funcdef_flag;
{
int is_friend_template = 0;
+ tree prefix_attributes, attributes;
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
@@ -330,9 +352,10 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
declarator = DECL_NAME (get_first_fn (declarator));
}
- if (TREE_CODE (decl) == FUNCTION_DECL)
- is_friend_template = processing_template_decl >
- template_class_depth (current_class_type);
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ my_friendly_abort (990513);
+
+ is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
if (ctype)
{
@@ -341,62 +364,35 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
cname = DECL_NAME (cname);
/* A method friend. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (flags == NO_SPECIAL && ctype && declarator == cname)
+ DECL_CONSTRUCTOR_P (decl) = 1;
+
+ /* This will set up DECL_ARGUMENTS for us. */
+ grokclassfn (ctype, decl, flags, quals);
+
+ if (is_friend_template)
+ decl = DECL_TI_TEMPLATE (push_template_decl (decl));
+ else if (template_class_depth (current_class_type))
+ decl = push_template_decl_real (decl, /*is_friend=*/1);
+
+ /* We can't do lookup in a type that involves template
+ parameters. Instead, we rely on tsubst_friend_function
+ to check the validity of the declaration later. */
+ if (uses_template_parms (ctype))
+ add_friend (current_class_type, decl);
+ /* A nested class may declare a member of an enclosing class
+ to be a friend, so we do lookup here even if CTYPE is in
+ the process of being defined. */
+ else if (TYPE_SIZE (ctype) != 0 || TYPE_BEING_DEFINED (ctype))
{
- if (flags == NO_SPECIAL && ctype && declarator == cname)
- DECL_CONSTRUCTOR_P (decl) = 1;
+ decl = check_classfn (ctype, decl);
- /* This will set up DECL_ARGUMENTS for us. */
- grokclassfn (ctype, cname, decl, flags, quals);
-
- if (is_friend_template)
- decl = DECL_TI_TEMPLATE (push_template_decl (decl));
-
- if (TYPE_SIZE (ctype) != 0 && template_class_depth (ctype) == 0)
- decl = check_classfn (ctype, decl);
-
- /* TYPE_BEING_DEFINED is a hack for nested classes having
- member functions of the enclosing class as friends. Will
- go away as parsing of classes gets rewritten. */
- if (TREE_TYPE (decl) != error_mark_node)
- {
- if (TYPE_BEING_DEFINED (ctype) ||
- TYPE_SIZE (ctype) || template_class_depth (ctype) > 0)
- add_friend (current_class_type, decl);
- else
- cp_error ("member `%D' declared as friend before type `%T' defined",
- decl, ctype);
- }
+ if (decl)
+ add_friend (current_class_type, decl);
}
else
- {
- /* Possibly a bunch of method friends. */
-
- /* Get the class they belong to. */
- tree ctype = IDENTIFIER_TYPE_VALUE (cname);
- tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0);
-
- if (fields)
- add_friends (current_class_type, declarator, ctype);
- else
- cp_error ("method `%D' is not a member of class `%T'",
- declarator, ctype);
- decl = void_type_node;
- }
- }
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && (MAIN_NAME_P (declarator)
- || (IDENTIFIER_LENGTH (declarator) > 10
- && IDENTIFIER_POINTER (declarator)[0] == '_'
- && IDENTIFIER_POINTER (declarator)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (declarator)+2,
- "builtin_", 8) == 0)))
- {
- /* raw "main", and builtin functions never gets overloaded,
- but they can become friends. */
- add_friend (current_class_type, decl);
- DECL_FRIEND_P (decl) = 1;
- decl = void_type_node;
+ cp_error ("member `%D' declared as friend before type `%T' defined",
+ decl, ctype);
}
/* A global friend.
@@ or possibly a friend from a base class ?!? */
@@ -407,9 +403,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
Note that because classes all wind up being top-level
in their scope, their friend wind up in top-level scope as well. */
- DECL_ASSEMBLER_NAME (decl)
- = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
- TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
DECL_ARGUMENTS (decl) = parmdecls;
if (funcdef_flag)
DECL_CLASS_CONTEXT (decl) = current_class_type;
@@ -417,22 +410,20 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
if (! DECL_USE_TEMPLATE (decl))
{
/* We can call pushdecl here, because the TREE_CHAIN of this
- FUNCTION_DECL is not needed for other purposes. Don't do this
- for a template instantiation. */
- if (!is_friend_template)
- {
- /* However, we don't call pushdecl() for a friend
- function of a template class, since in general,
- such a declaration depends on template
- parameters. Instead, we call pushdecl when the
- class is instantiated. */
- if (template_class_depth (current_class_type) == 0)
- decl = pushdecl (decl);
- }
+ FUNCTION_DECL is not needed for other purposes. Don't do
+ this for a template instantiation. However, we don't
+ call pushdecl() for a friend function of a template
+ class, since in general, such a declaration depends on
+ template parameters. Instead, we call pushdecl when the
+ class is instantiated. */
+ if (!is_friend_template
+ && template_class_depth (current_class_type) == 0)
+ decl = pushdecl (decl);
else
- decl = push_template_decl (decl);
+ decl = push_template_decl_real (decl, /*is_friend=*/1);
- if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
+ if (warn_nontemplate_friend
+ && ! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
&& current_template_parms && uses_template_parms (decl))
{
static int explained;
@@ -443,6 +434,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
warning (" (if this is not what you intended, make sure");
warning (" the function template has already been declared,");
warning (" and add <> after the function name here)");
+ warning (" -Wno-non-template-friend disables this warning.");
explained = 1;
}
}
@@ -453,32 +445,28 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl);
DECL_FRIEND_P (decl) = 1;
}
+
+ /* Unfortunately, we have to handle attributes here. Normally we would
+ handle them in start_decl_1, but since this is a friend decl start_decl_1
+ never gets to see it. */
+
+ if (attrlist)
+ {
+ attributes = TREE_PURPOSE (attrlist);
+ prefix_attributes = TREE_VALUE (attrlist);
+ }
else
{
- /* @@ Should be able to ingest later definitions of this function
- before use. */
- tree decl = lookup_name_nonclass (declarator);
- if (decl == NULL_TREE)
- {
- cp_warning ("implicitly declaring `%T' as struct", declarator);
- decl = xref_tag (record_type_node, declarator, NULL_TREE, 1);
- decl = TYPE_MAIN_DECL (decl);
- }
+ attributes = NULL_TREE;
+ prefix_attributes = NULL_TREE;
+ }
- /* Allow abbreviated declarations of overloaded functions,
- but not if those functions are really class names. */
- if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl)))
- {
- cp_warning ("`friend %T' archaic, use `friend class %T' instead",
- declarator, declarator);
- decl = TREE_TYPE (TREE_PURPOSE (decl));
- }
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
+#endif
+
+ /* Set attributes here so if duplicate decl, will have proper attributes. */
+ cplus_decl_attributes (decl, attributes, prefix_attributes);
- if (TREE_CODE (decl) == TREE_LIST)
- add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE);
- else
- make_friend_class (current_class_type, TREE_TYPE (decl));
- decl = void_type_node;
- }
return decl;
}
diff --git a/contrib/gcc/cp/g++spec.c b/contrib/gcc/cp/g++spec.c
index 542ca06..806b90e 100644
--- a/contrib/gcc/cp/g++spec.c
+++ b/contrib/gcc/cp/g++spec.c
@@ -1,5 +1,5 @@
/* Specific flags and argument handling of the C++ front-end.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,11 +19,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
-
#include "system.h"
-#include "gansidecl.h"
-
/* This bit is set if we saw a `-xfoo' language specification. */
#define LANGSPEC (1<<1)
/* This bit is set if they did `-lm' or `-lmath'. */
@@ -34,11 +31,10 @@ Boston, MA 02111-1307, USA. */
#ifndef MATH_LIBRARY
#define MATH_LIBRARY "-lm"
#endif
-#ifndef NEED_MATH_LIBRARY
-#define NEED_MATH_LIBRARY 1 /* Default is pass MATH_LIBRARY to linker */
-#endif
-extern char *xmalloc PROTO((size_t));
+#ifndef LIBSTDCXX
+#define LIBSTDCXX "-lstdc++"
+#endif
void
lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
@@ -83,8 +79,8 @@ lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
LANGSPEC, MATHLIB, or WITHLIBC. */
int *args;
- /* By default, we throw on the math library. */
- int need_math = NEED_MATH_LIBRARY;
+ /* By default, we throw on the math library if we have one. */
+ int need_math = (MATH_LIBRARY[0] != '\0');
/* The total number of arguments with the new stuff. */
int argc;
@@ -128,6 +124,7 @@ lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
}
else if (strcmp (argv[i], "-lm") == 0
|| strcmp (argv[i], "-lmath") == 0
+ || strcmp (argv[i], MATH_LIBRARY) == 0
#ifdef ALT_LIBM
|| strcmp (argv[i], ALT_LIBM) == 0
#endif
@@ -239,7 +236,7 @@ lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
/* Add `-lstdc++' if we haven't already done so. */
if (library)
{
- arglist[j++] = "-lstdc++";
+ arglist[j++] = LIBSTDCXX;
added_libraries++;
}
if (saw_math)
diff --git a/contrib/gcc/cp/gxx.gperf b/contrib/gcc/cp/gxx.gperf
index 71538567..1e621c4 100644
--- a/contrib/gcc/cp/gxx.gperf
+++ b/contrib/gcc/cp/gxx.gperf
@@ -1,7 +1,7 @@
%{
-/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
+/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
%}
-struct resword { char *name; short token; enum rid rid;};
+struct resword { const char *name; short token; enum rid rid;};
%%
__alignof, ALIGNOF, NORID
__alignof__, ALIGNOF, NORID
@@ -22,6 +22,8 @@ __label__, LABEL, NORID
__null, CONSTANT, RID_NULL
__real, REALPART, NORID
__real__, REALPART, NORID
+__restrict, CV_QUALIFIER, RID_RESTRICT
+__restrict__, CV_QUALIFIER, RID_RESTRICT
__signature__, AGGR, RID_SIGNATURE /* Extension */,
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
@@ -55,6 +57,7 @@ dynamic_cast, DYNAMIC_CAST, NORID,
else, ELSE, NORID,
enum, ENUM, NORID,
explicit, SCSPEC, RID_EXPLICIT,
+export, SCSPEC, RID_EXPORT,
extern, SCSPEC, RID_EXTERN,
false, CXX_FALSE, NORID,
float, TYPESPEC, RID_FLOAT,
@@ -78,7 +81,7 @@ protected, VISSPEC, RID_PROTECTED,
public, VISSPEC, RID_PUBLIC,
register, SCSPEC, RID_REGISTER,
reinterpret_cast, REINTERPRET_CAST, NORID,
-return, RETURN, NORID,
+return, RETURN_KEYWORD, NORID,
short, TYPESPEC, RID_SHORT,
signature, AGGR, RID_SIGNATURE /* Extension */,
signed, TYPESPEC, RID_SIGNED,
diff --git a/contrib/gcc/cp/gxxint.texi b/contrib/gcc/cp/gxxint.texi
index 7cb57f2..05f1373 100644
--- a/contrib/gcc/cp/gxxint.texi
+++ b/contrib/gcc/cp/gxxint.texi
@@ -23,7 +23,6 @@ Questions and comments to Benjamin Kosnik @code{<bkoz@@cygnus.com>}.
* Access Control::
* Error Reporting::
* Parser::
-* Copying Objects::
* Exception Handling::
* Free Store::
* Mangling:: Function name mangling for C++ and Java
@@ -167,77 +166,6 @@ class foo @{ public: int b; int a; foo (); @};
Thus, @samp{b} will be initialized with 2 first, then @samp{a} will be
initialized with 1, regardless of how they're listed in the mem-initializer.
-@item Argument Matching
-
-In early 1993, the argument matching scheme in @sc{gnu} C++ changed
-significantly. The original code was completely replaced with a new
-method that will, hopefully, be easier to understand and make fixing
-specific cases much easier.
-
-The @samp{-fansi-overloading} option is used to enable the new code; at
-some point in the future, it will become the default behavior of the
-compiler.
-
-The file @file{cp-call.c} contains all of the new work, in the functions
-@code{rank_for_overload}, @code{compute_harshness},
-@code{compute_conversion_costs}, and @code{ideal_candidate}.
-
-Instead of using obscure numerical values, the quality of an argument
-match is now represented by clear, individual codes. The new data
-structure @code{struct harshness} (it used to be an @code{unsigned}
-number) contains:
-
-@enumerate a
-@item the @samp{code} field, to signify what was involved in matching two
-arguments;
-@item the @samp{distance} field, used in situations where inheritance
-decides which function should be called (one is ``closer'' than
-another);
-@item and the @samp{int_penalty} field, used by some codes as a tie-breaker.
-@end enumerate
-
-The @samp{code} field is a number with a given bit set for each type of
-code, OR'd together. The new codes are:
-
-@itemize @bullet
-@item @code{EVIL_CODE}
-The argument was not a permissible match.
-
-@item @code{CONST_CODE}
-Currently, this is only used by @code{compute_conversion_costs}, to
-distinguish when a non-@code{const} member function is called from a
-@code{const} member function.
-
-@item @code{ELLIPSIS_CODE}
-A match against an ellipsis @samp{...} is considered worse than all others.
-
-@item @code{USER_CODE}
-Used for a match involving a user-defined conversion.
-
-@item @code{STD_CODE}
-A match involving a standard conversion.
-
-@item @code{PROMO_CODE}
-A match involving an integral promotion. For these, the
-@code{int_penalty} field is used to handle the ARM's rule (XXX cite)
-that a smaller @code{unsigned} type should promote to a @code{int}, not
-to an @code{unsigned int}.
-
-@item @code{QUAL_CODE}
-Used to mark use of qualifiers like @code{const} and @code{volatile}.
-
-@item @code{TRIVIAL_CODE}
-Used for trivial conversions. The @samp{int_penalty} field is used by
-@code{convert_harshness} to communicate further penalty information back
-to @code{build_overload_call_real} when deciding which function should
-be call.
-@end itemize
-
-The functions @code{convert_to_aggr} and @code{build_method_call} use
-@code{compute_conversion_costs} to rate each argument's suitability for
-a given candidate function (that's how we get the list of candidates for
-@code{ideal_candidate}).
-
@item The Explicit Keyword
The use of @code{explicit} on a constructor is used by @code{grokdeclarator}
@@ -1002,7 +930,7 @@ To have the line number on the error message indicate the line of the
DECL, use @code{cp_error_at} and its ilk; to indicate which argument you want,
use @code{%+D}, or it will default to the first.
-@node Parser, Copying Objects, Error Reporting, Top
+@node Parser, Exception Handling, Error Reporting, Top
@section Parser
Some comments on the parser:
@@ -1093,33 +1021,7 @@ conflicts.
Unlike the others, this ambiguity is not recognized by the Working Paper.
-@node Copying Objects, Exception Handling, Parser, Top
-@section Copying Objects
-
-The generated copy assignment operator in g++ does not currently do the
-right thing for multiple inheritance involving virtual bases; it just
-calls the copy assignment operators for its direct bases. What it
-should probably do is:
-
-1) Split up the copy assignment operator for all classes that have
-vbases into "copy my vbases" and "copy everything else" parts. Or do
-the trickiness that the constructors do to ensure that vbases don't get
-initialized by intermediate bases.
-
-2) Wander through the class lattice, find all vbases for which no
-intermediate base has a user-defined copy assignment operator, and call
-their "copy everything else" routines. If not all of my vbases satisfy
-this criterion, warn, because this may be surprising behavior.
-
-3) Call the "copy everything else" routine for my direct bases.
-
-If we only have one direct base, we can just foist everything off onto
-them.
-
-This issue is currently under discussion in the core reflector
-(2/28/94).
-
-@node Exception Handling, Free Store, Copying Objects, Top
+@node Exception Handling, Free Store, Parser, Top
@section Exception Handling
Note, exception handling in g++ is still under development.
@@ -1666,18 +1568,18 @@ as @samp{P} followed by the mangling of the class name.
@subsection Squangled type compression
-Squangling (enabled with the @samp{-fsquangle} option), utilizes
-the @samp{B} code to indicate reuse of a previously
-seen type within an indentifier. Types are recognized in a left to
-right manner and given increasing values, which are
-appended to the code in the standard manner. Ie, multiple digit numbers
-are delimited by @samp{_} characters. A type is considered to be any
-non primitive type, regardless of whether its a parameter, template
-parameter, or entire template. Certain codes are considered modifiers
-of a type, and are not included as part of the type. These are the
-@samp{C}, @samp{V}, @samp{P}, @samp{A}, @samp{R}, and @samp{U} codes,
-denoting constant, volatile, pointer, array, reference, and unsigned.
-These codes may precede a @samp{B} type in order to make the required
+Squangling (enabled with the @samp{-fsquangle} option), utilizes the
+@samp{B} code to indicate reuse of a previously seen type within an
+indentifier. Types are recognized in a left to right manner and given
+increasing values, which are appended to the code in the standard
+manner. Ie, multiple digit numbers are delimited by @samp{_}
+characters. A type is considered to be any non primitive type,
+regardless of whether its a parameter, template parameter, or entire
+template. Certain codes are considered modifiers of a type, and are not
+included as part of the type. These are the @samp{C}, @samp{V},
+@samp{P}, @samp{A}, @samp{R}, @samp{U} and @samp{u} codes, denoting
+constant, volatile, pointer, array, reference, unsigned, and restrict.
+These codes may precede a @samp{B} type in order to make the required
modifications to the type.
For example:
@@ -1845,6 +1747,14 @@ Used to indicate a template function.
@item i
Encodes the C++ and Java @code{int} types.
+@item I
+Encodes typedef names of the form @code{int@var{n}_t}, where @var{n} is a
+positive decimal number. The @samp{I} is followed by either two
+hexidecimal digits, which encode the value of @var{n}, or by an
+arbitrary number of hexidecimal digits between underscores. For
+example, @samp{I40} encodes the type @code{int64_t}, and @samp{I_200_}
+encodes the type @code{int512_t}.
+
@item J
Indicates a complex type.
@@ -1854,12 +1764,21 @@ Used by squangling to compress qualified names.
@item l
Encodes the C++ @code{long} type.
+@item n
+Immediate repeated type. Followed by the repeat count.
+
+@item N
+Repeated type. Followed by the repeat count of the repeated type,
+followed by the type index of the repeated type. Due to a bug in
+g++ 2.7.2, this is only generated if index is 0. Superceded by
+@samp{n} when squangling.
+
@item P
Indicates a pointer type. Followed by the type pointed to.
@item Q
Used to mangle qualified names, which arise from nested classes.
-Should also be used for namespaces (?).
+Also used for namespaces.
In Java used to mangle package-qualified names, and inner classes.
@item r
@@ -1888,11 +1807,14 @@ A modifier that indicates that the following integer type is unsigned.
Also used to indicate that the following class or namespace name
is encoded using Unicode-mangling.
+@item u
+The @code{restrict} type qualifier.
+
@item v
Encodes the C++ and Java @code{void} types.
@item V
-A modified for a @code{const} type or method.
+A modifier for a @code{volatile} type or method.
@item w
Encodes the C++ @code{wchar_t} type, and the Java @code{char} types.
diff --git a/contrib/gcc/cp/inc/exception b/contrib/gcc/cp/inc/exception
index 9954146..32efb9f 100644
--- a/contrib/gcc/cp/inc/exception
+++ b/contrib/gcc/cp/inc/exception
@@ -1,5 +1,5 @@
// Exception Handling support header for -*- C++ -*-
-// Copyright (C) 1995, 1996 Free Software Foundation
+// Copyright (C) 1995, 96-97, 1998 Free Software Foundation
#ifndef __EXCEPTION__
#define __EXCEPTION__
@@ -8,9 +8,7 @@
extern "C++" {
-#ifdef __HONOR_STD
namespace std {
-#endif
class exception {
public:
@@ -34,9 +32,7 @@ unexpected_handler set_unexpected (unexpected_handler);
void unexpected () __attribute__ ((__noreturn__));
bool uncaught_exception ();
-#ifdef __HONOR_STD
} // namespace std
-#endif
} // extern "C++"
diff --git a/contrib/gcc/cp/inc/new b/contrib/gcc/cp/inc/new
index 0f25a5c..b66673d 100644
--- a/contrib/gcc/cp/inc/new
+++ b/contrib/gcc/cp/inc/new
@@ -1,5 +1,5 @@
// The -*- C++ -*- dynamic memory management header.
-// Copyright (C) 1994, 1996 Free Software Foundation
+// Copyright (C) 1994, 96-97, 1998 Free Software Foundation
#ifndef __NEW__
#define __NEW__
@@ -10,9 +10,7 @@
extern "C++" {
-#ifdef __HONOR_STD
namespace std {
-#endif
class bad_alloc : public exception {
public:
@@ -24,9 +22,7 @@ namespace std {
typedef void (*new_handler)();
new_handler set_new_handler (new_handler);
-#ifdef __HONOR_STD
} // namespace std
-#endif
// replaceable signatures
void *operator new (size_t) throw (std::bad_alloc);
diff --git a/contrib/gcc/cp/inc/new.h b/contrib/gcc/cp/inc/new.h
index 799db7e..006be7e 100644
--- a/contrib/gcc/cp/inc/new.h
+++ b/contrib/gcc/cp/inc/new.h
@@ -5,9 +5,7 @@
#include <new>
-#ifdef __HONOR_STD
using std::new_handler;
using std::set_new_handler;
-#endif
#endif // __NEW_H__
diff --git a/contrib/gcc/cp/inc/typeinfo b/contrib/gcc/cp/inc/typeinfo
index e46acb9..9347849 100644
--- a/contrib/gcc/cp/inc/typeinfo
+++ b/contrib/gcc/cp/inc/typeinfo
@@ -1,5 +1,5 @@
// RTTI support for -*- C++ -*-
-// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+// Copyright (C) 1994, 95-97, 1998 Free Software Foundation
#ifndef __TYPEINFO__
#define __TYPEINFO__
@@ -10,9 +10,7 @@
extern "C++" {
-#ifdef __HONOR_STD
namespace std {
-#endif
class type_info {
private:
@@ -21,7 +19,7 @@ private:
type_info (const type_info&);
protected:
- type_info (const char *n): _name (n) { }
+ explicit type_info (const char *n): _name (n) { }
const char *_name;
@@ -54,9 +52,7 @@ class bad_typeid : public exception {
virtual ~bad_typeid () { }
};
-#ifdef __HONOR_STD
} // namespace std
-#endif
} // extern "C++"
#endif
diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c
index 931d033..38bf248 100644
--- a/contrib/gcc/cp/init.c
+++ b/contrib/gcc/cp/init.c
@@ -1,5 +1,5 @@
/* Handle initialization things in C++.
- Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -32,8 +32,6 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "toplev.h"
-extern void compiler_error ();
-
/* In C++, structures with well-defined constructors are initialized by
those constructors, unasked. CURRENT_BASE_INIT_LIST
holds a list of stmts for a BASE_INIT term in the grammar.
@@ -46,25 +44,22 @@ extern void compiler_error ();
tree current_base_init_list, current_member_init_list;
static void expand_aggr_vbase_init_1 PROTO((tree, tree, tree, tree));
-static void expand_aggr_vbase_init PROTO((tree, tree, tree, tree));
-static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int,
- int));
-static void expand_default_init PROTO((tree, tree, tree, tree, int,
- int));
+static void construct_virtual_bases PROTO((tree, tree, tree, tree, tree));
+static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int));
+static void expand_default_init PROTO((tree, tree, tree, tree, int));
static tree build_vec_delete_1 PROTO((tree, tree, tree, tree, tree,
int));
static void perform_member_init PROTO((tree, tree, tree, int));
static void sort_base_init PROTO((tree, tree *, tree *));
-static tree build_builtin_call PROTO((tree, tree, tree));
-static tree build_array_eh_cleanup PROTO((tree, tree, tree));
-static int member_init_ok_or_else PROTO((tree, tree, char *));
+static tree build_builtin_delete_call PROTO((tree));
+static int member_init_ok_or_else PROTO((tree, tree, const char *));
static void expand_virtual_init PROTO((tree, tree));
static tree sort_member_init PROTO((tree));
-static tree build_partial_cleanup_for PROTO((tree));
static tree initializing_context PROTO((tree));
-
-/* Cache _builtin_new and _builtin_delete exprs. */
-static tree BIN, BID, BIVN, BIVD;
+static void expand_vec_init_try_block PROTO((tree));
+static void expand_vec_init_catch_clause PROTO((tree, tree, tree, tree));
+static tree build_java_class_ref PROTO((tree));
+static void expand_cleanup_for_base PROTO((tree, tree));
/* Cache the identifier nodes for the magic field of a new cookie. */
static tree nc_nelts_field_id;
@@ -80,15 +75,6 @@ void init_init_processing ()
{
tree fields[1];
- /* Define implicit `operator new' and `operator delete' functions. */
- BIN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) NEW_EXPR])));
- TREE_USED (TREE_OPERAND (BIN, 0)) = 0;
- BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));
- TREE_USED (TREE_OPERAND (BID, 0)) = 0;
- BIVN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_NEW_EXPR])));
- TREE_USED (TREE_OPERAND (BIVN, 0)) = 0;
- BIVD = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_DELETE_EXPR])));
- TREE_USED (TREE_OPERAND (BIVD, 0)) = 0;
minus_one = build_int_2 (-1, -1);
/* Define the structure that holds header information for
@@ -189,7 +175,7 @@ perform_member_init (member, name, init, explicit)
array_type_nelts (type), TREE_VALUE (init), 1);
}
else
- expand_aggr_init (decl, init, 0, 0);
+ expand_aggr_init (decl, init, 0);
}
else
{
@@ -492,17 +478,6 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
*vbase_ptr = vbases;
}
-/* Perform partial cleanups for a base for exception handling. */
-
-static tree
-build_partial_cleanup_for (binfo)
- tree binfo;
-{
- return build_scoped_method_call
- (current_class_ref, binfo, dtor_identifier,
- build_expr_list (NULL_TREE, integer_zero_node));
-}
-
/* Perform whatever initializations have yet to be done on the base
class of the class variable. These actions are in the global
variable CURRENT_BASE_INIT_LIST. Such an action could be
@@ -562,14 +537,13 @@ emit_base_init (t, immediately)
sort_base_init (t, &rbase_init_list, &vbase_init_list);
current_base_init_list = NULL_TREE;
+ /* First, initialize the virtual base classes, if we are
+ constructing the most-derived object. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
-
- expand_start_cond (first_arg, 0);
- expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr,
- vbase_init_list);
- expand_end_cond ();
+ construct_virtual_bases (t, current_class_ref, current_class_ptr,
+ vbase_init_list, first_arg);
}
/* Now, perform initialization of non-virtual base classes. */
@@ -581,11 +555,8 @@ emit_base_init (t, immediately)
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
-#if 0 /* Once unsharing happens soon enough. */
- my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, 999);
-#else
- BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
-#endif
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo,
+ 999);
if (TREE_PURPOSE (rbase_init_list))
init = TREE_VALUE (rbase_init_list);
@@ -604,24 +575,13 @@ emit_base_init (t, immediately)
member = convert_pointer_to_real (base_binfo, current_class_ptr);
expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL_PTR), init,
- BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
+ LOOKUP_NORMAL);
expand_end_target_temps ();
free_temp_slots ();
}
- if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
- {
- tree expr;
-
- /* All cleanups must be on the function_obstack. */
- push_obstacks_nochange ();
- resume_temporary_allocation ();
- expr = build_partial_cleanup_for (base_binfo);
- pop_obstacks ();
- add_partial_entry (expr);
- }
-
+ expand_cleanup_for_base (base_binfo, NULL_TREE);
rbase_init_list = TREE_CHAIN (rbase_init_list);
}
@@ -783,6 +743,39 @@ expand_virtual_init (binfo, decl)
expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
}
+/* If an exception is thrown in a constructor, those base classes already
+ constructed must be destroyed. This function creates the cleanup
+ for BINFO, which has just been constructed. If FLAG is non-NULL,
+ it is a DECL which is non-zero when this base needs to be
+ destroyed. */
+
+static void
+expand_cleanup_for_base (binfo, flag)
+ tree binfo;
+ tree flag;
+{
+ tree expr;
+
+ if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
+ return;
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+
+ /* Call the destructor. */
+ expr = (build_scoped_method_call
+ (current_class_ref, binfo, dtor_identifier,
+ build_expr_list (NULL_TREE, integer_zero_node)));
+ if (flag)
+ expr = fold (build (COND_EXPR, void_type_node,
+ truthvalue_conversion (flag),
+ expr, integer_zero_node));
+
+ pop_obstacks ();
+ add_partial_entry (expr);
+}
+
/* Subroutine of `expand_aggr_vbase_init'.
BINFO is the binfo of the type that is being initialized.
INIT_LIST is the list of initializers for the virtual baseclass. */
@@ -799,42 +792,66 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
if (init)
init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */
- expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
+ expand_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN);
expand_end_target_temps ();
free_temp_slots ();
}
-/* Initialize this object's virtual base class pointers. This must be
- done only at the top-level of the object being constructed.
-
- INIT_LIST is list of initialization for constructor to perform. */
+/* Construct the virtual base-classes of THIS_REF (whose address is
+ THIS_PTR). The object has the indicated TYPE. The construction
+ actually takes place only if FLAG is non-zero. INIT_LIST is list
+ of initialization for constructor to perform. */
static void
-expand_aggr_vbase_init (binfo, exp, addr, init_list)
- tree binfo;
- tree exp;
- tree addr;
+construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
+ tree type;
+ tree this_ref;
+ tree this_ptr;
tree init_list;
+ tree flag;
{
- tree type = BINFO_TYPE (binfo);
+ tree vbases;
+ tree result;
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
- {
- tree result = init_vbase_pointers (type, addr);
- tree vbases;
+ /* If there are no virtual baseclasses, we shouldn't even be here. */
+ my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
- if (result)
- expand_expr_stmt (build_compound_expr (result));
+ /* First set the pointers in our object that tell us where to find
+ our virtual baseclasses. */
+ expand_start_cond (flag, 0);
+ result = init_vbase_pointers (type, this_ptr);
+ if (result)
+ expand_expr_stmt (build_compound_expr (result));
+ expand_end_cond ();
- for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree tmp = purpose_member (vbases, result);
- expand_aggr_vbase_init_1 (vbases, exp,
- TREE_OPERAND (TREE_VALUE (tmp), 0),
- init_list);
- }
+ /* Now, run through the baseclasses, initializing each. */
+ for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree tmp = purpose_member (vbases, result);
+
+ /* If there are virtual base classes with destructors, we need to
+ emit cleanups to destroy them if an exception is thrown during
+ the construction process. These exception regions (i.e., the
+ period during which the cleanups must occur) begin from the time
+ the construction is complete to the end of the function. If we
+ create a conditional block in which to initialize the
+ base-classes, then the cleanup region for the virtual base begins
+ inside a block, and ends outside of that block. This situation
+ confuses the sjlj exception-handling code. Therefore, we do not
+ create a single conditional block, but one for each
+ initialization. (That way the cleanup regions always begin
+ in the outer block.) We trust the back-end to figure out
+ that the FLAG will not change across initializations, and
+ avoid doing multiple tests. */
+ expand_start_cond (flag, 0);
+ expand_aggr_vbase_init_1 (vbases, this_ref,
+ TREE_OPERAND (TREE_VALUE (tmp), 0),
+ init_list);
+ expand_end_cond ();
+
+ expand_cleanup_for_base (vbases, flag);
}
}
@@ -864,7 +881,7 @@ static int
member_init_ok_or_else (field, type, member_name)
tree field;
tree type;
- char *member_name;
+ const char *member_name;
{
if (field == error_mark_node)
return 0;
@@ -914,7 +931,7 @@ expand_member_init (exp, name, init)
if (name && TREE_CODE (name) == TYPE_DECL)
{
- basetype = TREE_TYPE (name);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
name = DECL_NAME (name);
}
@@ -1052,9 +1069,8 @@ expand_member_init (exp, name, init)
perform the initialization, but not both, as it would be ambiguous. */
void
-expand_aggr_init (exp, init, alias_this, flags)
+expand_aggr_init (exp, init, flags)
tree exp, init;
- int alias_this;
int flags;
{
tree type = TREE_TYPE (exp);
@@ -1075,7 +1091,7 @@ expand_aggr_init (exp, init, alias_this, flags)
/* Must arrange to initialize each element of EXP
from elements of INIT. */
tree itype = init ? TREE_TYPE (init) : NULL_TREE;
- if (TYPE_READONLY (TREE_TYPE (type)) || TYPE_VOLATILE (TREE_TYPE (type)))
+ if (CP_TYPE_QUALS (type) != TYPE_UNQUALIFIED)
{
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (init)
@@ -1099,7 +1115,8 @@ expand_aggr_init (exp, init, alias_this, flags)
return;
}
expand_vec_init (exp, exp, array_type_nelts (type), init,
- init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
+ init && same_type_p (TREE_TYPE (init),
+ TREE_TYPE (exp)));
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
TREE_TYPE (exp) = type;
@@ -1123,18 +1140,17 @@ expand_aggr_init (exp, init, alias_this, flags)
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
- init, alias_this, LOOKUP_NORMAL|flags);
+ init, LOOKUP_NORMAL|flags);
TREE_TYPE (exp) = type;
TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
}
static void
-expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
+expand_default_init (binfo, true_exp, exp, init, flags)
tree binfo;
tree true_exp, exp;
tree init;
- int alias_this;
int flags;
{
tree type = TREE_TYPE (exp);
@@ -1155,14 +1171,13 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
if (true_exp != exp)
abort ();
- /* We special-case TARGET_EXPRs here to avoid an error about
- private copy constructors for temporaries bound to reference vars.
- If the TARGET_EXPR represents a call to a function that has
- permission to create such objects, a reference can bind directly
- to the return value. An object variable must be initialized
- via the copy constructor, even if the call is elided. */
- if (! (TREE_CODE (exp) == VAR_DECL && DECL_ARTIFICIAL (exp)
- && TREE_CODE (init) == TARGET_EXPR && TREE_TYPE (init) == type))
+ if (flags & DIRECT_BIND)
+ /* Do nothing. We hit this in two cases: Reference initialization,
+ where we aren't initializing a real variable, so we don't want
+ to run a new constructor; and catching an exception, where we
+ have already built up the constructor call so we could wrap it
+ in an exception region. */;
+ else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
if (TREE_CODE (init) == TRY_CATCH_EXPR)
@@ -1227,11 +1242,10 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
its description. */
static void
-expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
+expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
tree binfo;
tree true_exp, exp;
tree init;
- int alias_this;
int flags;
{
tree type = TREE_TYPE (exp);
@@ -1262,7 +1276,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
/* We know that expand_default_init can handle everything we want
at this point. */
- expand_default_init (binfo, true_exp, exp, init, alias_this, flags);
+ expand_default_init (binfo, true_exp, exp, init, flags);
}
/* Report an error if NAME is not the name of a user-defined,
@@ -1379,7 +1393,6 @@ build_member_call (type, name, parmlist)
tree t;
tree method_name;
int dtor = 0;
- int dont_use_this = 0;
tree basetype_path, decl;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR
@@ -1387,7 +1400,18 @@ build_member_call (type, name, parmlist)
{
/* 'name' already refers to the decls from the namespace, since we
hit do_identifier for template_ids. */
- my_friendly_assert (is_overloaded_fn (TREE_OPERAND (name, 0)), 980519);
+ method_name = TREE_OPERAND (name, 0);
+ /* FIXME: Since we don't do independent names right yet, the
+ name might also be a LOOKUP_EXPR. Once we resolve this to a
+ real decl earlier, this can go. This may happen during
+ tsubst'ing. */
+ if (TREE_CODE (method_name) == LOOKUP_EXPR)
+ {
+ method_name = lookup_namespace_name
+ (type, TREE_OPERAND (method_name, 0));
+ TREE_OPERAND (name, 0) = method_name;
+ }
+ my_friendly_assert (is_overloaded_fn (method_name), 980519);
return build_x_function_call (name, parmlist, current_class_ref);
}
@@ -1398,10 +1422,17 @@ build_member_call (type, name, parmlist)
return build_x_function_call (lookup_namespace_name (type, name),
parmlist, current_class_ref);
- if (TREE_CODE (name) != TEMPLATE_ID_EXPR)
- method_name = name;
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ method_name = TREE_OPERAND (name, 0);
+ if (TREE_CODE (method_name) == COMPONENT_REF)
+ method_name = TREE_OPERAND (method_name, 1);
+ if (is_overloaded_fn (method_name))
+ method_name = DECL_NAME (OVL_CURRENT (method_name));
+ TREE_OPERAND (name, 0) = method_name;
+ }
else
- method_name = TREE_OPERAND (name, 0);
+ method_name = name;
if (TREE_CODE (method_name) == BIT_NOT_EXPR)
{
@@ -1435,42 +1466,29 @@ build_member_call (type, name, parmlist)
return error_mark_node;
}
- /* No object? Then just fake one up, and let build_method_call
- figure out what to do. */
- if (current_class_type == 0
- || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)
- dont_use_this = 1;
+ decl = maybe_dummy_object (type, &basetype_path);
- if (dont_use_this)
- {
- basetype_path = TYPE_BINFO (type);
- decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
- }
- else if (current_class_ptr == 0)
- {
- dont_use_this = 1;
- decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
- }
- else
+ /* Convert 'this' to the specified type to disambiguate conversion
+ to the function's context. Apparently Standard C++ says that we
+ shouldn't do this. */
+ if (decl == current_class_ref
+ && ! pedantic
+ && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
{
tree olddecl = current_class_ptr;
tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
if (oldtype != type)
{
- tree newtype = build_type_variant (type, TYPE_READONLY (oldtype),
- TYPE_VOLATILE (oldtype));
+ tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
decl = convert_force (build_pointer_type (newtype), olddecl, 0);
+ decl = build_indirect_ref (decl, NULL_PTR);
}
- else
- decl = olddecl;
}
- decl = build_indirect_ref (decl, NULL_PTR);
-
if (method_name == constructor_name (type)
|| method_name == constructor_name_full (type))
return build_functional_cast (type, parmlist);
- if ((t = lookup_fnfields (basetype_path, method_name, 0)))
+ if (lookup_fnfields (basetype_path, method_name, 0))
return build_method_call (decl,
TREE_CODE (name) == TEMPLATE_ID_EXPR
? name : method_name,
@@ -1483,7 +1501,7 @@ build_member_call (type, name, parmlist)
return error_mark_node;
if (TREE_CODE (t) == FIELD_DECL)
{
- if (dont_use_this)
+ if (is_dummy_object (decl))
{
cp_error ("invalid use of non-static field `%D'", t);
return error_mark_node;
@@ -1523,7 +1541,8 @@ tree
build_offset_ref (type, name)
tree type, name;
{
- tree decl, fnfields, fields, t = error_mark_node;
+ tree decl, t = error_mark_node;
+ tree member;
tree basebinfo = NULL_TREE;
tree orig_name = name;
@@ -1541,7 +1560,7 @@ build_offset_ref (type, name)
if (TREE_CODE (type) == NAMESPACE_DECL)
{
t = lookup_namespace_name (type, name);
- if (! type_unknown_p (t))
+ if (t != error_mark_node && ! type_unknown_p (t))
{
mark_used (t);
t = convert_from_reference (t);
@@ -1559,6 +1578,11 @@ build_offset_ref (type, name)
part, we treat this just like a.f. We do remember, however,
the template-id that was used. */
name = TREE_OPERAND (orig_name, 0);
+
+ if (TREE_CODE (name) == LOOKUP_EXPR)
+ /* This can happen during tsubst'ing. */
+ name = TREE_OPERAND (name, 0);
+
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
}
@@ -1576,57 +1600,27 @@ build_offset_ref (type, name)
name = ctor_identifier;
#endif
- if (TYPE_SIZE (complete_type (type)) == 0)
+ if (TYPE_SIZE (complete_type (type)) == 0
+ && !TYPE_BEING_DEFINED (type))
{
- if (type == current_class_type)
- t = IDENTIFIER_CLASS_VALUE (name);
- else
- t = NULL_TREE;
- if (t == 0)
- {
- cp_error ("incomplete type `%T' does not have member `%D'", type,
- name);
- return error_mark_node;
- }
- if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
- || TREE_CODE (t) == CONST_DECL)
- {
- mark_used (t);
- return t;
- }
- if (TREE_CODE (t) == FIELD_DECL)
- sorry ("use of member in incomplete aggregate type");
- else if (TREE_CODE (t) == FUNCTION_DECL)
- sorry ("use of member function in incomplete aggregate type");
- else
- my_friendly_abort (52);
+ cp_error ("incomplete type `%T' does not have member `%D'", type,
+ name);
return error_mark_node;
}
- if (current_class_type == 0
- || get_base_distance (type, current_class_type, 0, &basebinfo) == -1)
- {
- basebinfo = TYPE_BINFO (type);
- decl = build1 (NOP_EXPR, type, error_mark_node);
- }
- else if (current_class_ptr == 0)
- decl = build1 (NOP_EXPR, type, error_mark_node);
- else
- decl = current_class_ref;
+ decl = maybe_dummy_object (type, &basebinfo);
- fnfields = lookup_fnfields (basebinfo, name, 1);
- fields = lookup_field (basebinfo, name, 0, 0);
+ member = lookup_member (basebinfo, name, 1, 0);
- if (fields == error_mark_node || fnfields == error_mark_node)
+ if (member == error_mark_node)
return error_mark_node;
/* A lot of this logic is now handled in lookup_field and
lookup_fnfield. */
- if (fnfields)
+ if (member && BASELINK_P (member))
{
- extern int flag_save_memoized_contexts;
-
/* Go from the TREE_BASELINK to the member function info. */
+ tree fnfields = member;
t = TREE_VALUE (fnfields);
if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
@@ -1644,7 +1638,7 @@ build_offset_ref (type, name)
t = ovl_cons (t, NULL_TREE);
return build (OFFSET_REF,
- build_offset_type (type, unknown_type_node),
+ unknown_type_node,
decl,
build (TEMPLATE_ID_EXPR,
TREE_TYPE (t),
@@ -1654,56 +1648,35 @@ build_offset_ref (type, name)
if (!really_overloaded_fn (t))
{
- tree access;
-
/* Get rid of a potential OVERLOAD around it */
t = OVL_CURRENT (t);
/* unique functions are handled easily. */
basebinfo = TREE_PURPOSE (fnfields);
- access = compute_access (basebinfo, t);
- if (access == access_protected_node)
- {
- cp_error_at ("member function `%#D' is protected", t);
- error ("in this context");
- return error_mark_node;
- }
- if (access == access_private_node)
- {
- cp_error_at ("member function `%#D' is private", t);
- error ("in this context");
- return error_mark_node;
- }
+ if (!enforce_access (basebinfo, t))
+ return error_mark_node;
mark_used (t);
+ if (DECL_STATIC_FUNCTION_P (t))
+ return t;
return build (OFFSET_REF, TREE_TYPE (t), decl, t);
}
/* FNFIELDS is most likely allocated on the search_obstack,
which will go away after this class scope. If we need
- to save this value for later (either for memoization
- or for use as an initializer for a static variable), then
- do so here.
+ to save this value for later (i.e. for use as an initializer
+ for a static variable), then do so here.
??? The smart thing to do for the case of saving initializers
is to resolve them before we're done with this scope. */
if (!TREE_PERMANENT (fnfields)
- && ((flag_save_memoized_contexts && toplevel_bindings_p ())
- || ! allocation_temporary_p ()))
+ && ! allocation_temporary_p ())
fnfields = copy_list (fnfields);
- t = build_tree_list (error_mark_node, fnfields);
- TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
- return t;
+ TREE_TYPE (fnfields) = unknown_type_node;
+ return build (OFFSET_REF, unknown_type_node, decl, fnfields);
}
- /* Now that we know we are looking for a field, see if we
- have access to that field. Lookup_field will give us the
- error message. */
-
- t = lookup_field (basebinfo, name, 1, 0);
-
- if (t == error_mark_node)
- return error_mark_node;
+ t = member;
if (t == NULL_TREE)
{
@@ -1724,7 +1697,7 @@ build_offset_ref (type, name)
return convert_from_reference (t);
}
- if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t))
+ if (TREE_CODE (t) == FIELD_DECL && DECL_C_BIT_FIELD (t))
{
cp_error ("illegal pointer to bit field `%D'", t);
return error_mark_node;
@@ -1753,12 +1726,6 @@ resolve_offset_ref (exp)
tree member;
tree basetype, addr;
- if (TREE_CODE (exp) == TREE_LIST)
- {
- cp_pedwarn ("assuming & on overloaded member function");
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
-
if (TREE_CODE (exp) == OFFSET_REF)
{
member = TREE_OPERAND (exp, 1);
@@ -1777,10 +1744,22 @@ resolve_offset_ref (exp)
base = current_class_ref;
}
+ if (BASELINK_P (member))
+ {
+ cp_pedwarn ("assuming & on overloaded member function");
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
+
+ if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
+ {
+ cp_pedwarn ("assuming & on `%E'", member);
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
+
if ((TREE_CODE (member) == VAR_DECL
- && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
- || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
+ && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member))
+ && ! TYPE_PTRMEM_P (TREE_TYPE (member)))
+ || TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
{
/* These were static members. */
if (mark_addressable (member) == 0)
@@ -1808,11 +1787,10 @@ resolve_offset_ref (exp)
/* The first case is really just a reference to a member of `this'. */
if (TREE_CODE (member) == FIELD_DECL
- && (base == current_class_ref
- || (TREE_CODE (base) == NOP_EXPR
- && TREE_OPERAND (base, 0) == error_mark_node)))
+ && (base == current_class_ref || is_dummy_object (base)))
{
- tree basetype_path, access;
+ tree basetype_path;
+ tree expr;
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
basetype = TYPE_OFFSET_BASETYPE (type);
@@ -1828,40 +1806,28 @@ resolve_offset_ref (exp)
}
/* Kludge: we need to use basetype_path now, because
convert_pointer_to will bash it. */
- access = compute_access (basetype_path, member);
+ enforce_access (basetype_path, member);
addr = convert_pointer_to (basetype, base);
- if (access == access_public_node)
- return build (COMPONENT_REF, TREE_TYPE (member),
- build_indirect_ref (addr, NULL_PTR), member);
- if (access == access_protected_node)
- {
- cp_error_at ("member `%D' is protected", member);
- error ("in this context");
- return error_mark_node;
- }
- if (access == access_private_node)
- {
- cp_error_at ("member `%D' is private", member);
- error ("in this context");
- return error_mark_node;
- }
- my_friendly_abort (55);
+
+ /* Even in the case of illegal access, we form the
+ COMPONENT_REF; that will allow better error recovery than
+ just feeding back error_mark_node. */
+ expr = build (COMPONENT_REF, TREE_TYPE (member),
+ build_indirect_ref (addr, NULL_PTR), member);
+ return convert_from_reference (expr);
}
/* Ensure that we have an object. */
- if (TREE_CODE (base) == NOP_EXPR
- && TREE_OPERAND (base, 0) == error_mark_node)
+ if (is_dummy_object (base))
addr = error_mark_node;
else
- {
- /* If this is a reference to a member function, then return the
- address of the member function (which may involve going
- through the object's vtable), otherwise, return an expression
- for the dereferenced pointer-to-member construct. */
- addr = build_unary_op (ADDR_EXPR, base, 0);
- }
+ /* If this is a reference to a member function, then return the
+ address of the member function (which may involve going
+ through the object's vtable), otherwise, return an expression
+ for the dereferenced pointer-to-member construct. */
+ addr = build_unary_op (ADDR_EXPR, base, 0);
- if (TREE_CODE (TREE_TYPE (member)) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (TREE_TYPE (member)))
{
if (addr == error_mark_node)
{
@@ -1869,17 +1835,15 @@ resolve_offset_ref (exp)
return error_mark_node;
}
- basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (member));
+ basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
addr = convert_pointer_to (basetype, addr);
- member = cp_convert (ptrdiff_type_node,
- build_unary_op (ADDR_EXPR, member, 0));
+ member = cp_convert (ptrdiff_type_node, member);
/* Pointer to data members are offset by one, so that a null
pointer with a real value of 0 is distinguishable from an
offset of the first member of a structure. */
member = build_binary_op (MINUS_EXPR, member,
- cp_convert (ptrdiff_type_node, integer_one_node),
- 0);
+ cp_convert (ptrdiff_type_node, integer_one_node));
return build1 (INDIRECT_REF, type,
build (PLUS_EXPR, build_pointer_type (type),
@@ -1901,48 +1865,29 @@ decl_constant_value (decl)
tree decl;
{
if (! TREE_THIS_VOLATILE (decl)
-#if 0
- /* These may be necessary for C, but they break C++. */
- ! TREE_PUBLIC (decl)
- /* Don't change a variable array bound or initial value to a constant
- in a place where a variable is invalid. */
- && ! pedantic
-#endif /* 0 */
- && DECL_INITIAL (decl) != 0
+ && DECL_INITIAL (decl)
&& DECL_INITIAL (decl) != error_mark_node
/* This is invalid if initial value is not constant.
If it has either a function call, a memory reference,
or a variable, then re-evaluating it could give different results. */
&& TREE_CONSTANT (DECL_INITIAL (decl))
/* Check for cases where this is sub-optimal, even though valid. */
- && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
-#if 0
- /* We must allow this to work outside of functions so that
- static constants can be used for array sizes. */
- && current_function_decl != 0
- && DECL_MODE (decl) != BLKmode
-#endif
- )
+ && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
return DECL_INITIAL (decl);
return decl;
}
/* Common subroutines of build_new and build_vec_delete. */
-/* Common interface for calling "builtin" functions that are not
- really builtin. */
+/* Call the global __builtin_delete to delete ADDR. */
static tree
-build_builtin_call (type, node, arglist)
- tree type;
- tree node;
- tree arglist;
+build_builtin_delete_call (addr)
+ tree addr;
{
- tree rval = build (CALL_EXPR, type, node, arglist, NULL_TREE);
- TREE_SIDE_EFFECTS (rval) = 1;
- assemble_external (TREE_OPERAND (node, 0));
- TREE_USED (TREE_OPERAND (node, 0)) = 1;
- return rval;
+ mark_used (global_delete_fndecl);
+ return build_call (global_delete_fndecl,
+ void_type_node, build_expr_list (NULL_TREE, addr));
}
/* Generate a C++ "new" expression. DECL is either a TREE_LIST
@@ -2036,6 +1981,11 @@ build_new (placement, decl, init, use_global_new)
}
else
{
+ int flags = pedantic ? WANT_INT : (WANT_INT | WANT_ENUM);
+ if (build_expr_type_conversion (flags, this_nelts, 0)
+ == NULL_TREE)
+ pedwarn ("size in array new must have integral type");
+
this_nelts = save_expr (cp_convert (sizetype, this_nelts));
absdcl = TREE_OPERAND (absdcl, 0);
if (this_nelts == integer_zero_node)
@@ -2044,7 +1994,7 @@ build_new (placement, decl, init, use_global_new)
nelts = integer_zero_node;
}
else
- nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
+ nelts = build_binary_op (MULT_EXPR, nelts, this_nelts);
}
}
else
@@ -2155,6 +2105,46 @@ build_new (placement, decl, init, use_global_new)
return rval;
}
+/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */
+
+static tree jclass_node = NULL_TREE;
+
+/* Given a Java class, return a decl for the corresponding java.lang.Class. */
+
+static tree
+build_java_class_ref (type)
+ tree type;
+{
+ tree name, class_decl;
+ static tree CL_prefix = NULL_TREE;
+ if (CL_prefix == NULL_TREE)
+ CL_prefix = get_identifier("_CL_");
+ if (jclass_node == NULL_TREE)
+ {
+ jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass"));
+ if (jclass_node == NULL_TREE)
+ fatal("call to Java constructor, while `jclass' undefined");
+ jclass_node = TREE_TYPE (jclass_node);
+ }
+ name = build_overload_with_type (CL_prefix, type);
+ class_decl = IDENTIFIER_GLOBAL_VALUE (name);
+ if (class_decl == NULL_TREE)
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
+ TREE_STATIC (class_decl) = 1;
+ DECL_EXTERNAL (class_decl) = 1;
+ TREE_PUBLIC (class_decl) = 1;
+ DECL_ARTIFICIAL (class_decl) = 1;
+ DECL_IGNORED_P (class_decl) = 1;
+ pushdecl_top_level (class_decl);
+ make_decl_rtl (class_decl, NULL_PTR, 1);
+ pop_obstacks ();
+ }
+ return class_decl;
+}
+
/* Called from cplus_expand_expr when expanding a NEW_EXPR. The return
value is immediately handed to expand_expr. */
@@ -2170,6 +2160,7 @@ build_new_1 (exp)
enum tree_code code = NEW_EXPR;
int use_cookie, nothrow, check_new;
int use_global_new;
+ int use_java_new = 0;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
@@ -2184,7 +2175,7 @@ build_new_1 (exp)
}
true_type = type;
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
+ if (CP_TYPE_QUALS (type))
type = TYPE_MAIN_VARIANT (type);
/* If our base type is an array, then make sure we know how many elements
@@ -2192,16 +2183,16 @@ build_new_1 (exp)
while (TREE_CODE (true_type) == ARRAY_TYPE)
{
tree this_nelts = array_type_nelts_top (true_type);
- nelts = build_binary_op (MULT_EXPR, nelts, this_nelts, 1);
+ nelts = build_binary_op (MULT_EXPR, nelts, this_nelts);
true_type = TREE_TYPE (true_type);
}
- if (!complete_type_or_else (true_type))
+ if (!complete_type_or_else (true_type, exp))
return error_mark_node;
if (has_array)
size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type),
- nelts, 1));
+ nelts));
else
size = size_in_bytes (type);
@@ -2223,21 +2214,21 @@ build_new_1 (exp)
signature_error (NULL_TREE, true_type);
return error_mark_node;
}
+
+ /* When we allocate an array, and the corresponding deallocation
+ function takes a second argument of type size_t, and that's the
+ "usual deallocation function", we allocate some extra space at
+ the beginning of the array to store the size of the array.
-#if 1
- /* Get a little extra space to store a couple of things before the new'ed
- array, if this isn't the default placement new. */
+ Well, that's what we should do. For backwards compatibility, we
+ have to do this whenever there's a two-argument array-delete
+ operator.
+ FIXME: For -fnew-abi, we don't have to maintain backwards
+ compatibility and we should fix this. */
use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
&& ! (placement && ! TREE_CHAIN (placement)
&& TREE_TYPE (TREE_VALUE (placement)) == ptr_type_node));
-#else
- /* Get a little extra space to store a couple of things before the new'ed
- array, if this is either non-placement new or new (nothrow). */
-
- use_cookie = (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type)
- && (! placement || nothrow));
-#endif
if (use_cookie)
{
@@ -2267,9 +2258,26 @@ build_new_1 (exp)
return error_mark_node;
}
}
+ else if (! placement && TYPE_FOR_JAVA (true_type))
+ {
+ tree class_addr, alloc_decl;
+ tree class_decl = build_java_class_ref (true_type);
+ tree class_size = size_in_bytes (true_type);
+ static char alloc_name[] = "_Jv_AllocObject";
+ use_java_new = 1;
+ alloc_decl = IDENTIFIER_GLOBAL_VALUE (get_identifier (alloc_name));
+ if (alloc_decl == NULL_TREE)
+ fatal("call to Java constructor, while `%s' undefined", alloc_name);
+ class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
+ rval = build_function_call (alloc_decl,
+ tree_cons (NULL_TREE, class_addr,
+ build_tree_list (NULL_TREE,
+ class_size)));
+ rval = cp_convert (build_pointer_type (true_type), rval);
+ }
else
{
- int susp;
+ int susp = 0;
if (flag_exceptions)
/* We will use RVAL when generating an exception handler for
@@ -2302,12 +2310,9 @@ build_new_1 (exp)
tree t = TREE_OPERAND (rval, 0);
/* The function. */
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
- t = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
-
- if (t && TREE_VALUE (t) == NULL_TREE)
- nothrow = 1;
+ nothrow = TYPE_NOTHROW_P (TREE_TYPE (t));
}
- check_new = flag_check_new || nothrow;
+ check_new = (flag_check_new || nothrow) && ! use_java_new;
if ((check_new || flag_exceptions) && rval)
{
@@ -2326,7 +2331,7 @@ build_new_1 (exp)
tree extra = BI_header_size;
tree cookie, exp1;
rval = convert (string_type_node, rval); /* for ptr arithmetic */
- rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1));
+ rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra));
/* Store header info. */
cookie = build_indirect_ref (build (MINUS_EXPR,
build_pointer_type (BI_header_type),
@@ -2354,12 +2359,26 @@ build_new_1 (exp)
if (! TYPE_NEEDS_CONSTRUCTING (type)
&& ! IS_AGGR_TYPE (type) && ! has_array)
{
- /* New 2.0 interpretation: `new int (10)' means
- allocate an int, and initialize it with 10. */
+ /* We are processing something like `new int (10)', which
+ means allocate an int, and initialize it with 10. */
tree deref;
+ tree deref_type;
+ /* At present RVAL is a temporary variable, created to hold
+ the value from the call to `operator new'. We transform
+ it to (*RVAL = INIT, RVAL). */
rval = save_expr (rval);
deref = build_indirect_ref (rval, NULL_PTR);
+
+ /* Even for something like `new const int (10)' we must
+ allow the expression to be non-const while we do the
+ initialization. */
+ deref_type = TREE_TYPE (deref);
+ if (CP_TYPE_CONST_P (deref_type))
+ TREE_TYPE (deref)
+ = cp_build_qualified_type (deref_type,
+ CP_TYPE_QUALS (deref_type)
+ & ~TYPE_QUAL_CONST);
TREE_READONLY (deref) = 0;
if (TREE_CHAIN (init) != NULL_TREE)
@@ -2393,6 +2412,8 @@ build_new_1 (exp)
flags |= LOOKUP_HAS_IN_CHARGE;
}
+ if (use_java_new)
+ rval = save_expr (rval);
newrval = rval;
if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
@@ -2404,6 +2425,10 @@ build_new_1 (exp)
if (newrval == NULL_TREE || newrval == error_mark_node)
return error_mark_node;
+ /* Java constructors compiled by jc1 do not return this. */
+ if (use_java_new)
+ newrval = build (COMPOUND_EXPR, TREE_TYPE (newrval),
+ newrval, rval);
rval = newrval;
TREE_HAS_CONSTRUCTOR (rval) = 1;
}
@@ -2411,11 +2436,15 @@ build_new_1 (exp)
rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
save_expr (rval), init, nelts);
- /* If any part of the object initialization terminates by throwing
- an exception and the new-expression does not contain a
- new-placement, then the deallocation function is called to free
- the memory in which the object was being constructed. */
- if (flag_exceptions && alloc_expr)
+ /* If any part of the object initialization terminates by throwing an
+ exception and a suitable deallocation function can be found, the
+ deallocation function is called to free the memory in which the
+ object was being constructed, after which the exception continues
+ to propagate in the context of the new-expression. If no
+ unambiguous matching deallocation function can be found,
+ propagating the exception does not cause the object's memory to be
+ freed. */
+ if (flag_exceptions && alloc_expr && ! use_java_new)
{
enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
tree cleanup, fn = NULL_TREE;
@@ -2435,7 +2464,7 @@ build_new_1 (exp)
}
/* Copy size to the saveable obstack. */
- size = copy_node (size);
+ size = mapcar (size, permanent_p);
cleanup = build_op_delete_call (dcode, alloc_node, size, flags, fn);
@@ -2448,9 +2477,6 @@ build_new_1 (exp)
if (cleanup)
{
-#if 0
- /* Disable this until flow is fixed so that it doesn't
- think the initialization of sentry is a dead write. */
tree end, sentry, begin, buf, t = TREE_TYPE (rval);
begin = get_target_expr (boolean_true_node);
@@ -2473,18 +2499,10 @@ build_new_1 (exp)
rval = build (COMPOUND_EXPR, t, begin,
build (COMPOUND_EXPR, t, rval,
build (COMPOUND_EXPR, t, end, buf)));
-#else
- /* FIXME: this is a workaround for a crash due to overlapping
- exception regions. Cleanups shouldn't really happen here. */
- rval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (rval), rval);
-
- rval = build (TRY_CATCH_EXPR, TREE_TYPE (rval), rval, cleanup);
- rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
-#endif
}
}
}
- else if (TYPE_READONLY (true_type))
+ else if (CP_TYPE_CONST_P (true_type))
cp_error ("uninitialized const in `new' of `%#T'", true_type);
done:
@@ -2499,7 +2517,7 @@ build_new_1 (exp)
{
/* Did we modify the storage? */
tree ifexp = build_binary_op (NE_EXPR, alloc_node,
- integer_zero_node, 1);
+ integer_zero_node);
rval = build_conditional_expr (ifexp, rval, alloc_node);
}
@@ -2569,12 +2587,11 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
tree base_tbd = cp_convert (ptype,
build_binary_op (MINUS_EXPR,
cp_convert (ptr_type_node, base),
- BI_header_size,
- 1));
+ BI_header_size));
/* This is the real size */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
body = build_expr_list (NULL_TREE,
- build_x_delete (ptype, base_tbd,
+ build_x_delete (base_tbd,
2 | use_global_delete,
virtual_size));
body = build (COND_EXPR, void_type_node,
@@ -2608,8 +2625,7 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
no_destructor:
/* If the delete flag is one, or anything else with the low bit set,
delete the storage. */
- if (auto_delete_vec == integer_zero_node
- || auto_delete_vec == integer_two_node)
+ if (auto_delete_vec == integer_zero_node)
deallocate_expr = integer_zero_node;
else
{
@@ -2626,12 +2642,11 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
base_tbd = cp_convert (ptype,
build_binary_op (MINUS_EXPR,
cp_convert (string_type_node, base),
- BI_header_size,
- 1));
+ BI_header_size));
/* True size with header. */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
}
- deallocate_expr = build_x_delete (ptype, base_tbd,
+ deallocate_expr = build_x_delete (base_tbd,
2 | use_global_delete,
virtual_size);
if (auto_delete_vec != integer_one_node)
@@ -2665,18 +2680,80 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
return cp_convert (void_type_node, body);
}
-/* Build a tree to cleanup partially built arrays.
- BASE is that starting address of the array.
- COUNT is the count of objects that have been built, that need destroying.
- TYPE is the type of elements in the array. */
+/* Protect the vector initialization with a try-block so that we can
+ destroy the first few elements if constructing a later element
+ causes an exception to be thrown. TYPE is the type of the array
+ elements. */
-static tree
-build_array_eh_cleanup (base, count, type)
- tree base, count, type;
+static void
+expand_vec_init_try_block (type)
+ tree type;
+{
+ if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions)
+ return;
+
+ /* The code we generate looks like:
+
+ try {
+ // Initialize the vector.
+ } catch (...) {
+ // Destory the elements that need destroying.
+ throw;
+ }
+
+ Here we're just beginning the `try'. */
+
+ expand_eh_region_start ();
+}
+
+/* Add code to destroy the array elements constructed so far if the
+ construction of some element in the array causes an exception to be
+ thrown. RVAL is the address of the last element in the array.
+ TYPE is the type of the array elements. MAXINDEX is the maximum
+ allowable index into the array. ITERATOR is an integer variable
+ indicating how many elements remain to be constructed. */
+
+static void
+expand_vec_init_catch_clause (rval, type, maxindex, iterator)
+ tree rval;
+ tree type;
+ tree maxindex;
+ tree iterator;
{
- tree expr = build_vec_delete_1 (base, count, type, integer_two_node,
- integer_zero_node, 0);
- return expr;
+ tree e;
+ tree cleanup;
+
+ if (!TYPE_NEEDS_DESTRUCTOR (type) || !flag_exceptions)
+ return;
+
+ /* We have to ensure that this can live to the cleanup expansion
+ time, since we know it is only ever needed once, generate code
+ now. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+
+ cleanup = make_node (RTL_EXPR);
+ TREE_TYPE (cleanup) = void_type_node;
+ RTL_EXPR_RTL (cleanup) = const0_rtx;
+ TREE_SIDE_EFFECTS (cleanup) = 1;
+ do_pending_stack_adjust ();
+ start_sequence_for_rtl_expr (cleanup);
+
+ e = build_vec_delete_1 (rval,
+ build_binary_op (MINUS_EXPR, maxindex,
+ iterator),
+ type,
+ /*auto_delete_vec=*/integer_zero_node,
+ /*auto_delete=*/integer_zero_node,
+ /*use_global_delete=*/0);
+ expand_expr (e, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ do_pending_stack_adjust ();
+ RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
+ end_sequence ();
+ cleanup = protect_with_terminate (cleanup);
+ expand_eh_region_end (cleanup);
+ pop_obstacks ();
}
/* `expand_vec_init' performs initialization of a vector of aggregate
@@ -2702,9 +2779,12 @@ expand_vec_init (decl, base, maxindex, init, from_array)
int from_array;
{
tree rval;
- tree iterator, base2 = NULL_TREE;
+ tree base2 = NULL_TREE;
tree type = TREE_TYPE (TREE_TYPE (base));
tree size;
+ tree itype = NULL_TREE;
+ tree iterator;
+ int num_initialized_elts = 0;
maxindex = cp_convert (ptrdiff_type_node, maxindex);
if (maxindex == error_mark_node)
@@ -2721,104 +2801,100 @@ expand_vec_init (decl, base, maxindex, init, from_array)
size = size_in_bytes (type);
- /* Set to zero in case size is <= 0. Optimizer will delete this if
- it is not needed. */
- rval = get_temp_regvar (build_pointer_type (type),
- cp_convert (build_pointer_type (type), null_pointer_node));
base = default_conversion (base);
base = cp_convert (build_pointer_type (type), base);
- expand_assignment (rval, base, 0, 0);
+ rval = get_temp_regvar (build_pointer_type (type), base);
base = get_temp_regvar (build_pointer_type (type), base);
+ iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
- if (init != NULL_TREE
- && TREE_CODE (init) == CONSTRUCTOR
- && (! decl || TREE_TYPE (init) == TREE_TYPE (decl)))
+ /* Protect the entire array initialization so that we can destroy
+ the partially constructed array if an exception is thrown. */
+ expand_vec_init_try_block (type);
+
+ if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR
+ && (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl))))
{
- /* Initialization of array from {...}. */
- tree elts = CONSTRUCTOR_ELTS (init);
+ /* Do non-default initialization resulting from brace-enclosed
+ initializers. */
+
+ tree elts;
tree baseref = build1 (INDIRECT_REF, type, base);
- tree baseinc = build (PLUS_EXPR, build_pointer_type (type), base, size);
- int host_i = TREE_INT_CST_LOW (maxindex);
- if (IS_AGGR_TYPE (type))
+ from_array = 0;
+
+ for (elts = CONSTRUCTOR_ELTS (init); elts; elts = TREE_CHAIN (elts))
{
- while (elts)
- {
- host_i -= 1;
- expand_aggr_init (baseref, TREE_VALUE (elts), 0, 0);
+ tree elt = TREE_VALUE (elts);
- expand_assignment (base, baseinc, 0, 0);
- elts = TREE_CHAIN (elts);
- }
- /* Initialize any elements by default if possible. */
- if (host_i >= 0)
- {
- if (TYPE_NEEDS_CONSTRUCTING (type) == 0)
- {
- if (obey_regdecls)
- use_variable (DECL_RTL (base));
- goto done_init;
- }
+ num_initialized_elts++;
- iterator = get_temp_regvar (ptrdiff_type_node,
- build_int_2 (host_i, 0));
- init = NULL_TREE;
- goto init_by_default;
- }
+ if (IS_AGGR_TYPE (type) || TREE_CODE (type) == ARRAY_TYPE)
+ expand_aggr_init (baseref, elt, 0);
+ else
+ expand_assignment (baseref, elt, 0, 0);
+
+ expand_assignment (base,
+ build (PLUS_EXPR, build_pointer_type (type),
+ base, size),
+ 0, 0);
+ expand_assignment (iterator,
+ build (MINUS_EXPR, ptrdiff_type_node,
+ iterator, integer_one_node),
+ 0, 0);
}
- else
- while (elts)
- {
- expand_assignment (baseref, TREE_VALUE (elts), 0, 0);
- expand_assignment (base, baseinc, 0, 0);
- elts = TREE_CHAIN (elts);
- }
+ /* Clear out INIT so that we don't get confused below. */
+ init = NULL_TREE;
if (obey_regdecls)
use_variable (DECL_RTL (base));
}
- else
+ else if (from_array)
{
- tree itype;
+ /* If initializing one array from another, initialize element by
+ element. We rely upon the below calls the do argument
+ checking. */
+ if (decl == NULL_TREE)
+ {
+ sorry ("initialization of array from dissimilar array type");
+ return error_mark_node;
+ }
+ if (init)
+ {
+ base2 = default_conversion (init);
+ itype = TREE_TYPE (base2);
+ base2 = get_temp_regvar (itype, base2);
+ itype = TREE_TYPE (itype);
+ }
+ else if (TYPE_LANG_SPECIFIC (type)
+ && TYPE_NEEDS_CONSTRUCTING (type)
+ && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ {
+ error ("initializer ends prematurely");
+ return error_mark_node;
+ }
+ }
- iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
+ /* Now, default-initialize any remaining elements. We don't need to
+ do that if a) the type does not need constructing, or b) we've
+ already initialized all the elements.
- init_by_default:
- itype = NULL_TREE;
+ We do need to keep going if we're copying an array. */
- /* If initializing one array from another,
- initialize element by element. */
- if (from_array)
- {
- /* We rely upon the below calls the do argument checking */
- if (decl == NULL_TREE)
- {
- sorry ("initialization of array from dissimilar array type");
- return error_mark_node;
- }
- if (init)
- {
- base2 = default_conversion (init);
- itype = TREE_TYPE (base2);
- base2 = get_temp_regvar (itype, base2);
- itype = TREE_TYPE (itype);
- }
- else if (TYPE_LANG_SPECIFIC (type)
- && TYPE_NEEDS_CONSTRUCTING (type)
- && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
- {
- error ("initializer ends prematurely");
- return error_mark_node;
- }
- }
+ if (from_array
+ || (TYPE_NEEDS_CONSTRUCTING (type)
+ && !(TREE_CODE (maxindex) == INTEGER_CST
+ && num_initialized_elts == TREE_INT_CST_LOW (maxindex) + 1)))
+ {
+ /* If the ITERATOR is equal to -1, then we don't have to loop;
+ we've already initialized all the elements. */
+ expand_start_cond (build (NE_EXPR, boolean_type_node,
+ iterator, minus_one),
+ 0);
- expand_start_cond (build (GE_EXPR, boolean_type_node,
- iterator, integer_zero_node), 0);
- if (TYPE_NEEDS_DESTRUCTOR (type))
- expand_eh_region_start ();
+ /* Otherwise, loop through the elements. */
expand_start_loop_continue_elsewhere (1);
-
+
/* The initialization of each array element is a full-expression. */
expand_start_target_temps ();
@@ -2835,7 +2911,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
if (from_array == 2)
expand_expr_stmt (build_modify_expr (to, NOP_EXPR, from));
else if (TYPE_NEEDS_CONSTRUCTING (type))
- expand_aggr_init (to, from, 0, 0);
+ expand_aggr_init (to, from, 0);
else if (from)
expand_assignment (to, from, 0, 0);
else
@@ -2845,70 +2921,55 @@ expand_vec_init (decl, base, maxindex, init, from_array)
{
if (init != 0)
sorry ("cannot initialize multi-dimensional array with initializer");
- expand_vec_init (decl, build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), base),
+ expand_vec_init (decl,
+ build1 (NOP_EXPR,
+ build_pointer_type (TREE_TYPE
+ (type)),
+ base),
array_type_nelts (type), 0, 0);
}
else
- expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0, 0);
+ expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0);
expand_assignment (base,
- build (PLUS_EXPR, build_pointer_type (type), base, size),
- 0, 0);
+ build (PLUS_EXPR, build_pointer_type (type),
+ base, size), 0, 0);
if (base2)
expand_assignment (base2,
- build (PLUS_EXPR, build_pointer_type (type), base2, size), 0, 0);
+ build (PLUS_EXPR, build_pointer_type (type),
+ base2, size), 0, 0);
/* Cleanup any temporaries needed for the initial value. */
expand_end_target_temps ();
-
+
expand_loop_continue_here ();
expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node,
- build (PREDECREMENT_EXPR, ptrdiff_type_node, iterator, integer_one_node), minus_one));
-
+ build (PREDECREMENT_EXPR,
+ ptrdiff_type_node,
+ iterator,
+ integer_one_node),
+ minus_one));
+
if (obey_regdecls)
{
use_variable (DECL_RTL (base));
if (base2)
use_variable (DECL_RTL (base2));
}
+
expand_end_loop ();
- if (TYPE_NEEDS_DESTRUCTOR (type) && flag_exceptions)
- {
- /* We have to ensure that this can live to the cleanup
- expansion time, since we know it is only ever needed
- once, generate code now. */
- push_obstacks_nochange ();
- resume_temporary_allocation ();
- {
- tree e1, cleanup = make_node (RTL_EXPR);
- TREE_TYPE (cleanup) = void_type_node;
- RTL_EXPR_RTL (cleanup) = const0_rtx;
- TREE_SIDE_EFFECTS (cleanup) = 1;
- do_pending_stack_adjust ();
- start_sequence_for_rtl_expr (cleanup);
-
- e1 = build_array_eh_cleanup
- (rval,
- build_binary_op (MINUS_EXPR, maxindex, iterator, 1),
- type);
- expand_expr (e1, const0_rtx, VOIDmode, EXPAND_NORMAL);
- do_pending_stack_adjust ();
- RTL_EXPR_SEQUENCE (cleanup) = get_insns ();
- end_sequence ();
-
- cleanup = protect_with_terminate (cleanup);
- expand_eh_region_end (cleanup);
- }
- pop_obstacks ();
- }
expand_end_cond ();
- if (obey_regdecls)
- use_variable (DECL_RTL (iterator));
}
- done_init:
+
+ /* Make sure to cleanup any partially constructed elements. */
+ expand_vec_init_catch_clause (rval, type, maxindex, iterator);
if (obey_regdecls)
- use_variable (DECL_RTL (rval));
+ {
+ use_variable (DECL_RTL (iterator));
+ use_variable (DECL_RTL (rval));
+ }
+
return rval;
}
@@ -2927,8 +2988,8 @@ expand_vec_init (decl, base, maxindex, init, from_array)
This does not call any destructors. */
tree
-build_x_delete (type, addr, which_delete, virtual_size)
- tree type, addr;
+build_x_delete (addr, which_delete, virtual_size)
+ tree addr;
int which_delete;
tree virtual_size;
{
@@ -2976,15 +3037,14 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (TREE_CODE (type) == POINTER_TYPE)
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if (!complete_type_or_else (type))
+ if (type != void_type_node && !complete_type_or_else (type, addr))
return error_mark_node;
if (TREE_CODE (type) == ARRAY_TYPE)
goto handle_array;
if (! IS_AGGR_TYPE (type))
{
/* Call the builtin operator delete. */
- return build_builtin_call (void_type_node, BID,
- build_expr_list (NULL_TREE, addr));
+ return build_builtin_delete_call (addr);
}
if (TREE_SIDE_EFFECTS (addr))
addr = save_expr (addr);
@@ -3004,7 +3064,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
return error_mark_node;
}
return build_vec_delete (addr, array_type_nelts (type),
- auto_delete, integer_two_node,
+ auto_delete, integer_zero_node,
use_global_delete);
}
else
@@ -3050,8 +3110,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
tree cond = fold (build (BIT_AND_EXPR, integer_type_node,
auto_delete, integer_one_node));
- tree call = build_builtin_call
- (void_type_node, BID, build_expr_list (NULL_TREE, addr));
+ tree call = build_builtin_delete_call (addr);
cond = fold (build (COND_EXPR, void_type_node, cond,
call, void_zero_node));
@@ -3076,7 +3135,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
ifexp = integer_one_node;
else
/* Handle deleting a null pointer. */
- ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node, 1));
+ ifexp = fold (build_binary_op (NE_EXPR, addr, integer_zero_node));
if (ifexp != integer_one_node)
expr = build (COND_EXPR, void_type_node,
@@ -3094,6 +3153,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
tree parent_auto_delete = auto_delete;
tree cond;
+ /* Set this again before we call anything, as we might get called
+ recursively. */
+ TYPE_HAS_DESTRUCTOR (type) = 1;
+
/* If we have member delete or vbases, we call delete in
finish_function. */
if (auto_delete == integer_zero_node)
@@ -3103,8 +3166,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
cond = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node),
- build_builtin_call (void_type_node, BID,
- build_expr_list (NULL_TREE, addr)),
+ build_builtin_delete_call (addr),
void_zero_node);
}
else
diff --git a/contrib/gcc/cp/input.c b/contrib/gcc/cp/input.c
index 5a73fea..9148c86 100644
--- a/contrib/gcc/cp/input.c
+++ b/contrib/gcc/cp/input.c
@@ -1,5 +1,5 @@
/* Input handling for G++.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
This file is part of GNU CC.
@@ -53,12 +53,6 @@ static struct input_source *input, *free_inputs;
extern char *input_filename;
extern int lineno;
-#ifdef __GNUC__
-#define inline __inline__
-#else
-#define inline
-#endif
-
#if USE_CPPLIB
extern unsigned char *yy_cur, *yy_lim;
extern int yy_get_token ();
diff --git a/contrib/gcc/cp/lang-options.h b/contrib/gcc/cp/lang-options.h
index 5c50332..cfc6456 100644
--- a/contrib/gcc/cp/lang-options.h
+++ b/contrib/gcc/cp/lang-options.h
@@ -1,5 +1,5 @@
/* Definitions for switches for C++.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -23,9 +23,6 @@ DEFINE_LANG_NAME ("C++")
/* This is the contribution to the `lang_options' array in gcc.c for
g++. */
- { "-+e0", "" }, /* gcc.c tacks the `-' on the front. */
- { "-+e1", "" },
- { "-+e2", "" },
{ "-faccess-control", "" },
{ "-fno-access-control", "Do not obey access control semantics" },
{ "-fall-virtual", "Make all member functions virtual" },
@@ -38,8 +35,10 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-check-new", "" },
{ "-fconserve-space", "Reduce size of object files" },
{ "-fno-conserve-space", "" },
+ { "-fconst-strings", "" },
+ { "-fno-const-strings", "Make string literals `char[]' instead of `const char[]'" },
{ "-fdefault-inline", "" },
- { "-fno-default-inline", "Do not inline mmeber functions be default"},
+ { "-fno-default-inline", "Do not inline member functions by default"},
{ "-frtti", "" },
{ "-fno-rtti", "Do not generate run time type descriptor information" },
{ "-felide-constructors", "" },
@@ -54,23 +53,27 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-guiding-decls", "" },
{ "-fgnu-keywords", "" },
{ "-fno-gnu-keywords", "Do not recognise GNU defined keywords" },
- { "-fhandle-exceptions", "Enable exception handling" },
+ { "-fhandle-exceptions", "" },
{ "-fno-handle-exceptions", "" },
{ "-fhandle-signatures", "Handle signature language constructs" },
{ "-fno-handle-signatures", "" },
- { "-fhonor-std", "Do not ignore the namespace standard" },
+ { "-fhonor-std", "Treat the namespace `std' as a normal namespace" },
{ "-fno-honor-std", "" },
{ "-fhuge-objects", "Enable support for huge objects" },
{ "-fno-huge-objects", "" },
{ "-fimplement-inlines", "" },
{ "-fno-implement-inlines", "Export functions even if they can be inlined" },
- { "-fimplicit-templates", "Emit implicit instatiations if needed" },
- { "-fno-implicit-templates", "" },
+ { "-fimplicit-templates", "" },
+ { "-fno-implicit-templates", "Only emit explicit template instatiations" },
+ { "-fimplicit-inline-templates", "" },
+ { "-fno-implicit-inline-templates", "Only emit explicit instatiations of inline templates" },
+ { "-finit-priority", "Handle the init_priority attribute" },
+ { "-fno-init-priority", "" },
{ "-flabels-ok", "Labels can be used as first class objects" },
{ "-fno-labels-ok", "" },
- { "-fmemoize-lookups", "Enable caching of member function resolutions" },
+ { "-fmemoize-lookups", "" },
{ "-fno-memoize-lookups", "" },
- { "-fname-mangling-version-", "Set the version of name mangling to use" },
+ { "-fname-mangling-version-", "" },
{ "-fnew-abi", "Enable experimental ABI changes" },
{ "-fno-new-abi", "" },
{ "-fnonnull-objects", "" },
@@ -79,9 +82,11 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-operator-names", "" },
{ "-foptional-diags", "" },
{ "-fno-optional-diags", "Disable optional diagnostics" },
+ { "-fpermissive", "Downgrade conformance errors to warnings" },
+ { "-fno-permissive", "" },
{ "-frepo", "Enable automatic template instantiation" },
{ "-fno-repo", "" },
- { "-fsave-memoized", "Save cache of member function resolutions" },
+ { "-fsave-memoized", "" },
{ "-fno-save-memoized", "" },
{ "-fsquangle", "Enable squashed name mangling" },
{ "-fno-squangle", "" },
@@ -92,6 +97,8 @@ DEFINE_LANG_NAME ("C++")
{ "-ftemplate-depth-", "Specify maximum template instantiation depth"},
{ "-fthis-is-variable", "Make 'this' not be type '* const'" },
{ "-fno-this-is-variable", "" },
+ { "-fvtable-gc", "Discard unused virtual functions" },
+ { "-fno-vtable-gc", "" },
{ "-fvtable-thunks", "Implement vtables using thunks" },
{ "-fno-vtable-thunks", "" },
{ "-fweak", "Emit common-like symbols as weak symbols" },
@@ -103,8 +110,8 @@ DEFINE_LANG_NAME ("C++")
{ "-Wno-return-type", "" },
{ "-Woverloaded-virtual", "Warn about overloaded virtual function names" },
{ "-Wno-overloaded-virtual", "" },
- { "-Wctor-dtor-privacy", "Warn when all ctors/dtors are private" },
- { "-Wno-ctor-dtor-privacy", "" },
+ { "-Wctor-dtor-privacy", "" },
+ { "-Wno-ctor-dtor-privacy", "Don't warn when all ctors/dtors are private" },
{ "-Wnon-virtual-dtor", "Warn about non virtual destructors" },
{ "-Wno-non-virtual-dtor", "" },
{ "-Wextern-inline", "Warn when a function is declared extern, then inline" },
@@ -113,11 +120,15 @@ DEFINE_LANG_NAME ("C++")
{ "-Wno-reorder", "" },
{ "-Wsynth", "Warn when synthesis behaviour differs from Cfront" },
{ "-Wno-synth", "" },
- { "-Wpmf-conversions", "Warn when type converting pointers to member functions" },
- { "-Wno-pmf-conversions", "" },
+ { "-Wpmf-conversions", "" },
+ { "-Wno-pmf-conversions", "Don't warn when type converting pointers to member functions" },
{ "-Weffc++", "Warn about violations of Effective C++ style rules" },
{ "-Wno-effc++", "" },
{ "-Wsign-promo", "Warn when overload promotes from unsigned to signed" },
{ "-Wno-sign-promo", "" },
{ "-Wold-style-cast", "Warn if a C style cast is used in a program" },
{ "-Wno-old-style-cast", "" },
+ { "-Wnon-template-friend", "" },
+ { "-Wno-non-template-friend", "Don't warn when non-templatized friend functions are declared within a template" },
+ { "-Wdeprecated", "" },
+ { "-Wno-deprecated", "Don't announce deprecation of compiler features" },
diff --git a/contrib/gcc/cp/lang-specs.h b/contrib/gcc/cp/lang-specs.h
index b208ca1..648bc1f 100644
--- a/contrib/gcc/cp/lang-specs.h
+++ b/contrib/gcc/cp/lang-specs.h
@@ -1,5 +1,5 @@
/* Definitions for specs for C++.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -30,51 +30,54 @@ Boston, MA 02111-1307, USA. */
{"@c++",
#if USE_CPPLIB
{
- "%{E|M|MM:cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ "%{E|M|MM:cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C++ does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUG__=%v1 -D__cplusplus -D__GNUC_MINOR__=%v2\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\
+ -D__cplusplus\
%{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
%{!fno-exceptions:-D__EXCEPTIONS}\
- %{fhonor-std:-D__HONOR_STD} %{fnew-abi:-D__HONOR_STD}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} %{trigraphs}\
+ %{ffast-math:-D__FAST_MATH__}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
%{!E:%{!M:%{!MM:cc1plus %i %1 %2\
- -lang-c++ %{nostdinc*} %{C} %{A*} %{I*} %{P} %I\
- -undef -D__GNUC__=%v1 -D__GNUG__=%v1 -D__cplusplus\
- -D__GNUC_MINOR__=%v2\
+ -lang-c++ %{nostdinc*} %{C} %{A*} %{I*} %{P} %{$} %I\
+ %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1\
+ -D__GNUC_MINOR__=%v2} -D__cplusplus\
%{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
%{!fno-exceptions:-D__EXCEPTIONS}\
- %{fhonor-std:-D__HONOR_STD} %{fnew-abi:-D__HONOR_STD}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{trigraphs}\
%{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
%{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%{v:-version} %{pg:-p} %{p}\
- %{f*} %{+e*} %{aux-info*}\
+ %{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}}|\n\
%{!S:as %a %Y\
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
%{!pipe:%g.s} %A\n }}}}"}},
#else /* ! USE_CPPLIB */
- {"cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {"cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C++ does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUG__=%v1 -D__cplusplus -D__GNUC_MINOR__=%v2\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\
+ -D__cplusplus\
%{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
%{!fno-exceptions:-D__EXCEPTIONS}\
- %{fhonor-std:-D__HONOR_STD} %{fnew-abi:-D__HONOR_STD}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} %{trigraphs}\
+ %{ffast-math:-D__FAST_MATH__}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.ii}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
"%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.ii} %1 %2\
%{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
%{v:-version} %{pg:-p} %{p}\
- %{f*} %{+e*} %{aux-info*}\
+ %{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}}|\n\
%{!S:as %a %Y\
@@ -86,7 +89,7 @@ Boston, MA 02111-1307, USA. */
{"%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
%{v:-version} %{pg:-p} %{p}\
- %{f*} %{+e*} %{aux-info*}\
+ %{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c
index 57639ad..d9f2262 100644
--- a/contrib/gcc/cp/lex.c
+++ b/contrib/gcc/cp/lex.c
@@ -1,5 +1,5 @@
/* Separate lexical analyzer for GNU C++.
- Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include <setjmp.h>
#include "input.h"
#include "tree.h"
#include "lex.h"
@@ -39,14 +38,8 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "output.h"
-/* MULTIBYTE_CHARS support only works for native compilers.
- ??? Ideally what we want is to model widechar support after
- the current floating point support. */
-#ifdef CROSS_COMPILE
-#undef MULTIBYTE_CHARS
-#endif
-
#ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
#include <locale.h>
#endif
@@ -61,28 +54,26 @@ extern struct obstack permanent_obstack;
extern struct obstack *current_obstack, *saveable_obstack;
extern void yyprint PROTO((FILE *, int, YYSTYPE));
-extern void compiler_error PROTO((char *, HOST_WIDE_INT,
- HOST_WIDE_INT));
-static tree get_time_identifier PROTO((char *));
+static tree get_time_identifier PROTO((const char *));
static int check_newline PROTO((void));
static int skip_white_space PROTO((int));
static void finish_defarg PROTO((void));
static int my_get_run_time PROTO((void));
static int get_last_nonwhite_on_line PROTO((void));
-static int interface_strcmp PROTO((char *));
+static int interface_strcmp PROTO((const char *));
static int readescape PROTO((int *));
-static char *extend_token_buffer PROTO((char *));
+static char *extend_token_buffer PROTO((const char *));
static void consume_string PROTO((struct obstack *, int));
-static void set_typedecl_interface_info PROTO((tree, tree));
+static int set_typedecl_interface_info PROTO((tree *, void *));
static void feed_defarg PROTO((tree, tree));
-static int set_vardecl_interface_info PROTO((tree, tree));
+static int set_vardecl_interface_info PROTO((tree *, void *));
static void store_pending_inline PROTO((tree, struct pending_inline *));
static void reinit_parse_for_expr PROTO((struct obstack *));
static int *init_cpp_parse PROTO((void));
-static int handle_cp_pragma PROTO((char *));
-#ifdef HANDLE_SYSV_PRAGMA
-static int handle_sysv_pragma PROTO((int));
+static int handle_cp_pragma PROTO((const char *));
+#ifdef HANDLE_GENERIC_PRAGMAS
+static int handle_generic_pragma PROTO((int));
#endif
#ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
@@ -90,12 +81,16 @@ static int reduce_cmp PROTO((int *, int *));
static int token_cmp PROTO((int *, int *));
#endif
#endif
+static void begin_definition_of_inclass_inline PROTO((struct pending_inline*));
+static void parse_float PROTO((PTR));
+static int is_global PROTO((tree));
+static void init_filename_times PROTO((void));
/* Given a file name X, return the nondirectory portion.
Keep in mind that X can be computed more than once. */
char *
file_name_nondirectory (x)
- char *x;
+ const char *x;
{
char *tmp = (char *) rindex (x, '/');
if (DIR_SEPARATOR != '/' && ! tmp)
@@ -103,7 +98,7 @@ file_name_nondirectory (x)
if (tmp)
return (char *) (tmp + 1);
else
- return x;
+ return (char *) x;
}
/* This obstack is needed to hold text. It is not safe to use
@@ -319,7 +314,7 @@ static int ignore_escape_flag = 0;
static tree
get_time_identifier (name)
- char *name;
+ const char *name;
{
tree time_identifier;
int len = strlen (name);
@@ -328,12 +323,13 @@ get_time_identifier (name)
bcopy (name, buf+5, len);
buf[len+5] = '\0';
time_identifier = get_identifier (buf);
- if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
+ if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
push_obstacks_nochange ();
end_temporary_allocation ();
- IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
- IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
+ TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
+ TIME_IDENTIFIER_FILEINFO (time_identifier)
+ = build_int_2 (0, 1);
SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times);
filename_times = time_identifier;
pop_obstacks ();
@@ -383,7 +379,7 @@ int cplus_tree_code_length[] = {
Used for printing out the tree and error messages. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-char *cplus_tree_code_name[] = {
+const char *cplus_tree_code_name[] = {
"@@dummy",
#include "cp-tree.def"
};
@@ -394,6 +390,12 @@ char *cplus_tree_code_name[] = {
void
lang_init_options ()
{
+#if USE_CPPLIB
+ cpp_reader_init (&parse_in);
+ parse_in.opts = &parse_options;
+ cpp_options_init (&parse_options);
+#endif
+
/* Default exceptions on. */
flag_exceptions = 1;
}
@@ -401,11 +403,14 @@ lang_init_options ()
void
lang_init ()
{
-#if ! USE_CPPLIB
/* the beginning of the file is a new line; check for # */
/* With luck, we discover the real source file's name from that
and put it in input_filename. */
+#if ! USE_CPPLIB
put_back (check_newline ());
+#else
+ check_newline ();
+ yy_cur--;
#endif
if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename);
@@ -424,7 +429,7 @@ lang_identify ()
return "cplusplus";
}
-void
+static void
init_filename_times ()
{
this_filename_time = get_time_identifier ("<top level>");
@@ -432,7 +437,8 @@ init_filename_times ()
{
header_time = 0;
body_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+ = body_time;
}
}
@@ -474,13 +480,22 @@ init_parse (filename)
int i;
-#if USE_CPPLIB
- yy_cur = "\n";
- yy_lim = yy_cur + 1;
+#ifdef MULTIBYTE_CHARS
+ /* Change to the native locale for multibyte conversions. */
+ setlocale (LC_CTYPE, "");
+ literal_codeset = getenv ("LANG");
+#endif
+#if USE_CPPLIB
parse_in.show_column = 1;
if (! cpp_start_read (&parse_in, filename))
abort ();
+
+ /* cpp_start_read always puts at least one line directive into the
+ token buffer. We must arrange to read it out here. */
+ yy_cur = parse_in.token_buffer;
+ yy_lim = CPP_PWRITTEN (&parse_in);
+
#else
/* Open input file. */
if (filename == 0 || !strcmp (filename, "-"))
@@ -635,7 +650,7 @@ init_parse (filename)
IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1;
ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd");
IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1;
- ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
+ ansi_opname[(int) TYPE_EXPR] = get_identifier (OPERATOR_TYPENAME_FORMAT);
IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
/* This is not true: these operators are not defined in ANSI,
@@ -664,67 +679,28 @@ init_parse (filename)
token_buffer = (char *) xmalloc (maxtoken + 2);
ridpointers[(int) RID_INT] = get_identifier ("int");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
ridpointers[(int) RID_BOOL] = get_identifier ("bool");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_BOOL],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_BOOL]));
ridpointers[(int) RID_CHAR] = get_identifier ("char");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
ridpointers[(int) RID_VOID] = get_identifier ("void");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
ridpointers[(int) RID_FLOAT] = get_identifier ("float");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
ridpointers[(int) RID_SHORT] = get_identifier ("short");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
ridpointers[(int) RID_LONG] = get_identifier ("long");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
ridpointers[(int) RID_INLINE] = get_identifier ("inline");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
ridpointers[(int) RID_CONST] = get_identifier ("const");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
+ ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
ridpointers[(int) RID_STATIC] = get_identifier ("static");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
ridpointers[(int) RID_REGISTER] = get_identifier ("register");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
ridpointers[(int) RID_COMPLEX] = get_identifier ("__complex");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_COMPLEX],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_COMPLEX]));
/* C++ extensions. These are probably not correctly named. */
ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR]));
class_type_node = build_int_2 (class_type, 0);
TREE_TYPE (class_type_node) = class_type_node;
ridpointers[(int) RID_CLASS] = class_type_node;
@@ -742,37 +718,26 @@ init_parse (filename)
ridpointers[(int) RID_ENUM] = enum_type_node;
ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
ridpointers[(int) RID_EXPLICIT] = get_identifier ("explicit");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXPLICIT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXPLICIT]));
+ ridpointers[(int) RID_EXPORT] = get_identifier ("export");
ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
ridpointers[(int) RID_TEMPLATE] = get_identifier ("template");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TEMPLATE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_TEMPLATE]));
/* This is for ANSI C++. */
ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_MUTABLE]));
/* Signature handling extensions. */
signature_type_node = build_int_2 (signature_type, 0);
TREE_TYPE (signature_type_node) = signature_type_node;
ridpointers[(int) RID_SIGNATURE] = signature_type_node;
+ /* Create the built-in __null node. Note that we can't yet call for
+ type_for_size here because integer_type_node and so forth are not
+ set up. Therefore, we don't set the type of these nodes until
+ init_decl_processing. */
null_node = build_int_2 (0, 0);
ridpointers[RID_NULL] = null_node;
@@ -1123,7 +1088,7 @@ extract_interface_info ()
}
if (!fileinfo)
fileinfo = get_time_identifier (input_filename);
- fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
+ fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo);
interface_only = TREE_INT_CST_LOW (fileinfo);
interface_unknown = TREE_INT_CST_HIGH (fileinfo);
}
@@ -1133,15 +1098,15 @@ extract_interface_info ()
static int
interface_strcmp (s)
- char *s;
+ const char *s;
{
/* Set the interface/implementation bits for this scope. */
struct impl_files *ifiles;
- char *s1;
+ const char *s1;
for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
{
- char *t1 = ifiles->filename;
+ const char *t1 = ifiles->filename;
s1 = s;
if (*s1 != *t1 || *s1 == 0)
@@ -1169,37 +1134,71 @@ interface_strcmp (s)
return 1;
}
-static void
-set_typedecl_interface_info (prev, vars)
- tree prev, vars;
+static int
+set_typedecl_interface_info (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
- tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
- tree type = TREE_TYPE (vars);
+ tree id = get_time_identifier (DECL_SOURCE_FILE (*t));
+ tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
+ tree type = TREE_TYPE (*t);
CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
- = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (vars)));
+ = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (*t)));
+ return 0;
}
static int
-set_vardecl_interface_info (prev, vars)
- tree prev, vars;
+set_vardecl_interface_info (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- tree type = DECL_CONTEXT (vars);
+ tree type = DECL_CONTEXT (*t);
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
if (CLASSTYPE_INTERFACE_ONLY (type))
- set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type));
+ set_typedecl_interface_info (&TYPE_MAIN_DECL (type), data);
else
CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
- DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
- TREE_PUBLIC (vars) = 1;
+ DECL_EXTERNAL (*t) = CLASSTYPE_INTERFACE_ONLY (type);
+ TREE_PUBLIC (*t) = 1;
return 1;
}
return 0;
}
+/* Set up the state required to correctly handle the definition of the
+ inline function whose preparsed state has been saved in PI. */
+
+static void
+begin_definition_of_inclass_inline (pi)
+ struct pending_inline* pi;
+{
+ tree context;
+
+ if (!pi->fndecl)
+ return;
+
+ /* If this is an inline function in a local class, we must make sure
+ that we save all pertinent information about the function
+ surrounding the local class. */
+ context = hack_decl_function_context (pi->fndecl);
+ if (context)
+ push_cp_function_context (context);
+
+ feed_input (pi->buf, pi->len);
+ lineno = pi->lineno;
+ input_filename = pi->filename;
+ yychar = PRE_PARSED_FUNCTION_DECL;
+ yylval.ttype = build_tree_list ((tree) pi, pi->fndecl);
+ /* Pass back a handle to the rest of the inline functions, so that they
+ can be processed later. */
+ DECL_PENDING_INLINE_INFO (pi->fndecl) = 0;
+ interface_unknown = pi->interface == 1;
+ interface_only = pi->interface == 0;
+}
+
/* Called from the top level: if there are any pending inlines to
do, set up to process them now. This function sets up the first function
to be parsed; after it has been, the rule for fndef in parse.y will
@@ -1209,7 +1208,6 @@ void
do_pending_inlines ()
{
struct pending_inline *t;
- tree context;
/* Oops, we're still dealing with the last batch. */
if (yychar == PRE_PARSED_FUNCTION_DECL)
@@ -1236,32 +1234,7 @@ do_pending_inlines ()
return;
/* Now start processing the first inline function. */
- context = hack_decl_function_context (t->fndecl);
- if (context)
- push_cp_function_context (context);
- maybe_begin_member_template_processing (t->fndecl);
- if (t->len > 0)
- {
- feed_input (t->buf, t->len);
- lineno = t->lineno;
-#if 0
- if (input_filename != t->filename)
- {
- input_filename = t->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- }
-#else
- input_filename = t->filename;
- interface_unknown = t->interface == 1;
- interface_only = t->interface == 0;
-#endif
- yychar = PRE_PARSED_FUNCTION_DECL;
- }
- /* Pass back a handle on the rest of the inline functions, so that they
- can be processed later. */
- yylval.ttype = build_tree_list ((tree) t, t->fndecl);
- DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
+ begin_definition_of_inclass_inline (t);
}
static int nextchar = -1;
@@ -1277,7 +1250,6 @@ process_next_inline (t)
tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl);
- maybe_end_member_template_processing (i->fndecl);
if (context)
pop_cp_function_context (context);
i = i->next;
@@ -1295,24 +1267,8 @@ process_next_inline (t)
}
yychar = YYEMPTY;
end_input ();
- if (i && i->fndecl != NULL_TREE)
- {
- context = hack_decl_function_context (i->fndecl);
- if (context)
- push_cp_function_context (context);
- maybe_begin_member_template_processing (i->fndecl);
- feed_input (i->buf, i->len);
- lineno = i->lineno;
- input_filename = i->filename;
- yychar = PRE_PARSED_FUNCTION_DECL;
- yylval.ttype = build_tree_list ((tree) i, i->fndecl);
- DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
- }
if (i)
- {
- interface_unknown = i->interface == 1;
- interface_only = i->interface == 0;
- }
+ begin_definition_of_inclass_inline (i);
else
extract_interface_info ();
}
@@ -1538,10 +1494,12 @@ reinit_parse_for_block (pyychar, obstackp)
else if (pyychar == ':')
{
obstack_1grow (obstackp, pyychar);
+ /* Add a space so we don't get confused by ': ::A(20)'. */
+ obstack_1grow (obstackp, ' ');
look_for_lbrac = 1;
blev = 0;
}
- else if (pyychar == RETURN)
+ else if (pyychar == RETURN_KEYWORD)
{
obstack_grow (obstackp, "return", 6);
look_for_lbrac = 1;
@@ -1928,12 +1886,12 @@ do_pending_defargs ()
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{
- maybe_end_member_template_processing (defarg_fn);
+ maybe_end_member_template_processing ();
check_default_args (defarg_fn);
}
poplevel (0, 0, 0);
- pop_nested_class (1);
+ pop_nested_class ();
}
}
@@ -1977,7 +1935,7 @@ cons_up_default_function (type, full_name, kind)
break;
case 3:
- type = build_type_variant (type, 1, 0);
+ type = build_qualified_type (type, TYPE_QUAL_CONST);
/* Fall through... */
case 4:
/* According to ARM $12.8, the default copy ctor will be declared, but
@@ -1995,7 +1953,7 @@ cons_up_default_function (type, full_name, kind)
declspecs = build_decl_list (NULL_TREE, type);
if (kind == 5)
- type = build_type_variant (type, 1, 0);
+ type = build_qualified_type (type, TYPE_QUAL_CONST);
name = ansi_opname [(int) MODIFY_EXPR];
@@ -2113,7 +2071,7 @@ note_got_semicolon (type)
{
if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
my_friendly_abort (60);
- if (IS_AGGR_TYPE (type))
+ if (CLASS_TYPE_P (type))
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
@@ -2182,7 +2140,7 @@ skip_white_space (c)
static char *
extend_token_buffer (p)
- char *p;
+ const char *p;
{
int offset = p - token_buffer;
@@ -2208,6 +2166,32 @@ get_last_nonwhite_on_line ()
return c;
}
+#if defined HANDLE_PRAGMA
+/* Local versions of these macros, that can be passed as function pointers. */
+static int
+pragma_getc ()
+{
+ int c;
+
+ if (nextchar != EOF)
+ {
+ c = nextchar;
+ nextchar = EOF;
+ }
+ else
+ c = getch ();
+
+ return c;
+}
+
+static void
+pragma_ungetc (arg)
+ int arg;
+{
+ yyungetc (arg, 0);
+}
+#endif /* HANDLE_PRAGMA */
+
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
@@ -2215,13 +2199,12 @@ get_last_nonwhite_on_line ()
int linemode;
-static int handle_cp_pragma PROTO((char *));
-
static int
check_newline ()
{
register int c;
register int token;
+ int saw_line = 0;
/* Read first nonwhite char on the line. Do this before incrementing the
line number, in case we're at the end of saved text. */
@@ -2251,7 +2234,7 @@ check_newline ()
it and ignore it; otherwise, ignore the line, with an error
if the word isn't `pragma'. */
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+ if (ISALPHA (c))
{
if (c == 'p')
{
@@ -2274,21 +2257,29 @@ check_newline ()
else if (token == END_OF_LINE)
goto skipline;
-#ifdef HANDLE_SYSV_PRAGMA
- if (handle_sysv_pragma (token))
- goto skipline;
-#else
#ifdef HANDLE_PRAGMA
-#if USE_CPPLIB
- /* TODO: ??? */
- goto skipline;
-#else
- if (HANDLE_PRAGMA (finput, yylval.ttype))
- goto skipline;
-#endif /* !USE_CPPLIB */
-#endif
-#endif
+ /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS
+ (if both are defined), in order to give the back
+ end a chance to override the interpretation of
+ SYSV style pragmas. */
+ if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc,
+ IDENTIFIER_POINTER (yylval.ttype)))
+ goto skipline;
+#endif /* HANDLE_PRAGMA */
+
+#ifdef HANDLE_GENERIC_PRAGMAS
+ if (handle_generic_pragma (token))
+ goto skipline;
+#endif /* HANDLE_GENERIC_PRAGMAS */
+
+ /* Issue a warning message if we have been asked to do so.
+ Ignoring unknown pragmas in system header file unless
+ an explcit -Wunknown-pragmas has been given. */
+ if (warn_unknown_pragmas > 1
+ || (warn_unknown_pragmas && ! in_system_header))
+ warning ("ignoring pragma: %s", token_buffer);
}
+
goto skipline;
}
else if (c == 'd')
@@ -2322,7 +2313,10 @@ check_newline ()
&& getch () == 'n'
&& getch () == 'e'
&& ((c = getch ()) == ' ' || c == '\t'))
- goto linenum;
+ {
+ saw_line = 1;
+ goto linenum;
+ }
}
else if (c == 'i')
{
@@ -2419,9 +2413,16 @@ linenum:
/* More follows: it must be a string constant (filename). */
- /* Read the string constant, but don't treat \ as special. */
- ignore_escape_flag = 1;
+ if (saw_line)
+ {
+ /* Don't treat \ as special if we are processing #line 1 "...".
+ If you want it to be treated specially, use # 1 "...". */
+ ignore_escape_flag = 1;
+ }
+
+ /* Read the string constant. */
token = real_yylex ();
+
ignore_escape_flag = 0;
if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
@@ -2438,7 +2439,7 @@ linenum:
int this_time = my_get_run_time ();
tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
header_time += this_time - body_time;
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
this_filename_time = time_identifier;
body_time = this_time;
@@ -2463,7 +2464,14 @@ linenum:
main_input_filename = input_filename;
if (write_virtuals == 3)
- walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
+ {
+ walk_globals (vtable_decl_p,
+ set_vardecl_interface_info,
+ /*data=*/0);
+ walk_globals (vtype_decl_p,
+ set_typedecl_interface_info,
+ /*data=*/0);
+ }
}
extract_interface_info ();
@@ -2662,7 +2670,8 @@ readescape (ignore_ptr)
;
else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
|| (count > 1
- && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
+ && (((unsigned)1 <<
+ (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
<= firstdig)))
pedwarn ("hex escape out of range");
return code;
@@ -2727,7 +2736,7 @@ readescape (ignore_ptr)
pedwarn ("unknown escape sequence `\\%c'", c);
return c;
}
- if (c >= 040 && c < 0177)
+ if (ISGRAPH (c))
pedwarn ("unknown escape sequence `\\%c'", c);
else
pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
@@ -2746,6 +2755,7 @@ int
identifier_type (decl)
tree decl;
{
+ tree t;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
@@ -2755,7 +2765,10 @@ identifier_type (decl)
}
if (looking_for_template && really_overloaded_fn (decl))
{
- tree t;
+ /* See through a baselink. */
+ if (TREE_CODE (decl) == TREE_LIST)
+ decl = TREE_VALUE (decl);
+
for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
return PFUNCNAME;
@@ -2764,10 +2777,20 @@ identifier_type (decl)
return NSNAME;
if (TREE_CODE (decl) != TYPE_DECL)
return IDENTIFIER;
- if (((got_scope && TREE_TYPE (decl) == got_scope)
- || TREE_TYPE (decl) == current_class_type)
- && DECL_ARTIFICIAL (decl))
+ if (DECL_ARTIFICIAL (decl) && TREE_TYPE (decl) == current_class_type)
return SELFNAME;
+
+ /* A constructor declarator for a template type will get here as an
+ implicit typename, a TYPENAME_TYPE with a type. */
+ t = got_scope;
+ if (t && TREE_CODE (t) == TYPENAME_TYPE)
+ t = TREE_TYPE (t);
+ decl = TREE_TYPE (decl);
+ if (TREE_CODE (decl) == TYPENAME_TYPE)
+ decl = TREE_TYPE (decl);
+ if (t && t == decl)
+ return SELFNAME;
+
return TYPENAME;
}
@@ -2801,6 +2824,9 @@ is_global (d)
while (1)
switch (TREE_CODE (d))
{
+ case ERROR_MARK:
+ return 1;
+
case OVERLOAD: d = OVL_FUNCTION (d); continue;
case TREE_LIST: d = TREE_VALUE (d); continue;
default:
@@ -2843,12 +2869,19 @@ do_identifier (token, parsing, args)
|| TREE_CODE (field) == CONST_DECL
|| TREE_CODE (field) == TEMPLATE_DECL)
id = field;
+ else if (TREE_CODE (field) == TYPE_DECL
+ && DECL_ARTIFICIAL (field)
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (field)))
+ /* When we did name-lookup before, we will have eschewed
+ implicit typenames in favor of global bindings. Therefore,
+ if lookup_field returns an implicit typename, but ID is not
+ an implicit typename, then we should skip this one, too. */
+ ;
else if (TREE_CODE (field) != FIELD_DECL)
my_friendly_abort (61);
else
{
- cp_error ("invalid use of member `%D' from base class `%T'", field,
- DECL_FIELD_CONTEXT (field));
+ cp_error ("invalid use of member `%D'", field);
id = error_mark_node;
return id;
}
@@ -2857,44 +2890,41 @@ do_identifier (token, parsing, args)
/* Do Koenig lookup if appropriate (inside templates we build lookup
expressions instead). */
if (args && !current_template_parms && (!id || is_global (id)))
- {
- /* If we have arguments and we only found global names,
- do Koenig lookup. */
- id = lookup_arg_dependent (token, id, args);
- }
+ /* If we have arguments and we only found global names, do Koenig
+ lookup. */
+ id = lookup_arg_dependent (token, id, args);
/* Remember that this name has been used in the class definition, as per
[class.scope0] */
- if (id && current_class_type && parsing
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE (token)
+ if (id && parsing
/* Avoid breaking if we get called for a default argument that
refers to an overloaded method. Eventually this will not be
necessary, since default arguments shouldn't be parsed until
after the class is complete. (jason 3/12/97) */
&& TREE_CODE (id) != OVERLOAD)
- pushdecl_class_level (id);
-
- if (!id || id == error_mark_node)
- {
- if (id == error_mark_node && current_class_type != NULL_TREE)
- {
- id = lookup_nested_field (token, 1);
- /* In lookup_nested_field(), we marked this so we can gracefully
- leave this whole mess. */
- if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
- return id;
- }
+ maybe_note_name_used_in_class (token, id);
+ if (id == error_mark_node)
+ {
+ /* lookup_name quietly returns error_mark_node if we're parsing,
+ as we don't want to complain about an identifier that ends up
+ being used as a declarator. So we call it again to get the error
+ message. */
+ id = lookup_name (token, 0);
+ return error_mark_node;
+ }
+
+ if (!id)
+ {
if (current_template_parms)
- return build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ return build_min_nt (LOOKUP_EXPR, token);
else if (IDENTIFIER_OPNAME_P (token))
{
if (token != ansi_opname[ERROR_MARK])
cp_error ("`%D' not defined", token);
id = error_mark_node;
}
- else if (in_call)
+ else if (in_call && ! flag_strict_prototype)
{
id = implicitly_declare (token);
}
@@ -2968,37 +2998,39 @@ do_identifier (token, parsing, args)
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id) == CONST_DECL)
{
+ /* Check access. */
if (IDENTIFIER_CLASS_VALUE (token) == id)
- {
- /* Check access. */
- tree access = compute_access (TYPE_BINFO (current_class_type), id);
- if (access == access_private_node)
- cp_error ("enum `%D' is private", id);
- /* protected is OK, since it's an enum of `this'. */
- }
- if (! processing_template_decl
- || (DECL_INITIAL (id)
- && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
+ enforce_access (DECL_REAL_CONTEXT(id), id);
+ if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
id = DECL_INITIAL (id);
}
else
id = hack_identifier (id, token);
- if (current_template_parms)
- {
- if (is_overloaded_fn (id))
- {
- tree t = build_min (LOOKUP_EXPR, unknown_type_node,
- token, get_first_fn (id));
- if (id != IDENTIFIER_NAMESPACE_VALUE (token))
- TREE_OPERAND (t, 1) = error_mark_node;
- id = t;
- }
- else if (! TREE_PERMANENT (id) || TREE_CODE (id) == PARM_DECL
- || TREE_CODE (id) == USING_DECL)
- id = build_min (LOOKUP_EXPR, TREE_TYPE (id), token, error_mark_node);
- /* else just use the decl */
- }
+ /* We must look up dependent names when the template is
+ instantiated, not while parsing it. For now, we don't
+ distinguish between dependent and independent names. So, for
+ example, we look up all overloaded functions at
+ instantiation-time, even though in some cases we should just use
+ the DECL we have here. We also use LOOKUP_EXPRs to find things
+ like local variables, rather than creating TEMPLATE_DECLs for the
+ local variables and then finding matching instantiations. */
+ if (current_template_parms
+ && (is_overloaded_fn (id)
+ /* If it's not going to be around at instantiation time, we
+ look it up then. This is a hack, and should go when we
+ really get dependent/independent name lookup right. */
+ || !TREE_PERMANENT (id)
+ /* Some local VAR_DECLs (such as those for local variables
+ in member functions of local classes) are built on the
+ permanent obstack. */
+ || (TREE_CODE (id) == VAR_DECL
+ && CP_DECL_CONTEXT (id)
+ && TREE_CODE (CP_DECL_CONTEXT (id)) == FUNCTION_DECL)
+ || TREE_CODE (id) == PARM_DECL
+ || TREE_CODE (id) == RESULT_DECL
+ || TREE_CODE (id) == USING_DECL))
+ id = build_min_nt (LOOKUP_EXPR, token);
return id;
}
@@ -3027,17 +3059,17 @@ do_scoped_id (token, parsing)
{
if (processing_template_decl)
{
- id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
return id;
}
- if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
+ if (parsing && (yychar == '(' || yychar == LEFT_RIGHT)
+ && ! flag_strict_prototype)
id = implicitly_declare (token);
else
{
if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
- error ("undeclared variable `%s' (first use here)",
- IDENTIFIER_POINTER (token));
+ cp_error ("`::%D' undeclared (first use here)", token);
id = error_mark_node;
/* Prevent repeated error messages. */
SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
@@ -3064,9 +3096,9 @@ do_scoped_id (token, parsing)
{
if (is_overloaded_fn (id))
{
- id = build_min (LOOKUP_EXPR, unknown_type_node,
- token, get_first_fn (id));
+ id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
+ return id;
}
/* else just use the decl */
}
@@ -3081,16 +3113,20 @@ identifier_typedecl_value (node)
type = IDENTIFIER_TYPE_VALUE (node);
if (type == NULL_TREE)
return NULL_TREE;
-#define do(X) \
- { \
- t = (X); \
- if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
- return t; \
- }
- do (IDENTIFIER_LOCAL_VALUE (node));
- do (IDENTIFIER_CLASS_VALUE (node));
- do (IDENTIFIER_NAMESPACE_VALUE (node));
-#undef do
+
+ if (IDENTIFIER_BINDING (node))
+ {
+ t = IDENTIFIER_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+ if (IDENTIFIER_NAMESPACE_VALUE (node))
+ {
+ t = IDENTIFIER_NAMESPACE_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+
/* Will this one ever happen? */
if (TYPE_MAIN_DECL (type))
return TYPE_MAIN_DECL (type);
@@ -3100,6 +3136,103 @@ identifier_typedecl_value (node)
return NULL_TREE;
}
+struct pf_args
+{
+ /* Input */
+ /* I/O */
+ char *p;
+ int c;
+ int imag;
+ tree type;
+ /* Output */
+ REAL_VALUE_TYPE value;
+};
+
+static void
+parse_float (data)
+ PTR data;
+{
+ struct pf_args * args = (struct pf_args *) data;
+ int fflag = 0, lflag = 0;
+ /* Copy token_buffer now, while it has just the number
+ and not the suffixes; once we add `f' or `i',
+ REAL_VALUE_ATOF may not work any more. */
+ char *copy = (char *) alloca (args->p - token_buffer + 1);
+ bcopy (token_buffer, copy, args->p - token_buffer + 1);
+
+ while (1)
+ {
+ int lose = 0;
+
+ /* Read the suffixes to choose a data type. */
+ switch (args->c)
+ {
+ case 'f': case 'F':
+ if (fflag)
+ error ("more than one `f' in numeric constant");
+ fflag = 1;
+ break;
+
+ case 'l': case 'L':
+ if (lflag)
+ error ("more than one `l' in numeric constant");
+ lflag = 1;
+ break;
+
+ case 'i': case 'I':
+ if (args->imag)
+ error ("more than one `i' or `j' in numeric constant");
+ else if (pedantic)
+ pedwarn ("ANSI C++ forbids imaginary numeric constants");
+ args->imag = 1;
+ break;
+
+ default:
+ lose = 1;
+ }
+
+ if (lose)
+ break;
+
+ if (args->p >= token_buffer + maxtoken - 3)
+ args->p = extend_token_buffer (args->p);
+ *(args->p++) = args->c;
+ *(args->p) = 0;
+ args->c = getch ();
+ }
+
+ /* The second argument, machine_mode, of REAL_VALUE_ATOF
+ tells the desired precision of the binary result
+ of decimal-to-binary conversion. */
+
+ if (fflag)
+ {
+ if (lflag)
+ error ("both `f' and `l' in floating constant");
+
+ args->type = float_type_node;
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ /* A diagnostic is required here by some ANSI C testsuites.
+ This is not pedwarn, become some people don't want
+ an error for this. */
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `float'");
+ }
+ else if (lflag)
+ {
+ args->type = long_double_type_node;
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `long double'");
+ }
+ else
+ {
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `double'");
+ }
+}
+
int
real_yylex ()
{
@@ -3635,7 +3768,7 @@ real_yylex ()
int exceeds_double = 0;
int imag = 0;
REAL_VALUE_TYPE value;
- jmp_buf handler;
+ struct pf_args args;
/* Read explicit exponent if any, and put it in tokenbuf. */
@@ -3664,97 +3797,31 @@ real_yylex ()
*p = 0;
errno = 0;
+ /* Setup input for parse_float() */
+ args.p = p;
+ args.c = c;
+ args.imag = imag;
+ args.type = type;
+
/* Convert string to a double, checking for overflow. */
- if (setjmp (handler))
+ if (do_float_handler (parse_float, (PTR) &args))
{
- error ("floating constant out of range");
- value = dconst0;
+ /* Receive output from parse_float() */
+ value = args.value;
}
else
{
- int fflag = 0, lflag = 0;
- /* Copy token_buffer now, while it has just the number
- and not the suffixes; once we add `f' or `i',
- REAL_VALUE_ATOF may not work any more. */
- char *copy = (char *) alloca (p - token_buffer + 1);
- bcopy (token_buffer, copy, p - token_buffer + 1);
-
- set_float_handler (handler);
-
- while (1)
- {
- int lose = 0;
-
- /* Read the suffixes to choose a data type. */
- switch (c)
- {
- case 'f': case 'F':
- if (fflag)
- error ("more than one `f' in numeric constant");
- fflag = 1;
- break;
-
- case 'l': case 'L':
- if (lflag)
- error ("more than one `l' in numeric constant");
- lflag = 1;
- break;
-
- case 'i': case 'I':
- if (imag)
- error ("more than one `i' or `j' in numeric constant");
- else if (pedantic)
- pedwarn ("ANSI C++ forbids imaginary numeric constants");
- imag = 1;
- break;
-
- default:
- lose = 1;
- }
-
- if (lose)
- break;
-
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- *p = 0;
- c = getch ();
- }
-
- /* The second argument, machine_mode, of REAL_VALUE_ATOF
- tells the desired precision of the binary result
- of decimal-to-binary conversion. */
-
- if (fflag)
- {
- if (lflag)
- error ("both `f' and `l' in floating constant");
-
- type = float_type_node;
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- /* A diagnostic is required here by some ANSI C testsuites.
- This is not pedwarn, become some people don't want
- an error for this. */
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `float'");
- }
- else if (lflag)
- {
- type = long_double_type_node;
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `long double'");
- }
- else
- {
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `double'");
- }
-
- set_float_handler (NULL_PTR);
+ /* We got an exception from parse_float() */
+ error ("floating constant out of range");
+ value = dconst0;
}
+
+ /* Receive output from parse_float() */
+ p = args.p;
+ c = args.c;
+ imag = args.imag;
+ type = args.type;
+
#ifdef ERANGE
if (errno == ERANGE && pedantic)
{
@@ -3808,7 +3875,7 @@ real_yylex ()
{
if (spec_long_long)
error ("three `l's in integer constant");
- else if (pedantic)
+ else if (pedantic && ! in_system_header && warn_long_long)
pedwarn ("ANSI C++ forbids long long integer constants");
spec_long_long = 1;
}
@@ -3922,30 +3989,27 @@ real_yylex ()
{
register int result = 0;
register int num_chars = 0;
+ int chars_seen = 0;
unsigned width = TYPE_PRECISION (char_type_node);
int max_chars;
-
- if (wide_flag)
- {
- width = WCHAR_TYPE_SIZE;
#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif
- }
- else
- max_chars = TYPE_PRECISION (integer_type_node) / width;
+
+ max_chars = TYPE_PRECISION (integer_type_node) / width;
+ if (wide_flag)
+ width = WCHAR_TYPE_SIZE;
while (1)
{
tryagain:
-
c = getch ();
if (c == '\'' || c == EOF)
break;
+ ++chars_seen;
if (c == '\\')
{
int ignore = 0;
@@ -3953,8 +4017,8 @@ real_yylex ()
if (ignore)
goto tryagain;
if (width < HOST_BITS_PER_INT
- && (unsigned) c >= (1 << width))
- warning ("escape sequence out of range for character");
+ && (unsigned) c >= ((unsigned)1 << width))
+ pedwarn ("escape sequence out of range for character");
#ifdef MAP_CHARACTER
if (ISPRINT (c))
c = MAP_CHARACTER (c);
@@ -3963,21 +4027,79 @@ real_yylex ()
else if (c == '\n')
{
if (pedantic)
- pedwarn ("ANSI C++ forbids newline in character constant");
+ pedwarn ("ANSI C forbids newline in character constant");
lineno++;
}
-#ifdef MAP_CHARACTER
else
- c = MAP_CHARACTER (c);
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 1; i <= longest_char; ++i)
+ {
+ if (i > maxtoken - 4)
+ extend_token_buffer (token_buffer);
+
+ token_buffer[i] = c;
+ char_len = local_mbtowc (& wc,
+ token_buffer + 1,
+ i);
+ if (char_len != -1)
+ break;
+ c = getch ();
+ }
+ if (char_len > 1)
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len < i)
+ put_back (c);
+ if (! wide_flag)
+ {
+ /* Merge character into result; ignore excess chars. */
+ for (i = 1; i <= char_len; ++i)
+ {
+ if (i > max_chars)
+ break;
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width)
+ | (token_buffer[i]
+ & ((1 << width) - 1));
+ else
+ result = token_buffer[i];
+ }
+ num_chars += char_len;
+ goto tryagain;
+ }
+ c = wc;
+ }
+ else
+ {
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ if (wide_flag)
+ c = wc;
+#ifdef MAP_CHARACTER
+ else
+ c = MAP_CHARACTER (c);
#endif
+ }
+#else /* ! MULTIBYTE_CHARS */
+#ifdef MAP_CHARACTER
+ c = MAP_CHARACTER (c);
+#endif
+#endif /* ! MULTIBYTE_CHARS */
+ }
- num_chars++;
- if (num_chars > maxtoken - 4)
- extend_token_buffer (token_buffer);
-
- token_buffer[num_chars] = c;
+ if (wide_flag)
+ {
+ if (chars_seen == 1) /* only keep the first one */
+ result = c;
+ goto tryagain;
+ }
/* Merge character into result; ignore excess chars. */
+ num_chars++;
if (num_chars < max_chars + 1)
{
if (width < HOST_BITS_PER_INT)
@@ -3987,19 +4109,16 @@ real_yylex ()
}
}
- token_buffer[num_chars + 1] = '\'';
- token_buffer[num_chars + 2] = 0;
-
if (c != '\'')
error ("malformatted character constant");
- else if (num_chars == 0)
+ else if (chars_seen == 0)
error ("empty character constant");
else if (num_chars > max_chars)
{
num_chars = max_chars;
error ("character constant too long");
}
- else if (num_chars != 1 && warn_multichar)
+ else if (chars_seen != 1 && warn_multichar)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
@@ -4012,37 +4131,21 @@ real_yylex ()
else if (TREE_UNSIGNED (char_type_node)
|| ((result >> (num_bits - 1)) & 1) == 0)
yylval.ttype
- = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
+ = build_int_2 (result & (~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
0);
else
yylval.ttype
- = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
+ = build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
-1);
- if (num_chars<=1)
+ if (chars_seen <= 1)
TREE_TYPE (yylval.ttype) = char_type_node;
else
TREE_TYPE (yylval.ttype) = integer_type_node;
}
else
{
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[1] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL, NULL, 0);
- if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
- result = wc;
- else
- warning ("Ignoring invalid multibyte character");
- }
-#endif
yylval.ttype = build_int_2 (result, 0);
TREE_TYPE (yylval.ttype) = wchar_type_node;
}
@@ -4055,6 +4158,12 @@ real_yylex ()
string_constant:
{
register char *p;
+ unsigned width = wide_flag ? WCHAR_TYPE_SIZE
+ : TYPE_PRECISION (char_type_node);
+#ifdef MULTIBYTE_CHARS
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
+#endif
c = getch ();
p = token_buffer + 1;
@@ -4068,9 +4177,8 @@ real_yylex ()
c = readescape (&ignore);
if (ignore)
goto skipnewline;
- if (!wide_flag
- && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
- && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
+ if (width < HOST_BITS_PER_INT
+ && (unsigned) c >= ((unsigned)1 << width))
warning ("escape sequence out of range for character");
}
else if (c == '\n')
@@ -4079,10 +4187,72 @@ real_yylex ()
pedwarn ("ANSI C++ forbids newline in string constant");
lineno++;
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 0; i < longest_char; ++i)
+ {
+ if (p + i >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ p[i] = c;
- if (p == token_buffer + maxtoken)
- p = extend_token_buffer (p);
- *p++ = c;
+ char_len = local_mbtowc (& wc, p, i + 1);
+ if (char_len != -1)
+ break;
+ c = getch ();
+ }
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ else
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len <= i)
+ put_back (c);
+ if (! wide_flag)
+ {
+ p += (i + 1);
+ c = getch ();
+ continue;
+ }
+ c = wc;
+ }
+#endif /* MULTIBYTE_CHARS */
+ }
+
+ /* Add this single character into the buffer either as a wchar_t
+ or as a single byte. */
+ if (wide_flag)
+ {
+ unsigned width = TYPE_PRECISION (char_type_node);
+ unsigned bytemask = (1 << width) - 1;
+ int byte;
+
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+
+ for (byte = 0; byte < WCHAR_BYTES; ++byte)
+ {
+ int value;
+ if (byte >= (int) sizeof(c))
+ value = 0;
+ else
+ value = (c >> (byte * width)) & bytemask;
+ if (BYTES_BIG_ENDIAN)
+ p[WCHAR_BYTES - byte - 1] = value;
+ else
+ p[byte] = value;
+ }
+ p += WCHAR_BYTES;
+ }
+ else
+ {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = c;
+ }
skipnewline:
c = getch ();
@@ -4091,56 +4261,36 @@ real_yylex ()
break;
}
}
- *p = 0;
-
- /* We have read the entire constant.
- Construct a STRING_CST for the result. */
+ /* Terminate the string value, either with a single byte zero
+ or with a wide zero. */
if (wide_flag)
{
- /* If this is a L"..." wide-string, convert the multibyte string
- to a wide character string. */
- char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
- int len;
-
-#ifdef MULTIBYTE_CHARS
- len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
- if (len < 0 || len >= (p - token_buffer))
- {
- warning ("Ignoring invalid multibyte string");
- len = 0;
- }
- bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
-#else
- {
- char *wp, *cp;
-
- wp = widep + (BYTES_BIG_ENDIAN ? WCHAR_BYTES - 1 : 0);
- bzero (widep, (p - token_buffer) * WCHAR_BYTES);
- for (cp = token_buffer + 1; cp < p; cp++)
- *wp = *cp, wp += WCHAR_BYTES;
- len = p - token_buffer - 1;
- }
-#endif
- if (processing_template_decl)
- push_obstacks (&permanent_obstack, &permanent_obstack);
- yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
- if (processing_template_decl)
- pop_obstacks ();
- TREE_TYPE (yylval.ttype) = wchar_array_type_node;
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ bzero (p, WCHAR_BYTES);
+ p += WCHAR_BYTES;
}
else
{
- if (processing_template_decl)
- push_obstacks (&permanent_obstack, &permanent_obstack);
- yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
- if (processing_template_decl)
- pop_obstacks ();
- TREE_TYPE (yylval.ttype) = char_array_type_node;
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = 0;
}
- *p++ = '"';
- *p = 0;
+ /* We have read the entire constant.
+ Construct a STRING_CST for the result. */
+
+ if (processing_template_decl)
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ yylval.ttype = build_string (p - (token_buffer + 1), token_buffer + 1);
+ if (processing_template_decl)
+ pop_obstacks ();
+
+ if (wide_flag)
+ TREE_TYPE (yylval.ttype) = wchar_array_type_node;
+ else
+ TREE_TYPE (yylval.ttype) = char_array_type_node;
value = STRING; break;
}
@@ -4392,6 +4542,17 @@ build_lang_decl (code, name, type)
tree type;
{
register tree t = build_decl (code, name, type);
+ retrofit_lang_decl (t);
+ return t;
+}
+
+/* Add DECL_LANG_SPECIFIC info to T. Called from build_lang_decl
+ and pushdecl (for functions generated by the backend). */
+
+void
+retrofit_lang_decl (t)
+ tree t;
+{
struct obstack *obstack = current_obstack;
register int i = sizeof (struct lang_decl) / sizeof (int);
register int *pi;
@@ -4440,8 +4601,6 @@ build_lang_decl (code, name, type)
tree_node_counts[(int)lang_decl] += 1;
tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
-
- return t;
}
tree
@@ -4503,39 +4662,49 @@ make_lang_type (code)
{
extern struct obstack *current_obstack, *saveable_obstack;
register tree t = make_node (code);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_type) / sizeof (int);
- register int *pi;
/* Set up some flags that give proper default behavior. */
- IS_AGGR_TYPE (t) = 1;
+ if (IS_AGGR_TYPE_CODE (code))
+ {
+ struct obstack *obstack = current_obstack;
+ struct lang_type *pi;
- if (! TREE_PERMANENT (t))
- obstack = saveable_obstack;
- else
- my_friendly_assert (obstack == &permanent_obstack, 236);
+ SET_IS_AGGR_TYPE (t, 1);
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
- while (i > 0)
- pi[--i] = 0;
+ if (! TREE_PERMANENT (t))
+ obstack = saveable_obstack;
+ else
+ my_friendly_assert (obstack == &permanent_obstack, 236);
+
+ pi = (struct lang_type *) obstack_alloc (obstack, sizeof (struct lang_type));
+ bzero ((char *) pi, (int) sizeof (struct lang_type));
- TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
- CLASSTYPE_AS_LIST (t) = build_expr_list (NULL_TREE, t);
- SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
- CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE,
- NULL_TREE);
- CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
+ TYPE_LANG_SPECIFIC (t) = pi;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
+ CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- /* Make sure this is laid out, for ease of use later.
- In the presence of parse errors, the normal was of assuring
- this might not ever get executed, so we lay it out *immediately*. */
- build_pointer_type (t);
+ /* Make sure this is laid out, for ease of use later. In the
+ presence of parse errors, the normal was of assuring this
+ might not ever get executed, so we lay it out *immediately*. */
+ build_pointer_type (t);
#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
+ tree_node_counts[(int)lang_type] += 1;
+ tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
#endif
+ }
+ else
+ /* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits. But,
+ TYPE_ALIAS_SET is initialized to -1 by default, so we must
+ clear it here. */
+ TYPE_ALIAS_SET (t) = 0;
+
+ /* We need to allocate a TYPE_BINFO even for TEMPALTE_TYPE_PARMs
+ since they can be virtual base types, and we then need a
+ canonical binfo for them. Ideally, this would be done lazily for
+ all types. */
+ if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM)
+ TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE);
return t;
}
@@ -4545,7 +4714,7 @@ dump_time_statistics ()
{
register tree prev = 0, decl, next;
int this_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
fprintf (stderr, "\n******\n");
@@ -4564,22 +4733,31 @@ dump_time_statistics ()
for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
print_time (IDENTIFIER_POINTER (decl),
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (decl)));
}
void
-compiler_error (s, v, v2)
- char *s;
- HOST_WIDE_INT v, v2; /* @@also used as pointer */
+compiler_error VPROTO ((const char *msg, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msg;
+#endif
char buf[1024];
- sprintf (buf, s, v, v2);
+ va_list ap;
+
+ VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+ msg = va_arg (ap, const char *);
+#endif
+
+ vsprintf (buf, msg, ap);
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
void
yyerror (string)
- char *string;
+ const char *string;
{
extern int end_of_file;
char buf[200];
@@ -4598,7 +4776,7 @@ yyerror (string)
strcat (buf, " before string constant");
else if (token_buffer[0] == '\'')
strcat (buf, " before character constant");
- else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
+ else if (!ISGRAPH ((unsigned char)token_buffer[0]))
sprintf (buf + strlen (buf), " before character 0%o",
(unsigned char) token_buffer[0]);
else
@@ -4609,7 +4787,7 @@ yyerror (string)
static int
handle_cp_pragma (pname)
- char *pname;
+ const char *pname;
{
register int token;
@@ -4655,7 +4833,8 @@ handle_cp_pragma (pname)
}
else if (! strcmp (pname, "interface"))
{
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
char *main_filename = input_filename;
main_filename = file_name_nondirectory (main_filename);
@@ -4677,7 +4856,6 @@ handle_cp_pragma (pname)
if (token != END_OF_LINE)
warning ("garbage after `#pragma interface' ignored");
-#ifndef NO_LINKAGE_HEURISTICS
write_virtuals = 3;
if (impl_file_chain == 0)
@@ -4690,7 +4868,7 @@ handle_cp_pragma (pname)
#ifdef AUTO_IMPLEMENT
filename = file_name_nondirectory (main_input_filename);
fi = get_time_identifier (filename);
- fi = IDENTIFIER_CLASS_VALUE (fi);
+ fi = TIME_IDENTIFIER_FILEINFO (fi);
TREE_INT_CST_LOW (fi) = 0;
TREE_INT_CST_HIGH (fi) = 1;
/* Get default. */
@@ -4701,16 +4879,21 @@ handle_cp_pragma (pname)
}
interface_only = interface_strcmp (main_filename);
+#ifdef MULTIPLE_SYMBOL_SPACES
+ if (! interface_only)
+ interface_unknown = 0;
+#else /* MULTIPLE_SYMBOL_SPACES */
interface_unknown = 0;
+#endif /* MULTIPLE_SYMBOL_SPACES */
TREE_INT_CST_LOW (fileinfo) = interface_only;
TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
-#endif /* NO_LINKAGE_HEURISTICS */
return 1;
}
else if (! strcmp (pname, "implementation"))
{
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
char *main_filename = main_input_filename ? main_input_filename : input_filename;
main_filename = file_name_nondirectory (main_filename);
@@ -4730,7 +4913,6 @@ handle_cp_pragma (pname)
if (token != END_OF_LINE)
warning ("garbage after `#pragma implementation' ignored");
-#ifndef NO_LINKAGE_HEURISTICS
if (write_virtuals == 3)
{
struct impl_files *ifiles = impl_file_chain;
@@ -4775,25 +4957,43 @@ handle_cp_pragma (pname)
#endif
TREE_INT_CST_LOW (fileinfo) = interface_only;
TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
-#endif /* NO_LINKAGE_HEURISTICS */
return 1;
}
return 0;
}
+
+/* Return the type-qualifier corresponding to the identifier given by
+ RID. */
+
+int
+cp_type_qual_from_rid (rid)
+ tree rid;
+{
+ if (rid == ridpointers[(int) RID_CONST])
+ return TYPE_QUAL_CONST;
+ else if (rid == ridpointers[(int) RID_VOLATILE])
+ return TYPE_QUAL_VOLATILE;
+ else if (rid == ridpointers[(int) RID_RESTRICT])
+ return TYPE_QUAL_RESTRICT;
+
+ my_friendly_abort (0);
+ return TYPE_UNQUALIFIED;
+}
+
-#ifdef HANDLE_SYSV_PRAGMA
+#ifdef HANDLE_GENERIC_PRAGMAS
-/* Handle a #pragma directive. INPUT is the current input stream,
- and C is a character to reread. Processes the entire input line
- and returns a character for the caller to reread: either \n or EOF. */
+/* Handle a #pragma directive. TOKEN is the type of the word following
+ the #pragma directive on the line. Process the entire input line and
+ return non-zero iff the directive successfully parsed. */
/* This function has to be in this file, in order to get at
the token types. */
static int
-handle_sysv_pragma (token)
+handle_generic_pragma (token)
register int token;
{
for (;;)
@@ -4802,32 +5002,24 @@ handle_sysv_pragma (token)
{
case IDENTIFIER:
case TYPENAME:
- case STRING:
- case CONSTANT:
- handle_pragma_token ("ignored", yylval.ttype);
- break;
- case '(':
- handle_pragma_token ("(", NULL_TREE);
- break;
- case ')':
- handle_pragma_token (")", NULL_TREE);
- break;
- case ',':
- handle_pragma_token (",", NULL_TREE);
- break;
- case '=':
- handle_pragma_token ("=", NULL_TREE);
+ case STRING:
+ case CONSTANT:
+ handle_pragma_token (token_buffer, yylval.ttype);
break;
+
case LEFT_RIGHT:
handle_pragma_token ("(", NULL_TREE);
handle_pragma_token (")", NULL_TREE);
break;
+
case END_OF_LINE:
+ return handle_pragma_token (NULL_PTR, NULL_TREE);
+
default:
- handle_pragma_token (NULL_PTR, NULL_TREE);
- return 1;
+ handle_pragma_token (token_buffer, NULL_TREE);
}
+
token = real_yylex ();
}
}
-#endif /* HANDLE_SYSV_PRAGMA */
+#endif /* HANDLE_GENERIC_PRAGMAS */
diff --git a/contrib/gcc/cp/lex.h b/contrib/gcc/cp/lex.h
index 8df6b76..249eef9 100644
--- a/contrib/gcc/cp/lex.h
+++ b/contrib/gcc/cp/lex.h
@@ -1,5 +1,5 @@
/* Define constants and variables for communication with parse.y.
- Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
and by Brendan Kehoe (brendan@cygnus.com).
@@ -59,10 +59,12 @@ enum rid
RID_FRIEND,
RID_VIRTUAL,
RID_EXPLICIT,
+ RID_EXPORT,
RID_SIGNED,
RID_AUTO,
RID_MUTABLE,
RID_COMPLEX,
+ RID_RESTRICT,
/* This is where grokdeclarator ends its search when setting the
specbits. */
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index 29b31c4..d4a667b 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -1,6 +1,6 @@
/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
- Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -57,7 +57,8 @@ static char *scratch_firstobj;
static void icat PROTO((HOST_WIDE_INT));
static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
-static void flush_repeats PROTO((int, tree));
+static int old_backref_index PROTO((tree));
+static int flush_repeats PROTO((int, tree));
static void build_overload_identifier PROTO((tree));
static void build_overload_nested_name PROTO((tree));
static void build_overload_int PROTO((tree, int));
@@ -71,8 +72,6 @@ static void process_overload_item PROTO((tree,int));
static void do_build_assign_ref PROTO((tree));
static void do_build_copy_constructor PROTO((tree));
static tree largest_union_member PROTO((tree));
-static tree build_decl_overload_real PROTO((tree, tree, tree, tree,
- tree, int));
static void build_template_template_parm_names PROTO((tree));
static void build_template_parm_names PROTO((tree, tree));
static void build_underscore_int PROTO((int));
@@ -82,6 +81,9 @@ static int check_ktype PROTO((tree, int));
static int issue_ktype PROTO((tree));
static void build_overload_scope_ref PROTO((tree));
static void build_mangled_template_parm_index PROTO((char *, tree));
+#if HOST_BITS_PER_WIDE_INT >= 64
+static void build_mangled_C9x_name PROTO((int));
+#endif
static int is_back_referenceable_type PROTO((tree));
static int check_btype PROTO((tree));
static void build_mangled_name_for_type PROTO((tree));
@@ -298,15 +300,48 @@ dicat (lo, hi)
OB_PUTC ('0' + ulo);
}
-static __inline void
+/* Returns the index of TYPE in the typevec, or -1 if it's not there. */
+
+static __inline int
+old_backref_index (type)
+ tree type;
+{
+ int tindex = 0;
+
+ if (! is_back_referenceable_type (type))
+ return -1;
+
+ /* The entry for this parm is at maxtype-1, so don't look there for
+ something to repeat. */
+ for (tindex = 0; tindex < maxtype - 1; ++tindex)
+ if (same_type_p (typevec[tindex], type))
+ break;
+
+ if (tindex == maxtype - 1)
+ return -1;
+
+ return tindex;
+}
+
+/* Old mangling style: If TYPE has already been used in the parameter list,
+ emit a backward reference and return non-zero; otherwise, return 0.
+
+ NREPEATS is the number of repeats we've recorded of this type, or 0 if
+ this is the first time we've seen it and we're just looking to see if
+ it had been used before. */
+
+static __inline int
flush_repeats (nrepeats, type)
int nrepeats;
tree type;
{
- int tindex = 0;
+ int tindex = old_backref_index (type);
- while (typevec[tindex] != type)
- tindex++;
+ if (tindex == -1)
+ {
+ my_friendly_assert (nrepeats == 0, 990316);
+ return 0;
+ }
if (nrepeats > 1)
{
@@ -320,25 +355,33 @@ flush_repeats (nrepeats, type)
icat (tindex);
if (tindex > 9)
OB_PUTC ('_');
+
+ return 1;
}
/* Returns nonzero iff this is a type to which we will want to make
back-references (using the `B' code). */
-int
+static int
is_back_referenceable_type (type)
tree type;
{
- if (btypelist == NULL)
- /* We're not generating any back-references. */
+ /* For some reason, the Java folks don't want back refs on these. */
+ if (TYPE_FOR_JAVA (type))
return 0;
switch (TREE_CODE (type))
{
+ case BOOLEAN_TYPE:
+ if (!flag_do_squangling)
+ /* Even though the mangling of this is just `b', we did
+ historically generate back-references for it. */
+ return 1;
+ /* Fall through. */
+
case INTEGER_TYPE:
case REAL_TYPE:
case VOID_TYPE:
- case BOOLEAN_TYPE:
/* These types have single-character manglings, so there's no
point in generating back-references. */
return 0;
@@ -376,8 +419,10 @@ issue_nrepeats (nrepeats, type)
}
}
-/* Check to see if a tree node has been entered into the Kcode typelist */
-/* if not, add it. Return -1 if it isn't found, otherwise return the index */
+/* Check to see if a tree node has been entered into the Kcode typelist.
+ If not, add it. Returns -1 if it isn't found, otherwise returns the
+ index. */
+
static int
check_ktype (node, add)
tree node;
@@ -394,10 +439,10 @@ check_ktype (node, add)
for (x=0; x < maxktype; x++)
{
- if (localnode == ktypelist[x])
- return x ;
+ if (same_type_p (localnode, ktypelist[x]))
+ return x;
}
- /* Didn't find it, so add it here */
+ /* Didn't find it, so add it here. */
if (add)
{
if (maxksize <= maxktype)
@@ -625,20 +670,53 @@ build_mangled_template_parm_index (s, index)
}
+/* Mangling for C9X integer types (and Cygnus extensions for 128-bit
+ and other types) is based on the letter "I" followed by the hex
+ representations of the bitsize for the type in question. For
+ encodings that result in larger than two digits, a leading and
+ trailing underscore is added.
+
+ Thus:
+ int1_t = 001 = I01
+ int8_t = 008 = I08
+ int16_t = 010 = I10
+ int24_t = 018 = I18
+ int32_t = 020 = I20
+ int64_t = 040 = I40
+ int80_t = 050 = I50
+ int128_t = 080 = I80
+ int256_t = 100 = I_100_
+ int512_t = 200 = I_200_
+
+ Given an integer in decimal format, mangle according to this scheme. */
+
+#if HOST_BITS_PER_WIDE_INT >= 64
+static void
+build_mangled_C9x_name (bits)
+ int bits;
+{
+ char mangled[10] = "";
+
+ if (bits > 255)
+ sprintf (mangled, "I_%x_", bits);
+ else
+ sprintf (mangled, "I%.2x", bits);
+
+ OB_PUTCP (mangled);
+}
+#endif
+
static void
build_overload_value (type, value, in_template)
tree type, value;
int in_template;
{
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
+
while (TREE_CODE (value) == NON_LVALUE_EXPR
|| TREE_CODE (value) == NOP_EXPR)
value = TREE_OPERAND (value, 0);
- if (TREE_CODE (type) == PARM_DECL)
- type = TREE_TYPE (type);
-
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0);
-
if (numeric_output_need_bar)
{
OB_PUTC ('_');
@@ -651,21 +729,21 @@ build_overload_value (type, value, in_template)
return;
}
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (type))
{
- /* Handle a pointer to data member as a template instantiation
- parameter, boy, what fun! */
- type = integer_type_node;
- if (TREE_CODE (value) != INTEGER_CST)
- {
- sorry ("unknown pointer to member constant");
- return;
- }
- }
+ if (TREE_CODE (value) != PTRMEM_CST)
+ /* We should have already rejected this pointer to member,
+ since it is not a constant. */
+ my_friendly_abort (0);
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ /* Get the actual FIELD_DECL. */
+ value = PTRMEM_CST_MEMBER (value);
+ my_friendly_assert (TREE_CODE (value) == FIELD_DECL, 0);
+
+ /* Output the name of the field. */
+ build_overload_identifier (DECL_NAME (value));
+ return;
+ }
switch (TREE_CODE (type))
{
@@ -743,46 +821,6 @@ build_overload_value (type, value, in_template)
return;
}
case POINTER_TYPE:
- if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
- && TREE_CODE (value) != ADDR_EXPR)
- {
- if (TREE_CODE (value) == CONSTRUCTOR)
- {
- /* This is dangerous code, crack built up pointer to members. */
- tree args = CONSTRUCTOR_ELTS (value);
- tree a1 = TREE_VALUE (args);
- tree a2 = TREE_VALUE (TREE_CHAIN (args));
- tree a3 = CONSTRUCTOR_ELTS (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))));
- a3 = TREE_VALUE (a3);
- STRIP_NOPS (a3);
- if (TREE_CODE (a1) == INTEGER_CST
- && TREE_CODE (a2) == INTEGER_CST)
- {
- build_overload_int (a1, in_template);
- OB_PUTC ('_');
- build_overload_int (a2, in_template);
- OB_PUTC ('_');
- if (TREE_CODE (a3) == ADDR_EXPR)
- {
- a3 = TREE_OPERAND (a3, 0);
- if (TREE_CODE (a3) == FUNCTION_DECL)
- {
- numeric_output_need_bar = 0;
- build_overload_identifier (DECL_ASSEMBLER_NAME (a3));
- return;
- }
- }
- else if (TREE_CODE (a3) == INTEGER_CST)
- {
- OB_PUTC ('i');
- build_overload_int (a3, in_template);
- return;
- }
- }
- }
- sorry ("template instantiation with pointer to method that is too complex");
- return;
- }
if (TREE_CODE (value) == INTEGER_CST)
{
build_overload_int (value, in_template);
@@ -796,6 +834,10 @@ build_overload_value (type, value, in_template)
}
value = TREE_OPERAND (value, 0);
+
+ /* Fall through. */
+
+ case REFERENCE_TYPE:
if (TREE_CODE (value) == VAR_DECL)
{
my_friendly_assert (DECL_NAME (value) != 0, 245);
@@ -814,6 +856,51 @@ build_overload_value (type, value, in_template)
my_friendly_abort (71);
break; /* not really needed */
+ case RECORD_TYPE:
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 0);
+
+ /* We'll get a ADDR_EXPR of a SCOPE_REF here if we're
+ mangling, an instantiation of something like:
+
+ template <class T, void (T::*fp)()> class C {};
+ template <class T> C<T, &T::f> x();
+
+ We mangle the return type of the function, and that
+ contains template parameters. */
+ if (TREE_CODE (value) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (value, 0)) == SCOPE_REF)
+ {
+ build_overload_scope_ref (TREE_OPERAND (value, 0));
+ break;
+ }
+
+ my_friendly_assert (TREE_CODE (value) == PTRMEM_CST, 0);
+
+ expand_ptrmemfunc_cst (value, &delta, &idx, &pfn, &delta2);
+ build_overload_int (delta, in_template);
+ OB_PUTC ('_');
+ build_overload_int (idx, in_template);
+ OB_PUTC ('_');
+ if (pfn)
+ {
+ numeric_output_need_bar = 0;
+ build_overload_identifier (DECL_ASSEMBLER_NAME
+ (PTRMEM_CST_MEMBER (value)));
+ }
+ else
+ {
+ OB_PUTC ('i');
+ build_overload_int (delta2, in_template);
+ }
+ }
+ break;
+
default:
sorry ("conversion of %s as template parameter",
tree_code_name [(int) TREE_CODE (type)]);
@@ -823,7 +910,7 @@ build_overload_value (type, value, in_template)
/* Add encodings for the declaration of template template parameters.
- PARMLIST must be a TREE_VEC */
+ PARMLIST must be a TREE_VEC. */
static void
build_template_template_parm_names (parmlist)
@@ -864,13 +951,14 @@ build_template_parm_names (parmlist, arglist)
tree arglist;
{
int i, nparms;
-
+ tree inner_args = innermost_args (arglist);
+
nparms = TREE_VEC_LENGTH (parmlist);
icat (nparms);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
- tree arg = TREE_VEC_ELT (arglist, i);
+ tree arg = TREE_VEC_ELT (inner_args, i);
if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
@@ -879,9 +967,9 @@ build_template_parm_names (parmlist, arglist)
}
else if (TREE_CODE (parm) == TEMPLATE_DECL)
{
- /* This parameter is a template. */
+ /* This parameter is a template. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- /* Output parameter declaration, argument index and level */
+ /* Output parameter declaration, argument index and level. */
build_mangled_name_for_type (arg);
else
{
@@ -889,17 +977,19 @@ build_template_parm_names (parmlist, arglist)
and template name */
OB_PUTC ('z');
- build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm));
+ build_template_template_parm_names
+ (DECL_INNERMOST_TEMPLATE_PARMS (parm));
icat (IDENTIFIER_LENGTH (DECL_NAME (arg)));
OB_PUTID (DECL_NAME (arg));
}
}
else
{
- parm = tsubst (parm, arglist, NULL_TREE);
+ parm = tsubst (parm, arglist, /*complain=*/1, NULL_TREE);
/* It's a PARM_DECL. */
build_mangled_name_for_type (TREE_TYPE (parm));
- build_overload_value (parm, arg, uses_template_parms (arglist));
+ build_overload_value (TREE_TYPE (parm), arg,
+ uses_template_parms (arglist));
}
}
}
@@ -912,7 +1002,7 @@ build_overload_identifier (name)
tree name;
{
if (TREE_CODE (name) == TYPE_DECL
- && IS_AGGR_TYPE (TREE_TYPE (name))
+ && CLASS_TYPE_P (TREE_TYPE (name))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name))
&& (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name)))
|| (TREE_CODE (DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE
@@ -921,9 +1011,8 @@ build_overload_identifier (name)
{
/* NAME is the TYPE_DECL for a template specialization. */
tree template, parmlist, arglist, tname;
- template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
- arglist = innermost_args (TREE_VALUE (template), 0);
- template = TREE_PURPOSE (template);
+ template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name));
+ arglist = CLASSTYPE_TI_ARGS (TREE_TYPE (name));
tname = DECL_NAME (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
OB_PUTC ('t');
@@ -970,15 +1059,18 @@ build_qualified_name (decl)
}
context = decl;
- /* if we can't find a Ktype, do it the hard way */
+ /* If we can't find a Ktype, do it the hard way. */
if (check_ktype (context, FALSE) == -1)
{
- /* count type and namespace scopes */
- while (DECL_CONTEXT (context) && DECL_CONTEXT (context) != global_namespace)
+ /* Count type and namespace scopes. */
+ while (1)
{
+ context = CP_DECL_CONTEXT (context);
+ if (context == global_namespace)
+ break;
i += 1;
- context = DECL_CONTEXT (context);
- if (check_ktype (context, FALSE) != -1) /* found it! */
+ if (check_ktype (context, FALSE) != -1)
+ /* Found one! */
break;
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context);
@@ -998,14 +1090,13 @@ build_qualified_name (decl)
non-zero, mangled names for structure/union types are intentionally
mangled differently from the method described in the ARM. */
-void
+static void
build_mangled_name_for_type_with_Gcode (type, extra_Gcode)
tree type;
int extra_Gcode;
{
if (TYPE_PTRMEMFUNC_P (type))
type = TYPE_PTRMEMFUNC_FN_TYPE (type);
- type = canonical_type_variant (type);
process_modifiers (type);
process_overload_item (type, extra_Gcode);
}
@@ -1013,7 +1104,7 @@ build_mangled_name_for_type_with_Gcode (type, extra_Gcode)
/* Like build_mangled_name_for_type_with_Gcode, but never outputs the
`G'. */
-void
+static void
build_mangled_name_for_type (type)
tree type;
{
@@ -1069,7 +1160,11 @@ build_mangled_name (parmtypes, begin, end)
for (; parmtypes && parmtypes != void_list_node;
parmtypes = TREE_CHAIN (parmtypes))
{
- tree parmtype = canonical_type_variant (TREE_VALUE (parmtypes));
+ /* We used to call canonical_type_variant here, but that isn't
+ good enough; it doesn't handle pointers to typedef types. So
+ we can't just set TREE_USED to say we've seen a type already;
+ we have to check each of the earlier types with same_type_p. */
+ tree parmtype = TREE_VALUE (parmtypes);
if (old_style_repeats)
{
@@ -1078,11 +1173,11 @@ build_mangled_name (parmtypes, begin, end)
typevec[maxtype++] = parmtype;
}
- if (parmtype == last_type)
+ if (last_type && same_type_p (parmtype, last_type))
{
if (flag_do_squangling
- || (old_style_repeats && TREE_USED (parmtype)
- && !TYPE_FOR_JAVA (parmtype)))
+ || (old_style_repeats
+ && is_back_referenceable_type (parmtype)))
{
/* The next type is the same as this one. Keep
track of the repetition, and output the repeat
@@ -1104,35 +1199,11 @@ build_mangled_name (parmtypes, begin, end)
last_type = parmtype;
- if (old_style_repeats)
- {
- if (nrepeats)
- {
- flush_repeats (nrepeats, last_type);
- nrepeats = 0;
- }
-
- if (TREE_USED (parmtype))
- {
-#if 0
- /* We can turn this on at some point when we want
- improved symbol mangling. */
- nrepeats++;
-#else
- /* This is bug compatible with 2.7.x */
- flush_repeats (nrepeats, parmtype);
-#endif
- nrepeats = 0;
- continue;
- }
-
- /* Only cache types which take more than one character. */
- if ((parmtype != TYPE_MAIN_VARIANT (parmtype)
- || (TREE_CODE (parmtype) != INTEGER_TYPE
- && TREE_CODE (parmtype) != REAL_TYPE))
- && ! TYPE_FOR_JAVA (parmtype))
- TREE_USED (parmtype) = 1;
- }
+ /* Note that for bug-compatibility with 2.7.2, we can't build up
+ repeats of types other than the most recent one. So we call
+ flush_repeats every round, if we get this far. */
+ if (old_style_repeats && flush_repeats (0, parmtype))
+ continue;
/* Output the PARMTYPE. */
build_mangled_name_for_type_with_Gcode (parmtype, 1);
@@ -1159,27 +1230,37 @@ build_mangled_name (parmtypes, begin, end)
return (char *)obstack_base (&scratch_obstack);
}
-/* handles emitting modifiers such as Constant, read-only, and volatile */
-void
+/* Emit modifiers such as constant, read-only, and volatile. */
+
+static void
process_modifiers (parmtype)
tree parmtype;
{
- if (TREE_READONLY (parmtype))
+ /* Note that here we do not use CP_TYPE_CONST_P and friends because
+ we describe types recursively; we will get the `const' in
+ `const int ()[10]' when processing the `const int' part. */
+ if (TYPE_READONLY (parmtype))
OB_PUTC ('C');
if (TREE_CODE (parmtype) == INTEGER_TYPE
+ && parmtype != char_type_node
+ && parmtype != wchar_type_node
&& (TYPE_MAIN_VARIANT (parmtype)
== unsigned_type (TYPE_MAIN_VARIANT (parmtype)))
&& ! TYPE_FOR_JAVA (parmtype))
OB_PUTC ('U');
if (TYPE_VOLATILE (parmtype))
OB_PUTC ('V');
+ /* It would be better to use `R' for `restrict', but that's already
+ used for reference types. And `r' is used for `long double'. */
+ if (TYPE_RESTRICT (parmtype))
+ OB_PUTC ('u');
}
/* Check to see if TYPE has been entered into the Bcode typelist. If
so, return 1 and emit a backreference to TYPE. Otherwise, add TYPE
to the list of back-referenceable types and return 0. */
-int
+static int
check_btype (type)
tree type;
{
@@ -1191,12 +1272,8 @@ check_btype (type)
if (!is_back_referenceable_type (type))
return 0;
- /* We assume that our caller has put out any necessary
- qualifiers. */
- type = TYPE_MAIN_VARIANT (type);
-
for (x = 0; x < maxbtype; x++)
- if (type == btypelist[x])
+ if (same_type_p (type, btypelist[x]))
{
OB_PUTC ('B');
icat (x);
@@ -1218,7 +1295,8 @@ check_btype (type)
return 0;
}
-/* handle emitting the correct code for various node types */
+/* Emit the correct code for various node types. */
+
static void
process_overload_item (parmtype, extra_Gcode)
tree parmtype;
@@ -1226,9 +1304,17 @@ process_overload_item (parmtype, extra_Gcode)
{
numeric_output_need_bar = 0;
- /* These tree types are considered modifiers for B code squangling , */
- /* and therefore should not get entries in the Btypelist */
- /* they are, however, repeatable types */
+ /* Our caller should have already handed any qualifiers, so pull out the
+ TYPE_MAIN_VARIANT to avoid typedef confusion. Except we can't do that
+ for arrays, because they are transparent to qualifiers. Sigh. */
+ if (TREE_CODE (parmtype) == ARRAY_TYPE)
+ parmtype = canonical_type_variant (parmtype);
+ else
+ parmtype = TYPE_MAIN_VARIANT (parmtype);
+
+ /* These tree types are considered modifiers for B code squangling,
+ and therefore should not get entries in the Btypelist. They are,
+ however, repeatable types. */
switch (TREE_CODE (parmtype))
{
@@ -1239,11 +1325,9 @@ process_overload_item (parmtype, extra_Gcode)
case ARRAY_TYPE:
#if PARM_CAN_BE_ARRAY_TYPE
{
- tree length;
-
OB_PUTC ('A');
if (TYPE_DOMAIN (parmtype) == NULL_TREE)
- error("pointer/reference to array of unknown bound in parm type");
+ OB_PUTC ('_');
else
{
tree length = array_type_nelts (parmtype);
@@ -1331,7 +1415,6 @@ process_overload_item (parmtype, extra_Gcode)
}
case INTEGER_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == integer_type_node
|| parmtype == unsigned_type_node
|| parmtype == java_int_type_node)
@@ -1359,15 +1442,18 @@ process_overload_item (parmtype, extra_Gcode)
|| parmtype == long_long_unsigned_type_node
|| parmtype == java_long_type_node)
OB_PUTC ('x');
-#if 0
- /* it would seem there is no way to enter these in source code,
- yet. (mrs) */
- else if (parmtype == long_long_long_integer_type_node
- || parmtype == long_long_long_unsigned_type_node)
- OB_PUTC ('q');
-#endif
else if (parmtype == java_boolean_type_node)
OB_PUTC ('b');
+#if HOST_BITS_PER_WIDE_INT >= 64
+ else if (parmtype == intTI_type_node
+ || parmtype == unsigned_intTI_type_node)
+ {
+ /* Should just check a flag here instead of specific
+ *_type_nodes, because all C9x types could use this. */
+ int bits = TREE_INT_CST_LOW (TYPE_SIZE (parmtype));
+ build_mangled_C9x_name (bits);
+ }
+#endif
else
my_friendly_abort (73);
break;
@@ -1377,7 +1463,6 @@ process_overload_item (parmtype, extra_Gcode)
break;
case REAL_TYPE:
- parmtype = TYPE_MAIN_VARIANT (parmtype);
if (parmtype == long_double_type_node)
OB_PUTC ('r');
else if (parmtype == double_type_node
@@ -1413,11 +1498,6 @@ process_overload_item (parmtype, extra_Gcode)
{
tree name = TYPE_NAME (parmtype);
- if (TREE_CODE (name) == IDENTIFIER_NODE)
- {
- build_overload_identifier (TYPE_NAME (parmtype));
- break;
- }
my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248);
build_qualified_name (name);
@@ -1432,14 +1512,14 @@ process_overload_item (parmtype, extra_Gcode)
case TEMPLATE_TEMPLATE_PARM:
/* Find and output the original template parameter
declaration. */
- if (CLASSTYPE_TEMPLATE_INFO (parmtype))
+ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parmtype))
{
build_mangled_template_parm_index ("tzX",
TEMPLATE_TYPE_PARM_INDEX
(parmtype));
build_template_parm_names
- (DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
- CLASSTYPE_TI_ARGS (parmtype));
+ (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (parmtype)),
+ TYPE_TI_ARGS (parmtype));
}
else
{
@@ -1499,7 +1579,10 @@ build_static_name (context, name)
return get_identifier ((char *)obstack_base (&scratch_obstack));
}
-static tree
+/* FOR_METHOD should be 1 if the declaration in question is for a member
+ of a class (including a static member) and 2 if the declaration is
+ for a constructor. */
+tree
build_decl_overload_real (dname, parms, ret_type, tparms, targs,
for_method)
tree dname;
@@ -1557,12 +1640,13 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
OB_PUTC ('v');
else
{
- if (!flag_do_squangling) /* Allocate typevec array. */
+ if (!flag_do_squangling)
{
+ /* Allocate typevec array. */
maxtype = 0;
typevec_size = list_length (parms);
if (!for_method && current_namespace != global_namespace)
- /* the namespace of a global function needs one slot */
+ /* The namespace of a global function needs one slot. */
typevec_size++;
typevec = (tree *)alloca (typevec_size * sizeof (tree));
}
@@ -1583,12 +1667,6 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
{
my_friendly_assert (maxtype < typevec_size, 387);
typevec[maxtype++] = this_type;
- TREE_USED (this_type) = 1;
-
- /* By setting up PARMS in this way, the loop below will
- automatically clear TREE_USED on THIS_TYPE. */
- parms = temp_tree_cons (NULL_TREE, this_type,
- TREE_CHAIN (parms));
}
if (TREE_CHAIN (parms))
@@ -1609,20 +1687,9 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs,
build_mangled_name (parms, 0, 0);
}
- if (!flag_do_squangling) /* Deallocate typevec array */
- {
- tree t = parms;
- typevec = NULL;
- while (t)
- {
- tree temp = TREE_VALUE (t);
- TREE_USED (temp) = 0;
- /* clear out the type variant in case we used it */
- temp = canonical_type_variant (temp);
- TREE_USED (temp) = 0;
- t = TREE_CHAIN (t);
- }
- }
+ if (!flag_do_squangling)
+ /* Deallocate typevec array. */
+ typevec = NULL;
}
if (ret_type != NULL_TREE && for_method != 2)
@@ -1661,38 +1728,38 @@ build_decl_overload (dname, parms, for_method)
NULL_TREE, for_method);
}
+/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */
-/* Like build_decl_overload, but for template functions. */
-
-tree
-build_template_decl_overload (decl, parms, ret_type, tparms, targs,
- for_method)
+void
+set_mangled_name_for_decl (decl)
tree decl;
- tree parms;
- tree ret_type;
- tree tparms;
- tree targs;
- int for_method;
{
- tree res, saved_ctx;
-
- /* If the template is in a namespace, we need to put that into the
- mangled name. Unfortunately, build_decl_overload_real does not
- get the decl to mangle, so it relies on the current
- namespace. Therefore, we set that here temporarily. */
+ tree parm_types;
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
- saved_ctx = current_namespace;
- current_namespace = CP_DECL_CONTEXT (decl);
+ if (processing_template_decl)
+ /* There's no need to mangle the name of a template function. */
+ return;
- res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type,
- tparms, targs, for_method);
+ parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
- current_namespace = saved_ctx;
- return res;
+ if (DECL_STATIC_FUNCTION_P (decl))
+ parm_types =
+ hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)),
+ parm_types);
+ else
+ /* The only member functions whose type is a FUNCTION_TYPE, rather
+ than a METHOD_TYPE, should be static members. */
+ my_friendly_assert (!DECL_CONTEXT (decl)
+ || !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl)))
+ || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE,
+ 0);
+
+ DECL_ASSEMBLER_NAME (decl)
+ = build_decl_overload (DECL_NAME (decl), parm_types,
+ DECL_FUNCTION_MEMBER_P (decl)
+ + DECL_CONSTRUCTOR_P (decl));
}
-
/* Build an overload name for the type expression TYPE. */
tree
@@ -1851,8 +1918,16 @@ hack_identifier (value, name)
{
if (current_class_ptr == NULL_TREE)
{
- error ("request for member `%s' in static member function",
- IDENTIFIER_POINTER (DECL_NAME (value)));
+ if (current_function_decl
+ && DECL_STATIC_FUNCTION_P (current_function_decl))
+ cp_error ("invalid use of member `%D' in static member function",
+ value);
+ else
+ /* We can get here when processing a bad default
+ argument, like:
+ struct S { int a; void f(int i = a); } */
+ cp_error ("invalid use of member `%D'", value);
+
return error_mark_node;
}
TREE_USED (current_class_ptr) = 1;
@@ -1863,24 +1938,24 @@ hack_identifier (value, name)
TREE_USED (value) = 1;
value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
}
- else if (TREE_CODE (value) == FUNCTION_DECL
- && DECL_FUNCTION_MEMBER_P (value))
- /* This is a placeholder; don't mark it used. */
- return value;
- else if (really_overloaded_fn (value))
+ else if ((TREE_CODE (value) == FUNCTION_DECL
+ && DECL_FUNCTION_MEMBER_P (value))
+ || (TREE_CODE (value) == OVERLOAD
+ && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (value))))
{
-#if 0
- tree t = get_first_fn (value);
- for (; t; t = DECL_CHAIN (t))
- {
- if (TREE_CODE (t) == TEMPLATE_DECL)
- continue;
+ tree decl;
- assemble_external (t);
- TREE_USED (t) = 1;
- }
-#endif
+ if (TREE_CODE (value) == OVERLOAD)
+ value = OVL_CURRENT (value);
+
+ if (IS_SIGNATURE (DECL_CLASS_CONTEXT (value)))
+ return value;
+
+ decl = maybe_dummy_object (DECL_CLASS_CONTEXT (value), 0);
+ value = build_component_ref (decl, name, NULL_TREE, 1);
}
+ else if (really_overloaded_fn (value))
+ ;
else if (TREE_CODE (value) == OVERLOAD)
/* not really overloaded function */
mark_used (OVL_FUNCTION (value));
@@ -1907,7 +1982,8 @@ hack_identifier (value, name)
else
mark_used (value);
- if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)
+ if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL
+ || TREE_CODE (value) == RESULT_DECL)
{
tree context = decl_function_context (value);
if (context != NULL_TREE && context != current_function_decl
@@ -1926,44 +2002,27 @@ hack_identifier (value, name)
if (DECL_LANG_SPECIFIC (value)
&& DECL_CLASS_CONTEXT (value) != current_class_type)
{
- tree path, access;
+ tree path;
register tree context
= (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value))
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
get_base_distance (context, current_class_type, 0, &path);
- if (path)
- {
- access = compute_access (path, value);
- if (access != access_public_node)
- {
- if (TREE_CODE (value) == VAR_DECL)
- error ("static member `%s' is %s",
- IDENTIFIER_POINTER (name),
- TREE_PRIVATE (value) ? "private"
- : "from a private base class");
- else
- error ("enum `%s' is from private base class",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- }
+ if (path && !enforce_access (current_class_type, value))
+ return error_mark_node;
}
}
- else if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value))
+ else if (TREE_CODE (value) == TREE_LIST
+ && TREE_TYPE (value) == error_mark_node)
{
- if (type == 0)
- {
- error ("request for member `%s' is ambiguous in multiple inheritance lattice",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
-
- return value;
+ error ("request for member `%s' is ambiguous in multiple inheritance lattice",
+ IDENTIFIER_POINTER (name));
+ print_candidates (value);
+ return error_mark_node;
}
- if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl)
+ if (! processing_template_decl)
value = convert_from_reference (value);
return value;
}
@@ -2172,42 +2231,21 @@ do_build_copy_constructor (fndecl)
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
int i;
+ /* Initialize all the base-classes. */
for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
t = TREE_CHAIN (t))
- {
- tree basetype = BINFO_TYPE (t);
- tree p = convert_to_reference
- (build_reference_type (basetype), parm,
- CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
- p = convert_from_reference (p);
-
- if (p == error_mark_node)
- cp_error ("in default copy constructor");
- else
- current_base_init_list = tree_cons (basetype,
- p, current_base_init_list);
- }
-
+ current_base_init_list
+ = tree_cons (BINFO_TYPE (t), parm, current_base_init_list);
for (i = 0; i < n_bases; ++i)
{
- tree p, basetype = TREE_VEC_ELT (binfos, i);
- if (TREE_VIA_VIRTUAL (basetype))
+ t = TREE_VEC_ELT (binfos, i);
+ if (TREE_VIA_VIRTUAL (t))
continue;
- basetype = BINFO_TYPE (basetype);
- p = convert_to_reference
- (build_reference_type (basetype), parm,
- CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE);
-
- if (p == error_mark_node)
- cp_error ("in default copy constructor");
- else
- {
- p = convert_from_reference (p);
- current_base_init_list = tree_cons (basetype,
- p, current_base_init_list);
- }
+ current_base_init_list
+ = tree_cons (BINFO_TYPE (t), parm, current_base_init_list);
}
+
for (; fields; fields = TREE_CHAIN (fields))
{
tree init, t;
@@ -2305,7 +2343,7 @@ do_build_assign_ref (fndecl)
if (TREE_CODE (field) != FIELD_DECL)
continue;
- if (TREE_READONLY (field))
+ if (CP_TYPE_CONST_P (TREE_TYPE (field)))
{
if (DECL_NAME (field))
cp_error ("non-static const member `%#D', can't use default assignment operator", field);
diff --git a/contrib/gcc/cp/new.cc b/contrib/gcc/cp/new.cc
index 28187a4..3197012 100644
--- a/contrib/gcc/cp/new.cc
+++ b/contrib/gcc/cp/new.cc
@@ -1,5 +1,5 @@
// Implementation file for the -*- C++ -*- dynamic memory management header.
-// Copyright (C) 1996 Free Software Foundation
+// Copyright (C) 1996, 1997, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/new1.cc b/contrib/gcc/cp/new1.cc
index 5bb85c9..73fbcd2 100644
--- a/contrib/gcc/cp/new1.cc
+++ b/contrib/gcc/cp/new1.cc
@@ -1,5 +1,5 @@
// Support routines for the -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997 Free Software Foundation
+// Copyright (C) 1997, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/new2.cc b/contrib/gcc/cp/new2.cc
index 0be1c0d..2833ea2 100644
--- a/contrib/gcc/cp/new2.cc
+++ b/contrib/gcc/cp/new2.cc
@@ -1,5 +1,5 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997 Free Software Foundation
+// Copyright (C) 1997, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/parse.y b/contrib/gcc/cp/parse.y
index 279cec3..7b5d3bd 100644
--- a/contrib/gcc/cp/parse.y
+++ b/contrib/gcc/cp/parse.y
@@ -1,5 +1,5 @@
/* YACC parser for C++ syntax.
- Copyright (C) 1988, 89, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 93-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -60,9 +60,10 @@ extern int end_of_file;
/* Contains the statement keyword (if/while/do) to include in an
error message if the user supplies an empty conditional expression. */
-static char *cond_stmt_keyword;
+static const char *cond_stmt_keyword;
static tree empty_parms PROTO((void));
+static int parse_decl PROTO((tree, tree, tree, int, tree *));
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
int have_extern_spec;
@@ -130,7 +131,7 @@ empty_parms ()
/* the reserved words */
/* SCO include files test "ASM", so use something else. */
%token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
-%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
+%token BREAK CONTINUE RETURN_KEYWORD GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token SIGOF
%token ATTRIBUTE EXTENSION LABEL
%token REALPART IMAGPART
@@ -203,11 +204,12 @@ empty_parms ()
%type <ttype> compstmt implicitly_scoped_stmt
%type <ttype> declarator notype_declarator after_type_declarator
+%type <ttype> notype_declarator_intern absdcl_intern
+%type <ttype> after_type_declarator_intern
%type <ttype> direct_notype_declarator direct_after_type_declarator
-
-%type <ttype> opt.component_decl_list component_decl_list
-%type <ttype> component_decl component_decl_1 components notype_components
-%type <ttype> component_declarator component_declarator0 self_reference
+%type <itype> components notype_components
+%type <ttype> component_decl component_decl_1
+%type <ttype> component_declarator component_declarator0
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist enumerator
@@ -217,7 +219,8 @@ empty_parms ()
%type <ttype> xexpr parmlist parms bad_parm
%type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl
-%type <ttype> expr_or_declarator complex_notype_declarator
+%type <ttype> expr_or_declarator expr_or_declarator_intern
+%type <ttype> complex_notype_declarator
%type <ttype> notype_unqualified_id unqualified_id qualified_id
%type <ttype> template_id do_id object_template_id notype_template_declarator
%type <ttype> overqualified_id notype_qualified_id any_id
@@ -235,11 +238,12 @@ empty_parms ()
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
%type <ttype> component_constructor_declarator
%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
-%type <itype> ctor_initializer_opt
-%type <ttype> named_class_head named_class_head_sans_basetype
-%type <ttype> named_complex_class_head_sans_basetype
+%type <itype> ctor_initializer_opt function_try_block
+%type <ttype> named_class_head_sans_basetype
+%type <ftype> class_head named_class_head
+%type <ftype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head
-%type <ttype> class_head base_class_list
+%type <ttype> base_class_list
%type <ttype> base_class_access_list
%type <ttype> base_class maybe_base_class_list base_class.1
%type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
@@ -252,6 +256,7 @@ empty_parms ()
%type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type_parm template_template_parm
%type <code> template_close_bracket
+%type <ttype> apparent_template_type
%type <ttype> template_type template_arg_list template_arg_list_opt
%type <ttype> template_arg
%type <ttype> condition xcond paren_cond_or_null
@@ -267,7 +272,7 @@ empty_parms ()
%type <ttype> named_class_head_sans_basetype_defn
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
-%type <ttype> self_template_type
+%type <ttype> self_template_type .finish_template_type
%token NSNAME
%type <ttype> NSNAME
@@ -290,9 +295,13 @@ static tree current_declspecs;
a declspec list have been updated. */
static tree prefix_attributes;
-/* When defining an aggregate, this is the most recent one being defined. */
+/* When defining an aggregate, this is the kind of the most recent one
+ being defined. (For example, this might be class_type_node.) */
static tree current_aggr;
+/* When defining an enumeration, this is the type of the enumeration. */
+static tree current_enum_type;
+
/* Tell yyparse how to print a token's value, if yydebug is set. */
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
@@ -312,7 +321,7 @@ parse_decl(declarator, specs_attrs, attributes, initialized, decl)
split_specs_attrs (specs_attrs, &current_declspecs, &prefix_attributes);
if (current_declspecs
&& TREE_CODE (current_declspecs) != TREE_LIST)
- current_declspecs = get_decl_list (current_declspecs);
+ current_declspecs = build_decl_list (NULL_TREE, current_declspecs);
if (have_extern_spec && !used_extern_spec)
{
current_declspecs = decl_tree_cons (NULL_TREE,
@@ -556,22 +565,38 @@ template_parm:
;
template_def:
- template_header
- extdef
- {
- if ($1)
- end_template_decl ();
- else
- end_specialization ();
- }
- | template_header
- error %prec EMPTY
- {
- if ($1)
- end_template_decl ();
- else
- end_specialization ();
- }
+ template_header template_extdef
+ { finish_template_decl ($1); }
+ | template_header error %prec EMPTY
+ { finish_template_decl ($1); }
+ ;
+
+template_extdef:
+ fndef eat_saved_input
+ { if (pending_inlines) do_pending_inlines (); }
+ | template_datadef
+ { if (pending_inlines) do_pending_inlines (); }
+ | template_def
+ { if (pending_inlines) do_pending_inlines (); }
+ | extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
+ { if (pending_inlines) do_pending_inlines ();
+ pop_lang_context (); }
+ | extern_lang_string .hush_warning template_datadef .warning_ok
+ { if (pending_inlines) do_pending_inlines ();
+ pop_lang_context (); }
+ | extension template_extdef
+ { pedantic = $<itype>1; }
+ ;
+
+template_datadef:
+ nomods_initdecls ';'
+ | declmods notype_initdecls ';'
+ {}
+ | typed_declspecs initdecls ';'
+ { note_list_got_semicolon ($1.t); }
+ | structsp ';'
+ { maybe_process_partial_specialization ($1.t);
+ note_got_semicolon ($1.t); }
;
datadef:
@@ -579,9 +604,7 @@ datadef:
| declmods notype_initdecls ';'
{}
| typed_declspecs initdecls ';'
- {
- note_list_got_semicolon ($1.t);
- }
+ { note_list_got_semicolon ($1.t); }
| declmods ';'
{ pedwarn ("empty declaration"); }
| explicit_instantiation ';'
@@ -619,7 +642,11 @@ fndef:
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
{ finish_function (lineno, (int)$3, 0); }
| fn.def1 maybe_return_init function_try_block
- { }
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3, nested);
+ }
| fn.def1 maybe_return_init error
{ }
;
@@ -692,8 +719,10 @@ component_constructor_declarator:
reduce/reduce conflict introduced by these rules. */
fn.def2:
declmods component_constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2);
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs);
rest_of_mdef:
if (! $$)
YYERROR1;
@@ -701,24 +730,33 @@ fn.def2:
yychar = YYLEX;
reinit_parse_for_method (yychar, $$); }
| component_constructor_declarator
- { $$ = start_method (NULL_TREE, $1); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $1, NULL_TREE);
+ goto rest_of_mdef; }
| typed_declspecs declarator
- { tree specs = strip_attrs ($1.t);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { tree specs, attrs;
+ split_specs_attrs ($1.t, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| declmods notype_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| notype_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $$, NULL_TREE);
+ goto rest_of_mdef; }
| declmods constructor_declarator
- { tree specs = strip_attrs ($1);
- $$ = start_method (specs, $2); goto rest_of_mdef; }
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ attrs = build_tree_list (attrs, NULL_TREE);
+ $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| constructor_declarator
- { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
+ { $$ = start_method (NULL_TREE, $$, NULL_TREE);
+ goto rest_of_mdef; }
;
return_id:
- RETURN IDENTIFIER
+ RETURN_KEYWORD IDENTIFIER
{
if (! current_function_parms_stored)
store_parm_decls ();
@@ -870,29 +908,35 @@ end_explicit_instantiation:
template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket
- {
- $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
- if ($$ != error_mark_node)
- $$ = TYPE_STUB_DECL ($$);
- }
+ .finish_template_type
+ { $$ = $5; }
| TYPENAME '<' template_arg_list_opt template_close_bracket
- {
- $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
- if ($$ != error_mark_node)
- $$ = TYPE_STUB_DECL ($$);
- }
+ .finish_template_type
+ { $$ = $5; }
| self_template_type
;
+apparent_template_type:
+ template_type
+ | identifier '<' template_arg_list_opt '>'
+ .finish_template_type
+ { $$ = $5; }
+
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
- {
- $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
- if ($$ != error_mark_node)
- $$ = TYPE_STUB_DECL ($$);
- }
+ .finish_template_type
+ { $$ = $5; }
;
+.finish_template_type:
+ {
+ if (yychar == YYEMPTY)
+ yychar = YYLEX;
+
+ $$ = finish_template_type ($<ttype>-3, $<ttype>-1,
+ yychar == SCOPE);
+ }
+
template_close_bracket:
'>'
| RSHIFT
@@ -1056,7 +1100,8 @@ unary_expr:
| SIZEOF unary_expr %prec UNARY
{ $$ = expr_sizeof ($2); }
| SIZEOF '(' type_id ')' %prec HYPERUNARY
- { $$ = c_sizeof (groktypename ($3.t)); }
+ { $$ = c_sizeof (groktypename ($3.t));
+ check_for_new_type ("sizeof", $3); }
| ALIGNOF unary_expr %prec UNARY
{ $$ = grok_alignof ($2); }
| ALIGNOF '(' type_id ')' %prec HYPERUNARY
@@ -1265,6 +1310,8 @@ expr_no_commas:
notype_unqualified_id:
'~' see_typename identifier
{ $$ = build_parse_node (BIT_NOT_EXPR, $3); }
+ | '~' see_typename template_type
+ { $$ = build_parse_node (BIT_NOT_EXPR, $3); }
| template_id
| operator_name
| IDENTIFIER
@@ -1273,7 +1320,16 @@ notype_unqualified_id:
;
do_id:
- { $$ = do_identifier ($<ttype>-1, 1, NULL_TREE); }
+ {
+ /* If lastiddecl is a TREE_LIST, it's a baselink, which
+ means that we're in an expression like S::f<int>, so
+ don't do_identifier; we only do that for unqualified
+ identifiers. */
+ if (lastiddecl && TREE_CODE (lastiddecl) != TREE_LIST)
+ $$ = do_identifier ($<ttype>-1, 1, NULL_TREE);
+ else
+ $$ = $<ttype>-1;
+ }
template_id:
PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
@@ -1298,13 +1354,23 @@ unqualified_id:
| SELFNAME
;
+expr_or_declarator_intern:
+ expr_or_declarator
+ | attributes expr_or_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
expr_or_declarator:
notype_unqualified_id
- | '*' expr_or_declarator %prec UNARY
+ | '*' expr_or_declarator_intern %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); }
- | '&' expr_or_declarator %prec UNARY
+ | '&' expr_or_declarator_intern %prec UNARY
{ $$ = build_parse_node (ADDR_EXPR, $2); }
- | '(' expr_or_declarator ')'
+ | '(' expr_or_declarator_intern ')'
{ $$ = $2; }
;
@@ -1321,8 +1387,8 @@ direct_notype_declarator:
to the Koenig lookup shift in primary, below. I hate yacc. */
| notype_unqualified_id %prec '('
| notype_template_declarator
- | '(' expr_or_declarator ')'
- { $$ = finish_decl_parsing ($2); }
+ | '(' expr_or_declarator_intern ')'
+ { $$ = finish_decl_parsing ($2); }
;
primary:
@@ -1340,18 +1406,25 @@ primary:
if (processing_template_decl)
push_obstacks (&permanent_obstack, &permanent_obstack);
$$ = combine_strings ($$);
+ /* combine_strings doesn't set up TYPE_MAIN_VARIANT of
+ a const array the way we want, so fix it. */
+ if (flag_const_strings)
+ TREE_TYPE ($$) = build_cplus_array_type
+ (TREE_TYPE (TREE_TYPE ($$)),
+ TYPE_DOMAIN (TREE_TYPE ($$)));
if (processing_template_decl)
pop_obstacks ();
}
| '(' expr ')'
{ $$ = finish_parenthesized_expr ($2); }
- | '(' expr_or_declarator ')'
+ | '(' expr_or_declarator_intern ')'
{ $2 = reparse_decl_as_expr (NULL_TREE, $2);
$$ = finish_parenthesized_expr ($2); }
| '(' error ')'
{ $$ = error_mark_node; }
| '('
- { if (current_function_decl == 0)
+ { tree scope = current_scope ();
+ if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
{
error ("braced-group within expression allowed only inside a function");
YYERROR;
@@ -1384,47 +1457,20 @@ primary:
{ $$ = finish_this_expr (); }
| CV_QUALIFIER '(' nonnull_exprlist ')'
{
- tree type = NULL_TREE;
- tree id = $$;
+ /* This is a C cast in C++'s `functional' notation
+ using the "implicit int" extension so that:
+ `const (3)' is equivalent to `const int (3)'. */
+ tree type;
- /* This is a C cast in C++'s `functional' notation. */
if ($3 == error_mark_node)
{
$$ = error_mark_node;
break;
}
-#if 0
- if ($3 == NULL_TREE)
- {
- error ("cannot cast null list to type `%s'",
- IDENTIFIER_POINTER (TYPE_NAME (id)));
- $$ = error_mark_node;
- break;
- }
-#endif
-#if 0
- /* type is not set! (mrs) */
- if (type == error_mark_node)
- $$ = error_mark_node;
- else
-#endif
- {
- if (id == ridpointers[(int) RID_CONST])
- type = build_type_variant (integer_type_node, 1, 0);
- else if (id == ridpointers[(int) RID_VOLATILE])
- type = build_type_variant (integer_type_node, 0, 1);
-#if 0
- /* should not be able to get here (mrs) */
- else if (id == ridpointers[(int) RID_FRIEND])
- {
- error ("cannot cast expression to `friend' type");
- $$ = error_mark_node;
- break;
- }
-#endif
- else my_friendly_abort (79);
- $$ = build_c_cast (type, build_compound_expr ($3));
- }
+
+ type = cp_build_qualified_type (integer_type_node,
+ cp_type_qual_from_rid ($1));
+ $$ = build_c_cast (type, build_compound_expr ($3));
}
| functional_cast
| DYNAMIC_CAST '<' type_id '>' '(' expr ')'
@@ -1464,9 +1510,9 @@ primary:
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
- { $$ = finish_globally_qualified_member_call_expr ($1, $3); }
+ { $$ = finish_qualified_call_expr ($1, $3); }
| overqualified_id LEFT_RIGHT
- { $$ = finish_globally_qualified_member_call_expr ($1, NULL_TREE); }
+ { $$ = finish_qualified_call_expr ($1, NULL_TREE); }
| object object_template_id %prec UNARY
{
$$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
@@ -1642,7 +1688,8 @@ type_id:
{ $$.t = build_decl_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec absdcl
- { $$.t = build_decl_list (get_decl_list ($1.t), $2);
+ { $$.t = build_decl_list (build_decl_list (NULL_TREE, $1.t),
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_typespecs %prec EMPTY
{ $$.t = build_decl_list ($1.t, NULL_TREE);
@@ -1708,24 +1755,33 @@ reserved_declspecs:
to redeclare a typedef-name.
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
+/* We use hash_tree_cons for lists of typeless declspecs so that they end
+ up on a persistent obstack. Otherwise, they could appear at the
+ beginning of something like
+
+ static const struct { int foo () { } } b;
+
+ and would be discarded after we finish compiling foo. We don't need to
+ worry once we see a type. */
+
declmods:
nonempty_cv_qualifiers %prec EMPTY
{ $$ = $1.t; TREE_STATIC ($$) = 1; }
| SCSPEC
- { $$ = IDENTIFIER_AS_LIST ($$); }
+ { $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
| declmods CV_QUALIFIER
- { $$ = decl_tree_cons (NULL_TREE, $2, $$);
+ { $$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = 1; }
| declmods SCSPEC
{ if (extra_warnings && TREE_STATIC ($$))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
- $$ = decl_tree_cons (NULL_TREE, $2, $$);
+ $$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = TREE_STATIC ($1); }
| declmods attributes
- { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
- | attributes
- { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
+ { $$ = hash_tree_cons ($2, NULL_TREE, $1); }
+ | attributes %prec EMPTY
+ { $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
;
/* Used instead of declspecs where storage classes are not allowed
@@ -1736,7 +1792,7 @@ declmods:
typed_typespecs:
typespec %prec EMPTY
- { $$.t = get_decl_list ($1.t);
+ { $$.t = build_decl_list (NULL_TREE, $1.t);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t);
@@ -1767,7 +1823,7 @@ typespec:
| complete_type_name
{ $$.t = $1; $$.new_type_flag = 0; }
| TYPEOF '(' expr ')'
- { $$.t = TREE_TYPE ($3);
+ { $$.t = finish_typeof ($3);
$$.new_type_flag = 0; }
| TYPEOF '(' type_id ')'
{ $$.t = groktypename ($3.t);
@@ -1817,16 +1873,19 @@ typespecqual_reserved:
initdecls:
initdcl0
| initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
notype_initdecls:
notype_initdcl0
| notype_initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
nomods_initdecls:
nomods_initdcl0
| nomods_initdecls ',' initdcl
+ { check_multiple_declarators (); }
;
maybeasm:
@@ -1995,7 +2054,7 @@ initlist:
fn.defpen:
PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($1),
- NULL_TREE, 1);
+ NULL_TREE, 2);
reinit_parse_for_function (); }
pending_inline:
@@ -2003,11 +2062,16 @@ pending_inline:
{
int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE);
- finish_function (lineno, (int)$3, nested);
+ finish_function (lineno, (int)$3 | 2, nested);
process_next_inline ($1);
}
| fn.defpen maybe_return_init function_try_block
- { process_next_inline ($1); }
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3 | 2, nested);
+ process_next_inline ($1);
+ }
| fn.defpen maybe_return_init error
{ process_next_inline ($1); }
;
@@ -2036,39 +2100,48 @@ pending_defargs:
structsp:
ENUM identifier '{'
{ $<itype>3 = suspend_momentary ();
- $<ttype>$ = start_enum ($2); }
+ $<ttype>$ = current_enum_type;
+ current_enum_type = start_enum ($2); }
enumlist maybecomma_warn '}'
- { $$.t = finish_enum ($<ttype>4, $5);
+ { TYPE_VALUES (current_enum_type) = $5;
+ $$.t = finish_enum (current_enum_type);
$$.new_type_flag = 1;
+ current_enum_type = $<ttype>4;
resume_momentary ((int) $<itype>3);
- check_for_missing_semicolon ($<ttype>4); }
+ check_for_missing_semicolon ($$.t); }
| ENUM identifier '{' '}'
- { $$.t = finish_enum (start_enum ($2), NULL_TREE);
+ { $$.t = finish_enum (start_enum ($2));
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM '{'
{ $<itype>2 = suspend_momentary ();
- $<ttype>$ = start_enum (make_anon_name ()); }
+ $<ttype>$ = current_enum_type;
+ current_enum_type = start_enum (make_anon_name ()); }
enumlist maybecomma_warn '}'
- { $$.t = finish_enum ($<ttype>3, $4);
+ { TYPE_VALUES (current_enum_type) = $4;
+ $$.t = finish_enum (current_enum_type);
+ $$.new_type_flag = 1;
+ current_enum_type = $<ttype>3;
resume_momentary ((int) $<itype>1);
- check_for_missing_semicolon ($<ttype>3);
- $$.new_type_flag = 1; }
+ check_for_missing_semicolon ($$.t); }
| ENUM '{' '}'
- { $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE);
+ { $$.t = finish_enum (start_enum (make_anon_name()));
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
- { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1);
+ { $$.t = xref_tag (enum_type_node, $2, 1);
$$.new_type_flag = 0; }
| ENUM complex_type_name
- { $$.t = xref_tag (enum_type_node, $2, NULL_TREE, 1);
+ { $$.t = xref_tag (enum_type_node, $2, 1);
$$.new_type_flag = 0; }
| TYPENAME_KEYWORD typename_sub
{ $$.t = $2;
- $$.new_type_flag = 0; }
+ $$.new_type_flag = 0;
+ if (!processing_template_decl)
+ cp_pedwarn ("using `typename' outside of template"); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
- | class_head left_curly
+ | class_head '{'
+ { $1.t = begin_class_definition ($1.t); }
opt.component_decl_list '}' maybe_attribute
{
int semi;
@@ -2077,25 +2150,32 @@ structsp:
yychar = YYLEX;
semi = yychar == ';';
- $<ttype>$ = finish_class_definition ($1, $3, $5, semi);
+ $<ttype>$ = finish_class_definition ($1.t, $6, semi,
+ $1.new_type_flag);
}
pending_defargs
- { finish_default_args (); }
+ {
+ begin_inline_definitions ();
+ }
pending_inlines
- { $$.t = $<ttype>6;
+ {
+ finish_inline_definitions ();
+ $$.t = $<ttype>7;
$$.new_type_flag = 1;
- begin_inline_definitions (); }
+ }
| class_head %prec EMPTY
{
+ if ($1.new_type_flag)
+ pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL ($1.t)));
$$.new_type_flag = 0;
- if (TYPE_BINFO ($1) == NULL_TREE)
+ if (TYPE_BINFO ($1.t) == NULL_TREE)
{
- cp_error ("%T is not a class type", $1);
+ cp_error ("%T is not a class type", $1.t);
$$.t = error_mark_node;
}
else
{
- $$.t = $1;
+ $$.t = $1.t;
/* struct B: public A; is not accepted by the WP grammar. */
if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
&& ! TYPE_BEING_DEFINED ($$.t))
@@ -2133,7 +2213,10 @@ aggr:
named_class_head_sans_basetype:
aggr identifier
- { current_aggr = $$; $$ = $2; }
+ {
+ current_aggr = $1;
+ $$ = $2;
+ }
;
named_class_head_sans_basetype_defn:
@@ -2149,75 +2232,98 @@ named_complex_class_head_sans_basetype:
aggr nested_name_specifier identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, $2, $3);
+ $$.t = handle_class_head ($1, $2, $3);
+ $$.new_type_flag = 1;
}
| aggr global_scope nested_name_specifier identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, $3, $4);
+ $$.t = handle_class_head ($1, $3, $4);
+ $$.new_type_flag = 1;
}
| aggr global_scope identifier
{
current_aggr = $1;
- $$ = handle_class_head ($1, NULL_TREE, $3);
+ $$.t = handle_class_head ($1, NULL_TREE, $3);
+ $$.new_type_flag = 1;
+ }
+ | aggr apparent_template_type
+ {
+ current_aggr = $1;
+ $$.t = $2;
+ $$.new_type_flag = 0;
+ }
+ | aggr nested_name_specifier apparent_template_type
+ {
+ current_aggr = $1;
+ $$.t = $3;
+ if (CP_DECL_CONTEXT ($$.t))
+ push_scope (CP_DECL_CONTEXT ($$.t));
+ $$.new_type_flag = 1;
}
- | aggr template_type
- { current_aggr = $$; $$ = $2; }
- | aggr nested_name_specifier template_type
- { current_aggr = $$; $$ = $3; }
- ;
-
-do_xref_defn:
- /* empty */ %prec EMPTY
- { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
;
named_class_head:
named_class_head_sans_basetype %prec EMPTY
- { $$ = xref_tag (current_aggr, $1, NULL_TREE, 1); }
- | named_class_head_sans_basetype_defn do_xref_defn
+ {
+ $$.t = xref_tag (current_aggr, $1, 1);
+ $$.new_type_flag = 0;
+ }
+ | named_class_head_sans_basetype_defn
+ { $<ttype>$ = xref_tag (current_aggr, $1, 0); }
+ /* Class name is unqualified, so we look for base classes
+ in the current scope. */
maybe_base_class_list %prec EMPTY
{
- $$ = $<ttype>2;
+ $$.t = $<ttype>2;
+ $$.new_type_flag = 0;
if ($3)
xref_basetypes (current_aggr, $1, $<ttype>2, $3);
}
- | named_complex_class_head_sans_basetype maybe_base_class_list
+ | named_complex_class_head_sans_basetype
+ maybe_base_class_list
{
- $$ = TREE_TYPE ($1);
- if (TREE_INT_CST_LOW (current_aggr) == union_type
- && TREE_CODE ($$) != UNION_TYPE)
- cp_pedwarn ("`union' tag used in declaring `%#T'", $$);
- else if (TREE_CODE ($$) == UNION_TYPE
- && TREE_INT_CST_LOW (current_aggr) != union_type)
- cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
- if ($2)
+ if ($1.t != error_mark_node)
{
- if (IS_AGGR_TYPE ($$) && CLASSTYPE_USE_TEMPLATE ($$))
- {
- if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$)
- && TYPE_SIZE ($$) == NULL_TREE)
- {
- SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
- if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL ($$));
- }
- else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$))
- cp_error ("specialization after instantiation of `%T'", $$);
+ $$.t = TREE_TYPE ($1.t);
+ $$.new_type_flag = $1.new_type_flag;
+ if (current_aggr == union_type_node
+ && TREE_CODE ($$.t) != UNION_TYPE)
+ cp_pedwarn ("`union' tag used in declaring `%#T'",
+ $$.t);
+ else if (TREE_CODE ($$.t) == UNION_TYPE
+ && current_aggr != union_type_node)
+ cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
+ else if (TREE_CODE ($$.t) == RECORD_TYPE)
+ /* We might be specializing a template with a different
+ class-key; deal. */
+ CLASSTYPE_DECLARED_CLASS ($$.t)
+ = (current_aggr == class_type_node);
+ if ($2)
+ {
+ maybe_process_partial_specialization ($$.t);
+ xref_basetypes (current_aggr, $1.t, $$.t, $2);
}
- xref_basetypes (current_aggr, $1, $$, $2);
}
}
;
unnamed_class_head:
aggr '{'
- { $$ = xref_tag ($$, make_anon_name (), NULL_TREE, 0);
+ { $$ = xref_tag ($$, make_anon_name (), 0);
yyungetc ('{', 1); }
;
+/* The tree output of this nonterminal a declarationf or the type
+ named. If NEW_TYPE_FLAG is set, then the name used in this
+ class-head was explicitly qualified, e.g.: `struct X::Y'. We have
+ already called push_scope for X. */
class_head:
unnamed_class_head
+ {
+ $$.t = $1;
+ $$.new_type_flag = 0;
+ }
| named_class_head
;
@@ -2238,76 +2344,18 @@ base_class_list:
base_class:
base_class.1
- {
- tree type;
- if ($1 == NULL_TREE)
- {
- error ("invalid base class");
- type = error_mark_node;
- }
- else
- type = TREE_TYPE ($1);
- if (! is_aggr_type (type, 1))
- $$ = NULL_TREE;
- else if (current_aggr == signature_type_node
- && (! type) && (! IS_SIGNATURE (type)))
- {
- error ("class name not allowed as base signature");
- $$ = NULL_TREE;
- }
- else if (current_aggr == signature_type_node)
- {
- sorry ("signature inheritance, base type `%s' ignored",
- IDENTIFIER_POINTER ($$));
- $$ = build_tree_list (access_public_node, type);
- }
- else if (type && IS_SIGNATURE (type))
- {
- error ("signature name not allowed as base class");
- $$ = NULL_TREE;
- }
- else
- $$ = build_tree_list (access_default_node, type);
- }
+ { $$ = finish_base_specifier (access_default_node, $1,
+ current_aggr
+ == signature_type_node); }
| base_class_access_list see_typename base_class.1
- {
- tree type;
- if ($3 == NULL_TREE)
- {
- error ("invalid base class");
- type = error_mark_node;
- }
- else
- type = TREE_TYPE ($3);
- if (current_aggr == signature_type_node)
- error ("access and source specifiers not allowed in signature");
- if (! is_aggr_type (type, 1))
- $$ = NULL_TREE;
- else if (current_aggr == signature_type_node
- && (! type) && (! IS_SIGNATURE (type)))
- {
- error ("class name not allowed as base signature");
- $$ = NULL_TREE;
- }
- else if (current_aggr == signature_type_node)
- {
- sorry ("signature inheritance, base type `%s' ignored",
- IDENTIFIER_POINTER ($$));
- $$ = build_tree_list (access_public_node, type);
- }
- else if (type && IS_SIGNATURE (type))
- {
- error ("signature name not allowed as base class");
- $$ = NULL_TREE;
- }
- else
- $$ = build_tree_list ($$, type);
- }
+ { $$ = finish_base_specifier ($1, $3,
+ current_aggr
+ == signature_type_node); }
;
base_class.1:
typename_sub
- { $$ = TYPE_MAIN_DECL ($1); }
+ { if ($$ != error_mark_node) $$ = TYPE_MAIN_DECL ($1); }
| nonnested_type
| SIGOF '(' expr ')'
{
@@ -2384,71 +2432,40 @@ base_class_access_list:
}
;
-left_curly:
- '{'
- { $<ttype>0 = begin_class_definition ($<ttype>0); }
- ;
-
-self_reference:
- /* empty */
- {
- $$ = build_self_reference ();
- }
- ;
-
opt.component_decl_list:
- self_reference
- { if ($$) $$ = build_tree_list (access_public_node, $$); }
- | self_reference component_decl_list
- {
- if (current_aggr == signature_type_node)
- $$ = build_tree_list (access_public_node, $2);
- else
- $$ = build_tree_list (access_default_node, $2);
- if ($1) $$ = tree_cons (access_public_node, $1, $$);
- }
- | opt.component_decl_list VISSPEC ':' component_decl_list
- {
- tree visspec = $2;
+ | component_decl_list
+ | opt.component_decl_list access_specifier component_decl_list
+ | opt.component_decl_list access_specifier
+ ;
+access_specifier:
+ VISSPEC ':'
+ {
if (current_aggr == signature_type_node)
{
error ("access specifier not allowed in signature");
- visspec = access_public_node;
+ $1 = access_public_node;
}
- $$ = chainon ($$, build_tree_list (visspec, $4));
- }
- | opt.component_decl_list VISSPEC ':'
- {
- if (current_aggr == signature_type_node)
- error ("access specifier not allowed in signature");
- }
+
+ current_access_specifier = $1;
+ }
;
/* Note: we no longer warn about the semicolon after a component_decl_list.
ARM $9.2 says that the semicolon is optional, and therefore allowed. */
component_decl_list:
component_decl
- { if ($$ == void_type_node) $$ = NULL_TREE;
+ {
+ finish_member_declaration ($1);
}
| component_decl_list component_decl
- { /* In pushdecl, we created a reverse list of names
- in this binding level. Make sure that the chain
- of what we're trying to add isn't the item itself
- (which can happen with what pushdecl's doing). */
- if ($2 != NULL_TREE && $2 != void_type_node)
- {
- if (TREE_CHAIN ($2) != $$)
- $$ = chainon ($$, $2);
- else
- $$ = $2;
- }
+ {
+ finish_member_declaration ($2);
}
;
component_decl:
component_decl_1 ';'
- { }
| component_decl_1 '}'
{ error ("missing ';' before right brace");
yyungetc ('}', 0); }
@@ -2458,7 +2475,7 @@ component_decl:
{ $$ = finish_method ($$); }
| fn.def2 TRY /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 RETURN /* base_init compstmt */
+ | fn.def2 RETURN_KEYWORD /* base_init compstmt */
{ $$ = finish_method ($$); }
| fn.def2 '{' /* nodecls compstmt */
{ $$ = finish_method ($$); }
@@ -2468,9 +2485,20 @@ component_decl:
{ $$ = $2;
pedantic = $<itype>1; }
| template_header component_decl
- { $$ = finish_member_template_decl ($1, $2); }
+ {
+ if ($2)
+ $$ = finish_member_template_decl ($2);
+ else
+ /* The component was already processed. */
+ $$ = NULL_TREE;
+
+ finish_template_decl ($1);
+ }
| template_header typed_declspecs ';'
- { $$ = finish_member_class_template ($1, $2.t); }
+ {
+ $$ = finish_member_class_template ($2.t);
+ finish_template_decl ($1);
+ }
;
component_decl_1:
@@ -2478,9 +2506,32 @@ component_decl_1:
speed; we need to call grok_x_components for enums, so the
speedup would be insignificant. */
typed_declspecs components
- { $$ = grok_x_components ($1.t, $2); }
+ {
+ /* Most of the productions for component_decl only
+ allow the creation of one new member, so we call
+ finish_member_declaration in component_decl_list.
+ For this rule and the next, however, there can be
+ more than one member, e.g.:
+
+ int i, j;
+
+ and we need the first member to be fully
+ registered before the second is processed.
+ Therefore, the rules for components take care of
+ this processing. To avoid registering the
+ components more than once, we send NULL_TREE up
+ here; that lets finish_member_declaration know
+ that there is nothing to do. */
+ if (!$2)
+ grok_x_components ($1.t);
+ $$ = NULL_TREE;
+ }
| declmods notype_components
- { $$ = grok_x_components ($1, $2); }
+ {
+ if (!$2)
+ grok_x_components ($1);
+ $$ = NULL_TREE;
+ }
| notype_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2,
build_tree_list ($3, NULL_TREE)); }
@@ -2515,31 +2566,41 @@ component_decl_1:
/* ??? Huh? ^^^ */
components:
/* empty: possibly anonymous */
- { $$ = NULL_TREE; }
+ { $$ = 0; }
| component_declarator0
+ {
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $1 = finish_member_template_decl ($1);
+ finish_member_declaration ($1);
+ $$ = 1;
+ }
| components ',' component_declarator
- {
- /* In this context, void_type_node encodes
- friends. They have been recorded elsewhere. */
- if ($$ == void_type_node)
- $$ = $3;
- else
- $$ = chainon ($$, $3);
+ {
+ check_multiple_declarators ();
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $3 = finish_member_template_decl ($3);
+ finish_member_declaration ($3);
+ $$ = 2;
}
;
notype_components:
/* empty: possibly anonymous */
- { $$ = NULL_TREE; }
+ { $$ = 0; }
| notype_component_declarator0
+ {
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $1 = finish_member_template_decl ($1);
+ finish_member_declaration ($1);
+ $$ = 1;
+ }
| notype_components ',' notype_component_declarator
- {
- /* In this context, void_type_node encodes
- friends. They have been recorded elsewhere. */
- if ($$ == void_type_node)
- $$ = $3;
- else
- $$ = chainon ($$, $3);
+ {
+ check_multiple_declarators ();
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+ $3 = finish_member_template_decl ($3);
+ finish_member_declaration ($3);
+ $$ = 2;
}
;
@@ -2628,9 +2689,9 @@ enumlist:
enumerator:
identifier
- { $$ = build_enumerator ($$, NULL_TREE); }
+ { $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
| identifier '=' expr_no_commas
- { $$ = build_enumerator ($$, $3); }
+ { $$ = build_enumerator ($$, $3, current_enum_type); }
;
/* ANSI new-type-id (5.3.4) */
@@ -2664,10 +2725,10 @@ cv_qualifiers:
nonempty_cv_qualifiers:
CV_QUALIFIER
- { $$.t = IDENTIFIER_AS_LIST ($1);
+ { $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers CV_QUALIFIER
- { $$.t = decl_tree_cons (NULL_TREE, $2, $1.t);
+ { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
$$.new_type_flag = $1.new_type_flag; }
;
@@ -2697,37 +2758,57 @@ maybe_parmlist:
;
/* A declarator that is allowed only after an explicit typespec. */
+
+after_type_declarator_intern:
+ after_type_declarator
+ | attributes after_type_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
/* may all be followed by prec '.' */
after_type_declarator:
- '*' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers after_type_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers after_type_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
- | '*' after_type_declarator %prec UNARY
+ | '*' after_type_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' after_type_declarator %prec UNARY
+ | '&' after_type_declarator_intern %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers after_type_declarator
+ | ptr_to_mem cv_qualifiers after_type_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
| direct_after_type_declarator
;
+direct_after_type_declarator:
+ direct_after_type_declarator maybe_parmlist cv_qualifiers exception_specification_opt %prec '.'
+ { $$ = make_call_declarator ($$, $2, $3, $4); }
+ | direct_after_type_declarator '[' nonmomentary_expr ']'
+ { $$ = build_parse_node (ARRAY_REF, $$, $3); }
+ | direct_after_type_declarator '[' ']'
+ { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
+ | '(' after_type_declarator_intern ')'
+ { $$ = $2; }
+ | nested_name_specifier type_name %prec EMPTY
+ { push_nested_class ($1, 3);
+ $$ = build_parse_node (SCOPE_REF, $$, $2);
+ TREE_COMPLEXITY ($$) = current_class_depth; }
+ | type_name %prec EMPTY
+ ;
+
nonnested_type:
type_name %prec EMPTY
{
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
$$ = lookup_name ($1, 1);
- if (current_class_type
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE ($1))
- {
- /* Remember that this name has been used in the class
- definition, as per [class.scope0] */
- pushdecl_class_level ($$);
- }
+ maybe_note_name_used_in_class ($1, $$);
}
else
$$ = $1;
@@ -2754,35 +2835,29 @@ nested_type:
{ $$ = get_type_decl ($2); }
;
-direct_after_type_declarator:
- direct_after_type_declarator maybe_parmlist cv_qualifiers exception_specification_opt %prec '.'
- { $$ = make_call_declarator ($$, $2, $3, $4); }
- | direct_after_type_declarator '[' nonmomentary_expr ']'
- { $$ = build_parse_node (ARRAY_REF, $$, $3); }
- | direct_after_type_declarator '[' ']'
- { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
- | '(' after_type_declarator ')'
- { $$ = $2; }
- | nested_name_specifier type_name %prec EMPTY
- { push_nested_class ($1, 3);
- $$ = build_parse_node (SCOPE_REF, $$, $2);
- TREE_COMPLEXITY ($$) = current_class_depth; }
- | type_name %prec EMPTY
- ;
-
/* A declarator allowed whether or not there has been
an explicit typespec. These cannot redeclare a typedef-name. */
+notype_declarator_intern:
+ notype_declarator
+ | attributes notype_declarator
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
notype_declarator:
- '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
- | '*' notype_declarator %prec UNARY
+ | '*' notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
- | '&' notype_declarator %prec UNARY
+ | '&' notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -2790,15 +2865,15 @@ notype_declarator:
;
complex_notype_declarator:
- '*' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ '*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '&' nonempty_cv_qualifiers notype_declarator %prec UNARY
+ | '&' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_reference_declarator ($2.t, $3); }
| '*' complex_notype_declarator %prec UNARY
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '&' complex_notype_declarator %prec UNARY
{ $$ = make_reference_declarator (NULL_TREE, $2); }
- | ptr_to_mem cv_qualifiers notype_declarator
+ | ptr_to_mem cv_qualifiers notype_declarator_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -2815,25 +2890,11 @@ complex_direct_notype_declarator:
| direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| notype_qualified_id
- { if (TREE_CODE (OP0 ($1)) == NAMESPACE_DECL)
- {
- push_decl_namespace (OP0 ($1));
- TREE_COMPLEXITY ($1) = -1;
- }
- else if (OP0 ($1) != current_class_type)
- {
- push_nested_class (OP0 ($1), 3);
- TREE_COMPLEXITY ($1) = current_class_depth;
- }
- }
+ { enter_scope_of ($1); }
| nested_name_specifier notype_template_declarator
{ got_scope = NULL_TREE;
$$ = build_parse_node (SCOPE_REF, $1, $2);
- if ($1 != current_class_type)
- {
- push_nested_class ($1, 3);
- TREE_COMPLEXITY ($$) = current_class_depth;
- }
+ enter_scope_of ($$);
}
;
@@ -2864,12 +2925,11 @@ overqualified_id:
functional_cast:
typespec '(' nonnull_exprlist ')'
{ $$ = build_functional_cast ($1.t, $3); }
- | typespec '(' expr_or_declarator ')'
+ | typespec '(' expr_or_declarator_intern ')'
{ $$ = reparse_decl_as_expr ($1.t, $3); }
| typespec fcast_or_absdcl %prec EMPTY
{ $$ = reparse_absdcl_as_expr ($1.t, $2); }
;
-
type_name:
TYPENAME
| SELFNAME
@@ -2892,14 +2952,10 @@ nested_name_specifier_1:
if (TREE_CODE ($1) == IDENTIFIER_NODE)
{
$$ = lastiddecl;
- /* Remember that this name has been used in the class
- definition, as per [class.scope0] */
- if (current_class_type
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE ($1))
- pushdecl_class_level ($$);
+ maybe_note_name_used_in_class ($1, $$);
}
- got_scope = $$ = TYPE_MAIN_VARIANT (TREE_TYPE ($$));
+ got_scope = $$ =
+ complete_type (TYPE_MAIN_VARIANT (TREE_TYPE ($$)));
}
| SELFNAME SCOPE
{
@@ -3073,19 +3129,29 @@ direct_new_declarator:
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
;
+absdcl_intern:
+ absdcl
+ | attributes absdcl
+ {
+ /* Provide support for '(' attributes '*' declarator ')'
+ etc */
+ $$ = decl_tree_cons ($1, $2, NULL_TREE);
+ }
+ ;
+
/* ANSI abstract-declarator (8.1) */
absdcl:
- '*' nonempty_cv_qualifiers absdcl
+ '*' nonempty_cv_qualifiers absdcl_intern
{ $$ = make_pointer_declarator ($2.t, $3); }
- | '*' absdcl
+ | '*' absdcl_intern
{ $$ = make_pointer_declarator (NULL_TREE, $2); }
| '*' nonempty_cv_qualifiers %prec EMPTY
{ $$ = make_pointer_declarator ($2.t, NULL_TREE); }
| '*' %prec EMPTY
{ $$ = make_pointer_declarator (NULL_TREE, NULL_TREE); }
- | '&' nonempty_cv_qualifiers absdcl
+ | '&' nonempty_cv_qualifiers absdcl_intern
{ $$ = make_reference_declarator ($2.t, $3); }
- | '&' absdcl
+ | '&' absdcl_intern
{ $$ = make_reference_declarator (NULL_TREE, $2); }
| '&' nonempty_cv_qualifiers %prec EMPTY
{ $$ = make_reference_declarator ($2.t, NULL_TREE); }
@@ -3095,7 +3161,7 @@ absdcl:
{ tree arg = make_pointer_declarator ($2, NULL_TREE);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
- | ptr_to_mem cv_qualifiers absdcl
+ | ptr_to_mem cv_qualifiers absdcl_intern
{ tree arg = make_pointer_declarator ($2, $3);
$$ = build_parse_node (SCOPE_REF, $1, arg);
}
@@ -3104,7 +3170,7 @@ absdcl:
/* ANSI direct-abstract-declarator (8.1) */
direct_abstract_declarator:
- '(' absdcl ')'
+ '(' absdcl_intern ')'
{ $$ = $2; }
/* `(typedef)1' is `int'. */
| PAREN_STAR_PAREN
@@ -3270,9 +3336,9 @@ simple_stmt:
{ finish_break_stmt (); }
| CONTINUE ';'
{ finish_continue_stmt (); }
- | RETURN ';'
+ | RETURN_KEYWORD ';'
{ finish_return_stmt (NULL_TREE); }
- | RETURN expr ';'
+ | RETURN_KEYWORD expr ';'
{ finish_return_stmt ($2); }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
{
@@ -3324,14 +3390,13 @@ function_try_block:
}
ctor_initializer_opt compstmt
{
+ end_protect_partials ();
expand_start_all_catch ();
}
handler_seq
{
- int nested = (hack_decl_function_context
- (current_function_decl) != NULL_TREE);
expand_end_all_catch ();
- finish_function (lineno, (int)$3, nested);
+ $$ = $3;
}
;
@@ -3561,7 +3626,8 @@ named_parm:
{ $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec declarator
- { $$.t = build_tree_list (get_decl_list ($1.t), $2);
+ { $$.t = build_tree_list (build_decl_list (NULL_TREE, $1.t),
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 absdcl
{ tree specs = strip_attrs ($1.t);
diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c
index 556b761..47fa99a 100644
--- a/contrib/gcc/cp/pt.c
+++ b/contrib/gcc/cp/pt.c
@@ -1,5 +1,5 @@
/* Handle parameterized types (templates) for GNU C++.
- Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-97, 1998, 1999 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
@@ -39,6 +39,8 @@ Boston, MA 02111-1307, USA. */
#include "defaults.h"
#include "except.h"
#include "toplev.h"
+#include "rtl.h"
+#include "varray.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
@@ -48,15 +50,21 @@ extern struct obstack permanent_obstack;
extern int lineno;
extern char *input_filename;
-struct pending_inline *pending_template_expansions;
tree current_template_parms;
HOST_WIDE_INT processing_template_decl;
-tree pending_templates;
+/* The PENDING_TEMPLATES is a TREE_LIST of templates whose
+ instantiations have been deferred, either because their definitions
+ were not yet available, or because we were putting off doing the
+ work. The TREE_PURPOSE of each entry is a SRCLOC indicating where
+ the instantiate request occurred; the TREE_VALUE is a either a DECL
+ (for a function or static data member), or a TYPE (for a class)
+ indicating what we are hoping to instantiate. */
+static tree pending_templates;
static tree *template_tail = &pending_templates;
-tree maybe_templates;
+static tree maybe_templates;
static tree *maybe_template_tail = &maybe_templates;
int minimal_parse_mode;
@@ -67,6 +75,8 @@ int processing_template_parmlist;
static int template_header_count;
static tree saved_trees;
+static varray_type inline_parm_levels;
+static size_t inline_parm_levels_used;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -75,35 +85,47 @@ static tree saved_trees;
#define UNIFY_ALLOW_MORE_CV_QUAL 1
#define UNIFY_ALLOW_LESS_CV_QUAL 2
#define UNIFY_ALLOW_DERIVED 4
-
-static int unify PROTO((tree, tree, tree, tree, int, int*));
+#define UNIFY_ALLOW_INTEGER 8
+
+#define GTB_VIA_VIRTUAL 1 /* The base class we are examining is
+ virtual, or a base class of a virtual
+ base. */
+#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
+ type with the desired type. */
+
+static int resolve_overloaded_unification PROTO((tree, tree, tree, tree,
+ unification_kind_t, int));
+static int try_one_overload PROTO((tree, tree, tree, tree, tree,
+ unification_kind_t, int));
+static int unify PROTO((tree, tree, tree, tree, int));
static void add_pending_template PROTO((tree));
static int push_tinst_level PROTO((tree));
static tree classtype_mangled_name PROTO((tree));
-static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree));
+static char *mangle_class_name_for_template PROTO((char *, tree, tree));
static tree tsubst_expr_values PROTO((tree, tree));
static int list_eq PROTO((tree, tree));
-static tree get_class_bindings PROTO((tree, tree, tree, tree));
+static tree get_class_bindings PROTO((tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
-static tree tsubst_enum PROTO((tree, tree, tree *));
+static void tsubst_enum PROTO((tree, tree, tree));
static tree add_to_template_args PROTO((tree, tree));
+static tree add_outermost_template_args PROTO((tree, tree));
static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
tree*));
static int type_unification_real PROTO((tree, tree, tree, tree,
- int, unification_kind_t, int, int*));
-static tree complete_template_args PROTO((tree, tree, int));
+ int, unification_kind_t, int));
static void note_template_header PROTO((int));
static tree maybe_fold_nontype_arg PROTO((tree));
static tree convert_nontype_argument PROTO((tree, tree));
+static tree convert_template_argument PROTO ((tree, tree, tree, int,
+ int , tree));
static tree get_bindings_overload PROTO((tree, tree, tree));
static int for_each_template_parm PROTO((tree, tree_fn_t, void*));
static tree build_template_parm_index PROTO((int, int, int, tree, tree));
-static tree original_template PROTO((tree));
static int inline_needs_template_parms PROTO((tree));
static void push_inline_template_parms_recursive PROTO((tree, int));
static tree retrieve_specialization PROTO((tree, tree));
-static void register_specialization PROTO((tree, tree, tree));
-static void print_candidates PROTO((tree));
+static tree register_specialization PROTO((tree, tree, tree));
+static int unregister_specialization PROTO((tree, tree));
static tree reduce_template_parm_level PROTO((tree, tree, int));
static tree build_template_decl PROTO((tree, tree));
static int mark_template_parm PROTO((tree, void *));
@@ -113,35 +135,108 @@ static tree get_bindings_real PROTO((tree, tree, tree, int));
static int template_decl_level PROTO((tree));
static tree maybe_get_template_decl_from_type_decl PROTO((tree));
static int check_cv_quals_for_unify PROTO((int, tree, tree));
-static tree tsubst_template_arg_vector PROTO((tree, tree));
+static tree tsubst_template_arg_vector PROTO((tree, tree, int));
+static tree tsubst_template_parms PROTO((tree, tree, int));
static void regenerate_decl_from_template PROTO((tree, tree));
-static int is_member_template_class PROTO((tree));
-
-/* Nonzero if ARGVEC contains multiple levels of template arguments. */
-#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
- (NODE != NULL_TREE \
- && TREE_CODE (NODE) == TREE_VEC \
- && TREE_VEC_LENGTH (NODE) > 0 \
- && TREE_VEC_ELT (NODE, 0) != NULL_TREE \
+static tree most_specialized PROTO((tree, tree, tree));
+static tree most_specialized_class PROTO((tree, tree));
+static tree most_general_template PROTO((tree));
+static void set_mangled_name_for_template_decl PROTO((tree));
+static int template_class_depth_real PROTO((tree, int));
+static tree tsubst_aggr_type PROTO((tree, tree, int, tree, int));
+static tree tsubst_decl PROTO((tree, tree, tree, tree));
+static tree tsubst_arg_types PROTO((tree, tree, int, tree));
+static tree tsubst_function_type PROTO((tree, tree, int, tree));
+static void check_specialization_scope PROTO((void));
+static tree process_partial_specialization PROTO((tree));
+static void set_current_access_from_decl PROTO((tree));
+static void check_default_tmpl_args PROTO((tree, tree, int, int));
+static tree tsubst_call_declarator_parms PROTO((tree, tree, int, tree));
+static tree get_template_base_recursive PROTO((tree, tree,
+ tree, tree, tree, int));
+static tree get_template_base PROTO((tree, tree, tree, tree));
+static tree try_class_unification PROTO((tree, tree, tree, tree));
+static int coerce_template_template_parms PROTO((tree, tree, int,
+ tree, tree));
+static tree determine_specialization PROTO((tree, tree, tree *, int));
+static int template_args_equal PROTO((tree, tree));
+static void print_template_context PROTO((int));
+
+/* We use TREE_VECs to hold template arguments. If there is only one
+ level of template arguments, then the TREE_VEC contains the
+ arguments directly. If there is more than one level of template
+ arguments, then each entry in the TREE_VEC is itself a TREE_VEC,
+ containing the template arguments for a single level. The first
+ entry in the outer TREE_VEC is the outermost level of template
+ parameters; the last is the innermost.
+
+ It is incorrect to ever form a template argument vector containing
+ only one level of arguments, but which is a TREE_VEC containing as
+ its only entry the TREE_VEC for that level. */
+
+/* Non-zero if the template arguments is actually a vector of vectors,
+ rather than just a vector. */
+#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
+ (NODE != NULL_TREE \
+ && TREE_CODE (NODE) == TREE_VEC \
+ && TREE_VEC_LENGTH (NODE) > 0 \
+ && TREE_VEC_ELT (NODE, 0) != NULL_TREE \
&& TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
+/* The depth of a template argument vector. When called directly by
+ the parser, we use a TREE_LIST rather than a TREE_VEC to represent
+ template arguments. In fact, we may even see NULL_TREE if there
+ are no template arguments. In both of those cases, there is only
+ one level of template arguments. */
+#define TMPL_ARGS_DEPTH(NODE) \
+ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
+
+/* The LEVELth level of the template ARGS. Note that template
+ parameter levels are indexed from 1, not from 0. */
+#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \
+ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
+ ? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS)
+
+/* Set the LEVELth level of the template ARGS to VAL. This macro does
+ not work with single-level argument vectors. */
+#define SET_TMPL_ARGS_LEVEL(ARGS, LEVEL, VAL) \
+ (TREE_VEC_ELT ((ARGS), (LEVEL) - 1) = (VAL))
+
+/* Accesses the IDXth parameter in the LEVELth level of the ARGS. */
+#define TMPL_ARG(ARGS, LEVEL, IDX) \
+ (TREE_VEC_ELT (TMPL_ARGS_LEVEL (ARGS, LEVEL), IDX))
+
+/* Set the IDXth element in the LEVELth level of ARGS to VAL. This
+ macro does not work with single-level argument vectors. */
+#define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL) \
+ (TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL))
+
+/* Given a single level of template arguments in NODE, return the
+ number of arguments. */
+#define NUM_TMPL_ARGS(NODE) \
+ ((NODE) == NULL_TREE ? 0 \
+ : (TREE_CODE (NODE) == TREE_VEC \
+ ? TREE_VEC_LENGTH (NODE) : list_length (NODE)))
+
+/* The number of levels of template parameters given by NODE. */
+#define TMPL_PARMS_DEPTH(NODE) \
+ (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))
+
/* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
it is a specialization, in which case the DECL itself is returned. */
tree
-finish_member_template_decl (template_parameters, decl)
- tree template_parameters;
+finish_member_template_decl (decl)
tree decl;
{
- if (template_parameters)
- end_template_decl ();
- else
- end_specialization ();
-
if (decl == NULL_TREE || decl == void_type_node)
return NULL_TREE;
+ else if (decl == error_mark_node)
+ /* By returning NULL_TREE, the parser will just ignore this
+ declaration. We have already issued the error. */
+ return NULL_TREE;
else if (TREE_CODE (decl) == TREE_LIST)
{
/* Assume that the class is the only declspec. */
@@ -167,7 +262,6 @@ finish_member_template_decl (template_parameters, decl)
}
else
cp_error ("invalid member template declaration `%D'", decl);
-
return error_mark_node;
}
@@ -182,37 +276,59 @@ finish_member_template_decl (template_parameters, decl)
struct B {};
};
- A<T>::B<U> has depth two, while A<T> has depth one. Also,
- both A<T>::B<int> and A<int>::B<U> have depth one. */
+ A<T>::B<U> has depth two, while A<T> has depth one.
+ Both A<T>::B<int> and A<int>::B<U> have depth one, if
+ COUNT_SPECIALIZATIONS is 0 or if they are instantiations, not
+ specializations.
-int
-template_class_depth (type)
+ This function is guaranteed to return 0 if passed NULL_TREE so
+ that, for example, `template_class_depth (current_class_type)' is
+ always safe. */
+
+static int
+template_class_depth_real (type, count_specializations)
tree type;
+ int count_specializations;
{
int depth;
for (depth = 0;
- type && TREE_CODE (type) != FUNCTION_DECL
- && TREE_CODE (type) != NAMESPACE_DECL;
- type = TYPE_CONTEXT (type))
- if (CLASSTYPE_TEMPLATE_INFO (type)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
- && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
- ++depth;
+ type && TREE_CODE (type) != NAMESPACE_DECL;
+ type = (TREE_CODE (type) == FUNCTION_DECL)
+ ? DECL_REAL_CONTEXT (type) : TYPE_CONTEXT (type))
+ {
+ if (TREE_CODE (type) != FUNCTION_DECL)
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && ((count_specializations
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
+ || uses_template_parms (CLASSTYPE_TI_ARGS (type))))
+ ++depth;
+ }
+ else
+ {
+ if (DECL_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type))
+ && ((count_specializations
+ && DECL_TEMPLATE_SPECIALIZATION (type))
+ || uses_template_parms (DECL_TI_ARGS (type))))
+ ++depth;
+ }
+ }
return depth;
}
-/* Return the original template for this decl, disregarding any
- specializations. */
+/* Returns the template nesting level of the indicated class TYPE.
+ Like template_class_depth_real, but instantiations do not count in
+ the depth. */
-static tree
-original_template (decl)
- tree decl;
+int
+template_class_depth (type)
+ tree type;
{
- while (DECL_TEMPLATE_INFO (decl))
- decl = DECL_TI_TEMPLATE (decl);
- return decl;
+ return template_class_depth_real (type, /*count_specializations=*/0);
}
/* Returns 1 if processing DECL as part of do_pending_inlines
@@ -225,7 +341,7 @@ inline_needs_template_parms (decl)
if (! DECL_TEMPLATE_INFO (decl))
return 0;
- return (list_length (DECL_TEMPLATE_PARMS (original_template (decl)))
+ return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl)))
> (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl)));
}
@@ -266,10 +382,15 @@ push_inline_template_parms_recursive (parmlist, levels)
case PARM_DECL:
{
- /* Make a CONST_DECL as is done in process_template_parm. */
+ /* Make a CONST_DECL as is done in process_template_parm.
+ It is ugly that we recreate this here; the original
+ version built in process_template_parm is no longer
+ available. */
tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
+ SET_DECL_ARTIFICIAL (decl);
DECL_INITIAL (decl) = DECL_INITIAL (parm);
+ DECL_TEMPLATE_PARM_P (decl) = 1;
pushdecl (decl);
}
break;
@@ -288,35 +409,46 @@ maybe_begin_member_template_processing (decl)
tree decl;
{
tree parms;
- int levels;
-
- if (! inline_needs_template_parms (decl))
- return;
+ int levels = 0;
- parms = DECL_TEMPLATE_PARMS (original_template (decl));
+ if (inline_needs_template_parms (decl))
+ {
+ parms = DECL_TEMPLATE_PARMS (most_general_template (decl));
+ levels = TMPL_PARMS_DEPTH (parms) - processing_template_decl;
- levels = list_length (parms) - processing_template_decl;
+ if (DECL_TEMPLATE_SPECIALIZATION (decl))
+ {
+ --levels;
+ parms = TREE_CHAIN (parms);
+ }
- if (DECL_TEMPLATE_SPECIALIZATION (decl))
- {
- --levels;
- parms = TREE_CHAIN (parms);
+ push_inline_template_parms_recursive (parms, levels);
}
- push_inline_template_parms_recursive (parms, levels);
+ /* Remember how many levels of template parameters we pushed so that
+ we can pop them later. */
+ if (!inline_parm_levels)
+ VARRAY_INT_INIT (inline_parm_levels, 4, "inline_parm_levels");
+ if (inline_parm_levels_used == inline_parm_levels->num_elements)
+ VARRAY_GROW (inline_parm_levels, 2 * inline_parm_levels_used);
+ VARRAY_INT (inline_parm_levels, inline_parm_levels_used) = levels;
+ ++inline_parm_levels_used;
}
/* Undo the effects of begin_member_template_processing. */
void
-maybe_end_member_template_processing (decl)
- tree decl;
+maybe_end_member_template_processing ()
{
- if (! processing_template_decl)
+ int i;
+
+ if (!inline_parm_levels_used)
return;
- while (current_template_parms
- && TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
+ --inline_parm_levels_used;
+ for (i = 0;
+ i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used);
+ ++i)
{
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
@@ -336,14 +468,14 @@ maybe_end_member_template_processing (decl)
template <class T> class C { template <class U> void f(U); }
then neither C<int>::f<char> nor C<T>::f<double> is considered
- to be a member template. */
+ to be a member template. But, `template <class U> void
+ C<int>::f(U)' is considered a member template. */
int
is_member_template (t)
tree t;
{
- if (TREE_CODE (t) != FUNCTION_DECL
- && !DECL_FUNCTION_TEMPLATE_P (t))
+ if (!DECL_FUNCTION_TEMPLATE_P (t))
/* Anything that isn't a function or a template function is
certainly not a member template. */
return 0;
@@ -352,33 +484,15 @@ is_member_template (t)
if (hack_decl_function_context (t))
return 0;
- if ((DECL_FUNCTION_MEMBER_P (t)
- && !DECL_TEMPLATE_SPECIALIZATION (t))
- || (TREE_CODE (t) == TEMPLATE_DECL
- && DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
- {
- tree tmpl;
-
- if (DECL_FUNCTION_TEMPLATE_P (t))
- tmpl = t;
- else if (DECL_TEMPLATE_INFO (t)
- && DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
- tmpl = DECL_TI_TEMPLATE (t);
- else
- tmpl = NULL_TREE;
-
- if (tmpl
+ return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))
/* If there are more levels of template parameters than
there are template classes surrounding the declaration,
then we have a member template. */
- && (list_length (DECL_TEMPLATE_PARMS (tmpl)) >
- template_class_depth (DECL_CLASS_CONTEXT (t))))
- return 1;
- }
-
- return 0;
+ && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
+ template_class_depth (DECL_CLASS_CONTEXT (t))));
}
+#if 0 /* UNUSED */
/* Returns non-zero iff T is a member template class. See
is_member_template for a description of what precisely constitutes
a member template. */
@@ -400,146 +514,69 @@ is_member_template_class (t)
/* If there are more levels of template parameters than there are
template classes surrounding the declaration, then we have a
member template. */
- return (list_length (DECL_TEMPLATE_PARMS (t)) >
+ return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
template_class_depth (DECL_CONTEXT (t)));
}
+#endif
-/* Return a new template argument vector which contains all of ARGS
- for all outer templates TMPL is contained in, but has as its
- innermost set of arguments the EXTRA_ARGS. If UNBOUND_ONLY, we
- are only interested in unbound template arguments, not arguments from
- enclosing templates that have been instantiated already. */
+/* Return a new template argument vector which contains all of ARGS,
+ but has as its innermost set of arguments the EXTRA_ARGS. The
+ resulting vector will be built on a temporary obstack, and so must
+ be explicitly copied to the permanent obstack, if required. */
static tree
-complete_template_args (tmpl, extra_args, unbound_only)
- tree tmpl, extra_args;
- int unbound_only;
+add_to_template_args (args, extra_args)
+ tree args;
+ tree extra_args;
{
- /* depth is the number of levels of enclosing args we're adding. */
- int depth, i;
- tree args, new_args, spec_args = NULL_TREE;
- int extra_arg_depth;
-
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
- my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
-
- if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (extra_args))
- extra_arg_depth = TREE_VEC_LENGTH (extra_args);
- else
- extra_arg_depth = 1;
-
- if (DECL_TEMPLATE_INFO (tmpl) && !unbound_only)
- {
- /* A specialization of a member template of a template class shows up
- as a TEMPLATE_DECL with DECL_TEMPLATE_SPECIALIZATION set.
- DECL_TI_ARGS is the specialization args, and DECL_TI_TEMPLATE
- is the template being specialized. */
- if (DECL_TEMPLATE_SPECIALIZATION (tmpl))
- {
- spec_args = DECL_TI_ARGS (tmpl);
- tmpl = DECL_TI_TEMPLATE (tmpl);
- }
-
- if (DECL_TEMPLATE_INFO (tmpl))
- {
- /* A partial instantiation of a member template shows up as a
- TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is
- all the bound template arguments. */
- args = DECL_TI_ARGS (tmpl);
- if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- depth = 1;
- else
- depth = TREE_VEC_LENGTH (args);
- }
- else
- /* If we are a specialization, we might have no previously bound
- template args. */
- depth = 0;
-
- new_args = make_tree_vec (depth + extra_arg_depth + (!!spec_args));
-
- if (depth == 1)
- TREE_VEC_ELT (new_args, 0) = args;
- else
- for (i = 0; i < depth; ++i)
- TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
- }
- else
- {
- tree type;
- int skip;
-
- /* For unbound args, we have to do more work. We are getting bindings
- for the innermost args from extra_args, so we start from our
- context and work out until we've seen all the args. We need to
- do it this way to handle partial specialization. */
-
- depth = list_length (DECL_TEMPLATE_PARMS (tmpl)) - 1;
- if (depth == 0)
- return extra_args;
-
- new_args = make_tree_vec (depth + extra_arg_depth);
-
- /* If this isn't a member template, extra_args is for the innermost
- template class, so skip over it. */
- skip = (! is_member_template (tmpl));
-
- if (depth > skip)
- {
- type = DECL_REAL_CONTEXT (tmpl);
- for (i = depth; i; type = TYPE_CONTEXT (type))
- if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)))
- {
- if (skip)
- skip = 0;
- else
- {
- --i;
- TREE_VEC_ELT (new_args, i) = CLASSTYPE_TI_ARGS (type);
- }
- }
- }
- }
+ tree new_args;
+ int extra_depth;
+ int i;
+ int j;
- if (extra_arg_depth == 1)
- TREE_VEC_ELT (new_args, depth++) = extra_args;
- else
- for (i = 0; i < extra_arg_depth; ++i)
- TREE_VEC_ELT (new_args, depth++) = TREE_VEC_ELT (extra_args, i);
+ extra_depth = TMPL_ARGS_DEPTH (extra_args);
+ new_args = make_temp_vec (TMPL_ARGS_DEPTH (args) + extra_depth);
- if (spec_args)
- TREE_VEC_ELT (new_args, depth) = spec_args;
+ for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i)
+ SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i));
+ for (j = 1; j <= extra_depth; ++j, ++i)
+ SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j));
+
return new_args;
}
-/* Return a new template argument vector which contains all of ARGS,
- but has as its innermost set of arguments the EXTRA_ARGS. */
+/* Like add_to_template_args, but only the outermost ARGS are added to
+ the EXTRA_ARGS. In particular, all but TMPL_ARGS_DEPTH
+ (EXTRA_ARGS) levels are added. This function is used to combine
+ the template arguments from a partial instantiation with the
+ template arguments used to attain the full instantiation from the
+ partial instantiation. */
static tree
-add_to_template_args (args, extra_args)
+add_outermost_template_args (args, extra_args)
tree args;
tree extra_args;
{
tree new_args;
- if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- {
- new_args = make_tree_vec (2);
- TREE_VEC_ELT (new_args, 0) = args;
- }
- else
- {
- int i;
+ /* If there are more levels of EXTRA_ARGS than there are ARGS,
+ something very fishy is going on. */
+ my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
+ 0);
- new_args = make_tree_vec (TREE_VEC_LENGTH (args) + 1);
+ /* If *all* the new arguments will be the EXTRA_ARGS, just return
+ them. */
+ if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))
+ return extra_args;
- for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
- TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
- }
-
- TREE_VEC_ELT (new_args,
- TREE_VEC_LENGTH (new_args) - 1) = extra_args;
+ /* For the moment, we make ARGS look like it contains fewer levels. */
+ TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
+
+ new_args = add_to_template_args (args, extra_args);
+
+ /* Now, we restore ARGS to its full dimensions. */
+ TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args);
return new_args;
}
@@ -571,12 +608,46 @@ begin_template_parm_list ()
note_template_header (0);
}
+/* This routine is called when a specialization is declared. If it is
+ illegal to declare a specialization here, an error is reported. */
+
+static void
+check_specialization_scope ()
+{
+ tree scope = current_scope ();
+
+ /* [temp.expl.spec]
+
+ An explicit specialization shall be declared in the namespace of
+ which the template is a member, or, for member templates, in the
+ namespace of which the enclosing class or enclosing class
+ template is a member. An explicit specialization of a member
+ function, member class or static data member of a class template
+ shall be declared in the namespace of which the class template
+ is a member. */
+ if (scope && TREE_CODE (scope) != NAMESPACE_DECL)
+ cp_error ("explicit specialization in non-namespace scope `%D'",
+ scope);
+
+ /* [temp.expl.spec]
+
+ In an explicit specialization declaration for a member of a class
+ template or a member template that appears in namespace scope,
+ the member template and some of its enclosing class templates may
+ remain unspecialized, except that the declaration shall not
+ explicitly specialize a class member template if its enclosing
+ class templates are not explicitly specialized as well. */
+ if (current_template_parms)
+ cp_error ("enclosing class templates are not explicitly specialized");
+}
+
/* We've just seen template <>. */
void
begin_specialization ()
{
note_template_header (1);
+ check_specialization_scope ();
}
/* Called at then end of processing a declaration preceeded by
@@ -625,6 +696,36 @@ end_explicit_instantiation ()
--processing_explicit_instantiation;
}
+/* The TYPE is being declared. If it is a template type, that means it
+ is a partial specialization. Do appropriate error-checking. */
+
+void
+maybe_process_partial_specialization (type)
+ tree type;
+{
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+ && TYPE_SIZE (type) == NULL_TREE)
+ {
+ if (current_namespace
+ != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ {
+ cp_pedwarn ("specializing `%#T' in different namespace", type);
+ cp_pedwarn_at (" from definition of `%#D'",
+ CLASSTYPE_TI_TEMPLATE (type));
+ }
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ if (processing_template_decl)
+ push_template_decl (TYPE_MAIN_DECL (type));
+ }
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ cp_error ("specialization of `%T' after instantiation", type);
+ }
+ else if (processing_specialization)
+ cp_error ("explicit specialization of non-template `%T'", type);
+}
+
/* Retrieve the specialization (in the sense of [temp.spec] - a
specialization is either an instantiation or an explicit
specialization) of TMPL for the given template ARGS. If there is
@@ -641,6 +742,12 @@ retrieve_specialization (tmpl, args)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+ /* There should be as many levels of arguments as there are
+ levels of parameters. */
+ my_friendly_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
+ 0);
+
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
@@ -675,8 +782,8 @@ is_specialization_of (decl, tmpl)
t != NULL_TREE;
t = CLASSTYPE_USE_TEMPLATE (t)
? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE)
- if (comptypes (TYPE_MAIN_VARIANT (t),
- TYPE_MAIN_VARIANT (TREE_TYPE (tmpl)), 1))
+ if (same_type_p (TYPE_MAIN_VARIANT (t),
+ TYPE_MAIN_VARIANT (TREE_TYPE (tmpl))))
return 1;
}
@@ -684,9 +791,10 @@ is_specialization_of (decl, tmpl)
}
/* Register the specialization SPEC as a specialization of TMPL with
- the indicated ARGS. */
+ the indicated ARGS. Returns SPEC, or an equivalent prior
+ declaration, if available. */
-static void
+static tree
register_specialization (spec, tmpl, args)
tree spec;
tree tmpl;
@@ -696,14 +804,27 @@ register_specialization (spec, tmpl, args)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
- if (TREE_CODE (spec) != TEMPLATE_DECL
- && list_length (DECL_TEMPLATE_PARMS (tmpl)) > 1)
- /* Avoid registering function declarations as
- specializations of member templates, as would otherwise
- happen with out-of-class specializations of member
- templates. */
- return;
+ if (TREE_CODE (spec) == FUNCTION_DECL
+ && uses_template_parms (DECL_TI_ARGS (spec)))
+ /* This is the FUNCTION_DECL for a partial instantiation. Don't
+ register it; we want the corresponding TEMPLATE_DECL instead.
+ We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than
+ the more obvious `uses_template_parms (spec)' to avoid problems
+ with default function arguments. In particular, given
+ something like this:
+
+ template <class T> void f(T t1, T t = T())
+
+ the default argument expression is not substituted for in an
+ instantiation unless and until it is actually needed. */
+ return spec;
+ /* There should be as many levels of arguments as there are
+ levels of parameters. */
+ my_friendly_assert (TMPL_ARGS_DEPTH (args)
+ == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)),
+ 0);
+
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
@@ -720,7 +841,7 @@ register_specialization (spec, tmpl, args)
{
cp_error ("specialization of %D after instantiation",
fn);
- return;
+ return spec;
}
else
{
@@ -729,68 +850,117 @@ register_specialization (spec, tmpl, args)
the second is an explicit specialization, and
the implicit instantiation has not yet been
used. That situation can occur if we have
- implicitly instantiated a member function of
- class type, and then specialized it later. */
- TREE_VALUE (s) = spec;
- return;
+ implicitly instantiated a member function and
+ then specialized it later.
+
+ We can also wind up here if a friend
+ declaration that looked like an instantiation
+ turns out to be a specialization:
+
+ template <class T> void foo(T);
+ class S { friend void foo<>(int) };
+ template <> void foo(int);
+
+ We transform the existing DECL in place so that
+ any pointers to it become pointers to the
+ updated declaration.
+
+ If there was a definition for the template, but
+ not for the specialization, we want this to
+ look as if there is no definition, and vice
+ versa. */
+ DECL_INITIAL (fn) = NULL_TREE;
+ duplicate_decls (spec, fn);
+
+ return fn;
}
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
- if (DECL_INITIAL (fn))
- cp_error ("duplicate specialization of %D", fn);
-
- TREE_VALUE (s) = spec;
- return;
+ duplicate_decls (spec, fn);
+ return fn;
}
}
}
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= perm_tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+
+ return spec;
+}
+
+/* Unregister the specialization SPEC as a specialization of TMPL.
+ Returns nonzero if the SPEC was listed as a specialization of
+ TMPL. */
+
+static int
+unregister_specialization (spec, tmpl)
+ tree spec;
+ tree tmpl;
+{
+ tree* s;
+
+ for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ *s != NULL_TREE;
+ s = &TREE_CHAIN (*s))
+ if (TREE_VALUE (*s) == spec)
+ {
+ *s = TREE_CHAIN (*s);
+ return 1;
+ }
+
+ return 0;
}
/* Print the list of candidate FNS in an error message. */
-static void
+void
print_candidates (fns)
tree fns;
{
tree fn;
- char* str = "candidates are:";
+ const char *str = "candidates are:";
for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
{
- cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
+ tree f;
+
+ for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f))
+ cp_error_at ("%s %+#D", str, OVL_CURRENT (f));
str = " ";
}
}
/* Returns the template (one of the functions given by TEMPLATE_ID)
which can be specialized to match the indicated DECL with the
- explicit template args given in TEMPLATE_ID. If
- NEED_MEMBER_TEMPLATE is true the function is a specialization of a
- member template. The template args (those explicitly specified and
- those deduced) are output in a newly created vector *TARGS_OUT. If
- it is impossible to determine the result, an error message is
- issued, unless COMPLAIN is 0. The DECL may be NULL_TREE if none is
- available. */
+ explicit template args given in TEMPLATE_ID. The DECL may be
+ NULL_TREE if none is available. In that case, the functions in
+ TEMPLATE_ID are non-members.
-tree
+ If NEED_MEMBER_TEMPLATE is non-zero the function is known to be a
+ specialization of a member template.
+
+ The template args (those explicitly specified and those deduced)
+ are output in a newly created vector *TARGS_OUT.
+
+ If it is impossible to determine the result, an error message is
+ issued. The error_mark_node is returned to indicate failure. */
+
+static tree
determine_specialization (template_id, decl, targs_out,
- need_member_template,
- complain)
+ need_member_template)
tree template_id;
tree decl;
tree* targs_out;
int need_member_template;
- int complain;
{
- tree fns, targs_in;
- tree templates = NULL_TREE;
tree fn;
- int i;
+ tree fns;
+ tree targs;
+ tree explicit_targs;
+ tree candidates = NULL_TREE;
+ tree templates = NULL_TREE;
*targs_out = NULL_TREE;
@@ -798,7 +968,7 @@ determine_specialization (template_id, decl, targs_out,
return error_mark_node;
fns = TREE_OPERAND (template_id, 0);
- targs_in = TREE_OPERAND (template_id, 1);
+ explicit_targs = TREE_OPERAND (template_id, 1);
if (fns == error_mark_node)
return error_mark_node;
@@ -812,86 +982,146 @@ determine_specialization (template_id, decl, targs_out,
tree tmpl;
fn = OVL_CURRENT (fns);
- if (!need_member_template
- && TREE_CODE (fn) == FUNCTION_DECL
- && DECL_FUNCTION_MEMBER_P (fn)
- && DECL_USE_TEMPLATE (fn)
- && DECL_TI_TEMPLATE (fn))
- /* We can get here when processing something like:
- template <class T> class X { void f(); }
- template <> void X<int>::f() {}
- We're specializing a member function, but not a member
- template. */
- tmpl = DECL_TI_TEMPLATE (fn);
- else if (TREE_CODE (fn) != TEMPLATE_DECL
- || (need_member_template && !is_member_template (fn)))
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ /* DECL might be a specialization of FN. */
+ tmpl = fn;
+ else if (need_member_template)
+ /* FN is an ordinary member function, and we need a
+ specialization of a member template. */
+ continue;
+ else if (TREE_CODE (fn) != FUNCTION_DECL)
+ /* We can get IDENTIFIER_NODEs here in certain erroneous
+ cases. */
+ continue;
+ else if (!DECL_FUNCTION_MEMBER_P (fn))
+ /* This is just an ordinary non-member function. Nothing can
+ be a specialization of that. */
continue;
else
- tmpl = fn;
+ {
+ tree decl_arg_types;
- if (list_length (targs_in) > DECL_NTPARMS (tmpl))
- continue;
+ /* This is an ordinary member function. However, since
+ we're here, we can assume it's enclosing class is a
+ template class. For example,
+
+ template <typename T> struct S { void f(); };
+ template <> void S<int>::f() {}
- if (decl == NULL_TREE)
- {
- tree targs = make_scratch_vec (DECL_NTPARMS (tmpl));
-
- /* We allow incomplete unification here, because we are going to
- check all the functions. */
- i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
- targs,
- NULL_TREE,
- NULL_TREE,
- targs_in,
- DEDUCE_EXACT, 1);
-
- if (i == 0)
- /* Unification was successful. */
- templates = scratch_tree_cons (targs, tmpl, templates);
+ Here, S<int>::f is a non-template, but S<int> is a
+ template class. If FN has the same type as DECL, we
+ might be in business. */
+ if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
+ TREE_TYPE (TREE_TYPE (fn))))
+ /* The return types differ. */
+ continue;
+
+ /* Adjust the type of DECL in case FN is a static member. */
+ decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ if (DECL_STATIC_FUNCTION_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ decl_arg_types = TREE_CHAIN (decl_arg_types);
+
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ decl_arg_types))
+ /* They match! */
+ candidates = tree_cons (NULL_TREE, fn, candidates);
+
+ continue;
}
- else
- templates = scratch_tree_cons (NULL_TREE, tmpl, templates);
- }
-
- if (decl != NULL_TREE)
- {
- tree tmpl = most_specialized (templates, decl, targs_in);
- if (tmpl == error_mark_node)
- goto ambiguous;
- else if (tmpl == NULL_TREE)
- goto no_match;
+ /* See whether this function might be a specialization of this
+ template. */
+ targs = get_bindings (tmpl, decl, explicit_targs);
+
+ if (!targs)
+ /* We cannot deduce template arguments that when used to
+ specialize TMPL will produce DECL. */
+ continue;
- *targs_out = get_bindings (tmpl, decl, targs_in);
- return tmpl;
+ /* Save this template, and the arguments deduced. */
+ templates = scratch_tree_cons (targs, tmpl, templates);
}
- if (templates == NULL_TREE)
+ if (templates && TREE_CHAIN (templates))
{
- no_match:
- if (complain)
- {
- cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",
- template_id, decl);
- return error_mark_node;
- }
- return NULL_TREE;
+ /* We have:
+
+ [temp.expl.spec]
+
+ It is possible for a specialization with a given function
+ signature to be instantiated from more than one function
+ template. In such cases, explicit specification of the
+ template arguments must be used to uniquely identify the
+ function template specialization being specialized.
+
+ Note that here, there's no suggestion that we're supposed to
+ determine which of the candidate templates is most
+ specialized. However, we, also have:
+
+ [temp.func.order]
+
+ Partial ordering of overloaded function template
+ declarations is used in the following contexts to select
+ the function template to which a function template
+ specialization refers:
+
+ -- when an explicit specialization refers to a function
+ template.
+
+ So, we do use the partial ordering rules, at least for now.
+ This extension can only serve to make illegal programs legal,
+ so it's safe. And, there is strong anecdotal evidence that
+ the committee intended the partial ordering rules to apply;
+ the EDG front-end has that behavior, and John Spicer claims
+ that the committee simply forgot to delete the wording in
+ [temp.expl.spec]. */
+ tree tmpl = most_specialized (templates, decl, explicit_targs);
+ if (tmpl && tmpl != error_mark_node)
+ {
+ targs = get_bindings (tmpl, decl, explicit_targs);
+ templates = scratch_tree_cons (targs, tmpl, NULL_TREE);
+ }
+ }
+
+ if (templates == NULL_TREE && candidates == NULL_TREE)
+ {
+ cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",
+ template_id, decl);
+ return error_mark_node;
}
- else if (TREE_CHAIN (templates) != NULL_TREE)
+ else if ((templates && TREE_CHAIN (templates))
+ || (candidates && TREE_CHAIN (candidates))
+ || (templates && candidates))
{
- ambiguous:
- if (complain)
- {
- cp_error_at ("ambiguous template specialization `%D' for `%+D'",
- template_id, decl);
- print_candidates (templates);
- return error_mark_node;
- }
- return NULL_TREE;
+ cp_error_at ("ambiguous template specialization `%D' for `%+D'",
+ template_id, decl);
+ chainon (candidates, templates);
+ print_candidates (candidates);
+ return error_mark_node;
}
/* We have one, and exactly one, match. */
- *targs_out = TREE_PURPOSE (templates);
+ if (candidates)
+ {
+ /* It was a specialization of an ordinary member function in a
+ template class. */
+ *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates)));
+ return DECL_TI_TEMPLATE (TREE_VALUE (candidates));
+ }
+
+ /* It was a specialization of a template. */
+ targs = DECL_TI_ARGS (DECL_RESULT (TREE_VALUE (templates)));
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
+ {
+ *targs_out = copy_node (targs);
+ SET_TMPL_ARGS_LEVEL (*targs_out,
+ TMPL_ARGS_DEPTH (*targs_out),
+ TREE_PURPOSE (templates));
+ }
+ else
+ *targs_out = TREE_PURPOSE (templates);
return TREE_VALUE (templates);
}
@@ -901,19 +1131,14 @@ determine_specialization (template_id, decl, targs_out,
instantiation at this point.
Returns DECL, or an equivalent declaration that should be used
- instead.
+ instead if all goes well. Issues an error message if something is
+ amiss. Returns error_mark_node if the error is not easily
+ recoverable.
FLAGS is a bitmask consisting of the following flags:
- 1: We are being called by finish_struct. (We are unable to
- determine what template is specialized by an in-class
- declaration until the class definition is complete, so
- finish_struct_methods calls this function again later to finish
- the job.)
2: The function has a definition.
4: The function is a friend.
- 8: The function is known to be a specialization of a member
- template.
The TEMPLATE_COUNT is the number of references to qualifying
template classes that appeared in the name of the function. For
@@ -927,8 +1152,7 @@ determine_specialization (template_id, decl, targs_out,
template <class T> struct S {};
template <> struct S<int> { void f(); }
- template <>
- void S<int>::f();
+ template <> void S<int>::f();
the TEMPLATE_COUNT would be 0. (Note that this declaration is
illegal; there should be no template <>.)
@@ -945,113 +1169,117 @@ check_explicit_specialization (declarator, decl, template_count, flags)
int template_count;
int flags;
{
- int finish_member = flags & 1;
int have_def = flags & 2;
int is_friend = flags & 4;
int specialization = 0;
int explicit_instantiation = 0;
- int member_specialization = flags & 8;
+ int member_specialization = 0;
tree ctype = DECL_CLASS_CONTEXT (decl);
tree dname = DECL_NAME (decl);
- if (!finish_member)
+ if (processing_specialization)
{
- if (processing_specialization)
- {
- /* The last template header was of the form template <>. */
+ /* The last template header was of the form template <>. */
- if (template_header_count > template_count)
- {
- /* There were more template headers than qualifying template
- classes. */
- if (template_header_count - template_count > 1)
- /* There shouldn't be that many template parameter
- lists. There can be at most one parameter list for
- every qualifying class, plus one for the function
- itself. */
- cp_error ("too many template parameter lists in declaration of `%D'", decl);
-
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- if (ctype)
- member_specialization = 1;
- else
- specialization = 1;
- }
- else if (template_header_count == template_count)
- {
- /* The counts are equal. So, this might be a
- specialization, but it is not a specialization of a
- member template. It might be something like
-
- template <class T> struct S {
- void f(int i);
- };
- template <>
- void S<int>::f(int i) {} */
- specialization = 1;
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
- }
- else
- {
- /* This cannot be an explicit specialization. There are not
- enough headers for all of the qualifying classes. For
- example, we might have:
-
- template <>
- void S<int>::T<char>::f();
+ if (template_header_count > template_count)
+ {
+ /* There were more template headers than qualifying template
+ classes. */
+ if (template_header_count - template_count > 1)
+ /* There shouldn't be that many template parameter lists.
+ There can be at most one parameter list for every
+ qualifying class, plus one for the function itself. */
+ cp_error ("too many template parameter lists in declaration of `%D'", decl);
- But, we're missing another template <>. */
- cp_error("too few template parameter lists in declaration of `%D'", decl);
- return decl;
- }
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ if (ctype)
+ member_specialization = 1;
+ else
+ specialization = 1;
}
- else if (processing_explicit_instantiation)
+ else if (template_header_count == template_count)
{
- if (template_header_count)
- cp_error ("template parameter list used in explicit instantiation");
-
- if (have_def)
- cp_error ("definition provided for explicit instantiation");
-
- explicit_instantiation = 1;
+ /* The counts are equal. So, this might be a
+ specialization, but it is not a specialization of a
+ member template. It might be something like
+
+ template <class T> struct S {
+ void f(int i);
+ };
+ template <>
+ void S<int>::f(int i) {} */
+ specialization = 1;
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
}
- else if (ctype != NULL_TREE
- && !TYPE_BEING_DEFINED (ctype)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
+ else
{
- /* This case catches outdated code that looks like this:
+ /* This cannot be an explicit specialization. There are not
+ enough headers for all of the qualifying classes. For
+ example, we might have:
+
+ template <>
+ void S<int>::T<char>::f();
- template <class T> struct S { void f(); };
- void S<int>::f() {} // Missing template <>
+ But, we're missing another template <>. */
+ cp_error("too few template parameter lists in declaration of `%D'", decl);
+ return decl;
+ }
+ }
+ else if (processing_explicit_instantiation)
+ {
+ if (template_header_count)
+ cp_error ("template parameter list used in explicit instantiation");
+
+ if (have_def)
+ cp_error ("definition provided for explicit instantiation");
+
+ explicit_instantiation = 1;
+ }
+ else if (ctype != NULL_TREE
+ && !TYPE_BEING_DEFINED (ctype)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
+ && !is_friend)
+ {
+ /* This case catches outdated code that looks like this:
- We disable this check when the type is being defined to
- avoid complaining about default compiler-generated
- constructors, destructors, and assignment operators.
- Since the type is an instantiation, not a specialization,
- these are the only functions that can be defined before
- the class is complete. */
+ template <class T> struct S { void f(); };
+ void S<int>::f() {} // Missing template <>
+
+ We disable this check when the type is being defined to
+ avoid complaining about default compiler-generated
+ constructors, destructors, and assignment operators.
+ Since the type is an instantiation, not a specialization,
+ these are the only functions that can be defined before
+ the class is complete. */
/* If they said
template <class T> void S<int>::f() {}
that's bogus. */
- if (template_header_count)
- {
- cp_error ("template parameters specified in specialization");
- return decl;
- }
-
- if (pedantic)
- cp_pedwarn
- ("explicit specialization not preceded by `template <>'");
- specialization = 1;
- SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ if (template_header_count)
+ {
+ cp_error ("template parameters specified in specialization");
+ return decl;
}
- else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+
+ if (pedantic)
+ cp_pedwarn
+ ("explicit specialization not preceded by `template <>'");
+ specialization = 1;
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ }
+ else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ {
+ if (is_friend)
+ /* This could be something like:
+
+ template <class T> void f(T);
+ class S { friend void f<>(int); } */
+ specialization = 1;
+ else
{
- /* This case handles bogus declarations like
- template <> template <class T>
- void f<int>(); */
+ /* This case handles bogus declarations like template <>
+ template <class T> void f<int>(); */
cp_error ("template-id `%D' in declaration of primary template",
declarator);
@@ -1069,6 +1297,8 @@ check_explicit_specialization (declarator, decl, template_count, flags)
("default argument specified in explicit specialization");
break;
}
+ if (current_lang_name == lang_name_c)
+ cp_error ("template specialization with C linkage");
}
if (specialization || member_specialization || explicit_instantiation)
@@ -1095,47 +1325,41 @@ check_explicit_specialization (declarator, decl, template_count, flags)
if (declarator == error_mark_node)
return error_mark_node;
- if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR)
- {
- /* A friend declaration. We can't do much, because we don't
- know what this resolves to, yet. */
- my_friendly_assert (is_friend != 0, 0);
- my_friendly_assert (!explicit_instantiation, 0);
- SET_DECL_IMPLICIT_INSTANTIATION (decl);
- return decl;
- }
-
if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype))
{
if (!explicit_instantiation)
- {
- /* Since finish_struct_1 has not been called yet, we
- can't call lookup_fnfields. We note that this
- template is a specialization, and proceed, letting
- finish_struct fix this up later. */
- tree ti = perm_tree_cons (NULL_TREE,
- TREE_OPERAND (declarator, 1),
- NULL_TREE);
- TI_PENDING_SPECIALIZATION_FLAG (ti) = 1;
- DECL_TEMPLATE_INFO (decl) = ti;
- }
+ /* A specialization in class scope. This is illegal,
+ but the error will already have been flagged by
+ check_specialization_scope. */
+ return error_mark_node;
else
- /* It's not legal to write an explicit instantiation in
- class scope, e.g.:
+ {
+ /* It's not legal to write an explicit instantiation in
+ class scope, e.g.:
- class C { template void f(); }
+ class C { template void f(); }
- This case is caught by the parser. However, on
- something like:
+ This case is caught by the parser. However, on
+ something like:
- template class C { void f(); };
+ template class C { void f(); };
- (which is illegal) we can get here. The error will be
- issued later. */
- ;
+ (which is illegal) we can get here. The error will be
+ issued later. */
+ ;
+ }
return decl;
}
+ else if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR)
+ {
+ /* A friend declaration. We can't do much, because we don't
+ know what this resolves to, yet. */
+ my_friendly_assert (is_friend != 0, 0);
+ my_friendly_assert (!explicit_instantiation, 0);
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ return decl;
+ }
else if (ctype != NULL_TREE
&& (TREE_CODE (TREE_OPERAND (declarator, 0)) ==
IDENTIFIER_NODE))
@@ -1143,8 +1367,9 @@ check_explicit_specialization (declarator, decl, template_count, flags)
/* Find the list of functions in ctype that have the same
name as the declared function. */
tree name = TREE_OPERAND (declarator, 0);
- tree fns;
-
+ tree fns = NULL_TREE;
+ int idx;
+
if (name == constructor_name (ctype)
|| name == constructor_name_full (ctype))
{
@@ -1162,21 +1387,51 @@ check_explicit_specialization (declarator, decl, template_count, flags)
Similar language is found in [temp.explicit]. */
cp_error ("specialization of implicitly-declared special member function");
-
- return decl;
+ return error_mark_node;
}
name = is_constructor ? ctor_identifier : dtor_identifier;
}
- fns = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
-
+ if (!IDENTIFIER_TYPENAME_P (name))
+ {
+ idx = lookup_fnfields_1 (ctype, name);
+ if (idx >= 0)
+ fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), idx);
+ }
+ else
+ {
+ tree methods;
+
+ /* For a type-conversion operator, we cannot do a
+ name-based lookup. We might be looking for `operator
+ int' which will be a specialization of `operator T'.
+ So, we find *all* the conversion operators, and then
+ select from them. */
+ fns = NULL_TREE;
+
+ methods = CLASSTYPE_METHOD_VEC (ctype);
+ if (methods)
+ for (idx = 2; idx < TREE_VEC_LENGTH (methods); ++idx)
+ {
+ tree ovl = TREE_VEC_ELT (methods, idx);
+
+ if (!ovl || !DECL_CONV_FN_P (OVL_CURRENT (ovl)))
+ /* There are no more conversion functions. */
+ break;
+
+ /* Glue all these conversion functions together
+ with those we already have. */
+ for (; ovl; ovl = OVL_NEXT (ovl))
+ fns = ovl_cons (OVL_CURRENT (ovl), fns);
+ }
+ }
+
if (fns == NULL_TREE)
{
- cp_error ("no member function `%s' declared in `%T'",
- IDENTIFIER_POINTER (name),
- ctype);
- return decl;
+ cp_error ("no member function `%D' declared in `%T'",
+ name, ctype);
+ return error_mark_node;
}
else
TREE_OPERAND (declarator, 0) = fns;
@@ -1186,100 +1441,141 @@ check_explicit_specialization (declarator, decl, template_count, flags)
Note that for an explicit instantiation, even one for a
member function, we cannot tell apriori whether the
instantiation is for a member template, or just a member
- function of a template class. In particular, even in if the
- instantiation is for a member template, the template
- arguments could be deduced from the declaration. */
+ function of a template class. Even if a member template is
+ being instantiated, the member template arguments may be
+ elided if they can be deduced from the rest of the
+ declaration. */
tmpl = determine_specialization (declarator, decl,
&targs,
- member_specialization,
- 1);
+ member_specialization);
- if (tmpl && tmpl != error_mark_node)
+ if (!tmpl || tmpl == error_mark_node)
+ /* We couldn't figure out what this declaration was
+ specializing. */
+ return error_mark_node;
+ else
{
+ tree gen_tmpl = most_general_template (tmpl);
+
if (explicit_instantiation)
{
+ /* We don't set DECL_EXPLICIT_INSTANTIATION here; that
+ is done by do_decl_instantiation later. */
+
+ int arg_depth = TMPL_ARGS_DEPTH (targs);
+ int parm_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+
+ if (arg_depth > parm_depth)
+ {
+ /* If TMPL is not the most general template (for
+ example, if TMPL is a friend template that is
+ injected into namespace scope), then there will
+ be too many levels fo TARGS. Remove some of them
+ here. */
+ int i;
+ tree new_targs;
+
+ new_targs = make_temp_vec (parm_depth);
+ for (i = arg_depth - parm_depth; i < arg_depth; ++i)
+ TREE_VEC_ELT (new_targs, i - (arg_depth - parm_depth))
+ = TREE_VEC_ELT (targs, i);
+ targs = new_targs;
+ }
+
decl = instantiate_template (tmpl, targs);
- if (!DECL_TEMPLATE_SPECIALIZATION (decl))
- /* There doesn't seem to be anything in the draft to
- prevent a specialization from being explicitly
- instantiated. We're careful not to destroy the
- information indicating that this is a
- specialization here. */
- SET_DECL_EXPLICIT_INSTANTIATION (decl);
return decl;
}
- else if (DECL_STATIC_FUNCTION_P (tmpl)
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+
+ /* If we though that the DECL was a member function, but it
+ turns out to be specializing a static member function,
+ make DECL a static member function as well. */
+ if (DECL_STATIC_FUNCTION_P (tmpl)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{
revert_static_member_fn (&decl, 0, 0);
last_function_parms = TREE_CHAIN (last_function_parms);
}
+ /* Set up the DECL_TEMPLATE_INFO for DECL. */
+ DECL_TEMPLATE_INFO (decl)
+ = perm_tree_cons (tmpl, targs, NULL_TREE);
+
/* Mangle the function name appropriately. Note that we do
not mangle specializations of non-template member
functions of template classes, e.g. with
+
template <class T> struct S { void f(); }
+
and given the specialization
+
template <> void S<int>::f() {}
+
we do not mangle S<int>::f() here. That's because it's
just an ordinary member function and doesn't need special
- treatment. */
+ treatment. We do this here so that the ordinary,
+ non-template, name-mangling algorith will not be used
+ later. */
if ((is_member_template (tmpl) || ctype == NULL_TREE)
&& name_mangling_version >= 1)
- {
- tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
-
- if (ctype
- && TREE_CODE (TREE_TYPE (tmpl)) == FUNCTION_TYPE)
- arg_types =
- hash_tree_chain (build_pointer_type (ctype),
- arg_types);
-
- DECL_ASSEMBLER_NAME (decl)
- = build_template_decl_overload
- (decl, arg_types, TREE_TYPE (TREE_TYPE (tmpl)),
- DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
- targs, ctype != NULL_TREE);
- }
+ set_mangled_name_for_template_decl (decl);
if (is_friend && !have_def)
- {
- /* This is not really a declaration of a specialization.
- It's just the name of an instantiation. But, it's not
- a request for an instantiation, either. */
- SET_DECL_IMPLICIT_INSTANTIATION (decl);
- DECL_TEMPLATE_INFO (decl)
- = perm_tree_cons (tmpl, targs, NULL_TREE);
- return decl;
- }
+ /* This is not really a declaration of a specialization.
+ It's just the name of an instantiation. But, it's not
+ a request for an instantiation, either. */
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+
+ /* Register this specialization so that we can find it
+ again. */
+ decl = register_specialization (decl, gen_tmpl, targs);
+ }
+ }
+
+ return decl;
+}
- /* If DECL_TI_TEMPLATE (decl), the decl is an
- instantiation of a specialization of a member template.
- (In other words, there was a member template, in a
- class template. That member template was specialized.
- We then instantiated the class, so there is now an
- instance of that specialization.)
+/* TYPE is being declared. Verify that the use of template headers
+ and such is reasonable. Issue error messages if not. */
- According to the CD2,
+void
+maybe_check_template_type (type)
+ tree type;
+{
+ if (template_header_count)
+ {
+ /* We are in the scope of some `template <...>' header. */
- 14.7.3.13 [tmpl.expl.spec]
-
- A specialization of a member function template or
- member class template of a non-specialized class
- template is itself a template.
+ int context_depth
+ = template_class_depth_real (TYPE_CONTEXT (type),
+ /*count_specializations=*/1);
- So, we just leave the template info alone in this case. */
- if (!(DECL_TEMPLATE_INFO (decl) && DECL_TI_TEMPLATE (decl)))
- DECL_TEMPLATE_INFO (decl)
- = perm_tree_cons (tmpl, targs, NULL_TREE);
+ if (template_header_count <= context_depth)
+ /* This is OK; the template headers are for the context. We
+ are actually too lenient here; like
+ check_explicit_specialization we should consider the number
+ of template types included in the actual declaration. For
+ example,
- register_specialization (decl, tmpl, targs);
+ template <class T> struct S {
+ template <class U> template <class V>
+ struct I {};
+ };
- return decl;
- }
+ is illegal, but:
+
+ template <class T> struct S {
+ template <class U> struct I;
+ };
+
+ template <class T> template <class U.
+ struct S<T>::I {};
+
+ is not. */
+ ;
+ else if (template_header_count > context_depth + 1)
+ /* There are two many template parameter lists. */
+ cp_error ("too many template parameter lists in declaration of `%T'", type);
}
-
- return decl;
}
/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
@@ -1320,8 +1616,7 @@ int comp_template_parms (parms1, parms2)
if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM)
continue;
- else if (!comptypes (TREE_TYPE (parm1),
- TREE_TYPE (parm2), 1))
+ else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2)))
return 0;
}
}
@@ -1334,6 +1629,51 @@ int comp_template_parms (parms1, parms2)
return 1;
}
+/* Complain if DECL shadows a template parameter.
+
+ [temp.local]: A template-parameter shall not be redeclared within its
+ scope (including nested scopes). */
+
+void
+check_template_shadow (decl)
+ tree decl;
+{
+ tree olddecl;
+
+ /* If we're not in a template, we can't possibly shadow a template
+ parameter. */
+ if (!current_template_parms)
+ return;
+
+ /* Figure out what we're shadowing. */
+ if (TREE_CODE (decl) == OVERLOAD)
+ decl = OVL_CURRENT (decl);
+ olddecl = IDENTIFIER_VALUE (DECL_NAME (decl));
+
+ /* If there's no previous binding for this name, we're not shadowing
+ anything, let alone a template parameter. */
+ if (!olddecl)
+ return;
+
+ /* If we're not shadowing a template parameter, we're done. Note
+ that OLDDECL might be an OVERLOAD (or perhaps even an
+ ERROR_MARK), so we can't just blithely assume it to be a _DECL
+ node. */
+ if (TREE_CODE_CLASS (TREE_CODE (olddecl)) != 'd'
+ || !DECL_TEMPLATE_PARM_P (olddecl))
+ return;
+
+ /* We check for decl != olddecl to avoid bogus errors for using a
+ name inside a class. We check TPFI to avoid duplicate errors for
+ inline member templates. */
+ if (decl == olddecl
+ || TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
+ return;
+
+ cp_error_at ("declaration of `%#D'", decl);
+ cp_error_at (" shadows template parm `%#D'", olddecl);
+}
+
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
ORIG_LEVEL, DECL, and TYPE. */
@@ -1428,6 +1768,13 @@ process_template_parm (list, next)
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL_TREE);
+
+ /* [temp.param]
+
+ The top-level cv-qualifiers on the template-parameter are
+ ignored when determining its type. */
+ TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
if (IS_AGGR_TYPE (TREE_TYPE (parm))
@@ -1477,7 +1824,6 @@ process_template_parm (list, next)
decl = build_decl (TYPE_DECL, parm, t);
}
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
TYPE_NAME (t) = decl;
TYPE_STUB_DECL (t) = decl;
parm = decl;
@@ -1487,6 +1833,7 @@ process_template_parm (list, next)
decl, TREE_TYPE (parm));
}
SET_DECL_ARTIFICIAL (decl);
+ DECL_TEMPLATE_PARM_P (decl) = 1;
pushdecl (decl);
parm = build_tree_list (defval, parm);
return chainon (list, parm);
@@ -1535,26 +1882,34 @@ end_template_decl ()
(void) get_pending_sizes (); /* Why? */
}
-/* Generate a valid set of template args from current_template_parms. */
+/* Given a template argument vector containing the template PARMS.
+ The innermost PARMS are given first. */
tree
current_template_args ()
{
- tree header = current_template_parms;
- int length = list_length (header);
- tree args = make_tree_vec (length);
+ tree header;
+ tree args = NULL_TREE;
+ int length = TMPL_PARMS_DEPTH (current_template_parms);
int l = length;
- while (header)
+ /* If there is only one level of template parameters, we do not
+ create a TREE_VEC of TREE_VECs. Instead, we return a single
+ TREE_VEC containing the arguments. */
+ if (length > 1)
+ args = make_tree_vec (length);
+
+ for (header = current_template_parms; header; header = TREE_CHAIN (header))
{
tree a = copy_node (TREE_VALUE (header));
- int i = TREE_VEC_LENGTH (a);
+ int i;
+
TREE_TYPE (a) = NULL_TREE;
- while (i--)
+ for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
{
tree t = TREE_VEC_ELT (a, i);
- /* t will be a list if we are called from within a
+ /* T will be a list if we are called from within a
begin/end_template_parm_list pair, but a vector directly
if within a begin/end_member_template_processing pair. */
if (TREE_CODE (t) == TREE_LIST)
@@ -1566,18 +1921,19 @@ current_template_args ()
t = TREE_TYPE (t);
else
t = DECL_INITIAL (t);
+ TREE_VEC_ELT (a, i) = t;
}
-
- TREE_VEC_ELT (a, i) = t;
}
- TREE_VEC_ELT (args, --l) = a;
- header = TREE_CHAIN (header);
+
+ if (length > 1)
+ TREE_VEC_ELT (args, --l) = a;
+ else
+ args = a;
}
return args;
}
-
/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
template PARMS. Used by push_template_decl below. */
@@ -1592,8 +1948,8 @@ build_template_decl (decl, parms)
if (DECL_LANG_SPECIFIC (decl))
{
DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
- DECL_STATIC_FUNCTION_P (tmpl) =
- DECL_STATIC_FUNCTION_P (decl);
+ DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
+ DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
}
return tmpl;
@@ -1601,8 +1957,23 @@ build_template_decl (decl, parms)
struct template_parm_data
{
+ /* The level of the template parameters we are currently
+ processing. */
int level;
+
+ /* The index of the specialization argument we are currently
+ processing. */
+ int current_arg;
+
+ /* An array whose size is the number of template parameters. The
+ elements are non-zero if the parameter has been used in any one
+ of the arguments processed so far. */
int* parms;
+
+ /* An array whose size is the number of template arguments. The
+ elements are non-zero if the argument makes use of template
+ parameters of this level. */
+ int* arg_uses_template_parms;
};
/* Subroutine of push_template_decl used to see if each template
@@ -1632,13 +2003,296 @@ mark_template_parm (t, data)
}
if (level == tpd->level)
- tpd->parms[idx] = 1;
+ {
+ tpd->parms[idx] = 1;
+ tpd->arg_uses_template_parms[tpd->current_arg] = 1;
+ }
/* Return zero so that for_each_template_parm will continue the
traversal of the tree; we want to mark *every* template parm. */
return 0;
}
+/* Process the partial specialization DECL. */
+
+static tree
+process_partial_specialization (decl)
+ tree decl;
+{
+ tree type = TREE_TYPE (decl);
+ tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree specargs = CLASSTYPE_TI_ARGS (type);
+ tree inner_args = innermost_args (specargs);
+ tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
+ int nargs = TREE_VEC_LENGTH (inner_args);
+ int ntparms = TREE_VEC_LENGTH (inner_parms);
+ int i;
+ int did_error_intro = 0;
+ struct template_parm_data tpd;
+ struct template_parm_data tpd2;
+
+ /* We check that each of the template parameters given in the
+ partial specialization is used in the argument list to the
+ specialization. For example:
+
+ template <class T> struct S;
+ template <class T> struct S<T*>;
+
+ The second declaration is OK because `T*' uses the template
+ parameter T, whereas
+
+ template <class T> struct S<int>;
+
+ is no good. Even trickier is:
+
+ template <class T>
+ struct S1
+ {
+ template <class U>
+ struct S2;
+ template <class U>
+ struct S2<T>;
+ };
+
+ The S2<T> declaration is actually illegal; it is a
+ full-specialization. Of course,
+
+ template <class U>
+ struct S2<T (*)(U)>;
+
+ or some such would have been OK. */
+ tpd.level = TMPL_PARMS_DEPTH (current_template_parms);
+ tpd.parms = alloca (sizeof (int) * ntparms);
+ bzero ((PTR) tpd.parms, sizeof (int) * ntparms);
+
+ tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs);
+ bzero ((PTR) tpd.arg_uses_template_parms, sizeof (int) * nargs);
+ for (i = 0; i < nargs; ++i)
+ {
+ tpd.current_arg = i;
+ for_each_template_parm (TREE_VEC_ELT (inner_args, i),
+ &mark_template_parm,
+ &tpd);
+ }
+ for (i = 0; i < ntparms; ++i)
+ if (tpd.parms[i] == 0)
+ {
+ /* One of the template parms was not used in the
+ specialization. */
+ if (!did_error_intro)
+ {
+ cp_error ("template parameters not used in partial specialization:");
+ did_error_intro = 1;
+ }
+
+ cp_error (" `%D'",
+ TREE_VALUE (TREE_VEC_ELT (inner_parms, i)));
+ }
+
+ /* [temp.class.spec]
+
+ The argument list of the specialization shall not be identical to
+ the implicit argument list of the primary template. */
+ if (comp_template_args (inner_args,
+ innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE
+ (maintmpl)))))
+ cp_error ("partial specialization `%T' does not specialize any template arguments", type);
+
+ /* [temp.class.spec]
+
+ A partially specialized non-type argument expression shall not
+ involve template parameters of the partial specialization except
+ when the argument expression is a simple identifier.
+
+ The type of a template parameter corresponding to a specialized
+ non-type argument shall not be dependent on a parameter of the
+ specialization. */
+ my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0);
+ tpd2.parms = 0;
+ for (i = 0; i < nargs; ++i)
+ {
+ tree arg = TREE_VEC_ELT (inner_args, i);
+ if (/* These first two lines are the `non-type' bit. */
+ TREE_CODE_CLASS (TREE_CODE (arg)) != 't'
+ && TREE_CODE (arg) != TEMPLATE_DECL
+ /* This next line is the `argument expression is not just a
+ simple identifier' condition and also the `specialized
+ non-type argument' bit. */
+ && TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
+ {
+ if (tpd.arg_uses_template_parms[i])
+ cp_error ("template argument `%E' involves template parameter(s)", arg);
+ else
+ {
+ /* Look at the corresponding template parameter,
+ marking which template parameters its type depends
+ upon. */
+ tree type =
+ TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms,
+ i)));
+
+ if (!tpd2.parms)
+ {
+ /* We haven't yet initialized TPD2. Do so now. */
+ tpd2.arg_uses_template_parms
+ = (int*) alloca (sizeof (int) * nargs);
+ /* The number of parameters here is the number in the
+ main template, which, as checked in the assertion
+ above, is NARGS. */
+ tpd2.parms = (int*) alloca (sizeof (int) * nargs);
+ tpd2.level =
+ TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (maintmpl));
+ }
+
+ /* Mark the template parameters. But this time, we're
+ looking for the template parameters of the main
+ template, not in the specialization. */
+ tpd2.current_arg = i;
+ tpd2.arg_uses_template_parms[i] = 0;
+ bzero ((PTR) tpd2.parms, sizeof (int) * nargs);
+ for_each_template_parm (type,
+ &mark_template_parm,
+ &tpd2);
+
+ if (tpd2.arg_uses_template_parms [i])
+ {
+ /* The type depended on some template parameters.
+ If they are fully specialized in the
+ specialization, that's OK. */
+ int j;
+ for (j = 0; j < nargs; ++j)
+ if (tpd2.parms[j] != 0
+ && tpd.arg_uses_template_parms [j])
+ {
+ cp_error ("type `%T' of template argument `%E' depends on template parameter(s)",
+ type,
+ arg);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (retrieve_specialization (maintmpl, specargs))
+ /* We've already got this specialization. */
+ return decl;
+
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
+ = perm_tree_cons (inner_args, inner_parms,
+ DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+ TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+ return decl;
+}
+
+/* Check that a template declaration's use of default arguments is not
+ invalid. Here, PARMS are the template parameters. IS_PRIMARY is
+ non-zero if DECL is the thing declared by a primary template.
+ IS_PARTIAL is non-zero if DECL is a partial specialization. */
+
+static void
+check_default_tmpl_args (decl, parms, is_primary, is_partial)
+ tree decl;
+ tree parms;
+ int is_primary;
+ int is_partial;
+{
+ const char *msg;
+ int last_level_to_check;
+
+ /* [temp.param]
+
+ A default template-argument shall not be specified in a
+ function template declaration or a function template definition, nor
+ in the template-parameter-list of the definition of a member of a
+ class template. */
+
+ if (current_class_type
+ && !TYPE_BEING_DEFINED (current_class_type)
+ && DECL_LANG_SPECIFIC (decl)
+ /* If this is either a friend defined in the scope of the class
+ or a member function. */
+ && DECL_CLASS_CONTEXT (decl) == current_class_type
+ /* And, if it was a member function, it really was defined in
+ the scope of the class. */
+ && (!DECL_FUNCTION_MEMBER_P (decl) || DECL_DEFINED_IN_CLASS_P (decl)))
+ /* We already checked these parameters when the template was
+ declared, so there's no need to do it again now. This function
+ was defined in class scope, but we're processing it's body now
+ that the class is complete. */
+ return;
+
+ if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary)
+ /* For an ordinary class template, default template arguments are
+ allowed at the innermost level, e.g.:
+ template <class T = int>
+ struct S {};
+ but, in a partial specialization, they're not allowed even
+ there, as we have in [temp.class.spec]:
+
+ The template parameter list of a specialization shall not
+ contain default template argument values.
+
+ So, for a partial specialization, or for a function template,
+ we look at all of them. */
+ ;
+ else
+ /* But, for a primary class template that is not a partial
+ specialization we look at all template parameters except the
+ innermost ones. */
+ parms = TREE_CHAIN (parms);
+
+ /* Figure out what error message to issue. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ msg = "default argument for template parameter in function template `%D'";
+ else if (is_partial)
+ msg = "default argument in partial specialization `%D'";
+ else
+ msg = "default argument for template parameter for class enclosing `%D'";
+
+ if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
+ /* If we're inside a class definition, there's no need to
+ examine the parameters to the class itself. On the one
+ hand, they will be checked when the class is defined, and,
+ on the other, default arguments are legal in things like:
+ template <class T = double>
+ struct S { template <class U> void f(U); };
+ Here the default argument for `S' has no bearing on the
+ declaration of `f'. */
+ last_level_to_check = template_class_depth (current_class_type) + 1;
+ else
+ /* Check everything. */
+ last_level_to_check = 0;
+
+ for (; parms && TMPL_PARMS_DEPTH (parms) >= last_level_to_check;
+ parms = TREE_CHAIN (parms))
+ {
+ tree inner_parms = TREE_VALUE (parms);
+ int i, ntparms;
+
+ ntparms = TREE_VEC_LENGTH (inner_parms);
+ for (i = 0; i < ntparms; ++i)
+ if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
+ {
+ if (msg)
+ {
+ cp_error (msg, decl);
+ msg = 0;
+ }
+
+ /* Clear out the default argument so that we are not
+ confused later. */
+ TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
+ }
+
+ /* At this point, if we're still interested in issuing messages,
+ they must apply to classes surrounding the object declared. */
+ if (msg)
+ msg = "default argument for template parameter for class enclosing `%D'";
+ }
+}
+
/* Creates a TEMPLATE_DECL for the indicated DECL using the template
parameters given by current_template_args, or reuses a
previously existing one, if appropriate. Returns the DECL, or an
@@ -1656,6 +2310,12 @@ push_template_decl_real (decl, is_friend)
tree info;
tree ctx;
int primary;
+ int is_partial;
+
+ /* See if this is a partial specialization. */
+ is_partial = (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl));
@@ -1682,12 +2342,11 @@ push_template_decl_real (decl, is_friend)
/* For determining whether this is a primary template or not, we're really
interested in the lexical context, not the true context. */
if (is_friend)
- /* For a TYPE_DECL, there is no DECL_CLASS_CONTEXT. */
- info = TREE_CODE (decl) == FUNCTION_DECL
- ? DECL_CLASS_CONTEXT (decl) : current_class_type;
+ info = current_class_type;
else
info = ctx;
+ /* See if this is a primary template. */
if (info && TREE_CODE (info) == FUNCTION_DECL)
primary = 0;
/* Note that template_class_depth returns 0 if given NULL_TREE, so
@@ -1703,91 +2362,18 @@ push_template_decl_real (decl, is_friend)
cp_error ("template with C linkage");
if (TREE_CODE (decl) == TYPE_DECL && ANON_AGGRNAME_P (DECL_NAME (decl)))
cp_error ("template class without a name");
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ cp_error ("template declaration of `%#T'", TREE_TYPE (decl));
}
- /* Partial specialization. */
- if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- {
- tree type = TREE_TYPE (decl);
- tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
- tree mainargs = CLASSTYPE_TI_ARGS (type);
- tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl);
-
- /* We check that each of the template parameters given in the
- partial specialization is used in the argument list to the
- specialization. For example:
-
- template <class T> struct S;
- template <class T> struct S<T*>;
-
- The second declaration is OK because `T*' uses the template
- parameter T, whereas
-
- template <class T> struct S<int>;
-
- is no good. Even trickier is:
-
- template <class T>
- struct S1
- {
- template <class U>
- struct S2;
- template <class U>
- struct S2<T>;
- };
-
- The S2<T> declaration is actually illegal; it is a
- full-specialization. Of course,
-
- template <class U>
- struct S2<T (*)(U)>;
-
- or some such would have been OK. */
- int i;
- struct template_parm_data tpd;
- int ntparms = TREE_VEC_LENGTH (TREE_VALUE (current_template_parms));
- int did_error_intro = 0;
-
- tpd.level = TREE_INT_CST_HIGH (TREE_PURPOSE (current_template_parms));
- tpd.parms = alloca (sizeof (int) * ntparms);
- for (i = 0; i < ntparms; ++i)
- tpd.parms[i] = 0;
- for (i = 0; i < TREE_VEC_LENGTH (mainargs); ++i)
- for_each_template_parm (TREE_VEC_ELT (mainargs, i),
- &mark_template_parm,
- &tpd);
- for (i = 0; i < ntparms; ++i)
- if (tpd.parms[i] == 0)
- {
- /* One of the template parms was not used in the
- specialization. */
- if (!did_error_intro)
- {
- cp_error ("template parameters not used in partial specialization:");
- did_error_intro = 1;
- }
-
- cp_error (" `%D'",
- TREE_VALUE (TREE_VEC_ELT
- (TREE_VALUE (current_template_parms),
- i)));
- }
+ /* Check to see that the rules regarding the use of default
+ arguments are not being violated. */
+ check_default_tmpl_args (decl, current_template_parms,
+ primary, is_partial);
- for (; spec; spec = TREE_CHAIN (spec))
- {
- /* purpose: args to main template
- value: spec template */
- if (comp_template_args (TREE_PURPOSE (spec), mainargs))
- return decl;
- }
-
- DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type)
- = perm_tree_cons (mainargs, TREE_VALUE (current_template_parms),
- DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
- TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
- return decl;
- }
+ if (is_partial)
+ return process_partial_specialization (decl);
args = current_template_args ();
@@ -1817,18 +2403,19 @@ push_template_decl_real (decl, is_friend)
}
else
{
- tree t;
- tree a;
+ tree a, t, current, parms;
+ int i;
if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
cp_error ("must specialize `%#T' before defining member `%#D'",
ctx, decl);
if (TREE_CODE (decl) == TYPE_DECL)
{
- if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
- && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl))
- && CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)))
- tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
+ if ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (decl)))
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ && TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
+ && TYPE_TI_TEMPLATE (TREE_TYPE (decl)))
+ tmpl = TYPE_TI_TEMPLATE (TREE_TYPE (decl));
else
{
cp_error ("`%D' does not declare a template type", decl);
@@ -1843,93 +2430,78 @@ push_template_decl_real (decl, is_friend)
else
tmpl = DECL_TI_TEMPLATE (decl);
- if (is_member_template (tmpl) || is_member_template_class (tmpl))
+ if (is_member_template (tmpl)
+ && DECL_FUNCTION_TEMPLATE_P (tmpl)
+ && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl))
{
- if (DECL_FUNCTION_TEMPLATE_P (tmpl)
- && DECL_TEMPLATE_INFO (decl) && DECL_TI_ARGS (decl)
- && DECL_TEMPLATE_SPECIALIZATION (decl))
- {
- tree new_tmpl;
-
- /* The declaration is a specialization of a member
- template, declared outside the class. Therefore, the
- innermost template arguments will be NULL, so we
- replace them with the arguments determined by the
- earlier call to check_explicit_specialization. */
- args = DECL_TI_ARGS (decl);
-
- new_tmpl
- = build_template_decl (decl, current_template_parms);
- DECL_TEMPLATE_RESULT (new_tmpl) = decl;
- TREE_TYPE (new_tmpl) = TREE_TYPE (decl);
- DECL_TI_TEMPLATE (decl) = new_tmpl;
- SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
- DECL_TEMPLATE_INFO (new_tmpl) =
- perm_tree_cons (tmpl, args, NULL_TREE);
-
- register_specialization (new_tmpl, tmpl, args);
- return decl;
- }
-
- a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
- t = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
- if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
- {
- cp_error ("got %d template parameters for `%#D'",
- TREE_VEC_LENGTH (a), decl);
- cp_error (" but %d required", TREE_VEC_LENGTH (t));
- }
- if (TREE_VEC_LENGTH (args) > 1)
- /* Get the template parameters for the enclosing template
- class. */
- a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 2);
- else
- a = NULL_TREE;
+ tree new_tmpl;
+
+ /* The declaration is a specialization of a member
+ template, declared outside the class. Therefore, the
+ innermost template arguments will be NULL, so we
+ replace them with the arguments determined by the
+ earlier call to check_explicit_specialization. */
+ args = DECL_TI_ARGS (decl);
+
+ new_tmpl
+ = build_template_decl (decl, current_template_parms);
+ DECL_TEMPLATE_RESULT (new_tmpl) = decl;
+ TREE_TYPE (new_tmpl) = TREE_TYPE (decl);
+ DECL_TI_TEMPLATE (decl) = new_tmpl;
+ SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
+ DECL_TEMPLATE_INFO (new_tmpl) =
+ perm_tree_cons (tmpl, args, NULL_TREE);
+
+ register_specialization (new_tmpl, tmpl, args);
+ return decl;
}
- else
- a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
- t = NULL_TREE;
+ /* Make sure the template headers we got make sense. */
- if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+ parms = DECL_TEMPLATE_PARMS (tmpl);
+ i = TMPL_PARMS_DEPTH (parms);
+ if (TMPL_ARGS_DEPTH (args) != i)
{
- /* When processing an inline member template of a
- specialized class, there is no CLASSTYPE_TI_SPEC_INFO. */
- if (CLASSTYPE_TI_SPEC_INFO (ctx))
- t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
+ cp_error ("expected %d levels of template parms for `%#D', got %d",
+ i, decl, TMPL_ARGS_DEPTH (args));
}
- else if (CLASSTYPE_TEMPLATE_INFO (ctx))
- t = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
+ else
+ for (current = decl; i > 0; --i, parms = TREE_CHAIN (parms))
+ {
+ a = TMPL_ARGS_LEVEL (args, i);
+ t = INNERMOST_TEMPLATE_PARMS (parms);
- /* There should be template arguments if and only if there is a
- template class. */
- my_friendly_assert((a != NULL_TREE) == (t != NULL_TREE), 0);
+ if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
+ {
+ if (current == decl)
+ cp_error ("got %d template parameters for `%#D'",
+ TREE_VEC_LENGTH (a), decl);
+ else
+ cp_error ("got %d template parameters for `%#T'",
+ TREE_VEC_LENGTH (a), current);
+ cp_error (" but %d required", TREE_VEC_LENGTH (t));
+ }
- if (t != NULL_TREE
- && TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
- {
- cp_error ("got %d template parameters for `%#D'",
- TREE_VEC_LENGTH (a), decl);
- cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
- }
+ /* Perhaps we should also check that the parms are used in the
+ appropriate qualifying scopes in the declarator? */
+
+ if (current == decl)
+ current = ctx;
+ else
+ current = TYPE_CONTEXT (current);
+ }
}
- /* Get the innermost set of template arguments. We don't do this
- for a non-template member function of a nested template class
- because there we will never get a `partial instantiation' of the
- function containing the outer arguments, and so we must save all
- of the arguments here. */
- if (TREE_CODE (decl) != FUNCTION_DECL
- || template_class_depth (ctx) <= 1
- || primary)
- args = innermost_args (args, 0);
DECL_TEMPLATE_RESULT (tmpl) = decl;
TREE_TYPE (tmpl) = TREE_TYPE (decl);
- if (! ctx && !(is_friend && template_class_depth (info) > 0))
- /* Note that we do not try to push a global template friend
- declared in a template class; such a thing may well depend on
- the template parameters of the class. */
+ /* Push template declarations for global functions and types. Note
+ that we do not try to push a global template friend declared in a
+ template class; such a thing may well depend on the template
+ parameters of the class. */
+ if (! ctx
+ && !(is_friend && template_class_depth (current_class_type) > 0))
tmpl = pushdecl_namespace_level (tmpl);
if (primary)
@@ -1939,8 +2511,9 @@ push_template_decl_real (decl, is_friend)
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
{
- CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
- if (!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
+ SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
+ if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)
DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
else if (! DECL_LANG_SPECIFIC (decl))
@@ -1969,10 +2542,17 @@ redeclare_class_template (type, parms)
tree type;
tree parms;
{
- tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree tmpl;
tree tmpl_parms;
int i;
+ if (!TYPE_TEMPLATE_INFO (type))
+ {
+ cp_error ("`%T' is not a template type", type);
+ return;
+ }
+
+ tmpl = TYPE_TI_TEMPLATE (type);
if (!PRIMARY_TEMPLATE_P (tmpl))
/* The type is nested in some template class. Nothing to worry
about here; there are no new template parameters for the nested
@@ -2072,22 +2652,16 @@ convert_nontype_argument (type, expr)
Check this first since if expr_type is the unknown_type_node
we would otherwise complain below. */
;
- else if (INTEGRAL_TYPE_P (expr_type)
- || TYPE_PTRMEM_P (expr_type)
- || TYPE_PTRMEMFUNC_P (expr_type)
- /* The next two are g++ extensions. */
- || TREE_CODE (expr_type) == REAL_TYPE
- || TREE_CODE (expr_type) == COMPLEX_TYPE)
+ else if (TYPE_PTRMEM_P (expr_type)
+ || TYPE_PTRMEMFUNC_P (expr_type))
{
- if (! TREE_CONSTANT (expr))
- {
- non_constant:
- cp_error ("non-constant `%E' cannot be used as template argument",
- expr);
- return NULL_TREE;
- }
+ if (TREE_CODE (expr) != PTRMEM_CST)
+ goto bad_argument;
}
- else if (TYPE_PTR_P (expr_type)
+ else if (TYPE_PTR_P (expr_type)
+ || TYPE_PTRMEM_P (expr_type)
+ || TREE_CODE (expr_type) == ARRAY_TYPE
+ || TREE_CODE (type) == REFERENCE_TYPE
/* If expr is the address of an overloaded function, we
will get the unknown_type_node at this point. */
|| expr_type == unknown_type_node)
@@ -2096,21 +2670,33 @@ convert_nontype_argument (type, expr)
tree e = expr;
STRIP_NOPS (e);
- if (TREE_CODE (e) != ADDR_EXPR)
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ || TREE_CODE (expr_type) == ARRAY_TYPE)
+ referent = e;
+ else
{
- bad_argument:
- cp_error ("`%E' is not a valid template argument", expr);
- error ("it must be %s%s with external linkage",
- TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
- ? "a pointer to " : "",
- TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == FUNCTION_TYPE
- ? "a function" : "an object");
- return NULL_TREE;
+ if (TREE_CODE (e) != ADDR_EXPR)
+ {
+ bad_argument:
+ cp_error ("`%E' is not a valid template argument", expr);
+ if (TYPE_PTR_P (expr_type))
+ {
+ if (TREE_CODE (TREE_TYPE (expr_type)) == FUNCTION_TYPE)
+ cp_error ("it must be the address of a function with external linkage");
+ else
+ cp_error ("it must be the address of an object with external linkage");
+ }
+ else if (TYPE_PTRMEM_P (expr_type)
+ || TYPE_PTRMEMFUNC_P (expr_type))
+ cp_error ("it must be a pointer-to-member of the form `&X::Y'");
+
+ return NULL_TREE;
+ }
+
+ referent = TREE_OPERAND (e, 0);
+ STRIP_NOPS (referent);
}
- referent = TREE_OPERAND (e, 0);
- STRIP_NOPS (referent);
-
if (TREE_CODE (referent) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument",
@@ -2130,10 +2716,20 @@ convert_nontype_argument (type, expr)
return error_mark_node;
}
}
- else if (TREE_CODE (expr) == VAR_DECL)
+ else if (INTEGRAL_TYPE_P (expr_type)
+ || TYPE_PTRMEM_P (expr_type)
+ || TYPE_PTRMEMFUNC_P (expr_type)
+ /* The next two are g++ extensions. */
+ || TREE_CODE (expr_type) == REAL_TYPE
+ || TREE_CODE (expr_type) == COMPLEX_TYPE)
{
- if (!TREE_PUBLIC (expr))
- goto bad_argument;
+ if (! TREE_CONSTANT (expr))
+ {
+ non_constant:
+ cp_error ("non-constant `%E' cannot be used as template argument",
+ expr);
+ return NULL_TREE;
+ }
}
else
{
@@ -2157,7 +2753,7 @@ convert_nontype_argument (type, expr)
expr = digest_init (type, expr, (tree*) 0);
if (TREE_CODE (expr) != INTEGER_CST)
- /* Curiously, some TREE_CONSTNAT integral expressions do not
+ /* Curiously, some TREE_CONSTANT integral expressions do not
simplify to integer constants. For example, `3 % 0',
remains a TRUNC_MOD_EXPR. */
goto non_constant;
@@ -2182,10 +2778,24 @@ convert_nontype_argument (type, expr)
tree type_pointed_to = TREE_TYPE (type);
if (TYPE_PTRMEM_P (type))
- /* For a non-type template-parameter of type pointer to data
- member, qualification conversions (_conv.qual_) are
- applied. */
- return perform_qualification_conversions (type, expr);
+ {
+ tree e;
+
+ /* For a non-type template-parameter of type pointer to data
+ member, qualification conversions (_conv.qual_) are
+ applied. */
+ e = perform_qualification_conversions (type, expr);
+ if (TREE_CODE (e) == NOP_EXPR)
+ /* The call to perform_qualification_conversions will
+ insert a NOP_EXPR over EXPR to do express conversion,
+ if necessary. But, that will confuse us if we use
+ this (converted) template parameter to instantiate
+ another template; then the thing will not look like a
+ valid template argument. So, just make a new
+ constant, of the appropriate type. */
+ e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
+ return e;
+ }
else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
{
/* For a non-type template-parameter of type pointer to
@@ -2217,7 +2827,7 @@ convert_nontype_argument (type, expr)
expr = build_unary_op (ADDR_EXPR, fn, 0);
- my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1),
+ my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
0);
return expr;
}
@@ -2252,15 +2862,18 @@ convert_nontype_argument (type, expr)
if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
{
/* For a non-type template-parameter of type reference to
- function, no conversions apply. If the
- template-argument represents a set of overloaded
- functions, the matching function is selected from the
- set (_over.over_). */
+ function, no conversions apply. If the
+ template-argument represents a set of overloaded
+ functions, the matching function is selected from the
+ set (_over.over_). */
tree fns = expr;
tree fn;
fn = instantiate_type (type_referred_to, fns, 0);
+ if (fn == error_mark_node)
+ return error_mark_node;
+
if (!TREE_PUBLIC (fn))
{
if (really_overloaded_fn (fns))
@@ -2272,10 +2885,8 @@ convert_nontype_argument (type, expr)
goto bad_argument;
}
- if (fn == error_mark_node)
- return error_mark_node;
-
- my_friendly_assert (comptypes (type, TREE_TYPE (fn), 1),
+ my_friendly_assert (same_type_p (type_referred_to,
+ TREE_TYPE (fn)),
0);
return fn;
@@ -2288,12 +2899,10 @@ convert_nontype_argument (type, expr)
identical) type of the template-argument. The
template-parameter is bound directly to the
template-argument, which must be an lvalue. */
- if (!comptypes (TYPE_MAIN_VARIANT (expr_type),
- TYPE_MAIN_VARIANT (type), 1)
- || (TYPE_READONLY (expr_type) >
- TYPE_READONLY (type_referred_to))
- || (TYPE_VOLATILE (expr_type) >
- TYPE_VOLATILE (type_referred_to))
+ if ((TYPE_MAIN_VARIANT (expr_type)
+ != TYPE_MAIN_VARIANT (type_referred_to))
+ || !at_least_as_qualified_p (type_referred_to,
+ expr_type)
|| !real_lvalue_p (expr))
return error_mark_node;
else
@@ -2304,9 +2913,6 @@ convert_nontype_argument (type, expr)
case RECORD_TYPE:
{
- tree fns;
- tree fn;
-
if (!TYPE_PTRMEMFUNC_P (type))
/* This handles templates like
template<class T, T t> void f();
@@ -2325,10 +2931,10 @@ convert_nontype_argument (type, expr)
expr_type != unknown_type_node)
return error_mark_node;
- if (TREE_CODE (expr) == CONSTRUCTOR)
+ if (TREE_CODE (expr) == PTRMEM_CST)
{
/* A ptr-to-member constant. */
- if (!comptypes (type, expr_type, 1))
+ if (!same_type_p (type, expr_type))
return error_mark_node;
else
return expr;
@@ -2337,17 +2943,12 @@ convert_nontype_argument (type, expr)
if (TREE_CODE (expr) != ADDR_EXPR)
return error_mark_node;
- fns = TREE_OPERAND (expr, 0);
+ expr = instantiate_type (type, expr, 0);
- fn = instantiate_type (TREE_TYPE (TREE_TYPE (type)),
- fns, 0);
-
- if (fn == error_mark_node)
+ if (expr == error_mark_node)
return error_mark_node;
- expr = build_unary_op (ADDR_EXPR, fn, 0);
-
- my_friendly_assert (comptypes (type, TREE_TYPE (expr), 1),
+ my_friendly_assert (same_type_p (type, TREE_TYPE (expr)),
0);
return expr;
}
@@ -2380,8 +2981,11 @@ convert_nontype_argument (type, expr)
substitute the TT parameter. */
static int
-coerce_template_template_parms (parm_parms, arg_parms, in_decl, outer_args)
- tree parm_parms, arg_parms, in_decl, outer_args;
+coerce_template_template_parms (parm_parms, arg_parms, complain,
+ in_decl, outer_args)
+ tree parm_parms, arg_parms;
+ int complain;
+ tree in_decl, outer_args;
{
int nparms, nargs, i;
tree parm, arg;
@@ -2419,15 +3023,24 @@ coerce_template_template_parms (parm_parms, arg_parms, in_decl, outer_args)
/* We encounter instantiations of templates like
template <template <template <class> class> class TT>
class C; */
- sorry ("nested template template parameter");
- return 0;
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (!coerce_template_template_parms (parmparm, argparm,
+ complain, in_decl,
+ outer_args))
+ return 0;
+ }
+ break;
case PARM_DECL:
/* The tsubst call is used to handle cases such as
template <class T, template <T> class TT> class D;
i.e. the parameter list of TT depends on earlier parameters. */
- if (!comptypes (tsubst (TREE_TYPE (parm), outer_args, in_decl),
- TREE_TYPE (arg), 1))
+ if (!same_type_p (tsubst (TREE_TYPE (parm), outer_args,
+ complain, in_decl),
+ TREE_TYPE (arg)))
return 0;
break;
@@ -2438,36 +3051,229 @@ coerce_template_template_parms (parm_parms, arg_parms, in_decl, outer_args)
return 1;
}
-/* Convert all template arguments to their appropriate types, and return
- a vector containing the resulting values. If any error occurs, return
- error_mark_node, and, if COMPLAIN is non-zero, issue an error message.
- Some error messages are issued even if COMPLAIN is zero; for
- instance, if a template argument is composed from a local class.
+/* Convert the indicated template ARG as necessary to match the
+ indicated template PARM. Returns the converted ARG, or
+ error_mark_node if the conversion was unsuccessful. Error messages
+ are issued if COMPLAIN is non-zero. This conversion is for the Ith
+ parameter in the parameter list. ARGS is the full set of template
+ arguments deduced so far. */
+
+static tree
+convert_template_argument (parm, arg, args, complain, i, in_decl)
+ tree parm;
+ tree arg;
+ tree args;
+ int complain;
+ int i;
+ tree in_decl;
+{
+ tree val;
+ tree inner_args;
+ int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
+
+ inner_args = innermost_args (args);
+
+ if (TREE_CODE (arg) == TREE_LIST
+ && TREE_TYPE (arg) != NULL_TREE
+ && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+ {
+ /* The template argument was the name of some
+ member function. That's usually
+ illegal, but static members are OK. In any
+ case, grab the underlying fields/functions
+ and issue an error later if required. */
+ arg = TREE_VALUE (arg);
+ TREE_TYPE (arg) = unknown_type_node;
+ }
+
+ requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
+ requires_type = (TREE_CODE (parm) == TYPE_DECL
+ || requires_tmpl_type);
+
+ /* Check if it is a class template. If REQUIRES_TMPL_TYPE is true,
+ we also accept implicitly created TYPE_DECL as a valid argument.
+ This is necessary to handle the case where we pass a template name
+ to a template template parameter in a scope where we've derived from
+ in instantiation of that template, so the template name refers to that
+ instantiation. We really ought to handle this better. */
+ is_tmpl_type
+ = ((TREE_CODE (arg) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+ || (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ && !TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (arg))
+ || (TREE_CODE (arg) == RECORD_TYPE
+ && CLASSTYPE_TEMPLATE_INFO (arg)
+ && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
+ && DECL_ARTIFICIAL (TYPE_NAME (arg))
+ && requires_tmpl_type
+ && is_base_of_enclosing_class (arg, current_class_type)));
+ if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_STUB_DECL (arg);
+ else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
+ arg = CLASSTYPE_TI_TEMPLATE (arg);
+
+ is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || is_tmpl_type;
+
+ if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
+ && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
+ {
+ cp_pedwarn ("to refer to a type member of a template parameter,");
+ cp_pedwarn (" use `typename %E'", arg);
+
+ arg = make_typename_type (TREE_OPERAND (arg, 0),
+ TREE_OPERAND (arg, 1));
+ is_type = 1;
+ }
+ if (is_type != requires_type)
+ {
+ if (in_decl)
+ {
+ if (complain)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ if (is_type)
+ cp_error (" expected a constant of type `%T', got `%T'",
+ TREE_TYPE (parm),
+ (is_tmpl_type ? DECL_NAME (arg) : arg));
+ else
+ cp_error (" expected a type, got `%E'", arg);
+ }
+ }
+ return error_mark_node;
+ }
+ if (is_tmpl_type ^ requires_tmpl_type)
+ {
+ if (in_decl && complain)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ if (is_tmpl_type)
+ cp_error (" expected a type, got `%T'", DECL_NAME (arg));
+ else
+ cp_error (" expected a class template, got `%T'", arg);
+ }
+ return error_mark_node;
+ }
+
+ if (is_type)
+ {
+ if (requires_tmpl_type)
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (coerce_template_template_parms (parmparm, argparm, complain,
+ in_decl, inner_args))
+ {
+ val = arg;
+
+ /* TEMPLATE_TEMPLATE_PARM node is preferred over
+ TEMPLATE_DECL. */
+ if (val != error_mark_node
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+ val = TREE_TYPE (val);
+ }
+ else
+ {
+ if (in_decl && complain)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ cp_error (" expected a template of type `%D', got `%D'", parm, arg);
+ }
+
+ val = error_mark_node;
+ }
+ }
+ else
+ {
+ val = groktypename (arg);
+ if (! processing_template_decl)
+ {
+ /* [basic.link]: A name with no linkage (notably, the
+ name of a class or enumeration declared in a local
+ scope) shall not be used to declare an entity with
+ linkage. This implies that names with no linkage
+ cannot be used as template arguments. */
+ tree t = no_linkage_check (val);
+ if (t)
+ {
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+ cp_pedwarn
+ ("template-argument `%T' uses anonymous type", val);
+ else
+ cp_error
+ ("template-argument `%T' uses local type `%T'",
+ val, t);
+ return error_mark_node;
+ }
+ }
+ }
+ }
+ else
+ {
+ tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
+
+ if (processing_template_decl)
+ arg = maybe_fold_nontype_arg (arg);
+
+ if (!uses_template_parms (arg) && !uses_template_parms (t))
+ /* We used to call digest_init here. However, digest_init
+ will report errors, which we don't want when complain
+ is zero. More importantly, digest_init will try too
+ hard to convert things: for example, `0' should not be
+ converted to pointer type at this point according to
+ the standard. Accepting this is not merely an
+ extension, since deciding whether or not these
+ conversions can occur is part of determining which
+ function template to call, or whether a given epxlicit
+ argument specification is legal. */
+ val = convert_nontype_argument (t, arg);
+ else
+ val = arg;
+
+ if (val == NULL_TREE)
+ val = error_mark_node;
+ else if (val == error_mark_node && complain)
+ cp_error ("could not convert template argument `%E' to `%T'",
+ arg, t);
+ }
+
+ return val;
+}
+
+/* Convert all template arguments to their appropriate types, and
+ return a vector containing the innermost resulting template
+ arguments. If any error occurs, return error_mark_node, and, if
+ COMPLAIN is non-zero, issue an error message. Some error messages
+ are issued even if COMPLAIN is zero; for instance, if a template
+ argument is composed from a local class.
If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be
provided in ARGLIST, or else trailing parameters must have default
values. If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
- deduction for any unspecified trailing arguments. */
+ deduction for any unspecified trailing arguments.
+
+ The resulting TREE_VEC is allocated on a temporary obstack, and
+ must be explicitly copied if it will be permanent. */
static tree
-coerce_template_parms (parms, arglist, in_decl,
+coerce_template_parms (parms, args, in_decl,
complain,
require_all_arguments)
- tree parms, arglist;
+ tree parms, args;
tree in_decl;
int complain;
int require_all_arguments;
{
int nparms, nargs, i, lost = 0;
- tree vec = NULL_TREE;
-
- if (arglist == NULL_TREE)
- nargs = 0;
- else if (TREE_CODE (arglist) == TREE_VEC)
- nargs = TREE_VEC_LENGTH (arglist);
- else
- nargs = list_length (arglist);
+ tree inner_args;
+ tree new_args;
+ tree new_inner_args;
+ inner_args = innermost_args (args);
+ nargs = NUM_TMPL_ARGS (inner_args);
nparms = TREE_VEC_LENGTH (parms);
if (nargs > nparms
@@ -2477,253 +3283,96 @@ coerce_template_parms (parms, arglist, in_decl,
{
if (complain)
{
- error ("incorrect number of parameters (%d, should be %d)",
- nargs, nparms);
+ cp_error ("wrong number of template arguments (%d, should be %d)",
+ nargs, nparms);
if (in_decl)
- cp_error_at ("in template expansion for decl `%D'",
- in_decl);
+ cp_error_at ("provided for `%D'", in_decl);
}
return error_mark_node;
}
- if (arglist && TREE_CODE (arglist) == TREE_VEC && nargs == nparms)
- vec = copy_node (arglist);
- else
+ new_inner_args = make_temp_vec (nparms);
+ new_args = add_outermost_template_args (args, new_inner_args);
+ for (i = 0; i < nparms; i++)
{
- vec = make_tree_vec (nparms);
-
- for (i = 0; i < nparms; i++)
- {
- tree arg;
- tree parm = TREE_VEC_ELT (parms, i);
+ tree arg;
+ tree parm;
- if (arglist && TREE_CODE (arglist) == TREE_LIST)
- {
- arg = arglist;
- arglist = TREE_CHAIN (arglist);
-
- if (arg == error_mark_node)
- lost++;
- else
- arg = TREE_VALUE (arg);
- }
- else if (i < nargs)
- {
- arg = TREE_VEC_ELT (arglist, i);
- if (arg == error_mark_node)
- lost++;
- }
- else if (TREE_PURPOSE (parm) == NULL_TREE)
- {
- my_friendly_assert (!require_all_arguments, 0);
- break;
- }
- else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
- arg = tsubst (TREE_PURPOSE (parm), vec, in_decl);
- else
- arg = tsubst_expr (TREE_PURPOSE (parm), vec, in_decl);
+ /* Get the Ith template parameter. */
+ parm = TREE_VEC_ELT (parms, i);
- TREE_VEC_ELT (vec, i) = arg;
+ /* Calculate the Ith argument. */
+ if (inner_args && TREE_CODE (inner_args) == TREE_LIST)
+ {
+ arg = TREE_VALUE (inner_args);
+ inner_args = TREE_CHAIN (inner_args);
}
- }
- for (i = 0; i < nparms; i++)
- {
- tree arg = TREE_VEC_ELT (vec, i);
- tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
- tree val = 0;
- int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
+ else if (i < nargs)
+ arg = TREE_VEC_ELT (inner_args, i);
+ /* If no template argument was supplied, look for a default
+ value. */
+ else if (TREE_PURPOSE (parm) == NULL_TREE)
+ {
+ /* There was no default value. */
+ my_friendly_assert (!require_all_arguments, 0);
+ break;
+ }
+ else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
+ arg = tsubst (TREE_PURPOSE (parm), new_args, complain, in_decl);
+ else
+ arg = tsubst_expr (TREE_PURPOSE (parm), new_args, complain,
+ in_decl);
+ /* Now, convert the Ith argument, as necessary. */
if (arg == NULL_TREE)
/* We're out of arguments. */
{
my_friendly_assert (!require_all_arguments, 0);
break;
}
-
- if (arg == error_mark_node)
+ else if (arg == error_mark_node)
{
cp_error ("template argument %d is invalid", i + 1);
- lost++;
- continue;
- }
-
- if (TREE_CODE (arg) == TREE_LIST
- && TREE_TYPE (arg) != NULL_TREE
- && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
- {
- /* The template argument was the name of some
- member function. That's usually
- illegal, but static members are OK. In any
- case, grab the underlying fields/functions
- and issue an error later if required. */
- arg = TREE_VALUE (arg);
- TREE_TYPE (arg) = unknown_type_node;
- }
-
- requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
- requires_type = TREE_CODE (parm) == TYPE_DECL
- || requires_tmpl_type;
-
- /* Check if it is a class template. If REQUIRES_TMPL_TYPE is true,
- we also accept implicitly created TYPE_DECL as a valid argument.
- This is necessary to handle the case where we pass a template name
- to a template template parameter in a scope where we've derived from
- in instantiation of that template, so the template name refers to that
- instantiation. We really ought to handle this better. */
- is_tmpl_type = (TREE_CODE (arg) == TEMPLATE_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
- || (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
- && !CLASSTYPE_TEMPLATE_INFO (arg))
- || (TREE_CODE (arg) == RECORD_TYPE
- && CLASSTYPE_TEMPLATE_INFO (arg)
- && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
- && DECL_ARTIFICIAL (TYPE_NAME (arg))
- && requires_tmpl_type
- && current_class_type
- /* FIXME what about nested types? */
- && get_binfo (arg, current_class_type, 0));
- if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- arg = TYPE_STUB_DECL (arg);
- else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
- arg = CLASSTYPE_TI_TEMPLATE (arg);
-
- is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || is_tmpl_type;
-
- if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
- && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
- {
- cp_pedwarn ("to refer to a type member of a template parameter,");
- cp_pedwarn (" use `typename %E'", arg);
-
- arg = make_typename_type (TREE_OPERAND (arg, 0),
- TREE_OPERAND (arg, 1));
- is_type = 1;
- }
- if (is_type != requires_type)
- {
- if (in_decl)
- {
- if (complain)
- {
- cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
- if (is_type)
- cp_error (" expected a constant of type `%T', got `%T'",
- TREE_TYPE (parm),
- (is_tmpl_type ? DECL_NAME (arg) : arg));
- else
- cp_error (" expected a type, got `%E'", arg);
- }
- }
- lost++;
- TREE_VEC_ELT (vec, i) = error_mark_node;
- continue;
- }
- if (is_tmpl_type ^ requires_tmpl_type)
- {
- if (in_decl && complain)
- {
- cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
- if (is_tmpl_type)
- cp_error (" expected a type, got `%T'", DECL_NAME (arg));
- else
- cp_error (" expected a class template, got `%T'", arg);
- }
- lost++;
- TREE_VEC_ELT (vec, i) = error_mark_node;
- continue;
- }
-
- if (is_type)
- {
- if (requires_tmpl_type)
- {
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
- if (coerce_template_template_parms (parmparm, argparm,
- in_decl, vec))
- {
- val = arg;
-
- /* TEMPLATE_TEMPLATE_PARM node is preferred over
- TEMPLATE_DECL. */
- if (val != error_mark_node
- && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
- val = TREE_TYPE (val);
- }
- else
- {
- if (in_decl && complain)
- {
- cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
- cp_error (" expected a template of type `%D', got `%D'", parm, arg);
- }
-
- val = error_mark_node;
- }
- }
- else
- {
- val = groktypename (arg);
- if (! processing_template_decl)
- {
- tree t = target_type (val);
- if (((IS_AGGR_TYPE (t) && TREE_CODE (t) != TYPENAME_TYPE)
- || TREE_CODE (t) == ENUMERAL_TYPE)
- && decl_function_context (TYPE_MAIN_DECL (t)))
- {
- cp_error ("type `%T' composed from a local type is not a valid template-argument",
- val);
- return error_mark_node;
- }
- }
- }
- }
- else
- {
- tree t = tsubst (TREE_TYPE (parm), vec, in_decl);
-
- if (processing_template_decl)
- arg = maybe_fold_nontype_arg (arg);
-
- if (!uses_template_parms (arg) && !uses_template_parms (t))
- /* We used to call digest_init here. However, digest_init
- will report errors, which we don't want when complain
- is zero. More importantly, digest_init will try too
- hard to convert things: for example, `0' should not be
- converted to pointer type at this point according to
- the standard. Accepting this is not merely an
- extension, since deciding whether or not these
- conversions can occur is part of determining which
- function template to call, or whether a given epxlicit
- argument specification is legal. */
- val = convert_nontype_argument (t, arg);
- else
- val = arg;
-
- if (val == NULL_TREE)
- val = error_mark_node;
- else if (val == error_mark_node && complain)
- cp_error ("could not convert template argument `%E' to `%T'",
- arg, t);
+ arg = error_mark_node;
}
-
- if (val == error_mark_node)
+ else
+ arg = convert_template_argument (TREE_VALUE (parm),
+ arg, new_args, complain, i,
+ in_decl);
+
+ if (arg == error_mark_node)
lost++;
-
- TREE_VEC_ELT (vec, i) = val;
+ TREE_VEC_ELT (new_inner_args, i) = arg;
}
+
if (lost)
return error_mark_node;
- return vec;
+
+ return new_inner_args;
+}
+
+/* Returns 1 if template args OT and NT are equivalent. */
+
+static int
+template_args_equal (ot, nt)
+ tree ot, nt;
+{
+ if (nt == ot)
+ return 1;
+ if (TREE_CODE (nt) != TREE_CODE (ot))
+ return 0;
+ if (TREE_CODE (nt) == TREE_VEC)
+ /* For member templates */
+ return comp_template_args (ot, nt);
+ else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
+ return same_type_p (ot, nt);
+ else
+ return (cp_tree_equal (ot, nt) > 0);
}
-/* Renturns 1 iff the OLDARGS and NEWARGS are in fact identical sets
+/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets
of template arguments. Returns 0 otherwise. */
int
@@ -2740,24 +3389,8 @@ comp_template_args (oldargs, newargs)
tree nt = TREE_VEC_ELT (newargs, i);
tree ot = TREE_VEC_ELT (oldargs, i);
- if (nt == ot)
- continue;
- if (TREE_CODE (nt) != TREE_CODE (ot))
+ if (! template_args_equal (ot, nt))
return 0;
- if (TREE_CODE (nt) == TREE_VEC)
- {
- /* For member templates */
- if (comp_template_args (nt, ot))
- continue;
- }
- else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
- {
- if (comptypes (ot, nt, 1))
- continue;
- }
- else if (cp_tree_equal (ot, nt) > 0)
- continue;
- return 0;
}
return 1;
}
@@ -2766,10 +3399,9 @@ comp_template_args (oldargs, newargs)
for the instantiation. */
static char *
-mangle_class_name_for_template (name, parms, arglist, ctx)
+mangle_class_name_for_template (name, parms, arglist)
char *name;
tree parms, arglist;
- tree ctx;
{
static struct obstack scratch_obstack;
static char *scratch_firstobj;
@@ -2781,37 +3413,13 @@ mangle_class_name_for_template (name, parms, arglist, ctx)
obstack_free (&scratch_obstack, scratch_firstobj);
scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
-#if 0
-#define buflen sizeof(buf)
-#define check if (bufp >= buf+buflen-1) goto too_long
-#define ccat(c) *bufp++=(c); check
-#define advance bufp+=strlen(bufp); check
-#define cat(s) strncpy(bufp, s, buf+buflen-bufp-1); advance
-#else
-#define check
#define ccat(c) obstack_1grow (&scratch_obstack, (c));
-#define advance
#define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s))
-#endif
-
- if (ctx && ctx != global_namespace)
- {
- char* s;
- if (TREE_CODE (ctx) == FUNCTION_DECL)
- s = fndecl_as_string (ctx, 0);
- else if (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't')
- s = type_as_string_real (ctx, 0, 1);
- else if (TREE_CODE (ctx) == NAMESPACE_DECL)
- s = decl_as_string (ctx, 0);
- else
- my_friendly_abort (0);
- cat (s);
- cat ("::");
- }
cat (name);
ccat ('<');
nparms = TREE_VEC_LENGTH (parms);
+ arglist = innermost_args (arglist);
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++)
{
@@ -2874,13 +3482,6 @@ mangle_class_name_for_template (name, parms, arglist, ctx)
ccat ('>');
ccat ('\0');
return (char *) obstack_base (&scratch_obstack);
-
-#if 0
- too_long:
-#endif
- fatal ("out of (preallocated) string space creating template instantiation name");
- /* NOTREACHED */
- return NULL;
}
static tree
@@ -2888,28 +3489,28 @@ classtype_mangled_name (t)
tree t;
{
if (CLASSTYPE_TEMPLATE_INFO (t)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
- {
- tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
- /* We do not pass in the context here since that is only needed
- when mangling the name of instantiations, not the primary
- template declaration. In reality, it should not be needed
- then either, but the way lookup_template_class operates
- requires the context for the moment. In the long run,
- lookup_template_class should not be looking for existing
- instantiations by matching mangled names, but rather by
- matching the templates, and then scanning the instantiation
- list. */
- char *mangled_name = mangle_class_name_for_template
- (IDENTIFIER_POINTER (name),
- DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
- CLASSTYPE_TI_ARGS (t), NULL_TREE);
- tree id = get_identifier (mangled_name);
- IDENTIFIER_TEMPLATE (id) = name;
- return id;
+ /* Specializations have already had their names set up in
+ lookup_template_class. */
+ && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+ {
+ tree tmpl = most_general_template (CLASSTYPE_TI_TEMPLATE (t));
+
+ /* For non-primary templates, the template parameters are
+ implicit from their surrounding context. */
+ if (PRIMARY_TEMPLATE_P (tmpl))
+ {
+ tree name = DECL_NAME (tmpl);
+ char *mangled_name = mangle_class_name_for_template
+ (IDENTIFIER_POINTER (name),
+ DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ CLASSTYPE_TI_ARGS (t));
+ tree id = get_identifier (mangled_name);
+ IDENTIFIER_TEMPLATE (id) = name;
+ return id;
+ }
}
- else
- return TYPE_IDENTIFIER (t);
+
+ return TYPE_IDENTIFIER (t);
}
static void
@@ -2949,14 +3550,14 @@ lookup_template_function (fns, arglist)
return error_mark_node;
}
- if (arglist != NULL_TREE && !TREE_PERMANENT (arglist))
- copy_to_permanent (arglist);
-
type = TREE_TYPE (fns);
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
- return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
+ if (processing_template_decl)
+ return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
+ else
+ return build (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
@@ -2966,13 +3567,14 @@ lookup_template_function (fns, arglist)
return the associated TEMPLATE_DECL. Otherwise, the original
DECL is returned. */
-tree
+static tree
maybe_get_template_decl_from_type_decl (decl)
tree decl;
{
return (decl != NULL_TREE
&& TREE_CODE (decl) == TYPE_DECL
&& DECL_ARTIFICIAL (decl)
+ && CLASS_TYPE_P (TREE_TYPE (decl))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
}
@@ -2981,37 +3583,43 @@ maybe_get_template_decl_from_type_decl (decl)
parameters, find the desired type.
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
- Since ARGLIST is build on the decl_obstack, we must copy it here
- to keep it from being reclaimed when the decl storage is reclaimed.
+ (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC. It will
+ be a TREE_LIST if called directly from the parser, and a TREE_VEC
+ otherwise.) Since ARGLIST is build on the decl_obstack, we must
+ copy it here to keep it from being reclaimed when the decl storage
+ is reclaimed.
IN_DECL, if non-NULL, is the template declaration we are trying to
instantiate.
+ If ENTERING_SCOPE is non-zero, we are about to enter the scope of
+ the class we are looking up.
+
If the template class is really a local class in a template
function, then the FUNCTION_CONTEXT is the function in which it is
being instantiated. */
tree
-lookup_template_class (d1, arglist, in_decl, context)
+lookup_template_class (d1, arglist, in_decl, context, entering_scope)
tree d1, arglist;
tree in_decl;
tree context;
+ int entering_scope;
{
tree template = NULL_TREE, parmlist;
- char *mangled_name;
- tree id, t;
+ tree t;
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
- if (IDENTIFIER_LOCAL_VALUE (d1)
- && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_LOCAL_VALUE (d1)))
- template = IDENTIFIER_LOCAL_VALUE (d1);
+ if (IDENTIFIER_VALUE (d1)
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
+ template = IDENTIFIER_VALUE (d1);
else
{
if (context)
push_decl_namespace (context);
if (current_class_type != NULL_TREE)
- template =
+ template =
maybe_get_template_decl_from_type_decl
(IDENTIFIER_CLASS_VALUE (d1));
if (template == NULL_TREE)
@@ -3024,14 +3632,24 @@ lookup_template_class (d1, arglist, in_decl, context)
}
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{
- if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)) == NULL_TREE)
- return error_mark_node;
- template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
- d1 = DECL_NAME (template);
+ tree type = TREE_TYPE (d1);
+
+ /* If we are declaring a constructor, say A<T>::A<T>, we will get
+ an implicit typename for the second A. Deal with it. */
+ if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+ type = TREE_TYPE (type);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type))
+ {
+ template = CLASSTYPE_TI_TEMPLATE (type);
+ d1 = DECL_NAME (template);
+ }
}
- else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
+ else if (TREE_CODE (d1) == ENUMERAL_TYPE
+ || (TREE_CODE_CLASS (TREE_CODE (d1)) == 't'
+ && IS_AGGR_TYPE (d1)))
{
- template = CLASSTYPE_TI_TEMPLATE (d1);
+ template = TYPE_TI_TEMPLATE (d1);
d1 = DECL_NAME (template);
}
else if (TREE_CODE (d1) == TEMPLATE_DECL
@@ -3045,11 +3663,15 @@ lookup_template_class (d1, arglist, in_decl, context)
my_friendly_abort (272);
/* With something like `template <class T> class X class X { ... };'
- we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE.
- We don't want to do that, but we have to deal with the situation, so
- let's give them some syntax errors to chew on instead of a crash. */
+ we could end up with D1 having nothing but an IDENTIFIER_VALUE.
+ We don't want to do that, but we have to deal with the situation,
+ so let's give them some syntax errors to chew on instead of a
+ crash. */
if (! template)
- return error_mark_node;
+ {
+ cp_error ("`%T' is not a template", d1);
+ return error_mark_node;
+ }
if (context == NULL_TREE)
context = global_namespace;
@@ -3071,7 +3693,6 @@ lookup_template_class (d1, arglist, in_decl, context)
tree template2 = TYPE_STUB_DECL (parm);
tree arglist2;
- CLASSTYPE_GOT_SEMICOLON (parm) = 1;
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
arglist2 = coerce_template_parms (parmlist, arglist, template, 1, 1);
@@ -3079,166 +3700,307 @@ lookup_template_class (d1, arglist, in_decl, context)
return error_mark_node;
arglist2 = copy_to_permanent (arglist2);
- CLASSTYPE_TEMPLATE_INFO (parm)
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm)
= perm_tree_cons (template2, arglist2, NULL_TREE);
TYPE_SIZE (parm) = 0;
return parm;
}
- else if (PRIMARY_TEMPLATE_P (template)
- || (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template)))
- == FUNCTION_DECL))
+ else
{
- tree arglist_for_mangling;
+ tree template_type = TREE_TYPE (template);
+ tree gen_tmpl;
+ tree type_decl;
+ tree found = NULL_TREE;
+ int arg_depth;
+ int parm_depth;
+ int is_partial_instantiation;
- parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+ gen_tmpl = most_general_template (template);
+ parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
+ parm_depth = TMPL_PARMS_DEPTH (parmlist);
+ arg_depth = TMPL_ARGS_DEPTH (arglist);
- if (/* ARGLIST can be NULL_TREE if there are default arguments. */
- arglist != NULL_TREE
- && TREE_CODE (arglist) == TREE_VEC
- && TREE_VEC_LENGTH (arglist) > 1
- && list_length (DECL_TEMPLATE_PARMS (template)) > 1)
+ /* We build up the coerced arguments and such on the
+ momentary_obstack. */
+ push_momentary ();
+
+ if (arg_depth == 1 && parm_depth > 1)
+ {
+ /* We've been given an incomplete set of template arguments.
+ For example, given:
+
+ template <class T> struct S1 {
+ template <class U> struct S2 {};
+ template <class U> struct S2<U*> {};
+ };
+
+ we will be called with an ARGLIST of `U*', but the
+ TEMPLATE will be `template <class T> template
+ <class U> struct S1<T>::S2'. We must fill in the missing
+ arguments. */
+ arglist
+ = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (template)),
+ arglist);
+ arg_depth = TMPL_ARGS_DEPTH (arglist);
+ }
+
+ /* Now we should enough arguments. */
+ my_friendly_assert (parm_depth == arg_depth, 0);
+
+ /* From here on, we're only interested in the most general
+ template. */
+ template = gen_tmpl;
+
+ /* Calculate the BOUND_ARGS. These will be the args that are
+ actually tsubst'd into the definition to create the
+ instantiation. */
+ if (parm_depth > 1)
{
/* We have multiple levels of arguments to coerce, at once. */
- tree new_args =
- make_tree_vec (list_length (DECL_TEMPLATE_PARMS (template)));
int i;
+ int saved_depth = TMPL_ARGS_DEPTH (arglist);
+
+ tree bound_args = make_temp_vec (parm_depth);
- for (i = TREE_VEC_LENGTH (arglist) - 1,
+ for (i = saved_depth,
t = DECL_TEMPLATE_PARMS (template);
- i >= 0 && t != NULL_TREE;
+ i > 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t))
- TREE_VEC_ELT (new_args, i) =
- coerce_template_parms (TREE_VALUE (t),
- TREE_VEC_ELT (arglist, i),
- template, 1, 1);
- arglist = new_args;
+ {
+ tree a = coerce_template_parms (TREE_VALUE (t),
+ arglist, template, 1, 1);
+ SET_TMPL_ARGS_LEVEL (bound_args, i, a);
+
+ /* We temporarily reduce the length of the ARGLIST so
+ that coerce_template_parms will see only the arguments
+ corresponding to the template parameters it is
+ examining. */
+ TREE_VEC_LENGTH (arglist)--;
+ }
+
+ /* Restore the ARGLIST to its full size. */
+ TREE_VEC_LENGTH (arglist) = saved_depth;
+
+ arglist = bound_args;
}
else
- arglist = coerce_template_parms (parmlist,
- innermost_args (arglist, 0),
- template, 1, 1);
- if (arglist == error_mark_node)
+ arglist
+ = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
+ innermost_args (arglist),
+ template, 1, 1);
+
+ if (arglist == error_mark_node)
+ /* We were unable to bind the arguments. */
return error_mark_node;
- if (uses_template_parms (arglist))
+
+ /* In the scope of a template class, explicit references to the
+ template class refer to the type of the template, not any
+ instantiation of it. For example, in:
+
+ template <class T> class C { void f(C<T>); }
+
+ the `C<T>' is just the same as `C'. Outside of the
+ class, however, such a reference is an instantiation. */
+ if (comp_template_args (TYPE_TI_ARGS (template_type),
+ arglist))
{
- tree found;
- if (comp_template_args
- (CLASSTYPE_TI_ARGS (TREE_TYPE (template)), arglist))
- found = TREE_TYPE (template);
- else
+ found = template_type;
+
+ if (!entering_scope && PRIMARY_TEMPLATE_P (template))
{
- for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
- found; found = TREE_CHAIN (found))
- {
- if (TI_USES_TEMPLATE_PARMS (found)
- && comp_template_args (TREE_PURPOSE (found), arglist))
- break;
- }
- if (found)
- found = TREE_VALUE (found);
+ tree ctx;
+
+ /* Note that we use DECL_CONTEXT, rather than
+ CP_DECL_CONTEXT, so that the termination test is
+ always just `ctx'. We're not interested in namepace
+ scopes. */
+ for (ctx = current_class_type;
+ ctx;
+ ctx = (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't')
+ ? TYPE_CONTEXT (ctx) : DECL_CONTEXT (ctx))
+ if (same_type_p (ctx, template_type))
+ break;
+
+ if (!ctx)
+ /* We're not in the scope of the class, so the
+ TEMPLATE_TYPE is not the type we want after
+ all. */
+ found = NULL_TREE;
}
+ }
+
+ if (!found)
+ {
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ if (comp_template_args (TREE_PURPOSE (found), arglist))
+ break;
if (found)
- {
- if (can_free (&permanent_obstack, arglist))
- obstack_free (&permanent_obstack, arglist);
- return found;
- }
+ found = TREE_VALUE (found);
+ }
+
+ if (found)
+ {
+ pop_momentary ();
+ return found;
}
- if (TREE_CODE (arglist) == TREE_VEC)
- arglist_for_mangling = innermost_args (arglist, 0);
+ /* Since we didn't find the type, we'll have to create it.
+ Since we'll be saving this type on the
+ DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+
+ /* This type is a "partial instantiation" if any of the template
+ arguments still inolve template parameters. Note that we set
+ IS_PARTIAL_INSTANTIATION for partial specializations as
+ well. */
+ is_partial_instantiation = uses_template_parms (arglist);
+
+ /* Create the type. */
+ if (TREE_CODE (template_type) == ENUMERAL_TYPE)
+ {
+ if (!is_partial_instantiation)
+ t = start_enum (TYPE_IDENTIFIER (template_type));
+ else
+ /* We don't want to call start_enum for this type, since
+ the values for the enumeration constants may involve
+ template parameters. And, no one should be interested
+ in the enumeration constants for such a type. */
+ t = make_node (ENUMERAL_TYPE);
+ }
else
- arglist_for_mangling = arglist;
-
- /* FIXME avoid duplication. */
- mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
- parmlist,
- arglist_for_mangling,
- context);
- id = get_identifier (mangled_name);
- IDENTIFIER_TEMPLATE (id) = d1;
-
- maybe_push_to_top_level (uses_template_parms (arglist));
- t = xref_tag_from_type (TREE_TYPE (template), id, 1);
-
- if (context != NULL_TREE)
{
- /* Set up the context for the type_decl correctly. Note
- that we must clear DECL_ASSEMBLER_NAME to fool
- build_overload_name into creating a new name. */
- tree type_decl = TYPE_STUB_DECL (t);
-
- TYPE_CONTEXT (t) = FROB_CONTEXT (context);
- DECL_CONTEXT (type_decl) = FROB_CONTEXT (context);
- DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
- DECL_ASSEMBLER_NAME (type_decl) =
- get_identifier (build_overload_name (t, 1, 1));
+ t = make_lang_type (TREE_CODE (template_type));
+ CLASSTYPE_DECLARED_CLASS (t)
+ = CLASSTYPE_DECLARED_CLASS (template_type);
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+ SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
+ TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA (template_type);
}
- pop_from_top_level ();
- }
- else
- {
- tree type_ctx = TYPE_CONTEXT (TREE_TYPE (template));
- tree args = tsubst (CLASSTYPE_TI_ARGS (type_ctx), arglist, in_decl);
- tree ctx = lookup_template_class (type_ctx, args,
- in_decl, NULL_TREE);
- id = d1;
- arglist = CLASSTYPE_TI_ARGS (ctx);
-
- if (TYPE_BEING_DEFINED (ctx) && ctx == current_class_type)
+ /* If we called start_enum above, this information will already
+ be set up. */
+ if (!TYPE_NAME (t))
{
- int save_temp = processing_template_decl;
- processing_template_decl = 0;
- t = xref_tag_from_type (TREE_TYPE (template), id, 0);
- processing_template_decl = save_temp;
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+
+ /* Create a stub TYPE_DECL for it. */
+ type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
+ SET_DECL_ARTIFICIAL (type_decl);
+ DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
+ DECL_SOURCE_FILE (type_decl)
+ = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
+ DECL_SOURCE_LINE (type_decl)
+ = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
+ TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
}
else
+ type_decl = TYPE_NAME (t);
+
+ /* Set up the template information. We have to figure out which
+ template is the immediate parent if this is a full
+ instantiation. */
+ if (parm_depth == 1 || is_partial_instantiation
+ || !PRIMARY_TEMPLATE_P (template))
+ /* This case is easy; there are no member templates involved. */
+ found = template;
+ else
{
- t = lookup_nested_type_by_name (ctx, id);
- my_friendly_assert (t != NULL_TREE, 42);
- }
- }
+ /* This is a full instantiation of a member template. There
+ should be some partial instantiation of which this is an
+ instance. */
- /* Seems to be wanted. */
- CLASSTYPE_GOT_SEMICOLON (t) = 1;
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ {
+ int success;
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (TREE_VALUE (found));
+
+ /* We only want partial instantiations, here, not
+ specializations or full instantiations. */
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_VALUE (found))
+ || !uses_template_parms (TREE_VALUE (found)))
+ continue;
+
+ /* Temporarily reduce by one the number of levels in the
+ ARGLIST and in FOUND so as to avoid comparing the
+ last set of arguments. */
+ TREE_VEC_LENGTH (arglist)--;
+ TREE_VEC_LENGTH (TREE_PURPOSE (found)) --;
+
+ /* See if the arguments match. If they do, then TMPL is
+ the partial instantiation we want. */
+ success = comp_template_args (TREE_PURPOSE (found), arglist);
+
+ /* Restore the argument vectors to their full size. */
+ TREE_VEC_LENGTH (arglist)++;
+ TREE_VEC_LENGTH (TREE_PURPOSE (found))++;
+
+ if (success)
+ {
+ found = tmpl;
+ break;
+ }
+ }
+
+ if (!found)
+ my_friendly_abort (0);
+ }
- if (! CLASSTYPE_TEMPLATE_INFO (t))
- {
arglist = copy_to_permanent (arglist);
- CLASSTYPE_TEMPLATE_INFO (t)
- = perm_tree_cons (template, arglist, NULL_TREE);
- DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
- (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
- TI_USES_TEMPLATE_PARMS (DECL_TEMPLATE_INSTANTIATIONS (template))
- = uses_template_parms (arglist);
-
- SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
-
- /* We need to set this again after CLASSTYPE_TEMPLATE_INFO is set up. */
- DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) = id;
- if (! uses_template_parms (arglist))
- DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t))
- = get_identifier (build_overload_name (t, 1, 1));
-
- if (flag_external_templates && ! uses_template_parms (arglist)
- && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
- && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
- add_pending_template (t);
-
- if (uses_template_parms (arglist))
+ SET_TYPE_TEMPLATE_INFO (t,
+ tree_cons (found, arglist, NULL_TREE));
+ DECL_TEMPLATE_INSTANTIATIONS (template)
+ = tree_cons (arglist, t,
+ DECL_TEMPLATE_INSTANTIATIONS (template));
+
+ if (TREE_CODE (t) == ENUMERAL_TYPE
+ && !is_partial_instantiation)
+ /* Now that the type has been registered on the instantiations
+ list, we set up the enumerators. Because the enumeration
+ constants may involve the enumeration type itself, we make
+ sure to register the type first, and then create the
+ constants. That way, doing tsubst_expr for the enumeration
+ constants won't result in recursive calls here; we'll find
+ the instantiation and exit above. */
+ tsubst_enum (template_type, t, arglist);
+
+ /* We're done with the permanent obstack, now. */
+ pop_obstacks ();
+ /* We're also done with the momentary allocation we started
+ above. */
+ pop_momentary ();
+
+ /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
+ is set up. */
+ if (TREE_CODE (t) != ENUMERAL_TYPE)
+ DECL_NAME (type_decl) = classtype_mangled_name (t);
+ DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
+ if (!is_partial_instantiation)
+ {
+ DECL_ASSEMBLER_NAME (type_decl)
+ = get_identifier (build_overload_name (t, 1, 1));
+
+ /* For backwards compatibility; code that uses
+ -fexternal-templates expects looking up a template to
+ instantiate it. I think DDD still relies on this.
+ (jason 8/20/1998) */
+ if (TREE_CODE (t) != ENUMERAL_TYPE
+ && flag_external_templates
+ && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
+ && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
+ add_pending_template (t);
+ }
+ else
/* If the type makes use of template parameters, the
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
- }
- return t;
+ return t;
+ }
}
-/* Should be defined in parse.h. */
-extern int yychar;
-
/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
If FN returns non-zero, the iteration is terminated, and
@@ -3247,7 +4009,7 @@ extern int yychar;
returned by for_each_template_parm is 0. If FN is NULL, it is
considered to be the function which always returns 1. */
-int
+static int
for_each_template_parm (t, fn, data)
tree t;
tree_fn_t fn;
@@ -3269,6 +4031,11 @@ for_each_template_parm (t, fn, data)
COMPONENT_REF uses template parms. */
return for_each_template_parm (TREE_TYPE (t), fn, data);
+ case ARRAY_REF:
+ case OFFSET_REF:
+ return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
+ || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
+
case IDENTIFIER_NODE:
if (!IDENTIFIER_TEMPLATE (t))
return 0;
@@ -3298,20 +4065,43 @@ for_each_template_parm (t, fn, data)
case POINTER_TYPE:
case REFERENCE_TYPE:
return for_each_template_parm (TREE_TYPE (t), fn, data);
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (t))
return for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE (t),
fn, data);
+ /* Fall through. */
+
case UNION_TYPE:
- if (! CLASSTYPE_TEMPLATE_INFO (t))
+ case ENUMERAL_TYPE:
+ if (! TYPE_TEMPLATE_INFO (t))
return 0;
return for_each_template_parm (TREE_VALUE
- (CLASSTYPE_TEMPLATE_INFO (t)),
+ (TYPE_TEMPLATE_INFO (t)),
fn, data);
- case FUNCTION_TYPE:
- if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
+ case METHOD_TYPE:
+ if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
return 1;
+ /* Fall through. */
+
+ case FUNCTION_TYPE:
+ /* Check the parameter types. Since default arguments are not
+ instantiated until they are needed, the TYPE_ARG_TYPES may
+ contain expressions that involve template parameters. But,
+ no-one should be looking at them yet. And, once they're
+ instantiated, they don't contain template parameters, so
+ there's no point in looking at them then, either. */
+ {
+ tree parm;
+
+ for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
+ if (for_each_template_parm (TREE_VALUE (parm), fn, data))
+ return 1;
+ }
+
+ /* Check the return type, too. */
return for_each_template_parm (TREE_TYPE (t), fn, data);
+
case ARRAY_TYPE:
if (for_each_template_parm (TYPE_DOMAIN (t), fn, data))
return 1;
@@ -3320,12 +4110,6 @@ for_each_template_parm (t, fn, data)
if (for_each_template_parm (TYPE_OFFSET_BASETYPE (t), fn, data))
return 1;
return for_each_template_parm (TREE_TYPE (t), fn, data);
- case METHOD_TYPE:
- if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
- return 1;
- if (for_each_template_parm (TYPE_ARG_TYPES (t), fn, data))
- return 1;
- return for_each_template_parm (TREE_TYPE (t), fn, data);
/* decl nodes */
case TYPE_DECL:
@@ -3360,15 +4144,17 @@ for_each_template_parm (t, fn, data)
return 0;
case CALL_EXPR:
- return for_each_template_parm (TREE_TYPE (t), fn, data);
+ return (for_each_template_parm (TREE_OPERAND (t, 0), fn, data)
+ || for_each_template_parm (TREE_OPERAND (t, 1), fn, data));
+
case ADDR_EXPR:
return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
/* template parm nodes */
case TEMPLATE_TEMPLATE_PARM:
/* Record template parameters such as `T' inside `TT<T>'. */
- if (CLASSTYPE_TEMPLATE_INFO (t)
- && for_each_template_parm (CLASSTYPE_TI_ARGS (t), fn, data))
+ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t)
+ && for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
return 1;
case TEMPLATE_TYPE_PARM:
case TEMPLATE_PARM_INDEX:
@@ -3390,16 +4176,6 @@ for_each_template_parm (t, fn, data)
case NAMESPACE_DECL:
return 0;
- case ENUMERAL_TYPE:
- {
- tree v;
-
- for (v = TYPE_VALUES (t); v != NULL_TREE; v = TREE_CHAIN (v))
- if (for_each_template_parm (TREE_VALUE (v), fn, data))
- return 1;
- }
- return 0;
-
/* constants */
case INTEGER_CST:
case REAL_CST:
@@ -3416,6 +4192,9 @@ for_each_template_parm (t, fn, data)
case TYPENAME_TYPE:
return 1;
+ case PTRMEM_CST:
+ return for_each_template_parm (TREE_TYPE (t), fn, data);
+
case SCOPE_REF:
return for_each_template_parm (TREE_OPERAND (t, 0), fn, data);
@@ -3494,25 +4273,28 @@ print_template_context (err)
int line = lineno;
char *file = input_filename;
- if (err)
+ if (err && p)
{
- if (current_function_decl == p->decl)
- /* Avoid redundancy with the the "In function" line. */;
- else if (current_function_decl == NULL_TREE)
- fprintf (stderr, "%s: In instantiation of `%s':\n",
- file, decl_as_string (p->decl, 0));
+ if (current_function_decl != p->decl
+ && current_function_decl != NULL_TREE)
+ /* We can get here during the processing of some synthesized
+ method. Then, p->decl will be the function that's causing
+ the synthesis. */
+ ;
else
- my_friendly_abort (980521);
-
- if (p)
{
+ if (current_function_decl == p->decl)
+ /* Avoid redundancy with the the "In function" line. */;
+ else
+ fprintf (stderr, "%s: In instantiation of `%s':\n",
+ file, decl_as_string (p->decl, 0));
+
line = p->line;
file = p->file;
p = p->next;
}
}
- next:
for (; p; p = p->next)
{
fprintf (stderr, "%s:%d: instantiated from `%s'\n", file, line,
@@ -3590,6 +4372,12 @@ pop_tinst_level ()
{
struct tinst_level *old = current_tinst_level;
+ /* Restore the filename and line number stashed away when we started
+ this instantiation. */
+ lineno = old->line;
+ input_filename = old->file;
+ extract_interface_info ();
+
current_tinst_level = old->next;
old->next = free_tinst_level;
free_tinst_level = old;
@@ -3640,32 +4428,27 @@ tsubst_friend_function (decl, args)
tree template_id;
tree new_args;
tree tmpl;
- tree tinfo;
template_id
= lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
- args, NULL_TREE),
+ args, /*complain=*/1,
+ NULL_TREE),
tsubst (DECL_TI_ARGS (decl),
- args, NULL_TREE));
-
- /* Temporarily remove the DECL_TEMPLATE_INFO so as not to
- confuse tsubst. */
- tinfo = DECL_TEMPLATE_INFO (decl);
- DECL_TEMPLATE_INFO (decl) = NULL_TREE;
- new_friend = tsubst (decl, args, NULL_TREE);
- DECL_TEMPLATE_INFO (decl) = tinfo;
-
- tmpl = determine_specialization (template_id,
- new_friend,
- &new_args,
- 0, 1);
+ args, /*complain=*/1,
+ NULL_TREE));
+ /* FIXME: The decl we create via the next tsubst could be
+ created on a temporary obstack. */
+ new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
+ tmpl = determine_specialization (template_id, new_friend,
+ &new_args,
+ /*need_member_template=*/0);
new_friend = instantiate_template (tmpl, new_args);
goto done;
}
- else
- new_friend = tsubst (decl, args, NULL_TREE);
+
+ new_friend = tsubst (decl, args, /*complain=*/1, NULL_TREE);
- /* The new_friend will look like an instantiation, to the
+ /* The NEW_FRIEND will look like an instantiation, to the
compiler, but is not an instantiation from the point of view of
the language. For example, we might have had:
@@ -3678,15 +4461,143 @@ tsubst_friend_function (decl, args)
DECL_USE_TEMPLATE (new_friend) = 0;
if (TREE_CODE (decl) == TEMPLATE_DECL)
DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
-
+
+ /* The mangled name for the NEW_FRIEND is incorrect. The call to
+ tsubst will have resulted in a call to
+ set_mangled_name_for_template_decl. But, the function is not a
+ template instantiation and should not be mangled like one.
+ Therefore, we remangle the function name. We don't have to do
+ this if the NEW_FRIEND is a template since
+ set_mangled_name_for_template_decl doesn't do anything if the
+ function declaration still uses template arguments. */
+ if (TREE_CODE (new_friend) != TEMPLATE_DECL)
+ {
+ set_mangled_name_for_decl (new_friend);
+ DECL_RTL (new_friend) = 0;
+ make_decl_rtl (new_friend, NULL_PTR, 1);
+ }
+
if (DECL_NAMESPACE_SCOPE_P (new_friend))
{
+ tree old_decl;
+ tree new_friend_template_info;
+ tree new_friend_result_template_info;
+ int new_friend_is_defn;
+
+ /* We must save some information from NEW_FRIEND before calling
+ duplicate decls since that function will free NEW_FRIEND if
+ possible. */
+ new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
if (TREE_CODE (new_friend) == TEMPLATE_DECL)
- /* This declaration is a `primary' template. */
- TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (new_friend))
- = new_friend;
+ {
+ /* This declaration is a `primary' template. */
+ DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
+
+ new_friend_is_defn
+ = DECL_INITIAL (DECL_RESULT (new_friend)) != NULL_TREE;
+ new_friend_result_template_info
+ = DECL_TEMPLATE_INFO (DECL_RESULT (new_friend));
+ }
+ else
+ {
+ new_friend_is_defn = DECL_INITIAL (new_friend) != NULL_TREE;
+ new_friend_result_template_info = NULL_TREE;
+ }
+
+ old_decl = pushdecl_namespace_level (new_friend);
- new_friend = pushdecl_namespace_level (new_friend);
+ if (old_decl != new_friend)
+ {
+ /* This new friend declaration matched an existing
+ declaration. For example, given:
+
+ template <class T> void f(T);
+ template <class U> class C {
+ template <class T> friend void f(T) {}
+ };
+
+ the friend declaration actually provides the definition
+ of `f', once C has been instantiated for some type. So,
+ old_decl will be the out-of-class template declaration,
+ while new_friend is the in-class definition.
+
+ But, if `f' was called before this point, the
+ instantiation of `f' will have DECL_TI_ARGS corresponding
+ to `T' but not to `U', references to which might appear
+ in the definition of `f'. Previously, the most general
+ template for an instantiation of `f' was the out-of-class
+ version; now it is the in-class version. Therefore, we
+ run through all specialization of `f', adding to their
+ DECL_TI_ARGS appropriately. In particular, they need a
+ new set of outer arguments, corresponding to the
+ arguments for this class instantiation.
+
+ The same situation can arise with something like this:
+
+ friend void f(int);
+ template <class T> class C {
+ friend void f(T) {}
+ };
+
+ when `C<int>' is instantiated. Now, `f(int)' is defined
+ in the class. */
+
+ if (!new_friend_is_defn)
+ /* On the other hand, if the in-class declaration does
+ *not* provide a definition, then we don't want to alter
+ existing definitions. We can just leave everything
+ alone. */
+ ;
+ else
+ {
+ /* Overwrite whatever template info was there before, if
+ any, with the new template information pertaining to
+ the declaration. */
+ DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
+
+ if (TREE_CODE (old_decl) != TEMPLATE_DECL)
+ /* duplicate_decls will take care of this case. */
+ ;
+ else
+ {
+ tree t;
+ tree new_friend_args;
+
+ DECL_TEMPLATE_INFO (DECL_RESULT (old_decl))
+ = new_friend_result_template_info;
+
+ new_friend_args = TI_ARGS (new_friend_template_info);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl);
+ t != NULL_TREE;
+ t = TREE_CHAIN (t))
+ {
+ tree spec = TREE_VALUE (t);
+
+ DECL_TI_ARGS (spec)
+ = add_outermost_template_args (new_friend_args,
+ DECL_TI_ARGS (spec));
+ DECL_TI_ARGS (spec)
+ = copy_to_permanent (DECL_TI_ARGS (spec));
+ }
+
+ /* Now, since specializations are always supposed to
+ hang off of the most general template, we must move
+ them. */
+ t = most_general_template (old_decl);
+ if (t != old_decl)
+ {
+ DECL_TEMPLATE_SPECIALIZATIONS (t)
+ = chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
+ DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
+ DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
+ }
+ }
+ }
+
+ /* The information from NEW_FRIEND has been merged into OLD_DECL
+ by duplicate_decls. */
+ new_friend = old_decl;
+ }
}
else if (TYPE_SIZE (DECL_CONTEXT (new_friend)))
{
@@ -3716,16 +4627,40 @@ tsubst_friend_class (friend_tmpl, args)
tree args;
{
tree friend_type;
- tree tmpl = lookup_name (DECL_NAME (friend_tmpl), 1);
+ tree tmpl;
- tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+ /* First, we look for a class template. */
+ tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0);
+
+ /* But, if we don't find one, it might be because we're in a
+ situation like this:
- if (tmpl != NULL_TREE && DECL_CLASS_TEMPLATE_P (tmpl))
+ template <class T>
+ struct S {
+ template <class U>
+ friend struct S;
+ };
+
+ Here, in the scope of (say) S<int>, `S' is bound to a TYPE_DECL
+ for `S<int>', not the TEMPLATE_DECL. */
+ if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+ {
+ tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/1);
+ tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+ }
+
+ if (tmpl && DECL_CLASS_TEMPLATE_P (tmpl))
{
/* The friend template has already been declared. Just
- check to see that the declarations match. */
- redeclare_class_template (TREE_TYPE (tmpl),
- DECL_TEMPLATE_PARMS (friend_tmpl));
+ check to see that the declarations match, and install any new
+ default parameters. We must tsubst the default parameters,
+ of course. We only need the innermost template parameters
+ because that is all that redeclare_class_template will look
+ at. */
+ tree parms
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
+ args, /*complain=*/1);
+ redeclare_class_template (TREE_TYPE (tmpl), parms);
friend_type = TREE_TYPE (tmpl);
}
else
@@ -3733,7 +4668,7 @@ tsubst_friend_class (friend_tmpl, args)
/* The friend template has not already been declared. In this
case, the instantiation of the template class will cause the
injection of this template into the global scope. */
- tmpl = tsubst (friend_tmpl, args, NULL_TREE);
+ tmpl = tsubst (friend_tmpl, args, /*complain=*/1, NULL_TREE);
/* The new TMPL is not an instantiation of anything, so we
forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
@@ -3754,83 +4689,152 @@ tree
instantiate_class_template (type)
tree type;
{
- tree template, template_info, args, pattern, t, *field_chain;
- tree typedecl, outer_args;
+ tree template, args, pattern, t;
+ tree typedecl;
if (type == error_mark_node)
return error_mark_node;
- template_info = CLASSTYPE_TEMPLATE_INFO (type);
-
if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type))
return type;
- template = TI_TEMPLATE (template_info);
+ /* We want to allocate temporary vectors of template arguments and
+ template argument expressions on the momentary obstack, not on
+ the expression obstack. Otherwise, all the space allocated in
+ argument coercion and such is simply lost. */
+ push_momentary ();
+
+ /* Figure out which template is being instantiated. */
+ template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
- args = TI_ARGS (template_info);
- if (DECL_TEMPLATE_INFO (template))
- {
- outer_args = DECL_TI_ARGS (template);
- while (DECL_TEMPLATE_INFO (template))
- template = DECL_TI_TEMPLATE (template);
- }
- else
- outer_args = NULL_TREE;
+ /* Figure out which arguments are being used to do the
+ instantiation. */
+ args = CLASSTYPE_TI_ARGS (type);
+ PARTIAL_INSTANTIATION_P (type) = uses_template_parms (args);
- t = most_specialized_class
- (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args);
+ if (pedantic && PARTIAL_INSTANTIATION_P (type))
+ /* If this is a partial instantiation, then we can't instantiate
+ the type; there's no telling whether or not one of the
+ template parameters might eventually be instantiated to some
+ value that results in a specialization being used. For
+ example, consider:
- if (t == error_mark_node)
+ template <class T>
+ struct S {};
+
+ template <class U>
+ void f(S<U>);
+
+ template <>
+ struct S<int> {};
+
+ Now, the `S<U>' in `f<int>' is the specialization, not an
+ instantiation of the original template. */
+ goto end;
+
+ /* Determine what specialization of the original template to
+ instantiate. */
+ if (PARTIAL_INSTANTIATION_P (type))
+ /* There's no telling which specialization is appropriate at this
+ point. Since all peeking at the innards of this partial
+ instantiation are extensions (like the "implicit typename"
+ extension, which allows users to omit the keyword `typename' on
+ names that are declared as types in template base classes), we
+ are free to do what we please.
+
+ Trying to figure out which partial instantiation to use can
+ cause a crash. (Some of the template arguments don't even have
+ types.) So, we just use the most general version. */
+ t = NULL_TREE;
+ else
{
- char *str = "candidates are:";
- cp_error ("ambiguous class template instantiation for `%#T'", type);
- for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
+ t = most_specialized_class (template, args);
+
+ if (t == error_mark_node)
{
- if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- args, outer_args))
+ const char *str = "candidates are:";
+ cp_error ("ambiguous class template instantiation for `%#T'", type);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
+ t = TREE_CHAIN (t))
{
- cp_error_at ("%s %+#T", str, TREE_TYPE (t));
- str = " ";
+ if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args))
+ {
+ cp_error_at ("%s %+#T", str, TREE_TYPE (t));
+ str = " ";
+ }
}
+ TYPE_BEING_DEFINED (type) = 1;
+ type = error_mark_node;
+ goto end;
}
- TYPE_BEING_DEFINED (type) = 1;
- return error_mark_node;
}
- else if (t)
+
+ if (t)
pattern = TREE_TYPE (t);
else
pattern = TREE_TYPE (template);
+ /* If the template we're instantiating is incomplete, then clearly
+ there's nothing we can do. */
if (TYPE_SIZE (pattern) == NULL_TREE)
- return type;
+ goto end;
- if (t)
- args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- args, outer_args);
-
- if (pedantic && uses_template_parms (args))
- /* If there are still template parameters amongst the args, then
- we can't instantiate the type; there's no telling whether or not one
- of the template parameters might eventually be instantiated to some
- value that results in a specialization being used. */
- return type;
+ /* If this is a partial instantiation, don't tsubst anything. We will
+ only use this type for implicit typename, so the actual contents don't
+ matter. All that matters is whether a particular name is a type. */
+ if (PARTIAL_INSTANTIATION_P (type))
+ {
+ /* The fields set here must be kept in sync with those cleared
+ in begin_class_definition. */
+ TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
+ TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
+ TYPE_METHODS (type) = TYPE_METHODS (pattern);
+ CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
+ /* Pretend that the type is complete, so that we will look
+ inside it during name lookup and such. */
+ TYPE_SIZE (type) = integer_zero_node;
+ goto end;
+ }
- /* We must copy the arguments to the permanent obstack since
- during the tsubst'ing below they may wind up in the
- DECL_TI_ARGS of some instantiated member template. */
- args = copy_to_permanent (args);
+ /* If we've recursively instantiated too many templates, stop. */
+ if (! push_tinst_level (type))
+ goto end;
+ /* Now we're really doing the instantiation. Mark the type as in
+ the process of being defined. */
TYPE_BEING_DEFINED (type) = 1;
- if (! push_tinst_level (type))
- return type;
-
maybe_push_to_top_level (uses_template_parms (type));
- pushclass (type, 0);
- if (outer_args)
- args = add_to_template_args (outer_args, args);
+ if (t)
+ {
+ /* This TYPE is actually a instantiation of of a partial
+ specialization. We replace the innermost set of ARGS with
+ the arguments appropriate for substitution. For example,
+ given:
+
+ template <class T> struct S {};
+ template <class T> struct S<T*> {};
+
+ and supposing that we are instantiating S<int*>, ARGS will
+ present be {int*} but we need {int}. */
+ tree inner_args
+ = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
+ args);
+
+ /* If there were multiple levels in ARGS, replacing the
+ innermost level would alter CLASSTYPE_TI_ARGS, which we don't
+ want, so we make a copy first. */
+ if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
+ {
+ args = copy_node (args);
+ SET_TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args), inner_args);
+ }
+ else
+ args = inner_args;
+ }
if (flag_external_templates)
{
@@ -3860,7 +4864,6 @@ instantiate_class_template (type)
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
- TYPE_HAS_ASSIGNMENT (type) = TYPE_HAS_ASSIGNMENT (pattern);
TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
@@ -3883,108 +4886,163 @@ instantiate_class_template (type)
TYPE_PACKED (type) = TYPE_PACKED (pattern);
TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
+ if (ANON_UNION_TYPE_P (pattern))
+ SET_ANON_UNION_TYPE_P (type);
- CLASSTYPE_LOCAL_TYPEDECLS (type) = CLASSTYPE_LOCAL_TYPEDECLS (pattern);
+ /* We must copy the arguments to the permanent obstack since
+ during the tsubst'ing below they may wind up in the
+ DECL_TI_ARGS of some instantiated member template. */
+ args = copy_to_permanent (args);
- /* If this is a partial instantiation, don't tsubst anything. We will
- only use this type for implicit typename, so the actual contents don't
- matter. All that matters is whether a particular name is a type. */
- if (uses_template_parms (type))
+ if (TYPE_BINFO_BASETYPES (pattern))
{
- TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
- TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
- TYPE_METHODS (type) = TYPE_METHODS (pattern);
- CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
- TYPE_SIZE (type) = integer_zero_node;
- goto end;
- }
+ tree base_list = NULL_TREE;
+ tree pbases = TYPE_BINFO_BASETYPES (pattern);
+ int i;
- {
- tree binfo = TYPE_BINFO (type);
- tree pbases = TYPE_BINFO_BASETYPES (pattern);
+ /* Substitute into each of the bases to determine the actual
+ basetypes. */
+ for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
+ {
+ tree base;
+ tree access;
+ tree pbase;
- if (pbases)
- {
- tree bases;
- int i;
- int len = TREE_VEC_LENGTH (pbases);
- bases = make_tree_vec (len);
- for (i = 0; i < len; ++i)
- {
- tree elt, basetype;
+ pbase = TREE_VEC_ELT (pbases, i);
- TREE_VEC_ELT (bases, i) = elt
- = tsubst (TREE_VEC_ELT (pbases, i), args, NULL_TREE);
- BINFO_INHERITANCE_CHAIN (elt) = binfo;
+ /* Substitue to figure out the base class. */
+ base = tsubst (BINFO_TYPE (pbase), args,
+ /*complain=*/1, NULL_TREE);
+ if (base == error_mark_node)
+ continue;
- basetype = TREE_TYPE (elt);
+ /* Calculate the correct access node. */
+ if (TREE_VIA_VIRTUAL (pbase))
+ {
+ if (TREE_VIA_PUBLIC (pbase))
+ access = access_public_virtual_node;
+ else if (TREE_VIA_PROTECTED (pbase))
+ access = access_protected_virtual_node;
+ else
+ access = access_private_virtual_node;
+ }
+ else
+ {
+ if (TREE_VIA_PUBLIC (pbase))
+ access = access_public_node;
+ else if (TREE_VIA_PROTECTED (pbase))
+ access = access_protected_node;
+ else
+ access = access_private_node;
+ }
- if (! IS_AGGR_TYPE (basetype))
- cp_error
- ("base type `%T' of `%T' fails to be a struct or class type",
- basetype, type);
- else if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE)
- cp_error ("base class `%T' of `%T' has incomplete type",
- basetype, type);
+ base_list = tree_cons (access, base, base_list);
+ }
- /* These are set up in xref_basetypes for normal classes, so
- we have to handle them here for template bases. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- TYPE_USES_VIRTUAL_BASECLASSES (type) = 1;
- TYPE_USES_COMPLEX_INHERITANCE (type) = 1;
- }
- TYPE_GETS_NEW (type) |= TYPE_GETS_NEW (basetype);
- TYPE_GETS_DELETE (type) |= TYPE_GETS_DELETE (basetype);
- CLASSTYPE_LOCAL_TYPEDECLS (type)
- |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
- }
- /* Don't initialize this until the vector is filled out, or
- lookups will crash. */
- BINFO_BASETYPES (binfo) = bases;
- }
- }
+ /* The list is now in reverse order; correct that. */
+ base_list = nreverse (base_list);
+
+ /* Now call xref_basetypes to set up all the base-class
+ information. */
+ xref_basetypes (TREE_CODE (pattern) == RECORD_TYPE
+ ? (CLASSTYPE_DECLARED_CLASS (pattern)
+ ? class_type_node : record_type_node)
+ : union_type_node,
+ DECL_NAME (TYPE_NAME (pattern)),
+ type,
+ base_list);
+ }
- field_chain = &TYPE_FIELDS (type);
+ /* Now that our base classes are set up, enter the scope of the
+ class, so that name lookups into base classes, etc. will work
+ corectly. This is precisely analagous to what we do in
+ begin_class_definition when defining an ordinary non-template
+ class. */
+ pushclass (type, 1);
for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
{
tree tag = TREE_VALUE (t);
+ tree name = TYPE_IDENTIFIER (tag);
+ tree newtag;
- /* These will add themselves to CLASSTYPE_TAGS for the new type. */
- if (TREE_CODE (tag) == ENUMERAL_TYPE)
+ newtag = tsubst (tag, args, /*complain=*/1, NULL_TREE);
+ if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
- (void) tsubst_enum (tag, args, field_chain);
- while (*field_chain)
- {
- DECL_FIELD_CONTEXT (*field_chain) = type;
- field_chain = &TREE_CHAIN (*field_chain);
- }
+ if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
+ /* Unfortunately, lookup_template_class sets
+ CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
+ instantiation (i.e., for the type of a member template
+ class nested within a template class.) This behavior is
+ required for maybe_process_partial_specialization to work
+ correctly, but is not accurate in this case; the TAG is not
+ an instantiation of anything. (The corresponding
+ TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
+ CLASSTYPE_USE_TEMPLATE (newtag) = 0;
+
+ /* Now, we call pushtag to put this NEWTAG into the scope of
+ TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
+ pushtag calling push_template_decl. We don't have to do
+ this for enums because it will already have been done in
+ tsubst_enum. */
+ if (name)
+ SET_IDENTIFIER_TYPE_VALUE (name, newtag);
+ pushtag (name, newtag, /*globalize=*/0);
}
- else
- tsubst (tag, args, NULL_TREE);
}
/* Don't replace enum constants here. */
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL)
{
- tree r = tsubst (t, args, NULL_TREE);
+ tree r;
+
+ /* The the file and line for this declaration, to assist in
+ error message reporting. Since we called push_tinst_level
+ above, we don't need to restore these. */
+ lineno = DECL_SOURCE_LINE (t);
+ input_filename = DECL_SOURCE_FILE (t);
+
+ r = tsubst (t, args, /*complain=*/1, NULL_TREE);
if (TREE_CODE (r) == VAR_DECL)
{
- pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
- /* Perhaps we should do more of grokfield here. */
- start_decl_1 (r);
- DECL_IN_AGGR_P (r) = 1;
- DECL_EXTERNAL (r) = 1;
- cp_finish_decl (r, DECL_INITIAL (r), NULL_TREE, 0, 0);
- }
+ tree init;
+
+ if (DECL_DEFINED_IN_CLASS_P (r))
+ init = tsubst_expr (DECL_INITIAL (t), args,
+ /*complain=*/1, NULL_TREE);
+ else
+ init = NULL_TREE;
+
+ finish_static_data_member_decl (r, init,
+ /*asmspec_tree=*/NULL_TREE,
+ /*need_pop=*/0,
+ /*flags=*/0);
- *field_chain = r;
- field_chain = &TREE_CHAIN (r);
+ if (DECL_DEFINED_IN_CLASS_P (r))
+ check_static_variable_definition (r, TREE_TYPE (r));
+ }
+
+ /* R will have a TREE_CHAIN if and only if it has already been
+ processed by finish_member_declaration. This can happen
+ if, for example, it is a TYPE_DECL for a class-scoped
+ ENUMERAL_TYPE; such a thing will already have been added to
+ the field list by tsubst_enum above. */
+ if (!TREE_CHAIN (r))
+ {
+ set_current_access_from_decl (r);
+ finish_member_declaration (r);
+ }
}
- TYPE_METHODS (type) = tsubst_chain (TYPE_METHODS (pattern), args);
+ /* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
+ for this instantiation. */
+ for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
+ {
+ tree r = tsubst (t, args, /*complain=*/1, NULL_TREE);
+ set_current_access_from_decl (r);
+ finish_member_declaration (r);
+ }
/* Construct the DECL_FRIENDLIST for the new class type. */
typedecl = TYPE_MAIN_DECL (type);
@@ -3994,31 +5052,19 @@ instantiate_class_template (type)
{
tree friends;
- DECL_FRIENDLIST (typedecl)
- = tree_cons (TREE_PURPOSE (t), NULL_TREE,
- DECL_FRIENDLIST (typedecl));
-
for (friends = TREE_VALUE (t);
friends != NULL_TREE;
friends = TREE_CHAIN (friends))
- {
- if (TREE_PURPOSE (friends) == error_mark_node)
- {
- TREE_VALUE (DECL_FRIENDLIST (typedecl))
- = tree_cons (error_mark_node,
- tsubst_friend_function (TREE_VALUE (friends),
- args),
- TREE_VALUE (DECL_FRIENDLIST (typedecl)));
- }
- else
- {
- TREE_VALUE (DECL_FRIENDLIST (typedecl))
- = tree_cons (tsubst (TREE_PURPOSE (friends), args, NULL_TREE),
- NULL_TREE,
- TREE_VALUE (DECL_FRIENDLIST (typedecl)));
-
- }
- }
+ if (TREE_PURPOSE (friends) == error_mark_node)
+ add_friend (type,
+ tsubst_friend_function (TREE_VALUE (friends),
+ args));
+ else
+ add_friends (type,
+ tsubst_copy (TREE_PURPOSE (t), args,
+ /*complain=*/1, NULL_TREE),
+ tsubst (TREE_PURPOSE (friends), args,
+ /*complain=*/1, NULL_TREE));
}
for (t = CLASSTYPE_FRIEND_CLASSES (pattern);
@@ -4028,14 +5074,17 @@ instantiate_class_template (type)
tree friend_type = TREE_VALUE (t);
tree new_friend_type;
- if (TREE_CODE (friend_type) != TEMPLATE_DECL)
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ new_friend_type = tsubst_friend_class (friend_type, args);
+ else if (uses_template_parms (friend_type))
+ new_friend_type = tsubst (friend_type, args, /*complain=*/1,
+ NULL_TREE);
+ else
/* The call to xref_tag_from_type does injection for friend
classes. */
new_friend_type =
- xref_tag_from_type (tsubst (friend_type, args, NULL_TREE),
- NULL_TREE, 1);
- else
- new_friend_type = tsubst_friend_class (friend_type, args);
+ xref_tag_from_type (friend_type, NULL_TREE, 1);
+
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
/* Trick make_friend_class into realizing that the friend
@@ -4054,7 +5103,8 @@ instantiate_class_template (type)
/* This does injection for friend functions. */
if (!processing_template_decl)
{
- t = tsubst (DECL_TEMPLATE_INJECT (template), args, NULL_TREE);
+ t = tsubst (DECL_TEMPLATE_INJECT (template), args,
+ /*complain=*/1, NULL_TREE);
for (; t; t = TREE_CHAIN (t))
{
@@ -4074,18 +5124,28 @@ instantiate_class_template (type)
require_complete_type (t);
}
- type = finish_struct_1 (type, 0);
- CLASSTYPE_GOT_SEMICOLON (type) = 1;
+ /* Set the file and line number information to whatever is given for
+ the class itself. This puts error messages involving generated
+ implicit functions at a predictable point, and the same point
+ that would be used for non-template classes. */
+ lineno = DECL_SOURCE_LINE (typedecl);
+ input_filename = DECL_SOURCE_FILE (typedecl);
- repo_template_used (type);
+ unreverse_member_declarations (type);
+ finish_struct_1 (type, 0);
+ CLASSTYPE_GOT_SEMICOLON (type) = 1;
- end:
+ /* Clear this now so repo_template_used is happy. */
TYPE_BEING_DEFINED (type) = 0;
- popclass (0);
+ repo_template_used (type);
+ popclass ();
pop_from_top_level ();
pop_tinst_level ();
+ end:
+ pop_momentary ();
+
return type;
}
@@ -4105,24 +5165,6 @@ list_eq (t1, t2)
return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
}
-tree
-lookup_nested_type_by_name (ctype, name)
- tree ctype, name;
-{
- tree t;
-
- complete_type (ctype);
-
- for (t = CLASSTYPE_TAGS (ctype); t; t = TREE_CHAIN (t))
- {
- if (name == TREE_PURPOSE (t)
- /* this catches typedef enum { foo } bar; */
- || name == TYPE_IDENTIFIER (TREE_VALUE (t)))
- return TREE_VALUE (t);
- }
- return NULL_TREE;
-}
-
/* If arg is a non-type template parameter that does not depend on template
arguments, fold it like we weren't in the body of a template. */
@@ -4150,28 +5192,23 @@ maybe_fold_nontype_arg (arg)
}
/* Return the TREE_VEC with the arguments for the innermost template header,
- where ARGS is either that or the VEC of VECs for all the arguments.
-
- If is_spec, then we are dealing with a specialization of a member
- template, and want the second-innermost args, the innermost ones that
- are instantiated. */
+ where ARGS is either that or the VEC of VECs for all the
+ arguments. */
tree
-innermost_args (args, is_spec)
+innermost_args (args)
tree args;
- int is_spec;
{
- if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
- return args;
+ return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
}
/* Substitute ARGS into the vector of template arguments T. */
-tree
-tsubst_template_arg_vector (t, args)
+static tree
+tsubst_template_arg_vector (t, args, complain)
tree t;
tree args;
+ int complain;
{
int len = TREE_VEC_LENGTH (t), need_new = 0, i;
tree *elts = (tree *) alloca (len * sizeof (tree));
@@ -4182,10 +5219,12 @@ tsubst_template_arg_vector (t, args)
{
if (TREE_VEC_ELT (t, i) != NULL_TREE
&& TREE_CODE (TREE_VEC_ELT (t, i)) == TREE_VEC)
- elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i), args);
+ elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i),
+ args, complain);
else
elts[i] = maybe_fold_nontype_arg
- (tsubst_expr (TREE_VEC_ELT (t, i), args, NULL_TREE));
+ (tsubst_expr (TREE_VEC_ELT (t, i), args, complain,
+ NULL_TREE));
if (elts[i] != TREE_VEC_ELT (t, i))
need_new = 1;
@@ -4194,46 +5233,77 @@ tsubst_template_arg_vector (t, args)
if (!need_new)
return t;
- t = make_tree_vec (len);
+ t = make_temp_vec (len);
for (i = 0; i < len; i++)
TREE_VEC_ELT (t, i) = elts[i];
return t;
}
-/* Take the tree structure T and replace template parameters used therein
- with the argument vector ARGS. IN_DECL is an associated decl for
- diagnostics.
+/* Return the result of substituting ARGS into the template parameters
+ given by PARMS. If there are m levels of ARGS and m + n levels of
+ PARMS, then the result will contain n levels of PARMS. For
+ example, if PARMS is `template <class T> template <class U>
+ template <T*, U, class V>' and ARGS is {{int}, {double}} then the
+ result will be `template <int*, double, class V>'. */
- tsubst is used for dealing with types, decls and the like; for
- expressions, use tsubst_expr or tsubst_copy. */
-
-tree
-tsubst (t, args, in_decl)
- tree t, args;
- tree in_decl;
+static tree
+tsubst_template_parms (parms, args, complain)
+ tree parms;
+ tree args;
+ int complain;
{
- tree type;
+ tree r;
+ tree* new_parms = &r;
- if (t == NULL_TREE || t == error_mark_node
- || t == integer_type_node
- || t == void_type_node
- || t == char_type_node
- || TREE_CODE (t) == NAMESPACE_DECL)
- return t;
+ for (new_parms = &r;
+ TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
+ new_parms = &(TREE_CHAIN (*new_parms)),
+ parms = TREE_CHAIN (parms))
+ {
+ tree new_vec =
+ make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
+ int i;
+
+ for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
+ {
+ tree default_value =
+ TREE_PURPOSE (TREE_VEC_ELT (TREE_VALUE (parms), i));
+ tree parm_decl =
+ TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i));
+
+ TREE_VEC_ELT (new_vec, i)
+ = build_tree_list (tsubst (default_value, args, complain,
+ NULL_TREE),
+ tsubst (parm_decl, args, complain,
+ NULL_TREE));
+ }
+
+ *new_parms =
+ tree_cons (build_int_2 (0, (TMPL_PARMS_DEPTH (parms)
+ - TMPL_ARGS_DEPTH (args))),
+ new_vec, NULL_TREE);
+ }
- if (TREE_CODE (t) == IDENTIFIER_NODE)
- type = IDENTIFIER_TYPE_VALUE (t);
- else
- type = TREE_TYPE (t);
- if (type == unknown_type_node)
- my_friendly_abort (42);
+ return r;
+}
- if (type && TREE_CODE (t) != FUNCTION_DECL
- && TREE_CODE (t) != TYPENAME_TYPE
- && TREE_CODE (t) != TEMPLATE_DECL
- && TREE_CODE (t) != IDENTIFIER_NODE)
- type = tsubst (type, args, in_decl);
+/* Substitute the ARGS into the indicated aggregate (or enumeration)
+ type T. If T is not an aggregate or enumeration type, it is
+ handled as if by tsubst. IN_DECL is as for tsubst. If
+ ENTERING_SCOPE is non-zero, T is the context for a template which
+ we are presently tsubst'ing. Return the subsituted value. */
+
+static tree
+tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
+ tree t;
+ tree args;
+ int complain;
+ tree in_decl;
+ int entering_scope;
+{
+ if (t == NULL_TREE)
+ return NULL_TREE;
switch (TREE_CODE (t))
{
@@ -4241,234 +5311,115 @@ tsubst (t, args, in_decl)
if (TYPE_PTRMEMFUNC_P (t))
{
tree r = build_ptrmemfunc_type
- (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, in_decl));
- return cp_build_type_variant (r, TYPE_READONLY (t),
- TYPE_VOLATILE (t));
+ (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl));
+ return cp_build_qualified_type (r, TYPE_QUALS (t));
}
/* else fall through */
+ case ENUMERAL_TYPE:
case UNION_TYPE:
- if (uses_template_parms (t))
+ if (TYPE_TEMPLATE_INFO (t))
{
- tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
+ tree argvec;
tree context;
tree r;
+ /* First, determine the context for the type we are looking
+ up. */
if (TYPE_CONTEXT (t) != NULL_TREE)
- {
- context = tsubst (TYPE_CONTEXT (t), args, in_decl);
-
- if (TREE_CODE (context) != FUNCTION_DECL
- && TREE_CODE (context) != NAMESPACE_DECL)
- {
- /* For a member class template, we need all the
- template arguments. */
- if (CLASSTYPE_IS_TEMPLATE (TYPE_CONTEXT (t)))
- argvec =
- add_to_template_args (CLASSTYPE_TI_ARGS (context),
- argvec);
-
- if (CLASSTYPE_TEMPLATE_INFO (context))
- argvec =
- complete_template_args (CLASSTYPE_TI_TEMPLATE (context),
- argvec, 0);
- }
- }
+ context = tsubst_aggr_type (TYPE_CONTEXT (t), args,
+ complain,
+ in_decl, /*entering_scope=*/1);
else
context = NULL_TREE;
- r = lookup_template_class (t, argvec, in_decl, context);
+ /* Then, figure out what arguments are appropriate for the
+ type we are trying to find. For example, given:
- return cp_build_type_variant (r, TYPE_READONLY (t),
- TYPE_VOLATILE (t));
- }
-
- /* else fall through */
- case ERROR_MARK:
- case IDENTIFIER_NODE:
- case OP_IDENTIFIER:
- case VOID_TYPE:
- case REAL_TYPE:
- case COMPLEX_TYPE:
- case BOOLEAN_TYPE:
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case NAMESPACE_DECL:
- return t;
+ template <class T> struct S;
+ template <class T, class U> void f(T, U) { S<U> su; }
- case ENUMERAL_TYPE:
- {
- tree ctx = tsubst (TYPE_CONTEXT (t), args, in_decl);
- if (ctx == NULL_TREE || TREE_CODE (ctx) == NAMESPACE_DECL)
- return t;
- else if (ctx == current_function_decl)
- return lookup_name (TYPE_IDENTIFIER (t), 1);
- else
- return lookup_nested_type_by_name (ctx, TYPE_IDENTIFIER (t));
- }
+ and supposing that we are instantiating f<int, double>,
+ then our ARGS will be {int, double}, but, when looking up
+ S we only want {double}. */
+ push_momentary ();
+ argvec = tsubst_template_arg_vector (TYPE_TI_ARGS (t), args,
+ complain);
- case INTEGER_TYPE:
- if (t == integer_type_node)
- return t;
+ r = lookup_template_class (t, argvec, in_decl, context,
+ entering_scope);
+ pop_momentary ();
- if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
- && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+ return cp_build_qualified_type (r, TYPE_QUALS (t));
+ }
+ else
+ /* This is not a template type, so there's nothing to do. */
return t;
- {
- tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
- max = tsubst_expr (max, args, in_decl);
- if (processing_template_decl)
- {
- tree itype = make_node (INTEGER_TYPE);
- TYPE_MIN_VALUE (itype) = size_zero_node;
- TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
- integer_one_node);
- return itype;
- }
-
- max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
- return build_index_2_type (size_zero_node, max);
- }
-
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_TEMPLATE_PARM:
- case TEMPLATE_PARM_INDEX:
- {
- int idx;
- int level;
- int levels;
- tree r = NULL_TREE;
-
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
- {
- idx = TEMPLATE_TYPE_IDX (t);
- level = TEMPLATE_TYPE_LEVEL (t);
- }
- else
- {
- idx = TEMPLATE_PARM_IDX (t);
- level = TEMPLATE_PARM_LEVEL (t);
- }
-
- if (TREE_VEC_LENGTH (args) > 0)
- {
- tree arg = NULL_TREE;
-
- if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- {
- levels = TREE_VEC_LENGTH (args);
- if (level <= levels)
- arg = TREE_VEC_ELT
- (TREE_VEC_ELT (args, level - 1), idx);
- }
- else
- {
- levels = 1;
- if (level == 1)
- arg = TREE_VEC_ELT (args, idx);
- }
-
- if (arg != NULL_TREE)
- {
- if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- return cp_build_type_variant
- (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
- TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
- else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
- {
- if (CLASSTYPE_TEMPLATE_INFO (t))
- {
- /* We are processing a type constructed from
- a template template parameter */
- tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
- args, in_decl);
- tree r;
-
- /* We can get a TEMPLATE_TEMPLATE_PARM here when
- we are resolving nested-types in the signature of
- a member function templates.
- Otherwise ARG is a TEMPLATE_DECL and is the real
- template to be instantiated. */
- if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- arg = TYPE_NAME (arg);
-
- r = lookup_template_class (DECL_NAME (arg),
- argvec, in_decl,
- DECL_CONTEXT (arg));
- return cp_build_type_variant (r, TYPE_READONLY (t),
- TYPE_VOLATILE (t));
- }
- else
- /* We are processing a template argument list. */
- return arg;
- }
- else
- return arg;
- }
- }
-
- if (level == 1)
- /* This can happen during the attempted tsubst'ing in
- unify. This means that we don't yet have any information
- about the template parameter in question. */
- return t;
-
- /* If we get here, we must have been looking at a parm for a
- more deeply nested template. Make a new version of this
- template parameter, but with a lower level. */
- switch (TREE_CODE (t))
- {
- case TEMPLATE_TYPE_PARM:
- case TEMPLATE_TEMPLATE_PARM:
- r = copy_node (t);
- TEMPLATE_TYPE_PARM_INDEX (r)
- = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
- r, levels);
- TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
- TYPE_MAIN_VARIANT (r) = r;
- TYPE_POINTER_TO (r) = NULL_TREE;
- TYPE_REFERENCE_TO (r) = NULL_TREE;
+ default:
+ return tsubst (t, args, complain, in_decl);
+ }
+}
- if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
- && CLASSTYPE_TEMPLATE_INFO (t))
- {
- tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
- CLASSTYPE_TEMPLATE_INFO (r)
- = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
- }
- break;
+/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
+ (already computed) substitution of ARGS into TREE_TYPE (T), if
+ appropriate. Return the result of the substitution. IN_DECL is as
+ for tsubst. */
- case TEMPLATE_PARM_INDEX:
- r = reduce_template_parm_level (t, type, levels);
- break;
-
- default:
- my_friendly_abort (0);
- }
+static tree
+tsubst_decl (t, args, type, in_decl)
+ tree t;
+ tree args;
+ tree type;
+ tree in_decl;
+{
+ int saved_lineno;
+ char* saved_filename;
+ tree r = NULL_TREE;
- return r;
- }
+ /* Set the filename and linenumber to improve error-reporting. */
+ saved_lineno = lineno;
+ saved_filename = input_filename;
+ lineno = DECL_SOURCE_LINE (t);
+ input_filename = DECL_SOURCE_FILE (t);
+ switch (TREE_CODE (t))
+ {
case TEMPLATE_DECL:
{
/* We can get here when processing a member template function
of a template class. */
- tree tmpl;
tree decl = DECL_TEMPLATE_RESULT (t);
- tree parms;
- tree* new_parms;
tree spec;
int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
if (!is_template_template_parm)
{
- /* We might already have an instance of this template. */
- spec = retrieve_specialization (t, args);
+ /* We might already have an instance of this template.
+ The ARGS are for the surrounding class type, so the
+ full args contain the tsubst'd args for the context,
+ plus the innermost args from the template decl. */
+ tree tmpl_args = DECL_CLASS_TEMPLATE_P (t)
+ ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
+ : DECL_TI_ARGS (DECL_RESULT (t));
+ tree full_args;
+
+ push_momentary ();
+ full_args = tsubst_template_arg_vector (tmpl_args, args,
+ /*complain=*/1);
+
+ /* tsubst_template_arg_vector doesn't copy the vector if
+ nothing changed. But, *something* should have
+ changed. */
+ my_friendly_assert (full_args != tmpl_args, 0);
+
+ spec = retrieve_specialization (t, full_args);
+ pop_momentary ();
if (spec != NULL_TREE)
- return spec;
+ {
+ r = spec;
+ break;
+ }
}
/* Make a new template decl. It will be similar to the
@@ -4476,90 +5427,64 @@ tsubst (t, args, in_decl)
We also create a new function declaration, which is just
like the old one, but points to this new template, rather
than the old one. */
- tmpl = copy_node (t);
- copy_lang_decl (tmpl);
- my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
- TREE_CHAIN (tmpl) = NULL_TREE;
+ r = copy_node (t);
+ copy_lang_decl (r);
+ my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0);
+ TREE_CHAIN (r) = NULL_TREE;
if (is_template_template_parm)
{
- tree new_decl = tsubst (decl, args, in_decl);
- DECL_RESULT (tmpl) = new_decl;
- TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
- return tmpl;
+ tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);
+ DECL_RESULT (r) = new_decl;
+ TREE_TYPE (r) = TREE_TYPE (new_decl);
+ break;
}
- DECL_CONTEXT (tmpl) = tsubst (DECL_CONTEXT (t),
- args, in_decl);
- DECL_CLASS_CONTEXT (tmpl) = tsubst (DECL_CLASS_CONTEXT (t),
- args, in_decl);
- DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
+ DECL_CONTEXT (r)
+ = tsubst_aggr_type (DECL_CONTEXT (t), args, /*complain=*/1,
+ in_decl, /*entering_scope=*/1);
+ DECL_CLASS_CONTEXT (r)
+ = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args,
+ /*complain=*/1, in_decl,
+ /*entering_scope=*/1);
+ DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_DECL)
{
- tree new_type = tsubst (TREE_TYPE (t), args, in_decl);
- TREE_TYPE (tmpl) = new_type;
- CLASSTYPE_TI_TEMPLATE (new_type) = tmpl;
- DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type);
+ tree new_type = tsubst (TREE_TYPE (t), args,
+ /*complain=*/1, in_decl);
+ TREE_TYPE (r) = new_type;
+ CLASSTYPE_TI_TEMPLATE (new_type) = r;
+ DECL_RESULT (r) = TYPE_MAIN_DECL (new_type);
+ DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
}
else
{
- tree new_decl = tsubst (decl, args, in_decl);
- DECL_RESULT (tmpl) = new_decl;
- DECL_TI_TEMPLATE (new_decl) = tmpl;
- TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
+ tree new_decl = tsubst (decl, args, /*complain=*/1, in_decl);
+ DECL_RESULT (r) = new_decl;
+ DECL_TI_TEMPLATE (new_decl) = r;
+ TREE_TYPE (r) = TREE_TYPE (new_decl);
+ DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
}
- DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
- SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
+ DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
- for (new_parms = &DECL_TEMPLATE_PARMS (tmpl),
- parms = DECL_TEMPLATE_PARMS (t);
- TREE_CHAIN (parms) != NULL_TREE;
- new_parms = &(TREE_CHAIN (*new_parms)),
- parms = TREE_CHAIN (parms))
- {
- tree new_vec =
- make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
- int i;
-
- for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
- {
- tree default_value =
- TREE_PURPOSE (TREE_VEC_ELT (TREE_VALUE (parms), i));
- tree parm_decl =
- TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i));
-
- TREE_VEC_ELT (new_vec, i)
- = build_tree_list (tsubst (default_value, args, in_decl),
- tsubst (parm_decl, args, in_decl));
-
- }
-
- *new_parms =
- tree_cons (build_int_2 (0,
- TREE_INT_CST_HIGH
- (TREE_PURPOSE (parms)) - 1),
- new_vec,
- NULL_TREE);
- }
+ DECL_TEMPLATE_PARMS (r)
+ = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
+ /*complain=*/1);
if (PRIMARY_TEMPLATE_P (t))
- DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ DECL_PRIMARY_TEMPLATE (r) = r;
/* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL)
- return tmpl;
+ break;
- /* What should we do with the specializations of this member
- template? Are they specializations of this new template,
- or instantiations of the templates they previously were?
- this new template? And where should their
- DECL_TI_TEMPLATES point? */
- DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE;
for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec != NULL_TREE;
spec = TREE_CHAIN (spec))
@@ -4600,28 +5525,132 @@ tsubst (t, args, in_decl)
no concern to us. */
continue;
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ /* A full specialization. There's no need to record
+ that here. */
+ continue;
+
spec_args = tsubst (DECL_TI_ARGS (fn), args,
- in_decl);
- new_fn = tsubst (DECL_RESULT (fn), args,
- in_decl);
- DECL_TEMPLATE_SPECIALIZATIONS (tmpl) =
- perm_tree_cons (spec_args, new_fn,
- DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
+ /*complain=*/1, in_decl);
+ new_fn = tsubst (DECL_RESULT (most_general_template (fn)),
+ spec_args, /*complain=*/1, in_decl);
+ DECL_TI_TEMPLATE (new_fn) = fn;
+ register_specialization (new_fn, r,
+ innermost_args (spec_args));
}
/* Record this partial instantiation. */
- register_specialization (tmpl, t, args);
+ register_specialization (r, t,
+ DECL_TI_ARGS (DECL_RESULT (r)));
- return tmpl;
}
+ break;
case FUNCTION_DECL:
{
- tree r = NULL_TREE;
tree ctx;
- tree argvec;
- tree tmpl = NULL_TREE;
+ tree argvec = NULL_TREE;
+ tree *friends;
+ tree gen_tmpl;
int member;
+ int args_depth;
+ int parms_depth;
+
+ /* Nobody should be tsubst'ing into non-template functions. */
+ my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
+
+ if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
+ {
+ tree spec;
+
+ /* Allocate template arguments on the momentary obstack,
+ in case we don't need to keep them. */
+ push_momentary ();
+
+ /* Calculate the most general template of which R is a
+ specialization, and the complete set of arguments used to
+ specialize R. */
+ gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
+ argvec
+ = tsubst_template_arg_vector (DECL_TI_ARGS
+ (DECL_TEMPLATE_RESULT (gen_tmpl)),
+ args, /*complain=*/1);
+
+ /* Check to see if we already have this specialization. */
+ spec = retrieve_specialization (gen_tmpl, argvec);
+
+ if (spec)
+ {
+ r = spec;
+ pop_momentary ();
+ break;
+ }
+
+ /* We're going to need to keep the ARGVEC, so we copy it
+ here. */
+ argvec = copy_to_permanent (argvec);
+ pop_momentary ();
+
+ /* Here, we deal with the peculiar case:
+
+ template <class T> struct S {
+ template <class U> friend void f();
+ };
+ template <class U> friend void f() {}
+ template S<int>;
+ template void f<double>();
+
+ Here, the ARGS for the instantiation of will be {int,
+ double}. But, we only need as many ARGS as there are
+ levels of template parameters in CODE_PATTERN. We are
+ careful not to get fooled into reducing the ARGS in
+ situations like:
+
+ template <class T> struct S { template <class U> void f(U); }
+ template <class T> template <> void S<T>::f(int) {}
+
+ which we can spot because the pattern will be a
+ specialization in this case. */
+ args_depth = TMPL_ARGS_DEPTH (args);
+ parms_depth =
+ TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
+ if (args_depth > parms_depth
+ && !DECL_TEMPLATE_SPECIALIZATION (t))
+ {
+ my_friendly_assert (DECL_FRIEND_P (t), 0);
+
+ if (parms_depth > 1)
+ {
+ int i;
+
+ args = make_temp_vec (parms_depth);
+ for (i = 0; i < parms_depth; ++i)
+ TREE_VEC_ELT (args, i) =
+ TREE_VEC_ELT (args, i + (args_depth - parms_depth));
+ }
+ else
+ args = TREE_VEC_ELT (args, args_depth - parms_depth);
+ }
+ }
+ else
+ {
+ /* This special case arises when we have something like this:
+
+ template <class T> struct S {
+ friend void f<int>(int, double);
+ };
+
+ Here, the DECL_TI_TEMPLATE for the friend declaration
+ will be a LOOKUP_EXPR or an IDENTIFIER_NODE. We are
+ being called from tsubst_friend_function, and we want
+ only to create a new decl (R) with appropriate types so
+ that we can call determine_specialization. */
+ my_friendly_assert ((TREE_CODE (DECL_TI_TEMPLATE (t))
+ == LOOKUP_EXPR)
+ || (TREE_CODE (DECL_TI_TEMPLATE (t))
+ == IDENTIFIER_NODE), 0);
+ gen_tmpl = NULL_TREE;
+ }
if (DECL_CLASS_SCOPE_P (t))
{
@@ -4629,36 +5658,16 @@ tsubst (t, args, in_decl)
member = 2;
else
member = 1;
- ctx = tsubst (DECL_CLASS_CONTEXT (t), args, t);
+ ctx = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args,
+ /*complain=*/1, t,
+ /*entering_scope=*/1);
}
else
{
member = 0;
ctx = NULL_TREE;
}
- type = tsubst (type, args, in_decl);
-
- /* If we are instantiating a specialization, get the other args. */
- if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
- {
- tree spec;
-
- tmpl = DECL_TI_TEMPLATE (t);
-
- /* Start by getting the innermost args. */
- if (DECL_TEMPLATE_SPECIALIZATION (tmpl))
- argvec = args;
- else
- argvec = tsubst (DECL_TI_ARGS (t), args, in_decl);
-
- if (DECL_TEMPLATE_INFO (tmpl))
- argvec = complete_template_args (tmpl, argvec, 0);
-
- /* Do we already have this instantiation? */
- spec = retrieve_specialization (tmpl, argvec);
- if (spec)
- return spec;
- }
+ type = tsubst (type, args, /*complain=*/1, in_decl);
/* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this
@@ -4671,22 +5680,19 @@ tsubst (t, args, in_decl)
TREE_TYPE (r) = type;
DECL_CONTEXT (r)
- = tsubst (DECL_CONTEXT (t), args, t);
+ = tsubst_aggr_type (DECL_CONTEXT (t), args, /*complain=*/1, t,
+ /*entering_scope=*/1);
DECL_CLASS_CONTEXT (r) = ctx;
- if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
- IDENTIFIER_POINTER (DECL_NAME (r)),
- sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
- {
- /* Type-conversion operator. Reconstruct the name, in
- case it's the name of one of the template's parameters. */
- DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
- }
+ if (member && IDENTIFIER_TYPENAME_P (DECL_NAME (r)))
+ /* Type-conversion operator. Reconstruct the name, in
+ case it's the name of one of the template's parameters. */
+ DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
- DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
+ DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
+ /*complain=*/1, t);
DECL_MAIN_VARIANT (r) = r;
DECL_RESULT (r) = NULL_TREE;
- DECL_INITIAL (r) = NULL_TREE;
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
@@ -4697,142 +5703,85 @@ tsubst (t, args, in_decl)
DECL_PENDING_INLINE_INFO (r) = 0;
TREE_USED (r) = 0;
- if (DECL_CONSTRUCTOR_P (r))
+ /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
+ name. There's no need to do this in the special friend
+ case mentioned above where GEN_TMPL is NULL. */
+ if (gen_tmpl)
{
- maybe_retrofit_in_chrg (r);
- grok_ctor_properties (ctx, r);
- }
- if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
- grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
+ /* The ARGVEC was built on the momentary obstack. Make it
+ permanent now. */
+ argvec = copy_to_permanent (argvec);
+ DECL_TEMPLATE_INFO (r)
+ = perm_tree_cons (gen_tmpl, argvec, NULL_TREE);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ register_specialization (r, gen_tmpl, argvec);
- if (DECL_DESTRUCTOR_P (t))
- DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
- else
- {
- /* Instantiations of template functions must be mangled
- specially, in order to conform to 14.5.5.1
- [temp.over.link]. We use in_decl below rather than
- DECL_TI_TEMPLATE (r) because the latter is set to
- NULL_TREE in instantiate_decl. */
- tree tmpl;
- tree arg_types;
-
- if (DECL_TEMPLATE_INFO (r))
- tmpl = DECL_TI_TEMPLATE (r);
- else
- tmpl = in_decl;
-
- /* tmpl will be NULL if this is a specialization of a
- member function of a template class. */
- if (name_mangling_version < 1
- || tmpl == NULL_TREE
- || (member && !is_member_template (tmpl)
- && !DECL_TEMPLATE_INFO (tmpl)))
+ /* Set the mangled name for R. */
+ if (DECL_DESTRUCTOR_P (t))
+ DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ else
{
- arg_types = TYPE_ARG_TYPES (type);
- if (member && TREE_CODE (type) == FUNCTION_TYPE)
- arg_types = hash_tree_chain
- (build_pointer_type (DECL_CONTEXT (r)),
- arg_types);
+ /* Instantiations of template functions must be mangled
+ specially, in order to conform to 14.5.5.1
+ [temp.over.link]. */
+ tree tmpl = DECL_TI_TEMPLATE (t);
- DECL_ASSEMBLER_NAME (r)
- = build_decl_overload (DECL_NAME (r), arg_types,
- member);
- }
- else
- {
- tree tparms;
- tree targs;
-
- if (!DECL_TEMPLATE_SPECIALIZATION (tmpl))
- {
- /* We pass the outermost template parameters to
- build_template_decl_overload, since the innermost
- template parameters are still just template
- parameters; there are no corresponding subsitution
- arguments. Levels of parms that have been bound
- before are not represented in DECL_TEMPLATE_PARMS. */
- tparms = DECL_TEMPLATE_PARMS (tmpl);
- while (tparms && TREE_CHAIN (tparms) != NULL_TREE)
- tparms = TREE_CHAIN (tparms);
-
- targs = innermost_args (args, 0);
- }
+ /* TMPL will be NULL if this is a specialization of a
+ member function of a template class. */
+ if (name_mangling_version < 1
+ || tmpl == NULL_TREE
+ || (member && !is_member_template (tmpl)
+ && !DECL_TEMPLATE_INFO (tmpl)))
+ set_mangled_name_for_decl (r);
else
- {
- /* If the template is a specialization, then it is
- a member template specialization. We have
- something like:
-
- template <class T> struct S {
- template <int i> void f();
- template <> void f<7>();
- };
-
- and now we are forming S<double>::f<7>.
- Therefore, the template parameters of interest
- are those that are specialized by the template
- (i.e., the int), not those we are using to
- instantiate the template, i.e. the double. */
- tparms = DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (tmpl));
- targs = DECL_TI_ARGS (tmpl);
- }
-
- my_friendly_assert (tparms != NULL_TREE
- && TREE_CODE (tparms) == TREE_LIST,
- 0);
- tparms = TREE_VALUE (tparms);
-
- arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
- if (member && TREE_CODE (type) == FUNCTION_TYPE)
- arg_types = hash_tree_chain
- (build_pointer_type (DECL_CONTEXT (r)),
- arg_types);
-
- DECL_ASSEMBLER_NAME (r)
- = build_template_decl_overload
- (r, arg_types, TREE_TYPE (TREE_TYPE (tmpl)),
- tparms, targs, member);
+ set_mangled_name_for_template_decl (r);
}
+
+ DECL_RTL (r) = 0;
+ make_decl_rtl (r, NULL_PTR, 1);
+
+ /* Like grokfndecl. If we don't do this, pushdecl will
+ mess up our TREE_CHAIN because it doesn't find a
+ previous decl. Sigh. */
+ if (member
+ && ! uses_template_parms (r)
+ && (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r))
+ == NULL_TREE))
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
- DECL_RTL (r) = 0;
- make_decl_rtl (r, NULL_PTR, 1);
- if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+ /* Copy the list of befriending classes. */
+ for (friends = &DECL_BEFRIENDING_CLASSES (r);
+ *friends;
+ friends = &TREE_CHAIN (*friends))
{
- DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
-
- /* If we're not using ANSI overloading, then we might have
- called duplicate_decls above, and gotten back an
- preexisting version of this function. We treat such a
- function as a specialization. Otherwise, we cleared
- both TREE_STATIC and DECL_TEMPLATE_SPECIALIZATION, so
- this condition will be false. */
- if (TREE_STATIC (r) || DECL_TEMPLATE_SPECIALIZATION (r))
- SET_DECL_TEMPLATE_SPECIALIZATION (r);
- else
- SET_DECL_IMPLICIT_INSTANTIATION (r);
-
- register_specialization (r, tmpl, argvec);
+ *friends = copy_node (*friends);
+ TREE_VALUE (*friends) = tsubst (TREE_VALUE (*friends),
+ args, /*complain=*/1,
+ in_decl);
}
- /* Like grokfndecl. If we don't do this, pushdecl will mess up our
- TREE_CHAIN because it doesn't find a previous decl. Sigh. */
- if (member
- && IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) == NULL_TREE)
- SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
-
- return r;
+ if (DECL_CONSTRUCTOR_P (r))
+ {
+ maybe_retrofit_in_chrg (r);
+ grok_ctor_properties (ctx, r);
+ }
+ if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
+ grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
}
+ break;
case PARM_DECL:
{
- tree r = copy_node (t);
+ r = copy_node (t);
TREE_TYPE (r) = type;
+ c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
DECL_INITIAL (r) = TREE_TYPE (r);
else
- DECL_INITIAL (r) = tsubst (DECL_INITIAL (r), args, in_decl);
+ DECL_INITIAL (r) = tsubst (DECL_INITIAL (r), args,
+ /*complain=*/1, in_decl);
DECL_CONTEXT (r) = NULL_TREE;
#ifdef PROMOTE_PROTOTYPES
@@ -4842,125 +5791,539 @@ tsubst (t, args, in_decl)
DECL_ARG_TYPE (r) = integer_type_node;
#endif
if (TREE_CHAIN (t))
- TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t));
- return r;
+ TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,
+ /*complain=*/1, TREE_CHAIN (t));
}
+ break;
case FIELD_DECL:
{
- tree r = copy_node (t);
- TREE_TYPE (r) = type;
+ r = copy_node (t);
copy_lang_decl (r);
-#if 0
- DECL_FIELD_CONTEXT (r) = tsubst (DECL_FIELD_CONTEXT (t), args, in_decl);
-#endif
- DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, in_decl);
+ TREE_TYPE (r) = type;
+ c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+
+ /* We don't have to set DECL_CONTEXT here; it is set by
+ finish_member_declaration. */
+ DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
+ /*complain=*/1, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- if (TREE_CODE (type) == VOID_TYPE)
+ if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
- return r;
}
+ break;
case USING_DECL:
{
- tree r = copy_node (t);
+ r = copy_node (t);
DECL_INITIAL (r)
- = tsubst_copy (DECL_INITIAL (t), args, in_decl);
+ = tsubst_copy (DECL_INITIAL (t), args, /*complain=*/1, in_decl);
TREE_CHAIN (r) = NULL_TREE;
- return r;
}
+ break;
case VAR_DECL:
{
- tree r;
- tree ctx = tsubst_copy (DECL_CONTEXT (t), args, in_decl);
+ tree argvec;
+ tree gen_tmpl;
+ tree spec;
+ tree tmpl;
+ tree ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
+ /*complain=*/1,
+ in_decl, /*entering_scope=*/1);
+
+ /* Nobody should be tsubst'ing into non-template variables. */
+ my_friendly_assert (DECL_LANG_SPECIFIC (t)
+ && DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
- /* Do we already have this instantiation? */
- if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ /* Check to see if we already have this specialization. */
+ tmpl = DECL_TI_TEMPLATE (t);
+ gen_tmpl = most_general_template (tmpl);
+ argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
+ spec = retrieve_specialization (gen_tmpl, argvec);
+
+ if (spec)
{
- tree tmpl = DECL_TI_TEMPLATE (t);
- tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
-
- for (; decls; decls = TREE_CHAIN (decls))
- if (DECL_CONTEXT (TREE_VALUE (decls)) == ctx)
- return TREE_VALUE (decls);
+ r = spec;
+ break;
}
r = copy_node (t);
TREE_TYPE (r) = type;
+ c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
DECL_CONTEXT (r) = ctx;
- if (TREE_STATIC (r))
- DECL_ASSEMBLER_NAME (r)
- = build_static_name (DECL_CONTEXT (r), DECL_NAME (r));
/* Don't try to expand the initializer until someone tries to use
this variable; otherwise we run into circular dependencies. */
DECL_INITIAL (r) = NULL_TREE;
-
DECL_RTL (r) = 0;
DECL_SIZE (r) = 0;
+ copy_lang_decl (r);
+ DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
- if (DECL_LANG_SPECIFIC (r))
- {
- copy_lang_decl (r);
- DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
- }
+ /* A static data member declaration is always marked external
+ when it is declared in-class, even if an initializer is
+ present. We mimic the non-template processing here. */
+ DECL_EXTERNAL (r) = 1;
- if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
- {
- tree tmpl = DECL_TI_TEMPLATE (t);
- tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
- tree argvec = tsubst (DECL_TI_ARGS (t), args, in_decl);
+ DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ register_specialization (r, gen_tmpl, argvec);
- DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
- *declsp = perm_tree_cons (argvec, r, *declsp);
- SET_DECL_IMPLICIT_INSTANTIATION (r);
- }
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
- return r;
}
+ break;
case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t)))
- return TYPE_NAME (type);
+ r = TYPE_NAME (type);
+ else
+ {
+ r = copy_node (t);
+ TREE_TYPE (r) = type;
+ DECL_CONTEXT (r) = current_class_type;
+ TREE_CHAIN (r) = NULL_TREE;
+ }
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+
+ /* Restore the file and line information. */
+ lineno = saved_lineno;
+ input_filename = saved_filename;
+
+ return r;
+}
+
+/* Substitue into the ARG_TYPES of a function type. */
+
+static tree
+tsubst_arg_types (arg_types, args, complain, in_decl)
+ tree arg_types;
+ tree args;
+ int complain;
+ tree in_decl;
+{
+ tree remaining_arg_types;
+ tree type;
+
+ if (!arg_types || arg_types == void_list_node)
+ return arg_types;
+
+ remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
+ args, complain, in_decl);
+ if (remaining_arg_types == error_mark_node)
+ return error_mark_node;
+
+ type = tsubst (TREE_VALUE (arg_types), args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ /* Do array-to-pointer, function-to-pointer conversion, and ignore
+ top-level qualifiers as required. */
+ type = TYPE_MAIN_VARIANT (type_decays_to (type));
+
+ /* Note that we do not substitute into default arguments here. The
+ standard mandates that they be instantiated only when needed,
+ which is done in build_over_call. */
+ return hash_tree_cons (TREE_PURPOSE (arg_types), type,
+ remaining_arg_types);
+
+}
+
+/* Substitute into a FUNCTION_TYPE or METHOD_TYPE. This routine does
+ *not* handle the exception-specification for FNTYPE, because the
+ initial substitution of explicitly provided template parameters
+ during argument deduction forbids substitution into the
+ exception-specification:
+
+ [temp.deduct]
+
+ All references in the function type of the function template to the
+ corresponding template parameters are replaced by the specified tem-
+ plate argument values. If a substitution in a template parameter or
+ in the function type of the function template results in an invalid
+ type, type deduction fails. [Note: The equivalent substitution in
+ exception specifications is done only when the function is instanti-
+ ated, at which point a program is ill-formed if the substitution
+ results in an invalid type.] */
+
+static tree
+tsubst_function_type (t, args, complain, in_decl)
+ tree t;
+ tree args;
+ int complain;
+ tree in_decl;
+{
+ tree return_type;
+ tree arg_types;
+ tree fntype;
+
+ /* The TYPE_CONTEXT is not used for function/method types. */
+ my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
+
+ /* Substitue the return type. */
+ return_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (return_type == error_mark_node)
+ return error_mark_node;
+
+ /* Substitue the argument types. */
+ arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args,
+ complain, in_decl);
+ if (arg_types == error_mark_node)
+ return error_mark_node;
+
+ /* Construct a new type node and return it. */
+ if (TREE_CODE (t) == FUNCTION_TYPE)
+ fntype = build_function_type (return_type, arg_types);
+ else
+ {
+ tree r = TREE_TYPE (TREE_VALUE (arg_types));
+ if (! IS_AGGR_TYPE (r))
+ {
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ -- Attempting to create "pointer to member of T" when T
+ is not a class type. */
+ if (complain)
+ cp_error ("creating pointer to member function of non-class type `%T'",
+ r);
+ return error_mark_node;
+ }
+
+ fntype = build_cplus_method_type (r, return_type, TREE_CHAIN
+ (arg_types));
+ }
+ fntype = build_qualified_type (fntype, TYPE_QUALS (t));
+ fntype = build_type_attribute_variant (fntype, TYPE_ATTRIBUTES (t));
+
+ return fntype;
+}
+
+/* Substitute into the PARMS of a call-declarator. */
+
+static tree
+tsubst_call_declarator_parms (parms, args, complain, in_decl)
+ tree parms;
+ tree args;
+ int complain;
+ tree in_decl;
+{
+ tree new_parms;
+ tree type;
+ tree defarg;
+
+ if (!parms || parms == void_list_node)
+ return parms;
+
+ new_parms = tsubst_call_declarator_parms (TREE_CHAIN (parms),
+ args, complain, in_decl);
+
+ /* Figure out the type of this parameter. */
+ type = tsubst (TREE_VALUE (parms), args, complain, in_decl);
+
+ /* Figure out the default argument as well. Note that we use
+ tsubst_expr since the default argument is really an expression. */
+ defarg = tsubst_expr (TREE_PURPOSE (parms), args, complain, in_decl);
+
+ /* Chain this parameter on to the front of those we have already
+ processed. We don't use hash_tree_cons because that function
+ doesn't check TREE_PARMLIST. */
+ new_parms = tree_cons (defarg, type, new_parms);
+
+ /* And note that these are parameters. */
+ TREE_PARMLIST (new_parms) = 1;
+
+ return new_parms;
+}
+
+/* Take the tree structure T and replace template parameters used
+ therein with the argument vector ARGS. IN_DECL is an associated
+ decl for diagnostics. If an error occurs, returns ERROR_MARK_NODE.
+ An appropriate error message is issued only if COMPLAIN is
+ non-zero. Note that we must be relatively non-tolerant of
+ extensions here, in order to preserve conformance; if we allow
+ substitutions that should not be allowed, we may allow argument
+ deductions that should not succeed, and therefore report ambiguous
+ overload situations where there are none. In theory, we could
+ allow the substitution, but indicate that it should have failed,
+ and allow our caller to make sure that the right thing happens, but
+ we don't try to do this yet.
+
+ This function is used for dealing with types, decls and the like;
+ for expressions, use tsubst_expr or tsubst_copy. */
+
+tree
+tsubst (t, args, complain, in_decl)
+ tree t, args;
+ int complain;
+ tree in_decl;
+{
+ tree type, r;
+
+ if (t == NULL_TREE || t == error_mark_node
+ || t == integer_type_node
+ || t == void_type_node
+ || t == char_type_node
+ || TREE_CODE (t) == NAMESPACE_DECL)
+ return t;
+
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ type = IDENTIFIER_TYPE_VALUE (t);
+ else
+ type = TREE_TYPE (t);
+ if (type == unknown_type_node)
+ my_friendly_abort (42);
+
+ if (type && TREE_CODE (t) != FUNCTION_DECL
+ && TREE_CODE (t) != TYPENAME_TYPE
+ && TREE_CODE (t) != TEMPLATE_DECL
+ && TREE_CODE (t) != IDENTIFIER_NODE
+ && TREE_CODE (t) != FUNCTION_TYPE
+ && TREE_CODE (t) != METHOD_TYPE)
+ type = tsubst (type, args, complain, in_decl);
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
+ return tsubst_decl (t, args, type, in_decl);
+
+ switch (TREE_CODE (t))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ return tsubst_aggr_type (t, args, complain, in_decl,
+ /*entering_scope=*/0);
+
+ case ERROR_MARK:
+ case IDENTIFIER_NODE:
+ case OP_IDENTIFIER:
+ case VOID_TYPE:
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ case BOOLEAN_TYPE:
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ return t;
+
+ case INTEGER_TYPE:
+ if (t == integer_type_node)
+ return t;
+
+ if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
+ && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
+ return t;
{
- tree r = copy_node (t);
- TREE_TYPE (r) = type;
- DECL_CONTEXT (r) = current_class_type;
- TREE_CHAIN (r) = NULL_TREE;
+ tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
+
+ max = tsubst_expr (omax, args, complain, in_decl);
+ if (max == error_mark_node)
+ return error_mark_node;
+
+ if (processing_template_decl
+ /* When providing explicit arguments to a template
+ function, but leaving some arguments for subsequent
+ deduction, MAX may be template-dependent even if we're
+ not PROCESSING_TEMPLATE_DECL. */
+ || TREE_CODE (max) != INTEGER_CST)
+ {
+ return build_index_type (build_min
+ (MINUS_EXPR, sizetype, max, integer_one_node));
+ }
+
+ if (integer_zerop (omax))
+ {
+ /* Still allow an explicit array of size zero. */
+ if (pedantic)
+ pedwarn ("creating array with size zero");
+ }
+ else if (integer_zerop (max) || INT_CST_LT (max, integer_zero_node))
+ {
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ Attempting to create an array with a size that is
+ zero or negative. */
+ if (complain)
+ cp_error ("creating array with size `%E'", max);
+
+ return error_mark_node;
+ }
+
+ max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node));
+ if (!TREE_PERMANENT (max) && !allocation_temporary_p ())
+ max = copy_to_permanent (max);
+ return build_index_type (max);
+ }
+
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ {
+ int idx;
+ int level;
+ int levels;
+
+ r = NULL_TREE;
+
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ {
+ idx = TEMPLATE_TYPE_IDX (t);
+ level = TEMPLATE_TYPE_LEVEL (t);
+ }
+ else
+ {
+ idx = TEMPLATE_PARM_IDX (t);
+ level = TEMPLATE_PARM_LEVEL (t);
+ }
+
+ if (TREE_VEC_LENGTH (args) > 0)
+ {
+ tree arg = NULL_TREE;
+
+ levels = TMPL_ARGS_DEPTH (args);
+ if (level <= levels)
+ arg = TMPL_ARG (args, level, idx);
+
+ if (arg == error_mark_node)
+ return error_mark_node;
+ else if (arg != NULL_TREE)
+ {
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ {
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
+ == 't', 0);
+ return cp_build_qualified_type
+ (arg, CP_TYPE_QUALS (arg) | CP_TYPE_QUALS (t));
+ }
+ else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
+ {
+ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
+ {
+ /* We are processing a type constructed from
+ a template template parameter */
+ tree argvec = tsubst (TYPE_TI_ARGS (t),
+ args, complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
+
+ /* We can get a TEMPLATE_TEMPLATE_PARM here when
+ we are resolving nested-types in the signature of
+ a member function templates.
+ Otherwise ARG is a TEMPLATE_DECL and is the real
+ template to be instantiated. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ arg = TYPE_NAME (arg);
+
+ r = lookup_template_class (DECL_NAME (arg),
+ argvec, in_decl,
+ DECL_CONTEXT (arg),
+ /*entering_scope=*/0);
+ return cp_build_qualified_type (r, TYPE_QUALS (t));
+ }
+ else
+ /* We are processing a template argument list. */
+ return arg;
+ }
+ else
+ return arg;
+ }
+ }
+ else
+ my_friendly_abort (981018);
+
+ if (level == 1)
+ /* This can happen during the attempted tsubst'ing in
+ unify. This means that we don't yet have any information
+ about the template parameter in question. */
+ return t;
+
+ /* If we get here, we must have been looking at a parm for a
+ more deeply nested template. Make a new version of this
+ template parameter, but with a lower level. */
+ switch (TREE_CODE (t))
+ {
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_TEMPLATE_PARM:
+ r = copy_node (t);
+ TEMPLATE_TYPE_PARM_INDEX (r)
+ = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+ r, levels);
+ TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
+ TYPE_MAIN_VARIANT (r) = r;
+ TYPE_POINTER_TO (r) = NULL_TREE;
+ TYPE_REFERENCE_TO (r) = NULL_TREE;
+
+ if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+ && TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
+ {
+ tree argvec = tsubst (TYPE_TI_ARGS (t), args,
+ complain, in_decl);
+ if (argvec == error_mark_node)
+ return error_mark_node;
+
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
+ = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE);
+ }
+ break;
+
+ case TEMPLATE_PARM_INDEX:
+ r = reduce_template_parm_level (t, type, levels);
+ break;
+
+ default:
+ my_friendly_abort (0);
+ }
+
return r;
- }
+ }
case TREE_LIST:
{
tree purpose, value, chain, result;
- int via_public, via_virtual, via_protected;
if (t == void_list_node)
return t;
- via_public = TREE_VIA_PUBLIC (t);
- via_protected = TREE_VIA_PROTECTED (t);
- via_virtual = TREE_VIA_VIRTUAL (t);
-
purpose = TREE_PURPOSE (t);
if (purpose)
- purpose = tsubst (purpose, args, in_decl);
+ {
+ purpose = tsubst (purpose, args, complain, in_decl);
+ if (purpose == error_mark_node)
+ return error_mark_node;
+ }
value = TREE_VALUE (t);
if (value)
- value = tsubst (value, args, in_decl);
+ {
+ value = tsubst (value, args, complain, in_decl);
+ if (value == error_mark_node)
+ return error_mark_node;
+ }
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
- chain = tsubst (chain, args, in_decl);
+ {
+ chain = tsubst (chain, args, complain, in_decl);
+ if (chain == error_mark_node)
+ return error_mark_node;
+ }
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
- result = hash_tree_cons (via_public, via_virtual, via_protected,
- purpose, value, chain);
+ result = hash_tree_cons (purpose, value, chain);
TREE_PARMLIST (result) = TREE_PARMLIST (t);
return result;
}
@@ -4987,19 +6350,29 @@ tsubst (t, args, in_decl)
}
/* Otherwise, a vector of template arguments. */
- return tsubst_template_arg_vector (t, args);
+ return tsubst_template_arg_vector (t, args, complain);
case POINTER_TYPE:
case REFERENCE_TYPE:
{
- tree r;
enum tree_code code;
if (type == TREE_TYPE (t))
return t;
code = TREE_CODE (t);
- if (TREE_CODE (type) == REFERENCE_TYPE)
+
+
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ -- Attempting to create a pointer to reference type.
+ -- Attempting to create a reference to a reference type or
+ a reference to void. */
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
{
static int last_line = 0;
static char* last_file = 0;
@@ -5007,179 +6380,237 @@ tsubst (t, args, in_decl)
/* We keep track of the last time we issued this error
message to avoid spewing a ton of messages during a
single bad template instantiation. */
- if (last_line != lineno ||
- last_file != input_filename)
+ if (complain && (last_line != lineno ||
+ last_file != input_filename))
{
- cp_error ("cannot form type %s to reference type %T during template instantiation",
- (code == POINTER_TYPE) ? "pointer" : "reference",
- type);
+ if (TREE_CODE (type) == VOID_TYPE)
+ cp_error ("forming reference to void");
+ else
+ cp_error ("forming %s to reference type `%T'",
+ (code == POINTER_TYPE) ? "pointer" : "reference",
+ type);
last_line = lineno;
last_file = input_filename;
}
- /* Use the underlying type in an attempt at error
- recovery; maybe the user meant vector<int> and wrote
- vector<int&>, or some such. */
- if (code == REFERENCE_TYPE)
- r = type;
- else
- r = build_pointer_type (TREE_TYPE (type));
+ return error_mark_node;
}
else if (code == POINTER_TYPE)
r = build_pointer_type (type);
else
r = build_reference_type (type);
- r = cp_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ r = cp_build_qualified_type (r, TYPE_QUALS (t));
/* Will this ever be needed for TYPE_..._TO values? */
layout_type (r);
return r;
}
case OFFSET_TYPE:
- return build_offset_type
- (tsubst (TYPE_OFFSET_BASETYPE (t), args, in_decl), type);
+ {
+ r = tsubst (TYPE_OFFSET_BASETYPE (t), args, complain, in_decl);
+ if (r == error_mark_node || !IS_AGGR_TYPE (r))
+ {
+ /* [temp.deduct]
+
+ Type deduction may fail for any of the following
+ reasons:
+
+ -- Attempting to create "pointer to member of T" when T
+ is not a class type. */
+ if (complain)
+ cp_error ("creating pointer to member of non-class type `%T'",
+ r);
+ return error_mark_node;
+ }
+ return build_offset_type (r, type);
+ }
case FUNCTION_TYPE:
case METHOD_TYPE:
{
- tree values = TYPE_ARG_TYPES (t);
- tree context = TYPE_CONTEXT (t);
- tree raises = TYPE_RAISES_EXCEPTIONS (t);
tree fntype;
+ tree raises;
- /* Don't bother recursing if we know it won't change anything. */
- if (values != void_list_node)
- {
- /* This should probably be rewritten to use hash_tree_cons for
- the memory savings. */
- tree first = NULL_TREE;
- tree last = NULL_TREE;
-
- for (; values && values != void_list_node;
- values = TREE_CHAIN (values))
- {
- tree value = TYPE_MAIN_VARIANT (type_decays_to
- (tsubst (TREE_VALUE (values), args, in_decl)));
- /* Don't instantiate default args unless they are used.
- Handle it in build_over_call instead. */
- tree purpose = TREE_PURPOSE (values);
- tree x = build_tree_list (purpose, value);
-
- if (first)
- TREE_CHAIN (last) = x;
- else
- first = x;
- last = x;
- }
-
- if (values == void_list_node)
- TREE_CHAIN (last) = void_list_node;
-
- values = first;
- }
- if (context)
- context = tsubst (context, args, in_decl);
- /* Could also optimize cases where return value and
- values have common elements (e.g., T min(const &T, const T&). */
-
- /* If the above parameters haven't changed, just return the type. */
- if (type == TREE_TYPE (t)
- && values == TYPE_VALUES (t)
- && context == TYPE_CONTEXT (t))
- return t;
+ fntype = tsubst_function_type (t, args, complain, in_decl);
+ if (fntype == error_mark_node)
+ return error_mark_node;
- /* Construct a new type node and return it. */
- if (TREE_CODE (t) == FUNCTION_TYPE
- && context == NULL_TREE)
- {
- fntype = build_function_type (type, values);
- }
- else if (context == NULL_TREE)
- {
- tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))),
- args, in_decl);
- fntype = build_cplus_method_type (base, type,
- TREE_CHAIN (values));
- }
- else
- {
- fntype = make_node (TREE_CODE (t));
- TREE_TYPE (fntype) = type;
- TYPE_CONTEXT (fntype) = FROB_CONTEXT (context);
- TYPE_VALUES (fntype) = values;
- TYPE_SIZE (fntype) = TYPE_SIZE (t);
- TYPE_ALIGN (fntype) = TYPE_ALIGN (t);
- TYPE_MODE (fntype) = TYPE_MODE (t);
- if (TYPE_METHOD_BASETYPE (t))
- TYPE_METHOD_BASETYPE (fntype) = tsubst (TYPE_METHOD_BASETYPE (t),
- args, in_decl);
- /* Need to generate hash value. */
- my_friendly_abort (84);
- }
- fntype = build_type_variant (fntype,
- TYPE_READONLY (t),
- TYPE_VOLATILE (t));
+ /* Substitue the exception specification. */
+ raises = TYPE_RAISES_EXCEPTIONS (t);
if (raises)
{
- raises = tsubst (raises, args, in_decl);
+ raises = tsubst (raises, args, complain, in_decl);
+ if (raises == error_mark_node)
+ return raises;
fntype = build_exception_variant (fntype, raises);
}
return fntype;
}
case ARRAY_TYPE:
{
- tree domain = tsubst (TYPE_DOMAIN (t), args, in_decl);
- tree r;
+ tree domain = tsubst (TYPE_DOMAIN (t), args, complain, in_decl);
+ if (domain == error_mark_node)
+ return error_mark_node;
+
+ /* As an optimization, we avoid regenerating the array type if
+ it will obviously be the same as T. */
if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
return t;
+
+ /* These checks should match the ones in grokdeclarator.
+
+ [temp.deduct]
+
+ The deduction may fail for any of the following reasons:
+
+ -- Attempting to create an array with an element type that
+ is void, a function type, or a reference type. */
+ if (TREE_CODE (type) == VOID_TYPE
+ || TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ if (complain)
+ cp_error ("creating array of `%T'", type);
+ return error_mark_node;
+ }
+
r = build_cplus_array_type (type, domain);
return r;
}
case PLUS_EXPR:
case MINUS_EXPR:
- return fold (build (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, in_decl),
- tsubst (TREE_OPERAND (t, 1), args, in_decl)));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain,
+ in_decl);
+
+ if (e1 == error_mark_node || e2 == error_mark_node)
+ return error_mark_node;
+
+ return fold (build (TREE_CODE (t), TREE_TYPE (t), e1, e2));
+ }
case NEGATE_EXPR:
case NOP_EXPR:
- return fold (build1 (TREE_CODE (t), TREE_TYPE (t),
- tsubst (TREE_OPERAND (t, 0), args, in_decl)));
+ {
+ tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ if (e == error_mark_node)
+ return error_mark_node;
+
+ return fold (build (TREE_CODE (t), TREE_TYPE (t), e));
+ }
case TYPENAME_TYPE:
{
- tree ctx = tsubst (TYPE_CONTEXT (t), args, in_decl);
- tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl);
+ tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
+ in_decl, /*entering_scope=*/1);
+ tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args,
+ complain, in_decl);
+
+ if (ctx == error_mark_node || f == error_mark_node)
+ return error_mark_node;
+
+ if (!IS_AGGR_TYPE (ctx))
+ {
+ if (complain)
+ cp_error ("`%T' is not a class, struct, or union type",
+ ctx);
+ return error_mark_node;
+ }
+ else if (!uses_template_parms (ctx) && !TYPE_BEING_DEFINED (ctx))
+ {
+ /* Normally, make_typename_type does not require that the CTX
+ have complete type in order to allow things like:
+
+ template <class T> struct S { typename S<T>::X Y; };
+
+ But, such constructs have already been resolved by this
+ point, so here CTX really should have complete type, unless
+ it's a partial instantiation. */
+ ctx = complete_type (ctx);
+ if (!TYPE_SIZE (ctx))
+ {
+ if (complain)
+ incomplete_type_error (NULL_TREE, ctx);
+ return error_mark_node;
+ }
+ }
+
f = make_typename_type (ctx, f);
- return cp_build_type_variant
- (f, TYPE_READONLY (f) || TYPE_READONLY (t),
- TYPE_VOLATILE (f) || TYPE_VOLATILE (t));
+ if (f == error_mark_node)
+ return f;
+ return cp_build_qualified_type (f,
+ CP_TYPE_QUALS (f)
+ | CP_TYPE_QUALS (t));
}
case INDIRECT_REF:
- return make_pointer_declarator
- (type, tsubst (TREE_OPERAND (t, 0), args, in_decl));
-
+ {
+ tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ if (e == error_mark_node)
+ return error_mark_node;
+ return make_pointer_declarator (type, e);
+ }
+
case ADDR_EXPR:
- return make_reference_declarator
- (type, tsubst (TREE_OPERAND (t, 0), args, in_decl));
+ {
+ tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ if (e == error_mark_node)
+ return error_mark_node;
+ return make_reference_declarator (type, e);
+ }
case ARRAY_REF:
- return build_parse_node
- (ARRAY_REF, tsubst (TREE_OPERAND (t, 0), args, in_decl),
- tsubst_expr (TREE_OPERAND (t, 1), args, in_decl));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain,
+ in_decl);
+ if (e1 == error_mark_node || e2 == error_mark_node)
+ return error_mark_node;
+
+ return build_parse_node (ARRAY_REF, e1, e2, tsubst_expr);
+ }
case CALL_EXPR:
- return make_call_declarator
- (tsubst (TREE_OPERAND (t, 0), args, in_decl),
- tsubst (TREE_OPERAND (t, 1), args, in_decl),
- TREE_OPERAND (t, 2),
- tsubst (TREE_TYPE (t), args, in_decl));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst_call_declarator_parms (TREE_OPERAND (t, 1), args,
+ complain, in_decl);
+ tree e3 = tsubst (TREE_TYPE (t), args, complain, in_decl);
+
+ if (e1 == error_mark_node || e2 == error_mark_node
+ || e3 == error_mark_node)
+ return error_mark_node;
+
+ return make_call_declarator (e1, e2, TREE_OPERAND (t, 2), e3);
+ }
case SCOPE_REF:
- return build_parse_node
- (TREE_CODE (t), tsubst (TREE_OPERAND (t, 0), args, in_decl),
- tsubst (TREE_OPERAND (t, 1), args, in_decl));
+ {
+ tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain,
+ in_decl);
+ tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
+ if (e1 == error_mark_node || e2 == error_mark_node)
+ return error_mark_node;
+
+ return build_parse_node (TREE_CODE (t), e1, e2);
+ }
+
+ case TYPEOF_TYPE:
+ {
+ tree e1 = tsubst_expr (TYPE_FIELDS (t), args, complain,
+ in_decl);
+ if (e1 == error_mark_node)
+ return error_mark_node;
+
+ return TREE_TYPE (e1);
+ }
default:
sorry ("use of `%s' in template",
@@ -5222,11 +6653,13 @@ do_poplevel ()
tsubst_expr. */
tree
-tsubst_copy (t, args, in_decl)
+tsubst_copy (t, args, complain, in_decl)
tree t, args;
+ int complain;
tree in_decl;
{
enum tree_code code;
+ tree r;
if (t == NULL_TREE || t == error_mark_node)
return t;
@@ -5239,14 +6672,48 @@ tsubst_copy (t, args, in_decl)
return do_identifier (DECL_NAME (t), 0, NULL_TREE);
case CONST_DECL:
+ {
+ tree enum_type;
+ tree v;
+
+ if (!DECL_CONTEXT (t))
+ /* This is a global enumeration constant. */
+ return t;
+
+ /* Unfortunately, we cannot just call lookup_name here.
+ Consider:
+
+ template <int I> int f() {
+ enum E { a = I };
+ struct S { void g() { E e = a; } };
+ };
+
+ When we instantiate f<7>::S::g(), say, lookup_name is not
+ clever enough to find f<7>::a. */
+ enum_type
+ = tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
+ /*entering_scope=*/0);
+
+ for (v = TYPE_VALUES (enum_type);
+ v != NULL_TREE;
+ v = TREE_CHAIN (v))
+ if (TREE_PURPOSE (v) == DECL_NAME (t))
+ return TREE_VALUE (v);
+
+ /* We didn't find the name. That should never happen; if
+ name-lookup found it during preliminary parsing, we
+ should find it again here during instantiation. */
+ my_friendly_abort (0);
+ }
+ return t;
+
case FIELD_DECL:
if (DECL_CONTEXT (t))
{
tree ctx;
- if (TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
- return lookup_name (DECL_NAME (t), 0);
- ctx = tsubst (DECL_CONTEXT (t), args, in_decl);
+ ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl,
+ /*entering_scope=*/1);
if (ctx != DECL_CONTEXT (t))
return lookup_field (ctx, DECL_NAME (t), 0, 0);
}
@@ -5255,29 +6722,44 @@ tsubst_copy (t, args, in_decl)
case VAR_DECL:
case FUNCTION_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
- t = tsubst (t, args, in_decl);
+ t = tsubst (t, args, complain, in_decl);
mark_used (t);
return t;
case TEMPLATE_DECL:
if (is_member_template (t))
- return tsubst (t, args, in_decl);
+ return tsubst (t, args, complain, in_decl);
else
return t;
-#if 0
- case IDENTIFIER_NODE:
- return do_identifier (t, 0);
-#endif
-
+ case LOOKUP_EXPR:
+ {
+ /* We must tsbust into a LOOKUP_EXPR in case the names to
+ which it refers is a conversion operator; in that case the
+ name will change. We avoid making unnecessary copies,
+ however. */
+
+ tree id = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
+
+ if (id != TREE_OPERAND (t, 0))
+ {
+ r = build_nt (LOOKUP_EXPR, id);
+ LOOKUP_EXPR_GLOBAL (r) = LOOKUP_EXPR_GLOBAL (t);
+ t = r;
+ }
+
+ return t;
+ }
+
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case NOP_EXPR:
return build1
- (code, tsubst (TREE_TYPE (t), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
+ (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
case INDIRECT_REF:
case PREDECREMENT_EXPR:
@@ -5295,8 +6777,8 @@ tsubst_copy (t, args, in_decl)
case THROW_EXPR:
case TYPEID_EXPR:
return build1
- (code, NULL_TREE,
- tsubst_copy (TREE_OPERAND (t, 0), args, in_decl));
+ (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
case PLUS_EXPR:
case MINUS_EXPR:
@@ -5335,19 +6817,20 @@ tsubst_copy (t, args, in_decl)
case DOTSTAR_EXPR:
case MEMBER_REF:
return build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, in_decl));
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
case CALL_EXPR:
{
tree fn = TREE_OPERAND (t, 0);
if (is_overloaded_fn (fn))
- fn = tsubst_copy (get_first_fn (fn), args, in_decl);
+ fn = tsubst_copy (get_first_fn (fn), args, complain, in_decl);
else
/* Sometimes FN is a LOOKUP_EXPR. */
- fn = tsubst_copy (fn, args, in_decl);
+ fn = tsubst_copy (fn, args, complain, in_decl);
return build_nt
- (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
+ (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, complain,
+ in_decl),
NULL_TREE);
}
@@ -5356,23 +6839,27 @@ tsubst_copy (t, args, in_decl)
tree name = TREE_OPERAND (t, 0);
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
- name = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ name = tsubst_copy (TREE_OPERAND (name, 0), args,
+ complain, in_decl);
name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
}
else if (TREE_CODE (name) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (name, 1)) == BIT_NOT_EXPR)
{
- tree base = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ tree base = tsubst_copy (TREE_OPERAND (name, 0), args,
+ complain, in_decl);
name = TREE_OPERAND (name, 1);
- name = tsubst_copy (TREE_OPERAND (name, 0), args, in_decl);
+ name = tsubst_copy (TREE_OPERAND (name, 0), args,
+ complain, in_decl);
name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
name = build_nt (SCOPE_REF, base, name);
}
else
- name = tsubst_copy (TREE_OPERAND (t, 0), args, in_decl);
+ name = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
return build_nt
- (code, name, tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, in_decl),
+ (code, name, tsubst_copy (TREE_OPERAND (t, 1), args,
+ complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl),
NULL_TREE);
}
@@ -5380,21 +6867,22 @@ tsubst_copy (t, args, in_decl)
case COND_EXPR:
case MODOP_EXPR:
{
- tree r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, in_decl));
+ r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
if (code == BIND_EXPR && !processing_template_decl)
{
- /* This processing should really occur in tsubst_expr,
+ /* This processing should really occur in tsubst_expr,
However, tsubst_expr does not recurse into expressions,
since it assumes that there aren't any statements
inside them. Instead, it simply calls
build_expr_from_tree. So, we need to expand the
BIND_EXPR here. */
tree rtl_expr = begin_stmt_expr ();
- tree block = tsubst_expr (TREE_OPERAND (r, 1), args, in_decl);
+ tree block = tsubst_expr (TREE_OPERAND (r, 1), args,
+ complain, in_decl);
r = finish_stmt_expr (rtl_expr, block);
}
@@ -5403,19 +6891,19 @@ tsubst_copy (t, args, in_decl)
case NEW_EXPR:
{
- tree r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 2), args, in_decl));
+ r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
return r;
}
case DELETE_EXPR:
{
- tree r = build_nt
- (code, tsubst_copy (TREE_OPERAND (t, 0), args, in_decl),
- tsubst_copy (TREE_OPERAND (t, 1), args, in_decl));
+ r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
return r;
@@ -5424,13 +6912,25 @@ tsubst_copy (t, args, in_decl)
case TEMPLATE_ID_EXPR:
{
/* Substituted template arguments */
- tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, in_decl);
- tree chain;
- for (chain = targs; chain; chain = TREE_CHAIN (chain))
- TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
+ tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, complain,
+ in_decl);
+
+ if (targs && TREE_CODE (targs) == TREE_LIST)
+ {
+ tree chain;
+ for (chain = targs; chain; chain = TREE_CHAIN (chain))
+ TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
+ }
+ else if (targs)
+ {
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (targs); ++i)
+ TREE_VEC_ELT (targs, i)
+ = maybe_fold_nontype_arg (TREE_VEC_ELT (targs, i));
+ }
return lookup_template_function
- (tsubst_copy (TREE_OPERAND (t, 0), args, in_decl), targs);
+ (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl), targs);
}
case TREE_LIST:
@@ -5442,13 +6942,13 @@ tsubst_copy (t, args, in_decl)
purpose = TREE_PURPOSE (t);
if (purpose)
- purpose = tsubst_copy (purpose, args, in_decl);
+ purpose = tsubst_copy (purpose, args, complain, in_decl);
value = TREE_VALUE (t);
if (value)
- value = tsubst_copy (value, args, in_decl);
+ value = tsubst_copy (value, args, complain, in_decl);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
- chain = tsubst_copy (chain, args, in_decl);
+ chain = tsubst_copy (chain, args, complain, in_decl);
if (purpose == TREE_PURPOSE (t)
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
@@ -5471,19 +6971,27 @@ tsubst_copy (t, args, in_decl)
case ARRAY_TYPE:
case TYPENAME_TYPE:
case TYPE_DECL:
- return tsubst (t, args, in_decl);
+ return tsubst (t, args, complain, in_decl);
case IDENTIFIER_NODE:
- if (IDENTIFIER_TYPENAME_P (t))
+ if (IDENTIFIER_TYPENAME_P (t)
+ /* Make sure it's not just a variable named `__opr', for instance,
+ which can occur in some existing code. */
+ && TREE_TYPE (t))
return build_typename_overload
- (tsubst (TREE_TYPE (t), args, in_decl));
+ (tsubst (TREE_TYPE (t), args, complain, in_decl));
else
return t;
case CONSTRUCTOR:
- return build
- (CONSTRUCTOR, tsubst (TREE_TYPE (t), args, in_decl), NULL_TREE,
- tsubst_copy (CONSTRUCTOR_ELTS (t), args, in_decl));
+ {
+ r = build
+ (CONSTRUCTOR, tsubst (TREE_TYPE (t), args, complain, in_decl),
+ NULL_TREE, tsubst_copy (CONSTRUCTOR_ELTS (t), args,
+ complain, in_decl));
+ TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
+ return r;
+ }
default:
return t;
@@ -5493,28 +7001,29 @@ tsubst_copy (t, args, in_decl)
/* Like tsubst_copy, but also does semantic processing and RTL expansion. */
tree
-tsubst_expr (t, args, in_decl)
+tsubst_expr (t, args, complain, in_decl)
tree t, args;
+ int complain;
tree in_decl;
{
if (t == NULL_TREE || t == error_mark_node)
return t;
if (processing_template_decl)
- return tsubst_copy (t, args, in_decl);
+ return tsubst_copy (t, args, complain, in_decl);
switch (TREE_CODE (t))
{
case RETURN_STMT:
lineno = TREE_COMPLEXITY (t);
finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
- args, in_decl));
+ args, complain, in_decl));
break;
case EXPR_STMT:
lineno = TREE_COMPLEXITY (t);
finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t),
- args, in_decl));
+ args, complain, in_decl));
break;
case DECL_STMT:
@@ -5525,10 +7034,10 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
emit_line_note (input_filename, lineno);
dcl = start_decl
- (tsubst (TREE_OPERAND (t, 0), args, in_decl),
- tsubst (TREE_OPERAND (t, 1), args, in_decl),
+ (tsubst (TREE_OPERAND (t, 0), args, complain, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, complain, in_decl),
TREE_OPERAND (t, 2) != 0, NULL_TREE, NULL_TREE);
- init = tsubst_expr (TREE_OPERAND (t, 2), args, in_decl);
+ init = tsubst_expr (TREE_OPERAND (t, 2), args, complain, in_decl);
cp_finish_decl
(dcl, init, NULL_TREE, 1, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
resume_momentary (i);
@@ -5542,14 +7051,14 @@ tsubst_expr (t, args, in_decl)
begin_for_stmt ();
for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, in_decl);
finish_for_init_stmt (NULL_TREE);
finish_for_cond (tsubst_expr (FOR_COND (t), args,
- in_decl),
+ complain, in_decl),
NULL_TREE);
- tmp = tsubst_expr (FOR_EXPR (t), args, in_decl);
+ tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
finish_for_expr (tmp, NULL_TREE);
- tsubst_expr (FOR_BODY (t), args, in_decl);
+ tsubst_expr (FOR_BODY (t), args, complain, in_decl);
finish_for_stmt (tmp, NULL_TREE);
}
break;
@@ -5559,9 +7068,9 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
begin_while_stmt ();
finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
- args, in_decl),
+ args, complain, in_decl),
NULL_TREE);
- tsubst_expr (WHILE_BODY (t), args, in_decl);
+ tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
finish_while_stmt (NULL_TREE);
}
break;
@@ -5570,10 +7079,10 @@ tsubst_expr (t, args, in_decl)
{
lineno = TREE_COMPLEXITY (t);
begin_do_stmt ();
- tsubst_expr (DO_BODY (t), args, in_decl);
+ tsubst_expr (DO_BODY (t), args, complain, in_decl);
finish_do_body (NULL_TREE);
finish_do_stmt (tsubst_expr (DO_COND (t), args,
- in_decl),
+ complain, in_decl),
NULL_TREE);
}
break;
@@ -5585,19 +7094,19 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
begin_if_stmt ();
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
- args, in_decl),
+ args, complain, in_decl),
NULL_TREE);
if (tmp = THEN_CLAUSE (t), tmp)
{
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, in_decl);
finish_then_clause (NULL_TREE);
}
if (tmp = ELSE_CLAUSE (t), tmp)
{
begin_else_clause ();
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, in_decl);
finish_else_clause (NULL_TREE);
}
@@ -5614,7 +7123,7 @@ tsubst_expr (t, args, in_decl)
for (substmt = COMPOUND_BODY (t);
substmt != NULL_TREE;
substmt = TREE_CHAIN (substmt))
- tsubst_expr (substmt, args, in_decl);
+ tsubst_expr (substmt, args, complain, in_decl);
return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
}
@@ -5636,19 +7145,19 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
begin_switch_stmt ();
- val = tsubst_expr (SWITCH_COND (t), args, in_decl);
+ val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
finish_switch_cond (val);
if (tmp = TREE_OPERAND (t, 1), tmp)
- tsubst_expr (tmp, args, in_decl);
+ tsubst_expr (tmp, args, complain, in_decl);
finish_switch_stmt (val, NULL_TREE);
}
break;
case CASE_LABEL:
- finish_case_label (tsubst_expr (CASE_LOW (t), args, in_decl),
- tsubst_expr (CASE_HIGH (t), args, in_decl));
+ finish_case_label (tsubst_expr (CASE_LOW (t), args, complain, in_decl),
+ tsubst_expr (CASE_HIGH (t), args, complain, in_decl));
break;
case LABEL_DECL:
@@ -5665,28 +7174,29 @@ tsubst_expr (t, args, in_decl)
/* Computed goto's must be tsubst'd into. On the other hand,
non-computed gotos must not be; the identifier in question
will have no binding. */
- t = tsubst_expr (t, args, in_decl);
+ t = tsubst_expr (t, args, complain, in_decl);
finish_goto_stmt (t);
break;
case ASM_STMT:
lineno = TREE_COMPLEXITY (t);
- finish_asm_stmt (tsubst_expr (ASM_CV_QUAL (t), args, in_decl),
- tsubst_expr (ASM_STRING (t), args, in_decl),
- tsubst_expr (ASM_OUTPUTS (t), args, in_decl),
- tsubst_expr (ASM_INPUTS (t), args, in_decl),
- tsubst_expr (ASM_CLOBBERS (t), args, in_decl));
+ finish_asm_stmt (tsubst_expr (ASM_CV_QUAL (t), args, complain, in_decl),
+ tsubst_expr (ASM_STRING (t), args, complain, in_decl),
+ tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl),
+ tsubst_expr (ASM_INPUTS (t), args, complain, in_decl),
+ tsubst_expr (ASM_CLOBBERS (t), args, complain,
+ in_decl));
break;
case TRY_BLOCK:
lineno = TREE_COMPLEXITY (t);
begin_try_block ();
- tsubst_expr (TRY_STMTS (t), args, in_decl);
+ tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_try_block (NULL_TREE);
{
tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
- tsubst_expr (handler, args, in_decl);
+ tsubst_expr (handler, args, complain, in_decl);
}
finish_handler_sequence (NULL_TREE);
break;
@@ -5698,13 +7208,13 @@ tsubst_expr (t, args, in_decl)
{
tree d = HANDLER_PARMS (t);
expand_start_catch_block
- (tsubst (TREE_OPERAND (d, 1), args, in_decl),
- tsubst (TREE_OPERAND (d, 0), args, in_decl));
+ (tsubst (TREE_OPERAND (d, 1), args, complain, in_decl),
+ tsubst (TREE_OPERAND (d, 0), args, complain, in_decl));
}
else
expand_start_catch_block (NULL_TREE, NULL_TREE);
finish_handler_parms (NULL_TREE);
- tsubst_expr (HANDLER_BODY (t), args, in_decl);
+ tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
finish_handler (NULL_TREE);
break;
@@ -5712,67 +7222,86 @@ tsubst_expr (t, args, in_decl)
lineno = TREE_COMPLEXITY (t);
t = TREE_TYPE (t);
if (TREE_CODE (t) == ENUMERAL_TYPE)
- tsubst_enum (t, args, NULL);
+ tsubst (t, args, complain, NULL_TREE);
break;
default:
- return build_expr_from_tree (tsubst_copy (t, args, in_decl));
+ return build_expr_from_tree (tsubst_copy (t, args, complain, in_decl));
}
return NULL_TREE;
}
+/* Instantiate the indicated variable or function template TMPL with
+ the template arguments in TARG_PTR. */
+
tree
instantiate_template (tmpl, targ_ptr)
tree tmpl, targ_ptr;
{
tree fndecl;
+ tree gen_tmpl;
+ tree spec;
int i, len;
struct obstack *old_fmp_obstack;
extern struct obstack *function_maybepermanent_obstack;
+ tree inner_args;
if (tmpl == error_mark_node)
return error_mark_node;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
- /* Check to see if we already have this specialization. This does work
- for member template specializations; the list is set up from the
- tsubst TEMPLATE_DECL case when the containing class is instantiated. */
- if (DECL_FUNCTION_TEMPLATE_P (tmpl))
+ /* Check to see if we already have this specialization. */
+ spec = retrieve_specialization (tmpl, targ_ptr);
+ if (spec != NULL_TREE)
+ return spec;
+
+ if (DECL_TEMPLATE_INFO (tmpl))
{
- tree spec = retrieve_specialization (tmpl, targ_ptr);
-
+ /* The TMPL is a partial instantiation. To get a full set of
+ arguments we must add the arguments used to perform the
+ partial instantiation. */
+ targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
+ targ_ptr);
+ gen_tmpl = most_general_template (tmpl);
+
+ /* Check to see if we already have this specialization. */
+ spec = retrieve_specialization (gen_tmpl, targ_ptr);
if (spec != NULL_TREE)
return spec;
}
+ else
+ gen_tmpl = tmpl;
push_obstacks (&permanent_obstack, &permanent_obstack);
old_fmp_obstack = function_maybepermanent_obstack;
function_maybepermanent_obstack = &permanent_obstack;
- len = DECL_NTPARMS (tmpl);
-
+ len = DECL_NTPARMS (gen_tmpl);
+ inner_args = innermost_args (targ_ptr);
i = len;
while (i--)
{
- tree t = TREE_VEC_ELT (targ_ptr, i);
+ tree t = TREE_VEC_ELT (inner_args, i);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
tree nt = target_type (t);
if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
{
cp_error ("type `%T' composed from a local class is not a valid template-argument", t);
- cp_error (" trying to instantiate `%D'", tmpl);
+ cp_error (" trying to instantiate `%D'", gen_tmpl);
fndecl = error_mark_node;
goto out;
}
}
- TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
}
targ_ptr = copy_to_permanent (targ_ptr);
/* substitute template parameters */
- fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, tmpl);
+ fndecl = tsubst (DECL_RESULT (gen_tmpl), targ_ptr, /*complain=*/1, gen_tmpl);
+ /* The DECL_TI_TEMPLATE should always be the immediate parent
+ template, not the most general template. */
+ DECL_TI_TEMPLATE (fndecl) = tmpl;
if (flag_external_templates)
add_pending_template (fndecl);
@@ -5802,76 +7331,18 @@ overload_template_name (type)
pushdecl_class_level (decl);
}
-/* Like type_unification but designed specially to handle conversion
- operators.
-
- The FN is a TEMPLATE_DECL for a function. The ARGS are the
- arguments that are being used when calling it.
-
- If FN is a conversion operator, RETURN_TYPE is the type desired as
- the result of the conversion operator.
-
- The EXTRA_FN_ARG, if any, is the type of an additional
- parameter to be added to the beginning of FN's parameter list.
-
- The other arguments are as for type_unification. */
-
-int
-fn_type_unification (fn, explicit_targs, targs, args, return_type,
- strict, extra_fn_arg)
- tree fn, explicit_targs, targs, args, return_type;
- unification_kind_t strict;
- tree extra_fn_arg;
-{
- tree parms;
-
- my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
-
- parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
-
- if (IDENTIFIER_TYPENAME_P (DECL_NAME (fn)))
- {
- /* This is a template conversion operator. Use the return types
- as well as the argument types. */
- parms = scratch_tree_cons (NULL_TREE,
- TREE_TYPE (TREE_TYPE (fn)),
- parms);
- args = scratch_tree_cons (NULL_TREE, return_type, args);
- }
-
- if (extra_fn_arg != NULL_TREE)
- parms = scratch_tree_cons (NULL_TREE, extra_fn_arg, parms);
-
- /* We allow incomplete unification without an error message here
- because the standard doesn't seem to explicitly prohibit it. Our
- callers must be ready to deal with unification failures in any
- event. */
- return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
- targs,
- parms,
- args,
- explicit_targs,
- strict, 1);
-}
-
-
-/* Type unification.
-
- We have a function template signature with one or more references to
- template parameters, and a parameter list we wish to fit to this
- template. If possible, produce a list of parameters for the template
- which will cause it to fit the supplied parameter list.
+/* The FN is a TEMPLATE_DECL for a function. The ARGS are the
+ arguments that are being used when calling it. TARGS is a vector
+ into which the deduced template arguments are placed.
Return zero for success, 2 for an incomplete match that doesn't resolve
all the types, and 1 for complete failure. An error message will be
printed only for an incomplete match.
- TPARMS[NTPARMS] is an array of template parameter types.
+ If FN is a conversion operator, RETURN_TYPE is the type desired as
+ the result of the conversion operator.
- TARGS[NTPARMS] is the array into which the deduced template
- parameter values are placed. PARMS is the function template's
- signature (using TEMPLATE_PARM_IDX nodes), and ARGS is the argument
- list we're trying to match against it.
+ TPARMS is a vector of template parameters.
The EXPLICIT_TARGS are explicit template arguments provided via a
template-id.
@@ -5893,49 +7364,79 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
when doing an explicit instantiation as in [temp.explicit],
when determining an explicit specialization as in
[temp.expl.spec], or when taking the address of a function
- template, as in [temp.deduct.funcaddr]. */
+ template, as in [temp.deduct.funcaddr].
+
+ The other arguments are as for type_unification. */
int
-type_unification (tparms, targs, parms, args, explicit_targs,
- strict, allow_incomplete)
- tree tparms, targs, parms, args, explicit_targs;
+fn_type_unification (fn, explicit_targs, targs, args, return_type,
+ strict)
+ tree fn, explicit_targs, targs, args, return_type;
unification_kind_t strict;
- int allow_incomplete;
{
- int* explicit_mask;
- int i;
-
- for (i = 0; i < TREE_VEC_LENGTH (tparms); i++)
- TREE_VEC_ELT (targs, i) = NULL_TREE;
+ tree parms;
+ tree fntype;
- if (explicit_targs != NULL_TREE)
+ my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
+
+ fntype = TREE_TYPE (fn);
+ if (explicit_targs)
{
- tree arg_vec;
- arg_vec = coerce_template_parms (tparms, explicit_targs, NULL_TREE, 0,
- 0);
+ /* [temp.deduct]
+
+ The specified template arguments must match the template
+ parameters in kind (i.e., type, nontype, template), and there
+ must not be more arguments than there are parameters;
+ otherwise type deduction fails.
+
+ Nontype arguments must match the types of the corresponding
+ nontype template parameters, or must be convertible to the
+ types of the corresponding nontype parameters as specified in
+ _temp.arg.nontype_, otherwise type deduction fails.
+
+ All references in the function type of the function template
+ to the corresponding template parameters are replaced by the
+ specified template argument values. If a substitution in a
+ template parameter or in the function type of the function
+ template results in an invalid type, type deduction fails. */
+ int i;
+ tree converted_args;
- if (arg_vec == error_mark_node)
+ converted_args
+ = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ explicit_targs, NULL_TREE, /*complain=*/0,
+ /*require_all_arguments=*/0));
+ if (converted_args == error_mark_node)
return 1;
- explicit_mask = alloca (sizeof (int) * TREE_VEC_LENGTH (targs));
- bzero ((char *) explicit_mask, sizeof(int) * TREE_VEC_LENGTH (targs));
+ fntype = tsubst (fntype, converted_args, /*complain=*/0, NULL_TREE);
+ if (fntype == error_mark_node)
+ return 1;
- for (i = 0;
- i < TREE_VEC_LENGTH (arg_vec)
- && TREE_VEC_ELT (arg_vec, i) != NULL_TREE;
- ++i)
- {
- TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (arg_vec, i);
- /* Let unify know that this argument was explicit. */
- explicit_mask [i] = 1;
- }
+ /* Place the explicitly specified arguments in TARGS. */
+ for (i = 0; i < TREE_VEC_LENGTH (targs); i++)
+ TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
+ }
+
+ parms = TYPE_ARG_TYPES (fntype);
+
+ if (DECL_CONV_FN_P (fn))
+ {
+ /* This is a template conversion operator. Use the return types
+ as well as the argument types. We use it instead of 'this', since
+ we could be comparing conversions from different classes. */
+ parms = scratch_tree_cons (NULL_TREE, TREE_TYPE (fntype),
+ TREE_CHAIN (parms));
+ args = scratch_tree_cons (NULL_TREE, return_type, TREE_CHAIN (args));
}
- else
- explicit_mask = 0;
- return
- type_unification_real (tparms, targs, parms, args, 0,
- strict, allow_incomplete, explicit_mask);
+ /* We allow incomplete unification without an error message here
+ because the standard doesn't seem to explicitly prohibit it. Our
+ callers must be ready to deal with unification failures in any
+ event. */
+ return type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ targs, parms, args, /*subr=*/0,
+ strict, /*allow_incomplete*/1);
}
/* Adjust types before performing type deduction, as described in
@@ -5945,7 +7446,7 @@ type_unification (tparms, targs, parms, args, explicit_targs,
the argument passed to the call, or the type of the value
intialized with the result of the conversion function. */
-void
+static void
maybe_adjust_types_for_deduction (strict, parm, arg)
unification_kind_t strict;
tree* parm;
@@ -5995,8 +7496,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
deduction. */
if (TREE_CODE (*arg) == ARRAY_TYPE)
*arg = build_pointer_type (TREE_TYPE (*arg));
- else if (TREE_CODE (*arg) == FUNCTION_TYPE
- || TREE_CODE (*arg) == METHOD_TYPE)
+ else if (TREE_CODE (*arg) == FUNCTION_TYPE)
*arg = build_pointer_type (*arg);
else
*arg = TYPE_MAIN_VARIANT (*arg);
@@ -6013,9 +7513,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm);
}
-/* Like type_unfication. EXPLICIT_MASK, if non-NULL, is an array of
- integers, with ones in positions corresponding to arguments in
- targs that were provided explicitly, and zeros elsewhere.
+/* Like type_unfication.
If SUBR is 1, we're being called recursively (to unify the
arguments of a function or method parameter of a function
@@ -6023,12 +7521,11 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
static int
type_unification_real (tparms, targs, parms, args, subr,
- strict, allow_incomplete, explicit_mask)
+ strict, allow_incomplete)
tree tparms, targs, parms, args;
int subr;
unification_kind_t strict;
int allow_incomplete;
- int* explicit_mask;
{
tree parm, arg;
int i;
@@ -6075,7 +7572,9 @@ type_unification_real (tparms, targs, parms, args, subr,
if (arg == error_mark_node)
return 1;
if (arg == unknown_type_node)
- return 1;
+ /* We can't deduce anything from this, but we might get all the
+ template args from other function args. */
+ continue;
/* Conversions will be performed on a function argument that
corresponds with a function parameter that contains only
@@ -6095,7 +7594,7 @@ type_unification_real (tparms, targs, parms, args, subr,
if (strict == DEDUCE_EXACT)
{
- if (comptypes (parm, type, 1))
+ if (same_type_p (parm, type))
continue;
}
else
@@ -6107,47 +7606,30 @@ type_unification_real (tparms, targs, parms, args, subr,
return 1;
}
-#if 0
- if (TREE_CODE (arg) == VAR_DECL)
- arg = TREE_TYPE (arg);
- else if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'e')
- arg = TREE_TYPE (arg);
-#else
if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
{
my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
- if (TREE_CODE (arg) == OVERLOAD
- && TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL)
+ if (type_unknown_p (arg))
{
- tree targs;
- tree arg_type;
-
- /* Have to back unify here */
- arg = OVL_FUNCTION (arg);
- targs = make_scratch_vec (DECL_NTPARMS (arg));
- arg_type = TREE_TYPE (arg);
- maybe_adjust_types_for_deduction (strict, &parm, &arg_type);
- parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
- arg_type = scratch_tree_cons (NULL_TREE, arg_type, NULL_TREE);
- return
- type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
- targs, arg_type, parm, NULL_TREE,
- DEDUCE_EXACT, allow_incomplete);
+ /* [temp.deduct.type] A template-argument can be deduced from
+ a pointer to function or pointer to member function
+ argument if the set of overloaded functions does not
+ contain function templates and at most one of a set of
+ overloaded functions provides a unique match. */
+
+ if (resolve_overloaded_unification
+ (tparms, targs, parm, arg, strict, sub_strict)
+ != 0)
+ return 1;
+ continue;
}
arg = TREE_TYPE (arg);
}
-#endif
- if (! flag_ansi && arg == TREE_TYPE (null_node))
- {
- warning ("using type void* for NULL");
- arg = ptr_type_node;
- }
if (!subr)
maybe_adjust_types_for_deduction (strict, &parm, &arg);
- switch (unify (tparms, targs, parm, arg, sub_strict,
- explicit_mask))
+ switch (unify (tparms, targs, parm, arg, sub_strict))
{
case 0:
break;
@@ -6175,9 +7657,341 @@ type_unification_real (tparms, targs, parms, args, subr,
return 0;
}
+/* Subroutine of type_unification_real. Args are like the variables at the
+ call site. ARG is an overloaded function (or template-id); we try
+ deducing template args from each of the overloads, and if only one
+ succeeds, we go with that. Modifies TARGS and returns 0 on success. */
+
+static int
+resolve_overloaded_unification (tparms, targs, parm, arg, strict,
+ sub_strict)
+ tree tparms, targs, parm, arg;
+ unification_kind_t strict;
+ int sub_strict;
+{
+ tree tempargs = copy_node (targs);
+ int good = 0;
+
+ if (TREE_CODE (arg) == ADDR_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+
+ if (TREE_CODE (arg) == COMPONENT_REF)
+ /* Handle `&x' where `x' is some static or non-static member
+ function name. */
+ arg = TREE_OPERAND (arg, 1);
+
+ if (TREE_CODE (arg) == OFFSET_REF)
+ arg = TREE_OPERAND (arg, 1);
+
+ /* Strip baselink information. */
+ while (TREE_CODE (arg) == TREE_LIST)
+ arg = TREE_VALUE (arg);
+
+ if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
+ {
+ /* If we got some explicit template args, we need to plug them into
+ the affected templates before we try to unify, in case the
+ explicit args will completely resolve the templates in question. */
+
+ tree expl_subargs = TREE_OPERAND (arg, 1);
+ arg = TREE_OPERAND (arg, 0);
+
+ for (; arg; arg = OVL_NEXT (arg))
+ {
+ tree fn = OVL_CURRENT (arg);
+ tree subargs, elem;
+
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ continue;
+
+ subargs = get_bindings_overload (fn, DECL_RESULT (fn), expl_subargs);
+ if (subargs)
+ {
+ elem = tsubst (TREE_TYPE (fn), subargs, /*complain=*/0,
+ NULL_TREE);
+ if (TREE_CODE (elem) == METHOD_TYPE)
+ elem = build_ptrmemfunc_type (build_pointer_type (elem));
+ good += try_one_overload (tparms, targs, tempargs, parm, elem,
+ strict, sub_strict);
+ }
+ }
+ }
+ else if (TREE_CODE (arg) == OVERLOAD)
+ {
+ for (; arg; arg = OVL_NEXT (arg))
+ {
+ tree type = TREE_TYPE (OVL_CURRENT (arg));
+ if (TREE_CODE (type) == METHOD_TYPE)
+ type = build_ptrmemfunc_type (build_pointer_type (type));
+ good += try_one_overload (tparms, targs, tempargs, parm,
+ type,
+ strict, sub_strict);
+ }
+ }
+ else
+ my_friendly_abort (981006);
+
+ /* [temp.deduct.type] A template-argument can be deduced from a pointer
+ to function or pointer to member function argument if the set of
+ overloaded functions does not contain function templates and at most
+ one of a set of overloaded functions provides a unique match.
+
+ So if we found multiple possibilities, we return success but don't
+ deduce anything. */
+
+ if (good == 1)
+ {
+ int i = TREE_VEC_LENGTH (targs);
+ for (; i--; )
+ if (TREE_VEC_ELT (tempargs, i))
+ TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (tempargs, i);
+ }
+ if (good)
+ return 0;
+
+ return 1;
+}
+
+/* Subroutine of resolve_overloaded_unification; does deduction for a single
+ overload. Fills TARGS with any deduced arguments, or error_mark_node if
+ different overloads deduce different arguments for a given parm.
+ Returns 1 on success. */
+
+static int
+try_one_overload (tparms, orig_targs, targs, parm, arg, strict,
+ sub_strict)
+ tree tparms, orig_targs, targs, parm, arg;
+ unification_kind_t strict;
+ int sub_strict;
+{
+ int nargs;
+ tree tempargs;
+ int i;
+
+ /* [temp.deduct.type] A template-argument can be deduced from a pointer
+ to function or pointer to member function argument if the set of
+ overloaded functions does not contain function templates and at most
+ one of a set of overloaded functions provides a unique match.
+
+ So if this is a template, just return success. */
+
+ if (uses_template_parms (arg))
+ return 1;
+
+ maybe_adjust_types_for_deduction (strict, &parm, &arg);
+
+ /* We don't copy orig_targs for this because if we have already deduced
+ some template args from previous args, unify would complain when we
+ try to deduce a template parameter for the same argument, even though
+ there isn't really a conflict. */
+ nargs = TREE_VEC_LENGTH (targs);
+ tempargs = make_scratch_vec (nargs);
+
+ if (unify (tparms, tempargs, parm, arg, sub_strict) != 0)
+ return 0;
+
+ /* First make sure we didn't deduce anything that conflicts with
+ explicitly specified args. */
+ for (i = nargs; i--; )
+ {
+ tree elt = TREE_VEC_ELT (tempargs, i);
+ tree oldelt = TREE_VEC_ELT (orig_targs, i);
+
+ if (elt == NULL_TREE)
+ continue;
+ else if (uses_template_parms (elt))
+ {
+ /* Since we're unifying against ourselves, we will fill in template
+ args used in the function parm list with our own template parms.
+ Discard them. */
+ TREE_VEC_ELT (tempargs, i) = NULL_TREE;
+ continue;
+ }
+ else if (oldelt && ! template_args_equal (oldelt, elt))
+ return 0;
+ }
+
+ for (i = nargs; i--; )
+ {
+ tree elt = TREE_VEC_ELT (tempargs, i);
+
+ if (elt)
+ TREE_VEC_ELT (targs, i) = elt;
+ }
+
+ return 1;
+}
+
+/* PARM is a template class (perhaps with unbound template
+ parameters). ARG is a fully instantiated type. If ARG can be
+ bound to PARM, return ARG, otherwise return NULL_TREE. TPARMS and
+ TARGS are as for unify. */
+
+static tree
+try_class_unification (tparms, targs, parm, arg)
+ tree tparms;
+ tree targs;
+ tree parm;
+ tree arg;
+{
+ int i;
+ tree copy_of_targs;
+
+ if (!CLASSTYPE_TEMPLATE_INFO (arg)
+ || CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
+ return NULL_TREE;
+
+ /* We need to make a new template argument vector for the call to
+ unify. If we used TARGS, we'd clutter it up with the result of
+ the attempted unification, even if this class didn't work out.
+ We also don't want to commit ourselves to all the unifications
+ we've already done, since unification is supposed to be done on
+ an argument-by-argument basis. In other words, consider the
+ following pathological case:
+
+ template <int I, int J, int K>
+ struct S {};
+
+ template <int I, int J>
+ struct S<I, J, 2> : public S<I, I, I>, S<J, J, J> {};
+
+ template <int I, int J, int K>
+ void f(S<I, J, K>, S<I, I, I>);
+
+ void g() {
+ S<0, 0, 0> s0;
+ S<0, 1, 2> s2;
+
+ f(s0, s2);
+ }
+
+ Now, by the time we consider the unification involving `s2', we
+ already know that we must have `f<0, 0, 0>'. But, even though
+ `S<0, 1, 2>' is derived from `S<0, 0, 0>', the code is not legal
+ because there are two ways to unify base classes of S<0, 1, 2>
+ with S<I, I, I>. If we kept the already deduced knowledge, we
+ would reject the possibility I=1. */
+ push_momentary ();
+ copy_of_targs = make_temp_vec (TREE_VEC_LENGTH (targs));
+ i = unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
+ CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE);
+ pop_momentary ();
+
+ /* If unification failed, we're done. */
+ if (i != 0)
+ return NULL_TREE;
+ else
+ return arg;
+}
+
+/* Subroutine of get_template_base. RVAL, if non-NULL, is a base we
+ have alreay discovered to be satisfactory. ARG_BINFO is the binfo
+ for the base class of ARG that we are currently examining. */
+
+static tree
+get_template_base_recursive (tparms, targs, parm,
+ arg_binfo, rval, flags)
+ tree tparms;
+ tree targs;
+ tree arg_binfo;
+ tree rval;
+ tree parm;
+ int flags;
+{
+ tree binfos;
+ int i, n_baselinks;
+ tree arg = BINFO_TYPE (arg_binfo);
+
+ if (!(flags & GTB_IGNORE_TYPE))
+ {
+ tree r = try_class_unification (tparms, targs,
+ parm, arg);
+
+ /* If there is more than one satisfactory baseclass, then:
+
+ [temp.deduct.call]
+
+ If they yield more than one possible deduced A, the type
+ deduction fails.
+
+ applies. */
+ if (r && rval && !same_type_p (r, rval))
+ return error_mark_node;
+ else if (r)
+ rval = r;
+ }
+
+ binfos = BINFO_BASETYPES (arg_binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
+ /* Process base types. */
+ for (i = 0; i < n_baselinks; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ int this_virtual;
+
+ /* Skip this base, if we've already seen it. */
+ if (BINFO_MARKED (base_binfo))
+ continue;
+
+ this_virtual =
+ (flags & GTB_VIA_VIRTUAL) || TREE_VIA_VIRTUAL (base_binfo);
+
+ /* When searching for a non-virtual, we cannot mark virtually
+ found binfos. */
+ if (! this_virtual)
+ SET_BINFO_MARKED (base_binfo);
+
+ rval = get_template_base_recursive (tparms, targs,
+ parm,
+ base_binfo,
+ rval,
+ GTB_VIA_VIRTUAL * this_virtual);
+
+ /* If we discovered more than one matching base class, we can
+ stop now. */
+ if (rval == error_mark_node)
+ return error_mark_node;
+ }
+
+ return rval;
+}
+
+/* Given a template type PARM and a class type ARG, find the unique
+ base type in ARG that is an instance of PARM. We do not examine
+ ARG itself; only its base-classes. If there is no appropriate base
+ class, return NULL_TREE. If there is more than one, return
+ error_mark_node. PARM may be the type of a partial specialization,
+ as well as a plain template type. Used by unify. */
+
+static tree
+get_template_base (tparms, targs, parm, arg)
+ tree tparms;
+ tree targs;
+ tree parm;
+ tree arg;
+{
+ tree rval;
+ tree arg_binfo;
+
+ my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)), 92);
+
+ arg_binfo = TYPE_BINFO (complete_type (arg));
+ rval = get_template_base_recursive (tparms, targs,
+ parm, arg_binfo,
+ NULL_TREE,
+ GTB_IGNORE_TYPE);
+
+ /* Since get_template_base_recursive marks the bases classes, we
+ must unmark them here. */
+ dfs_walk (arg_binfo, dfs_unmark, markedp, 0);
+
+ return rval;
+}
+
/* Returns the level of DECL, which declares a template parameter. */
-int
+static int
template_decl_level (decl)
tree decl;
{
@@ -6200,18 +8014,16 @@ template_decl_level (decl)
cv-qualifiers of each type, given STRICT as documented for unify.
Returns non-zero iff the unification is OK on that basis.*/
-int
+static int
check_cv_quals_for_unify (strict, arg, parm)
int strict;
tree arg;
tree parm;
{
return !((!(strict & UNIFY_ALLOW_MORE_CV_QUAL)
- && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
- || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm)))
+ && !at_least_as_qualified_p (arg, parm))
|| (!(strict & UNIFY_ALLOW_LESS_CV_QUAL)
- && (TYPE_READONLY (arg) > TYPE_READONLY (parm)
- || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))));
+ && (!at_least_as_qualified_p (parm, arg))));
}
/* Takes parameters as for type_unification. Returns 0 if the
@@ -6227,13 +8039,15 @@ check_cv_quals_for_unify (strict, arg, parm)
UNIFY_ALLOW_DERIVED:
Allow the deduced ARG to be a template base class of ARG,
or a pointer to a template base class of the type pointed to by
- ARG. */
+ ARG.
+ UNIFY_ALLOW_INTEGER:
+ Allow any integral type to be deduced. See the TEMPLATE_PARM_INDEX
+ case for more information. */
-int
-unify (tparms, targs, parm, arg, strict, explicit_mask)
+static int
+unify (tparms, targs, parm, arg, strict)
tree tparms, targs, parm, arg;
int strict;
- int* explicit_mask;
{
int idx;
tree targ;
@@ -6249,9 +8063,12 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
if (arg == error_mark_node)
return 1;
if (arg == unknown_type_node)
- return 1;
+ /* We can't deduce anything from this, but we might get all the
+ template args from other function args. */
+ return 0;
+
/* If PARM uses template parameters, then we can't bail out here,
- even in ARG == PARM, since we won't record unifications for the
+ even if ARG == PARM, since we won't record unifications for the
template parameters. We might need them if we're trying to
figure out which of two things is more specialized. */
if (arg == parm && !uses_template_parms (parm))
@@ -6286,7 +8103,7 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
/* The PARM is not one we're trying to unify. Just check
to see if it matches ARG. */
return (TREE_CODE (arg) == TREE_CODE (parm)
- && comptypes (parm, arg, 1)) ? 0 : 1;
+ && same_type_p (parm, arg)) ? 0 : 1;
idx = TEMPLATE_TYPE_IDX (parm);
targ = TREE_VEC_ELT (targs, idx);
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
@@ -6298,16 +8115,9 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
&& TREE_CODE (tparm) != TEMPLATE_DECL))
return 1;
- if (!strict && targ != NULL_TREE
- && explicit_mask && explicit_mask[idx])
- /* An explicit template argument. Don't even try to match
- here; the overload resolution code will manage check to
- see whether the call is legal. */
- return 0;
-
if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
{
- if (CLASSTYPE_TEMPLATE_INFO (parm))
+ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm))
{
/* We arrive here when PARM does not involve template
specialization. */
@@ -6317,8 +8127,8 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
return 1;
{
- tree parmtmpl = CLASSTYPE_TI_TEMPLATE (parm);
- tree parmvec = CLASSTYPE_TI_ARGS (parm);
+ tree parmtmpl = TYPE_TI_TEMPLATE (parm);
+ tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = CLASSTYPE_TI_ARGS (arg);
tree argtmplvec
= DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
@@ -6331,24 +8141,22 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
template <class T, class Allocator = allocator>
class vector. */
- if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1)
+ if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
== error_mark_node)
return 1;
- /* Deduce arguments T, i from TT<T> or TT<i>. */
+ /* Deduce arguments T, i from TT<T> or TT<i>.
+ We check each element of PARMVEC and ARGVEC individually
+ rather than the whole TREE_VEC since they can have
+ different number of elements. */
+
for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
{
tree t = TREE_VEC_ELT (parmvec, i);
- if (TREE_CODE (t) != TEMPLATE_TYPE_PARM
- && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
- && TREE_CODE (t) != TEMPLATE_PARM_INDEX)
- continue;
-
- /* This argument can be deduced. */
if (unify (tparms, targs, t,
TREE_VEC_ELT (argvec, i),
- UNIFY_ALLOW_NONE, explicit_mask))
+ UNIFY_ALLOW_NONE))
return 1;
}
}
@@ -6368,18 +8176,30 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
/* Consider the case where ARG is `const volatile int' and
PARM is `const T'. Then, T should be `volatile int'. */
arg =
- cp_build_type_variant (arg,
- TYPE_READONLY (arg) > TYPE_READONLY (parm),
- TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm));
+ cp_build_qualified_type (arg,
+ CP_TYPE_QUALS (arg)
+ & ~CP_TYPE_QUALS (parm));
}
/* Simple cases: Value already set, does match or doesn't. */
- if (targ != NULL_TREE
- && (comptypes (targ, arg, 1)
- || (explicit_mask && explicit_mask[idx])))
+ if (targ != NULL_TREE && same_type_p (targ, arg))
return 0;
else if (targ)
return 1;
+
+ /* Make sure that ARG is not a variable-sized array. (Note that
+ were talking about variable-sized arrays (like `int[n]'),
+ rather than arrays of unknown size (like `int[]').) We'll
+ get very confused by such a type since the bound of the array
+ will not be computable in an instantiation. Besides, such
+ types are not allowed in ISO C++, so we can do as we please
+ here. */
+ if (TREE_CODE (arg) == ARRAY_TYPE
+ && !uses_template_parms (arg)
+ && (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (arg)))
+ != INTEGER_CST))
+ return 1;
+
TREE_VEC_ELT (targs, idx) = arg;
return 0;
@@ -6407,6 +8227,22 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
my_friendly_abort (42);
}
+ /* [temp.deduct.type] If, in the declaration of a function template
+ with a non-type template-parameter, the non-type
+ template-parameter is used in an expression in the function
+ parameter-list and, if the corresponding template-argument is
+ deduced, the template-argument type shall match the type of the
+ template-parameter exactly, except that a template-argument
+ deduced from an array bound may be of any integral type. */
+ if (same_type_p (TREE_TYPE (arg), TREE_TYPE (parm)))
+ /* OK */;
+ else if ((strict & UNIFY_ALLOW_INTEGER)
+ && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (parm)) == BOOLEAN_TYPE))
+ /* OK */;
+ else
+ return 1;
+
TREE_VEC_ELT (targs, idx) = copy_to_permanent (arg);
return 0;
@@ -6416,8 +8252,7 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
return (unify (tparms, targs, parm,
- TYPE_PTRMEMFUNC_FN_TYPE (arg), strict,
- explicit_mask));
+ TYPE_PTRMEMFUNC_FN_TYPE (arg), strict));
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
@@ -6445,14 +8280,14 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
sub_strict &= ~UNIFY_ALLOW_DERIVED;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE
- (arg), sub_strict, explicit_mask);
+ (arg), sub_strict);
}
case REFERENCE_TYPE:
if (TREE_CODE (arg) != REFERENCE_TYPE)
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE, explicit_mask);
+ UNIFY_ALLOW_NONE);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
@@ -6462,10 +8297,10 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
return 1;
if (TYPE_DOMAIN (parm) != NULL_TREE
&& unify (tparms, targs, TYPE_DOMAIN (parm),
- TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE, explicit_mask) != 0)
+ TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE) != 0)
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE, explicit_mask);
+ UNIFY_ALLOW_NONE);
case REAL_TYPE:
case COMPLEX_TYPE:
@@ -6475,23 +8310,23 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
- if (TREE_CODE (parm) == INTEGER_TYPE)
+ if (TREE_CODE (parm) == INTEGER_TYPE
+ && TREE_CODE (TYPE_MAX_VALUE (parm)) != INTEGER_CST)
{
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
&& unify (tparms, targs, TYPE_MIN_VALUE (parm),
- TYPE_MIN_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TYPE_MIN_VALUE (arg), UNIFY_ALLOW_INTEGER))
return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
&& unify (tparms, targs, TYPE_MAX_VALUE (parm),
- TYPE_MAX_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TYPE_MAX_VALUE (arg), UNIFY_ALLOW_INTEGER))
return 1;
}
- else if (TREE_CODE (parm) == REAL_TYPE
- /* We use the TYPE_MAIN_VARIANT since we have already
- checked cv-qualification at the top of the
- function. */
- && !comptypes (TYPE_MAIN_VARIANT (arg),
- TYPE_MAIN_VARIANT (parm), 1))
+ /* We use the TYPE_MAIN_VARIANT since we have already
+ checked cv-qualification at the top of the
+ function. */
+ else if (!same_type_p (TYPE_MAIN_VARIANT (arg),
+ TYPE_MAIN_VARIANT (parm)))
return 1;
/* As far as unification is concerned, this wins. Later checks
@@ -6518,44 +8353,63 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
if (unify (tparms, targs,
TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
- UNIFY_ALLOW_NONE, explicit_mask))
+ UNIFY_ALLOW_NONE))
return 1;
return 0;
}
case RECORD_TYPE:
+ case UNION_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
- arg, strict, explicit_mask);
+ arg, strict);
- if (TREE_CODE (arg) != RECORD_TYPE)
+ if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
- if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
+ if (CLASSTYPE_TEMPLATE_INFO (parm))
{
tree t = NULL_TREE;
+
if (strict & UNIFY_ALLOW_DERIVED)
- /* [temp.deduct.call]
-
- If P is a class, and P has the form template-id, then A
- can be a derived class of the deduced A. Likewise, if
- P is a pointer to a class of the form template-id, A
- can be a pointer to a derived class pointed to by the
- deduced A. */
- t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
- else if
- (CLASSTYPE_TEMPLATE_INFO (arg)
- && CLASSTYPE_TI_TEMPLATE (parm) == CLASSTYPE_TI_TEMPLATE (arg))
+ {
+ /* First, we try to unify the PARM and ARG directly. */
+ t = try_class_unification (tparms, targs,
+ parm, arg);
+
+ if (!t)
+ {
+ /* Fallback to the special case allowed in
+ [temp.deduct.call]:
+
+ If P is a class, and P has the form
+ template-id, then A can be a derived class of
+ the deduced A. Likewise, if P is a pointer to
+ a class of the form template-id, A can be a
+ pointer to a derived class pointed to by the
+ deduced A. */
+ t = get_template_base (tparms, targs,
+ parm, arg);
+
+ if (! t || t == error_mark_node)
+ return 1;
+ }
+ }
+ else if (CLASSTYPE_TEMPLATE_INFO (arg)
+ && (CLASSTYPE_TI_TEMPLATE (parm)
+ == CLASSTYPE_TI_TEMPLATE (arg)))
+ /* Perhaps PARM is something like S<U> and ARG is S<int>.
+ Then, we should unify `int' and `U'. */
t = arg;
- if (! t || t == error_mark_node)
+ else
+ /* There's no chance of unication succeeding. */
return 1;
return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE,
- explicit_mask);
+ CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
}
- else if (!comptypes (TYPE_MAIN_VARIANT (parm),
- TYPE_MAIN_VARIANT (arg), 1))
+ else if (!same_type_p (TYPE_MAIN_VARIANT (parm),
+ TYPE_MAIN_VARIANT (arg)))
return 1;
return 0;
@@ -6565,20 +8419,20 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
return 1;
if (unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TREE_TYPE (arg), UNIFY_ALLOW_NONE))
return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), 1,
- DEDUCE_EXACT, 0, explicit_mask);
+ DEDUCE_EXACT, 0);
case OFFSET_TYPE:
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
- TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
+ TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE))
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE, explicit_mask);
+ strict);
case CONST_DECL:
if (arg != decl_constant_value (parm))
@@ -6608,41 +8462,31 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
integer_type_node,
arg, t2));
- return unify (tparms, targs, t1, t, UNIFY_ALLOW_NONE,
- explicit_mask);
+ return unify (tparms, targs, t1, t, strict);
}
/* else fall through */
default:
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
- {
- /* We're looking at an expression. This can happen with
- something like:
-
- template <int I>
- void foo(S<I>, S<I + 2>);
+ /* We're looking at an expression. This can happen with
+ something like:
+
+ template <int I>
+ void foo(S<I>, S<I + 2>);
- If the call looked like:
+ This is a "nondeduced context":
- foo(S<2>(), S<4>());
+ [deduct.type]
+
+ The nondeduced contexts are:
- we would have already matched `I' with `2'. Now, we'd
- like to know if `4' matches `I + 2'. So, we substitute
- into that expression, and fold constants, in the hope of
- figuring it out. */
- tree t =
- maybe_fold_nontype_arg (tsubst_expr (parm, targs, NULL_TREE));
- tree a = maybe_fold_nontype_arg (arg);
+ --A type that is a template-id in which one or more of
+ the template-arguments is an expression that references
+ a template-parameter.
- if (!IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))))
- /* Good, we mangaged to simplify the exression. */
- return unify (tparms, targs, t, a, UNIFY_ALLOW_NONE,
- explicit_mask);
- else
- /* Bad, we couldn't simplify this. Assume it doesn't
- unify. */
- return 1;
- }
+ In these cases, we assume deduction succeeded, but don't
+ actually infer any unifications. */
+ return 0;
else
sorry ("use of `%s' in template type unification",
tree_code_name [(int) TREE_CODE (parm)]);
@@ -6651,14 +8495,15 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
}
}
+/* Called if RESULT is explicitly instantiated, or is a member of an
+ explicitly instantiated class, or if using -frepo and the
+ instantiation of RESULT has been assigned to this file. */
+
void
mark_decl_instantiated (result, extern_p)
tree result;
int extern_p;
{
- if (DECL_TEMPLATE_INSTANTIATION (result))
- SET_DECL_EXPLICIT_INSTANTIATION (result);
-
if (TREE_CODE (result) != FUNCTION_DECL)
/* The TREE_PUBLIC flag for function declarations will have been
set correctly by tsubst. */
@@ -6669,9 +8514,12 @@ mark_decl_instantiated (result, extern_p)
DECL_INTERFACE_KNOWN (result) = 1;
DECL_NOT_REALLY_EXTERN (result) = 1;
+ /* Always make artificials weak. */
+ if (DECL_ARTIFICIAL (result) && flag_weak)
+ comdat_linkage (result);
/* For WIN32 we also want to put explicit instantiations in
linkonce sections. */
- if (TREE_PUBLIC (result))
+ else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
else if (TREE_CODE (result) == FUNCTION_DECL)
@@ -6692,17 +8540,13 @@ more_specialized (pat1, pat2, explicit_args)
tree targs;
int winner = 0;
- targs = get_bindings_overload (pat1, pat2, explicit_args);
+ targs = get_bindings_overload (pat1, DECL_RESULT (pat2), explicit_args);
if (targs)
- {
- --winner;
- }
+ --winner;
- targs = get_bindings_overload (pat2, pat1, explicit_args);
+ targs = get_bindings_overload (pat2, DECL_RESULT (pat1), explicit_args);
if (targs)
- {
- ++winner;
- }
+ ++winner;
return winner;
}
@@ -6720,15 +8564,13 @@ more_specialized_class (pat1, pat2)
tree targs;
int winner = 0;
- targs = get_class_bindings
- (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
- TREE_PURPOSE (pat2), NULL_TREE);
+ targs = get_class_bindings (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
+ TREE_PURPOSE (pat2));
if (targs)
--winner;
- targs = get_class_bindings
- (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
- TREE_PURPOSE (pat1), NULL_TREE);
+ targs = get_class_bindings (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
+ TREE_PURPOSE (pat1));
if (targs)
++winner;
@@ -6738,7 +8580,8 @@ more_specialized_class (pat1, pat2)
/* Return the template arguments that will produce the function signature
DECL from the function template FN, with the explicit template
arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must
- also match. */
+ also match. Return NULL_TREE if no satisfactory arguments could be
+ found. */
static tree
get_bindings_real (fn, decl, explicit_args, check_rettype)
@@ -6747,35 +8590,50 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
{
int ntparms = DECL_NTPARMS (fn);
tree targs = make_scratch_vec (ntparms);
- tree decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
- tree extra_fn_arg = NULL_TREE;
+ tree decl_type;
+ tree decl_arg_types;
int i;
- if (DECL_STATIC_FUNCTION_P (fn)
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ /* Substitute the explicit template arguments into the type of DECL.
+ The call to fn_type_unification will handle substitution into the
+ FN. */
+ decl_type = TREE_TYPE (decl);
+ if (explicit_args && uses_template_parms (decl_type))
{
- /* Sometimes we are trying to figure out what's being
- specialized by a declaration that looks like a method, and it
- turns out to be a static member function. */
- if (CLASSTYPE_TEMPLATE_INFO (DECL_REAL_CONTEXT (fn))
- && !is_member_template (fn))
- /* The natural thing to do here seems to be to remove the
- spurious `this' parameter from the DECL, but that prevents
- unification from making use of the class type. So,
- instead, we have fn_type_unification add to the parameters
- for FN. */
- extra_fn_arg = build_pointer_type (DECL_REAL_CONTEXT (fn));
+ tree tmpl;
+ tree converted_args;
+
+ if (DECL_TEMPLATE_INFO (decl))
+ tmpl = DECL_TI_TEMPLATE (decl);
else
- /* In this case, though, adding the extra_fn_arg can confuse
- things, so we remove from decl_arg_types instead. */
- decl_arg_types = TREE_CHAIN (decl_arg_types);
+ /* We can get here for some illegal specializations. */
+ return NULL_TREE;
+
+ converted_args
+ = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ explicit_args, NULL_TREE,
+ /*complain=*/0,
+ /*require_all_arguments=*/0));
+ if (converted_args == error_mark_node)
+ return NULL_TREE;
+
+ decl_type = tsubst (decl_type, converted_args, /*complain=*/0,
+ NULL_TREE);
+ if (decl_type == error_mark_node)
+ return NULL_TREE;
}
+ /* If FN is a static member function, adjust the type of DECL
+ appropriately. */
+ decl_arg_types = TYPE_ARG_TYPES (decl_type);
+ if (DECL_STATIC_FUNCTION_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ decl_arg_types = TREE_CHAIN (decl_arg_types);
+
i = fn_type_unification (fn, explicit_args, targs,
decl_arg_types,
- TREE_TYPE (TREE_TYPE (decl)),
- DEDUCE_EXACT,
- extra_fn_arg);
+ TREE_TYPE (decl_type),
+ DEDUCE_EXACT);
if (i != 0)
return NULL_TREE;
@@ -6783,11 +8641,10 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
if (check_rettype)
{
/* Check to see that the resulting return type is also OK. */
- tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)),
- complete_template_args (fn, targs, 1),
- NULL_TREE);
+ tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs,
+ /*complain=*/0, NULL_TREE);
- if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
+ if (!same_type_p (t, TREE_TYPE (TREE_TYPE (decl))))
return NULL_TREE;
}
@@ -6812,31 +8669,32 @@ get_bindings_overload (fn, decl, explicit_args)
return get_bindings_real (fn, decl, explicit_args, 0);
}
+/* Return the innermost template arguments that, when applied to a
+ template specialization whose innermost template parameters are
+ TPARMS, and whose specialization arguments are ARGS, yield the
+ ARGS.
+
+ For example, suppose we have:
+
+ template <class T, class U> struct S {};
+ template <class T> struct S<T*, int> {};
+
+ Then, suppose we want to get `S<double*, int>'. The TPARMS will be
+ {T}, the PARMS will be {T*, int} and the ARGS will be {double*,
+ int}. The resulting vector will be {double}, indicating that `T'
+ is bound to `double'. */
+
static tree
-get_class_bindings (tparms, parms, args, outer_args)
- tree tparms, parms, args, outer_args;
+get_class_bindings (tparms, parms, args)
+ tree tparms, parms, args;
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_temp_vec (ntparms);
- if (outer_args)
- {
- tparms = tsubst (tparms, outer_args, NULL_TREE);
- parms = tsubst (parms, outer_args, NULL_TREE);
- }
+ args = innermost_args (args);
- for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
- {
- switch (unify (tparms, vec,
- TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
- UNIFY_ALLOW_NONE, 0))
- {
- case 0:
- break;
- case 1:
- return NULL_TREE;
- }
- }
+ if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
+ return NULL_TREE;
for (i = 0; i < ntparms; ++i)
if (! TREE_VEC_ELT (vec, i))
@@ -6845,37 +8703,30 @@ get_class_bindings (tparms, parms, args, outer_args)
return vec;
}
-/* Return the most specialized of the list of templates in FNS that can
- produce an instantiation matching DECL, given the explicit template
- arguments EXPLICIT_ARGS. */
+/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
+ Pick the most specialized template, and return the corresponding
+ instantiation, or if there is no corresponding instantiation, the
+ template itself. EXPLICIT_ARGS is any template arguments explicity
+ mentioned in a template-id. If there is no most specialized
+ tempalte, error_mark_node is returned. If there are no templates
+ at all, NULL_TREE is returned. */
tree
-most_specialized (fns, decl, explicit_args)
- tree fns, decl, explicit_args;
+most_specialized_instantiation (instantiations, explicit_args)
+ tree instantiations;
+ tree explicit_args;
{
- tree fn, champ, args, *p;
+ tree fn, champ;
int fate;
- for (p = &fns; *p; )
- {
- args = get_bindings (TREE_VALUE (*p), decl, explicit_args);
- if (args)
- {
- p = &TREE_CHAIN (*p);
- }
- else
- *p = TREE_CHAIN (*p);
- }
-
- if (! fns)
+ if (!instantiations)
return NULL_TREE;
- fn = fns;
- champ = TREE_VALUE (fn);
- fn = TREE_CHAIN (fn);
- for (; fn; fn = TREE_CHAIN (fn))
+ champ = instantiations;
+ for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
+ fate = more_specialized (TREE_VALUE (champ),
+ TREE_VALUE (fn), explicit_args);
if (fate == 1)
;
else
@@ -6886,35 +8737,89 @@ most_specialized (fns, decl, explicit_args)
if (! fn)
return error_mark_node;
}
- champ = TREE_VALUE (fn);
+ champ = fn;
}
}
- for (fn = fns; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn))
+ for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
+ fate = more_specialized (TREE_VALUE (champ),
+ TREE_VALUE (fn), explicit_args);
if (fate != 1)
return error_mark_node;
}
- return champ;
+ return TREE_PURPOSE (champ) ? TREE_PURPOSE (champ) : TREE_VALUE (champ);
}
-/* Return the most specialized of the class template specializations in
- SPECS that can produce an instantiation matching ARGS. */
+/* Return the most specialized of the list of templates in FNS that can
+ produce an instantiation matching DECL, given the explicit template
+ arguments EXPLICIT_ARGS. */
-tree
-most_specialized_class (specs, mainargs, outer_args)
- tree specs, mainargs, outer_args;
+static tree
+most_specialized (fns, decl, explicit_args)
+ tree fns, decl, explicit_args;
{
- tree list = NULL_TREE, t, args, champ;
- int fate;
+ tree candidates = NULL_TREE;
+ tree fn, args;
- for (t = specs; t; t = TREE_CHAIN (t))
+ for (fn = fns; fn; fn = TREE_CHAIN (fn))
{
- args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
- mainargs, outer_args);
+ tree candidate = TREE_VALUE (fn);
+
+ args = get_bindings (candidate, decl, explicit_args);
if (args)
+ candidates = scratch_tree_cons (NULL_TREE, candidate,
+ candidates);
+ }
+
+ return most_specialized_instantiation (candidates, explicit_args);
+}
+
+/* If DECL is a specialization of some template, return the most
+ general such template. For example, given:
+
+ template <class T> struct S { template <class U> void f(U); };
+
+ if TMPL is `template <class U> void S<int>::f(U)' this will return
+ the full template. This function will not trace past partial
+ specializations, however. For example, given in addition:
+
+ template <class T> struct S<T*> { template <class U> void f(U); };
+
+ if TMPL is `template <class U> void S<int*>::f(U)' this will return
+ `template <class T> template <class U> S<T*>::f(U)'. */
+
+static tree
+most_general_template (decl)
+ tree decl;
+{
+ while (DECL_TEMPLATE_INFO (decl))
+ decl = DECL_TI_TEMPLATE (decl);
+
+ return decl;
+}
+
+/* Return the most specialized of the class template specializations
+ of TMPL which can produce an instantiation matching ARGS, or
+ error_mark_node if the choice is ambiguous. */
+
+static tree
+most_specialized_class (tmpl, args)
+ tree tmpl;
+ tree args;
+{
+ tree list = NULL_TREE;
+ tree t;
+ tree champ;
+ int fate;
+
+ tmpl = most_general_template (tmpl);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
+ {
+ tree spec_args
+ = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
+ if (spec_args)
{
list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t);
@@ -6969,29 +8874,69 @@ do_decl_instantiation (declspecs, declarator, storage)
cp_error ("explicit instantiation of non-template `%#D'", decl);
return;
}
-
- /* If we've already seen this template instance, use it. */
- if (TREE_CODE (decl) == VAR_DECL)
+ else if (TREE_CODE (decl) == VAR_DECL)
{
+ /* There is an asymmetry here in the way VAR_DECLs and
+ FUNCTION_DECLs are handled by grokdeclarator. In the case of
+ the latter, the DECL we get back will be marked as a
+ template instantiation, and the appropriate
+ DECL_TEMPLATE_INFO will be set up. This does not happen for
+ VAR_DECLs so we do the lookup here. Probably, grokdeclarator
+ should handle VAR_DECLs as it currently handles
+ FUNCTION_DECLs. */
result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
if (result && TREE_CODE (result) != VAR_DECL)
- result = NULL_TREE;
+ {
+ cp_error ("no matching template for `%D' found", result);
+ return;
+ }
}
else if (TREE_CODE (decl) != FUNCTION_DECL)
{
cp_error ("explicit instantiation of `%#D'", decl);
return;
}
- else if (DECL_TEMPLATE_INSTANTIATION (decl))
+ else
result = decl;
- if (! result)
+ /* Check for various error cases. Note that if the explicit
+ instantiation is legal the RESULT will currently be marked as an
+ *implicit* instantiation; DECL_EXPLICIT_INSTANTIATION is not set
+ until we get here. */
+
+ if (DECL_TEMPLATE_SPECIALIZATION (result))
{
- cp_error ("no matching template for `%D' found", decl);
+ /* [temp.spec]
+
+ No program shall both explicitly instantiate and explicitly
+ specialize a template. */
+ cp_pedwarn ("explicit instantiation of `%#D' after", result);
+ cp_pedwarn_at ("explicit specialization here", result);
return;
}
+ else if (DECL_EXPLICIT_INSTANTIATION (result))
+ {
+ /* [temp.spec]
+
+ No program shall explicitly instantiate any template more
+ than once.
- if (! DECL_TEMPLATE_INFO (result))
+ We check DECL_INTERFACE_KNOWN so as not to complain when the
+ first instantiation was `extern' and the second is not, and
+ EXTERN_P for the opposite case. */
+ if (DECL_INTERFACE_KNOWN (result) && !extern_p)
+ cp_pedwarn ("duplicate explicit instantiation of `%#D'", result);
+
+ /* If we've already instantiated the template, just return now. */
+ if (DECL_INTERFACE_KNOWN (result))
+ return;
+ }
+ else if (!DECL_IMPLICIT_INSTANTIATION (result))
+ {
+ cp_error ("no matching template for `%D' found", result);
+ return;
+ }
+ else if (!DECL_TEMPLATE_INFO (result))
{
cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
return;
@@ -7003,11 +8948,16 @@ do_decl_instantiation (declspecs, declarator, storage)
if (storage == NULL_TREE)
;
else if (storage == ridpointers[(int) RID_EXTERN])
- extern_p = 1;
+ {
+ if (pedantic)
+ cp_pedwarn ("ANSI C++ forbids the use of `extern' on explicit instantiations");
+ extern_p = 1;
+ }
else
cp_error ("storage class `%D' applied to template instantiation",
storage);
+ SET_DECL_EXPLICIT_INSTANTIATION (result);
mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
if (! extern_p)
@@ -7042,7 +8992,7 @@ do_type_instantiation (t, storage)
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
- if (! IS_AGGR_TYPE (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
+ if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
{
cp_error ("explicit instantiation of non-template type `%T'", t);
return;
@@ -7062,38 +9012,82 @@ do_type_instantiation (t, storage)
return;
}
- if (storage == NULL_TREE)
- /* OK */;
- else if (storage == ridpointers[(int) RID_INLINE])
- nomem_p = 1;
- else if (storage == ridpointers[(int) RID_EXTERN])
- extern_p = 1;
- else if (storage == ridpointers[(int) RID_STATIC])
- static_p = 1;
- else
+ if (storage != NULL_TREE)
{
- cp_error ("storage class `%D' applied to template instantiation",
- storage);
- extern_p = 0;
+ if (pedantic)
+ cp_pedwarn("ANSI C++ forbids the use of `%s' on explicit instantiations",
+ IDENTIFIER_POINTER (storage));
+
+ if (storage == ridpointers[(int) RID_INLINE])
+ nomem_p = 1;
+ else if (storage == ridpointers[(int) RID_EXTERN])
+ extern_p = 1;
+ else if (storage == ridpointers[(int) RID_STATIC])
+ static_p = 1;
+ else
+ {
+ cp_error ("storage class `%D' applied to template instantiation",
+ storage);
+ extern_p = 0;
+ }
}
- /* We've already instantiated this. */
- if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t)
- && extern_p)
- return;
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+ {
+ /* [temp.spec]
- if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+ No program shall both explicitly instantiate and explicitly
+ specialize a template. */
+ cp_error ("explicit instantiation of `%#T' after", t);
+ cp_error_at ("explicit specialization here", t);
+ return;
+ }
+ else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
{
- mark_class_instantiated (t, extern_p);
- repo_template_instantiated (t, extern_p);
+ /* [temp.spec]
+
+ No program shall explicitly instantiate any template more
+ than once.
+
+ If CLASSTYPE_INTERFACE_ONLY, then the first explicit
+ instantiation was `extern', and if EXTERN_P then the second
+ is. Both cases are OK. */
+ if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p)
+ cp_error ("duplicate explicit instantiation of `%#T'", t);
+
+ /* If we've already instantiated the template, just return now. */
+ if (!CLASSTYPE_INTERFACE_ONLY (t))
+ return;
}
+ mark_class_instantiated (t, extern_p);
+ repo_template_instantiated (t, extern_p);
+
if (nomem_p)
return;
{
tree tmp;
+ /* In contrast to implicit instantiation, where only the
+ declarations, and not the definitions, of members are
+ instantiated, we have here:
+
+ [temp.explicit]
+
+ The explicit instantiation of a class template specialization
+ implies the instantiation of all of its members not
+ previously explicitly specialized in the translation unit
+ containing the explicit instantiation.
+
+ Of course, we can't instantiate member template classes, since
+ we don't have any arguments for them. Note that the standard
+ is unclear on whether the instatiation of the members are
+ *explicit* instantiations or not. We choose to be generous,
+ and not set DECL_EXPLICIT_INSTANTIATION. Therefore, we allow
+ the explicit instantiation of a class where some of the members
+ have no definition in the current translation unit. */
+
if (! static_p)
for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
if (TREE_CODE (tmp) == FUNCTION_DECL
@@ -7115,14 +9109,16 @@ do_type_instantiation (t, storage)
}
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
- if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
+ if (IS_AGGR_TYPE (TREE_VALUE (tmp))
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
}
}
-/* Given a function DECL, which is a specialization of TEMP, modify
- DECL to be a re-instantiation of TEMPL with the same template
- arguments.
+/* Given a function DECL, which is a specialization of TMPL, modify
+ DECL to be a re-instantiation of TMPL with the same template
+ arguments. TMPL should be the template into which tsubst'ing
+ should occur for DECL, not the most general template.
One reason for doing this is a scenario like this:
@@ -7139,54 +9135,76 @@ do_type_instantiation (t, storage)
first parameter, and the wrong type for the second. So, when we go
to instantiate the DECL, we regenerate it. */
-void
+static void
regenerate_decl_from_template (decl, tmpl)
tree decl;
tree tmpl;
{
tree args;
- tree save_ti;
tree code_pattern;
tree new_decl;
+ tree gen_tmpl;
+ int unregistered;
args = DECL_TI_ARGS (decl);
code_pattern = DECL_TEMPLATE_RESULT (tmpl);
- /* Trick tsubst into giving us a new decl. CODE_PATTERN must be the
- most distant ancestor of DECL, since that's the one that will
- actually be altered by a redefinition. */
- save_ti = DECL_TEMPLATE_INFO (code_pattern);
- DECL_TEMPLATE_INFO (code_pattern) = NULL_TREE;
- new_decl = tsubst (code_pattern, args, NULL_TREE);
- SET_DECL_IMPLICIT_INSTANTIATION (new_decl);
- DECL_TEMPLATE_INFO (code_pattern) = save_ti;
+ /* Unregister the specialization so that when we tsubst we will not
+ just return DECL. We don't have to unregister DECL from TMPL
+ because if would only be registered there if it were a partial
+ instantiation of a specialization, which it isn't: it's a full
+ instantiation. */
+ gen_tmpl = most_general_template (tmpl);
+ unregistered = unregister_specialization (decl, gen_tmpl);
+
+ /* If the DECL was not unregistered then something peculiar is
+ happening: we created a specialization but did not call
+ register_specialization for it. */
+ my_friendly_assert (unregistered, 0);
+
+ if (TREE_CODE (decl) == VAR_DECL)
+ /* Make sure that we can see identifiers, and compute access
+ correctly, for the class members used in the declaration of
+ this static variable. */
+ pushclass (DECL_CONTEXT (decl), 2);
+
+ /* Do the substitution to get the new declaration. */
+ new_decl = tsubst (code_pattern, args, /*complain=*/1, NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
- pushclass (DECL_CONTEXT (decl), 2);
DECL_INITIAL (new_decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args,
- DECL_TI_TEMPLATE (decl));
- popclass (1);
+ /*complain=*/1, DECL_TI_TEMPLATE (decl));
+ /* Pop the class context we pushed above. */
+ popclass ();
}
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ else if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
DECL_INITIAL (new_decl) = error_mark_node;
-
- if (DECL_TEMPLATE_SPECIALIZATION (new_decl)
- && !DECL_TEMPLATE_INFO (new_decl))
- /* Set up the information about what is being specialized. */
- DECL_TEMPLATE_INFO (new_decl) = DECL_TEMPLATE_INFO (decl);
- }
-
+ /* And don't complain about a duplicate definition. */
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+
+ /* The immediate parent of the new template is still whatever it was
+ before, even though tsubst sets DECL_TI_TEMPLATE up as the most
+ general template. We also reset the DECL_ASSEMBLER_NAME since
+ tsubst always calculates the name as if the function in question
+ were really a template instance, and sometimes, with friend
+ functions, this is not so. See tsubst_friend_function for
+ details. */
+ DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl);
+ DECL_ASSEMBLER_NAME (new_decl) = DECL_ASSEMBLER_NAME (decl);
+ DECL_RTL (new_decl) = DECL_RTL (decl);
+
+ /* Call duplicate decls to merge the old and new declarations. */
duplicate_decls (new_decl, decl);
- if (TREE_CODE (decl) == FUNCTION_DECL)
- DECL_INITIAL (new_decl) = NULL_TREE;
+ /* Now, re-register the specialization. */
+ register_specialization (decl, gen_tmpl, args);
}
/* Produce the definition of D, a _DECL generated from a template. */
@@ -7195,60 +9213,101 @@ tree
instantiate_decl (d)
tree d;
{
- tree ti = DECL_TEMPLATE_INFO (d);
- tree tmpl = TI_TEMPLATE (ti);
- tree args = TI_ARGS (ti);
+ tree tmpl = DECL_TI_TEMPLATE (d);
+ tree args = DECL_TI_ARGS (d);
tree td;
- tree decl_pattern, code_pattern;
+ tree code_pattern;
+ tree spec;
+ tree gen_tmpl;
int nested = in_function_p ();
- int d_defined;
int pattern_defined;
int line = lineno;
char *file = input_filename;
- for (td = tmpl;
- DECL_TEMPLATE_INSTANTIATION (td)
- /* This next clause handles friend templates defined inside
- class templates. The friend templates are not really
- instantiations from the point of view of the language, but
- they are instantiations from the point of view of the
- compiler. */
- || (DECL_TEMPLATE_INFO (td) && !DECL_TEMPLATE_SPECIALIZATION (td));
- )
- td = DECL_TI_TEMPLATE (td);
+ /* This function should only be used to instantiate templates for
+ functions and static member variables. */
+ my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
+ || TREE_CODE (d) == VAR_DECL, 0);
+
+ if (DECL_TEMPLATE_INSTANTIATED (d))
+ /* D has already been instantiated. It might seem reasonable to
+ check whether or not D is an explict instantiation, and, if so,
+ stop here. But when an explicit instantiation is deferred
+ until the end of the compilation, DECL_EXPLICIT_INSTANTIATION
+ is set, even though we still need to do the instantiation. */
+ return d;
- /* In the case of a member template, decl_pattern is the partially
- instantiated declaration (in the instantiated class), and code_pattern
- is the original template definition. */
- decl_pattern = DECL_TEMPLATE_RESULT (tmpl);
- code_pattern = DECL_TEMPLATE_RESULT (td);
+ /* If we already have a specialization of this declaration, then
+ there's no reason to instantiate it. Note that
+ retrieve_specialization gives us both instantiations and
+ specializations, so we must explicitly check
+ DECL_TEMPLATE_SPECIALIZATION. */
+ gen_tmpl = most_general_template (tmpl);
+ spec = retrieve_specialization (gen_tmpl, args);
+ if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
+ return spec;
- if (TREE_CODE (d) == FUNCTION_DECL)
- {
- d_defined = (DECL_INITIAL (d) != NULL_TREE);
- pattern_defined = (DECL_INITIAL (code_pattern) != NULL_TREE);
- }
- else
- {
- d_defined = ! DECL_IN_AGGR_P (d);
- pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
- }
-
- if (d_defined)
+ /* This needs to happen before any tsubsting. */
+ if (! push_tinst_level (d))
return d;
- if (TREE_CODE (d) == FUNCTION_DECL)
+ /* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
+ for the instantiation. This is not always the most general
+ template. Consider, for example:
+
+ template <class T>
+ struct S { template <class U> void f();
+ template <> void f<int>(); };
+
+ and an instantiation of S<double>::f<int>. We want TD to be the
+ specialization S<T>::f<int>, not the more general S<T>::f<U>. */
+ td = tmpl;
+ for (td = tmpl;
+ /* An instantiation cannot have a definition, so we need a
+ more general template. */
+ DECL_TEMPLATE_INSTANTIATION (td)
+ /* We must also deal with friend templates. Given:
+
+ template <class T> struct S {
+ template <class U> friend void f() {};
+ };
+
+ S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
+ so far as the language is concerned, but that's still
+ where we get the pattern for the instantiation from. On
+ ther hand, if the definition comes outside the class, say:
+
+ template <class T> struct S {
+ template <class U> friend void f();
+ };
+ template <class U> friend void f() {}
+
+ we don't need to look any further. That's what the check for
+ DECL_INITIAL is for. */
+ || (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td)
+ && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td)));
+ )
{
- tree spec = retrieve_specialization (tmpl, args);
+ /* The present template, TD, should not be a definition. If it
+ were a definition, we should be using it! Note that we
+ cannot restructure the loop to just keep going until we find
+ a template with a definition, since that might go too far if
+ a specialization was declared, but not defined. */
+ my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
+ && !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (td))),
+ 0);
- if (spec != NULL_TREE
- && DECL_TEMPLATE_SPECIALIZATION (spec))
- return spec;
+ /* Fetch the more general template. */
+ td = DECL_TI_TEMPLATE (td);
}
- /* This needs to happen before any tsubsting. */
- if (! push_tinst_level (d))
- return d;
+ code_pattern = DECL_TEMPLATE_RESULT (td);
+
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ pattern_defined = (DECL_INITIAL (code_pattern) != NULL_TREE);
+ else
+ pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
push_to_top_level ();
lineno = DECL_SOURCE_LINE (d);
@@ -7295,14 +9354,34 @@ instantiate_decl (d)
&& ! at_eof))
{
/* Defer all templates except inline functions used in another
- function. */
+ function. We restore the source position here because it's used
+ by add_pending_template. */
lineno = line;
input_filename = file;
+ if (at_eof && !pattern_defined
+ && DECL_EXPLICIT_INSTANTIATION (d))
+ /* [temp.explicit]
+
+ The definition of a non-exported function template, a
+ non-exported member function template, or a non-exported
+ member function or static data member of a class template
+ shall be present in every translation unit in which it is
+ explicitly instantiated. */
+ cp_error ("explicit instantiation of `%D' but no definition available",
+ d);
+
add_pending_template (d);
goto out;
}
+ /* We're now committed to instantiating this template. Mark it as
+ instantiated so that recursive calls to instantiate_decl do not
+ try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+
+ /* Regenerate the declaration in case the template has been modified
+ by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
/* We already set the file and line above. Reset them now in case
@@ -7333,7 +9412,7 @@ instantiate_decl (d)
{
store_return_init
(TREE_OPERAND (t, 0),
- tsubst_expr (TREE_OPERAND (t, 1), args, tmpl));
+ tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, tmpl));
t = TREE_CHAIN (t);
}
@@ -7353,7 +9432,7 @@ instantiate_decl (d)
keep_next_level ();
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
- tsubst_expr (t, args, tmpl);
+ tsubst_expr (t, args, /*complain=*/1, tmpl);
finish_function (lineno, 0, nested);
}
@@ -7368,27 +9447,119 @@ out:
return d;
}
-tree
-tsubst_chain (t, argvec)
- tree t, argvec;
+/* Run through the list of templates that we wish we could
+ instantiate, and instantiate any we can. */
+
+int
+instantiate_pending_templates ()
{
- if (t)
+ tree *t;
+ int instantiated_something = 0;
+ int reconsider;
+
+ do
{
- tree first = tsubst (t, argvec, NULL_TREE);
- tree last = first;
+ reconsider = 0;
- for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
+ t = &pending_templates;
+ while (*t)
{
- tree x = tsubst (t, argvec, NULL_TREE);
- TREE_CHAIN (last) = x;
- last = x;
+ tree srcloc = TREE_PURPOSE (*t);
+ tree instantiation = TREE_VALUE (*t);
+
+ input_filename = SRCLOC_FILE (srcloc);
+ lineno = SRCLOC_LINE (srcloc);
+
+ if (TREE_CODE_CLASS (TREE_CODE (instantiation)) == 't')
+ {
+ tree fn;
+
+ if (!TYPE_SIZE (instantiation))
+ {
+ instantiate_class_template (instantiation);
+ if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
+ for (fn = TYPE_METHODS (instantiation);
+ fn;
+ fn = TREE_CHAIN (fn))
+ if (! DECL_ARTIFICIAL (fn))
+ instantiate_decl (fn);
+ if (TYPE_SIZE (instantiation))
+ {
+ instantiated_something = 1;
+ reconsider = 1;
+ }
+ }
+
+ if (TYPE_SIZE (instantiation))
+ /* If INSTANTIATION has been instantiated, then we don't
+ need to consider it again in the future. */
+ *t = TREE_CHAIN (*t);
+ else
+ t = &TREE_CHAIN (*t);
+ }
+ else
+ {
+ if (DECL_TEMPLATE_INSTANTIATION (instantiation)
+ && !DECL_TEMPLATE_INSTANTIATED (instantiation))
+ {
+ instantiation = instantiate_decl (instantiation);
+ if (DECL_TEMPLATE_INSTANTIATED (instantiation))
+ {
+ instantiated_something = 1;
+ reconsider = 1;
+ }
+ }
+
+ if (!DECL_TEMPLATE_INSTANTIATION (instantiation)
+ || DECL_TEMPLATE_INSTANTIATED (instantiation))
+ /* If INSTANTIATION has been instantiated, then we don't
+ need to consider it again in the future. */
+ *t = TREE_CHAIN (*t);
+ else
+ t = &TREE_CHAIN (*t);
+ }
}
+ template_tail = t;
- return first;
- }
- return NULL_TREE;
+ /* Go through the things that are template instantiations if we are
+ using guiding declarations. */
+ t = &maybe_templates;
+ while (*t)
+ {
+ tree template;
+ tree fn;
+ tree args;
+
+ fn = TREE_VALUE (*t);
+
+ if (DECL_INITIAL (fn))
+ /* If the FN is already defined, then it was either already
+ instantiated or, even though guiding declarations were
+ allowed, a non-template definition was provided. */
+ ;
+ else
+ {
+ template = TREE_PURPOSE (*t);
+ args = get_bindings (template, fn, NULL_TREE);
+ fn = instantiate_template (template, args);
+ instantiate_decl (fn);
+ reconsider = 1;
+ }
+
+ /* Remove this entry from the chain. */
+ *t = TREE_CHAIN (*t);
+ }
+ maybe_template_tail = t;
+ }
+ while (reconsider);
+
+ return instantiated_something;
}
+/* Substitute ARGVEC into T, which is a TREE_LIST. In particular, it
+ is an initializer list: the TREE_PURPOSEs are DECLs, and the
+ TREE_VALUEs are initializer values. Used by instantiate_decl. */
+
static tree
tsubst_expr_values (t, argvec)
tree t, argvec;
@@ -7398,8 +9569,10 @@ tsubst_expr_values (t, argvec)
for (; t; t = TREE_CHAIN (t))
{
- tree pur = tsubst_copy (TREE_PURPOSE (t), argvec, NULL_TREE);
- tree val = tsubst_expr (TREE_VALUE (t), argvec, NULL_TREE);
+ tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
+ /*complain=*/1, NULL_TREE);
+ tree val = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1,
+ NULL_TREE);
*p = build_tree_list (pur, val);
p = &TREE_CHAIN (*p);
}
@@ -7461,35 +9634,199 @@ add_maybe_template (d, fns)
DECL_MAYBE_TEMPLATE (d) = 1;
}
-/* Instantiate an enumerated type. Used by instantiate_class_template and
- tsubst_expr. */
+/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
-static tree
-tsubst_enum (tag, args, field_chain)
- tree tag, args;
- tree * field_chain;
+static void
+set_current_access_from_decl (decl)
+ tree decl;
{
- extern tree current_local_enum;
- tree prev_local_enum = current_local_enum;
+ if (TREE_PRIVATE (decl))
+ current_access_specifier = access_private_node;
+ else if (TREE_PROTECTED (decl))
+ current_access_specifier = access_protected_node;
+ else
+ current_access_specifier = access_public_node;
+}
- tree newtag = start_enum (TYPE_IDENTIFIER (tag));
- tree e, values = NULL_TREE;
+/* Instantiate an enumerated type. TAG is the template type, NEWTAG
+ is the instantiation (which should have been created with
+ start_enum) and ARGS are the template arguments to use. */
+
+static void
+tsubst_enum (tag, newtag, args)
+ tree tag;
+ tree newtag;
+ tree args;
+{
+ tree e;
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
- tree elt = build_enumerator (TREE_PURPOSE (e),
- tsubst_expr (TREE_VALUE (e), args,
- NULL_TREE));
- TREE_CHAIN (elt) = values;
- values = elt;
+ tree value;
+ tree elt;
+
+ /* Note that in a template enum, the TREE_VALUE is the
+ CONST_DECL, not the corresponding INTEGER_CST. */
+ value = tsubst_expr (DECL_INITIAL (TREE_VALUE (e)),
+ args, /*complain=*/1,
+ NULL_TREE);
+
+ /* Give this enumeration constant the correct access. */
+ set_current_access_from_decl (TREE_VALUE (e));
+
+ /* Actually build the enumerator itself. */
+ elt = build_enumerator (TREE_PURPOSE (e), value, newtag);
+
+ /* We save the enumerators we have built so far in the
+ TYPE_VALUES so that if the enumeration constants for
+ subsequent enumerators involve those for previous ones,
+ tsubst_copy will be able to find them. */
+ TREE_CHAIN (elt) = TYPE_VALUES (newtag);
+ TYPE_VALUES (newtag) = elt;
}
- finish_enum (newtag, values);
+ finish_enum (newtag);
+}
+
+/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
+ is either an instantiation or specialization of a template
+ function. */
+
+static void
+set_mangled_name_for_template_decl (decl)
+ tree decl;
+{
+ tree saved_namespace;
+ tree context = NULL_TREE;
+ tree fn_type;
+ tree ret_type;
+ tree parm_types;
+ tree tparms;
+ tree targs;
+ tree tmpl;
+ int parm_depth;
+
+ my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0);
+ my_friendly_assert (DECL_TEMPLATE_INFO (decl) != NULL_TREE, 0);
+
+ /* The names of template functions must be mangled so as to indicate
+ what template is being specialized with what template arguments.
+ For example, each of the following three functions must get
+ different mangled names:
+
+ void f(int);
+ template <> void f<7>(int);
+ template <> void f<8>(int); */
+
+ targs = DECL_TI_ARGS (decl);
+ if (uses_template_parms (targs))
+ /* This DECL is for a partial instantiation. There's no need to
+ mangle the name of such an entity. */
+ return;
+
+ tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
+ tparms = DECL_TEMPLATE_PARMS (tmpl);
+ parm_depth = TMPL_PARMS_DEPTH (tparms);
- if (NULL != field_chain)
- *field_chain = grok_enum_decls (NULL_TREE);
+ /* There should be as many levels of arguments as there are levels
+ of parameters. */
+ my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
- current_local_enum = prev_local_enum;
+ /* We now compute the PARMS and RET_TYPE to give to
+ build_decl_overload_real. The PARMS and RET_TYPE are the
+ parameter and return types of the template, after all but the
+ innermost template arguments have been substituted, not the
+ parameter and return types of the function DECL. For example,
+ given:
- return newtag;
+ template <class T> T f(T);
+
+ both PARMS and RET_TYPE should be `T' even if DECL is `int f(int)'.
+ A more subtle example is:
+
+ template <class T> struct S { template <class U> void f(T, U); }
+
+ Here, if DECL is `void S<int>::f(int, double)', PARMS should be
+ {int, U}. Thus, the args that we want to subsitute into the
+ return and parameter type for the function are those in TARGS,
+ with the innermost level omitted. */
+ fn_type = TREE_TYPE (tmpl);
+ if (DECL_STATIC_FUNCTION_P (decl))
+ context = DECL_CLASS_CONTEXT (decl);
+
+ if (parm_depth == 1)
+ /* No substitution is necessary. */
+ ;
+ else
+ {
+ int i;
+ tree partial_args;
+
+ /* Replace the innermost level of the TARGS with NULL_TREEs to
+ let tsubst know not to subsitute for those parameters. */
+ partial_args = make_temp_vec (TREE_VEC_LENGTH (targs));
+ for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
+ SET_TMPL_ARGS_LEVEL (partial_args, i,
+ TMPL_ARGS_LEVEL (targs, i));
+ SET_TMPL_ARGS_LEVEL (partial_args,
+ TMPL_ARGS_DEPTH (targs),
+ make_temp_vec (DECL_NTPARMS (tmpl)));
+
+ /* Now, do the (partial) substitution to figure out the
+ appropriate function type. */
+ fn_type = tsubst (fn_type, partial_args, /*complain=*/1, NULL_TREE);
+ if (DECL_STATIC_FUNCTION_P (decl))
+ context = tsubst (context, partial_args, /*complain=*/1, NULL_TREE);
+
+ /* Substitute into the template parameters to obtain the real
+ innermost set of parameters. This step is important if the
+ innermost set of template parameters contains value
+ parameters whose types depend on outer template parameters. */
+ TREE_VEC_LENGTH (partial_args)--;
+ tparms = tsubst_template_parms (tparms, partial_args, /*complain=*/1);
+ }
+
+ /* Now, get the innermost parameters and arguments, and figure out
+ the parameter and return types. */
+ tparms = INNERMOST_TEMPLATE_PARMS (tparms);
+ targs = innermost_args (targs);
+ ret_type = TREE_TYPE (fn_type);
+ parm_types = TYPE_ARG_TYPES (fn_type);
+
+ /* For a static member function, we generate a fake `this' pointer,
+ for the purposes of mangling. This indicates of which class the
+ function is a member. Because of:
+
+ [class.static]
+
+ There shall not be a static and a nonstatic member function
+ with the same name and the same parameter types
+
+ we don't have to worry that this will result in a clash with a
+ non-static member function. */
+ if (DECL_STATIC_FUNCTION_P (decl))
+ parm_types = hash_tree_chain (build_pointer_type (context), parm_types);
+
+ /* There should be the same number of template parameters as
+ template arguments. */
+ my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs),
+ 0);
+
+ /* If the template is in a namespace, we need to put that into the
+ mangled name. Unfortunately, build_decl_overload_real does not
+ get the decl to mangle, so it relies on the current
+ namespace. Therefore, we set that here temporarily. */
+ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
+ saved_namespace = current_namespace;
+ current_namespace = CP_DECL_CONTEXT (decl);
+
+ /* Actually set the DCL_ASSEMBLER_NAME. */
+ DECL_ASSEMBLER_NAME (decl)
+ = build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type,
+ tparms, targs,
+ DECL_FUNCTION_MEMBER_P (decl)
+ + DECL_CONSTRUCTOR_P (decl));
+
+ /* Restore the previously active namespace. */
+ current_namespace = saved_namespace;
}
diff --git a/contrib/gcc/cp/ptree.c b/contrib/gcc/cp/ptree.c
index aa3066c..1f17aec 100644
--- a/contrib/gcc/cp/ptree.c
+++ b/contrib/gcc/cp/ptree.c
@@ -1,5 +1,5 @@
/* Prints out trees in human readable form.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-96, 1998, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -113,8 +113,6 @@ print_lang_type (file, node, indent)
fputs (" delete", file);
if (TYPE_GETS_DELETE (node) & 2)
fputs (" delete[]", file);
- if (TYPE_HAS_ASSIGNMENT (node))
- fputs (" has=", file);
if (TYPE_HAS_ASSIGN_REF (node))
fputs (" this=(X&)", file);
if (TYPE_OVERLOADS_CALL_EXPR (node))
@@ -128,9 +126,7 @@ print_lang_type (file, node, indent)
if (TREE_CODE (node) == RECORD_TYPE)
{
- fprintf (file, " n_parents %d n_ancestors %d",
- CLASSTYPE_N_BASECLASSES (node),
- CLASSTYPE_N_SUPERCLASSES (node));
+ fprintf (file, " n_parents %d", CLASSTYPE_N_BASECLASSES (node));
fprintf (file, " use_template=%d", CLASSTYPE_USE_TEMPLATE (node));
if (CLASSTYPE_INTERFACE_ONLY (node))
fprintf (file, " interface-only");
@@ -138,9 +134,6 @@ print_lang_type (file, node, indent)
fprintf (file, " interface-unknown");
print_node (file, "member-functions", CLASSTYPE_METHOD_VEC (node),
indent + 4);
- print_node (file, "baselinks",
- TYPE_BINFO_BASETYPES (node) ? CLASSTYPE_BASELINK_VEC (node) : NULL_TREE,
- indent + 4);
}
}
@@ -152,7 +145,7 @@ print_lang_identifier (file, node, indent)
{
print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
- print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
+ print_node (file, "local bindings", IDENTIFIER_BINDING (node), indent + 4);
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
@@ -168,7 +161,8 @@ lang_print_xnode (file, node, indent)
switch (TREE_CODE (node))
{
case CPLUS_BINDING:
- print_node (file, "scope", BINDING_SCOPE (node), indent+4);
+ fprintf (file, " scope ");
+ fprintf (file, HOST_PTR_PRINTF, BINDING_SCOPE (node));
print_node (file, "value", BINDING_VALUE (node), indent+4);
print_node (file, "chain", TREE_CHAIN (node), indent+4);
break;
diff --git a/contrib/gcc/cp/repo.c b/contrib/gcc/cp/repo.c
index 742250d..9fa8e5c 100644
--- a/contrib/gcc/cp/repo.c
+++ b/contrib/gcc/cp/repo.c
@@ -1,5 +1,5 @@
/* Code to maintain a C++ template repository.
- Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-97, 1998 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GNU CC.
@@ -37,8 +37,8 @@ extern char *getpwd PROTO((void));
static tree repo_get_id PROTO((tree));
static char *extract_string PROTO((char **));
-static char *get_base_filename PROTO((char *));
-static void open_repo_file PROTO((char *));
+static char *get_base_filename PROTO((const char *));
+static void open_repo_file PROTO((const char *));
static char *afgets PROTO((FILE *));
static void reopen_repo_file_for_write PROTO((void));
@@ -99,6 +99,12 @@ repo_get_id (t)
{
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
+ /* If we're not done setting up the class, we may not have set up
+ the vtable, so going ahead would give the wrong answer.
+ See g++.pt/instantiate4.C. */
+ if (TYPE_SIZE (t) == NULL_TREE || TYPE_BEING_DEFINED (t))
+ my_friendly_abort (981113);
+
t = TYPE_BINFO_VTABLE (t);
if (t == NULL_TREE)
return t;
@@ -233,7 +239,7 @@ extract_string (pp)
static char *
get_base_filename (filename)
- char *filename;
+ const char *filename;
{
char *p = getenv ("COLLECT_GCC_OPTIONS");
char *output = NULL;
@@ -264,10 +270,10 @@ get_base_filename (filename)
static void
open_repo_file (filename)
- char *filename;
+ const char *filename;
{
- register char *p;
- char *s = get_base_filename (filename);
+ register const char *p;
+ const char *s = get_base_filename (filename);
if (s == NULL)
return;
@@ -298,7 +304,7 @@ afgets (stream)
void
init_repo (filename)
- char *filename;
+ const char *filename;
{
char *buf;
diff --git a/contrib/gcc/cp/rtti.c b/contrib/gcc/cp/rtti.c
index b93c1cc..e0ce5cd 100644
--- a/contrib/gcc/cp/rtti.c
+++ b/contrib/gcc/cp/rtti.c
@@ -1,5 +1,5 @@
/* RunTime Type Identification
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC.
@@ -35,18 +35,17 @@ Boston, MA 02111-1307, USA. */
extern struct obstack permanent_obstack;
-static tree call_void_fn PROTO((char *));
+static tree call_void_fn PROTO((const char *));
static tree build_headof_sub PROTO((tree));
static tree build_headof PROTO((tree));
static tree get_tinfo_var PROTO((tree));
-static tree get_typeid_1 PROTO((tree));
static tree ifnonnull PROTO((tree, tree));
static tree build_dynamic_cast_1 PROTO((tree, tree));
static void expand_si_desc PROTO((tree, tree));
static void expand_class_desc PROTO((tree, tree));
static void expand_attr_desc PROTO((tree, tree));
static void expand_ptr_desc PROTO((tree, tree));
-static void expand_generic_desc PROTO((tree, tree, char *));
+static void expand_generic_desc PROTO((tree, tree, const char *));
static tree throw_bad_cast PROTO((void));
static tree throw_bad_typeid PROTO((void));
@@ -60,12 +59,13 @@ init_rtti_processing ()
if (flag_honor_std)
push_namespace (get_identifier ("std"));
type_info_type_node = xref_tag
- (class_type_node, get_identifier ("type_info"), NULL_TREE, 1);
+ (class_type_node, get_identifier ("type_info"), 1);
if (flag_honor_std)
pop_namespace ();
tinfo_fn_id = get_identifier ("__tf");
tinfo_fn_type = build_function_type
- (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
+ (build_reference_type (build_qualified_type (type_info_type_node,
+ TYPE_QUAL_CONST)),
void_list_node);
}
@@ -108,6 +108,11 @@ build_headof (exp)
if (!TYPE_VIRTUAL_P (type))
return exp;
+ if (CLASSTYPE_COM_INTERFACE (type))
+ {
+ cp_error ("RTTI not supported for COM interface type `%T'", type);
+ return error_mark_node;
+ }
/* If we don't have rtti stuff, get to a sub-object that does. */
if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
@@ -123,8 +128,8 @@ build_headof (exp)
else
offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
- type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
- TREE_THIS_VOLATILE (exp));
+ type = build_qualified_type (ptr_type_node,
+ CP_TYPE_QUALS (TREE_TYPE (exp)));
return build (PLUS_EXPR, type, exp,
cp_convert (ptrdiff_type_node, offset));
}
@@ -133,7 +138,7 @@ build_headof (exp)
static tree
call_void_fn (name)
- char *name;
+ const char *name;
{
tree d = get_identifier (name);
tree type;
@@ -151,11 +156,10 @@ call_void_fn (name)
DECL_ARTIFICIAL (d) = 1;
pushdecl_top_level (d);
make_function_rtl (d);
- assemble_external (d);
-
pop_obstacks ();
}
+ mark_used (d);
return build_call (d, void_type_node, NULL_TREE);
}
@@ -203,6 +207,12 @@ get_tinfo_fn_dynamic (exp)
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
+ {
+ cp_error ("taking typeid of incomplete type `%T'", type);
+ return error_mark_node;
+ }
+
/* If exp is a reference to polymorphic type, get the real type_info. */
if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))
{
@@ -210,12 +220,11 @@ get_tinfo_fn_dynamic (exp)
tree t;
if (! flag_rtti)
+ error ("taking dynamic typeid of object with -fno-rtti");
+ if (CLASSTYPE_COM_INTERFACE (type))
{
- warning ("taking dynamic typeid of object without -frtti");
- push_obstacks (&permanent_obstack, &permanent_obstack);
- init_rtti_processing ();
- pop_obstacks ();
- flag_rtti = 1;
+ cp_error ("RTTI not supported for COM interface type `%T'", type);
+ return error_mark_node;
}
/* If we don't have rtti stuff, get to a sub-object that does. */
@@ -252,9 +261,21 @@ build_x_typeid (exp)
tree exp;
{
tree cond = NULL_TREE;
- tree type = TREE_TYPE (tinfo_fn_type);
+ tree type;
int nonnull;
+ if (! flag_rtti)
+ {
+ error ("cannot use typeid with -fno-rtti");
+ return error_mark_node;
+ }
+
+ if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
+ {
+ error ("must #include <typeinfo> before using typeid");
+ return error_mark_node;
+ }
+
if (processing_template_decl)
return build_min_nt (TYPEID_EXPR, exp);
@@ -273,6 +294,7 @@ build_x_typeid (exp)
if (exp == error_mark_node)
return error_mark_node;
+ type = TREE_TYPE (tinfo_fn_type);
exp = build_call (exp, type, NULL_TREE);
if (cond)
@@ -302,7 +324,7 @@ get_tinfo_var (type)
/* Figure out how much space we need to allocate for the type_info object.
If our struct layout or the type_info classes are changed, this will
need to be modified. */
- if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
+ if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
size = 3 * POINTER_SIZE + INT_TYPE_SIZE;
else if (TREE_CODE (type) == POINTER_TYPE
&& ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
@@ -366,23 +388,25 @@ get_tinfo_fn (type)
TREE_PUBLIC (d) = 1;
DECL_ARTIFICIAL (d) = 1;
DECL_NOT_REALLY_EXTERN (d) = 1;
- DECL_MUTABLE_P (d) = 1;
+ SET_DECL_TINFO_FN_P (d);
TREE_TYPE (name) = copy_to_permanent (type);
pushdecl_top_level (d);
make_function_rtl (d);
- assemble_external (d);
+ mark_used (d);
mark_inline_for_output (d);
pop_obstacks ();
return d;
}
-static tree
+tree
get_typeid_1 (type)
tree type;
{
- tree t = build_call
+ tree t;
+
+ t = build_call
(get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);
return convert_from_reference (t);
}
@@ -395,15 +419,15 @@ get_typeid (type)
{
if (type == error_mark_node)
return error_mark_node;
-
- if (! flag_rtti)
+
+ if (TYPE_SIZE (type_info_type_node) == NULL_TREE)
{
- warning ("requesting typeid of object without -frtti");
- push_obstacks (&permanent_obstack, &permanent_obstack);
- init_rtti_processing ();
- pop_obstacks ();
- flag_rtti = 1;
+ error ("must #include <typeinfo> before using typeid");
+ return error_mark_node;
}
+
+ if (! flag_rtti)
+ error ("requesting typeid with -fno-rtti");
if (processing_template_decl)
return build_min_nt (TYPEID_EXPR, type);
@@ -418,6 +442,12 @@ get_typeid (type)
that is the operand of typeid are always ignored. */
type = TYPE_MAIN_VARIANT (type);
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
+ {
+ cp_error ("taking typeid of incomplete type `%T'", type);
+ return error_mark_node;
+ }
+
return get_typeid_1 (type);
}
@@ -442,10 +472,15 @@ build_dynamic_cast_1 (type, expr)
tree type, expr;
{
enum tree_code tc = TREE_CODE (type);
- tree exprtype = TREE_TYPE (expr);
+ tree exprtype;
enum tree_code ec;
tree dcast_fn;
+ tree old_expr = expr;
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ exprtype = TREE_TYPE (expr);
assert (exprtype != NULL_TREE);
ec = TREE_CODE (exprtype);
@@ -464,8 +499,8 @@ build_dynamic_cast_1 (type, expr)
goto fail;
if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
goto fail;
- if (TREE_READONLY (TREE_TYPE (exprtype))
- && ! TYPE_READONLY (TREE_TYPE (type)))
+ if (!at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (exprtype)))
goto fail;
if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
break;
@@ -484,8 +519,6 @@ build_dynamic_cast_1 (type, expr)
/* Apply trivial conversion T -> T& for dereferenced ptrs. */
if (ec == RECORD_TYPE)
{
- exprtype = build_type_variant (exprtype, TREE_READONLY (expr),
- TREE_THIS_VOLATILE (expr));
exprtype = build_reference_type (exprtype);
expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL, NULL_TREE);
@@ -500,8 +533,8 @@ build_dynamic_cast_1 (type, expr)
goto fail;
if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)
goto fail;
- if (TREE_READONLY (TREE_TYPE (exprtype))
- && ! TYPE_READONLY (TREE_TYPE (type)))
+ if (!at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (exprtype)))
goto fail;
}
@@ -513,6 +546,20 @@ build_dynamic_cast_1 (type, expr)
distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
&path);
+
+ if (distance == -2)
+ {
+ cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
+ TREE_TYPE (exprtype), TREE_TYPE (type));
+ return error_mark_node;
+ }
+ if (distance == -3)
+ {
+ cp_error ("dynamic_cast from `%T' to private base class `%T'",
+ TREE_TYPE (exprtype), TREE_TYPE (type));
+ return error_mark_node;
+ }
+
if (distance >= 0)
return build_vbase_path (PLUS_EXPR, type, expr, path, 0);
}
@@ -548,11 +595,11 @@ build_dynamic_cast_1 (type, expr)
dynamic_cast<D&>(b) (b an object) cannot succeed. */
if (ec == REFERENCE_TYPE)
{
- if (TREE_CODE (expr) == VAR_DECL
- && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE)
+ if (TREE_CODE (old_expr) == VAR_DECL
+ && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)
{
cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
- expr, type);
+ old_expr, type);
return throw_bad_cast ();
}
}
@@ -564,7 +611,7 @@ build_dynamic_cast_1 (type, expr)
&& TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
{
cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
- expr, type);
+ op, type);
retval = build_int_2 (0, 0);
TREE_TYPE (retval) = type;
return retval;
@@ -622,10 +669,10 @@ build_dynamic_cast_1 (type, expr)
DECL_ARTIFICIAL (dcast_fn) = 1;
pushdecl_top_level (dcast_fn);
make_function_rtl (dcast_fn);
- assemble_external (dcast_fn);
pop_obstacks ();
}
+ mark_used (dcast_fn);
result = build_call
(dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);
@@ -689,7 +736,7 @@ expand_si_desc (tdecl, type)
tree type;
{
tree t, elems, fn;
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
@@ -720,10 +767,10 @@ expand_si_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -737,7 +784,7 @@ expand_class_desc (tdecl, type)
{
tree name_string;
tree fn, tmp;
- char *name;
+ const char *name;
int i = CLASSTYPE_N_BASECLASSES (type);
int base_cnt = 0;
@@ -763,7 +810,9 @@ expand_class_desc (tdecl, type)
/* Actually const __user_type_info * */
fields [0] = build_lang_field_decl
(FIELD_DECL, NULL_TREE,
- build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
+ build_pointer_type (build_qualified_type
+ (type_info_type_node,
+ TYPE_QUAL_CONST)));
fields [1] = build_lang_field_decl
(FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
DECL_BIT_FIELD (fields[1]) = 1;
@@ -795,11 +844,10 @@ expand_class_desc (tdecl, type)
if (TREE_VIA_VIRTUAL (binfo))
{
tree t = BINFO_TYPE (binfo);
- char *name;
+ const char *name;
tree field;
- name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1);
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t));
+ FORMAT_VBASE_NAME (name, t);
field = lookup_field (type, get_identifier (name), 0, 0);
offset = size_binop (FLOOR_DIV_EXPR,
DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
@@ -900,10 +948,10 @@ expand_class_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -916,7 +964,7 @@ expand_ptr_desc (tdecl, type)
tree type;
{
tree t, elems, fn;
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
type = TREE_TYPE (type);
@@ -947,10 +995,10 @@ expand_ptr_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -963,10 +1011,9 @@ expand_attr_desc (tdecl, type)
tree type;
{
tree elems, t, fn;
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
- tree attrval = build_int_2
- (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
+ tree attrval = build_int_2 (TYPE_QUALS (type), 0);
expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
@@ -996,10 +1043,10 @@ expand_attr_desc (tdecl, type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -1010,9 +1057,9 @@ static void
expand_generic_desc (tdecl, type, fnname)
tree tdecl;
tree type;
- char *fnname;
+ const char *fnname;
{
- char *name = build_overload_name (type, 1, 1);
+ const char *name = build_overload_name (type, 1, 1);
tree name_string = combine_strings (build_string (strlen (name)+1, name));
tree elems = tree_cons
(NULL_TREE, decay_conversion (tdecl), tree_cons
@@ -1036,10 +1083,10 @@ expand_generic_desc (tdecl, type, fnname)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
- assemble_external (fn);
pop_obstacks ();
}
+ mark_used (fn);
fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);
expand_expr_stmt (fn);
}
@@ -1089,14 +1136,14 @@ synthesize_tinfo_fn (fndecl)
addr = decay_conversion (tdecl);
tmp = cp_convert (build_pointer_type (ptr_type_node), addr);
tmp = build_indirect_ref (tmp, 0);
- tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
+ tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node);
expand_start_cond (tmp, 0);
if (TREE_CODE (type) == FUNCTION_TYPE)
expand_generic_desc (tdecl, type, "__rtti_func");
else if (TREE_CODE (type) == ARRAY_TYPE)
expand_generic_desc (tdecl, type, "__rtti_array");
- else if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
+ else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
expand_attr_desc (tdecl, type);
else if (TREE_CODE (type) == POINTER_TYPE)
{
diff --git a/contrib/gcc/cp/search.c b/contrib/gcc/cp/search.c
index d5971e0..8760c6a 100644
--- a/contrib/gcc/cp/search.c
+++ b/contrib/gcc/cp/search.c
@@ -1,6 +1,6 @@
/* Breadth-first and depth-first routines for
searching multiple-inheritance lattice for GNU C++.
- Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "output.h"
#include "toplev.h"
+#include "varray.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -76,80 +77,80 @@ pop_stack_level (stack)
#define search_level stack_level
static struct search_level *search_stack;
-static void clear_memoized_cache PROTO((void));
-static tree make_memoized_table_entry PROTO((tree, tree, int));
static tree get_abstract_virtuals_1 PROTO((tree, int, tree));
+static tree next_baselink PROTO((tree));
static tree get_vbase_1 PROTO((tree, tree, unsigned int *));
static tree convert_pointer_to_vbase PROTO((tree, tree));
static tree lookup_field_1 PROTO((tree, tree));
static tree convert_pointer_to_single_level PROTO((tree, tree));
-static int lookup_fnfields_1 PROTO((tree, tree));
static int lookup_fnfields_here PROTO((tree, tree));
static int is_subobject_of_p PROTO((tree, tree));
static int hides PROTO((tree, tree));
static tree virtual_context PROTO((tree, tree, tree));
-static tree get_template_base_recursive
- PROTO((tree, tree, tree, int));
-static void dfs_walk PROTO((tree, void (*) (tree), int (*) (tree)));
-static void dfs_check_overlap PROTO((tree));
-static int dfs_no_overlap_yet PROTO((tree));
-static void envelope_add_decl PROTO((tree, tree, tree *));
+static tree dfs_check_overlap PROTO((tree, void *));
+static tree dfs_no_overlap_yet PROTO((tree, void *));
static int get_base_distance_recursive
- PROTO((tree, int, int, int, int *, tree *, tree, tree *,
+ PROTO((tree, int, int, int, int *, tree *, tree,
int, int *, int, int));
static void expand_upcast_fixups
PROTO((tree, tree, tree, tree, tree, tree, tree *));
static void fixup_virtual_upcast_offsets
PROTO((tree, tree, int, int, tree, tree, tree, tree,
tree *));
-static int markedp PROTO((tree));
-static int unmarkedp PROTO((tree));
-#ifdef MI_MATRIX
-static int numberedp PROTO((tree));
-static int unnumberedp PROTO((tree));
-#endif
-static int marked_vtable_pathp PROTO((tree));
-static int unmarked_vtable_pathp PROTO((tree));
-static int marked_new_vtablep PROTO((tree));
-static int unmarked_new_vtablep PROTO((tree));
-static int dfs_debug_unmarkedp PROTO((tree));
-#ifdef MI_MATRIX
-static void dfs_number PROTO((tree));
-static void dfs_unnumber PROTO((tree));
-static void dfs_record_inheritance PROTO((tree));
-#endif
-static void dfs_debug_mark PROTO((tree));
-static void dfs_find_vbases PROTO((tree));
-static void dfs_clear_vbase_slots PROTO((tree));
-static void dfs_unmark PROTO((tree));
-static void dfs_init_vbase_pointers PROTO((tree));
-static void dfs_get_vbase_types PROTO((tree));
-static void dfs_pushdecls PROTO((tree));
-static void dfs_compress_decls PROTO((tree));
-static void dfs_unuse_fields PROTO((tree));
-static void add_conversions PROTO((tree));
-static tree get_virtuals_named_this PROTO((tree));
-static tree get_virtual_destructor PROTO((tree, int));
-static int tree_has_any_destructor_p PROTO((tree, int));
+static tree unmarkedp PROTO((tree, void *));
+static tree marked_vtable_pathp PROTO((tree, void *));
+static tree unmarked_vtable_pathp PROTO((tree, void *));
+static tree marked_new_vtablep PROTO((tree, void *));
+static tree unmarked_new_vtablep PROTO((tree, void *));
+static tree marked_pushdecls_p PROTO((tree, void *));
+static tree unmarked_pushdecls_p PROTO((tree, void *));
+static tree dfs_debug_unmarkedp PROTO((tree, void *));
+static tree dfs_debug_mark PROTO((tree, void *));
+static tree dfs_find_vbases PROTO((tree, void *));
+static tree dfs_clear_vbase_slots PROTO((tree, void *));
+static tree dfs_init_vbase_pointers PROTO((tree, void *));
+static tree dfs_get_vbase_types PROTO((tree, void *));
+static tree dfs_push_type_decls PROTO((tree, void *));
+static tree dfs_push_decls PROTO((tree, void *));
+static tree dfs_unuse_fields PROTO((tree, void *));
+static tree add_conversions PROTO((tree, void *));
+static tree get_virtuals_named_this PROTO((tree, tree));
+static tree get_virtual_destructor PROTO((tree, void *));
+static tree tree_has_any_destructor_p PROTO((tree, void *));
static int covariant_return_p PROTO((tree, tree));
static struct search_level *push_search_level
PROTO((struct stack_level *, struct obstack *));
static struct search_level *pop_search_level
PROTO((struct stack_level *));
-static struct type_level *push_type_level
- PROTO((struct stack_level *, struct obstack *));
-static struct type_level *pop_type_level
- PROTO((struct type_level *));
-static tree my_tree_cons PROTO((tree, tree, tree));
-static tree my_build_string PROTO((char *));
-static struct memoized_entry * my_new_memoized_entry
- PROTO((struct memoized_entry *));
-static HOST_WIDE_INT breadth_first_search
- PROTO((tree, int (*) (tree, int), int (*) (tree, int)));
-
-static tree vbase_types;
-static tree vbase_decl_ptr_intermediate, vbase_decl_ptr;
-static tree vbase_init_result;
+static tree bfs_walk
+ PROTO((tree, tree (*) (tree, void *), tree (*) (tree, void *),
+ void *));
+static tree lookup_field_queue_p PROTO((tree, void *));
+static tree lookup_field_r PROTO((tree, void *));
+static tree dfs_walk_real PROTO ((tree,
+ tree (*) (tree, void *),
+ tree (*) (tree, void *),
+ tree (*) (tree, void *),
+ void *));
+static tree dfs_bfv_queue_p PROTO ((tree, void *));
+static tree dfs_bfv_helper PROTO ((tree, void *));
+static tree get_virtuals_named_this_r PROTO ((tree, void *));
+static tree context_for_name_lookup PROTO ((tree));
+static tree canonical_binfo PROTO ((tree));
+static tree shared_marked_p PROTO ((tree, void *));
+static tree shared_unmarked_p PROTO ((tree, void *));
+static int dependent_base_p PROTO ((tree));
+static tree dfs_accessible_queue_p PROTO ((tree, void *));
+static tree dfs_accessible_p PROTO ((tree, void *));
+static tree dfs_access_in_type PROTO ((tree, void *));
+static tree access_in_type PROTO ((tree, tree));
+static tree dfs_canonical_queue PROTO ((tree, void *));
+static tree dfs_assert_unmarked_p PROTO ((tree, void *));
+static void assert_canonical_unmarked PROTO ((tree));
+static int protected_accessible_p PROTO ((tree, tree, tree, tree));
+static int friend_accessible_p PROTO ((tree, tree, tree, tree));
+static void setup_class_bindings PROTO ((tree, int));
+static int template_self_reference_p PROTO ((tree, tree));
/* Allocate a level of searching. */
@@ -175,39 +176,9 @@ pop_search_level (obstack)
return stack;
}
-/* Search memoization. */
-
-struct type_level
-{
- struct stack_level base;
-
- /* First object allocated in obstack of entries. */
- char *entries;
-
- /* Number of types memoized in this context. */
- int len;
-
- /* Type being memoized; save this if we are saving
- memoized contexts. */
- tree type;
-};
-
-/* Obstack used for memoizing member and member function lookup. */
-
-static struct obstack type_obstack, type_obstack_entries;
-static struct type_level *type_stack;
static tree _vptr_name;
-/* Make things that look like tree nodes, but allocate them
- on type_obstack_entries. */
-static int my_tree_node_counter;
-
-extern int flag_memoize_lookups, flag_save_memoized_contexts;
-
/* Variables for gathering statistics. */
-static int my_memoized_entry_counter;
-static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];
-static int memoized_fields_searched[2];
#ifdef GATHER_STATISTICS
static int n_fields_searched;
static int n_calls_lookup_field, n_calls_lookup_field_1;
@@ -217,264 +188,14 @@ static int n_outer_fields_searched;
static int n_contexts_saved;
#endif /* GATHER_STATISTICS */
-/* Local variables to help save memoization contexts. */
-static tree prev_type_memoized;
-static struct type_level *prev_type_stack;
-
-/* This list is used by push_class_decls to know what decls need to
- be pushed into class scope. */
-static tree closed_envelopes = NULL_TREE;
-
-/* Allocate a level of type memoization context. */
-
-static struct type_level *
-push_type_level (stack, obstack)
- struct stack_level *stack;
- struct obstack *obstack;
-{
- struct type_level tem;
-
- tem.base.prev = stack;
-
- obstack_finish (&type_obstack_entries);
- tem.entries = (char *) obstack_base (&type_obstack_entries);
- tem.len = 0;
- tem.type = NULL_TREE;
-
- return (struct type_level *)push_stack_level (obstack, (char *)&tem, sizeof (tem));
-}
-
-/* Discard a level of type memoization context. */
-
-static struct type_level *
-pop_type_level (stack)
- struct type_level *stack;
-{
- obstack_free (&type_obstack_entries, stack->entries);
- return (struct type_level *)pop_stack_level ((struct stack_level *)stack);
-}
-
-/* Make something that looks like a TREE_LIST, but
- do it on the type_obstack_entries obstack. */
-
-static tree
-my_tree_cons (purpose, value, chain)
- tree purpose, value, chain;
-{
- tree p;
- struct obstack *ambient_obstack = current_obstack;
- current_obstack = &type_obstack_entries;
- p = tree_cons (purpose, value, chain);
- current_obstack = ambient_obstack;
- ++my_tree_node_counter;
- return p;
-}
-
-static tree
-my_build_string (str)
- char *str;
-{
- tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_string));
- ++my_tree_node_counter;
- TREE_TYPE (p) = 0;
- ((int *)p)[3] = 0;
- TREE_SET_CODE (p, STRING_CST);
- TREE_STRING_POINTER (p) = str;
- TREE_STRING_LENGTH (p) = strlen (str);
- return p;
-}
-
-/* Memoizing machinery to make searches for multiple inheritance
- reasonably efficient. */
-
-#define MEMOIZE_HASHSIZE 8
-typedef struct memoized_entry
-{
- struct memoized_entry *chain;
- int uid;
- tree data_members[MEMOIZE_HASHSIZE];
- tree function_members[MEMOIZE_HASHSIZE];
-} *ME;
-
-#define MEMOIZED_CHAIN(ENTRY) (((ME)ENTRY)->chain)
-#define MEMOIZED_UID(ENTRY) (((ME)ENTRY)->uid)
-#define MEMOIZED_FIELDS(ENTRY,INDEX) (((ME)ENTRY)->data_members[INDEX])
-#define MEMOIZED_FNFIELDS(ENTRY,INDEX) (((ME)ENTRY)->function_members[INDEX])
-/* The following is probably a lousy hash function. */
-#define MEMOIZED_HASH_FN(NODE) (((long)(NODE)>>4)&(MEMOIZE_HASHSIZE - 1))
-
-static struct memoized_entry *
-my_new_memoized_entry (chain)
- struct memoized_entry *chain;
-{
- struct memoized_entry *p
- = (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
- sizeof (struct memoized_entry));
- bzero ((char *) p, sizeof (struct memoized_entry));
- MEMOIZED_CHAIN (p) = chain;
- MEMOIZED_UID (p) = ++my_memoized_entry_counter;
- return p;
-}
-
-/* Clears the deferred pop from pop_memoized_context, if any. */
-
-static void
-clear_memoized_cache ()
-{
- if (prev_type_stack)
- {
- type_stack = pop_type_level (prev_type_stack);
- prev_type_memoized = 0;
- prev_type_stack = 0;
- }
-}
-
-/* Make an entry in the memoized table for type TYPE
- that the entry for NAME is FIELD. */
-
-static tree
-make_memoized_table_entry (type, name, function_p)
- tree type, name;
- int function_p;
-{
- int idx = MEMOIZED_HASH_FN (name);
- tree entry, *prev_entry;
-
- /* Since we allocate from the type_obstack, we must pop any deferred
- levels. */
- clear_memoized_cache ();
-
- memoized_adds[function_p] += 1;
- if (CLASSTYPE_MTABLE_ENTRY (type) == 0)
- {
- obstack_ptr_grow (&type_obstack, type);
- obstack_blank (&type_obstack, sizeof (struct memoized_entry *));
- CLASSTYPE_MTABLE_ENTRY (type) = (char *)my_new_memoized_entry ((struct memoized_entry *)0);
- type_stack->len++;
- if (type_stack->len * 2 >= type_stack->base.limit)
- my_friendly_abort (88);
- }
- if (function_p)
- prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
- else
- prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
-
- entry = my_tree_cons (name, NULL_TREE, *prev_entry);
- *prev_entry = entry;
-
- /* Don't know the error message to give yet. */
- TREE_TYPE (entry) = error_mark_node;
-
- return entry;
-}
-
-/* When a new function or class context is entered, we build
- a table of types which have been searched for members.
- The table is an array (obstack) of types. When a type is
- entered into the obstack, its CLASSTYPE_MTABLE_ENTRY
- field is set to point to a new record, of type struct memoized_entry.
-
- A non-NULL TREE_TYPE of the entry contains an access control error message.
-
- The slots for the data members are arrays of tree nodes.
- These tree nodes are lists, with the TREE_PURPOSE
- of this list the known member name, and the TREE_VALUE
- as the FIELD_DECL for the member.
-
- For member functions, the TREE_PURPOSE is again the
- name of the member functions for that class,
- and the TREE_VALUE of the list is a pairs
- whose TREE_PURPOSE is a member functions of this name,
- and whose TREE_VALUE is a list of known argument lists this
- member function has been called with. The TREE_TYPE of the pair,
- if non-NULL, is an error message to print. */
-
-/* Tell search machinery that we are entering a new context, and
- to update tables appropriately.
-
- TYPE is the type of the context we are entering, which can
- be NULL_TREE if we are not in a class's scope.
-
- USE_OLD, if nonzero tries to use previous context. */
-
-void
-push_memoized_context (type, use_old)
- tree type;
- int use_old;
-{
- int len;
- tree *tem;
-
- if (prev_type_stack)
- {
- if (use_old && prev_type_memoized == type)
- {
-#ifdef GATHER_STATISTICS
- n_contexts_saved++;
-#endif /* GATHER_STATISTICS */
- type_stack = prev_type_stack;
- prev_type_stack = 0;
-
- tem = &type_stack->base.first[0];
- len = type_stack->len;
- while (len--)
- CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)tem[len*2+1];
- return;
- }
- /* Otherwise, need to pop old stack here. */
- clear_memoized_cache ();
- }
-
- type_stack = push_type_level ((struct stack_level *)type_stack,
- &type_obstack);
- type_stack->type = type;
-}
-
-/* Tell search machinery that we have left a context.
- We do not currently save these contexts for later use.
- If we wanted to, we could not use pop_search_level, since
- poping that level allows the data we have collected to
- be clobbered; a stack of obstacks would be needed. */
-
-void
-pop_memoized_context (use_old)
- int use_old;
-{
- int len;
- tree *tem = &type_stack->base.first[0];
-
- if (! flag_save_memoized_contexts)
- use_old = 0;
- else if (use_old)
- {
- len = type_stack->len;
- while (len--)
- tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]);
-
- /* If there was a deferred pop, we need to pop it now. */
- clear_memoized_cache ();
-
- prev_type_stack = type_stack;
- prev_type_memoized = type_stack->type;
- }
-
- if (flag_memoize_lookups)
- {
- len = type_stack->len;
- while (len--)
- CLASSTYPE_MTABLE_ENTRY (tem[len*2])
- = (char *)MEMOIZED_CHAIN (CLASSTYPE_MTABLE_ENTRY (tem[len*2]));
- }
- if (! use_old)
- type_stack = pop_type_level (type_stack);
- else
- type_stack = (struct type_level *)type_stack->base.prev;
-}
/* Get a virtual binfo that is found inside BINFO's hierarchy that is
the same type as the type given in PARENT. To be optimal, we want
the first one that is found by going through the least number of
- virtual bases. */
+ virtual bases.
+
+ This uses a clever algorithm that updates *depth when we find the vbase,
+ and cuts off other paths of search when they reach that depth. */
static tree
get_vbase_1 (parent, binfo, depth)
@@ -513,6 +234,9 @@ get_vbase_1 (parent, binfo, depth)
return rval;
}
+/* Return the shortest path to vbase PARENT within BINFO, ignoring
+ access and ambiguity. */
+
tree
get_vbase (parent, binfo)
tree parent;
@@ -589,13 +313,13 @@ get_binfo (parent, binfo, protect)
static int
get_base_distance_recursive (binfo, depth, is_private, rval,
- rval_private_ptr, new_binfo_ptr, parent, path_ptr,
+ rval_private_ptr, new_binfo_ptr, parent,
protect, via_virtual_ptr, via_virtual,
current_scope_in_chain)
tree binfo;
int depth, is_private, rval;
int *rval_private_ptr;
- tree *new_binfo_ptr, parent, *path_ptr;
+ tree *new_binfo_ptr, parent;
int protect, *via_virtual_ptr, via_virtual;
int current_scope_in_chain;
{
@@ -609,38 +333,42 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
if (BINFO_TYPE (binfo) == parent || binfo == parent)
{
+ int better = 0;
+
if (rval == -1)
+ /* This is the first time we've found parent. */
+ better = 1;
+ else if (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
+ BINFO_OFFSET (binfo))
+ && *via_virtual_ptr && via_virtual)
+ {
+ /* A new path to the same vbase. If this one has better
+ access or is shorter, take it. */
+
+ if (protect)
+ better = *rval_private_ptr - is_private;
+ if (better == 0)
+ better = rval - depth;
+ }
+ else
+ {
+ /* Ambiguous base class. */
+ rval = depth = -2;
+
+ /* If we get an ambiguity between virtual and non-virtual base
+ class, return the non-virtual in case we are ignoring
+ ambiguity. */
+ better = *via_virtual_ptr - via_virtual;
+ }
+
+ if (better > 0)
{
rval = depth;
*rval_private_ptr = is_private;
*new_binfo_ptr = binfo;
*via_virtual_ptr = via_virtual;
}
- else
- {
- int same_object = (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
- BINFO_OFFSET (binfo))
- && *via_virtual_ptr && via_virtual);
-
- if (*via_virtual_ptr && via_virtual==0)
- {
- *rval_private_ptr = is_private;
- *new_binfo_ptr = binfo;
- *via_virtual_ptr = via_virtual;
- }
- else if (same_object)
- {
- if (*rval_private_ptr && ! is_private)
- {
- *rval_private_ptr = is_private;
- *new_binfo_ptr = binfo;
- *via_virtual_ptr = via_virtual;
- }
- return rval;
- }
- rval = -2;
- }
return rval;
}
@@ -653,43 +381,26 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- /* Find any specific instance of a virtual base, when searching with
- a binfo... */
- if (BINFO_MARKED (base_binfo) == 0 || TREE_CODE (parent) == TREE_VEC)
- {
- int via_private
- = (protect
- && (is_private
- || (!TREE_VIA_PUBLIC (base_binfo)
- && !(TREE_VIA_PROTECTED (base_binfo)
- && current_scope_in_chain)
- && !is_friend (BINFO_TYPE (binfo), current_scope ()))));
- int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
- int was;
-
- /* When searching for a non-virtual, we cannot mark
- virtually found binfos. */
- if (! this_virtual)
- SET_BINFO_MARKED (base_binfo);
-
-#define WATCH_VALUES(rval, via_private) (rval == -1 ? 3 : via_private)
-
- was = WATCH_VALUES (rval, *via_virtual_ptr);
- rval = get_base_distance_recursive (base_binfo, depth, via_private,
- rval, rval_private_ptr,
- new_binfo_ptr, parent, path_ptr,
- protect, via_virtual_ptr,
- this_virtual,
- current_scope_in_chain);
- /* watch for updates; only update if path is good. */
- if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was)
- BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
- if (rval == -2 && *via_virtual_ptr == 0)
- return rval;
+ int via_private
+ = (protect
+ && (is_private
+ || (!TREE_VIA_PUBLIC (base_binfo)
+ && !(TREE_VIA_PROTECTED (base_binfo)
+ && current_scope_in_chain)
+ && !is_friend (BINFO_TYPE (binfo), current_scope ()))));
+ int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
-#undef WATCH_VALUES
+ rval = get_base_distance_recursive (base_binfo, depth, via_private,
+ rval, rval_private_ptr,
+ new_binfo_ptr, parent,
+ protect, via_virtual_ptr,
+ this_virtual,
+ current_scope_in_chain);
- }
+ /* If we've found a non-virtual, ambiguous base class, we don't need
+ to keep searching. */
+ if (rval == -2 && *via_virtual_ptr == 0)
+ return rval;
}
return rval;
@@ -698,7 +409,7 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
/* Return the number of levels between type PARENT and the type given
in BINFO, following the leftmost path to PARENT not found along a
virtual path, if there are no real PARENTs (all come from virtual
- base classes), then follow the leftmost path to PARENT.
+ base classes), then follow the shortest public path to PARENT.
Return -1 if TYPE is not derived from PARENT.
Return -2 if PARENT is an ambiguous base class of TYPE, and PROTECT is
@@ -741,7 +452,8 @@ get_base_distance (parent, binfo, protect, path_ptr)
binfo = TYPE_BINFO (type);
if (path_ptr)
- BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (binfo) == NULL_TREE,
+ 980827);
}
else
my_friendly_abort (92);
@@ -760,11 +472,9 @@ get_base_distance (parent, binfo, protect, path_ptr)
rval = get_base_distance_recursive (binfo, 0, 0, -1,
&rval_private, &new_binfo, parent,
- path_ptr, watch_access, &via_virtual, 0,
+ watch_access, &via_virtual, 0,
0);
- dfs_walk (binfo, dfs_unmark, markedp);
-
/* Access restrictions don't count if we found an ambiguous basetype. */
if (rval == -2 && protect >= 0)
rval_private = 0;
@@ -772,12 +482,14 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (rval && protect && rval_private)
return -3;
- /* find real virtual base classes. */
+ /* If they gave us the real vbase binfo, which isn't in the main binfo
+ tree, deal with it. This happens when we are called from
+ expand_upcast_fixups. */
if (rval == -1 && TREE_CODE (parent) == TREE_VEC
&& parent == binfo_member (BINFO_TYPE (parent),
CLASSTYPE_VBASECLASSES (type)))
{
- BINFO_INHERITANCE_CHAIN (parent) = binfo;
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (parent) == binfo, 980827);
new_binfo = parent;
rval = 1;
}
@@ -828,7 +540,14 @@ lookup_field_1 (type, name)
if (temp)
return temp;
}
- if (DECL_NAME (field) == name)
+ if (TREE_CODE (field) == USING_DECL)
+ /* For now, we're just treating member using declarations as
+ old ARM-style access declarations. Thus, there's no reason
+ to return a USING_DECL, and the rest of the compiler can't
+ handle it. Once the class is defined, these are purged
+ from TYPE_FIELDS anyhow; see handle_using_decl. */
+ ;
+ else if (DECL_NAME (field) == name)
{
if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL)
&& DECL_ASSEMBLER_NAME (field) != NULL)
@@ -877,210 +596,461 @@ current_scope ()
return current_class_type;
}
-/* Compute the access of FIELD. This is done by computing
- the access available to each type in BASETYPES (which comes
- as a list of [via_public/basetype] in reverse order, namely base
- class before derived class). The first one which defines a
- access defines the access for the field. Otherwise, the
- access of the field is that which occurs normally.
+/* Return the scope of DECL, as appropriate when doing name-lookup. */
- Uses global variables CURRENT_CLASS_TYPE and
- CURRENT_FUNCTION_DECL to use friend relationships
- if necessary.
+static tree
+context_for_name_lookup (decl)
+ tree decl;
+{
+ /* [class.union]
+
+ For the purposes of name lookup, after the anonymous union
+ definition, the members of the anonymous union are considered to
+ have been defined in the scope in which teh anonymous union is
+ declared. */
+ tree context = DECL_REAL_CONTEXT (decl);
+
+ while (TYPE_P (context) && ANON_UNION_TYPE_P (context))
+ context = TYPE_CONTEXT (context);
+ if (!context)
+ context = global_namespace;
- This will be static when lookup_fnfield comes into this file.
+ return context;
+}
- access_public_node means that the field can be accessed by the current lexical
- scope.
+/* Return a canonical BINFO if BINFO is a virtual base, or just BINFO
+ otherwise. */
- access_protected_node means that the field cannot be accessed by the current
- lexical scope because it is protected.
+static tree
+canonical_binfo (binfo)
+ tree binfo;
+{
+ return (TREE_VIA_VIRTUAL (binfo)
+ ? TYPE_BINFO (BINFO_TYPE (binfo)) : binfo);
+}
- access_private_node means that the field cannot be accessed by the current
- lexical scope because it is private. */
+/* A queue function that simply ensures that we walk into the
+ canonical versions of virtual bases. */
-#if 0
-#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public_node
-#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected_node
-#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private_node
-#else
-#define PUBLIC_RETURN return access_public_node
-#define PROTECTED_RETURN return access_protected_node
-#define PRIVATE_RETURN return access_private_node
-#endif
+static tree
+dfs_canonical_queue (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return canonical_binfo (binfo);
+}
-#if 0
-/* Disabled with DECL_PUBLIC &c. */
-static tree previous_scope = NULL_TREE;
-#endif
+/* Called via dfs_walk from assert_canonical_unmarked. */
-tree
-compute_access (basetype_path, field)
- tree basetype_path, field;
+static tree
+dfs_assert_unmarked_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
- tree access;
- tree types;
- tree context;
- int protected_ok, via_protected;
- extern int flag_access_control;
-#if 1
- /* Replaces static decl above. */
- tree previous_scope;
-#endif
- int static_mem
- = ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
- || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
+ my_friendly_assert (!BINFO_MARKED (binfo), 0);
+ return NULL_TREE;
+}
- if (! flag_access_control)
- return access_public_node;
+/* Asserts that all the nodes below BINFO (using the canonical
+ versions of virtual bases) are unmarked. */
- /* The field lives in the current class. */
- if (BINFO_TYPE (basetype_path) == current_class_type)
- return access_public_node;
+static void
+assert_canonical_unmarked (binfo)
+ tree binfo;
+{
+ dfs_walk (binfo, dfs_assert_unmarked_p, dfs_canonical_queue, 0);
+}
-#if 0
- /* Disabled until pushing function scope clears these out. If ever. */
- /* Make these special cases fast. */
- if (current_scope () == previous_scope)
- {
- if (DECL_PUBLIC (field))
- return access_public_node;
- if (DECL_PROTECTED (field))
- return access_protected_node;
- if (DECL_PRIVATE (field))
- return access_private_node;
- }
-#endif
+/* If BINFO is marked, return a canonical version of BINFO.
+ Otherwise, return NULL_TREE. */
- /* We don't currently support access control on nested types. */
- if (TREE_CODE (field) == TYPE_DECL)
- return access_public_node;
+static tree
+shared_marked_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ binfo = canonical_binfo (binfo);
+ return markedp (binfo, data) ? binfo : NULL_TREE;
+}
- previous_scope = current_scope ();
+/* If BINFO is not marked, return a canonical version of BINFO.
+ Otherwise, return NULL_TREE. */
- context = DECL_REAL_CONTEXT (field);
+static tree
+shared_unmarked_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ binfo = canonical_binfo (binfo);
+ return unmarkedp (binfo, data) ? binfo : NULL_TREE;
+}
- /* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
- slot set to the union type rather than the record type containing
- the anonymous union. */
- if (context && ANON_UNION_TYPE_P (context)
- && TREE_CODE (field) == FIELD_DECL)
- context = TYPE_CONTEXT (context);
+/* Called from access_in_type via dfs_walk. Calculate the access to
+ DATA (which is really a DECL) in BINFO. */
- /* Virtual function tables are never private. But we should know that
- we are looking for this, and not even try to hide it. */
- if (DECL_NAME (field) && VFIELD_NAME_P (DECL_NAME (field)) == 1)
- PUBLIC_RETURN;
-
- /* Member found immediately within object. */
- if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE)
- {
- /* Are we (or an enclosing scope) friends with the class that has
- FIELD? */
- if (is_friend (context, previous_scope))
- PUBLIC_RETURN;
-
- /* If it's private, it's private, you letch. */
- if (TREE_PRIVATE (field))
- PRIVATE_RETURN;
-
- /* ARM $11.5. Member functions of a derived class can access the
- non-static protected members of a base class only through a
- pointer to the derived class, a reference to it, or an object
- of it. Also any subsequently derived classes also have
- access. */
- else if (TREE_PROTECTED (field))
- {
- if (current_class_type
- && (static_mem || DECL_CONSTRUCTOR_P (field))
- && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
- PUBLIC_RETURN;
- else
- PROTECTED_RETURN;
- }
+static tree
+dfs_access_in_type (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree decl = (tree) data;
+ tree type = BINFO_TYPE (binfo);
+ tree access = NULL_TREE;
+
+ if (context_for_name_lookup (decl) == type)
+ {
+ /* If we have desceneded to the scope of DECL, just note the
+ appropriate access. */
+ if (TREE_PRIVATE (decl))
+ access = access_private_node;
+ else if (TREE_PROTECTED (decl))
+ access = access_protected_node;
else
- PUBLIC_RETURN;
+ access = access_public_node;
}
-
- /* must reverse more than one element */
- basetype_path = reverse_path (basetype_path);
- types = basetype_path;
- via_protected = 0;
- access = access_default_node;
- protected_ok = static_mem && current_class_type
- && ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type);
-
- while (1)
+ else
{
- tree member;
- tree binfo = types;
- tree type = BINFO_TYPE (binfo);
- int private_ok = 0;
-
- /* Friends of a class can see protected members of its bases.
- Note that classes are their own friends. */
- if (is_friend (type, previous_scope))
- {
- protected_ok = 1;
- private_ok = 1;
- }
-
- member = purpose_member (type, DECL_ACCESS (field));
- if (member)
+ /* First, check for an access-declaration that gives us more
+ access to the DECL. The CONST_DECL for an enumeration
+ constant will not have DECL_LANG_SPECIFIC, and thus no
+ DECL_ACCESS. */
+ if (DECL_LANG_SPECIFIC (decl))
{
- access = TREE_VALUE (member);
- break;
+ access = purpose_member (type, DECL_ACCESS (decl));
+ if (access)
+ access = TREE_VALUE (access);
}
- types = BINFO_INHERITANCE_CHAIN (types);
-
- /* If the next type was VIA_PROTECTED, then fields of all remaining
- classes past that one are *at least* protected. */
- if (types)
+ if (!access)
{
- if (TREE_VIA_PROTECTED (types))
- via_protected = 1;
- else if (! TREE_VIA_PUBLIC (types) && ! private_ok)
+ int i;
+ int n_baselinks;
+ tree binfos;
+
+ /* Otherwise, scan our baseclasses, and pick the most favorable
+ access. */
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ for (i = 0; i < n_baselinks; ++i)
{
- access = access_private_node;
- break;
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ tree base_access = TREE_CHAIN (canonical_binfo (base_binfo));
+
+ if (!base_access || base_access == access_private_node)
+ /* If it was not accessible in the base, or only
+ accessible as a private member, we can't access it
+ all. */
+ base_access = NULL_TREE;
+ else if (TREE_VIA_PROTECTED (base_binfo))
+ /* Public and protected members in the base are
+ protected here. */
+ base_access = access_protected_node;
+ else if (!TREE_VIA_PUBLIC (base_binfo))
+ /* Public and protected members in the base are
+ private here. */
+ base_access = access_private_node;
+
+ /* See if the new access, via this base, gives more
+ access than our previous best access. */
+ if (base_access &&
+ (base_access == access_public_node
+ || (base_access == access_protected_node
+ && access != access_public_node)
+ || (base_access == access_private_node
+ && !access)))
+ {
+ access = base_access;
+
+ /* If the new access is public, we can't do better. */
+ if (access == access_public_node)
+ break;
+ }
}
}
- else
- break;
}
- reverse_path (basetype_path);
- /* No special visibilities apply. Use normal rules. */
+ /* Note the access to DECL in TYPE. */
+ TREE_CHAIN (binfo) = access;
+
+ /* Mark TYPE as visited so that if we reach it again we do not
+ duplicate our efforts here. */
+ SET_BINFO_MARKED (binfo);
+
+ return NULL_TREE;
+}
+
+/* Return the access to DECL in TYPE. */
+
+static tree
+access_in_type (type, decl)
+ tree type;
+ tree decl;
+{
+ tree binfo = TYPE_BINFO (type);
+
+ /* We must take into account
+
+ [class.paths]
+
+ If a name can be reached by several paths through a multiple
+ inheritance graph, the access is that of the path that gives
+ most access.
+
+ The algorithm we use is to make a post-order depth-first traversal
+ of the base-class hierarchy. As we come up the tree, we annotate
+ each node with the most lenient access. */
+ dfs_walk_real (binfo, 0, dfs_access_in_type, shared_unmarked_p, decl);
+ dfs_walk (binfo, dfs_unmark, shared_marked_p, 0);
+ assert_canonical_unmarked (binfo);
+
+ return TREE_CHAIN (binfo);
+}
+
+/* Called from dfs_accessible_p via dfs_walk. */
+
+static tree
+dfs_accessible_queue_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ if (BINFO_MARKED (binfo))
+ return NULL_TREE;
+
+ /* If this class is inherited via private or protected inheritance,
+ then we can't see it, unless we are a friend of the subclass. */
+ if (!TREE_VIA_PUBLIC (binfo)
+ && !is_friend (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
+ current_scope ()))
+ return NULL_TREE;
+
+ return canonical_binfo (binfo);
+}
+
+/* Called from dfs_accessible_p via dfs_walk. */
+
+static tree
+dfs_accessible_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ int protected_ok = data != 0;
+ tree access;
+
+ /* We marked the binfos while computing the access in each type.
+ So, we unmark as we go now. */
+ SET_BINFO_MARKED (binfo);
+
+ access = TREE_CHAIN (binfo);
+ if (access == access_public_node
+ || (access == access_protected_node && protected_ok))
+ return binfo;
+ else if (access && is_friend (BINFO_TYPE (binfo), current_scope ()))
+ return binfo;
+
+ return NULL_TREE;
+}
+
+/* Returns non-zero if it is OK to access DECL when named in TYPE
+ through an object indiated by BINFO in the context of DERIVED. */
+
+static int
+protected_accessible_p (type, decl, derived, binfo)
+ tree type;
+ tree decl;
+ tree derived;
+ tree binfo;
+{
+ tree access;
+
+ /* We're checking this clause from [class.access.base]
+
+ m as a member of N is protected, and the reference occurs in a
+ member or friend of class N, or in a member or friend of a
+ class P derived from N, where m as a member of P is private or
+ protected.
- if (access == access_default_node)
+ If DERIVED isn't derived from TYPE, then it certainly does not
+ apply. */
+ if (!DERIVED_FROM_P (type, derived))
+ return 0;
+
+ access = access_in_type (derived, decl);
+ if (same_type_p (derived, type))
{
- if (is_friend (context, previous_scope))
- access = access_public_node;
- else if (TREE_PRIVATE (field))
- access = access_private_node;
- else if (TREE_PROTECTED (field))
- access = access_protected_node;
- else
- access = access_public_node;
+ if (access != access_private_node)
+ return 0;
+ }
+ else if (access != access_private_node
+ && access != access_protected_node)
+ return 0;
+
+ /* [class.protected]
+
+ When a friend or a member function of a derived class references
+ a protected nonstatic member of a base class, an access check
+ applies in addition to those described earlier in clause
+ _class.access_.4) Except when forming a pointer to member
+ (_expr.unary.op_), the access must be through a pointer to,
+ reference to, or object of the derived class itself (or any class
+ derived from that class) (_expr.ref_). If the access is to form
+ a pointer to member, the nested-name-specifier shall name the
+ derived class (or any class derived from that class). */
+ if (DECL_NONSTATIC_MEMBER_P (decl))
+ {
+ /* We can tell through what the reference is occurring by
+ chasing BINFO up to the root. */
+ tree t = binfo;
+ while (BINFO_INHERITANCE_CHAIN (t))
+ t = BINFO_INHERITANCE_CHAIN (t);
+
+ if (!DERIVED_FROM_P (derived, BINFO_TYPE (t)))
+ return 0;
}
- if (access == access_public_node && via_protected)
- access = access_protected_node;
+ return 1;
+}
- if (access == access_protected_node && protected_ok)
- access = access_public_node;
+/* Returns non-zero if SCOPE is a friend of a type which would be able
+ to acces DECL, named in TYPE, through the object indicated by
+ BINFO. */
-#if 0
- if (access == access_public_node)
- DECL_PUBLIC (field) = 1;
- else if (access == access_protected_node)
- DECL_PROTECTED (field) = 1;
- else if (access == access_private_node)
- DECL_PRIVATE (field) = 1;
- else my_friendly_abort (96);
-#endif
- return access;
+static int
+friend_accessible_p (scope, type, decl, binfo)
+ tree scope;
+ tree type;
+ tree decl;
+ tree binfo;
+{
+ tree befriending_classes;
+ tree t;
+
+ if (!scope)
+ return 0;
+
+ if (TREE_CODE (scope) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (scope))
+ befriending_classes = DECL_BEFRIENDING_CLASSES (scope);
+ else if (TYPE_P (scope))
+ befriending_classes = CLASSTYPE_BEFRIENDING_CLASSES (scope);
+ else
+ return 0;
+
+ for (t = befriending_classes; t; t = TREE_CHAIN (t))
+ if (protected_accessible_p (type, decl, TREE_VALUE (t), binfo))
+ return 1;
+
+ if (TREE_CODE (scope) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (scope))
+ {
+ /* Perhaps this SCOPE is a member of a class which is a
+ friend. */
+ if (friend_accessible_p (DECL_CLASS_CONTEXT (scope), type,
+ decl, binfo))
+ return 1;
+
+ /* Or an instantiation of something which is a friend. */
+ if (DECL_TEMPLATE_INFO (scope))
+ return friend_accessible_p (DECL_TI_TEMPLATE (scope),
+ type, decl, binfo);
+ }
+ else if (CLASSTYPE_TEMPLATE_INFO (scope))
+ return friend_accessible_p (CLASSTYPE_TI_TEMPLATE (scope),
+ type, decl, binfo);
+
+ return 0;
+}
+
+/* DECL is a declaration from a base class of TYPE, which was the
+ classs used to name DECL. Return non-zero if, in the current
+ context, DECL is accessible. If TYPE is actually a BINFO node,
+ then we can tell in what context the access is occurring by looking
+ at the most derived class along the path indicated by BINFO. */
+
+int
+accessible_p (type, decl)
+ tree type;
+ tree decl;
+
+{
+ tree binfo;
+ tree t;
+
+ /* Non-zero if it's OK to access DECL if it has protected
+ accessibility in TYPE. */
+ int protected_ok = 0;
+
+ /* If we're not checking access, everything is accessible. */
+ if (!flag_access_control)
+ return 1;
+
+ /* If this declaration is in a block or namespace scope, there's no
+ access control. */
+ if (!TYPE_P (context_for_name_lookup (decl)))
+ return 1;
+
+ /* We don't do access control for types yet. */
+ if (TREE_CODE (decl) == TYPE_DECL)
+ return 1;
+
+ if (!TYPE_P (type))
+ {
+ binfo = type;
+ type = BINFO_TYPE (type);
+ }
+ else
+ binfo = TYPE_BINFO (type);
+
+ /* [class.access.base]
+
+ A member m is accessible when named in class N if
+
+ --m as a member of N is public, or
+
+ --m as a member of N is private, and the reference occurs in a
+ member or friend of class N, or
+
+ --m as a member of N is protected, and the reference occurs in a
+ member or friend of class N, or in a member or friend of a
+ class P derived from N, where m as a member of P is private or
+ protected, or
+
+ --there exists a base class B of N that is accessible at the point
+ of reference, and m is accessible when named in class B.
+
+ We walk the base class hierarchy, checking these conditions. */
+
+ /* Figure out where the reference is occurring. Check to see if
+ DECL is private or protected in this scope, since that will
+ determine whether protected access in TYPE allowed. */
+ if (current_class_type)
+ protected_ok
+ = protected_accessible_p (type, decl, current_class_type,
+ binfo);
+
+ /* Now, loop through the classes of which we are a friend. */
+ if (!protected_ok)
+ protected_ok = friend_accessible_p (current_scope (),
+ type, decl, binfo);
+
+ /* Standardize on the same that will access_in_type will use. We
+ don't need to know what path was chosen from this point onwards. */
+ binfo = TYPE_BINFO (type);
+
+ /* Compute the accessibility of DECL in the class hierarchy
+ dominated by type. */
+ access_in_type (type, decl);
+ /* Walk the hierarchy again, looking for a base class that allows
+ access. */
+ t = dfs_walk (binfo, dfs_accessible_p,
+ dfs_accessible_queue_p,
+ protected_ok ? &protected_ok : 0);
+ /* Clear any mark bits. Note that we have to walk the whole tree
+ here, since we have aborted the previous walk from some point
+ deep in the tree. */
+ dfs_walk (binfo, dfs_unmark, dfs_canonical_queue, 0);
+ assert_canonical_unmarked (binfo);
+
+ return t != NULL_TREE;
}
/* Routine to see if the sub-object denoted by the binfo PARENT can be
@@ -1092,18 +1062,31 @@ static int
is_subobject_of_p (parent, binfo)
tree parent, binfo;
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree binfos;
+ int i, n_baselinks;
+
+ /* We want to canonicalize for comparison purposes. But, when we
+ iterate through basetypes later, we want the binfos from the
+ original hierarchy. That's why we have to calculate BINFOS
+ first, and then canonicalize. */
+ binfos = BINFO_BASETYPES (binfo);
+ parent = canonical_binfo (parent);
+ binfo = canonical_binfo (binfo);
if (parent == binfo)
return 1;
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
/* Process and/or queue base types. */
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TREE_VIA_VIRTUAL (base_binfo))
- base_binfo = TYPE_BINFO (BINFO_TYPE (base_binfo));
+ if (!CLASS_TYPE_P (TREE_TYPE (base_binfo)))
+ /* If we see a TEMPLATE_TYPE_PARM, or some such, as a base
+ class there's no way to descend into it. */
+ continue;
+
if (is_subobject_of_p (parent, base_binfo))
return 1;
}
@@ -1154,27 +1137,230 @@ lookup_fnfields_here (type, name)
return -1;
}
-/* Look for a field named NAME in an inheritance lattice dominated by
- XBASETYPE. PROTECT is zero if we can avoid computing access
- information, otherwise it is 1. WANT_TYPE is 1 when we should only
- return TYPE_DECLs, if no TYPE_DECL can be found return NULL_TREE.
+struct lookup_field_info {
+ /* The type in which we're looking. */
+ tree type;
+ /* The name of the field for which we're looking. */
+ tree name;
+ /* If non-NULL, the current result of the lookup. */
+ tree rval;
+ /* The path to RVAL. */
+ tree rval_binfo;
+ /* If non-NULL, the lookup was ambiguous, and this is a list of the
+ candidates. */
+ tree ambiguous;
+ /* If non-zero, we are looking for types, not data members. */
+ int want_type;
+ /* If non-zero, RVAL was found by looking through a dependent base. */
+ int from_dep_base_p;
+ /* If something went wrong, a message indicating what. */
+ const char *errstr;
+};
+
+/* Returns non-zero if BINFO is not hidden by the value found by the
+ lookup so far. If BINFO is hidden, then there's no need to look in
+ it. DATA is really a struct lookup_field_info. Called from
+ lookup_field via breadth_first_search. */
+
+static tree
+lookup_field_queue_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct lookup_field_info *lfi = (struct lookup_field_info *) data;
+
+ /* Don't look for constructors or destructors in base classes. */
+ if (lfi->name == ctor_identifier || lfi->name == dtor_identifier)
+ return NULL_TREE;
+
+ /* If this base class is hidden by the best-known value so far, we
+ don't need to look. */
+ if (!lfi->from_dep_base_p && lfi->rval_binfo
+ && hides (lfi->rval_binfo, binfo))
+ return NULL_TREE;
+
+ if (TREE_VIA_VIRTUAL (binfo))
+ return binfo_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (lfi->type));
+ else
+ return binfo;
+}
+
+/* Within the scope of a template class, you can refer to the
+ particular to the current specialization with the name of the
+ template itself. For example:
+
+ template <typename T> struct S { S* sp; }
+
+ Returns non-zero if DECL is such a declaration in a class TYPE. */
+
+static int
+template_self_reference_p (type, decl)
+ tree type;
+ tree decl;
+{
+ return (CLASSTYPE_USE_TEMPLATE (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && TREE_CODE (decl) == TYPE_DECL
+ && DECL_ARTIFICIAL (decl)
+ && DECL_NAME (decl) == constructor_name (type));
+}
+
+/* DATA is really a struct lookup_field_info. Look for a field with
+ the name indicated there in BINFO. If this function returns a
+ non-NULL value it is the result of the lookup. Called from
+ lookup_field via breadth_first_search. */
+
+static tree
+lookup_field_r (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct lookup_field_info *lfi = (struct lookup_field_info *) data;
+ tree type = BINFO_TYPE (binfo);
+ tree nval = NULL_TREE;
+ int from_dep_base_p;
+
+ /* First, look for a function. There can't be a function and a data
+ member with the same name, and if there's a function and a type
+ with the same name, the type is hidden by the function. */
+ if (!lfi->want_type)
+ {
+ int idx = lookup_fnfields_here (type, lfi->name);
+ if (idx >= 0)
+ nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
+ }
+
+ if (!nval)
+ /* Look for a data member or type. */
+ nval = lookup_field_1 (type, lfi->name);
+
+ /* If there is no declaration with the indicated name in this type,
+ then there's nothing to do. */
+ if (!nval)
+ return NULL_TREE;
+
+ /* If we're looking up a type (as with an elaborated type specifier)
+ we ignore all non-types we find. */
+ if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL)
+ {
+ nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type));
+ if (nval)
+ nval = TYPE_MAIN_DECL (TREE_VALUE (nval));
+ else
+ return NULL_TREE;
+ }
+
+ /* You must name a template base class with a template-id. */
+ if (!same_type_p (type, lfi->type)
+ && template_self_reference_p (type, nval))
+ return NULL_TREE;
+
+ from_dep_base_p = dependent_base_p (binfo);
+ if (lfi->from_dep_base_p && !from_dep_base_p)
+ {
+ /* If the new declaration is not found via a dependent base, and
+ the old one was, then we must prefer the new one. We weren't
+ really supposed to be able to find the old one, so we don't
+ want to be affected by a specialization. Consider:
+
+ struct B { typedef int I; };
+ template <typename T> struct D1 : virtual public B {};
+ template <typename T> struct D :
+ public D1, virtual pubic B { I i; };
+
+ The `I' in `D<T>' is unambigousuly `B::I', regardless of how
+ D1 is specialized. */
+ lfi->from_dep_base_p = 0;
+ lfi->rval = NULL_TREE;
+ lfi->rval_binfo = NULL_TREE;
+ lfi->ambiguous = NULL_TREE;
+ lfi->errstr = 0;
+ }
+ else if (lfi->rval_binfo && !lfi->from_dep_base_p && from_dep_base_p)
+ /* Similarly, if the old declaration was not found via a dependent
+ base, and the new one is, ignore the new one. */
+ return NULL_TREE;
+
+ /* If the lookup already found a match, and the new value doesn't
+ hide the old one, we might have an ambiguity. */
+ if (lfi->rval_binfo && !hides (binfo, lfi->rval_binfo))
+ {
+ if (nval == lfi->rval && SHARED_MEMBER_P (nval))
+ /* The two things are really the same. */
+ ;
+ else if (hides (lfi->rval_binfo, binfo))
+ /* The previous value hides the new one. */
+ ;
+ else
+ {
+ /* We have a real ambiguity. We keep a chain of all the
+ candidates. */
+ if (!lfi->ambiguous && lfi->rval)
+ {
+ /* This is the first time we noticed an ambiguity. Add
+ what we previously thought was a reasonable candidate
+ to the list. */
+ lfi->ambiguous = scratch_tree_cons (NULL_TREE, lfi->rval,
+ NULL_TREE);
+ TREE_TYPE (lfi->ambiguous) = error_mark_node;
+ }
+
+ /* Add the new value. */
+ lfi->ambiguous = scratch_tree_cons (NULL_TREE, nval,
+ lfi->ambiguous);
+ TREE_TYPE (lfi->ambiguous) = error_mark_node;
+ lfi->errstr = "request for member `%D' is ambiguous";
+ }
+ }
+ else
+ {
+ /* If the thing we're looking for is a virtual base class, then
+ we know we've got what we want at this point; there's no way
+ to get an ambiguity. */
+ if (VBASE_NAME_P (lfi->name))
+ {
+ lfi->rval = nval;
+ return nval;
+ }
+
+ if (from_dep_base_p && TREE_CODE (nval) != TYPE_DECL
+ /* We need to return a member template class so we can
+ define partial specializations. Is there a better
+ way? */
+ && !DECL_CLASS_TEMPLATE_P (nval))
+ /* The thing we're looking for isn't a type, so the implicit
+ typename extension doesn't apply, so we just pretend we
+ didn't find anything. */
+ return NULL_TREE;
+
+ lfi->rval = nval;
+ lfi->from_dep_base_p = from_dep_base_p;
+ lfi->rval_binfo = binfo;
+ }
+
+ return NULL_TREE;
+}
+
+/* Look for a memer named NAME in an inheritance lattice dominated by
+ XBASETYPE. PROTECT is 0 or two, we do not check access. If it is
+ 1, we enforce accessibility. If PROTECT is zero, then, for an
+ ambiguous lookup, we return NULL. If PROTECT is 1, we issue an
+ error message. If PROTECT is 2, we return a TREE_LIST whose
+ TREEE_TYPE is error_mark_node and whose TREE_VALUEs are the list of
+ ambiguous candidates.
- It was not clear what should happen if WANT_TYPE is set, and an
- ambiguity is found. At least one use (lookup_name) to not see
- the error. */
+ WANT_TYPE is 1 when we should only return TYPE_DECLs, if no
+ TYPE_DECL can be found return NULL_TREE. */
tree
-lookup_field (xbasetype, name, protect, want_type)
+lookup_member (xbasetype, name, protect, want_type)
register tree xbasetype, name;
int protect, want_type;
{
- int head = 0, tail = 0;
- tree rval, rval_binfo = NULL_TREE, rval_binfo_h = NULL_TREE;
- tree type = NULL_TREE, basetype_chain, basetype_path = NULL_TREE;
- tree this_v = access_default_node;
- tree entry, binfo, binfo_h;
- tree own_access = access_default_node;
- int vbase_name_p = VBASE_NAME_P (name);
+ tree rval, rval_binfo = NULL_TREE;
+ tree type = NULL_TREE, basetype_path = NULL_TREE;
+ struct lookup_field_info lfi;
/* rval_binfo is the binfo associated with the found member, note,
this can be set with useful information, even when rval is not
@@ -1183,27 +1369,7 @@ lookup_field (xbasetype, name, protect, want_type)
checks. Whereas rval is only set if a proper (not hidden)
non-function member is found. */
- /* rval_binfo_h and binfo_h are binfo values used when we perform the
- hiding checks, as virtual base classes may not be shared. The strategy
- is we always go into the binfo hierarchy owned by TYPE_BINFO of
- virtual base classes, as we cross virtual base class lines. This way
- we know that binfo of a virtual base class will always == itself when
- found along any line. (mrs) */
-
- char *errstr = 0;
-
- /* Set this to nonzero if we don't know how to compute
- accurate error messages for access control. */
- int idx = MEMOIZED_HASH_FN (name);
-
-#if 0
- /* We cannot search for constructor/destructor names like this. */
- /* This can't go here, but where should it go? */
- /* If we are looking for a constructor in a templated type, use the
- unspecialized name, as that is how we store it. */
- if (IDENTIFIER_TEMPLATE (name))
- name = constructor_name (name);
-#endif
+ const char *errstr = 0;
if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype)
&& IDENTIFIER_CLASS_VALUE (name))
@@ -1211,6 +1377,8 @@ lookup_field (xbasetype, name, protect, want_type)
tree field = IDENTIFIER_CLASS_VALUE (name);
if (TREE_CODE (field) != FUNCTION_DECL
&& ! (want_type && TREE_CODE (field) != TYPE_DECL))
+ /* We're in the scope of this class, and the value has already
+ been looked up. Just return the cached value. */
return field;
}
@@ -1223,416 +1391,119 @@ lookup_field (xbasetype, name, protect, want_type)
{
type = xbasetype;
basetype_path = TYPE_BINFO (type);
- BINFO_VIA_PUBLIC (basetype_path) = 1;
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE,
+ 980827);
}
else
my_friendly_abort (97);
complete_type (type);
- if (CLASSTYPE_MTABLE_ENTRY (type))
- {
- tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
-
- while (tem && TREE_PURPOSE (tem) != name)
- {
- memoized_fields_searched[0]++;
- tem = TREE_CHAIN (tem);
- }
- if (tem)
- {
- if (protect && TREE_TYPE (tem))
- {
- error (TREE_STRING_POINTER (TREE_TYPE (tem)),
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (DECL_FIELD_CONTEXT (TREE_VALUE (tem))));
- return error_mark_node;
- }
- if (TREE_VALUE (tem) == NULL_TREE)
- memoized_fast_rejects[0] += 1;
- else
- memoized_fast_finds[0] += 1;
- return TREE_VALUE (tem);
- }
- }
-
#ifdef GATHER_STATISTICS
n_calls_lookup_field++;
#endif /* GATHER_STATISTICS */
- if (protect && flag_memoize_lookups && ! toplevel_bindings_p ())
- entry = make_memoized_table_entry (type, name, 0);
- else
- entry = 0;
-
- rval = lookup_field_1 (type, name);
-
- if (rval || lookup_fnfields_here (type, name) >= 0)
- {
- if (entry)
- TREE_VALUE (entry) = rval;
-
- if (rval)
- {
- if (want_type)
- {
- if (TREE_CODE (rval) != TYPE_DECL)
- {
- rval = purpose_member (name, CLASSTYPE_TAGS (type));
- if (rval)
- rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
- }
- }
- else
- {
- if (TREE_CODE (rval) == TYPE_DECL
- && lookup_fnfields_here (type, name) >= 0)
- rval = NULL_TREE;
- }
- }
-
- if (protect && rval)
- {
- if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
- this_v = compute_access (basetype_path, rval);
- if (TREE_CODE (rval) == CONST_DECL)
- {
- if (this_v == access_private_node)
- errstr = "enum `%D' is a private value of class `%T'";
- else if (this_v == access_protected_node)
- errstr = "enum `%D' is a protected value of class `%T'";
- }
- else
- {
- if (this_v == access_private_node)
- errstr = "member `%D' is a private member of class `%T'";
- else if (this_v == access_protected_node)
- errstr = "member `%D' is a protected member of class `%T'";
- }
- }
- rval_binfo = basetype_path;
- goto out;
- }
-
- basetype_chain = build_expr_list (NULL_TREE, basetype_path);
- TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
- TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
- TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
-
- /* The ambiguity check relies upon breadth first searching. */
-
- search_stack = push_search_level (search_stack, &search_obstack);
- binfo = basetype_path;
- binfo_h = binfo;
-
- while (1)
+ bzero ((PTR) &lfi, sizeof (lfi));
+ lfi.type = type;
+ lfi.name = name;
+ lfi.want_type = want_type;
+ bfs_walk (basetype_path, &lookup_field_r, &lookup_field_queue_p, &lfi);
+ rval = lfi.rval;
+ rval_binfo = lfi.rval_binfo;
+ if (rval_binfo)
+ type = BINFO_TYPE (rval_binfo);
+ errstr = lfi.errstr;
+
+ /* If we are not interested in ambiguities, don't report them;
+ just return NULL_TREE. */
+ if (!protect && lfi.ambiguous)
+ return NULL_TREE;
+
+ if (protect == 2)
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- tree nval;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (BINFO_FIELDS_MARKED (base_binfo) == 0)
- {
- tree btypes;
-
- SET_BINFO_FIELDS_MARKED (base_binfo);
- btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
- TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
- TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
- TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
- if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = my_tree_cons (NULL_TREE,
- TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
- btypes);
- else
- btypes = my_tree_cons (NULL_TREE,
- TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
- btypes);
- obstack_ptr_grow (&search_obstack, btypes);
- tail += 1;
- if (tail >= search_stack->limit)
- my_friendly_abort (98);
- }
- }
-
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetype_chain = search_stack->first[head++];
- binfo_h = TREE_VALUE (basetype_chain);
- basetype_chain = TREE_CHAIN (basetype_chain);
- basetype_path = TREE_VALUE (basetype_chain);
- if (TREE_CHAIN (basetype_chain))
- BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
+ if (lfi.ambiguous)
+ return lfi.ambiguous;
else
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
-
- binfo = basetype_path;
- type = BINFO_TYPE (binfo);
-
- /* See if we can find NAME in TYPE. If RVAL is nonzero,
- and we do find NAME in TYPE, verify that such a second
- sighting is in fact valid. */
-
- nval = lookup_field_1 (type, name);
-
- if (nval || lookup_fnfields_here (type, name)>=0)
- {
- if (nval && nval == rval && SHARED_MEMBER_P (nval))
- {
- /* This is ok, the member found is the same [class.ambig] */
- }
- else if (rval_binfo && hides (rval_binfo_h, binfo_h))
- {
- /* This is ok, the member found is in rval_binfo, not
- here (binfo). */
- }
- else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h))
- {
- /* This is ok, the member found is here (binfo), not in
- rval_binfo. */
- if (nval)
- {
- rval = nval;
- if (entry || protect)
- this_v = compute_access (basetype_path, rval);
- /* These may look ambiguous, but they really are not. */
- if (vbase_name_p)
- break;
- }
- else
- {
- /* Undo finding it before, as something else hides it. */
- rval = NULL_TREE;
- }
- rval_binfo = binfo;
- rval_binfo_h = binfo_h;
- }
- else
- {
- /* This is ambiguous. */
- errstr = "request for member `%D' is ambiguous";
- protect += 2;
- break;
- }
- }
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- if (entry)
- TREE_VALUE (entry) = rval;
-
- if (rval_binfo)
- {
- type = BINFO_TYPE (rval_binfo);
-
- if (rval)
- {
- if (want_type)
- {
- if (TREE_CODE (rval) != TYPE_DECL)
- {
- rval = purpose_member (name, CLASSTYPE_TAGS (type));
- if (rval)
- rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
- }
- }
- else
- {
- if (TREE_CODE (rval) == TYPE_DECL
- && lookup_fnfields_here (type, name) >= 0)
- rval = NULL_TREE;
- }
- }
- }
-
- if (rval == NULL_TREE)
- errstr = 0;
-
- /* If this FIELD_DECL defines its own access level, deal with that. */
- if (rval && errstr == 0
- && ((protect&1) || entry)
- && DECL_LANG_SPECIFIC (rval)
- && DECL_ACCESS (rval))
- {
- while (tp < search_tail)
- {
- /* If is possible for one of the derived types on the path to
- have defined special access for this field. Look for such
- declarations and report an error if a conflict is found. */
- tree new_v = NULL_TREE;
-
- if (this_v != access_default_node)
- new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval);
- if (this_v != access_default_node && new_v != this_v)
- {
- errstr = "conflicting access to member `%D'";
- this_v = access_default_node;
- }
- own_access = new_v;
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- else
- {
- while (tp < search_tail)
- {
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- }
- search_stack = pop_search_level (search_stack);
-
- if (errstr == 0)
- {
- if (own_access == access_private_node)
- errstr = "member `%D' declared private";
- else if (own_access == access_protected_node)
- errstr = "member `%D' declared protected";
- else if (this_v == access_private_node)
- errstr = TREE_PRIVATE (rval)
- ? "member `%D' is private"
- : "member `%D' is from private base class";
- else if (this_v == access_protected_node)
- errstr = TREE_PROTECTED (rval)
- ? "member `%D' is protected"
- : "member `%D' is from protected base class";
- }
-
- out:
- if (entry)
- {
- if (errstr)
- {
- tree error_string = my_build_string (errstr);
- /* Save error message with entry. */
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Mark entry as having no error string. */
- TREE_TYPE (entry) = NULL_TREE;
- }
+ protect = 0;
}
- if (protect == 2)
- {
- /* If we are not interested in ambiguities, don't report them,
- just return NULL_TREE. */
- rval = NULL_TREE;
- protect = 0;
- }
+ /* [class.access]
+
+ In the case of overloaded function names, access control is
+ applied to the function selected by overloaded resolution. */
+ if (rval && protect && !is_overloaded_fn (rval)
+ && !IS_SIGNATURE_POINTER (DECL_REAL_CONTEXT (rval))
+ && !IS_SIGNATURE_REFERENCE (DECL_REAL_CONTEXT (rval))
+ && !enforce_access (xbasetype, rval))
+ return error_mark_node;
if (errstr && protect)
{
cp_error (errstr, name, type);
+ if (lfi.ambiguous)
+ print_candidates (lfi.ambiguous);
rval = error_mark_node;
}
- /* Do implicit typename stuff. */
- if (rval && TREE_CODE (rval) == TYPE_DECL
- && ! DECL_ARTIFICIAL (rval)
- && processing_template_decl
- && ! currently_open_class (BINFO_TYPE (rval_binfo))
- && uses_template_parms (type))
- {
- binfo = rval_binfo;
- for (; ; binfo = BINFO_INHERITANCE_CHAIN (binfo))
- if (BINFO_INHERITANCE_CHAIN (binfo) == NULL_TREE
- || (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo))
- == current_class_type))
- break;
+ /* If the thing we found was found via the implicit typename
+ extension, build the typename type. */
+ if (rval && lfi.from_dep_base_p && !DECL_CLASS_TEMPLATE_P (rval))
+ rval = TYPE_STUB_DECL (build_typename_type (BINFO_TYPE (basetype_path),
+ name, name,
+ TREE_TYPE (rval)));
- entry = make_typename_type (BINFO_TYPE (binfo), name);
- TREE_TYPE (entry) = TREE_TYPE (rval);
- rval = TYPE_MAIN_DECL (entry);
+ if (rval && is_overloaded_fn (rval))
+ {
+ rval = scratch_tree_cons (basetype_path, rval, NULL_TREE);
+ SET_BASELINK_P (rval);
}
return rval;
}
-/* Try to find NAME inside a nested class. */
+/* Like lookup_member, except that if we find a function member we
+ return NULL_TREE. */
tree
-lookup_nested_field (name, complain)
- tree name;
- int complain;
+lookup_field (xbasetype, name, protect, want_type)
+ register tree xbasetype, name;
+ int protect, want_type;
{
- register tree t;
+ tree rval = lookup_member (xbasetype, name, protect, want_type);
+
+ /* Ignore functions. */
+ if (rval && TREE_CODE (rval) == TREE_LIST)
+ return NULL_TREE;
- tree id = NULL_TREE;
- if (TYPE_MAIN_DECL (current_class_type))
- {
- /* Climb our way up the nested ladder, seeing if we're trying to
- modify a field in an enclosing class. If so, we should only
- be able to modify if it's static. */
- for (t = TYPE_MAIN_DECL (current_class_type);
- t && DECL_CONTEXT (t);
- t = TYPE_MAIN_DECL (DECL_CONTEXT (t)))
- {
- if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE)
- break;
+ return rval;
+}
- /* N.B.: lookup_field will do the access checking for us */
- id = lookup_field (DECL_CONTEXT (t), name, complain, 0);
- if (id == error_mark_node)
- {
- id = NULL_TREE;
- continue;
- }
+/* Like lookup_member, except that if we find a non-function member we
+ return NULL_TREE. */
- if (id != NULL_TREE)
- {
- if (TREE_CODE (id) == FIELD_DECL
- && ! TREE_STATIC (id)
- && TREE_TYPE (id) != error_mark_node)
- {
- if (complain)
- {
- /* At parse time, we don't want to give this error, since
- we won't have enough state to make this kind of
- decision properly. But there are times (e.g., with
- enums in nested classes) when we do need to call
- this fn at parse time. So, in those cases, we pass
- complain as a 0 and just return a NULL_TREE. */
- cp_error ("assignment to non-static member `%D' of enclosing class `%T'",
- id, DECL_CONTEXT (t));
- /* Mark this for do_identifier(). It would otherwise
- claim that the variable was undeclared. */
- TREE_TYPE (id) = error_mark_node;
- }
- else
- {
- id = NULL_TREE;
- continue;
- }
- }
- break;
- }
- }
- }
+tree
+lookup_fnfields (xbasetype, name, protect)
+ register tree xbasetype, name;
+ int protect;
+{
+ tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
+
+ /* Ignore non-functions. */
+ if (rval && TREE_CODE (rval) != TREE_LIST)
+ return NULL_TREE;
- return id;
+ return rval;
}
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 is no such field exists. */
-static int
+int
lookup_fnfields_1 (type, name)
tree type, name;
{
- register tree method_vec = CLASSTYPE_METHOD_VEC (type);
+ register tree method_vec
+ = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE;
if (method_vec != 0)
{
@@ -1651,7 +1522,7 @@ lookup_fnfields_1 (type, name)
if (*++methods && name == dtor_identifier)
return 1;
- while (++methods != end)
+ while (++methods != end && *methods)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
@@ -1663,498 +1534,251 @@ lookup_fnfields_1 (type, name)
/* If we didn't find it, it might have been a template
conversion operator. (Note that we don't look for this case
above so that we will always find specializations first.) */
- if (methods == end
+ if ((methods == end || !*methods)
&& IDENTIFIER_TYPENAME_P (name))
{
methods = &TREE_VEC_ELT (method_vec, 0) + 1;
- while (++methods != end)
+ while (++methods != end && *methods)
{
- if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL
- && IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (*methods))))
+ tree method_name = DECL_NAME (OVL_CURRENT (*methods));
+
+ if (!IDENTIFIER_TYPENAME_P (method_name))
+ {
+ /* Since all conversion operators come first, we know
+ there is no such operator. */
+ methods = end;
+ break;
+ }
+ else if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL)
break;
}
}
- if (methods != end)
+ if (methods != end && *methods)
return methods - &TREE_VEC_ELT (method_vec, 0);
}
return -1;
}
+
+/* Walk the class hierarchy dominated by TYPE. FN is called for each
+ type in the hierarchy, in a breadth-first preorder traversal. .
+ If it ever returns a non-NULL value, that value is immediately
+ returned and the walk is terminated. At each node FN, is passed a
+ BINFO indicating the path from the curently visited base-class to
+ TYPE. The TREE_CHAINs of the BINFOs may be used for scratch space;
+ they are otherwise unused. Before each base-class is walked QFN is
+ called. If the value returned is non-zero, the base-class is
+ walked; otherwise it is not. If QFN is NULL, it is treated as a
+ function which always returns 1. Both FN and QFN are passed the
+ DATA whenever they are called. */
-/* Starting from BASETYPE, return a TREE_BASELINK-like object
- which gives the following information (in a list):
-
- TREE_TYPE: list of basetypes needed to get to...
- TREE_VALUE: list of all functions in a given type
- which have name NAME.
-
- No access information is computed by this function,
- other then to adorn the list of basetypes with
- TREE_VIA_PUBLIC.
-
- If there are two ways to find a name (two members), if COMPLAIN is
- non-zero, then error_mark_node is returned, and an error message is
- printed, otherwise, just an error_mark_node is returned.
-
- As a special case, is COMPLAIN is -1, we don't complain, and we
- don't return error_mark_node, but rather the complete list of
- virtuals. This is used by get_virtuals_named_this. */
-
-tree
-lookup_fnfields (basetype_path, name, complain)
- tree basetype_path, name;
- int complain;
+static tree
+bfs_walk (binfo, fn, qfn, data)
+ tree binfo;
+ tree (*fn) PROTO((tree, void *));
+ tree (*qfn) PROTO((tree, void *));
+ void *data;
{
- int head = 0, tail = 0;
- tree type, rval, rval_binfo = NULL_TREE, rvals = NULL_TREE;
- tree rval_binfo_h = NULL_TREE, entry, binfo, basetype_chain, binfo_h;
- int find_all = 0;
-
- /* rval_binfo is the binfo associated with the found member, note,
- this can be set with useful information, even when rval is not
- set, because it must deal with ALL members, not just function
- members. It is used for ambiguity checking and the hidden
- checks. Whereas rval is only set if a proper (not hidden)
- function member is found. */
-
- /* rval_binfo_h and binfo_h are binfo values used when we perform the
- hiding checks, as virtual base classes may not be shared. The strategy
- is we always go into the binfo hierarchy owned by TYPE_BINFO of
- virtual base classes, as we cross virtual base class lines. This way
- we know that binfo of a virtual base class will always == itself when
- found along any line. (mrs) */
-
- /* For now, don't try this. */
- int protect = complain;
+ size_t head;
+ size_t tail;
+ tree rval = NULL_TREE;
+ /* An array of the base classes of BINFO. These will be built up in
+ breadth-first order, except where QFN prunes the search. */
+ varray_type bfs_bases;
- char *errstr = 0;
+ /* Start with enough room for ten base classes. That will be enough
+ for most hierarchies. */
+ VARRAY_TREE_INIT (bfs_bases, 10, "search_stack");
- /* Set this to nonzero if we don't know how to compute
- accurate error messages for access control. */
- int idx = MEMOIZED_HASH_FN (name);
+ /* Put the first type into the stack. */
+ VARRAY_TREE (bfs_bases, 0) = binfo;
+ tail = 1;
- if (complain == -1)
+ for (head = 0; head < tail; ++head)
{
- find_all = 1;
- protect = complain = 0;
- }
-
-#if 0
- /* We cannot search for constructor/destructor names like this. */
- /* This can't go here, but where should it go? */
- /* If we are looking for a constructor in a templated type, use the
- unspecialized name, as that is how we store it. */
- if (IDENTIFIER_TEMPLATE (name))
- name = constructor_name (name);
-#endif
+ int i;
+ int n_baselinks;
+ tree binfos;
- binfo = basetype_path;
- binfo_h = binfo;
- type = complete_type (BINFO_TYPE (basetype_path));
+ /* Pull the next type out of the queue. */
+ binfo = VARRAY_TREE (bfs_bases, head);
- /* The memoization code is in need of maintenance. */
- if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
- {
- tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
+ /* If this is the one we're looking for, we're done. */
+ rval = (*fn) (binfo, data);
+ if (rval)
+ break;
- while (tem && TREE_PURPOSE (tem) != name)
- {
- memoized_fields_searched[1]++;
- tem = TREE_CHAIN (tem);
- }
- if (tem)
+ /* Queue up the base types. */
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
+ for (i = 0; i < n_baselinks; i++)
{
- if (protect && TREE_TYPE (tem))
- {
- error (TREE_STRING_POINTER (TREE_TYPE (tem)),
- IDENTIFIER_POINTER (name),
- TYPE_NAME_STRING (DECL_CLASS_CONTEXT (TREE_VALUE (TREE_VALUE (tem)))));
- return error_mark_node;
- }
- if (TREE_VALUE (tem) == NULL_TREE)
- {
- memoized_fast_rejects[1] += 1;
- return NULL_TREE;
- }
- else
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+
+ if (qfn)
+ base_binfo = (*qfn) (base_binfo, data);
+
+ if (base_binfo)
{
- /* Want to return this, but we must make sure
- that access information is consistent. */
- tree baselink = TREE_VALUE (tem);
- tree memoized_basetypes = TREE_PURPOSE (baselink);
- tree these_basetypes = basetype_path;
- while (memoized_basetypes && these_basetypes)
- {
- memoized_fields_searched[1]++;
- if (TREE_VALUE (memoized_basetypes) != these_basetypes)
- break;
- memoized_basetypes = TREE_CHAIN (memoized_basetypes);
- these_basetypes = BINFO_INHERITANCE_CHAIN (these_basetypes);
- }
- /* The following statement is true only when both are NULL. */
- if (memoized_basetypes == these_basetypes)
- {
- memoized_fast_finds[1] += 1;
- return TREE_VALUE (tem);
- }
- /* else, we must re-find this field by hand. */
- baselink = tree_cons (basetype_path, TREE_VALUE (baselink), TREE_CHAIN (baselink));
- return baselink;
+ if (tail == VARRAY_SIZE (bfs_bases))
+ VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
+ VARRAY_TREE (bfs_bases, tail) = base_binfo;
+ ++tail;
}
}
}
-#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields++;
-#endif /* GATHER_STATISTICS */
- if (protect && flag_memoize_lookups && ! toplevel_bindings_p ())
- entry = make_memoized_table_entry (type, name, 1);
- else
- entry = 0;
-
- idx = lookup_fnfields_here (type, name);
- if (idx >= 0 || lookup_field_1 (type, name))
- {
- rval_binfo = basetype_path;
- rval_binfo_h = rval_binfo;
- }
-
- if (idx >= 0)
- {
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
- rvals = my_tree_cons (basetype_path, rval, rvals);
- if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
-
- if (entry)
- {
- TREE_VALUE (entry) = rvals;
- TREE_TYPE (entry) = NULL_TREE;
- }
+ /* Clean up. */
+ VARRAY_FREE (bfs_bases);
- return rvals;
- }
- rval = NULL_TREE;
+ return rval;
+}
- if (name == ctor_identifier || name == dtor_identifier)
- {
- /* Don't allow lookups of constructors and destructors to go
- deeper than the first place we look. */
- if (entry)
- TREE_TYPE (entry) = TREE_VALUE (entry) = NULL_TREE;
+/* Exactly like bfs_walk, except that a depth-first traversal is
+ performed, and PREFN is called in preorder, while POSTFN is called
+ in postorder. */
- return NULL_TREE;
- }
+static tree
+dfs_walk_real (binfo, prefn, postfn, qfn, data)
+ tree binfo;
+ tree (*prefn) PROTO((tree, void *));
+ tree (*postfn) PROTO((tree, void *));
+ tree (*qfn) PROTO((tree, void *));
+ void *data;
+{
+ int i;
+ int n_baselinks;
+ tree binfos;
+ tree rval = NULL_TREE;
- if (basetype_path == TYPE_BINFO (type))
+ /* Call the pre-order walking function. */
+ if (prefn)
{
- basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
- TREE_VIA_PUBLIC (basetype_chain) = 1;
- BINFO_VIA_PUBLIC (basetype_path) = 1;
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
- }
- else
- {
- basetype_chain = build_expr_list (NULL_TREE, basetype_path);
- TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
- TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
- TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
+ rval = (*prefn) (binfo, data);
+ if (rval)
+ return rval;
}
- /* The ambiguity check relies upon breadth first searching. */
-
- search_stack = push_search_level (search_stack, &search_obstack);
- binfo = basetype_path;
- binfo_h = binfo;
-
- while (1)
+ /* Process the basetypes. */
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
+ for (i = 0; i < n_baselinks; i++)
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int idx;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (BINFO_FIELDS_MARKED (base_binfo) == 0)
- {
- tree btypes;
-
- SET_BINFO_FIELDS_MARKED (base_binfo);
- btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain);
- TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo);
- TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
- TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
- if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = my_tree_cons (NULL_TREE,
- TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
- btypes);
- else
- btypes = my_tree_cons (NULL_TREE,
- TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
- btypes);
- obstack_ptr_grow (&search_obstack, btypes);
- tail += 1;
- if (tail >= search_stack->limit)
- my_friendly_abort (99);
- }
- }
-
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetype_chain = search_stack->first[head++];
- binfo_h = TREE_VALUE (basetype_chain);
- basetype_chain = TREE_CHAIN (basetype_chain);
- basetype_path = TREE_VALUE (basetype_chain);
- if (TREE_CHAIN (basetype_chain))
- BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain));
- else
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
-
- binfo = basetype_path;
- type = BINFO_TYPE (binfo);
-
- /* See if we can find NAME in TYPE. If RVAL is nonzero,
- and we do find NAME in TYPE, verify that such a second
- sighting is in fact valid. */
-
- idx = lookup_fnfields_here (type, name);
-
- if (idx >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
- {
- if (rval_binfo && !find_all && hides (rval_binfo_h, binfo_h))
- {
- /* This is ok, the member found is in rval_binfo, not
- here (binfo). */
- }
- else if (rval_binfo==NULL_TREE || find_all || hides (binfo_h, rval_binfo_h))
- {
- /* This is ok, the member found is here (binfo), not in
- rval_binfo. */
- if (idx >= 0)
- {
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
- /* Note, rvals can only be previously set if find_all is
- true. */
- rvals = my_tree_cons (basetype_path, rval, rvals);
- if (TYPE_BINFO_BASETYPES (type)
- && CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
- }
- else
- {
- /* Undo finding it before, as something else hides it. */
- rval = NULL_TREE;
- rvals = NULL_TREE;
- }
- rval_binfo = binfo;
- rval_binfo_h = binfo_h;
- }
- else
- {
- /* This is ambiguous. */
- errstr = "request for method `%D' is ambiguous";
- rvals = error_mark_node;
- break;
- }
- }
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
-
- while (tp < search_tail)
- {
- CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
- tp += 1;
- }
- }
- search_stack = pop_search_level (search_stack);
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+
+ if (qfn)
+ base_binfo = (*qfn) (base_binfo, data);
- if (entry)
- {
- if (errstr)
+ if (base_binfo)
{
- tree error_string = my_build_string (errstr);
- /* Save error message with entry. */
- TREE_TYPE (entry) = error_string;
- }
- else
- {
- /* Mark entry as having no error string. */
- TREE_TYPE (entry) = NULL_TREE;
- TREE_VALUE (entry) = rvals;
+ rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
+ if (rval)
+ return rval;
}
}
- if (errstr && protect)
- {
- cp_error (errstr, name);
- rvals = error_mark_node;
- }
-
- return rvals;
+ /* Call the post-order walking function. */
+ if (postfn)
+ rval = (*postfn) (binfo, data);
+
+ return rval;
}
-/* Look for a field or function named NAME in an inheritance lattice
- dominated by XBASETYPE. PROTECT is zero if we can avoid computing
- access information, otherwise it is 1. WANT_TYPE is 1 when we should
- only return TYPE_DECLs, if no TYPE_DECL can be found return NULL_TREE. */
+/* Exactly like bfs_walk, except that a depth-first post-order traversal is
+ performed. */
tree
-lookup_member (xbasetype, name, protect, want_type)
- tree xbasetype, name;
- int protect, want_type;
+dfs_walk (binfo, fn, qfn, data)
+ tree binfo;
+ tree (*fn) PROTO((tree, void *));
+ tree (*qfn) PROTO((tree, void *));
+ void *data;
{
- tree ret, basetype_path;
-
- if (TREE_CODE (xbasetype) == TREE_VEC)
- basetype_path = xbasetype;
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
- {
- basetype_path = TYPE_BINFO (xbasetype);
- BINFO_VIA_PUBLIC (basetype_path) = 1;
- BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
- }
- else
- my_friendly_abort (97);
-
- ret = lookup_field (basetype_path, name, protect, want_type);
- if (! ret && ! want_type)
- ret = lookup_fnfields (basetype_path, name, protect);
- return ret;
+ return dfs_walk_real (binfo, 0, fn, qfn, data);
}
-
-/* BREADTH-FIRST SEARCH ROUTINES. */
-/* Search a multiple inheritance hierarchy by breadth-first search.
+struct gvnt_info
+{
+ /* The name of the function we are looking for. */
+ tree name;
+ /* The overloaded functions we have found. */
+ tree fields;
+};
- BINFO is an aggregate type, possibly in a multiple-inheritance hierarchy.
- TESTFN is a function, which, if true, means that our condition has been met,
- and its return value should be returned.
- QFN, if non-NULL, is a predicate dictating whether the type should
- even be queued. */
+/* Called from get_virtuals_named_this via bfs_walk. */
-static HOST_WIDE_INT
-breadth_first_search (binfo, testfn, qfn)
+static tree
+get_virtuals_named_this_r (binfo, data)
tree binfo;
- int (*testfn) PROTO((tree, int));
- int (*qfn) PROTO((tree, int));
+ void *data;
{
- int head = 0, tail = 0;
- int rval = 0;
-
- search_stack = push_search_level (search_stack, &search_obstack);
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int i;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
+ struct gvnt_info *gvnti = (struct gvnt_info *) data;
+ tree type = BINFO_TYPE (binfo);
+ int idx;
- if (BINFO_MARKED (base_binfo) == 0
- && (qfn == 0 || (*qfn) (binfo, i)))
- {
- SET_BINFO_MARKED (base_binfo);
- obstack_ptr_grow (&search_obstack, binfo);
- obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) i);
- tail += 2;
- if (tail >= search_stack->limit)
- my_friendly_abort (100);
- }
- }
- /* Process head of queue, if one exists. */
- if (head >= tail)
- {
- rval = 0;
- break;
- }
+ idx = lookup_fnfields_here (BINFO_TYPE (binfo), gvnti->name);
+ if (idx >= 0)
+ gvnti->fields
+ = scratch_tree_cons (binfo,
+ TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type),
+ idx),
+ gvnti->fields);
- binfo = search_stack->first[head++];
- i = (HOST_WIDE_INT) search_stack->first[head++];
- if ((rval = (*testfn) (binfo, i)))
- break;
- binfo = BINFO_BASETYPE (binfo, i);
- }
- {
- tree *tp = search_stack->first;
- tree *search_tail = tp + tail;
- while (tp < search_tail)
- {
- tree binfo = *tp++;
- int i = (HOST_WIDE_INT)(*tp++);
- CLEAR_BINFO_MARKED (BINFO_BASETYPE (binfo, i));
- }
- }
-
- search_stack = pop_search_level (search_stack);
- return rval;
+ return NULL_TREE;
}
-/* Functions to use in breadth first searches. */
-typedef int (*pfi) PROTO((tree, int));
-
-static tree declarator;
+/* Return the virtual functions with the indicated NAME in the type
+ indicated by BINFO. The result is a TREE_LIST whose TREE_PURPOSE
+ indicates the base class from which the TREE_VALUE (an OVERLOAD or
+ just a FUNCTION_DECL) originated. */
static tree
-get_virtuals_named_this (binfo)
+get_virtuals_named_this (binfo, name)
tree binfo;
+ tree name;
{
+ struct gvnt_info gvnti;
tree fields;
- fields = lookup_fnfields (binfo, declarator, -1);
- /* fields cannot be error_mark_node */
+ gvnti.name = name;
+ gvnti.fields = NULL_TREE;
- if (fields == 0)
- return 0;
+ bfs_walk (binfo, get_virtuals_named_this_r, 0, &gvnti);
/* Get to the function decls, and return the first virtual function
with this name, if there is one. */
- while (fields)
+ for (fields = gvnti.fields; fields; fields = next_baselink (fields))
{
tree fndecl;
for (fndecl = TREE_VALUE (fields); fndecl; fndecl = OVL_NEXT (fndecl))
if (DECL_VINDEX (OVL_CURRENT (fndecl)))
return fields;
- fields = next_baselink (fields);
}
return NULL_TREE;
}
static tree
-get_virtual_destructor (binfo, i)
+get_virtual_destructor (binfo, data)
tree binfo;
- int i;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = BINFO_TYPE (binfo);
- if (i >= 0)
- type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
if (TYPE_HAS_DESTRUCTOR (type)
&& DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1)))
return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1);
return 0;
}
-static int
-tree_has_any_destructor_p (binfo, i)
+static tree
+tree_has_any_destructor_p (binfo, data)
tree binfo;
- int i;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = BINFO_TYPE (binfo);
- if (i >= 0)
- type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
- return TYPE_NEEDS_DESTRUCTOR (type);
+ return TYPE_NEEDS_DESTRUCTOR (type) ? binfo : NULL_TREE;
}
/* Returns > 0 if a function with type DRETTYPE overriding a function
@@ -2181,14 +1805,13 @@ covariant_return_p (brettype, drettype)
drettype = TREE_TYPE (drettype);
}
- if (comptypes (brettype, drettype, 1))
+ if (same_type_p (brettype, drettype))
return 0;
if (! (TREE_CODE (brettype) == TREE_CODE (drettype)
&& (TREE_CODE (brettype) == POINTER_TYPE
|| TREE_CODE (brettype) == REFERENCE_TYPE)
- && TYPE_READONLY (brettype) == TYPE_READONLY (drettype)
- && TYPE_VOLATILE (brettype) == TYPE_VOLATILE (drettype)))
+ && TYPE_QUALS (brettype) == TYPE_QUALS (drettype)))
return 0;
if (! can_convert (brettype, drettype))
@@ -2238,30 +1861,19 @@ get_matching_virtual (binfo, fndecl, dtorp)
/* Breadth first search routines start searching basetypes
of TYPE, so we must perform first ply of search here. */
if (dtorp)
- {
- if (tree_has_any_destructor_p (binfo, -1))
- tmp = get_virtual_destructor (binfo, -1);
-
- if (tmp)
- return tmp;
-
- tmp = (tree) breadth_first_search (binfo,
- (pfi) get_virtual_destructor,
- tree_has_any_destructor_p);
- return tmp;
- }
+ return bfs_walk (binfo, get_virtual_destructor,
+ tree_has_any_destructor_p, 0);
else
{
tree drettype, dtypes, btypes, instptr_type;
tree basetype = DECL_CLASS_CONTEXT (fndecl);
tree baselink, best = NULL_TREE;
tree name = DECL_ASSEMBLER_NAME (fndecl);
-
- declarator = DECL_NAME (fndecl);
+ tree declarator = DECL_NAME (fndecl);
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
return NULL_TREE;
- baselink = get_virtuals_named_this (binfo);
+ baselink = get_virtuals_named_this (binfo, declarator);
if (baselink == NULL_TREE)
return NULL_TREE;
@@ -2284,18 +1896,22 @@ get_matching_virtual (binfo, fndecl, dtorp)
btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp));
if (instptr_type == NULL_TREE)
{
- if (compparms (TREE_CHAIN (btypes), dtypes, 3))
+ if (compparms (TREE_CHAIN (btypes), dtypes))
/* Caller knows to give error in this case. */
return tmp;
return NULL_TREE;
}
- if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes)))
- == TYPE_READONLY (instptr_type))
- && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
+ if (/* The first parameter is the `this' parameter,
+ which has POINTER_TYPE, and we can therefore
+ safely use TYPE_QUALS, rather than
+ CP_TYPE_QUALS. */
+ (TYPE_QUALS (TREE_TYPE (TREE_VALUE (btypes)))
+ == TYPE_QUALS (instptr_type))
+ && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
{
tree brettype = TREE_TYPE (TREE_TYPE (tmp));
- if (comptypes (brettype, drettype, 1))
+ if (same_type_p (brettype, drettype))
/* OK */;
else if ((i = covariant_return_p (brettype, drettype)))
{
@@ -2309,7 +1925,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
}
}
else if (IS_AGGR_TYPE_2 (brettype, drettype)
- && comptypes (brettype, drettype, 0))
+ && same_or_base_type_p (brettype, drettype))
{
error ("invalid covariant return type (must use pointer or reference)");
cp_error_at (" overriding `%#D'", tmp);
@@ -2321,15 +1937,15 @@ get_matching_virtual (binfo, fndecl, dtorp)
cp_error_at (" overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
- break;
+
+ /* FNDECL overrides this function. We continue to
+ check all the other functions in order to catch
+ errors; it might be that in some other baseclass
+ a virtual function was declared with the same
+ parameter types, but a different return type. */
+ best = tmp;
}
}
- /* If not at the end */
- if (tmps)
- {
- best = tmp;
- break;
- }
}
return best;
@@ -2364,7 +1980,7 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
{
tree virtuals = BINFO_VIRTUALS (binfo);
- skip_rtti_stuff (&virtuals);
+ skip_rtti_stuff (&virtuals, BINFO_TYPE (binfo));
while (virtuals)
{
@@ -2387,7 +2003,7 @@ get_abstract_virtuals (type)
tree type;
{
tree vbases;
- tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
+ tree abstract_virtuals = NULL;
/* First get all from non-virtual bases. */
abstract_virtuals
@@ -2397,13 +2013,15 @@ get_abstract_virtuals (type)
{
tree virtuals = BINFO_VIRTUALS (vbases);
- skip_rtti_stuff (&virtuals);
+ skip_rtti_stuff (&virtuals, type);
while (virtuals)
{
tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
tree base_fndecl = TREE_OPERAND (base_pfn, 0);
- if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
+ if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
+ cp_error ("`%#D' needs a final overrider", base_fndecl);
+ else if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
virtuals = TREE_CHAIN (virtuals);
}
@@ -2411,77 +2029,7 @@ get_abstract_virtuals (type)
return nreverse (abstract_virtuals);
}
-/* For the type TYPE, return a list of member functions available from
- base classes with name NAME. The TREE_VALUE of the list is a chain of
- member functions with name NAME. The TREE_PURPOSE of the list is a
- basetype, or a list of base types (in reverse order) which were
- traversed to reach the chain of member functions. If we reach a base
- type which provides a member function of name NAME, and which has at
- most one base type itself, then we can terminate the search. */
-
-tree
-get_baselinks (type_as_binfo_list, type, name)
- tree type_as_binfo_list;
- tree type, name;
-{
- int head = 0, tail = 0, idx;
- tree rval = 0, nval = 0;
- tree basetypes = type_as_binfo_list;
- tree binfo = TYPE_BINFO (type);
-
- search_stack = push_search_level (search_stack, &search_obstack);
-
- while (1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Process and/or queue base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree btypes;
-
- btypes = hash_tree_cons (TREE_VIA_PUBLIC (base_binfo),
- TREE_VIA_VIRTUAL (base_binfo),
- TREE_VIA_PROTECTED (base_binfo),
- NULL_TREE, base_binfo,
- basetypes);
- obstack_ptr_grow (&search_obstack, btypes);
- search_stack->first = (tree *)obstack_base (&search_obstack);
- tail += 1;
- }
-
- dont_queue:
- /* Process head of queue, if one exists. */
- if (head >= tail)
- break;
-
- basetypes = search_stack->first[head++];
- binfo = TREE_VALUE (basetypes);
- type = BINFO_TYPE (binfo);
- idx = lookup_fnfields_1 (type, name);
- if (idx >= 0)
- {
- nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
- rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval);
- if (TYPE_BINFO_BASETYPES (type) == 0)
- goto dont_queue;
- else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1)
- {
- if (CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
- goto dont_queue;
- }
- }
- nval = NULL_TREE;
- }
-
- search_stack = pop_search_level (search_stack);
- return rval;
-}
-
-tree
+static tree
next_baselink (baselink)
tree baselink;
{
@@ -2500,33 +2048,6 @@ next_baselink (baselink)
/* DEPTH-FIRST SEARCH ROUTINES. */
-#ifdef MI_MATRIX
-/* Assign unique numbers to _CLASSTYPE members of the lattice
- specified by TYPE. The root nodes are marked first; the nodes
- are marked depth-fisrt, left-right. */
-
-static int cid;
-
-/* Matrix implementing a relation from CLASSTYPE X CLASSTYPE => INT.
- Relation yields 1 if C1 <= C2, 0 otherwise. */
-typedef char mi_boolean;
-static mi_boolean *mi_matrix;
-
-/* Type for which this matrix is defined. */
-static tree mi_type;
-
-/* Size of the matrix for indexing purposes. */
-static int mi_size;
-
-/* Return nonzero if class C2 derives from class C1. */
-#define BINFO_DERIVES_FROM(C1, C2) \
- ((mi_matrix+mi_size*(BINFO_CID (C1)-1))[BINFO_CID (C2)-1])
-#define TYPE_DERIVES_FROM(C1, C2) \
- ((mi_matrix+mi_size*(CLASSTYPE_CID (C1)-1))[CLASSTYPE_CID (C2)-1])
-#define BINFO_DERIVES_FROM_STAR(C) \
- (mi_matrix+(BINFO_CID (C)-1))
-#endif
-
/* This routine converts a pointer to be a pointer of an immediate
base class. The normal convert_pointer_to routine would diagnose
the conversion as ambiguous, under MI code that has the base class
@@ -2536,163 +2057,128 @@ static tree
convert_pointer_to_single_level (to_type, expr)
tree to_type, expr;
{
+ tree derived;
tree binfo_of_derived;
- tree last;
-
- binfo_of_derived = TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr)));
- last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0);
- BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived;
- BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE;
- return build_vbase_path (PLUS_EXPR, build_pointer_type (to_type), expr, last, 1);
-}
-
-/* The main function which implements depth first search.
-
- This routine has to remember the path it walked up, when
- dfs_init_vbase_pointers is the work function, as otherwise there
- would be no record. */
-
-static void
-dfs_walk (binfo, fn, qfn)
- tree binfo;
- void (*fn) PROTO((tree));
- int (*qfn) PROTO((tree));
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ int i;
- for (i = 0; i < n_baselinks; i++)
+ derived = TREE_TYPE (TREE_TYPE (expr));
+ binfo_of_derived = TYPE_BINFO (derived);
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (binfo_of_derived) == NULL_TREE,
+ 980827);
+ for (i = CLASSTYPE_N_BASECLASSES (derived) - 1; i >= 0; --i)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (qfn == 0 || (*qfn)(base_binfo))
- {
- if (TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TYPE_PARM
- || TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TEMPLATE_PARM)
- /* Pass */;
- else if (fn == dfs_init_vbase_pointers)
- {
- /* When traversing an arbitrary MI hierarchy, we need to keep
- a record of the path we took to get down to the final base
- type, as otherwise there would be no record of it, and just
- trying to blindly convert at the bottom would be ambiguous.
-
- The easiest way is to do the conversions one step at a time,
- as we know we want the immediate base class at each step.
+ tree binfo = BINFO_BASETYPE (binfo_of_derived, i);
+ my_friendly_assert (BINFO_INHERITANCE_CHAIN (binfo) == binfo_of_derived,
+ 980827);
+ if (same_type_p (BINFO_TYPE (binfo), to_type))
+ return build_vbase_path (PLUS_EXPR,
+ build_pointer_type (to_type),
+ expr, binfo, 1);
+ }
- The only special trick to converting one step at a time,
- is that when we hit the last virtual base class, we must
- use the SLOT value for it, and not use the normal convert
- routine. We use the last virtual base class, as in our
- implementation, we have pointers to all virtual base
- classes in the base object. */
+ my_friendly_abort (19990607);
- tree saved_vbase_decl_ptr_intermediate
- = vbase_decl_ptr_intermediate;
+ /* NOTREACHED */
+ return NULL_TREE;
+}
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- /* No need for the conversion here, as we know it is the
- right type. */
- vbase_decl_ptr_intermediate
- = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
- }
- else
- {
- vbase_decl_ptr_intermediate
- = convert_pointer_to_single_level (BINFO_TYPE (base_binfo),
- vbase_decl_ptr_intermediate);
- }
+tree markedp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return BINFO_MARKED (binfo) ? binfo : NULL_TREE;
+}
- dfs_walk (base_binfo, fn, qfn);
+static tree
+unmarkedp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
+}
- vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
- }
- else
- dfs_walk (base_binfo, fn, qfn);
- }
- }
+static tree
+marked_vtable_pathp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
+}
- fn (binfo);
+static tree
+unmarked_vtable_pathp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return !BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
}
-#ifdef MI_MATRIX
-/* Predicate functions which serve for dfs_walk. */
-static int numberedp (binfo) tree binfo;
-{ return BINFO_CID (binfo); }
-static int unnumberedp (binfo) tree binfo;
-{ return BINFO_CID (binfo) == 0; }
-#endif
+static tree
+marked_new_vtablep (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
+}
-static int markedp (binfo) tree binfo;
-{ return BINFO_MARKED (binfo); }
-static int unmarkedp (binfo) tree binfo;
-{ return BINFO_MARKED (binfo) == 0; }
+static tree
+unmarked_new_vtablep (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return !BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
+}
-#if 0
-static int bfs_markedp (binfo, i) tree binfo; int i;
-{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int bfs_unmarkedp (binfo, i) tree binfo; int i;
-{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
-{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
-{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
-{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
-{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-#endif
+static tree
+marked_pushdecls_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (CLASS_TYPE_P (BINFO_TYPE (binfo))
+ && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
+}
-static int marked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo); }
-static int unmarked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
-static int marked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo); }
-static int unmarked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
+static tree
+unmarked_pushdecls_p (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (CLASS_TYPE_P (BINFO_TYPE (binfo))
+ && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
+}
#if 0
static int dfs_search_slot_nonempty_p (binfo) tree binfo;
{ return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
#endif
-static int dfs_debug_unmarkedp (binfo) tree binfo;
-{ return CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) == 0; }
+static tree
+dfs_debug_unmarkedp (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo))
+ ? binfo : NULL_TREE);
+}
/* The worker functions for `dfs_walk'. These do not need to
test anything (vis a vis marking) if they are paired with
a predicate function (above). */
-#ifdef MI_MATRIX
-/* Assign each type within the lattice a number which is unique
- in the lattice. The first number assigned is 1. */
-
-static void
-dfs_number (binfo)
- tree binfo;
-{
- BINFO_CID (binfo) = ++cid;
-}
-
-static void
-dfs_unnumber (binfo)
- tree binfo;
-{
- BINFO_CID (binfo) = 0;
-}
-#endif
-
#if 0
static void
dfs_mark (binfo) tree binfo;
{ SET_BINFO_MARKED (binfo); }
#endif
-static void
-dfs_unmark (binfo) tree binfo;
-{ CLEAR_BINFO_MARKED (binfo); }
+tree
+dfs_unmark (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ CLEAR_BINFO_MARKED (binfo);
+ return NULL_TREE;
+}
#if 0
static void
@@ -2716,9 +2202,10 @@ dfs_clear_search_slot (binfo) tree binfo;
{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
#endif
-static void
-dfs_debug_mark (binfo)
+static tree
+dfs_debug_mark (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
tree t = BINFO_TYPE (binfo);
@@ -2729,13 +2216,12 @@ dfs_debug_mark (binfo)
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
if (methods == 0)
- return;
+ return NULL_TREE;
/* If interface info is known, either we've already emitted the debug
info or we don't need to. */
- if (CLASSTYPE_INTERFACE_KNOWN (t)
- || (write_virtuals == 2 && TYPE_VIRTUAL_P (t)))
- return;
+ if (CLASSTYPE_INTERFACE_KNOWN (t))
+ return NULL_TREE;
/* If debug info is requested from this context for this type, supply it.
If debug info is requested from another context for this type,
@@ -2759,7 +2245,7 @@ dfs_debug_mark (binfo)
/* Somebody, somewhere is going to have to define this
virtual function. When they do, they will provide
the debugging info. */
- return;
+ return NULL_TREE;
}
methods = TREE_CHAIN (methods);
}
@@ -2768,17 +2254,26 @@ dfs_debug_mark (binfo)
so we must write out the debug info ourselves. */
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
rest_of_type_compilation (t, toplevel_bindings_p ());
+
+ return NULL_TREE;
}
-/* Attach to the type of the virtual base class, the pointer to the
- virtual base class, given the global pointer vbase_decl_ptr.
+struct vbase_info
+{
+ tree decl_ptr;
+ tree inits;
+ tree vbase_types;
+};
- We use the global vbase_types. ICK! */
+/* Attach to the type of the virtual base class, the pointer to the
+ virtual base class. */
-static void
-dfs_find_vbases (binfo)
+static tree
+dfs_find_vbases (binfo, data)
tree binfo;
+ void *data;
{
+ struct vbase_info *vi = (struct vbase_info *) data;
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2790,21 +2285,25 @@ dfs_find_vbases (binfo)
&& CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo)) == 0)
{
tree vbase = BINFO_TYPE (base_binfo);
- tree binfo = binfo_member (vbase, vbase_types);
+ tree binfo = binfo_member (vbase, vi->vbase_types);
CLASSTYPE_SEARCH_SLOT (vbase)
= build (PLUS_EXPR, build_pointer_type (vbase),
- vbase_decl_ptr, BINFO_OFFSET (binfo));
+ vi->decl_ptr, BINFO_OFFSET (binfo));
}
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo);
+
+ return NULL_TREE;
}
-static void
-dfs_init_vbase_pointers (binfo)
+static tree
+dfs_init_vbase_pointers (binfo, data)
tree binfo;
+ void *data;
{
+ struct vbase_info *vi = (struct vbase_info *) data;
tree type = BINFO_TYPE (binfo);
tree fields = TYPE_FIELDS (type);
tree this_vbase_ptr;
@@ -2818,42 +2317,57 @@ dfs_init_vbase_pointers (binfo)
fields = TREE_CHAIN (fields);
#endif
+ if (BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ this_vbase_ptr = TREE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo));
+ if (TREE_VIA_VIRTUAL (binfo))
+ this_vbase_ptr = CLASSTYPE_SEARCH_SLOT (type);
+ else
+ this_vbase_ptr = convert_pointer_to_single_level (type,
+ this_vbase_ptr);
+ TREE_CHAIN (binfo) = this_vbase_ptr;
+ }
+ else
+ this_vbase_ptr = TREE_CHAIN (binfo);
+
if (fields == NULL_TREE
|| DECL_NAME (fields) == NULL_TREE
|| ! VBASE_NAME_P (DECL_NAME (fields)))
- return;
-
- this_vbase_ptr = vbase_decl_ptr_intermediate;
+ return NULL_TREE;
- if (build_pointer_type (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
+ if (build_pointer_type (type)
+ != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
my_friendly_abort (125);
- while (fields && DECL_NAME (fields)
- && VBASE_NAME_P (DECL_NAME (fields)))
+ while (fields && DECL_NAME (fields) && VBASE_NAME_P (DECL_NAME (fields)))
{
tree ref = build (COMPONENT_REF, TREE_TYPE (fields),
build_indirect_ref (this_vbase_ptr, NULL_PTR), fields);
tree init = CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
- vbase_init_result = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
- vbase_types),
- build_modify_expr (ref, NOP_EXPR, init),
- vbase_init_result);
+ vi->inits = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
+ vi->vbase_types),
+ build_modify_expr (ref, NOP_EXPR, init),
+ vi->inits);
fields = TREE_CHAIN (fields);
}
+
+ return NULL_TREE;
}
/* Sometimes this needs to clear both VTABLE_PATH and NEW_VTABLE. Other
times, just NEW_VTABLE, but optimizer should make both with equal
efficiency (though it does not currently). */
-static void
-dfs_clear_vbase_slots (binfo)
+static tree
+dfs_clear_vbase_slots (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = BINFO_TYPE (binfo);
CLASSTYPE_SEARCH_SLOT (type) = 0;
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
+ return NULL_TREE;
}
tree
@@ -2863,17 +2377,29 @@ init_vbase_pointers (type, decl_ptr)
{
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
+ struct vbase_info vi;
int old_flag = flag_this_is_variable;
tree binfo = TYPE_BINFO (type);
flag_this_is_variable = -2;
- vbase_types = CLASSTYPE_VBASECLASSES (type);
- vbase_decl_ptr = vbase_decl_ptr_intermediate = decl_ptr;
- vbase_init_result = NULL_TREE;
- dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp);
- dfs_walk (binfo, dfs_init_vbase_pointers, marked_vtable_pathp);
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
+
+ /* Find all the virtual base classes, marking them for later
+ initialization. */
+ vi.decl_ptr = decl_ptr;
+ vi.vbase_types = CLASSTYPE_VBASECLASSES (type);
+ vi.inits = NULL_TREE;
+
+ dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp, &vi);
+
+ /* Build up a list of the initializers. */
+ TREE_CHAIN (binfo) = decl_ptr;
+ dfs_walk_real (binfo,
+ dfs_init_vbase_pointers, 0,
+ marked_vtable_pathp,
+ &vi);
+
+ dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
flag_this_is_variable = old_flag;
- return vbase_init_result;
+ return vi.inits;
}
return 0;
}
@@ -2962,7 +2488,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
*vbase_offsets = delta;
}
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, t);
while (virtuals)
{
@@ -2987,7 +2513,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
/* Dup it if it isn't in local scope yet. */
nvtbl = build_decl
(VAR_DECL, DECL_NAME (vtbl),
- TYPE_MAIN_VARIANT (TREE_TYPE (BINFO_VTABLE (binfo))));
+ TYPE_MAIN_VARIANT (TREE_TYPE (vtbl)));
DECL_ALIGN (nvtbl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (nvtbl));
TREE_READONLY (nvtbl) = 0;
@@ -3012,8 +2538,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
(build_indirect_ref (addr, NULL_PTR),
DECL_CONTEXT (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))));
expand_expr_stmt
- (build_modify_expr (ref, NOP_EXPR,
- build_unary_op (ADDR_EXPR, nvtbl, 0)));
+ (build_modify_expr (ref, NOP_EXPR, nvtbl));
}
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
@@ -3026,7 +2551,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
/* This is a upcast, so we have to add the offset for the
virtual base. */
old_delta = build_binary_op (PLUS_EXPR, old_delta,
- TREE_VALUE (delta), 0);
+ TREE_VALUE (delta));
if (vc)
{
/* If this is set, we need to subtract out the delta
@@ -3047,10 +2572,14 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
/* This is a downcast, so we have to subtract the offset
for the virtual base. */
- old_delta = build_binary_op (MINUS_EXPR, old_delta, vc_delta, 0);
+ old_delta = build_binary_op (MINUS_EXPR, old_delta, vc_delta);
}
TREE_READONLY (new_delta) = 0;
+ TREE_TYPE (new_delta) =
+ cp_build_qualified_type (TREE_TYPE (new_delta),
+ CP_TYPE_QUALS (TREE_TYPE (new_delta))
+ & ~TYPE_QUAL_CONST);
expand_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
old_delta));
}
@@ -3108,10 +2637,7 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
When USE_COMPUTED_OFFSETS is non-zero, we can assume that the
object was laid out by a top-level constructor and the computed
offsets are valid to store vtables. When zero, we must store new
- vtables through virtual baseclass pointers.
-
- We setup and use the globals: vbase_decl_ptr, vbase_types
- ICK! */
+ vtables through virtual baseclass pointers. */
void
expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
@@ -3120,21 +2646,34 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
{
tree type = BINFO_TYPE (binfo);
+ /* This function executes during the finish_function() segment,
+ AFTER the auto variables and temporary stack space has been marked
+ unused...If space is needed for the virtual function tables,
+ some of them might fit within what the compiler now thinks
+ are available stack slots... These values are actually initialized at
+ the beginnning of the function, so when the automatics use their space,
+ they will overwrite the values that are placed here. Marking all
+ temporary space as unavailable prevents this from happening. */
+
+ mark_all_temps_used();
+
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
rtx fixup_insns = NULL_RTX;
tree vbases = CLASSTYPE_VBASECLASSES (type);
- vbase_types = vbases;
- vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
+ struct vbase_info vi;
+ vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0)
+ : decl_ptr);
+ vi.vbase_types = vbases;
- dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
+ dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
/* Initialized with vtables of type TYPE. */
for (; vbases; vbases = TREE_CHAIN (vbases))
{
tree addr;
- addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
+ addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vi.decl_ptr);
/* Do all vtables from this virtual base. */
/* This assumes that virtual bases can never serve as parent
@@ -3159,7 +2698,7 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
push_to_sequence (fixup_insns);
fixup_virtual_upcast_offsets (vbases,
TYPE_BINFO (BINFO_TYPE (vbases)),
- 1, 0, addr, vbase_decl_ptr,
+ 1, 0, addr, vi.decl_ptr,
type, vbases, &vbase_offsets);
fixup_insns = get_insns ();
end_sequence ();
@@ -3175,13 +2714,13 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
warning ("recoverable internal compiler error, nobody's in charge!");
in_charge_node = integer_zero_node;
}
- in_charge_node = build_binary_op (EQ_EXPR, in_charge_node, integer_zero_node, 1);
+ in_charge_node = build_binary_op (EQ_EXPR, in_charge_node, integer_zero_node);
expand_start_cond (in_charge_node, 0);
emit_insns (fixup_insns);
expand_end_cond ();
}
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
+ dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
}
}
@@ -3189,38 +2728,43 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
This adds type to the vbase_types list in reverse dfs order.
Ordering is very important, so don't change it. */
-static void
-dfs_get_vbase_types (binfo)
+static tree
+dfs_get_vbase_types (binfo, data)
tree binfo;
+ void *data;
{
+ tree *vbase_types = (tree *) data;
+
if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
{
- vbase_types = make_binfo (integer_zero_node, binfo,
- BINFO_VTABLE (binfo),
- BINFO_VIRTUALS (binfo), vbase_types);
- TREE_VIA_VIRTUAL (vbase_types) = 1;
+ tree new_vbase = make_binfo (integer_zero_node, binfo,
+ BINFO_VTABLE (binfo),
+ BINFO_VIRTUALS (binfo));
+ TREE_CHAIN (new_vbase) = *vbase_types;
+ TREE_VIA_VIRTUAL (new_vbase) = 1;
+ *vbase_types = new_vbase;
SET_BINFO_VBASE_MARKED (binfo);
}
SET_BINFO_MARKED (binfo);
+ return NULL_TREE;
}
-/* get a list of virtual base classes in dfs order. */
+/* Return a list of binfos for the virtual base classes for TYPE, in
+ depth-first search order. The list is freshly allocated, so
+ no modification is made to the current binfo hierarchy. */
tree
get_vbase_types (type)
tree type;
{
+ tree vbase_types;
tree vbases;
tree binfo;
- if (TREE_CODE (type) == TREE_VEC)
- binfo = type;
- else
- binfo = TYPE_BINFO (type);
-
+ binfo = TYPE_BINFO (type);
vbase_types = NULL_TREE;
- dfs_walk (binfo, dfs_get_vbase_types, unmarkedp);
- dfs_walk (binfo, dfs_unmark, markedp);
+ dfs_walk (binfo, dfs_get_vbase_types, unmarkedp, &vbase_types);
+ dfs_walk (binfo, dfs_unmark, markedp, 0);
/* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
reverse it so that we get normal dfs ordering. */
vbase_types = nreverse (vbase_types);
@@ -3232,95 +2776,6 @@ get_vbase_types (type)
return vbase_types;
}
-#ifdef MI_MATRIX
-static void
-dfs_record_inheritance (binfo)
- tree binfo;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- mi_boolean *derived_row = BINFO_DERIVES_FROM_STAR (binfo);
-
- for (i = n_baselinks-1; i >= 0; i--)
- {
- int j;
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree baseclass = BINFO_TYPE (base_binfo);
- mi_boolean *base_row = BINFO_DERIVES_FROM_STAR (base_binfo);
-
- if (TREE_CODE (baseclass) == TEMPLATE_TYPE_PARM
- || TREE_CODE (baseclass) == TEMPLATE_TEMPLATE_PARM)
- continue;
- my_friendly_assert (CLASSTYPE_CID (baseclass) != 0, 2365);
-
- /* Don't search if there's nothing there! MI_SIZE can be
- zero as a result of parse errors. */
- if (TYPE_BINFO_BASETYPES (baseclass) && mi_size > 0)
- for (j = mi_size*(CLASSTYPE_CID (baseclass)-1); j >= 0; j -= mi_size)
- derived_row[j] |= base_row[j];
- TYPE_DERIVES_FROM (baseclass, BINFO_TYPE (binfo)) = 1;
- }
-
- SET_BINFO_MARKED (binfo);
-}
-
-/* Given a _CLASSTYPE node in a multiple inheritance lattice,
- convert the lattice into a simple relation such that,
- given to CIDs, C1 and C2, one can determine if C1 <= C2
- or C2 <= C1 or C1 <> C2.
-
- Once constructed, we walk the lattice depth fisrt,
- applying various functions to elements as they are encountered.
-
- We use xmalloc here, in case we want to randomly free these tables. */
-
-#define SAVE_MI_MATRIX
-
-void
-build_mi_matrix (type)
- tree type;
-{
- tree binfo = TYPE_BINFO (type);
- cid = 0;
-
-#ifdef SAVE_MI_MATRIX
- if (CLASSTYPE_MI_MATRIX (type))
- {
- mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
- mi_matrix = CLASSTYPE_MI_MATRIX (type);
- mi_type = type;
- dfs_walk (binfo, dfs_number, unnumberedp);
- return;
- }
-#endif
-
- dfs_walk (binfo, dfs_number, unnumberedp);
-
- mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
- if (mi_size < (cid-1))
- mi_size = cid-1;
- mi_matrix = (char *)xmalloc ((mi_size + 1) * (mi_size + 1));
- mi_type = type;
- bzero (mi_matrix, (mi_size + 1) * (mi_size + 1));
- dfs_walk (binfo, dfs_record_inheritance, unmarkedp);
- dfs_walk (binfo, dfs_unmark, markedp);
-}
-
-void
-free_mi_matrix ()
-{
- dfs_walk (TYPE_BINFO (mi_type), dfs_unnumber, numberedp);
-
-#ifdef SAVE_MI_MATRIX
- CLASSTYPE_MI_MATRIX (mi_type) = mi_matrix;
-#else
- free (mi_matrix);
- mi_size = 0;
- cid = 0;
-#endif
-}
-#endif
-
/* If we want debug info for a type TYPE, make sure all its base types
are also marked as being potentially interesting. This avoids
the problem of not writing any debug info for intermediate basetypes
@@ -3347,284 +2802,167 @@ note_debug_info_needed (type)
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
return;
- dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
+ dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
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)))
+ && dfs_debug_unmarkedp (TYPE_BINFO (ttype), 0))
note_debug_info_needed (ttype);
}
}
/* Subroutines of push_class_decls (). */
-/* Add in a decl to the envelope. */
+/* Returns 1 iff BINFO is a base we shouldn't really be able to see into,
+ because it (or one of the intermediate bases) depends on template parms. */
+
+static int
+dependent_base_p (binfo)
+ tree binfo;
+{
+ for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ if (currently_open_class (TREE_TYPE (binfo)))
+ break;
+ if (uses_template_parms (TREE_TYPE (binfo)))
+ return 1;
+ }
+ return 0;
+}
+
static void
-envelope_add_decl (type, decl, values)
- tree type, decl, *values;
-{
- tree context, *tmp;
- tree name = DECL_NAME (decl);
- int dont_add = 0;
-
- /* Yet Another Implicit Typename Kludge: Since we don't tsubst
- the members for partial instantiations, DECL_CONTEXT (decl) is wrong.
- But pretend it's right for this function. */
- if (processing_template_decl)
- type = DECL_REAL_CONTEXT (decl);
-
- /* virtual base names are always unique. */
- if (VBASE_NAME_P (name))
- *values = NULL_TREE;
-
- /* Possible ambiguity. If its defining type(s)
- is (are all) derived from us, no problem. */
- else if (*values && TREE_CODE (*values) != TREE_LIST)
- {
- tree value = *values;
- /* Only complain if we shadow something we can access. */
- if (warn_shadow && TREE_CODE (decl) == FUNCTION_DECL
- && ((DECL_LANG_SPECIFIC (*values)
- && DECL_CLASS_CONTEXT (value) == current_class_type)
- || ! TREE_PRIVATE (value)))
- /* Should figure out access control more accurately. */
- {
- cp_warning_at ("member `%#D' is shadowed", value);
- cp_warning_at ("by member function `%#D'", decl);
- warning ("in this context");
- }
+setup_class_bindings (name, type_binding_p)
+ tree name;
+ int type_binding_p;
+{
+ tree type_binding = NULL_TREE;
+ tree value_binding;
- context = DECL_REAL_CONTEXT (value);
+ /* If we've already done the lookup for this declaration, we're
+ done. */
+ if (IDENTIFIER_CLASS_VALUE (name))
+ return;
- if (context == type)
- {
- if (TREE_CODE (value) == TYPE_DECL
- && DECL_ARTIFICIAL (value))
- *values = NULL_TREE;
- else
- dont_add = 1;
- }
- else if (type == current_class_type
-#ifdef MI_MATRIX
- /* If we don't check CLASSTYPE_CID on CONTEXT right now,
- we'll end up subtracting from the address of MI_MATRIX,
- putting us off in la la land. */
- || (CLASSTYPE_CID (type)
- && TYPE_DERIVES_FROM (context, type))
-#else
- || DERIVED_FROM_P (context, type)
-#endif
- )
- {
- /* Don't add in *values to list */
- *values = NULL_TREE;
- }
+ /* First, deal with the type binding. */
+ if (type_binding_p)
+ {
+ type_binding = lookup_member (current_class_type, name,
+ /*protect=*/2,
+ /*want_type=*/1);
+ if (TREE_CODE (type_binding) == TREE_LIST
+ && TREE_TYPE (type_binding) == error_mark_node)
+ /* NAME is ambiguous. */
+ push_class_level_binding (name, type_binding);
else
- *values = build_tree_list (NULL_TREE, value);
- }
+ pushdecl_class_level (type_binding);
+ }
+
+ /* Now, do the value binding. */
+ value_binding = lookup_member (current_class_type, name,
+ /*protect=*/2,
+ /*want_type=*/0);
+
+ if (type_binding_p
+ && (TREE_CODE (value_binding) == TYPE_DECL
+ || (TREE_CODE (value_binding) == TREE_LIST
+ && TREE_TYPE (value_binding) == error_mark_node
+ && (TREE_CODE (TREE_VALUE (value_binding))
+ == TYPE_DECL))))
+ /* We found a type-binding, even when looking for a non-type
+ binding. This means that we already processed this binding
+ above. */
+ my_friendly_assert (type_binding_p, 19990401);
else
- for (tmp = values; *tmp;)
- {
- tree value = TREE_VALUE (*tmp);
- my_friendly_assert (TREE_CODE (value) != TREE_LIST, 999);
- context = (TREE_CODE (value) == FUNCTION_DECL
- && DECL_VIRTUAL_P (value))
- ? DECL_CLASS_CONTEXT (value)
- : DECL_CONTEXT (value);
-
- if (type == current_class_type
-#ifdef MI_MATRIX
- /* If we don't check CLASSTYPE_CID on CONTEXT right now,
- we'll end up subtracting from the address of MI_MATRIX,
- putting us off in la la land. */
- || (CLASSTYPE_CID (type)
- && TYPE_DERIVES_FROM (context, type))
-#else
- || DERIVED_FROM_P (context, type)
-#endif
- )
- {
- /* remove *tmp from list */
- *tmp = TREE_CHAIN (*tmp);
- }
- else
- tmp = &TREE_CHAIN (*tmp);
- }
-
- if (! dont_add)
- {
- /* Put the new contents in our envelope. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- *values = tree_cons (name, decl, *values);
- TREE_NONLOCAL_FLAG (*values) = 1;
- TREE_TYPE (*values) = unknown_type_node;
- }
+ {
+ if (TREE_CODE (value_binding) == TREE_LIST
+ && TREE_TYPE (value_binding) == error_mark_node)
+ /* NAME is ambiguous. */
+ push_class_level_binding (name, value_binding);
else
{
- if (*values)
- {
- *values = tree_cons (NULL_TREE, decl, *values);
- /* Mark this as a potentially ambiguous member. */
- /* Leaving TREE_TYPE blank is intentional.
- We cannot use `error_mark_node' (lookup_name)
- or `unknown_type_node' (all member functions use this). */
- TREE_NONLOCAL_FLAG (*values) = 1;
- }
- else
- *values = decl;
+ if (BASELINK_P (value_binding))
+ /* NAME is some overloaded functions. */
+ value_binding = TREE_VALUE (value_binding);
+ pushdecl_class_level (value_binding);
}
}
}
-/* Add the instance variables which this class contributed to the
- current class binding contour. When a redefinition occurs, if the
- redefinition is strictly within a single inheritance path, we just
- overwrite the old declaration with the new. If the fields are not
- within a single inheritance path, we must cons them.
+/* Push class-level declarations for any names appearing in BINFO that
+ are TYPE_DECLS. */
- In order to know what decls are new (stemming from the current
- invocation of push_class_decls) we enclose them in an "envelope",
- which is a TREE_LIST node where the TREE_PURPOSE slot contains the
- new decl (or possibly a list of competing ones), the TREE_VALUE slot
- points to the old value and the TREE_CHAIN slot chains together all
- envelopes which needs to be "opened" in push_class_decls. Opening an
- envelope means: push the old value onto the class_shadowed list,
- install the new one and if it's a TYPE_DECL do the same to the
- IDENTIFIER_TYPE_VALUE. Such an envelope is recognized by seeing that
- the TREE_PURPOSE slot is non-null, and that it is not an identifier.
- Because if it is, it could be a set of overloaded methods from an
- outer scope. */
-
-static void
-dfs_pushdecls (binfo)
+static tree
+dfs_push_type_decls (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
- tree type = BINFO_TYPE (binfo);
- tree fields, *methods, *end;
- tree method_vec;
+ tree type;
+ tree fields;
+ type = BINFO_TYPE (binfo);
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- {
- /* Unmark so that if we are in a constructor, and then find that
- this field was initialized by a base initializer,
- we can emit an error message. */
- if (TREE_CODE (fields) == FIELD_DECL)
- TREE_USED (fields) = 0;
+ if (DECL_NAME (fields) && TREE_CODE (fields) == TYPE_DECL
+ && !(!same_type_p (type, current_class_type)
+ && template_self_reference_p (type, fields)))
+ setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/1);
- /* Recurse into anonymous unions. */
- if (DECL_NAME (fields) == NULL_TREE
- && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
- {
- dfs_pushdecls (TYPE_BINFO (TREE_TYPE (fields)));
- continue;
- }
-
- if (DECL_NAME (fields))
- {
- tree name = DECL_NAME (fields);
- tree class_value = IDENTIFIER_CLASS_VALUE (name);
-
- /* If the class value is not an envelope of the kind described in
- the comment above, we create a new envelope. */
- if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
- || TREE_PURPOSE (class_value) == NULL_TREE
- || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
- {
- /* See comment above for a description of envelopes. */
- closed_envelopes = tree_cons (NULL_TREE, class_value,
- closed_envelopes);
- IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
- class_value = IDENTIFIER_CLASS_VALUE (name);
- }
-
- envelope_add_decl (type, fields, &TREE_PURPOSE (class_value));
- }
- }
-
- method_vec = CLASSTYPE_METHOD_VEC (type);
- if (method_vec)
- {
- /* Farm out constructors and destructors. */
- methods = &TREE_VEC_ELT (method_vec, 2);
- end = TREE_VEC_END (method_vec);
-
- while (methods != end)
- {
- /* This will cause lookup_name to return a pointer
- to the tree_list of possible methods of this name. */
- tree name = DECL_NAME (OVL_CURRENT (*methods));
- tree class_value = IDENTIFIER_CLASS_VALUE (name);
-
- /* If the class value is not an envelope of the kind described in
- the comment above, we create a new envelope. */
- if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
- || TREE_PURPOSE (class_value) == NULL_TREE
- || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
- {
- /* See comment above for a description of envelopes. */
- closed_envelopes = tree_cons (NULL_TREE, class_value,
- closed_envelopes);
- IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
- class_value = IDENTIFIER_CLASS_VALUE (name);
- }
+ /* We can't just use BINFO_MARKED because envelope_add_decl uses
+ DERIVED_FROM_P, which calls get_base_distance. */
+ SET_BINFO_PUSHDECLS_MARKED (binfo);
- /* Here we try to rule out possible ambiguities.
- If we can't do that, keep a TREE_LIST with possibly ambiguous
- decls in there. */
- maybe_push_cache_obstack ();
- /* Arbitrarily choose the first function in the list. This is OK
- because this is only used for initial lookup; anything that
- actually uses the function will look it up again. */
- envelope_add_decl (type, OVL_CURRENT (*methods),
- &TREE_PURPOSE (class_value));
- pop_obstacks ();
-
- methods++;
- }
- }
- SET_BINFO_MARKED (binfo);
+ return NULL_TREE;
}
-/* Consolidate unique (by name) member functions. */
+/* Push class-level declarations for any names appearing in BINFO that
+ are not TYPE_DECLS. */
-static void
-dfs_compress_decls (binfo)
+static tree
+dfs_push_decls (binfo, data)
tree binfo;
+ void *data;
{
- tree type = BINFO_TYPE (binfo);
- tree method_vec = CLASSTYPE_METHOD_VEC (type);
+ tree type;
+ tree method_vec;
+ int dep_base_p;
+
+ type = BINFO_TYPE (binfo);
+ dep_base_p = (processing_template_decl && type != current_class_type
+ && dependent_base_p (binfo));
+ if (!dep_base_p)
+ {
+ tree fields;
+ for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
+ if (DECL_NAME (fields)
+ && TREE_CODE (fields) != TYPE_DECL
+ && TREE_CODE (fields) != USING_DECL)
+ setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
+ else if (TREE_CODE (fields) == FIELD_DECL
+ && ANON_UNION_TYPE_P (TREE_TYPE (fields)))
+ dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
+
+ method_vec = (CLASS_TYPE_P (type)
+ ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
+ if (method_vec)
+ {
+ tree *methods;
+ tree *end;
- if (method_vec != 0)
- {
- /* Farm out constructors and destructors. */
- tree *methods = &TREE_VEC_ELT (method_vec, 2);
- tree *end = TREE_VEC_END (method_vec);
+ /* Farm out constructors and destructors. */
+ end = TREE_VEC_END (method_vec);
- for (; methods != end; methods++)
- {
- /* This is known to be an envelope of the kind described before
- dfs_pushdecls. */
- tree class_value =
- IDENTIFIER_CLASS_VALUE (DECL_NAME (OVL_CURRENT (*methods)));
- tree tmp = TREE_PURPOSE (class_value);
-
- /* This was replaced in scope by somebody else. Just leave it
- alone. */
- if (TREE_CODE (tmp) != TREE_LIST)
- continue;
-
- if (TREE_CHAIN (tmp) == NULL_TREE
- && TREE_VALUE (tmp)
- && OVL_NEXT (TREE_VALUE (tmp)) == NULL_TREE)
- {
- TREE_PURPOSE (class_value) = TREE_VALUE (tmp);
- }
+ for (methods = &TREE_VEC_ELT (method_vec, 2);
+ *methods && methods != end;
+ methods++)
+ setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)),
+ /*type_binding_p=*/0);
}
}
- CLEAR_BINFO_MARKED (binfo);
+
+ CLEAR_BINFO_PUSHDECLS_MARKED (binfo);
+
+ return NULL_TREE;
}
/* When entering the scope of a class, we cache all of the
@@ -3641,81 +2979,29 @@ push_class_decls (type)
struct obstack *ambient_obstack = current_obstack;
search_stack = push_search_level (search_stack, &search_obstack);
- /* Push class fields into CLASS_VALUE scope, and mark. */
- dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
-
- /* Compress fields which have only a single entry
- by a given name, and unmark. */
- dfs_walk (TYPE_BINFO (type), dfs_compress_decls, markedp);
-
- /* Open up all the closed envelopes and push the contained decls into
- class scope. */
- while (closed_envelopes)
- {
- tree new = TREE_PURPOSE (closed_envelopes);
- tree id;
-
- /* This is messy because the class value may be a *_DECL, or a
- TREE_LIST of overloaded *_DECLs or even a TREE_LIST of ambiguous
- *_DECLs. The name is stored at different places in these three
- cases. */
- if (TREE_CODE (new) == TREE_LIST)
- {
- if (TREE_PURPOSE (new) != NULL_TREE)
- id = TREE_PURPOSE (new);
- else
- {
- tree node = TREE_VALUE (new);
+ /* Build up all the relevant bindings and such on the cache
+ obstack. That way no memory is wasted when we throw away the
+ cache later. */
+ push_cache_obstack ();
- if (TREE_CODE (node) == TYPE_DECL
- && DECL_ARTIFICIAL (node)
- && IS_AGGR_TYPE (TREE_TYPE (node))
- && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (node)))
- {
- tree t = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (node));
- tree n = new;
+ /* Enter type declarations and mark. */
+ dfs_walk (TYPE_BINFO (type), dfs_push_type_decls, unmarked_pushdecls_p, 0);
- for (; n; n = TREE_CHAIN (n))
- {
- tree d = TREE_VALUE (n);
- if (TREE_CODE (d) == TYPE_DECL
- && DECL_ARTIFICIAL (node)
- && IS_AGGR_TYPE (TREE_TYPE (d))
- && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d))
- && CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d)) == t)
- /* OK */;
- else
- break;
- }
+ /* Enter non-type declarations and unmark. */
+ dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
- if (n == NULL_TREE)
- new = t;
- }
- else while (TREE_CODE (node) == TREE_LIST)
- node = TREE_VALUE (node);
- id = DECL_NAME (node);
- }
- }
- else
- id = DECL_NAME (new);
+ /* Undo the call to push_cache_obstack above. */
+ pop_obstacks ();
- /* Install the original class value in order to make
- pushdecl_class_level work correctly. */
- IDENTIFIER_CLASS_VALUE (id) = TREE_VALUE (closed_envelopes);
- if (TREE_CODE (new) == TREE_LIST)
- push_class_level_binding (id, new);
- else
- pushdecl_class_level (new);
- closed_envelopes = TREE_CHAIN (closed_envelopes);
- }
current_obstack = ambient_obstack;
}
/* Here's a subroutine we need because C lacks lambdas. */
-static void
-dfs_unuse_fields (binfo)
+static tree
+dfs_unuse_fields (binfo, data)
tree binfo;
+ void *data ATTRIBUTE_UNUSED;
{
tree type = TREE_TYPE (binfo);
tree fields;
@@ -3730,13 +3016,15 @@ dfs_unuse_fields (binfo)
&& TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
unuse_fields (TREE_TYPE (fields));
}
+
+ return NULL_TREE;
}
void
unuse_fields (type)
tree type;
{
- dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp);
+ dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp, 0);
}
void
@@ -3752,23 +3040,6 @@ void
print_search_statistics ()
{
#ifdef GATHER_STATISTICS
- if (flag_memoize_lookups)
- {
- fprintf (stderr, "%d memoized contexts saved\n",
- n_contexts_saved);
- fprintf (stderr, "%d local tree nodes made\n", my_tree_node_counter);
- fprintf (stderr, "%d local hash nodes made\n", my_memoized_entry_counter);
- fprintf (stderr, "fields statistics:\n");
- fprintf (stderr, " memoized finds = %d; rejects = %d; (searches = %d)\n",
- memoized_fast_finds[0], memoized_fast_rejects[0],
- memoized_fields_searched[0]);
- fprintf (stderr, " memoized_adds = %d\n", memoized_adds[0]);
- fprintf (stderr, "fnfields statistics:\n");
- fprintf (stderr, " memoized finds = %d; rejects = %d; (searches = %d)\n",
- memoized_fast_finds[1], memoized_fast_rejects[1],
- memoized_fields_searched[1]);
- fprintf (stderr, " memoized_adds = %d\n", memoized_adds[1]);
- }
fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1);
fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
@@ -3783,27 +3054,12 @@ void
init_search_processing ()
{
gcc_obstack_init (&search_obstack);
- gcc_obstack_init (&type_obstack);
- gcc_obstack_init (&type_obstack_entries);
-
- /* This gives us room to build our chains of basetypes,
- whether or not we decide to memoize them. */
- type_stack = push_type_level ((struct stack_level *)0, &type_obstack);
_vptr_name = get_identifier ("_vptr");
}
void
reinit_search_statistics ()
{
- my_memoized_entry_counter = 0;
- memoized_fast_finds[0] = 0;
- memoized_fast_finds[1] = 0;
- memoized_adds[0] = 0;
- memoized_adds[1] = 0;
- memoized_fast_rejects[0] = 0;
- memoized_fast_rejects[1] = 0;
- memoized_fields_searched[0] = 0;
- memoized_fields_searched[1] = 0;
#ifdef GATHER_STATISTICS
n_fields_searched = 0;
n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
@@ -3816,145 +3072,92 @@ reinit_search_statistics ()
#define scratch_tree_cons expr_tree_cons
-static tree conversions;
-static void
-add_conversions (binfo)
+static tree
+add_conversions (binfo, data)
tree binfo;
+ void *data;
{
int i;
tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+ tree *conversions = (tree *) data;
for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
{
tree tmp = TREE_VEC_ELT (method_vec, i);
- if (! IDENTIFIER_TYPENAME_P (DECL_NAME (OVL_CURRENT (tmp))))
- break;
- conversions = scratch_tree_cons (binfo, tmp, conversions);
- }
- SET_BINFO_MARKED (binfo);
-}
-
-tree
-lookup_conversions (type)
- tree type;
-{
- conversions = NULL_TREE;
- if (TYPE_SIZE (type))
- {
- dfs_walk (TYPE_BINFO (type), add_conversions, unmarkedp);
- dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
- }
- return conversions;
-}
-
-/* Subroutine of get_template_base. */
-
-static tree
-get_template_base_recursive (binfo, rval, template, via_virtual)
- tree binfo, template, rval;
- int via_virtual;
-{
- tree binfos;
- int i, n_baselinks;
- tree type = BINFO_TYPE (binfo);
-
- if (CLASSTYPE_TEMPLATE_INFO (type)
- && CLASSTYPE_TI_TEMPLATE (type) == template)
- {
- if (rval == NULL_TREE || rval == type)
- return type;
- else
- return error_mark_node;
- }
+ tree name;
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
+ break;
- /* Process base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
+ name = DECL_NAME (OVL_CURRENT (tmp));
- /* Find any specific instance of a virtual base, when searching with
- a binfo... */
- if (BINFO_MARKED (base_binfo) == 0)
+ /* Make sure we don't already have this conversion. */
+ if (! IDENTIFIER_MARKED (name))
{
- int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
-
- /* When searching for a non-virtual, we cannot mark
- virtually found binfos. */
- if (! this_virtual)
- SET_BINFO_MARKED (base_binfo);
-
- rval = get_template_base_recursive
- (base_binfo, rval, template, this_virtual);
- if (rval == error_mark_node)
- return rval;
+ *conversions = scratch_tree_cons (binfo, tmp, *conversions);
+ IDENTIFIER_MARKED (name) = 1;
}
}
-
- return rval;
+ return NULL_TREE;
}
-/* Given a class template TEMPLATE and a class type or binfo node BINFO,
- find the unique base type in BINFO that is an instance of TEMPLATE.
- If there are more than one, return error_mark_node. Used by unify. */
-
tree
-get_template_base (template, binfo)
- register tree template, binfo;
+lookup_conversions (type)
+ tree type;
{
- tree type = NULL_TREE, rval;
+ tree t;
+ tree conversions = NULL_TREE;
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
- {
- type = complete_type (binfo);
- binfo = TYPE_BINFO (type);
- }
- else
- my_friendly_abort (92);
-
- if (CLASSTYPE_TEMPLATE_INFO (type)
- && CLASSTYPE_TI_TEMPLATE (type) == template)
- return type;
+ if (TYPE_SIZE (type))
+ bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
- rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
- dfs_walk (binfo, dfs_unmark, markedp);
+ for (t = conversions; t; t = TREE_CHAIN (t))
+ IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
- return rval;
+ return conversions;
}
+struct overlap_info
+{
+ tree compare_type;
+ int found_overlap;
+};
+
/* Check whether the empty class indicated by EMPTY_BINFO is also present
at offset 0 in COMPARE_TYPE, and set found_overlap if so. */
-static tree compare_type;
-static int found_overlap;
-static void
-dfs_check_overlap (empty_binfo)
+static tree
+dfs_check_overlap (empty_binfo, data)
tree empty_binfo;
+ void *data;
{
+ struct overlap_info *oi = (struct overlap_info *) data;
tree binfo;
- for (binfo = TYPE_BINFO (compare_type); ; binfo = BINFO_BASETYPE (binfo, 0))
+ for (binfo = TYPE_BINFO (oi->compare_type);
+ ;
+ binfo = BINFO_BASETYPE (binfo, 0))
{
if (BINFO_TYPE (binfo) == BINFO_TYPE (empty_binfo))
{
- found_overlap = 1;
+ oi->found_overlap = 1;
break;
}
else if (BINFO_BASETYPES (binfo) == NULL_TREE)
break;
}
+
+ return NULL_TREE;
}
/* Trivial function to stop base traversal when we find something. */
-static int
-dfs_no_overlap_yet (t)
- tree t ATTRIBUTE_UNUSED;
+static tree
+dfs_no_overlap_yet (binfo, data)
+ tree binfo;
+ void *data;
{
- return found_overlap == 0;
+ struct overlap_info *oi = (struct overlap_info *) data;
+ return !oi->found_overlap ? binfo : NULL_TREE;
}
/* Returns nonzero if EMPTY_TYPE or any of its bases can also be found at
@@ -3964,10 +3167,64 @@ int
types_overlap_p (empty_type, next_type)
tree empty_type, next_type;
{
+ struct overlap_info oi;
+
if (! IS_AGGR_TYPE (next_type))
return 0;
- compare_type = next_type;
- found_overlap = 0;
- dfs_walk (TYPE_BINFO (empty_type), dfs_check_overlap, dfs_no_overlap_yet);
- return found_overlap;
+ oi.compare_type = next_type;
+ oi.found_overlap = 0;
+ dfs_walk (TYPE_BINFO (empty_type), dfs_check_overlap,
+ dfs_no_overlap_yet, &oi);
+ return oi.found_overlap;
+}
+
+struct bfv_info {
+ tree vbases;
+ tree var;
+};
+
+static tree
+dfs_bfv_queue_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct bfv_info *bfvi = (struct bfv_info *) data;
+
+ /* Use the real virtual base class objects, not the placeholders in
+ the usual hierarchy. */
+ if (TREE_VIA_VIRTUAL (binfo))
+ return binfo_member (BINFO_TYPE (binfo), bfvi->vbases);
+
+ return binfo;
+}
+
+/* Passed to dfs_walk_real by binfo_for_vtable; determine if bvtable
+ comes from BINFO. */
+
+static tree
+dfs_bfv_helper (binfo, data)
+ tree binfo;
+ void *data;
+{
+ struct bfv_info *bfvi = (struct bfv_info *) data;
+
+ if (BINFO_VTABLE (binfo) == bfvi->var)
+ return binfo;
+ return NULL_TREE;
+}
+
+/* Given a vtable VAR, determine which binfo it comes from. */
+
+tree
+binfo_for_vtable (var)
+ tree var;
+{
+ tree type;
+ struct bfv_info bfvi;
+
+ type = DECL_CONTEXT (var);
+ bfvi.vbases = CLASSTYPE_VBASECLASSES (type);
+ bfvi.var = var;
+ return dfs_walk_real (TYPE_BINFO (type),
+ 0, dfs_bfv_helper, dfs_bfv_queue_p, &bfvi);
}
diff --git a/contrib/gcc/cp/semantics.c b/contrib/gcc/cp/semantics.c
index 5068512..7267f46 100644
--- a/contrib/gcc/cp/semantics.c
+++ b/contrib/gcc/cp/semantics.c
@@ -3,7 +3,7 @@
building RTL. These routines are used both during actual parsing
and during the instantiation of template functions.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
@@ -120,7 +120,7 @@ finish_if_stmt_cond (cond, if_stmt)
if (last_tree != if_stmt)
RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
else
- IF_COND (if_stmt) = cond;
+ IF_COND (if_stmt) = copy_to_permanent (cond);
}
else
{
@@ -219,7 +219,7 @@ finish_while_stmt_cond (cond, while_stmt)
RECHAIN_STMTS_FROM_LAST (while_stmt,
WHILE_COND (while_stmt));
else
- TREE_OPERAND (while_stmt, 0) = cond;
+ TREE_OPERAND (while_stmt, 0) = copy_to_permanent (cond);
}
else
{
@@ -294,7 +294,7 @@ finish_do_stmt (cond, do_stmt)
tree do_stmt;
{
if (processing_template_decl)
- DO_COND (do_stmt) = cond;
+ DO_COND (do_stmt) = copy_to_permanent (cond);
else
{
emit_line_note (input_filename, lineno);
@@ -378,7 +378,7 @@ finish_for_cond (cond, for_stmt)
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
else
- FOR_COND (for_stmt) = cond;
+ FOR_COND (for_stmt) = copy_to_permanent (cond);
}
else
{
@@ -490,12 +490,20 @@ finish_switch_cond (cond)
r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
add_tree (r);
}
- else
+ else if (cond != error_mark_node)
{
emit_line_note (input_filename, lineno);
c_expand_start_case (cond);
r = NULL_TREE;
}
+ else
+ {
+ /* The code is in error, but we don't want expand_end_case to
+ crash. */
+ c_expand_start_case (boolean_false_node);
+ r = NULL_TREE;
+ }
+
push_switch ();
/* Don't let the tree nodes for COND be discarded by
@@ -731,13 +739,18 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
{
emit_line_note (input_filename, lineno);
if (output_operands != NULL_TREE || input_operands != NULL_TREE
- || clobbers != NULL_TREE)
+ || clobbers != NULL_TREE)
{
+ tree t;
+
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
cp_warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
-
+
+ for (t = input_operands; t; t = TREE_CHAIN (t))
+ TREE_VALUE (t) = decay_conversion (TREE_VALUE (t));
+
c_expand_asm_operands (string, output_operands,
input_operands,
clobbers,
@@ -747,12 +760,14 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
}
else
{
- if (cv_qualifier != NULL_TREE)
+ /* Don't warn about redundant specification of 'volatile' here. */
+ if (cv_qualifier != NULL_TREE
+ && cv_qualifier != ridpointers[(int) RID_VOLATILE])
cp_warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
expand_asm (string);
}
-
+
finish_stmt ();
}
}
@@ -807,8 +822,8 @@ finish_stmt_expr (rtl_expr, expr)
{
/* Make a BIND_EXPR for the BLOCK already made. */
if (processing_template_decl)
- result = build (BIND_EXPR, NULL_TREE,
- NULL_TREE, last_tree, expr);
+ result = build_min_nt (BIND_EXPR, NULL_TREE, last_tree,
+ NULL_TREE);
else
result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
NULL_TREE, rtl_expr, expr);
@@ -853,7 +868,8 @@ finish_call_expr (fn, args, koenig)
result = build_x_function_call (fn, args, current_class_ref);
if (TREE_CODE (result) == CALL_EXPR
- && TREE_TYPE (result) != void_type_node)
+ && (! TREE_TYPE (result)
+ || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
result = require_complete_type (result);
return result;
@@ -995,7 +1011,7 @@ finish_pseudo_destructor_call_expr (object, scope, destructor)
ARGS. Returns an expression for the call. */
tree
-finish_globally_qualified_member_call_expr (fn, args)
+finish_qualified_call_expr (fn, args)
tree fn;
tree args;
{
@@ -1098,6 +1114,10 @@ begin_function_definition (decl_specs, declarator)
return 0;
reinit_parse_for_function ();
+ /* The things we're about to see are not directly qualified by any
+ template headers we've seen thus far. */
+ reset_specialization ();
+
return 1;
}
@@ -1110,13 +1130,7 @@ begin_constructor_declarator (scope, name)
tree name;
{
tree result = build_parse_node (SCOPE_REF, scope, name);
-
- if (scope != current_class_type)
- {
- push_nested_class (scope, 3);
- TREE_COMPLEXITY (result) = current_class_depth;
- }
-
+ enter_scope_of (result);
return result;
}
@@ -1210,50 +1224,85 @@ tree
begin_class_definition (t)
tree t;
{
- tree new_type = t;
-
push_obstacks_nochange ();
end_temporary_allocation ();
if (t == error_mark_node
|| ! IS_AGGR_TYPE (t))
{
- t = new_type = make_lang_type (RECORD_TYPE);
+ t = make_lang_type (RECORD_TYPE);
pushtag (make_anon_name (), t, 0);
}
- if (TYPE_SIZE (t))
+
+ /* In a definition of a member class template, we will get here with an
+ implicit typename, a TYPENAME_TYPE with a type. */
+ if (TREE_CODE (t) == TYPENAME_TYPE)
+ t = TREE_TYPE (t);
+
+ /* If we generated a partial instantiation of this type, but now
+ we're seeing a real definition, we're actually looking at a
+ partial specialization. Consider:
+
+ template <class T, class U>
+ struct Y {};
+
+ template <class T>
+ struct X {};
+
+ template <class T, class U>
+ void f()
+ {
+ typename X<Y<T, U> >::A a;
+ }
+
+ template <class T, class U>
+ struct X<Y<T, U> >
+ {
+ };
+
+ We have to undo the effects of the previous partial
+ instantiation. */
+ if (PARTIAL_INSTANTIATION_P (t))
+ {
+ if (!pedantic)
+ {
+ /* Unfortunately, when we're not in pedantic mode, we
+ attempt to actually fill in some of the fields of the
+ partial instantiation, in order to support the implicit
+ typename extension. Clear those fields now, in
+ preparation for the definition here. The fields cleared
+ here must match those set in instantiate_class_template.
+ Look for a comment mentioning begin_class_definition
+ there. */
+ TYPE_BINFO_BASETYPES (t) = NULL_TREE;
+ TYPE_FIELDS (t) = NULL_TREE;
+ TYPE_METHODS (t) = NULL_TREE;
+ CLASSTYPE_TAGS (t) = NULL_TREE;
+ TYPE_SIZE (t) = NULL_TREE;
+ }
+
+ /* This isn't a partial instantiation any more. */
+ PARTIAL_INSTANTIATION_P (t) = 0;
+ }
+ /* If this type was already complete, and we see another definition,
+ that's an error. */
+ else if (TYPE_SIZE (t))
duplicate_tag_error (t);
- if (TYPE_SIZE (t) || TYPE_BEING_DEFINED (t))
+
+ if (TYPE_BEING_DEFINED (t))
{
t = make_lang_type (TREE_CODE (t));
pushtag (TYPE_IDENTIFIER (t), t, 0);
- new_type = t;
}
- if (processing_template_decl && TYPE_CONTEXT (t)
- && TREE_CODE (TYPE_CONTEXT (t)) != NAMESPACE_DECL
- && ! current_class_type)
- push_template_decl (TYPE_STUB_DECL (t));
- pushclass (t, 0);
+ maybe_process_partial_specialization (t);
+ pushclass (t, 1);
TYPE_BEING_DEFINED (t) = 1;
- if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t))
- {
- if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
- && TYPE_SIZE (t) == NULL_TREE)
- {
- SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
- if (processing_template_decl)
- push_template_decl (TYPE_MAIN_DECL (t));
- }
- else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
- cp_error ("specialization after instantiation of `%T'", t);
- }
/* Reset the interface data, at the earliest possible
moment, as it might have been set via a class foo;
before. */
/* Don't change signatures. */
if (! IS_SIGNATURE (t))
{
- extern tree pending_vtables;
int needs_writing;
tree name = TYPE_IDENTIFIER (t);
@@ -1265,30 +1314,19 @@ begin_class_definition (t)
}
/* Record how to set the access of this class's
- virtual functions. If write_virtuals == 2 or 3, then
+ virtual functions. If write_virtuals == 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 (t)
- && CLASSTYPE_INTERFACE_KNOWN (t);
- break;
- default:
- needs_writing = 0;
- }
+ if (write_virtuals == 3)
+ needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
+ && CLASSTYPE_INTERFACE_KNOWN (t);
+ else
+ needs_writing = 1;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
}
#if 0
- t = TYPE_IDENTIFIER ($<ttype>0);
- if (t && IDENTIFIER_TEMPLATE (t))
- overload_template_name (t, 1);
+ tmp = TYPE_IDENTIFIER ($<ttype>0);
+ if (tmp && IDENTIFIER_TEMPLATE (tmp))
+ overload_template_name (tmp, 1);
#endif
reset_specialization();
@@ -1297,26 +1335,108 @@ begin_class_definition (t)
that we can get it back later. */
begin_tree ();
- return new_type;
+ /* Make a declaration for this class in its own scope. */
+ build_self_reference ();
+
+ return t;
}
-/* Finish a class definition T, with the indicated COMPONENTS, and
- with the indicate ATTRIBUTES. If SEMI, the definition is
- immediately followed by a semicolon. Returns the type. */
+/* Finish the member declaration given by DECL. */
+
+void
+finish_member_declaration (decl)
+ tree decl;
+{
+ if (decl == error_mark_node || decl == NULL_TREE)
+ return;
+
+ if (decl == void_type_node)
+ /* The COMPONENT was a friend, not a member, and so there's
+ nothing for us to do. */
+ return;
+
+ /* We should see only one DECL at a time. */
+ my_friendly_assert (TREE_CHAIN (decl) == NULL_TREE, 0);
+
+ /* Set up access control for DECL. */
+ TREE_PRIVATE (decl)
+ = (current_access_specifier == access_private_node);
+ TREE_PROTECTED (decl)
+ = (current_access_specifier == access_protected_node);
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ TREE_PRIVATE (DECL_RESULT (decl)) = TREE_PRIVATE (decl);
+ TREE_PROTECTED (DECL_RESULT (decl)) = TREE_PROTECTED (decl);
+ }
+
+ /* Mark the DECL as a member of the current class. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (decl))
+ /* Historically, DECL_CONTEXT was not set for a FUNCTION_DECL in
+ finish_struct. Presumably it is already set as the function is
+ parsed. Perhaps DECL_CLASS_CONTEXT is already set, too? */
+ DECL_CLASS_CONTEXT (decl) = current_class_type;
+ else
+ DECL_CONTEXT (decl) = current_class_type;
+
+ /* Put functions on the TYPE_METHODS list and everything else on the
+ TYPE_FIELDS list. Note that these are built up in reverse order.
+ We reverse them (to obtain declaration order) in finish_struct. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (decl))
+ {
+ /* We also need to add this function to the
+ CLASSTYPE_METHOD_VEC. */
+ add_method (current_class_type, 0, decl);
+
+ TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
+ TYPE_METHODS (current_class_type) = decl;
+ }
+ else
+ {
+ /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
+ go at the beginning. The reason is that lookup_field_1
+ searches the list in order, and we want a field name to
+ override a type name so that the "struct stat hack" will
+ work. In particular:
+
+ struct S { enum E { }; int E } s;
+ s.E = 3;
+
+ is legal. In addition, the FIELD_DECLs must be maintained in
+ declaration order so that class layout works as expected.
+ However, we don't need that order until class layout, so we
+ save a little time by putting FIELD_DECLs on in reverse order
+ here, and then reversing them in finish_struct_1. (We could
+ also keep a pointer to the correct insertion points in the
+ list.) */
+
+ if (TREE_CODE (decl) == TYPE_DECL)
+ TYPE_FIELDS (current_class_type)
+ = chainon (TYPE_FIELDS (current_class_type), decl);
+ else
+ {
+ TREE_CHAIN (decl) = TYPE_FIELDS (current_class_type);
+ TYPE_FIELDS (current_class_type) = decl;
+ }
+
+ /* Enter the DECL into the scope of the class. */
+ if (TREE_CODE (decl) != USING_DECL)
+ pushdecl_class_level (decl);
+ }
+}
+
+/* Finish a class definition T with the indicate ATTRIBUTES. If SEMI,
+ the definition is immediately followed by a semicolon. Returns the
+ type. */
tree
-finish_class_definition (t, components, attributes, semi)
+finish_class_definition (t, attributes, semi, pop_scope_p)
tree t;
- tree components;
tree attributes;
int semi;
+ int pop_scope_p;
{
-#if 0
- /* Need to rework class nesting in the presence of nested classes,
- etc. */
- shadow_tag (CLASSTYPE_AS_LIST (t)); */
-#endif
-
/* finish_struct nukes this anyway; if finish_exception does too,
then it can go. */
if (semi)
@@ -1331,7 +1451,7 @@ finish_class_definition (t, components, attributes, semi)
;
else
{
- t = finish_struct (t, components, attributes, semi);
+ t = finish_struct (t, attributes, semi);
if (semi)
note_got_semicolon (t);
}
@@ -1340,6 +1460,8 @@ finish_class_definition (t, components, attributes, semi)
if (! semi)
check_for_missing_semicolon (t);
+ if (pop_scope_p)
+ pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t)));
if (current_scope () == current_function_decl)
do_pending_defargs ();
@@ -1350,7 +1472,7 @@ finish_class_definition (t, components, attributes, semi)
the processing of a class definition. */
void
-finish_default_args ()
+begin_inline_definitions ()
{
if (pending_inlines
&& current_scope () == current_function_decl)
@@ -1361,7 +1483,7 @@ finish_default_args ()
processing of a class definition. */
void
-begin_inline_definitions ()
+finish_inline_definitions ()
{
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
@@ -1374,20 +1496,191 @@ begin_inline_definitions ()
TYPES whose template parameters are given by PARMS. */
tree
-finish_member_class_template (parms, types)
- tree parms;
+finish_member_class_template (types)
tree types;
{
+ tree t;
+
+ /* If there are declared, but undefined, partial specializations
+ mixed in with the typespecs they will not yet have passed through
+ maybe_process_partial_specialization, so we do that here. */
+ for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
+ if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
+ maybe_process_partial_specialization (TREE_VALUE (t));
+
note_list_got_semicolon (types);
- grok_x_components (types, NULL_TREE);
+ grok_x_components (types);
if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
/* The component was in fact a friend declaration. We avoid
finish_member_template_decl performing certain checks by
unsetting TYPES. */
types = NULL_TREE;
- finish_member_template_decl (parms, types);
+
+ finish_member_template_decl (types);
+
/* As with other component type declarations, we do
not store the new DECL on the list of
component_decls. */
return NULL_TREE;
}
+
+/* Finish processsing a complete template declaration. The PARMS are
+ the template parameters. */
+
+void
+finish_template_decl (parms)
+ tree parms;
+{
+ if (parms)
+ end_template_decl ();
+ else
+ end_specialization ();
+}
+
+/* Finish processing a a template-id (which names a type) of the form
+ NAME < ARGS >. Return the TYPE_DECL for the type named by the
+ template-id. If ENTERING_SCOPE is non-zero we are about to enter
+ the scope of template-id indicated. */
+
+tree
+finish_template_type (name, args, entering_scope)
+ tree name;
+ tree args;
+ int entering_scope;
+{
+ tree decl;
+
+ decl = lookup_template_class (name, args,
+ NULL_TREE, NULL_TREE, entering_scope);
+ if (decl != error_mark_node)
+ decl = TYPE_STUB_DECL (decl);
+
+ return decl;
+}
+
+/* SR is a SCOPE_REF node. Enter the scope of SR, whether it is a
+ namespace scope or a class scope. */
+
+void
+enter_scope_of (sr)
+ tree sr;
+{
+ tree scope = TREE_OPERAND (sr, 0);
+
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ {
+ push_decl_namespace (scope);
+ TREE_COMPLEXITY (sr) = -1;
+ }
+ else if (scope != current_class_type)
+ {
+ if (TREE_CODE (scope) == TYPENAME_TYPE)
+ {
+ /* In a declarator for a template class member, the scope will
+ get here as an implicit typename, a TYPENAME_TYPE with a type. */
+ scope = TREE_TYPE (scope);
+ TREE_OPERAND (sr, 0) = scope;
+ }
+ push_nested_class (scope, 3);
+ TREE_COMPLEXITY (sr) = current_class_depth;
+ }
+}
+
+/* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
+ Return a TREE_LIST containing the ACCESS_SPECIFIER and the
+ BASE_CLASS, or NULL_TREE if an error occurred. The
+ ACCESSS_SPECIFIER is one of
+ access_{default,public,protected_private}[_virtual]_node.*/
+
+tree
+finish_base_specifier (access_specifier, base_class,
+ current_aggr_is_signature)
+ tree access_specifier;
+ tree base_class;
+ int current_aggr_is_signature;
+{
+ tree type;
+ tree result;
+
+ if (base_class == NULL_TREE)
+ {
+ error ("invalid base class");
+ type = error_mark_node;
+ }
+ else
+ type = TREE_TYPE (base_class);
+ if (current_aggr_is_signature && access_specifier)
+ error ("access and source specifiers not allowed in signature");
+ if (! is_aggr_type (type, 1))
+ result = NULL_TREE;
+ else if (current_aggr_is_signature
+ && (! type) && (! IS_SIGNATURE (type)))
+ {
+ error ("class name not allowed as base signature");
+ result = NULL_TREE;
+ }
+ else if (current_aggr_is_signature)
+ {
+ sorry ("signature inheritance, base type `%s' ignored",
+ IDENTIFIER_POINTER (access_specifier));
+ result = build_tree_list (access_public_node, type);
+ }
+ else if (type && IS_SIGNATURE (type))
+ {
+ error ("signature name not allowed as base class");
+ result = NULL_TREE;
+ }
+ else
+ result = build_tree_list (access_specifier, type);
+
+ return result;
+}
+
+/* Called when multiple declarators are processed. If that is not
+ premitted in this context, an error is issued. */
+
+void
+check_multiple_declarators ()
+{
+ /* [temp]
+
+ In a template-declaration, explicit specialization, or explicit
+ instantiation the init-declarator-list in the declaration shall
+ contain at most one declarator.
+
+ We don't just use PROCESSING_TEMPLATE_DECL for the first
+ condition since that would disallow the perfectly legal code,
+ like `template <class T> struct S { int i, j; };'. */
+ tree scope = current_scope ();
+
+ if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ /* It's OK to write `template <class T> void f() { int i, j;}'. */
+ return;
+
+ if (PROCESSING_REAL_TEMPLATE_DECL_P ()
+ || processing_explicit_instantiation
+ || processing_specialization)
+ cp_error ("multiple declarators in template declaration");
+}
+
+tree
+finish_typeof (expr)
+ tree expr;
+{
+ if (processing_template_decl)
+ {
+ tree t;
+
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ t = make_lang_type (TYPEOF_TYPE);
+ TYPE_FIELDS (t) = expr;
+
+ pop_obstacks ();
+
+ return t;
+ }
+
+ return TREE_TYPE (expr);
+}
diff --git a/contrib/gcc/cp/sig.c b/contrib/gcc/cp/sig.c
index 65350db..f170df5 100644
--- a/contrib/gcc/cp/sig.c
+++ b/contrib/gcc/cp/sig.c
@@ -1,5 +1,5 @@
/* Functions dealing with signatures and signature pointers/references.
- Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
Contributed by Gerald Baumgartner (gb@cs.purdue.edu)
This file is part of GNU CC.
@@ -33,18 +33,16 @@ extern struct obstack *current_obstack;
extern struct obstack permanent_obstack;
extern struct obstack *saveable_obstack;
-extern void compiler_error ();
-
static tree save_this PROTO((tree));
static tree build_sptr_ref PROTO((tree));
static tree build_member_function_pointer PROTO((tree));
static void undo_casts PROTO((tree));
static tree build_signature_pointer_or_reference_name
- PROTO((tree, int, int, int));
+ PROTO((tree, int, int));
static void build_signature_pointer_or_reference_decl
PROTO((tree, tree));
static tree build_signature_pointer_or_reference_type
- PROTO((tree, int, int, int));
+ PROTO((tree, int, int));
static tree get_sigtable_name PROTO((tree, tree));
static tree build_signature_table_constructor PROTO((tree, tree));
static int match_method_types PROTO((tree, tree));
@@ -58,25 +56,31 @@ static int global_sigtable_name_counter;
can use it's name in function name mangling. */
static tree
-build_signature_pointer_or_reference_name (to_type, constp, volatilep, refp)
+build_signature_pointer_or_reference_name (to_type, type_quals, refp)
tree to_type;
- int constp, volatilep, refp;
+ int type_quals;
+ int refp;
{
- char * sig_name = TYPE_NAME_STRING (to_type);
- int name_len = TYPE_NAME_LENGTH (to_type) + constp + volatilep;
+ const char * sig_name = TYPE_NAME_STRING (to_type);
+ int name_len = TYPE_NAME_LENGTH (to_type) + 3 /* Enough room for
+ C,V,R. */;
char * name;
+ const char *const_rep = (type_quals & TYPE_QUAL_CONST) ? "C" : "";
+ const char *restrict_rep = (type_quals & TYPE_QUAL_RESTRICT) ? "R" : "";
+ const char *volatile_rep = (type_quals & TYPE_QUAL_VOLATILE) ? "C" : "";
+
if (refp)
{
name = (char *) alloca (name_len + sizeof (SIGNATURE_REFERENCE_NAME) +2);
sprintf (name, SIGNATURE_REFERENCE_NAME_FORMAT,
- constp ? "C" : "", volatilep ? "V": "", sig_name);
+ const_rep, volatile_rep, restrict_rep, sig_name);
}
else
{
name = (char *) alloca (name_len + sizeof (SIGNATURE_POINTER_NAME) + 2);
sprintf (name, SIGNATURE_POINTER_NAME_FORMAT,
- constp ? "C" : "", volatilep ? "V": "", sig_name);
+ const_rep, volatile_rep, restrict_rep, sig_name);
}
return get_identifier (name);
}
@@ -98,21 +102,22 @@ build_signature_pointer_or_reference_decl (type, name)
TREE_CHAIN (type) = decl;
}
-/* Construct, lay out and return the type of pointers or references
- to signature TO_TYPE. If such a type has already been constructed,
- reuse it. If CONSTP or VOLATILEP is specified, make the `optr' const
- or volatile, respectively. If we are constructing a const/volatile
- type variant and the main type variant doesn't exist yet, it is built
- as well. If REFP is 1, we construct a signature reference, otherwise
- a signature pointer is constructed.
+/* Construct, lay out and return the type of pointers or references to
+ signature TO_TYPE. If such a type has already been constructed,
+ reuse it. If TYPE_QUALS are specified, qualify the `optr'. If we
+ are constructing a const/volatile type variant and the main type
+ variant doesn't exist yet, it is built as well. If REFP is 1, we
+ construct a signature reference, otherwise a signature pointer is
+ constructed.
This function is a subroutine of `build_signature_pointer_type' and
`build_signature_reference_type'. */
static tree
-build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
+build_signature_pointer_or_reference_type (to_type, type_quals, refp)
tree to_type;
- int constp, volatilep, refp;
+ int type_quals;
+ int refp;
{
register tree t, m;
register struct obstack *ambient_obstack = current_obstack;
@@ -121,13 +126,11 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
m = refp ? SIGNATURE_REFERENCE_TO (to_type) : SIGNATURE_POINTER_TO (to_type);
/* If we don't have the main variant yet, construct it. */
- if (m == NULL_TREE
- && (constp || volatilep))
- m = build_signature_pointer_or_reference_type (to_type, 0, 0, refp);
+ if (m == NULL_TREE && type_quals != TYPE_UNQUALIFIED)
+ m = build_signature_pointer_or_reference_type (to_type,
+ TYPE_UNQUALIFIED, refp);
/* Treat any nonzero argument as 1. */
- constp = !!constp;
- volatilep = !!volatilep;
refp = !!refp;
/* If not generating auxiliary info, search the chain of variants to see
@@ -141,8 +144,8 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
if (m && !flag_gen_aux_info)
for (t = m; t; t = TYPE_NEXT_VARIANT (t))
- if (constp == TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t))))
- && volatilep == TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t)))))
+ if (type_quals == CP_TYPE_QUALS (TREE_TYPE (TREE_TYPE
+ (TYPE_FIELDS (t)))))
return t;
/* We need a new one. If TO_TYPE is permanent, make this permanent too. */
@@ -170,7 +173,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
t = make_lang_type (RECORD_TYPE);
{
- tree obj_type = build_type_variant (void_type_node, constp, volatilep);
+ tree obj_type = build_qualified_type (void_type_node, type_quals);
tree optr_type = build_pointer_type (obj_type);
tree optr, sptr;
@@ -185,7 +188,8 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
sptr = TREE_CHAIN (TYPE_FIELDS (m));
else
{
- tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0);
+ tree sig_tbl_type =
+ cp_build_qualified_type (to_type, TYPE_QUAL_CONST);
sptr = build_lang_field_decl (FIELD_DECL,
get_identifier (SIGNATURE_SPTR_NAME),
@@ -203,12 +207,13 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
TYPE_ALIGN (optr_type));
/* A signature pointer/reference type isn't a `real' class type. */
- IS_AGGR_TYPE (t) = 0;
+ SET_IS_AGGR_TYPE (t, 0);
}
{
- tree name = build_signature_pointer_or_reference_name (to_type, constp,
- volatilep, refp);
+ tree name = build_signature_pointer_or_reference_name (to_type,
+ type_quals,
+ refp);
/* Build a DECL node for this type, so the debugger has access to it. */
build_signature_pointer_or_reference_decl (t, name);
@@ -250,23 +255,23 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
/* Construct, lay out and return the type of pointers to signature TO_TYPE. */
tree
-build_signature_pointer_type (to_type, constp, volatilep)
+build_signature_pointer_type (to_type)
tree to_type;
- int constp, volatilep;
{
return
- build_signature_pointer_or_reference_type (to_type, constp, volatilep, 0);
+ build_signature_pointer_or_reference_type (TYPE_MAIN_VARIANT (to_type),
+ CP_TYPE_QUALS (to_type), 0);
}
/* Construct, lay out and return the type of pointers to signature TO_TYPE. */
tree
-build_signature_reference_type (to_type, constp, volatilep)
+build_signature_reference_type (to_type)
tree to_type;
- int constp, volatilep;
{
return
- build_signature_pointer_or_reference_type (to_type, constp, volatilep, 1);
+ build_signature_pointer_or_reference_type (TYPE_MAIN_VARIANT (to_type),
+ CP_TYPE_QUALS (to_type), 1);
}
/* Return the name of the signature table (as an IDENTIFIER_NODE)
@@ -281,8 +286,8 @@ get_sigtable_name (sig_type, rhs_type)
char *buf = (char *) alloca (sizeof (SIGTABLE_NAME_FORMAT_LONG)
+ IDENTIFIER_LENGTH (sig_type_id)
+ IDENTIFIER_LENGTH (rhs_type_id) + 20);
- char *sig_ptr = IDENTIFIER_POINTER (sig_type_id);
- char *rhs_ptr = IDENTIFIER_POINTER (rhs_type_id);
+ const char *sig_ptr = IDENTIFIER_POINTER (sig_type_id);
+ const char *rhs_ptr = IDENTIFIER_POINTER (rhs_type_id);
int i, j;
for (i = 0; sig_ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++)
@@ -309,7 +314,7 @@ static tree
build_member_function_pointer (member)
tree member;
{
- char *namstr = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (member));
+ const char *namstr = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (member));
int namlen = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (member));
char *name;
tree entry;
@@ -321,7 +326,7 @@ build_member_function_pointer (member)
GNU_xref_ref (current_function_decl, name);
entry = build_lang_field_decl (FIELD_DECL, get_identifier (name),
- TYPE_MAIN_VARIANT (sigtable_entry_type));
+ sigtable_entry_type);
TREE_CONSTANT (entry) = 1;
TREE_READONLY (entry) = 1;
@@ -341,49 +346,45 @@ build_member_function_pointer (member)
The new FIELD_DECLs are appended at the end of the last (and only)
sublist of `list_of_fieldlists.'
+ T is the signature type.
+
As a side effect, each member function in the signature gets the
`decl.ignored' bit turned on, so we don't output debug info for it. */
void
-append_signature_fields (list_of_fieldlists)
- tree list_of_fieldlists;
+append_signature_fields (t)
+ tree t;
{
- tree l, x;
- tree last_x = NULL_TREE;
+ tree x;
tree mfptr;
tree last_mfptr = NULL_TREE;
tree mfptr_list = NULL_TREE;
- /* For signatures it should actually be only a list with one element. */
- for (l = list_of_fieldlists; l; l = TREE_CHAIN (l))
+ for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
- for (x = TREE_VALUE (l); x; x = TREE_CHAIN (x))
+ if (TREE_CODE (x) == FUNCTION_DECL)
{
- if (TREE_CODE (x) == FUNCTION_DECL)
+ mfptr = build_member_function_pointer (x);
+ DECL_MEMFUNC_POINTER_TO (x) = mfptr;
+ DECL_MEMFUNC_POINTING_TO (mfptr) = x;
+ DECL_IGNORED_P (x) = 1;
+ DECL_IN_AGGR_P (mfptr) = 1;
+ if (! mfptr_list)
+ mfptr_list = last_mfptr = mfptr;
+ else
{
- mfptr = build_member_function_pointer (x);
- DECL_MEMFUNC_POINTER_TO (x) = mfptr;
- DECL_MEMFUNC_POINTING_TO (mfptr) = x;
- DECL_IGNORED_P (x) = 1;
- DECL_IN_AGGR_P (mfptr) = 1;
- if (! mfptr_list)
- mfptr_list = last_mfptr = mfptr;
- else
- {
- TREE_CHAIN (last_mfptr) = mfptr;
- last_mfptr = mfptr;
- }
+ TREE_CHAIN (last_mfptr) = mfptr;
+ last_mfptr = mfptr;
}
- last_x = x;
}
}
- /* Append the lists. */
- if (last_x && mfptr_list)
- {
- TREE_CHAIN (last_x) = mfptr_list;
- TREE_CHAIN (last_mfptr) = NULL_TREE;
- }
+ /* The member function pointers must come after the TYPE_DECLs, in
+ this case, because build_signature_table_constructor depends on
+ finding opaque TYPE_DECLS before the functions that make use of
+ them. */
+ if (last_mfptr)
+ TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), mfptr_list);
}
/* Compare the types of a signature member function and a class member
@@ -405,7 +406,7 @@ match_method_types (sig_mtype, class_mtype)
tree class_arg_types = TYPE_ARG_TYPES (class_mtype);
/* The return types have to be the same. */
- if (! comptypes (sig_return_type, class_return_type, 1))
+ if (!same_type_p (sig_return_type, class_return_type))
return 0;
/* Compare the first argument `this.' */
@@ -422,8 +423,7 @@ match_method_types (sig_mtype, class_mtype)
/* If a signature method's `this' is const or volatile, so has to be
the corresponding class method's `this.' */
- if ((TYPE_READONLY (sig_this) && ! TYPE_READONLY (class_this))
- || (TYPE_VOLATILE (sig_this) && ! TYPE_VOLATILE (class_this)))
+ if (!at_least_as_qualified_p (class_this, sig_this))
return 0;
}
@@ -431,7 +431,7 @@ match_method_types (sig_mtype, class_mtype)
class_arg_types = TREE_CHAIN (class_arg_types);
/* The number of arguments and the argument types have to be the same. */
- return compparms (sig_arg_types, class_arg_types, 3);
+ return compparms (sig_arg_types, class_arg_types);
}
/* Undo casts of opaque type variables to the RHS types. */
@@ -546,12 +546,10 @@ build_signature_table_constructor (sig_ty, rhs)
break;
if (rhs_methods == NULL_TREE
- || (compute_access (basetypes, rhs_method)
- != access_public_node))
+ || !accessible_p (basetypes, rhs_method))
{
- error ("class `%s' does not contain a method conforming to `%s'",
- TYPE_NAME_STRING (rhstype),
- fndecl_as_string (sig_method, 1));
+ cp_error ("`%T' does not contain a method conforming to `%#D'",
+ rhstype, sig_method);
undo_casts (sig_ty);
return error_mark_node;
}
@@ -886,7 +884,7 @@ build_signature_pointer_constructor (lhs, rhs)
}
else
{
- if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype))
+ if (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype))
readonly_error (lhs, "assignment", 0);
optr_expr = build_modify_expr (build_optr_ref (lhs), NOP_EXPR,
@@ -980,9 +978,8 @@ build_signature_method_call (function, parms)
tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))))
- = build_type_variant (build_pointer_type (basetype),
- TYPE_READONLY (old_this),
- TYPE_VOLATILE (old_this));
+ = build_qualified_type (build_pointer_type (basetype),
+ TYPE_QUALS (old_this));
direct_call = build_function_call (pfn, new_parms);
diff --git a/contrib/gcc/cp/spew.c b/contrib/gcc/cp/spew.c
index f153150..a573cba 100644
--- a/contrib/gcc/cp/spew.c
+++ b/contrib/gcc/cp/spew.c
@@ -1,5 +1,5 @@
/* Type Analyzer for GNU C++.
- Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
This file is part of GNU CC.
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "parse.h"
#include "flags.h"
#include "obstack.h"
+#include "toplev.h"
/* This takes a token stream that hasn't decided much about types and
tries to figure out as much as it can, with excessive lookahead and
@@ -47,7 +48,7 @@ struct token {
static int do_aggr PROTO((void));
static int probe_obstack PROTO((struct obstack *, tree, unsigned int));
-static void scan_tokens PROTO((int));
+static void scan_tokens PROTO((unsigned int));
#ifdef SPEW_DEBUG
static int num_tokens PROTO((void));
@@ -155,9 +156,9 @@ consume_token ()
static void
scan_tokens (n)
- int n;
+ unsigned int n;
{
- int i;
+ unsigned int i;
struct token *tmp;
/* We cannot read past certain tokens, so make sure we don't. */
@@ -244,7 +245,7 @@ int
yylex ()
{
struct token tmp_token;
- tree trrr;
+ tree trrr = NULL_TREE;
int old_looking_for_typename = 0;
retry:
@@ -360,6 +361,19 @@ yylex ()
break;
case SCSPEC:
+ /* If export, warn that it's unimplemented and go on. */
+ if (tmp_token.yylval.ttype == get_identifier("export"))
+ {
+ warning ("keyword 'export' not implemented and will be ignored");
+ consume_token ();
+ goto retry;
+ }
+ else
+ {
+ ++first_token;
+ break;
+ }
+
case NEW:
/* do_aggr needs to check if the previous token was RID_NEW,
so just increment first_token instead of calling consume_token. */
diff --git a/contrib/gcc/cp/tinfo.cc b/contrib/gcc/cp/tinfo.cc
index d8380da..5269cb5 100644
--- a/contrib/gcc/cp/tinfo.cc
+++ b/contrib/gcc/cp/tinfo.cc
@@ -1,5 +1,5 @@
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
-// Copyright (C) 1994, 1996 Free Software Foundation
+// Copyright (C) 1994, 1996, 1998 Free Software Foundation
// This file is part of GNU CC.
@@ -40,8 +40,8 @@ std::type_info::
{ }
// We can't rely on common symbols being shared between shared objects.
-bool type_info::
-operator== (const type_info& arg) const
+bool std::type_info::
+operator== (const std::type_info& arg) const
{
return (&arg == this) || (strcmp (name (), arg.name ()) == 0);
}
diff --git a/contrib/gcc/cp/tinfo.h b/contrib/gcc/cp/tinfo.h
index 3cfee04..e0b9eec 100644
--- a/contrib/gcc/cp/tinfo.h
+++ b/contrib/gcc/cp/tinfo.h
@@ -1,5 +1,5 @@
// RTTI support internals for -*- C++ -*-
-// Copyright (C) 1994, 1995, 1996 Free Software Foundation
+// Copyright (C) 1994, 1995, 1996, 1998 Free Software Foundation
#include "typeinfo"
@@ -40,7 +40,7 @@ struct __class_type_info : public __user_type_info {
const __user_type_info *base;
USItype offset: 29;
bool is_virtual: 1;
- access access: 2;
+ enum access access: 2;
};
const base_info *base_list;
diff --git a/contrib/gcc/cp/tinfo2.cc b/contrib/gcc/cp/tinfo2.cc
index 3e63354..b101db3 100644
--- a/contrib/gcc/cp/tinfo2.cc
+++ b/contrib/gcc/cp/tinfo2.cc
@@ -1,5 +1,5 @@
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
-// Copyright (C) 1994, 1996 Free Software Foundation
+// Copyright (C) 1994, 96-97, 1998 Free Software Foundation
// This file is part of GNU CC.
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c
index 7c7768f..866aa27 100644
--- a/contrib/gcc/cp/tree.c
+++ b/contrib/gcc/cp/tree.c
@@ -1,5 +1,5 @@
/* Language-dependent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -28,40 +28,30 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "toplev.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-extern void compiler_error ();
-
-static tree get_identifier_list PROTO((tree));
static tree bot_manip PROTO((tree));
static tree perm_manip PROTO((tree));
static tree build_cplus_array_type_1 PROTO((tree, tree));
static void list_hash_add PROTO((int, tree));
static int list_hash PROTO((tree, tree, tree));
-static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
- tree));
+static tree list_hash_lookup PROTO((int, tree, tree, tree));
static void propagate_binfo_offsets PROTO((tree, tree));
-static void unshare_base_binfos PROTO((tree));
static int avoid_overlap PROTO((tree, tree));
+static int lvalue_p_1 PROTO((tree, int));
static int equal_functions PROTO((tree, tree));
+static tree no_linkage_helper PROTO((tree));
+static tree build_srcloc PROTO((char *, int));
#define CEIL(x,y) (((x) + (y) - 1) / (y))
-/* Return nonzero if REF is an lvalue valid for this language.
- Lvalues can be assigned, unless they have TREE_READONLY.
- Lvalues can have their address taken, unless they have DECL_REGISTER. */
+/* Returns non-zero if REF is an lvalue. If
+ TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type
+ are considered lvalues. */
-int
-real_lvalue_p (ref)
+static int
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
tree ref;
+ int treat_class_rvalues_as_lvalues;
{
- if (! language_lvalue_valid (ref))
- return 0;
-
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
@@ -79,7 +69,11 @@ real_lvalue_p (ref)
case UNSAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 0));
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case NOP_EXPR:
+ return lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues);
case STRING_CST:
return 1;
@@ -93,9 +87,7 @@ real_lvalue_p (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)
+ if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
@@ -105,24 +97,43 @@ real_lvalue_p (ref)
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
- return real_lvalue_p (TREE_OPERAND (ref, 0))
- && real_lvalue_p (TREE_OPERAND (ref, 1));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues));
break;
case COND_EXPR:
- return (real_lvalue_p (TREE_OPERAND (ref, 1))
- && real_lvalue_p (TREE_OPERAND (ref, 2)));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 2),
+ treat_class_rvalues_as_lvalues));
case MODIFY_EXPR:
return 1;
case COMPOUND_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 1));
+ return lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues);
case MAX_EXPR:
case MIN_EXPR:
- return (real_lvalue_p (TREE_OPERAND (ref, 0))
- && real_lvalue_p (TREE_OPERAND (ref, 1)));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues));
+
+ case TARGET_EXPR:
+ return treat_class_rvalues_as_lvalues;
+
+ case CALL_EXPR:
+ return (treat_class_rvalues_as_lvalues
+ && IS_AGGR_TYPE (TREE_TYPE (ref)));
+
+ case FUNCTION_DECL:
+ /* All functions (except non-static-member functions) are
+ lvalues. */
+ return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref);
default:
break;
@@ -131,92 +142,26 @@ real_lvalue_p (ref)
return 0;
}
+/* Return nonzero if REF is an lvalue valid for this language.
+ Lvalues can be assigned, unless they have TREE_READONLY, or unless
+ they are FUNCTION_DECLs. Lvalues can have their address taken,
+ unless they have DECL_REGISTER. */
+
+int
+real_lvalue_p (ref)
+ tree ref;
+{
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+}
+
/* This differs from real_lvalue_p in that class rvalues are considered
lvalues. */
+
int
lvalue_p (ref)
tree ref;
{
- if (! language_lvalue_valid (ref))
- return 0;
-
- if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
- return 1;
-
- if (ref == current_class_ptr && flag_this_is_variable <= 0)
- return 0;
-
- switch (TREE_CODE (ref))
- {
- /* preincrements and predecrements are valid lvals, provided
- what they refer to are valid lvals. */
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- case COMPONENT_REF:
- case SAVE_EXPR:
- case UNSAVE_EXPR:
- case TRY_CATCH_EXPR:
- case WITH_CLEANUP_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;
- break;
-
- case TARGET_EXPR:
- return 1;
-
- case CALL_EXPR:
- if (IS_AGGR_TYPE (TREE_TYPE (ref)))
- return 1;
- break;
-
- /* A currently unresolved scope ref. */
- case SCOPE_REF:
- my_friendly_abort (103);
- case OFFSET_REF:
- if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
- return 1;
- return lvalue_p (TREE_OPERAND (ref, 0))
- && lvalue_p (TREE_OPERAND (ref, 1));
- break;
-
- case COND_EXPR:
- return (lvalue_p (TREE_OPERAND (ref, 1))
- && lvalue_p (TREE_OPERAND (ref, 2)));
-
- case MODIFY_EXPR:
- return 1;
-
- case COMPOUND_EXPR:
- return lvalue_p (TREE_OPERAND (ref, 1));
-
- case MAX_EXPR:
- case MIN_EXPR:
- return (lvalue_p (TREE_OPERAND (ref, 0))
- && lvalue_p (TREE_OPERAND (ref, 1)));
-
- default:
- break;
- }
-
- return 0;
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);
}
/* Return nonzero if REF is an lvalue valid for this language;
@@ -225,7 +170,7 @@ lvalue_p (ref)
int
lvalue_or_else (ref, string)
tree ref;
- char *string;
+ const char *string;
{
int win = lvalue_p (ref);
if (! win)
@@ -249,7 +194,7 @@ build_cplus_new (type, init)
tree rval;
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
- return init;
+ return convert (type, init);
slot = build (VAR_DECL, type);
DECL_ARTIFICIAL (slot) = 1;
@@ -431,9 +376,7 @@ build_cplus_method_type (basetype, rettype, argtypes)
TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
TREE_TYPE (t) = rettype;
if (IS_SIGNATURE (basetype))
- ptype = build_signature_pointer_type (TYPE_MAIN_VARIANT (basetype),
- TYPE_READONLY (basetype),
- TYPE_VOLATILE (basetype));
+ ptype = build_signature_pointer_type (basetype);
else
ptype = build_pointer_type (basetype);
@@ -473,7 +416,8 @@ build_cplus_array_type_1 (elt_type, index_type)
saveable_obstack = &permanent_obstack;
}
- if (processing_template_decl
+ if (processing_template_decl
+ || uses_template_parms (elt_type)
|| uses_template_parms (index_type))
{
t = make_node (ARRAY_TYPE);
@@ -498,14 +442,14 @@ build_cplus_array_type (elt_type, index_type)
tree index_type;
{
tree t;
- int constp = TYPE_READONLY (elt_type);
- int volatilep = TYPE_VOLATILE (elt_type);
+ int type_quals = CP_TYPE_QUALS (elt_type);
+
elt_type = TYPE_MAIN_VARIANT (elt_type);
t = build_cplus_array_type_1 (elt_type, index_type);
- if (constp || volatilep)
- t = cp_build_type_variant (t, constp, volatilep);
+ if (type_quals != TYPE_UNQUALIFIED)
+ t = cp_build_qualified_type (t, type_quals);
return t;
}
@@ -514,21 +458,32 @@ build_cplus_array_type (elt_type, index_type)
down to the element type of an array. */
tree
-cp_build_type_variant (type, constp, volatilep)
+cp_build_qualified_type (type, type_quals)
tree type;
- int constp, volatilep;
+ int type_quals;
{
if (type == error_mark_node)
return type;
+ /* A restrict-qualified pointer type must be a pointer (or reference)
+ to object or incomplete type. */
+ if ((type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || TYPE_PTRMEM_P (type)
+ || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
+ {
+ cp_error ("`%T' cannot be `restrict'-qualified", type);
+ type_quals &= ~TYPE_QUAL_RESTRICT;
+ }
+
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_1 (cp_build_type_variant
- (TREE_TYPE (type), constp, volatilep),
+ type = build_cplus_array_type_1 (cp_build_qualified_type
+ (TREE_TYPE (type), type_quals),
TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
@@ -545,7 +500,7 @@ cp_build_type_variant (type, constp, volatilep)
pop_obstacks ();
return type;
}
- return build_type_variant (type, constp, volatilep);
+ return build_qualified_type (type, type_quals);
}
/* Returns the canonical version of TYPE. In other words, if TYPE is
@@ -557,18 +512,7 @@ tree
canonical_type_variant (t)
tree t;
{
- int constp, volatilep;
- if (TREE_CODE (t) == ARRAY_TYPE)
- {
- constp = TYPE_READONLY (TREE_TYPE (t));
- volatilep = TYPE_VOLATILE (TREE_TYPE (t));
- }
- else
- {
- constp = TYPE_READONLY (t);
- volatilep = TYPE_VOLATILE (t);
- }
- return cp_build_type_variant (TYPE_MAIN_VARIANT (t), constp, volatilep);
+ return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), CP_TYPE_QUALS (t));
}
/* Add OFFSET to all base types of T.
@@ -618,7 +562,7 @@ propagate_binfo_offsets (binfo, offset)
BINFO_OFFSET (base_binfo) = offset;
#endif
- unshare_base_binfos (base_binfo);
+ propagate_binfo_offsets (base_binfo, offset);
/* Go to our next class that counts for offset propagation. */
i = j;
@@ -628,40 +572,35 @@ propagate_binfo_offsets (binfo, offset)
}
}
-/* Makes new binfos for the indirect bases under BASE_BINFO, and updates
+/* Makes new binfos for the indirect bases under BINFO, and updates
BINFO_OFFSET for them and their bases. */
-static void
-unshare_base_binfos (base_binfo)
- tree base_binfo;
+void
+unshare_base_binfos (binfo)
+ tree binfo;
{
- if (BINFO_BASETYPES (base_binfo))
- {
- tree base_binfos = BINFO_BASETYPES (base_binfo);
- tree chain = NULL_TREE;
- int j;
+ tree binfos = BINFO_BASETYPES (binfo);
+ tree new_binfo;
+ int j;
- /* Now unshare the structure beneath BASE_BINFO. */
- for (j = TREE_VEC_LENGTH (base_binfos)-1;
- j >= 0; j--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, j)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- base_base_binfo,
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, j);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
- }
+ if (binfos == NULL_TREE)
+ return;
- /* Completely unshare potentially shared data, and
- update what is ours. */
- propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
+ /* Now unshare the structure beneath BINFO. */
+ for (j = TREE_VEC_LENGTH (binfos)-1;
+ j >= 0; j--)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, j);
+ new_binfo = TREE_VEC_ELT (binfos, j)
+ = make_binfo (BINFO_OFFSET (base_binfo),
+ base_binfo,
+ BINFO_VTABLE (base_binfo),
+ BINFO_VIRTUALS (base_binfo));
+ TREE_VIA_PUBLIC (new_binfo) = TREE_VIA_PUBLIC (base_binfo);
+ TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
+ TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
+ BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
+ unshare_base_binfos (new_binfo);
}
}
@@ -681,9 +620,7 @@ layout_basetypes (rec, max)
tree binfos = TYPE_BINFO_BASETYPES (rec);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- /* Get all the virtual base types that this type uses.
- The TREE_VALUE slot holds the virtual baseclass type. */
- tree vbase_types = get_vbase_types (rec);
+ tree vbase_types;
unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
unsigned int desired_align;
@@ -698,7 +635,11 @@ layout_basetypes (rec, max)
record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY);
#endif
- CLASSTYPE_VBASECLASSES (rec) = vbase_types;
+ /* Get all the virtual base types that this type uses. The
+ TREE_VALUE slot holds the virtual baseclass type. Note that
+ get_vbase_types makes copies of the virtual base BINFOs, so that
+ the vbase_types are unshared. */
+ vbase_types = CLASSTYPE_VBASECLASSES (rec);
my_friendly_assert (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST, 19970302);
const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
@@ -764,10 +705,15 @@ layout_basetypes (rec, max)
continue;
my_friendly_assert (TREE_TYPE (field) == basetype, 23897);
+
+ if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
+ cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, rec);
+
BINFO_OFFSET (base_binfo)
= size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)),
BITS_PER_UNIT));
- unshare_base_binfos (base_binfo);
+ propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
TYPE_FIELDS (rec) = TREE_CHAIN (field);
}
@@ -776,6 +722,15 @@ layout_basetypes (rec, max)
{
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
unshare_base_binfos (vbase_types);
+ propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
+
+ if (extra_warnings)
+ {
+ tree basetype = BINFO_TYPE (vbase_types);
+ if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
+ cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, rec);
+ }
}
return max;
@@ -851,7 +806,7 @@ build_base_fields (rec)
base_align = MAX (base_align, DECL_ALIGN (decl));
DECL_SIZE (decl)
= size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
- base_align));
+ (int) base_align));
}
else if (DECL_SIZE (decl) == integer_zero_node)
saw_empty = 1;
@@ -925,8 +880,7 @@ build_vbase_pointer_fields (rec)
if (TREE_VIA_VIRTUAL (base_binfo))
{
int j;
- char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype)
- + sizeof (VBASE_NAME) + 1);
+ const char *name;
/* The offset for a virtual base class is only used in computing
virtual function tables and for initializing virtual base
@@ -946,7 +900,7 @@ build_vbase_pointer_fields (rec)
))
goto got_it;
}
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
+ FORMAT_VBASE_NAME (name, basetype);
decl = build_lang_field_decl (FIELD_DECL, get_identifier (name),
build_pointer_type (basetype));
/* If you change any of the below, take a look at all the
@@ -1024,18 +978,14 @@ list_hash (purpose, value, chain)
If one is found, return it. Otherwise return 0. */
static tree
-list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
- purpose, value, chain)
- int hashcode, via_public, via_virtual, via_protected;
+list_hash_lookup (hashcode, purpose, value, chain)
+ int hashcode;
tree purpose, value, chain;
{
register struct list_hash *h;
for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == via_virtual
- && TREE_VIA_PUBLIC (h->list) == via_public
- && TREE_VIA_PROTECTED (h->list) == via_protected
&& TREE_PURPOSE (h->list) == purpose
&& TREE_VALUE (h->list) == value
&& TREE_CHAIN (h->list) == chain)
@@ -1060,24 +1010,16 @@ list_hash_add (hashcode, list)
list_hash_table[hashcode % TYPE_HASH_SIZE] = h;
}
-/* Given TYPE, and HASHCODE its hash code, return the canonical
- object for an identical list if one already exists.
- Otherwise, return TYPE, and record it as the canonical object
- if it is a permanent object.
-
- To use this function, first create a list of the sort you want.
- Then compute its hash code from the fields of the list that
- make it different from other similar lists.
- Then call this function and use the value.
- This function frees the list you pass in if it is a duplicate. */
+/* Given list components PURPOSE, VALUE, AND CHAIN, return the canonical
+ object for an identical list if one already exists. Otherwise, build a
+ new one, and record it as the canonical object. */
/* Set to 1 to debug without canonicalization. Never set by program. */
static int debug_no_list_hash = 0;
tree
-hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
- int via_public, via_virtual, via_protected;
+hash_tree_cons (purpose, value, chain)
tree purpose, value, chain;
{
struct obstack *ambient_obstack = current_obstack;
@@ -1087,8 +1029,7 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
if (! debug_no_list_hash)
{
hashcode = list_hash (purpose, value, chain);
- t = list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
- purpose, value, chain);
+ t = list_hash_lookup (hashcode, purpose, value, chain);
if (t)
return t;
}
@@ -1096,9 +1037,6 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
current_obstack = &class_obstack;
t = tree_cons (purpose, value, chain);
- TREE_VIA_PUBLIC (t) = via_public;
- TREE_VIA_PROTECTED (t) = via_protected;
- TREE_VIA_VIRTUAL (t) = via_virtual;
/* If this is a new list, record it for later reuse. */
if (! debug_no_list_hash)
@@ -1114,7 +1052,7 @@ tree
hash_tree_chain (value, chain)
tree value, chain;
{
- return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
+ return hash_tree_cons (NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */
@@ -1132,60 +1070,6 @@ hash_chainon (list1, list2)
return hash_tree_chain (TREE_VALUE (list1),
hash_chainon (TREE_CHAIN (list1), list2));
}
-
-static tree
-get_identifier_list (value)
- tree value;
-{
- tree list = IDENTIFIER_AS_LIST (value);
- if (list != NULL_TREE
- && (TREE_CODE (list) != TREE_LIST
- || TREE_VALUE (list) != value))
- list = NULL_TREE;
- else if (IDENTIFIER_HAS_TYPE_VALUE (value)
- && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE
- && IDENTIFIER_TYPE_VALUE (value)
- == TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (value)))
- {
- tree type = IDENTIFIER_TYPE_VALUE (value);
-
- if (TYPE_PTRMEMFUNC_P (type))
- list = NULL_TREE;
- else if (type == current_class_type)
- /* Don't mess up the constructor name. */
- list = tree_cons (NULL_TREE, value, NULL_TREE);
- else
- {
- if (! CLASSTYPE_ID_AS_LIST (type))
- CLASSTYPE_ID_AS_LIST (type)
- = perm_tree_cons (NULL_TREE, TYPE_IDENTIFIER (type), NULL_TREE);
- list = CLASSTYPE_ID_AS_LIST (type);
- }
- }
- return list;
-}
-
-tree
-get_decl_list (value)
- tree value;
-{
- tree list = NULL_TREE;
-
- if (TREE_CODE (value) == IDENTIFIER_NODE)
- list = get_identifier_list (value);
- else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value)
- && value == TYPE_MAIN_VARIANT (value))
- list = CLASSTYPE_AS_LIST (value);
-
- if (list != NULL_TREE)
- {
- my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 301);
- return list;
- }
-
- return build_decl_list (NULL_TREE, value);
-}
/* Build an association between TYPE and some parameters:
@@ -1200,15 +1084,12 @@ get_decl_list (value)
VTABLE is the virtual function table with which to initialize
sub-objects of type TYPE.
- VIRTUALS are the virtual functions sitting in VTABLE.
-
- CHAIN are more associations we must retain. */
+ VIRTUALS are the virtual functions sitting in VTABLE. */
tree
-make_binfo (offset, binfo, vtable, virtuals, chain)
+make_binfo (offset, binfo, vtable, virtuals)
tree offset, binfo;
tree vtable, virtuals;
- tree chain;
{
tree new_binfo = make_tree_vec (7);
tree type;
@@ -1218,13 +1099,9 @@ make_binfo (offset, binfo, vtable, virtuals, chain)
else
{
type = binfo;
- binfo = TYPE_BINFO (binfo);
+ binfo = CLASS_TYPE_P (type) ? TYPE_BINFO (binfo) : NULL_TREE;
}
- TREE_CHAIN (new_binfo) = chain;
- if (chain)
- TREE_USED (new_binfo) = TREE_USED (chain);
-
TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
BINFO_OFFSET (new_binfo) = offset;
BINFO_VTABLE (new_binfo) = vtable;
@@ -1253,17 +1130,24 @@ binfo_value (elem, type)
return get_binfo (elem, type, 0);
}
+/* Return a reversed copy of the BINFO-chain given by PATH. (If the
+ BINFO_INHERITANCE_CHAIN points from base classes to derived
+ classes, it will instead point from derived classes to base
+ classes.) Returns the first node in the reversed chain. */
+
tree
reverse_path (path)
tree path;
{
- register tree prev = 0, tmp, next;
- for (tmp = path; tmp; tmp = next)
+ register tree prev = NULL_TREE, cur;
+ push_expression_obstack ();
+ for (cur = path; cur; cur = BINFO_INHERITANCE_CHAIN (cur))
{
- next = BINFO_INHERITANCE_CHAIN (tmp);
- BINFO_INHERITANCE_CHAIN (tmp) = prev;
- prev = tmp;
+ tree r = copy_node (cur);
+ BINFO_INHERITANCE_CHAIN (r) = prev;
+ prev = r;
}
+ pop_obstacks ();
return prev;
}
@@ -1286,7 +1170,7 @@ debug_binfo (elem)
fprintf (stderr, "virtuals:\n");
virtuals = BINFO_VIRTUALS (elem);
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, BINFO_TYPE (elem));
while (virtuals)
{
@@ -1340,15 +1224,11 @@ int
is_overloaded_fn (x)
tree x;
{
- /* XXX A baselink is also considered an overloaded function.
- As is a placeholder from push_class_decls. */
- if (TREE_CODE (x) == TREE_LIST)
- {
- my_friendly_assert (TREE_CODE (TREE_PURPOSE (x)) == TREE_VEC
- || TREE_CODE (TREE_PURPOSE (x)) == IDENTIFIER_NODE,
- 388);
- x = TREE_VALUE (x);
- }
+ /* A baselink is also considered an overloaded function. */
+ if (TREE_CODE (x) == OFFSET_REF)
+ x = TREE_OPERAND (x, 1);
+ if (BASELINK_P (x))
+ x = TREE_VALUE (x);
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (x)
@@ -1359,9 +1239,10 @@ int
really_overloaded_fn (x)
tree x;
{
- /* A baselink is also considered an overloaded function.
- This might also be an ambiguous class member. */
- if (TREE_CODE (x) == TREE_LIST)
+ /* A baselink is also considered an overloaded function. */
+ if (TREE_CODE (x) == OFFSET_REF)
+ x = TREE_OPERAND (x, 1);
+ if (BASELINK_P (x))
x = TREE_VALUE (x);
return (TREE_CODE (x) == OVERLOAD
&& (TREE_CHAIN (x) != NULL_TREE
@@ -1374,11 +1255,22 @@ get_first_fn (from)
{
my_friendly_assert (is_overloaded_fn (from), 9);
/* A baselink is also considered an overloaded function. */
- if (TREE_CODE (from) == TREE_LIST)
+ if (BASELINK_P (from))
from = TREE_VALUE (from);
return OVL_CURRENT (from);
}
+/* Returns nonzero if T is a ->* or .* expression that refers to a
+ member function. */
+
+int
+bound_pmf_p (t)
+ tree t;
+{
+ return (TREE_CODE (t) == OFFSET_REF
+ && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
+}
+
/* Return a new OVL node, concatenating it with the old one. */
tree
@@ -1417,9 +1309,9 @@ build_overload (decl, chain)
tree decl;
tree chain;
{
- if (!chain)
+ if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)
return decl;
- if (TREE_CODE (chain) != OVERLOAD)
+ if (chain && TREE_CODE (chain) != OVERLOAD)
chain = ovl_cons (chain, NULL_TREE);
return ovl_cons (decl, chain);
}
@@ -1518,21 +1410,26 @@ build_exception_variant (type, raises)
tree raises;
{
tree v = TYPE_MAIN_VARIANT (type);
- int constp = TYPE_READONLY (type);
- int volatilep = TYPE_VOLATILE (type);
+ int type_quals = TYPE_QUALS (type);
for (; v; v = TYPE_NEXT_VARIANT (v))
{
- if (TYPE_READONLY (v) != constp
- || TYPE_VOLATILE (v) != volatilep)
+ tree t;
+ tree u;
+
+ if (TYPE_QUALS (v) != type_quals)
continue;
- /* @@ This should do set equality, not exact match. */
- if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
- /* List of exceptions raised matches previously found list.
+ for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
+ t != NULL_TREE && u != NULL_TREE;
+ t = TREE_CHAIN (t), u = TREE_CHAIN (u))
+ if (((TREE_VALUE (t) != NULL_TREE)
+ != (TREE_VALUE (u) != NULL_TREE))
+ || !same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
+ break;
- @@ Nice to free up storage used in consing up the
- @@ list of exceptions raised. */
+ if (!t && !u)
+ /* There's a memory leak here; RAISES is not freed. */
return v;
}
@@ -1540,12 +1437,7 @@ build_exception_variant (type, raises)
v = build_type_copy (type);
if (raises && ! TREE_PERMANENT (raises))
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- raises = copy_list (raises);
- pop_obstacks ();
- }
+ raises = copy_to_permanent (raises);
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
@@ -1559,29 +1451,39 @@ copy_template_template_parm (t)
tree t;
{
tree template = TYPE_NAME (t);
- tree t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+ tree t2;
+
+ /* Make sure these end up on the permanent_obstack. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
template = copy_node (template);
copy_lang_decl (template);
+
+ pop_obstacks ();
+
TREE_TYPE (template) = t2;
TYPE_NAME (t2) = template;
TYPE_STUB_DECL (t2) = template;
/* No need to copy these */
TYPE_FIELDS (t2) = TYPE_FIELDS (t);
- CLASSTYPE_TEMPLATE_INFO (t2) = CLASSTYPE_TEMPLATE_INFO (t);
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
+ = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t);
return t2;
}
-/* Subroutine of copy_to_permanent
-
- Assuming T is a node build bottom-up, make it all exist on
- permanent obstack, if it is not permanent already. */
+/* Walk through the tree structure T, applying func. If func ever returns
+ non-null, return that value. */
tree
-mapcar (t, func)
+search_tree (t, func)
tree t;
tree (*func) PROTO((tree));
{
+#define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp
+
tree tmp;
if (t == NULL_TREE)
@@ -1593,6 +1495,259 @@ mapcar (t, func)
switch (TREE_CODE (t))
{
case ERROR_MARK:
+ break;
+
+ case IDENTIFIER_NODE:
+ break;
+
+ case VAR_DECL:
+ case FUNCTION_DECL:
+ case CONST_DECL:
+ case TEMPLATE_DECL:
+ case NAMESPACE_DECL:
+ break;
+
+ case TYPE_DECL:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case PARM_DECL:
+ TRY (TREE_TYPE (t));
+ TRY (TREE_CHAIN (t));
+ break;
+
+ case TREE_LIST:
+ TRY (TREE_PURPOSE (t));
+ TRY (TREE_VALUE (t));
+ TRY (TREE_CHAIN (t));
+ break;
+
+ case OVERLOAD:
+ TRY (OVL_FUNCTION (t));
+ TRY (OVL_CHAIN (t));
+ break;
+
+ case TREE_VEC:
+ {
+ int len = TREE_VEC_LENGTH (t);
+
+ t = copy_node (t);
+ while (len--)
+ TRY (TREE_VEC_ELT (t, len));
+ }
+ break;
+
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ case DEFAULT_ARG:
+ break;
+
+ case PTRMEM_CST:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case COND_EXPR:
+ case TARGET_EXPR:
+ case AGGR_INIT_EXPR:
+ case NEW_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ TRY (TREE_OPERAND (t, 1));
+ TRY (TREE_OPERAND (t, 2));
+ break;
+
+ case MODIFY_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case MIN_EXPR:
+ case MAX_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_ANDTC_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case CEIL_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ case COMPOUND_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case ARRAY_REF:
+ case SCOPE_REF:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
+ case CALL_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ TRY (TREE_OPERAND (t, 1));
+ break;
+
+ case SAVE_EXPR:
+ case CONVERT_EXPR:
+ case ADDR_EXPR:
+ case INDIRECT_REF:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case NOP_EXPR:
+ case NON_LVALUE_EXPR:
+ case COMPONENT_REF:
+ case CLEANUP_POINT_EXPR:
+ case LOOKUP_EXPR:
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ break;
+
+ case MODOP_EXPR:
+ case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case ARROW_EXPR:
+ case DOTSTAR_EXPR:
+ case TYPEID_EXPR:
+ break;
+
+ case COMPLEX_CST:
+ TRY (TREE_REALPART (t));
+ TRY (TREE_IMAGPART (t));
+ break;
+
+ case CONSTRUCTOR:
+ TRY (CONSTRUCTOR_ELTS (t));
+ break;
+
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ case TEMPLATE_TYPE_PARM:
+ break;
+
+ case BIND_EXPR:
+ break;
+
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ case TYPENAME_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ case TYPEOF_TYPE:
+ break;
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_ARG_TYPES (t));
+ break;
+
+ case ARRAY_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_DOMAIN (t));
+ break;
+
+ case INTEGER_TYPE:
+ TRY (TYPE_MAX_VALUE (t));
+ break;
+
+ case OFFSET_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_OFFSET_BASETYPE (t));
+ break;
+
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (t))
+ TRY (TYPE_PTRMEMFUNC_FN_TYPE (t));
+ break;
+
+ /* This list is incomplete, but should suffice for now.
+ It is very important that `sorry' not call
+ `report_error_function'. That could cause an infinite loop. */
+ default:
+ sorry ("initializer contains unrecognized tree code");
+ return error_mark_node;
+
+ }
+
+ return NULL_TREE;
+
+#undef TRY
+}
+
+/* Passed to search_tree. Checks for the use of types with no linkage. */
+
+static tree
+no_linkage_helper (t)
+ tree t;
+{
+ if (TYPE_P (t)
+ && (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
+ && (decl_function_context (TYPE_MAIN_DECL (t))
+ || ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
+ return t;
+ return NULL_TREE;
+}
+
+/* Check if the type T depends on a type with no linkage and if so, return
+ it. */
+
+tree
+no_linkage_check (t)
+ tree t;
+{
+ t = search_tree (t, no_linkage_helper);
+ if (t != error_mark_node)
+ return t;
+ return NULL_TREE;
+}
+
+
+/* Make copies of all the nodes below T. If FUNC is non-NULL, call it
+ for each node. */
+
+tree
+mapcar (t, func)
+ tree t;
+ tree (*func) PROTO((tree));
+{
+ tree tmp;
+
+ if (t == NULL_TREE)
+ return t;
+
+ if (func)
+ {
+ tmp = func (t);
+ if (tmp)
+ return tmp;
+ }
+
+ switch (TREE_CODE (t))
+ {
+ case ERROR_MARK:
return error_mark_node;
case VAR_DECL:
@@ -1608,11 +1763,13 @@ mapcar (t, func)
void g() { const int i = 7; f<i>(7); }
however, we must actually return the constant initializer. */
- tmp = decl_constant_value (t);
- if (tmp != t)
- return mapcar (tmp, func);
- else
- return error_mark_node;
+ if (TREE_READONLY_DECL_P (t))
+ {
+ tmp = decl_constant_value (t);
+ if (tmp != t)
+ return mapcar (tmp, func);
+ }
+ return error_mark_node;
case PARM_DECL:
{
@@ -1659,6 +1816,12 @@ mapcar (t, func)
case STRING_CST:
return copy_node (t);
+ case PTRMEM_CST:
+ t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+ PTRMEM_CST_MEMBER (t) = mapcar (PTRMEM_CST_MEMBER (t), func);
+ return t;
+
case COND_EXPR:
case TARGET_EXPR:
case AGGR_INIT_EXPR:
@@ -1722,7 +1885,7 @@ mapcar (t, func)
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
/* tree.def says that operand two is RTL, but
- build_call_declarator puts trees in there. */
+ make_call_declarator puts trees in there. */
if (TREE_OPERAND (t, 2)
&& TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
@@ -1739,37 +1902,39 @@ mapcar (t, func)
case NOP_EXPR:
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
+ case NON_LVALUE_EXPR:
t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
case POINTER_TYPE:
tmp = build_pointer_type (mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case REFERENCE_TYPE:
tmp = build_reference_type (mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case FUNCTION_TYPE:
tmp = build_function_type (mapcar (TREE_TYPE (t), func),
mapcar (TYPE_ARG_TYPES (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case ARRAY_TYPE:
tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func),
mapcar (TYPE_DOMAIN (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, CP_TYPE_QUALS (t));
case INTEGER_TYPE:
tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case OFFSET_TYPE:
tmp = build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func),
mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case METHOD_TYPE:
tmp = build_cplus_method_type
(mapcar (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), func),
mapcar (TREE_TYPE (t), func),
mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case COMPLEX_CST:
t = copy_node (t);
@@ -1799,6 +1964,11 @@ mapcar (t, func)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
return t;
+ case LOOKUP_EXPR:
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ return t;
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
@@ -1818,6 +1988,16 @@ mapcar (t, func)
return NULL_TREE;
}
+/* Returns T if T is allocated on the permanent obstack, NULL_TREE
+ otherwise. */
+
+tree
+permanent_p (t)
+ tree t;
+{
+ return TREE_PERMANENT (t) ? t : NULL_TREE;
+}
+
static tree
perm_manip (t)
tree t;
@@ -1885,17 +2065,10 @@ print_lang_statistics ()
void
__eprintf (string, expression, line, filename)
-#ifdef __STDC__
const char *string;
const char *expression;
unsigned line;
const char *filename;
-#else
- char *string;
- char *expression;
- unsigned line;
- char *filename;
-#endif
{
fprintf (stderr, string, expression, line, filename);
fflush (stderr);
@@ -2037,7 +2210,7 @@ build_min VPROTO((enum tree_code code, tree tt, ...))
t = make_node (code);
length = tree_code_length[(int) code];
- TREE_TYPE (t) = tt;
+ TREE_TYPE (t) = copy_to_permanent (tt);
TREE_COMPLEXITY (t) = lineno;
for (i = 0; i < length; i++)
@@ -2114,7 +2287,7 @@ vec_binfo_member (elem, vec)
if (vec)
for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
- if (comptypes (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i)), 1))
+ if (same_type_p (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i))))
return TREE_VEC_ELT (vec, i);
return NULL_TREE;
@@ -2134,6 +2307,24 @@ hack_decl_function_context (decl)
return decl_function_context (decl);
}
+/* Returns the namespace that contains DECL, whether directly or
+ indirectly. */
+
+tree
+decl_namespace_context (decl)
+ tree decl;
+{
+ while (1)
+ {
+ if (TREE_CODE (decl) == NAMESPACE_DECL)
+ return decl;
+ else if (TYPE_P (decl))
+ decl = CP_DECL_CONTEXT (TYPE_MAIN_DECL (decl));
+ else
+ decl = CP_DECL_CONTEXT (decl);
+ }
+}
+
/* Return truthvalue of whether T1 is the same tree structure as T2.
Return 1 if they are the same.
Return 0 if they are understandably different.
@@ -2187,7 +2378,7 @@ cp_tree_equal (t1, t2)
/* We need to do this when determining whether or not two
non-type pointer to member function template arguments
are the same. */
- if (!(comptypes (TREE_TYPE (t1), TREE_TYPE (t2), 1)
+ if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
/* The first operand is RTL. */
&& TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
return 0;
@@ -2255,9 +2446,15 @@ cp_tree_equal (t1, t2)
if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
return 0;
if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't')
- return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
+ return same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
break;
+ case PTRMEM_CST:
+ /* Two pointer-to-members are the same if they point to the same
+ field or function in the same class. */
+ return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2)
+ && same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2)));
+
default:
break;
}
@@ -2284,17 +2481,17 @@ cp_tree_equal (t1, t2)
return -1;
}
-/* Similar to make_tree_vec, but build on a temporary obstack. */
+/* Similar to make_tree_vec, but build on the momentary_obstack.
+ Thus, these vectors are really and truly temporary. */
tree
make_temp_vec (len)
int len;
{
register tree node;
- register struct obstack *ambient_obstack = current_obstack;
- current_obstack = expression_obstack;
+ push_expression_obstack ();
node = make_tree_vec (len);
- current_obstack = ambient_obstack;
+ pop_obstacks ();
return node;
}
@@ -2333,7 +2530,7 @@ build_int_wrapper (i)
return t;
}
-tree
+static tree
build_srcloc (file, line)
char *file;
int line;
@@ -2378,8 +2575,7 @@ lvalue_type (arg)
tree type = TREE_TYPE (arg);
if (TREE_CODE (arg) == OVERLOAD)
type = unknown_type_node;
- return cp_build_type_variant
- (type, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
+ return type;
}
/* The type of ARG for printing error messages; denote lvalues with
@@ -2422,3 +2618,194 @@ member_p (decl)
tree ctx = DECL_CONTEXT (decl);
return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't');
}
+
+/* Create a placeholder for member access where we don't actually have an
+ object that the access is against. */
+
+tree
+build_dummy_object (type)
+ tree type;
+{
+ tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
+ return build_indirect_ref (decl, NULL_PTR);
+}
+
+/* We've gotten a reference to a member of TYPE. Return *this if appropriate,
+ or a dummy object otherwise. If BINFOP is non-0, it is filled with the
+ binfo path from current_class_type to TYPE, or 0. */
+
+tree
+maybe_dummy_object (type, binfop)
+ tree type;
+ tree *binfop;
+{
+ tree decl, context;
+
+ if (current_class_type
+ && get_base_distance (type, current_class_type, 0, binfop) != -1)
+ context = current_class_type;
+ else
+ {
+ /* Reference from a nested class member function. */
+ context = type;
+ if (binfop)
+ *binfop = TYPE_BINFO (type);
+ }
+
+ if (current_class_ref && context == current_class_type)
+ decl = current_class_ref;
+ else
+ decl = build_dummy_object (context);
+
+ return decl;
+}
+
+/* Returns 1 if OB is a placeholder object, or a pointer to one. */
+
+int
+is_dummy_object (ob)
+ tree ob;
+{
+ if (TREE_CODE (ob) == INDIRECT_REF)
+ ob = TREE_OPERAND (ob, 0);
+ return (TREE_CODE (ob) == NOP_EXPR
+ && TREE_OPERAND (ob, 0) == void_zero_node);
+}
+
+/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
+
+int
+pod_type_p (t)
+ tree t;
+{
+ tree f;
+
+ while (TREE_CODE (t) == ARRAY_TYPE)
+ t = TREE_TYPE (t);
+
+ if (! IS_AGGR_TYPE (t))
+ return 1;
+
+ if (CLASSTYPE_NON_AGGREGATE (t)
+ || TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+ || TYPE_HAS_DESTRUCTOR (t))
+ return 0;
+
+ for (f = TYPE_FIELDS (t); f; f = TREE_CHAIN (f))
+ {
+ if (TREE_CODE (f) != FIELD_DECL)
+ continue;
+
+ if (TREE_CODE (TREE_TYPE (f)) == REFERENCE_TYPE
+ || TYPE_PTRMEMFUNC_P (TREE_TYPE (f))
+ || TYPE_PTRMEM_P (TREE_TYPE (f)))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid C++-specific
+ attribute for either declaration DECL or type TYPE and 0 otherwise.
+ Plugged into valid_lang_attribute. */
+
+int
+cp_valid_lang_attribute (attr_name, attr_args, decl, type)
+ tree attr_name;
+ tree attr_args ATTRIBUTE_UNUSED;
+ tree decl ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+{
+ if (is_attribute_p ("com_interface", attr_name))
+ {
+ if (! flag_vtable_thunks)
+ {
+ error ("`com_interface' only supported with -fvtable-thunks");
+ return 0;
+ }
+
+ if (attr_args != NULL_TREE
+ || decl != NULL_TREE
+ || ! CLASS_TYPE_P (type)
+ || type != TYPE_MAIN_VARIANT (type))
+ {
+ warning ("`com_interface' attribute can only be applied to class definitions");
+ return 0;
+ }
+
+ CLASSTYPE_COM_INTERFACE (type) = 1;
+ return 1;
+ }
+ else if (is_attribute_p ("init_priority", attr_name))
+ {
+ tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE);
+ int pri;
+
+ if (initp_expr)
+ STRIP_NOPS (initp_expr);
+
+ if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
+ {
+ error ("requested init_priority is not an integer constant");
+ return 0;
+ }
+
+ pri = TREE_INT_CST_LOW (initp_expr);
+
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ if (decl == NULL_TREE
+ || TREE_CODE (decl) != VAR_DECL
+ || ! TREE_STATIC (decl)
+ || DECL_EXTERNAL (decl)
+ || (TREE_CODE (type) != RECORD_TYPE
+ && TREE_CODE (type) != UNION_TYPE)
+ /* Static objects in functions are initialized the
+ first time control passes through that
+ function. This is not precise enough to pin down an
+ init_priority value, so don't allow it. */
+ || current_function_decl)
+ {
+ error ("can only use init_priority attribute on file-scope definitions of objects of class type");
+ return 0;
+ }
+
+ if (pri > MAX_INIT_PRIORITY || pri <= 0)
+ {
+ error ("requested init_priority is out of range");
+ return 0;
+ }
+
+ /* Check for init_priorities that are reserved for
+ language and runtime support implementations.*/
+ if (pri <= MAX_RESERVED_INIT_PRIORITY)
+ {
+ warning
+ ("requested init_priority is reserved for internal use");
+ }
+
+ DECL_INIT_PRIORITY (decl) = pri;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
+ thing pointed to by the constant. */
+
+tree
+make_ptrmem_cst (type, member)
+ tree type;
+ tree member;
+{
+ tree ptrmem_cst = make_node (PTRMEM_CST);
+ /* If would seem a great convenience if make_node would set
+ TREE_CONSTANT for things of class `c', but it does not. */
+ TREE_CONSTANT (ptrmem_cst) = 1;
+ TREE_TYPE (ptrmem_cst) = type;
+ PTRMEM_CST_MEMBER (ptrmem_cst) = member;
+ return ptrmem_cst;
+}
+
diff --git a/contrib/gcc/cp/typeck.c b/contrib/gcc/cp/typeck.c
index 4e1d4fd..d0743e9 100644
--- a/contrib/gcc/cp/typeck.c
+++ b/contrib/gcc/cp/typeck.c
@@ -1,5 +1,5 @@
/* Build expressions with type checking for C++ compiler.
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -39,9 +39,7 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "toplev.h"
-extern void compiler_error ();
-
-static tree convert_for_assignment PROTO((tree, tree, char*, tree,
+static tree convert_for_assignment PROTO((tree, tree, const char *, tree,
int));
static tree pointer_int_sum PROTO((enum tree_code, tree, tree));
static tree rationalize_conditional_expr PROTO((enum tree_code, tree));
@@ -51,15 +49,16 @@ static int comp_ptr_ttypes_const PROTO((tree, tree));
static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
static int comp_array_types PROTO((int (*) (tree, tree, int), tree,
tree, int));
-static tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree));
static tree common_base_type PROTO((tree, tree));
#if 0
static tree convert_sequence PROTO((tree, tree));
#endif
static tree lookup_anon_field PROTO((tree, tree));
static tree pointer_diff PROTO((tree, tree, tree));
+static tree build_component_addr PROTO((tree, tree));
static tree qualify_type PROTO((tree, tree));
static tree get_delta_difference PROTO((tree, tree, int));
+static int comp_cv_target_types PROTO((tree, tree, int));
/* Return the target type of TYPE, which meas return T for:
T*, T&, T[], T (...), and otherwise, just T. */
@@ -80,7 +79,9 @@ target_type (type)
}
/* Do `exp = require_complete_type (exp);' to make sure exp
- does not have an incomplete type. (That includes void types.) */
+ does not have an incomplete type. (That includes void types.)
+ Returns the error_mark_node if the VALUE does not have
+ complete type when this function returns. */
tree
require_complete_type (value)
@@ -88,7 +89,7 @@ require_complete_type (value)
{
tree type;
- if (processing_template_decl)
+ if (processing_template_decl || value == error_mark_node)
return value;
if (TREE_CODE (value) == OVERLOAD)
@@ -98,7 +99,7 @@ require_complete_type (value)
/* First, detect a valid value with a complete type. */
if (TYPE_SIZE (type) != 0
- && type != void_type_node
+ && TYPE_SIZE (type) != size_zero_node
&& ! (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))
&& TYPE_SIZE (SIGNATURE_TYPE (type)) == 0))
@@ -120,13 +121,103 @@ require_complete_type (value)
return require_complete_type (value);
}
- if (TYPE_SIZE (complete_type (type)))
+ if (complete_type_or_else (type, value))
return value;
else
+ return error_mark_node;
+}
+
+/* Makes sure EXPR is a complete type when used in a void context, like a
+ whole expression, or lhs of a comma operator. Issue a diagnostic and
+ return error_mark_node on failure. This is a little tricky, because some
+ valid void types look stunningly similar to invalid void types. We err on
+ the side of caution */
+
+tree
+require_complete_type_in_void (expr)
+ tree expr;
+{
+ switch (TREE_CODE (expr))
{
- incomplete_type_error (value, type);
- return error_mark_node;
+ case COND_EXPR:
+ {
+ tree op;
+
+ op = TREE_OPERAND (expr,2);
+ op = require_complete_type_in_void (op);
+ TREE_OPERAND (expr,2) = op;
+ if (op == error_mark_node)
+ {
+ expr = op;
+ break;
+ }
+
+ /* fallthrough */
+ }
+
+ case COMPOUND_EXPR:
+ {
+ tree op;
+
+ op = TREE_OPERAND (expr,1);
+ op = require_complete_type_in_void (op);
+ TREE_OPERAND (expr,1) = op;
+ if (op == error_mark_node)
+ {
+ expr = op;
+ break;
+ }
+
+ break;
+ }
+
+ case NON_LVALUE_EXPR:
+ case NOP_EXPR:
+ {
+ tree op;
+
+ op = TREE_OPERAND (expr,0);
+ op = require_complete_type_in_void (op);
+ TREE_OPERAND (expr,0) = op;
+ if (op == error_mark_node)
+ {
+ expr = op;
+ break;
+ }
+ break;
+ }
+
+ case CALL_EXPR: /* function call return can be ignored */
+ case RTL_EXPR: /* RTL nodes have no value */
+ case DELETE_EXPR: /* delete expressions have no type */
+ case VEC_DELETE_EXPR:
+ case INTEGER_CST: /* used for null pointer */
+ case EXIT_EXPR: /* have no return */
+ case LOOP_EXPR: /* have no return */
+ case BIND_EXPR: /* have no return */
+ case THROW_EXPR: /* have no return */
+ case MODIFY_EXPR: /* sometimes this has a void type, but that's ok */
+ case CONVERT_EXPR: /* sometimes has a void type */
+ break;
+
+ case INDIRECT_REF:
+ {
+ tree op = TREE_OPERAND (expr,0);
+
+ /* Calling a function returning a reference has an implicit
+ dereference applied. We don't want to make that an error. */
+ if (TREE_CODE (op) == CALL_EXPR
+ && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE)
+ break;
+ /* else fallthrough */
+ }
+
+ default:
+ expr = require_complete_type (expr);
+ break;
}
+
+ return expr;
}
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
@@ -155,24 +246,28 @@ complete_type (type)
TYPE_NEEDS_DESTRUCTOR (type)
= TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
}
- else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
instantiate_class_template (TYPE_MAIN_VARIANT (type));
return type;
}
/* Like complete_type, but issue an error if the TYPE cannot be
- completed. Returns NULL_TREE if the type cannot be made
- complete. */
+ completed. VALUE is used for informative diagnostics.
+ Returns NULL_TREE if the type cannot be made complete. */
tree
-complete_type_or_else (type)
+complete_type_or_else (type, value)
tree type;
+ tree value;
{
type = complete_type (type);
- if (type != error_mark_node && !TYPE_SIZE (type))
+ if (type == error_mark_node)
+ /* We already issued an error. */
+ return NULL_TREE;
+ else if (!TYPE_SIZE (type) || TYPE_SIZE (type) == size_zero_node)
{
- incomplete_type_error (NULL_TREE, type);
+ incomplete_type_error (value, type);
return NULL_TREE;
}
else
@@ -204,32 +299,6 @@ fntype_p (t)
|| TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)));
}
-/* Do `exp = require_instantiated_type (type, exp);' to make sure EXP
- does not have an uninstantiated type.
- TYPE is type to instantiate with, if uninstantiated. */
-
-tree
-require_instantiated_type (type, exp, errval)
- tree type, exp, errval;
-{
- if (TREE_TYPE (exp) == NULL_TREE)
- {
- error ("argument list may not have an initializer list");
- return errval;
- }
-
- if (TREE_CODE (exp) == OVERLOAD
- || TREE_TYPE (exp) == unknown_type_node
- || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE
- && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node))
- {
- exp = instantiate_type (type, exp, 1);
- if (TREE_TYPE (exp) == error_mark_node)
- return errval;
- }
- return exp;
-}
-
/* Return a variant of TYPE which has all the type qualifiers of LIKE
as well as those of TYPE. */
@@ -237,10 +306,9 @@ static tree
qualify_type (type, like)
tree type, like;
{
- int constflag = TYPE_READONLY (type) || TYPE_READONLY (like);
- int volflag = TYPE_VOLATILE (type) || TYPE_VOLATILE (like);
/* @@ Must do member pointers here. */
- return cp_build_type_variant (type, constflag, volflag);
+ return cp_build_qualified_type (type, (CP_TYPE_QUALS (type)
+ | CP_TYPE_QUALS (like)));
}
/* Return the common type of two parameter lists.
@@ -494,16 +562,33 @@ common_type (t1, t2)
But ANSI C++ specifies doing this with the qualifiers.
So I turned it on again. */
{
- tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1));
- tree tt2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2));
- int constp
- = TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
- int volatilep
- = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
+ tree tt1 = TREE_TYPE (t1);
+ tree tt2 = TREE_TYPE (t2);
+ tree b1, b2;
+ int type_quals;
tree target;
+ if (TREE_CODE (tt1) == OFFSET_TYPE)
+ {
+ b1 = TYPE_OFFSET_BASETYPE (tt1);
+ b2 = TYPE_OFFSET_BASETYPE (tt2);
+ tt1 = TREE_TYPE (tt1);
+ tt2 = TREE_TYPE (tt2);
+ }
+ else
+ b1 = b2 = NULL_TREE;
+
+ type_quals = (CP_TYPE_QUALS (tt1) | CP_TYPE_QUALS (tt2));
+ tt1 = TYPE_MAIN_VARIANT (tt1);
+ tt2 = TYPE_MAIN_VARIANT (tt2);
+
if (tt1 == tt2)
target = tt1;
+ else if (b1)
+ {
+ compiler_error ("common_type called with uncommon member types");
+ target = tt1;
+ }
else if (tt1 == void_type_node || tt2 == void_type_node)
target = void_type_node;
else if (tt1 == unknown_type_node)
@@ -513,7 +598,17 @@ common_type (t1, t2)
else
target = common_type (tt1, tt2);
- target = cp_build_type_variant (target, constp, volatilep);
+ target = cp_build_qualified_type (target, type_quals);
+
+ if (b1)
+ {
+ if (same_type_p (b1, b2)
+ || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
+ target = build_offset_type (b2, target);
+ else if (binfo_or_else (b2, b1))
+ target = build_offset_type (b1, target);
+ }
+
if (code1 == POINTER_TYPE)
t1 = build_pointer_type (target);
else
@@ -587,7 +682,10 @@ common_type (t1, t2)
else if (binfo_or_else (t2, t1))
return build_type_attribute_variant (t2, attributes);
else
- compiler_error ("common_type called with uncommon aggregate types");
+ {
+ compiler_error ("common_type called with uncommon aggregate types");
+ return error_mark_node;
+ }
case METHOD_TYPE:
if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
@@ -600,7 +698,7 @@ common_type (t1, t2)
tree b1 = TYPE_OFFSET_BASETYPE (t1);
tree b2 = TYPE_OFFSET_BASETYPE (t2);
- if (comptypes (b1, b2, 1)
+ if (same_type_p (b1, b2)
|| (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
else
@@ -630,18 +728,9 @@ common_type (t1, t2)
return build_type_attribute_variant (t1, attributes);
case OFFSET_TYPE:
- if (TREE_TYPE (t1) == TREE_TYPE (t2))
- {
- tree b1 = TYPE_OFFSET_BASETYPE (t1);
- tree b2 = TYPE_OFFSET_BASETYPE (t2);
-
- if (comptypes (b1, b2, 1)
- || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
- return build_type_attribute_variant (t2, attributes);
- else if (binfo_or_else (b2, b1))
- return build_type_attribute_variant (t1, attributes);
- }
- compiler_error ("common_type called with uncommon member types");
+ /* Pointers to members should now be handled by the POINTER_TYPE
+ case above. */
+ my_friendly_abort (990325);
default:
return build_type_attribute_variant (t1, attributes);
@@ -657,61 +746,58 @@ compexcepttypes (t1, t2)
return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);
}
+/* Compare the array types T1 and T2, using CMP as the type comparison
+ function for the element types. STRICT is as for comptypes. */
+
static int
comp_array_types (cmp, t1, t2, strict)
register int (*cmp) PROTO((tree, tree, int));
tree t1, t2;
int strict;
{
- tree d1 = TYPE_DOMAIN (t1);
- tree d2 = TYPE_DOMAIN (t2);
+ tree d1;
+ tree d2;
+
+ if (t1 == t2)
+ return 1;
- /* Target types must match incl. qualifiers. */
+ /* The type of the array elements must be the same. */
if (!(TREE_TYPE (t1) == TREE_TYPE (t2)
- || (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2), strict)))
+ || (*cmp) (TREE_TYPE (t1), TREE_TYPE (t2),
+ strict & ~COMPARE_REDECLARATION)))
return 0;
- /* Sizes must match unless one is missing or variable. */
- if (d1 == 0 || d2 == 0 || d1 == d2
- || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
- || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
+ d1 = TYPE_DOMAIN (t1);
+ d2 = TYPE_DOMAIN (t2);
+
+ if (d1 == d2)
return 1;
- return ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2)))
- && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2)))
- && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1))
- == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2))));
+ /* If one of the arrays is dimensionless, and the other has a
+ dimension, they are of different types. However, it is legal to
+ write:
+
+ extern int a[];
+ int a[3];
+
+ by [basic.link]:
+
+ declarations for an array object can specify
+ array types that differ by the presence or absence of a major
+ array bound (_dcl.array_). */
+ if (!d1 || !d2)
+ return strict & COMPARE_REDECLARATION;
+
+ /* Check that the dimensions are the same. */
+ return (cp_tree_equal (TYPE_MIN_VALUE (d1),
+ TYPE_MIN_VALUE (d2))
+ && cp_tree_equal (TYPE_MAX_VALUE (d1),
+ TYPE_MAX_VALUE (d2)));
}
/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
- or various other operations. This is what ANSI C++ speaks of as
- "being the same".
-
- For C++: argument STRICT says we should be strict about this
- comparison:
-
- 2 : strict, except that if one type is a reference and
- the other is not, compare the target type of the
- reference to the type that's not a reference (ARM, p308).
- This is used for checking for invalid overloading.
- 1 : strict (compared according to ANSI C)
- This is used for checking whether two function decls match.
- 0 : <= (compared according to C++)
- -1: <= or >= (relaxed)
-
- Otherwise, pointers involving base classes and derived classes can
- be mixed as valid: i.e. a pointer to a derived class may be converted
- to a pointer to one of its base classes, as per C++. A pointer to
- a derived class may be passed as a parameter to a function expecting a
- pointer to a base classes. These allowances do not commute. In this
- case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to
- be the derived class. */
+ or various other operations. STRICT is a bitwise-or of the
+ COMPARE_* flags. */
int
comptypes (type1, type2, strict)
@@ -721,9 +807,18 @@ comptypes (type1, type2, strict)
register tree t1 = type1;
register tree t2 = type2;
int attrval, val;
+ int orig_strict = strict;
- /* Suppress errors caused by previously reported errors */
+ /* The special exemption for redeclaring array types without an
+ array bound only applies at the top level:
+
+ extern int (*i)[];
+ int (*i)[8];
+ is not legal, for example. */
+ strict &= ~COMPARE_REDECLARATION;
+
+ /* Suppress errors caused by previously reported errors */
if (t1 == t2)
return 1;
@@ -733,7 +828,7 @@ comptypes (type1, type2, strict)
if (t2 == error_mark_node)
return 0;
- if (strict < 0)
+ if (strict & COMPARE_RELAXED)
{
/* Treat an enum type as the unsigned integer type of the same width. */
@@ -752,30 +847,14 @@ comptypes (type1, type2, strict)
t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
/* Different classes of types can't be compatible. */
-
if (TREE_CODE (t1) != TREE_CODE (t2))
- {
- if (strict == 2
- && ((TREE_CODE (t1) == REFERENCE_TYPE)
- ^ (TREE_CODE (t2) == REFERENCE_TYPE)))
- {
- if (TREE_CODE (t1) == REFERENCE_TYPE)
- return comptypes (TREE_TYPE (t1), t2, 1);
- return comptypes (t1, TREE_TYPE (t2), 1);
- }
-
- return 0;
- }
- if (strict > 1)
- strict = 1;
+ return 0;
/* Qualifiers must match. */
-
- if (TYPE_READONLY (t1) != TYPE_READONLY (t2))
+ if (CP_TYPE_QUALS (t1) != CP_TYPE_QUALS (t2))
return 0;
- if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
- return 0;
- if (strict > 0 && TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
+ if (strict == COMPARE_STRICT
+ && TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return 0;
/* Allow for two different type nodes which have essentially the same
@@ -791,8 +870,10 @@ comptypes (type1, type2, strict)
#define COMP_TYPE_ATTRIBUTES(t1,t2) 1
#endif
+ if (strict & COMPARE_NO_ATTRIBUTES)
+ attrval = 1;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
- if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
+ else if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
return 0;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
@@ -807,22 +888,32 @@ comptypes (type1, type2, strict)
if (! comp_template_parms (DECL_TEMPLATE_PARMS (TYPE_NAME (t1)),
DECL_TEMPLATE_PARMS (TYPE_NAME (t2))))
return 0;
- if (! CLASSTYPE_TEMPLATE_INFO (t1) && ! CLASSTYPE_TEMPLATE_INFO (t2))
+ if (!TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t1)
+ && ! TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2))
return 1;
/* Don't check inheritance. */
- strict = 1;
+ strict = COMPARE_STRICT;
/* fall through */
case RECORD_TYPE:
case UNION_TYPE:
- if (CLASSTYPE_TEMPLATE_INFO (t1) && CLASSTYPE_TEMPLATE_INFO (t2)
- && (CLASSTYPE_TI_TEMPLATE (t1) == CLASSTYPE_TI_TEMPLATE (t2)
+ if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2)
+ && (TYPE_TI_TEMPLATE (t1) == TYPE_TI_TEMPLATE (t2)
|| TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM))
- return comp_template_args (CLASSTYPE_TI_ARGS (t1),
- CLASSTYPE_TI_ARGS (t2));
- if (strict <= 0)
- goto look_hard;
- return 0;
+ val = comp_template_args (TYPE_TI_ARGS (t1),
+ TYPE_TI_ARGS (t2));
+ look_hard:
+ if ((strict & COMPARE_BASE) && DERIVED_FROM_P (t1, t2))
+ {
+ val = 1;
+ break;
+ }
+ if ((strict & COMPARE_RELAXED) && DERIVED_FROM_P (t2, t1))
+ {
+ val = 1;
+ break;
+ }
+ break;
case OFFSET_TYPE:
val = (comptypes (build_pointer_type (TYPE_OFFSET_BASETYPE (t1)),
@@ -840,42 +931,21 @@ comptypes (type1, type2, strict)
but not vice-versa! */
val = (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
- && compparms (TYPE_ARG_TYPES (t1),
- TYPE_ARG_TYPES (t2), strict));
+ && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2)));
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
t1 = TREE_TYPE (t1);
t2 = TREE_TYPE (t2);
- if (t1 == t2)
- {
- val = 1;
- break;
- }
- if (strict <= 0)
- {
- if (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE)
- {
- int rval;
- look_hard:
- rval = t1 == t2 || DERIVED_FROM_P (t1, t2);
-
- if (rval)
- {
- val = 1;
- break;
- }
- if (strict < 0)
- {
- val = DERIVED_FROM_P (t2, t1);
- break;
- }
- }
- return 0;
- }
- else
- val = comptypes (t1, t2, strict);
+ /* first, check whether the referred types match with the
+ required level of strictness */
+ val = comptypes (t1, t2, strict);
+ if (val)
+ break;
+ if (TREE_CODE (t1) == RECORD_TYPE
+ && TREE_CODE (t2) == RECORD_TYPE)
+ goto look_hard;
break;
case FUNCTION_TYPE:
@@ -884,12 +954,14 @@ comptypes (type1, type2, strict)
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
|| comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict))
- && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict));
+ && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2)));
break;
case ARRAY_TYPE:
- /* Target types must match incl. qualifiers. */
- val = comp_array_types (comptypes, t1, t2, strict);
+ /* Target types must match incl. qualifiers. We use ORIG_STRICT
+ here since this is the one place where
+ COMPARE_REDECLARATION should be used. */
+ val = comp_array_types (comptypes, t1, t2, orig_strict);
break;
case TEMPLATE_TYPE_PARM:
@@ -899,7 +971,7 @@ comptypes (type1, type2, strict)
case TYPENAME_TYPE:
if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
return 0;
- return comptypes (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2), 1);
+ return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
default:
break;
@@ -907,6 +979,32 @@ comptypes (type1, type2, strict)
return attrval == 2 && val == 1 ? 2 : val;
}
+/* Subroutine of comp_target-types. Make sure that the cv-quals change
+ only in the same direction as the target type. */
+
+static int
+comp_cv_target_types (ttl, ttr, nptrs)
+ tree ttl, ttr;
+ int nptrs;
+{
+ int t;
+
+ if (!at_least_as_qualified_p (ttl, ttr)
+ && !at_least_as_qualified_p (ttr, ttl))
+ /* The qualifications are incomparable. */
+ return 0;
+
+ if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))
+ return more_qualified_p (ttr, ttl) ? -1 : 1;
+
+ t = comp_target_types (ttl, ttr, nptrs);
+ if ((t == 1 && at_least_as_qualified_p (ttl, ttr))
+ || (t == -1 && at_least_as_qualified_p (ttr, ttl)))
+ return t;
+
+ return 0;
+}
+
/* Return 1 or -1 if TTL and TTR are pointers to types that are equivalent,
ignoring their qualifiers, 0 if not. Return 1 means that TTR can be
converted to TTL. Return -1 means that TTL can be converted to TTR but
@@ -926,21 +1024,26 @@ comp_target_types (ttl, ttr, nptrs)
{
ttl = TYPE_MAIN_VARIANT (ttl);
ttr = TYPE_MAIN_VARIANT (ttr);
- if (ttl == ttr)
+ if (same_type_p (ttl, ttr))
return 1;
if (TREE_CODE (ttr) != TREE_CODE (ttl))
return 0;
- if (TREE_CODE (ttr) == POINTER_TYPE
- || (TREE_CODE (ttr) == REFERENCE_TYPE))
+ if ((TREE_CODE (ttr) == POINTER_TYPE
+ || TREE_CODE (ttr) == REFERENCE_TYPE)
+ /* If we get a pointer with nptrs == 0, we don't allow any tweaking
+ of the type pointed to. This is necessary for reference init
+ semantics. We won't get here from a previous call with nptrs == 1;
+ for multi-level pointers we end up in comp_ptr_ttypes. */
+ && nptrs > 0)
{
int is_ptr = TREE_CODE (ttr) == POINTER_TYPE;
ttl = TREE_TYPE (ttl);
ttr = TREE_TYPE (ttr);
- if (nptrs > 0 && is_ptr)
+ if (is_ptr)
{
if (TREE_CODE (ttl) == UNKNOWN_TYPE
|| TREE_CODE (ttr) == UNKNOWN_TYPE)
@@ -971,29 +1074,11 @@ comp_target_types (ttl, ttr, nptrs)
if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE)
return comp_target_types (ttl, ttr, nptrs - 1);
- /* Make sure that the cv-quals change only in the same direction as
- the target type. */
- {
- int t;
- int c = TYPE_READONLY (ttl) - TYPE_READONLY (ttr);
- int v = TYPE_VOLATILE (ttl) - TYPE_VOLATILE (ttr);
-
- if ((c > 0 && v < 0) || (c < 0 && v > 0))
- return 0;
-
- if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))
- return (c + v < 0) ? -1 : 1;
-
- t = comp_target_types (ttl, ttr, nptrs - 1);
- if ((t == 1 && c + v >= 0) || (t == -1 && c + v <= 0))
- return t;
-
- return 0;
- }
+ return comp_cv_target_types (ttl, ttr, nptrs - 1);
}
if (TREE_CODE (ttr) == ARRAY_TYPE)
- return comp_array_types (comp_target_types, ttl, ttr, 0);
+ return comp_array_types (comp_target_types, ttl, ttr, COMPARE_STRICT);
else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
{
tree argsl, argsr;
@@ -1001,7 +1086,7 @@ comp_target_types (ttl, ttr, nptrs)
if (pedantic)
{
- if (comptypes (TREE_TYPE (ttl), TREE_TYPE (ttr), 1) == 0)
+ if (!same_type_p (TREE_TYPE (ttl), TREE_TYPE (ttr)))
return 0;
}
else
@@ -1024,9 +1109,9 @@ comp_target_types (ttl, ttr, nptrs)
tree tl = TYPE_METHOD_BASETYPE (ttl);
tree tr = TYPE_METHOD_BASETYPE (ttr);
- if (comptypes (tr, tl, 0) == 0)
+ if (!same_or_base_type_p (tr, tl))
{
- if (comptypes (tl, tr, 0))
+ if (same_or_base_type_p (tl, tr))
saw_contra = 1;
else
return 0;
@@ -1049,24 +1134,51 @@ comp_target_types (ttl, ttr, nptrs)
/* for C++ */
else if (TREE_CODE (ttr) == OFFSET_TYPE)
{
+ int base;
+
/* Contravariance: we can assign a pointer to base member to a pointer
to derived member. Note difference from simple pointer case, where
we can pass a pointer to derived to a pointer to base. */
- if (comptypes (TYPE_OFFSET_BASETYPE (ttr),
- TYPE_OFFSET_BASETYPE (ttl), 0))
- return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
- else if (comptypes (TYPE_OFFSET_BASETYPE (ttl),
- TYPE_OFFSET_BASETYPE (ttr), 0)
- && comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
- return -1;
+ if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttr),
+ TYPE_OFFSET_BASETYPE (ttl)))
+ base = 1;
+ else if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttl),
+ TYPE_OFFSET_BASETYPE (ttr)))
+ {
+ tree tmp = ttl;
+ ttl = ttr;
+ ttr = tmp;
+ base = -1;
+ }
+ else
+ return 0;
+
+ ttl = TREE_TYPE (ttl);
+ ttr = TREE_TYPE (ttr);
+
+ if (TREE_CODE (ttl) == POINTER_TYPE
+ || TREE_CODE (ttl) == ARRAY_TYPE)
+ {
+ if (comp_ptr_ttypes (ttl, ttr))
+ return base;
+ return 0;
+ }
+ else
+ {
+ if (comp_cv_target_types (ttl, ttr, nptrs) == 1)
+ return base;
+ return 0;
+ }
}
else if (IS_AGGR_TYPE (ttl))
{
if (nptrs < 0)
return 0;
- if (comptypes (build_pointer_type (ttl), build_pointer_type (ttr), 0))
+ if (same_or_base_type_p (build_pointer_type (ttl),
+ build_pointer_type (ttr)))
return 1;
- if (comptypes (build_pointer_type (ttr), build_pointer_type (ttl), 0))
+ if (same_or_base_type_p (build_pointer_type (ttr),
+ build_pointer_type (ttl)))
return -1;
return 0;
}
@@ -1074,6 +1186,29 @@ comp_target_types (ttl, ttr, nptrs)
return 0;
}
+/* Returns 1 if TYPE1 is at least as qualified as TYPE2. */
+
+int
+at_least_as_qualified_p (type1, type2)
+ tree type1;
+ tree type2;
+{
+ /* All qualifiers for TYPE2 must also appear in TYPE1. */
+ return ((CP_TYPE_QUALS (type1) & CP_TYPE_QUALS (type2))
+ == CP_TYPE_QUALS (type2));
+}
+
+/* Returns 1 if TYPE1 is more qualified than TYPE2. */
+
+int
+more_qualified_p (type1, type2)
+ tree type1;
+ tree type2;
+{
+ return (CP_TYPE_QUALS (type1) != CP_TYPE_QUALS (type2)
+ && at_least_as_qualified_p (type1, type2));
+}
+
/* Returns 1 if TYPE1 is more cv-qualified than TYPE2, -1 if TYPE2 is
more cv-qualified that TYPE1, and 0 otherwise. */
@@ -1082,16 +1217,13 @@ comp_cv_qualification (type1, type2)
tree type1;
tree type2;
{
- if (TYPE_READONLY (type1) == TYPE_READONLY (type2)
- && TYPE_VOLATILE (type1) == TYPE_VOLATILE (type2))
+ if (CP_TYPE_QUALS (type1) == CP_TYPE_QUALS (type2))
return 0;
- if (TYPE_READONLY (type1) >= TYPE_READONLY (type2)
- && TYPE_VOLATILE (type1) >= TYPE_VOLATILE (type2))
+ if (at_least_as_qualified_p (type1, type2))
return 1;
- if (TYPE_READONLY (type2) >= TYPE_READONLY (type1)
- && TYPE_VOLATILE (type2) >= TYPE_VOLATILE (type1))
+ else if (at_least_as_qualified_p (type2, type1))
return -1;
return 0;
@@ -1168,20 +1300,16 @@ common_base_type (tt1, tt2)
/* Subroutines of `comptypes'. */
-/* Return 1 if two parameter type lists PARMS1 and PARMS2
- are equivalent in the sense that functions with those parameter types
- can have equivalent types.
- If either list is empty, we win.
- Otherwise, the two lists must be equivalent, element by element.
+/* Return 1 if two parameter type lists PARMS1 and PARMS2 are
+ equivalent in the sense that functions with those parameter types
+ can have equivalent types. The two lists must be equivalent,
+ element by element.
- C++: See comment above about TYPE1, TYPE2.
-
- STRICT is no longer used. */
+ C++: See comment above about TYPE1, TYPE2. */
int
-compparms (parms1, parms2, strict)
+compparms (parms1, parms2)
tree parms1, parms2;
- int strict;
{
register tree t1 = parms1, t2 = parms2;
@@ -1196,7 +1324,7 @@ compparms (parms1, parms2, strict)
they fail to match. */
if (t1 == 0 || t2 == 0)
return 0;
- if (! comptypes (TREE_VALUE (t2), TREE_VALUE (t1), 1))
+ if (!same_type_p (TREE_VALUE (t2), TREE_VALUE (t1)))
return 0;
t1 = TREE_CHAIN (t1);
@@ -1227,8 +1355,13 @@ comp_target_parms (parms1, parms2, strict)
if (t1 == 0 && t2 != 0)
{
- cp_pedwarn ("ANSI C++ prohibits conversion from `(%#T)' to `(...)'",
- parms2);
+ if (! flag_strict_prototype && t2 == void_list_node)
+ /* t1 might be the arglist of a function pointer in extern "C"
+ declared to take (), which we fudged to (...). Don't make the
+ user pay for our mistake. */;
+ else
+ cp_pedwarn ("ANSI C++ prohibits conversion from `%#T' to `(...)'",
+ parms2);
return self_promoting_args_p (t2);
}
if (t2 == 0)
@@ -1250,7 +1383,7 @@ comp_target_parms (parms1, parms2, strict)
}
p1 = TREE_VALUE (t1);
p2 = TREE_VALUE (t2);
- if (comptypes (p1, p2, 1))
+ if (same_type_p (p1, p2))
continue;
if (pedantic)
@@ -1274,12 +1407,10 @@ comp_target_parms (parms1, parms2, strict)
warn_contravariance = 1;
continue;
}
- if (IS_AGGR_TYPE (TREE_TYPE (p1)))
- {
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (p1)),
- TYPE_MAIN_VARIANT (TREE_TYPE (p2)), 1) == 0)
- return 0;
- }
+ if (IS_AGGR_TYPE (TREE_TYPE (p1))
+ && !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (p1)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (p2))))
+ return 0;
}
/* Note backwards order due to contravariance. */
if (comp_target_types (p2, p1, 1) <= 0)
@@ -1342,8 +1473,10 @@ unsigned_type (type)
return long_unsigned_type_node;
if (type1 == long_long_integer_type_node)
return long_long_unsigned_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
if (type1 == intTI_type_node)
return unsigned_intTI_type_node;
+#endif
if (type1 == intDI_type_node)
return unsigned_intDI_type_node;
if (type1 == intSI_type_node)
@@ -1373,8 +1506,10 @@ signed_type (type)
return long_integer_type_node;
if (type1 == long_long_unsigned_type_node)
return long_long_integer_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
if (type1 == unsigned_intTI_type_node)
return intTI_type_node;
+#endif
if (type1 == unsigned_intDI_type_node)
return intDI_type_node;
if (type1 == unsigned_intSI_type_node)
@@ -1493,7 +1628,7 @@ expr_sizeof (e)
return build_min (SIZEOF_EXPR, sizetype, e);
if (TREE_CODE (e) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (e, 1)))
+ && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
error ("sizeof applied to a bit-field");
/* ANSI says arrays and functions are converted inside comma.
But we can't really convert them in build_compound_expr
@@ -1503,15 +1638,17 @@ expr_sizeof (e)
&& (TREE_CODE (TREE_TYPE (e)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (e)) == FUNCTION_TYPE))
e = default_conversion (e);
- else if (TREE_CODE (e) == TREE_LIST)
+ else if (is_overloaded_fn (e))
{
- tree t = TREE_VALUE (e);
- if (t != NULL_TREE
- && ((TREE_TYPE (t)
- && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
- || is_overloaded_fn (t)))
- pedwarn ("ANSI C++ forbids taking the sizeof a function type");
+ pedwarn ("ANSI C++ forbids taking the sizeof a function type");
+ return size_int (1);
}
+ else if (type_unknown_p (e))
+ {
+ incomplete_type_error (e, TREE_TYPE (e));
+ return size_int (1);
+ }
+
return c_sizeof (TREE_TYPE (e));
}
@@ -1577,34 +1714,24 @@ c_alignof (type)
return t;
}
-/* Perform default promotions for C data used in expressions.
- Arrays and functions are converted to pointers;
- enumeral types or short or char, to int.
- In addition, manifest constants symbols are replaced by their values.
+/* Perform the array-to-pointer and function-to-pointer conversions
+ for EXP.
- C++: this will automatically bash references to their target type. */
+ In addition, references are converted to rvalues and manifest
+ constants are replaced by their values. */
tree
decay_conversion (exp)
tree exp;
{
- register tree type = TREE_TYPE (exp);
- register enum tree_code code = TREE_CODE (type);
-
- if (code == OFFSET_TYPE)
- {
- if (TREE_CODE (exp) == OFFSET_REF)
- return decay_conversion (resolve_offset_ref (exp));
+ register tree type;
+ register enum tree_code code;
- type = TREE_TYPE (type);
- code = TREE_CODE (type);
+ if (TREE_CODE (exp) == OFFSET_REF)
+ exp = resolve_offset_ref (exp);
- if (type == unknown_type_node)
- {
- cp_pedwarn ("assuming & on overloaded member function");
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
- }
+ type = TREE_TYPE (exp);
+ code = TREE_CODE (type);
if (code == REFERENCE_TYPE)
{
@@ -1616,8 +1743,15 @@ decay_conversion (exp)
/* Constants can be used directly unless they're not loadable. */
if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp);
- /* Replace a nonvolatile const static variable with its value. */
- else if (TREE_READONLY_DECL_P (exp))
+ /* Replace a nonvolatile const static variable with its value. We
+ don't do this for arrays, though; we want the address of the
+ first element of the array, not the address of the first element
+ of its initializing constant. We *do* replace variables that the
+ user isn't really supposed to know about; this is a hack to deal
+ with __PRETTY_FUNCTION__ and the like. */
+ else if (TREE_READONLY_DECL_P (exp)
+ && (code != ARRAY_TYPE
+ || (TREE_CODE (exp) == VAR_DECL && DECL_IGNORED_P (exp))))
{
exp = decl_constant_value (exp);
type = TREE_TYPE (exp);
@@ -1631,21 +1765,14 @@ decay_conversion (exp)
error ("void value not ignored as it ought to be");
return error_mark_node;
}
- if (code == FUNCTION_TYPE)
- {
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
if (code == METHOD_TYPE)
- {
- cp_pedwarn ("assuming & on `%E'", exp);
- return build_unary_op (ADDR_EXPR, exp, 0);
- }
+ my_friendly_abort (990506);
+ if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
+ return build_unary_op (ADDR_EXPR, exp, 0);
if (code == ARRAY_TYPE)
{
register tree adr;
- tree restype;
tree ptrtype;
- int constp, volatilep;
if (TREE_CODE (exp) == INDIRECT_REF)
{
@@ -1677,21 +1804,7 @@ decay_conversion (exp)
return error_mark_node;
}
- constp = volatilep = 0;
- if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r'
- || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
- {
- constp = TREE_READONLY (exp);
- volatilep = TREE_THIS_VOLATILE (exp);
- }
-
- restype = TREE_TYPE (type);
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
- || constp || volatilep)
- restype = cp_build_type_variant (restype,
- TYPE_READONLY (type) || constp,
- TYPE_VOLATILE (type) || volatilep);
- ptrtype = build_pointer_type (restype);
+ ptrtype = build_pointer_type (TREE_TYPE (type));
if (TREE_CODE (exp) == VAR_DECL)
{
@@ -1745,12 +1858,52 @@ inline_conversion (exp)
tree exp;
{
if (TREE_CODE (exp) == FUNCTION_DECL)
+ exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
+
+ return exp;
+}
+
+/* Returns nonzero iff exp is a STRING_CST or the result of applying
+ decay_conversion to one. */
+
+int
+string_conv_p (totype, exp, warn)
+ tree totype, exp;
+ int warn;
+{
+ tree t;
+
+ if (! flag_const_strings || TREE_CODE (totype) != POINTER_TYPE)
+ return 0;
+
+ t = TREE_TYPE (totype);
+ if (!same_type_p (t, char_type_node)
+ && !same_type_p (t, wchar_type_node))
+ return 0;
+
+ if (TREE_CODE (exp) == STRING_CST)
{
- tree type = build_type_variant
- (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp));
- exp = build1 (ADDR_EXPR, build_pointer_type (type), exp);
+ /* Make sure that we don't try to convert between char and wchar_t. */
+ if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), t))
+ return 0;
}
- return exp;
+ else
+ {
+ /* Is this a string constant which has decayed to 'const char *'? */
+ t = build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
+ if (!same_type_p (TREE_TYPE (exp), t))
+ return 0;
+ STRIP_NOPS (exp);
+ if (TREE_CODE (exp) != ADDR_EXPR
+ || TREE_CODE (TREE_OPERAND (exp, 0)) != STRING_CST)
+ return 0;
+ }
+
+ /* This warning is not very useful, as it complains about printf. */
+ if (warn && warn_write_strings)
+ cp_warning ("deprecated conversion from string constant to `%T'", totype);
+
+ return 1;
}
tree
@@ -1877,14 +2030,23 @@ build_component_ref (datum, component, basetype_path, protect)
tree datum, component, basetype_path;
int protect;
{
- register tree basetype = TREE_TYPE (datum);
+ register tree basetype;
register enum tree_code code;
register tree field = NULL;
register tree ref;
+ tree field_type;
+ int type_quals;
if (processing_template_decl)
return build_min_nt (COMPONENT_REF, datum, component);
+
+ if (datum == error_mark_node
+ || TREE_TYPE (datum) == error_mark_node)
+ return error_mark_node;
+ /* BASETYPE holds the type of the class containing the COMPONENT. */
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
+
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
inside it. */
switch (TREE_CODE (datum))
@@ -1918,13 +2080,13 @@ build_component_ref (datum, component, basetype_path, protect)
if (code == REFERENCE_TYPE)
{
datum = convert_from_reference (datum);
- basetype = TREE_TYPE (datum);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
code = TREE_CODE (basetype);
}
if (TREE_CODE (datum) == OFFSET_REF)
{
datum = resolve_offset_ref (datum);
- basetype = TREE_TYPE (datum);
+ basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
code = TREE_CODE (basetype);
}
@@ -1948,7 +2110,7 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node;
}
- if (!complete_type_or_else (basetype))
+ if (!complete_type_or_else (basetype, datum))
return error_mark_node;
if (TREE_CODE (component) == BIT_NOT_EXPR)
@@ -1978,8 +2140,8 @@ build_component_ref (datum, component, basetype_path, protect)
field = component;
else if (TREE_CODE (component) == TYPE_DECL)
{
- cp_pedwarn ("invalid use of type decl `%#D' as expression", component);
- return component;
+ cp_error ("invalid use of type decl `%#D' as expression", component);
+ return error_mark_node;
}
else
{
@@ -2003,58 +2165,35 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node;
if (fndecls)
{
+ /* If the function is unique and static, we can resolve it
+ now. Otherwise, we have to wait and see what context it is
+ used in; a component_ref involving a non-static member
+ function can only be used in a call (expr.ref). */
+
if (TREE_CHAIN (fndecls) == NULL_TREE
- && TREE_CODE (TREE_VALUE (fndecls)) != OVERLOAD)
+ && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL)
{
- tree access, fndecl;
-
- /* Unique, so use this one now. */
- basetype = TREE_PURPOSE (fndecls);
- fndecl = TREE_VALUE (fndecls);
- access = compute_access (TREE_PURPOSE (fndecls), fndecl);
- if (access == access_public_node)
+ if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
{
- if (DECL_VINDEX (fndecl)
- && ! resolves_to_fixed_type_p (datum, 0))
- {
- tree addr = build_unary_op (ADDR_EXPR, datum, 0);
- tree fntype = TREE_TYPE (fndecl);
-
- addr = convert_pointer_to (DECL_CONTEXT (fndecl),
- addr);
- datum = build_indirect_ref (addr, NULL_PTR);
- my_friendly_assert (datum != error_mark_node, 310);
- fndecl = build_vfn_ref (&addr, datum,
- DECL_VINDEX (fndecl));
- /* The type of fndecl is a function type,
- not a pointer-to-function type, since
- build_vfn_ref returns not the correct
- vtable slot, but the indirection of the
- correct vtable slot. */
- TREE_TYPE (fndecl) = fntype;
- }
- else
- mark_used (fndecl);
- return build (OFFSET_REF, TREE_TYPE (fndecl),
- datum, fndecl);
+ tree fndecl = TREE_VALUE (fndecls);
+ enforce_access (TREE_PURPOSE (fndecls), fndecl);
+ mark_used (fndecl);
+ return fndecl;
}
- if (access == access_protected_node)
- cp_error ("member function `%D' is protected", fndecl);
else
- cp_error ("member function `%D' is private", fndecl);
- return error_mark_node;
- }
- else
- {
- /* Just act like build_offset_ref, since the object does
- not matter unless we're actually calling the function. */
- tree t;
-
- t = build_tree_list (error_mark_node, fndecls);
- TREE_TYPE (t) = build_offset_type (basetype,
- unknown_type_node);
- return t;
+ {
+ /* A unique non-static member function. Other parts
+ of the compiler expect something with
+ unknown_type_node to be really overloaded, so
+ let's oblige. */
+ TREE_VALUE (fndecls)
+ = scratch_ovl_cons (TREE_VALUE (fndecls), NULL_TREE);
+ }
}
+
+ ref = build (COMPONENT_REF, unknown_type_node,
+ datum, TREE_VALUE (fndecls));
+ return ref;
}
cp_error ("`%#T' has no member named `%D'", basetype, name);
@@ -2081,7 +2220,7 @@ build_component_ref (datum, component, basetype_path, protect)
{
tree context = DECL_FIELD_CONTEXT (field);
tree base = context;
- while (!comptypes (base, basetype,1) && TYPE_NAME (base)
+ while (!same_type_p (base, basetype) && TYPE_NAME (base)
&& ANON_UNION_TYPE_P (base))
{
base = TYPE_CONTEXT (base);
@@ -2121,15 +2260,38 @@ build_component_ref (datum, component, basetype_path, protect)
}
}
- ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
+ /* Compute the type of the field, as described in [expr.ref]. */
+ type_quals = TYPE_UNQUALIFIED;
+ field_type = TREE_TYPE (field);
+ if (TREE_CODE (field_type) == REFERENCE_TYPE)
+ /* The standard says that the type of the result should be the
+ type referred to by the reference. But for now, at least, we
+ do the conversion from reference type later. */
+ ;
+ else
+ {
+ type_quals = (CP_TYPE_QUALS (field_type)
+ | CP_TYPE_QUALS (TREE_TYPE (datum)));
+
+ /* A field is const (volatile) if the enclosing object, or the
+ field itself, is const (volatile). But, a mutable field is
+ not const, even within a const object. */
+ if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))
+ type_quals &= ~TYPE_QUAL_CONST;
+ if (!IS_SIGNATURE (field_type))
+ field_type = cp_build_qualified_type (field_type, type_quals);
+ }
+
+ ref = fold (build (COMPONENT_REF, field_type,
break_out_cleanups (datum), field));
- if (TREE_READONLY (datum) || TREE_READONLY (field))
+ /* Mark the expression const or volatile, as appropriate. Even
+ though we've dealt with the type above, we still have to mark the
+ expression itself. */
+ if (type_quals & TYPE_QUAL_CONST)
TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
+ else if (type_quals & TYPE_QUAL_VOLATILE)
TREE_THIS_VOLATILE (ref) = 1;
- if (DECL_LANG_SPECIFIC (field) && DECL_MUTABLE_P (field))
- TREE_READONLY (ref) = 0;
return ref;
}
@@ -2160,7 +2322,7 @@ build_x_component_ref (datum, component, basetype_path, protect)
tree
build_x_indirect_ref (ptr, errorstring)
tree ptr;
- char *errorstring;
+ const char *errorstring;
{
tree rval;
@@ -2177,52 +2339,57 @@ build_x_indirect_ref (ptr, errorstring)
tree
build_indirect_ref (ptr, errorstring)
tree ptr;
- char *errorstring;
+ const char *errorstring;
{
register tree pointer, type;
if (ptr == error_mark_node)
return error_mark_node;
+ if (ptr == current_class_ptr)
+ return current_class_ref;
+
pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
? ptr : default_conversion (ptr));
type = TREE_TYPE (pointer);
- if (ptr == current_class_ptr)
- return current_class_ref;
-
- if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
+ if (TYPE_PTR_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
{
+ /* [expr.unary.op]
+
+ If the type of the expression is "pointer to T," the type
+ of the result is "T."
+
+ We must use the canonical variant because certain parts of
+ the back end, like fold, do pointer comparisons between
+ types. */
+ tree t = canonical_type_variant (TREE_TYPE (type));
+
if (TREE_CODE (pointer) == ADDR_EXPR
&& !flag_volatile
- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (pointer, 0)))
- == TYPE_MAIN_VARIANT (TREE_TYPE (type)))
- && (TREE_READONLY (TREE_OPERAND (pointer, 0))
- == TYPE_READONLY (TREE_TYPE (type)))
- && (TREE_THIS_VOLATILE (TREE_OPERAND (pointer, 0))
- == TYPE_VOLATILE (TREE_TYPE (type))))
+ && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
+ /* The POINTER was something like `&x'. We simplify `*&x' to
+ `x'. */
return TREE_OPERAND (pointer, 0);
else
{
- tree t = TREE_TYPE (type);
- register tree ref = build1 (INDIRECT_REF,
- TYPE_MAIN_VARIANT (t), pointer);
+ tree ref = build1 (INDIRECT_REF, t, pointer);
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
so that we get the proper error message if the result is used
to assign to. Also, &* is supposed to be a no-op. */
- TREE_READONLY (ref) = TYPE_READONLY (t);
+ TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
+ TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
TREE_SIDE_EFFECTS (ref)
- = (TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer)
+ = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer)
|| flag_volatile);
- TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
/* `pointer' won't be an error_mark_node if we were given a
pointer to member, so it's cool to check for this here. */
- else if (TYPE_PTRMEMFUNC_P (type))
- error ("invalid use of `%s' on pointer to member function", errorstring);
+ else if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+ error ("invalid use of `%s' on pointer to member", errorstring);
else if (TREE_CODE (type) == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))
error ("cannot dereference signature pointer/reference");
@@ -2326,23 +2493,16 @@ build_array_ref (array, idx)
warning ("subscripting array declared `register'");
}
- type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
+ type = TREE_TYPE (TREE_TYPE (array));
rval = build (ARRAY_REF, type, array, idx);
/* Array ref is const/volatile if the array elements are
or if the array is.. */
TREE_READONLY (rval)
- |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
- | TREE_READONLY (array));
+ |= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
- |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
- | TREE_SIDE_EFFECTS (array));
+ |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
- |= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
- /* This was added by rms on 16 Nov 91.
- It fixes vol struct foo *a; a->elts[1]
- in an inline function.
- Hope it doesn't break something else. */
- | TREE_THIS_VOLATILE (array));
+ |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
return require_complete_type (fold (rval));
}
@@ -2444,21 +2604,25 @@ build_x_function_call (function, params, decl)
TYPE_BINFO (type), LOOKUP_NORMAL);
}
+ if ((TREE_CODE (function) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (function))
+ || (TREE_CODE (function) == TEMPLATE_DECL
+ && DECL_STATIC_FUNCTION_P (DECL_RESULT (function))))
+ return build_member_call(DECL_CONTEXT (function),
+ template_id
+ ? template_id : DECL_NAME (function),
+ params);
+
is_method = ((TREE_CODE (function) == TREE_LIST
&& current_class_type != NULL_TREE
&& (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function))
== function))
+ || (TREE_CODE (function) == OVERLOAD
+ && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (function)))
|| TREE_CODE (function) == IDENTIFIER_NODE
|| TREE_CODE (type) == METHOD_TYPE
|| TYPE_PTRMEMFUNC_P (type));
- if ((TREE_CODE (function) == FUNCTION_DECL
- && DECL_STATIC_FUNCTION_P (function))
- || (TREE_CODE (function) == TEMPLATE_DECL
- && DECL_STATIC_FUNCTION_P (DECL_RESULT (function))))
- return build_member_call
- (DECL_CONTEXT (function), DECL_NAME (function), params);
-
/* A friend template. Make it look like a toplevel declaration. */
if (! is_method && TREE_CODE (function) == TEMPLATE_DECL)
function = scratch_ovl_cons (function, NULL_TREE);
@@ -2468,6 +2632,9 @@ build_x_function_call (function, params, decl)
{
tree basetype = NULL_TREE;
+ if (TREE_CODE (function) == OVERLOAD)
+ function = OVL_CURRENT (function);
+
if (TREE_CODE (function) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (function))
{
@@ -2519,14 +2686,11 @@ build_x_function_call (function, params, decl)
{
if (current_class_type == NULL_TREE)
{
- error ("object missing in call to method `%s'",
- IDENTIFIER_POINTER (function));
+ cp_error ("object missing in call to method `%D'", function);
return error_mark_node;
}
/* Yow: call from a static member function. */
- decl = build1 (NOP_EXPR, build_pointer_type (current_class_type),
- error_mark_node);
- decl = build_indirect_ref (decl, NULL_PTR);
+ decl = build_dummy_object (current_class_type);
}
/* Put back explicit template arguments, if any. */
@@ -2538,12 +2702,17 @@ build_x_function_call (function, params, decl)
else if (TREE_CODE (function) == COMPONENT_REF
&& type == unknown_type_node)
{
- /* Should we undo what was done in build_component_ref? */
- if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC)
- /* Get the name that build_component_ref hid. */
- function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1)));
- else
- function = TREE_PURPOSE (TREE_OPERAND (function, 1));
+ /* Undo what we did in build_component_ref. */
+ decl = TREE_OPERAND (function, 0);
+ function = TREE_OPERAND (function, 1);
+ function = DECL_NAME (OVL_CURRENT (function));
+
+ if (template_id)
+ {
+ TREE_OPERAND (template_id, 0) = function;
+ function = template_id;
+ }
+
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
@@ -2666,7 +2835,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
tree fntype, idx, e1, delta, delta2, e2, e3, aref, vtbl;
- tree instance;
+ tree instance, basetype;
tree instance_ptr = *instance_ptrptr;
@@ -2677,61 +2846,76 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
function = save_expr (function);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
- /* Promoting idx before saving it improves performance on RISC
- targets. Without promoting, the first compare used
- load-with-sign-extend, while the second used normal load then
- shift to sign-extend. An optimizer flaw, perhaps, but it's easier
- to make this change. */
- idx = save_expr (default_conversion
- (build_component_ref (function,
- index_identifier,
- NULL_TREE, 0)));
- e1 = build_binary_op (GT_EXPR, idx, integer_zero_node, 1);
delta = cp_convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier,
NULL_TREE, 0));
- delta2 = DELTA2_FROM_PTRMEMFUNC (function);
-
- /* Convert down to the right base, before using the instance. */
- instance
- = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
- instance_ptr);
- if (instance == error_mark_node && instance_ptr != error_mark_node)
- return instance;
-
- vtbl = convert_pointer_to (ptr_type_node, instance);
- vtbl
- = build (PLUS_EXPR,
- build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, cp_convert (ptrdiff_type_node, delta2));
- vtbl = build_indirect_ref (vtbl, NULL_PTR);
- aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
- idx,
- integer_one_node, 1));
- if (! flag_vtable_thunks)
- {
- aref = save_expr (aref);
-
- delta = build_binary_op
+ e3 = PFN_FROM_PTRMEMFUNC (function);
+
+ if (TYPE_SIZE (basetype) != NULL_TREE
+ && ! TYPE_VIRTUAL_P (basetype))
+ /* If basetype doesn't have virtual functions, don't emit code to
+ handle that case. */
+ e1 = e3;
+ else
+ {
+ /* Promoting idx before saving it improves performance on RISC
+ targets. Without promoting, the first compare used
+ load-with-sign-extend, while the second used normal load then
+ shift to sign-extend. An optimizer flaw, perhaps, but it's
+ easier to make this change. */
+ idx = save_expr (default_conversion
+ (build_component_ref (function,
+ index_identifier,
+ NULL_TREE, 0)));
+ e1 = build_binary_op (GE_EXPR, idx, integer_zero_node);
+
+ /* Convert down to the right base, before using the instance. */
+ instance = convert_pointer_to_real (basetype, instance_ptr);
+ if (instance == error_mark_node && instance_ptr != error_mark_node)
+ return instance;
+
+ vtbl = convert_pointer_to (ptr_type_node, instance);
+ delta2 = DELTA2_FROM_PTRMEMFUNC (function);
+ vtbl = build
(PLUS_EXPR,
- build_conditional_expr (e1, build_component_ref (aref,
+ build_pointer_type (build_pointer_type (vtable_entry_type)),
+ vtbl, cp_convert (ptrdiff_type_node, delta2));
+ vtbl = build_indirect_ref (vtbl, NULL_PTR);
+ aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
+ idx,
+ integer_one_node));
+ if (! flag_vtable_thunks)
+ {
+ aref = save_expr (aref);
+
+ delta = build_binary_op
+ (PLUS_EXPR,
+ build_conditional_expr (e1,
+ build_component_ref (aref,
delta_identifier,
NULL_TREE, 0),
- integer_zero_node),
- delta, 1);
+ integer_zero_node),
+ delta);
+ }
+
+ if (flag_vtable_thunks)
+ e2 = aref;
+ else
+ e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
+ TREE_TYPE (e2) = TREE_TYPE (e3);
+ e1 = build_conditional_expr (e1, e2, e3);
+
+ /* Make sure this doesn't get evaluated first inside one of the
+ branches of the COND_EXPR. */
+ if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+ e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
+ instance_ptr, e1);
}
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
- if (flag_vtable_thunks)
- e2 = aref;
- else
- e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
-
- e3 = PFN_FROM_PTRMEMFUNC (function);
- TREE_TYPE (e2) = TREE_TYPE (e3);
- e1 = build_conditional_expr (e1, e2, e3);
if (instance_ptr == error_mark_node
&& TREE_CODE (e1) != ADDR_EXPR
@@ -2739,12 +2923,6 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
cp_error ("object missing in `%E'", function);
function = e1;
-
- /* Make sure this doesn't get evaluated first inside one of the
- branches of the COND_EXPR. */
- if (TREE_CODE (instance_ptr) == SAVE_EXPR)
- function = build (COMPOUND_EXPR, TREE_TYPE (function),
- instance_ptr, function);
}
return function;
}
@@ -2829,10 +3007,10 @@ build_function_call_real (function, params, require_complete, flags)
function prototype, or apply default promotions. */
if (flags & LOOKUP_COMPLAIN)
- coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
+ coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
params, fndecl, LOOKUP_NORMAL);
else
- coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
+ coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
params, fndecl, 0);
if (coerced_params == error_mark_node)
@@ -2876,7 +3054,7 @@ build_function_call_real (function, params, require_complete, flags)
if (require_complete)
{
- if (value_type == void_type_node)
+ if (TREE_CODE (value_type) == VOID_TYPE)
return result;
result = require_complete_type (result);
}
@@ -2898,12 +3076,6 @@ build_function_call (function, params)
If parmdecls is exhausted, or when an element has NULL as its type,
perform the default conversions.
- RETURN_LOC is the location of the return value, if known, NULL_TREE
- otherwise. This is useful in the case where we can avoid creating
- a temporary variable in the case where we can initialize the return
- value directly. If we are not eliding constructors, then we set this
- to NULL_TREE to avoid this avoidance.
-
NAME is an IDENTIFIER_NODE or 0. It is used only for error messages.
This is also where warnings about wrong number of args are generated.
@@ -2917,18 +3089,15 @@ build_function_call (function, params)
default arguments, if such were specified. Do so here. */
tree
-convert_arguments (return_loc, typelist, values, fndecl, flags)
- tree return_loc, typelist, values, fndecl;
+convert_arguments (typelist, values, fndecl, flags)
+ tree typelist, values, fndecl;
int flags;
{
register tree typetail, valtail;
register tree result = NULL_TREE;
- char *called_thing = 0;
+ const char *called_thing = 0;
int i = 0;
- if (! flag_elide_constructors)
- return_loc = 0;
-
/* Argument passing is always copy-initialization. */
flags |= LOOKUP_ONLYCONVERTING;
@@ -2960,7 +3129,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
if (fndecl)
{
- cp_error_at ("too many arguments to %s `%+D'", called_thing,
+ cp_error_at ("too many arguments to %s `%+#D'", called_thing,
fndecl);
error ("at this point in file");
}
@@ -2973,31 +3142,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
break;
}
- /* The tree type of the parameter being passed may not yet be
- known. In this case, its type is TYPE_UNKNOWN, and will
- be instantiated by the type given by TYPE. If TYPE
- is also NULL, the tree type of VAL is ERROR_MARK_NODE. */
- if (type && type_unknown_p (val))
- val = require_instantiated_type (type, val, integer_zero_node);
- else if (type_unknown_p (val))
- {
- /* Strip the `&' from an overloaded FUNCTION_DECL. */
- if (TREE_CODE (val) == ADDR_EXPR)
- val = TREE_OPERAND (val, 0);
- if (really_overloaded_fn (val))
- cp_error ("insufficient type information to resolve address of overloaded function `%D'",
- DECL_NAME (get_first_fn (val)));
- else
- error ("insufficient type information in parameter list");
- val = integer_zero_node;
- }
- else if (TREE_CODE (val) == OFFSET_REF
- && TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
- {
- /* This is unclean. Should be handled elsewhere. */
- val = build_unary_op (ADDR_EXPR, val, 0);
- }
- else if (TREE_CODE (val) == OFFSET_REF)
+ if (TREE_CODE (val) == OFFSET_REF)
val = resolve_offset_ref (val);
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
@@ -3013,8 +3158,6 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
|| TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
val = default_conversion (val);
-
- val = require_complete_type (val);
}
if (val == error_mark_node)
@@ -3033,7 +3176,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
else
{
parmval = convert_for_initialization
- (return_loc, type, val, flags,
+ (NULL_TREE, type, val, flags,
"argument passing", fndecl, i);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
@@ -3070,9 +3213,10 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
for (; typetail != void_list_node; ++i)
{
- tree type = TREE_VALUE (typetail);
- tree val = TREE_PURPOSE (typetail);
- tree parmval = convert_default_arg (type, val);
+ tree parmval
+ = convert_default_arg (TREE_VALUE (typetail),
+ TREE_PURPOSE (typetail),
+ fndecl);
if (parmval == error_mark_node)
return error_mark_node;
@@ -3088,9 +3232,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
if (fndecl)
{
- char *buf = (char *)alloca (32 + strlen (called_thing));
- sprintf (buf, "too few arguments to %s `%%#D'", called_thing);
- cp_error_at (buf, fndecl);
+ cp_error_at ("too few arguments to %s `%+#D'",
+ called_thing, fndecl);
error ("at this point in file");
}
else
@@ -3117,44 +3260,11 @@ build_x_binary_op (code, arg1, arg2)
}
tree
-build_binary_op (code, arg1, arg2, convert_p)
+build_binary_op (code, arg1, arg2)
enum tree_code code;
tree arg1, arg2;
- int convert_p;
{
- tree args[2];
-
- args[0] = arg1;
- args[1] = arg2;
-
- if (convert_p)
- {
- tree type0, type1;
- args[0] = decay_conversion (args[0]);
- args[1] = decay_conversion (args[1]);
-
- if (args[0] == error_mark_node || args[1] == error_mark_node)
- return error_mark_node;
-
- type0 = TREE_TYPE (args[0]);
- type1 = TREE_TYPE (args[1]);
-
- if (type_unknown_p (args[0]))
- {
- args[0] = instantiate_type (type1, args[0], 1);
- args[0] = decay_conversion (args[0]);
- }
- else if (type_unknown_p (args[1]))
- {
- args[1] = require_instantiated_type (type0, args[1],
- error_mark_node);
- args[1] = decay_conversion (args[1]);
- }
-
- if (IS_AGGR_TYPE (type0) || IS_AGGR_TYPE (type1))
- my_friendly_abort (754867);
- }
- return build_binary_op_nodefault (code, args[0], args[1], code);
+ return build_binary_op_nodefault (code, arg1, arg2, code);
}
/* Build a binary-operation expression without default conversions.
@@ -3244,6 +3354,32 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
op1 = default_conversion (orig_op1);
}
+ /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
+ STRIP_TYPE_NOPS (op0);
+ STRIP_TYPE_NOPS (op1);
+
+ /* DTRT if one side is an overloaded function, but complain about it. */
+ if (type_unknown_p (op0))
+ {
+ tree t = instantiate_type (TREE_TYPE (op1), op0, 0);
+ if (t != error_mark_node)
+ {
+ cp_pedwarn ("assuming cast to `%T' from overloaded function",
+ TREE_TYPE (t));
+ op0 = t;
+ }
+ }
+ if (type_unknown_p (op1))
+ {
+ tree t = instantiate_type (TREE_TYPE (op0), op1, 0);
+ if (t != error_mark_node)
+ {
+ cp_pedwarn ("assuming cast to `%T' from overloaded function",
+ TREE_TYPE (t));
+ op1 = t;
+ }
+ }
+
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
@@ -3252,10 +3388,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
code0 = TREE_CODE (type0);
code1 = TREE_CODE (type1);
- /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
- STRIP_TYPE_NOPS (op0);
- STRIP_TYPE_NOPS (op1);
-
/* If an error was already reported for one of the arguments,
avoid reporting another error. */
@@ -3528,8 +3660,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1)
- && (TYPE_PTRMEMFUNC_FN_TYPE (type0)
- == TYPE_PTRMEMFUNC_FN_TYPE (type1)))
+ && same_type_p (type0, type1))
{
/* The code we generate for the test is:
@@ -3548,21 +3679,22 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree e1, e2, e3;
tree integer_neg_one_node
= build_binary_op (MINUS_EXPR, integer_zero_node,
- integer_one_node, 1);
- e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
- e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
+ integer_one_node);
+ e1 = build_binary_op (EQ_EXPR, index0, index1);
+ e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node);
e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2,
- build_binary_op (EQ_EXPR, delta20, delta21, 1),
- 1);
- e3 = build_binary_op (EQ_EXPR, pfn0, pfn1, 1);
- e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3, 1);
- e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2, 1);
+ build_binary_op (EQ_EXPR, delta20, delta21));
+ /* We can't use build_binary_op for this cmp because it would get
+ confused by the ptr to method types and think we want pmfs. */
+ e3 = build (EQ_EXPR, boolean_type_node, pfn0, pfn1);
+ e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3);
+ e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2);
if (code == EQ_EXPR)
return e2;
- return build_binary_op (EQ_EXPR, e2, integer_zero_node, 1);
+ return build_binary_op (EQ_EXPR, e2, integer_zero_node);
}
else if (TYPE_PTRMEMFUNC_P (type0)
- && TYPE_PTRMEMFUNC_FN_TYPE (type0) == type1)
+ && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0), type1))
{
tree index0 = build_component_ref (op0, index_identifier,
NULL_TREE, 0);
@@ -3572,7 +3704,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree delta21 = integer_zero_node;
tree e1, e2, e3;
tree integer_neg_one_node
- = build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node, 1);
+ = build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node);
if (TREE_CODE (TREE_OPERAND (op1, 0)) == FUNCTION_DECL
&& DECL_VINDEX (TREE_OPERAND (op1, 0)))
{
@@ -3597,23 +3729,22 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
TREE_CONSTANT (nop1) = TREE_CONSTANT (op1);
op1 = nop1;
}
- e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
- e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
+ e1 = build_binary_op (EQ_EXPR, index0, index1);
+ e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node);
e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2,
- build_binary_op (EQ_EXPR, delta20, delta21, 1),
- 1);
- e3 = build_binary_op (EQ_EXPR, pfn0, op1, 1);
- e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3, 1);
- e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2, 1);
+ build_binary_op (EQ_EXPR, delta20, delta21));
+ /* We can't use build_binary_op for this cmp because it would get
+ confused by the ptr to method types and think we want pmfs. */
+ e3 = build (EQ_EXPR, boolean_type_node, pfn0, op1);
+ e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3);
+ e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2);
if (code == EQ_EXPR)
return e2;
- return build_binary_op (EQ_EXPR, e2, integer_zero_node, 1);
+ return build_binary_op (EQ_EXPR, e2, integer_zero_node);
}
else if (TYPE_PTRMEMFUNC_P (type1)
- && TYPE_PTRMEMFUNC_FN_TYPE (type1) == type0)
- {
- return build_binary_op (code, op1, op0, 1);
- }
+ && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1), type0))
+ return build_binary_op (code, op1, op0);
break;
case MAX_EXPR:
@@ -3826,8 +3957,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree primop1 = get_narrower (op1, &unsignedp1);
/* Check for comparison of different enum types. */
- if (flag_int_enum_equivalence == 0
- && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
+ if (TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
!= TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
@@ -3940,12 +4070,34 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
return error_mark_node;
}
+ /* Issue warnings about peculiar, but legal, uses of NULL. */
+ if (/* It's reasonable to use pointer values as operands of &&
+ and ||, so NULL is no exception. */
+ !(code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
+ && (/* If OP0 is NULL and OP1 is not a pointer, or vice versa. */
+ (orig_op0 == null_node
+ && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)
+ /* Or vice versa. */
+ || (orig_op1 == null_node
+ && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
+ /* Or, both are NULL and the operation was not a comparison. */
+ || (orig_op0 == null_node && orig_op1 == null_node
+ && code != EQ_EXPR && code != NE_EXPR)))
+ /* Some sort of arithmetic operation involving NULL was
+ performed. Note that pointer-difference and pointer-addition
+ have already been handled above, and so we don't end up here in
+ that case. */
+ cp_warning ("NULL used in arithmetic");
+
if (! converted)
{
if (TREE_TYPE (op0) != result_type)
op0 = cp_convert (result_type, op0);
if (TREE_TYPE (op1) != result_type)
op1 = cp_convert (result_type, op1);
+
+ if (op0 == error_mark_node || op1 == error_mark_node)
+ return error_mark_node;
}
if (build_type == NULL_TREE)
@@ -3981,7 +4133,7 @@ pointer_int_sum (resultcode, ptrop, intop)
register tree result_type = TREE_TYPE (ptrop);
- if (!complete_type_or_else (result_type))
+ if (!complete_type_or_else (result_type, ptrop))
return error_mark_node;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
@@ -4031,7 +4183,7 @@ pointer_int_sum (resultcode, ptrop, intop)
enum tree_code subcode = resultcode;
if (TREE_CODE (intop) == MINUS_EXPR)
subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
- ptrop = build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1), 1);
+ ptrop = build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1));
intop = TREE_OPERAND (intop, 0);
}
@@ -4048,8 +4200,7 @@ pointer_int_sum (resultcode, ptrop, intop)
intop = cp_convert (result_type,
build_binary_op (MULT_EXPR, intop,
cp_convert (TREE_TYPE (intop),
- size_exp),
- 1));
+ size_exp)));
/* Create the sum or difference. */
@@ -4073,7 +4224,7 @@ pointer_diff (op0, op1, ptrtype)
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (ptrtype);
- if (!complete_type_or_else (target_type))
+ if (!complete_type_or_else (target_type, NULL_TREE))
return error_mark_node;
if (pedantic || warn_pointer_arith)
@@ -4092,7 +4243,7 @@ pointer_diff (op0, op1, ptrtype)
then drop through to build the divide operator. */
op0 = build_binary_op (MINUS_EXPR, cp_convert (restype, op0),
- cp_convert (restype, op1), 1);
+ cp_convert (restype, op1));
/* This generates an error if op1 is a pointer to an incomplete type. */
if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
@@ -4116,25 +4267,25 @@ pointer_diff (op0, op1, ptrtype)
}
/* Handle the case of taking the address of a COMPONENT_REF.
- Called by `build_unary_op' and `build_up_reference'.
+ Called by `build_unary_op'.
ARG is the COMPONENT_REF whose address we want.
- ARGTYPE is the pointer type that this address should have.
- MSG is an error message to print if this COMPONENT_REF is not
- addressable (such as a bitfield). */
+ ARGTYPE is the pointer type that this address should have. */
-tree
-build_component_addr (arg, argtype, msg)
+static tree
+build_component_addr (arg, argtype)
tree arg, argtype;
- char *msg;
{
tree field = TREE_OPERAND (arg, 1);
tree basetype = decl_type_context (field);
tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
- if (DECL_BIT_FIELD (field))
+ my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 981018);
+
+ if (DECL_C_BIT_FIELD (field))
{
- error (msg, IDENTIFIER_POINTER (DECL_NAME (field)));
+ cp_error ("attempt to take address of bit-field structure member `%D'",
+ field);
return error_mark_node;
}
@@ -4236,7 +4387,7 @@ build_unary_op (code, xarg, noconvert)
/* No default_conversion here. It causes trouble for ADDR_EXPR. */
register tree arg = xarg;
register tree argtype = 0;
- char *errstring = NULL;
+ const char *errstring = NULL;
tree val;
if (arg == error_mark_node)
@@ -4365,7 +4516,7 @@ build_unary_op (code, xarg, noconvert)
/* Report something read-only. */
- if (TYPE_READONLY (TREE_TYPE (arg))
+ if (CP_TYPE_CONST_P (TREE_TYPE (arg))
|| TREE_READONLY (arg))
readonly_error (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
@@ -4492,12 +4643,12 @@ build_unary_op (code, xarg, noconvert)
/* Note that this operation never does default_conversion
regardless of NOCONVERT. */
- argtype = TREE_TYPE (arg);
+ argtype = lvalue_type (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
arg = build1
(CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
+ build_pointer_type (TREE_TYPE (argtype)), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
return arg;
}
@@ -4533,7 +4684,7 @@ build_unary_op (code, xarg, noconvert)
if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
return error_mark_node;
return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
- TREE_OPERAND (arg, 1), 1);
+ TREE_OPERAND (arg, 1));
}
/* Uninstantiated types are all functions. Taking the
@@ -4549,47 +4700,31 @@ build_unary_op (code, xarg, noconvert)
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
- if (TREE_CODE (arg) == OVERLOAD
- || (TREE_CODE (arg) == OFFSET_REF
- && TREE_CODE (TREE_OPERAND (arg, 1)) == TEMPLATE_ID_EXPR))
- return build1 (ADDR_EXPR, unknown_type_node, arg);
- else if (TREE_CODE (arg) == TREE_LIST)
- {
- if (TREE_CODE (TREE_VALUE (arg)) == FUNCTION_DECL)
- /* Unique overloaded non-member function. */
- return build_unary_op (ADDR_EXPR, TREE_VALUE (arg), 0);
- if (TREE_CHAIN (arg) == NULL_TREE
- && TREE_CODE (TREE_VALUE (arg)) == TREE_LIST
- && TREE_CODE (TREE_VALUE (TREE_VALUE (arg))) != OVERLOAD)
- /* Unique overloaded member function. */
- return build_unary_op (ADDR_EXPR, TREE_VALUE (TREE_VALUE (arg)),
- 0);
- return build1 (ADDR_EXPR, unknown_type_node, arg);
- }
- else if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
+ if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
+ && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
{
- tree targs;
- tree fn;
-
- /* We don't require a match here; it's possible that the
- context (like a cast to a particular type) will resolve
- the particular choice of template. */
- fn = determine_specialization (arg,
- NULL_TREE,
- &targs,
- 0,
- 0);
-
- if (fn)
- {
- fn = instantiate_template (fn, targs);
- mark_addressable (fn);
- return build_unary_op (ADDR_EXPR, fn, 0);
- }
+ /* They're trying to take the address of a unique non-static
+ member function. This is ill-formed, but let's try to DTRT. */
+ tree base, name;
- return build1 (ADDR_EXPR, unknown_type_node, arg);
+ if (current_class_type
+ && TREE_OPERAND (arg, 0) == current_class_ref)
+ /* An expression like &memfn. */
+ pedwarn ("taking the address of a non-static member function");
+ else
+ pedwarn ("taking the address of a bound member function");
+
+ base = TREE_TYPE (TREE_OPERAND (arg, 0));
+ name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
+
+ cp_pedwarn (" to form a pointer to member function, say `&%T::%D'",
+ base, name);
+ arg = build_offset_ref (base, name);
}
+ if (type_unknown_p (arg))
+ return build1 (ADDR_EXPR, unknown_type_node, arg);
+
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
val = unary_complex_lvalue (code, arg);
@@ -4625,19 +4760,8 @@ build_unary_op (code, xarg, noconvert)
&& !lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
- /* Ordinary case; arg is a COMPONENT_REF or a decl. */
- /* If the lvalue is const or volatile,
- merge that into the type that the address will point to. */
- if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
- || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
- {
- if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
- argtype = cp_build_type_variant (argtype,
- TREE_READONLY (arg),
- TREE_THIS_VOLATILE (arg));
- }
-
- argtype = build_pointer_type (argtype);
+ if (argtype != error_mark_node)
+ argtype = build_pointer_type (argtype);
if (mark_addressable (arg) == 0)
return error_mark_node;
@@ -4646,11 +4770,9 @@ build_unary_op (code, xarg, noconvert)
tree addr;
if (TREE_CODE (arg) == COMPONENT_REF)
- addr = build_component_addr
- (arg, argtype,
- "attempt to take address of bit-field structure member `%s'");
+ addr = build_component_addr (arg, argtype);
else
- addr = build1 (code, argtype, arg);
+ addr = build1 (ADDR_EXPR, argtype, arg);
/* Address of a static or external variable or
function counts as a constant */
@@ -4783,35 +4905,20 @@ unary_complex_lvalue (code, arg)
else
{
tree type;
- tree offset;
if (TREE_OPERAND (arg, 0)
- && (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
- || (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)
- != error_mark_node)))
- if (TREE_CODE (t) != FIELD_DECL)
- {
- /* Don't know if this should return address to just
- _DECL, or actual address resolved in this expression. */
- sorry ("address of bound pointer-to-member expression");
- return error_mark_node;
- }
-
- /* Add in the offset to the field. */
- offset = convert (sizetype,
- size_binop (EASY_DIV_EXPR,
- DECL_FIELD_BITPOS (t),
- size_int (BITS_PER_UNIT)));
-
- /* We offset all pointer to data members by 1 so that we can
- distinguish between a null pointer to data member and the first
- data member of a structure. */
- offset = size_binop (PLUS_EXPR, offset, size_int (1));
+ && ! is_dummy_object (TREE_OPERAND (arg, 0))
+ && TREE_CODE (t) != FIELD_DECL)
+ {
+ cp_error ("taking address of bound pointer-to-member expression");
+ return error_mark_node;
+ }
type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
type = build_pointer_type (type);
- return cp_convert (type, offset);
+ t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
+ return t;
}
}
@@ -4889,7 +4996,8 @@ mark_addressable (exp)
TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (x) = 0;
- rest_of_decl_compilation (x, 0, IDENTIFIER_LOCAL_VALUE (x) == 0,
+ rest_of_decl_compilation (x, 0,
+ !DECL_FUNCTION_SCOPE_P (x),
0);
TREE_ADDRESSABLE (x) = 1;
@@ -4974,24 +5082,20 @@ build_conditional_expr (ifexp, op1, op2)
ifexp = op1 = save_expr (ifexp);
}
+ type1 = TREE_TYPE (op1);
+ code1 = TREE_CODE (type1);
+ type2 = TREE_TYPE (op2);
+ code2 = TREE_CODE (type2);
+ if (op1 == error_mark_node || op2 == error_mark_node
+ || type1 == error_mark_node || type2 == error_mark_node)
+ return error_mark_node;
+
ifexp = cp_convert (boolean_type_node, ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
- op1 = require_instantiated_type (TREE_TYPE (op2), op1, error_mark_node);
- if (op1 == error_mark_node)
- return error_mark_node;
- op2 = require_instantiated_type (TREE_TYPE (op1), op2, error_mark_node);
- if (op2 == error_mark_node)
- return error_mark_node;
-
/* C++: REFERENCE_TYPES must be dereferenced. */
- type1 = TREE_TYPE (op1);
- code1 = TREE_CODE (type1);
- type2 = TREE_TYPE (op2);
- code2 = TREE_CODE (type2);
-
if (code1 == REFERENCE_TYPE)
{
op1 = convert_from_reference (op1);
@@ -5030,10 +5134,9 @@ build_conditional_expr (ifexp, op1, op2)
else if (TREE_READONLY_DECL_P (op2))
op2 = decl_constant_value (op2);
if (type1 != type2)
- type1 = cp_build_type_variant
- (type1,
- TREE_READONLY (op1) || TREE_READONLY (op2),
- TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
+ type1 = cp_build_qualified_type
+ (type1, (CP_TYPE_QUALS (TREE_TYPE (op1))
+ | CP_TYPE_QUALS (TREE_TYPE (op2))));
/* ??? This is a kludge to deal with the fact that
we don't sort out integers and enums properly, yet. */
result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
@@ -5089,7 +5192,7 @@ build_conditional_expr (ifexp, op1, op2)
if (code1 == RECORD_TYPE && code2 == RECORD_TYPE
&& real_lvalue_p (op1) && real_lvalue_p (op2)
- && comptypes (type1, type2, -1))
+ && comptypes (type1, type2, COMPARE_BASE | COMPARE_RELAXED))
{
type1 = build_reference_type (type1);
type2 = build_reference_type (type2);
@@ -5106,10 +5209,10 @@ build_conditional_expr (ifexp, op1, op2)
if (type1 == type2)
result_type = type1;
else
- result_type = cp_build_type_variant
- (type1,
- TREE_READONLY (op1) || TREE_READONLY (op2),
- TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
+ result_type =
+ cp_build_qualified_type (type1,
+ CP_TYPE_QUALS (TREE_TYPE (op1))
+ | CP_TYPE_QUALS (TREE_TYPE (op2)));
}
else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE)
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
@@ -5143,7 +5246,7 @@ build_conditional_expr (ifexp, op1, op2)
result_type = qualify_type (type2, type1);
}
/* C++ */
- else if (comptypes (type2, type1, 0))
+ else if (same_or_base_type_p (type2, type1))
result_type = type2;
else if (IS_AGGR_TYPE (TREE_TYPE (type1))
&& IS_AGGR_TYPE (TREE_TYPE (type2))
@@ -5183,6 +5286,10 @@ build_conditional_expr (ifexp, op1, op2)
pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type2;
}
+ if (type2 == unknown_type_node)
+ result_type = type1;
+ else if (type1 == unknown_type_node)
+ result_type = type2;
if (!result_type)
{
@@ -5202,10 +5309,13 @@ build_conditional_expr (ifexp, op1, op2)
tree tmp;
if (code2 == POINTER_TYPE)
tmp = build_pointer_type
- (build_type_variant (TREE_TYPE (type2), 1, 1));
+ (cp_build_qualified_type (TREE_TYPE (type2),
+ TYPE_QUAL_CONST
+ | TYPE_QUAL_VOLATILE
+ | TYPE_QUAL_RESTRICT));
else
tmp = type2;
- tmp = build_type_conversion (CONVERT_EXPR, tmp, op1, 0);
+ tmp = build_type_conversion (tmp, op1, 0);
if (tmp == NULL_TREE)
{
cp_error ("incompatible types `%T' and `%T' in `?:'",
@@ -5224,11 +5334,14 @@ build_conditional_expr (ifexp, op1, op2)
tree tmp;
if (code1 == POINTER_TYPE)
tmp = build_pointer_type
- (build_type_variant (TREE_TYPE (type1), 1, 1));
+ (cp_build_qualified_type (TREE_TYPE (type1),
+ TYPE_QUAL_CONST
+ | TYPE_QUAL_VOLATILE
+ | TYPE_QUAL_RESTRICT));
else
tmp = type1;
- tmp = build_type_conversion (CONVERT_EXPR, tmp, op2, 0);
+ tmp = build_type_conversion (tmp, op2, 0);
if (tmp == NULL_TREE)
{
cp_error ("incompatible types `%T' and `%T' in `?:'",
@@ -5320,6 +5433,7 @@ build_compound_expr (list)
tree list;
{
register tree rest;
+ tree first;
if (TREE_READONLY_DECL_P (TREE_VALUE (list)))
TREE_VALUE (list) = decl_constant_value (TREE_VALUE (list));
@@ -5339,14 +5453,21 @@ build_compound_expr (list)
return TREE_VALUE (list);
}
+ first = TREE_VALUE (list);
+ first = require_complete_type_in_void (first);
+ if (first == error_mark_node)
+ return error_mark_node;
+
rest = build_compound_expr (TREE_CHAIN (list));
+ if (rest == error_mark_node)
+ return error_mark_node;
/* When pedantic, a compound expression cannot be a constant expression. */
- if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
+ if (! TREE_SIDE_EFFECTS (first) && ! pedantic)
return rest;
return build (COMPOUND_EXPR, TREE_TYPE (rest),
- break_out_cleanups (TREE_VALUE (list)), rest);
+ break_out_cleanups (first), rest);
}
tree
@@ -5379,13 +5500,6 @@ build_static_cast (type, expr)
if (TREE_CODE (type) == VOID_TYPE)
return build1 (CONVERT_EXPR, type, expr);
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
if (TREE_CODE (type) == REFERENCE_TYPE)
return (convert_from_reference
(convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
@@ -5409,22 +5523,18 @@ build_static_cast (type, expr)
{
tree binfo;
if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
- && (TYPE_READONLY (TREE_TYPE (type))
- >= TYPE_READONLY (TREE_TYPE (intype)))
- && (TYPE_VOLATILE (TREE_TYPE (type))
- >= TYPE_VOLATILE (TREE_TYPE (intype)))
+ && at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (intype))
&& (binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 0))
&& ! TREE_VIA_VIRTUAL (binfo))
ok = 1;
}
else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
{
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))),
- TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))), 1)
- && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (type)))
- >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype))))
- && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type)))
- >= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype))))
+ if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))))
+ && at_least_as_qualified_p (TREE_TYPE (TREE_TYPE (type)),
+ TREE_TYPE (TREE_TYPE (intype)))
&& (binfo = get_binfo (TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)), 0))
&& ! TREE_VIA_VIRTUAL (binfo))
@@ -5473,13 +5583,6 @@ build_reinterpret_cast (type, expr)
expr = TREE_OPERAND (expr, 0);
}
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
intype = TREE_TYPE (expr);
if (TREE_CODE (type) == REFERENCE_TYPE)
@@ -5497,7 +5600,8 @@ build_reinterpret_cast (type, expr)
expr = build_indirect_ref (expr, 0);
return expr;
}
- else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ else if (same_type_p (TYPE_MAIN_VARIANT (intype),
+ TYPE_MAIN_VARIANT (type)))
return build_static_cast (type, expr);
if (TYPE_PTR_P (type) && (TREE_CODE (intype) == INTEGER_TYPE
@@ -5528,7 +5632,7 @@ build_reinterpret_cast (type, expr)
return fold (build1 (NOP_EXPR, type, expr));
}
else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
- || (TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype)))
+ || (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
{
pedwarn ("ANSI C++ forbids casting between pointers to functions and objects");
if (TREE_READONLY_DECL_P (expr))
@@ -5563,6 +5667,20 @@ build_const_cast (type, expr)
return t;
}
+ if (!POINTER_TYPE_P (type))
+ {
+ cp_error ("`%T' is not a pointer, reference, or pointer-to-data-member type",
+ type);
+ cp_error ("as required by const_cast");
+ }
+ else if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ {
+ cp_error ("`%T' is a pointer or reference to a function type",
+ type);
+ cp_error ("which is forbidden by const_cast");
+ return error_mark_node;
+ }
+
if (TREE_CODE (type) != REFERENCE_TYPE)
{
expr = decay_conversion (expr);
@@ -5574,16 +5692,9 @@ build_const_cast (type, expr)
expr = TREE_OPERAND (expr, 0);
}
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
intype = TREE_TYPE (expr);
- if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ if (same_type_p (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type)))
return build_static_cast (type, expr);
else if (TREE_CODE (type) == REFERENCE_TYPE)
{
@@ -5619,6 +5730,7 @@ build_c_cast (type, expr)
tree type, expr;
{
register tree value = expr;
+ tree otype;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
@@ -5630,9 +5742,7 @@ build_c_cast (type, expr)
&& TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
value = TREE_OPERAND (value, 0);
- if (TREE_TYPE (expr)
- && TREE_CODE (TREE_TYPE (expr)) == OFFSET_TYPE
- && TREE_CODE (type) != OFFSET_TYPE)
+ if (TREE_CODE (value) == OFFSET_REF)
value = resolve_offset_ref (value);
if (TREE_CODE (type) == ARRAY_TYPE)
@@ -5673,116 +5783,99 @@ build_c_cast (type, expr)
return t;
}
+ /* Convert functions and arrays to pointers and
+ convert references to their expanded types,
+ but don't convert any other types. If, however, we are
+ casting to a class type, there's no reason to do this: the
+ cast will only succeed if there is a converting constructor,
+ and the default conversions will be done at that point. In
+ fact, doing the default conversion here is actually harmful
+ in cases like this:
+
+ typedef int A[2];
+ struct S { S(const A&); };
+
+ since we don't want the array-to-pointer conversion done. */
+ if (!IS_AGGR_TYPE (type))
+ {
+ if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
+ || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+ /* Don't do the default conversion on a ->* expression. */
+ && ! (TREE_CODE (type) == POINTER_TYPE
+ && bound_pmf_p (value)))
+ || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
+ value = default_conversion (value);
+ }
+ else if (TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
+ /* However, even for class types, we still need to strip away
+ the reference type, since the call to convert_force below
+ does not expect the input expression to be of reference
+ type. */
+ value = convert_from_reference (value);
+
+ otype = TREE_TYPE (value);
+
+ /* Optionally warn about potentially worrisome casts. */
+
+ if (warn_cast_qual
+ && TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == POINTER_TYPE
+ && !at_least_as_qualified_p (TREE_TYPE (type),
+ TREE_TYPE (otype)))
+ cp_warning ("cast discards qualifiers from pointer target type");
+
+ /* Warn about possible alignment problems. */
+ if (STRICT_ALIGNMENT && warn_cast_align
+ && TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
+ && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+ && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
+ warning ("cast increases required alignment of target type");
+
+#if 0
+ /* We should see about re-enabling these, they seem useful to
+ me. */
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TREE_CODE (otype) == POINTER_TYPE
+ && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
+ warning ("cast from pointer to integer of different size");
+
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == INTEGER_TYPE
+ && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
+ /* Don't warn about converting 0 to pointer,
+ provided the 0 was explicit--not cast or made by folding. */
+ && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)))
+ warning ("cast to pointer from integer of different size");
+#endif
+
if (TREE_CODE (type) == VOID_TYPE)
- value = build1 (CONVERT_EXPR, type, value);
- else if (TREE_TYPE (value) == NULL_TREE
- || type_unknown_p (value))
{
- value = instantiate_type (type, value, 1);
- /* Did we lose? */
- if (value == error_mark_node)
- return error_mark_node;
+ value = require_complete_type_in_void (value);
+ if (value != error_mark_node)
+ value = build1 (CONVERT_EXPR, void_type_node, value);
}
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ value = (convert_from_reference
+ (convert_to_reference (type, value, CONV_C_CAST,
+ LOOKUP_COMPLAIN, NULL_TREE)));
else
{
- tree otype;
-
- /* Convert functions and arrays to pointers and
- convert references to their expanded types,
- but don't convert any other types. If, however, we are
- casting to a class type, there's no reason to do this: the
- cast will only succeed if there is a converting constructor,
- and the default conversions will be done at that point. In
- fact, doing the default conversion here is actually harmful
- in cases like this:
-
- typedef int A[2];
- struct S { S(const A&); };
-
- since we don't want the array-to-pointer conversion done. */
- if (!IS_AGGR_TYPE (type))
- {
- if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
- || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
- /* Don't do the default conversion if we want a
- pointer to a function. */
- && ! (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
- || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
- value = default_conversion (value);
- }
- else if (TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
- /* However, even for class types, we still need to strip away
- the reference type, since the call to convert_force below
- does not expect the input expression to be of reference
- type. */
- value = convert_from_reference (value);
-
- otype = TREE_TYPE (value);
+ tree ovalue;
- /* Optionally warn about potentially worrisome casts. */
+ if (TREE_READONLY_DECL_P (value))
+ value = decl_constant_value (value);
- if (warn_cast_qual
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE)
- {
- /* For C++ we make these regular warnings, rather than
- softening them into pedwarns. */
- if (TYPE_VOLATILE (TREE_TYPE (otype))
- && ! TYPE_VOLATILE (TREE_TYPE (type)))
- warning ("cast discards `volatile' from pointer target type");
- if (TYPE_READONLY (TREE_TYPE (otype))
- && ! TYPE_READONLY (TREE_TYPE (type)))
- warning ("cast discards `const' from pointer target type");
- }
-
- /* Warn about possible alignment problems. */
- if (STRICT_ALIGNMENT && warn_cast_align
- && TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
- && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
- && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
- warning ("cast increases required alignment of target type");
-
-#if 0
- /* We should see about re-enabling these, they seem useful to
- me. */
- if (TREE_CODE (type) == INTEGER_TYPE
- && TREE_CODE (otype) == POINTER_TYPE
- && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
- warning ("cast from pointer to integer of different size");
-
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (otype) == INTEGER_TYPE
- && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
- /* Don't warn about converting 0 to pointer,
- provided the 0 was explicit--not cast or made by folding. */
- && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)))
- warning ("cast to pointer from integer of different size");
-#endif
+ ovalue = value;
+ value = convert_force (type, value, CONV_C_CAST);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- value = (convert_from_reference
- (convert_to_reference (type, value, CONV_C_CAST,
- LOOKUP_COMPLAIN, NULL_TREE)));
- else
+ /* Ignore any integer overflow caused by the cast. */
+ if (TREE_CODE (value) == INTEGER_CST)
{
- tree ovalue;
-
- if (TREE_READONLY_DECL_P (value))
- value = decl_constant_value (value);
-
- ovalue = value;
- value = convert_force (type, value, CONV_C_CAST);
-
- /* Ignore any integer overflow caused by the cast. */
- if (TREE_CODE (value) == INTEGER_CST)
- {
- TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
- TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
- }
+ TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+ TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
}
}
@@ -5909,6 +6002,9 @@ build_modify_expr (lhs, modifycode, rhs)
olhstype = lhstype = TREE_TYPE (lhs);
}
+ if (lhs == error_mark_node)
+ return lhs;
+
if (TREE_CODE (lhstype) == REFERENCE_TYPE
&& modifycode != INIT_EXPR)
{
@@ -5955,7 +6051,7 @@ build_modify_expr (lhs, modifycode, rhs)
else
{
lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs, 1);
+ newrhs = build_binary_op (modifycode, lhs, rhs);
if (newrhs == error_mark_node)
{
cp_error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
@@ -6022,12 +6118,15 @@ build_modify_expr (lhs, modifycode, rhs)
&& ! (TREE_CODE (lhs) == COMPONENT_REF
&& (IS_SIGNATURE_POINTER (TREE_TYPE (TREE_OPERAND (lhs, 0)))
|| IS_SIGNATURE_REFERENCE (TREE_TYPE (TREE_OPERAND (lhs, 0)))))
- && (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
+ && (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype)
+ /* Functions are not modifiable, even though they are
+ lvalues. */
+ || TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE
|| ((TREE_CODE (lhstype) == RECORD_TYPE
|| TREE_CODE (lhstype) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (lhstype))
|| (TREE_CODE (lhstype) == REFERENCE_TYPE
- && TYPE_READONLY (TREE_TYPE (lhstype)))))
+ && CP_TYPE_CONST_P (TREE_TYPE (lhstype)))))
readonly_error (lhs, "assignment", 0);
/* If storing into a structure or union member,
@@ -6063,14 +6162,6 @@ build_modify_expr (lhs, modifycode, rhs)
current_function_just_assigned_this = 1;
}
- /* The TREE_TYPE of RHS may be TYPE_UNKNOWN. This can happen
- when the type of RHS is not yet known, i.e. its type
- is inherited from LHS. */
- rhs = require_instantiated_type (lhstype, newrhs, error_mark_node);
- if (rhs == error_mark_node)
- return error_mark_node;
- newrhs = rhs;
-
if (modifycode != INIT_EXPR)
{
/* Make modifycode now either a NOP_EXPR or an INIT_EXPR. */
@@ -6111,7 +6202,7 @@ build_modify_expr (lhs, modifycode, rhs)
{
int from_array;
- if (! comptypes (lhstype, TREE_TYPE (rhs), 0))
+ if (!same_or_base_type_p (lhstype, TREE_TYPE (rhs)))
{
cp_error ("incompatible types in assignment of `%T' to `%T'",
TREE_TYPE (rhs), lhstype);
@@ -6271,19 +6362,15 @@ build_x_modify_expr (lhs, modifycode, rhs)
return build_modify_expr (lhs, modifycode, rhs);
}
-/* Return 0 if EXP is not a valid lvalue in this language
- even though `lvalue_or_else' would accept it. */
-
-int
-language_lvalue_valid (exp)
- tree exp ATTRIBUTE_UNUSED;
-{
- return 1;
-}
/* Get difference in deltas for different pointer to member function
types. Return integer_zero_node, if FROM cannot be converted to a
- TO type. If FORCE is true, then allow reverse conversions as well. */
+ TO type. If FORCE is true, then allow reverse conversions as well.
+
+ Note that the naming of FROM and TO is kind of backwards; the return
+ value is what we add to a TO in order to get a FROM. They are named
+ this way because we call this function to find out how to convert from
+ a pointer to member of FROM to a pointer to member of TO. */
static tree
get_delta_difference (from, to, force)
@@ -6331,7 +6418,7 @@ get_delta_difference (from, to, force)
return build_binary_op (MINUS_EXPR,
integer_zero_node,
- delta, 1);
+ delta);
}
if (TREE_VIA_VIRTUAL (binfo))
@@ -6350,7 +6437,7 @@ get_delta_difference (from, to, force)
return BINFO_OFFSET (binfo);
}
-static tree
+tree
build_ptrmemfunc1 (type, delta, idx, pfn, delta2)
tree type, delta, idx, pfn, delta2;
{
@@ -6439,15 +6526,15 @@ build_ptrmemfunc (type, pfn, force)
tree type, pfn;
int force;
{
- tree idx = integer_zero_node;
- tree delta = integer_zero_node;
- tree delta2 = integer_zero_node;
- tree vfield_offset;
- tree npfn = NULL_TREE;
-
+ tree fn;
+
/* Handle multiple conversions of pointer to member functions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
{
+ tree idx = integer_zero_node;
+ tree delta = integer_zero_node;
+ tree delta2 = integer_zero_node;
+ tree npfn = NULL_TREE;
tree ndelta, ndelta2;
tree e1, e2, e3, n;
tree pfn_type;
@@ -6458,21 +6545,45 @@ build_ptrmemfunc (type, pfn, force)
pfn_type = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn));
if (!force
- && comp_target_types (type, pfn_type, 0) != 1)
+ && comp_target_types (type, pfn_type, 1) != 1)
cp_error ("conversion to `%T' from `%T'", type, pfn_type);
- ndelta = cp_convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
- ndelta2 = cp_convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
- idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0);
+ if (TREE_CODE (pfn) == PTRMEM_CST)
+ {
+ /* We could just build the resulting CONSTRUCTOR now, but we
+ don't, relying on the general machinery below, together
+ with constant-folding, to do the right thing. We don't
+ want to return a PTRMEM_CST here, even though we could,
+ because a pointer-to-member constant ceases to be a
+ constant (from the point of view of the language) when it
+ is cast to another type. */
+
+ expand_ptrmemfunc_cst (pfn, &ndelta, &idx, &npfn, &ndelta2);
+ if (npfn)
+ /* This constant points to a non-virtual function.
+ NDELTA2 will be NULL, but it's value doesn't really
+ matter since we won't use it anyhow. */
+ ndelta2 = integer_zero_node;
+ }
+ else
+ {
+ ndelta = cp_convert (ptrdiff_type_node,
+ build_component_ref (pfn,
+ delta_identifier,
+ NULL_TREE, 0));
+ ndelta2 = cp_convert (ptrdiff_type_node,
+ DELTA2_FROM_PTRMEMFUNC (pfn));
+ idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0);
+ }
n = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (pfn_type)),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
-
- delta = build_binary_op (PLUS_EXPR, ndelta, n, 1);
- delta2 = build_binary_op (PLUS_EXPR, ndelta2, n, 1);
+ delta = build_binary_op (PLUS_EXPR, ndelta, n);
+ delta2 = build_binary_op (PLUS_EXPR, ndelta2, n);
e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node));
+ /* If it's a virtual function, this is what we want. */
e2 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx,
NULL_TREE, delta2);
@@ -6480,8 +6591,10 @@ build_ptrmemfunc (type, pfn, force)
npfn = build1 (NOP_EXPR, type, pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn,
- NULL_TREE);
+ /* But if it's a non-virtual function, or NULL, we use this
+ instead. */
+ e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta,
+ idx, npfn, NULL_TREE);
return build_conditional_expr (e1, e2, e3);
}
@@ -6494,55 +6607,115 @@ build_ptrmemfunc (type, pfn, force)
pfn, NULL_TREE);
}
- if (TREE_CODE (pfn) == TREE_LIST
- || (TREE_CODE (pfn) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
+ if (type_unknown_p (pfn))
return instantiate_type (type, pfn, 1);
- if (!force
- && comp_target_types (type, TREE_TYPE (pfn), 0) != 1)
- cp_error ("conversion to `%T' from `%T'", type, TREE_TYPE (pfn));
+ fn = TREE_OPERAND (pfn, 0);
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
+ return make_ptrmem_cst (build_ptrmemfunc_type (type), fn);
+}
- /* Allow pointer to member conversions here. */
- delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
- TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
- force);
- delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1);
+/* Return the DELTA, IDX, PFN, and DELTA2 values for the PTRMEM_CST
+ given by CST. */
- if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
- warning ("assuming pointer to member function is non-virtual");
+void
+expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2)
+ tree cst;
+ tree *delta;
+ tree *idx;
+ tree *pfn;
+ tree *delta2;
+{
+ tree type = TREE_TYPE (cst);
+ tree fn = PTRMEM_CST_MEMBER (cst);
+ tree ptr_class, fn_class;
- if (TREE_CODE (TREE_OPERAND (pfn, 0)) == FUNCTION_DECL
- && DECL_VINDEX (TREE_OPERAND (pfn, 0)))
- {
- /* Find the offset to the vfield pointer in the object. */
- vfield_offset = get_binfo (DECL_CONTEXT (TREE_OPERAND (pfn, 0)),
- DECL_CLASS_CONTEXT (TREE_OPERAND (pfn, 0)),
- 0);
- vfield_offset = get_vfield_offset (vfield_offset);
- delta2 = size_binop (PLUS_EXPR, vfield_offset, delta2);
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
- /* Map everything down one to make room for the null pointer to member. */
- idx = size_binop (PLUS_EXPR,
- DECL_VINDEX (TREE_OPERAND (pfn, 0)),
- integer_one_node);
+ /* The class that the function belongs to. */
+ fn_class = DECL_CLASS_CONTEXT (fn);
+
+ /* The class that we're creating a pointer to member of. */
+ ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
+
+ /* First, calculate the adjustment to the function's class. */
+ *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
+
+ if (!DECL_VIRTUAL_P (fn))
+ {
+ *idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+ *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
+ *delta2 = NULL_TREE;
}
else
{
- idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+ /* If we're dealing with a virtual function, we have to adjust 'this'
+ again, to point to the base which provides the vtable entry for
+ fn; the call will do the opposite adjustment. */
+ tree orig_class = DECL_VIRTUAL_CONTEXT (fn);
+ tree binfo = binfo_or_else (orig_class, fn_class);
+ *delta = size_binop (PLUS_EXPR, *delta, BINFO_OFFSET (binfo));
- if (type == TREE_TYPE (pfn))
- {
- npfn = pfn;
- }
- else
- {
- npfn = build1 (NOP_EXPR, type, pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- }
+ /* Map everything down one to make room for the null PMF. */
+ *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), integer_one_node);
+ *pfn = NULL_TREE;
+
+ /* Offset from an object of PTR_CLASS to the vptr for ORIG_CLASS. */
+ *delta2 = size_binop (PLUS_EXPR, *delta,
+ get_vfield_offset (TYPE_BINFO (orig_class)));
+ }
+}
+
+/* Return an expression for DELTA2 from the pointer-to-member function
+ given by T. */
+
+tree
+delta2_from_ptrmemfunc (t)
+ tree t;
+{
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ expand_ptrmemfunc_cst (t, &delta, &idx, &pfn, &delta2);
+ if (delta2)
+ return delta2;
+ }
+
+ return (build_component_ref
+ (build_component_ref (t,
+ pfn_or_delta2_identifier, NULL_TREE,
+ 0),
+ delta2_identifier, NULL_TREE, 0));
+}
+
+/* Return an expression for PFN from the pointer-to-member function
+ given by T. */
+
+tree
+pfn_from_ptrmemfunc (t)
+ tree t;
+{
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ expand_ptrmemfunc_cst (t, &delta, &idx, &pfn, &delta2);
+ if (pfn)
+ return pfn;
}
- return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn, delta2);
+ return (build_component_ref
+ (build_component_ref (t,
+ pfn_or_delta2_identifier, NULL_TREE,
+ 0),
+ pfn_identifier, NULL_TREE, 0));
}
/* Convert value RHS to type TYPE as preparation for an assignment
@@ -6561,62 +6734,55 @@ build_ptrmemfunc (type, pfn, force)
static tree
convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
tree type, rhs;
- char *errtype;
+ const char *errtype;
tree fndecl;
int parmnum;
{
register enum tree_code codel = TREE_CODE (type);
register tree rhstype;
- register enum tree_code coder = TREE_CODE (TREE_TYPE (rhs));
-
- if (coder == UNKNOWN_TYPE)
- rhs = instantiate_type (type, rhs, 1);
-
- if (coder == ERROR_MARK)
- return error_mark_node;
+ register enum tree_code coder;
if (codel == OFFSET_TYPE)
- {
- type = TREE_TYPE (type);
- codel = TREE_CODE (type);
- }
+ my_friendly_abort (990505);
+
+ if (TREE_CODE (rhs) == OFFSET_REF)
+ rhs = resolve_offset_ref (rhs);
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
- if (rhs == error_mark_node)
+ if (rhs == error_mark_node || TREE_TYPE (rhs) == error_mark_node)
return error_mark_node;
-
if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
- {
- rhs = resolve_offset_ref (rhs);
- if (rhs == error_mark_node)
- return error_mark_node;
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
-
if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
+ || is_overloaded_fn (rhs))
rhs = default_conversion (rhs);
else if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
rhs = convert_from_reference (rhs);
+ /* If rhs is some sort of overloaded function, ocp_convert will either
+ do the right thing or complain; we don't need to check anything else.
+ So just hand off. */
+ if (type_unknown_p (rhs))
+ return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
+
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
+ /* Issue warnings about peculiar, but legal, uses of NULL. */
+ if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
+ cp_warning ("converting NULL to non-pointer type");
+
/* This should no longer change types on us. */
if (TREE_CODE (rhs) == CONST_DECL)
rhs = DECL_INITIAL (rhs);
else if (TREE_READONLY_DECL_P (rhs))
rhs = decl_constant_value (rhs);
- if (comptypes (type, rhstype, 1))
+ if (same_type_p (type, rhstype))
{
overflow_warning (rhs);
return rhs;
@@ -6708,22 +6874,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (binfo == 0)
return error_not_base_type (ttl, ttr);
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- {
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
- rhstype, parmnum, fndecl);
- else
- cp_pedwarn ("%s to `%T' from `%T' discards const",
- errtype, type, rhstype);
- }
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
+ if (!at_least_as_qualified_p (ttl, ttr))
{
if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
+ cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
- cp_pedwarn ("%s to `%T' from `%T' discards volatile",
+ cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
}
@@ -6769,25 +6926,18 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
&& binfo_member (TYPE_OFFSET_BASETYPE (ttr),
CLASSTYPE_VBASECLASSES (TYPE_OFFSET_BASETYPE (ttl))))
{
- sorry ("%s between pointer to members converting across virtual baseclasses", errtype);
+ error ("%s between pointer to members converting across virtual baseclasses", errtype);
return error_mark_node;
}
- else if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- {
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
- rhstype, parmnum, fndecl);
- else
- cp_pedwarn ("%s to `%T' from `%T' discards const",
- errtype, type, rhstype);
- }
- else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
+ else if (!at_least_as_qualified_p (ttl, ttr))
{
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
+ if (string_conv_p (type, rhs, 1))
+ /* converting from string constant to char *, OK. */;
+ else if (fndecl)
+ cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
- cp_pedwarn ("%s to `%T' from `%T' discards volatile",
+ cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
else if (TREE_CODE (ttl) == TREE_CODE (ttr)
@@ -6804,7 +6954,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
else
{
- int add_quals = 0, const_parity = 0, volatile_parity = 0;
+ int add_quals = 0;
+ int drops_quals = 0;
int left_const = 1;
int unsigned_parity;
int nptrs = 0;
@@ -6813,12 +6964,10 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
for (; ; ttl = TREE_TYPE (ttl), ttr = TREE_TYPE (ttr))
{
nptrs -= 1;
- const_parity |= (TYPE_READONLY (ttl) < TYPE_READONLY (ttr));
- volatile_parity |= (TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr));
+ drops_quals |= !at_least_as_qualified_p (ttl, ttr);
if (! left_const
- && (TYPE_READONLY (ttl) > TYPE_READONLY (ttr)
- || TYPE_VOLATILE (ttl) > TYPE_VOLATILE (ttr)))
+ && !at_least_as_qualified_p (ttr, ttl))
add_quals = 1;
left_const &= TYPE_READONLY (ttl);
@@ -6846,22 +6995,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
cp_pedwarn ("%s to `%T' from `%T' adds cv-quals without intervening `const'",
errtype, type, rhstype);
}
- if (const_parity)
+ if (drops_quals)
{
if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards const",
+ cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
- cp_pedwarn ("%s to `%T' from `%T' discards const",
- errtype, type, rhstype);
- }
- if (volatile_parity)
- {
- if (fndecl)
- cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile",
- rhstype, parmnum, fndecl);
- else
- cp_pedwarn ("%s to `%T' from `%T' discards volatile",
+ cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
if (unsigned_parity > 0)
@@ -6887,7 +7027,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
member function pointers as C. Emit warnings here. */
if (TREE_CODE (ttl) == FUNCTION_TYPE
|| TREE_CODE (ttl) == METHOD_TYPE)
- if (! comptypes (ttl, ttr, 0))
+ if (!same_or_base_type_p (ttl, ttr))
{
warning ("conflicting function types in %s:", errtype);
cp_warning ("\t`%T' != `%T'", type, rhstype);
@@ -6905,7 +7045,9 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
return cp_convert (type, rhs);
}
- else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
+ else if (codel == POINTER_TYPE
+ && (coder == INTEGER_TYPE
+ || coder == BOOLEAN_TYPE))
{
/* An explicit constant 0 can convert to a pointer,
but not a 0 that results from casting or folding. */
@@ -6994,8 +7136,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
-/* Convert RHS to be of type TYPE. If EXP is non-zero,
- it is the target of the initialization.
+/* Convert RHS to be of type TYPE.
+ If EXP is non-zero, it is the target of the initialization.
ERRTYPE is a string to use in error messages.
Two major differences between the behavior of
@@ -7014,7 +7156,7 @@ tree
convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
tree exp, type, rhs;
int flags;
- char *errtype;
+ const char *errtype;
tree fndecl;
int parmnum;
{
@@ -7033,7 +7175,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
|| (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
+ if (TREE_CODE (rhs) == OFFSET_REF)
{
rhs = resolve_offset_ref (rhs);
if (rhs == error_mark_node)
@@ -7047,20 +7189,15 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
&& TREE_CODE (type) != ARRAY_TYPE
&& (TREE_CODE (type) != REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
- || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
+ || (TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
+ && (TREE_CODE (type) != REFERENCE_TYPE
+ || TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE))
|| TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
rhs = default_conversion (rhs);
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
- if (coder == UNKNOWN_TYPE)
- {
- rhs = instantiate_type (type, rhs, 1);
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
-
if (coder == ERROR_MARK)
return error_mark_node;
@@ -7087,11 +7224,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
return rhs;
}
- rhs = require_complete_type (rhs);
- if (rhs == error_mark_node)
- return error_mark_node;
-
- if (exp != 0) exp = require_complete_type (exp);
+ if (exp != 0)
+ exp = require_complete_type (exp);
if (exp == error_mark_node)
return error_mark_node;
@@ -7109,8 +7243,16 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (type == TREE_TYPE (rhs))
{
+ /* Issue warnings about peculiar, but legal, uses of NULL. We
+ do this *before* the call to decl_constant_value so as to
+ avoid duplicate warnings on code like `const int I = NULL;
+ f(I);'. */
+ if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
+ cp_warning ("converting NULL to non-pointer type");
+
if (TREE_READONLY_DECL_P (rhs))
rhs = decl_constant_value (rhs);
+
return rhs;
}
@@ -7162,7 +7304,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
else
{
tree type = TREE_TYPE (o[i]);
- if (TYPE_READONLY (type)
+ if (CP_TYPE_CONST_P (type)
|| ((TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (type)))
@@ -7219,6 +7361,13 @@ c_expand_return (retval)
return;
}
+ /* Only operator new(...) throw(), can return NULL [expr.new/13]. */
+ if ((DECL_NAME (current_function_decl) == ansi_opname[(int) NEW_EXPR]
+ || DECL_NAME (current_function_decl) == ansi_opname[(int) VEC_NEW_EXPR])
+ && !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
+ && null_ptr_cst_p (retval))
+ cp_warning ("operator new should throw an exception, not return NULL");
+
if (retval == NULL_TREE)
{
/* A non-named return value does not count. */
@@ -7283,7 +7432,7 @@ c_expand_return (retval)
if (retval == result
|| DECL_CONSTRUCTOR_P (current_function_decl))
/* It's already done for us. */;
- else if (TREE_TYPE (retval) == void_type_node)
+ else if (TREE_CODE (TREE_TYPE (retval)) == VOID_TYPE)
{
pedwarn ("return of void value in function returning non-void");
expand_expr_stmt (retval);
@@ -7351,9 +7500,9 @@ c_expand_return (retval)
if (TEMP_NAME_P (DECL_NAME (whats_returned)))
warning ("reference to non-lvalue returned");
else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE
- && ! TREE_STATIC (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_PUBLIC (whats_returned))
+ && DECL_FUNCTION_SCOPE_P (whats_returned)
+ && !(TREE_STATIC (whats_returned)
+ || TREE_PUBLIC (whats_returned)))
cp_warning_at ("reference to local variable `%D' returned", whats_returned);
}
}
@@ -7363,9 +7512,9 @@ c_expand_return (retval)
if (TREE_CODE (whats_returned) == VAR_DECL
&& DECL_NAME (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_STATIC (whats_returned)
- && !TREE_PUBLIC (whats_returned))
+ && DECL_FUNCTION_SCOPE_P (whats_returned)
+ && !(TREE_STATIC (whats_returned)
+ || TREE_PUBLIC (whats_returned)))
cp_warning_at ("address of local variable `%D' returned", whats_returned);
}
}
@@ -7403,45 +7552,26 @@ tree
c_expand_start_case (exp)
tree exp;
{
- tree type;
- register enum tree_code code;
-
- /* Convert from references, etc. */
- exp = default_conversion (exp);
- type = TREE_TYPE (exp);
- code = TREE_CODE (type);
-
- if (IS_AGGR_TYPE_CODE (code))
- exp = build_type_conversion (CONVERT_EXPR, integer_type_node, exp, 1);
+ tree type, idx;
+ exp = build_expr_type_conversion (WANT_INT | WANT_ENUM, exp, 1);
if (exp == NULL_TREE)
{
error ("switch quantity not an integer");
exp = error_mark_node;
}
- type = TREE_TYPE (exp);
- code = TREE_CODE (type);
-
- if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
- {
- error ("switch quantity not an integer");
- exp = error_mark_node;
- }
- else
- {
- tree idx;
+ if (exp == error_mark_node)
+ return error_mark_node;
- exp = default_conversion (exp);
- type = TREE_TYPE (exp);
- idx = get_unwidened (exp, 0);
- /* We can't strip a conversion from a signed type to an unsigned,
- because if we did, int_fits_type_p would do the wrong thing
- when checking case values for being in range,
- and it's too hard to do the right thing. */
- if (TREE_UNSIGNED (TREE_TYPE (exp))
- == TREE_UNSIGNED (TREE_TYPE (idx)))
- exp = idx;
- }
+ exp = default_conversion (exp);
+ type = TREE_TYPE (exp);
+ idx = get_unwidened (exp, 0);
+ /* We can't strip a conversion from a signed type to an unsigned,
+ because if we did, int_fits_type_p would do the wrong thing
+ when checking case values for being in range,
+ and it's too hard to do the right thing. */
+ if (TREE_UNSIGNED (TREE_TYPE (exp)) == TREE_UNSIGNED (TREE_TYPE (idx)))
+ exp = idx;
expand_start_case
(1, fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp)),
@@ -7471,20 +7601,18 @@ comp_ptr_ttypes_real (to, from, constp)
return 0;
if (TREE_CODE (from) == OFFSET_TYPE
- && comptypes (TYPE_OFFSET_BASETYPE (from),
- TYPE_OFFSET_BASETYPE (to), 1))
+ && same_type_p (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to)))
continue;
/* Const and volatile mean something different for function types,
so the usual checks are not appropriate. */
if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{
- if (TYPE_READONLY (from) > TYPE_READONLY (to)
- || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
+ if (!at_least_as_qualified_p (to, from))
return 0;
- if (TYPE_READONLY (to) > TYPE_READONLY (from)
- || TYPE_VOLATILE (to) > TYPE_VOLATILE (from))
+ if (!at_least_as_qualified_p (from, to))
{
if (constp == 0)
return 0;
@@ -7498,7 +7626,7 @@ comp_ptr_ttypes_real (to, from, constp)
if (TREE_CODE (to) != POINTER_TYPE)
return
- comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1)
+ same_type_p (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from))
&& (constp >= 0 || to_more_cv_qualified);
}
}
@@ -7528,12 +7656,14 @@ ptr_reasonably_similar (to, from)
if (TREE_CODE (from) == OFFSET_TYPE
&& comptypes (TYPE_OFFSET_BASETYPE (to),
- TYPE_OFFSET_BASETYPE (from), -1))
+ TYPE_OFFSET_BASETYPE (from),
+ COMPARE_BASE | COMPARE_RELAXED))
continue;
if (TREE_CODE (to) != POINTER_TYPE)
return comptypes
- (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), -1);
+ (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from),
+ COMPARE_BASE | COMPARE_RELAXED);
}
}
@@ -7549,12 +7679,13 @@ comp_ptr_ttypes_const (to, from)
return 0;
if (TREE_CODE (from) == OFFSET_TYPE
- && comptypes (TYPE_OFFSET_BASETYPE (from),
- TYPE_OFFSET_BASETYPE (to), 1))
+ && same_type_p (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to)))
continue;
if (TREE_CODE (to) != POINTER_TYPE)
- return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
+ return same_type_p (TYPE_MAIN_VARIANT (to),
+ TYPE_MAIN_VARIANT (from));
}
}
@@ -7573,25 +7704,46 @@ comp_ptr_ttypes_reinterpret (to, from)
if (TREE_CODE (to) == OFFSET_TYPE)
to = TREE_TYPE (to);
- if (TREE_CODE (to) != TREE_CODE (from))
- return 1;
-
/* Const and volatile mean something different for function types,
so the usual checks are not appropriate. */
- if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
+ if (TREE_CODE (from) != FUNCTION_TYPE && TREE_CODE (from) != METHOD_TYPE
+ && TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{
- if (TYPE_READONLY (from) > TYPE_READONLY (to)
- || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
+ if (!at_least_as_qualified_p (to, from))
return 0;
if (! constp
- && (TYPE_READONLY (to) > TYPE_READONLY (from)
- || TYPE_VOLATILE (to) > TYPE_READONLY (from)))
+ && !at_least_as_qualified_p (from, to))
return 0;
constp &= TYPE_READONLY (to);
}
- if (TREE_CODE (to) != POINTER_TYPE)
+ if (TREE_CODE (from) != POINTER_TYPE
+ || TREE_CODE (to) != POINTER_TYPE)
return 1;
}
}
+
+/* Returns the type-qualifier set corresponding to TYPE. */
+
+int
+cp_type_quals (type)
+ tree type;
+{
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ return TYPE_QUALS (type);
+}
+
+/* Returns non-zero if the TYPE contains a mutable member */
+
+int
+cp_has_mutable_p (type)
+ tree type;
+{
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
+}
diff --git a/contrib/gcc/cp/typeck2.c b/contrib/gcc/cp/typeck2.c
index 39b0626..6322157 100644
--- a/contrib/gcc/cp/typeck2.c
+++ b/contrib/gcc/cp/typeck2.c
@@ -1,6 +1,6 @@
/* Report error messages, build initializers, and perform
some front-end optimizations for C++ compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -38,6 +38,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
static tree process_init_constructor PROTO((tree, tree, tree *));
+static void ack PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1;
extern int errorcount;
extern int sorrycount;
@@ -80,11 +81,11 @@ binfo_or_else (parent_or_type, type)
void
readonly_error (arg, string, soft)
tree arg;
- char *string;
+ const char *string;
int soft;
{
- char *fmt;
- void (*fn)();
+ const char *fmt;
+ void (*fn) PVPROTO ((const char *, ...));
if (soft)
fn = cp_pedwarn;
@@ -118,7 +119,9 @@ readonly_error (arg, string, soft)
(*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0));
else if (TREE_CODE (arg) == RESULT_DECL)
(*fn) ("%s of read-only named return value `%D'", string, arg);
- else
+ else if (TREE_CODE (arg) == FUNCTION_DECL)
+ (*fn) ("%s of function `%D'", string, arg);
+ else
(*fn) ("%s of read-only location", string);
}
@@ -131,30 +134,8 @@ abstract_virtuals_error (decl, type)
tree type;
{
tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
- int has_abstract_virtuals, needs_final_overriders;
tree tu;
- /* Count how many abstract methods need to be defined. */
- for (has_abstract_virtuals = 0, tu = u; tu; tu = TREE_CHAIN (tu))
- {
- if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
- && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- {
- has_abstract_virtuals = 1;
- break;
- }
- }
-
- /* Count how many virtual methods need a final overrider. */
- for (needs_final_overriders = 0, tu = u; tu; tu = TREE_CHAIN (tu))
- {
- if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- {
- needs_final_overriders = 1;
- break;
- }
- }
-
if (decl)
{
if (TREE_CODE (decl) == RESULT_DECL)
@@ -183,44 +164,12 @@ abstract_virtuals_error (decl, type)
{
TREE_PURPOSE (u) = error_mark_node;
- if (has_abstract_virtuals)
- error (" since the following virtual functions are abstract:");
- tu = u;
- while (tu)
- {
- if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
- && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- cp_error ("\t%#D", TREE_VALUE (tu));
- tu = TREE_CHAIN (tu);
- }
-
- if (needs_final_overriders)
- {
- if (has_abstract_virtuals)
- error (" and the following virtual functions need a final overrider:");
- else
- error (" since the following virtual functions need a final overrider:");
- }
- tu = u;
- while (tu)
- {
- if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- cp_error ("\t%#D", TREE_VALUE (tu));
- tu = TREE_CHAIN (tu);
- }
+ error (" since the following virtual functions are abstract:");
+ for (tu = u; tu; tu = TREE_CHAIN (tu))
+ cp_error_at ("\t%#D", TREE_VALUE (tu));
}
else
- {
- if (has_abstract_virtuals)
- {
- if (needs_final_overriders)
- cp_error (" since type `%T' has abstract virtual functions and must override virtual functions", type);
- else
- cp_error (" since type `%T' has abstract virtual functions", type);
- }
- else
- cp_error (" since type `%T' must override virtual functions", type);
- }
+ cp_error (" since type `%T' has abstract virtual functions", type);
}
/* Print an error message for invalid use of a signature type.
@@ -265,73 +214,89 @@ incomplete_type_error (value, type)
tree value;
tree type;
{
- char *errmsg = 0;
-
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
return;
- if (value != 0 && (TREE_CODE (value) == VAR_DECL
- || TREE_CODE (value) == PARM_DECL))
- cp_error ("`%D' has incomplete type", value);
- else
- {
- retry:
- /* We must print an error message. Be clever about what it says. */
-
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- errmsg = "invalid use of undefined type `%#T'";
- break;
+retry:
+ /* We must print an error message. Be clever about what it says. */
- case VOID_TYPE:
- error ("invalid use of void expression");
- return;
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ cp_error ("invalid use of undefined type `%#T'", type);
+ cp_error_at ("forward declaration of `%#T'", type);
+ break;
- case ARRAY_TYPE:
- if (TYPE_DOMAIN (type))
- {
- type = TREE_TYPE (type);
- goto retry;
- }
- error ("invalid use of array with unspecified bounds");
- return;
+ case VOID_TYPE:
+ cp_error ("invalid use of void expression");
+ break;
- case OFFSET_TYPE:
- error ("invalid use of member type (did you forget the `&' ?)");
- return;
+ case ARRAY_TYPE:
+ if (TYPE_DOMAIN (type))
+ {
+ type = TREE_TYPE (type);
+ goto retry;
+ }
+ cp_error ("invalid use of array with unspecified bounds");
+ break;
- case TEMPLATE_TYPE_PARM:
- error ("invalid use of template type parameter");
- return;
+ case OFFSET_TYPE:
+ bad_member:
+ cp_error ("invalid use of member (did you forget the `&' ?)");
+ break;
- default:
- my_friendly_abort (108);
- }
+ case TEMPLATE_TYPE_PARM:
+ cp_error ("invalid use of template type parameter");
+ break;
- cp_error (errmsg, type);
+ case UNKNOWN_TYPE:
+ if (value && TREE_CODE (value) == COMPONENT_REF)
+ goto bad_member;
+ else if (value && TREE_CODE (value) == ADDR_EXPR)
+ cp_error ("address of overloaded function with no contextual type information");
+ else if (value && TREE_CODE (value) == OVERLOAD)
+ cp_error ("overloaded function with no contextual type information");
+ else
+ cp_error ("insufficient contextual information to determine type");
+ break;
+
+ default:
+ my_friendly_abort (108);
}
+
+ if (value != 0 && (TREE_CODE (value) == VAR_DECL
+ || TREE_CODE (value) == PARM_DECL))
+ cp_error_at ("incomplete `%D' defined here", value);
}
/* Like error(), but don't call report_error_function(). */
static void
-ack (s, v, v2)
- char *s;
- HOST_WIDE_INT v;
- HOST_WIDE_INT v2;
+ack VPROTO ((const char *msg, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msg;
+#endif
+ va_list ap;
extern char * progname;
+ VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+ msg = va_arg (ap, const char *);
+#endif
+
if (input_filename)
fprintf (stderr, "%s:%d: ", input_filename, lineno);
else
fprintf (stderr, "%s: ", progname);
- fprintf (stderr, s, v, v2);
+ vfprintf (stderr, msg, ap);
+ va_end (ap);
+
fprintf (stderr, "\n");
}
@@ -350,19 +315,14 @@ ack (s, v, v2)
59 is, so they can understand how to work around it, should they
ever run into it.
- Note, there will be no more calls in the C++ front end to abort,
- because the C++ front end is so unreliable still. The C front end
- can get away with calling abort, because for most of the calls to
- abort on most machines, it, I suspect, can be proven that it is
- impossible to ever call abort. The same is not yet true for C++,
- one day, maybe it will be.
-
We used to tell people to "fix the above error[s] and try recompiling
the program" via a call to fatal, but that message tended to look
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: 369. Free: */
+ We used to assign sequential numbers for the aborts; now we use an
+ encoding of the date the abort was added, since that has more meaning
+ when we only see the error message. */
static int abortcount = 0;
@@ -383,8 +343,8 @@ my_friendly_abort (i)
ack ("Internal compiler error.");
else
ack ("Internal compiler error %d.", i);
- ack ("Please submit a full bug report to `egcs-bugs@egcs.cygnus.com'.");
- ack ("See <URL:http://egcs.cygnus.com/faq.html#bugreport> for details.");
+ ack ("Please submit a full bug report.");
+ ack ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.");
}
else
error ("confused by earlier errors, bailing out");
@@ -398,8 +358,8 @@ my_friendly_abort (i)
else
error ("Internal compiler error %d.", i);
- error ("Please submit a full bug report to `egcs-bugs@egcs.cygnus.com'.");
- fatal ("See <URL:http://egcs.cygnus.com/faq.html#bugreport> for details.");
+ error ("Please submit a full bug report.");
+ fatal ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.");
}
void
@@ -440,6 +400,7 @@ initializer_constant_valid_p (value, endtype)
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
+ case PTRMEM_CST:
return null_pointer_node;
case ADDR_EXPR:
@@ -650,13 +611,6 @@ store_init_value (decl, init)
else
init = TREE_VALUE (init);
}
- else if (TREE_TYPE (init) != 0
- && TREE_CODE (TREE_TYPE (init)) == OFFSET_TYPE)
- {
- /* Use the type of our variable to instantiate
- the type of our initializer. */
- init = instantiate_type (type, init, 1);
- }
else if (TREE_CODE (init) == TREE_LIST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
@@ -767,6 +721,9 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type)
+ return init;
+
raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
if (raw_constructor
@@ -937,6 +894,7 @@ process_init_constructor (type, init, elts)
/* List of the elements of the result constructor,
in reverse order. */
register tree members = NULL;
+ register tree next1;
tree result;
int allconstant = 1;
int allsimple = 1;
@@ -971,42 +929,62 @@ process_init_constructor (type, init, elts)
else
len = -1; /* Take as many as there are */
- for (i = 0; (len < 0 || i < len) && tail != 0; i++)
+ for (i = 0; len < 0 || i < len; i++)
{
- register tree next1;
-
- if (TREE_PURPOSE (tail)
- && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
- || TREE_INT_CST_LOW (TREE_PURPOSE (tail)) != i))
- sorry ("non-trivial labeled initializers");
-
- if (TREE_VALUE (tail) != 0)
+ if (tail)
{
- tree tail1 = tail;
- next1 = digest_init (TREE_TYPE (type),
- TREE_VALUE (tail), &tail1);
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))
- && TYPE_MAIN_VARIANT (TREE_TYPE (type)) != TYPE_MAIN_VARIANT (TREE_TYPE (next1)))
+ if (TREE_PURPOSE (tail)
+ && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
+ || TREE_INT_CST_LOW (TREE_PURPOSE (tail)) != i))
+ sorry ("non-trivial labeled initializers");
+
+ if (TREE_VALUE (tail) != 0)
{
- /* The fact this needs to be done suggests this code needs
- to be totally rewritten. */
- next1 = convert_for_initialization (NULL_TREE, TREE_TYPE (type), next1, LOOKUP_NORMAL, "initialization", NULL_TREE, 0);
+ tree tail1 = tail;
+ next1 = digest_init (TREE_TYPE (type),
+ TREE_VALUE (tail), &tail1);
+ if (next1 == error_mark_node)
+ return next1;
+ my_friendly_assert
+ (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (next1))),
+ 981123);
+ my_friendly_assert (tail1 == 0
+ || TREE_CODE (tail1) == TREE_LIST, 319);
+ if (tail == tail1 && len < 0)
+ {
+ error ("non-empty initializer for array of empty elements");
+ /* Just ignore what we were supposed to use. */
+ tail1 = NULL_TREE;
+ }
+ tail = tail1;
}
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 319);
- if (tail == tail1 && len < 0)
+ else
{
- error ("non-empty initializer for array of empty elements");
- /* Just ignore what we were supposed to use. */
- tail1 = NULL_TREE;
+ next1 = error_mark_node;
+ tail = TREE_CHAIN (tail);
}
- tail = tail1;
}
- else
+ else if (len < 0)
+ /* We're done. */
+ break;
+ else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ /* If this type needs constructors run for
+ default-initialization, we can't rely on the backend to do it
+ for us, so build up TARGET_EXPRs. If the type in question is
+ a class, just build one up; if it's an array, recurse. */
+
+ if (IS_AGGR_TYPE (TREE_TYPE (type)))
+ next1 = build_functional_cast (TREE_TYPE (type), NULL_TREE);
+ else
+ next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
+ next1 = digest_init (TREE_TYPE (type), next1, 0);
}
+ else
+ /* The default zero-initialization is fine for us; don't
+ add anything to the CONSTRUCTOR. */
+ break;
if (next1 == error_mark_node)
erroneous = 1;
@@ -1017,7 +995,7 @@ process_init_constructor (type, init, elts)
members = expr_tree_cons (NULL_TREE, next1, members);
}
}
- if (TREE_CODE (type) == RECORD_TYPE)
+ else if (TREE_CODE (type) == RECORD_TYPE)
{
register tree field;
@@ -1042,12 +1020,10 @@ process_init_constructor (type, init, elts)
}
}
- for (field = TYPE_FIELDS (type); field && tail;
+ for (field = TYPE_FIELDS (type); field;
field = TREE_CHAIN (field))
{
- register tree next1;
-
- if (! DECL_NAME (field))
+ if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
members = expr_tree_cons (field, integer_zero_node, members);
continue;
@@ -1056,25 +1032,67 @@ process_init_constructor (type, init, elts)
if (TREE_CODE (field) != FIELD_DECL)
continue;
- if (TREE_PURPOSE (tail)
- && TREE_PURPOSE (tail) != field
- && TREE_PURPOSE (tail) != DECL_NAME (field))
- sorry ("non-trivial labeled initializers");
+ if (tail)
+ {
+ if (TREE_PURPOSE (tail)
+ && TREE_PURPOSE (tail) != field
+ && TREE_PURPOSE (tail) != DECL_NAME (field))
+ sorry ("non-trivial labeled initializers");
+
+ if (TREE_VALUE (tail) != 0)
+ {
+ tree tail1 = tail;
- if (TREE_VALUE (tail) != 0)
+ next1 = digest_init (TREE_TYPE (field),
+ TREE_VALUE (tail), &tail1);
+ my_friendly_assert (tail1 == 0
+ || TREE_CODE (tail1) == TREE_LIST, 320);
+ tail = tail1;
+ }
+ else
+ {
+ next1 = error_mark_node;
+ tail = TREE_CHAIN (tail);
+ }
+ }
+ else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
- tree tail1 = tail;
+ /* If this type needs constructors run for
+ default-initialization, we can't rely on the backend to do it
+ for us, so build up TARGET_EXPRs. If the type in question is
+ a class, just build one up; if it's an array, recurse. */
+
+ if (IS_AGGR_TYPE (TREE_TYPE (field)))
+ next1 = build_functional_cast (TREE_TYPE (field),
+ NULL_TREE);
+ else
+ next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE,
+ NULL_TREE);
+ next1 = digest_init (TREE_TYPE (field), next1, 0);
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1);
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 320);
- tail = tail1;
+ /* Warn when some struct elements are implicitly initialized. */
+ if (extra_warnings)
+ cp_warning ("missing initializer for member `%D'", field);
}
else
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ if (TREE_READONLY (field))
+ cp_error ("uninitialized const member `%D'", field);
+ else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
+ && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
+ cp_error ("member `%D' with uninitialized const fields",
+ field);
+ else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+ cp_error ("member `%D' is uninitialized reference", field);
+
+ /* Warn when some struct elements are implicitly initialized
+ to zero. */
+ if (extra_warnings)
+ cp_warning ("missing initializer for member `%D'", field);
+
+ /* The default zero-initialization is fine for us; don't
+ add anything to the CONSTRUCTOR. */
+ continue;
}
if (next1 == error_mark_node)
@@ -1085,45 +1103,10 @@ process_init_constructor (type, init, elts)
allsimple = 0;
members = expr_tree_cons (field, next1, members);
}
- for (; field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- /* Does this field have a default initialization? */
- if (DECL_INITIAL (field))
- {
- register tree next1 = DECL_INITIAL (field);
- if (TREE_CODE (next1) == ERROR_MARK)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
- allsimple = 0;
- members = expr_tree_cons (field, next1, members);
- }
- else if (TREE_READONLY (field))
- error ("uninitialized const member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
- && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
- error ("member `%s' with uninitialized const fields",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
- error ("member `%s' is uninitialized reference",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- /* Warn when some struct elements are implicitly initialized
- to zero. */
- else if (extra_warnings)
- warning ("missing initializer for member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- }
}
-
- if (TREE_CODE (type) == UNION_TYPE)
+ else if (TREE_CODE (type) == UNION_TYPE)
{
register tree field = TYPE_FIELDS (type);
- register tree next1;
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
@@ -1152,8 +1135,8 @@ process_init_constructor (type, init, elts)
if (temp)
field = temp, win = 1;
else
- error ("no field `%s' in union being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
+ cp_error ("no field `%D' in union being initialized",
+ TREE_PURPOSE (tail));
}
if (!win)
TREE_VALUE (tail) = error_mark_node;
@@ -1392,8 +1375,7 @@ build_m_component_ref (datum, component)
}
else
{
- component = build_indirect_ref (component, NULL_PTR);
- type = TREE_TYPE (component);
+ type = TREE_TYPE (TREE_TYPE (component));
rettype = TREE_TYPE (type);
}
@@ -1504,6 +1486,11 @@ build_functional_cast (exp, parms)
cp_error ("type `%T' is not yet defined", type);
return error_mark_node;
}
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
+ {
+ abstract_virtuals_error (NULL_TREE, type);
+ return error_mark_node;
+ }
if (parms && TREE_CHAIN (parms) == NULL_TREE)
return build_c_cast (type, TREE_VALUE (parms));
@@ -1659,11 +1646,15 @@ report_case_error (code, type, new_value, old_value)
}
#endif
+/* Complain about defining new types in inappropriate places. We give an
+ exception for C-style casts, to accommodate GNU C stylings. */
+
void
check_for_new_type (string, inptree)
- char *string;
+ const char *string;
flagged_type_tree inptree;
{
- if (pedantic && inptree.new_type_flag)
+ if (inptree.new_type_flag
+ && (pedantic || strcmp (string, "cast") != 0))
pedwarn ("ANSI C++ forbids defining types within %s",string);
}
diff --git a/contrib/gcc/cp/xref.c b/contrib/gcc/cp/xref.c
index 14915d6..6e06eda 100644
--- a/contrib/gcc/cp/xref.c
+++ b/contrib/gcc/cp/xref.c
@@ -86,8 +86,8 @@ typedef struct _XREF_SCOPE * XREF_SCOPE;
typedef struct _XREF_FILE
{
- char *name;
- char *outname;
+ const char *name;
+ const char *outname;
XREF_FILE next;
} XREF_FILE_INFO;
@@ -122,19 +122,20 @@ static tree last_fndecl = NULL;
/* */
/************************************************************************/
static void gen_assign PROTO((XREF_FILE, tree));
-static XREF_FILE find_file PROTO((char *));
-static char * filename PROTO((XREF_FILE));
-static char * fctname PROTO((tree));
-static char * declname PROTO((tree));
+static XREF_FILE find_file PROTO((const char *));
+static const char * filename PROTO((XREF_FILE));
+static const char * fctname PROTO((tree));
+static const char * declname PROTO((tree));
static void simplify_type PROTO((char *));
-static char * fixname PROTO((char *, char *));
-static void open_xref_file PROTO((char *));
+static const char * fixname PROTO((const char *, char *));
+static void open_xref_file PROTO((const char *));
+static const char * classname PROTO((tree));
/* Start cross referencing. FILE is the name of the file we xref. */
void
GNU_xref_begin (file)
- char *file;
+ const char *file;
{
doing_xref = 1;
@@ -178,7 +179,7 @@ GNU_xref_end (ect)
void
GNU_xref_file (name)
- char *name;
+ const char *name;
{
XREF_FILE xf;
@@ -209,8 +210,8 @@ GNU_xref_file (name)
else
{
char *nmbuf
- = (char *) malloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
- + strlen (name) + 1);
+ = (char *) xmalloc (strlen (wd_name) + strlen (FILE_NAME_JOINER)
+ + strlen (name) + 1);
sprintf (nmbuf, "%s%s%s", wd_name, FILE_NAME_JOINER, name);
name = nmbuf;
xf->outname = nmbuf;
@@ -259,7 +260,7 @@ GNU_xref_end_scope (id,inid,prm,keep)
{
XREF_FILE xf;
XREF_SCOPE xs,lxs,oxs;
- char *stype;
+ const char *stype;
if (!doing_xref) return;
xf = find_file (input_filename);
@@ -302,7 +303,7 @@ GNU_xref_end_scope (id,inid,prm,keep)
void
GNU_xref_ref (fndecl,name)
tree fndecl;
- char *name;
+ const char *name;
{
XREF_FILE xf;
@@ -322,8 +323,8 @@ GNU_xref_decl (fndecl,decl)
tree decl;
{
XREF_FILE xf,xf1;
- char *cls = 0;
- char *name;
+ const char *cls = 0;
+ const char *name;
char buf[10240];
int uselin;
@@ -432,11 +433,11 @@ GNU_xref_decl (fndecl,decl)
void
GNU_xref_call (fndecl, name)
tree fndecl;
- char *name;
+ const char *name;
{
XREF_FILE xf;
char buf[1024];
- char *s;
+ const char *s;
if (!doing_xref) return;
xf = find_file (input_filename);
@@ -508,7 +509,7 @@ gen_assign(xf, name)
XREF_FILE xf;
tree name;
{
- char *s;
+ const char *s;
s = NULL;
@@ -541,7 +542,7 @@ gen_assign(xf, name)
fprintf(xref_file, "ASG %s %d %s\n", filename(xf), lineno, s);
}
-static char*
+static const char *
classname (cls)
tree cls;
{
@@ -590,9 +591,9 @@ GNU_xref_member(cls, fld)
tree fld;
{
XREF_FILE xf;
- char *prot;
+ const char *prot;
int confg, pure;
- char *d;
+ const char *d;
#ifdef XREF_SHORT_MEMBER_NAMES
int i;
#endif
@@ -651,7 +652,7 @@ GNU_xref_member(cls, fld)
static XREF_FILE
find_file(name)
- char *name;
+ const char *name;
{
XREF_FILE xf;
@@ -664,7 +665,7 @@ find_file(name)
/* Return filename for output purposes. */
-static char *
+static const char *
filename(xf)
XREF_FILE xf;
{
@@ -682,12 +683,12 @@ filename(xf)
/* Return function name for output purposes. */
-static char *
+static const char *
fctname(fndecl)
tree fndecl;
{
static char fctbuf[1024];
- char *s;
+ const char *s;
if (fndecl == NULL && last_fndecl == NULL) return "*";
@@ -709,7 +710,7 @@ fctname(fndecl)
/* Return decl name for output purposes. */
-static char *
+static const char *
declname(dcl)
tree dcl;
{
@@ -731,7 +732,7 @@ simplify_type(typ)
int lvl, i;
i = strlen(typ);
- while (i > 0 && ISSPACE(typ[i-1])) typ[--i] = 0;
+ while (i > 0 && ISSPACE((unsigned char) typ[i-1])) typ[--i] = 0;
if (i > 7 && STREQL(&typ[i-5], "const"))
{
@@ -773,12 +774,13 @@ simplify_type(typ)
/* Fixup a function name (take care of embedded spaces). */
-static char *
+static const char *
fixname(nam, buf)
- char *nam;
+ const char *nam;
char *buf;
{
- char *s, *t;
+ const char *s;
+ char *t;
int fg;
s = nam;
@@ -806,9 +808,10 @@ fixname(nam, buf)
static void
open_xref_file(file)
- char *file;
+ const char *file;
{
- char *s, *t;
+ const char *s;
+ char *t;
#ifdef XREF_FILE_NAME
XREF_FILE_NAME (xref_name, file);
diff --git a/contrib/gcc/cpp.texi b/contrib/gcc/cpp.texi
index e71b6e9..ca50137 100644
--- a/contrib/gcc/cpp.texi
+++ b/contrib/gcc/cpp.texi
@@ -16,7 +16,7 @@
@ifinfo
This file documents the GNU C Preprocessor.
-Copyright 1987, 1989, 1991, 1992, 1993, 1994, 1995 Free Software
+Copyright 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1997, 1998 Free Software
Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
@@ -42,7 +42,7 @@ into another language, under the above conditions for modified versions.
@titlepage
@c @finalout
@title The C Preprocessor
-@subtitle Last revised March 1997
+@subtitle Last revised September 1998
@subtitle for GCC version 2
@author Richard M. Stallman
@page
@@ -51,8 +51,8 @@ This booklet is eventually intended to form the first chapter of a GNU
C Language manual.
@vskip 0pt plus 1filll
-Copyright @copyright{} 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free
-Software Foundation, Inc.
+Copyright @copyright{} 1987, 1989, 1991-1998
+Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -1482,7 +1482,7 @@ pointer (the argument @samp{p} says where to find it) across whitespace
characters:
@example
-#define SKIP_SPACES (p, limit) \
+#define SKIP_SPACES(p, limit) \
@{ register char *lim = (limit); \
while (p != lim) @{ \
if (*p++ != ' ') @{ \
@@ -1518,7 +1518,7 @@ The definition of the macro @samp{SKIP_SPACES} can be altered to solve
this problem, using a @samp{do @dots{} while} statement. Here is how:
@example
-#define SKIP_SPACES (p, limit) \
+#define SKIP_SPACES(p, limit) \
do @{ register char *lim = (limit); \
while (p != lim) @{ \
if (*p++ != ' ') @{ \
@@ -2594,6 +2594,46 @@ Traditionally, @samp{\} inside a macro argument suppresses the syntactic
significance of the following character.
@end itemize
+@cindex Fortran
+@cindex unterminated
+Use the @samp{-traditional} option when preprocessing Fortran code,
+so that singlequotes and doublequotes
+within Fortran comment lines
+(which are generally not recognized as such by the preprocessor)
+do not cause diagnostics
+about unterminated character or string constants.
+
+However, this option does not prevent diagnostics
+about unterminated comments
+when a C-style comment appears to start, but not end,
+within Fortran-style commentary.
+
+So, the following Fortran comment lines are accepted with
+@samp{-traditional}:
+
+@smallexample
+C This isn't an unterminated character constant
+C Neither is "20000000000, an octal constant
+C in some dialects of Fortran
+@end smallexample
+
+However, this type of comment line will likely produce a diagnostic,
+or at least unexpected output from the preprocessor,
+due to the unterminated comment:
+
+@smallexample
+C Some Fortran compilers accept /* as starting
+C an inline comment.
+@end smallexample
+
+@cindex g77
+Note that @code{g77} automatically supplies
+the @samp{-traditional} option
+when it invokes the preprocessor.
+However, a future version of @code{g77}
+might use a different, more-Fortran-aware preprocessor
+in place of @code{cpp}.
+
@item -trigraphs
@findex -trigraphs
Process ANSI standard trigraph sequences. These are three-character
@@ -2618,7 +2658,9 @@ warnings.
@item -Wtrigraphs
@findex -Wtrigraphs
-Warn if any trigraphs are encountered (assuming they are enabled).
+Warn if any trigraphs are encountered. Currently this only works if you
+have turned trigraphs on with @samp{-trigraphs} or @samp{-ansi}; in the
+future this restriction will be removed.
@item -Wcomment
@findex -Wcomment
@@ -2716,6 +2758,12 @@ is not predefined.
@findex -undef
Do not predefine any nonstandard macros.
+@item -gcc
+@findex -gcc
+Define the macros @var{__GNUC__} and @var{__GNUC_MINOR__}. These are
+defined automatically when you use @samp{gcc -E}; you can turn them off
+in that case with @samp{-no-gcc}.
+
@item -A @var{predicate}(@var{answer})
@findex -A
Make an assertion with the predicate @var{predicate} and answer
@@ -2723,7 +2771,8 @@ Make an assertion with the predicate @var{predicate} and answer
@noindent
You can use @samp{-A-} to disable all predefined assertions; it also
-undefines all predefined macros that identify the type of target system.
+undefines all predefined macros and all macros that preceded it on the
+command line.
@item -dM
@findex -dM
@@ -2778,8 +2827,8 @@ Like @samp{-M} but the dependency information is written to @var{file}.
This is in addition to compiling the file as specified---@samp{-MD} does
not inhibit ordinary compilation the way @samp{-M} does.
-When invoking gcc, do not specify the @var{file} argument.
-Gcc will create file names made by replacing ".c" with ".d" at
+When invoking @code{gcc}, do not specify the @var{file} argument.
+@code{gcc} will create file names made by replacing ".c" with ".d" at
the end of the input file names.
In Mach, you can use the utility @code{md} to merge multiple dependency
@@ -2834,48 +2883,75 @@ Add a directory to the beginning of the second include path, marking it
as a system directory, so that it gets the same special treatment as
is applied to the standard system directories.
-@item -lang-c
-@itemx -lang-c89
-@itemx -lang-c++
-@itemx -lang-objc
-@itemx -lang-objc++
-@findex -lang-c
-@findex -lang-c89
-@findex -lang-c++
-@findex -lang-objc
-@findex -lang-objc++
-Specify the source language. @samp{-lang-c} is the default; it
-allows recognition of C++ comments (comments that begin with
-@samp{//} and end at end of line) and hexadecimal floating-point constants,
-since these features will most likely appear in the next C standard.
-@samp{-lang-c89} disables recognition of C++ comments and
-hexadecimal floating-point constants. @samp{-lang-c++}
-handles C++ comment syntax and includes extra default include
-directories for C++. @samp{-lang-objc} enables the Objective C
-@samp{#import} directive. @samp{-lang-objc++} enables both C++ and Objective C
-extensions.
-
-These options are generated by the compiler driver @code{gcc}, but not
-passed from the @samp{gcc} command line unless you use the driver's
-@samp{-Wp} option.
-
-@item -lint
+@item -x c
+@itemx -x c++
+@itemx -x objective-c
+@itemx -x assembler-with-cpp
+@findex -x c
+@findex -x objective-c
+@findex -x assembler-with-cpp
+Specify the source language: C, C++, Objective-C, or assembly. This has
+nothing to do with standards conformance or extensions; it merely
+selects which base syntax to expect. If you give none of these options,
+cpp will deduce the language from the extension of the source file:
+@samp{.c}, @samp{.cc}, @samp{.m}, or @samp{.S}. Some other common
+extensions for C++ and assembly are also recognized. If cpp does not
+recognize the extension, it will treat the file as C; this is the most
+generic mode.
+
+@strong{Note:} Previous versions of cpp accepted a @samp{-lang} option
+which selected both the language and the standards conformance level.
+This option has been removed, because it conflicts with the @samp{-l}
+option.
+
+@item -std=@var{standard}
+@itemx -ansi
+@findex -std
+@findex -ansi
+Specify the standard to which the code should conform. Currently cpp
+only knows about the standards for C; other language standards will be
+added in the future.
+
+@var{standard}
+may be one of:
+@table @code
+@item iso9899:1990
+The ISO C standard from 1990.
+
+@item iso9899:199409
+@itemx c89
+The 1990 C standard, as amended in 1994. @samp{c89} is the customary
+shorthand for this version of the standard.
+
+The @samp{-ansi} option is equivalent to @samp{-std=c89}.
+
+@item iso9899:199x
+@itemx c9x
+The revised ISO C standard, which is expected to be promulgated some
+time in 1999. It has not been approved yet, hence the @samp{x}.
+
+@item gnu89
+The 1990 C standard plus GNU extensions. This is the default.
+
+@item gnu9x
+The 199x C standard plus GNU extensions.
+@end table
+
+@item -Wp,-lint
+@findex -lint
Look for commands to the program checker @code{lint} embedded in
comments, and emit them preceded by @samp{#pragma lint}. For example,
the comment @samp{/* NOTREACHED */} becomes @samp{#pragma lint
NOTREACHED}.
-This option is available only when you call @code{cpp} directly;
-@code{gcc} will not pass it from its command line.
+Because of the clash with @samp{-l}, you must use the awkward syntax
+above. In a future release, this option will be replaced by
+@samp{-flint} or @samp{-Wlint}; we are not sure which yet.
@item -$
@findex -$
-Forbid the use of @samp{$} in identifiers. This was formerly required
-for strict conformance to the C Standard before the standard was
-corrected.
-
-This option is available only when you call @code{cpp} directly;
-@code{gcc} will not pass it from its command line.
+Forbid the use of @samp{$} in identifiers. The C standard does not
+permit this, but it is a common extension.
@end table
diff --git a/contrib/gcc/cppalloc.c b/contrib/gcc/cppalloc.c
index bd3a605..5c96aff 100644
--- a/contrib/gcc/cppalloc.c
+++ b/contrib/gcc/cppalloc.c
@@ -1,5 +1,5 @@
/* Part of CPP library. (memory allocation - xmalloc etc)
- Copyright (C) 1986, 87, 89, 92 - 95, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1986, 87, 89, 92, 93, 94, 1995, 1998 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -24,33 +24,58 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "config.h"
#include "system.h"
-#include "gansidecl.h"
#include "cpplib.h"
+static void memory_full PROTO ((void)) ATTRIBUTE_NORETURN;
+
static void
memory_full ()
{
- fprintf (stderr, "%s: Memory exhausted.\n", progname);
+ cpp_notice ("%s: Memory exhausted.\n", progname);
exit (FATAL_EXIT_CODE);
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *ptr = (char *) malloc (size);
+ register PTR ptr = (PTR) malloc (size);
if (ptr == 0)
memory_full ();
return ptr;
}
-char *
+PTR
+xcalloc (number, size)
+ size_t number, size;
+{
+ register PTR ptr = (PTR) calloc (number, size);
+ if (ptr == 0)
+ memory_full ();
+ return ptr;
+}
+
+PTR
xrealloc (old, size)
- char *old;
- unsigned size;
+ PTR old;
+ size_t size;
{
- register char *ptr = (char *) realloc (old, size);
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
if (ptr == 0)
memory_full ();
return ptr;
}
+
+char *
+xstrdup (input)
+ const char *input;
+{
+ unsigned size = strlen (input);
+ char *output = xmalloc (size + 1);
+ strcpy (output, input);
+ return output;
+}
diff --git a/contrib/gcc/cpperror.c b/contrib/gcc/cpperror.c
index c4cac06..c7339dc 100644
--- a/contrib/gcc/cpperror.c
+++ b/contrib/gcc/cpperror.c
@@ -1,5 +1,5 @@
/* Default error handlers for CPP Library.
- Copyright (C) 1986, 87, 89, 92 - 95, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1986, 87, 89, 92-95, 98, 1999 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -24,18 +24,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef EMACS
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
-#include "gansidecl.h"
#else
#include <stdio.h>
#endif /* not EMACS */
#include "cpplib.h"
+#include "intl.h"
/* Print the file names and line numbers of the #include
commands which led to the current file. */
@@ -68,16 +63,16 @@ cpp_print_containing_files (pfile)
if (first)
{
first = 0;
- fprintf (stderr, "In file included");
+ cpp_notice ("In file included from %s:%ld",
+ ip->nominal_fname, line);
}
else
- fprintf (stderr, ",\n ");
+ cpp_message (pfile, -1, ",\n from %s:%ld",
+ ip->nominal_fname, line);
}
-
- fprintf (stderr, " from %s:%ld", ip->nominal_fname, line);
}
if (! first)
- fprintf (stderr, ":\n");
+ fputs (":\n", stderr);
/* Record we have printed the status as of this time. */
pfile->input_stack_listing_current = 1;
@@ -95,44 +90,58 @@ cpp_file_line_for_message (pfile, filename, line, column)
fprintf (stderr, "%s:%d: ", filename, line);
}
-/* IS_ERROR is 2 for "fatal" error, 1 for error, 0 for warning */
+/* IS_ERROR is 2 for "fatal" error, 1 for error, 0 for warning, -1 for notice */
void
-v_cpp_message (pfile, is_error, msg, ap)
+v_cpp_message (pfile, is_error, msgid, ap)
cpp_reader * pfile;
int is_error;
- const char *msg;
+ const char *msgid;
va_list ap;
{
- if (!is_error)
- fprintf (stderr, "warning: ");
- else if (is_error == 2)
- pfile->errors = CPP_FATAL_LIMIT;
- else if (pfile->errors < CPP_FATAL_LIMIT)
- pfile->errors++;
- vfprintf (stderr, msg, ap);
- fprintf (stderr, "\n");
+ switch (is_error)
+ {
+ case -1:
+ break;
+ case 0:
+ fprintf (stderr, _("warning: "));
+ break;
+ case 1:
+ if (pfile->errors < CPP_FATAL_LIMIT)
+ pfile->errors++;
+ break;
+ case 2:
+ pfile->errors = CPP_FATAL_LIMIT;
+ break;
+ default:
+ cpp_fatal (pfile, "internal error: bad is_error(%d) in v_cpp_message", is_error);
+ }
+
+ vfprintf (stderr, _(msgid), ap);
+
+ if (0 <= is_error)
+ fprintf (stderr, "\n");
}
void
-cpp_message VPROTO ((cpp_reader *pfile, int is_error, const char *msg, ...))
+cpp_message VPROTO ((cpp_reader *pfile, int is_error, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
int is_error;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, msg);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
is_error = va_arg (ap, int);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_cpp_message(pfile, is_error, msg, ap);
+ v_cpp_message(pfile, is_error, msgid, ap);
va_end(ap);
}
@@ -143,23 +152,23 @@ cpp_message VPROTO ((cpp_reader *pfile, int is_error, const char *msg, ...))
CPP_FATAL_ERRORS. */
void
-cpp_fatal VPROTO ((cpp_reader *pfile, const char *str, ...))
+cpp_fatal VPROTO ((cpp_reader *pfile, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
- const char *str;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, str);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
- str = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s: ", progname);
- v_cpp_message (pfile, 2, str, ap);
+ v_cpp_message (pfile, 2, msgid, ap);
va_end(ap);
}
@@ -175,3 +184,25 @@ cpp_pfatal_with_name (pfile, name)
exit (FATAL_EXIT_CODE);
#endif
}
+
+/* Print an error message. */
+
+void
+cpp_notice VPROTO ((const char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+#endif
+
+ fprintf (stderr, "%s: ", progname);
+ v_cpp_message ((cpp_reader *) 0, -1, msgid, ap);
+ va_end(ap);
+}
+
diff --git a/contrib/gcc/cppexp.c b/contrib/gcc/cppexp.c
index 44f8a66..aef6d19 100644
--- a/contrib/gcc/cppexp.c
+++ b/contrib/gcc/cppexp.c
@@ -1,5 +1,5 @@
/* Parse C expressions for CCCP.
- Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998 Free Software Foundation.
+ Copyright (C) 1987, 92, 94, 95, 97, 98, 1999 Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -26,24 +26,12 @@ Written by Per Bothner 1994. */
#include "config.h"
#include "system.h"
-#include "gansidecl.h"
#include "cpplib.h"
-extern char *xmalloc PARAMS ((unsigned));
-extern char *xrealloc PARAMS ((void *, unsigned));
-
#ifdef MULTIBYTE_CHARS
#include <locale.h>
#endif
-/* This is used for communicating lists of keywords with cccp.c. */
-struct arglist {
- struct arglist *next;
- U_CHAR *name;
- int length;
- int argno;
-};
-
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
@@ -76,13 +64,21 @@ struct arglist {
#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
#endif
+#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
+ ? (~ (~ (HOST_WIDEST_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
+ : ~ (HOST_WIDEST_INT) 0)
+
+#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
+ ? ~ (~ (HOST_WIDEST_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
+ : ~ (HOST_WIDEST_INT) 0)
+
/* Yield nonzero if adding two numbers with A's and B's signs can yield a
number with SUM's sign, where A, B, and SUM are all C integers. */
#define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
static void integer_overflow PARAMS ((cpp_reader *));
-static long left_shift PARAMS ((cpp_reader *, long, int, unsigned long));
-static long right_shift PARAMS ((cpp_reader *, long, int, unsigned long));
+static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, unsigned HOST_WIDEST_INT));
+static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, int, unsigned HOST_WIDEST_INT));
#define ERROR 299
#define OROR 300
@@ -105,135 +101,117 @@ static long right_shift PARAMS ((cpp_reader *, long, int, unsigned long));
#define SKIP_OPERAND 8
/*#define UNSIGNEDP 16*/
-/* Find the largest host integer type and set its size and type.
- Watch out: on some crazy hosts `long' is shorter than `int'. */
-
-#ifndef HOST_WIDE_INT
-# if HAVE_INTTYPES_H
-# include <inttypes.h>
-# define HOST_WIDE_INT intmax_t
-# else
-# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \
- && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
-# define HOST_WIDE_INT int
-# else
-# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \
- || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
-# define HOST_WIDE_INT long
-# else
-# define HOST_WIDE_INT long long
-# endif
-# endif
-# endif
-#endif
-
-#ifndef CHAR_BIT
-#define CHAR_BIT 8
-#endif
-
-#ifndef HOST_BITS_PER_WIDE_INT
-#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
-#endif
-
struct operation {
short op;
char rprio; /* Priority of op (relative to it right operand). */
char flags;
char unsignedp; /* true if value should be treated as unsigned */
- HOST_WIDE_INT value; /* The value logically "right" of op. */
+ HOST_WIDEST_INT value; /* The value logically "right" of op. */
};
-
-/* Take care of parsing a number (anything that starts with a digit).
- LEN is the number of characters in it. */
-/* maybe needs to actually deal with floating point numbers */
+/* Parse and convert an integer for #if. Accepts decimal, hex, or octal
+ with or without size suffixes. */
-struct operation
-parse_number (pfile, start, olen)
+static struct operation
+parse_number (pfile, start, end)
cpp_reader *pfile;
- char *start;
- int olen;
+ U_CHAR *start;
+ U_CHAR *end;
{
struct operation op;
- register char *p = start;
- register int c;
- register unsigned long n = 0, nd, ULONG_MAX_over_base;
- register int base = 10;
- register int len = olen;
- register int overflow = 0;
- register int digit, largest_digit = 0;
+ U_CHAR *p = start;
+ int c;
+ unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
+ int base = 10;
+ int overflow = 0;
+ int digit, largest_digit = 0;
int spec_long = 0;
op.unsignedp = 0;
- for (c = 0; c < len; c++)
- if (p[c] == '.') {
- /* It's a float since it contains a point. */
- cpp_error (pfile,
- "floating point numbers not allowed in #if expressions");
- op.op = ERROR;
- return op;
+ if (p[0] == '0')
+ {
+ if (end - start >= 3 && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ base = 16;
+ }
+ else
+ {
+ p += 1;
+ base = 8;
+ }
}
- if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) {
- p += 2;
- base = 16;
- len -= 2;
- }
- else if (*p == '0')
- base = 8;
-
/* Some buggy compilers (e.g. MPW C) seem to need both casts. */
- ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
-
- for (; len > 0; len--) {
- c = *p++;
-
- if (c >= '0' && c <= '9')
- digit = c - '0';
- else if (base == 16 && c >= 'a' && c <= 'f')
- digit = c - 'a' + 10;
- else if (base == 16 && c >= 'A' && c <= 'F')
- digit = c - 'A' + 10;
- else {
- /* `l' means long, and `u' means unsigned. */
- while (1) {
- if (c == 'l' || c == 'L')
- {
- if (spec_long)
- cpp_error (pfile, "two `l's in integer constant");
- spec_long = 1;
- }
- else if (c == 'u' || c == 'U')
- {
- if (op.unsignedp)
- cpp_error (pfile, "two `u's in integer constant");
- op.unsignedp = 1;
- }
- else
- break;
+ MAX_over_base = (((unsigned HOST_WIDEST_INT) -1)
+ / ((unsigned HOST_WIDEST_INT) base));
- if (--len == 0)
+ while (p < end)
+ {
+ c = *p++;
+
+ if (c >= '0' && c <= '9')
+ digit = c - '0';
+ else if (base == 16 && c >= 'a' && c <= 'f') /* FIXME: assumes ASCII */
+ digit = c - 'a' + 10;
+ else if (base == 16 && c >= 'A' && c <= 'F')
+ digit = c - 'A' + 10;
+ else if (c == '.')
+ {
+ /* It's a float since it contains a point. */
+ cpp_error (pfile,
+ "floating point numbers are not allowed in #if expressions");
+ goto error;
+ }
+ else
+ {
+ /* `l' means long, and `u' means unsigned. */
+ for (;;)
+ {
+ if (c == 'l' || c == 'L')
+ spec_long++;
+ else if (c == 'u' || c == 'U')
+ op.unsignedp++;
+ else
+ {
+ /* Decrement p here so that the error for an invalid number
+ will be generated below in the case where this is the
+ last character in the buffer. */
+ p--;
+ break;
+ }
+ if (p == end)
+ break;
+ c = *p++;
+ }
+ /* Don't look for any more digits after the suffixes. */
break;
- c = *p++;
- }
- /* Don't look for any more digits after the suffixes. */
- break;
+ }
+
+ if (largest_digit < digit)
+ largest_digit = digit;
+ nd = n * base + digit;
+ overflow |= MAX_over_base < n || nd < n;
+ n = nd;
}
- if (largest_digit < digit)
- largest_digit = digit;
- nd = n * base + digit;
- overflow |= ULONG_MAX_over_base < n || nd < n;
- n = nd;
- }
- if (len != 0)
+ if (p != end)
{
- cpp_error (pfile, "Invalid number in #if expression");
- op.op = ERROR;
- return op;
+ cpp_error (pfile, "invalid number in #if expression");
+ goto error;
}
-
+ else if (spec_long > (CPP_OPTIONS (pfile)->c89 ? 1 : 2))
+ {
+ cpp_error (pfile, "too many `l' suffixes in integer constant");
+ goto error;
+ }
+ else if (op.unsignedp > 1)
+ {
+ cpp_error (pfile, "too many `u' suffixes in integer constant");
+ goto error;
+ }
+
if (base <= largest_digit)
cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
@@ -241,18 +219,132 @@ parse_number (pfile, start, olen)
cpp_pedwarn (pfile, "integer constant out of range");
/* If too big to be signed, consider it unsigned. */
- if ((long) n < 0 && ! op.unsignedp)
+ else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp)
{
if (base == 10)
- cpp_warning (pfile, "integer constant is so large that it is unsigned");
+ cpp_warning (pfile,
+ "integer constant is so large that it is unsigned");
op.unsignedp = 1;
}
op.value = n;
op.op = INT;
return op;
+
+ error:
+ op.op = ERROR;
+ return op;
+}
+
+/* Parse and convert a character constant for #if. Understands backslash
+ escapes (\n, \031) and multibyte characters (if so configured). */
+static struct operation
+parse_charconst (pfile, start, end)
+ cpp_reader *pfile;
+ U_CHAR *start;
+ U_CHAR *end;
+{
+ struct operation op;
+ HOST_WIDEST_INT result = 0;
+ int num_chars = 0;
+ int num_bits;
+ unsigned int width = MAX_CHAR_TYPE_SIZE, mask = MAX_CHAR_TYPE_MASK;
+ int max_chars;
+ U_CHAR *ptr = start;
+
+ /* FIXME: Should use reentrant multibyte functions. */
+#ifdef MULTIBYTE_CHARS
+ wchar_t c = (wchar_t)-1;
+ (void) mbtowc (NULL_PTR, NULL_PTR, 0);
+#else
+ int c = -1;
+#endif
+
+ if (*ptr == 'L')
+ {
+ ++ptr;
+ width = MAX_WCHAR_TYPE_SIZE, mask = MAX_WCHAR_TYPE_MASK;
+ }
+ max_chars = MAX_LONG_TYPE_SIZE / width;
+
+ ++ptr; /* skip initial quote */
+
+ while (ptr < end)
+ {
+#ifndef MULTIBYTE_CHARS
+ c = *ptr++;
+#else
+ ptr += mbtowc (&c, ptr, end - ptr);
+#endif
+ if (c == '\'' || c == '\0')
+ break;
+ else if (c == '\\')
+ {
+ /* Hopefully valid assumption: if mbtowc returns a backslash,
+ we are in initial shift state. No valid escape-sequence
+ character can take us out of initial shift state or begin
+ an unshifted multibyte char, so cpp_parse_escape doesn't
+ need to know about multibyte chars. */
+
+ c = cpp_parse_escape (pfile, (char **) &ptr, mask);
+ if (width < HOST_BITS_PER_INT
+ && (unsigned int) c >= (unsigned int)(1 << width))
+ cpp_pedwarn (pfile, "escape sequence out of range for character");
+ }
+
+ /* Merge character into result; ignore excess chars. */
+ if (++num_chars <= max_chars)
+ {
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width) | (c & ((1 << width) - 1));
+ else
+ result = c;
+ }
+ }
+
+ if (num_chars == 0)
+ {
+ cpp_error (pfile, "empty character constant");
+ goto error;
+ }
+ else if (c != '\'')
+ {
+ /* cpp_get_token has already emitted an error if !traditional. */
+ if (! CPP_TRADITIONAL (pfile))
+ cpp_error (pfile, "malformatted character constant");
+ goto error;
+ }
+ else if (num_chars > max_chars)
+ {
+ cpp_error (pfile, "character constant too long");
+ goto error;
+ }
+ else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile))
+ cpp_warning (pfile, "multi-character character constant");
+
+ /* If char type is signed, sign-extend the constant. */
+ num_bits = num_chars * width;
+
+ if (cpp_lookup (pfile, (U_CHAR *)"__CHAR_UNSIGNED__",
+ sizeof ("__CHAR_UNSIGNED__")-1, -1)
+ || ((result >> (num_bits - 1)) & 1) == 0)
+ op.value = result & ((unsigned HOST_WIDEST_INT) ~0
+ >> (HOST_BITS_PER_WIDEST_INT - num_bits));
+ else
+ op.value = result | ~((unsigned HOST_WIDEST_INT) ~0
+ >> (HOST_BITS_PER_WIDEST_INT - num_bits));
+
+ /* This is always a signed type. */
+ op.unsignedp = 0;
+ op.op = CHAR;
+ return op;
+
+ error:
+ op.op = ERROR;
+ return op;
}
+
struct token {
char *operator;
int token;
@@ -274,13 +366,13 @@ static struct token tokentab2[] = {
/* Read one token. */
-struct operation
+static struct operation
cpp_lex (pfile, skip_evaluation)
cpp_reader *pfile;
int skip_evaluation;
{
- register int c;
- register struct token *toktab;
+ U_CHAR c;
+ struct token *toktab;
enum cpp_token token;
struct operation op;
U_CHAR *tok_start, *tok_end;
@@ -292,8 +384,11 @@ cpp_lex (pfile, skip_evaluation)
cpp_skip_hspace (pfile);
c = CPP_BUF_PEEK (CPP_BUFFER (pfile));
if (c == '#')
- return parse_number (pfile,
- cpp_read_check_assertion (pfile) ? "1" : "0", 1);
+ {
+ op.op = INT;
+ op.value = cpp_read_check_assertion (pfile);
+ return op;
+ }
if (c == '\n')
{
@@ -319,131 +414,66 @@ cpp_lex (pfile, skip_evaluation)
}
cpp_pop_buffer (pfile);
goto retry;
- case CPP_HSPACE: case CPP_COMMENT:
+ case CPP_HSPACE:
+ case CPP_COMMENT:
goto retry;
case CPP_NUMBER:
- return parse_number (pfile, tok_start, tok_end - tok_start);
+ return parse_number (pfile, tok_start, tok_end);
case CPP_STRING:
cpp_error (pfile, "string constants not allowed in #if expressions");
op.op = ERROR;
return op;
case CPP_CHAR:
- /* This code for reading a character constant
- handles multicharacter constants and wide characters.
- It is mostly copied from c-lex.c. */
- {
- register int result = 0;
- register int num_chars = 0;
- unsigned width = MAX_CHAR_TYPE_SIZE;
- int wide_flag = 0;
- int max_chars;
- U_CHAR *ptr = tok_start;
-#ifdef MULTIBYTE_CHARS
- char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + MB_CUR_MAX];
-#else
- char token_buffer[MAX_LONG_TYPE_SIZE/MAX_CHAR_TYPE_SIZE + 1];
-#endif
-
- if (*ptr == 'L')
- {
- ptr++;
- wide_flag = 1;
- width = MAX_WCHAR_TYPE_SIZE;
-#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
-#endif
- }
- else
- max_chars = MAX_LONG_TYPE_SIZE / width;
+ return parse_charconst (pfile, tok_start, tok_end);
- ++ptr;
- while (ptr < tok_end && ((c = *ptr++) != '\''))
- {
- if (c == '\\')
- {
- c = cpp_parse_escape (pfile, (char **) &ptr);
- if (width < HOST_BITS_PER_INT
- && (unsigned) c >= (1 << width))
- cpp_pedwarn (pfile,
- "escape sequence out of range for character");
- }
-
- num_chars++;
-
- /* Merge character into result; ignore excess chars. */
- if (num_chars < max_chars + 1)
- {
- if (width < HOST_BITS_PER_INT)
- result = (result << width) | (c & ((1 << width) - 1));
- else
- result = c;
- token_buffer[num_chars - 1] = c;
- }
- }
-
- token_buffer[num_chars] = 0;
-
- if (c != '\'')
- cpp_error (pfile, "malformatted character constant");
- else if (num_chars == 0)
- cpp_error (pfile, "empty character constant");
- else if (num_chars > max_chars)
- {
- num_chars = max_chars;
- cpp_error (pfile, "character constant too long");
- }
- else if (num_chars != 1 && ! CPP_TRADITIONAL (pfile))
- cpp_warning (pfile, "multi-character character constant");
+ case CPP_NAME:
+ op.op = INT;
+ op.unsignedp = 0;
+ op.value = 0;
+ if (strcmp (tok_start, "defined"))
+ {
+ if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
+ cpp_warning (pfile, "`%.*s' is not defined",
+ (int) (tok_end - tok_start), tok_start);
+ }
+ else
+ {
+ int paren = 0, len;
+ cpp_buffer *ip = CPP_BUFFER (pfile);
+ U_CHAR *tok;
- /* If char type is signed, sign-extend the constant. */
- if (! wide_flag)
- {
- int num_bits = num_chars * width;
+ cpp_skip_hspace (pfile);
+ if (*ip->cur == '(')
+ {
+ paren++;
+ ip->cur++; /* Skip over the paren */
+ cpp_skip_hspace (pfile);
+ }
- if (cpp_lookup (pfile, (U_CHAR *)"__CHAR_UNSIGNED__",
- sizeof ("__CHAR_UNSIGNED__")-1, -1)
- || ((result >> (num_bits - 1)) & 1) == 0)
- op.value
- = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
- else
- op.value
- = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits));
- }
- else
- {
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[0] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL_PTR, NULL_PTR, 0);
- if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
- result = wc;
- else
- cpp_pedwarn (pfile,"Ignoring invalid multibyte character");
- }
-#endif
- op.value = result;
+ if (!is_idstart[*ip->cur])
+ goto oops;
+ if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
+ goto oops;
+ tok = ip->cur;
+ while (is_idchar[*ip->cur])
+ ++ip->cur;
+ len = ip->cur - tok;
+ cpp_skip_hspace (pfile);
+ if (paren)
+ {
+ if (*ip->cur != ')')
+ goto oops;
+ ++ip->cur;
}
- }
+ if (cpp_lookup (pfile, tok, len, -1))
+ op.value = 1;
- /* This is always a signed type. */
- op.unsignedp = 0;
- op.op = CHAR;
-
+ }
return op;
- case CPP_NAME:
- if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
- cpp_warning (pfile, "`%.*s' is not defined",
- (int) (tok_end - tok_start), tok_start);
- return parse_number (pfile, "0", 0);
+ oops:
+ cpp_error (pfile, "`defined' without an identifier");
+ return op;
case CPP_OTHER:
/* See if it is a special token of length 2. */
@@ -454,11 +484,8 @@ cpp_lex (pfile, skip_evaluation)
&& tok_start[1] == toktab->operator[1])
break;
if (toktab->token == ERROR)
- {
- char *buf = (char *) alloca (40);
- sprintf (buf, "`%s' not allowed in operand of `#if'", tok_start);
- cpp_error (pfile, buf);
- }
+ cpp_error (pfile, "`%s' not allowed in operand of `#if'",
+ tok_start);
op.op = toktab->token;
return op;
}
@@ -484,10 +511,11 @@ cpp_lex (pfile, skip_evaluation)
If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */
-int
-cpp_parse_escape (pfile, string_ptr)
+HOST_WIDEST_INT
+cpp_parse_escape (pfile, string_ptr, result_mask)
cpp_reader *pfile;
char **string_ptr;
+ HOST_WIDEST_INT result_mask;
{
register int c = *(*string_ptr)++;
switch (c)
@@ -498,7 +526,7 @@ cpp_parse_escape (pfile, string_ptr)
return TARGET_BS;
case 'e':
case 'E':
- if (CPP_PEDANTIC (pfile))
+ if (CPP_OPTIONS (pfile)->pedantic)
cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, `\\%c'", c);
return 033;
case 'f':
@@ -526,7 +554,7 @@ cpp_parse_escape (pfile, string_ptr)
case '6':
case '7':
{
- register int i = c - '0';
+ register HOST_WIDEST_INT i = c - '0';
register int count = 0;
while (++count < 3)
{
@@ -539,17 +567,17 @@ cpp_parse_escape (pfile, string_ptr)
break;
}
}
- if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
+ if (i != (i & result_mask))
{
- i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
- cpp_pedwarn (pfile,
- "octal character constant does not fit in a byte");
+ i &= result_mask;
+ cpp_pedwarn (pfile, "octal escape sequence out of range");
}
return i;
}
case 'x':
{
- register unsigned i = 0, overflow = 0, digits_found = 0, digit;
+ register unsigned HOST_WIDEST_INT i = 0, overflow = 0;
+ register int digits_found = 0, digit;
for (;;)
{
c = *(*string_ptr)++;
@@ -570,11 +598,10 @@ cpp_parse_escape (pfile, string_ptr)
}
if (!digits_found)
cpp_error (pfile, "\\x used with no following hex digits");
- if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
+ if (overflow | (i != (i & result_mask)))
{
- i &= (1 << BITS_PER_UNIT) - 1;
- cpp_pedwarn (pfile,
- "hex character constant does not fit in a byte");
+ i &= result_mask;
+ cpp_pedwarn (pfile, "hex escape sequence out of range");
}
return i;
}
@@ -591,41 +618,41 @@ integer_overflow (pfile)
cpp_pedwarn (pfile, "integer overflow in preprocessor expression");
}
-static long
+static HOST_WIDEST_INT
left_shift (pfile, a, unsignedp, b)
cpp_reader *pfile;
- long a;
+ HOST_WIDEST_INT a;
int unsignedp;
- unsigned long b;
+ unsigned HOST_WIDEST_INT b;
{
- if (b >= HOST_BITS_PER_LONG)
+ if (b >= HOST_BITS_PER_WIDEST_INT)
{
if (! unsignedp && a != 0)
integer_overflow (pfile);
return 0;
}
else if (unsignedp)
- return (unsigned long) a << b;
+ return (unsigned HOST_WIDEST_INT) a << b;
else
{
- long l = a << b;
+ HOST_WIDEST_INT l = a << b;
if (l >> b != a)
integer_overflow (pfile);
return l;
}
}
-static long
+static HOST_WIDEST_INT
right_shift (pfile, a, unsignedp, b)
cpp_reader *pfile ATTRIBUTE_UNUSED;
- long a;
+ HOST_WIDEST_INT a;
int unsignedp;
- unsigned long b;
+ unsigned HOST_WIDEST_INT b;
{
- if (b >= HOST_BITS_PER_LONG)
- return unsignedp ? 0 : a >> (HOST_BITS_PER_LONG - 1);
+ if (b >= HOST_BITS_PER_WIDEST_INT)
+ return unsignedp ? 0 : a >> (HOST_BITS_PER_WIDEST_INT - 1);
else if (unsignedp)
- return (unsigned long) a >> b;
+ return (unsigned HOST_WIDEST_INT) a >> b;
else
return a >> b;
}
@@ -649,12 +676,13 @@ right_shift (pfile, a, unsignedp, b)
#define COMPARE(OP) \
top->unsignedp = 0;\
- top->value = (unsigned1 || unsigned2) ? (unsigned long) v1 OP v2 : (v1 OP v2)
+ top->value = (unsigned1 || unsigned2) \
+ ? (unsigned HOST_WIDEST_INT) v1 OP (unsigned HOST_WIDEST_INT) v2 : (v1 OP v2)
/* Parse and evaluate a C expression, reading from PFILE.
Returns the value of the expression. */
-HOST_WIDE_INT
+HOST_WIDEST_INT
cpp_parse_expr (pfile)
cpp_reader *pfile;
{
@@ -673,7 +701,7 @@ cpp_parse_expr (pfile)
struct operation *stack = init_stack;
struct operation *limit = stack + INIT_STACK_SIZE;
register struct operation *top = stack;
- int lprio, rprio;
+ int lprio, rprio = 0;
int skip_evaluation = 0;
top->rprio = 0;
@@ -693,7 +721,8 @@ cpp_parse_expr (pfile)
switch (op.op)
{
case NAME:
- abort ();
+ cpp_fatal (pfile, "internal error: cpp_lex returns a NAME");
+ goto syntax_error;
case INT: case CHAR:
top->value = op.value;
top->unsignedp = op.unsignedp;
@@ -734,6 +763,8 @@ cpp_parse_expr (pfile)
case '?':
lprio = COND_PRIO + 1; rprio = COND_PRIO;
goto maybe_reduce;
+ case ERROR:
+ goto syntax_error;
binop:
flags = LEFT_OPERAND_REQUIRED|RIGHT_OPERAND_REQUIRED;
rprio = lprio + 1;
@@ -757,7 +788,7 @@ cpp_parse_expr (pfile)
/* Push an operator, and check if we can reduce now. */
while (top->rprio > lprio)
{
- long v1 = top[-1].value, v2 = top[0].value;
+ HOST_WIDEST_INT v1 = top[-1].value, v2 = top[0].value;
int unsigned1 = top[-1].unsignedp, unsigned2 = top[0].unsignedp;
top--;
if ((top[1].flags & LEFT_OPERAND_REQUIRED)
@@ -812,7 +843,7 @@ cpp_parse_expr (pfile)
case '*':
top->unsignedp = unsigned1 || unsigned2;
if (top->unsignedp)
- top->value = (unsigned long) v1 * v2;
+ top->value = (unsigned HOST_WIDEST_INT) v1 * v2;
else if (!skip_evaluation)
{
top->value = v1 * v2;
@@ -832,7 +863,7 @@ cpp_parse_expr (pfile)
}
top->unsignedp = unsigned1 || unsigned2;
if (top->unsignedp)
- top->value = (unsigned long) v1 / v2;
+ top->value = (unsigned HOST_WIDEST_INT) v1 / v2;
else
{
top->value = v1 / v2;
@@ -850,7 +881,7 @@ cpp_parse_expr (pfile)
}
top->unsignedp = unsigned1 || unsigned2;
if (top->unsignedp)
- top->value = (unsigned long) v1 % v2;
+ top->value = (unsigned HOST_WIDEST_INT) v1 % v2;
else
top->value = v1 % v2;
break;
@@ -967,11 +998,11 @@ cpp_parse_expr (pfile)
}
break;
default:
- fprintf (stderr,
- top[1].op >= ' ' && top[1].op <= '~'
- ? "unimplemented operator '%c'\n"
- : "unimplemented operator '\\%03o'\n",
- top[1].op);
+ cpp_error (pfile,
+ (top[1].op >= ' ' && top[1].op <= '~'
+ ? "unimplemented operator '%c'\n"
+ : "unimplemented operator '\\%03o'\n"),
+ top[1].op);
}
}
if (op.op == 0)
diff --git a/contrib/gcc/cppfiles.c b/contrib/gcc/cppfiles.c
new file mode 100644
index 0000000..a63d7e5
--- /dev/null
+++ b/contrib/gcc/cppfiles.c
@@ -0,0 +1,1605 @@
+/* Part of CPP library. (include file handling)
+ Copyright (C) 1986, 87, 89, 92 - 95, 98, 1999 Free Software Foundation, Inc.
+ Written by Per Bothner, 1994.
+ Based on CCCP program by Paul Rubin, June 1986
+ Adapted to ANSI C, Richard Stallman, Jan 1987
+ Split out of cpplib.c, Zack Weinberg, Oct 1998
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+
+/* The entry points to this file are: find_include_file, finclude,
+ include_hash, append_include_chain, deps_output, and file_cleanup.
+ file_cleanup is only called through CPP_BUFFER(pfile)->cleanup,
+ so it's static anyway. */
+
+static struct include_hash *redundant_include_p
+ PROTO ((cpp_reader *,
+ struct include_hash *,
+ struct file_name_list *));
+static struct file_name_map *read_name_map PROTO ((cpp_reader *,
+ const char *));
+static char *read_filename_string PROTO ((int, FILE *));
+static char *remap_filename PROTO ((cpp_reader *, char *,
+ struct file_name_list *));
+static long read_and_prescan PROTO ((cpp_reader *, cpp_buffer *,
+ int, size_t));
+static struct file_name_list *actual_directory PROTO ((cpp_reader *, char *));
+
+static void initialize_input_buffer PROTO ((cpp_reader *, int,
+ struct stat *));
+
+#if 0
+static void hack_vms_include_specification PROTO ((char *));
+#endif
+
+/* Windows does not natively support inodes, and neither does MSDOS.
+ VMS has non-numeric inodes. */
+#ifdef VMS
+#define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
+#elif (defined _WIN32 && !defined CYGWIN && ! defined (_UWIN)) \
+ || defined __MSDOS__
+#define INO_T_EQ(a, b) 0
+#else
+#define INO_T_EQ(a, b) ((a) == (b))
+#endif
+
+/* Merge the four include chains together in the order quote, bracket,
+ system, after. Remove duplicate dirs (as determined by
+ INO_T_EQ()). The system_include and after_include chains are never
+ referred to again after this function; all access is through the
+ bracket_include path.
+
+ For the future: Check if the directory is empty (but
+ how?) and possibly preload the include hash. */
+
+void
+merge_include_chains (opts)
+ struct cpp_options *opts;
+{
+ struct file_name_list *prev, *cur, *other;
+ struct file_name_list *quote, *brack, *systm, *after;
+ struct file_name_list *qtail, *btail, *stail, *atail;
+
+ qtail = opts->pending->quote_tail;
+ btail = opts->pending->brack_tail;
+ stail = opts->pending->systm_tail;
+ atail = opts->pending->after_tail;
+
+ quote = opts->pending->quote_head;
+ brack = opts->pending->brack_head;
+ systm = opts->pending->systm_head;
+ after = opts->pending->after_head;
+
+ /* Paste together bracket, system, and after include chains. */
+ if (stail)
+ stail->next = after;
+ else
+ systm = after;
+ if (btail)
+ btail->next = systm;
+ else
+ brack = systm;
+
+ /* This is a bit tricky.
+ First we drop dupes from the quote-include list.
+ Then we drop dupes from the bracket-include list.
+ Finally, if qtail and brack are the same directory,
+ we cut out qtail.
+
+ We can't just merge the lists and then uniquify them because
+ then we may lose directories from the <> search path that should
+ be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however
+ safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written
+ -Ibar -I- -Ifoo -Iquux.
+
+ Note that this algorithm is quadratic in the number of -I switches,
+ which is acceptable since there aren't usually that many of them. */
+
+ for (cur = quote, prev = NULL; cur; cur = cur->next)
+ {
+ for (other = quote; other != cur; other = other->next)
+ if (INO_T_EQ (cur->ino, other->ino)
+ && cur->dev == other->dev)
+ {
+ if (opts->verbose)
+ cpp_notice ("ignoring duplicate directory `%s'\n", cur->name);
+
+ prev->next = cur->next;
+ free (cur->name);
+ free (cur);
+ cur = prev;
+ break;
+ }
+ prev = cur;
+ }
+ qtail = prev;
+
+ for (cur = brack; cur; cur = cur->next)
+ {
+ for (other = brack; other != cur; other = other->next)
+ if (INO_T_EQ (cur->ino, other->ino)
+ && cur->dev == other->dev)
+ {
+ if (opts->verbose)
+ cpp_notice ("ignoring duplicate directory `%s'\n", cur->name);
+
+ prev->next = cur->next;
+ free (cur->name);
+ free (cur);
+ cur = prev;
+ break;
+ }
+ prev = cur;
+ }
+
+ if (quote)
+ {
+ if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev)
+ {
+ if (quote == qtail)
+ {
+ if (opts->verbose)
+ cpp_notice ("ignoring duplicate directory `%s'\n",
+ quote->name);
+
+ free (quote->name);
+ free (quote);
+ quote = brack;
+ }
+ else
+ {
+ cur = quote;
+ while (cur->next != qtail)
+ cur = cur->next;
+ cur->next = brack;
+ if (opts->verbose)
+ cpp_notice ("ignoring duplicate directory `%s'\n",
+ qtail->name);
+
+ free (qtail->name);
+ free (qtail);
+ }
+ }
+ else
+ qtail->next = brack;
+ }
+ else
+ quote = brack;
+
+ opts->quote_include = quote;
+ opts->bracket_include = brack;
+}
+
+/* Look up or add an entry to the table of all includes. This table
+ is indexed by the name as it appears in the #include line. The
+ ->next_this_file chain stores all different files with the same
+ #include name (there are at least three ways this can happen). The
+ hash function could probably be improved a bit. */
+
+struct include_hash *
+include_hash (pfile, fname, add)
+ cpp_reader *pfile;
+ char *fname;
+ int add;
+{
+ unsigned int hash = 0;
+ struct include_hash *l, *m;
+ char *f = fname;
+
+ while (*f)
+ hash += *f++;
+
+ l = pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE];
+ m = 0;
+ for (; l; m = l, l = l->next)
+ if (!strcmp (l->nshort, fname))
+ return l;
+
+ if (!add)
+ return 0;
+
+ l = (struct include_hash *) xmalloc (sizeof (struct include_hash));
+ l->next = NULL;
+ l->next_this_file = NULL;
+ l->foundhere = NULL;
+ l->buf = NULL;
+ l->limit = NULL;
+ if (m)
+ m->next = l;
+ else
+ pfile->all_include_files[hash % ALL_INCLUDE_HASHSIZE] = l;
+
+ return l;
+}
+
+/* Return 0 if the file pointed to by IHASH has never been included before,
+ -1 if it has been included before and need not be again,
+ or a pointer to an IHASH entry which is the file to be reread.
+ "Never before" is with respect to the position in ILIST.
+
+ This will not detect redundancies involving odd uses of the
+ `current directory' rule for "" includes. They aren't quite
+ pathological, but I think they are rare enough not to worry about.
+ The simplest example is:
+
+ top.c:
+ #include "a/a.h"
+ #include "b/b.h"
+
+ a/a.h:
+ #include "../b/b.h"
+
+ and the problem is that for `current directory' includes,
+ ihash->foundhere is not on any of the global include chains,
+ so the test below (i->foundhere == l) may be false even when
+ the directories are in fact the same. */
+
+static struct include_hash *
+redundant_include_p (pfile, ihash, ilist)
+ cpp_reader *pfile;
+ struct include_hash *ihash;
+ struct file_name_list *ilist;
+{
+ struct file_name_list *l;
+ struct include_hash *i;
+
+ if (! ihash->foundhere)
+ return 0;
+
+ for (i = ihash; i; i = i->next_this_file)
+ for (l = ilist; l; l = l->next)
+ if (i->foundhere == l)
+ /* The control_macro works like this: If it's NULL, the file
+ is to be included again. If it's "", the file is never to
+ be included again. If it's a string, the file is not to be
+ included again if the string is the name of a defined macro. */
+ return (i->control_macro
+ && (i->control_macro[0] == '\0'
+ || cpp_lookup (pfile, i->control_macro, -1, -1)))
+ ? (struct include_hash *)-1 : i;
+
+ return 0;
+}
+
+static int
+file_cleanup (pbuf, pfile)
+ cpp_buffer *pbuf;
+ cpp_reader *pfile;
+{
+ if (pbuf->buf)
+ {
+ free (pbuf->buf);
+ pbuf->buf = 0;
+ }
+ if (pfile->system_include_depth)
+ pfile->system_include_depth--;
+ return 0;
+}
+
+/* Search for include file FNAME in the include chain starting at
+ SEARCH_START. Return -2 if this file doesn't need to be included
+ (because it was included already and it's marked idempotent),
+ -1 if an error occurred, or a file descriptor open on the file.
+ *IHASH is set to point to the include hash entry for this file, and
+ *BEFORE is 1 if the file was included before (but needs to be read
+ again). */
+int
+find_include_file (pfile, fname, search_start, ihash, before)
+ cpp_reader *pfile;
+ char *fname;
+ struct file_name_list *search_start;
+ struct include_hash **ihash;
+ int *before;
+{
+ struct file_name_list *l;
+ struct include_hash *ih, *jh;
+ int f, len;
+ char *name;
+
+ ih = include_hash (pfile, fname, 1);
+ jh = redundant_include_p (pfile, ih,
+ fname[0] == '/' ? ABSOLUTE_PATH : search_start);
+
+ if (jh != 0)
+ {
+ *before = 1;
+ *ihash = jh;
+
+ if (jh == (struct include_hash *)-1)
+ return -2;
+ else
+ return open (jh->name, O_RDONLY, 0666);
+ }
+
+ if (ih->foundhere)
+ /* A file is already known by this name, but it's not the same file.
+ Allocate another include_hash block and add it to the next_this_file
+ chain. */
+ {
+ jh = (struct include_hash *)xmalloc (sizeof (struct include_hash));
+ while (ih->next_this_file) ih = ih->next_this_file;
+
+ ih->next_this_file = jh;
+ jh = ih;
+ ih = ih->next_this_file;
+
+ ih->next = NULL;
+ ih->next_this_file = NULL;
+ ih->buf = NULL;
+ ih->limit = NULL;
+ }
+ *before = 0;
+ *ihash = ih;
+ ih->nshort = xstrdup (fname);
+ ih->control_macro = NULL;
+
+ /* If the pathname is absolute, just open it. */
+ if (fname[0] == '/')
+ {
+ ih->foundhere = ABSOLUTE_PATH;
+ ih->name = ih->nshort;
+ return open (ih->name, O_RDONLY, 0666);
+ }
+
+ /* Search directory path, trying to open the file. */
+
+ len = strlen (fname);
+ name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE);
+
+ for (l = search_start; l; l = l->next)
+ {
+ bcopy (l->name, name, l->nlen);
+ name[l->nlen] = '/';
+ strcpy (&name[l->nlen+1], fname);
+ simplify_pathname (name);
+ if (CPP_OPTIONS (pfile)->remap)
+ name = remap_filename (pfile, name, l);
+
+ f = open (name, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
+#ifdef EACCES
+ if (f == -1 && errno == EACCES)
+ {
+ cpp_error(pfile, "included file `%s' exists but is not readable",
+ name);
+ return -1;
+ }
+#endif
+
+ if (f >= 0)
+ {
+ ih->foundhere = l;
+ ih->name = xrealloc (name, strlen (name)+1);
+ return f;
+ }
+ }
+
+ if (jh)
+ {
+ jh->next_this_file = NULL;
+ free (ih);
+ }
+ free (name);
+ *ihash = (struct include_hash *)-1;
+ return -1;
+}
+
+/* The file_name_map structure holds a mapping of file names for a
+ particular directory. This mapping is read from the file named
+ FILE_NAME_MAP_FILE in that directory. Such a file can be used to
+ map filenames on a file system with severe filename restrictions,
+ such as DOS. The format of the file name map file is just a series
+ of lines with two tokens on each line. The first token is the name
+ to map, and the second token is the actual name to use. */
+
+struct file_name_map
+{
+ struct file_name_map *map_next;
+ char *map_from;
+ char *map_to;
+};
+
+#define FILE_NAME_MAP_FILE "header.gcc"
+
+/* Read a space delimited string of unlimited length from a stdio
+ file. */
+
+static char *
+read_filename_string (ch, f)
+ int ch;
+ FILE *f;
+{
+ char *alloc, *set;
+ int len;
+
+ len = 20;
+ set = alloc = xmalloc (len + 1);
+ if (! is_space[ch])
+ {
+ *set++ = ch;
+ while ((ch = getc (f)) != EOF && ! is_space[ch])
+ {
+ if (set - alloc == len)
+ {
+ len *= 2;
+ alloc = xrealloc (alloc, len + 1);
+ set = alloc + len / 2;
+ }
+ *set++ = ch;
+ }
+ }
+ *set = '\0';
+ ungetc (ch, f);
+ return alloc;
+}
+
+/* This structure holds a linked list of file name maps, one per directory. */
+
+struct file_name_map_list
+{
+ struct file_name_map_list *map_list_next;
+ char *map_list_name;
+ struct file_name_map *map_list_map;
+};
+
+/* Read the file name map file for DIRNAME. */
+
+static struct file_name_map *
+read_name_map (pfile, dirname)
+ cpp_reader *pfile;
+ const char *dirname;
+{
+ register struct file_name_map_list *map_list_ptr;
+ char *name;
+ FILE *f;
+
+ for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
+ map_list_ptr = map_list_ptr->map_list_next)
+ if (! strcmp (map_list_ptr->map_list_name, dirname))
+ return map_list_ptr->map_list_map;
+
+ map_list_ptr = ((struct file_name_map_list *)
+ xmalloc (sizeof (struct file_name_map_list)));
+ map_list_ptr->map_list_name = xstrdup (dirname);
+
+ name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
+ strcpy (name, dirname);
+ if (*dirname)
+ strcat (name, "/");
+ strcat (name, FILE_NAME_MAP_FILE);
+ f = fopen (name, "r");
+ if (!f)
+ map_list_ptr->map_list_map = (struct file_name_map *)-1;
+ else
+ {
+ int ch;
+ int dirlen = strlen (dirname);
+
+ while ((ch = getc (f)) != EOF)
+ {
+ char *from, *to;
+ struct file_name_map *ptr;
+
+ if (is_space[ch])
+ continue;
+ from = read_filename_string (ch, f);
+ while ((ch = getc (f)) != EOF && is_hor_space[ch])
+ ;
+ to = read_filename_string (ch, f);
+
+ ptr = ((struct file_name_map *)
+ xmalloc (sizeof (struct file_name_map)));
+ ptr->map_from = from;
+
+ /* Make the real filename absolute. */
+ if (*to == '/')
+ ptr->map_to = to;
+ else
+ {
+ ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
+ strcpy (ptr->map_to, dirname);
+ ptr->map_to[dirlen] = '/';
+ strcpy (ptr->map_to + dirlen + 1, to);
+ free (to);
+ }
+
+ ptr->map_next = map_list_ptr->map_list_map;
+ map_list_ptr->map_list_map = ptr;
+
+ while ((ch = getc (f)) != '\n')
+ if (ch == EOF)
+ break;
+ }
+ fclose (f);
+ }
+
+ map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
+ CPP_OPTIONS (pfile)->map_list = map_list_ptr;
+
+ return map_list_ptr->map_list_map;
+}
+
+/* Remap NAME based on the file_name_map (if any) for LOC. */
+
+static char *
+remap_filename (pfile, name, loc)
+ cpp_reader *pfile;
+ char *name;
+ struct file_name_list *loc;
+{
+ struct file_name_map *map;
+ const char *from, *p, *dir;
+
+ if (! loc->name_map)
+ loc->name_map = read_name_map (pfile,
+ loc->name
+ ? loc->name : ".");
+
+ if (loc->name_map == (struct file_name_map *)-1)
+ return name;
+
+ from = name + strlen (loc->name) + 1;
+
+ for (map = loc->name_map; map; map = map->map_next)
+ if (!strcmp (map->map_from, from))
+ return map->map_to;
+
+ /* Try to find a mapping file for the particular directory we are
+ looking in. Thus #include <sys/types.h> will look up sys/types.h
+ in /usr/include/header.gcc and look up types.h in
+ /usr/include/sys/header.gcc. */
+ p = rindex (name, '/');
+ if (!p)
+ p = name;
+ if (loc && loc->name
+ && strlen (loc->name) == (size_t) (p - name)
+ && !strncmp (loc->name, name, p - name))
+ /* FILENAME is in SEARCHPTR, which we've already checked. */
+ return name;
+
+ if (p == name)
+ {
+ dir = ".";
+ from = name;
+ }
+ else
+ {
+ char * newdir = (char *) alloca (p - name + 1);
+ bcopy (name, newdir, p - name);
+ newdir[p - name] = '\0';
+ dir = newdir;
+ from = p + 1;
+ }
+
+ for (map = read_name_map (pfile, dir); map; map = map->map_next)
+ if (! strcmp (map->map_from, name))
+ return map->map_to;
+
+ return name;
+}
+
+/* Read the contents of FD into the buffer on the top of PFILE's stack.
+ IHASH points to the include hash entry for the file associated with
+ FD.
+
+ The caller is responsible for the cpp_push_buffer. */
+
+int
+finclude (pfile, fd, ihash)
+ cpp_reader *pfile;
+ int fd;
+ struct include_hash *ihash;
+{
+ struct stat st;
+ size_t st_size;
+ long length;
+ cpp_buffer *fp;
+
+ if (fstat (fd, &st) < 0)
+ goto perror_fail;
+ if (fcntl (fd, F_SETFL, 0) == -1) /* turn off nonblocking mode */
+ goto perror_fail;
+
+ fp = CPP_BUFFER (pfile);
+
+ /* If fd points to a plain file, we know how big it is, so we can
+ allocate the buffer all at once. If fd is a pipe or terminal, we
+ can't. Most C source files are 4k or less, so we guess that. If
+ fd is something weird, like a block device or a directory, we
+ don't want to read it at all.
+
+ Unfortunately, different systems use different st.st_mode values
+ for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and
+ zero the entire struct stat except a couple fields. Hence the
+ mess below.
+
+ In all cases, read_and_prescan will resize the buffer if it
+ turns out there's more data than we thought. */
+
+ if (S_ISREG (st.st_mode))
+ {
+ /* off_t might have a wider range than size_t - in other words,
+ the max size of a file might be bigger than the address
+ space. We can't handle a file that large. (Anyone with
+ a single source file bigger than 4GB needs to rethink
+ their coding style.) */
+ st_size = (size_t) st.st_size;
+ if ((unsigned HOST_WIDEST_INT) st_size
+ != (unsigned HOST_WIDEST_INT) st.st_size)
+ {
+ cpp_error (pfile, "file `%s' is too large", ihash->name);
+ goto fail;
+ }
+ }
+ else if (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode)
+ /* Permit any kind of character device: the sensible ones are
+ ttys and /dev/null, but weeding out the others is too hard. */
+ || S_ISCHR (st.st_mode)
+ /* Some 4.x (x<4) derivatives have a bug that makes fstat() of a
+ socket or pipe return a stat struct with most fields zeroed. */
+ || (st.st_mode == 0 && st.st_nlink == 0 && st.st_size == 0))
+ {
+ /* Cannot get its file size before reading. 4k is a decent
+ first guess. */
+ st_size = 4096;
+ }
+ else
+ {
+ cpp_error (pfile, "`%s' is not a file, pipe, or tty", ihash->name);
+ goto fail;
+ }
+
+ if (pfile->input_buffer == NULL)
+ initialize_input_buffer (pfile, fd, &st);
+
+ /* Read the file, converting end-of-line characters and trigraphs
+ (if enabled). */
+ fp->ihash = ihash;
+ fp->nominal_fname = fp->fname = ihash->name;
+ length = read_and_prescan (pfile, fp, fd, st_size);
+ if (length < 0)
+ goto fail;
+ if (length == 0)
+ ihash->control_macro = ""; /* never re-include */
+
+ close (fd);
+ fp->rlimit = fp->alimit = fp->buf + length;
+ fp->cur = fp->buf;
+ if (ihash->foundhere != ABSOLUTE_PATH)
+ fp->system_header_p = ihash->foundhere->sysp;
+ fp->lineno = 1;
+ fp->colno = 1;
+ fp->line_base = fp->buf;
+ fp->cleanup = file_cleanup;
+
+ /* The ->actual_dir field is only used when ignore_srcdir is not in effect;
+ see do_include */
+ if (!CPP_OPTIONS (pfile)->ignore_srcdir)
+ fp->actual_dir = actual_directory (pfile, fp->fname);
+
+ pfile->input_stack_listing_current = 0;
+ return 1;
+
+ perror_fail:
+ cpp_error_from_errno (pfile, ihash->name);
+ fail:
+ cpp_pop_buffer (pfile);
+ close (fd);
+ return 0;
+}
+
+/* Given a path FNAME, extract the directory component and place it
+ onto the actual_dirs list. Return a pointer to the allocated
+ file_name_list structure. These structures are used to implement
+ current-directory "" include searching. */
+
+static struct file_name_list *
+actual_directory (pfile, fname)
+ cpp_reader *pfile;
+ char *fname;
+{
+ char *last_slash, *dir;
+ size_t dlen;
+ struct file_name_list *x;
+
+ dir = xstrdup (fname);
+ last_slash = rindex (dir, '/');
+ if (last_slash)
+ {
+ if (last_slash == dir)
+ {
+ dlen = 1;
+ last_slash[1] = '\0';
+ }
+ else
+ {
+ dlen = last_slash - dir;
+ *last_slash = '\0';
+ }
+ }
+ else
+ {
+ dir[0] = '.';
+ dir[1] = '\0';
+ dlen = 1;
+ }
+
+ if (dlen > pfile->max_include_len)
+ pfile->max_include_len = dlen;
+
+ for (x = pfile->actual_dirs; x; x = x->alloc)
+ if (!strcmp (x->name, dir))
+ {
+ free (dir);
+ return x;
+ }
+
+ /* Not found, make a new one. */
+ x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
+ x->name = dir;
+ x->nlen = dlen;
+ x->next = CPP_OPTIONS (pfile)->quote_include;
+ x->alloc = pfile->actual_dirs;
+ x->sysp = CPP_BUFFER (pfile)->system_header_p;
+ x->name_map = NULL;
+
+ pfile->actual_dirs = x;
+ return x;
+}
+
+/* Determine the current line and column. Used only by read_and_prescan. */
+static void
+find_position (start, limit, linep, colp)
+ U_CHAR *start;
+ U_CHAR *limit;
+ unsigned long *linep;
+ unsigned long *colp;
+{
+ unsigned long line = *linep, col = 0;
+ while (start < limit)
+ {
+ U_CHAR ch = *start++;
+ if (ch == '\n' || ch == '\r')
+ line++, col = 1;
+ else
+ col++;
+ }
+ *linep = line, *colp = col;
+}
+
+/* Read the entire contents of file DESC into buffer BUF. LEN is how
+ much memory to allocate initially; more will be allocated if
+ necessary. Convert end-of-line markers (\n, \r, \r\n, \n\r) to
+ canonical form (\n). If enabled, convert and/or warn about
+ trigraphs. Convert backslash-newline to a one-character escape
+ (\r) and remove it from "embarrassing" places (i.e. the middle of a
+ token). If there is no newline at the end of the file, add one and
+ warn. Returns -1 on failure, or the actual length of the data to
+ be scanned.
+
+ This function does a lot of work, and can be a serious performance
+ bottleneck. It has been tuned heavily; make sure you understand it
+ before hacking. The common case - no trigraphs, Unix style line
+ breaks, backslash-newline set off by whitespace, newline at EOF -
+ has been optimized at the expense of the others. The performance
+ penalty for DOS style line breaks (\r\n) is about 15%.
+
+ Warnings lose particularly heavily since we have to determine the
+ line number, which involves scanning from the beginning of the file
+ or from the last warning. The penalty for the absence of a newline
+ at the end of reload1.c is about 60%. (reload1.c is 329k.)
+
+ If your file has more than one kind of end-of-line marker, you
+ will get messed-up line numbering. */
+
+/* Table of characters that can't be handled in the inner loop.
+ Keep these contiguous to optimize the performance of the code generated
+ for the switch that uses them. */
+#define SPECCASE_EMPTY 0
+#define SPECCASE_NUL 1
+#define SPECCASE_CR 2
+#define SPECCASE_BACKSLASH 3
+#define SPECCASE_QUESTION 4
+
+static long
+read_and_prescan (pfile, fp, desc, len)
+ cpp_reader *pfile;
+ cpp_buffer *fp;
+ int desc;
+ size_t len;
+{
+ U_CHAR *buf = (U_CHAR *) xmalloc (len);
+ U_CHAR *ip, *op, *line_base;
+ U_CHAR *ibase;
+ U_CHAR *speccase = pfile->input_speccase;
+ unsigned long line;
+ unsigned int deferred_newlines;
+ int count;
+ size_t offset;
+
+ offset = 0;
+ op = buf;
+ line_base = buf;
+ line = 1;
+ ibase = pfile->input_buffer + 2;
+ deferred_newlines = 0;
+
+ for (;;)
+ {
+ read_next:
+
+ count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len);
+ if (count < 0)
+ goto error;
+ else if (count == 0)
+ break;
+
+ offset += count;
+ ip = ibase;
+ ibase = pfile->input_buffer + 2;
+ ibase[count] = ibase[count+1] = '\0';
+
+ if (offset > len)
+ {
+ size_t delta_op;
+ size_t delta_line_base;
+ len *= 2;
+ if (offset > len)
+ /* len overflowed.
+ This could happen if the file is larger than half the
+ maximum address space of the machine. */
+ goto too_big;
+
+ delta_op = op - buf;
+ delta_line_base = line_base - buf;
+ buf = (U_CHAR *) xrealloc (buf, len);
+ op = buf + delta_op;
+ line_base = buf + delta_line_base;
+ }
+
+ for (;;)
+ {
+ unsigned int span = 0;
+
+ /* Deal with \-newline in the middle of a token. */
+ if (deferred_newlines)
+ {
+ while (speccase[ip[span]] == SPECCASE_EMPTY
+ && ip[span] != '\n'
+ && ip[span] != '\t'
+ && ip[span] != ' ')
+ span++;
+ memcpy (op, ip, span);
+ op += span;
+ ip += span;
+ if (*ip == '\n' || *ip == '\t'
+ || *ip == ' ' || *ip == ' ')
+ while (deferred_newlines)
+ deferred_newlines--, *op++ = '\r';
+ span = 0;
+ }
+
+ /* Copy as much as we can without special treatment. */
+ while (speccase[ip[span]] == SPECCASE_EMPTY) span++;
+ memcpy (op, ip, span);
+ op += span;
+ ip += span;
+
+ switch (speccase[*ip++])
+ {
+ case SPECCASE_NUL: /* \0 */
+ ibase[-1] = op[-1];
+ goto read_next;
+
+ case SPECCASE_CR: /* \r */
+ if (*ip == '\n')
+ ip++;
+ else if (*ip == '\0')
+ {
+ *--ibase = '\r';
+ goto read_next;
+ }
+ else if (ip[-2] == '\n')
+ continue;
+ *op++ = '\n';
+ break;
+
+ case SPECCASE_BACKSLASH: /* \ */
+ backslash:
+ {
+ /* If we're at the end of the intermediate buffer,
+ we have to shift the backslash down to the start
+ and come back next pass. */
+ if (*ip == '\0')
+ {
+ *--ibase = '\\';
+ goto read_next;
+ }
+ else if (*ip == '\n')
+ {
+ ip++;
+ if (*ip == '\r') ip++;
+ if (*ip == '\n' || *ip == '\t' || *ip == ' ')
+ *op++ = '\r';
+ else if (op[-1] == '\t' || op[-1] == ' '
+ || op[-1] == '\r' || op[-1] == '\n')
+ *op++ = '\r';
+ else
+ deferred_newlines++;
+ line++;
+ line_base = op;
+ }
+ else if (*ip == '\r')
+ {
+ ip++;
+ if (*ip == '\n') ip++;
+ else if (*ip == '\0')
+ {
+ *--ibase = '\r';
+ *--ibase = '\\';
+ goto read_next;
+ }
+ else if (*ip == '\r' || *ip == '\t' || *ip == ' ')
+ *op++ = '\r';
+ else
+ deferred_newlines++;
+ line++;
+ line_base = op;
+ }
+ else
+ *op++ = '\\';
+ }
+ break;
+
+ case SPECCASE_QUESTION: /* ? */
+ {
+ unsigned int d;
+ /* If we're at the end of the intermediate buffer,
+ we have to shift the ?'s down to the start and
+ come back next pass. */
+ d = ip[0];
+ if (d == '\0')
+ {
+ *--ibase = '?';
+ goto read_next;
+ }
+ if (d != '?')
+ {
+ *op++ = '?';
+ break;
+ }
+ d = ip[1];
+ if (d == '\0')
+ {
+ *--ibase = '?';
+ *--ibase = '?';
+ goto read_next;
+ }
+ if (!trigraph_table[d])
+ {
+ *op++ = '?';
+ break;
+ }
+
+ if (CPP_OPTIONS (pfile)->warn_trigraphs)
+ {
+ unsigned long col;
+ find_position (line_base, op, &line, &col);
+ line_base = op - col;
+ cpp_warning_with_line (pfile, line, col,
+ "trigraph ??%c encountered", d);
+ }
+ if (CPP_OPTIONS (pfile)->trigraphs)
+ {
+ if (trigraph_table[d] == '\\')
+ goto backslash;
+ else
+ *op++ = trigraph_table[d];
+ }
+ else
+ {
+ *op++ = '?';
+ *op++ = '?';
+ *op++ = d;
+ }
+ ip += 2;
+ }
+ }
+ }
+ }
+
+ if (offset == 0)
+ return 0;
+
+ /* Deal with pushed-back chars at true EOF.
+ This may be any of: ?? ? \ \r \n \\r \\n.
+ \r must become \n, \\r or \\n must become \r.
+ We know we have space already. */
+ if (ibase == pfile->input_buffer)
+ {
+ if (*ibase == '?')
+ {
+ *op++ = '?';
+ *op++ = '?';
+ }
+ else
+ *op++ = '\r';
+ }
+ else if (ibase == pfile->input_buffer + 1)
+ {
+ if (*ibase == '\r')
+ *op++ = '\n';
+ else
+ *op++ = *ibase;
+ }
+
+ if (op[-1] != '\n')
+ {
+ unsigned long col;
+ find_position (line_base, op, &line, &col);
+ cpp_warning_with_line (pfile, line, col, "no newline at end of file\n");
+ if (offset + 1 > len)
+ {
+ len += 1;
+ if (offset + 1 > len)
+ goto too_big;
+ buf = (U_CHAR *) xrealloc (buf, len);
+ op = buf + offset;
+ }
+ *op++ = '\n';
+ }
+
+ fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf));
+ return op - buf;
+
+ too_big:
+ cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset);
+ free (buf);
+ return -1;
+
+ error:
+ cpp_error_from_errno (pfile, fp->fname);
+ free (buf);
+ return -1;
+}
+
+/* Initialize the `input_buffer' and `input_speccase' tables.
+ These are only used by read_and_prescan, but they're large and
+ somewhat expensive to set up, so we want them allocated once for
+ the duration of the cpp run. */
+
+static void
+initialize_input_buffer (pfile, fd, st)
+ cpp_reader *pfile;
+ int fd;
+ struct stat *st;
+{
+ long pipe_buf;
+ U_CHAR *tmp;
+
+ /* Table of characters that cannot be handled by the
+ read_and_prescan inner loop. The number of non-EMPTY entries
+ should be as small as humanly possible. */
+
+ tmp = xmalloc (1 << CHAR_BIT);
+ memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT);
+ tmp['\0'] = SPECCASE_NUL;
+ tmp['\r'] = SPECCASE_CR;
+ tmp['\\'] = SPECCASE_BACKSLASH;
+ if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs)
+ tmp['?'] = SPECCASE_QUESTION;
+
+ pfile->input_speccase = tmp;
+
+ /* Determine the appropriate size for the input buffer. Normal C
+ source files are smaller than eight K. If we are reading a pipe,
+ we want to make sure the input buffer is bigger than the kernel's
+ pipe buffer. */
+ pipe_buf = -1;
+
+ if (! S_ISREG (st->st_mode))
+ {
+#ifdef _PC_PIPE_BUF
+ pipe_buf = fpathconf (fd, _PC_PIPE_BUF);
+#endif
+ if (pipe_buf == -1)
+ {
+#ifdef PIPE_BUF
+ pipe_buf = PIPE_BUF;
+#else
+ pipe_buf = 8192;
+#endif
+ }
+ }
+
+ if (pipe_buf < 8192)
+ pipe_buf = 8192;
+ /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end
+ without address arithmetic all the time, and 2 for pushback in
+ the case there's a potential trigraph or end-of-line digraph at
+ the end of a block. */
+
+ tmp = xmalloc (pipe_buf + 2 + 2);
+ pfile->input_buffer = tmp;
+ pfile->input_buffer_len = pipe_buf;
+}
+
+/* Add output to `deps_buffer' for the -M switch.
+ STRING points to the text to be output.
+ SPACER is ':' for targets, ' ' for dependencies, zero for text
+ to be inserted literally. */
+
+void
+deps_output (pfile, string, spacer)
+ cpp_reader *pfile;
+ char *string;
+ int spacer;
+{
+ int size;
+ int cr = 0;
+
+ if (!*string)
+ return;
+
+ size = strlen (string);
+
+#ifndef MAX_OUTPUT_COLUMNS
+#define MAX_OUTPUT_COLUMNS 72
+#endif
+ if (pfile->deps_column > 0
+ && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
+ {
+ cr = 5;
+ pfile->deps_column = 0;
+ }
+
+ if (pfile->deps_size + size + cr + 8 > pfile->deps_allocated_size)
+ {
+ pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
+ pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
+ pfile->deps_allocated_size);
+ }
+
+ if (cr)
+ {
+ bcopy (" \\\n ", &pfile->deps_buffer[pfile->deps_size], 5);
+ pfile->deps_size += 5;
+ }
+
+ if (spacer == ' ' && pfile->deps_column > 0)
+ pfile->deps_buffer[pfile->deps_size++] = ' ';
+ bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
+ pfile->deps_size += size;
+ pfile->deps_column += size;
+ if (spacer == ':')
+ pfile->deps_buffer[pfile->deps_size++] = ':';
+ pfile->deps_buffer[pfile->deps_size] = 0;
+}
+
+/* Simplify a path name in place, deleting redundant components. This
+ reduces OS overhead and guarantees that equivalent paths compare
+ the same (modulo symlinks).
+
+ Transforms made:
+ foo/bar/../quux foo/quux
+ foo/./bar foo/bar
+ foo//bar foo/bar
+ /../quux /quux
+ //quux //quux (POSIX allows leading // as a namespace escape)
+
+ Guarantees no trailing slashes. All transforms reduce the length
+ of the string.
+ */
+void
+simplify_pathname (path)
+ char *path;
+{
+ char *from, *to;
+ char *base;
+ int absolute = 0;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Convert all backslashes to slashes. */
+ for (from = path; *from; from++)
+ if (*from == '\\') *from = '/';
+
+ /* Skip over leading drive letter if present. */
+ if (ISALPHA (path[0]) && path[1] == ':')
+ from = to = &path[2];
+ else
+ from = to = path;
+#else
+ from = to = path;
+#endif
+
+ /* Remove redundant initial /s. */
+ if (*from == '/')
+ {
+ absolute = 1;
+ to++;
+ from++;
+ if (*from == '/')
+ {
+ if (*++from == '/')
+ /* 3 or more initial /s are equivalent to 1 /. */
+ while (*++from == '/');
+ else
+ /* On some hosts // differs from /; Posix allows this. */
+ to++;
+ }
+ }
+ base = to;
+
+ for (;;)
+ {
+ while (*from == '/')
+ from++;
+
+ if (from[0] == '.' && from[1] == '/')
+ from += 2;
+ else if (from[0] == '.' && from[1] == '\0')
+ goto done;
+ else if (from[0] == '.' && from[1] == '.' && from[2] == '/')
+ {
+ if (base == to)
+ {
+ if (absolute)
+ from += 3;
+ else
+ {
+ *to++ = *from++;
+ *to++ = *from++;
+ *to++ = *from++;
+ base = to;
+ }
+ }
+ else
+ {
+ to -= 2;
+ while (to > base && *to != '/') to--;
+ if (*to == '/')
+ to++;
+ from += 3;
+ }
+ }
+ else if (from[0] == '.' && from[1] == '.' && from[2] == '\0')
+ {
+ if (base == to)
+ {
+ if (!absolute)
+ {
+ *to++ = *from++;
+ *to++ = *from++;
+ }
+ }
+ else
+ {
+ to -= 2;
+ while (to > base && *to != '/') to--;
+ if (*to == '/')
+ to++;
+ }
+ goto done;
+ }
+ else
+ /* Copy this component and trailing /, if any. */
+ while ((*to++ = *from++) != '/')
+ {
+ if (!to[-1])
+ {
+ to--;
+ goto done;
+ }
+ }
+
+ }
+
+ done:
+ /* Trim trailing slash */
+ if (to[0] == '/' && (!absolute || to > path+1))
+ to--;
+
+ /* Change the empty string to "." so that stat() on the result
+ will always work. */
+ if (to == path)
+ *to++ = '.';
+
+ *to = '\0';
+
+ return;
+}
+
+/* It is not clear when this should be used if at all, so I've
+ disabled it until someone who understands VMS can look at it. */
+#if 0
+
+/* Under VMS we need to fix up the "include" specification filename.
+
+ Rules for possible conversions
+
+ fullname tried paths
+
+ name name
+ ./dir/name [.dir]name
+ /dir/name dir:name
+ /name [000000]name, name
+ dir/name dir:[000000]name, dir:name, dir/name
+ dir1/dir2/name dir1:[dir2]name, dir1:[000000.dir2]name
+ path:/name path:[000000]name, path:name
+ path:/dir/name path:[000000.dir]name, path:[dir]name
+ path:dir/name path:[dir]name
+ [path]:[dir]name [path.dir]name
+ path/[dir]name [path.dir]name
+
+ The path:/name input is constructed when expanding <> includes. */
+
+
+static void
+hack_vms_include_specification (fullname)
+ char *fullname;
+{
+ register char *basename, *unixname, *local_ptr, *first_slash;
+ int f, check_filename_before_returning, must_revert;
+ char Local[512];
+
+ check_filename_before_returning = 0;
+ must_revert = 0;
+ /* See if we can find a 1st slash. If not, there's no path information. */
+ first_slash = index (fullname, '/');
+ if (first_slash == 0)
+ return 0; /* Nothing to do!!! */
+
+ /* construct device spec if none given. */
+
+ if (index (fullname, ':') == 0)
+ {
+
+ /* If fullname has a slash, take it as device spec. */
+
+ if (first_slash == fullname)
+ {
+ first_slash = index (fullname+1, '/'); /* 2nd slash ? */
+ if (first_slash)
+ *first_slash = ':'; /* make device spec */
+ for (basename = fullname; *basename != 0; basename++)
+ *basename = *(basename+1); /* remove leading slash */
+ }
+ else if ((first_slash[-1] != '.') /* keep ':/', './' */
+ && (first_slash[-1] != ':')
+ && (first_slash[-1] != ']')) /* or a vms path */
+ {
+ *first_slash = ':';
+ }
+ else if ((first_slash[1] == '[') /* skip './' in './[dir' */
+ && (first_slash[-1] == '.'))
+ fullname += 2;
+ }
+
+ /* Get part after first ':' (basename[-1] == ':')
+ or last '/' (basename[-1] == '/'). */
+
+ basename = base_name (fullname);
+
+ local_ptr = Local; /* initialize */
+
+ /* We are trying to do a number of things here. First of all, we are
+ trying to hammer the filenames into a standard format, such that later
+ processing can handle them.
+
+ If the file name contains something like [dir.], then it recognizes this
+ as a root, and strips the ".]". Later processing will add whatever is
+ needed to get things working properly.
+
+ If no device is specified, then the first directory name is taken to be
+ a device name (or a rooted logical). */
+
+ /* Point to the UNIX filename part (which needs to be fixed!)
+ but skip vms path information.
+ [basename != fullname since first_slash != 0]. */
+
+ if ((basename[-1] == ':') /* vms path spec. */
+ || (basename[-1] == ']')
+ || (basename[-1] == '>'))
+ unixname = basename;
+ else
+ unixname = fullname;
+
+ if (*unixname == '/')
+ unixname++;
+
+ /* If the directory spec is not rooted, we can just copy
+ the UNIX filename part and we are done. */
+
+ if (((basename - fullname) > 1)
+ && ( (basename[-1] == ']')
+ || (basename[-1] == '>')))
+ {
+ if (basename[-2] != '.')
+ {
+
+ /* The VMS part ends in a `]', and the preceding character is not a `.'.
+ -> PATH]:/name (basename = '/name', unixname = 'name')
+ We strip the `]', and then splice the two parts of the name in the
+ usual way. Given the default locations for include files in cccp.c,
+ we will only use this code if the user specifies alternate locations
+ with the /include (-I) switch on the command line. */
+
+ basename -= 1; /* Strip "]" */
+ unixname--; /* backspace */
+ }
+ else
+ {
+
+ /* The VMS part has a ".]" at the end, and this will not do. Later
+ processing will add a second directory spec, and this would be a syntax
+ error. Thus we strip the ".]", and thus merge the directory specs.
+ We also backspace unixname, so that it points to a '/'. This inhibits the
+ generation of the 000000 root directory spec (which does not belong here
+ in this case). */
+
+ basename -= 2; /* Strip ".]" */
+ unixname--; /* backspace */
+ }
+ }
+
+ else
+
+ {
+
+ /* We drop in here if there is no VMS style directory specification yet.
+ If there is no device specification either, we make the first dir a
+ device and try that. If we do not do this, then we will be essentially
+ searching the users default directory (as if they did a #include "asdf.h").
+
+ Then all we need to do is to push a '[' into the output string. Later
+ processing will fill this in, and close the bracket. */
+
+ if ((unixname != fullname) /* vms path spec found. */
+ && (basename[-1] != ':'))
+ *local_ptr++ = ':'; /* dev not in spec. take first dir */
+
+ *local_ptr++ = '['; /* Open the directory specification */
+ }
+
+ if (unixname == fullname) /* no vms dir spec. */
+ {
+ must_revert = 1;
+ if ((first_slash != 0) /* unix dir spec. */
+ && (*unixname != '/') /* not beginning with '/' */
+ && (*unixname != '.')) /* or './' or '../' */
+ *local_ptr++ = '.'; /* dir is local ! */
+ }
+
+ /* at this point we assume that we have the device spec, and (at least
+ the opening "[" for a directory specification. We may have directories
+ specified already.
+
+ If there are no other slashes then the filename will be
+ in the "root" directory. Otherwise, we need to add
+ directory specifications. */
+
+ if (index (unixname, '/') == 0)
+ {
+ /* if no directories specified yet and none are following. */
+ if (local_ptr[-1] == '[')
+ {
+ /* Just add "000000]" as the directory string */
+ strcpy (local_ptr, "000000]");
+ local_ptr += strlen (local_ptr);
+ check_filename_before_returning = 1; /* we might need to fool with this later */
+ }
+ }
+ else
+ {
+
+ /* As long as there are still subdirectories to add, do them. */
+ while (index (unixname, '/') != 0)
+ {
+ /* If this token is "." we can ignore it
+ if it's not at the beginning of a path. */
+ if ((unixname[0] == '.') && (unixname[1] == '/'))
+ {
+ /* remove it at beginning of path. */
+ if ( ((unixname == fullname) /* no device spec */
+ && (fullname+2 != basename)) /* starts with ./ */
+ /* or */
+ || ((basename[-1] == ':') /* device spec */
+ && (unixname-1 == basename))) /* and ./ afterwards */
+ *local_ptr++ = '.'; /* make '[.' start of path. */
+ unixname += 2;
+ continue;
+ }
+
+ /* Add a subdirectory spec. Do not duplicate "." */
+ if ( local_ptr[-1] != '.'
+ && local_ptr[-1] != '['
+ && local_ptr[-1] != '<')
+ *local_ptr++ = '.';
+
+ /* If this is ".." then the spec becomes "-" */
+ if ( (unixname[0] == '.')
+ && (unixname[1] == '.')
+ && (unixname[2] == '/'))
+ {
+ /* Add "-" and skip the ".." */
+ if ((local_ptr[-1] == '.')
+ && (local_ptr[-2] == '['))
+ local_ptr--; /* prevent [.- */
+ *local_ptr++ = '-';
+ unixname += 3;
+ continue;
+ }
+
+ /* Copy the subdirectory */
+ while (*unixname != '/')
+ *local_ptr++= *unixname++;
+
+ unixname++; /* Skip the "/" */
+ }
+
+ /* Close the directory specification */
+ if (local_ptr[-1] == '.') /* no trailing periods */
+ local_ptr--;
+
+ if (local_ptr[-1] == '[') /* no dir needed */
+ local_ptr--;
+ else
+ *local_ptr++ = ']';
+ }
+
+ /* Now add the filename. */
+
+ while (*unixname)
+ *local_ptr++ = *unixname++;
+ *local_ptr = 0;
+
+ /* Now append it to the original VMS spec. */
+
+ strcpy ((must_revert==1)?fullname:basename, Local);
+
+ /* If we put a [000000] in the filename, try to open it first. If this fails,
+ remove the [000000], and return that name. This provides flexibility
+ to the user in that they can use both rooted and non-rooted logical names
+ to point to the location of the file. */
+
+ if (check_filename_before_returning)
+ {
+ f = open (fullname, O_RDONLY, 0666);
+ if (f >= 0)
+ {
+ /* The file name is OK as it is, so return it as is. */
+ close (f);
+ return 1;
+ }
+
+ /* The filename did not work. Try to remove the [000000] from the name,
+ and return it. */
+
+ basename = index (fullname, '[');
+ local_ptr = index (fullname, ']') + 1;
+ strcpy (basename, local_ptr); /* this gets rid of it */
+
+ }
+
+ return 1;
+}
+#endif /* VMS */
diff --git a/contrib/gcc/cpphash.c b/contrib/gcc/cpphash.c
index 6aa9e9c..1d8a104 100644
--- a/contrib/gcc/cpphash.c
+++ b/contrib/gcc/cpphash.c
@@ -1,5 +1,5 @@
-/* Part of CPP library. (Macro hash table support.)
- Copyright (C) 1986, 87, 89, 92-95, 1996 Free Software Foundation, Inc.
+/* Part of CPP library. (Macro handling.)
+ Copyright (C) 1986, 87, 89, 92-95, 1996, 1998 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -24,11 +24,66 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "config.h"
#include "system.h"
-#include "gansidecl.h"
#include "cpplib.h"
#include "cpphash.h"
+#undef abort
+
+static int comp_def_part PARAMS ((int, U_CHAR *, int, U_CHAR *,
+ int, int));
+static int change_newlines PARAMS ((U_CHAR *, int));
+static void push_macro_expansion PARAMS ((cpp_reader *,
+ U_CHAR *, int, HASHNODE *));
+static int unsafe_chars PARAMS ((int, int));
+
+#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
+#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
+#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
+
+extern char *version_string;
+
+/* The arglist structure is built by create_definition to tell
+ collect_expansion where the argument names begin. That
+ is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
+ would contain pointers to the strings x, y, and z.
+ collect_expansion would then build a DEFINITION node,
+ with reflist nodes pointing to the places x, y, and z had
+ appeared. So the arglist is just convenience data passed
+ between these two routines. It is not kept around after
+ the current #define has been processed and entered into the
+ hash table. */
+
+struct arglist
+{
+ struct arglist *next;
+ U_CHAR *name;
+ int length;
+ int argno;
+ char rest_args;
+};
+
+/* This structure represents one parsed argument in a macro call.
+ `raw' points to the argument text as written (`raw_length' is its length).
+ `expanded' points to the argument's macro-expansion
+ (its length is `expand_length').
+ `stringified_length' is the length the argument would have
+ if stringified.
+ `use_count' is the number of times this macro arg is substituted
+ into the macro. If the actual use count exceeds 10,
+ the value stored is 10. */
+
+/* raw and expanded are relative to ARG_BASE */
+#define ARG_BASE ((pfile)->token_buffer)
+
+struct argdata
+{
+ /* Strings relative to pfile->token_buffer */
+ long raw, expanded, stringified;
+ int raw_length, expand_length;
+ int stringified_length;
+ char newlines;
+ char use_count;
+};
-extern char *xmalloc PARAMS ((unsigned));
/* Return hash function on name. must be compatible with the one
computed a step at a time, elsewhere */
@@ -48,7 +103,7 @@ hashf (name, len, hashsize)
}
/* Find the most recent hash node for name "name" (ending with first
- non-identifier char) installed by install
+ non-identifier char) installed by cpp_install
If LEN is >= 0, it is the length of the name.
Otherwise, compute the length by scanning the entire name.
@@ -68,19 +123,20 @@ cpp_lookup (pfile, name, len, hash)
if (len < 0)
{
- for (bp = name; is_idchar[*bp]; bp++) ;
+ for (bp = name; is_idchar[*bp]; bp++);
len = bp - name;
}
if (hash < 0)
hash = hashf (name, len, HASHSIZE);
- bucket = hashtab[hash];
- while (bucket) {
- if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
- return bucket;
- bucket = bucket->next;
- }
+ bucket = pfile->hashtab[hash];
+ while (bucket)
+ {
+ if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
+ return bucket;
+ bucket = bucket->next;
+ }
return (HASHNODE *) 0;
}
@@ -132,9 +188,9 @@ delete_macro (hp)
}
/* Install a name in the main hash table, even if it is already there.
- name stops with first non alphanumeric, except leading '#'.
- caller must check against redefinition if that is desired.
- delete_macro () removes things installed by install () in fifo order.
+ Name stops with first non alphanumeric, except leading '#'.
+ Caller must check against redefinition if that is desired.
+ delete_macro () removes things installed by cpp_install () in fifo order.
this is important because of the `defined' special symbol used
in #if, and also if pushdef/popdef directives are ever implemented.
@@ -145,24 +201,25 @@ delete_macro (hp)
Otherwise, compute the hash code. */
HASHNODE *
-install (name, len, type, ivalue, value, hash)
+cpp_install (pfile, name, len, type, value, hash)
+ cpp_reader *pfile;
U_CHAR *name;
int len;
enum node_type type;
- int ivalue;
- char *value;
+ const char *value;
int hash;
{
register HASHNODE *hp;
register int i, bucket;
- register U_CHAR *p, *q;
+ register U_CHAR *p;
- if (len < 0) {
- p = name;
- while (is_idchar[*p])
- p++;
- len = p - name;
- }
+ if (len < 0)
+ {
+ p = name;
+ while (is_idchar[*p])
+ p++;
+ len = p - name;
+ }
if (hash < 0)
hash = hashf (name, len, HASHSIZE);
@@ -170,35 +227,1509 @@ install (name, len, type, ivalue, value, hash)
i = sizeof (HASHNODE) + len + 1;
hp = (HASHNODE *) xmalloc (i);
bucket = hash;
- hp->bucket_hdr = &hashtab[bucket];
- hp->next = hashtab[bucket];
- hashtab[bucket] = hp;
+ hp->bucket_hdr = &pfile->hashtab[bucket];
+ hp->next = pfile->hashtab[bucket];
+ pfile->hashtab[bucket] = hp;
hp->prev = NULL;
if (hp->next != NULL)
hp->next->prev = hp;
hp->type = type;
hp->length = len;
- if (hp->type == T_CONST)
- hp->value.ival = ivalue;
- else
- hp->value.cpval = value;
+ hp->value.cpval = value;
hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
- p = hp->name;
- q = name;
- for (i = 0; i < len; i++)
- *p++ = *q++;
+ bcopy (name, hp->name, len);
hp->name[len] = 0;
return hp;
}
-void
-cpp_hash_cleanup (pfile)
+static int
+macro_cleanup (pbuf, pfile)
+ cpp_buffer *pbuf;
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
+ HASHNODE *macro = (HASHNODE *) pbuf->data;
+ if (macro->type == T_DISABLED)
+ macro->type = T_MACRO;
+ if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
+ free (pbuf->buf);
+ return 0;
+}
+
+
+/* Read a replacement list for a macro with parameters.
+ Build the DEFINITION structure.
+ Reads characters of text starting at BUF until END.
+ ARGLIST specifies the formal parameters to look for
+ in the text of the definition; NARGS is the number of args
+ in that list, or -1 for a macro name that wants no argument list.
+ MACRONAME is the macro name itself (so we can avoid recursive expansion)
+ and NAMELEN is its length in characters.
+
+ Note that comments, backslash-newlines, and leading white space
+ have already been deleted from the argument. */
+
+static DEFINITION *
+collect_expansion (pfile, buf, limit, nargs, arglist)
+ cpp_reader *pfile;
+ U_CHAR *buf, *limit;
+ int nargs;
+ struct arglist *arglist;
+{
+ DEFINITION *defn;
+ register U_CHAR *p, *lastp, *exp_p;
+ struct reflist *endpat = NULL;
+ /* Pointer to first nonspace after last ## seen. */
+ U_CHAR *concat = 0;
+ /* Pointer to first nonspace after last single-# seen. */
+ U_CHAR *stringify = 0;
+ int maxsize;
+ int expected_delimiter = '\0';
+
+ /* Scan thru the replacement list, ignoring comments and quoted
+ strings, picking up on the macro calls. It does a linear search
+ thru the arg list on every potential symbol. Profiling might say
+ that something smarter should happen. */
+
+ if (limit < buf)
+ {
+ cpp_fatal (pfile, "internal error: limit < buf in collect_expansion");
+ limit = buf; /* treat it like a null defn */
+ }
+
+ /* Find the beginning of the trailing whitespace. */
+ p = buf;
+ while (p < limit && is_space[limit[-1]])
+ limit--;
+
+ /* Allocate space for the text in the macro definition.
+ Leading and trailing whitespace chars need 2 bytes each.
+ Each other input char may or may not need 1 byte,
+ so this is an upper bound. The extra 5 are for invented
+ leading and trailing newline-marker and final null. */
+ maxsize = (sizeof (DEFINITION)
+ + (limit - p) + 5);
+ defn = (DEFINITION *) xcalloc (1, maxsize);
+
+ defn->nargs = nargs;
+ exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
+ lastp = exp_p;
+
+ p = buf;
+
+ /* Add one initial space escape-marker to prevent accidental
+ token-pasting (often removed by macroexpand). */
+ *exp_p++ = '\r';
+ *exp_p++ = ' ';
+
+ if (limit - p >= 2 && p[0] == '#' && p[1] == '#')
+ {
+ cpp_error (pfile, "`##' at start of macro definition");
+ p += 2;
+ }
+
+ /* Process the main body of the definition. */
+ while (p < limit)
+ {
+ int skipped_arg = 0;
+ register U_CHAR c = *p++;
+
+ *exp_p++ = c;
+
+ if (!CPP_TRADITIONAL (pfile))
+ {
+ switch (c)
+ {
+ case '\'':
+ case '\"':
+ if (expected_delimiter != '\0')
+ {
+ if (c == expected_delimiter)
+ expected_delimiter = '\0';
+ }
+ else
+ expected_delimiter = c;
+ break;
+
+ case '\\':
+ if (p < limit && expected_delimiter)
+ {
+ /* In a string, backslash goes through
+ and makes next char ordinary. */
+ *exp_p++ = *p++;
+ }
+ break;
+
+ case '#':
+ /* # is ordinary inside a string. */
+ if (expected_delimiter)
+ break;
+ if (p < limit && *p == '#')
+ {
+ /* ##: concatenate preceding and following tokens. */
+ /* Take out the first #, discard preceding whitespace. */
+ exp_p--;
+ while (exp_p > lastp && is_hor_space[exp_p[-1]])
+ --exp_p;
+ /* Skip the second #. */
+ p++;
+ /* Discard following whitespace. */
+ SKIP_WHITE_SPACE (p);
+ concat = p;
+ if (p == limit)
+ cpp_error (pfile, "`##' at end of macro definition");
+ }
+ else if (nargs >= 0)
+ {
+ /* Single #: stringify following argument ref.
+ Don't leave the # in the expansion. */
+ exp_p--;
+ SKIP_WHITE_SPACE (p);
+ if (p == limit || !is_idstart[*p]
+ || (*p == 'L' && p + 1 < limit && (p[1] == '\'' ||
+ p[1] == '"')))
+ cpp_error (pfile,
+ "`#' operator is not followed by a macro argument name");
+ else
+ stringify = p;
+ }
+ break;
+ }
+ }
+ else
+ {
+ /* In -traditional mode, recognize arguments inside strings and
+ character constants, and ignore special properties of #.
+ Arguments inside strings are considered "stringified", but no
+ extra quote marks are supplied. */
+ switch (c)
+ {
+ case '\'':
+ case '\"':
+ if (expected_delimiter != '\0')
+ {
+ if (c == expected_delimiter)
+ expected_delimiter = '\0';
+ }
+ else
+ expected_delimiter = c;
+ break;
+
+ case '\\':
+ /* Backslash quotes delimiters and itself,
+ but not macro args. */
+ if (expected_delimiter != 0 && p < limit
+ && (*p == expected_delimiter || *p == '\\'))
+ {
+ *exp_p++ = *p++;
+ continue;
+ }
+ break;
+
+ case '/':
+ if (expected_delimiter != '\0')
+ /* No comments inside strings. */
+ break;
+ if (*p == '*')
+ {
+ /* If we find a comment that wasn't removed by
+ handle_directive, this must be -traditional.
+ So replace the comment with nothing at all. */
+ exp_p--;
+ p += 1;
+ while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
+ p++;
+#if 0
+ /* Mark this as a concatenation-point,
+ as if it had been ##. */
+ concat = p;
+#endif
+ }
+ break;
+ }
+ }
+
+ /* Handle the start of a symbol. */
+ if (is_idchar[c] && nargs > 0)
+ {
+ U_CHAR *id_beg = p - 1;
+ int id_len;
+
+ --exp_p;
+ while (p != limit && is_idchar[*p])
+ p++;
+ id_len = p - id_beg;
+
+ if (is_idstart[c]
+ && !(id_len == 1 && c == 'L' && (*p == '\'' || *p == '"')))
+ {
+ register struct arglist *arg;
+
+ for (arg = arglist; arg != NULL; arg = arg->next)
+ {
+ struct reflist *tpat;
+
+ if (arg->name[0] == c
+ && arg->length == id_len
+ && strncmp (arg->name, id_beg, id_len) == 0)
+ {
+ if (expected_delimiter && CPP_OPTIONS
+ (pfile)->warn_stringify)
+ {
+ if (CPP_TRADITIONAL (pfile))
+ {
+ cpp_warning (pfile,
+ "macro argument `%.*s' is stringified.",
+ id_len, arg->name);
+ }
+ else
+ {
+ cpp_warning (pfile,
+ "macro arg `%.*s' would be stringified with -traditional.",
+ id_len, arg->name);
+ }
+ }
+ /* If ANSI, don't actually substitute
+ inside a string. */
+ if (!CPP_TRADITIONAL (pfile) && expected_delimiter)
+ break;
+ /* make a pat node for this arg and append it
+ to the end of the pat list */
+ tpat = (struct reflist *)
+ xmalloc (sizeof (struct reflist));
+ tpat->next = NULL;
+ tpat->raw_before = concat == id_beg;
+ tpat->raw_after = 0;
+ tpat->rest_args = arg->rest_args;
+ tpat->stringify = (CPP_TRADITIONAL (pfile)
+ ? expected_delimiter != '\0'
+ : stringify == id_beg);
+
+ if (endpat == NULL)
+ defn->pattern = tpat;
+ else
+ endpat->next = tpat;
+ endpat = tpat;
+
+ tpat->argno = arg->argno;
+ tpat->nchars = exp_p - lastp;
+ {
+ register U_CHAR *p1 = p;
+ SKIP_WHITE_SPACE (p1);
+ if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
+ tpat->raw_after = 1;
+ }
+ lastp = exp_p;
+ skipped_arg = 1;
+ break;
+ }
+ }
+ }
+
+ /* If this was not a macro arg, copy it into the expansion. */
+ if (!skipped_arg)
+ {
+ register U_CHAR *lim1 = p;
+ p = id_beg;
+ while (p != lim1)
+ *exp_p++ = *p++;
+ if (stringify == id_beg)
+ cpp_error (pfile,
+ "`#' operator should be followed by a macro argument name");
+ }
+ }
+ }
+
+ if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)
+ {
+ /* If ANSI, put in a "\r " marker to prevent token pasting.
+ But not if "inside a string" (which in ANSI mode
+ happens only for -D option). */
+ *exp_p++ = '\r';
+ *exp_p++ = ' ';
+ }
+
+ *exp_p = '\0';
+
+ defn->length = exp_p - defn->expansion;
+
+ /* Crash now if we overrun the allocated size. */
+ if (defn->length + 1 > maxsize)
+ abort ();
+
+#if 0
+/* This isn't worth the time it takes. */
+ /* give back excess storage */
+ defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
+#endif
+
+ return defn;
+}
+
+/*
+ * special extension string that can be added to the last macro argument to
+ * allow it to absorb the "rest" of the arguments when expanded. Ex:
+ * #define wow(a, b...) process (b, a, b)
+ * { wow (1, 2, 3); } -> { process (2, 3, 1, 2, 3); }
+ * { wow (one, two); } -> { process (two, one, two); }
+ * if this "rest_arg" is used with the concat token '##' and if it is not
+ * supplied then the token attached to with ## will not be outputted. Ex:
+ * #define wow (a, b...) process (b ## , a, ## b)
+ * { wow (1, 2); } -> { process (2, 1, 2); }
+ * { wow (one); } -> { process (one); {
+ */
+static char rest_extension[] = "...";
+#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
+
+/* Create a DEFINITION node from a #define directive. Arguments are
+ as for do_define. */
+
+MACRODEF
+create_definition (buf, limit, pfile, predefinition)
+ U_CHAR *buf, *limit;
+ cpp_reader *pfile;
+ int predefinition;
+{
+ U_CHAR *bp; /* temp ptr into input buffer */
+ U_CHAR *symname; /* remember where symbol name starts */
+ int sym_length; /* and how long it is */
+ int rest_args = 0;
+ long line, col;
+ char *file = CPP_BUFFER (pfile) ? CPP_BUFFER (pfile)->nominal_fname : "";
+ DEFINITION *defn;
+ int arglengths = 0; /* Accumulate lengths of arg names
+ plus number of args. */
+ MACRODEF mdef;
+ cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
+
+ bp = buf;
+
+ while (is_hor_space[*bp])
+ bp++;
+
+ symname = bp; /* remember where it starts */
+
+ sym_length = check_macro_name (pfile, bp, 0);
+ bp += sym_length;
+
+ /* Lossage will occur if identifiers or control keywords are broken
+ across lines using backslash. This is not the right place to take
+ care of that. */
+
+ if (*bp == '(')
+ {
+ struct arglist *arg_ptrs = NULL;
+ int argno = 0;
+
+ bp++; /* skip '(' */
+ SKIP_WHITE_SPACE (bp);
+
+ /* Loop over macro argument names. */
+ while (*bp != ')')
+ {
+ struct arglist *temp;
+
+ temp = (struct arglist *) alloca (sizeof (struct arglist));
+ temp->name = bp;
+ temp->next = arg_ptrs;
+ temp->argno = argno++;
+ temp->rest_args = 0;
+ arg_ptrs = temp;
+
+ if (rest_args)
+ cpp_pedwarn (pfile, "another parameter follows `%s'",
+ rest_extension);
+
+ if (!is_idstart[*bp])
+ cpp_pedwarn (pfile, "invalid character in macro parameter name");
+
+ /* Find the end of the arg name. */
+ while (is_idchar[*bp])
+ {
+ bp++;
+ /* do we have a "special" rest-args extension here? */
+ if ((size_t) (limit - bp) > REST_EXTENSION_LENGTH
+ && !strncmp (rest_extension, bp, REST_EXTENSION_LENGTH))
+ {
+ rest_args = 1;
+ temp->rest_args = 1;
+ break;
+ }
+ }
+ temp->length = bp - temp->name;
+ if (rest_args == 1)
+ bp += REST_EXTENSION_LENGTH;
+ arglengths += temp->length + 2;
+ SKIP_WHITE_SPACE (bp);
+ if (temp->length == 0 || (*bp != ',' && *bp != ')'))
+ {
+ cpp_error (pfile,
+ "badly punctuated parameter list in `#define'");
+ goto nope;
+ }
+ if (*bp == ',')
+ {
+ bp++;
+ SKIP_WHITE_SPACE (bp);
+ }
+ if (bp >= limit)
+ {
+ cpp_error (pfile, "unterminated parameter list in `#define'");
+ goto nope;
+ }
+ {
+ struct arglist *otemp;
+
+ for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
+ if (temp->length == otemp->length
+ && strncmp (temp->name, otemp->name, temp->length) == 0)
+ {
+ U_CHAR *name;
+
+ name = (U_CHAR *) alloca (temp->length + 1);
+ (void) strncpy (name, temp->name, temp->length);
+ name[temp->length] = '\0';
+ cpp_error (pfile,
+ "duplicate argument name `%s' in `#define'",
+ name);
+ goto nope;
+ }
+ }
+ }
+
+ ++bp; /* skip paren */
+ SKIP_WHITE_SPACE (bp);
+ /* now everything from bp before limit is the definition. */
+ defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
+ defn->rest_args = rest_args;
+
+ /* Now set defn->args.argnames to the result of concatenating
+ the argument names in reverse order
+ with comma-space between them. */
+ defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);
+ {
+ struct arglist *temp;
+ int i = 0;
+ for (temp = arg_ptrs; temp; temp = temp->next)
+ {
+ bcopy (temp->name, &defn->args.argnames[i], temp->length);
+ i += temp->length;
+ if (temp->next != 0)
+ {
+ defn->args.argnames[i++] = ',';
+ defn->args.argnames[i++] = ' ';
+ }
+ }
+ defn->args.argnames[i] = 0;
+ }
+ }
+ else
+ {
+ /* Simple expansion or empty definition. */
+
+ if (bp < limit)
+ {
+ if (is_hor_space[*bp])
+ {
+ bp++;
+ SKIP_WHITE_SPACE (bp);
+ }
+ else
+ /* Per C9x, missing white space after the name in a #define
+ of an object-like macro is always a constraint violation. */
+ cpp_pedwarn (pfile,
+ "missing white space after `#define %.*s'",
+ sym_length, symname);
+ }
+ /* now everything from bp before limit is the definition. */
+ defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
+ defn->args.argnames = (U_CHAR *) "";
+ }
+
+ defn->line = line;
+ defn->file = file;
+
+ /* OP is null if this is a predefinition */
+ defn->predefined = predefinition;
+ mdef.defn = defn;
+ mdef.symnam = symname;
+ mdef.symlen = sym_length;
+
+ return mdef;
+
+nope:
+ mdef.defn = 0;
+ return mdef;
+}
+
+/*
+ * Parse a macro argument and append the info on PFILE's token_buffer.
+ * REST_ARGS means to absorb the rest of the args.
+ * Return nonzero to indicate a syntax error.
+ */
+
+static enum cpp_token
+macarg (pfile, rest_args)
+ cpp_reader *pfile;
+ int rest_args;
+{
+ int paren = 0;
+ enum cpp_token token;
+ char save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
+ CPP_OPTIONS (pfile)->put_out_comments = 0;
+
+ /* Try to parse as much of the argument as exists at this
+ input stack level. */
+ pfile->no_macro_expand++;
+ CPP_OPTIONS (pfile)->no_line_commands++;
+ for (;;)
+ {
+ token = cpp_get_token (pfile);
+ switch (token)
+ {
+ case CPP_EOF:
+ goto done;
+ case CPP_POP:
+ /* If we've hit end of file, it's an error (reported by caller).
+ Ditto if it's the end of cpp_expand_to_buffer text.
+ If we've hit end of macro, just continue. */
+ if (!CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
+ goto done;
+ break;
+ case CPP_LPAREN:
+ paren++;
+ break;
+ case CPP_RPAREN:
+ if (--paren < 0)
+ goto found;
+ break;
+ case CPP_COMMA:
+ /* if we've returned to lowest level and
+ we aren't absorbing all args */
+ if (paren == 0 && rest_args == 0)
+ goto found;
+ break;
+ found:
+ /* Remove ',' or ')' from argument buffer. */
+ CPP_ADJUST_WRITTEN (pfile, -1);
+ goto done;
+ default:;
+ }
+ }
+
+done:
+ CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
+ CPP_OPTIONS (pfile)->no_line_commands--;
+ pfile->no_macro_expand--;
+
+ return token;
+}
+
+/* Turn newlines to spaces in the string of length LENGTH at START,
+ except inside of string constants.
+ The string is copied into itself with its beginning staying fixed. */
+
+static int
+change_newlines (start, length)
+ U_CHAR *start;
+ int length;
+{
+ register U_CHAR *ibp;
+ register U_CHAR *obp;
+ register U_CHAR *limit;
+ register int c;
+
+ ibp = start;
+ limit = start + length;
+ obp = start;
+
+ while (ibp < limit)
+ {
+ *obp++ = c = *ibp++;
+ switch (c)
+ {
+
+ case '\'':
+ case '\"':
+ /* Notice and skip strings, so that we don't
+ delete newlines in them. */
+ {
+ int quotec = c;
+ while (ibp < limit)
+ {
+ *obp++ = c = *ibp++;
+ if (c == quotec)
+ break;
+ if (c == '\n' && quotec == '\'')
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return obp - start;
+}
+
+
+static struct tm *
+timestamp (pfile)
+ cpp_reader *pfile;
+{
+ if (!pfile->timebuf)
+ {
+ time_t t = time ((time_t *) 0);
+ pfile->timebuf = localtime (&t);
+ }
+ return pfile->timebuf;
+}
+
+static char *monthnames[] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+};
+
+/*
+ * expand things like __FILE__. Place the expansion into the output
+ * buffer *without* rescanning.
+ */
+
+static void
+special_symbol (hp, pfile)
+ HASHNODE *hp;
+ cpp_reader *pfile;
+{
+ const char *buf;
+ int len;
+ cpp_buffer *ip;
+
+ switch (hp->type)
+ {
+ case T_FILE:
+ case T_BASE_FILE:
+ {
+ ip = CPP_BUFFER (pfile);
+ if (hp->type == T_BASE_FILE)
+ {
+ while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
+ ip = CPP_PREV_BUFFER (ip);
+ }
+ else
+ {
+ ip = CPP_BUFFER (pfile);
+ while (!ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
+ ip = CPP_PREV_BUFFER (ip);
+ }
+
+ buf = ip->nominal_fname;
+
+ if (!buf)
+ buf = "";
+ CPP_RESERVE (pfile, 3 + 4 * strlen (buf));
+ quote_string (pfile, buf);
+ return;
+ }
+
+ case T_INCLUDE_LEVEL:
+ {
+ int true_indepth = 0;
+ ip = CPP_BUFFER (pfile);
+ for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
+ if (ip->fname != NULL)
+ true_indepth++;
+
+ CPP_RESERVE (pfile, 10);
+ sprintf (CPP_PWRITTEN (pfile), "%d", true_indepth);
+ CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
+ return;
+ }
+
+ case T_VERSION:
+ len = strlen (version_string);
+ CPP_RESERVE (pfile, 3 + len);
+ CPP_PUTC_Q (pfile, '"');
+ CPP_PUTS_Q (pfile, version_string, len);
+ CPP_PUTC_Q (pfile, '"');
+ CPP_NUL_TERMINATE_Q (pfile);
+ return;
+
+ case T_CONST:
+ buf = hp->value.cpval;
+ if (!buf)
+ return;
+ if (*buf == '\0')
+ buf = "\r ";
+
+ len = strlen (buf);
+ CPP_RESERVE (pfile, len + 1);
+ CPP_PUTS_Q (pfile, buf, len);
+ CPP_NUL_TERMINATE_Q (pfile);
+ return;
+
+ case T_STDC:
+ CPP_RESERVE (pfile, 2);
+#ifdef STDC_0_IN_SYSTEM_HEADERS
+ ip = CPP_BUFFER (pfile);
+ while (!ip->nominal_fname && ip != CPP_NULL_BUFFER (pfile))
+ ip = CPP_PREV_BUFFER (ip);
+ if (ip->system_header_p
+ && !cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", 15, -1))
+ CPP_PUTC_Q (pfile, '0');
+ else
+#endif
+ CPP_PUTC_Q (pfile, '1');
+ CPP_NUL_TERMINATE_Q (pfile);
+ return;
+
+ case T_SPECLINE:
+ {
+ long line;
+ cpp_buf_line_and_col (cpp_file_buffer (pfile), &line, NULL);
+
+ CPP_RESERVE (pfile, 10);
+ sprintf (CPP_PWRITTEN (pfile), "%ld", line);
+ CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
+ return;
+ }
+
+ case T_DATE:
+ case T_TIME:
+ {
+ struct tm *timebuf;
+
+ CPP_RESERVE (pfile, 20);
+ timebuf = timestamp (pfile);
+ if (hp->type == T_DATE)
+ sprintf (CPP_PWRITTEN (pfile), "\"%s %2d %4d\"",
+ monthnames[timebuf->tm_mon],
+ timebuf->tm_mday, timebuf->tm_year + 1900);
+ else
+ sprintf (CPP_PWRITTEN (pfile), "\"%02d:%02d:%02d\"",
+ timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
+
+ CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
+ return;
+ }
+
+ default:
+ cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
+ return;
+ }
+}
+
+/* Expand a macro call.
+ HP points to the symbol that is the macro being called.
+ Put the result of expansion onto the input stack
+ so that subsequent input by our caller will use it.
+
+ If macro wants arguments, caller has already verified that
+ an argument list follows; arguments come from the input stack. */
+
+void
+macroexpand (pfile, hp)
+ cpp_reader *pfile;
+ HASHNODE *hp;
+{
+ int nargs;
+ DEFINITION *defn;
+ register U_CHAR *xbuf;
+ long start_line, start_column;
+ int xbuf_len;
+ struct argdata *args;
+ long old_written = CPP_WRITTEN (pfile);
+#if 0
+ int start_line = instack[indepth].lineno;
+#endif
+ int rest_args, rest_zero;
register int i;
- for (i = HASHSIZE; --i >= 0; )
+
+#if 0
+ /* This macro is being used inside a #if, which means it must be */
+ /* recorded as a precondition. */
+ if (pcp_inside_if && pcp_outfile && defn->predefined)
+ dump_single_macro (hp, pcp_outfile);
+#endif
+
+ cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
+
+ /* Check for and handle special symbols. */
+ if (hp->type != T_MACRO)
+ {
+ special_symbol (hp, pfile);
+ xbuf_len = CPP_WRITTEN (pfile) - old_written;
+ xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
+ CPP_SET_WRITTEN (pfile, old_written);
+ bcopy (CPP_PWRITTEN (pfile), xbuf, xbuf_len + 1);
+ push_macro_expansion (pfile, xbuf, xbuf_len, hp);
+ CPP_BUFFER (pfile)->has_escapes = 1;
+ return;
+ }
+
+ defn = hp->value.defn;
+ nargs = defn->nargs;
+ pfile->output_escapes++;
+
+ if (nargs >= 0)
+ {
+ enum cpp_token token = CPP_EOF;
+
+ args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
+
+ for (i = 0; i < nargs; i++)
+ {
+ args[i].raw = args[i].expanded = 0;
+ args[i].raw_length = 0;
+ args[i].expand_length = args[i].stringified_length = -1;
+ args[i].use_count = 0;
+ }
+
+ /* Parse all the macro args that are supplied. I counts them.
+ The first NARGS args are stored in ARGS.
+ The rest are discarded. If rest_args is set then we assume
+ macarg absorbed the rest of the args. */
+ i = 0;
+ rest_args = 0;
+ rest_args = 0;
+ FORWARD (1); /* Discard open-parenthesis before first arg. */
+ do
+ {
+ if (rest_args)
+ continue;
+ if (i < nargs || (nargs == 0 && i == 0))
+ {
+ /* if we are working on last arg which absorbs rest of args... */
+ if (i == nargs - 1 && defn->rest_args)
+ rest_args = 1;
+ args[i].raw = CPP_WRITTEN (pfile);
+ token = macarg (pfile, rest_args);
+ args[i].raw_length = CPP_WRITTEN (pfile) - args[i].raw;
+ args[i].newlines = 0; /* FIXME */
+ }
+ else
+ token = macarg (pfile, 0);
+ if (token == CPP_EOF || token == CPP_POP)
+ {
+ cpp_error_with_line (pfile, start_line, start_column,
+ "unterminated macro call");
+ return;
+ }
+ i++;
+ }
+ while (token == CPP_COMMA);
+
+ /* If we got one arg but it was just whitespace, call that 0 args. */
+ if (i == 1)
+ {
+ register U_CHAR *bp = ARG_BASE + args[0].raw;
+ register U_CHAR *lim = bp + args[0].raw_length;
+ /* cpp.texi says for foo ( ) we provide one argument.
+ However, if foo wants just 0 arguments, treat this as 0. */
+ if (nargs == 0)
+ while (bp != lim && is_space[*bp])
+ bp++;
+ if (bp == lim)
+ i = 0;
+ }
+
+ /* Don't output an error message if we have already output one for
+ a parse error above. */
+ rest_zero = 0;
+ if (nargs == 0 && i > 0)
+ {
+ cpp_error (pfile, "arguments given to macro `%s'", hp->name);
+ }
+ else if (i < nargs)
+ {
+ /* traditional C allows foo() if foo wants one argument. */
+ if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
+ ;
+ /* the rest args token is allowed to absorb 0 tokens */
+ else if (i == nargs - 1 && defn->rest_args)
+ rest_zero = 1;
+ else if (i == 0)
+ cpp_error (pfile, "macro `%s' used without args", hp->name);
+ else if (i == 1)
+ cpp_error (pfile, "macro `%s' used with just one arg", hp->name);
+ else
+ cpp_error (pfile, "macro `%s' used with only %d args",
+ hp->name, i);
+ }
+ else if (i > nargs)
+ {
+ cpp_error (pfile,
+ "macro `%s' used with too many (%d) args", hp->name, i);
+ }
+ }
+
+ /* If macro wants zero args, we parsed the arglist for checking only.
+ Read directly from the macro definition. */
+ if (nargs <= 0)
+ {
+ xbuf = defn->expansion;
+ xbuf_len = defn->length;
+ }
+ else
+ {
+ register U_CHAR *exp = defn->expansion;
+ register int offset; /* offset in expansion,
+ copied a piece at a time */
+ register int totlen; /* total amount of exp buffer filled so far */
+
+ register struct reflist *ap, *last_ap;
+
+ /* Macro really takes args. Compute the expansion of this call. */
+
+ /* Compute length in characters of the macro's expansion.
+ Also count number of times each arg is used. */
+ xbuf_len = defn->length;
+ for (ap = defn->pattern; ap != NULL; ap = ap->next)
+ {
+ if (ap->stringify)
+ {
+ register struct argdata *arg = &args[ap->argno];
+ /* Stringify if it hasn't already been */
+ if (arg->stringified_length < 0)
+ {
+ int arglen = arg->raw_length;
+ int escaped = 0;
+ int in_string = 0;
+ int c;
+ /* Initially need_space is -1. Otherwise, 1 means the
+ previous character was a space, but we suppressed it;
+ 0 means the previous character was a non-space. */
+ int need_space = -1;
+ i = 0;
+ arg->stringified = CPP_WRITTEN (pfile);
+ if (!CPP_TRADITIONAL (pfile))
+ CPP_PUTC (pfile, '\"'); /* insert beginning quote */
+ for (; i < arglen; i++)
+ {
+ c = (ARG_BASE + arg->raw)[i];
+
+ if (!in_string)
+ {
+ /* Internal sequences of whitespace are
+ replaced by one space except within
+ a string or char token. */
+ if (is_space[c])
+ {
+ if (CPP_WRITTEN (pfile) > (unsigned) arg->stringified
+ && (CPP_PWRITTEN (pfile))[-1] == '\r')
+ {
+ /* "\r " escape markers are removed */
+ CPP_ADJUST_WRITTEN (pfile, -1);
+ continue;
+ }
+ if (need_space == 0)
+ need_space = 1;
+ continue;
+ }
+ else if (need_space > 0)
+ CPP_PUTC (pfile, ' ');
+ need_space = 0;
+ }
+
+ if (escaped)
+ escaped = 0;
+ else
+ {
+ if (c == '\\')
+ escaped = 1;
+ if (in_string)
+ {
+ if (c == in_string)
+ in_string = 0;
+ }
+ else if (c == '\"' || c == '\'')
+ in_string = c;
+ }
+
+ /* Escape these chars */
+ if (c == '\"' || (in_string && c == '\\'))
+ CPP_PUTC (pfile, '\\');
+ if (ISPRINT (c))
+ CPP_PUTC (pfile, c);
+ else
+ {
+ CPP_RESERVE (pfile, 4);
+ sprintf ((char *) CPP_PWRITTEN (pfile), "\\%03o",
+ (unsigned int) c);
+ CPP_ADJUST_WRITTEN (pfile, 4);
+ }
+ }
+ if (!CPP_TRADITIONAL (pfile))
+ CPP_PUTC (pfile, '\"'); /* insert ending quote */
+ arg->stringified_length
+ = CPP_WRITTEN (pfile) - arg->stringified;
+ }
+ xbuf_len += args[ap->argno].stringified_length;
+ }
+ else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
+ /* Add 4 for two newline-space markers to prevent
+ token concatenation. */
+ xbuf_len += args[ap->argno].raw_length + 4;
+ else
+ {
+ /* We have an ordinary (expanded) occurrence of the arg.
+ So compute its expansion, if we have not already. */
+ if (args[ap->argno].expand_length < 0)
+ {
+ args[ap->argno].expanded = CPP_WRITTEN (pfile);
+ cpp_expand_to_buffer (pfile,
+ ARG_BASE + args[ap->argno].raw,
+ args[ap->argno].raw_length);
+
+ args[ap->argno].expand_length
+ = CPP_WRITTEN (pfile) - args[ap->argno].expanded;
+ }
+
+ /* Add 4 for two newline-space markers to prevent
+ token concatenation. */
+ xbuf_len += args[ap->argno].expand_length + 4;
+ }
+ if (args[ap->argno].use_count < 10)
+ args[ap->argno].use_count++;
+ }
+
+ xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
+
+ /* Generate in XBUF the complete expansion
+ with arguments substituted in.
+ TOTLEN is the total size generated so far.
+ OFFSET is the index in the definition
+ of where we are copying from. */
+ offset = totlen = 0;
+ for (last_ap = NULL, ap = defn->pattern; ap != NULL;
+ last_ap = ap, ap = ap->next)
+ {
+ register struct argdata *arg = &args[ap->argno];
+ int count_before = totlen;
+
+ /* Add chars to XBUF. */
+ for (i = 0; i < ap->nchars; i++, offset++)
+ xbuf[totlen++] = exp[offset];
+
+ /* If followed by an empty rest arg with concatenation,
+ delete the last run of nonwhite chars. */
+ if (rest_zero && totlen > count_before
+ && ((ap->rest_args && ap->raw_before)
+ || (last_ap != NULL && last_ap->rest_args
+ && last_ap->raw_after)))
+ {
+ /* Delete final whitespace. */
+ while (totlen > count_before && is_space[xbuf[totlen - 1]])
+ totlen--;
+
+ /* Delete the nonwhites before them. */
+ while (totlen > count_before && !is_space[xbuf[totlen - 1]])
+ totlen--;
+ }
+
+ if (ap->stringify != 0)
+ {
+ bcopy (ARG_BASE + arg->stringified,
+ xbuf + totlen, arg->stringified_length);
+ totlen += arg->stringified_length;
+ }
+ else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
+ {
+ U_CHAR *p1 = ARG_BASE + arg->raw;
+ U_CHAR *l1 = p1 + arg->raw_length;
+ if (ap->raw_before)
+ {
+ while (p1 != l1 && is_space[*p1])
+ p1++;
+ while (p1 != l1 && is_idchar[*p1])
+ xbuf[totlen++] = *p1++;
+ }
+ if (ap->raw_after)
+ {
+ /* Arg is concatenated after: delete trailing whitespace,
+ whitespace markers, and no-reexpansion markers. */
+ while (p1 != l1)
+ {
+ if (is_space[l1[-1]])
+ l1--;
+ else if (l1[-1] == '\r')
+ l1--;
+ else if (l1[-1] == '-')
+ {
+ if (l1 != p1 + 1 && l1[-2] == '\r')
+ l1 -= 2;
+ else
+ break;
+ }
+ else
+ break;
+ }
+ }
+
+ /* Delete any no-reexpansion marker that precedes
+ an identifier at the beginning of the argument. */
+ if (p1[0] == '\r' && p1[1] == '-')
+ p1 += 2;
+
+ bcopy (p1, xbuf + totlen, l1 - p1);
+ totlen += l1 - p1;
+ }
+ else
+ {
+ U_CHAR *expanded = ARG_BASE + arg->expanded;
+ if (!ap->raw_before && totlen > 0 && arg->expand_length
+ && !CPP_TRADITIONAL (pfile)
+ && unsafe_chars (xbuf[totlen - 1], expanded[0]))
+ {
+ xbuf[totlen++] = '\r';
+ xbuf[totlen++] = ' ';
+ }
+
+ bcopy (expanded, xbuf + totlen, arg->expand_length);
+ totlen += arg->expand_length;
+
+ if (!ap->raw_after && totlen > 0 && offset < defn->length
+ && !CPP_TRADITIONAL (pfile)
+ && unsafe_chars (xbuf[totlen - 1], exp[offset]))
+ {
+ xbuf[totlen++] = '\r';
+ xbuf[totlen++] = ' ';
+ }
+
+ /* If a macro argument with newlines is used multiple times,
+ then only expand the newlines once. This avoids creating
+ output lines which don't correspond to any input line,
+ which confuses gdb and gcov. */
+ if (arg->use_count > 1 && arg->newlines > 0)
+ {
+ /* Don't bother doing change_newlines for subsequent
+ uses of arg. */
+ arg->use_count = 1;
+ arg->expand_length
+ = change_newlines (expanded, arg->expand_length);
+ }
+ }
+
+ if (totlen > xbuf_len)
+ {
+ cpp_fatal (pfile, "internal_error: buffer overrun in macroexpand");
+ return;
+ }
+ }
+
+ /* if there is anything left of the definition
+ after handling the arg list, copy that in too. */
+
+ for (i = offset; i < defn->length; i++)
+ {
+ /* if we've reached the end of the macro */
+ if (exp[i] == ')')
+ rest_zero = 0;
+ if (!(rest_zero && last_ap != NULL && last_ap->rest_args
+ && last_ap->raw_after))
+ xbuf[totlen++] = exp[i];
+ }
+
+ xbuf[totlen] = 0;
+ xbuf_len = totlen;
+
+ }
+
+ pfile->output_escapes--;
+
+ /* Now put the expansion on the input stack
+ so our caller will commence reading from it. */
+ push_macro_expansion (pfile, xbuf, xbuf_len, hp);
+ CPP_BUFFER (pfile)->has_escapes = 1;
+
+ /* Pop the space we've used in the token_buffer for argument expansion. */
+ CPP_SET_WRITTEN (pfile, old_written);
+
+ /* Recursive macro use sometimes works traditionally.
+ #define foo(x,y) bar (x (y,0), y)
+ foo (foo, baz) */
+
+ if (!CPP_TRADITIONAL (pfile))
+ hp->type = T_DISABLED;
+}
+
+/* Return 1 iff a token ending in C1 followed directly by a token C2
+ could cause mis-tokenization. */
+
+static int
+unsafe_chars (c1, c2)
+ int c1, c2;
+{
+ switch (c1)
+ {
+ case '+':
+ case '-':
+ if (c2 == c1 || c2 == '=')
+ return 1;
+ goto letter;
+
+ case '.': case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7': case '8':
+ case '9': case 'e': case 'E': case 'p': case 'P':
+ if (c2 == '-' || c2 == '+')
+ return 1; /* could extend a pre-processing number */
+ goto letter;
+
+ case 'L':
+ if (c2 == '\'' || c2 == '\"')
+ return 1; /* Could turn into L"xxx" or L'xxx'. */
+ goto letter;
+
+ case '_': case 'a': case 'b': case 'c': case 'd': case 'f':
+ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+ case 'm': case 'n': case 'o': case 'q': case 'r': case 's':
+ case 't': case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z': case 'A': case 'B': case 'C': case 'D': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'M':
+ case 'N': case 'O': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ letter:
+ /* We're in the middle of either a name or a pre-processing number. */
+ return (is_idchar[c2] || c2 == '.');
+
+ case '<': case '>': case '!': case '%': case '#': case ':':
+ case '^': case '&': case '|': case '*': case '/': case '=':
+ return (c2 == c1 || c2 == '=');
+ }
+ return 0;
+}
+
+static void
+push_macro_expansion (pfile, xbuf, xbuf_len, hp)
+ cpp_reader *pfile;
+ register U_CHAR *xbuf;
+ int xbuf_len;
+ HASHNODE *hp;
+{
+ register cpp_buffer *mbuf = cpp_push_buffer (pfile, xbuf, xbuf_len);
+ if (mbuf == NULL)
+ return;
+ mbuf->cleanup = macro_cleanup;
+ mbuf->data = hp;
+
+ /* The first chars of the expansion should be a "\r " added by
+ collect_expansion. This is to prevent accidental token-pasting
+ between the text preceding the macro invocation, and the macro
+ expansion text.
+
+ We would like to avoid adding unneeded spaces (for the sake of
+ tools that use cpp, such as imake). In some common cases we can
+ tell that it is safe to omit the space.
+
+ The character before the macro invocation cannot have been an
+ idchar (or else it would have been pasted with the idchars of
+ the macro name). Therefore, if the first non-space character
+ of the expansion is an idchar, we do not need the extra space
+ to prevent token pasting.
+
+ Also, we don't need the extra space if the first char is '(',
+ or some other (less common) characters. */
+
+ if (xbuf[0] == '\r' && xbuf[1] == ' '
+ && (is_idchar[xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
+ || xbuf[2] == '\"'))
+ mbuf->cur += 2;
+
+ /* Likewise, avoid the extra space at the end of the macro expansion
+ if this is safe. We can do a better job here since we can know
+ what the next char will be. */
+ if (xbuf_len >= 3
+ && mbuf->rlimit[-2] == '\r'
+ && mbuf->rlimit[-1] == ' ')
+ {
+ int c1 = mbuf->rlimit[-3];
+ int c2 = CPP_BUF_PEEK (CPP_PREV_BUFFER (CPP_BUFFER (pfile)));
+ if (c2 == EOF || !unsafe_chars (c1, c2))
+ mbuf->rlimit -= 2;
+ }
+}
+
+/* Return zero if two DEFINITIONs are isomorphic. */
+
+int
+compare_defs (pfile, d1, d2)
+ cpp_reader *pfile;
+ DEFINITION *d1, *d2;
+{
+ register struct reflist *a1, *a2;
+ register U_CHAR *p1 = d1->expansion;
+ register U_CHAR *p2 = d2->expansion;
+ int first = 1;
+
+ if (d1->nargs != d2->nargs)
+ return 1;
+ if (CPP_PEDANTIC (pfile)
+ && strcmp ((char *) d1->args.argnames, (char *) d2->args.argnames))
+ return 1;
+ for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
+ a1 = a1->next, a2 = a2->next)
+ {
+ if (!((a1->nchars == a2->nchars && !strncmp (p1, p2, a1->nchars))
+ || !comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
+ || a1->argno != a2->argno
+ || a1->stringify != a2->stringify
+ || a1->raw_before != a2->raw_before
+ || a1->raw_after != a2->raw_after)
+ return 1;
+ first = 0;
+ p1 += a1->nchars;
+ p2 += a2->nchars;
+ }
+ if (a1 != a2)
+ return 1;
+
+ return comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
+ p2, d2->length - (p2 - d2->expansion), 1);
+}
+
+/* Return 1 if two parts of two macro definitions are effectively different.
+ One of the parts starts at BEG1 and has LEN1 chars;
+ the other has LEN2 chars at BEG2.
+ Any sequence of whitespace matches any other sequence of whitespace.
+ FIRST means these parts are the first of a macro definition;
+ so ignore leading whitespace entirely.
+ LAST means these parts are the last of a macro definition;
+ so ignore trailing whitespace entirely. */
+
+static int
+comp_def_part (first, beg1, len1, beg2, len2, last)
+ int first;
+ U_CHAR *beg1, *beg2;
+ int len1, len2;
+ int last;
+{
+ register U_CHAR *end1 = beg1 + len1;
+ register U_CHAR *end2 = beg2 + len2;
+ if (first)
+ {
+ while (beg1 != end1 && is_space[*beg1])
+ beg1++;
+ while (beg2 != end2 && is_space[*beg2])
+ beg2++;
+ }
+ if (last)
+ {
+ while (beg1 != end1 && is_space[end1[-1]])
+ end1--;
+ while (beg2 != end2 && is_space[end2[-1]])
+ end2--;
+ }
+ while (beg1 != end1 && beg2 != end2)
{
- while (hashtab[i])
- delete_macro (hashtab[i]);
+ if (is_space[*beg1] && is_space[*beg2])
+ {
+ while (beg1 != end1 && is_space[*beg1])
+ beg1++;
+ while (beg2 != end2 && is_space[*beg2])
+ beg2++;
+ }
+ else if (*beg1 == *beg2)
+ {
+ beg1++;
+ beg2++;
+ }
+ else
+ break;
+ }
+ return (beg1 != end1) || (beg2 != end2);
+}
+
+/* Dump the definition of macro MACRO on stdout. The format is suitable
+ to be read back in again. */
+
+void
+dump_definition (pfile, macro)
+ cpp_reader *pfile;
+ MACRODEF macro;
+{
+ DEFINITION *defn = macro.defn;
+
+ CPP_RESERVE (pfile, macro.symlen + sizeof "#define ");
+ CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1);
+ CPP_PUTS_Q (pfile, macro.symnam, macro.symlen);
+
+ if (defn->nargs == -1)
+ {
+ CPP_PUTC_Q (pfile, ' ');
+
+ /* The first and last two characters of a macro expansion are
+ always "\r "; this needs to be trimmed out.
+ So we need length-4 chars of space, plus one for the NUL. */
+ CPP_RESERVE (pfile, defn->length - 4 + 1);
+ CPP_PUTS_Q (pfile, defn->expansion + 2, defn->length - 4);
+ CPP_NUL_TERMINATE_Q (pfile);
+ }
+ else
+ {
+ struct reflist *r;
+ unsigned char *argnames = xstrdup (defn->args.argnames);
+ unsigned char **argv = alloca (defn->nargs * sizeof(char *));
+ int *argl = alloca (defn->nargs * sizeof(int));
+ unsigned char *x;
+ int i;
+
+ /* First extract the argument list. */
+ x = argnames;
+ i = defn->nargs;
+ while (i--)
+ {
+ argv[i] = x;
+ while (*x != ',' && *x != '\0') x++;
+ argl[i] = x - argv[i];
+ if (*x == ',')
+ {
+ *x = '\0';
+ x += 2; /* skip the space after the comma */
+ }
+ }
+
+ /* Now print out the argument list. */
+ CPP_PUTC_Q (pfile, '(');
+ for (i = 0; i < defn->nargs; i++)
+ {
+ CPP_RESERVE (pfile, argl[i] + 2);
+ CPP_PUTS_Q (pfile, argv[i], argl[i]);
+ if (i < defn->nargs-1)
+ CPP_PUTS_Q (pfile, ", ", 2);
+ }
+
+ if (defn->rest_args)
+ CPP_PUTS (pfile, "...) ", 5);
+ else
+ CPP_PUTS (pfile, ") ", 2);
+
+ /* Now the definition. */
+ x = defn->expansion;
+ for (r = defn->pattern; r; r = r->next)
+ {
+ i = r->nchars;
+ if (*x == '\r') x += 2, i -= 2;
+ /* i chars for macro text, plus the length of the macro
+ argument name, plus one for a stringify marker, plus two for
+ each concatenation marker. */
+ CPP_RESERVE (pfile,
+ i + argl[r->argno] + r->stringify
+ + (r->raw_before + r->raw_after) * 2);
+
+ if (i > 0) CPP_PUTS_Q (pfile, x, i);
+ if (r->raw_before)
+ CPP_PUTS_Q (pfile, "##", 2);
+ if (r->stringify)
+ CPP_PUTC_Q (pfile, '#');
+ CPP_PUTS_Q (pfile, argv[r->argno], argl[r->argno]);
+ if (r->raw_after && !(r->next && r->next->nchars == 0
+ && r->next->raw_before))
+ CPP_PUTS_Q (pfile, "##", 2);
+
+ x += i;
+ }
+
+ i = defn->length - (x - defn->expansion) - 2;
+ if (*x == '\r') x += 2, i -= 2;
+ if (i > 0) CPP_PUTS (pfile, x, i);
+ CPP_NUL_TERMINATE (pfile);
}
}
diff --git a/contrib/gcc/cpphash.h b/contrib/gcc/cpphash.h
index 2b0668d..bb306d9 100644
--- a/contrib/gcc/cpphash.h
+++ b/contrib/gcc/cpphash.h
@@ -1,12 +1,27 @@
+/* Part of CPP library. (Macro hash table support.)
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
/* different kinds of things that can appear in the value field
- of a hash node. Actually, this may be useless now. */
-union hashval {
- int ival;
- char *cpval;
- DEFINITION *defn;
-#if 0
- KEYDEF *keydef;
-#endif
+ of a hash node. */
+union hashval
+{
+ const char *cpval; /* some predefined macros */
+ DEFINITION *defn; /* #define */
+ struct hashnode *aschain; /* #assert */
};
struct hashnode {
@@ -30,11 +45,17 @@ typedef struct hashnode HASHNODE;
the hashf () function. Hashf () only exists for the sake of
politeness, for use when speed isn't so important. */
-#define HASHSIZE 1403
-static HASHNODE *hashtab[HASHSIZE];
#define HASHSTEP(old, c) ((old << 2) + c)
#define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
-extern HASHNODE *install PARAMS ((U_CHAR *,int,enum node_type, int,char *,int));
-extern int hashf PARAMS ((const U_CHAR *, int, int));
-extern void delete_macro PARAMS ((HASHNODE *));
+extern HASHNODE *cpp_install PARAMS ((cpp_reader *, U_CHAR *, int,
+ enum node_type, const char *, int));
+extern int hashf PARAMS ((const U_CHAR *, int, int));
+extern void delete_macro PARAMS ((HASHNODE *));
+
+extern MACRODEF create_definition PARAMS ((U_CHAR *, U_CHAR *,
+ cpp_reader *, int));
+extern int compare_defs PARAMS ((cpp_reader *, DEFINITION *,
+ DEFINITION *));
+extern void macroexpand PARAMS ((cpp_reader *, HASHNODE *));
+extern void dump_definition PARAMS ((cpp_reader *, MACRODEF));
diff --git a/contrib/gcc/cppinit.c b/contrib/gcc/cppinit.c
new file mode 100644
index 0000000..f9bc306
--- /dev/null
+++ b/contrib/gcc/cppinit.c
@@ -0,0 +1,1778 @@
+/* CPP Library.
+ Copyright (C) 1986, 87, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Contributed by Per Bothner, 1994-95.
+ Based on CCCP program by Paul Rubin, June 1986
+ Adapted to ANSI C, Richard Stallman, Jan 1987
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+
+#define FAKE_CONST
+#include "cpplib.h"
+#include "cpphash.h"
+#include "output.h"
+#include "prefix.h"
+#include "intl.h"
+
+/* XXX Should be in a header file. */
+extern char *version_string;
+
+/* Predefined symbols, built-in macros, and the default include path. */
+
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
+#endif
+
+/* By default, colon separates directories in a path. */
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
+#endif
+
+#ifndef STANDARD_INCLUDE_DIR
+#define STANDARD_INCLUDE_DIR "/usr/include"
+#endif
+
+/* We let tm.h override the types used here, to handle trivial differences
+ such as the choice of unsigned int or long unsigned int for size_t.
+ When machines start needing nontrivial differences in the size type,
+ it would be best to do something here to figure out automatically
+ from other information what type to use. */
+
+/* The string value for __SIZE_TYPE__. */
+
+#ifndef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+#endif
+
+/* The string value for __PTRDIFF_TYPE__. */
+
+#ifndef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+#endif
+
+/* The string value for __WCHAR_TYPE__. */
+
+#ifndef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#endif
+#define CPP_WCHAR_TYPE(PFILE) \
+ (CPP_OPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
+
+/* The string value for __USER_LABEL_PREFIX__ */
+
+#ifndef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#endif
+
+/* The string value for __REGISTER_PREFIX__ */
+
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX ""
+#endif
+
+/* Suffix for object files, and known input-file extensions. */
+static char *known_suffixes[] =
+{
+ ".c", ".C", ".s", ".S", ".m",
+ ".cc", ".cxx", ".cpp", ".cp", ".c++",
+ NULL
+};
+
+#ifndef OBJECT_SUFFIX
+# ifdef VMS
+# define OBJECT_SUFFIX ".obj"
+# else
+# define OBJECT_SUFFIX ".o"
+# endif
+#endif
+
+
+/* This is the default list of directories to search for include files.
+ It may be overridden by the various -I and -ixxx options.
+
+ #include "file" looks in the same directory as the current file,
+ then this list.
+ #include <file> just looks in this list.
+
+ All these directories are treated as `system' include directories
+ (they are not subject to pedantic warnings in some cases). */
+
+static struct default_include
+{
+ char *fname; /* The name of the directory. */
+ char *component; /* The component containing the directory
+ (see update_path in prefix.c) */
+ int cplusplus; /* Only look here if we're compiling C++. */
+ int cxx_aware; /* Includes in this directory don't need to
+ be wrapped in extern "C" when compiling
+ C++. This is not used anymore. */
+}
+include_defaults_array[]
+#ifdef INCLUDE_DEFAULTS
+= INCLUDE_DEFAULTS;
+#else
+= {
+ /* Pick up GNU C++ specific include files. */
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
+#ifdef CROSS_COMPILE
+ /* This is the dir for fixincludes. Put it just before
+ the files that we fix. */
+ { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+ /* For cross-compilation, this dir name is generated
+ automatically in Makefile.in. */
+ { CROSS_INCLUDE_DIR, "GCC", 0, 0 },
+#ifdef TOOL_INCLUDE_DIR
+ /* This is another place that the target system's headers might be. */
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
+#else /* not CROSS_COMPILE */
+#ifdef LOCAL_INCLUDE_DIR
+ /* This should be /usr/local/include and should come before
+ the fixincludes-fixed header files. */
+ { LOCAL_INCLUDE_DIR, 0, 0, 1 },
+#endif
+#ifdef TOOL_INCLUDE_DIR
+ /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
+ Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
+ /* This is the dir for fixincludes. Put it just before
+ the files that we fix. */
+ { GCC_INCLUDE_DIR, "GCC", 0, 0 },
+ /* Some systems have an extra dir of include files. */
+#ifdef SYSTEM_INCLUDE_DIR
+ { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
+#endif
+#ifndef STANDARD_INCLUDE_COMPONENT
+#define STANDARD_INCLUDE_COMPONENT 0
+#endif
+ { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
+#endif /* not CROSS_COMPILE */
+ { 0, 0, 0, 0 }
+ };
+#endif /* no INCLUDE_DEFAULTS */
+
+/* Internal structures and prototypes. */
+
+/* A `struct pending_option' remembers one -D, -A, -U, -include, or -imacros
+ switch. There are four lists: one for -D and -U, one for -A, one
+ for -include, one for -imacros. `undef' is set for -U, clear for
+ -D, ignored for the others.
+ (Future: add an equivalent of -U for -A) */
+struct pending_option
+{
+ struct pending_option *next;
+ char *arg;
+ int undef;
+};
+
+#ifdef __STDC__
+#define APPEND(pend, list, elt) \
+ do { if (!(pend)->list##_head) (pend)->list##_head = (elt); \
+ else (pend)->list##_tail->next = (elt); \
+ (pend)->list##_tail = (elt); \
+ } while (0)
+#else
+#define APPEND(pend, list, elt) \
+ do { if (!(pend)->list/**/_head) (pend)->list/**/_head = (elt); \
+ else (pend)->list/**/_tail->next = (elt); \
+ (pend)->list/**/_tail = (elt); \
+ } while (0)
+#endif
+
+static void initialize_char_syntax PARAMS ((int));
+static void print_help PARAMS ((void));
+static void path_include PARAMS ((cpp_reader *,
+ struct cpp_pending *,
+ char *, int));
+static void initialize_builtins PARAMS ((cpp_reader *));
+static void append_include_chain PARAMS ((cpp_reader *,
+ struct cpp_pending *,
+ char *, int));
+
+/* Last argument to append_include_chain: chain to use */
+enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
+
+/* If gcc is in use (stage2/stage3) we can make these tables initialized
+ data. */
+#if defined __GNUC__ && __GNUC__ >= 2
+/* Table to tell if a character is legal as the second or later character
+ of a C identifier. */
+U_CHAR is_idchar[256] =
+{
+ ['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1,
+ ['g'] = 1, ['h'] = 1, ['i'] = 1, ['j'] = 1, ['k'] = 1, ['l'] = 1,
+ ['m'] = 1, ['n'] = 1, ['o'] = 1, ['p'] = 1, ['q'] = 1, ['r'] = 1,
+ ['s'] = 1, ['t'] = 1, ['u'] = 1, ['v'] = 1, ['w'] = 1, ['x'] = 1,
+ ['y'] = 1, ['z'] = 1,
+
+ ['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1,
+ ['G'] = 1, ['H'] = 1, ['I'] = 1, ['J'] = 1, ['K'] = 1, ['L'] = 1,
+ ['M'] = 1, ['N'] = 1, ['O'] = 1, ['P'] = 1, ['Q'] = 1, ['R'] = 1,
+ ['S'] = 1, ['T'] = 1, ['U'] = 1, ['V'] = 1, ['W'] = 1, ['X'] = 1,
+ ['Y'] = 1, ['Z'] = 1,
+
+ ['1'] = 1, ['2'] = 1, ['3'] = 1, ['4'] = 1, ['5'] = 1, ['6'] = 1,
+ ['7'] = 1, ['8'] = 1, ['9'] = 1, ['0'] = 1,
+
+ ['_'] = 1,
+};
+
+/* Table to tell if a character is legal as the first character of
+ a C identifier. */
+U_CHAR is_idstart[256] =
+{
+ ['a'] = 1, ['b'] = 1, ['c'] = 1, ['d'] = 1, ['e'] = 1, ['f'] = 1,
+ ['g'] = 1, ['h'] = 1, ['i'] = 1, ['j'] = 1, ['k'] = 1, ['l'] = 1,
+ ['m'] = 1, ['n'] = 1, ['o'] = 1, ['p'] = 1, ['q'] = 1, ['r'] = 1,
+ ['s'] = 1, ['t'] = 1, ['u'] = 1, ['v'] = 1, ['w'] = 1, ['x'] = 1,
+ ['y'] = 1, ['z'] = 1,
+
+ ['A'] = 1, ['B'] = 1, ['C'] = 1, ['D'] = 1, ['E'] = 1, ['F'] = 1,
+ ['G'] = 1, ['H'] = 1, ['I'] = 1, ['J'] = 1, ['K'] = 1, ['L'] = 1,
+ ['M'] = 1, ['N'] = 1, ['O'] = 1, ['P'] = 1, ['Q'] = 1, ['R'] = 1,
+ ['S'] = 1, ['T'] = 1, ['U'] = 1, ['V'] = 1, ['W'] = 1, ['X'] = 1,
+ ['Y'] = 1, ['Z'] = 1,
+
+ ['_'] = 1,
+};
+
+/* Table to tell if a character is horizontal space.
+ \r is magical, so it is not in here. */
+U_CHAR is_hor_space[256] =
+{
+ [' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1,
+};
+/* table to tell if a character is horizontal or vertical space. */
+U_CHAR is_space[256] =
+{
+ [' '] = 1, ['\t'] = 1, ['\v'] = 1, ['\f'] = 1, ['\n'] = 1,
+};
+/* Table to handle trigraph conversion, which occurs before all other
+ processing, everywhere in the file. (This is necessary since one
+ of the trigraphs encodes backslash.) Note it's off by default.
+
+ from to from to from to
+ ?? = # ?? ) ] ?? ! |
+ ?? ( [ ?? ' ^ ?? > }
+ ?? / \ ?? < { ?? - ~
+
+ There is not a space between the ?? and the third char. I put spaces
+ there to avoid warnings when compiling this file. */
+U_CHAR trigraph_table[256] =
+{
+ ['='] = '#', [')'] = ']', ['!'] = '|',
+ ['('] = '[', ['\''] = '^', ['>'] = '}',
+ ['/'] = '\\', ['<'] = '{', ['-'] = '~',
+};
+
+/* This function will be entirely removed soon. */
+static inline void
+initialize_char_syntax (dollar_in_ident)
+ int dollar_in_ident;
+{
+ is_idchar['$'] = dollar_in_ident;
+ is_idstart['$'] = dollar_in_ident;
+}
+
+#else /* Not GCC. */
+
+U_CHAR is_idchar[256] = { 0 };
+U_CHAR is_idstart[256] = { 0 };
+U_CHAR is_hor_space[256] = { 0 };
+U_CHAR is_space[256] = { 0 };
+U_CHAR trigraph_table[256] = { 0 };
+
+/* Initialize syntactic classifications of characters. */
+static void
+initialize_char_syntax (dollar_in_ident)
+ int dollar_in_ident;
+{
+ is_idstart['a'] = 1; is_idstart['b'] = 1; is_idstart['c'] = 1;
+ is_idstart['d'] = 1; is_idstart['e'] = 1; is_idstart['f'] = 1;
+ is_idstart['g'] = 1; is_idstart['h'] = 1; is_idstart['i'] = 1;
+ is_idstart['j'] = 1; is_idstart['k'] = 1; is_idstart['l'] = 1;
+ is_idstart['m'] = 1; is_idstart['n'] = 1; is_idstart['o'] = 1;
+ is_idstart['p'] = 1; is_idstart['q'] = 1; is_idstart['r'] = 1;
+ is_idstart['s'] = 1; is_idstart['t'] = 1; is_idstart['u'] = 1;
+ is_idstart['v'] = 1; is_idstart['w'] = 1; is_idstart['x'] = 1;
+ is_idstart['y'] = 1; is_idstart['z'] = 1;
+
+ is_idstart['A'] = 1; is_idstart['B'] = 1; is_idstart['C'] = 1;
+ is_idstart['D'] = 1; is_idstart['E'] = 1; is_idstart['F'] = 1;
+ is_idstart['G'] = 1; is_idstart['H'] = 1; is_idstart['I'] = 1;
+ is_idstart['J'] = 1; is_idstart['K'] = 1; is_idstart['L'] = 1;
+ is_idstart['M'] = 1; is_idstart['N'] = 1; is_idstart['O'] = 1;
+ is_idstart['P'] = 1; is_idstart['Q'] = 1; is_idstart['R'] = 1;
+ is_idstart['S'] = 1; is_idstart['T'] = 1; is_idstart['U'] = 1;
+ is_idstart['V'] = 1; is_idstart['W'] = 1; is_idstart['X'] = 1;
+ is_idstart['Y'] = 1; is_idstart['Z'] = 1;
+
+ is_idstart['_'] = 1;
+
+ is_idchar['a'] = 1; is_idchar['b'] = 1; is_idchar['c'] = 1;
+ is_idchar['d'] = 1; is_idchar['e'] = 1; is_idchar['f'] = 1;
+ is_idchar['g'] = 1; is_idchar['h'] = 1; is_idchar['i'] = 1;
+ is_idchar['j'] = 1; is_idchar['k'] = 1; is_idchar['l'] = 1;
+ is_idchar['m'] = 1; is_idchar['n'] = 1; is_idchar['o'] = 1;
+ is_idchar['p'] = 1; is_idchar['q'] = 1; is_idchar['r'] = 1;
+ is_idchar['s'] = 1; is_idchar['t'] = 1; is_idchar['u'] = 1;
+ is_idchar['v'] = 1; is_idchar['w'] = 1; is_idchar['x'] = 1;
+ is_idchar['y'] = 1; is_idchar['z'] = 1;
+
+ is_idchar['A'] = 1; is_idchar['B'] = 1; is_idchar['C'] = 1;
+ is_idchar['D'] = 1; is_idchar['E'] = 1; is_idchar['F'] = 1;
+ is_idchar['G'] = 1; is_idchar['H'] = 1; is_idchar['I'] = 1;
+ is_idchar['J'] = 1; is_idchar['K'] = 1; is_idchar['L'] = 1;
+ is_idchar['M'] = 1; is_idchar['N'] = 1; is_idchar['O'] = 1;
+ is_idchar['P'] = 1; is_idchar['Q'] = 1; is_idchar['R'] = 1;
+ is_idchar['S'] = 1; is_idchar['T'] = 1; is_idchar['U'] = 1;
+ is_idchar['V'] = 1; is_idchar['W'] = 1; is_idchar['X'] = 1;
+ is_idchar['Y'] = 1; is_idchar['Z'] = 1;
+
+ is_idchar['1'] = 1; is_idchar['2'] = 1; is_idchar['3'] = 1;
+ is_idchar['4'] = 1; is_idchar['5'] = 1; is_idchar['6'] = 1;
+ is_idchar['7'] = 1; is_idchar['8'] = 1; is_idchar['9'] = 1;
+ is_idchar['0'] = 1;
+
+ is_idchar['_'] = 1;
+
+ is_idchar['$'] = dollar_in_ident;
+ is_idstart['$'] = dollar_in_ident;
+
+ /* white space tables */
+ is_hor_space[' '] = 1;
+ is_hor_space['\t'] = 1;
+ is_hor_space['\v'] = 1;
+ is_hor_space['\f'] = 1;
+
+ is_space[' '] = 1;
+ is_space['\t'] = 1;
+ is_space['\v'] = 1;
+ is_space['\f'] = 1;
+ is_space['\n'] = 1;
+
+ /* trigraph conversion */
+ trigraph_table['='] = '#'; trigraph_table[')'] = ']';
+ trigraph_table['!'] = '|'; trigraph_table['('] = '[';
+ trigraph_table['\''] = '^'; trigraph_table['>'] = '}';
+ trigraph_table['/'] = '\\'; trigraph_table['<'] = '{';
+ trigraph_table['-'] = '~';
+}
+
+#endif /* Not GCC. */
+
+/* Given a colon-separated list of file names PATH,
+ add all the names to the search path for include files. */
+
+static void
+path_include (pfile, pend, list, path)
+ cpp_reader *pfile;
+ struct cpp_pending *pend;
+ char *list;
+ int path;
+{
+ char *p, *q, *name;
+
+ p = list;
+
+ do
+ {
+ /* Find the end of this name. */
+ q = p;
+ while (*q != 0 && *q != PATH_SEPARATOR) q++;
+ if (q == p)
+ {
+ /* An empty name in the path stands for the current directory. */
+ name = (char *) xmalloc (2);
+ name[0] = '.';
+ name[1] = 0;
+ }
+ else
+ {
+ /* Otherwise use the directory that is named. */
+ name = (char *) xmalloc (q - p + 1);
+ memcpy (name, p, q - p);
+ name[q - p] = 0;
+ }
+
+ append_include_chain (pfile, pend, name, path);
+
+ /* Advance past this name. */
+ if (*q == 0)
+ break;
+ p = q + 1;
+ }
+ while (1);
+}
+
+/* Find the base name of a (partial) pathname FNAME.
+ Returns a pointer into the string passed in.
+ Accepts Unix (/-separated) paths on all systems,
+ DOS and VMS paths on those systems. */
+static char *
+base_name (fname)
+ const char *fname;
+{
+ char *s = (char *)fname;
+ char *p;
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (ISALPHA (s[0]) && s[1] == ':') s += 2;
+ if ((p = rindex (s, '\\'))) s = p + 1;
+#elif defined VMS
+ if ((p = rindex (s, ':'))) s = p + 1; /* Skip device. */
+ if ((p = rindex (s, ']'))) s = p + 1; /* Skip directory. */
+ if ((p = rindex (s, '>'))) s = p + 1; /* Skip alternate (int'n'l) dir. */
+#endif
+ if ((p = rindex (s, '/'))) s = p + 1;
+ return s;
+}
+
+
+/* Append DIR to include path PATH. DIR must be permanently allocated
+ and writable. */
+static void
+append_include_chain (pfile, pend, dir, path)
+ cpp_reader *pfile;
+ struct cpp_pending *pend;
+ char *dir;
+ int path;
+{
+ struct file_name_list *new;
+ struct stat st;
+ unsigned int len;
+
+ simplify_pathname (dir);
+ if (stat (dir, &st))
+ {
+ /* Dirs that don't exist are silently ignored. */
+ if (errno != ENOENT)
+ cpp_perror_with_name (pfile, dir);
+ else if (CPP_OPTIONS (pfile)->verbose)
+ cpp_notice ("ignoring nonexistent directory `%s'\n", dir);
+ return;
+ }
+
+ if (!S_ISDIR (st.st_mode))
+ {
+ cpp_message (pfile, 1, "%s: %s: Not a directory", progname, dir);
+ return;
+ }
+
+ len = strlen (dir);
+ if (len > pfile->max_include_len)
+ pfile->max_include_len = len;
+
+ new = (struct file_name_list *)xmalloc (sizeof (struct file_name_list));
+ new->name = dir;
+ new->nlen = len;
+ new->ino = st.st_ino;
+ new->dev = st.st_dev;
+ new->sysp = (path == SYSTEM);
+ new->name_map = NULL;
+
+ switch (path)
+ {
+ case QUOTE: APPEND (pend, quote, new); break;
+ case BRACKET: APPEND (pend, brack, new); break;
+ case SYSTEM: APPEND (pend, systm, new); break;
+ case AFTER: APPEND (pend, after, new); break;
+ }
+}
+
+
+/* Write out a #define command for the special named MACRO_NAME
+ to PFILE's token_buffer. */
+
+static void
+dump_special_to_buffer (pfile, macro_name)
+ cpp_reader *pfile;
+ char *macro_name;
+{
+ static char define_directive[] = "#define ";
+ int macro_name_length = strlen (macro_name);
+ output_line_command (pfile, same_file);
+ CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
+ CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
+ CPP_PUTS_Q (pfile, macro_name, macro_name_length);
+ CPP_PUTC_Q (pfile, ' ');
+ cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
+ CPP_PUTC (pfile, '\n');
+}
+
+/* Initialize a cpp_options structure. */
+void
+cpp_options_init (opts)
+ cpp_options *opts;
+{
+ bzero ((char *) opts, sizeof (struct cpp_options));
+
+ opts->dollars_in_ident = 1;
+ opts->cplusplus_comments = 1;
+ opts->warn_import = 1;
+
+ opts->pending = (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
+ bzero ((char *) opts->pending, sizeof (struct cpp_pending));
+}
+
+/* Initialize a cpp_reader structure. */
+void
+cpp_reader_init (pfile)
+ cpp_reader *pfile;
+{
+ bzero ((char *) pfile, sizeof (cpp_reader));
+#if 0
+ pfile->get_token = cpp_get_token;
+#endif
+
+ pfile->token_buffer_size = 200;
+ pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
+ CPP_SET_WRITTEN (pfile, 0);
+
+ pfile->hashtab = (HASHNODE **) xcalloc (HASHSIZE, sizeof (HASHNODE *));
+}
+
+/* Free resources used by PFILE.
+ This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology). */
+void
+cpp_cleanup (pfile)
+ cpp_reader *pfile;
+{
+ int i;
+ while (CPP_BUFFER (pfile) != CPP_NULL_BUFFER (pfile))
+ cpp_pop_buffer (pfile);
+
+ if (pfile->token_buffer)
+ {
+ free (pfile->token_buffer);
+ pfile->token_buffer = NULL;
+ }
+
+ if (pfile->deps_buffer)
+ {
+ free (pfile->deps_buffer);
+ pfile->deps_buffer = NULL;
+ pfile->deps_allocated_size = 0;
+ }
+
+ if (pfile->input_buffer)
+ {
+ free (pfile->input_buffer);
+ free (pfile->input_speccase);
+ pfile->input_buffer = pfile->input_speccase = NULL;
+ pfile->input_buffer_len = 0;
+ }
+
+ while (pfile->if_stack)
+ {
+ IF_STACK_FRAME *temp = pfile->if_stack;
+ pfile->if_stack = temp->next;
+ free (temp);
+ }
+
+ for (i = ALL_INCLUDE_HASHSIZE; --i >= 0; )
+ {
+ struct include_hash *imp = pfile->all_include_files[i];
+ while (imp)
+ {
+ struct include_hash *next = imp->next;
+#if 0
+ /* This gets freed elsewhere - I think. */
+ free (imp->name);
+#endif
+ free (imp);
+ imp = next;
+ }
+ pfile->all_include_files[i] = 0;
+ }
+
+ for (i = HASHSIZE; --i >= 0;)
+ {
+ while (pfile->hashtab[i])
+ delete_macro (pfile->hashtab[i]);
+ }
+ free (pfile->hashtab);
+}
+
+
+/* Initialize the built-in macros. */
+static void
+initialize_builtins (pfile)
+ cpp_reader *pfile;
+{
+#define NAME(str) (U_CHAR *)str, sizeof str - 1
+ cpp_install (pfile, NAME("__TIME__"), T_TIME, 0, -1);
+ cpp_install (pfile, NAME("__DATE__"), T_DATE, 0, -1);
+ cpp_install (pfile, NAME("__FILE__"), T_FILE, 0, -1);
+ cpp_install (pfile, NAME("__BASE_FILE__"), T_BASE_FILE, 0, -1);
+ cpp_install (pfile, NAME("__LINE__"), T_SPECLINE, 0, -1);
+ cpp_install (pfile, NAME("__INCLUDE_LEVEL__"), T_INCLUDE_LEVEL, 0, -1);
+ cpp_install (pfile, NAME("__VERSION__"), T_VERSION, 0, -1);
+#ifndef NO_BUILTIN_SIZE_TYPE
+ cpp_install (pfile, NAME("__SIZE_TYPE__"), T_CONST, SIZE_TYPE, -1);
+#endif
+#ifndef NO_BUILTIN_PTRDIFF_TYPE
+ cpp_install (pfile, NAME("__PTRDIFF_TYPE__ "), T_CONST, PTRDIFF_TYPE, -1);
+#endif
+ cpp_install (pfile, NAME("__WCHAR_TYPE__"), T_CONST, WCHAR_TYPE, -1);
+ cpp_install (pfile, NAME("__USER_LABEL_PREFIX__"), T_CONST, user_label_prefix, -1);
+ cpp_install (pfile, NAME("__REGISTER_PREFIX__"), T_CONST, REGISTER_PREFIX, -1);
+ cpp_install (pfile, NAME("__HAVE_BUILTIN_SETJMP__"), T_CONST, "1", -1);
+ if (!CPP_TRADITIONAL (pfile))
+ {
+ cpp_install (pfile, NAME("__STDC__"), T_STDC, 0, -1);
+#if 0
+ if (CPP_OPTIONS (pfile)->c9x)
+ cpp_install (pfile, NAME("__STDC_VERSION__"),T_CONST, "199909L", -1);
+ else
+#endif
+ cpp_install (pfile, NAME("__STDC_VERSION__"),T_CONST, "199409L", -1);
+ }
+#undef NAME
+
+ if (CPP_OPTIONS (pfile)->debug_output)
+ {
+ dump_special_to_buffer (pfile, "__BASE_FILE__");
+ dump_special_to_buffer (pfile, "__VERSION__");
+#ifndef NO_BUILTIN_SIZE_TYPE
+ dump_special_to_buffer (pfile, "__SIZE_TYPE__");
+#endif
+#ifndef NO_BUILTIN_PTRDIFF_TYPE
+ dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
+#endif
+ dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
+ dump_special_to_buffer (pfile, "__DATE__");
+ dump_special_to_buffer (pfile, "__TIME__");
+ if (!CPP_TRADITIONAL (pfile))
+ dump_special_to_buffer (pfile, "__STDC__");
+ }
+}
+
+/* Another subroutine of cpp_start_read. This one sets up to do
+ dependency-file output. */
+static void
+initialize_dependency_output (pfile)
+ cpp_reader *pfile;
+{
+ cpp_options *opts = CPP_OPTIONS (pfile);
+ char *spec, *s, *output_file;
+
+ /* Either of two environment variables can specify output of deps.
+ Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
+ where OUTPUT_FILE is the file to write deps info to
+ and DEPS_TARGET is the target to mention in the deps. */
+
+ if (opts->print_deps == 0)
+ {
+ spec = getenv ("DEPENDENCIES_OUTPUT");
+ if (spec)
+ opts->print_deps = 1;
+ else
+ {
+ spec = getenv ("SUNPRO_DEPENDENCIES");
+ if (spec)
+ opts->print_deps = 2;
+ else
+ return;
+ }
+
+ /* Find the space before the DEPS_TARGET, if there is one. */
+ s = strchr (spec, ' ');
+ if (s)
+ {
+ opts->deps_target = s + 1;
+ output_file = (char *) xmalloc (s - spec + 1);
+ memcpy (output_file, spec, s - spec);
+ output_file[s - spec] = 0;
+ }
+ else
+ {
+ opts->deps_target = 0;
+ output_file = spec;
+ }
+
+ opts->deps_file = output_file;
+ opts->print_deps_append = 1;
+ }
+
+ /* Print the expected object file name as the target of this Make-rule. */
+ pfile->deps_allocated_size = 200;
+ pfile->deps_buffer = (char *) xmalloc (pfile->deps_allocated_size);
+ pfile->deps_buffer[0] = 0;
+ pfile->deps_size = 0;
+ pfile->deps_column = 0;
+
+ if (opts->deps_target)
+ deps_output (pfile, opts->deps_target, ':');
+ else if (*opts->in_fname == 0)
+ deps_output (pfile, "-", ':');
+ else
+ {
+ char *p, *q, *r;
+ int len, x;
+
+ /* Discard all directory prefixes from filename. */
+ q = base_name (opts->in_fname);
+
+ /* Copy remainder to mungable area. */
+ len = strlen (q);
+ p = (char *) alloca (len + 8);
+ strcpy (p, q);
+
+ /* Output P, but remove known suffixes. */
+ q = p + len;
+ /* Point to the filename suffix. */
+ r = rindex (p, '.');
+ /* Compare against the known suffixes. */
+ for (x = 0; known_suffixes[x]; x++)
+ {
+ if (strncmp (known_suffixes[x], r, q - r) == 0)
+ {
+ /* Make q point to the bit we're going to overwrite
+ with an object suffix. */
+ q = r;
+ break;
+ }
+ }
+
+ /* Supply our own suffix. */
+ strcpy (q, OBJECT_SUFFIX);
+
+ deps_output (pfile, p, ':');
+ deps_output (pfile, opts->in_fname, ' ');
+ }
+}
+
+/* This is called after options have been processed.
+ * Check options for consistency, and setup for processing input
+ * from the file named FNAME. (Use standard input if FNAME==NULL.)
+ * Return 1 on success, 0 on failure.
+ */
+
+int
+cpp_start_read (pfile, fname)
+ cpp_reader *pfile;
+ char *fname;
+{
+ struct cpp_options *opts = CPP_OPTIONS (pfile);
+ struct pending_option *p, *q;
+ int f;
+ cpp_buffer *fp;
+ struct include_hash *ih_fake;
+
+ /* -MG doesn't select the form of output and must be specified with one of
+ -M or -MM. -MG doesn't make sense with -MD or -MMD since they don't
+ inhibit compilation. */
+ if (opts->print_deps_missing_files
+ && (opts->print_deps == 0 || !opts->no_output))
+ {
+ cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
+ return 0;
+ }
+
+ /* Chill should not be used with -trigraphs. */
+ if (opts->chill && opts->trigraphs)
+ {
+ cpp_warning (pfile, "-lang-chill and -trigraphs are mutually exclusive");
+ opts->trigraphs = 0;
+ }
+
+ /* Set this if it hasn't been set already. */
+ if (user_label_prefix == NULL)
+ user_label_prefix = USER_LABEL_PREFIX;
+
+ /* Now that we know dollars_in_ident, we can initialize the syntax
+ tables. */
+ initialize_char_syntax (opts->dollars_in_ident);
+
+ /* Do partial setup of input buffer for the sake of generating
+ early #line directives (when -g is in effect). */
+ fp = cpp_push_buffer (pfile, NULL, 0);
+ if (!fp)
+ return 0;
+ if (opts->in_fname == NULL || *opts->in_fname == 0)
+ {
+ opts->in_fname = fname;
+ if (opts->in_fname == NULL)
+ opts->in_fname = "";
+ }
+ fp->nominal_fname = fp->fname = opts->in_fname;
+ fp->lineno = 0;
+
+ /* Install __LINE__, etc. Must follow initialize_char_syntax
+ and option processing. */
+ initialize_builtins (pfile);
+
+ /* Do -U's, -D's and -A's in the order they were seen. */
+ p = opts->pending->define_head;
+ while (p)
+ {
+ if (opts->debug_output)
+ output_line_command (pfile, same_file);
+ if (p->undef)
+ cpp_undef (pfile, p->arg);
+ else
+ cpp_define (pfile, p->arg);
+
+ q = p->next;
+ free (p);
+ p = q;
+ }
+
+ p = opts->pending->assert_head;
+ while (p)
+ {
+ if (opts->debug_output)
+ output_line_command (pfile, same_file);
+ if (p->undef)
+ cpp_unassert (pfile, p->arg);
+ else
+ cpp_assert (pfile, p->arg);
+
+ q = p->next;
+ free (p);
+ p = q;
+ }
+
+ opts->done_initializing = 1;
+
+ /* Several environment variables may add to the include search path.
+ CPATH specifies an additional list of directories to be searched
+ as if specified with -I, while C_INCLUDE_PATH, CPLUS_INCLUDE_PATH,
+ etc. specify an additional list of directories to be searched as
+ if specified with -isystem, for the language indicated.
+
+ These variables are ignored if -nostdinc is on. */
+ if (! opts->no_standard_includes)
+ {
+ char *path;
+ GET_ENV_PATH_LIST (path, "CPATH");
+ if (path != 0 && *path != 0)
+ path_include (pfile, opts->pending, path, BRACKET);
+
+ switch ((opts->objc << 1) + opts->cplusplus)
+ {
+ case 0:
+ GET_ENV_PATH_LIST (path, "C_INCLUDE_PATH");
+ break;
+ case 1:
+ GET_ENV_PATH_LIST (path, "CPLUS_INCLUDE_PATH");
+ break;
+ case 2:
+ GET_ENV_PATH_LIST (path, "OBJC_INCLUDE_PATH");
+ break;
+ case 3:
+ GET_ENV_PATH_LIST (path, "OBJCPLUS_INCLUDE_PATH");
+ break;
+ }
+ if (path != 0 && *path != 0)
+ path_include (pfile, opts->pending, path, SYSTEM);
+ }
+
+ /* Unless -nostdinc, add the compiled-in include path to the list,
+ translating prefixes. */
+ if (!opts->no_standard_includes)
+ {
+ struct default_include *p = include_defaults_array;
+ char *specd_prefix = opts->include_prefix;
+
+ /* Search "translated" versions of GNU directories.
+ These have /usr/local/lib/gcc... replaced by specd_prefix. */
+ if (specd_prefix != 0)
+ {
+ char *default_prefix = alloca (sizeof GCC_INCLUDE_DIR - 7);
+ /* Remove the `include' from /usr/local/lib/gcc.../include.
+ GCC_INCLUDE_DIR will always end in /include. */
+ int default_len = sizeof GCC_INCLUDE_DIR - 8;
+ int specd_len = strlen (specd_prefix);
+
+ default_len = sizeof GCC_INCLUDE_DIR - 8;
+ memcpy (default_prefix, GCC_INCLUDE_DIR, default_len);
+ default_prefix[default_len] = '\0';
+
+ for (p = include_defaults_array; p->fname; p++)
+ {
+ /* Some standard dirs are only for C++. */
+ if (!p->cplusplus
+ || (opts->cplusplus
+ && !opts->no_standard_cplusplus_includes))
+ {
+ /* Does this dir start with the prefix? */
+ if (!strncmp (p->fname, default_prefix, default_len))
+ {
+ /* Yes; change prefix and add to search list. */
+ int flen = strlen (p->fname);
+ int this_len = specd_len + flen - default_len;
+ char *str = (char *) xmalloc (this_len + 1);
+ memcpy (str, specd_prefix, specd_len);
+ memcpy (str + specd_len,
+ p->fname + default_len,
+ flen - default_len + 1);
+
+ append_include_chain (pfile, opts->pending,
+ str, SYSTEM);
+ }
+ }
+ }
+ }
+
+ /* Search ordinary names for GNU include directories. */
+ for (p = include_defaults_array; p->fname; p++)
+ {
+ /* Some standard dirs are only for C++. */
+ if (!p->cplusplus
+ || (opts->cplusplus
+ && !opts->no_standard_cplusplus_includes))
+ {
+ char *str = (char *) update_path (p->fname, p->component);
+ str = xstrdup (str); /* XXX Potential memory leak! */
+ append_include_chain (pfile, opts->pending, str, SYSTEM);
+ }
+ }
+ }
+
+ merge_include_chains (opts);
+
+ /* With -v, print the list of dirs to search. */
+ if (opts->verbose)
+ {
+ struct file_name_list *p;
+ cpp_message (pfile, -1, "#include \"...\" search starts here:\n");
+ for (p = opts->quote_include; p; p = p->next)
+ {
+ if (p == opts->bracket_include)
+ cpp_message (pfile, -1, "#include <...> search starts here:\n");
+ fprintf (stderr, " %s\n", p->name);
+ }
+ cpp_message (pfile, -1, "End of search list.\n");
+ }
+
+ /* Open the main input file.
+ We do this in nonblocking mode so we don't get stuck here if
+ someone clever has asked cpp to process /dev/rmt0;
+ finclude() will check that we have a real file to work with. */
+ if (fname == NULL || *fname == 0)
+ {
+ fname = "";
+ f = 0;
+ }
+ else if ((f = open (fname, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666)) < 0)
+ cpp_pfatal_with_name (pfile, fname);
+
+ initialize_dependency_output (pfile);
+
+ /* Must call finclude() on the main input before processing
+ -include switches; otherwise the -included text winds up
+ after the main input. */
+ ih_fake = (struct include_hash *) xmalloc (sizeof (struct include_hash));
+ ih_fake->next = 0;
+ ih_fake->next_this_file = 0;
+ ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */
+ ih_fake->name = fname;
+ ih_fake->control_macro = 0;
+ ih_fake->buf = (char *)-1;
+ ih_fake->limit = 0;
+ if (!finclude (pfile, f, ih_fake))
+ return 0;
+ output_line_command (pfile, same_file);
+ pfile->only_seen_white = 2;
+
+ /* The -imacros files can be scanned now, but the -include files
+ have to be pushed onto the include stack and processed later,
+ in the main loop calling cpp_get_token. */
+
+ pfile->no_record_file++;
+ opts->no_output++;
+ p = opts->pending->imacros_head;
+ while (p)
+ {
+ int fd = open (p->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
+ if (fd < 0)
+ {
+ cpp_perror_with_name (pfile, p->arg);
+ return 0;
+ }
+ if (!cpp_push_buffer (pfile, NULL, 0))
+ return 0;
+
+ ih_fake = (struct include_hash *)
+ xmalloc (sizeof (struct include_hash));
+ ih_fake->next = 0;
+ ih_fake->next_this_file = 0;
+ ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */
+ ih_fake->name = p->arg;
+ ih_fake->control_macro = 0;
+ ih_fake->buf = (char *)-1;
+ ih_fake->limit = 0;
+ if (!finclude (pfile, fd, ih_fake))
+ cpp_scan_buffer (pfile);
+ free (ih_fake);
+
+ q = p->next;
+ free (p);
+ p = q;
+ }
+
+ opts->no_output--;
+
+ p = opts->pending->include_head;
+ while (p)
+ {
+ int fd = open (p->arg, O_RDONLY|O_NONBLOCK|O_NOCTTY, 0666);
+ if (fd < 0)
+ {
+ cpp_perror_with_name (pfile, p->arg);
+ return 0;
+ }
+ if (!cpp_push_buffer (pfile, NULL, 0))
+ return 0;
+
+ ih_fake = (struct include_hash *)
+ xmalloc (sizeof (struct include_hash));
+ ih_fake->next = 0;
+ ih_fake->next_this_file = 0;
+ ih_fake->foundhere = ABSOLUTE_PATH; /* well sort of ... */
+ ih_fake->name = p->arg;
+ ih_fake->control_macro = 0;
+ ih_fake->buf = (char *)-1;
+ ih_fake->limit = 0;
+ if (finclude (pfile, fd, ih_fake))
+ output_line_command (pfile, enter_file);
+
+ q = p->next;
+ free (p);
+ p = q;
+ }
+ pfile->no_record_file--;
+
+ free (opts->pending);
+ opts->pending = NULL;
+
+ return 1;
+}
+
+/* This is called at the end of preprocessing. It pops the
+ last buffer and writes dependency output. It should also
+ clear macro definitions, such that you could call cpp_start_read
+ with a new filename to restart processing. */
+void
+cpp_finish (pfile)
+ cpp_reader *pfile;
+{
+ struct cpp_options *opts = CPP_OPTIONS (pfile);
+
+ if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != CPP_NULL_BUFFER (pfile))
+ cpp_fatal (pfile,
+ "cpplib internal error: buffers still stacked in cpp_finish");
+ cpp_pop_buffer (pfile);
+
+ if (opts->print_deps)
+ {
+ /* Stream on which to print the dependency information. */
+ FILE *deps_stream;
+
+ /* Don't actually write the deps file if compilation has failed. */
+ if (pfile->errors == 0)
+ {
+ char *deps_mode = opts->print_deps_append ? "a" : "w";
+ if (opts->deps_file == 0)
+ deps_stream = stdout;
+ else if ((deps_stream = fopen (opts->deps_file, deps_mode)) == 0)
+ cpp_pfatal_with_name (pfile, opts->deps_file);
+ fputs (pfile->deps_buffer, deps_stream);
+ putc ('\n', deps_stream);
+ if (opts->deps_file)
+ {
+ if (ferror (deps_stream) || fclose (deps_stream) != 0)
+ cpp_fatal (pfile, "I/O error on output");
+ }
+ }
+ }
+
+ if (opts->dump_macros == dump_only)
+ {
+ int i;
+ HASHNODE *h;
+ MACRODEF m;
+ for (i = HASHSIZE; --i >= 0;)
+ {
+ for (h = pfile->hashtab[i]; h; h = h->next)
+ if (h->type == T_MACRO)
+ {
+ m.defn = h->value.defn;
+ m.symnam = h->name;
+ m.symlen = h->length;
+ dump_definition (pfile, m);
+ CPP_PUTC (pfile, '\n');
+ }
+ }
+ }
+}
+
+/* Handle one command-line option in (argc, argv).
+ Can be called multiple times, to handle multiple sets of options.
+ Returns number of strings consumed. */
+int
+cpp_handle_option (pfile, argc, argv)
+ cpp_reader *pfile;
+ int argc;
+ char **argv;
+{
+ struct cpp_options *opts = CPP_OPTIONS (pfile);
+ int i = 0;
+
+ if (argv[i][0] != '-')
+ {
+ if (opts->out_fname != NULL)
+ {
+ print_help ();
+ cpp_fatal (pfile, "Too many arguments");
+ }
+ else if (opts->in_fname != NULL)
+ opts->out_fname = argv[i];
+ else
+ opts->in_fname = argv[i];
+ }
+ else
+ switch (argv[i][1])
+ {
+ case 'f':
+ if (!strcmp (argv[i], "-fleading-underscore"))
+ user_label_prefix = "_";
+ else if (!strcmp (argv[i], "-fno-leading-underscore"))
+ user_label_prefix = "";
+ break;
+
+ case 'I': /* Add directory to path for includes. */
+ if (!strcmp (argv[i] + 2, "-"))
+ {
+ /* -I- means:
+ Use the preceding -I directories for #include "..."
+ but not #include <...>.
+ Don't search the directory of the present file
+ for #include "...". (Note that -I. -I- is not the same as
+ the default setup; -I. uses the compiler's working dir.) */
+ if (! opts->ignore_srcdir)
+ {
+ opts->ignore_srcdir = 1;
+ opts->pending->quote_head = opts->pending->brack_head;
+ opts->pending->quote_tail = opts->pending->brack_tail;
+ opts->pending->brack_head = 0;
+ opts->pending->brack_tail = 0;
+ }
+ else
+ {
+ cpp_fatal (pfile, "-I- specified twice");
+ return argc;
+ }
+ }
+ else
+ {
+ char *fname;
+ if (argv[i][2] != 0)
+ fname = argv[i] + 2;
+ else if (i + 1 == argc)
+ goto missing_dirname;
+ else
+ fname = argv[++i];
+ append_include_chain (pfile, opts->pending,
+ xstrdup (fname), BRACKET);
+ }
+ break;
+
+ case 'i':
+ /* Add directory to beginning of system include path, as a system
+ include directory. */
+ if (!strcmp (argv[i], "-isystem"))
+ {
+ if (i + 1 == argc)
+ goto missing_filename;
+ append_include_chain (pfile, opts->pending,
+ xstrdup (argv[++i]), SYSTEM);
+ }
+ else if (!strcmp (argv[i], "-include"))
+ {
+ if (i + 1 == argc)
+ goto missing_filename;
+ else
+ {
+ struct pending_option *o = (struct pending_option *)
+ xmalloc (sizeof (struct pending_option));
+ o->arg = argv[++i];
+
+ /* This list has to be built in reverse order so that
+ when cpp_start_read pushes all the -include files onto
+ the buffer stack, they will be scanned in forward order. */
+ o->next = opts->pending->include_head;
+ opts->pending->include_head = o;
+ }
+ }
+ else if (!strcmp (argv[i], "-imacros"))
+ {
+ if (i + 1 == argc)
+ goto missing_filename;
+ else
+ {
+ struct pending_option *o = (struct pending_option *)
+ xmalloc (sizeof (struct pending_option));
+ o->arg = argv[++i];
+ o->next = NULL;
+
+ APPEND (opts->pending, imacros, o);
+ }
+ }
+ /* Add directory to end of path for includes,
+ with the default prefix at the front of its name. */
+ else if (!strcmp (argv[i], "-iwithprefix"))
+ {
+ char *fname;
+ int len;
+ if (i + 1 == argc)
+ goto missing_dirname;
+ ++i;
+ len = strlen (argv[i]);
+
+ if (opts->include_prefix != 0)
+ {
+ fname = xmalloc (opts->include_prefix_len + len + 1);
+ memcpy (fname, opts->include_prefix, opts->include_prefix_len);
+ memcpy (fname + opts->include_prefix_len, argv[i], len + 1);
+ }
+ else
+ {
+ fname = xmalloc (sizeof GCC_INCLUDE_DIR - 8 + len);
+ memcpy (fname, GCC_INCLUDE_DIR, sizeof GCC_INCLUDE_DIR - 9);
+ memcpy (fname + sizeof GCC_INCLUDE_DIR - 9, argv[i], len + 1);
+ }
+
+ append_include_chain (pfile, opts->pending, fname, SYSTEM);
+ }
+ /* Add directory to main path for includes,
+ with the default prefix at the front of its name. */
+ else if (!strcmp (argv[i], "-iwithprefixbefore"))
+ {
+ char *fname;
+ int len;
+ if (i + 1 == argc)
+ goto missing_dirname;
+ ++i;
+ len = strlen (argv[i]);
+
+ if (opts->include_prefix != 0)
+ {
+ fname = xmalloc (opts->include_prefix_len + len + 1);
+ memcpy (fname, opts->include_prefix, opts->include_prefix_len);
+ memcpy (fname + opts->include_prefix_len, argv[i], len + 1);
+ }
+ else
+ {
+ fname = xmalloc (sizeof GCC_INCLUDE_DIR - 8 + len);
+ memcpy (fname, GCC_INCLUDE_DIR, sizeof GCC_INCLUDE_DIR - 9);
+ memcpy (fname + sizeof GCC_INCLUDE_DIR - 9, argv[i], len + 1);
+ }
+
+ append_include_chain (pfile, opts->pending, fname, BRACKET);
+ }
+ /* Add directory to end of path for includes. */
+ else if (!strcmp (argv[i], "-idirafter"))
+ {
+ if (i + 1 == argc)
+ goto missing_dirname;
+ append_include_chain (pfile, opts->pending,
+ xstrdup (argv[++i]), AFTER);
+ }
+ else if (!strcmp (argv[i], "-iprefix"))
+ {
+ if (i + 1 == argc)
+ goto missing_filename;
+ else
+ {
+ opts->include_prefix = argv[++i];
+ opts->include_prefix_len = strlen (argv[i]);
+ }
+ }
+ else if (!strcmp (argv[i], "-ifoutput"))
+ opts->output_conditionals = 1;
+
+ break;
+
+ case 'o':
+ if (opts->out_fname != NULL)
+ {
+ cpp_fatal (pfile, "Output filename specified twice");
+ return argc;
+ }
+ if (i + 1 == argc)
+ goto missing_filename;
+ opts->out_fname = argv[++i];
+ if (!strcmp (opts->out_fname, "-"))
+ opts->out_fname = "";
+ break;
+
+ case 'p':
+ if (!strcmp (argv[i], "-pedantic"))
+ CPP_PEDANTIC (pfile) = 1;
+ else if (!strcmp (argv[i], "-pedantic-errors"))
+ {
+ CPP_PEDANTIC (pfile) = 1;
+ opts->pedantic_errors = 1;
+ }
+#if 0
+ else if (!strcmp (argv[i], "-pcp")) {
+ char *pcp_fname = argv[++i];
+ pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
+ ? fopen (pcp_fname, "w")
+ : fdopen (dup (fileno (stdout)), "w"));
+ if (pcp_outfile == 0)
+ cpp_pfatal_with_name (pfile, pcp_fname);
+ no_precomp = 1;
+ }
+#endif
+ break;
+
+ case 't':
+ if (!strcmp (argv[i], "-traditional"))
+ {
+ opts->traditional = 1;
+ opts->cplusplus_comments = 0;
+ }
+ else if (!strcmp (argv[i], "-trigraphs"))
+ opts->trigraphs = 1;
+ break;
+
+ case 'l':
+ if (! strcmp (argv[i], "-lang-c"))
+ opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->c9x = 1, opts->objc = 0;
+ if (! strcmp (argv[i], "-lang-c89"))
+ opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
+ opts->c9x = 0, opts->objc = 0;
+ if (! strcmp (argv[i], "-lang-c++"))
+ opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->c9x = 0, opts->objc = 0;
+ if (! strcmp (argv[i], "-lang-objc"))
+ opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->c9x = 0, opts->objc = 1;
+ if (! strcmp (argv[i], "-lang-objc++"))
+ opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->c9x = 0, opts->objc = 1;
+ if (! strcmp (argv[i], "-lang-asm"))
+ opts->lang_asm = 1;
+ if (! strcmp (argv[i], "-lint"))
+ opts->for_lint = 1;
+ if (! strcmp (argv[i], "-lang-chill"))
+ opts->objc = 0, opts->cplusplus = 0, opts->chill = 1,
+ opts->traditional = 1;
+ break;
+
+ case '+':
+ opts->cplusplus = 1, opts->cplusplus_comments = 1;
+ break;
+
+ case 's':
+ if (!strcmp (argv[i], "-std=iso9899:1990")
+ || !strcmp (argv[i], "-std=iso9899:199409")
+ || !strcmp (argv[i], "-std=c89")
+ || !strcmp (argv[i], "-std=gnu89"))
+ opts->cplusplus = 0, opts->cplusplus_comments = 0,
+ opts->c89 = 1, opts->c9x = 0, opts->objc = 0;
+ else if (!strcmp (argv[i], "-std=iso9899:199x")
+ || !strcmp (argv[i], "-std=c9x")
+ || !strcmp (argv[i], "-std=gnu9x"))
+ opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->c9x = 1, opts->objc = 0;
+ break;
+
+ case 'w':
+ opts->inhibit_warnings = 1;
+ break;
+
+ case 'W':
+ if (!strcmp (argv[i], "-Wtrigraphs"))
+ opts->warn_trigraphs = 1;
+ else if (!strcmp (argv[i], "-Wno-trigraphs"))
+ opts->warn_trigraphs = 0;
+ else if (!strcmp (argv[i], "-Wcomment"))
+ opts->warn_comments = 1;
+ else if (!strcmp (argv[i], "-Wno-comment"))
+ opts->warn_comments = 0;
+ else if (!strcmp (argv[i], "-Wcomments"))
+ opts->warn_comments = 1;
+ else if (!strcmp (argv[i], "-Wno-comments"))
+ opts->warn_comments = 0;
+ else if (!strcmp (argv[i], "-Wtraditional"))
+ opts->warn_stringify = 1;
+ else if (!strcmp (argv[i], "-Wno-traditional"))
+ opts->warn_stringify = 0;
+ else if (!strcmp (argv[i], "-Wundef"))
+ opts->warn_undef = 1;
+ else if (!strcmp (argv[i], "-Wno-undef"))
+ opts->warn_undef = 0;
+ else if (!strcmp (argv[i], "-Wimport"))
+ opts->warn_import = 1;
+ else if (!strcmp (argv[i], "-Wno-import"))
+ opts->warn_import = 0;
+ else if (!strcmp (argv[i], "-Werror"))
+ opts->warnings_are_errors = 1;
+ else if (!strcmp (argv[i], "-Wno-error"))
+ opts->warnings_are_errors = 0;
+ else if (!strcmp (argv[i], "-Wall"))
+ {
+ opts->warn_trigraphs = 1;
+ opts->warn_comments = 1;
+ }
+ break;
+
+ case 'M':
+ /* The style of the choices here is a bit mixed.
+ The chosen scheme is a hybrid of keeping all options in one string
+ and specifying each option in a separate argument:
+ -M|-MM|-MD file|-MMD file [-MG]. An alternative is:
+ -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
+ -M[M][G][D file]. This is awkward to handle in specs, and is not
+ as extensible. */
+ /* ??? -MG must be specified in addition to one of -M or -MM.
+ This can be relaxed in the future without breaking anything.
+ The converse isn't true. */
+
+ /* -MG isn't valid with -MD or -MMD. This is checked for later. */
+ if (!strcmp (argv[i], "-MG"))
+ {
+ opts->print_deps_missing_files = 1;
+ break;
+ }
+ if (!strcmp (argv[i], "-M"))
+ opts->print_deps = 2;
+ else if (!strcmp (argv[i], "-MM"))
+ opts->print_deps = 1;
+ else if (!strcmp (argv[i], "-MD"))
+ opts->print_deps = 2;
+ else if (!strcmp (argv[i], "-MMD"))
+ opts->print_deps = 1;
+ /* For -MD and -MMD options, write deps on file named by next arg. */
+ if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
+ {
+ if (i+1 == argc)
+ goto missing_filename;
+ opts->deps_file = argv[++i];
+ }
+ else
+ {
+ /* For -M and -MM, write deps on standard output
+ and suppress the usual output. */
+ opts->no_output = 1;
+ }
+ break;
+
+ case 'd':
+ {
+ char *p = argv[i] + 2;
+ char c;
+ while ((c = *p++) != 0)
+ {
+ /* Arg to -d specifies what parts of macros to dump */
+ switch (c)
+ {
+ case 'M':
+ opts->dump_macros = dump_only;
+ opts->no_output = 1;
+ break;
+ case 'N':
+ opts->dump_macros = dump_names;
+ break;
+ case 'D':
+ opts->dump_macros = dump_definitions;
+ break;
+ case 'I':
+ opts->dump_includes = 1;
+ break;
+ }
+ }
+ }
+ break;
+
+ case 'g':
+ if (argv[i][2] == '3')
+ opts->debug_output = 1;
+ break;
+
+ case '-':
+ if (!strcmp (argv[i], "--help"))
+ print_help ();
+ else if (!strcmp (argv[i], "--version"))
+ cpp_notice ("GNU CPP version %s\n", version_string);
+ exit (0); /* XXX */
+ break;
+
+ case 'v':
+ cpp_notice ("GNU CPP version %s", version_string);
+#ifdef TARGET_VERSION
+ TARGET_VERSION;
+#endif
+ fputc ('\n', stderr);
+ opts->verbose = 1;
+ break;
+
+ case 'H':
+ opts->print_include_names = 1;
+ break;
+
+ case 'D':
+ {
+ struct pending_option *o = (struct pending_option *)
+ xmalloc (sizeof (struct pending_option));
+ if (argv[i][2] != 0)
+ o->arg = argv[i] + 2;
+ else if (i + 1 == argc)
+ {
+ cpp_fatal (pfile, "Macro name missing after -D option");
+ return argc;
+ }
+ else
+ o->arg = argv[++i];
+
+ o->next = NULL;
+ o->undef = 0;
+ APPEND (opts->pending, define, o);
+ }
+ break;
+
+ case 'A':
+ {
+ char *p;
+
+ if (argv[i][2] != 0)
+ p = argv[i] + 2;
+ else if (i + 1 == argc)
+ {
+ cpp_fatal (pfile, "Assertion missing after -A option");
+ return argc;
+ }
+ else
+ p = argv[++i];
+
+ if (strcmp (p, "-"))
+ {
+ struct pending_option *o = (struct pending_option *)
+ xmalloc (sizeof (struct pending_option));
+
+ o->arg = p;
+ o->next = NULL;
+ o->undef = 0;
+ APPEND (opts->pending, assert, o);
+ }
+ else
+ {
+ /* -A- eliminates all predefined macros and assertions.
+ Let's include also any that were specified earlier
+ on the command line. That way we can get rid of any
+ that were passed automatically in from GCC. */
+ struct pending_option *o1, *o2;
+
+ o1 = opts->pending->define_head;
+ while (o1)
+ {
+ o2 = o1->next;
+ free (o1);
+ o1 = o2;
+ }
+ o1 = opts->pending->assert_head;
+ while (o1)
+ {
+ o2 = o1->next;
+ free (o1);
+ o1 = o2;
+ }
+ opts->pending->assert_head = NULL;
+ opts->pending->assert_tail = NULL;
+ opts->pending->define_head = NULL;
+ opts->pending->define_tail = NULL;
+ }
+ }
+ break;
+
+ case 'U':
+ {
+ struct pending_option *o = (struct pending_option *)
+ xmalloc (sizeof (struct pending_option));
+
+ if (argv[i][2] != 0)
+ o->arg = argv[i] + 2;
+ else if (i + 1 == argc)
+ {
+ cpp_fatal (pfile, "Macro name missing after -U option");
+ return argc;
+ }
+ else
+ o->arg = argv[++i];
+
+ o->next = NULL;
+ o->undef = 1;
+ APPEND (opts->pending, define, o);
+ }
+ break;
+
+ case 'C':
+ opts->put_out_comments = 1;
+ break;
+
+ case 'E': /* -E comes from cc -E; ignore it. */
+ break;
+
+ case 'P':
+ opts->no_line_commands = 1;
+ break;
+
+ case '$': /* Don't include $ in identifiers. */
+ opts->dollars_in_ident = 0;
+ break;
+
+ case 'n':
+ if (!strcmp (argv[i], "-nostdinc"))
+ /* -nostdinc causes no default include directories.
+ You must specify all include-file directories with -I. */
+ opts->no_standard_includes = 1;
+ else if (!strcmp (argv[i], "-nostdinc++"))
+ /* -nostdinc++ causes no default C++-specific include directories. */
+ opts->no_standard_cplusplus_includes = 1;
+#if 0
+ else if (!strcmp (argv[i], "-noprecomp"))
+ no_precomp = 1;
+#endif
+ break;
+
+ case 'r':
+ if (!strcmp (argv[i], "-remap"))
+ opts->remap = 1;
+ break;
+
+ case '\0': /* JF handle '-' as file name meaning stdin or stdout */
+ if (opts->in_fname == NULL)
+ opts->in_fname = "";
+ else if (opts->out_fname == NULL)
+ opts->out_fname = "";
+ else
+ return i; /* error */
+ break;
+
+ default:
+ return i;
+ }
+
+ return i + 1;
+
+ missing_filename:
+ cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
+ return argc;
+ missing_dirname:
+ cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
+ return argc;
+}
+
+/* Handle command-line options in (argc, argv).
+ Can be called multiple times, to handle multiple sets of options.
+ Returns if an unrecognized option is seen.
+ Returns number of strings consumed. */
+
+int
+cpp_handle_options (pfile, argc, argv)
+ cpp_reader *pfile;
+ int argc;
+ char **argv;
+{
+ int i;
+ int strings_processed;
+ for (i = 0; i < argc; i += strings_processed)
+ {
+ strings_processed = cpp_handle_option (pfile, argc - i, argv + i);
+ if (strings_processed == 0)
+ break;
+ }
+ return i;
+}
+
+static void
+print_help ()
+{
+ cpp_notice ("Usage: %s [switches] input output\n", progname);
+ fputs (_("\
+Switches:\n\
+ -include <file> Include the contents of <file> before other files\n\
+ -imacros <file> Accept definition of macros in <file>\n\
+ -iprefix <path> Specify <path> as a prefix for next two options\n\
+ -iwithprefix <dir> Add <dir> to the end of the system include path\n\
+ -iwithprefixbefore <dir> Add <dir> to the end of the main include path\n\
+ -isystem <dir> Add <dir> to the start of the system include path\n\
+ -idirafter <dir> Add <dir> to the end of the system include path\n\
+ -I <dir> Add <dir> to the end of the main include path\n\
+ -nostdinc Do not search system include directories\n\
+ (dirs specified with -isystem will still be used)\n\
+ -nostdinc++ Do not search system include directories for C++\n\
+ -o <file> Put output into <file>\n\
+ -pedantic Issue all warnings demanded by strict ANSI C\n\
+ -traditional Follow K&R pre-processor behaviour\n\
+ -trigraphs Support ANSI C trigraphs\n\
+ -lang-c Assume that the input sources are in C\n\
+ -lang-c89 Assume that the input sources are in C89\n\
+ -lang-c++ Assume that the input sources are in C++\n\
+ -lang-objc Assume that the input sources are in ObjectiveC\n\
+ -lang-objc++ Assume that the input sources are in ObjectiveC++\n\
+ -lang-asm Assume that the input sources are in assembler\n\
+ -lang-chill Assume that the input sources are in Chill\n\
+ -std=<std name> Specify the conformance standard; one of:\n\
+ gnu89, gnu9x, c89, c9x, iso9899:1990,\n\
+ iso9899:199409, iso9899:199x\n\
+ -+ Allow parsing of C++ style features\n\
+ -w Inhibit warning messages\n\
+ -Wtrigraphs Warn if trigraphs are encountered\n\
+ -Wno-trigraphs Do not warn about trigraphs\n\
+ -Wcomment{s} Warn if one comment starts inside another\n\
+ -Wno-comment{s} Do not warn about comments\n\
+ -Wtraditional Warn if a macro argument is/would be turned into\n\
+ a string if -traditional is specified\n\
+ -Wno-traditional Do not warn about stringification\n\
+ -Wundef Warn if an undefined macro is used by #if\n\
+ -Wno-undef Do not warn about testing undefined macros\n\
+ -Wimport Warn about the use of the #import directive\n\
+ -Wno-import Do not warn about the use of #import\n\
+ -Werror Treat all warnings as errors\n\
+ -Wno-error Do not treat warnings as errors\n\
+ -Wall Enable all preprocessor warnings\n\
+ -M Generate make dependencies\n\
+ -MM As -M, but ignore system header files\n\
+ -MD As -M, but put output in a .d file\n\
+ -MMD As -MD, but ignore system header files\n\
+ -MG Treat missing header file as generated files\n\
+ -g Include #define and #undef directives in the output\n\
+ -D<macro> Define a <macro> with string '1' as its value\n\
+ -D<macro>=<val> Define a <macro> with <val> as its value\n\
+ -A<question> (<answer>) Assert the <answer> to <question>\n\
+ -U<macro> Undefine <macro> \n\
+ -v Display the version number\n\
+ -H Print the name of header files as they are used\n\
+ -C Do not discard comments\n\
+ -dM Display a list of macro definitions active at end\n\
+ -dD Preserve macro definitions in output\n\
+ -dN As -dD except that only the names are preserved\n\
+ -dI Include #include directives in the output\n\
+ -ifoutput Describe skipped code blocks in output \n\
+ -P Do not generate #line directives\n\
+ -$ Do not allow '$' in identifiers\n\
+ -remap Remap file names when including files.\n\
+ -h or --help Display this information\n\
+"), stdout);
+}
diff --git a/contrib/gcc/cpplib.c b/contrib/gcc/cpplib.c
index 5b10349..bcf40e1 100644
--- a/contrib/gcc/cpplib.c
+++ b/contrib/gcc/cpplib.c
@@ -1,5 +1,5 @@
/* CPP Library.
- Copyright (C) 1986, 87, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1986, 87, 89, 92-98, 1999 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -19,153 +19,12 @@ along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
-#ifndef STDC_VALUE
-#define STDC_VALUE 1
-#endif
-
-#include <signal.h>
-
-#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-#endif
-
-#include "gansidecl.h"
#include "cpplib.h"
#include "cpphash.h"
+#include "intl.h"
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
-#endif
-
-extern char *update_path PARAMS ((char *, char *));
-
-#undef MIN
-#undef MAX
-#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-
-/* Find the largest host integer type and set its size and type.
- Watch out: on some crazy hosts `long' is shorter than `int'. */
-
-#ifndef HOST_WIDE_INT
-# if HAVE_INTTYPES_H
-# include <inttypes.h>
-# define HOST_WIDE_INT intmax_t
-# else
-# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \
- && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
-# define HOST_WIDE_INT int
-# else
-# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \
- || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
-# define HOST_WIDE_INT long
-# else
-# define HOST_WIDE_INT long long
-# endif
-# endif
-# endif
-#endif
-
-#ifndef S_ISREG
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
-/* By default, colon separates directories in a path. */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
-#endif
-
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
-#endif
-#ifndef INCLUDE_LEN_FUDGE
-#define INCLUDE_LEN_FUDGE 0
-#endif
-
-/* Symbols to predefine. */
-
-#ifdef CPP_PREDEFINES
-static char *predefs = CPP_PREDEFINES;
-#else
-static char *predefs = "";
-#endif
-
-/* We let tm.h override the types used here, to handle trivial differences
- such as the choice of unsigned int or long unsigned int for size_t.
- When machines start needing nontrivial differences in the size type,
- it would be best to do something here to figure out automatically
- from other information what type to use. */
-
-/* The string value for __SIZE_TYPE__. */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-/* The string value for __PTRDIFF_TYPE__. */
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-/* The string value for __WCHAR_TYPE__. */
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-#define CPP_WCHAR_TYPE(PFILE) \
- (CPP_OPTIONS (PFILE)->cplusplus ? "__wchar_t" : WCHAR_TYPE)
-
-/* The string value for __USER_LABEL_PREFIX__ */
-
-#ifndef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX ""
-#endif
-
-/* The string value for __REGISTER_PREFIX__ */
-
-#ifndef REGISTER_PREFIX
-#define REGISTER_PREFIX ""
-#endif
-
-/* In the definition of a #assert name, this structure forms
- a list of the individual values asserted.
- Each value is itself a list of "tokens".
- These are strings that are compared by name. */
-
-struct tokenlist_list {
- struct tokenlist_list *next;
- struct arglist *tokens;
-};
-
-struct assertion_hashnode {
- struct assertion_hashnode *next; /* double links for easy deletion */
- struct assertion_hashnode *prev;
- /* also, a back pointer to this node's hash
- chain is kept, in case the node is the head
- of the chain and gets deleted. */
- struct assertion_hashnode **bucket_hdr;
- int length; /* length of token, for quick comparison */
- U_CHAR *name; /* the actual name */
- /* List of token-sequences. */
- struct tokenlist_list *value;
-};
-
#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
@@ -174,207 +33,59 @@ struct assertion_hashnode {
#define GETC() CPP_BUF_GET (CPP_BUFFER (pfile))
#define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile))
/* CPP_IS_MACRO_BUFFER is true if the buffer contains macro expansion.
- (Note that it is false while we're expanding marco *arguments*.) */
-#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->cleanup == macro_cleanup)
-
-/* Move all backslash-newline pairs out of embarrassing places.
- Exchange all such pairs following BP
- with any potentially-embarrassing characters that follow them.
- Potentially-embarrassing characters are / and *
- (because a backslash-newline inside a comment delimiter
- would cause it not to be recognized). */
-
-#define NEWLINE_FIX \
- do {while (PEEKC() == '\\' && PEEKN(1) == '\n') FORWARD(2); } while(0)
-
-/* Same, but assume we've already read the potential '\\' into C. */
-#define NEWLINE_FIX1(C) do { \
- while ((C) == '\\' && PEEKC() == '\n') { FORWARD(1); (C) = GETC(); }\
- } while(0)
-
-struct cpp_pending {
- struct cpp_pending *next;
- char *cmd;
- char *arg;
-};
+ (Note that it is false while we're expanding macro *arguments*.) */
+#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
/* Forward declarations. */
-char *xmalloc ();
-extern void cpp_hash_cleanup PARAMS ((cpp_reader *));
-
static char *my_strerror PROTO ((int));
-static void add_import PROTO ((cpp_reader *, int, char *));
-static void append_include_chain PROTO ((cpp_reader *,
- struct file_name_list *,
- struct file_name_list *));
-static void make_assertion PROTO ((cpp_reader *, char *, U_CHAR *));
-static void path_include PROTO ((cpp_reader *, char *));
-static void initialize_builtins PROTO ((cpp_reader *));
-static void initialize_char_syntax PROTO ((struct cpp_options *));
-#if 0
-static void trigraph_pcp ();
-#endif
-static int finclude PROTO ((cpp_reader *, int, char *,
- int, struct file_name_list *));
static void validate_else PROTO ((cpp_reader *, char *));
-static int comp_def_part PROTO ((int, U_CHAR *, int, U_CHAR *,
- int, int));
-#ifdef abort
-extern void fancy_abort ();
-#endif
-static int lookup_import PROTO ((cpp_reader *, char *,
- struct file_name_list *));
-static int redundant_include_p PROTO ((cpp_reader *, char *));
-static int is_system_include PROTO ((cpp_reader *, char *));
-static struct file_name_map *read_name_map PROTO ((cpp_reader *, char *));
-static char *read_filename_string PROTO ((int, FILE *));
-static int open_include_file PROTO ((cpp_reader *, char *,
- struct file_name_list *));
-static int check_macro_name PROTO ((cpp_reader *, U_CHAR *, char *));
-static int compare_defs PROTO ((cpp_reader *,
- DEFINITION *, DEFINITION *));
-static int compare_token_lists PROTO ((struct arglist *,
- struct arglist *));
-static HOST_WIDE_INT eval_if_expression PROTO ((cpp_reader *, U_CHAR *, int));
-static int change_newlines PROTO ((U_CHAR *, int));
-static struct arglist *read_token_list PROTO ((cpp_reader *, int *));
-static void free_token_list PROTO ((struct arglist *));
-static int safe_read PROTO ((int, char *, int));
-static void push_macro_expansion PARAMS ((cpp_reader *,
- U_CHAR *, int, HASHNODE *));
-static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
-extern char *xrealloc ();
-static char *xcalloc PROTO ((unsigned, unsigned));
-static char *savestring PROTO ((char *));
+static HOST_WIDEST_INT eval_if_expression PROTO ((cpp_reader *));
static void conditional_skip PROTO ((cpp_reader *, int,
- enum node_type, U_CHAR *));
-static void skip_if_group PROTO ((cpp_reader *, int));
-static int parse_name PARAMS ((cpp_reader *, int));
-static void print_help PROTO ((void));
+ enum node_type, U_CHAR *));
+static void skip_if_group PROTO ((cpp_reader *));
-/* Last arg to output_line_command. */
-enum file_change_code {same_file, enter_file, leave_file};
+static void parse_name PARAMS ((cpp_reader *, int));
+static void parse_string PARAMS ((cpp_reader *, int));
+static int parse_assertion PARAMS ((cpp_reader *));
/* External declarations. */
-extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader *));
-
-extern char *version_string;
-extern struct tm *localtime ();
-
-struct file_name_list
- {
- struct file_name_list *next;
- char *fname;
- /* If the following is nonzero, it is a macro name.
- Don't include the file again if that macro is defined. */
- U_CHAR *control_macro;
- /* If the following is nonzero, it is a C-language system include
- directory. */
- int c_system_include_path;
- /* Mapping of file names for this directory. */
- struct file_name_map *name_map;
- /* Non-zero if name_map is valid. */
- int got_name_map;
- };
-
-/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
- via the same directory as the file that #included it. */
-#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
-
-/* #include "file" looks in source file dir, then stack. */
-/* #include <file> just looks in the stack. */
-/* -I directories are added to the end, then the defaults are added. */
-/* The */
-static struct default_include {
- char *fname; /* The name of the directory. */
- char *component; /* The component containing the directory */
- int cplusplus; /* Only look here if we're compiling C++. */
- int cxx_aware; /* Includes in this directory don't need to
- be wrapped in extern "C" when compiling
- C++. */
-} include_defaults_array[]
-#ifdef INCLUDE_DEFAULTS
- = INCLUDE_DEFAULTS;
-#else
- = {
- /* Pick up GNU C++ specific include files. */
- { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
- { OLD_GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 },
-#ifdef CROSS_COMPILE
- /* This is the dir for fixincludes. Put it just before
- the files that we fix. */
- { GCC_INCLUDE_DIR, "GCC", 0, 0 },
- /* For cross-compilation, this dir name is generated
- automatically in Makefile.in. */
- { CROSS_INCLUDE_DIR, "GCC",0, 0 },
-#ifdef TOOL_INCLUDE_DIR
- /* This is another place that the target system's headers might be. */
- { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
-#endif
-#else /* not CROSS_COMPILE */
-#ifdef LOCAL_INCLUDE_DIR
- /* This should be /usr/local/include and should come before
- the fixincludes-fixed header files. */
- { LOCAL_INCLUDE_DIR, 0, 0, 1 },
-#endif
-#ifdef TOOL_INCLUDE_DIR
- /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
- Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
- { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
-#endif
- /* This is the dir for fixincludes. Put it just before
- the files that we fix. */
- { GCC_INCLUDE_DIR, "GCC", 0, 0 },
- /* Some systems have an extra dir of include files. */
-#ifdef SYSTEM_INCLUDE_DIR
- { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
-#endif
-#ifndef STANDARD_INCLUDE_COMPONENT
-#define STANDARD_INCLUDE_COMPONENT 0
-#endif
- { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
-#endif /* not CROSS_COMPILE */
- { 0, 0, 0, 0 }
- };
-#endif /* no INCLUDE_DEFAULTS */
+extern HOST_WIDEST_INT cpp_parse_expr PARAMS ((cpp_reader *));
/* `struct directive' defines one #-directive, including how to handle it. */
struct directive {
int length; /* Length of name */
int (*func) /* Function to handle directive */
- PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
+ PARAMS ((cpp_reader *, struct directive *));
char *name; /* Name of directive */
enum node_type type; /* Code which describes which directive. */
- char command_reads_line; /* One if rest of line is read by func. */
};
/* These functions are declared to return int instead of void since they
are going to be placed in a table and some old compilers have trouble with
pointers to functions returning void. */
-static int do_define PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_line PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_include PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_undef PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_error PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_pragma PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_ident PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_if PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_xifdef PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_else PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_elif PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_endif PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
+static int do_define PARAMS ((cpp_reader *, struct directive *));
+static int do_line PARAMS ((cpp_reader *, struct directive *));
+static int do_include PARAMS ((cpp_reader *, struct directive *));
+static int do_undef PARAMS ((cpp_reader *, struct directive *));
+static int do_error PARAMS ((cpp_reader *, struct directive *));
+static int do_pragma PARAMS ((cpp_reader *, struct directive *));
+static int do_ident PARAMS ((cpp_reader *, struct directive *));
+static int do_if PARAMS ((cpp_reader *, struct directive *));
+static int do_xifdef PARAMS ((cpp_reader *, struct directive *));
+static int do_else PARAMS ((cpp_reader *, struct directive *));
+static int do_elif PARAMS ((cpp_reader *, struct directive *));
+static int do_endif PARAMS ((cpp_reader *, struct directive *));
#ifdef SCCS_DIRECTIVE
-static int do_sccs PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
+static int do_sccs PARAMS ((cpp_reader *, struct directive *));
#endif
-static int do_once PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_assert PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_unassert PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
-static int do_warning PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHAR *));
+static int do_assert PARAMS ((cpp_reader *, struct directive *));
+static int do_unassert PARAMS ((cpp_reader *, struct directive *));
+static int do_warning PARAMS ((cpp_reader *, struct directive *));
#define IS_INCLUDE_DIRECTIVE_TYPE(t) \
((int) T_INCLUDE <= (int) (t) && (int) (t) <= (int) T_IMPORT)
@@ -383,89 +94,37 @@ static int do_warning PARAMS ((cpp_reader *, struct directive *, U_CHAR *, U_CHA
The initialize_builtins function assumes #define is the very first. */
static struct directive directive_table[] = {
- { 6, do_define, "define", T_DEFINE},
- { 5, do_xifdef, "ifdef", T_IFDEF, 1},
- { 6, do_xifdef, "ifndef", T_IFNDEF, 1},
- { 7, do_include, "include", T_INCLUDE, 1},
- { 12, do_include, "include_next", T_INCLUDE_NEXT, 1},
- { 6, do_include, "import", T_IMPORT, 1},
- { 5, do_endif, "endif", T_ENDIF, 1},
- { 4, do_else, "else", T_ELSE, 1},
- { 2, do_if, "if", T_IF, 1},
- { 4, do_elif, "elif", T_ELIF, 1},
- { 5, do_undef, "undef", T_UNDEF},
- { 5, do_error, "error", T_ERROR},
- { 7, do_warning, "warning", T_WARNING},
- { 6, do_pragma, "pragma", T_PRAGMA},
- { 4, do_line, "line", T_LINE, 1},
- { 5, do_ident, "ident", T_IDENT, 1},
+ { 6, do_define, "define", T_DEFINE },
+ { 5, do_xifdef, "ifdef", T_IFDEF },
+ { 6, do_xifdef, "ifndef", T_IFNDEF },
+ { 7, do_include, "include", T_INCLUDE },
+ { 12, do_include, "include_next", T_INCLUDE_NEXT },
+ { 6, do_include, "import", T_IMPORT },
+ { 5, do_endif, "endif", T_ENDIF },
+ { 4, do_else, "else", T_ELSE },
+ { 2, do_if, "if", T_IF },
+ { 4, do_elif, "elif", T_ELIF },
+ { 5, do_undef, "undef", T_UNDEF },
+ { 5, do_error, "error", T_ERROR },
+ { 7, do_warning, "warning", T_WARNING },
+ { 6, do_pragma, "pragma", T_PRAGMA },
+ { 4, do_line, "line", T_LINE },
+ { 5, do_ident, "ident", T_IDENT },
#ifdef SCCS_DIRECTIVE
- { 4, do_sccs, "sccs", T_SCCS},
+ { 4, do_sccs, "sccs", T_SCCS },
#endif
- { 6, do_assert, "assert", T_ASSERT, 1},
- { 8, do_unassert, "unassert", T_UNASSERT, 1},
- { -1, 0, "", T_UNUSED},
+ { 6, do_assert, "assert", T_ASSERT },
+ { 8, do_unassert, "unassert", T_UNASSERT },
+ { -1, 0, "", T_UNUSED }
};
-
-/* table to tell if char can be part of a C identifier. */
-U_CHAR is_idchar[256];
-/* table to tell if char can be first char of a c identifier. */
-U_CHAR is_idstart[256];
-/* table to tell if c is horizontal space. */
-U_CHAR is_hor_space[256];
-/* table to tell if c is horizontal or vertical space. */
-static U_CHAR is_space[256];
-
-/* Initialize syntactic classifications of characters. */
-
-static void
-initialize_char_syntax (opts)
- struct cpp_options *opts;
-{
- register int i;
-
- /*
- * Set up is_idchar and is_idstart tables. These should be
- * faster than saying (is_alpha (c) || c == '_'), etc.
- * Set up these things before calling any routines tthat
- * refer to them.
- */
- for (i = 'a'; i <= 'z'; i++) {
- is_idchar[i - 'a' + 'A'] = 1;
- is_idchar[i] = 1;
- is_idstart[i - 'a' + 'A'] = 1;
- is_idstart[i] = 1;
- }
- for (i = '0'; i <= '9'; i++)
- is_idchar[i] = 1;
- is_idchar['_'] = 1;
- is_idstart['_'] = 1;
- is_idchar['$'] = opts->dollars_in_ident;
- is_idstart['$'] = opts->dollars_in_ident;
-
- /* horizontal space table */
- is_hor_space[' '] = 1;
- is_hor_space['\t'] = 1;
- is_hor_space['\v'] = 1;
- is_hor_space['\f'] = 1;
- is_hor_space['\r'] = 1;
-
- is_space[' '] = 1;
- is_space['\t'] = 1;
- is_space['\v'] = 1;
- is_space['\f'] = 1;
- is_space['\n'] = 1;
- is_space['\r'] = 1;
-}
-
/* Place into PFILE a quoted string representing the string SRC.
Caller must reserve enough space in pfile->token_buffer. */
-static void
+void
quote_string (pfile, src)
cpp_reader *pfile;
- char *src;
+ const char *src;
{
U_CHAR c;
@@ -510,13 +169,10 @@ cpp_grow_buffer (pfile, n)
CPP_SET_WRITTEN (pfile, old_written);
}
-
-/*
- * process a given definition string, for initialization
- * If STR is just an identifier, define it with value 1.
- * If STR has anything after the identifier, then it should
- * be identifier=definition.
- */
+/* Process the string STR as if it appeared as the body of a #define
+ If STR is just an identifier, define it with value 1.
+ If STR has anything after the identifier, then it should
+ be identifier=definition. */
void
cpp_define (pfile, str)
@@ -524,267 +180,52 @@ cpp_define (pfile, str)
U_CHAR *str;
{
U_CHAR *buf, *p;
+ size_t count;
- buf = str;
- p = str;
- if (!is_idstart[*p])
- {
- cpp_error (pfile, "malformed option `-D %s'", str);
- return;
- }
- while (is_idchar[*++p])
- ;
- if (*p == 0)
- {
- buf = (U_CHAR *) alloca (p - buf + 4);
- strcpy ((char *)buf, str);
- strcat ((char *)buf, " 1");
- }
- else if (*p != '=')
+ /* Copy the entire option so we can modify it. */
+ count = strlen (str) + 3;
+ buf = (U_CHAR *) alloca (count);
+ memcpy (buf, str, count - 2);
+ /* Change the first "=" in the string to a space. If there is none,
+ tack " 1" on the end. */
+ p = (U_CHAR *) strchr (buf, '=');
+ if (p)
{
- cpp_error (pfile, "malformed option `-D %s'", str);
- return;
+ *p = ' ';
+ count -= 2;
}
else
- {
- U_CHAR *q;
- /* Copy the entire option so we can modify it. */
- buf = (U_CHAR *) alloca (2 * strlen (str) + 1);
- strncpy (buf, str, p - str);
- /* Change the = to a space. */
- buf[p - str] = ' ';
- /* Scan for any backslash-newline and remove it. */
- p++;
- q = &buf[p - str];
- while (*p)
- {
- if (*p == '\\' && p[1] == '\n')
- p += 2;
- else
- *q++ = *p++;
- }
- *q = 0;
- }
+ strcpy (&buf[count-3], " 1");
- do_define (pfile, NULL, buf, buf + strlen (buf));
-}
-
-/* Process the string STR as if it appeared as the body of a #assert.
- OPTION is the option name for which STR was the argument. */
-
-static void
-make_assertion (pfile, option, str)
- cpp_reader *pfile;
- char *option;
- U_CHAR *str;
-{
- U_CHAR *buf, *p, *q;
-
- /* Copy the entire option so we can modify it. */
- buf = (U_CHAR *) alloca (strlen (str) + 1);
- strcpy ((char *) buf, str);
- /* Scan for any backslash-newline and remove it. */
- p = q = buf;
- while (*p) {
-#if 0
- if (*p == '\\' && p[1] == '\n')
- p += 2;
- else
-#endif
- *q++ = *p++;
- }
- *q = 0;
-
- p = buf;
- if (!is_idstart[*p]) {
- cpp_error (pfile, "malformed option `%s %s'", option, str);
- return;
- }
- while (is_idchar[*++p])
- ;
- while (*p == ' ' || *p == '\t') p++;
- if (! (*p == 0 || *p == '(')) {
- cpp_error (pfile, "malformed option `%s %s'", option, str);
- return;
- }
-
- if (cpp_push_buffer (pfile, buf, strlen (buf)) != NULL)
+ if (cpp_push_buffer (pfile, buf, count - 1) != NULL)
{
- do_assert (pfile, NULL, NULL, NULL);
+ do_define (pfile, NULL);
cpp_pop_buffer (pfile);
}
}
-
-/* Append a chain of `struct file_name_list's
- to the end of the main include chain.
- FIRST is the beginning of the chain to append, and LAST is the end. */
-static void
-append_include_chain (pfile, first, last)
- cpp_reader *pfile;
- struct file_name_list *first, *last;
-{
- struct cpp_options *opts = CPP_OPTIONS (pfile);
- struct file_name_list *dir;
-
- if (!first || !last)
- return;
-
- if (opts->include == 0)
- opts->include = first;
- else
- opts->last_include->next = first;
-
- if (opts->first_bracket_include == 0)
- opts->first_bracket_include = first;
-
- for (dir = first; ; dir = dir->next) {
- int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
- if (len > pfile->max_include_len)
- pfile->max_include_len = len;
- if (dir == last)
- break;
- }
-
- last->next = NULL;
- opts->last_include = last;
-}
-
-/* Add output to `deps_buffer' for the -M switch.
- STRING points to the text to be output.
- SPACER is ':' for targets, ' ' for dependencies, zero for text
- to be inserted literally. */
-
-static void
-deps_output (pfile, string, spacer)
+/* Process the string STR as if it appeared as the body of a #assert. */
+void
+cpp_assert (pfile, str)
cpp_reader *pfile;
- char *string;
- int spacer;
+ U_CHAR *str;
{
- int size = strlen (string);
-
- if (size == 0)
- return;
-
-#ifndef MAX_OUTPUT_COLUMNS
-#define MAX_OUTPUT_COLUMNS 72
-#endif
- if (spacer
- && pfile->deps_column > 0
- && (pfile->deps_column + size) > MAX_OUTPUT_COLUMNS)
- {
- deps_output (pfile, " \\\n ", 0);
- pfile->deps_column = 0;
- }
-
- if (pfile->deps_size + size + 8 > pfile->deps_allocated_size)
+ if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
{
- pfile->deps_allocated_size = (pfile->deps_size + size + 50) * 2;
- pfile->deps_buffer = (char *) xrealloc (pfile->deps_buffer,
- pfile->deps_allocated_size);
+ do_assert (pfile, NULL);
+ cpp_pop_buffer (pfile);
}
- if (spacer == ' ' && pfile->deps_column > 0)
- pfile->deps_buffer[pfile->deps_size++] = ' ';
- bcopy (string, &pfile->deps_buffer[pfile->deps_size], size);
- pfile->deps_size += size;
- pfile->deps_column += size;
- if (spacer == ':')
- pfile->deps_buffer[pfile->deps_size++] = ':';
- pfile->deps_buffer[pfile->deps_size] = 0;
}
-
-/* Given a colon-separated list of file names PATH,
- add all the names to the search path for include files. */
-
-static void
-path_include (pfile, path)
- cpp_reader *pfile;
- char *path;
-{
- char *p;
-
- p = path;
-
- if (*p)
- while (1) {
- char *q = p;
- char *name;
- struct file_name_list *dirtmp;
-
- /* Find the end of this name. */
- while (*q != 0 && *q != PATH_SEPARATOR) q++;
- if (p == q) {
- /* An empty name in the path stands for the current directory. */
- name = (char *) xmalloc (2);
- name[0] = '.';
- name[1] = 0;
- } else {
- /* Otherwise use the directory that is named. */
- name = (char *) xmalloc (q - p + 1);
- bcopy (p, name, q - p);
- name[q - p] = 0;
- }
- dirtmp = (struct file_name_list *)
- xmalloc (sizeof (struct file_name_list));
- dirtmp->next = 0; /* New one goes on the end */
- dirtmp->control_macro = 0;
- dirtmp->c_system_include_path = 0;
- dirtmp->fname = name;
- dirtmp->got_name_map = 0;
- append_include_chain (pfile, dirtmp, dirtmp);
-
- /* Advance past this name. */
- p = q;
- if (*p == 0)
- break;
- /* Skip the colon. */
- p++;
- }
-}
-
-void
-cpp_options_init (opts)
- cpp_options *opts;
-{
- bzero ((char *) opts, sizeof *opts);
- opts->in_fname = NULL;
- opts->out_fname = NULL;
-
- /* Initialize is_idchar to allow $. */
- opts->dollars_in_ident = 1;
- initialize_char_syntax (opts);
-
- opts->no_line_commands = 0;
- opts->no_trigraphs = 1;
- opts->put_out_comments = 0;
- opts->print_include_names = 0;
- opts->dump_macros = dump_none;
- opts->no_output = 0;
- opts->remap = 0;
- opts->cplusplus = 0;
- opts->cplusplus_comments = 1;
-
- opts->verbose = 0;
- opts->objc = 0;
- opts->lang_asm = 0;
- opts->for_lint = 0;
- opts->chill = 0;
- opts->pedantic_errors = 0;
- opts->inhibit_warnings = 0;
- opts->warn_comments = 0;
- opts->warn_import = 1;
- opts->warnings_are_errors = 0;
-}
-enum cpp_token
+static enum cpp_token
null_underflow (pfile)
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
return CPP_EOF;
}
-int
+static int
null_cleanup (pbuf, pfile)
cpp_buffer *pbuf ATTRIBUTE_UNUSED;
cpp_reader *pfile ATTRIBUTE_UNUSED;
@@ -792,97 +233,148 @@ null_cleanup (pbuf, pfile)
return 0;
}
-int
-macro_cleanup (pbuf, pfile)
- cpp_buffer *pbuf;
- cpp_reader *pfile ATTRIBUTE_UNUSED;
-{
- HASHNODE *macro = (HASHNODE *) pbuf->data;
- if (macro->type == T_DISABLED)
- macro->type = T_MACRO;
- if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
- free (pbuf->buf);
- return 0;
-}
+/* Skip a comment - C, C++, or Chill style. M is the first character
+ of the comment marker. If this really is a comment, skip to its
+ end and return ' '. If we hit end-of-file before end-of-comment,
+ return EOF. If this is not a comment, return M (which will be
+ '/' or '-'). */
-int
-file_cleanup (pbuf, pfile)
- cpp_buffer *pbuf;
- cpp_reader *pfile ATTRIBUTE_UNUSED;
+static int
+skip_comment (pfile, m)
+ cpp_reader *pfile;
+ int m;
{
- if (pbuf->buf)
+ if (m == '/' && PEEKC() == '*')
{
- free (pbuf->buf);
- pbuf->buf = 0;
+ int c, prev_c = -1;
+ long line, col;
+
+ FORWARD(1);
+ cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
+ for (;;)
+ {
+ c = GETC ();
+ if (c == EOF)
+ {
+ cpp_error_with_line (pfile, line, col, "unterminated comment");
+ return EOF;
+ }
+ else if (c == '\n' || c == '\r')
+ /* \r cannot be a macro escape marker here. */
+ CPP_BUMP_LINE (pfile);
+ else if (c == '/' && prev_c == '*')
+ return ' ';
+ else if (c == '*' && prev_c == '/'
+ && CPP_OPTIONS (pfile)->warn_comments)
+ cpp_warning (pfile, "`/*' within comment");
+
+ prev_c = c;
+ }
}
- return 0;
+ else if ((m == '/' && PEEKC() == '/'
+ && CPP_OPTIONS (pfile)->cplusplus_comments)
+ || (m == '-' && PEEKC() == '-'
+ && CPP_OPTIONS (pfile)->chill))
+ {
+ FORWARD(1);
+ for (;;)
+ {
+ int c = GETC ();
+ if (c == EOF)
+ return ' '; /* Allow // to be terminated by EOF. */
+ if (c == '\n')
+ {
+ /* Don't consider final '\n' to be part of comment. */
+ FORWARD(-1);
+ return ' ';
+ }
+ else if (c == '\r')
+ /* \r cannot be a macro escape marker here. */
+ CPP_BUMP_LINE (pfile);
+ }
+ }
+ else
+ return m;
}
-/* Assuming we have read '/'.
- If this is the start of a comment (followed by '*' or '/'),
- skip to the end of the comment, and return ' '.
- Return EOF if we reached the end of file before the end of the comment.
- If not the start of a comment, return '/'. */
-
+/* Identical to skip_comment except that it copies the comment into the
+ token_buffer. This is used if put_out_comments. */
static int
-skip_comment (pfile, linep)
+copy_comment (pfile, m)
cpp_reader *pfile;
- long *linep;
+ int m;
{
- int c = 0;
- while (PEEKC() == '\\' && PEEKN(1) == '\n')
- {
- if (linep)
- (*linep)++;
- FORWARD(2);
- }
- if (PEEKC() == '*')
+ if (m == '/' && PEEKC() == '*')
{
+ int c, prev_c = -1;
+ long line, col;
+
+ CPP_PUTC (pfile, '/');
+ CPP_PUTC (pfile, '*');
FORWARD(1);
+ cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
for (;;)
{
- int prev_c = c;
c = GETC ();
if (c == EOF)
- return EOF;
- while (c == '\\' && PEEKC() == '\n')
{
- if (linep)
- (*linep)++;
- FORWARD(1), c = GETC();
+ cpp_error_with_line (pfile, line, col, "unterminated comment");
+ /* We must pretend this was a legitimate comment, so that the
+ output in token_buffer is not passed back tagged CPP_POP. */
+ return ' ';
+ }
+ else if (c == '\r')
+ {
+ /* \r cannot be a macro escape marker here. */
+ CPP_BUMP_LINE (pfile);
+ continue;
+ }
+
+ CPP_PUTC (pfile, c);
+ if (c == '\n')
+ {
+ pfile->lineno++;
+ CPP_BUMP_LINE (pfile);
}
- if (prev_c == '*' && c == '/')
+ else if (c == '/' && prev_c == '*')
return ' ';
- if (c == '\n' && linep)
- (*linep)++;
+ else if (c == '*' && prev_c == '/'
+ && CPP_OPTIONS (pfile)->warn_comments)
+ cpp_warning (pfile, "`/*' within comment");
+
+ prev_c = c;
}
}
- else if (PEEKC() == '/' && CPP_OPTIONS (pfile)->cplusplus_comments)
+ else if ((m == '/' && PEEKC() == '/'
+ && CPP_OPTIONS (pfile)->cplusplus_comments)
+ || (m == '-' && PEEKC() == '-'
+ && CPP_OPTIONS (pfile)->chill))
{
+ CPP_PUTC (pfile, m);
+ CPP_PUTC (pfile, m);
FORWARD(1);
for (;;)
{
- c = GETC ();
+ int c = GETC ();
if (c == EOF)
- return ' '; /* Allow // to be terminated by EOF. */
- while (c == '\\' && PEEKC() == '\n')
- {
- FORWARD(1);
- c = GETC();
- if (linep)
- (*linep)++;
- }
- if (c == '\n')
+ return ' '; /* Allow line comments to be terminated by EOF. */
+ else if (c == '\n')
{
/* Don't consider final '\n' to be part of comment. */
FORWARD(-1);
return ' ';
}
+ else if (c == '\r')
+ /* \r cannot be a macro escape marker here. */
+ CPP_BUMP_LINE (pfile);
+
+ CPP_PUTC (pfile, c);
}
}
else
- return '/';
-}
+ return m;
+}
+
/* Skip whitespace \-newline and comments. Does not macro-expand. */
@@ -890,35 +382,44 @@ void
cpp_skip_hspace (pfile)
cpp_reader *pfile;
{
+ int c;
while (1)
{
- int c = PEEKC();
+ c = GETC();
if (c == EOF)
- return; /* FIXME */
- if (is_hor_space[c])
+ return;
+ else if (is_hor_space[c])
{
if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "%s in preprocessing directive",
c == '\f' ? "formfeed" : "vertical tab");
- FORWARD(1);
}
- else if (c == '/')
+ else if (c == '\r')
{
- FORWARD (1);
- c = skip_comment (pfile, NULL);
- if (c == '/')
- FORWARD(-1);
- if (c == EOF || c == '/')
+ /* \r is a backslash-newline marker if !has_escapes, and
+ a deletable-whitespace or no-reexpansion marker otherwise. */
+ if (CPP_BUFFER (pfile)->has_escapes)
+ {
+ if (PEEKC() == ' ')
+ FORWARD(1);
+ else
+ break;
+ }
+ else
+ CPP_BUFFER (pfile)->lineno++;
+ }
+ else if (c == '/' || c == '-')
+ {
+ c = skip_comment (pfile, c);
+ if (c == EOF)
return;
+ else if (c != ' ')
+ break;
}
- else if (c == '\\' && PEEKN(1) == '\n') {
- FORWARD(2);
- }
- else if (c == '@' && CPP_BUFFER (pfile)->has_escapes
- && is_hor_space[PEEKN(1)])
- FORWARD(2);
- else return;
+ else
+ break;
}
+ FORWARD(-1);
}
/* Read the rest of the current line.
@@ -928,30 +429,41 @@ static void
copy_rest_of_line (pfile)
cpp_reader *pfile;
{
- struct cpp_options *opts = CPP_OPTIONS (pfile);
for (;;)
{
int c = GETC();
- int nextc;
switch (c)
{
+ case '\n':
+ FORWARD(-1);
case EOF:
- goto end_directive;
- case '\\':
- if (PEEKC() == '\n')
+ CPP_NUL_TERMINATE (pfile);
+ return;
+
+ case '\r':
+ if (CPP_BUFFER (pfile)->has_escapes)
+ break;
+ else
{
- FORWARD (1);
+ CPP_BUFFER (pfile)->lineno++;
continue;
}
case '\'':
case '\"':
- goto scan_directive_token;
- break;
+ parse_string (pfile, c);
+ continue;
case '/':
- nextc = PEEKC();
- if (nextc == '*' || (opts->cplusplus_comments && nextc == '/'))
- goto scan_directive_token;
+ if (PEEKC() == '*' && CPP_TRADITIONAL (pfile))
+ {
+ CPP_PUTS (pfile, "/**/", 4);
+ skip_comment (pfile, c);
+ continue;
+ }
+ /* else fall through */
+ case '-':
+ c = skip_comment (pfile, c);
break;
+
case '\f':
case '\v':
if (CPP_PEDANTIC (pfile))
@@ -959,20 +471,15 @@ copy_rest_of_line (pfile)
c == '\f' ? "formfeed" : "vertical tab");
break;
- case '\n':
- FORWARD(-1);
- goto end_directive;
- scan_directive_token:
- FORWARD(-1);
- cpp_get_token (pfile);
- continue;
}
CPP_PUTC (pfile, c);
}
- end_directive: ;
- CPP_NUL_TERMINATE (pfile);
}
+/* FIXME: It is almost definitely a performance win to make this do
+ the scan itself. >75% of calls to copy_r_o_l are from here or
+ skip_if_group, which means the common case is to copy stuff into the
+ token_buffer only to discard it. */
void
skip_rest_of_line (pfile)
cpp_reader *pfile;
@@ -985,14 +492,14 @@ skip_rest_of_line (pfile)
/* Handle a possible # directive.
'#' has already been read. */
-int
+static int
handle_directive (pfile)
cpp_reader *pfile;
-{ int c;
+{
+ int c;
register struct directive *kt;
int ident_length;
- long after_ident;
- U_CHAR *ident, *line_end;
+ U_CHAR *ident;
long old_written = CPP_WRITTEN (pfile);
cpp_skip_hspace (pfile);
@@ -1003,8 +510,8 @@ handle_directive (pfile)
/* Handle # followed by a line number. */
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "`#' followed by integer");
- do_line (pfile, NULL, NULL, NULL);
- goto done_a_directive;
+ do_line (pfile, NULL);
+ return 1;
}
/* Now find the directive name. */
@@ -1012,626 +519,64 @@ handle_directive (pfile)
parse_name (pfile, GETC());
ident = pfile->token_buffer + old_written + 1;
ident_length = CPP_PWRITTEN (pfile) - ident;
- if (ident_length == 0 && PEEKC() == '\n')
+ if (ident_length == 0)
{
/* A line of just `#' becomes blank. */
- goto done_a_directive;
- }
-
-#if 0
- if (ident_length == 0 || !is_idstart[*ident]) {
- U_CHAR *p = ident;
- while (is_idchar[*p]) {
- if (*p < '0' || *p > '9')
- break;
- p++;
- }
- /* Avoid error for `###' and similar cases unless -pedantic. */
- if (p == ident) {
- while (*p == '#' || is_hor_space[*p]) p++;
- if (*p == '\n') {
- if (pedantic && !lang_asm)
- cpp_warning (pfile, "invalid preprocessor directive");
+ if (PEEKC() == '\n')
+ return 1;
+ else
return 0;
- }
}
- if (!lang_asm)
- cpp_error (pfile, "invalid preprocessor directive name");
-
- return 0;
- }
-#endif
/*
* Decode the keyword and call the appropriate expansion
* routine, after moving the input pointer up to the next line.
*/
- for (kt = directive_table; ; kt++) {
- if (kt->length <= 0)
- goto not_a_directive;
- if (kt->length == ident_length && !strncmp (kt->name, ident, ident_length))
- break;
- }
-
- if (kt->command_reads_line)
- after_ident = 0;
- else
+ for (kt = directive_table; ; kt++)
{
- /* Nonzero means do not delete comments within the directive.
- #define needs this when -traditional. */
- int comments = CPP_TRADITIONAL (pfile) && kt->type == T_DEFINE;
- int save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
- CPP_OPTIONS (pfile)->put_out_comments = comments;
- after_ident = CPP_WRITTEN (pfile);
- copy_rest_of_line (pfile);
- CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
+ if (kt->length <= 0)
+ return 0;
+ if (kt->length == ident_length
+ && !strncmp (kt->name, ident, ident_length))
+ break;
}
- /* We may want to pass through #define, #pragma, and #include.
- Other directives may create output, but we don't want the directive
- itself out, so we pop it now. For example conditionals may emit
- #failed ... #endfailed stuff. But note that popping the buffer
- means the parameters to kt->func may point after pfile->limit
- so these parameters are invalid as soon as something gets appended
- to the token_buffer. */
-
- line_end = CPP_PWRITTEN (pfile);
- if (! (kt->type == T_DEFINE
- || kt->type == T_PRAGMA
- || (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)
- && CPP_OPTIONS (pfile)->dump_includes)))
- CPP_SET_WRITTEN (pfile, old_written);
-
- (*kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);
-
- if (kt->type == T_DEFINE)
- {
- if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
- {
- /* Skip "#define". */
- U_CHAR *p = pfile->token_buffer + old_written + 7;
-
- SKIP_WHITE_SPACE (p);
- while (is_idchar[*p]) p++;
- pfile->limit = p;
- CPP_PUTC (pfile, '\n');
- }
- else if (CPP_OPTIONS (pfile)->dump_macros != dump_definitions)
- CPP_SET_WRITTEN (pfile, old_written);
- }
+ CPP_SET_WRITTEN (pfile, old_written);
+ (*kt->func) (pfile, kt);
- done_a_directive:
return 1;
-
- not_a_directive:
- return 0;
}
/* Pass a directive through to the output file.
BUF points to the contents of the directive, as a contiguous string.
- LIMIT points to the first character past the end of the directive.
+ LEN is the length of the string pointed to by BUF.
KEYWORD is the keyword-table entry for the directive. */
static void
-pass_thru_directive (buf, limit, pfile, keyword)
- U_CHAR *buf, *limit;
+pass_thru_directive (buf, len, pfile, keyword)
+ U_CHAR *buf;
+ size_t len;
cpp_reader *pfile;
struct directive *keyword;
{
register unsigned keyword_length = keyword->length;
- CPP_RESERVE (pfile, 1 + keyword_length + (limit - buf));
+ CPP_RESERVE (pfile, 1 + keyword_length + len);
CPP_PUTC_Q (pfile, '#');
CPP_PUTS_Q (pfile, keyword->name, keyword_length);
- if (limit != buf && buf[0] != ' ')
+ if (len != 0 && buf[0] != ' ')
CPP_PUTC_Q (pfile, ' ');
- CPP_PUTS_Q (pfile, buf, limit - buf);
-#if 0
- CPP_PUTS_Q (pfile, '\n');
- /* Count the line we have just made in the output,
- to get in sync properly. */
- pfile->lineno++;
-#endif
-}
-
-/* The arglist structure is built by do_define to tell
- collect_definition where the argument names begin. That
- is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
- would contain pointers to the strings x, y, and z.
- Collect_definition would then build a DEFINITION node,
- with reflist nodes pointing to the places x, y, and z had
- appeared. So the arglist is just convenience data passed
- between these two routines. It is not kept around after
- the current #define has been processed and entered into the
- hash table. */
-
-struct arglist {
- struct arglist *next;
- U_CHAR *name;
- int length;
- int argno;
- char rest_args;
-};
-
-/* Read a replacement list for a macro with parameters.
- Build the DEFINITION structure.
- Reads characters of text starting at BUF until END.
- ARGLIST specifies the formal parameters to look for
- in the text of the definition; NARGS is the number of args
- in that list, or -1 for a macro name that wants no argument list.
- MACRONAME is the macro name itself (so we can avoid recursive expansion)
- and NAMELEN is its length in characters.
-
- Note that comments, backslash-newlines, and leading white space
- have already been deleted from the argument. */
-
-static DEFINITION *
-collect_expansion (pfile, buf, limit, nargs, arglist)
- cpp_reader *pfile;
- U_CHAR *buf, *limit;
- int nargs;
- struct arglist *arglist;
-{
- DEFINITION *defn;
- register U_CHAR *p, *lastp, *exp_p;
- struct reflist *endpat = NULL;
- /* Pointer to first nonspace after last ## seen. */
- U_CHAR *concat = 0;
- /* Pointer to first nonspace after last single-# seen. */
- U_CHAR *stringify = 0;
- int maxsize;
- int expected_delimiter = '\0';
-
- /* Scan thru the replacement list, ignoring comments and quoted
- strings, picking up on the macro calls. It does a linear search
- thru the arg list on every potential symbol. Profiling might say
- that something smarter should happen. */
-
- if (limit < buf)
- abort ();
-
- /* Find the beginning of the trailing whitespace. */
- p = buf;
- while (p < limit && is_space[limit[-1]]) limit--;
-
- /* Allocate space for the text in the macro definition.
- Leading and trailing whitespace chars need 2 bytes each.
- Each other input char may or may not need 1 byte,
- so this is an upper bound. The extra 5 are for invented
- leading and trailing newline-marker and final null. */
- maxsize = (sizeof (DEFINITION)
- + (limit - p) + 5);
- /* Occurrences of '@' get doubled, so allocate extra space for them. */
- while (p < limit)
- if (*p++ == '@')
- maxsize++;
- defn = (DEFINITION *) xcalloc (1, maxsize);
-
- defn->nargs = nargs;
- exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
- lastp = exp_p;
-
- p = buf;
-
- /* Add one initial space escape-marker to prevent accidental
- token-pasting (often removed by macroexpand). */
- *exp_p++ = '@';
- *exp_p++ = ' ';
-
- if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
- cpp_error (pfile, "`##' at start of macro definition");
- p += 2;
- }
-
- /* Process the main body of the definition. */
- while (p < limit) {
- int skipped_arg = 0;
- register U_CHAR c = *p++;
-
- *exp_p++ = c;
-
- if (!CPP_TRADITIONAL (pfile)) {
- switch (c) {
- case '\'':
- case '\"':
- if (expected_delimiter != '\0') {
- if (c == expected_delimiter)
- expected_delimiter = '\0';
- } else
- expected_delimiter = c;
- break;
-
- case '\\':
- if (p < limit && expected_delimiter) {
- /* In a string, backslash goes through
- and makes next char ordinary. */
- *exp_p++ = *p++;
- }
- break;
-
- case '@':
- /* An '@' in a string or character constant stands for itself,
- and does not need to be escaped. */
- if (!expected_delimiter)
- *exp_p++ = c;
- break;
-
- case '#':
- /* # is ordinary inside a string. */
- if (expected_delimiter)
- break;
- if (p < limit && *p == '#') {
- /* ##: concatenate preceding and following tokens. */
- /* Take out the first #, discard preceding whitespace. */
- exp_p--;
- while (exp_p > lastp && is_hor_space[exp_p[-1]])
- --exp_p;
- /* Skip the second #. */
- p++;
- /* Discard following whitespace. */
- SKIP_WHITE_SPACE (p);
- concat = p;
- if (p == limit)
- cpp_error (pfile, "`##' at end of macro definition");
- } else if (nargs >= 0) {
- /* Single #: stringify following argument ref.
- Don't leave the # in the expansion. */
- exp_p--;
- SKIP_WHITE_SPACE (p);
- if (p == limit || ! is_idstart[*p]
- || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))
- cpp_error (pfile,
- "`#' operator is not followed by a macro argument name");
- else
- stringify = p;
- }
- break;
- }
- } else {
- /* In -traditional mode, recognize arguments inside strings and
- character constants, and ignore special properties of #.
- Arguments inside strings are considered "stringified", but no
- extra quote marks are supplied. */
- switch (c) {
- case '\'':
- case '\"':
- if (expected_delimiter != '\0') {
- if (c == expected_delimiter)
- expected_delimiter = '\0';
- } else
- expected_delimiter = c;
- break;
-
- case '\\':
- /* Backslash quotes delimiters and itself, but not macro args. */
- if (expected_delimiter != 0 && p < limit
- && (*p == expected_delimiter || *p == '\\')) {
- *exp_p++ = *p++;
- continue;
- }
- break;
-
- case '/':
- if (expected_delimiter != '\0') /* No comments inside strings. */
- break;
- if (*p == '*') {
- /* If we find a comment that wasn't removed by handle_directive,
- this must be -traditional. So replace the comment with
- nothing at all. */
- exp_p--;
- p += 1;
- while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
- p++;
-#if 0
- /* Mark this as a concatenation-point, as if it had been ##. */
- concat = p;
-#endif
- }
- break;
- }
- }
-
- /* Handle the start of a symbol. */
- if (is_idchar[c] && nargs > 0) {
- U_CHAR *id_beg = p - 1;
- int id_len;
-
- --exp_p;
- while (p != limit && is_idchar[*p]) p++;
- id_len = p - id_beg;
-
- if (is_idstart[c]
- && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
- register struct arglist *arg;
-
- for (arg = arglist; arg != NULL; arg = arg->next) {
- struct reflist *tpat;
-
- if (arg->name[0] == c
- && arg->length == id_len
- && strncmp (arg->name, id_beg, id_len) == 0) {
- if (expected_delimiter && CPP_OPTIONS (pfile)->warn_stringify) {
- if (CPP_TRADITIONAL (pfile)) {
- cpp_warning (pfile, "macro argument `%.*s' is stringified.",
- id_len, arg->name);
- } else {
- cpp_warning (pfile,
- "macro arg `%.*s' would be stringified with -traditional.",
- id_len, arg->name);
- }
- }
- /* If ANSI, don't actually substitute inside a string. */
- if (!CPP_TRADITIONAL (pfile) && expected_delimiter)
- break;
- /* make a pat node for this arg and append it to the end of
- the pat list */
- tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
- tpat->next = NULL;
- tpat->raw_before = concat == id_beg;
- tpat->raw_after = 0;
- tpat->rest_args = arg->rest_args;
- tpat->stringify = (CPP_TRADITIONAL (pfile)
- ? expected_delimiter != '\0'
- : stringify == id_beg);
-
- if (endpat == NULL)
- defn->pattern = tpat;
- else
- endpat->next = tpat;
- endpat = tpat;
-
- tpat->argno = arg->argno;
- tpat->nchars = exp_p - lastp;
- {
- register U_CHAR *p1 = p;
- SKIP_WHITE_SPACE (p1);
- if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
- tpat->raw_after = 1;
- }
- lastp = exp_p; /* place to start copying from next time */
- skipped_arg = 1;
- break;
- }
- }
- }
-
- /* If this was not a macro arg, copy it into the expansion. */
- if (! skipped_arg) {
- register U_CHAR *lim1 = p;
- p = id_beg;
- while (p != lim1)
- *exp_p++ = *p++;
- if (stringify == id_beg)
- cpp_error (pfile,
- "`#' operator should be followed by a macro argument name");
- }
- }
- }
-
- if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)
- {
- /* If ANSI, put in a "@ " marker to prevent token pasting.
- But not if "inside a string" (which in ANSI mode
- happens only for -D option). */
- *exp_p++ = '@';
- *exp_p++ = ' ';
- }
-
- *exp_p = '\0';
-
- defn->length = exp_p - defn->expansion;
-
- /* Crash now if we overrun the allocated size. */
- if (defn->length + 1 > maxsize)
- abort ();
-
-#if 0
-/* This isn't worth the time it takes. */
- /* give back excess storage */
- defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
-#endif
-
- return defn;
-}
-
-/*
- * special extension string that can be added to the last macro argument to
- * allow it to absorb the "rest" of the arguments when expanded. Ex:
- * #define wow(a, b...) process (b, a, b)
- * { wow (1, 2, 3); } -> { process (2, 3, 1, 2, 3); }
- * { wow (one, two); } -> { process (two, one, two); }
- * if this "rest_arg" is used with the concat token '##' and if it is not
- * supplied then the token attached to with ## will not be outputted. Ex:
- * #define wow (a, b...) process (b ## , a, ## b)
- * { wow (1, 2); } -> { process (2, 1, 2); }
- * { wow (one); } -> { process (one); {
- */
-static char rest_extension[] = "...";
-#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
-
-/* Create a DEFINITION node from a #define directive. Arguments are
- as for do_define. */
-
-static MACRODEF
-create_definition (buf, limit, pfile, predefinition)
- U_CHAR *buf, *limit;
- cpp_reader *pfile;
- int predefinition;
-{
- U_CHAR *bp; /* temp ptr into input buffer */
- U_CHAR *symname; /* remember where symbol name starts */
- int sym_length; /* and how long it is */
- int rest_args = 0;
- long line, col;
- char *file = CPP_BUFFER (pfile) ? CPP_BUFFER (pfile)->nominal_fname : "";
- DEFINITION *defn;
- int arglengths = 0; /* Accumulate lengths of arg names
- plus number of args. */
- MACRODEF mdef;
- cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
-
- bp = buf;
-
- while (is_hor_space[*bp])
- bp++;
-
- symname = bp; /* remember where it starts */
-
- sym_length = check_macro_name (pfile, bp, "macro");
- bp += sym_length;
-
- /* Lossage will occur if identifiers or control keywords are broken
- across lines using backslash. This is not the right place to take
- care of that. */
-
- if (*bp == '(') {
- struct arglist *arg_ptrs = NULL;
- int argno = 0;
-
- bp++; /* skip '(' */
- SKIP_WHITE_SPACE (bp);
-
- /* Loop over macro argument names. */
- while (*bp != ')') {
- struct arglist *temp;
-
- temp = (struct arglist *) alloca (sizeof (struct arglist));
- temp->name = bp;
- temp->next = arg_ptrs;
- temp->argno = argno++;
- temp->rest_args = 0;
- arg_ptrs = temp;
-
- if (rest_args)
- cpp_pedwarn (pfile, "another parameter follows `%s'", rest_extension);
-
- if (!is_idstart[*bp])
- cpp_pedwarn (pfile, "invalid character in macro parameter name");
-
- /* Find the end of the arg name. */
- while (is_idchar[*bp]) {
- bp++;
- /* do we have a "special" rest-args extension here? */
- if (limit - bp > REST_EXTENSION_LENGTH
- && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
- rest_args = 1;
- temp->rest_args = 1;
- break;
- }
- }
- temp->length = bp - temp->name;
- if (rest_args == 1)
- bp += REST_EXTENSION_LENGTH;
- arglengths += temp->length + 2;
- SKIP_WHITE_SPACE (bp);
- if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
- cpp_error (pfile, "badly punctuated parameter list in `#define'");
- goto nope;
- }
- if (*bp == ',') {
- bp++;
- SKIP_WHITE_SPACE (bp);
- }
- if (bp >= limit) {
- cpp_error (pfile, "unterminated parameter list in `#define'");
- goto nope;
- }
- {
- struct arglist *otemp;
-
- for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
- if (temp->length == otemp->length
- && strncmp (temp->name, otemp->name, temp->length) == 0) {
- U_CHAR *name;
-
- name = (U_CHAR *) alloca (temp->length + 1);
- (void) strncpy (name, temp->name, temp->length);
- name[temp->length] = '\0';
- cpp_error (pfile,
- "duplicate argument name `%s' in `#define'", name);
- goto nope;
- }
- }
- }
-
- ++bp; /* skip paren */
- SKIP_WHITE_SPACE (bp);
- /* now everything from bp before limit is the definition. */
- defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
- defn->rest_args = rest_args;
-
- /* Now set defn->args.argnames to the result of concatenating
- the argument names in reverse order
- with comma-space between them. */
- defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);
- {
- struct arglist *temp;
- int i = 0;
- for (temp = arg_ptrs; temp; temp = temp->next) {
- bcopy (temp->name, &defn->args.argnames[i], temp->length);
- i += temp->length;
- if (temp->next != 0) {
- defn->args.argnames[i++] = ',';
- defn->args.argnames[i++] = ' ';
- }
- }
- defn->args.argnames[i] = 0;
- }
- } else {
- /* Simple expansion or empty definition. */
-
- if (bp < limit)
- {
- if (is_hor_space[*bp]) {
- bp++;
- SKIP_WHITE_SPACE (bp);
- } else {
- switch (*bp) {
- 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 '~':
- cpp_warning (pfile, "missing white space after `#define %.*s'",
- sym_length, symname);
- break;
-
- default:
- cpp_pedwarn (pfile, "missing white space after `#define %.*s'",
- sym_length, symname);
- break;
- }
- }
- }
- /* now everything from bp before limit is the definition. */
- defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
- defn->args.argnames = (U_CHAR *) "";
- }
-
- defn->line = line;
- defn->file = file;
-
- /* OP is null if this is a predefinition */
- defn->predefined = predefinition;
- mdef.defn = defn;
- mdef.symnam = symname;
- mdef.symlen = sym_length;
-
- return mdef;
-
- nope:
- mdef.defn = 0;
- return mdef;
+ CPP_PUTS_Q (pfile, buf, len);
}
/* Check a purported macro name SYMNAME, and yield its length.
- USAGE is the kind of name this is intended for. */
+ ASSERTION is nonzero if this is really for an assertion name. */
-static int
-check_macro_name (pfile, symname, usage)
+int
+check_macro_name (pfile, symname, assertion)
cpp_reader *pfile;
U_CHAR *symname;
- char *usage;
+ int assertion;
{
U_CHAR *p;
int sym_length;
@@ -1641,120 +586,53 @@ check_macro_name (pfile, symname, usage)
sym_length = p - symname;
if (sym_length == 0
|| (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
- cpp_error (pfile, "invalid %s name", usage);
- else if (!is_idstart[*symname]) {
+ cpp_error (pfile,
+ assertion ? "invalid assertion name" : "invalid macro name");
+ else if (!is_idstart[*symname]
+ || (! strncmp (symname, "defined", 7) && sym_length == 7)) {
U_CHAR *msg; /* what pain... */
msg = (U_CHAR *) alloca (sym_length + 1);
bcopy (symname, msg, sym_length);
msg[sym_length] = 0;
- cpp_error (pfile, "invalid %s name `%s'", usage, msg);
- } else {
- if (! strncmp (symname, "defined", 7) && sym_length == 7)
- cpp_error (pfile, "invalid %s name `defined'", usage);
+ cpp_error (pfile,
+ (assertion
+ ? "invalid assertion name `%s'"
+ : "invalid macro name `%s'"),
+ msg);
}
return sym_length;
}
-/* Return zero if two DEFINITIONs are isomorphic. */
-
-static int
-compare_defs (pfile, d1, d2)
- cpp_reader *pfile;
- DEFINITION *d1, *d2;
-{
- register struct reflist *a1, *a2;
- register U_CHAR *p1 = d1->expansion;
- register U_CHAR *p2 = d2->expansion;
- int first = 1;
-
- if (d1->nargs != d2->nargs)
- return 1;
- if (CPP_PEDANTIC (pfile)
- && strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
- return 1;
- for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
- a1 = a1->next, a2 = a2->next) {
- if (!((a1->nchars == a2->nchars && ! strncmp (p1, p2, a1->nchars))
- || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
- || a1->argno != a2->argno
- || a1->stringify != a2->stringify
- || a1->raw_before != a2->raw_before
- || a1->raw_after != a2->raw_after)
- return 1;
- first = 0;
- p1 += a1->nchars;
- p2 += a2->nchars;
- }
- if (a1 != a2)
- return 1;
- if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
- p2, d2->length - (p2 - d2->expansion), 1))
- return 1;
- return 0;
-}
-
-/* Return 1 if two parts of two macro definitions are effectively different.
- One of the parts starts at BEG1 and has LEN1 chars;
- the other has LEN2 chars at BEG2.
- Any sequence of whitespace matches any other sequence of whitespace.
- FIRST means these parts are the first of a macro definition;
- so ignore leading whitespace entirely.
- LAST means these parts are the last of a macro definition;
- so ignore trailing whitespace entirely. */
-
-static int
-comp_def_part (first, beg1, len1, beg2, len2, last)
- int first;
- U_CHAR *beg1, *beg2;
- int len1, len2;
- int last;
-{
- register U_CHAR *end1 = beg1 + len1;
- register U_CHAR *end2 = beg2 + len2;
- if (first) {
- while (beg1 != end1 && is_space[*beg1]) beg1++;
- while (beg2 != end2 && is_space[*beg2]) beg2++;
- }
- if (last) {
- while (beg1 != end1 && is_space[end1[-1]]) end1--;
- while (beg2 != end2 && is_space[end2[-1]]) end2--;
- }
- while (beg1 != end1 && beg2 != end2) {
- if (is_space[*beg1] && is_space[*beg2]) {
- while (beg1 != end1 && is_space[*beg1]) beg1++;
- while (beg2 != end2 && is_space[*beg2]) beg2++;
- } else if (*beg1 == *beg2) {
- beg1++; beg2++;
- } else break;
- }
- return (beg1 != end1) || (beg2 != end2);
-}
-
/* Process a #define command.
-BUF points to the contents of the #define command, as a contiguous string.
-LIMIT points to the first character past the end of the definition.
KEYWORD is the keyword-table entry for #define,
or NULL for a "predefined" macro. */
static int
-do_define (pfile, keyword, buf, limit)
+do_define (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword;
- U_CHAR *buf, *limit;
{
int hashcode;
MACRODEF mdef;
HASHNODE *hp;
+ long here;
+ U_CHAR *macro, *buf, *end;
-#if 0
- /* If this is a precompiler run (with -pcp) pass thru #define commands. */
- if (pcp_outfile && keyword)
- pass_thru_directive (buf, limit, pfile, keyword);
-#endif
+ here = CPP_WRITTEN (pfile);
+ copy_rest_of_line (pfile);
+
+ /* Copy out the line so we can pop the token buffer. */
+ buf = pfile->token_buffer + here;
+ end = CPP_PWRITTEN (pfile);
+ macro = alloca (end - buf + 1);
+ bcopy (buf, macro, end - buf + 1);
+ end = macro + (end - buf);
- mdef = create_definition (buf, limit, pfile, keyword == NULL);
+ CPP_SET_WRITTEN (pfile, here);
+
+ mdef = create_definition (macro, end, pfile, keyword == NULL);
if (mdef.defn == 0)
- goto nope;
+ return 0;
hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE);
@@ -1768,69 +646,37 @@ do_define (pfile, keyword, buf, limit)
else if (hp->type == T_MACRO)
ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */
- else if (hp->type == T_CONST)
+ else if (hp->type == T_CONST || hp->type == T_STDC)
ok = ! CPP_OPTIONS (pfile)->done_initializing;
/* Print the warning if it's not ok. */
if (!ok)
{
- U_CHAR *msg; /* what pain... */
-
- /* If we are passing through #define and #undef directives, do
- that for this re-definition now. */
- if (CPP_OPTIONS (pfile)->debug_output && keyword)
- pass_thru_directive (buf, limit, pfile, keyword);
-
- msg = (U_CHAR *) alloca (mdef.symlen + 22);
- *msg = '`';
- bcopy (mdef.symnam, msg + 1, mdef.symlen);
- strcpy ((char *) (msg + mdef.symlen + 1), "' redefined");
- cpp_pedwarn (pfile, msg);
+ cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
if (hp->type == T_MACRO)
- cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file, hp->value.defn->line,
- "this is the location of the previous definition");
+ cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file,
+ hp->value.defn->line,
+ "this is the location of the previous definition");
}
/* Replace the old definition. */
hp->type = T_MACRO;
hp->value.defn = mdef.defn;
}
else
+ cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO,
+ (char *) mdef.defn, hashcode);
+
+ if (keyword)
{
- /* If we are passing through #define and #undef directives, do
- that for this new definition now. */
- if (CPP_OPTIONS (pfile)->debug_output && keyword)
- pass_thru_directive (buf, limit, pfile, keyword);
- install (mdef.symnam, mdef.symlen, T_MACRO, 0,
- (char *) mdef.defn, hashcode);
+ if (CPP_OPTIONS (pfile)->debug_output
+ || CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
+ dump_definition (pfile, mdef);
+ else if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
+ pass_thru_directive (mdef.symnam, mdef.symlen, pfile, keyword);
}
return 0;
-
-nope:
-
- return 1;
}
-/* This structure represents one parsed argument in a macro call.
- `raw' points to the argument text as written (`raw_length' is its length).
- `expanded' points to the argument's macro-expansion
- (its length is `expand_length').
- `stringified_length' is the length the argument would have
- if stringified.
- `use_count' is the number of times this macro arg is substituted
- into the macro. If the actual use count exceeds 10,
- the value stored is 10. */
-
-/* raw and expanded are relative to ARG_BASE */
-#define ARG_BASE ((pfile)->token_buffer)
-
-struct argdata {
- /* Strings relative to pfile->token_buffer */
- long raw, expanded, stringified;
- int raw_length, expand_length;
- int stringified_length;
- char newlines;
- char use_count;
-};
/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack.
If BUFFER != NULL, then use the LENGTH characters in BUFFER
@@ -1843,23 +689,26 @@ cpp_push_buffer (pfile, buffer, length)
U_CHAR *buffer;
long length;
{
- register cpp_buffer *buf = CPP_BUFFER (pfile);
- if (buf == pfile->buffer_stack)
+ cpp_buffer *buf = CPP_BUFFER (pfile);
+ cpp_buffer *new;
+ if (++pfile->buffer_stack_depth == CPP_STACK_MAX)
{
- cpp_fatal (pfile, "%s: macro or `#include' recursion too deep",
- buf->fname);
+ cpp_fatal (pfile, "macro or `#include' recursion too deep");
return NULL;
}
- buf--;
- bzero ((char *) buf, sizeof (cpp_buffer));
- CPP_BUFFER (pfile) = buf;
- buf->if_stack = pfile->if_stack;
- buf->cleanup = null_cleanup;
- buf->underflow = null_underflow;
- buf->buf = buf->cur = buffer;
- buf->alimit = buf->rlimit = buffer + length;
-
- return buf;
+
+ new = (cpp_buffer *) xcalloc (sizeof (cpp_buffer), 1);
+
+ new->if_stack = pfile->if_stack;
+ new->cleanup = null_cleanup;
+ new->underflow = null_underflow;
+ new->buf = new->cur = buffer;
+ new->alimit = new->rlimit = buffer + length;
+ new->prev = buf;
+ new->mark = -1;
+
+ CPP_BUFFER (pfile) = new;
+ return new;
}
cpp_buffer *
@@ -1868,7 +717,10 @@ cpp_pop_buffer (pfile)
{
cpp_buffer *buf = CPP_BUFFER (pfile);
(*buf->cleanup) (buf, pfile);
- return ++CPP_BUFFER (pfile);
+ CPP_BUFFER (pfile) = CPP_PREV_BUFFER (buf);
+ free (buf);
+ pfile->buffer_stack_depth--;
+ return CPP_BUFFER (pfile);
}
/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer.
@@ -1901,7 +753,7 @@ cpp_scan_buffer (pfile)
* (because it follows CPP_WRITTEN). This is used by do_include.
*/
-static void
+void
cpp_expand_to_buffer (pfile, buf, length)
cpp_reader *pfile;
U_CHAR *buf;
@@ -1911,25 +763,21 @@ cpp_expand_to_buffer (pfile, buf, length)
#if 0
cpp_buffer obuf;
#endif
- U_CHAR *limit = buf + length;
U_CHAR *buf1;
#if 0
int odepth = indepth;
#endif
if (length < 0)
- abort ();
+ {
+ cpp_fatal (pfile, "internal error: length < 0 in cpp_expand_to_buffer");
+ return;
+ }
/* Set up the input on the input stack. */
buf1 = (U_CHAR *) alloca (length + 1);
- {
- register U_CHAR *p1 = buf;
- register U_CHAR *p2 = buf1;
-
- while (p1 != limit)
- *p2++ = *p1++;
- }
+ memcpy (buf1, buf, length);
buf1[length] = 0;
ip = cpp_push_buffer (pfile, buf1, length);
@@ -1943,68 +791,25 @@ cpp_expand_to_buffer (pfile, buf, length)
/* Scan the input, create the output. */
cpp_scan_buffer (pfile);
-#if 0
- if (indepth != odepth)
- abort ();
-#endif
-
CPP_NUL_TERMINATE (pfile);
}
-
-static void
-adjust_position (buf, limit, linep, colp)
- U_CHAR *buf;
- U_CHAR *limit;
- long *linep;
- long *colp;
-{
- while (buf < limit)
- {
- U_CHAR ch = *buf++;
- if (ch == '\n')
- (*linep)++, (*colp) = 1;
- else
- (*colp)++;
- }
-}
-
-/* Move line_base forward, updating lineno and colno. */
-
-static void
-update_position (pbuf)
- register cpp_buffer *pbuf;
-{
- unsigned char *old_pos = pbuf->buf + pbuf->line_base;
- unsigned char *new_pos = pbuf->cur;
- register struct parse_marker *mark;
- for (mark = pbuf->marks; mark != NULL; mark = mark->next)
- {
- if (pbuf->buf + mark->position < new_pos)
- new_pos = pbuf->buf + mark->position;
- }
- pbuf->line_base += new_pos - old_pos;
- adjust_position (old_pos, new_pos, &pbuf->lineno, &pbuf->colno);
-}
-
void
cpp_buf_line_and_col (pbuf, linep, colp)
register cpp_buffer *pbuf;
long *linep, *colp;
{
- long dummy;
- if (colp == NULL)
- colp = &dummy;
if (pbuf)
{
*linep = pbuf->lineno;
- *colp = pbuf->colno;
- adjust_position (pbuf->buf + pbuf->line_base, pbuf->cur, linep, colp);
+ if (colp)
+ *colp = pbuf->cur - pbuf->line_base;
}
else
{
*linep = 0;
- *colp = 0;
+ if (colp)
+ *colp = 0;
}
}
@@ -2022,1002 +827,84 @@ cpp_file_buffer (pfile)
return NULL;
}
-static long
-count_newlines (buf, limit)
- register U_CHAR *buf;
- register U_CHAR *limit;
-{
- register long count = 0;
- while (buf < limit)
- {
- U_CHAR ch = *buf++;
- if (ch == '\n')
- count++;
- }
- return count;
-}
-
/*
* write out a #line command, for instance, after an #include file.
- * If CONDITIONAL is nonzero, we can omit the #line if it would
- * appear to be a no-op, and we can output a few newlines instead
- * if we want to increase the line number by a small amount.
* FILE_CHANGE says whether we are entering a file, leaving, or neither.
*/
-static void
-output_line_command (pfile, conditional, file_change)
+void
+output_line_command (pfile, file_change)
cpp_reader *pfile;
- int conditional;
enum file_change_code file_change;
{
- long line, col;
+ long line;
cpp_buffer *ip = CPP_BUFFER (pfile);
if (ip->fname == NULL)
return;
- update_position (ip);
-
if (CPP_OPTIONS (pfile)->no_line_commands
|| CPP_OPTIONS (pfile)->no_output)
return;
- line = CPP_BUFFER (pfile)->lineno;
- col = CPP_BUFFER (pfile)->colno;
- adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
-
- if (CPP_OPTIONS (pfile)->no_line_commands)
- return;
+ cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, NULL);
- if (conditional) {
- if (line == pfile->lineno)
- return;
+ /* If the current file has not changed, we omit the #line if it would
+ appear to be a no-op, and we output a few newlines instead
+ if we want to increase the line number by a small amount.
+ We cannot do this if pfile->lineno is zero, because that means we
+ haven't output any line commands yet. (The very first line command
+ output is a `same_file' command.) */
+ if (file_change == same_file && pfile->lineno != 0)
+ {
+ if (line == pfile->lineno)
+ return;
- /* If the inherited line number is a little too small,
- output some newlines instead of a #line command. */
- if (line > pfile->lineno && line < pfile->lineno + 8) {
- CPP_RESERVE (pfile, 20);
- while (line > pfile->lineno) {
- CPP_PUTC_Q (pfile, '\n');
- pfile->lineno++;
- }
- return;
+ /* If the inherited line number is a little too small,
+ output some newlines instead of a #line command. */
+ if (line > pfile->lineno && line < pfile->lineno + 8)
+ {
+ CPP_RESERVE (pfile, 20);
+ while (line > pfile->lineno)
+ {
+ CPP_PUTC_Q (pfile, '\n');
+ pfile->lineno++;
+ }
+ return;
+ }
}
- }
-
-#if 0
- /* Don't output a line number of 0 if we can help it. */
- if (ip->lineno == 0 && ip->bufp - ip->buf < ip->length
- && *ip->bufp == '\n') {
- ip->lineno++;
- ip->bufp++;
- }
-#endif
CPP_RESERVE (pfile, 4 * strlen (ip->nominal_fname) + 50);
- {
-#ifdef OUTPUT_LINE_COMMANDS
- static char sharp_line[] = "#line ";
-#else
- static char sharp_line[] = "# ";
-#endif
- CPP_PUTS_Q (pfile, sharp_line, sizeof(sharp_line)-1);
- }
+ CPP_PUTS_Q (pfile, "# ", 2);
sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
quote_string (pfile, ip->nominal_fname);
- if (file_change != same_file) {
- CPP_PUTC_Q (pfile, ' ');
- CPP_PUTC_Q (pfile, file_change == enter_file ? '1' : '2');
- }
- /* Tell cc1 if following text comes from a system header file. */
- if (ip->system_header_p) {
- CPP_PUTC_Q (pfile, ' ');
- CPP_PUTC_Q (pfile, '3');
- }
-#ifndef NO_IMPLICIT_EXTERN_C
- /* Tell cc1plus if following text should be treated as C. */
- if (ip->system_header_p == 2 && CPP_OPTIONS (pfile)->cplusplus) {
- CPP_PUTC_Q (pfile, ' ');
- CPP_PUTC_Q (pfile, '4');
- }
-#endif
- CPP_PUTC_Q (pfile, '\n');
- pfile->lineno = line;
-}
-
-/*
- * Parse a macro argument and append the info on PFILE's token_buffer.
- * REST_ARGS means to absorb the rest of the args.
- * Return nonzero to indicate a syntax error.
- */
-
-static enum cpp_token
-macarg (pfile, rest_args)
- cpp_reader *pfile;
- int rest_args;
-{
- int paren = 0;
- enum cpp_token token;
- char save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
- CPP_OPTIONS (pfile)->put_out_comments = 0;
-
- /* Try to parse as much of the argument as exists at this
- input stack level. */
- pfile->no_macro_expand++;
- for (;;)
+ if (file_change != same_file)
{
- token = cpp_get_token (pfile);
- switch (token)
- {
- case CPP_EOF:
- goto done;
- case CPP_POP:
- /* If we've hit end of file, it's an error (reported by caller).
- Ditto if it's the end of cpp_expand_to_buffer text.
- If we've hit end of macro, just continue. */
- if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
- goto done;
- break;
- case CPP_LPAREN:
- paren++;
- break;
- case CPP_RPAREN:
- if (--paren < 0)
- goto found;
- break;
- case CPP_COMMA:
- /* if we've returned to lowest level and
- we aren't absorbing all args */
- if (paren == 0 && rest_args == 0)
- goto found;
- break;
- found:
- /* Remove ',' or ')' from argument buffer. */
- CPP_ADJUST_WRITTEN (pfile, -1);
- goto done;
- default: ;
- }
- }
-
- done:
- CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
- pfile->no_macro_expand--;
-
- return token;
-}
-
-/* Turn newlines to spaces in the string of length LENGTH at START,
- except inside of string constants.
- The string is copied into itself with its beginning staying fixed. */
-
-static int
-change_newlines (start, length)
- U_CHAR *start;
- int length;
-{
- register U_CHAR *ibp;
- register U_CHAR *obp;
- register U_CHAR *limit;
- register int c;
-
- ibp = start;
- limit = start + length;
- obp = start;
-
- while (ibp < limit) {
- *obp++ = c = *ibp++;
- switch (c) {
-
- case '\'':
- case '\"':
- /* Notice and skip strings, so that we don't delete newlines in them. */
- {
- int quotec = c;
- while (ibp < limit) {
- *obp++ = c = *ibp++;
- if (c == quotec)
- break;
- if (c == '\n' && quotec == '\'')
- break;
- }
- }
- break;
+ CPP_PUTC_Q (pfile, ' ');
+ CPP_PUTC_Q (pfile, file_change == enter_file ? '1' : '2');
}
- }
-
- return obp - start;
-}
-
-
-static struct tm *
-timestamp (pfile)
- cpp_reader *pfile;
-{
- if (!pfile->timebuf) {
- time_t t = time ((time_t *) 0);
- pfile->timebuf = localtime (&t);
- }
- return pfile->timebuf;
-}
-
-static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
- };
-
-/*
- * expand things like __FILE__. Place the expansion into the output
- * buffer *without* rescanning.
- */
-
-static void
-special_symbol (hp, pfile)
- HASHNODE *hp;
- cpp_reader *pfile;
-{
- char *buf;
- int len;
- int true_indepth;
- cpp_buffer *ip = NULL;
- struct tm *timebuf;
-
- int paren = 0; /* For special `defined' keyword */
-
-#if 0
- if (pcp_outfile && pcp_inside_if
- && hp->type != T_SPEC_DEFINED && hp->type != T_CONST)
- cpp_error (pfile,
- "Predefined macro `%s' used inside `#if' during precompilation",
- hp->name);
-#endif
-
- for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
+ /* Tell cc1 if following text comes from a system header file. */
+ if (ip->system_header_p)
{
- if (ip == CPP_NULL_BUFFER (pfile))
- {
- cpp_error (pfile, "cccp error: not in any file?!");
- return; /* the show must go on */
- }
- if (ip->fname != NULL)
- break;
+ CPP_PUTC_Q (pfile, ' ');
+ CPP_PUTC_Q (pfile, '3');
}
-
- switch (hp->type)
+#ifndef NO_IMPLICIT_EXTERN_C
+ /* Tell cc1plus if following text should be treated as C. */
+ if (ip->system_header_p == 2 && CPP_OPTIONS (pfile)->cplusplus)
{
- case T_FILE:
- case T_BASE_FILE:
- {
- char *string;
- if (hp->type == T_BASE_FILE)
- {
- while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
- ip = CPP_PREV_BUFFER (ip);
- }
- string = ip->nominal_fname;
-
- if (!string)
- string = "";
- CPP_RESERVE (pfile, 3 + 4 * strlen (string));
- quote_string (pfile, string);
- return;
- }
-
- case T_INCLUDE_LEVEL:
- true_indepth = 0;
- ip = CPP_BUFFER (pfile);
- for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
- if (ip->fname != NULL)
- true_indepth++;
-
- buf = (char *) alloca (8); /* Eight bytes ought to be more than enough */
- sprintf (buf, "%d", true_indepth - 1);
- break;
-
- case T_VERSION:
- buf = (char *) alloca (3 + strlen (version_string));
- sprintf (buf, "\"%s\"", version_string);
- break;
-
-#ifndef NO_BUILTIN_SIZE_TYPE
- case T_SIZE_TYPE:
- buf = SIZE_TYPE;
- break;
-#endif
-
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
- case T_PTRDIFF_TYPE:
- buf = PTRDIFF_TYPE;
- break;
-#endif
-
- case T_WCHAR_TYPE:
- buf = CPP_WCHAR_TYPE (pfile);
- break;
-
- case T_USER_LABEL_PREFIX_TYPE:
- buf = USER_LABEL_PREFIX;
- break;
-
- case T_REGISTER_PREFIX_TYPE:
- buf = REGISTER_PREFIX;
- break;
-
- case T_CONST:
- buf = (char *) alloca (4 * sizeof (int));
- sprintf (buf, "%d", hp->value.ival);
-#ifdef STDC_0_IN_SYSTEM_HEADERS
- if (ip->system_header_p
- && hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0
- && ! cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", -1, -1))
- strcpy (buf, "0");
-#endif
-#if 0
- if (pcp_inside_if && pcp_outfile)
- /* Output a precondition for this macro use */
- fprintf (pcp_outfile, "#define %s %d\n", hp->name, hp->value.ival);
-#endif
- break;
-
- case T_SPECLINE:
- {
- long line = ip->lineno;
- long col = ip->colno;
- adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
-
- buf = (char *) alloca (10);
- sprintf (buf, "%ld", line);
- }
- break;
-
- case T_DATE:
- case T_TIME:
- buf = (char *) alloca (20);
- timebuf = timestamp (pfile);
- if (hp->type == T_DATE)
- sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
- timebuf->tm_mday, timebuf->tm_year + 1900);
- else
- sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
- timebuf->tm_sec);
- break;
-
- case T_SPEC_DEFINED:
- buf = " 0 "; /* Assume symbol is not defined */
- ip = CPP_BUFFER (pfile);
- SKIP_WHITE_SPACE (ip->cur);
- if (*ip->cur == '(')
- {
- paren++;
- ip->cur++; /* Skip over the paren */
- SKIP_WHITE_SPACE (ip->cur);
- }
-
- if (!is_idstart[*ip->cur])
- goto oops;
- if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
- goto oops;
- if ((hp = cpp_lookup (pfile, ip->cur, -1, -1)))
- {
-#if 0
- if (pcp_outfile && pcp_inside_if
- && (hp->type == T_CONST
- || (hp->type == T_MACRO && hp->value.defn->predefined)))
- /* Output a precondition for this macro use. */
- fprintf (pcp_outfile, "#define %s\n", hp->name);
-#endif
- buf = " 1 ";
- }
-#if 0
- else
- if (pcp_outfile && pcp_inside_if)
- {
- /* Output a precondition for this macro use */
- U_CHAR *cp = ip->bufp;
- fprintf (pcp_outfile, "#undef ");
- while (is_idchar[*cp]) /* Ick! */
- fputc (*cp++, pcp_outfile);
- putc ('\n', pcp_outfile);
- }
-#endif
- while (is_idchar[*ip->cur])
- ++ip->cur;
- SKIP_WHITE_SPACE (ip->cur);
- if (paren)
- {
- if (*ip->cur != ')')
- goto oops;
- ++ip->cur;
- }
- break;
-
- oops:
-
- cpp_error (pfile, "`defined' without an identifier");
- break;
-
- default:
- cpp_error (pfile, "cccp error: invalid special hash type"); /* time for gdb */
- abort ();
+ CPP_PUTC_Q (pfile, ' ');
+ CPP_PUTC_Q (pfile, '4');
}
- len = strlen (buf);
- CPP_RESERVE (pfile, len + 1);
- CPP_PUTS_Q (pfile, buf, len);
- CPP_NUL_TERMINATE_Q (pfile);
-
- return;
-}
-
-/* Write out a #define command for the special named MACRO_NAME
- to PFILE's token_buffer. */
-
-static void
-dump_special_to_buffer (pfile, macro_name)
- cpp_reader *pfile;
- char *macro_name;
-{
- static char define_directive[] = "#define ";
- int macro_name_length = strlen (macro_name);
- output_line_command (pfile, 0, same_file);
- CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
- CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
- CPP_PUTS_Q (pfile, macro_name, macro_name_length);
- CPP_PUTC_Q (pfile, ' ');
- cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
- CPP_PUTC (pfile, '\n');
-}
-
-/* Initialize the built-in macros. */
-
-static void
-initialize_builtins (pfile)
- cpp_reader *pfile;
-{
- install ((U_CHAR *)"__LINE__", -1, T_SPECLINE, 0, 0, -1);
- install ((U_CHAR *)"__DATE__", -1, T_DATE, 0, 0, -1);
- install ((U_CHAR *)"__FILE__", -1, T_FILE, 0, 0, -1);
- install ((U_CHAR *)"__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
- install ((U_CHAR *)"__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
- install ((U_CHAR *)"__VERSION__", -1, T_VERSION, 0, 0, -1);
-#ifndef NO_BUILTIN_SIZE_TYPE
- install ((U_CHAR *)"__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
-#endif
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
- install ((U_CHAR *)"__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
#endif
- install ((U_CHAR *)"__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
- install ((U_CHAR *)"__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
- install ((U_CHAR *)"__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
- install ((U_CHAR *)"__TIME__", -1, T_TIME, 0, 0, -1);
- if (!CPP_TRADITIONAL (pfile))
- install ((U_CHAR *)"__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
- if (CPP_OPTIONS (pfile)->objc)
- install ((U_CHAR *)"__OBJC__", -1, T_CONST, 1, 0, -1);
-/* This is supplied using a -D by the compiler driver
- so that it is present only when truly compiling with GNU C. */
-/* install ("__GNUC__", -1, T_CONST, 2, 0, -1); */
-
- if (CPP_OPTIONS (pfile)->debug_output)
- {
- dump_special_to_buffer (pfile, "__BASE_FILE__");
- dump_special_to_buffer (pfile, "__VERSION__");
-#ifndef NO_BUILTIN_SIZE_TYPE
- dump_special_to_buffer (pfile, "__SIZE_TYPE__");
-#endif
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
- dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
-#endif
- dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
- dump_special_to_buffer (pfile, "__DATE__");
- dump_special_to_buffer (pfile, "__TIME__");
- if (!CPP_TRADITIONAL (pfile))
- dump_special_to_buffer (pfile, "__STDC__");
- if (CPP_OPTIONS (pfile)->objc)
- dump_special_to_buffer (pfile, "__OBJC__");
- }
-}
-
-/* Return 1 iff a token ending in C1 followed directly by a token C2
- could cause mis-tokenization. */
-
-static int
-unsafe_chars (c1, c2)
- int c1, c2;
-{
- switch (c1)
- {
- case '+': case '-':
- if (c2 == c1 || c2 == '=')
- return 1;
- goto letter;
- case '.':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case 'e': case 'E': case 'p': case 'P':
- if (c2 == '-' || c2 == '+')
- return 1; /* could extend a pre-processing number */
- goto letter;
- case 'L':
- if (c2 == '\'' || c2 == '\"')
- return 1; /* Could turn into L"xxx" or L'xxx'. */
- goto letter;
- letter:
- case '_':
- case 'a': case 'b': case 'c': case 'd': case 'f':
- case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'q': case 'r':
- case 's': case 't': case 'u': case 'v': case 'w': case 'x':
- case 'y': case 'z':
- case 'A': case 'B': case 'C': case 'D': case 'F':
- case 'G': case 'H': case 'I': case 'J': case 'K':
- case 'M': case 'N': case 'O': case 'Q': case 'R':
- case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
- case 'Y': case 'Z':
- /* We're in the middle of either a name or a pre-processing number. */
- return (is_idchar[c2] || c2 == '.');
- case '<': case '>': case '!': case '%': case '#': case ':':
- case '^': case '&': case '|': case '*': case '/': case '=':
- return (c2 == c1 || c2 == '=');
- }
- return 0;
+ CPP_PUTC_Q (pfile, '\n');
+ pfile->lineno = line;
}
-/* Expand a macro call.
- HP points to the symbol that is the macro being called.
- Put the result of expansion onto the input stack
- so that subsequent input by our caller will use it.
-
- If macro wants arguments, caller has already verified that
- an argument list follows; arguments come from the input stack. */
-
-static void
-macroexpand (pfile, hp)
- cpp_reader *pfile;
- HASHNODE *hp;
-{
- int nargs;
- DEFINITION *defn = hp->value.defn;
- register U_CHAR *xbuf;
- long start_line, start_column;
- int xbuf_len;
- struct argdata *args;
- long old_written = CPP_WRITTEN (pfile);
-#if 0
- int start_line = instack[indepth].lineno;
-#endif
- int rest_args, rest_zero;
- register int i;
-
-#if 0
- CHECK_DEPTH (return;);
-#endif
-
-#if 0
- /* This macro is being used inside a #if, which means it must be */
- /* recorded as a precondition. */
- if (pcp_inside_if && pcp_outfile && defn->predefined)
- dump_single_macro (hp, pcp_outfile);
-#endif
-
- pfile->output_escapes++;
- cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
-
- nargs = defn->nargs;
-
- if (nargs >= 0)
- {
- enum cpp_token token;
-
- args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
-
- for (i = 0; i < nargs; i++)
- {
- args[i].raw = args[i].expanded = 0;
- args[i].raw_length = 0;
- args[i].expand_length = args[i].stringified_length = -1;
- args[i].use_count = 0;
- }
-
- /* Parse all the macro args that are supplied. I counts them.
- The first NARGS args are stored in ARGS.
- The rest are discarded. If rest_args is set then we assume
- macarg absorbed the rest of the args. */
- i = 0;
- rest_args = 0;
- rest_args = 0;
- FORWARD(1); /* Discard the open-parenthesis before the first arg. */
- do
- {
- if (rest_args)
- continue;
- if (i < nargs || (nargs == 0 && i == 0))
- {
- /* if we are working on last arg which absorbs rest of args... */
- if (i == nargs - 1 && defn->rest_args)
- rest_args = 1;
- args[i].raw = CPP_WRITTEN (pfile);
- token = macarg (pfile, rest_args);
- args[i].raw_length = CPP_WRITTEN (pfile) - args[i].raw;
- args[i].newlines = 0; /* FIXME */
- }
- else
- token = macarg (pfile, 0);
- if (token == CPP_EOF || token == CPP_POP)
- {
- cpp_error_with_line (pfile, start_line, start_column,
- "unterminated macro call");
- return;
- }
- i++;
- } while (token == CPP_COMMA);
-
- /* If we got one arg but it was just whitespace, call that 0 args. */
- if (i == 1)
- {
- register U_CHAR *bp = ARG_BASE + args[0].raw;
- register U_CHAR *lim = bp + args[0].raw_length;
- /* cpp.texi says for foo ( ) we provide one argument.
- However, if foo wants just 0 arguments, treat this as 0. */
- if (nargs == 0)
- while (bp != lim && is_space[*bp]) bp++;
- if (bp == lim)
- i = 0;
- }
-
- /* Don't output an error message if we have already output one for
- a parse error above. */
- rest_zero = 0;
- if (nargs == 0 && i > 0)
- {
- cpp_error (pfile, "arguments given to macro `%s'", hp->name);
- }
- else if (i < nargs)
- {
- /* traditional C allows foo() if foo wants one argument. */
- if (nargs == 1 && i == 0 && CPP_TRADITIONAL (pfile))
- ;
- /* the rest args token is allowed to absorb 0 tokens */
- else if (i == nargs - 1 && defn->rest_args)
- rest_zero = 1;
- else if (i == 0)
- cpp_error (pfile, "macro `%s' used without args", hp->name);
- else if (i == 1)
- cpp_error (pfile, "macro `%s' used with just one arg", hp->name);
- else
- cpp_error (pfile, "macro `%s' used with only %d args",
- hp->name, i);
- }
- else if (i > nargs)
- {
- cpp_error (pfile,
- "macro `%s' used with too many (%d) args", hp->name, i);
- }
- }
-
- /* If macro wants zero args, we parsed the arglist for checking only.
- Read directly from the macro definition. */
- if (nargs <= 0)
- {
- xbuf = defn->expansion;
- xbuf_len = defn->length;
- }
- else
- {
- register U_CHAR *exp = defn->expansion;
- register int offset; /* offset in expansion,
- copied a piece at a time */
- register int totlen; /* total amount of exp buffer filled so far */
-
- register struct reflist *ap, *last_ap;
-
- /* Macro really takes args. Compute the expansion of this call. */
-
- /* Compute length in characters of the macro's expansion.
- Also count number of times each arg is used. */
- xbuf_len = defn->length;
- for (ap = defn->pattern; ap != NULL; ap = ap->next)
- {
- if (ap->stringify)
- {
- register struct argdata *arg = &args[ap->argno];
- /* Stringify if it hasn't already been */
- if (arg->stringified_length < 0)
- {
- int arglen = arg->raw_length;
- int escaped = 0;
- int in_string = 0;
- int c;
- /* Initially need_space is -1. Otherwise, 1 means the
- previous character was a space, but we suppressed it;
- 0 means the previous character was a non-space. */
- int need_space = -1;
- i = 0;
- arg->stringified = CPP_WRITTEN (pfile);
- if (!CPP_TRADITIONAL (pfile))
- CPP_PUTC (pfile, '\"'); /* insert beginning quote */
- for (; i < arglen; i++)
- {
- c = (ARG_BASE + arg->raw)[i];
-
- if (! in_string)
- {
- /* Internal sequences of whitespace are replaced by
- one space except within an string or char token.*/
- if (is_space[c])
- {
- if (CPP_WRITTEN (pfile) > arg->stringified
- && (CPP_PWRITTEN (pfile))[-1] == '@')
- {
- /* "@ " escape markers are removed */
- CPP_ADJUST_WRITTEN (pfile, -1);
- continue;
- }
- if (need_space == 0)
- need_space = 1;
- continue;
- }
- else if (need_space > 0)
- CPP_PUTC (pfile, ' ');
- need_space = 0;
- }
-
- if (escaped)
- escaped = 0;
- else
- {
- if (c == '\\')
- escaped = 1;
- if (in_string)
- {
- if (c == in_string)
- in_string = 0;
- }
- else if (c == '\"' || c == '\'')
- in_string = c;
- }
-
- /* Escape these chars */
- if (c == '\"' || (in_string && c == '\\'))
- CPP_PUTC (pfile, '\\');
- if (ISPRINT (c))
- CPP_PUTC (pfile, c);
- else
- {
- CPP_RESERVE (pfile, 4);
- sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o",
- (unsigned int) c);
- CPP_ADJUST_WRITTEN (pfile, 4);
- }
- }
- if (!CPP_TRADITIONAL (pfile))
- CPP_PUTC (pfile, '\"'); /* insert ending quote */
- arg->stringified_length
- = CPP_WRITTEN (pfile) - arg->stringified;
- }
- xbuf_len += args[ap->argno].stringified_length;
- }
- else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
- /* Add 4 for two newline-space markers to prevent
- token concatenation. */
- xbuf_len += args[ap->argno].raw_length + 4;
- else
- {
- /* We have an ordinary (expanded) occurrence of the arg.
- So compute its expansion, if we have not already. */
- if (args[ap->argno].expand_length < 0)
- {
- args[ap->argno].expanded = CPP_WRITTEN (pfile);
- cpp_expand_to_buffer (pfile,
- ARG_BASE + args[ap->argno].raw,
- args[ap->argno].raw_length);
-
- args[ap->argno].expand_length
- = CPP_WRITTEN (pfile) - args[ap->argno].expanded;
- }
-
- /* Add 4 for two newline-space markers to prevent
- token concatenation. */
- xbuf_len += args[ap->argno].expand_length + 4;
- }
- if (args[ap->argno].use_count < 10)
- args[ap->argno].use_count++;
- }
-
- xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
-
- /* Generate in XBUF the complete expansion
- with arguments substituted in.
- TOTLEN is the total size generated so far.
- OFFSET is the index in the definition
- of where we are copying from. */
- offset = totlen = 0;
- for (last_ap = NULL, ap = defn->pattern; ap != NULL;
- last_ap = ap, ap = ap->next)
- {
- register struct argdata *arg = &args[ap->argno];
- int count_before = totlen;
-
- /* Add chars to XBUF. */
- for (i = 0; i < ap->nchars; i++, offset++)
- xbuf[totlen++] = exp[offset];
-
- /* If followed by an empty rest arg with concatenation,
- delete the last run of nonwhite chars. */
- if (rest_zero && totlen > count_before
- && ((ap->rest_args && ap->raw_before)
- || (last_ap != NULL && last_ap->rest_args
- && last_ap->raw_after)))
- {
- /* Delete final whitespace. */
- while (totlen > count_before && is_space[xbuf[totlen - 1]])
- totlen--;
-
- /* Delete the nonwhites before them. */
- while (totlen > count_before && ! is_space[xbuf[totlen - 1]])
- totlen--;
- }
- if (ap->stringify != 0)
- {
- bcopy (ARG_BASE + arg->stringified,
- xbuf + totlen, arg->stringified_length);
- totlen += arg->stringified_length;
- }
- else if (ap->raw_before || ap->raw_after || CPP_TRADITIONAL (pfile))
- {
- U_CHAR *p1 = ARG_BASE + arg->raw;
- U_CHAR *l1 = p1 + arg->raw_length;
- if (ap->raw_before)
- {
- while (p1 != l1 && is_space[*p1]) p1++;
- while (p1 != l1 && is_idchar[*p1])
- xbuf[totlen++] = *p1++;
- /* Delete any no-reexpansion marker that follows
- an identifier at the beginning of the argument
- if the argument is concatenated with what precedes it. */
- if (p1[0] == '@' && p1[1] == '-')
- p1 += 2;
- }
- if (ap->raw_after)
- {
- /* Arg is concatenated after: delete trailing whitespace,
- whitespace markers, and no-reexpansion markers. */
- while (p1 != l1)
- {
- if (is_space[l1[-1]]) l1--;
- else if (l1[-1] == '-')
- {
- U_CHAR *p2 = l1 - 1;
- /* If a `-' is preceded by an odd number of newlines then it
- and the last newline are a no-reexpansion marker. */
- while (p2 != p1 && p2[-1] == '\n') p2--;
- if ((l1 - 1 - p2) & 1) {
- l1 -= 2;
- }
- else break;
- }
- else break;
- }
- }
-
- bcopy (p1, xbuf + totlen, l1 - p1);
- totlen += l1 - p1;
- }
- else
- {
- U_CHAR *expanded = ARG_BASE + arg->expanded;
- if (!ap->raw_before && totlen > 0 && arg->expand_length
- && !CPP_TRADITIONAL(pfile)
- && unsafe_chars (xbuf[totlen-1], expanded[0]))
- {
- xbuf[totlen++] = '@';
- xbuf[totlen++] = ' ';
- }
-
- bcopy (expanded, xbuf + totlen, arg->expand_length);
- totlen += arg->expand_length;
-
- if (!ap->raw_after && totlen > 0 && offset < defn->length
- && !CPP_TRADITIONAL(pfile)
- && unsafe_chars (xbuf[totlen-1], exp[offset]))
- {
- xbuf[totlen++] = '@';
- xbuf[totlen++] = ' ';
- }
-
- /* If a macro argument with newlines is used multiple times,
- then only expand the newlines once. This avoids creating
- output lines which don't correspond to any input line,
- which confuses gdb and gcov. */
- if (arg->use_count > 1 && arg->newlines > 0)
- {
- /* Don't bother doing change_newlines for subsequent
- uses of arg. */
- arg->use_count = 1;
- arg->expand_length
- = change_newlines (expanded, arg->expand_length);
- }
- }
-
- if (totlen > xbuf_len)
- abort ();
- }
-
- /* if there is anything left of the definition
- after handling the arg list, copy that in too. */
-
- for (i = offset; i < defn->length; i++)
- {
- /* if we've reached the end of the macro */
- if (exp[i] == ')')
- rest_zero = 0;
- if (! (rest_zero && last_ap != NULL && last_ap->rest_args
- && last_ap->raw_after))
- xbuf[totlen++] = exp[i];
- }
-
- xbuf[totlen] = 0;
- xbuf_len = totlen;
-
- }
-
- pfile->output_escapes--;
-
- /* Now put the expansion on the input stack
- so our caller will commence reading from it. */
- push_macro_expansion (pfile, xbuf, xbuf_len, hp);
- CPP_BUFFER (pfile)->has_escapes = 1;
-
- /* Pop the space we've used in the token_buffer for argument expansion. */
- CPP_SET_WRITTEN (pfile, old_written);
-
- /* Recursive macro use sometimes works traditionally.
- #define foo(x,y) bar (x (y,0), y)
- foo (foo, baz) */
-
- if (!CPP_TRADITIONAL (pfile))
- hp->type = T_DISABLED;
-}
-
-static void
-push_macro_expansion (pfile, xbuf, xbuf_len, hp)
- cpp_reader *pfile;
- register U_CHAR *xbuf;
- int xbuf_len;
- HASHNODE *hp;
-{
- register cpp_buffer *mbuf = cpp_push_buffer (pfile, xbuf, xbuf_len);
- if (mbuf == NULL)
- return;
- mbuf->cleanup = macro_cleanup;
- mbuf->data = hp;
-
- /* The first chars of the expansion should be a "@ " added by
- collect_expansion. This is to prevent accidental token-pasting
- between the text preceding the macro invocation, and the macro
- expansion text.
-
- We would like to avoid adding unneeded spaces (for the sake of
- tools that use cpp, such as imake). In some common cases we can
- tell that it is safe to omit the space.
-
- The character before the macro invocation cannot have been an
- idchar (or else it would have been pasted with the idchars of
- the macro name). Therefore, if the first non-space character
- of the expansion is an idchar, we do not need the extra space
- to prevent token pasting.
-
- Also, we don't need the extra space if the first char is '(',
- or some other (less common) characters. */
-
- if (xbuf[0] == '@' && xbuf[1] == ' '
- && (is_idchar[xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
- || xbuf[2] == '\"'))
- mbuf->cur += 2;
-}
-
/* Like cpp_get_token, except that it does not read past end-of-line.
Also, horizontal space is skipped, and macros are popped. */
@@ -3057,36 +944,27 @@ get_directive_token (pfile)
This is safe. */
static int
-do_include (pfile, keyword, unused1, unused2)
+do_include (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword;
- U_CHAR *unused1 ATTRIBUTE_UNUSED, *unused2 ATTRIBUTE_UNUSED;
{
int importing = (keyword->type == T_IMPORT);
int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
- char *fname; /* Dynamically allocated fname buffer */
- char *pcftry;
- U_CHAR *fbeg, *fend; /* Beginning and end of fname */
+ int angle_brackets = 0; /* 0 for "...", 1 for <...> */
+ int before; /* included before? */
+ long flen;
+ unsigned char *ftok;
+ cpp_buffer *fp;
+
enum cpp_token token;
/* Chain of dirs to search */
- struct file_name_list *search_start = CPP_OPTIONS (pfile)->include;
- struct file_name_list dsp[1]; /* First in chain, if #include "..." */
- struct file_name_list *searchptr = 0;
+ struct include_hash *ihash;
+ struct file_name_list *search_start;
+
long old_written = CPP_WRITTEN (pfile);
- int flen;
-
- int f; /* file number */
-
- int angle_brackets = 0; /* 0 for "...", 1 for <...> */
- char *pcfbuf;
-#if 0
- int pcf = -1;
- char *pcfbuflimit;
-#endif
- int pcfnum;
- f= -1; /* JF we iz paranoid! */
+ int fd;
if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
{
@@ -3101,17 +979,8 @@ do_include (pfile, keyword, unused1, unused2)
&& !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning)
{
pfile->import_warning = 1;
- cpp_warning (pfile, "using `#import' is not recommended");
- fprintf (stderr, "The fact that a certain header file need not be processed more than once\n");
- fprintf (stderr, "should be indicated in the header file, not where it is used.\n");
- fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n");
- fprintf (stderr, " #ifndef _FOO_H_INCLUDED\n");
- fprintf (stderr, " #define _FOO_H_INCLUDED\n");
- fprintf (stderr, " ... <real contents of file> ...\n");
- fprintf (stderr, " #endif /* Not _FOO_H_INCLUDED */\n\n");
- fprintf (stderr, "Then users can use `#include' any number of times.\n");
- fprintf (stderr, "GNU C automatically avoids processing the file more than once\n");
- fprintf (stderr, "when it is equipped with such a conditional.\n");
+ cpp_warning (pfile,
+ "#import is obsolete, use an #ifndef wrapper in the header file");
}
pfile->parsing_include_directive++;
@@ -3120,77 +989,20 @@ do_include (pfile, keyword, unused1, unused2)
if (token == CPP_STRING)
{
- /* FIXME - check no trailing garbage */
- fbeg = pfile->token_buffer + old_written + 1;
- fend = CPP_PWRITTEN (pfile) - 1;
- if (fbeg[-1] == '<')
- {
- angle_brackets = 1;
- /* If -I-, start with the first -I dir after the -I-. */
- if (CPP_OPTIONS (pfile)->first_bracket_include)
- search_start = CPP_OPTIONS (pfile)->first_bracket_include;
- }
- /* If -I- was specified, don't search current dir, only spec'd ones. */
- else if (! CPP_OPTIONS (pfile)->ignore_srcdir)
- {
- cpp_buffer *fp = CPP_BUFFER (pfile);
- /* We have "filename". Figure out directory this source
- file is coming from and put it on the front of the list. */
-
- for ( ; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
- {
- int n;
- char *ep,*nam;
-
- if ((nam = fp->nominal_fname) != NULL)
- {
- /* Found a named file. Figure out dir of the file,
- and put it in front of the search list. */
- dsp[0].next = search_start;
- search_start = dsp;
-#ifndef VMS
- ep = rindex (nam, '/');
-#else /* VMS */
- ep = rindex (nam, ']');
- if (ep == NULL) ep = rindex (nam, '>');
- if (ep == NULL) ep = rindex (nam, ':');
- if (ep != NULL) ep++;
-#endif /* VMS */
- if (ep != NULL)
- {
- n = ep - nam;
- dsp[0].fname = (char *) alloca (n + 1);
- strncpy (dsp[0].fname, nam, n);
- dsp[0].fname[n] = '\0';
- if (n + INCLUDE_LEN_FUDGE > pfile->max_include_len)
- pfile->max_include_len = n + INCLUDE_LEN_FUDGE;
- }
- else
- {
- dsp[0].fname = 0; /* Current directory */
- }
- dsp[0].got_name_map = 0;
- break;
- }
- }
- }
+ if (pfile->token_buffer[old_written] == '<')
+ angle_brackets = 1;
}
#ifdef VMS
else if (token == CPP_NAME)
{
- /*
- * Support '#include xyz' like VAX-C to allow for easy use of all the
- * decwindow include files. It defaults to '#include <xyz.h>' (so the
- * code from case '<' is repeated here) and generates a warning.
- */
+ /* Support '#include xyz' like VAX-C. It is taken as
+ '#include <xyz.h>' and generates a warning. */
cpp_warning (pfile,
- "VAX-C-style include specification found, use '#include <filename.h>' !");
+ "`#include filename' is obsolete, use `#include <filename.h>'");
angle_brackets = 1;
- /* If -I-, start with the first -I dir after the -I-. */
- if (CPP_OPTIONS (pfile)->first_bracket_include)
- search_start = CPP_OPTIONS (pfile)->first_bracket_include;
- fbeg = pfile->token_buffer + old_written;
- fend = CPP_PWRITTEN (pfile);
+
+ /* Append the missing `.h' to the name. */
+ CPP_PUTS (pfile, ".h", 2);
}
#endif
else
@@ -3202,653 +1014,376 @@ do_include (pfile, keyword, unused1, unused2)
return 0;
}
- *fend = 0;
+ flen = CPP_WRITTEN (pfile) - old_written;
+ ftok = alloca (flen + 1);
+ memcpy (ftok, pfile->token_buffer + old_written, flen);
+ ftok[flen] = '\0';
- token = get_directive_token (pfile);
- if (token != CPP_VSPACE)
+ if (get_directive_token (pfile) != CPP_VSPACE)
{
cpp_error (pfile, "junk at end of `#include'");
- while (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
- token = get_directive_token (pfile);
- }
-
- /* For #include_next, skip in the search path
- past the dir in which the containing file was found. */
- if (skip_dirs)
- {
- cpp_buffer *fp = CPP_BUFFER (pfile);
- for (; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
- if (fp->fname != NULL)
- {
- /* fp->dir is null if the containing file was specified with
- an absolute file name. In that case, don't skip anything. */
- if (fp->dir == SELF_DIR_DUMMY)
- search_start = CPP_OPTIONS (pfile)->include;
- else if (fp->dir)
- search_start = fp->dir->next;
- break;
- }
+ skip_rest_of_line (pfile);
}
CPP_SET_WRITTEN (pfile, old_written);
- flen = fend - fbeg;
-
if (flen == 0)
{
cpp_error (pfile, "empty file name in `#%s'", keyword->name);
return 0;
}
- /* Allocate this permanently, because it gets stored in the definitions
- of macros. */
- fname = (char *) xmalloc (pfile->max_include_len + flen + 4);
- /* + 2 above for slash and terminating null. */
- /* + 2 added for '.h' on VMS (to support '#include filename') */
-
- /* If specified file name is absolute, just open it. */
+ if (CPP_OPTIONS (pfile)->dump_includes)
+ pass_thru_directive (ftok,
+ flen
+#ifdef VMS
+ - ((token == CPP_NAME) ? 2 : 0)
+#endif
+ , pfile, keyword);
- if (*fbeg == '/') {
- strncpy (fname, fbeg, flen);
- fname[flen] = 0;
- if (redundant_include_p (pfile, fname))
- return 0;
- if (importing)
- f = lookup_import (pfile, fname, NULL_PTR);
- else
- f = open_include_file (pfile, fname, NULL_PTR);
- if (f == -2)
- return 0; /* Already included this file */
- } else {
- /* Search directory path, trying to open the file.
- Copy each filename tried into FNAME. */
-
- for (searchptr = search_start; searchptr; searchptr = searchptr->next) {
- if (searchptr->fname) {
- /* The empty string in a search path is ignored.
- This makes it possible to turn off entirely
- a standard piece of the list. */
- if (searchptr->fname[0] == 0)
- continue;
- strcpy (fname, searchptr->fname);
- strcat (fname, "/");
- fname[strlen (fname) + flen] = 0;
- } else {
- fname[0] = 0;
- }
- strncat (fname, fbeg, flen);
#ifdef VMS
- /* Change this 1/2 Unix 1/2 VMS file specification into a
- full VMS file specification */
- if (searchptr->fname && (searchptr->fname[0] != 0)) {
- /* Fix up the filename */
- hack_vms_include_specification (fname);
- } else {
- /* This is a normal VMS filespec, so use it unchanged. */
- strncpy (fname, fbeg, flen);
- fname[flen] = 0;
- /* if it's '#include filename', add the missing .h */
- if (index(fname,'.')==NULL) {
- strcat (fname, ".h");
- }
- }
-#endif /* VMS */
- /* ??? There are currently 3 separate mechanisms for avoiding processing
- of redundant include files: #import, #pragma once, and
- redundant_include_p. It would be nice if they were unified. */
- if (redundant_include_p (pfile, fname))
- return 0;
- if (importing)
- f = lookup_import (pfile, fname, searchptr);
- else
- f = open_include_file (pfile, fname, searchptr);
- if (f == -2)
- return 0; /* Already included this file */
-#ifdef EACCES
- else if (f == -1 && errno == EACCES)
- cpp_warning (pfile, "Header file %s exists, but is not readable",
- fname);
+ if (token == CPP_STRING)
#endif
- if (f >= 0)
- break;
+ {
+ ftok++;
+ flen -= 2;
+ ftok[flen] = '\0';
}
- }
- if (f < 0)
+ search_start = 0;
+
+ for (fp = CPP_BUFFER (pfile);
+ fp != CPP_NULL_BUFFER (pfile);
+ fp = CPP_PREV_BUFFER (fp))
+ if (fp->fname != NULL)
+ break;
+
+ if (fp == CPP_NULL_BUFFER (pfile))
{
- /* A file that was not found. */
- strncpy (fname, fbeg, flen);
- fname[flen] = 0;
- /* If generating dependencies and -MG was specified, we assume missing
- files are leaf files, living in the same directory as the source file
- or other similar place; these missing files may be generated from
- other files and may not exist yet (eg: y.tab.h). */
-
- if (CPP_OPTIONS(pfile)->print_deps_missing_files
- && CPP_PRINT_DEPS (pfile)
- > (angle_brackets || (pfile->system_include_depth > 0)))
- {
- /* If it was requested as a system header file,
- then assume it belongs in the first place to look for such. */
- if (angle_brackets)
+ cpp_fatal (pfile, "cpp internal error: fp == NULL_BUFFER in do_include");
+ return 0;
+ }
+
+ /* For #include_next, skip in the search path past the dir in which the
+ containing file was found. Treat files specified using an absolute path
+ as if there are no more directories to search. Treat the primary source
+ file like any other included source, but generate a warning. */
+ if (skip_dirs && CPP_PREV_BUFFER(fp) != CPP_NULL_BUFFER (pfile))
+ {
+ if (fp->ihash->foundhere != ABSOLUTE_PATH)
+ search_start = fp->ihash->foundhere->next;
+ }
+ else
+ {
+ if (skip_dirs)
+ cpp_warning (pfile, "#include_next in primary source file");
+
+ if (angle_brackets)
+ search_start = CPP_OPTIONS (pfile)->bracket_include;
+ else
+ {
+ if (!CPP_OPTIONS (pfile)->ignore_srcdir)
{
- for (searchptr = search_start; searchptr;
- searchptr = searchptr->next)
- {
- if (searchptr->fname)
- {
- char *p;
-
- if (searchptr->fname[0] == 0)
- continue;
- p = (char *) alloca (strlen (searchptr->fname)
- + strlen (fname) + 2);
- strcpy (p, searchptr->fname);
- strcat (p, "/");
- strcat (p, fname);
- deps_output (pfile, p, ' ');
- break;
- }
- }
+ if (fp)
+ search_start = fp->actual_dir;
}
else
- {
- /* Otherwise, omit the directory, as if the file existed
- in the directory with the source. */
- deps_output (pfile, fname, ' ');
- }
+ search_start = CPP_OPTIONS (pfile)->quote_include;
}
- /* If -M was specified, and this header file won't be added to the
- dependency list, then don't count this as an error, because we can
- still produce correct output. Otherwise, we can't produce correct
- output, because there may be dependencies we need inside the missing
- file, and we don't know what directory this missing file exists in.*/
- else if (CPP_PRINT_DEPS (pfile)
- && (CPP_PRINT_DEPS (pfile)
- <= (angle_brackets || (pfile->system_include_depth > 0))))
- cpp_warning (pfile, "No include path in which to find %s", fname);
- else if (search_start)
- cpp_error_from_errno (pfile, fname);
- else
- cpp_error (pfile, "No include path in which to find %s", fname);
- }
- else {
- /* Check to see if this include file is a once-only include file.
- If so, give up. */
-
- struct file_name_list *ptr;
-
- for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next) {
- if (!strcmp (ptr->fname, fname)) {
- close (f);
- return 0; /* This file was once'd. */
- }
}
- for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) {
- if (!strcmp (ptr->fname, fname))
- break; /* This file was included before. */
+ if (!search_start)
+ {
+ cpp_error (pfile, "No include path in which to find %s", ftok);
+ return 0;
}
- if (ptr == 0) {
- /* This is the first time for this file. */
- /* Add it to list of files included. */
-
- ptr = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
- ptr->control_macro = 0;
- ptr->c_system_include_path = 0;
- ptr->next = pfile->all_include_files;
- pfile->all_include_files = ptr;
- ptr->fname = savestring (fname);
- ptr->got_name_map = 0;
-
- /* For -M, add this file to the dependencies. */
- if (CPP_PRINT_DEPS (pfile)
- > (angle_brackets || (pfile->system_include_depth > 0)))
- deps_output (pfile, fname, ' ');
- }
-
- /* Handle -H option. */
- if (CPP_OPTIONS(pfile)->print_include_names)
- {
- cpp_buffer *buf = CPP_BUFFER (pfile);
- while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
- putc ('.', stderr);
- fprintf (stderr, "%s\n", fname);
- }
-
- if (angle_brackets)
- pfile->system_include_depth++;
-
- /* Actually process the file. */
-
- /* Record file on "seen" list for #import. */
- add_import (pfile, f, fname);
-
- pcftry = (char *) alloca (strlen (fname) + 30);
- pcfbuf = 0;
- pcfnum = 0;
-
-#if 0
- if (!no_precomp)
- {
- struct stat stat_f;
-
- fstat (f, &stat_f);
-
- do {
- sprintf (pcftry, "%s%d", fname, pcfnum++);
+ fd = find_include_file (pfile, ftok, search_start, &ihash, &before);
- pcf = open (pcftry, O_RDONLY, 0666);
- if (pcf != -1)
+ if (fd == -2)
+ return 0;
+
+ if (fd == -1)
+ {
+ if (CPP_OPTIONS (pfile)->print_deps_missing_files
+ && CPP_PRINT_DEPS (pfile) > (angle_brackets ||
+ (pfile->system_include_depth > 0)))
+ {
+ if (!angle_brackets)
+ deps_output (pfile, ftok, ' ');
+ else
{
- struct stat s;
-
- fstat (pcf, &s);
- if (bcmp ((char *) &stat_f.st_ino, (char *) &s.st_ino,
- sizeof (s.st_ino))
- || stat_f.st_dev != s.st_dev)
- {
- pcfbuf = check_precompiled (pcf, fname, &pcfbuflimit);
- /* Don't need it any more. */
- close (pcf);
- }
+ char *p;
+ struct file_name_list *ptr;
+ /* If requested as a system header, assume it belongs in
+ the first system header directory. */
+ if (CPP_OPTIONS (pfile)->bracket_include)
+ ptr = CPP_OPTIONS (pfile)->bracket_include;
else
- {
- /* Don't need it at all. */
- close (pcf);
- break;
- }
- }
- } while (pcf != -1 && !pcfbuf);
- }
-#endif
-
- /* Actually process the file */
- if (cpp_push_buffer (pfile, NULL, 0) == NULL)
- return 0;
- if (finclude (pfile, f, fname, is_system_include (pfile, fname),
- searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
- {
- output_line_command (pfile, 0, enter_file);
- pfile->only_seen_white = 2;
- }
-
- if (angle_brackets)
- pfile->system_include_depth--;
- }
- return 0;
-}
+ ptr = CPP_OPTIONS (pfile)->quote_include;
-/* Return nonzero if there is no need to include file NAME
- because it has already been included and it contains a conditional
- to make a repeated include do nothing. */
-
-static int
-redundant_include_p (pfile, name)
- cpp_reader *pfile;
- char *name;
-{
- struct file_name_list *l = pfile->all_include_files;
- for (; l; l = l->next)
- if (! strcmp (name, l->fname)
- && l->control_macro
- && cpp_lookup (pfile, l->control_macro, -1, -1))
- return 1;
- return 0;
-}
-
-/* Return nonzero if the given FILENAME is an absolute pathname which
- designates a file within one of the known "system" include file
- directories. We assume here that if the given FILENAME looks like
- it is the name of a file which resides either directly in a "system"
- include file directory, or within any subdirectory thereof, then the
- given file must be a "system" include file. This function tells us
- if we should suppress pedantic errors/warnings for the given FILENAME.
-
- The value is 2 if the file is a C-language system header file
- for which C++ should (on most systems) assume `extern "C"'. */
-
-static int
-is_system_include (pfile, filename)
- cpp_reader *pfile;
- register char *filename;
-{
- struct file_name_list *searchptr;
-
- for (searchptr = CPP_OPTIONS (pfile)->first_system_include; searchptr;
- searchptr = searchptr->next)
- if (searchptr->fname) {
- register char *sys_dir = searchptr->fname;
- register unsigned length = strlen (sys_dir);
-
- if (! strncmp (sys_dir, filename, length) && filename[length] == '/')
- {
- if (searchptr->c_system_include_path)
- return 2;
- else
- return 1;
+ p = (char *) alloca (strlen (ptr->name)
+ + strlen (ftok) + 2);
+ if (*ptr->name != '\0')
+ {
+ strcpy (p, ptr->name);
+ strcat (p, "/");
+ }
+ strcat (p, ftok);
+ deps_output (pfile, p, ' ');
+ }
}
- }
- return 0;
-}
-
-
-/*
- * Install a name in the assertion hash table.
- *
- * If LEN is >= 0, it is the length of the name.
- * Otherwise, compute the length by scanning the entire name.
- *
- * If HASH is >= 0, it is the precomputed hash code.
- * Otherwise, compute the hash code.
- */
+ /* If -M was specified, and this header file won't be added to
+ the dependency list, then don't count this as an error,
+ because we can still produce correct output. Otherwise, we
+ can't produce correct output, because there may be
+ dependencies we need inside the missing file, and we don't
+ know what directory this missing file exists in. */
+ else if (CPP_PRINT_DEPS (pfile)
+ && (CPP_PRINT_DEPS (pfile)
+ <= (angle_brackets || (pfile->system_include_depth > 0))))
+ cpp_warning (pfile, "No include path in which to find %s", ftok);
+ else
+ cpp_error_from_errno (pfile, ftok);
-static ASSERTION_HASHNODE *
-assertion_install (pfile, name, len, hash)
- cpp_reader *pfile;
- U_CHAR *name;
- int len;
- int hash;
-{
- register ASSERTION_HASHNODE *hp;
- register int i, bucket;
- register U_CHAR *p, *q;
-
- i = sizeof (ASSERTION_HASHNODE) + len + 1;
- hp = (ASSERTION_HASHNODE *) xmalloc (i);
- bucket = hash;
- hp->bucket_hdr = &pfile->assertion_hashtab[bucket];
- hp->next = pfile->assertion_hashtab[bucket];
- pfile->assertion_hashtab[bucket] = hp;
- hp->prev = NULL;
- if (hp->next != NULL)
- hp->next->prev = hp;
- hp->length = len;
- hp->value = 0;
- hp->name = ((U_CHAR *) hp) + sizeof (ASSERTION_HASHNODE);
- p = hp->name;
- q = name;
- for (i = 0; i < len; i++)
- *p++ = *q++;
- hp->name[len] = 0;
- return hp;
-}
-/*
- * find the most recent hash node for name "name" (ending with first
- * non-identifier char) installed by install
- *
- * If LEN is >= 0, it is the length of the name.
- * Otherwise, compute the length by scanning the entire name.
- *
- * If HASH is >= 0, it is the precomputed hash code.
- * Otherwise, compute the hash code.
- */
+ return 0;
+ }
-static ASSERTION_HASHNODE *
-assertion_lookup (pfile, name, len, hash)
- cpp_reader *pfile;
- U_CHAR *name;
- int len;
- int hash;
-{
- register ASSERTION_HASHNODE *bucket;
+ /* For -M, add the file to the dependencies on its first inclusion. */
+ if (!before && (CPP_PRINT_DEPS (pfile)
+ > (angle_brackets || (pfile->system_include_depth > 0))))
+ deps_output (pfile, ihash->name, ' ');
- bucket = pfile->assertion_hashtab[hash];
- while (bucket) {
- if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
- return bucket;
- bucket = bucket->next;
- }
- return NULL;
-}
+ /* Handle -H option. */
+ if (CPP_OPTIONS(pfile)->print_include_names)
+ {
+ fp = CPP_BUFFER (pfile);
+ while ((fp = CPP_PREV_BUFFER (fp)) != CPP_NULL_BUFFER (pfile))
+ putc ('.', stderr);
+ fprintf (stderr, " %s\n", ihash->name);
+ }
-static void
-delete_assertion (hp)
- ASSERTION_HASHNODE *hp;
-{
- struct tokenlist_list *tail;
- if (hp->prev != NULL)
- hp->prev->next = hp->next;
- if (hp->next != NULL)
- hp->next->prev = hp->prev;
+ /* Actually process the file */
- for (tail = hp->value; tail; )
+ if (importing)
+ ihash->control_macro = "";
+
+ if (cpp_push_buffer (pfile, NULL, 0) == NULL)
{
- struct tokenlist_list *next = tail->next;
- free_token_list (tail->tokens);
- free (tail);
- tail = next;
+ close (fd);
+ return 0;
}
+
+ if (angle_brackets)
+ pfile->system_include_depth++; /* Decremented in file_cleanup. */
- /* Make sure that the bucket chain header that
- the deleted guy was on points to the right thing afterwards. */
- if (hp == *hp->bucket_hdr)
- *hp->bucket_hdr = hp->next;
-
- free (hp);
-}
-
-/* Convert a character string literal into a nul-terminated string.
- The input string is [IN ... LIMIT).
- The result is placed in RESULT. RESULT can be the same as IN.
- The value returned in the end of the string written to RESULT,
- or NULL on error. */
-
-static U_CHAR *
-convert_string (pfile, result, in, limit, handle_escapes)
- cpp_reader *pfile;
- register U_CHAR *result, *in, *limit;
- int handle_escapes;
-{
- U_CHAR c;
- c = *in++;
- if (c != '\"')
- return NULL;
- while (in < limit)
+ if (finclude (pfile, fd, ihash))
{
- U_CHAR c = *in++;
- switch (c)
- {
- case '\0':
- return NULL;
- case '\"':
- limit = in;
- break;
- case '\\':
- if (handle_escapes)
- {
- char *bpc = (char *) in;
- int i = (U_CHAR) cpp_parse_escape (pfile, &bpc);
- in = (U_CHAR *) bpc;
- if (i >= 0)
- *result++ = (U_CHAR)c;
- break;
- }
- /* else fall through */
- default:
- *result++ = c;
- }
+ output_line_command (pfile, enter_file);
+ pfile->only_seen_white = 2;
}
- *result = 0;
- return result;
+
+ return 0;
}
-/*
- * interpret #line command. Remembers previously seen fnames
- * in its very own hash table.
- */
-#define FNAME_HASHSIZE 37
+/* Interpret #line command.
+ Note that the filename string (if any) is treated as if it were an
+ include filename. That means no escape handling. */
static int
-do_line (pfile, keyword, unused1, unused2)
+do_line (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *unused1 ATTRIBUTE_UNUSED, *unused2 ATTRIBUTE_UNUSED;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
int new_lineno;
long old_written = CPP_WRITTEN (pfile);
enum file_change_code file_change = same_file;
enum cpp_token token;
+ char *x;
token = get_directive_token (pfile);
- if (token != CPP_NUMBER
- || !ISDIGIT(pfile->token_buffer[old_written]))
+ if (token != CPP_NUMBER)
{
- cpp_error (pfile, "invalid format `#line' command");
+ cpp_error (pfile, "token after `#line' is not an integer");
goto bad_line_directive;
}
- /* The Newline at the end of this line remains to be processed.
- To put the next line at the specified line number,
- we must store a line number now that is one less. */
- new_lineno = atoi ((char *)(pfile->token_buffer + old_written)) - 1;
+ new_lineno = strtol (pfile->token_buffer + old_written, &x, 10);
+ if (x[0] != '\0')
+ {
+ cpp_error (pfile, "token after `#line' is not an integer");
+ goto bad_line_directive;
+ }
CPP_SET_WRITTEN (pfile, old_written);
- /* NEW_LINENO is one less than the actual line number here. */
- if (CPP_PEDANTIC (pfile) && new_lineno < 0)
+ if (CPP_PEDANTIC (pfile) && new_lineno <= 0)
cpp_pedwarn (pfile, "line number out of range in `#line' command");
-#if 0 /* #line 10"foo.c" is supposed to be allowed. */
- if (PEEKC() && !is_space[PEEKC()]) {
- cpp_error (pfile, "invalid format `#line' command");
- goto bad_line_directive;
- }
-#endif
-
token = get_directive_token (pfile);
- if (token == CPP_STRING) {
- U_CHAR *fname = pfile->token_buffer + old_written;
- U_CHAR *end_name;
- static HASHNODE *fname_table[FNAME_HASHSIZE];
- HASHNODE *hp, **hash_bucket;
- U_CHAR *p;
- long num_start;
- int fname_length;
-
- /* Turn the file name, which is a character string literal,
- into a null-terminated string. Do this in place. */
- end_name = convert_string (pfile, fname, fname, CPP_PWRITTEN (pfile), 1);
- if (end_name == NULL)
+ if (token == CPP_STRING)
{
- cpp_error (pfile, "invalid format `#line' command");
- goto bad_line_directive;
- }
+ U_CHAR *fname = pfile->token_buffer + old_written + 1;
+ U_CHAR *end_name = CPP_PWRITTEN (pfile) - 1;
+ long num_start = CPP_WRITTEN (pfile);
- fname_length = end_name - fname;
+ token = get_directive_token (pfile);
+ if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP)
+ {
+ U_CHAR *p = pfile->token_buffer + num_start;
+ if (CPP_PEDANTIC (pfile))
+ cpp_pedwarn (pfile, "garbage at end of `#line' command");
- num_start = CPP_WRITTEN (pfile);
- token = get_directive_token (pfile);
- if (token != CPP_VSPACE && token != CPP_EOF && token != CPP_POP) {
- p = pfile->token_buffer + num_start;
- if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "garbage at end of `#line' command");
+ if (token != CPP_NUMBER || *p < '0' || *p > '4' || p[1] != '\0')
+ {
+ cpp_error (pfile, "invalid format `#line' command");
+ goto bad_line_directive;
+ }
+ if (*p == '1')
+ file_change = enter_file;
+ else if (*p == '2')
+ file_change = leave_file;
+ else if (*p == '3')
+ ip->system_header_p = 1;
+ else /* if (*p == '4') */
+ ip->system_header_p = 2;
+
+ CPP_SET_WRITTEN (pfile, num_start);
+ token = get_directive_token (pfile);
+ p = pfile->token_buffer + num_start;
+ if (token == CPP_NUMBER && p[1] == '\0' && (*p == '3' || *p== '4'))
+ {
+ ip->system_header_p = *p == '3' ? 1 : 2;
+ token = get_directive_token (pfile);
+ }
+ if (token != CPP_VSPACE)
+ {
+ cpp_error (pfile, "invalid format `#line' command");
+ goto bad_line_directive;
+ }
+ }
+
+ *end_name = '\0';
+
+ if (strcmp (fname, ip->nominal_fname))
+ {
+ char *newname, *oldname;
+ if (!strcmp (fname, ip->fname))
+ newname = ip->fname;
+ else if (ip->last_nominal_fname
+ && !strcmp (fname, ip->last_nominal_fname))
+ newname = ip->last_nominal_fname;
+ else
+ newname = xstrdup (fname);
- if (token != CPP_NUMBER || *p < '0' || *p > '4' || p[1] != '\0')
- {
- cpp_error (pfile, "invalid format `#line' command");
- goto bad_line_directive;
- }
- if (*p == '1')
- file_change = enter_file;
- else if (*p == '2')
- file_change = leave_file;
- else if (*p == '3')
- ip->system_header_p = 1;
- else /* if (*p == '4') */
- ip->system_header_p = 2;
-
- CPP_SET_WRITTEN (pfile, num_start);
- token = get_directive_token (pfile);
- p = pfile->token_buffer + num_start;
- if (token == CPP_NUMBER && p[1] == '\0' && (*p == '3' || *p== '4')) {
- ip->system_header_p = *p == '3' ? 1 : 2;
- token = get_directive_token (pfile);
- }
- if (token != CPP_VSPACE) {
- cpp_error (pfile, "invalid format `#line' command");
- goto bad_line_directive;
- }
- }
+ oldname = ip->nominal_fname;
+ ip->nominal_fname = newname;
- hash_bucket = &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
- for (hp = *hash_bucket; hp != NULL; hp = hp->next)
- if (hp->length == fname_length
- && strncmp (hp->value.cpval, fname, fname_length) == 0) {
- ip->nominal_fname = hp->value.cpval;
- break;
- }
- if (hp == 0) {
- /* Didn't find it; cons up a new one. */
- hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);
- hp->next = *hash_bucket;
- *hash_bucket = hp;
-
- hp->length = fname_length;
- ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
- bcopy (fname, hp->value.cpval, fname_length);
+ if (ip->last_nominal_fname
+ && ip->last_nominal_fname != oldname
+ && ip->last_nominal_fname != newname
+ && ip->last_nominal_fname != ip->fname)
+ free (ip->last_nominal_fname);
+
+ if (newname == ip->fname)
+ ip->last_nominal_fname = NULL;
+ else
+ ip->last_nominal_fname = oldname;
+ }
}
- }
- else if (token != CPP_VSPACE && token != CPP_EOF) {
- cpp_error (pfile, "invalid format `#line' command");
- goto bad_line_directive;
- }
+ else if (token != CPP_VSPACE && token != CPP_EOF)
+ {
+ cpp_error (pfile, "token after `#line %d' is not a string", new_lineno);
+ goto bad_line_directive;
+ }
+
+ /* The Newline at the end of this line remains to be processed.
+ To put the next line at the specified line number,
+ we must store a line number now that is one less. */
+ ip->lineno = new_lineno - 1;
+ CPP_SET_WRITTEN (pfile, old_written);
+ output_line_command (pfile, file_change);
+ return 0;
- ip->lineno = new_lineno;
bad_line_directive:
skip_rest_of_line (pfile);
CPP_SET_WRITTEN (pfile, old_written);
- output_line_command (pfile, 0, file_change);
return 0;
}
-/*
- * remove the definition of a symbol from the symbol table.
- * according to un*x /lib/cpp, it is not an error to undef
- * something that has no definitions, so it isn't one here either.
- */
-
+/* Remove the definition of a symbol from the symbol table.
+ According to the C standard, it is not an error to undef
+ something that has no definitions. */
static int
-do_undef (pfile, keyword, buf, limit)
+do_undef (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword;
- U_CHAR *buf, *limit;
{
int sym_length;
HASHNODE *hp;
- U_CHAR *orig_buf = buf;
+ U_CHAR *buf, *name, *limit;
+ int c;
+ long here = CPP_WRITTEN (pfile);
+ enum cpp_token token;
-#if 0
- /* If this is a precompiler run (with -pcp) pass thru #undef commands. */
- if (pcp_outfile && keyword)
- pass_thru_directive (buf, limit, pfile, keyword);
-#endif
+ cpp_skip_hspace (pfile);
+ c = GETC();
+ if (! is_idstart[c])
+ {
+ cpp_error (pfile, "token after #undef is not an identifier");
+ skip_rest_of_line (pfile);
+ return 1;
+ }
+
+ parse_name (pfile, c);
+ buf = pfile->token_buffer + here;
+ limit = CPP_PWRITTEN(pfile);
+
+ /* Copy out the token so we can pop the token buffer. */
+ name = alloca (limit - buf + 1);
+ bcopy(buf, name, limit - buf);
+ name[limit - buf] = '\0';
+
+ token = get_directive_token (pfile);
+ if (token != CPP_VSPACE && token != CPP_POP)
+ {
+ cpp_pedwarn (pfile, "junk on line after #undef");
+ skip_rest_of_line (pfile);
+ }
+
+ CPP_SET_WRITTEN (pfile, here);
- SKIP_WHITE_SPACE (buf);
- sym_length = check_macro_name (pfile, buf, "macro");
+ sym_length = check_macro_name (pfile, buf, 0);
- while ((hp = cpp_lookup (pfile, buf, sym_length, -1)) != NULL)
+ while ((hp = cpp_lookup (pfile, name, sym_length, -1)) != NULL)
{
/* If we are generating additional info for debugging (with -g) we
need to pass through all effective #undef commands. */
if (CPP_OPTIONS (pfile)->debug_output && keyword)
- pass_thru_directive (orig_buf, limit, pfile, keyword);
+ pass_thru_directive (name, sym_length, pfile, keyword);
if (hp->type != T_MACRO)
cpp_warning (pfile, "undefining `%s'", hp->name);
delete_macro (hp);
}
- if (CPP_PEDANTIC (pfile)) {
- buf += sym_length;
- SKIP_WHITE_SPACE (buf);
- if (buf != limit)
- cpp_pedwarn (pfile, "garbage after `#undef' directive");
- }
return 0;
}
+
+/* Wrap do_undef for -U processing. */
+void
+cpp_undef (pfile, macro)
+ cpp_reader *pfile;
+ U_CHAR *macro;
+{
+ if (cpp_push_buffer (pfile, macro, strlen (macro)))
+ {
+ do_undef (pfile, NULL);
+ cpp_pop_buffer (pfile);
+ }
+}
+
/*
* Report an error detected by the program we are processing.
@@ -3857,182 +1392,146 @@ do_undef (pfile, keyword, buf, limit)
*/
static int
-do_error (pfile, keyword, buf, limit)
+do_error (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf, *limit;
{
- int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) alloca (length + 1);
- bcopy (buf, copy, length);
- copy[length] = 0;
- SKIP_WHITE_SPACE (copy);
- cpp_error (pfile, "#error %s", copy);
+ long here = CPP_WRITTEN (pfile);
+ U_CHAR *text;
+ copy_rest_of_line (pfile);
+ text = pfile->token_buffer + here;
+ SKIP_WHITE_SPACE(text);
+
+ cpp_error (pfile, "#error %s", text);
+ CPP_SET_WRITTEN (pfile, here);
return 0;
}
/*
* Report a warning detected by the program we are processing.
* Use the text of the line in the warning message, then continue.
- * (We use error because it prints the filename & line#.)
*/
static int
-do_warning (pfile, keyword, buf, limit)
+do_warning (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf, *limit;
{
- int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) alloca (length + 1);
- bcopy (buf, copy, length);
- copy[length] = 0;
- SKIP_WHITE_SPACE (copy);
+ U_CHAR *text;
+ long here = CPP_WRITTEN(pfile);
+ copy_rest_of_line (pfile);
+ text = pfile->token_buffer + here;
+ SKIP_WHITE_SPACE(text);
if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
cpp_pedwarn (pfile, "ANSI C does not allow `#warning'");
/* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
if -pedantic-errors is given, #warning should cause an error. */
- cpp_pedwarn (pfile, "#warning %s", copy);
- return 0;
-}
-
-/* Remember the name of the current file being read from so that we can
- avoid ever including it again. */
-
-static int
-do_once (pfile, keyword, unused1, unused2)
- cpp_reader *pfile;
- struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *unused1 ATTRIBUTE_UNUSED, *unused2 ATTRIBUTE_UNUSED;
-{
- cpp_buffer *ip = NULL;
- struct file_name_list *new;
-
- for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
- {
- if (ip == CPP_NULL_BUFFER (pfile))
- return 0;
- if (ip->fname != NULL)
- break;
- }
-
-
- new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
- new->next = pfile->dont_repeat_files;
- pfile->dont_repeat_files = new;
- new->fname = savestring (ip->fname);
- new->control_macro = 0;
- new->got_name_map = 0;
- new->c_system_include_path = 0;
-
+ cpp_pedwarn (pfile, "#warning %s", text);
+ CPP_SET_WRITTEN (pfile, here);
return 0;
}
-/* Report program identification. */
+/* Report program identification.
+ This is not precisely what cccp does with #ident, however I believe
+ it matches `closely enough' (behavior is identical as long as there
+ are no macros on the #ident line, which is pathological in my opinion). */
static int
-do_ident (pfile, keyword, buf, limit)
+do_ident (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
{
-/* long old_written = CPP_WRITTEN (pfile);*/
-
/* Allow #ident in system headers, since that's not user's fault. */
if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
cpp_pedwarn (pfile, "ANSI C does not allow `#ident'");
- /* Leave rest of line to be read by later calls to cpp_get_token. */
+ CPP_PUTS (pfile, "#ident ", 7);
+ cpp_skip_hspace (pfile);
+ copy_rest_of_line (pfile);
return 0;
}
-/* #pragma and its argument line have already been copied to the output file.
- Just check for some recognized pragmas that need validation here. */
+/* Just check for some recognized pragmas that need validation here,
+ and leave the text in the token buffer to be output. */
static int
-do_pragma (pfile, keyword, buf, limit)
+do_pragma (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf, *limit ATTRIBUTE_UNUSED;
{
- while (*buf == ' ' || *buf == '\t')
- buf++;
- if (!strncmp (buf, "once", 4)) {
- /* Allow #pragma once in system headers, since that's not the user's
- fault. */
- if (!CPP_BUFFER (pfile)->system_header_p)
- cpp_warning (pfile, "`#pragma once' is obsolete");
- do_once (pfile, NULL, NULL, NULL);
- }
+ long here;
+ U_CHAR *buf;
- if (!strncmp (buf, "implementation", 14)) {
- /* Be quiet about `#pragma implementation' for a file only if it hasn't
- been included yet. */
- struct file_name_list *ptr;
- U_CHAR *p = buf + 14, *fname, *inc_fname;
- int fname_len;
- SKIP_WHITE_SPACE (p);
- if (*p == '\n' || *p != '\"')
- return 0;
+ CPP_PUTS (pfile, "#pragma ", 8);
+ cpp_skip_hspace (pfile);
+
+ here = CPP_WRITTEN (pfile);
+ copy_rest_of_line (pfile);
+ buf = pfile->token_buffer + here;
+
+ if (!strncmp (buf, "once", 4))
+ {
+ cpp_buffer *ip = NULL;
- fname = p + 1;
- p = (U_CHAR *) index (fname, '\"');
- fname_len = p != NULL ? p - fname : strlen (fname);
-
- for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) {
- inc_fname = (U_CHAR *) rindex (ptr->fname, '/');
- inc_fname = inc_fname ? inc_fname + 1 : (U_CHAR *) ptr->fname;
- if (inc_fname && !strncmp (inc_fname, fname, fname_len))
- cpp_warning (pfile,
- "`#pragma implementation' for `%s' appears after file is included",
- fname);
+ /* Allow #pragma once in system headers, since that's not the user's
+ fault. */
+ if (!CPP_BUFFER (pfile)->system_header_p)
+ cpp_warning (pfile, "`#pragma once' is obsolete");
+
+ for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
+ {
+ if (ip == CPP_NULL_BUFFER (pfile))
+ return 0;
+ if (ip->fname != NULL)
+ break;
+ }
+
+ if (CPP_PREV_BUFFER (ip) == CPP_NULL_BUFFER (pfile))
+ cpp_warning (pfile, "`#pragma once' outside include file");
+ else
+ ip->ihash->control_macro = ""; /* never repeat */
}
- }
+ else if (!strncmp (buf, "implementation", 14))
+ {
+ /* Be quiet about `#pragma implementation' for a file only if it hasn't
+ been included yet. */
+ struct include_hash *ptr;
+ U_CHAR *p = buf + 14, *fname, *fcopy;
+ SKIP_WHITE_SPACE (p);
+ if (*p == '\n' || *p != '\"')
+ return 0;
- return 0;
-}
+ fname = p + 1;
+ p = (U_CHAR *) index (fname, '\"');
-#if 0
-/* This was a fun hack, but #pragma seems to start to be useful.
- By failing to recognize it, we pass it through unchanged to cc1. */
+ fcopy = alloca (p - fname + 1);
+ bcopy (fname, fcopy, p - fname);
+ fcopy[p-fname] = '\0';
-/*
- * the behavior of the #pragma directive is implementation defined.
- * this implementation defines it as follows.
- */
+ ptr = include_hash (pfile, fcopy, 0);
+ if (ptr)
+ cpp_warning (pfile,
+ "`#pragma implementation' for `%s' appears after file is included",
+ fcopy);
+ }
-static int
-do_pragma ()
-{
- close (0);
- if (open ("/dev/tty", O_RDONLY, 0666) != 0)
- goto nope;
- close (1);
- if (open ("/dev/tty", O_WRONLY, 0666) != 1)
- goto nope;
- execl ("/usr/games/hack", "#pragma", 0);
- execl ("/usr/games/rogue", "#pragma", 0);
- execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);
- execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);
-nope:
- fatal ("You are in a maze of twisty compiler features, all different");
+ return 0;
}
-#endif
#ifdef SCCS_DIRECTIVE
/* Just ignore #sccs, on systems where we define it at all. */
static int
-do_sccs (pfile, keyword, buf, limit)
+do_sccs (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
{
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "ANSI C does not allow `#sccs'");
+ skip_rest_of_line (pfile);
return 0;
}
#endif
@@ -4051,12 +1550,11 @@ do_sccs (pfile, keyword, buf, limit)
*/
static int
-do_if (pfile, keyword, buf, limit)
+do_if (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf, *limit;
{
- HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
+ HOST_WIDEST_INT value = eval_if_expression (pfile);
conditional_skip (pfile, value == 0, T_IF, NULL_PTR);
return 0;
}
@@ -4067,10 +1565,9 @@ do_if (pfile, keyword, buf, limit)
*/
static int
-do_elif (pfile, keyword, buf, limit)
+do_elif (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf, *limit;
{
if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) {
cpp_error (pfile, "`#elif' not within a conditional");
@@ -4091,14 +1588,14 @@ do_elif (pfile, keyword, buf, limit)
}
if (pfile->if_stack->if_succeeded)
- skip_if_group (pfile, 0);
+ skip_if_group (pfile);
else {
- HOST_WIDE_INT value = eval_if_expression (pfile, buf, limit - buf);
+ HOST_WIDEST_INT value = eval_if_expression (pfile);
if (value == 0)
- skip_if_group (pfile, 0);
+ skip_if_group (pfile);
else {
++pfile->if_stack->if_succeeded; /* continue processing input */
- output_line_command (pfile, 1, same_file);
+ output_line_command (pfile, same_file);
}
}
return 0;
@@ -4109,22 +1606,16 @@ do_elif (pfile, keyword, buf, limit)
* then parse the result as a C expression and return the value as an int.
*/
-static HOST_WIDE_INT
-eval_if_expression (pfile, buf, length)
+static HOST_WIDEST_INT
+eval_if_expression (pfile)
cpp_reader *pfile;
- U_CHAR *buf ATTRIBUTE_UNUSED;
- int length ATTRIBUTE_UNUSED;
{
- HASHNODE *save_defined;
- HOST_WIDE_INT value;
+ HOST_WIDEST_INT value;
long old_written = CPP_WRITTEN (pfile);
- save_defined = install ((U_CHAR *)"defined", -1, T_SPEC_DEFINED, 0, 0, -1);
pfile->pcp_inside_if = 1;
-
value = cpp_parse_expr (pfile);
pfile->pcp_inside_if = 0;
- delete_macro (save_defined); /* clean up special symbol */
CPP_SET_WRITTEN (pfile, old_written); /* Pop */
@@ -4138,10 +1629,9 @@ eval_if_expression (pfile, buf, length)
*/
static int
-do_xifdef (pfile, keyword, unused1, unused2)
+do_xifdef (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword;
- U_CHAR *unused1 ATTRIBUTE_UNUSED, *unused2 ATTRIBUTE_UNUSED;
{
int skip;
cpp_buffer *ip = CPP_BUFFER (pfile);
@@ -4240,175 +1730,168 @@ conditional_skip (pfile, skip, type, control_macro)
pfile->if_stack->type = type;
if (skip != 0) {
- skip_if_group (pfile, 0);
+ skip_if_group (pfile);
return;
} else {
++pfile->if_stack->if_succeeded;
- output_line_command (pfile, 1, same_file);
+ output_line_command (pfile, same_file);
}
}
-/*
- * skip to #endif, #else, or #elif. adjust line numbers, etc.
+/* Subroutine of skip_if_group. Examine one preprocessing directive and
+ return 0 if skipping should continue, 1 if it should halt. Also
+ adjusts the if_stack as appropriate.
+ The `#' has been read, but not the identifier. */
+
+static int
+consider_directive_while_skipping (pfile, stack)
+ cpp_reader *pfile;
+ IF_STACK_FRAME *stack;
+{
+ long ident_len, ident;
+ struct directive *kt;
+ IF_STACK_FRAME *temp;
+
+ cpp_skip_hspace (pfile);
+
+ ident = CPP_WRITTEN (pfile);
+ parse_name (pfile, GETC());
+ ident_len = CPP_WRITTEN (pfile) - ident;
+
+ CPP_SET_WRITTEN (pfile, ident);
+
+ for (kt = directive_table; kt->length >= 0; kt++)
+ if (kt->length == ident_len
+ && strncmp (pfile->token_buffer + ident, kt->name, kt->length) == 0)
+ switch (kt->type)
+ {
+ case T_IF:
+ case T_IFDEF:
+ case T_IFNDEF:
+ temp = (IF_STACK_FRAME *) xmalloc (sizeof (IF_STACK_FRAME));
+ temp->next = pfile->if_stack;
+ pfile->if_stack = temp;
+ temp->fname = CPP_BUFFER(pfile)->nominal_fname;
+ temp->type = kt->type;
+ return 0;
+
+ case T_ELSE:
+ if (CPP_PEDANTIC (pfile) && pfile->if_stack != stack)
+ validate_else (pfile, "#else");
+ /* fall through */
+ case T_ELIF:
+ if (pfile->if_stack->type == T_ELSE)
+ cpp_error (pfile, "`%s' after `#else'", kt->name);
+
+ if (pfile->if_stack == stack)
+ return 1;
+ else
+ {
+ pfile->if_stack->type = kt->type;
+ return 0;
+ }
+
+ case T_ENDIF:
+ if (CPP_PEDANTIC (pfile) && pfile->if_stack != stack)
+ validate_else (pfile, "#endif");
+
+ if (pfile->if_stack == stack)
+ return 1;
+
+ temp = pfile->if_stack;
+ pfile->if_stack = temp->next;
+ free (temp);
+ return 0;
+
+ default:
+ return 0;
+ }
+
+ /* Don't let erroneous code go by. */
+ if (!CPP_OPTIONS (pfile)->lang_asm && CPP_PEDANTIC (pfile))
+ cpp_pedwarn (pfile, "invalid preprocessor directive name");
+ return 0;
+}
+
+/* skip to #endif, #else, or #elif. adjust line numbers, etc.
* leaves input ptr at the sharp sign found.
- * If ANY is nonzero, return at next directive of any sort.
*/
-
static void
-skip_if_group (pfile, any)
- cpp_reader *pfile;
- int any;
+skip_if_group (pfile)
+ cpp_reader *pfile;
{
int c;
- struct directive *kt;
IF_STACK_FRAME *save_if_stack = pfile->if_stack; /* don't pop past here */
-#if 0
- U_CHAR *beg_of_line = bp;
-#endif
- register int ident_length;
- U_CHAR *ident;
- struct parse_marker line_start_mark;
-
- parse_set_mark (&line_start_mark, pfile);
-
- if (CPP_OPTIONS (pfile)->output_conditionals) {
- static char failed[] = "#failed\n";
- CPP_PUTS (pfile, failed, sizeof(failed)-1);
- pfile->lineno++;
- output_line_command (pfile, 1, same_file);
- }
+ U_CHAR *beg_of_line;
+ long old_written;
- beg_of_line:
if (CPP_OPTIONS (pfile)->output_conditionals)
{
- cpp_buffer *pbuf = CPP_BUFFER (pfile);
- U_CHAR *start_line = pbuf->buf + line_start_mark.position;
- CPP_PUTS (pfile, start_line, pbuf->cur - start_line);
+ CPP_PUTS (pfile, "#failed\n", 8);
+ pfile->lineno++;
+ output_line_command (pfile, same_file);
}
- parse_move_mark (&line_start_mark, pfile);
- if (!CPP_TRADITIONAL (pfile))
- cpp_skip_hspace (pfile);
- c = GETC();
- if (c == '#')
- {
- int old_written = CPP_WRITTEN (pfile);
- cpp_skip_hspace (pfile);
- parse_name (pfile, GETC());
- ident_length = CPP_WRITTEN (pfile) - old_written;
- ident = pfile->token_buffer + old_written;
- pfile->limit = ident;
-#if 0
- if (ident_length == 0)
- goto not_a_directive;
+ old_written = CPP_WRITTEN (pfile);
+
+ for (;;)
+ {
+ beg_of_line = CPP_BUFFER (pfile)->cur;
- /* Handle # followed by a line number. */
+ if (! CPP_TRADITIONAL (pfile))
+ cpp_skip_hspace (pfile);
+ c = GETC();
+ if (c == '\n')
+ {
+ if (CPP_OPTIONS (pfile)->output_conditionals)
+ CPP_PUTC (pfile, c);
+ CPP_BUMP_LINE (pfile);
+ continue;
+ }
+ else if (c == '#')
+ {
+ if (consider_directive_while_skipping (pfile, save_if_stack))
+ break;
+ }
+ else if (c == EOF)
+ return; /* Caller will issue error. */
- /* Avoid error for `###' and similar cases unless -pedantic. */
-#endif
+ FORWARD(-1);
+ if (CPP_OPTIONS (pfile)->output_conditionals)
+ {
+ CPP_PUTS (pfile, beg_of_line, CPP_BUFFER (pfile)->cur - beg_of_line);
+ copy_rest_of_line (pfile);
+ }
+ else
+ {
+ copy_rest_of_line (pfile);
+ CPP_SET_WRITTEN (pfile, old_written); /* discard it */
+ }
- for (kt = directive_table; kt->length >= 0; kt++)
+ c = GETC();
+ if (c == EOF)
+ return; /* Caller will issue error. */
+ else
{
- IF_STACK_FRAME *temp;
- if (ident_length == kt->length
- && strncmp (ident, kt->name, kt->length) == 0)
+ /* \n */
+ if (CPP_OPTIONS (pfile)->output_conditionals)
{
- /* If we are asked to return on next directive, do so now. */
- if (any)
- goto done;
-
- switch (kt->type)
- {
- case T_IF:
- case T_IFDEF:
- case T_IFNDEF:
- temp
- = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
- temp->next = pfile->if_stack;
- pfile->if_stack = temp;
-#if 0
- temp->lineno = CPP_BUFFER(pfile)->lineno;
-#endif
- temp->fname = CPP_BUFFER(pfile)->nominal_fname;
- temp->type = kt->type;
- break;
- case T_ELSE:
- case T_ENDIF:
- if (CPP_PEDANTIC (pfile) && pfile->if_stack != save_if_stack)
- validate_else (pfile,
- kt->type == T_ELSE ? "#else" : "#endif");
- case T_ELIF:
- if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
- {
- cpp_error (pfile,
- "`#%s' not within a conditional", kt->name);
- break;
- }
- else if (pfile->if_stack == save_if_stack)
- goto done; /* found what we came for */
-
- if (kt->type != T_ENDIF)
- {
- if (pfile->if_stack->type == T_ELSE)
- cpp_error (pfile, "`#else' or `#elif' after `#else'");
- pfile->if_stack->type = kt->type;
- break;
- }
-
- temp = pfile->if_stack;
- pfile->if_stack = temp->next;
- free (temp);
- break;
- default: ;
- }
- break;
+ CPP_PUTC (pfile, c);
+ pfile->lineno++;
}
- /* Don't let erroneous code go by. */
- if (kt->length < 0 && !CPP_OPTIONS (pfile)->lang_asm
- && CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "invalid preprocessor directive name");
+ CPP_BUMP_LINE (pfile);
}
- c = GETC ();
- }
- /* We're in the middle of a line. Skip the rest of it. */
- for (;;) {
- switch (c)
- {
- long old;
- case EOF:
- goto done;
- case '/': /* possible comment */
- c = skip_comment (pfile, NULL);
- if (c == EOF)
- goto done;
- break;
- case '\"':
- case '\'':
- FORWARD(-1);
- old = CPP_WRITTEN (pfile);
- cpp_get_token (pfile);
- CPP_SET_WRITTEN (pfile, old);
- break;
- case '\\':
- /* Char after backslash loses its special meaning. */
- if (PEEKC() == '\n')
- FORWARD (1);
- break;
- case '\n':
- goto beg_of_line;
- break;
- }
- c = GETC ();
- }
- done:
- if (CPP_OPTIONS (pfile)->output_conditionals) {
- static char end_failed[] = "#endfailed\n";
- CPP_PUTS (pfile, end_failed, sizeof(end_failed)-1);
- pfile->lineno++;
- }
+ }
+
+ /* Back up to the beginning of this line. Caller will process the
+ directive. */
+ CPP_BUFFER (pfile)->cur = beg_of_line;
pfile->only_seen_white = 1;
- parse_goto_mark (&line_start_mark, pfile);
- parse_clear_mark (&line_start_mark);
+ if (CPP_OPTIONS (pfile)->output_conditionals)
+ {
+ CPP_PUTS (pfile, "#endfailed\n", 11);
+ pfile->lineno++;
+ }
}
/*
@@ -4419,10 +1902,9 @@ skip_if_group (pfile, any)
*/
static int
-do_else (pfile, keyword, buf, limit)
+do_else (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
@@ -4449,10 +1931,10 @@ do_else (pfile, keyword, buf, limit)
}
if (pfile->if_stack->if_succeeded)
- skip_if_group (pfile, 0);
+ skip_if_group (pfile);
else {
++pfile->if_stack->if_succeeded; /* continue processing input */
- output_line_command (pfile, 1, same_file);
+ output_line_command (pfile, same_file);
}
return 0;
}
@@ -4462,10 +1944,9 @@ do_else (pfile, keyword, buf, limit)
*/
static int
-do_endif (pfile, keyword, buf, limit)
+do_endif (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
{
if (CPP_PEDANTIC (pfile))
validate_else (pfile, "#endif");
@@ -4481,10 +1962,9 @@ do_endif (pfile, keyword, buf, limit)
{
/* This #endif matched a #ifndef at the start of the file.
See if it is at the end of the file. */
- struct parse_marker start_mark;
int c;
- parse_set_mark (&start_mark, pfile);
+ parse_set_mark (pfile);
for (;;)
{
@@ -4493,40 +1973,23 @@ do_endif (pfile, keyword, buf, limit)
if (c != '\n')
break;
}
- parse_goto_mark (&start_mark, pfile);
- parse_clear_mark (&start_mark);
+ parse_goto_mark (pfile);
if (c == EOF)
{
- /* If we get here, this #endif ends a #ifndef
+ /* This #endif ends a #ifndef
that contains all of the file (aside from whitespace).
Arrange not to include the file again
- if the macro that was tested is defined.
-
- Do not do this for the top-level file in a -include or any
- file in a -imacros. */
-#if 0
-FIXME!
- if (indepth != 0
- && ! (indepth == 1 && pfile->no_record_file)
- && ! (pfile->no_record_file && no_output))
-#endif
- {
- struct file_name_list *ifile = pfile->all_include_files;
-
- for ( ; ifile != NULL; ifile = ifile->next)
- {
- if (!strcmp (ifile->fname, CPP_BUFFER (pfile)->fname))
- {
- ifile->control_macro = temp->control_macro;
- break;
- }
- }
- }
+ if the macro that was tested is defined. */
+ struct cpp_buffer *ip;
+ for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
+ if (ip->fname != NULL)
+ break;
+ ip->ihash->control_macro = (char *) temp->control_macro;
}
}
free (temp);
- output_line_command (pfile, 1, same_file);
+ output_line_command (pfile, same_file);
}
return 0;
}
@@ -4556,11 +2019,9 @@ cpp_get_token (pfile)
cpp_reader *pfile;
{
register int c, c2, c3;
- long old_written;
- long start_line, start_column;
enum cpp_token token;
struct cpp_options *opts = CPP_OPTIONS (pfile);
- CPP_BUFFER (pfile)->prev = CPP_BUFFER (pfile)->cur;
+
get_next:
c = GETC();
if (c == EOF)
@@ -4568,10 +2029,11 @@ cpp_get_token (pfile)
handle_eof:
if (CPP_BUFFER (pfile)->seen_eof)
{
- if (cpp_pop_buffer (pfile) != CPP_NULL_BUFFER (pfile))
- goto get_next;
- else
+ if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) == CPP_NULL_BUFFER (pfile))
return CPP_EOF;
+
+ cpp_pop_buffer (pfile);
+ goto get_next;
}
else
{
@@ -4587,7 +2049,7 @@ cpp_get_token (pfile)
cpp_buffer *cur_buffer = CPP_BUFFER (pfile);
CPP_BUFFER (pfile) = next_buf;
pfile->input_stack_listing_current = 0;
- output_line_command (pfile, 0, leave_file);
+ output_line_command (pfile, leave_file);
CPP_BUFFER (pfile) = cur_buffer;
}
return CPP_POP;
@@ -4597,68 +2059,27 @@ cpp_get_token (pfile)
{
switch (c)
{
- long newlines;
- struct parse_marker start_mark;
case '/':
if (PEEKC () == '=')
goto op2;
+
+ comment:
if (opts->put_out_comments)
- parse_set_mark (&start_mark, pfile);
- newlines = 0;
- cpp_buf_line_and_col (cpp_file_buffer (pfile),
- &start_line, &start_column);
- c = skip_comment (pfile, &newlines);
- if (opts->put_out_comments && (c == '/' || c == EOF))
- parse_clear_mark (&start_mark);
- if (c == '/')
- goto randomchar;
+ c = copy_comment (pfile, c);
+ else
+ c = skip_comment (pfile, c);
if (c == EOF)
- {
- cpp_error_with_line (pfile, start_line, start_column,
- "unterminated comment");
- goto handle_eof;
- }
- c = '/'; /* Initial letter of comment. */
- return_comment:
+ goto handle_eof;
+ else if (c != ' ')
+ goto randomchar;
+
/* Comments are equivalent to spaces.
For -traditional, a comment is equivalent to nothing. */
- if (opts->put_out_comments)
- {
- cpp_buffer *pbuf = CPP_BUFFER (pfile);
- U_CHAR *start = pbuf->buf + start_mark.position;
- int len = pbuf->cur - start;
- CPP_RESERVE(pfile, 1 + len);
- CPP_PUTC_Q (pfile, c);
- CPP_PUTS_Q (pfile, start, len);
- pfile->lineno += newlines;
- parse_clear_mark (&start_mark);
- return CPP_COMMENT;
- }
- else if (CPP_TRADITIONAL (pfile))
- {
- return CPP_COMMENT;
- }
+ if (opts->traditional || opts->put_out_comments)
+ return CPP_COMMENT;
else
{
-#if 0
- /* This may not work if cpp_get_token is called recursively,
- since many places look for horizontal space. */
- if (newlines)
- {
- /* Copy the newlines into the output buffer, in order to
- avoid the pain of a #line every time a multiline comment
- is seen. */
- CPP_RESERVE(pfile, newlines);
- while (--newlines >= 0)
- {
- CPP_PUTC_Q (pfile, '\n');
- pfile->lineno++;
- }
- return CPP_VSPACE;
- }
-#endif
- CPP_RESERVE(pfile, 1);
- CPP_PUTC_Q (pfile, ' ');
+ CPP_PUTC (pfile, c);
return CPP_HSPACE;
}
#if 0
@@ -4684,7 +2105,7 @@ cpp_get_token (pfile)
/* OK, now bring us back to the state we were in before we entered
this branch. We need #line because the newline for the pragma
could mess things up. */
- output_line_command (pfile, 0, same_file);
+ output_line_command (pfile, same_file);
*(obp++) = ' '; /* just in case, if comments are copied thru */
*(obp++) = '/';
}
@@ -4715,96 +2136,8 @@ cpp_get_token (pfile)
case '\"':
case '\'':
- /* A single quoted string is treated like a double -- some
- programs (e.g., troff) are perverse this way */
- cpp_buf_line_and_col (cpp_file_buffer (pfile),
- &start_line, &start_column);
- old_written = CPP_WRITTEN (pfile);
string:
- CPP_PUTC (pfile, c);
- while (1)
- {
- int cc = GETC();
- if (cc == EOF)
- {
- if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
- {
- /* try harder: this string crosses a macro expansion
- boundary. This can happen naturally if -traditional.
- Otherwise, only -D can make a macro with an unmatched
- quote. */
- cpp_buffer *next_buf
- = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
- (*CPP_BUFFER (pfile)->cleanup)
- (CPP_BUFFER (pfile), pfile);
- CPP_BUFFER (pfile) = next_buf;
- continue;
- }
- if (!CPP_TRADITIONAL (pfile))
- {
- cpp_error_with_line (pfile, start_line, start_column,
- "unterminated string or character constant");
- if (pfile->multiline_string_line != start_line
- && pfile->multiline_string_line != 0)
- cpp_error_with_line (pfile,
- pfile->multiline_string_line, -1,
- "possible real start of unterminated constant");
- pfile->multiline_string_line = 0;
- }
- break;
- }
- CPP_PUTC (pfile, cc);
- switch (cc)
- {
- case '\n':
- /* Traditionally, end of line ends a string constant with
- no error. So exit the loop and record the new line. */
- if (CPP_TRADITIONAL (pfile))
- goto while2end;
- if (c == '\'')
- {
- cpp_error_with_line (pfile, start_line, start_column,
- "unterminated character constant");
- goto while2end;
- }
- if (CPP_PEDANTIC (pfile)
- && pfile->multiline_string_line == 0)
- {
- cpp_pedwarn_with_line (pfile, start_line, start_column,
- "string constant runs past end of line");
- }
- if (pfile->multiline_string_line == 0)
- pfile->multiline_string_line = start_line;
- break;
-
- case '\\':
- cc = GETC();
- if (cc == '\n')
- {
- /* Backslash newline is replaced by nothing at all. */
- CPP_ADJUST_WRITTEN (pfile, -1);
- pfile->lineno++;
- }
- else
- {
- /* ANSI stupidly requires that in \\ the second \
- is *not* prevented from combining with a newline. */
- NEWLINE_FIX1(cc);
- if (cc != EOF)
- CPP_PUTC (pfile, cc);
- }
- break;
-
- case '\"':
- case '\'':
- if (cc == c)
- goto while2end;
- break;
- }
- }
- while2end:
- pfile->lineno += count_newlines (pfile->token_buffer + old_written,
- CPP_PWRITTEN (pfile));
+ parse_string (pfile, c);
pfile->only_seen_white = 0;
return c == '\'' ? CPP_CHAR : CPP_STRING;
@@ -4821,7 +2154,6 @@ cpp_get_token (pfile)
case '&':
case '+':
case '|':
- NEWLINE_FIX;
c2 = PEEKC ();
if (c2 == c || c2 == '=')
goto op2;
@@ -4832,35 +2164,14 @@ cpp_get_token (pfile)
case '%':
case '=':
case '^':
- NEWLINE_FIX;
if (PEEKC () == '=')
goto op2;
goto randomchar;
case '-':
- NEWLINE_FIX;
c2 = PEEKC ();
if (c2 == '-' && opts->chill)
- {
- /* Chill style comment */
- if (opts->put_out_comments)
- parse_set_mark (&start_mark, pfile);
- FORWARD(1); /* Skip second '-'. */
- for (;;)
- {
- c = GETC ();
- if (c == EOF)
- break;
- if (c == '\n')
- {
- /* Don't consider final '\n' to be part of comment. */
- FORWARD(-1);
- break;
- }
- }
- c = '-';
- goto return_comment;
- }
+ goto comment; /* Chill style comment */
if (c2 == '-' || c2 == '=' || c2 == '>')
goto op2;
goto randomchar;
@@ -4874,19 +2185,37 @@ cpp_get_token (pfile)
if (c == '>')
break;
c = GETC ();
- NEWLINE_FIX1 (c);
if (c == '\n' || c == EOF)
{
cpp_error (pfile,
"missing '>' in `#include <FILENAME>'");
break;
}
+ else if (c == '\r')
+ {
+ if (!CPP_BUFFER (pfile)->has_escapes)
+ {
+ /* Backslash newline is replaced by nothing. */
+ CPP_ADJUST_WRITTEN (pfile, -1);
+ CPP_BUMP_LINE (pfile);
+ }
+ else
+ {
+ /* We might conceivably get \r- or \r<space> in
+ here. Just delete 'em. */
+ int d = GETC();
+ if (d != '-' && d != ' ')
+ cpp_fatal (pfile,
+ "internal error: unrecognized escape \\r%c",
+ d);
+ CPP_ADJUST_WRITTEN (pfile, -1);
+ }
+ }
}
return CPP_STRING;
}
/* else fall through */
case '>':
- NEWLINE_FIX;
c2 = PEEKC ();
if (c2 == '=')
goto op2;
@@ -4896,7 +2225,6 @@ cpp_get_token (pfile)
CPP_RESERVE (pfile, 4);
CPP_PUTC (pfile, c);
CPP_PUTC (pfile, c2);
- NEWLINE_FIX;
c3 = PEEKC ();
if (c3 == '=')
CPP_PUTC_Q (pfile, GETC ());
@@ -4904,35 +2232,7 @@ cpp_get_token (pfile)
pfile->only_seen_white = 0;
return CPP_OTHER;
- case '@':
- if (CPP_BUFFER (pfile)->has_escapes)
- {
- c = GETC ();
- if (c == '-')
- {
- if (pfile->output_escapes)
- CPP_PUTS (pfile, "@-", 2);
- parse_name (pfile, GETC ());
- return CPP_NAME;
- }
- else if (is_space [c])
- {
- CPP_RESERVE (pfile, 2);
- if (pfile->output_escapes)
- CPP_PUTC_Q (pfile, '@');
- CPP_PUTC_Q (pfile, c);
- return CPP_HSPACE;
- }
- }
- if (pfile->output_escapes)
- {
- CPP_PUTS (pfile, "@@", 2);
- return CPP_OTHER;
- }
- goto randomchar;
-
case '.':
- NEWLINE_FIX;
c2 = PEEKC ();
if (ISDIGIT(c2))
{
@@ -4941,7 +2241,6 @@ cpp_get_token (pfile)
c = GETC ();
goto number;
}
- /* FIXME - misses the case "..\\\n." */
if (c2 == '.' && PEEKN(1) == '.')
{
CPP_RESERVE(pfile, 4);
@@ -4958,7 +2257,6 @@ cpp_get_token (pfile)
op2:
token = CPP_OTHER;
pfile->only_seen_white = 0;
- op2any:
CPP_RESERVE(pfile, 3);
CPP_PUTC_Q (pfile, c);
CPP_PUTC_Q (pfile, GETC ());
@@ -4966,7 +2264,6 @@ cpp_get_token (pfile)
return token;
case 'L':
- NEWLINE_FIX;
c2 = PEEKC ();
if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile))
{
@@ -4984,7 +2281,6 @@ cpp_get_token (pfile)
{
CPP_RESERVE (pfile, 2);
CPP_PUTC_Q (pfile, c);
- NEWLINE_FIX;
c = PEEKC ();
if (c == EOF)
break;
@@ -5014,14 +2310,7 @@ cpp_get_token (pfile)
if (c == EOF)
goto chill_number_eof;
if (!is_idchar[c])
- {
- if (c == '\\' && PEEKC() == '\n')
- {
- FORWARD(2);
- continue;
- }
- break;
- }
+ break;
CPP_PUTC (pfile, c);
}
if (c == '\'')
@@ -5068,13 +2357,13 @@ cpp_get_token (pfile)
if (hp->type == T_DISABLED)
{
if (pfile->output_escapes)
- { /* Return "@-IDENT", followed by '\0'. */
+ { /* Return "\r-IDENT", followed by '\0'. */
int i;
CPP_RESERVE (pfile, 3);
ident = pfile->token_buffer + before_name_written;
CPP_ADJUST_WRITTEN (pfile, 2);
for (i = ident_len; i >= 0; i--) ident[i+2] = ident[i];
- ident[0] = '@';
+ ident[0] = '\r';
ident[1] = '-';
}
return CPP_NAME;
@@ -5086,72 +2375,58 @@ cpp_get_token (pfile)
decide this is not a macro call and leave things that way. */
if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
{
- struct parse_marker macro_mark;
- int is_macro_call;
- while (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
- {
- cpp_buffer *next_buf;
- cpp_skip_hspace (pfile);
- if (PEEKC () != EOF)
- break;
- next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
- (*CPP_BUFFER (pfile)->cleanup) (CPP_BUFFER (pfile), pfile);
- CPP_BUFFER (pfile) = next_buf;
- }
- parse_set_mark (&macro_mark, pfile);
+ int is_macro_call, macbuf_whitespace = 0;
+
+ parse_set_mark (pfile);
for (;;)
{
cpp_skip_hspace (pfile);
c = PEEKC ();
is_macro_call = c == '(';
- if (c != '\n')
- break;
- FORWARD (1);
+ if (c != EOF)
+ {
+ if (c != '\n')
+ break;
+ FORWARD (1);
+ }
+ else
+ {
+ if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
+ {
+ if (CPP_BUFFER (pfile)->mark !=
+ (CPP_BUFFER (pfile)->cur
+ - CPP_BUFFER (pfile)->buf))
+ macbuf_whitespace = 1;
+
+ /* The mark goes away automatically when
+ the buffer is popped. */
+ cpp_pop_buffer (pfile);
+ parse_set_mark (pfile);
+ }
+ else
+ break;
+ }
}
if (!is_macro_call)
- parse_goto_mark (&macro_mark, pfile);
- parse_clear_mark (&macro_mark);
+ {
+ parse_goto_mark (pfile);
+ if (macbuf_whitespace)
+ CPP_PUTC (pfile, ' ');
+ }
+ else
+ parse_clear_mark (pfile);
if (!is_macro_call)
return CPP_NAME;
}
- /* This is now known to be a macro call. */
-
- /* it might not actually be a macro. */
- if (hp->type != T_MACRO) {
- int xbuf_len; U_CHAR *xbuf;
- CPP_SET_WRITTEN (pfile, before_name_written);
- special_symbol (hp, pfile);
- xbuf_len = CPP_WRITTEN (pfile) - before_name_written;
- xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
- CPP_SET_WRITTEN (pfile, before_name_written);
- bcopy (CPP_PWRITTEN (pfile), xbuf, xbuf_len + 1);
- push_macro_expansion (pfile, xbuf, xbuf_len, hp);
- }
- else
- {
- /* Expand the macro, reading arguments as needed,
- and push the expansion on the input stack. */
- macroexpand (pfile, hp);
- CPP_SET_WRITTEN (pfile, before_name_written);
- }
-
- /* An extra "@ " is added to the end of a macro expansion
- to prevent accidental token pasting. We prefer to avoid
- unneeded extra spaces (for the sake of cpp-using tools like
- imake). Here we remove the space if it is safe to do so. */
- if (pfile->buffer->rlimit - pfile->buffer->cur >= 3
- && pfile->buffer->rlimit[-2] == '@'
- && pfile->buffer->rlimit[-1] == ' ')
- {
- int c1 = pfile->buffer->rlimit[-3];
- int c2 = CPP_BUF_PEEK (CPP_PREV_BUFFER (CPP_BUFFER (pfile)));
- if (c2 == EOF || ! unsafe_chars (c1, c2))
- pfile->buffer->rlimit -= 2;
- }
+ /* This is now known to be a macro call.
+ Expand the macro, reading arguments as needed,
+ and push the expansion on the input stack. */
+ macroexpand (pfile, hp);
+ CPP_SET_WRITTEN (pfile, before_name_written);
}
goto get_next;
- case ' ': case '\t': case '\v': case '\r':
+ case ' ': case '\t': case '\v':
for (;;)
{
CPP_PUTC (pfile, c);
@@ -5162,19 +2437,50 @@ cpp_get_token (pfile)
}
return CPP_HSPACE;
- case '\\':
- c2 = PEEKC ();
- if (c2 != '\n')
- goto randomchar;
- token = CPP_HSPACE;
- goto op2any;
+ case '\r':
+ if (CPP_BUFFER (pfile)->has_escapes)
+ {
+ c = GETC ();
+ if (c == '-')
+ {
+ if (pfile->output_escapes)
+ CPP_PUTS (pfile, "\r-", 2);
+ parse_name (pfile, GETC ());
+ return CPP_NAME;
+ }
+ else if (c == ' ')
+ {
+ CPP_RESERVE (pfile, 2);
+ if (pfile->output_escapes)
+ CPP_PUTC_Q (pfile, '\r');
+ CPP_PUTC_Q (pfile, c);
+ return CPP_HSPACE;
+ }
+ else
+ {
+ cpp_fatal (pfile,
+ "internal error: unrecognized escape \\r%c", c);
+ goto get_next;
+ }
+ }
+ else
+ {
+ /* Backslash newline is ignored. */
+ CPP_BUMP_LINE (pfile);
+ goto get_next;
+ }
case '\n':
CPP_PUTC (pfile, c);
if (pfile->only_seen_white == 0)
pfile->only_seen_white = 1;
- pfile->lineno++;
- output_line_command (pfile, 1, same_file);
+ CPP_BUMP_LINE (pfile);
+ if (! CPP_OPTIONS (pfile)->no_line_commands)
+ {
+ pfile->lineno++;
+ if (CPP_BUFFER (pfile)->lineno != pfile->lineno)
+ output_line_command (pfile, same_file);
+ }
return CPP_VSPACE;
case '(': token = CPP_LPAREN; goto char1;
@@ -5214,19 +2520,15 @@ cpp_get_non_space_token (pfile)
/* Parse an identifier starting with C. */
-static int
+static void
parse_name (pfile, c)
- cpp_reader *pfile; int c;
+ cpp_reader *pfile;
+ int c;
{
for (;;)
{
if (! is_idchar[c])
{
- if (c == '\\' && PEEKC() == '\n')
- {
- FORWARD(2);
- continue;
- }
FORWARD (-1);
break;
}
@@ -5241,2179 +2543,393 @@ parse_name (pfile, c)
break;
}
CPP_NUL_TERMINATE_Q (pfile);
- return 1;
-}
-
-
-/* Maintain and search list of included files, for #import. */
-
-/* Hash a file name for import_hash_table. */
-
-static int
-import_hash (f)
- char *f;
-{
- int val = 0;
-
- while (*f) val += *f++;
- return (val%IMPORT_HASH_SIZE);
-}
-
-/* Search for file FILENAME in import_hash_table.
- Return -2 if found, either a matching name or a matching inode.
- Otherwise, open the file and return a file descriptor if successful
- or -1 if unsuccessful. */
-
-static int
-lookup_import (pfile, filename, searchptr)
- cpp_reader *pfile;
- char *filename;
- struct file_name_list *searchptr;
-{
- struct import_file *i;
- int h;
- int hashval;
- struct stat sb;
- int fd;
-
- hashval = import_hash (filename);
-
- /* Attempt to find file in list of already included files */
- i = pfile->import_hash_table[hashval];
-
- while (i) {
- if (!strcmp (filename, i->name))
- return -2; /* return found */
- i = i->next;
- }
- /* Open it and try a match on inode/dev */
- fd = open_include_file (pfile, filename, searchptr);
- if (fd < 0)
- return fd;
- fstat (fd, &sb);
- for (h = 0; h < IMPORT_HASH_SIZE; h++) {
- i = pfile->import_hash_table[h];
- while (i) {
- /* Compare the inode and the device.
- Supposedly on some systems the inode is not a scalar. */
- if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
- && i->dev == sb.st_dev) {
- close (fd);
- return -2; /* return found */
- }
- i = i->next;
- }
- }
- return fd; /* Not found, return open file */
+ return;
}
-/* Add the file FNAME, open on descriptor FD, to import_hash_table. */
-
+/* Parse a string starting with C. A single quoted string is treated
+ like a double -- some programs (e.g., troff) are perverse this way.
+ (However, a single quoted string is not allowed to extend over
+ multiple lines. */
static void
-add_import (pfile, fd, fname)
+parse_string (pfile, c)
cpp_reader *pfile;
- int fd;
- char *fname;
+ int c;
{
- struct import_file *i;
- int hashval;
- struct stat sb;
-
- hashval = import_hash (fname);
- fstat (fd, &sb);
- i = (struct import_file *)xmalloc (sizeof (struct import_file));
- i->name = (char *)xmalloc (strlen (fname)+1);
- strcpy (i->name, fname);
- bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
- i->dev = sb.st_dev;
- i->next = pfile->import_hash_table[hashval];
- pfile->import_hash_table[hashval] = i;
-}
-
-/* The file_name_map structure holds a mapping of file names for a
- particular directory. This mapping is read from the file named
- FILE_NAME_MAP_FILE in that directory. Such a file can be used to
- map filenames on a file system with severe filename restrictions,
- such as DOS. The format of the file name map file is just a series
- of lines with two tokens on each line. The first token is the name
- to map, and the second token is the actual name to use. */
-
-struct file_name_map
-{
- struct file_name_map *map_next;
- char *map_from;
- char *map_to;
-};
-
-#define FILE_NAME_MAP_FILE "header.gcc"
-
-/* Read a space delimited string of unlimited length from a stdio
- file. */
-
-static char *
-read_filename_string (ch, f)
- int ch;
- FILE *f;
-{
- char *alloc, *set;
- int len;
+ long start_line, start_column;
+
+ cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
- len = 20;
- set = alloc = xmalloc (len + 1);
- if (! is_space[ch])
+ CPP_PUTC (pfile, c);
+ while (1)
{
- *set++ = ch;
- while ((ch = getc (f)) != EOF && ! is_space[ch])
+ int cc = GETC();
+ if (cc == EOF)
{
- if (set - alloc == len)
+ if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
{
- len *= 2;
- alloc = xrealloc (alloc, len + 1);
- set = alloc + len / 2;
+ /* try harder: this string crosses a macro expansion
+ boundary. This can happen naturally if -traditional.
+ Otherwise, only -D can make a macro with an unmatched
+ quote. */
+ cpp_pop_buffer (pfile);
+ continue;
}
- *set++ = ch;
- }
- }
- *set = '\0';
- ungetc (ch, f);
- return alloc;
-}
-
-/* This structure holds a linked list of file name maps, one per directory. */
-
-struct file_name_map_list
-{
- struct file_name_map_list *map_list_next;
- char *map_list_name;
- struct file_name_map *map_list_map;
-};
-
-/* Read the file name map file for DIRNAME. */
-
-static struct file_name_map *
-read_name_map (pfile, dirname)
- cpp_reader *pfile;
- char *dirname;
-{
- register struct file_name_map_list *map_list_ptr;
- char *name;
- FILE *f;
-
- for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
- map_list_ptr = map_list_ptr->map_list_next)
- if (! strcmp (map_list_ptr->map_list_name, dirname))
- return map_list_ptr->map_list_map;
-
- map_list_ptr = ((struct file_name_map_list *)
- xmalloc (sizeof (struct file_name_map_list)));
- map_list_ptr->map_list_name = savestring (dirname);
- map_list_ptr->map_list_map = NULL;
-
- name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2);
- strcpy (name, dirname);
- if (*dirname)
- strcat (name, "/");
- strcat (name, FILE_NAME_MAP_FILE);
- f = fopen (name, "r");
- if (!f)
- map_list_ptr->map_list_map = NULL;
- else
- {
- int ch;
- int dirlen = strlen (dirname);
-
- while ((ch = getc (f)) != EOF)
- {
- char *from, *to;
- struct file_name_map *ptr;
-
- if (is_space[ch])
- continue;
- from = read_filename_string (ch, f);
- while ((ch = getc (f)) != EOF && is_hor_space[ch])
- ;
- to = read_filename_string (ch, f);
-
- ptr = ((struct file_name_map *)
- xmalloc (sizeof (struct file_name_map)));
- ptr->map_from = from;
-
- /* Make the real filename absolute. */
- if (*to == '/')
- ptr->map_to = to;
- else
+ if (!CPP_TRADITIONAL (pfile))
{
- ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
- strcpy (ptr->map_to, dirname);
- ptr->map_to[dirlen] = '/';
- strcpy (ptr->map_to + dirlen + 1, to);
- free (to);
- }
-
- ptr->map_next = map_list_ptr->map_list_map;
- map_list_ptr->map_list_map = ptr;
-
- while ((ch = getc (f)) != '\n')
- if (ch == EOF)
- break;
+ cpp_error_with_line (pfile, start_line, start_column,
+ "unterminated string or character constant");
+ if (pfile->multiline_string_line != start_line
+ && pfile->multiline_string_line != 0)
+ cpp_error_with_line (pfile,
+ pfile->multiline_string_line, -1,
+ "possible real start of unterminated constant");
+ pfile->multiline_string_line = 0;
+ }
+ break;
}
- fclose (f);
- }
-
- map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
- CPP_OPTIONS (pfile)->map_list = map_list_ptr;
-
- return map_list_ptr->map_list_map;
-}
-
-/* Try to open include file FILENAME. SEARCHPTR is the directory
- being tried from the include file search path. This function maps
- filenames on file systems based on information read by
- read_name_map. */
-
-static int
-open_include_file (pfile, filename, searchptr)
- cpp_reader *pfile;
- char *filename;
- struct file_name_list *searchptr;
-{
- if (CPP_OPTIONS (pfile)->remap)
- {
- register struct file_name_map *map;
- register char *from;
- char *p, *dir;
-
- if (searchptr && ! searchptr->got_name_map)
+ CPP_PUTC (pfile, cc);
+ switch (cc)
{
- searchptr->name_map = read_name_map (pfile,
- searchptr->fname
- ? searchptr->fname : ".");
- searchptr->got_name_map = 1;
- }
+ case '\n':
+ CPP_BUMP_LINE (pfile);
+ pfile->lineno++;
+ /* Traditionally, end of line ends a string constant with
+ no error. */
+ if (CPP_TRADITIONAL (pfile))
+ return;
+ /* Character constants may not extend over multiple lines. */
+ if (c == '\'')
+ {
+ cpp_error_with_line (pfile, start_line, start_column,
+ "unterminated character constant");
+ return;
+ }
+ if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
+ {
+ cpp_pedwarn_with_line (pfile, start_line, start_column,
+ "string constant runs past end of line");
+ }
+ if (pfile->multiline_string_line == 0)
+ pfile->multiline_string_line = start_line;
+ break;
- /* First check the mapping for the directory we are using. */
- if (searchptr && searchptr->name_map)
- {
- from = filename;
- if (searchptr->fname)
- from += strlen (searchptr->fname) + 1;
- for (map = searchptr->name_map; map; map = map->map_next)
+ case '\r':
+ CPP_ADJUST_WRITTEN (pfile, -1);
+ if (CPP_BUFFER (pfile)->has_escapes)
{
- if (! strcmp (map->map_from, from))
- {
- /* Found a match. */
- return open (map->map_to, O_RDONLY, 0666);
- }
+ cpp_fatal (pfile,
+ "internal error: \\r escape inside string constant");
+ FORWARD(1);
}
- }
+ else
+ /* Backslash newline is replaced by nothing at all. */
+ CPP_BUMP_LINE (pfile);
+ break;
- /* Try to find a mapping file for the particular directory we are
- looking in. Thus #include <sys/types.h> will look up sys/types.h
- in /usr/include/header.gcc and look up types.h in
- /usr/include/sys/header.gcc. */
- p = rindex (filename, '/');
- if (! p)
- p = filename;
- if (searchptr
- && searchptr->fname
- && strlen (searchptr->fname) == p - filename
- && ! strncmp (searchptr->fname, filename, p - filename))
- {
- /* FILENAME is in SEARCHPTR, which we've already checked. */
- return open (filename, O_RDONLY, 0666);
- }
+ case '\\':
+ cc = GETC();
+ if (cc != EOF)
+ CPP_PUTC (pfile, cc);
+ break;
- if (p == filename)
- {
- dir = ".";
- from = filename;
- }
- else
- {
- dir = (char *) alloca (p - filename + 1);
- bcopy (filename, dir, p - filename);
- dir[p - filename] = '\0';
- from = p + 1;
+ case '\"':
+ case '\'':
+ if (cc == c)
+ return;
+ break;
}
- for (map = read_name_map (pfile, dir); map; map = map->map_next)
- if (! strcmp (map->map_from, from))
- return open (map->map_to, O_RDONLY, 0666);
}
-
- return open (filename, O_RDONLY, 0666);
}
-/* Process the contents of include file FNAME, already open on descriptor F,
- with output to OP.
- SYSTEM_HEADER_P is 1 if this file resides in any one of the known
- "system" include directories (as decided by the `is_system_include'
- function above).
- DIRPTR is the link in the dir path through which this file was found,
- or 0 if the file name was absolute or via the current directory.
- Return 1 on success, 0 on failure.
-
- The caller is responsible for the cpp_push_buffer. */
-
+/* Read an assertion into the token buffer, converting to
+ canonical form: `#predicate(a n swe r)' The next non-whitespace
+ character to read should be the first letter of the predicate.
+ Returns 0 for syntax error, 1 for bare predicate, 2 for predicate
+ with answer (see callers for why). In case of 0, an error has been
+ printed. */
static int
-finclude (pfile, f, fname, system_header_p, dirptr)
- cpp_reader *pfile;
- int f;
- char *fname;
- int system_header_p;
- struct file_name_list *dirptr;
-{
- struct stat st;
- size_t st_size;
- long i;
- int length;
- cpp_buffer *fp; /* For input stack frame */
-#if 0
- int missing_newline = 0;
-#endif
-
- if (fstat (f, &st) < 0)
- {
- cpp_perror_with_name (pfile, fname);
- close (f);
- cpp_pop_buffer (pfile);
- return 0;
- }
-
- fp = CPP_BUFFER (pfile);
- fp->nominal_fname = fp->fname = fname;
-#if 0
- fp->length = 0;
-#endif
- fp->dir = dirptr;
- fp->system_header_p = system_header_p;
- fp->lineno = 1;
- fp->colno = 1;
- fp->cleanup = file_cleanup;
-
- if (S_ISREG (st.st_mode)) {
- st_size = (size_t) st.st_size;
- if (st_size != st.st_size || st_size + 2 < st_size) {
- cpp_error (pfile, "file `%s' too large", fname);
- close (f);
- return 0;
- }
- fp->buf = (U_CHAR *) xmalloc (st_size + 2);
- fp->alimit = fp->buf + st_size + 2;
- fp->cur = fp->buf;
-
- /* Read the file contents, knowing that st_size is an upper bound
- on the number of bytes we can read. */
- length = safe_read (f, fp->buf, st_size);
- fp->rlimit = fp->buf + length;
- if (length < 0) goto nope;
- }
- else if (S_ISDIR (st.st_mode)) {
- cpp_error (pfile, "directory `%s' specified in #include", fname);
- close (f);
- return 0;
- } else {
- /* Cannot count its file size before reading.
- First read the entire file into heap and
- copy them into buffer on stack. */
-
- int bsize = 2000;
-
- st_size = 0;
- fp->buf = (U_CHAR *) xmalloc (bsize + 2);
-
- for (;;) {
- i = safe_read (f, fp->buf + st_size, bsize - st_size);
- if (i < 0)
- goto nope; /* error! */
- st_size += i;
- if (st_size != bsize)
- break; /* End of file */
- bsize *= 2;
- fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
- }
- fp->cur = fp->buf;
- length = st_size;
- }
-
- if ((length > 0 && fp->buf[length - 1] != '\n')
- /* Backslash-newline at end is not good enough. */
- || (length > 1 && fp->buf[length - 2] == '\\')) {
- fp->buf[length++] = '\n';
-#if 0
- missing_newline = 1;
-#endif
- }
- fp->buf[length] = '\0';
- fp->rlimit = fp->buf + length;
-
- /* Close descriptor now, so nesting does not use lots of descriptors. */
- close (f);
-
- /* Must do this before calling trigraph_pcp, so that the correct file name
- will be printed in warning messages. */
-
- pfile->input_stack_listing_current = 0;
-
-#if 0
- if (!no_trigraphs)
- trigraph_pcp (fp);
-#endif
-
-#if 0
- rescan (op, 0);
-
- if (missing_newline)
- fp->lineno--;
-
- if (CPP_PEDANTIC (pfile) && missing_newline)
- pedwarn ("file does not end in newline");
-
- indepth--;
- input_file_stack_tick++;
- free (fp->buf);
-#endif
- return 1;
-
- nope:
-
- cpp_perror_with_name (pfile, fname);
- close (f);
- free (fp->buf);
- return 1;
-}
-
-/* This is called after options have been processed.
- * Check options for consistency, and setup for processing input
- * from the file named FNAME. (Use standard input if FNAME==NULL.)
- * Return 1 on success, 0 on failure.
- */
-
-int
-cpp_start_read (pfile, fname)
+parse_assertion (pfile)
cpp_reader *pfile;
- char *fname;
{
- struct cpp_options *opts = CPP_OPTIONS (pfile);
- struct cpp_pending *pend;
- char *p;
- int f;
- cpp_buffer *fp;
-
- /* The code looks at the defaults through this pointer, rather than through
- the constant structure above. This pointer gets changed if an environment
- variable specifies other defaults. */
- struct default_include *include_defaults = include_defaults_array;
-
- /* Add dirs from CPATH after dirs from -I. */
- /* There seems to be confusion about what CPATH should do,
- so for the moment it is not documented. */
- /* Some people say that CPATH should replace the standard include dirs,
- but that seems pointless: it comes before them, so it overrides them
- anyway. */
- GET_ENVIRONMENT (p, "CPATH");
- if (p != 0 && ! opts->no_standard_includes)
- path_include (pfile, p);
-
- /* Now that dollars_in_ident is known, initialize is_idchar. */
- initialize_char_syntax (opts);
-
- /* Do partial setup of input buffer for the sake of generating
- early #line directives (when -g is in effect). */
- fp = cpp_push_buffer (pfile, NULL, 0);
- if (!fp)
- return 0;
- if (opts->in_fname == NULL)
- opts->in_fname = "";
- fp->nominal_fname = fp->fname = opts->in_fname;
- fp->lineno = 0;
-
- /* Install __LINE__, etc. Must follow initialize_char_syntax
- and option processing. */
- initialize_builtins (pfile);
-
- /* Do standard #defines and assertions
- that identify system and machine type. */
-
- if (!opts->inhibit_predefs) {
- char *p = (char *) alloca (strlen (predefs) + 1);
- strcpy (p, predefs);
- while (*p) {
- char *q;
- while (*p == ' ' || *p == '\t')
- p++;
- /* Handle -D options. */
- if (p[0] == '-' && p[1] == 'D') {
- q = &p[2];
- while (*p && *p != ' ' && *p != '\t')
- p++;
- if (*p != 0)
- *p++= 0;
- if (opts->debug_output)
- output_line_command (pfile, 0, same_file);
- cpp_define (pfile, q);
- while (*p == ' ' || *p == '\t')
- p++;
- } else if (p[0] == '-' && p[1] == 'A') {
- /* Handle -A options (assertions). */
- char *assertion;
- char *past_name;
- char *value;
- char *past_value;
- char *termination;
- int save_char;
-
- assertion = &p[2];
- past_name = assertion;
- /* Locate end of name. */
- while (*past_name && *past_name != ' '
- && *past_name != '\t' && *past_name != '(')
- past_name++;
- /* Locate `(' at start of value. */
- value = past_name;
- while (*value && (*value == ' ' || *value == '\t'))
- value++;
- if (*value++ != '(')
- abort ();
- while (*value && (*value == ' ' || *value == '\t'))
- value++;
- past_value = value;
- /* Locate end of value. */
- while (*past_value && *past_value != ' '
- && *past_value != '\t' && *past_value != ')')
- past_value++;
- termination = past_value;
- while (*termination && (*termination == ' ' || *termination == '\t'))
- termination++;
- if (*termination++ != ')')
- abort ();
- if (*termination && *termination != ' ' && *termination != '\t')
- abort ();
- /* Temporarily null-terminate the value. */
- save_char = *termination;
- *termination = '\0';
- /* Install the assertion. */
- make_assertion (pfile, "-A", assertion);
- *termination = (char) save_char;
- p = termination;
- while (*p == ' ' || *p == '\t')
- p++;
- } else {
- abort ();
- }
- }
- }
-
- /* Now handle the command line options. */
-
- /* Do -U's, -D's and -A's in the order they were seen. */
- /* First reverse the list. */
- opts->pending = nreverse_pending (opts->pending);
-
- for (pend = opts->pending; pend; pend = pend->next)
- {
- if (pend->cmd != NULL && pend->cmd[0] == '-')
- {
- switch (pend->cmd[1])
- {
- case 'U':
- if (opts->debug_output)
- output_line_command (pfile, 0, same_file);
- do_undef (pfile, NULL, pend->arg, pend->arg + strlen (pend->arg));
- break;
- case 'D':
- if (opts->debug_output)
- output_line_command (pfile, 0, same_file);
- cpp_define (pfile, pend->arg);
- break;
- case 'A':
- make_assertion (pfile, "-A", pend->arg);
- break;
- }
- }
- }
-
- opts->done_initializing = 1;
-
- { /* Read the appropriate environment variable and if it exists
- replace include_defaults with the listed path. */
- char *epath = 0;
- switch ((opts->objc << 1) + opts->cplusplus)
- {
- case 0:
- GET_ENVIRONMENT (epath, "C_INCLUDE_PATH");
- break;
- case 1:
- GET_ENVIRONMENT (epath, "CPLUS_INCLUDE_PATH");
- break;
- case 2:
- GET_ENVIRONMENT (epath, "OBJC_INCLUDE_PATH");
- break;
- case 3:
- GET_ENVIRONMENT (epath, "OBJCPLUS_INCLUDE_PATH");
- break;
- }
- /* If the environment var for this language is set,
- add to the default list of include directories. */
- if (epath) {
- char *nstore = (char *) alloca (strlen (epath) + 2);
- int num_dirs;
- char *startp, *endp;
-
- for (num_dirs = 1, startp = epath; *startp; startp++)
- if (*startp == PATH_SEPARATOR)
- num_dirs++;
- include_defaults
- = (struct default_include *) xmalloc ((num_dirs
- * sizeof (struct default_include))
- + sizeof (include_defaults_array));
- startp = endp = epath;
- num_dirs = 0;
- while (1) {
- /* Handle cases like c:/usr/lib:d:/gcc/lib */
- if ((*endp == PATH_SEPARATOR)
- || *endp == 0) {
- strncpy (nstore, startp, endp-startp);
- if (endp == startp)
- strcpy (nstore, ".");
- else
- nstore[endp-startp] = '\0';
-
- include_defaults[num_dirs].fname = savestring (nstore);
- include_defaults[num_dirs].component = 0;
- include_defaults[num_dirs].cplusplus = opts->cplusplus;
- include_defaults[num_dirs].cxx_aware = 1;
- num_dirs++;
- if (*endp == '\0')
- break;
- endp = startp = endp + 1;
- } else
- endp++;
- }
- /* Put the usual defaults back in at the end. */
- bcopy ((char *) include_defaults_array,
- (char *) &include_defaults[num_dirs],
- sizeof (include_defaults_array));
- }
- }
-
- append_include_chain (pfile, opts->before_system, opts->last_before_system);
- opts->first_system_include = opts->before_system;
-
- /* Unless -fnostdinc,
- tack on the standard include file dirs to the specified list */
- if (!opts->no_standard_includes) {
- struct default_include *p = include_defaults;
- char *specd_prefix = opts->include_prefix;
- char *default_prefix = savestring (GCC_INCLUDE_DIR);
- int default_len = 0;
- /* Remove the `include' from /usr/local/lib/gcc.../include. */
- if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
- default_len = strlen (default_prefix) - 7;
- default_prefix[default_len] = 0;
- }
- /* Search "translated" versions of GNU directories.
- These have /usr/local/lib/gcc... replaced by specd_prefix. */
- if (specd_prefix != 0 && default_len != 0)
- for (p = include_defaults; p->fname; p++) {
- /* Some standard dirs are only for C++. */
- if (!p->cplusplus
- || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
- /* Does this dir start with the prefix? */
- if (!strncmp (p->fname, default_prefix, default_len)) {
- /* Yes; change prefix and add to search list. */
- struct file_name_list *new
- = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
- int this_len = strlen (specd_prefix) + strlen (p->fname) - default_len;
- char *str = (char *) xmalloc (this_len + 1);
- strcpy (str, specd_prefix);
- strcat (str, p->fname + default_len);
- new->fname = str;
- new->control_macro = 0;
- new->c_system_include_path = !p->cxx_aware;
- new->got_name_map = 0;
- append_include_chain (pfile, new, new);
- if (opts->first_system_include == 0)
- opts->first_system_include = new;
- }
- }
- }
- /* Search ordinary names for GNU include directories. */
- for (p = include_defaults; p->fname; p++) {
- /* Some standard dirs are only for C++. */
- if (!p->cplusplus
- || (opts->cplusplus && !opts->no_standard_cplusplus_includes)) {
- struct file_name_list *new
- = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
- new->control_macro = 0;
- new->c_system_include_path = !p->cxx_aware;
- new->fname = update_path (p->fname, p->component);
- new->got_name_map = 0;
- append_include_chain (pfile, new, new);
- if (opts->first_system_include == 0)
- opts->first_system_include = new;
- }
- }
- }
-
- /* Tack the after_include chain at the end of the include chain. */
- append_include_chain (pfile, opts->after_include, opts->last_after_include);
- if (opts->first_system_include == 0)
- opts->first_system_include = opts->after_include;
-
- /* With -v, print the list of dirs to search. */
- if (opts->verbose) {
- struct file_name_list *p;
- fprintf (stderr, "#include \"...\" search starts here:\n");
- for (p = opts->include; p; p = p->next) {
- if (p == opts->first_bracket_include)
- fprintf (stderr, "#include <...> search starts here:\n");
- fprintf (stderr, " %s\n", p->fname);
- }
- fprintf (stderr, "End of search list.\n");
- }
-
- /* Scan the -imacros files before the main input.
- Much like #including them, but with no_output set
- so that only their macro definitions matter. */
-
- opts->no_output++; pfile->no_record_file++;
- for (pend = opts->pending; pend; pend = pend->next)
- {
- if (pend->cmd != NULL && strcmp (pend->cmd, "-imacros") == 0)
- {
- int fd = open (pend->arg, O_RDONLY, 0666);
- if (fd < 0)
- {
- cpp_perror_with_name (pfile, pend->arg);
- return 0;
- }
- if (!cpp_push_buffer (pfile, NULL, 0))
- return 0;
- finclude (pfile, fd, pend->arg, 0, NULL_PTR);
- cpp_scan_buffer (pfile);
- }
- }
- opts->no_output--; pfile->no_record_file--;
-
- /* Copy the entire contents of the main input file into
- the stacked input buffer previously allocated for it. */
- if (fname == NULL || *fname == 0) {
- fname = "";
- f = 0;
- } else if ((f = open (fname, O_RDONLY, 0666)) < 0)
- cpp_pfatal_with_name (pfile, fname);
-
- /* -MG doesn't select the form of output and must be specified with one of
- -M or -MM. -MG doesn't make sense with -MD or -MMD since they don't
- inhibit compilation. */
- if (opts->print_deps_missing_files
- && (opts->print_deps == 0 || !opts->no_output))
+ int c, dropwhite;
+ cpp_skip_hspace (pfile);
+ c = PEEKC();
+ if (! is_idstart[c])
{
- cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
+ cpp_error (pfile, "assertion predicate is not an identifier");
return 0;
}
+ CPP_PUTC(pfile, '#');
+ FORWARD(1);
+ parse_name(pfile, c);
- /* Either of two environment variables can specify output of deps.
- Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
- where OUTPUT_FILE is the file to write deps info to
- and DEPS_TARGET is the target to mention in the deps. */
-
- if (opts->print_deps == 0
- && (getenv ("SUNPRO_DEPENDENCIES") != 0
- || getenv ("DEPENDENCIES_OUTPUT") != 0)) {
- char *spec = getenv ("DEPENDENCIES_OUTPUT");
- char *s;
- char *output_file;
-
- if (spec == 0)
- {
- spec = getenv ("SUNPRO_DEPENDENCIES");
- opts->print_deps = 2;
- }
- else
- opts->print_deps = 1;
-
- s = spec;
- /* Find the space before the DEPS_TARGET, if there is one. */
- /* This should use index. (mrs) */
- while (*s != 0 && *s != ' ') s++;
- if (*s != 0)
- {
- opts->deps_target = s + 1;
- output_file = (char *) xmalloc (s - spec + 1);
- bcopy (spec, output_file, s - spec);
- output_file[s - spec] = 0;
- }
- else
- {
- opts->deps_target = 0;
- output_file = spec;
- }
-
- opts->deps_file = output_file;
- opts->print_deps_append = 1;
- }
-
- /* For -M, print the expected object file name
- as the target of this Make-rule. */
- if (opts->print_deps)
+ c = PEEKC();
+ if (c != '(')
{
- pfile->deps_allocated_size = 200;
- pfile->deps_buffer = (char *) xmalloc (pfile->deps_allocated_size);
- pfile->deps_buffer[0] = 0;
- pfile->deps_size = 0;
- pfile->deps_column = 0;
-
- if (opts->deps_target)
- deps_output (pfile, opts->deps_target, ':');
- else if (*opts->in_fname == 0)
- deps_output (pfile, "-", ':');
- else
- {
- char *p, *q, *r;
- int len, x;
- static char *known_suffixes[] = { ".c", ".C", ".s", ".S", ".m",
- ".cc", ".cxx", ".cpp", ".cp",
- ".c++", 0
- };
-
- /* Discard all directory prefixes from filename. */
- if ((q = rindex (opts->in_fname, '/')) != NULL
-#ifdef DIR_SEPARATOR
- && (q = rindex (opts->in_fname, DIR_SEPARATOR)) != NULL
-#endif
- )
- ++q;
- else
- q = opts->in_fname;
-
- /* Copy remainder to mungable area. */
- p = (char *) alloca (strlen(q) + 8);
- strcpy (p, q);
-
- /* Output P, but remove known suffixes. */
- len = strlen (p);
- q = p + len;
- /* Point to the filename suffix. */
- r = rindex (p, '.');
- /* Compare against the known suffixes. */
- x = 0;
- while (known_suffixes[x] != 0)
- {
- if (strncmp (known_suffixes[x], r, q - r) == 0)
- {
- /* Make q point to the bit we're going to overwrite
- with an object suffix. */
- q = r;
- break;
- }
- x++;
- }
-
- /* Supply our own suffix. */
-#ifndef VMS
- strcpy (q, ".o");
-#else
- strcpy (q, ".obj");
-#endif
-
- deps_output (pfile, p, ':');
- deps_output (pfile, opts->in_fname, ' ');
- }
+ if (is_hor_space[c] || c == '\r')
+ cpp_skip_hspace (pfile);
+ c = PEEKC();
}
+ if (c != '(')
+ return 1;
-#if 0
- /* Make sure data ends with a newline. And put a null after it. */
-
- if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n')
- /* Backslash-newline at end is not good enough. */
- || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) {
- fp->buf[fp->length++] = '\n';
- missing_newline = 1;
- }
- fp->buf[fp->length] = '\0';
-
- /* Unless inhibited, convert trigraphs in the input. */
-
- if (!no_trigraphs)
- trigraph_pcp (fp);
-#endif
-
- /* Scan the -include files before the main input.
- We push these in reverse order, so that the first one is handled first. */
-
- pfile->no_record_file++;
- opts->pending = nreverse_pending (opts->pending);
- for (pend = opts->pending; pend; pend = pend->next)
+ CPP_PUTC(pfile, '(');
+ FORWARD(1);
+ dropwhite = 1;
+ while ((c = GETC()) != ')')
{
- if (pend->cmd != NULL && strcmp (pend->cmd, "-include") == 0)
+ if (is_hor_space[c])
{
- int fd = open (pend->arg, O_RDONLY, 0666);
- if (fd < 0)
+ if (! dropwhite)
{
- cpp_perror_with_name (pfile, pend->arg);
- return 0;
+ CPP_PUTC(pfile, ' ');
+ dropwhite = 1;
}
- if (!cpp_push_buffer (pfile, NULL, 0))
- return 0;
- finclude (pfile, fd, pend->arg, 0, NULL_PTR);
}
- }
- pfile->no_record_file--;
-
- /* Free the pending list. */
- for (pend = opts->pending; pend; )
- {
- struct cpp_pending *next = pend->next;
- free (pend);
- pend = next;
- }
- opts->pending = NULL;
-
-#if 0
- /* Scan the input, processing macros and directives. */
-
- rescan (&outbuf, 0);
-
- if (missing_newline)
- fp->lineno--;
-
- if (CPP_PEDANTIC (pfile) && missing_newline)
- pedwarn ("file does not end in newline");
-
-#endif
- if (finclude (pfile, f, fname, 0, NULL_PTR))
- output_line_command (pfile, 0, same_file);
- return 1;
-}
-
-void
-cpp_reader_init (pfile)
- cpp_reader *pfile;
-{
- bzero ((char *) pfile, sizeof (cpp_reader));
- pfile->get_token = cpp_get_token;
-
- pfile->token_buffer_size = 200;
- pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
- CPP_SET_WRITTEN (pfile, 0);
-
- pfile->system_include_depth = 0;
- pfile->dont_repeat_files = 0;
- pfile->all_include_files = 0;
- pfile->max_include_len = 0;
- pfile->timebuf = NULL;
- pfile->only_seen_white = 1;
- pfile->buffer = CPP_NULL_BUFFER(pfile);
-}
-
-static struct cpp_pending *
-nreverse_pending (list)
- struct cpp_pending *list;
-
-{
- register struct cpp_pending *prev = 0, *next, *pend;
- for (pend = list; pend; pend = next)
- {
- next = pend->next;
- pend->next = prev;
- prev = pend;
- }
- return prev;
-}
-
-static void
-push_pending (pfile, cmd, arg)
- cpp_reader *pfile;
- char *cmd;
- char *arg;
-{
- struct cpp_pending *pend
- = (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
- pend->cmd = cmd;
- pend->arg = arg;
- pend->next = CPP_OPTIONS (pfile)->pending;
- CPP_OPTIONS (pfile)->pending = pend;
-}
-
-
-static void
-print_help ()
-{
- printf ("Usage: %s [switches] input output\n", progname);
- printf ("Switches:\n");
- printf (" -include <file> Include the contents of <file> before other files\n");
- printf (" -imacros <file> Accept definition of marcos in <file>\n");
- printf (" -iprefix <path> Specify <path> as a prefix for next two options\n");
- printf (" -iwithprefix <dir> Add <dir> to the end of the system include paths\n");
- printf (" -iwithprefixbefore <dir> Add <dir> to the end of the main include paths\n");
- printf (" -isystem <dir> Add <dir> to the start of the system include paths\n");
- printf (" -idirafter <dir> Add <dir> to the end of the system include paths\n");
- printf (" -I <dir> Add <dir> to the end of the main include paths\n");
- printf (" -nostdinc Do not search the system include directories\n");
- printf (" -nostdinc++ Do not search the system include directories for C++\n");
- printf (" -o <file> Put output into <file>\n");
- printf (" -pedantic Issue all warnings demanded by strict ANSI C\n");
- printf (" -traditional Follow K&R pre-processor behaviour\n");
- printf (" -trigraphs Support ANSI C trigraphs\n");
- printf (" -lang-c Assume that the input sources are in C\n");
- printf (" -lang-c89 Assume that the input sources are in C89\n");
- printf (" -lang-c++ Assume that the input sources are in C++\n");
- printf (" -lang-objc Assume that the input sources are in ObjectiveC\n");
- printf (" -lang-objc++ Assume that the input sources are in ObjectiveC++\n");
- printf (" -lang-asm Assume that the input sources are in assembler\n");
- printf (" -lang-chill Assume that the input sources are in Chill\n");
- printf (" -+ Allow parsing of C++ style features\n");
- printf (" -w Inhibit warning messages\n");
- printf (" -Wtrigraphs Warn if trigraphs are encountered\n");
- printf (" -Wno-trigraphs Do not warn about trigraphs\n");
- printf (" -Wcomment{s} Warn if one comment starts inside another\n");
- printf (" -Wno-comment{s} Do not warn about comments\n");
- printf (" -Wtraditional Warn if a macro argument is/would be turned into\n");
- printf (" a string if -tradtional is specified\n");
- printf (" -Wno-traditional Do not warn about stringification\n");
- printf (" -Wundef Warn if an undefined macro is used by #if\n");
- printf (" -Wno-undef Do not warn about testing udefined macros\n");
- printf (" -Wimport Warn about the use of the #import directive\n");
- printf (" -Wno-import Do not warn about the use of #import\n");
- printf (" -Werror Treat all warnings as errors\n");
- printf (" -Wno-error Do not treat warnings as errors\n");
- printf (" -Wall Enable all preprocessor warnings\n");
- printf (" -M Generate make dependencies\n");
- printf (" -MM As -M, but ignore system header files\n");
- printf (" -MD As -M, but put output in a .d file\n");
- printf (" -MMD As -MD, but ignore system header files\n");
- printf (" -MG Treat missing header file as generated files\n");
- printf (" -g Include #define and #undef directives in the output\n");
- printf (" -D<macro> Define a <macro> with string '1' as its value\n");
- printf (" -D<macro>=<val> Define a <macro> with <val> as its value\n");
- printf (" -A<question> (<answer>) Assert the <answer> to <question>\n");
- printf (" -U<macro> Undefine <macro> \n");
- printf (" -u or -undef Do not predefine any macros\n");
- printf (" -v Display the version number\n");
- printf (" -H Print the name of header files as they are used\n");
- printf (" -C Do not discard comments\n");
- printf (" -dM Display a list of macro definitions active at end\n");
- printf (" -dD Preserve macro definitions in output\n");
- printf (" -dN As -dD except that only the names are preserved\n");
- printf (" -dI Include #include directives in the output\n");
- printf (" -ifoutput Describe skipped code blocks in output \n");
- printf (" -P Do not generate #line directives\n");
- printf (" -$ Do not include '$' in identifiers\n");
- printf (" -remap Remap file names when including files.\n");
- printf (" -h or --help Display this information\n");
-}
-
-
-/* Handle one command-line option in (argc, argv).
- Can be called multiple times, to handle multiple sets of options.
- Returns number of strings consumed. */
-int
-cpp_handle_option (pfile, argc, argv)
- cpp_reader *pfile;
- int argc;
- char **argv;
-{
- struct cpp_options *opts = CPP_OPTIONS (pfile);
- int i = 0;
- if (argv[i][0] != '-') {
- if (opts->out_fname != NULL)
- {
- print_help ();
- cpp_fatal (pfile, "Too many arguments");
- }
- else if (opts->in_fname != NULL)
- opts->out_fname = argv[i];
- else
- opts->in_fname = argv[i];
- } else {
- switch (argv[i][1]) {
-
- missing_filename:
- cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
- return argc;
- missing_dirname:
- cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
- return argc;
-
- case 'i':
- if (!strcmp (argv[i], "-include")
- || !strcmp (argv[i], "-imacros")) {
- if (i + 1 == argc)
- goto missing_filename;
- else
- push_pending (pfile, argv[i], argv[i+1]), i++;
- }
- if (!strcmp (argv[i], "-iprefix")) {
- if (i + 1 == argc)
- goto missing_filename;
- else
- opts->include_prefix = argv[++i];
- }
- if (!strcmp (argv[i], "-ifoutput")) {
- opts->output_conditionals = 1;
- }
- if (!strcmp (argv[i], "-isystem")) {
- struct file_name_list *dirtmp;
-
- if (i + 1 == argc)
- goto missing_filename;
-
- dirtmp = (struct file_name_list *)
- xmalloc (sizeof (struct file_name_list));
- dirtmp->next = 0;
- dirtmp->control_macro = 0;
- dirtmp->c_system_include_path = 1;
- dirtmp->fname = (char *) xmalloc (strlen (argv[i+1]) + 1);
- strcpy (dirtmp->fname, argv[++i]);
- dirtmp->got_name_map = 0;
-
- if (opts->before_system == 0)
- opts->before_system = dirtmp;
- else
- opts->last_before_system->next = dirtmp;
- opts->last_before_system = dirtmp; /* Tail follows the last one */
- }
- /* Add directory to end of path for includes,
- with the default prefix at the front of its name. */
- if (!strcmp (argv[i], "-iwithprefix")) {
- struct file_name_list *dirtmp;
- char *prefix;
-
- if (opts->include_prefix != 0)
- prefix = opts->include_prefix;
- else {
- prefix = savestring (GCC_INCLUDE_DIR);
- /* Remove the `include' from /usr/local/lib/gcc.../include. */
- if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
- prefix[strlen (prefix) - 7] = 0;
- }
-
- dirtmp = (struct file_name_list *)
- xmalloc (sizeof (struct file_name_list));
- dirtmp->next = 0; /* New one goes on the end */
- dirtmp->control_macro = 0;
- dirtmp->c_system_include_path = 0;
- if (i + 1 == argc)
- goto missing_dirname;
-
- dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
- + strlen (prefix) + 1);
- strcpy (dirtmp->fname, prefix);
- strcat (dirtmp->fname, argv[++i]);
- dirtmp->got_name_map = 0;
-
- if (opts->after_include == 0)
- opts->after_include = dirtmp;
- else
- opts->last_after_include->next = dirtmp;
- opts->last_after_include = dirtmp; /* Tail follows the last one */
- }
- /* Add directory to main path for includes,
- with the default prefix at the front of its name. */
- if (!strcmp (argv[i], "-iwithprefixbefore")) {
- struct file_name_list *dirtmp;
- char *prefix;
-
- if (opts->include_prefix != 0)
- prefix = opts->include_prefix;
- else {
- prefix = savestring (GCC_INCLUDE_DIR);
- /* Remove the `include' from /usr/local/lib/gcc.../include. */
- if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
- prefix[strlen (prefix) - 7] = 0;
- }
-
- dirtmp = (struct file_name_list *)
- xmalloc (sizeof (struct file_name_list));
- dirtmp->next = 0; /* New one goes on the end */
- dirtmp->control_macro = 0;
- dirtmp->c_system_include_path = 0;
- if (i + 1 == argc)
- goto missing_dirname;
-
- dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
- + strlen (prefix) + 1);
- strcpy (dirtmp->fname, prefix);
- strcat (dirtmp->fname, argv[++i]);
- dirtmp->got_name_map = 0;
-
- append_include_chain (pfile, dirtmp, dirtmp);
- }
- /* Add directory to end of path for includes. */
- if (!strcmp (argv[i], "-idirafter")) {
- struct file_name_list *dirtmp;
-
- dirtmp = (struct file_name_list *)
- xmalloc (sizeof (struct file_name_list));
- dirtmp->next = 0; /* New one goes on the end */
- dirtmp->control_macro = 0;
- dirtmp->c_system_include_path = 0;
- if (i + 1 == argc)
- goto missing_dirname;
- else
- dirtmp->fname = argv[++i];
- dirtmp->got_name_map = 0;
-
- if (opts->after_include == 0)
- opts->after_include = dirtmp;
- else
- opts->last_after_include->next = dirtmp;
- opts->last_after_include = dirtmp; /* Tail follows the last one */
- }
- break;
-
- case 'o':
- if (opts->out_fname != NULL)
- {
- cpp_fatal (pfile, "Output filename specified twice");
- return argc;
- }
- if (i + 1 == argc)
- goto missing_filename;
- opts->out_fname = argv[++i];
- if (!strcmp (opts->out_fname, "-"))
- opts->out_fname = "";
- break;
-
- case 'p':
- if (!strcmp (argv[i], "-pedantic"))
- CPP_PEDANTIC (pfile) = 1;
- else if (!strcmp (argv[i], "-pedantic-errors")) {
- CPP_PEDANTIC (pfile) = 1;
- opts->pedantic_errors = 1;
- }
-#if 0
- else if (!strcmp (argv[i], "-pcp")) {
- char *pcp_fname = argv[++i];
- pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
- ? fopen (pcp_fname, "w")
- : fdopen (dup (fileno (stdout)), "w"));
- if (pcp_outfile == 0)
- cpp_pfatal_with_name (pfile, pcp_fname);
- no_precomp = 1;
- }
-#endif
- break;
-
- case 't':
- if (!strcmp (argv[i], "-traditional")) {
- opts->traditional = 1;
- opts->cplusplus_comments = 0;
- } else if (!strcmp (argv[i], "-trigraphs")) {
- if (!opts->chill)
- opts->no_trigraphs = 0;
- }
- break;
-
- case 'l':
- if (! strcmp (argv[i], "-lang-c"))
- opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
- opts->objc = 0;
- if (! strcmp (argv[i], "-lang-c89"))
- opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
- opts->objc = 0;
- if (! strcmp (argv[i], "-lang-c++"))
- opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
- opts->objc = 0;
- if (! strcmp (argv[i], "-lang-objc"))
- opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
- opts->objc = 1;
- if (! strcmp (argv[i], "-lang-objc++"))
- opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
- opts->objc = 1;
- if (! strcmp (argv[i], "-lang-asm"))
- opts->lang_asm = 1;
- if (! strcmp (argv[i], "-lint"))
- opts->for_lint = 1;
- if (! strcmp (argv[i], "-lang-chill"))
- opts->objc = 0, opts->cplusplus = 0, opts->chill = 1,
- opts->traditional = 1, opts->no_trigraphs = 1;
- break;
-
- case '+':
- opts->cplusplus = 1, opts->cplusplus_comments = 1;
- break;
-
- case 'w':
- opts->inhibit_warnings = 1;
- break;
-
- case 'W':
- if (!strcmp (argv[i], "-Wtrigraphs"))
- opts->warn_trigraphs = 1;
- else if (!strcmp (argv[i], "-Wno-trigraphs"))
- opts->warn_trigraphs = 0;
- else if (!strcmp (argv[i], "-Wcomment"))
- opts->warn_comments = 1;
- else if (!strcmp (argv[i], "-Wno-comment"))
- opts->warn_comments = 0;
- else if (!strcmp (argv[i], "-Wcomments"))
- opts->warn_comments = 1;
- else if (!strcmp (argv[i], "-Wno-comments"))
- opts->warn_comments = 0;
- else if (!strcmp (argv[i], "-Wtraditional"))
- opts->warn_stringify = 1;
- else if (!strcmp (argv[i], "-Wno-traditional"))
- opts->warn_stringify = 0;
- else if (!strcmp (argv[i], "-Wundef"))
- opts->warn_undef = 1;
- else if (!strcmp (argv[i], "-Wno-undef"))
- opts->warn_undef = 0;
- else if (!strcmp (argv[i], "-Wimport"))
- opts->warn_import = 1;
- else if (!strcmp (argv[i], "-Wno-import"))
- opts->warn_import = 0;
- else if (!strcmp (argv[i], "-Werror"))
- opts->warnings_are_errors = 1;
- else if (!strcmp (argv[i], "-Wno-error"))
- opts->warnings_are_errors = 0;
- else if (!strcmp (argv[i], "-Wall"))
- {
- opts->warn_trigraphs = 1;
- opts->warn_comments = 1;
- }
- break;
-
- case 'M':
- /* The style of the choices here is a bit mixed.
- The chosen scheme is a hybrid of keeping all options in one string
- and specifying each option in a separate argument:
- -M|-MM|-MD file|-MMD file [-MG]. An alternative is:
- -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
- -M[M][G][D file]. This is awkward to handle in specs, and is not
- as extensible. */
- /* ??? -MG must be specified in addition to one of -M or -MM.
- This can be relaxed in the future without breaking anything.
- The converse isn't true. */
-
- /* -MG isn't valid with -MD or -MMD. This is checked for later. */
- if (!strcmp (argv[i], "-MG"))
- {
- opts->print_deps_missing_files = 1;
- break;
- }
- if (!strcmp (argv[i], "-M"))
- opts->print_deps = 2;
- else if (!strcmp (argv[i], "-MM"))
- opts->print_deps = 1;
- else if (!strcmp (argv[i], "-MD"))
- opts->print_deps = 2;
- else if (!strcmp (argv[i], "-MMD"))
- opts->print_deps = 1;
- /* For -MD and -MMD options, write deps on file named by next arg. */
- if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
- {
- if (i+1 == argc)
- goto missing_filename;
- opts->deps_file = argv[++i];
- }
- else
- {
- /* For -M and -MM, write deps on standard output
- and suppress the usual output. */
- opts->no_output = 1;
- }
- break;
-
- case 'd':
- {
- char *p = argv[i] + 2;
- char c;
- while ((c = *p++) != 0) {
- /* Arg to -d specifies what parts of macros to dump */
- switch (c) {
- case 'M':
- opts->dump_macros = dump_only;
- opts->no_output = 1;
- break;
- case 'N':
- opts->dump_macros = dump_names;
- break;
- case 'D':
- opts->dump_macros = dump_definitions;
- break;
- case 'I':
- opts->dump_includes = 1;
- break;
- }
- }
- }
- break;
-
- case 'g':
- if (argv[i][2] == '3')
- opts->debug_output = 1;
- break;
-
- case '-':
- if (strcmp (argv[i], "--help") != 0)
- return i;
- print_help ();
- break;
-
- case 'v':
- fprintf (stderr, "GNU CPP version %s", version_string);
-#ifdef TARGET_VERSION
- TARGET_VERSION;
-#endif
- fprintf (stderr, "\n");
- opts->verbose = 1;
- break;
-
- case 'H':
- opts->print_include_names = 1;
- break;
-
- case 'D':
- if (argv[i][2] != 0)
- push_pending (pfile, "-D", argv[i] + 2);
- else if (i + 1 == argc)
+ else if (c == '\n' || c == EOF)
{
- cpp_fatal (pfile, "Macro name missing after -D option");
- return argc;
+ if (c == '\n') FORWARD(-1);
+ cpp_error (pfile, "un-terminated assertion answer");
+ return 0;
}
+ else if (c == '\r')
+ /* \r cannot be a macro escape here. */
+ CPP_BUMP_LINE (pfile);
else
- i++, push_pending (pfile, "-D", argv[i]);
- break;
-
- case 'A':
- {
- char *p;
-
- if (argv[i][2] != 0)
- p = argv[i] + 2;
- else if (i + 1 == argc)
- {
- cpp_fatal (pfile, "Assertion missing after -A option");
- return argc;
- }
- else
- p = argv[++i];
-
- if (!strcmp (p, "-")) {
- struct cpp_pending **ptr;
- /* -A- eliminates all predefined macros and assertions.
- Let's include also any that were specified earlier
- on the command line. That way we can get rid of any
- that were passed automatically in from GCC. */
- opts->inhibit_predefs = 1;
- for (ptr = &opts->pending; *ptr != NULL; )
- {
- struct cpp_pending *pend = *ptr;
- if (pend->cmd && pend->cmd[0] == '-'
- && (pend->cmd[1] == 'D' || pend->cmd[1] == 'A'))
- {
- *ptr = pend->next;
- free (pend);
- }
- else
- ptr = &pend->next;
- }
- } else {
- push_pending (pfile, "-A", p);
- }
- }
- break;
-
- case 'U': /* JF #undef something */
- if (argv[i][2] != 0)
- push_pending (pfile, "-U", argv[i] + 2);
- else if (i + 1 == argc)
{
- cpp_fatal (pfile, "Macro name missing after -U option");
- return argc;
- }
- else
- push_pending (pfile, "-U", argv[i+1]), i++;
- break;
-
- case 'C':
- opts->put_out_comments = 1;
- break;
-
- case 'E': /* -E comes from cc -E; ignore it. */
- break;
-
- case 'P':
- opts->no_line_commands = 1;
- break;
-
- case '$': /* Don't include $ in identifiers. */
- opts->dollars_in_ident = 0;
- break;
-
- case 'I': /* Add directory to path for includes. */
- {
- struct file_name_list *dirtmp;
-
- if (! CPP_OPTIONS(pfile)->ignore_srcdir
- && !strcmp (argv[i] + 2, "-")) {
- CPP_OPTIONS (pfile)->ignore_srcdir = 1;
- /* Don't use any preceding -I directories for #include <...>. */
- CPP_OPTIONS (pfile)->first_bracket_include = 0;
- }
- else {
- dirtmp = (struct file_name_list *)
- xmalloc (sizeof (struct file_name_list));
- dirtmp->next = 0; /* New one goes on the end */
- dirtmp->control_macro = 0;
- dirtmp->c_system_include_path = 0;
- if (argv[i][2] != 0)
- dirtmp->fname = argv[i] + 2;
- else if (i + 1 == argc)
- goto missing_dirname;
- else
- dirtmp->fname = argv[++i];
- dirtmp->got_name_map = 0;
- append_include_chain (pfile, dirtmp, dirtmp);
+ CPP_PUTC (pfile, c);
+ dropwhite = 0;
}
- }
- break;
-
- case 'n':
- if (!strcmp (argv[i], "-nostdinc"))
- /* -nostdinc causes no default include directories.
- You must specify all include-file directories with -I. */
- opts->no_standard_includes = 1;
- else if (!strcmp (argv[i], "-nostdinc++"))
- /* -nostdinc++ causes no default C++-specific include directories. */
- opts->no_standard_cplusplus_includes = 1;
-#if 0
- else if (!strcmp (argv[i], "-noprecomp"))
- no_precomp = 1;
-#endif
- break;
-
- case 'r':
- if (!strcmp (argv[i], "-remap"))
- opts->remap = 1;
- break;
-
- case 'u':
- /* Sun compiler passes undocumented switch "-undef".
- Let's assume it means to inhibit the predefined symbols. */
- opts->inhibit_predefs = 1;
- break;
-
- case '\0': /* JF handle '-' as file name meaning stdin or stdout */
- if (opts->in_fname == NULL) {
- opts->in_fname = "";
- break;
- } else if (opts->out_fname == NULL) {
- opts->out_fname = "";
- break;
- } /* else fall through into error */
-
- default:
- return i;
}
- }
- return i + 1;
-}
-
-/* Handle command-line options in (argc, argv).
- Can be called multiple times, to handle multiple sets of options.
- Returns if an unrecognized option is seen.
- Returns number of strings consumed. */
-
-int
-cpp_handle_options (pfile, argc, argv)
- cpp_reader *pfile;
- int argc;
- char **argv;
-{
- int i;
- int strings_processed;
- for (i = 0; i < argc; i += strings_processed)
+ if (pfile->limit[-1] == ' ')
+ pfile->limit[-1] = ')';
+ else if (pfile->limit[-1] == '(')
{
- strings_processed = cpp_handle_option (pfile, argc - i, argv + i);
- if (strings_processed == 0)
- break;
+ cpp_error (pfile, "empty token sequence in assertion");
+ return 0;
}
- return i;
-}
-
-void
-cpp_finish (pfile)
- cpp_reader *pfile;
-{
- struct cpp_options *opts = CPP_OPTIONS (pfile);
-
- if (opts->print_deps)
- {
- /* Stream on which to print the dependency information. */
- FILE *deps_stream;
+ else
+ CPP_PUTC (pfile, ')');
- /* Don't actually write the deps file if compilation has failed. */
- if (pfile->errors == 0)
- {
- char *deps_mode = opts->print_deps_append ? "a" : "w";
- if (opts->deps_file == 0)
- deps_stream = stdout;
- else if ((deps_stream = fopen (opts->deps_file, deps_mode)) == 0)
- cpp_pfatal_with_name (pfile, opts->deps_file);
- fputs (pfile->deps_buffer, deps_stream);
- putc ('\n', deps_stream);
- if (opts->deps_file)
- {
- if (ferror (deps_stream) || fclose (deps_stream) != 0)
- cpp_fatal (pfile, "I/O error on output");
- }
- }
- }
+ CPP_NUL_TERMINATE (pfile);
+ return 2;
}
-/* Free resources used by PFILE.
- This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology). */
-
-void
-cpp_cleanup (pfile)
- cpp_reader *pfile;
-{
- int i;
- while ( CPP_BUFFER (pfile) != CPP_NULL_BUFFER (pfile))
- cpp_pop_buffer (pfile);
-
- if (pfile->token_buffer)
- {
- free (pfile->token_buffer);
- pfile->token_buffer = NULL;
- }
-
- if (pfile->deps_buffer)
- {
- free (pfile->deps_buffer);
- pfile->deps_buffer = NULL;
- pfile->deps_allocated_size = 0;
- }
-
- while (pfile->if_stack)
- {
- IF_STACK_FRAME *temp = pfile->if_stack;
- pfile->if_stack = temp->next;
- free (temp);
- }
-
- while (pfile->dont_repeat_files)
- {
- struct file_name_list *temp = pfile->dont_repeat_files;
- pfile->dont_repeat_files = temp->next;
- free (temp->fname);
- free (temp);
- }
-
- while (pfile->all_include_files)
- {
- struct file_name_list *temp = pfile->all_include_files;
- pfile->all_include_files = temp->next;
- free (temp->fname);
- free (temp);
- }
-
- for (i = IMPORT_HASH_SIZE; --i >= 0; )
- {
- register struct import_file *imp = pfile->import_hash_table[i];
- while (imp)
- {
- struct import_file *next = imp->next;
- free (imp->name);
- free (imp);
- imp = next;
- }
- pfile->import_hash_table[i] = 0;
- }
-
- for (i = ASSERTION_HASHSIZE; --i >= 0; )
- {
- while (pfile->assertion_hashtab[i])
- delete_assertion (pfile->assertion_hashtab[i]);
- }
-
- cpp_hash_cleanup (pfile);
-}
-
static int
-do_assert (pfile, keyword, buf, limit)
+do_assert (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
{
- long symstart; /* remember where symbol name starts */
- int c;
- int sym_length; /* and how long it is */
- struct arglist *tokens = NULL;
+ char *sym;
+ int ret, c;
+ HASHNODE *base, *this;
+ int baselen, thislen;
if (CPP_PEDANTIC (pfile) && CPP_OPTIONS (pfile)->done_initializing
&& !CPP_BUFFER (pfile)->system_header_p)
cpp_pedwarn (pfile, "ANSI C does not allow `#assert'");
cpp_skip_hspace (pfile);
- symstart = CPP_WRITTEN (pfile); /* remember where it starts */
- parse_name (pfile, GETC());
- sym_length = check_macro_name (pfile, pfile->token_buffer + symstart,
- "assertion");
-
- cpp_skip_hspace (pfile);
- if (PEEKC() != '(') {
- cpp_error (pfile, "missing token-sequence in `#assert'");
+ sym = (char *) CPP_PWRITTEN (pfile); /* remember where it starts */
+ ret = parse_assertion (pfile);
+ if (ret == 0)
goto error;
- }
-
- {
- int error_flag = 0;
- tokens = read_token_list (pfile, &error_flag);
- if (error_flag)
- goto error;
- if (tokens == 0) {
- cpp_error (pfile, "empty token-sequence in `#assert'");
+ else if (ret == 1)
+ {
+ cpp_error (pfile, "missing token-sequence in `#assert'");
goto error;
}
+
cpp_skip_hspace (pfile);
- c = PEEKC ();
+ c = PEEKC();
if (c != EOF && c != '\n')
- cpp_pedwarn (pfile, "junk at end of `#assert'");
- skip_rest_of_line (pfile);
- }
-
- /* If this name isn't already an assertion name, make it one.
- Error if it was already in use in some other way. */
+ {
+ cpp_error (pfile, "junk at end of `#assert'");
+ goto error;
+ }
- {
- ASSERTION_HASHNODE *hp;
- U_CHAR *symname = pfile->token_buffer + symstart;
- int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
- struct tokenlist_list *value
- = (struct tokenlist_list *) xmalloc (sizeof (struct tokenlist_list));
-
- hp = assertion_lookup (pfile, symname, sym_length, hashcode);
- if (hp == NULL) {
- if (sym_length == 7 && ! strncmp (symname, "defined", sym_length))
- cpp_error (pfile, "`defined' redefined as assertion");
- hp = assertion_install (pfile, symname, sym_length, hashcode);
+ thislen = strlen (sym);
+ baselen = index (sym, '(') - sym;
+ this = cpp_lookup (pfile, sym, thislen, -1);
+ if (this)
+ {
+ cpp_warning (pfile, "`%s' re-asserted", sym);
+ goto error;
}
- /* Add the spec'd token-sequence to the list of such. */
- value->tokens = tokens;
- value->next = hp->value;
- hp->value = value;
+ base = cpp_lookup (pfile, sym, baselen, -1);
+ if (! base)
+ base = cpp_install (pfile, sym, baselen, T_ASSERT, 0, -1);
+ else if (base->type != T_ASSERT)
+ {
+ /* Token clash - but with what?! */
+ cpp_fatal (pfile,
+ "cpp internal error: base->type != T_ASSERT in do_assert");
+ goto error;
}
- CPP_SET_WRITTEN (pfile, symstart); /* Pop */
+
+ this = cpp_install (pfile, sym, thislen, T_ASSERT,
+ (char *)base->value.aschain, -1);
+ base->value.aschain = this;
+
+ pfile->limit = (unsigned char *) sym; /* Pop */
return 0;
+
error:
- CPP_SET_WRITTEN (pfile, symstart); /* Pop */
skip_rest_of_line (pfile);
- return 1;
+ pfile->limit = (unsigned char *) sym; /* Pop */
+ return 0;
}
-
+
static int
-do_unassert (pfile, keyword, buf, limit)
+do_unassert (pfile, keyword)
cpp_reader *pfile;
struct directive *keyword ATTRIBUTE_UNUSED;
- U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
{
- long symstart; /* remember where symbol name starts */
- int sym_length; /* and how long it is */
- int c;
-
- struct arglist *tokens = NULL;
- int tokens_specified = 0;
-
+ int c, ret;
+ char *sym;
+ long baselen, thislen;
+ HASHNODE *base, *this, *next;
+
if (CPP_PEDANTIC (pfile) && CPP_OPTIONS (pfile)->done_initializing
&& !CPP_BUFFER (pfile)->system_header_p)
cpp_pedwarn (pfile, "ANSI C does not allow `#unassert'");
cpp_skip_hspace (pfile);
- symstart = CPP_WRITTEN (pfile); /* remember where it starts */
- parse_name (pfile, GETC());
- sym_length = check_macro_name (pfile, pfile->token_buffer + symstart,
- "assertion");
-
- cpp_skip_hspace (pfile);
- if (PEEKC() == '(') {
- int error_flag = 0;
-
- tokens = read_token_list (pfile, &error_flag);
- if (error_flag)
- goto error;
- if (tokens == 0) {
- cpp_error (pfile, "empty token list in `#unassert'");
- goto error;
- }
-
- tokens_specified = 1;
- }
-
+ sym = (char *) CPP_PWRITTEN (pfile); /* remember where it starts */
+ ret = parse_assertion (pfile);
+ if (ret == 0)
+ goto error;
+
cpp_skip_hspace (pfile);
c = PEEKC ();
if (c != EOF && c != '\n')
cpp_error (pfile, "junk at end of `#unassert'");
- skip_rest_of_line (pfile);
-
- {
- ASSERTION_HASHNODE *hp;
- U_CHAR *symname = pfile->token_buffer + symstart;
- int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
- struct tokenlist_list *tail, *prev;
- hp = assertion_lookup (pfile, symname, sym_length, hashcode);
- if (hp == NULL)
- return 1;
-
- /* If no token list was specified, then eliminate this assertion
- entirely. */
- if (! tokens_specified)
- delete_assertion (hp);
- else {
- /* If a list of tokens was given, then delete any matching list. */
-
- tail = hp->value;
- prev = 0;
- while (tail) {
- struct tokenlist_list *next = tail->next;
- if (compare_token_lists (tail->tokens, tokens)) {
- if (prev)
- prev->next = next;
- else
- hp->value = tail->next;
- free_token_list (tail->tokens);
- free (tail);
- } else {
- prev = tail;
+ thislen = strlen (sym);
+ if (ret == 1)
+ {
+ base = cpp_lookup (pfile, sym, thislen, -1);
+ if (! base)
+ goto error; /* It isn't an error to #undef what isn't #defined,
+ so it isn't an error to #unassert what isn't
+ #asserted either. */
+
+ for (this = base->value.aschain; this; this = next)
+ {
+ next = this->value.aschain;
+ delete_macro (this);
}
- tail = next;
- }
+ delete_macro (base);
}
- }
+ else
+ {
+ baselen = index (sym, '(') - sym;
+ base = cpp_lookup (pfile, sym, baselen, -1);
+ if (! base) goto error;
+ this = cpp_lookup (pfile, sym, thislen, -1);
+ if (! this) goto error;
+
+ next = base;
+ while (next->value.aschain != this)
+ next = next->value.aschain;
+
+ next->value.aschain = this->value.aschain;
+ delete_macro (this);
- CPP_SET_WRITTEN (pfile, symstart); /* Pop */
+ if (base->value.aschain == NULL)
+ delete_macro (base); /* Last answer for this predicate deleted. */
+ }
+
+ pfile->limit = (unsigned char *) sym; /* Pop */
return 0;
error:
- CPP_SET_WRITTEN (pfile, symstart); /* Pop */
skip_rest_of_line (pfile);
- return 1;
+ pfile->limit = (unsigned char *) sym; /* Pop */
+ return 0;
}
-
-/* Test whether there is an assertion named NAME
- and optionally whether it has an asserted token list TOKENS.
- NAME is not null terminated; its length is SYM_LENGTH.
- If TOKENS_SPECIFIED is 0, then don't check for any token list. */
-int
-check_assertion (pfile, name, sym_length, tokens_specified, tokens)
+/* Process STR as if it appeared as the body of an #unassert. */
+void
+cpp_unassert (pfile, str)
cpp_reader *pfile;
- U_CHAR *name;
- int sym_length;
- int tokens_specified;
- struct arglist *tokens;
-{
- ASSERTION_HASHNODE *hp;
- int hashcode = hashf (name, sym_length, ASSERTION_HASHSIZE);
-
- if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
- cpp_pedwarn (pfile, "ANSI C does not allow testing assertions");
-
- hp = assertion_lookup (pfile, name, sym_length, hashcode);
- if (hp == NULL)
- /* It is not an assertion; just return false. */
- return 0;
-
- /* If no token list was specified, then value is 1. */
- if (! tokens_specified)
- return 1;
-
- {
- struct tokenlist_list *tail;
-
- tail = hp->value;
-
- /* If a list of tokens was given,
- then succeed if the assertion records a matching list. */
-
- while (tail) {
- if (compare_token_lists (tail->tokens, tokens))
- return 1;
- tail = tail->next;
- }
-
- /* Fail if the assertion has no matching list. */
- return 0;
- }
-}
-
-/* Compare two lists of tokens for equality including order of tokens. */
-
-static int
-compare_token_lists (l1, l2)
- struct arglist *l1, *l2;
-{
- while (l1 && l2) {
- if (l1->length != l2->length)
- return 0;
- if (strncmp (l1->name, l2->name, l1->length))
- return 0;
- l1 = l1->next;
- l2 = l2->next;
- }
-
- /* Succeed if both lists end at the same time. */
- return l1 == l2;
-}
-
-struct arglist *
-reverse_token_list (tokens)
- struct arglist *tokens;
+ unsigned char *str;
{
- register struct arglist *prev = 0, *this, *next;
- for (this = tokens; this; this = next)
+ if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
{
- next = this->next;
- this->next = prev;
- prev = this;
+ do_assert (pfile, NULL);
+ cpp_pop_buffer (pfile);
}
- return prev;
-}
-
-/* Read a space-separated list of tokens ending in a close parenthesis.
- Return a list of strings, in the order they were written.
- (In case of error, return 0 and store -1 in *ERROR_FLAG.) */
+}
-static struct arglist *
-read_token_list (pfile, error_flag)
+int
+cpp_read_check_assertion (pfile)
cpp_reader *pfile;
- int *error_flag;
{
- struct arglist *token_ptrs = 0;
- int depth = 1;
- int length;
-
- *error_flag = 0;
- FORWARD (1); /* Skip '(' */
-
- /* Loop over the assertion value tokens. */
- while (depth > 0)
+ U_CHAR *name = CPP_PWRITTEN (pfile);
+ int result;
+ HASHNODE *hp;
+
+ FORWARD (1); /* Skip '#' */
+ cpp_skip_hspace (pfile);
+ if (! parse_assertion (pfile))
+ result = 0;
+ else
{
- struct arglist *temp;
- long name_written = CPP_WRITTEN (pfile);
- int c;
-
- cpp_skip_hspace (pfile);
-
- c = GETC ();
-
- /* Find the end of the token. */
- if (c == '(')
- {
- CPP_PUTC (pfile, c);
- depth++;
- }
- else if (c == ')')
- {
- depth--;
- if (depth == 0)
- break;
- CPP_PUTC (pfile, c);
- }
- else if (c == '"' || c == '\'')
- {
- FORWARD(-1);
- cpp_get_token (pfile);
- }
- else if (c == '\n')
- break;
- else
- {
- while (c != EOF && ! is_space[c] && c != '(' && c != ')'
- && c != '"' && c != '\'')
- {
- CPP_PUTC (pfile, c);
- c = GETC();
- }
- if (c != EOF) FORWARD(-1);
- }
-
- length = CPP_WRITTEN (pfile) - name_written;
- temp = (struct arglist *)
- xmalloc (sizeof (struct arglist) + length + 1);
- temp->name = (U_CHAR *) (temp + 1);
- bcopy ((char *) (pfile->token_buffer + name_written),
- (char *) temp->name, length);
- temp->name[length] = 0;
- temp->next = token_ptrs;
- token_ptrs = temp;
- temp->length = length;
-
- CPP_ADJUST_WRITTEN (pfile, -length); /* pop */
-
- if (c == EOF || c == '\n')
- { /* FIXME */
- cpp_error (pfile,
- "unterminated token sequence following `#' operator");
- return 0;
- }
+ hp = cpp_lookup (pfile, name, CPP_PWRITTEN (pfile) - name, -1);
+ result = (hp != 0);
}
- /* We accumulated the names in reverse order.
- Now reverse them to get the proper order. */
- return reverse_token_list (token_ptrs);
-}
-
-static void
-free_token_list (tokens)
- struct arglist *tokens;
-{
- while (tokens) {
- struct arglist *next = tokens->next;
- free (tokens->name);
- free (tokens);
- tokens = next;
- }
-}
-
-/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
- retrying if necessary. If MAX_READ_LEN is defined, read at most
- that bytes at a time. Return a negative value if an error occurs,
- otherwise return the actual number of bytes read,
- which must be LEN unless end-of-file was reached. */
-
-static int
-safe_read (desc, ptr, len)
- int desc;
- char *ptr;
- int len;
-{
- int left, rcount, nchars;
-
- left = len;
- while (left > 0) {
- rcount = left;
-#ifdef MAX_READ_LEN
- if (rcount > MAX_READ_LEN)
- rcount = MAX_READ_LEN;
-#endif
- nchars = read (desc, ptr, rcount);
- if (nchars < 0)
- {
-#ifdef EINTR
- if (errno == EINTR)
- continue;
-#endif
- return nchars;
- }
- if (nchars == 0)
- break;
- ptr += nchars;
- left -= nchars;
- }
- return len - left;
+ pfile->limit = name;
+ return result;
}
-static char *
-xcalloc (number, size)
- unsigned number, size;
-{
- register unsigned total = number * size;
- register char *ptr = (char *) xmalloc (total);
- bzero (ptr, total);
- return ptr;
-}
-
-static char *
-savestring (input)
- char *input;
-{
- unsigned size = strlen (input);
- char *output = xmalloc (size + 1);
- strcpy (output, input);
- return output;
-}
-
-/* Initialize PMARK to remember the current position of PFILE. */
+/* Remember the current position of PFILE. */
void
-parse_set_mark (pmark, pfile)
- struct parse_marker *pmark;
+parse_set_mark (pfile)
cpp_reader *pfile;
{
- cpp_buffer *pbuf = CPP_BUFFER (pfile);
- pmark->next = pbuf->marks;
- pbuf->marks = pmark;
- pmark->buf = pbuf;
- pmark->position = pbuf->cur - pbuf->buf;
-}
-
-/* Cleanup PMARK - we no longer need it. */
+ cpp_buffer *ip = CPP_BUFFER (pfile);
+ if (ip->mark != -1)
+ cpp_fatal (pfile,
+ "cpp internal error: ip->mark != -1 in parse_set_mark");
-void
-parse_clear_mark (pmark)
- struct parse_marker *pmark;
-{
- struct parse_marker **pp = &pmark->buf->marks;
- for (; ; pp = &(*pp)->next) {
- if (*pp == NULL) abort ();
- if (*pp == pmark) break;
- }
- *pp = pmark->next;
+ ip->mark = ip->cur - ip->buf;
}
-/* Backup the current position of PFILE to that saved in PMARK. */
+/* Clear the current mark - we no longer need it. */
void
-parse_goto_mark (pmark, pfile)
- struct parse_marker *pmark;
+parse_clear_mark (pfile)
cpp_reader *pfile;
{
- cpp_buffer *pbuf = CPP_BUFFER (pfile);
- if (pbuf != pmark->buf)
- cpp_fatal (pfile, "internal error %s", "parse_goto_mark");
- pbuf->cur = pbuf->buf + pmark->position;
+ cpp_buffer *ip = CPP_BUFFER (pfile);
+ if (ip->mark == -1)
+ cpp_fatal (pfile,
+ "cpp internal error: ip->mark == -1 in parse_clear_mark");
+
+ ip->mark = -1;
}
-/* Reset PMARK to point to the current position of PFILE. (Same
- as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */
+/* Backup the current position of PFILE to that saved in its mark,
+ and clear the mark. */
void
-parse_move_mark (pmark, pfile)
- struct parse_marker *pmark;
+parse_goto_mark (pfile)
cpp_reader *pfile;
{
- cpp_buffer *pbuf = CPP_BUFFER (pfile);
- if (pbuf != pmark->buf)
- cpp_fatal (pfile, "internal error %s", "parse_move_mark");
- pmark->position = pbuf->cur - pbuf->buf;
-}
+ cpp_buffer *ip = CPP_BUFFER (pfile);
+ if (ip->mark == -1)
+ cpp_fatal (pfile,
+ "cpp internal error: ip->mark == -1 in parse_goto_mark");
-int
-cpp_read_check_assertion (pfile)
- cpp_reader *pfile;
-{
- int name_start = CPP_WRITTEN (pfile);
- int name_length, name_written;
- int result;
- FORWARD (1); /* Skip '#' */
- cpp_skip_hspace (pfile);
- parse_name (pfile, GETC ());
- name_written = CPP_WRITTEN (pfile);
- name_length = name_written - name_start;
- cpp_skip_hspace (pfile);
- if (CPP_BUF_PEEK (CPP_BUFFER (pfile)) == '(')
- {
- int error_flag;
- struct arglist *token_ptrs = read_token_list (pfile, &error_flag);
- result = check_assertion (pfile,
- pfile->token_buffer + name_start, name_length,
- 1, token_ptrs);
- }
- else
- result = check_assertion (pfile,
- pfile->token_buffer + name_start, name_length,
- 0, NULL_PTR);
- CPP_ADJUST_WRITTEN (pfile, - name_length); /* pop */
- return result;
+ ip->cur = ip->buf + ip->mark;
+ ip->mark = -1;
}
-
+
void
cpp_print_file_and_line (pfile)
cpp_reader *pfile;
@@ -7430,42 +2946,42 @@ cpp_print_file_and_line (pfile)
}
static void
-v_cpp_error (pfile, msg, ap)
+v_cpp_error (pfile, msgid, ap)
cpp_reader *pfile;
- const char *msg;
+ const char *msgid;
va_list ap;
{
cpp_print_containing_files (pfile);
cpp_print_file_and_line (pfile);
- v_cpp_message (pfile, 1, msg, ap);
+ v_cpp_message (pfile, 1, msgid, ap);
}
void
-cpp_error VPROTO ((cpp_reader * pfile, const char *msg, ...))
+cpp_error VPROTO ((cpp_reader * pfile, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START(ap, msg);
+ VA_START(ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_cpp_error (pfile, msg, ap);
+ v_cpp_error (pfile, msgid, ap);
va_end(ap);
}
/* Print error message but don't count it. */
static void
-v_cpp_warning (pfile, msg, ap)
+v_cpp_warning (pfile, msgid, ap)
cpp_reader *pfile;
- const char *msg;
+ const char *msgid;
va_list ap;
{
if (CPP_OPTIONS (pfile)->inhibit_warnings)
@@ -7476,60 +2992,60 @@ v_cpp_warning (pfile, msg, ap)
cpp_print_containing_files (pfile);
cpp_print_file_and_line (pfile);
- v_cpp_message (pfile, 0, msg, ap);
+ v_cpp_message (pfile, 0, msgid, ap);
}
void
-cpp_warning VPROTO ((cpp_reader * pfile, const char *msg, ...))
+cpp_warning VPROTO ((cpp_reader * pfile, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, msg);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_cpp_warning (pfile, msg, ap);
+ v_cpp_warning (pfile, msgid, ap);
va_end(ap);
}
/* Print an error message and maybe count it. */
void
-cpp_pedwarn VPROTO ((cpp_reader * pfile, const char *msg, ...))
+cpp_pedwarn VPROTO ((cpp_reader * pfile, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, msg);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
if (CPP_OPTIONS (pfile)->pedantic_errors)
- v_cpp_error (pfile, msg, ap);
+ v_cpp_error (pfile, msgid, ap);
else
- v_cpp_warning (pfile, msg, ap);
+ v_cpp_warning (pfile, msgid, ap);
va_end(ap);
}
static void
-v_cpp_error_with_line (pfile, line, column, msg, ap)
+v_cpp_error_with_line (pfile, line, column, msgid, ap)
cpp_reader * pfile;
int line;
int column;
- const char * msg;
+ const char * msgid;
va_list ap;
{
cpp_buffer *ip = cpp_file_buffer (pfile);
@@ -7539,39 +3055,40 @@ v_cpp_error_with_line (pfile, line, column, msg, ap)
if (ip != NULL)
cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
- v_cpp_message (pfile, 1, msg, ap);
+ v_cpp_message (pfile, 1, msgid, ap);
}
void
-cpp_error_with_line VPROTO ((cpp_reader * pfile, int line, int column, const char *msg, ...))
+cpp_error_with_line VPROTO ((cpp_reader * pfile, int line, int column,
+ const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
int line;
int column;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, msg);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
line = va_arg (ap, int);
column = va_arg (ap, int);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_cpp_error_with_line(pfile, line, column, msg, ap);
+ v_cpp_error_with_line(pfile, line, column, msgid, ap);
va_end(ap);
}
static void
-v_cpp_warning_with_line (pfile, line, column, msg, ap)
+v_cpp_warning_with_line (pfile, line, column, msgid, ap)
cpp_reader * pfile;
int line;
int column;
- const char *msg;
+ const char *msgid;
va_list ap;
{
cpp_buffer *ip;
@@ -7589,59 +3106,59 @@ v_cpp_warning_with_line (pfile, line, column, msg, ap)
if (ip != NULL)
cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
- v_cpp_message (pfile, 0, msg, ap);
+ v_cpp_message (pfile, 0, msgid, ap);
}
-#if 0
-static void
-cpp_warning_with_line VPROTO ((cpp_reader * pfile, int line, int column, const char *msg, ...))
+void
+cpp_warning_with_line VPROTO ((cpp_reader * pfile, int line, int column,
+ const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
int line;
int column;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, msg);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
line = va_arg (ap, int);
column = va_arg (ap, int);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_cpp_warning_with_line (pfile, line, column, msg, ap);
+ v_cpp_warning_with_line (pfile, line, column, msgid, ap);
va_end(ap);
}
-#endif
void
-cpp_pedwarn_with_line VPROTO ((cpp_reader * pfile, int line, int column, const char *msg, ...))
+cpp_pedwarn_with_line VPROTO ((cpp_reader * pfile, int line, int column,
+ const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
int line;
int column;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, msg);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
line = va_arg (ap, int);
column = va_arg (ap, int);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
if (CPP_OPTIONS (pfile)->pedantic_errors)
- v_cpp_error_with_line (pfile, column, line, msg, ap);
+ v_cpp_error_with_line (pfile, column, line, msgid, ap);
else
- v_cpp_warning_with_line (pfile, line, column, msg, ap);
+ v_cpp_warning_with_line (pfile, line, column, msgid, ap);
va_end(ap);
}
@@ -7649,23 +3166,24 @@ cpp_pedwarn_with_line VPROTO ((cpp_reader * pfile, int line, int column, const c
giving specified file name and line number, not current. */
void
-cpp_pedwarn_with_file_and_line VPROTO ((cpp_reader *pfile, char *file, int line, const char *msg, ...))
+cpp_pedwarn_with_file_and_line VPROTO ((cpp_reader *pfile, char *file, int line,
+ const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
char *file;
int line;
- const char *msg;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, msg);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
file = va_arg (ap, char *);
line = va_arg (ap, int);
- msg = va_arg (ap, const char *);
+ msgid = va_arg (ap, const char *);
#endif
if (!CPP_OPTIONS (pfile)->pedantic_errors
@@ -7673,7 +3191,7 @@ cpp_pedwarn_with_file_and_line VPROTO ((cpp_reader *pfile, char *file, int line,
return;
if (file != NULL)
cpp_file_line_for_message (pfile, file, line, -1);
- v_cpp_message (pfile, CPP_OPTIONS (pfile)->pedantic_errors, msg, ap);
+ v_cpp_message (pfile, CPP_OPTIONS (pfile)->pedantic_errors, msgid, ap);
va_end(ap);
}
@@ -7704,7 +3222,7 @@ my_strerror (errnum)
#endif
if (!result)
- result = "undocumented I/O error";
+ result = "errno = ?";
return result;
}
@@ -7749,13 +3267,8 @@ cpp_perror_with_name (pfile, name)
*
* Possibly different enum token codes for each C/C++ token.
*
- * Should clean up remaining directives to that do_XXX functions
- * only take two arguments and all have command_reads_line.
- *
* Find and cleanup remaining uses of static variables,
*
- * Support for trigraphs.
- *
* Support -dM flag (dump_all_macros).
*
* Support for_lint flag.
diff --git a/contrib/gcc/cpplib.h b/contrib/gcc/cpplib.h
index 65cb5da..aadec44 100644
--- a/contrib/gcc/cpplib.h
+++ b/contrib/gcc/cpplib.h
@@ -1,5 +1,5 @@
/* Definitions for CPP library.
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Written by Per Bothner, 1994-95.
This program is free software; you can redistribute it and/or modify it
@@ -19,14 +19,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
+#ifndef __GCC_CPPLIB__
+#define __GCC_CPPLIB__
#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#ifdef __cplusplus
extern "C" {
@@ -73,26 +69,12 @@ enum cpp_token {
CPP_POP
};
-#ifndef PARAMS
-#define PARAMS(P) PROTO(P)
-#endif /* !PARAMS */
-
typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *));
typedef int (*parse_cleanup_t) PARAMS((cpp_buffer *, cpp_reader *));
-/* A parse_marker indicates a previous position,
- which we can backtrack to. */
-
-struct parse_marker {
- cpp_buffer *buf;
- struct parse_marker *next;
- int position;
-};
-
-extern void parse_set_mark PARAMS ((struct parse_marker *, cpp_reader *));
-extern void parse_clear_mark PARAMS ((struct parse_marker *));
-extern void parse_goto_mark PARAMS((struct parse_marker *, cpp_reader *));
-extern void parse_move_mark PARAMS((struct parse_marker *, cpp_reader *));
+extern void parse_set_mark PARAMS ((cpp_reader *));
+extern void parse_clear_mark PARAMS ((cpp_reader *));
+extern void parse_goto_mark PARAMS ((cpp_reader *));
extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **));
extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
@@ -103,42 +85,36 @@ extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *));
/* This frees resources used by PFILE. */
extern void cpp_cleanup PARAMS ((cpp_reader *PFILE));
-/* Maintain and search list of included files, for #import. */
-
-#define IMPORT_HASH_SIZE 31
-
-struct import_file {
- char *name;
- ino_t inode;
- dev_t dev;
- struct import_file *next;
-};
-
-/* If we have a huge buffer, may need to cache more recent counts */
-#define CPP_LINE_BASE(BUF) ((BUF)->buf + (BUF)->line_base)
-
-struct cpp_buffer {
- unsigned char *buf;
- unsigned char *cur;
+struct cpp_buffer
+{
+ unsigned char *cur; /* current position */
unsigned char *rlimit; /* end of valid data */
+ unsigned char *buf; /* entire buffer */
unsigned char *alimit; /* end of allocated buffer */
- unsigned char *prev; /* start of current token */
+ unsigned char *line_base; /* start of current line */
+
+ struct cpp_buffer *prev;
+ /* Real filename. (Alias to ->ihash->fname, obsolete). */
char *fname;
/* Filename specified with #line command. */
char *nominal_fname;
+ /* Last filename specified with #line command. */
+ char *last_nominal_fname;
+ /* Actual directory of this file, used only for "" includes */
+ struct file_name_list *actual_dir;
- /* Record where in the search path this file was found.
- For #include_next. */
- struct file_name_list *dir;
+ /* Pointer into the include hash table. Used for include_next and
+ to record control macros. */
+ struct include_hash *ihash;
- long line_base;
long lineno; /* Line number at CPP_LINE_BASE. */
long colno; /* Column number at CPP_LINE_BASE. */
+ long mark; /* Saved position for lengthy backtrack. */
parse_underflow_t underflow;
parse_cleanup_t cleanup;
void *data;
- struct parse_marker *marks;
+
/* Value of if_stack at start of this file.
Used to prohibit unmatched #endif (etc) in an include file. */
struct if_stack *if_stack;
@@ -148,21 +124,22 @@ struct cpp_buffer {
char seen_eof;
/* True if buffer contains escape sequences.
- Currently there are three kinds:
- "@-" means following identifier should not be macro-expanded.
- "@ " means a token-separator. This turns into " " in final output
+ Currently there are two kinds:
+ "\r-" means following identifier should not be macro-expanded.
+ "\r " means a token-separator. This turns into " " in final output
if not stringizing and needed to separate tokens; otherwise nothing.
- "@@" means a normal '@'.
- (An '@' inside a string stands for itself and is never an escape.) */
+ Any other two-character sequence beginning with \r is an error.
+
+ If this is NOT set, then \r is a one-character escape meaning backslash
+ newline. This is guaranteed not to occur in the middle of a token.
+ The two interpretations of \r do not conflict, because the two-character
+ escapes are used only in macro buffers, and backslash-newline is removed
+ from macro expansion text in collect_expansion and/or macarg. */
char has_escapes;
};
-struct cpp_pending; /* Forward declaration - for C++. */
struct file_name_map_list;
-typedef struct assertion_hashnode ASSERTION_HASHNODE;
-#define ASSERTION_HASHSIZE 37
-
/* Maximum nesting of cpp_buffers. We use a static limit, partly for
efficiency, and partly to limit runaway recursion. */
#define CPP_STACK_MAX 200
@@ -171,41 +148,46 @@ typedef struct assertion_hashnode ASSERTION_HASHNODE;
Applying cpp_get_token repeatedly yields a stream of pre-processor
tokens. Usually, there is only one cpp_reader object active. */
-struct cpp_reader {
+struct cpp_reader
+{
parse_underflow_t get_token;
cpp_buffer *buffer;
- cpp_buffer buffer_stack[CPP_STACK_MAX];
-
- int errors; /* Error counter for exit code */
- void *data;
+ cpp_options *opts;
/* A buffer used for both for cpp_get_token's output, and also internally. */
unsigned char *token_buffer;
/* Allocated size of token_buffer. CPP_RESERVE allocates space. */
- int token_buffer_size;
+ unsigned int token_buffer_size;
/* End of the written part of token_buffer. */
unsigned char *limit;
+ /* Error counter for exit code */
+ int errors;
+
/* Line where a newline was first seen in a string constant. */
int multiline_string_line;
/* Current depth in #include directives that use <...>. */
int system_include_depth;
- /* List of included files that contained #pragma once. */
- struct file_name_list *dont_repeat_files;
+ /* Current depth of buffer stack. */
+ int buffer_stack_depth;
+
+ /* Hash table of macros and assertions. See cpphash.c */
+#define HASHSIZE 1403
+ struct hashnode **hashtab;
+
+ /* Hash table of other included files. See cppfiles.c */
+#define ALL_INCLUDE_HASHSIZE 71
+ struct include_hash *all_include_files[ALL_INCLUDE_HASHSIZE];
- /* List of other included files.
- If ->control_macro if nonzero, the file had a #ifndef
- around the entire contents, and ->control_macro gives the macro name. */
- struct file_name_list *all_include_files;
+ /* Chain of `actual directory' file_name_list entries,
+ for "" inclusion. */
+ struct file_name_list *actual_dirs;
/* Current maximum length of directory names in the search path
for include files. (Altered as we get more of them.) */
- int max_include_len;
-
- /* Hash table of files already included with #include or #import. */
- struct import_file *import_hash_table[IMPORT_HASH_SIZE];
+ unsigned int max_include_len;
struct if_stack *if_stack;
@@ -248,8 +230,6 @@ struct cpp_reader {
struct tm *timebuf;
- ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE];
-
/* Buffer of -M output. */
char *deps_buffer;
@@ -262,9 +242,12 @@ struct cpp_reader {
/* Number of bytes since the last newline. */
int deps_column;
-#ifdef __cplusplus
- ~cpp_reader () { cpp_cleanup (this); }
-#endif
+ /* A buffer and a table, used only by read_and_prescan (in cppfiles.c)
+ which are allocated once per cpp_reader object to keep them off the
+ stack and avoid setup costs. */
+ U_CHAR *input_buffer;
+ U_CHAR *input_speccase;
+ size_t input_buffer_len;
};
#define CPP_FATAL_LIMIT 1000
@@ -282,18 +265,18 @@ struct cpp_reader {
#define CPP_OUT_BUFFER(PFILE) ((PFILE)->token_buffer)
/* Number of characters currently in PFILE's output buffer. */
-#define CPP_WRITTEN(PFILE) ((PFILE)->limit - (PFILE)->token_buffer)
+#define CPP_WRITTEN(PFILE) ((size_t)((PFILE)->limit - (PFILE)->token_buffer))
#define CPP_PWRITTEN(PFILE) ((PFILE)->limit)
/* Make sure PFILE->token_buffer has space for at least N more characters. */
#define CPP_RESERVE(PFILE, N) \
- (CPP_WRITTEN (PFILE) + N > (PFILE)->token_buffer_size \
+ (CPP_WRITTEN (PFILE) + (size_t)(N) > (PFILE)->token_buffer_size \
&& (cpp_grow_buffer (PFILE, N), 0))
/* Append string STR (of length N) to PFILE's output buffer.
Assume there is enough space. */
#define CPP_PUTS_Q(PFILE, STR, N) \
- (bcopy (STR, (PFILE)->limit, (N)), (PFILE)->limit += (N))
+ (memcpy ((PFILE)->limit, STR, (N)), (PFILE)->limit += (N))
/* Append string STR (of length N) to PFILE's output buffer. Make space. */
#define CPP_PUTS(PFILE, STR, N) CPP_RESERVE(PFILE, N), CPP_PUTS_Q(PFILE, STR,N)
/* Append character CH to PFILE's output buffer. Assume sufficient space. */
@@ -306,14 +289,36 @@ struct cpp_reader {
#define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA))
#define CPP_SET_WRITTEN(PFILE,N) ((PFILE)->limit = (PFILE)->token_buffer + (N))
-#define CPP_OPTIONS(PFILE) ((cpp_options *) (PFILE)->data)
+/* Advance the current line by one. */
+#define CPP_BUMP_BUFFER_LINE(PBUF) ((PBUF)->lineno++,\
+ (PBUF)->line_base = (PBUF)->cur)
+#define CPP_BUMP_LINE(PFILE) CPP_BUMP_BUFFER_LINE(CPP_BUFFER(PFILE))
+#define CPP_OPTIONS(PFILE) ((PFILE)->opts)
#define CPP_BUFFER(PFILE) ((PFILE)->buffer)
-#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)+1)
+#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)->prev)
/* The bottom of the buffer stack. */
-#define CPP_NULL_BUFFER(PFILE) (&(PFILE)->buffer_stack[CPP_STACK_MAX])
+#define CPP_NULL_BUFFER(PFILE) NULL
+
+/* The `pending' structure accumulates all the options that are not
+ actually processed until we hit cpp_start_read. It consists of
+ several lists, one for each type of option. We keep both head and
+ tail pointers for quick insertion. */
+struct cpp_pending
+{
+ struct pending_option *define_head, *define_tail;
+ struct pending_option *assert_head, *assert_tail;
+
+ struct file_name_list *quote_head, *quote_tail;
+ struct file_name_list *brack_head, *brack_tail;
+ struct file_name_list *systm_head, *systm_tail;
+ struct file_name_list *after_head, *after_tail;
-/* Pointed to by cpp_reader::data. */
+ struct pending_option *imacros_head, *imacros_tail;
+ struct pending_option *include_head, *include_tail;
+};
+
+/* Pointed to by cpp_reader.opts. */
struct cpp_options {
char *in_fname;
@@ -355,9 +360,9 @@ struct cpp_options {
char put_out_comments;
- /* Nonzero means don't process the ANSI trigraph sequences. */
+ /* Nonzero means process the ANSI trigraph sequences. */
- char no_trigraphs;
+ char trigraphs;
/* Nonzero means print the names of included files rather than
the preprocessed output. 1 means just the #include "...",
@@ -443,34 +448,23 @@ struct cpp_options {
/* Nonzero for the 1989 C Standard, including corrigenda and amendments. */
char c89;
+ /* Nonzero for the 199x C Standard, including corrigenda and amendments. */
+ char c9x;
+
/* Nonzero means give all the error messages the ANSI standard requires. */
char pedantic;
char done_initializing;
- struct file_name_list *include; /* First dir to search */
- /* First dir to search for <file> */
- /* This is the first element to use for #include <...>.
- If it is 0, use the entire chain for such includes. */
- struct file_name_list *first_bracket_include;
- /* This is the first element in the chain that corresponds to
- a directory of system header files. */
- struct file_name_list *first_system_include;
- struct file_name_list *last_include; /* Last in chain */
-
- /* Chain of include directories to put at the end of the other chain. */
- struct file_name_list *after_include;
- struct file_name_list *last_after_include; /* Last in chain */
-
- /* Chain to put at the start of the system include files. */
- struct file_name_list *before_system;
- struct file_name_list *last_before_system; /* Last in chain */
-
- /* Directory prefix that should replace `/usr' in the standard
- include file directories. */
+ /* Search paths for include files. */
+ struct file_name_list *quote_include; /* First dir to search for "file" */
+ struct file_name_list *bracket_include;/* First dir to search for <file> */
+
+ /* Directory prefix that should replace `/usr/lib/gcc-lib/TARGET/VERSION'
+ in the standard include file directories. */
char *include_prefix;
+ int include_prefix_len;
- char inhibit_predefs;
char no_standard_includes;
char no_standard_cplusplus_includes;
@@ -496,7 +490,7 @@ struct cpp_options {
even if they are ifdefed out. */
int dump_includes;
- /* Pending -D, -U and -A options, in reverse order. */
+ /* Pending options - -D, -U, -A, -I, -ixxx. */
struct cpp_pending *pending;
/* File name which deps are being written to.
@@ -513,6 +507,47 @@ struct cpp_options {
#define CPP_PEDANTIC(PFILE) (CPP_OPTIONS (PFILE)->pedantic)
#define CPP_PRINT_DEPS(PFILE) (CPP_OPTIONS (PFILE)->print_deps)
+/* List of directories to look for include files in. */
+struct file_name_list
+{
+ struct file_name_list *next;
+ struct file_name_list *alloc; /* for the cache of
+ current directory entries */
+ char *name;
+ unsigned int nlen;
+ /* We use these to tell if the directory mentioned here is a duplicate
+ of an earlier directory on the search path. */
+ ino_t ino;
+ dev_t dev;
+ /* If the following is nonzero, it is a C-language system include
+ directory. */
+ int sysp;
+ /* Mapping of file names for this directory.
+ Only used on MS-DOS and related platforms. */
+ struct file_name_map *name_map;
+};
+#define ABSOLUTE_PATH ((struct file_name_list *)-1)
+
+/* This structure is used for the table of all includes. It is
+ indexed by the `short name' (the name as it appeared in the
+ #include statement) which is stored in *nshort. */
+struct include_hash
+{
+ struct include_hash *next;
+ /* Next file with the same short name but a
+ different (partial) pathname). */
+ struct include_hash *next_this_file;
+
+ /* Location of the file in the include search path.
+ Used for include_next */
+ struct file_name_list *foundhere;
+ char *name; /* (partial) pathname of file */
+ char *nshort; /* name of file as referenced in #include */
+ char *control_macro; /* macro, if any, preventing reinclusion - see
+ redundant_include_p */
+ char *buf, *limit; /* for file content cache, not yet implemented */
+};
+
/* Name under which this program was invoked. */
extern char *progname;
@@ -551,16 +586,11 @@ enum node_type {
T_BASE_FILE, /* `__BASE_FILE__' */
T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
T_VERSION, /* `__VERSION__' */
- T_SIZE_TYPE, /* `__SIZE_TYPE__' */
- T_PTRDIFF_TYPE, /* `__PTRDIFF_TYPE__' */
- T_WCHAR_TYPE, /* `__WCHAR_TYPE__' */
- T_USER_LABEL_PREFIX_TYPE, /* `__USER_LABEL_PREFIX__' */
- T_REGISTER_PREFIX_TYPE, /* `__REGISTER_PREFIX__' */
T_TIME, /* `__TIME__' */
- T_CONST, /* Constant value, used by `__STDC__' */
+ T_STDC, /* `__STDC__' */
+ T_CONST, /* Constant string, used by `__SIZE_TYPE__' etc */
T_MACRO, /* macro defined by `#define' */
T_DISABLED, /* macro temporarily turned off for rescan */
- T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
T_UNUSED /* Used for something not defined. */
};
@@ -625,7 +655,19 @@ struct definition {
} args;
};
-extern unsigned char is_idchar[256];
+/* These tables are not really `const', but they are only modified at
+ initialization time, in a separate translation unit from the rest
+ of the library. We let the rest of the library think they are `const'
+ to get better code and some additional sanity checks. */
+#ifndef FAKE_CONST
+#define FAKE_CONST const
+#endif
+extern FAKE_CONST unsigned char is_idstart[256];
+extern FAKE_CONST unsigned char is_idchar[256];
+extern FAKE_CONST unsigned char is_hor_space[256];
+extern FAKE_CONST unsigned char is_space[256];
+extern FAKE_CONST unsigned char trigraph_table[256];
+#undef FAKE_CONST
/* Stack of conditionals currently in progress
(including both successful and failing conditionals). */
@@ -644,7 +686,10 @@ typedef struct if_stack IF_STACK_FRAME;
extern void cpp_buf_line_and_col PARAMS((cpp_buffer *, long *, long *));
extern cpp_buffer* cpp_file_buffer PARAMS((cpp_reader *));
-extern void cpp_define PARAMS ((cpp_reader*, unsigned char *));
+extern void cpp_define PARAMS ((cpp_reader *, unsigned char *));
+extern void cpp_assert PARAMS ((cpp_reader *, unsigned char *));
+extern void cpp_undef PARAMS ((cpp_reader *, unsigned char *));
+extern void cpp_unassert PARAMS ((cpp_reader *, unsigned char *));
extern void cpp_error PVPROTO ((cpp_reader *, const char *, ...))
ATTRIBUTE_PRINTF_2;
@@ -654,6 +699,8 @@ extern void cpp_pedwarn PVPROTO ((cpp_reader *, const char *, ...))
ATTRIBUTE_PRINTF_2;
extern void cpp_error_with_line PVPROTO ((cpp_reader *, int, int, const char *, ...))
ATTRIBUTE_PRINTF_4;
+extern void cpp_warning_with_line PVPROTO ((cpp_reader *, int, int, const char *, ...))
+ ATTRIBUTE_PRINTF_4;
extern void cpp_pedwarn_with_line PVPROTO ((cpp_reader *, int, int, const char *, ...))
ATTRIBUTE_PRINTF_4;
extern void cpp_pedwarn_with_file_and_line PVPROTO ((cpp_reader *, char *, int, const char *, ...))
@@ -664,7 +711,7 @@ extern void cpp_perror_with_name PROTO ((cpp_reader *, const char *));
extern void v_cpp_message PROTO ((cpp_reader *, int, const char *, va_list));
extern void cpp_grow_buffer PARAMS ((cpp_reader *, long));
-extern int cpp_parse_escape PARAMS ((cpp_reader *, char **));
+extern HOST_WIDEST_INT cpp_parse_escape PARAMS ((cpp_reader *, char **, HOST_WIDEST_INT));
extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *,
unsigned char *, long));
extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *));
@@ -679,6 +726,16 @@ extern int scan_decls PARAMS ((cpp_reader *, int, char **));
extern void skip_rest_of_line PARAMS ((cpp_reader *));
extern void cpp_finish PARAMS ((cpp_reader *));
+extern void quote_string PARAMS ((cpp_reader *, const char *));
+extern void cpp_expand_to_buffer PARAMS ((cpp_reader *, U_CHAR *, int));
+extern void cpp_scan_buffer PARAMS ((cpp_reader *));
+extern int check_macro_name PARAMS ((cpp_reader *, U_CHAR *, int));
+
+/* Last arg to output_line_command. */
+enum file_change_code {same_file, enter_file, leave_file};
+extern void output_line_command PARAMS ((cpp_reader *,
+ enum file_change_code));
+
/* From cpperror.c */
extern void cpp_fatal PVPROTO ((cpp_reader *, const char *, ...))
ATTRIBUTE_PRINTF_2;
@@ -687,7 +744,27 @@ extern void cpp_message PVPROTO ((cpp_reader *, int, const char *, ...))
extern void cpp_pfatal_with_name PROTO ((cpp_reader *, const char *));
extern void cpp_file_line_for_message PROTO ((cpp_reader *, char *, int, int));
extern void cpp_print_containing_files PROTO ((cpp_reader *));
+extern void cpp_notice PVPROTO ((const char *msgid, ...)) ATTRIBUTE_PRINTF_1;
+
+/* In cppfiles.c */
+extern void simplify_pathname PROTO ((char *));
+extern void merge_include_chains PROTO ((struct cpp_options *));
+extern int find_include_file PROTO ((cpp_reader *, char *,
+ struct file_name_list *,
+ struct include_hash **,
+ int *));
+extern int finclude PROTO ((cpp_reader *, int,
+ struct include_hash *));
+extern void deps_output PROTO ((cpp_reader *, char *, int));
+extern struct include_hash *include_hash PROTO ((cpp_reader *, char *, int));
+
+#ifndef INCLUDE_LEN_FUDGE
+#define INCLUDE_LEN_FUDGE 0
+#endif
+
#ifdef __cplusplus
}
#endif
+#endif /* __GCC_CPPLIB__ */
+
diff --git a/contrib/gcc/cppmain.c b/contrib/gcc/cppmain.c
index 0a45e86..0d891f8 100644
--- a/contrib/gcc/cppmain.c
+++ b/contrib/gcc/cppmain.c
@@ -1,5 +1,5 @@
/* CPP main program, using CPP Library.
- Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
Written by Per Bothner, 1994-95.
This program is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef EMACS
#include "config.h"
#include "system.h"
-#include "gansidecl.h"
#else
#include <stdio.h>
@@ -31,30 +30,13 @@ extern char *getenv ();
#endif /* not EMACS */
#include "cpplib.h"
+#include "intl.h"
char *progname;
cpp_reader parse_in;
cpp_options options;
-#ifdef abort
-/* More 'friendly' abort that prints the line and file.
- config.h can #define abort fancy_abort if you like that sort of thing. */
-void
-fatal (s)
- char *s;
-{
- fputs (s, stderr);
- exit (FATAL_EXIT_CODE);
-}
-
-void
-fancy_abort ()
-{
- fatal ("Internal gcc abort.");
-}
-#endif
-
int
main (argc, argv)
@@ -64,13 +46,20 @@ main (argc, argv)
char *p;
int argi = 1; /* Next argument to handle. */
struct cpp_options *opts = &options;
+ enum cpp_token kind;
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && p[-1] != '/') --p;
progname = p;
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
cpp_reader_init (&parse_in);
- parse_in.data = opts;
+ parse_in.opts = opts;
cpp_options_init (opts);
@@ -92,20 +81,30 @@ main (argc, argv)
else if (! freopen (opts->out_fname, "w", stdout))
cpp_pfatal_with_name (&parse_in, opts->out_fname);
- for (;;)
+ do
{
- enum cpp_token kind;
- if (! opts->no_output)
+ kind = cpp_get_token (&parse_in);
+ if (CPP_WRITTEN (&parse_in) >= BUFSIZ || kind == CPP_EOF)
{
- fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (&parse_in), stdout);
+ if (! opts->no_output)
+ {
+ size_t rem, count = CPP_WRITTEN (&parse_in);
+
+ rem = fwrite (parse_in.token_buffer, 1, count, stdout);
+ if (rem < count)
+ /* Write error. */
+ cpp_pfatal_with_name (&parse_in, opts->out_fname);
+ }
+
+ CPP_SET_WRITTEN (&parse_in, 0);
}
- CPP_SET_WRITTEN (&parse_in, 0);
- kind = cpp_get_token (&parse_in);
- if (kind == CPP_EOF)
- break;
}
+ while (kind != CPP_EOF);
cpp_finish (&parse_in);
+ if (fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (&parse_in), stdout)
+ < CPP_WRITTEN (&parse_in))
+ cpp_pfatal_with_name (&parse_in, opts->out_fname);
if (parse_in.errors)
exit (FATAL_EXIT_CODE);
diff --git a/contrib/gcc/cppspec.c b/contrib/gcc/cppspec.c
new file mode 100644
index 0000000..2e02216
--- /dev/null
+++ b/contrib/gcc/cppspec.c
@@ -0,0 +1,234 @@
+/* Specific flags and argument handling of the C preprocessor.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+
+/* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
+ is a customized version of the gcc driver. It forces -E; -S and -c
+ are errors. It defaults to -x c for files with unrecognized
+ extensions, unless -x options appear in argv, in which case we
+ assume the user knows what they're doing. If no explicit input is
+ mentioned, it will read stdin. */
+
+/* Snarfed from gcc.c: */
+
+/* This defines which switch letters take arguments. */
+
+#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
+ ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
+ || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
+ || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
+ || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
+ || (CHAR) == 'B' || (CHAR) == 'b')
+
+#ifndef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
+#endif
+
+/* This defines which multi-letter switches take arguments. */
+
+#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \
+ (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
+ || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
+ || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
+ || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
+ || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
+ || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
+
+#ifndef WORD_SWITCH_TAKES_ARG
+#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
+#endif
+
+/* Suffixes for known sorts of input files. Note that we do not list
+ files which are normally considered to have been preprocessed already,
+ since the user's expectation is that `cpp' always preprocesses. */
+static const char *const known_suffixes[] =
+{
+ ".c", ".C", ".S", ".m",
+ ".cc", ".cxx", ".cpp", ".cp", ".c++",
+ NULL
+};
+
+/* Filter argc and argv before processing by the gcc driver proper. */
+void
+lang_specific_driver (errfn, in_argc, in_argv, in_added_libraries)
+ void (*errfn) PVPROTO((const char *, ...));
+ int *in_argc;
+ char ***in_argv;
+ int *in_added_libraries ATTRIBUTE_UNUSED;
+{
+ int argc = *in_argc;
+ char **argv = *in_argv;
+
+ /* Do we need to read stdin? */
+ int read_stdin = 1;
+
+ /* Do we need to insert -E? */
+ int need_E = 1;
+
+ /* Do we need to insert -no-gcc? */
+ int need_no_gcc = 1;
+
+ /* Have we seen an input file? */
+ int seen_input = 0;
+
+ /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
+ 0 means unnecessary. */
+ int lang_c_here = 0;
+ int lang_S_here = 0;
+ int o_here = 0;
+
+ /* Do we need to fix up an input file with an unrecognized suffix? */
+ int need_fixups = 1;
+
+ int i, j, quote;
+ char **new_argv;
+ int new_argc;
+
+ /* First pass. If we see an -S or -c, barf. If we see an input file,
+ turn off read_stdin. If we see a second input file, it is actually
+ the output file. If we see a third input file, barf. */
+ for (i = 1; i < argc; i++)
+ {
+ if (quote == 1)
+ {
+ quote = 0;
+ continue;
+ }
+
+ if (argv[i][0] == '-')
+ {
+ if (argv[i][1] == '\0')
+ read_stdin = 0;
+ else if (argv[i][2] == '\0')
+ {
+ if (argv[i][1] == 'E')
+ need_E = 0;
+ else if (argv[i][1] == 'S' || argv[i][1] == 'c')
+ {
+ (*errfn) ("`%s' is not a legal option to the preprocessor",
+ argv[i]);
+ return;
+ }
+ else if (argv[i][1] == 'x')
+ {
+ need_fixups = 0;
+ quote = 1;
+ }
+ else if (SWITCH_TAKES_ARG (argv[i][1]))
+ quote = 1;
+ }
+ else if (argv[i][1] == 'x')
+ need_fixups = 0;
+ else if (argv[i][1] == 'g' && !strcmp(&argv[i][2], "cc"))
+ need_no_gcc = 0;
+ else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
+ quote = 1;
+ }
+ else /* not an option */
+ {
+ seen_input++;
+ if (seen_input == 3)
+ {
+ (*errfn) ("too many input files");
+ return;
+ }
+ else if (seen_input == 2)
+ {
+ o_here = i;
+ }
+ else
+ {
+ read_stdin = 0;
+ if (need_fixups)
+ {
+ int l = strlen (argv[i]);
+ int known = 0;
+ const char *const *suff;
+
+ for (suff = known_suffixes; *suff; suff++)
+ if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
+ {
+ known = 1;
+ break;
+ }
+
+ if (! known)
+ {
+ /* .s files are a special case; we have to treat
+ them like .S files so -D__ASSEMBLER__ will be
+ in effect. */
+ if (!strcmp (".s", &argv[i][l - 2]))
+ lang_S_here = i;
+ else
+ lang_c_here = i;
+ }
+ }
+ }
+ }
+ }
+
+ /* If we don't need to edit the command line, we can bail early. */
+
+ new_argc = argc + need_E + need_no_gcc + read_stdin
+ + !!o_here + !!lang_c_here + !!lang_S_here;
+
+ if (new_argc == argc)
+ return;
+
+ new_argv = xmalloc (new_argc * sizeof(char *));
+
+ new_argv[0] = argv[0];
+ j = 1;
+
+ if (need_E)
+ new_argv[j++] = "-E";
+
+ if (need_no_gcc)
+ new_argv[j++] = "-no-gcc";
+
+ for (i = 1; i < argc; i++, j++)
+ {
+ if (i == lang_c_here)
+ new_argv[j++] = "-xc";
+ else if (i == lang_S_here)
+ new_argv[j++] = "-xassembler-with-cpp";
+ else if (i == o_here)
+ new_argv[j++] = "-o";
+
+ new_argv[j] = argv[i];
+ }
+
+ if (read_stdin)
+ new_argv[j] = "-";
+
+ *in_argc = new_argc;
+ *in_argv = new_argv;
+}
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
+int lang_specific_pre_link ()
+{
+ return 0; /* Not used for cpp. */
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for cpp. */
diff --git a/contrib/gcc/cppulp.c b/contrib/gcc/cppulp.c
new file mode 100644
index 0000000..7e7457c
--- /dev/null
+++ b/contrib/gcc/cppulp.c
@@ -0,0 +1,26 @@
+/* CPP Library.
+ Copyright (C) 1986, 87, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Contributed by Per Bothner, 1994-95.
+ Based on CCCP program by Paul Rubin, June 1986
+ Adapted to ANSI C, Richard Stallman, Jan 1987
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+
+#include "output.h"
+
+const char *user_label_prefix = 0;
diff --git a/contrib/gcc/cross-make b/contrib/gcc/cross-make
index 810f505..84be67f 100644
--- a/contrib/gcc/cross-make
+++ b/contrib/gcc/cross-make
@@ -3,14 +3,6 @@
# and gives up immediately if the user has not done so.
LIBGCC1 = $(CROSS_LIBGCC1)
-# Specify tools and options for manipulating libraries for the target machine.
-AR = $(AR_FOR_TARGET)
-AR_FLAGS = $(AR_FOR_TARGET_FLAGS)
-OLDAR = $(AR_FOR_TARGET)
-OLDAR_FLAGS = $(AR_FOR_TARGET_FLAGS)
-RANLIB = $(RANLIB_FOR_TARGET)
-RANLIB_TEST = $(RANLIB_TEST_FOR_TARGET)
-
# Dir to search for system headers. Normally /usr/include.
# Use CROSS_INCLUDE_DIR not TOOL_INCLUDE_DIR for other vendor's headers.
SYSTEM_HEADER_DIR = $(tooldir)/sys-include
@@ -18,8 +10,5 @@ SYSTEM_HEADER_DIR = $(tooldir)/sys-include
# Don't try to compile the things we can't compile.
ALL = all.cross
-# Use cross-compiler version of float.h.
-FLOAT_H = $(CROSS_FLOAT_H)
-
# Don't install assert.h in /usr/local/include.
assertdir = $(tooldir)/include
diff --git a/contrib/gcc/crtstuff.c b/contrib/gcc/crtstuff.c
index a1b9ef8..ccebde1 100644
--- a/contrib/gcc/crtstuff.c
+++ b/contrib/gcc/crtstuff.c
@@ -56,17 +56,6 @@ Boston, MA 02111-1307, USA. */
#include <stddef.h>
#include "frame.h"
-/* This really belongs in gansidecl.h, but for the egcs-1.1.x branch, the
- only code which uses weak attributes is in this file and this file does
- not include gansidecl.h. */
-#ifndef TARGET_ATTRIBUTE_WEAK
-# if SUPPORTS_WEAK
-# define TARGET_ATTRIBUTE_WEAK __attribute__ ((weak))
-# else
-# define TARGET_ATTRIBUTE_WEAK
-# endif
-#endif
-
/* We do not want to add the weak attribute to the declarations of these
routines in frame.h because that will cause the definition of these
symbols to be weak as well.
@@ -95,6 +84,8 @@ extern void __register_frame_info (void *, struct object *)
extern void *__deregister_frame_info (void *)
TARGET_ATTRIBUTE_WEAK;
+#ifndef OBJECT_FORMAT_MACHO
+
/* Provide default definitions for the pseudo-ops used to switch to the
.ctors and .dtors sections.
@@ -166,7 +157,7 @@ typedef void (*func_ptr) (void);
static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];
static void
-__do_global_dtors_aux ()
+__do_global_dtors_aux (void)
{
static func_ptr *p = __DTOR_LIST__ + 1;
static int completed = 0;
@@ -191,7 +182,7 @@ __do_global_dtors_aux ()
/* Stick a call to __do_global_dtors_aux into the .fini section. */
static void __attribute__ ((__unused__))
-fini_dummy ()
+fini_dummy (void)
{
asm (FINI_SECTION_ASM_OP);
__do_global_dtors_aux ();
@@ -207,7 +198,7 @@ fini_dummy ()
call in another function. */
static void
-frame_dummy ()
+frame_dummy (void)
{
static struct object object;
if (__register_frame_info)
@@ -215,7 +206,7 @@ frame_dummy ()
}
static void __attribute__ ((__unused__))
-init_dummy ()
+init_dummy (void)
{
asm (INIT_SECTION_ASM_OP);
frame_dummy ();
@@ -236,7 +227,8 @@ init_dummy ()
to switch to the .text section. */
static void __do_global_ctors_aux ();
-void __do_global_ctors ()
+void
+__do_global_ctors (void)
{
#ifdef INVOKE__main /* If __main won't actually call __do_global_ctors
then it doesn't matter what's inside the function.
@@ -266,7 +258,7 @@ asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
file-scope static-storage C++ objects within shared libraries. */
static void
-__do_global_ctors_aux () /* prologue goes in .init section */
+__do_global_ctors_aux (void) /* prologue goes in .init section */
{
#ifdef FORCE_INIT_SECTION_ALIGN
FORCE_INIT_SECTION_ALIGN; /* Explicit align before switch to .text */
@@ -288,7 +280,7 @@ __do_global_ctors_aux () /* prologue goes in .init section */
static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];
void
-__do_global_dtors ()
+__do_global_dtors (void)
{
func_ptr *p;
for (p = __DTOR_LIST__ + 1; *p; p++)
@@ -305,7 +297,7 @@ __do_global_dtors ()
after libgcc.a, and hence can't call libgcc.a functions directly. That
can lead to unresolved function references. */
void
-__frame_dummy ()
+__frame_dummy (void)
{
static struct object object;
if (__register_frame_info)
@@ -369,7 +361,7 @@ char __EH_FRAME_BEGIN__[] = { };
static func_ptr __CTOR_END__[];
static void
-__do_global_ctors_aux ()
+__do_global_ctors_aux (void)
{
func_ptr *p;
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
@@ -379,7 +371,7 @@ __do_global_ctors_aux ()
/* Stick a call to __do_global_ctors_aux into the .init section. */
static void __attribute__ ((__unused__))
-init_dummy ()
+init_dummy (void)
{
asm (INIT_SECTION_ASM_OP);
__do_global_ctors_aux ();
@@ -428,7 +420,7 @@ init_dummy ()
before we start to execute any of the user's code. */
static void
-__do_global_ctors_aux () /* prologue goes in .text section */
+__do_global_ctors_aux (void) /* prologue goes in .text section */
{
asm (INIT_SECTION_ASM_OP);
DO_GLOBAL_CTORS_BODY;
@@ -454,7 +446,7 @@ static func_ptr __CTOR_END__[];
extern void __frame_dummy (void);
#endif
void
-__do_global_ctors ()
+__do_global_ctors (void)
{
func_ptr *p;
#ifdef EH_FRAME_SECTION_ASM_OP
@@ -501,3 +493,72 @@ STATIC ui32 __FRAME_END__[] __attribute__ ((__unused__)) = { 0 };
#endif /* EH_FRAME_SECTION */
#endif /* defined(CRT_END) */
+
+#else /* OBJECT_FORMAT_MACHO */
+
+/* For Mach-O format executables, we assume that the system's runtime is
+ smart enough to handle constructors and destructors, but doesn't have
+ an init section (if it can't even handle constructors/destructors
+ you should be using INVOKE__main, not crtstuff). All we need to do
+ is install/deinstall the frame information for exceptions. We do this
+ by putting a constructor in crtbegin.o and a destructor in crtend.o.
+
+ crtend.o also puts in the terminating zero in the frame information
+ segment. */
+
+/* The crtstuff for other object formats use the symbol __EH_FRAME_BEGIN__
+ to figure out the start of the exception frame, but here we use
+ getsectbynamefromheader to find this value. Either method would work,
+ but this method avoids creating any global symbols, which seems
+ cleaner. */
+
+#include <mach-o/ldsyms.h>
+extern const struct section *
+ getsectbynamefromheader (const struct mach_header *,
+ const char *, const char *);
+
+#ifdef CRT_BEGIN
+
+static void __reg_frame_ctor () __attribute__ ((constructor));
+
+static void
+__reg_frame_ctor (void)
+{
+ static struct object object;
+ const struct section *eh_frame;
+
+ eh_frame = getsectbynamefromheader (&_mh_execute_header,
+ "__TEXT", "__eh_frame");
+ __register_frame_info ((void *) eh_frame->addr, &object);
+}
+
+#endif /* CRT_BEGIN */
+
+#ifdef CRT_END
+
+static void __dereg_frame_dtor () __attribute__ ((destructor));
+
+static
+void
+__dereg_frame_dtor (void)
+{
+ const struct section *eh_frame;
+
+ eh_frame = getsectbynamefromheader (&_mh_execute_header,
+ "__TEXT", "__eh_frame");
+ __deregister_frame_info ((void *) eh_frame->addr);
+}
+
+/* Terminate the frame section with a final zero. */
+
+/* Force cc1 to switch to .data section. */
+static void * force_to_data[0] __attribute__ ((__unused__)) = { };
+
+typedef unsigned int ui32 __attribute__ ((mode (SI)));
+asm (EH_FRAME_SECTION_ASM_OP);
+static ui32 __FRAME_END__[] __attribute__ ((__unused__)) = { 0 };
+
+#endif /* CRT_END */
+
+#endif /* OBJECT_FORMAT_MACHO */
+
diff --git a/contrib/gcc/cse.c b/contrib/gcc/cse.c
index cfcc4fa..45613ed 100644
--- a/contrib/gcc/cse.c
+++ b/contrib/gcc/cse.c
@@ -1,5 +1,5 @@
/* Common subexpression elimination for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-7, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "toplev.h"
#include "output.h"
+#include "splay-tree.h"
/* The basic idea of common subexpression elimination is to go
through the code, keeping a record of expressions that would
@@ -274,11 +275,6 @@ static rtx prev_insn;
static rtx this_insn;
-/* Index by register number, gives the quantity number
- of the register's current contents. */
-
-static int *reg_qty;
-
/* Index by register number, gives the number of the next (or
previous) register in the chain of registers sharing the same
value.
@@ -290,19 +286,36 @@ static int *reg_qty;
static int *reg_next_eqv;
static int *reg_prev_eqv;
-/* Index by register number, gives the number of times
- that register has been altered in the current basic block. */
+struct cse_reg_info {
+ union {
+ /* The number of times the register has been altered in the current
+ basic block. */
+ int reg_tick;
+
+ /* The next cse_reg_info structure in the free list. */
+ struct cse_reg_info* next;
+ } variant;
+
+ /* The REG_TICK value at which rtx's containing this register are
+ valid in the hash table. If this does not equal the current
+ reg_tick value, such expressions existing in the hash table are
+ invalid. */
+ int reg_in_table;
+
+ /* The quantity number of the register's current contents. */
+ int reg_qty;
+};
-static int *reg_tick;
+/* A free list of cse_reg_info entries. */
+static struct cse_reg_info *cse_reg_info_free_list;
-/* Index by register number, gives the reg_tick value at which
- rtx's containing this register are valid in the hash table.
- If this does not equal the current reg_tick value, such expressions
- existing in the hash table are invalid.
- If this is -1, no expressions containing this register have been
- entered in the table. */
+/* A mapping from registers to cse_reg_info data structures. */
+static splay_tree cse_reg_info_tree;
-static int *reg_in_table;
+/* The last lookup we did into the cse_reg_info_tree. This allows us
+ to cache repeated lookups. */
+static int cached_regno;
+static struct cse_reg_info *cached_cse_reg_info;
/* A HARD_REG_SET containing all the hard registers for which there is
currently a REG expression in the hash table. Note the difference
@@ -316,14 +329,6 @@ static HARD_REG_SET hard_regs_in_table;
static HARD_REG_SET regs_invalidated_by_call;
-/* Two vectors of ints:
- one containing max_reg -1's; the other max_reg + 500 (an approximation
- for max_qty) elements where element i contains i.
- These are used to initialize various other vectors fast. */
-
-static int *all_minus_one;
-static int *consec_ints;
-
/* CUID of insn that starts the basic block currently being cse-processed. */
static int cse_basic_block_start;
@@ -447,7 +452,7 @@ struct table_elt
#define HASH(X, M) \
(GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER \
- ? (((unsigned) REG << 7) + (unsigned) reg_qty[REGNO (X)]) % NBUCKETS \
+ ? (((unsigned) REG << 7) + (unsigned) REG_QTY (REGNO (X))) % NBUCKETS \
: canon_hash (X, M) % NBUCKETS)
/* Determine whether register number N is considered a fixed register for CSE.
@@ -492,10 +497,29 @@ struct table_elt
: 2) \
: notreg_cost(X))
+/* Get the info associated with register N. */
+
+#define GET_CSE_REG_INFO(N) \
+ (((N) == cached_regno && cached_cse_reg_info) \
+ ? cached_cse_reg_info : get_cse_reg_info ((N)))
+
+/* Get the number of times this register has been updated in this
+ basic block. */
+
+#define REG_TICK(N) ((GET_CSE_REG_INFO (N))->variant.reg_tick)
+
+/* Get the point at which REG was recorded in the table. */
+
+#define REG_IN_TABLE(N) ((GET_CSE_REG_INFO (N))->reg_in_table)
+
+/* Get the quantity number for REG. */
+
+#define REG_QTY(N) ((GET_CSE_REG_INFO (N))->reg_qty)
+
/* Determine if the quantity number for register X represents a valid index
into the `qty_...' variables. */
-#define REGNO_QTY_VALID_P(N) (reg_qty[N] != (N))
+#define REGNO_QTY_VALID_P(N) (REG_QTY (N) != (N))
#ifdef ADDRESS_COST
/* The ADDRESS_COST macro does not deal with ADDRESSOF nodes. But,
@@ -626,6 +650,7 @@ static void merge_equiv_classes PROTO((struct table_elt *,
static void invalidate PROTO((rtx, enum machine_mode));
static int cse_rtx_varies_p PROTO((rtx));
static void remove_invalid_refs PROTO((int));
+static void remove_invalid_subreg_refs PROTO((int, int, enum machine_mode));
static void rehash_using_reg PROTO((rtx));
static void invalidate_memory PROTO((void));
static void invalidate_for_call PROTO((void));
@@ -662,9 +687,33 @@ static void cse_check_loop_start PROTO((rtx, rtx));
static void cse_set_around_loop PROTO((rtx, rtx, rtx));
static rtx cse_basic_block PROTO((rtx, rtx, struct branch_path *, int));
static void count_reg_usage PROTO((rtx, int *, rtx, int));
+extern void dump_class PROTO((struct table_elt*));
+static void check_fold_consts PROTO((PTR));
+static struct cse_reg_info* get_cse_reg_info PROTO((int));
+static void free_cse_reg_info PROTO((splay_tree_value));
+static void flush_hash_table PROTO((void));
extern int rtx_equal_function_value_matters;
+/* Dump the expressions in the equivalence class indicated by CLASSP.
+ This function is used only for debugging. */
+void
+dump_class (classp)
+ struct table_elt *classp;
+{
+ struct table_elt *elt;
+
+ fprintf (stderr, "Equivalence chain for ");
+ print_rtl (stderr, classp->exp);
+ fprintf (stderr, ": \n");
+
+ for (elt = classp->first_same_value; elt; elt = elt->next_same_value)
+ {
+ print_rtl (stderr, elt->exp);
+ fprintf (stderr, "\n");
+ }
+}
+
/* Return an estimate of the cost of computing rtx X.
One use is in cse, to decide which expression to keep in the hash table.
Another is in rtl generation, to pick the cheapest way to multiply.
@@ -701,7 +750,7 @@ notreg_cost (x)
int
rtx_cost (x, outer_code)
rtx x;
- enum rtx_code outer_code;
+ enum rtx_code outer_code ATTRIBUTE_UNUSED;
{
register int i, j;
register enum rtx_code code;
@@ -786,6 +835,57 @@ rtx_cost (x, outer_code)
return total;
}
+static struct cse_reg_info *
+get_cse_reg_info (regno)
+ int regno;
+{
+ struct cse_reg_info *cri;
+ splay_tree_node n;
+
+ /* See if we already have this entry. */
+ n = splay_tree_lookup (cse_reg_info_tree,
+ (splay_tree_key) regno);
+ if (n)
+ cri = (struct cse_reg_info *) (n->value);
+ else
+ {
+ /* Get a new cse_reg_info structure. */
+ if (cse_reg_info_free_list)
+ {
+ cri = cse_reg_info_free_list;
+ cse_reg_info_free_list = cri->variant.next;
+ }
+ else
+ cri = (struct cse_reg_info *) xmalloc (sizeof (struct cse_reg_info));
+
+ /* Initialize it. */
+ cri->variant.reg_tick = 0;
+ cri->reg_in_table = -1;
+ cri->reg_qty = regno;
+
+ splay_tree_insert (cse_reg_info_tree,
+ (splay_tree_key) regno,
+ (splay_tree_value) cri);
+ }
+
+ /* Cache this lookup; we tend to be looking up information about the
+ same register several times in a row. */
+ cached_regno = regno;
+ cached_cse_reg_info = cri;
+
+ return cri;
+}
+
+static void
+free_cse_reg_info (v)
+ splay_tree_value v;
+{
+ struct cse_reg_info *cri = (struct cse_reg_info *) v;
+
+ cri->variant.next = cse_reg_info_free_list;
+ cse_reg_info_free_list = cri;
+}
+
/* Clear the hash table and initialize each register with its own quantity,
for a new basic block. */
@@ -796,11 +896,15 @@ new_basic_block ()
next_qty = max_reg;
- bzero ((char *) reg_tick, max_reg * sizeof (int));
+ if (cse_reg_info_tree)
+ {
+ splay_tree_delete (cse_reg_info_tree);
+ cached_cse_reg_info = 0;
+ }
+
+ cse_reg_info_tree = splay_tree_new (splay_tree_compare_ints, 0,
+ free_cse_reg_info);
- bcopy ((char *) all_minus_one, (char *) reg_in_table,
- max_reg * sizeof (int));
- bcopy ((char *) consec_ints, (char *) reg_qty, max_reg * sizeof (int));
CLEAR_HARD_REG_SET (hard_regs_in_table);
/* The per-quantity values used to be initialized here, but it is
@@ -837,7 +941,7 @@ make_new_qty (reg)
if (next_qty >= max_qty)
abort ();
- q = reg_qty[reg] = next_qty++;
+ q = REG_QTY (reg) = next_qty++;
qty_first_reg[q] = reg;
qty_last_reg[q] = reg;
qty_const[q] = qty_const_insn[q] = 0;
@@ -854,13 +958,13 @@ make_regs_eqv (new, old)
register int new, old;
{
register int lastr, firstr;
- register int q = reg_qty[old];
+ register int q = REG_QTY (old);
/* Nothing should become eqv until it has a "non-invalid" qty number. */
if (! REGNO_QTY_VALID_P (old))
abort ();
- reg_qty[new] = q;
+ REG_QTY (new) = q;
firstr = qty_first_reg[q];
lastr = qty_last_reg[q];
@@ -914,7 +1018,7 @@ static void
delete_reg_equiv (reg)
register int reg;
{
- register int q = reg_qty[reg];
+ register int q = REG_QTY (reg);
register int p, n;
/* If invalid, do nothing. */
@@ -933,7 +1037,7 @@ delete_reg_equiv (reg)
else
qty_first_reg[q] = n;
- reg_qty[reg] = reg;
+ REG_QTY (reg) = reg;
}
/* Remove any invalid expressions from the hash table
@@ -971,15 +1075,39 @@ mention_regs (x)
for (i = regno; i < endregno; i++)
{
- if (reg_in_table[i] >= 0 && reg_in_table[i] != reg_tick[i])
+ if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
remove_invalid_refs (i);
- reg_in_table[i] = reg_tick[i];
+ REG_IN_TABLE (i) = REG_TICK (i);
}
return 0;
}
+ /* If this is a SUBREG, we don't want to discard other SUBREGs of the same
+ pseudo if they don't use overlapping words. We handle only pseudos
+ here for simplicity. */
+ if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG
+ && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
+ {
+ int i = REGNO (SUBREG_REG (x));
+
+ if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
+ {
+ /* If reg_tick has been incremented more than once since
+ reg_in_table was last set, that means that the entire
+ register has been set before, so discard anything memorized
+ for the entrire register, including all SUBREG expressions. */
+ if (REG_IN_TABLE (i) != REG_TICK (i) - 1)
+ remove_invalid_refs (i);
+ else
+ remove_invalid_subreg_refs (i, SUBREG_WORD (x), GET_MODE (x));
+ }
+
+ REG_IN_TABLE (i) = REG_TICK (i);
+ return 0;
+ }
+
/* If X is a comparison or a COMPARE and either operand is a register
that does not have a quantity, give it one. This is so that a later
call to record_jump_equiv won't cause X to be assigned a different
@@ -1044,7 +1172,7 @@ insert_regs (x, classp, modified)
wrong mode for that equivalence, don't do anything here. */
if (REGNO_QTY_VALID_P (regno)
- && qty_mode[reg_qty[regno]] != GET_MODE (x))
+ && qty_mode[REG_QTY (regno)] != GET_MODE (x))
return 0;
if (modified || ! REGNO_QTY_VALID_P (regno))
@@ -1061,7 +1189,7 @@ insert_regs (x, classp, modified)
}
make_new_qty (regno);
- qty_mode[reg_qty[regno]] = GET_MODE (x);
+ qty_mode[REG_QTY (regno)] = GET_MODE (x);
return 1;
}
@@ -1077,8 +1205,19 @@ insert_regs (x, classp, modified)
else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG
&& ! REGNO_QTY_VALID_P (REGNO (SUBREG_REG (x))))
{
+ int regno = REGNO (SUBREG_REG (x));
+
insert_regs (SUBREG_REG (x), NULL_PTR, 0);
- mention_regs (SUBREG_REG (x));
+ /* Mention_regs checks if REG_TICK is exactly one larger than
+ REG_IN_TABLE to find out if there was only a single preceding
+ invalidation - for the SUBREG - or another one, which would be
+ for the full register. Since we don't invalidate the SUBREG
+ here first, we might have to bump up REG_TICK so that mention_regs
+ will do the right thing. */
+ if (REG_IN_TABLE (regno) >= 0
+ && REG_TICK (regno) == REG_IN_TABLE (regno) + 1)
+ REG_TICK (regno)++;
+ mention_regs (x);
return 1;
}
else
@@ -1254,6 +1393,17 @@ lookup_as_function (x, code)
{
register struct table_elt *p = lookup (x, safe_hash (x, VOIDmode) % NBUCKETS,
GET_MODE (x));
+ /* If we are looking for a CONST_INT, the mode doesn't really matter, as
+ long as we are narrowing. So if we looked in vain for a mode narrower
+ than word_mode before, look for word_mode now. */
+ if (p == 0 && code == CONST_INT
+ && GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (word_mode))
+ {
+ x = copy_rtx (x);
+ PUT_MODE (x, word_mode);
+ p = lookup (x, safe_hash (x, VOIDmode) % NBUCKETS, word_mode);
+ }
+
if (p == 0)
return 0;
@@ -1401,12 +1551,12 @@ insert (x, classp, hash, mode)
if (elt->is_const && classp && GET_CODE (classp->exp) == REG
&& GET_CODE (x) != REG)
{
- qty_const[reg_qty[REGNO (classp->exp)]]
- = gen_lowpart_if_possible (qty_mode[reg_qty[REGNO (classp->exp)]], x);
- qty_const_insn[reg_qty[REGNO (classp->exp)]] = this_insn;
+ qty_const[REG_QTY (REGNO (classp->exp))]
+ = gen_lowpart_if_possible (qty_mode[REG_QTY (REGNO (classp->exp))], x);
+ qty_const_insn[REG_QTY (REGNO (classp->exp))] = this_insn;
}
- else if (GET_CODE (x) == REG && classp && ! qty_const[reg_qty[REGNO (x)]]
+ else if (GET_CODE (x) == REG && classp && ! qty_const[REG_QTY (REGNO (x))]
&& ! elt->is_const)
{
register struct table_elt *p;
@@ -1415,17 +1565,17 @@ insert (x, classp, hash, mode)
{
if (p->is_const && GET_CODE (p->exp) != REG)
{
- qty_const[reg_qty[REGNO (x)]]
+ qty_const[REG_QTY (REGNO (x))]
= gen_lowpart_if_possible (GET_MODE (x), p->exp);
- qty_const_insn[reg_qty[REGNO (x)]] = this_insn;
+ qty_const_insn[REG_QTY (REGNO (x))] = this_insn;
break;
}
}
}
- else if (GET_CODE (x) == REG && qty_const[reg_qty[REGNO (x)]]
- && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]])
- qty_const_insn[reg_qty[REGNO (x)]] = this_insn;
+ else if (GET_CODE (x) == REG && qty_const[REG_QTY (REGNO (x))]
+ && GET_MODE (x) == qty_mode[REG_QTY (REGNO (x))])
+ qty_const_insn[REG_QTY (REGNO (x))] = this_insn;
/* If this is a constant with symbolic value,
and it has a term with an explicit integer value,
@@ -1517,6 +1667,28 @@ merge_equiv_classes (class1, class2)
}
}
+
+/* Flush the entire hash table. */
+
+static void
+flush_hash_table ()
+{
+ int i;
+ struct table_elt *p;
+
+ for (i = 0; i < NBUCKETS; i++)
+ for (p = table[i]; p; p = table[i])
+ {
+ /* Note that invalidate can remove elements
+ after P in the current hash chain. */
+ if (GET_CODE (p->exp) == REG)
+ invalidate (p->exp, p->mode);
+ else
+ remove_from_table (p, i);
+ }
+}
+
+
/* Remove from the hash table, or mark as invalid,
all expressions whose values could be altered by storing in X.
X is a register, a subreg, or a memory reference with nonvarying address
@@ -1560,7 +1732,7 @@ invalidate (x, full_mode)
overlap these registers. */
delete_reg_equiv (regno);
- reg_tick[regno]++;
+ REG_TICK (regno)++;
if (regno >= FIRST_PSEUDO_REGISTER)
{
@@ -1587,7 +1759,7 @@ invalidate (x, full_mode)
in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, i);
CLEAR_HARD_REG_BIT (hard_regs_in_table, i);
delete_reg_equiv (i);
- reg_tick[i]++;
+ REG_TICK (i)++;
}
if (in_table)
@@ -1604,7 +1776,7 @@ invalidate (x, full_mode)
tendregno
= tregno + HARD_REGNO_NREGS (tregno, GET_MODE (p->exp));
if (tendregno > regno && tregno < endregno)
- remove_from_table (p, hash);
+ remove_from_table (p, hash);
}
}
@@ -1684,6 +1856,37 @@ remove_invalid_refs (regno)
remove_from_table (p, i);
}
}
+
+/* Likewise for a subreg with subreg_reg WORD and mode MODE. */
+static void
+remove_invalid_subreg_refs (regno, word, mode)
+ int regno;
+ int word;
+ enum machine_mode mode;
+{
+ register int i;
+ register struct table_elt *p, *next;
+ int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
+
+ for (i = 0; i < NBUCKETS; i++)
+ for (p = table[i]; p; p = next)
+ {
+ rtx exp;
+ next = p->next_same_hash;
+
+ exp = p->exp;
+ if (GET_CODE (p->exp) != REG
+ && (GET_CODE (exp) != SUBREG
+ || GET_CODE (SUBREG_REG (exp)) != REG
+ || REGNO (SUBREG_REG (exp)) != regno
+ || (((SUBREG_WORD (exp)
+ + (GET_MODE_SIZE (GET_MODE (exp)) - 1) / UNITS_PER_WORD)
+ >= word)
+ && SUBREG_WORD (exp) <= end))
+ && refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
+ remove_from_table (p, i);
+ }
+}
/* Recompute the hash codes of any valid entries in the hash table that
reference X, if X is a register, or SUBREG_REG (X) if X is a SUBREG.
@@ -1694,7 +1897,7 @@ static void
rehash_using_reg (x)
rtx x;
{
- int i;
+ unsigned int i;
struct table_elt *p, *next;
unsigned hash;
@@ -1705,8 +1908,8 @@ rehash_using_reg (x)
valid entries in the table, we have no work to do. */
if (GET_CODE (x) != REG
- || reg_in_table[REGNO (x)] < 0
- || reg_in_table[REGNO (x)] != reg_tick[REGNO (x)])
+ || REG_IN_TABLE (REGNO (x)) < 0
+ || REG_IN_TABLE (REGNO (x)) != REG_TICK (REGNO (x)))
return;
/* Scan all hash chains looking for valid entries that mention X.
@@ -1759,8 +1962,8 @@ invalidate_for_call ()
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
{
delete_reg_equiv (regno);
- if (reg_tick[regno] >= 0)
- reg_tick[regno]++;
+ if (REG_TICK (regno) >= 0)
+ REG_TICK (regno)++;
in_table |= (TEST_HARD_REG_BIT (hard_regs_in_table, regno) != 0);
}
@@ -1911,7 +2114,12 @@ canon_hash (x, mode)
/* On some machines, we can't record any non-fixed hard register,
because extending its life will cause reload problems. We
- consider ap, fp, and sp to be fixed for this purpose.
+ consider ap, fp, and sp to be fixed for this purpose.
+
+ We also consider CCmode registers to be fixed for this purpose;
+ failure to do so leads to failure to simplify 0<100 type of
+ conditionals.
+
On all machines, we can't record any global registers. */
if (regno < FIRST_PSEUDO_REGISTER
@@ -1921,15 +2129,30 @@ canon_hash (x, mode)
&& regno != FRAME_POINTER_REGNUM
&& regno != HARD_FRAME_POINTER_REGNUM
&& regno != ARG_POINTER_REGNUM
- && regno != STACK_POINTER_REGNUM)))
+ && regno != STACK_POINTER_REGNUM
+ && GET_MODE_CLASS (GET_MODE (x)) != MODE_CC)))
{
do_not_record = 1;
return 0;
}
- hash += ((unsigned) REG << 7) + (unsigned) reg_qty[regno];
+ hash += ((unsigned) REG << 7) + (unsigned) REG_QTY (regno);
return hash;
}
+ /* We handle SUBREG of a REG specially because the underlying
+ reg changes its hash value with every value change; we don't
+ want to have to forget unrelated subregs when one subreg changes. */
+ case SUBREG:
+ {
+ if (GET_CODE (SUBREG_REG (x)) == REG)
+ {
+ hash += (((unsigned) SUBREG << 7)
+ + REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
+ return hash;
+ }
+ break;
+ }
+
case CONST_INT:
{
unsigned HOST_WIDE_INT tem = INTVAL (x);
@@ -2104,15 +2327,15 @@ exp_equiv_p (x, y, validate, equal_values)
equivalent. We only have to validate if Y is a register. */
if (CONSTANT_P (x) && GET_CODE (y) == REG
&& REGNO_QTY_VALID_P (REGNO (y))
- && GET_MODE (y) == qty_mode[reg_qty[REGNO (y)]]
- && rtx_equal_p (x, qty_const[reg_qty[REGNO (y)]])
- && (! validate || reg_in_table[REGNO (y)] == reg_tick[REGNO (y)]))
+ && GET_MODE (y) == qty_mode[REG_QTY (REGNO (y))]
+ && rtx_equal_p (x, qty_const[REG_QTY (REGNO (y))])
+ && (! validate || REG_IN_TABLE (REGNO (y)) == REG_TICK (REGNO (y))))
return 1;
if (CONSTANT_P (y) && code == REG
&& REGNO_QTY_VALID_P (REGNO (x))
- && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]]
- && rtx_equal_p (y, qty_const[reg_qty[REGNO (x)]]))
+ && GET_MODE (x) == qty_mode[REG_QTY (REGNO (x))]
+ && rtx_equal_p (y, qty_const[REG_QTY (REGNO (x))]))
return 1;
return 0;
@@ -2149,14 +2372,14 @@ exp_equiv_p (x, y, validate, equal_values)
equivalent. If there are and we are not to validate, they
are equivalent. Otherwise, ensure all regs are up-to-date. */
- if (reg_qty[REGNO (x)] != reg_qty[regno])
+ if (REG_QTY (REGNO (x)) != REG_QTY (regno))
return 0;
if (! validate)
return 1;
for (i = regno; i < endregno; i++)
- if (reg_in_table[i] != reg_tick[i])
+ if (REG_IN_TABLE (i) != REG_TICK (i))
return 0;
return 1;
@@ -2315,20 +2538,20 @@ set_nonvarying_address_components (addr, size, pbase, pstart, pend)
if (GET_CODE (base) == REG
&& qty_const != 0
&& REGNO_QTY_VALID_P (REGNO (base))
- && qty_mode[reg_qty[REGNO (base)]] == GET_MODE (base)
- && qty_const[reg_qty[REGNO (base)]] != 0)
- base = qty_const[reg_qty[REGNO (base)]];
+ && qty_mode[REG_QTY (REGNO (base))] == GET_MODE (base)
+ && qty_const[REG_QTY (REGNO (base))] != 0)
+ base = qty_const[REG_QTY (REGNO (base))];
else if (GET_CODE (base) == PLUS
&& GET_CODE (XEXP (base, 1)) == CONST_INT
&& GET_CODE (XEXP (base, 0)) == REG
&& qty_const != 0
&& REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
- && (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
+ && (qty_mode[REG_QTY (REGNO (XEXP (base, 0)))]
== GET_MODE (XEXP (base, 0)))
- && qty_const[reg_qty[REGNO (XEXP (base, 0))]])
+ && qty_const[REG_QTY (REGNO (XEXP (base, 0)))])
{
start = INTVAL (XEXP (base, 1));
- base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
+ base = qty_const[REG_QTY (REGNO (XEXP (base, 0)))];
}
/* This can happen as the result of virtual register instantiation,
if the initial offset is too large to be a valid address. */
@@ -2337,16 +2560,16 @@ set_nonvarying_address_components (addr, size, pbase, pstart, pend)
&& GET_CODE (XEXP (base, 1)) == REG
&& qty_const != 0
&& REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
- && (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
+ && (qty_mode[REG_QTY (REGNO (XEXP (base, 0)))]
== GET_MODE (XEXP (base, 0)))
- && qty_const[reg_qty[REGNO (XEXP (base, 0))]]
+ && qty_const[REG_QTY (REGNO (XEXP (base, 0)))]
&& REGNO_QTY_VALID_P (REGNO (XEXP (base, 1)))
- && (qty_mode[reg_qty[REGNO (XEXP (base, 1))]]
+ && (qty_mode[REG_QTY (REGNO (XEXP (base, 1)))]
== GET_MODE (XEXP (base, 1)))
- && qty_const[reg_qty[REGNO (XEXP (base, 1))]])
+ && qty_const[REG_QTY (REGNO (XEXP (base, 1)))])
{
- rtx tem = qty_const[reg_qty[REGNO (XEXP (base, 1))]];
- base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
+ rtx tem = qty_const[REG_QTY (REGNO (XEXP (base, 1)))];
+ base = qty_const[REG_QTY (REGNO (XEXP (base, 0)))];
/* One of the two values must be a constant. */
if (GET_CODE (base) != CONST_INT)
@@ -2448,8 +2671,8 @@ cse_rtx_varies_p (x)
if (GET_CODE (x) == REG
&& REGNO_QTY_VALID_P (REGNO (x))
- && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]]
- && qty_const[reg_qty[REGNO (x)]] != 0)
+ && GET_MODE (x) == qty_mode[REG_QTY (REGNO (x))]
+ && qty_const[REG_QTY (REGNO (x))] != 0)
return 0;
if (GET_CODE (x) == PLUS
@@ -2457,8 +2680,8 @@ cse_rtx_varies_p (x)
&& GET_CODE (XEXP (x, 0)) == REG
&& REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
&& (GET_MODE (XEXP (x, 0))
- == qty_mode[reg_qty[REGNO (XEXP (x, 0))]])
- && qty_const[reg_qty[REGNO (XEXP (x, 0))]])
+ == qty_mode[REG_QTY (REGNO (XEXP (x, 0)))])
+ && qty_const[REG_QTY (REGNO (XEXP (x, 0)))])
return 0;
/* This can happen as the result of virtual register instantiation, if
@@ -2471,12 +2694,12 @@ cse_rtx_varies_p (x)
&& GET_CODE (XEXP (x, 1)) == REG
&& REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
&& (GET_MODE (XEXP (x, 0))
- == qty_mode[reg_qty[REGNO (XEXP (x, 0))]])
- && qty_const[reg_qty[REGNO (XEXP (x, 0))]]
+ == qty_mode[REG_QTY (REGNO (XEXP (x, 0)))])
+ && qty_const[REG_QTY (REGNO (XEXP (x, 0)))]
&& REGNO_QTY_VALID_P (REGNO (XEXP (x, 1)))
&& (GET_MODE (XEXP (x, 1))
- == qty_mode[reg_qty[REGNO (XEXP (x, 1))]])
- && qty_const[reg_qty[REGNO (XEXP (x, 1))]])
+ == qty_mode[REG_QTY (REGNO (XEXP (x, 1)))])
+ && qty_const[REG_QTY (REGNO (XEXP (x, 1)))])
return 0;
return rtx_varies_p (x);
@@ -2532,10 +2755,10 @@ canon_reg (x, insn)
|| ! REGNO_QTY_VALID_P (REGNO (x)))
return x;
- first = qty_first_reg[reg_qty[REGNO (x)]];
+ first = qty_first_reg[REG_QTY (REGNO (x))];
return (first >= FIRST_PSEUDO_REGISTER ? regno_reg_rtx[first]
: REGNO_REG_CLASS (first) == NO_REGS ? x
- : gen_rtx_REG (qty_mode[reg_qty[REGNO (x)]], first));
+ : gen_rtx_REG (qty_mode[REG_QTY (REGNO (x))], first));
}
default:
@@ -3150,6 +3373,19 @@ simplify_unary_operation (code, mode, op, op_mode)
!= ((HOST_WIDE_INT) (-1) << (width - 1))))
val &= ((HOST_WIDE_INT) 1 << width) - 1;
+ /* If this would be an entire word for the target, but is not for
+ the host, then sign-extend on the host so that the number will look
+ the same way on the host that it would on the target.
+
+ For example, when building a 64 bit alpha hosted 32 bit sparc
+ targeted compiler, then we want the 32 bit unsigned value -1 to be
+ represented as a 64 bit value -1, and not as 0x00000000ffffffff.
+ The later confuses the sparc backend. */
+
+ if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width
+ && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
+ val |= ((HOST_WIDE_INT) (-1) << width);
+
return GEN_INT (val);
}
@@ -4463,6 +4699,28 @@ cse_gen_binary (code, mode, op0, op1)
return gen_rtx_fmt_ee (code, mode, op0, op1);
}
+struct cfc_args
+{
+ /* Input */
+ rtx op0, op1;
+ /* Output */
+ int equal, op0lt, op1lt;
+};
+
+static void
+check_fold_consts (data)
+ PTR data;
+{
+ struct cfc_args * args = (struct cfc_args *) data;
+ REAL_VALUE_TYPE d0, d1;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (d0, args->op0);
+ REAL_VALUE_FROM_CONST_DOUBLE (d1, args->op1);
+ args->equal = REAL_VALUES_EQUAL (d0, d1);
+ args->op0lt = REAL_VALUES_LESS (d0, d1);
+ args->op1lt = REAL_VALUES_LESS (d1, d0);
+}
+
/* Like simplify_binary_operation except used for relational operators.
MODE is the mode of the operands, not that of the result. If MODE
is VOIDmode, both operands must also be VOIDmode and we compare the
@@ -4524,19 +4782,20 @@ simplify_relational_operation (code, mode, op0, op1)
else if (GET_CODE (op0) == CONST_DOUBLE && GET_CODE (op1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
{
- REAL_VALUE_TYPE d0, d1;
- jmp_buf handler;
+ struct cfc_args args;
+
+ /* Setup input for check_fold_consts() */
+ args.op0 = op0;
+ args.op1 = op1;
- if (setjmp (handler))
+ if (do_float_handler(check_fold_consts, (PTR) &args) == 0)
+ /* We got an exception from check_fold_consts() */
return 0;
- set_float_handler (handler);
- REAL_VALUE_FROM_CONST_DOUBLE (d0, op0);
- REAL_VALUE_FROM_CONST_DOUBLE (d1, op1);
- equal = REAL_VALUES_EQUAL (d0, d1);
- op0lt = op0ltu = REAL_VALUES_LESS (d0, d1);
- op1lt = op1ltu = REAL_VALUES_LESS (d1, d0);
- set_float_handler (NULL_PTR);
+ /* Receive output from check_fold_consts() */
+ equal = args.equal;
+ op0lt = op0ltu = args.op0lt;
+ op1lt = op1ltu = args.op1lt;
}
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
@@ -5072,9 +5331,9 @@ fold_rtx (x, insn)
if (GET_CODE (addr) == REG
&& REGNO_QTY_VALID_P (REGNO (addr))
- && GET_MODE (addr) == qty_mode[reg_qty[REGNO (addr)]]
- && qty_const[reg_qty[REGNO (addr)]] != 0)
- addr = qty_const[reg_qty[REGNO (addr)]];
+ && GET_MODE (addr) == qty_mode[REG_QTY (REGNO (addr))]
+ && qty_const[REG_QTY (REGNO (addr))] != 0)
+ addr = qty_const[REG_QTY (REGNO (addr))];
/* If address is constant, split it into a base and integer offset. */
if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
@@ -5216,12 +5475,12 @@ fold_rtx (x, insn)
/* This is the same as calling equiv_constant; it is duplicated
here for speed. */
if (REGNO_QTY_VALID_P (REGNO (arg))
- && qty_const[reg_qty[REGNO (arg)]] != 0
- && GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != REG
- && GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != PLUS)
+ && qty_const[REG_QTY (REGNO (arg))] != 0
+ && GET_CODE (qty_const[REG_QTY (REGNO (arg))]) != REG
+ && GET_CODE (qty_const[REG_QTY (REGNO (arg))]) != PLUS)
const_arg
= gen_lowpart_if_possible (GET_MODE (arg),
- qty_const[reg_qty[REGNO (arg)]]);
+ qty_const[REG_QTY (REGNO (arg))]);
break;
case CONST:
@@ -5444,8 +5703,8 @@ fold_rtx (x, insn)
&& (folded_arg0 == folded_arg1
|| (GET_CODE (folded_arg0) == REG
&& GET_CODE (folded_arg1) == REG
- && (reg_qty[REGNO (folded_arg0)]
- == reg_qty[REGNO (folded_arg1)]))
+ && (REG_QTY (REGNO (folded_arg0))
+ == REG_QTY (REGNO (folded_arg1))))
|| ((p0 = lookup (folded_arg0,
(safe_hash (folded_arg0, mode_arg0)
% NBUCKETS), mode_arg0))
@@ -5462,7 +5721,7 @@ fold_rtx (x, insn)
(we only check the reverse if not floating-point). */
else if (GET_CODE (folded_arg0) == REG)
{
- int qty = reg_qty[REGNO (folded_arg0)];
+ int qty = REG_QTY (REGNO (folded_arg0));
if (REGNO_QTY_VALID_P (REGNO (folded_arg0))
&& (comparison_dominates_p (qty_comparison_code[qty], code)
@@ -5474,7 +5733,7 @@ fold_rtx (x, insn)
&& rtx_equal_p (qty_comparison_const[qty],
const_arg1))
|| (GET_CODE (folded_arg1) == REG
- && (reg_qty[REGNO (folded_arg1)]
+ && (REG_QTY (REGNO (folded_arg1))
== qty_comparison_qty[qty]))))
return (comparison_dominates_p (qty_comparison_code[qty],
code)
@@ -5672,14 +5931,14 @@ fold_rtx (x, insn)
identical powers of two with post decrement. */
if (code == PLUS && INTVAL (const_arg1) == INTVAL (inner_const)
- && (0
-#if defined(HAVE_PRE_INCREMENT) || defined(HAVE_POST_INCREMENT)
- || exact_log2 (INTVAL (const_arg1)) >= 0
-#endif
-#if defined(HAVE_PRE_DECREMENT) || defined(HAVE_POST_DECREMENT)
- || exact_log2 (- INTVAL (const_arg1)) >= 0
-#endif
- ))
+ && ((HAVE_PRE_INCREMENT
+ && exact_log2 (INTVAL (const_arg1)) >= 0)
+ || (HAVE_POST_INCREMENT
+ && exact_log2 (INTVAL (const_arg1)) >= 0)
+ || (HAVE_PRE_DECREMENT
+ && exact_log2 (- INTVAL (const_arg1)) >= 0)
+ || (HAVE_POST_DECREMENT
+ && exact_log2 (- INTVAL (const_arg1)) >= 0)))
break;
/* Compute the code used to compose the constants. For example,
@@ -5769,10 +6028,10 @@ equiv_constant (x)
{
if (GET_CODE (x) == REG
&& REGNO_QTY_VALID_P (REGNO (x))
- && qty_const[reg_qty[REGNO (x)]])
- x = gen_lowpart_if_possible (GET_MODE (x), qty_const[reg_qty[REGNO (x)]]);
+ && qty_const[REG_QTY (REGNO (x))])
+ x = gen_lowpart_if_possible (GET_MODE (x), qty_const[REG_QTY (REGNO (x))]);
- if (x != 0 && CONSTANT_P (x))
+ if (x == 0 || CONSTANT_P (x))
return x;
/* If X is a MEM, try to fold it outside the context of any insn to see if
@@ -5835,9 +6094,8 @@ gen_lowpart_if_possible (mode, x)
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
if (! memory_address_p (mode, XEXP (new, 0)))
return 0;
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
return new;
}
else
@@ -6050,7 +6308,7 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
op0_elt->in_struct = op0_in_struct;
}
- qty_comparison_code[reg_qty[REGNO (op0)]] = code;
+ qty_comparison_code[REG_QTY (REGNO (op0))] = code;
if (GET_CODE (op1) == REG)
{
/* Look it up again--in case op0 and op1 are the same. */
@@ -6070,13 +6328,13 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
op1_elt->in_struct = op1_in_struct;
}
- qty_comparison_qty[reg_qty[REGNO (op0)]] = reg_qty[REGNO (op1)];
- qty_comparison_const[reg_qty[REGNO (op0)]] = 0;
+ qty_comparison_qty[REG_QTY (REGNO (op0))] = REG_QTY (REGNO (op1));
+ qty_comparison_const[REG_QTY (REGNO (op0))] = 0;
}
else
{
- qty_comparison_qty[reg_qty[REGNO (op0)]] = -1;
- qty_comparison_const[reg_qty[REGNO (op0)]] = op1;
+ qty_comparison_qty[REG_QTY (REGNO (op0))] = -1;
+ qty_comparison_const[REG_QTY (REGNO (op0))] = op1;
}
return;
@@ -7001,8 +7259,8 @@ cse_insn (insn, libcall_insn)
their lifetimes will likely abut instead of overlapping. */
if (GET_CODE (dest) == REG
&& REGNO_QTY_VALID_P (REGNO (dest))
- && qty_mode[reg_qty[REGNO (dest)]] == GET_MODE (dest)
- && qty_first_reg[reg_qty[REGNO (dest)]] != REGNO (dest)
+ && qty_mode[REG_QTY (REGNO (dest))] == GET_MODE (dest)
+ && qty_first_reg[REG_QTY (REGNO (dest))] != REGNO (dest)
&& GET_CODE (src) == REG && REGNO (src) == REGNO (dest)
/* Don't do this if the original insn had a hard reg as
SET_SRC. */
@@ -7011,7 +7269,7 @@ cse_insn (insn, libcall_insn)
/* We can't call canon_reg here because it won't do anything if
SRC is a hard register. */
{
- int first = qty_first_reg[reg_qty[REGNO (src)]];
+ int first = qty_first_reg[REG_QTY (REGNO (src))];
rtx new_src
= (first >= FIRST_PSEUDO_REGISTER
? regno_reg_rtx[first] : gen_rtx_REG (GET_MODE (src), first));
@@ -7065,6 +7323,9 @@ cse_insn (insn, libcall_insn)
{
tem = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+ /* Make sure that the rtx is not shared with any other insn. */
+ src_const = copy_rtx (src_const);
+
/* Record the actual constant value in a REG_EQUAL note, making
a new one if one does not already exist. */
if (tem)
@@ -7085,11 +7346,11 @@ cse_insn (insn, libcall_insn)
the last set for this quantity was for this register. */
if (REGNO_QTY_VALID_P (REGNO (dest))
- && qty_const[reg_qty[REGNO (dest)]] == const0_rtx)
+ && qty_const[REG_QTY (REGNO (dest))] == const0_rtx)
{
/* See if we previously had a REG_WAS_0 note. */
rtx note = find_reg_note (insn, REG_WAS_0, NULL_RTX);
- rtx const_insn = qty_const_insn[reg_qty[REGNO (dest)]];
+ rtx const_insn = qty_const_insn[REG_QTY (REGNO (dest))];
if ((tem = single_set (const_insn)) != 0
&& rtx_equal_p (SET_DEST (tem), dest))
@@ -7222,9 +7483,12 @@ cse_insn (insn, libcall_insn)
&& GET_CODE (NEXT_INSN (p)) != BARRIER
&& GET_CODE (NEXT_INSN (p)) != CODE_LABEL)
{
+ /* Note, we must update P with the return value from
+ delete_insn, otherwise we could get an infinite loop
+ if NEXT_INSN (p) had INSN_DELETED_P set. */
if (GET_CODE (NEXT_INSN (p)) != NOTE
|| NOTE_LINE_NUMBER (NEXT_INSN (p)) == NOTE_INSN_DELETED)
- delete_insn (NEXT_INSN (p));
+ p = PREV_INSN (delete_insn (NEXT_INSN (p)));
else
p = NEXT_INSN (p);
}
@@ -7346,7 +7610,12 @@ cse_insn (insn, libcall_insn)
enum machine_mode mode
= GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
- if (sets[i].src_elt == 0)
+ /* Don't put a hard register source into the table if this is
+ the last insn of a libcall. */
+ if (sets[i].src_elt == 0
+ && (GET_CODE (src) != REG
+ || REGNO (src) >= FIRST_PSEUDO_REGISTER
+ || ! find_reg_note (insn, REG_RETVAL, NULL_RTX)))
{
register struct table_elt *elt;
@@ -7413,6 +7682,12 @@ cse_insn (insn, libcall_insn)
invalidate (XEXP (dest, 0), GET_MODE (dest));
}
+ /* A volatile ASM invalidates everything. */
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
+ && MEM_VOLATILE_P (PATTERN (insn)))
+ flush_hash_table ();
+
/* Make sure registers mentioned in destinations
are safe for use in an expression to be inserted.
This removes from the hash table
@@ -7422,8 +7697,44 @@ cse_insn (insn, libcall_insn)
we are going to hash the SET_DEST values unconditionally. */
for (i = 0; i < n_sets; i++)
- if (sets[i].rtl && GET_CODE (SET_DEST (sets[i].rtl)) != REG)
- mention_regs (SET_DEST (sets[i].rtl));
+ {
+ if (sets[i].rtl)
+ {
+ rtx x = SET_DEST (sets[i].rtl);
+
+ if (GET_CODE (x) != REG)
+ mention_regs (x);
+ else
+ {
+ /* We used to rely on all references to a register becoming
+ inaccessible when a register changes to a new quantity,
+ since that changes the hash code. However, that is not
+ safe, since after NBUCKETS new quantities we get a
+ hash 'collision' of a register with its own invalid
+ entries. And since SUBREGs have been changed not to
+ change their hash code with the hash code of the register,
+ it wouldn't work any longer at all. So we have to check
+ for any invalid references lying around now.
+ This code is similar to the REG case in mention_regs,
+ but it knows that reg_tick has been incremented, and
+ it leaves reg_in_table as -1 . */
+ register int regno = REGNO (x);
+ register int endregno
+ = regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
+ : HARD_REGNO_NREGS (regno, GET_MODE (x)));
+ int i;
+
+ for (i = regno; i < endregno; i++)
+ {
+ if (REG_IN_TABLE (i) >= 0)
+ {
+ remove_invalid_refs (i);
+ REG_IN_TABLE (i) = -1;
+ }
+ }
+ }
+ }
+ }
/* We may have just removed some of the src_elt's from the hash table.
So replace each one with the current head of the same class. */
@@ -7612,15 +7923,20 @@ cse_insn (insn, libcall_insn)
then be used in the sequel and we may be changing a two-operand insn
into a three-operand insn.
- Also do not do this if we are operating on a copy of INSN. */
+ Also do not do this if we are operating on a copy of INSN.
+
+ Also don't do this if INSN ends a libcall; this would cause an unrelated
+ register to be set in the middle of a libcall, and we then get bad code
+ if the libcall is deleted. */
if (n_sets == 1 && sets[0].rtl && GET_CODE (SET_DEST (sets[0].rtl)) == REG
&& NEXT_INSN (PREV_INSN (insn)) == insn
&& GET_CODE (SET_SRC (sets[0].rtl)) == REG
&& REGNO (SET_SRC (sets[0].rtl)) >= FIRST_PSEUDO_REGISTER
&& REGNO_QTY_VALID_P (REGNO (SET_SRC (sets[0].rtl)))
- && (qty_first_reg[reg_qty[REGNO (SET_SRC (sets[0].rtl))]]
- == REGNO (SET_DEST (sets[0].rtl))))
+ && (qty_first_reg[REG_QTY (REGNO (SET_SRC (sets[0].rtl)))]
+ == REGNO (SET_DEST (sets[0].rtl)))
+ && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
{
rtx prev = PREV_INSN (insn);
while (prev && GET_CODE (prev) == NOTE)
@@ -7694,7 +8010,7 @@ cse_insn (insn, libcall_insn)
prev_insn = insn;
}
-/* Remove from the ahsh table all expressions that reference memory. */
+/* Remove from the hash table all expressions that reference memory. */
static void
invalidate_memory ()
{
@@ -7722,8 +8038,8 @@ note_mem_written (addr)
&& GET_CODE (XEXP (addr, 0)) == REG
&& REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
{
- if (reg_tick[STACK_POINTER_REGNUM] >= 0)
- reg_tick[STACK_POINTER_REGNUM]++;
+ if (REG_TICK (STACK_POINTER_REGNUM) >= 0)
+ REG_TICK (STACK_POINTER_REGNUM)++;
/* This should be *very* rare. */
if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
@@ -7832,7 +8148,7 @@ cse_process_notes (x, object)
}
case REG:
- i = reg_qty[REGNO (x)];
+ i = REG_QTY (REGNO (x));
/* Return a constant or a constant register. */
if (REGNO_QTY_VALID_P (REGNO (x))
@@ -8390,20 +8706,8 @@ cse_main (f, nregs, after_loop, file)
max_insn_uid = get_max_uid ();
- all_minus_one = (int *) alloca (nregs * sizeof (int));
- consec_ints = (int *) alloca (nregs * sizeof (int));
-
- for (i = 0; i < nregs; i++)
- {
- all_minus_one[i] = -1;
- consec_ints[i] = i;
- }
-
reg_next_eqv = (int *) alloca (nregs * sizeof (int));
reg_prev_eqv = (int *) alloca (nregs * sizeof (int));
- reg_qty = (int *) alloca (nregs * sizeof (int));
- reg_in_table = (int *) alloca (nregs * sizeof (int));
- reg_tick = (int *) alloca (nregs * sizeof (int));
#ifdef LOAD_EXTEND_OP
@@ -8494,7 +8798,7 @@ cse_main (f, nregs, after_loop, file)
max_qty = val.nsets * 2;
if (file)
- fprintf (file, ";; Processing block from %d to %d, %d sets.\n",
+ fnotice (file, ";; Processing block from %d to %d, %d sets.\n",
INSN_UID (insn), val.last ? INSN_UID (val.last) : 0,
val.nsets);
@@ -8591,8 +8895,6 @@ cse_basic_block (from, to, next_branch, around_loop)
for (insn = from; insn != to; insn = NEXT_INSN (insn))
{
register enum rtx_code code = GET_CODE (insn);
- int i;
- struct table_elt *p, *next;
/* If we have processed 1,000 insns, flush the hash table to
avoid extreme quadratic behavior. We must not include NOTEs
@@ -8605,17 +8907,7 @@ cse_basic_block (from, to, next_branch, around_loop)
Perhaps for 2.9. */
if (code != NOTE && num_insns++ > 1000)
{
- for (i = 0; i < NBUCKETS; i++)
- for (p = table[i]; p; p = next)
- {
- next = p->next_same_hash;
-
- if (GET_CODE (p->exp) == REG)
- invalidate (p->exp, p->mode);
- else
- remove_from_table (p, i);
- }
-
+ flush_hash_table ();
num_insns = 0;
}
@@ -8661,7 +8953,7 @@ cse_basic_block (from, to, next_branch, around_loop)
its destination is the result of the block and hence should be
recorded. */
- if (p = find_reg_note (insn, REG_LIBCALL, NULL_RTX))
+ if ((p = find_reg_note (insn, REG_LIBCALL, NULL_RTX)))
libcall_insn = XEXP (p, 0);
else if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
libcall_insn = NULL_RTX;
diff --git a/contrib/gcc/dbxout.c b/contrib/gcc/dbxout.c
index 5e6f2a9..bc15a4d 100644
--- a/contrib/gcc/dbxout.c
+++ b/contrib/gcc/dbxout.c
@@ -163,10 +163,12 @@ static int source_label_number = 1;
#define FORCE_TEXT
#endif
-/* If there is a system stabs.h, use it. Otherwise, use our own. */
-
-#ifndef HAVE_STABS_H
-#include "gstab.h"
+/* If there is a system stab.h, use it. Otherwise, use our own. */
+/* ??? This is supposed to describe the target's stab format, so using
+ the host HAVE_STAB_H appears to be wrong. For now, we use our own file
+ when cross compiling. */
+#if defined (USG) || !defined (HAVE_STAB_H) || defined (CROSS_COMPILE)
+#include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
#else
#include <stab.h>
@@ -495,7 +497,7 @@ dbxout_typedefs (syms)
void
dbxout_start_new_source_file (filename)
- char *filename;
+ char *filename ATTRIBUTE_UNUSED;
{
#ifdef DBX_USE_BINCL
struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n);
@@ -580,8 +582,8 @@ dbxout_source_line (file, filename, lineno)
void
dbxout_finish (file, filename)
- FILE *file;
- char *filename;
+ FILE *file ATTRIBUTE_UNUSED;
+ char *filename ATTRIBUTE_UNUSED;
{
#ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END
DBX_OUTPUT_MAIN_SOURCE_FILE_END (file, filename);
@@ -1935,7 +1937,7 @@ dbxout_symbol (decl, local)
DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
@@ -2188,7 +2190,7 @@ dbxout_symbol_name (decl, suffix, letter)
static void
dbxout_prepare_symbol (decl)
- tree decl;
+ tree decl ATTRIBUTE_UNUSED;
{
#ifdef WINNING_GDB
char *filename = DECL_SOURCE_FILE (decl);
@@ -2257,7 +2259,7 @@ dbxout_parms (parms)
= eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
{
leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));
leaf_renumber_regs_insn (DECL_RTL (parms));
@@ -2681,7 +2683,7 @@ dbxout_really_begin_function (decl)
void
dbxout_begin_function (decl)
- tree decl;
+ tree decl ATTRIBUTE_UNUSED;
{
#ifdef DBX_FUNCTION_FIRST
dbxout_really_begin_function (decl);
diff --git a/contrib/gcc/doprint.c b/contrib/gcc/doprint.c
index dc36254..2dc4dde 100644
--- a/contrib/gcc/doprint.c
+++ b/contrib/gcc/doprint.c
@@ -1,16 +1,25 @@
/* Provide a version _doprnt in terms of fprintf.
- By Kaveh Ghazi (ghazi@caip.rutgers.edu) 3/29/98
Copyright (C) 1998 Free Software Foundation, Inc.
+ Contributed by Kaveh Ghazi (ghazi@caip.rutgers.edu) 3/29/98
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
*/
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
-#include "gansidecl.h"
#undef _doprnt
#ifdef TEST /* Make sure to use the internal one. */
@@ -205,13 +214,13 @@ checkit VPROTO ((const char* format, ...))
va_list args;
int result;
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
char *format;
#endif
VA_START (args, format);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
format = va_arg (args, char *);
#endif
diff --git a/contrib/gcc/dwarf2.h b/contrib/gcc/dwarf2.h
index db19904..ddbe1b8 100644
--- a/contrib/gcc/dwarf2.h
+++ b/contrib/gcc/dwarf2.h
@@ -4,21 +4,22 @@
Contributed by Gary Funck (gary@intrepid.com). Derived from the
DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com).
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* This file is derived from the DWARF specification (a public document)
Revision 2.0.0 (July 27, 1993) developed by the UNIX International
diff --git a/contrib/gcc/dwarf2out.c b/contrib/gcc/dwarf2out.c
index b72d861..de3d26f 100644
--- a/contrib/gcc/dwarf2out.c
+++ b/contrib/gcc/dwarf2out.c
@@ -1,5 +1,5 @@
/* Output Dwarf2 format symbol table information from the GNU C compiler.
- Copyright (C) 1992, 93, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 95-98, 1999 Free Software Foundation, Inc.
Contributed by Gary Funck (gary@intrepid.com).
Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
Extensively modified by Jason Merrill (jason@cygnus.com).
@@ -18,7 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* The first part of this file deals with the DWARF 2 frame unwind
information, which is also used by the GCC efficient exception handling
@@ -71,10 +72,6 @@ dwarf2out_do_frame ()
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
-#ifndef __GNUC__
-#define inline
-#endif
-
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
@@ -346,6 +343,16 @@ static void dwarf2out_stack_adjust PROTO((rtx));
} while (0)
#endif
+/* ??? This macro takes an RTX in dwarfout.c and a string in dwarf2out.c.
+ We resolve the conflict by creating a new macro ASM_OUTPUT_DWARF2_ADDR_CONST
+ for ports that want to support both DWARF1 and DWARF2. This needs a better
+ solution. See also the comments in sparc/sp64-elf.h. */
+#ifdef ASM_OUTPUT_DWARF2_ADDR_CONST
+#undef ASM_OUTPUT_DWARF_ADDR_CONST
+#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \
+ ASM_OUTPUT_DWARF2_ADDR_CONST (FILE, ADDR)
+#endif
+
#ifndef ASM_OUTPUT_DWARF_ADDR_CONST
#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \
fprintf ((FILE), "\t%s\t%s", UNALIGNED_WORD_ASM_OP, (ADDR))
@@ -632,24 +639,28 @@ expand_builtin_dwarf_reg_size (reg_tree, target)
}
else
{
+ /* Initialize last_end to be larger than any possible
+ DWARF_FRAME_REGNUM. */
+ int last_end = 0x7fffffff;
--n_ranges;
t = build_int_2 (ranges[n_ranges].size, 0);
- size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
- for (; n_ranges--; )
+ do
{
- if ((DWARF_FRAME_REGNUM (ranges[n_ranges].end)
- - DWARF_FRAME_REGNUM (ranges[n_ranges].beg))
- != ranges[n_ranges].end - ranges[n_ranges].beg)
+ int beg = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
+ int end = DWARF_FRAME_REGNUM (ranges[n_ranges].end);
+ if (beg < 0)
+ continue;
+ if (end >= last_end)
abort ();
- if (DWARF_FRAME_REGNUM (ranges[n_ranges].beg) >= size)
+ last_end = end;
+ if (end - beg != ranges[n_ranges].end - ranges[n_ranges].beg)
abort ();
- size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
- build_int_2 (DWARF_FRAME_REGNUM
- (ranges[n_ranges].end), 0)));
+ build_int_2 (end, 0)));
t = fold (build (COND_EXPR, integer_type_node, t2,
build_int_2 (ranges[n_ranges].size, 0), t));
}
+ while (--n_ranges >= 0);
}
return expand_expr (t, target, Pmode, 0);
}
@@ -1026,7 +1037,7 @@ static void
initial_return_save (rtl)
register rtx rtl;
{
- unsigned reg = -1;
+ unsigned int reg = (unsigned int) -1;
long offset = 0;
switch (GET_CODE (rtl))
@@ -1175,6 +1186,230 @@ dwarf2out_stack_adjust (insn)
dwarf2out_args_size (label, args_size);
}
+/* A temporary register used in adjusting SP or setting up the store_reg. */
+static unsigned cfa_temp_reg;
+
+/* A temporary value used in adjusting SP or setting up the store_reg. */
+static long cfa_temp_value;
+
+/* Record call frame debugging information for an expression, which either
+ sets SP or FP (adjusting how we calculate the frame address) or saves a
+ register to the stack. */
+
+static void
+dwarf2out_frame_debug_expr (expr, label)
+ rtx expr;
+ char *label;
+{
+ rtx src, dest;
+ long offset;
+
+ /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
+ the PARALLEL independantly. The first element is always processed if
+ it is a SET. This is for backward compatability. Other elements
+ are processed only if they are SETs and the RTX_FRAME_RELATED_P
+ flag is set in them. */
+
+ if (GET_CODE (expr) == PARALLEL)
+ {
+ int par_index;
+ int limit = XVECLEN (expr, 0);
+
+ for (par_index = 0; par_index < limit; par_index++)
+ {
+ rtx x = XVECEXP (expr, 0, par_index);
+
+ if (GET_CODE (x) == SET &&
+ (RTX_FRAME_RELATED_P (x) || par_index == 0))
+ dwarf2out_frame_debug_expr (x, label);
+ }
+ return;
+ }
+
+ if (GET_CODE (expr) != SET)
+ abort ();
+
+ src = SET_SRC (expr);
+ dest = SET_DEST (expr);
+
+ switch (GET_CODE (dest))
+ {
+ case REG:
+ /* Update the CFA rule wrt SP or FP. Make sure src is
+ relative to the current CFA register. */
+ switch (GET_CODE (src))
+ {
+ /* Setting FP from SP. */
+ case REG:
+ if (cfa_reg != (unsigned) REGNO (src))
+ abort ();
+ if (REGNO (dest) != STACK_POINTER_REGNUM
+ && !(frame_pointer_needed
+ && REGNO (dest) == HARD_FRAME_POINTER_REGNUM))
+ abort ();
+ cfa_reg = REGNO (dest);
+ break;
+
+ case PLUS:
+ case MINUS:
+ if (dest == stack_pointer_rtx)
+ {
+ /* Adjusting SP. */
+ switch (GET_CODE (XEXP (src, 1)))
+ {
+ case CONST_INT:
+ offset = INTVAL (XEXP (src, 1));
+ break;
+ case REG:
+ if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
+ abort ();
+ offset = cfa_temp_value;
+ break;
+ default:
+ abort ();
+ }
+
+ if (XEXP (src, 0) == hard_frame_pointer_rtx)
+ {
+ /* Restoring SP from FP in the epilogue. */
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+ abort ();
+ cfa_reg = STACK_POINTER_REGNUM;
+ }
+ else if (XEXP (src, 0) != stack_pointer_rtx)
+ abort ();
+
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ if (cfa_reg == STACK_POINTER_REGNUM)
+ cfa_offset += offset;
+ if (cfa_store_reg == STACK_POINTER_REGNUM)
+ cfa_store_offset += offset;
+ }
+ else if (dest == hard_frame_pointer_rtx)
+ {
+ /* Either setting the FP from an offset of the SP,
+ or adjusting the FP */
+ if (! frame_pointer_needed
+ || REGNO (dest) != HARD_FRAME_POINTER_REGNUM)
+ abort ();
+
+ if (XEXP (src, 0) == stack_pointer_rtx
+ && GET_CODE (XEXP (src, 1)) == CONST_INT)
+ {
+ if (cfa_reg != STACK_POINTER_REGNUM)
+ abort ();
+ offset = INTVAL (XEXP (src, 1));
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ cfa_offset += offset;
+ cfa_reg = HARD_FRAME_POINTER_REGNUM;
+ }
+ else if (XEXP (src, 0) == hard_frame_pointer_rtx
+ && GET_CODE (XEXP (src, 1)) == CONST_INT)
+ {
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+ abort ();
+ offset = INTVAL (XEXP (src, 1));
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ cfa_offset += offset;
+ }
+
+ else
+ abort();
+ }
+ else
+ {
+ if (GET_CODE (src) != PLUS
+ || XEXP (src, 1) != stack_pointer_rtx)
+ abort ();
+ if (GET_CODE (XEXP (src, 0)) != REG
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
+ abort ();
+ if (cfa_reg != STACK_POINTER_REGNUM)
+ abort ();
+ cfa_store_reg = REGNO (dest);
+ cfa_store_offset = cfa_offset - cfa_temp_value;
+ }
+ break;
+
+ case CONST_INT:
+ cfa_temp_reg = REGNO (dest);
+ cfa_temp_value = INTVAL (src);
+ break;
+
+ case IOR:
+ if (GET_CODE (XEXP (src, 0)) != REG
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg
+ || (unsigned) REGNO (dest) != cfa_temp_reg
+ || GET_CODE (XEXP (src, 1)) != CONST_INT)
+ abort ();
+ cfa_temp_value |= INTVAL (XEXP (src, 1));
+ break;
+
+ default:
+ abort ();
+ }
+ dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ break;
+
+ case MEM:
+ /* Saving a register to the stack. Make sure dest is relative to the
+ CFA register. */
+ if (GET_CODE (src) != REG)
+ abort ();
+ switch (GET_CODE (XEXP (dest, 0)))
+ {
+ /* With a push. */
+ case PRE_INC:
+ case PRE_DEC:
+ offset = GET_MODE_SIZE (GET_MODE (dest));
+ if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
+ offset = -offset;
+
+ if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
+ || cfa_store_reg != STACK_POINTER_REGNUM)
+ abort ();
+ cfa_store_offset += offset;
+ if (cfa_reg == STACK_POINTER_REGNUM)
+ cfa_offset = cfa_store_offset;
+
+ offset = -cfa_store_offset;
+ break;
+
+ /* With an offset. */
+ case PLUS:
+ case MINUS:
+ offset = INTVAL (XEXP (XEXP (dest, 0), 1));
+ if (GET_CODE (XEXP (dest, 0)) == MINUS)
+ offset = -offset;
+
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+ abort ();
+ offset -= cfa_store_offset;
+ break;
+
+ /* Without an offset. */
+ case REG:
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (dest, 0)))
+ abort();
+ offset = -cfa_store_offset;
+ break;
+
+ default:
+ abort ();
+ }
+ dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ dwarf2out_reg_save (label, REGNO (src), offset);
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+
/* Record call frame debugging information for INSN, which either
sets SP or FP (adjusting how we calculate the frame address) or saves a
register to the stack. If INSN is NULL_RTX, initialize our state. */
@@ -1184,12 +1419,7 @@ dwarf2out_frame_debug (insn)
rtx insn;
{
char *label;
- rtx src, dest;
- long offset;
-
- /* A temporary register used in adjusting SP or setting up the store_reg. */
- static unsigned cfa_temp_reg;
- static long cfa_temp_value;
+ rtx src;
if (insn == NULL_RTX)
{
@@ -1213,185 +1443,13 @@ dwarf2out_frame_debug (insn)
label = dwarf2out_cfi_label ();
- insn = PATTERN (insn);
- /* Assume that in a PARALLEL prologue insn, only the first elt is
- significant. Currently this is true. */
- if (GET_CODE (insn) == PARALLEL)
- insn = XVECEXP (insn, 0, 0);
- if (GET_CODE (insn) != SET)
- abort ();
-
- src = SET_SRC (insn);
- dest = SET_DEST (insn);
-
- switch (GET_CODE (dest))
- {
- case REG:
- /* Update the CFA rule wrt SP or FP. Make sure src is
- relative to the current CFA register. */
- switch (GET_CODE (src))
- {
- /* Setting FP from SP. */
- case REG:
- if (cfa_reg != REGNO (src))
- abort ();
- if (REGNO (dest) != STACK_POINTER_REGNUM
- && !(frame_pointer_needed
- && REGNO (dest) == HARD_FRAME_POINTER_REGNUM))
- abort ();
- cfa_reg = REGNO (dest);
- break;
+ src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+ if (src)
+ insn = XEXP (src, 0);
+ else
+ insn = PATTERN (insn);
- case PLUS:
- case MINUS:
- if (dest == stack_pointer_rtx)
- {
- /* Adjusting SP. */
- switch (GET_CODE (XEXP (src, 1)))
- {
- case CONST_INT:
- offset = INTVAL (XEXP (src, 1));
- break;
- case REG:
- if (REGNO (XEXP (src, 1)) != cfa_temp_reg)
- abort ();
- offset = cfa_temp_value;
- break;
- default:
- abort ();
- }
-
- if (XEXP (src, 0) == hard_frame_pointer_rtx)
- {
- /* Restoring SP from FP in the epilogue. */
- if (cfa_reg != HARD_FRAME_POINTER_REGNUM)
- abort ();
- cfa_reg = STACK_POINTER_REGNUM;
- }
- else if (XEXP (src, 0) != stack_pointer_rtx)
- abort ();
-
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset += offset;
- if (cfa_store_reg == STACK_POINTER_REGNUM)
- cfa_store_offset += offset;
- }
- else if (dest == hard_frame_pointer_rtx)
- {
- /* Either setting the FP from an offset of the SP,
- or adjusting the FP */
- if (! frame_pointer_needed
- || REGNO (dest) != HARD_FRAME_POINTER_REGNUM)
- abort ();
-
- if (XEXP (src, 0) == stack_pointer_rtx
- && GET_CODE (XEXP (src, 1)) == CONST_INT)
- {
- if (cfa_reg != STACK_POINTER_REGNUM)
- abort ();
- offset = INTVAL (XEXP (src, 1));
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- cfa_offset += offset;
- cfa_reg = HARD_FRAME_POINTER_REGNUM;
- }
- else if (XEXP (src, 0) == hard_frame_pointer_rtx
- && GET_CODE (XEXP (src, 1)) == CONST_INT)
- {
- if (cfa_reg != HARD_FRAME_POINTER_REGNUM)
- abort ();
- offset = INTVAL (XEXP (src, 1));
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- cfa_offset += offset;
- }
-
- else
- abort();
- }
- else
- {
- if (GET_CODE (src) != PLUS
- || XEXP (src, 1) != stack_pointer_rtx)
- abort ();
- if (GET_CODE (XEXP (src, 0)) != REG
- || REGNO (XEXP (src, 0)) != cfa_temp_reg)
- abort ();
- if (cfa_reg != STACK_POINTER_REGNUM)
- abort ();
- cfa_store_reg = REGNO (dest);
- cfa_store_offset = cfa_offset - cfa_temp_value;
- }
- break;
-
- case CONST_INT:
- cfa_temp_reg = REGNO (dest);
- cfa_temp_value = INTVAL (src);
- break;
-
- case IOR:
- if (GET_CODE (XEXP (src, 0)) != REG
- || REGNO (XEXP (src, 0)) != cfa_temp_reg
- || REGNO (dest) != cfa_temp_reg
- || GET_CODE (XEXP (src, 1)) != CONST_INT)
- abort ();
- cfa_temp_value |= INTVAL (XEXP (src, 1));
- break;
-
- default:
- abort ();
- }
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
- break;
-
- case MEM:
- /* Saving a register to the stack. Make sure dest is relative to the
- CFA register. */
- if (GET_CODE (src) != REG)
- abort ();
- switch (GET_CODE (XEXP (dest, 0)))
- {
- /* With a push. */
- case PRE_INC:
- case PRE_DEC:
- offset = GET_MODE_SIZE (GET_MODE (dest));
- if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
- offset = -offset;
-
- if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
- || cfa_store_reg != STACK_POINTER_REGNUM)
- abort ();
- cfa_store_offset += offset;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset = cfa_store_offset;
-
- offset = -cfa_store_offset;
- break;
-
- /* With an offset. */
- case PLUS:
- case MINUS:
- offset = INTVAL (XEXP (XEXP (dest, 0), 1));
- if (GET_CODE (src) == MINUS)
- offset = -offset;
-
- if (cfa_store_reg != REGNO (XEXP (XEXP (dest, 0), 0)))
- abort ();
- offset -= cfa_store_offset;
- break;
-
- default:
- abort ();
- }
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
- dwarf2out_reg_save (label, REGNO (src), offset);
- break;
-
- default:
- abort ();
- }
+ dwarf2out_frame_debug_expr (insn, label);
}
/* Return the size of an unsigned LEB128 quantity. */
@@ -1665,7 +1723,7 @@ output_call_frame_info (for_eh)
#else
tree label = get_file_function_name ('F');
- data_section ();
+ force_data_section ();
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
@@ -1803,8 +1861,16 @@ output_call_frame_info (for_eh)
fputc ('\n', asm_out_file);
ASM_OUTPUT_LABEL (asm_out_file, l1);
+ /* ??? This always emits a 4 byte offset when for_eh is true, but it
+ emits a target dependent sized offset when for_eh is not true.
+ This inconsistency may confuse gdb. The only case where we need a
+ non-4 byte offset is for the Irix6 N64 ABI, so we may lose SGI
+ compatibility if we emit a 4 byte offset. We need a 4 byte offset
+ though in order to be compatible with the dwarf_fde struct in frame.c.
+ If the for_eh case is changed, then the struct in frame.c has
+ to be adjusted appropriately. */
if (for_eh)
- ASM_OUTPUT_DWARF_DELTA (asm_out_file, l1, "__FRAME_BEGIN__");
+ ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l1, "__FRAME_BEGIN__");
else
ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (FRAME_SECTION));
if (flag_debug_asm)
@@ -1982,7 +2048,7 @@ typedef enum
dw_val_class_die_ref,
dw_val_class_fde_ref,
dw_val_class_lbl_id,
- dw_val_class_section_offset,
+ dw_val_class_lbl_offset,
dw_val_class_str
}
dw_val_class;
@@ -2061,7 +2127,6 @@ typedef struct dw_val_struct
unsigned val_fde_index;
char *val_str;
char *val_lbl_id;
- char *val_section;
unsigned char val_flag;
}
v;
@@ -2361,6 +2426,22 @@ static unsigned pending_types;
be enough for most typical programs. */
#define PENDING_TYPES_INCREMENT 64
+/* A pointer to the base of a list of incomplete types which might be
+ completed at some later time. */
+
+static tree *incomplete_types_list;
+
+/* Number of elements currently allocated for the incomplete_types_list. */
+static unsigned incomplete_types_allocated;
+
+/* Number of elements of incomplete_types_list currently in use. */
+static unsigned incomplete_types;
+
+/* Size (in elements) of increments by which we may expand the incomplete
+ types list. Actually, a single hunk of space of this size should
+ be enough for most typical programs. */
+#define INCOMPLETE_TYPES_INCREMENT 64
+
/* Record whether the function being analyzed contains inlined functions. */
static int current_function_has_inlines;
#if 0 && defined (MIPS_DEBUGGING_INFO)
@@ -2420,7 +2501,7 @@ static void add_AT_addr PROTO((dw_die_ref,
enum dwarf_attribute, char *));
static void add_AT_lbl_id PROTO((dw_die_ref,
enum dwarf_attribute, char *));
-static void add_AT_section_offset PROTO((dw_die_ref,
+static void add_AT_lbl_offset PROTO((dw_die_ref,
enum dwarf_attribute, char *));
static int is_extern_subr_die PROTO((dw_die_ref));
static dw_attr_ref get_AT PROTO((dw_die_ref,
@@ -2593,6 +2674,22 @@ static unsigned lookup_filename PROTO((char *));
#define BSS_SECTION ".bss"
#endif
+/* Labels we insert at beginning sections we can reference instead of
+ the section names themselves. */
+
+#ifndef TEXT_SECTION_LABEL
+#define TEXT_SECTION_LABEL "Ltext"
+#endif
+#ifndef DEBUG_LINE_SECTION_LABEL
+#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
+#endif
+#ifndef DEBUG_INFO_SECTION_LABEL
+#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
+#endif
+#ifndef ABBREV_SECTION_LABEL
+#define ABBREV_SECTION_LABEL "Ldebug_abbrev"
+#endif
+
/* Definitions of defaults for formats and names of various special
(artificial) labels which may be generated within this file (when the -g
@@ -2601,6 +2698,10 @@ static unsigned lookup_filename PROTO((char *));
typically, overriding these defaults is unnecessary. */
static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
#ifndef TEXT_END_LABEL
#define TEXT_END_LABEL "Letext"
@@ -2637,13 +2738,18 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
a string rather than writing to a file. */
#ifndef ASM_NAME_TO_STRING
-#define ASM_NAME_TO_STRING(STR, NAME) \
- do { \
- if ((NAME)[0] == '*') \
- dyn_string_append (STR, NAME + 1); \
- else \
- dyn_string_append (STR, NAME); \
- } \
+#define ASM_NAME_TO_STRING(STR, NAME) \
+ do { \
+ if ((NAME)[0] == '*') \
+ dyn_string_append (STR, NAME + 1); \
+ else \
+ { \
+ char *newstr; \
+ STRIP_NAME_ENCODING (newstr, NAME); \
+ dyn_string_append (STR, user_label_prefix); \
+ dyn_string_append (STR, newstr); \
+ } \
+ } \
while (0)
#endif
@@ -3517,24 +3623,14 @@ static tree
decl_ultimate_origin (decl)
register tree decl;
{
- register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl);
-
- if (immediate_origin == NULL_TREE)
- return NULL_TREE;
- else
- {
- register tree ret_val;
- register tree lookahead = immediate_origin;
-
- do
- {
- ret_val = lookahead;
- lookahead = DECL_ABSTRACT_ORIGIN (ret_val);
- }
- while (lookahead != NULL && lookahead != ret_val);
+#ifdef ENABLE_CHECKING
+ if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
+ /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
+ most distant ancestor, this should never happen. */
+ abort ();
+#endif
- return ret_val;
- }
+ return DECL_ABSTRACT_ORIGIN (decl);
}
/* Determine the "ultimate origin" of a block. The block may be an inlined
@@ -3807,17 +3903,17 @@ add_AT_lbl_id (die, attr_kind, lbl_id)
/* Add a section offset attribute value to a DIE. */
static inline void
-add_AT_section_offset (die, attr_kind, section)
+add_AT_lbl_offset (die, attr_kind, label)
register dw_die_ref die;
register enum dwarf_attribute attr_kind;
- register char *section;
+ register char *label;
{
register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_section_offset;
- attr->dw_attr_val.v.val_section = section;
+ attr->dw_attr_val.val_class = dw_val_class_lbl_offset;
+ attr->dw_attr_val.v.val_lbl_id = label;
add_dwarf_attr (die, attr);
}
@@ -4280,11 +4376,9 @@ print_die (die, outfile)
fprintf (outfile, "die -> <null>");
break;
case dw_val_class_lbl_id:
+ case dw_val_class_lbl_offset:
fprintf (outfile, "label: %s", a->dw_attr_val.v.val_lbl_id);
break;
- case dw_val_class_section_offset:
- fprintf (outfile, "section: %s", a->dw_attr_val.v.val_section);
- break;
case dw_val_class_str:
if (a->dw_attr_val.v.val_str != NULL)
fprintf (outfile, "\"%s\"", a->dw_attr_val.v.val_str);
@@ -4648,7 +4742,7 @@ size_of_die (die)
case dw_val_class_lbl_id:
size += PTR_SIZE;
break;
- case dw_val_class_section_offset:
+ case dw_val_class_lbl_offset:
size += DWARF_OFFSET_SIZE;
break;
case dw_val_class_str:
@@ -4750,14 +4844,15 @@ size_of_line_info ()
/* Prolog. */
size += size_of_line_prolog ();
- /* Set address register instruction. */
- size += size_of_set_address;
-
current_file = 1;
current_line = 1;
for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
{
- register dw_line_info_ref line_info;
+ register dw_line_info_ref line_info = &line_info_table[lt_index];
+
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file)
+ continue;
/* Advance pc instruction. */
/* ??? See the DW_LNS_advance_pc comment in output_line_info. */
@@ -4766,7 +4861,6 @@ size_of_line_info ()
else
size += size_of_set_address;
- line_info = &line_info_table[lt_index];
if (line_info->dw_file_num != current_file)
{
/* Set file number instruction. */
@@ -4810,6 +4904,12 @@ size_of_line_info ()
{
register dw_separate_line_info_ref line_info
= &separate_line_info_table[lt_index];
+
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file
+ && line_info->function == function)
+ goto cont;
+
if (function != line_info->function)
{
function = line_info->function;
@@ -4852,6 +4952,7 @@ size_of_line_info ()
}
}
+ cont:
++lt_index;
/* If we're done with a function, end its sequence. */
@@ -4961,7 +5062,7 @@ value_format (v)
return DW_FORM_data;
case dw_val_class_lbl_id:
return DW_FORM_addr;
- case dw_val_class_section_offset:
+ case dw_val_class_lbl_offset:
return DW_FORM_data;
case dw_val_class_str:
return DW_FORM_string;
@@ -5034,6 +5135,11 @@ output_abbrev_section ()
fprintf (asm_out_file, "\t%s\t0,0\n", ASM_BYTE_OP);
}
+
+ /* We need to properly terminate the abbrev table for this
+ compilation unit, as per the standard, and not rely on
+ workarounds in e.g. gdb. */
+ fprintf (asm_out_file, "\t%s\t0\n", ASM_BYTE_OP);
}
/* Output location description stack opcode's operands (if any). */
@@ -5183,7 +5289,6 @@ output_die (die)
register unsigned long ref_offset;
register unsigned long size;
register dw_loc_descr_ref loc;
- register int i;
output_uleb128 (die->die_abbrev);
if (flag_debug_asm)
@@ -5286,24 +5391,27 @@ output_die (die)
break;
case dw_val_class_float:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- a->dw_attr_val.v.val_float.length * 4);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s %s",
- ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
-
- fputc ('\n', asm_out_file);
- for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
- {
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
- a->dw_attr_val.v.val_float.array[i]);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s fp constant word %d",
- ASM_COMMENT_START, i);
+ {
+ register unsigned int i;
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ a->dw_attr_val.v.val_float.length * 4);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s %s",
+ ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
+
+ fputc ('\n', asm_out_file);
+ for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
+ {
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+ a->dw_attr_val.v.val_float.array[i]);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s fp constant word %u",
+ ASM_COMMENT_START, i);
- fputc ('\n', asm_out_file);
- }
+ fputc ('\n', asm_out_file);
+ }
break;
+ }
case dw_val_class_flag:
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag);
@@ -5334,10 +5442,8 @@ output_die (die)
ASM_OUTPUT_DWARF_ADDR (asm_out_file, a->dw_attr_val.v.val_lbl_id);
break;
- case dw_val_class_section_offset:
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file,
- stripattributes
- (a->dw_attr_val.v.val_section));
+ case dw_val_class_lbl_offset:
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, a->dw_attr_val.v.val_lbl_id);
break;
case dw_val_class_str:
@@ -5346,7 +5452,7 @@ output_die (die)
else
ASM_OUTPUT_ASCII (asm_out_file,
a->dw_attr_val.v.val_str,
- strlen (a->dw_attr_val.v.val_str) + 1);
+ (int) strlen (a->dw_attr_val.v.val_str) + 1);
break;
default:
@@ -5397,7 +5503,7 @@ output_compilation_unit_header ()
fprintf (asm_out_file, "\t%s DWARF version number", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (ABBREV_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, abbrev_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Offset Into Abbrev. Section",
ASM_COMMENT_START);
@@ -5470,7 +5576,7 @@ output_pubnames ()
fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
ASM_COMMENT_START);
@@ -5498,7 +5604,8 @@ output_pubnames ()
}
else
{
- ASM_OUTPUT_ASCII (asm_out_file, pub->name, strlen (pub->name) + 1);
+ ASM_OUTPUT_ASCII (asm_out_file, pub->name,
+ (int) strlen (pub->name) + 1);
}
fputc ('\n', asm_out_file);
@@ -5550,7 +5657,7 @@ output_aranges ()
fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (DEBUG_INFO_SECTION));
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.",
ASM_COMMENT_START);
@@ -5576,12 +5683,13 @@ output_aranges ()
ASM_COMMENT_START, 2 * PTR_SIZE);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, text_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Address", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label, TEXT_SECTION);
+ ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label,
+ text_section_label);
if (flag_debug_asm)
fprintf (asm_out_file, "%s Length", ASM_COMMENT_START);
@@ -5734,7 +5842,7 @@ output_line_info ()
{
ASM_OUTPUT_ASCII (asm_out_file,
file_table[ft_index],
- strlen (file_table[ft_index]) + 1);
+ (int) strlen (file_table[ft_index]) + 1);
}
fputc ('\n', asm_out_file);
@@ -5756,27 +5864,25 @@ output_line_info ()
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
fputc ('\n', asm_out_file);
- /* Set the address register to the first location in the text section */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s DW_LNE_set_address", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- output_uleb128 (1 + PTR_SIZE);
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address);
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
- fputc ('\n', asm_out_file);
+ /* We used to set the address register to the first location in the text
+ section here, but that didn't accomplish anything since we already
+ have a line note for the opening brace of the first function. */
/* Generate the line number to PC correspondence table, encoded as
a series of state machine operations. */
current_file = 1;
current_line = 1;
- strcpy (prev_line_label, TEXT_SECTION);
+ strcpy (prev_line_label, text_section_label);
for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
{
- register dw_line_info_ref line_info;
+ register dw_line_info_ref line_info = &line_info_table[lt_index];
+
+ /* Don't emit anything for redundant notes. Just updating the
+ address doesn't accomplish anything, because we already assume
+ that anything after the last address is this line. */
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file)
+ continue;
/* Emit debug info for the address of the current line, choosing
the encoding that uses the least amount of space. */
@@ -5820,7 +5926,6 @@ output_line_info ()
/* Emit debug info for the source file of the current line, if
different from the previous line. */
- line_info = &line_info_table[lt_index];
if (line_info->dw_file_num != current_file)
{
current_file = line_info->dw_file_num;
@@ -5838,35 +5943,48 @@ output_line_info ()
/* Emit debug info for the current line number, choosing the encoding
that uses the least amount of space. */
- line_offset = line_info->dw_line_num - current_line;
- line_delta = line_offset - DWARF_LINE_BASE;
- current_line = line_info->dw_line_num;
- if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+ if (line_info->dw_line_num != current_line)
{
- /* This can handle deltas from -10 to 234, using the current
- definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This
- takes 1 byte. */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- DWARF_LINE_OPCODE_BASE + line_delta);
- if (flag_debug_asm)
- fprintf (asm_out_file,
- "\t%s line %ld", ASM_COMMENT_START, current_line);
+ line_offset = line_info->dw_line_num - current_line;
+ line_delta = line_offset - DWARF_LINE_BASE;
+ current_line = line_info->dw_line_num;
+ if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+ {
+ /* This can handle deltas from -10 to 234, using the current
+ definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This
+ takes 1 byte. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ DWARF_LINE_OPCODE_BASE + line_delta);
+ if (flag_debug_asm)
+ fprintf (asm_out_file,
+ "\t%s line %ld", ASM_COMMENT_START, current_line);
- fputc ('\n', asm_out_file);
+ fputc ('\n', asm_out_file);
+ }
+ else
+ {
+ /* This can handle any delta. This takes at least 4 bytes,
+ depending on the value being encoded. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s advance to line %ld",
+ ASM_COMMENT_START, current_line);
+
+ fputc ('\n', asm_out_file);
+ output_sleb128 (line_offset);
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
+ fputc ('\n', asm_out_file);
+ }
}
else
{
- /* This can handle any delta. This takes at least 4 bytes, depending
- on the value being encoded. */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s advance to line %ld",
- ASM_COMMENT_START, current_line);
-
- fputc ('\n', asm_out_file);
- output_sleb128 (line_offset);
- fputc ('\n', asm_out_file);
+ /* We still need to start a new row, so output a copy insn. */
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
}
@@ -5916,6 +6034,12 @@ output_line_info ()
register dw_separate_line_info_ref line_info
= &separate_line_info_table[lt_index];
+ /* Don't emit anything for redundant notes. */
+ if (line_info->dw_line_num == current_line
+ && line_info->dw_file_num == current_file
+ && line_info->function == function)
+ goto cont;
+
/* Emit debug info for the address of the current line. If this is
a new function, or the first line of a function, then we need
to handle it differently. */
@@ -6016,10 +6140,21 @@ output_line_info ()
output_sleb128 (line_offset);
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
}
}
+ else
+ {
+ /* We still need to start a new row, so output a copy insn. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START);
+ fputc ('\n', asm_out_file);
+ }
+ cont:
++lt_index;
/* If we're done with a function, end its sequence. */
@@ -7053,9 +7188,42 @@ add_location_or_const_value_attribute (die, decl)
rtl = DECL_INCOMING_RTL (decl);
else if (! BYTES_BIG_ENDIAN
&& TREE_CODE (declared_type) == INTEGER_TYPE
- && TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
+ && (GET_MODE_SIZE (TYPE_MODE (declared_type))
+ <= GET_MODE_SIZE (TYPE_MODE (passed_type))))
rtl = DECL_INCOMING_RTL (decl);
}
+
+ /* If the parm was passed in registers, but lives on the stack, then
+ make a big endian correction if the mode of the type of the
+ parameter is not the same as the mode of the rtl. */
+ /* ??? This is the same series of checks that are made in dbxout.c before
+ we reach the big endian correction code there. It isn't clear if all
+ of these checks are necessary here, but keeping them all is the safe
+ thing to do. */
+ else if (GET_CODE (rtl) == MEM
+ && XEXP (rtl, 0) != const0_rtx
+ && ! CONSTANT_P (XEXP (rtl, 0))
+ /* Not passed in memory. */
+ && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM
+ /* Not passed by invisible reference. */
+ && (GET_CODE (XEXP (rtl, 0)) != REG
+ || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM
+ || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ || REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM
+#endif
+ )
+ /* Big endian correction check. */
+ && BYTES_BIG_ENDIAN
+ && TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl)
+ && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))
+ < UNITS_PER_WORD))
+ {
+ int offset = (UNITS_PER_WORD
+ - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))));
+ rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
+ plus_constant (XEXP (rtl, 0), offset));
+ }
}
if (rtl == NULL_RTX)
@@ -7063,7 +7231,7 @@ add_location_or_const_value_attribute (die, decl)
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (rtl);
#endif
@@ -7528,7 +7696,7 @@ push_decl_scope (scope)
subtype. In such a case, we need to search the decl_scope_table to
find the parent of this subtype. */
- if (TREE_CODE_CLASS (TREE_CODE (scope)) == 't')
+ if (AGGREGATE_TYPE_P (scope))
containing_scope = TYPE_CONTEXT (scope);
else
containing_scope = NULL_TREE;
@@ -7580,6 +7748,12 @@ scope_die_for (t, context_die)
if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
containing_scope = NULL_TREE;
+ /* Ignore function type "scopes" from the C frontend. They mean that
+ a tagged type is local to a parmlist of a function declarator, but
+ that isn't useful to DWARF. */
+ if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE)
+ containing_scope = NULL_TREE;
+
/* Function-local tags and functions get stuck in limbo until they are
fixed up by decls_for_scope. */
if (context_die == NULL && containing_scope != NULL_TREE
@@ -7616,12 +7790,14 @@ scope_die_for (t, context_die)
if (i < 0)
{
- if (scope_die != comp_unit_die
- || TREE_CODE_CLASS (TREE_CODE (containing_scope)) != 't')
+ if (TREE_CODE_CLASS (TREE_CODE (containing_scope)) != 't')
abort ();
if (debug_info_level > DINFO_LEVEL_TERSE
&& !TREE_ASM_WRITTEN (containing_scope))
abort ();
+
+ /* If none of the current dies are suitable, we get file scope. */
+ scope_die = comp_unit_die;
}
}
@@ -7881,6 +8057,39 @@ output_pending_types_for_scope (context_die)
}
}
+/* Remember a type in the incomplete_types_list. */
+
+static void
+add_incomplete_type (type)
+ tree type;
+{
+ if (incomplete_types == incomplete_types_allocated)
+ {
+ incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT;
+ incomplete_types_list
+ = (tree *) xrealloc (incomplete_types_list,
+ sizeof (tree) * incomplete_types_allocated);
+ }
+
+ incomplete_types_list[incomplete_types++] = type;
+}
+
+/* Walk through the list of incomplete types again, trying once more to
+ emit full debugging info for them. */
+
+static void
+retry_incomplete_types ()
+{
+ register tree type;
+
+ while (incomplete_types)
+ {
+ --incomplete_types;
+ type = incomplete_types_list[incomplete_types];
+ gen_type_die (type, comp_unit_die);
+ }
+}
+
/* Generate a DIE to represent an inlined instance of an enumeration type. */
static void
@@ -8162,7 +8371,17 @@ gen_subprogram_die (decl, context_die)
= lookup_filename (DECL_SOURCE_FILE (decl));
if (get_AT_flag (old_die, DW_AT_declaration) != 1)
- abort ();
+ {
+ /* ??? This can happen if there is a bug in the program, for
+ instance, if it has duplicate function definitions. Ideally,
+ we should detect this case and ignore it. For now, if we have
+ already reported an error, any error at all, then assume that
+ we got here because of a input error, not a dwarf2 bug. */
+ extern int errorcount;
+ if (errorcount)
+ return;
+ abort ();
+ }
/* If the definition comes from the same place as the declaration,
maybe use the old DIE. We always want the DIE for this function
@@ -8490,7 +8709,13 @@ gen_label_die (decl, context_die)
else
{
insn = DECL_RTL (decl);
- if (GET_CODE (insn) == CODE_LABEL)
+
+ /* Deleted labels are programmer specified labels which have been
+ eliminated because of various optimisations. We still emit them
+ here so that it is possible to put breakpoints on them. */
+ if (GET_CODE (insn) == CODE_LABEL
+ || ((GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
{
/* When optimization is enabled (via -O) some parts of the compiler
(e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which
@@ -8797,7 +9022,7 @@ gen_struct_or_union_type_die (type, context_die)
return;
if (TYPE_CONTEXT (type) != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't')
+ && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)))
nested = 1;
scope_die = scope_die_for (type, context_die);
@@ -8856,7 +9081,13 @@ gen_struct_or_union_type_die (type, context_die)
}
}
else
- add_AT_flag (type_die, DW_AT_declaration, 1);
+ {
+ add_AT_flag (type_die, DW_AT_declaration, 1);
+
+ /* We can't do this for function-local types, and we don't need to. */
+ if (TREE_PERMANENT (type))
+ add_incomplete_type (type);
+ }
}
/* Generate a DIE for a subroutine _type_. */
@@ -9010,7 +9241,7 @@ gen_type_die (type, context_die)
/* If this is a nested type whose containing class hasn't been
written out yet, writing it out will cover this one, too. */
if (TYPE_CONTEXT (type)
- && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+ && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
{
gen_type_die (TYPE_CONTEXT (type), context_die);
@@ -9029,7 +9260,7 @@ gen_type_die (type, context_die)
gen_struct_or_union_type_die (type, context_die);
if (TYPE_CONTEXT (type)
- && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+ && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
pop_decl_scope ();
@@ -9409,7 +9640,7 @@ dwarf2out_decl (decl)
if (DECL_IGNORED_P (decl))
{
if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl) != NULL)
+ && DECL_INITIAL (decl) != NULL)
abort ();
return;
@@ -9775,6 +10006,21 @@ dwarf2out_init (asm_out_file, main_input_filename)
gen_compile_unit_die (main_input_filename);
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
+ DEBUG_INFO_SECTION_LABEL, 0);
+ ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
+ DEBUG_LINE_SECTION_LABEL, 0);
+
+ ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
+ ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+ ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
+ ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
}
/* Output stuff that dwarf requires at the end of every file,
@@ -9810,6 +10056,10 @@ dwarf2out_finish ()
free (node);
}
+ /* Walk through the list of incomplete types again, trying once more to
+ emit full debugging info for them. */
+ retry_incomplete_types ();
+
/* Traverse the DIE tree and add sibling attributes to those DIE's
that have children. */
add_sibling_attributes (comp_unit_die);
@@ -9842,11 +10092,12 @@ dwarf2out_finish ()
was in .text. */
if (separate_line_info_table_in_use == 0)
{
- add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, TEXT_SECTION);
+ add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
}
- add_AT_section_offset (comp_unit_die, DW_AT_stmt_list, DEBUG_LINE_SECTION);
+ add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list,
+ debug_line_section_label);
}
/* Output the abbreviation table. */
diff --git a/contrib/gcc/dwarfout.c b/contrib/gcc/dwarfout.c
index 80475c6..8e0d018 100644
--- a/contrib/gcc/dwarfout.c
+++ b/contrib/gcc/dwarfout.c
@@ -1,5 +1,5 @@
/* Output Dwarf format symbol table information from the GNU C compiler.
- Copyright (C) 1992, 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 95-98, 1999 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com) of Network Computing Devices.
This file is part of GNU CC.
@@ -63,10 +63,6 @@ extern char *getpwd PROTO((void));
/* Note that the implementation of C++ support herein is (as yet) unfinished.
If you want to try to complete it, more power to you. */
-#if !defined(__GNUC__) || (NDEBUG != 1)
-#define inline
-#endif
-
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
@@ -274,6 +270,22 @@ static unsigned pending_types;
#define PENDING_TYPES_INCREMENT 64
+/* A pointer to the base of a list of incomplete types which might be
+ completed at some later time. */
+
+static tree *incomplete_types_list;
+
+/* Number of elements currently allocated for the incomplete_types_list. */
+static unsigned incomplete_types_allocated;
+
+/* Number of elements of incomplete_types_list currently in use. */
+static unsigned incomplete_types;
+
+/* Size (in elements) of increments by which we may expand the incomplete
+ types list. Actually, a single hunk of space of this size should
+ be enough for most typical programs. */
+#define INCOMPLETE_TYPES_INCREMENT 64
+
/* Pointer to an artificial RECORD_TYPE which we create in dwarfout_init.
This is used in a hack to help us get the DIEs describing types of
formal parameters to come *after* all of the DIEs describing the formal
@@ -857,10 +869,20 @@ static int is_redundant_typedef PROTO((tree));
} while (0)
#endif
+/* ASM_OUTPUT_DWARF_STRING is defined to output an ascii string, but to
+ NOT issue a trailing newline. We define ASM_OUTPUT_DWARF_STRING_NEWLINE
+ based on whether ASM_OUTPUT_DWARF_STRING is defined or not. If it is
+ defined, we call it, then issue the line feed. If not, we supply a
+ default defintion of calling ASM_OUTPUT_ASCII */
+
#ifndef ASM_OUTPUT_DWARF_STRING
-#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
+#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
ASM_OUTPUT_ASCII ((FILE), P, strlen (P)+1)
+#else
+#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
+ ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n")
#endif
+
/************************ general utility functions **************************/
@@ -1150,23 +1172,14 @@ static tree
decl_ultimate_origin (decl)
register tree decl;
{
- register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl);
-
- if (immediate_origin == NULL)
- return NULL;
- else
- {
- register tree ret_val;
- register tree lookahead = immediate_origin;
+#ifdef ENABLE_CHECKING
+ if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
+ /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
+ most distant ancestor, this should never happen. */
+ abort ();
+#endif
- do
- {
- ret_val = lookahead;
- lookahead = DECL_ABSTRACT_ORIGIN (ret_val);
- }
- while (lookahead != NULL && lookahead != ret_val);
- return ret_val;
- }
+ return DECL_ABSTRACT_ORIGIN (decl);
}
/* Determine the "ultimate origin" of a block. The block may be an
@@ -1400,6 +1413,10 @@ fundamental_type_code (type)
if (TYPE_PRECISION (type) == CHAR_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? FT_unsigned_char : FT_char);
+ /* In C++, __java_boolean is an INTEGER_TYPE with precision == 1 */
+ if (TYPE_PRECISION (type) == 1)
+ return FT_boolean;
+
abort ();
case REAL_TYPE:
@@ -1421,7 +1438,16 @@ fundamental_type_code (type)
}
if (TYPE_PRECISION (type) == DOUBLE_TYPE_SIZE)
- return FT_dbl_prec_float;
+ {
+ /* On the SH, when compiling with -m3e or -m4-single-only, both
+ float and double are 32 bits. But since the debugger doesn't
+ know about the subtarget, it always thinks double is 64 bits.
+ So we have to tell the debugger that the type is float to
+ make the output of the 'print' command etc. readable. */
+ if (DOUBLE_TYPE_SIZE == FLOAT_TYPE_SIZE && FLOAT_TYPE_SIZE == 32)
+ return FT_float;
+ return FT_dbl_prec_float;
+ }
if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
return FT_float;
@@ -1893,7 +1919,7 @@ output_enumeral_list (link)
output_enumeral_list (TREE_CHAIN (link));
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
(unsigned) TREE_INT_CST_LOW (TREE_VALUE (link)));
- ASM_OUTPUT_DWARF_STRING (asm_out_file,
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
IDENTIFIER_POINTER (TREE_PURPOSE (link)));
}
}
@@ -2084,8 +2110,16 @@ field_byte_offset (decl)
negative. Gdb fails when given negative bit offsets. We avoid this
by recomputing using the first bit of the bitfield. This will give
us an object which does not completely contain the bitfield, but it
- will be aligned, and it will contain the first bit of the bitfield. */
- if (object_offset_in_bits > bitpos_int)
+ will be aligned, and it will contain the first bit of the bitfield.
+
+ However, only do this for a BYTES_BIG_ENDIAN target. For a
+ ! BYTES_BIG_ENDIAN target, bitpos_int + field_size_in_bits is the first
+ first bit of the bitfield. If we recompute using bitpos_int + 1 below,
+ then we end up computing the object byte offset for the wrong word of the
+ desired bitfield, which in turn causes the field offset to be negative
+ in bit_offset_attribute. */
+ if (BYTES_BIG_ENDIAN
+ && object_offset_in_bits > bitpos_int)
{
deepest_bitpos = bitpos_int + 1;
object_offset_in_bits
@@ -2256,7 +2290,7 @@ const_value_attribute (rtl)
break;
case CONST_STRING:
- ASM_OUTPUT_DWARF_STRING (asm_out_file, XSTR (rtl, 0));
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, XSTR (rtl, 0));
break;
case SYMBOL_REF:
@@ -2415,7 +2449,7 @@ location_or_const_value_attribute (decl)
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (rtl);
#endif
@@ -2466,7 +2500,7 @@ name_attribute (name_string)
if (name_string && *name_string)
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_name);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, name_string);
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, name_string);
}
}
@@ -2904,7 +2938,7 @@ comp_dir_attribute (dirname)
register char *dirname;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_comp_dir);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, dirname);
}
static inline void
@@ -2942,7 +2976,7 @@ prototyped_attribute (func_type)
&& (TYPE_ARG_TYPES (func_type) != NULL))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_prototyped);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
@@ -2951,7 +2985,7 @@ producer_attribute (producer)
register char *producer;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_producer);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, producer);
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, producer);
}
static inline void
@@ -2961,7 +2995,7 @@ inline_attribute (decl)
if (DECL_INLINE (decl))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_inline);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
@@ -3024,7 +3058,7 @@ pure_or_virtual_attribute (func_decl)
else
#endif
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
@@ -3513,7 +3547,12 @@ output_label_die (arg)
{
register rtx insn = DECL_RTL (decl);
- if (GET_CODE (insn) == CODE_LABEL)
+ /* Deleted labels are programmer specified labels which have been
+ eliminated because of various optimisations. We still emit them
+ here so that it is possible to put breakpoints on them. */
+ if (GET_CODE (insn) == CODE_LABEL
+ || ((GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -3751,17 +3790,17 @@ output_inheritance_die (arg)
if (TREE_VIA_VIRTUAL (binfo))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
if (TREE_VIA_PUBLIC (binfo))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
else if (TREE_VIA_PROTECTED (binfo))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
@@ -4205,6 +4244,40 @@ output_pending_types_for_scope (containing_scope)
}
}
+/* Remember a type in the incomplete_types_list. */
+
+static void
+add_incomplete_type (type)
+ tree type;
+{
+ if (incomplete_types == incomplete_types_allocated)
+ {
+ incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT;
+ incomplete_types_list
+ = (tree *) xrealloc (incomplete_types_list,
+ sizeof (tree) * incomplete_types_allocated);
+ }
+
+ incomplete_types_list[incomplete_types++] = type;
+}
+
+/* Walk through the list of incomplete types again, trying once more to
+ emit full debugging info for them. */
+
+static void
+retry_incomplete_types ()
+{
+ register tree type;
+
+ finalizing = 1;
+ while (incomplete_types)
+ {
+ --incomplete_types;
+ type = incomplete_types_list[incomplete_types];
+ output_type (type, NULL_TREE);
+ }
+}
+
static void
output_type (type, containing_scope)
register tree type;
@@ -4369,7 +4442,13 @@ output_type (type, containing_scope)
&& TREE_CODE (TYPE_CONTEXT (type)) != FUNCTION_TYPE
&& TREE_CODE (TYPE_CONTEXT (type)) != METHOD_TYPE))
&& !finalizing)
- return; /* EARLY EXIT! Avoid setting TREE_ASM_WRITTEN. */
+ {
+ /* We can't do this for function-local types, and we don't need
+ to. */
+ if (TREE_PERMANENT (type))
+ add_incomplete_type (type);
+ return; /* EARLY EXIT! Avoid setting TREE_ASM_WRITTEN. */
+ }
/* Prevent infinite recursion in cases where the type of some
member of this type is expressed in terms of this type itself. */
@@ -4424,7 +4503,11 @@ output_type (type, containing_scope)
register int i;
for (i = 0; i < n_bases; i++)
- output_die (output_inheritance_die, TREE_VEC_ELT (bases, i));
+ {
+ tree binfo = TREE_VEC_ELT (bases, i);
+ output_type (BINFO_TYPE (binfo), containing_scope);
+ output_die (output_inheritance_die, binfo);
+ }
}
++in_class;
@@ -5121,7 +5204,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, label);
- ASM_OUTPUT_DWARF_STRING (asm_out_file,
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
IDENTIFIER_POINTER (DECL_NAME (decl)));
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@@ -5159,7 +5242,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, label);
- ASM_OUTPUT_DWARF_STRING (asm_out_file,
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
IDENTIFIER_POINTER (DECL_NAME (decl)));
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@@ -5247,10 +5330,16 @@ dwarfout_file_scope_decl (decl, set_finalizing)
output_pending_types_for_scope (NULL_TREE);
- /* The above call should have totally emptied the pending_types_list. */
-
- if (pending_types != 0)
- abort ();
+ /* The above call should have totally emptied the pending_types_list
+ if this is not a nested function or class. If this is a nested type,
+ then the remaining pending_types will be emitted when the containing type
+ is handled. */
+
+ if (! DECL_CONTEXT (decl))
+ {
+ if (pending_types != 0)
+ abort ();
+ }
ASM_OUTPUT_POP_SECTION (asm_out_file);
@@ -5386,7 +5475,7 @@ generate_new_sfname_entry ()
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
sprintf (label, SFNAMES_ENTRY_LABEL_FMT, filename_table[0].number);
ASM_OUTPUT_LABEL (asm_out_file, label);
- ASM_OUTPUT_DWARF_STRING (asm_out_file,
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
filename_table[0].name
? filename_table[0].name
: "");
@@ -5559,7 +5648,7 @@ generate_macinfo_entry (type_and_offset, string)
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
fprintf (asm_out_file, "\t%s\t%s\n", UNALIGNED_INT_ASM_OP, type_and_offset);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, string);
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, string);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@@ -5740,7 +5829,7 @@ dwarfout_init (asm_out_file, main_input_filename)
strcpy (dirname, pwd);
strcpy (dirname + len, "/");
- ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, dirname);
free (dirname);
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
@@ -5827,6 +5916,8 @@ dwarfout_finish ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
+ retry_incomplete_types ();
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
@@ -5944,7 +6035,7 @@ dwarfout_finish ()
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@@ -5953,7 +6044,7 @@ dwarfout_finish ()
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
- ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
/* Generate the terminating entries for the .debug_aranges section.
@@ -6003,6 +6094,12 @@ dwarfout_finish ()
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
+
+ /* There should not be any pending types left at the end. We need
+ this now because it may not have been checked on the last call to
+ dwarfout_file_scope_decl. */
+ if (pending_types != 0)
+ abort ();
}
#endif /* DWARF_DEBUGGING_INFO */
diff --git a/contrib/gcc/dwarfout.h b/contrib/gcc/dwarfout.h
index b4bb9b9..29c8dd3 100644
--- a/contrib/gcc/dwarfout.h
+++ b/contrib/gcc/dwarfout.h
@@ -35,6 +35,8 @@ extern void dwarfout_end_epilogue PROTO ((void));
extern void dwarfout_begin_block PROTO ((unsigned));
extern void dwarfout_end_block PROTO ((unsigned));
+#ifdef RTX_CODE
extern void dwarfout_label PROTO ((rtx));
+#endif
extern void dwarfout_line PROTO ((char *, unsigned));
diff --git a/contrib/gcc/dyn-string.c b/contrib/gcc/dyn-string.c
index cfcace9..c9edfcb 100644
--- a/contrib/gcc/dyn-string.c
+++ b/contrib/gcc/dyn-string.c
@@ -1,31 +1,28 @@
/* An abstract string datatype.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Contributed by Mark Mitchell (mark@markmitchell.com).
- This file is part of GNU CC.
+This file is part of GNU CC.
- GNU CC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
- GNU CC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+GNU CC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include "gansidecl.h"
#include "dyn-string.h"
-extern char *xmalloc ();
-extern char *xrealloc ();
-
/* Create a new dynamic string capable of holding at least SPACE
characters, including the terminating NUL. If SPACE is 0, it
will be silently increased to 1. */
@@ -65,7 +62,7 @@ dyn_string_delete (ds)
dyn_string_t
dyn_string_append (ds, s)
dyn_string_t ds;
- char *s;
+ const char *s;
{
int len = strlen (s);
dyn_string_resize (ds, ds->length + len + 1 /* '\0' */);
diff --git a/contrib/gcc/dyn-string.h b/contrib/gcc/dyn-string.h
index ed8071f..9f93308 100644
--- a/contrib/gcc/dyn-string.h
+++ b/contrib/gcc/dyn-string.h
@@ -1,22 +1,23 @@
/* An abstract string datatype.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Contributed by Mark Mitchell (mark@markmitchell.com).
- This file is part of GNU CC.
+This file is part of GNU CC.
- GNU CC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
- GNU CC is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+GNU CC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
typedef struct dyn_string
{
@@ -27,5 +28,5 @@ typedef struct dyn_string
extern dyn_string_t dyn_string_new PROTO((int));
extern void dyn_string_delete PROTO((dyn_string_t));
-extern dyn_string_t dyn_string_append PROTO((dyn_string_t, char*));
+extern dyn_string_t dyn_string_append PROTO((dyn_string_t, const char*));
extern dyn_string_t dyn_string_resize PROTO((dyn_string_t, int));
diff --git a/contrib/gcc/eh-common.h b/contrib/gcc/eh-common.h
index 143ddff..c0ff7e7 100644
--- a/contrib/gcc/eh-common.h
+++ b/contrib/gcc/eh-common.h
@@ -1,5 +1,22 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
- This file is part of GNU CC. */
+/* EH stuff
+ Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
/* This file contains the structures required for the language
independant exception handling model. Both the static compiler and
@@ -15,8 +32,6 @@
checking of runtime conditions. If the handler wasn't suppose to
get the exception, it performs a re-throw. */
-#include "gansidecl.h"
-
/* The handler_label field MUST be the first field in this structure. The
__throw() library routine expects uses __eh_stub() from except.c, which
@@ -31,6 +46,8 @@ struct eh_context
void **dynamic_handler_chain;
/* This is language dependent part of the eh context. */
void *info;
+ /* This is used to remember where we threw for re-throws */
+ void *table_index; /* address of exception table entry to rethrow from */
};
#ifndef EH_TABLE_LOOKUP
diff --git a/contrib/gcc/emit-rtl.c b/contrib/gcc/emit-rtl.c
index 2ca007a..36b030a 100644
--- a/contrib/gcc/emit-rtl.c
+++ b/contrib/gcc/emit-rtl.c
@@ -1,5 +1,5 @@
/* Emit RTL for the GNU C-Compiler expander.
- Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-97, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -35,12 +35,8 @@ Boston, MA 02111-1307, USA. */
is the kind of rtx's they make and what arguments they use. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
+#include "toplev.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
@@ -96,18 +92,27 @@ static int no_line_numbers;
All of these except perhaps the floating-point CONST_DOUBLEs
are unique; no other rtx-object will be equal to any of these. */
+/* Avoid warnings by initializing the `fld' field. Since its a union,
+ bypass problems with KNR compilers by only doing so when __GNUC__. */
+#ifdef __GNUC__
+#define FLDI , {{0}}
+#else
+#define FLDI
+#endif
+
struct _global_rtl global_rtl =
{
- {PC, VOIDmode}, /* pc_rtx */
- {CC0, VOIDmode}, /* cc0_rtx */
- {REG}, /* stack_pointer_rtx */
- {REG}, /* frame_pointer_rtx */
- {REG}, /* hard_frame_pointer_rtx */
- {REG}, /* arg_pointer_rtx */
- {REG}, /* virtual_incoming_args_rtx */
- {REG}, /* virtual_stack_vars_rtx */
- {REG}, /* virtual_stack_dynamic_rtx */
- {REG}, /* virtual_outgoing_args_rtx */
+ {PC, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* pc_rtx */
+ {CC0, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* cc0_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* stack_pointer_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* frame_pointer_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* hard_frame_pointer_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* arg_pointer_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_incoming_args_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_vars_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_dynamic_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_outgoing_args_rtx */
+ {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_cfa_rtx */
};
/* We record floating-point CONST_DOUBLEs in each floating-point mode for
@@ -260,6 +265,29 @@ gen_rtx_CONST_INT (mode, arg)
return gen_rtx_raw_CONST_INT (mode, arg);
}
+/* CONST_DOUBLEs needs special handling because its length is known
+ only at run-time. */
+rtx
+gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2)
+ enum machine_mode mode;
+ rtx arg0;
+ HOST_WIDE_INT arg1, arg2;
+{
+ rtx r = rtx_alloc (CONST_DOUBLE);
+ int i;
+
+ PUT_MODE (r, mode);
+ XEXP (r, 0) = arg0;
+ XEXP (r, 1) = NULL_RTX;
+ XWINT (r, 2) = arg1;
+ XWINT (r, 3) = arg2;
+
+ for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 3; --i)
+ XWINT (r, i) = 0;
+
+ return r;
+}
+
rtx
gen_rtx_REG (mode, regno)
enum machine_mode mode;
@@ -346,7 +374,7 @@ gen_rtx_MEM (mode, addr)
rtx
gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
enum rtx_code code;
enum machine_mode mode;
#endif
@@ -357,19 +385,35 @@ gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...))
VA_START (p, mode);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
code = va_arg (p, enum rtx_code);
mode = va_arg (p, enum machine_mode);
#endif
- if (code == CONST_INT)
- rt_val = gen_rtx_CONST_INT (mode, va_arg (p, HOST_WIDE_INT));
- else if (code == REG)
- rt_val = gen_rtx_REG (mode, va_arg (p, int));
- else if (code == MEM)
- rt_val = gen_rtx_MEM (mode, va_arg (p, rtx));
- else
+ switch (code)
{
+ case CONST_INT:
+ rt_val = gen_rtx_CONST_INT (mode, va_arg (p, HOST_WIDE_INT));
+ break;
+
+ case CONST_DOUBLE:
+ {
+ rtx arg0 = va_arg (p, rtx);
+ HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
+ HOST_WIDE_INT arg2 = va_arg (p, HOST_WIDE_INT);
+ rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2);
+ }
+ break;
+
+ case REG:
+ rt_val = gen_rtx_REG (mode, va_arg (p, int));
+ break;
+
+ case MEM:
+ rt_val = gen_rtx_MEM (mode, va_arg (p, rtx));
+ break;
+
+ default:
rt_val = rtx_alloc (code); /* Allocate the storage space. */
rt_val->mode = mode; /* Store the machine mode... */
@@ -414,9 +458,11 @@ gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...))
abort ();
}
}
+ break;
}
+
va_end (p);
- return rt_val; /* Return the new RTX... */
+ return rt_val;
}
/* gen_rtvec (n, [rt1, ..., rtn])
@@ -429,7 +475,7 @@ gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...))
rtvec
gen_rtvec VPROTO((int n, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
int n;
#endif
int i;
@@ -438,7 +484,7 @@ gen_rtvec VPROTO((int n, ...))
VA_START (p, n);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
n = va_arg (p, int);
#endif
@@ -501,11 +547,9 @@ gen_reg_rtx (mode)
{
register rtx val;
- /* Don't let anything called by or after reload create new registers
- (actually, registers can't be created after flow, but this is a good
- approximation). */
-
- if (reload_in_progress || reload_completed)
+ /* Don't let anything called after initial flow analysis create new
+ registers. */
+ if (no_new_pseudos)
abort ();
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
@@ -586,9 +630,15 @@ mark_reg_pointer (reg, align)
rtx reg;
int align;
{
- REGNO_POINTER_FLAG (REGNO (reg)) = 1;
+ if (! REGNO_POINTER_FLAG (REGNO (reg)))
+ {
+ REGNO_POINTER_FLAG (REGNO (reg)) = 1;
- if (align)
+ if (align)
+ REGNO_POINTER_ALIGN (REGNO (reg)) = align;
+ }
+ else if (align && align < REGNO_POINTER_ALIGN (REGNO (reg)))
+ /* We can no-longer be sure just how aligned this pointer is */
REGNO_POINTER_ALIGN (REGNO (reg)) = align;
}
@@ -852,6 +902,22 @@ gen_lowpart_common (mode, x)
r = REAL_VALUE_FROM_TARGET_SINGLE (i);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
+ else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
+ && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
+ || flag_pretend_float)
+ && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && GET_MODE_SIZE (mode) == UNITS_PER_WORD
+ && GET_CODE (x) == CONST_INT
+ && (sizeof (double) * HOST_BITS_PER_CHAR
+ == HOST_BITS_PER_WIDE_INT))
+ {
+ REAL_VALUE_TYPE r;
+ HOST_WIDE_INT i;
+
+ i = INTVAL (x);
+ r = REAL_VALUE_FROM_TARGET_DOUBLE (&i);
+ return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
+ }
#endif
/* Similarly, if this is converting a floating-point value into a
@@ -906,6 +972,11 @@ gen_realpart (mode, x)
{
if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode)
return XEXP (x, 0);
+ else if (WORDS_BIG_ENDIAN
+ && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
+ && REG_P (x)
+ && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ fatal ("Unable to access real part of complex value in a hard register on this target");
else if (WORDS_BIG_ENDIAN)
return gen_highpart (mode, x);
else
@@ -924,6 +995,11 @@ gen_imagpart (mode, x)
return XEXP (x, 1);
else if (WORDS_BIG_ENDIAN)
return gen_lowpart (mode, x);
+ else if (!WORDS_BIG_ENDIAN
+ && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
+ && REG_P (x)
+ && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ fatal ("Unable to access imaginary part of complex value in a hard register on this target");
else
return gen_highpart (mode, x);
}
@@ -940,7 +1016,7 @@ subreg_realpart_p (x)
if (GET_CODE (x) != SUBREG)
abort ();
- return SUBREG_WORD (x) == 0;
+ return SUBREG_WORD (x) * UNITS_PER_WORD < GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x)));
}
/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value,
@@ -1134,12 +1210,16 @@ operand_subword (op, i, validate_address, mode)
if (mode == VOIDmode)
abort ();
- /* If OP is narrower than a word or if we want a word outside OP, fail. */
+ /* If OP is narrower than a word, fail. */
if (mode != BLKmode
- && (GET_MODE_SIZE (mode) < UNITS_PER_WORD
- || (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode)))
+ && (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
return 0;
+ /* If we want a word outside OP, return zero. */
+ if (mode != BLKmode
+ && (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
+ return const0_rtx;
+
/* If OP is already an integer word, return it. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD)
@@ -1148,10 +1228,33 @@ operand_subword (op, i, validate_address, mode)
/* If OP is a REG or SUBREG, we can handle it very simply. */
if (GET_CODE (op) == REG)
{
- /* If the register is not valid for MODE, return 0. If we don't
- do this, there is no way to fix up the resulting REG later. */
+ /* ??? There is a potential problem with this code. It does not
+ properly handle extractions of a subword from a hard register
+ that is larger than word_mode. Presumably the check for
+ HARD_REGNO_MODE_OK catches these most of these cases. */
+
+ /* If OP is a hard register, but OP + I is not a hard register,
+ then extracting a subword is impossible.
+
+ For example, consider if OP is the last hard register and it is
+ larger than word_mode. If we wanted word N (for N > 0) because a
+ part of that hard register was known to contain a useful value,
+ then OP + I would refer to a pseudo, not the hard register we
+ actually wanted. */
if (REGNO (op) < FIRST_PSEUDO_REGISTER
- && ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode))
+ && REGNO (op) + i >= FIRST_PSEUDO_REGISTER)
+ return 0;
+
+ /* If the register is not valid for MODE, return 0. Note we
+ have to check both OP and OP + I since they may refer to
+ different parts of the register file.
+
+ Consider if OP refers to the last 96bit FP register and we want
+ subword 3 because that subword is known to contain a value we
+ needed. */
+ if (REGNO (op) < FIRST_PSEUDO_REGISTER
+ && (! HARD_REGNO_MODE_OK (REGNO (op), word_mode)
+ || ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)))
return 0;
else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| (REG_FUNCTION_VALUE_P (op)
@@ -1197,8 +1300,7 @@ operand_subword (op, i, validate_address, mode)
new = gen_rtx_MEM (word_mode, addr);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (op);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (op);
+ MEM_COPY_ATTRIBUTES (new, op);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
return new;
@@ -1226,24 +1328,35 @@ operand_subword (op, i, validate_address, mode)
/* We handle 32-bit and >= 64-bit words here. Note that the order in
which the words are written depends on the word endianness.
-
??? This is a potential portability problem and should
- be fixed at some point. */
+ be fixed at some point.
+
+ We must excercise caution with the sign bit. By definition there
+ are 32 significant bits in K; there may be more in a HOST_WIDE_INT.
+ Consider a host with a 32-bit long and a 64-bit HOST_WIDE_INT.
+ So we explicitly mask and sign-extend as necessary. */
if (BITS_PER_WORD == 32)
- return GEN_INT ((HOST_WIDE_INT) k[i]);
-#if HOST_BITS_PER_WIDE_INT > 32
+ {
+ val = k[i];
+ val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ return GEN_INT (val);
+ }
+#if HOST_BITS_PER_WIDE_INT >= 64
else if (BITS_PER_WORD >= 64 && i == 0)
- return GEN_INT ((((HOST_WIDE_INT) k[! WORDS_BIG_ENDIAN]) << 32)
- | (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN]);
+ {
+ val = k[! WORDS_BIG_ENDIAN];
+ val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
+ val |= (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN] & 0xffffffff;
+ return GEN_INT (val);
+ }
#endif
else if (BITS_PER_WORD == 16)
{
- long value;
- value = k[i >> 1];
- if ((i & 0x1) == !WORDS_BIG_ENDIAN)
- value >>= 16;
- value &= 0xffff;
- return GEN_INT ((HOST_WIDE_INT) value);
+ val = k[i >> 1];
+ if ((i & 1) == !WORDS_BIG_ENDIAN)
+ val >>= 16;
+ val &= 0xffff;
+ return GEN_INT (val);
}
else
abort ();
@@ -1260,7 +1373,13 @@ operand_subword (op, i, validate_address, mode)
REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
if (BITS_PER_WORD == 32)
- return GEN_INT ((HOST_WIDE_INT) k[i]);
+ {
+ val = k[i];
+ val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ return GEN_INT (val);
+ }
+ else
+ abort ();
}
#else /* no REAL_ARITHMETIC */
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
@@ -1298,13 +1417,18 @@ operand_subword (op, i, validate_address, mode)
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+ /* Sign extend from known 32-bit value to HOST_WIDE_INT. */
+ val = l;
+ val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+
if (BITS_PER_WORD == 16)
{
- if ((i & 0x1) == !WORDS_BIG_ENDIAN)
- l >>= 16;
- l &= 0xffff;
+ if ((i & 1) == !WORDS_BIG_ENDIAN)
+ val >>= 16;
+ val &= 0xffff;
}
- return GEN_INT ((HOST_WIDE_INT) l);
+
+ return GEN_INT (val);
}
#else
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
@@ -1497,9 +1621,8 @@ change_address (memref, mode, addr)
return memref;
new = gen_rtx_MEM (mode, addr);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (memref);
+ MEM_COPY_ATTRIBUTES (new, memref);
return new;
}
@@ -2264,7 +2387,8 @@ try_split (pat, trial, last)
Ignore deleted insns, which can be occur if not optimizing. */
for (tem = NEXT_INSN (before); tem != after;
tem = NEXT_INSN (tem))
- if (! INSN_DELETED_P (tem))
+ if (! INSN_DELETED_P (tem)
+ && GET_RTX_CLASS (GET_CODE (tem)) == 'i')
tem = try_split (PATTERN (tem), tem, 1);
}
/* Avoid infinite loop if the result matches the original pattern. */
@@ -2468,6 +2592,64 @@ add_insn_before (insn, before)
PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn;
}
+/* Remove an insn from its doubly-linked list. This function knows how
+ to handle sequences. */
+void
+remove_insn (insn)
+ rtx insn;
+{
+ rtx next = NEXT_INSN (insn);
+ rtx prev = PREV_INSN (insn);
+ if (prev)
+ {
+ NEXT_INSN (prev) = next;
+ if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
+ {
+ rtx sequence = PATTERN (prev);
+ NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = next;
+ }
+ }
+ else if (first_insn == insn)
+ first_insn = next;
+ else
+ {
+ struct sequence_stack *stack = sequence_stack;
+ /* Scan all pending sequences too. */
+ for (; stack; stack = stack->next)
+ if (insn == stack->first)
+ {
+ stack->first = next;
+ break;
+ }
+
+ if (stack == 0)
+ abort ();
+ }
+
+ if (next)
+ {
+ PREV_INSN (next) = prev;
+ if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
+ PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev;
+ }
+ else if (last_insn == insn)
+ last_insn = prev;
+ else
+ {
+ struct sequence_stack *stack = sequence_stack;
+ /* Scan all pending sequences too. */
+ for (; stack; stack = stack->next)
+ if (insn == stack->last)
+ {
+ stack->last = prev;
+ break;
+ }
+
+ if (stack == 0)
+ abort ();
+ }
+}
+
/* Delete all insns made since FROM.
FROM becomes the new last instruction. */
@@ -2635,7 +2817,7 @@ emit_call_insn_before (pattern, before)
}
/* Make an insn of code BARRIER
- and output it before the insn AFTER. */
+ and output it before the insn BEFORE. */
rtx
emit_barrier_before (before)
@@ -2649,6 +2831,23 @@ emit_barrier_before (before)
return insn;
}
+/* Emit the label LABEL before the insn BEFORE. */
+
+rtx
+emit_label_before (label, before)
+ rtx label, before;
+{
+ /* This can be called twice for the same label as a result of the
+ confusion that follows a syntax error! So make it harmless. */
+ if (INSN_UID (label) == 0)
+ {
+ INSN_UID (label) = cur_insn_uid++;
+ add_insn_before (label, before);
+ }
+
+ return label;
+}
+
/* Emit a note of subtype SUBTYPE before the insn BEFORE. */
rtx
@@ -3038,7 +3237,7 @@ emit_note (file, line)
return note;
}
-/* Emit a NOTE, and don't omit it even if LINE it the previous note. */
+/* Emit a NOTE, and don't omit it even if LINE is the previous note. */
rtx
emit_line_note_force (file, line)
@@ -3057,6 +3256,24 @@ force_next_line_note ()
{
last_linenum = -1;
}
+
+/* Place a note of KIND on insn INSN with DATUM as the datum. If a
+ note of this type already exists, remove it first. */
+
+void
+set_unique_reg_note (insn, kind, datum)
+ rtx insn;
+ enum reg_note kind;
+ rtx datum;
+{
+ rtx note = find_reg_note (insn, kind, NULL_RTX);
+
+ /* First remove the note if there already is one. */
+ if (note)
+ remove_note (insn, note);
+
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn));
+}
/* Return an indication of which type of insn should have X as a body.
The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */
@@ -3122,7 +3339,13 @@ emit (x)
abort ();
}
-/* Begin emitting insns to a sequence which can be packaged in an RTL_EXPR. */
+/* Begin emitting insns to a sequence which can be packaged in an
+ RTL_EXPR. If this sequence will contain something that might cause
+ the compiler to pop arguments to function calls (because those
+ pops have previously been deferred; see INHIBIT_DEFER_POP for more
+ details), use do_pending_stack_adjust before calling this function.
+ That will ensure that the deferred pops are not accidentally
+ emitted in the middel of this sequence. */
void
start_sequence ()
@@ -3149,8 +3372,9 @@ start_sequence ()
last_insn = 0;
}
-/* Similarly, but indicate that this sequence will be placed in
- T, an RTL_EXPR. */
+/* Similarly, but indicate that this sequence will be placed in T, an
+ RTL_EXPR. See the documentation for start_sequence for more
+ information about how to use this function. */
void
start_sequence_for_rtl_expr (t)
@@ -3161,8 +3385,9 @@ start_sequence_for_rtl_expr (t)
sequence_rtl_expr = t;
}
-/* Set up the insn chain starting with FIRST
- as the current sequence, saving the previously current one. */
+/* Set up the insn chain starting with FIRST as the current sequence,
+ saving the previously current one. See the documentation for
+ start_sequence for more information about how to use this function. */
void
push_to_sequence (first)
@@ -3216,8 +3441,16 @@ pop_topmost_sequence ()
/* After emitting to a sequence, restore previous saved state.
- To get the contents of the sequence just made,
- you must call `gen_sequence' *before* calling here. */
+ To get the contents of the sequence just made, you must call
+ `gen_sequence' *before* calling here.
+
+ If the compiler might have deferred popping arguments while
+ generating this sequence, and this sequence will not be immediately
+ inserted into the instruction stream, use do_pending_stack_adjust
+ before calling gen_sequence. That will ensure that the deferred
+ pops are inserted into this sequence, and not into some random
+ location in the instruction stream. See INHIBIT_DEFER_POP for more
+ information about deferred popping of arguments. */
void
end_sequence ()
@@ -3296,6 +3529,18 @@ gen_sequence ()
return result;
}
+/* Put the various virtual registers into REGNO_REG_RTX. */
+
+void
+init_virtual_regs ()
+{
+ regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
+ regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
+ regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
+ regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
+ regno_reg_rtx[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx;
+}
+
/* Initialize data structures and variables in this file
before generating rtl for each function. */
@@ -3338,10 +3583,7 @@ init_emit ()
bzero ((char *) regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx));
/* Put copies of all the virtual register rtx into regno_reg_rtx. */
- regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
- regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
- regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
- regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
+ init_virtual_regs ();
/* Indicate that the virtual registers and stack locations are
all pointers. */
@@ -3354,6 +3596,7 @@ init_emit ()
REGNO_POINTER_FLAG (VIRTUAL_STACK_VARS_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_STACK_DYNAMIC_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_OUTGOING_ARGS_REGNUM) = 1;
+ REGNO_POINTER_FLAG (VIRTUAL_CFA_REGNUM) = 1;
#ifdef STACK_BOUNDARY
REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
@@ -3370,6 +3613,7 @@ init_emit ()
= STACK_BOUNDARY / BITS_PER_UNIT;
REGNO_POINTER_ALIGN (VIRTUAL_OUTGOING_ARGS_REGNUM)
= STACK_BOUNDARY / BITS_PER_UNIT;
+ REGNO_POINTER_ALIGN (VIRTUAL_CFA_REGNUM) = UNITS_PER_WORD;
#endif
#ifdef INIT_EXPANDERS
@@ -3504,6 +3748,8 @@ init_emit_once (line_numbers)
PUT_MODE (virtual_stack_dynamic_rtx, Pmode);
REGNO (virtual_outgoing_args_rtx) = VIRTUAL_OUTGOING_ARGS_REGNUM;
PUT_MODE (virtual_outgoing_args_rtx, Pmode);
+ REGNO (virtual_cfa_rtx) = VIRTUAL_CFA_REGNUM;
+ PUT_MODE (virtual_cfa_rtx, Pmode);
#ifdef RETURN_ADDRESS_POINTER_REGNUM
return_address_pointer_rtx
@@ -3551,6 +3797,14 @@ init_emit_once (line_numbers)
#ifdef PIC_OFFSET_TABLE_REGNUM
pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
#endif
+
+#ifdef INIT_EXPANDERS
+ /* This is to initialize save_machine_status and restore_machine_status before
+ the first call to push_function_context_to. This is needed by the Chill
+ front end which calls push_function_context_to before the first cal to
+ init_function_start. */
+ INIT_EXPANDERS;
+#endif
}
/* Query and clear/ restore no_line_numbers. This is used by the
diff --git a/contrib/gcc/except.c b/contrib/gcc/except.c
index ccd5a6b..f7d78d6 100644
--- a/contrib/gcc/except.c
+++ b/contrib/gcc/except.c
@@ -406,6 +406,8 @@ Boston, MA 02111-1307, USA. */
#include "recog.h"
#include "output.h"
#include "toplev.h"
+#include "intl.h"
+#include "obstack.h"
/* One to use setjmp/longjmp method of generating code for exception
handling. */
@@ -490,6 +492,29 @@ struct label_node *outer_context_label_stack = NULL;
struct label_node *false_label_stack = NULL;
+/* Pseudos used to hold exception return data in the interim between
+ __builtin_eh_return and the end of the function. */
+
+static rtx eh_return_context;
+static rtx eh_return_stack_adjust;
+static rtx eh_return_handler;
+
+/* Used to mark the eh return stub for flow, so that the Right Thing
+ happens with the values for the hardregs therin. */
+
+rtx eh_return_stub_label;
+
+/* This is used for targets which can call rethrow with an offset instead
+ of an address. This is subtracted from the rethrow label we are
+ interested in. */
+
+static rtx first_rethrow_symbol = NULL_RTX;
+static rtx final_rethrow = NULL_RTX;
+static rtx last_rethrow_symbol = NULL_RTX;
+
+
+/* Prototypes for local functions. */
+
static void push_eh_entry PROTO((struct eh_stack *));
static struct eh_entry * pop_eh_entry PROTO((struct eh_stack *));
static void enqueue_eh_entry PROTO((struct eh_queue *, struct eh_entry *));
@@ -501,18 +526,40 @@ static void expand_rethrow PROTO((rtx));
static void output_exception_table_entry PROTO((FILE *, int));
static int can_throw PROTO((rtx));
static rtx scan_region PROTO((rtx, int, int *));
-static void eh_regs PROTO((rtx *, rtx *, int));
+static void eh_regs PROTO((rtx *, rtx *, rtx *, int));
static void set_insn_eh_region PROTO((rtx *, int));
#ifdef DONT_USE_BUILTIN_SETJMP
static void jumpif_rtx PROTO((rtx, rtx));
#endif
-
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
/* Various support routines to manipulate the various data structures
used by the exception handling code. */
+extern struct obstack permanent_obstack;
+
+/* Generate a SYMBOL_REF for rethrow to use */
+static rtx
+create_rethrow_ref (region_num)
+ int region_num;
+{
+ rtx def;
+ char *ptr;
+ char buf[60];
+
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", region_num);
+ ptr = (char *) obstack_copy0 (&permanent_obstack, buf, strlen (buf));
+ def = gen_rtx_SYMBOL_REF (Pmode, ptr);
+ SYMBOL_REF_NEED_ADJUST (def) = 1;
+
+ pop_obstacks ();
+ return def;
+}
+
/* Push a label entry onto the given STACK. */
void
@@ -570,11 +617,7 @@ rtx
gen_exception_label ()
{
rtx lab;
-
- push_obstacks_nochange ();
- end_temporary_allocation ();
lab = gen_label_rtx ();
- pop_obstacks ();
return lab;
}
@@ -587,10 +630,16 @@ push_eh_entry (stack)
struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
struct eh_entry *entry = (struct eh_entry *) xmalloc (sizeof (struct eh_entry));
- entry->outer_context = gen_label_rtx ();
+ rtx rlab = gen_exception_label ();
entry->finalization = NULL_TREE;
entry->label_used = 0;
- entry->exception_handler_label = gen_exception_label ();
+ entry->exception_handler_label = rlab;
+ entry->false_label = NULL_RTX;
+ if (! flag_new_exceptions)
+ entry->outer_context = gen_label_rtx ();
+ else
+ entry->outer_context = create_rethrow_ref (CODE_LABEL_NUMBER (rlab));
+ entry->rethrow_label = entry->outer_context;
node->entry = entry;
node->chain = stack->top;
@@ -693,6 +742,7 @@ receive_exception_label (handler_label)
struct func_eh_entry
{
int range_number; /* EH region number from EH NOTE insn's */
+ rtx rethrow_label; /* Label for rethrow */
struct handler_info *handlers;
};
@@ -705,12 +755,14 @@ static int current_func_eh_entry = 0;
#define SIZE_FUNC_EH(X) (sizeof (struct func_eh_entry) * X)
/* Add a new eh_entry for this function, and base it off of the information
- in the EH_ENTRY parameter. A NULL parameter is invalid. The number
+ in the EH_ENTRY parameter. A NULL parameter is invalid.
+ OUTER_CONTEXT is a label which is used for rethrowing. The number
returned is an number which uniquely identifies this exception range. */
-int
-new_eh_region_entry (note_eh_region)
+static int
+new_eh_region_entry (note_eh_region, rethrow)
int note_eh_region;
+ rtx rethrow;
{
if (current_func_eh_entry == num_func_eh_entries)
{
@@ -728,6 +780,11 @@ new_eh_region_entry (note_eh_region)
}
}
function_eh_regions[current_func_eh_entry].range_number = note_eh_region;
+ if (rethrow == NULL_RTX)
+ function_eh_regions[current_func_eh_entry].rethrow_label =
+ create_rethrow_ref (note_eh_region);
+ else
+ function_eh_regions[current_func_eh_entry].rethrow_label = rethrow;
function_eh_regions[current_func_eh_entry].handlers = NULL;
return current_func_eh_entry++;
@@ -753,8 +810,13 @@ add_new_handler (region, newhandler)
function_eh_regions[region].handlers = newhandler;
else
{
- for ( ; last->next != NULL; last = last->next)
- ;
+ for ( ; ; last = last->next)
+ {
+ if (last->type_info == CATCH_ALL_TYPE)
+ pedwarn ("additional handler after ...");
+ if (last->next == NULL)
+ break;
+ }
last->next = newhandler;
}
}
@@ -859,6 +921,7 @@ get_new_handler (handler, typeinfo)
struct handler_info* ptr;
ptr = (struct handler_info *) malloc (sizeof (struct handler_info));
ptr->handler_label = handler;
+ ptr->handler_number = CODE_LABEL_NUMBER (handler);
ptr->type_info = typeinfo;
ptr->next = NULL;
@@ -910,34 +973,97 @@ clear_function_eh_region ()
}
/* Make a duplicate of an exception region by copying all the handlers
- for an exception region. Return the new handler index. */
+ for an exception region. Return the new handler index. The final
+ parameter is a routine which maps old labels to new ones. */
int
-duplicate_handlers (old_note_eh_region, new_note_eh_region)
+duplicate_eh_handlers (old_note_eh_region, new_note_eh_region, map)
int old_note_eh_region, new_note_eh_region;
+ rtx (*map) PARAMS ((rtx));
{
struct handler_info *ptr, *new_ptr;
int new_region, region;
region = find_func_region (old_note_eh_region);
if (region == -1)
- error ("Cannot duplicate non-existant exception region.");
+ fatal ("Cannot duplicate non-existant exception region.");
+
+ /* duplicate_eh_handlers may have been called during a symbol remap. */
+ new_region = find_func_region (new_note_eh_region);
+ if (new_region != -1)
+ return (new_region);
- if (find_func_region (new_note_eh_region) != -1)
- error ("Cannot duplicate EH region because new note region already exists");
+ new_region = new_eh_region_entry (new_note_eh_region, NULL_RTX);
- new_region = new_eh_region_entry (new_note_eh_region);
ptr = function_eh_regions[region].handlers;
for ( ; ptr; ptr = ptr->next)
{
- new_ptr = get_new_handler (ptr->handler_label, ptr->type_info);
+ new_ptr = get_new_handler (map (ptr->handler_label), ptr->type_info);
add_new_handler (new_region, new_ptr);
}
return new_region;
}
+
+/* Given a rethrow symbol, find the EH region number this is for. */
+int
+eh_region_from_symbol (sym)
+ rtx sym;
+{
+ int x;
+ if (sym == last_rethrow_symbol)
+ return 1;
+ for (x = 0; x < current_func_eh_entry; x++)
+ if (function_eh_regions[x].rethrow_label == sym)
+ return function_eh_regions[x].range_number;
+ return -1;
+}
+
+
+/* When inlining/unrolling, we have to map the symbols passed to
+ __rethrow as well. This performs the remap. If a symbol isn't foiund,
+ the original one is returned. This is not an efficient routine,
+ so don't call it on everything!! */
+rtx
+rethrow_symbol_map (sym, map)
+ rtx sym;
+ rtx (*map) PARAMS ((rtx));
+{
+ int x, y;
+ for (x = 0; x < current_func_eh_entry; x++)
+ if (function_eh_regions[x].rethrow_label == sym)
+ {
+ /* We've found the original region, now lets determine which region
+ this now maps to. */
+ rtx l1 = function_eh_regions[x].handlers->handler_label;
+ rtx l2 = map (l1);
+ y = CODE_LABEL_NUMBER (l2); /* This is the new region number */
+ x = find_func_region (y); /* Get the new permanent region */
+ if (x == -1) /* Hmm, Doesn't exist yet */
+ {
+ x = duplicate_eh_handlers (CODE_LABEL_NUMBER (l1), y, map);
+ /* Since we're mapping it, it must be used. */
+ SYMBOL_REF_USED (function_eh_regions[x].rethrow_label) = 1;
+ }
+ return function_eh_regions[x].rethrow_label;
+ }
+ return sym;
+}
+
+int
+rethrow_used (region)
+ int region;
+{
+ if (flag_new_exceptions)
+ {
+ rtx lab = function_eh_regions[find_func_region (region)].rethrow_label;
+ return (SYMBOL_REF_USED (lab));
+ }
+ return 0;
+}
+
/* Routine to see if exception handling is turned on.
DO_WARN is non-zero if we want to inform the user that exception
@@ -1252,7 +1378,7 @@ start_dynamic_handler ()
/* We are committed to this, so update the handler chain. */
- emit_move_insn (dhc, XEXP (arg, 0));
+ emit_move_insn (dhc, force_operand (XEXP (arg, 0), NULL_RTX));
}
/* Start an exception handling region for the given cleanup action.
@@ -1391,6 +1517,7 @@ expand_eh_region_end (handler)
{
struct eh_entry *entry;
rtx note;
+ int ret, r;
if (! doing_eh (0))
return;
@@ -1398,9 +1525,9 @@ expand_eh_region_end (handler)
entry = pop_eh_entry (&ehstack);
note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_END);
- NOTE_BLOCK_NUMBER (note)
+ ret = NOTE_BLOCK_NUMBER (note)
= CODE_LABEL_NUMBER (entry->exception_handler_label);
- if (exceptions_via_longjmp == 0
+ if (exceptions_via_longjmp == 0 && ! flag_new_exceptions
/* We share outer_context between regions; only emit it once. */
&& INSN_UID (entry->outer_context) == 0)
{
@@ -1420,7 +1547,7 @@ expand_eh_region_end (handler)
entry->finalization = handler;
/* create region entry in final exception table */
- new_eh_region_entry (NOTE_BLOCK_NUMBER (note));
+ r = new_eh_region_entry (NOTE_BLOCK_NUMBER (note), entry->rethrow_label);
enqueue_eh_entry (&ehqueue, entry);
@@ -1616,6 +1743,62 @@ start_catch_handler (rtime)
receive_exception_label (handler_label);
add_new_handler (eh_region_entry, get_new_handler (handler_label, rtime));
+
+ if (flag_new_exceptions && ! exceptions_via_longjmp)
+ return;
+
+ /* Under the old mechanism, as well as setjmp/longjmp, we need to
+ issue code to compare 'rtime' to the value in eh_info, via the
+ matching function in eh_info. If its is false, we branch around
+ the handler we are about to issue. */
+
+ if (rtime != NULL_TREE && rtime != CATCH_ALL_TYPE)
+ {
+ rtx call_rtx, rtime_address;
+
+ if (catchstack.top->entry->false_label != NULL_RTX)
+ fatal ("Compiler Bug: Never issued previous false_label");
+ catchstack.top->entry->false_label = gen_exception_label ();
+
+ rtime_address = expand_expr (rtime, NULL_RTX, Pmode, EXPAND_INITIALIZER);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ rtime_address = convert_memory_address (Pmode, rtime_address);
+#endif
+ rtime_address = force_reg (Pmode, rtime_address);
+
+ /* Now issue the call, and branch around handler if needed */
+ call_rtx = emit_library_call_value (eh_rtime_match_libfunc, NULL_RTX,
+ 0, SImode, 1, rtime_address, Pmode);
+
+ /* Did the function return true? */
+ emit_cmp_and_jump_insns (call_rtx, const0_rtx, EQ, NULL_RTX,
+ GET_MODE (call_rtx), 0, 0,
+ catchstack.top->entry->false_label);
+ }
+}
+
+/* Called to end a catch clause. If we aren't using the new exception
+ model tabel mechanism, we need to issue the branch-around label
+ for the end of the catch block. */
+
+void
+end_catch_handler ()
+{
+ if (! doing_eh (1))
+ return;
+
+ if (flag_new_exceptions && ! exceptions_via_longjmp)
+ {
+ emit_barrier ();
+ return;
+ }
+
+ /* A NULL label implies the catch clause was a catch all or cleanup */
+ if (catchstack.top->entry->false_label == NULL_RTX)
+ return;
+
+ emit_label (catchstack.top->entry->false_label);
+ catchstack.top->entry->false_label = NULL_RTX;
}
/* Generate RTL for the start of a group of catch clauses.
@@ -1709,9 +1892,6 @@ expand_start_all_catch ()
ehstack.top->entry->outer_context = outer_context;
}
- /* We also have to start the handler if we aren't using the new model. */
- if (! flag_new_exceptions)
- start_catch_handler (NULL);
}
/* Finish up the catch block. At this point all the insns for the
@@ -1723,7 +1903,7 @@ expand_start_all_catch ()
void
expand_end_all_catch ()
{
- rtx new_catch_clause, outer_context = NULL_RTX;
+ rtx new_catch_clause;
struct eh_entry *entry;
if (! doing_eh (1))
@@ -1735,11 +1915,17 @@ expand_end_all_catch ()
if (! exceptions_via_longjmp)
{
- outer_context = ehstack.top->entry->outer_context;
+ rtx outer_context = ehstack.top->entry->outer_context;
/* Finish the rethrow region. size_zero_node is just a NOP. */
expand_eh_region_end (size_zero_node);
+ /* New exceptions handling models will never have a fall through
+ of a catch clause */
+ if (!flag_new_exceptions)
+ expand_rethrow (outer_context);
}
+ else
+ expand_rethrow (NULL_RTX);
/* Code to throw out to outer context, if we fall off end of catch
handlers. This is rethrow (Lresume, same id, same obj) in the
@@ -1750,7 +1936,6 @@ expand_end_all_catch ()
do a "throw" (using the address of Lresume as the point being
thrown from) so that the outer EH region can then try to process
the exception. */
- expand_rethrow (outer_context);
/* Now we have the complete catch sequence. */
new_catch_clause = get_insns ();
@@ -1779,7 +1964,28 @@ expand_rethrow (label)
if (exceptions_via_longjmp)
emit_throw ();
else
- emit_jump (label);
+ if (flag_new_exceptions)
+ {
+ rtx insn, val;
+ if (label == NULL_RTX)
+ label = last_rethrow_symbol;
+ emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
+ SYMBOL_REF_USED (label) = 1;
+
+ /* Search backwards for the actual call insn. */
+ insn = get_last_insn ();
+ while (GET_CODE (insn) != CALL_INSN)
+ insn = PREV_INSN (insn);
+ delete_insns_since (insn);
+
+ /* Mark the label/symbol on the call. */
+ val = GEN_INT (eh_region_from_symbol (label));
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_RETHROW, val,
+ REG_NOTES (insn));
+ emit_barrier ();
+ }
+ else
+ emit_jump (label);
}
/* End all the pending exception regions on protect_list. The handlers
@@ -1913,12 +2119,29 @@ output_exception_table_entry (file, n)
{
char buf[256];
rtx sym;
- struct handler_info *handler;
+ struct handler_info *handler = get_first_handler (n);
+ int index = find_func_region (n);
+ rtx rethrow;
+
+ /* form and emit the rethrow label, if needed */
+ rethrow = function_eh_regions[index].rethrow_label;
+ if (rethrow != NULL_RTX && !flag_new_exceptions)
+ rethrow = NULL_RTX;
+ if (rethrow != NULL_RTX && handler == NULL)
+ if (! SYMBOL_REF_USED (rethrow))
+ rethrow = NULL_RTX;
- handler = get_first_handler (n);
- for ( ; handler != NULL; handler = handler->next)
+ for ( ; handler != NULL || rethrow != NULL_RTX; handler = handler->next)
{
+ /* rethrow label should indicate the LAST entry for a region */
+ if (rethrow != NULL_RTX && (handler == NULL || handler->next == NULL))
+ {
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", n);
+ assemble_label(buf);
+ rethrow = NULL_RTX;
+ }
+
ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", n);
sym = gen_rtx_SYMBOL_REF (Pmode, buf);
assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
@@ -1927,12 +2150,18 @@ output_exception_table_entry (file, n)
sym = gen_rtx_SYMBOL_REF (Pmode, buf);
assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
- assemble_integer (handler->handler_label,
- POINTER_SIZE / BITS_PER_UNIT, 1);
+ if (handler == NULL)
+ assemble_integer (GEN_INT (0), POINTER_SIZE / BITS_PER_UNIT, 1);
+ else
+ {
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", handler->handler_number);
+ sym = gen_rtx_SYMBOL_REF (Pmode, buf);
+ assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
+ }
if (flag_new_exceptions)
{
- if (handler->type_info == NULL)
+ if (handler == NULL || handler->type_info == NULL)
assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
else
if (handler->type_info == CATCH_ALL_TYPE)
@@ -1943,6 +2172,9 @@ output_exception_table_entry (file, n)
POINTER_SIZE / BITS_PER_UNIT);
}
putc ('\n', file); /* blank line */
+ /* We only output the first label under the old scheme */
+ if (! flag_new_exceptions || handler == NULL)
+ break;
}
}
@@ -1952,15 +2184,17 @@ static short language_code = 0;
static short version_code = 0;
/* This routine will set the language code for exceptions. */
-void set_exception_lang_code (code)
- short code;
+void
+set_exception_lang_code (code)
+ int code;
{
language_code = code;
}
/* This routine will set the language version code for exceptions. */
-void set_exception_version_code (code)
- short code;
+void
+set_exception_version_code (code)
+ int code;
{
version_code = code;
}
@@ -1970,6 +2204,7 @@ void
output_exception_table ()
{
int i;
+ char buf[256];
extern FILE *asm_out_file;
if (! doing_eh (0) || ! eh_table)
@@ -1994,6 +2229,10 @@ output_exception_table ()
;
if (i != 0)
assemble_integer (const0_rtx, i , 1);
+
+ /* Generate the label for offset calculations on rethrows */
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", 0);
+ assemble_label(buf);
}
for (i = 0; i < eh_table_size; ++i)
@@ -2003,6 +2242,9 @@ output_exception_table ()
clear_function_eh_region ();
/* Ending marker for table. */
+ /* Generate the label for end of table. */
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", CODE_LABEL_NUMBER (final_rethrow));
+ assemble_label(buf);
assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
/* for binary compatability, the old __throw checked the second
@@ -2053,6 +2295,14 @@ emit_eh_context ()
end_sequence ();
emit_insns_before (insns, insn);
+
+ /* At -O0, we must make the context register stay alive so
+ that the stupid.c register allocator doesn't get confused. */
+ if (obey_regdecls != 0)
+ {
+ insns = gen_rtx_USE (GET_MODE (XEXP (reg,0)), XEXP (reg,0));
+ emit_insn_before (insns, get_last_insn ());
+ }
}
}
}
@@ -2153,6 +2403,9 @@ check_exception_handler_labels ()
void
init_eh ()
{
+ first_rethrow_symbol = create_rethrow_ref (0);
+ final_rethrow = gen_exception_label ();
+ last_rethrow_symbol = create_rethrow_ref (CODE_LABEL_NUMBER (final_rethrow));
}
/* Initialize the per-function EH information. */
@@ -2168,6 +2421,10 @@ init_eh_for_function ()
caught_return_label_stack = 0;
protect_list = NULL_TREE;
current_function_ehc = NULL_RTX;
+ eh_return_context = NULL_RTX;
+ eh_return_stack_adjust = NULL_RTX;
+ eh_return_handler = NULL_RTX;
+ eh_return_stub_label = NULL_RTX;
}
/* Save some of the per-function EH info into the save area denoted by
@@ -2190,6 +2447,7 @@ save_eh_status (p)
p->caught_return_label_stack = caught_return_label_stack;
p->protect_list = protect_list;
p->ehc = current_function_ehc;
+ p->eh_return_stub_label = eh_return_stub_label;
init_eh_for_function ();
}
@@ -2213,6 +2471,7 @@ restore_eh_status (p)
ehstack = p->ehstack;
catchstack = p->catchstack;
current_function_ehc = p->ehc;
+ eh_return_stub_label = p->eh_return_stub_label;
}
/* This section is for the exception handling specific optimization
@@ -2268,6 +2527,11 @@ scan_region (insn, n, delete_outer)
/* Assume we can delete the region. */
int delete = 1;
+ int r = find_func_region (n);
+ /* Can't delete something which is rethrown to. */
+ if (SYMBOL_REF_USED((function_eh_regions[r].rethrow_label)))
+ delete = 0;
+
if (insn == NULL_RTX
|| GET_CODE (insn) != NOTE
|| NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
@@ -2424,79 +2688,72 @@ expand_builtin_frob_return_addr (addr_tree)
return addr;
}
-/* Given an actual address in addr_tree, set the return address register up
- so the epilogue will return to that address. If the return address is
- not in a register, do nothing. */
-
-void
-expand_builtin_set_return_addr_reg (addr_tree)
- tree addr_tree;
-{
- rtx tmp;
- rtx ra = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
- 0, hard_frame_pointer_rtx);
-
- if (GET_CODE (ra) != REG || REGNO (ra) >= FIRST_PSEUDO_REGISTER)
- return;
+/* Choose three registers for communication between the main body of
+ __throw and the epilogue (or eh stub) and the exception handler.
+ We must do this with hard registers because the epilogue itself
+ will be generated after reload, at which point we may not reference
+ pseudos at all.
- tmp = force_operand (expand_builtin_frob_return_addr (addr_tree), ra);
- if (tmp != ra)
- emit_move_insn (ra, tmp);
-}
+ The first passes the exception context to the handler. For this
+ we use the return value register for a void*.
-/* Choose two registers for communication between the main body of
- __throw and the stub for adjusting the stack pointer. The first register
- is used to pass the address of the exception handler; the second register
- is used to pass the stack pointer offset.
+ The second holds the stack pointer value to be restored. For
+ this we use the static chain register if it exists and is different
+ from the previous, otherwise some arbitrary call-clobbered register.
- For register 1 we use the return value register for a void *.
- For register 2 we use the static chain register if it exists and is
- different from register 1, otherwise some arbitrary call-clobbered
- register. */
+ The third holds the address of the handler itself. Here we use
+ some arbitrary call-clobbered register. */
static void
-eh_regs (r1, r2, outgoing)
- rtx *r1, *r2;
+eh_regs (pcontext, psp, pra, outgoing)
+ rtx *pcontext, *psp, *pra;
int outgoing;
{
- rtx reg1, reg2;
+ rtx rcontext, rsp, rra;
+ int i;
#ifdef FUNCTION_OUTGOING_VALUE
if (outgoing)
- reg1 = FUNCTION_OUTGOING_VALUE (build_pointer_type (void_type_node),
- current_function_decl);
+ rcontext = FUNCTION_OUTGOING_VALUE (build_pointer_type (void_type_node),
+ current_function_decl);
else
#endif
- reg1 = FUNCTION_VALUE (build_pointer_type (void_type_node),
- current_function_decl);
+ rcontext = FUNCTION_VALUE (build_pointer_type (void_type_node),
+ current_function_decl);
#ifdef STATIC_CHAIN_REGNUM
if (outgoing)
- reg2 = static_chain_incoming_rtx;
+ rsp = static_chain_incoming_rtx;
else
- reg2 = static_chain_rtx;
- if (REGNO (reg2) == REGNO (reg1))
+ rsp = static_chain_rtx;
+ if (REGNO (rsp) == REGNO (rcontext))
#endif /* STATIC_CHAIN_REGNUM */
- reg2 = NULL_RTX;
+ rsp = NULL_RTX;
- if (reg2 == NULL_RTX)
+ if (rsp == NULL_RTX)
{
- int i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
- if (call_used_regs[i] && ! fixed_regs[i] && i != REGNO (reg1))
- {
- reg2 = gen_rtx_REG (Pmode, i);
- break;
- }
+ if (call_used_regs[i] && ! fixed_regs[i] && i != REGNO (rcontext))
+ break;
+ if (i == FIRST_PSEUDO_REGISTER)
+ abort();
- if (reg2 == NULL_RTX)
- abort ();
+ rsp = gen_rtx_REG (Pmode, i);
}
- *r1 = reg1;
- *r2 = reg2;
-}
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (call_used_regs[i] && ! fixed_regs[i]
+ && i != REGNO (rcontext) && i != REGNO (rsp))
+ break;
+ if (i == FIRST_PSEUDO_REGISTER)
+ abort();
+
+ rra = gen_rtx_REG (Pmode, i);
+ *pcontext = rcontext;
+ *psp = rsp;
+ *pra = rra;
+}
/* Retrieve the register which contains the pointer to the eh_context
structure set the __throw. */
@@ -2510,79 +2767,95 @@ get_reg_for_handler ()
return reg1;
}
+/* Set up the epilogue with the magic bits we'll need to return to the
+ exception handler. */
-/* Emit inside of __throw a stub which adjusts the stack pointer and jumps
- to the exception handler. __throw will set up the necessary values
- and then return to the stub. */
-
-rtx
-expand_builtin_eh_stub_old ()
+void
+expand_builtin_eh_return (context, stack, handler)
+ tree context, stack, handler;
{
- rtx stub_start = gen_label_rtx ();
- rtx after_stub = gen_label_rtx ();
- rtx handler, offset;
-
- emit_jump (after_stub);
- emit_label (stub_start);
-
- eh_regs (&handler, &offset, 0);
+ if (eh_return_context)
+ error("Duplicate call to __builtin_eh_return");
- adjust_stack (offset);
- emit_indirect_jump (handler);
- emit_label (after_stub);
- return gen_rtx_LABEL_REF (Pmode, stub_start);
+ eh_return_context
+ = copy_to_reg (expand_expr (context, NULL_RTX, VOIDmode, 0));
+ eh_return_stack_adjust
+ = copy_to_reg (expand_expr (stack, NULL_RTX, VOIDmode, 0));
+ eh_return_handler
+ = copy_to_reg (expand_expr (handler, NULL_RTX, VOIDmode, 0));
}
-rtx
-expand_builtin_eh_stub ()
+void
+expand_eh_return ()
{
- rtx stub_start = gen_label_rtx ();
- rtx after_stub = gen_label_rtx ();
- rtx handler, offset;
- rtx temp;
+ rtx reg1, reg2, reg3;
+ rtx stub_start, after_stub;
+ rtx ra, tmp;
- emit_jump (after_stub);
- emit_label (stub_start);
+ if (!eh_return_context)
+ return;
- eh_regs (&handler, &offset, 0);
+ current_function_cannot_inline = N_("function uses __builtin_eh_return");
- adjust_stack (offset);
+ eh_regs (&reg1, &reg2, &reg3, 1);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ eh_return_context = convert_memory_address (Pmode, eh_return_context);
+ eh_return_stack_adjust =
+ convert_memory_address (Pmode, eh_return_stack_adjust);
+ eh_return_handler = convert_memory_address (Pmode, eh_return_handler);
+#endif
+ emit_move_insn (reg1, eh_return_context);
+ emit_move_insn (reg2, eh_return_stack_adjust);
+ emit_move_insn (reg3, eh_return_handler);
- /* Handler is in fact a pointer to the _eh_context structure, we need
- to pick out the handler field (first element), and jump to there,
- leaving the pointer to _eh_conext in the same hardware register. */
+ /* Talk directly to the target's epilogue code when possible. */
- temp = gen_rtx_MEM (Pmode, handler);
- MEM_IN_STRUCT_P (temp) = 1;
- RTX_UNCHANGING_P (temp) = 1;
- emit_move_insn (offset, temp);
- emit_insn (gen_rtx_USE (Pmode, handler));
+#ifdef HAVE_eh_epilogue
+ if (HAVE_eh_epilogue)
+ {
+ emit_insn (gen_eh_epilogue (reg1, reg2, reg3));
+ return;
+ }
+#endif
- emit_indirect_jump (offset);
-
- emit_label (after_stub);
- return gen_rtx_LABEL_REF (Pmode, stub_start);
-}
+ /* Otherwise, use the same stub technique we had before. */
-/* Set up the registers for passing the handler address and stack offset
- to the stub above. */
+ eh_return_stub_label = stub_start = gen_label_rtx ();
+ after_stub = gen_label_rtx ();
-void
-expand_builtin_set_eh_regs (handler, offset)
- tree handler, offset;
-{
- rtx reg1, reg2;
+ /* Set the return address to the stub label. */
- eh_regs (&reg1, &reg2, 1);
+ ra = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+ 0, hard_frame_pointer_rtx);
+ if (GET_CODE (ra) == REG && REGNO (ra) >= FIRST_PSEUDO_REGISTER)
+ abort();
- store_expr (offset, reg2, 0);
- store_expr (handler, reg1, 0);
+ tmp = memory_address (Pmode, gen_rtx_LABEL_REF (Pmode, stub_start));
+#ifdef RETURN_ADDR_OFFSET
+ tmp = plus_constant (tmp, -RETURN_ADDR_OFFSET);
+#endif
+ tmp = force_operand (tmp, ra);
+ if (tmp != ra)
+ emit_move_insn (ra, tmp);
- /* These will be used by the stub. */
+ /* Indicate that the registers are in fact used. */
emit_insn (gen_rtx_USE (VOIDmode, reg1));
emit_insn (gen_rtx_USE (VOIDmode, reg2));
-}
+ emit_insn (gen_rtx_USE (VOIDmode, reg3));
+ if (GET_CODE (ra) == REG)
+ emit_insn (gen_rtx_USE (VOIDmode, ra));
+
+ /* Generate the stub. */
+
+ emit_jump (after_stub);
+ emit_label (stub_start);
+
+ eh_regs (&reg1, &reg2, &reg3, 0);
+ adjust_stack (reg2);
+ emit_indirect_jump (reg3);
+ emit_label (after_stub);
+}
/* This contains the code required to verify whether arbitrary instructions
diff --git a/contrib/gcc/except.h b/contrib/gcc/except.h
index c08d0c5..a8c4f9c 100644
--- a/contrib/gcc/except.h
+++ b/contrib/gcc/except.h
@@ -1,5 +1,5 @@
/* Exception Handling interface routines.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Mike Stump <mrs@cygnus.com>.
This file is part of GNU CC.
@@ -24,6 +24,10 @@ typedef struct rtx_def *_except_rtx;
#define rtx _except_rtx
#endif
+/* The label generated by expand_builtin_eh_return. */
+
+extern rtx eh_return_stub_label;
+
#ifdef TREE_CODE
/* A stack of labels. CHAIN points to the next entry in the stack. */
@@ -47,6 +51,10 @@ struct label_node {
label or not. New ones are needed for additional catch blocks if
it has.
+ FALSE_LABEL is used when either setjmp/longjmp exceptions are in
+ use, or old style table exceptions. It contains the label for
+ branching to the next runtime type check as handlers are processed.
+
FINALIZATION is the tree codes for the handler, or is NULL_TREE if
one hasn't been generated yet, or is integer_zero_node to mark the
end of a group of try blocks. */
@@ -56,6 +64,8 @@ struct eh_entry {
rtx exception_handler_label;
tree finalization;
int label_used;
+ rtx false_label;
+ rtx rethrow_label;
};
/* A list of EH_ENTRYs. ENTRY is the entry; CHAIN points to the next
@@ -82,7 +92,6 @@ struct eh_queue {
struct eh_node *tail;
};
-
/* Start an exception handling region. All instructions emitted after
this point are considered to be part of the region until
expand_eh_region_end () is invoked. */
@@ -149,8 +158,8 @@ extern int doing_eh PROTO ((int));
/* Toplevel initialization for EH. */
-void set_exception_lang_code PROTO((short));
-void set_exception_version_code PROTO((short));
+void set_exception_lang_code PROTO((int));
+void set_exception_version_code PROTO((int));
/* A list of handlers asocciated with an exception region. HANDLER_LABEL
is the the label that control should be transfered to if the data
@@ -163,19 +172,13 @@ void set_exception_version_code PROTO((short));
typedef struct handler_info
{
- rtx handler_label;
+ rtx handler_label;
+ int handler_number;
void *type_info;
struct handler_info *next;
} handler_info;
-/* Add a new eh_entry for this function, The parameter specifies what
- exception region number NOTE insns use to delimit this range.
- The integer returned is uniquely identifies this exception range
- within an internal table. */
-
-int new_eh_region_entry PROTO((int));
-
/* Add new handler information to an exception range. The first parameter
specifies the range number (returned from new_eh_entry()). The second
parameter specifies the handler. By default the handler is inserted at
@@ -200,8 +203,19 @@ struct handler_info *get_new_handler PROTO((rtx, void *));
/* Make a duplicate of an exception region by copying all the handlers
for an exception region. Return the new handler index. */
-int duplicate_handlers PROTO((int, int));
+int duplicate_eh_handlers PROTO((int, int, rtx (*)(rtx)));
+
+/* map symbol refs for rethrow */
+rtx rethrow_symbol_map PROTO((rtx, rtx (*)(rtx)));
+
+/* Is the rethrow label for a region used? */
+
+int rethrow_used PROTO((int));
+
+/* Return the region number a this is the rethrow label for. */
+
+int eh_region_from_symbol PROTO((rtx));
/* Get a pointer to the first handler in an exception region's list. */
@@ -232,6 +246,10 @@ extern void add_eh_table_entry PROTO((int n));
extern void start_catch_handler PROTO((tree));
#endif
+/* End an individual catch clause. */
+
+extern void end_catch_handler PROTO((void));
+
/* Returns a non-zero value if we need to output an exception table. */
extern int exception_table_p PROTO((void));
@@ -363,15 +381,13 @@ extern void expand_fixup_region_end PROTO((tree));
void expand_builtin_unwind_init PROTO((void));
rtx expand_builtin_dwarf_fp_regnum PROTO((void));
-rtx expand_builtin_eh_stub PROTO((void));
-rtx expand_builtin_eh_stub_old PROTO((void));
#ifdef TREE_CODE
rtx expand_builtin_frob_return_addr PROTO((tree));
rtx expand_builtin_extract_return_addr PROTO((tree));
-void expand_builtin_set_return_addr_reg PROTO((tree));
-void expand_builtin_set_eh_regs PROTO((tree, tree));
rtx expand_builtin_dwarf_reg_size PROTO((tree, rtx));
+void expand_builtin_eh_return PROTO((tree, tree, tree));
#endif
+void expand_eh_return PROTO((void));
/* Checking whether 2 instructions are within the same exception region. */
diff --git a/contrib/gcc/exgettext b/contrib/gcc/exgettext
new file mode 100755
index 0000000..93d553c
--- /dev/null
+++ b/contrib/gcc/exgettext
@@ -0,0 +1,118 @@
+#! /bin/sh
+# Wrapper around gettext for GCC sources.
+# Copyright 1998 Free Software Foundation, Inc.
+
+# Written by Paul Eggert <eggert@twinsun.com>.
+
+# This file is part of GNU CC.
+
+# GNU CC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# GNU CC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNU CC; see the file COPYING. If not, write to
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# Set environment to default value, if not already set.
+: ${AWK=awk}
+
+# The argument to this wrapper is the xgettext command to be executed.
+# Extract the xgettext program name from the rest of the command.
+xgettext=${1?}
+shift
+
+# Save work if we're just wrapping a no-op.
+case $xgettext in
+:) exit;;
+esac
+
+# Find the files to be scanned, and the directory to scan them from.
+directory=.
+files=
+for i
+do
+ case $i in
+ --directory=*)
+ directory=`expr " $i" : ' --directory=\(.*\)'`;;
+ --files-from=*)
+ files_from=`expr " $i" : ' --files-from=\(.*\)'`
+ files=`$AWK '/^[^#]/ { print }' $files_from`;;
+ esac
+done
+
+# Generate keyword options for xgettext,
+# by scanning for declarations of functions
+# whose parameter names end in "msgid".
+generate_keyword_options='
+ /^[A-Z_a-z].*\(.*msgid[,)]/ {
+
+ paren_index = index($0, "(")
+
+ name = substr($0, 1, paren_index - 1)
+ sub(/[^0-9A-Z_a-z]*$/, "", name)
+ sub(/[ ]+PARAMS/, "", name)
+ sub(/[ ]+VPROTO/, "", name)
+ sub(/.*[^0-9A-Z_a-z]/, "", name)
+
+ args = substr($0, paren_index)
+ sub(/msgid[,)].*/, "", args)
+ for (n = 1; sub(/^[^,]*,/, "", args); n++) {
+ continue;
+ }
+
+ if (n == 1) {
+ keyword = name
+ } else {
+ keyword = name ":" n
+ }
+
+ if (! keyword_seen[keyword]++) {
+ print "--keyword=" keyword
+ }
+ }
+'
+keyword_options=`(
+ cd $directory &&
+ $AWK "$generate_keyword_options" $files < /dev/null
+)` || exit
+
+# Generate temporary file reflecting the %e strings in the scanned files.
+tmp=tmp-emsgids.c
+
+generate_emsgids='
+ /%e.*}/ {
+ line = $0
+ while ((percent_index = index(line, "%e")) != 0) {
+ line = substr(line, percent_index + 2)
+ bracket_index = index(line, "}")
+ if (bracket_index == 0) {
+ continue
+ }
+ msgid = substr(line, 1, bracket_index - 1)
+ if (index(msgid, "%") != 0) {
+ continue
+ }
+ printf "#line %d \"%s\"\n", FNR, FILENAME
+ printf "_(\"%s\")\n", msgid
+ line = substr(line, bracket_index + 1)
+ }
+ }
+'
+(cd $directory &&
+ $AWK "$generate_emsgids" $files < /dev/null
+) > $directory/$tmp || exit
+
+# Run the xgettext command, with temporary added as a file to scan.
+"$xgettext" $keyword_options ${1+"$@"} $tmp || exit
+
+# Clean up.
+# If we don't get here, `make clean' will remove this file later.
+rm -f $directory/$tmp
diff --git a/contrib/gcc/explow.c b/contrib/gcc/explow.c
index fc7ebf2..f06d992 100644
--- a/contrib/gcc/explow.c
+++ b/contrib/gcc/explow.c
@@ -1,5 +1,5 @@
/* Subroutines for manipulating rtx's in semantically interesting ways.
- Copyright (C) 1987, 91, 94-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 94-97, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "toplev.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
@@ -31,6 +32,10 @@ Boston, MA 02111-1307, USA. */
#include "insn-flags.h"
#include "insn-codes.h"
+#if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
+#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
+#endif
+
static rtx break_out_memory_refs PROTO((rtx));
static void emit_stack_probe PROTO((rtx));
/* Return an rtx for the sum of X and the integer C.
@@ -112,19 +117,32 @@ plus_constant_wide (x, c)
integer. For a constant term that is not an explicit integer,
we cannot really combine, but group them together anyway.
- Use a recursive call in case the remaining operand is something
- that we handle specially, such as a SYMBOL_REF. */
+ Restart or use a recursive call in case the remaining operand is
+ something that we handle specially, such as a SYMBOL_REF.
+
+ We may not immediately return from the recursive call here, lest
+ all_constant gets lost. */
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- return plus_constant (XEXP (x, 0), c + INTVAL (XEXP (x, 1)));
+ {
+ c += INTVAL (XEXP (x, 1));
+ x = XEXP (x, 0);
+ goto restart;
+ }
else if (CONSTANT_P (XEXP (x, 0)))
- return gen_rtx_PLUS (mode,
- plus_constant (XEXP (x, 0), c),
- XEXP (x, 1));
+ {
+ x = gen_rtx_PLUS (mode,
+ plus_constant (XEXP (x, 0), c),
+ XEXP (x, 1));
+ c = 0;
+ }
else if (CONSTANT_P (XEXP (x, 1)))
- return gen_rtx_PLUS (mode,
- XEXP (x, 0),
- plus_constant (XEXP (x, 1), c));
+ {
+ x = gen_rtx_PLUS (mode,
+ XEXP (x, 0),
+ plus_constant (XEXP (x, 1), c));
+ c = 0;
+ }
break;
default:
@@ -589,9 +607,10 @@ stabilize (x)
/* Mark returned memref with in_struct if it's in an array or
structure. Copy const and volatile from original memref. */
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (x) || GET_CODE (addr) == PLUS;
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (x);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (x);
+ MEM_COPY_ATTRIBUTES (mem, x);
+ if (GET_CODE (addr) == PLUS)
+ MEM_SET_IN_STRUCT_P (mem, 1);
/* Since the new MEM is just like the old X, it can alias only
the things that X could. */
@@ -736,7 +755,7 @@ promote_mode (type, mode, punsignedp, for_call)
tree type;
enum machine_mode mode;
int *punsignedp;
- int for_call;
+ int for_call ATTRIBUTE_UNUSED;
{
enum tree_code code = TREE_CODE (type);
int unsignedp = *punsignedp;
@@ -830,8 +849,8 @@ rtx
round_push (size)
rtx size;
{
-#ifdef STACK_BOUNDARY
- int align = STACK_BOUNDARY / BITS_PER_UNIT;
+#ifdef PREFERRED_STACK_BOUNDARY
+ int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
if (align == 1)
return size;
if (GET_CODE (size) == CONST_INT)
@@ -851,7 +870,7 @@ round_push (size)
NULL_RTX, 1);
size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
}
-#endif /* STACK_BOUNDARY */
+#endif /* PREFERRED_STACK_BOUNDARY */
return size;
}
@@ -1124,10 +1143,10 @@ allocate_dynamic_stack_space (size, target, known_align)
If we have to align, we must leave space in SIZE for the hole
that might result from the alignment operation. */
-#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) || ! defined (STACK_BOUNDARY)
+#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) || ! defined (PREFERRED_STACK_BOUNDARY)
#define MUST_ALIGN 1
#else
-#define MUST_ALIGN (STACK_BOUNDARY < BIGGEST_ALIGNMENT)
+#define MUST_ALIGN (PREFERRED_STACK_BOUNDARY < BIGGEST_ALIGNMENT)
#endif
if (MUST_ALIGN)
@@ -1154,12 +1173,12 @@ allocate_dynamic_stack_space (size, target, known_align)
if (!current_function_calls_setjmp)
{
- int align = STACK_BOUNDARY / BITS_PER_UNIT;
+ int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
/* See optimize_save_area_alloca to understand what is being
set up here. */
-#if !defined(STACK_BOUNDARY) || !defined(MUST_ALIGN) || (STACK_BOUNDARY != BIGGEST_ALIGNMENT)
+#if !defined(PREFERRED_STACK_BOUNDARY) || !defined(MUST_ALIGN) || (PREFERRED_STACK_BOUNDARY != BIGGEST_ALIGNMENT)
/* If anyone creates a target with these characteristics, let them
know that our optimization cannot work correctly in such a case. */
abort();
@@ -1209,11 +1228,11 @@ allocate_dynamic_stack_space (size, target, known_align)
way of knowing which systems have this problem. So we avoid even
momentarily mis-aligning the stack. */
-#ifdef STACK_BOUNDARY
+#ifdef PREFERRED_STACK_BOUNDARY
/* If we added a variable amount to SIZE,
we can no longer assume it is aligned. */
#if !defined (SETJMP_VIA_SAVE_AREA)
- if (MUST_ALIGN || known_align % STACK_BOUNDARY != 0)
+ if (MUST_ALIGN || known_align % PREFERRED_STACK_BOUNDARY != 0)
#endif
size = round_push (size);
#endif
@@ -1243,7 +1262,11 @@ allocate_dynamic_stack_space (size, target, known_align)
if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]
&& ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0])
(target, Pmode)))
+#ifdef POINTERS_EXTEND_UNSIGNED
+ target = convert_memory_address (Pmode, target);
+#else
target = copy_to_mode_reg (Pmode, target);
+#endif
size = convert_modes (mode, ptr_mode, size, 1);
if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][1]
&& ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][1])
@@ -1299,7 +1322,7 @@ allocate_dynamic_stack_space (size, target, known_align)
#endif
/* Record the new stack level for nonlocal gotos. */
- if (nonlocal_goto_handler_slot != 0)
+ if (nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
return target;
@@ -1427,8 +1450,8 @@ probe_stack_range (first, size)
abort ();
emit_label (test_lab);
- emit_cmp_insn (test_addr, last_addr, CMP_OPCODE, NULL_RTX, Pmode, 1, 0);
- emit_jump_insn ((*bcc_gen_fctn[(int) CMP_OPCODE]) (loop_lab));
+ emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
+ NULL_RTX, Pmode, 1, 0, loop_lab);
emit_jump (end_lab);
emit_note (NULL_PTR, NOTE_INSN_LOOP_END);
emit_label (end_lab);
@@ -1450,7 +1473,7 @@ probe_stack_range (first, size)
rtx
hard_function_value (valtype, func)
tree valtype;
- tree func;
+ tree func ATTRIBUTE_UNUSED;
{
rtx val = FUNCTION_VALUE (valtype, func);
if (GET_CODE (val) == REG
diff --git a/contrib/gcc/expmed.c b/contrib/gcc/expmed.c
index 2f656c2..ffe16fe 100644
--- a/contrib/gcc/expmed.c
+++ b/contrib/gcc/expmed.c
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "toplev.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
@@ -211,10 +212,10 @@ negate_rtx (mode, x)
/* ??? Note that there are two different ideas here for how
to determine the size to count bits within, for a register.
One is BITS_PER_WORD, and the other is the size of operand 3
- of the insv pattern. (The latter assumes that an n-bit machine
- will be able to insert bit fields up to n bits wide.)
- It isn't certain that either of these is right.
- extract_bit_field has the same quandary. */
+ of the insv pattern.
+
+ If operand 3 of the insv pattern is VOIDmode, then we will use BITS_PER_WORD
+ else, we use the mode of operand 3. */
rtx
store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
@@ -230,6 +231,14 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
register int offset = bitnum / unit;
register int bitpos = bitnum % unit;
register rtx op0 = str_rtx;
+#ifdef HAVE_insv
+ int insv_bitsize;
+
+ if (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode)
+ insv_bitsize = GET_MODE_BITSIZE (word_mode);
+ else
+ insv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]);
+#endif
if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx))
abort ();
@@ -253,6 +262,21 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
op0 = SUBREG_REG (op0);
}
+ /* Make sure we are playing with integral modes. Pun with subregs
+ if we aren't. */
+ {
+ enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
+ if (imode != GET_MODE (op0))
+ {
+ if (GET_CODE (op0) == MEM)
+ op0 = change_address (op0, imode, NULL_RTX);
+ else if (imode != BLKmode)
+ op0 = gen_lowpart (imode, op0);
+ else
+ abort ();
+ }
+ }
+
/* If OP0 is a register, BITPOS must count within a word.
But as we have it, it counts within whatever size OP0 now has.
On a bigendian machine, these are not the same, so convert. */
@@ -279,6 +303,18 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
can be done with just SUBREG. */
if (GET_MODE (op0) != fieldmode)
{
+ if (GET_CODE (op0) == SUBREG)
+ {
+ if (GET_MODE (SUBREG_REG (op0)) == fieldmode
+ || GET_MODE_CLASS (fieldmode) == MODE_INT
+ || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
+ op0 = SUBREG_REG (op0);
+ else
+ /* Else we've got some float mode source being extracted into
+ a different float mode destination -- this combination of
+ subregs results in Severe Tire Damage. */
+ abort ();
+ }
if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
else
@@ -312,8 +348,22 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
else
{
int icode = movstrict_optab->handlers[(int) fieldmode].insn_code;
- if(! (*insn_operand_predicate[icode][1]) (value, fieldmode))
+ if (! (*insn_operand_predicate[icode][1]) (value, fieldmode))
value = copy_to_mode_reg (fieldmode, value);
+
+ if (GET_CODE (op0) == SUBREG)
+ {
+ if (GET_MODE (SUBREG_REG (op0)) == fieldmode
+ || GET_MODE_CLASS (fieldmode) == MODE_INT
+ || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
+ op0 = SUBREG_REG (op0);
+ else
+ /* Else we've got some float mode source being extracted into
+ a different float mode destination -- this combination of
+ subregs results in Severe Tire Damage. */
+ abort ();
+ }
+
emit_insn (GEN_FCN (icode)
(gen_rtx_SUBREG (fieldmode, op0, offset), value));
}
@@ -368,12 +418,27 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
/* OFFSET is the number of words or bytes (UNIT says which)
from STR_RTX to the first word or byte containing part of the field. */
- if (GET_CODE (op0) == REG)
+ if (GET_CODE (op0) != MEM)
{
if (offset != 0
|| GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
- op0 = gen_rtx_SUBREG (TYPE_MODE (type_for_size (BITS_PER_WORD, 0)),
- op0, offset);
+ {
+ if (GET_CODE (op0) != REG)
+ {
+ /* Since this is a destination (lvalue), we can't copy it to a
+ pseudo. We can trivially remove a SUBREG that does not
+ change the size of the operand. Such a SUBREG may have been
+ added above. Otherwise, abort. */
+ if (GET_CODE (op0) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (op0))
+ == GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
+ op0 = SUBREG_REG (op0);
+ else
+ abort ();
+ }
+ op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
+ op0, offset);
+ }
offset = 0;
}
else
@@ -400,21 +465,22 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
&& GET_MODE (value) != BLKmode
&& !(bitsize == 1 && GET_CODE (value) == CONST_INT)
/* Ensure insv's size is wide enough for this field. */
- && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3])
- >= bitsize)
+ && (insv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
- && (bitsize + bitpos
- > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]))))
+ && (bitsize + bitpos > insv_bitsize)))
{
int xbitpos = bitpos;
rtx value1;
rtx xop0 = op0;
rtx last = get_last_insn ();
rtx pat;
- enum machine_mode maxmode
- = insn_operand_mode[(int) CODE_FOR_insv][3];
-
+ enum machine_mode maxmode;
int save_volatile_ok = volatile_ok;
+
+ maxmode = insn_operand_mode[(int) CODE_FOR_insv][3];
+ if (maxmode == VOIDmode)
+ maxmode = word_mode;
+
volatile_ok = 1;
/* If this machine's insv can only insert into a register, copy OP0
@@ -503,7 +569,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
{
/* Avoid making subreg of a subreg, or of a mem. */
if (GET_CODE (value1) != REG)
- value1 = copy_to_reg (value1);
+ value1 = copy_to_reg (value1);
value1 = gen_rtx_SUBREG (maxmode, value1, 0);
}
else
@@ -894,6 +960,27 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
register rtx op0 = str_rtx;
rtx spec_target = target;
rtx spec_target_subreg = 0;
+#ifdef HAVE_extv
+ int extv_bitsize;
+#endif
+#ifdef HAVE_extzv
+ int extzv_bitsize;
+#endif
+
+#ifdef HAVE_extv
+ if (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode)
+ extv_bitsize = GET_MODE_BITSIZE (word_mode);
+ else
+ extv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]);
+#endif
+
+#ifdef HAVE_extzv
+ if (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode)
+ extzv_bitsize = GET_MODE_BITSIZE (word_mode);
+ else
+ extzv_bitsize
+ = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]);
+#endif
/* Discount the part of the structure before the desired byte.
We need to know how many bytes are safe to reference after it. */
@@ -925,6 +1012,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
op0 = SUBREG_REG (op0);
}
+ /* Make sure we are playing with integral modes. Pun with subregs
+ if we aren't. */
+ {
+ enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
+ if (imode != GET_MODE (op0))
+ {
+ if (GET_CODE (op0) == MEM)
+ op0 = change_address (op0, imode, NULL_RTX);
+ else if (imode != BLKmode)
+ op0 = gen_lowpart (imode, op0);
+ else
+ abort ();
+ }
+ }
+
/* ??? We currently assume TARGET is at least as big as BITSIZE.
If that's wrong, the solution is to test for it and set TARGET to 0
if needed. */
@@ -943,7 +1045,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
So too extracting a subword value in
the least significant part of the register. */
- if (((GET_CODE (op0) == REG
+ if (((GET_CODE (op0) != MEM
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (op0))))
|| (GET_CODE (op0) == MEM
@@ -953,6 +1055,10 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
&& ((bitsize >= BITS_PER_WORD && bitsize == GET_MODE_BITSIZE (mode)
&& bitpos % BITS_PER_WORD == 0)
|| (mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0) != BLKmode
+ /* ??? The big endian test here is wrong. This is correct
+ if the value is in a register, and if mode_for_size is not
+ the same mode as op0. This causes us to get unnecessarily
+ inefficient code from the Thumb port when -mbig-endian. */
&& (BYTES_BIG_ENDIAN
? bitpos + bitsize == BITS_PER_WORD
: bitpos == 0))))
@@ -962,6 +1068,18 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
if (mode1 != GET_MODE (op0))
{
+ if (GET_CODE (op0) == SUBREG)
+ {
+ if (GET_MODE (SUBREG_REG (op0)) == mode1
+ || GET_MODE_CLASS (mode1) == MODE_INT
+ || GET_MODE_CLASS (mode1) == MODE_PARTIAL_INT)
+ op0 = SUBREG_REG (op0);
+ else
+ /* Else we've got some float mode source being extracted into
+ a different float mode destination -- this combination of
+ subregs results in Severe Tire Damage. */
+ abort ();
+ }
if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (mode1, op0, offset);
else
@@ -1054,12 +1172,16 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
/* OFFSET is the number of words or bytes (UNIT says which)
from STR_RTX to the first word or byte containing part of the field. */
- if (GET_CODE (op0) == REG)
+ if (GET_CODE (op0) != MEM)
{
if (offset != 0
|| GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
- op0 = gen_rtx_SUBREG (TYPE_MODE (type_for_size (BITS_PER_WORD, 0)),
- op0, offset);
+ {
+ if (GET_CODE (op0) != REG)
+ op0 = copy_to_reg (op0);
+ op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
+ op0, offset);
+ }
offset = 0;
}
else
@@ -1073,11 +1195,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
{
#ifdef HAVE_extzv
if (HAVE_extzv
- && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0])
- >= bitsize)
+ && (extzv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
- && (bitsize + bitpos
- > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]))))
+ && (bitsize + bitpos > extzv_bitsize)))
{
int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx;
@@ -1087,8 +1207,11 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
rtx xspec_target = spec_target;
rtx xspec_target_subreg = spec_target_subreg;
rtx pat;
- enum machine_mode maxmode
- = insn_operand_mode[(int) CODE_FOR_extzv][0];
+ enum machine_mode maxmode;
+
+ maxmode = insn_operand_mode[(int) CODE_FOR_extzv][0];
+ if (maxmode == VOIDmode)
+ maxmode = word_mode;
if (GET_CODE (xop0) == MEM)
{
@@ -1213,11 +1336,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
{
#ifdef HAVE_extv
if (HAVE_extv
- && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0])
- >= bitsize)
+ && (extv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
- && (bitsize + bitpos
- > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]))))
+ && (bitsize + bitpos > extv_bitsize)))
{
int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx;
@@ -1226,8 +1347,11 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
rtx xspec_target = spec_target;
rtx xspec_target_subreg = spec_target_subreg;
rtx pat;
- enum machine_mode maxmode
- = insn_operand_mode[(int) CODE_FOR_extv][0];
+ enum machine_mode maxmode;
+
+ maxmode = insn_operand_mode[(int) CODE_FOR_extv][0];
+ if (maxmode == VOIDmode)
+ maxmode = word_mode;
if (GET_CODE (xop0) == MEM)
{
@@ -1764,7 +1888,8 @@ expand_shift (code, mode, shifted, amount, target, unsignedp)
if (SHIFT_COUNT_TRUNCATED)
{
if (GET_CODE (op1) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (op1) >= GET_MODE_BITSIZE (mode))
+ && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
+ (unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (mode)))
op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
% GET_MODE_BITSIZE (mode));
else if (GET_CODE (op1) == SUBREG
@@ -1939,7 +2064,7 @@ synth_mult (alg_out, t, cost_limit)
{
int m;
struct algorithm *alg_in, *best_alg;
- unsigned int cost;
+ int cost;
unsigned HOST_WIDE_INT q;
/* Indicate that no algorithm is yet found. If no algorithm
@@ -2349,10 +2474,10 @@ expand_mult (mode, op0, op1, target, unsignedp)
multiplication sequences. */
insn = get_last_insn ();
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_MULT (mode, op0, GEN_INT (val_so_far)),
- REG_NOTES (insn));
+ set_unique_reg_note (insn,
+ REG_EQUAL,
+ gen_rtx_MULT (mode, op0,
+ GEN_INT (val_so_far)));
}
if (variant == negate_variant)
@@ -2728,6 +2853,27 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
This could optimize to a bfexts instruction.
But C doesn't use these operations, so their optimizations are
left for later. */
+/* ??? For modulo, we don't actually need the highpart of the first product,
+ the low part will do nicely. And for small divisors, the second multiply
+ can also be a low-part only multiply or even be completely left out.
+ E.g. to calculate the remainder of a division by 3 with a 32 bit
+ multiply, multiply with 0x55555556 and extract the upper two bits;
+ the result is exact for inputs up to 0x1fffffff.
+ The input range can be reduced by using cross-sum rules.
+ For odd divisors >= 3, the following table gives right shift counts
+ so that if an number is shifted by an integer multiple of the given
+ amount, the remainder stays the same:
+ 2, 4, 3, 6, 10, 12, 4, 8, 18, 6, 11, 20, 18, 0, 5, 10, 12, 0, 12, 20,
+ 14, 12, 23, 21, 8, 0, 20, 18, 0, 0, 6, 12, 0, 22, 0, 18, 20, 30, 0, 0,
+ 0, 8, 0, 11, 12, 10, 36, 0, 30, 0, 0, 12, 0, 0, 0, 0, 44, 12, 24, 0,
+ 20, 0, 7, 14, 0, 18, 36, 0, 0, 46, 60, 0, 42, 0, 15, 24, 20, 0, 0, 33,
+ 0, 20, 0, 0, 18, 0, 60, 0, 0, 0, 0, 0, 40, 18, 0, 0, 12
+
+ Cross-sum rules for even numbers can be derived by leaving as many bits
+ to the right alone as the divisor has zeros to the right.
+ E.g. if x is an unsigned 32 bit number:
+ (x mod 12) == (((x & 1023) + ((x >> 8) & ~3)) * 0x15555558 >> 2 * 3) >> 28
+ */
#define EXACT_POWER_OF_2_OR_ZERO_P(x) (((x) & ((x) - 1)) == 0)
@@ -3025,10 +3171,9 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
if (insn != last
&& (set = single_set (insn)) != 0
&& SET_DEST (set) == quotient)
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_UDIV (compute_mode, op0, op1),
- REG_NOTES (insn));
+ set_unique_reg_note (insn,
+ REG_EQUAL,
+ gen_rtx_UDIV (compute_mode, op0, op1));
}
else /* TRUNC_DIV, signed */
{
@@ -3101,13 +3246,14 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
insn = get_last_insn ();
if (insn != last
&& (set = single_set (insn)) != 0
- && SET_DEST (set) == quotient)
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_DIV (compute_mode,
- op0,
- GEN_INT (abs_d)),
- REG_NOTES (insn));
+ && SET_DEST (set) == quotient
+ && abs_d < ((unsigned HOST_WIDE_INT) 1
+ << (HOST_BITS_PER_WIDE_INT - 1)))
+ set_unique_reg_note (insn,
+ REG_EQUAL,
+ gen_rtx_DIV (compute_mode,
+ op0,
+ GEN_INT (abs_d)));
quotient = expand_unop (compute_mode, neg_optab,
quotient, quotient, 0);
@@ -3172,10 +3318,9 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
if (insn != last
&& (set = single_set (insn)) != 0
&& SET_DEST (set) == quotient)
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_DIV (compute_mode, op0, op1),
- REG_NOTES (insn));
+ set_unique_reg_note (insn,
+ REG_EQUAL,
+ gen_rtx_DIV (compute_mode, op0, op1));
}
break;
}
@@ -3588,12 +3733,11 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
NULL_RTX, unsignedp);
insn = get_last_insn ();
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
- compute_mode,
- op0, op1),
- REG_NOTES (insn));
+ set_unique_reg_note (insn,
+ REG_EQUAL,
+ gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
+ compute_mode,
+ op0, op1));
}
break;
@@ -3639,8 +3783,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
remainder = expand_binop (compute_mode, sub_optab, op0, tem,
remainder, 0, OPTAB_LIB_WIDEN);
}
- abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 0, 0);
- abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 0, 0);
+ abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 0);
+ abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 0);
tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
build_int_2 (1, 0), NULL_RTX, 1);
do_cmp_and_jump (tem, abs_op1, LTU, compute_mode, label);
@@ -3673,10 +3817,22 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
if (rem_flag)
{
- /* Try to produce the remainder directly without a library call. */
- remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
- op0, op1, target,
- unsignedp, OPTAB_WIDEN);
+ /* Try to produce the remainder without producing the quotient.
+ If we seem to have a divmod patten that does not require widening,
+ don't try windening here. We should really have an WIDEN argument
+ to expand_twoval_binop, since what we'd really like to do here is
+ 1) try a mod insn in compute_mode
+ 2) try a divmod insn in compute_mode
+ 3) try a div insn in compute_mode and multiply-subtract to get
+ remainder
+ 4) try the same things with widening allowed. */
+ remainder
+ = sign_expand_binop (compute_mode, umod_optab, smod_optab,
+ op0, op1, target,
+ unsignedp,
+ ((optab2->handlers[(int) compute_mode].insn_code
+ != CODE_FOR_nothing)
+ ? OPTAB_DIRECT : OPTAB_WIDEN));
if (remainder == 0)
{
/* No luck there. Can we do remainder and divide at once
@@ -3767,7 +3923,9 @@ make_tree (type, x)
{
case CONST_INT:
t = build_int_2 (INTVAL (x),
- TREE_UNSIGNED (type) || INTVAL (x) >= 0 ? 0 : -1);
+ (TREE_UNSIGNED (type)
+ && (GET_MODE_BITSIZE (TYPE_MODE (type)) < HOST_BITS_PER_WIDE_INT))
+ || INTVAL (x) >= 0 ? 0 : -1);
TREE_TYPE (t) = type;
return t;
@@ -4188,7 +4346,7 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
- == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))
+ == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)))
;
else
return 0;
@@ -4415,9 +4573,6 @@ do_cmp_and_jump (arg1, arg2, op, mode, label)
}
else
{
- emit_cmp_insn(arg1, arg2, op, NULL_RTX, mode, 0, 0);
- if (bcc_gen_fctn[(int) op] == 0)
- abort ();
- emit_jump_insn ((*bcc_gen_fctn[(int) op]) (label));
+ emit_cmp_and_jump_insns (arg1, arg2, op, NULL_RTX, mode, 0, 0, label);
}
}
diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c
index 0457b87..812e1fb 100644
--- a/contrib/gcc/expr.c
+++ b/contrib/gcc/expr.c
@@ -65,9 +65,6 @@ Boston, MA 02111-1307, USA. */
#endif
#endif
-/* Like STACK_BOUNDARY but in units of bytes, not bits. */
-#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
-
/* Assume that case vectors are not pc-relative. */
#ifndef CASE_VECTOR_PC_RELATIVE
#define CASE_VECTOR_PC_RELATIVE 0
@@ -90,10 +87,21 @@ int do_preexpand_calls = 1;
These are the arguments to function calls that have already returned. */
int pending_stack_adjust;
-/* Nonzero means stack pops must not be deferred, and deferred stack
- pops must not be output. It is nonzero inside a function call,
- inside a conditional expression, inside a statement expression,
- and in other cases as well. */
+/* Under some ABIs, it is the caller's responsibility to pop arguments
+ pushed for function calls. A naive implementation would simply pop
+ the arguments immediately after each call. However, if several
+ function calls are made in a row, it is typically cheaper to pop
+ all the arguments after all of the calls are complete since a
+ single pop instruction can be used. Therefore, GCC attempts to
+ defer popping the arguments until absolutely necessary. (For
+ example, at the end of a conditional, the arguments must be popped,
+ since code outside the conditional won't know whether or not the
+ arguments need to be popped.)
+
+ When INHIBIT_DEFER_POP is non-zero, however, the compiler does not
+ attempt to defer pops. Instead, the stack is popped immediately
+ after each call. Rather then setting this variable directly, use
+ NO_DEFER_POP and OK_DEFER_POP. */
int inhibit_defer_pop;
/* Nonzero means __builtin_saveregs has already been done in this function.
@@ -104,14 +112,9 @@ static rtx saveregs_value;
/* Similarly for __builtin_apply_args. */
static rtx apply_args_value;
-/* Nonzero if the machine description has been fixed to accept
- CONSTANT_P_RTX patterns. We will emit a warning and continue
- if we find we must actually use such a beast. */
-static int can_handle_constant_p;
-
/* Don't check memory usage, since code is being emitted to check a memory
- usage. Used when flag_check_memory_usage is true, to avoid infinite
- recursion. */
+ usage. Used when current_function_check_memory_usage is true, to avoid
+ infinite recursion. */
static int in_check_memory_usage;
/* Postincrements that still need to be expanded. */
@@ -157,9 +160,7 @@ extern rtx arg_pointer_save_area;
static rtx get_push_address PROTO ((int));
static rtx enqueue_insn PROTO((rtx, rtx));
-static int queued_subexp_p PROTO((rtx));
static void init_queue PROTO((void));
-static void move_by_pieces PROTO((rtx, rtx, int, int));
static int move_by_pieces_ninsns PROTO((unsigned int, int));
static void move_by_pieces_1 PROTO((rtx (*) (rtx, ...), enum machine_mode,
struct move_by_pieces *));
@@ -172,7 +173,8 @@ static void store_constructor_field PROTO((rtx, int, int, enum machine_mode,
tree, tree, int));
static void store_constructor PROTO((tree, rtx, int));
static rtx store_field PROTO((rtx, int, int, enum machine_mode, tree,
- enum machine_mode, int, int, int));
+ enum machine_mode, int, int,
+ int, int));
static enum memory_use_mode
get_memory_usage_from_modifier PROTO((enum expand_modifier));
static tree save_noncopied_parts PROTO((tree, tree));
@@ -207,8 +209,8 @@ static rtx do_store_flag PROTO((tree, rtx, enum machine_mode, int));
static char direct_load[NUM_MACHINE_MODES];
static char direct_store[NUM_MACHINE_MODES];
-/* MOVE_RATIO is the number of move instructions that is better than
- a block move. */
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+ move-instruction sequences, we will do a movstr or libcall instead. */
#ifndef MOVE_RATIO
#if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
@@ -219,6 +221,13 @@ static char direct_store[NUM_MACHINE_MODES];
#endif
#endif
+/* This macro is used to determine whether move_by_pieces should be called
+ to perform a structure copy. */
+#ifndef MOVE_BY_PIECES_P
+#define MOVE_BY_PIECES_P(SIZE, ALIGN) (move_by_pieces_ninsns \
+ (SIZE, ALIGN) < MOVE_RATIO)
+#endif
+
/* This array records the insn_code of insns to perform block moves. */
enum insn_code movstr_optab[NUM_MACHINE_MODES];
@@ -312,14 +321,6 @@ init_expr_once ()
}
}
- /* Find out if CONSTANT_P_RTX is accepted. */
- SET_DEST (pat) = gen_rtx_REG (TYPE_MODE (integer_type_node),
- FIRST_PSEUDO_REGISTER);
- SET_SRC (pat) = gen_rtx_CONSTANT_P_RTX (TYPE_MODE (integer_type_node),
- SET_DEST (pat));
- if (recog (pat, insn, &num_clobbers) >= 0)
- can_handle_constant_p = 1;
-
end_sequence ();
obfree (free_point);
}
@@ -436,9 +437,8 @@ protect_from_queue (x, modify)
register rtx y = XEXP (x, 0);
register rtx new = gen_rtx_MEM (GET_MODE (x), QUEUED_VAR (y));
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
+ MEM_COPY_ATTRIBUTES (new, x);
MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
if (QUEUED_INSN (y))
@@ -494,7 +494,7 @@ protect_from_queue (x, modify)
We handle only combinations of MEM, PLUS, MINUS and MULT operators
since memory addresses generally contain only those. */
-static int
+int
queued_subexp_p (x)
rtx x;
{
@@ -1100,6 +1100,8 @@ convert_move (to, from, unsignedp)
else
{
enum machine_mode intermediate;
+ rtx tmp;
+ tree shift_amount;
/* Search for a mode to convert via. */
for (intermediate = from_mode; intermediate != VOIDmode;
@@ -1116,8 +1118,18 @@ convert_move (to, from, unsignedp)
return;
}
- /* No suitable intermediate mode. */
- abort ();
+ /* No suitable intermediate mode.
+ Generate what we need with shifts. */
+ shift_amount = build_int_2 (GET_MODE_BITSIZE (to_mode)
+ - GET_MODE_BITSIZE (from_mode), 0);
+ from = gen_lowpart (to_mode, force_reg (from_mode, from));
+ tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
+ to, unsignedp);
+ tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
+ to, unsignedp);
+ if (tmp != to)
+ emit_move_insn (to, tmp);
+ return;
}
}
@@ -1389,20 +1401,34 @@ convert_modes (mode, oldmode, x, unsignedp)
return temp;
}
+
+/* This macro is used to determine what the largest unit size that
+ move_by_pieces can use is. */
+
+/* MOVE_MAX_PIECES is the number of bytes at a time which we can
+ move efficiently, as opposed to MOVE_MAX which is the maximum
+ number of bhytes we can move with a single instruction. */
+
+#ifndef MOVE_MAX_PIECES
+#define MOVE_MAX_PIECES MOVE_MAX
+#endif
+
/* Generate several move instructions to copy LEN bytes
from block FROM to block TO. (These are MEM rtx's with BLKmode).
The caller must pass FROM and TO
through protect_from_queue before calling.
ALIGN (in bytes) is maximum alignment we can assume. */
-static void
+void
move_by_pieces (to, from, len, align)
rtx to, from;
int len, align;
{
struct move_by_pieces data;
rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
- int max_size = MOVE_MAX + 1;
+ int max_size = MOVE_MAX_PIECES + 1;
+ enum machine_mode mode = VOIDmode, tmode;
+ enum insn_code icode;
data.offset = 0;
data.to_addr = to_addr;
@@ -1433,40 +1459,38 @@ move_by_pieces (to, from, len, align)
if (!(data.autinc_from && data.autinc_to)
&& move_by_pieces_ninsns (len, align) > 2)
{
-#ifdef HAVE_PRE_DECREMENT
- if (data.reverse && ! data.autinc_from)
+ /* Find the mode of the largest move... */
+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
+ if (GET_MODE_SIZE (tmode) < max_size)
+ mode = tmode;
+
+ if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
{
data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
data.autinc_from = 1;
data.explicit_inc_from = -1;
}
-#endif
-#ifdef HAVE_POST_INCREMENT
- if (! data.autinc_from)
+ if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
{
data.from_addr = copy_addr_to_reg (from_addr);
data.autinc_from = 1;
data.explicit_inc_from = 1;
}
-#endif
if (!data.autinc_from && CONSTANT_P (from_addr))
data.from_addr = copy_addr_to_reg (from_addr);
-#ifdef HAVE_PRE_DECREMENT
- if (data.reverse && ! data.autinc_to)
+ if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
{
data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
data.autinc_to = 1;
data.explicit_inc_to = -1;
}
-#endif
-#ifdef HAVE_POST_INCREMENT
- if (! data.reverse && ! data.autinc_to)
+ if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
{
data.to_addr = copy_addr_to_reg (to_addr);
data.autinc_to = 1;
data.explicit_inc_to = 1;
}
-#endif
if (!data.autinc_to && CONSTANT_P (to_addr))
data.to_addr = copy_addr_to_reg (to_addr);
}
@@ -1480,9 +1504,6 @@ move_by_pieces (to, from, len, align)
while (max_size > 1)
{
- enum machine_mode mode = VOIDmode, tmode;
- enum insn_code icode;
-
for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
if (GET_MODE_SIZE (tmode) < max_size)
@@ -1577,20 +1598,16 @@ move_by_pieces_1 (genfun, mode, data)
data->offset))));
MEM_IN_STRUCT_P (from1) = data->from_struct;
-#ifdef HAVE_PRE_DECREMENT
- if (data->explicit_inc_to < 0)
+ if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
- if (data->explicit_inc_from < 0)
+ if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
-#endif
emit_insn ((*genfun) (to1, from1));
-#ifdef HAVE_POST_INCREMENT
- if (data->explicit_inc_to > 0)
+ if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
- if (data->explicit_inc_from > 0)
+ if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0)
emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
-#endif
if (! data->reverse) data->offset += size;
@@ -1640,8 +1657,7 @@ emit_block_move (x, y, size, align)
if (size == 0)
abort ();
- if (GET_CODE (size) == CONST_INT
- && (move_by_pieces_ninsns (INTVAL (size), align) < MOVE_RATIO))
+ if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P (INTVAL (size), align))
move_by_pieces (x, y, INTVAL (size), align);
else
{
@@ -1694,6 +1710,37 @@ emit_block_move (x, y, size, align)
}
}
+ /* X, Y, or SIZE may have been passed through protect_from_queue.
+
+ It is unsafe to save the value generated by protect_from_queue
+ and reuse it later. Consider what happens if emit_queue is
+ called before the return value from protect_from_queue is used.
+
+ Expansion of the CALL_EXPR below will call emit_queue before
+ we are finished emitting RTL for argument setup. So if we are
+ not careful we could get the wrong value for an argument.
+
+ To avoid this problem we go ahead and emit code to copy X, Y &
+ SIZE into new pseudos. We can then place those new pseudos
+ into an RTL_EXPR and use them later, even after a call to
+ emit_queue.
+
+ Note this is not strictly needed for library calls since they
+ do not call emit_queue before loading their arguments. However,
+ we may need to have library calls call emit_queue in the future
+ since failing to do so could cause problems for targets which
+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
+ x = copy_to_mode_reg (Pmode, XEXP (x, 0));
+ y = copy_to_mode_reg (Pmode, XEXP (y, 0));
+
+#ifdef TARGET_MEM_FUNCTIONS
+ size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
+#else
+ size = convert_to_mode (TYPE_MODE (integer_type_node), size,
+ TREE_UNSIGNED (integer_type_node));
+ size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
+#endif
+
#ifdef TARGET_MEM_FUNCTIONS
/* It is incorrect to use the libcall calling conventions to call
memcpy in this context.
@@ -1732,12 +1779,10 @@ emit_block_move (x, y, size, align)
the last is a size_t byte count for the copy. */
arg_list
= build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node),
- XEXP (x, 0)));
+ make_tree (build_pointer_type (void_type_node), x));
TREE_CHAIN (arg_list)
= build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node),
- XEXP (y, 0)));
+ make_tree (build_pointer_type (void_type_node), y));
TREE_CHAIN (TREE_CHAIN (arg_list))
= build_tree_list (NULL_TREE, make_tree (sizetype, size));
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
@@ -1751,8 +1796,7 @@ emit_block_move (x, y, size, align)
retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
#else
emit_library_call (bcopy_libfunc, 0,
- VOIDmode, 3, XEXP (y, 0), Pmode,
- XEXP (x, 0), Pmode,
+ VOIDmode, 3, y, Pmode, x, Pmode,
convert_to_mode (TYPE_MODE (integer_type_node), size,
TREE_UNSIGNED (integer_type_node)),
TYPE_MODE (integer_type_node));
@@ -2007,7 +2051,26 @@ emit_group_store (orig_dst, src, ssize, align)
/* If we won't be storing directly into memory, protect the real destination
from strange tricks we might play. */
dst = orig_dst;
- if (GET_CODE (dst) != MEM)
+ if (GET_CODE (dst) == PARALLEL)
+ {
+ rtx temp;
+
+ /* We can get a PARALLEL dst if there is a conditional expression in
+ a return statement. In that case, the dst and src are the same,
+ so no action is necessary. */
+ if (rtx_equal_p (dst, src))
+ return;
+
+ /* It is unclear if we can ever reach here, but we may as well handle
+ it. Allocate a temporary, and split this into a store/load to/from
+ the temporary. */
+
+ temp = assign_stack_temp (GET_MODE (dst), ssize, 0);
+ emit_group_store (temp, src, ssize, align);
+ emit_group_load (dst, temp, ssize, align);
+ return;
+ }
+ else if (GET_CODE (dst) != MEM)
{
dst = gen_reg_rtx (GET_MODE (orig_dst));
/* Make life a bit easier for combine. */
@@ -2019,7 +2082,7 @@ emit_group_store (orig_dst, src, ssize, align)
mem_in_struct_p set; we might not. */
dst = copy_rtx (orig_dst);
- MEM_IN_STRUCT_P (dst) = 1;
+ MEM_SET_IN_STRUCT_P (dst, 1);
}
/* Process the pieces. */
@@ -2065,6 +2128,88 @@ emit_group_store (orig_dst, src, ssize, align)
emit_move_insn (orig_dst, dst);
}
+/* Generate code to copy a BLKmode object of TYPE out of a
+ set of registers starting with SRCREG into TGTBLK. If TGTBLK
+ is null, a stack temporary is created. TGTBLK is returned.
+
+ The primary purpose of this routine is to handle functions
+ that return BLKmode structures in registers. Some machines
+ (the PA for example) want to return all small structures
+ in registers regardless of the structure's alignment.
+ */
+
+rtx
+copy_blkmode_from_reg(tgtblk,srcreg,type)
+ rtx tgtblk;
+ rtx srcreg;
+ tree type;
+{
+ int bytes = int_size_in_bytes (type);
+ rtx src = NULL, dst = NULL;
+ int bitsize = MIN (TYPE_ALIGN (type), (unsigned int) BITS_PER_WORD);
+ int bitpos, xbitpos, big_endian_correction = 0;
+
+ if (tgtblk == 0)
+ {
+ tgtblk = assign_stack_temp (BLKmode, bytes, 0);
+ MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
+ preserve_temp_slots (tgtblk);
+ }
+
+ /* This code assumes srcreg is at least a full word. If it isn't,
+ copy it into a new pseudo which is a full word. */
+ if (GET_MODE (srcreg) != BLKmode
+ && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
+ srcreg = convert_to_mode (word_mode, srcreg,
+ TREE_UNSIGNED (type));
+
+ /* Structures whose size is not a multiple of a word are aligned
+ to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
+ machine, this means we must skip the empty high order bytes when
+ calculating the bit offset. */
+ if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
+ big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
+ * BITS_PER_UNIT));
+
+ /* Copy the structure BITSIZE bites at a time.
+
+ We could probably emit more efficient code for machines
+ which do not use strict alignment, but it doesn't seem
+ worth the effort at the current time. */
+ for (bitpos = 0, xbitpos = big_endian_correction;
+ bitpos < bytes * BITS_PER_UNIT;
+ bitpos += bitsize, xbitpos += bitsize)
+ {
+
+ /* We need a new source operand each time xbitpos is on a
+ word boundary and when xbitpos == big_endian_correction
+ (the first time through). */
+ if (xbitpos % BITS_PER_WORD == 0
+ || xbitpos == big_endian_correction)
+ src = operand_subword_force (srcreg,
+ xbitpos / BITS_PER_WORD,
+ BLKmode);
+
+ /* We need a new destination operand each time bitpos is on
+ a word boundary. */
+ if (bitpos % BITS_PER_WORD == 0)
+ dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
+
+ /* Use xbitpos for the source extraction (right justified) and
+ xbitpos for the destination store (left justified). */
+ store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
+ extract_bit_field (src, bitsize,
+ xbitpos % BITS_PER_WORD, 1,
+ NULL_RTX, word_mode,
+ word_mode,
+ bitsize / BITS_PER_UNIT,
+ BITS_PER_WORD),
+ bitsize / BITS_PER_UNIT, BITS_PER_WORD);
+ }
+ return tgtblk;
+}
+
+
/* Add a USE expression for REG to the (possibly empty) list pointed
to by CALL_FUSAGE. REG must denote a hard register. */
@@ -2134,7 +2279,9 @@ clear_by_pieces (to, len, align)
{
struct clear_by_pieces data;
rtx to_addr = XEXP (to, 0);
- int max_size = MOVE_MAX + 1;
+ int max_size = MOVE_MAX_PIECES + 1;
+ enum machine_mode mode = VOIDmode, tmode;
+ enum insn_code icode;
data.offset = 0;
data.to_addr = to_addr;
@@ -2157,22 +2304,24 @@ clear_by_pieces (to, len, align)
if (!data.autinc_to
&& move_by_pieces_ninsns (len, align) > 2)
{
-#ifdef HAVE_PRE_DECREMENT
- if (data.reverse && ! data.autinc_to)
+ /* Determine the main mode we'll be using */
+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
+ if (GET_MODE_SIZE (tmode) < max_size)
+ mode = tmode;
+
+ if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
{
data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
data.autinc_to = 1;
data.explicit_inc_to = -1;
}
-#endif
-#ifdef HAVE_POST_INCREMENT
- if (! data.reverse && ! data.autinc_to)
+ if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
{
data.to_addr = copy_addr_to_reg (to_addr);
data.autinc_to = 1;
data.explicit_inc_to = 1;
}
-#endif
if (!data.autinc_to && CONSTANT_P (to_addr))
data.to_addr = copy_addr_to_reg (to_addr);
}
@@ -2186,9 +2335,6 @@ clear_by_pieces (to, len, align)
while (max_size > 1)
{
- enum machine_mode mode = VOIDmode, tmode;
- enum insn_code icode;
-
for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
if (GET_MODE_SIZE (tmode) < max_size)
@@ -2235,16 +2381,12 @@ clear_by_pieces_1 (genfun, mode, data)
data->offset))));
MEM_IN_STRUCT_P (to1) = data->to_struct;
-#ifdef HAVE_PRE_DECREMENT
- if (data->explicit_inc_to < 0)
+ if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
-#endif
emit_insn ((*genfun) (to1, const0_rtx));
-#ifdef HAVE_POST_INCREMENT
- if (data->explicit_inc_to > 0)
+ if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
-#endif
if (! data->reverse) data->offset += size;
@@ -2276,7 +2418,7 @@ clear_storage (object, size, align)
size = protect_from_queue (size, 0);
if (GET_CODE (size) == CONST_INT
- && (move_by_pieces_ninsns (INTVAL (size), align) < MOVE_RATIO))
+ && MOVE_BY_PIECES_P (INTVAL (size), align))
clear_by_pieces (object, INTVAL (size), align);
else
@@ -2330,69 +2472,97 @@ clear_storage (object, size, align)
}
}
+ /* OBJECT or SIZE may have been passed through protect_from_queue.
-#ifdef TARGET_MEM_FUNCTIONS
- /* It is incorrect to use the libcall calling conventions to call
- memset in this context.
+ It is unsafe to save the value generated by protect_from_queue
+ and reuse it later. Consider what happens if emit_queue is
+ called before the return value from protect_from_queue is used.
- This could be a user call to memset and the user may wish to
- examine the return value from memset.
+ Expansion of the CALL_EXPR below will call emit_queue before
+ we are finished emitting RTL for argument setup. So if we are
+ not careful we could get the wrong value for an argument.
- For targets where libcalls and normal calls have different conventions
- for returning pointers, we could end up generating incorrect code.
+ To avoid this problem we go ahead and emit code to copy OBJECT
+ and SIZE into new pseudos. We can then place those new pseudos
+ into an RTL_EXPR and use them later, even after a call to
+ emit_queue.
- So instead of using a libcall sequence we build up a suitable
- CALL_EXPR and expand the call in the normal fashion. */
- if (fn == NULL_TREE)
- {
- tree fntype;
+ Note this is not strictly needed for library calls since they
+ do not call emit_queue before loading their arguments. However,
+ we may need to have library calls call emit_queue in the future
+ since failing to do so could cause problems for targets which
+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
+ object = copy_to_mode_reg (Pmode, XEXP (object, 0));
- /* This was copied from except.c, I don't know if all this is
- necessary in this context or not. */
- fn = get_identifier ("memset");
- push_obstacks_nochange ();
- end_temporary_allocation ();
- fntype = build_pointer_type (void_type_node);
- fntype = build_function_type (fntype, NULL_TREE);
- fn = build_decl (FUNCTION_DECL, fn, fntype);
- DECL_EXTERNAL (fn) = 1;
- TREE_PUBLIC (fn) = 1;
- DECL_ARTIFICIAL (fn) = 1;
- make_decl_rtl (fn, NULL_PTR, 1);
- assemble_external (fn);
- pop_obstacks ();
- }
+#ifdef TARGET_MEM_FUNCTIONS
+ size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
+#else
+ size = convert_to_mode (TYPE_MODE (integer_type_node), size,
+ TREE_UNSIGNED (integer_type_node));
+ size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
+#endif
- /* We need to make an argument list for the function call.
- memset has three arguments, the first is a void * addresses, the
- second a integer with the initialization value, the last is a size_t
- byte count for the copy. */
- arg_list
- = build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node),
- XEXP (object, 0)));
- TREE_CHAIN (arg_list)
- = build_tree_list (NULL_TREE,
- make_tree (integer_type_node, const0_rtx));
- TREE_CHAIN (TREE_CHAIN (arg_list))
- = build_tree_list (NULL_TREE, make_tree (sizetype, size));
- TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
+#ifdef TARGET_MEM_FUNCTIONS
+ /* It is incorrect to use the libcall calling conventions to call
+ memset in this context.
- /* Now we have to build up the CALL_EXPR itself. */
- call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
- call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
- call_expr, arg_list, NULL_TREE);
- TREE_SIDE_EFFECTS (call_expr) = 1;
+ This could be a user call to memset and the user may wish to
+ examine the return value from memset.
- retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+ For targets where libcalls and normal calls have different
+ conventions for returning pointers, we could end up generating
+ incorrect code.
+
+ So instead of using a libcall sequence we build up a suitable
+ CALL_EXPR and expand the call in the normal fashion. */
+ if (fn == NULL_TREE)
+ {
+ tree fntype;
+
+ /* This was copied from except.c, I don't know if all this is
+ necessary in this context or not. */
+ fn = get_identifier ("memset");
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ fntype = build_pointer_type (void_type_node);
+ fntype = build_function_type (fntype, NULL_TREE);
+ fn = build_decl (FUNCTION_DECL, fn, fntype);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ make_decl_rtl (fn, NULL_PTR, 1);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ /* We need to make an argument list for the function call.
+
+ memset has three arguments, the first is a void * addresses, the
+ second a integer with the initialization value, the last is a
+ size_t byte count for the copy. */
+ arg_list
+ = build_tree_list (NULL_TREE,
+ make_tree (build_pointer_type (void_type_node),
+ object));
+ TREE_CHAIN (arg_list)
+ = build_tree_list (NULL_TREE,
+ make_tree (integer_type_node, const0_rtx));
+ TREE_CHAIN (TREE_CHAIN (arg_list))
+ = build_tree_list (NULL_TREE, make_tree (sizetype, size));
+ TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
+
+ /* Now we have to build up the CALL_EXPR itself. */
+ call_expr = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (fn)), fn);
+ call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+ call_expr, arg_list, NULL_TREE);
+ TREE_SIDE_EFFECTS (call_expr) = 1;
+
+ retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
#else
emit_library_call (bzero_libfunc, 0,
- VOIDmode, 2,
- XEXP (object, 0), Pmode,
- convert_to_mode
- (TYPE_MODE (integer_type_node), size,
- TREE_UNSIGNED (integer_type_node)),
+ VOIDmode, 2, object, Pmode, size,
TYPE_MODE (integer_type_node));
#endif
}
@@ -2422,7 +2592,10 @@ emit_move_insn (x, y)
if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))
abort ();
- if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
+ /* Never force constant_p_rtx to memory. */
+ if (GET_CODE (y) == CONSTANT_P_RTX)
+ ;
+ else if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
y = force_const_mem (mode, y);
/* If X or Y are memory references, verify that their addresses are valid
@@ -2459,6 +2632,9 @@ emit_move_insn_1 (x, y)
enum mode_class class = GET_MODE_CLASS (mode);
int i;
+ if (mode >= MAX_MACHINE_MODE)
+ abort ();
+
if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
return
emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
@@ -2503,9 +2679,14 @@ emit_move_insn_1 (x, y)
}
else
{
- /* Show the output dies here. */
- if (x != y)
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ /* Show the output dies here. This is necessary for pseudos;
+ hard regs shouldn't appear here except as return values.
+ We never want to emit such a clobber after reload. */
+ if (x != y
+ && ! (reload_in_progress || reload_completed))
+ {
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ }
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
(gen_realpart (submode, x), gen_realpart (submode, y)));
@@ -2534,9 +2715,14 @@ emit_move_insn_1 (x, y)
}
#endif
- /* Show the output dies here. */
- if (x != y)
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ /* Show the output dies here. This is necessary for pseudos;
+ hard regs shouldn't appear here except as return values.
+ We never want to emit such a clobber after reload. */
+ if (x != y
+ && ! (reload_in_progress || reload_completed))
+ {
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ }
for (i = 0;
i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
@@ -2600,7 +2786,13 @@ push_block (size, extra, below)
anti_adjust_stack (temp);
}
-#ifdef STACK_GROWS_DOWNWARD
+#if defined (STACK_GROWS_DOWNWARD) \
+ || (defined (ARGS_GROW_DOWNWARD) \
+ && !defined (ACCUMULATE_OUTGOING_ARGS))
+
+ /* Return the lowest stack address when STACK or ARGS grow downward and
+ we are not aaccumulating outgoing arguments (the c4x port uses such
+ conventions). */
temp = virtual_outgoing_args_rtx;
if (extra != 0 && below)
temp = plus_constant (temp, extra);
@@ -2745,8 +2937,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
if (args_addr == 0
&& GET_CODE (size) == CONST_INT
&& skip == 0
- && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align)
- < MOVE_RATIO)
+ && (MOVE_BY_PIECES_P ((unsigned) INTVAL (size) - used, align))
/* Here we avoid the case of a structure whose weak alignment
forces many pushes of a small amount of data,
and such small pushes do rounding that causes trouble. */
@@ -2765,7 +2956,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
move_by_pieces (gen_rtx_MEM (BLKmode, gen_push_operand ()), xinner,
INTVAL (size) - used, align);
- if (flag_check_memory_usage && ! in_check_memory_usage)
+ if (current_function_check_memory_usage && ! in_check_memory_usage)
{
rtx temp;
@@ -2773,13 +2964,13 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
temp = get_push_address (INTVAL(size) - used);
if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- temp, ptr_mode,
- XEXP (xinner, 0), ptr_mode,
+ temp, Pmode,
+ XEXP (xinner, 0), Pmode,
GEN_INT (INTVAL(size) - used),
TYPE_MODE (sizetype));
else
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- temp, ptr_mode,
+ temp, Pmode,
GEN_INT (INTVAL(size) - used),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
@@ -2822,7 +3013,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
args_addr,
args_so_far),
skip));
- if (flag_check_memory_usage && ! in_check_memory_usage)
+ if (current_function_check_memory_usage && ! in_check_memory_usage)
{
rtx target;
@@ -2830,12 +3021,12 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
target = copy_to_reg (temp);
if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- target, ptr_mode,
- XEXP (xinner, 0), ptr_mode,
+ target, Pmode,
+ XEXP (xinner, 0), Pmode,
size, TYPE_MODE (sizetype));
else
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- target, ptr_mode,
+ target, Pmode,
size, TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));
@@ -2844,8 +3035,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
/* TEMP is the address of the block. Copy the data there. */
if (GET_CODE (size) == CONST_INT
- && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
- < MOVE_RATIO))
+ && (MOVE_BY_PIECES_P ((unsigned) INTVAL (size), align)))
{
move_by_pieces (gen_rtx_MEM (BLKmode, temp), xinner,
INTVAL (size), align);
@@ -3022,7 +3212,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
emit_move_insn (gen_rtx_MEM (mode, addr), x);
- if (flag_check_memory_usage && ! in_check_memory_usage)
+ if (current_function_check_memory_usage && ! in_check_memory_usage)
{
in_check_memory_usage = 1;
if (target == 0)
@@ -3030,13 +3220,13 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- target, ptr_mode,
- XEXP (x, 0), ptr_mode,
+ target, Pmode,
+ XEXP (x, 0), Pmode,
GEN_INT (GET_MODE_SIZE (mode)),
TYPE_MODE (sizetype));
else
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- target, ptr_mode,
+ target, Pmode,
GEN_INT (GET_MODE_SIZE (mode)),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
@@ -3136,8 +3326,11 @@ expand_assignment (to, from, want_value, suggest_reg)
#endif
}
+ /* A constant address in TO_RTX can have VOIDmode, we must not try
+ to call force_reg for that case. Avoid that case. */
if (GET_CODE (to_rtx) == MEM
&& GET_MODE (to_rtx) == BLKmode
+ && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
&& bitsize
&& (bitpos % bitsize) == 0
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
@@ -3190,7 +3383,7 @@ expand_assignment (to, from, want_value, suggest_reg)
}
/* Check the access. */
- if (flag_check_memory_usage && GET_CODE (to_rtx) == MEM)
+ if (current_function_check_memory_usage && GET_CODE (to_rtx) == MEM)
{
rtx to_addr;
int size;
@@ -3211,7 +3404,7 @@ expand_assignment (to, from, want_value, suggest_reg)
/* Check the access right of the pointer. */
if (size)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- to_addr, ptr_mode,
+ to_addr, Pmode,
GEN_INT (size), TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
@@ -3225,7 +3418,8 @@ expand_assignment (to, from, want_value, suggest_reg)
unsignedp,
/* Required alignment of containing datum. */
alignment,
- int_size_in_bytes (TREE_TYPE (tem)));
+ int_size_in_bytes (TREE_TYPE (tem)),
+ get_alias_set (to));
preserve_temp_slots (result);
free_temp_slots ();
pop_temp_slots ();
@@ -3269,7 +3463,14 @@ expand_assignment (to, from, want_value, suggest_reg)
emit_block_move (to_rtx, value, expr_size (from),
TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
else
- emit_move_insn (to_rtx, value);
+ {
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (TREE_CODE (TREE_TYPE (to)) == REFERENCE_TYPE
+ || TREE_CODE (TREE_TYPE (to)) == POINTER_TYPE)
+ value = convert_memory_address (GET_MODE (to_rtx), value);
+#endif
+ emit_move_insn (to_rtx, value);
+ }
preserve_temp_slots (to_rtx);
free_temp_slots ();
pop_temp_slots ();
@@ -3315,10 +3516,10 @@ expand_assignment (to, from, want_value, suggest_reg)
EXPAND_MEMORY_USE_DONT);
/* Copy the rights of the bitmap. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- XEXP (to_rtx, 0), ptr_mode,
- XEXP (from_rtx, 0), ptr_mode,
+ XEXP (to_rtx, 0), Pmode,
+ XEXP (from_rtx, 0), Pmode,
convert_to_mode (TYPE_MODE (sizetype),
size, TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
@@ -3537,18 +3738,18 @@ store_expr (exp, target, want_value)
temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
temp, TREE_UNSIGNED (TREE_TYPE (exp)));
- if (flag_check_memory_usage
+ if (current_function_check_memory_usage
&& GET_CODE (target) == MEM
&& AGGREGATE_TYPE_P (TREE_TYPE (exp)))
{
if (GET_CODE (temp) == MEM)
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- XEXP (target, 0), ptr_mode,
- XEXP (temp, 0), ptr_mode,
+ XEXP (target, 0), Pmode,
+ XEXP (temp, 0), Pmode,
expr_size (exp), TYPE_MODE (sizetype));
else
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- XEXP (target, 0), ptr_mode,
+ XEXP (target, 0), Pmode,
expr_size (exp), TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
@@ -3643,18 +3844,17 @@ store_expr (exp, target, want_value)
copy_size_rtx, NULL_RTX, 0,
OPTAB_LIB_WIDEN);
- emit_cmp_insn (size, const0_rtx, LT, NULL_RTX,
- GET_MODE (size), 0, 0);
label = gen_label_rtx ();
- emit_jump_insn (gen_blt (label));
+ emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
+ GET_MODE (size), 0, 0, label);
}
if (size != const0_rtx)
{
/* Be sure we can write on ADDR. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- addr, ptr_mode,
+ addr, Pmode,
size, TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
@@ -3818,7 +4018,7 @@ store_constructor_field (target, bitsize, bitpos,
else
store_field (target, bitsize, bitpos, mode, exp,
VOIDmode, 0, TYPE_ALIGN (type) / BITS_PER_UNIT,
- int_size_in_bytes (type));
+ int_size_in_bytes (type), 0);
}
/* Store the value of constructor EXP into the rtx TARGET.
@@ -3832,6 +4032,7 @@ store_constructor (exp, target, cleared)
int cleared;
{
tree type = TREE_TYPE (exp);
+ rtx exp_size = expr_size (exp);
/* We know our target cannot conflict, since safe_from_p has been called. */
#if 0
@@ -3893,6 +4094,7 @@ store_constructor (exp, target, cleared)
for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
{
register tree field = TREE_PURPOSE (elt);
+ tree value = TREE_VALUE (elt);
register enum machine_mode mode;
int bitsize;
int bitpos = 0;
@@ -3964,8 +4166,36 @@ store_constructor (exp, target, cleared)
RTX_UNCHANGING_P (to_rtx) = 1;
}
+#ifdef WORD_REGISTER_OPERATIONS
+ /* If this initializes a field that is smaller than a word, at the
+ start of a word, try to widen it to a full word.
+ This special case allows us to output C++ member function
+ initializations in a form that the optimizers can understand. */
+ if (constant
+ && GET_CODE (target) == REG
+ && bitsize < BITS_PER_WORD
+ && bitpos % BITS_PER_WORD == 0
+ && GET_MODE_CLASS (mode) == MODE_INT
+ && TREE_CODE (value) == INTEGER_CST
+ && GET_CODE (exp_size) == CONST_INT
+ && bitpos + BITS_PER_WORD <= INTVAL (exp_size) * BITS_PER_UNIT)
+ {
+ tree type = TREE_TYPE (value);
+ if (TYPE_PRECISION (type) < BITS_PER_WORD)
+ {
+ type = type_for_size (BITS_PER_WORD, TREE_UNSIGNED (type));
+ value = convert (type, value);
+ }
+ if (BYTES_BIG_ENDIAN)
+ value
+ = fold (build (LSHIFT_EXPR, type, value,
+ build_int_2 (BITS_PER_WORD - bitsize, 0)));
+ bitsize = BITS_PER_WORD;
+ mode = word_mode;
+ }
+#endif
store_constructor_field (to_rtx, bitsize, bitpos,
- mode, TREE_VALUE (elt), type, cleared);
+ mode, value, type, cleared);
}
}
else if (TREE_CODE (type) == ARRAY_TYPE)
@@ -4368,11 +4598,15 @@ store_constructor (exp, target, cleared)
In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
ALIGN is the alignment that TARGET is known to have, measured in bytes.
- TOTAL_SIZE is the size in bytes of the structure, or -1 if varying. */
+ TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.
+
+ ALIAS_SET is the alias set for the destination. This value will
+ (in general) be different from that for TARGET, since TARGET is a
+ reference to the containing structure. */
static rtx
store_field (target, bitsize, bitpos, mode, exp, value_mode,
- unsignedp, align, total_size)
+ unsignedp, align, total_size, alias_set)
rtx target;
int bitsize, bitpos;
enum machine_mode mode;
@@ -4381,6 +4615,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
int unsignedp;
int align;
int total_size;
+ int alias_set;
{
HOST_WIDE_INT width_mask = 0;
@@ -4408,15 +4643,15 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
GET_MODE_SIZE (GET_MODE (target)), 0);
rtx blk_object = copy_rtx (object);
- MEM_IN_STRUCT_P (object) = 1;
- MEM_IN_STRUCT_P (blk_object) = 1;
+ MEM_SET_IN_STRUCT_P (object, 1);
+ MEM_SET_IN_STRUCT_P (blk_object, 1);
PUT_MODE (blk_object, BLKmode);
if (bitsize != GET_MODE_BITSIZE (GET_MODE (target)))
emit_move_insn (object, target);
store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0,
- align, total_size);
+ align, total_size, alias_set);
/* Even though we aren't returning target, we need to
give it the updated value. */
@@ -4430,7 +4665,9 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
Use bit-field techniques or SUBREG to store in it. */
if (mode == VOIDmode
- || (mode != BLKmode && ! direct_store[(int) mode])
+ || (mode != BLKmode && ! direct_store[(int) mode]
+ && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
+ && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
|| GET_CODE (target) == REG
|| GET_CODE (target) == SUBREG
/* If the field isn't aligned enough to store as an ordinary memref,
@@ -4530,7 +4767,8 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
plus_constant (addr,
(bitpos
/ BITS_PER_UNIT))));
- MEM_IN_STRUCT_P (to_rtx) = 1;
+ MEM_SET_IN_STRUCT_P (to_rtx, 1);
+ MEM_ALIAS_SET (to_rtx) = alias_set;
return store_expr (exp, to_rtx, value_mode != VOIDmode);
}
@@ -4577,7 +4815,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
tree size_tree = 0;
enum machine_mode mode = VOIDmode;
tree offset = integer_zero_node;
- int alignment = BIGGEST_ALIGNMENT;
+ unsigned int alignment = BIGGEST_ALIGNMENT;
if (TREE_CODE (exp) == COMPONENT_REF)
{
@@ -4594,6 +4832,9 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
else
{
mode = TYPE_MODE (TREE_TYPE (exp));
+ if (mode == BLKmode)
+ size_tree = TYPE_SIZE (TREE_TYPE (exp));
+
*pbitsize = GET_MODE_BITSIZE (mode);
*punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
}
@@ -4660,8 +4901,20 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
index_type = TREE_TYPE (index);
}
+ /* Optimize the special-case of a zero lower bound.
+
+ We convert the low_bound to sizetype to avoid some problems
+ with constant folding. (E.g. suppose the lower bound is 1,
+ and its mode is QI. Without the conversion, (ARRAY
+ +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
+ +INDEX), which becomes (ARRAY+255+INDEX). Oops!)
+
+ But sizetype isn't quite right either (especially if
+ the lowbound is negative). FIXME */
+
if (! integer_zerop (low_bound))
- index = fold (build (MINUS_EXPR, index_type, index, low_bound));
+ index = fold (build (MINUS_EXPR, index_type, index,
+ convert (sizetype, low_bound)));
if (TREE_CODE (index) == INTEGER_CST)
{
@@ -4900,7 +5153,7 @@ init_noncopied_parts (lhs, list)
for (tail = list; tail; tail = TREE_CHAIN (tail))
if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
- else
+ else if (TREE_PURPOSE (tail))
{
tree part = TREE_VALUE (tail);
tree part_type = TREE_TYPE (part);
@@ -5085,13 +5338,19 @@ safe_from_p (x, exp, top_p)
if (save_expr_count >= save_expr_size)
return 0;
save_expr_rewritten[save_expr_count++] = exp;
- TREE_SET_CODE (exp, ERROR_MARK);
nops = tree_code_length[(int) SAVE_EXPR];
for (i = 0; i < nops; i++)
- if (TREE_OPERAND (exp, i) != 0
- && ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
- return 0;
+ {
+ tree operand = TREE_OPERAND (exp, i);
+ if (operand == NULL_TREE)
+ continue;
+ TREE_SET_CODE (exp, ERROR_MARK);
+ if (!safe_from_p (x, operand, 0))
+ return 0;
+ TREE_SET_CODE (exp, SAVE_EXPR);
+ }
+ TREE_SET_CODE (exp, ERROR_MARK);
return 1;
case BIND_EXPR:
@@ -5183,6 +5442,11 @@ check_max_integer_computation_mode (exp)
enum tree_code code = TREE_CODE (exp);
enum machine_mode mode;
+ /* We must allow conversions of constants to MAX_INTEGER_COMPUTATION_MODE. */
+ if (code == NOP_EXPR
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
+ return;
+
/* First check the type of the overall operation. We need only look at
unary, binary and relational operations. */
if (TREE_CODE_CLASS (code) == '1'
@@ -5269,21 +5533,34 @@ expand_expr (exp, target, tmode, modifier)
register rtx op0, op1, temp;
tree type = TREE_TYPE (exp);
int unsignedp = TREE_UNSIGNED (type);
- register enum machine_mode mode = TYPE_MODE (type);
+ register enum machine_mode mode;
register enum tree_code code = TREE_CODE (exp);
optab this_optab;
- /* Use subtarget as the target for operand 0 of a binary operation. */
- rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
- rtx original_target = target;
- int ignore = (target == const0_rtx
- || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
- || code == CONVERT_EXPR || code == REFERENCE_EXPR
- || code == COND_EXPR)
- && TREE_CODE (type) == VOID_TYPE));
+ rtx subtarget, original_target;
+ int ignore;
tree context;
/* Used by check-memory-usage to make modifier read only. */
enum expand_modifier ro_modifier;
+ /* Handle ERROR_MARK before anybody tries to access its type. */
+ if (TREE_CODE (exp) == ERROR_MARK)
+ {
+ op0 = CONST0_RTX (tmode);
+ if (op0 != 0)
+ return op0;
+ return const0_rtx;
+ }
+
+ mode = TYPE_MODE (type);
+ /* Use subtarget as the target for operand 0 of a binary operation. */
+ subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
+ original_target = target;
+ ignore = (target == const0_rtx
+ || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
+ || code == CONVERT_EXPR || code == REFERENCE_EXPR
+ || code == COND_EXPR)
+ && TREE_CODE (type) == VOID_TYPE));
+
/* Make a read-only version of the modifier. */
if (modifier == EXPAND_NORMAL || modifier == EXPAND_SUM
|| modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER)
@@ -5343,7 +5620,15 @@ expand_expr (exp, target, tmode, modifier)
}
#ifdef MAX_INTEGER_COMPUTATION_MODE
- if (target)
+ if (target
+ && TREE_CODE (exp) != INTEGER_CST
+ && TREE_CODE (exp) != PARM_DECL
+ && TREE_CODE (exp) != ARRAY_REF
+ && TREE_CODE (exp) != COMPONENT_REF
+ && TREE_CODE (exp) != BIT_FIELD_REF
+ && TREE_CODE (exp) != INDIRECT_REF
+ && TREE_CODE (exp) != CALL_EXPR
+ && TREE_CODE (exp) != VAR_DECL)
{
enum machine_mode mode = GET_MODE (target);
@@ -5352,7 +5637,15 @@ expand_expr (exp, target, tmode, modifier)
fatal ("unsupported wide integer operation");
}
- if (GET_MODE_CLASS (tmode) == MODE_INT
+ if (TREE_CODE (exp) != INTEGER_CST
+ && TREE_CODE (exp) != PARM_DECL
+ && TREE_CODE (exp) != ARRAY_REF
+ && TREE_CODE (exp) != COMPONENT_REF
+ && TREE_CODE (exp) != BIT_FIELD_REF
+ && TREE_CODE (exp) != INDIRECT_REF
+ && TREE_CODE (exp) != VAR_DECL
+ && TREE_CODE (exp) != CALL_EXPR
+ && GET_MODE_CLASS (tmode) == MODE_INT
&& tmode > MAX_INTEGER_COMPUTATION_MODE)
fatal ("unsupported wide integer operation");
@@ -5388,9 +5681,13 @@ expand_expr (exp, target, tmode, modifier)
p->forced_labels);
pop_obstacks ();
}
- else if (modifier == EXPAND_INITIALIZER)
- forced_labels = gen_rtx_EXPR_LIST (VOIDmode,
- label_rtx (exp), forced_labels);
+ else
+ {
+ if (modifier == EXPAND_INITIALIZER)
+ forced_labels = gen_rtx_EXPR_LIST (VOIDmode,
+ label_rtx (exp),
+ forced_labels);
+ }
temp = gen_rtx_MEM (FUNCTION_MODE,
gen_rtx_LABEL_REF (Pmode, label_rtx (exp)));
if (function != current_function_decl
@@ -5421,13 +5718,16 @@ expand_expr (exp, target, tmode, modifier)
pop_obstacks ();
}
- /* Only check automatic variables. Currently, function arguments are
- not checked (this can be done at compile-time with prototypes).
- Aggregates are not checked. */
- if (flag_check_memory_usage && code == VAR_DECL
+ /* Although static-storage variables start off initialized, according to
+ ANSI C, a memcpy could overwrite them with uninitialized values. So
+ we check them too. This also lets us check for read-only variables
+ accessed via a non-const declaration, in case it won't be detected
+ any other way (e.g., in an embedded system or OS kernel without
+ memory protection).
+
+ Aggregates are not checked here; they're handled elsewhere. */
+ if (current_function_check_memory_usage && code == VAR_DECL
&& GET_CODE (DECL_RTL (exp)) == MEM
- && DECL_CONTEXT (exp) != NULL_TREE
- && ! TREE_STATIC (exp)
&& ! AGGREGATE_TYPE_P (TREE_TYPE (exp)))
{
enum memory_use_mode memory_usage;
@@ -5435,7 +5735,7 @@ expand_expr (exp, target, tmode, modifier)
if (memory_usage != MEMORY_USE_DONT)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- XEXP (DECL_RTL (exp), 0), ptr_mode,
+ XEXP (DECL_RTL (exp), 0), Pmode,
GEN_INT (int_size_in_bytes (type)),
TYPE_MODE (sizetype),
GEN_INT (memory_usage),
@@ -5775,11 +6075,30 @@ expand_expr (exp, target, tmode, modifier)
placeholder_list = TREE_CHAIN (placeholder_list);
return target;
+ case GOTO_EXPR:
+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL)
+ expand_goto (TREE_OPERAND (exp, 0));
+ else
+ expand_computed_goto (TREE_OPERAND (exp, 0));
+ return const0_rtx;
+
case EXIT_EXPR:
expand_exit_loop_if_false (NULL_PTR,
invert_truthvalue (TREE_OPERAND (exp, 0)));
return const0_rtx;
+ case LABELED_BLOCK_EXPR:
+ if (LABELED_BLOCK_BODY (exp))
+ expand_expr_stmt (LABELED_BLOCK_BODY (exp));
+ emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
+ return const0_rtx;
+
+ case EXIT_BLOCK_EXPR:
+ if (EXIT_BLOCK_RETURN (exp))
+ sorry ("returned value in block_exit_expr");
+ expand_goto (LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (exp)));
+ return const0_rtx;
+
case LOOP_EXPR:
push_temp_slots ();
expand_start_loop (1);
@@ -5858,10 +6177,9 @@ expand_expr (exp, target, tmode, modifier)
&& ! (target != 0 && safe_from_p (target, exp, 1)))
|| TREE_ADDRESSABLE (exp)
|| (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && (move_by_pieces_ninsns
- (TREE_INT_CST_LOW (TYPE_SIZE (type))/BITS_PER_UNIT,
- TYPE_ALIGN (type) / BITS_PER_UNIT)
- > MOVE_RATIO)
+ && (!MOVE_BY_PIECES_P
+ (TREE_INT_CST_LOW (TYPE_SIZE (type))/BITS_PER_UNIT,
+ TYPE_ALIGN (type) / BITS_PER_UNIT))
&& ! mostly_zeros_p (exp))))
|| (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
{
@@ -5925,7 +6243,7 @@ expand_expr (exp, target, tmode, modifier)
op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address (mode, op0);
- if (flag_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (exp)))
+ if (current_function_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (exp)))
{
enum memory_use_mode memory_usage;
memory_usage = get_memory_usage_from_modifier (modifier);
@@ -5934,7 +6252,7 @@ expand_expr (exp, target, tmode, modifier)
{
in_check_memory_usage = 1;
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- op0, ptr_mode,
+ op0, Pmode,
GEN_INT (int_size_in_bytes (type)),
TYPE_MODE (sizetype),
GEN_INT (memory_usage),
@@ -5953,26 +6271,7 @@ expand_expr (exp, target, tmode, modifier)
|| (TREE_CODE (exp1) == ADDR_EXPR
&& (exp2 = TREE_OPERAND (exp1, 0))
&& AGGREGATE_TYPE_P (TREE_TYPE (exp2))))
- MEM_IN_STRUCT_P (temp) = 1;
-
- /* If the pointer is actually a REFERENCE_TYPE, this could be pointing
- into some aggregate too. In theory we could fold this into the
- previous check and use rtx_addr_varies_p there too.
-
- However, this seems safer. */
- if (!MEM_IN_STRUCT_P (temp)
- && (TREE_CODE (TREE_TYPE (exp1)) == REFERENCE_TYPE
- /* This may have been an array reference to the first element
- that was optimized away from being an addition. */
- || (TREE_CODE (exp1) == NOP_EXPR
- && ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp1, 0)))
- == REFERENCE_TYPE)
- || ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp1, 0)))
- == POINTER_TYPE)
- && (AGGREGATE_TYPE_P
- (TREE_TYPE (TREE_TYPE
- (TREE_OPERAND (exp1, 0))))))))))
- MEM_IN_STRUCT_P (temp) = ! rtx_addr_varies_p (temp);
+ MEM_SET_IN_STRUCT_P (temp, 1);
MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile;
MEM_ALIAS_SET (temp) = get_alias_set (exp);
@@ -6195,8 +6494,11 @@ expand_expr (exp, target, tmode, modifier)
#endif
}
+ /* A constant address in TO_RTX can have VOIDmode, we must not try
+ to call force_reg for that case. Avoid that case. */
if (GET_CODE (op0) == MEM
&& GET_MODE (op0) == BLKmode
+ && GET_MODE (XEXP (op0, 0)) != VOIDmode
&& bitsize
&& (bitpos % bitsize) == 0
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
@@ -6229,7 +6531,7 @@ expand_expr (exp, target, tmode, modifier)
}
/* Check the access. */
- if (flag_check_memory_usage && GET_CODE (op0) == MEM)
+ if (current_function_check_memory_usage && GET_CODE (op0) == MEM)
{
enum memory_use_mode memory_usage;
memory_usage = get_memory_usage_from_modifier (modifier);
@@ -6245,7 +6547,7 @@ expand_expr (exp, target, tmode, modifier)
/* Check the access right of the pointer. */
if (size > BITS_PER_UNIT)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- to, ptr_mode,
+ to, Pmode,
GEN_INT (size / BITS_PER_UNIT),
TYPE_MODE (sizetype),
GEN_INT (memory_usage),
@@ -6271,7 +6573,7 @@ expand_expr (exp, target, tmode, modifier)
/* If the field isn't aligned enough to fetch as a memref,
fetch it as a bit field. */
|| (SLOW_UNALIGNED_ACCESS
- && ((TYPE_ALIGN (TREE_TYPE (tem)) < GET_MODE_ALIGNMENT (mode))
+ && ((TYPE_ALIGN (TREE_TYPE (tem)) < (unsigned int) GET_MODE_ALIGNMENT (mode))
|| (bitpos % GET_MODE_ALIGNMENT (mode) != 0))))))
{
enum machine_mode ext_mode = mode;
@@ -6331,7 +6633,7 @@ expand_expr (exp, target, tmode, modifier)
emit_move_insn (new, op0);
op0 = copy_rtx (new);
PUT_MODE (op0, BLKmode);
- MEM_IN_STRUCT_P (op0) = 1;
+ MEM_SET_IN_STRUCT_P (op0, 1);
}
return op0;
@@ -6358,7 +6660,7 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (XEXP (op0, 0)) == REG)
mark_reg_pointer (XEXP (op0, 0), alignment);
- MEM_IN_STRUCT_P (op0) = 1;
+ MEM_SET_IN_STRUCT_P (op0, 1);
MEM_VOLATILE_P (op0) |= volatilep;
if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
|| modifier == EXPAND_CONST_ADDRESS
@@ -6430,17 +6732,15 @@ expand_expr (exp, target, tmode, modifier)
if (! (GET_CODE (index_val) == CONST_INT
&& GET_CODE (lo_r) == CONST_INT))
{
- emit_cmp_insn (index_val, lo_r, LT, NULL_RTX,
- GET_MODE (index_val), iunsignedp, 0);
- emit_jump_insn (gen_blt (op1));
+ emit_cmp_and_jump_insns (index_val, lo_r, LT, NULL_RTX,
+ GET_MODE (index_val), iunsignedp, 0, op1);
}
if (! (GET_CODE (index_val) == CONST_INT
&& GET_CODE (hi_r) == CONST_INT))
{
- emit_cmp_insn (index_val, hi_r, GT, NULL_RTX,
- GET_MODE (index_val), iunsignedp, 0);
- emit_jump_insn (gen_bgt (op1));
+ emit_cmp_and_jump_insns (index_val, hi_r, GT, NULL_RTX,
+ GET_MODE (index_val), iunsignedp, 0, op1);
}
/* Calculate the element number of bit zero in the first word
@@ -6500,7 +6800,6 @@ expand_expr (exp, target, tmode, modifier)
case CLEANUP_POINT_EXPR:
{
- extern int temp_slot_level;
/* Start a new binding layer that will keep track of all cleanup
actions to be performed. */
expand_start_bindings (0);
@@ -6556,7 +6855,8 @@ expand_expr (exp, target, tmode, modifier)
store_field (target, GET_MODE_BITSIZE (TYPE_MODE (valtype)), 0,
TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
VOIDmode, 0, 1,
- int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0))));
+ int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0))),
+ 0);
else
abort ();
@@ -6983,7 +7283,7 @@ expand_expr (exp, target, tmode, modifier)
if (TREE_UNSIGNED (type))
return op0;
- return expand_abs (mode, op0, target, unsignedp,
+ return expand_abs (mode, op0, target,
safe_from_p (target, TREE_OPERAND (exp, 0), 1));
case MAX_EXPR:
@@ -7137,9 +7437,8 @@ expand_expr (exp, target, tmode, modifier)
temp = copy_to_reg (temp);
op1 = gen_label_rtx ();
- emit_cmp_insn (temp, const0_rtx, EQ, NULL_RTX,
- GET_MODE (temp), unsignedp, 0);
- emit_jump_insn (gen_beq (op1));
+ emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX,
+ GET_MODE (temp), unsignedp, 0, op1);
emit_move_insn (temp, const1_rtx);
emit_label (op1);
return temp;
@@ -7657,6 +7956,13 @@ expand_expr (exp, target, tmode, modifier)
return temp;
}
+ case RETURN_EXPR:
+ if (!TREE_OPERAND (exp, 0))
+ expand_null_return ();
+ else
+ expand_return (TREE_OPERAND (exp, 0));
+ return const0_rtx;
+
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
return expand_increment (exp, 0, ignore);
@@ -7861,6 +8167,47 @@ expand_expr (exp, target, tmode, modifier)
return op0;
}
+ case TRY_FINALLY_EXPR:
+ {
+ tree try_block = TREE_OPERAND (exp, 0);
+ tree finally_block = TREE_OPERAND (exp, 1);
+ rtx finally_label = gen_label_rtx ();
+ rtx done_label = gen_label_rtx ();
+ rtx return_link = gen_reg_rtx (Pmode);
+ tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node,
+ (tree) finally_label, (tree) return_link);
+ TREE_SIDE_EFFECTS (cleanup) = 1;
+
+ /* Start a new binding layer that will keep track of all cleanup
+ actions to be performed. */
+ expand_start_bindings (0);
+
+ target_temp_slot_level = temp_slot_level;
+
+ expand_decl_cleanup (NULL_TREE, cleanup);
+ op0 = expand_expr (try_block, target, tmode, modifier);
+
+ preserve_temp_slots (op0);
+ expand_end_bindings (NULL_TREE, 0, 0);
+ emit_jump (done_label);
+ emit_label (finally_label);
+ expand_expr (finally_block, const0_rtx, VOIDmode, 0);
+ emit_indirect_jump (return_link);
+ emit_label (done_label);
+ return op0;
+ }
+
+ case GOTO_SUBROUTINE_EXPR:
+ {
+ rtx subr = (rtx) TREE_OPERAND (exp, 0);
+ rtx return_link = *(rtx *) &TREE_OPERAND (exp, 1);
+ rtx return_address = gen_label_rtx ();
+ emit_move_insn (return_link, gen_rtx_LABEL_REF (Pmode, return_address));
+ emit_jump (subr);
+ emit_label (return_address);
+ return const0_rtx;
+ }
+
case POPDCC_EXPR:
{
rtx dcc = get_dynamic_cleanup_chain ();
@@ -7875,12 +8222,6 @@ expand_expr (exp, target, tmode, modifier)
return const0_rtx;
}
- case ERROR_MARK:
- op0 = CONST0_RTX (tmode);
- if (op0 != 0)
- return op0;
- return const0_rtx;
-
default:
return (*lang_expand_expr) (exp, original_target, tmode, modifier);
}
@@ -8181,7 +8522,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
(gen_rtx_MEM (Pmode,
plus_constant (buf_addr,
GET_MODE_SIZE (Pmode)))),
- gen_rtx_LABEL_REF (Pmode, lab1));
+ force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1)));
stack_save = gen_rtx_MEM (sa_mode,
plus_constant (buf_addr,
@@ -8200,8 +8541,13 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
emit_barrier ();
emit_label (lab1);
- /* Tell flow about the strange goings on. */
+ /* Tell flow about the strange goings on. Putting `lab1' on
+ `nonlocal_goto_handler_labels' to indicates that function
+ calls may traverse the arc back to this label. */
+
current_function_has_nonlocal_label = 1;
+ nonlocal_goto_handler_labels =
+ gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
/* Clobber the FP when we get here, so we have to make sure it's
marked as used by this function. */
@@ -8223,7 +8569,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
if (fixed_regs[ARG_POINTER_REGNUM])
{
#ifdef ELIMINABLE_REGS
- int i;
+ size_t i;
static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
@@ -8369,7 +8715,7 @@ get_memory_rtx (exp)
is_aggregate = AGGREGATE_TYPE_P (type);
}
- MEM_IN_STRUCT_P (mem) = is_aggregate;
+ MEM_SET_IN_STRUCT_P (mem, is_aggregate);
return mem;
}
@@ -8467,7 +8813,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
/* Check the results by default. But if flag_fast_math is turned on,
then assume sqrt will always be called with valid arguments. */
- if (! flag_fast_math)
+ if (flag_errno_math && ! flag_fast_math)
{
/* Don't define the builtin FP instructions
if your machine is not IEEE. */
@@ -8478,8 +8824,8 @@ expand_builtin (exp, target, subtarget, mode, ignore)
/* Test the result; if it is NaN, set errno=EDOM because
the argument was not in the domain. */
- emit_cmp_insn (target, target, EQ, 0, GET_MODE (target), 0, 0);
- emit_jump_insn (gen_beq (lab1));
+ emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
+ 0, 0, lab1);
#ifdef TARGET_EDOM
{
@@ -8792,36 +9138,37 @@ expand_builtin (exp, target, subtarget, mode, ignore)
else
{
tree arg = TREE_VALUE (arglist);
+ rtx tmp;
+ /* We return 1 for a numeric type that's known to be a constant
+ value at compile-time or for an aggregate type that's a
+ literal constant. */
STRIP_NOPS (arg);
- if (really_constant_p (arg)
+
+ /* If we know this is a constant, emit the constant of one. */
+ if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'c'
+ || (TREE_CODE (arg) == CONSTRUCTOR
+ && TREE_CONSTANT (arg))
|| (TREE_CODE (arg) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST))
return const1_rtx;
- /* Only emit CONSTANT_P_RTX if CSE will be run.
- Moreover, we don't want to expand trees that have side effects,
- as the original __builtin_constant_p did not evaluate its
- argument at all, and we would break existing usage by changing
- this. This quirk was generally useful, eliminating a bit of hair
- in the writing of the macros that use this function. Now the
- same thing can be better accomplished in an inline function. */
+ /* If we aren't going to be running CSE or this expression
+ has side effects, show we don't know it to be a constant.
+ Likewise if it's a pointer or aggregate type since in those
+ case we only want literals, since those are only optimized
+ when generating RTL, not later. */
+ if (TREE_SIDE_EFFECTS (arg) || cse_not_expected
+ || AGGREGATE_TYPE_P (TREE_TYPE (arg))
+ || POINTER_TYPE_P (TREE_TYPE (arg)))
+ return const0_rtx;
- if (! cse_not_expected && ! TREE_SIDE_EFFECTS (arg))
- {
- /* Lazy fixup of old code: issue a warning and fail the test. */
- if (! can_handle_constant_p)
- {
- warning ("Delayed evaluation of __builtin_constant_p not supported on this target.");
- warning ("Please report this as a bug to egcs-bugs@egcs.cygnus.com.");
- return const0_rtx;
- }
- return gen_rtx_CONSTANT_P_RTX (TYPE_MODE (integer_type_node),
- expand_expr (arg, NULL_RTX,
- VOIDmode, 0));
- }
+ /* Otherwise, emit (constant_p_rtx (ARG)) and let CSE get a
+ chance to see if it can deduce whether ARG is constant. */
- return const0_rtx;
+ tmp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+ tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
+ return tmp;
}
case BUILT_IN_FRAME_ADDRESS:
@@ -8864,8 +9211,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
return tem;
- if (GET_CODE (tem) != REG)
- tem = copy_to_reg (tem);
+ if (GET_CODE (tem) != REG
+ && ! CONSTANT_P (tem))
+ tem = copy_to_mode_reg (Pmode, tem);
return tem;
}
@@ -8973,9 +9321,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
src_rtx = copy_to_mode_reg (Pmode, src_rtx);
/* Check the string is readable and has an end. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_check_str_libfunc, 1, VOIDmode, 2,
- src_rtx, ptr_mode,
+ src_rtx, Pmode,
GEN_INT (MEMORY_USE_RO),
TYPE_MODE (integer_type_node));
@@ -9066,10 +9414,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
/* Just copy the rights of SRC to the rights of DEST. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
- XEXP (dest_mem, 0), ptr_mode,
- XEXP (src_mem, 0), ptr_mode,
+ XEXP (dest_mem, 0), Pmode,
+ XEXP (src_mem, 0), Pmode,
len_rtx, TYPE_MODE (sizetype));
/* Copy word part most expediently. */
@@ -9137,9 +9485,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
dest_mem = get_memory_rtx (dest);
/* Just check DST is writable and mark it as readable. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
- XEXP (dest_mem, 0), ptr_mode,
+ XEXP (dest_mem, 0), Pmode,
len_rtx, TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
@@ -9163,7 +9511,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break;
/* If we need to check memory accesses, call the library function. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
break;
if (arglist == 0
@@ -9219,7 +9567,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break;
/* If we need to check memory accesses, call the library function. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
break;
if (arglist == 0
@@ -9335,10 +9683,8 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_UNWIND_INIT:
expand_builtin_unwind_init ();
return const0_rtx;
- case BUILT_IN_FP:
- return frame_pointer_rtx;
- case BUILT_IN_SP:
- return stack_pointer_rtx;
+ case BUILT_IN_DWARF_CFA:
+ return virtual_cfa_rtx;
#ifdef DWARF2_UNWIND_INFO
case BUILT_IN_DWARF_FP_REGNUM:
return expand_builtin_dwarf_fp_regnum ();
@@ -9349,16 +9695,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
case BUILT_IN_EXTRACT_RETURN_ADDR:
return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
- case BUILT_IN_SET_RETURN_ADDR_REG:
- expand_builtin_set_return_addr_reg (TREE_VALUE (arglist));
- return const0_rtx;
- case BUILT_IN_EH_STUB_OLD:
- return expand_builtin_eh_stub_old ();
- case BUILT_IN_EH_STUB:
- return expand_builtin_eh_stub ();
- case BUILT_IN_SET_EH_REGS:
- expand_builtin_set_eh_regs (TREE_VALUE (arglist),
- TREE_VALUE (TREE_CHAIN (arglist)));
+ case BUILT_IN_EH_RETURN:
+ expand_builtin_eh_return (TREE_VALUE (arglist),
+ TREE_VALUE (TREE_CHAIN (arglist)),
+ TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
return const0_rtx;
default: /* just do library call, if unknown builtin */
@@ -10056,7 +10396,7 @@ expand_increment (exp, post, ignore)
/* Increment however we can. */
op1 = expand_binop (mode, this_optab, value, op1,
- flag_check_memory_usage ? NULL_RTX : op0,
+ current_function_check_memory_usage ? NULL_RTX : op0,
TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
/* Make sure the value is stored into OP0. */
if (op1 != op0)
@@ -10834,7 +11174,8 @@ do_jump_for_compare (comparison, if_false_label, if_true_label)
if (if_true_label)
{
if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
- emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_true_label));
+ emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)])
+ (if_true_label));
else
abort ();
@@ -10843,52 +11184,80 @@ do_jump_for_compare (comparison, if_false_label, if_true_label)
}
else if (if_false_label)
{
- rtx insn;
- rtx prev = get_last_insn ();
- rtx branch = 0;
+ rtx first = get_last_insn (), insn, branch;
+ int br_count;
/* 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
branch is not the last insn written, abort. If we can't invert
the branch, emit make a true label, redirect this jump to that,
emit a jump to the false label and define the true label. */
+ /* ??? Note that we wouldn't have to do any of this nonsense if
+ we passed both labels into a combined compare-and-branch.
+ Ah well, jump threading does a good job of repairing the damage. */
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
abort ();
- /* Here we get the first insn that was just emitted. It used to be the
+ /* Here we get the first insn that was just emitted. It used to be the
case that, on some machines, emitting the branch would discard
the previous compare insn and emit a replacement. This isn't
- done anymore, but abort if we see that PREV is deleted. */
+ done anymore, but abort if we see that FIRST is deleted. */
- if (prev == 0)
- insn = get_insns ();
- else if (INSN_DELETED_P (prev))
+ if (first == 0)
+ first = get_insns ();
+ else if (INSN_DELETED_P (first))
abort ();
else
- insn = NEXT_INSN (prev);
+ first = NEXT_INSN (first);
- for (; insn; insn = NEXT_INSN (insn))
+ /* Look for multiple branches in this sequence, as might be generated
+ for a multi-word integer comparison. */
+
+ br_count = 0;
+ branch = NULL_RTX;
+ for (insn = first; insn ; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == JUMP_INSN)
{
- if (branch)
- abort ();
branch = insn;
+ br_count += 1;
}
- if (branch != get_last_insn ())
- abort ();
+ /* If we've got one branch at the end of the sequence,
+ we can try to reverse it. */
- JUMP_LABEL (branch) = if_false_label;
- if (! invert_jump (branch, if_false_label))
+ if (br_count == 1 && NEXT_INSN (branch) == NULL_RTX)
{
- if_true_label = gen_label_rtx ();
- redirect_jump (branch, if_true_label);
- emit_jump (if_false_label);
- emit_label (if_true_label);
+ rtx insn_label;
+ insn_label = XEXP (condjump_label (branch), 0);
+ JUMP_LABEL (branch) = insn_label;
+
+ if (insn_label != if_false_label)
+ abort ();
+
+ if (invert_jump (branch, if_false_label))
+ return;
}
+
+ /* Multiple branches, or reversion failed. Convert to branches
+ around an unconditional jump. */
+
+ if_true_label = gen_label_rtx ();
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ rtx insn_label;
+ insn_label = XEXP (condjump_label (insn), 0);
+ JUMP_LABEL (insn) = insn_label;
+
+ if (insn_label == if_false_label)
+ redirect_jump (insn, if_true_label);
+ }
+ emit_jump (if_false_label);
+ emit_label (if_true_label);
}
}
@@ -10906,14 +11275,22 @@ compare (exp, signed_code, unsigned_code)
register tree exp;
enum rtx_code signed_code, unsigned_code;
{
- register rtx op0
- = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
- register rtx op1
- = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
- register tree type = TREE_TYPE (TREE_OPERAND (exp, 0));
- register enum machine_mode mode = TYPE_MODE (type);
- int unsignedp = TREE_UNSIGNED (type);
- enum rtx_code code = unsignedp ? unsigned_code : signed_code;
+ register rtx op0, op1;
+ register tree type;
+ register enum machine_mode mode;
+ int unsignedp;
+ enum rtx_code code;
+
+ /* Don't crash if the comparison was erroneous. */
+ op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
+ return op0;
+
+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
+ type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ mode = TYPE_MODE (type);
+ unsignedp = TREE_UNSIGNED (type);
+ code = unsignedp ? unsigned_code : signed_code;
#ifdef HAVE_canonicalize_funcptr_for_compare
/* If function pointers need to be "canonicalized" before they can
@@ -11309,8 +11686,8 @@ do_tablejump (index, mode, range, table_label, default_label)
or equal to the minimum value of the range and less than or equal to
the maximum value of the range. */
- emit_cmp_insn (index, range, GTU, NULL_RTX, mode, 1, 0);
- emit_jump_insn (gen_bgtu (default_label));
+ emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
+ 0, default_label);
/* If index is in range, it must fit in Pmode.
Convert to Pmode so we can index with it. */
diff --git a/contrib/gcc/expr.h b/contrib/gcc/expr.h
index a53a036..55e82e6 100644
--- a/contrib/gcc/expr.h
+++ b/contrib/gcc/expr.h
@@ -1,5 +1,5 @@
/* Definitions for code generation pass of GNU compiler.
- Copyright (C) 1987, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -91,20 +91,45 @@ extern int current_function_uses_pic_offset_table;
/* The arg pointer hard register, or the pseudo into which it was copied. */
extern rtx current_function_internal_arg_pointer;
-/* Nonzero means stack pops must not be deferred, and deferred stack
- pops must not be output. It is nonzero inside a function call,
- inside a conditional expression, inside a statement expression,
- and in other cases as well. */
+/* This is nonzero if memory access checking be enabled in the current
+ function. */
+extern int current_function_check_memory_usage;
+
+/* Under some ABIs, it is the caller's responsibility to pop arguments
+ pushed for function calls. A naive implementation would simply pop
+ the arguments immediately after each call. However, if several
+ function calls are made in a row, it is typically cheaper to pop
+ all the arguments after all of the calls are complete since a
+ single pop instruction can be used. Therefore, GCC attempts to
+ defer popping the arguments until absolutely necessary. (For
+ example, at the end of a conditional, the arguments must be popped,
+ since code outside the conditional won't know whether or not the
+ arguments need to be popped.)
+
+ When INHIBIT_DEFER_POP is non-zero, however, the compiler does not
+ attempt to defer pops. Instead, the stack is popped immediately
+ after each call. Rather then setting this variable directly, use
+ NO_DEFER_POP and OK_DEFER_POP. */
extern int inhibit_defer_pop;
+/* Prevent the compiler from deferring stack pops. See
+ inhibit_defer_pop for more information. */
+#define NO_DEFER_POP (inhibit_defer_pop += 1)
+
+/* Allow the compiler to defer stack pops. See inhibit_defer_pop for
+ more information. */
+#define OK_DEFER_POP (inhibit_defer_pop -= 1)
+
/* Number of function calls seen so far in current function. */
extern int function_call_count;
-/* RTX for stack slot that holds the current handler for nonlocal gotos.
+/* List (chain of EXPR_LIST) of stack slots that hold the current handlers
+ for nonlocal gotos. There is one for every nonlocal label in the function;
+ this list matches the one in nonlocal_labels.
Zero when function does not have nonlocal labels. */
-extern rtx nonlocal_goto_handler_slot;
+extern rtx nonlocal_goto_handler_slots;
/* RTX for stack slot that holds the stack pointer value to restore
for a nonlocal goto.
@@ -120,9 +145,6 @@ extern rtx nonlocal_goto_stack_level;
extern tree nonlocal_labels;
#endif
-#define NO_DEFER_POP (inhibit_defer_pop += 1)
-#define OK_DEFER_POP (inhibit_defer_pop -= 1)
-
/* Number of units that we should eventually pop off the stack.
These are the arguments to function calls that have already returned. */
extern int pending_stack_adjust;
@@ -210,6 +232,17 @@ enum direction {none, upward, downward}; /* Value has this type. */
#define STRICT_ARGUMENT_NAMING 0
#endif
+/* Provide a default value for PRETEND_OUTGOING_VARARGS_NAMED. */
+#ifdef SETUP_INCOMING_VARARGS
+#ifndef PRETEND_OUTGOING_VARARGS_NAMED
+#define PRETEND_OUTGOING_VARARGS_NAMED 1
+#endif
+#else
+/* It is an error to define PRETEND_OUTGOING_VARARGS_NAMED without
+ defining SETUP_INCOMING_VARARGS. */
+#define PRETEND_OUTGOING_VARARGS_NAMED 0
+#endif
+
/* Nonzero if we do not know how to pass TYPE solely in registers.
We cannot do so in the following cases:
@@ -437,11 +470,13 @@ extern rtx memset_libfunc;
extern rtx bzero_libfunc;
extern rtx throw_libfunc;
+extern rtx rethrow_libfunc;
extern rtx sjthrow_libfunc;
extern rtx sjpopnthrow_libfunc;
extern rtx terminate_libfunc;
extern rtx setjmp_libfunc;
extern rtx longjmp_libfunc;
+extern rtx eh_rtime_match_libfunc;
extern rtx eqhf2_libfunc;
extern rtx nehf2_libfunc;
@@ -532,6 +567,10 @@ extern rtx chkr_set_right_libfunc;
extern rtx chkr_copy_bitmap_libfunc;
extern rtx chkr_check_exec_libfunc;
extern rtx chkr_check_str_libfunc;
+
+/* For instrument-functions. */
+extern rtx profile_function_entry_libfunc;
+extern rtx profile_function_exit_libfunc;
typedef rtx (*rtxfun) PROTO ((rtx));
@@ -576,7 +615,7 @@ extern int expand_twoval_binop PROTO((optab, rtx, rtx, rtx, rtx, int));
extern rtx expand_unop PROTO((enum machine_mode, optab, rtx, rtx, int));
/* Expand the absolute value operation. */
-extern rtx expand_abs PROTO((enum machine_mode, rtx, rtx, int, int));
+extern rtx expand_abs PROTO((enum machine_mode, rtx, rtx, int));
/* Expand the complex absolute value operation. */
extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int));
@@ -602,6 +641,11 @@ extern void emit_0_to_1_insn PROTO((rtx));
extern void emit_cmp_insn PROTO((rtx, rtx, enum rtx_code, rtx,
enum machine_mode, int, int));
+/* Emit a pair of rtl insns to compare two rtx's and to jump
+ to a label if the comparison is true. */
+extern void emit_cmp_and_jump_insns PROTO((rtx, rtx, enum rtx_code, rtx,
+ enum machine_mode, int, int, rtx));
+
/* Nonzero if a compare of mode MODE can be done straightforwardly
(without splitting it into pieces). */
extern int can_compare_p PROTO((enum machine_mode));
@@ -699,6 +743,9 @@ extern rtx protect_from_queue PROTO((rtx, int));
/* Perform all the pending incrementations. */
extern void emit_queue PROTO((void));
+/* Tell if something has a queued subexpression. */
+extern int queued_subexp_p PROTO((rtx));
+
/* Emit some rtl insns to move data between rtx's, converting machine modes.
Both modes must be floating or both fixed. */
extern void convert_move PROTO((rtx, rtx, int));
@@ -727,6 +774,11 @@ extern void emit_group_load PROTO((rtx, rtx, int, int));
PARALLEL. */
extern void emit_group_store PROTO((rtx, rtx, int, int));
+#ifdef TREE_CODE
+/* Copy BLKmode object from a set of registers. */
+extern rtx copy_blkmode_from_reg PROTO((rtx,rtx,tree));
+#endif
+
/* Mark REG as holding a parameter for the next CALL_INSN. */
extern void use_reg PROTO((rtx *, rtx));
/* Mark NREGS consecutive regs, starting at REGNO, as holding parameters
@@ -963,6 +1015,14 @@ extern rtx (*lang_expand_expr) PROTO ((union tree_node *, rtx,
enum machine_mode,
enum expand_modifier modifier));
+#ifdef TREE_CODE
+/* Hook called by output_constant for language-specific tree codes.
+ It is up to the language front-end to install a hook if it has any
+ such codes that output_constant needs to know about. Returns a
+ language-independent constant equivalent to its input. */
+extern tree (*lang_expand_constant) PROTO((tree));
+#endif
+
extern void init_all_optabs PROTO ((void));
extern void init_mov_optab PROTO ((void));
extern void do_jump_by_parts_equality_rtx PROTO((rtx, rtx, rtx));
diff --git a/contrib/gcc/extend.texi b/contrib/gcc/extend.texi
index 5cf1b24..f969f65 100644
--- a/contrib/gcc/extend.texi
+++ b/contrib/gcc/extend.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988,89,92,93,94,96 Free Software Foundation, Inc.
+@c Copyright (C) 1988,89,92,93,94,96,99 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -33,6 +33,7 @@ C++ Language}, for extensions that apply @emph{only} to C++.
* Conditionals:: Omitting the middle operand of a @samp{?:} expression.
* Long Long:: Double-word integers---@code{long long int}.
* Complex:: Data types for complex numbers.
+* Hex Floats:: Hexadecimal floating-point constants.
* Zero Length:: Zero-length arrays.
* Variable Length:: Arrays whose length is computed at run time.
* Macro Varargs:: Macros with variable number of arguments.
@@ -63,6 +64,8 @@ C++ Language}, for extensions that apply @emph{only} to C++.
* Function Names:: Printable strings which are the name of the current
function.
* Return Address:: Getting the return or frame address of a function.
+* Other Builtins:: Other built-in functions.
+* Deprecated Features:: Things might disappear from g++.
@end menu
@end ifset
@ifclear INTERNALS
@@ -78,6 +81,7 @@ C++ Language}, for extensions that apply @emph{only} to C++.
* Conditionals:: Omitting the middle operand of a @samp{?:} expression.
* Long Long:: Double-word integers---@code{long long int}.
* Complex:: Data types for complex numbers.
+* Hex Floats:: Hexadecimal floating-point constants.
* Zero Length:: Zero-length arrays.
* Variable Length:: Arrays whose length is computed at run time.
* Macro Varargs:: Macros with variable number of arguments.
@@ -109,6 +113,7 @@ C++ Language}, for extensions that apply @emph{only} to C++.
* Function Names:: Printable strings which are the name of the current
function.
* Return Address:: Getting the return or frame address of a function.
+* Deprecated Features:: Things might disappear from g++.
@end menu
@end ifclear
@@ -791,6 +796,24 @@ examine and set these two fictitious variables with your debugger.
A future version of GDB will know how to recognize such pairs and treat
them as a single variable with a complex type.
+@node Hex Floats
+@section Hex Floats
+@cindex hex floats
+GNU CC recognizes floating-point numbers written not only in the usual
+decimal notation, such as @code{1.55e1}, but also numbers such as
+@code{0x1.fp3} written in hexadecimal format. In that format the
+@code{0x} hex introducer and the @code{p} or @code{P} exponent field are
+mandatory. The exponent is a decimal number that indicates the power of
+2 by which the significand part will be multiplied. Thus @code{0x1.f} is
+1 15/16, @code{p3} multiplies it by 8, and the value of @code{0x1.fp3}
+is the same as @code{1.55e1}.
+
+Unlike for floating-point numbers in the decimal notation the exponent
+is always required in the hexadecimal notation. Otherwise the compiler
+would not be able to resolve the ambiguity of, e.g., @code{0x1.f}. This
+could mean @code{1.0f} or @code{1.9375} since @code{f} is also the
+extension for floating-point constants of type @code{float}.
+
@node Zero Length
@section Arrays of Length Zero
@cindex arrays of length zero
@@ -1286,8 +1309,9 @@ carefully.
The keyword @code{__attribute__} allows you to specify special
attributes when making a declaration. This keyword is followed by an
-attribute specification inside double parentheses. Eight attributes,
-@code{noreturn}, @code{const}, @code{format}, @code{section},
+attribute specification inside double parentheses. Nine attributes,
+@code{noreturn}, @code{const}, @code{format},
+@code{no_instrument_function}, @code{section},
@code{constructor}, @code{destructor}, @code{unused} and @code{weak} are
currently defined for functions. Other attributes, including
@code{section} are supported for variables declarations (@pxref{Variable
@@ -1447,6 +1471,12 @@ operands are a call to one of your own function. The compiler always
treats @code{gettext}, @code{dgettext}, and @code{dcgettext} in this
manner.
+@item no_instrument_function
+@cindex @code{no_instrument_function} function attribute
+If @samp{-finstrument-functions} is given, profiling function calls will
+be generated at entry and exit of most user-compiled functions.
+Functions with this attribute will not be so instrumented.
+
@item section ("section-name")
@cindex @code{section} function attribute
Normally, the compiler places the code it generates in the @code{text} section.
@@ -1511,6 +1541,19 @@ mangled name for the target must be used.
Not all target machines support this attribute.
+@item no_check_memory_usage
+@cindex @code{no_check_memory_usage} function attribute
+If @samp{-fcheck-memory-usage} is given, calls to support routines will
+be generated before most memory accesses, to permit support code to
+record usage and detect uses of uninitialized or unallocated storage.
+Since the compiler cannot handle them properly, @code{asm} statements
+are not allowed. Declaring a function with this attribute disables the
+memory checking code for that function, permitting the use of @code{asm}
+statements without requiring separate compilation with different
+options, and allowing you to write support routines of your own if you
+wish, without getting infinite recursion if they get compiled with this
+option.
+
@item regparm (@var{number})
@cindex functions that are passed arguments in registers on the 386
On the Intel 386, the @code{regparm} attribute causes the compiler to
@@ -2217,10 +2260,16 @@ inc (int *a)
(If you are writing a header file to be included in ANSI C programs, write
@code{__inline__} instead of @code{inline}. @xref{Alternate Keywords}.)
-
You can also make all ``simple enough'' functions inline with the option
-@samp{-finline-functions}. Note that certain usages in a function
-definition can make it unsuitable for inline substitution.
+@samp{-finline-functions}.
+
+Note that certain usages in a function definition can make it unsuitable
+for inline substitution. Among these usages are: use of varargs, use of
+alloca, use of variable sized data types (@pxref{Variable Length}),
+use of computed goto (@pxref{Labels as Values}), use of nonlocal goto,
+and nested functions (@pxref{Nested Functions}). Using @samp{-Winline}
+will warn when a function marked @code{inline} could not be substituted,
+and will give the reason for the failure.
Note that in C and Objective C, unlike C++, the @code{inline} keyword
does not affect the linkage of the function.
@@ -2384,6 +2433,14 @@ asm volatile ("movc3 %0,%1,%2"
: "r0", "r1", "r2", "r3", "r4", "r5");
@end example
+It is an error for a clobber description to overlap an input or output
+operand (for example, an operand describing a register class with one
+member, mentioned in the clobber list). Most notably, it is invalid to
+describe that an input operand is modified, but unused as output. It has
+to be specified as an input and output operand anyway. Note that if there
+are only unused output operands, you will then also need to specify
+@code{volatile} for the @code{asm} construct, as described below.
+
If you refer to a particular hardware register from the assembler code,
you will probably have to list the register after the third colon to
tell the compiler the register's value is modified. In some assemblers,
@@ -2488,7 +2545,7 @@ the @code{asm}. For example:
(@{ int __old; \
asm volatile ("get_and_set_priority %0, %1": "=g" (__old) : "g" (new)); \
__old; @})
-b@end example
+@end example
@noindent
If you write an @code{asm} instruction with no outputs, GNU CC will know
@@ -2524,6 +2581,96 @@ If you are writing a header file that should be includable in ANSI C
programs, write @code{__asm__} instead of @code{asm}. @xref{Alternate
Keywords}.
+@subsection i386 floating point asm operands
+
+There are several rules on the usage of stack-like regs in
+asm_operands insns. These rules apply only to the operands that are
+stack-like regs:
+
+@enumerate
+@item
+Given a set of input regs that die in an asm_operands, it is
+necessary to know which are implicitly popped by the asm, and
+which must be explicitly popped by gcc.
+
+An input reg that is implicitly popped by the asm must be
+explicitly clobbered, unless it is constrained to match an
+output operand.
+
+@item
+For any input reg that is implicitly popped by an asm, it is
+necessary to know how to adjust the stack to compensate for the pop.
+If any non-popped input is closer to the top of the reg-stack than
+the implicitly popped reg, it would not be possible to know what the
+stack looked like --- it's not clear how the rest of the stack ``slides
+up''.
+
+All implicitly popped input regs must be closer to the top of
+the reg-stack than any input that is not implicitly popped.
+
+It is possible that if an input dies in an insn, reload might
+use the input reg for an output reload. Consider this example:
+
+@example
+asm ("foo" : "=t" (a) : "f" (b));
+@end example
+
+This asm says that input B is not popped by the asm, and that
+the asm pushes a result onto the reg-stack, ie, the stack is one
+deeper after the asm than it was before. But, it is possible that
+reload will think that it can use the same reg for both the input and
+the output, if input B dies in this insn.
+
+If any input operand uses the @code{f} constraint, all output reg
+constraints must use the @code{&} earlyclobber.
+
+The asm above would be written as
+
+@example
+asm ("foo" : "=&t" (a) : "f" (b));
+@end example
+
+@item
+Some operands need to be in particular places on the stack. All
+output operands fall in this category --- there is no other way to
+know which regs the outputs appear in unless the user indicates
+this in the constraints.
+
+Output operands must specifically indicate which reg an output
+appears in after an asm. @code{=f} is not allowed: the operand
+constraints must select a class with a single reg.
+
+@item
+Output operands may not be ``inserted'' between existing stack regs.
+Since no 387 opcode uses a read/write operand, all output operands
+are dead before the asm_operands, and are pushed by the asm_operands.
+It makes no sense to push anywhere but the top of the reg-stack.
+
+Output operands must start at the top of the reg-stack: output
+operands may not ``skip'' a reg.
+
+@item
+Some asm statements may need extra stack space for internal
+calculations. This can be guaranteed by clobbering stack registers
+unrelated to the inputs and outputs.
+
+@end enumerate
+
+Here are a couple of reasonable asms to want to write. This asm
+takes one input, which is internally popped, and produces two outputs.
+
+@example
+asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp));
+@end example
+
+This asm takes two inputs, which are popped by the @code{fyl2xp1} opcode,
+and replaces them with one output. The user must code the @code{st(1)}
+clobber for reg-stack.c to know that @code{fyl2xp1} pops both inputs.
+
+@example
+asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)");
+@end example
+
@ifclear INTERNALS
@c Show the details on constraints if they do not appear elsewhere in
@c the manual
@@ -2593,7 +2740,9 @@ very often.
Local register variables in specific registers do not reserve the
registers. The compiler's data flow analysis is capable of determining
where the specified registers contain live values, and where they are
-available for other uses.
+available for other uses. Stores into local register variables may be deleted
+when they appear to be dead according to dataflow analysis. References
+to local register variables may be deleted or moved or simplified.
These local variables are sometimes convenient for use with the extended
@code{asm} feature (@pxref{Extended Asm}), if you want to write one
@@ -2744,6 +2893,10 @@ this variable in the register you specify at all times. You may not
code an explicit reference to this register in an @code{asm} statement
and assume it will always refer to this variable.
+Stores into local register variables may be deleted when they appear to be dead
+according to dataflow analysis. References to local register variables may
+be deleted or moved or simplified.
+
@node Alternate Keywords
@section Alternate Keywords
@cindex alternate keywords
@@ -2774,6 +2927,7 @@ macros to replace them with the customary keywords. It looks like this:
#endif
@end example
+@findex __extension__
@samp{-pedantic} causes warnings for many GNU C extensions. You can
prevent such warnings within one expression by writing
@code{__extension__} before the expression. @code{__extension__} has no
@@ -2850,6 +3004,7 @@ These functions may be used to get information about the callers of a
function.
@table @code
+@findex __builtin_return_address
@item __builtin_return_address (@var{level})
This function returns the return address of the current function, or of
one of its callers. The @var{level} argument is number of frames to
@@ -2866,6 +3021,7 @@ of the stack has been reached, this function will return @code{0}.
This function should only be used with a non-zero argument for debugging
purposes.
+@findex __builtin_frame_address
@item __builtin_frame_address (@var{level})
This function is similar to @code{__builtin_return_address}, but it
returns the address of the function frame rather than the return address
@@ -2886,6 +3042,86 @@ The caveats that apply to @code{__builtin_return_address} apply to this
function as well.
@end table
+@node Other Builtins
+@section Other built-in functions provided by GNU CC
+
+GNU CC provides a large number of built-in functions other than the ones
+mentioned above. Some of these are for internal use in the processing
+of exceptions or variable-length argument lists and will not be
+documented here because they may change from time to time; we do not
+recommend general use of these functions.
+
+The remaining functions are provided for optimization purposes.
+
+GNU CC includes builtin versions of many of the functions in the
+standard C library. These will always be treated as having the same
+meaning as the C library function even if you specify the
+@samp{-fno-builtin} (@pxref{C Dialect Options}) option. These functions
+correspond to the C library functions @code{alloca}, @code{ffs},
+@code{abs}, @code{fabsf}, @code{fabs}, @code{fabsl}, @code{labs},
+@code{memcpy}, @code{memcmp}, @code{strcmp}, @code{strcpy},
+@code{strlen}, @code{sqrtf}, @code{sqrt}, @code{sqrtl}, @code{sinf},
+@code{sin}, @code{sinl}, @code{cosf}, @code{cos}, and @code{cosl}.
+
+@findex __builtin_constant_p
+You can use the builtin function @code{__builtin_constant_p} to
+determine if a value is known to be constant at compile-time and hence
+that GNU CC can perform constant-folding on expressions involving that
+value. The argument of the function is the value to test. The function
+returns the integer 1 if the argument is known to be a compile-time
+constant and 0 if it is not known to be a compile-time constant. A
+return of 0 does not indicate that the value is @emph{not} a constant,
+but merely that GNU CC cannot prove it is a constant with the specified
+value of the @samp{-O} option.
+
+You would typically use this function in an embedded application where
+memory was a critical resource. If you have some complex calculation,
+you may want it to be folded if it involves constants, but need to call
+a function if it does not. For example:
+
+@smallexample
+#define Scale_Value(X) \
+ (__builtin_constant_p (X) ? ((X) * SCALE + OFFSET) : Scale (X))
+@end smallexample
+
+You may use this builtin function in either a macro or an inline
+function. However, if you use it in an inlined function and pass an
+argument of the function as the argument to the builtin, GNU CC will
+never return 1 when you call the inline function with a string constant
+or constructor expression (@pxref{Constructors}) and will not return 1
+when you pass a constant numeric value to the inline function unless you
+specify the @samp{-O} option.
+
+@node Deprecated Features
+@section Deprecated Features
+
+In the past, the GNU C++ compiler was extended to experiment with new
+features, at a time when the C++ language was still evolving. Now that
+the C++ standard is complete, some of those features are superceded by
+superior alternatives. Using the old features might cause a warning in
+some cases that the feature will be dropped in the future. In other
+cases, the feature might be gone already.
+
+While the list below is not exhaustive, it documents some of the options
+that are now deprecated:
+
+@table @code
+@item -fthis-is-variable
+In early versions of C++, assignment to this could be used to implement
+application-defined memory allocation. Now, allocation functions
+(@samp{operator new}) are the standard-conforming way to achieve the
+same effect.
+
+@item -fexternal-templates
+@itemx -falt-external-templates
+These are two of the many ways for g++ to implement template
+instantiation. @xref{Template Instantiation}. The C++ standard clearly
+defines how template definitions have to be organized across
+implementation units. g++ has an implicit instantiation mechanism that
+should work just fine for standard-conforming code.
+
+@end table
+
@node C++ Extensions
@chapter Extensions to the C++ Language
@cindex extensions, C++ language
@@ -2908,8 +3144,11 @@ Predefined Macros,cpp.info,The C Preprocessor}).
declarations and definitions.
* Template Instantiation:: Methods for ensuring that exactly one copy of
each needed template instantiation is emitted.
+* Bound member functions:: You can extract a function pointer to the
+ method denoted by a @samp{->*} or @samp{.*} expression.
* C++ Signatures:: You can specify abstract types to get subtype
polymorphism independent from inheritance.
+
@end menu
@node Naming Results
@@ -3317,14 +3556,12 @@ instances required by your explicit instantiations (but not by any
other files) without having to specify them as well.
g++ has extended the template instantiation syntax outlined in the
-Working Paper to allow forward declaration of explicit instantiations,
-explicit instantiation of members of template classes and instantiation
-of the compiler support data for a template class (i.e. the vtable)
-without instantiating any of its members:
+Working Paper to allow forward declaration of explicit instantiations
+and instantiation of the compiler support data for a template class
+(i.e. the vtable) without instantiating any of its members:
@example
extern template int max (int, int);
-template void Foo<int>::f ();
inline template class Foo<int>;
@end example
@@ -3371,6 +3608,40 @@ be the same in all translation units, or things are likely to break.
more discussion of these pragmas.
@end enumerate
+@node Bound member functions
+@section Extracting the function pointer from a bound pointer to member function
+
+@cindex pmf
+@cindex pointer to member function
+@cindex bound pointer to member function
+
+In C++, pointer to member functions (PMFs) are implemented using a wide
+pointer of sorts to handle all the possible call mechanisms; the PMF
+needs to store information about how to adjust the @samp{this} pointer,
+and if the function pointed to is virtual, where to find the vtable, and
+where in the vtable to look for the member function. If you are using
+PMFs in an inner loop, you should really reconsider that decision. If
+that is not an option, you can extract the pointer to the function that
+would be called for a given object/PMF pair and call it directly inside
+the inner loop, to save a bit of time.
+
+Note that you will still be paying the penalty for the call through a
+function pointer; on most modern architectures, such a call defeats the
+branch prediction features of the CPU. This is also true of normal
+virtual function calls.
+
+The syntax for this extension is
+
+@example
+extern A a;
+extern int (A::*fp)();
+typedef int (*fptr)(A *);
+
+fptr p = (fptr)(a.*fp);
+@end example
+
+You must specify @samp{-Wno-pmf-conversions} to use this extension.
+
@node C++ Signatures
@section Type Abstraction using Signatures
diff --git a/contrib/gcc/f/BUGS b/contrib/gcc/f/BUGS
index ae6efd9..6f04b2b 100644
--- a/contrib/gcc/f/BUGS
+++ b/contrib/gcc/f/BUGS
@@ -1,59 +1,46 @@
-This file lists known bugs in the GNU Fortran compiler. Copyright (C)
-1995, 1996 Free Software Foundation, Inc. You may copy, distribute,
-and modify it freely as long as you preserve this copyright notice and
-permission notice.
+*Note:* This file is automatically generated from the files
+`bugs0.texi' and `bugs.texi'. `BUGS' is *not* a source file, although
+it is normally included within source distributions.
-Bugs in GNU Fortran
-*******************
+ This file lists known bugs in the GCC-2.95 version of the GNU
+Fortran compiler. Copyright (C) 1995-1999 Free Software Foundation,
+Inc. You may copy, distribute, and modify it freely as long as you
+preserve this copyright notice and permission notice.
+
+Known Bugs In GNU Fortran
+*************************
This section identifies bugs that `g77' *users* might run into in
-the `egcs'-1.1.2 version of `g77'. This includes bugs that are
-actually in the `gcc' back end (GBE) or in `libf2c', because those sets
-of code are at least somewhat under the control of (and necessarily
-intertwined with) `g77', so it isn't worth separating them out.
+the GCC-2.95 version of `g77'. This includes bugs that are actually in
+the `gcc' back end (GBE) or in `libf2c', because those sets of code are
+at least somewhat under the control of (and necessarily intertwined
+with) `g77', so it isn't worth separating them out.
For information on bugs in *other* versions of `g77', see
-`egcs/gcc/f/NEWS'.
+`egcs/gcc/f/NEWS'. There, lists of bugs fixed in various versions of
+`g77' can help determine what bugs existed in prior versions.
+
+ *Warning:* The information below is still under development, and
+might not accurately reflect the `g77' code base of which it is a part.
+Efforts are made to keep it somewhat up-to-date, but they are
+particularly concentrated on any version of this information that is
+distributed as part of a *released* `g77'.
+
+ In particular, while this information is intended to apply to the
+GCC-2.95 version of `g77', only an official *release* of that version
+is expected to contain documentation that is most consistent with the
+`g77' product in that version.
An online, "live" version of this document (derived directly from
-the up-to-date mainline version of `g77' within `egcs') is available at
-`http://egcs.cygnus.com/onlinedocs/g77_bugs.html'.
+the mainline, development version of `g77' within `egcs') is available
+via `http://www.gnu.org/software/gcc/onlinedocs/g77_bugs.html'. Follow the
+"Known Bugs" link.
For information on bugs that might afflict people who configure,
port, build, and install `g77', see "Problems Installing" in
`egcs/gcc/f/INSTALL'.
- * `g77' generates bad code for assignments, or other conversions, of
- `REAL' or `COMPLEX' constant expressions to type `INTEGER(KIND=2)'
- (often referred to as `INTEGER*8').
-
- For example, `INTEGER*8 J; J = 4E10' is miscompiled on some
- systems--the wrong value is stored in J.
-
- * The `IDate' Intrinsic (VXT) fails to return the year in the
- documented, non-Y2K-compliant range of 0-99, instead returning 100
- for the year 2000.
-
- * Year 2000 (Y2K) compliance information is missing from the
- documentation.
-
- * `g77' crashes when compiling I/O statements using keywords that
- define `INTEGER' values, such as `IOSTAT=J', where J is other than
- default `INTEGER' (such as `INTEGER*2').
-
- * The `-ax' option is not obeyed when compiling Fortran programs.
- (It is not passed to the `f771' driver.)
-
- * `g77' fails to warn about a reference to a function when the
- corresponding *subsequent* function program unit disagrees with
- the reference concerning the type of the function.
-
- * Automatic arrays possibly aren't working on HP-UX systems, at
- least in HP-UX version 10.20. Writing into them apparently causes
- over-writing of statically declared data in the main program.
- This probably means the arrays themselves are being
- under-allocated, or pointers to them being improperly handled,
- e.g. not passed to other procedures as they should be.
+ The following information was last updated on 1999-06-29:
* `g77' fails to warn about use of a "live" iterative-DO variable as
an implied-DO variable in a `WRITE' or `PRINT' statement (although
@@ -147,18 +134,6 @@ port, build, and install `g77', see "Problems Installing" in
0.6 should solve most or all remaining problems (such as
cross-compiling involving 64-bit machines).
- * Maintainers of gcc report that the back end definitely has "broken"
- support for `COMPLEX' types. Based on their input, it seems many
- of the problems affect only the more-general facilities for gcc's
- `__complex__' type, such as `__complex__ int' (where the real and
- imaginary parts are integers) that GNU Fortran does not use.
-
- Version 0.5.20 of `g77' works around this problem by not using the
- back end's support for `COMPLEX'. The new option
- `-fno-emulate-complex' avoids the work-around, reverting to using
- the same "broken" mechanism as that used by versions of `g77'
- prior to 0.5.20.
-
* `g77' currently inserts needless padding for things like `COMMON
A,IPAD' where `A' is `CHARACTER*1' and `IPAD' is `INTEGER(KIND=1)'
on machines like x86, because the back end insists that `IPAD' be
@@ -170,33 +145,6 @@ port, build, and install `g77', see "Problems Installing" in
targets, and front ends like `g77' should take advantage of this
when it becomes available.
- * The x86 target's `-malign-double' option no longer reliably aligns
- double-precision variables and arrays when they are placed in the
- stack frame.
-
- This can significantly reduce the performance of some applications,
- even on a run-to-run basis (that is, performance measurements can
- vary fairly widely depending on whether frequently used variables
- are properly aligned, and that can change from one program run to
- the next, even from one procedure call to the next).
-
- Versions 0.5.22 and earlier of `g77' included a patch to `gcc'
- that enabled this, but that patch has been deemed an improper
- (probably buggy) one for version 2.8 of `gcc' and for `egcs'.
-
- Note that version 1.1 of `egcs' aligns double-precision variables
- and arrays when they are in static storage even if
- `-malign-double' is not specified.
-
- There is ongoing investigation into how to make `-malign-double'
- work properly, also into how to make it unnecessary to get all
- double-precision variables and arrays aligned when such alignment
- would not violate the relevant specifications for processor and
- inter-procedural interfaces.
-
- For a suite of programs to test double-precision alignment, see
- `ftp://alpha.gnu.org/gnu/g77/align/'.
-
* The `libf2c' routines that perform some run-time arithmetic on
`COMPLEX' operands were modified circa version 0.5.20 of `g77' to
work properly even in the presence of aliased operands.
diff --git a/contrib/gcc/f/ChangeLog b/contrib/gcc/f/ChangeLog
index bc8637d..a3755f4 100644
--- a/contrib/gcc/f/ChangeLog
+++ b/contrib/gcc/f/ChangeLog
@@ -1,4804 +1,1266 @@
-Sun Mar 14 02:38:07 PST 1999 Jeff Law (law@cygnus.com)
+Mon Aug 16 01:29:24 PDT 1999 Jeff Law (law@cygnus.com)
- * egcs-1.1.2 Released.
+ * gcc-2.95.1 Released.
-1999-03-13 Craig Burley <craig@jcb-sc.com>
+Thu Aug 5 02:40:42 1999 Jeffrey A Law (law@cygnus.com)
- * bugs.texi: Document newly discovered bug (19990313-*.f tests).
+ * g77spec.c: Update URLS and mail addresses.
+ * root.texi: Update URLS and mail addresses.
-1999-03-13 Craig Burley <craig@jcb-sc.com>
+Wed Jul 28 21:39:31 PDT 1999 Jeff Law (law@cygnus.com)
- * bugs.texi: Editorial fixes.
+ * gcc-2.95 Released.
-1999-03-11 Craig Burley <craig@jcb-sc.com>
+ * version.c: No longer a prerelease.
- * bugs.texi, g77.texi, news.texi: Point to URLs for live
- versions of docs.
- Clarify which versions to which these docs apply.
- Other minor fix-ups.
+Sat Jul 17 21:57:07 1999 Jeffrey A Law (law@cygnus.com)
-1999-03-05 Craig Burley <craig@jcb-sc.com>
+ * root.texi: Clear DEVEOPMENT per Craig's instructions.
- * news.texi: IDATE (VXT) fixed to return year as 0..99.
-
-1999-03-03 Craig Burley <craig@jcb-sc.com>
-
- * bugs.texi: Update with latest bug-fixes from 1.2.
- Remove fixed bugs.
-
-1999-02-26 Craig Burley <craig@jcb-sc.com>
-
- * news.texi: List fixes to Date_and_Time and LStat, plus
- the docs, under a new heading for egcs 1.1.2.
-
-1999-02-26 Craig Burley <craig@jcb-sc.com>
-
- * intdoc.in (STAT_func, STAT_subr,
- FSTAT_func, FSTAT_subr, LSTAT_func, LSTAT_subr):
- Properly order array elements. Specify N/A return values.
-
-1999-02-26 Craig Burley <craig@jcb-sc.com>
-
- * intdoc.in (DATE_AND_TIME): Explain that VALUES(7) holds
- seconds, and VALUES(8), therefore, the milliseconds.
-
-1999-02-26 Craig Burley <craig@jcb-sc.com>
-
- * bugs.texi: Mention bugs known fixed in egcs 1.2 as of now.
-
-1999-02-26 Craig Burley <craig@jcb-sc.com>
-
- Fix what evidently remains of these, for 4.4bsd:
- Tue Aug 18 21:41:31 1998 Jeffrey A Law (law@cygnus.com)
- * Make-lang.in: Add several "else true" clauses to deal with lame
- systems.
-
-1999-02-25 Andreas Jaeger <aj@arthur.rhein-neckar.de>
-
- * f/intdoc.in: Add missing `,' after cross references.
-
-1999-02-20 Craig Burley <craig@jcb-sc.com>
-
- * g77.texi: Properly attribute Priest document; clarify
- that it is in the .ps version of the Goldberg document.
-
-1999-02-18 Craig Burley <craig@jcb-sc.com>
-
- * intdoc.in (LOG10): Fix typo.
-
-1999-02-17 Dave Love <fx@gnu.org>
-
- * intdoc.in: Say `common' logarithm for log10.
-
-1999-02-15 Craig Burley <craig@jcb-sc.com>
-
- * g77.texi: Change my email address in a couple of places.
-
-1999-02-14 Craig Burley <craig@jcb-sc.com>
-
- * version.c: Bump for 1998-10-02 change (forgot to do this
- before).
-
-1999-02-14 Craig Burley <craig@jcb-sc.com>
-
- * intdoc.in (LOG10): Fix description.
-
-1999-02-14 Craig Burley <craig@jcb-sc.com>
-
- * news.texi: Mention fix for SIGNAL invocation circa egcs-1.1.
-
-1999-02-14 Craig Burley <craig@jcb-sc.com>
-
- * intdoc.in (MCLOCK8, TIME8): Warn about lower range on
- 32-bit systems.
-
-Sat Feb 6 17:17:09 1999 Jeffrey A Law (law@cygnus.com)
-
- * g77.texi: Update email addresses.
-
-1998-11-20 Dave Love <d.love@dl.ac.uk>
-
- * g77.texi: Assorted minor changes.
-
-1998-11-19 Dave Love <d.love@dl.ac.uk>
-
- * intdoc.in: Terminate some @xrefs with `,'.
-
-Mon Nov 9 23:13:30 1998 Jeffrey A Law (law@cygnus.com)
-
- * g77.texi: Updates from Craig.
-
-1998-10-09 Dave Love <d.love@dl.ac.uk>
-
- * g77.texi: Various updates.
-
-1998-10-02 Dave Love <d.love@dl.ac.uk>
-
- * com.c (ffecom_expr_intrinsic_): Fix return type for RAND.
-
-Fri Oct 2 01:27:06 1998 Kamil Iskra <iskra@student.uci.agh.edu.pl>
-
- * Make-lang.in (f77.install-common): Add missing "else true;".
-
-Sat Sep 5 23:55:15 1998 Jeffrey A Law (law@cygnus.com)
-
- * news.texi: Tweaks from Craig.
-
-Tue Sep 1 10:00:21 1998 Craig Burley <burley@gnu.org>
-
- * bugs.texi, g77.1, g77.texi, intdoc.in, news.texi: Doc updates
- from Craig.
-
-1998-08-23 Dave Love <d.love@dl.ac.uk>
+1999-07-17 Alexandre Oliva <oliva@dcc.unicamp.br>
+
+ * root.texi: Update e-mail addresses to gcc.gnu.org.
+ * g77spec.c (lang_specific_driver): Updated URL with bug reporting
+ instructions to gcc.gnu.org. Removed e-mail address.
- * g77.texi: Increment `version-g77' and fix a few typos.
-
-Tue Aug 11 08:12:14 1998 H.J. Lu (hjl@gnu.org)
-
- * Make-lang.in (g77.o): Touch lang-f77 before checking it.
-
-1998-08-09 Dave Love <d.love@dl.ac.uk>
-
- * Make-lang.in (f/g77.dvi): Replace non-working use of texi2dvi
- with explicit use of tex.
- (f77.mostlyclean): Remove TeX index files.
-
- * g77install.texi (Prerequisites): Kluge round TeX lossage with
- hyphen in @value in @code.
+Sat Jul 17 11:28:43 1999 Craig Burley <craig@jcb-sc.com>
-Tue Aug 4 16:59:39 1998 Craig Burley <burley@gnu.org>
+ * root.texi, g77install.texi: Switchover to GCC terminology.
+ Also, FSF-G77 had been mistakenly set at some point.
- * com.c (ffecom_convert_narrow_, ffecom_convert_widen_):
- Allow conversion from pointer to same-sized integer,
- to fix invoking SIGNAL as a function.
+Thu Jul 8 15:38:50 1999 Craig Burley <craig@jcb-sc.com>
-1998-07-26 Dave Love <d.love@dl.ac.uk>
+ * news.texi: Describe DATE intrinsic fix.
- * BUGS, INSTALL, NEWS: Rebuilt.
+Tue Jun 29 10:10:25 1999 Craig Burley <craig@jcb-sc.com>
-Sat Jul 25 17:23:55 1998 Craig Burley <burley@gnu.org>
+ * bugs.texi: Undo Friday's change, as there's now a fix
+ available from netlib.
+ * news.texi: Document the fix.
- Fix 980615-0.f:
- * stc.c (ffestc_R1229_start): Set info to ANY as well.
+Mon Jun 28 10:43:11 1999 Craig Burley <craig@jcb-sc.com>
-Tue Jul 21 04:33:37 1998 Craig Burley <burley@gnu.org>
-
- * g77spec.c (lang_specific_driver): Return unmolested
- command line when --help seen.
- Comment out code that printed g77-specific --help info.
-
-Sat Jul 18 19:16:48 1998 Craig Burley <burley@gnu.org>
-
- * lang-options.h: Fix up doc strings.
- Remove the unimplemented -fdcp-intrinsics-* options.
-
- * str-1t.fin: Change mixed-case spelling of `GoTo' from
- `Goto'.
-
-Thu Jul 16 13:26:36 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_finish_symbol_transform_): Revert change
- of 1998-05-23, as it was too aggressive, in that it
- prevented transformation of (used) functions before
- primary code generation.
-
-1998-07-15 Dave Love <d.love@dl.ac.uk>
-
- * intdoc.texi: Regenerated.
-
-Mon Jul 13 18:45:06 1998 Craig Burley <burley@gnu.org>
-
- * Make-lang.in (f77.rebuilt): Fix to depend on
- build-dir-based, not source-based, g77.info.
-
- * g77.texi: Merge docs with 0.5.24.
- * g77install.texi: Ditto.
-
-Mon Jul 13 18:02:29 1998 Craig Burley <burley@gnu.org>
-
- Cleanups vis-a-vis g77-0.5.24:
- * g77spec.c (lang_specific_driver): Tabify source.
- * top.c (ffe_decode_option): Use fixed macro to set
- internal-checking flag.
- * top.h (ffe_set_is_do_internal_checks): Fix macro.
-
-Mon Jul 13 17:33:44 1998 Craig Burley <burley@gnu.org>
-
- Cleanups vis-a-vis system.h cutover and g77-0.5.24:
- * Makefile.in (fini.o): Define USE_HCONFIG macro
- so source code doesn't have to.
- * fini.c: Don't define USE_HCONFIG here, since
- source code usually shouldn't care about this.
- * ansify.c: Include stddef.h only if we have it.
- * intdoc.c: Ditto.
- * proj.h: Ditto.
-
-Mon Jul 13 17:30:29 1998 Nick Clifton <nickc@cygnus.com>
-
- * lang-options.h: Format changed to work with --help support added
- to gcc/toplev.c
-
-Mon Jul 13 11:54:03 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_push_tempvar): Replace kludge that
- munged back-end globals directly with proper calls
- to push_topmost_sequence and pop_topmost_sequence.
-
-1998-07-12 Dave Love <d.love@dl.ac.uk>
+ * com.c (ffecom_prepare_expr_): A COMPLEX intrinsic needs
+ a temp even if -fno-f2c.
* version.c: Bump version.
-Sat Jul 11 19:24:32 1998 Craig Burley <burley@gnu.org>
-
- Fix 980616-0.f:
- * equiv.c (ffeequiv_offset_): Don't crash on various
- possible ANY operands.
-
-Sat Jul 11 18:24:37 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_expr_) [FFEBLD_opCONTER]: Die if padding
- for constant is non-zero.
-
- * com.c (__eprintf): Delete this function, it is obsolete.
-
-1998-07-09 Dave Love <d.love@dl.ac.uk>
-
- * intdoc.in (HOSTNM_func, HOSTNM_subr): Update last change.
-
-Thu Jul 9 00:45:59 1998 Craig Burley <burley@gnu.org>
-
- Fix debugging of CHARACTER*(*), etc., which requires
- emitting debug info on types like `ftnlen':
- * com.c (ffecom_start_progunit_): Don't bother
- resetting "invented" flag for identifier.
- (ffecom_transform_equiv_): Don't bother zeroing
- "ignored" flag for decl.
- (pushdecl): No longer set "ignored", "used", or
- "suppressed debug" flags for decls having "invented"
- identifiers.
-
-1998-07-06 Mike Stump <mrs@wrs.com>
-
- * Make-lang.in (f77.stage?): Use mv -f instead of just mv so that
- we can move g77.c.
-
-1998-07-06 Dave Love <d.love@dl.ac.uk>
-
- * intdoc.in (HOSTNM_func, HOSTNM_subr): Note possible need for
- -lsocket.
-
-1998-07-05 Dave Love <d.love@dl.ac.uk>
-
- * intdoc.in: Add entry for DATE_AND_TIME.
-
- * intrin.def: Add implementation for DATE_AND_TIME. Make second
- and third args of SYSTEM_CLOCK optional.
-
- * com.c (ffecom_expr_intrinsic_): New case for DATE_AND_TIME.
-
- * com-rt.def (FFECOM_gfrtSYSTEM_CLOCK): Call G77_system_clock_0,
- not system_clock_.
- (FFECOM_gfrtDATE_AND_TIME): New DEFGFRT.
-
-Wed Jul 1 11:19:13 1998 Craig Burley <burley@gnu.org>
-
- Fix 980701-1.f (which was producing "unaligned trap"
- on an Alpha running GNU/Linux, as predicted):
- * equiv.c (ffeequiv_layout_local_): Don't bother
- coping with pre-padding of entire area while building
- it; do that instead after the building is done, and
- do it by modifying only the modulo field. This covers
- the case of alignment stringency being increased without
- lowering the starting offset, unlike the previous changes,
- and even more elegantly than those.
-
- * target.c (ffetarget_align): Make sure alignments
- are non-zero, just in case.
-
-Mon Jun 29 09:47:33 1998 Craig Burley <burley@gnu.org>
-
- Fix 980628-*.f:
- * bld.h: New `pad' field and accessor macros for
- ACCTER, ARRTER, and CONTER ops.
- * bld.c (ffebld_new_accter, ffebld_new_arrter,
- ffebld_new_conter_with_orig): Initialize `pad' field
- to zero.
- * com.c (ffecom_transform_common_): Include initial
- padding (aka modulo aka offset) in size calculation.
- Copy initial padding value into FFE initialization expression
- so the GBE transformation of that expression includes it.
- Make array low bound 0 instead of 1, for consistency.
- (ffecom_transform_equiv_): Include initial
- padding (aka modulo aka offset) in size calculation.
- Copy initial padding value into FFE initialization expression
- so the GBE transformation of that expression includes it.
- Make array low bound 0 instead of 1, for consistency.
- (ffecom_expr_, case FFEBLD_opACCTER): Delete unused `size'
- variable.
- Track destination offset separately, allowing for
- initial padding.
- Don't bother setting initial PURPOSE offset if zero.
- Include initial padding in size calculation.
- (ffecom_expr_, case FFEBLD_opARRTER): Allow for
- initial padding.
- Include initial padding in size calculation.
- Make array low bound 0 instead of 1, for consistency.
- (ffecom_finish_global_): Make array low bound 0 instead
- of 1, for consistency.
- (ffecom_notify_init_storage): Copy `pad' field from old
- ACCTER to new ARRTER.
- (ffecom_notify_init_symbol): Ditto.
- * data.c (ffedata_gather_): Initialize `pad' field in new
- ARRTER to 0.
- (ffedata_value_): Ditto.
- * equiv.c (ffeequiv_layout_local_): When lowering start
- of equiv area, extend lowering to maintain needed alignment.
- * target.c (ffetarget_align): Handle negative offset correctly.
-
- * global.c (ffeglobal_pad_common): Warn about non-zero
- padding only the first time its seen.
- If new padding larger than old, update old.
- (ffeglobal_save_common): Use correct type for size throughout.
- * global.h: Use correct type for size throughout.
- (ffeglobal_common_pad): New macro.
- (ffeglobal_pad): Delete this unused and broken macro.
-
-Fri Jun 26 11:54:19 1998 Craig Burley <burley@gnu.org>
-
- * g77spec.c (lang_specific_driver): Put `-lg2c' in
- front of any `-lm' that is seen.
-
-Mon Jun 22 23:12:05 1998 H.J. Lu (hjl@gnu.org)
-
- * Make-lang.in (G77STAGESTUFF): Add g77.c.
-
-Mon Jun 15 23:39:24 1998 Craig Burley <burley@gnu.org>
-
- * Make-lang.in (f/g77.info): Use -f when removing
- pre-existing Info files, if any. (This rm command
- can go away once makeinfo has been changed to delete
- .info-N files beyond the last one it creates.)
-
- * Make-lang.in ($(srcdir)/f/intdoc.texi): Compile
- using $(INCLUDES) macro to get the new hconfig.h
- and system.h headers.
-
-Mon Jun 15 22:21:57 1998 Craig Burley <burley@gnu.org>
-
- Cutover to system.h:
- * Make-lang.in:
- * Makefile.in:
- * ansify.c:
- * bad.c:
- * bld.c:
- * com.c:
- * com.h:
- * expr.c:
- * fini.c:
- * g77spec.c:
- * implic.c:
- * intdoc.c:
- * intrin.c:
- * lex.c:
- * lex.h:
- * parse.c:
- * proj.c:
- * proj.h:
- * src.c:
- * src.h:
- * stb.c:
- * ste.c:
- * target.c:
- * top.c:
- * system.j: New file.
-
- Use toplev.h where appropriate:
- * Make-lang.in:
- * Makefile.in:
- * bad.c:
- * bld.c:
- * com.c:
- * lex.c:
- * ste.c:
- * top.c:
- * toplev.j: New file.
-
- Conditionalize all dumping/reporting routines so they don't
- get built for gcc/egcs:
- * bld.c:
- * bld.h:
- * com.c:
- * equiv.c:
- * equiv.h:
- * sta.c:
- * stt.c:
- * stt.h:
- * symbol.c:
- * symbol.h:
-
- Use hconfig.h instead of config.h where appropriate:
- * Makefile.in (proj-h.o): Compile with -DUSE_HCONFIG.
- * fini.c: Define USE_HCONFIG before including proj.h.
-
- * Makefile.in (deps-kinda): Redirect stderr to stdout,
- to eliminate diagnostics vis-a-vis g77spec.c.
-
- * Makefile.in: Regenerate dependencies via deps-kinda.
-
- * lex.c (ffelex_file_fixed, ffelex_file_free): Eliminate
- apparently spurious warnings about uninitialized variables
- `c', `column', and so on.
-
-Sat Jun 13 03:13:18 1998 Craig Burley <burley@gnu.org>
-
- * g77spec.c (lang_specific_driver): Print out egcs
- version info first, to be compatible with what some
- test facilities expect.
-
-Wed Jun 10 13:17:32 1998 Dave Brolley <brolley@cygnus.com>
-
- * top.h (ffe_decode_option): New argc/argv interface.
- * top.c (ffe_decode_option): New argc/argv interface.
- * parse.c (yyparse): New argc/argv interface for ffe_decode_option.
- * com.c (lang_decode_option): New argc/argv interface.
-
-Mon Jun 1 19:37:42 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_init_0): Fix setup of INTEGER(KIND=7)
- pointer type.
- * info.c (ffeinfo_type): Don't crash on null type.
- * expr.c (ffeexpr_fulfill_call_): Don't special-case
- %LOC(expr) or LOC(expr).
- Delete FFEGLOBAL_argsummaryPTR.
- * global.c, global.h: Delete FFEGLOBAL_argsummaryPTR.
-
-Thu May 28 21:32:18 1998 Craig Burley <burley@gnu.org>
-
- Restore circa-0.5.22 capabilities of `g77' driver:
- * Make-lang.in (g77spec.o): Depend on f/version.h.
- (g77version.o): New rule to compile g77 version info.
- (g77$(exeext)): Depend on and link in g77version.o.
- * g77spec.c: Rewrite to be more like 0.5.22 version
- of g77.c, making filtering of command line smarter
- so mixed Fortran and C (etc.) can be compiled, verbose
- version info can be obtained, etc.
- * lang-specs.h (f77-version): New "language" to support
- "g77 -v" command under new gcc 2.8 regime.
- * lex.c (ffelex_file_fixed): If -fnull-version, just
- substitute a "source file" that prints out version info.
- * top.c, top.h: Support -fnull-version.
-
- * lang-specs.h: Use "%O" instead of OO macro to specify
- object extension. Remove old stringizing cruft.
-
- * Make-lang.in (g77.c, g77spec.o, g77.o, g77$(exeext),
- g77-cross$(exeext), f771,
- $(srcdir)/f/g77.info, $(srcdir)/f/g77.dvi,
- $(srcdir)/f/intdoc.texi,
- f77.install-common, f77.install-info, f77.install-man,
- f77.uninstall, $(G77STAGESTUFF), f77.stage1, f77.stage2,
- f77.stage3, f77.stage4, f77.distdir): Don't do anything
- unless user specified "f77" or "F77" in $LANGUAGES either
- during configuration or explicitly. For convenience of
- various tests and to work around lack of the assignment
- "LANGUAGES=$(BOOT_LANGUAGES)" in the "make stage1" command
- of "make bootstrap" in gcc, use a touch file named "lang-f77"
- to communicate whether this is the case.
-
- * Make-lang.in (F77_FLAGS_TO_PASS): Delete this macro,
- replace with minimal expansion of its former self in
- each of the two instances where it was used.
-
- * Makefile.in (HOST_CC): Delete this definition.
-
- * com.c (index, rindex): Delete these declarations.
-
- * proj.h: (isascii): Delete this.
-
- * Make-lang.in (f77.install-common): Warn if `f77-install-ok'
- flag-file exists, since it no longer triggers any activity.
-
- Rename libf2c.a and f2c.h to libg2c.a and g2c.h,
- normalize and simplify g77/libg2c build process:
- * Make-lang.in: Remove all support for overwriting
- /usr/bin/f77 etc., or whatever the actual names are
- via $(prefix) and $(local_prefix). (g++ overwrites
- /usr/bin/c++, but then it's often the only C++ compiler
- on the system; f77 often exists on systems that are
- installing g77.)
- (f77.realclean): Remove obsolete target.
- (g77.c, g77$(exeext)): Minor changes to look more like g++'s
- stuff.
- (f771): Now built with srcdir=gcc/f, not srcdir=gcc, to be
- more like g++ and such.
- (f/Makefile): Removed, as g++ doesn't need this rule.
- (f77.install-common): No longer install f77, etc.
- (f77.install-man): No longer install f77.1.
- (f77.uninstall): No longer uninstall f77, f77.1, etc.
- (f77.stage1, f77.stage2, f77.stage3, f77.stage4): Do work
- only if "f77" appears in $(LANGUAGES).
- (Note: gcc's Makefile.in's bootstrap target should set
- LANGUAGES=$(BOOT_LANGUAGES) when making the stage1 target.)
- * Makefile.in: Update vis-a-vis gcc/cp/Makefile.in.
- (none): Remove.
- (g77-only): Relocate.
- (all.indirect, f771, *.o): Now assumes current directory
- is this dir (gcc/f), not the parent directory.
- (TAGS): Remove "echo 'parse.y,0' >> TAGS ;" line.
- * config-lang.in: Delete commented-out code.
- Fix stagestuff definition. Add more stuff to
- diff_excludes definition. Don't create any directories.
- Set outputs to f/Makefile, to get variable substition
- to happen (what does that really do, anyway?!).
- * g77spec.c: Rename libf2c to libg2c.
-
- * com.h: Remove all of the gcc back-end decls,
- since egcs should have all of them correct.
-
- * com.c: Include "proj.h" before anything else,
- as that's how things are supposed to work.
- * ste.c: Ditto.
-
- * bad.c: Include "flags.j" here, since some diagnostics
- check flag_pedantic_errors.
-
- * Makefile.in (f/*.o): Rebuild dependencies via
- deps-kinda.
-
- * output.j: New source file.
- * Make-lang.in (F77_SRCS): Update accordingly.
- * Makefile.in (OUTPUT_H): Ditto.
- (deps-kinda): Ditto.
- * com.c: Include "output.j" here.
- * lex.c: Ditto.
-
-Mon May 25 03:34:42 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_expr_): Fix D**I and Z**I cases to
- not convert (DOUBLE PRECISION) D and (DOUBLE COMPLEX) Z
- to INTEGER. (This is dead code here anyway.)
-
-Sat May 23 06:32:52 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_finish_symbol_transform_): Don't transform
- statement (nested) functions, to avoid gcc compiling them
- and thus producing linker errors if they refer to undefined
- external functions. But warn if they're unused and -Wunused.
- * bad.def (FFEBAD_SFUNC_UNUSED): New diagnostic.
-
-Wed May 20 12:12:55 1998 Craig Burley <burley@gnu.org>
-
- * Version 0.5.23 released.
-
-Tue May 19 14:52:41 1998 Craig Burley <burley@gnu.org>
-
- * bad.def (FFEBAD_OPEN_UNSUPPORTED, FFEBAD_INQUIRE_UNSUPPORTED,
- FFEBAD_READ_UNSUPPORTED, FFEBAD_WRITE_UNSUPPORTED,
- FFEBAD_QUAD_UNSUPPORTED, FFEBAD_BLOCKDATA_STMT,
- FFEBAD_TRUNCATING_CHARACTER, FFEBAD_TRUNCATING_HOLLERITH,
- FFEBAD_TRUNCATING_NUMERIC, FFEBAD_TRUNCATING_TYPELESS,
- FFEBAD_TYPELESS_OVERFLOW): Change these from warnings
- to errors.
-
-Tue May 19 14:51:59 1998 Craig Burley <burley@gnu.org>
-
- * Make-lang.in (f77.install-info, f77.uninstall):
- Use install-info as appropriate.
-
-Tue May 19 12:56:54 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_init_0): Rename xargc to f__xargc,
- in accord with same-dated change to f/runtime.
-
-Fri May 15 10:52:49 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_convert_narrow_, ffecom_convert_widen_):
- Be even more persnickety in checking for internal bugs.
- Also, if precision isn't changing, just return the expr.
-
- * expr.c (ffeexpr_token_number_): Call
- ffeexpr_make_float_const_ to make an integer.
- (ffeexpr_make_float_const_): Handle making an integer.
-
- * intrin.c (ffeintrin_init_0): Distinguish between
- crashes on bad arg base and kind types.
-
-Thu May 14 13:30:59 1998 Craig Burley <burley@gnu.org>
-
- * Make-lang.in (f/expr.c): Now depends on f/stamp-str.
- * expr.c: Use ffestrOther in place of ffeexprDotdot_.
- * str-ot.fin: Add more keywords for expr.c.
-
- * intdoc.c (dumpimp): Trivial fix.
-
- * com.c (ffecom_expr_): Add ltkt variable for clarity.
-
-Wed May 13 13:05:34 1998 Craig Burley <burley@gnu.org>
-
- * Make-lang.in (G77STAGESTUFF): Add g77.o, g77spec.o,
- and g77version.o.
- (f77.clean): Add removal of g77.c, g77.o, g77spec.o,
- and g77version.o.
- (f77.distclean): Delete removal of g77.c.
-
-Thu Apr 30 18:59:43 1998 Jim Wilson <wilson@cygnus.com>
-
- * Make-lang.in (g77.info, g77.dvi, BUGS, INSTALL, NEWS): Put -o
- option before input file.
-
-Tue Apr 28 09:23:10 1998 Craig Burley <burley@gnu.org>
-
- Fix 980427-0.f:
- * global.c (ffeglobal_ref_progunit_): When transitioning
- from EXT to FUNC, discard hook, since the decl, if any, is
- probably wrong.
-
-Sun Apr 26 09:05:50 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_char_enhance_arg_): Wrap the upper bound
- (the PARM_DECL specifying the length of the CHARACTER*(*)
- dummy arg) in a variable_size invocation, to prevent
- dwarf2out.c crashing when compiling code with -g.
-
-Sat Apr 18 05:03:21 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_check_size_overflow_): Ignore overflow
- as well if dummy argument.
-
-Fri Apr 17 17:18:04 1998 Craig Burley <burley@gnu.org>
-
- * version.h: Get rid of the overly large headers
- here too, as done in version.c.
-
-Tue Apr 14 14:40:40 1998 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_start_progunit_): Mark function decl
- as used, to avoid spurious warning (-Wunused) for ENTRY.
-
-Tue Apr 14 14:19:34 1998 Craig Burley <burley@gnu.org>
-
- * sta.c (ffesta_second_): Check for CASE DEFAULT
- as well as CASE, or it won't be recognized.
-
-Mon Mar 23 21:20:35 1998 Craig Burley <burley@gnu.org>
-
- * version.c: Reduce to a one-line file, like
- gcc's version.c, since there's really no content
- there.
-
-Mon Mar 23 11:58:43 1998 Craig Burley <burley@gnu.org>
-
- * bugs.texi: Various updates.
-
- * com.c (ffecom_tree_canonize_ptr_): Fix up spacing a bit.
-
-Mon Mar 16 21:20:35 1998 Craig Burley <burley@gnu.org>
-
- * expr.c (ffeexpr_sym_impdoitem_): Don't blindly
- reset symbol info after calling ffesymbol_error,
- to avoid crash.
-
-Mon Mar 16 15:38:50 1998 Craig Burley <burley@gnu.org>
-
- * Version 0.5.22 released.
-
-Mon Mar 16 14:36:02 1998 Craig Burley <burley@gnu.org>
-
- Make -g work better for ENTRY:
- * com.c (ffecom_start_progunit_): Master function
- for ENTRY-laden procedure is not really invented,
- so it can be debugged.
- (ffecom_do_entry_): Push/set/pop lineno for each
- entry point.
-
-Sun Mar 15 05:48:49 1998 Craig Burley <burley@gnu.org>
-
- * intrin.def: Fix spelling of mixed-case form
- of `CPU_Time' (was `Cpu_Time').
-
-Thu Mar 12 13:50:21 1998 Craig Burley <burley@gnu.org>
-
- * lang-options.h: Sort all -f*-intrinsics-* options,
- for consistency with other g77 versions.
-
-1998-03-09 Dave Love <d.love@dl.ac.uk>
-
- * Make-lang.in: Set CONFIG_SITE to a non-existent file since
- /dev/null loses with bash 2.0/autoconf 2.12. Put
- F77_FLAGS_TO_PASS before CC.
-
-Sun Mar 8 16:35:34 1998 Craig Burley <burley@gnu.org>
-
- * intrin.def: Use tabs instead of blanks more
- consistently (excepting DEFGEN section for now).
-
-Sat Feb 28 15:24:38 1998 Craig Burley <burley@gnu.org>
-
- * intrin.def: Make CPU_TIME's arg generic real to be just
- like SECOND_subr.
-
-Fri Feb 20 12:45:53 1998 Craig Burley <burley@gnu.org>
-
- * expr.c (ffeexpr_token_arguments_): Make sure
- outer exprstack isn't null.
-
-1998-02-16 Dave Love <d.love@dl.ac.uk>
-
- * Makefile.in (f/fini): Don't use -W -Wall with HOST_CC.
-
-Fri Feb 13 00:14:56 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * com.c (type_for_mode): Add explicit braces to avoid ambiguous `else'.
-
- * expr.c (ffeexpr_type_combine): Likewise.
- (ffeexpr_reduce_): Likewise.
- (ffeexpr_declare_parenthesized_): Likewise.
-
- * src.c (ffesrc_strcmp_1ns2i): Likewise.
- (ffesrc_strcmp_2c): Likewise.
- (ffesrc_strncmp_2c): Likewise.
-
- * stb.c (ffestb_halt1_): Likewise.
- (ffestb_R90910_): Likewise.
- (ffestb_R9109_): Likewise.
-
- * stc.c (ffestc_R544_equiv_): Likewise.
-
- * std.c (ffestd_subr_copy_easy_): Likewise.
- (ffestd_R1001dump_): Likewise.
- (ffestd_R1001dump_1005_1_): Likewise.
- (ffestd_R1001dump_1005_2_): Likewise.
- (ffestd_R1001dump_1005_3_): Likewise.
- (ffestd_R1001dump_1005_4_): Likewise.
- (ffestd_R1001dump_1005_5_): Likewise.
- (ffestd_R1001dump_1010_2_): Likewise.
-
- * ste.c (ffeste_R840): Likewise.
-
- * sts.c (ffests_puttext): Likewise.
-
- * symbol.c (ffesymbol_check_token_): Likewise.
-
- * target.c (ffetarget_real1): Likewise.
- (ffetarget_real2): Likewise.
-
-Sun Jan 25 12:32:15 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-
- * Make-lang.in (f77.stage1): Depend on stage1-start so parallel
- make works better.
- * (f77.stage2): Likewise for stage2-start.
- * (f77.stage3): Likewise for stage3-start.
- * (f77.stage4): Likewise for stage4-start.
-
-Sun Jan 11 02:14:47 1998 Craig Burley <burley@gnu.org>
-
- Support FORMAT(I<1+2>) (constant variable-FORMAT
- expressions):
- * bad.def (FFEBAD_FORMAT_VARIABLE): New diagnostic.
- * std.c (ffestd_R1001rtexpr_): New function.
- (ffestd_R1001dump_, ffestd_R1001dump_1005_1_,
- ffestd_R1001dump_1005_2_, ffestd_R1001dump_1005_3_,
- ffestd_R1001dump_1005_4_, ffestd_R1001dump_1005_5_,
- ffestd_R1001dump_1010_2_, ffestd_R1001dump_1010_3_,
- ffestd_R1001dump_1010_4_, ffestd_R1001dump_1010_5_):
- Use new function instead of ffestd_R1001error_.
-
- * stb.c (ffestb_R10014_, ffestb_R10016_, ffestb_R10018_,
- ffestb_R100110_): Restructure `for' loop for style.
-
- Fix 970626-2.f by not doing most back-end processing
- when current_function_decl is an ERROR_MARK, and by
- making that the case when its type would be an ERROR_MARK:
- * com.c (ffecom_start_progunit_, finish_function,
- lang_printable_name, start_function,
- ffecom_finish_symbol_transform_): Test for ERROR_MARK.
- * std.c (ffestd_stmt_pass_): Don't do any downstream
- processing if ERROR_MARK.
-
- * Make-lang.in (f77.install-common): Don't install, and
- don't uninstall existing, Info files if f/g77.info
- doesn't exit. (This is a somewhat modified version
- of an egcs patch on 1998-01-07 12:05:51 by Bruno Haible
- <bruno@linuix.mathematik.uni-karlsruhe.de>.)
-
-Fri Jan 9 19:09:07 1998 Craig Burley <burley@gnu.org>
-
- Fix -fpedantic combined with `F()' invocation,
- also -fugly-comma combined with `IARGC()' invocation:
- * bad.def (FFEBAD_NULL_ARGUMENT_W): New diagnostic.
- * expr.c (ffeexpr_finished_): Don't reject null expressions
- in the argument-expression context -- let outer context
- handle that.
- (ffeexpr_token_arguments_): Warn about null expressions
- here if -fpedantic (as appropriate).
- Obey -fugly-comma for only external-procedure invocations.
- * intrin.c (ffeintrin_check_): No longer ignore explicit
- omitted trailing args.
-
-Tue Dec 23 14:58:04 1997 Craig Burley <burley@gnu.org>
-
- * intrin.c (ffeintrin_fulfill_generic): Don't generate
- FFEBAD_INTRINSIC_TYPE for CHARACTER*(*) intrinsic.
-
- * com.c (ffecom_gfrt_basictype):
- (ffecom_gfrt_kindtype):
- (ffecom_make_gfrt_):
- (FFECOM_rttypeVOIDSTAR_): New return type `void *', for
- the SIGNAL intrinsic.
- * com-rt.def (FFECOM_rttypeSIGNAL): Now returns `void *'.
- * intdoc.c: Replace `p' kind specifier with `7'.
- * intrin.c (ffeintrin_check_, ffeintrin_init_0): Replace
- `p' kind specifier with `7'.
- * intrin.def (FFEINTRIN_impLOC, FFEINTRIN_impSIGNAL_func,
- FFEINTRIN_impSIGNAL_subr): Replace `p' specifier with `7'.
- Also, SIGNAL now returns a `void *' status, not `int'.
-
- Improve run-time diagnostic for "PRINT '(I1', 42":
- * com.c (ffecom_char_args_x_): Renamed from ffecom_char_args_,
- which is now a macro (to avoid lots of changes to other code)
- with new arg, ffecom_char_args_with_null_ being another new
- macro to call same function with different value for new arg.
- This function now appends a null byte to opCONTER expression
- if the new arg is TRUE.
- (ffecom_arg_ptr_to_expr): Support NULL length pointer.
- * ste.c (ffeste_io_cilist_):
- (ffeste_io_icilist_): Pass NULL length ptr for
- FORMAT expression, so null byte gets appended where
- feasible.
- * target.c (ffetarget_character1):
- (ffetarget_concatenate_character1):
- (ffetarget_substr_character1):
- (ffetarget_convert_character1_character1):
- (ffetarget_convert_character1_hollerith):
- (ffetarget_convert_character1_integer4):
- (ffetarget_convert_character1_logical4):
- (ffetarget_convert_character1_typeless):
- (ffetarget_hollerith): Append extra phantom null byte as
- part of FFETARGET-NULL-BYTE kludge.
-
- * intrin.def (FFEINTRIN_impCPU_TIME): Point to
- FFECOM_gfrtSECOND as primary run-time routine.
-
-Mon Dec 22 12:41:07 1997 Craig Burley <burley@gnu.org>
-
- * intrin.c (ffeintrin_init_0): Remove duplicate
- check for `!'.
-
-Sun Dec 14 02:49:58 1997 Craig Burley <burley@gnu.org>
-
- * intrin.c (ffeintrin_init_0): Fix up indentation a bit.
- Fix bug that prevented checking of arguments other
- than the first.
-
- * intdoc.c: Fix up indentation a bit.
-
-Tue Dec 9 16:20:57 1997 Richard Henderson <rth@cygnus.com>
-
- * com.c (ffecom_type_vardesc_): Vardesc.dims is a `ftnlen*'.
-
-Mon Dec 1 19:12:36 1997 Craig Burley <burley@gnu.org>
-
- * intrin.c (ffeintrin_check_): Fix up indentation a bit more.
-
-Mon Dec 1 16:21:08 1997 Craig Burley <burley@gnu.org>
-
- * com.c (ffecom_arglist_expr_): Crash if non-supplied
- optional arg isn't passed as an address.
- Pass null pointer explicitly, instead of via ffecom routine.
- If incoming argstring is NULL, substitute pointer to "0".
- Recognize '0' as ending the usual arg stuff, just like '\0'.
-
-Sun Nov 30 22:22:22 1997 Craig Burley <burley@gnu.org>
-
- * intdoc.c: Minor fix-ups.
-
- * intrin.c (ffeintrin_check_): Fix up indentation a bit.
-
- * intrin.def: Fix up spacing a bit.
-
-1997-11-17 Dave Love <d.love@dl.ac.uk>
-
- * com.c (ffecom_arglist_expr_): Pass null pointers for optional
- args which aren't supplied.
-
-Sun Nov 16 21:45:43 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
-
- * Make-lang.in (f77.install-info): Depend on f77.info.
-
-1997-11-06 Dave Love <d.love@dl.ac.uk>
-
- * intrin.def: Allow non-integer args for INT2 and INT8 (per
- documentation).
-
-Tue Oct 28 02:21:25 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * lang-options.h: Add -fgnu-intrinsics-* and
- -fbadu77-intrinsics-* options.
-
-Sun Oct 26 02:36:21 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (lang_print_error_function): Fix to more
- reliably notice when the diagnosed region changes.
-
-Sat Oct 25 23:43:36 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix 950327-0.f:
- * sta.c, sta.h (ffesta_outpooldisp): New function.
- * std.c (ffestd_stmt_pass_): Don't kill NULL pool.
- (ffestd_R842): If pool already preserved, save NULL
- for pool, because it should be killed only once.
-
- * malloc.c [MALLOC_DEBUG]: Put initializer for `name'
- component in braces, to avoid compiler warning.
-
-Fri Oct 10 13:00:48 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * ste.c (ffeste_begin_iterdo_): Fix loop setup so iteration
- variable is modified only after the #iterations is calculated;
- otherwise if the iteration variable is aliased to any of the
- operands in the start, end, or increment expressions, the
- wrong #iterations might be calculated.
-
- * com.c (ffecom_save_tree): Fix indentation.
-
-1997-10-05 Dave Love <d.love@dl.ac.uk>
-
- * intrin.def: Make SECOND_subr's arg generic real for people
- porting from Cray and making everything double precision.
-
-Mon Sep 29 16:18:21 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * stu.c (ffestu_list_exec_transition_,
- ffestu_dummies_transition_): Specify `bool' type for
- `in_progress' variables.
-
- * com.h (assemble_string): Declare this routine (instead
- of #include'ing "output.h" from gcc) to eliminate warnings
- from lex.c.
-
-Fri Sep 19 01:12:27 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c (ffeexpr_reduced_eqop2_):
- (ffeexpr_reduced_relop2_): Minor fixes to diagnostic code.
-
- * fini.c (main): Change return type to `int'.
-
-Wed Sep 17 10:47:08 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com-rt.def (FFECOM_gfrtDSIGN, FFECOM_gfrtISIGN,
- FFECOM_gfrtSIGN): Add second argument.
-
- * expr.c (ffeexpr_cb_comma_c_): Trivial fixes.
-
-Tue Sep 9 01:59:35 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Version 0.5.21 released.
-
-Tue Sep 9 00:31:01 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * intdoc.c (dumpem): Put appropriate commentary in
- output file, so readers know it isn't source.
-
-Wed Aug 27 08:08:25 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * proj.h: Always #include "config.j" first, to pick up
- gcc's configuration.
- * com.c: Change bcopy() and bzero() calls to memcpy()
- and memset() calls, to make more of g77 ANSI C.
-
-1997-08-26 Dave Love <d.love@dl.ac.uk>
-
- * Make-lang.in ($(srcdir)/f/runtime/configure,
- $(srcdir)/f/runtime/libU77/configure): Fix for when srcdir isn't
- relative.
+Fri Jun 25 11:06:32 1999 Craig Burley <craig@jcb-sc.com>
-Tue Aug 26 05:59:21 1997 Craig Burley <burley@gnu.ai.mit.edu>
+ * bugs.texi: Describe K(5)=10*3 NAMELIST-read bug.
- * ansify.c (main): Make sure readers of stdout know
- it's derived from stdin; omit comment text; get source
- line numbers in future stderr output to be correct.
+Mon Jun 21 12:40:17 1999 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-Tue Aug 26 01:36:01 1997 Craig Burley <burley@gnu.ai.mit.edu>
+ * g77.texi: Update links.
- Fix 970825-0.f:
- * stb.c (ffestb_R5284_): Allow OPEN_PAREN after closing
- SLASH as well as NAME.
+Wed Jun 16 11:43:02 1999 Craig Burley <craig@jcb-sc.com>
-Mon Aug 25 23:48:17 1997 Craig Burley <burley@gnu.ai.mit.edu>
+ * news.texi: Mention BACKSPACE fix to libg2c.
- Changes to allow g77 docs to be built entirely from scratch
- using any ANSI C compiler, not requiring GNU C:
- * Make-lang.in ($(srcdir)/f/intdoc.texi): "Pipe" new
- location of intrinsic documentation data base, f/intdoc.in,
- through new `ansify' program to append `\n\' to quoted
- newlines, into f/intdoc.h0. Do appropriate cleanups. Explain.
- (f77.mostlyclean): Add f/ansify and f/intdoc.h0 to cleanups.
- * f/ansify.c: New program.
- * f/intdoc.c: Fix so it conforms to ANSI C.
- #include f/intdoc.h0 instead of f/intdoc.h.
- Avoid some warnings.
- * f/intdoc.h, f/intdoc.in: Rename the former to the latter; no
- changes made to the content in this patch!
- * f/intrin.h (ffeintrinFamily): Fix to conform to ANSI C.
+Mon Jun 7 08:42:40 1999 Craig Burley <craig@jcb-sc.com>
-Sun Aug 24 06:52:48 1997 Craig Burley <burley@gnu.ai.mit.edu>
+ * Make-lang.in: Any target using libsubdir must depend
+ on installdirs.
- Fix up g77 compiler data base for libf2c routines:
- * com-rt.def (FFECOM_gfrtSIGNAL): Change return type to
- FTNINT to match actual code.
+Sat Jun 5 23:50:36 1999 Craig Burley <craig@jcb-sc.com>
- * com.c (ffecomRttype_): Replace FFECOM_rttypeINT_ with
- FFECOM_rttypeFTNINT_.
- Add and fix up comments.
- (ffecom_make_gfrt_, ffecom_gfrt_basictype,
- ffecom_gfrt_kindtype): Replace FFECOM_rttypeINT_ with
- FFECOM_rttypeFTNINT_; add FFECOM_rttypeDOUBLEREAL_.
+ * g77.texi: Describe a few more missing features people
+ have emailed me about.
-Wed Aug 20 17:18:40 1997 Craig Burley <burley@gnu.ai.mit.edu>
+Sat Jun 5 17:03:23 1999 Craig Burley <craig@jcb-sc.com>
- * global.c (ffeglobal_ref_progunit_): It's okay to have
- a different CHARACTER*n length for a reference if the
- existing length is for another reference, not a definition.
+ From Dave Love to egcs-patches on 20 May 1999 17:38:38 +0100:
+ * g77.texi: Clean up fossil text vis-a-vis Intel CPUs.
-Mon Aug 18 14:27:18 1997 Craig Burley <burley@gnu.ai.mit.edu>
+Fri Jun 4 13:56:56 1999 Craig Burley <craig@jcb-sc.com>
- Fix 970814-0.f:
- * global.c (ffeglobal_new_progunit_): Distinguish
- between previously defined, versus inferred, filewide
- when it comes to diagnostics.
-
- Fix 970816-1.f:
- * global.c (ffeglobal_ref_progunit_): Change BDATA into EXT
- right at the beginning, so EXTERNAL FOO followed later
- by SUBROUTINE FOO is not diagnosed.
+ * Make-lang.in: Use libsubdir, not prefix, to store
+ temporary lang-f77 `flag' file.
- Fix 970813-0.f:
- * com-rt.def (FFECOM_gfrtALARM): Returns `integer', not
- `void'.
+Fri Jun 4 10:26:04 1999 Craig Burley <craig@jcb-sc.com>
-Sun Aug 17 03:32:44 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix up problems when virtual memory exhausted:
- * malloc.c (malloc_new_): Use gcc's xmalloc(), so we
- print a nicer message when malloc returns no memory.
- (malloc_resize_): Ditto for xrealloc().
-
- * Make-lang.in, Makefile.in: Comment out lines containing
- just formfeeds.
-
-Sat Aug 16 19:41:33 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_make_gfrt_): For rttypeREAL_F2C_, return
- double_type_node; for rttypeREAL_GNU_, return
- _real_type_node.
-
-1997-08-13 Dave Love <d.love@dl.ac.uk>
-
- * config-lang.in (diff_excludes): Add some hints about known
- problematic platforms.
-
-1997-08-13 Dave Love <d.love@dl.ac.uk>
-
- * intdoc.h: Document `alarm'.
-
-Mon Aug 11 21:19:22 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in ($(RUNTIMESTAGESTUFF)): Add
- f/runtime/stamp-lib.
-
-Mon Aug 11 01:52:03 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_build_complex_constant_): Go with the
- new build_complex() approach used in gcc-2.8.
-
- * com.c (ffecom_sym_transform_): Don't set
- DECL_IN_SYSTEM_HEADER for a tree node that isn't
- a VAR_DECL, which happens when var is in common!
-
- * com.c (ffecom_expr_intrinsic_) (case FFEINTRIN_impALARM):
- No need to test codegen_imp -- there's only one valid here.
-
- * intrin.def (FFEINTRIN_impALARM): Specify `Status' argument
- as write-only.
-
-Fri Aug 8 05:40:23 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Substantial changes to accommodate distinctions among
- run-time routines that support intrinsics, and between
- routines that compute and return the same type vs. those
- that compute one type and return another (or `void'):
- * com-rt.def: Specify new return type REAL_F2C_ instead
- of many DOUBLE_, COMPLEX_F2C_ instead of COMPLEX_, and
- so on.
- Clear up the *BES* routines "once and for all".
- * com.c: New return types.
- (ffecom_convert_narrow_, ffecom_convert_widen_):
- New functions that are "safe" variants of convert(),
- to catch errors that ffecom_expr_intrinsic_() now
- no longer catches.
- (ffecom_arglist_expr_): Ensure arguments are not
- converted to narrower types.
- (ffecom_call_): Ensure return value is not converted
- to a wider type.
- (ffecom_char_args_): Use new ffeintrin_gfrt_direct()
- routine.
- (ffecom_expr_intrinsic_): Simplify how run-time
- routine is selected (via `gfrt' only now; lose the
- redundant `ix' variable).
- Eliminate the `library' label; any code that doesn't
- return directly just `break's out now with `gfrt'
- set appropriately.
- Set `gfrt' to default choice initially, either a
- fast direct form or, if not available, a slower
- indirect-callable form.
- (ffecom_make_gfrt_): No longer need to do special
- check for complex; it's built into the new return-type
- regime.
- (ffecom_ptr_to_expr): Use new ffeintrin_gfrt_indirect()
- routine.
- * intrin.c, intrin.h: `gfrt' field replaced with three fields,
- so it is easier to provide faster direct-callable and
- GNU-convention indirect-callable routines in the future.
- DEFIMP macro adjusted accordingly, along with all its uses.
- (ffeintrin_gfrt_direct): New function.
- (ffeintrin_gfrt_indirect): Ditto.
- (ffeintrin_is_actualarg): If `-fno-f2c' is in effect,
- require a GNU-callable version of intrinsic instead of
- an f2c-callable version, so indirect calling is still checked.
- * intrin.def: Replace one GFRT field with the three new fields,
- as appropriate for each DEFIMP intrinsic.
-
- * com.c (ffecom_stabilize_aggregate_,
- ffecom_convert_to_complex_): Make these `static'.
-
-Thu Aug 7 11:24:34 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Provide means for front end to determine actual
- "standard" return type for an intrinsic if it is
- passed as an actual argument:
- * com.h, com.c (ffecom_gfrt_basictype,
- ffecom_gfrt_kindtype): New functions.
- (ffecom_gfrt_kind_type_): Replaced with new function.
- All callers updated.
- (ffecom_make_gfrt_): No longer need do anything
- with kind type.
-
- * intrin.c (ffeintrin_basictype, ffeintrin_kindtype):
- Now returns correct type info for specific intrinsic
- (based on type of run-time-library implementation).
-
-Wed Aug 6 23:08:46 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * global.c (ffeglobal_ref_progunit_): Don't reset
- number of arguments just due to new type info,
- so useful warnings can be issued.
-
-1997-08-06 Dave Love <d.love@dl.ac.uk>
-
- * intrin.def: Fix IDATE_vxt argument order.
- * intdoc.h: Likewise.
-
-Thu Jul 31 22:22:03 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * global.c (ffeglobal_proc_ref_arg): If REF/DESCR
- disagreement, DESCR is CHARACTER, and types disagree,
- pretend the argsummary agrees so the message ends up
- being about type disagreement.
- (ffeglobal_proc_def_arg): Ditto.
-
- * expr.c (ffeexpr_token_first_rhs_3_): Set info for LABTOK
- to NONE of everything, to avoid misdiagnosing filewide
- usage of alternate returns.
-
-Sun Jul 20 23:07:47 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_sym_transform_): If type gets set
- to error_mark_node, just return that for transformed symbol.
- (ffecom_member_phase2_): If type gets set to error_mark_node,
- just return.
- (ffecom_check_size_overflow_): Add `dummy' argument to
- flag that type is for a dummy, update all callers.
-
-Sun Jul 13 17:40:53 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix 970712-1.f:
- * where.c (ffewhere_set_from_track): If start point
- is too large, just use initial start point. 0.6 should
- fix all this properly.
-
- Fix 970712-2.f:
- * com.c (ffecom_sym_transform_): Preserve error_mark_node for type.
- (ffecom_type_localvar_): Ditto.
- (ffecom_sym_transform_): If type is error_mark_node,
- don't error-check decl size, because back end responds by
- setting that to an integer 0 instead of error_mark_node.
- (ffecom_transform_common_): Same as earlier fix to _transform_
- in that size is checked by dividing BITS_PER_UNIT instead of
- multiplying.
- (ffecom_transform_equiv_): Ditto.
-
- Fix 970712-3.f:
- * stb.c (ffestb_R10014_): Fix flaky fall-through in error
- test for FFELEX_typeCONCAT by just replicating the code,
- and do FFELEX_typeCOLONCOLON while at it.
-
-1997-07-07 Dave Love <d.love@dl.ac.uk>
-
- * intdoc.h: Add various missing pieces; correct GMTIME, LTIME
- result ordering.
-
- * intrin.def, com-rt.def: Add alarm.
-
- * com.c (ffecom_expr_intrinsic_): Add case for alarm.
-
-Thu Jun 26 04:19:40 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix 970302-3.f:
- * com.c (ffecom_sym_transform_): For sanity-check compare
- of gbe size of local variable to g77 expectation,
- use varasm.c/assemble_variable technique of dividing
- BITS_PER_UNIT out of gbe info instead of multiplying
- g77 info up, to avoid crash when size in bytes is very
- large, and overflows an `int' or similar when multiplied.
-
- Fix 970626-2.f:
- * com.c (ffecom_finish_symbol_transform_): Don't bother
- transforming a dummy argument, to avoid a crash.
- * ste.c (ffeste_R1227): Don't return a value if the
- result decl, or its type, is error_mark_node.
-
- Fix 970626-4.f:
- * lex.c (ffelex_splice_tokens): `-fdollar-ok' is
- irrelevant to whether a DOLLAR token should be made
- from an initial character of `$'.
-
- Fix 970626-6.f:
- * stb.c (ffestb_do3_): DO iteration variable is an
- lhs, not rhs, expression.
-
- Fix 970626-7.f and 970626-8.f:
- * expr.c (ffeexpr_cb_comma_i_1_): Set IMPDO expression
- to have clean info, because undefined rank, for example,
- caused crash on mangled source on UltraSPARC but not
- on Alpha for a series of weird reasons.
- (ffeexpr_cb_close_paren_): If not CLOSE_PAREN, push
- opANY expression onto stack instead of attempting
- to mimic what program might have wanted.
- (ffeexpr_cb_close_paren_): Don't wrap opPAREN around
- opIMPDO, just warn that it's gratuitous.
- * bad.def (FFEBAD_IMPDO_PAREN): New warning.
-
- Fix 970626-9.f:
- * expr.c (ffeexpr_declare_parenthesized_): Must shut down
- parsing in kindANY case, otherwise the parsing engine might
- decide there's an ambiguity.
- (ffeexpr_token_name_rhs_): Eliminate parentypeSUBROUTINE_
- case, so we crash right away if it comes through.
- * st.c, st.h, sta.c, sta.h (ffest_shutdown, ffesta_shutdown):
- New functions.
-
-Tue Jun 24 19:47:29 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_check_size_overflow_): New function
- catches some cases of the size of a type getting
- too large. varasm.c must catch the rest.
- (ffecom_sym_transform_): Use new function.
- (ffecom_type_localvar_): Ditto.
-
-Mon Jun 23 01:09:28 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * global.c (ffeglobal_proc_def_arg): Fix comparison
- of argno to #args.
- (ffeglobal_proc_ref_arg): Ditto.
-
- * lang-options.h, top.c: Rename `-fdebug' to `-fxyzzy',
- since it's an unsupported internals option and some
- poor user might guess that it does something.
-
- * bad.def: Make a warning for each filewide diagnostic.
- Put all filewides together.
- * com.c (ffecom_sym_transform_): Don't substitute
- known global tree for global entities when `-fno-globals'.
- * global.c (ffeglobal_new_progunit_): Don't produce
- fatal diagnostics about globals when `-fno-globals'.
- Instead, produce equivalent warning when `-Wglobals'.
- (ffeglobal_proc_ref_arg): Ditto.
- (ffeglobal_proc_ref_nargs): Ditto.
- (ffeglobal_ref_progunit_): Ditto.
- * lang-options.h, top.c, top.h: New `-fno-globals' option.
-
-Sat Jun 21 12:32:54 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c (ffeexpr_fulfill_call_): Set array variable
- to avoid warning about uninitialized variable.
-
- * Make-lang.in: Get rid of any setting of HOST_* macros,
- since these will break gcc's build!
- * makefile: New file to make building derived files
- easier.
-
-Thu Jun 19 18:19:28 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * g77.c (main): Install Emilio Lopes' patch to support
- Ratfor, and to fix the printing of the version string
- to go to stderr, not stdout.
- * lang-specs.h: Install Emilio Lopes' patch to support
- Ratfor, and patch the result to support picking up
- `*f771' from the `specs' file.
-
-Thu Jun 12 14:36:25 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * storag.c (ffestorag_update_init, ffestorag_update_save):
- Also update parent, in case equivalence processing
- has already eliminated pointers to it via the
- local equivalence info.
-
-Tue Jun 10 14:08:26 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * intdoc.c: Add cross-reference to end of description
- of any generic intrinsic pointing to other intrinsics
- with the same name.
-
- Warn about explicit type declaration for intrinsic
- that disagrees with invocation:
- * expr.c (ffeexpr_paren_rhs_let_): Preserve type info
- for intrinsic functions.
- (ffeexpr_token_funsubstr_): Ditto.
- * intrin.c (ffeintrin_fulfill_generic): Warn if type
- info of fulfilled intrinsic invocation disagrees with
- explicit type info given symbol.
- (ffeintrin_fulfill_specific): Ditto.
- * stc.c (ffestc_R1208_item): Preserve type info
- for intrinsics.
- (ffestc_R501_item): Ditto.
-
-Mon Jun 9 17:45:44 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_expr_intrinsic_): Fix several of the
- libU77/libF77-unix handlers to properly convert their
- arguments.
-
- * com-rt.def (FFECOM_gfrtFSTAT): Append missing "i" to
- arg string.
-
-Fri Jun 6 14:37:30 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_expr_intrinsic_): Have a case statement
- for every intrinsic implementation, so missing ones
- are caught via gcc warnings.
- Don't call ffeintrin_codegen_imp anymore.
- * intrin.c (ffeintrin_fulfill_generic): Remove cg_imp
- stuff from here.
- (ffeintrin_codegen_imp): Delete this function.
- * intrin.def, intrin.h: Remove DEFIMQ stuff from here
- as well.
-
-Thu Jun 5 13:03:07 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * top.c (ffe_decode_option): New -fbadu77-intrinsics-*
- options.
- * top.h: Ditto.
- * intrin.h: New BADU77 family.
- * intrin.c (ffeintrin_state_family): Ditto.
-
- Implement new scheme to track intrinsic names vs. forms:
- * intrin.c (ffeintrin_fulfill_generic),
- (ffeintrin_fulfill_specific), (ffeintrin_is_intrinsic),
- intrin.def: The documented name is now either in the
- generic info or, if no generic, in the specific info.
- For a generic, the specific info contains merely the
- distinguishing form (usually "function" or "subroutine"),
- used for diagnostics about ambiguous references and
- in the documentation.
-
- * intrin.def: Clean up formatting of DEFNAME block.
- Convert many libU77 intrinsics into generics that
- support both subroutine and function forms.
- Put the function forms of side-effect routines into
- the new BADU77 family.
- Make MCLOCK and TIME return INTEGER*4 again, and add
- INTEGER*8 equivalents called MCLOCK8 and TIME8.
- Fix up more status return values to be written and
- insist on them being I1 as well.
- * com.c (ffecom_expr_intrinsic_): Lots of changes to
- support new libU77 intrinsic interfaces.
-
-Mon Jun 2 00:37:53 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_init_0): Pointer type is now INTEGER(KIND=7),
- not INTEGER(KIND=0), since we want to reserve KIND=0 for
- future use.
-
-Thu May 29 14:30:33 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix bugs preventing CTIME(I*4) from working correctly:
- * com.c (ffecom_char_args_): For FUNCREF case, process
- args to intrinsic just as they would be in
- ffecom_expr_intrinsic_.
- * com-rt.def (FFECOM_gfrtCTIME, FFECOM_gfrtTTYNAM): Fix
- argument decls to specify `&'.
-
-Wed May 28 22:19:49 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix gratuitous warnings exposed by dophot aka 970528-1:
- * global.c (ffeglobal_proc_def_arg, ffeglobal_proc_ref_arg):
- Support distinct function/subroutine arguments instead of
- just procedures.
- * global.h: Ditto.
- * expr.c (ffeexpr_fulfill_call_): A SYMTER with kindNONE
- also is a procedure (either function or subroutine).
-
-Mon May 26 20:25:31 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * bad.def: Have several lexer diagnostics refer to
- documentation for people who need more info on what Fortran
- source code is supposed to look like.
-
- * expr.c (ffeexpr_reduced_bool1_), bad.def: New diagnostics
- specific to .NOT. now mention only one operand instead
- of two.
-
- * g77.c: Recognize -fsyntax-only, similar to -c etc.
- (lookup_option): Fix bug that prevented non-`--' options
- from being recognized.
-
-Sun May 25 04:29:04 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * intrin.def (FFEINTRIN_impCTIME): Accept `I*' expression
- for STime instead of requiring `I2'.
-
-Tue May 20 16:14:40 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * symbol.c (ffesymbol_reference): All references to
- standard intrinsics are considered explicit, so as
- to avoid generating basically useless warnings.
- * intrin.c, intrin.h (ffeintrin_is_standard): Returns TRUE
- if intrinsic is standard.
-
-Sun May 18 21:14:59 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com-rt.def: Changed all external names of the
- form `"\([a-z0-9]*\)_' to `"G77_\1_0"' so as to
- allow any name valid as an intrinsic to be used
- as such and as a user-defined external procedure
- name or common block as well.
-
-Thu May 8 13:07:10 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c (ffeexpr_cb_end_notloc_): For %VAL, %REF, and
- %DESCR, copy arg info into new node.
-
-Mon May 5 14:42:17 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- From Uwe F. Mayer <mayer@math.Vanderbilt.Edu>:
- * Make-lang.in (g77-cross): Fix typo in g77.c path.
-
- From Brian McIlwrath <bkm@star.rl.ac.uk>:
- * lang-specs.h: Have g77 pick up options from a section
- labeled `*f771' of the `specs' file.
-
-Sat May 3 02:46:08 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * intrin.def (FFEINTRIN_defSIGNAL): Add optional `Status'
- argument that com.c already expects (per Dave Love).
-
- More changes to support better tracking of (filewide)
- globals, in particular, the arguments to procedures:
- * bad.def (FFEBAD_FILEWIDE_NARGS, FFEBAD_FILEWIDE_NARGS_W,
- FFEBAD_FILEWIDE_ARG, FFEBAD_FILEWIDE_ARG_W): New diagnostics.
- * expr.c (ffebad_fulfill_call_): Provide info on each
- argument to ffeglobal.
- * global.c, global.h (ffeglobal_proc_def_arg,
- ffeglobal_proc_def_nargs, ffeglobal_proc_ref_arg,
- ffeglobal_proc_ref_args): New functions.
- (ffeglobalArgSummary, ffeglobalArgInfo_): New types.
-
-Tue Apr 29 18:35:41 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- More changes to support better tracking of (filewide)
- globals:
- * expr.c (ffeexpr_fulfill_call_): New function.
- (ffeexpr_token_name_lhs_): Call after building procedure
- reference expression. Also leave info field for ANY-ized
- expression alone.
- (ffeexpr_token_arguments_): Ditto.
-
-Mon Apr 28 20:04:18 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Changes to support better tracking of (filewide)
- globals, mainly to avoid crashes due to inlining:
- * bad.def: Go back to quoting intrinsic names,
- (FFEBAD_FILEWIDE_DISAGREEMENT, FFEBAD_FILEWIDE_TIFF,
- FFEBAD_FILEWIDE_TYPE_MISMATCH): New diagnostics.
- (FFEBAD_INTRINSIC_EXPIMP, FFEBAD_INTRINSIC_GLOBAL): Reword
- for clarity.
- * com.c (ffecom_do_entry_, ffecom_start_progunit_,
- ffecom_sym_transform_): Accommodate new FFEGLOBAL_typeEXT
- possibility.
- * expr.c (ffeexpr_sym_lhs_call_, ffeexpr_sym_lhs_extfunc_,
- ffeexpr_sym_rhs_actualarg_, ffeexpr_declare_parenthesized_,
- ffeexpr_paren_rhs_let_, ffeexpr_token_funsubstr_):
- Fill in real kind info instead of leaving NONE where
- appropriate.
- Register references to intrinsics and globals with ffesymbol
- using new ffesymbol_reference function instead of
- ffesymbol_globalize.
- * global.c (ffeglobal_type_string_): New array for
- new diagnostics.
- * global.h, global.c:
- Replace ->init mechanism with ->tick mechanism.
- Move other common-related members into a substructure of
- a union, so the proc substructure can be introduced
- to include members related to externals other than commons.
- Don't complain about ANY-ized globals; ANY-ize globals
- once they're complained about, in any case where code
- generation could become a problem.
- Handle global entries that have NONE type (seen as
- intrinsics), EXT type (seen as EXTERNAL), and so on.
- Keep track of kind and type of externals, both via
- definition and via reference.
- Diagnose disagreements about kind or type of externals
- (such as functions).
- (ffeglobal_ref_intrinsic, ffeglobal_ref_progunit_): New
- functions.
- * stc.c (ffestc_R1207_item, ffestc_R1208_item,
- ffestc_R1219, ffestc_R1226):
- Call ffesymbol_reference, not ffesymbol_globalize.
- * stu.c (ffestu_sym_end_transition,
- ffestu_sym_exec_transition):
- Call ffesymbol_reference, not ffesymbol_globalize.
- * symbol.c (ffesymbol_globalize): Removed...
- (ffesymbol_reference): ...to this new function,
- which more generally registers references to symbols,
- globalizes globals, and calls on the ffeglobal module
- to check globals filewide.
-
- * global.h, global.c: Rename some macros and functions
- to more clearly distinguish common from other globals.
- All callers changed.
-
- * com.c (ffecom_sym_transform_): Trees describing
- filewide globals must be allocated on permanent obstack.
-
- * expr.c (ffeexpr_token_name_lhs_): Don't generate
- gratuitous diagnostics for FFEINFO_whereANY case.
-
-Thu Apr 17 03:27:18 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * global.c: Add support for flagging intrinsic/global
- confusion via warnings.
- * bad.def (FFEBAD_INTRINSIC_EXPIMP,
- FFEBAD_INTRINSIC_GLOBAL): New diagnostics.
- * expr.c (ffeexpr_token_funsubstr_): Ditto.
- (ffeexpr_sym_lhs_call_): Ditto.
- (ffeexpr_paren_rhs_let_): Ditto.
- * stc.c (ffestc_R1208_item): Ditto.
-
-Wed Apr 16 22:40:56 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c (ffeexpr_declare_parenthesized_): INCLUDE
- context can't be an intrinsic invocation either.
-
-Fri Mar 28 10:43:28 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c (ffeexpr_token_arguments_): Make sure top of
- exprstack is operand before dereferencing operand field.
-
- * lex.c (ffelex_prepare_eos_): Fill up truncated
- hollerith token, so crash on null ->text field doesn't
- happen later.
-
- * stb.c (ffestb_R10014_): If NAMES isn't recognized (or
- the recognized part is followed in the token by a
- non-digit), don't try and collect digits, as there
- might be more than FFEWHERE_indexMAX letters to skip
- past to do so -- and the code is diagnosed anyway.
-
-Thu Mar 27 00:02:48 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_sym_transform_): Force local
- adjustable array onto stack.
-
- * stc.c (ffestc_R547_item_object): Don't actually put
- the symbol in COMMON if the symbol has already been
- EQUIVALENCE'd to a different COMMON area.
-
- * equiv.c (ffeequiv_add): Don't actually do anything
- if there's a disagreement over which COMMON area is
- involved.
-
-Tue Mar 25 03:35:19 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_transform_common_): If no explicit init
- of COMMON area, don't actually init it even though
- storage area suggests it.
-
-Mon Mar 24 12:10:08 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * lex.c (ffelex_image_char_): Avoid overflowing the
- column counter itself, as well as the card image.
-
- * where.c (ffewhere_line_new): Cast ffelex_line_length()
- to (size_t) so 255 doesn't overflow to 0!
-
- * stc.c (ffestc_labeldef_notloop_begin_): Don't gratuitously
- terminate loop before processing statement, so block
- doesn't disappear out from under EXIT/CYCLE processing.
- (ffestc_labeldef_notloop_): Has old code from above
- function, instead of just calling it.
-
- * expr.c (ffeexpr_cb_comma_i_4_): Don't skip over
- arbitrary token (such as EOS).
-
- * com.c (ffecom_init_zero_): Handle RECORD_TYPE and
- UNION_TYPE so -fno-zeros works with -femulated-complex.
-
-1997-03-12 Dave Love <d.love@dl.ac.uk>
-
- * intrin.def: New intrinsics INT2, INT8, CPU_TIME. Fix AND, OR,
- XOR. [Integrated by burley, AND/OR/XOR already fixed, INT8
- implementation changed/fixed.]
-
-Wed Mar 12 10:40:08 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in ($(srcdir)/f/intdoc.texi): Simplify rules
- so building f/intdoc is not always necessary; remove
- f/intdoc after running it if it is built.
-
-Tue Mar 11 23:42:00 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * intrin.def (FFEINTRIN_impAND, FFEINTRIN_impOR,
- FFEINTRIN_impXOR): Use the IAND, IOR, and IEOR implementations
- of these, instead of crashing in ffecom_expr_intrinsic_
- or adding case labels there.
-
-Mon Mar 10 22:51:23 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * intdoc.c: Fix so any C compiler can compile this.
-
-Fri Feb 28 13:16:50 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Version 0.5.20 released.
-
-Fri Feb 28 01:45:25 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in (RUNTIMESTAGESTUFF, LIBU77STAGESTUFF):
- Move some files incorrectly in the former to the latter,
- and add another file or two to the latter.
-
- New meanings for (KIND=n), and new denotations in the
- little language describing intrinsics:
- * com.c (ffecom_init_0): Assign new meanings.
- * intdoc.c: Document new meanings.
- Support the new denotations.
- * intrin.c: Employ new meanings, mapping them to internal
- values (which are the same as they ever were for now).
- Support the new denotations.
- * intrin.def: Switch DEFIMP table to the new denotations.
-
- * intrin.c (ffeintrin_check_): Fix bug that was leaving
- LOC() and %LOC() returning INTEGER*4 on systems where
- it should return INTEGER*8.
-
- * type.c: Canonicalize function definitions, for etags
- and such.
-
-Wed Feb 26 20:43:03 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_init_0): Choose INTEGER(KIND=n) types,
- where n is 2, 3, and 4, according to the new docs
- instead of according to the old C correspondences
- (which seem less useful at this point).
-
- * equiv.c (ffeequiv_destroy_): New function.
- (ffeequiv_layout_local_): Use this new function
- whenever the laying out of a local equivalence chain
- is aborted for any reason.
- Otherwise ensure that symbols no longer reference
- the stale ffeequiv entries that result when they
- are killed off in this procedure.
- Also, the rooted symbol is one that has storage,
- it really is irrelevant whether it has an equiv entry
- at this point (though the code to remove the equiv
- entry was put in at the end, just in case).
- (ffeequiv_kill): When doing internal checks, make
- sure the victim isn't named by any symbols it points
- to. Not as complete a check as looking through the
- entire symbol table (which does matter, since some
- code in equiv.c used to remove symbols from the lists
- for an ffeequiv victim but not remove that victim as the
- symbol's equiv info), but this check did find some
- real bugs in the code (that were fixed).
-
-Mon Feb 24 16:42:13 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_expr_intrinsic_): Fix a couple of
- warnings about uninitialized variables.
- * intrin.c (ffeintrin_check_): Ditto, but there were
- a couple of _real_ uninitialized-variable _bugs_ here!
- (ffeintrin_fulfill_specific): Ditto, no real bug here.
-
-Sun Feb 23 15:01:20 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Clean up diagnostics (especially about intrinsics):
- * bad.def (FFEBAD_UNIMPL_STMT): Remove.
- (FFEBAD_INTRINSIC_*, FFEBAD_NEED_INTRINSIC): Clean these
- up so they're friendlier.
- (FFEBAD_INTRINSIC_CMPAMBIG): New.
- * intrin.c (ffeintrin_fulfill_generic,
- ffeintrin_fulfill_specific, ffeintrin_is_intrinsic):
- Always choose
- generic or specific name text (which is for doc purposes
- anyway) over implementation name text (which is for
- internal use).
- * intrin.def: Use more descriptive name texts for generics
- and specifics in cases where the names themselves are not
- enough (e.g. IDATE, which has two forms).
-
- Fix some intrinsic mappings:
- * intrin.def (FFEINTRIN_specIDINT, FFEINTRIN_specAND,
- FFEINTRIN_specDFLOAT, FFEINTRIN_specDREAL, FFEINTRIN_specOR,
- FFEINTRIN_specXOR): Now have their own implementations,
- instead of borrowing from others.
- (FFEINTRIN_specAJMAX0, FFEINTRIN_specAJMIN0, FFEINTRIN_specBJTEST,
- FFEINTRIN_specDFLOTJ, FFEINTRIN_specFLOATJ, FFEINTRIN_specJIABS,
- FFEINTRIN_specJIAND, FFEINTRIN_specJIBCLR, FFEINTRIN_specJIBITS,
- FFEINTRIN_specJIBSET, FFEINTRIN_specJIDIM, FFEINTRIN_specJIDINT,
- FFEINTRIN_specJIDNNT, FFEINTRIN_specJIEOR, FFEINTRIN_specJIFIX,
- FFEINTRIN_specJINT, FFEINTRIN_specJIOR, FFEINTRIN_specJISHFT,
- FFEINTRIN_specJISHFTC, FFEINTRIN_specJISIN, FFEINTRIN_specJMAX0,
- FFEINTRIN_specJMAX1, FFEINTRIN_specJMIN0, FFEINTRIN_specJMIN1,
- FFEINTRIN_specJMOD, FFEINTRIN_specJNINT, FFEINTRIN_specJNOT,):
- Turn these implementations off, since it's not clear
- just what types they expect in the context of portable Fortran.
- (DFLOAT): Now in FVZ family, since f2c supports them
-
- Support intrinsic inquiry functions (BIT_SIZE, LEN):
- * intrin.c: Allow `i' in <arg_extra>.
- * intrin.def (FFEINTRIN_impBIT_SIZE, FFEINTRIN_impLEN):
- Mark args with `i'.
-
-Sat Feb 22 13:34:09 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Only warn, don't error, for reference to unimplemented
- intrinsic:
- * bad.def (FFEBAD_INTRINSIC_UNIMPLW): Warning version
- of _UNIMPL.
- * intrin.c (ffeintrin_is_intrinsic): Use new warning
- version of _UNIMPL (FFEBAD_INTRINSIC_UNIMPLW).
-
- Complain about REAL(Z) and AIMAG(Z) (Z is DOUBLE COMPLEX):
- * bad.def (FFEBAD_INTRINSIC_CMPAMBIG): New diagnostic.
- * expr.c: Needed #include "intrin.h" anyway.
- (ffeexpr_token_intrincheck_): New function handles delayed
- diagnostic for "REAL(REAL(expr)" if next token isn't ")".
- (ffeexpr_token_arguments_): Do most of the actual checking here.
- * intrin.h, intrin.c (ffeintrin_fulfill_specific): New
- argument, check_intrin, to tell caller that intrin is REAL(Z)
- or AIMAG(Z). All callers updated, mostly to pass NULL in
- for this.
- (ffeintrin_check_): Also has new arg check_intrin for same
- purpose. All callers updated the same way.
- * intrin.def (FFEINTRIN_impAIMAG): Change return type
- from "R0" to "RC", to accommodate f2c (and perhaps other
- non-F90 F77 compilers).
- * top.h, top.c: New option -fugly-complex.
-
- New GNU intrinsics REALPART, IMAGPART, and COMPLEX:
- * com.c (ffecom_expr_intrinsic_): Implement impCOMPLEX
- and impREALPART here. (specIMAGPART => specAIMAG.)
- * intrin.def: Add the intrinsics here.
-
- Rename implementations of VXTIDATE and VXTTIME to IDATEVXT
- and TIMEVXT, so they sort more consistently:
- * com.c (ffecom_expr_intrinsic_):
- * intrin.def:
-
- Delete intrinsic group `dcp', add `gnu', etc.:
- * intrin.c (ffeintrin_state_family): FFEINTRIN_familyGNU
- replaces FFEINTRIN_familyDCP, and gets state from `gnu'
- group.
- Get rid of FFEINTRIN_familyF2Z, nobody needs it.
- Move FFEINTRIN_specDCMPLX from DCP family to FVZ family,
- as f2c has it.
- Move FFEINTRIN_specDFLOAT from F2C family to FVZ family.
- (FFEINTRIN_specZABS, FFEINTRIN_specZCOS, FFEINTRIN_specZEXP,
- FFEINTRIN_specZLOG, FFEINTRIN_specZSIN, FFEINTRIN_specZSQRT):
- Move these from F2Z family to F2C family.
- * intrin.h (FFEINTRIN_familyF2Z, FFEINTRIN_familyDCP): Remove.
- (FFEINTRIN_familyGNU): Add.
- * top.h, top.c: Replace `dcp' with `gnu'.
-
- * com.c (ffecom_expr_intrinsic_): Clean up by collecting
- simple conversions into one nice, conceptual place.
- Fix up some intrinsic subroutines (MVBITS, KILL, UMASK) to
- properly push and pop call temps, to avoid wasting temp
- registers.
-
- * g77.c (doit): Toon says variables should be defined
- before being referenced. Spoilsport.
-
- * intrin.c (ffeintrin_check_): Now Dave's worried about
- warnings about uninitialized variables. Okay, so for
- basic return values 'g' and 's', they _were_
- uninitialized -- is determinism really _that_ useful?
-
- * intrin.def (FFEINTRIN_impFGETC): Fix STATUS argument
- so that it is INTENT(OUT) instead of INTENT(IN).
-
-1997-02-21 Dave Love <d.love@dl.ac.uk>
-
- * intrin.def, com.c: Support Sun-type `short' and `long'
- intrinsics. Perhaps should also do Microcruft-style `int2'.
-
-Thu Feb 20 15:16:53 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_expr_intrinsic_): Clean up indentation.
- Support SECONDSUBR intrinsic implementation.
- Rename SECOND to SECONDFUNC for direct support via library.
-
- * g77.c: Fix to return proper status value to shell,
- by obtaining it from processes it spawns.
-
- * intdoc.c: Fix minor typo.
-
- * intrin.def: Turn SECOND into generic that maps into
- function and subroutine forms.
-
- * intrin.def: Make FLOAT and SNGL into specific intrinsics.
-
- * intrin.def, intrin.h: Change the way DEFGEN and DEFSPEC
- macros work, to save on verbage.
-
-Mon Feb 17 02:08:04 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- New subsystem to automatically generate documentation
- on intrinsics:
- * Make-lang.in ($(srcdir)/f/g77.info,
- $(srcdir)/f/g77.dvi): Move g77 doc rules around.
- Add to g77 doc rules the new subsystem.
- (f77.mostlyclean, f77.maintainer-clean): Also clean up
- after new doc subsystem.
- * intdoc.c, intdoc.h: New doc subsystem code.
- * intrin.h [FFEINTRIN_DOC]: When 1, don't pull in
- stuff not needed by doc subsystem.
-
- Improve on intrinsics mechanism to both be more
- self-documenting and to catch more user errors:
- * intrin.c (ffeintrin_check_): Recognize new arg-len
- and arg-rank information, and check it.
- Move goto and signal indicators to the basic type.
- Permit reference to arbitrary argument number, not
- just first argument (for BESJN and BESYN).
- (ffeintrin_init_0): Check and accept new notations.
- * intrin.c, intrin.def: Value in COL now identifies
- arguments starting with number 0 being the first.
-
- Some minor intrinsics cleanups (resulting from doc work):
- * com.c (ffecom_expr_intrinsic_): Implement FLUSH
- directly once again, handle its optional argument,
- so it need not be a generic (awkward to handle in docs).
- * intrin.def (BESJ0, BESJ1, BESJN, BESY0, BESY1, BESYN,
- CHDIR, CHMOD, CTIME, DBESJ0, DBESJ1, DBESJN, DBESY0,
- DBESY1, DBESYN, DDIM, ETIME, FGETC, FNUM, FPUTC, FSTAT,
- GERROR, GETCWD, GETGID, GETLOG, GETPID, GETUID, GMTIME,
- HOSTNM, IDATE, IERRNO, IIDINT, IRAND, ISATTY, ITIME, JIDINT,
- LNBLNK, LSTAT, LTIME, MCLOCK, PERROR, SRAND, SYMLNK, TTYNAM,
- UMASK): Change capitalization of initcaps (official) name
- to be consistent with Burley's somewhat arbitrary rules.
- (BESJN, BESYN): These have return arguments of same type
- as their _second_ argument.
- (FLUSH): Now a specific, not generic, intrinsic, with one
- optional argument.
- (FLUSH1): Eliminated.
- Add arg-len and arg-rank info to several intrinsics.
- (ITIME): Change argument type from REAL to INTEGER.
-
-Tue Feb 11 14:04:42 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in (f771): Invocation of Makefile now done
- with $(srcdir)=gcc to go along with $(VPATH)=gcc.
- ($(srcdir)/f/runtime/configure,
- $(srcdir)/f/runtime/libU77/configure): Break these out
- so spurious triggers of this rule don't happen (as when
- configure.in is more recent than libU77/configure).
- (f77.rebuilt): Distinguish source versus build files,
- so this target can be invoked from build directory and
- still work.
- * Makefile.in: This now expects $(srcdir) to be the gcc
- source directory, not gcc/f, to agree with $(VPATH).
- Accordingly, $(INCLUDES) has been fixed, various cruft
- removed, the removal of f771 has been fixed to remove
- the _real_ f771 (not the one in gcc's parent directory),
- and so on.
-
- * lex.c: Part of ffelex_finish_statement_() now done
- by new function ffelex_prepare_eos_(), so that, in one
- popular case, the EOS can be prepared while the pointer
- is at the end of the non-continued line instead of the
- end of the line that marks no continuation. This improves
- the appearance of diagnostics substantially.
-
-Mon Feb 10 12:44:06 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in: runtime Makefile's, and include/f2c.h,
- also depend on f/runtime/configure and f/runtime/libU77/configure.
-
- Fix various libU77 routines:
- * com-rt.def (FFECOM_gfrtCTIME, FFECOM_gfrtMCLOCK,
- FFECOM_gfrtTIME): These now use INTEGER*8 for time values,
- for compatibility with systems like Alpha.
- (FFECOM_gfrtSYSTEM_CLOCK, FFECOM_gfrtTTYNAM): Delete incorrect
- trailing underscore in routine names.
- * intrin.c, intrin.def: Support INTEGER*8 return values and
- arguments ('4'). Change FFEINTRIN_impCTIME, FFEINTRIN_impMCLOCK,
- and FFEINTRIN_impTIME accordingly.
- (ffeintrin_is_intrinsic): Don't give caller a clue about
- form of intrinsic -- shouldn't be needed at this point.
-
- Cope with generic intrinsics that are subroutines and functions:
- * com.c (ffecom_finish_symbol_transform_, ffecom_expr_transform_):
- Don't transform an intrinsic that is not known to be a subroutine
- or a function. (Maybe someday have to avoid transforming
- any intrinsic with an undecided or unknown implementation.)
- * expr.c (ffeexpr_declare_unadorned_,
- ffeexpr_declare_parenthesized_): Ok to invoke generic
- intrinsic that has at least one subroutine form as a
- subroutine.
- Ok to pass intrinsic as actual arg if it has a known specific
- intrinsic form that is valid as actual arg.
- (ffeexpr_declare_parenthesized_): An unknown kind of
- intrinsic has a paren_type chosen based on context.
- (ffeexpr_token_arguments_): Build funcref/subrref based
- on context, not on kind of procedure being called.
- * intrin.h, intrin.c (ffeintrin_is_intrinsic): Undo changes of
- Tue Feb 4 23:12:04 1997 by me, change all callers to leave
- intrinsics as FFEINFO_kindNONE at this point. (Some callers
- also had unused variables deleted as a result.)
-
- Enable all intrinsic groups (especially f90 and vxt):
- * target.h (FFETARGET_defaultSTATE_DCP, FFETARGET_defaultSTATE_F2C,
- FFETARGET_defaultSTATE_F90, FFETARGET_defaultSTATE_MIL,
- FFETARGET_defaultSTATE_UNIX, FFETARGET_defaultSTATE_VXT):
- Delete these macros, let top.c set them directly.
- * top.c (ffeintrinsic_state_dcp_, ffe_intrinsic_state_f2c_,
- ffe_intrinsic_state_f90_, ffe_intrinsic_state_mil_,
- ffe_intrinsic_state_unix_, ffe_intrinsic_state_vxt_):
- Enable all these directly.
-
-Sat Feb 8 03:21:50 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * g77.c: Incorporate recent changes to ../gcc.c.
- For version magic (e.g. `g77 -v'), instead of compiling
- /dev/null, write, compile, run, and then delete a small
- program that prints the version numbers of the three
- components of libf2c (libF77, libI77, and libU77),
- so we get this info with bug reports.
- Also, this change reduces the chances of accidentally
- linking to an old (complex-alias-problem) libf2c.
- Fix `-L' so the argument is expected in `-Larg'.
-
- * com.h (FFECOM_f2cLONGINT): For INTEGER*8 support in f2c.h,
- dynamically determine proper type here, instead of
- assuming `long long int' is correct.
-
-Tue Feb 4 23:12:04 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Add libU77 library from Dave Love <d.love@dl.ac.uk>:
- * Make-lang.in (f77-runtime): Depend on new Makefile.
- (f/runtime/libU77/Makefile): New rule.
- Also configure libU77.
- ($(srcdir)/f/runtime/configure: Use Makefile.in,
- so configuration doesn't have to have happened.
- (f77.mostlyclean, f77.clean, f77.distclean,
- f77.maintainer-clean): Some fixups here, but more work
- needed.
- (RUNTIMESTAGESTUFF): Add libU77's config.status.
- (LIBU77STAGESTUFF, f77.stage1, f77.stage2, f77.stage3,
- f77.stage4): New macro, appropriate uses added.
- * com-rt.def: Add libU77 procedures.
- * com.c (ffecom_f2c_ptr_to_integer_type_node,
- ffecom_f2c_ptr_to_real_type_node): New type nodes.
- (FFECOM_rttypeCHARACTER_): New type of run-time function.
- (ffecom_char_args_): Handle CHARACTER*n intrinsics
- where n != 1 here, instead of in ffecom_expr_intrinsic_.
- (ffecom_expr_intrinsic_): New code to handle new
- intrinsics.
- In particular, change how FFEINTRIN_impFLUSH is handled.
- (ffecom_make_gfrt_): Handle new type of run-time function.
- (ffecom_init_0): Initialize new type nodes.
- * config-lang.in: New libU77 directory.
- * intrin.h, intrin.c (ffeintrin_is_intrinsic): Handle
- potential generic for subroutine _and_ function
- specifics via two new arguments. All callers changed.
- Properly ignore deleted/disabled intrinsics in resolving
- generics.
- (ffeintrin_check_, ffeintrin_init_0): Handle CHARACTER intrinsics of (*)
- length.
- * intrin.def: Permission granted by FSF to place this in
- public domain, which will allow it to serve as source
- for both g77 program and its documentation.
- Add libU77 intrinsics.
- (FLUSH): Now a generic, not specific, intrinsic.
- (DEFIMP): Now support return modifier for CHARACTER intrinsics.
-
- * com-rt.def (FFECOM_gfrtDIM, FFECOM_gfrtERF,
- FFECOM_gfrtERFC, FFECOM_gfrtEXP, FFECOM_gfrtSIGN,
- FFECOM_gfrtSIN, FFECOM_gfrtSINH, FFECOM_gfrtTAN,
- FFECOM_gfrtTANH, FFECOM_gfrtPOW_RI): Change "&r" to "&f".
-
-Sat Feb 1 12:15:09 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Version 0.5.19.1 released.
-
- * com.c (ffecom_expr_, ffecom_expr_intrinsic_,
- ffecom_tree_divide_): FFECOM_gfrtPOW_ZI,
- FFECOM_gfrtCONJG, FFECOM_gfrtDCONJG,
- FFECOM_gfrtCCOS, FFECOM_gfrtCDCOS,
- FFECOM_gfrtCLOG, FFECOM_gfrtCDLOG,
- FFECOM_gfrtCSIN, FFECOM_gfrtCDSIN,
- FFECOM_gfrtCSQRT, FFECOM_gfrtCDSQRT,
- FFECOM_gfrtDIV_CC, FFECOM_gfrtDIV_ZZ: These all require
- result to _not_ overlap one or more inputs.
-
-Sat Feb 1 00:25:55 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_init_0): Do internal checks only if
- -fset-g77-defaults not specified.
-
- Fix %LOC(), LOC() to return sufficiently wide type:
- * com.h, com.c (ffecom_pointer_kind_, ffecom_label_kind_,
- ffecom_pointer_kind(), ffecom_label_kind()): New globals
- and accessor macros hold kind for integer pointers on target
- machine.
- (ffecom_init_0): Determine narrowest INTEGER type that
- can hold a pointer (usually INTEGER*4 or INTEGER*8),
- store it in ffecom_pointer_kind_, etc.
- * expr.c (ffeexpr_cb_end_loc_): Use right type for %LOC().
- * intrin.c (ffeintrin_check_, ffeintrin_init_0): Support
- new 'p' kind for type of intrinsic.
- * intrin.def (FFEINTRIN_impLOC): Returns "Ip" instead of "I1",
- so LOC() type is correct for target machine.
-
- Support -fugly-assign:
- * lang-options.h, top.h, top.c (ffe_decode_option):
- Accept -fugly-assign and -fno-ugly-assign.
- * com.c (ffecom_expr_): Handle -fugly-assign.
- * expr.c (ffeexpr_finished_): Check right type for ASSIGN
- contexts.
-
-Fri Jan 31 14:30:00 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Remove last vestiges of -fvxt-not-f90:
- * stb.c (ffestb_R10012_, ffestb_R10014_, ffestb_V0201_):
- top.c, top.h:
-
-Fri Jan 31 02:13:54 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * top.c (ffe_decode_option): Warn if -fugly is specified,
- it'll go away soon.
-
- * symbol.h: No need to #include "bad.h".
-
- Reorganize features from -fvxt-not-f90 to -fvxt:
- * lang-options.h, top.h, top.c:
- Accept -fvxt and -fno-vxt, but not -fvxt-not-f90 or -ff90-not-vxt.
- Warn if the latter two are used.
- * expr.c (ffeexpr_nil_rhs_): Double-quote means octal constant.
- (ffeexpr_token_rhs_): Double-quote means octal constant.
- * target.h (FFETARGET_defaultIS_VXT_NOT_90): Delete macro
- definition, no longer needed.
-
- Make some -ff90 features the default:
- * data.c (ffedata_value): DATA implies SAVE.
- * src.h (ffesrc_is_name_noninit): Underscores always okay.
-
- Fix up some more #error directives by quoting their text:
- * bld.c (ffebld_constant_is_zero):
- * target.h:
-
-Sat Jan 18 18:22:09 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * g77.c (lookup_option, main): Recognize `-Xlinker',
- `-Wl,', `-l', `-L', `--library-directory', `-o',
- `--output'.
- (lookup_option): Don't depend on SWITCH_TAKES_ARG
- being correct, it might or might not have `-x' in
- it depending on host.
- Return NULL argument if it would be an empty string.
- (main): If no input files (by gcc.c's definition)
- but `-o' or `--output' specified, produce diagnostic
- to avoid overwriting output via gcc.
- Recognize C++ `+e' options.
- Treat -L as another non-magical option (like -B).
- Don't append_arg `-x' twice.
-
-Fri Jan 10 23:36:00 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * top.c [BUILT_FOR_270] (ffe_decode_option): Make
- -fargument-noalias-global the default.
-
-Fri Jan 10 07:42:27 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Enable inlining of previously-compiled program units:
- * com.c (ffecom_do_entry_, ffecom_start_progunit_):
- Register new public function in ffeglobal database.
- (ffecom_sym_transform_): Any GLOBAL or potentially GLOBAL
- symbol should be looked up in ffeglobal database and
- that tree node used, if found. That way, gcc knows
- the references are to those earlier definitions, so it
- can emit shorter branches/calls, inline, etc.
- (ffecom_transform_common_): Minor change for clarity.
- * expr.c (ffeexpr_sym-lhs_call_, ffeexpr_sym_lhs_extfunc_,
- ffeexpr_sym_rhs_actualarg_, ffeexpr_paren_rhs_let_,
- ffeexpr_token_funsubstr_): Globalize symbol as needed.
- * global.c (ffeglobal_promoted): New function to look up
- existing local symbol in ffeglobal database.
- * global.h: Declare new function.
- * name.h (ffename_token): New macro, plus alphabetize.
- * stc.c (ffestc_R1207_item): Globalize EXTERNAL symbol.
- * stu.c (ffestu_sym_end_transition, ffestu_sym_exec_transition):
- Globalize symbol as needed.
- * symbol.h, symbol.c (ffesymbol_globalize): New function.
-
-Thu Jan 9 14:20:00 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * ste.c (ffeste_R809): Produce a diagnostic for SELECT CASE
- on CHARACTER type, instead of crashing.
-
-Thu Jan 9 00:52:45 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * stc.c (ffestc_order_entry_, ffestc_order_format_,
- ffestc_R1226): Allow ENTRY and FORMAT before IMPLICIT
- NONE, by having them transition only to state 1 instead
- of state 2 (which is disallowed by IMPLICIT NONE).
-
-Mon Jan 6 22:44:53 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix AXP bug found by Rick Niles (961201-1.f):
- * com.c (ffecom_init_0): Undo my 1996-05-14 change, as
- it is incorrect and prevented easily finding this bug.
- * target.h [__alpha__] (ffetargetReal1, ffetargetReal2):
- Use int instead of long.
- (ffetarget_cvt_r1_to_rv_, ffetarget_cvt_rv_to_r1_,
- ffetarget_cvt_r2_to_rv_, ffetarget_cvt_rv_to_r2_):
- New functions that intercede for callers of
- REAL_VALUE_(TO|UNTO)_TARGET_(SINGLE|DOUBLE).
- All callers changed, and damaging casts to (long *) removed.
-
-Sun Jan 5 03:26:11 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in (g77, g77-cross): Depend on both g77.c and
- zzz.c, in $(srcdir)/f/.
-
- Better design for -fugly-assumed:
- * stc.c (ffestc_R501_item, ffestc_R524_item,
- ffestc_R547_item_object): Pass new is_ugly_assumed flag.
- * stt.c, stt.h (ffestt_dimlist_as_expr,
- ffestt_dimlist_type): New is_ugly_assumed flag now
- controls whether "1" is treated as "*".
- Don't treat "2-1" or other collapsed constants as "*".
-
-Sat Jan 4 15:26:22 1997 Craig Burley <burley@gnu.ai.mit.edu>
-
- * stb.c (ffestb_R10012_): Don't confirm on FORMAT(A,)
- or even FORMAT(A,,B), as R1229 only warns about the
- former currently, and this seems reasonable.
-
- Improvements to diagnostics:
- * sta.c (ffesta_second_): Don't add any ffestb parsers
- unless they're specifically called for.
- Set up ffesta_tokens[0] before calling ffestc_exec_transition,
- else stale info might get used.
- (ffesta_save_): Do a better job picking which parser to run
- after running all parsers with no confirmed possibles.
- (FFESTA_maxPOSSIBLES_): Decrease from 100 now that so few
- possibles are ever on the list at a given time.
- (struct _ffesta_possible): Add named attribute.
- (ffesta_add_possible_exec_, ffesta_add_possible_nonexec_):
- Make these into macros that call a single function that now
- sets the named attribute.
- (ffesta_add_possible_unnamed_exec_,
- ffeseta_add_possible_unnamed_nonexec_): New macros.
- (ffesta_second_): Designate unnamed possibles as
- appropriate.
- * stb.c (ffestb_R1229, ffestb_R12291_): Use more general
- diagnostic, so things like "POINTER (FOO, BAR)" are
- diagnosed as unrecognized statements, not invalid statement
- functions.
- * stb.h, stb.c (ffestb_unimplemented): Remove function.
-
-1996-12-30 Dave Love <d.love@dl.ac.uk>
-
- * com.c: #include libU77/config.h
- (ffecom_f2c_ptr_to_integer_type_node,
- ffecom_f2c_ptr_to_integer_type_node): New variables.
- (ffecom_init_0): Use them.
- (ffecom_expr_intrinsic_): Many news cases for libU77 intrinsics.
-
- * com-rt.def: New definitions for libU77.
- * intrin.def: Likewise. Also correct ftell arg spec.
-
- * Makefile.in (f/runtime/libU77/config.h): New target for com.c
- dependency.
- * Make-lang.in (f771): Depend on f/runtime/Makefile for the above.
-
-Sat Dec 28 12:28:29 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * stt.c (ffestt_dimlist_type): Treat ([...,]1) in dimlist
- as ([...,]*) if -fugly-assumed, so assumed-size array
- detected early enough.
-
-Thu Dec 19 14:01:57 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * target.h (FFETARGET_REAL_VALUE_FROM_INT_): Conditionalize
- definition on BUILT_FOR_280, not BUILT_WITH_280, since
- the name of the macro was (properly) changed since 0.5.19.
-
- Fix warnings/errors resulting from ffetargetOffset becoming
- `long long int' instead of `unsigned long' as of 0.5.19,
- while ffebitCount remains `unsigned long':
- * bld.c (ffebld_constantarray_dump): Avoid warnings by
- using loop var of appropriate type, and using casts.
- * com.c (ffecom_expr_): Use right type for loop var.
- (ffecom_sym_transform_, ffecom_transform_equiv_):
- Cast to right type in assertions.
- * data.c (ffedata_gather_, ffedata_value_): Cast to right
- type in assertions and comparisons.
-
-Wed Dec 18 12:07:11 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- Patch from Alexandre Oliva <oliva@dcc.unicamp.br>:
- * Makefile.in (all.indirect): Don't pass -bbigtoc option
- to GNU ld.
-
- Cope with new versions of gcc:
- * com.h (BUILT_FOR_280): New macro.
- * com.c (ffecom_ptr_to_expr): Conditionalize test of
- OFFSET_REF.
- (ffecom_build_complex_constant_): Conditionalize calling
- sequence for build_complex.
-
-Sat Dec 7 07:15:17 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Version 0.5.19 released.
-
-Fri Dec 6 12:23:55 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * g77.c: Default to assuming "f77" is in $LANGUAGES, since
- the LANGUAGE_F77 macro isn't defined by anyone anymore (but
- might as well leave the no-f77 code in just in case).
- * Make-lang.in (g77, g77-cross): Don't define LANGUAGE_F77
- anymore.
-
-1996-12-06 Dave Love <d.love@dl.ac.uk>
-
- * Make-lang.in (g77, g77-cross): Revert to building `g77' or not
- conditional on `f77' in LANGUAGES.
-
-Wed Dec 4 13:08:44 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in (g77, g77-cross): No libs or lib dependencies
- in case where "f77" is not in $LANGUAGES.
-
- * lex.c (ffelex_image_char_, ffelex_file_fixed,
- ffelex_file_free): Fixes to properly handle lines with
- null character, and too-long lines as well.
-
- * lex.c: Call ffebad_start_msg_lex instead of
- ffebad_start_msg throughout.
-
-Sun Dec 1 21:19:55 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- Fix-up for 1996-11-25 changes:
- * com.c (ffecom_member_phase2_): Subtract out 0 offset for
- elegance and consistency with EQUIVALENCE aggregates.
- (ffecom_sym_transform_): Ditto for LOCAL/COMMON, and
- ensure we get the same parent storage area.
- * data.c (ffedata_gather_, ffedata_value_): Subtract out
- aggregate offset.
+ * news.texi (News): Mention GCC 2.95 in favor of EGCS 1.2.
+ Mention that libg2c is multilibbed.
-Wed Nov 27 13:55:57 1996 Craig Burley <burley@gnu.ai.mit.edu>
+Fri Jun 4 10:09:50 1999 Craig Burley <craig@jcb-sc.com>
- * proj.h: Quote the text of the #error message, to avoid
- strange-looking diagnostics from non-gcc ANSI compilers.
+ * g77.texi (Missing Features): Add `Better Warnings'
+ item.
- * top.c: Make -fno-debug-kludge the default.
+Fri May 28 16:51:41 1999 Craig Burley <craig@jcb-sc.com>
-Mon Nov 25 20:13:45 1996 Craig Burley <burley@gnu.ai.mit.edu>
+ * g77.texi: Fix thinko.
- Provide more info on EQUIVALENCE mismatches:
- * bad.def (FFEBAD_EQUIV_MISMATCH): More detailed message.
- * equiv.c (ffeequiv_layout_local_, ffeequiv_layout_cblock):
- More details for FFEBAD_EQUIV_MISMATCH.
+Wed May 26 14:43:27 1999 Craig Burley <craig@jcb-sc.com>
- Fix problem with EQUIVALENCE handling:
- * equiv.c (ffeequiv_layout_local_): Redesign algorithm --
- old one was broken, resulting in rejection of good code.
- (ffeequiv_offset_): Add argument, change callers.
- Clean up the code, fix up the (probably unused) negative-value
- case for SYMTER.
- * com.c (ffecom_sym_transform_): For local EQUIVALENCE
- member, subtract out aggregate offset (which is <= 0).
+ * news.texi: Document Tue May 18 03:52:04 1999 patch.
+ Fix a grammo.
-Thu Nov 21 12:44:56 1996 Craig Burley <burley@gnu.ai.mit.edu>
+Wed May 26 14:25:07 1999 Craig Burley <craig@jcb-sc.com>
- Change type of ffetargetOffset from `unsigned long' to `long long':
- * bld.c (ffebld_constantarray_dump): Change printf formats.
- * storag.c (ffestorag_dump): Ditto.
- * symbol.c (ffesymbol_report): Ditto.
- * target.h (ffetargetOffset_f): Ditto and change type itself.
+ * g77.texi, news.texi, root.texi, version.c: Start renaming
+ EGCS 1.2 to GCC 2.95, and start using 0.5.25 to designate
+ the version of g77 within GCC 2.95.
- Handle situation where list of languages does not include f77:
- * Make-lang.in: Define LANGUAGE_F77 to 1 only if `f77' is in
- the $LANGUAGES macro for the build.
- * g77.c: Compile to a (nearly) no-op program if LANGUAGE_F77
- is not defined to 1.
-
- Fixes to delay confirmation of READ, WRITE, and GOTO statements
- so the corresponding assignments to same-named CHAR*(*) arrays
- work:
- * stb.c (ffestb_R90915_, ffestb_91014_): New functions.
- (ffestb_goto3_, ffestb_goto5_): Move confirmation from 3 to 5
- for the OPEN_PAREN case.
- (ffestb_R9091_, ffestb_R9094_, ffestb_R90913_, ffestb_R90914_,
- ffestb_R91012_, ffestb_R91013_): Use new functions, and confirm
- except for the OPEN_PAREN case.
+Wed May 26 11:45:21 1999 Craig Burley <craig@jcb-sc.com>
- Fixes to not confirm declarations with an open paren where
- an equal sign or other assignment-like token might be, so the
- corresponding assignments to same-named CHAR*(*) arrays work:
- (ffestb_decl_entsp_5_): Move assertion so we crash on that first,
- if it turns out to be wrong, before the less-debuggable crash
- on mistaken confirmation.
- (ffestb_decl_entsp_6_, ffestb_decl_entsp_7_, ffestb_decl_entsp_8_):
- Include OPEN_PAREN in list of assignment-only tokens.
+ Rename -fsubscript-check to -fbounds-check and
+ -ff2c-subscript-check to -ffortran-bounds-check:
+ * g77.texi: Rename options in docs, clarify usage.
+ * lang-options.h: Rename options, clarify doclets.
+ * news.texi: Rename options, don't bother with fortran-specific
+ option.
+ * top.c (ffe_decode_option): Rename recognized strings.
- Fix more diagnosed-crash bugs:
- * stu.c (ffestu_sym_end_transition): ANY-ize an adjustable array
- with bad dimension expressions even if still stateUNCERTAIN.
- (ffestu_symter_end_transition_, ffestu_symter_exec_transition_):
- Return TRUE for opANY as well.
- For code elegance, move opSYMTER case into first switch.
+Tue May 25 18:21:09 1999 Craig Burley <craig@jcb-sc.com>
-1996-11-17 Dave Love <d.love@dl.ac.uk>
+ * com.c (FFECOM_FASTER_ARRAY_REFS): Delete this vestige,
+ now that -fflatten-arrays exists.
- * lex.c: Fix last change.
+Tue May 25 17:48:34 1999 Craig Burley <craig@jcb-sc.com>
-1996-11-14 Dave Love <d.love@dl.ac.uk>
+ Fix 19990525-0.f:
+ * com.c (ffecom_arg_ptr_to_expr): Strip off parens around
+ CHARACTER expression.
+ (ffecom_prepare_expr_): Ditto.
- * Make-lang.in, config-lang.in: Remove the (broken) libU77 stuff,
- pending 0.5.20.
+Tue May 18 03:52:04 1999 Craig Burley <craig@jcb-sc.com>
-Thu Nov 14 15:40:59 1996 Craig Burley <burley@gnu.ai.mit.edu>
+ Support use of back end's improved open-coding of complex divide:
+ * com.c (ffecom_tree_divide_): Use RDIV_EXPR for complex divide,
+ instead of run-time call to [cz]_div, if `-Os' option specified.
+ (lang_init_options): Tell back end we want support for wide range
+ of inputs to complex divide.
- * bad.def (FFEBAD_UNIMPL_STMT): Explain that invalid
- intrinsic references can trigger this message, too.
+ * Bump version.
-1996-11-12 Dave Love <d.love@dl.ac.uk>
+Tue May 18 00:21:34 1999 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * lex.c: Declare dwarfout routines.
+ * lang-specs.h: Define __GNUC__ and __GNUC_MINOR__ only if -no-gcc
+ was not given.
- * config-lang.in: Sink grep o/p.
+Thu May 13 12:23:20 1999 Craig Burley <craig@jcb-sc.com>
-Mon Nov 11 14:21:13 1996 Craig Burley <burley@gnu.ai.mit.edu>
+ Fix INTEGER*8 subscripts in array references:
+ * com.c (ffecom_subscript_check_): Convert low, high, and
+ element as necessary to make comparison work.
+ (ffecom_arrayref_): Do more of the work.
+ Properly handle subscript expr that's wider than int,
+ if pointers are wider than int.
+ (ffecom_expr_): Leave more work to ffecom_arrayref_.
+ (ffecom_init_0): Record sizes of pointers and ints for
+ convenience.
+ Use set_sizetype etc. as done by gcc front end.
+ (ffecom_ptr_to_expr): Leave more work to ffecom_arrayref_.
+ * expr.c (ffeexpr_finished_): Don't convert INTEGER subscript
+ expressions in run-time contexts.
+ (ffeexpr_token_elements_, ffeexpr_token_substring_1_): Cope with
+ non-default INTEGER subscript expressions.
+ * news.texi: Announce.
- * g77.c (main): Might as well print version number
- for --verbose as well.
+ Finish accepting -fflatten-arrays option:
+ * com.c (ffecom_arrayref_): Flatten references if requested.
+ * g77.texi: Describe.
+ * lang-options.h: Allow.
+ * news.texi: Announce.
+ * top.c, top.h: Recognize.
-Thu Nov 7 18:41:41 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c, lang-options.h, target.h, top.c, top.h: Split out
- remaining -fugly stuff into -fugly-logint and -fugly-comma,
- leaving -fugly as simply a `macro' that expands into other
- options, and eliminate defaults for some of the ugly stuff
- in target.h.
-
- * Make-lang.in (gcc-cross): Compile zzz.c, not version.o (!),
- in to get version info for this target.
-
- * config-lang.in: Test for GBE patch application based
- on whether 2.6.x or 2.7.x GBE is detected.
-
-Wed Nov 6 14:19:45 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in (g77): Compile zzz.c in to get version info.
- * g77.c: Add support for --help and --version.
-
- * g77.c (lookup_option): Short-circuit long-winded tests
- when second char is not hyphen, just to save a spot of time.
-
-Sat Nov 2 13:50:31 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * intrin.def: Add FTELL and FSEEK intrinsics, plus new
- `g' codes for alternate-return (GOTO) arguments.
- * intrin.c (ffeintrin_check_): Support `g' codes.
- * com-rt.def: Add ftell_() and fseek_() to database.
- * com.c (ffecom_expr_intrinsic_): Ditto. Also, let each
- subroutine intrinsic decide for itself what to do with
- tree_type, the default being NULL_TREE once again (so
- ffecom_call_ doesn't think it's supposed to cast the
- function call to the type in the fall-through case).
-
- * ste.c (ffeste_R909_finish): Don't special-case list-directed
- I/O, now that libf2c can return non-zero status codes.
- (ffeste_R910_finish): Ditto.
- (ffeste_io_call_): Simplify logic.
- (ffeste_io_impdo_):
- (ffeste_subr_beru_):
- (ffeste_R904):
- (ffeste_R907):
- (ffeste_R909_start):
- (ffeste_R909_item):
- (ffeste_R909_finish):
- (ffeste_R910_start):
- (ffeste_R910_item):
- (ffeste_R910_finish):
- (ffeste_R911_start):
- (ffeste_R923A): Ditto all the above.
-
-Thu Oct 31 20:56:28 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * config-lang.in, Make-lang.in: Rename flag file
- build-u77 to build-libu77, for consistency with
- install-libf2c and such.
-
- * config-lang.in: Don't complain about failure to patch
- if pre-2.7.0 gcc is involved (since our patch for that
- doesn't add support for tooning).
-
-Sat Oct 26 05:56:51 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * bad.def (FFEBAD_TYPELESS_TOO_LARGE): Remove this
- unused and redundant diagnostic.
-
-Sat Oct 26 00:45:42 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * target.c (ffetarget_integerhex): Fix dumb bug.
-
-1996-10-20 Dave Love <d.love@dl.ac.uk>
-
- * gbe/2.7.2.1.diff: New file.
-
- * Makefile.in (F771_LDFLAGS): Add -bbigtoc for AIX4.1 up, suggested by
- endo@material.tohoku.ac.jp [among others!].
-
-Sat Oct 19 03:11:14 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * bad.def, bld.c, bld.h, expr.c, lang-options.h, target.c,
- target.h, top.c, top.h (ffebld_constant_new_integerbinary,
- ffebld_constant_new_integerhex, ffebld_constant_new_integeroctal,
- ffeexpr_token_name_apos_name_, ffetarget_integerbinary,
- ffetarget_integerhex, ffetarget_integeroctal): Support
- new -fno-typeless-boz option with new functions, mods to
- existing octal-handling functions, new macros, new error
- messages, and so on.
-
- * com.c, lang-options.h, top.c, top.h (ffecom_notify_primary_entry):
- Print program unit name on stderr if -fno-silent (new option).
-
- * lang-options.h, top.c, top.h, stt.c (ffestt_dimlist_as_expr):
- Treat ([...,]1) in dimlist as ([...,]*) if -fugly-assumed
- (new option).
-
- * lang-options.h: Comment out options duplicated in gcc/toplev.c,
- because, somehow, having them commented in and building on my
- DEC Alpha results in a cc1 that always segfaults, and gdb that
- also segfaults whenever it debugs it up to init_lex() calling
- xmalloc() or so.
-
-Thu Oct 17 00:39:27 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * stb.c (ffestb_R10013_): Don't change meaning of .sign until
- after previous meaning/value used to set sign of value
- (960507-1.f).
-
-Sun Oct 13 22:15:23 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * top.c (ffe_decode_option): Don't set back-end flags
- that are nonexistent prior to gcc 2.7.0.
-
-Sun Oct 13 12:48:45 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (convert): Don't convert emulated complex expr to
- real (via REALPART_EXPR) if the target type is (emulated)
- complex.
-
-Wed Oct 2 21:57:12 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_debug_kludge_): Set DECL_IN_SYSTEM_HEADER so
- -Wunused doesn't complain about these manufactured decls.
- (ffecom_expr_): Ditto, for original (non-ASSIGN'ed) variable.
- (ffecom_transform_equiv_): Clear DECL_IGNORED_P for aggregate
- area so it shows up as a debug-accessible symbol.
- (pushdecl): Default for "invented" identifiers (a g77-specific
- concept for now) is that they are artificial, in system header,
- ignored for debugging purposes, used, and (for types) suppressed.
- This ought to be overkill.
-
-Fri Sep 27 23:13:07 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * ste.c (ffeste_begin_iterdo_, ffeste_end_iterdo_): Support
- one-trip DO loops (F66-style).
- * lang-options.h, top.c, top.h (-fonetrip): New option.
-
-Thu Sep 26 00:18:40 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_debug_kludge_): New function.
- (ffecom_sym_transform_): Use new function for COMMON and EQUIVALENCE
- members.
-
- * lang-options.h, top.c, top.h (-fno-debug-kludge):
- New option.
-
-1996-09-24 Dave Love <d.love@dl.ac.uk>
-
- * Make-lang.in (include/f2c.h):
- Remove dependencies on xmake_file and tmake_file.
- They expand inconsistently in 2.8 c.f. 2.7; $(GCC_PARTS) depends on
- them anyhow.
-
-1996-09-22 Dave Love <d.love@dl.ac.uk>
-
- * config-lang.in: Add --enable-libu77 option handling.
-
- * Make-lang.in:
- Conditionally add --enable-libu77 when running runtime configure.
- Define LIBU77STAGESTUFF and use it in relevant rules.
-
-1996-08-21 Dave Love <d.love@dl.ac.uk>
-
- * Make-lang.in (f77-runtime):
- `stmp-hdrs' should have been `stmp-headers'.
-
-1996-08-20 Dave Love <d.love@dl.ac.uk>
-
- * Make-lang.in (f77-runtime):
- Depend on stmp-hdrs, not stmp-int-hdrs, since libF77
- needs float.h.
-
-Sat Jun 22 18:17:11 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_tree_divide_): Fix RECORD_TYPE case to
- look at type of first field, properly, to determine
- whether to call c_div or z_div.
-
-Tue Jun 4 04:27:18 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_build_complex_constant_): Explicitly specify
- TREE_PURPOSE.
- (ffecom_expr_): Fix thinko.
- (ffecom_2): For COMPLEX_EXPR, explicitly specify TREE_PURPOSE.
-
-Mon May 27 16:23:43 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- Changes to optionally avoid gcc's back-end complex support:
- * com.c (ffecom_stabilize_aggregate_): New function.
- (ffecom_convert_to_complex_): New function.
- (ffecom_make_complex_type_): New function.
- (ffecom_build_complex_constant_): New function.
- (ffecom_expr_): For opCONVERT of non-COMPLEX to COMPLEX,
- don't bother explicitly converting to the subtype first,
- because gcc does that anyway, and more code would have
- to be added to find the subtype for the emulated-complex
- case.
- (ffecom_f2c_make_type_): Use ffecom_make_complex_type_
- instead of make_node etc. to make a complex type.
- (ffecom_1, ffecom_2): Translate operations on COMPLEX operands
- to appropriate operations when emulating complex.
- (ffecom_constantunion): Use ffecom_build_complex_constant_
- instead of build_complex to build a complex constant.
- (ffecom_init_0): Change point at which types are laid out
- for improved consistency.
- Use ffecom_make_complex_type_ instead of make_node etc.
- to make a complex type.
- Always calculate storage sizes from TYPE_SIZE, never TYPE_PRECISION.
- (convert): Use e, not expr, since we've copied into that anyway.
- For RECORD_TYPE cases, do emulated-complex conversions.
- (ffecom_f2c_set_lio_code_): Always calculate storage sizes
- from TYPE_SIZE, never TYPE_PRECISION.
- (ffecom_tree_divide_): Allow RECORD_TYPE to also be handled
- by run-time library.
- (ffecom_expr_intrinsic_): Handle possible RECORD_TYPE as argument
- to AIMAG intrinsic.
-
- * top.h, top.c, lang-options.h: Support new -f(no-)emulate-complex option.
-
- * com.c (ffecom_sym_transform_): Clarify and fix typos in comments.
-
-Mon May 20 02:06:27 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * target.h: Use new REAL_VALUE_UNTO_TARGET_* macros instead
- of REAL_VALUE_FROM_TARGET_DOUBLE and _SINGLE.
- Explicitly use long instead of HOST_WIDE_INT for emulation
- of ffetargetReal1 and ffetargetReal2.
-
-1996-05-20 Dave Love <d.love@dl.ac.uk>
-
- * config-lang.in:
- Test for patch being applied with flag_move_all_movables in toplev.c.
-
- * install.texi (Patching GNU Fortran):
- Mention overriding X_CFLAGS rather than
- editing proj.h on SunOS4.
-
- * Make-lang.in (F77_FLAGS_TO_PASS):
- Add X_CFLAGS (convenient for SunOS4 kluge, in
- particular).
- (f77.{,mostly,dist}clean): Reorder things, in particular not to delete
- Makefiles too early.
-
- * g77.c (DEFAULT_SWITCH_TAKES_ARG): Define a la gcc.c in the
- current GCC snapshot.
-
-Tue May 14 00:24:07 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- Changes for DEC Alpha AXP support:
- * com.c (ffecom_init_0): REAL_ARITHMETIC means internal
- REAL/DOUBLE PRECISION might well have a different size
- than the compiled type, so don't crash if this is the
- case.
- * target.h: Use `int' for ffetargetInteger1,
- ffetargetLogical1, and magical tests. Set _f format
- strings accordingly.
-
-Tue Apr 16 14:08:28 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * top.c (ffe_decode_option): -Wall no longer implies
- -Wsurprising.
-
-Sat Apr 13 14:50:06 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_char_args_): If item is error_mark_node,
- set *length that way, too.
-
- * com.c (ffecom_expr_power_integer_): If either operand
- is error_mark_node, return that.
-
- * com.c (ffecom_intrinsic_len_): If item is error_mark_node,
- return that for length.
-
- * expr.c (ffeexpr_declare_unadorned_,
- ffeexpr_declare_parenthesized_): Instead of crashing
- on unexpected contexts, produce a diagnostic.
-
- * intrin.c (ffeintrin_check_), intrin.def (impSIGNAL):
- Allow procedure as second arg to SIGNAL intrinsic.
-
- * stu.c (ffestu_symter_end_transition_): New function.
- (ffestu_symter_exec_transition_): Return bool arg.
- Always transition symbol (don't inhibit when !whereNONE).
- (ffestu_sym_end_transition): If DUMMY/LOCAL arg has any
- opANY exprs in its dimlist, diagnose it so it doesn't
- make it through to later stages that try to deal with
- dimlist stuff.
- (ffestu_sym_exec_transition): If sym has any opANY exprs
- in its dimlist, diagnose it so it becomes opANY itself.
-
- * symbol.c (ffesymbol_error): If token arg is NULL,
- just ANY-ize the symbol -- don't produce diagnostic.
-
-Mon Apr 1 10:14:02 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Version 0.5.18 released.
-
-Mon Mar 25 20:52:24 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_expr_power_integer_): Don't generate code
- that compares COMPLEX (or, as it happens, REAL) via "LT_EXPR",
- since the back end crashes on that. (This code would never
- be executed anyway, but the test that avoids it has now been
- translated to control whether the code gets generated at all.)
- Fixes 960323-3.f.
-
- * com.c (ffecom_type_localvar_): Handle variable-sized
- dimension bounds expressions here, so they get calculated
- and saved on procedure entry. Fixes 960323-4.f.
-
- * com.c (ffecom_notify_init_symbol): Symbol has no init
- info at all if only zeros have been used to initialize it.
- Fixes 960324-0.f.
-
- * expr.c, expr.h (ffeexpr_type_combine): Renamed from
- ffeexpr_type_combine_ and now a public procedure; last arg now
- a token, instead of an internal structure used to extract a token.
- Now allows the outputs to be aliased with the inputs.
- Now allows a NULL token to mean "don't report error".
- (ffeexpr_reduced_bool2_, ffeexpr_reduced_eqop2_,
- ffeexpr_reduced_math2_, ffeexpr_reduced_power_,
- ffeexpr_reduced_relop2_): Handle new calling sequence for
- ffeexpr_type_combine.
- * (ffeexpr_convert): Don't put an opCONVERT node
- in just because the size is unknown; all downstream code
- should be able to deal without it being there anyway, and
- getting rid of it allows new intrinsic code to more easily
- combine types and such without generating bad code.
- * info.c, info.h (ffeinfo_kindtype_max): Rewrite to do
- proper comparison of size of types, not just comparison
- of their internal kind numbers (so I2.eq.I1 doesn't promote
- I1 to I2, rather the other way around).
- * intrin.c (ffeintrin_check_): Combine types of arguments
- in COL a la expression handling, for greater flexibility
- and permissiveness (though, someday, -fpedantic should
- report use of this kind of thing).
- Make sure Hollerith/typeless where CHARACTER expected is
- rejected. This all fixes 960323-2.f.
-
- * ste.c (ffeste_begin_iterdo_): Fix some more type conversions
- so INTEGER*2-laden DO loops don't crash at compile time on
- certain machines. Believed to fix 960323-1.f.
-
- * stu.c (ffestu_sym_end_transition): Certainly reject
- whereDUMMY not in any dummy list, whether stateUNCERTAIN
- or stateUNDERSTOOD. Fixes 960323-0.f.
-
-Tue Mar 19 13:12:40 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * data.c (ffedata_value): Fix crash on opANY, and simplify
- the code at the same time.
-
- * Make-lang.in (f77-runtime): Also depends on lib[FI]77/Makefile...
- (include/f2c.h...): ...which in turn depend on */Makefile.in.
- (f77.rebuilt): Rebuild runtime stuff too.
-
- * intrin.c (ffeintrin_check_): Accommodate TYPELESS/HOLLERITH
- types, convert args as necessary, etc.
-
- * expr.c (ffeexpr_convert): Fix test for TYPELESS/HOLLERITH
- to obey the docs; crash if no source token when error.
- (ffeexpr_collapse_convert): Crash if no token when error.
-
-Mon Mar 18 15:51:30 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_init_zero_): Renamed from
- ffecom_init_local_zero_; now handles top-level
- (COMMON) initializations too.
-
- * bld.c (ffebld_constant_is_zero):
- * com.c (ffecom_symbol_transform_, ffecom_sym_transform_assign_,
- ffecom_transform_common_, ffecom_transform_equiv_):
- * data.c:
- * equiv.c:
- * equiv.h:
- * lang-options.h:
- * stc.c:
- * storag.c:
- * storag.h:
- * symbol.c:
- * symbol.h:
- * target.c:
- * target.h:
- * top.c:
- * top.h: All of this is mostly housekeeping-type changes
- to support -f(no-)zeros, i.e. not always stuff zero
- values into the initializer fields of symbol/storage objects,
- but still track that they have been given initial values.
-
- * bad.def: Fix wording for DATA-related diagnostics.
-
- * com.c (ffecom_sym_transform_assign_): Don't check
- any EQUIVALENCE stuff for local ASSIGN, the check was
- bad (crashing), and it's not necessary, anyway.
-
- * com.c (ffecom_expr_intrinsic_): For MAX and MIN,
- ignore null arguments as far arg[123], and fix handling
- of ANY arguments. (New intrinsic support now allows
- spurious trailing null arguments.)
-
- * com.c (ffecom_init_0): Add HOLLERITH (unsigned)
- equivalents for INTEGER*2, *4, and *8, so shift intrinsics
- and other things that need unsigned versions of signed
- types work.
-
-Sat Mar 16 12:11:40 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * storag.c (ffestorag_exec_layout): Treat adjustable
- local array like dummy -- don't create storage object.
- * com.c (ffecom_sym_transform_): Allow for NULL storage
- object in LOCAL case (adjustable array).
-
-Fri Mar 15 13:09:41 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_sym_transform_): Allow local symbols
- with nonconstant sizes (adjustable local arrays).
- (ffecom_type_localvar_): Allow dimensions with nonconstant
- component (adjustable local arrays).
- * expr.c: Various minor changes to handle adjustable
- local arrays (a new case of stateUNCERTAIN).
- * stu.c (ffestu_sym_end_transition,
- ffestu_sym_exec_transition): Ditto.
- * symbol.def: Update docs to reflect these changes.
-
- * com.c (ffecom_expr_): Reduce space/time needed for
- opACCTER case by handling it here instead of converting
- it to opARRTER earlier on.
- (ffecom_notify_init_storage): Don't convert ACCTER to ARRTER.
- (ffecom_notify_init_symbol): Ditto.
-
- * com.c (ffecom_init_0): Crash and burn if any of the types'
- sizes, according to the GBE, disagrees with the sizes of
- the FFE's internal implementation. This might catch
- Alpha/SGI bugs earlier.
-
-Fri Mar 15 01:09:41 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com-rt.def, com.c, com.h: Changes for rewrite of intrinsic
- handling.
- * com.c (ffecom_arglist_expr_): New function.
- (ffecom_widest_expr_type_): New function.
- (ffecom_expr_intrinsic_): Reorganize, some rewriting.
- (ffecom_f2c_make_type_): Layout complex types.
- (ffecom_gfrt_args_): New function.
- (ffecom_list_expr): Trivial change for consistency.
-
- * expr.c (ffeexpr_token_name_rhs_): Go back to getting
- type from specific, not implementation, info.
- (ffeexpr_token_funsubstr_): Set intrinsic implementation too!
- * intrin.c: Major rewrite of most portions.
- * intrin.def: Major rearchitecting of tables.
- * intrin.h (ffeintrin_basictype, ffeintrin_kindtype):
- Now (once again) take ffeintrinSpec as arg, not ffeintrinImp;
- for now, these return NONE, since they're not really needed
- and adding the necessary info to the tables is not trivial.
- (ffeintrin_codegen_imp): New function.
- * stc.c (ffestc_R1208_item): Change way ffeintrin funcs called,
- back to original per above; but comment out the code anyway.
-
- * intrin.c (ffe_init_0): Do internal checks only if
- -fset-g77-defaults not specified.
-
- * lang-options.h: Add -fset-g77-defaults option.
- * lang-specs.h: Always pass -fset-g77-defaults.
- * top.c, top.h: New option.
-
-Sat Mar 9 17:49:50 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in (stmp-int-hdrs): Use --no-validate when
- generating the f77.rebuilt files (BUGS, INSTALL, NEWS)
- so cross-references can work properly in g77.info
- without a lot of hassle. Users can probably deal with
- the way they end up looking in the f77.rebuilt files.
-
- * bld.c (ffebld_constant_new_integer4_val): INTEGER*8
- support -- new function.
- (ffebld_constant_new_logical4_val): New function.
- * com.c (ffecom_f2c_longint_type_node): New type.
- (FFECOM_rttypeLONGINT_): New return type code.
- (ffecom_expr_): Add code to invoke pow_qq instead
- of pow_ii for INTEGER4 (INTEGER*8) case.
- If ffecom_expr_power_integer_ returns NULL_TREE, just do
- the usual work.
- (ffecom_make_gfrt_): Handle new type.
- (ffecom_expr_power_integer_): Let caller do the work if in
- dummy-transforming case, since
- caller now knows about INTEGER*8 and such, by returning
- NULL_TREE.
- * expr.c (ffeexpr_reduced_power_): Complain about non-INTEGER
- raised to INTEGER4 (INTEGER*8) power.
-
- * target.c (ffetarget_power_integerdefault_integerdefault):
- Fix any**negative.
- * com.c (ffecom_expr_power_integer_): Fix (-1)**(-8) and similar
- to ABS() the integral result if the exponent is negative
- and even.
-
- * ste.c (ffeste_begin_iterdo_): Clean up a type ref.
- Always convert iteration count to _default_ INTEGER.
-
- * sta.c (ffesta_second_): Add BYTE and WORD type/stmts;
- changes by Scott Snyder <snyder@d0sgif.fnal.gov>.
- * stb.c (ffestb_decl_recursive): Ditto.
- (ffestb_decl_recursive): Ditto.
- (ffestb_decl_entsp_2_): Ditto.
- (ffestb_decl_entsp_3_): Ditto.
- (ffestb_decl_funcname_2_): Ditto.
- (ffestb_decl_R539): Ditto.
- (ffestb_decl_R5395_): Ditto.
- * stc.c (ffestc_establish_declstmt_): Ditto.
- * std.c (ffestd_R539item): Ditto.
- (ffestd_R1219): Ditto.
- * stp.h: Ditto.
- * str-1t.fin: Ditto.
- * str-2t.fin: Ditto.
-
- * expr.c (ffeexpr_finished_): For DO loops, allow
- any INTEGER type; convert LOGICAL (assuming -fugly)
- to corresponding INTEGER type instead of always default
- INTEGER; let later phases do conversion of DO start,
- end, incr vars for implied-DO; change checks for non-integral
- DO vars to be -Wsurprising warnings.
- * ste.c (ffeste_io_impdo_): Convert start, end, and incr
- to type of DO variable.
-
- * com.c (ffecom_init_0): Add new types for [IL][234],
- much of which was done by Scott Snyder <snyder@d0sgif.fnal.gov>.
- * target.c: Ditto.
- * target.h: Ditto.
-
-Wed Mar 6 14:08:45 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * top.c (ffe_init_gbe_): Make -frerun-loop-opt the default.
-
-Mon Mar 4 12:27:00 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c (ffeexpr_exprstack_push_unary_): Really warn only
- about two successive _arithmetic_ operators.
-
- * stc.c (ffestc_R522item_object): Allow SAVE of (understood)
- local entity.
-
- * top.c (ffe_decode_option): New -f(no-)second-underscore options.
- * top.h: New options.
- * com.c (ffecom_get_external_identifier_, ffecom_get_identifier_):
- New options.
-
- * Make-lang.in (f77.maintainer-clean): Clean f/BUGS, f/INSTALL,
- f/NEWS.
- ($(srcdir)/f/BUGS, $(srcdir)/f/INSTALL, $(srcdir)/f/NEWS):
- New rules.
- ($(srcdir)/f/g77.info, $(srcdir)/f/g77.dvi): Depend on
- f/bugs.texi and f/news.texi.
- (f77.install-man): Install f77 man pages (if enabled).
- (f77.uninstall): Uninstall info docs, f77 man pages (if enabled).
-
- * top.c (ffe_init_gbe_): New function.
- (ffe_decode_option, ffe_file): Call ffe_init_gbe_ to
- set defaults for gcc options.
-
-Sat Jan 20 13:57:19 1996 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_get_identifier_): Eliminate needless
- comparison of results of strchr.
-
-Tue Dec 26 11:41:56 1995 Craig Burley <burley@gnu.ai.mit.edu>
-
- * Make-lang.in: Add rules for new files g77.texi, g77.info,
- and g77.dvi.
- Reorganize the *clean rules to more closely parallel gcc's.
-
- * config-lang.in: Exclude g77.info from diffs.
-
-Sun Dec 10 02:29:13 1995 Craig Burley <burley@gnu.ai.mit.edu>
-
- * expr.c (ffeexpr_declare_unadorned_,
- ffeexpr_declare_parenthesized_): Break out handling of
- contextDATAIMPDO[INDEX,CTRL] so it's independent of symbol state.
- Don't exec-transition these here (let ffeexpr_sym_impdoitem_
- handle that when appropriate). Don't "declare" them twice.
-
-Tue Dec 5 06:48:26 1995 Craig Burley <burley@gnu.ai.mit.edu>
-
- * stc.c (ffestc_promote_sfdummy_): Allow whereNONE parent
- symbol, since it is not necessarily known whether it will
- become LOCAL or DUMMY.
-
-Mon Dec 4 03:46:55 1995 Craig Burley <burley@gnu.ai.mit.edu>
-
- * lex.c (ffelex_display_token, ffelex_type_string_): Resurrect
- these from their old versions and update them for possible invocation
- from debugger.
- * lex.h (ffelex_display_token): Declare this in case anyone
- else wants to call it.
-
- * lex.c (ffelex_total_tokens_): Have this reflect actual allocated
- tokens, no longer include outstanding "uses" of tokens.
-
- * malloc.c, malloc.h (MALLOC_DEBUG): New macro to control
- checking of whether callers follow rules, now defaults to 0
- for "no checking" to improve compile times.
-
- * malloc.c (malloc_pool_kill): Fix bug that could prevent
- subpool from actually being killed (wasn't setting its use
- count to 1).
-
- * proj.h, *.c (dmpout): Replace all occurrences of `stdout'
- and some of `stderr' with `dmpout', so where to dump debugging
- output can be easily controlled during build; add default
- for `dmpout' of `stderr' to proj.h.
-
-Sun Dec 3 00:56:29 1995 Craig Burley <burley@gnu.ai.mit.edu>
-
- * com.c (ffecom_return_expr): Eliminate attempt at warning
- about unset return values, since the back end does this better,
- with better wording, and is not triggered by clearly working
- (but spaghetti) code as easily as this test.
-
-Sat Dec 2 08:28:56 1995 Craig Burley <burley@gnu.ai.mit.edu>
-
- * target.c (ffetarget_power_*_integerdefault): Raising 0 to
- integer constant power should not be an error condition;
- if so, other code should catch 0 to any power, etc.
-
- * bad.def (FFEBAD_BAD_POWER): 0**integer now a warning instead
- of an error.
-
-Fri Dec 1 00:12:03 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * bad.def: Clarify diagnostic regarding complex constant elements.
- * expr.c (ffeexpr_cb_comma_c_): Capitalize real/imaginary
- for clarified diagnostic.
-
- * com.c (ffecom_close_include_): Close the file!
-
- * lex.c (ffelex_file_fixed): Update line info if the line
- has any content, not just if it finishes a previous line
- or has a label.
- (ffelex_file_free): Clarify switch statement code.
-
-Sat Nov 18 19:37:22 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Version 0.5.17 released.
-
-Fri Nov 17 14:27:24 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Make-lang.in: Fix typo in comment.
-
- * Makefile.in (f/fini.o, f/proj-h.o): Don't use `$<' since
- not all makes support it (e.g. NeXT make), use explicit
- source name instead (with $(srcdir) and munging).
- (ASSERT_H): assert.h lives in source dir, not build dir.
-
-Thu Nov 16 12:47:50 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (ffecom_init_0): Fix dumb bug in code to produce
- warning message about non-32-bit-systems.
-
- * stc.c (ffestc_R501_item): Parenthesize test to make
- warning go away (and perhaps fix bug).
-
-Thu Nov 16 03:43:33 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * g77.c: Upgrade to 2.7.0's gcc.c.
- Fix -v to pass a temp name instead of "/dev/null" for "-o".
-
-Fri Nov 10 19:16:05 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * ste.c (ffeste_begin_iterdo_): Add Toon's change to
- make loops faster on some machines (implement termination
- condition as "--i >= 0" instead of "i-- > 0").
-
-Thu Nov 2 03:58:17 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Make-lang.in: Remove unnecessary $(exeext) a la cp/Make-lang.in.
-
- * com.c (ffecom_expr_): Restore old strategy for assignp variant
- of opSYMTER case...always return the ASSIGN version of var.
- That way, `-O -Wuninitialized' will catch "I=3;GOTO I;END"
- (though the diagnostic will refer to `__g77_ASSIGN_i').
-
- * com.c (ffecom_expr_power_integer_): For constant rhs case,
- wrap every new eval of lhs in save_expr() so it is clear to
- back end that MULT_EXPR(lhs,lhs) has identical operands,
- otherwise for an rhs like 32767 it generates around 65K pseudo
- registers, with which stupid_life_analysis cannot cope
- (due to reg_renumber in regs.h being `short *' instead of
- `int *').
-
- * com.c (ffecom_expr_): Speed up implementation of LOGICAL
- versions of opNOT, opAND, opOR, opXOR/opNEQV, and opEQV by
- assuming the values actually are kosher LOGICAL bit patterns.
- Also simplify code that implements some of the INTEGER versions
- of these.
-
- * com.c (skip_redundant_dir_prefix, read_name_map,
- ffecom_open_include_, signed_type, unsigned_type): Fold in
- changes to cccp.c made from 2.7.0 through ss-950826.
-
- * equiv.c (ffeequiv_layout_local_): Kill the equiv list
- if no syms in list.
-
- * expr.c (ffeexpr_reduced_eqop2_): Issue specific diagnostic
- regarding usage of .EQV./.NEQV. in preference to .EQ./.NE..
-
- * intrin.c: Add ERF and ERFC as generic intrinsics.
- intrin.def: Same.
-
- * sta.c (ffesta_save_, ffesta_second_): Whoever calls
- ffestd_exec_begin must also set ffesta_seen_first_exec = TRUE,
- and anytime stc sees an exec transition, it must do both.
- stc.c (ffestc_eof): Same.
-
- * stc.c (ffestc_promote_sfdummy_): If failed implicit typing
- or CHARACTER*(*) arg, after calling ffesymbol_error, don't
- reset info to ENTITY/DUMMY, because ffecom_sym_transform_
- doesn't expect such a thing with ANY/ANY type.
-
- * target.h (*logical*): Change some of these so they parallel
- changes in com.c, e.g. for _eqv_, use (l)==(r) instead of
- !!(l)==!!(r), to get a more faithful result.
-
-Fri Oct 27 07:06:59 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (ffecom_sym_transform_): Simplify code for local
- EQUIVALENCE case.
-
- * expr.c (ffeexpr_exprstack_push_unary_): Warn about two
- successive operators.
- (ffeexpr_exprstack_push_binary_): Warn about "surprising"
- operator precedence, as in "-2**2".
-
- * lang-options.h: Add -W(no-)surprising options.
-
- * parse.c (yyparse): Don't reset -fpedantic if not -pedantic.
-
- * top.c (ffe_decode_option): Support new -Wsurprising option.
- * top.h: Ditto.
-
-Mon Oct 23 09:14:15 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (ffecom_finish_symbol_transform_): Don't transform
- NONE/NONE (CHARACTER*(*)) vars, as these don't mean anything
- in debugging terms, and can't be turned into anything
- in the back end (so ffecom_sym_transform_ crashes on them).
-
- * com.c (ffecom_expr_): Change strategy for assignp variant
- of opSYMTER case...always return the original var unless
- it is not wide enough.
-
- * ste.c (ffeste_io_cilist_): Clarify diagnostic for ASSIGN
- involving too-narrow variable. This shouldn't happen, though.
- (ffeste_io_icilist_): Ditto.
- (ffeste_R838): Ditto.
- (ffeste_R839): Ditto.
-
-Thu Oct 19 03:21:20 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (ffecom_sym_transform_assign_): Set TREE_STATIC
- using the same decision-making process as used for their twin
- variables, so ASSIGN can last across RETURN/CALL as appropriate.
-
-Fri Sep 22 20:21:18 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Makefile.in: fini is a host program, so it needs a host-compiled
- version of proj.o, named proj-h.o. f/fini, f/fini.o, and
- f/proj-h.o targets updated accordingly.
-
- * com.c (__eprintf): New function.
-
-Wed Sep 20 02:26:36 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * lang-options.h: Add omitted -funix-intrinsics-* options.
-
- * malloc.c (malloc_find_inpool_): Check for infinite
- loop, crash if detected (user reports encountering
- them in some large programs, this might help track
- down the bugs).
-
-Thu Sep 7 13:00:32 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (lang_print_error_function): Don't dereference null
- pointer when outside any program unit.
- (ffecom_let_char_, ffecom_arg_ptr_to_expr): If catlist
- item or length ever error_mark_node, don't continue processing,
- since back-end functions like build_pointer_type crash on
- error_mark_node's (due to pushing bad obstacks, etc.).
-
-Wed Aug 30 15:58:35 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Version 0.5.16 released.
-
-Mon Aug 28 12:24:20 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * bad.c (ffebad_finish): Fix botched message when no places
- are printed (due to unknown line info, etc.).
-
- * std.c (ffestd_subr_labels_): Do a better job finding
- line info in the case of typeANY and diagnostics.
-
-Fri Aug 25 15:19:29 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (DECL_ARTIFICIAL): Surround all references to this
- macro with #if !BUILT_FOR_270 and #endif.
- (init_lex): Surround print_error_function decl with
- #if !BUILT_FOR_270 and #endif.
- (lang_init): Call new ffelex_hash_kludge function to solve
- problem with preprocessed files that have INCLUDE statements.
-
- * lex.c (ffelex_getc_): New function.
- (ffelex_cfelex_): Use ffelex_getc_ instead of getc in any
- paths of code that can be affected by ffelex_hash_kludge.
- Don't make an EOF token for unrecognized token; set token
- to NULL instead, to avoid problems when not initialized.
- (ffelex_hash_): Use ffelex_getc_ instead of getc in any
- paths of code that can be affected by ffelex_hash_kludge.
- Test token returned by ffelex_cfelex_ for NULL, meaning
- unrecognized token.
- Get rid of useless used_up variable.
- Don't do ffewhere stuff or kill any tokens if in
- ffelex_hash_kludge.
- (ffelex_file_fixed, ffelex_file_free): Use ffelex_getc_
- instead of getc in any paths of code that can be affected
- by ffelex_hash_kludge.
- (ffelex_hash_kludge): New function.
-
- * lex.h (ffelex_hash_kludge): New function.
-
-Wed Aug 23 15:17:40 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c: Implement -f(no-)underscoring options by always
- compiling in code to do it, and having that code inhibit
- itself when -fno-underscoring is in effect. This option
- overrides -f(no-)f2c for this purpose; -f(no-)f2c returns
- to it's <=0.5.15 behavior of affecting only how code
- is generated, not how/whether names are mangled.
-
- * target.h: Redo specification of appending underscores so
- the macros are named "_default" instead of "_is" and the
- two-underscore macro defaults to 1.
-
- * top.c, top.h (underscoring): Add appropriate stuff
- for the -f(no-)underscoring options.
-
-Tue Aug 22 10:25:01 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * bad.c (ffebad_finish): Call report_error_function (in toplev.c)
- to better identify location of problem.
- Say "(continued):" instead of "(continued:)" for consistency.
-
- * com.c (ffecom_gen_sfuncdef_): Set and reset new
- ffecom_nested_entry_ variable to hold ffesymbol being compiled.
- (lang_print_error_function): New function from toplev.c.
- Use ffecom_nested_entry_ to help determine which name
- and kind-string to print.
- (ffecom_expr_intrinsic_): Handle EXIT and FLUSH invocations
- with different calling sequences than library functions.
- Have SIGNAL and SYSTEM push and pop calltemps, and convert
- their return values to the destination type (just in case).
- (FFECOM_rttypeINT_): New return type for `int', in case
- gcc/f/runtime/libF77/system_.c(system_) is really supposed
- to return `int' instead of `ftnint'.
-
- * com.h (report_error_function): Declare this.
-
- * equiv.c (ffeequiv_layout_local_): Don't forget to consider
- root variable itself as possible "first rooted variable",
- else might never set symbol and then crash later.
-
- * intrin.c (ffeintrin_check_exit_): Change to allow no args
- and rename to ffeintrin_check_int_1_o_ for `optional'.
- #define ffeintrin_check_exit_ and _flush_ to this new
- function, so intrin.def can refer to the appropriate names.
-
- * intrin.def (FFEINTRIN_impFLUSH): Validate using
- ffeintrin_check_flush_ so passing an INTEGER arg is allowed.
-
- * lex.c (ffelex_file_push_, ffelex_file_pop_): New functions
- to manage input_file_stack in gbe.
- (ffelex_hash_): Call new functions (instead of doing code).
- (ffelex_include_): Call new functions to update stack for
- INCLUDE (_hash_ handles cpp output of #include).
-
-Mon Aug 21 08:09:04 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Makefile.in: Put `-W' in front of every `-Wall', since
- 2.7.0 requires that to engage `-Wunused' for parameters.
-
- * com.c: Mark all parameters as artificial, so
- `-W -Wunused' doesn't complain about unused ones (since
- there's no way right not to individually specify attributes
- like `unused').
-
- * proj.h: Don't #define UNUSED if already defined, regardless
- of host compiler.
-
-Sun Aug 20 16:03:56 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * gbe/2.7.0.diff: Regenerate.
-
- * lang-options.h, lang-specs.h: If not __STDC__ (ANSI C),
- avoid doing anything, especially the stringizing in -specs.h.
-
-Thu Aug 17 03:36:12 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * lang-specs.h: Remove useless optional settings of -traditional,
- since -traditional is always set anyway.
-
-Wed Aug 16 16:56:46 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Make-lang.in (F2C_INSTALL_FLAG, F2CLIBOK): More
- control over whether to install f2c-related stuff.
- (install-f2c-*): New targets to install f2c-related
- stuff in system, not just gcc, directories.
-
- * com.c: Change calls to ffecom_get_invented_identifier
- to use generally more predictable names.
- Change calls to build_range_type to ensure consistency
- of types of operands.
- (ffecom_get_external_identifier_): Change to accept
- symbol info, not just text, so it can use f2c flag for
- symbol to decide whether to append underscore(s).
- (ffecom_get_identifier_): Don't change names if f2c flag
- off for compilation.
- (ffecom_type_permanent_copy_): Use same type for new max as
- used for min.
- (ffecom_notify_init_storage): Offline fixups for stand-alone.
-
- * data.c (ffedata_gather): Explicitly test for common block,
- since it's no longer always the case that a local EQUIVALENCE
- group has no symbol ptr (it now can, if a user-predictable
- "rooted" symbol has been identified).
-
- * equiv.c: Add some debugging stuff.
- (ffeequiv_layout_local_): Set symbol ptr with user-predictable
- "rooted" symbol, for giving the invented aggregate a
- predictable name.
-
- * g77.c (append_arg): Allow for 20 extra args instead of 10.
- (main): For version-only case, add `-fnull-version' and, unless
- explicitly omitted, `-lf2c -lm'.
-
- * lang-options.h: New "-fnull-version" option.
-
- * lang-specs.h: Support ".fpp" suffix for preprocessed source
- (useful for OS/2, MS-DOS, other case-insensitive systems).
-
- * stc.c (ffestc_R544_equiv_): Swap way lists are merged so this
- is consistent with the order in which lists are built, making
- user predictability of invented aggregate name much higher.
-
- * storag.c, storag.h (FFESTORAG_typeDUMMY): Delete this enum.
-
- * top.c: Accept, but otherwise ignore, `-fnull-version'.
-
-Tue Aug 15 07:01:07 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * DOC, INSTALL, PROJECTS: Extensive improvements to documentation.
-
-Sun Aug 13 01:55:18 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * INSTALL (f77-install-ok): Document the use of this file.
-
- * Make-lang.in (F77_INSTALL_FLAG): New flag to control
- whether to install an `f77' command (based on whether
- a file named `f77-install-ok' exists in the source or
- build directory) to replace the broken attempt to use
- comment lines to avoid installing `f77' (broken in the
- sense that it prevented installation of `g77').
-
-Mon Aug 7 06:14:26 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * DOC: Add new sections for g77 & gcc compiler options,
- source code form, and types, sizes and precisions.
- Remove lots of old "delta-version" info, or at least
- summarize it.
-
- * INSTALL: Add info here that used to be in DOC.
- Other changes.
-
- * g77.c (lookup_option, main): Check for --print-* options,
- so we avoid adding version-determining stuff.
-
-Wed Jul 26 15:51:03 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Make-lang.in, Makefile.in (input.j, INPUT_H): New file.
- Update dependencies accordingly.
-
- * bad.c (ffebad_here): Okay to use unknown line/col.
-
- * compilers.h (@f77-cpp-input): Remove -P option now that
- # directives are handled by f771. Update other options
- to be more consistent with @c in gcc/gcc.c. Don't run f771
- if -E specified, etc., a la @c.
- (@f77): Don't run f771 if -E specified, etc., a la @c.
-
- * config-lang.in: Avoid use of word "guaranteed".
-
- * input.j: New file to wrap around gcc/input.h.
-
- * lex.j: Add support for parsing # directives output by cpp.
- (ffelex_cfebackslash_): New function.
- (ffelex_cfelex_): New function.
- (ffelex_get_directive_line_): New function.
- (ffelex_hash_): New function.
- (ffelex_include_): Change to not use ffewhere_file_(begin|end).
- Also fix bug in pointing to next line (for diagnostics, &c)
- following successful INCLUDE.
- (ffelex_next_line_): New function that does chunk of code
- seen in several places elsewhere in the lexers.
- (ffelex_file_fixed): Delay finishing statement until source
- line is registered with ffewhere, so INCLUDE processing
- picks up the info correctly.
- Okay to kill or use unknown line/col objects now.
- Handle HASH (#) lines.
- Reorder tests for insubstantial lines to put most frequent
- occurrences at top, for possible minor speedup.
- Some general consolidation of code.
- (ffelex_file_free): Handle HASH (#) lines.
- Okay to kill or use unknown line/col objects now.
- Some general consolidation of code.
- (ffelex_init_1): Detect HASH (#) lines.
- (ffelex_set_expecting_hollerith): Okay to kill or use unknown
- line/col objects now.
-
- * lex.h (FFELEX_typeHASH): New enum.
-
- * options-lang.h (-fident, -fno-ident): New options.
-
- * stw.c (ffestw_update): Okay to kill unknown line/col objects
- now.
-
- * target.h (FFETARGET_okREALQUAD, FFETARGET_okCOMPLEXDOUBLE,
- FFETARGET_okCOMPLEXQUAD): #define these appropriately.
-
- * top.c: Include flag.j wrapper, not flags.h directly.
- (ffe_is_ident_): New flag.
- (ffe_decode_option): Handle -fident and -fno-ident.
- (ffe_file): Replace obsolete ffewhere_file_(begin|end) with
- ffewhere_file_set.
-
- * top.h (ffe_is_ident_, ffe_is_ident, ffe_set_is_ident):
- New flag and access functions.
-
- * where.c, where.h: Remove all tracking of parent file.
- (ffewhere_file_begin, ffewhere_file_end): Delete these.
- (ffewhere_line_use): Make it work with unknown line object.
-
-Mon Jul 17 03:04:09 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (ffecom_sym_transform_): Set DECL_IN_SYSTEM_HEADER
- flag for any local vars used as stmtfunc dummies or DATA
- implied-DO iter vars, so no -Wunused warnings are produced
- for them (a la f2c).
- (ffecom_init_0): Do "extern int xargc;" for IARGC() intrinsic.
- Warn if target machine not 32 bits, since g77 isn't yet
- working on them at all well.
-
- * expr.c (ffeexpr_sym_lhs_call_, ffeexpr_sym_lhs_data_,
- ffeexpr_sym_lhs_extfunc_, ffeexpr_sym_rhs_actualarg_,
- ffeexpr_sym_rhs_let_, ffeexpr_paren_rhs_let_): Don't
- gratuitously set attr bits that don't apply just
- to avoid null set meaning error; instead, use explicit
- error flag, and allow null attr set, to
- fix certain bugs discovered by looking at this code.
-
- * g77.c: Major changes to improve support for gcc long options,
- to make `g77 -v' report more useful info, and so on.
-
-Mon Jul 3 14:49:16 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * DOC, com.c, intrin.h, intrin.c, intrin.def, target.h, top.c,
- top.h: Add new `unix' group of intrinsics, which includes the
- newly added ERF, ERFC, EXIT, plus even newer ABORT, DERF, DERFC,
- FLUSH, GETARG, GETENV, SIGNAL, and SYSTEM.
-
-Tue Jun 27 23:01:05 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * bld.c, bld.h (ffebld_constant_pool,
- ffebld_constant_character_pool): Use a single macro (the
- former) to access the pool for allocating constants, instead
- of latter in public and FFEBLD_CONSTANT_POOL_ internally
- in bld.c (which was the only one that was correct before
- these changes). Add verification of integrity of certain
- heap-allocated areas.
-
- * com.c (ffecom_overlap_, ffecom_args_overlap_,
- ffecom_tree_canonize_ptr_, ffecom_tree_canonize_ref_): New
- functions to optimize calling COMPLEX and, someday, CHARACTER
- functions requiring additional argument to be passed.
- (ffecom_call_, ffecom_call_binop_, ffecom_expr_,
- ffecom_expr_intrinsic_): Change calling
- sequences to include more info on possible destination.
- (ffecom_expr_intrinsic_): Add ERF(), ERFC(), and EXIT()
- intrinsic code.
- (ffecom_sym_transform_): For assumed-size arrays, set high
- bound to highest possible value instead of low bound, to
- improve validity of overlap checking.
- (duplicate_decls): If olddecl and newdecl are the same,
- don't do any munging, just return affirmative.
-
- * expr.c: Change ffecom_constant_character_pool() to
- ffecom_constant_pool().
-
- * info.c (ffeinfo_new): Compile this version if not being
- compiled by GNU C.
-
- * info.h (ffeinfo_new): Don't define macro if not being
- compiled by GNU C.
-
- * intrin.c, intrin.def: Add ERF(), ERFC(), and EXIT() intrinsics.
- (ffeintrin_check_exit_): New for EXIT() subroutine intrinsic.
-
- * malloc.c, malloc.h (malloc_verify_*): New functions to verify
- integrity of heap-storage areas.
-
- * stc.c (ffestc_R834, ffestc_R835): Handle possibility that
- an enclosing DO won't have a construct name even when the
- CYCLE/EXIT does (i.e. without dereferencing NULL).
-
- * target.c, target.h (ffetarget_verify_character1): New function
- to verify integrity of heap storage used to hold character constant.
-
-Thu Jun 22 15:36:39 1995 Howard Gordon (flash@super.org)
-
- * stp.h (ffestpVxtcodeIx): Fix typo in typedef for this.
-
-Mon May 29 15:22:31 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * *: Make all sorts of changes to accommodate upcoming gcc-2.7.0.
- I didn't keep track of them, nor just when I made them, nor
- when I (much later, probably in early August 1995) modified
- them so they could properly handle both 2.7.0 and 2.6.x.
-
- * com.c (ffecom_expr_power_integer_): Don't expand_start_stmt_expr
- if transforming dummy args, because the back end cannot handle
- that (it's rejected by the gcc front end), just generate
- call to run-time library.
- Back out changes in 0.5.15 because more temporaries might be
- needed anyway (for COMPLEX**INTEGER).
- (ffecom_push_tempvar): Remove inhibitor.
- Around start_decl and finish_decl (in particular, arround
- expand_decl, which is called by them), push NULL_TREE into
- sequence_rtl_expr, an external published by gcc/function.c.
- This makes sure the temporary is truly in the function's
- context, not the inner context of a statement-valued expression.
- (I think the back end is inconsistent here, but am not
- interested in convincing the gbe maintainers about this now.)
- (pushdecl): Make sure that when pushing PARM_DECLs, nothing
- other than them are pushed, as happened for 0.5.15 and which,
- if done for other reasons not fixed here, might well indicate
- some other problem -- so crash if it happens.
-
- * equiv.c (ffeequiv_layout_local_): If the local equiv group
- has a non-nil COMMON field, it should mean that an error has
- occurred and been reported, so just trash the local equiv
- group and do nothing.
-
- * stc.c (ffestc_promote_sfdummy_): Set sfdummy arg state to
- UNDERSTOOD so above checking for duplicate args actually
- works, and so we don't crash later in pushdecl.
-
- * ste.c (ffeste_R1001): Set initial value only for VAR_DECLs,
- not for, e.g., LABEL_DECLs, which the FORMAT label can be
- if it was previously treated as an executable label.
-
-Sat May 20 01:53:53 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (ffecom_sym_transform_): For adjustable arrays,
- pass high bound through variable_size in case its primaries
- are changed (dumb0.f, and this might also improve
- performance so it approaches f2c|gcc).
-
-Fri May 19 11:00:36 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Version 0.5.15 released.
-
- * com.c (ffecom_expr_power_integer_): Push temp vars
- before expanding a statement expression, since that seems
- to cause temp vars to be "forgotten" after the end of the
- expansion in the back end. Disallow more temp-var
- pushing during such an expansion, just in case.
- (ffecom_push_tempvar): Crash if a new variable needs to be
- pushed but cannot be at this point (should never happen).
-
-Wed May 17 12:26:16 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * expr.c (ffeexpr_collapse_convert): Add code to convert
- LOGICAL to CHARACTER. Reject conversion of REAL or COMPLEX
- to CHARACTER entirely, as it cannot be supported with all
- configurations.
-
- * target.h, target.c (ffetarget_convert_character1_logical1):
- New function.
-
-Sun May 14 00:00:09 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * com.c (ffecom_do_entry_, ffecom_gen_sfuncdef_,
- ffecom_start_progunit_, ffecom_sym_transform_,
- ffecom_init_0, start_function): Changes to have REAL
- external functions return same type as DOUBLE PRECISION
- external functions when -ff2c is in force; while at it,
- some code cleanups done.
-
- * stc.c (ffestc_R547_item_object): Disallow array declarator
- if one already exists for symbol.
-
- * ste.c (ffeste_R1227): Convert result variable to type
- of function result as seen by back end (e.g. for when REAL
- external function actually returns result as double).
-
- * target.h (FFETARGET_defaultFIXED_LINE_LENGTH): New
- macro for default for -ffixed-line-length-N option.
-
- * top.c (ffe_fixed_line_length_): Initialize this to new
- target.h macro instead of constant 72.
-
-Tue May 9 01:20:03 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * lex.c (ffelex_send_token_): If sending CHARACTER token with
- null text field, put a single '\0' in it and set length/size
- fields to 0 (to fix 950508-0.f).
- (ffelex_image_char_): When setting ffelex_bad_line_ to TRUE,
- always "close" card image by appending a null char and setting
- ffelex_card_length_. As part of this, append useful text
- to identify the two kinds of problems that involve this.
- (ffelex_file_fixed): Reset ffelex_bad_line_ to FALSE after
- seeing a line with invalid first character (fixes 950508-1.f).
- If final nontab column is zero, assume tab seen in line.
- (ffelex_card_image_): Always make this array 8 characters
- longer than reflected by ffelex_card_size_.
- (ffelex_init_1): Get final nontab column info from top instead
- of assuming 72.
-
- * options-lang.h: Add -ffixed-line-length- prefix.
-
- * top.h: Add ffe_fixed_line_length() and _set_ version, plus
- corresponding extern.
-
- * top.c: Handle -ffixed-line-length- option prefix.
-
-Fri Apr 28 05:40:25 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * Version 0.5.14 released.
-
- * Make-lang.in: Add assert.j.
-
- * Makefile.in: Add assert.j.
-
- * assert.j: New file.
-
-Thu Apr 27 16:24:22 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * bad.h (ffebad_severity): New function.
-
- * bad.c (ffebad_severity): New function.
-
- * bad.def (FFEBAD_OPEN_INCLUDE): Change severity from SEVERE
- to FATAL, since processing continues, and that seems fine.
+ * version.c: Bump version.
- * com.c: Add facility to handle -I.
- (ffecom_file, ffecom_close_include, ffecom_open_include,
- ffecom_decode_include_option): New global functions for -I.
- (ffecom_file_, ffecom_initialize_char_syntax_,
- ffecom_close_include_, ffecom_decode_include_option_,
- ffecom_open_include_, append_include_chain, open_include_file,
- print_containing_files, read_filename_string, file_name_map,
- savestring): New internal functions for -I.
+Wed May 12 07:30:05 1999 Craig Burley <craig@jcb-sc.com>
- * compilers.h: Pass -I flag(s) to f771 (via "%{I*}").
+ * com.c (lang_init_options): Disable back end's maintenance
+ of errno.
+ * news.texi: Document dropping of errno.
- * lex.c (ffelex_include_): Call ffecom_close_include
- to close include file, for its tracking needs for -I,
- instead of using fclose.
+1999-05-10 18:21 -0400 Zack Weinberg <zack@rabi.phys.columbia.edu>
- * options-lang.h: Add -I prefix.
+ * lang-specs.h: Pass -$ to the preprocessor.
- * parse.c (yyparse): Call ffecom_file for main input file,
- so -I handling works (diagnostics).
+Mon May 10 18:14:28 1999 Craig Burley <craig@jcb-sc.com>
- * std.c (ffestd_S3P4): Have ffecom_open_include handle
- opening and diagnosing errors with INCLUDE files.
+ * g77.texi: Fix various @xref's per proper style.
+ Go ahead and use nested braces in @xref's, with care.
+ * g77install.texi: Fix @xref per proper style.
- * ste.c (ffeste_begin_iterdo_): Use correct algorithm for
- calculating # of iterations -- mathematically similar but
- computationally different algorithm was not handling cases
- like "DO I=6,5,2" correctly, because (5-6)/2+1 => 1, not 0.
+Mon May 10 17:38:39 1999 Craig Burley <craig@jcb-sc.com>
- * top.c (ffe_decode_option): Allow -I, restructure a bit
- for clarity and, maybe, speed.
+ * news.texi: Doc upgrade to netlib libf2c as of today.
-Mon Apr 17 13:31:11 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Sun May 9 18:52:13 1999 Hans-Peter Nilsson <hp@bitrange.com>
- * g77.c: Remove -lc, turns out not all systems has it, but
- leave other changes in for clarity of code.
+ * f/g77spec.c (lang_specific_driver): Correct bug-report address
+ and point to the FAQ.
-Sun Apr 16 21:50:33 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Thu May 6 12:40:21 1999 Craig Burley <craig@jcb-sc.com>
- * com.c (ffecom_expr_): Implement ARRAY_EXPR as INDIRECT_REF
- of appropriate PLUS_EXPRs of ptr_to_expr of array, to see
- if this generates better code. (Conditional on
- FFECOM_FASTER_ARRAY_REFS.)
+ * g77.texi (Arbitrary Concatenation): Put this under
+ "Missing Features" instead of "Projects".
+ (Internals Documentation): Point to new "Front End" chapter.
-Sun Apr 16 00:22:48 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Thu May 6 08:23:52 1999 Craig Burley <craig@jcb-sc.com>
- * Make-lang.in (F77_SRCS): Remove g77.c, since it doesn't
- contribute to building f771.
+ * bugs.texi, news.texi: Automatic arrays reportedly working
+ on HP-UX systems.
- * Makefile.in (dircheck): Remove/replace with f/Makefile, because
- phony targets that are referenced in other real targets get run
- when those targets are specified, which is a waste of time (e.g.
- when rebuilding and only g77.c has changed, f771 was being linked
- anyway).
+Thu May 6 08:19:31 1999 Craig Burley <craig@jcb-sc.com>
- * g77.c: Include -lc between -lf2c and -lm throughout.
+ * g77.texi (Advantages Over f2c): Expand on this topic.
- * implic.c (ffeimplic_establish_symbol): If -Wimplicit, warn if
- implicit type given to symbol.
+Mon May 3 19:41:48 1999 Craig Burley <craig@jcb-sc.com>
- * lex.c (ffelex_include_): Don't gratuitously increment line
- number here.
+ * com.c (ffecom_expr_intrinsic_): Fix test of CTIME_subr.
- * top.h, top.c (ffe_is_warn_implicit_): New global variable and
- related access macros.
- (ffe_decode_option): Handle -W options, including -Wall and
- -Wimplicit.
+Mon May 3 18:11:48 1999 Craig Burley <craig@jcb-sc.com>
- * where.c (ffewhere_line_new): Don't muck with root line (was
- crashing on null input since lexer changes over the past week
- or so).
+ Reverse order of two arguments to CTIME_subr, DTIME_subr,
+ ETIME_subr, and TTYNAM_subr:
+ * com.c (ffecom_expr_intrinsic_): Reverse the arguments.
+ While at it, set TREE_SIDE_EFFECTS for CTIME_subr and
+ TTYNAM_subr.
+ * intdoc.in: Document the new calling sequences.
+ * intrin.def: Reverse the arguments.
+ * news.texi: Document the fact that they changed.
+ * version.c: Bump version.
-Thu Apr 13 16:48:30 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Mon May 3 11:28:14 1999 Craig Burley <craig@jcb-sc.com>
- * com.c (ffecom_init_0): Register built-in functions for cos,
- sin, and sqrt.
- (ffecom_tree_fun_type_double): New variable.
- (ffecom_expr_intrinsic_): Update f2c input and output files
- to latest version of f2c (no important g77-related changes
- noted, just bug fixes to f2c and such).
- (builtin_function): New function from c-decl.c.
+ * news.texi: Doc upgrade to netlib libf2c as of today.
- * com-rt.def: Refer to built-in functions for cos, sin, and sqrt.
+Sun May 2 17:04:28 1999 Craig Burley <craig@jcb-sc.com>
-Thu Apr 13 10:25:09 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * version.c: Bump version.
- * com.c (ffecom_expr_intrinsic_): Convert 0. to appropriate
- type to keep DCMPLX(I) from crashing the compiler.
- (ffecom_expr_): Don't convert result from ffecom_tree_divide_.
- (ffecom_tree_divide_): Add tree_type argument, have all callers
- pass one, and don't convert right-hand operand to it (this is
- to make this new function work as much like the old in-line
- code used in ffecom_expr_ as possible).
+Sun May 2 16:53:01 1999 Craig Burley <craig@jcb-sc.com>
- * lex.c: Maintain lineno and input_filename the way the gcc
- lexer does.
+ Fix compile/19990502-1.f:
+ * ste.c (ffeste_R819B): Don't overwrite tree for temp
+ variable when expanding the assignment into it.
- * std.c (ffestd_exec_end): Save and restore lineno and
- input_filename around the second pass, which sets them
- appropriately for each saved statement.
+Sun Apr 25 20:55:10 1999 Craig Burley <craig@jcb-sc.com>
-Wed Apr 12 09:44:45 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ Fix 19990325-0.f and 19990325-1.f:
+ * com.c (ffecom_possible_partial_overlap_): New function.
+ (ffecom_expand_let_stmt): Use it to determine whether to assign
+ to a COMPLEX operand through a temp.
+ * news.texi: Document fix.
- * com.c (ffecom_expr_power_integer_): New function.
- (ffecom_expr_): Call new function for power op with integer second
- argument, for generating better code. Also replace divide
- code with call to new ffecom_tree_divide_ function.
- Canonicalize calls to ffecom_truth_value(_invert).
- (ffecom_tree_divide_): New function.
+ * version.c: Bump version.
-Wed Apr 5 14:15:44 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Sat Apr 24 12:19:53 1999 Craig Burley <craig@jcb-sc.com>
- * lex.c: Change to allocate text for tokens only when actually
- needed, which should speed compilation up somewhat.
- Change to allow INCLUDE at any point where a statement
- can end, i.e. in ffelex_finish_statement_ or when a SEMICOLON
- token is sent.
- Remove some old, obsolete code.
- Clean up layout of entire file to improve formatting,
- readability, etc.
- (ffelex_set_expecting_hollerith): Remove include argument.
+ * expr.c (ffeexpr_finished_): Convert DATA implied-do
+ start/end/incr expressions to default INTEGER.
+ Fix some broken conditionals.
+ Clean up some code in the region.
+ * news.c: Document the fix.
-Fri Mar 31 23:19:08 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * version.c: Bump version.
- * bad.h, bad.c (ffebad_start_msg, ffebad_start_msg_lex):
- New functions to generate arbitrary messages.
- (FFEBAD_severityPEDANTIC): New severity, to correspond
- to toplev's pedwarn() function.
+Fri Apr 23 02:08:32 1999 Craig Burley <craig@jcb-sc.com>
- * lex.c (ffelex_backslash_): New function to implement
- backslash processing.
- (ffelex_file_fixed, ffelex_file_free): Implement new
- backslash processing.
+ * g77.texi (Compiler Prototypes): Replace "missing" subscript-
+ checking option with something else.
- * std.c (ffestd_R1001dump_): Don't assume CHARACTER and
- HOLLERITH tokens stop at '\0' characters, now that backslash
- processing is supported -- use their advertised lengths instead,
- and double up the '\002' character for libf2c.
+Fri Apr 23 01:48:28 1999 Craig Burley <craig@jcb-sc.com>
-Mon Mar 27 17:10:33 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ Support new -fsubscript-check and -ff2c-subscript-check options:
+ * com-rt.def (FFECOM_gfrtRANGE): Describe s_rnge, in libf2c/libF77.
+ * com.c (ffecom_subscript_check_, ffecom_arrayref_): New functions.
+ (ffecom_char_args_x_): Use new ffecom_arrayref_ function for
+ FFEBLD_opARRAYREF case.
+ Compute character name, array type, and use new
+ ffecom_subscript_check_ function for FFEBLD_opSUBSTRING case.
+ (ffecom_expr_): Use new ffecom_arrayref_ function.
+ (ffecom_ptr_to_expr): Use new ffecom_arrayref_ function.
+ * g77.texi, news.texi: Document new options.
+ * top.c, top.h: Support new options.
- * com.c (ffecom_init_local_zero_): Implement -finit-local-zero.
- (ffecom_sym_transform_): Same.
- (ffecom_transform_equiv_): Same.
+ * news.texi: Fix up some items to not be in "User-Visible Changes".
- * options-lang.h: Add -f(no-)(init-local-zero,backslash,ugly-init).
+ * ste.c (ffeste_R819B): Fix type for loop variable, to avoid
+ warnings.
- * stb.c (ffestb_V020): Reject "TYPEblah(...", which might be
- an array assignment.
+ * version.c: Bump version.
- * target.h, top.h, top.c: Implement -finit-local-zero.
+Tue Apr 20 01:38:57 1999 Craig Burley <craig@jcb-sc.com>
-Fri Mar 24 19:56:22 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * bugs.texi, news.texi: Clarify -malign-double situation.
- * Make-lang.in, Makefile.in: Remove conf-proj(.in) and
- proj.h(.in) rules, plus related config.log, config.cache,
- and config.status stuff.
+Tue Apr 20 01:15:25 1999 Craig Burley <craig@jcb-sc.com>
- * com.c (ffecom_init_0): Change messages when atof(), bsearch(),
- or strtoul() do not work as expected in the start-up test.
-
- * conf-proj, conf-proj.in: Delete.
-
- * lex.c (ffelex_file_fixed): Allow f2c's '&' in column 1
- to mean continuation line.
-
- * options-lang.h: New file, #include'd by ../toplev.c.
-
- * proj.h.in: Rename back to proj.h.
-
- * proj.h (LAME_ASSERT): Remove.
- (LAME_STDIO): Remove.
- (NO_STDDEF): Remove.
- (NO_STDLIB): Remove.
- (NO_BSEARCH): Remove auto detection, rename to !FFEPROJ_BSEARCH.
- (NO_STRTOUL): Remove auto detection, rename to !FFEPROJ_STRTOUL.
- (USE_HOST_LIMITS): Remove (maybe still needed by stand-alone?).
- (STR, STRX): Do only ANSI C definitions.
-
-Mon Mar 13 10:46:13 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * stb.c (ffestb_R5282_): Convert DATA repeat count
+ to default INTEGER, to avoid problems downstream.
- * BUGS: Add item about g77 requiring gcc to compile it.
-
- * NEWS: New file listing user-visible changes in the release.
-
- * PROJECTS: Update to include a new item or two, and modify
- or delete items that are addressed in this or previous releases.
-
- * bad.c (ffebad_finish): Don't crash if missing string &c,
- just substitute obviously distressed string "[REPORT BUG!!]"
- for cases where the message/caller are fudgy.
+ * version.c: Bump version.
- * bad.def: Clean up error messages in a major way, add new ones
- for use by changes in target.c.
-
- * com.c (ffecom_expr_): Handle opANY in opCONVERT.
- (ffecom_let_char_): Disregard destinations with ERROR_MARK.
- (ffecom_1, ffecom_1_fn, ffecom_2, ffecom_2s, ffecom_3,
- ffecom_3s, &c): Check all inputs for error_mark_node.
- (ffecom_start_progunit_): Don't transform all symbols
- in BLOCK DATA, since it never executes, and it is silly
- to, e.g., generate all the structures for NAMELIST.
- (ffecom_char_length_expr_): Rename to ffecom_intrinsic_len_.
- (ffecom_intrinsic_ichar_): New function to handle ICHAR of
- arbitrary expression with possible 0-length operands.
- (ffecom_expr_intrinsic_): Use ffecom_intrinsic_char_.
- For MVBITS, set tree_type to void_type_node.
- (ffecom_start_progunit_): Name master function for entry points
- after primary entry point so users can easily guess it while
- debugging.
- (ffecom_arg_ptr_to_expr): Change treatment of Hollerith,
- Typeless, and %DESCR.
- (ffecom_expr_): Change treatment of Hollerith.
-
- * data.c (ffedata_gather_): Handle opANY in opCONVERT.
+Mon Apr 19 21:36:48 1999 Craig Burley <craig@jcb-sc.com>
- * expr.c (ffeexpr_token_apostrophe_): Issue FFEBAD_NULL_CHAR_CONST
- warning as necessary.
- (ffeexpr_token_name_rhs_): Set context for args to intrinsic
- so that assignment-like concatenation is allowed for ICHAR(),
- IACHAR(), and LEN() intrinsics.
- (ffeexpr_reduced_*_): Say "an array" instead of "an entity" in
- diagnostics, since it's more informative.
- (ffeexpr_finished_): For many contexts, check for null expression
- and array before trying to do a conversion, to avoid redundant
- diagnostics.
+ * ste.c (ffeste_R819B): Start the loop before expanding
+ the termination expression.
- * g77.1: Fix typo for preprocessed suffix (.F, not .f).
+ * version.c: Bump version.
- * global.c (ffeglobal_init_common): Warn if initializing
- blank common.
- (ffeglobal_pad_common): Enable code to warn if initial
- padding needed.
- (ffeglobal_size_common): Complain if enlarging already-
- initialized common, since it won't work right anyway.
+Sun Apr 18 21:53:58 1999 Craig Burley <craig@jcb-sc.com>
+
+ * com.c (ffecom_sym_transform_): COMMON and EQUIVALENCE
+ variables have constant addresses (EQUIVALENCE only if
+ containing aggregate is static).
+
+Sat Apr 17 16:55:59 1999 Craig Burley <craig@jcb-sc.com>
+
+ * bugs.texi, ffe.texi, g77.texi, g77install.texi, news.texi:
+ Clean up @code{} vs. @samp{}.
+ Clean up dashes (`--') vs. @minus{} vs. `---'.
+
+ * ffe.texi: Add copyright header.
+
+ * g77.texi, lang-options.h, news.texi, top.c (ffe_decode_option):
+ Remove support for -fugly option.
+ Clarify that -fugly-logint is needed instead of -fugly
+ to work around using .EQ./.NE. on LOGICAL operands.
+ Explain more about why -fugly-logint is bad juju.
+
+ * g77.texi (Missing Features): Describe READONLY as a missing
+ feature. Describe AUTOMATIC better.
+
+ * news.texi: Mention libf2c upgrade.
+
+Sat Apr 17 14:05:53 1999 Craig Burley <craig@jcb-sc.com>
+
+ Make a place for front-end internals documentation:
+ * Make-lang.in (f/g77.info, f/g77.dvi): Depend on f/ffe.texi.
+ * ffe.texi: New file, containing docs on front-end internals.
+ * g77.texi: New chapter for, and inclusion of, ffe.texi.
+
+ * g77.texi: Fix an index entry.
+
+Sat Apr 17 13:53:43 1999 Craig Burley <craig@jcb-sc.com>
+
+ Rewrite to use block/scope structure of GBE and to ensure
+ variables (especially those going on stack/reg) are declared
+ before executable code generated:
+ * bld.c (ffebld_new_item, ffebld_new_one, ffebld_new_two):
+ Support new hooks.
+ * bld.h (ffebld_item_hook, ffebld_item_set_hook,
+ ffebld_nonter_hook, ffebld_nonter_set_hook): Ditto.
+ * bld.h (ffebld_basictype, ffebld_kind, ffebld_kindtype,
+ ffebld_rank, ffebld_where): New convenience macros (used
+ by rest of this patch).
+ * com.c, com.h (ffecom_push_calltemps, ffecom_pop_calltemps,
+ ffecom_push_tempvar, ffecom_pop_tempvar): Remove temp-var-
+ handling mechanism.
+ * com.c (ffecom_call_, ffecom_call_binop_, ffecom_tree_divide_,
+ ffecom_call_gfrt): Support passing hooks for temp-var info.
+ (ffecom_expr_power_integer_): Takes opPOWER expression, instead
+ of its left and right operands, so it can get at the hook.
+ (ffecom_prepare_let_char_, ffecom_prepare_arg_ptr_to_expr,
+ ffecom_prepare_end, ffecom_prepare_expr_, ffecom_prepare_expr_rw,
+ ffecom_prepare_expr_w, ffecom_prepare_return_expr,
+ ffecom_prepare_ptr_to_expr): New functions supporting expression
+ pre-scanning.
+ (bison_rule_compstmt_): Return the tree, as in the CFE.
+ (delete_block): New function, from CFE.
+ (kept_level_p): New function, from CFE, modified.
+ (ffecom_start_compstmt, ffecom_end_compstmt): New functions,
+ replacing ffecom_start_compstmt_ and ffecom_end_compstmt_ macros,
+ and they do real work.
+ (struct binding_level): Add prep_state member. Initialize to 0.
+ (ffecom_get_invented_identifier): Now takes either or both a
+ string and an integer, using -1 to denote no integer.
+ (ffecom_do_entry_): Disallow temp-var generation via expressions
+ in body of function, since the exprs aren't prescanned.
+ (ffecom_expr_rw): Now takes destination tree.
+ (ffecom_expr_w): New function, now used in some places
+ ffecom_expr_rw had been used.
+ (ffecom_expr_intrinsic_): Move huge f2c-related comment to bottom
+ of source file, to avoid annoying problems editing com.c using
+ Emacs C-mode.
+ (ffecom_expr_power_integer_): Make a temp var for division, if
+ necessary.
+ Handle expanded statement expression as does CFE.
+ (ffecom_start_progunit_): Disallow temp-var generation in body
+ of function, since expressions are not prescanned at this level.
+ (ffecom_sym_transform_): Transform ASSIGN variables as well,
+ so these are all transformed up front, before code-generation
+ begins.
+ (ffecom_arg_ptr_to_const_expr, ffecom_const_expr,
+ ffecom_ptr_to_const_expr): New functions to transform expressions
+ only if the results will surely be constants.
+ (ffecom_arg_ptr_to_expr): Precompute size, for convenience
+ obtaining temp vars.
+ (ffecom_expand_let_stmt): Guess at usability of destination
+ pre-expansion, to provide better prescan preparation (fewer
+ spurious temp vars).
+ (ffecom_init_0): Disallow temp-var generation in global scope.
+ (ffecom_type_expr): New function, returns just the type tree
+ for the expression.
+ (start_function): Disallow temp-var generation in parm scope.
+ (incomplete_type_error): Fix introductory comment.
+ (poplevel): Update (somewhat) from CFE.
+ (pushlevel): Update (somewhat) from CFE.
+ * stc.c (ffestc_R838): Mark ASSIGNed variable as so.
+ * std.c (ffestd_stmt_pass_, ffestd_R803, ffestd_R804, ffestd_R805,
+ ffestd_R806): Remember and pass through the ffestw block info
+ for these (IFTHEN, ELSEIF, ELSE, and ENDIF) statements.
+ * ste.c (ffeste_end_iterdo_): Now takes ffestw block argument.
+ (ffeste_io_inlist_): Add prototype.
+ (ffeste_f2c_*): Macros rewritten, new ones added.
+ (ffeste_start_block_, ffeste_end_block_, ffeste_start_stmt_,
+ ffeste_end_stmt_): New macros/functions, depending on whether
+ checking is enabled, to keep track of symmetry of other ste.c code.
+ (ffeste_begin_iterdo_, ffeste_end_iterdo_, ffeste_io_impdo_,
+ ffeste_io_dofio_, ffeste_io_dolio_, ffeste_io_douio_,
+ ffeste_io_ialist_, ffeste_io_cilist_, ffeste_io_cllist_,
+ ffeste_icilist_, ffeste_io_inlist_, ffeste_io_olist_,
+ ffeste_subr_beru_, ffeste_do, ffeste_end_R807, ffeste_R737A,
+ ffeste_R803, ffeste_R804, ffeste_R805, ffeste_R806, ffeste_R807,
+ ffeste_R809, ffeste_R810, ffeste_R811, ffeste_R819A, ffeste_R819B,
+ ffeste_R837, ffeste_R838, ffeste_R839, ffeste_R840, ffeste_R904,
+ ffeste_R907, ffeste_R909_start, ffeste_R909_item, ffeste_R909_finish,
+ ffeste_R910_start, ffeste_R910_item, ffeste_R910_finish,
+ ffeste_R911_start, ffeste_R911_item, ffeste_R911_finish,
+ ffeste_R923A, ffeste_R1212, ffeste_R1227): Prescan/prepare
+ all pertinent expressions, update to new com.c interface, etc.
+ (ffeste_io_impdo_): Relocate.
+ (ffeste_R834, ffeste_R835, ffeste_R836, ffeste_R1226): Don't
+ bother calling clear_momentary, nothing was generated.
+ (ffeste_R842, ffeste_R843): Update to new com.c interface.
+ (ffeste_R1226): Don't try to stuff error_mark_node's DECL_INITIAL.
+ (ffeste_terminate_2): When checking enabled, make sure all blocks
+ and statements have been ended.
+ * ste.h (ffeste_R803, ffeste_R804, ffeste_R805, ffeste_R806):
+ These now take ffestw block argument.
+ (ffeste_terminate_2): When checking enabled, it's a function, not
+ a macro.
+ * stw.h (struct _ffestw_): New variable for IFTHEN.
+ (ffestw_ifthen_fake_else, ffestw_set_ifthen_fake_else): New
+ accessor macros.
+ * symbol.c, symbol.h: Support new ASSIGN'ed-to info.
+
+ * com.c: Clean up commentary per GNU coding standards.
+
+ * bld.h (ffebld_size, ffebld_size_known): Canonize.
- * intrin.c: Add IMAG() intrinsic.
- (ffeintrin_check_loc_): Allow opSUBSTR in LOC().
+ * version.c: Bump version.
- * intrin.def: Add IMAG() intrinsic.
+Sun Apr 11 21:33:33 1999 Mumit Khan <khan@xraylith.wisc.edu>
- * lex.c: Don't report FFEBAD_NULL_CHAR_CONST errors.
+ * g77spec.c (lang_specific_driver): Check whether MATH_LIBRARY is
+ null to decide whether to use it.
- * sta.c, sta.h, stb.c: Changes to clean up error messages (see
- bad.def).
+Wed Apr 7 09:47:09 1999 Kaveh R. Ghazi <ghazi@snafu.rutgers.edu>
- * stb.c (ffestb_R100113_): Issue FFEBAD_NULL_CHAR_CONST
- warning as necessary.
+ * ansify.c (die): Specify void argument.
- * stc.c (ffestc_shriek_do_): Don't try to reference doref_line
- stuff in ANY case, since it won't be valid.
- (ffestc_R1227): Allow RETURN in main program unit, with
- appropriate warnings/errors.
- (ffestc_subr_format_): Array of any type is a CHAREXPR (F77 C5).
-
- * ste.c (ffeste_begin_doiter_): Couple of fixes to accurately
- determine if loop never executes.
-
- * target.c (ffetarget_convert_*_hollerith_): Append spaces,
- not zeros, to follow F77 Appendix C, and to warn when
- truncation of non-blanks done.
- (ffetarget_convert_*_typeless): Rewrite to do typeless
- conversions properly, and warn when truncation done.
- (ffetarget_print_binary, ffetarget_print_octal,
- ffetarget_print_hex): Rewrite to use new implementation of
- typeless.
- (ffetarget_typeless_*): Rewrite to use new implementation
- of typeless, and to warn about overflow.
-
- * target.h (ffetargetTypeless): New implementation of
- this type.
-
- * type.h, type.c (ffetype_size_typeless): Remove (incorrect)
- implementation of this function and its extern.
-
-Sun Mar 5 18:46:42 1995 Craig Burley (burley@gnu.ai.mit.edu)
-
- * BUGS: Clarify that constant handling would also fix lack of
- adequate IEEE-754/854 support to some degree, and typeless
- and non-decimal constants.
-
- * com.c (ffecom_type_permanent_copy_): Comment out to avoid
- warnings.
- (duplicate_decls): New function a la gcc/c-decl.c.
- (pushdecl): Use duplicate_decls to decide whether to return
- existing decl or new one, instead of always returning existing
- decl.
- (ffecom_expr_): opPERCENT_LOC now supports CHARACTER arguments.
- (ffecom_init_0): Give f2c I/O code 0 for basictypeANY/kindtypeANY.
- (ffecom_sym_transform_): For adjustable arrays, pass low bound
- through variable_size in case its primaries are changed (950302-1.f).
+ * intdoc.c (family_name, dumpgen, dumpspec, dumpimp,
+ argument_info_ptr, argument_info_string, argument_name_ptr,
+ argument_name_string, elaborate_if_complex,
+ elaborate_if_maybe_complex, elaborate_if_real, print_type_string):
+ Const-ify a char*.
+ (main): Mark parameter `argv' with ATTRIBUTE_UNUSED.
+ (_ffeintrin_name_, _ffeintrin_gen_, _ffeintrin_spec_,
+ _ffeintrin_imp_, cc_pair, descriptions, summaries): Const-ify a char*.
- * com.h: More decls that belong in tree.h &c.
+Mon Apr 5 11:57:54 1999 Donn Terry (donn@interix.com)
- * data.c (ffedata_eval_integer1_): Fix opPAREN case to not
- treat value of expression as an error code.
+ * Make-lang.in (HOST_CFLAGS): compute dynamically.
- * expr.c (ffeexpr_finished_): Allow opSUBSTR in contextLOC case.
+Mon Apr 5 02:11:23 1999 Craig Burley <craig@jcb-sc.com>
- * proj.c: Add "const" as appropriate.
+ Fix bugs exposed by configuring with --enable-checking:
+ * com.c (ffecom_do_entry_, ffecom_expr_, ffecom_arg_ptr_to_expr,
+ ffecom_list_expr, ffecom_list_ptr_to_expr, finish_function,
+ pop_f_function_context, store_parm_decls, poplevel): Handle
+ error_mark_node properly.
+ * ste.c (ffeste_begin_iterdo_, ffeste_end_iterdo_): Ditto.
+ * version.c: Bump version.
-Mon Feb 27 10:04:03 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Sat Apr 3 23:57:56 1999 Craig Burley <craig@jcb-sc.com>
- * bad.def (FFEBAD_BAD_SUBSTR): Fix bad grammar in message.
+ * g77.texi: Fix up docs for -fset-g77-defaults, and
+ describe how internal consistency checking now happens.
+ (Should have been done for EGCS version 1.1.)
-Fri Feb 24 16:21:31 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Sat Apr 3 23:29:33 1999 Craig Burley <craig@jcb-sc.com>
- * Version 0.5.13 released.
+ * bugs.texi, g77.texi, lang-options.h, news.texi, top.c:
+ Make -fno-emulate-complex the default, as COMPLEX support
+ in the back end is now believed to be working.
- * INSTALL: Warn that f/zzz.o will compare differently between
- stages, since it puts the __TIME__ macro into a string.
+ * version.c: Bump version.
- * com.c (ffecom_sym_transform_): Transform kindFUNCTION/whereDUMMY
- to pointer-to-function, not function.
- (ffecom_expr_): Use ffecom_arg_ptr_to_expr instead of
- ffecom_char_args_ to handle comparison between CHARACTER
- types, so either operand can be a CONCATENATE.
- (ffecom_transform_common_): Set size of initialized common area
- to global (largest-known) size, even though size of init might
- be smaller.
+Fri Apr 2 13:33:16 1999 Craig Burley <craig@jcb-sc.com>
- * equiv.c (ffeequiv_offset_): Check symbol info for ANY.
+ * g77.texi: -malign-double now works.
+ Give URL for alignment-testing package.
+ * news.texi: -malign-double now works.
- * expr.c (ffeexpr_find_close_paren_, ffeexpr_nil_*): New functions
- to handle following the contour of a rejected expression, so
- statements like "PRINT(I,I,I)=0" don't cause the PRINT statement
- code to get the second passed back to it as if there was a
- missing close-paren before it, the comma causing the PRINT code
- to confirm the statement, resulting in an ambiguity vis-a-vis
- the let statement code.
- Use the new ffecom_find_close_paren_ handler when an expected
- close-paren is missing.
- (ffeexpr_isdigits_): New function, use in all places that
- currently use isdigit in repetitive code.
- (ffeexpr_collapse_symter): Collapse to ANY if init-expr is ANY,
- so as to avoid having symbol get "transformed" if used to
- dimension an array.
- (ffeexpr_token_real_, ffeexpr_token_number_real_): Don't issue
- diagnostic about exponent, since it'll be passed along the
- handler path, resulting in a diagnostic anyway.
- (ffeexpr_token_apos_char_): Use consistent handler path
- regardless of whether diagnostics inhibited.
- (ffeexpr_token_name_apos_name_): Skip past closing quote/apos
- even if not a match or other diagnostic issued.
- (ffeexpr_sym_impdoitem_): Exec-transition local SEEN symbol.
+Fri Apr 2 12:49:12 1999 Craig Burley <craig@jcb-sc.com>
- * lex.c (ffelex_image_char_): Set ffelex_saw_tab_ if TAB
- seen, not if anything other than TAB seen!
+ * g77.texi (Funding GNU Fortran): Dude's got a web page.
+ * root.texi: Ditto.
- * stc.c (ffestc_R537_item): If source is ANY but dest isn't,
- set dest symbol's init expr to ANY.
- (ffestc_R501_attrib, ffestc_R522, ffestc_R522start): Complain
- about conflict between "SAVE" by itself and other uses of
- SAVE only in pedantic mode.
+Tue Mar 30 12:04:11 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * ste.c (ffeste_R1212): Fix loop over labels to always
- increment caseno, to avoid pushcase returning 2 for duplicate
- values when one of the labels is invalid.
+ * sta.c (ffesta_ffebad_1sp, ffesta_ffebad_1st, ffesta_ffebad_2st):
+ Const-ify a char*.
-Thu Feb 23 12:42:04 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * sta.h (ffesta_ffebad_1sp, ffesta_ffebad_1st, ffesta_ffebad_2st):
+ Likewise.
- * Version 0.5.12 released.
+ * stb.c (ffestb_local_u_): Likewise.
+ (ffestb_do, ffestb_dowhile, ffestb_else, ffestb_elsexyz,
+ ffestb_else3_, ffestb_endxyz, ffestb_goto, ffestb_let,
+ ffestb_type, ffestb_type1_, ffestb_varlist, ffestb_R423B,
+ ffestb_R522, ffestb_R528, ffestb_R542, ffestb_R834, ffestb_R835,
+ ffestb_R838, ffestb_R841, ffestb_R1102, ffestb_blockdata,
+ ffestb_R1212, ffestb_R1228, ffestb_V009, ffestb_module,
+ ffestb_R809, ffestb_R810, ffestb_R10014_, ffestb_R10015_,
+ ffestb_R10018_, ffestb_R1107, ffestb_R1202, ffestb_R12026_,
+ ffestb_S3P4, ffestb_V012, ffestb_V014, ffestb_V025, ffestb_V0255_,
+ ffestb_V020, ffestb_dimlist, ffestb_dummy, ffestb_R524,
+ ffestb_R547, ffestb_decl_chartype, ffestb_decl_dbltype,
+ ffestb_decl_gentype, ffestb_decl_recursive, ffestb_decl_entsp_2_,
+ ffestb_decl_func_, ffestb_V003, ffestb_V016, ffestb_V027,
+ ffestb_decl_R539): Likewise.
- * Make-lang.in (f77.install-common): Add "else true;" before outer
- "fi" per Makefile.in patch.
+ * stb.h (_ffestb_args_): Likewise.
- * Makefile.in (dircheck): Add "else true;" before "fi" per
- patch from chs1pm@surrey.ac.uk.
+ * stc.c (ffestc_subr_binsrch_, ffestc_subr_is_present_,
+ ffestc_subr_speccmp_, ffestc_R904, ffestc_R907): Likewise.
- * com.c (ffecom_push_tempvar): If type desired is ERROR_MARK,
- return error_mark_node, to avoid crash that results from
- making a VAR_DECL with error_mark_node as its type.
+ * std.c (ffestd_R1001dump_1005_1_, ffestd_R1001dump_1005_2_,
+ ffestd_R1001dump_1005_3_, ffestd_R1001dump_1005_4_,
+ ffestd_R1001dump_1005_5_, ffestd_R1001dump_1010_1_,
+ ffestd_R1001dump_1010_2_, ffestd_R1001dump_1010_3_,
+ ffestd_R1001dump_1010_4_, ffestd_R1001dump_1010_5_): Likewise.
- * ste.c (ffeste_begin_iterdo_): Convert itercount to INTEGER
- anytime calculation of number of iterations ends up with type
- other than INTEGER (e.g. DOUBLE PRECISION, REAL).
+ * ste.c (ffeste_begin_iterdo_, ffeste_subr_file_): Likewise.
-Thu Feb 23 02:48:38 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * sts.c (ffests_printf_1D, ffests_printf_1U, ffests_printf_1s,
+ ffests_printf_2Us, ffests_puts, ffests_puttext): Likewise.
- * Version 0.5.11 released.
+ * sts.h (ffests_printf_1D, ffests_printf_1U, ffests_printf_1s,
+ ffests_printf_2Us, ffests_puts, ffests_puttext): Likewise.
- * DOC: Explain -fugly-args.
+ * stt.c (ffestt_exprlist_drive, ffestt_implist_drive,
+ ffestt_tokenlist_drive): Add prototype arguments.
- * bad.def (FFEBAD_ACTUALARG): Explain -fugly-args and how to
- rewrite code to not require it.
+ * stt.h (ffestt_exprlist_drive, ffestt_implist_drive,
+ ffestt_tokenlist_drive): Likewise.
- * com.c (ffecom_vardesc_): Handle negative type code, just in
- case.
- (ffecom_arg_ptr_to_expr): Let ffecom_expr handle hollerith
- and typeless constants (move code to ffecom_constantunion).
- (ffecom_constantunion): Handle hollerith and typeless constants.
+ * stu.c (ffestu_dummies_transition_): Likewise.
+ (ffestu_sym_end_transition): Const-ify a char*.
- * expr.c (ffecom_finished_): Check -fugly-args in actual-arg
- context where hollerith/typeless provided.
+ * stw.c (ffestw_display_state, ffestw_new, ffestw_pop): Add
+ prototype arguments.
- * intrin.def (FFEINTRIN_genDFLOAT): Add FFEINTRIN_specDFLOAT.
- (FFEINTRIN_specDFLOAT): Add as f2c intrinsic.
+ * stw.h (ffestw_display_state, ffestw_new, ffestw_pop): Likewise.
- * target.h (ffetarget_convert_real[12]_integer,
- ffetarget_convert_complex[12]_integer): Pass -1 for high integer
- value if low part is negative.
- (FFETARGET_defaultIS_UGLY_ARGS): New macro.
+ * version.c (ffe_version_string): Const-ify a char*.
- * top.c (ffe_is_ugly_args_): New variable.
- (ffe_decode_option): Handle -fugly-args and -fno-ugly-args.
+ * version.h (ffe_version_string): Likewise.
- * top.h (ffe_is_ugly_args_, ffe_is_ugly_args(),
- ffe_set_is_ugly_args()): New variable and macros.
+Sat Mar 27 13:00:43 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Thu Feb 23 02:48:38 1995 Pedro A M Vazquez (vazquez@iqm.unicamp.br)
+ * bad.c (_ffebad_message_, ffebad_string_, ffebad_message_,
+ ffebad_bufputs_, ffebad_bufputs_, ffebad_start_, ffebad_string,
+ ffebad_finish): Const-ify a char*.
- * g77.c (sys_errlist): Use const for __FreeBSD__ systems
- as well.
+ * bld.c (ffebld_op_string_, ffebld_op_string): Likewise.
-Wed Feb 22 13:33:43 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * bld.h (ffebld_op_string): Likewise.
- * Version 0.5.10 released.
+ * com.c (ffecom_arglist_expr_, ffecom_build_f2c_string_,
+ ffecom_debug_kludge_, ffecom_f2c_make_type_,
+ ffecom_get_appended_identifier_, ffecom_get_identifier_,
+ ffecom_gfrt_args_): Likewise.
+ (ffecom_convert_narrow_, ffecom_convert_widen_): Add prototype.
+ (builtin_function, ffecom_gfrt_name_, ffecom_gfrt_argstring_,
+ ffecom_arglist_expr_, ffecom_build_f2c_string_,
+ ffecom_debug_kludge_, ffecom_f2c_make_type_,
+ ffecom_get_appended_identifier_, ffecom_get_external_identifier_,
+ ffecom_get_identifier_, ffecom_decl_field,
+ ffecom_get_invented_identifier, lang_print_error_function,
+ skip_redundant_dir_prefix, read_name_map, print_containing_files):
+ Const-ify a char*.
+ (savestring): Remove, use `xstrdup' instead.
- * CREDITS: Add Rick Niles.
+ * com.h (ffecom_decl_field, ffecom_get_invented_identifier):
+ Const-ify a char*.
- * INSTALL: Note how to get around lack of makeinfo.
+ * data.c (ffebld, ffedata_gather_): Make explicitly static.
- * Make-lang.in (f/proj.h): Remove # comment.
+ * expr.c (ffeexpr_isdigits_, ffeexpr_percent_,
+ ffeexpr_reduced_concatenate_, ffeexpr_nil_real_,
+ ffeexpr_nil_number_, ffeexpr_nil_number_period_,
+ ffeexpr_nil_number_real_, ffeexpr_token_real_,
+ ffeexpr_token_number_, ffeexpr_token_number_period_,
+ ffeexpr_token_number_real_): Const-ify a char*.
- * Makefile.in (f/proj.h): Remove # comment.
+ * fini.c (xspaces): Likewise.
- * com.c (ffecom_expr_): Simplify opFUNCREF/opSUBRREF conversion.
- (ffecom_sym_transform_): For whereGLOBAL and whereDUMMY
- kindFUNCTION, use ffecom_tree_fun_type[][] only for non-constant
- (non-statement-function) f2c functions.
- (ffecom_init_0): ffecom_tree_fun_type[][] and _ptr_to_*_* are
- really f2c-interface arrays, so use base type void for COMPLEX
- (like CHARACTER).
+ * global.c (ffeglobal_type_string_): Likewise.
+ (ffeglobal_drive): Protoize.
+ (ffeglobal_proc_def_arg): Const-ify a char*.
-Tue Feb 21 19:01:18 1995 Dave Love <d.love@dl.ac.uk>
+ * global.h (ffeglobal_drive): Protoize.
+ (ffeglobal_proc_def_arg): Const-ify a char*.
- * Make-lang.in (f77.install-common): Expurgate the test for and
- possible installation of f2c in line with elsewhere. Seems to have
- been missing a semicolon anyhow!
+ * implic.c (ffeimplic_none, ffeimplic_peek_symbol_type):
+ Likewise.
-Tue Feb 21 11:45:25 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * implic.h (ffeimplic_peek_symbol_type): Likewise.
- * Version 0.5.9 released.
+ * info.c (ffeinfo_basictype_string_, ffeinfo_kind_message_,
+ ffeinfo_kind_string_, ffeinfo_kindtype_string_,
+ ffeinfo_where_string_, ffeinfo_basictype_string,
+ ffeinfo_kind_message, ffeinfo_kind_string,
+ ffeinfo_kindtype_string, ffeinfo_where_string): Likewise.
- * Make-lang.in (f/proj.h): touch file to register update,
- because the previous commands won't necessarily modify it.
+ * info.h (ffeinfo_basictype_string, ffeinfo_kind_message,
+ ffeinfo_kind_string, ffeinfo_kindtype_string,
+ ffeinfo_where_string): Likewise.
- * Makefile.in (f/proj.h): touch file to register update,
- because the previous commands won't necessarily modify it.
+ * intrin.c (_ffeintrin_name_, _ffeintrin_gen_, _ffeintrin_spec_,
+ _ffeintrin_imp_, ffeintrin_check_, ffeintrin_cmp_name_,
+ ffeintrin_fulfill_specific, ffeintrin_init_0,
+ ffeintrin_is_actualarg, ffeintrin_is_intrinsic,
+ ffeintrin_name_generic, ffeintrin_name_implementation,
+ ffeintrin_name_specific): Likewise.
- * Makefile.in (f/str-*.h, f/str-*.j): Explicitly specify
- output file names, so these targets go in build, not source,
- directory.
+ * intrin.h (ffeintrin_is_intrinsic, ffeintrin_name_generic,
+ ffeintrin_name_implementation, ffeintrin_name_specific): Likewise.
- * bits.c, bits.h: Switch to valid ANSI C replacement for
- ARRAY_ZERO.
+ * lex.c (ffelex_type_string_, ffelex_token_new_character,
+ ffelex_token_new_name, ffelex_token_new_names,
+ ffelex_token_new_number): Likewise.
- * com.c (ffecom_expr_): Add assignp arg to support ASSIGN better.
- If assignp is TRUE, use different tree for FFEBLD_opSYMTER case.
- (ffecom_sym_transform_assign_): New function.
- (ffecom_expr_assign): New function.
- (ffecom_expr_assign_w): New function.
+ * lex.h (ffelex_token_new_character, ffelex_token_new_name,
+ ffelex_token_new_names, ffelex_token_new_number): Likewise.
- * com.c (ffecom_f2c_make_type_): Do make_signed_type instead
- of make_unsigned_type throughout.
+ * malloc.c (malloc_types_, malloc_pool_new, malloc_new_inpool_,
+ malloc_new_zinpool_): Likewise.
- * com.c (ffecom_finish_symbol_transform_): Expand scope of
- commented-out code to probably produce faster compiler code.
+ * malloc.h (malloc_new_inpool_, malloc_new_zinpool_,
+ malloc_pool_new): Likewise.
- * com.c (ffecom_gen_sfuncdef_): Push/pop calltemps so
- COMPLEX works right.
- Remove obsolete comment.
+ * name.c (ffename_space_drive_global, ffename_space_drive_symbol):
+ Protoize.
- * com.c (ffecom_start_progunit_): If non-multi alt-entry
- COMPLEX function, primary (static) entry point returns result
- directory, not via extra arg -- to agree with ffecom_return_expr
- and others.
- Pretransform all symbols so statement functions are defined
- before any code emitted.
+ * name.h (ffename_space_drive_global, ffename_space_drive_symbol):
+ Likewise.
- * com.c (ffecom_finish_progunit): Don't posttransform all
- symbols here -- pretransform them instead.
+ * symbol.c (ffesymbol_state_name_, ffesymbol_attr_name_,
+ ffesymbol_attrs_string): Const-ify a char*.
+ (ffesymbol_drive, ffesymbol_drive_sfnames): Protoize.
+ (ffesymbol_state_string): Const-ify a char*.
- * com.c (ffecom_init_0): Don't warn about possible ASSIGN
- crash, as this shouldn't happen now.
+ * symbol.h (ffesymbol_attrs_string): Likewise.
+ (ffesymbol_drive, ffesymbol_drive_sfnames): Protoize.
+ (ffesymbol_state_string): Const-ify a char*.
- * com.c (ffecom_push_tempvar): Fix to handle temp vars
- pushed while context is a statement (nested) function, and
- add appropriate commentary.
+ * target.c (ffetarget_layout): Likewise.
- * com.c (ffecom_return_expr): Check TREE_USED to determine
- where return value is unset.
+ * target.h (ffetarget_layout): Likewise.
- * com.h (struct _ffecom_symbol_): Add note about length_tree
- now being used to keep tree for ASSIGN version of symbol.
+1999-03-25 Zack Weinberg <zack@rabi.columbia.edu>
- * com.h (ffecom_expr_assign, ffecom_expr_assign_rw): New decls.
- (error): Add this prototype for back-end function.
+ * Make-lang.in: Remove all references to g77.o/g77.c.
+ Link g77 from gcc.o.
- * fini.c (main): Grab input, output, and include names
- directly off the command line instead of making the latter
- two out of the first.
+1999-03-21 Manfred Hollstein <manfred@s-direktnet.de>
- * lex.c: Improve tab handling for both fixed and free source
- forms, and ignore carriage-returns on input, while generally
- improving the code. ffelex_handle_tab_ has been renamed and
- reinvented as ffelex_image_char_, among other things.
+ * Makefile.in (g77$(exeext)): Depend on intl.o. Link in intl.o.
- * malloc.c, malloc.h: Switch to valid ANSI C replacement for
- ARRAY_ZERO, and kill the full number of bytes in pools and
- areas.
+Wed Mar 17 11:39:44 1999 Craig Burley <craig@jcb-sc.com>
- * proj.h.in (ARRAY_ZERO, ARRAY_ZERO_SIZE): Remove.
+ * news.texi: Editorial fix.
- * ste.c (ffeste_io_cilist_, ffeste_io_icilist_, ffeste_R838,
- ffeste_R839): Issue diagnostic if a too-narrow variable used in an
- ASSIGN context despite changes to this code and code in com.c.
+Mon Mar 15 17:12:07 1999 Craig Burley <craig@jcb-sc.com>
- * where.c, where.h: Switch to valid ANSI C replacement for
- ARRAY_ZERO.
+ * bugs.texi, g77.texi, news.texi: Editorial fixes.
-Fri Feb 17 03:35:19 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Sat Mar 13 17:51:55 1999 Craig Burley <craig@jcb-sc.com>
- * Version 0.5.8 released.
+ Fix 19990313-0.f, 19990313-1.f, 19990313-2.f, 19990313-3.f:
+ * bad.def (FFEBAD_NOCANDO): New error code for internal use only.
+ * expr.c (ffeexpr_collapse_convert): If FFEBAD_NOCANDO returned
+ by convertor, just return original expr.
+ * target.h: Return FFEBAD_NOCANDO for (usually) 64-bit
+ conversions that aren't yet working properly.
+ * news.texi: Explain.
- * INSTALL: In quick-build case, list g77 target first so g77
- gets installed. Also, explain that gcc gets built and installed
- as well, even though this isn't really what we want (and maybe
- we'll find a way around this someday).
+ * version.c: Bump version.
-Fri Feb 17 02:35:41 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Sat Mar 13 14:26:55 1999 Craig Burley <craig@jcb-sc.com>
+
+ * RELEASE-PREP: New file, lists things to do for a release.
+
+ * Make-lang.in, bugs.texi, bugs0.texi, g77.texi, g77install.texi,
+ install0.texi, news.texi, news0.texi: Accommodate new doc
+ architecture.
+ Consolidate news items. Don't describe old news items in
+ various generated docs.
+ Don't describe FSF-g77 installation stuff in various EGCS-g77
+ generated docs.
+ Move description of AUTOMATIC to more suitable location.
+ * root.texi: New file for new doc architecture.
+
+Thu Mar 11 17:32:55 1999 Craig Burley <craig@jcb-sc.com>
+
+ * g77.texi: Add AUTOMATIC to list of unsupported extensions.
+
+Sat Mar 6 02:28:35 1999 Craig Burley <craig@jcb-sc.com>
+
+ Warn about non-Y2K-compliant intrinsics:
+ * bad.def (FFEBAD_INTRINSIC_Y2KBAD): New diagnostic.
+ * intrin.def (FFEINTRIN_impDATE, FFEINTRIN_impIDATE_vxt):
+ Use new DEFIMPY macro to flag these as non-Y2K-compliant.
+ * intdoc.c (DEFIMPY): Support new Y2K macro.
+ * intrin.h (DEFIMPY): Ditto.
+ * intrin.c (DEFIMPY): Ditto.
+ (ffeintrin_fulfill_generic, ffeintrin_fulfill_specific):
+ Warn about invocation of non-Y2K-compliant intrinsic.
+ * com-rt.def (FFECOM_gfrtDATE, FFECOM_gfrtVXTIDATE):
+ Rename external procedure names, to keep previously-
+ compiled (sans-new-warnings) code from linking to
+ new library.
+ * g77.texi: Document all this stuff.
+ * news.texi: Spread the joy.
+ * version.c: Bump version.
- * Version 0.5.7 released.
+Fri Mar 5 13:22:44 1999 Craig Burley <craig@jcb-sc.com>
- * Makefile.in (CONFIG_H, HCONFIG_H, TCONFIG_H, TM_H): Remove
- ../ prefix in front of .h files, since they're in the cd.
+ * news.texi: Relocate IDATE (VXT) fix: we put it in 1.1.2
+ so describe it there, instead of under 1.2.
-Fri Feb 17 01:50:48 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Wed Mar 3 00:57:56 1999 Craig Burley <craig@jcb-sc.com>
- * Version 0.5.6 released.
+ * news.texi: IDATE (VXT) fixed to return year as 0..99.
-Thu Feb 16 20:26:54 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Wed Mar 3 00:43:49 1999 Craig Burley <craig@jcb-sc.com>
- * ../README.g77: Remove description of g77 as "not-yet-published".
+ * g77.texi: Add remaining changes pending from Dave Love.
- * CREDITS: More changes.
+Wed Mar 3 00:38:42 1999 Craig Burley <craig@jcb-sc.com>
- * Make-lang.in (G77STAGESTUFF): Remove cktyps stuff.
+ * bugs.texi, news.texi: Conditionalize cross-references
+ on non-html processing, providing temporary HTML "links".
- * Makefile.in (CONFIG_H, HCONFIG_H, TCONFIG_H, TM_H): Don't
- prefix gcc dir with $(srcdir) since these don't live there,
- they are created in the build dir by gcc's configure. Add
- a note explaining what these macros are about.
- Update dependencies via deps-kinda.
+ * g77.texi: Fix up a reference.
- * README.NEXTSTEP: Credit Toon, and per his request, add his
- email address.
+Wed Mar 3 00:12:31 1999 Craig Burley <craig@jcb-sc.com>
- * com.h (FFECOM_DETERMINE_TYPES): #include "config.j".
+ * news.texi, bugs.texi: Delete fixed bugs, make one
+ of them into the appropriate news item.
- * config.j, convert.j, flags.j, hconfig.j, rtl.j, tconfig.j,
- tm.j, tree.j: Don't #include if already done.
+Wed Mar 3 00:05:52 1999 Craig Burley <craig@jcb-sc.com>
- * convert.j: #include "tree.j" first, as convert.h clearly depends
- on trees being defined.
+ * news.texi: Copy over 1.1.2 news.
- * rtl.j: #include "config.j" first, since there's some stuff
- in rtl.h that assumes it has been #included.
+1999-03-02 Craig Burley <craig@jcb-sc.com>
- * tree.j: #include "config.j" first, or real.h makes inconsistent
- decision about return type of ereal_atof, leading to bugs, and
- because tree.h/real.h assume config.h already included.
+ * g77.texi (Bug Reporting): Clarify whether to use -E.
+ Clarify other instructions.
-Wed Feb 15 14:40:20 1995 Craig Burley (burley@gnu.ai.mit.edu)
+1999-02-27 Craig Burley <craig@jcb-sc.com>
- * Version 0.5.5 released.
+ * lang-specs.h: Fix specs to pass `-ax' as well as `-a' option.
- * Copyright notices updated to be FSF-style.
+1999-02-26 Craig Burley <craig@jcb-sc.com>
- * INSTALL: Some more clarification regarding building just f77.
+ * intdoc.in (STAT_func, STAT_subr,
+ FSTAT_func, FSTAT_subr, LSTAT_func, LSTAT_subr):
+ Properly order array elements. Specify N/A return values.
- * Make-lang.in (F77_SRCS): Update wrt changing some .h to .j.
- (install-libf77): Fix typo in new parenthetical note.
+1999-02-26 Craig Burley <craig@jcb-sc.com>
- * Makefile.in (f/*.o): Update.
- (CONFIG_H, CONVERT_H, FLAGS_H, GLIMITS_H, HCONFIG_H, RTL_H,
- TCONFIG_H, TM_H, TREE_H): Update/new symbols.
- (deps-kinda): More fixes wrt changing some .h to .j.
- Document and explain this rule a bit better.
- Accommodate changes in output of gcc -MM.
+ * intdoc.in (DATE_AND_TIME): Explain that VALUES(7) holds
+ seconds, and VALUES(8), therefore, milliseconds.
- * *.h, *.c: Change #include's so proj.h not assumed to #include
- malloc.h or config.h (now config.j), and so new .j files are
- used instead of old .h ones.
+1999-02-26 Craig Burley <craig@jcb-sc.com>
- * com.c (ffecom_init_0): Use FLOAT_TYPE_SIZE for f2c's
- TYLONG/TYLOGICAL type codes, to get g77 working on Alpha.
+ * news.texi: Clarify IOSTAT= fix.
- * com.h: Make all f2c-related integral types "int", not "long
- int".
+1999-02-25 Richard Henderson <rth@cygnus.com>
- * config.j, convert.j, flags.j, glimits.j, hconfig.j, rtl.j,
- tconfig.j, tm.j, tree.j: New files wrapping around gbe
- .h files.
+ * lang-specs.h: Define __FAST_MATH__ when appropriate.
- * config.h, convert.h, flags.h, glimits.h, hconfig.h, rtl.h,
- tconfig.h, tm.h, tree.h: Deleted so new .j files
- can #include the gbe files directly, instead of using "../",
- and thus do better with various kinds of builds.
+1999-02-25 Craig Burley <craig@jcb-sc.com>
- * proj.h: Delete unused NO_STDDEF and related stuff.
+ * g77.texi: Clarify/index lack of run-time allocation for
+ concatenation.
+
+1999-02-25 Andreas Jaeger <aj@arthur.rhein-neckar.de>
-Tue Feb 14 08:28:08 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * f/intdoc.in: Add missing `,' after cross references.
- * BUGS: Remove item #12, cross-compiling & autoconf scripts
- reportedly expected to work properly (according to d.love).
+1999-02-20 Craig Burley <craig@jcb-sc.com>
- * INSTALL: Add explanation of d.love's patch to config-lang.in.
- Add explanation of how to install just g77 when gcc already installed.
- Add note about usability of "-Wall". Add note about bug-
- reporting.
+ * Make-lang.in (f77.install-common, f77.install-info,
+ f77.install-man, f77.uninstall): Use `$(prefix)/lang-f77'
+ instead of `lang-f77' for flag file, to be sure of a
+ writable directory, and remove the flag file after each
+ operation to keep things clean.
- * Make-lang.in ($(srcdir)/f/conf-proj): Add comment about why
- conf-proj.out.
- (install-libf77): Echo parenthetical note to user about how to do
- just the (aborted) libf2c installation.
- (deps-kinda): Update to work with new configuration/build stuff.
+1999-02-20 Craig Burley <craig@jcb-sc.com>
- * bad.c (ffebad_finish): Put capitalized "warning:" &c message
- as prefix on any diagnostic without pointers into source.
+ * g77.texi: Properly attribute Priest document; clarify
+ that it is in the .ps version of the Goldberg document.
- * bad.def (FFEBAD_TOO_BIG_INIT): Add this warning message.
+1999-02-19 Craig Burley <craig@jcb-sc.com>
- * config-lang.in: Add Dave Love's patch to catch case where
- back-end patches not applied and abort configuration.
+ * bugs0.texi, bugs.texi, install0.texi, g77install.texi,
+ news0.texi, news.texi: Update copyright dates.
+ Clarify which files are source, which are derived,
+ and remind maintainers where copyright dates are sourced.
+ * BUGS, INSTALL, NEWS: Regenerated.
- * data.c (ffedata_gather_, ffedata_value_): Warn when about
- to initialize a large aggregate area, due to design flaw resulting
- in too much time/space used to handle such cases.
- Use COMMON area name, and first notice of symbol, for multiple-
- initialization diagnostic, instead of member symbol and unknown
- location.
- (FFEDATA_sizeTOO_BIG_INIT_): New macro per above.
+1999-02-19 Craig Burley <craig@jcb-sc.com>
-Mon Feb 13 13:54:26 1995 Dave Love <d.love@dl.ac.uk>
+ * global.c (ffeglobal_ref_progunit_): Warn about a function
+ definition that disagrees with the type of a previous reference.
+ Improve commentary. Fix a couple of minor bugs. Clean up
+ some code.
+ * news.texi: Spread the joy.
- * Make-lang.in (F77_SRCS): Use $(srcdir)/f/proj.h.in, not
- $(srcdir)/f/proj.h for build outside srcdir.
+1999-02-18 Craig Burley <craig@jcb-sc.com>
-Sun Feb 12 13:37:11 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * expr.c (ffeexpr_finished_): Disallow non-default INTEGER
+ as argument for FILEINT and FILEASSOC as lhs.
+ * news.texi: Document fix.
+ * version.c: Bump.
- * ../README.g77: Clarify procedures for unpacking, add asterisks
- to mark important things the user must do.
+1999-02-18 Craig Burley <craig@jcb-sc.com>
- * Fix dates in/add dates to ../README.g77, BUGS, CREDITS, DOC,
- INSTALL, PROJECTS, README.
+ * g77.texi: Clarify -fno-globals vs. -Wno-globals.
-Sun Feb 12 00:26:10 1995 Craig Burley (burley@gnu.ai.mit.edu)
+1999-02-18 Craig Burley <craig@jcb-sc.com>
- * Version 0.5.4 released.
+ * intdoc.in (LOG10): Fix typo.
- * Make-lang.in (f/proj.h): Reproduce this rule here from
- Makefile.in.
- ($(srcdir)/f/conf-proj): Put autoconf's stdout in temp file
- conf-proj.out, then mv to conf-proj only if successful, so
- conf-proj not touched if autoconf not installed.
+1999-02-17 Ulrich Drepper <drepper@cygnus.com>
- * Makefile.in ($(srcdir)/conf-proj): See Make-lang.in's similar
- rule.
+ * intdoc.in: Fix typo.
-Sat Feb 11 20:56:02 1995 Craig Burley (burley@gnu.ai.mit.edu)
+1999-02-17 Craig Burley <craig@jcb-sc.com>
- * BUGS: Clarify some bugs.
+ * g77.texi, intdoc.in: Document Y2K and some other known
+ limitations.
+ * intrin.def (DTIME, FDATE): Fix capitalization of
+ case-sensitive forms of these intrinsics' names.
- * DOC: Many improvements and fixes.
+1999-02-17 Dave Love <fx@gnu.org>
- * README: Move bulk of text, edited, to ../README.g77, and
- replace with pointer to that file.
+ * intdoc.in: Say `common' logarithm for log10.
- * com.c (ffecom_init_0): Comment out warning about sizeof(ftnlen)
- as per ste.c change. Add text about ASSIGN to help user understand
- what is being warned about.
+1999-02-16 Ulrich Drepper <drepper@cygnus.com>
- * conf-proj.in: Fix typos in comments.
+ * g77.texi: Add missing @ in email addresses.
- * proj.h.in: Add ARRAY_ZERO_SIZE to parallel malloc.h's version,
- in case it proves to be needed.
+1999-02-15 Craig Burley <craig@jcb-sc.com>
- * ste.c: Comment out assertions requiring sizeof(ftnlen) >=
- sizeof(char *), in the hopes that overflow will never happen.
- (ffeste_R838): Change assertion to fatal() with at least
- partially helpful message.
+ * *.*: Delete my (old) email address in most places, change it
+ in a few.
-Sat Feb 11 12:38:00 1995 Craig Burley (burley@gnu.ai.mit.edu)
+1999-02-14 Craig Burley <craig@jcb-sc.com>
- * com.c (ffecom_vardesc_): Crash if typecode is -1.
+ * version.c: Bump.
- * ste.c (ffeste_io_dolio_): Crash if typecode is -1.
+1999-02-14 Craig Burley <craig@jcb-sc.com>
-Sat Feb 11 09:51:57 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * version.c: Bump for 1998-10-02 change (forgot to do this
+ before).
- * ste.c: In I/O code tests for item arrayness, sort of revert
- to much earlier code that tests original exp, but also check
- in newer way just in case. Newer way alone treated FOO(1:40)
- as an array, not sure why older way alone didn't work, but I
- think maybe it was when diagnosed code was involved, and
- since there are now checks for error_mark_node, maybe the old
- way alone would work. But better to be safe; both original
- ffebld exp _and_ the transformed tree must indicate an array
- for the size-determination code to be used, else just 1/2 elements
- assumed. And this text is for EMACS: (foo at bar).
+1999-02-14 Craig Burley <craig@jcb-sc.com>
-Fri Feb 10 11:05:50 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * lang-specs.h, g77.1, g77.texi, news.texi: Recognize `.FOR'
+ and `.FPP' as well as `.for' and `.fpp'.
- * ste.c: In many cases, surround statement-expansion code
- with ffecom_push_calltemps () and ffecom_pop_calltemps ()
- so COMPLEX-returning functions can have temporaries pushed
- in "auto-pop" mode and have them auto-popped at the end of
- the statement.
+1999-02-14 Craig Burley <craig@jcb-sc.com>
-Wed Feb 8 14:35:10 1995 Dave Love <d.love@dl.ac.uk>
+ * intdoc.in (LOG10): Fix description.
- * runtime/f2c.h.in (ftnlen, ftnint): Make same size as integer.
+1999-02-14 Craig Burley <craig@jcb-sc.com>
- * runtime/libI77/err.c (f_init): Thinko in MISSING_FILE_ELEMS
- conditional.
- * runtime/libI77/wrtfmt.c (mv_cur): Likewise.
- * runtime/libI77/wsfe.c (x_putc): Likewise.
+ * news.texi: Mention fix for SIGNAL invocation circa egcs-1.1.
- * runtime/libF77/signal_.c (signal_): Return 0 (this is a
- subroutine).
+1999-02-14 Craig Burley <craig@jcb-sc.com>
- * Makefile.in (f/proj.h): Depend on com.h.
- * Make-lang.in (include/f2c.h): Likewise (and proj.h).
- (install-libf77): Also install f2c.h.
+ * g77.texi, g77install.texi, bugs.texi, g77install.texi: Clean
+ up and improve indexing, and some other areas of docs.
- * runtime/libI77/Makefile.in (*.o): Add f2c.h dependency.
- * runtime/libF77/Makefile.in: Likewise.
+1999-02-14 Craig Burley <craig@jcb-sc.com>
-Wed Feb 8 13:56:47 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * intdoc.in (MCLOCK8, TIME8): Warn about lower range on
+ 32-bit systems.
- * stc.c (ffestc_R501_item): Don't reset kind/where to NONE when
- setting basictype/kindtype info for symbol, or especially
- its function/result twin, because kind/where might not be NONE.
+Sat Feb 6 18:02:17 1999 Jeffrey A Law (law@cygnus.com)
-Tue Feb 7 14:47:26 1995 Dave Love <d.love@dl.ac.uk>
+ * g77.texi: Update email addresses.
- * Make-lang.in (include/f2c.h:): Set shell variable src more
- robustly (independent of whether srcdir is relative or absolute).
- * Makefile.in (f/proj.h:): Likewise.
+Wed Feb 3 22:50:17 1999 Marc Espie <Marc.Espie@liafa.jussieu.fr>
- * conf-proj.in: Check need for LAME_ASSERT. Fix indentation in
- check for LAME_STDIO (cosmetic only with ANSI C).
+ * Make-lang.in (g77$(exeext)): Get choose-temp.o, pexecute.o and
+ mkstemp.o from libiberty.
- * com.h: Extra ...SIZE stuff taken from com.c.
+1999-02-01 Zack Weinberg <zack@rabi.columbia.edu>
- * com.c (FFECOM_DETERMINE_TYPES): Define before including com.h.
- (BITS_PER_WORD etc.) Remove and use conditional definitions to com.h.
+ * top.c: Don't define ffe_is_ident_. Don't process
+ -f(no-)ident here.
+ * top.h: Remove declaration of ffe_is_ident_ and macros
+ ffe_is_ident() and ffe_set_is_ident().
+ * lex.c: Use flag_no_ident instead of ffe_is_ident().
- * runtime/configure.in: #define FFECOM_DETERMINE_TYPES for com.h in
- f2c type determination.
+Sun Jan 31 20:34:29 1999 Zack Weinberg <zack@rabi.columbia.edu>
- * tm.h: Remove (at least pro tem) because of relative path and use
- top-level one.
+ * lang-specs.h: Map -Qn to -fno-ident.
- * Make-lang.in (include/f2c.h:): Set shell variable src more
- robustly (independent of whether srcdir is relative or absolute).
- * Makefile.in (f/proj.h:): Likewise.
+Tue Jan 5 22:12:41 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Mon Feb 6 19:58:32 1995 Dave Love <d.love@dl.ac.uk>
+ * Make-lang.in (g77.o): Depend on prefix.h.
- * g77.c (append_arg): Use K&R declaration for, e.g. SunOS4 build.
+Fri Nov 27 13:10:32 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-Fri Feb 3 20:33:14 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * fini.c: Rename variable `spaces' to `xspaces' to avoid
+ conflicting with function `spaces' from libiberty.
- * g77.c (main): Treat -l like filename in terms of -x handling.
- Rewrite arglist mechanism for ease of maintenance.
- Make sure every -lf2c is followed by -lm and vice versa.
+ * g77spec.c: Don't prototype libiberty functions.
+ * malloc.c: Likewise.
- * Make-lang.in: Put complete list of sources in F77_SRCS def
- so changing a .h file, for example, causes rebuild.
+1998-11-20 Dave Love <d.love@dl.ac.uk>
- * Makefile.in: Change test for nextstep to m68k-next-nextstep* so
- all versions of nextstep on m68k get the necessary flag.
+ * g77.texi: Assorted minor changes.
-Fri Feb 3 19:10:32 1995 Dave Love <d.love@dl.ac.uk>
+1998-11-19 Dave Love <d.love@dl.ac.uk>
- * INSTALL: Note about possible conflict with existing libf2c.a and
- f2c.h.
+ * bugs.texi: Formatting changes from Craig.
- * Make-lang.in (f77.distclean): Tidy and move deletion of
- f/config.cache to mostlyclean.
- (install-libf77): Test for $(libdir)/libf2c.* and barf if found
- unless F2CLIBOK defined.
+ * intdoc.in: Terminate some @xrefs with `,'.
- * runtime/Makefile.in (all): Change path to include directory (and
- elsewhere).
- (INCLUDES): Remove (unused/misleading).
- (distclean): Include f2c.h.
- (clean): Include config.cache.
+1998-11-19 Manfred Hollstein <manfred@s-direktnet.de>
- * runtime/libF77/Makefile.in (.SUFFIXES): Correct typo.
- (ALL_CFLAGS) Fix up include search path to find f2c.h in top level
- includes always.
- (all): Depend on f2c.h.
- * runtime/libI77/Makefile.in (.SUFFIXES): Likewise.
+ * Make-lang.in (mandir): Replace all uses of $(mandir) by $(man1dir).
-Thu Feb 2 17:17:06 1995 Dave Love <d.love@dl.ac.uk>
+Mon Nov 9 23:15:39 1998 Jeffrey A Law (law@cygnus.com)
- * INSTALL: Note about --srcdir and GNU make.
+ * g77.texi, news.texi: Updates from Craig.
- * runtime/f2c.h.in (Pad_UDread, ALWAYS_FLUSH): Reomve the #defines
- per below.
+Sun Nov 8 17:47:56 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * runtime/configure.in (Pad_UDread, ALWAYS_FLUSH): Define these
- here, not in f2c.h as they'r eonly relevant for building.
- * runtime/configure: Regenerated.
+ * Makefile.in (INCLUDES): Add "-I$(srcdir)/../../include".
- * config-lang.in: Warn about using GNU make outside source tree
- since I can't get Irix5 or SunOS4 makes to work in this case.
+Sat Nov 7 15:58:54 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * Makefile.in (VPATH): Don't set it here.
- (srcdir): Make it the normal `.' (overridden) at top level.
- (all.indirect): New dependency `dircheck'.
- (f771): Likewise
- (dircheck): New target for foolproofing.
- (f/proj.h:): Change finding source.
- (CONFIG_H): Don't use this as the relative path in the include loses
- f builddir != srcdir.
+ * g77spec.c: Don't include gansidecl.h.
+ * output.j: Likewise.
- * config.h: Remove per CONFIG_H change above.
+1998-11-04 Dave Love <d.love@dl.ac.uk>
- * Make-lang.in (F77_FLAGS_TO_PASS): Remove GCC_FOR_TARGET.
- (f771:): Pass VPATH, srcdir to sub-make.
- (f/Makefile:): New target.
- (stmp-int-hdrs): new variable for cheating build.
- (f77-runtime:): Alter GCC_FOR_TARGET treatment.
- (include/f2c.h f/runtime/Makefile:) Likewise.
- (f77-runtime-unsafe:): New (cheating) target.
+ * g77.texi: Small formatting/indexing fixes.
-Thu Feb 2 12:09:51 1995 Craig Burley (burley@gnu.ai.mit.edu)
+Mon Oct 12 20:41:59 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * BUGS: Update regarding losing EQUIVALENCE members in -g, and
- regarding RS/6000 problems in the back end.
+ * bad.c (ffebad_finish): Change type of variable `c' to unsigned
+ char, change type of variable `s' to unsigned char *.
- * CREDITS: Make some changes as requested.
+ * com.c (ffecom_symbol_null_): Add missing initializers.
- * com.c (ffecom_member_trunk_): Remove unused static variable.
- (ffecom_finish_symbol_transform_): Improve comments.
- (ffecom_let_char_): Fix size of temp address-type var.
- (ffecom_member_phase2_): Try fixing problem fixed by change
- to ffecom_transform_equiv_ (f_m_p2_ function currently not used).
- (ffecom_transform_equiv_): Remove def of unused static variable.
- Comment-out use of ffecom_member_phase2_, until problems with
- back end fixed.
- (ffecom_push_tempvar): Fix assertion to not crash okay code.
+ * fini.c (MAXNAMELEN): Undef it before defining.
- * com.h: Remove old, commented-out code.
- Add prototype for warning() in back end.
+ * implic.c (ffeimplic_lookup_): Change type of parameter `c' to
+ unsigned char.
- * ste.c (ffeste_io_dofio_, ffeste_io_dolio_, ffeste_io_douio_,
- ffeste_io_icilist_): Check correct type of variable for arrayness.
+ * intrin.c (ffeintrin_init_0): Cast the argument of ctype macros
+ to (unsigned char).
-Sun Jan 29 14:41:42 1995 Dave Love <d.love@dl.ac.uk>
+ * lex.c (ffelex_splice_tokens): Change type of variable `p' to
+ unsigned char *.
+ (ffelex_token_name_from_names): Cast the argument of
+ `ffelex_is_firstnamechar' to (unsigned char).
+ (ffelex_token_names_from_names): Likewise.
+ (ffelex_token_new_name): Likewise.
+ (ffelex_token_new_names): Likewise.
- * BUGS: Remove references to my configure bugs; add another.
+ * malloc.c (malloc_root_): Add missing initializer.
- * runtime/Makefile.in (AR_FLAGS): Provide default value.
+ * stb.c (ffestb_do): Change type of variable `p' to unsigned char *.
+ (ffestb_else) Likewise.
+ (ffestb_else3_) Likewise.
+ (ffestb_endxyz) Likewise.
+ (ffestb_goto) Likewise.
+ (ffestb_let) Likewise.
+ (ffestb_varlist) Likewise.
+ (ffestb_R522) Likewise.
+ (ffestb_R528) Likewise.
+ (ffestb_R834) Likewise.
+ (ffestb_R835) Likewise.
+ (ffestb_R838) Likewise.
+ (ffestb_R1102) Likewise.
+ (ffestb_blockdata) Likewise.
+ (ffestb_R1212) Likewise.
+ (ffestb_R810) Likewise.
+ (ffestb_R10014_): Cast the argument of `ffelex_is_firstnamechar'
+ to (unsigned char).
+ (ffestb_V014): Change type of variable `p' to unsigned char *.
+ (ffestb_dummy) Likewise.
+ (ffestb_R524) Likewise.
+ (ffestb_R547) Likewise.
+ (ffestb_decl_chartype) Likewise.
+ (ffestb_decl_dbltype) Likewise.
+ (ffestb_decl_gentype) Likewise.
+ (ffestb_decl_entsp_2_) Likewise.
+ (ffestb_V027) Likewise.
+ (ffestb_decl_R539) Likewise.
- * runtime/f2c.h.in (integer, logical): Take typedefs from
- F2C_INTEGER configuration parameter again.
- (NON_UNIX_STDIO): don't define it.
+ * top.c (ffe_decode_option): Mark parameter `argc' with
+ ATTRIBUTE_UNUSED.
- * runtime/configure.in: Bring type checks for f2c.h in line with
- com.h.
- (MISSING_FILE_ELEMS): New variable to determine whether the relevant
- elements of the FILE struct exist, independent of NON_UNIX_STDIO.
- * runtime/libI77/{err,wrtfmt,wsfe}.c (MISSING_FILE_ELEMS): Use new
- parameter.
+ * where.c (ffewhere_unknown_line_): Add missing initializers.
- * config-lang.in: Comment out more of f2c rules (c.f. Make-lang.in).
- (This stuff is relevant iff you gave configure --enable-f2c.)
- Create f/runtime directory tree iff not building in source
- directory.
+1998-10-02 Dave Love <d.love@dl.ac.uk>
- * Makefile.in (srcdir): Append slash so we get the right value when
- not building in the source directory. This is a consequence of not
- building the `f' sources in `f'.
- (VPATH): Override configure's value for reasons above.
- (f/proj.h f/conf-proj): New rules to build proj.h by
- autoconfiguration.
+ * com.c (ffecom_expr_intrinsic_): Fix return type for RAND.
- * proj.h: Rename to proj.h.in for autoconfiguration.
- * proj.h.in: New as above.
- * conf-proj conf-proj.in: New files for autoconfiguration.
+Thu Oct 1 10:43:45 1998 Nick Clifton <nickc@cygnus.com>
- * Make-lang.in (include/f2c.h f/runtime/Makefile:): Change the order
- of setting the sh variables so that the right GCC_FOR_TARGET is
- used.
- (f77.*clean:) Add products of new configuration files and make sure
- all the *clean targets do something (unlike the ones in
- cp/Make-lange.in).
+ * lex.c: Replace occurances of HANDLE_SYSV_PRAGMA with
+ HANDLE_GENERIC_PRAGMAS.
- * com.h (FFECOM_f2cINTEGER, FFECOM_f2cLOGICAL): Define as long or
- int appropriately to ensure sizeof(real) == sizeof(integer).
+Mon Sep 28 04:22:00 1998 Jeffrey A Law (law@cygnus.com)
- * PROJECTS: Library section.
+ * news.texi: Update from Craig.
- * runtime/libI77/endfile.c: Don't #include sys/types.h conditional
- on NON_UNIX_STDIO since rawio.h needs size_t.
- * runtime/libI77/uio.c: #include <sys/types.h> for size_t if not
- KR_headers.
+1998-09-23 Dave Love <d.love@dl.ac.uk>
-Wed Jan 25 03:31:51 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * g77.texi: Additions about `/*', trailing comments and cpp.
- * Version 0.5.3 released.
+1998-09-18 Dave Love <d.love@dl.ac.uk>
- * INSTALL: Revise.
+ * g77.texi: Various additions and some small fixes.
- * Make-lang.in: Comment out rules for building f2c itself (f/f2c/).
+Thu Sep 10 14:55:44 1998 Kamil Iskra <iskra@student.uci.agh.edu.pl>
- * README: Revise.
+ * Make-lang.in (f77.install-common): Add missing "else true;".
- * com.c (ffecom_init_0): Warn if ftnlen or INTEGER not big enough
- to hold a char *.
+1998-09-07 Dave Love <d.love@dl.ac.uk>
- * gbe/2.6.2.diff: Update.
+ * ChangeLog.egcs: Deleted. Entries merged here.
-Mon Jan 23 17:10:49 1995 Craig Burley (burley@gnu.ai.mit.edu)
+1998-09-05 Dave Love <d.love@dl.ac.uk>
- * TODO: Remove.
- BUGS: New file.
- PROJECTS: New file.
- CREDITS: New file.
+ * Makefile.in (LDFLAGS): Set from BOOT_LDFLAGS.
+ (F771_LDFLAGS): Variable dispensed with.
- * cktyps*: Remove.
- Make-lang.in: Remove cktyps stuff.
- Makefile.in: Remove cktyps stuff.
+Fri Sep 4 19:53:34 1998 Craig Burley <burley@gnu.org>
- * DOC: Add info on changes for 0.5.3.
+ * intdoc.in: Minor editorial tweaks.
- * bad.c: Put "warning:" &c on diagnostic messages.
- Don't output informational messages if warnings disabled.
+Fri Sep 4 18:35:52 1998 Craig Burley <burley@gnu.org>
-Thu Jan 19 12:38:13 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * lang-options.h: Convert to wrap option and doc string
+ in a new macro invocation, FTNOPT, so the nearly identical
+ list can be used in FSF-g77.
- * g77.c: Avoid putting out useless "-xnone -xf77" pairs so
- larger command lines can be accommodated.
- Recognize both `-xlang' and `-x lang'.
- Recognize `-xnone' and `-x none' to mean what it does, instead
- of treating "none" as any other language.
- Some minor, slight improvements in the way args are handled
- (hopefully for clearer, more maintainable code), including
- consistency checks on arg count just in case.
+Fri Sep 4 18:35:52 1998 Craig Burley <burley@gnu.org>
-Wed Jan 18 16:41:57 1995 Craig Burley (burley@gnu.ai.mit.edu)
+ * Makefile.in (fini.o): Don't define USE_HCONFIG here.
+ * fini.c: Define USE_HCONFIG here instead, so deps-kinda
+ picks up correct dependency.
- * DOC: Explain -fautomatic better.
+ * Makefile.in (proj-h.o): Fix dependencies list.
- * INSTALL: Describe libf2c.a better.
+Wed Sep 02 09:25:29 1998 Nick Clifton <nickc@cygnus.com>
- * Make-lang.in, Makefile.in: Build f771 &c with gcc/ as cd instead
- of gcc/f/ so debugging info is better (source file tracking).
- Add new source file type.c.
+ * lex.c (ffe_lex_hash): Change how HANDLE_PRAGMA and
+ HANDLE_SYSV_PRAGMA would be called if they pragma parsing was
+ enabled in this code.
+ Generate warning messages if unknown pragmas are encountered.
+ (pragma_getc): New function: retrieves characters from the
+ input stream. Defined when HANDLE_PRAGMA is defined.
+ (pragma_ungetc): New function: replaces characters back into the
+ input stream. Defined when HANDLE_PRAGMA is defined.
- * Makefile.in: For nextstep3, link f771 with -segaddr __DATA
- 6000000. Fix typo. Change deps-kinda target to handle building
- from gcc/. Update dependencies.
+Tue Sep 1 10:00:21 1998 Craig Burley <burley@gnu.org>
- * bld-op.def, bld.h, bld.c: Remove opBACKEND and all related
- stuff.
- Remove consistency tests that cause compiler warnings.
+ * bugs.texi, g77.1, g77.texi, intdoc.in, news.texi: Doc updates
+ from Craig.
- * cktyps.c: Remove all typing checking.
+1998-08-23 Dave Love <d.love@dl.ac.uk>
- * com-rt.def: Change all rttypeFLOAT_ intrinsics to rttypeDOUBLE_,
- to precisely match how they're declared in libf2c.
+ * g77.texi: Increment `version-g77' and fix a few typos.
- * com.h, com.c: Revise to more elegantly track related stuff
- in the version of f2c.h used to build libf2c.
+Tue Aug 18 21:41:31 1998 Jeffrey A Law (law@cygnus.com)
- * com.c: Increase FFECOM_sizeMAXSTACKITEM, and if 0 or undefined
- when checked to determine where to put entity, treat as infinite.
- Rewrite temporary mechanism to be based on trees instead of
- ffeinfo stuff, and make it much simpler. Change interface
- accordingly.
- Fixes to better track types of things, make appropriate
- conversions, etc. E.g. when making an arg for a libf2c
- function, make sure it's of the right type (such as ftnlen).
- Delete opBACKEND transformation code.
- (ffecom_init_0): Smoother initialization of types, especially
- paying attention to using consistent rules for making INTEGER,
- REAL, DOUBLE PRECISION, etc., and for deciding their "*N"
- and kind values that will work across all g77 platforms.
- No longer require per-target configuration info in target.h
- or config/*/*; use new type module to store size, alignment.
- (ffecom_member_phase2): Declare COMMON/EQUIVALENCE group members
- so debugger sees them.
- (ffecom_finish_progunit): Transform all symbols in program unit,
- so -g will show they all exist.
+ * Make-lang.in: Add several "else true" clauses to deal with lame
+ systems.
- * expr.c (ffeexpr_collapse_substr): Handle strange substring
- range values.
+Tue Aug 11 08:12:14 1998 H.J. Lu (hjl@gnu.org)
- * info.h, info.c: Provide connection to new type module.
- Remove tests that yield compiler warnings.
+ * Make-lang.in (g77.o): Touch lang-f77 before checking it.
- * intrin.c (ffeintrin_is_intrinsic): Properly handle deleted
- intrinsic.
+1998-08-09 Dave Love <d.love@dl.ac.uk>
- * lex.c (ffelex_file_fixed): Remove redundant/buggy code.
+ * Make-lang.in (f/g77.dvi): Replace non-working use of texi2dvi
+ with explicit use of tex.
+ (f77.mostlyclean): Remove TeX index files.
- * stc.c (ffestc_kindtype_kind_, ffestc_kindtype_star_): Replace
- boring switch stmt with simple call to new type module. This
- sort of thing is a reason to get up in the morning.
+ * g77install.texi (Prerequisites): Kluge round TeX lossage with
+ hyphen in @value in @code.
- * ste.c: Update to handle new interface for
- ffecom_push/pop_tempvar.
- Fixes to better track types of things.
- Fixes to not crash for certain diagnosed constructs.
- (ffeste_begin_iterdo_): Check only constants for overflow to avoid
- spurious diagnostics.
- Don't convert larger integer (say, INTEGER*8) to canonical integer
- for iteration count.
+Tue Aug 4 16:59:39 1998 Craig Burley <burley@gnu.org>
- * stw.h: Track DO iteration count temporary variable.
+ * com.c (ffecom_convert_narrow_, ffecom_convert_widen_):
+ Allow conversion from pointer to same-sized integer,
+ to fix invoking SIGNAL as a function.
- * symbol.c: Remove consistency tests that cause compiler warnings.
+1998-07-26 Dave Love <d.love@dl.ac.uk>
- * target.c (ffetarget_aggregate_info): Replace big switch with
- little call to new type module.
- (ffetarget_layout): Remove consistency tests that cause
- compiler warnings.
- (ffetarget_convert_character1_typeless): Pick up length of
- typeless type from new type module.
+ * BUGS, INSTALL, NEWS: Rebuilt.
- * target.h: Crash build if target float bit pattern cannot be
- precisely determined.
- Remove all the type cruft now determined by ffecom_init_0
- at invocation time and maintained in new type module.
- Put casts on second arg of all REAL_VALUE_TO_TARGET_DOUBLE
- uses so compiler warnings avoided (requires target float bit
- pattern to be precisely determined, hence code to crash build).
+Sat Jul 25 17:23:55 1998 Craig Burley <burley@gnu.org>
- * top.c: Add inits/terminates for new type module.
+ Fix 980615-0.f:
+ * stc.c (ffestc_R1229_start): Set info to ANY as well.
- * type.h, type.c: New module.
+Tue Jul 21 04:33:37 1998 Craig Burley <burley@gnu.org>
- * gbe/2.6.2.diff: Remove all patches to files in gcc/config/
- directory and its subdirectories.
+ * g77spec.c (lang_specific_driver): Return unmolested
+ command line when --help seen.
+ Comment out code that printed g77-specific --help info.
-Mon Jan 9 19:23:25 1995 Dave Love <d.love@dl.ac.uk>
+Sat Jul 18 19:16:48 1998 Craig Burley <burley@gnu.org>
- * com.h (FFECOM_F2C_INTEGER_TYPE_NODE): Define and use instead of
- long_integer_type_node where appropriate.
+ * lang-options.h: Fix up doc strings.
+ Remove the unimplemented -fdcp-intrinsics-* options.
-Tue Jan 3 14:56:18 1995 Dave Love <d.love@dl.ac.uk>
+ * str-1t.fin: Change mixed-case spelling of `GoTo' from
+ `Goto'.
- * com.h: Make ffecom_f2c_logical_type_node long, consistent with
- integer.
+Thu Jul 16 13:26:36 1998 Craig Burley <burley@gnu.org>
-Fri Dec 2 20:07:37 1994 Dave Love <d.love@dl.ac.uk>
+ * com.c (ffecom_finish_symbol_transform_): Revert change
+ of 1998-05-23, as it was too aggressive, in that it
+ prevented transformation of (used) functions before
+ primary code generation.
- * config-lang.in (stagestuff): Add f2c conditionally.
- * Make-lang.in: Add f2c and related targets.
- * f2c: Add the directory.
+1998-07-15 Dave Love <d.love@dl.ac.uk>
-Fri Nov 25 22:17:26 1994 Dave Love <d.love@dl.ac.uk>
+ * intdoc.texi: Regenerated.
- * Makefile.in (FLAGS_TO_PASS): pass $(CROSS)
- * Make-lang.in: more changes to runtime targets
+Mon Jul 13 18:45:06 1998 Craig Burley <burley@gnu.org>
-Thu Nov 24 18:03:21 1994 Dave Love <d.love@dl.ac.uk>
+ * Make-lang.in (f77.rebuilt): Fix to depend on
+ build-dir-based, not source-based, g77.info.
- * Makefile.in (FLAGS_TO_PASS): define for sub-makes
+ * g77.texi: Merge docs with 0.5.24.
+ * g77install.texi: Ditto.
- * g77.c (main): change f77-cpp-output to f77-cpp-input (.F files)
+Mon Jul 13 18:02:29 1998 Craig Burley <burley@gnu.org>
-Wed Nov 23 15:22:53 1994 Dave Love <d.love@dl.ac.uk>
+ Cleanups vis-a-vis g77-0.5.24:
+ * g77spec.c (lang_specific_driver): Tabify source.
+ * top.c (ffe_decode_option): Use fixed macro to set
+ internal-checking flag.
+ * top.h (ffe_set_is_do_internal_checks): Fix macro.
- * bad.c (ffebad_finish): kluge to fool emacs19 into finding errors:
- add trailing space to <file>:<line>:
+Mon Jul 13 17:33:44 1998 Craig Burley <burley@gnu.org>
-Tue Nov 22 11:30:50 1994 Dave Love <d.love@dl.ac.uk>
+ Cleanups vis-a-vis system.h cutover and g77-0.5.24:
+ * Makefile.in (fini.o): Define USE_HCONFIG macro
+ so source code doesn't have to.
+ * fini.c: Don't define USE_HCONFIG here, since
+ source code usually shouldn't care about this.
+ * ansify.c: Include stddef.h only if we have it.
+ * intdoc.c: Ditto.
+ * proj.h: Ditto.
- * runtime/libF77/signal_.c (RETSIGTYPE): added
+Mon Jul 13 17:30:29 1998 Nick Clifton <nickc@cygnus.com>
-Mon Nov 21 13:04:13 1994 Dave Love <d.love@dl.ac.uk>
+ * lang-options.h: Format changed to work with --help support added
+ to gcc/toplev.c
- * Makefile.in (compiler): add runtime
+Mon Jul 13 11:54:03 1998 Craig Burley <burley@gnu.org>
- * config-lang.in (stagestuff): add libf2c.a to stagestuff
+ * com.c (ffecom_push_tempvar): Replace kludge that
+ munged back-end globals directly with proper calls
+ to push_topmost_sequence and pop_topmost_sequence.
- * Make-lang.in:
- G77STAGESTUFF <- MORESTAGESTUFF
- f77-runtime: new target, plus supporting ones
+1998-07-12 Dave Love <d.love@dl.ac.uk>
- * runtime: add the directory, containing libI77, libF77 and autoconf
- stuff
+ * version.c: Bump version.
- * g++.1: remove
+Sat Jul 11 19:24:32 1998 Craig Burley <burley@gnu.org>
- * g77.1: minor fixes
+ Fix 980616-0.f:
+ * equiv.c (ffeequiv_offset_): Don't crash on various
+ possible ANY operands.
-Thu Nov 17 15:18:05 1994 Craig Burley (burley@gnu.ai.mit.edu)
+Sat Jul 11 18:24:37 1998 Craig Burley <burley@gnu.org>
- * Version 0.5.2 released.
+ * com.c (ffecom_expr_) [FFEBLD_opCONTER]: Die if padding
+ for constant is non-zero.
- * bad.def: Modify wording of FFEBAD_UNIMPL_STMT to indicate
- that it covers a wide array of possible problems (that, someday,
- should be handled via separate diagnostics).
+ * com.c (__eprintf): Delete this function, it is obsolete.
- * lex.c: Allow $ in identifiers if -fdollar-ok.
- * top.c: Support -fdollar-ok.
- * top.h: Support -fdollar-ok.
- * target.h: Support -fdollar-ok.
- * DOC: Describe -fdollar-ok.
+1998-07-09 Dave Love <d.love@dl.ac.uk>
- * std.c (ffestd_R1229_finish): Fix bug so stand-alone build works.
- * ste.c (ffeste_R819A): Fix bug so stand-alone build works.
+ * intdoc.in (HOSTNM_func, HOSTNM_subr): Update last change.
- * Make: Improvements for stand-alone build.
+Thu Jul 9 00:45:59 1998 Craig Burley <burley@gnu.org>
- * Makefile.in: Fix copyright text at top of file.
+ Fix debugging of CHARACTER*(*), etc., which requires
+ emitting debug info on types like `ftnlen':
+ * com.c (ffecom_start_progunit_): Don't bother
+ resetting "invented" flag for identifier.
+ (ffecom_transform_equiv_): Don't bother zeroing
+ "ignored" flag for decl.
+ (pushdecl): No longer set "ignored", "used", or
+ "suppressed debug" flags for decls having "invented"
+ identifiers.
- * LINK, SRCS, UNLINK: Removed. Not particularly useful now that
- g77 sources live in their own subdirectory.
+1998-07-06 Mike Stump <mrs@wrs.com>
- * g77.c (main): Cast arg to bzero to avoid warning. (This is
- identical to Kenner's fix to cp/g++.c.)
+ * Make-lang.in (f77.stage?): Use mv -f instead of just mv so that
+ we can move g77.c.
- * gbe/: New subdirectory, to contain .diff files for various
- versions of the GNU CC back end.
+1998-07-06 Dave Love <d.love@dl.ac.uk>
- * gbe/README: New file.
- * gbe/2.6.2.diff: New file.
+ * intdoc.in (HOSTNM_func, HOSTNM_subr): Note possible need for
+ -lsocket.
-Tue Nov 8 10:23:10 1994 Dave Love <d.love@dl.ac.uk>
+1998-07-05 Dave Love <d.love@dl.ac.uk>
- * Make-lang.in: don't install as f77 as well as g77 to avoid
- confusion with system's compiler (especially while testing)
+ * intdoc.in: Add entry for DATE_AND_TIME.
- * g77.c (main): use -lf2c and -lm; fix sense of test for .f/.F files
+ * intrin.def: Add implementation for DATE_AND_TIME. Make second
+ and third args of SYSTEM_CLOCK optional.
-Fri Oct 28 09:45:00 1994 Craig Burley (burley@gnu.ai.mit.edu)
+ * com.c (ffecom_expr_intrinsic_): New case for DATE_AND_TIME.
- * Version 0.5.1 released.
+ * com-rt.def (FFECOM_gfrtSYSTEM_CLOCK): Call G77_system_clock_0,
+ not system_clock_.
+ (FFECOM_gfrtDATE_AND_TIME): New DEFGFRT.
- * gcc.c: Invoke f771 instead of f-771.
+Wed Jul 1 11:19:13 1998 Craig Burley <burley@gnu.org>
-Fri Oct 28 02:00:44 1994 Craig Burley (burley@gnu.ai.mit.edu)
+ Fix 980701-1.f (which was producing "unaligned trap"
+ on an Alpha running GNU/Linux, as predicted):
+ * equiv.c (ffeequiv_layout_local_): Don't bother
+ coping with pre-padding of entire area while building
+ it; do that instead after the building is done, and
+ do it by modifying only the modulo field. This covers
+ the case of alignment stringency being increased without
+ lowering the starting offset, unlike the previous changes,
+ and even more elegantly than those.
- * Version 0.5.0 released.
+ * target.c (ffetarget_align): Make sure alignments
+ are non-zero, just in case.
-Fri Oct 14 15:03:35 1994 Craig Burley (burley@gnu.ai.mit.edu)
+See ChangeLog.0 for earlier changes.
- * Makefile.in: Handle the Fortran-77 front-end in a subdirectory.
- * f-*: Move Fortran-77 front-end to f/*.
+Local Variables:
+add-log-time-format: current-time-string
+End:
diff --git a/contrib/gcc/f/INSTALL b/contrib/gcc/f/INSTALL
new file mode 100644
index 0000000..9185880
--- /dev/null
+++ b/contrib/gcc/f/INSTALL
@@ -0,0 +1,352 @@
+*Note:* This file is automatically generated from the files
+`install0.texi' and `g77install.texi'. `INSTALL' is *not* a source
+file, although it is normally included within source distributions.
+
+ This file contains installation information for the GNU Fortran
+compiler. Copyright (C) {No Value For "copyrights-install"} Free
+Software Foundation, Inc. You may copy, distribute, and modify it
+freely as long as you preserve this copyright notice and permission
+notice.
+
+Installing GNU Fortran
+**********************
+
+ The following information describes how to install `g77'.
+
+ Note that, for users of the GCC-2.95 version of `g77', much of the
+information is obsolete, and is superceded by the GCC installation
+procedures. Such information is accordingly omitted and flagged as
+such.
+
+ *Warning:* The information below is still under development, and
+might not accurately reflect the `g77' code base of which it is a part.
+Efforts are made to keep it somewhat up-to-date, but they are
+particularly concentrated on any version of this information that is
+distributed as part of a *released* `g77'.
+
+ In particular, while this information is intended to apply to the
+GCC-2.95 version of `g77', only an official *release* of that version
+is expected to contain documentation that is most consistent with the
+`g77' product in that version.
+
+ The following information was last updated on 1999-07-17:
+
+Prerequisites
+=============
+
+ For users of the GCC-2.95 version of `g77', this information is
+superceded by the GCC installation instructions.
+
+Problems Installing
+===================
+
+ This is a list of problems (and some apparent problems which don't
+really mean anything is wrong) that show up when configuring, building,
+installing, or porting GNU Fortran.
+
+ *Note Installation Problems: (gcc)Installation Problems, for more
+information on installation problems that can afflict either `gcc' or
+`g77'.
+
+General Problems
+----------------
+
+ These problems can occur on most or all systems.
+
+GNU C Required
+..............
+
+ Compiling `g77' requires GNU C, not just ANSI C. Fixing this
+wouldn't be very hard (just tedious), but the code using GNU extensions
+to the C language is expected to be rewritten for 0.6 anyway, so there
+are no plans for an interim fix.
+
+ This requirement does not mean you must already have `gcc' installed
+to build `g77'. As long as you have a working C compiler, you can use a
+"bootstrap" build to automate the process of first building `gcc' using
+the working C compiler you have, then building `g77' and rebuilding
+`gcc' using that just-built `gcc', and so on.
+
+Patching GNU CC
+...............
+
+ `g77' no longer requires application of a patch file to the `gcc'
+compiler tree. In fact, no such patch file is distributed with `g77'.
+This is as of version 0.5.23 and `egcs' version 1.0.
+
+Building GNU CC Necessary
+.........................
+
+ It should be possible to build the runtime without building `cc1'
+and other non-Fortran items, but, for now, an easy way to do that is
+not yet established.
+
+Missing strtoul or bsearch
+..........................
+
+ This information does not apply to the GCC-2.95 version of `g77',
+
+Cleanup Kills Stage Directories
+...............................
+
+ It'd be helpful if `g77''s `Makefile.in' or `Make-lang.in' would
+create the various `stageN' directories and their subdirectories, so
+developers and expert installers wouldn't have to reconfigure after
+cleaning up.
+
+ That help has arrived as of version 0.5.23 of `g77' and version 1.1
+of `egcs'. Configuration itself no longer creates any particular
+directories that are unique to `g77'. The build procedures in
+`Make-lang.in' take care of that, on demand.
+
+LANGUAGES Macro Ignored
+.......................
+
+ Prior to version 0.5.23 of `g77' and version 1.1 of `egcs', `g77'
+would sometimes ignore the absence of `f77' and `F77' in the
+`LANGUAGES' macro definition used for the `make' command being
+processed.
+
+ As of `g77' version 0.5.23 and `egcs' version 1.1, `g77' now obeys
+this macro in all relevant situations.
+
+ However, in versions of `gcc' through 2.8.1, non-`g77' portions of
+`gcc', such as `g++', are known to go ahead and perform various
+language-specific activities when their respective language strings do
+not appear in the `LANGUAGES' macro in effect during that invocation of
+`make'.
+
+ It is expected that these remaining problems will be fixed in a
+future version of `gcc'.
+
+System-specific Problems
+------------------------
+
+ A linker bug on some versions of AIX 4.1 might prevent building when
+`g77' is built within `gcc'. It might also occur when building within
+`egcs'.
+
+Cross-compiler Problems
+-----------------------
+
+ `g77' has been in alpha testing since September of 1992, and in
+public beta testing since February of 1995. Alpha testing was done by
+a small number of people worldwide on a fairly wide variety of
+machines, involving self-compilation in most or all cases. Beta
+testing has been done primarily via self-compilation, but in more and
+more cases, cross-compilation (and "criss-cross compilation", where a
+version of a compiler is built on one machine to run on a second and
+generate code that runs on a third) has been tried and has succeeded,
+to varying extents.
+
+ Generally, `g77' can be ported to any configuration to which `gcc',
+`f2c', and `libf2c' can be ported and made to work together, aside from
+the known problems described in this manual. If you want to port `g77'
+to a particular configuration, you should first make sure `gcc' and
+`libf2c' can be ported to that configuration before focusing on `g77',
+because `g77' is so dependent on them.
+
+ Even for cases where `gcc' and `libf2c' work, you might run into
+problems with cross-compilation on certain machines, for several
+reasons.
+
+ * There is one known bug (a design bug to be fixed in 0.6) that
+ prevents configuration of `g77' as a cross-compiler in some cases,
+ though there are assumptions made during configuration that
+ probably make doing non-self-hosting builds a hassle, requiring
+ manual intervention.
+
+ * `gcc' might still have some trouble being configured for certain
+ combinations of machines. For example, it might not know how to
+ handle floating-point constants.
+
+ * Improvements to the way `libg2c' is built could make building
+ `g77' as a cross-compiler easier--for example, passing and using
+ `$(LD)' and `$(AR)' in the appropriate ways. (This is improved in
+ the `egcs' version of `g77', especially as of version 1.1.)
+
+ * There are still some challenges putting together the right
+ run-time libraries (needed by `libg2c') for a target system,
+ depending on the systems involved in the configuration. (This is
+ a general problem with cross-compilation, and with `gcc' in
+ particular.)
+
+Changing Settings Before Building
+=================================
+
+ Here are some internal `g77' settings that can be changed by editing
+source files in `egcs/gcc/f/' before building.
+
+ This information, and perhaps even these settings, represent
+stop-gap solutions to problems people doing various ports of `g77' have
+encountered. As such, none of the following information is expected to
+be pertinent in future versions of `g77'.
+
+Larger File Unit Numbers
+------------------------
+
+ As distributed, whether as part of `f2c' or `g77', `libf2c' accepts
+file unit numbers only in the range 0 through 99. For example, a
+statement such as `WRITE (UNIT=100)' causes a run-time crash in
+`libf2c', because the unit number, 100, is out of range.
+
+ If you know that Fortran programs at your installation require the
+use of unit numbers higher than 99, you can change the value of the
+`MXUNIT' macro, which represents the maximum unit number, to an
+appropriately higher value.
+
+ To do this, edit the file `egcs/libf2c/libI77/fio.h' in your `g77'
+source tree, changing the following line:
+
+ #define MXUNIT 100
+
+ Change the line so that the value of `MXUNIT' is defined to be at
+least one *greater* than the maximum unit number used by the Fortran
+programs on your system.
+
+ (For example, a program that does `WRITE (UNIT=255)' would require
+`MXUNIT' set to at least 256 to avoid crashing.)
+
+ Then build or rebuild `g77' as appropriate.
+
+ *Note:* Changing this macro has *no* effect on other limits your
+system might place on the number of files open at the same time. That
+is, the macro might allow a program to do `WRITE (UNIT=100)', but the
+library and operating system underlying `libf2c' might disallow it if
+many other files have already been opened (via `OPEN' or implicitly via
+`READ', `WRITE', and so on). Information on how to increase these
+other limits should be found in your system's documentation.
+
+Always Flush Output
+-------------------
+
+ Some Fortran programs require output (writes) to be flushed to the
+operating system (under UNIX, via the `fflush()' library call) so that
+errors, such as disk full, are immediately flagged via the relevant
+`ERR=' and `IOSTAT=' mechanism, instead of such errors being flagged
+later as subsequent writes occur, forcing the previously written data
+to disk, or when the file is closed.
+
+ Essentially, the difference can be viewed as synchronous error
+reporting (immediate flagging of errors during writes) versus
+asynchronous, or, more precisely, buffered error reporting (detection
+of errors might be delayed).
+
+ `libg2c' supports flagging write errors immediately when it is built
+with the `ALWAYS_FLUSH' macro defined. This results in a `libg2c' that
+runs slower, sometimes quite a bit slower, under certain
+circumstances--for example, accessing files via the networked file
+system NFS--but the effect can be more reliable, robust file I/O.
+
+ If you know that Fortran programs requiring this level of precision
+of error reporting are to be compiled using the version of `g77' you
+are building, you might wish to modify the `g77' source tree so that
+the version of `libg2c' is built with the `ALWAYS_FLUSH' macro defined,
+enabling this behavior.
+
+ To do this, find this line in `egcs/libf2c/f2c.h' in your `g77'
+source tree:
+
+ /* #define ALWAYS_FLUSH */
+
+ Remove the leading `/* ', so the line begins with `#define', and the
+trailing ` */'.
+
+ Then build or rebuild `g77' as appropriate.
+
+Maximum Stackable Size
+----------------------
+
+ `g77', on most machines, puts many variables and arrays on the stack
+where possible, and can be configured (by changing
+`FFECOM_sizeMAXSTACKITEM' in `egcs/gcc/f/com.c') to force smaller-sized
+entities into static storage (saving on stack space) or permit
+larger-sized entities to be put on the stack (which can improve
+run-time performance, as it presents more opportunities for the GBE to
+optimize the generated code).
+
+ *Note:* Putting more variables and arrays on the stack might cause
+problems due to system-dependent limits on stack size. Also, the value
+of `FFECOM_sizeMAXSTACKITEM' has no effect on automatic variables and
+arrays. *Note But-bugs::, for more information.
+
+Floating-point Bit Patterns
+---------------------------
+
+ The `g77' build will crash if an attempt is made to build it as a
+cross-compiler for a target when `g77' cannot reliably determine the
+bit pattern of floating-point constants for the target. Planned
+improvements for version 0.6 of `g77' will give it the capabilities it
+needs to not have to crash the build but rather generate correct code
+for the target. (Currently, `g77' would generate bad code under such
+circumstances if it didn't crash during the build, e.g. when compiling
+a source file that does something like `EQUIVALENCE (I,R)' and `DATA
+R/9.43578/'.)
+
+Initialization of Large Aggregate Areas
+---------------------------------------
+
+ A warning message is issued when `g77' sees code that provides
+initial values (e.g. via `DATA') to an aggregate area (`COMMON' or
+`EQUIVALENCE', or even a large enough array or `CHARACTER' variable)
+that is large enough to increase `g77''s compile time by roughly a
+factor of 10.
+
+ This size currently is quite small, since `g77' currently has a
+known bug requiring too much memory and time to handle such cases. In
+`egcs/gcc/f/data.c', the macro `FFEDATA_sizeTOO_BIG_INIT_' is defined
+to the minimum size for the warning to appear. The size is specified
+in storage units, which can be bytes, words, or whatever, on a
+case-by-case basis.
+
+ After changing this macro definition, you must (of course) rebuild
+and reinstall `g77' for the change to take effect.
+
+ Note that, as of version 0.5.18, improvements have reduced the scope
+of the problem for *sparse* initialization of large arrays, especially
+those with large, contiguous uninitialized areas. However, the warning
+is issued at a point prior to when `g77' knows whether the
+initialization is sparse, and delaying the warning could mean it is
+produced too late to be helpful.
+
+ Therefore, the macro definition should not be adjusted to reflect
+sparse cases. Instead, adjust it to generate the warning when densely
+initialized arrays begin to cause responses noticeably slower than
+linear performance would suggest.
+
+Alpha Problems Fixed
+--------------------
+
+ `g77' used to warn when it was used to compile Fortran code for a
+target configuration that is not basically a 32-bit machine (such as an
+Alpha, which is a 64-bit machine, especially if it has a 64-bit
+operating system running on it). That was because `g77' was known to
+not work properly on such configurations.
+
+ As of version 0.5.20, `g77' is believed to work well enough on such
+systems. So, the warning is no longer needed or provided.
+
+ However, support for 64-bit systems, especially in areas such as
+cross-compilation and handling of intrinsics, is still incomplete. The
+symptoms are believed to be compile-time diagnostics rather than the
+generation of bad code. It is hoped that version 0.6 will completely
+support 64-bit systems.
+
+Quick Start
+===========
+
+ For users of the GCC-2.95 version of `g77', this information is
+superceded by the GCC installation instructions.
+
+Complete Installation
+=====================
+
+ For users of the GCC-2.95 version of `g77', this information is
+superceded by the GCC installation instructions.
+
+Distributing Binaries
+=====================
+
+ For users of the GCC-2.95 version of `g77', this information is
+superceded by the GCC installation instructions.
+
diff --git a/contrib/gcc/f/Make-lang.in b/contrib/gcc/f/Make-lang.in
index 38712fd..a531abb 100644
--- a/contrib/gcc/f/Make-lang.in
+++ b/contrib/gcc/f/Make-lang.in
@@ -59,16 +59,6 @@ F77 f77: f771$(exeext)
f77.extraclean f77.maintainer-clean f77.distdir f77.rebuilt \
f77.stage1 f77.stage2 f77.stage3 f77.stage4
-g77.c: $(srcdir)/gcc.c
- case "$(LANGUAGES)" in \
- *[fF]77*) touch lang-f77;; \
- *) rm -f lang-f77;; \
- esac
- if [ -f lang-f77 ]; then \
- rm -f g77.c; \
- $(LN_S) $(srcdir)/gcc.c g77.c; \
- else true; fi
-
g77spec.o: $(srcdir)/f/g77spec.c $(srcdir)/f/version.h
case "$(LANGUAGES)" in \
*[fF]77*) touch lang-f77;; \
@@ -88,26 +78,12 @@ g77version.o: $(srcdir)/f/version.c
$(srcdir)/f/version.c; \
else true; fi
-# N.B.: This is a copy of the gcc.o rule, with -DLANG_SPECIFIC_DRIVER added.
-# It'd be nice if we could find an easier way to do this---rather than have
-# to track changes to the toplevel gcc Makefile as well.
-# We depend on g77.c last, to make it obvious where it came from.
-g77.o: $(CONFIG_H) multilib.h config.status $(lang_specs_files) g77.c
- case "$(LANGUAGES)" in \
- *[fF]77*) touch lang-f77;; \
- *) rm -f lang-f77;; \
- esac
- if [ -f lang-f77 ]; then \
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(DRIVER_DEFINES) \
- -DLANG_SPECIFIC_DRIVER -c g77.c; \
- else true; fi
-
# Create the compiler driver for g77.
-g77$(exeext): g77.o g77spec.o g77version.o version.o choose-temp.o pexecute.o prefix.o mkstemp.o \
+g77$(exeext): gcc.o g77spec.o g77version.o version.o prefix.o intl.o \
$(LIBDEPS) $(EXTRA_GCC_OBJS)
if [ -f lang-f77 ]; then \
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ g77.o g77spec.o g77version.o \
- version.o choose-temp.o pexecute.o prefix.o mkstemp.o $(EXTRA_GCC_OBJS) $(LIBS); \
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o g77spec.o g77version.o \
+ version.o prefix.o intl.o $(EXTRA_GCC_OBJS) $(LIBS); \
else true; fi
# Create a version of the g77 driver which calls the cross-compiler.
@@ -227,7 +203,8 @@ F77_SRCS = \
f771$(exeext): $(P) $(F77_SRCS) $(LIBDEPS) stamp-objlist
touch lang-f77
cd f; $(MAKE) $(FLAGS_TO_PASS) \
- HOST_CC="$(HOST_CC)" HOST_CFLAGS="$(HOST_CFLAGS)" HOST_CPPFLAGS="$(HOST_CPPFLAGS)" \
+ HOST_CC="`case '$(HOST_CC)' in stage*) echo '$(HOST_CC)' | sed -e 's|stage|../stage|g';; *) echo '$(HOST_CC)';; esac`" \
+ HOST_CFLAGS="$(HOST_CFLAGS)" HOST_CPPFLAGS="$(HOST_CPPFLAGS)" \
../f771$(exeext)
#
@@ -243,8 +220,9 @@ f77.dvi: f/g77.dvi
# g77 documentation.
f/g77.info: $(srcdir)/f/g77.texi $(srcdir)/f/bugs.texi \
+ $(srcdir)/f/ffe.texi \
$(srcdir)/f/g77install.texi $(srcdir)/f/news.texi \
- $(srcdir)/f/intdoc.texi
+ $(srcdir)/f/intdoc.texi $(srcdir)/f/root.texi
case "$(LANGUAGES)" in \
*[fF]77*) touch lang-f77;; \
*) rm -f lang-f77;; \
@@ -255,8 +233,9 @@ f/g77.info: $(srcdir)/f/g77.texi $(srcdir)/f/bugs.texi \
else true; fi
f/g77.dvi: $(srcdir)/f/g77.texi $(srcdir)/f/bugs.texi \
+ $(srcdir)/f/ffe.texi \
$(srcdir)/f/g77install.texi $(srcdir)/f/news.texi \
- $(srcdir)/f/intdoc.texi
+ $(srcdir)/f/intdoc.texi $(srcdir)/f/root.texi
case "$(LANGUAGES)" in \
*[fF]77*) touch lang-f77;; \
*) rm -f lang-f77;; \
@@ -306,15 +285,15 @@ $(srcdir)/f/intdoc.texi: f/intdoc.c f/intdoc.in f/ansify.c f/intrin.def f/intrin
rm f/intdoc f/ansify f/intdoc.h0; \
else true; fi
-$(srcdir)/f/BUGS: f/bugs0.texi f/bugs.texi
+$(srcdir)/f/BUGS: f/bugs0.texi f/bugs.texi f/root.texi
cd $(srcdir)/f; $(MAKEINFO) -D BUGSONLY --no-header --no-split \
--no-validate -o BUGS bugs0.texi
-$(srcdir)/f/INSTALL: f/install0.texi f/g77install.texi
+$(srcdir)/f/INSTALL: f/install0.texi f/g77install.texi f/root.texi
cd $(srcdir)/f; $(MAKEINFO) -D INSTALLONLY --no-header --no-split \
--no-validate -o INSTALL install0.texi
-$(srcdir)/f/NEWS: f/news0.texi f/news.texi
+$(srcdir)/f/NEWS: f/news0.texi f/news.texi f/root.texi
cd $(srcdir)/f; $(MAKEINFO) -D NEWSONLY --no-header --no-split \
--no-validate -o NEWS news0.texi
@@ -329,12 +308,14 @@ f77.install-normal:
# Install the driver program as $(target)-g77
# and also as either g77 (if native) or $(tooldir)/bin/g77.
-f77.install-common:
+# Make sure `installdirs' target (from gcc Makefile) has been
+# run, since we use libsubdir to store our `flag' file, lang-f77.
+f77.install-common: installdirs
case "$(LANGUAGES)" in \
- *[fF]77*) touch lang-f77;; \
- *) rm -f lang-f77;; \
+ *[fF]77*) touch $(libsubdir)/lang-f77;; \
+ *) rm -f $(libsubdir)/lang-f77;; \
esac
- -if [ -f lang-f77 -a -f f771$(exeext) ] ; then \
+ -if [ -f $(libsubdir)/lang-f77 -a -f f771$(exeext) ] ; then \
if [ -f g77-cross$(exeext) ] ; then \
rm -f $(bindir)/$(G77_CROSS_NAME)$(exeext); \
$(INSTALL_PROGRAM) g77-cross$(exeext) $(bindir)/$(G77_CROSS_NAME)$(exeext); \
@@ -354,64 +335,74 @@ f77.install-common:
echo ' f77-install-ok in the source or build directory.)'; \
echo ''; \
else true; fi
+ rm -f $(libsubdir)/lang-f77
# $(INSTALL_DATA) might be a relative pathname, so we can't cd into srcdir
# to do the install. The sed rule was copied from stmp-int-hdrs.
-f77.install-info: f77.info
+# Make sure `installdirs' target (from gcc Makefile) has been
+# run, since we use libsubdir to store our `flag' file, lang-f77.
+f77.install-info: f77.info installdirs
case "$(LANGUAGES)" in \
- *[fF]77*) touch lang-f77;; \
- *) rm -f lang-f77;; \
+ *[fF]77*) touch $(libsubdir)/lang-f77;; \
+ *) rm -f $(libsubdir)/lang-f77;; \
esac
- if [ -f lang-f77 -a -f f/g77.info ] ; then \
+ if [ -f $(libsubdir)/lang-f77 -a -f f/g77.info ] ; then \
rm -f $(infodir)/g77.info*; \
for f in f/g77.info*; do \
realfile=`echo $$f | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
$(INSTALL_DATA) $$f $(infodir)/$$realfile; \
done; \
chmod a-x $(infodir)/g77.info*; \
- fi
- @if [ -f lang-f77 -a -f $(srcdir)/f/g77.info ] ; then \
+ else true; fi
+ @if [ -f $(libsubdir)/lang-f77 -a -f $(srcdir)/f/g77.info ] ; then \
if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
echo " install-info --info-dir=$(infodir) $(infodir)/g77.info"; \
install-info --info-dir=$(infodir) $(infodir)/g77.info || : ; \
else : ; fi; \
else : ; fi
+ rm -f $(libsubdir)/lang-f77
-f77.install-man: $(srcdir)/f/g77.1
+# Make sure `installdirs' target (from gcc Makefile) has been
+# run, since we use libsubdir to store our `flag' file, lang-f77.
+f77.install-man: $(srcdir)/f/g77.1 installdirs
case "$(LANGUAGES)" in \
- *[fF]77*) touch lang-f77;; \
- *) rm -f lang-f77;; \
+ *[fF]77*) touch $(libsubdir)/lang-f77;; \
+ *) rm -f $(libsubdir)/lang-f77;; \
esac
- -if [ -f lang-f77 -a -f f771$(exeext) ] ; then \
+ -if [ -f $(libsubdir)/lang-f77 -a -f f771$(exeext) ] ; then \
if [ -f g77-cross$(exeext) ] ; then \
- rm -f $(mandir)/$(G77_CROSS_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/f/g77.1 $(mandir)/$(G77_CROSS_NAME)$(manext); \
- chmod a-x $(mandir)/$(G77_CROSS_NAME)$(manext); \
+ rm -f $(man1dir)/$(G77_CROSS_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/f/g77.1 $(man1dir)/$(G77_CROSS_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(G77_CROSS_NAME)$(manext); \
else \
- rm -f $(mandir)/$(G77_INSTALL_NAME)$(manext); \
- $(INSTALL_DATA) $(srcdir)/f/g77.1 $(mandir)/$(G77_INSTALL_NAME)$(manext); \
- chmod a-x $(mandir)/$(G77_INSTALL_NAME)$(manext); \
+ rm -f $(man1dir)/$(G77_INSTALL_NAME)$(manext); \
+ $(INSTALL_DATA) $(srcdir)/f/g77.1 $(man1dir)/$(G77_INSTALL_NAME)$(manext); \
+ chmod a-x $(man1dir)/$(G77_INSTALL_NAME)$(manext); \
fi; \
else true; fi
+ rm -f $(libsubdir)/lang-f77
-f77.uninstall:
+# Make sure `installdirs' target (from gcc Makefile) has been
+# run, since we use libsubdir to store our `flag' file, lang-f77.
+f77.uninstall: installdirs
case "$(LANGUAGES)" in \
- *[fF]77*) touch lang-f77;; \
- *) rm -f lang-f77;; \
+ *[fF]77*) touch $(libsubdir)/lang-f77;; \
+ *) rm -f $(libsubdir)/lang-f77;; \
esac
- @if [ -f lang-f77 ] ; then \
+ @if [ -f $(libsubdir)/lang-f77 ] ; then \
if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
echo " install-info --delete --info-dir=$(infodir) $(infodir)/g77.info"; \
install-info --delete --info-dir=$(infodir) $(infodir)/g77.info || : ; \
else : ; fi; \
else : ; fi
- -if [ -f lang-f77 ]; then \
+ -if [ -f $(libsubdir)/lang-f77 ]; then \
rm -rf $(bindir)/$(G77_INSTALL_NAME)$(exeext); \
rm -rf $(bindir)/$(G77_CROSS_NAME)$(exeext); \
- rm -rf $(mandir)/$(G77_INSTALL_NAME)$(manext); \
- rm -rf $(mandir)/$(G77_CROSS_NAME)$(manext); \
+ rm -rf $(man1dir)/$(G77_INSTALL_NAME)$(manext); \
+ rm -rf $(man1dir)/$(G77_CROSS_NAME)$(manext); \
rm -rf $(infodir)/g77.info*; \
fi
+ rm -f $(libsubdir)/lang-f77
#
# Clean hooks:
# A lot of the ancillary files are deleted by the main makefile.
@@ -424,7 +415,7 @@ f77.mostlyclean:
-rm -f g77.aux g77.cps g77.ky g77.toc g77.vr g77.fn g77.kys \
g77.pg g77.tp g77.vrs g77.cp g77.fns g77.log g77.pgs g77.tps
f77.clean:
- -rm -f g77.c g77.o g77spec.o g77version.o
+ -rm -f g77spec.o g77version.o
f77.distclean:
-rm -f lang-f77 f/Makefile
f77.extraclean:
@@ -435,7 +426,7 @@ f77.maintainer-clean:
# The main makefile has already created stage?/f.
G77STAGESTUFF = f/*$(objext) f/fini f/stamp-str f/str-*.h f/str-*.j \
- lang-f77 g77.c g77.o g77spec.o g77version.o
+ lang-f77 g77spec.o g77version.o
f77.stage1: stage1-start
-if [ -f lang-f77 ]; then \
diff --git a/contrib/gcc/f/Makefile.in b/contrib/gcc/f/Makefile.in
index 4f9733b..96975a5 100644
--- a/contrib/gcc/f/Makefile.in
+++ b/contrib/gcc/f/Makefile.in
@@ -134,12 +134,11 @@ ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS) -W
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
-# f771 is so big, need to tell linker on m68k-next-nextstep* to make enough
-# room for it. On AIX, linking f771 overflows the linker TOC;
-# `-bbigtoc' is appropriate for the linker on AIX 4.1 and above.
-F771_LDFLAGS = `case "${target}" in\
- m68k-next-nextstep*) echo -segaddr __DATA 6000000;;\
- *-*-aix[4-9]*) \`$(CC) --print-prog-name=ld\` -v 2>&1 | grep BFD >/dev/null || echo -Wl,-bbigtoc;; esac`
+# We should be compiling with the built compiler, for which
+# BOOT_LDFLAGS is appropriate. (Formerly we had a separate
+# F771_LDFLAGS, but the ld flags can be taken care of by the target
+# configuration files in egcs.)
+LDFLAGS=$(BOOT_LDFLAGS)
# Even if ALLOCA is set, don't use it if compiling with GCC.
@@ -155,7 +154,7 @@ LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) $(CLIB)
# Both . and srcdir are used, in that order,
# so that tm.h and config.h will be found in the compilation
# subdirectory rather than in the source directory.
-INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
+INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config -I$(srcdir)/../../include
# Always use -I$(srcdir)/config when compiling.
.c.o:
@@ -213,8 +212,7 @@ OBJDEPS = ../stamp-objlist
compiler: ../f771$(exeext)
../f771$(exeext): $(P) $(F77_OBJS) $(OBJDEPS) $(LIBDEPS)
rm -f f771$(exeext)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(F771_LDFLAGS) -o $@ \
- $(F77_OBJS) $(OBJS) $(LIBS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(F77_OBJS) $(OBJS) $(LIBS)
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
@@ -461,10 +459,11 @@ fini: fini.o proj-h.o
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o fini fini.o proj-h.o
fini.o:
- $(HOST_CC) -c -DUSE_HCONFIG $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
`echo $(srcdir)/fini.c | sed 's,^\./,,'` -o $@
-proj-h.o: proj.o
+# Like proj.o, but depends on hconfig.h instead of config.h.
+proj-h.o: proj.c proj.h $(HCONFIG_H) $(SYSTEM_H) $(ASSERT_H) $(GLIMITS_H)
$(HOST_CC) -c -DUSE_HCONFIG $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
`echo $(srcdir)/proj.c | sed 's,^\./,,'` -o $@
diff --git a/contrib/gcc/f/NEWS b/contrib/gcc/f/NEWS
index ff1bb45..b8b5243 100644
--- a/contrib/gcc/f/NEWS
+++ b/contrib/gcc/f/NEWS
@@ -1,7 +1,12 @@
-This file lists recent changes to the GNU Fortran compiler. Copyright
-(C) 1995, 1996 Free Software Foundation, Inc. You may copy,
-distribute, and modify it freely as long as you preserve this copyright
-notice and permission notice.
+*Note:* This file is automatically generated from the files
+`news0.texi' and `news.texi'. `NEWS' is *not* a source file, although
+it is normally included within source distributions.
+
+ This file lists news about the GCC-2.95 version (and some other
+versions) of the GNU Fortran compiler. Copyright (C) 1995-1999 Free
+Software Foundation, Inc. You may copy, distribute, and modify it
+freely as long as you preserve this copyright notice and permission
+notice.
News About GNU Fortran
**********************
@@ -38,16 +43,169 @@ clarify how they differ from other versions, though this can make
getting a complete picture of what a particular `egcs' version contains
somewhat more difficult.
+ *Warning:* The information below is still under development, and
+might not accurately reflect the `g77' code base of which it is a part.
+Efforts are made to keep it somewhat up-to-date, but they are
+particularly concentrated on any version of this information that is
+distributed as part of a *released* `g77'.
+
+ In particular, while this information is intended to apply to the
+GCC-2.95 version of `g77', only an official *release* of that version
+is expected to contain documentation that is most consistent with the
+`g77' product in that version.
+
+ Nevertheless, information on *previous* releases of `g77', below, is
+likely to be more up-to-date and accurate than the equivalent
+information that accompanied those releases, assuming the last-updated
+date of the information below is later than the dates of those releases.
+
+ That's due to attempts to keep this development version of news
+about previous `g77' versions up-to-date.
+
An online, "live" version of this document (derived directly from
-the up-to-date mainline version of `g77' within `egcs') is available at
-`http://egcs.cygnus.com/onlinedocs/g77_news.html'.
+the mainline, development version of `g77' within `egcs') is available
+at `http://www.gnu.org/software/gcc/onlinedocs/g77_news.html'.
+
+ The following information was last updated on 1999-07-08:
+
+In 0.5.25, `GCC' 2.95 (`EGCS' 1.2) versus `EGCS' 1.1.2:
+=======================================================
+
+ 1. `g77' no longer generates bad code for assignments, or other
+ conversions, of `REAL' or `COMPLEX' constant expressions to type
+ `INTEGER(KIND=2)' (often referred to as `INTEGER*8').
+
+ For example, `INTEGER*8 J; J = 4E10' now works as documented.
+
+ 2. `g77' no longer truncates `INTEGER(KIND=2)' (usually `INTEGER*8')
+ subscript expressions when evaluating array references on systems
+ with pointers widers than `INTEGER(KIND=1)' (such as Alphas).
+
+ 3. `g77' no longer generates bad code for an assignment to a
+ `COMPLEX' variable or array that partially overlaps one or more of
+ the sources of the same assignment (a very rare construction). It
+ now assigns through a temporary, in cases where such partial
+ overlap is deemed possible.
+
+ 4. `libg2c' (`libf2c') no longer loses track of the file being worked
+ on during a `BACKSPACE' operation.
+
+ 5. `libg2c' (`libf2c') fixes a bug whereby input to a `NAMELIST' read
+ involving a repeat count, such as `K(5)=10*3', was not properly
+ handled by `libf2c'. The first item was written to `K(5)', but
+ the remaining nine were written elsewhere (still within the array),
+ not necessarily starting at `K(6)'.
+
+ 6. Automatic arrays now seem to be working on HP-UX systems.
+
+ 7. The `Date' intrinsic now returns the correct result on big-endian
+ systems.
+
+ 8. Fix `g77' so it no longer crashes when compiling I/O statements
+ using keywords that define `INTEGER' values, such as `IOSTAT=J',
+ where J is other than default `INTEGER' (such as `INTEGER*2').
+ Instead, it issues a diagnostic.
+
+ 9. Fix `g77' so it properly handles `DATA A/RPT*VAL/', where RPT is
+ not default `INTEGER', such as `INTEGER*2', instead of producing a
+ spurious diagnostic. Also fix `DATA (A(I),I=1,N)', where `N' is
+ not default `INTEGER' to work instead of crashing `g77'.
+
+ 10. The `-ax' option is now obeyed when compiling Fortran programs.
+ (It is passed to the `f771' driver.)
+
+ * The new `-fbounds-check' option causes `g77' to compile run-time
+ bounds checks of array subscripts, as well as of substring start
+ and end points.
+
+ * `libg2c' now supports building as multilibbed library, which
+ provides better support for systems that require options such as
+ `-mieee' to work properly.
+
+ * Source file names with the suffixes `.FOR' and `.FPP' now are
+ recognized by `g77' as if they ended in `.for' and `.fpp',
+ respectively.
+
+ * The order of arguments to the *subroutine* forms of the `CTime',
+ `DTime', `ETime', and `TtyNam' intrinsics has been swapped. The
+ argument serving as the returned value for the corresponding
+ function forms now is the *second* argument, making these
+ consistent with the other subroutine forms of `libU77' intrinsics.
+
+ * `g77' now warns about a reference to an intrinsic that has an
+ interface that is not Year 2000 (Y2K) compliant. Also, `libg2c'
+ has been changed to increase the likelihood of catching references
+ to the implementations of these intrinsics using the `EXTERNAL'
+ mechanism (which would avoid the new warnings).
+
+ 11. `g77' now warns about a reference to a function when the
+ corresponding *subsequent* function program unit disagrees with
+ the reference concerning the type of the function.
+
+ * `-fno-emulate-complex' is now the default option. This should
+ result in improved performance of code that uses the `COMPLEX'
+ data type.
+
+ * The `-malign-double' option now reliably aligns *all*
+ double-precision variables and arrays on Intel x86 targets.
+
+ 12. Even without the `-malign-double' option, `g77' reliably aligns
+ local double-precision variables that are not in `EQUIVALENCE'
+ areas and not `SAVE''d.
+
+ 13. `g77' now open-codes ("inlines") division of `COMPLEX' operands
+ instead of generating a run-time call to the `libf2c' routines
+ `c_div' or `z_div', unless the `-Os' option is specified.
+
+ * `g77' no longer generates code to maintain `errno', a C-language
+ concept, when performing operations such as the `SqRt' intrinsic.
+
+ 14. `g77' developers can temporarily use the `-fflatten-arrays' option
+ to compare how the compiler handles code generation using C-like
+ constructs as compared to the Fortran-like method constructs
+ normally used.
+
+ 15. A substantial portion of the `g77' front end's code-generation
+ component was rewritten. It now generates code using facilities
+ more robustly supported by the `gcc' back end. One effect of this
+ rewrite is that some codes no longer produce a spurious "label LAB
+ used before containing binding contour" message.
+
+ * Support for the `-fugly' option has been removed.
-In 0.5.24 and `egcs' 1.1.2 (versus 0.5.23 and 1.1.1):
-=====================================================
+ 16. Improve documentation and indexing, including information on Year
+ 2000 (Y2K) compliance, and providing more information on internals
+ of the front end.
- * Fix the `IDate' Intrinsic (VXT) so the returned year is in the
- documented, non-Y2K-compliant range of 0-99, instead of being
- returned as 100 in the year 2000.
+ 17. Upgrade to `libf2c' as of 1999-05-10.
+
+In 0.5.24 versus 0.5.23:
+========================
+
+ There is no `g77' version 0.5.24 at this time, or planned. 0.5.24
+is the version number designated for bug fixes and, perhaps, some new
+features added, to 0.5.23. Version 0.5.23 requires `gcc' 2.8.1, as
+0.5.24 was planned to require.
+
+ Due to `EGCS' becoming `GCC' (which is now an acronym for "GNU
+Compiler Collection"), and `EGCS' 1.2 becoming officially designated
+`GCC' 2.95, there seems to be no need for an actual 0.5.24 release.
+
+ To reduce the confusion already resulting from use of 0.5.24 to
+designate `g77' versions within `EGCS' versions 1.0 and 1.1, as well as
+in versions of `g77' documentation and notices during that period,
+"mainline" `g77' version numbering resumes at 0.5.25 with `GCC' 2.95
+(`EGCS' 1.2), skipping over 0.5.24 as a placeholder version number.
+
+ To repeat, there is no `g77' 0.5.24, but there is now a 0.5.25.
+Please remain calm and return to your keypunch units.
+
+In `EGCS' 1.1.2 versus `EGCS' 1.1.1:
+====================================
+
+ * Fix the `IDate' intrinsic (VXT) (in `libg2c') so the returned year
+ is in the documented, non-Y2K-compliant range of 0-99, instead of
+ being returned as 100 in the year 2000.
* Fix the `Date_and_Time' intrinsic (in `libg2c') to return the
milliseconds value properly in VALUES(8).
@@ -57,8 +215,8 @@ In 0.5.24 and `egcs' 1.1.2 (versus 0.5.23 and 1.1.1):
* Improve documentation.
-In 0.5.24 and `egcs' 1.1.1 (versus 0.5.23 and 1.1):
-===================================================
+In `EGCS' 1.1.1 versus `EGCS' 1.1:
+==================================
* Fix `libg2c' so it performs an implicit `ENDFILE' operation (as
appropriate) whenever a `REWIND' is done.
@@ -79,51 +237,28 @@ In 0.5.24 and `egcs' 1.1.1 (versus 0.5.23 and 1.1):
some systems (those with shells requiring `else true' clauses on
`if' constructs for the completion code to be set properly).
-In `egcs' 1.1 (versus 0.5.24):
-==============================
-
- * Fix `g77' crash compiling code containing the construct
- `CMPLX(0.)' or similar.
-
- * Fix `g77' crash (or apparently infinite run-time) when compiling
- certain complicated expressions involving `COMPLEX' arithmetic
- (especially multiplication).
+In `EGCS' 1.1 versus `EGCS' 1.0.3:
+==================================
- * Fix a code-generation bug that afflicted Intel x86 targets when
- `-O2' was specified compiling, for example, an old version of the
- `DNRM2' routine.
-
- The x87 coprocessor stack was being mismanaged in cases involving
- assigned `GOTO' and `ASSIGN'.
-
- * Align static double-precision variables and arrays on Intel x86
- targets regardless of whether `-malign-double' is specified.
-
- Generally, this affects only local variables and arrays having the
- `SAVE' attribute or given initial values via `DATA'.
-
-In `egcs' 1.1 (versus `egcs' 1.0.3):
-====================================
-
- * Fix bugs in the `libU77' intrinsic `HostNm' that wrote one byte
+ 18. Fix bugs in the `libU77' intrinsic `HostNm' that wrote one byte
beyond the end of its `CHARACTER' argument, and in the `libU77'
intrinsics `GMTime' and `LTime' that overwrote their arguments.
- * Assumed arrays with negative bounds (such as `REAL A(-1:*)') no
+ 19. Assumed arrays with negative bounds (such as `REAL A(-1:*)') no
longer elicit spurious diagnostics from `g77', even on systems
with pointers having different sizes than integers.
This bug is not known to have existed in any recent version of
`gcc'. It was introduced in an early release of `egcs'.
- * Valid combinations of `EXTERNAL', passing that external as a dummy
+ 20. Valid combinations of `EXTERNAL', passing that external as a dummy
argument without explicitly giving it a type, and, in a subsequent
program unit, referencing that external as an external function
with a different type no longer crash `g77'.
- * `CASE DEFAULT' no longer crashes `g77'.
+ 21. `CASE DEFAULT' no longer crashes `g77'.
- * The `-Wunused' option no longer issues a spurious warning about
+ 22. The `-Wunused' option no longer issues a spurious warning about
the "master" procedure generated by `g77' for procedures
containing `ENTRY' statements.
@@ -148,25 +283,25 @@ In `egcs' 1.1 (versus `egcs' 1.0.3):
`libf2c' environment, even when `libf2c' (now `libg2c') is a
shared library.
- * `g77' no longer installs the `f77' command and `f77.1' man page in
+ 23. `g77' no longer installs the `f77' command and `f77.1' man page in
the `/usr' or `/usr/local' heirarchy, even if the `f77-install-ok'
file exists in the source or build directory. See the
installation documentation for more information.
- * `g77' no longer installs the `libf2c.a' library and `f2c.h'
+ 24. `g77' no longer installs the `libf2c.a' library and `f2c.h'
include file in the `/usr' or `/usr/local' heirarchy, even if the
`f2c-install-ok' or `f2c-exists-ok' files exist in the source or
build directory. See the installation documentation for more
information.
- * The `libf2c.a' library produced by `g77' has been renamed to
+ 25. The `libf2c.a' library produced by `g77' has been renamed to
`libg2c.a'. It is installed only in the `gcc' "private" directory
heirarchy, `gcc-lib'. This allows system administrators and users
to choose which version of the `libf2c' library from `netlib' they
wish to use on a case-by-case basis. See the installation
documentation for more information.
- * The `f2c.h' include (header) file produced by `g77' has been
+ 26. The `f2c.h' include (header) file produced by `g77' has been
renamed to `g2c.h'. It is installed only in the `gcc' "private"
directory heirarchy, `gcc-lib'. This allows system administrators
and users to choose which version of the include file from
@@ -178,11 +313,11 @@ In `egcs' 1.1 (versus `egcs' 1.0.3):
than the one built and installed as part of the same `g77' version
is picked up.
- * During the configuration and build process, `g77' creates
+ 27. During the configuration and build process, `g77' creates
subdirectories it needs only as it needs them. Other cleaning up
of the configuration and build process has been performed as well.
- * `install-info' now used to update the directory of Info
+ 28. `install-info' now used to update the directory of Info
documentation to contain an entry for `g77' (during installation).
* Some diagnostics have been changed from warnings to errors, to
@@ -191,28 +326,38 @@ In `egcs' 1.1 (versus `egcs' 1.0.3):
in the `OPEN', `INQUIRE', `READ', and `WRITE' statements, and
about truncations of various sorts of constants.
- * Improve compilation of `FORMAT' expressions so that a null byte is
+ 29. Improve compilation of `FORMAT' expressions so that a null byte is
appended to the last operand if it is a constant. This provides a
cleaner run-time diagnostic as provided by `libf2c' for statements
like `PRINT '(I1', 42'.
- * Improve documentation and indexing.
+ 30. Improve documentation and indexing.
- * The upgrade to `libf2c' as of 1998-06-18 should fix a variety of
+ 31. The upgrade to `libf2c' as of 1998-06-18 should fix a variety of
problems, including those involving some uses of the `T' format
specifier, and perhaps some build (porting) problems as well.
-In 0.5.24 and `egcs' 1.1 (versus 0.5.23):
-=========================================
+In `EGCS' 1.1 versus `g77' 0.5.23:
+==================================
+
+ 32. Fix a code-generation bug that afflicted Intel x86 targets when
+ `-O2' was specified compiling, for example, an old version of the
+ `DNRM2' routine.
+
+ The x87 coprocessor stack was being mismanaged in cases involving
+ assigned `GOTO' and `ASSIGN'.
- * `g77' no longer produces incorrect code and initial values for
+ 33. `g77' no longer produces incorrect code and initial values for
`EQUIVALENCE' and `COMMON' aggregates that, due to "unnatural"
ordering of members vis-a-vis their types, require initial padding.
- * `g77' no longer crashes when compiling code containing
+ 34. Fix `g77' crash compiling code containing the construct
+ `CMPLX(0.)' or similar.
+
+ 35. `g77' no longer crashes when compiling code containing
specification statements such as `INTEGER(KIND=7) PTR'.
- * `g77' no longer crashes when compiling code such as `J = SIGNAL(1,
+ 36. `g77' no longer crashes when compiling code such as `J = SIGNAL(1,
2)'.
* `g77' now treats `%LOC(EXPR)' and `LOC(EXPR)' as "ordinary"
@@ -223,6 +368,16 @@ In 0.5.24 and `egcs' 1.1 (versus 0.5.23):
Previously, `g77' treated these expressions as denoting special
"pointer" arguments for the purposes of filewide analysis.
+ 37. Fix `g77' crash (or apparently infinite run-time) when compiling
+ certain complicated expressions involving `COMPLEX' arithmetic
+ (especially multiplication).
+
+ * Align static double-precision variables and arrays on Intel x86
+ targets regardless of whether `-malign-double' is specified.
+
+ Generally, this affects only local variables and arrays having the
+ `SAVE' attribute or given initial values via `DATA'.
+
* The `g77' driver now ensures that `-lg2c' is specified in the link
phase prior to any occurrence of `-lm'. This prevents
accidentally linking to a routine in the SunOS4 `-lm' library when
@@ -243,1381 +398,15 @@ In 0.5.24 and `egcs' 1.1 (versus 0.5.23):
* The F90 `System_Clock' intrinsic allows the optional arguments
(except for the `Count' argument) to be omitted.
- * Upgrade to `libf2c' as of 1998-06-18.
-
- * Improve documentation and indexing.
-
-In 0.5.23 (versus 0.5.22):
-==========================
-
- * This release contains several regressions against version 0.5.22
- of `g77', due to using the "vanilla" `gcc' back end instead of
- patching it to fix a few bugs and improve performance in a few
- cases.
-
- See `egcs/gcc/f/BUGS', for information on the known bugs in this
- version, including the regressions.
-
- Features that have been dropped from this version of `g77' due to
- their being implemented via `g77'-specific patches to the `gcc'
- back end in previous releases include:
-
- - Support for `__restrict__' keyword, the options
- `-fargument-alias', `-fargument-noalias', and
- `-fargument-noalias-global', and the corresponding
- alias-analysis code.
-
- (`egcs' has the alias-analysis code, but not the
- `__restrict__' keyword. `egcs' `g77' users benefit from the
- alias-analysis code despite the lack of the `__restrict__'
- keyword, which is a C-language construct.)
-
- - Support for the GNU compiler options `-fmove-all-movables',
- `-freduce-all-givs', and `-frerun-loop-opt'.
-
- (`egcs' supports these options. `g77' users of `egcs'
- benefit from them even if they are not explicitly specified,
- because the defaults are optimized for `g77' users.)
-
- - Support for the `-W' option warning about integer division by
- zero.
-
- - The Intel x86-specific option `-malign-double' applying to
- stack-allocated data as well as statically-allocate data.
-
- Note that the `gcc/f/gbe/' subdirectory has been removed from this
- distribution as a result of `g77' no longer including patches for
- the `gcc' back end.
-
- * Fix bugs in the `libU77' intrinsic `HostNm' that wrote one byte
- beyond the end of its `CHARACTER' argument, and in the `libU77'
- intrinsics `GMTime' and `LTime' that overwrote their arguments.
-
- * Support `gcc' version 2.8, and remove support for prior versions
- of `gcc'.
-
- * Remove support for the `--driver' option, as `g77' now does all
- the driving, just like `gcc'.
-
- * `CASE DEFAULT' no longer crashes `g77'.
-
- * Valid combinations of `EXTERNAL', passing that external as a dummy
- argument without explicitly giving it a type, and, in a subsequent
- program unit, referencing that external as an external function
- with a different type no longer crash `g77'.
-
- * `g77' no longer installs the `f77' command and `f77.1' man page in
- the `/usr' or `/usr/local' heirarchy, even if the `f77-install-ok'
- file exists in the source or build directory. See the
- installation documentation for more information.
-
- * `g77' no longer installs the `libf2c.a' library and `f2c.h'
- include file in the `/usr' or `/usr/local' heirarchy, even if the
- `f2c-install-ok' or `f2c-exists-ok' files exist in the source or
- build directory. See the installation documentation for more
- information.
-
- * The `libf2c.a' library produced by `g77' has been renamed to
- `libg2c.a'. It is installed only in the `gcc' "private" directory
- heirarchy, `gcc-lib'. This allows system administrators and users
- to choose which version of the `libf2c' library from `netlib' they
- wish to use on a case-by-case basis. See the installation
- documentation for more information.
-
- * The `f2c.h' include (header) file produced by `g77' has been
- renamed to `g2c.h'. It is installed only in the `gcc' "private"
- directory heirarchy, `gcc-lib'. This allows system administrators
- and users to choose which version of the include file from
- `netlib' they wish to use on a case-by-case basis. See the
- installation documentation for more information.
-
- * The `g77' command now expects the run-time library to be named
- `libg2c.a' instead of `libf2c.a', to ensure that a version other
- than the one built and installed as part of the same `g77' version
- is picked up.
-
- * The `-Wunused' option no longer issues a spurious warning about
- the "master" procedure generated by `g77' for procedures
- containing `ENTRY' statements.
-
- * `g77''s version of `libf2c' separates out the setting of global
- state (such as command-line arguments and signal handling) from
- `main.o' into distinct, new library archive members.
-
- This should make it easier to write portable applications that
- have their own (non-Fortran) `main()' routine properly set up the
- `libf2c' environment, even when `libf2c' (now `libg2c') is a
- shared library.
-
- * During the configuration and build process, `g77' creates
- subdirectories it needs only as it needs them, thus avoiding
- unnecessary creation of, for example, `stage1/f/runtime' when
- doing a non-bootstrap build. Other cleaning up of the
- configuration and build process has been performed as well.
-
- * `install-info' now used to update the directory of Info
- documentation to contain an entry for `g77' (during installation).
-
- * Some diagnostics have been changed from warnings to errors, to
- prevent inadvertent use of the resulting, probably buggy, programs.
- These mostly include diagnostics about use of unsupported features
- in the `OPEN', `INQUIRE', `READ', and `WRITE' statements, and
- about truncations of various sorts of constants.
-
- * Improve documentation and indexing.
-
- * Upgrade to `libf2c' as of 1998-04-20.
-
- This should fix a variety of problems, including those involving
- some uses of the `T' format specifier, and perhaps some build
- (porting) problems as well.
-
-In 0.5.22 (versus 0.5.21):
-==========================
-
- * Fix code generation for iterative `DO' loops that have one or more
- references to the iteration variable, or to aliases of it, in
- their control expressions. For example, `DO 10 J=2,J' now is
- compiled correctly.
-
- * Fix a code-generation bug that afflicted Intel x86 targets when
- `-O2' was specified compiling, for example, an old version of the
- `DNRM2' routine.
-
- The x87 coprocessor stack was being mismanaged in cases involving
- assigned `GOTO' and `ASSIGN'.
-
- * Fix `DTime' intrinsic so as not to truncate results to integer
- values (on some systems).
-
- * Fix `Signal' intrinsic so it offers portable support for 64-bit
- systems (such as Digital Alphas running GNU/Linux).
-
- * Fix run-time crash involving `NAMELIST' on 64-bit machines such as
- Alphas.
-
- * Fix `g77' version of `libf2c' so it no longer produces a spurious
- `I/O recursion' diagnostic at run time when an I/O operation (such
- as `READ *,I') is interrupted in a manner that causes the program
- to be terminated via the `f_exit' routine (such as via `C-c').
-
- * Fix `g77' crash triggered by `CASE' statement with an omitted
- lower or upper bound.
-
- * Fix `g77' crash compiling references to `CPU_Time' intrinsic.
-
- * Fix `g77' crash (or apparently infinite run-time) when compiling
- certain complicated expressions involving `COMPLEX' arithmetic
- (especially multiplication).
-
- * Fix `g77' crash on statements such as `PRINT *,
- (REAL(Z(I)),I=1,2)', where `Z' is `DOUBLE COMPLEX'.
-
- * Fix a `g++' crash.
-
- * Support `FORMAT(I<EXPR>)' when EXPR is a compile-time constant
- `INTEGER' expression.
-
- * Fix `g77' `-g' option so procedures that use `ENTRY' can be
- stepped through, line by line, in `gdb'.
-
- * Fix a profiling-related bug in `gcc' back end for Intel x86
- architecture.
-
- * Allow any `REAL' argument to intrinsics `Second' and `CPU_Time'.
-
- * Allow any numeric argument to intrinsics `Int2' and `Int8'.
-
- * Use `tempnam', if available, to open scratch files (as in
- `OPEN(STATUS='SCRATCH')') so that the `TMPDIR' environment
- variable, if present, is used.
-
- * Rename the `gcc' keyword `restrict' to `__restrict__', to avoid
- rejecting valid, existing, C programs. Support for `restrict' is
- now more like support for `complex'.
-
- * Fix `-fpedantic' to not reject procedure invocations such as
- `I=J()' and `CALL FOO()'.
-
- * Fix `-fugly-comma' to affect invocations of only external
- procedures. Restore rejection of gratuitous trailing omitted
- arguments to intrinsics, as in `I=MAX(3,4,,)'.
-
- * Fix compiler so it accepts `-fgnu-intrinsics-*' and
- `-fbadu77-intrinsics-*' options.
-
- * Improve diagnostic messages from `libf2c' so it is more likely
- that the printing of the active format string is limited to the
- string, with no trailing garbage being printed.
-
- (Unlike `f2c', `g77' did not append a null byte to its compiled
- form of every format string specified via a `FORMAT' statement.
- However, `f2c' would exhibit the problem anyway for a statement
- like `PRINT '(I)garbage', 1' by printing `(I)garbage' as the
- format string.)
-
- * Improve compilation of `FORMAT' expressions so that a null byte is
- appended to the last operand if it is a constant. This provides a
- cleaner run-time diagnostic as provided by `libf2c' for statements
- like `PRINT '(I1', 42'.
-
- * Fix various crashes involving code with diagnosed errors.
-
- * Fix cross-compilation bug when configuring `libf2c'.
-
- * Improve diagnostics.
-
- * Improve documentation and indexing.
-
- * Upgrade to `libf2c' as of 1997-09-23. This fixes a formatted-I/O
- bug that afflicted 64-bit systems with 32-bit integers (such as
- Digital Alpha running GNU/Linux).
-
-In `egcs' 1.0.2 (versus `egcs' 1.0.1):
-======================================
-
- * Fix `g77' crash triggered by `CASE' statement with an omitted
- lower or upper bound.
-
- * Fix `g77' crash on statements such as `PRINT *,
- (REAL(Z(I)),I=1,2)', where `Z' is `DOUBLE COMPLEX'.
-
- * Fix `-fPIC' (such as compiling for ELF targets) on the Intel x86
- architecture target so invalid assembler code is no longer
- produced.
-
- * Fix `-fpedantic' to not reject procedure invocations such as
- `I=J()' and `CALL FOO()'.
-
- * Fix `-fugly-comma' to affect invocations of only external
- procedures. Restore rejection of gratuitous trailing omitted
- arguments to intrinsics, as in `I=MAX(3,4,,)'.
-
- * Fix compiler so it accepts `-fgnu-intrinsics-*' and
- `-fbadu77-intrinsics-*' options.
-
-In `egcs' 1.0.1 (versus `egcs' 1.0):
-====================================
-
- * Fix run-time crash involving `NAMELIST' on 64-bit machines such as
- Alphas.
-
-In `egcs' 1.0 (versus 0.5.21):
-==============================
-
- * Version 1.0 of `egcs' contains several regressions against version
- 0.5.21 of `g77', due to using the "vanilla" `gcc' back end instead
- of patching it to fix a few bugs and improve performance in a few
- cases.
-
- See `egcs/gcc/f/BUGS', for information on the known bugs in this
- version, including the regressions.
-
- Features that have been dropped from this version of `g77' due to
- their being implemented via `g77'-specific patches to the `gcc'
- back end in previous releases include:
-
- - Support for the C-language `restrict' keyword.
-
- - Support for the `-W' option warning about integer division by
- zero.
-
- - The Intel x86-specific option `-malign-double' applying to
- stack-allocated data as well as statically-allocate data.
-
- Note that the `gcc/f/gbe/' subdirectory has been removed from this
- distribution as a result of `g77' being fully integrated with the
- `egcs' variant of the `gcc' back end.
-
- * Fix code generation for iterative `DO' loops that have one or more
- references to the iteration variable, or to aliases of it, in
- their control expressions. For example, `DO 10 J=2,J' now is
- compiled correctly.
-
- * Fix `DTime' intrinsic so as not to truncate results to integer
- values (on some systems).
-
- * Remove support for non-`egcs' versions of `gcc'.
-
- * Remove support for the `--driver' option, as `g77' now does all
- the driving, just like `gcc'.
-
- * Allow any numeric argument to intrinsics `Int2' and `Int8'.
-
- * Improve diagnostic messages from `libf2c' so it is more likely
- that the printing of the active format string is limited to the
- string, with no trailing garbage being printed.
-
- (Unlike `f2c', `g77' did not append a null byte to its compiled
- form of every format string specified via a `FORMAT' statement.
- However, `f2c' would exhibit the problem anyway for a statement
- like `PRINT '(I)garbage', 1' by printing `(I)garbage' as the
- format string.)
-
- * Upgrade to `libf2c' as of 1997-09-23. This fixes a formatted-I/O
- bug that afflicted 64-bit systems with 32-bit integers (such as
- Digital Alpha running GNU/Linux).
-
-In 0.5.21:
-==========
-
- * Fix a code-generation bug introduced by 0.5.20 caused by loop
- unrolling (by specifying `-funroll-loops' or similar). This bug
- afflicted all code compiled by version 2.7.2.2.f.2 of `gcc' (C,
- C++, Fortran, and so on).
-
- * Fix a code-generation bug manifested when combining local
- `EQUIVALENCE' with a `DATA' statement that follows the first
- executable statement (or is treated as an executable-context
- statement as a result of using the `-fpedantic' option).
-
- * Fix a compiler crash that occured when an integer division by a
- constant zero is detected. Instead, when the `-W' option is
- specified, the `gcc' back end issues a warning about such a case.
- This bug afflicted all code compiled by version 2.7.2.2.f.2 of
- `gcc' (C, C++, Fortran, and so on).
-
- * Fix a compiler crash that occurred in some cases of procedure
- inlining. (Such cases became more frequent in 0.5.20.)
-
- * Fix a compiler crash resulting from using `DATA' or similar to
- initialize a `COMPLEX' variable or array to zero.
-
- * Fix compiler crashes involving use of `AND', `OR', or `XOR'
- intrinsics.
-
- * Fix compiler bug triggered when using a `COMMON' or `EQUIVALENCE'
- variable as the target of an `ASSIGN' or assigned-`GOTO' statement.
-
- * Fix compiler crashes due to using the name of a some non-standard
- intrinsics (such as `FTELL' or `FPUTC') as such and as the name of
- a procedure or common block. Such dual use of a name in a program
- is allowed by the standard.
-
- * Place automatic arrays on the stack, even if `SAVE' or the
- `-fno-automatic' option is in effect. This avoids a compiler
- crash in some cases.
-
- * The `-malign-double' option now reliably aligns `DOUBLE PRECISION'
- optimally on Pentium and Pentium Pro architectures (586 and 686 in
- `gcc').
-
- * New option `-Wno-globals' disables warnings about "suspicious" use
- of a name both as a global name and as the implicit name of an
- intrinsic, and warnings about disagreements over the number or
- natures of arguments passed to global procedures, or the natures
- of the procedures themselves.
-
- The default is to issue such warnings, which are new as of this
- version of `g77'.
-
- * New option `-fno-globals' disables diagnostics about potentially
- fatal disagreements analysis problems, such as disagreements over
- the number or natures of arguments passed to global procedures, or
- the natures of those procedures themselves.
-
- The default is to issue such diagnostics and flag the compilation
- as unsuccessful. With this option, the diagnostics are issued as
- warnings, or, if `-Wno-globals' is specified, are not issued at
- all.
-
- This option also disables inlining of global procedures, to avoid
- compiler crashes resulting from coding errors that these
- diagnostics normally would identify.
-
- * Diagnose cases where a reference to a procedure disagrees with the
- type of that procedure, or where disagreements about the number or
- nature of arguments exist. This avoids a compiler crash.
-
- * Fix parsing bug whereby `g77' rejected a second initialization
- specification immediately following the first's closing `/' without
- an intervening comma in a `DATA' statement, and the second
- specification was an implied-DO list.
-
- * Improve performance of the `gcc' back end so certain complicated
- expressions involving `COMPLEX' arithmetic (especially
- multiplication) don't appear to take forever to compile.
-
- * Fix a couple of profiling-related bugs in `gcc' back end.
-
- * Integrate GNU Ada's (GNAT's) changes to the back end, which
- consist almost entirely of bug fixes. These fixes are circa
- version 3.10p of GNAT.
-
- * Include some other `gcc' fixes that seem useful in `g77''s version
- of `gcc'. (See `gcc/ChangeLog' for details--compare it to that
- file in the vanilla `gcc-2.7.2.3.tar.gz' distribution.)
-
- * Fix `libU77' routines that accept file and other names to strip
- trailing blanks from them, for consistency with other
- implementations. Blanks may be forcibly appended to such names by
- appending a single null character (`CHAR(0)') to the significant
- trailing blanks.
-
- * Fix `CHMOD' intrinsic to work with file names that have embedded
- blanks, commas, and so on.
-
- * Fix `SIGNAL' intrinsic so it accepts an optional third `Status'
- argument.
-
- * Fix `IDATE()' intrinsic subroutine (VXT form) so it accepts
- arguments in the correct order. Documentation fixed accordingly,
- and for `GMTIME()' and `LTIME()' as well.
-
- * Make many changes to `libU77' intrinsics to support existing code
- more directly.
-
- Such changes include allowing both subroutine and function forms
- of many routines, changing `MCLOCK()' and `TIME()' to return
- `INTEGER(KIND=1)' values, introducing `MCLOCK8()' and `TIME8()' to
- return `INTEGER(KIND=2)' values, and placing functions that are
- intended to perform side effects in a new intrinsic group,
- `badu77'.
-
- * Improve `libU77' so it is more portable.
-
- * Add options `-fbadu77-intrinsics-delete',
- `-fbadu77-intrinsics-hide', and so on.
-
- * Fix crashes involving diagnosed or invalid code.
-
- * `g77' and `gcc' now do a somewhat better job detecting and
- diagnosing arrays that are too large to handle before these cause
- diagnostics during the assembler or linker phase, a compiler
- crash, or generation of incorrect code.
-
- * Make some fixes to alias analysis code.
-
- * Add support for `restrict' keyword in `gcc' front end.
-
- * Support `gcc' version 2.7.2.3 (modified by `g77' into version
- 2.7.2.3.f.1), and remove support for prior versions of `gcc'.
-
- * Incorporate GNAT's patches to the `gcc' back end into `g77''s, so
- GNAT users do not need to apply GNAT's patches to build both GNAT
- and `g77' from the same source tree.
-
- * Modify `make' rules and related code so that generation of Info
- documentation doesn't require compilation using `gcc'. Now, any
- ANSI C compiler should be adequate to produce the `g77'
- documentation (in particular, the tables of intrinsics) from
- scratch.
-
- * Add `INT2' and `INT8' intrinsics.
-
- * Add `CPU_TIME' intrinsic.
-
- * Add `ALARM' intrinsic.
-
- * `CTIME' intrinsic now accepts any `INTEGER' argument, not just
- `INTEGER(KIND=2)'.
-
- * Warn when explicit type declaration disagrees with the type of an
- intrinsic invocation.
-
- * Support `*f771' entry in `gcc' `specs' file.
-
- * Fix typo in `make' rule `g77-cross', used only for cross-compiling.
-
- * Fix `libf2c' build procedure to re-archive library if previous
- attempt to archive was interrupted.
-
- * Change `gcc' to unroll loops only during the last invocation (of
- as many as two invocations) of loop optimization.
-
- * Improve handling of `-fno-f2c' so that code that attempts to pass
- an intrinsic as an actual argument, such as `CALL FOO(ABS)', is
- rejected due to the fact that the run-time-library routine is,
- effectively, compiled with `-ff2c' in effect.
-
- * Fix `g77' driver to recognize `-fsyntax-only' as an option that
- inhibits linking, just like `-c' or `-S', and to recognize and
- properly handle the `-nostdlib', `-M', `-MM', `-nodefaultlibs',
- and `-Xlinker' options.
-
- * Upgrade to `libf2c' as of 1997-08-16.
-
- * Modify `libf2c' to consistently and clearly diagnose recursive I/O
- (at run time).
-
- * `g77' driver now prints version information (such as produced by
- `g77 -v') to `stderr' instead of `stdout'.
-
- * The `.r' suffix now designates a Ratfor source file, to be
- preprocessed via the `ratfor' command, available separately.
-
- * Fix some aspects of how `gcc' determines what kind of system is
- being configured and what kinds are supported. For example, GNU
- Linux/Alpha ELF systems now are directly supported.
-
- * Improve diagnostics.
-
- * Improve documentation and indexing.
-
- * Include all pertinent files for `libf2c' that come from
- `netlib.bell-labs.com'; give any such files that aren't quite
- accurate in `g77''s version of `libf2c' the suffix `.netlib'.
-
- * Reserve `INTEGER(KIND=0)' for future use.
-
-In 0.5.20:
-==========
-
- * The `-fno-typeless-boz' option is now the default.
-
- This option specifies that non-decimal-radix constants using the
- prefixed-radix form (such as `Z'1234'') are to be interpreted as
- `INTEGER' constants. Specify `-ftypeless-boz' to cause such
- constants to be interpreted as typeless.
-
- (Version 0.5.19 introduced `-fno-typeless-boz' and its inverse.)
-
- * Options `-ff90-intrinsics-enable' and `-fvxt-intrinsics-enable'
- now are the defaults.
-
- Some programs might use names that clash with intrinsic names
- defined (and now enabled) by these options or by the new `libU77'
- intrinsics. Users of such programs might need to compile them
- differently (using, for example, `-ff90-intrinsics-disable') or,
- better yet, insert appropriate `EXTERNAL' statements specifying
- that these names are not intended to be names of intrinsics.
-
- * The `ALWAYS_FLUSH' macro is no longer defined when building
- `libf2c', which should result in improved I/O performance,
- especially over NFS.
-
- *Note:* If you have code that depends on the behavior of `libf2c'
- when built with `ALWAYS_FLUSH' defined, you will have to modify
- `libf2c' accordingly before building it from this and future
- versions of `g77'.
-
- * Dave Love's implementation of `libU77' has been added to the
- version of `libf2c' distributed with and built as part of `g77'.
- `g77' now knows about the routines in this library as intrinsics.
-
- * New option `-fvxt' specifies that the source file is written in
- VXT Fortran, instead of GNU Fortran.
-
- * The `-fvxt-not-f90' option has been deleted, along with its
- inverse, `-ff90-not-vxt'.
-
- If you used one of these deleted options, you should re-read the
- pertinent documentation to determine which options, if any, are
- appropriate for compiling your code with this version of `g77'.
-
- * The `-fugly' option now issues a warning, as it likely will be
- removed in a future version.
-
- (Enabling all the `-fugly-*' options is unlikely to be feasible,
- or sensible, in the future, so users should learn to specify only
- those `-fugly-*' options they really need for a particular source
- file.)
-
- * The `-fugly-assumed' option, introduced in version 0.5.19, has
- been changed to better accommodate old and new code.
-
- * Make a number of fixes to the `g77' front end and the `gcc' back
- end to better support Alpha (AXP) machines. This includes
- providing at least one bug-fix to the `gcc' back end for Alphas.
-
- * Related to supporting Alpha (AXP) machines, the `LOC()' intrinsic
- and `%LOC()' construct now return values of integer type that is
- the same width (holds the same number of bits) as the pointer type
- on the machine.
-
- On most machines, this won't make a difference, whereas on Alphas,
- the type these constructs return is `INTEGER*8' instead of the
- more common `INTEGER*4'.
-
- * Emulate `COMPLEX' arithmetic in the `g77' front end, to avoid bugs
- in `complex' support in the `gcc' back end. New option
- `-fno-emulate-complex' causes `g77' to revert the 0.5.19 behavior.
-
- * Fix bug whereby `REAL A(1)', for example, caused a compiler crash
- if `-fugly-assumed' was in effect and A was a local (automatic)
- array. That case is no longer affected by the new handling of
- `-fugly-assumed'.
-
- * Fix `g77' command driver so that `g77 -o foo.f' no longer deletes
- `foo.f' before issuing other diagnostics, and so the `-x' option
- is properly handled.
-
- * Enable inlining of subroutines and functions by the `gcc' back end.
- This works as it does for `gcc' itself--program units may be
- inlined for invocations that follow them in the same program unit,
- as long as the appropriate compile-time options are specified.
-
- * Dummy arguments are no longer assumed to potentially alias
- (overlap) other dummy arguments or `COMMON' areas when any of
- these are defined (assigned to) by Fortran code.
-
- This can result in faster and/or smaller programs when compiling
- with optimization enabled, though on some systems this effect is
- observed only when `-fforce-addr' also is specified.
-
- New options `-falias-check', `-fargument-alias',
- `-fargument-noalias', and `-fno-argument-noalias-global' control
- the way `g77' handles potential aliasing.
-
- * The `CONJG()' and `DCONJG()' intrinsics now are compiled in-line.
-
- * The bug-fix for 0.5.19.1 has been re-done. The `g77' compiler has
- been changed back to assume `libf2c' has no aliasing problems in
- its implementations of the `COMPLEX' (and `DOUBLE COMPLEX')
- intrinsics. The `libf2c' has been changed to have no such
- problems.
-
- As a result, 0.5.20 is expected to offer improved performance over
- 0.5.19.1, perhaps as good as 0.5.19 in most or all cases, due to
- this change alone.
-
- *Note:* This change requires version 0.5.20 of `libf2c', at least,
- when linking code produced by any versions of `g77' other than
- 0.5.19.1. Use `g77 -v' to determine the version numbers of the
- `libF77', `libI77', and `libU77' components of the `libf2c'
- library. (If these version numbers are not printed--in
- particular, if the linker complains about unresolved references to
- names like `g77__fvers__'--that strongly suggests your
- installation has an obsolete version of `libf2c'.)
-
- * New option `-fugly-assign' specifies that the same memory
- locations are to be used to hold the values assigned by both
- statements `I = 3' and `ASSIGN 10 TO I', for example. (Normally,
- `g77' uses a separate memory location to hold assigned statement
- labels.)
-
- * `FORMAT' and `ENTRY' statements now are allowed to precede
- `IMPLICIT NONE' statements.
-
- * Produce diagnostic for unsupported `SELECT CASE' on `CHARACTER'
- type, instead of crashing, at compile time.
-
- * Fix crashes involving diagnosed or invalid code.
-
- * Change approach to building `libf2c' archive (`libf2c.a') so that
- members are added to it only when truly necessary, so the user
- that installs an already-built `g77' doesn't need to have write
- access to the build tree (whereas the user doing the build might
- not have access to install new software on the system).
-
- * Support `gcc' version 2.7.2.2 (modified by `g77' into version
- 2.7.2.2.f.2), and remove support for prior versions of `gcc'.
-
- * Upgrade to `libf2c' as of 1997-02-08, and fix up some of the build
- procedures.
-
- * Improve general build procedures for `g77', fixing minor bugs
- (such as deletion of any file named `f771' in the parent directory
- of `gcc/').
-
- * Enable full support of `INTEGER*8' available in `libf2c' and
- `f2c.h' so that `f2c' users may make full use of its features via
- the `g77' version of `f2c.h' and the `INTEGER*8' support routines
- in the `g77' version of `libf2c'.
-
- * Improve `g77' driver and `libf2c' so that `g77 -v' yields version
- information on the library.
-
- * The `SNGL' and `FLOAT' intrinsics now are specific intrinsics,
- instead of synonyms for the generic intrinsic `REAL'.
-
- * New intrinsics have been added. These are `REALPART', `IMAGPART',
- `COMPLEX', `LONG', and `SHORT'.
-
- * A new group of intrinsics, `gnu', has been added to contain the
- new `REALPART', `IMAGPART', and `COMPLEX' intrinsics. An old
- group, `dcp', has been removed.
-
- * Complain about industry-wide ambiguous references `REAL(EXPR)' and
- `AIMAG(EXPR)', where EXPR is `DOUBLE COMPLEX' (or any complex type
- other than `COMPLEX'), unless `-ff90' option specifies Fortran 90
- interpretation or new `-fugly-complex' option, in conjunction with
- `-fnot-f90', specifies `f2c' interpretation.
-
- * Make improvements to diagnostics.
-
- * Speed up compiler a bit.
-
- * Improvements to documentation and indexing, including a new
- chapter containing information on one, later more, diagnostics
- that users are directed to pull up automatically via a message in
- the diagnostic itself.
-
- (Hence the menu item `M' for the node `Diagnostics' in the
- top-level menu of the Info documentation.)
-
-In 0.5.19.1:
-============
-
- * Code-generation bugs afflicting operations on complex data have
- been fixed.
-
- These bugs occurred when assigning the result of an operation to a
- complex variable (or array element) that also served as an input
- to that operation.
-
- The operations affected by this bug were: `CONJG()', `DCONJG()',
- `CCOS()', `CDCOS()', `CLOG()', `CDLOG()', `CSIN()', `CDSIN()',
- `CSQRT()', `CDSQRT()', complex division, and raising a `DOUBLE
- COMPLEX' operand to an `INTEGER' power. (The related generic and
- `Z'-prefixed intrinsics, such as `ZSIN()', also were affected.)
-
- For example, `C = CSQRT(C)', `Z = Z/C', and `Z = Z**I' (where `C'
- is `COMPLEX' and `Z' is `DOUBLE COMPLEX') have been fixed.
-
-In 0.5.19:
-==========
-
- * Fix `FORMAT' statement parsing so negative values for specifiers
- such as `P' (e.g. `FORMAT(-1PF8.1)') are correctly processed as
- negative.
-
- * Fix `SIGNAL' intrinsic so it once again accepts a procedure as its
- second argument.
-
- * A temporary kludge option provides bare-bones information on
- `COMMON' and `EQUIVALENCE' members at debug time.
-
- * New `-fonetrip' option specifies FORTRAN-66-style one-trip `DO'
- loops.
-
- * New `-fno-silent' option causes names of program units to be
- printed as they are compiled, in a fashion similar to UNIX `f77'
- and `f2c'.
-
- * New `-fugly-assumed' option specifies that arrays dimensioned via
- `DIMENSION X(1)', for example, are to be treated as assumed-size.
-
- * New `-fno-typeless-boz' option specifies that non-decimal-radix
- constants using the prefixed-radix form (such as `Z'1234'') are to
- be interpreted as `INTEGER' constants.
-
- * New `-ff66' option is a "shorthand" option that specifies
- behaviors considered appropriate for FORTRAN 66 programs.
-
- * New `-ff77' option is a "shorthand" option that specifies
- behaviors considered appropriate for UNIX `f77' programs.
-
- * New `-fugly-comma' and `-fugly-logint' options provided to perform
- some of what `-fugly' used to do. `-fugly' and `-fno-ugly' are
- now "shorthand" options, in that they do nothing more than enable
- (or disable) other `-fugly-*' options.
-
- * Fix parsing of assignment statements involving targets that are
- substrings of elements of `CHARACTER' arrays having names such as
- `READ', `WRITE', `GOTO', and `REALFUNCTIONFOO'.
-
- * Fix crashes involving diagnosed code.
-
- * Fix handling of local `EQUIVALENCE' areas so certain cases of
- valid Fortran programs are not misdiagnosed as improperly
- extending the area backwards.
-
- * Support `gcc' version 2.7.2.1.
-
- * Upgrade to `libf2c' as of 1996-09-26, and fix up some of the build
- procedures.
-
- * Change code generation for list-directed I/O so it allows for new
- versions of `libf2c' that might return non-zero status codes for
- some operations previously assumed to always return zero.
-
- This change not only affects how `IOSTAT=' variables are set by
- list-directed I/O, it also affects whether `END=' and `ERR='
- labels are reached by these operations.
-
- * Add intrinsic support for new `FTELL' and `FSEEK' procedures in
- `libf2c'.
-
- * Modify `fseek_()' in `libf2c' to be more portable (though, in
- practice, there might be no systems where this matters) and to
- catch invalid `whence' arguments.
-
- * Some useless warnings from the `-Wunused' option have been
- eliminated.
-
- * Fix a problem building the `f771' executable on AIX systems by
- linking with the `-bbigtoc' option.
-
- * Abort configuration if `gcc' has not been patched using the patch
- file provided in the `gcc/f/gbe/' subdirectory.
-
- * Add options `--help' and `--version' to the `g77' command, to
- conform to GNU coding guidelines. Also add printing of `g77'
- version number when the `--verbose' (`-v') option is used.
-
- * Change internally generated name for local `EQUIVALENCE' areas to
- one based on the alphabetically sorted first name in the list of
- names for entities placed at the beginning of the areas.
-
- * Improvements to documentation and indexing.
-
-In 0.5.18:
-==========
-
- * Add some rudimentary support for `INTEGER*1', `INTEGER*2',
- `INTEGER*8', and their `LOGICAL' equivalents. (This support works
- on most, maybe all, `gcc' targets.)
-
- Thanks to Scott Snyder (<snyder@d0sgif.fnal.gov>) for providing
- the patch for this!
-
- Among the missing elements from the support for these features are
- full intrinsic support and constants.
-
- * Add some rudimentary support for the `BYTE' and `WORD'
- type-declaration statements. `BYTE' corresponds to `INTEGER*1',
- while `WORD' corresponds to `INTEGER*2'.
-
- Thanks to Scott Snyder (<snyder@d0sgif.fnal.gov>) for providing
- the patch for this!
-
- * The compiler code handling intrinsics has been largely rewritten
- to accommodate the new types. No new intrinsics or arguments for
- existing intrinsics have been added, so there is, at this point,
- no intrinsic to convert to `INTEGER*8', for example.
-
- * Support automatic arrays in procedures.
-
- * Reduce space/time requirements for handling large *sparsely*
- initialized aggregate arrays. This improvement applies to only a
- subset of the general problem to be addressed in 0.6.
-
- * Treat initial values of zero as if they weren't specified (in DATA
- and type-declaration statements). The initial values will be set
- to zero anyway, but the amount of compile time processing them
- will be reduced, in some cases significantly (though, again, this
- is only a subset of the general problem to be addressed in 0.6).
-
- A new option, `-fzeros', is introduced to enable the traditional
- treatment of zeros as any other value.
-
- * With `-ff90' in force, `g77' incorrectly interpreted `REAL(Z)' as
- returning a `REAL' result, instead of as a `DOUBLE PRECISION'
- result. (Here, `Z' is `DOUBLE COMPLEX'.)
-
- With `-fno-f90' in force, the interpretation remains unchanged,
- since this appears to be how at least some F77 code using the
- `DOUBLE COMPLEX' extension expected it to work.
-
- Essentially, `REAL(Z)' in F90 is the same as `DBLE(Z)', while in
- extended F77, it appears to be the same as `REAL(REAL(Z))'.
-
- * An expression involving exponentiation, where both operands were
- type `INTEGER' and the right-hand operand was negative, was
- erroneously evaluated.
-
- * Fix bugs involving `DATA' implied-`DO' constructs (these involved
- an errant diagnostic and a crash, both on good code, one involving
- subsequent statement-function definition).
-
- * Close `INCLUDE' files after processing them, so compiling source
- files with lots of `INCLUDE' statements does not result in being
- unable to open `INCLUDE' files after all the available file
- descriptors are used up.
-
- * Speed up compiling, especially of larger programs, and perhaps
- slightly reduce memory utilization while compiling (this is *not*
- the improvement planned for 0.6 involving large aggregate
- areas)--these improvements result from simply turning off some
- low-level code to do self-checking that hasn't been triggered in a
- long time.
-
- * Introduce three new options that implement optimizations in the
- `gcc' back end (GBE). These options are `-fmove-all-movables',
- `-freduce-all-givs', and `-frerun-loop-opt', which are enabled, by
- default, for Fortran compilations. These optimizations are
- intended to help toon Fortran programs.
-
- * Patch the GBE to do a better job optimizing certain kinds of
- references to array elements.
-
- * Due to patches to the GBE, the version number of `gcc' also is
- patched to make it easier to manage installations, especially
- useful if it turns out a `g77' change to the GBE has a bug.
-
- The `g77'-modified version number is the `gcc' version number with
- the string `.f.N' appended, where `f' identifies the version as
- enhanced for Fortran, and N is `1' for the first Fortran patch for
- that version of `gcc', `2' for the second, and so on.
-
- So, this introduces version 2.7.2.f.1 of `gcc'.
-
- * Make several improvements and fixes to diagnostics, including the
- removal of two that were inappropriate or inadequate.
-
- * Warning about two successive arithmetic operators, produced by
- `-Wsurprising', now produced *only* when both operators are,
- indeed, arithmetic (not relational/boolean).
-
- * `-Wsurprising' now warns about the remaining cases of using
- non-integral variables for implied-`DO' loops, instead of these
- being rejected unless `-fpedantic' or `-fugly' specified.
-
- * Allow `SAVE' of a local variable or array, even after it has been
- given an initial value via `DATA', for example.
-
- * Introduce an Info version of `g77' documentation, which supercedes
- `gcc/f/CREDITS', `gcc/f/DOC', and `gcc/f/PROJECTS'. These files
- will be removed in a future release. The files `gcc/f/BUGS',
- `gcc/f/INSTALL', and `gcc/f/NEWS' now are automatically built from
- the texinfo source when distributions are made.
-
- This effort was inspired by a first pass at translating
- `g77-0.5.16/f/DOC' that was contributed to Craig by David Ronis
- (<ronis@onsager.chem.mcgill.ca>).
-
- * New `-fno-second-underscore' option to specify that, when
- `-funderscoring' is in effect, a second underscore is not to be
- appended to Fortran names already containing an underscore.
-
- * Change the way iterative `DO' loops work to follow the F90
- standard. In particular, calculation of the iteration count is
- still done by converting the start, end, and increment parameters
- to the type of the `DO' variable, but the result of the
- calculation is always converted to the default `INTEGER' type.
-
- (This should have no effect on existing code compiled by `g77',
- but code written to assume that use of a *wider* type for the `DO'
- variable will result in an iteration count being fully calculated
- using that wider type (wider than default `INTEGER') must be
- rewritten.)
-
- * Support `gcc' version 2.7.2.
-
- * Upgrade to `libf2c' as of 1996-03-23, and fix up some of the build
- procedures.
-
- Note that the email addresses related to `f2c' have changed--the
- distribution site now is named `netlib.bell-labs.com', and the
- maintainer's new address is <dmg@bell-labs.com>.
-
-In 0.5.17:
-==========
-
- * *Fix serious bug* in `g77 -v' command that can cause removal of a
- system's `/dev/null' special file if run by user `root'.
-
- *All users* of version 0.5.16 should ensure that they have not
- removed `/dev/null' or replaced it with an ordinary file (e.g. by
- comparing the output of `ls -l /dev/null' with `ls -l /dev/zero'.
- If the output isn't basically the same, contact your system
- administrator about restoring `/dev/null' to its proper status).
-
- This bug is particularly insidious because removing `/dev/null' as
- a special file can go undetected for quite a while, aside from
- various applications and programs exhibiting sudden, strange
- behaviors.
-
- I sincerely apologize for not realizing the implications of the
- fact that when `g77 -v' runs the `ld' command with `-o /dev/null'
- that `ld' tries to *remove* the executable it is supposed to build
- (especially if it reports unresolved references, which it should
- in this case)!
-
- * Fix crash on `CHARACTER*(*) FOO' in a main or block data program
- unit.
-
- * Fix crash that can occur when diagnostics given outside of any
- program unit (such as when input file contains `@foo').
-
- * Fix crashes, infinite loops (hangs), and such involving diagnosed
- code.
-
- * Fix `ASSIGN''ed variables so they can be `SAVE''d or dummy
- arguments, and issue clearer error message in cases where target
- of `ASSIGN' or `ASSIGN'ed `GOTO'/`FORMAT' is too small (which
- should never happen).
-
- * Make `libf2c' build procedures work on more systems again by
- eliminating unnecessary invocations of `ld -r -x' and `mv'.
-
- * Fix omission of `-funix-intrinsics-...' options in list of
- permitted options to compiler.
-
- * Fix failure to always diagnose missing type declaration for
- `IMPLICIT NONE'.
-
- * Fix compile-time performance problem (which could sometimes crash
- the compiler, cause a hang, or whatever, due to a bug in the back
- end) involving exponentiation with a large `INTEGER' constant for
- the right-hand operator (e.g. `I**32767').
-
- * Fix build procedures so cross-compiling `g77' (the `fini' utility
- in particular) is properly built using the host compiler.
-
- * Add new `-Wsurprising' option to warn about constructs that are
- interpreted by the Fortran standard (and `g77') in ways that are
- surprising to many programmers.
-
- * Add `ERF()' and `ERFC()' as generic intrinsics mapping to existing
- `ERF'/`DERF' and `ERFC'/`DERFC' specific intrinsics.
-
- *Note:* You should specify `INTRINSIC ERF,ERFC' in any code where
- you might use these as generic intrinsics, to improve likelihood
- of diagnostics (instead of subtle run-time bugs) when using a
- compiler that doesn't support these as intrinsics (e.g. `f2c').
-
- * Remove from `-fno-pedantic' the diagnostic about `DO' with
- non-`INTEGER' index variable; issue that under `-Wsurprising'
- instead.
-
- * Clarify some diagnostics that say things like "ignored" when that's
- misleading.
-
- * Clarify diagnostic on use of `.EQ.'/`.NE.' on `LOGICAL' operands.
-
- * Minor improvements to code generation for various operations on
- `LOGICAL' operands.
-
- * Minor improvement to code generation for some `DO' loops on some
- machines.
-
- * Support `gcc' version 2.7.1.
-
- * Upgrade to `libf2c' as of 1995-11-15.
-
-In 0.5.16:
-==========
-
- * Fix a code-generation bug involving complicated `EQUIVALENCE'
- statements not involving `COMMON'.
-
- * Fix code-generation bugs involving invoking "gratis" library
- procedures in `libf2c' from code compiled with `-fno-f2c' by
- making these procedures known to `g77' as intrinsics (not affected
- by -fno-f2c). This is known to fix code invoking `ERF()',
- `ERFC()', `DERF()', and `DERFC()'.
-
- * Update `libf2c' to include netlib patches through 1995-08-16, and
- `#define' `WANT_LEAD_0' to 1 to make `g77'-compiled code more
- consistent with other Fortran implementations by outputting
- leading zeros in formatted and list-directed output.
-
- * Fix a code-generation bug involving adjustable dummy arrays with
- high bounds whose primaries are changed during procedure
- execution, and which might well improve code-generation
- performance for such arrays compared to `f2c' plus `gcc' (but
- apparently only when using `gcc-2.7.0' or later).
-
- * Fix a code-generation bug involving invocation of `COMPLEX' and
- `DOUBLE COMPLEX' `FUNCTION's and doing `COMPLEX' and `DOUBLE
- COMPLEX' divides, when the result of the invocation or divide is
- assigned directly to a variable that overlaps one or more of the
- arguments to the invocation or divide.
-
- * Fix crash by not generating new optimal code for `X**I' if `I' is
- nonconstant and the expression is used to dimension a dummy array,
- since the `gcc' back end does not support the necessary mechanics
- (and the `gcc' front end rejects the equivalent construct, as it
- turns out).
-
- * Fix crash on expressions like `COMPLEX**INTEGER'.
-
- * Fix crash on expressions like `(1D0,2D0)**2', i.e. raising a
- `DOUBLE COMPLEX' constant to an `INTEGER' constant power.
-
- * Fix crashes and such involving diagnosed code.
-
- * Diagnose, instead of crashing on, statement function definitions
- having duplicate dummy argument names.
-
- * Fix bug causing rejection of good code involving statement function
- definitions.
-
- * Fix bug resulting in debugger not knowing size of local equivalence
- area when any member of area has initial value (via `DATA', for
- example).
-
- * Fix installation bug that prevented installation of `g77' driver.
- Provide for easy selection of whether to install copy of `g77' as
- `f77' to replace the broken code.
-
- * Fix `gcc' driver (affects `g77' thereby) to not gratuitously
- invoke the `f771' program (e.g. when `-E' is specified).
-
- * Fix diagnostic to point to correct source line when it immediately
- follows an `INCLUDE' statement.
-
- * Support more compiler options in `gcc'/`g77' when compiling
- Fortran files. These options include `-p', `-pg', `-aux-info',
- `-P', correct setting of version-number macros for preprocessing,
- full recognition of `-O0', and automatic insertion of
- configuration-specific linker specs.
-
- * Add new intrinsics that interface to existing routines in `libf2c':
- `ABORT', `DERF', `DERFC', `ERF', `ERFC', `EXIT', `FLUSH',
- `GETARG', `GETENV', `IARGC', `SIGNAL', and `SYSTEM'. Note that
- `ABORT', `EXIT', `FLUSH', `SIGNAL', and `SYSTEM' are intrinsic
- subroutines, not functions (since they have side effects), so to
- get the return values from `SIGNAL' and `SYSTEM', append a final
- argument specifying an `INTEGER' variable or array element (e.g.
- `CALL SYSTEM('rm foo',ISTAT)').
-
- * Add new intrinsic group named `unix' to contain the new intrinsics,
- and by default enable this new group.
-
- * Move `LOC()' intrinsic out of the `vxt' group to the new `unix'
- group.
-
- * Improve `g77' so that `g77 -v' by itself (or with certain other
- options, including `-B', `-b', `-i', `-nostdlib', and `-V')
- reports lots more useful version info, and so that long-form
- options `gcc' accepts are understood by `g77' as well (even in
- truncated, unambiguous forms).
-
- * Add new `g77' option `--driver=name' to specify driver when
- default, `gcc', isn't appropriate.
-
- * Add support for `#' directives (as output by the preprocessor) in
- the compiler, and enable generation of those directives by the
- preprocessor (when compiling `.F' files) so diagnostics and
- debugging info are more useful to users of the preprocessor.
-
- * Produce better diagnostics, more like `gcc', with info such as `In
- function `foo':' and `In file included from...:'.
-
- * Support `gcc''s `-fident' and `-fno-ident' options.
-
- * When `-Wunused' in effect, don't warn about local variables used as
- statement-function dummy arguments or `DATA' implied-`DO' iteration
- variables, even though, strictly speaking, these are not uses of
- the variables themselves.
-
- * When `-W -Wunused' in effect, don't warn about unused dummy
- arguments at all, since there's no way to turn this off for
- individual cases (`g77' might someday start warning about
- these)--applies to `gcc' versions 2.7.0 and later, since earlier
- versions didn't warn about unused dummy arguments.
-
- * New option `-fno-underscoring' that inhibits transformation of
- names (by appending one or two underscores) so users may experiment
- with implications of such an environment.
-
- * Minor improvement to `gcc/f/info' module to make it easier to build
- `g77' using the native (non-`gcc') compiler on certain machines
- (but definitely not all machines nor all non-`gcc' compilers).
- Please do not report bugs showing problems compilers have with
- macros defined in `gcc/f/target.h' and used in places like
- `gcc/f/expr.c'.
-
- * Add warning to be printed for each invocation of the compiler if
- the target machine `INTEGER', `REAL', or `LOGICAL' size is not 32
- bits, since `g77' is known to not work well for such cases (to be
- fixed in Version 0.6--*note Actual Bugs We Haven't Fixed Yet:
- Actual Bugs.).
-
- * Lots of new documentation (though work is still needed to put it
- into canonical GNU format).
-
- * Build `libf2c' with `-g0', not `-g2', in effect (by default), to
- produce smaller library without lots of debugging clutter.
-
-In 0.5.15:
-==========
-
- * Fix bad code generation involving `X**I' and temporary, internal
- variables generated by `g77' and the back end (such as for `DO'
- loops).
-
- * Fix crash given `CHARACTER A;DATA A/.TRUE./'.
-
- * Replace crash with diagnostic given `CHARACTER A;DATA A/1.0/'.
-
- * Fix crash or other erratic behavior when null character constant
- (`''') is encountered.
-
- * Fix crash or other erratic behavior involving diagnosed code.
-
- * Fix code generation for external functions returning type `REAL'
- when the `-ff2c' option is in force (which it is by default) so
- that `f2c' compatibility is indeed provided.
-
- * Disallow `COMMON I(10)' if `I' has previously been specified with
- an array declarator.
-
- * New `-ffixed-line-length-N' option, where N is the maximum length
- of a typical fixed-form line, defaulting to 72 columns, such that
- characters beyond column N are ignored, or N is `none', meaning no
- characters are ignored. does not affect lines with `&' in column
- 1, which are always processed as if `-ffixed-line-length-none' was
- in effect.
-
- * No longer generate better code for some kinds of array references,
- as `gcc' back end is to be fixed to do this even better, and it
- turned out to slow down some code in some cases after all.
-
- * In `COMMON' and `EQUIVALENCE' areas with any members given initial
- values (e.g. via `DATA'), uninitialized members now always
- initialized to binary zeros (though this is not required by the
- standard, and might not be done in future versions of `g77').
- Previously, in some `COMMON'/`EQUIVALENCE' areas (essentially
- those with members of more than one type), the uninitialized
- members were initialized to spaces, to cater to `CHARACTER' types,
- but it seems no existing code expects that, while much existing
- code expects binary zeros.
-
-In 0.5.14:
-==========
-
- * Don't emit bad code when low bound of adjustable array is
- nonconstant and thus might vary as an expression at run time.
-
- * Emit correct code for calculation of number of trips in `DO' loops
- for cases where the loop should not execute at all. (This bug
- affected cases where the difference between the begin and end
- values was less than the step count, though probably not for
- floating-point cases.)
-
- * Fix crash when extra parentheses surround item in `DATA'
- implied-`DO' list.
-
- * Fix crash over minor internal inconsistencies in handling
- diagnostics, just substitute dummy strings where necessary.
-
- * Fix crash on some systems when compiling call to `MVBITS()'
- intrinsic.
-
- * Fix crash on array assignment `TYPEDDD(...)=...', where DDD is a
- string of one or more digits.
-
- * Fix crash on `DCMPLX()' with a single `INTEGER' argument.
-
- * Fix various crashes involving code with diagnosed errors.
-
- * Support `-I' option for `INCLUDE' statement, plus `gcc''s
- `header.gcc' facility for handling systems like MS-DOS.
-
- * Allow `INCLUDE' statement to be continued across multiple lines,
- even allow it to coexist with other statements on the same line.
-
- * Incorporate Bellcore fixes to `libf2c' through 1995-03-15--this
- fixes a bug involving infinite loops reading EOF with empty
- list-directed I/O list.
-
- * Remove all the `g77'-specific auto-configuration scripts, code,
- and so on, except for temporary substitutes for bsearch() and
- strtoul(), as too many configure/build problems were reported in
- these areas. People will have to fix their systems' problems
- themselves, or at least somewhere other than `g77', which expects
- a working ANSI C environment (and, for now, a GNU C compiler to
- compile `g77' itself).
-
- * Complain if initialized common redeclared as larger in subsequent
- program unit.
-
- * Warn if blank common initialized, since its size can vary and hence
- related warnings that might be helpful won't be seen.
-
- * New `-fbackslash' option, on by default, that causes `\' within
- `CHARACTER' and Hollerith constants to be interpreted a la GNU C.
- Note that this behavior is somewhat different from `f2c''s, which
- supports only a limited subset of backslash (escape) sequences.
-
- * Make `-fugly-args' the default.
-
- * New `-fugly-init' option, on by default, that allows
- typeless/Hollerith to be specified as initial values for variables
- or named constants (`PARAMETER'), and also allows
- character<->numeric conversion in those contexts--turn off via
- `-fno-ugly-init'.
-
- * New `-finit-local-zero' option to initialize local variables to
- binary zeros. This does not affect whether they are `SAVE'd, i.e.
- made automatic or static.
-
- * New `-Wimplicit' option to warn about implicitly typed variables,
- arrays, and functions. (Basically causes all program units to
- default to `IMPLICIT NONE'.)
-
- * `-Wall' now implies `-Wuninitialized' as with `gcc' (i.e. unless
- `-O' not specified, since `-Wuninitialized' requires `-O'), and
- implies `-Wunused' as well.
-
- * `-Wunused' no longer gives spurious messages for unused `EXTERNAL'
- names (since they are assumed to refer to block data program
- units, to make use of libraries more reliable).
-
- * Support `%LOC()' and `LOC()' of character arguments.
-
- * Support null (zero-length) character constants and expressions.
-
- * Support `f2c''s `IMAG()' generic intrinsic.
-
- * Support `ICHAR()', `IACHAR()', and `LEN()' of character
- expressions that are valid in assignments but not normally as
- actual arguments.
-
- * Support `f2c'-style `&' in column 1 to mean continuation line.
-
- * Allow `NAMELIST', `EXTERNAL', `INTRINSIC', and `VOLATILE' in
- `BLOCK DATA', even though these are not allowed by the standard.
-
- * Allow `RETURN' in main program unit.
-
- * Changes to Hollerith-constant support to obey Appendix C of the
- standard:
-
- - Now padded on the right with zeros, not spaces.
-
- - Hollerith "format specifications" in the form of arrays of
- non-character allowed.
-
- - Warnings issued when non-space truncation occurs when
- converting to another type.
-
- - When specified as actual argument, now passed by reference to
- `INTEGER' (padded on right with spaces if constant too small,
- otherwise fully intact if constant wider the `INTEGER' type)
- instead of by value.
-
- *Warning:* `f2c' differs on the interpretation of `CALL FOO(1HX)',
- which it treats exactly the same as `CALL FOO('X')', but which the
- standard and `g77' treat as `CALL FOO(%REF('X '))' (padded with
- as many spaces as necessary to widen to `INTEGER'), essentially.
-
- * Changes and fixes to typeless-constant support:
-
- - Now treated as a typeless double-length `INTEGER' value.
-
- - Warnings issued when overflow occurs.
-
- - Padded on the left with zeros when converting to a larger
- type.
-
- - Should be properly aligned and ordered on the target machine
- for whatever type it is turned into.
-
- - When specified as actual argument, now passed as reference to
- a default `INTEGER' constant.
-
- * `%DESCR()' of a non-`CHARACTER' expression now passes a pointer to
- the expression plus a length for the expression just as if it were
- a `CHARACTER' expression. For example, `CALL FOO(%DESCR(D))',
- where `D' is `REAL*8', is the same as `CALL FOO(D,%VAL(8)))'.
-
- * Name of multi-entrypoint master function changed to incorporate
- the name of the primary entry point instead of a decimal value, so
- the name of the master function for `SUBROUTINE X' with alternate
- entry points is now `__g77_masterfun_x'.
-
- * Remove redundant message about zero-step-count `DO' loops.
-
- * Clean up diagnostic messages, shortening many of them.
-
- * Fix typo in `g77' man page.
-
- * Clarify implications of constant-handling bugs in `f/BUGS'.
-
- * Generate better code for `**' operator with a right-hand operand of
- type `INTEGER'.
+ 38. Upgrade to `libf2c' as of 1998-06-18.
- * Generate better code for `SQRT()' and `DSQRT()', also when
- `-ffast-math' specified, enable better code generation for `SIN()'
- and `COS()'.
+ 39. Improve documentation and indexing.
- * Generate better code for some kinds of array references.
+In previous versions:
+=====================
- * Speed up lexing somewhat (this makes the compilation phase
- noticeably faster).
+ Information on previous versions is not provided in this
+`egcs/gcc/f/NEWS' file, to keep it short. See `egcs/gcc/f/news.texi',
+or any of its other derivations (Info, HTML, dvi forms) for such
+information.
diff --git a/contrib/gcc/f/RELEASE-PREP b/contrib/gcc/f/RELEASE-PREP
new file mode 100644
index 0000000..7069ea5
--- /dev/null
+++ b/contrib/gcc/f/RELEASE-PREP
@@ -0,0 +1,5 @@
+1999-03-13 RELEASE-PREP
+
+Things to do to prepare a g77 release (FSF, egcs, whatever).
+
+- Update root.texi: clear DEVELOPMENT flag, set version info.
diff --git a/contrib/gcc/f/ansify.c b/contrib/gcc/f/ansify.c
index 3af68e5..6c6d01f 100644
--- a/contrib/gcc/f/ansify.c
+++ b/contrib/gcc/f/ansify.c
@@ -1,6 +1,6 @@
/* ansify.c
Copyright (C) 1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -51,7 +51,7 @@ typedef enum
while(0)
static void
-die ()
+die (void)
{
exit (1);
}
diff --git a/contrib/gcc/f/assert.j b/contrib/gcc/f/assert.j
index a24b66f..d9b9daa 100644
--- a/contrib/gcc/f/assert.j
+++ b/contrib/gcc/f/assert.j
@@ -1,6 +1,6 @@
/* assert.j -- Wrapper for GCC's assert.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/bad.c b/contrib/gcc/f/bad.c
index a2a4832..704fa12 100644
--- a/contrib/gcc/f/bad.c
+++ b/contrib/gcc/f/bad.c
@@ -1,6 +1,6 @@
/* bad.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -62,7 +62,7 @@ bool ffebad_is_inhibited_ = FALSE;
struct _ffebad_message_
{
ffebadSeverity severity;
- char *message;
+ const char *message;
};
/* Static objects accessed by functions in this module. */
@@ -89,11 +89,11 @@ static struct
}
ffebad_here_[FFEBAD_MAX_];
-static char *ffebad_string_[FFEBAD_MAX_];
+static const char *ffebad_string_[FFEBAD_MAX_];
static ffebadIndex ffebad_order_[FFEBAD_MAX_];
static ffebad ffebad_errnum_;
static ffebadSeverity ffebad_severity_;
-static char *ffebad_message_;
+static const char *ffebad_message_;
static unsigned char ffebad_index_;
static ffebadIndex ffebad_places_;
static bool ffebad_is_temp_inhibited_; /* Effective setting of
@@ -102,7 +102,7 @@ static bool ffebad_is_temp_inhibited_; /* Effective setting of
/* Static functions (internal). */
-static int ffebad_bufputs_ (char buf[], int bufi, char *s);
+static int ffebad_bufputs_ (char buf[], int bufi, const char *s);
/* Internal macros. */
@@ -115,7 +115,7 @@ static int ffebad_bufputs_ (char buf[], int bufi, char *s);
static int
-ffebad_bufputs_ (char buf[], int bufi, char *s)
+ffebad_bufputs_ (char buf[], int bufi, const char *s)
{
for (; *s != '\0'; ++s)
bufi = ffebad_bufputc_ (buf, bufi, *s);
@@ -161,7 +161,7 @@ ffebad_severity (ffebad errnum)
bool
ffebad_start_ (bool lex_override, ffebad errnum, ffebadSeverity sev,
- char *message)
+ const char *message)
{
unsigned char i;
@@ -321,7 +321,7 @@ ffebad_here (ffebadIndex index, ffewhereLine line, ffewhereColumn col)
/* Establish string for next index (always in order) of message
- ffebad_string(char *string);
+ ffebad_string(const char *string);
Call ffebad_start to establish the message, ffebad_here and ffebad_string
to send run-time data to it as necessary, then ffebad_finish when through
@@ -330,7 +330,7 @@ ffebad_here (ffebadIndex index, ffewhereLine line, ffewhereColumn col)
the argument passed in until then. */
void
-ffebad_string (char *string)
+ffebad_string (const char *string)
{
if (ffebad_is_temp_inhibited_)
return;
@@ -351,7 +351,7 @@ void
ffebad_finish ()
{
#define MAX_SPACES 132
- static char *spaces
+ static const char *spaces
= "...>\
\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\
\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\
@@ -372,9 +372,9 @@ ffebad_finish ()
ffebadIndex bi;
unsigned short i;
char pointer;
- char c;
- char *s;
- char *fn;
+ unsigned char c;
+ unsigned const char *s;
+ const char *fn;
static char buf[1024];
int bufi;
int index;
diff --git a/contrib/gcc/f/bad.def b/contrib/gcc/f/bad.def
index 3a86a1f..4c7bfe4 100644
--- a/contrib/gcc/f/bad.def
+++ b/contrib/gcc/f/bad.def
@@ -1,6 +1,6 @@
/* bad.def -- Public #include File (module.h template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -700,6 +700,10 @@ FFEBAD_MSGS1 (FFEBAD_ARRAY_LARGE, FATAL,
"Array `%A' at %0 is too large to handle")
FFEBAD_MSGS1 (FFEBAD_SFUNC_UNUSED, WARN,
"Statement function `%A' defined at %0 is not used")
+FFEBAD_MSGS1 (FFEBAD_INTRINSIC_Y2KBAD, WARN,
+"Intrinsic `%A', invoked at %0, known to be non-Y2K-compliant [info -f g77 M Y2KBAD]")
+FFEBAD_MSGS1 (FFEBAD_NOCANDO, DISASTER,
+"Internal compiler error -- cannot perform operation")
#undef INFORM
#undef TRIVIAL
diff --git a/contrib/gcc/f/bad.h b/contrib/gcc/f/bad.h
index a52ff1f..7340223 100644
--- a/contrib/gcc/f/bad.h
+++ b/contrib/gcc/f/bad.h
@@ -1,6 +1,6 @@
/* bad.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -82,8 +82,8 @@ void ffebad_init_0 (void);
bool ffebad_is_fatal (ffebad errnum);
ffebadSeverity ffebad_severity (ffebad errnum);
bool ffebad_start_ (bool lex_override, ffebad errnum, ffebadSeverity sev,
- char *message);
-void ffebad_string (char *string);
+ const char *message);
+void ffebad_string (const char *string);
/* Define macros. */
diff --git a/contrib/gcc/f/bit.c b/contrib/gcc/f/bit.c
index 71e74d7..5f581a0 100644
--- a/contrib/gcc/f/bit.c
+++ b/contrib/gcc/f/bit.c
@@ -1,6 +1,6 @@
/* bit.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/bit.h b/contrib/gcc/f/bit.h
index 0e84499..a2acc25 100644
--- a/contrib/gcc/f/bit.h
+++ b/contrib/gcc/f/bit.h
@@ -1,6 +1,6 @@
/* bit.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/bld-op.def b/contrib/gcc/f/bld-op.def
index 44cde44..737dcc7 100644
--- a/contrib/gcc/f/bld-op.def
+++ b/contrib/gcc/f/bld-op.def
@@ -1,6 +1,6 @@
/* bld-op.def -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/bld.c b/contrib/gcc/f/bld.c
index 6e75692..15cadf1 100644
--- a/contrib/gcc/f/bld.c
+++ b/contrib/gcc/f/bld.c
@@ -1,6 +1,6 @@
/* bld.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -203,7 +203,7 @@ static ffebldConstant ffebld_constant_hollerith_;
static ffebldConstant ffebld_constant_typeless_[FFEBLD_constTYPELESS_LAST
- FFEBLD_constTYPELESS_FIRST + 1];
-static char *ffebld_op_string_[]
+static const char *ffebld_op_string_[]
=
{
#define FFEBLD_OP(KWD,NAME,ARITY) NAME,
@@ -5573,6 +5573,9 @@ ffebld_new_item (ffebld head, ffebld trail)
x->op = FFEBLD_opITEM;
x->u.item.head = head;
x->u.item.trail = trail;
+#ifdef FFECOM_itemHOOK
+ x->u.item.hook = FFECOM_itemNULL;
+#endif
return x;
}
@@ -5655,6 +5658,9 @@ ffebld_new_one (ffebldOp o, ffebld left)
#endif
x->op = o;
x->u.nonter.left = left;
+#ifdef FFECOM_nonterHOOK
+ x->u.nonter.hook = FFECOM_nonterNULL;
+#endif
return x;
}
@@ -5703,6 +5709,9 @@ ffebld_new_two (ffebldOp o, ffebld left, ffebld right)
x->op = o;
x->u.nonter.left = left;
x->u.nonter.right = right;
+#ifdef FFECOM_nonterHOOK
+ x->u.nonter.hook = FFECOM_nonterNULL;
+#endif
return x;
}
@@ -5745,7 +5754,7 @@ ffebld_pool_push (mallocPool pool)
Returns a short string (uppercase) containing the name of the op. */
-char *
+const char *
ffebld_op_string (ffebldOp o)
{
if (o >= ARRAY_SIZE (ffebld_op_string_))
diff --git a/contrib/gcc/f/bld.h b/contrib/gcc/f/bld.h
index d3b613ef..ddbd448 100644
--- a/contrib/gcc/f/bld.h
+++ b/contrib/gcc/f/bld.h
@@ -1,6 +1,6 @@
/* bld.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -406,12 +406,18 @@ struct _ffebld_
{
ffebld left;
ffebld right;
+#ifdef FFECOM_nonterHOOK
+ ffecomNonter hook; /* Whatever the compiler/backend wants! */
+#endif
}
nonter;
struct
{
ffebld head;
ffebld trail;
+#ifdef FFECOM_itemHOOK
+ ffecomItem hook; /* Whatever the compiler/backend wants! */
+#endif
}
item;
struct
@@ -726,7 +732,7 @@ ffebld ffebld_new_symter (ffesymbol s, ffeintrinGen gen, ffeintrinSpec spec,
ffeintrinImp imp);
ffebld ffebld_new_one (ffebldOp o, ffebld left);
ffebld ffebld_new_two (ffebldOp o, ffebld left, ffebld right);
-char *ffebld_op_string (ffebldOp o);
+const char *ffebld_op_string (ffebldOp o);
void ffebld_pool_pop (void);
void ffebld_pool_push (mallocPool pool);
ffetargetCharacterSize ffebld_size_max (ffebld b);
@@ -748,6 +754,7 @@ ffetargetCharacterSize ffebld_size_max (ffebld b);
#define ffebld_arrter_set_pad(b,p) ((b)->u.arrter.pad = (p))
#define ffebld_arrter_set_size(b,s) ((b)->u.arrter.size = (s))
#define ffebld_arrter_size(b) ((b)->u.arrter.size)
+#define ffebld_basictype(b) (ffeinfo_basictype (ffebld_info ((b))))
#if FFEBLD_whereconstCURRENT_ == FFEBLD_whereconstPROGUNIT_
#define ffebld_constant_pool() ffe_pool_program_unit()
#elif FFEBLD_whereconstCURRENT_ == FFEBLD_whereconstFILE_
@@ -944,6 +951,10 @@ ffetargetCharacterSize ffebld_size_max (ffebld b);
#define ffebld_init_3()
#define ffebld_init_4()
#define ffebld_init_list(l,b) (*(l) = NULL, *(b) = (l))
+#define ffebld_item_hook(b) ((b)->u.item.hook)
+#define ffebld_item_set_hook(b,h) ((b)->u.item.hook = (h))
+#define ffebld_kind(b) (ffeinfo_kind (ffebld_info ((b))))
+#define ffebld_kindtype(b) (ffeinfo_kindtype (ffebld_info ((b))))
#define ffebld_labter(b) ((b)->u.labter)
#define ffebld_labtok(b) ((b)->u.labtok)
#define ffebld_left(b) ((b)->u.nonter.left)
@@ -987,8 +998,11 @@ ffetargetCharacterSize ffebld_size_max (ffebld b);
#define ffebld_new_arrayref(l,r) ffebld_new_two(FFEBLD_opARRAYREF,(l),(r))
#define ffebld_new_substr(l,r) ffebld_new_two(FFEBLD_opSUBSTR,(l),(r))
#define ffebld_new_impdo(l,r) ffebld_new_two(FFEBLD_opIMPDO,(l),(r))
+#define ffebld_nonter_hook(b) ((b)->u.nonter.hook)
+#define ffebld_nonter_set_hook(b,h) ((b)->u.nonter.hook = (h))
#define ffebld_op(b) ((b)->op)
#define ffebld_pool() (ffebld_pool_stack_.pool)
+#define ffebld_rank(b) (ffeinfo_rank (ffebld_info ((b))))
#define ffebld_right(b) ((b)->u.nonter.right)
#define ffebld_set_accter(b,a) ((b)->u.accter.array = (a))
#define ffebld_set_arrter(b,a) ((b)->u.arrter.array = (a))
@@ -1000,8 +1014,8 @@ ffetargetCharacterSize ffebld_size_max (ffebld b);
#define ffebld_set_left(b,l) ((b)->u.nonter.left = (l))
#define ffebld_set_right(b,r) ((b)->u.nonter.right = (r))
#define ffebld_set_trail(b,t) ((b)->u.item.trail = (t))
-#define ffebld_size(b) (ffeinfo_size((b)->info))
-#define ffebld_size_known(b) ffebld_size(b)
+#define ffebld_size(b) (ffeinfo_size (ffebld_info ((b))))
+#define ffebld_size_known(b) ffebld_size((b))
#define ffebld_symter(b) ((b)->u.symter.symbol)
#define ffebld_symter_generic(b) ((b)->u.symter.generic)
#define ffebld_symter_doiter(b) ((b)->u.symter.do_iter)
@@ -1018,6 +1032,7 @@ ffetargetCharacterSize ffebld_size_max (ffebld b);
#define ffebld_terminate_3()
#define ffebld_terminate_4()
#define ffebld_trail(b) ((b)->u.item.trail)
+#define ffebld_where(b) (ffeinfo_where (ffebld_info ((b))))
/* End of #include file. */
diff --git a/contrib/gcc/f/bugs.texi b/contrib/gcc/f/bugs.texi
index 52c9287..3f4cd90 100644
--- a/contrib/gcc/f/bugs.texi
+++ b/contrib/gcc/f/bugs.texi
@@ -1,20 +1,40 @@
-@c Copyright (C) 1995-1998 Free Software Foundation, Inc.
+@c Copyright (C) 1995-1999 Free Software Foundation, Inc.
@c This is part of the G77 manual.
@c For copying conditions, see the file g77.texi.
@c The text of this file appears in the file BUGS
@c in the G77 distribution, as well as in the G77 manual.
-@c 1999-03-13
+@c Keep this the same as the dates above, since it's used
+@c in the standalone derivations of this file (e.g. BUGS).
+@set copyrights-bugs 1995-1999
-@ifset BUGSONLY
-@set which-g77 @code{egcs}-1.1.2
+@set last-update-bugs 1999-06-29
+
+@include root.texi
+
+@ifset DOC-BUGS
+@c The immediately following lines apply to the BUGS file
+@c which is derived from this file.
+@emph{Note:} This file is automatically generated from the files
+@file{bugs0.texi} and @file{bugs.texi}.
+@file{BUGS} is @emph{not} a source file,
+although it is normally included within source distributions.
+
+This file lists known bugs in the @value{which-g77} version
+of the GNU Fortran compiler.
+Copyright (C) @value{copyrights-bugs} Free Software Foundation, Inc.
+You may copy, distribute, and modify it freely as long as you preserve
+this copyright notice and permission notice.
+
+@node Top,,, (dir)
+@chapter Known Bugs In GNU Fortran
@end ifset
-@ifclear BUGSONLY
-@node Actual Bugs
-@section Actual Bugs We Haven't Fixed Yet
-@end ifclear
+@ifset DOC-G77
+@node Known Bugs
+@section Known Bugs In GNU Fortran
+@end ifset
This section identifies bugs that @code{g77} @emph{users}
might run into in the @value{which-g77} version
@@ -25,97 +45,64 @@ sets of code are at least somewhat under the control
of (and necessarily intertwined with) @code{g77},
so it isn't worth separating them out.
-@ifset last-up-date
+@ifset DOC-G77
For information on bugs in @emph{other} versions of @code{g77},
-@ref{News,,News About GNU Fortran}.
+see @ref{News,,News About GNU Fortran}.
+There, lists of bugs fixed in various versions of @code{g77}
+can help determine what bugs existed in prior versions.
@end ifset
-@ifset BUGSONLY
+@ifset DOC-BUGS
For information on bugs in @emph{other} versions of @code{g77},
-see @file{egcs/gcc/f/NEWS}.
+see @file{@value{path-g77}/NEWS}.
+There, lists of bugs fixed in various versions of @code{g77}
+can help determine what bugs existed in prior versions.
+@end ifset
+
+@ifset DEVELOPMENT
+@emph{Warning:} The information below is still under development,
+and might not accurately reflect the @code{g77} code base
+of which it is a part.
+Efforts are made to keep it somewhat up-to-date,
+but they are particularly concentrated
+on any version of this information
+that is distributed as part of a @emph{released} @code{g77}.
+
+In particular, while this information is intended to apply to
+the @value{which-g77} version of @code{g77},
+only an official @emph{release} of that version
+is expected to contain documentation that is
+most consistent with the @code{g77} product in that version.
@end ifset
An online, ``live'' version of this document
-(derived directly from the up-to-date mainline version
+(derived directly from the mainline, development version
of @code{g77} within @code{egcs})
-is available at
-@uref{http://egcs.cygnus.com/onlinedocs/g77_bugs.html}.
+is available via
+@uref{http://www.gnu.org/software/gcc/onlinedocs/g77_bugs.html}.
+Follow the ``Known Bugs'' link.
-@ifset last-up-date
+@ifset DOC-G77
For information on bugs that might afflict people who
configure, port, build, and install @code{g77},
-@ref{Problems Installing}.
+see @ref{Problems Installing}.
@end ifset
-@ifset BUGSONLY
+@ifset DOC-BUGS
For information on bugs that might afflict people who
configure, port, build, and install @code{g77},
-see ``Problems Installing'' in @file{egcs/gcc/f/INSTALL}.
+see "Problems Installing" in @file{@value{path-g77}/INSTALL}.
@end ifset
-@itemize @bullet
-@item
-@code{g77} generates bad code for assignments,
-or other conversions,
-of @code{REAL} or @code{COMPLEX} constant expressions
-to type @code{INTEGER(KIND=2)}
-(often referred to as @code{INTEGER*8}).
-
-For example, @samp{INTEGER*8 J; J = 4E10} is miscompiled
-on some systems---the wrong value is stored in @var{J}.
-
-@item
-The @code{IDate} Intrinsic (VXT)
-fails to return the year in the documented, non-Y2K-compliant range
-of 0--99,
-instead returning 100 for the year 2000.
-
-@c Fixed in @code{egcs} 1.2.
-
-@item
-Year 2000 (Y2K) compliance information
-is missing from the documentation.
-
-@c Fixed in @code{egcs} 1.2.
-
-@item
-@code{g77} crashes when compiling
-I/O statements using keywords that define @code{INTEGER} values,
-such as @samp{IOSTAT=@var{j}},
-where @var{j} is other than default @code{INTEGER}
-(such as @code{INTEGER*2}).
-
-@c Fixed in @code{egcs} 1.2.
-
-@item
-The @samp{-ax} option is not obeyed when compiling Fortran programs.
-(It is not passed to the @file{f771} driver.)
-
-@c Fixed in @code{egcs} 1.2.
-
-@item
-@code{g77} fails to warn about a reference to a function
-when the corresponding @emph{subsequent} function program unit
-disagrees with the reference concerning the type of the function.
-
-@c Fixed in @code{egcs} 1.2.
-
-@item
-@c Tim Prince discovered this.
-Automatic arrays possibly aren't working on HP-UX systems,
-at least in HP-UX version 10.20.
-Writing into them apparently causes over-writing
-of statically declared data in the main program.
-This probably means the arrays themselves are being under-allocated,
-or pointers to them being improperly handled,
-e.g. not passed to other procedures as they should be.
+The following information was last updated on @value{last-update-bugs}:
+@itemize @bullet
@item
@code{g77} fails to warn about
use of a ``live'' iterative-DO variable
as an implied-DO variable
-in a @samp{WRITE} or @samp{PRINT} statement
-(although it does warn about this in a @samp{READ} statement).
+in a @code{WRITE} or @code{PRINT} statement
+(although it does warn about this in a @code{READ} statement).
@item
Something about @code{g77}'s straightforward handling of
@@ -153,7 +140,7 @@ This is to be fixed in version 0.6, when @code{g77} will use the
@cindex compiler memory usage
@cindex memory usage, of compiler
@cindex large aggregate areas
-@cindex initialization
+@cindex initialization, bug
@cindex DATA statement
@cindex statements, DATA
@item
@@ -179,7 +166,7 @@ improvements to the compiler.)
Note that @code{g77} does display a warning message to
notify the user before the compiler appears to hang.
-@ifset last-up-date
+@ifset DOC-G77
@xref{Large Initialization,,Initialization of Large Aggregate Areas},
for information on how to change the point at which
@code{g77} decides to issue this warning.
@@ -201,7 +188,7 @@ As of Version 0.5.19, a temporary kludge solution is provided whereby
some rudimentary information on a member is written as a string that
is the member's value as a character string.
-@ifset last-up-date
+@ifset DOC-G77
@xref{Code Gen Options,,Options for Code Generation Conventions},
for information on the @samp{-fdebug-kludge} option.
@end ifset
@@ -213,8 +200,8 @@ for information on the @samp{-fdebug-kludge} option.
@item
When debugging, after starting up the debugger but before being able
to see the source code for the main program unit, the user must currently
-set a breakpoint at @samp{MAIN__} (or @samp{MAIN___} or @samp{MAIN_} if
-@samp{MAIN__} doesn't exist)
+set a breakpoint at @code{MAIN__} (or @code{MAIN___} or @code{MAIN_} if
+@code{MAIN__} doesn't exist)
and run the program until it hits the breakpoint.
At that point, the
main program unit is activated and about to execute its first
@@ -250,23 +237,6 @@ This problem is largely resolved as of version 0.5.23.
Version 0.6 should solve most or all remaining problems
(such as cross-compiling involving 64-bit machines).
-@cindex COMPLEX support
-@cindex support, COMPLEX
-@item
-Maintainers of gcc report that the back end definitely has ``broken''
-support for @code{COMPLEX} types.
-Based on their input, it seems many of
-the problems affect only the more-general facilities for gcc's
-@code{__complex__} type, such as @code{__complex__ int}
-(where the real and imaginary parts are integers) that GNU
-Fortran does not use.
-
-Version 0.5.20 of @code{g77} works around this
-problem by not using the back end's support for @code{COMPLEX}.
-The new option @samp{-fno-emulate-complex} avoids the work-around,
-reverting to using the same ``broken'' mechanism as that used
-by versions of @code{g77} prior to 0.5.20.
-
@cindex padding
@cindex structures
@cindex common blocks
@@ -285,42 +255,6 @@ of specifications of alignment requirements and preferences for targets,
and front ends like @code{g77} should take advantage of this
when it becomes available.
-@cindex alignment
-@cindex double-precision performance
-@cindex -malign-double
-@item
-The x86 target's @samp{-malign-double} option
-no longer reliably aligns double-precision variables and arrays
-when they are placed in the stack frame.
-
-This can significantly reduce the performance of some applications,
-even on a run-to-run basis
-(that is, performance measurements can vary fairly widely
-depending on whether frequently used variables are properly aligned,
-and that can change from one program run to the next,
-even from one procedure call to the next).
-
-Versions 0.5.22 and earlier of @code{g77}
-included a patch to @code{gcc} that enabled this,
-but that patch has been deemed an improper (probably buggy) one
-for version 2.8 of @code{gcc} and for @code{egcs}.
-
-Note that version 1.1 of @code{egcs}
-aligns double-precision variables and arrays
-when they are in static storage
-even if @samp{-malign-double} is not specified.
-
-There is ongoing investigation into
-how to make @samp{-malign-double} work properly,
-also into how to make it unnecessary to get
-all double-precision variables and arrays aligned
-when such alignment would not violate
-the relevant specifications for processor
-and inter-procedural interfaces.
-
-For a suite of programs to test double-precision alignment,
-see @uref{ftp://alpha.gnu.org/gnu/g77/align/}.
-
@cindex complex performance
@cindex aliasing
@item
diff --git a/contrib/gcc/f/bugs0.texi b/contrib/gcc/f/bugs0.texi
index e8f6d22..9636f4d 100644
--- a/contrib/gcc/f/bugs0.texi
+++ b/contrib/gcc/f/bugs0.texi
@@ -1,17 +1,9 @@
\input texinfo @c -*-texinfo-*-
-@c %**start of header
+@c %**start of header
@setfilename BUGS
-@set BUGSONLY
@c %**end of header
-@c The immediately following lines apply to the BUGS file
-@c which is generated using this file.
-This file lists known bugs in the GNU Fortran compiler.
-Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-You may copy, distribute, and modify it freely as long as you preserve
-this copyright notice and permission notice.
-
-@node Top,,, (dir)
-@chapter Bugs in GNU Fortran
+@c This tells bugs.texi that it's generating just the BUGS file.
+@set DOC-BUGS
@include bugs.texi
@bye
diff --git a/contrib/gcc/f/com-rt.def b/contrib/gcc/f/com-rt.def
index 6ceaf17..cb3a5f1 100644
--- a/contrib/gcc/f/com-rt.def
+++ b/contrib/gcc/f/com-rt.def
@@ -1,6 +1,6 @@
/* com-rt.def -- Public #include File (module.h template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -66,6 +66,7 @@ DEFGFRT (FFECOM_gfrtCMP, "s_cmp", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
DEFGFRT (FFECOM_gfrtCOPY, "s_copy", FFECOM_rttypeVOID_, 0, FALSE, FALSE)
DEFGFRT (FFECOM_gfrtPAUSE, "s_paus", FFECOM_rttypeVOID_, 0, FALSE, FALSE)
DEFGFRT (FFECOM_gfrtSTOP, "s_stop", FFECOM_rttypeVOID_, 0, TRUE, FALSE)
+DEFGFRT (FFECOM_gfrtRANGE, "s_rnge", FFECOM_rttypeINTEGER_, 0, TRUE, FALSE)
DEFGFRT (FFECOM_gfrtSRDUE, "s_rdue", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
DEFGFRT (FFECOM_gfrtERDUE, "e_rdue", FFECOM_rttypeINTEGER_, 0, FALSE, FALSE)
@@ -142,7 +143,7 @@ DEFGFRT (FFECOM_gfrtDACOS, "d_acos", FFECOM_rttypeDOUBLE_, "&d", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtDASIN, "d_asin", FFECOM_rttypeDOUBLE_, "&d", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtDATAN, "d_atan", FFECOM_rttypeDOUBLE_, "&d", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtDATAN2, "d_atn2", FFECOM_rttypeDOUBLE_, "&d", FALSE, FALSE)
-DEFGFRT (FFECOM_gfrtDATE, "G77_date_0", FFECOM_rttypeVOID_, "&a", FALSE, FALSE)
+DEFGFRT (FFECOM_gfrtDATE, "G77_date_y2kbug_0", FFECOM_rttypeVOID_, "&a", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtDATE_AND_TIME, "G77_date_and_time_0", FFECOM_rttypeVOID_, "&a&a&a&i", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtL_BESJ0, "j0", FFECOM_rttypeDOUBLE_, "d", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtL_BESJ1, "j1", FFECOM_rttypeDOUBLE_, "d", FALSE, FALSE)
@@ -242,7 +243,7 @@ DEFGFRT (FFECOM_gfrtTIME, "G77_time_0", FFECOM_rttypeLONGINT_, 0, FALSE, FALSE)
DEFGFRT (FFECOM_gfrtTTYNAM, "G77_ttynam_0", FFECOM_rttypeCHARACTER_, "&i", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtUNLINK, "G77_unlink_0", FFECOM_rttypeINTEGER_, "&a", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtUMASK, "G77_umask_0", FFECOM_rttypeINTEGER_, "&i", FALSE, FALSE)
-DEFGFRT (FFECOM_gfrtVXTIDATE, "G77_vxtidate_0", FFECOM_rttypeVOID_, "&i&i&i", FALSE, FALSE)
+DEFGFRT (FFECOM_gfrtVXTIDATE, "G77_vxtidate_y2kbug_0", FFECOM_rttypeVOID_, "&i&i&i", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtVXTTIME, "G77_vxttime_0", FFECOM_rttypeVOID_, "&a", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtCDABS, "z_abs", FFECOM_rttypeDOUBLE_, "&e", FALSE, FALSE)
DEFGFRT (FFECOM_gfrtCDCOS, "z_cos", FFECOM_rttypeDBLCMPLX_F2C_, "&e", FALSE, TRUE)
diff --git a/contrib/gcc/f/com.c b/contrib/gcc/f/com.c
index 9db1f84..c326fed 100644
--- a/contrib/gcc/f/com.c
+++ b/contrib/gcc/f/com.c
@@ -1,6 +1,6 @@
/* com.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -60,9 +60,9 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
is_nested, is_public);
// for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
store_parm_decls (is_main_program);
- ffecom_start_compstmt_ ();
+ ffecom_start_compstmt ();
// for stmts and decls inside function, do appropriate things;
- ffecom_end_compstmt_ ();
+ ffecom_end_compstmt ();
finish_function (is_nested);
if (is_nested) pop_f_function_context ();
if (is_nested) resume_momentary (yes);
@@ -213,8 +213,6 @@ typedef struct { unsigned :16, :16, :16; } vms_ino_t;
/* Externals defined here. */
-#define FFECOM_FASTER_ARRAY_REFS 0 /* Generates faster code? */
-
#if FFECOM_targetCURRENT == FFECOM_targetGCC
/* tree.h declares a bunch of stuff that it expects the front end to
@@ -231,8 +229,8 @@ tree unsigned_type_node;
tree char_type_node;
tree current_function_decl;
-/* ~~tree.h SHOULD declare this, because toplev.c and dwarfout.c reference
- it. */
+/* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
+ reference it. */
char *language_string = "GNU F77";
@@ -302,6 +300,8 @@ ffecomSymbol ffecom_symbol_null_
NULL_TREE,
NULL_TREE,
NULL_TREE,
+ NULL_TREE,
+ false
};
ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
@@ -367,7 +367,6 @@ typedef enum
#if FFECOM_targetCURRENT == FFECOM_targetGCC
typedef struct _ffecom_concat_list_ ffecomConcatList_;
-typedef struct _ffecom_temp_ *ffecomTemp_;
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
/* Private include files. */
@@ -384,24 +383,12 @@ struct _ffecom_concat_list_
ffetargetCharacterSize minlen;
ffetargetCharacterSize maxlen;
};
-
-struct _ffecom_temp_
- {
- ffecomTemp_ next;
- tree type; /* Base type (w/o size/array applied). */
- tree t;
- ffetargetCharacterSize size;
- int elements;
- bool in_use;
- bool auto_pop;
- };
-
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
/* Static functions (internal). */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
-static tree ffecom_arglist_expr_ (char *argstring, ffebld args);
+static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
static tree ffecom_widest_expr_type_ (ffebld list);
static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
tree dest_size, tree source_tree,
@@ -409,18 +396,18 @@ static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
tree args, tree callee_commons,
bool scalar_args);
-static tree ffecom_build_f2c_string_ (int i, char *s);
+static tree ffecom_build_f2c_string_ (int i, const char *s);
static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
bool is_f2c_complex, tree type,
tree args, tree dest_tree,
ffebld dest, bool *dest_used,
- tree callee_commons, bool scalar_args);
+ tree callee_commons, bool scalar_args, tree hook);
static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
bool is_f2c_complex, tree type,
ffebld left, ffebld right,
tree dest_tree, ffebld dest,
bool *dest_used, tree callee_commons,
- bool scalar_args);
+ bool scalar_args, tree hook);
static void ffecom_char_args_x_ (tree *xitem, tree *length,
ffebld expr, bool with_null);
static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
@@ -432,27 +419,28 @@ static ffecomConcatList_
static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
ffetargetCharacterSize max);
-static void ffecom_debug_kludge_ (tree aggr, char *aggr_type, ffesymbol member,
- tree member_type, ffetargetOffset offset);
+static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
+ ffesymbol member, tree member_type,
+ ffetargetOffset offset);
static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
bool *dest_used, bool assignp, bool widenp);
static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
ffebld dest, bool *dest_used);
-static tree ffecom_expr_power_integer_ (ffebld left, ffebld right);
+static tree ffecom_expr_power_integer_ (ffebld expr);
static void ffecom_expr_transform_ (ffebld expr);
-static void ffecom_f2c_make_type_ (tree *type, int tcode, char *name);
+static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
int code);
static ffeglobal ffecom_finish_global_ (ffeglobal global);
static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
-static tree ffecom_get_appended_identifier_ (char us, char *text);
+static tree ffecom_get_appended_identifier_ (char us, const char *text);
static tree ffecom_get_external_identifier_ (ffesymbol s);
-static tree ffecom_get_identifier_ (char *text);
+static tree ffecom_get_identifier_ (const char *text);
static tree ffecom_gen_sfuncdef_ (ffesymbol s,
ffeinfoBasictype bt,
ffeinfoKindtype kt);
-static char *ffecom_gfrt_args_ (ffecomGfrt ix);
+static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
static tree ffecom_init_zero_ (tree decl);
static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
@@ -467,6 +455,8 @@ static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
#endif
+static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
+ ffebld source);
static void ffecom_push_dummy_decls_ (ffebld dumlist,
bool stmtfunc);
static void ffecom_start_progunit_ (void);
@@ -481,7 +471,7 @@ static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
tree *size, tree tree);
static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
tree dest_tree, ffebld dest,
- bool *dest_used);
+ bool *dest_used, tree hook);
static tree ffecom_type_localvar_ (ffesymbol s,
ffeinfoBasictype bt,
ffeinfoKindtype kt);
@@ -493,17 +483,20 @@ static tree ffecom_type_vardesc_ (void);
static tree ffecom_vardesc_ (ffebld expr);
static tree ffecom_vardesc_array_ (ffesymbol s);
static tree ffecom_vardesc_dims_ (ffesymbol s);
+static tree ffecom_convert_narrow_ (tree type, tree expr);
+static tree ffecom_convert_widen_ (tree type, tree expr);
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
/* These are static functions that parallel those found in the C front
end and thus have the same names. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
-static void bison_rule_compstmt_ (void);
+static tree bison_rule_compstmt_ (void);
static void bison_rule_pushlevel_ (void);
-static tree builtin_function (char *name, tree type,
+static tree builtin_function (const char *name, tree type,
enum built_in_function function_code,
- char *library_name);
+ const char *library_name);
+static void delete_block (tree block);
static int duplicate_decls (tree newdecl, tree olddecl);
static void finish_decl (tree decl, tree init, bool is_top_level);
static void finish_function (int nested);
@@ -514,6 +507,7 @@ static void pop_f_function_context (void);
static void push_f_function_context (void);
static void push_parm_decl (tree parm);
static tree pushdecl_top_level (tree decl);
+static int kept_level_p (void);
static tree storedecls (tree decls);
static void store_parm_decls (int is_main_program);
static tree start_decl (tree decl, bool is_top_level);
@@ -538,8 +532,6 @@ static bool ffecom_primary_entry_is_proc_;
static tree ffecom_outer_function_decl_;
static tree ffecom_previous_function_decl_;
static tree ffecom_which_entrypoint_decl_;
-static ffecomTemp_ ffecom_latest_temp_;
-static int ffecom_pending_calls_ = 0;
static tree ffecom_float_zero_ = NULL_TREE;
static tree ffecom_float_half_ = NULL_TREE;
static tree ffecom_double_zero_ = NULL_TREE;
@@ -562,6 +554,8 @@ static tree
static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
static bool ffecom_doing_entry_ = FALSE;
static bool ffecom_transform_only_dummies_ = FALSE;
+static int ffecom_typesize_pointer_;
+static int ffecom_typesize_integer1_;
/* Holds pointer-to-function expressions. */
@@ -575,7 +569,7 @@ static tree ffecom_gfrt_[FFECOM_gfrt]
/* Holds the external names of the functions. */
-static char *ffecom_gfrt_name_[FFECOM_gfrt]
+static const char *ffecom_gfrt_name_[FFECOM_gfrt]
=
{
#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
@@ -615,7 +609,7 @@ static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
/* String of codes for the function's arguments. */
-static char *ffecom_gfrt_argstring_[FFECOM_gfrt]
+static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
=
{
#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
@@ -634,17 +628,15 @@ static char *ffecom_gfrt_argstring_[FFECOM_gfrt]
it would be best to do something here to figure out automatically
from other information what type to use. */
-/* NOTE: g77 currently doesn't use these; see setting of sizetype and
- change that if you need to. -- jcb 09/01/91. */
+#ifndef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+#endif
#define ffecom_concat_list_count_(catlist) ((catlist).count)
#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
-#define ffecom_start_compstmt_ bison_rule_pushlevel_
-#define ffecom_end_compstmt_ bison_rule_compstmt_
-
#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
@@ -664,20 +656,27 @@ static char *ffecom_gfrt_argstring_[FFECOM_gfrt]
struct binding_level
{
- /* A chain of _DECL nodes for all variables, constants, functions, and
- typedef types. These are in the reverse of the order supplied. */
+ /* A chain of _DECL nodes for all variables, constants, functions,
+ and typedef types. These are in the reverse of the order supplied.
+ */
tree names;
- /* For each level (except not the global one), a chain of BLOCK nodes for
- all the levels that were entered and exited one level down. */
+ /* For each level (except not the global one),
+ a chain of BLOCK nodes for all the levels
+ that were entered and exited one level down. */
tree blocks;
- /* The BLOCK node for this level, if one has been preallocated. If 0, the
- BLOCK is allocated (if needed) when the level is popped. */
+ /* The BLOCK node for this level, if one has been preallocated.
+ If 0, the BLOCK is allocated (if needed) when the level is popped. */
tree this_block;
/* The binding level which this one is contained in (inherits from). */
struct binding_level *level_chain;
+
+ /* 0: no ffecom_prepare_* functions called at this level yet;
+ 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
+ 2: ffecom_prepare_end called. */
+ int prep_state;
};
#define NULL_BINDING_LEVEL (struct binding_level *) NULL
@@ -700,7 +699,7 @@ static struct binding_level *global_binding_level;
static struct binding_level clear_binding_level
=
-{NULL, NULL, NULL, NULL_BINDING_LEVEL};
+{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
/* Language-dependent contents of an identifier. */
@@ -747,6 +746,314 @@ static tree shadowed_labels;
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
+/* Return the subscript expression, modified to do range-checking.
+
+ `array' is the array to be checked against.
+ `element' is the subscript expression to check.
+ `dim' is the dimension number (starting at 0).
+ `total_dims' is the total number of dimensions (0 for CHARACTER substring).
+*/
+
+static tree
+ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
+ char *array_name)
+{
+ tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
+ tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
+ tree cond;
+ tree die;
+ tree args;
+
+ if (element == error_mark_node)
+ return element;
+
+ if (TREE_TYPE (low) != TREE_TYPE (element))
+ {
+ if (TYPE_PRECISION (TREE_TYPE (low))
+ > TYPE_PRECISION (TREE_TYPE (element)))
+ element = convert (TREE_TYPE (low), element);
+ else
+ {
+ low = convert (TREE_TYPE (element), low);
+ if (high)
+ high = convert (TREE_TYPE (element), high);
+ }
+ }
+
+ element = ffecom_save_tree (element);
+ cond = ffecom_2 (LE_EXPR, integer_type_node,
+ low,
+ element);
+ if (high)
+ {
+ cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
+ cond,
+ ffecom_2 (LE_EXPR, integer_type_node,
+ element,
+ high));
+ }
+
+ {
+ int len;
+ char *proc;
+ char *var;
+ tree arg3;
+ tree arg2;
+ tree arg1;
+ tree arg4;
+
+ switch (total_dims)
+ {
+ case 0:
+ var = xmalloc (strlen (array_name) + 20);
+ sprintf (&var[0], "%s[%s-substring]",
+ array_name,
+ dim ? "end" : "start");
+ len = strlen (var) + 1;
+ break;
+
+ case 1:
+ len = strlen (array_name) + 1;
+ var = array_name;
+ break;
+
+ default:
+ var = xmalloc (strlen (array_name) + 40);
+ sprintf (&var[0], "%s[subscript-%d-of-%d]",
+ array_name,
+ dim + 1, total_dims);
+ len = strlen (var) + 1;
+ break;
+ }
+
+ arg1 = build_string (len, var);
+
+ if (total_dims != 1)
+ free (var);
+
+ TREE_TYPE (arg1)
+ = build_type_variant (build_array_type (char_type_node,
+ build_range_type
+ (integer_type_node,
+ integer_one_node,
+ build_int_2 (len, 0))),
+ 1, 0);
+ TREE_CONSTANT (arg1) = 1;
+ TREE_STATIC (arg1) = 1;
+ arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
+ arg1);
+
+ /* s_rnge adds one to the element to print it, so bias against
+ that -- want to print a faithful *subscript* value. */
+ arg2 = convert (ffecom_f2c_ftnint_type_node,
+ ffecom_2 (MINUS_EXPR,
+ TREE_TYPE (element),
+ element,
+ convert (TREE_TYPE (element),
+ integer_one_node)));
+
+ proc = xmalloc ((len = strlen (input_filename)
+ + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
+ + 2));
+
+ sprintf (&proc[0], "%s/%s",
+ input_filename,
+ IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+ arg3 = build_string (len, proc);
+
+ free (proc);
+
+ TREE_TYPE (arg3)
+ = build_type_variant (build_array_type (char_type_node,
+ build_range_type
+ (integer_type_node,
+ integer_one_node,
+ build_int_2 (len, 0))),
+ 1, 0);
+ TREE_CONSTANT (arg3) = 1;
+ TREE_STATIC (arg3) = 1;
+ arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
+ arg3);
+
+ arg4 = convert (ffecom_f2c_ftnint_type_node,
+ build_int_2 (lineno, 0));
+
+ arg1 = build_tree_list (NULL_TREE, arg1);
+ arg2 = build_tree_list (NULL_TREE, arg2);
+ arg3 = build_tree_list (NULL_TREE, arg3);
+ arg4 = build_tree_list (NULL_TREE, arg4);
+ TREE_CHAIN (arg3) = arg4;
+ TREE_CHAIN (arg2) = arg3;
+ TREE_CHAIN (arg1) = arg2;
+
+ args = arg1;
+ }
+ die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
+ args, NULL_TREE);
+ TREE_SIDE_EFFECTS (die) = 1;
+
+ element = ffecom_3 (COND_EXPR,
+ TREE_TYPE (element),
+ cond,
+ element,
+ die);
+
+ return element;
+}
+
+/* Return the computed element of an array reference.
+
+ `item' is NULL_TREE, or the transformed pointer to the array.
+ `expr' is the original opARRAYREF expression, which is transformed
+ if `item' is NULL_TREE.
+ `want_ptr' is non-zero if a pointer to the element, instead of
+ the element itself, is to be returned. */
+
+static tree
+ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
+{
+ ffebld dims[FFECOM_dimensionsMAX];
+ int i;
+ int total_dims;
+ int flatten = ffe_is_flatten_arrays ();
+ int need_ptr;
+ tree array;
+ tree element;
+ tree tree_type;
+ tree tree_type_x;
+ char *array_name;
+ ffetype type;
+ ffebld list;
+
+ if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
+ array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
+ else
+ array_name = "[expr?]";
+
+ /* Build up ARRAY_REFs in reverse order (since we're column major
+ here in Fortran land). */
+
+ for (i = 0, list = ffebld_right (expr);
+ list != NULL;
+ ++i, list = ffebld_trail (list))
+ {
+ dims[i] = ffebld_head (list);
+ type = ffeinfo_type (ffebld_basictype (dims[i]),
+ ffebld_kindtype (dims[i]));
+ if (! flatten
+ && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
+ && ffetype_size (type) > ffecom_typesize_integer1_)
+ /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
+ pointers and 32-bit integers. Do the full 64-bit pointer
+ arithmetic, for codes using arrays for nonstandard heap-like
+ work. */
+ flatten = 1;
+ }
+
+ total_dims = i;
+
+ need_ptr = want_ptr || flatten;
+
+ if (! item)
+ {
+ if (need_ptr)
+ item = ffecom_ptr_to_expr (ffebld_left (expr));
+ else
+ item = ffecom_expr (ffebld_left (expr));
+
+ if (item == error_mark_node)
+ return item;
+
+ if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
+ && ! mark_addressable (item))
+ return error_mark_node;
+ }
+
+ if (item == error_mark_node)
+ return item;
+
+ if (need_ptr)
+ {
+ tree min;
+
+ for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
+ i >= 0;
+ --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
+ {
+ min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
+ element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
+ if (ffe_is_subscript_check ())
+ element = ffecom_subscript_check_ (array, element, i, total_dims,
+ array_name);
+ if (element == error_mark_node)
+ return element;
+
+ /* Widen integral arithmetic as desired while preserving
+ signedness. */
+ tree_type = TREE_TYPE (element);
+ tree_type_x = tree_type;
+ if (tree_type
+ && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
+ && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
+ tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
+
+ if (TREE_TYPE (min) != tree_type_x)
+ min = convert (tree_type_x, min);
+ if (TREE_TYPE (element) != tree_type_x)
+ element = convert (tree_type_x, element);
+
+ item = ffecom_2 (PLUS_EXPR,
+ build_pointer_type (TREE_TYPE (array)),
+ item,
+ size_binop (MULT_EXPR,
+ size_in_bytes (TREE_TYPE (array)),
+ fold (build (MINUS_EXPR,
+ tree_type_x,
+ element,
+ min))));
+ }
+ if (! want_ptr)
+ {
+ item = ffecom_1 (INDIRECT_REF,
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
+ item);
+ }
+ }
+ else
+ {
+ for (--i;
+ i >= 0;
+ --i)
+ {
+ array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
+
+ element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
+ if (ffe_is_subscript_check ())
+ element = ffecom_subscript_check_ (array, element, i, total_dims,
+ array_name);
+ if (element == error_mark_node)
+ return element;
+
+ /* Widen integral arithmetic as desired while preserving
+ signedness. */
+ tree_type = TREE_TYPE (element);
+ tree_type_x = tree_type;
+ if (tree_type
+ && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
+ && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
+ tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
+
+ element = convert (tree_type_x, element);
+
+ item = ffecom_2 (ARRAY_REF,
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
+ item,
+ element);
+ }
+ }
+
+ return item;
+}
/* This is like gcc's stabilize_reference -- in fact, most of the code
comes from that -- but it handles the situation where the reference
@@ -1095,7 +1402,7 @@ ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
-ffecom_arglist_expr_ (char *c, ffebld expr)
+ffecom_arglist_expr_ (const char *c, ffebld expr)
{
tree list;
tree *plist = &list;
@@ -1279,6 +1586,48 @@ ffecom_widest_expr_type_ (ffebld list)
}
#endif
+/* Check whether a partial overlap between two expressions is possible.
+
+ Can *starting* to write a portion of expr1 change the value
+ computed (perhaps already, *partially*) by expr2?
+
+ Currently, this is a concern only for a COMPLEX expr1. But if it
+ isn't in COMMON or local EQUIVALENCE, since we don't support
+ aliasing of arguments, it isn't a concern. */
+
+static bool
+ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2)
+{
+ ffesymbol sym;
+ ffestorag st;
+
+ switch (ffebld_op (expr1))
+ {
+ case FFEBLD_opSYMTER:
+ sym = ffebld_symter (expr1);
+ break;
+
+ case FFEBLD_opARRAYREF:
+ if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
+ return FALSE;
+ sym = ffebld_symter (ffebld_left (expr1));
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
+ && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
+ || ! (st = ffesymbol_storage (sym))
+ || ! ffestorag_parent (st)))
+ return FALSE;
+
+ /* It's in COMMON or local EQUIVALENCE. */
+
+ return TRUE;
+}
+
/* Check whether dest and source might overlap. ffebld versions of these
might or might not be passed, will be NULL if not.
@@ -1517,14 +1866,14 @@ ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
-ffecom_build_f2c_string_ (int i, char *s)
+ffecom_build_f2c_string_ (int i, const char *s)
{
if (!ffe_is_f2c_library ())
return build_string (i, s);
{
char *tmp;
- char *p;
+ const char *p;
char *q;
char space[34];
tree t;
@@ -1558,7 +1907,7 @@ static tree
ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
tree type, tree args, tree dest_tree,
ffebld dest, bool *dest_used, tree callee_commons,
- bool scalar_args)
+ bool scalar_args, tree hook)
{
tree item;
tree tempvar;
@@ -1578,10 +1927,15 @@ ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
callee_commons,
scalar_args))
{
- tempvar = ffecom_push_tempvar (ffecom_tree_type
+#ifdef HOHO
+ tempvar = ffecom_make_tempvar (ffecom_tree_type
[FFEINFO_basictypeCOMPLEX][kt],
FFETARGET_charactersizeNONE,
- -1, TRUE);
+ -1);
+#else
+ tempvar = hook;
+ assert (tempvar);
+#endif
}
else
{
@@ -1593,7 +1947,7 @@ ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
item
= build_tree_list (NULL_TREE,
ffecom_1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (tempvar)),
+ build_pointer_type (TREE_TYPE (tempvar)),
tempvar));
TREE_CHAIN (item) = args;
@@ -1622,17 +1976,15 @@ static tree
ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
tree type, ffebld left, ffebld right,
tree dest_tree, ffebld dest, bool *dest_used,
- tree callee_commons, bool scalar_args)
+ tree callee_commons, bool scalar_args, tree hook)
{
tree left_tree;
tree right_tree;
tree left_length;
tree right_length;
- ffecom_push_calltemps ();
left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
- ffecom_pop_calltemps ();
left_tree = build_tree_list (NULL_TREE, left_tree);
right_tree = build_tree_list (NULL_TREE, right_tree);
@@ -1655,17 +2007,11 @@ ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
dest_tree, dest, dest_used, callee_commons,
- scalar_args);
+ scalar_args, hook);
}
#endif
-/* ffecom_char_args_x_ -- Return ptr/length args for char subexpression
-
- tree ptr_arg;
- tree length_arg;
- ffebld expr;
- bool with_null;
- ffecom_char_args_x_(&ptr_arg,&length_arg,expr,with_null);
+/* Return ptr/length args for char subexpression
Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
subexpressions by constructing the appropriate trees for the ptr-to-
@@ -1691,15 +2037,17 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
newlen = ffetarget_length_character1 (val);
if (with_null)
{
+ /* Begin FFETARGET-NULL-KLUDGE. */
if (newlen != 0)
- ++newlen; /* begin FFETARGET-NULL-KLUDGE. */
+ ++newlen;
}
*length = build_int_2 (newlen, 0);
TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
high = build_int_2 (newlen, 0);
TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
- item = build_string (newlen, /* end FFETARGET-NULL-KLUDGE. */
+ item = build_string (newlen,
ffetarget_text_character1 (val));
+ /* End FFETARGET-NULL-KLUDGE. */
TREE_TYPE (item)
= build_type_variant
(build_array_type
@@ -1737,7 +2085,8 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
}
else if (item == error_mark_node)
*length = error_mark_node;
- else /* FFEINFO_kindFUNCTION: */
+ else
+ /* FFEINFO_kindFUNCTION. */
*length = NULL_TREE;
if (!ffesymbol_hook (s).addr
&& (item != error_mark_node))
@@ -1749,13 +2098,7 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
case FFEBLD_opARRAYREF:
{
- ffebld dims[FFECOM_dimensionsMAX];
- tree array;
- int i;
-
- ffecom_push_calltemps ();
ffecom_char_args_ (&item, length, ffebld_left (expr));
- ffecom_pop_calltemps ();
if (item == error_mark_node || *length == error_mark_node)
{
@@ -1763,26 +2106,7 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
break;
}
- /* Build up ARRAY_REFs in reverse order (since we're column major
- here in Fortran land). */
-
- for (i = 0, expr = ffebld_right (expr);
- expr != NULL;
- expr = ffebld_trail (expr))
- dims[i++] = ffebld_head (expr);
-
- for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
- i >= 0;
- --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
- {
- item = ffecom_2 (PLUS_EXPR, build_pointer_type (TREE_TYPE (array)),
- item,
- size_binop (MULT_EXPR,
- size_in_bytes (TREE_TYPE (array)),
- size_binop (MINUS_EXPR,
- ffecom_expr (dims[i]),
- TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
- }
+ item = ffecom_arrayref_ (item, expr, 1);
}
break;
@@ -1793,6 +2117,9 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
ffebld thing = ffebld_right (expr);
tree start_tree;
tree end_tree;
+ char *char_name;
+ ffebld left_symter;
+ tree array;
assert (ffebld_op (thing) == FFEBLD_opITEM);
start = ffebld_head (thing);
@@ -1800,9 +2127,17 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
assert (ffebld_trail (thing) == NULL);
end = ffebld_head (thing);
- ffecom_push_calltemps ();
+ /* Determine name for pretty-printing range-check errors. */
+ for (left_symter = ffebld_left (expr);
+ left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
+ left_symter = ffebld_left (left_symter))
+ ;
+ if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
+ char_name = ffesymbol_text (ffebld_symter (left_symter));
+ else
+ char_name = "[expr?]";
+
ffecom_char_args_ (&item, length, ffebld_left (expr));
- ffecom_pop_calltemps ();
if (item == error_mark_node || *length == error_mark_node)
{
@@ -1810,14 +2145,22 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
break;
}
+ array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
+
+ /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
+
if (start == NULL)
{
if (end == NULL)
;
else
{
+ end_tree = ffecom_expr (end);
+ if (ffe_is_subscript_check ())
+ end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
+ char_name);
end_tree = convert (ffecom_f2c_ftnlen_type_node,
- ffecom_expr (end));
+ end_tree);
if (end_tree == error_mark_node)
{
@@ -1830,8 +2173,12 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
}
else
{
+ start_tree = ffecom_expr (start);
+ if (ffe_is_subscript_check ())
+ start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
+ char_name);
start_tree = convert (ffecom_f2c_ftnlen_type_node,
- ffecom_expr (start));
+ start_tree);
if (start_tree == error_mark_node)
{
@@ -1859,8 +2206,12 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
}
else
{
+ end_tree = ffecom_expr (end);
+ if (ffe_is_subscript_check ())
+ end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
+ char_name);
end_tree = convert (ffecom_f2c_ftnlen_type_node,
- ffecom_expr (end));
+ end_tree);
if (end_tree == error_mark_node)
{
@@ -1887,7 +2238,8 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
ffecomGfrt ix;
if (size == FFETARGET_charactersizeNONE)
- size = 24; /* ~~~~ Kludge alert! This should someday be fixed. */
+ /* ~~Kludge alert! This should someday be fixed. */
+ size = 24;
*length = build_int_2 (size, 0);
TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
@@ -1896,7 +2248,8 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
== FFEINFO_whereINTRINSIC)
{
if (size == 1)
- { /* Invocation of an intrinsic returning CHARACTER*1. */
+ {
+ /* Invocation of an intrinsic returning CHARACTER*1. */
item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
NULL, NULL);
break;
@@ -1924,14 +2277,16 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
item = ffecom_1_fn (item);
}
- assert (ffecom_pending_calls_ != 0);
+#ifdef HOHO
tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
+#else
+ tempvar = ffebld_nonter_hook (expr);
+ assert (tempvar);
+#endif
tempvar = ffecom_1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (tempvar)),
tempvar);
- ffecom_push_calltemps ();
-
args = build_tree_list (NULL_TREE, tempvar);
if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
@@ -1957,16 +2312,12 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
item, args, NULL_TREE);
item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
tempvar);
-
- ffecom_pop_calltemps ();
}
break;
case FFEBLD_opCONVERT:
- ffecom_push_calltemps ();
ffecom_char_args_ (&item, length, ffebld_left (expr));
- ffecom_pop_calltemps ();
if (item == error_mark_node || *length == error_mark_node)
{
@@ -1983,9 +2334,13 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
tree args;
tree newlen;
- assert (ffecom_pending_calls_ != 0);
- tempvar = ffecom_push_tempvar (char_type_node,
- ffebld_size (expr), -1, TRUE);
+#ifdef HOHO
+ tempvar = ffecom_make_tempvar (char_type_node,
+ ffebld_size (expr), -1);
+#else
+ tempvar = ffebld_nonter_hook (expr);
+ assert (tempvar);
+#endif
tempvar = ffecom_1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (tempvar)),
tempvar);
@@ -1999,7 +2354,7 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
= build_tree_list (NULL_TREE, *length);
- item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args);
+ item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
TREE_SIDE_EFFECTS (item) = 1;
item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
tempvar);
@@ -2077,10 +2432,10 @@ ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
{
if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
tlen = ffecom_get_invented_identifier ("__g77_length_%s",
- ffesymbol_text (s), 0);
+ ffesymbol_text (s), -1);
else
tlen = ffecom_get_invented_identifier ("__g77_%s",
- "length", 0);
+ "length", -1);
tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
#if BUILT_FOR_270
DECL_ARTIFICIAL (tlen) = 1;
@@ -2177,7 +2532,8 @@ recurse: /* :::::::::::::::::::: */
case FFEBLD_opARRAYREF:
case FFEBLD_opFUNCREF:
case FFEBLD_opSUBSTR:
- break; /* ~~Do useful truncations here. */
+ /* ~~Do useful truncations here. */
+ break;
default:
assert ("op changed or inconsistent switches!" == NULL);
@@ -2238,12 +2594,7 @@ ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
}
#endif
-/* ffecom_concat_list_new_ -- Make list of concatenated string exprs
-
- ffecomConcatList_ catlist;
- ffebld expr; // Root expr of CHARACTER basictype.
- ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
- catlist = ffecom_concat_list_new_(expr,max);
+/* Make list of concatenated string exprs.
Returns a flattened list of concatenated subexpressions given a
tree of such expressions. */
@@ -2266,7 +2617,7 @@ ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
-ffecom_debug_kludge_ (tree aggr, char *aggr_type, ffesymbol member,
+ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
tree member_type UNUSED, ffetargetOffset offset)
{
tree value;
@@ -2521,7 +2872,7 @@ ffecom_do_entry_ (ffesymbol fn, int entrynum)
type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
result = ffecom_get_invented_identifier ("__g77_%s",
- "result", 0);
+ "result", -1);
/* Make length arg _and_ enhance type info for CHAR arg itself. */
@@ -2551,7 +2902,9 @@ ffecom_do_entry_ (ffesymbol fn, int entrynum)
store_parm_decls (0);
- ffecom_start_compstmt_ ();
+ ffecom_start_compstmt ();
+ /* Disallow temp vars at this level. */
+ current_binding_level->prep_state = 2;
/* Make local var to hold return type for multi-type master fn. */
@@ -2560,7 +2913,7 @@ ffecom_do_entry_ (ffesymbol fn, int entrynum)
yes = suspend_momentary ();
multi_retval = ffecom_get_invented_identifier ("__g77_%s",
- "multi_retval", 0);
+ "multi_retval", -1);
multi_retval = build_decl (VAR_DECL, multi_retval,
ffecom_multi_type_node_);
multi_retval = start_decl (multi_retval, FALSE);
@@ -2594,7 +2947,8 @@ ffecom_do_entry_ (ffesymbol fn, int entrynum)
if (ffebld_op (arg) != FFEBLD_opSYMTER)
continue;
s = ffebld_symter (arg);
- if (ffesymbol_hook (s).decl_tree == NULL_TREE)
+ if (ffesymbol_hook (s).decl_tree == NULL_TREE
+ || ffesymbol_hook (s).decl_tree == error_mark_node)
actarg = null_pointer_node; /* We don't have this arg. */
else
actarg = ffesymbol_hook (s).decl_tree;
@@ -2617,7 +2971,8 @@ ffecom_do_entry_ (ffesymbol fn, int entrynum)
continue; /* Only looking for CHARACTER arguments. */
if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
continue; /* Only looking for variables and arrays. */
- if (ffesymbol_hook (s).length_tree == NULL_TREE)
+ if (ffesymbol_hook (s).length_tree == NULL_TREE
+ || ffesymbol_hook (s).length_tree == error_mark_node)
actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
else
actarg = ffesymbol_hook (s).length_tree;
@@ -2719,7 +3074,7 @@ ffecom_do_entry_ (ffesymbol fn, int entrynum)
clear_momentary ();
}
- ffecom_end_compstmt_ ();
+ ffecom_end_compstmt ();
finish_function (0);
@@ -2975,65 +3330,14 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
return t;
case FFEBLD_opARRAYREF:
- {
- ffebld dims[FFECOM_dimensionsMAX];
-#if FFECOM_FASTER_ARRAY_REFS
- tree array;
-#endif
- int i;
-
-#if FFECOM_FASTER_ARRAY_REFS
- t = ffecom_ptr_to_expr (ffebld_left (expr));
-#else
- t = ffecom_expr (ffebld_left (expr));
-#endif
- if (t == error_mark_node)
- return t;
-
- if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
- && !mark_addressable (t))
- return error_mark_node; /* Make sure non-const ref is to
- non-reg. */
-
- /* Build up ARRAY_REFs in reverse order (since we're column major
- here in Fortran land). */
-
- for (i = 0, expr = ffebld_right (expr);
- expr != NULL;
- expr = ffebld_trail (expr))
- dims[i++] = ffebld_head (expr);
-
-#if FFECOM_FASTER_ARRAY_REFS
- for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t)));
- i >= 0;
- --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
- t = ffecom_2 (PLUS_EXPR,
- build_pointer_type (TREE_TYPE (array)),
- t,
- size_binop (MULT_EXPR,
- size_in_bytes (TREE_TYPE (array)),
- size_binop (MINUS_EXPR,
- ffecom_expr (dims[i]),
- TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
- t = ffecom_1 (INDIRECT_REF,
- TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
- t);
-#else
- while (i > 0)
- t = ffecom_2 (ARRAY_REF,
- TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
- t,
- ffecom_expr_ (dims[--i], NULL, NULL, NULL, FALSE, TRUE));
-#endif
-
- return t;
- }
+ return ffecom_arrayref_ (NULL_TREE, expr, 0);
case FFEBLD_opUPLUS:
left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
return ffecom_1 (NOP_EXPR, tree_type, left);
- case FFEBLD_opPAREN: /* ~~~Make sure Fortran rules respected here */
+ case FFEBLD_opPAREN:
+ /* ~~~Make sure Fortran rules respected here */
left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
return ffecom_1 (NOP_EXPR, tree_type, left);
@@ -3089,7 +3393,8 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
right = convert (tree_type, right);
}
return ffecom_tree_divide_ (tree_type, left, right,
- dest_tree, dest, dest_used);
+ dest_tree, dest, dest_used,
+ ffebld_nonter_hook (expr));
case FFEBLD_opPOWER:
{
@@ -3104,7 +3409,7 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
case FFEINFO_basictypeINTEGER:
if (1 || optimize)
{
- item = ffecom_expr_power_integer_ (left, right);
+ item = ffecom_expr_power_integer_ (expr);
if (item != NULL_TREE)
return item;
}
@@ -3221,7 +3526,8 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
&& ffecom_gfrt_complex_[code]),
tree_type, left, right,
dest_tree, dest, dest_used,
- NULL_TREE, FALSE);
+ NULL_TREE, FALSE,
+ ffebld_nonter_hook (expr));
}
case FFEBLD_opNOT:
@@ -3270,12 +3576,13 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
else
item = ffecom_1_fn (dt);
- ffecom_push_calltemps ();
if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
args = ffecom_list_expr (ffebld_right (expr));
else
args = ffecom_list_ptr_to_expr (ffebld_right (expr));
- ffecom_pop_calltemps ();
+
+ if (args == error_mark_node)
+ return error_mark_node;
item = ffecom_call_ (item, kt,
ffesymbol_is_f2c (s)
@@ -3285,7 +3592,8 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
tree_type,
args,
dest_tree, dest, dest_used,
- error_mark_node, FALSE);
+ error_mark_node, FALSE,
+ ffebld_nonter_hook (expr));
TREE_SIDE_EFFECTS (item) = 1;
return item;
@@ -3503,8 +3811,6 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
}
case FFEINFO_basictypeCHARACTER:
- ffecom_push_calltemps (); /* Even though we might not call. */
-
{
ffebld left = ffebld_left (expr);
ffebld right = ffebld_right (expr);
@@ -3536,10 +3842,7 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
if (left_tree == error_mark_node || left_length == error_mark_node
|| right_tree == error_mark_node
|| right_length == error_mark_node)
- {
- ffecom_pop_calltemps ();
- return error_mark_node;
- }
+ return error_mark_node;
if ((ffebld_size_known (left) == 1)
&& (ffebld_size_known (right) == 1))
@@ -3572,7 +3875,7 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
left_length);
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
= build_tree_list (NULL_TREE, right_length);
- item = ffecom_call_gfrt (FFECOM_gfrtCMP, item);
+ item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
item = ffecom_2 (code, integer_type_node,
item,
convert (TREE_TYPE (item),
@@ -3581,7 +3884,6 @@ ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
item = convert (tree_type, item);
}
- ffecom_pop_calltemps ();
return item;
default:
@@ -3783,8 +4085,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
case FFEINTRIN_impAINT:
case FFEINTRIN_impDINT:
-#if 0 /* ~~ someday implement FIX_TRUNC_EXPR
- yielding same type as arg */
+#if 0
+ /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
#else /* in the meantime, must use floor to avoid range problems with ints */
/* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
@@ -3800,14 +4102,16 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
build_tree_list (NULL_TREE,
convert (double_type_node,
- saved_expr1))),
+ saved_expr1)),
+ NULL_TREE),
ffecom_1 (NEGATE_EXPR, double_type_node,
ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
build_tree_list (NULL_TREE,
convert (double_type_node,
ffecom_1 (NEGATE_EXPR,
arg1_type,
- saved_expr1))))
+ saved_expr1))),
+ NULL_TREE)
))
);
#endif
@@ -3852,7 +4156,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
arg1_type,
saved_expr1,
convert (arg1_type,
- ffecom_float_half_))))),
+ ffecom_float_half_)))),
+ NULL_TREE),
ffecom_1 (NEGATE_EXPR, double_type_node,
ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
build_tree_list (NULL_TREE,
@@ -3861,7 +4166,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
arg1_type,
convert (arg1_type,
ffecom_float_half_),
- saved_expr1)))))
+ saved_expr1))),
+ NULL_TREE))
)
);
#endif
@@ -3876,9 +4182,12 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
case FFEINTRIN_impCHAR:
case FFEINTRIN_impACHAR:
- assert (ffecom_pending_calls_ != 0);
- tempvar = ffecom_push_tempvar (char_type_node,
- 1, -1, TRUE);
+#ifdef HOHO
+ tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
+#else
+ tempvar = ffebld_nonter_hook (expr);
+ assert (tempvar);
+#endif
{
tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
@@ -4128,8 +4437,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
case FFEINTRIN_impNINT:
case FFEINTRIN_impIDNINT:
-#if 0 /* ~~ ideally FIX_ROUND_EXPR would be
- implemented, but it ain't yet */
+#if 0
+ /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
#else
/* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
@@ -4542,13 +4851,11 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree prep_arg4;
tree arg5_plus_arg3;
- ffecom_push_calltemps ();
-
arg2_tree = convert (integer_type_node,
ffecom_expr (arg2));
arg3_tree = ffecom_save_tree (convert (integer_type_node,
ffecom_expr (arg3)));
- arg4_tree = ffecom_expr_rw (arg4);
+ arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
arg4_type = TREE_TYPE (arg4_tree);
arg1_tree = ffecom_save_tree (convert (arg4_type,
@@ -4557,8 +4864,6 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
arg5_tree = ffecom_save_tree (convert (integer_type_node,
ffecom_expr (arg5)));
- ffecom_pop_calltemps ();
-
prep_arg1
= ffecom_2 (LSHIFT_EXPR, arg4_type,
ffecom_2 (BIT_AND_EXPR, arg4_type,
@@ -4676,8 +4981,6 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg2_tree;
tree arg3_tree;
- ffecom_push_calltemps ();
-
arg1_tree = convert (ffecom_f2c_integer_type_node,
ffecom_expr (arg1));
arg1_tree = ffecom_1 (ADDR_EXPR,
@@ -4693,12 +4996,10 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
arg2_tree);
if (arg3 != NULL)
- arg3_tree = ffecom_expr_rw (arg3);
+ arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
else
arg3_tree = NULL_TREE;
- ffecom_pop_calltemps ();
-
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
TREE_CHAIN (arg1_tree) = arg2_tree;
@@ -4711,7 +5012,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
NULL_TREE :
tree_type),
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
if (arg3_tree != NULL_TREE)
expr_tree
@@ -4727,8 +5029,6 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg2_tree;
tree arg3_tree;
- ffecom_push_calltemps ();
-
arg1_tree = convert (ffecom_f2c_integer_type_node,
ffecom_expr (arg1));
arg1_tree = ffecom_1 (ADDR_EXPR,
@@ -4744,12 +5044,10 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
arg2_tree);
if (arg3 != NULL)
- arg3_tree = ffecom_expr_rw (arg3);
+ arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
else
arg3_tree = NULL_TREE;
- ffecom_pop_calltemps ();
-
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
TREE_CHAIN (arg1_tree) = arg2_tree;
@@ -4760,7 +5058,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
if (arg3_tree != NULL_TREE)
expr_tree
@@ -4783,17 +5082,13 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg1_tree;
tree arg2_tree;
- ffecom_push_calltemps ();
-
arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
if (arg2 != NULL)
- arg2_tree = ffecom_expr_rw (arg2);
+ arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
else
arg2_tree = NULL_TREE;
- ffecom_pop_calltemps ();
-
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg1_len = build_tree_list (NULL_TREE, arg1_len);
TREE_CHAIN (arg1_tree) = arg1_len;
@@ -4804,7 +5099,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
if (arg2_tree != NULL_TREE)
expr_tree
@@ -4830,7 +5126,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
void_type_node,
expr_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
case FFEINTRIN_impFLUSH:
if (arg1 == NULL)
@@ -4850,17 +5147,13 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg2_tree;
tree arg3_tree;
- ffecom_push_calltemps ();
-
arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
if (arg3 != NULL)
- arg3_tree = ffecom_expr_rw (arg3);
+ arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
else
arg3_tree = NULL_TREE;
- ffecom_pop_calltemps ();
-
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg1_len = build_tree_list (NULL_TREE, arg1_len);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
@@ -4873,7 +5166,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
if (arg3_tree != NULL_TREE)
expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
convert (TREE_TYPE (arg3_tree),
@@ -4889,19 +5183,15 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg2_tree;
tree arg3_tree;
- ffecom_push_calltemps ();
-
arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
arg2_tree = ffecom_ptr_to_expr (arg2);
if (arg3 != NULL)
- arg3_tree = ffecom_expr_rw (arg3);
+ arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
else
arg3_tree = NULL_TREE;
- ffecom_pop_calltemps ();
-
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg1_len = build_tree_list (NULL_TREE, arg1_len);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
@@ -4912,7 +5202,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
if (arg3_tree != NULL_TREE)
expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
convert (TREE_TYPE (arg3_tree),
@@ -4928,8 +5219,6 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg2_len = integer_zero_node;
tree arg3_tree;
- ffecom_push_calltemps ();
-
arg1_tree = convert (ffecom_f2c_integer_type_node,
ffecom_expr (arg1));
arg1_tree = ffecom_1 (ADDR_EXPR,
@@ -4937,9 +5226,7 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
arg1_tree);
arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
- arg3_tree = ffecom_expr_rw (arg3);
-
- ffecom_pop_calltemps ();
+ arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
@@ -4952,7 +5239,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
convert (TREE_TYPE (arg3_tree),
expr_tree));
@@ -4965,8 +5253,6 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg2_tree;
tree arg3_tree;
- ffecom_push_calltemps ();
-
arg1_tree = convert (ffecom_f2c_integer_type_node,
ffecom_expr (arg1));
arg1_tree = ffecom_1 (ADDR_EXPR,
@@ -4979,9 +5265,7 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
if (arg3 == NULL)
arg3_tree = NULL_TREE;
else
- arg3_tree = ffecom_expr_rw (arg3);
-
- ffecom_pop_calltemps ();
+ arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
@@ -4991,7 +5275,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
if (arg3_tree != NULL_TREE) {
expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
convert (TREE_TYPE (arg3_tree),
@@ -5006,8 +5291,6 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg2_tree;
tree arg3_tree;
- ffecom_push_calltemps ();
-
arg1_tree = convert (ffecom_f2c_integer_type_node,
ffecom_expr (arg1));
arg1_tree = ffecom_1 (ADDR_EXPR,
@@ -5023,9 +5306,7 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
if (arg3 == NULL)
arg3_tree = NULL_TREE;
else
- arg3_tree = ffecom_expr_rw (arg3);
-
- ffecom_pop_calltemps ();
+ arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
@@ -5035,7 +5316,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
if (arg3_tree != NULL_TREE) {
expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
convert (TREE_TYPE (arg3_tree),
@@ -5051,20 +5333,16 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg1_tree;
tree arg2_tree;
- ffecom_push_calltemps ();
-
- arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
+ arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
- arg2_tree = convert (((gfrt == FFEINTRIN_impCTIME_subr) ?
+ arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
ffecom_f2c_longint_type_node :
ffecom_f2c_integer_type_node),
- ffecom_expr (arg2));
+ ffecom_expr (arg1));
arg2_tree = ffecom_1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (arg2_tree)),
arg2_tree);
- ffecom_pop_calltemps ();
-
arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
arg1_len = build_tree_list (NULL_TREE, arg1_len);
arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
@@ -5077,7 +5355,9 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
arg1_tree,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
+ TREE_SIDE_EFFECTS (expr_tree) = 1;
}
return expr_tree;
@@ -5106,7 +5386,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
ffecom_f2c_real_type_node),
arg1_tree,
dest_tree, dest, dest_used,
- NULL_TREE, TRUE);
+ NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
}
return expr_tree;
@@ -5116,8 +5397,6 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
tree arg1_tree;
tree arg2_tree;
- ffecom_push_calltemps ();
-
arg1_tree = convert (ffecom_f2c_integer_type_node,
ffecom_expr (arg1));
arg1_tree = ffecom_1 (ADDR_EXPR,
@@ -5127,9 +5406,7 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
if (arg2 == NULL)
arg2_tree = NULL_TREE;
else
- arg2_tree = ffecom_expr_rw (arg2);
-
- ffecom_pop_calltemps ();
+ arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
ffecom_gfrt_kindtype (gfrt),
@@ -5137,7 +5414,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
NULL_TREE,
build_tree_list (NULL_TREE, arg1_tree),
NULL_TREE, NULL, NULL, NULL_TREE,
- TRUE);
+ TRUE,
+ ffebld_nonter_hook (expr));
if (arg2_tree != NULL_TREE) {
expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
convert (TREE_TYPE (arg2_tree),
@@ -5151,11 +5429,7 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
{
tree arg1_tree;
- ffecom_push_calltemps ();
-
- arg1_tree = ffecom_expr_rw (arg1);
-
- ffecom_pop_calltemps ();
+ arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
expr_tree
= ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
@@ -5163,7 +5437,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
FALSE,
NULL_TREE,
NULL_TREE,
- NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
+ NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
expr_tree
= ffecom_modify (NULL_TREE, arg1_tree,
@@ -5176,30 +5451,27 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
case FFEINTRIN_impETIME_subr:
{
tree arg1_tree;
- tree arg2_tree;
+ tree result_tree;
- ffecom_push_calltemps ();
+ result_tree = ffecom_expr_w (NULL_TREE, arg2);
- arg1_tree = ffecom_expr_rw (arg1);
-
- arg2_tree = ffecom_ptr_to_expr (arg2);
-
- ffecom_pop_calltemps ();
+ arg1_tree = ffecom_ptr_to_expr (arg1);
expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
ffecom_gfrt_kindtype (gfrt),
FALSE,
NULL_TREE,
- build_tree_list (NULL_TREE, arg2_tree),
+ build_tree_list (NULL_TREE, arg1_tree),
NULL_TREE, NULL, NULL, NULL_TREE,
- TRUE);
- expr_tree = ffecom_modify (NULL_TREE, arg1_tree,
- convert (TREE_TYPE (arg1_tree),
+ TRUE,
+ ffebld_nonter_hook (expr));
+ expr_tree = ffecom_modify (NULL_TREE, result_tree,
+ convert (TREE_TYPE (result_tree),
expr_tree));
}
return expr_tree;
- /* Straightforward calls of libf2c routines: */
+ /* Straightforward calls of libf2c routines: */
case FFEINTRIN_impABORT:
case FFEINTRIN_impACCESS:
case FFEINTRIN_impBESJ0:
@@ -5280,890 +5552,20 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
- ffecom_push_calltemps ();
expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
ffebld_right (expr));
- ffecom_pop_calltemps ();
return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
(ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
tree_type,
expr_tree, dest_tree, dest, dest_used,
- NULL_TREE, TRUE);
-
- /**INDENT* (Do not reformat this comment even with -fca option.)
- Data-gathering files: Given the source file listed below, compiled with
- f2c I obtained the output file listed after that, and from the output
- file I derived the above code.
+ NULL_TREE, TRUE,
+ ffebld_nonter_hook (expr));
--------- (begin input file to f2c)
- implicit none
- character*10 A1,A2
- complex C1,C2
- integer I1,I2
- real R1,R2
- double precision D1,D2
-C
- call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
-c /
- call fooI(I1/I2)
- call fooR(R1/I1)
- call fooD(D1/I1)
- call fooC(C1/I1)
- call fooR(R1/R2)
- call fooD(R1/D1)
- call fooD(D1/D2)
- call fooD(D1/R1)
- call fooC(C1/C2)
- call fooC(C1/R1)
- call fooZ(C1/D1)
-c **
- call fooI(I1**I2)
- call fooR(R1**I1)
- call fooD(D1**I1)
- call fooC(C1**I1)
- call fooR(R1**R2)
- call fooD(R1**D1)
- call fooD(D1**D2)
- call fooD(D1**R1)
- call fooC(C1**C2)
- call fooC(C1**R1)
- call fooZ(C1**D1)
-c FFEINTRIN_impABS
- call fooR(ABS(R1))
-c FFEINTRIN_impACOS
- call fooR(ACOS(R1))
-c FFEINTRIN_impAIMAG
- call fooR(AIMAG(C1))
-c FFEINTRIN_impAINT
- call fooR(AINT(R1))
-c FFEINTRIN_impALOG
- call fooR(ALOG(R1))
-c FFEINTRIN_impALOG10
- call fooR(ALOG10(R1))
-c FFEINTRIN_impAMAX0
- call fooR(AMAX0(I1,I2))
-c FFEINTRIN_impAMAX1
- call fooR(AMAX1(R1,R2))
-c FFEINTRIN_impAMIN0
- call fooR(AMIN0(I1,I2))
-c FFEINTRIN_impAMIN1
- call fooR(AMIN1(R1,R2))
-c FFEINTRIN_impAMOD
- call fooR(AMOD(R1,R2))
-c FFEINTRIN_impANINT
- call fooR(ANINT(R1))
-c FFEINTRIN_impASIN
- call fooR(ASIN(R1))
-c FFEINTRIN_impATAN
- call fooR(ATAN(R1))
-c FFEINTRIN_impATAN2
- call fooR(ATAN2(R1,R2))
-c FFEINTRIN_impCABS
- call fooR(CABS(C1))
-c FFEINTRIN_impCCOS
- call fooC(CCOS(C1))
-c FFEINTRIN_impCEXP
- call fooC(CEXP(C1))
-c FFEINTRIN_impCHAR
- call fooA(CHAR(I1))
-c FFEINTRIN_impCLOG
- call fooC(CLOG(C1))
-c FFEINTRIN_impCONJG
- call fooC(CONJG(C1))
-c FFEINTRIN_impCOS
- call fooR(COS(R1))
-c FFEINTRIN_impCOSH
- call fooR(COSH(R1))
-c FFEINTRIN_impCSIN
- call fooC(CSIN(C1))
-c FFEINTRIN_impCSQRT
- call fooC(CSQRT(C1))
-c FFEINTRIN_impDABS
- call fooD(DABS(D1))
-c FFEINTRIN_impDACOS
- call fooD(DACOS(D1))
-c FFEINTRIN_impDASIN
- call fooD(DASIN(D1))
-c FFEINTRIN_impDATAN
- call fooD(DATAN(D1))
-c FFEINTRIN_impDATAN2
- call fooD(DATAN2(D1,D2))
-c FFEINTRIN_impDCOS
- call fooD(DCOS(D1))
-c FFEINTRIN_impDCOSH
- call fooD(DCOSH(D1))
-c FFEINTRIN_impDDIM
- call fooD(DDIM(D1,D2))
-c FFEINTRIN_impDEXP
- call fooD(DEXP(D1))
-c FFEINTRIN_impDIM
- call fooR(DIM(R1,R2))
-c FFEINTRIN_impDINT
- call fooD(DINT(D1))
-c FFEINTRIN_impDLOG
- call fooD(DLOG(D1))
-c FFEINTRIN_impDLOG10
- call fooD(DLOG10(D1))
-c FFEINTRIN_impDMAX1
- call fooD(DMAX1(D1,D2))
-c FFEINTRIN_impDMIN1
- call fooD(DMIN1(D1,D2))
-c FFEINTRIN_impDMOD
- call fooD(DMOD(D1,D2))
-c FFEINTRIN_impDNINT
- call fooD(DNINT(D1))
-c FFEINTRIN_impDPROD
- call fooD(DPROD(R1,R2))
-c FFEINTRIN_impDSIGN
- call fooD(DSIGN(D1,D2))
-c FFEINTRIN_impDSIN
- call fooD(DSIN(D1))
-c FFEINTRIN_impDSINH
- call fooD(DSINH(D1))
-c FFEINTRIN_impDSQRT
- call fooD(DSQRT(D1))
-c FFEINTRIN_impDTAN
- call fooD(DTAN(D1))
-c FFEINTRIN_impDTANH
- call fooD(DTANH(D1))
-c FFEINTRIN_impEXP
- call fooR(EXP(R1))
-c FFEINTRIN_impIABS
- call fooI(IABS(I1))
-c FFEINTRIN_impICHAR
- call fooI(ICHAR(A1))
-c FFEINTRIN_impIDIM
- call fooI(IDIM(I1,I2))
-c FFEINTRIN_impIDNINT
- call fooI(IDNINT(D1))
-c FFEINTRIN_impINDEX
- call fooI(INDEX(A1,A2))
-c FFEINTRIN_impISIGN
- call fooI(ISIGN(I1,I2))
-c FFEINTRIN_impLEN
- call fooI(LEN(A1))
-c FFEINTRIN_impLGE
- call fooL(LGE(A1,A2))
-c FFEINTRIN_impLGT
- call fooL(LGT(A1,A2))
-c FFEINTRIN_impLLE
- call fooL(LLE(A1,A2))
-c FFEINTRIN_impLLT
- call fooL(LLT(A1,A2))
-c FFEINTRIN_impMAX0
- call fooI(MAX0(I1,I2))
-c FFEINTRIN_impMAX1
- call fooI(MAX1(R1,R2))
-c FFEINTRIN_impMIN0
- call fooI(MIN0(I1,I2))
-c FFEINTRIN_impMIN1
- call fooI(MIN1(R1,R2))
-c FFEINTRIN_impMOD
- call fooI(MOD(I1,I2))
-c FFEINTRIN_impNINT
- call fooI(NINT(R1))
-c FFEINTRIN_impSIGN
- call fooR(SIGN(R1,R2))
-c FFEINTRIN_impSIN
- call fooR(SIN(R1))
-c FFEINTRIN_impSINH
- call fooR(SINH(R1))
-c FFEINTRIN_impSQRT
- call fooR(SQRT(R1))
-c FFEINTRIN_impTAN
- call fooR(TAN(R1))
-c FFEINTRIN_impTANH
- call fooR(TANH(R1))
-c FFEINTRIN_imp_CMPLX_C
- call fooC(cmplx(C1,C2))
-c FFEINTRIN_imp_CMPLX_D
- call fooZ(cmplx(D1,D2))
-c FFEINTRIN_imp_CMPLX_I
- call fooC(cmplx(I1,I2))
-c FFEINTRIN_imp_CMPLX_R
- call fooC(cmplx(R1,R2))
-c FFEINTRIN_imp_DBLE_C
- call fooD(dble(C1))
-c FFEINTRIN_imp_DBLE_D
- call fooD(dble(D1))
-c FFEINTRIN_imp_DBLE_I
- call fooD(dble(I1))
-c FFEINTRIN_imp_DBLE_R
- call fooD(dble(R1))
-c FFEINTRIN_imp_INT_C
- call fooI(int(C1))
-c FFEINTRIN_imp_INT_D
- call fooI(int(D1))
-c FFEINTRIN_imp_INT_I
- call fooI(int(I1))
-c FFEINTRIN_imp_INT_R
- call fooI(int(R1))
-c FFEINTRIN_imp_REAL_C
- call fooR(real(C1))
-c FFEINTRIN_imp_REAL_D
- call fooR(real(D1))
-c FFEINTRIN_imp_REAL_I
- call fooR(real(I1))
-c FFEINTRIN_imp_REAL_R
- call fooR(real(R1))
-c
-c FFEINTRIN_imp_INT_D:
-c
-c FFEINTRIN_specIDINT
- call fooI(IDINT(D1))
-c
-c FFEINTRIN_imp_INT_R:
-c
-c FFEINTRIN_specIFIX
- call fooI(IFIX(R1))
-c FFEINTRIN_specINT
- call fooI(INT(R1))
-c
-c FFEINTRIN_imp_REAL_D:
-c
-c FFEINTRIN_specSNGL
- call fooR(SNGL(D1))
-c
-c FFEINTRIN_imp_REAL_I:
-c
-c FFEINTRIN_specFLOAT
- call fooR(FLOAT(I1))
-c FFEINTRIN_specREAL
- call fooR(REAL(I1))
-c
- end
--------- (end input file to f2c)
-
--------- (begin output from providing above input file as input to:
--------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
--------- -e "s:^#.*$::g"')
-
-// -- translated by f2c (version 19950223).
- You must link the resulting object file with the libraries:
- -lf2c -lm (in that order)
-//
-
-
-// f2c.h -- Standard Fortran to C header file //
-
-/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
-
- - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
-
-
-
-
-// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
-// we assume short, float are OK //
-typedef long int // long int // integer;
-typedef char *address;
-typedef short int shortint;
-typedef float real;
-typedef double doublereal;
-typedef struct { real r, i; } complex;
-typedef struct { doublereal r, i; } doublecomplex;
-typedef long int // long int // logical;
-typedef short int shortlogical;
-typedef char logical1;
-typedef char integer1;
-// typedef long long longint; // // system-dependent //
-
-
-
-
-// Extern is for use with -E //
-
-
-
-
-// I/O stuff //
-
-
-
-
-
-
-
-
-typedef long int // int or long int // flag;
-typedef long int // int or long int // ftnlen;
-typedef long int // int or long int // ftnint;
-
-
-//external read, write//
-typedef struct
-{ flag cierr;
- ftnint ciunit;
- flag ciend;
- char *cifmt;
- ftnint cirec;
-} cilist;
-
-//internal read, write//
-typedef struct
-{ flag icierr;
- char *iciunit;
- flag iciend;
- char *icifmt;
- ftnint icirlen;
- ftnint icirnum;
-} icilist;
-
-//open//
-typedef struct
-{ flag oerr;
- ftnint ounit;
- char *ofnm;
- ftnlen ofnmlen;
- char *osta;
- char *oacc;
- char *ofm;
- ftnint orl;
- char *oblnk;
-} olist;
-
-//close//
-typedef struct
-{ flag cerr;
- ftnint cunit;
- char *csta;
-} cllist;
-
-//rewind, backspace, endfile//
-typedef struct
-{ flag aerr;
- ftnint aunit;
-} alist;
-
-// inquire //
-typedef struct
-{ flag inerr;
- ftnint inunit;
- char *infile;
- ftnlen infilen;
- ftnint *inex; //parameters in standard's order//
- ftnint *inopen;
- ftnint *innum;
- ftnint *innamed;
- char *inname;
- ftnlen innamlen;
- char *inacc;
- ftnlen inacclen;
- char *inseq;
- ftnlen inseqlen;
- char *indir;
- ftnlen indirlen;
- char *infmt;
- ftnlen infmtlen;
- char *inform;
- ftnint informlen;
- char *inunf;
- ftnlen inunflen;
- ftnint *inrecl;
- ftnint *innrec;
- char *inblank;
- ftnlen inblanklen;
-} inlist;
-
-
-
-union Multitype { // for multiple entry points //
- integer1 g;
- shortint h;
- integer i;
- // longint j; //
- real r;
- doublereal d;
- complex c;
- doublecomplex z;
- };
-
-typedef union Multitype Multitype;
-
-typedef long Long; // No longer used; formerly in Namelist //
-
-struct Vardesc { // for Namelist //
- char *name;
- char *addr;
- ftnlen *dims;
- int type;
- };
-typedef struct Vardesc Vardesc;
-
-struct Namelist {
- char *name;
- Vardesc **vars;
- int nvars;
- };
-typedef struct Namelist Namelist;
-
-
-
-
-
-
-
-
-// procedure parameter types for -A and -C++ //
-
-
-
-
-typedef int // Unknown procedure type // (*U_fp)();
-typedef shortint (*J_fp)();
-typedef integer (*I_fp)();
-typedef real (*R_fp)();
-typedef doublereal (*D_fp)(), (*E_fp)();
-typedef // Complex // void (*C_fp)();
-typedef // Double Complex // void (*Z_fp)();
-typedef logical (*L_fp)();
-typedef shortlogical (*K_fp)();
-typedef // Character // void (*H_fp)();
-typedef // Subroutine // int (*S_fp)();
-
-// E_fp is for real functions when -R is not specified //
-typedef void C_f; // complex function //
-typedef void H_f; // character function //
-typedef void Z_f; // double complex function //
-typedef doublereal E_f; // real function with -R not specified //
-
-// undef any lower-case symbols that your C compiler predefines, e.g.: //
-
-
-// (No such symbols should be defined in a strict ANSI C compiler.
- We can avoid trouble with f2c-translated code by using
- gcc -ansi [-traditional].) //
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Main program // MAIN__()
-{
- // System generated locals //
- integer i__1;
- real r__1, r__2;
- doublereal d__1, d__2;
- complex q__1;
- doublecomplex z__1, z__2, z__3;
- logical L__1;
- char ch__1[1];
-
- // Builtin functions //
- void c_div();
- integer pow_ii();
- double pow_ri(), pow_di();
- void pow_ci();
- double pow_dd();
- void pow_zz();
- double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
- asin(), atan(), atan2(), c_abs();
- void c_cos(), c_exp(), c_log(), r_cnjg();
- double cos(), cosh();
- void c_sin(), c_sqrt();
- double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
- d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
- integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
- logical l_ge(), l_gt(), l_le(), l_lt();
- integer i_nint();
- double r_sign();
-
- // Local variables //
- extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
- fool_(), fooz_(), getem_();
- static char a1[10], a2[10];
- static complex c1, c2;
- static doublereal d1, d2;
- static integer i1, i2;
- static real r1, r2;
-
-
- getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
-// / //
- i__1 = i1 / i2;
- fooi_(&i__1);
- r__1 = r1 / i1;
- foor_(&r__1);
- d__1 = d1 / i1;
- food_(&d__1);
- d__1 = (doublereal) i1;
- q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
- fooc_(&q__1);
- r__1 = r1 / r2;
- foor_(&r__1);
- d__1 = r1 / d1;
- food_(&d__1);
- d__1 = d1 / d2;
- food_(&d__1);
- d__1 = d1 / r1;
- food_(&d__1);
- c_div(&q__1, &c1, &c2);
- fooc_(&q__1);
- q__1.r = c1.r / r1, q__1.i = c1.i / r1;
- fooc_(&q__1);
- z__1.r = c1.r / d1, z__1.i = c1.i / d1;
- fooz_(&z__1);
-// ** //
- i__1 = pow_ii(&i1, &i2);
- fooi_(&i__1);
- r__1 = pow_ri(&r1, &i1);
- foor_(&r__1);
- d__1 = pow_di(&d1, &i1);
- food_(&d__1);
- pow_ci(&q__1, &c1, &i1);
- fooc_(&q__1);
- d__1 = (doublereal) r1;
- d__2 = (doublereal) r2;
- r__1 = pow_dd(&d__1, &d__2);
- foor_(&r__1);
- d__2 = (doublereal) r1;
- d__1 = pow_dd(&d__2, &d1);
- food_(&d__1);
- d__1 = pow_dd(&d1, &d2);
- food_(&d__1);
- d__2 = (doublereal) r1;
- d__1 = pow_dd(&d1, &d__2);
- food_(&d__1);
- z__2.r = c1.r, z__2.i = c1.i;
- z__3.r = c2.r, z__3.i = c2.i;
- pow_zz(&z__1, &z__2, &z__3);
- q__1.r = z__1.r, q__1.i = z__1.i;
- fooc_(&q__1);
- z__2.r = c1.r, z__2.i = c1.i;
- z__3.r = r1, z__3.i = 0.;
- pow_zz(&z__1, &z__2, &z__3);
- q__1.r = z__1.r, q__1.i = z__1.i;
- fooc_(&q__1);
- z__2.r = c1.r, z__2.i = c1.i;
- z__3.r = d1, z__3.i = 0.;
- pow_zz(&z__1, &z__2, &z__3);
- fooz_(&z__1);
-// FFEINTRIN_impABS //
- r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
- foor_(&r__1);
-// FFEINTRIN_impACOS //
- r__1 = acos(r1);
- foor_(&r__1);
-// FFEINTRIN_impAIMAG //
- r__1 = r_imag(&c1);
- foor_(&r__1);
-// FFEINTRIN_impAINT //
- r__1 = r_int(&r1);
- foor_(&r__1);
-// FFEINTRIN_impALOG //
- r__1 = log(r1);
- foor_(&r__1);
-// FFEINTRIN_impALOG10 //
- r__1 = r_lg10(&r1);
- foor_(&r__1);
-// FFEINTRIN_impAMAX0 //
- r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
- foor_(&r__1);
-// FFEINTRIN_impAMAX1 //
- r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
- foor_(&r__1);
-// FFEINTRIN_impAMIN0 //
- r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
- foor_(&r__1);
-// FFEINTRIN_impAMIN1 //
- r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
- foor_(&r__1);
-// FFEINTRIN_impAMOD //
- r__1 = r_mod(&r1, &r2);
- foor_(&r__1);
-// FFEINTRIN_impANINT //
- r__1 = r_nint(&r1);
- foor_(&r__1);
-// FFEINTRIN_impASIN //
- r__1 = asin(r1);
- foor_(&r__1);
-// FFEINTRIN_impATAN //
- r__1 = atan(r1);
- foor_(&r__1);
-// FFEINTRIN_impATAN2 //
- r__1 = atan2(r1, r2);
- foor_(&r__1);
-// FFEINTRIN_impCABS //
- r__1 = c_abs(&c1);
- foor_(&r__1);
-// FFEINTRIN_impCCOS //
- c_cos(&q__1, &c1);
- fooc_(&q__1);
-// FFEINTRIN_impCEXP //
- c_exp(&q__1, &c1);
- fooc_(&q__1);
-// FFEINTRIN_impCHAR //
- *(unsigned char *)&ch__1[0] = i1;
- fooa_(ch__1, 1L);
-// FFEINTRIN_impCLOG //
- c_log(&q__1, &c1);
- fooc_(&q__1);
-// FFEINTRIN_impCONJG //
- r_cnjg(&q__1, &c1);
- fooc_(&q__1);
-// FFEINTRIN_impCOS //
- r__1 = cos(r1);
- foor_(&r__1);
-// FFEINTRIN_impCOSH //
- r__1 = cosh(r1);
- foor_(&r__1);
-// FFEINTRIN_impCSIN //
- c_sin(&q__1, &c1);
- fooc_(&q__1);
-// FFEINTRIN_impCSQRT //
- c_sqrt(&q__1, &c1);
- fooc_(&q__1);
-// FFEINTRIN_impDABS //
- d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
- food_(&d__1);
-// FFEINTRIN_impDACOS //
- d__1 = acos(d1);
- food_(&d__1);
-// FFEINTRIN_impDASIN //
- d__1 = asin(d1);
- food_(&d__1);
-// FFEINTRIN_impDATAN //
- d__1 = atan(d1);
- food_(&d__1);
-// FFEINTRIN_impDATAN2 //
- d__1 = atan2(d1, d2);
- food_(&d__1);
-// FFEINTRIN_impDCOS //
- d__1 = cos(d1);
- food_(&d__1);
-// FFEINTRIN_impDCOSH //
- d__1 = cosh(d1);
- food_(&d__1);
-// FFEINTRIN_impDDIM //
- d__1 = d_dim(&d1, &d2);
- food_(&d__1);
-// FFEINTRIN_impDEXP //
- d__1 = exp(d1);
- food_(&d__1);
-// FFEINTRIN_impDIM //
- r__1 = r_dim(&r1, &r2);
- foor_(&r__1);
-// FFEINTRIN_impDINT //
- d__1 = d_int(&d1);
- food_(&d__1);
-// FFEINTRIN_impDLOG //
- d__1 = log(d1);
- food_(&d__1);
-// FFEINTRIN_impDLOG10 //
- d__1 = d_lg10(&d1);
- food_(&d__1);
-// FFEINTRIN_impDMAX1 //
- d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
- food_(&d__1);
-// FFEINTRIN_impDMIN1 //
- d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
- food_(&d__1);
-// FFEINTRIN_impDMOD //
- d__1 = d_mod(&d1, &d2);
- food_(&d__1);
-// FFEINTRIN_impDNINT //
- d__1 = d_nint(&d1);
- food_(&d__1);
-// FFEINTRIN_impDPROD //
- d__1 = (doublereal) r1 * r2;
- food_(&d__1);
-// FFEINTRIN_impDSIGN //
- d__1 = d_sign(&d1, &d2);
- food_(&d__1);
-// FFEINTRIN_impDSIN //
- d__1 = sin(d1);
- food_(&d__1);
-// FFEINTRIN_impDSINH //
- d__1 = sinh(d1);
- food_(&d__1);
-// FFEINTRIN_impDSQRT //
- d__1 = sqrt(d1);
- food_(&d__1);
-// FFEINTRIN_impDTAN //
- d__1 = tan(d1);
- food_(&d__1);
-// FFEINTRIN_impDTANH //
- d__1 = tanh(d1);
- food_(&d__1);
-// FFEINTRIN_impEXP //
- r__1 = exp(r1);
- foor_(&r__1);
-// FFEINTRIN_impIABS //
- i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
- fooi_(&i__1);
-// FFEINTRIN_impICHAR //
- i__1 = *(unsigned char *)a1;
- fooi_(&i__1);
-// FFEINTRIN_impIDIM //
- i__1 = i_dim(&i1, &i2);
- fooi_(&i__1);
-// FFEINTRIN_impIDNINT //
- i__1 = i_dnnt(&d1);
- fooi_(&i__1);
-// FFEINTRIN_impINDEX //
- i__1 = i_indx(a1, a2, 10L, 10L);
- fooi_(&i__1);
-// FFEINTRIN_impISIGN //
- i__1 = i_sign(&i1, &i2);
- fooi_(&i__1);
-// FFEINTRIN_impLEN //
- i__1 = i_len(a1, 10L);
- fooi_(&i__1);
-// FFEINTRIN_impLGE //
- L__1 = l_ge(a1, a2, 10L, 10L);
- fool_(&L__1);
-// FFEINTRIN_impLGT //
- L__1 = l_gt(a1, a2, 10L, 10L);
- fool_(&L__1);
-// FFEINTRIN_impLLE //
- L__1 = l_le(a1, a2, 10L, 10L);
- fool_(&L__1);
-// FFEINTRIN_impLLT //
- L__1 = l_lt(a1, a2, 10L, 10L);
- fool_(&L__1);
-// FFEINTRIN_impMAX0 //
- i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
- fooi_(&i__1);
-// FFEINTRIN_impMAX1 //
- i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
- fooi_(&i__1);
-// FFEINTRIN_impMIN0 //
- i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
- fooi_(&i__1);
-// FFEINTRIN_impMIN1 //
- i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
- fooi_(&i__1);
-// FFEINTRIN_impMOD //
- i__1 = i1 % i2;
- fooi_(&i__1);
-// FFEINTRIN_impNINT //
- i__1 = i_nint(&r1);
- fooi_(&i__1);
-// FFEINTRIN_impSIGN //
- r__1 = r_sign(&r1, &r2);
- foor_(&r__1);
-// FFEINTRIN_impSIN //
- r__1 = sin(r1);
- foor_(&r__1);
-// FFEINTRIN_impSINH //
- r__1 = sinh(r1);
- foor_(&r__1);
-// FFEINTRIN_impSQRT //
- r__1 = sqrt(r1);
- foor_(&r__1);
-// FFEINTRIN_impTAN //
- r__1 = tan(r1);
- foor_(&r__1);
-// FFEINTRIN_impTANH //
- r__1 = tanh(r1);
- foor_(&r__1);
-// FFEINTRIN_imp_CMPLX_C //
- r__1 = c1.r;
- r__2 = c2.r;
- q__1.r = r__1, q__1.i = r__2;
- fooc_(&q__1);
-// FFEINTRIN_imp_CMPLX_D //
- z__1.r = d1, z__1.i = d2;
- fooz_(&z__1);
-// FFEINTRIN_imp_CMPLX_I //
- r__1 = (real) i1;
- r__2 = (real) i2;
- q__1.r = r__1, q__1.i = r__2;
- fooc_(&q__1);
-// FFEINTRIN_imp_CMPLX_R //
- q__1.r = r1, q__1.i = r2;
- fooc_(&q__1);
-// FFEINTRIN_imp_DBLE_C //
- d__1 = (doublereal) c1.r;
- food_(&d__1);
-// FFEINTRIN_imp_DBLE_D //
- d__1 = d1;
- food_(&d__1);
-// FFEINTRIN_imp_DBLE_I //
- d__1 = (doublereal) i1;
- food_(&d__1);
-// FFEINTRIN_imp_DBLE_R //
- d__1 = (doublereal) r1;
- food_(&d__1);
-// FFEINTRIN_imp_INT_C //
- i__1 = (integer) c1.r;
- fooi_(&i__1);
-// FFEINTRIN_imp_INT_D //
- i__1 = (integer) d1;
- fooi_(&i__1);
-// FFEINTRIN_imp_INT_I //
- i__1 = i1;
- fooi_(&i__1);
-// FFEINTRIN_imp_INT_R //
- i__1 = (integer) r1;
- fooi_(&i__1);
-// FFEINTRIN_imp_REAL_C //
- r__1 = c1.r;
- foor_(&r__1);
-// FFEINTRIN_imp_REAL_D //
- r__1 = (real) d1;
- foor_(&r__1);
-// FFEINTRIN_imp_REAL_I //
- r__1 = (real) i1;
- foor_(&r__1);
-// FFEINTRIN_imp_REAL_R //
- r__1 = r1;
- foor_(&r__1);
-
-// FFEINTRIN_imp_INT_D: //
-
-// FFEINTRIN_specIDINT //
- i__1 = (integer) d1;
- fooi_(&i__1);
-
-// FFEINTRIN_imp_INT_R: //
-
-// FFEINTRIN_specIFIX //
- i__1 = (integer) r1;
- fooi_(&i__1);
-// FFEINTRIN_specINT //
- i__1 = (integer) r1;
- fooi_(&i__1);
-
-// FFEINTRIN_imp_REAL_D: //
-
-// FFEINTRIN_specSNGL //
- r__1 = (real) d1;
- foor_(&r__1);
-
-// FFEINTRIN_imp_REAL_I: //
-
-// FFEINTRIN_specFLOAT //
- r__1 = (real) i1;
- foor_(&r__1);
-// FFEINTRIN_specREAL //
- r__1 = (real) i1;
- foor_(&r__1);
-
-} // MAIN__ //
-
--------- (end output file from f2c)
-
-*/
+ /* See bottom of this file for f2c transforms used to determine
+ many of the above implementations. The info seems to confuse
+ Emacs's C mode indentation, which is why it's been moved to
+ the bottom of this source file. */
}
#endif
@@ -6173,10 +5575,10 @@ typedef doublereal E_f; // real function with -R not specified //
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
-ffecom_expr_power_integer_ (ffebld left, ffebld right)
+ffecom_expr_power_integer_ (ffebld expr)
{
- tree l = ffecom_expr (left);
- tree r = ffecom_expr (right);
+ tree l = ffecom_expr (ffebld_left (expr));
+ tree r = ffecom_expr (ffebld_right (expr));
tree ltype = TREE_TYPE (l);
tree rtype = TREE_TYPE (r);
tree result = NULL_TREE;
@@ -6202,7 +5604,7 @@ ffecom_expr_power_integer_ (ffebld left, ffebld right)
result = ffecom_tree_divide_ (ltype,
convert (ltype, integer_one_node),
l,
- NULL_TREE, NULL, NULL);
+ NULL_TREE, NULL, NULL, NULL_TREE);
r = ffecom_1 (NEGATE_EXPR,
rtype,
r);
@@ -6221,7 +5623,8 @@ ffecom_expr_power_integer_ (ffebld left, ffebld right)
l = ffecom_tree_divide_ (ltype,
convert (ltype, integer_one_node),
l,
- NULL_TREE, NULL, NULL);
+ NULL_TREE, NULL, NULL,
+ ffebld_nonter_hook (expr));
r = ffecom_1 (NEGATE_EXPR, rtype, r);
assert (TREE_CODE (r) == INTEGER_CST);
@@ -6341,21 +5744,50 @@ ffecom_expr_power_integer_ (ffebld left, ffebld right)
{
tree rtmp;
tree ltmp;
+ tree divide;
tree basetypeof_l_is_int;
tree se;
+ tree t;
basetypeof_l_is_int
= build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
se = expand_start_stmt_expr ();
- ffecom_push_calltemps ();
- rtmp = ffecom_push_tempvar (rtype, FFETARGET_charactersizeNONE, -1,
- TRUE);
- ltmp = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
- TRUE);
- result = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
- TRUE);
+ ffecom_start_compstmt ();
+
+#ifndef HAHA
+ rtmp = ffecom_make_tempvar ("power_r", rtype,
+ FFETARGET_charactersizeNONE, -1);
+ ltmp = ffecom_make_tempvar ("power_l", ltype,
+ FFETARGET_charactersizeNONE, -1);
+ result = ffecom_make_tempvar ("power_res", ltype,
+ FFETARGET_charactersizeNONE, -1);
+ if (TREE_CODE (ltype) == COMPLEX_TYPE
+ || TREE_CODE (ltype) == RECORD_TYPE)
+ divide = ffecom_make_tempvar ("power_div", ltype,
+ FFETARGET_charactersizeNONE, -1);
+ else
+ divide = NULL_TREE;
+#else /* HAHA */
+ {
+ tree hook;
+
+ hook = ffebld_nonter_hook (expr);
+ assert (hook);
+ assert (TREE_CODE (hook) == TREE_VEC);
+ assert (TREE_VEC_LENGTH (hook) == 4);
+ rtmp = TREE_VEC_ELT (hook, 0);
+ ltmp = TREE_VEC_ELT (hook, 1);
+ result = TREE_VEC_ELT (hook, 2);
+ divide = TREE_VEC_ELT (hook, 3);
+ if (TREE_CODE (ltype) == COMPLEX_TYPE
+ || TREE_CODE (ltype) == RECORD_TYPE)
+ assert (divide);
+ else
+ assert (! divide);
+ }
+#endif /* HAHA */
expand_expr_stmt (ffecom_modify (void_type_node,
rtmp,
@@ -6372,7 +5804,7 @@ ffecom_expr_power_integer_ (ffebld left, ffebld right)
result,
convert (ltype, integer_one_node)));
expand_start_else ();
- if (!integer_zerop (basetypeof_l_is_int))
+ if (! integer_zerop (basetypeof_l_is_int))
{
expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
rtmp,
@@ -6385,7 +5817,8 @@ ffecom_expr_power_integer_ (ffebld left, ffebld right)
(ltype,
convert (ltype, integer_one_node),
ltmp,
- NULL_TREE, NULL, NULL)));
+ NULL_TREE, NULL, NULL,
+ divide)));
expand_start_cond (ffecom_truth_value
(ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
ffecom_2 (LT_EXPR, integer_type_node,
@@ -6429,7 +5862,8 @@ ffecom_expr_power_integer_ (ffebld left, ffebld right)
(ltype,
convert (ltype, integer_one_node),
ltmp,
- NULL_TREE, NULL, NULL)));
+ NULL_TREE, NULL, NULL,
+ divide)));
expand_expr_stmt (ffecom_modify (void_type_node,
rtmp,
ffecom_1 (NEGATE_EXPR, rtype,
@@ -6484,9 +5918,24 @@ ffecom_expr_power_integer_ (ffebld left, ffebld right)
expand_end_cond ();
expand_expr_stmt (result);
- ffecom_pop_calltemps ();
+ t = ffecom_end_compstmt ();
+
result = expand_end_stmt_expr (se);
- TREE_SIDE_EFFECTS (result) = 1;
+
+ /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
+
+ if (TREE_CODE (t) == BLOCK)
+ {
+ /* Make a BIND_EXPR for the BLOCK already made. */
+ result = build (BIND_EXPR, TREE_TYPE (result),
+ NULL_TREE, result, t);
+ /* Remove the block from the tree at this point.
+ It gets put back at the proper place
+ when the BIND_EXPR is expanded. */
+ delete_block (t);
+ }
+ else
+ result = t;
}
return result;
@@ -6560,7 +6009,7 @@ tail_recurse: /* :::::::::::::::::::: */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
-ffecom_f2c_make_type_ (tree *type, int tcode, char *name)
+ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
{
switch (tcode)
{
@@ -6624,7 +6073,7 @@ ffecom_f2c_make_type_ (tree *type, int tcode, char *name)
pushdecl (build_decl (TYPE_DECL,
ffecom_get_invented_identifier ("__g77_f2c_%s",
- name, 0),
+ name, -1),
*type));
}
@@ -6760,7 +6209,7 @@ ffecom_finish_symbol_transform_ (ffesymbol s)
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
-ffecom_get_appended_identifier_ (char us, char *name)
+ffecom_get_appended_identifier_ (char us, const char *name)
{
int i;
char *newname;
@@ -6789,7 +6238,7 @@ static tree
ffecom_get_external_identifier_ (ffesymbol s)
{
char us;
- char *name = ffesymbol_text (s);
+ const char *name = ffesymbol_text (s);
/* If name is a built-in name, just return it as is. */
@@ -6828,7 +6277,7 @@ ffecom_get_external_identifier_ (ffesymbol s)
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
-ffecom_get_identifier_ (char *name)
+ffecom_get_identifier_ (const char *name)
{
/* If name does not contain an underscore, just return it as is. */
@@ -6894,8 +6343,6 @@ ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
push_f_function_context ();
- ffecom_push_calltemps ();
-
if (charfunc)
type = void_type_node;
else
@@ -6924,7 +6371,7 @@ ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
result = ffecom_get_invented_identifier ("__g77_%s",
- "result", 0);
+ "result", -1);
ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
@@ -6942,7 +6389,7 @@ ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
store_parm_decls (0);
- ffecom_start_compstmt_ ();
+ ffecom_start_compstmt ();
if (expr != NULL)
{
@@ -6954,24 +6401,32 @@ ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
result_length = build_int_2 (sz, 0);
TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
+ ffecom_prepare_let_char_ (sz, expr);
+
+ ffecom_prepare_end ();
+
ffecom_let_char_ (result, result_length, sz, expr);
expand_null_return ();
}
else
- expand_return (ffecom_modify (NULL_TREE,
- DECL_RESULT (current_function_decl),
- ffecom_expr (expr)));
+ {
+ ffecom_prepare_expr (expr);
+
+ ffecom_prepare_end ();
+
+ expand_return (ffecom_modify (NULL_TREE,
+ DECL_RESULT (current_function_decl),
+ ffecom_expr (expr)));
+ }
clear_momentary ();
}
- ffecom_end_compstmt_ ();
+ ffecom_end_compstmt ();
func = current_function_decl;
finish_function (1);
- ffecom_pop_calltemps ();
-
pop_f_function_context ();
resume_momentary (yes);
@@ -6989,7 +6444,7 @@ ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
#endif
#if FFECOM_targetCURRENT == FFECOM_targetGCC
-static char *
+static const char *
ffecom_gfrt_args_ (ffecomGfrt ix)
{
return ffecom_gfrt_argstring_[ix];
@@ -7095,9 +6550,7 @@ ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
case FFEBLD_opARRAYREF:
case FFEBLD_opFUNCREF:
case FFEBLD_opSUBSTR:
- ffecom_push_calltemps ();
ffecom_char_args_ (&expr_tree, &length_tree, arg);
- ffecom_pop_calltemps ();
if ((expr_tree == error_mark_node)
|| (length_tree == error_mark_node))
@@ -7323,13 +6776,7 @@ ffecom_intrinsic_len_ (ffebld expr)
}
#endif
-/* ffecom_let_char_ -- Do assignment stuff for character type
-
- tree dest_tree; // destination (ADDR_EXPR)
- tree dest_length; // length (INT_CST/INDIRECT_REF(PARM_DECL))
- ffetargetCharacterSize dest_size; // length
- ffebld source; // source expression
- ffecom_let_char_(dest_tree,dest_length,dest_size,source);
+/* Handle CHARACTER assignments.
Generates code to do the assignment. Used by ordinary assignment
statement handler ffecom_let_stmt and by statement-function
@@ -7376,7 +6823,7 @@ ffecom_let_char_ (tree dest_tree, tree dest_length,
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
= build_tree_list (NULL_TREE, source_length);
- expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
+ expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
TREE_SIDE_EFFECTS (expr_tree) = 1;
expand_expr_stmt (expr_tree);
@@ -7433,7 +6880,7 @@ ffecom_let_char_ (tree dest_tree, tree dest_length,
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
= build_tree_list (NULL_TREE, source_length);
- expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
+ expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
TREE_SIDE_EFFECTS (expr_tree) = 1;
expand_expr_stmt (expr_tree);
@@ -7456,6 +6903,7 @@ ffecom_let_char_ (tree dest_tree, tree dest_length,
tree citem;
tree clength;
+#ifdef HOHO
length_array
= lengths
= ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
@@ -7463,6 +6911,18 @@ ffecom_let_char_ (tree dest_tree, tree dest_length,
item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
FFETARGET_charactersizeNONE,
count, TRUE);
+#else
+ {
+ tree hook;
+
+ hook = ffebld_nonter_hook (source);
+ assert (hook);
+ assert (TREE_CODE (hook) == TREE_VEC);
+ assert (TREE_VEC_LENGTH (hook) == 2);
+ length_array = lengths = TREE_VEC_ELT (hook, 0);
+ item_array = items = TREE_VEC_ELT (hook, 1);
+ }
+#endif
for (i = 0; i < count; ++i)
{
@@ -7515,7 +6975,7 @@ ffecom_let_char_ (tree dest_tree, tree dest_length,
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
= build_tree_list (NULL_TREE, dest_length);
- expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree);
+ expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
TREE_SIDE_EFFECTS (expr_tree) = 1;
expand_expr_stmt (expr_tree);
@@ -7694,6 +7154,51 @@ ffecom_member_phase2_ (ffestorag mst, ffestorag st)
#endif
#endif
+/* Prepare source expression for assignment into a destination perhaps known
+ to be of a specific size. */
+
+static void
+ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
+{
+ ffecomConcatList_ catlist;
+ int count;
+ int i;
+ tree ltmp;
+ tree itmp;
+ tree tempvar = NULL_TREE;
+
+ while (ffebld_op (source) == FFEBLD_opCONVERT)
+ source = ffebld_left (source);
+
+ catlist = ffecom_concat_list_new_ (source, dest_size);
+ count = ffecom_concat_list_count_ (catlist);
+
+ if (count >= 2)
+ {
+ ltmp
+ = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
+ FFETARGET_charactersizeNONE, count);
+ itmp
+ = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
+ FFETARGET_charactersizeNONE, count);
+
+ tempvar = make_tree_vec (2);
+ TREE_VEC_ELT (tempvar, 0) = ltmp;
+ TREE_VEC_ELT (tempvar, 1) = itmp;
+ }
+
+ for (i = 0; i < count; ++i)
+ ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
+
+ ffecom_concat_list_kill_ (catlist);
+
+ if (tempvar)
+ {
+ ffebld_nonter_set_hook (source, tempvar);
+ current_binding_level->prep_state = 1;
+ }
+}
+
/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
Ignores STAR (alternate-return) dummies. All other get exec-transitioned
@@ -7910,7 +7415,7 @@ ffecom_start_progunit_ ()
{
id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
ffesymbol_text (fn),
- 0);
+ -1);
}
#if FFETARGET_isENFORCED_MAIN
else if (main_program)
@@ -7946,7 +7451,7 @@ ffecom_start_progunit_ ()
= build_decl (PARM_DECL,
ffecom_get_invented_identifier ("__g77_%s",
"which_entrypoint",
- 0),
+ -1),
integer_type_node);
push_parm_decl (ffecom_which_entrypoint_decl_);
}
@@ -7966,7 +7471,7 @@ ffecom_start_progunit_ ()
type = ffecom_multi_type_node_;
result = ffecom_get_invented_identifier ("__g77_%s",
- "result", 0);
+ "result", -1);
/* Make length arg _and_ enhance type info for CHAR arg itself. */
@@ -8005,7 +7510,9 @@ ffecom_start_progunit_ ()
if (TREE_CODE (current_function_decl) != ERROR_MARK)
store_parm_decls (main_program ? 1 : 0);
- ffecom_start_compstmt_ ();
+ ffecom_start_compstmt ();
+ /* Disallow temp vars at this level. */
+ current_binding_level->prep_state = 2;
lineno = old_lineno;
input_filename = old_input_filename;
@@ -8042,6 +7549,20 @@ ffecom_sym_transform_ (ffesymbol s)
int old_lineno = lineno;
char *old_input_filename = input_filename;
+ /* Must ensure special ASSIGN variables are declared at top of outermost
+ block, else they'll end up in the innermost block when their first
+ ASSIGN is seen, which leaves them out of scope when they're the
+ subject of a GOTO or I/O statement.
+
+ We make this variable even if -fugly-assign. Just let it go unused,
+ in case it turns out there are cases where we really want to use this
+ variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
+
+ if (! ffecom_transform_only_dummies_
+ && ffesymbol_assigned (s)
+ && ! ffesymbol_hook (s).assign_tree)
+ s = ffecom_sym_transform_assign_ (s);
+
if (ffesymbol_sfdummyparent (s) == NULL)
{
input_filename = ffesymbol_where_filename (s);
@@ -8134,7 +7655,8 @@ ffecom_sym_transform_ (ffesymbol s)
switch (ffeinfo_where (ffesymbol_info (s)))
{
- case FFEINFO_whereCONSTANT: /* ~~debugging info needed? */
+ case FFEINFO_whereCONSTANT:
+ /* ~~Debugging info needed? */
assert (!ffecom_transform_only_dummies_);
t = error_mark_node; /* Shouldn't ever see this in expr. */
break;
@@ -8199,6 +7721,7 @@ ffecom_sym_transform_ (ffesymbol s)
build_int_2 (offset, 0));
t = convert (build_pointer_type (type),
t);
+ TREE_CONSTANT (t) = staticp (et);
addr = TRUE;
@@ -8537,13 +8060,13 @@ ffecom_sym_transform_ (ffesymbol s)
ffecom_integer_zero_node);
#endif
- /* ~~~gcc/stor-layout.c/layout_type should do this,
+ /* ~~~gcc/stor-layout.c (layout_type) should do this,
probably. Fixes 950302-1.f. */
if (TREE_CODE (low) != INTEGER_CST)
low = variable_size (low);
- /* ~~~similarly, this fixes dumb0.f. The C front end
+ /* ~~~Similarly, this fixes dumb0.f. The C front end
does this, which is why dumb0.c would work. */
if (high && TREE_CODE (high) != INTEGER_CST)
@@ -8715,6 +8238,7 @@ ffecom_sym_transform_ (ffesymbol s)
build_int_2 (offset, 0));
t = convert (build_pointer_type (type),
t);
+ TREE_CONSTANT (t) = 1;
addr = TRUE;
}
@@ -9112,7 +8636,7 @@ ffecom_sym_transform_assign_ (ffesymbol s)
t = build_decl (VAR_DECL,
ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
ffesymbol_text (s),
- 0),
+ -1),
TREE_TYPE (null_pointer_node));
switch (ffesymbol_where (s))
@@ -9432,7 +8956,7 @@ ffecom_transform_equiv_ (ffestorag eqst)
ffesymbol_text
(ffestorag_symbol
(eqst)),
- 0),
+ -1),
eqtype);
DECL_EXTERNAL (eqt) = 0;
if (is_init
@@ -9837,7 +9361,8 @@ ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
ffecom_tree_divide_ (tree tree_type, tree left, tree right,
- tree dest_tree, ffebld dest, bool *dest_used)
+ tree dest_tree, ffebld dest, bool *dest_used,
+ tree hook)
{
if ((left == error_mark_node)
|| (right == error_mark_node))
@@ -9851,6 +9376,10 @@ ffecom_tree_divide_ (tree tree_type, tree left, tree right,
right);
case COMPLEX_TYPE:
+ if (! optimize_size)
+ return ffecom_2 (RDIV_EXPR, tree_type,
+ left,
+ right);
{
ffecomGfrt ix;
@@ -9876,7 +9405,7 @@ ffecom_tree_divide_ (tree tree_type, tree left, tree right,
tree_type,
left,
dest_tree, dest, dest_used,
- NULL_TREE, TRUE);
+ NULL_TREE, TRUE, hook);
}
break;
@@ -9906,7 +9435,7 @@ ffecom_tree_divide_ (tree tree_type, tree left, tree right,
tree_type,
left,
dest_tree, dest, dest_used,
- NULL_TREE, TRUE);
+ NULL_TREE, TRUE, hook);
}
break;
@@ -9918,16 +9447,7 @@ ffecom_tree_divide_ (tree tree_type, tree left, tree right,
}
#endif
-/* ffecom_type_localvar_ -- Build type info for non-dummy variable
-
- tree type;
- ffesymbol s; // the variable's symbol
- ffeinfoBasictype bt; // it's basictype
- ffeinfoKindtype kt; // it's kindtype
-
- type = ffecom_type_localvar_(s,bt,kt);
-
- Handles static arrays, CHARACTER type, etc. */
+/* Build type info for non-dummy variable. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
@@ -10890,6 +10410,7 @@ ffecom_3s (enum tree_code code, tree type, tree node1,
}
#endif
+
/* ffecom_arg_expr -- Transform argument expr into gcc tree
See use by ffecom_list_expr.
@@ -10925,6 +10446,51 @@ ffecom_arg_expr (ffebld expr, tree *length)
}
#endif
+/* Transform expression into constant argument-pointer-to-expression tree.
+
+ If the expression can be transformed into a argument-pointer-to-expression
+ tree that is constant, that is done, and the tree returned. Else
+ NULL_TREE is returned.
+
+ That way, a caller can attempt to provide compile-time initialization
+ of a variable and, if that fails, *then* choose to start a new block
+ and resort to using temporaries, as appropriate. */
+
+tree
+ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
+{
+ if (! expr)
+ return integer_zero_node;
+
+ if (ffebld_op (expr) == FFEBLD_opANY)
+ {
+ if (length)
+ *length = error_mark_node;
+ return error_mark_node;
+ }
+
+ if (ffebld_arity (expr) == 0
+ && (ffebld_op (expr) != FFEBLD_opSYMTER
+ || ffebld_where (expr) == FFEINFO_whereCOMMON
+ || ffebld_where (expr) == FFEINFO_whereGLOBAL
+ || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
+ {
+ tree t;
+
+ t = ffecom_arg_ptr_to_expr (expr, length);
+ assert (TREE_CONSTANT (t));
+ assert (! length || TREE_CONSTANT (*length));
+ return t;
+ }
+
+ if (length
+ && ffebld_size (expr) != FFETARGET_charactersizeNONE)
+ *length = build_int_2 (ffebld_size (expr), 0);
+ else if (length)
+ *length = NULL_TREE;
+ return NULL_TREE;
+}
+
/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
See use by ffecom_list_ptr_to_expr.
@@ -10972,6 +10538,9 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
tree temp_length;
temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
+ if (temp_exp == error_mark_node)
+ return error_mark_node;
+
return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
temp_exp);
}
@@ -11029,6 +10598,9 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
assert (ffeinfo_kindtype (ffebld_info (expr))
== FFEINFO_kindtypeCHARACTER1);
+ while (ffebld_op (expr) == FFEBLD_opPAREN)
+ expr = ffebld_left (expr);
+
catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
switch (ffecom_concat_list_count_ (catlist))
{
@@ -11070,6 +10642,11 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
tree known_length;
ffetargetCharacterSize sz;
+ sz = ffecom_concat_list_maxlen_ (catlist);
+ /* ~~Kludge! */
+ assert (sz != FFETARGET_charactersizeNONE);
+
+#ifdef HOHO
length_array
= lengths
= ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
@@ -11078,6 +10655,21 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
= items
= ffecom_push_tempvar (ffecom_f2c_address_type_node,
FFETARGET_charactersizeNONE, count, TRUE);
+ temporary = ffecom_push_tempvar (char_type_node,
+ sz, -1, TRUE);
+#else
+ {
+ tree hook;
+
+ hook = ffebld_nonter_hook (expr);
+ assert (hook);
+ assert (TREE_CODE (hook) == TREE_VEC);
+ assert (TREE_VEC_LENGTH (hook) == 3);
+ length_array = lengths = TREE_VEC_ELT (hook, 0);
+ item_array = items = TREE_VEC_ELT (hook, 1);
+ temporary = TREE_VEC_ELT (hook, 2);
+ }
+#endif
known_length = ffecom_f2c_ftnlen_zero_node;
@@ -11124,11 +10716,6 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
lengths);
}
- sz = ffecom_concat_list_maxlen_ (catlist);
- assert (sz != FFETARGET_charactersizeNONE);
-
- temporary = ffecom_push_tempvar (char_type_node,
- sz, -1, TRUE);
temporary = ffecom_1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (temporary)),
temporary);
@@ -11155,7 +10742,7 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
= build_tree_list (NULL_TREE, num);
- item = ffecom_call_gfrt (FFECOM_gfrtCAT, item);
+ item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
TREE_SIDE_EFFECTS (item) = 1;
item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
item,
@@ -11171,10 +10758,7 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
}
#endif
-/* ffecom_call_gfrt -- Generate call to run-time function
-
- tree expr;
- expr = ffecom_call_gfrt(FFECOM_gfrtSTOPNIL,NULL_TREE);
+/* Generate call to run-time function.
The first arg is the GNU Fortran Run-Time function index, the second
arg is the list of arguments to pass to it. Returned is the expression
@@ -11183,23 +10767,17 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
#if FFECOM_targetCURRENT == FFECOM_targetGCC
tree
-ffecom_call_gfrt (ffecomGfrt ix, tree args)
+ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
{
return ffecom_call_ (ffecom_gfrt_tree_ (ix),
ffecom_gfrt_kindtype (ix),
ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
NULL_TREE, args, NULL_TREE, NULL,
- NULL, NULL_TREE, TRUE);
+ NULL, NULL_TREE, TRUE, hook);
}
#endif
-/* ffecom_constantunion -- Transform constant-union to tree
-
- ffebldConstantUnion cu; // the constant to transform
- ffeinfoBasictype bt; // its basic type
- ffeinfoKindtype kt; // its kind type
- tree tree_type; // ffecom_tree_type[bt][kt]
- ffecom_constantunion(&cu,bt,kt,tree_type); */
+/* Transform constant-union to tree. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
tree
@@ -11471,12 +11049,49 @@ ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
#endif
+/* Transform expression into constant tree.
+
+ If the expression can be transformed into a tree that is constant,
+ that is done, and the tree returned. Else NULL_TREE is returned.
+
+ That way, a caller can attempt to provide compile-time initialization
+ of a variable and, if that fails, *then* choose to start a new block
+ and resort to using temporaries, as appropriate. */
+
+tree
+ffecom_const_expr (ffebld expr)
+{
+ if (! expr)
+ return integer_zero_node;
+
+ if (ffebld_op (expr) == FFEBLD_opANY)
+ return error_mark_node;
+
+ if (ffebld_arity (expr) == 0
+ && (ffebld_op (expr) != FFEBLD_opSYMTER
+#if NEWCOMMON
+ /* ~~Enable once common/equivalence is handled properly? */
+ || ffebld_where (expr) == FFEINFO_whereCOMMON
+#endif
+ || ffebld_where (expr) == FFEINFO_whereGLOBAL
+ || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
+ {
+ tree t;
+
+ t = ffecom_expr (expr);
+ assert (TREE_CONSTANT (t));
+ return t;
+ }
+
+ return NULL_TREE;
+}
+
/* Handy way to make a field in a struct/union. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
tree
ffecom_decl_field (tree context, tree prevfield,
- char *name, tree type)
+ const char *name, tree type)
{
tree field;
@@ -11509,6 +11124,16 @@ ffecom_decode_include_option (char *spec)
#endif
}
+/* End a compound statement (block). */
+
+#if FFECOM_targetCURRENT == FFECOM_targetGCC
+tree
+ffecom_end_compstmt (void)
+{
+ return bison_rule_compstmt_ ();
+}
+#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
+
/* ffecom_end_transition -- Perform end transition on all symbols
ffecom_end_transition();
@@ -11630,11 +11255,7 @@ ffecom_exec_transition ()
ffebad_set_inhibit (TRUE);
}
-/* ffecom_expand_let_stmt -- Compile let (assignment) statement
-
- ffebld dest;
- ffebld source;
- ffecom_expand_let_stmt(dest,source);
+/* Handle assignment statement.
Convert dest and source using ffecom_expr, then join them
with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
@@ -11651,8 +11272,46 @@ ffecom_expand_let_stmt (ffebld dest, ffebld source)
if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
{
bool dest_used;
+ tree assign_temp;
+
+ /* This attempts to replicate the test below, but must not be
+ true when the test below is false. (Always err on the side
+ of creating unused temporaries, to avoid ICEs.) */
+ if (ffebld_op (dest) != FFEBLD_opSYMTER
+ || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
+ && (TREE_CODE (dest_tree) != VAR_DECL
+ || TREE_ADDRESSABLE (dest_tree))))
+ {
+ ffecom_prepare_expr_ (source, dest);
+ dest_used = TRUE;
+ }
+ else
+ {
+ ffecom_prepare_expr_ (source, NULL);
+ dest_used = FALSE;
+ }
+
+ ffecom_prepare_expr_w (NULL_TREE, dest);
+
+ /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
+ create a temporary through which the assignment is to take place,
+ since MODIFY_EXPR doesn't handle partial overlap properly. */
+ if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
+ && ffecom_possible_partial_overlap_ (dest, source))
+ {
+ assign_temp = ffecom_make_tempvar ("complex_let",
+ ffecom_tree_type
+ [ffebld_basictype (dest)]
+ [ffebld_kindtype (dest)],
+ FFETARGET_charactersizeNONE,
+ -1);
+ }
+ else
+ assign_temp = NULL_TREE;
- dest_tree = ffecom_expr_rw (dest);
+ ffecom_prepare_end ();
+
+ dest_tree = ffecom_expr_w (NULL_TREE, dest);
if (dest_tree == error_mark_node)
return;
@@ -11662,14 +11321,36 @@ ffecom_expand_let_stmt (ffebld dest, ffebld source)
FALSE, FALSE);
else
{
- source_tree = ffecom_expr (source);
+ assert (! dest_used);
dest_used = FALSE;
+ source_tree = ffecom_expr (source);
}
if (source_tree == error_mark_node)
return;
if (dest_used)
expr_tree = source_tree;
+ else if (assign_temp)
+ {
+#ifdef MOVE_EXPR
+ /* The back end understands a conceptual move (evaluate source;
+ store into dest), so use that, in case it can determine
+ that it is going to use, say, two registers as temporaries
+ anyway. So don't use the temp (and someday avoid generating
+ it, once this code starts triggering regularly). */
+ expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
+ dest_tree,
+ source_tree);
+#else
+ expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
+ assign_temp,
+ source_tree);
+ expand_expr_stmt (expr_tree);
+ expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
+ dest_tree,
+ assign_temp);
+#endif
+ }
else
expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
dest_tree,
@@ -11679,11 +11360,14 @@ ffecom_expand_let_stmt (ffebld dest, ffebld source)
return;
}
- ffecom_push_calltemps ();
+ ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
+ ffecom_prepare_expr_w (NULL_TREE, dest);
+
+ ffecom_prepare_end ();
+
ffecom_char_args_ (&dest_tree, &dest_length, dest);
ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
source);
- ffecom_pop_calltemps ();
}
#endif
@@ -11732,9 +11416,29 @@ ffecom_expr_assign_w (ffebld expr)
#if FFECOM_targetCURRENT == FFECOM_targetGCC
tree
-ffecom_expr_rw (ffebld expr)
+ffecom_expr_rw (tree type, ffebld expr)
+{
+ assert (expr != NULL);
+ /* Different target types not yet supported. */
+ assert (type == NULL_TREE || type == ffecom_type_expr (expr));
+
+ return stabilize_reference (ffecom_expr (expr));
+}
+
+#endif
+/* Transform expr for use as into write tree and stabilize the
+ reference. Not for use on CHARACTER expressions.
+
+ Recursive descent on expr while making corresponding tree nodes and
+ attaching type info and such. */
+
+#if FFECOM_targetCURRENT == FFECOM_targetGCC
+tree
+ffecom_expr_w (tree type, ffebld expr)
{
assert (expr != NULL);
+ /* Different target types not yet supported. */
+ assert (type == NULL_TREE || type == ffecom_type_expr (expr));
return stabilize_reference (ffecom_expr (expr));
}
@@ -11770,7 +11474,7 @@ ffecom_finish_decl (tree decl, tree init, bool is_top_level)
void
ffecom_finish_progunit ()
{
- ffecom_end_compstmt_ ();
+ ffecom_end_compstmt ();
ffecom_previous_function_decl_ = current_function_decl;
ffecom_which_entrypoint_decl_ = NULL_TREE;
@@ -11779,33 +11483,54 @@ ffecom_finish_progunit ()
}
#endif
-/* Wrapper for get_identifier. pattern is like "...%s...", text is
- inserted into final name in place of "%s", or if text is NULL,
- pattern is like "...%d..." and text form of number is inserted
- in place of "%d". */
+/* Wrapper for get_identifier. pattern is sprintf-like, assumed to contain
+ one %s if text is not NULL, assumed to contain one %d if number is
+ not -1. If both are assumed, the %s is assumed to precede the %d. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
tree
-ffecom_get_invented_identifier (char *pattern, char *text, int number)
+ffecom_get_invented_identifier (const char *pattern, const char *text,
+ int number)
{
tree decl;
char *nam;
mallocSize lenlen;
char space[66];
- if (text == NULL)
- lenlen = strlen (pattern) + 20;
- else
- lenlen = strlen (pattern) + strlen (text) - 1;
- if (lenlen > ARRAY_SIZE (space))
- nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
+ lenlen = 0;
+ if (text)
+ lenlen += strlen (text);
+ if (number != -1)
+ lenlen += 20;
+ if (text || number != -1)
+ {
+ lenlen += strlen (pattern);
+ if (lenlen > ARRAY_SIZE (space))
+ nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
+ else
+ nam = &space[0];
+ }
else
- nam = &space[0];
+ {
+ lenlen = 0;
+ nam = (char *) pattern;
+ }
+
if (text == NULL)
- sprintf (&nam[0], pattern, number);
+ {
+ if (number != -1)
+ sprintf (&nam[0], pattern, number);
+ }
else
- sprintf (&nam[0], pattern, text);
+ {
+ if (number == -1)
+ sprintf (&nam[0], pattern, text);
+ else
+ sprintf (&nam[0], pattern, text, number);
+ }
+
decl = get_identifier (nam);
+
if (lenlen > ARRAY_SIZE (space))
malloc_kill_ks (malloc_pool_image (), nam, lenlen);
@@ -11958,12 +11683,6 @@ ffecom_init_0 ()
}
}
- /* Set the sizetype before we do anything else. This _should_ be the
- first type we create. */
-
- t = make_unsigned_type (POINTER_SIZE);
- assert (t == sizetype);
-
#if FFECOM_GCC_INCLUDE
ffecom_initialize_char_syntax_ ();
#endif
@@ -11973,9 +11692,10 @@ ffecom_init_0 ()
named_labels = NULL_TREE;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
- pushlevel (0); /* make the binding_level structure for
- global names */
+ /* Make the binding_level structure for global names. */
+ pushlevel (0);
global_binding_level = current_binding_level;
+ current_binding_level->prep_state = 2;
/* Define `int' and `char' first so that dbx will output them first. */
@@ -12007,9 +11727,6 @@ ffecom_init_0 ()
pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
long_long_unsigned_type_node));
- error_mark_node = make_node (ERROR_MARK);
- TREE_TYPE (error_mark_node) = error_mark_node;
-
short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
short_integer_type_node));
@@ -12018,6 +11735,17 @@ ffecom_init_0 ()
pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
short_unsigned_type_node));
+ /* Set the sizetype before we make other types. This *should* be the
+ first type we create. */
+
+ set_sizetype
+ (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
+ ffecom_typesize_pointer_
+ = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
+
+ error_mark_node = make_node (ERROR_MARK);
+ TREE_TYPE (error_mark_node) = error_mark_node;
+
/* Define both `signed char' and `unsigned char'. */
signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
@@ -12136,6 +11864,7 @@ ffecom_init_0 ()
TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
type);
ffetype_set_kind (base_type, 1, type);
+ ffecom_typesize_integer1_ = ffetype_size (type);
assert (ffetype_size (type) == sizeof (ffetargetInteger1));
ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
@@ -12448,8 +12177,9 @@ ffecom_init_0 ()
FFETARGET_f2cTYLOGICAL2);
ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
FFETARGET_f2cTYLOGICAL1);
+ /* ~~~Not really such a type in libf2c, e.g. I/O support? */
ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
- FFETARGET_f2cTYQUAD /* ~~~ */);
+ FFETARGET_f2cTYQUAD);
/* CHARACTER stuff is all special-cased, so it is not handled in the above
loop. CHARACTER items are built as arrays of unsigned char. */
@@ -12670,7 +12400,6 @@ ffecom_init_2 ()
ffecom_master_arglist_ = NULL;
++ffecom_num_fns_;
- ffecom_latest_temp_ = NULL;
ffecom_primary_entry_ = NULL;
ffecom_is_altreturning_ = FALSE;
ffecom_func_result_ = NULL_TREE;
@@ -12698,9 +12427,12 @@ ffecom_list_expr (ffebld expr)
while (expr != NULL)
{
- *plist
- = build_tree_list (NULL_TREE, ffecom_arg_expr (ffebld_head (expr),
- &length));
+ tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
+
+ if (texpr == error_mark_node)
+ return error_mark_node;
+
+ *plist = build_tree_list (NULL_TREE, texpr);
plist = &TREE_CHAIN (*plist);
expr = ffebld_trail (expr);
if (length != NULL_TREE)
@@ -12737,10 +12469,12 @@ ffecom_list_ptr_to_expr (ffebld expr)
while (expr != NULL)
{
- *plist
- = build_tree_list (NULL_TREE,
- ffecom_arg_ptr_to_expr (ffebld_head (expr),
- &length));
+ tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
+
+ if (texpr == error_mark_node)
+ return error_mark_node;
+
+ *plist = build_tree_list (NULL_TREE, texpr);
plist = &TREE_CHAIN (*plist);
expr = ffebld_trail (expr);
if (length != NULL_TREE)
@@ -13089,65 +12823,6 @@ ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
#endif
}
-/* Clean up after making automatically popped call-arg temps.
-
- Call this in pairs with push_calltemps around calls to
- ffecom_arg_ptr_to_expr if the latter might use temporaries.
- Any temporaries made within the outermost sequence of
- push_calltemps and pop_calltemps, that are marked as "auto-pop"
- meaning they won't be explicitly popped (freed), are popped
- at this point so they can be reused later.
-
- NOTE: when called by ffecom_gen_sfuncdef_, ffecom_pending_calls_
- should come in == 1, and all of the in-use auto-pop temps
- should have DECL_CONTEXT (temp->t) == current_function_decl.
- Moreover, these temps should _never_ be re-used in future
- calls to ffecom_push_tempvar -- since current_function_decl will
- never be the same again.
-
- SO, it could be a minor win in terms of compile time to just
- strip these temps off the list. That is, if the above assumptions
- are correct, just remove from the list of temps any temp
- that is both in-use and has DECL_CONTEXT (temp->t)
- == current_function_decl, when called from ffecom_gen_sfuncdef_. */
-
-#if FFECOM_targetCURRENT == FFECOM_targetGCC
-void
-ffecom_pop_calltemps ()
-{
- ffecomTemp_ temp;
-
- assert (ffecom_pending_calls_ > 0);
-
- if (--ffecom_pending_calls_ == 0)
- for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
- if (temp->auto_pop)
- temp->in_use = FALSE;
-}
-
-#endif
-/* Mark latest temp with given tree as no longer in use. */
-
-#if FFECOM_targetCURRENT == FFECOM_targetGCC
-void
-ffecom_pop_tempvar (tree t)
-{
- ffecomTemp_ temp;
-
- for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
- if (temp->in_use && (temp->t == t))
- {
- assert (!temp->auto_pop);
- temp->in_use = FALSE;
- return;
- }
- else
- assert (temp->t != t);
-
- assert ("couldn't ffecom_pop_tempvar!" != NULL);
-}
-
-#endif
/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
tree t;
@@ -13201,49 +12876,7 @@ ffecom_ptr_to_expr (ffebld expr)
return item;
case FFEBLD_opARRAYREF:
- {
- ffebld dims[FFECOM_dimensionsMAX];
- tree array;
- int i;
-
- item = ffecom_ptr_to_expr (ffebld_left (expr));
-
- if (item == error_mark_node)
- return item;
-
- if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
- && !mark_addressable (item))
- return error_mark_node; /* Make sure non-const ref is to
- non-reg. */
-
- /* Build up ARRAY_REFs in reverse order (since we're column major
- here in Fortran land). */
-
- for (i = 0, expr = ffebld_right (expr);
- expr != NULL;
- expr = ffebld_trail (expr))
- dims[i++] = ffebld_head (expr);
-
- for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
- i >= 0;
- --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
- {
- /* The initial subtraction should happen in the original type so
- that (possible) negative values are handled appropriately. */
- item
- = ffecom_2 (PLUS_EXPR,
- build_pointer_type (TREE_TYPE (array)),
- item,
- size_binop (MULT_EXPR,
- size_in_bytes (TREE_TYPE (array)),
- convert (sizetype,
- fold (build (MINUS_EXPR,
- TREE_TYPE (TYPE_MIN_VALUE (TYPE_DOMAIN (array))),
- ffecom_expr (dims[i]),
- TYPE_MIN_VALUE (TYPE_DOMAIN (array)))))));
- }
- }
- return item;
+ return ffecom_arrayref_ (NULL_TREE, expr, 1);
case FFEBLD_opCONTER:
@@ -13263,8 +12896,6 @@ ffecom_ptr_to_expr (ffebld expr)
return error_mark_node;
default:
- assert (ffecom_pending_calls_ > 0);
-
bt = ffeinfo_basictype (ffebld_info (expr));
kt = ffeinfo_kindtype (ffebld_info (expr));
@@ -13304,60 +12935,27 @@ ffecom_ptr_to_expr (ffebld expr)
}
#endif
-/* Prepare to make call-arg temps.
-
- Call this in pairs with pop_calltemps around calls to
- ffecom_arg_ptr_to_expr if the latter might use temporaries. */
-
-#if FFECOM_targetCURRENT == FFECOM_targetGCC
-void
-ffecom_push_calltemps ()
-{
- ffecom_pending_calls_++;
-}
-
-#endif
/* Obtain a temp var with given data type.
- Returns a VAR_DECL tree of a currently (that is, at the current
- statement being compiled) not in use and having the given data type,
- making a new one if necessary. size is FFETARGET_charactersizeNONE
- for a non-CHARACTER type or >= 0 for a CHARACTER type. elements is
- -1 for a scalar or > 0 for an array of type. auto_pop is TRUE if
- ffecom_pop_tempvar won't be called, meaning temp will be freed
- when #pending calls goes to zero. */
+ size is FFETARGET_charactersizeNONE for a non-CHARACTER type
+ or >= 0 for a CHARACTER type.
+
+ elements is -1 for a scalar or > 0 for an array of type. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
tree
-ffecom_push_tempvar (tree type, ffetargetCharacterSize size, int elements,
- bool auto_pop)
+ffecom_make_tempvar (const char *commentary, tree type,
+ ffetargetCharacterSize size, int elements)
{
- ffecomTemp_ temp;
int yes;
tree t;
static int mynumber;
- assert (!auto_pop || (ffecom_pending_calls_ > 0));
+ assert (current_binding_level->prep_state < 2);
if (type == error_mark_node)
return error_mark_node;
- for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
- {
- if (temp->in_use
- || (temp->type != type)
- || (temp->size != size)
- || (temp->elements != elements)
- || (DECL_CONTEXT (temp->t) != current_function_decl))
- continue;
-
- temp->in_use = TRUE;
- temp->auto_pop = auto_pop;
- return temp->t;
- }
-
- /* Create a new temp. */
-
yes = suspend_momentary ();
if (size != FFETARGET_charactersizeNONE)
@@ -13372,42 +12970,378 @@ ffecom_push_tempvar (tree type, ffetargetCharacterSize size, int elements,
build_int_2 (elements - 1,
0)));
t = build_decl (VAR_DECL,
- ffecom_get_invented_identifier ("__g77_expr_%d", NULL,
+ ffecom_get_invented_identifier ("__g77_%s_%d",
+ commentary,
mynumber++),
type);
- /* This temp must be put in the same scope as the containing BLOCK
- (aka function), but for reasons that should be explained elsewhere,
- the GBE normally decides it should be in a "phantom BLOCK" associated
- with the expand_start_stmt_expr() call. So push the topmost
- sequence back onto the GBE's internal stack before telling it
- about the decl, then restore it afterwards. */
- push_topmost_sequence ();
-
t = start_decl (t, FALSE);
finish_decl (t, NULL_TREE, FALSE);
- pop_topmost_sequence ();
-
resume_momentary (yes);
- temp = malloc_new_kp (ffe_pool_program_unit (), "ffecomTemp_",
- sizeof (*temp));
+ return t;
+}
+#endif
- temp->next = ffecom_latest_temp_;
- temp->type = type;
- temp->t = t;
- temp->size = size;
- temp->elements = elements;
- temp->in_use = TRUE;
- temp->auto_pop = auto_pop;
+/* Prepare argument pointer to expression.
- ffecom_latest_temp_ = temp;
+ Like ffecom_prepare_expr, except for expressions to be evaluated
+ via ffecom_arg_ptr_to_expr. */
- return t;
+void
+ffecom_prepare_arg_ptr_to_expr (ffebld expr)
+{
+ /* ~~For now, it seems to be the same thing. */
+ ffecom_prepare_expr (expr);
+ return;
+}
+
+/* End of preparations. */
+
+bool
+ffecom_prepare_end (void)
+{
+ int prep_state = current_binding_level->prep_state;
+
+ assert (prep_state < 2);
+ current_binding_level->prep_state = 2;
+
+ return (prep_state == 1) ? TRUE : FALSE;
+}
+
+/* Prepare expression.
+
+ This is called before any code is generated for the current block.
+ It scans the expression, declares any temporaries that might be needed
+ during evaluation of the expression, and stores those temporaries in
+ the appropriate "hook" fields of the expression. `dest', if not NULL,
+ specifies the destination that ffecom_expr_ will see, in case that
+ helps avoid generating unused temporaries.
+
+ ~~Improve to avoid allocating unused temporaries by taking `dest'
+ into account vis-a-vis aliasing requirements of complex/character
+ functions. */
+
+void
+ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
+{
+ ffeinfoBasictype bt;
+ ffeinfoKindtype kt;
+ ffetargetCharacterSize sz;
+ tree tempvar = NULL_TREE;
+
+ assert (current_binding_level->prep_state < 2);
+
+ if (! expr)
+ return;
+
+ bt = ffeinfo_basictype (ffebld_info (expr));
+ kt = ffeinfo_kindtype (ffebld_info (expr));
+ sz = ffeinfo_size (ffebld_info (expr));
+
+ /* Generate whatever temporaries are needed to represent the result
+ of the expression. */
+
+ if (bt == FFEINFO_basictypeCHARACTER)
+ {
+ while (ffebld_op (expr) == FFEBLD_opPAREN)
+ expr = ffebld_left (expr);
+ }
+
+ switch (ffebld_op (expr))
+ {
+ default:
+ /* Don't make temps for SYMTER, CONTER, etc. */
+ if (ffebld_arity (expr) == 0)
+ break;
+
+ switch (bt)
+ {
+ case FFEINFO_basictypeCOMPLEX:
+ if (ffebld_op (expr) == FFEBLD_opFUNCREF)
+ {
+ ffesymbol s;
+
+ if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
+ break;
+
+ s = ffebld_symter (ffebld_left (expr));
+ if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
+ || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
+ && ! ffesymbol_is_f2c (s))
+ || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
+ && ! ffe_is_f2c_library ()))
+ break;
+ }
+ else if (ffebld_op (expr) == FFEBLD_opPOWER)
+ {
+ /* Requires special treatment. There's no POW_CC function
+ in libg2c, so POW_ZZ is used, which means we always
+ need a double-complex temp, not a single-complex. */
+ kt = FFEINFO_kindtypeREAL2;
+ }
+ else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
+ /* The other ops don't need temps for complex operands. */
+ break;
+
+ /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
+ REAL(C). See 19990325-0.f, routine `check', for cases. */
+ tempvar = ffecom_make_tempvar ("complex",
+ ffecom_tree_type
+ [FFEINFO_basictypeCOMPLEX][kt],
+ FFETARGET_charactersizeNONE,
+ -1);
+ break;
+
+ case FFEINFO_basictypeCHARACTER:
+ if (ffebld_op (expr) != FFEBLD_opFUNCREF)
+ break;
+
+ if (sz == FFETARGET_charactersizeNONE)
+ /* ~~Kludge alert! This should someday be fixed. */
+ sz = 24;
+
+ tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+#ifdef HAHA
+ case FFEBLD_opPOWER:
+ {
+ tree rtype, ltype;
+ tree rtmp, ltmp, result;
+
+ ltype = ffecom_type_expr (ffebld_left (expr));
+ rtype = ffecom_type_expr (ffebld_right (expr));
+
+ rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
+ ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
+ result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
+
+ tempvar = make_tree_vec (3);
+ TREE_VEC_ELT (tempvar, 0) = rtmp;
+ TREE_VEC_ELT (tempvar, 1) = ltmp;
+ TREE_VEC_ELT (tempvar, 2) = result;
+ }
+ break;
+#endif /* HAHA */
+
+ case FFEBLD_opCONCATENATE:
+ {
+ /* This gets special handling, because only one set of temps
+ is needed for a tree of these -- the tree is treated as
+ a flattened list of concatenations when generating code. */
+
+ ffecomConcatList_ catlist;
+ tree ltmp, itmp, result;
+ int count;
+ int i;
+
+ catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
+ count = ffecom_concat_list_count_ (catlist);
+
+ if (count >= 2)
+ {
+ ltmp
+ = ffecom_make_tempvar ("concat_len",
+ ffecom_f2c_ftnlen_type_node,
+ FFETARGET_charactersizeNONE, count);
+ itmp
+ = ffecom_make_tempvar ("concat_item",
+ ffecom_f2c_address_type_node,
+ FFETARGET_charactersizeNONE, count);
+ result
+ = ffecom_make_tempvar ("concat_res",
+ char_type_node,
+ ffecom_concat_list_maxlen_ (catlist),
+ -1);
+
+ tempvar = make_tree_vec (3);
+ TREE_VEC_ELT (tempvar, 0) = ltmp;
+ TREE_VEC_ELT (tempvar, 1) = itmp;
+ TREE_VEC_ELT (tempvar, 2) = result;
+ }
+
+ for (i = 0; i < count; ++i)
+ ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
+ i));
+
+ ffecom_concat_list_kill_ (catlist);
+
+ if (tempvar)
+ {
+ ffebld_nonter_set_hook (expr, tempvar);
+ current_binding_level->prep_state = 1;
+ }
+ }
+ return;
+
+ case FFEBLD_opCONVERT:
+ if (bt == FFEINFO_basictypeCHARACTER
+ && ((ffebld_size_known (ffebld_left (expr))
+ == FFETARGET_charactersizeNONE)
+ || (ffebld_size_known (ffebld_left (expr)) >= sz)))
+ tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
+ break;
+ }
+
+ if (tempvar)
+ {
+ ffebld_nonter_set_hook (expr, tempvar);
+ current_binding_level->prep_state = 1;
+ }
+
+ /* Prepare subexpressions for this expr. */
+
+ switch (ffebld_op (expr))
+ {
+ case FFEBLD_opPERCENT_LOC:
+ ffecom_prepare_ptr_to_expr (ffebld_left (expr));
+ break;
+
+ case FFEBLD_opPERCENT_VAL:
+ case FFEBLD_opPERCENT_REF:
+ ffecom_prepare_expr (ffebld_left (expr));
+ break;
+
+ case FFEBLD_opPERCENT_DESCR:
+ ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
+ break;
+
+ case FFEBLD_opITEM:
+ {
+ ffebld item;
+
+ for (item = expr;
+ item != NULL;
+ item = ffebld_trail (item))
+ if (ffebld_head (item) != NULL)
+ ffecom_prepare_expr (ffebld_head (item));
+ }
+ break;
+
+ default:
+ /* Need to handle character conversion specially. */
+ switch (ffebld_arity (expr))
+ {
+ case 2:
+ ffecom_prepare_expr (ffebld_left (expr));
+ ffecom_prepare_expr (ffebld_right (expr));
+ break;
+
+ case 1:
+ ffecom_prepare_expr (ffebld_left (expr));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return;
+}
+
+/* Prepare expression for reading and writing.
+
+ Like ffecom_prepare_expr, except for expressions to be evaluated
+ via ffecom_expr_rw. */
+
+void
+ffecom_prepare_expr_rw (tree type, ffebld expr)
+{
+ /* This is all we support for now. */
+ assert (type == NULL_TREE || type == ffecom_type_expr (expr));
+
+ /* ~~For now, it seems to be the same thing. */
+ ffecom_prepare_expr (expr);
+ return;
+}
+
+/* Prepare expression for writing.
+
+ Like ffecom_prepare_expr, except for expressions to be evaluated
+ via ffecom_expr_w. */
+
+void
+ffecom_prepare_expr_w (tree type, ffebld expr)
+{
+ /* This is all we support for now. */
+ assert (type == NULL_TREE || type == ffecom_type_expr (expr));
+
+ /* ~~For now, it seems to be the same thing. */
+ ffecom_prepare_expr (expr);
+ return;
+}
+
+/* Prepare expression for returning.
+
+ Like ffecom_prepare_expr, except for expressions to be evaluated
+ via ffecom_return_expr. */
+
+void
+ffecom_prepare_return_expr (ffebld expr)
+{
+ assert (current_binding_level->prep_state < 2);
+
+ if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
+ && ffecom_is_altreturning_
+ && expr != NULL)
+ ffecom_prepare_expr (expr);
+}
+
+/* Prepare pointer to expression.
+
+ Like ffecom_prepare_expr, except for expressions to be evaluated
+ via ffecom_ptr_to_expr. */
+
+void
+ffecom_prepare_ptr_to_expr (ffebld expr)
+{
+ /* ~~For now, it seems to be the same thing. */
+ ffecom_prepare_expr (expr);
+ return;
+}
+
+/* Transform expression into constant pointer-to-expression tree.
+
+ If the expression can be transformed into a pointer-to-expression tree
+ that is constant, that is done, and the tree returned. Else NULL_TREE
+ is returned.
+
+ That way, a caller can attempt to provide compile-time initialization
+ of a variable and, if that fails, *then* choose to start a new block
+ and resort to using temporaries, as appropriate. */
+
+tree
+ffecom_ptr_to_const_expr (ffebld expr)
+{
+ if (! expr)
+ return integer_zero_node;
+
+ if (ffebld_op (expr) == FFEBLD_opANY)
+ return error_mark_node;
+
+ if (ffebld_arity (expr) == 0
+ && (ffebld_op (expr) != FFEBLD_opSYMTER
+ || ffebld_where (expr) == FFEINFO_whereCOMMON
+ || ffebld_where (expr) == FFEINFO_whereGLOBAL
+ || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
+ {
+ tree t;
+
+ t = ffecom_ptr_to_expr (expr);
+ assert (TREE_CONSTANT (t));
+ return t;
+ }
+
+ return NULL_TREE;
}
-#endif
/* ffecom_return_expr -- Returns return-value expr given alt return expr
tree rtn; // NULL_TREE means use expand_null_return()
@@ -13503,6 +13437,16 @@ ffecom_save_tree (tree t)
}
#endif
+/* Start a compound statement (block). */
+
+#if FFECOM_targetCURRENT == FFECOM_targetGCC
+void
+ffecom_start_compstmt (void)
+{
+ bison_rule_pushlevel_ ();
+}
+#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
+
/* Public entry point for front end to access start_decl. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
@@ -13747,6 +13691,74 @@ ffecom_truth_value_invert (tree expr)
}
#endif
+
+/* Return the tree that is the type of the expression, as would be
+ returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
+ transforming the expression, generating temporaries, etc. */
+
+tree
+ffecom_type_expr (ffebld expr)
+{
+ ffeinfoBasictype bt;
+ ffeinfoKindtype kt;
+ tree tree_type;
+
+ assert (expr != NULL);
+
+ bt = ffeinfo_basictype (ffebld_info (expr));
+ kt = ffeinfo_kindtype (ffebld_info (expr));
+ tree_type = ffecom_tree_type[bt][kt];
+
+ switch (ffebld_op (expr))
+ {
+ case FFEBLD_opCONTER:
+ case FFEBLD_opSYMTER:
+ case FFEBLD_opARRAYREF:
+ case FFEBLD_opUPLUS:
+ case FFEBLD_opPAREN:
+ case FFEBLD_opUMINUS:
+ case FFEBLD_opADD:
+ case FFEBLD_opSUBTRACT:
+ case FFEBLD_opMULTIPLY:
+ case FFEBLD_opDIVIDE:
+ case FFEBLD_opPOWER:
+ case FFEBLD_opNOT:
+ case FFEBLD_opFUNCREF:
+ case FFEBLD_opSUBRREF:
+ case FFEBLD_opAND:
+ case FFEBLD_opOR:
+ case FFEBLD_opXOR:
+ case FFEBLD_opNEQV:
+ case FFEBLD_opEQV:
+ case FFEBLD_opCONVERT:
+ case FFEBLD_opLT:
+ case FFEBLD_opLE:
+ case FFEBLD_opEQ:
+ case FFEBLD_opNE:
+ case FFEBLD_opGT:
+ case FFEBLD_opGE:
+ case FFEBLD_opPERCENT_LOC:
+ return tree_type;
+
+ case FFEBLD_opACCTER:
+ case FFEBLD_opARRTER:
+ case FFEBLD_opITEM:
+ case FFEBLD_opSTAR:
+ case FFEBLD_opBOUNDS:
+ case FFEBLD_opREPEAT:
+ case FFEBLD_opLABTER:
+ case FFEBLD_opLABTOK:
+ case FFEBLD_opIMPDO:
+ case FFEBLD_opCONCATENATE:
+ case FFEBLD_opSUBSTR:
+ default:
+ assert ("bad op for ffecom_type_expr" == NULL);
+ /* Fall through. */
+ case FFEBLD_opANY:
+ return error_mark_node;
+ }
+}
+
/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
If the PARM_DECL already exists, return it, else create it. It's an
@@ -13784,15 +13796,6 @@ ffecom_which_entrypoint_decl ()
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
-bison_rule_compstmt_ ()
-{
- emit_line_note (input_filename, lineno);
- expand_end_bindings (getdecls (), 1, 1);
- poplevel (1, 1, 0);
- pop_momentary ();
-}
-
-static void
bison_rule_pushlevel_ ()
{
emit_line_note (input_filename, lineno);
@@ -13802,6 +13805,24 @@ bison_rule_pushlevel_ ()
expand_start_bindings (0);
}
+static tree
+bison_rule_compstmt_ ()
+{
+ tree t;
+ int keep = kept_level_p ();
+
+ /* Make the temps go away. */
+ if (! keep)
+ current_binding_level->names = NULL_TREE;
+
+ emit_line_note (input_filename, lineno);
+ expand_end_bindings (getdecls (), keep, 0);
+ t = poplevel (keep, 1, 0);
+ pop_momentary ();
+
+ return t;
+}
+
/* Return a definition for a builtin function named NAME and whose data type
is TYPE. TYPE should be a function type with argument types.
FUNCTION_CODE tells later passes how to compile calls to this function.
@@ -13811,8 +13832,9 @@ bison_rule_pushlevel_ ()
the name to be called if we can't opencode the function. */
static tree
-builtin_function (char *name, tree type,
- enum built_in_function function_code, char *library_name)
+builtin_function (const char *name, tree type,
+ enum built_in_function function_code,
+ const char *library_name)
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
@@ -14360,7 +14382,9 @@ finish_function (int nested)
if (!nested)
permanent_allocation (1);
- if (DECL_SAVED_INSNS (fndecl) == 0 && !nested && (TREE_CODE (fndecl) != ERROR_MARK))
+ if (TREE_CODE (fndecl) != ERROR_MARK
+ && !nested
+ && DECL_SAVED_INSNS (fndecl) == 0)
{
/* Stop pointing to the local nodes about to be freed. */
/* But DECL_INITIAL must remain nonzero so we know this was an actual
@@ -14416,7 +14440,7 @@ lang_print_error_function (file)
static ffesymbol last_s = NULL;
ffeglobal g;
ffesymbol s;
- char *kind;
+ const char *kind;
if ((ffecom_primary_entry_ == NULL)
|| (ffesymbol_global (ffecom_primary_entry_) == NULL))
@@ -14470,7 +14494,7 @@ lang_print_error_function (file)
fprintf (stderr, "Outside of any program unit:\n");
else
{
- char *name = ffesymbol_text (s);
+ const char *name = ffesymbol_text (s);
fprintf (stderr, "In %s `%s':\n", kind, name);
}
@@ -14538,7 +14562,8 @@ pop_f_function_context ()
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
= TREE_VALUE (link);
- if (DECL_SAVED_INSNS (current_function_decl) == 0)
+ if (current_function_decl != error_mark_node
+ && DECL_SAVED_INSNS (current_function_decl) == 0)
{
/* Stop pointing to the local nodes about to be freed. */
/* But DECL_INITIAL must remain nonzero so we know this was an actual
@@ -14642,6 +14667,9 @@ store_parm_decls (int is_main_program UNUSED)
{
register tree fndecl = current_function_decl;
+ if (fndecl == error_mark_node)
+ return;
+
/* This is a chain of PARM_DECLs from old-style parm declarations. */
DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
@@ -14777,6 +14805,7 @@ start_function (tree name, tree type, int nested, int public)
ffecom_outer_function_decl_ = current_function_decl;
pushlevel (0);
+ current_binding_level->prep_state = 2;
if (TREE_CODE (current_function_decl) != ERROR_MARK)
{
@@ -14869,9 +14898,9 @@ global_bindings_p ()
return current_binding_level == global_binding_level;
}
-/* Insert BLOCK at the end of the list of subblocks of the
- current binding level. This is used when a BIND_EXPR is expanded,
- to handle the BLOCK node inside the BIND_EXPR. */
+/* Print an error message for invalid use of an incomplete type.
+ VALUE is the expression that was used (or 0 if that isn't known)
+ and TYPE is the type that was invalid. */
void
incomplete_type_error (value, type)
@@ -14930,6 +14959,30 @@ finish_parse ()
fclose (finput);
}
+/* Delete the node BLOCK from the current binding level.
+ This is used for the block inside a stmt expr ({...})
+ so that the block can be reinserted where appropriate. */
+
+static void
+delete_block (block)
+ tree block;
+{
+ tree t;
+ if (current_binding_level->blocks == block)
+ current_binding_level->blocks = TREE_CHAIN (block);
+ for (t = current_binding_level->blocks; t;)
+ {
+ if (TREE_CHAIN (t) == block)
+ TREE_CHAIN (t) = TREE_CHAIN (block);
+ else
+ t = TREE_CHAIN (t);
+ }
+ TREE_CHAIN (block) = NULL;
+ /* Clear TREE_USED which is always set by poplevel.
+ The flag is set again if insert_block is called. */
+ TREE_USED (block) = 0;
+}
+
void
insert_block (block)
tree block;
@@ -14979,6 +15032,8 @@ lang_init_options ()
flag_move_all_movables = 1;
flag_reduce_all_givs = 1;
flag_argument_noalias = 2;
+ flag_errno_math = 0;
+ flag_complex_divide_method = 1;
}
void
@@ -15082,17 +15137,17 @@ poplevel (keep, reverse, functionbody)
int functionbody;
{
register tree link;
- /* The chain of decls was accumulated in reverse order. Put it into forward
- order, just for cleanliness. */
+ /* The chain of decls was accumulated in reverse order.
+ Put it into forward order, just for cleanliness. */
tree decls;
tree subblocks = current_binding_level->blocks;
tree block = 0;
tree decl;
int block_previously_created;
- /* Get the decls in the order they were written. Usually
- current_binding_level->names is in reverse order. But parameter decls
- were previously put in forward order. */
+ /* Get the decls in the order they were written.
+ Usually current_binding_level->names is in reverse order.
+ But parameter decls were previously put in forward order. */
if (reverse)
current_binding_level->names
@@ -15100,21 +15155,25 @@ poplevel (keep, reverse, functionbody)
else
decls = current_binding_level->names;
- /* Output any nested inline functions within this block if they weren't
- already output. */
+ /* Output any nested inline functions within this block
+ if they weren't already output. */
for (decl = decls; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == FUNCTION_DECL
- && !TREE_ASM_WRITTEN (decl)
+ && ! TREE_ASM_WRITTEN (decl)
&& DECL_INITIAL (decl) != 0
&& TREE_ADDRESSABLE (decl))
{
- /* If this decl was copied from a file-scope decl on account of a
- block-scope extern decl, propagate TREE_ADDRESSABLE to the
- file-scope decl. */
- if (DECL_ABSTRACT_ORIGIN (decl) != 0)
+ /* If this decl was copied from a file-scope decl
+ on account of a block-scope extern decl,
+ propagate TREE_ADDRESSABLE to the file-scope decl.
+
+ DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
+ true, since then the decl goes through save_for_inline_copying. */
+ if (DECL_ABSTRACT_ORIGIN (decl) != 0
+ && DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else
+ else if (DECL_SAVED_INSNS (decl) != 0)
{
push_function_context ();
output_inline_function (decl);
@@ -15122,9 +15181,9 @@ poplevel (keep, reverse, functionbody)
}
}
- /* If there were any declarations or structure tags in that level, or if
- this level is a function body, create a BLOCK to record them for the
- life of this function. */
+ /* If there were any declarations or structure tags in that level,
+ or if this level is a function body,
+ create a BLOCK to record them for the life of this function. */
block = 0;
block_previously_created = (current_binding_level->this_block != 0);
@@ -15163,15 +15222,16 @@ poplevel (keep, reverse, functionbody)
}
}
- /* If the level being exited is the top level of a function, check over all
- the labels, and clear out the current (function local) meanings of their
- names. */
+ /* If the level being exited is the top level of a function,
+ check over all the labels, and clear out the current
+ (function local) meanings of their names. */
if (functionbody)
{
- /* If this is the top level block of a function, the vars are the
- function's parameters. Don't leave them in the BLOCK because they
- are found in the FUNCTION_DECL instead. */
+ /* If this is the top level block of a function,
+ the vars are the function's parameters.
+ Don't leave them in the BLOCK because they are
+ found in the FUNCTION_DECL instead. */
BLOCK_VARS (block) = 0;
}
@@ -15187,7 +15247,8 @@ poplevel (keep, reverse, functionbody)
}
/* Dispose of the block that we just made inside some higher level. */
- if (functionbody)
+ if (functionbody
+ && current_function_decl != error_mark_node)
DECL_INITIAL (current_function_decl) = block;
else if (block)
{
@@ -15195,28 +15256,15 @@ poplevel (keep, reverse, functionbody)
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
}
- /* If we did not make a block for the level just exited, any blocks made
- for inner levels (since they cannot be recorded as subblocks in that
- level) must be carried forward so they will later become subblocks of
- something else. */
+ /* If we did not make a block for the level just exited,
+ any blocks made for inner levels
+ (since they cannot be recorded as subblocks in that level)
+ must be carried forward so they will later become subblocks
+ of something else. */
else if (subblocks)
current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks);
- /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
- binding contour so that they point to the appropriate construct, i.e.
- either to the current FUNCTION_DECL node, or else to the BLOCK node we
- just constructed.
-
- Note that for tagged types whose scope is just the formal parameter list
- for some function type specification, we can't properly set their
- TYPE_CONTEXTs here, because we don't have a pointer to the appropriate
- FUNCTION_TYPE node readily available to us. For those cases, the
- TYPE_CONTEXTs of the relevant tagged type nodes get set in
- `grokdeclarator' as soon as we have created the FUNCTION_TYPE node which
- will represent the "scope" for these "parameter list local" tagged
- types. */
-
if (block)
TREE_USED (block) = 1;
return block;
@@ -15372,6 +15420,27 @@ pushdecl (x)
return x;
}
+/* Nonzero if the current level needs to have a BLOCK made. */
+
+static int
+kept_level_p ()
+{
+ tree decl;
+
+ for (decl = current_binding_level->names;
+ decl;
+ decl = TREE_CHAIN (decl))
+ {
+ if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
+ || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
+ /* Currently, there aren't supposed to be non-artificial names
+ at other than the top block for a function -- they're
+ believed to always be temps. But it's wise to check anyway. */
+ return 1;
+ }
+ return 0;
+}
+
/* Enter a new binding level.
If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
not for that of tags. */
@@ -15382,7 +15451,12 @@ pushlevel (tag_transparent)
{
register struct binding_level *newlevel = NULL_BINDING_LEVEL;
- assert (!tag_transparent);
+ assert (! tag_transparent);
+
+ if (current_binding_level == global_binding_level)
+ {
+ named_labels = 0;
+ }
/* Reuse or create a struct for this binding level. */
@@ -15396,8 +15470,8 @@ pushlevel (tag_transparent)
newlevel = make_binding_level ();
}
- /* Add this level to the front of the chain (stack) of levels that are
- active. */
+ /* Add this level to the front of the chain (stack) of levels that
+ are active. */
*newlevel = clear_binding_level;
newlevel->level_chain = current_binding_level;
@@ -15414,7 +15488,7 @@ set_block (block)
current_binding_level->this_block = block;
}
-/* ~~tree.h SHOULD declare this, because toplev.c references it. */
+/* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
/* Can't 'yydebug' a front end not generated by yacc/bison! */
@@ -15822,8 +15896,8 @@ unsigned_type (type)
/* Skip leading "./" from a directory name.
This may yield the empty string, which represents the current directory. */
-static char *
-skip_redundant_dir_prefix (char *dir)
+static const char *
+skip_redundant_dir_prefix (const char *dir)
{
while (dir[0] == '.' && dir[1] == '/')
for (dir += 2; *dir == '/'; dir++)
@@ -15921,10 +15995,9 @@ static void append_include_chain (struct file_name_list *first,
static FILE *open_include_file (char *filename,
struct file_name_list *searchptr);
static void print_containing_files (ffebadSeverity sev);
-static char *skip_redundant_dir_prefix (char *);
+static const char *skip_redundant_dir_prefix (const char *);
static char *read_filename_string (int ch, FILE *f);
-static struct file_name_map *read_name_map (char *dirname);
-static char *savestring (char *input);
+static struct file_name_map *read_name_map (const char *dirname);
/* Append a chain of `struct file_name_list's
to the end of the main include chain.
@@ -16046,8 +16119,8 @@ print_containing_files (ffebadSeverity sev)
FILE_BUF *ip = NULL;
int i;
int first = 1;
- char *str1;
- char *str2;
+ const char *str1;
+ const char *str2;
/* If stack of files hasn't changed since we last printed
this info, don't repeat it. */
@@ -16132,7 +16205,7 @@ read_filename_string (ch, f)
static struct file_name_map *
read_name_map (dirname)
- char *dirname;
+ const char *dirname;
{
/* This structure holds a linked list of file name maps, one per
directory. */
@@ -16158,7 +16231,7 @@ read_name_map (dirname)
map_list_ptr = ((struct file_name_map_list *)
xmalloc (sizeof (struct file_name_map_list)));
- map_list_ptr->map_list_name = savestring (dirname);
+ map_list_ptr->map_list_name = xstrdup (dirname);
map_list_ptr->map_list_map = NULL;
dirlen = strlen (dirname);
@@ -16219,16 +16292,6 @@ read_name_map (dirname)
return map_list_ptr->map_list_map;
}
-static char *
-savestring (input)
- char *input;
-{
- unsigned size = strlen (input);
- char *output = xmalloc (size + 1);
- strcpy (output, input);
- return output;
-}
-
static void
ffecom_file_ (char *name)
{
@@ -16508,3 +16571,877 @@ ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
return f;
}
#endif /* FFECOM_GCC_INCLUDE */
+
+/**INDENT* (Do not reformat this comment even with -fca option.)
+ Data-gathering files: Given the source file listed below, compiled with
+ f2c I obtained the output file listed after that, and from the output
+ file I derived the above code.
+
+-------- (begin input file to f2c)
+ implicit none
+ character*10 A1,A2
+ complex C1,C2
+ integer I1,I2
+ real R1,R2
+ double precision D1,D2
+C
+ call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
+c /
+ call fooI(I1/I2)
+ call fooR(R1/I1)
+ call fooD(D1/I1)
+ call fooC(C1/I1)
+ call fooR(R1/R2)
+ call fooD(R1/D1)
+ call fooD(D1/D2)
+ call fooD(D1/R1)
+ call fooC(C1/C2)
+ call fooC(C1/R1)
+ call fooZ(C1/D1)
+c **
+ call fooI(I1**I2)
+ call fooR(R1**I1)
+ call fooD(D1**I1)
+ call fooC(C1**I1)
+ call fooR(R1**R2)
+ call fooD(R1**D1)
+ call fooD(D1**D2)
+ call fooD(D1**R1)
+ call fooC(C1**C2)
+ call fooC(C1**R1)
+ call fooZ(C1**D1)
+c FFEINTRIN_impABS
+ call fooR(ABS(R1))
+c FFEINTRIN_impACOS
+ call fooR(ACOS(R1))
+c FFEINTRIN_impAIMAG
+ call fooR(AIMAG(C1))
+c FFEINTRIN_impAINT
+ call fooR(AINT(R1))
+c FFEINTRIN_impALOG
+ call fooR(ALOG(R1))
+c FFEINTRIN_impALOG10
+ call fooR(ALOG10(R1))
+c FFEINTRIN_impAMAX0
+ call fooR(AMAX0(I1,I2))
+c FFEINTRIN_impAMAX1
+ call fooR(AMAX1(R1,R2))
+c FFEINTRIN_impAMIN0
+ call fooR(AMIN0(I1,I2))
+c FFEINTRIN_impAMIN1
+ call fooR(AMIN1(R1,R2))
+c FFEINTRIN_impAMOD
+ call fooR(AMOD(R1,R2))
+c FFEINTRIN_impANINT
+ call fooR(ANINT(R1))
+c FFEINTRIN_impASIN
+ call fooR(ASIN(R1))
+c FFEINTRIN_impATAN
+ call fooR(ATAN(R1))
+c FFEINTRIN_impATAN2
+ call fooR(ATAN2(R1,R2))
+c FFEINTRIN_impCABS
+ call fooR(CABS(C1))
+c FFEINTRIN_impCCOS
+ call fooC(CCOS(C1))
+c FFEINTRIN_impCEXP
+ call fooC(CEXP(C1))
+c FFEINTRIN_impCHAR
+ call fooA(CHAR(I1))
+c FFEINTRIN_impCLOG
+ call fooC(CLOG(C1))
+c FFEINTRIN_impCONJG
+ call fooC(CONJG(C1))
+c FFEINTRIN_impCOS
+ call fooR(COS(R1))
+c FFEINTRIN_impCOSH
+ call fooR(COSH(R1))
+c FFEINTRIN_impCSIN
+ call fooC(CSIN(C1))
+c FFEINTRIN_impCSQRT
+ call fooC(CSQRT(C1))
+c FFEINTRIN_impDABS
+ call fooD(DABS(D1))
+c FFEINTRIN_impDACOS
+ call fooD(DACOS(D1))
+c FFEINTRIN_impDASIN
+ call fooD(DASIN(D1))
+c FFEINTRIN_impDATAN
+ call fooD(DATAN(D1))
+c FFEINTRIN_impDATAN2
+ call fooD(DATAN2(D1,D2))
+c FFEINTRIN_impDCOS
+ call fooD(DCOS(D1))
+c FFEINTRIN_impDCOSH
+ call fooD(DCOSH(D1))
+c FFEINTRIN_impDDIM
+ call fooD(DDIM(D1,D2))
+c FFEINTRIN_impDEXP
+ call fooD(DEXP(D1))
+c FFEINTRIN_impDIM
+ call fooR(DIM(R1,R2))
+c FFEINTRIN_impDINT
+ call fooD(DINT(D1))
+c FFEINTRIN_impDLOG
+ call fooD(DLOG(D1))
+c FFEINTRIN_impDLOG10
+ call fooD(DLOG10(D1))
+c FFEINTRIN_impDMAX1
+ call fooD(DMAX1(D1,D2))
+c FFEINTRIN_impDMIN1
+ call fooD(DMIN1(D1,D2))
+c FFEINTRIN_impDMOD
+ call fooD(DMOD(D1,D2))
+c FFEINTRIN_impDNINT
+ call fooD(DNINT(D1))
+c FFEINTRIN_impDPROD
+ call fooD(DPROD(R1,R2))
+c FFEINTRIN_impDSIGN
+ call fooD(DSIGN(D1,D2))
+c FFEINTRIN_impDSIN
+ call fooD(DSIN(D1))
+c FFEINTRIN_impDSINH
+ call fooD(DSINH(D1))
+c FFEINTRIN_impDSQRT
+ call fooD(DSQRT(D1))
+c FFEINTRIN_impDTAN
+ call fooD(DTAN(D1))
+c FFEINTRIN_impDTANH
+ call fooD(DTANH(D1))
+c FFEINTRIN_impEXP
+ call fooR(EXP(R1))
+c FFEINTRIN_impIABS
+ call fooI(IABS(I1))
+c FFEINTRIN_impICHAR
+ call fooI(ICHAR(A1))
+c FFEINTRIN_impIDIM
+ call fooI(IDIM(I1,I2))
+c FFEINTRIN_impIDNINT
+ call fooI(IDNINT(D1))
+c FFEINTRIN_impINDEX
+ call fooI(INDEX(A1,A2))
+c FFEINTRIN_impISIGN
+ call fooI(ISIGN(I1,I2))
+c FFEINTRIN_impLEN
+ call fooI(LEN(A1))
+c FFEINTRIN_impLGE
+ call fooL(LGE(A1,A2))
+c FFEINTRIN_impLGT
+ call fooL(LGT(A1,A2))
+c FFEINTRIN_impLLE
+ call fooL(LLE(A1,A2))
+c FFEINTRIN_impLLT
+ call fooL(LLT(A1,A2))
+c FFEINTRIN_impMAX0
+ call fooI(MAX0(I1,I2))
+c FFEINTRIN_impMAX1
+ call fooI(MAX1(R1,R2))
+c FFEINTRIN_impMIN0
+ call fooI(MIN0(I1,I2))
+c FFEINTRIN_impMIN1
+ call fooI(MIN1(R1,R2))
+c FFEINTRIN_impMOD
+ call fooI(MOD(I1,I2))
+c FFEINTRIN_impNINT
+ call fooI(NINT(R1))
+c FFEINTRIN_impSIGN
+ call fooR(SIGN(R1,R2))
+c FFEINTRIN_impSIN
+ call fooR(SIN(R1))
+c FFEINTRIN_impSINH
+ call fooR(SINH(R1))
+c FFEINTRIN_impSQRT
+ call fooR(SQRT(R1))
+c FFEINTRIN_impTAN
+ call fooR(TAN(R1))
+c FFEINTRIN_impTANH
+ call fooR(TANH(R1))
+c FFEINTRIN_imp_CMPLX_C
+ call fooC(cmplx(C1,C2))
+c FFEINTRIN_imp_CMPLX_D
+ call fooZ(cmplx(D1,D2))
+c FFEINTRIN_imp_CMPLX_I
+ call fooC(cmplx(I1,I2))
+c FFEINTRIN_imp_CMPLX_R
+ call fooC(cmplx(R1,R2))
+c FFEINTRIN_imp_DBLE_C
+ call fooD(dble(C1))
+c FFEINTRIN_imp_DBLE_D
+ call fooD(dble(D1))
+c FFEINTRIN_imp_DBLE_I
+ call fooD(dble(I1))
+c FFEINTRIN_imp_DBLE_R
+ call fooD(dble(R1))
+c FFEINTRIN_imp_INT_C
+ call fooI(int(C1))
+c FFEINTRIN_imp_INT_D
+ call fooI(int(D1))
+c FFEINTRIN_imp_INT_I
+ call fooI(int(I1))
+c FFEINTRIN_imp_INT_R
+ call fooI(int(R1))
+c FFEINTRIN_imp_REAL_C
+ call fooR(real(C1))
+c FFEINTRIN_imp_REAL_D
+ call fooR(real(D1))
+c FFEINTRIN_imp_REAL_I
+ call fooR(real(I1))
+c FFEINTRIN_imp_REAL_R
+ call fooR(real(R1))
+c
+c FFEINTRIN_imp_INT_D:
+c
+c FFEINTRIN_specIDINT
+ call fooI(IDINT(D1))
+c
+c FFEINTRIN_imp_INT_R:
+c
+c FFEINTRIN_specIFIX
+ call fooI(IFIX(R1))
+c FFEINTRIN_specINT
+ call fooI(INT(R1))
+c
+c FFEINTRIN_imp_REAL_D:
+c
+c FFEINTRIN_specSNGL
+ call fooR(SNGL(D1))
+c
+c FFEINTRIN_imp_REAL_I:
+c
+c FFEINTRIN_specFLOAT
+ call fooR(FLOAT(I1))
+c FFEINTRIN_specREAL
+ call fooR(REAL(I1))
+c
+ end
+-------- (end input file to f2c)
+
+-------- (begin output from providing above input file as input to:
+-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
+-------- -e "s:^#.*$::g"')
+
+// -- translated by f2c (version 19950223).
+ You must link the resulting object file with the libraries:
+ -lf2c -lm (in that order)
+//
+
+
+// f2c.h -- Standard Fortran to C header file //
+
+/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
+
+ - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
+
+
+
+
+// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
+// we assume short, float are OK //
+typedef long int // long int // integer;
+typedef char *address;
+typedef short int shortint;
+typedef float real;
+typedef double doublereal;
+typedef struct { real r, i; } complex;
+typedef struct { doublereal r, i; } doublecomplex;
+typedef long int // long int // logical;
+typedef short int shortlogical;
+typedef char logical1;
+typedef char integer1;
+// typedef long long longint; // // system-dependent //
+
+
+
+
+// Extern is for use with -E //
+
+
+
+
+// I/O stuff //
+
+
+
+
+
+
+
+
+typedef long int // int or long int // flag;
+typedef long int // int or long int // ftnlen;
+typedef long int // int or long int // ftnint;
+
+
+//external read, write//
+typedef struct
+{ flag cierr;
+ ftnint ciunit;
+ flag ciend;
+ char *cifmt;
+ ftnint cirec;
+} cilist;
+
+//internal read, write//
+typedef struct
+{ flag icierr;
+ char *iciunit;
+ flag iciend;
+ char *icifmt;
+ ftnint icirlen;
+ ftnint icirnum;
+} icilist;
+
+//open//
+typedef struct
+{ flag oerr;
+ ftnint ounit;
+ char *ofnm;
+ ftnlen ofnmlen;
+ char *osta;
+ char *oacc;
+ char *ofm;
+ ftnint orl;
+ char *oblnk;
+} olist;
+
+//close//
+typedef struct
+{ flag cerr;
+ ftnint cunit;
+ char *csta;
+} cllist;
+
+//rewind, backspace, endfile//
+typedef struct
+{ flag aerr;
+ ftnint aunit;
+} alist;
+
+// inquire //
+typedef struct
+{ flag inerr;
+ ftnint inunit;
+ char *infile;
+ ftnlen infilen;
+ ftnint *inex; //parameters in standard's order//
+ ftnint *inopen;
+ ftnint *innum;
+ ftnint *innamed;
+ char *inname;
+ ftnlen innamlen;
+ char *inacc;
+ ftnlen inacclen;
+ char *inseq;
+ ftnlen inseqlen;
+ char *indir;
+ ftnlen indirlen;
+ char *infmt;
+ ftnlen infmtlen;
+ char *inform;
+ ftnint informlen;
+ char *inunf;
+ ftnlen inunflen;
+ ftnint *inrecl;
+ ftnint *innrec;
+ char *inblank;
+ ftnlen inblanklen;
+} inlist;
+
+
+
+union Multitype { // for multiple entry points //
+ integer1 g;
+ shortint h;
+ integer i;
+ // longint j; //
+ real r;
+ doublereal d;
+ complex c;
+ doublecomplex z;
+ };
+
+typedef union Multitype Multitype;
+
+typedef long Long; // No longer used; formerly in Namelist //
+
+struct Vardesc { // for Namelist //
+ char *name;
+ char *addr;
+ ftnlen *dims;
+ int type;
+ };
+typedef struct Vardesc Vardesc;
+
+struct Namelist {
+ char *name;
+ Vardesc **vars;
+ int nvars;
+ };
+typedef struct Namelist Namelist;
+
+
+
+
+
+
+
+
+// procedure parameter types for -A and -C++ //
+
+
+
+
+typedef int // Unknown procedure type // (*U_fp)();
+typedef shortint (*J_fp)();
+typedef integer (*I_fp)();
+typedef real (*R_fp)();
+typedef doublereal (*D_fp)(), (*E_fp)();
+typedef // Complex // void (*C_fp)();
+typedef // Double Complex // void (*Z_fp)();
+typedef logical (*L_fp)();
+typedef shortlogical (*K_fp)();
+typedef // Character // void (*H_fp)();
+typedef // Subroutine // int (*S_fp)();
+
+// E_fp is for real functions when -R is not specified //
+typedef void C_f; // complex function //
+typedef void H_f; // character function //
+typedef void Z_f; // double complex function //
+typedef doublereal E_f; // real function with -R not specified //
+
+// undef any lower-case symbols that your C compiler predefines, e.g.: //
+
+
+// (No such symbols should be defined in a strict ANSI C compiler.
+ We can avoid trouble with f2c-translated code by using
+ gcc -ansi [-traditional].) //
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// Main program // MAIN__()
+{
+ // System generated locals //
+ integer i__1;
+ real r__1, r__2;
+ doublereal d__1, d__2;
+ complex q__1;
+ doublecomplex z__1, z__2, z__3;
+ logical L__1;
+ char ch__1[1];
+
+ // Builtin functions //
+ void c_div();
+ integer pow_ii();
+ double pow_ri(), pow_di();
+ void pow_ci();
+ double pow_dd();
+ void pow_zz();
+ double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
+ asin(), atan(), atan2(), c_abs();
+ void c_cos(), c_exp(), c_log(), r_cnjg();
+ double cos(), cosh();
+ void c_sin(), c_sqrt();
+ double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
+ d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
+ integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
+ logical l_ge(), l_gt(), l_le(), l_lt();
+ integer i_nint();
+ double r_sign();
+
+ // Local variables //
+ extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
+ fool_(), fooz_(), getem_();
+ static char a1[10], a2[10];
+ static complex c1, c2;
+ static doublereal d1, d2;
+ static integer i1, i2;
+ static real r1, r2;
+
+
+ getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
+// / //
+ i__1 = i1 / i2;
+ fooi_(&i__1);
+ r__1 = r1 / i1;
+ foor_(&r__1);
+ d__1 = d1 / i1;
+ food_(&d__1);
+ d__1 = (doublereal) i1;
+ q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
+ fooc_(&q__1);
+ r__1 = r1 / r2;
+ foor_(&r__1);
+ d__1 = r1 / d1;
+ food_(&d__1);
+ d__1 = d1 / d2;
+ food_(&d__1);
+ d__1 = d1 / r1;
+ food_(&d__1);
+ c_div(&q__1, &c1, &c2);
+ fooc_(&q__1);
+ q__1.r = c1.r / r1, q__1.i = c1.i / r1;
+ fooc_(&q__1);
+ z__1.r = c1.r / d1, z__1.i = c1.i / d1;
+ fooz_(&z__1);
+// ** //
+ i__1 = pow_ii(&i1, &i2);
+ fooi_(&i__1);
+ r__1 = pow_ri(&r1, &i1);
+ foor_(&r__1);
+ d__1 = pow_di(&d1, &i1);
+ food_(&d__1);
+ pow_ci(&q__1, &c1, &i1);
+ fooc_(&q__1);
+ d__1 = (doublereal) r1;
+ d__2 = (doublereal) r2;
+ r__1 = pow_dd(&d__1, &d__2);
+ foor_(&r__1);
+ d__2 = (doublereal) r1;
+ d__1 = pow_dd(&d__2, &d1);
+ food_(&d__1);
+ d__1 = pow_dd(&d1, &d2);
+ food_(&d__1);
+ d__2 = (doublereal) r1;
+ d__1 = pow_dd(&d1, &d__2);
+ food_(&d__1);
+ z__2.r = c1.r, z__2.i = c1.i;
+ z__3.r = c2.r, z__3.i = c2.i;
+ pow_zz(&z__1, &z__2, &z__3);
+ q__1.r = z__1.r, q__1.i = z__1.i;
+ fooc_(&q__1);
+ z__2.r = c1.r, z__2.i = c1.i;
+ z__3.r = r1, z__3.i = 0.;
+ pow_zz(&z__1, &z__2, &z__3);
+ q__1.r = z__1.r, q__1.i = z__1.i;
+ fooc_(&q__1);
+ z__2.r = c1.r, z__2.i = c1.i;
+ z__3.r = d1, z__3.i = 0.;
+ pow_zz(&z__1, &z__2, &z__3);
+ fooz_(&z__1);
+// FFEINTRIN_impABS //
+ r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
+ foor_(&r__1);
+// FFEINTRIN_impACOS //
+ r__1 = acos(r1);
+ foor_(&r__1);
+// FFEINTRIN_impAIMAG //
+ r__1 = r_imag(&c1);
+ foor_(&r__1);
+// FFEINTRIN_impAINT //
+ r__1 = r_int(&r1);
+ foor_(&r__1);
+// FFEINTRIN_impALOG //
+ r__1 = log(r1);
+ foor_(&r__1);
+// FFEINTRIN_impALOG10 //
+ r__1 = r_lg10(&r1);
+ foor_(&r__1);
+// FFEINTRIN_impAMAX0 //
+ r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
+ foor_(&r__1);
+// FFEINTRIN_impAMAX1 //
+ r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
+ foor_(&r__1);
+// FFEINTRIN_impAMIN0 //
+ r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
+ foor_(&r__1);
+// FFEINTRIN_impAMIN1 //
+ r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
+ foor_(&r__1);
+// FFEINTRIN_impAMOD //
+ r__1 = r_mod(&r1, &r2);
+ foor_(&r__1);
+// FFEINTRIN_impANINT //
+ r__1 = r_nint(&r1);
+ foor_(&r__1);
+// FFEINTRIN_impASIN //
+ r__1 = asin(r1);
+ foor_(&r__1);
+// FFEINTRIN_impATAN //
+ r__1 = atan(r1);
+ foor_(&r__1);
+// FFEINTRIN_impATAN2 //
+ r__1 = atan2(r1, r2);
+ foor_(&r__1);
+// FFEINTRIN_impCABS //
+ r__1 = c_abs(&c1);
+ foor_(&r__1);
+// FFEINTRIN_impCCOS //
+ c_cos(&q__1, &c1);
+ fooc_(&q__1);
+// FFEINTRIN_impCEXP //
+ c_exp(&q__1, &c1);
+ fooc_(&q__1);
+// FFEINTRIN_impCHAR //
+ *(unsigned char *)&ch__1[0] = i1;
+ fooa_(ch__1, 1L);
+// FFEINTRIN_impCLOG //
+ c_log(&q__1, &c1);
+ fooc_(&q__1);
+// FFEINTRIN_impCONJG //
+ r_cnjg(&q__1, &c1);
+ fooc_(&q__1);
+// FFEINTRIN_impCOS //
+ r__1 = cos(r1);
+ foor_(&r__1);
+// FFEINTRIN_impCOSH //
+ r__1 = cosh(r1);
+ foor_(&r__1);
+// FFEINTRIN_impCSIN //
+ c_sin(&q__1, &c1);
+ fooc_(&q__1);
+// FFEINTRIN_impCSQRT //
+ c_sqrt(&q__1, &c1);
+ fooc_(&q__1);
+// FFEINTRIN_impDABS //
+ d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
+ food_(&d__1);
+// FFEINTRIN_impDACOS //
+ d__1 = acos(d1);
+ food_(&d__1);
+// FFEINTRIN_impDASIN //
+ d__1 = asin(d1);
+ food_(&d__1);
+// FFEINTRIN_impDATAN //
+ d__1 = atan(d1);
+ food_(&d__1);
+// FFEINTRIN_impDATAN2 //
+ d__1 = atan2(d1, d2);
+ food_(&d__1);
+// FFEINTRIN_impDCOS //
+ d__1 = cos(d1);
+ food_(&d__1);
+// FFEINTRIN_impDCOSH //
+ d__1 = cosh(d1);
+ food_(&d__1);
+// FFEINTRIN_impDDIM //
+ d__1 = d_dim(&d1, &d2);
+ food_(&d__1);
+// FFEINTRIN_impDEXP //
+ d__1 = exp(d1);
+ food_(&d__1);
+// FFEINTRIN_impDIM //
+ r__1 = r_dim(&r1, &r2);
+ foor_(&r__1);
+// FFEINTRIN_impDINT //
+ d__1 = d_int(&d1);
+ food_(&d__1);
+// FFEINTRIN_impDLOG //
+ d__1 = log(d1);
+ food_(&d__1);
+// FFEINTRIN_impDLOG10 //
+ d__1 = d_lg10(&d1);
+ food_(&d__1);
+// FFEINTRIN_impDMAX1 //
+ d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
+ food_(&d__1);
+// FFEINTRIN_impDMIN1 //
+ d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
+ food_(&d__1);
+// FFEINTRIN_impDMOD //
+ d__1 = d_mod(&d1, &d2);
+ food_(&d__1);
+// FFEINTRIN_impDNINT //
+ d__1 = d_nint(&d1);
+ food_(&d__1);
+// FFEINTRIN_impDPROD //
+ d__1 = (doublereal) r1 * r2;
+ food_(&d__1);
+// FFEINTRIN_impDSIGN //
+ d__1 = d_sign(&d1, &d2);
+ food_(&d__1);
+// FFEINTRIN_impDSIN //
+ d__1 = sin(d1);
+ food_(&d__1);
+// FFEINTRIN_impDSINH //
+ d__1 = sinh(d1);
+ food_(&d__1);
+// FFEINTRIN_impDSQRT //
+ d__1 = sqrt(d1);
+ food_(&d__1);
+// FFEINTRIN_impDTAN //
+ d__1 = tan(d1);
+ food_(&d__1);
+// FFEINTRIN_impDTANH //
+ d__1 = tanh(d1);
+ food_(&d__1);
+// FFEINTRIN_impEXP //
+ r__1 = exp(r1);
+ foor_(&r__1);
+// FFEINTRIN_impIABS //
+ i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
+ fooi_(&i__1);
+// FFEINTRIN_impICHAR //
+ i__1 = *(unsigned char *)a1;
+ fooi_(&i__1);
+// FFEINTRIN_impIDIM //
+ i__1 = i_dim(&i1, &i2);
+ fooi_(&i__1);
+// FFEINTRIN_impIDNINT //
+ i__1 = i_dnnt(&d1);
+ fooi_(&i__1);
+// FFEINTRIN_impINDEX //
+ i__1 = i_indx(a1, a2, 10L, 10L);
+ fooi_(&i__1);
+// FFEINTRIN_impISIGN //
+ i__1 = i_sign(&i1, &i2);
+ fooi_(&i__1);
+// FFEINTRIN_impLEN //
+ i__1 = i_len(a1, 10L);
+ fooi_(&i__1);
+// FFEINTRIN_impLGE //
+ L__1 = l_ge(a1, a2, 10L, 10L);
+ fool_(&L__1);
+// FFEINTRIN_impLGT //
+ L__1 = l_gt(a1, a2, 10L, 10L);
+ fool_(&L__1);
+// FFEINTRIN_impLLE //
+ L__1 = l_le(a1, a2, 10L, 10L);
+ fool_(&L__1);
+// FFEINTRIN_impLLT //
+ L__1 = l_lt(a1, a2, 10L, 10L);
+ fool_(&L__1);
+// FFEINTRIN_impMAX0 //
+ i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
+ fooi_(&i__1);
+// FFEINTRIN_impMAX1 //
+ i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
+ fooi_(&i__1);
+// FFEINTRIN_impMIN0 //
+ i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
+ fooi_(&i__1);
+// FFEINTRIN_impMIN1 //
+ i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
+ fooi_(&i__1);
+// FFEINTRIN_impMOD //
+ i__1 = i1 % i2;
+ fooi_(&i__1);
+// FFEINTRIN_impNINT //
+ i__1 = i_nint(&r1);
+ fooi_(&i__1);
+// FFEINTRIN_impSIGN //
+ r__1 = r_sign(&r1, &r2);
+ foor_(&r__1);
+// FFEINTRIN_impSIN //
+ r__1 = sin(r1);
+ foor_(&r__1);
+// FFEINTRIN_impSINH //
+ r__1 = sinh(r1);
+ foor_(&r__1);
+// FFEINTRIN_impSQRT //
+ r__1 = sqrt(r1);
+ foor_(&r__1);
+// FFEINTRIN_impTAN //
+ r__1 = tan(r1);
+ foor_(&r__1);
+// FFEINTRIN_impTANH //
+ r__1 = tanh(r1);
+ foor_(&r__1);
+// FFEINTRIN_imp_CMPLX_C //
+ r__1 = c1.r;
+ r__2 = c2.r;
+ q__1.r = r__1, q__1.i = r__2;
+ fooc_(&q__1);
+// FFEINTRIN_imp_CMPLX_D //
+ z__1.r = d1, z__1.i = d2;
+ fooz_(&z__1);
+// FFEINTRIN_imp_CMPLX_I //
+ r__1 = (real) i1;
+ r__2 = (real) i2;
+ q__1.r = r__1, q__1.i = r__2;
+ fooc_(&q__1);
+// FFEINTRIN_imp_CMPLX_R //
+ q__1.r = r1, q__1.i = r2;
+ fooc_(&q__1);
+// FFEINTRIN_imp_DBLE_C //
+ d__1 = (doublereal) c1.r;
+ food_(&d__1);
+// FFEINTRIN_imp_DBLE_D //
+ d__1 = d1;
+ food_(&d__1);
+// FFEINTRIN_imp_DBLE_I //
+ d__1 = (doublereal) i1;
+ food_(&d__1);
+// FFEINTRIN_imp_DBLE_R //
+ d__1 = (doublereal) r1;
+ food_(&d__1);
+// FFEINTRIN_imp_INT_C //
+ i__1 = (integer) c1.r;
+ fooi_(&i__1);
+// FFEINTRIN_imp_INT_D //
+ i__1 = (integer) d1;
+ fooi_(&i__1);
+// FFEINTRIN_imp_INT_I //
+ i__1 = i1;
+ fooi_(&i__1);
+// FFEINTRIN_imp_INT_R //
+ i__1 = (integer) r1;
+ fooi_(&i__1);
+// FFEINTRIN_imp_REAL_C //
+ r__1 = c1.r;
+ foor_(&r__1);
+// FFEINTRIN_imp_REAL_D //
+ r__1 = (real) d1;
+ foor_(&r__1);
+// FFEINTRIN_imp_REAL_I //
+ r__1 = (real) i1;
+ foor_(&r__1);
+// FFEINTRIN_imp_REAL_R //
+ r__1 = r1;
+ foor_(&r__1);
+
+// FFEINTRIN_imp_INT_D: //
+
+// FFEINTRIN_specIDINT //
+ i__1 = (integer) d1;
+ fooi_(&i__1);
+
+// FFEINTRIN_imp_INT_R: //
+
+// FFEINTRIN_specIFIX //
+ i__1 = (integer) r1;
+ fooi_(&i__1);
+// FFEINTRIN_specINT //
+ i__1 = (integer) r1;
+ fooi_(&i__1);
+
+// FFEINTRIN_imp_REAL_D: //
+
+// FFEINTRIN_specSNGL //
+ r__1 = (real) d1;
+ foor_(&r__1);
+
+// FFEINTRIN_imp_REAL_I: //
+
+// FFEINTRIN_specFLOAT //
+ r__1 = (real) i1;
+ foor_(&r__1);
+// FFEINTRIN_specREAL //
+ r__1 = (real) i1;
+ foor_(&r__1);
+
+} // MAIN__ //
+
+-------- (end output file from f2c)
+
+*/
diff --git a/contrib/gcc/f/com.h b/contrib/gcc/f/com.h
index db8f469..baa2953 100644
--- a/contrib/gcc/f/com.h
+++ b/contrib/gcc/f/com.h
@@ -1,6 +1,6 @@
/* com.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -56,6 +56,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#if FFECOM_targetCURRENT == FFECOM_targetGCC
#define FFECOM_constantNULL NULL_TREE
+#define FFECOM_nonterNULL NULL_TREE
#define FFECOM_globalNULL NULL_TREE
#define FFECOM_labelNULL NULL_TREE
#define FFECOM_storageNULL NULL_TREE
@@ -202,6 +203,8 @@ typedef enum
typedef tree ffecomConstant;
#define FFECOM_constantHOOK
+typedef tree ffecomNonter;
+#define FFECOM_nonterHOOK
typedef tree ffecomLabel;
#define FFECOM_globalHOOK
typedef tree ffecomGlobal;
@@ -279,15 +282,20 @@ tree ffecom_3 (enum tree_code code, tree type, tree node1, tree node2,
tree ffecom_3s (enum tree_code code, tree type, tree node1, tree node2,
tree node3);
tree ffecom_arg_expr (ffebld expr, tree *length);
+tree ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length);
tree ffecom_arg_ptr_to_expr (ffebld expr, tree *length);
-tree ffecom_call_gfrt (ffecomGfrt ix, tree args);
+tree ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook);
tree ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
ffeinfoKindtype kt, tree tree_type);
-tree ffecom_decl_field (tree context, tree prevfield, char *name,
+tree ffecom_const_expr (ffebld expr);
+tree ffecom_decl_field (tree context, tree prevfield, const char *name,
tree type);
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
void ffecom_close_include (FILE *f);
int ffecom_decode_include_option (char *spec);
+#if FFECOM_targetCURRENT == FFECOM_targetGCC
+tree ffecom_end_compstmt (void);
+#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
void ffecom_end_transition (void);
void ffecom_exec_transition (void);
void ffecom_expand_let_stmt (ffebld dest, ffebld source);
@@ -295,11 +303,12 @@ void ffecom_expand_let_stmt (ffebld dest, ffebld source);
tree ffecom_expr (ffebld expr);
tree ffecom_expr_assign (ffebld expr);
tree ffecom_expr_assign_w (ffebld expr);
-tree ffecom_expr_rw (ffebld expr);
+tree ffecom_expr_rw (tree type, ffebld expr);
+tree ffecom_expr_w (tree type, ffebld expr);
void ffecom_finish_compile (void);
void ffecom_finish_decl (tree decl, tree init, bool is_top_level);
void ffecom_finish_progunit (void);
-tree ffecom_get_invented_identifier (char *pattern, char *text,
+tree ffecom_get_invented_identifier (const char *pattern, const char *text,
int number);
ffeinfoKindtype ffecom_gfrt_basictype (ffecomGfrt ix);
ffeinfoKindtype ffecom_gfrt_kindtype (ffecomGfrt ix);
@@ -308,6 +317,8 @@ void ffecom_init_2 (void);
tree ffecom_list_expr (ffebld list);
tree ffecom_list_ptr_to_expr (ffebld list);
tree ffecom_lookup_label (ffelab label);
+tree ffecom_make_tempvar (const char *commentary, tree type,
+ ffetargetCharacterSize size, int elements);
tree ffecom_modify (tree newtype, tree lhs, tree rhs);
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
void ffecom_file (char *name);
@@ -316,14 +327,18 @@ void ffecom_notify_init_symbol (ffesymbol s);
void ffecom_notify_primary_entry (ffesymbol fn);
FILE *ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c);
#if FFECOM_targetCURRENT == FFECOM_targetGCC
-void ffecom_pop_calltemps (void);
-void ffecom_pop_tempvar (tree var);
+void ffecom_prepare_arg_ptr_to_expr (ffebld expr);
+bool ffecom_prepare_end (void);
+void ffecom_prepare_expr_ (ffebld expr, ffebld dest);
+void ffecom_prepare_expr_rw (tree type, ffebld expr);
+void ffecom_prepare_expr_w (tree type, ffebld expr);
+void ffecom_prepare_ptr_to_expr (ffebld expr);
+void ffecom_prepare_return_expr (ffebld expr);
+tree ffecom_ptr_to_const_expr (ffebld expr);
tree ffecom_ptr_to_expr (ffebld expr);
-void ffecom_push_calltemps (void);
-tree ffecom_push_tempvar (tree type, ffetargetCharacterSize size,
- int elements, bool auto_pop);
tree ffecom_return_expr (ffebld expr);
tree ffecom_save_tree (tree t);
+void ffecom_start_compstmt (void);
tree ffecom_start_decl (tree decl, bool is_init);
void ffecom_sym_commit (ffesymbol s);
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
@@ -335,6 +350,7 @@ void ffecom_sym_retract (ffesymbol s);
tree ffecom_temp_label (void);
tree ffecom_truth_value (tree expr);
tree ffecom_truth_value_invert (tree expr);
+tree ffecom_type_expr (ffebld expr);
tree ffecom_which_entrypoint_decl (void);
/* These need to be in the front end with exactly these interfaces,
@@ -360,6 +376,7 @@ int mark_addressable (tree expr);
#define ffecom_f2c_typecode(bt,kt) ffecom_f2c_typecode_[(bt)][(kt)]
#define ffecom_label_kind() ffecom_label_kind_
#define ffecom_pointer_kind() ffecom_pointer_kind_
+#define ffecom_prepare_expr(e) ffecom_prepare_expr_ ((e), NULL)
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
#define ffecom_init_1()
diff --git a/contrib/gcc/f/config.j b/contrib/gcc/f/config.j
index 3fd1c11..fda03eb 100644
--- a/contrib/gcc/f/config.j
+++ b/contrib/gcc/f/config.j
@@ -1,6 +1,6 @@
/* config.j -- Wrapper for GCC's config.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/convert.j b/contrib/gcc/f/convert.j
index 85e3af8..76b8e02 100644
--- a/contrib/gcc/f/convert.j
+++ b/contrib/gcc/f/convert.j
@@ -1,6 +1,6 @@
/* convert.j -- Wrapper for GCC's convert.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/data.c b/contrib/gcc/f/data.c
index a8acd5c..51eb2b7 100644
--- a/contrib/gcc/f/data.c
+++ b/contrib/gcc/f/data.c
@@ -1,6 +1,6 @@
/* data.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -668,7 +668,7 @@ tail_recurse: /* :::::::::::::::::::: */
expression doesn't already exist in the cache) and then puts the result
in the cache. */
-ffebld
+static ffebld
ffedata_convert_ (ffebld source, ffelexToken source_token,
ffelexToken dest_token, ffeinfoBasictype bt,
ffeinfoKindtype kt, ffeinfoRank rk,
@@ -1119,7 +1119,7 @@ ffedata_eval_substr_end_ (ffebld expr, ffetargetCharacterSize min,
If st has any initialization info, transfer that info into mst and
clear st's info. */
-void
+static void
ffedata_gather_ (ffestorag mst, ffestorag st)
{
ffesymbol s;
diff --git a/contrib/gcc/f/data.h b/contrib/gcc/f/data.h
index 26c4f54..666612e 100644
--- a/contrib/gcc/f/data.h
+++ b/contrib/gcc/f/data.h
@@ -1,6 +1,6 @@
/* data.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/equiv.c b/contrib/gcc/f/equiv.c
index a9de49d..4d89622 100644
--- a/contrib/gcc/f/equiv.c
+++ b/contrib/gcc/f/equiv.c
@@ -1,6 +1,6 @@
/* equiv.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/equiv.h b/contrib/gcc/f/equiv.h
index daf0cee..0a0ce92 100644
--- a/contrib/gcc/f/equiv.h
+++ b/contrib/gcc/f/equiv.h
@@ -1,6 +1,6 @@
/* equiv.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/expr.c b/contrib/gcc/f/expr.c
index 7e7bf867..67b3765 100644
--- a/contrib/gcc/f/expr.c
+++ b/contrib/gcc/f/expr.c
@@ -1,6 +1,6 @@
/* expr.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -268,7 +268,7 @@ static void ffeexpr_update_impdo_sym_ (ffebld expr, ffesymbol dovar);
static ffeexprContext ffeexpr_context_outer_ (ffeexprStack_ s);
static ffeexprExpr_ ffeexpr_expr_new_ (void);
static void ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t);
-static bool ffeexpr_isdigits_ (char *p);
+static bool ffeexpr_isdigits_ (const char *p);
static ffelexHandler ffeexpr_token_first_lhs_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_lhs_1_ (ffelexToken t);
static ffelexHandler ffeexpr_token_first_rhs_ (ffelexToken t);
@@ -633,6 +633,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer1_val
(ffebld_cu_val_integer1 (u)), expr);
@@ -822,6 +826,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer2_val
(ffebld_cu_val_integer2 (u)), expr);
@@ -1011,6 +1019,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer3_val
(ffebld_cu_val_integer3 (u)), expr);
@@ -1200,6 +1212,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_integer4_val
(ffebld_cu_val_integer4 (u)), expr);
@@ -1317,6 +1333,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical1_val
(ffebld_cu_val_logical1 (u)), expr);
@@ -1424,6 +1444,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical2_val
(ffebld_cu_val_logical2 (u)), expr);
@@ -1531,6 +1555,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical3_val
(ffebld_cu_val_logical3 (u)), expr);
@@ -1638,6 +1666,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_logical4_val
(ffebld_cu_val_logical4 (u)), expr);
@@ -1796,6 +1828,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real1_val
(ffebld_cu_val_real1 (u)), expr);
@@ -1944,6 +1980,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real2_val
(ffebld_cu_val_real2 (u)), expr);
@@ -2092,6 +2132,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real3_val
(ffebld_cu_val_real3 (u)), expr);
@@ -2240,6 +2284,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_real4_val
(ffebld_cu_val_real4 (u)), expr);
@@ -2398,6 +2446,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex1_val
(ffebld_cu_val_complex1 (u)), expr);
@@ -2546,6 +2598,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex2_val
(ffebld_cu_val_complex2 (u)), expr);
@@ -2694,6 +2750,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex3_val
(ffebld_cu_val_complex3 (u)), expr);
@@ -2842,6 +2902,10 @@ ffeexpr_collapse_convert (ffebld expr, ffelexToken t)
break;
}
+ /* If conversion operation is not implemented, return original expr. */
+ if (error == FFEBAD_NOCANDO)
+ return expr;
+
expr = ffebld_new_conter_with_orig
(ffebld_constant_new_complex4_val
(ffebld_cu_val_complex4 (u)), expr);
@@ -8520,7 +8584,7 @@ ffeexpr_context_outer_ (ffeexprStack_ s)
static ffeexprPercent_
ffeexpr_percent_ (ffelexToken t)
{
- char *p;
+ const char *p;
switch (ffelex_token_length (t))
{
@@ -9473,7 +9537,7 @@ ffeexpr_fulfill_call_ (ffebld *expr, ffelexToken t)
/* Check whether rest of string is all decimal digits. */
static bool
-ffeexpr_isdigits_ (char *p)
+ffeexpr_isdigits_ (const char *p)
{
for (; *p != '\0'; ++p)
if (! ISDIGIT (*p))
@@ -10314,7 +10378,7 @@ ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
if ((lkd != FFEINFO_kindANY)
&& ffebad_start (FFEBAD_CONCAT_ARG_KIND))
{
- char *what;
+ const char *what;
if (lrk != 0)
what = "an array";
@@ -10330,7 +10394,7 @@ ffeexpr_reduced_concatenate_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
{
if (ffebad_start (FFEBAD_CONCAT_ARG_KIND))
{
- char *what;
+ const char *what;
if (rrk != 0)
what = "an array";
@@ -11602,7 +11666,7 @@ static ffelexHandler
ffeexpr_nil_real_ (ffelexToken t)
{
char d;
- char *p;
+ const char *p;
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
@@ -11640,7 +11704,7 @@ static ffelexHandler
ffeexpr_nil_number_ (ffelexToken t)
{
char d;
- char *p;
+ const char *p;
if (ffeexpr_hollerith_count_ > 0)
ffelex_set_expecting_hollerith (0, '\0',
@@ -11715,7 +11779,7 @@ ffeexpr_nil_number_period_ (ffelexToken t)
{
ffelexHandler nexthandler;
char d;
- char *p;
+ const char *p;
switch (ffelex_token_type (t))
{
@@ -11772,7 +11836,7 @@ static ffelexHandler
ffeexpr_nil_number_real_ (ffelexToken t)
{
char d;
- char *p;
+ const char *p;
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
@@ -12203,7 +12267,6 @@ again: /* :::::::::::::::::::: */
case FFEEXPR_contextINDEX_:
case FFEEXPR_contextSFUNCDEFINDEX_:
- case FFEEXPR_contextRETURN:
if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
break;
switch ((expr == NULL) ? FFEINFO_basictypeNONE
@@ -12226,7 +12289,6 @@ again: /* :::::::::::::::::::: */
break;
}
/* Fall through. */
- case FFEINFO_basictypeINTEGER:
case FFEINFO_basictypeHOLLERITH:
case FFEINFO_basictypeTYPELESS:
error = FALSE;
@@ -12235,6 +12297,11 @@ again: /* :::::::::::::::::::: */
FFEEXPR_contextLET);
break;
+ case FFEINFO_basictypeINTEGER:
+ /* Specifically, allow INTEGER(KIND=2), aka INTEGER*8, through
+ unmolested. Leave it to downstream to handle kinds. */
+ break;
+
default:
error = TRUE;
break;
@@ -12242,6 +12309,44 @@ again: /* :::::::::::::::::::: */
break; /* expr==NULL ok for substring; element case
caught by callback. */
+ case FFEEXPR_contextRETURN:
+ if ((error = (expr != NULL) && (ffeinfo_rank (info) != 0)))
+ break;
+ switch ((expr == NULL) ? FFEINFO_basictypeNONE
+ : ffeinfo_basictype (info))
+ {
+ case FFEINFO_basictypeNONE:
+ error = FALSE;
+ break;
+
+ case FFEINFO_basictypeLOGICAL:
+ expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeLOGICAL,
+ FFEINFO_kindtypeLOGICALDEFAULT, 0, FFETARGET_charactersizeNONE,
+ FFEEXPR_contextLET);
+ /* Fall through. */
+ case FFEINFO_basictypeREAL:
+ case FFEINFO_basictypeCOMPLEX:
+ if (ffe_is_pedantic ())
+ {
+ error = TRUE;
+ break;
+ }
+ /* Fall through. */
+ case FFEINFO_basictypeINTEGER:
+ case FFEINFO_basictypeHOLLERITH:
+ case FFEINFO_basictypeTYPELESS:
+ error = FALSE;
+ expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
+ FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
+ FFEEXPR_contextLET);
+ break;
+
+ default:
+ error = TRUE;
+ break;
+ }
+ break;
+
case FFEEXPR_contextDO:
if ((error = (expr == NULL) || (ffeinfo_rank (info) != 0)))
break;
@@ -12616,11 +12721,12 @@ again: /* :::::::::::::::::::: */
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
- error = error && !ffe_is_ugly_logint ();
- if (!ffeexpr_stack_->is_rhs)
- break; /* Don't convert lhs variable. */
+ if (! ffe_is_ugly_logint ())
+ error = TRUE;
+ if (! ffeexpr_stack_->is_rhs)
+ break;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
- ffeinfo_kindtype (ffebld_info (expr)), 0,
+ ffeinfo_kindtype (info), 0,
FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
break;
@@ -12664,18 +12770,21 @@ again: /* :::::::::::::::::::: */
switch (ffeinfo_basictype (info))
{
case FFEINFO_basictypeLOGICAL:
- error = error
- && (ffeinfo_kindtype (info) != FFEINFO_kindtypeLOGICALDEFAULT);
- if (!ffeexpr_stack_->is_rhs)
- break; /* Don't convert lhs variable. */
+ if (! ffeexpr_stack_->is_rhs)
+ break;
expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
- FFEINFO_kindtypeINTEGERDEFAULT, 0, FFETARGET_charactersizeNONE,
+ ffeinfo_kindtype (info), 0,
+ FFETARGET_charactersizeNONE,
FFEEXPR_contextLET);
- break;
-
+ /* Fall through. */
case FFEINFO_basictypeINTEGER:
- error = error &&
- (ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
+ if (ffeexpr_stack_->is_rhs
+ && (ffeinfo_kindtype (ffebld_info (expr))
+ != FFEINFO_kindtypeINTEGERDEFAULT))
+ expr = ffeexpr_convert (expr, ft, ft, FFEINFO_basictypeINTEGER,
+ FFEINFO_kindtypeINTEGERDEFAULT, 0,
+ FFETARGET_charactersizeNONE,
+ FFEEXPR_contextLET);
break;
case FFEINFO_basictypeHOLLERITH:
@@ -12853,7 +12962,11 @@ again: /* :::::::::::::::::::: */
: ffeinfo_basictype (info))
{
case FFEINFO_basictypeINTEGER:
- error = FALSE;
+ /* Maybe this should be supported someday, but, right now,
+ g77 can't generate a call to libf2c to write to an
+ integer other than the default size. */
+ error = ((! ffeexpr_stack_->is_rhs)
+ && ffeinfo_kindtype (info) != FFEINFO_kindtypeINTEGERDEFAULT);
break;
default:
@@ -13584,7 +13697,7 @@ static ffelexHandler
ffeexpr_token_real_ (ffelexToken t)
{
char d;
- char *p;
+ const char *p;
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
@@ -13741,7 +13854,7 @@ ffeexpr_token_number_ (ffelexToken t)
ffeexprExpr_ e;
ffeinfo ni;
char d;
- char *p;
+ const char *p;
if (ffeexpr_hollerith_count_ > 0)
ffelex_set_expecting_hollerith (0, '\0',
@@ -13897,7 +14010,7 @@ ffeexpr_token_number_period_ (ffelexToken t)
{
ffeexprExpr_ e;
ffelexHandler nexthandler;
- char *p;
+ const char *p;
char d;
switch (ffelex_token_type (t))
@@ -14015,7 +14128,7 @@ static ffelexHandler
ffeexpr_token_number_real_ (ffelexToken t)
{
char d;
- char *p;
+ const char *p;
if (((ffelex_token_type (t) != FFELEX_typeNAME)
&& (ffelex_token_type (t) != FFELEX_typeNAMES))
@@ -18530,7 +18643,8 @@ ffeexpr_token_elements_ (ffelexToken ft, ffebld expr, ffelexToken t)
ffeexpr_stack_->immediate = FALSE;
break;
}
- if (ffebld_op (expr) == FFEBLD_opCONTER)
+ if (ffebld_op (expr) == FFEBLD_opCONTER
+ && ffebld_kindtype (expr) == FFEINFO_kindtypeINTEGERDEFAULT)
{
val = ffebld_constant_integerdefault (ffebld_conter (expr));
@@ -18841,26 +18955,33 @@ ffeexpr_token_substring_1_ (ffelexToken ft, ffebld last, ffelexToken t)
ffetargetIntegerDefault last_val;
ffetargetCharacterSize size;
ffetargetCharacterSize strop_size_max;
+ bool first_known;
string = ffeexpr_stack_->exprstack;
strop = string->u.operand;
info = ffebld_info (strop);
- if ((first == NULL) || (ffebld_op (first) == FFEBLD_opCONTER))
+ if (first == NULL
+ || (ffebld_op (first) == FFEBLD_opCONTER
+ && ffebld_kindtype (first) == FFEINFO_kindtypeINTEGERDEFAULT))
{ /* The starting point is known. */
first_val = (first == NULL) ? 1
: ffebld_constant_integerdefault (ffebld_conter (first));
+ first_known = TRUE;
}
else
{ /* Assume start of the entity. */
first_val = 1;
+ first_known = FALSE;
}
- if ((last != NULL) && (ffebld_op (last) == FFEBLD_opCONTER))
+ if (last != NULL
+ && (ffebld_op (last) == FFEBLD_opCONTER
+ && ffebld_kindtype (last) == FFEINFO_kindtypeINTEGERDEFAULT))
{ /* The ending point is known. */
last_val = ffebld_constant_integerdefault (ffebld_conter (last));
- if ((first == NULL) || (ffebld_op (first) == FFEBLD_opCONTER))
+ if (first_known)
{ /* The beginning point is a constant. */
if (first_val <= last_val)
size = last_val - first_val + 1;
diff --git a/contrib/gcc/f/expr.h b/contrib/gcc/f/expr.h
index 04143e6..3f781f9 100644
--- a/contrib/gcc/f/expr.h
+++ b/contrib/gcc/f/expr.h
@@ -1,6 +1,6 @@
/* expr.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/ffe.texi b/contrib/gcc/f/ffe.texi
new file mode 100644
index 0000000..e303332
--- /dev/null
+++ b/contrib/gcc/f/ffe.texi
@@ -0,0 +1,2024 @@
+@c Copyright (C) 1999 Free Software Foundation, Inc.
+@c This is part of the G77 manual.
+@c For copying conditions, see the file g77.texi.
+
+@node Front End
+@chapter Front End
+@cindex GNU Fortran Front End (FFE)
+@cindex FFE
+@cindex @code{g77}, front end
+@cindex front end, @code{g77}
+
+This chapter describes some aspects of the design and implementation
+of the @code{g77} front end.
+Much of the information below applies not to current
+releases of @code{g77},
+but to the 0.6 rewrite being designed and implemented
+as of late May, 1999.
+
+To find about things that are ``To Be Determined'' or ``To Be Done'',
+search for the string TBD.
+If you want to help by working on one or more of these items,
+email me at @email{@value{email-burley}}.
+If you're planning to do more than just research issues and offer comments,
+see @uref{http://www.gnu.org/software/contribute.html} for steps you might
+need to take first.
+
+@menu
+* Overview of Sources::
+* Overview of Translation Process::
+* Philosophy of Code Generation::
+* Two-pass Design::
+* Challenges Posed::
+* Transforming Statements::
+* Transforming Expressions::
+* Internal Naming Conventions::
+@end menu
+
+@node Overview of Sources
+@section Overview of Sources
+
+The current directory layout includes the following:
+
+@table @file
+@item @value{srcdir}/gcc/
+Non-g77 files in gcc
+
+@item @value{srcdir}/gcc/f/
+GNU Fortran front end sources
+
+@item @value{srcdir}/libf2c/
+@code{libg2c} configuration and @code{g2c.h} file generation
+
+@item @value{srcdir}/libf2c/libF77/
+General support and math portion of @code{libg2c}
+
+@item @value{srcdir}/libf2c/libI77/
+I/O portion of @code{libg2c}
+
+@item @value{srcdir}/libf2c/libU77/
+Additional interfaces to Unix @code{libc} for @code{libg2c}
+@end table
+
+Components of note in @code{g77} are described below.
+
+@file{f/} as a whole contains the source for @code{g77},
+while @file{libf2c/} contains a portion of the separate program
+@code{f2c}.
+Note that the @code{libf2c} code is not part of the program @code{g77},
+just distributed with it.
+
+@file{f/} contains text files that document the Fortran compiler, source
+files for the GNU Fortran Front End (FFE), and some other stuff.
+The @code{g77} compiler code is placed in @file{f/} because it,
+along with its contents,
+is designed to be a subdirectory of a @code{gcc} source directory,
+@file{gcc/},
+which is structured so that language-specific front ends can be ``dropped
+in'' as subdirectories.
+The C++ front end (@code{g++}), is an example of this---it resides in
+the @file{cp/} subdirectory.
+Note that the C front end (also referred to as @code{gcc})
+is an exception to this, as its source files reside
+in the @file{gcc/} directory itself.
+
+@file{libf2c/} contains the run-time libraries for the @code{f2c} program,
+also used by @code{g77}.
+These libraries normally referred to collectively as @code{libf2c}.
+When built as part of @code{g77},
+@code{libf2c} is installed under the name @code{libg2c} to avoid
+conflict with any existing version of @code{libf2c},
+and thus is often referred to as @code{libg2c} when the
+@code{g77} version is specifically being referred to.
+
+The @code{netlib} version of @code{libf2c/}
+contains two distinct libraries,
+@code{libF77} and @code{libI77},
+each in their own subdirectories.
+In @code{g77}, this distinction is not made,
+beyond maintaining the subdirectory structure in the source-code tree.
+
+@file{libf2c/} is not part of the program @code{g77},
+just distributed with it.
+It contains files not present
+in the official (@code{netlib}) version of @code{libf2c},
+and also contains some minor changes made from @code{libf2c},
+to fix some bugs,
+and to facilitate automatic configuration, building, and installation of
+@code{libf2c} (as @code{libg2c}) for use by @code{g77} users.
+See @file{libf2c/README} for more information,
+including licensing conditions
+governing distribution of programs containing code from @code{libg2c}.
+
+@code{libg2c}, @code{g77}'s version of @code{libf2c},
+adds Dave Love's implementation of @code{libU77},
+in the @file{libf2c/libU77/} directory.
+This library is distributed under the
+GNU Library General Public License (LGPL)---see the
+file @file{libf2c/libU77/COPYING.LIB}
+for more information,
+as this license
+governs distribution conditions for programs containing code
+from this portion of the library.
+
+Files of note in @file{f/} and @file{libf2c/} are described below:
+
+@table @file
+@item f/BUGS
+Lists some important bugs known to be in g77.
+Or use Info (or GNU Emacs Info mode) to read
+the ``Actual Bugs'' node of the @code{g77} documentation:
+
+@smallexample
+info -f f/g77.info -n "Actual Bugs"
+@end smallexample
+
+@item f/ChangeLog
+Lists recent changes to @code{g77} internals.
+
+@item libf2c/ChangeLog
+Lists recent changes to @code{libg2c} internals.
+
+@item f/NEWS
+Contains the per-release changes.
+These include the user-visible
+changes described in the node ``Changes''
+in the @code{g77} documentation, plus internal
+changes of import.
+Or use:
+
+@smallexample
+info -f f/g77.info -n News
+@end smallexample
+
+@item f/g77.info*
+The @code{g77} documentation, in Info format,
+produced by building @code{g77}.
+
+All users of @code{g77} (not just installers) should read this,
+using the @code{more} command if neither the @code{info} command,
+nor GNU Emacs (with its Info mode), are available, or if users
+aren't yet accustomed to using these tools.
+All of these files are readable as ``plain text'' files,
+though they're easier to navigate using Info readers
+such as @code{info} and GNU Emacs Info mode.
+@end table
+
+If you want to explore the FFE code, which lives entirely in @file{f/},
+here are a few clues.
+The file @file{g77spec.c} contains the @code{g77}-specific source code
+for the @code{g77} command only---this just forms a variant of the
+@code{gcc} command, so,
+just as the @code{gcc} command itself does not contain the C front end,
+the @code{g77} command does not contain the Fortran front end (FFE).
+The FFE code ends up in an executable named @file{f771},
+which does the actual compiling,
+so it contains the FFE plus the @code{gcc} back end (GBE),
+the latter to do most of the optimization, and the code generation.
+
+The file @file{parse.c} is the source file for @code{yyparse()},
+which is invoked by the GBE to start the compilation process,
+for @file{f771}.
+
+The file @file{top.c} contains the top-level FFE function @code{ffe_file}
+and it (along with top.h) define all @samp{ffe_[a-z].*}, @samp{ffe[A-Z].*},
+and @samp{FFE_[A-Za-z].*} symbols.
+
+The file @file{fini.c} is a @code{main()} program that is used when building
+the FFE to generate C header and source files for recognizing keywords.
+The files @file{malloc.c} and @file{malloc.h} comprise a memory manager
+that defines all @samp{malloc_[a-z].*}, @samp{malloc[A-Z].*}, and
+@samp{MALLOC_[A-Za-z].*} symbols.
+
+All other modules named @var{xyz}
+are comprised of all files named @samp{@var{xyz}*.@var{ext}}
+and define all @samp{ffe@var{xyz}_[a-z].*}, @samp{ffe@var{xyz}[A-Z].*},
+and @samp{FFE@var{XYZ}_[A-Za-z].*} symbols.
+If you understand all this, congratulations---it's easier for me to remember
+how it works than to type in these regular expressions.
+But it does make it easy to find where a symbol is defined.
+For example, the symbol @samp{ffexyz_set_something} would be defined
+in @file{xyz.h} and implemented there (if it's a macro) or in @file{xyz.c}.
+
+The ``porting'' files of note currently are:
+
+@table @file
+@item proj.c
+@itemx proj.h
+This defines the ``language'' used by all the other source files,
+the language being Standard C plus some useful things
+like @code{ARRAY_SIZE} and such.
+
+@item target.c
+@itemx target.h
+These describe the target machine
+in terms of what data types are supported,
+how they are denoted
+(to what C type does an @code{INTEGER*8} map, for example),
+how to convert between them,
+and so on.
+Over time, versions of @code{g77} rely less on this file
+and more on run-time configuration based on GBE info
+in @file{com.c}.
+
+@item com.c
+@itemx com.h
+These are the primary interface to the GBE.
+
+@item ste.c
+@itemx ste.h
+This contains code for implementing recognized executable statements
+in the GBE.
+
+@item src.c
+@itemx src.h
+These contain information on the format(s) of source files
+(such as whether they are never to be processed as case-insensitive
+with regard to Fortran keywords).
+@end table
+
+If you want to debug the @file{f771} executable,
+for example if it crashes,
+note that the global variables @code{lineno} and @code{input_filename}
+are usually set to reflect the current line being read by the lexer
+during the first-pass analysis of a program unit and to reflect
+the current line being processed during the second-pass compilation
+of a program unit.
+
+If an invocation of the function @code{ffestd_exec_end} is on the stack,
+the compiler is in the second pass, otherwise it is in the first.
+
+(This information might help you reduce a test case and/or work around
+a bug in @code{g77} until a fix is available.)
+
+@node Overview of Translation Process
+@section Overview of Translation Process
+
+The order of phases translating source code to the form accepted
+by the GBE is:
+
+@enumerate
+@item
+Stripping punched-card sources (@file{g77stripcard.c})
+
+@item
+Lexing (@file{lex.c})
+
+@item
+Stand-alone statement identification (@file{sta.c})
+
+@item
+Parsing (@file{stb.c} and @file{expr.c})
+
+@item
+Constructing (@file{stc.c})
+
+@item
+Collecting (@file{std.c})
+
+@item
+Expanding (@file{ste.c})
+@end enumerate
+
+To get a rough idea of how a particularly twisted Fortran statement
+gets treated by the passes, consider:
+
+@smallexample
+ FORMAT(I2 4H)=(J/
+ & I3)
+@end smallexample
+
+The job of @file{lex.c} is to know enough about Fortran syntax rules
+to break the statement up into distinct lexemes without requiring
+any feedback from subsequent phases:
+
+@smallexample
+`FORMAT'
+`('
+`I24H'
+`)'
+`='
+`('
+`J'
+`/'
+`I3'
+`)'
+@end smallexample
+
+The job of @file{sta.c} is to figure out the kind of statement,
+or, at least, statement form, that sequence of lexemes represent.
+
+The sooner it can do this (in terms of using the smallest number of
+lexemes, starting with the first for each statement), the better,
+because that leaves diagnostics for problems beyond the recognition
+of the statement form to subsequent phases,
+which can usually better describe the nature of the problem.
+
+In this case, the @samp{=} at ``level zero''
+(not nested within parentheses)
+tells @file{sta.c} that this is an @emph{assignment-form},
+not @code{FORMAT}, statement.
+
+An assignment-form statement might be a statement-function
+definition or an executable assignment statement.
+
+To make that determination,
+@file{sta.c} looks at the first two lexemes.
+
+Since the second lexeme is @samp{(},
+the first must represent an array for this to be an assignment statement,
+else it's a statement function.
+
+Either way, @file{sta.c} hands off the statement to @file{stb.c}
+(either its statement-function parser or its assignment-statement parser).
+
+@file{stb.c} forms a
+statement-specific record containing the pertinent information.
+That information includes a source expression and,
+for an assignment statement, a destination expression.
+Expressions are parsed by @file{expr.c}.
+
+This record is passed to @file{stc.c},
+which copes with the implications of the statement
+within the context established by previous statements.
+
+For example, if it's the first statement in the file
+or after an @code{END} statement,
+@file{stc.c} recognizes that, first of all,
+a main program unit is now being lexed
+(and tells that to @file{std.c}
+before telling it about the current statement).
+
+@file{stc.c} attaches whatever information it can,
+usually derived from the context established by the preceding statements,
+and passes the information to @file{std.c}.
+
+@file{std.c} saves this information away,
+since the GBE cannot cope with information
+that might be incomplete at this stage.
+
+For example, @samp{I3} might later be determined
+to be an argument to an alternate @code{ENTRY} point.
+
+When @file{std.c} is told about the end of an external (top-level)
+program unit,
+it passes all the information it has saved away
+on statements in that program unit
+to @file{ste.c}.
+
+@file{ste.c} ``expands'' each statement, in sequence, by
+constructing the appropriate GBE information and calling
+the appropriate GBE routines.
+
+Details on the transformational phases follow.
+Keep in mind that Fortran numbering is used,
+so the first character on a line is column 1,
+decimal numbering is used, and so on.
+
+@menu
+* g77stripcard::
+* lex.c::
+* sta.c::
+* stb.c::
+* expr.c::
+* stc.c::
+* std.c::
+* ste.c::
+
+* Gotchas (Transforming)::
+* TBD (Transforming)::
+@end menu
+
+@node g77stripcard
+@subsection g77stripcard
+
+The @code{g77stripcard} program handles removing content beyond
+column 72 (adjustable via a command-line option),
+optionally warning about that content being something other
+than trailing whitespace or Fortran commentary.
+
+This program is needed because @code{lex.c} doesn't pay attention
+to maximum line lengths at all, to make it easier to maintain,
+as well as faster (for sources that don't depend on the maximum
+column length vis-a-vis trailing non-blank non-commentary content).
+
+Just how this program will be run---whether automatically for
+old source (perhaps as the default for @file{.f} files?)---is not
+yet determined.
+
+In the meantime, it might as well be implemented as a typical UNIX pipe.
+
+It should accept a @samp{-fline-length-@var{n}} option,
+with the default line length set to 72.
+
+When the text it strips off the end of a line is not blank
+(not spaces and tabs),
+it should insert an additional comment line
+(beginning with @samp{!},
+so it works for both fixed-form and free-form files)
+containing the text,
+following the stripped line.
+The inserted comment should have a prefix of some kind,
+TBD, that distinguishes the comment as representing stripped text.
+Users could use that to @code{sed} out such lines, if they wished---it
+seems silly to provide a command-line option to delete information
+when it can be so easily filtered out by another program.
+
+(This inserted comment should be designed to ``fit in'' well
+with whatever the Fortran community is using these days for
+preprocessor, translator, and other such products, like OpenMP.
+What that's all about, and how @code{g77} can elegantly fit its
+special comment conventions into it all, is TBD as well.
+We don't want to reinvent the wheel here, but if there turn out
+to be too many conflicting conventions, we might have to invent
+one that looks nothing like the others, but which offers their
+host products a better infrastructure in which to fit and coexist
+peacefully.)
+
+@code{g77stripcard} probably shouldn't do any tab expansion or other
+fancy stuff.
+People can use @code{expand} or other pre-filtering if they like.
+The idea here is to keep each stage quite simple, while providing
+excellent performance for ``normal'' code.
+
+(Code with junk beyond column 73 is not really ``normal'',
+as it comes from a card-punch heritage,
+and will be increasingly hard for tomorrow's Fortran programmers to read.)
+
+@node lex.c
+@subsection lex.c
+
+To help make the lexer simple, fast, and easy to maintain,
+while also having @code{g77} generally encourage Fortran programmers
+to write simple, maintainable, portable code by maximizing the
+performance of compiling that kind of code:
+
+@itemize @bullet
+@item
+There'll be just one lexer, for both fixed-form and free-form source.
+
+@item
+It'll care about the form only when handling the first 7 columns of
+text, stuff like spaces between strings of alphanumerics, and
+how lines are continued.
+
+Some other distinctions will be handled by subsequent phases,
+so at least one of them will have to know which form is involved.
+
+For example, @samp{I = 2 . 4} is acceptable in fixed form,
+and works in free form as well given the implementation @code{g77}
+presently uses.
+But the standard requires a diagnostic for it in free form,
+so the parser has to be able to recognize that
+the lexemes aren't contiguous
+(information the lexer @emph{does} have to provide)
+and that free-form source is being parsed,
+so it can provide the diagnostic.
+
+The @code{g77} lexer doesn't try to gather @samp{2 . 4} into a single lexeme.
+Otherwise, it'd have to know a whole lot more about how to parse Fortran,
+or subsequent phases (mainly parsing) would have two paths through
+lots of critical code---one to handle the lexeme @samp{2}, @samp{.},
+and @samp{4} in sequence, another to handle the lexeme @samp{2.4}.
+
+@item
+It won't worry about line lengths
+(beyond the first 7 columns for fixed-form source).
+
+That is, once it starts parsing the ``statement'' part of a line
+(column 7 for fixed-form, column 1 for free-form),
+it'll keep going until it finds a newline,
+rather than ignoring everything past a particular column
+(72 or 132).
+
+The implication here is that there shouldn't @emph{be}
+anything past that last column, other than whitespace or
+commentary, because users using typical editors
+(or viewing output as typically printed)
+won't necessarily know just where the last column is.
+
+Code that has ``garbage'' beyond the last column
+(almost certainly only fixed-form code with a punched-card legacy,
+such as code using columns 73-80 for ``sequence numbers'')
+will have to be run through @code{g77stripcard} first.
+
+Also, keeping track of the maximum column position while also watching out
+for the end of a line @emph{and} while reading from a file
+just makes things slower.
+Since a file must be read, and watching for the end of the line
+is necessary (unless the typical input file was preprocessed to
+include the necessary number of trailing spaces),
+dropping the tracking of the maximum column position
+is the only way to reduce the complexity of the pertinent code
+while maintaining high performance.
+
+@item
+ASCII encoding is assumed for the input file.
+
+Code written in other character sets will have to be converted first.
+
+@item
+Tabs (ASCII code 9)
+will be converted to spaces via the straightforward
+approach.
+
+Specifically, a tab is converted to between one and eight spaces
+as necessary to reach column @var{n},
+where dividing @samp{(@var{n} - 1)} by eight
+results in a remainder of zero.
+
+@item
+Linefeeds (ASCII code 10)
+mark the ends of lines.
+
+@item
+A carriage return (ASCII code 13)
+is accept if it immediately precedes a linefeed,
+in which case it is ignored.
+
+Otherwise, it is rejected (with a diagnostic).
+
+@item
+Any other characters other than the above
+that are not part of the GNU Fortran Character Set
+(@pxref{Character Set})
+are rejected with a diagnostic.
+
+This includes backspaces, form feeds, and the like.
+
+(It might make sense to allow a form feed in column 1
+as long as that's the only character on a line.
+It certainly wouldn't seem to cost much in terms of performance.)
+
+@item
+The end of the input stream (EOF)
+ends the current line.
+
+@item
+The distinction between uppercase and lowercase letters
+will be preserved.
+
+It will be up to subsequent phases to decide to fold case.
+
+Current plans are to permit any casing for Fortran (reserved) keywords
+while preserving casing for user-defined names.
+(This might not be made the default for @file{.f} files, though.)
+
+Preserving case seems necessary to provide more direct access
+to facilities outside of @code{g77}, such as to C or Pascal code.
+
+Names of intrinsics will probably be matchable in any case,
+However, there probably won't be any option to require
+a particular mixed-case appearance of intrinsics
+(as there was for @code{g77} prior to version 0.6),
+because that's painful to maintain,
+and probably nobody uses it.
+
+(How @samp{external SiN; r = sin(x)} would be handled is TBD.
+I think old @code{g77} might already handle that pretty elegantly,
+but whether we can cope with allowing the same fragment to reference
+a @emph{different} procedure, even with the same interface,
+via @samp{s = SiN(r)}, needs to be determined.
+If it can't, we need to make sure that when code introduces
+a user-defined name, any intrinsic matching that name
+using a case-insensitive comparison
+is ``turned off''.)
+
+@item
+Backslashes in @code{CHARACTER} and Hollerith constants
+are not allowed.
+
+This avoids the confusion introduced by some Fortran compiler vendors
+providing C-like interpretation of backslashes,
+while others provide straight-through interpretation.
+
+Some kind of lexical construct (TBD) will be provided to allow
+flagging of a @code{CHARACTER}
+(but probably not a Hollerith)
+constant that permits backslashes.
+It'll necessarily be a prefix, such as:
+
+@smallexample
+PRINT *, C'This line has a backspace \b here.'
+PRINT *, F'This line has a straight backslash \ here.'
+@end smallexample
+
+Further, command-line options might be provided to specify that
+one prefix or the other is to be assumed as the default
+for @code{CHARACTER} constants.
+
+However, it seems more helpful for @code{g77} to provide a program
+that converts prefix all constants
+(or just those containing backslashes)
+with the desired designation,
+so printouts of code can be read
+without knowing the compile-time options used when compiling it.
+
+If such a program is provided
+(let's name it @code{g77slash} for now),
+then a command-line option to @code{g77} should not be provided.
+(Though, given that it'll be easy to implement, it might be hard
+to resist user requests for it ``to compile faster than if we
+have to invoke another filter''.)
+
+This program would take a command-line option to specify the
+default interpretation of slashes,
+affecting which prefix it uses for constants.
+
+@code{g77slash} probably should automatically convert Hollerith
+constants that contain slashes
+to the appropriate @code{CHARACTER} constants.
+Then @code{g77} wouldn't have to define a prefix syntax for Hollerith
+constants specifying whether they want C-style or straight-through
+backslashes.
+@end itemize
+
+The above implements nearly exactly what is specified by
+@ref{Character Set},
+and
+@ref{Lines},
+except it also provides automatic conversion of tabs
+and ignoring of newline-related carriage returns.
+
+It also effects the ``pure visual'' model,
+by which is meant that a user viewing his code
+in a typical text editor
+(assuming it's not preprocessed via @code{g77stripcard} or similar)
+doesn't need any special knowledge
+of whether spaces on the screen are really tabs,
+whether lines end immediately after the last visible non-space character
+or after a number of spaces and tabs that follow it,
+or whether the last line in the file is ended by a newline.
+
+Most editors don't make these distinctions,
+the ANSI FORTRAN 77 standard doesn't require them to,
+and it permits a standard-conforming compiler
+to define a method for transforming source code to
+``standard form'' however it wants.
+
+So, GNU Fortran defines it such that users have the best chance
+of having the code be interpreted the way it looks on the screen
+of the typical editor.
+
+(Fancy editors should @emph{never} be required to correctly read code
+written in classic two-dimensional-plaintext form.
+By correct reading I mean ability to read it, book-like, without
+mistaking text ignored by the compiler for program code and vice versa,
+and without having to count beyond the first several columns.
+The vague meaning of ASCII TAB, among other things, complicates
+this somewhat, but as long as ``everyone'', including the editor,
+other tools, and printer, agrees about the every-eighth-column convention,
+the GNU Fortran ``pure visual'' model meets these requirements.
+Any language or user-visible source form
+requiring special tagging of tabs,
+the ends of lines after spaces/tabs,
+and so on, is broken by this definition.
+Fortunately, Fortran @emph{itself} is not broken,
+even if most vendor-supplied defaults for their Fortran compilers @emph{are}
+in this regard.)
+
+Further, this model provides a clean interface
+to whatever preprocessors or code-generators are used
+to produce input to this phase of @code{g77}.
+Mainly, they need not worry about long lines.
+
+@node sta.c
+@subsection sta.c
+
+@node stb.c
+@subsection stb.c
+
+@node expr.c
+@subsection expr.c
+
+@node stc.c
+@subsection stc.c
+
+@node std.c
+@subsection std.c
+
+@node ste.c
+@subsection ste.c
+
+@node Gotchas (Transforming)
+@subsection Gotchas (Transforming)
+
+This section is not about transforming ``gotchas'' into something else.
+It is about the weirder aspects of transforming Fortran,
+however that's defined,
+into a more modern, canonical form.
+
+@subsubsection Multi-character Lexemes
+
+Each lexeme carries with it a pointer to where it appears in the source.
+
+To provide the ability for diagnostics to point to column numbers,
+in addition to line numbers and names,
+lexemes that represent more than one (significant) character
+in the source code need, generally,
+to provide pointers to where each @emph{character} appears in the source.
+
+This provides the ability to properly identify the precise location
+of the problem in code like
+
+@smallexample
+SUBROUTINE X
+END
+BLOCK DATA X
+END
+@end smallexample
+
+which, in fixed-form source, would result in single lexemes
+consisting of the strings @samp{SUBROUTINEX} and @samp{BLOCKDATAX}.
+(The problem is that @samp{X} is defined twice,
+so a pointer to the @samp{X} in the second definition,
+as well as a follow-up pointer to the corresponding pointer in the first,
+would be preferable to pointing to the beginnings of the statements.)
+
+This need also arises when parsing (and diagnosing) @code{FORMAT}
+statements.
+
+Further, it arises when diagnosing
+@code{FMT=} specifiers that contain constants
+(or partial constants, or even propagated constants!)
+in I/O statements, as in:
+
+@smallexample
+PRINT '(I2, 3HAB)', J
+@end smallexample
+
+(A pointer to the beginning of the prematurely-terminated Hollerith
+constant, and/or to the close parenthese, is preferable to a pointer
+to the open-parenthese or the apostrophe that precedes it.)
+
+Multi-character lexemes, which would seem to naturally include
+at least digit strings, alphanumeric strings, @code{CHARACTER}
+constants, and Hollerith constants, therefore need to provide
+location information on each character.
+(Maybe Hollerith constants don't, but it's unnecessary to except them.)
+
+The question then arises, what about @emph{other} multi-character lexemes,
+such as @samp{**} and @samp{//},
+and Fortran 90's @samp{(/}, @samp{/)}, @samp{::}, and so on?
+
+Turns out there's a need to identify the location of the second character
+of these two-character lexemes.
+For example, in @samp{I(/J) = K}, the slash needs to be diagnosed
+as the problem, not the open parenthese.
+Similarly, it is preferable to diagnose the second slash in
+@samp{I = J // K} rather than the first, given the implicit typing
+rules, which would result in the compiler disallowing the attempted
+concatenation of two integers.
+(Though, since that's more of a semantic issue,
+it's not @emph{that} much preferable.)
+
+Even sequences that could be parsed as digit strings could use location info,
+for example, to diagnose the @samp{9} in the octal constant @samp{O'129'}.
+(This probably will be parsed as a character string,
+to be consistent with the parsing of @samp{Z'129A'}.)
+
+To avoid the hassle of recording the location of the second character,
+while also preserving the general rule that each significant character
+is distinctly pointed to by the lexeme that contains it,
+it's best to simply not have any fixed-size lexemes
+larger than one character.
+
+This new design is expected to make checking for two
+@samp{*} lexemes in a row much easier than the old design,
+so this is not much of a sacrifice.
+It probably makes the lexer much easier to implement
+than it makes the parser harder.
+
+@subsubsection Space-padding Lexemes
+
+Certain lexemes need to be padded with virtual spaces when the
+end of the line (or file) is encountered.
+
+This is necessary in fixed form, to handle lines that don't
+extend to column 72, assuming that's the line length in effect.
+
+@subsubsection Bizarre Free-form Hollerith Constants
+
+Last I checked, the Fortran 90 standard actually required the compiler
+to silently accept something like
+
+@smallexample
+FORMAT ( 1 2 Htwelve chars )
+@end smallexample
+
+as a valid @code{FORMAT} statement specifying a twelve-character
+Hollerith constant.
+
+The implication here is that, since the new lexer is a zero-feedback one,
+it won't know that the special case of a @code{FORMAT} statement being parsed
+requires apparently distinct lexemes @samp{1} and @samp{2} to be treated as
+a single lexeme.
+
+(This is a horrible misfeature of the Fortran 90 language.
+It's one of many such misfeatures that almost make me want
+to not support them, and forge ahead with designing a new
+``GNU Fortran'' language that has the features,
+but not the misfeatures, of Fortran 90,
+and provide utility programs to do the conversion automatically.)
+
+So, the lexer must gather distinct chunks of decimal strings into
+a single lexeme in contexts where a single decimal lexeme might
+start a Hollerith constant.
+
+(Which probably means it might as well do that all the time
+for all multi-character lexemes, even in free-form mode,
+leaving it to subsequent phases to pull them apart as they see fit.)
+
+Compare the treatment of this to how
+
+@smallexample
+CHARACTER * 4 5 HEY
+@end smallexample
+
+and
+
+@smallexample
+CHARACTER * 12 HEY
+@end smallexample
+
+must be treated---the former must be diagnosed, due to the separation
+between lexemes, the latter must be accepted as a proper declaration.
+
+@subsubsection Hollerith Constants
+
+Recognizing a Hollerith constant---specifically,
+that an @samp{H} or @samp{h} after a digit string begins
+such a constant---requires some knowledge of context.
+
+Hollerith constants (such as @samp{2HAB}) can appear after:
+
+@itemize @bullet
+@item
+@samp{(}
+
+@item
+@samp{,}
+
+@item
+@samp{=}
+
+@item
+@samp{+}, @samp{-}, @samp{/}
+
+@item
+@samp{*}, except as noted below
+@end itemize
+
+Hollerith constants don't appear after:
+
+@itemize @bullet
+@item
+@samp{CHARACTER*},
+which can be treated generally as
+any @samp{*} that is the second lexeme of a statement
+@end itemize
+
+@subsubsection Confusing Function Keyword
+
+While
+
+@smallexample
+REAL FUNCTION FOO ()
+@end smallexample
+
+must be a @code{FUNCTION} statement and
+
+@smallexample
+REAL FUNCTION FOO (5)
+@end smallexample
+
+must be a type-definition statement,
+
+@smallexample
+REAL FUNCTION FOO (@var{names})
+@end smallexample
+
+where @var{names} is a comma-separated list of names,
+can be one or the other.
+
+The only way to disambiguate that statement
+(short of mandating free-form source or a short maximum
+length for name for external procedures)
+is based on the context of the statement.
+
+In particular, the statement is known to be within an
+already-started program unit
+(but not at the outer level of the @code{CONTAINS} block),
+it is a type-declaration statement.
+
+Otherwise, the statement is a @code{FUNCTION} statement,
+in that it begins a function program unit
+(external, or, within @code{CONTAINS}, nested).
+
+@subsubsection Weird READ
+
+The statement
+
+@smallexample
+READ (N)
+@end smallexample
+
+is equivalent to either
+
+@smallexample
+READ (UNIT=(N))
+@end smallexample
+
+or
+
+@smallexample
+READ (FMT=(N))
+@end smallexample
+
+depending on which would be valid in context.
+
+Specifically, if @samp{N} is type @code{INTEGER},
+@samp{READ (FMT=(N))} would not be valid,
+because parentheses may not be used around @samp{N},
+whereas they may around it in @samp{READ (UNIT=(N))}.
+
+Further, if @samp{N} is type @code{CHARACTER},
+the opposite is true---@samp{READ (UNIT=(N))} is not valid,
+but @samp{READ (FMT=(N))} is.
+
+Strictly speaking, if anything follows
+
+@smallexample
+READ (N)
+@end smallexample
+
+in the statement, whether the first lexeme after the close
+parenthese is a comma could be used to disambiguate the two cases,
+without looking at the type of @samp{N},
+because the comma is required for the @samp{READ (FMT=(N))}
+interpretation and disallowed for the @samp{READ (UNIT=(N))}
+interpretation.
+
+However, in practice, many Fortran compilers allow
+the comma for the @samp{READ (UNIT=(N))}
+interpretation anyway
+(in that they generally allow a leading comma before
+an I/O list in an I/O statement),
+and much code takes advantage of this allowance.
+
+(This is quite a reasonable allowance, since the
+juxtaposition of a comma-separated list immediately
+after an I/O control-specification list, which is also comma-separated,
+without an intervening comma,
+looks sufficiently ``wrong'' to programmers
+that they can't resist the itch to insert the comma.
+@samp{READ (I, J), K, L} simply looks cleaner than
+@samp{READ (I, J) K, L}.)
+
+So, type-based disambiguation is needed unless strict adherence
+to the standard is always assumed, and we're not going to assume that.
+
+@node TBD (Transforming)
+@subsection TBD (Transforming)
+
+Continue researching gotchas, designing the transformational process,
+and implementing it.
+
+Specific issues to resolve:
+
+@itemize @bullet
+@item
+Just where should @code{INCLUDE} processing take place?
+
+Clearly before (or part of) statement identification (@file{sta.c}),
+since determining whether @samp{I(J)=K} is a statement-function
+definition or an assignment statement requires knowing the context,
+which in turn requires having processed @code{INCLUDE} files.
+
+@item
+Just where should (if it was implemented) @code{USE} processing take place?
+
+This gets into the whole issue of how @code{g77} should handle the concept
+of modules.
+I think GNAT already takes on this issue, but don't know more than that.
+Jim Giles has written extensively on @code{comp.lang.fortran}
+about his opinions on module handling, as have others.
+Jim's views should be taken into account.
+
+Actually, Richard M. Stallman (RMS) also has written up
+some guidelines for implementing such things,
+but I'm not sure where I read them.
+Perhaps the old @email{gcc2@@cygnus.com} list.
+
+If someone could dig references to these up and get them to me,
+that would be much appreciated!
+Even though modules are not on the short-term list for implementation,
+it'd be helpful to know @emph{now} how to avoid making them harder to
+implement them @emph{later}.
+
+@item
+Should the @code{g77} command become just a script that invokes
+all the various preprocessing that might be needed,
+thus making it seem slower than necessary for legacy code
+that people are unwilling to convert,
+or should we provide a separate script for that,
+thus encouraging people to convert their code once and for all?
+
+At least, a separate script to behave as old @code{g77} did,
+perhaps named @code{g77old}, might ease the transition,
+as might a corresponding one that converts source codes
+named @code{g77oldnew}.
+
+These scripts would take all the pertinent options @code{g77} used
+to take and run the appropriate filters,
+passing the results to @code{g77} or just making new sources out of them
+(in a subdirectory, leaving the user to do the dirty deed of
+moving or copying them over the old sources).
+
+@item
+Do other Fortran compilers provide a prefix syntax
+to govern the treatment of backslashes in @code{CHARACTER}
+(or Hollerith) constants?
+
+Knowing what other compilers provide would help.
+
+@item
+Is it okay to drop support for the @samp{-fintrin-case-initcap},
+@samp{-fmatch-case-initcap}, @samp{-fsymbol-case-initcap},
+and @samp{-fcase-initcap} options?
+
+I've asked @email{info-gnu-fortran@@gnu.org} for input on this.
+Not having to support these makes it easier to write the new front end,
+and might also avoid complicated its design.
+@end itemize
+
+@node Philosophy of Code Generation
+@section Philosophy of Code Generation
+
+Don't poke the bear.
+
+The @code{g77} front end generates code
+via the @code{gcc} back end.
+
+@cindex GNU Back End (GBE)
+@cindex GBE
+@cindex @code{gcc}, back end
+@cindex back end, gcc
+@cindex code generator
+The @code{gcc} back end (GBE) is a large, complex
+labyrinth of intricate code
+written in a combination of the C language
+and specialized languages internal to @code{gcc}.
+
+While the @emph{code} that implements the GBE
+is written in a combination of languages,
+the GBE itself is,
+to the front end for a language like Fortran,
+best viewed as a @emph{compiler}
+that compiles its own, unique, language.
+
+The GBE's ``source'', then, is written in this language,
+which consists primarily of
+a combination of calls to GBE functions
+and @dfn{tree} nodes
+(which are, themselves, created
+by calling GBE functions).
+
+So, the @code{g77} generates code by, in effect,
+translating the Fortran code it reads
+into a form ``written'' in the ``language''
+of the @code{gcc} back end.
+
+@cindex GBEL
+@cindex GNU Back End Language (GBEL)
+This language will heretofore be referred to as @dfn{GBEL},
+for GNU Back End Language.
+
+GBEL is an evolving language,
+not fully specified in any published form
+as of this writing.
+It offers many facilities,
+but its ``core'' facilities
+are those that corresponding most directly
+to those needed to support @code{gcc}
+(compiling code written in GNU C).
+
+The @code{g77} Fortran Front End (FFE)
+is designed and implemented
+to navigate the currents and eddies
+of ongoing GBEL and @code{gcc} development
+while also delivering on the potential
+of an integrated FFE
+(as compared to using a converter like @code{f2c}
+and feeding the output into @code{gcc}).
+
+Goals of the FFE's code-generation strategy include:
+
+@itemize @bullet
+@item
+High likelihood of generation of correct code,
+or, failing that, producing a fatal diagnostic or crashing.
+
+@item
+Generation of highly optimized code,
+as directed by the user
+via GBE-specific (versus @code{g77}-specific) constructs,
+such as command-line options.
+
+@item
+Fast overall (FFE plus GBE) compilation.
+
+@item
+Preservation of source-level debugging information.
+@end itemize
+
+The strategies historically, and currently, used by the FFE
+to achieve these goals include:
+
+@itemize @bullet
+@item
+Use of GBEL constructs that most faithfully encapsulate
+the semantics of Fortran.
+
+@item
+Avoidance of GBEL constructs that are so rarely used,
+or limited to use in specialized situations not related to Fortran,
+that their reliability and performance has not yet been established
+as sufficient for use by the FFE.
+
+@item
+Flexible design, to readily accommodate changes to specific
+code-generation strategies, perhaps governed by command-line options.
+@end itemize
+
+@cindex Bear-poking
+@cindex Poking the bear
+``Don't poke the bear'' somewhat summarizes the above strategies.
+The GBE is the bear.
+The FFE is designed and implemented to avoid poking it
+in ways that are likely to just annoy it.
+The FFE usually either tackles it head-on,
+or avoids treating it in ways dissimilar to how
+the @code{gcc} front end treats it.
+
+For example, the FFE uses the native array facility in the back end
+instead of the lower-level pointer-arithmetic facility
+used by @code{gcc} when compiling @code{f2c} output).
+Theoretically, this presents more opportunities for optimization,
+faster compile times,
+and the production of more faithful debugging information.
+These benefits were not, however, immediately realized,
+mainly because @code{gcc} itself makes little or no use
+of the native array facility.
+
+Complex arithmetic is a case study of the evolution of this strategy.
+When originally implemented,
+the GBEL had just evolved its own native complex-arithmetic facility,
+so the FFE took advantage of that.
+
+When porting @code{g77} to 64-bit systems,
+it was discovered that the GBE didn't really
+implement its native complex-arithmetic facility properly.
+
+The short-term solution was to rewrite the FFE
+to instead use the lower-level facilities
+that'd be used by @code{gcc}-compiled code
+(assuming that code, itself, didn't use the native complex type
+provided, as an extension, by @code{gcc}),
+since these were known to work,
+and, in any case, if shown to not work,
+would likely be rapidly fixed
+(since they'd likely not work for vanilla C code in similar circumstances).
+
+However, the rewrite accommodated the original, native approach as well
+by offering a command-line option to select it over the emulated approach.
+This allowed users, and especially GBE maintainers, to try out
+fixes to complex-arithmetic support in the GBE
+while @code{g77} continued to default to compiling more code correctly,
+albeit producing (typically) slower executables.
+
+As of April 1999, it appeared that the last few bugs
+in the GBE's support of its native complex-arithmetic facility
+were worked out.
+The FFE was changed back to default to using that native facility,
+leaving emulation as an option.
+
+Other Fortran constructs---arrays, character strings,
+complex division, @code{COMMON} and @code{EQUIVALENCE} aggregates,
+and so on---involve issues similar to those pertaining to complex arithmetic.
+
+So, it is possible that the history
+of how the FFE handled complex arithmetic
+will be repeated, probably in modified form
+(and hopefully over shorter timeframes),
+for some of these other facilities.
+
+@node Two-pass Design
+@section Two-pass Design
+
+The FFE does not tell the GBE anything about a program unit
+until after the last statement in that unit has been parsed.
+(A program unit is a Fortran concept that corresponds, in the C world,
+mostly closely to functions definitions in ISO C.
+That is, a program unit in Fortran is like a top-level function in C.
+Nested functions, found among the extensions offered by GNU C,
+correspond roughly to Fortran's statement functions.)
+
+So, while parsing the code in a program unit,
+the FFE saves up all the information
+on statements, expressions, names, and so on,
+until it has seen the last statement.
+
+At that point, the FFE revisits the saved information
+(in what amounts to a second @dfn{pass} over the program unit)
+to perform the actual translation of the program unit into GBEL,
+ultimating in the generation of assembly code for it.
+
+Some lookahead is performed during this second pass,
+so the FFE could be viewed as a ``two-plus-pass'' design.
+
+@menu
+* Two-pass Code::
+* Why Two Passes::
+@end menu
+
+@node Two-pass Code
+@subsection Two-pass Code
+
+Most of the code that turns the first pass (parsing)
+into a second pass for code generation
+is in @file{@value{path-g77}/std.c}.
+
+It has external functions,
+called mainly by siblings in @file{@value{path-g77}/stc.c},
+that record the information on statements and expressions
+in the order they are seen in the source code.
+These functions save that information.
+
+It also has an external function that revisits that information,
+calling the siblings in @file{@value{path-g77}/ste.c},
+which handles the actual code generation
+(by generating GBEL code,
+that is, by calling GBE routines
+to represent and specify expressions, statements, and so on).
+
+@node Why Two Passes
+@subsection Why Two Passes
+
+The need for two passes was not immediately evident
+during the design and implementation of the code in the FFE
+that was to produce GBEL.
+Only after a few kludges,
+to handle things like incorrectly-guessed @code{ASSIGN} label nature,
+had been implemented,
+did enough evidence pile up to make it clear
+that @file{std.c} had to be introduced to intercept,
+save, then revisit as part of a second pass,
+the digested contents of a program unit.
+
+Other such missteps have occurred during the evolution of the FFE,
+because of the different goals of the FFE and the GBE.
+
+Because the GBE's original, and still primary, goal
+was to directly support the GNU C language,
+the GBEL, and the GBE itself,
+requires more complexity
+on the part of most front ends
+than it requires of @code{gcc}'s.
+
+For example,
+the GBEL offers an interface that permits the @code{gcc} front end
+to implement most, or all, of the language features it supports,
+without the front end having to
+make use of non-user-defined variables.
+(It's almost certainly the case that all of K&R C,
+and probably ANSI C as well,
+is handled by the @code{gcc} front end
+without declaring such variables.)
+
+The FFE, on the other hand, must resort to a variety of ``tricks''
+to achieve its goals.
+
+Consider the following C code:
+
+@smallexample
+int
+foo (int a, int b)
+@{
+ int c = 0;
+
+ if ((c = bar (c)) == 0)
+ goto done;
+
+ quux (c << 1);
+
+done:
+ return c;
+@}
+@end smallexample
+
+Note what kinds of objects are declared, or defined, before their use,
+and before any actual code generation involving them
+would normally take place:
+
+@itemize @bullet
+@item
+Return type of function
+
+@item
+Entry point(s) of function
+
+@item
+Dummy arguments
+
+@item
+Variables
+
+@item
+Initial values for variables
+@end itemize
+
+Whereas, the following items can, and do,
+suddenly appear ``out of the blue'' in C:
+
+@itemize @bullet
+@item
+Label references
+
+@item
+Function references
+@end itemize
+
+Not surprisingly, the GBE faithfully permits the latter set of items
+to be ``discovered'' partway through GBEL ``programs'',
+just as they are permitted to in C.
+
+Yet, the GBE has tended, at least in the past,
+to be reticent to fully support similar ``late'' discovery
+of items in the former set.
+
+This makes Fortran a poor fit for the ``safe'' subset of GBEL.
+Consider:
+
+@smallexample
+ FUNCTION X (A, ARRAY, ID1)
+ CHARACTER*(*) A
+ DOUBLE PRECISION X, Y, Z, TMP, EE, PI
+ REAL ARRAY(ID1*ID2)
+ COMMON ID2
+ EXTERNAL FRED
+
+ ASSIGN 100 TO J
+ CALL FOO (I)
+ IF (I .EQ. 0) PRINT *, A(0)
+ GOTO 200
+
+ ENTRY Y (Z)
+ ASSIGN 101 TO J
+200 PRINT *, A(1)
+ READ *, TMP
+ GOTO J
+100 X = TMP * EE
+ RETURN
+101 Y = TMP * PI
+ CALL FRED
+ DATA EE, PI /2.71D0, 3.14D0/
+ END
+@end smallexample
+
+Here are some observations about the above code,
+which, while somewhat contrived,
+conforms to the FORTRAN 77 and Fortran 90 standards:
+
+@itemize @bullet
+@item
+The return type of function @samp{X} is not known
+until the @samp{DOUBLE PRECISION} line has been parsed.
+
+@item
+Whether @samp{A} is a function or a variable
+is not known until the @samp{PRINT *, A(0)} statement
+has been parsed.
+
+@item
+The bounds of the array of argument @samp{ARRAY}
+depend on a computation involving
+the subsequent argument @samp{ID1}
+and the blank-common member @samp{ID2}.
+
+@item
+Whether @samp{Y} and @samp{Z} are local variables,
+additional function entry points,
+or dummy arguments to additional entry points
+is not known
+until the @code{ENTRY} statement is parsed.
+
+@item
+Similarly, whether @samp{TMP} is a local variable is not known
+until the @samp{READ *, TMP} statement is parsed.
+
+@item
+The initial values for @samp{EE} and @samp{PI}
+are not known until after the @code{DATA} statement is parsed.
+
+@item
+Whether @samp{FRED} is a function returning type @code{REAL}
+or a subroutine
+(which can be thought of as returning type @code{void}
+@emph{or}, to support alternate returns in a simple way,
+type @code{int})
+is not known
+until the @samp{CALL FRED} statement is parsed.
+
+@item
+Whether @samp{100} is a @code{FORMAT} label
+or the label of an executable statement
+is not known
+until the @samp{X =} statement is parsed.
+(These two types of labels get @emph{very} different treatment,
+especially when @code{ASSIGN}'ed.)
+
+@item
+That @samp{J} is a local variable is not known
+until the first @code{ASSIGN} statement is parsed.
+(This happens @emph{after} executable code has been seen.)
+@end itemize
+
+Very few of these ``discoveries''
+can be accommodated by the GBE as it has evolved over the years.
+The GBEL doesn't support several of them,
+and those it might appear to support
+don't always work properly,
+especially in combination with other GBEL and GBE features,
+as implemented in the GBE.
+
+(Had the GBE and its GBEL originally evolved to support @code{g77},
+the shoe would be on the other foot, so to speak---most, if not all,
+of the above would be directly supported by the GBEL,
+and a few C constructs would probably not, as they are in reality,
+be supported.
+Both this mythical, and today's real, GBE caters to its GBEL
+by, sometimes, scrambling around, cleaning up after itself---after
+discovering that assumptions it made earlier during code generation
+are incorrect.)
+
+So, the FFE handles these discrepancies---between the order in which
+it discovers facts about the code it is compiling,
+and the order in which the GBEL and GBE support such discoveries---by
+performing what amounts to two
+passes over each program unit.
+
+(A few ambiguities can remain at that point,
+such as whether, given @samp{EXTERNAL BAZ}
+and no other reference to @samp{BAZ} in the program unit,
+it is a subroutine, a function, or a block-data---which, in C-speak,
+governs its declared return type.
+Fortunately, these distinctions are easily finessed
+for the procedure, library, and object-file interfaces
+supported by @code{g77}.)
+
+@node Challenges Posed
+@section Challenges Posed
+
+Consider the following Fortran code, which uses various extensions
+(including some to Fortran 90):
+
+@smallexample
+SUBROUTINE X(A)
+CHARACTER*(*) A
+COMPLEX CFUNC
+INTEGER*2 CLOCKS(200)
+INTEGER IFUNC
+
+CALL SYSTEM_CLOCK (CLOCKS (IFUNC (CFUNC ('('//A//')'))))
+@end smallexample
+
+The above poses the following challenges to any Fortran compiler
+that uses run-time interfaces, and a run-time library, roughly similar
+to those used by @code{g77}:
+
+@itemize @bullet
+@item
+Assuming the library routine that supports @code{SYSTEM_CLOCK}
+expects to set an @code{INTEGER*4} variable via its @code{COUNT} argument,
+the compiler must make available to it a temporary variable of that type.
+
+@item
+Further, after the @code{SYSTEM_CLOCK} library routine returns,
+the compiler must ensure that the temporary variable it wrote
+is copied into the appropriate element of the @samp{CLOCKS} array.
+(This assumes the compiler doesn't just reject the code,
+which it should if it is compiling under some kind of a ``strict'' option.)
+
+@item
+To determine the correct index into the @samp{CLOCKS} array,
+(putting aside the fact that the index, in this particular case,
+need not be computed until after
+the @code{SYSTEM_CLOCK} library routine returns),
+the compiler must ensure that the @code{IFUNC} function is called.
+
+That requires evaluating its argument,
+which requires, for @code{g77}
+(assuming @code{-ff2c} is in force),
+reserving a temporary variable of type @code{COMPLEX}
+for use as a repository for the return value
+being computed by @samp{CFUNC}.
+
+@item
+Before invoking @samp{CFUNC},
+is argument must be evaluated,
+which requires allocating, at run time,
+a temporary large enough to hold the result of the concatenation,
+as well as actually performing the concatenation.
+
+@item
+The large temporary needed during invocation of @code{CFUNC}
+should, ideally, be deallocated
+(or, at least, left to the GBE to dispose of, as it sees fit)
+as soon as @code{CFUNC} returns,
+which means before @code{IFUNC} is called
+(as it might need a lot of dynamically allocated memory).
+@end itemize
+
+@code{g77} currently doesn't support all of the above,
+but, so that it might someday, it has evolved to handle
+at least some of the above requirements.
+
+Meeting the above requirements is made more challenging
+by conforming to the requirements of the GBEL/GBE combination.
+
+@node Transforming Statements
+@section Transforming Statements
+
+Most Fortran statements are given their own block,
+and, for temporary variables they might need, their own scope.
+(A block is what distinguishes @samp{@{ foo (); @}}
+from just @samp{foo ();} in C.
+A scope is included with every such block,
+providing a distinct name space for local variables.)
+
+Label definitions for the statement precede this block,
+so @samp{10 PRINT *, I} is handled more like
+@samp{fl10: @{ @dots{} @}} than @samp{@{ fl10: @dots{} @}}
+(where @samp{fl10} is just a notation meaning ``Fortran Label 10''
+for the purposes of this document).
+
+@menu
+* Statements Needing Temporaries::
+* Transforming DO WHILE::
+* Transforming Iterative DO::
+* Transforming Block IF::
+* Transforming SELECT CASE::
+@end menu
+
+@node Statements Needing Temporaries
+@subsection Statements Needing Temporaries
+
+Any temporaries needed during, but not beyond,
+execution of a Fortran statement,
+are made local to the scope of that statement's block.
+
+This allows the GBE to share storage for these temporaries
+among the various statements without the FFE
+having to manage that itself.
+
+(The GBE could, of course, decide to optimize
+management of these temporaries.
+For example, it could, theoretically,
+schedule some of the computations involving these temporaries
+to occur in parallel.
+More practically, it might leave the storage for some temporaries
+``live'' beyond their scopes, to reduce the number of
+manipulations of the stack pointer at run time.)
+
+Temporaries needed across distinct statement boundaries usually
+are associated with Fortran blocks (such as @code{DO}/@code{END DO}).
+(Also, there might be temporaries not associated with blocks at all---these
+would be in the scope of the entire program unit.)
+
+Each Fortran block @emph{should} get its own block/scope in the GBE.
+This is best, because it allows temporaries to be more naturally handled.
+However, it might pose problems when handling labels
+(in particular, when they're the targets of @code{GOTO}s outside the Fortran
+block), and generally just hassling with replicating
+parts of the @code{gcc} front end
+(because the FFE needs to support
+an arbitrary number of nested back-end blocks
+if each Fortran block gets one).
+
+So, there might still be a need for top-level temporaries, whose
+``owning'' scope is that of the containing procedure.
+
+Also, there seems to be problems declaring new variables after
+generating code (within a block) in the back end, leading to, e.g.,
+@samp{label not defined before binding contour} or similar messages,
+when compiling with @samp{-fstack-check} or
+when compiling for certain targets.
+
+Because of that, and because sometimes these temporaries are not
+discovered until in the middle of of generating code for an expression
+statement (as in the case of the optimization for @samp{X**I}),
+it seems best to always
+pre-scan all the expressions that'll be expanded for a block
+before generating any of the code for that block.
+
+This pre-scan then handles discovering and declaring, to the back end,
+the temporaries needed for that block.
+
+It's also important to treat distinct items in an I/O list as distinct
+statements deserving their own blocks.
+That's because there's a requirement
+that each I/O item be fully processed before the next one,
+which matters in cases like @samp{READ (*,*), I, A(I)}---the
+element of @samp{A} read in the second item
+@emph{must} be determined from the value
+of @samp{I} read in the first item.
+
+@node Transforming DO WHILE
+@subsection Transforming DO WHILE
+
+@samp{DO WHILE(expr)} @emph{must} be implemented
+so that temporaries needed to evaluate @samp{expr}
+are generated just for the test, each time.
+
+Consider how @samp{DO WHILE (A//B .NE. 'END'); @dots{}; END DO} is transformed:
+
+@smallexample
+for (;;)
+ @{
+ int temp0;
+
+ @{
+ char temp1[large];
+
+ libg77_catenate (temp1, a, b);
+ temp0 = libg77_ne (temp1, 'END');
+ @}
+
+ if (! temp0)
+ break;
+
+ @dots{}
+ @}
+@end smallexample
+
+In this case, it seems like a time/space tradeoff
+between allocating and deallocating @samp{temp1} for each iteration
+and allocating it just once for the entire loop.
+
+However, if @samp{temp1} is allocated just once for the entire loop,
+it could be the wrong size for subsequent iterations of that loop
+in cases like @samp{DO WHILE (A(I:J)//B .NE. 'END')},
+because the body of the loop might modify @samp{I} or @samp{J}.
+
+So, the above implementation is used,
+though a more optimal one can be used
+in specific circumstances.
+
+@node Transforming Iterative DO
+@subsection Transforming Iterative DO
+
+An iterative @code{DO} loop
+(one that specifies an iteration variable)
+is required by the Fortran standards
+to be implemented as though an iteration count
+is computed before entering the loop body,
+and that iteration count used to determine
+the number of times the loop body is to be performed
+(assuming the loop isn't cut short via @code{GOTO} or @code{EXIT}).
+
+The FFE handles this by allocating a temporary variable
+to contain the computed number of iterations.
+Since this variable must be in a scope that includes the entire loop,
+a GBEL block is created for that loop,
+and the variable declared as belonging to the scope of that block.
+
+@node Transforming Block IF
+@subsection Transforming Block IF
+
+Consider:
+
+@smallexample
+SUBROUTINE X(A,B,C)
+CHARACTER*(*) A, B, C
+LOGICAL LFUNC
+
+IF (LFUNC (A//B)) THEN
+ CALL SUBR1
+ELSE IF (LFUNC (A//C)) THEN
+ CALL SUBR2
+ELSE
+ CALL SUBR3
+END
+@end smallexample
+
+The arguments to the two calls to @samp{LFUNC}
+require dynamic allocation (at run time),
+but are not required during execution of the @code{CALL} statements.
+
+So, the scopes of those temporaries must be within blocks inside
+the block corresponding to the Fortran @code{IF} block.
+
+This cannot be represented ``naturally''
+in vanilla C, nor in GBEL.
+The @code{if}, @code{elseif}, @code{else},
+and @code{endif} constructs
+provided by both languages must,
+for a given @code{if} block,
+share the same C/GBE block.
+
+Therefore, any temporaries needed during evaluation of @samp{expr}
+while executing @samp{ELSE IF(expr)}
+must either have been predeclared
+at the top of the corresponding @code{IF} block,
+or declared within a new block for that @code{ELSE IF}---a block that,
+since it cannot contain the @code{else} or @code{else if} itself
+(due to the above requirement),
+actually implements the rest of the @code{IF} block's
+@code{ELSE IF} and @code{ELSE} statements
+within an inner block.
+
+The FFE takes the latter approach.
+
+@node Transforming SELECT CASE
+@subsection Transforming SELECT CASE
+
+@code{SELECT CASE} poses a few interesting problems for code generation,
+if efficiency and frugal stack management are important.
+
+Consider @samp{SELECT CASE (I('PREFIX'//A))},
+where @samp{A} is @code{CHARACTER*(*)}.
+In a case like this---basically,
+in any case where largish temporaries are needed
+to evaluate the expression---those temporaries should
+not be ``live'' during execution of any of the @code{CASE} blocks.
+
+So, evaluation of the expression is best done within its own block,
+which in turn is within the @code{SELECT CASE} block itself
+(which contains the code for the CASE blocks as well,
+though each within their own block).
+
+Otherwise, we'd have the rough equivalent of this pseudo-code:
+
+@smallexample
+@{
+ char temp[large];
+
+ libg77_catenate (temp, 'prefix', a);
+
+ switch (i (temp))
+ @{
+ case 0:
+ @dots{}
+ @}
+@}
+@end smallexample
+
+And that would leave temp[large] in scope during the CASE blocks
+(although a clever back end *could* see that it isn't referenced
+in them, and thus free that temp before executing the blocks).
+
+So this approach is used instead:
+
+@smallexample
+@{
+ int temp0;
+
+ @{
+ char temp1[large];
+
+ libg77_catenate (temp1, 'prefix', a);
+ temp0 = i (temp1);
+ @}
+
+ switch (temp0)
+ @{
+ case 0:
+ @dots{}
+ @}
+@}
+@end smallexample
+
+Note how @samp{temp1} goes out of scope before starting the switch,
+thus making it easy for a back end to free it.
+
+The problem @emph{that} solution has, however,
+is with @samp{SELECT CASE('prefix'//A)}
+(which is currently not supported).
+
+Unless the GBEL is extended to support arbitrarily long character strings
+in its @code{case} facility,
+the FFE has to implement @code{SELECT CASE} on @code{CHARACTER}
+(probably excepting @code{CHARACTER*1})
+using a cascade of
+@code{if}, @code{elseif}, @code{else}, and @code{endif} constructs
+in GBEL.
+
+To prevent the (potentially large) temporary,
+needed to hold the selected expression itself (@samp{'prefix'//A}),
+from being in scope during execution of the @code{CASE} blocks,
+two approaches are available:
+
+@itemize @bullet
+@item
+Pre-evaluate all the @code{CASE} tests,
+producing an integer ordinal that is used,
+a la @samp{temp0} in the earlier example,
+as if @samp{SELECT CASE(temp0)} had been written.
+
+Each corresponding @code{CASE} is replaced with @samp{CASE(@var{i})},
+where @var{i} is the ordinal for that case,
+determined while, or before,
+generating the cascade of @code{if}-related constructs
+to cope with @code{CHARACTER} selection.
+
+@item
+Make @samp{temp0} above just
+large enough to hold the longest @code{CASE} string
+that'll actually be compared against the expression
+(in this case, @samp{'prefix'//A}).
+
+Since that length must be constant
+(because @code{CASE} expressions are all constant),
+it won't be so large,
+and, further, @samp{temp1} need not be dynamically allocated,
+since normal @code{CHARACTER} assignment can be used
+into the fixed-length @samp{temp0}.
+@end itemize
+
+Both of these solutions require @code{SELECT CASE} implementation
+to be changed so all the corresponding @code{CASE} statements
+are seen during the actual code generation for @code{SELECT CASE}.
+
+@node Transforming Expressions
+@section Transforming Expressions
+
+The interactions between statements, expressions, and subexpressions
+at program run time can be viewed as:
+
+@smallexample
+@var{action}(@var{expr})
+@end smallexample
+
+Here, @var{action} is the series of steps
+performed to effect the statement,
+and @var{expr} is the expression
+whose value is used by @var{action}.
+
+Expanding the above shows a typical order of events at run time:
+
+@smallexample
+Evaluate @var{expr}
+Perform @var{action}, using result of evaluation of @var{expr}
+Clean up after evaluating @var{expr}
+@end smallexample
+
+So, if evaluating @var{expr} requires allocating memory,
+that memory can be freed before performing @var{action}
+only if it is not needed to hold the result of evaluating @var{expr}.
+Otherwise, it must be freed no sooner than
+after @var{action} has been performed.
+
+The above are recursive definitions,
+in the sense that they apply to subexpressions of @var{expr}.
+
+That is, evaluating @var{expr} involves
+evaluating all of its subexpressions,
+performing the @var{action} that computes the
+result value of @var{expr},
+then cleaning up after evaluating those subexpressions.
+
+The recursive nature of this evaluation is implemented
+via recursive-descent transformation of the top-level statements,
+their expressions, @emph{their} subexpressions, and so on.
+
+However, that recursive-descent transformation is,
+due to the nature of the GBEL,
+focused primarily on generating a @emph{single} stream of code
+to be executed at run time.
+
+Yet, from the above, it's clear that multiple streams of code
+must effectively be simultaneously generated
+during the recursive-descent analysis of statements.
+
+The primary stream implements the primary @var{action} items,
+while at least two other streams implement
+the evaluation and clean-up items.
+
+Requirements imposed by expressions include:
+
+@itemize @bullet
+@item
+Whether the caller needs to have a temporary ready
+to hold the value of the expression.
+
+@item
+Other stuff???
+@end itemize
+
+@node Internal Naming Conventions
+@section Internal Naming Conventions
+
+Names exported by FFE modules have the following (regular-expression) forms.
+Note that all names beginning @code{ffe@var{mod}} or @code{FFE@var{mod}},
+where @var{mod} is lowercase or uppercase alphanumerics, respectively,
+are exported by the module @code{ffe@var{mod}},
+with the source code doing the exporting in @file{@var{mod}.h}.
+(Usually, the source code for the implementation is in @file{@var{mod}.c}.)
+
+Identifiers that don't fit the following forms
+are not considered exported,
+even if they are according to the C language.
+(For example, they might be made available to other modules
+solely for use within expansions of exported macros,
+not for use within any source code in those other modules.)
+
+@table @code
+@item ffe@var{mod}
+The single typedef exported by the module.
+
+@item FFE@var{umod}_[A-Z][A-Z0-9_]*
+(Where @var{umod} is the uppercase for of @var{mod}.)
+
+A @code{#define} or @code{enum} constant of the type @code{ffe@var{mod}}.
+
+@item ffe@var{mod}[A-Z][A-Z][a-z0-9]*
+A typedef exported by the module.
+
+The portion of the identifier after @code{ffe@var{mod}} is
+referred to as @code{ctype}, a capitalized (mixed-case) form
+of @code{type}.
+
+@item FFE@var{umod}_@var{type}[A-Z][A-Z0-9_]*[A-Z0-9]?
+(Where @var{umod} is the uppercase for of @var{mod}.)
+
+A @code{#define} or @code{enum} constant of the type
+@code{ffe@var{mod}@var{type}},
+where @var{type} is the lowercase form of @var{ctype}
+in an exported typedef.
+
+@item ffe@var{mod}_@var{value}
+A function that does or returns something,
+as described by @var{value} (see below).
+
+@item ffe@var{mod}_@var{value}_@var{input}
+A function that does or returns something based
+primarily on the thing described by @var{input} (see below).
+@end table
+
+Below are names used for @var{value} and @var{input},
+along with their definitions.
+
+@table @code
+@item col
+A column number within a line (first column is number 1).
+
+@item file
+An encapsulation of a file's name.
+
+@item find
+Looks up an instance of some type that matches specified criteria,
+and returns that, even if it has to create a new instance or
+crash trying to find it (as appropriate).
+
+@item initialize
+Initializes, usually a module. No type.
+
+@item int
+A generic integer of type @code{int}.
+
+@item is
+A generic integer that contains a true (non-zero) or false (zero) value.
+
+@item len
+A generic integer that contains the length of something.
+
+@item line
+A line number within a source file,
+or a global line number.
+
+@item lookup
+Looks up an instance of some type that matches specified criteria,
+and returns that, or returns nil.
+
+@item name
+A @code{text} that points to a name of something.
+
+@item new
+Makes a new instance of the indicated type.
+Might return an existing one if appropriate---if so,
+similar to @code{find} without crashing.
+
+@item pt
+Pointer to a particular character (line, column pairs)
+in the input file (source code being compiled).
+
+@item run
+Performs some herculean task. No type.
+
+@item terminate
+Terminates, usually a module. No type.
+
+@item text
+A @code{char *} that points to generic text.
+@end table
diff --git a/contrib/gcc/f/fini.c b/contrib/gcc/f/fini.c
index 439ecca..1b7c981 100644
--- a/contrib/gcc/f/fini.c
+++ b/contrib/gcc/f/fini.c
@@ -1,6 +1,6 @@
/* fini.c
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -19,9 +19,12 @@ along with GNU Fortran; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+#define USE_HCONFIG
+
#include "proj.h"
#include "malloc.h"
+#undef MAXNAMELEN
#define MAXNAMELEN 100
typedef struct _name_ *name;
@@ -59,7 +62,7 @@ static FILE *out;
static char prefix[32];
static char postfix[32];
static char storage[32];
-static char *spaces[]
+static const char *xspaces[]
=
{
"", /* 0 */
@@ -633,7 +636,7 @@ testname (bool nested, int indent, name first, name last)
int numhalf;
assert (!nested || indent >= 2);
- assert (((size_t) indent) + 4 < ARRAY_SIZE (spaces));
+ assert (((size_t) indent) + 4 < ARRAY_SIZE (xspaces));
num = 0;
numhalf = 0;
@@ -651,15 +654,15 @@ testname (bool nested, int indent, name first, name last)
"\
%s{\n\
",
- spaces[indent - 2]);
+ xspaces[indent - 2]);
fprintf (out,
"\
%sif ((c = ffesrc_strcmp_2c (ffe_case_match (), p, \"%s\", \"%s\", \"%s\")) == 0)\n\
%sreturn %s%s%s;\n\
",
- spaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
- spaces[indent + 2], prefix, nhalf->kwname, postfix);
+ xspaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
+ xspaces[indent + 2], prefix, nhalf->kwname, postfix);
if (num != 1)
{
@@ -667,14 +670,14 @@ testname (bool nested, int indent, name first, name last)
"\
%selse if (c < 0)\n\
",
- spaces[indent]);
+ xspaces[indent]);
if (numhalf == 0)
fprintf (out,
"\
%s;\n\
",
- spaces[indent + 2]);
+ xspaces[indent + 2]);
else
testname (TRUE, indent + 4, first, nhalf->previous);
@@ -684,7 +687,7 @@ testname (bool nested, int indent, name first, name last)
"\
%selse\n\
",
- spaces[indent]);
+ xspaces[indent]);
testname (TRUE, indent + 4, nhalf->next, last);
}
@@ -695,7 +698,7 @@ testname (bool nested, int indent, name first, name last)
"\
%s}\n\
",
- spaces[indent - 2]);
+ xspaces[indent - 2]);
}
void
@@ -707,7 +710,7 @@ testnames (bool nested, int indent, int len, name first, name last)
int numhalf;
assert (!nested || indent >= 2);
- assert (((size_t) indent) + 4 < ARRAY_SIZE (spaces));
+ assert (((size_t) indent) + 4 < ARRAY_SIZE (xspaces));
num = 0;
numhalf = 0;
@@ -725,15 +728,15 @@ testnames (bool nested, int indent, int len, name first, name last)
"\
%s{\n\
",
- spaces[indent - 2]);
+ xspaces[indent - 2]);
fprintf (out,
"\
%sif ((c = ffesrc_strncmp_2c (ffe_case_match (), p, \"%s\", \"%s\", \"%s\", %d)) == 0)\n\
%sreturn %s%s%s;\n\
",
- spaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
- len, spaces[indent + 2], prefix, nhalf->kwname, postfix);
+ xspaces[indent], nhalf->name_uc, nhalf->name_lc, nhalf->name_ic,
+ len, xspaces[indent + 2], prefix, nhalf->kwname, postfix);
if (num != 1)
{
@@ -741,14 +744,14 @@ testnames (bool nested, int indent, int len, name first, name last)
"\
%selse if (c < 0)\n\
",
- spaces[indent]);
+ xspaces[indent]);
if (numhalf == 0)
fprintf (out,
"\
%s;\n\
",
- spaces[indent + 2]);
+ xspaces[indent + 2]);
else
testnames (TRUE, indent + 4, len, first, nhalf->previous);
@@ -758,7 +761,7 @@ testnames (bool nested, int indent, int len, name first, name last)
"\
%selse\n\
",
- spaces[indent]);
+ xspaces[indent]);
testnames (TRUE, indent + 4, len, nhalf->next, last);
}
@@ -769,5 +772,5 @@ testnames (bool nested, int indent, int len, name first, name last)
"\
%s}\n\
",
- spaces[indent - 2]);
+ xspaces[indent - 2]);
}
diff --git a/contrib/gcc/f/flags.j b/contrib/gcc/f/flags.j
index 02742d8..44587a4 100644
--- a/contrib/gcc/f/flags.j
+++ b/contrib/gcc/f/flags.j
@@ -1,6 +1,6 @@
/* flags.j -- Wrapper for GCC's flags.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/g77.1 b/contrib/gcc/f/g77.1
index d6a465b..3f20af9 100644
--- a/contrib/gcc/f/g77.1
+++ b/contrib/gcc/f/g77.1
@@ -1,7 +1,7 @@
.\" Copyright (c) 1995-1997 Free Software Foundation -*-Text-*-
.\" See section COPYING for conditions for redistribution
.\" FIXME: no info here on predefines. Should there be? extra for F77...
-.TH G77 1 "1998-09-01" "GNU Tools" "GNU Tools"
+.TH G77 1 "1999-02-14" "GNU Tools" "GNU Tools"
.de BP
.sp
.ti \-.2i
@@ -88,14 +88,18 @@ For complete documentation on GNU Fortran, type `\|\c
F77 source files use the suffix `\|\c
.B .f\c
-\&\|' or `\|\c
+\&\|', `\|\c
.B .for\c
+\&\|', or `\|\c
+.B .FOR\c
\&\|'; F77 files to be preprocessed by
.BR cpp ( 1 )
use the suffix `\|\c
.B .F\c
-\&\|' or `\|\c
+\&\|', `\|\c
.B .fpp\c
+\&\|', or `\|\c
+.B .FPP\c
\&\|'; Ratfor source files use the suffix `\|\c
.B .r\c
\&\|' (though
@@ -250,10 +254,14 @@ file.f Fortran source file
.br
file.for Fortran source file
.br
+file.FOR Fortran source file
+.br
file.F preprocessed Fortran source file
.br
file.fpp preprocessed Fortran source file
.br
+file.FPP preprocessed Fortran source file
+.br
file.r Ratfor source file (ratfor not included)
.br
file.s assembly language file
diff --git a/contrib/gcc/f/g77.texi b/contrib/gcc/f/g77.texi
index 48c36e9..eaab254 100644
--- a/contrib/gcc/f/g77.texi
+++ b/contrib/gcc/f/g77.texi
@@ -1,28 +1,15 @@
\input texinfo @c -*-texinfo-*-
-@c fix @set inside @example:
-@tex
-\gdef\set{\begingroup\catcode` =10 \parsearg\setxxx}
-\gdef\setyyy#1 #2\endsetyyy{%
- \def\temp{#2}%
- \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
- \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
- \fi
- \endgroup
-}
-@end tex
-
-@c %**start of header
+@c %**start of header
@setfilename g77.info
-@set last-up-date 1999-03-11
-@set version-g77 0.5.24
-@set version-egcs 1.1.2
-@set email-general egcs@@egcs.cygnus.com
-@set email-bugs egcs-bugs@@egcs.cygnus.com
-@set email-burley craig@@jcb-sc.com
-@set path-g77 egcs/gcc/f
-@set path-libf2c egcs/libf2c
-@set which-g77 @code{egcs}-@value{version-egcs}
+@set last-update 1999-06-06
+@set copyrights-g77 1995-1999
+
+@include root.texi
+
+@c This tells @include'd files that they're part of the overall G77 doc
+@c set. (They might be part of a higher-level doc set too.)
+@set DOC-G77
@c @setfilename useg77.info
@c @setfilename portg77.info
@@ -37,9 +24,13 @@
@c and make sure the following does NOT begin with '@c':
@c @clear USING
-@c (For FSF printing, turn on smallbook; that is all that is needed.)
+@c 6/27/96 FSF DO wants smallbook fmt for 1st bound edition. (from gcc.texi)
+@c @smallbook
-@c smallbook
+@c i also commented out the finalout command, so if there *are* any
+@c overfulls, you'll (hopefully) see the rectangle in the right hand
+@c margin. -- burley 1999-03-13 (from mew's comment in gcc.texi).
+@c @finalout
@ifset INTERNALS
@ifset USING
@@ -52,7 +43,7 @@
@end ifclear
@ifclear USING
@settitle Porting GNU Fortran
-@end ifclear
+@end ifclear
@c then again, have some fun
@ifclear INTERNALS
@ifclear USING
@@ -63,16 +54,48 @@
@syncodeindex fn cp
@syncodeindex vr cp
@c %**end of header
-@setchapternewpage odd
+
+@c Cause even numbered pages to be printed on the left hand side of
+@c the page and odd numbered pages to be printed on the right hand
+@c side of the page. Using this, you can print on both sides of a
+@c sheet of paper and have the text on the same part of the sheet.
+
+@c The text on right hand pages is pushed towards the right hand
+@c margin and the text on left hand pages is pushed toward the left
+@c hand margin.
+@c (To provide the reverse effect, set bindingoffset to -0.75in.)
+
+@c @tex
+@c \global\bindingoffset=0.75in
+@c \global\normaloffset =0.75in
+@c @end tex
@ifinfo
-This file explains how to use the GNU Fortran system.
+@dircategory Programming
+@direntry
+* g77: (g77). The GNU Fortran compiler.
+@end direntry
+@ifset INTERNALS
+@ifset USING
+This file documents the use and the internals of the GNU Fortran (@code{g77})
+compiler.
+It corresponds to the @value{which-g77} version of @code{g77}.
+@end ifset
+@end ifset
+@ifclear USING
+This file documents the internals of the GNU Fortran (@code{g77}) compiler.
+It corresponds to the @value{which-g77} version of @code{g77}.
+@end ifclear
+@ifclear INTERNALS
+This file documents the use of the GNU Fortran (@code{g77}) compiler.
+It corresponds to the @value{which-g77} version of @code{g77}.
+@end ifclear
Published by the Free Software Foundation
59 Temple Place - Suite 330
Boston, MA 02111-1307 USA
-Copyright (C) 1995-1997 Free Software Foundation, Inc.
+Copyright (C) @value{copyrights-g77} Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -106,23 +129,32 @@ Contributed by James Craig Burley (@email{@value{email-burley}}).
Inspired by a first pass at translating @file{g77-0.5.16/f/DOC} that
was contributed to Craig by David Ronis (@email{ronis@@onsager.chem.mcgill.ca}).
-@finalout
+@setchapternewpage odd
+@c @finalout
@titlepage
-@comment The title is printed in a large font.
-@center @titlefont{Using GNU Fortran}
+@ifset INTERNALS
+@ifset USING
+@center @titlefont{Using and Porting GNU Fortran}
+
+@end ifset
+@end ifset
+@ifclear INTERNALS
+@title Using GNU Fortran
+@end ifclear
+@ifclear USING
+@title Porting GNU Fortran
+@end ifclear
@sp 2
@center James Craig Burley
@sp 3
-@center Last updated @value{last-up-date}
+@center Last updated @value{last-update}
@sp 1
-@c The version number appears some more times in this file.
-
@center for version @value{version-g77}
@page
@vskip 0pt plus 1filll
-Copyright @copyright{} 1995-1997 Free Software Foundation, Inc.
+Copyright @copyright{} @value{copyrights-g77} Free Software Foundation, Inc.
@sp 2
-For GNU Fortran Version @value{version-g77}*
+For the @value{which-g77} Version*
@sp 1
Published by the Free Software Foundation @*
59 Temple Place - Suite 330@*
@@ -155,40 +187,50 @@ original English.
@ifinfo
-@dircategory Programming
-@direntry
-* g77: (g77). The GNU Fortran compiler.
-@end direntry
@node Top, Copying,, (DIR)
@top Introduction
@cindex Introduction
@ifset INTERNALS
@ifset USING
-This manual documents how to run, install and port the GNU Fortran
-compiler, as well as its new features and incompatibilities, and how to
-report bugs. It corresponds to GNU Fortran version @value{version-g77}.
+This manual documents how to run, install and port @code{g77},
+as well as its new features and incompatibilities,
+and how to report bugs.
+It corresponds to the @value{which-g77} version of @code{g77}.
@end ifset
@end ifset
@ifclear INTERNALS
-This manual documents how to run and install the GNU Fortran compiler,
+This manual documents how to run and install @code{g77},
as well as its new features and incompatibilities, and how to report
-bugs. It corresponds to GNU Fortran version @value{version-g77}.
+bugs.
+It corresponds to the @value{which-g77} version of @code{g77}.
@end ifclear
@ifclear USING
-This manual documents how to port the GNU Fortran compiler,
-as well as its new features and incompatibilities, and how to report
-bugs. It corresponds to GNU Fortran version @value{version-g77}.
+This manual documents how to port @code{g77},
+as well as its new features and incompatibilities,
+and how to report bugs.
+It corresponds to the @value{which-g77} version of @code{g77}.
@end ifclear
-An online, ``live'' version of this document
-(derived directly from the up-to-date mainline version
-of @code{g77} within @code{egcs})
-is available at
-@uref{http://egcs.cygnus.com/onlinedocs/g77_toc.html}.
-
@end ifinfo
+
+@ifset DEVELOPMENT
+@emph{Warning:} This document is still under development,
+and might not accurately reflect the @code{g77} code base
+of which it is a part.
+Efforts are made to keep it somewhat up-to-date,
+but they are particularly concentrated
+on any version of this information
+that is distributed as part of a @emph{released} @code{g77}.
+
+In particular, while this document is intended to apply to
+the @value{which-g77} version of @code{g77},
+only an official @emph{release} of that version
+is expected to contain documentation that is
+most consistent with the @code{g77} product in that version.
+@end ifset
+
@menu
* Copying:: GNU General Public License says
how you can copy and share GNU Fortran.
@@ -219,6 +261,7 @@ is available at
@ifset INTERNALS
* Adding Options:: Guidance on teaching @code{g77} about new options.
* Projects:: Projects for @code{g77} internals hackers.
+* Front End:: Design and implementation of the @code{g77} front end.
@end ifset
* M: Diagnostics. Diagnostics produced by @code{g77}.
@@ -567,9 +610,9 @@ the ``copyright'' line and a pointer to where the full notice is found.
@var{one line to give the program's name and a brief idea of what it does.}
Copyright (C) 19@var{yy} @var{name of author}
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -590,8 +633,8 @@ when it starts in an interactive mode:
@smallexample
Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
-type `show w'.
-This is free software, and you are welcome to redistribute it
+type `show w'.
+This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@end smallexample
@@ -786,6 +829,8 @@ without royalty; alteration is not permitted.
Work on GNU Fortran is still being done mostly by its author,
James Craig Burley (@email{@value{email-burley}}), who is a volunteer
for, not an employee of, the Free Software Foundation (FSF).
+(He has a web page at @uref{@value{www-burley}}.)
+
As with other GNU software, funding is important because it can pay for
needed equipment, personnel, and so on.
@@ -810,7 +855,7 @@ continuing operation of the FSF offices, their workstations, their
network connections, and so on, which are invaluable to volunteers.
(Similarly, hiring Cygnus Support can help a project like GNU
Fortran---Cygnus has been a long-time donor of equipment usage to the author
-of GNU Fortran, and this too has been invaluable---@xref{Contributors}.)
+of GNU Fortran, and this too has been invaluable---see @ref{Contributors}.)
Currently, the only way to directly fund the author of GNU Fortran
in his work on that project is to hire him for the work you want
@@ -838,7 +883,7 @@ Email @email{@value{email-general}} to volunteer for this work.
@node Look and Feel
@chapter Protect Your Freedom---Fight ``Look And Feel''
-@c the above chapter heading overflows onto the next line. --mew 1/26/93
+@c the above chapter heading overflows onto the next line. --mew 1/26/93
To preserve the ability to write free software, including replacements
for proprietary software, authors must be free to replicate the
@@ -872,7 +917,7 @@ Everyone except experienced @code{g77} users should
see @ref{Invoking G77}.
If you're acquainted with previous versions of @code{g77},
-you should see @ref{News}.
+you should see @ref{News,,News About GNU Fortran}.
Further, if you've actually used previous versions of @code{g77},
especially if you've written or modified Fortran code to
be compiled by previous versions of @code{g77}, you
@@ -966,8 +1011,8 @@ to make big mistakes.
@cindex debugger
@cindex bugs, finding
-@cindex gdb command
-@cindex commands, gdb
+@cindex @code{gdb}, command
+@cindex commands, @code{gdb}
@item
They provide information in the generated machine code
that can make it easier to find bugs in the program
@@ -976,8 +1021,8 @@ such as @code{gdb}).
@cindex libraries
@cindex linking
-@cindex ld command
-@cindex commands, ld
+@cindex @code{ld} command
+@cindex commands, @code{ld}
@item
They locate and gather machine code already generated
to perform actions requested by statements in
@@ -1036,11 +1081,11 @@ of the language), how much time to spend making
the generated machine code run faster, and so on.
@cindex components of g77
-@cindex g77, components of
+@cindex @code{g77}, components of
@code{g77} consists of several components:
-@cindex gcc command
-@cindex commands, gcc
+@cindex @code{gcc}, command
+@cindex commands, @code{gcc}
@itemize @bullet
@item
A modified version of the @code{gcc} command, which also might be
@@ -1051,8 +1096,8 @@ might be a non-GNU compiler, or an older version
of @code{gcc} considered more stable or that is
used to build the operating system kernel.)
-@cindex g77 command
-@cindex commands, g77
+@cindex @code{g77}, command
+@cindex commands, @code{g77}
@item
The @code{g77} command itself, which also might be installed as the
system's @code{f77} command.
@@ -1061,7 +1106,7 @@ system's @code{f77} command.
@cindex libf2c library
@cindex libraries, libf2c
@cindex libraries, libg2c
-@cindex run-time library
+@cindex run-time, library
@item
The @code{libg2c} run-time library.
This library contains the machine code needed to support
@@ -1079,11 +1124,11 @@ on the system.
The maintainer of @code{libf2c} currently is
@email{dmg@@bell-labs.com}.
-@cindex f771 program
-@cindex programs, f771
+@cindex @code{f771}, program
+@cindex programs, @code{f771}
@cindex assembler
-@cindex as command
-@cindex commands, as
+@cindex @code{as} command
+@cindex commands, @code{as}
@cindex assembly code
@cindex code, assembly
@item
@@ -1103,7 +1148,7 @@ preprocessing, compiling (in a variety of possible languages), assembling,
and linking.
@cindex driver, gcc command as
-@cindex gcc command as driver
+@cindex @code{gcc}, command as driver
@cindex executable file
@cindex files, executable
@cindex cc1 program
@@ -1124,14 +1169,14 @@ As another example, the command @samp{gcc foo.cc} would do much the same as
@samp{gcc foo.c}, but instead of using the C compiler named @code{cc1},
@code{gcc} would use the C++ compiler (named @code{cc1plus}).
-@cindex f771 program
-@cindex programs, f771
+@cindex @code{f771}, program
+@cindex programs, @code{f771}
In a GNU Fortran installation, @code{gcc} recognizes Fortran source
files by name just like it does C and C++ source files.
It knows to use the Fortran compiler named @code{f771}, instead of
@code{cc1} or @code{cc1plus}, to compile Fortran files.
-@cindex gcc not recognizing Fortran source
+@cindex @code{gcc}, not recognizing Fortran source
@cindex unrecognized file format
@cindex file format not recognized
Non-Fortran-related operation of @code{gcc} is generally
@@ -1141,8 +1186,8 @@ GNU Fortran version, @code{gcc} will not be able to compile
and link Fortran programs---and since @code{g77} uses @code{gcc}
to do most of the actual work, neither will @code{g77}!
-@cindex g77 command
-@cindex commands, g77
+@cindex @code{g77}, command
+@cindex commands, @code{g77}
The @code{g77} command is essentially just a front-end for
the @code{gcc} command.
Fortran users will normally use @code{g77} instead of @code{gcc},
@@ -1201,7 +1246,7 @@ large chunks of code.
@cindex GNU Back End (GBE)
@cindex GBE
-@cindex gcc back end
+@cindex @code{gcc}, back end
@cindex back end, gcc
@cindex code generator
One chunk is the so-called @dfn{GNU Back End}, or GBE,
@@ -1214,8 +1259,8 @@ whenever the distinction is important.
@cindex GNU Fortran Front End (FFE)
@cindex FFE
-@cindex g77 front end
-@cindex front end, g77
+@cindex @code{g77}, front end
+@cindex front end, @code{g77}
The other chunk of @code{f771} is the
majority of what is unique about GNU Fortran---the code that knows how
to interpret Fortran programs to determine what they are intending to
@@ -1245,8 +1290,8 @@ of generated code (in terms of speed and size) is roughly similar
@cindex compiling programs
@cindex programs, compiling
-@cindex gcc command
-@cindex commands, gcc
+@cindex @code{gcc}, command
+@cindex commands, @code{gcc}
A GNU Fortran installation includes a modified version of the @code{gcc}
command.
@@ -1262,8 +1307,8 @@ but apply to other languages as well.
for information on the way different languages are handled
by the GNU CC compiler (@code{gcc}).
-@cindex g77 command
-@cindex commands, g77
+@cindex @code{g77}, command
+@cindex commands, @code{g77}
Also provided as part of GNU Fortran is the @code{g77} command.
The @code{g77} command is designed to make compiling and linking Fortran
programs somewhat easier than when using the @code{gcc} command for
@@ -1272,7 +1317,7 @@ It does this by analyzing the command line somewhat and changing it
appropriately before submitting it to the @code{gcc} command.
@cindex -v option
-@cindex g77 options, -v
+@cindex @code{g77} options, -v
@cindex options, -v
Use the @samp{-v} option with @code{g77}
to see what is going on---the first line of output is the invocation
@@ -1343,7 +1388,7 @@ by type. Explanations are in the following sections.
@item Shorthand Options
@xref{Shorthand Options}.
@smallexample
--ff66 -fno-f66 -ff77 -fno-f77 -fugly -fno-ugly
+-ff66 -fno-f66 -ff77 -fno-f77 -fno-ugly
@end smallexample
@item Fortran Language Options
@@ -1422,10 +1467,11 @@ by type. Explanations are in the following sections.
-fpcc-struct-return -freg-struct-return
-fshort-double -fno-common -fpack-struct
-fzeros -fno-second-underscore
--fdebug-kludge -fno-emulate-complex
+-fdebug-kludge -femulate-complex
-falias-check -fargument-alias
-fargument-noalias -fno-argument-noalias-global
--fno-globals
+-fno-globals -fflatten-arrays
+-fbounds-check -ffortran-bounds-check
@end smallexample
@end table
@@ -1473,15 +1519,20 @@ Suffixes specific to GNU Fortran are listed below.
information on suffixes recognized by GNU CC.
@table @code
+@cindex .f filename suffix
+@cindex .for filename suffix
+@cindex .FOR filename suffix
@item @var{file}.f
@item @var{file}.for
+@item @var{file}.FOR
Fortran source code that should not be preprocessed.
Such source code cannot contain any preprocessor directives, such
as @code{#include}, @code{#define}, @code{#if}, and so on.
-You can force @samp{.f} files to be preprocessed by @samp{cpp} by using
-@samp{-x f77-cpp-input}, @ref{LEX}.
+You can force @samp{.f} files to be preprocessed by @code{cpp} by using
+@samp{-x f77-cpp-input}.
+@xref{LEX}.
@cindex preprocessor
@cindex C preprocessor
@@ -1491,8 +1542,10 @@ You can force @samp{.f} files to be preprocessed by @samp{cpp} by using
@cindex programs, cpp
@cindex .F filename suffix
@cindex .fpp filename suffix
+@cindex .FPP filename suffix
@item @var{file}.F
@item @var{file}.fpp
+@item @var{file}.FPP
Fortran source code that must be preprocessed (by the C preprocessor
@code{cpp}, which is part of GNU CC).
@@ -1501,9 +1554,9 @@ files included by the @code{INCLUDE} directive---the @code{#include}
preprocessor directive must be used instead.
@cindex Ratfor preprocessor
-@cindex programs, ratfor
-@cindex .r filename suffix
-@pindex ratfor
+@cindex programs, @code{ratfor}
+@cindex @samp{.r} filename suffix
+@cindex @code{ratfor}
@item @var{file}.r
Ratfor source code, which must be preprocessed by the @code{ratfor}
command, which is available separately (as it is not yet part of the GNU
@@ -1584,12 +1637,18 @@ by the @code{g77} and @code{gcc} commands in a GNU Fortran installation:
@cindex options, -fversion
@cindex printing version information
@cindex version information, printing
+@cindex consistency checks
+@cindex internal consistency checks
+@cindex checks, of internal consistency
@item -fversion
Ensure that the @code{g77}-specific version of the compiler phase is reported,
-if run.
-(This is supplied automatically when @samp{-v} or @samp{--verbose}
+if run,
+and, starting in @code{egcs} version 1.1,
+that internal consistency checks in the @file{f771} program are run.
+
+This option is supplied automatically when @samp{-v} or @samp{--verbose}
is specified as a command-line option for @code{g77} or @code{gcc}
-and when the resulting commands compile Fortran source files.)
+and when the resulting commands compile Fortran source files.
@cindex -fset-g77-defaults option
@cindex options, -fset-g77-defaults
@@ -1597,7 +1656,13 @@ and when the resulting commands compile Fortran source files.)
@emph{Version info:}
This option is obsolete in @code{egcs}
as of version 1.1.
+The effect is instead achieved
+by the @code{lang_init_options} routine
+in @file{egcs/gcc/f/com.c}.
+@cindex consistency checks
+@cindex internal consistency checks
+@cindex checks, of internal consistency
Set up whatever @code{gcc} options are to apply to Fortran
compilations, and avoid running internal consistency checks
that might take some time.
@@ -1623,10 +1688,10 @@ with a diagnostic if it detects an inconsistency.
@cindex -fno-silent option
@cindex options, -fno-silent
-@cindex @code{f2c} compatibility
-@cindex compatibility, @code{f2c}
+@cindex f2c compatibility
+@cindex compatibility, f2c
@cindex status, compilation
-@cindex compilation status
+@cindex compilation, status
@cindex reporting compilation status
@cindex printing compilation status
@item -fno-silent
@@ -1656,6 +1721,10 @@ for other options accepted by the compiler:
@item -fugly
@cindex ugly features
@cindex features, ugly
+@emph{Note:} This option is no longer supported.
+The information, below, is provided to aid
+in the conversion of old scripts.
+
Specify that certain ``ugly'' constructs are to be quietly accepted.
Same as:
@@ -1670,14 +1739,6 @@ or well-maintained portable Fortran code, but widely used
in old code.
@xref{Distensions}, for more information.
-@emph{Note:} The @samp{-fugly} option is likely to
-be removed in a future version.
-Implicitly enabling all the @samp{-fugly-*} options
-is unlikely to be feasible, or sensible, in the future,
-so users should learn to specify only those
-@samp{-fugly-*} options they really need for a
-particular source file.
-
@cindex -fno-ugly option
@cindex options, -fno-ugly
@item -fno-ugly
@@ -1713,10 +1774,10 @@ existing and obsolete Fortran implementations.
@cindex options, -ff77
@item -ff77
@cindex UNIX f77
-@cindex @code{f2c} compatibility
-@cindex compatibility, @code{f2c}
-@cindex @code{f77} compatibility
-@cindex compatibility, @code{f77}
+@cindex f2c compatibility
+@cindex compatibility, f2c
+@cindex f77 compatibility
+@cindex compatibility, f77
Specify that the program is written in idiomatic UNIX FORTRAN 77
and/or the dialect accepted by the @code{f2c} product.
Same as @samp{-fbackslash -fno-typeless-boz}.
@@ -1743,7 +1804,7 @@ existing and obsolete Fortran implementations.
@node Fortran Dialect Options
@section Options Controlling Fortran Dialect
@cindex dialect options
-@cindex language dialect options
+@cindex language, dialect options
@cindex options, dialect
The following options control the dialect of Fortran
@@ -1754,10 +1815,10 @@ that the compiler accepts:
@cindex options, -ffree-form
@cindex -fno-fixed-form option
@cindex options, -fno-fixed-form
-@cindex source file form
+@cindex source file format
@cindex free form
@cindex fixed form
-@cindex Fortran 90 features
+@cindex Fortran 90, features
@item -ffree-form
@item -fno-fixed-form
Specify that the source file is written in free form
@@ -1765,7 +1826,7 @@ Specify that the source file is written in free form
@cindex -ff90 option
@cindex options, -ff90
-@cindex Fortran 90 features
+@cindex Fortran 90, features
@item -ff90
Allow certain Fortran-90 constructs.
@@ -1781,8 +1842,8 @@ current level of support for Fortran 90.)
@cindex -fvxt option
@cindex options, -fvxt
@item -fvxt
-@cindex Fortran 90 features
-@cindex VXT features
+@cindex Fortran 90, features
+@cindex VXT extensions
Specify the treatment of certain constructs that have different
meanings depending on whether the code is written in
GNU Fortran (based on FORTRAN 77 and akin to Fortran 90)
@@ -1922,14 +1983,16 @@ For example, automatic conversion between @code{INTEGER} and
@cindex options, -fonetrip
@item -fonetrip
@cindex FORTRAN 66
-@cindex DO loops, one-trip
-@cindex one-trip DO loops
+@cindex @code{DO} loops, one-trip
+@cindex one-trip @code{DO} loops
+@cindex @code{DO} loops, zero-trip
+@cindex zero-trip @code{DO} loops
@cindex compatibility, FORTRAN 66
-Imperative executable @code{DO} loops are to be executed at
+Executable iterative @code{DO} loops are to be executed at
least once each time they are reached.
ANSI FORTRAN 77 and more recent versions of the Fortran standard
-specify that the body of an imperative @code{DO} loop is not executed
+specify that the body of an iterative @code{DO} loop is not executed
if the number of iterations calculated from the parameters of the
loop is less than 1.
(For example, @samp{DO 10 I = 1, 0}.)
@@ -1947,7 +2010,7 @@ standard did not specify this behavior.
The @samp{-fonetrip} option specifies that the source file(s) being
compiled require one-trip loops.
-This option affects only those loops specified by the (imperative) @code{DO}
+This option affects only those loops specified by the (iterative) @code{DO}
statement and by implied-@code{DO} lists in I/O statements.
Loops specified by implied-@code{DO} lists in @code{DATA} and
specification (non-executable) statements are not affected.
@@ -2096,8 +2159,8 @@ variables named @samp{i} and @samp{I} to a procedure named @samp{Foo}.)
@cindex -fbadu77-intrinsics-enable option
@cindex options, -fbadu77-intrinsics-enable
@item -fbadu77-intrinsics-enable
-@cindex badu77 intrinsics
-@cindex intrinsics, badu77
+@cindex @code{badu77} intrinsics
+@cindex intrinsics, @code{badu77}
Specify status of UNIX intrinsics having inappropriate forms.
@samp{-fbadu77-intrinsics-enable} is the default.
@xref{Intrinsic Groups}.
@@ -2114,8 +2177,8 @@ Specify status of UNIX intrinsics having inappropriate forms.
@cindex -ff2c-intrinsics-enable option
@cindex options, -ff2c-intrinsics-enable
@item -ff2c-intrinsics-enable
-@cindex f2c intrinsics
-@cindex intrinsics, f2c
+@cindex @code{f2c} intrinsics
+@cindex intrinsics, @code{f2c}
Specify status of f2c-specific intrinsics.
@samp{-ff2c-intrinsics-enable} is the default.
@xref{Intrinsic Groups}.
@@ -2132,7 +2195,7 @@ Specify status of f2c-specific intrinsics.
@cindex -ff90-intrinsics-enable option
@cindex options, -ff90-intrinsics-enable
@item -ff90-intrinsics-enable
-@cindex Fortran 90 intrinsics
+@cindex Fortran 90, intrinsics
@cindex intrinsics, Fortran 90
Specify status of F90-specific intrinsics.
@samp{-ff90-intrinsics-enable} is the default.
@@ -2151,8 +2214,8 @@ Specify status of F90-specific intrinsics.
@cindex options, -fgnu-intrinsics-enable
@item -fgnu-intrinsics-enable
@cindex Digital Fortran features
-@cindex COMPLEX intrinsics
-@cindex intrinsics, COMPLEX
+@cindex @code{COMPLEX} intrinsics
+@cindex intrinsics, @code{COMPLEX}
Specify status of Digital's COMPLEX-related intrinsics.
@samp{-fgnu-intrinsics-enable} is the default.
@xref{Intrinsic Groups}.
@@ -2215,9 +2278,10 @@ Specify status of VXT intrinsics.
@cindex options, -ffixed-line-length-@var{n}
@item -ffixed-line-length-@var{n}
@cindex source file format
-@cindex line length
+@cindex lines, length
@cindex length of source lines
-@cindex fixed-form line length
+@cindex fixed form
+@cindex limits, lengths of source lines
Set column after which characters are ignored in typical fixed-form
lines in the source file, and through which spaces are assumed (as
if padded to that length) after the ends of short fixed-form lines.
@@ -2238,8 +2302,8 @@ to them to fill out the line.
@node Warning Options
@section Options to Request or Suppress Warnings
-@cindex options to control warnings
-@cindex warning messages
+@cindex options, warnings
+@cindex warnings, suppressing
@cindex messages, warning
@cindex suppressing warnings
@@ -2413,12 +2477,12 @@ use, on occasion, in clean programs.
@table @code
@c @item -W
@c Print extra warning messages for these events:
-@c
+@c
@c @itemize @bullet
@c @item
@c If @samp{-Wall} or @samp{-Wunused} is also specified, warn about unused
@c arguments.
-@c
+@c
@c @end itemize
@c
@cindex -Wsurprising option
@@ -2650,11 +2714,7 @@ and data sets.
this option does not apply, generally speaking, to Fortran
code compiled by @code{g77}.
-@emph{Also note:} @samp{-malign-double} applies only to
-statically-allocated data.
-Double-precision data on the stack can still
-cause problems due to misalignment.
-@xref{Aligned Data}.
+@xref{Aligned Data}, for more information on alignment issues.
@emph{Also also note:} The negative form of @samp{-malign-double}
is @samp{-mno-align-double}, not @samp{-benign-double}.
@@ -2662,16 +2722,16 @@ is @samp{-mno-align-double}, not @samp{-benign-double}.
@cindex -ffloat-store option
@cindex options, -ffloat-store
@item -ffloat-store
-@cindex IEEE conformance
-@cindex conformance, IEEE
-@cindex floating point precision
+@cindex IEEE 754 conformance
+@cindex conformance, IEEE 754
+@cindex floating-point, precision
Might help a Fortran program that depends on exact IEEE conformance on
some machines, but might slow down a program that doesn't.
-This option is effective when the floating point unit is set to work in
+This option is effective when the floating-point unit is set to work in
IEEE 854 `extended precision'---as it typically is on x86 and m68k GNU
-systems---rather than IEEE 754 double precision. @code{-ffloat-store}
-tries to remove the extra precision by spilling data from floating point
+systems---rather than IEEE 754 double precision. @samp{-ffloat-store}
+tries to remove the extra precision by spilling data from floating-point
registers into memory and this typically involves a big performance
hit. However, it doesn't affect intermediate results, so that it is
only partially effective. `Excess precision' is avoided in code like:
@@ -2684,8 +2744,8 @@ but not in code like:
d = (b + c) * e
@end smallexample
-For another, potentially better, way of controlling the precision
-@ref{Floating point precision}.
+For another, potentially better, way of controlling the precision,
+see @ref{Floating-point precision}.
@cindex -fforce-mem option
@cindex options, -fforce-mem
@@ -2694,13 +2754,13 @@ For another, potentially better, way of controlling the precision
@cindex options, -fforce-addr
@item -fforce-addr
@cindex loops, speeding up
-@cindex speeding up loops
+@cindex speed, of loops
Might improve optimization of loops.
@cindex -fno-inline option
@cindex options, -fno-inline
@item -fno-inline
-@cindex in-line compilation
+@cindex in-line code
@cindex compilation, in-line
@c DL: Only relevant for -O3?
Don't compile statement functions inline.
@@ -2711,8 +2771,8 @@ Note that if you are not optimizing, no functions can be expanded inline.
@cindex -ffast-math option
@cindex options, -ffast-math
@item -ffast-math
-@cindex IEEE conformance
-@cindex conformance, IEEE
+@cindex IEEE 754 conformance
+@cindex conformance, IEEE 754
Might allow some programs designed to not be too dependent
on IEEE behavior for floating-point to run faster, or die trying.
@@ -2720,7 +2780,7 @@ on IEEE behavior for floating-point to run faster, or die trying.
@cindex options, -fstrength-reduce
@item -fstrength-reduce
@cindex loops, speeding up
-@cindex speeding up loops
+@cindex speed, of loops
@c DL: normally defaulted?
Might make some loops run faster.
@@ -2750,14 +2810,19 @@ Might improve performance on some code.
@item -funroll-loops
@cindex loops, unrolling
@cindex unrolling loops
-@cindex loop optimization
+@cindex loops, optimizing
+@cindex indexed (iterative) @code{DO}
+@cindex iterative @code{DO}
@c DL: fixme: Craig doesn't like `indexed' but f95 doesn't seem to
@c provide a suitable term
-Typically improves performance on code using indexed @code{DO} loops by
+@c CB: I've decided on `iterative', for the time being, and changed
+@c my previous, rather bizarre, use of `imperative' to that
+@c (though `precomputed-trip' would be a more precise adjective)
+Typically improves performance on code using iterative @code{DO} loops by
unrolling them and is probably generally appropriate for Fortran, though
-it is not turned on at any optimization level.
+it is not turned on at any optimization level.
Note that outer loop unrolling isn't done specifically; decisions about
-whether to unroll a loop are made on the basis of its instruction count.
+whether to unroll a loop are made on the basis of its instruction count.
@c DL: Fixme: This should obviously go somewhere else...
Also, no `loop discovery'@footnote{@dfn{loop discovery} refers to the
@@ -2773,18 +2838,18 @@ constructed out of lower-level constructs (such as @code{IF} and
@code{GOTO}) can lead to generation of more optimal code
than otherwise.} is done, so only loops written with @code{DO}
benefit from loop optimizations, including---but not limited
-to---unrolling. Loops written with @code{IF} and @code{GOTO} will not
-be recognized as such. This option only unrolls indexed @code{DO}
-loops, not @code{DO WHILE} loops.
+to---unrolling. Loops written with @code{IF} and @code{GOTO} are not
+currently recognized as such. This option unrolls only iterative
+@code{DO} loops, not @code{DO WHILE} loops.
@cindex -funroll-all-loops option
@cindex options, -funroll-all-loops
-@cindex @code{DO WHILE}
+@cindex DO WHILE
@item -funroll-all-loops
@c DL: Check my understanding of -funroll-all-loops v. -funroll-loops is correct.
Probably improves performance on code using @code{DO WHILE} loops by
-unrolling them in addition to indexed @code{DO} loops. In the absence
-of @code{DO WHILE}, this option is equivalent to @code{-funroll-loops}
+unrolling them in addition to iterative @code{DO} loops. In the absence
+of @code{DO WHILE}, this option is equivalent to @samp{-funroll-loops}
but possibly slower.
@item -fno-move-all-movables
@@ -2857,7 +2922,7 @@ contains preprocessor directives.
@node Directory Options
@section Options for Directory Search
-@cindex directory options
+@cindex directory, options
@cindex options, directory search
@cindex search path
@@ -2881,9 +2946,10 @@ These options are:
@cindex -Idir option
@cindex options, -Idir
@item -I@var{dir}
-@cindex directory search paths for inclusion
+@cindex directory, search paths for inclusion
@cindex inclusion, directory search paths for
-@cindex searching for included files
+@cindex search paths, for included files
+@cindex paths, search
These affect interpretation of the @code{INCLUDE} directive
(as well as of the @code{#include} directive of the @code{cpp}
preprocessor).
@@ -2905,9 +2971,9 @@ gcc,Using and Porting GNU CC}, for information on the @samp{-I} option.
@node Code Gen Options
@section Options for Code Generation Conventions
-@cindex code generation conventions
-@cindex options, code generation
-@cindex run-time options
+@cindex code generation, conventions
+@cindex options, code generation
+@cindex run-time, options
These machine-independent options control the interface conventions
used in code generation.
@@ -2935,7 +3001,7 @@ the name @samp{-static}.)
@item -finit-local-zero
@cindex DATA statement
@cindex statements, DATA
-@cindex initialization of local variables
+@cindex initialization, of local variables
@cindex variables, initialization of
@cindex uninitialized variables
@cindex variables, uninitialized
@@ -3009,7 +3075,7 @@ generating code for an incompatible library.
@cindex -fno-underscoring option
@cindex options, -fno-underscoring
@item -fno-underscoring
-@cindex underscores
+@cindex underscore
@cindex symbol names, underscores
@cindex transforming symbol names
@cindex symbol names, transforming
@@ -3084,7 +3150,7 @@ interfaces.
@cindex -fno-second-underscore option
@cindex options, -fno-second-underscore
@item -fno-second-underscore
-@cindex underscores
+@cindex underscore
@cindex symbol names, underscores
@cindex transforming symbol names
@cindex symbol names, transforming
@@ -3184,7 +3250,7 @@ $6 = "At (EQUIVALENCE) `__g77_equiv_xx' plus 20 bytes"
(gdb) p xx
$7 = "At (EQUIVALENCE) `__g77_equiv_xx' plus 1 bytes"
(gdb) set language fortran
-(gdb)
+(gdb)
@end smallexample
@noindent
@@ -3197,44 +3263,36 @@ Current plans call for this to happen when published versions of @code{g77}
and @code{gdb} exist that provide proper access to debugging information on
@code{COMMON} and @code{EQUIVALENCE} members.
-@cindex -fno-emulate-complex option
-@cindex options, -fno-emulate-complex
-@item -fno-emulate-complex
-Implement @code{COMPLEX} arithmetic using the facilities in
+@cindex -femulate-complex option
+@cindex options, -femulate-complex
+@item -femulate-complex
+Implement @code{COMPLEX} arithmetic via emulation,
+instead of using the facilities of
the @code{gcc} back end that provide direct support of
-@code{complex} arithmetic, instead of emulating the arithmetic.
+@code{complex} arithmetic.
-@code{gcc} has some known problems in its back-end support
+(@code{gcc} had some bugs in its back-end support
for @code{complex} arithmetic, due primarily to the support not being
-completed as of version 2.7.2.2.
-Other front ends for the @code{gcc} back end avoid this problem
-by emulating @code{complex} arithmetic at a higher level, so the
-back end sees arithmetic on the real and imaginary components.
-To make @code{g77} more portable to systems where @code{complex}
-support in the @code{gcc} back end is particularly troublesome,
-@code{g77} now defaults to performing the same kinds of emulations
-done by these other front ends.
-
-Use @samp{-fno-emulate-complex} to try the @code{complex} support
-in the @code{gcc} back end, in case it works and produces faster
-programs.
-So far, all the known bugs seem to involve compile-time crashes,
-rather than the generation of incorrect code.
+completed as of version 2.8.1 and @code{egcs} 1.1.2.)
+
+Use @samp{-femulate-complex} if you suspect code-generation bugs,
+or experience compiler crashes,
+that might result from @code{g77} using the @code{COMPLEX} support
+in the @code{gcc} back end.
+If using that option fixes the bugs or crashes you are seeing,
+that indicates a likely @code{g77} bugs
+(though, all compiler crashes are considered bugs),
+so, please report it.
+(Note that the known bugs, now believed fixed, produced compiler crashes
+rather than causing the generation of incorrect code.)
Use of this option should not affect how Fortran code compiled
by @code{g77} works in terms of its interfaces to other code,
e.g. that compiled by @code{f2c}.
-@emph{Caution:} Future versions of @code{g77} are likely to change
-the default for this option to
-@samp{-fno-emulate-complex}, and perhaps someday ignore both forms
+@emph{Caution:} Future versions of @code{g77} might ignore both forms
of this option.
-Also, it is possible that use of the @samp{-fno-emulate-complex} option
-could result in incorrect code being silently produced by @code{g77}.
-But, this is generally true of compilers anyway, so, as usual, test
-the programs you compile before assuming they are working.
-
@cindex -falias-check option
@cindex options, -falias-check
@cindex -fargument-alias option
@@ -3275,6 +3333,8 @@ arguments.
@item -fno-globals
@cindex global names, warning
@cindex warnings, global names
+@cindex in-line code
+@cindex compilation, in-line
Disable diagnostics about inter-procedural
analysis problems, such as disagreements about the
type of a function or a procedure's argument,
@@ -3291,9 +3351,8 @@ code that would otherwise be diagnosed.
As such, this option might be quite useful when
compiling existing, ``working'' code that happens
-to have a few bugs that do not generally show
-themselves, but @code{g77} exposes via a
-diagnostic.
+to have a few bugs that do not generally show themselves,
+but which @code{g77} diagnoses.
Use of this option therefore has the effect of
instructing @code{g77} to behave more like it did
@@ -3307,7 +3366,92 @@ Without this option, @code{g77} defaults to performing
the potentially inlining procedures as it started doing
in version 0.5.20, but as of version 0.5.21, it also
diagnoses disagreements that might cause such inlining
-to crash the compiler.
+to crash the compiler as (fatal) errors,
+and warns about similar disagreements
+that are currently believed to not
+likely to result in the compiler later crashing
+or producing incorrect code.
+
+@cindex -fflatten-arrays option
+@item -fflatten-arrays
+@cindex array performance
+@cindex arrays, flattening
+Use back end's C-like constructs
+(pointer plus offset)
+instead of its @code{ARRAY_REF} construct
+to handle all array references.
+
+@emph{Note:} This option is not supported.
+It is intended for use only by @code{g77} developers,
+to evaluate code-generation issues.
+It might be removed at any time.
+
+@cindex -fbounds-check option
+@cindex -ffortran-bounds-check option
+@item -fbounds-check
+@itemx -ffortran-bounds-check
+@cindex bounds checking
+@cindex range checking
+@cindex array bounds checking
+@cindex subscript checking
+@cindex substring checking
+@cindex checking subscripts
+@cindex checking substrings
+Enable generation of run-time checks for array subscripts
+and substring start and end points
+against the (locally) declared minimum and maximum values.
+
+The current implementation uses the @code{libf2c}
+library routine @code{s_rnge} to print the diagnostic.
+
+However, whereas @code{f2c} generates a single check per
+reference for a multi-dimensional array, of the computed
+offset against the valid offset range (0 through the size of the array),
+@code{g77} generates a single check per @emph{subscript} expression.
+This catches some cases of potential bugs that @code{f2c} does not,
+such as references to below the beginning of an assumed-size array.
+
+@code{g77} also generates checks for @code{CHARACTER} substring references,
+something @code{f2c} currently does not do.
+
+Use the new @samp{-ffortran-bounds-check} option
+to specify bounds-checking for only the Fortran code you are compiling,
+not necessarily for code written in other languages.
+
+@emph{Note:} To provide more detailed information on the offending subscript,
+@code{g77} provides the @code{libg2c} run-time library routine @code{s_rnge}
+with somewhat differently-formatted information.
+Here's a sample diagnostic:
+
+@smallexample
+Subscript out of range on file line 4, procedure rnge.f/bf.
+Attempt to access the -6-th element of variable b[subscript-2-of-2].
+Aborted
+@end smallexample
+
+The above message indicates that the offending source line is
+line 4 of the file @file{rnge.f},
+within the program unit (or statement function) named @samp{bf}.
+The offended array is named @samp{b}.
+The offended array dimension is the second for a two-dimensional array,
+and the offending, computed subscript expression was @samp{-6}.
+
+For a @code{CHARACTER} substring reference, the second line has
+this appearance:
+
+@smallexample
+Attempt to access the 11-th element of variable a[start-substring].
+@end smallexample
+
+This indicates that the offended @code{CHARACTER} variable or array
+is named @samp{a},
+the offended substring position is the starting (leftmost) position,
+and the offending substring expression is @samp{11}.
+
+(Though the verbage of @code{s_rnge} is not ideal
+for the purpose of the @code{g77} compiler,
+the above information should provide adequate diagnostic abilities
+to it users.)
@end table
@xref{Code Gen Options,,Options for Code Generation Conventions,
@@ -3362,798 +3506,9 @@ variables.
@include news.texi
-@node Changes
-@chapter User-visible Changes
-@cindex versions, recent
-@cindex recent versions
-@cindex changes, user-visible
-@cindex user-visible changes
-
-This section describes changes to @code{g77} that are visible
-to the programmers who actually write and maintain Fortran
-code they compile with @code{g77}.
-Information on changes to installation procedures,
-changes to the documentation, and bug fixes is
-not provided here, unless it is likely to affect how
-users use @code{g77}.
-@xref{News,,News About GNU Fortran}, for information on
-such changes to @code{g77}.
-
-To find out about existing bugs and ongoing plans for GNU
-Fortran, retrieve @uref{ftp://alpha.gnu.org/g77.plan}
-or, if you cannot do that, email
-@email{fortran@@gnu.org} asking for a recent copy of the
-GNU Fortran @file{.plan} file.
-
-@heading In @code{egcs} 1.1 (versus 0.5.24):
-@itemize @bullet
-@cindex alignment
-@cindex double-precision performance
-@cindex -malign-double
-@item
-Align static double-precision variables and arrays
-on Intel x86 targets
-regardless of whether @samp{-malign-double} is specified.
-
-Generally, this affects only local variables and arrays
-having the @code{SAVE} attribute
-or given initial values via @code{DATA}.
-@end itemize
-
-@heading In @code{egcs} 1.1 (versus @code{egcs} 1.0.3):
-@itemize @bullet
-@item
-Support @samp{FORMAT(I<@var{expr}>)} when @var{expr} is a
-compile-time constant @code{INTEGER} expression.
-
-@item
-Fix @code{g77} @samp{-g} option so procedures that
-use @samp{ENTRY} can be stepped through, line by line,
-in @code{gdb}.
-
-@item
-Allow any @code{REAL} argument to intrinsics
-@code{Second} and @code{CPU_Time}.
-
-@item
-Use @code{tempnam}, if available, to open scratch files
-(as in @samp{OPEN(STATUS='SCRATCH')})
-so that the @code{TMPDIR} environment variable,
-if present, is used.
-
-@item
-@code{g77}'s version of @code{libf2c} separates out
-the setting of global state
-(such as command-line arguments and signal handling)
-from @file{main.o} into distinct, new library
-archive members.
-
-This should make it easier to write portable applications
-that have their own (non-Fortran) @code{main()} routine
-properly set up the @code{libf2c} environment, even
-when @code{libf2c} (now @code{libg2c}) is a shared library.
-
-@item
-The @code{g77} command now expects the run-time library
-to be named @code{libg2c.a} instead of @code{libf2c.a},
-to ensure that a version other than the one built and
-installed as part of the same @code{g77} version is picked up.
-
-@item
-Some diagnostics have been changed from warnings to errors,
-to prevent inadvertent use of the resulting, probably buggy,
-programs.
-These mostly include diagnostics about use of unsupported features
-in the @code{OPEN}, @code{INQUIRE}, @code{READ}, and
-@code{WRITE} statements,
-and about truncations of various sorts of constants.
-@end itemize
-
-@heading In 0.5.24 and @code{egcs} 1.1 (versus 0.5.23):
-@itemize @bullet
-@item
-@code{g77} now treats @samp{%LOC(@var{expr})} and
-@samp{LOC(@var{expr})} as ``ordinary'' expressions
-when they are used as arguments in procedure calls.
-This change applies only to global (filewide) analysis,
-making it consistent with
-how @code{g77} actually generates code
-for these cases.
-
-Previously, @code{g77} treated these expressions
-as denoting special ``pointer'' arguments
-for the purposes of filewide analysis.
-
-@item
-The @code{g77} driver now ensures that @samp{-lg2c}
-is specified in the link phase prior to any
-occurrence of @samp{-lm}.
-This prevents accidentally linking to a routine
-in the SunOS4 @samp{-lm} library
-when the generated code wants to link to the one
-in @code{libf2c} (@code{libg2c}).
-
-@item
-@code{g77} emits more debugging information when
-@samp{-g} is used.
-
-This new information allows, for example,
-@kbd{which __g77_length_a} to be used in @code{gdb}
-to determine the type of the phantom length argument
-supplied with @samp{CHARACTER} variables.
-
-This information pertains to internally-generated
-type, variable, and other information,
-not to the longstanding deficiencies vis-a-vis
-@samp{COMMON} and @samp{EQUIVALENCE}.
-
-@item
-The F90 @samp{Date_and_Time} intrinsic now is
-supported.
-
-@item
-The F90 @samp{System_Clock} intrinsic allows
-the optional arguments (except for the @samp{Count}
-argument) to be omitted.
-@end itemize
-
-@heading In 0.5.23:
-@itemize @bullet
-@item
-This release contains several regressions against
-version 0.5.22 of @code{g77}, due to using the
-``vanilla'' @code{gcc} back end instead of patching
-it to fix a few bugs and improve performance in a
-few cases.
-
-@xref{Actual Bugs,,Actual Bugs We Haven't Fixed Yet},
-available in plain-text format in @code{gcc/f/BUGS},
-for information on the known bugs in this version,
-including the regressions.
-
-Features that have been dropped from this version
-of @code{g77} due to their being implemented
-via @code{g77}-specific patches to the @code{gcc}
-back end in previous releases include:
-
-@itemize --
-@item
-Support for @code{__restrict__} keyword,
-the options @samp{-fargument-alias}, @samp{-fargument-noalias},
-and @samp{-fargument-noalias-global},
-and the corresponding alias-analysis code.
-
-(@code{egcs} has the alias-analysis
-code, but not the @code{__restrict__} keyword.
-@code{egcs} @code{g77} users benefit from the alias-analysis
-code despite the lack of the @code{__restrict__} keyword,
-which is a C-language construct.)
-
-@item
-Support for the GNU compiler options
-@samp{-fmove-all-movables},
-@samp{-freduce-all-givs},
-and @samp{-frerun-loop-opt}.
-
-(@code{egcs} supports these options.
-@code{g77} users of @code{egcs} benefit from them even if
-they are not explicitly specified,
-because the defaults are optimized for @code{g77} users.)
-
-@item
-Support for the @samp{-W} option warning about
-integer division by zero.
-
-@item
-The Intel x86-specific option @samp{-malign-double}
-applying to stack-allocated data
-as well as statically-allocate data.
-@end itemize
-
-@item
-Support @code{gcc} version 2.8,
-and remove support for prior versions of @code{gcc}.
-
-@cindex -@w{}-driver option
-@cindex g77 options, -@w{}-driver
-@cindex options, -@w{}-driver
-@item
-Remove support for the @samp{--driver} option,
-as @code{g77} now does all the driving,
-just like @code{gcc}.
-
-@item
-The @code{g77} command now expects the run-time library
-to be named @code{libg2c.a} instead of @code{libf2c.a},
-to ensure that a version other than the one built and
-installed as part of the same @code{g77} version is picked up.
-
-@item
-@code{g77}'s version of @code{libf2c} separates out
-the setting of global state
-(such as command-line arguments and signal handling)
-from @file{main.o} into distinct, new library
-archive members.
-
-This should make it easier to write portable applications
-that have their own (non-Fortran) @code{main()} routine
-properly set up the @code{libf2c} environment, even
-when @code{libf2c} (now @code{libg2c}) is a shared library.
-
-@item
-Some diagnostics have been changed from warnings to errors,
-to prevent inadvertent use of the resulting, probably buggy,
-programs.
-These mostly include diagnostics about use of unsupported features
-in the @code{OPEN}, @code{INQUIRE}, @code{READ}, and
-@code{WRITE} statements,
-and about truncations of various sorts of constants.
-@end itemize
-
-@heading In 0.5.22:
-@itemize @bullet
-@item
-Fix @code{Signal} intrinsic so it offers portable
-support for 64-bit systems (such as Digital Alphas
-running GNU/Linux).
-
-@item
-Support @samp{FORMAT(I<@var{expr}>)} when @var{expr} is a
-compile-time constant @code{INTEGER} expression.
-
-@item
-Fix @code{g77} @samp{-g} option so procedures that
-use @samp{ENTRY} can be stepped through, line by line,
-in @code{gdb}.
-
-@item
-Allow any @code{REAL} argument to intrinsics
-@code{Second} and @code{CPU_Time}.
-
-@item
-Allow any numeric argument to intrinsics
-@code{Int2} and @code{Int8}.
-
-@item
-Use @code{tempnam}, if available, to open scratch files
-(as in @samp{OPEN(STATUS='SCRATCH')})
-so that the @code{TMPDIR} environment variable,
-if present, is used.
-
-@item
-Rename the @code{gcc} keyword @code{restrict} to
-@code{__restrict__}, to avoid rejecting valid, existing,
-C programs.
-Support for @code{restrict} is now more like support
-for @code{complex}.
-
-@item
-Fix @samp{-fugly-comma} to affect invocations of
-only external procedures.
-Restore rejection of gratuitous trailing omitted
-arguments to intrinsics, as in @samp{I=MAX(3,4,,)}.
-
-@item
-Fix compiler so it accepts @samp{-fgnu-intrinsics-*} and
-@samp{-fbadu77-intrinsics-*} options.
-@end itemize
-
-@heading In @code{egcs} 1.0.2 (versus @code{egcs} 1.0.1):
-@itemize @bullet
-@item
-Fix compiler so it accepts @samp{-fgnu-intrinsics-*} and
-@samp{-fbadu77-intrinsics-*} options.
-@end itemize
-
-@heading In @code{egcs} 1.0 (versus 0.5.21):
-@itemize @bullet
-@item
-Version 1.0 of @code{egcs}
-contains several regressions against
-version 0.5.21 of @code{g77},
-due to using the
-``vanilla'' @code{gcc} back end instead of patching
-it to fix a few bugs and improve performance in a
-few cases.
-
-@xref{Actual Bugs,,Actual Bugs We Haven't Fixed Yet},
-available in plain-text format in @code{gcc/f/BUGS},
-for information on the known bugs in this version,
-including the regressions.
-
-Features that have been dropped from this version
-of @code{g77} due to their being implemented
-via @code{g77}-specific patches to the @code{gcc}
-back end in previous releases include:
-
-@itemize --
-@item
-Support for the C-language @code{restrict} keyword.
-
-@item
-Support for the @samp{-W} option warning about
-integer division by zero.
-
-@item
-The Intel x86-specific option @samp{-malign-double}
-applying to stack-allocated data
-as well as statically-allocate data.
-@end itemize
-
-@cindex -@w{}-driver option
-@cindex g77 options, -@w{}-driver
-@cindex options, -@w{}-driver
-@item
-Remove support for the @samp{--driver} option,
-as @code{g77} now does all the driving,
-just like @code{gcc}.
-
-@item
-Allow any numeric argument to intrinsics
-@code{Int2} and @code{Int8}.
-@end itemize
-
-@heading In 0.5.21:
-@itemize @bullet
-@item
-When the @samp{-W} option is specified, @code{gcc}, @code{g77},
-and other GNU compilers that incorporate the @code{gcc}
-back end as modified by @code{g77}, issue
-a warning about integer division by constant zero.
-
-@item
-New option @samp{-Wno-globals} disables warnings
-about ``suspicious'' use of a name both as a global
-name and as the implicit name of an intrinsic, and
-warnings about disagreements over the number or natures of
-arguments passed to global procedures, or the
-natures of the procedures themselves.
-
-The default is to issue such warnings, which are
-new as of this version of @code{g77}.
-
-@item
-New option @samp{-fno-globals} disables diagnostics
-about potentially fatal disagreements
-analysis problems, such as disagreements over the
-number or natures of arguments passed to global
-procedures, or the natures of those procedures themselves.
-
-The default is to issue such diagnostics and flag
-the compilation as unsuccessful.
-With this option, the diagnostics are issued as
-warnings, or, if @samp{-Wno-globals} is specified,
-are not issued at all.
-
-This option also disables inlining of global procedures,
-to avoid compiler crashes resulting from coding errors
-that these diagnostics normally would identify.
-
-@item
-Fix @code{libU77} routines that accept file and other names
-to strip trailing blanks from them, for consistency
-with other implementations.
-Blanks may be forcibly appended to such names by
-appending a single null character (@samp{CHAR(0)})
-to the significant trailing blanks.
-
-@item
-Fix @code{CHMOD} intrinsic to work with file names
-that have embedded blanks, commas, and so on.
-
-@item
-Fix @code{SIGNAL} intrinsic so it accepts an
-optional third @samp{Status} argument.
-
-@item
-Make many changes to @code{libU77} intrinsics to
-support existing code more directly.
-
-Such changes include allowing both subroutine and
-function forms of many routines, changing @code{MCLOCK()}
-and @code{TIME()} to return @code{INTEGER(KIND=1)} values,
-introducing @code{MCLOCK8()} and @code{TIME8()} to
-return @code{INTEGER(KIND=2)} values,
-and placing functions that are intended to perform
-side effects in a new intrinsic group, @code{badu77}.
-
-@item
-Add options @samp{-fbadu77-intrinsics-delete},
-@samp{-fbadu77-intrinsics-hide}, and so on.
-
-@item
-Add @code{INT2} and @code{INT8} intrinsics.
-
-@item
-Add @code{CPU_TIME} intrinsic.
-
-@item
-Add @code{ALARM} intrinsic.
-
-@item
-@code{CTIME} intrinsic now accepts any @code{INTEGER}
-argument, not just @code{INTEGER(KIND=2)}.
-
-@item
-@code{g77} driver now prints version information (such as produced
-by @kbd{g77 -v}) to @code{stderr} instead of @code{stdout}.
-
-@item
-The @samp{.r} suffix now designates a Ratfor source file,
-to be preprocessed via the @code{ratfor} command, available
-separately.
-@end itemize
-
-@heading In 0.5.20:
-@itemize @bullet
-@item
-The @samp{-fno-typeless-boz} option is now the default.
-
-This option specifies that non-decimal-radix
-constants using the prefixed-radix form (such as @samp{Z'1234'})
-are to be interpreted as @code{INTEGER(KIND=1)} constants.
-Specify @samp{-ftypeless-boz} to cause such
-constants to be interpreted as typeless.
-
-(Version 0.5.19 introduced @samp{-fno-typeless-boz} and
-its inverse.)
-
-@xref{Fortran Dialect Options,,Options Controlling Fortran Dialect},
-for information on the @samp{-ftypeless-boz} option.
-
-@item
-Options @samp{-ff90-intrinsics-enable} and
-@samp{-fvxt-intrinsics-enable} now are the
-defaults.
-
-Some programs might use names that clash with
-intrinsic names defined (and now enabled) by these
-options or by the new @code{libU77} intrinsics.
-Users of such programs might need to compile them
-differently (using, for example, @samp{-ff90-intrinsics-disable})
-or, better yet, insert appropriate @code{EXTERNAL}
-statements specifying that these names are not intended
-to be names of intrinsics.
-
-@item
-The @samp{ALWAYS_FLUSH} macro is no longer defined when
-building @code{libf2c}, which should result in improved
-I/O performance, especially over NFS.
-
-@emph{Note:} If you have code that depends on the behavior
-of @code{libf2c} when built with @samp{ALWAYS_FLUSH} defined,
-you will have to modify @code{libf2c} accordingly before
-building it from this and future versions of @code{g77}.
-
-@xref{Output Assumed To Flush}, for more information.
-
-@item
-Dave Love's implementation of @code{libU77} has been
-added to the version of @code{libf2c} distributed with
-and built as part of @code{g77}.
-@code{g77} now knows about the routines in this library
-as intrinsics.
-
-@item
-New option @samp{-fvxt} specifies that the
-source file is written in VXT Fortran, instead of GNU Fortran.
-
-@xref{VXT Fortran}, for more information on the constructs
-recognized when the @samp{-fvxt} option is specified.
-
-@item
-The @samp{-fvxt-not-f90} option has been deleted,
-along with its inverse, @samp{-ff90-not-vxt}.
-
-If you used one of these deleted options, you should
-re-read the pertinent documentation to determine which
-options, if any, are appropriate for compiling your
-code with this version of @code{g77}.
-
-@xref{Other Dialects}, for more information.
-
-@item
-The @samp{-fugly} option now issues a warning, as it
-likely will be removed in a future version.
-
-(Enabling all the @samp{-fugly-*} options is unlikely
-to be feasible, or sensible, in the future,
-so users should learn to specify only those
-@samp{-fugly-*} options they really need for a
-particular source file.)
-
-@item
-The @samp{-fugly-assumed} option, introduced in
-version 0.5.19, has been changed to
-better accommodate old and new code.
-@xref{Ugly Assumed-Size Arrays}, for more information.
-
-@item
-Related to supporting Alpha (AXP) machines, the @code{LOC()}
-intrinsic and @code{%LOC()} construct now return
-values of @code{INTEGER(KIND=0)} type,
-as defined by the GNU Fortran language.
-
-This type is wide enough
-(holds the same number of bits)
-as the character-pointer type on the machine.
-
-On most machines, this won't make a difference,
-whereas, on Alphas and other systems with 64-bit pointers,
-the @code{INTEGER(KIND=0)} type is equivalent to @code{INTEGER(KIND=2)}
-(often referred to as @code{INTEGER*8})
-instead of the more common @code{INTEGER(KIND=1)}
-(often referred to as @code{INTEGER*4}).
-
-@item
-Emulate @code{COMPLEX} arithmetic in the @code{g77} front
-end, to avoid bugs in @code{complex} support in the
-@code{gcc} back end.
-New option @samp{-fno-emulate-complex}
-causes @code{g77} to revert the 0.5.19 behavior.
-
-@item
-Dummy arguments are no longer assumed to potentially alias
-(overlap)
-other dummy arguments or @code{COMMON} areas when any of
-these are defined (assigned to) by Fortran code.
-
-This can result in faster and/or smaller programs when
-compiling with optimization enabled, though on some
-systems this effect is observed only when @samp{-fforce-addr}
-also is specified.
-
-New options @samp{-falias-check}, @samp{-fargument-alias},
-@samp{-fargument-noalias},
-and @samp{-fno-argument-noalias-global} control the
-way @code{g77} handles potential aliasing.
-
-@xref{Aliasing Assumed To Work}, for detailed information on why the
-new defaults might result in some programs no longer working the way they
-did when compiled by previous versions of @code{g77}.
-
-@item
-New option @samp{-fugly-assign} specifies that the
-same memory locations are to be used to hold the
-values assigned by both statements @samp{I = 3} and
-@samp{ASSIGN 10 TO I}, for example.
-(Normally, @code{g77} uses a separate memory location
-to hold assigned statement labels.)
-
-@xref{Ugly Assigned Labels}, for more information.
-
-@item
-@code{FORMAT} and @code{ENTRY} statements now are allowed to
-precede @code{IMPLICIT NONE} statements.
-
-@item
-Enable full support of @code{INTEGER(KIND=2)}
-(often referred to as @code{INTEGER*8})
-available in
-@code{libf2c} and @file{f2c.h} so that @code{f2c} users
-may make full use of its features via the @code{g77}
-version of @file{f2c.h} and the @code{INTEGER(KIND=2)}
-support routines in the @code{g77} version of @code{libf2c}.
-
-@item
-Improve @code{g77} driver and @code{libf2c} so that @samp{g77 -v}
-yields version information on the library.
-
-@item
-The @code{SNGL} and @code{FLOAT} intrinsics now are
-specific intrinsics, instead of synonyms for the
-generic intrinsic @code{REAL}.
-
-@item
-New intrinsics have been added.
-These are @code{REALPART}, @code{IMAGPART},
-@code{COMPLEX},
-@code{LONG}, and @code{SHORT}.
-
-@item
-A new group of intrinsics, @samp{gnu}, has been added
-to contain the new @code{REALPART}, @code{IMAGPART},
-and @code{COMPLEX} intrinsics.
-An old group, @samp{dcp}, has been removed.
-
-@item
-Complain about industry-wide ambiguous references
-@samp{REAL(@var{expr})} and @samp{AIMAG(@var{expr})},
-where @var{expr} is @code{DOUBLE COMPLEX} (or any
-complex type other than @code{COMPLEX}), unless
-@samp{-ff90} option specifies Fortran 90 interpretation
-or new @samp{-fugly-complex} option, in conjunction with
-@samp{-fnot-f90}, specifies @code{f2c} interpretation.
-@end itemize
-
-@heading In 0.5.19:
-
-@itemize @bullet
-@item
-A temporary kludge option provides bare-bones information on
-@code{COMMON} and @code{EQUIVALENCE} members at debug time.
-@xref{Code Gen Options,,Options for Code Generation Conventions},
-for information on the @samp{-fdebug-kludge} option.
-
-@item
-New @samp{-fonetrip} option specifies FORTRAN-66-style
-one-trip @code{DO} loops.
-
-@item
-New @samp{-fno-silent} option causes names of program units
-to be printed as they are compiled, in a fashion similar to
-UNIX @code{f77} and @code{f2c}.
-
-@item
-New @samp{-fugly-assumed} option specifies that arrays
-dimensioned via @samp{DIMENSION X(1)}, for example, are to be
-treated as assumed-size.
-
-@item
-New @samp{-fno-typeless-boz} option specifies that non-decimal-radix
-constants using the prefixed-radix form (such as @samp{Z'1234'})
-are to be interpreted as @code{INTEGER(KIND=1)} constants.
-
-@item
-New @samp{-ff66} option is a ``shorthand'' option that specifies
-behaviors considered appropriate for FORTRAN 66 programs.
-
-@item
-New @samp{-ff77} option is a ``shorthand'' option that specifies
-behaviors considered appropriate for UNIX @code{f77} programs.
-
-@item
-New @samp{-fugly-comma} and @samp{-fugly-logint} options provided
-to perform some of what @samp{-fugly} used to do.
-@samp{-fugly} and @samp{-fno-ugly} are now ``shorthand'' options,
-in that they do nothing more than enable (or disable) other
-@samp{-fugly-*} options.
-
-@item
-Change code generation for list-directed I/O so it allows
-for new versions of @code{libf2c} that might return non-zero
-status codes for some operations previously assumed to always
-return zero.
-
-This change not only affects how @code{IOSTAT=} variables
-are set by list-directed I/O, it also affects whether
-@code{END=} and @code{ERR=} labels are reached by these
-operations.
-
-@item
-Add intrinsic support for new @code{FTELL} and @code{FSEEK}
-procedures in @code{libf2c}.
-
-@item
-Add options @samp{--help} and @samp{--version} to the
-@code{g77} command, to conform to GNU coding guidelines.
-Also add printing of @code{g77} version number when
-the @samp{--verbose} (@samp{-v}) option is used.
-@end itemize
-
-@heading In 0.5.18:
-
-@itemize @bullet
-@item
-The @code{BYTE} and @code{WORD} statements now are supported,
-to a limited extent.
-
-@item
-@code{INTEGER*1}, @code{INTEGER*2}, @code{INTEGER*8},
-and their @code{LOGICAL}
-equivalents, now are supported to a limited extent.
-Among the missing elements are complete intrinsic and constant
-support.
-
-@item
-Support automatic arrays in procedures.
-For example, @samp{REAL A(N)}, where @samp{A} is
-not a dummy argument, specifies that @samp{A} is
-an automatic array.
-The size of @samp{A} is calculated from the value
-of @samp{N} each time the procedure is called,
-that amount of space is allocated, and that space
-is freed when the procedure returns to its caller.
-
-@item
-Add @samp{-fno-zeros} option, enabled by default,
-to reduce compile-time CPU and memory usage for
-code that provides initial zero values for variables
-and arrays.
-
-@item
-Introduce three new options that apply to all compilations
-by @code{g77}-aware GNU compilers---@samp{-fmove-all-movables},
-@samp{-freduce-all-givs}, and @samp{-frerun-loop-opt}---which
-can improve the run-time performance of some programs.
-
-@item
-Replace much of the existing documentation with a single
-Info document.
-
-@item
-New option @samp{-fno-second-underscore}.
-@end itemize
-
-@heading In 0.5.17:
-
-@itemize @bullet
-@item
-The @code{ERF()} and @code{ERFC()} intrinsics now are generic
-intrinsics, mapping to @code{ERF}/@code{DERF} and
-@code{ERFC}/@code{DERFC}, respectively.
-@emph{Note:} Use @samp{INTRINSIC ERF,ERFC} in any code that
-might reference these as generic intrinsics, to
-improve the likelihood of diagnostics (instead of subtle run-time
-bugs) when using compilers that don't support these as intrinsics.
-
-@item
-New option @samp{-Wsurprising}.
-
-@item
-DO loops with non-@code{INTEGER} variables now diagnosed only when
-@samp{-Wsurprising} specified.
-Previously, this was diagnosed @emph{unless} @samp{-fpedantic} or
-@samp{-fugly} was specified.
-@end itemize
-
-@heading In 0.5.16:
-
-@itemize @bullet
-@item
-@code{libf2c} changed to output a leading zero (0) digit for floating-point
-values output via list-directed and formatted output (to bring @code{g77}
-more into line with many existing Fortran implementations---the
-ANSI FORTRAN 77 standard leaves this choice to the implementation).
-
-@item
-@code{libf2c} no longer built with debugging information
-intact, making it much smaller.
-
-@item
-Automatic installation of the @code{g77} command now works.
-
-@item
-Diagnostic messages now more informative, a la @code{gcc},
-including messages like @samp{In function `foo':} and @samp{In file
-included from...:}.
-
-@item
-New group of intrinsics called @samp{unix}, including @code{ABORT},
-@code{DERF}, @code{DERFC}, @code{ERF}, @code{ERFC}, @code{EXIT},
-@code{FLUSH}, @code{GETARG}, @code{GETENV}, @code{SIGNAL}, and
-@code{SYSTEM}.
-
-@item
-@samp{-funix-intrinsics-@{delete,hide,disable,enable@}}
-options added.
-
-@item
-@samp{-fno-underscoring} option added.
-
-@item
-@samp{--driver} option added to the @code{g77} command.
-
-@item
-Support for the @code{gcc} options @samp{-fident} and @samp{-fno-ident}
-added.
-
-@item
-@samp{g77 -v} returns much more version info, making the submission
-of better bug reports easily.
-
-@item
-Many improvements to the @code{g77} command to better fulfill its role as
-a front-end to the @code{gcc} driver.
-For example, @code{g77} now
-recognizes @samp{--verbose} as a verbose way of specifying @samp{-v}.
-
-@item
-Compiling preprocessed (@file{*.F} and @file{*.fpp}) files now
-results in better diagnostics and debugging information, as the
-source-location info now is passed all the
-way through the compilation process instead of being lost.
-@end itemize
+@set USERVISONLY
+@include news.texi
+@clear USERVISONLY
@node Language
@chapter The GNU Fortran Language
@@ -4223,7 +3578,7 @@ Extensions to the ANSI FORTRAN 77 standard:
@section Direction of Language Development
@cindex direction of language development
@cindex features, language
-@cindex language features
+@cindex language, features
The purpose of the following description of the GNU Fortran
language is to promote wide portability of GNU Fortran programs.
@@ -4368,8 +3723,8 @@ of @code{g77}).
@node Standard Support
@section ANSI FORTRAN 77 Standard Support
@cindex ANSI FORTRAN 77 support
-@cindex standard support
-@cindex support for ANSI FORTRAN 77
+@cindex standard, support for
+@cindex support, FORTRAN 77
@cindex compatibility, FORTRAN 77
@cindex FORTRAN 77 compatibility
@@ -4600,7 +3955,7 @@ For example: @samp{PRINT *, 'My name is Bob'}.
@item
A metasyntactic variable---that is, a name used in this document
to serve as a placeholder for whatever text is used by the
-user or programmer--appears as shown in the following example:
+user or programmer---appears as shown in the following example:
``The @code{INTEGER @var{ivar}} statement specifies that
@var{ivar} is a variable or array of type @code{INTEGER}.''
@@ -4644,6 +3999,7 @@ for the relevant aspects of GNU Fortran.)
(Corresponds to Section 2.2 of ANSI X3.9-1978 FORTRAN 77.)
+@cindex limits, lengths of names
In GNU Fortran, a symbolic name is at least one character long,
and has no arbitrary upper limit on length.
However, names of entities requiring external linkage (such as
@@ -4660,8 +4016,13 @@ character (which must be a letter).
(Corresponds to Section 2.3 of ANSI X3.9-1978 FORTRAN 77.)
-@cindex comments, trailing
-@cindex trailing comments
+@cindex trailing comment
+@cindex comment
+@cindex characters, comment
+@cindex !
+@cindex exclamation point
+@cindex continuation character
+@cindex characters, continuation
Use of an exclamation point (@samp{!}) to begin a
trailing comment (a comment that extends to the end of the same
source line) is permitted under the following conditions:
@@ -4685,7 +4046,8 @@ That is, a trailing comment may contain exclamation points
in their commentary text.
@end itemize
-@cindex semicolons
+@cindex ;
+@cindex semicolon
@cindex statements, separated by semicolon
Use of a semicolon (@samp{;}) as a statement separator
is permitted under the following conditions:
@@ -4771,36 +4133,65 @@ Special characters include:
@itemize @bullet
@item
+@cindex ;
+@cindex semicolon
Semicolon (@samp{;})
@item
+@cindex !
+@cindex exclamation point
Exclamation point (@samp{!})
@item
+@cindex "
+@cindex double quote
Double quote (@samp{"})
@item
+@cindex \
+@cindex backslash
Backslash (@samp{\})
@item
+@cindex ?
+@cindex question mark
Question mark (@samp{?})
@item
+@cindex #
+@cindex hash mark
+@cindex pound sign
Hash mark (@samp{#})
@item
+@cindex &
+@cindex ampersand
Ampersand (@samp{&})
@item
+@cindex %
+@cindex percent sign
Percent sign (@samp{%})
@item
+@cindex _
+@cindex underscore
Underscore (@samp{_})
@item
+@cindex <
+@cindex open angle
+@cindex left angle
+@cindex open bracket
+@cindex left bracket
Open angle (@samp{<})
@item
+@cindex >
+@cindex close angle
+@cindex right angle
+@cindex close bracket
+@cindex right bracket
Close angle (@samp{>})
@item
@@ -4810,7 +4201,9 @@ The FORTRAN 77 special characters (@key{SPC}, @samp{=},
and @samp{:})
@end itemize
-@cindex blanks (spaces)
+@cindex blank
+@cindex space
+@cindex SPC
Note that this document refers to @key{SPC} as @dfn{space},
while X3.9-1978 FORTRAN 77 refers to it as @dfn{blank}.
@@ -4818,8 +4211,8 @@ while X3.9-1978 FORTRAN 77 refers to it as @dfn{blank}.
@subsection Lines
@cindex lines
@cindex source file format
-@cindex source form
-@cindex files, source
+@cindex source format
+@cindex file, source
@cindex source code
@cindex code, source
@cindex fixed form
@@ -4850,7 +4243,7 @@ stream-based text file is translated to GNU Fortran lines as follows:
A newline in the file is the character that represents the end of
a line of text to the underlying system.
For example, on ASCII-based systems, a newline is the @key{NL}
-character, which has ASCII value 12 (decimal).
+character, which has ASCII value 10 (decimal).
@item
Each newline in the file serves to end the line of text that precedes
@@ -4861,7 +4254,9 @@ The end-of-file marker (@code{EOF}) also serves to end the line
of text that precedes it (and that does not contain a newline).
@item
-@cindex blanks (spaces)
+@cindex blank
+@cindex space
+@cindex SPC
Any line of text that is shorter than 72 characters is padded to that length
with spaces (called ``blanks'' in the standard).
@@ -4890,10 +4285,10 @@ line containing 72 spaces.
@node Continuation Line
@subsection Continuation Line
-@cindex continuation lines, number of
+@cindex continuation line, number of
@cindex lines, continuation
@cindex number of continuation lines
-@cindex limits on continuation lines
+@cindex limits, continuation lines
(Corresponds to Section 3.2.3 of ANSI X3.9-1978 FORTRAN 77.)
@@ -5007,7 +4402,7 @@ An @code{END BLOCK DATA} statement, if the program unit is a block data.
@node INCLUDE
@subsection Including Source Text
-@cindex INCLUDE
+@cindex INCLUDE directive
Additional source text may be included in the processing of
the source file via the @code{INCLUDE} directive:
@@ -5096,8 +4491,9 @@ This permits long names to be used for @var{filename}.
@cindex #
@cindex preprocessor
-@code{cpp} output-style @code{#} directives @xref{C Preprocessor
-Output,,, cpp, The C Preprocessor}, are recognized by the compiler even
+@code{cpp} output-style @code{#} directives
+(@pxref{C Preprocessor Output,,, cpp, The C Preprocessor})
+are recognized by the compiler even
when the preprocessor isn't run on the input (as it is when compiling
@samp{.F} files). (Note the distinction between these @code{cpp}
@code{#} @emph{output} directives and @code{#line} @emph{input}
@@ -5901,6 +5297,10 @@ as appropriate.
@node CYCLE and EXIT
@subsection The @code{CYCLE} and @code{EXIT} Statements
+@cindex CYCLE statement
+@cindex EXIT statement
+@cindex statements, CYCLE
+@cindex statements, EXIT
The @code{CYCLE} and @code{EXIT} statements specify that
the remaining statements in the current iteration of a
particular active (enclosing) @code{DO} loop are to be skipped.
@@ -6237,12 +5637,12 @@ are given arguments that do not conform to their stated requirements:
@smallexample
PROGRAM JCB002
C Version 1:
+C Modified 1999-02-15 (Burley) to delete my email address.
C Modified 1997-05-21 (Burley) to accommodate compilers that implement
C INT(I1-I2) as INT(I1)-INT(I2) given INTEGER*2 I1,I2.
C
C Version 0:
C Written by James Craig Burley 1997-02-20.
-C Contact via Internet email: burley@@gnu.org
C
C Purpose:
C Determine how compilers handle non-standard IDIM
@@ -6345,7 +5745,7 @@ These disagreements strongly suggest that Fortran programmers,
and certainly existing Fortran programs, disagree about the
meaning of such invocations.
-The first version of @samp{JCB002} didn't accommodate some compilers'
+The first version of @code{JCB002} didn't accommodate some compilers'
treatment of @samp{INT(I1-I2)} where @samp{I1} and @samp{I2} are
@code{INTEGER*2}.
In such a case, these compilers apparently convert both
@@ -6357,7 +5757,7 @@ However, the results of the careful analyses done on the outputs
of programs compiled by these various compilers show that they
all implement either @samp{Interp 1} or @samp{Interp 2} above.
-Specifically, it is believed that the new version of @samp{JCB002}
+Specifically, it is believed that the new version of @code{JCB002}
above will confirm that:
@itemize @bullet
@@ -6380,10 +5780,10 @@ worth adding to the above list, please let us know the details
@node REAL() and AIMAG() of Complex
@subsection @code{REAL()} and @code{AIMAG()} of Complex
-@cindex REAL intrinsic
-@cindex intrinsics, REAL
-@cindex AIMAG intrinsic
-@cindex intrinsics, AIMAG
+@cindex @code{Real} intrinsic
+@cindex intrinsics, @code{Real}
+@cindex @code{AImag} intrinsic
+@cindex intrinsics, @code{AImag}
The GNU Fortran language disallows @code{REAL(@var{expr})}
and @code{AIMAG(@var{expr})},
@@ -6440,8 +5840,8 @@ treated as @samp{REAL(REALPART(@var{expr}))}.
@node CMPLX() of DOUBLE PRECISION
@subsection @code{CMPLX()} of @code{DOUBLE PRECISION}
-@cindex CMPLX intrinsic
-@cindex intrinsics, CMPLX
+@cindex @code{Cmplx} intrinsic
+@cindex intrinsics, @code{Cmplx}
In accordance with Fortran 90 and at least some (perhaps all)
other compilers, the GNU Fortran language defines @code{CMPLX()}
@@ -6604,7 +6004,7 @@ did not exist, would leave this document in far worse shape!)
@node Scope and Classes of Names
@section Scope and Classes of Symbolic Names
-@cindex symbolic names
+@cindex symbol names, scope and classes
@cindex scope
(The following information augments or overrides the information in
@@ -6619,7 +6019,7 @@ for the relevant aspects of GNU Fortran.)
@node Underscores in Symbol Names
@subsection Underscores in Symbol Names
-@cindex underscores
+@cindex underscore
Underscores (@samp{_}) are accepted in symbol names after the first
character (which must be a letter).
@@ -6641,12 +6041,16 @@ Edit descriptors in @code{FORMAT} statements may contain compile-time
The @code{OPEN} specifier @code{NAME=} is equivalent to @code{FILE=}.
-These Fortran 90 features are supported:
+These Fortran 90 features are supported:
@itemize @bullet
@item
+@cindex FORMAT descriptors
@cindex Z edit descriptor
@cindex edit descriptor, Z
-The @code{Z} edit descriptor is supported.
+@cindex O edit descriptor
+@cindex edit descriptor, O
+The @code{O} and @code{Z} edit descriptors are supported for I/O of
+integers in octal and hexadecimal formats, respectively.
@item
The @code{FILE=} specifier may be omitted in an @code{OPEN} statement if
@code{STATUS='SCRATCH'} is supplied. The @code{STATUS='REPLACE'}
@@ -6656,25 +6060,21 @@ specifier is supported.
@node Fortran 90 Features
@section Fortran 90 Features
@cindex Fortran 90
+@cindex extensions, from Fortran 90
For convenience this section collects a list (probably incomplete) of
the Fortran 90 features supported by the GNU Fortran language, even if
they are documented elsewhere.
-@c makeinfo 1.68 objects to the nested parens
-@ifnotinfo
-@xref{Characters Lines Sequence,,{Characters, Lines, and Execution Sequence}},
-@end ifnotinfo
-@ifinfo
-@xref{Characters Lines Sequence},
-@end ifinfo
-for information on additional fixed source form lexical issues. In
-addition, the free source form is supported through the
+@xref{Characters Lines Sequence,,@asis{Characters, Lines, and Execution Sequence}},
+for information on additional fixed source form lexical issues.
@cindex @samp{-ffree-form}
-@samp{-ffree-form} option. Other Fortran 90 features can be turned on
-by the
+Further, the free source form is supported through the
+@samp{-ffree-form} option.
@cindex @samp{-ff90}
-@samp{-ff90} option, @ref{Fortran 90}. For information on the Fortran
-90 intrinsics available @ref{Table of Intrinsic Functions}.
+Other Fortran 90 features can be turned on by the @samp{-ff90} option;
+see @ref{Fortran 90}.
+For information on the Fortran 90 intrinsics available,
+see @ref{Table of Intrinsic Functions}.
@table @asis
@item Automatic arrays in procedures
@@ -6688,12 +6088,11 @@ Strings may have zero length and substrings of character constants are
permitted. Character constants may be enclosed in double quotes
(@code{"}) as well as single quotes. @xref{Character Type}.
@item Construct names
-(Symbolic tags on blocks.) @xref{Construct Names }.
+(Symbolic tags on blocks.) @xref{Construct Names}.
@item @code{CYCLE} and @code{EXIT}
@xref{CYCLE and EXIT,,The @code{CYCLE} and @code{EXIT} Statements}.
@item @code{DOUBLE COMPLEX}
-@xref{DOUBLE COMPLEX,,@code{DOUBLE COMPLEX} Statement
-}.
+@xref{DOUBLE COMPLEX,,@code{DOUBLE COMPLEX} Statement}.
@item @code{DO WHILE}
@xref{DO WHILE}.
@item @code{END} decoration
@@ -6704,21 +6103,29 @@ permitted. Character constants may be enclosed in double quotes
@item @code{IMPLICIT NONE}
@item @code{INCLUDE} statements
@xref{INCLUDE}.
-@item List directed and namelist i/o on internal files
+@item List-directed and namelist I/O on internal files
@item Binary, octal and hexadecimal constants
These are supported more generally than required by Fortran 90.
@xref{Integer Type}.
+@item @samp{O} and @samp{Z} edit descriptors
@item @code{NAMELIST}
@xref{NAMELIST}.
@item @code{OPEN} specifiers
@code{STATUS='REPLACE'} is supported.
+The @code{FILE=} specifier may be omitted in an @code{OPEN} statement if
+@code{STATUS='SCRATCH'} is supplied.
+@item @code{FORMAT} edit descriptors
+@cindex FORMAT descriptors
+@cindex Z edit descriptor
+@cindex edit descriptor, Z
+The @code{Z} edit descriptor is supported.
@item Relational operators
The operators @code{<}, @code{<=}, @code{==}, @code{/=}, @code{>} and
@code{>=} may be used instead of @code{.LT.}, @code{.LE.}, @code{.EQ.},
@code{.NE.}, @code{.GT.} and @code{.GE.} respectively.
@item @code{SELECT CASE}
-Not fully implemented. @xref{SELECT CASE on CHARACTER Type,,
-@code{SELECT CASE} on @code{CHARACTER} Type}.
+Not fully implemented.
+@xref{SELECT CASE on CHARACTER Type,, @code{SELECT CASE} on @code{CHARACTER} Type}.
@item Specification statements
A limited subset of the Fortran 90 syntax and semantics for variable
declarations is supported, including @code{KIND}. @xref{Kind Notation}.
@@ -6765,8 +6172,8 @@ of work!}
@node Source Form
@section Source Form
@cindex source file format
-@cindex source form
-@cindex files, source
+@cindex source format
+@cindex file, source
@cindex source code
@cindex code, source
@cindex fixed form
@@ -6815,7 +6222,8 @@ inside such constants.
@node Tabs
@subsection Tabs
-@cindex tab characters
+@cindex tab character
+@cindex horizontal tab
A source line with a @key{TAB} character anywhere in it is treated as
entirely significant---however long it is---instead of ending in
@@ -6849,8 +6257,7 @@ the way continued character/Hollerith constants are interpreted).
@node Short Lines
@subsection Short Lines
@cindex short source lines
-@cindex space-padding
-@cindex spaces
+@cindex space, padding with
@cindex source lines, short
@cindex lines, short
@@ -6876,7 +6283,7 @@ like @samp{-ffixed-line-length-none}, for example.
@node Long Lines
@subsection Long Lines
@cindex long source lines
-@cindex truncation
+@cindex truncation, of long lines
@cindex lines, long
@cindex source lines, long
@@ -6903,8 +6310,11 @@ continuation line, imitating the behavior of @code{f2c}.
@section Trailing Comment
@cindex trailing comment
-@cindex comment, trailing
+@cindex comment
+@cindex characters, comment
@cindex /*
+@cindex !
+@cindex exclamation point
@code{g77} supports use of @samp{/*} to start a trailing
comment.
In the GNU Fortran language, @samp{!} is used for this purpose.
@@ -7058,7 +6468,7 @@ but that seems to be overkill for a product in beta test.
Note 2: Rules for InitialCaps names are:
-@itemize --
+@itemize @minus
@item
Must be a single uppercase letter, @strong{or}
@item
@@ -7071,7 +6481,7 @@ valid InitialCaps names, but @samp{AB}, @samp{A2}, and @samp{ABC} are
not.
Note that most, but not all, built-in names meet these
requirements---the exceptions are some of the two-letter format
-specifiers, such as @samp{BN} and @samp{BZ}.
+specifiers, such as @code{BN} and @code{BZ}.
Here are the names of the corresponding command-line options:
@@ -7265,7 +6675,7 @@ meaning is to be assumed.
@code{g77} treats double-quote (@samp{"})
as beginning an octal constant of @code{INTEGER(KIND=1)} type
-when the @code{-fvxt} option is specified.
+when the @samp{-fvxt} option is specified.
The form of this octal constant is
@example
@@ -7276,7 +6686,7 @@ The form of this octal constant is
where @var{octal-digits} is a nonempty string of characters in
the set @samp{01234567}.
-For example, the @code{-fvxt} option permits this:
+For example, the @samp{-fvxt} option permits this:
@example
PRINT *, "20
@@ -7297,7 +6707,8 @@ both constructs in the general case, since statements like
@node Exclamation Point
@subsection Meaning of Exclamation Point in Column 6
-@cindex exclamation points
+@cindex !
+@cindex exclamation point
@cindex continuation character
@cindex characters, continuation
@cindex comment character
@@ -7308,7 +6719,7 @@ a fixed-form source file
as a continuation character rather than
as the beginning of a comment
(as it does in any other column)
-when the @code{-fvxt} option is specified.
+when the @samp{-fvxt} option is specified.
The following program, when run, prints a message indicating
whether it is interpreted according to GNU Fortran (and Fortran 90)
@@ -7331,7 +6742,7 @@ marks a line as a continuation line when it appears in column 6.)
@node Fortran 90
@section Fortran 90
@cindex compatibility, Fortran 90
-@cindex Fortran 90 compatibility
+@cindex Fortran 90, compatibility
The GNU Fortran language includes a number of features that are
part of Fortran 90, even when the @samp{-ff90} option is not specified.
@@ -7419,7 +6830,7 @@ provided for by that standard.
Automatic conversion of numeric
expressions to @code{INTEGER(KIND=1)} in contexts such as:
-@itemize --
+@itemize @minus
@item
Array-reference indexes.
@item
@@ -7538,18 +6949,6 @@ portable constructs, are accepted.
These are humorously referred to as ``distensions'',
extensions that just plain look ugly in the harsh light of day.
-@emph{Note:} The @samp{-fugly} option, which currently serves
-as shorthand to enable all of the distensions below, is likely to
-be removed in a future version of @code{g77}.
-That's because it's likely new distensions will be added that
-conflict with existing ones in terms of assigning meaning to
-a given chunk of code.
-(Also, it's pretty clear that users should not use @samp{-fugly}
-as shorthand when the next release of @code{g77} might add a
-distension to that that causes their existing code, when recompiled,
-to behave differently---perhaps even fail to compile or run
-correctly.)
-
@menu
* Ugly Implicit Argument Conversion:: Disabled via @samp{-fno-ugly-args}.
* Ugly Assumed-Size Arrays:: Enabled via @samp{-fugly-assumed}.
@@ -7684,8 +7083,9 @@ without conversion.
@node Ugly Null Arguments
@subsection Ugly Null Arguments
-@cindex trailing commas
-@cindex commas, trailing
+@cindex trailing comma
+@cindex comma, trailing
+@cindex characters, comma
@cindex null arguments
@cindex arguments, null
@@ -7842,7 +7242,7 @@ ASSIGN 10 TO I
Normally, for portability and improved diagnostics, @code{g77}
reserves distinct storage for a ``sibling'' of @samp{I}, used
only for @code{ASSIGN} statements to that variable (along with
-the corresponding assigned-@code{GOTO} and assigned-@samp{FORMAT}-I/O
+the corresponding assigned-@code{GOTO} and assigned-@code{FORMAT}-I/O
statements that reference the variable).
However, some code (that violates the ANSI FORTRAN 77 standard)
@@ -7899,6 +7299,7 @@ of work!}
@menu
* Compiler Limits::
+* Run-time Environment Limits::
* Compiler Types::
* Compiler Constants::
* Compiler Intrinsics::
@@ -7917,6 +7318,8 @@ symbols in a program, and so on.
@cindex -Nl option
@cindex options, -Nx
@cindex -Nx option
+@cindex limits, continuation lines
+@cindex limits, lengths of names
For example, some other Fortran compiler have an option
(such as @samp{-Nl@var{x}}) to increase the limit on the
number of continuation lines.
@@ -7932,9 +7335,315 @@ limits in these areas.
@cindex maximum rank
@cindex number of dimensions, maximum
@cindex maximum number of dimensions
+@cindex limits, rank
+@cindex limits, array dimensions
@code{g77} does currently limit the number of dimensions in an array
to the same degree as do the Fortran standards---seven (7).
-This restriction might well be lifted in a future version.
+This restriction might be lifted in a future version.
+
+@node Run-time Environment Limits
+@section Run-time Environment Limits
+@cindex limits, run-time library
+@cindex wraparound
+
+As a portable Fortran implementation,
+@code{g77} offers its users direct access to,
+and otherwise depends upon,
+the underlying facilities of the system
+used to build @code{g77},
+the system on which @code{g77} itself is used to compile programs,
+and the system on which the @code{g77}-compiled program is actually run.
+(For most users, the three systems are of the same
+type---combination of operating environment and hardware---often
+the same physical system.)
+
+The run-time environment for a particular system
+inevitably imposes some limits on a program's use
+of various system facilities.
+These limits vary from system to system.
+
+Even when such limits might be well beyond the
+possibility of being encountered on a particular system,
+the @code{g77} run-time environment
+has certain built-in limits,
+usually, but not always, stemming from intrinsics
+with inherently limited interfaces.
+
+Currently, the @code{g77} run-time environment
+does not generally offer a less-limiting environment
+by augmenting the underlying system's own environment.
+
+Therefore, code written in the GNU Fortran language,
+while syntactically and semantically portable,
+might nevertheless make non-portable assumptions
+about the run-time environment---assumptions that
+prove to be false for some particular environments.
+
+The GNU Fortran language,
+the @code{g77} compiler and run-time environment,
+and the @code{g77} documentation
+do not yet offer comprehensive portable work-arounds for such limits,
+though programmers should be able to
+find their own in specific instances.
+
+Not all of the limitations are described in this document.
+Some of the known limitations include:
+
+@menu
+* Timer Wraparounds::
+* Year 2000 (Y2K) Problems::
+* Array Size::
+* Character-variable Length::
+* Year 10000 (Y10K) Problems::
+@end menu
+
+@node Timer Wraparounds
+@subsection Timer Wraparounds
+
+Intrinsics that return values computed from system timers,
+whether elapsed (wall-clock) timers,
+process CPU timers,
+or other kinds of timers,
+are prone to experiencing wrap-around errors
+(or returning wrapped-around values from successive calls)
+due to insufficient ranges
+offered by the underlying system's timers.
+
+@cindex negative time
+@cindex short time
+@cindex long time
+Some of the symptoms of such behaviors include
+apparently negative time being computed for a duration,
+an extremely short amount of time being computed for a long duration,
+and an extremely long amount of time being computed for a short duration.
+
+See the following for intrinsics
+known to have potential problems in these areas
+on at least some systems:
+@ref{CPU_Time Intrinsic},
+@ref{DTime Intrinsic (function)}, @ref{DTime Intrinsic (subroutine)},
+@ref{ETime Intrinsic (function)}, @ref{ETime Intrinsic (subroutine)},
+@ref{MClock Intrinsic}, @ref{MClock8 Intrinsic},
+@ref{Secnds Intrinsic},
+@ref{Second Intrinsic (function)}, @ref{Second Intrinsic (subroutine)},
+@ref{System_Clock Intrinsic},
+@ref{Time Intrinsic (UNIX)}, @ref{Time Intrinsic (VXT)},
+@ref{Time8 Intrinsic}.
+
+@node Year 2000 (Y2K) Problems
+@subsection Year 2000 (Y2K) Problems
+@cindex Y2K compliance
+@cindex Year 2000 compliance
+
+While the @code{g77} compiler itself is believed to
+be Year-2000 (Y2K) compliant,
+some intrinsics are not,
+and, potentially, some underlying systems are not,
+perhaps rendering some Y2K-compliant intrinsics
+non-compliant when used on those particular systems.
+
+Fortran code that uses non-Y2K-compliant intrinsics
+(listed below)
+is, itself, almost certainly not compliant,
+and should be modified to use Y2K-compliant intrinsics instead.
+
+Fortran code that uses no non-Y2K-compliant intrinsics,
+but which currently is running on a non-Y2K-compliant system,
+can be made more Y2K compliant by compiling and
+linking it for use on a new Y2K-compliant system,
+such as a new version of an old, non-Y2K-compliant, system.
+
+Currently, information on Y2K and related issues
+is being maintained at
+@uref{http://www.gnu.org/software/year2000-list.html}.
+
+See the following for intrinsics
+known to have potential problems in these areas
+on at least some systems:
+@ref{Date Intrinsic},
+@ref{IDate Intrinsic (VXT)}.
+
+@cindex y2kbuggy
+@cindex date_y2kbuggy_0
+@cindex vxtidate_y2kbuggy_0
+@cindex G77_date_y2kbuggy_0
+@cindex G77_vxtidate_y2kbuggy_0
+The @code{libg2c} library
+shipped with any @code{g77} that warns
+about invocation of a non-Y2K-compliant intrinsic
+has renamed the @code{EXTERNAL} procedure names
+of those intrinsics.
+This is done so that
+the @code{libg2c} implementations of these intrinsics
+cannot be directly linked to
+as @code{EXTERNAL} names
+(which normally would avoid the non-Y2K-intrinsic warning).
+
+The renamed forms of the @code{EXTERNAL} names
+of these renamed procedures
+may be linked to
+by appending the string @samp{_y2kbug}
+to the name of the procedure
+in the source code.
+For example:
+
+@smallexample
+CHARACTER*20 STR
+INTEGER YY, MM, DD
+EXTERNAL DATE_Y2KBUG, VXTIDATE_Y2KBUG
+CALL DATE_Y2KBUG (STR)
+CALL VXTIDATE_Y2KBUG (MM, DD, YY)
+@end smallexample
+
+(Note that the @code{EXTERNAL} statement
+is not actually required,
+since the modified names are not recognized as intrinsics
+by the current version of @code{g77}.
+But it is shown in this specific case,
+for purposes of illustration.)
+
+The renaming of @code{EXTERNAL} procedure names of these intrinsics
+causes unresolved references at link time.
+For example, @samp{EXTERNAL DATE; CALL DATE(STR)}
+is normally compiled by @code{g77}
+as, in C, @samp{date_(&str, 20);}.
+This, in turn, links to the @code{date_} procedure
+in the @code{libE77} portion of @code{libg2c},
+which purposely calls a nonexistent procedure
+named @code{G77_date_y2kbuggy_0}.
+The resulting link-time error is designed, via this name,
+to encourage the programmer to look up the
+index entries to this portion of the @code{g77} documentation.
+
+Generally, we recommend that the @code{EXTERNAL} method
+of invoking procedures in @code{libg2c}
+@emph{not} be used.
+When used, some of the correctness checking
+normally performed by @code{g77}
+is skipped.
+
+In particular, it is probably better to use the
+@code{INTRINSIC} method of invoking
+non-Y2K-compliant procedures,
+so anyone compiling the code
+can quickly notice the potential Y2K problems
+(via the warnings printing by @code{g77})
+without having to even look at the code itself.
+
+If there are problems linking @code{libg2c}
+to code compiled by @code{g77}
+that involve the string @samp{y2kbug},
+and these are not explained above,
+that probably indicates
+that a version of @code{libg2c}
+older than @code{g77}
+is being linked to,
+or that the new library is being linked
+to code compiled by an older version of @code{g77}.
+
+That's because, as of the version that warns about
+non-Y2K-compliant intrinsic invocation,
+@code{g77} references the @code{libg2c} implementations
+of those intrinsics
+using new names, containing the string @samp{y2kbug}.
+
+So, linking newly-compiled code
+(invoking one of the intrinsics in question)
+to an old library
+might yield an unresolved reference
+to @code{G77_date_y2kbug_0}.
+(The old library calls it @code{G77_date_0}.)
+
+Similarly, linking previously-compiled code
+to a new library
+might yield an unresolved reference
+to @code{G77_vxtidate_0}.
+(The new library calls it @code{G77_vxtidate_y2kbug_0}.)
+
+The proper fix for the above problems
+is to obtain the latest release of @code{g77}
+and related products
+(including @code{libg2c})
+and install them on all systems,
+then recompile, relink, and install
+(as appropriate)
+all existing Fortran programs.
+
+(Normally, this sort of renaming is steadfastly avoided.
+In this case, however, it seems more important to highlight
+potential Y2K problems
+than to ease the transition
+of potentially non-Y2K-compliant code
+to new versions of @code{g77} and @code{libg2c}.)
+
+@node Array Size
+@subsection Array Size
+@cindex limits, array size
+@cindex array size
+
+Currently, @code{g77} uses the default @code{INTEGER} type
+for array indexes,
+which limits the sizes of single-dimension arrays
+on systems offering a larger address space
+than can be addressed by that type.
+(That @code{g77} puts all arrays in memory
+could be considered another limitation---it
+could use large temporary files---but that decision
+is left to the programmer as an implementation choice
+by most Fortran implementations.)
+
+@c ??? Investigate this, to offer a more clear statement
+@c than the following paragraphs do. -- burley 1999-02-17
+It is not yet clear whether this limitation
+never, sometimes, or always applies to the
+sizes of multiple-dimension arrays as a whole.
+
+For example, on a system with 64-bit addresses
+and 32-bit default @code{INTEGER},
+an array with a size greater than can be addressed
+by a 32-bit offset
+can be declared using multiple dimensions.
+Such an array is therefore larger
+than a single-dimension array can be,
+on the same system.
+
+@cindex limits, multi-dimension arrays
+@cindex multi-dimension arrays
+@cindex arrays, dimensioning
+Whether large multiple-dimension arrays are reliably supported
+depends mostly on the @code{gcc} back end (code generator)
+used by @code{g77}, and has not yet been fully investigated.
+
+@node Character-variable Length
+@subsection Character-variable Length
+@cindex limits, on character-variable length
+@cindex character-variable length
+
+Currently, @code{g77} uses the default @code{INTEGER} type
+for the lengths of @code{CHARACTER} variables
+and array elements.
+
+This means that, for example,
+a system with a 64-bit address space
+and a 32-bit default @code{INTEGER} type
+does not, under @code{g77},
+support a @code{CHARACTER*@var{n}} declaration
+where @var{n} is greater than 2147483647.
+
+@node Year 10000 (Y10K) Problems
+@subsection Year 10000 (Y10K) Problems
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+
+Most intrinsics returning, or computing values based on,
+date information are prone to Year-10000 (Y10K) problems,
+due to supporting only 4 digits for the year.
+
+See the following for examples:
+@ref{FDate Intrinsic (function)}, @ref{FDate Intrinsic (subroutine)},
+@ref{IDate Intrinsic (UNIX)},
+@ref{Time Intrinsic (VXT)},
+@ref{Date_and_Time Intrinsic}.
@node Compiler Types
@section Compiler Types
@@ -8470,7 +8179,7 @@ command.
of work!}
@menu
-* Interoperating with C and C++::
+* Interoperating with C and C++::
@end menu
@node Interoperating with C and C++
@@ -8511,7 +8220,7 @@ options @code{g77} passes by running @samp{g77 -v}.
@pindex f2c
@cindex cfortran.h
@cindex Netlib
-Even if you don't actually use it as a compiler, @samp{f2c} from
+Even if you don't actually use it as a compiler, @code{f2c} from
@uref{ftp://ftp.netlib.org/f2c/src}, can be a useful tool when you're
interfacing (linking) Fortran and C@.
@xref{f2c Skeletons and Prototypes,,Generating Skeletons and Prototypes with @code{f2c}}.
@@ -8538,7 +8247,7 @@ Generally, C code written to link with
called from Fortran---should @samp{#include <g2c.h>} to define the C
versions of the Fortran types.
Don't assume Fortran @code{INTEGER} types
-correspond to C @samp{int}s, for instance; instead, declare them as
+correspond to C @code{int}s, for instance; instead, declare them as
@code{integer}, a type defined by @file{g2c.h}.
@file{g2c.h} is installed where @code{gcc} will find it by
default, assuming you use a copy of @code{gcc} compatible with
@@ -8553,7 +8262,7 @@ A simple and foolproof way to write @code{g77}-callable C routines---e.g.@: to
interface with an existing library---is to write a file (named, for
example, @file{fred.f}) of dummy Fortran
skeletons comprising just the declaration of the routine(s) and dummy
-arguments plus @samp{END} statements.
+arguments plus @code{END} statements.
Then run @code{f2c} on file @file{fred.f} to produce @file{fred.c}
into which you can edit
useful code, confident the calling sequence is correct, at least.
@@ -8567,7 +8276,7 @@ as the return type of a @code{REAL} @code{FUNCTION}.)
@samp{-P} option to generate C prototypes appropriate for calling the
Fortran.@footnote{The files generated like this can also be used for
inter-unit consistency checking of dummy and actual arguments, although
-the @samp{ftnchek} tool from @uref{ftp://ftp.netlib.org/fortran}
+the @code{ftnchek} tool from @uref{ftp://ftp.netlib.org/fortran}
or @uref{ftp://ftp.dsm.fordham.edu} is
probably better for this purpose.}
If the Fortran code containing any
@@ -8599,8 +8308,8 @@ avoid clashes with C++ reserved words in addition to those in C@.
@subsection Startup Code
@cindex startup code
-@cindex runtime initialization
-@cindex initialization, runtime
+@cindex run-time, initialization
+@cindex initialization, run-time
Unlike with some runtime systems,
it shouldn't be necessary
(unless there are bugs)
@@ -8813,11 +8522,11 @@ described in this section.
@cindex statements, PROGRAM
When @code{g77} compiles a main program unit, it gives it the public
-procedure name @samp{MAIN__}.
+procedure name @code{MAIN__}.
The @code{libg2c} library has the actual @code{main()} procedure
as is typical of C-based environments, and
it is this procedure that performs some initial start-up
-activity and then calls @samp{MAIN__}.
+activity and then calls @code{MAIN__}.
Generally, @code{g77} and @code{libg2c} are designed so that you need not
include a main program unit written in Fortran in your program---it
@@ -8835,10 +8544,10 @@ file @file{@value{path-libf2c}/libF77/main.c}, to see what kinds of things
might need to be done by your @code{main()} in order to provide the
Fortran environment your Fortran code is expecting.
-@cindex IARGC() intrinsic
-@cindex intrinsics, IARGC()
-@cindex GETARG() intrinsic
-@cindex intrinsics, GETARG()
+@cindex @code{IArgC} intrinsic
+@cindex intrinsics, @code{IArgC}
+@cindex @code{GetArg} intrinsic
+@cindex intrinsics, @code{GetArg}
For example, @code{libg2c}'s @code{main()} sets up the information used by
the @code{IARGC} and @code{GETARG} intrinsics.
Bypassing @code{libg2c}'s @code{main()}
@@ -8859,7 +8568,7 @@ Fortran code.
The standard way to get around this problem is to set a break
point (a one-time, or temporary, break point will do) at
-the entrance to @samp{MAIN__}, and then run the program.
+the entrance to @code{MAIN__}, and then run the program.
A convenient way to do so is to add the @code{gdb} command
@example
@@ -8876,7 +8585,7 @@ unit of your program.
Of course, if you really want to set a break point at some
other place in your program and just start the program
-running, without first breaking at @samp{MAIN__},
+running, without first breaking at @code{MAIN__},
that should work fine.
@node Procedures
@@ -9009,7 +8718,7 @@ functions return @code{float}.
@node Names
@section Names
@cindex symbol names
-@cindex transformation of symbol names
+@cindex transforming symbol names
Fortran permits each implementation to decide how to represent
names as far as how they're seen in other contexts, such as debuggers
@@ -9109,8 +8818,8 @@ could be used to inhibit the appending of the underscore to the name.
@node Common Blocks
@section Common Blocks (COMMON)
@cindex common blocks
-@cindex COMMON statement
-@cindex statements, COMMON
+@cindex @code{COMMON} statement
+@cindex statements, @code{COMMON}
@code{g77} names and lays out @code{COMMON} areas
the same way @code{f2c} does,
@@ -9224,7 +8933,7 @@ previous method in the documentation.)
@node Complex Variables
@section Complex Variables (COMPLEX)
@cindex complex variables
-@cindex imaginary part of complex
+@cindex imaginary part
@cindex COMPLEX statement
@cindex statements, COMPLEX
@@ -9252,11 +8961,6 @@ mode afterward.
(In @code{gdb}, this is accomplished via @samp{set lang c} and
either @samp{set lang fortran} or @samp{set lang auto}.)
-@emph{Note:} Compiling with the @samp{-fno-emulate-complex} option
-avoids the debugging problem, but is known to cause other problems
-like compiler crashes and generation of incorrect code, so it is
-not recommended.
-
@node Arrays
@section Arrays (DIMENSION)
@cindex DIMENSION statement
@@ -9678,7 +9382,7 @@ Instead, make a separate @code{INCLUDE} file that defines
so you can more easily change the actual numbers in the future.
The information below is culled from the definition
-of @samp{F_err} in @file{f/runtime/libI77/err.c} in the
+of @code{F_err} in @file{f/runtime/libI77/err.c} in the
@code{g77} source tree.
@smallexample
@@ -9772,7 +9476,8 @@ is not intended to be comprehensive.
@menu
* Language Extensions:: Features used by Fortran code.
-* Compiler Options:: Features helpful during development.
+* Diagnostic Abilities:: Abilities to spot problems early.
+* Compiler Options:: Features helpful to accommodate legacy code, etc.
* Compiler Speed:: Speed of the compilation process.
* Program Speed:: Speed of the generated, optimized code.
* Ease of Debugging:: Debugging ease-of-use at the source level.
@@ -9782,25 +9487,114 @@ is not intended to be comprehensive.
@node Language Extensions
@subsection Language Extensions
-@code{g77} offers several extensions to the Fortran language that @code{f2c}
-doesn't.
+@code{g77} offers several extensions to FORTRAN 77 language that @code{f2c}
+doesn't:
+
+@itemize @bullet
+@item
+Automatic arrays
+
+@item
+@code{CYCLE} and @code{EXIT}
+
+@item
+Construct names
+
+@item
+@code{SELECT CASE}
+
+@item
+@code{KIND=} and @code{LEN=} notation
+
+@item
+Semicolon as statement separator
+
+@item
+Constant expressions in @code{FORMAT} statements
+(such as @samp{FORMAT(I<J>)},
+where @samp{J} is a @code{PARAMETER} named constant)
+
+@item
+@code{MvBits} intrinsic
+
+@item
+@code{libU77} (Unix-compatibility) library,
+with routines known to compiler as intrinsics
+(so they work even when compiler options are used
+to change the interfaces used by Fortran routines)
+@end itemize
+
+@code{g77} also implements iterative @code{DO} loops
+so that they work even in the presence of certain ``extreme'' inputs,
+unlike @code{f2c}.
+@xref{Loops}.
+
+However, @code{f2c} offers a few that @code{g77} doesn't, such as:
+
+@itemize @bullet
+@item
+Intrinsics in @code{PARAMETER} statements
+
+@item
+Array bounds expressions (such as @samp{REAL M(N(2))})
+
+@item
+@code{AUTOMATIC} statement
+@end itemize
-However, @code{f2c} offers a few that @code{g77} doesn't, like
-fairly complete support for @code{INTEGER*2}.
It is expected that @code{g77} will offer some or all of these missing
features at some time in the future.
-(Version 0.5.18 of @code{g77} offers some rudimentary support for some
-of these features.)
+
+@node Diagnostic Abilities
+@subsection Diagnostic Abilities
+
+@code{g77} offers better diagnosis of problems in @code{FORMAT} statements.
+@code{f2c} doesn't, for example, emit any diagnostic for
+@samp{FORMAT(XZFAJG10324)},
+leaving that to be diagnosed, at run time, by
+the @code{libf2c} run-time library.
@node Compiler Options
@subsection Compiler Options
-@code{g77} offers a whole bunch of compiler options that @code{f2c} doesn't.
+@code{g77} offers compiler options that @code{f2c} doesn't,
+most of which are designed to more easily accommodate
+legacy code:
+
+@itemize @bullet
+@item
+Two that control the automatic appending of extra
+underscores to external names
+
+@item
+One that allows dollar signs (@samp{$}) in symbol names
+
+@item
+A variety that control acceptance of various
+``ugly'' constructs
+
+@item
+Several that specify acceptable use of upper and lower case
+in the source code
+
+@item
+Many that enable, disable, delete, or hide
+groups of intrinsics
-However, @code{f2c} offers a few that @code{g77} doesn't, like an
-option to generate code to check array subscripts at run time.
-It is expected that @code{g77} will offer some or all of these
-missing options at some time in the future.
+@item
+One to specify the length of fixed-form source lines
+(normally 72)
+
+@item
+One to specify the the source code is written in
+Fortran-90-style free-form
+@end itemize
+
+However, @code{f2c} offers a few that @code{g77} doesn't,
+like an option to have @code{REAL} default to @code{REAL*8}.
+It is expected that @code{g77} will offer all of the
+missing options pertinent to being a Fortran compiler
+at some time in the future.
@node Compiler Speed
@subsection Compiler Speed
@@ -9948,8 +9742,8 @@ Microsoft's rumored patent on the digits 0 and 1 is upheld.)
@cindex BLOCK DATA statement
@cindex statements, BLOCK DATA
@cindex libraries, containing BLOCK DATA
-@cindex @code{f2c} compatibility
-@cindex compatibility, @code{f2c}
+@cindex f2c compatibility
+@cindex compatibility, f2c
To ensure that block data program units are linked, especially a concern
when they are put into libraries, give each one a name (as in
@@ -10049,7 +9843,7 @@ The meaning of a @code{DO} loop in Fortran is precisely specified
in the Fortran standard@dots{}and is quite different from what
many programmers might expect.
-In particular, Fortran indexed @code{DO} loops are implemented as if
+In particular, Fortran iterative @code{DO} loops are implemented as if
the number of trips through the loop is calculated @emph{before}
the loop is entered.
@@ -10233,7 +10027,7 @@ tracking down bugs in such programs.
* Aliasing Assumed To Work::
* Output Assumed To Flush::
* Large File Unit Numbers::
-* Floating point precision::
+* Floating-point precision::
* Inconsistent Calling Sequences::
@end menu
@@ -10292,7 +10086,7 @@ are given types and then evaluated.
@node Variables Assumed To Be Zero
@subsection Variables Assumed To Be Zero
@cindex zero-initialized variables
-@cindex variables assumed to be zero
+@cindex variables, assumed to be zero
@cindex uninitialized variables
Many Fortran programs were developed on systems that provided
@@ -10317,7 +10111,7 @@ options using @code{g77}.
@node Variables Assumed To Be Saved
@subsection Variables Assumed To Be Saved
-@cindex variables retaining values across calls
+@cindex variables, retaining values across calls
@cindex saved variables
@cindex static variables
@@ -10590,7 +10384,7 @@ it provides either form of detection are welcome.
For several versions prior to 0.5.20, @code{g77} configured its
version of the @code{libf2c} run-time library so that one of
-its configuration macros, @samp{ALWAYS_FLUSH}, was defined.
+its configuration macros, @code{ALWAYS_FLUSH}, was defined.
This was done as a result of a belief that many programs expected
output to be flushed to the operating system (under UNIX, via
@@ -10615,7 +10409,7 @@ non-flushing library routines.)
@xref{Always Flush Output}, for information on how to modify
the @code{g77} source tree so that a version of @code{libg2c}
-can be built and installed with the @samp{ALWAYS_FLUSH} macro defined.
+can be built and installed with the @code{ALWAYS_FLUSH} macro defined.
@node Large File Unit Numbers
@subsection Large File Unit Numbers
@@ -10634,13 +10428,13 @@ file unit number that is out of the range accepted by
@code{libg2c}.
Normally, this range is 0 through 99, and the high end
of the range is controlled by a @code{libg2c} source-file
-macro named @samp{MXUNIT}.
+macro named @code{MXUNIT}.
If you can easily change your program to use unit numbers
in the range 0 through 99, you should do so.
Otherwise, see @ref{Larger File Unit Numbers}, for information on how
-to change @samp{MXUNIT} in @code{libg2c} so you can build and
+to change @code{MXUNIT} in @code{libg2c} so you can build and
install a new version of @code{libg2c} that supports the larger
unit numbers you need.
@@ -10652,23 +10446,26 @@ open by a running program.
Information on how to increase these limits should be found
in your system's documentation.
-@node Floating point precision
-@subsection Floating point precision
+@node Floating-point precision
+@subsection Floating-point precision
-@cindex IEEE 754
-@cindex IEEE conformance
-@cindex conformance, IEEE
-@cindex floating point precision
-If your program depends on exact IEEE 754 floating point handling it may
+@cindex IEEE 754 conformance
+@cindex conformance, IEEE 754
+@cindex floating-point, precision
+@cindex ix86 floating-point
+@cindex x86 floating-point
+If your program depends on exact IEEE 754 floating-point handling it may
help on some systems---specifically x86 or m68k hardware---to use
-the @code{-ffloat-store} option or to reset the precision flag on the
-floating point unit @xref{Optimize Options}.
+the @samp{-ffloat-store} option or to reset the precision flag on the
+floating-point unit.
+@xref{Optimize Options}.
However, it might be better simply to put the FPU into double precision
-mode and not take the performance hit of @code{-ffloat-store}. On x86
+mode and not take the performance hit of @samp{-ffloat-store}. On x86
and m68k GNU systems you can do this with a technique similar to that
-for turning on floating point exceptions @xref{Floating-point Exception
-Handling}. The control word could be set to double precision by
+for turning on floating-point exceptions
+(@pxref{Floating-point Exception Handling}).
+The control word could be set to double precision by
replacing the @code{__setfpucw} call with one like this:
@smallexample
__setfpucw ((_FPU_DEFAULT & ~_FPU_EXTENDED) | _FPU_DOUBLE);
@@ -10677,34 +10474,30 @@ replacing the @code{__setfpucw} call with one like this:
maths library, but we have no evidence of it causing trouble.)
Some targets (such as the Alpha) may need special options for full IEEE
-conformance @xref{Submodel Options,,Hardware Models and
-Configurations,gcc,Using and Porting GNU CC}.
+conformance.
+@xref{Submodel Options,,Hardware Models and Configurations,gcc,Using and Porting GNU CC}.
@node Inconsistent Calling Sequences
@subsection Inconsistent Calling Sequences
@pindex ftnchek
-@cindex floating point errors
+@cindex floating-point, errors
+@cindex ix86 FPU stack
@cindex x86 FPU stack
Code containing inconsistent calling sequences in the same file is
-normally rejected @xref{GLOBALS}. (Use, say, @code{ftnchek} to ensure
-consistency across source files
-@c makeinfo 1.68 objects to the nested parens
-@ifinfo
-@xref{f2c Skeletons and Prototypes}.)
-@end ifinfo
-@ifnotinfo
+normally rejected---see @ref{GLOBALS}.
+(Use, say, @code{ftnchek} to ensure
+consistency across source files.
@xref{f2c Skeletons and Prototypes,,
-{Generating Skeletons and Prototypes with @code{f2c}}}.)
-@end ifnotinfo
+Generating Skeletons and Prototypes with @code{f2c}}.)
Mysterious errors, which may appear to be code generation problems, can
appear specifically on the x86 architecture with some such
-inconsistencies. On x86 hardware, floating point return values of
-functions are placed on the floating point unit's register stack, not
+inconsistencies. On x86 hardware, floating-point return values of
+functions are placed on the floating-point unit's register stack, not
the normal stack. Thus calling a @code{REAL} or @code{DOUBLE PRECISION}
@code{FUNCTION} as some other sort of procedure, or vice versa,
-scrambles the floating point stack. This may break unrelated code
+scrambles the floating-point stack. This may break unrelated code
executed later. Similarly if, say, external C routines are written
incorrectly.
@@ -10784,15 +10577,6 @@ Currently, @code{g77} supports only automatic arrays, not
@code{RECURSIVE} procedures or other means of explicitly
specifying that variables or arrays are automatic.
-@cindex -fugly option
-@cindex options, -fugly
-@item -fugly
-Fix the source code so that @samp{-fno-ugly} will work.
-Note that, for many programs, it is difficult to practically
-avoid using the features enabled via @samp{-fugly-init}, and these
-features pose the lowest risk of writing nonportable code, among the
-various ``ugly'' features.
-
@cindex -f@var{group}-intrinsics-hide option
@cindex options, -f@var{group}-intrinsics-hide
@item -f@var{group}-intrinsics-hide
@@ -10803,7 +10587,7 @@ It is easy to find these using @samp{-f@var{group}-intrinsics-disable}.
@node Faster Programs
@section Faster Programs
-@cindex speeding up programs
+@cindex speed, of programs
@cindex programs, speeding up
Aside from the usual @code{gcc} options, such as @samp{-O},
@@ -10820,12 +10604,13 @@ it working).
@node Aligned Data
@subsection Aligned Data
+@cindex alignment
@cindex data, aligned
@cindex stack, aligned
@cindex aligned data
@cindex aligned stack
@cindex Pentium optimizations
-@cindex optimizations, Pentium
+@cindex optimization, for Pentium
On some systems, such as those with Pentium Pro CPUs, programs
that make heavy use of @code{REAL(KIND=2)} (@code{DOUBLE PRECISION})
@@ -10847,8 +10632,8 @@ There are a variety of approaches to use to address this problem:
@itemize @bullet
@item
-@cindex COMMON, layout
-@cindex layout of common blocks
+@cindex @code{COMMON} layout
+@cindex layout of @code{COMMON} blocks
Order your @code{COMMON} and @code{EQUIVALENCE} areas such
that the variables and arrays with the widest alignment
guidelines come first.
@@ -10878,7 +10663,7 @@ avoid having to carefully count the number of bytes
occupied by each entity to determine whether the
actual alignment of each subsequent entity meets the
alignment guidelines for the type of that entity.
-
+
If you don't ensure correct alignment of @code{COMMON} elements, the
compiler may be forced by some systems to violate the Fortran semantics by
adding padding to get @code{DOUBLE PRECISION} data properly aligned.
@@ -10921,12 +10706,6 @@ of the FORTRAN 77 standard,
or uses @code{EQUIVALENCE} or different layouts
in ways that assume no padding is ever inserted by the compiler.
-@emph{Note:} @samp{-malign-double} applies only to
-statically-allocated data.
-Double-precision data on the stack can still
-cause problems due to misalignment.
-@xref{Aligned Data}.
-
@item
Ensure that @file{crt0.o} or @file{crt1.o}
on your system guarantees a 64-bit
@@ -10943,6 +10722,13 @@ Progress is being made on making this work
@code{gcc}, and some of the relevant operating systems
(such as GNU/Linux).
+@cindex alignment testing
+@cindex testing alignment
+A package that tests the degree to which a Fortran compiler
+(such as @code{g77})
+aligns 64-bit floating-point variables and arrays
+is available at @uref{ftp://alpha.gnu.org/gnu/g77/align/}.
+
@node Prefer Automatic Uninitialized Variables
@subsection Prefer Automatic Uninitialized Variables
@@ -10988,30 +10774,25 @@ compiler, typically @code{gcc}.)
@node Use Submodel Options
@subsection Use Submodel Options
-@cindex Pentium optimizations
-@cindex optimizations, Pentium
-@cindex 586/686 CPUs
@cindex submodels
Using an appropriate @samp{-m} option to generate specific code for your
CPU may be worthwhile, though it may mean the executable won't run on
other versions of the CPU that don't support the same instruction set.
@xref{Submodel Options,,Hardware Models and Configurations,gcc,Using and
-Porting GNU CC}.
+Porting GNU CC}. For instance on an x86 system the compiler might have
+been built---as shown by @samp{g77 -v}---for the target
+@samp{i386-pc-linux-gnu}, i.e.@: an @samp{i386} CPU@. In that case to
+generate code best optimized for a Pentium you could use the option
+@samp{-march=pentium}.
-For recent CPUs that don't have explicit support in
-the released version of @code{gcc}, it may still be possible to get
-improvements.
-For instance, the flags recommended for 586/686
-(Pentium(Pro)) chips for building the Linux kernel are:
+For recent CPUs that don't have explicit support in the released version
+of @code{gcc}, it @emph{might} still be possible to get improvements
+with certain @samp{-m} options.
-@smallexample
--m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2
--fomit-frame-pointer
-@end smallexample
-
-@noindent @samp{-fomit-frame-pointer} will, however, inhibit debugging
-on x86 systems.
+@samp{-fomit-frame-pointer} can help performance on x86 systems and
+others. It will, however, inhibit debugging on the systems on which it
+is not turned on anyway by @samp{-O}.
@node Trouble
@chapter Known Causes of Trouble with GNU Fortran
@@ -11033,20 +10814,20 @@ or installing @code{g77} is not provided here.
@xref{Problems Installing}.
To find out about major bugs discovered in the current release and
-possible workarounds for them, retrieve
+possible workarounds for them, see
@uref{ftp://alpha.gnu.org/g77.plan}.
(Note that some of this portion of the manual is lifted
directly from the @code{gcc} manual, with minor modifications
to tailor it to users of @code{g77}.
Anytime a bug seems to have more to do with the @code{gcc}
-portion of @code{g77},
-@xref{Trouble,,Known Causes of Trouble with GNU CC,
+portion of @code{g77}, see
+@ref{Trouble,,Known Causes of Trouble with GNU CC,
gcc,Using and Porting GNU CC}.)
@menu
* But-bugs:: Bugs really in other programs or elsewhere.
-* Actual Bugs:: Bugs and misfeatures we will fix later.
+* Known Bugs:: Bugs known to be in this version of @code{g77}.
* Missing Features:: Features we already know we want to add later.
* Disappointments:: Regrettable things we can't change.
* Non-bugs:: Things we think are right, but some others disagree.
@@ -11140,7 +10921,7 @@ How to cope with such problems is well beyond the scope
of this manual.
However, users of Linux-based systems (such as GNU/Linux)
-should review @uref{http://www.bitwizard.nl/sig11}, a source
+should review @uref{http://www.bitwizard.nl/sig11/}, a source
of detailed information on diagnosing hardware problems,
by recognizing their common symptoms.
@@ -11155,8 +10936,8 @@ a reference to it in future versions of this manual.
@cindex unresolved reference (various)
@cindex linking error for user code
@cindex code, user
-@cindex ld error for user code
-@cindex ld can't find strange names
+@cindex @code{ld}, error linking user code
+@cindex @code{ld}, can't find strange names
On some systems, perhaps just those with out-of-date (shared?)
libraries, unresolved-reference errors happen when linking @code{g77}-compiled
programs (which should be done using @code{g77}).
@@ -11172,10 +10953,10 @@ systems where @samp{-lg2c -lm} is insufficient to resolve code produced
by @code{g77}.
@cindex undefined reference (_main)
-@cindex linking error for user code
-@cindex ld error for user code
+@cindex linking error, user code
+@cindex @code{ld}, error linking user code
@cindex code, user
-@cindex ld can't find _main
+@cindex @code{ld}, can't find @samp{_main}
If your program doesn't link due to unresolved references to names
like @samp{_main}, make sure you're using the @code{g77} command to do the
link, since this command ensures that the necessary libraries are
@@ -11192,8 +10973,8 @@ command line, in case that helps.
@subsection Large Common Blocks
@cindex common blocks, large
@cindex large common blocks
-@cindex linker errors
-@cindex ld errors
+@cindex linking, errors
+@cindex @code{ld}, errors
@cindex errors, linker
On some older GNU/Linux systems, programs with common blocks larger
than 16MB cannot be linked without some kind of error
@@ -11204,7 +10985,7 @@ more recent versions of @code{binutils}, such as version 2.6.
@node Debugger Problems
@subsection Debugger Problems
-@cindex @code{gdb} support
+@cindex @code{gdb}, support
@cindex support, @code{gdb}
There are some known problems when using @code{gdb} on code
compiled by @code{g77}.
@@ -11274,7 +11055,7 @@ not enough.)
@node Stack Overflow
@subsection Stack Overflow
-@cindex stack overflow
+@cindex stack, overflow
@cindex segmentation violation
@code{g77} code might fail at runtime (probably with a ``segmentation
violation'') due to overflowing the stack.
@@ -11326,9 +11107,9 @@ simply too large for the system, or buggy.)
@node Nothing Happens
@subsection Nothing Happens
@cindex nothing happens
-@cindex naming programs @samp{test}
-@cindex @samp{test} programs
-@cindex programs named @samp{test}
+@cindex naming programs
+@cindex @code{test} programs
+@cindex programs, @code{test}
It is occasionally reported that a ``simple'' program,
such as a ``Hello, World!'' program, does nothing when
it is run, even though the compiler reported no errors,
@@ -11336,7 +11117,7 @@ despite the program containing nothing other than a
simple @code{PRINT} statement.
This most often happens because the program has been
-compiled and linked on a UNIX system and named @samp{test},
+compiled and linked on a UNIX system and named @code{test},
though other names can lead to similarly unexpected
run-time behavior on various systems.
@@ -11392,6 +11173,8 @@ themselves as @emph{visible} problems some time later.
Overflowing the bounds of an array---usually by writing beyond
the end of it---is one of two kinds of bug that often occurs
in Fortran code.
+(Compile your code with the @samp{-fbounds-check} option
+to catch many of these kinds of errors at program run time.)
The other kind of bug is a mismatch between the actual arguments
passed to a procedure and the dummy arguments as declared by that
@@ -11405,18 +11188,20 @@ That is, these bugs can be quite sensitive to data, including
data representing the placement of other data in memory (that is,
pointers, such as the placement of stack frames in memory).
-Plans call for improving @code{g77} so that it can offer the
+@code{g77} now offers the
ability to catch and report some of these problems at compile, link, or
run time, such as by generating code to detect references to
-beyond the bounds of an array, or checking for agreement between
-calling and called procedures.
+beyond the bounds of most arrays (except assumed-size arrays),
+and checking for agreement between calling and called procedures.
+Future improvements are likely to be made in the procedure-mismatch area,
+at least.
In the meantime, finding and fixing the programming
bugs that lead to these behaviors is, ultimately, the user's
responsibility, as difficult as that task can sometimes be.
-@cindex ``infinite spaces'' printed
-@cindex spaces, endless printing of
+@cindex infinite spaces printed
+@cindex space, endless printing of
@cindex libc, non-ANSI or non-default
@cindex C library
@cindex linking against non-standard library
@@ -11503,7 +11288,7 @@ used by @code{g77}, handles only double-precision values.
Since @samp{0.2} in the program is a single-precision value, it
is converted to double precision (still in binary notation)
before being converted back to decimal.
-The conversion to binary appends _binary_ zero digits to the
+The conversion to binary appends @emph{binary} zero digits to the
original value---which, again, is an inexact approximation of
0.2---resulting in an approximation that is much less exact
than is connoted by the use of double precision.
@@ -11548,15 +11333,15 @@ with that produced by some other Fortran implementations.
A useful source of information on floating-point computation is David
Goldberg, `What Every Computer Scientist Should Know About
Floating-Point Arithmetic', Computing Surveys, 23, March 1991, pp.@:
-5--48.
+5-48.
An online version is available at
-@uref{http://docs.sun.com},
+@uref{http://docs.sun.com/},
and there is a supplemented version, in PostScript form, at
@uref{http://www.validgh.com/goldberg/paper.ps}.
Information related to the IEEE 754
floating-point standard by a leading light can be found at
-@uref{http://http.cs.berkeley.edu/%7Ewkahan/ieee754status};
+@uref{http://http.cs.berkeley.edu/%7Ewkahan/ieee754status/};
see also slides from the short course referenced from
@uref{http://http.cs.berkeley.edu/%7Efateman/}.
@uref{http://www.linuxsupportline.com/%7Ebillm/} has a brief
@@ -11588,7 +11373,7 @@ as an option, or perhaps even as the default behavior.)
The GNU C library provides routines for controlling the FPU, and other
documentation about this.
-@xref{Floating point precision}, regarding IEEE 754 conformance.
+@xref{Floating-point precision}, regarding IEEE 754 conformance.
@include bugs.texi
@@ -11604,6 +11389,7 @@ GNU Fortran language:
* Better Source Model::
* Fortran 90 Support::
* Intrinsics in PARAMETER Statements::
+* Arbitrary Concatenation::
* SELECT CASE on CHARACTER Type::
* RECURSIVE Keyword::
* Popular Non-standard Types::
@@ -11611,6 +11397,7 @@ GNU Fortran language:
* Array Bounds Expressions::
* POINTER Statements::
* Sensible Non-standard Constructs::
+* READONLY Keyword::
* FLUSH Statement::
* Expressions in FORMAT Statements::
* Explicit Assembler Code::
@@ -11622,9 +11409,11 @@ GNU Fortran dialects:
* STRUCTURE UNION RECORD MAP::
* OPEN CLOSE and INQUIRE Keywords::
* ENCODE and DECODE::
+* AUTOMATIC Statement::
* Suppressing Space Padding::
* Fortran Preprocessor::
* Bit Operations on Floating-point Data::
+* Really Ugly Character Assignments::
New facilities:
* POSIX Standard::
@@ -11633,8 +11422,10 @@ New facilities:
* Large Automatic Arrays::
* Support for Threads::
* Increasing Precision/Range::
+* Enabling Debug Lines::
Better diagnostics:
+* Better Warnings::
* Gracefully Handle Sensible Bad Code::
* Non-standard Conversions::
* Non-standard Intrinsics::
@@ -11650,8 +11441,9 @@ Better diagnostics:
Run-time facilities:
* Uninitialized Variables at Run Time::
-* Bounds Checking at Run Time::
* Portable Unformatted Files::
+* Better List-directed I/O::
+* Default to Console I/O::
Debugging:
* Labels Visible to Debugger::
@@ -11695,11 +11487,11 @@ but one of the most frequent bugs encountered by new users is
accidentally writing fixed-form source code into and beyond
column 73.
So, maybe the users of old code would be able to more easily handle
-having to specify, say, a @code{-Wno-col73to80} option.
+having to specify, say, a @samp{-Wno-col73to80} option.
@node Fortran 90 Support
@subsection Fortran 90 Support
-@cindex Fortran 90 support
+@cindex Fortran 90, support
@cindex support, Fortran 90
@code{g77} does not support many of the features that
@@ -11743,6 +11535,22 @@ But, if the @code{gcc} back end is enhanced to provide
such a facility, @code{g77} will likely use that facility
in implementing this feature soon afterwards.
+@node Arbitrary Concatenation
+@subsection Arbitrary Concatenation
+@cindex concatenation
+@cindex CHARACTER*(*)
+@cindex run-time, dynamic allocation
+
+@code{g77} doesn't support arbitrary operands for concatenation
+in contexts where run-time allocation is required.
+For example:
+
+@smallexample
+SUBROUTINE X(A)
+CHARACTER*(*) A
+CALL FOO(A // 'suffix')
+@end smallexample
+
@node SELECT CASE on CHARACTER Type
@subsection @code{SELECT CASE} on @code{CHARACTER} Type
@@ -11767,6 +11575,7 @@ but the result is not pretty.
@node Increasing Precision/Range
@subsection Increasing Precision/Range
@cindex -r8
+@cindex -qrealsize=8
@cindex -i8
@cindex f2c
@cindex increasing precision
@@ -11776,7 +11585,8 @@ but the result is not pretty.
@cindex Toolpack
@cindex Netlib
-Some compilers, such as @code{f2c}, have an option (@samp{-r8} or
+Some compilers, such as @code{f2c}, have an option (@samp{-r8},
+@samp{-qrealsize=8} or
similar) that provides automatic treatment of @code{REAL}
entities such that they have twice the storage size, and
a corresponding increase in the range and precision, of what
@@ -11809,8 +11619,10 @@ alleviate this problem).
@node Popular Non-standard Types
@subsection Popular Non-standard Types
-@cindex INTEGER*2 support
-@cindex LOGICAL*1 support
+@cindex @code{INTEGER*2} support
+@cindex types, @code{INTEGER*2}
+@cindex @code{LOGICAL*1} support
+@cindex types, @code{LOGICAL*1}
@code{g77} doesn't fully support @code{INTEGER*2}, @code{LOGICAL*1},
and similar.
@@ -11822,7 +11634,10 @@ for them.
@node Full Support for Compiler Types
@subsection Full Support for Compiler Types
-@cindex REAL*16 support
+@cindex @code{REAL*16} support
+@cindex types, @code{REAL*16}
+@cindex @code{INTEGER*8} support
+@cindex types, @code{INTEGER*8}
@code{g77} doesn't support @code{INTEGER}, @code{REAL}, and @code{COMPLEX} equivalents
for @emph{all} applicable back-end-supported types (@code{char}, @code{short int},
@code{int}, @code{long int}, @code{long long int}, and @code{long double}).
@@ -11838,8 +11653,8 @@ This is scheduled for version 0.6.
@cindex array elements, in adjustable array bounds
@cindex function references, in adjustable array bounds
@cindex array bounds, adjustable
-@cindex DIMENSION statement
-@cindex statements, DIMENSION
+@cindex @code{DIMENSION} statement
+@cindex statements, @code{DIMENSION}
@code{g77} doesn't support more general expressions to dimension
arrays, such as array element references, function
@@ -11931,6 +11746,34 @@ specification of an attribute), please submit a
bug report with an explanation, so we can consider
fixing @code{g77} just for cases like yours.
+@node READONLY Keyword
+@subsection @code{READONLY} Keyword
+@cindex READONLY
+
+Support for @code{READONLY}, in @code{OPEN} statements,
+requires @code{libg2c} support,
+to make sure that @samp{CLOSE(@dots{},STATUS='DELETE')}
+does not delete a file opened on a unit
+with the @code{READONLY} keyword,
+and perhaps to trigger a fatal diagnostic
+if a @code{WRITE} or @code{PRINT}
+to such a unit is attempted.
+
+@emph{Note:} It is not sufficient for @code{g77} and @code{libg2c}
+(its version of @code{libf2c})
+to assume that @code{READONLY} does not need some kind of explicit support
+at run time,
+due to UNIX systems not (generally) needing it.
+@code{g77} is not just a UNIX-based compiler!
+
+Further, mounting of non-UNIX filesystems on UNIX systems
+(such as via NFS)
+might require proper @code{READONLY} support.
+
+@cindex SHARED
+(Similar issues might be involved with supporting the @code{SHARED}
+keyword.)
+
@node FLUSH Statement
@subsection @code{FLUSH} Statement
@@ -12073,7 +11916,7 @@ require much more work on @code{libg2c}.
@cindex FORM='PRINT'
@cindex ANS carriage control
-@cindex carraige control
+@cindex carriage control
@pindex asa
@pindex fpr
@code{g77} doesn't support @code{FORM='PRINT'} or an equivalent to
@@ -12148,6 +11991,44 @@ with:
It is entirely possible that @code{ENCODE} and @code{DECODE} will
be supported by a future version of @code{g77}.
+@node AUTOMATIC Statement
+@subsection @code{AUTOMATIC} Statement
+@cindex @code{AUTOMATIC} statement
+@cindex statements, @code{AUTOMATIC}
+@cindex automatic variables
+@cindex variables, automatic
+
+@code{g77} doesn't support the @code{AUTOMATIC} statement that
+@code{f2c} does.
+
+@code{AUTOMATIC} would identify a variable or array
+as not being @code{SAVE}'d, which is normally the default,
+but which would be especially useful for code that, @emph{generally},
+needed to be compiled with the @samp{-fno-automatic} option.
+
+@code{AUTOMATIC} also would serve as a hint to the compiler that placing
+the variable or array---even a very large array--on the stack is acceptable.
+
+@code{AUTOMATIC} would not, by itself, designate the containing procedure
+as recursive.
+
+@code{AUTOMATIC} should work syntactically like @code{SAVE},
+in that @code{AUTOMATIC} with no variables listed should apply to
+all pertinent variables and arrays
+(which would not include common blocks or their members).
+
+Variables and arrays denoted as @code{AUTOMATIC}
+would not be permitted to be initialized via @code{DATA}
+or other specification of any initial values,
+requiring explicit initialization,
+such as via assignment statements.
+
+@cindex UNSAVE
+@cindex STATIC
+Perhaps @code{UNSAVE} and @code{STATIC},
+as strict semantic opposites to @code{SAVE} and @code{AUTOMATIC},
+should be provided as well.
+
@node Suppressing Space Padding
@subsection Suppressing Space Padding of Source Lines
@@ -12194,18 +12075,18 @@ files included via the @code{INCLUDE} directive.
@node Bit Operations on Floating-point Data
@subsection Bit Operations on Floating-point Data
-@cindex AND intrinsic
-@cindex intrinsics, AND
-@cindex OR intrinsic
-@cindex intrinsics, OR
-@cindex SHIFT intrinsic
-@cindex intrinsics, SHIFT
+@cindex @code{And} intrinsic
+@cindex intrinsics, @code{And}
+@cindex @code{Or} intrinsic
+@cindex intrinsics, @code{Or}
+@cindex @code{Shift} intrinsic
+@cindex intrinsics, @code{Shift}
@code{g77} does not allow @code{REAL} and other non-integral types for
-arguments to intrinsics like @code{AND}, @code{OR}, and @code{SHIFT}.
+arguments to intrinsics like @code{And}, @code{Or}, and @code{Shift}.
For example, this program is rejected by @code{g77}, because
-the intrinsic @code{IAND} does not accept @code{REAL} arguments:
+the intrinsic @code{Iand} does not accept @code{REAL} arguments:
@smallexample
DATA A/7.54/, B/9.112/
@@ -12213,6 +12094,24 @@ PRINT *, IAND(A, B)
END
@end smallexample
+@node Really Ugly Character Assignments
+@subsection Really Ugly Character Assignments
+
+An option such as @samp{-fugly-char} should be provided
+to allow
+
+@smallexample
+REAL*8 A1
+DATA A1 / '12345678' /
+@end smallexample
+
+and:
+
+@smallexample
+REAL*8 A1
+A1 = 'ABCDEFGH'
+@end smallexample
+
@node POSIX Standard
@subsection @code{POSIX} Standard
@@ -12220,8 +12119,8 @@ END
@node Floating-point Exception Handling
@subsection Floating-point Exception Handling
-@cindex floating point exceptions
-@cindex exceptions, floating point
+@cindex floating-point, exceptions
+@cindex exceptions, floating-point
@cindex FPE handling
@cindex NaN values
@@ -12254,7 +12153,7 @@ A convenient trick is to compile this something like:
@smallexample
gcc -o libtrapfpe.a trapfpe.c
@end smallexample
-and then use it by adding @code{-trapfpe} to the @code{g77} command line
+and then use it by adding @samp{-trapfpe} to the @code{g77} command line
when linking.
@node Nonportable Conversions
@@ -12269,7 +12168,7 @@ is type @code{REAL}), that other compilers might
quietly accept.
Some of these conversions are accepted by @code{g77}
-when the @samp{-fugly} option is specified.
+when the @samp{-fugly-logint} option is specified.
Perhaps it should accept more or all of them.
@node Large Automatic Arrays
@@ -12293,6 +12192,73 @@ are thread-safe, nor does @code{g77} have support for parallel processing
processors).
A package such as PVM might help here.
+@node Enabling Debug Lines
+@subsection Enabling Debug Lines
+@cindex debug line
+@cindex comment line, debug
+
+An option such as @samp{-fdebug-lines} should be provided
+to turn fixed-form lines beginning with @samp{D}
+to be treated as if they began with a space,
+instead of as if they began with a @samp{C}
+(as comment lines).
+
+@node Better Warnings
+@subsection Better Warnings
+
+Because of how @code{g77} generates code via the back end,
+it doesn't always provide warnings the user wants.
+Consider:
+
+@smallexample
+PROGRAM X
+PRINT *, A
+END
+@end smallexample
+
+Currently, the above is not flagged as a case of
+using an uninitialized variable,
+because @code{g77} generates a run-time library call that looks,
+to the GBE, like it might actually @emph{modify} @samp{A} at run time.
+(And, in fact, depending on the previous run-time library call,
+it would!)
+
+Fixing this requires one of the following:
+
+@itemize @bullet
+@item
+Switch to new library, @code{libg77}, that provides
+a more ``clean'' interface,
+vis-a-vis input, output, and modified arguments,
+so the GBE can tell what's going on.
+
+This would provide a pretty big performance improvement,
+at least theoretically, and, ultimately, in practice,
+for some types of code.
+
+@item
+Have @code{g77} pass a pointer to a temporary
+containing a copy of @samp{A},
+instead of to @samp{A} itself.
+The GBE would then complain about the copy operation
+involving a potentially uninitialized variable.
+
+This might also provide a performance boost for some code,
+because @samp{A} might then end up living in a register,
+which could help with inner loops.
+
+@item
+Have @code{g77} use a GBE construct similar to @code{ADDR_EXPR}
+but with extra information on the fact that the
+item pointed to won't be modified
+(a la @code{const} in C).
+
+Probably the best solution for now, but not quite trivial
+to implement in the general case.
+Worth considering after @code{g77} 0.6 is considered
+pretty solid.
+@end itemize
+
@node Gracefully Handle Sensible Bad Code
@subsection Gracefully Handle Sensible Bad Code
@@ -12461,15 +12427,6 @@ some kinds of uninitialized variables at run time.
Note that use of the options @samp{-O -Wuninitialized} can catch
many such bugs at compile time.
-@node Bounds Checking at Run Time
-@subsection Bounds Checking at Run Time
-
-@code{g77} should offer run-time bounds-checking of array/subscript references
-in a fashion similar to @code{f2c}.
-
-Note that @code{g77} already warns about references to out-of-bounds
-elements of arrays when it detects these at compile time.
-
@node Portable Unformatted Files
@subsection Portable Unformatted Files
@@ -12500,6 +12457,7 @@ A number giving the length of the record contents;
@item
the length of record contents again (for backspace).
@end enumerate
+
The record length is of C type
@code{long}; this means that it is 8 bytes on 64-bit systems such as
Alpha GNU/Linux and 4 bytes on other systems, such as x86 GNU/Linux.
@@ -12519,7 +12477,7 @@ written.
Thus for exchanging a sequential or direct access unformatted file
between big- and little-endian 32-bit systems using IEEE 754 floating
point it would be sufficient to reverse the bytes in consecutive words
-in the file @emph{iff} only @code{REAL*4}, @code{COMPLEX},
+in the file if, and @emph{only} if, only @code{REAL*4}, @code{COMPLEX},
@code{INTEGER*4} and/or @code{LOGICAL*4} data have been written to it by
@code{g77}.
@@ -12540,6 +12498,49 @@ only incur overhead when they are read on a system with a different
format.) A future @code{g77} runtime library should use such
techniques.
+@node Better List-directed I/O
+@subsection Better List-directed I/O
+
+Values output using list-directed I/O
+(@samp{PRINT *, R, D})
+should be written with a field width, precision, and so on
+appropriate for the type (precision) of each value.
+
+(Currently, no distinction is made between single-precision
+and double-precision values
+by @code{libf2c}.)
+
+It is likely this item will require the @code{libg77} project
+to be undertaken.
+
+In the meantime, use of formatted I/O is recommended.
+While it might be of little consolation,
+@code{g77} does support @samp{FORMAT(F<WIDTH>.4)}, for example,
+as long as @samp{WIDTH} is defined as a named constant
+(via @code{PARAMETER}).
+That at least allows some compile-time specification
+of the precision of a data type,
+perhaps controlled by preprocessing directives.
+
+@node Default to Console I/O
+@subsection Default to Console I/O
+
+The default I/O units,
+specified by @samp{READ @var{fmt}},
+@samp{READ (UNIT=*)},
+@samp{WRITE (UNIT=*)}, and
+@samp{PRINT @var{fmt}},
+should not be units 5 (input) and 6 (output),
+but, rather, unit numbers not normally available
+for use in statements such as @code{OPEN} and @code{CLOSE}.
+
+Changing this would allow a program to connect units 5 and 6
+to files via @code{OPEN},
+but still use @samp{READ (UNIT=*)} and @samp{PRINT}
+to do I/O to the ``console''.
+
+This change probably requires the @code{libg77} project.
+
@node Labels Visible to Debugger
@subsection Labels Visible to Debugger
@@ -12568,7 +12569,7 @@ way around them for now.
@cindex external names
@cindex common blocks
@cindex name space
-@cindex underscores
+@cindex underscore
The current external-interface design, which includes naming of
external procedures, COMMON blocks, and the library interface,
@@ -12588,8 +12589,8 @@ with popular existing compilers.
@cindex block data
@cindex BLOCK DATA statement
@cindex statements, BLOCK DATA
-@cindex COMMON statement
-@cindex statements, COMMON
+@cindex @code{COMMON} statement
+@cindex statements, @code{COMMON}
@cindex naming conflicts
@code{g77} doesn't allow a common block and an external procedure or
@@ -12651,8 +12652,8 @@ we do not make because we think GNU Fortran is better without them.
@node Backslash in Constants
@subsection Backslash in Constants
@cindex backslash
-@cindex f77 support
-@cindex support, f77
+@cindex @code{f77} support
+@cindex support, @code{f77}
In the opinion of many experienced Fortran users,
@samp{-fno-backslash} should be the default, not @samp{-fbackslash},
@@ -12944,7 +12945,7 @@ could be very helpful.
@cindex logical expressions, comparing
Use of @code{.EQ.} and @code{.NE.} on @code{LOGICAL} operands
-is not supported, except via @samp{-fugly}, which is not
+is not supported, except via @samp{-fugly-logint}, which is not
recommended except for legacy code (where the behavior expected
by the @emph{code} is assumed).
@@ -13002,6 +13003,20 @@ that were well-designed in the first place.
you, without knowing more context, whether the @samp{&} and @samp{-}
operators are infix (binary) or unary!)
+Most dangerous of all is the fact that,
+even assuming consensus on its meaning,
+an expression like @samp{L.AND.M.EQ.N},
+if it is the result of a typographical error,
+doesn't @emph{look} like it has such a typo.
+Even experienced Fortran programmers would not likely notice that
+@samp{L.AND.M.EQV.N} was, in fact, intended.
+
+So, this is a prime example of a circumstance in which
+a quality compiler diagnoses the code,
+instead of leaving it up to someone debugging it
+to know to turn on special compiler options
+that might diagnose it.
+
@node Order of Side Effects
@subsection Order of Side Effects
@cindex side effects, order of evaluation
@@ -13067,7 +13082,7 @@ warnings.
Each kind has a different purpose:
@itemize @w{}
-@item
+@item
@emph{Errors} report problems that make it impossible to compile your
program.
GNU Fortran reports errors with the source file name, line
@@ -13152,7 +13167,7 @@ Bug reports are your contribution to the maintenance of GNU Fortran.
Since the maintainers are very overloaded, we cannot respond to every
bug report.
However, if the bug has not been fixed, we are likely to
-send you a patch and ask you to tell us whether it works.
+send you a patch and ask you to tell us whether it works.
In order for a bug report to serve its purpose, you must include the
information that makes for fixing the bug.
@@ -13463,23 +13478,30 @@ the bug in the current version of GNU Fortran.
@cindex programs, cpp
@pindex cpp
A complete input file that will reproduce the bug.
-If the bug is in the compiler proper (@file{f771}) and
-you are using the C preprocessor, run your
-source file through the C preprocessor by doing @samp{g77 -E
-@var{sourcefile} > @var{outfile}}, then include the contents of
-@var{outfile} in the bug report. (When you do this, use the same
-@samp{-I}, @samp{-D} or @samp{-U} options that you used in actual
+
+If your source file(s) require preprocessing
+(for example, their names have suffixes like
+@samp{.F}, @samp{.fpp}, @samp{.FPP}, and @samp{.r}),
+and the bug is in the compiler proper (@file{f771})
+or in a subsequent phase of processing,
+run your source file through the C preprocessor
+by doing @samp{g77 -E @var{sourcefile} > @var{newfile}}.
+Then, include the contents of @var{newfile} in the bug report.
+(When you do this, use the same preprocessor options---such as
+@samp{-I}, @samp{-D}, and @samp{-U}---that you used in actual
compilation.)
A single statement is not enough of an example.
In order to compile it,
-it must be embedded in a complete file of compiler input; and the bug
-might depend on the details of how this is done.
+it must be embedded in a complete file of compiler input.
+The bug might depend on the details of how this is done.
-Without a real example one can compile, all anyone can do about your bug
-report is wish you luck. It would be futile to try to guess how to
-provoke the bug. For example, bugs in register allocation and reloading
-frequently depend on every little detail of the function they happen in.
+Without a real example one can compile,
+all anyone can do about your bug report is wish you luck.
+It would be futile to try to guess how to provoke the bug.
+For example, bugs in register allocation and reloading
+can depend on every little detail of the source and include files
+that trigger them.
@item
@cindex included files
@@ -13851,13 +13873,13 @@ when compiling most any kind of program.
which is used during the build of @code{gcc} to
build a list of all options that are accepted by
at least one language's compiler.
-This list goes into the @samp{lang_options} array
+This list goes into the @code{lang_options} array
in @file{gcc/toplev.c}, which uses this array to
determine whether a particular option should be
offered to the linked-in front end for processing
-by calling @samp{lang_option_decode}, which, for
+by calling @code{lang_option_decode}, which, for
@code{g77}, is in @file{@value{path-g77}/com.c} and just
-calls @samp{ffe_decode_option}.
+calls @code{ffe_decode_option}.
If the linked-in front end ``rejects'' a
particular option passed to it, @file{toplev.c}
@@ -13867,7 +13889,7 @@ language's compiler is willing to accept it.
This allows commands like @samp{gcc -fno-asm foo.c bar.f}
to work, even though Fortran compilation does
not currently support the @samp{-fno-asm} option;
-even though the @code{f771} version of @samp{lang_decode_option}
+even though the @code{f771} version of @code{lang_decode_option}
rejects @samp{-fno-asm}, @file{toplev.c} doesn't
produce a diagnostic because some other language (C)
does accept it.
@@ -13880,7 +13902,7 @@ a warning about this would be helpful if it were
possible.
Code that processes Fortran options is found in
-@file{@value{path-g77}/top.c}, function @samp{ffe_decode_option}.
+@file{@value{path-g77}/top.c}, function @code{ffe_decode_option}.
This code needs to check positive and negative forms
of each option.
@@ -13900,9 +13922,9 @@ Accessor macros for Fortran options, used by code
in the @code{g77} FFE, are defined in @file{@value{path-g77}/top.h}.
@emph{Compiler options} are listed in @file{gcc/toplev.c}
-in the array @samp{f_options}.
-An option not listed in @samp{lang_options} is
-looked up in @samp{f_options} and handled from there.
+in the array @code{f_options}.
+An option not listed in @code{lang_options} is
+looked up in @code{f_options} and handled from there.
The defaults for compiler options are set in the
global definitions for the corresponding variables,
@@ -13910,11 +13932,25 @@ some of which are in @file{gcc/toplev.c}.
You can set different defaults for @emph{Fortran-oriented}
or @emph{Fortran-reticent} compiler options by changing
-the way @code{f771} handles the @samp{-fset-g77-defaults}
+the source code of @code{g77} and rebuilding.
+How to do this depends on the version of @code{g77}:
+
+@table @code
+@item G77 0.5.24 (EGCS 1.1)
+@itemx G77 0.5.25 (EGCS 1.2)
+Change the @code{lang_init_options} routine in @file{egcs/gcc/f/com.c}.
+
+(Note that these versions of @code{g77}
+perform internal consistency checking automatically
+when the @samp{-fversion} option is specified.)
+
+@item G77 0.5.23
+@itemx G77 0.5.24 (EGCS 1.0)
+Change the way @code{f771} handles the @samp{-fset-g77-defaults}
option, which is always provided as the first option when
called by @code{g77} or @code{gcc}.
-This code is in @samp{ffe_decode_options} in @file{@value{path-g77}/top.c}.
+This code is in @code{ffe_decode_options} in @file{@value{path-g77}/top.c}.
Have it change just the variables that you want to default
to a different setting for Fortran compiles compared to
compiles of other languages.
@@ -13933,6 +13969,7 @@ It is in @file{@value{path-g77}/lang-specs.h} that @samp{-fset-g77-defaults},
even when the user has not explicitly specified them.
Other ``internal'' options such as @samp{-quiet} also
are passed via this mechanism.
+@end table
@node Projects
@chapter Projects
@@ -13967,7 +14004,7 @@ them show up only given certain kinds of (popular) input.
@itemize @bullet
@item
-Improve @samp{malloc} package and its uses to specify more info about
+Improve @code{malloc} package and its uses to specify more info about
memory pools and, where feasible, use obstacks to implement them.
@item
@@ -13994,11 +14031,11 @@ unimplemented-statement catch-all.
@item
Throughout @code{g77}, don't pass line/column pairs where
-a simple @samp{ffewhere} type, which points to the error as much as is
-desired by the configuration, will do, and don't pass @samp{ffelexToken} types
-where a simple @samp{ffewhere} type will do.
+a simple @code{ffewhere} type, which points to the error as much as is
+desired by the configuration, will do, and don't pass @code{ffelexToken} types
+where a simple @code{ffewhere} type will do.
Then, allow new default
-configuration of @samp{ffewhere} such that the source line text is not
+configuration of @code{ffewhere} such that the source line text is not
preserved, and leave it to things like Emacs' next-error function
to point to them (now that @samp{next-error} supports column,
or, perhaps, character-offset, numbers).
@@ -14048,7 +14085,7 @@ that are at all worth inlining.
@item
When doing @samp{CHAR_VAR = CHAR_FUNC(@dots{})},
and it's clear that types line up
-and @samp{CHAR_VAR} is addressable or not a @samp{VAR_DECL},
+and @samp{CHAR_VAR} is addressable or not a @code{VAR_DECL},
make @samp{CHAR_VAR}, not a
temporary, be the receiver for @samp{CHAR_FUNC}.
(This is now done for @code{COMPLEX} variables.)
@@ -14096,7 +14133,7 @@ external names for @code{COMPLEX} functions in some cases once @code{g77} uses
@code{gcc} rather than @code{f2c} calling conventions.)
@item
-Do something useful with @samp{doiter} references where possible.
+Do something useful with @code{doiter} references where possible.
For example, @samp{CALL FOO(I)} cannot modify @samp{I} if within
a @code{DO} loop that uses @samp{I} as the
iteration variable, and the back end might find that info useful
@@ -14171,12 +14208,6 @@ sprinkled throughout.
It is not worth repeating them here.
@item
-@cindex concatenation
-@cindex CHARACTER*(*)
-Support arbitrary operands for concatenation, even in contexts where
-run-time allocation is required.
-
-@item
Consider adding a @code{NUMERIC} type to designate typeless numeric constants,
named and unnamed.
The idea is to provide a forward-looking, effective
@@ -14252,7 +14283,7 @@ provides it via its configuration.
@itemize @bullet
@item
-Switch to using @samp{REAL_VALUE_TYPE} to represent floating-point constants
+Switch to using @code{REAL_VALUE_TYPE} to represent floating-point constants
exclusively so the target float format need not be required.
This
means changing the way @code{g77} handles initialization of aggregate areas
@@ -14281,6 +14312,9 @@ Better info on how @code{g77} works and how to port it is needed.
Much of this should be done only after the redesign planned for
0.6 is complete.
+@xref{Front End}, which contains some information
+on @code{g77} internals.
+
@node Internals Improvements
@section Internals Improvements
@@ -14305,13 +14339,13 @@ Come up with better naming conventions for @samp{-D} to establish requirements
to achieve desired implementation dialect via @file{proj.h}.
@item
-Clean up used tokens and @samp{ffewhere}s in @samp{ffeglobal_terminate_1}.
+Clean up used tokens and @code{ffewhere}s in @code{ffeglobal_terminate_1}.
@item
-Replace @file{sta.c} @samp{outpooldisp} mechanism with @samp{malloc_pool_use}.
+Replace @file{sta.c} @code{outpooldisp} mechanism with @code{malloc_pool_use}.
@item
-Check for @samp{opANY} in more places in @file{com.c}, @file{std.c},
+Check for @code{opANY} in more places in @file{com.c}, @file{std.c},
and @file{ste.c}, and get rid of the @samp{opCONVERT(opANY)} kludge
(after determining if there is indeed no real need for it).
@@ -14353,22 +14387,22 @@ to the official standard, or put documentation of the rules as used
in the code@dots{}uh@dots{}in the code.
@item
-Some @samp{ffebld_new} calls (those outside of @file{ffeexpr.c} or
-inside but invoked via paths not involving @samp{ffeexpr_lhs} or
-@samp{ffeexpr_rhs}) might be creating things
+Some @code{ffebld_new} calls (those outside of @file{ffeexpr.c} or
+inside but invoked via paths not involving @code{ffeexpr_lhs} or
+@code{ffeexpr_rhs}) might be creating things
in improper pools, leading to such things staying around too long or
(doubtful, but possible and dangerous) not long enough.
@item
-Some @samp{ffebld_list_new} (or whatever) calls might not be matched by
-@samp{ffebld_list_bottom} (or whatever) calls, which might someday matter.
+Some @code{ffebld_list_new} (or whatever) calls might not be matched by
+@code{ffebld_list_bottom} (or whatever) calls, which might someday matter.
(It definitely is not a problem just yet.)
@item
Probably not doing clean things when we fail to @code{EQUIVALENCE} something
due to alignment/mismatch or other problems---they end up without
-@samp{ffestorag} objects, so maybe the backend (and other parts of the front
-end) can notice that and handle like an @samp{opANY} (do what it wants, just
+@code{ffestorag} objects, so maybe the backend (and other parts of the front
+end) can notice that and handle like an @code{opANY} (do what it wants, just
don't complain or crash).
Most of this seems to have been addressed
by now, but a code review wouldn't hurt.
@@ -14386,7 +14420,7 @@ clutter.
@item
When @code{FUNCTION} and @code{ENTRY} point types disagree (@code{CHARACTER}
lengths, type classes, and so on),
-@samp{ANY}-ize the offending @code{ENTRY} point and any @emph{new} dummies
+@code{ANY}-ize the offending @code{ENTRY} point and any @emph{new} dummies
it specifies.
@item
@@ -14407,6 +14441,9 @@ END
is processed in the context of executable, not specification,
statements.)
@end itemize
+
+@include ffe.texi
+
@end ifset
@ifset USING
@@ -14452,7 +14489,8 @@ as the above is just a sample, no such section exists.
* INTGLOB:: Intrinsic also used as name of global.
* LEX:: Various lexer messages
* GLOBALS:: Disagreements about globals.
-* LINKFAIL:: When linking @samp{f771} fails.
+* LINKFAIL:: When linking @code{f771} fails.
+* Y2KBAD:: Use of non-Y2K-compliant intrinsic.
@end menu
@node CMPAMBIG
@@ -14570,8 +14608,8 @@ expects the Fortran 90 interpretation, you can:
@itemize @bullet
@item
Change it to @samp{DBLE(@var{expr})} (if @var{intrinsic} is
-@samp{REAL}) or @samp{DIMAG(@var{expr})} (if @var{intrinsic}
-is @samp{AIMAG})
+@code{REAL}) or @samp{DIMAG(@var{expr})} (if @var{intrinsic}
+is @code{AIMAG})
if it expected the Fortran 90 interpretation.
This assumes @var{expr} is @code{COMPLEX(KIND=2)}---if it is
@@ -14624,7 +14662,6 @@ The following sample program might help:
PROGRAM JCB003
C
C Written by James Craig Burley 1997-02-23.
-C Contact via Internet email: burley@@gnu.org
C
C Determine how compilers handle non-standard REAL
C and AIMAG on DOUBLE COMPLEX operands.
@@ -14800,6 +14837,8 @@ was not specified on the command line to compile it.
Free form is a newer form for Fortran code.
The older, classic form is called fixed form.
+@cindex continuation character
+@cindex characters, continuation
Fixed-form code is visually fairly distinctive, because
numerical labels and comments are all that appear in
the first five columns of a line, the sixth column is
@@ -14808,8 +14847,15 @@ and actual statements start at or beyond column 7.
Spaces generally are not significant, so if you
see statements such as @samp{REALX,Y} and @samp{DO10I=1,100},
you are looking at fixed-form code.
+@cindex *
+@cindex asterisk
Comment lines are indicated by the letter @samp{C} or the symbol
@samp{*} in column 1.
+@cindex trailing comment
+@cindex comment
+@cindex characters, comment
+@cindex !
+@cindex exclamation point
(Some code uses @samp{!} or @samp{/*} to begin in-line comments,
which many compilers support.)
@@ -14851,13 +14897,13 @@ C On XYZZY systems, remove "C" on next line:
CALL XYZZY_RESET
@end smallexample
-However, that leaves the first @samp{C} in the @samp{CALL}
+However, that leaves the first @samp{C} in the @code{CALL}
statement in column 6, making it a comment line, which is
not really what the author intended, and which is likely
to result in one of the above-listed diagnostics.
@emph{Replacing} the @samp{C} in column 1 with a space
-is the proper change to make, to ensure the @samp{CALL}
+is the proper change to make, to ensure the @code{CALL}
keyword starts in or after column 7.
Another common mistake like this is to forget that fixed-form
@@ -14875,12 +14921,15 @@ A source file containing lines beginning with @code{#define},
@code{#include}, @code{#if}, and so on is likely one that
requires preprocessing.
-If the file's suffix is @samp{.f} or @samp{.for}, the file
-will normally be compiled @emph{without} preprocessing by @code{g77}.
+If the file's suffix is @samp{.f}, @samp{.for}, or @samp{.FOR},
+the file normally will be compiled @emph{without} preprocessing
+by @code{g77}.
-Change the file's suffix from @samp{.f} to @samp{.F} (or, on
-systems with case-insensitive file names, to @samp{.fpp}) or
-from @samp{.for} to @samp{.fpp}.
+Change the file's suffix from @samp{.f} to @samp{.F}
+(or, on systems with case-insensitive file names,
+to @samp{.fpp} or @samp{.FPP}),
+from @samp{.for} to @samp{.fpp},
+or from @samp{.FOR} to @samp{.FPP}.
@code{g77} compiles files with such names @emph{with}
preprocessing.
@@ -14924,29 +14973,54 @@ Argument #@var{n} of @var{name} is @dots{}
@end smallexample
These messages all identify disagreements about the
-global procedure named @var{name} among different program
-units (usually including @var{name} itself).
-
-These disagreements, if not diagnosed, could result in a
-compiler crash if the compiler attempted to inline a reference
-to @var{name} within a calling program unit that disagreed
-with the @var{name} program unit regarding whether the
-procedure is a subroutine or function, the type of the
-return value of the procedure (if it is a function), the
-number of arguments the procedure accepts, or the type
-of each argument.
-
-Such disagreements @emph{should} be fixed in the Fortran
-code itself.
-However, if that is not immediately practical, and the code
-has been working for some time, it is possible it will work
-when compiled by @code{g77} with the @samp{-fno-globals} option.
-
-The @samp{-fno-globals} option disables these diagnostics, and
-also disables all inlining of references to global procedures
-to avoid compiler crashes.
-The diagnostics are actually produced, but as warnings, unless
-the @samp{-Wno-globals} option also is specified.
+global procedure named @var{name} among different program units
+(usually including @var{name} itself).
+
+Whether a particular disagreement is reported
+as a warning or an error
+can depend on the relative order
+of the disagreeing portions of the source file.
+
+Disagreements between a procedure invocation
+and the @emph{subsequent} procedure itself
+are, usually, diagnosed as errors
+when the procedure itself @emph{precedes} the invocation.
+Other disagreements are diagnosed via warnings.
+
+@cindex forward references
+@cindex in-line code
+@cindex compilation, in-line
+This distinction, between warnings and errors,
+is due primarily to the present tendency of the @code{gcc} back end
+to inline only those procedure invocations that are
+@emph{preceded} by the corresponding procedure definitions.
+If the @code{gcc} back end is changed
+to inline ``forward references'',
+in which invocations precede definitions,
+the @code{g77} front end will be changed
+to treat both orderings as errors, accordingly.
+
+The sorts of disagreements that are diagnosed by @code{g77} include
+whether a procedure is a subroutine or function;
+if it is a function, the type of the return value of the procedure;
+the number of arguments the procedure accepts;
+and the type of each argument.
+
+Disagreements regarding global names among program units
+in a Fortran program @emph{should} be fixed in the code itself.
+However, if that is not immediately practical,
+and the code has been working for some time,
+it is possible it will work
+when compiled with the @samp{-fno-globals} option.
+
+The @samp{-fno-globals} option
+causes these diagnostics to all be warnings
+and disables all inlining of references to global procedures
+(to avoid subsequent compiler crashes and bad-code generation).
+Use of the @samp{-Wno-globals} option as well as @samp{-fno-globals}
+suppresses all of these diagnostics.
+(@samp{-Wno-globals} by itself disables only the warnings,
+not the errors.)
After using @samp{-fno-globals} to work around these problems,
it is wise to stop using that option and address them by fixing
@@ -14988,6 +15062,24 @@ might solve this problem, e.g.@: by adding
BOOT_CFLAGS='-mminimal-toc -O2 -g'
@end smallexample
to the @code{make bootstrap} command line.
+
+@node Y2KBAD
+@section @code{Y2KBAD}
+@cindex Y2K compliance
+@cindex Year 2000 compliance
+
+@noindent
+@smallexample
+Intrinsic `@var{name}', invoked at (^), known to be non-Y2K-compliant@dots{}
+@end smallexample
+
+This diagnostic indicates that
+the specific intrinsic invoked by the name @var{name}
+is known to have an interface
+that is not Year-2000 (Y2K) compliant.
+
+@xref{Year 2000 (Y2K) Problems}.
+
@end ifset
@node Index
diff --git a/contrib/gcc/f/g77spec.c b/contrib/gcc/f/g77spec.c
index 79d3637..50e7738 100644
--- a/contrib/gcc/f/g77spec.c
+++ b/contrib/gcc/f/g77spec.c
@@ -1,5 +1,5 @@
/* Specific flags and argument handling of the Fortran front-end.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -46,7 +46,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include "gansidecl.h"
#include <f/version.h>
#ifndef MATH_LIBRARY
@@ -93,8 +92,6 @@ static void (*g77_fn)();
static int g77_newargc;
static char **g77_newargv;
-extern char *xmalloc PROTO((size_t));
-
extern char *version_string;
/* --- This comes from gcc.c (2.8.1) verbatim: */
@@ -289,6 +286,9 @@ lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
2 => last two args were -l<library> -lm. */
int saw_library = 0;
+ /* By default, we throw on the math library if we have one. */
+ int need_math = (MATH_LIBRARY[0] != '\0');
+
/* The number of input and output files in the incoming arg list. */
int n_infiles = 0;
int n_outfiles = 0;
@@ -427,7 +427,8 @@ code-generation methodology, and so on.\n\
For more information on g77 and gcc, type the commands `info -f g77'\n\
and `info -f gcc' to read the Info documentation.\n\
\n\
-Report bugs to <egcs-bugs@cygnus.org>.\n");
+For bug reporting instructions, please see:\n\
+<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>.\n");
exit (0);
break;
#endif
@@ -469,7 +470,7 @@ Report bugs to <egcs-bugs@cygnus.org>.\n");
{
/* Not a filename or library. */
- if (saw_library == 1) /* -l<library>. */
+ if (saw_library == 1 && need_math) /* -l<library>. */
append_arg (MATH_LIBRARY);
saw_library = 0;
@@ -524,7 +525,7 @@ Report bugs to <egcs-bugs@cygnus.org>.\n");
saw_library = 1; /* -l<library>. */
else
{ /* Other library, or filename. */
- if (saw_library == 1)
+ if (saw_library == 1 && need_math)
append_arg (MATH_LIBRARY);
saw_library = 0;
}
@@ -544,7 +545,8 @@ Report bugs to <egcs-bugs@cygnus.org>.\n");
case 0:
append_arg (library);
case 1:
- append_arg (MATH_LIBRARY);
+ if (need_math)
+ append_arg (MATH_LIBRARY);
default:
break;
}
diff --git a/contrib/gcc/f/glimits.j b/contrib/gcc/f/glimits.j
index 5d5406c..0262258 100644
--- a/contrib/gcc/f/glimits.j
+++ b/contrib/gcc/f/glimits.j
@@ -1,6 +1,6 @@
/* glimits.j -- Wrapper for GCC's glimits.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/global.c b/contrib/gcc/f/global.c
index 8be7d0c4..85311f1 100644
--- a/contrib/gcc/f/global.c
+++ b/contrib/gcc/f/global.c
@@ -1,6 +1,6 @@
/* global.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -60,7 +60,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#if FFEGLOBAL_ENABLED
static ffenameSpace ffeglobal_filewide_ = NULL;
-static char *ffeglobal_type_string_[] =
+static const char *ffeglobal_type_string_[] =
{
[FFEGLOBAL_typeNONE] "??",
[FFEGLOBAL_typeMAIN] "main program",
@@ -86,7 +86,7 @@ static char *ffeglobal_type_string_[] =
#if FFEGLOBAL_ENABLED
void
-ffeglobal_drive (ffeglobal (*fn) ())
+ffeglobal_drive (ffeglobal (*fn) (ffeglobal))
{
if (ffeglobal_filewide_ != NULL)
ffename_space_drive_global (ffeglobal_filewide_, fn);
@@ -181,6 +181,7 @@ ffeglobal_init_common (ffesymbol s, ffelexToken t)
{
if (g->u.common.blank)
{
+ /* Not supposed to initialize blank common, though it works. */
ffebad_start (FFEBAD_COMMON_BLANK_INIT);
ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
ffebad_finish ();
@@ -229,10 +230,13 @@ ffeglobal_new_common (ffesymbol s, ffelexToken t, bool blank)
{
if (g->type == FFEGLOBAL_typeCOMMON)
{
+ /* The names match, so the "blankness" should match too! */
assert (g->u.common.blank == blank);
}
else
{
+ /* This global name has already been established,
+ but as something other than a common block. */
if (ffe_is_globals () || ffe_is_warn_globals ())
{
ffebad_start (ffe_is_globals ()
@@ -258,6 +262,10 @@ ffeglobal_new_common (ffesymbol s, ffelexToken t, bool blank)
&& !g->explicit_intrinsic
&& ffe_is_warn_globals ())
{
+ /* Common name previously used as intrinsic. Though it works,
+ warn, because the intrinsic reference might have been intended
+ as a ref to an external procedure, but g77's vast list of
+ intrinsics happened to snarf the name. */
ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
ffebad_string (ffelex_token_text (t));
ffebad_string ("common block");
@@ -308,6 +316,7 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
|| (g->type == FFEGLOBAL_typeBDATA))
&& g->u.proc.defined)
{
+ /* This program unit has already been defined. */
if (ffe_is_globals () || ffe_is_warn_globals ())
{
ffebad_start (ffe_is_globals ()
@@ -327,6 +336,13 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
&& (g->type != FFEGLOBAL_typeEXT)
&& (g->type != type))
{
+ /* A reference to this program unit has been seen, but its
+ context disagrees about the new definition regarding
+ what kind of program unit it is. (E.g. `call foo' followed
+ by `function foo'.) But `external foo' alone doesn't mean
+ disagreement with either a function or subroutine, though
+ g77 normally interprets it as a request to force-load
+ a block data program unit by that name (to cope with libs). */
if (ffe_is_globals () || ffe_is_warn_globals ())
{
ffebad_start (ffe_is_globals ()
@@ -353,11 +369,16 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
g->u.proc.other_t = NULL;
}
else if ((ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
+ && (g->type == FFEGLOBAL_typeFUNC)
&& ((ffesymbol_basictype (s) != g->u.proc.bt)
|| (ffesymbol_kindtype (s) != g->u.proc.kt)
|| ((ffesymbol_size (s) != FFETARGET_charactersizeNONE)
&& (ffesymbol_size (s) != g->u.proc.sz))))
{
+ /* The previous reference and this new function definition
+ disagree about the type of the function. I (Burley) think
+ this rarely occurs, because when this code is reached,
+ the type info doesn't appear to be filled in yet. */
if (ffe_is_globals () || ffe_is_warn_globals ())
{
ffebad_start (ffe_is_globals ()
@@ -377,6 +398,10 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
&& !g->explicit_intrinsic
&& ffe_is_warn_globals ())
{
+ /* This name, previously used as an intrinsic, now is known
+ to also be a global procedure name. Warn, since the previous
+ use as an intrinsic might have been intended to refer to
+ this procedure. */
ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
ffebad_string (ffelex_token_text (t));
ffebad_string ("global");
@@ -395,10 +420,12 @@ ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
g->u.proc.kt = ffesymbol_kindtype (s);
g->u.proc.sz = ffesymbol_size (s);
}
- g->tick = ffe_count_2;
+ /* If there's a known disagreement about the kind of program
+ unit, then don't even bother tracking arglist argreement. */
if ((g->tick != 0)
&& (g->type != type))
g->u.proc.n_args = -1;
+ g->tick = ffe_count_2;
g->type = type;
g->u.proc.defined = TRUE;
}
@@ -487,7 +514,7 @@ ffeglobal_pad_common (ffesymbol s, ffetargetAlign pad, ffewhereLine wl,
/* Collect info for a global's argument. */
void
-ffeglobal_proc_def_arg (ffesymbol s, int argno, char *name, ffeglobalArgSummary as,
+ffeglobal_proc_def_arg (ffesymbol s, int argno, const char *name, ffeglobalArgSummary as,
ffeinfoBasictype bt, ffeinfoKindtype kt,
bool array)
{
@@ -511,8 +538,8 @@ ffeglobal_proc_def_arg (ffesymbol s, int argno, char *name, ffeglobalArgSummary
if ((ai->t != NULL)
&& ffe_is_warn_globals ())
{
- char *refwhy = NULL;
- char *defwhy = NULL;
+ const char *refwhy = NULL;
+ const char *defwhy = NULL;
bool warn = FALSE;
switch (as)
@@ -789,8 +816,8 @@ ffeglobal_proc_ref_arg (ffesymbol s, int argno, ffeglobalArgSummary as,
if (ai->t != NULL)
{
- char *refwhy = NULL;
- char *defwhy = NULL;
+ const char *refwhy = NULL;
+ const char *defwhy = NULL;
bool fail = FALSE;
bool warn = FALSE;
@@ -1160,6 +1187,10 @@ ffeglobal_ref_intrinsic (ffesymbol s, ffelexToken t, bool explicit)
&& ! g->intrinsic
&& ffe_is_warn_globals ())
{
+ /* This name, previously used as a global, now is used
+ for an intrinsic. Warn, since this new use as an
+ intrinsic might have been intended to refer to
+ the global procedure. */
ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
ffebad_string (ffelex_token_text (t));
ffebad_string ("intrinsic");
@@ -1186,6 +1217,11 @@ ffeglobal_ref_intrinsic (ffesymbol s, ffelexToken t, bool explicit)
&& (g->tick != ffe_count_2)
&& ffe_is_warn_globals ())
{
+ /* An earlier reference to this intrinsic disagrees with
+ this reference vis-a-vis explicit `intrinsic foo',
+ which suggests that the one relying on implicit
+ intrinsicacity might have actually intended to refer
+ to a global of the same name. */
ffebad_start (FFEBAD_INTRINSIC_EXPIMP);
ffebad_string (ffelex_token_text (t));
ffebad_string (explicit ? "explicit" : "implicit");
@@ -1235,10 +1271,13 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
if ((g != NULL)
&& (g->type != FFEGLOBAL_typeNONE)
- && (g->type != type)
&& (g->type != FFEGLOBAL_typeEXT)
+ && (g->type != type)
&& (type != FFEGLOBAL_typeEXT))
{
+ /* Disagreement about (fully refined) class of program unit
+ (main, subroutine, function, block data). Treat EXTERNAL/
+ COMMON disagreements distinctly. */
if ((((type == FFEGLOBAL_typeBDATA)
&& (g->type != FFEGLOBAL_typeCOMMON))
|| ((g->type == FFEGLOBAL_typeBDATA)
@@ -1248,6 +1287,7 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
#if 0 /* This is likely to just annoy people. */
if (ffe_is_warn_globals ())
{
+ /* Warn about EXTERNAL of a COMMON name, though it works. */
ffebad_start (FFEBAD_FILEWIDE_TIFF);
ffebad_string (ffelex_token_text (t));
ffebad_string (ffeglobal_type_string_[type]);
@@ -1260,23 +1300,11 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
}
#endif
}
- else if (ffe_is_globals ())
+ else if (ffe_is_globals () || ffe_is_warn_globals ())
{
- ffebad_start (FFEBAD_FILEWIDE_DISAGREEMENT);
- ffebad_string (ffelex_token_text (t));
- ffebad_string (ffeglobal_type_string_[type]);
- ffebad_string (ffeglobal_type_string_[g->type]);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_here (1, ffelex_token_where_line (g->t),
- ffelex_token_where_column (g->t));
- ffebad_finish ();
- g->type = FFEGLOBAL_typeANY;
- return FALSE;
- }
- else if (ffe_is_warn_globals ())
- {
- ffebad_start (FFEBAD_FILEWIDE_DISAGREEMENT_W);
+ ffebad_start (ffe_is_globals ()
+ ? FFEBAD_FILEWIDE_DISAGREEMENT
+ : FFEBAD_FILEWIDE_DISAGREEMENT_W);
ffebad_string (ffelex_token_text (t));
ffebad_string (ffeglobal_type_string_[type]);
ffebad_string (ffeglobal_type_string_[g->type]);
@@ -1286,7 +1314,7 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
ffelex_token_where_column (g->t));
ffebad_finish ();
g->type = FFEGLOBAL_typeANY;
- return TRUE;
+ return (! ffe_is_globals ());
}
}
@@ -1302,39 +1330,65 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
g->u.proc.kt = ffesymbol_kindtype (s);
g->u.proc.sz = ffesymbol_size (s);
}
- /* Else, make sure there is type agreement. */
- else if ((g->u.proc.bt != FFEINFO_basictypeNONE)
- && (ffesymbol_basictype (s) != FFEINFO_basictypeNONE)
- && ((ffesymbol_basictype (s) != g->u.proc.bt)
- || (ffesymbol_kindtype (s) != g->u.proc.kt)
- || ((ffesymbol_size (s) != g->u.proc.sz)
- && g->u.proc.defined
- && (g->u.proc.sz != FFETARGET_charactersizeNONE))))
+ /* Make sure there is type agreement. */
+ if (g->type == FFEGLOBAL_typeFUNC
+ && g->u.proc.bt != FFEINFO_basictypeNONE
+ && ffesymbol_basictype (s) != FFEINFO_basictypeNONE
+ && (ffesymbol_basictype (s) != g->u.proc.bt
+ || ffesymbol_kindtype (s) != g->u.proc.kt
+ /* CHARACTER*n disagreements matter only once a
+ definition is involved, since the definition might
+ be CHARACTER*(*), which accepts all references. */
+ || (g->u.proc.defined
+ && ffesymbol_size (s) != g->u.proc.sz
+ && ffesymbol_size (s) != FFETARGET_charactersizeNONE
+ && g->u.proc.sz != FFETARGET_charactersizeNONE)))
{
- if (ffe_is_globals ())
+ int error;
+
+ /* Type mismatch between function reference/definition and
+ this subsequent reference (which might just be the filling-in
+ of type info for the definition, but we can't reach here
+ if that's the case and there was a previous definition).
+
+ It's an error given a previous definition, since that
+ implies inlining can crash the compiler, unless the user
+ asked for no such inlining. */
+ error = (g->tick != ffe_count_2
+ && g->u.proc.defined
+ && ffe_is_globals ());
+ if (error || ffe_is_warn_globals ())
{
- ffebad_start (FFEBAD_FILEWIDE_TYPE_MISMATCH);
+ ffebad_start (error
+ ? FFEBAD_FILEWIDE_TYPE_MISMATCH
+ : FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
ffebad_string (ffelex_token_text (t));
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_here (1, ffelex_token_where_line (g->t),
- ffelex_token_where_column (g->t));
+ if (g->tick == ffe_count_2)
+ {
+ /* Current reference fills in type info for definition.
+ The current token doesn't necessarily point to the actual
+ definition of the function, so use the definition pointer
+ and the pointer to the pre-definition type info. */
+ ffebad_here (0, ffelex_token_where_line (g->t),
+ ffelex_token_where_column (g->t));
+ ffebad_here (1, ffelex_token_where_line (g->u.proc.other_t),
+ ffelex_token_where_column (g->u.proc.other_t));
+ }
+ else
+ {
+ /* Current reference is not a filling-in of a current
+ definition. The current token is fine, as is
+ the previous-mention token. */
+ ffebad_here (0, ffelex_token_where_line (t),
+ ffelex_token_where_column (t));
+ ffebad_here (1, ffelex_token_where_line (g->t),
+ ffelex_token_where_column (g->t));
+ }
ffebad_finish ();
- g->type = FFEGLOBAL_typeANY;
+ if (error)
+ g->type = FFEGLOBAL_typeANY;
return FALSE;
}
- if (ffe_is_warn_globals ())
- {
- ffebad_start (FFEBAD_FILEWIDE_TYPE_MISMATCH_W);
- ffebad_string (ffelex_token_text (t));
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_here (1, ffelex_token_where_line (g->t),
- ffelex_token_where_column (g->t));
- ffebad_finish ();
- }
- g->type = FFEGLOBAL_typeANY;
- return TRUE;
}
}
@@ -1357,6 +1411,9 @@ ffeglobal_ref_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type)
&& (g->tick != ffe_count_2)
&& ffe_is_warn_globals ())
{
+ /* Now known as a global, this name previously was seen as an
+ intrinsic. Warn, in case the previous reference was intended
+ for the same global. */
ffebad_start (FFEBAD_INTRINSIC_GLOBAL);
ffebad_string (ffelex_token_text (t));
ffebad_string ("global");
diff --git a/contrib/gcc/f/global.h b/contrib/gcc/f/global.h
index 38cf8d5..eaf9921 100644
--- a/contrib/gcc/f/global.h
+++ b/contrib/gcc/f/global.h
@@ -1,6 +1,6 @@
/* global.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995, 1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -128,14 +128,14 @@ struct _ffeglobal_
/* Declare functions with prototypes. */
-void ffeglobal_drive (ffeglobal (*fn) ());
+void ffeglobal_drive (ffeglobal (*fn) (ffeglobal));
void ffeglobal_init_1 (void);
void ffeglobal_init_common (ffesymbol s, ffelexToken t);
void ffeglobal_new_progunit_ (ffesymbol s, ffelexToken t, ffeglobalType type);
void ffeglobal_new_common (ffesymbol s, ffelexToken t, bool blank);
void ffeglobal_pad_common (ffesymbol s, ffetargetAlign pad, ffewhereLine wl,
ffewhereColumn wc);
-void ffeglobal_proc_def_arg (ffesymbol s, int argno, char *name, ffeglobalArgSummary as,
+void ffeglobal_proc_def_arg (ffesymbol s, int argno, const char *name, ffeglobalArgSummary as,
ffeinfoBasictype bt, ffeinfoKindtype kt,
bool array);
void ffeglobal_proc_def_nargs (ffesymbol s, int n_args);
diff --git a/contrib/gcc/f/hconfig.j b/contrib/gcc/f/hconfig.j
index a2fc0d1..c73930c 100644
--- a/contrib/gcc/f/hconfig.j
+++ b/contrib/gcc/f/hconfig.j
@@ -1,6 +1,6 @@
/* hconfig.j -- Wrapper for GCC's hconfig.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/implic.c b/contrib/gcc/f/implic.c
index bee8edf..7e0c61b 100644
--- a/contrib/gcc/f/implic.c
+++ b/contrib/gcc/f/implic.c
@@ -1,6 +1,6 @@
/* implic.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -73,7 +73,7 @@ static struct _ffeimplic_ ffeimplic_table_['z' - 'A' + 1];
/* Static functions (internal). */
-static ffeimplic_ ffeimplic_lookup_ (char c);
+static ffeimplic_ ffeimplic_lookup_ (unsigned char c);
/* Internal macros. */
@@ -89,7 +89,7 @@ static ffeimplic_ ffeimplic_lookup_ (char c);
data type. */
static ffeimplic_
-ffeimplic_lookup_ (char c)
+ffeimplic_lookup_ (unsigned char c)
{
/* NOTE: This is definitely ASCII-specific!! */
if (ISALPHA (c) || (c == '_'))
@@ -331,7 +331,7 @@ ffeimplic_none ()
/* ffeimplic_peek_symbol_type -- Determine implicit type of a symbol
ffesymbol s;
- char *name; // name for s in case it is NULL, or NULL if s never NULL
+ const char *name; // name for s in case it is NULL, or NULL if s never NULL
if (ffeimplic_peek_symbol_type(s,name) == FFEINFO_basictypeCHARACTER)
// is or will be a CHARACTER-typed name
@@ -348,7 +348,7 @@ ffeimplic_none ()
needed anyway (as when ffecom calls it). */
ffeinfoBasictype
-ffeimplic_peek_symbol_type (ffesymbol s, char *name)
+ffeimplic_peek_symbol_type (ffesymbol s, const char *name)
{
char c;
ffeimplic_ imp;
diff --git a/contrib/gcc/f/implic.h b/contrib/gcc/f/implic.h
index 7550e0d..ae96653 100644
--- a/contrib/gcc/f/implic.h
+++ b/contrib/gcc/f/implic.h
@@ -1,6 +1,6 @@
/* implic.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -55,7 +55,7 @@ bool ffeimplic_establish_initial (char c, ffeinfoBasictype basic_type,
bool ffeimplic_establish_symbol (ffesymbol s);
void ffeimplic_init_2 (void);
void ffeimplic_none (void);
-ffeinfoBasictype ffeimplic_peek_symbol_type (ffesymbol s, char *name);
+ffeinfoBasictype ffeimplic_peek_symbol_type (ffesymbol s, const char *name);
void ffeimplic_terminate_2 (void);
/* Define macros. */
diff --git a/contrib/gcc/f/info-b.def b/contrib/gcc/f/info-b.def
index 30df25e..088d108 100644
--- a/contrib/gcc/f/info-b.def
+++ b/contrib/gcc/f/info-b.def
@@ -1,6 +1,6 @@
/* info-b.def -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/info-k.def b/contrib/gcc/f/info-k.def
index a1441c9..30fb382 100644
--- a/contrib/gcc/f/info-k.def
+++ b/contrib/gcc/f/info-k.def
@@ -1,6 +1,6 @@
/* info-k.def -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/info-w.def b/contrib/gcc/f/info-w.def
index 54a1b364..57e3f8c 100644
--- a/contrib/gcc/f/info-w.def
+++ b/contrib/gcc/f/info-w.def
@@ -1,6 +1,6 @@
/* info-w.def -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/info.c b/contrib/gcc/f/info.c
index 05a6e26..784e699 100644
--- a/contrib/gcc/f/info.c
+++ b/contrib/gcc/f/info.c
@@ -1,6 +1,6 @@
/* info.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -55,21 +55,21 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Static objects accessed by functions in this module. */
-static char *ffeinfo_basictype_string_[]
+static const char *ffeinfo_basictype_string_[]
=
{
#define FFEINFO_BASICTYPE(KWD,LNAM,SNAM) SNAM,
#include "info-b.def"
#undef FFEINFO_BASICTYPE
};
-static char *ffeinfo_kind_message_[]
+static const char *ffeinfo_kind_message_[]
=
{
#define FFEINFO_KIND(KWD,LNAM,SNAM) LNAM,
#include "info-k.def"
#undef FFEINFO_KIND
};
-static char *ffeinfo_kind_string_[]
+static const char *ffeinfo_kind_string_[]
=
{
#define FFEINFO_KIND(KWD,LNAM,SNAM) SNAM,
@@ -77,7 +77,7 @@ static char *ffeinfo_kind_string_[]
#undef FFEINFO_KIND
};
static ffeinfoBasictype ffeinfo_combine_[FFEINFO_basictype][FFEINFO_basictype];
-static char *ffeinfo_kindtype_string_[]
+static const char *ffeinfo_kindtype_string_[]
=
{
"",
@@ -91,7 +91,7 @@ static char *ffeinfo_kindtype_string_[]
"8",
"*",
};
-static char *ffeinfo_where_string_[]
+static const char *ffeinfo_where_string_[]
=
{
#define FFEINFO_WHERE(KWD,LNAM,SNAM) SNAM,
@@ -129,7 +129,7 @@ ffeinfo_basictype_combine (ffeinfoBasictype l, ffeinfoBasictype r)
Returns the string based on the basic type. */
-char *
+const char *
ffeinfo_basictype_string (ffeinfoBasictype basictype)
{
if (basictype >= ARRAY_SIZE (ffeinfo_basictype_string_))
@@ -186,7 +186,7 @@ ffeinfo_init_0 ()
Returns the string based on the kind. */
-char *
+const char *
ffeinfo_kind_message (ffeinfoKind kind)
{
if (kind >= ARRAY_SIZE (ffeinfo_kind_message_))
@@ -201,7 +201,7 @@ ffeinfo_kind_message (ffeinfoKind kind)
Returns the string based on the kind. */
-char *
+const char *
ffeinfo_kind_string (ffeinfoKind kind)
{
if (kind >= ARRAY_SIZE (ffeinfo_kind_string_))
@@ -232,7 +232,7 @@ ffeinfo_kindtype_max(ffeinfoBasictype bt,
Returns the string based on the kind type. */
-char *
+const char *
ffeinfo_kindtype_string (ffeinfoKindtype kind_type)
{
if (kind_type >= ARRAY_SIZE (ffeinfo_kindtype_string_))
@@ -267,7 +267,7 @@ ffeinfo_type (ffeinfoBasictype basictype, ffeinfoKindtype kindtype)
Returns the string based on the where. */
-char *
+const char *
ffeinfo_where_string (ffeinfoWhere where)
{
if (where >= ARRAY_SIZE (ffeinfo_where_string_))
diff --git a/contrib/gcc/f/info.h b/contrib/gcc/f/info.h
index 8eaaa5d..bbf4e94 100644
--- a/contrib/gcc/f/info.h
+++ b/contrib/gcc/f/info.h
@@ -1,6 +1,6 @@
/* info.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -127,15 +127,15 @@ struct _ffeinfo_
ffeinfoBasictype ffeinfo_basictype_combine (ffeinfoBasictype l,
ffeinfoBasictype r);
-char *ffeinfo_basictype_string (ffeinfoBasictype basictype);
+const char *ffeinfo_basictype_string (ffeinfoBasictype basictype);
void ffeinfo_init_0 (void);
-char *ffeinfo_kind_message (ffeinfoKind kind);
-char *ffeinfo_kind_string (ffeinfoKind kind);
+const char *ffeinfo_kind_message (ffeinfoKind kind);
+const char *ffeinfo_kind_string (ffeinfoKind kind);
ffeinfoKindtype ffeinfo_kindtype_max(ffeinfoBasictype bt,
ffeinfoKindtype k1,
ffeinfoKindtype k2);
-char *ffeinfo_kindtype_string (ffeinfoKindtype kind_type);
-char *ffeinfo_where_string (ffeinfoWhere where);
+const char *ffeinfo_kindtype_string (ffeinfoKindtype kind_type);
+const char *ffeinfo_where_string (ffeinfoWhere where);
ffeinfo ffeinfo_new (ffeinfoBasictype basictype, ffeinfoKindtype kindtype,
ffeinfoRank rank, ffeinfoKind kind, ffeinfoWhere where,
ffetargetCharacterSize size);
diff --git a/contrib/gcc/f/input.j b/contrib/gcc/f/input.j
index 1444de2..cc9ff24 100644
--- a/contrib/gcc/f/input.j
+++ b/contrib/gcc/f/input.j
@@ -1,6 +1,6 @@
/* input.j -- Wrapper for GCC's input.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/intdoc.c b/contrib/gcc/f/intdoc.c
index 0ac39ff..7e0a630 100644
--- a/contrib/gcc/f/intdoc.c
+++ b/contrib/gcc/f/intdoc.c
@@ -1,6 +1,6 @@
/* intdoc.c
Copyright (C) 1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -46,30 +46,30 @@ typedef enum
#define FFEINTRIN_DOC 1
#include "intrin.h"
-char *family_name (ffeintrinFamily family);
+const char *family_name (ffeintrinFamily family);
static void dumpif (ffeintrinFamily fam);
static void dumpendif (void);
static void dumpclearif (void);
static void dumpem (void);
-static void dumpgen (int menu, char *name, char *name_uc,
+static void dumpgen (int menu, const char *name, const char *name_uc,
ffeintrinGen gen);
-static void dumpspec (int menu, char *name, char *name_uc,
+static void dumpspec (int menu, const char *name, const char *name_uc,
ffeintrinSpec spec);
-static void dumpimp (int menu, char *name, char *name_uc, size_t genno, ffeintrinFamily family,
+static void dumpimp (int menu, const char *name, const char *name_uc, size_t genno, ffeintrinFamily family,
ffeintrinImp imp, ffeintrinSpec spec);
-static char *argument_info_ptr (ffeintrinImp imp, int argno);
-static char *argument_info_string (ffeintrinImp imp, int argno);
-static char *argument_name_ptr (ffeintrinImp imp, int argno);
-static char *argument_name_string (ffeintrinImp imp, int argno);
+static const char *argument_info_ptr (ffeintrinImp imp, int argno);
+static const char *argument_info_string (ffeintrinImp imp, int argno);
+static const char *argument_name_ptr (ffeintrinImp imp, int argno);
+static const char *argument_name_string (ffeintrinImp imp, int argno);
#if 0
-static char *elaborate_if_complex (ffeintrinImp imp, int argno);
-static char *elaborate_if_maybe_complex (ffeintrinImp imp, int argno);
-static char *elaborate_if_real (ffeintrinImp imp, int argno);
+static const char *elaborate_if_complex (ffeintrinImp imp, int argno);
+static const char *elaborate_if_maybe_complex (ffeintrinImp imp, int argno);
+static const char *elaborate_if_real (ffeintrinImp imp, int argno);
#endif
-static void print_type_string (char *c);
+static void print_type_string (const char *c);
int
-main (int argc, char **argv)
+main (int argc, char **argv ATTRIBUTE_UNUSED)
{
if (argc != 1)
{
@@ -86,22 +86,22 @@ Usage: intdoc > intdoc.texi\n\
struct _ffeintrin_name_
{
- char *name_uc;
- char *name_lc;
- char *name_ic;
+ const char *name_uc;
+ const char *name_lc;
+ const char *name_ic;
ffeintrinGen generic;
ffeintrinSpec specific;
};
struct _ffeintrin_gen_
{
- char *name; /* Name as seen in program. */
+ const char *name; /* Name as seen in program. */
ffeintrinSpec specs[2];
};
struct _ffeintrin_spec_
{
- char *name; /* Uppercase name as seen in source code,
+ const char *name; /* Uppercase name as seen in source code,
lowercase if no source name, "none" if no
name at all (NONE case). */
bool is_actualarg; /* Ok to pass as actual arg if -pedantic. */
@@ -111,11 +111,11 @@ struct _ffeintrin_spec_
struct _ffeintrin_imp_
{
- char *name; /* Name of implementation. */
+ const char *name; /* Name of implementation. */
#if 0 /* FFECOM_targetCURRENT == FFECOM_targetGCC */
ffecomGfrt gfrt; /* gfrt index in library. */
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
- char *control;
+ const char *control;
};
static struct _ffeintrin_name_ names[] = {
@@ -124,11 +124,13 @@ static struct _ffeintrin_name_ names[] = {
#define DEFGEN(CODE,NAME,SPEC1,SPEC2)
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFNAME
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
static struct _ffeintrin_gen_ gens[] = {
@@ -137,11 +139,13 @@ static struct _ffeintrin_gen_ gens[] = {
{ NAME, { SPEC1, SPEC2, }, },
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFNAME
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
static struct _ffeintrin_imp_ imps[] = {
@@ -151,9 +155,13 @@ static struct _ffeintrin_imp_ imps[] = {
#if 0 /* FFECOM_targetCURRENT == FFECOM_targetGCC */
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
{ NAME, FFECOM_gfrt ## GFRT, CONTROL },
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
+ { NAME, FFECOM_gfrt ## GFRT, CONTROL },
#elif 1 /* FFECOM_targetCURRENT == FFECOM_targetFFE */
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
{ NAME, CONTROL },
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
+ { NAME, CONTROL },
#else
#error
#endif
@@ -162,6 +170,7 @@ static struct _ffeintrin_imp_ imps[] = {
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
static struct _ffeintrin_spec_ specs[] = {
@@ -170,29 +179,31 @@ static struct _ffeintrin_spec_ specs[] = {
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP) \
{ NAME, CALLABLE, FAMILY, IMP, },
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
-struct cc_pair { ffeintrinImp imp; char *text; };
+struct cc_pair { ffeintrinImp imp; const char *text; };
-static char *descriptions[FFEINTRIN_imp] = { 0 };
+static const char *descriptions[FFEINTRIN_imp] = { 0 };
static struct cc_pair cc_descriptions[] = {
#define DEFDOC(IMP,SUMMARY,DESCRIPTION) { FFEINTRIN_imp ## IMP, DESCRIPTION },
#include "intdoc.h0"
#undef DEFDOC
};
-static char *summaries[FFEINTRIN_imp] = { 0 };
+static const char *summaries[FFEINTRIN_imp] = { 0 };
static struct cc_pair cc_summaries[] = {
#define DEFDOC(IMP,SUMMARY,DESCRIPTION) { FFEINTRIN_imp ## IMP, SUMMARY },
#include "intdoc.h0"
#undef DEFDOC
};
-char *
+const char *
family_name (ffeintrinFamily family)
{
switch (family)
@@ -313,7 +324,7 @@ dumpem ()
}
static void
-dumpgen (int menu, char *name, char *name_uc, ffeintrinGen gen)
+dumpgen (int menu, const char *name, const char *name_uc, ffeintrinGen gen)
{
size_t i;
int total = 0;
@@ -366,7 +377,7 @@ For information on other intrinsics with the same name:\n");
}
static void
-dumpspec (int menu, char *name, char *name_uc, ffeintrinSpec spec)
+dumpspec (int menu, const char *name, const char *name_uc, ffeintrinSpec spec)
{
dumpif (specs[spec].family);
dumpimp (menu, name, name_uc, 0, specs[spec].family, specs[spec].implementation,
@@ -375,13 +386,13 @@ dumpspec (int menu, char *name, char *name_uc, ffeintrinSpec spec)
}
static void
-dumpimp (int menu, char *name, char *name_uc, size_t genno, ffeintrinFamily family, ffeintrinImp imp,
- ffeintrinSpec spec)
+dumpimp (int menu, const char *name, const char *name_uc, size_t genno,
+ ffeintrinFamily family, ffeintrinImp imp, ffeintrinSpec spec)
{
- char *c;
+ const char *c;
bool subr;
- char *argc;
- char *argi;
+ const char *argc;
+ const char *argi;
int colon;
int argno;
@@ -399,7 +410,7 @@ dumpimp (int menu, char *name, char *name_uc, size_t genno, ffeintrinFamily fami
|| (summaries[imp] != NULL))
{
int spaces = INDENT_SUMMARY - 14 - strlen (name);
- char *c;
+ const char *c;
if (spec != FFEINTRIN_specNONE)
spaces -= (3 + strlen (specs[spec].name)); /* See XYZZY1 above */
@@ -509,8 +520,8 @@ external procedure.\n\
if (!subr)
{
int other_arg;
- char *arg_string;
- char *arg_info;
+ const char *arg_string;
+ const char *arg_info;
if ((c[colon + 1] >= '0')
&& (c[colon + 1] <= '9'))
@@ -1019,7 +1030,7 @@ Intrinsic groups: ");
if (descriptions[imp] != NULL)
{
- char *c = descriptions[imp];
+ const char *c = descriptions[imp];
printf ("\
@noindent\n\
@@ -1056,10 +1067,10 @@ Description:\n\
}
}
-static char *
+static const char *
argument_info_ptr (ffeintrinImp imp, int argno)
{
- char *c = imps[imp].control;
+ const char *c = imps[imp].control;
static char arginfos[8][32];
static int argx = 0;
int i;
@@ -1099,20 +1110,20 @@ argument_info_ptr (ffeintrinImp imp, int argno)
return c;
}
-static char *
+static const char *
argument_info_string (ffeintrinImp imp, int argno)
{
- char *p;
+ const char *p;
p = argument_info_ptr (imp, argno);
assert (p != NULL);
return p;
}
-static char *
+static const char *
argument_name_ptr (ffeintrinImp imp, int argno)
{
- char *c = imps[imp].control;
+ const char *c = imps[imp].control;
static char argnames[8][32];
static int argx = 0;
int i;
@@ -1148,10 +1159,10 @@ argument_name_ptr (ffeintrinImp imp, int argno)
return c;
}
-static char *
+static const char *
argument_name_string (ffeintrinImp imp, int argno)
{
- char *p;
+ const char *p;
p = argument_name_ptr (imp, argno);
assert (p != NULL);
@@ -1159,7 +1170,7 @@ argument_name_string (ffeintrinImp imp, int argno)
}
static void
-print_type_string (char *c)
+print_type_string (const char *c)
{
char basic = c[0];
char kind = c[1];
diff --git a/contrib/gcc/f/intdoc.in b/contrib/gcc/f/intdoc.in
index 203dd61..565b771 100644
--- a/contrib/gcc/f/intdoc.in
+++ b/contrib/gcc/f/intdoc.in
@@ -1043,9 +1043,9 @@ and returns that string as the function value.
")
DEFDOC (CTIME_subr, "Convert time to Day Mon dd hh:mm:ss yyyy.", "\
-Converts @var{@2@}, a system time value, such as returned by
+Converts @var{@1@}, a system time value, such as returned by
@code{TIME8()}, to a string of the form @samp{Sat Aug 19 18:13:14 1995},
-and returns that string in @var{@1@}.
+and returns that string in @var{@2@}.
@xref{Time8 Intrinsic}.
@@ -1059,7 +1059,11 @@ representing the numeric day of the month @var{dd}, a three-character
abbreviation of the month name @var{mmm} and the last two digits of
the year @var{yy}, e.g.@: @samp{25-Nov-96}.
+@cindex Y2K compliance
+@cindex Year 2000 compliance
This intrinsic is not recommended, due to the year 2000 approaching.
+Therefore, programs making use of this intrinsic
+might not be Year 2000 (Y2K) compliant.
@xref{CTime Intrinsic (subroutine)}, for information on obtaining more digits
for the current (or any) date.
")
@@ -1075,6 +1079,16 @@ The functions' value is equal to @samp{@var{@1@}(1) + @var{@1@}(2)}.
Subsequent invocations of @samp{@0@()} return values accumulated since the
previous invocation.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
Due to the side effects performed by this intrinsic, the function
form is not recommended.
")
@@ -1082,14 +1096,24 @@ form is not recommended.
DEFDOC (DTIME_subr, "Get elapsed time since last time.", "\
Initially, return the number of seconds of runtime
since the start of the process's execution
-in @var{@1@},
-and the user and system components of this in @samp{@var{@2@}(1)}
-and @samp{@var{@2@}(2)} respectively.
-The value of @var{@1@} is equal to @samp{@var{@2@}(1) + @var{@2@}(2)}.
+in @var{@2@},
+and the user and system components of this in @samp{@var{@1@}(1)}
+and @samp{@var{@1@}(2)} respectively.
+The value of @var{@2@} is equal to @samp{@var{@1@}(1) + @var{@1@}(2)}.
Subsequent invocations of @samp{@0@()} set values based on accumulations
since the previous invocation.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine.
")
@@ -1101,15 +1125,35 @@ as the function value,
and the user and system components of this in @samp{@var{@1@}(1)}
and @samp{@var{@1@}(2)} respectively.
The functions' value is equal to @samp{@var{@1@}(1) + @var{@1@}(2)}.
+
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
")
DEFDOC (ETIME_subr, "Get elapsed time for process.", "\
Return the number of seconds of runtime
since the start of the process's execution
-in @var{@1@},
-and the user and system components of this in @samp{@var{@2@}(1)}
-and @samp{@var{@2@}(2)} respectively.
-The value of @var{@1@} is equal to @samp{@var{@2@}(1) + @var{@2@}(2)}.
+in @var{@2@},
+and the user and system components of this in @samp{@var{@1@}(1)}
+and @samp{@var{@1@}(2)} respectively.
+The value of @var{@2@} is equal to @samp{@var{@1@}(1) + @var{@1@}(2)}.
+
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine.
@@ -1124,6 +1168,17 @@ Equivalent to:
CTIME(TIME8())
@end example
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
@xref{CTime Intrinsic (function)}.
")
@@ -1137,6 +1192,17 @@ Equivalent to:
CALL CTIME(@var{@1@}, TIME8())
@end example
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
@xref{CTime Intrinsic (subroutine)}.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -1226,6 +1292,17 @@ Fills @var{@1@} with the numerical values at the current local time
of day, month (in the range 1--12), and year in elements 1, 2, and 3,
respectively.
The year has four significant digits.
+
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
")
DEFDOC (IDATE_vxt, "Get local time info (VAX/VMS).", "\
@@ -1234,7 +1311,20 @@ The month (in the range 1--12) is returned in @var{@1@},
the day (in the range 1--7) in @var{@2@},
and the year in @var{@3@} (in the range 0--99).
+@cindex Y2K compliance
+@cindex Year 2000 compliance
+@cindex wraparound, Y2K
+@cindex limits, Y2K
This intrinsic is not recommended, due to the year 2000 approaching.
+Therefore, programs making use of this intrinsic
+might not be Year 2000 (Y2K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 2000.
+
+@xref{IDate Intrinsic (UNIX)}, for information on obtaining more digits
+for the current date.
")
DEFDOC (ITIME, "Get local time of day.", "\
@@ -1246,9 +1336,16 @@ DEFDOC (MCLOCK, "Get number of clock ticks for process.", "\
Returns the number of clock ticks since the start of the process.
Supported on systems with @code{clock(3)} (q.v.).
+@cindex wraparound, timings
+@cindex limits, timings
This intrinsic is not fully portable, such as to systems
with 32-bit @code{INTEGER} types but supporting times
wider than 32 bits.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
@xref{MClock8 Intrinsic}, for information on a
similar intrinsic that might be portable to more
GNU Fortran implementations, though to fewer
@@ -1262,12 +1359,18 @@ DEFDOC (MCLOCK8, "Get number of clock ticks for process.", "\
Returns the number of clock ticks since the start of the process.
Supported on systems with @code{clock(3)} (q.v.).
+@cindex wraparound, timings
+@cindex limits, timings
@emph{Warning:} this intrinsic does not increase the range
of the timing values over that returned by @code{clock(3)}.
On a system with a 32-bit @code{clock(3)},
@code{@0@} will return a 32-bit value,
even though converted to an @samp{INTEGER(KIND=2)} value.
That means overflows of the 32-bit value can still occur.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
No Fortran implementations other than GNU Fortran are
known to support this intrinsic at the time of this
@@ -1283,17 +1386,45 @@ If the system does not support @code{clock(3)},
DEFDOC (SECNDS, "Get local time offset since midnight.", "\
Returns the local time in seconds since midnight minus the value
@var{@1@}.
+
+@cindex wraparound, timings
+@cindex limits, timings
+This values returned by this intrinsic
+become numerically less than previous values
+(they wrap around) during a single run of the
+compiler program, under normal circumstances
+(such as running through the midnight hour).
")
DEFDOC (SECOND_func, "Get CPU time for process in seconds.", "\
Returns the process's runtime in seconds---the same value as the
UNIX function @code{etime} returns.
+
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
")
DEFDOC (SECOND_subr, "Get CPU time for process@99@in seconds.", "\
Returns the process's runtime in seconds in @var{@1@}---the same value
as the UNIX function @code{etime} returns.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
This routine is known from Cray Fortran. @xref{CPU_Time Intrinsic},
for a standard equivalent.
")
@@ -1307,12 +1438,32 @@ isn't in general.
@var{@3@} is the maximum value this can take, which isn't very useful
in this implementation since it's just the maximum C @code{unsigned
int} value.
+
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
")
DEFDOC (CPU_TIME, "Get current CPU time.", "\
Returns in @var{@1@} the current value of the system time.
This implementation of the Fortran 95 intrinsic is just an alias for
@code{second} @xref{Second Intrinsic (subroutine)}.
+
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
")
DEFDOC (TIME8, "Get current time as time value.", "\
@@ -1321,12 +1472,18 @@ Returns the current time encoded as a long integer
This value is suitable for passing to @code{CTIME},
@code{GMTIME}, and @code{LTIME}.
+@cindex wraparound, timings
+@cindex limits, timings
@emph{Warning:} this intrinsic does not increase the range
of the timing values over that returned by @code{time(3)}.
On a system with a 32-bit @code{time(3)},
@code{@0@} will return a 32-bit value,
even though converted to an @samp{INTEGER(KIND=2)} value.
That means overflows of the 32-bit value can still occur.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
No Fortran implementations other than GNU Fortran are
known to support this intrinsic at the time of this
@@ -1342,9 +1499,16 @@ Returns the current time encoded as an integer
This value is suitable for passing to @code{CTIME},
@code{GMTIME}, and @code{LTIME}.
+@cindex wraparound, timings
+@cindex limits, timings
This intrinsic is not fully portable, such as to systems
with 32-bit @code{INTEGER} types but supporting times
wider than 32 bits.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
@xref{Time8 Intrinsic}, for information on a
similar intrinsic that might be portable to more
GNU Fortran implementations, though to fewer
@@ -1378,7 +1542,7 @@ See @code{erf(3m)}, which provides the implementation.
DEFDOC (ERFC, "Complementary error function.", "\
Returns the complementary error function of @var{@1@}:
-@samp{ERFC(R) = 1 - ERF(R)} (except that the result may be more
+@samp{ERFC(R) = 1 - ERF(R)} (except that the result might be more
accurate than explicitly evaluating that formulae would give).
See @code{erfc(3m)}, which provides the implementation.
")
@@ -1458,7 +1622,7 @@ See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
non-absolute file name can cause subsequent I/O on such a unit to fail
-because the I/O library may reopen files by name.
+because the I/O library might reopen files by name.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -1472,7 +1636,7 @@ See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
non-absolute file name can cause subsequent I/O on such a unit to fail
-because the I/O library may reopen files by name.
+because the I/O library might reopen files by name.
Due to the side effects performed by this intrinsic, the function
form is not recommended.
@@ -1492,7 +1656,7 @@ Returns 0 on success or a non-zero error code otherwise.
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
-the library was configured) and so may fail in some circumstances and
+the library was configured) and so might fail in some circumstances and
will, anyway, be slow.
Due to the side effects performed by this intrinsic, the function
@@ -1514,7 +1678,7 @@ If the @var{@3@} argument is supplied, it contains
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
-the library was configured) and so may fail in some circumstances and
+the library was configured) and so might fail in some circumstances and
will, anyway, be slow.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2077,7 +2241,7 @@ Fills @var{@1@} with the system's host name returned by
@code{gethostname(2)}, returning 0 on success or a non-zero error code
(@code{ENOSYS} if the system does not provide @code{gethostname(2)}).
-On some systems (specifically SCO) it may be necessary to link the
+On some systems (specifically SCO) it might be necessary to link the
``socket'' library if you call this routine.
Typically this means adding @samp{-lg2c -lsocket -lm}
to the @code{g77} command line when linking the program.
@@ -2094,7 +2258,7 @@ Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
(optional) @var{@2@} argument.
-On some systems (specifically SCO) it may be necessary to link the
+On some systems (specifically SCO) it might be necessary to link the
``socket'' library if you call this routine.
Typically this means adding @samp{-lg2c -lsocket -lm}
to the @code{g77} command line when linking the program.
@@ -2217,8 +2381,8 @@ terminal.
")
DEFDOC (TTYNAM_subr, "Get name of terminal device for unit.", "\
-Sets @var{@1@} to the name of the terminal device open on logical unit
-@var{@2@} or a blank string if @var{@2@} is not connected to a
+Sets @var{@2@} to the name of the terminal device open on logical unit
+@var{@1@} or to a blank string if @var{@1@} is not connected to a
terminal.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2415,7 +2579,18 @@ DEFDOC (TIME_vxt, "Get the time as a character value.", "\
Returns in @var{@1@} a character representation of the current time as
obtained from @code{ctime(3)}.
-@xref{Fdate Intrinsic (subroutine)}, for an equivalent routine.
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
+@xref{FDate Intrinsic (subroutine)}, for an equivalent routine.
")
DEFDOC (IBCLR, "Clear a bit.", "\
@@ -2445,8 +2620,7 @@ All bits representing @var{@1@} are shifted @var{@2@} places.
indicates no shift and @samp{@var{@2@}.LT.0} indicates a right shift.
If the absolute value of the shift count is greater than
@samp{BIT_SIZE(@var{@1@})}, the result is undefined.
-Bits shifted out from the left end or the right end, as the case may be,
-are lost.
+Bits shifted out from the left end or the right end are lost.
Zeros are shifted in from the opposite end.
@xref{IShftC Intrinsic}, for the circular-shift equivalent.
@@ -2514,6 +2688,17 @@ of the minute, and milliseconds
of the second in successive values of the array.
@end table
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
On systems where a millisecond timer isn't available, the millisecond
value is returned as zero.
")
diff --git a/contrib/gcc/f/intdoc.texi b/contrib/gcc/f/intdoc.texi
index a507d41..a34f700 100644
--- a/contrib/gcc/f/intdoc.texi
+++ b/contrib/gcc/f/intdoc.texi
@@ -274,10 +274,10 @@
* DTanH Intrinsic:: Hyperbolic tangent (archaic).
@end ifset
@ifset familyF2U
-* Dtime Intrinsic (subroutine):: Get elapsed time since last time.
+* DTime Intrinsic (subroutine):: Get elapsed time since last time.
@end ifset
@ifset familyBADU77
-* Dtime Intrinsic (function):: Get elapsed time since last time.
+* DTime Intrinsic (function):: Get elapsed time since last time.
@end ifset
@ifset familyF90
* EOShift Intrinsic:: (Reserved for future use.)
@@ -297,8 +297,8 @@
* Exponent Intrinsic:: (Reserved for future use.)
@end ifset
@ifset familyF2U
-* Fdate Intrinsic (subroutine):: Get current time as Day Mon dd hh:mm:ss yyyy.
-* Fdate Intrinsic (function):: Get current time as Day Mon dd hh:mm:ss yyyy.
+* FDate Intrinsic (subroutine):: Get current time as Day Mon dd hh:mm:ss yyyy.
+* FDate Intrinsic (function):: Get current time as Day Mon dd hh:mm:ss yyyy.
* FGet Intrinsic (subroutine):: Read a character from unit 5 stream-wise.
@end ifset
@ifset familyBADU77
@@ -2231,7 +2231,7 @@ See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
non-absolute file name can cause subsequent I/O on such a unit to fail
-because the I/O library may reopen files by name.
+because the I/O library might reopen files by name.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -2270,7 +2270,7 @@ See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
non-absolute file name can cause subsequent I/O on such a unit to fail
-because the I/O library may reopen files by name.
+because the I/O library might reopen files by name.
Due to the side effects performed by this intrinsic, the function
form is not recommended.
@@ -2319,7 +2319,7 @@ If the @var{Status} argument is supplied, it contains
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
-the library was configured) and so may fail in some circumstances and
+the library was configured) and so might fail in some circumstances and
will, anyway, be slow.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2369,7 +2369,7 @@ Returns 0 on success or a non-zero error code otherwise.
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
-the library was configured) and so may fail in some circumstances and
+the library was configured) and so might fail in some circumstances and
will, anyway, be slow.
Due to the side effects performed by this intrinsic, the function
@@ -2626,6 +2626,16 @@ Returns in @var{Seconds} the current value of the system time.
This implementation of the Fortran 95 intrinsic is just an alias for
@code{second} @xref{Second Intrinsic (subroutine)}.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
@node CShift Intrinsic
@subsubsection CShift Intrinsic
@cindex CShift intrinsic
@@ -2699,14 +2709,14 @@ to one type for @var{X}.
@noindent
@example
-CALL CTime(@var{Result}, @var{STime})
+CALL CTime(@var{STime}, @var{Result})
@end example
@noindent
-@var{Result}: @code{CHARACTER}; scalar; INTENT(OUT).
+@var{STime}: @code{INTEGER}; scalar; INTENT(IN).
@noindent
-@var{STime}: @code{INTEGER}; scalar; INTENT(IN).
+@var{Result}: @code{CHARACTER}; scalar; INTENT(OUT).
@noindent
Intrinsic groups: @code{unix}.
@@ -2966,7 +2976,11 @@ representing the numeric day of the month @var{dd}, a three-character
abbreviation of the month name @var{mmm} and the last two digits of
the year @var{yy}, e.g.@: @samp{25-Nov-96}.
+@cindex Y2K compliance
+@cindex Year 2000 compliance
This intrinsic is not recommended, due to the year 2000 approaching.
+Therefore, programs making use of this intrinsic
+might not be Year 2000 (Y2K) compliant.
@xref{CTime Intrinsic (subroutine)}, for information on obtaining more digits
for the current (or any) date.
@@ -3017,6 +3031,17 @@ of the minute, and milliseconds
of the second in successive values of the array.
@end table
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
On systems where a millisecond timer isn't available, the millisecond
value is returned as zero.
@@ -4088,21 +4113,21 @@ to one type for @var{X}.
@end ifset
@ifset familyF2U
-@node Dtime Intrinsic (subroutine)
-@subsubsection Dtime Intrinsic (subroutine)
-@cindex Dtime intrinsic
-@cindex intrinsics, Dtime
+@node DTime Intrinsic (subroutine)
+@subsubsection DTime Intrinsic (subroutine)
+@cindex DTime intrinsic
+@cindex intrinsics, DTime
@noindent
@example
-CALL Dtime(@var{Result}, @var{TArray})
+CALL DTime(@var{TArray}, @var{Result})
@end example
@noindent
-@var{Result}: @code{REAL(KIND=1)}; scalar; INTENT(OUT).
+@var{TArray}: @code{REAL(KIND=1)}; DIMENSION(2); INTENT(OUT).
@noindent
-@var{TArray}: @code{REAL(KIND=1)}; DIMENSION(2); INTENT(OUT).
+@var{Result}: @code{REAL(KIND=1)}; scalar; INTENT(OUT).
@noindent
Intrinsic groups: @code{unix}.
@@ -4120,26 +4145,36 @@ The value of @var{Result} is equal to @samp{@var{TArray}(1) + @var{TArray}(2)}.
Subsequent invocations of @samp{DTIME()} set values based on accumulations
since the previous invocation.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine.
For information on other intrinsics with the same name:
-@xref{Dtime Intrinsic (function)}.
+@xref{DTime Intrinsic (function)}.
@end ifset
@ifset familyBADU77
-@node Dtime Intrinsic (function)
-@subsubsection Dtime Intrinsic (function)
-@cindex Dtime intrinsic
-@cindex intrinsics, Dtime
+@node DTime Intrinsic (function)
+@subsubsection DTime Intrinsic (function)
+@cindex DTime intrinsic
+@cindex intrinsics, DTime
@noindent
@example
-Dtime(@var{TArray})
+DTime(@var{TArray})
@end example
@noindent
-Dtime: @code{REAL(KIND=1)} function.
+DTime: @code{REAL(KIND=1)} function.
@noindent
@var{TArray}: @code{REAL(KIND=1)}; DIMENSION(2); INTENT(OUT).
@@ -4160,11 +4195,21 @@ The functions' value is equal to @samp{@var{TArray}(1) + @var{TArray}(2)}.
Subsequent invocations of @samp{DTIME()} return values accumulated since the
previous invocation.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
Due to the side effects performed by this intrinsic, the function
form is not recommended.
For information on other intrinsics with the same name:
-@xref{Dtime Intrinsic (subroutine)}.
+@xref{DTime Intrinsic (subroutine)}.
@end ifset
@ifset familyF90
@@ -4238,7 +4283,7 @@ Intrinsic groups: @code{unix}.
Description:
Returns the complementary error function of @var{X}:
-@samp{ERFC(R) = 1 - ERF(R)} (except that the result may be more
+@samp{ERFC(R) = 1 - ERF(R)} (except that the result might be more
accurate than explicitly evaluating that formulae would give).
See @code{erfc(3m)}, which provides the implementation.
@@ -4249,14 +4294,14 @@ See @code{erfc(3m)}, which provides the implementation.
@noindent
@example
-CALL ETime(@var{Result}, @var{TArray})
+CALL ETime(@var{TArray}, @var{Result})
@end example
@noindent
-@var{Result}: @code{REAL(KIND=1)}; scalar; INTENT(OUT).
+@var{TArray}: @code{REAL(KIND=1)}; DIMENSION(2); INTENT(OUT).
@noindent
-@var{TArray}: @code{REAL(KIND=1)}; DIMENSION(2); INTENT(OUT).
+@var{Result}: @code{REAL(KIND=1)}; scalar; INTENT(OUT).
@noindent
Intrinsic groups: @code{unix}.
@@ -4271,6 +4316,16 @@ and the user and system components of this in @samp{@var{TArray}(1)}
and @samp{@var{TArray}(2)} respectively.
The value of @var{Result} is equal to @samp{@var{TArray}(1) + @var{TArray}(2)}.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine.
@@ -4306,6 +4361,16 @@ and the user and system components of this in @samp{@var{TArray}(1)}
and @samp{@var{TArray}(2)} respectively.
The functions' value is equal to @samp{@var{TArray}(1) + @var{TArray}(2)}.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
For information on other intrinsics with the same name:
@xref{ETime Intrinsic (subroutine)}.
@@ -4376,14 +4441,14 @@ external procedure.
@end ifset
@ifset familyF2U
-@node Fdate Intrinsic (subroutine)
-@subsubsection Fdate Intrinsic (subroutine)
-@cindex Fdate intrinsic
-@cindex intrinsics, Fdate
+@node FDate Intrinsic (subroutine)
+@subsubsection FDate Intrinsic (subroutine)
+@cindex FDate intrinsic
+@cindex intrinsics, FDate
@noindent
@example
-CALL Fdate(@var{Date})
+CALL FDate(@var{Date})
@end example
@noindent
@@ -4404,26 +4469,37 @@ Equivalent to:
CALL CTIME(@var{Date}, TIME8())
@end example
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
@xref{CTime Intrinsic (subroutine)}.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine.
For information on other intrinsics with the same name:
-@xref{Fdate Intrinsic (function)}.
+@xref{FDate Intrinsic (function)}.
-@node Fdate Intrinsic (function)
-@subsubsection Fdate Intrinsic (function)
-@cindex Fdate intrinsic
-@cindex intrinsics, Fdate
+@node FDate Intrinsic (function)
+@subsubsection FDate Intrinsic (function)
+@cindex FDate intrinsic
+@cindex intrinsics, FDate
@noindent
@example
-Fdate()
+FDate()
@end example
@noindent
-Fdate: @code{CHARACTER*(*)} function.
+FDate: @code{CHARACTER*(*)} function.
@noindent
Intrinsic groups: @code{unix}.
@@ -4439,10 +4515,21 @@ Equivalent to:
CTIME(TIME8())
@end example
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
@xref{CTime Intrinsic (function)}.
For information on other intrinsics with the same name:
-@xref{Fdate Intrinsic (subroutine)}.
+@xref{FDate Intrinsic (subroutine)}.
@node FGet Intrinsic (subroutine)
@subsubsection FGet Intrinsic (subroutine)
@@ -5457,7 +5544,7 @@ Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
(optional) @var{Status} argument.
-On some systems (specifically SCO) it may be necessary to link the
+On some systems (specifically SCO) it might be necessary to link the
``socket'' library if you call this routine.
Typically this means adding @samp{-lg2c -lsocket -lm}
to the @code{g77} command line when linking the program.
@@ -5491,7 +5578,7 @@ Fills @var{Name} with the system's host name returned by
@code{gethostname(2)}, returning 0 on success or a non-zero error code
(@code{ENOSYS} if the system does not provide @code{gethostname(2)}).
-On some systems (specifically SCO) it may be necessary to link the
+On some systems (specifically SCO) it might be necessary to link the
``socket'' library if you call this routine.
Typically this means adding @samp{-lg2c -lsocket -lm}
to the @code{g77} command line when linking the program.
@@ -5811,6 +5898,17 @@ of day, month (in the range 1--12), and year in elements 1, 2, and 3,
respectively.
The year has four significant digits.
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
For information on other intrinsics with the same name:
@xref{IDate Intrinsic (VXT)}.
@@ -5846,7 +5944,20 @@ The month (in the range 1--12) is returned in @var{M},
the day (in the range 1--7) in @var{D},
and the year in @var{Y} (in the range 0--99).
+@cindex Y2K compliance
+@cindex Year 2000 compliance
+@cindex wraparound, Y2K
+@cindex limits, Y2K
This intrinsic is not recommended, due to the year 2000 approaching.
+Therefore, programs making use of this intrinsic
+might not be Year 2000 (Y2K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 2000.
+
+@xref{IDate Intrinsic (UNIX)}, for information on obtaining more digits
+for the current date.
For information on other intrinsics with the same name:
@xref{IDate Intrinsic (UNIX)}.
@@ -6603,8 +6714,7 @@ All bits representing @var{I} are shifted @var{Shift} places.
indicates no shift and @samp{@var{Shift}.LT.0} indicates a right shift.
If the absolute value of the shift count is greater than
@samp{BIT_SIZE(@var{I})}, the result is undefined.
-Bits shifted out from the left end or the right end, as the case may be,
-are lost.
+Bits shifted out from the left end or the right end are lost.
Zeros are shifted in from the opposite end.
@xref{IShftC Intrinsic}, for the circular-shift equivalent.
@@ -7997,9 +8107,16 @@ Description:
Returns the number of clock ticks since the start of the process.
Supported on systems with @code{clock(3)} (q.v.).
+@cindex wraparound, timings
+@cindex limits, timings
This intrinsic is not fully portable, such as to systems
with 32-bit @code{INTEGER} types but supporting times
wider than 32 bits.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
@xref{MClock8 Intrinsic}, for information on a
similar intrinsic that might be portable to more
GNU Fortran implementations, though to fewer
@@ -8030,12 +8147,18 @@ Description:
Returns the number of clock ticks since the start of the process.
Supported on systems with @code{clock(3)} (q.v.).
+@cindex wraparound, timings
+@cindex limits, timings
@emph{Warning:} this intrinsic does not increase the range
of the timing values over that returned by @code{clock(3)}.
On a system with a 32-bit @code{clock(3)},
@code{MCLOCK8} will return a 32-bit value,
even though converted to an @samp{INTEGER(KIND=2)} value.
That means overflows of the 32-bit value can still occur.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
No Fortran implementations other than GNU Fortran are
known to support this intrinsic at the time of this
@@ -9141,6 +9264,14 @@ Description:
Returns the local time in seconds since midnight minus the value
@var{T}.
+@cindex wraparound, timings
+@cindex limits, timings
+This values returned by this intrinsic
+become numerically less than previous values
+(they wrap around) during a single run of the
+compiler program, under normal circumstances
+(such as running through the midnight hour).
+
@end ifset
@ifset familyF2U
@node Second Intrinsic (function)
@@ -9165,6 +9296,16 @@ Description:
Returns the process's runtime in seconds---the same value as the
UNIX function @code{etime} returns.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
For information on other intrinsics with the same name:
@xref{Second Intrinsic (subroutine)}.
@@ -9190,6 +9331,16 @@ Description:
Returns the process's runtime in seconds in @var{Seconds}---the same value
as the UNIX function @code{etime} returns.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
This routine is known from Cray Fortran. @xref{CPU_Time Intrinsic},
for a standard equivalent.
@@ -10086,6 +10237,16 @@ isn't in general.
in this implementation since it's just the maximum C @code{unsigned
int} value.
+@cindex wraparound, timings
+@cindex limits, timings
+On some systems, the underlying timings are represented
+using types with sufficiently small limits that overflows
+(wraparounds) are possible, such as 32-bit types.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
@end ifset
@ifset familyF77
@node Tan Intrinsic
@@ -10179,9 +10340,16 @@ Returns the current time encoded as an integer
This value is suitable for passing to @code{CTIME},
@code{GMTIME}, and @code{LTIME}.
+@cindex wraparound, timings
+@cindex limits, timings
This intrinsic is not fully portable, such as to systems
with 32-bit @code{INTEGER} types but supporting times
wider than 32 bits.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
+
@xref{Time8 Intrinsic}, for information on a
similar intrinsic that might be portable to more
GNU Fortran implementations, though to fewer
@@ -10214,7 +10382,18 @@ Description:
Returns in @var{Time} a character representation of the current time as
obtained from @code{ctime(3)}.
-@xref{Fdate Intrinsic (subroutine)}, for an equivalent routine.
+@cindex Y10K compliance
+@cindex Year 10000 compliance
+@cindex wraparound, Y10K
+@cindex limits, Y10K
+Programs making use of this intrinsic
+might not be Year 10000 (Y10K) compliant.
+For example, the date might appear,
+to such programs, to wrap around
+(change from a larger value to a smaller one)
+as of the Year 10000.
+
+@xref{FDate Intrinsic (subroutine)}, for an equivalent routine.
For information on other intrinsics with the same name:
@xref{Time Intrinsic (UNIX)}.
@@ -10245,12 +10424,18 @@ Returns the current time encoded as a long integer
This value is suitable for passing to @code{CTIME},
@code{GMTIME}, and @code{LTIME}.
+@cindex wraparound, timings
+@cindex limits, timings
@emph{Warning:} this intrinsic does not increase the range
of the timing values over that returned by @code{time(3)}.
On a system with a 32-bit @code{time(3)},
@code{TIME8} will return a 32-bit value,
even though converted to an @samp{INTEGER(KIND=2)} value.
That means overflows of the 32-bit value can still occur.
+Therefore, the values returned by this intrinsic
+might be, or become, negative,
+or numerically less than previous values,
+during a single run of the compiled program.
No Fortran implementations other than GNU Fortran are
known to support this intrinsic at the time of this
@@ -10310,14 +10495,14 @@ external procedure.
@noindent
@example
-CALL TtyNam(@var{Name}, @var{Unit})
+CALL TtyNam(@var{Unit}, @var{Name})
@end example
@noindent
-@var{Name}: @code{CHARACTER}; scalar; INTENT(OUT).
+@var{Unit}: @code{INTEGER}; scalar; INTENT(IN).
@noindent
-@var{Unit}: @code{INTEGER}; scalar; INTENT(IN).
+@var{Name}: @code{CHARACTER}; scalar; INTENT(OUT).
@noindent
Intrinsic groups: @code{unix}.
@@ -10326,7 +10511,7 @@ Intrinsic groups: @code{unix}.
Description:
Sets @var{Name} to the name of the terminal device open on logical unit
-@var{Unit} or a blank string if @var{Unit} is not connected to a
+@var{Unit} or to a blank string if @var{Unit} is not connected to a
terminal.
Some non-GNU implementations of Fortran provide this intrinsic as
diff --git a/contrib/gcc/f/intrin.c b/contrib/gcc/f/intrin.c
index 6e27d21..dbf375b 100644
--- a/contrib/gcc/f/intrin.c
+++ b/contrib/gcc/f/intrin.c
@@ -1,6 +1,6 @@
/* intrin.c -- Recognize references to intrinsics
Copyright (C) 1995-1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -32,22 +32,22 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
struct _ffeintrin_name_
{
- char *name_uc;
- char *name_lc;
- char *name_ic;
+ const char *name_uc;
+ const char *name_lc;
+ const char *name_ic;
ffeintrinGen generic;
ffeintrinSpec specific;
};
struct _ffeintrin_gen_
{
- char *name; /* Name as seen in program. */
+ const char *name; /* Name as seen in program. */
ffeintrinSpec specs[2];
};
struct _ffeintrin_spec_
{
- char *name; /* Uppercase name as seen in source code,
+ const char *name; /* Uppercase name as seen in source code,
lowercase if no source name, "none" if no
name at all (NONE case). */
bool is_actualarg; /* Ok to pass as actual arg if -pedantic. */
@@ -57,13 +57,14 @@ struct _ffeintrin_spec_
struct _ffeintrin_imp_
{
- char *name; /* Name of implementation. */
+ const char *name; /* Name of implementation. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
ffecomGfrt gfrt_direct; /* library routine, direct-callable form. */
ffecomGfrt gfrt_f2c; /* library routine, f2c-callable form. */
ffecomGfrt gfrt_gnu; /* library routine, gnu-callable form. */
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
- char *control;
+ const char *control;
+ char y2kbad;
};
static ffebad ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
@@ -84,11 +85,13 @@ static struct _ffeintrin_name_ ffeintrin_names_[]
#define DEFGEN(CODE,NAME,SPEC1,SPEC2)
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFNAME
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
static struct _ffeintrin_gen_ ffeintrin_gens_[]
@@ -99,11 +102,13 @@ static struct _ffeintrin_gen_ ffeintrin_gens_[]
{ NAME, { SPEC1, SPEC2, }, },
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFNAME
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
static struct _ffeintrin_imp_ ffeintrin_imps_[]
@@ -115,10 +120,15 @@ static struct _ffeintrin_imp_ ffeintrin_imps_[]
#if FFECOM_targetCURRENT == FFECOM_targetGCC
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
{ NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
- FFECOM_gfrt ## GFRTGNU, CONTROL },
+ FFECOM_gfrt ## GFRTGNU, CONTROL, FALSE },
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
+ { NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
+ FFECOM_gfrt ## GFRTGNU, CONTROL, Y2KBAD },
#elif FFECOM_targetCURRENT == FFECOM_targetFFE
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
- { NAME, CONTROL },
+ { NAME, CONTROL, FALSE },
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
+ { NAME, CONTROL, Y2KBAD },
#else
#error
#endif
@@ -127,6 +137,7 @@ static struct _ffeintrin_imp_ ffeintrin_imps_[]
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
static struct _ffeintrin_spec_ ffeintrin_specs_[]
@@ -137,10 +148,12 @@ static struct _ffeintrin_spec_ ffeintrin_specs_[]
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP) \
{ NAME, CALLABLE, FAMILY, IMP, },
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
};
@@ -153,9 +166,9 @@ ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
ffelexToken t,
bool commit)
{
- char *c = ffeintrin_imps_[imp].control;
+ const char *c = ffeintrin_imps_[imp].control;
bool subr = (c[0] == '-');
- char *argc;
+ const char *argc;
ffebld arg;
ffeinfoBasictype bt;
ffeinfoKindtype kt;
@@ -1152,9 +1165,9 @@ ffeintrin_check_any_ (ffebld arglist)
static int
ffeintrin_cmp_name_ (const void *name, const void *intrinsic)
{
- char *uc = (char *) ((struct _ffeintrin_name_ *) intrinsic)->name_uc;
- char *lc = (char *) ((struct _ffeintrin_name_ *) intrinsic)->name_lc;
- char *ic = (char *) ((struct _ffeintrin_name_ *) intrinsic)->name_ic;
+ const char *uc = ((struct _ffeintrin_name_ *) intrinsic)->name_uc;
+ const char *lc = ((struct _ffeintrin_name_ *) intrinsic)->name_lc;
+ const char *ic = ((struct _ffeintrin_name_ *) intrinsic)->name_ic;
return ffesrc_strcmp_2c (ffe_case_intrin (), name, uc, lc, ic);
}
@@ -1374,6 +1387,14 @@ ffeintrin_fulfill_generic (ffebld *expr, ffeinfo *info, ffelexToken t)
ffebad_string (ffeintrin_gens_[gen].name);
ffebad_finish ();
}
+ if (ffeintrin_imps_[imp].y2kbad)
+ {
+ ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
+ ffebad_here (0, ffelex_token_where_line (t),
+ ffelex_token_where_column (t));
+ ffebad_string (ffeintrin_gens_[gen].name);
+ ffebad_finish ();
+ }
}
}
@@ -1408,7 +1429,7 @@ ffeintrin_fulfill_specific (ffebld *expr, ffeinfo *info,
ffeIntrinsicState state;
ffebad error;
bool any = FALSE;
- char *name;
+ const char *name;
op = ffebld_op (*expr);
assert ((op == FFEBLD_opFUNCREF) || (op == FFEBLD_opSUBRREF));
@@ -1489,6 +1510,14 @@ ffeintrin_fulfill_specific (ffebld *expr, ffeinfo *info,
ffebad_string (name);
ffebad_finish ();
}
+ if (ffeintrin_imps_[imp].y2kbad)
+ {
+ ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
+ ffebad_here (0, ffelex_token_where_line (t),
+ ffelex_token_where_column (t));
+ ffebad_string (name);
+ ffebad_finish ();
+ }
}
}
@@ -1522,9 +1551,9 @@ void
ffeintrin_init_0 ()
{
int i;
- char *p1;
- char *p2;
- char *p3;
+ const char *p1;
+ const char *p2;
+ const char *p3;
int colon;
if (!ffe_is_do_internal_checks ())
@@ -1558,8 +1587,9 @@ ffeintrin_init_0 ()
break;
if ((ISDIGIT (*p1) || (*p1 == '_')) && (*p1 == *p2) && (*p1 == *p3))
continue;
- if (! ISUPPER (*p1) || ! ISLOWER (*p2)
- || (*p1 != toupper (*p2)) || ((*p3 != *p1) && (*p3 != *p2)))
+ if (! ISUPPER ((unsigned char)*p1) || ! ISLOWER ((unsigned char)*p2)
+ || (*p1 != toupper ((unsigned char)*p2))
+ || ((*p3 != *p1) && (*p3 != *p2)))
break;
}
assert ((*p1 == *p2) && (*p1 == *p3) && (*p1 == '\0'));
@@ -1567,7 +1597,7 @@ ffeintrin_init_0 ()
for (i = 0; ((size_t) i) < ARRAY_SIZE (ffeintrin_imps_); ++i)
{
- char *c = ffeintrin_imps_[i].control;
+ const char *c = ffeintrin_imps_[i].control;
if (c[0] == '\0')
continue;
@@ -1745,7 +1775,7 @@ ffeintrin_is_actualarg (ffeintrinSpec spec)
/* Determine if name is intrinsic, return info.
- char *name; // C-string name of possible intrinsic.
+ const char *name; // C-string name of possible intrinsic.
ffelexToken t; // NULL if no diagnostic to be given.
bool explicit; // TRUE if INTRINSIC name.
ffeintrinGen gen; // (TRUE only) Generic id of intrinsic.
@@ -1757,7 +1787,7 @@ ffeintrin_is_actualarg (ffeintrinSpec spec)
// kind accordingly. */
bool
-ffeintrin_is_intrinsic (char *name, ffelexToken t, bool explicit,
+ffeintrin_is_intrinsic (const char *name, ffelexToken t, bool explicit,
ffeintrinGen *xgen, ffeintrinSpec *xspec,
ffeintrinImp *ximp)
{
@@ -1968,7 +1998,7 @@ ffeintrin_kindtype (ffeintrinSpec spec)
/* Return name of generic intrinsic. */
-char *
+const char *
ffeintrin_name_generic (ffeintrinGen gen)
{
assert (gen < FFEINTRIN_gen);
@@ -1977,7 +2007,7 @@ ffeintrin_name_generic (ffeintrinGen gen)
/* Return name of intrinsic implementation. */
-char *
+const char *
ffeintrin_name_implementation (ffeintrinImp imp)
{
assert (imp < FFEINTRIN_imp);
@@ -1986,7 +2016,7 @@ ffeintrin_name_implementation (ffeintrinImp imp)
/* Return external/internal name of specific intrinsic. */
-char *
+const char *
ffeintrin_name_specific (ffeintrinSpec spec)
{
assert (spec < FFEINTRIN_spec);
diff --git a/contrib/gcc/f/intrin.def b/contrib/gcc/f/intrin.def
index 0c00dcc..4864abb 100644
--- a/contrib/gcc/f/intrin.def
+++ b/contrib/gcc/f/intrin.def
@@ -133,7 +133,7 @@ DEFNAME ("DSQRT", "dsqrt", "DSqRt", genNONE, specDSQRT)
DEFNAME ("DTAN", "dtan", "DTan", genNONE, specDTAN)
DEFNAME ("DTAND", "dtand", "DTanD", genNONE, specDTAND) /* VXT */
DEFNAME ("DTANH", "dtanh", "DTanH", genNONE, specDTANH)
-DEFNAME ("DTIME", "dtime", "Dtime", genDTIME, specNONE) /* UNIX */
+DEFNAME ("DTIME", "dtime", "DTime", genDTIME, specNONE) /* UNIX */
DEFNAME ("EOSHIFT", "eoshift", "EOShift", genNONE, specEOSHIFT) /* F90 */
DEFNAME ("EPSILON", "epsilon", "Epsilon", genNONE, specEPSILON) /* F90 */
DEFNAME ("ERF", "erf", "ErF", genNONE, specERF) /* UNIX */
@@ -142,7 +142,7 @@ DEFNAME ("ETIME", "etime", "ETime", genETIME, specNONE) /* UNIX */
DEFNAME ("EXIT", "exit", "Exit", genNONE, specEXIT) /* UNIX */
DEFNAME ("EXP", "exp", "Exp", genNONE, specEXP)
DEFNAME ("EXPONENT", "exponent", "Exponent", genNONE, specEXPONENT) /* F90 */
-DEFNAME ("FDATE", "fdate", "Fdate", genFDATE, specNONE) /* UNIX */
+DEFNAME ("FDATE", "fdate", "FDate", genFDATE, specNONE) /* UNIX */
DEFNAME ("FGET", "fget", "FGet", genFGET, specNONE) /* UNIX */
DEFNAME ("FGETC", "fgetc", "FGetC", genFGETC, specNONE) /* UNIX */
DEFNAME ("FLOAT", "float", "Float", genNONE, specFLOAT)
@@ -3006,6 +3006,12 @@ DEFSPEC (NONE,
CONTROL -- A control string, described below.
+ The DEFIMPY macro specifies the above, plus:
+
+ Y2KBAD -- TRUE if the intrinsic is known to be non-Y2K-compliant,
+ FALSE if it is known to be Y2K-compliant. (In terms of
+ interface and libg2c implementation.)
+
*/
/* The control string has the following format:
@@ -3231,8 +3237,8 @@ DEFIMP (CHMOD_subr, "CHMOD_subr", CHMOD,,, "--:-:Name=A1,Mode=A1,Status=?I1w")
DEFIMP (COMPLEX, "COMPLEX", ,,, "C=:*:Real=S*,Imag=S*")
DEFIMP (CPU_TIME, "CPU_TIME", SECOND,,, "--:-:Seconds=R*w")
DEFIMP (CTIME_func, "CTIME_func", CTIME,,, "A1*:-:STime=I*")
-DEFIMP (CTIME_subr, "CTIME_subr", CTIME,,, "--:-:Result=A1w,STime=I*")
-DEFIMP (DATE, "DATE", DATE,,, "--:-:Date=A1w")
+DEFIMP (CTIME_subr, "CTIME_subr", CTIME,,, "--:-:STime=I*,Result=A1w")
+DEFIMPY (DATE, "DATE", DATE,,, "--:-:Date=A1w", TRUE)
DEFIMP (DATE_AND_TIME, "DATE_AND_TIME", DATE_AND_TIME,,, "--:-:Date=A1w,Time=?A1w,Zone=?A1w,Values=?I1(8)w")
DEFIMP (DBESJ0, "DBESJ0", L_BESJ0,,, "R2:-:X=R2")
DEFIMP (DBESJ1, "DBESJ1", L_BESJ1,,, "R2:-:X=R2")
@@ -3247,11 +3253,11 @@ DEFIMP (DFLOAT, "DFLOAT", ,,, "R2:-:A=I*")
DEFIMP (DIMAG, "DIMAG", ,DIMAG,, "R2:-:Z=C2")
DEFIMP (DREAL, "DREAL", ,,, "R2:-:A=N*")
DEFIMP (DTIME_func, "DTIME_func", DTIME,,, "R1:-:TArray=R1(2)w")
-DEFIMP (DTIME_subr, "DTIME_subr", DTIME,,, "--:-:Result=R1w,TArray=R1(2)w")
+DEFIMP (DTIME_subr, "DTIME_subr", DTIME,,, "--:-:TArray=R1(2)w,Result=R1w")
DEFIMP (ERF, "ERF", L_ERF,ERF,, "R=:0:X=R*")
DEFIMP (ERFC, "ERFC", L_ERFC,ERFC,, "R=:0:X=R*")
DEFIMP (ETIME_func, "ETIME_func", ETIME,,, "R1:-:TArray=R1(2)w")
-DEFIMP (ETIME_subr, "ETIME_subr", ETIME,,, "--:-:Result=R1w,TArray=R1(2)w")
+DEFIMP (ETIME_subr, "ETIME_subr", ETIME,,, "--:-:TArray=R1(2)w,Result=R1w")
DEFIMP (EXIT, "EXIT", EXIT,,, "--:-:Status=?I*")
DEFIMP (FDATE_func, "FDATE_func", FDATE,,, "A1*:-:")
DEFIMP (FDATE_subr, "FDATE_subr", FDATE,,, "--:-:Date=A1w")
@@ -3289,7 +3295,7 @@ DEFIMP (IBCLR, "IBCLR", ,,, "I=:0:I=I*,Pos=I*")
DEFIMP (IBITS, "IBITS", ,,, "I=:0:I=I*,Pos=I*,Len=I*")
DEFIMP (IBSET, "IBSET", ,,, "I=:0:I=I*,Pos=I*")
DEFIMP (IDATE_unix, "IDATE_unix", IDATE,,, "--:-:TArray=I1(3)w")
-DEFIMP (IDATE_vxt, "IDATE_vxt", VXTIDATE,,, "--:-:M=I1w,D=I1w,Y=I1w")
+DEFIMPY (IDATE_vxt, "IDATE_vxt", VXTIDATE,,, "--:-:M=I1w,D=I1w,Y=I1w", TRUE)
DEFIMP (IEOR, "IEOR", ,,, "I=:*:I=I*,J=I*")
DEFIMP (IOR, "IOR", ,,, "I=:*:I=I*,J=I*")
DEFIMP (IERRNO, "IERRNO", IERRNO,,, "I1:-:")
@@ -3342,7 +3348,7 @@ DEFIMP (TIME8, "TIME8", TIME,,, "I2:-:")
DEFIMP (TIME_unix, "TIME_unix", TIME,,, "I1:-:")
DEFIMP (TIME_vxt, "TIME_vxt", VXTTIME,,, "--:-:Time=A1[8]w")
DEFIMP (TTYNAM_func, "TTYNAM_func", TTYNAM,,, "A1*:-:Unit=I*")
-DEFIMP (TTYNAM_subr, "TTYNAM_subr", TTYNAM,,, "--:-:Name=A1w,Unit=I*")
+DEFIMP (TTYNAM_subr, "TTYNAM_subr", TTYNAM,,, "--:-:Unit=I*,Name=A1w")
DEFIMP (UMASK_func, "UMASK_func", UMASK,,, "I1:-:Mask=I*")
DEFIMP (UMASK_subr, "UMASK_subr", UMASK,,, "--:-:Mask=I*,Old=?I1w")
DEFIMP (UNLINK_func, "UNLINK_func", UNLINK,,, "I1:-:File=A1")
diff --git a/contrib/gcc/f/intrin.h b/contrib/gcc/f/intrin.h
index 0006c8a..5b8d725 100644
--- a/contrib/gcc/f/intrin.h
+++ b/contrib/gcc/f/intrin.h
@@ -1,6 +1,6 @@
/* intrin.h -- Public interface for intrin.c
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -51,11 +51,13 @@ typedef enum
#define DEFGEN(CODE,NAME,SPEC1,SPEC2) FFEINTRIN_gen ## CODE,
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFNAME
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
FFEINTRIN_gen
} ffeintrinGen;
@@ -65,11 +67,13 @@ typedef enum
#define DEFGEN(CODE,NAME,SPEC1,SPEC2)
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP) FFEINTRIN_spec ## CODE,
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
#include "intrin.def"
#undef DEFNAME
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
FFEINTRIN_spec
} ffeintrinSpec;
@@ -80,11 +84,14 @@ typedef enum
#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
FFEINTRIN_imp ## CODE,
+#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
+ FFEINTRIN_imp ## CODE,
#include "intrin.def"
#undef DEFNAME
#undef DEFGEN
#undef DEFSPEC
#undef DEFIMP
+#undef DEFIMPY
FFEINTRIN_imp
} ffeintrinImp;
@@ -108,14 +115,14 @@ void ffeintrin_init_0 (void);
#define ffeintrin_init_3()
#define ffeintrin_init_4()
bool ffeintrin_is_actualarg (ffeintrinSpec spec);
-bool ffeintrin_is_intrinsic (char *name, ffelexToken t, bool explicit,
+bool ffeintrin_is_intrinsic (const char *name, ffelexToken t, bool explicit,
ffeintrinGen *gen, ffeintrinSpec *spec,
ffeintrinImp *imp);
bool ffeintrin_is_standard (ffeintrinGen gen, ffeintrinSpec spec);
ffeinfoKindtype ffeintrin_kindtype (ffeintrinSpec spec);
-char *ffeintrin_name_generic (ffeintrinGen gen);
-char *ffeintrin_name_implementation (ffeintrinImp imp);
-char *ffeintrin_name_specific (ffeintrinSpec spec);
+const char *ffeintrin_name_generic (ffeintrinGen gen);
+const char *ffeintrin_name_implementation (ffeintrinImp imp);
+const char *ffeintrin_name_specific (ffeintrinSpec spec);
ffeIntrinsicState ffeintrin_state_family (ffeintrinFamily family);
#define ffeintrin_terminate_0()
#define ffeintrin_terminate_1()
diff --git a/contrib/gcc/f/lab.c b/contrib/gcc/f/lab.c
index e161097..a870a7f 100644
--- a/contrib/gcc/f/lab.c
+++ b/contrib/gcc/f/lab.c
@@ -1,6 +1,6 @@
/* lab.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/lab.h b/contrib/gcc/f/lab.h
index d559860..09f1291 100644
--- a/contrib/gcc/f/lab.h
+++ b/contrib/gcc/f/lab.h
@@ -1,6 +1,6 @@
/* lab.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/lang-options.h b/contrib/gcc/f/lang-options.h
index 4b7c6b8..f9bb90d 100644
--- a/contrib/gcc/f/lang-options.h
+++ b/contrib/gcc/f/lang-options.h
@@ -1,6 +1,6 @@
/* lang-options.h file for Fortran
Copyright (C) 1995-1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -28,131 +28,142 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
overflowing some old compiler's tables, etc. */
DEFINE_LANG_NAME ("Fortran")
-
- { "-fversion", "Print g77-specific compiler version info, run internal tests" },
- { "-fnull-version", "" },
+
+/* Use of FTNOPT makes tracking changes between FSF-g77 and egcs-g77
+ easier, since FSF-gcc doesn't support doc strings. */
+#define FTNOPT(opt,doc) { opt, doc },
+
+FTNOPT( "-fversion", "Print g77-specific compiler version info, run internal tests" )
+FTNOPT( "-fnull-version", "" )
/*"-fident",*/
/*"-fno-ident",*/
- { "-ff66", "Program is written in typical FORTRAN 66 dialect" },
- { "-fno-f66", "" },
- { "-ff77", "Program is written in typical Unix f77 dialect" },
- { "-fno-f77", "Program does not use Unix-f77 dialectal features" },
- { "-ff90", "Program is written in Fortran-90-ish dialect" },
- { "-fno-f90", "" },
- { "-fautomatic", "" },
- { "-fno-automatic", "Treat local vars and COMMON blocks as if they were named in SAVE statements" },
- { "-fdollar-ok", "Allow $ in symbol names" },
- { "-fno-dollar-ok", "" },
- { "-ff2c", "" },
- { "-fno-f2c", "f2c-compatible code need not be generated" },
- { "-ff2c-library", "" },
- { "-fno-f2c-library", "Unsupported; do not generate libf2c-calling code" },
- { "-ffree-form", "Program is written in Fortran-90-ish free form" },
- { "-fno-free-form", "" },
- { "-ffixed-form", "" },
- { "-fno-fixed-form", "" },
- { "-fpedantic", "Warn about use of (only a few for now) Fortran extensions" },
- { "-fno-pedantic", "" },
- { "-fvxt", "Program is written in VXT (Digital-like) FORTRAN" },
- { "-fno-vxt", "" },
- { "-fugly", "Obsolete; allow certain ugly features" },
- { "-fno-ugly", "" },
- { "-fugly-args", "" },
- { "-fno-ugly-args", "Hollerith and typeless constants not passed as arguments" },
- { "-fugly-assign", "Allow ordinary copying of ASSIGN'ed vars" },
- { "-fno-ugly-assign", "" },
- { "-fugly-assumed", "Dummy array dimensioned to (1) is assumed-size" },
- { "-fno-ugly-assumed", "" },
- { "-fugly-comma", "Trailing comma in procedure call denotes null argument" },
- { "-fno-ugly-comma", "" },
- { "-fugly-complex", "Allow REAL(Z) and AIMAG(Z) given DOUBLE COMPLEX Z" },
- { "-fno-ugly-complex", "" },
- { "-fugly-init", "" },
- { "-fno-ugly-init", "Initialization via DATA and PARAMETER is type-compatible" },
- { "-fugly-logint", "Allow INTEGER and LOGICAL interchangeability" },
- { "-fno-ugly-logint", "" },
- { "-fxyzzy", "Print internal debugging-related info" },
- { "-fno-xyzzy", "" },
- { "-finit-local-zero", "Initialize local vars and arrays to zero" },
- { "-fno-init-local-zero", "" },
- { "-fbackslash", "" },
- { "-fno-backslash", "Backslashes in character/hollerith constants not special (C-style)" },
- { "-femulate-complex", "" },
- { "-fno-emulate-complex", "Have compiler back end cope with COMPLEX arithmetic" },
- { "-funderscoring", "" },
- { "-fno-underscoring", "Disable the appending of underscores to externals" },
- { "-fsecond-underscore", "" },
- { "-fno-second-underscore", "Never append a second underscore to externals" },
- { "-fintrin-case-initcap", "Intrinsics spelled as e.g. SqRt" },
- { "-fintrin-case-upper", "Intrinsics in uppercase" },
- { "-fintrin-case-lower", "" },
- { "-fintrin-case-any", "Intrinsics letters in arbitrary cases" },
- { "-fmatch-case-initcap", "Language keywords spelled as e.g. IOStat" },
- { "-fmatch-case-upper", "Language keywords in uppercase" },
- { "-fmatch-case-lower", "" },
- { "-fmatch-case-any", "Language keyword letters in arbitrary cases" },
- { "-fsource-case-upper", "Internally convert most source to uppercase" },
- { "-fsource-case-lower", "" },
- { "-fsource-case-preserve", "Internally preserve source case" },
- { "-fsymbol-case-initcap", "Symbol names spelled in mixed case" },
- { "-fsymbol-case-upper", "Symbol names in uppercase" },
- { "-fsymbol-case-lower", "Symbol names in lowercase" },
- { "-fsymbol-case-any", "" },
- { "-fcase-strict-upper", "Program written in uppercase" },
- { "-fcase-strict-lower", "Program written in lowercase" },
- { "-fcase-initcap", "Program written in strict mixed-case" },
- { "-fcase-upper", "Compile as if program written in uppercase" },
- { "-fcase-lower", "Compile as if program written in lowercase" },
- { "-fcase-preserve", "Preserve all spelling (case) used in program" },
- { "-fbadu77-intrinsics-delete", "Delete libU77 intrinsics with bad interfaces" },
- { "-fbadu77-intrinsics-disable", "Disable libU77 intrinsics with bad interfaces" },
- { "-fbadu77-intrinsics-enable", "" },
- { "-fbadu77-intrinsics-hide", "Hide libU77 intrinsics with bad interfaces" },
- { "-ff2c-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics f2c supports" },
- { "-ff2c-intrinsics-disable", "Disable non-FORTRAN-77 intrinsics f2c supports" },
- { "-ff2c-intrinsics-enable", "" },
- { "-ff2c-intrinsics-hide", "Hide non-FORTRAN-77 intrinsics f2c supports" },
- { "-ff90-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics F90 supports" },
- { "-ff90-intrinsics-disable", "Disable non-FORTRAN-77 intrinsics F90 supports" },
- { "-ff90-intrinsics-enable", "" },
- { "-ff90-intrinsics-hide", "Hide non-FORTRAN-77 intrinsics F90 supports" },
- { "-fgnu-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics g77 supports" },
- { "-fgnu-intrinsics-disable", "Disable non-FORTRAN 77 intrinsics F90 supports" },
- { "-fgnu-intrinsics-enable", "" },
- { "-fgnu-intrinsics-hide", "Hide non-FORTRAN 77 intrinsics F90 supports" },
- { "-fmil-intrinsics-delete", "Delete MIL-STD 1753 intrinsics" },
- { "-fmil-intrinsics-disable", "Disable MIL-STD 1753 intrinsics" },
- { "-fmil-intrinsics-enable", "" },
- { "-fmil-intrinsics-hide", "Hide MIL-STD 1753 intrinsics" },
- { "-funix-intrinsics-delete", "Delete libU77 intrinsics" },
- { "-funix-intrinsics-disable", "Disable libU77 intrinsics" },
- { "-funix-intrinsics-enable", "" },
- { "-funix-intrinsics-hide", "Hide libU77 intrinsics" },
- { "-fvxt-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics VXT FORTRAN supports" },
- { "-fvxt-intrinsics-disable", "Disable non-FORTRAN-77 intrinsics VXT FORTRAN supports" },
- { "-fvxt-intrinsics-enable", "" },
- { "-fvxt-intrinsics-hide", "Hide non-FORTRAN-77 intrinsics VXT FORTRAN supports" },
- { "-fzeros", "Treat initial values of 0 like non-zero values" },
- { "-fno-zeros", "" },
- { "-fdebug-kludge", "Emit special debugging information for COMMON and EQUIVALENCE" },
- { "-fno-debug-kludge", "" },
- { "-fonetrip", "Take at least one trip through each iterative DO loop" },
- { "-fno-onetrip", "" },
- { "-fsilent", "" },
- { "-fno-silent", "Print names of program units as they are compiled" },
- { "-fglobals", "" },
- { "-fno-globals", "Disable fatal diagnostics about inter-procedural problems" },
- { "-ftypeless-boz", "Make prefix-radix non-decimal constants be typeless" },
- { "-fno-typeless-boz", "" },
- { "-Wglobals", "" },
- { "-Wno-globals", "Disable warnings about inter-procedural problems" },
+FTNOPT( "-ff66", "Program is written in typical FORTRAN 66 dialect" )
+FTNOPT( "-fno-f66", "" )
+FTNOPT( "-ff77", "Program is written in typical Unix f77 dialect" )
+FTNOPT( "-fno-f77", "Program does not use Unix-f77 dialectal features" )
+FTNOPT( "-ff90", "Program is written in Fortran-90-ish dialect" )
+FTNOPT( "-fno-f90", "" )
+FTNOPT( "-fautomatic", "" )
+FTNOPT( "-fno-automatic", "Treat local vars and COMMON blocks as if they were named in SAVE statements" )
+FTNOPT( "-fdollar-ok", "Allow $ in symbol names" )
+FTNOPT( "-fno-dollar-ok", "" )
+FTNOPT( "-ff2c", "" )
+FTNOPT( "-fno-f2c", "f2c-compatible code need not be generated" )
+FTNOPT( "-ff2c-library", "" )
+FTNOPT( "-fno-f2c-library", "Unsupported; do not generate libf2c-calling code" )
+FTNOPT( "-fflatten-arrays", "Unsupported; affects code-generation of arrays" )
+FTNOPT( "-fno-flatten-arrays", "" )
+FTNOPT( "-ffree-form", "Program is written in Fortran-90-ish free form" )
+FTNOPT( "-fno-free-form", "" )
+FTNOPT( "-ffixed-form", "" )
+FTNOPT( "-fno-fixed-form", "" )
+FTNOPT( "-fpedantic", "Warn about use of (only a few for now) Fortran extensions" )
+FTNOPT( "-fno-pedantic", "" )
+FTNOPT( "-fvxt", "Program is written in VXT (Digital-like) FORTRAN" )
+FTNOPT( "-fno-vxt", "" )
+FTNOPT( "-fno-ugly", "Disallow all ugly features" )
+FTNOPT( "-fugly-args", "" )
+FTNOPT( "-fno-ugly-args", "Hollerith and typeless constants not passed as arguments" )
+FTNOPT( "-fugly-assign", "Allow ordinary copying of ASSIGN'ed vars" )
+FTNOPT( "-fno-ugly-assign", "" )
+FTNOPT( "-fugly-assumed", "Dummy array dimensioned to (1) is assumed-size" )
+FTNOPT( "-fno-ugly-assumed", "" )
+FTNOPT( "-fugly-comma", "Trailing comma in procedure call denotes null argument" )
+FTNOPT( "-fno-ugly-comma", "" )
+FTNOPT( "-fugly-complex", "Allow REAL(Z) and AIMAG(Z) given DOUBLE COMPLEX Z" )
+FTNOPT( "-fno-ugly-complex", "" )
+FTNOPT( "-fugly-init", "" )
+FTNOPT( "-fno-ugly-init", "Initialization via DATA and PARAMETER is type-compatible" )
+FTNOPT( "-fugly-logint", "Allow INTEGER and LOGICAL interchangeability" )
+FTNOPT( "-fno-ugly-logint", "" )
+FTNOPT( "-fxyzzy", "Print internal debugging-related info" )
+FTNOPT( "-fno-xyzzy", "" )
+FTNOPT( "-finit-local-zero", "Initialize local vars and arrays to zero" )
+FTNOPT( "-fno-init-local-zero", "" )
+FTNOPT( "-fbackslash", "" )
+FTNOPT( "-fno-backslash", "Backslashes in character/hollerith constants not special (C-style)" )
+FTNOPT( "-femulate-complex", "Have front end emulate COMPLEX arithmetic to avoid bugs" )
+FTNOPT( "-fno-emulate-complex", "" )
+FTNOPT( "-funderscoring", "" )
+FTNOPT( "-fno-underscoring", "Disable the appending of underscores to externals" )
+FTNOPT( "-fsecond-underscore", "" )
+FTNOPT( "-fno-second-underscore", "Never append a second underscore to externals" )
+FTNOPT( "-fintrin-case-initcap", "Intrinsics spelled as e.g. SqRt" )
+FTNOPT( "-fintrin-case-upper", "Intrinsics in uppercase" )
+FTNOPT( "-fintrin-case-lower", "" )
+FTNOPT( "-fintrin-case-any", "Intrinsics letters in arbitrary cases" )
+FTNOPT( "-fmatch-case-initcap", "Language keywords spelled as e.g. IOStat" )
+FTNOPT( "-fmatch-case-upper", "Language keywords in uppercase" )
+FTNOPT( "-fmatch-case-lower", "" )
+FTNOPT( "-fmatch-case-any", "Language keyword letters in arbitrary cases" )
+FTNOPT( "-fsource-case-upper", "Internally convert most source to uppercase" )
+FTNOPT( "-fsource-case-lower", "" )
+FTNOPT( "-fsource-case-preserve", "Internally preserve source case" )
+FTNOPT( "-fsymbol-case-initcap", "Symbol names spelled in mixed case" )
+FTNOPT( "-fsymbol-case-upper", "Symbol names in uppercase" )
+FTNOPT( "-fsymbol-case-lower", "Symbol names in lowercase" )
+FTNOPT( "-fsymbol-case-any", "" )
+FTNOPT( "-fcase-strict-upper", "Program written in uppercase" )
+FTNOPT( "-fcase-strict-lower", "Program written in lowercase" )
+FTNOPT( "-fcase-initcap", "Program written in strict mixed-case" )
+FTNOPT( "-fcase-upper", "Compile as if program written in uppercase" )
+FTNOPT( "-fcase-lower", "Compile as if program written in lowercase" )
+FTNOPT( "-fcase-preserve", "Preserve all spelling (case) used in program" )
+FTNOPT( "-fbadu77-intrinsics-delete", "Delete libU77 intrinsics with bad interfaces" )
+FTNOPT( "-fbadu77-intrinsics-disable", "Disable libU77 intrinsics with bad interfaces" )
+FTNOPT( "-fbadu77-intrinsics-enable", "" )
+FTNOPT( "-fbadu77-intrinsics-hide", "Hide libU77 intrinsics with bad interfaces" )
+FTNOPT( "-ff2c-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics f2c supports" )
+FTNOPT( "-ff2c-intrinsics-disable", "Disable non-FORTRAN-77 intrinsics f2c supports" )
+FTNOPT( "-ff2c-intrinsics-enable", "" )
+FTNOPT( "-ff2c-intrinsics-hide", "Hide non-FORTRAN-77 intrinsics f2c supports" )
+FTNOPT( "-ff90-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics F90 supports" )
+FTNOPT( "-ff90-intrinsics-disable", "Disable non-FORTRAN-77 intrinsics F90 supports" )
+FTNOPT( "-ff90-intrinsics-enable", "" )
+FTNOPT( "-ff90-intrinsics-hide", "Hide non-FORTRAN-77 intrinsics F90 supports" )
+FTNOPT( "-fgnu-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics g77 supports" )
+FTNOPT( "-fgnu-intrinsics-disable", "Disable non-FORTRAN 77 intrinsics F90 supports" )
+FTNOPT( "-fgnu-intrinsics-enable", "" )
+FTNOPT( "-fgnu-intrinsics-hide", "Hide non-FORTRAN 77 intrinsics F90 supports" )
+FTNOPT( "-fmil-intrinsics-delete", "Delete MIL-STD 1753 intrinsics" )
+FTNOPT( "-fmil-intrinsics-disable", "Disable MIL-STD 1753 intrinsics" )
+FTNOPT( "-fmil-intrinsics-enable", "" )
+FTNOPT( "-fmil-intrinsics-hide", "Hide MIL-STD 1753 intrinsics" )
+FTNOPT( "-funix-intrinsics-delete", "Delete libU77 intrinsics" )
+FTNOPT( "-funix-intrinsics-disable", "Disable libU77 intrinsics" )
+FTNOPT( "-funix-intrinsics-enable", "" )
+FTNOPT( "-funix-intrinsics-hide", "Hide libU77 intrinsics" )
+FTNOPT( "-fvxt-intrinsics-delete", "Delete non-FORTRAN-77 intrinsics VXT FORTRAN supports" )
+FTNOPT( "-fvxt-intrinsics-disable", "Disable non-FORTRAN-77 intrinsics VXT FORTRAN supports" )
+FTNOPT( "-fvxt-intrinsics-enable", "" )
+FTNOPT( "-fvxt-intrinsics-hide", "Hide non-FORTRAN-77 intrinsics VXT FORTRAN supports" )
+FTNOPT( "-fzeros", "Treat initial values of 0 like non-zero values" )
+FTNOPT( "-fno-zeros", "" )
+FTNOPT( "-fdebug-kludge", "Emit special debugging information for COMMON and EQUIVALENCE" )
+FTNOPT( "-fno-debug-kludge", "" )
+FTNOPT( "-fonetrip", "Take at least one trip through each iterative DO loop" )
+FTNOPT( "-fno-onetrip", "" )
+FTNOPT( "-fsilent", "" )
+FTNOPT( "-fno-silent", "Print names of program units as they are compiled" )
+FTNOPT( "-fglobals", "" )
+FTNOPT( "-fno-globals", "Disable fatal diagnostics about inter-procedural problems" )
+FTNOPT( "-ftypeless-boz", "Make prefix-radix non-decimal constants be typeless" )
+FTNOPT( "-fno-typeless-boz", "" )
+FTNOPT( "-fbounds-check", "Generate code to check subscript and substring bounds" )
+FTNOPT( "-fno-bounds-check", "" )
+FTNOPT( "-ffortran-bounds-check", "Fortran-specific form of -fbounds-check")
+FTNOPT( "-fno-fortran-bounds-check", "" )
+FTNOPT( "-Wglobals", "" )
+FTNOPT( "-Wno-globals", "Disable warnings about inter-procedural problems" )
/*"-Wimplicit",*/
/*"-Wno-implicit",*/
- { "-Wsurprising", "Warn about constructs with surprising meanings" },
- { "-Wno-surprising", "" },
+FTNOPT( "-Wsurprising", "Warn about constructs with surprising meanings" )
+FTNOPT( "-Wno-surprising", "" )
/*"-Wall",*/
/* Prefix options. */
- { "-I", "Add a directory for INCLUDE searching" },
- { "-ffixed-line-length-", "Set the maximum line length" },
+FTNOPT( "-I", "Add a directory for INCLUDE searching" )
+FTNOPT( "-ffixed-line-length-", "Set the maximum line length" )
+
+#undef FTNOPT
#endif
diff --git a/contrib/gcc/f/lang-specs.h b/contrib/gcc/f/lang-specs.h
index bf8786f..b4492a6 100644
--- a/contrib/gcc/f/lang-specs.h
+++ b/contrib/gcc/f/lang-specs.h
@@ -1,6 +1,6 @@
/* lang-specs.h file for Fortran
- Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Copyright (C) 1995-1997, 1999 Free Software Foundation, Inc.
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -26,6 +26,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
{".F", {"@f77-cpp-input"}},
{".fpp", {"@f77-cpp-input"}},
+ {".FPP", {"@f77-cpp-input"}},
{"@f77-cpp-input",
/* For f77 we want -traditional to avoid errors with, for
instance, mismatched '. Also, we avoid unpleasant surprises
@@ -34,20 +35,21 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Sun f77, at least) so you test `__unix' rather than `unix'.
-D_LANGUAGE_FORTRAN is used by some compilers like SGI and
might as well be in there. */
- {"cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {"cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
%{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
%{!undef:%P} -D_LANGUAGE_FORTRAN %{trigraphs} \
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} -traditional\
+ %{ffast-math:-D__FAST_MATH__}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
"%{!M:%{!MM:%{!E:f771 %{!pipe:%g.i} %(f771) \
- %{!Q:-quiet} -dumpbase %b.F %{d*} %{m*} %{a}\
+ %{!Q:-quiet} -dumpbase %b.F %{d*} %{m*} %{a*}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} \
%{v:-version -fversion} %{pg:-p} %{p} %{f*} %{I*}\
- %{aux-info*}\
+ %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
@@ -59,10 +61,10 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{!E:%{!pipe:-o %g.f}}%{E:%W{o*}} %i |\n",
"%{!E:f771 %{!pipe:%g.f} %(f771) \
- %{!Q:-quiet} -dumpbase %b.r %{d*} %{m*} %{a}\
+ %{!Q:-quiet} -dumpbase %b.r %{d*} %{m*} %{a*}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} \
%{v:-version -fversion} %{pg:-p} %{p} %{f*} %{I*}\
- %{aux-info*}\
+ %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
@@ -70,29 +72,31 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
%{!pipe:%g.s} %A\n }}"}},
{".f", {"@f77"}},
{".for", {"@f77"}},
+ {".FOR", {"@f77"}},
{"@f77",
{"%{!M:%{!MM:%{!E:f771 %i %(f771) \
- %{!Q:-quiet} -dumpbase %b.f %{d*} %{m*} %{a}\
+ %{!Q:-quiet} -dumpbase %b.f %{d*} %{m*} %{a*}\
%{g*} %{O*} %{W*} %{w} %{pedantic*}\
%{v:-version -fversion} %{pg:-p} %{p} %{f*} %{I*}\
- %{aux-info*}\
+ %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
%{!pipe:%g.s} %A\n }}}}"}},
{"@f77-version",
- {"cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I \
+ {"cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I \
%{C:%{!E:%eGNU C does not support -C without using -E}} \
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} \
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 \
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2} \
%{ansi:-trigraphs -$ -D__STRICT_ANSI__} \
%{!undef:%P} -D_LANGUAGE_FORTRAN %{trigraphs} \
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} -traditional \
+ %{ffast-math:-D__FAST_MATH__}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z \
/dev/null /dev/null \n\
f771 -fnull-version %(f771) \
- %{!Q:-quiet} -dumpbase g77-version.f %{d*} %{m*} %{a} \
+ %{!Q:-quiet} -dumpbase g77-version.f %{d*} %{m*} %{a*} \
%{g*} %{O*} %{W*} %{w} %{pedantic*} \
-version -fversion %{f*} %{I*} -o %g.s /dev/null \n\
as %a %Y -o %g%O %g.s %A \n\
diff --git a/contrib/gcc/f/lex.c b/contrib/gcc/f/lex.c
index c62e5b2..3136d40 100644
--- a/contrib/gcc/f/lex.c
+++ b/contrib/gcc/f/lex.c
@@ -1,6 +1,6 @@
/* Implementation of Fortran lexer
- Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Copyright (C) 1995-1998 Free Software Foundation, Inc.
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -1077,6 +1077,23 @@ ffelex_get_directive_line_ (char **text, FILE *finput)
Returns the next character unhandled, which is always newline or EOF. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
+
+#if defined HANDLE_PRAGMA
+/* Local versions of these macros, that can be passed as function pointers. */
+static int
+pragma_getc ()
+{
+ return getc (finput);
+}
+
+static void
+pragma_ungetc (arg)
+ int arg;
+{
+ ungetc (arg, finput);
+}
+#endif /* HANDLE_PRAGMA */
+
static int
ffelex_hash_ (FILE *finput)
{
@@ -1105,17 +1122,42 @@ ffelex_hash_ (FILE *finput)
&& ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'
|| c == EOF))
{
- goto skipline;
#if 0 /* g77 doesn't handle pragmas, so ignores them FOR NOW. */
-#ifdef HANDLE_SYSV_PRAGMA
- return handle_sysv_pragma (finput, c);
-#else /* !HANDLE_SYSV_PRAGMA */
+ static char buffer [128];
+ char * buff = buffer;
+
+ /* Read the pragma name into a buffer. */
+ while (isspace (c = getc (finput)))
+ continue;
+
+ do
+ {
+ * buff ++ = c;
+ c = getc (finput);
+ }
+ while (c != EOF && ! isspace (c) && c != '\n'
+ && buff < buffer + 128);
+
+ pragma_ungetc (c);
+
+ * -- buff = 0;
#ifdef HANDLE_PRAGMA
- HANDLE_PRAGMA (finput);
+ if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc, buffer))
+ goto skipline;
#endif /* HANDLE_PRAGMA */
- goto skipline;
-#endif /* !HANDLE_SYSV_PRAGMA */
+#ifdef HANDLE_GENERIC_PRAGMAS
+ if (handle_generic_pragma (buffer))
+ goto skipline;
+#endif /* !HANDLE_GENERIC_PRAGMAS */
+
+ /* Issue a warning message if we have been asked to do so.
+ Ignoring unknown pragmas in system header file unless
+ an explcit -Wunknown-pragmas has been given. */
+ if (warn_unknown_pragmas > 1
+ || (warn_unknown_pragmas && ! in_system_header))
+ warning ("ignoring pragma: %s", token_buffer);
#endif /* 0 */
+ goto skipline;
}
}
@@ -1201,7 +1243,7 @@ ffelex_hash_ (FILE *finput)
goto skipline;
}
- if (ffe_is_ident ())
+ if (! flag_no_ident)
{
#ifdef ASM_OUTPUT_IDENT
ASM_OUTPUT_IDENT (asm_out_file,
@@ -1709,10 +1751,10 @@ ffelex_token_new_ ()
return t;
}
-static char *
+static const char *
ffelex_type_string_ (ffelexType type)
{
- static char *types[] = {
+ static const char *types[] = {
"FFELEX_typeNONE",
"FFELEX_typeCOMMENT",
"FFELEX_typeEOS",
@@ -4305,7 +4347,7 @@ ffelexHandler
ffelex_splice_tokens (ffelexHandler first, ffelexToken master,
ffeTokenLength start)
{
- char *p;
+ unsigned char *p;
ffeTokenLength i;
ffelexToken t;
@@ -4448,7 +4490,7 @@ ffelex_token_name_from_names (ffelexToken t, ffeTokenLength start,
assert (len > 0);
assert ((start + len) <= t->length);
}
- assert (ffelex_is_firstnamechar (t->text[start]));
+ assert (ffelex_is_firstnamechar ((unsigned char)(t->text[start])));
nt = ffelex_token_new_ ();
nt->type = FFELEX_typeNAME;
@@ -4483,7 +4525,7 @@ ffelex_token_names_from_names (ffelexToken t, ffeTokenLength start,
assert (len > 0);
assert ((start + len) <= t->length);
}
- assert (ffelex_is_firstnamechar (t->text[start]));
+ assert (ffelex_is_firstnamechar ((unsigned char)(t->text[start])));
nt = ffelex_token_new_ ();
nt->type = FFELEX_typeNAMES;
@@ -4504,7 +4546,7 @@ ffelex_token_names_from_names (ffelexToken t, ffeTokenLength start,
/* Make a new CHARACTER token. */
ffelexToken
-ffelex_token_new_character (char *s, ffewhereLine l, ffewhereColumn c)
+ffelex_token_new_character (const char *s, ffewhereLine l, ffewhereColumn c)
{
ffelexToken t;
@@ -4539,11 +4581,11 @@ ffelex_token_new_eof ()
/* Make a new NAME token. */
ffelexToken
-ffelex_token_new_name (char *s, ffewhereLine l, ffewhereColumn c)
+ffelex_token_new_name (const char *s, ffewhereLine l, ffewhereColumn c)
{
ffelexToken t;
- assert (ffelex_is_firstnamechar (*s));
+ assert (ffelex_is_firstnamechar ((unsigned char)*s));
t = ffelex_token_new_ ();
t->type = FFELEX_typeNAME;
@@ -4560,11 +4602,11 @@ ffelex_token_new_name (char *s, ffewhereLine l, ffewhereColumn c)
/* Make a new NAMES token. */
ffelexToken
-ffelex_token_new_names (char *s, ffewhereLine l, ffewhereColumn c)
+ffelex_token_new_names (const char *s, ffewhereLine l, ffewhereColumn c)
{
ffelexToken t;
- assert (ffelex_is_firstnamechar (*s));
+ assert (ffelex_is_firstnamechar ((unsigned char)*s));
t = ffelex_token_new_ ();
t->type = FFELEX_typeNAMES;
@@ -4589,7 +4631,7 @@ ffelex_token_new_names (char *s, ffewhereLine l, ffewhereColumn c)
in the original string. */
ffelexToken
-ffelex_token_new_number (char *s, ffewhereLine l, ffewhereColumn c)
+ffelex_token_new_number (const char *s, ffewhereLine l, ffewhereColumn c)
{
ffelexToken t;
ffeTokenLength len;
diff --git a/contrib/gcc/f/lex.h b/contrib/gcc/f/lex.h
index c9a9dd5..c82a9c8 100644
--- a/contrib/gcc/f/lex.h
+++ b/contrib/gcc/f/lex.h
@@ -1,6 +1,6 @@
/* lex.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -148,14 +148,14 @@ ffelexToken ffelex_token_names_from_names (ffelexToken t,
ffeTokenLength start,
ffeTokenLength len);
ffelexToken ffelex_token_new (void);
-ffelexToken ffelex_token_new_character (char *s, ffewhereLine l,
+ffelexToken ffelex_token_new_character (const char *s, ffewhereLine l,
ffewhereColumn c);
ffelexToken ffelex_token_new_eof (void);
-ffelexToken ffelex_token_new_name (char *s, ffewhereLine l,
+ffelexToken ffelex_token_new_name (const char *s, ffewhereLine l,
ffewhereColumn c);
-ffelexToken ffelex_token_new_names (char *s, ffewhereLine l,
+ffelexToken ffelex_token_new_names (const char *s, ffewhereLine l,
ffewhereColumn c);
-ffelexToken ffelex_token_new_number (char *s, ffewhereLine l,
+ffelexToken ffelex_token_new_number (const char *s, ffewhereLine l,
ffewhereColumn c);
ffelexToken ffelex_token_new_simple_ (ffelexType type, ffewhereLine l,
ffewhereColumn c);
diff --git a/contrib/gcc/f/malloc.c b/contrib/gcc/f/malloc.c
index 4560211..b0d31af 100644
--- a/contrib/gcc/f/malloc.c
+++ b/contrib/gcc/f/malloc.c
@@ -1,6 +1,6 @@
/* malloc.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -33,10 +33,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "proj.h"
#include "malloc.h"
-/* Assume gcc/toplev.o is linked in. */
-void *xmalloc (unsigned size);
-void *xrealloc (void *ptr, int size);
-
/* Externals defined here. */
struct _malloc_root_ malloc_root_
@@ -52,6 +48,8 @@ struct _malloc_root_ malloc_root_
0,
#if MALLOC_DEBUG
0, 0, 0, 0, 0, 0, 0, { '/' }
+#else
+ { 0 }
#endif
},
};
@@ -72,7 +70,7 @@ struct _malloc_root_ malloc_root_
static void *malloc_reserve_ = NULL; /* For crashes. */
#if MALLOC_DEBUG
-static char *malloc_types_[] =
+static const char *malloc_types_[] =
{"KS", "KSR", "NF", "NFR", "US", "USR"};
#endif
@@ -236,7 +234,7 @@ malloc_pool_kill (mallocPool p)
Makes a new pool with the given name and default new-chunk allocation. */
mallocPool
-malloc_pool_new (char *name, mallocPool parent,
+malloc_pool_new (const char *name, mallocPool parent,
unsigned long chunks UNUSED)
{
mallocPool p;
@@ -386,7 +384,7 @@ malloc_new_ (mallocSize s)
add it to the list of mallocArea_s for the pool. */
void *
-malloc_new_inpool_ (mallocPool pool, mallocType_ type, char *name, mallocSize s)
+malloc_new_inpool_ (mallocPool pool, mallocType_ type, const char *name, mallocSize s)
{
void *ptr;
mallocArea_ a;
@@ -439,7 +437,7 @@ malloc_new_inpool_ (mallocPool pool, mallocType_ type, char *name, mallocSize s)
you pass it a 0). */
void *
-malloc_new_zinpool_ (mallocPool pool, mallocType_ type, char *name, mallocSize s,
+malloc_new_zinpool_ (mallocPool pool, mallocType_ type, const char *name, mallocSize s,
int z)
{
void *ptr;
diff --git a/contrib/gcc/f/malloc.h b/contrib/gcc/f/malloc.h
index ea43276..d9efdf2 100644
--- a/contrib/gcc/f/malloc.h
+++ b/contrib/gcc/f/malloc.h
@@ -1,6 +1,6 @@
/* malloc.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -109,14 +109,14 @@ void malloc_init (void);
void malloc_kill_inpool_ (mallocPool pool, mallocType_ type, void *ptr,
mallocSize size);
void *malloc_new_ (mallocSize size);
-void *malloc_new_inpool_ (mallocPool pool, mallocType_ type, char *name,
+void *malloc_new_inpool_ (mallocPool pool, mallocType_ type, const char *name,
mallocSize size);
-void *malloc_new_zinpool_ (mallocPool pool, mallocType_ type, char *name,
+void *malloc_new_zinpool_ (mallocPool pool, mallocType_ type, const char *name,
mallocSize size, int z);
void malloc_pool_display (mallocPool p);
char malloc_pool_find_ (mallocPool p, mallocPool parent);
void malloc_pool_kill (mallocPool p);
-mallocPool malloc_pool_new (char *name, mallocPool parent, unsigned long chunks);
+mallocPool malloc_pool_new (const char *name, mallocPool parent, unsigned long chunks);
mallocPool malloc_pool_use (mallocPool p);
void *malloc_resize_ (void *ptr, mallocSize new_size);
void *malloc_resize_inpool_ (mallocPool pool, mallocType_ type, void *ptr,
diff --git a/contrib/gcc/f/name.c b/contrib/gcc/f/name.c
index 560f642..360279b 100644
--- a/contrib/gcc/f/name.c
+++ b/contrib/gcc/f/name.c
@@ -1,6 +1,6 @@
/* name.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -167,7 +167,7 @@ ffename_lookup (ffenameSpace ns, ffelexToken t)
ffename_space_drive_global(ns,fn); */
void
-ffename_space_drive_global (ffenameSpace ns, ffeglobal (*fn) ())
+ffename_space_drive_global (ffenameSpace ns, ffeglobal (*fn) (ffeglobal))
{
ffename n;
@@ -188,7 +188,7 @@ ffename_space_drive_global (ffenameSpace ns, ffeglobal (*fn) ())
ffename_space_drive_symbol(ns,fn); */
void
-ffename_space_drive_symbol (ffenameSpace ns, ffesymbol (*fn) ())
+ffename_space_drive_symbol (ffenameSpace ns, ffesymbol (*fn) (ffesymbol))
{
ffename n;
diff --git a/contrib/gcc/f/name.h b/contrib/gcc/f/name.h
index 8359ed6..6c3499f 100644
--- a/contrib/gcc/f/name.h
+++ b/contrib/gcc/f/name.h
@@ -1,6 +1,6 @@
/* name.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -75,8 +75,8 @@ struct _ffename_space_
ffename ffename_find (ffenameSpace ns, ffelexToken t);
void ffename_kill (ffenameSpace ns, ffename n);
ffename ffename_lookup (ffenameSpace ns, ffelexToken t);
-void ffename_space_drive_global (ffenameSpace ns, ffeglobal (*fn) ());
-void ffename_space_drive_symbol (ffenameSpace ns, ffesymbol (*fn) ());
+void ffename_space_drive_global (ffenameSpace ns, ffeglobal (*fn) (ffeglobal));
+void ffename_space_drive_symbol (ffenameSpace ns, ffesymbol (*fn) (ffesymbol));
void ffename_space_kill (ffenameSpace ns);
ffenameSpace ffename_space_new (mallocPool pool);
diff --git a/contrib/gcc/f/news.texi b/contrib/gcc/f/news.texi
index 3885137..a4b6d68 100644
--- a/contrib/gcc/f/news.texi
+++ b/contrib/gcc/f/news.texi
@@ -2,18 +2,64 @@
@c This is part of the G77 manual.
@c For copying conditions, see the file g77.texi.
-@c The text of this file appears in the file BUGS
+@c The text of this file appears in the file NEWS
@c in the G77 distribution, as well as in the G77 manual.
-@c 1999-03-11
+@c Keep this the same as the dates above, since it's used
+@c in the standalone derivations of this file (e.g. NEWS).
+@set copyrights-news 1995-1999
-@ifclear NEWSONLY
+@set last-update-news 1999-07-08
+
+@include root.texi
+
+@ifset DOC-NEWS
+@c The immediately following lines apply to the NEWS file
+@c which is derived from this file.
+@emph{Note:} This file is automatically generated from the files
+@file{news0.texi} and @file{news.texi}.
+@file{NEWS} is @emph{not} a source file,
+although it is normally included within source distributions.
+
+This file lists news about the @value{which-g77} version
+(and some other versions) of the GNU Fortran compiler.
+Copyright (C) @value{copyrights-news} Free Software Foundation, Inc.
+You may copy, distribute, and modify it freely as long as you preserve
+this copyright notice and permission notice.
+
+@node Top,,, (dir)
+@chapter News About GNU Fortran
+@end ifset
+
+@ifset DOC-G77
+@ifset USERVISONLY
+@node Changes
+@chapter User-visible Changes
+@cindex versions, recent
+@cindex recent versions
+@cindex changes, user-visible
+@cindex user-visible changes
+
+This chapter describes changes to @code{g77} that are visible
+to the programmers who actually write and maintain Fortran
+code they compile with @code{g77}.
+Information on changes to installation procedures,
+changes to the documentation, and bug fixes is
+not provided here, unless it is likely to affect how
+users use @code{g77}.
+@xref{News,,News About GNU Fortran}, for information on
+such changes to @code{g77}.
+@end ifset
+
+@ifclear USERVISONLY
@node News
@chapter News About GNU Fortran
-@end ifclear
@cindex versions, recent
@cindex recent versions
+@end ifclear
+@end ifset
+@ifclear USERVISONLY
Changes made to recent versions of GNU Fortran are listed
below, with the most recent version first.
@@ -45,6 +91,7 @@ Miscellany
This order is not strict---for example, some items
involve a combination of these elements.
+@end ifclear
Note that two variants of @code{g77} are tracked below.
The @code{egcs} variant is described vis-a-vis
@@ -58,35 +105,315 @@ though this can make getting a complete picture
of what a particular @code{egcs} version contains
somewhat more difficult.
+@ifset DOC-G77
+For information on bugs in the @value{which-g77} version of @code{g77},
+see @ref{Known Bugs,,Known Bugs In GNU Fortran}.
+@end ifset
+
+@ifset DOC-BUGS
+For information on bugs in the @value{which-g77} version of @code{g77},
+see @file{@value{path-g77}/BUGS}.
+@end ifset
+
+@ifset DEVELOPMENT
+@emph{Warning:} The information below is still under development,
+and might not accurately reflect the @code{g77} code base
+of which it is a part.
+Efforts are made to keep it somewhat up-to-date,
+but they are particularly concentrated
+on any version of this information
+that is distributed as part of a @emph{released} @code{g77}.
+
+In particular, while this information is intended to apply to
+the @value{which-g77} version of @code{g77},
+only an official @emph{release} of that version
+is expected to contain documentation that is
+most consistent with the @code{g77} product in that version.
+
+Nevertheless, information on @emph{previous} releases of @code{g77}, below,
+is likely to be more up-to-date and accurate
+than the equivalent information that accompanied
+those releases,
+assuming the last-updated date of the information below
+is later than the dates of those releases.
+
+That's due to attempts to keep this development version
+of news about previous @code{g77} versions up-to-date.
+@end ifset
+
+@ifclear USERVISONLY
An online, ``live'' version of this document
-(derived directly from the up-to-date mainline version
+(derived directly from the mainline, development version
of @code{g77} within @code{egcs})
is available at
-@uref{http://egcs.cygnus.com/onlinedocs/g77_news.html}.
+@uref{http://www.gnu.org/software/gcc/onlinedocs/g77_news.html}.
+@end ifclear
+
+The following information was last updated on @value{last-update-news}:
+
+@heading In 0.5.25, @code{GCC} 2.95 (@code{EGCS} 1.2) versus @code{EGCS} 1.1.2:
+@itemize @bullet
+@ifclear USERVISONLY
+@item
+@code{g77} no longer generates bad code for assignments,
+or other conversions,
+of @code{REAL} or @code{COMPLEX} constant expressions
+to type @code{INTEGER(KIND=2)}
+(often referred to as @code{INTEGER*8}).
+
+For example, @samp{INTEGER*8 J; J = 4E10} now works as documented.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+@code{g77} no longer truncates @code{INTEGER(KIND=2)}
+(usually @code{INTEGER*8})
+subscript expressions when evaluating array references
+on systems with pointers widers than @code{INTEGER(KIND=1)}
+(such as Alphas).
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+@code{g77} no longer generates bad code
+for an assignment to a @code{COMPLEX} variable or array
+that partially overlaps one or more of the sources
+of the same assignment
+(a very rare construction).
+It now assigns through a temporary,
+in cases where such partial overlap is deemed possible.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+@code{libg2c} (@code{libf2c}) no longer loses track
+of the file being worked on
+during a @code{BACKSPACE} operation.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+@code{libg2c} (@code{libf2c}) fixes a bug whereby
+input to a @code{NAMELIST} read involving a repeat count,
+such as @samp{K(5)=10*3},
+was not properly handled by @code{libf2c}.
+The first item was written to @samp{K(5)},
+but the remaining nine were written elsewhere (still within the array),
+not necessarily starting at @samp{K(6)}.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+@c Tim Prince reported this, regarding the TEST_FPU benchmark.
+Automatic arrays now seem to be working on HP-UX systems.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+The @code{Date} intrinsic now returns the correct result
+on big-endian systems.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+Fix @code{g77} so it no longer crashes when compiling
+I/O statements using keywords that define @code{INTEGER} values,
+such as @samp{IOSTAT=@var{j}},
+where @var{j} is other than default @code{INTEGER}
+(such as @code{INTEGER*2}).
+Instead, it issues a diagnostic.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+Fix @code{g77} so it properly handles @samp{DATA A/@var{rpt}*@var{val}/},
+where @var{rpt} is not default @code{INTEGER}, such as @code{INTEGER*2},
+instead of producing a spurious diagnostic.
+Also fix @samp{DATA (A(I),I=1,N)},
+where @samp{N} is not default @code{INTEGER}
+to work instead of crashing @code{g77}.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+The @samp{-ax} option is now obeyed when compiling Fortran programs.
+(It is passed to the @file{f771} driver.)
+@end ifclear
+
+@item
+The new @samp{-fbounds-check} option
+causes @code{g77} to compile run-time bounds checks
+of array subscripts, as well as of substring start and end points.
+
+@item
+@code{libg2c} now supports building as multilibbed library,
+which provides better support for systems
+that require options such as @samp{-mieee}
+to work properly.
+
+@item
+Source file names with the suffixes @samp{.FOR} and @samp{.FPP}
+now are recognized by @code{g77}
+as if they ended in @samp{.for} and @samp{.fpp}, respectively.
+
+@item
+The order of arguments to the @emph{subroutine} forms of the
+@code{CTime}, @code{DTime}, @code{ETime}, and @code{TtyNam}
+intrinsics has been swapped.
+The argument serving as the returned value
+for the corresponding function forms
+now is the @emph{second} argument,
+making these consistent with the other subroutine forms
+of @code{libU77} intrinsics.
+
+@item
+@code{g77} now warns about a reference to an intrinsic
+that has an interface that is not Year 2000 (Y2K) compliant.
+Also, @code{libg2c} has been changed to increase the likelihood
+of catching references to the implementations of these intrinsics
+using the @code{EXTERNAL} mechanism
+(which would avoid the new warnings).
+
+@ifset DOC-G77
+@xref{Year 2000 (Y2K) Problems}, for more information.
+@end ifset
+
+@ifclear USERVISONLY
+@item
+@code{g77} now warns about a reference to a function
+when the corresponding @emph{subsequent} function program unit
+disagrees with the reference concerning the type of the function.
+@end ifclear
+
+@item
+@samp{-fno-emulate-complex} is now the default option.
+This should result in improved performance
+of code that uses the @code{COMPLEX} data type.
+
+@cindex alignment
+@cindex double-precision performance
+@cindex -malign-double
+@item
+The @samp{-malign-double} option
+now reliably aligns @emph{all} double-precision variables and arrays
+on Intel x86 targets.
+
+@ifclear USERVISONLY
+@item
+Even without the @samp{-malign-double} option,
+@code{g77} reliably aligns local double-precision variables
+that are not in @code{EQUIVALENCE} areas
+and not @code{SAVE}'d.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+@code{g77} now open-codes (``inlines'') division of @code{COMPLEX} operands
+instead of generating a run-time call to
+the @code{libf2c} routines @code{c_div} or @code{z_div},
+unless the @samp{-Os} option is specified.
+@end ifclear
+
+@item
+@code{g77} no longer generates code to maintain @code{errno},
+a C-language concept,
+when performing operations such as the @code{SqRt} intrinsic.
+
+@ifclear USERVISONLY
+@item
+@code{g77} developers can temporarily use
+the @samp{-fflatten-arrays} option
+to compare how the compiler handles code generation
+using C-like constructs as compared to the
+Fortran-like method constructs normally used.
+@end ifclear
-@heading In 0.5.24 and @code{egcs} 1.1.2 (versus 0.5.23 and 1.1.1):
+@ifclear USERVISONLY
+@item
+A substantial portion of the @code{g77} front end's code-generation component
+was rewritten.
+It now generates code using facilities more robustly supported
+by the @code{gcc} back end.
+One effect of this rewrite is that some codes no longer produce
+a spurious ``label @var{lab} used before containing binding contour''
+message.
+@end ifclear
+
+@item
+Support for the @samp{-fugly} option has been removed.
+
+@ifclear USERVISONLY
+@item
+Improve documentation and indexing,
+including information on Year 2000 (Y2K) compliance,
+and providing more information on internals of the front end.
+@end ifclear
+
+@ifclear USERVISONLY
+@item
+Upgrade to @code{libf2c} as of 1999-05-10.
+@end ifclear
+@end itemize
+
+@heading In 0.5.24 versus 0.5.23:
+
+There is no @code{g77} version 0.5.24 at this time,
+or planned.
+0.5.24 is the version number designated for bug fixes and,
+perhaps, some new features added,
+to 0.5.23.
+Version 0.5.23 requires @code{gcc} 2.8.1,
+as 0.5.24 was planned to require.
+
+Due to @code{EGCS} becoming @code{GCC}
+(which is now an acronym for ``GNU Compiler Collection''),
+and @code{EGCS} 1.2 becoming officially designated @code{GCC} 2.95,
+there seems to be no need for an actual 0.5.24 release.
+
+To reduce the confusion already resulting from use of 0.5.24
+to designate @code{g77} versions within @code{EGCS} versions 1.0 and 1.1,
+as well as in versions of @code{g77} documentation and notices
+during that period,
+``mainline'' @code{g77} version numbering resumes
+at 0.5.25 with @code{GCC} 2.95 (@code{EGCS} 1.2),
+skipping over 0.5.24 as a placeholder version number.
+
+To repeat, there is no @code{g77} 0.5.24, but there is now a 0.5.25.
+Please remain calm and return to your keypunch units.
+
+@c 1999-03-15: EGCS 1.1.2 released.
+@heading In @code{EGCS} 1.1.2 versus @code{EGCS} 1.1.1:
+@ifclear USERVISONLY
@itemize @bullet
@item
-Fix the @code{IDate} Intrinsic (VXT)
+Fix the @code{IDate} intrinsic (VXT) (in @code{libg2c})
so the returned year is in the documented, non-Y2K-compliant range
-of 0--99,
+of 0-99,
instead of being returned as 100 in the year 2000.
+@ifset DOC-G77
+@xref{IDate Intrinsic (VXT)},
+for more information.
+@end ifset
+
@item
-Fix the @samp{Date_and_Time} intrinsic (in @code{libg2c})
+Fix the @code{Date_and_Time} intrinsic (in @code{libg2c})
to return the milliseconds value properly
in @var{Values}(8).
@item
-Fix the @samp{LStat} intrinsic (in @code{libg2c})
+Fix the @code{LStat} intrinsic (in @code{libg2c})
to return device-ID information properly
in @var{SArray}(7).
@item
Improve documentation.
@end itemize
+@end ifclear
-@heading In 0.5.24 and @code{egcs} 1.1.1 (versus 0.5.23 and 1.1):
+@c 1998-12-04: EGCS 1.1.1 released.
+@heading In @code{EGCS} 1.1.1 versus @code{EGCS} 1.1:
+@ifclear USERVISONLY
@itemize @bullet
@item
Fix @code{libg2c} so it performs an implicit @code{ENDFILE} operation
@@ -105,67 +432,31 @@ upon doing any I/O following a direct formatted write.
@item
Fix @code{g77} so it no longer crashes compiling references
-to the @samp{Rand} intrinsic on some systems.
+to the @code{Rand} intrinsic on some systems.
@item
Fix @code{g77} portion of installation process so it works
better on some systems
(those with shells requiring @samp{else true} clauses
-on @samp{if} constructs
+on @code{if} constructs
for the completion code to be set properly).
@end itemize
+@end ifclear
-@heading In @code{egcs} 1.1 (versus 0.5.24):
-@itemize @bullet
-@item
-Fix @code{g77} crash compiling code
-containing the construct @samp{CMPLX(0.)} or similar.
-
-@item
-Fix @code{g77} crash
-(or apparently infinite run-time)
-when compiling certain complicated expressions
-involving @code{COMPLEX} arithmetic
-(especially multiplication).
-
-@cindex DNRM2
-@cindex stack, 387 coprocessor
-@cindex Intel x86
-@cindex -O2
-@item
-Fix a code-generation bug that afflicted
-Intel x86 targets when @samp{-O2} was specified
-compiling, for example, an old version of
-the @samp{DNRM2} routine.
-
-The x87 coprocessor stack was being
-mismanaged in cases involving assigned @code{GOTO}
-and @code{ASSIGN}.
-
-@cindex alignment
-@cindex double-precision performance
-@cindex -malign-double
-@item
-Align static double-precision variables and arrays
-on Intel x86 targets
-regardless of whether @samp{-malign-double} is specified.
-
-Generally, this affects only local variables and arrays
-having the @code{SAVE} attribute
-or given initial values via @code{DATA}.
-@end itemize
-
-@c 1998-09-01: egcs-1.1 released.
-@heading In @code{egcs} 1.1 (versus @code{egcs} 1.0.3):
+@c 1998-09-03: EGCS 1.1 released.
+@heading In @code{EGCS} 1.1 versus @code{EGCS} 1.0.3:
@itemize @bullet
+@ifclear USERVISONLY
@item
-Fix bugs in the @code{libU77} intrinsic @samp{HostNm}
-that wrote one byte beyond the end of its @samp{CHARACTER}
+Fix bugs in the @code{libU77} intrinsic @code{HostNm}
+that wrote one byte beyond the end of its @code{CHARACTER}
argument,
and in the @code{libU77} intrinsics
-@samp{GMTime} and @samp{LTime}
+@code{GMTime} and @code{LTime}
that overwrote their arguments.
+@end ifclear
+@ifclear USERVISONLY
@item
Assumed arrays with negative bounds
(such as @samp{REAL A(-1:*)})
@@ -176,7 +467,9 @@ different sizes than integers.
This bug is not known to have existed in any
recent version of @code{gcc}.
It was introduced in an early release of @code{egcs}.
+@end ifclear
+@ifclear USERVISONLY
@item
Valid combinations of @code{EXTERNAL},
passing that external as a dummy argument
@@ -185,14 +478,19 @@ and, in a subsequent program unit,
referencing that external as
an external function with a different type
no longer crash @code{g77}.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{CASE DEFAULT} no longer crashes @code{g77}.
+@end ifclear
+@ifclear USERVISONLY
@item
The @samp{-Wunused} option no longer issues a spurious
warning about the ``master'' procedure generated by
@code{g77} for procedures containing @code{ENTRY} statements.
+@end ifclear
@item
Support @samp{FORMAT(I<@var{expr}>)} when @var{expr} is a
@@ -200,7 +498,7 @@ compile-time constant @code{INTEGER} expression.
@item
Fix @code{g77} @samp{-g} option so procedures that
-use @samp{ENTRY} can be stepped through, line by line,
+use @code{ENTRY} can be stepped through, line by line,
in @code{gdb}.
@item
@@ -225,6 +523,7 @@ that have their own (non-Fortran) @code{main()} routine
properly set up the @code{libf2c} environment, even
when @code{libf2c} (now @code{libg2c}) is a shared library.
+@ifclear USERVISONLY
@item
@code{g77} no longer installs the @file{f77} command
and @file{f77.1} man page
@@ -232,7 +531,9 @@ in the @file{/usr} or @file{/usr/local} heirarchy,
even if the @file{f77-install-ok} file exists
in the source or build directory.
See the installation documentation for more information.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{g77} no longer installs the @file{libf2c.a} library
and @file{f2c.h} include file
@@ -240,7 +541,9 @@ in the @file{/usr} or @file{/usr/local} heirarchy,
even if the @file{f2c-install-ok} or @file{f2c-exists-ok} files exist
in the source or build directory.
See the installation documentation for more information.
+@end ifclear
+@ifclear USERVISONLY
@item
The @file{libf2c.a} library produced by @code{g77} has been
renamed to @file{libg2c.a}.
@@ -250,7 +553,9 @@ This allows system administrators and users to choose which
version of the @code{libf2c} library from @code{netlib} they
wish to use on a case-by-case basis.
See the installation documentation for more information.
+@end ifclear
+@ifclear USERVISONLY
@item
The @file{f2c.h} include (header) file produced by @code{g77}
has been renamed to @file{g2c.h}.
@@ -260,6 +565,7 @@ This allows system administrators and users to choose which
version of the include file from @code{netlib} they
wish to use on a case-by-case basis.
See the installation documentation for more information.
+@end ifclear
@item
The @code{g77} command now expects the run-time library
@@ -267,17 +573,21 @@ to be named @code{libg2c.a} instead of @code{libf2c.a},
to ensure that a version other than the one built and
installed as part of the same @code{g77} version is picked up.
+@ifclear USERVISONLY
@item
During the configuration and build process,
@code{g77} creates subdirectories it needs only as it
needs them.
Other cleaning up of the configuration and build process
has been performed as well.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{install-info} now used to update the directory of
Info documentation to contain an entry for @code{g77}
(during installation).
+@end ifclear
@item
Some diagnostics have been changed from warnings to errors,
@@ -288,41 +598,76 @@ in the @code{OPEN}, @code{INQUIRE}, @code{READ}, and
@code{WRITE} statements,
and about truncations of various sorts of constants.
+@ifclear USERVISONLY
@item
Improve compilation of @code{FORMAT} expressions so that
a null byte is appended to the last operand if it
is a constant.
This provides a cleaner run-time diagnostic as provided
by @code{libf2c} for statements like @samp{PRINT '(I1', 42}.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve documentation and indexing.
+@end ifclear
+@ifclear USERVISONLY
@item
The upgrade to @code{libf2c} as of 1998-06-18
should fix a variety of problems, including
-those involving some uses of the @samp{T} format
+those involving some uses of the @code{T} format
specifier, and perhaps some build (porting) problems
as well.
+@end ifclear
@end itemize
-@heading In 0.5.24 and @code{egcs} 1.1 (versus 0.5.23):
+@c 1998-09-03: EGCS 1.1 released.
+@heading In @code{EGCS} 1.1 versus @code{g77} 0.5.23:
@itemize @bullet
+@ifclear USERVISONLY
+@cindex DNRM2
+@cindex stack, 387 coprocessor
+@cindex Intel x86
+@cindex -O2
+@item
+Fix a code-generation bug that afflicted
+Intel x86 targets when @samp{-O2} was specified
+compiling, for example, an old version of
+the @code{DNRM2} routine.
+
+The x87 coprocessor stack was being
+mismanaged in cases involving assigned @code{GOTO}
+and @code{ASSIGN}.
+@end ifclear
+
+@ifclear USERVISONLY
@item
@code{g77} no longer produces incorrect code
and initial values
-for @samp{EQUIVALENCE} and @samp{COMMON}
+for @code{EQUIVALENCE} and @code{COMMON}
aggregates that, due to ``unnatural'' ordering of members
vis-a-vis their types, require initial padding.
+@end ifclear
+@ifclear USERVISONLY
+@item
+Fix @code{g77} crash compiling code
+containing the construct @samp{CMPLX(0.)} or similar.
+@end ifclear
+
+@ifclear USERVISONLY
@item
@code{g77} no longer crashes when compiling code
containing specification statements such as
@samp{INTEGER(KIND=7) PTR}.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{g77} no longer crashes when compiling code
such as @samp{J = SIGNAL(1, 2)}.
+@end ifclear
@item
@code{g77} now treats @samp{%LOC(@var{expr})} and
@@ -337,6 +682,27 @@ Previously, @code{g77} treated these expressions
as denoting special ``pointer'' arguments
for the purposes of filewide analysis.
+@ifclear USERVISONLY
+@item
+Fix @code{g77} crash
+(or apparently infinite run-time)
+when compiling certain complicated expressions
+involving @code{COMPLEX} arithmetic
+(especially multiplication).
+@end ifclear
+
+@cindex alignment
+@cindex double-precision performance
+@cindex -malign-double
+@item
+Align static double-precision variables and arrays
+on Intel x86 targets
+regardless of whether @samp{-malign-double} is specified.
+
+Generally, this affects only local variables and arrays
+having the @code{SAVE} attribute
+or given initial values via @code{DATA}.
+
@item
The @code{g77} driver now ensures that @samp{-lg2c}
is specified in the link phase prior to any
@@ -353,31 +719,48 @@ in @code{libf2c} (@code{libg2c}).
This new information allows, for example,
@kbd{which __g77_length_a} to be used in @code{gdb}
to determine the type of the phantom length argument
-supplied with @samp{CHARACTER} variables.
+supplied with @code{CHARACTER} variables.
This information pertains to internally-generated
type, variable, and other information,
not to the longstanding deficiencies vis-a-vis
-@samp{COMMON} and @samp{EQUIVALENCE}.
+@code{COMMON} and @code{EQUIVALENCE}.
@item
-The F90 @samp{Date_and_Time} intrinsic now is
+The F90 @code{Date_and_Time} intrinsic now is
supported.
@item
-The F90 @samp{System_Clock} intrinsic allows
-the optional arguments (except for the @samp{Count}
+The F90 @code{System_Clock} intrinsic allows
+the optional arguments (except for the @code{Count}
argument) to be omitted.
+@ifclear USERVISONLY
@item
Upgrade to @code{libf2c} as of 1998-06-18.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve documentation and indexing.
+@end ifclear
@end itemize
+@ifset DOC-NEWS
+@heading In previous versions:
+
+Information on previous versions is not provided
+in this @file{@value{path-g77}/NEWS} file,
+to keep it short.
+See @file{@value{path-g77}/news.texi},
+or any of its other derivations
+(Info, HTML, dvi forms)
+for such information.
+@end ifset
+
+@ifclear DOC-NEWS
@c 1998-05-20: 0.5.23 released.
-@heading In 0.5.23 (versus 0.5.22):
+@heading In 0.5.23 versus 0.5.22:
@itemize @bullet
@item
This release contains several regressions against
@@ -386,24 +769,12 @@ version 0.5.22 of @code{g77}, due to using the
it to fix a few bugs and improve performance in a
few cases.
-@ifset last-up-date
-@xref{Actual Bugs,,Actual Bugs We Haven't Fixed Yet},
-for information on the known bugs in this version,
-including the regressions.
-@end ifset
-
-@ifset NEWSONLY
-See @file{egcs/gcc/f/BUGS},
-for information on the known bugs in this version,
-including the regressions.
-@end ifset
-
Features that have been dropped from this version
of @code{g77} due to their being implemented
via @code{g77}-specific patches to the @code{gcc}
back end in previous releases include:
-@itemize --
+@itemize @minus
@item
Support for @code{__restrict__} keyword,
the options @samp{-fargument-alias}, @samp{-fargument-noalias},
@@ -437,33 +808,40 @@ applying to stack-allocated data
as well as statically-allocate data.
@end itemize
+@ifclear USERVISONLY
Note that the @file{gcc/f/gbe/} subdirectory has been removed
from this distribution as a result of @code{g77} no longer
including patches for the @code{gcc} back end.
+@end ifclear
+@ifclear USERVISONLY
@item
-Fix bugs in the @code{libU77} intrinsic @samp{HostNm}
-that wrote one byte beyond the end of its @samp{CHARACTER}
+Fix bugs in the @code{libU77} intrinsic @code{HostNm}
+that wrote one byte beyond the end of its @code{CHARACTER}
argument,
and in the @code{libU77} intrinsics
-@samp{GMTime} and @samp{LTime}
+@code{GMTime} and @code{LTime}
that overwrote their arguments.
+@end ifclear
@item
Support @code{gcc} version 2.8,
and remove support for prior versions of @code{gcc}.
@cindex -@w{}-driver option
-@cindex g77 options, -@w{}-driver
+@cindex @code{g77} options, -@w{}-driver
@cindex options, -@w{}-driver
@item
Remove support for the @samp{--driver} option,
as @code{g77} now does all the driving,
just like @code{gcc}.
+@ifclear USERVISONLY
@item
@code{CASE DEFAULT} no longer crashes @code{g77}.
+@end ifclear
+@ifclear USERVISONLY
@item
Valid combinations of @code{EXTERNAL},
passing that external as a dummy argument
@@ -472,7 +850,9 @@ and, in a subsequent program unit,
referencing that external as
an external function with a different type
no longer crash @code{g77}.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{g77} no longer installs the @file{f77} command
and @file{f77.1} man page
@@ -480,7 +860,9 @@ in the @file{/usr} or @file{/usr/local} heirarchy,
even if the @file{f77-install-ok} file exists
in the source or build directory.
See the installation documentation for more information.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{g77} no longer installs the @file{libf2c.a} library
and @file{f2c.h} include file
@@ -488,7 +870,9 @@ in the @file{/usr} or @file{/usr/local} heirarchy,
even if the @file{f2c-install-ok} or @file{f2c-exists-ok} files exist
in the source or build directory.
See the installation documentation for more information.
+@end ifclear
+@ifclear USERVISONLY
@item
The @file{libf2c.a} library produced by @code{g77} has been
renamed to @file{libg2c.a}.
@@ -498,7 +882,9 @@ This allows system administrators and users to choose which
version of the @code{libf2c} library from @code{netlib} they
wish to use on a case-by-case basis.
See the installation documentation for more information.
+@end ifclear
+@ifclear USERVISONLY
@item
The @file{f2c.h} include (header) file produced by @code{g77}
has been renamed to @file{g2c.h}.
@@ -508,6 +894,7 @@ This allows system administrators and users to choose which
version of the include file from @code{netlib} they
wish to use on a case-by-case basis.
See the installation documentation for more information.
+@end ifclear
@item
The @code{g77} command now expects the run-time library
@@ -515,10 +902,12 @@ to be named @code{libg2c.a} instead of @code{libf2c.a},
to ensure that a version other than the one built and
installed as part of the same @code{g77} version is picked up.
+@ifclear USERVISONLY
@item
The @samp{-Wunused} option no longer issues a spurious
warning about the ``master'' procedure generated by
@code{g77} for procedures containing @code{ENTRY} statements.
+@end ifclear
@item
@code{g77}'s version of @code{libf2c} separates out
@@ -532,6 +921,7 @@ that have their own (non-Fortran) @code{main()} routine
properly set up the @code{libf2c} environment, even
when @code{libf2c} (now @code{libg2c}) is a shared library.
+@ifclear USERVISONLY
@item
During the configuration and build process,
@code{g77} creates subdirectories it needs only as it
@@ -539,11 +929,14 @@ needs them, thus avoiding unnecessary creation of, for example,
@file{stage1/f/runtime} when doing a non-bootstrap build.
Other cleaning up of the configuration and build process
has been performed as well.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{install-info} now used to update the directory of
Info documentation to contain an entry for @code{g77}
(during installation).
+@end ifclear
@item
Some diagnostics have been changed from warnings to errors,
@@ -554,27 +947,34 @@ in the @code{OPEN}, @code{INQUIRE}, @code{READ}, and
@code{WRITE} statements,
and about truncations of various sorts of constants.
+@ifclear USERVISONLY
@item
Improve documentation and indexing.
+@end ifclear
+@ifclear USERVISONLY
@item
Upgrade to @code{libf2c} as of 1998-04-20.
This should fix a variety of problems, including
-those involving some uses of the @samp{T} format
+those involving some uses of the @code{T} format
specifier, and perhaps some build (porting) problems
as well.
+@end ifclear
@end itemize
@c 1998-03-16: 0.5.22 released.
-@heading In 0.5.22 (versus 0.5.21):
+@heading In 0.5.22 versus 0.5.21:
@itemize @bullet
+@ifclear USERVISONLY
@item
Fix code generation for iterative @code{DO} loops that
have one or more references to the iteration variable,
or to aliases of it, in their control expressions.
For example, @samp{DO 10 J=2,J} now is compiled correctly.
+@end ifclear
+@ifclear USERVISONLY
@cindex DNRM2
@cindex stack, 387 coprocessor
@cindex Intel x86
@@ -583,54 +983,71 @@ For example, @samp{DO 10 J=2,J} now is compiled correctly.
Fix a code-generation bug that afflicted
Intel x86 targets when @samp{-O2} was specified
compiling, for example, an old version of
-the @samp{DNRM2} routine.
+the @code{DNRM2} routine.
The x87 coprocessor stack was being
mismanaged in cases involving assigned @code{GOTO}
and @code{ASSIGN}.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{DTime} intrinsic so as not to truncate
results to integer values (on some systems).
+@end ifclear
@item
Fix @code{Signal} intrinsic so it offers portable
support for 64-bit systems (such as Digital Alphas
running GNU/Linux).
+@ifclear USERVISONLY
@item
Fix run-time crash involving @code{NAMELIST} on 64-bit
machines such as Alphas.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} version of @code{libf2c} so it no longer
produces a spurious @samp{I/O recursion} diagnostic at run time
when an I/O operation (such as @samp{READ *,I}) is interrupted
in a manner that causes the program to be terminated
-via the @samp{f_exit} routine (such as via @kbd{C-c}).
+via the @code{f_exit} routine (such as via @kbd{C-c}).
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} crash triggered by @code{CASE} statement with
an omitted lower or upper bound.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} crash compiling references to @code{CPU_Time}
intrinsic.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} crash
(or apparently infinite run-time)
when compiling certain complicated expressions
involving @code{COMPLEX} arithmetic
(especially multiplication).
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} crash on statements such as
@samp{PRINT *, (REAL(Z(I)),I=1,2)}, where
@samp{Z} is @code{DOUBLE COMPLEX}.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix a @code{g++} crash.
+@end ifclear
@item
Support @samp{FORMAT(I<@var{expr}>)} when @var{expr} is a
@@ -638,12 +1055,14 @@ compile-time constant @code{INTEGER} expression.
@item
Fix @code{g77} @samp{-g} option so procedures that
-use @samp{ENTRY} can be stepped through, line by line,
+use @code{ENTRY} can be stepped through, line by line,
in @code{gdb}.
+@ifclear USERVISONLY
@item
Fix a profiling-related bug in @code{gcc} back end for
Intel x86 architecture.
+@end ifclear
@item
Allow any @code{REAL} argument to intrinsics
@@ -666,9 +1085,11 @@ C programs.
Support for @code{restrict} is now more like support
for @code{complex}.
+@ifclear USERVISONLY
@item
Fix @samp{-fpedantic} to not reject procedure invocations
such as @samp{I=J()} and @samp{CALL FOO()}.
+@end ifclear
@item
Fix @samp{-fugly-comma} to affect invocations of
@@ -680,6 +1101,7 @@ arguments to intrinsics, as in @samp{I=MAX(3,4,,)}.
Fix compiler so it accepts @samp{-fgnu-intrinsics-*} and
@samp{-fbadu77-intrinsics-*} options.
+@ifclear USERVISONLY
@item
Improve diagnostic messages from @code{libf2c}
so it is more likely that the printing of the
@@ -692,45 +1114,63 @@ format string specified via a @code{FORMAT} statement.
However, @code{f2c} would exhibit the problem
anyway for a statement like @samp{PRINT '(I)garbage', 1}
by printing @samp{(I)garbage} as the format string.)
+@end ifclear
+@ifclear USERVISONLY
@item
Improve compilation of @code{FORMAT} expressions so that
a null byte is appended to the last operand if it
is a constant.
This provides a cleaner run-time diagnostic as provided
by @code{libf2c} for statements like @samp{PRINT '(I1', 42}.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix various crashes involving code with diagnosed errors.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix cross-compilation bug when configuring @code{libf2c}.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve diagnostics.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve documentation and indexing.
+@end ifclear
+@ifclear USERVISONLY
@item
Upgrade to @code{libf2c} as of 1997-09-23.
This fixes a formatted-I/O bug that afflicted
64-bit systems with 32-bit integers
(such as Digital Alpha running GNU/Linux).
+@end ifclear
@end itemize
-@c 1998-03-15: egcs-1.0.2 released.
-@heading In @code{egcs} 1.0.2 (versus @code{egcs} 1.0.1):
+@c 1998-03-18: EGCS 1.0.2 released.
+@heading In @code{EGCS} 1.0.2 versus @code{EGCS} 1.0.1:
@itemize @bullet
+@ifclear USERVISONLY
@item
Fix @code{g77} crash triggered by @code{CASE} statement with
an omitted lower or upper bound.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} crash on statements such as
@samp{PRINT *, (REAL(Z(I)),I=1,2)}, where
@samp{Z} is @code{DOUBLE COMPLEX}.
+@end ifclear
+@ifclear USERVISONLY
@cindex ELF support
@cindex support, ELF
@cindex -fPIC option
@@ -739,32 +1179,39 @@ Fix @code{g77} crash on statements such as
Fix @samp{-fPIC} (such as compiling for ELF targets)
on the Intel x86 architecture target
so invalid assembler code is no longer produced.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @samp{-fpedantic} to not reject procedure invocations
such as @samp{I=J()} and @samp{CALL FOO()}.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @samp{-fugly-comma} to affect invocations of
only external procedures.
Restore rejection of gratuitous trailing omitted
arguments to intrinsics, as in @samp{I=MAX(3,4,,)}.
+@end ifclear
@item
Fix compiler so it accepts @samp{-fgnu-intrinsics-*} and
@samp{-fbadu77-intrinsics-*} options.
@end itemize
-@c 1998-01-02: egcs-1.0.1 released.
-@heading In @code{egcs} 1.0.1 (versus @code{egcs} 1.0):
+@c 1998-01-06: EGCS 1.0.1 released.
+@heading In @code{EGCS} 1.0.1 versus @code{EGCS} 1.0:
+@ifclear USERVISONLY
@itemize @bullet
@item
Fix run-time crash involving @code{NAMELIST} on 64-bit
machines such as Alphas.
@end itemize
+@end ifclear
-@c 1997-12-03: egcs-1.0 released.
-@heading In @code{egcs} 1.0 (versus 0.5.21):
+@c 1997-12-03: EGCS 1.0 released.
+@heading In @code{EGCS} 1.0 versus @code{g77} 0.5.21:
@itemize @bullet
@item
Version 1.0 of @code{egcs}
@@ -775,24 +1222,12 @@ due to using the
it to fix a few bugs and improve performance in a
few cases.
-@ifset last-up-date
-@xref{Actual Bugs,,Actual Bugs We Haven't Fixed Yet},
-for information on the known bugs in this version,
-including the regressions.
-@end ifset
-
-@ifset NEWSONLY
-See @file{egcs/gcc/f/BUGS},
-for information on the known bugs in this version,
-including the regressions.
-@end ifset
-
Features that have been dropped from this version
of @code{g77} due to their being implemented
via @code{g77}-specific patches to the @code{gcc}
back end in previous releases include:
-@itemize --
+@itemize @minus
@item
Support for the C-language @code{restrict} keyword.
@@ -806,26 +1241,48 @@ applying to stack-allocated data
as well as statically-allocate data.
@end itemize
+@ifclear USERVISONLY
Note that the @file{gcc/f/gbe/} subdirectory has been removed
from this distribution as a result of @code{g77}
being fully integrated with
the @code{egcs} variant of the @code{gcc} back end.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix code generation for iterative @code{DO} loops that
have one or more references to the iteration variable,
or to aliases of it, in their control expressions.
For example, @samp{DO 10 J=2,J} now is compiled correctly.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{DTime} intrinsic so as not to truncate
results to integer values (on some systems).
+@end ifclear
+@ifclear USERVISONLY
+@item
+@c Toon Moene discovered these.
+Some Fortran code, miscompiled
+by @code{g77} built on @code{gcc} version 2.8.1
+on m68k-next-nextstep3 configurations
+when using the @samp{-O2} option,
+is now compiled correctly.
+It is believed that a C function known to miscompile
+on that configuration
+when using the @samp{-O2 -funroll-loops} options
+also is now compiled correctly.
+@end ifclear
+
+@ifclear USERVISONLY
@item
Remove support for non-@code{egcs} versions of @code{gcc}.
+@end ifclear
@cindex -@w{}-driver option
-@cindex g77 options, -@w{}-driver
+@cindex @code{g77} options, -@w{}-driver
@cindex options, -@w{}-driver
@item
Remove support for the @samp{--driver} option,
@@ -836,6 +1293,7 @@ just like @code{gcc}.
Allow any numeric argument to intrinsics
@code{Int2} and @code{Int8}.
+@ifclear USERVISONLY
@item
Improve diagnostic messages from @code{libf2c}
so it is more likely that the printing of the
@@ -848,17 +1306,21 @@ format string specified via a @code{FORMAT} statement.
However, @code{f2c} would exhibit the problem
anyway for a statement like @samp{PRINT '(I)garbage', 1}
by printing @samp{(I)garbage} as the format string.)
+@end ifclear
+@ifclear USERVISONLY
@item
Upgrade to @code{libf2c} as of 1997-09-23.
This fixes a formatted-I/O bug that afflicted
64-bit systems with 32-bit integers
(such as Digital Alpha running GNU/Linux).
+@end ifclear
@end itemize
@c 1997-09-09: 0.5.21 released.
@heading In 0.5.21:
@itemize @bullet
+@ifclear USERVISONLY
@item
Fix a code-generation bug introduced by 0.5.20
caused by loop unrolling (by specifying
@@ -866,7 +1328,9 @@ caused by loop unrolling (by specifying
This bug afflicted all code compiled by
version 2.7.2.2.f.2 of @code{gcc} (C, C++,
Fortran, and so on).
+@end ifclear
+@ifclear USERVISONLY
@item
Fix a code-generation bug manifested when
combining local @code{EQUIVALENCE} with a
@@ -875,7 +1339,9 @@ the first executable statement (or is
treated as an executable-context statement
as a result of using the @samp{-fpedantic}
option).
+@end ifclear
+@ifclear USERVISONLY
@item
Fix a compiler crash that occured when an
integer division by a constant zero is detected.
@@ -884,34 +1350,52 @@ the @code{gcc} back end issues a warning about such a case.
This bug afflicted all code compiled by
version 2.7.2.2.f.2 of @code{gcc} (C, C++,
Fortran, and so on).
+@end ifclear
+@ifset USERVISONLY
+@item
+When the @samp{-W} option is specified, @code{gcc}, @code{g77},
+and other GNU compilers that incorporate the @code{gcc}
+back end as modified by @code{g77}, issue
+a warning about integer division by constant zero.
+@end ifset
+@ifclear USERVISONLY
@item
Fix a compiler crash that occurred in some cases
of procedure inlining.
(Such cases became more frequent in 0.5.20.)
+@end ifclear
+@ifclear USERVISONLY
@item
Fix a compiler crash resulting from using @code{DATA}
or similar to initialize a @code{COMPLEX} variable or
array to zero.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix compiler crashes involving use of @code{AND}, @code{OR},
or @code{XOR} intrinsics.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix compiler bug triggered when using a @code{COMMON}
or @code{EQUIVALENCE} variable
as the target of an @code{ASSIGN}
or assigned-@code{GOTO} statement.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix compiler crashes due to using the name of a some
-non-standard intrinsics (such as @samp{FTELL} or
-@samp{FPUTC}) as such and as the name of a procedure
+non-standard intrinsics (such as @code{FTell} or
+@code{FPutC}) as such and as the name of a procedure
or common block.
Such dual use of a name in a program is allowed by
the standard.
+@end ifclear
@c @code{g77}'s version of @code{libf2c} has been modified
@c so that the external names of library's procedures do not
@@ -924,30 +1408,34 @@ the standard.
@c
@c For example, the intrinsic @code{FPUTC} previously was
@c implemented by @code{g77} as a call to the @code{libf2c}
-@c routine @samp{fputc_}.
+@c routine @code{fputc_}.
@c This would conflict with a Fortran procedure named @code{FPUTC}
@c (using default compiler options), and this conflict
@c would cause a crash under certain circumstances.
@c
-@c Now, the intrinsic @code{FPUTC} calls @samp{G77_fputc_0},
-@c which does not conflict with the @samp{fputc_} external
+@c Now, the intrinsic @code{FPUTC} calls @code{G77_fputc_0},
+@c which does not conflict with the @code{fputc_} external
@c that implements a Fortran procedure named @code{FPUTC}.
@c
@c Programs that refer to @code{FPUTC} as an external procedure
@c without supplying their own implementation will link to
-@c the new @code{libf2c} routine @samp{fputc_}, which is
-@c simply a jacket routine that calls @samp{G77_fputc_0}.
+@c the new @code{libf2c} routine @code{fputc_}, which is
+@c simply a jacket routine that calls @code{G77_fputc_0}.
+@ifclear USERVISONLY
@item
Place automatic arrays on the stack, even if
@code{SAVE} or the @samp{-fno-automatic} option
is in effect.
This avoids a compiler crash in some cases.
+@end ifclear
+@ifclear USERVISONLY
@item
The @samp{-malign-double} option now reliably aligns
@code{DOUBLE PRECISION} optimally on Pentium and
Pentium Pro architectures (586 and 686 in @code{gcc}).
+@end ifclear
@item
New option @samp{-Wno-globals} disables warnings
@@ -977,41 +1465,53 @@ This option also disables inlining of global procedures,
to avoid compiler crashes resulting from coding errors
that these diagnostics normally would identify.
+@ifclear USERVISONLY
@item
Diagnose cases where a reference to a procedure
disagrees with the type of that procedure, or
where disagreements about the number or nature
of arguments exist.
This avoids a compiler crash.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix parsing bug whereby @code{g77} rejected a
second initialization specification immediately
following the first's closing @samp{/} without
an intervening comma in a @code{DATA} statement,
and the second specification was an implied-DO list.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve performance of the @code{gcc} back end so
certain complicated expressions involving @code{COMPLEX}
arithmetic (especially multiplication) don't appear to
take forever to compile.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix a couple of profiling-related bugs in @code{gcc}
back end.
+@end ifclear
+@ifclear USERVISONLY
@item
Integrate GNU Ada's (GNAT's) changes to the back end,
which consist almost entirely of bug fixes.
These fixes are circa version 3.10p of GNAT.
+@end ifclear
+@ifclear USERVISONLY
@item
Include some other @code{gcc} fixes that seem useful in
@code{g77}'s version of @code{gcc}.
(See @file{gcc/ChangeLog} for details---compare it
to that file in the vanilla @code{gcc-2.7.2.3.tar.gz}
distribution.)
+@end ifclear
@item
Fix @code{libU77} routines that accept file and other names
@@ -1027,13 +1527,15 @@ that have embedded blanks, commas, and so on.
@item
Fix @code{SIGNAL} intrinsic so it accepts an
-optional third @samp{Status} argument.
+optional third @code{Status} argument.
+@ifclear USERVISONLY
@item
Fix @code{IDATE()} intrinsic subroutine (VXT form)
so it accepts arguments in the correct order.
Documentation fixed accordingly, and for
@code{GMTIME()} and @code{LTIME()} as well.
+@end ifclear
@item
Make many changes to @code{libU77} intrinsics to
@@ -1047,42 +1549,57 @@ return @code{INTEGER(KIND=2)} values,
and placing functions that are intended to perform
side effects in a new intrinsic group, @code{badu77}.
+@ifclear USERVISONLY
@item
Improve @code{libU77} so it is more portable.
+@end ifclear
@item
Add options @samp{-fbadu77-intrinsics-delete},
@samp{-fbadu77-intrinsics-hide}, and so on.
+@ifclear USERVISONLY
@item
Fix crashes involving diagnosed or invalid code.
+@end ifclear
+@ifclear USERVISONLY
@item
@code{g77} and @code{gcc} now do a somewhat better
job detecting and diagnosing arrays that are too
large to handle before these cause diagnostics
during the assembler or linker phase, a compiler
crash, or generation of incorrect code.
+@end ifclear
+@ifclear USERVISONLY
@item
Make some fixes to alias analysis code.
+@end ifclear
+@ifclear USERVISONLY
@item
Add support for @code{restrict} keyword in @code{gcc}
front end.
+@end ifclear
+@ifclear USERVISONLY
@item
Support @code{gcc} version 2.7.2.3
(modified by @code{g77} into version 2.7.2.3.f.1),
and remove
support for prior versions of @code{gcc}.
+@end ifclear
+@ifclear USERVISONLY
@item
Incorporate GNAT's patches to the @code{gcc} back
end into @code{g77}'s, so GNAT users do not need
to apply GNAT's patches to build both GNAT and @code{g77}
from the same source tree.
+@end ifclear
+@ifclear USERVISONLY
@item
Modify @code{make} rules and related code so that
generation of Info documentation doesn't require
@@ -1090,6 +1607,7 @@ compilation using @code{gcc}.
Now, any ANSI C compiler should be adequate to
produce the @code{g77} documentation (in particular,
the tables of intrinsics) from scratch.
+@end ifclear
@item
Add @code{INT2} and @code{INT8} intrinsics.
@@ -1104,46 +1622,64 @@ Add @code{ALARM} intrinsic.
@code{CTIME} intrinsic now accepts any @code{INTEGER}
argument, not just @code{INTEGER(KIND=2)}.
+@ifclear USERVISONLY
@item
Warn when explicit type declaration disagrees with
the type of an intrinsic invocation.
+@end ifclear
+@ifclear USERVISONLY
@item
Support @samp{*f771} entry in @code{gcc} @file{specs} file.
+@end ifclear
+@ifclear USERVISONLY
@item
-Fix typo in @code{make} rule @samp{g77-cross}, used only for
+Fix typo in @code{make} rule @code{g77-cross}, used only for
cross-compiling.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{libf2c} build procedure to re-archive library
if previous attempt to archive was interrupted.
+@end ifclear
+@ifclear USERVISONLY
@item
Change @code{gcc} to unroll loops only during the last
invocation (of as many as two invocations) of loop
optimization.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve handling of @samp{-fno-f2c} so that code that
attempts to pass an intrinsic as an actual argument,
such as @samp{CALL FOO(ABS)}, is rejected due to the fact
that the run-time-library routine is, effectively,
compiled with @samp{-ff2c} in effect.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} driver to recognize @samp{-fsyntax-only}
as an option that inhibits linking, just like @samp{-c} or
@samp{-S}, and to recognize and properly handle the
@samp{-nostdlib}, @samp{-M}, @samp{-MM}, @samp{-nodefaultlibs},
and @samp{-Xlinker} options.
+@end ifclear
+@ifclear USERVISONLY
@item
Upgrade to @code{libf2c} as of 1997-08-16.
+@end ifclear
+@ifclear USERVISONLY
@item
Modify @code{libf2c} to consistently and clearly diagnose
recursive I/O (at run time).
+@end ifclear
@item
@code{g77} driver now prints version information (such as produced
@@ -1154,26 +1690,36 @@ The @samp{.r} suffix now designates a Ratfor source file,
to be preprocessed via the @code{ratfor} command, available
separately.
+@ifclear USERVISONLY
@item
Fix some aspects of how @code{gcc} determines what kind of
system is being configured and what kinds are supported.
For example, GNU Linux/Alpha ELF systems now are directly
supported.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve diagnostics.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve documentation and indexing.
+@end ifclear
+@ifclear USERVISONLY
@item
Include all pertinent files for @code{libf2c} that come
from @code{netlib.bell-labs.com}; give any such files
that aren't quite accurate in @code{g77}'s version of
@code{libf2c} the suffix @samp{.netlib}.
+@end ifclear
+@ifclear USERVISONLY
@item
Reserve @code{INTEGER(KIND=0)} for future use.
+@end ifclear
@end itemize
@c 1997-02-28: 0.5.20 released.
@@ -1184,13 +1730,18 @@ The @samp{-fno-typeless-boz} option is now the default.
This option specifies that non-decimal-radix
constants using the prefixed-radix form (such as @samp{Z'1234'})
-are to be interpreted as @code{INTEGER} constants.
+are to be interpreted as @code{INTEGER(KIND=1)} constants.
Specify @samp{-ftypeless-boz} to cause such
constants to be interpreted as typeless.
(Version 0.5.19 introduced @samp{-fno-typeless-boz} and
its inverse.)
+@ifset DOC-G77
+@xref{Fortran Dialect Options,,Options Controlling Fortran Dialect},
+for information on the @samp{-ftypeless-boz} option.
+@end ifset
+
@item
Options @samp{-ff90-intrinsics-enable} and
@samp{-fvxt-intrinsics-enable} now are the
@@ -1206,15 +1757,19 @@ statements specifying that these names are not intended
to be names of intrinsics.
@item
-The @samp{ALWAYS_FLUSH} macro is no longer defined when
+The @code{ALWAYS_FLUSH} macro is no longer defined when
building @code{libf2c}, which should result in improved
I/O performance, especially over NFS.
@emph{Note:} If you have code that depends on the behavior
-of @code{libf2c} when built with @samp{ALWAYS_FLUSH} defined,
+of @code{libf2c} when built with @code{ALWAYS_FLUSH} defined,
you will have to modify @code{libf2c} accordingly before
building it from this and future versions of @code{g77}.
+@ifset DOC-G77
+@xref{Output Assumed To Flush}, for more information.
+@end ifset
+
@item
Dave Love's implementation of @code{libU77} has been
added to the version of @code{libf2c} distributed with
@@ -1226,6 +1781,11 @@ as intrinsics.
New option @samp{-fvxt} specifies that the
source file is written in VXT Fortran, instead of GNU Fortran.
+@ifset DOC-G77
+@xref{VXT Fortran}, for more information on the constructs
+recognized when the @samp{-fvxt} option is specified.
+@end ifset
+
@item
The @samp{-fvxt-not-f90} option has been deleted,
along with its inverse, @samp{-ff90-not-vxt}.
@@ -1235,6 +1795,10 @@ re-read the pertinent documentation to determine which
options, if any, are appropriate for compiling your
code with this version of @code{g77}.
+@ifset DOC-G77
+@xref{Other Dialects}, for more information.
+@end ifset
+
@item
The @samp{-fugly} option now issues a warning, as it
likely will be removed in a future version.
@@ -1250,23 +1814,35 @@ The @samp{-fugly-assumed} option, introduced in
version 0.5.19, has been changed to
better accommodate old and new code.
+@ifset DOC-G77
+@xref{Ugly Assumed-Size Arrays}, for more information.
+@end ifset
+
+@ifclear USERVISONLY
@item
Make a number of fixes to the @code{g77} front end and
the @code{gcc} back end to better support Alpha (AXP)
machines.
This includes providing at least one bug-fix to the
@code{gcc} back end for Alphas.
+@end ifclear
@item
Related to supporting Alpha (AXP) machines, the @code{LOC()}
intrinsic and @code{%LOC()} construct now return
-values of integer type that is the same width (holds
-the same number of bits) as the pointer type on the
-machine.
+values of @code{INTEGER(KIND=0)} type,
+as defined by the GNU Fortran language.
-On most machines, this won't make a difference, whereas
-on Alphas, the type these constructs return is
-@code{INTEGER*8} instead of the more common @code{INTEGER*4}.
+This type is wide enough
+(holds the same number of bits)
+as the character-pointer type on the machine.
+
+On most machines, this won't make a difference,
+whereas, on Alphas and other systems with 64-bit pointers,
+the @code{INTEGER(KIND=0)} type is equivalent to @code{INTEGER(KIND=2)}
+(often referred to as @code{INTEGER*8})
+instead of the more common @code{INTEGER(KIND=1)}
+(often referred to as @code{INTEGER*4}).
@item
Emulate @code{COMPLEX} arithmetic in the @code{g77} front
@@ -1275,19 +1851,24 @@ end, to avoid bugs in @code{complex} support in the
New option @samp{-fno-emulate-complex}
causes @code{g77} to revert the 0.5.19 behavior.
+@ifclear USERVISONLY
@item
Fix bug whereby @samp{REAL A(1)}, for example, caused
a compiler crash if @samp{-fugly-assumed} was in effect
and @var{A} was a local (automatic) array.
That case is no longer affected by the new
handling of @samp{-fugly-assumed}.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix @code{g77} command driver so that @samp{g77 -o foo.f}
no longer deletes @file{foo.f} before issuing other
diagnostics, and so the @samp{-x} option is properly
handled.
+@end ifclear
+@ifclear USERVISONLY
@item
Enable inlining of subroutines and functions by the @code{gcc}
back end.
@@ -1295,6 +1876,7 @@ This works as it does for @code{gcc} itself---program units
may be inlined for invocations that follow them in the same
program unit, as long as the appropriate compile-time
options are specified.
+@end ifclear
@item
Dummy arguments are no longer assumed to potentially alias
@@ -1312,10 +1894,19 @@ New options @samp{-falias-check}, @samp{-fargument-alias},
and @samp{-fno-argument-noalias-global} control the
way @code{g77} handles potential aliasing.
+@ifset DOC-G77
+@xref{Aliasing Assumed To Work}, for detailed information on why the
+new defaults might result in some programs no longer working the way they
+did when compiled by previous versions of @code{g77}.
+@end ifset
+
+@ifclear USERVISONLY
@item
The @code{CONJG()} and @code{DCONJG()} intrinsics now
are compiled in-line.
+@end ifclear
+@ifclear USERVISONLY
@item
The bug-fix for 0.5.19.1 has been re-done.
The @code{g77} compiler has been changed back to
@@ -1340,6 +1931,7 @@ particular, if the linker complains about unresolved
references to names like @samp{g77__fvers__}---that
strongly suggests your installation has an obsolete
version of @code{libf2c}.)
+@end ifclear
@item
New option @samp{-fugly-assign} specifies that the
@@ -1349,17 +1941,26 @@ values assigned by both statements @samp{I = 3} and
(Normally, @code{g77} uses a separate memory location
to hold assigned statement labels.)
+@ifset DOC-G77
+@xref{Ugly Assigned Labels}, for more information.
+@end ifset
+
@item
@code{FORMAT} and @code{ENTRY} statements now are allowed to
precede @code{IMPLICIT NONE} statements.
+@ifclear USERVISONLY
@item
Produce diagnostic for unsupported @code{SELECT CASE} on
@code{CHARACTER} type, instead of crashing, at compile time.
+@end ifclear
+@ifclear USERVISONLY
@item
Fix crashes involving diagnosed or invalid code.
+@end ifclear
+@ifclear USERVISONLY
@item
Change approach to building @code{libf2c} archive
(@file{libf2c.a}) so that members are added to it
@@ -1368,27 +1969,36 @@ an already-built @code{g77} doesn't need to have write
access to the build tree (whereas the user doing the
build might not have access to install new software
on the system).
+@end ifclear
+@ifclear USERVISONLY
@item
Support @code{gcc} version 2.7.2.2
(modified by @code{g77} into version 2.7.2.2.f.2),
and remove
support for prior versions of @code{gcc}.
+@end ifclear
+@ifclear USERVISONLY
@item
Upgrade to @code{libf2c} as of 1997-02-08, and
fix up some of the build procedures.
+@end ifclear
+@ifclear USERVISONLY
@item
Improve general build procedures for @code{g77},
fixing minor bugs (such as deletion of any file
named @file{f771} in the parent directory of @code{gcc/}).
+@end ifclear
@item
-Enable full support of @code{INTEGER*8} available in
+Enable full support of @code{INTEGER(KIND=2)}
+(often referred to as @code{INTEGER*8})
+available in
@code{libf2c} and @file{f2c.h} so that @code{f2c} users
may make full use of its features via the @code{g77}
-version of @file{f2c.h} and the @code{INTEGER*8}
+version of @file{f2c.h} and the @code{INTEGER(KIND=2)}
support routines in the @code{g77} version of @code{libf2c}.
@item
@@ -1407,10 +2017,10 @@ These are @code{REALPART}, @code{IMAGPART},
@code{LONG}, and @code{SHORT}.
@item
-A new group of intrinsics, @samp{gnu}, has been added
+A new group of intrinsics, @code{gnu}, has been added
to contain the new @code{REALPART}, @code{IMAGPART},
and @code{COMPLEX} intrinsics.
-An old group, @samp{dcp}, has been removed.
+An old group, @code{dcp}, has been removed.
@item
Complain about industry-wide ambiguous references
@@ -1421,23 +2031,38 @@ complex type other than @code{COMPLEX}), unless
or new @samp{-fugly-complex} option, in conjunction with
@samp{-fnot-f90}, specifies @code{f2c} interpretation.
+@ifclear USERVISONLY
@item
Make improvements to diagnostics.
+@end ifclear
+@ifclear USERVISONLY
@item
Speed up compiler a bit.
+@end ifclear
+@ifclear USERVISONLY
@item
Improvements to documentation and indexing, including
a new chapter containing information on one, later
more, diagnostics that users are directed to pull
up automatically via a message in the diagnostic itself.
-(Hence the menu item @samp{M} for the node
-@samp{Diagnostics} in the top-level menu of
+(Hence the menu item @code{M} for the node
+@code{Diagnostics} in the top-level menu of
the Info documentation.)
+@end ifclear
@end itemize
+@ifclear DOC-OLDNEWS
+@heading In previous versions:
+
+Information on previous versions is archived
+in @file{@value{path-g77}/news.texi}
+following the test of the @code{DOC-OLDNEWS} macro.
+@end ifclear
+
+@ifset DOC-OLDNEWS
@c 1997-02-01: 0.5.19.1 released.
@heading In 0.5.19.1:
@itemize @bullet
@@ -1449,14 +2074,14 @@ These bugs occurred when assigning the result of an
operation to a complex variable (or array element)
that also served as an input to that operation.
-The operations affected by this bug were: @samp{CONJG()},
-@samp{DCONJG()}, @samp{CCOS()}, @samp{CDCOS()},
-@samp{CLOG()}, @samp{CDLOG()}, @samp{CSIN()}, @samp{CDSIN()},
-@samp{CSQRT()}, @samp{CDSQRT()}, complex division, and
+The operations affected by this bug were: @code{CONJG()},
+@code{DCONJG()}, @code{CCOS()}, @code{CDCOS()},
+@code{CLOG()}, @code{CDLOG()}, @code{CSIN()}, @code{CDSIN()},
+@code{CSQRT()}, @code{CDSQRT()}, complex division, and
raising a @code{DOUBLE COMPLEX} operand to an @code{INTEGER}
power.
(The related generic and @samp{Z}-prefixed intrinsics,
-such as @samp{ZSIN()}, also were affected.)
+such as @code{ZSIN()}, also were affected.)
For example, @samp{C = CSQRT(C)}, @samp{Z = Z/C}, and @samp{Z = Z**I}
(where @samp{C} is @code{COMPLEX} and @samp{Z} is
@@ -1468,7 +2093,7 @@ For example, @samp{C = CSQRT(C)}, @samp{Z = Z/C}, and @samp{Z = Z**I}
@itemize @bullet
@item
Fix @code{FORMAT} statement parsing so negative values for
-specifiers such as @samp{P} (e.g. @samp{FORMAT(-1PF8.1)})
+specifiers such as @code{P} (e.g. @samp{FORMAT(-1PF8.1)})
are correctly processed as negative.
@item
@@ -1552,7 +2177,7 @@ procedures in @code{libf2c}.
@item
Modify @code{fseek_()} in @code{libf2c} to be more portable
(though, in practice, there might be no systems where this
-matters) and to catch invalid @samp{whence} arguments.
+matters) and to catch invalid @code{whence} arguments.
@item
Some useless warnings from the @samp{-Wunused} option have
@@ -1564,7 +2189,7 @@ on AIX systems by linking with the @samp{-bbigtoc} option.
@item
Abort configuration if @code{gcc} has not been patched
-using the patch file provided in the @samp{gcc/f/gbe/}
+using the patch file provided in the @file{gcc/f/gbe/}
subdirectory.
@item
@@ -1776,7 +2401,7 @@ maintainer's new address is @email{dmg@@bell-labs.com}.
@itemize @bullet
@item
@strong{Fix serious bug} in @samp{g77 -v} command that can cause removal of a
-system's @file{/dev/null} special file if run by user @samp{root}.
+system's @file{/dev/null} special file if run by user @code{root}.
@strong{All users} of version 0.5.16 should ensure that
they have not removed @file{/dev/null} or replaced it with an ordinary
@@ -1815,7 +2440,7 @@ never happen).
@item
Make @code{libf2c} build procedures work on more systems again by
-eliminating unnecessary invocations of @samp{ld -r -x} and @samp{mv}.
+eliminating unnecessary invocations of @samp{ld -r -x} and @code{mv}.
@item
Fix omission of @samp{-funix-intrinsics-@dots{}} options in list of permitted
@@ -1894,7 +2519,7 @@ This is known to fix code invoking @code{ERF()}, @code{ERFC()},
@item
Update @code{libf2c} to include netlib patches through 1995-08-16, and
-@code{#define} @samp{WANT_LEAD_0} to 1 to make @code{g77}-compiled code more
+@code{#define} @code{WANT_LEAD_0} to 1 to make @code{g77}-compiled code more
consistent with other Fortran implementations by outputting
leading zeros in formatted and list-directed output.
@@ -1976,12 +2601,12 @@ and @code{SYSTEM}, append a final argument specifying an @code{INTEGER}
variable or array element (e.g. @samp{CALL SYSTEM('rm foo',ISTAT)}).
@item
-Add new intrinsic group named @samp{unix} to contain the new intrinsics,
+Add new intrinsic group named @code{unix} to contain the new intrinsics,
and by default enable this new group.
@item
-Move @code{LOC()} intrinsic out of the @samp{vxt} group to the new
-@samp{unix} group.
+Move @code{LOC()} intrinsic out of the @code{vxt} group to the new
+@code{unix} group.
@item
Improve @code{g77} so that @samp{g77 -v} by itself (or with
@@ -2038,8 +2663,7 @@ macros defined in @file{gcc/f/target.h} and used in places like
Add warning to be printed for each invocation of the compiler
if the target machine @code{INTEGER}, @code{REAL}, or @code{LOGICAL} size
is not 32 bits,
-since @code{g77} is known to not work well for such cases (to be
-fixed in Version 0.6---@pxref{Actual Bugs,,Actual Bugs We Haven't Fixed Yet}).
+since @code{g77} is known to not work well for such cases.
@item
Lots of new documentation (though work is still needed to put it into
@@ -2239,7 +2863,7 @@ Allow @code{RETURN} in main program unit.
Changes to Hollerith-constant support to obey Appendix C of the
standard:
-@itemize --
+@itemize @minus
@item
Now padded on the right with zeros, not spaces.
@@ -2267,7 +2891,7 @@ to widen to @code{INTEGER}), essentially.
@item
Changes and fixes to typeless-constant support:
-@itemize --
+@itemize @minus
@item
Now treated as a typeless double-length @code{INTEGER} value.
@@ -2328,3 +2952,6 @@ Generate better code for some kinds of array references.
Speed up lexing somewhat (this makes the compilation phase noticeably
faster).
@end itemize
+
+@end ifset
+@end ifclear
diff --git a/contrib/gcc/f/news0.texi b/contrib/gcc/f/news0.texi
index 8fb85f4..21176c3 100644
--- a/contrib/gcc/f/news0.texi
+++ b/contrib/gcc/f/news0.texi
@@ -1,14 +1,9 @@
-@setfilename NEW
-@set NEWSONLY
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename NEWS
+@c %**end of header
-@c The immediately following lines apply to the NEWS file
-@c which is generated using this file.
-This file lists recent changes to the GNU Fortran compiler.
-Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-You may copy, distribute, and modify it freely as long as you preserve
-this copyright notice and permission notice.
-
-@node Top,,, (dir)
-@chapter News About GNU Fortran
+@c This tells news.texi that it's generating just the NEWS file.
+@set DOC-NEWS
@include news.texi
@bye
diff --git a/contrib/gcc/f/output.j b/contrib/gcc/f/output.j
index f995fcb..8816b75 100644
--- a/contrib/gcc/f/output.j
+++ b/contrib/gcc/f/output.j
@@ -1,6 +1,6 @@
/* output.j -- Wrapper for GCC's output.h
Copyright (C) 1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -22,7 +22,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef MAKING_DEPENDENCIES
#ifndef _J_f_output
#define _J_f_output
-#include "gansidecl.h"
#include "output.h"
#endif
#endif
diff --git a/contrib/gcc/f/parse.c b/contrib/gcc/f/parse.c
index 6c92de9..1ffd6b3 100644
--- a/contrib/gcc/f/parse.c
+++ b/contrib/gcc/f/parse.c
@@ -1,6 +1,6 @@
/* GNU Fortran
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/proj.c b/contrib/gcc/f/proj.c
index 6af2df5..237ebe0 100644
--- a/contrib/gcc/f/proj.c
+++ b/contrib/gcc/f/proj.c
@@ -1,6 +1,6 @@
/* proj.c file for GNU Fortran
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/proj.h b/contrib/gcc/f/proj.h
index 93b12b3..47fc2f9 100644
--- a/contrib/gcc/f/proj.h
+++ b/contrib/gcc/f/proj.h
@@ -1,6 +1,6 @@
/* proj.h file for Gnu Fortran
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/root.texi b/contrib/gcc/f/root.texi
new file mode 100644
index 0000000..dce97c0
--- /dev/null
+++ b/contrib/gcc/f/root.texi
@@ -0,0 +1,40 @@
+@c DEVELOPMENT is set to indicate an in-development version,
+@c as compared to a release version. When making a release
+@c (e.g. a release branch in the CVS repository for egcs),
+@c clear this and set the version information correctly.
+@clear DEVELOPMENT
+@set version-g77 0.5.25
+@set version-egcs 1.2
+@set version-gcc 2.95
+
+@c GCC-G77 indicates this is the GCC (2.95 or later) version of g77.
+@set GCC-G77
+
+@c EGCS-G77 indicates this is the EGCS (1.0 or 1.1) version of g77.
+@clear EGCS-G77
+
+@c FSF-G77 indicates this is the FSF (0.5.23 or earlier) version of g77.
+@clear FSF-G77
+
+@set email-general gcc@@gcc.gnu.org
+@set email-bugs gcc-bugs@@gcc.gnu.org or bug-gcc@@gnu.org
+@set path-g77 egcs/gcc/f
+@set path-libf2c egcs/libf2c
+
+@ifset GCC-G77
+@set which-g77 GCC-@value{version-gcc}
+@set which-gcc GCC
+@end ifset
+
+@ifset EGCS-G77
+@set which-g77 EGCS-@value{version-egcs}
+@set which-gcc EGCS
+@end ifset
+
+@ifset FSF-G77
+@set which-g77 FSF-@value{version-g77}
+@set which-gcc GCC
+@end ifset
+
+@set email-burley craig@@jcb-sc.com
+@set www-burley http://world.std.com/%7Eburley
diff --git a/contrib/gcc/f/rtl.j b/contrib/gcc/f/rtl.j
index 99923f4..ab78e3a 100644
--- a/contrib/gcc/f/rtl.j
+++ b/contrib/gcc/f/rtl.j
@@ -1,6 +1,6 @@
/* rtl.j -- Wrapper for GCC's rtl.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/src.c b/contrib/gcc/f/src.c
index 3fd1755..7b23931 100644
--- a/contrib/gcc/f/src.c
+++ b/contrib/gcc/f/src.c
@@ -1,6 +1,6 @@
/* src.c -- Implementation File
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/src.h b/contrib/gcc/f/src.h
index 0216a7c..7ba03e0 100644
--- a/contrib/gcc/f/src.h
+++ b/contrib/gcc/f/src.h
@@ -1,6 +1,6 @@
/* src.h -- Public #include File
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/st.c b/contrib/gcc/f/st.c
index 2abd099..8f27f89 100644
--- a/contrib/gcc/f/st.c
+++ b/contrib/gcc/f/st.c
@@ -1,6 +1,6 @@
/* st.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/st.h b/contrib/gcc/f/st.h
index 5036b27..cfcc7be 100644
--- a/contrib/gcc/f/st.h
+++ b/contrib/gcc/f/st.h
@@ -1,6 +1,6 @@
/* st.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/sta.c b/contrib/gcc/f/sta.c
index 58156f5..52cb37b 100644
--- a/contrib/gcc/f/sta.c
+++ b/contrib/gcc/f/sta.c
@@ -1,6 +1,6 @@
/* sta.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -1701,7 +1701,7 @@ ffesta_ffebad_1p (ffebad errnum, ffelexToken names_token, ffeTokenLength index,
}
void
-ffesta_ffebad_1sp (ffebad errnum, char *s, ffelexToken names_token,
+ffesta_ffebad_1sp (ffebad errnum, const char *s, ffelexToken names_token,
ffeTokenLength index, ffelexToken next_token)
{
ffewhereLine line;
@@ -1735,7 +1735,7 @@ ffesta_ffebad_1sp (ffebad errnum, char *s, ffelexToken names_token,
}
void
-ffesta_ffebad_1st (ffebad errnum, char *s, ffelexToken t)
+ffesta_ffebad_1st (ffebad errnum, const char *s, ffelexToken t)
{
if (ffesta_ffebad_start (errnum))
{
@@ -1764,7 +1764,7 @@ ffesta_ffebad_1t (ffebad errnum, ffelexToken t)
}
void
-ffesta_ffebad_2st (ffebad errnum, char *s, ffelexToken t1, ffelexToken t2)
+ffesta_ffebad_2st (ffebad errnum, const char *s, ffelexToken t1, ffelexToken t2)
{
if (ffesta_ffebad_start (errnum))
{
diff --git a/contrib/gcc/f/sta.h b/contrib/gcc/f/sta.h
index 6bb9913..64e1607 100644
--- a/contrib/gcc/f/sta.h
+++ b/contrib/gcc/f/sta.h
@@ -1,6 +1,6 @@
/* sta.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -90,11 +90,11 @@ ffesymbol ffesta_sym_end_transition (ffesymbol s);
ffesymbol ffesta_sym_exec_transition (ffesymbol s);
void ffesta_ffebad_1p (ffebad msg, ffelexToken names_token,
ffeTokenLength index, ffelexToken next_token);
-void ffesta_ffebad_1sp (ffebad msg, char *s, ffelexToken names_token,
+void ffesta_ffebad_1sp (ffebad msg, const char *s, ffelexToken names_token,
ffeTokenLength index, ffelexToken next_token);
-void ffesta_ffebad_1st (ffebad msg, char *s, ffelexToken t);
+void ffesta_ffebad_1st (ffebad msg, const char *s, ffelexToken t);
void ffesta_ffebad_1t (ffebad msg, ffelexToken t);
-void ffesta_ffebad_2st (ffebad msg, char *s, ffelexToken t1, ffelexToken t2);
+void ffesta_ffebad_2st (ffebad msg, const char *s, ffelexToken t1, ffelexToken t2);
void ffesta_ffebad_2t (ffebad msg, ffelexToken t1, ffelexToken t2);
ffelexHandler ffesta_zero (ffelexToken t);
ffelexHandler ffesta_two (ffelexToken first, ffelexToken second);
diff --git a/contrib/gcc/f/stb.c b/contrib/gcc/f/stb.c
index dc4bda4..ef523c4 100644
--- a/contrib/gcc/f/stb.c
+++ b/contrib/gcc/f/stb.c
@@ -1,6 +1,6 @@
/* stb.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -404,7 +404,7 @@ union ffestb_local_u_
dimlist;
struct
{
- char *badname;
+ const char *badname;
ffestrFirst first_kw;
bool is_subr;
}
@@ -421,7 +421,7 @@ union ffestb_local_u_
ffesttTokenList toklist;/* For ambiguity resolution. */
ffesttImpList imps; /* List of IMPLICIT letters. */
ffelexHandler imp_handler; /* Call if paren list wasn't letters. */
- char *badname;
+ const char *badname;
ffestrOther kw; /* INTENT(IN/OUT/INOUT). */
ffestpType type;
bool parameter; /* If PARAMETER attribute seen (governs =expr
@@ -1859,7 +1859,7 @@ ffelexHandler
ffestb_do (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexHandler next;
ffelexToken nt;
ffestrSecond kw;
@@ -2033,7 +2033,7 @@ ffelexHandler
ffestb_dowhile (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexHandler next;
ffelexToken nt;
@@ -2507,7 +2507,7 @@ ffelexHandler
ffestb_else (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -2600,7 +2600,7 @@ ffelexHandler
ffestb_elsexyz (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -2787,7 +2787,7 @@ static ffelexHandler
ffestb_else3_ (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelex_set_names (FALSE);
@@ -3013,7 +3013,7 @@ ffelexHandler
ffestb_endxyz (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -3319,7 +3319,7 @@ ffelexHandler
ffestb_goto (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexHandler next;
ffelexToken nt;
@@ -4152,7 +4152,7 @@ ffestb_let (ffelexToken t)
ffelexHandler next;
bool vxtparam; /* TRUE if it might really be a VXT PARAMETER
stmt. */
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -4292,7 +4292,7 @@ ffelexHandler
ffestb_type (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -4376,7 +4376,7 @@ static ffelexHandler
ffestb_type1_ (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelex_set_names (FALSE);
@@ -4537,7 +4537,7 @@ ffelexHandler
ffestb_varlist (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -5215,7 +5215,7 @@ ffestb_varlist6_ (ffelexToken t)
ffelexHandler
ffestb_R423B (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -5284,7 +5284,7 @@ ffelexHandler
ffestb_R522 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -5528,7 +5528,7 @@ ffestb_R5224_ (ffelexToken t)
ffelexHandler
ffestb_R528 (ffelexToken t)
{
- char *p;
+ unsigned const char *p;
ffeTokenLength i;
ffelexToken nt;
ffelexHandler next;
@@ -5707,7 +5707,12 @@ ffestb_R5282_ (ffelexToken ft, ffebld expr, ffelexToken t)
case FFELEX_typeASTERISK:
if (expr == NULL)
break;
- ffestb_local_.data.expr = expr;
+ ffestb_local_.data.expr = ffeexpr_convert (expr, ft, t,
+ FFEINFO_basictypeINTEGER,
+ FFEINFO_kindtypeINTEGER1,
+ 0,
+ FFETARGET_charactersizeNONE,
+ FFEEXPR_contextLET);
ffesta_tokens[1] = ffelex_token_use (ft);
return (ffelexHandler) ffeexpr_rhs
(ffesta_output_pool, FFEEXPR_contextDATA,
@@ -6005,7 +6010,7 @@ ffestb_R5373_ (ffelexToken t)
ffelexHandler
ffestb_R542 (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -6419,7 +6424,7 @@ ffelexHandler
ffestb_R834 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -6534,7 +6539,7 @@ ffelexHandler
ffestb_R835 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -6648,7 +6653,7 @@ ffestb_R8351_ (ffelexToken t)
ffelexHandler
ffestb_R838 (ffelexToken t)
{
- char *p;
+ unsigned const char *p;
ffeTokenLength i;
ffelexHandler next;
ffelexToken et; /* First token in target. */
@@ -7073,7 +7078,7 @@ ffestb_R8407_ (ffelexToken t)
ffelexHandler
ffestb_R841 (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -7141,7 +7146,7 @@ ffelexHandler
ffestb_R1102 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -7293,7 +7298,7 @@ ffelexHandler
ffestb_blockdata (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -7436,7 +7441,7 @@ ffelexHandler
ffestb_R1212 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexHandler next;
ffelexToken nt;
@@ -7675,7 +7680,7 @@ ffestb_R12271_ (ffelexToken ft, ffebld expr, ffelexToken t)
ffelexHandler
ffestb_R1228 (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -7744,7 +7749,7 @@ bad_i: /* :::::::::::::::::::: */
ffelexHandler
ffestb_V009 (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -8156,7 +8161,7 @@ ffelexHandler
ffestb_module (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexToken nt;
ffelexToken mt; /* Name in MODULE PROCEDUREname, i.e.
includes "PROCEDURE". */
@@ -8429,7 +8434,7 @@ ffelexHandler
ffestb_R809 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -8630,7 +8635,7 @@ ffelexHandler
ffestb_R810 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -9185,7 +9190,7 @@ ffestb_R10014_ (ffelexToken t)
{
ffesttFormatList f;
ffeTokenLength i;
- char *p;
+ const char *p;
ffestrFormat kw;
ffelex_set_expecting_hollerith (0, '\0',
@@ -9709,7 +9714,8 @@ ffestb_R10014_ (ffelexToken t)
i += ffelex_token_length (ffestb_local_.format.post.t);
if (*p == '\0')
return (ffelexHandler) ffestb_R10016_;
- if ((kw != FFESTR_formatP) || !ffelex_is_firstnamechar (*p))
+ if ((kw != FFESTR_formatP) ||
+ !ffelex_is_firstnamechar ((unsigned char)*p))
{
if (ffestb_local_.format.current != FFESTP_formattypeH)
ffesta_ffebad_1p (FFEBAD_FORMAT_TEXT_IN_NUMBER, t, i, NULL);
@@ -9813,7 +9819,7 @@ ffestb_R10015_ (ffelexToken t)
bool split_pea; /* New NAMES requires splitting kP from new
edit desc. */
ffestrFormat kw;
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (t))
@@ -10190,7 +10196,7 @@ static ffelexHandler
ffestb_R10018_ (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
switch (ffelex_token_type (t))
{
@@ -10984,7 +10990,7 @@ ffelexHandler
ffestb_R1107 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -11430,7 +11436,7 @@ ffelexHandler
ffestb_R1202 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -11821,7 +11827,7 @@ ffestb_R12025_ (ffelexToken t)
static ffelexHandler
ffestb_R12026_ (ffelexToken t)
{
- char *p;
+ const char *p;
switch (ffelex_token_type (t))
{
@@ -11964,7 +11970,7 @@ ffelexHandler
ffestb_S3P4 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexHandler next;
ffelexToken nt;
ffelexToken ut;
@@ -12096,7 +12102,7 @@ ffestb_S3P41_ (ffelexToken ft, ffebld expr, ffelexToken t)
ffelexHandler
ffestb_V012 (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -12165,7 +12171,7 @@ ffelexHandler
ffestb_V014 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -12399,7 +12405,7 @@ ffelexHandler
ffestb_V025 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -12595,7 +12601,7 @@ ffestb_V0254_ (ffelexToken ft, ffebld expr, ffelexToken t)
static ffelexHandler
ffestb_V0255_ (ffelexToken t)
{
- char *p;
+ const char *p;
switch (ffelex_token_type (t))
{
@@ -17909,7 +17915,7 @@ ffelexHandler
ffestb_V020 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexHandler next;
ffestpTypeIx ix;
@@ -18845,7 +18851,7 @@ ffelexHandler
ffestb_dimlist (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -19399,7 +19405,7 @@ ffelexHandler
ffestb_dummy (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
switch (ffelex_token_type (ffesta_tokens[0]))
{
@@ -19618,7 +19624,7 @@ ffelexHandler
ffestb_R524 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -19847,7 +19853,7 @@ ffelexHandler
ffestb_R547 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -20485,7 +20491,7 @@ ffelexHandler
ffestb_decl_chartype (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffestb_local_.decl.type = FFESTP_typeCHARACTER;
ffestb_local_.decl.recursive = NULL;
@@ -20672,7 +20678,7 @@ ffelexHandler
ffestb_decl_dbltype (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffestb_local_.decl.type = ffestb_args.decl.type;
ffestb_local_.decl.recursive = NULL;
@@ -20863,7 +20869,7 @@ ffelexHandler
ffestb_decl_gentype (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffestb_local_.decl.type = ffestb_args.decl.type;
ffestb_local_.decl.recursive = NULL;
@@ -21009,7 +21015,7 @@ ffelexHandler
ffestb_decl_recursive (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexToken nt;
ffelexToken ot;
ffelexHandler next;
@@ -22667,7 +22673,7 @@ ffestb_decl_entsp_2_ (ffelexToken t)
{
ffelexToken nt;
bool asterisk_ok;
- char *p;
+ unsigned const char *p;
ffeTokenLength i;
switch (ffelex_token_type (t))
@@ -23094,7 +23100,7 @@ ffestb_decl_entsp_8_ (ffelexToken t)
static ffelexHandler
ffestb_decl_func_ (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
ffelex_set_names (FALSE);
@@ -23572,7 +23578,7 @@ ffelexHandler
ffestb_V003 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ const char *p;
ffelexToken nt;
ffelexHandler next;
@@ -23888,7 +23894,7 @@ bad: /* :::::::::::::::::::: */
ffelexHandler
ffestb_V016 (ffelexToken t)
{
- char *p;
+ const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -24156,7 +24162,7 @@ ffestb_V0166_ (ffelexToken t)
ffelexHandler
ffestb_V027 (ffelexToken t)
{
- char *p;
+ unsigned const char *p;
ffeTokenLength i;
switch (ffelex_token_type (ffesta_tokens[0]))
@@ -24336,7 +24342,7 @@ ffelexHandler
ffestb_decl_R539 (ffelexToken t)
{
ffeTokenLength i;
- char *p;
+ unsigned const char *p;
ffelexToken nt;
ffestrSecond kw;
diff --git a/contrib/gcc/f/stb.h b/contrib/gcc/f/stb.h
index 7338bcf..6ee761d 100644
--- a/contrib/gcc/f/stb.h
+++ b/contrib/gcc/f/stb.h
@@ -1,6 +1,6 @@
/* stb.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -50,7 +50,7 @@ struct _ffestb_args_
{
struct
{
- char *badname;
+ const char *badname;
ffeTokenLength len; /* Length of "ENTRY/FUNCTION/SUBROUTINE". */
bool is_subr; /* TRUE if SUBROUTINE or if ENTRY within
SUBROUTINE. */
@@ -58,7 +58,7 @@ struct _ffestb_args_
dummy;
struct
{
- char *badname;
+ const char *badname;
ffeTokenLength len; /* Length of
"BACKSPACE/ENDFILE/REWIND/UNLOCK". */
}
@@ -82,7 +82,7 @@ struct _ffestb_args_
#if FFESTR_F90
struct
{
- char *badname;
+ const char *badname;
ffeTokenLength len; /* Length of "ALLOCATE/DEALLOCATE". */
ffeexprContext ctx; /* Either ALLOCATE or DEALLOCATE. */
}
@@ -90,7 +90,7 @@ struct _ffestb_args_
#endif
struct
{
- char *badname;
+ const char *badname;
ffeTokenLength len; /* Length of
"EXTERNAL/INTENT/INTRINSIC/OPTIONAL/PUBLIC/
PRIVATE". */
@@ -99,7 +99,7 @@ struct _ffestb_args_
#if FFESTR_VXT
struct
{
- char *badname;
+ const char *badname;
ffeTokenLength len; /* Length of "ENCODE/DECODE". */
}
vxtcode;
@@ -107,14 +107,14 @@ struct _ffestb_args_
#if FFESTR_F90
struct
{
- char *badname;
+ const char *badname;
ffeTokenLength len; /* Length of "ALLOCATABLE/POINTER/TARGET". */
}
dimlist;
#endif
struct
{
- char *badname;
+ const char *badname;
ffeTokenLength len; /* Length of "DIMENSION/VIRTUAL". */
}
R524;
diff --git a/contrib/gcc/f/stc.c b/contrib/gcc/f/stc.c
index e720f9d..b89b747 100644
--- a/contrib/gcc/f/stc.c
+++ b/contrib/gcc/f/stc.c
@@ -1,6 +1,6 @@
/* stc.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -339,14 +339,14 @@ static void ffestc_shriek_where_ (bool ok);
#if FFESTR_F90
static void ffestc_shriek_wherethen_ (bool ok);
#endif
-static int ffestc_subr_binsrch_ (char **list, int size, ffestpFile *spec,
- char *whine);
+static int ffestc_subr_binsrch_ (const char **list, int size, ffestpFile *spec,
+ const char *whine);
static ffestvFormat ffestc_subr_format_ (ffestpFile *spec);
static bool ffestc_subr_is_branch_ (ffestpFile *spec);
static bool ffestc_subr_is_format_ (ffestpFile *spec);
-static bool ffestc_subr_is_present_ (char *name, ffestpFile *spec);
-static int ffestc_subr_speccmp_ (char *string, ffestpFile *spec,
- char **target, int *length);
+static bool ffestc_subr_is_present_ (const char *name, ffestpFile *spec);
+static int ffestc_subr_speccmp_ (const char *string, ffestpFile *spec,
+ const char **target, int *length);
static ffestvUnit ffestc_subr_unit_ (ffestpFile *spec);
static void ffestc_try_shriek_do_ (void);
@@ -5044,14 +5044,14 @@ ffestc_shriek_wherethen_ (bool ok)
using "etc" as the pick-one-of-these string. */
static int
-ffestc_subr_binsrch_ (char **list, int size, ffestpFile *spec, char *whine)
+ffestc_subr_binsrch_ (const char **list, int size, ffestpFile *spec, const char *whine)
{
int lowest_tested;
int highest_tested;
int halfway;
int offset;
int c;
- char *str;
+ const char *str;
int len;
if (size == 0)
@@ -5186,7 +5186,7 @@ ffestc_subr_is_format_ (ffestpFile *spec)
ffestc_subr_is_present_("SPECIFIER",&specifier); */
static bool
-ffestc_subr_is_present_ (char *name, ffestpFile *spec)
+ffestc_subr_is_present_ (const char *name, ffestpFile *spec)
{
if (spec->kw_or_val_present)
{
@@ -5219,7 +5219,7 @@ ffestc_subr_is_present_ (char *name, ffestpFile *spec)
0 if 2 is returned, the length of the constant string value otherwise. */
static int
-ffestc_subr_speccmp_ (char *string, ffestpFile *spec, char **target,
+ffestc_subr_speccmp_ (const char *string, ffestpFile *spec, const char **target,
int *length)
{
ffebldConstant c;
@@ -10000,6 +10000,10 @@ ffestc_R838 (ffelexToken label_token, ffebld target,
return;
ffestc_labeldef_branch_begin_ ();
+ /* Mark target symbol as target of an ASSIGN. */
+ if (ffebld_op (target) == FFEBLD_opSYMTER)
+ ffesymbol_set_assigned (ffebld_symter (target), TRUE);
+
if (ffestc_labelref_is_assignable_ (label_token, &label))
ffestd_R838 (label, target);
@@ -10198,7 +10202,7 @@ ffestc_R904 ()
{
int i;
int expect_file;
- char *status_strs[]
+ const char *status_strs[]
=
{
"New",
@@ -10207,7 +10211,7 @@ ffestc_R904 ()
"Scratch",
"Unknown"
};
- char *access_strs[]
+ const char *access_strs[]
=
{
"Append",
@@ -10215,20 +10219,20 @@ ffestc_R904 ()
"Keyed",
"Sequential"
};
- char *blank_strs[]
+ const char *blank_strs[]
=
{
"Null",
"Zero"
};
- char *carriagecontrol_strs[]
+ const char *carriagecontrol_strs[]
=
{
"Fortran",
"List",
"None"
};
- char *dispose_strs[]
+ const char *dispose_strs[]
=
{
"Delete",
@@ -10239,41 +10243,41 @@ ffestc_R904 ()
"Submit",
"Submit/Delete"
};
- char *form_strs[]
+ const char *form_strs[]
=
{
"Formatted",
"Unformatted"
};
- char *organization_strs[]
+ const char *organization_strs[]
=
{
"Indexed",
"Relative",
"Sequential"
};
- char *position_strs[]
+ const char *position_strs[]
=
{
"Append",
"AsIs",
"Rewind"
};
- char *action_strs[]
+ const char *action_strs[]
=
{
"Read",
"ReadWrite",
"Write"
};
- char *delim_strs[]
+ const char *delim_strs[]
=
{
"Apostrophe",
"None",
"Quote"
};
- char *recordtype_strs[]
+ const char *recordtype_strs[]
=
{
"Fixed",
@@ -10283,7 +10287,7 @@ ffestc_R904 ()
"Stream_LF",
"Variable"
};
- char *pad_strs[]
+ const char *pad_strs[]
=
{
"No",
@@ -10453,7 +10457,7 @@ ffestc_R904 ()
void
ffestc_R907 ()
{
- char *status_strs[]
+ const char *status_strs[]
=
{
"Delete",
diff --git a/contrib/gcc/f/stc.h b/contrib/gcc/f/stc.h
index c26fca1..12b4783 100644
--- a/contrib/gcc/f/stc.h
+++ b/contrib/gcc/f/stc.h
@@ -1,6 +1,6 @@
/* stc.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/std.c b/contrib/gcc/f/std.c
index 540da6c..72037c1 100644
--- a/contrib/gcc/f/std.c
+++ b/contrib/gcc/f/std.c
@@ -1,6 +1,6 @@
/* std.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -192,17 +192,29 @@ struct _ffestd_stmt_
struct
{
mallocPool pool;
+ ffestw block;
ffebld expr;
}
R803;
struct
{
mallocPool pool;
+ ffestw block;
ffebld expr;
}
R804;
struct
{
+ ffestw block;
+ }
+ R805;
+ struct
+ {
+ ffestw block;
+ }
+ R806;
+ struct
+ {
mallocPool pool;
ffebld expr;
}
@@ -526,25 +538,25 @@ static void ffestd_subr_f90_ (void);
static void ffestd_subr_labels_ (bool unexpected);
static void ffestd_R1001dump_ (ffests s, ffesttFormatList list);
static void ffestd_R1001dump_1005_1_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1005_2_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1005_3_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1005_4_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1005_5_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1010_1_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1010_2_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1010_3_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1010_4_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001dump_1010_5_ (ffests s, ffesttFormatList f,
- char *string);
+ const char *string);
static void ffestd_R1001error_ (ffesttFormatList f);
static void ffestd_R1001rtexpr_ (ffests s, ffesttFormatList f, ffebld expr);
@@ -750,27 +762,28 @@ ffestd_stmt_pass_ ()
case FFESTD_stmtidR803_:
ffestd_subr_line_restore_ (stmt);
if (okay)
- ffeste_R803 (stmt->u.R803.expr);
+ ffeste_R803 (stmt->u.R803.block, stmt->u.R803.expr);
malloc_pool_kill (stmt->u.R803.pool);
break;
case FFESTD_stmtidR804_:
ffestd_subr_line_restore_ (stmt);
if (okay)
- ffeste_R804 (stmt->u.R804.expr);
+ ffeste_R804 (stmt->u.R803.block, stmt->u.R804.expr);
malloc_pool_kill (stmt->u.R804.pool);
break;
case FFESTD_stmtidR805_:
ffestd_subr_line_restore_ (stmt);
if (okay)
- ffeste_R805 ();
+ ffeste_R805 (stmt->u.R803.block);
break;
case FFESTD_stmtidR806_:
ffestd_subr_line_restore_ (stmt);
if (okay)
- ffeste_R806 ();
+ ffeste_R806 (stmt->u.R806.block);
+ ffestw_kill (stmt->u.R806.block);
break;
case FFESTD_stmtidR807_:
@@ -1597,7 +1610,19 @@ ffestd_labeldef_format (ffelab label)
ffestdStmt_ stmt;
stmt = ffestd_stmt_new_ (FFESTD_stmtidFORMATLABEL_);
+#if 0
+ /* Don't bother with this. See FORMAT statement. */
+ /* Prepend FORMAT label instead of appending it, so all the
+ FORMAT label/statement pairs end up at the top of the list.
+ This helps ensure all decls for a block (in the GBE) are
+ known before any executable statements are generated. */
+ stmt->previous = (ffestdStmt_) &ffestd_stmt_list_.first;
+ stmt->next = ffestd_stmt_list_.first;
+ stmt->next->previous = stmt;
+ stmt->previous->next = stmt;
+#else
ffestd_stmt_append_ (stmt);
+#endif
stmt->u.formatlabel.label = label;
}
#endif
@@ -2989,13 +3014,7 @@ ffestd_R744 ()
#endif
}
-/* ffestd_R745 -- Implicit END WHERE statement
-
- ffestd_R745(TRUE);
-
- Implement the end of the current WHERE "block". ok==TRUE iff statement
- following WHERE (substatement) is valid; else, statement is invalid
- or stack forcibly popped due to ffestd_eof_(). */
+/* ffestd_R745 -- Implicit END WHERE statement. */
void
ffestd_R745 (bool ok)
@@ -3011,11 +3030,8 @@ ffestd_R745 (bool ok)
}
#endif
-/* ffestd_R803 -- Block IF (IF-THEN) statement
-
- ffestd_R803(construct_name,expr,expr_token);
- Make sure statement is valid here; implement. */
+/* Block IF (IF-THEN) statement. */
void
ffestd_R803 (ffelexToken construct_name UNUSED, ffebld expr)
@@ -3033,6 +3049,7 @@ ffestd_R803 (ffelexToken construct_name UNUSED, ffebld expr)
ffestd_stmt_append_ (stmt);
ffestd_subr_line_save_ (stmt);
stmt->u.R803.pool = ffesta_output_pool;
+ stmt->u.R803.block = ffestw_use (ffestw_stack_top ());
stmt->u.R803.expr = expr;
ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE);
}
@@ -3042,13 +3059,7 @@ ffestd_R803 (ffelexToken construct_name UNUSED, ffebld expr)
assert (ffestd_block_level_ > 0);
}
-/* ffestd_R804 -- ELSE IF statement
-
- ffestd_R804(expr,expr_token,name_token);
-
- Make sure ffestd_kind_ identifies an IF block. If not
- NULL, make sure name_token gives the correct name. Implement the else
- of the IF block. */
+/* ELSE IF statement. */
void
ffestd_R804 (ffebld expr, ffelexToken name UNUSED)
@@ -3066,19 +3077,14 @@ ffestd_R804 (ffebld expr, ffelexToken name UNUSED)
ffestd_stmt_append_ (stmt);
ffestd_subr_line_save_ (stmt);
stmt->u.R804.pool = ffesta_output_pool;
+ stmt->u.R804.block = ffestw_use (ffestw_stack_top ());
stmt->u.R804.expr = expr;
ffesta_set_outpooldisp (FFESTA_pooldispPRESERVE);
}
#endif
}
-/* ffestd_R805 -- ELSE statement
-
- ffestd_R805(name_token);
-
- Make sure ffestd_kind_ identifies an IF block. If not
- NULL, make sure name_token gives the correct name. Implement the ELSE
- of the IF block. */
+/* ELSE statement. */
void
ffestd_R805 (ffelexToken name UNUSED)
@@ -3095,13 +3101,12 @@ ffestd_R805 (ffelexToken name UNUSED)
stmt = ffestd_stmt_new_ (FFESTD_stmtidR805_);
ffestd_stmt_append_ (stmt);
ffestd_subr_line_save_ (stmt);
+ stmt->u.R805.block = ffestw_use (ffestw_stack_top ());
}
#endif
}
-/* ffestd_R806 -- End an IF-THEN
-
- ffestd_R806(TRUE); */
+/* END IF statement. */
void
ffestd_R806 (bool ok UNUSED)
@@ -3116,6 +3121,7 @@ ffestd_R806 (bool ok UNUSED)
stmt = ffestd_stmt_new_ (FFESTD_stmtidR806_);
ffestd_stmt_append_ (stmt);
ffestd_subr_line_save_ (stmt);
+ stmt->u.R806.block = ffestw_use (ffestw_stack_top ());
}
#endif
@@ -4273,7 +4279,24 @@ ffestd_R1001 (ffesttFormatList f)
ffestdStmt_ stmt;
stmt = ffestd_stmt_new_ (FFESTD_stmtidR1001_);
+#if 0
+ /* Don't bother with this. After all, things like cilists also are
+ declared midway through code-generation. Perhaps the only problems
+ the gcc back end has with midway declarations are with stack vars,
+ maybe only with vars that can be put in registers. Unless/until the
+ need is established, handle FORMAT just like cilists and others; at
+ that point, they'd likely *all* have to be fixed, which would be
+ very painful anyway. */
+ /* Insert FORMAT statement just after the first item on the
+ statement list, which must be a FORMAT label, which see. */
+ assert (ffestd_stmt_list_.first->id == FFESTD_stmtidFORMATLABEL_);
+ stmt->previous = ffestd_stmt_list_.first;
+ stmt->next = ffestd_stmt_list_.first->next;
+ stmt->next->previous = stmt;
+ stmt->previous->next = stmt;
+#else
ffestd_stmt_append_ (stmt);
+#endif
stmt->u.R1001.str = str;
}
#endif
@@ -4487,7 +4510,7 @@ ffestd_R1001dump_ (ffests s, ffesttFormatList list)
The format is dumped with form [r]X[w]. */
static void
-ffestd_R1001dump_1005_1_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1005_1_ (ffests s, ffesttFormatList f, const char *string)
{
assert (!f->u.R1005.R1007_or_R1008.present);
assert (!f->u.R1005.R1009.present);
@@ -4519,7 +4542,7 @@ ffestd_R1001dump_1005_1_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form [r]Xw. */
static void
-ffestd_R1001dump_1005_2_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1005_2_ (ffests s, ffesttFormatList f, const char *string)
{
assert (!f->u.R1005.R1007_or_R1008.present);
assert (!f->u.R1005.R1009.present);
@@ -4549,7 +4572,7 @@ ffestd_R1001dump_1005_2_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form [r]Xw[.m]. */
static void
-ffestd_R1001dump_1005_3_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1005_3_ (ffests s, ffesttFormatList f, const char *string)
{
assert (!f->u.R1005.R1009.present);
assert (f->u.R1005.R1006.present);
@@ -4588,7 +4611,7 @@ ffestd_R1001dump_1005_3_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form [r]Xw.d. */
static void
-ffestd_R1001dump_1005_4_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1005_4_ (ffests s, ffesttFormatList f, const char *string)
{
assert (!f->u.R1005.R1009.present);
assert (f->u.R1005.R1007_or_R1008.present);
@@ -4624,7 +4647,7 @@ ffestd_R1001dump_1005_4_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form [r]Xw.d[Ee]. */
static void
-ffestd_R1001dump_1005_5_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1005_5_ (ffests s, ffesttFormatList f, const char *string)
{
assert (f->u.R1005.R1007_or_R1008.present);
assert (f->u.R1005.R1006.present);
@@ -4668,7 +4691,7 @@ ffestd_R1001dump_1005_5_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form X. */
static void
-ffestd_R1001dump_1010_1_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1010_1_ (ffests s, ffesttFormatList f, const char *string)
{
assert (!f->u.R1010.val.present);
@@ -4683,7 +4706,7 @@ ffestd_R1001dump_1010_1_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form [r]X. */
static void
-ffestd_R1001dump_1010_2_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1010_2_ (ffests s, ffesttFormatList f, const char *string)
{
if (f->u.R1010.val.present)
{
@@ -4704,7 +4727,7 @@ ffestd_R1001dump_1010_2_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form nX. */
static void
-ffestd_R1001dump_1010_3_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1010_3_ (ffests s, ffesttFormatList f, const char *string)
{
assert (f->u.R1010.val.present);
@@ -4724,7 +4747,7 @@ ffestd_R1001dump_1010_3_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form kX. Note that k is signed. */
static void
-ffestd_R1001dump_1010_4_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1010_4_ (ffests s, ffesttFormatList f, const char *string)
{
assert (f->u.R1010.val.present);
@@ -4744,7 +4767,7 @@ ffestd_R1001dump_1010_4_ (ffests s, ffesttFormatList f, char *string)
The format is dumped with form Xn. */
static void
-ffestd_R1001dump_1010_5_ (ffests s, ffesttFormatList f, char *string)
+ffestd_R1001dump_1010_5_ (ffests s, ffesttFormatList f, const char *string)
{
assert (f->u.R1010.val.present);
diff --git a/contrib/gcc/f/std.h b/contrib/gcc/f/std.h
index 810f427..bfad671 100644
--- a/contrib/gcc/f/std.h
+++ b/contrib/gcc/f/std.h
@@ -1,6 +1,6 @@
/* std.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/ste.c b/contrib/gcc/f/ste.c
index 4a2476d..dbe48dd 100644
--- a/contrib/gcc/f/ste.c
+++ b/contrib/gcc/f/ste.c
@@ -1,6 +1,6 @@
/* ste.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -28,21 +28,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Modifications:
*/
-/* As of 0.5.4, any statement that calls on ffecom to transform an
- expression might need to be wrapped in ffecom_push_calltemps ()
- and ffecom_pop_calltemps () as are some other cases. That is
- the case when the transformation might involve generation of
- a temporary that must be auto-popped, the specific case being
- when a COMPLEX operation requiring a call to libf2c being
- generated, whereby a temp is needed to hold the result since
- libf2c doesn't return COMPLEX results directly. Cases where it
- is known that ffecom_expr () won't need to do this, such as
- the CALL statement (where it's the transformation of the
- call expr itself that does the wrapping), don't need to bother
- with this wrapping. Forgetting to do the wrapping currently
- means a crash at an assertion when the wrapping would be helpful
- to keep temporaries from being wasted -- see ffecom_push_tempvar. */
-
/* Include files. */
#include "proj.h"
@@ -113,9 +98,11 @@ static void ffeste_begin_iterdo_ (ffestw block, tree *tvar, tree *tincr,
ffebld start, ffelexToken start_token,
ffebld end, ffelexToken end_token,
ffebld incr, ffelexToken incr_token,
- char *msg);
-static void ffeste_end_iterdo_ (tree tvar, tree tincr, tree itersvar);
+ const char *msg);
+static void ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr,
+ tree itersvar);
static void ffeste_io_call_ (tree call, bool do_check);
+static void ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token);
static tree ffeste_io_dofio_ (ffebld expr);
static tree ffeste_io_dolio_ (ffebld expr);
static tree ffeste_io_douio_ (ffebld expr);
@@ -131,7 +118,23 @@ static tree ffeste_io_cllist_ (bool have_err, ffebld unit_expr,
static tree ffeste_io_icilist_ (bool have_err, ffebld unit_expr,
bool have_end, ffestvFormat format,
ffestpFile *format_spec);
-static void ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token);
+static tree ffeste_io_inlist_ (bool have_err,
+ ffestpFile *unit_spec,
+ ffestpFile *file_spec,
+ ffestpFile *exist_spec,
+ ffestpFile *open_spec,
+ ffestpFile *number_spec,
+ ffestpFile *named_spec,
+ ffestpFile *name_spec,
+ ffestpFile *access_spec,
+ ffestpFile *sequential_spec,
+ ffestpFile *direct_spec,
+ ffestpFile *form_spec,
+ ffestpFile *formatted_spec,
+ ffestpFile *unformatted_spec,
+ ffestpFile *recl_spec,
+ ffestpFile *nextrec_spec,
+ ffestpFile *blank_spec);
static tree ffeste_io_olist_ (bool have_err, ffebld unit_expr,
ffestpFile *file_spec,
ffestpFile *stat_spec,
@@ -141,7 +144,7 @@ static tree ffeste_io_olist_ (bool have_err, ffebld unit_expr,
ffestpFile *blank_spec);
static void ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt);
#elif FFECOM_targetCURRENT == FFECOM_targetFFE
-static void ffeste_subr_file_ (char *kw, ffestpFile *spec);
+static void ffeste_subr_file_ (const char *kw, ffestpFile *spec);
#else
#error
#endif
@@ -177,118 +180,325 @@ static void ffeste_subr_file_ (char *kw, ffestpFile *spec);
|| ffeste_statelet_ == FFESTE_stateletITEM_); \
ffeste_statelet_ = FFESTE_stateletSIMPLE_
-#define ffeste_f2c_charnolenspec_(Spec,Exp,Init) \
+#define ffeste_f2c_init_charnolen_(Exp,Init,Spec) \
do \
{ \
- if (Spec->kw_or_val_present) \
- Exp = ffecom_arg_ptr_to_expr(Spec->u.expr,&ignore); \
+ if ((Spec)->kw_or_val_present) \
+ Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &ignore); \
else \
Exp = null_pointer_node; \
- if (TREE_CONSTANT(Exp)) \
- { \
+ if (Exp) \
Init = Exp; \
- Exp = NULL_TREE; \
- } \
else \
{ \
- Init = null_pointer_node; \
- constantp = FALSE; \
+ Init = null_pointer_node; \
+ constantp = FALSE; \
} \
} while(0)
-#define ffeste_f2c_charspec_(Spec,Exp,Init,Lenexp,Leninit) \
+#define ffeste_f2c_init_char_(Exp,Init,Lenexp,Leninit,Spec) \
do \
{ \
- if (Spec->kw_or_val_present) \
- Exp = ffecom_arg_ptr_to_expr(Spec->u.expr,&Lenexp); \
+ if ((Spec)->kw_or_val_present) \
+ Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &Lenexp); \
else \
{ \
- Exp = null_pointer_node; \
- Lenexp = ffecom_f2c_ftnlen_zero_node; \
+ Exp = null_pointer_node; \
+ Lenexp = ffecom_f2c_ftnlen_zero_node; \
} \
- if (TREE_CONSTANT(Exp)) \
- { \
+ if (Exp) \
Init = Exp; \
- Exp = NULL_TREE; \
+ else \
+ { \
+ Init = null_pointer_node; \
+ constantp = FALSE; \
} \
+ if (Lenexp) \
+ Leninit = Lenexp; \
else \
{ \
- Init = null_pointer_node; \
- constantp = FALSE; \
+ Leninit = ffecom_f2c_ftnlen_zero_node; \
+ constantp = FALSE; \
} \
- if ((Lenexp != NULL_TREE) && TREE_CONSTANT(Lenexp)) \
+ } while(0)
+
+#define ffeste_f2c_init_flag_(Flag,Init) \
+ do \
+ { \
+ Init = convert (ffecom_f2c_flag_type_node, \
+ (Flag) ? integer_one_node : integer_zero_node); \
+ } while(0)
+
+#define ffeste_f2c_init_format_(Exp,Init,Spec) \
+ do \
+ { \
+ Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, NULL); \
+ if (Exp) \
+ Init = Exp; \
+ else \
{ \
- Leninit = Lenexp; \
- Lenexp = NULL_TREE; \
+ Init = null_pointer_node; \
+ constantp = FALSE; \
} \
+ } while(0)
+
+#define ffeste_f2c_init_int_(Exp,Init,Spec) \
+ do \
+ { \
+ if ((Spec)->kw_or_val_present) \
+ Exp = ffecom_const_expr ((Spec)->u.expr); \
+ else \
+ Exp = ffecom_integer_zero_node; \
+ if (Exp) \
+ Init = Exp; \
else \
{ \
- Leninit = ffecom_f2c_ftnlen_zero_node; \
- constantp = FALSE; \
+ Init = ffecom_integer_zero_node; \
+ constantp = FALSE; \
} \
} while(0)
-#define ffeste_f2c_exp_(Field,Exp) \
+#define ffeste_f2c_init_ptrtoint_(Exp,Init,Spec) \
do \
{ \
- if (Exp != NULL_TREE) \
+ if ((Spec)->kw_or_val_present) \
+ Exp = ffecom_ptr_to_const_expr ((Spec)->u.expr); \
+ else \
+ Exp = null_pointer_node; \
+ if (Exp) \
+ Init = Exp; \
+ else \
{ \
- Exp = ffecom_modify(void_type_node,ffecom_2(COMPONENT_REF, \
- TREE_TYPE(Field),t,Field),Exp); \
- expand_expr_stmt(Exp); \
+ Init = null_pointer_node; \
+ constantp = FALSE; \
} \
} while(0)
-#define ffeste_f2c_init_(Init) \
+#define ffeste_f2c_init_next_(Init) \
do \
{ \
- TREE_CHAIN(initn) = build_tree_list((field = TREE_CHAIN(field)),Init); \
- initn = TREE_CHAIN(initn); \
+ TREE_CHAIN (initn) = build_tree_list ((field = TREE_CHAIN (field)), \
+ (Init)); \
+ initn = TREE_CHAIN(initn); \
} while(0)
-#define ffeste_f2c_flagspec_(Flag,Init) \
- do { Init = convert (ffecom_f2c_flag_type_node, \
- Flag ? integer_one_node : integer_zero_node); } \
- while(0)
+#define ffeste_f2c_prepare_charnolen_(Spec,Exp) \
+ do \
+ { \
+ if (! (Exp)) \
+ ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
+ } while(0)
-#define ffeste_f2c_intspec_(Spec,Exp,Init) \
+#define ffeste_f2c_prepare_char_(Spec,Exp) \
do \
{ \
- if (Spec->kw_or_val_present) \
- Exp = ffecom_expr(Spec->u.expr); \
- else \
- Exp = ffecom_integer_zero_node; \
- if (TREE_CONSTANT(Exp)) \
+ if (! (Exp)) \
+ ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
+ } while(0)
+
+#define ffeste_f2c_prepare_format_(Spec,Exp) \
+ do \
+ { \
+ if (! (Exp)) \
+ ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr); \
+ } while(0)
+
+#define ffeste_f2c_prepare_int_(Spec,Exp) \
+ do \
+ { \
+ if (! (Exp)) \
+ ffecom_prepare_expr ((Spec)->u.expr); \
+ } while(0)
+
+#define ffeste_f2c_prepare_ptrtoint_(Spec,Exp) \
+ do \
+ { \
+ if (! (Exp)) \
+ ffecom_prepare_ptr_to_expr ((Spec)->u.expr); \
+ } while(0)
+
+#define ffeste_f2c_compile_(Field,Exp) \
+ do \
+ { \
+ tree exz; \
+ if ((Exp)) \
{ \
- Init = Exp; \
- Exp = NULL_TREE; \
+ exz = ffecom_modify (void_type_node, \
+ ffecom_2 (COMPONENT_REF, TREE_TYPE (Field), \
+ t, (Field)), \
+ (Exp)); \
+ expand_expr_stmt (exz); \
} \
- else \
+ } while(0)
+
+#define ffeste_f2c_compile_charnolen_(Field,Spec,Exp) \
+ do \
+ { \
+ tree exq; \
+ if (! (Exp)) \
{ \
- Init = ffecom_integer_zero_node; \
- constantp = FALSE; \
+ exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &ignore); \
+ ffeste_f2c_compile_ ((Field), exq); \
} \
} while(0)
-#define ffeste_f2c_ptrtointspec_(Spec,Exp,Init) \
+#define ffeste_f2c_compile_char_(Field,Lenfield,Spec,Exp,Lenexp) \
do \
{ \
- if (Spec->kw_or_val_present) \
- Exp = ffecom_ptr_to_expr(Spec->u.expr); \
- else \
- Exp = null_pointer_node; \
- if (TREE_CONSTANT(Exp)) \
+ tree exq = (Exp); \
+ tree lenexq = (Lenexp); \
+ int need_exq = (! exq); \
+ int need_lenexq = (! lenexq); \
+ if (need_exq || need_lenexq) \
{ \
- Init = Exp; \
- Exp = NULL_TREE; \
+ exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &lenexq); \
+ if (need_exq) \
+ ffeste_f2c_compile_ ((Field), exq); \
+ if (need_lenexq) \
+ ffeste_f2c_compile_ ((Lenfield), lenexq); \
} \
- else \
+ } while(0)
+
+#define ffeste_f2c_compile_format_(Field,Spec,Exp) \
+ do \
+ { \
+ tree exq; \
+ if (! (Exp)) \
{ \
- Init = null_pointer_node; \
- constantp = FALSE; \
+ exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, NULL); \
+ ffeste_f2c_compile_ ((Field), exq); \
+ } \
+ } while(0)
+
+#define ffeste_f2c_compile_int_(Field,Spec,Exp) \
+ do \
+ { \
+ tree exq; \
+ if (! (Exp)) \
+ { \
+ exq = ffecom_expr ((Spec)->u.expr); \
+ ffeste_f2c_compile_ ((Field), exq); \
+ } \
+ } while(0)
+
+#define ffeste_f2c_compile_ptrtoint_(Field,Spec,Exp) \
+ do \
+ { \
+ tree exq; \
+ if (! (Exp)) \
+ { \
+ exq = ffecom_ptr_to_expr ((Spec)->u.expr); \
+ ffeste_f2c_compile_ ((Field), exq); \
} \
} while(0)
+/* Start a Fortran block. */
+
+#ifdef ENABLE_CHECKING
+
+typedef struct gbe_block
+{
+ struct gbe_block *outer;
+ ffestw block;
+ int lineno;
+ char *input_filename;
+ bool is_stmt;
+} *gbe_block;
+
+gbe_block ffeste_top_block_ = NULL;
+
+static void
+ffeste_start_block_ (ffestw block)
+{
+ gbe_block b = xmalloc (sizeof (*b));
+
+ b->outer = ffeste_top_block_;
+ b->block = block;
+ b->lineno = lineno;
+ b->input_filename = input_filename;
+ b->is_stmt = FALSE;
+
+ ffeste_top_block_ = b;
+
+ ffecom_start_compstmt ();
+}
+
+/* End a Fortran block. */
+
+static void
+ffeste_end_block_ (ffestw block)
+{
+ gbe_block b = ffeste_top_block_;
+
+ assert (b);
+ assert (! b->is_stmt);
+ assert (b->block == block);
+ assert (! b->is_stmt);
+
+ ffeste_top_block_ = b->outer;
+
+ free (b);
+
+ clear_momentary ();
+
+ ffecom_end_compstmt ();
+}
+
+/* Start a Fortran statement.
+
+ Starts a back-end block, so temporaries can be managed, clean-ups
+ properly handled, etc. Nesting of statements *is* allowed -- the
+ handling of I/O items, even implied-DO I/O lists, within a READ,
+ PRINT, or WRITE statement is one example. */
+
+static void
+ffeste_start_stmt_(void)
+{
+ gbe_block b = xmalloc (sizeof (*b));
+
+ b->outer = ffeste_top_block_;
+ b->block = NULL;
+ b->lineno = lineno;
+ b->input_filename = input_filename;
+ b->is_stmt = TRUE;
+
+ ffeste_top_block_ = b;
+
+ ffecom_start_compstmt ();
+}
+
+/* End a Fortran statement. */
+
+static void
+ffeste_end_stmt_(void)
+{
+ gbe_block b = ffeste_top_block_;
+
+ assert (b);
+ assert (b->is_stmt);
+
+ ffeste_top_block_ = b->outer;
+
+ free (b);
+
+ clear_momentary ();
+
+ ffecom_end_compstmt ();
+}
+
+#else /* ! defined (ENABLE_CHECKING) */
+
+#define ffeste_start_block_(b) ffecom_start_compstmt ()
+#define ffeste_end_block_(b) \
+ do \
+ { \
+ clear_momentary (); \
+ ffecom_end_compstmt (); \
+ } while(0)
+#define ffeste_start_stmt_() ffeste_start_block_(NULL)
+#define ffeste_end_stmt_() ffeste_end_block_(NULL)
+
+#endif /* ! defined (ENABLE_CHECKING) */
/* Begin an iterative DO loop. Pass the block to start if applicable.
@@ -302,7 +512,7 @@ ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
ffebld start, ffelexToken start_token,
ffebld end, ffelexToken end_token,
ffebld incr, ffelexToken incr_token,
- char *msg)
+ const char *msg)
{
tree tvar;
tree expr;
@@ -311,12 +521,43 @@ ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
tree tincr;
tree tincr_saved;
tree niters;
+ struct nesting *expanded_loop;
+
+ /* Want to have tvar, tincr, and niters for the whole loop body. */
+
+ if (block)
+ ffeste_start_block_ (block);
+ else
+ ffeste_start_stmt_ ();
+
+ niters = ffecom_make_tempvar (block ? "do" : "impdo",
+ ffecom_integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
- push_momentary (); /* Want to save these throughout the loop. */
+ ffecom_prepare_expr (incr);
+ ffecom_prepare_expr_rw (NULL_TREE, var);
- tvar = ffecom_expr_rw (var);
+ ffecom_prepare_end ();
+
+ tvar = ffecom_expr_rw (NULL_TREE, var);
tincr = ffecom_expr (incr);
+ if (TREE_CODE (tvar) == ERROR_MARK
+ || TREE_CODE (tincr) == ERROR_MARK)
+ {
+ if (block)
+ {
+ ffeste_end_block_ (block);
+ ffestw_set_do_tvar (block, error_mark_node);
+ }
+ else
+ {
+ ffeste_end_stmt_ ();
+ *xtvar = error_mark_node;
+ }
+ return;
+ }
+
/* Check whether incr is known to be zero, complain and fix. */
if (integer_zerop (tincr) || real_zerop (tincr))
@@ -331,16 +572,43 @@ ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
tincr_saved = ffecom_save_tree (tincr);
- push_momentary (); /* Want to discard the rest after the loop. */
+ preserve_momentary ();
+
+ /* Want to have tstart, tend for just this statement. */
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (start);
+ ffecom_prepare_expr (end);
+
+ ffecom_prepare_end ();
tstart = ffecom_expr (start);
tend = ffecom_expr (end);
- { /* For warnings only, nothing else
- happens here. */
+ if (TREE_CODE (tstart) == ERROR_MARK
+ || TREE_CODE (tend) == ERROR_MARK)
+ {
+ ffeste_end_stmt_ ();
+
+ if (block)
+ {
+ ffeste_end_block_ (block);
+ ffestw_set_do_tvar (block, error_mark_node);
+ }
+ else
+ {
+ ffeste_end_stmt_ ();
+ *xtvar = error_mark_node;
+ }
+ return;
+ }
+
+ /* For warnings only, nothing else happens here. */
+ {
tree try;
- if (!ffe_is_onetrip ())
+ if (! ffe_is_onetrip ())
{
try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
tend,
@@ -402,7 +670,7 @@ ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
tend,
tstart);
- if (!ffe_is_onetrip ())
+ if (! ffe_is_onetrip ())
{
expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
expr,
@@ -434,21 +702,22 @@ ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
expr = convert (ffecom_integer_type_node, expr);
#endif
- niters = ffecom_push_tempvar (TREE_TYPE (expr),
- FFETARGET_charactersizeNONE, -1, FALSE);
+ assert (TYPE_MAIN_VARIANT (TREE_TYPE (niters))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (expr)));
+
expr = ffecom_modify (void_type_node, niters, expr);
expand_expr_stmt (expr);
expr = ffecom_modify (void_type_node, tvar, tstart);
expand_expr_stmt (expr);
- if (block == NULL)
- expand_start_loop_continue_elsewhere (0);
- else
- ffestw_set_do_hook (block,
- expand_start_loop_continue_elsewhere (1));
+ ffeste_end_stmt_ ();
+
+ expanded_loop = expand_start_loop_continue_elsewhere (!! block);
+ if (block)
+ ffestw_set_do_hook (block, expanded_loop);
- if (!ffe_is_onetrip ())
+ if (! ffe_is_onetrip ())
{
expr = ffecom_truth_value
(ffecom_2 (GE_EXPR, integer_type_node,
@@ -463,21 +732,18 @@ ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
expand_exit_loop_if_false (0, expr);
}
- clear_momentary (); /* Discard the above now that we're done with
- DO stmt. */
-
- if (block == NULL)
- {
- *xtvar = tvar;
- *xtincr = tincr_saved;
- *xitersvar = niters;
- }
- else
+ if (block)
{
ffestw_set_do_tvar (block, tvar);
ffestw_set_do_incr_saved (block, tincr_saved);
ffestw_set_do_count_var (block, niters);
}
+ else
+ {
+ *xtvar = tvar;
+ *xtincr = tincr_saved;
+ *xitersvar = niters;
+ }
}
#endif
@@ -487,13 +753,18 @@ ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
-ffeste_end_iterdo_ (tree tvar, tree tincr, tree itersvar)
+ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr, tree itersvar)
{
tree expr;
tree niters = itersvar;
+ if (tvar == error_mark_node)
+ return;
+
expand_loop_continue_here ();
+ ffeste_start_stmt_ ();
+
if (ffe_is_onetrip ())
{
expr = ffecom_truth_value
@@ -514,27 +785,21 @@ ffeste_end_iterdo_ (tree tvar, tree tincr, tree itersvar)
tvar,
tincr));
expand_expr_stmt (expr);
- expand_end_loop ();
- ffecom_pop_tempvar (itersvar); /* Free #iters var. */
+ /* Lose the stuff we just built. */
+ ffeste_end_stmt_ ();
- clear_momentary ();
- pop_momentary (); /* Lose the stuff we just built. */
+ expand_end_loop ();
- clear_momentary ();
- pop_momentary (); /* Lose the tvar and incr_saved trees. */
+ /* Lose the tvar and incr_saved trees. */
+ if (block)
+ ffeste_end_block_ (block);
+ else
+ ffeste_end_stmt_ ();
}
-
#endif
-/* ffeste_io_call_ -- Generate call to run-time I/O routine
-
- tree callexpr = build(CALL_EXPR,...);
- ffeste_io_call_(callexpr,TRUE);
- Sets TREE_SIDE_EFFECTS(callexpr) = 1. If ffeste_io_iostat_ is not
- NULL_TREE, replaces callexpr with "iostat = callexpr;". Expands the
- result. If ffeste_io_abort_ is not NULL_TREE and the second argument
- is TRUE, generates "if (iostat != 0) goto ffeste_io_abort_;". */
+/* Generate call to run-time I/O routine. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
@@ -544,15 +809,13 @@ ffeste_io_call_ (tree call, bool do_check)
TREE_SIDE_EFFECTS (call) = 1;
if (ffeste_io_iostat_ != NULL_TREE)
- {
- call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
- ffeste_io_iostat_, call);
- }
+ call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
+ ffeste_io_iostat_, call);
expand_expr_stmt (call);
- if (!do_check
- || (ffeste_io_abort_ == NULL_TREE)
- || (TREE_CODE (ffeste_io_abort_) == ERROR_MARK))
+ if (! do_check
+ || ffeste_io_abort_ == NULL_TREE
+ || TREE_CODE (ffeste_io_abort_) == ERROR_MARK)
return;
/* Generate optional test. */
@@ -561,13 +824,96 @@ ffeste_io_call_ (tree call, bool do_check)
expand_goto (ffeste_io_abort_);
expand_end_cond ();
}
+#endif
+
+/* Handle implied-DO in I/O list.
+
+ Expands code to start up the DO loop. Then for each item in the
+ DO loop, handles appropriately (possibly including recursively calling
+ itself). Then expands code to end the DO loop. */
+
+#if FFECOM_targetCURRENT == FFECOM_targetGCC
+static void
+ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
+{
+ ffebld var = ffebld_head (ffebld_right (impdo));
+ ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
+ ffebld end = ffebld_head (ffebld_trail (ffebld_trail
+ (ffebld_right (impdo))));
+ ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
+ (ffebld_trail (ffebld_right (impdo)))));
+ ffebld list;
+ ffebld item;
+ tree tvar;
+ tree tincr;
+ tree titervar;
+
+ if (incr == NULL)
+ {
+ incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
+ ffebld_set_info (incr, ffeinfo_new
+ (FFEINFO_basictypeINTEGER,
+ FFEINFO_kindtypeINTEGERDEFAULT,
+ 0,
+ FFEINFO_kindENTITY,
+ FFEINFO_whereCONSTANT,
+ FFETARGET_charactersizeNONE));
+ }
+
+ /* Start the DO loop. */
+
+ start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
+ FFEEXPR_contextLET);
+ end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
+ FFEEXPR_contextLET);
+ incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
+ FFEEXPR_contextLET);
+
+ ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
+ start, impdo_token,
+ end, impdo_token,
+ incr, impdo_token,
+ "Implied DO loop");
+
+ /* Handle the list of items. */
+
+ for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
+ {
+ item = ffebld_head (list);
+ if (item == NULL)
+ continue;
+
+ /* Strip parens off items such as in "READ *,(A)". This is really a bug
+ in the user's code, but I've been told lots of code does this. */
+ while (ffebld_op (item) == FFEBLD_opPAREN)
+ item = ffebld_left (item);
+
+ if (ffebld_op (item) == FFEBLD_opANY)
+ continue;
+
+ if (ffebld_op (item) == FFEBLD_opIMPDO)
+ ffeste_io_impdo_ (item, impdo_token);
+ else
+ {
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_arg_ptr_to_expr (item);
+
+ ffecom_prepare_end ();
+
+ ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
+
+ ffeste_end_stmt_ ();
+ }
+ }
+
+ /* Generate end of implied-do construct. */
+ ffeste_end_iterdo_ (NULL, tvar, tincr, titervar);
+}
#endif
-/* ffeste_io_dofio_ -- Generate call to do_fio for formatted I/O item
- ffebld expr;
- tree call;
- call = ffeste_io_dofio_(expr);
+/* I/O driver for formatted I/O item (do_fio)
Returns a tree for a CALL_EXPR to the do_fio function, which handles
a formatted I/O list item, along with the appropriate arguments for
@@ -603,16 +949,11 @@ ffeste_io_dofio_ (ffebld expr)
else
is_complex = FALSE;
- ffecom_push_calltemps ();
-
variable = ffecom_arg_ptr_to_expr (expr, &size);
if ((variable == error_mark_node)
|| (size == error_mark_node))
- {
- ffecom_pop_calltemps ();
- return error_mark_node;
- }
+ return error_mark_node;
if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
{ /* "(ftnlen) sizeof(type)" */
@@ -629,14 +970,15 @@ ffeste_io_dofio_ (ffebld expr)
size = convert (ffecom_f2c_ftnlen_type_node, size);
}
- if ((ffeinfo_rank (ffebld_info (expr)) == 0)
- || (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
- num_elements = is_complex ? ffecom_f2c_ftnlen_two_node
- : ffecom_f2c_ftnlen_one_node;
+ if (ffeinfo_rank (ffebld_info (expr)) == 0
+ || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
+ num_elements
+ = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
else
{
num_elements = size_binop (CEIL_DIV_EXPR,
- TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
+ TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))),
+ size);
num_elements = size_binop (CEIL_DIV_EXPR,
num_elements,
size_int (TYPE_PRECISION
@@ -655,17 +997,11 @@ ffeste_io_dofio_ (ffebld expr)
TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
- ffecom_pop_calltemps ();
-
- return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist);
+ return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist, NULL_TREE);
}
#endif
-/* ffeste_io_dolio_ -- Generate call to do_lio for list-directed I/O item
-
- ffebld expr;
- tree call;
- call = ffeste_io_dolio_(expr);
+/* I/O driver for list-directed I/O item (do_lio)
Returns a tree for a CALL_EXPR to the do_lio function, which handles
a list-directed I/O list item, along with the appropriate arguments for
@@ -694,8 +1030,6 @@ ffeste_io_dolio_ (ffebld expr)
|| (kt == FFEINFO_kindtypeANY))
return error_mark_node;
- ffecom_push_calltemps ();
-
tc = ffecom_f2c_typecode (bt, kt);
assert (tc != -1);
type_id = build_int_2 (tc, 0);
@@ -710,10 +1044,7 @@ ffeste_io_dolio_ (ffebld expr)
if ((type_id == error_mark_node)
|| (variable == error_mark_node)
|| (size == error_mark_node))
- {
- ffecom_pop_calltemps ();
- return error_mark_node;
- }
+ return error_mark_node;
if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
{ /* "(ftnlen) sizeof(type)" */
@@ -730,13 +1061,14 @@ ffeste_io_dolio_ (ffebld expr)
size = convert (ffecom_f2c_ftnlen_type_node, size);
}
- if ((ffeinfo_rank (ffebld_info (expr)) == 0)
- || (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
+ if (ffeinfo_rank (ffebld_info (expr)) == 0
+ || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
num_elements = ffecom_integer_one_node;
else
{
num_elements = size_binop (CEIL_DIV_EXPR,
- TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
+ TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))),
+ size);
num_elements = size_binop (CEIL_DIV_EXPR,
num_elements,
size_int (TYPE_PRECISION
@@ -757,17 +1089,11 @@ ffeste_io_dolio_ (ffebld expr)
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))
= build_tree_list (NULL_TREE, size);
- ffecom_pop_calltemps ();
-
- return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist);
+ return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist, NULL_TREE);
}
#endif
-/* ffeste_io_douio_ -- Generate call to do_uio for unformatted I/O item
-
- ffebld expr;
- tree call;
- call = ffeste_io_douio_(expr);
+/* I/O driver for unformatted I/O item (do_uio)
Returns a tree for a CALL_EXPR to the do_uio function, which handles
an unformatted I/O list item, along with the appropriate arguments for
@@ -803,16 +1129,11 @@ ffeste_io_douio_ (ffebld expr)
else
is_complex = FALSE;
- ffecom_push_calltemps ();
-
variable = ffecom_arg_ptr_to_expr (expr, &size);
if ((variable == error_mark_node)
|| (size == error_mark_node))
- {
- ffecom_pop_calltemps ();
- return error_mark_node;
- }
+ return error_mark_node;
if (size == NULL_TREE) /* Already filled in for CHARACTER type. */
{ /* "(ftnlen) sizeof(type)" */
@@ -829,14 +1150,15 @@ ffeste_io_douio_ (ffebld expr)
size = convert (ffecom_f2c_ftnlen_type_node, size);
}
- if ((ffeinfo_rank (ffebld_info (expr)) == 0)
- || (TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE))
- num_elements = is_complex ? ffecom_f2c_ftnlen_two_node
- : ffecom_f2c_ftnlen_one_node;
+ if (ffeinfo_rank (ffebld_info (expr)) == 0
+ || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
+ num_elements
+ = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
else
{
num_elements = size_binop (CEIL_DIV_EXPR,
- TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))), size);
+ TYPE_SIZE (TREE_TYPE (TREE_TYPE (variable))),
+ size);
num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
size_int (TYPE_PRECISION
(char_type_node)));
@@ -854,21 +1176,24 @@ ffeste_io_douio_ (ffebld expr)
TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
- ffecom_pop_calltemps ();
-
- return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist);
+ return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist, NULL_TREE);
}
#endif
-/* ffeste_io_ialist_ -- Make arglist with ptr to B/E/R control list
-
- tree arglist;
- arglist = ffeste_io_ialist_(...);
+/* Make arglist with ptr to BACKSPACE/ENDFILE/REWIND control list.
Returns a tree suitable as an argument list containing a pointer to
a BACKSPACE/ENDFILE/REWIND control list. First, generates that control
list, if necessary, along with any static and run-time initializations
- that are needed as specified by the arguments to this function. */
+ that are needed as specified by the arguments to this function.
+
+ Must ensure that all expressions are prepared before being evaluated,
+ for any whose evaluation might result in the generation of temporaries.
+
+ Note that this means this function causes a transition, within the
+ current block being code-generated via the back end, from the
+ declaration of variables (temporaries) to the expanding of expressions,
+ statements, etc. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
@@ -912,23 +1237,23 @@ ffeste_io_ialist_ (bool have_err,
f2c_alist_struct = ref;
}
- ffeste_f2c_flagspec_ (have_err, errinit);
+ /* Try to do as much compile-time initialization of the structure
+ as possible, to save run time. */
+
+ ffeste_f2c_init_flag_ (have_err, errinit);
switch (unit)
{
case FFESTV_unitNONE:
case FFESTV_unitASTERISK:
unitinit = build_int_2 (unit_dflt, 0);
- unitexp = NULL_TREE;
+ unitexp = unitinit;
break;
case FFESTV_unitINTEXPR:
- unitexp = ffecom_expr (unit_expr);
- if (TREE_CONSTANT (unitexp))
- {
- unitinit = unitexp;
- unitexp = NULL_TREE;
- }
+ unitexp = ffecom_const_expr (unit_expr);
+ if (unitexp)
+ unitinit = unitexp;
else
{
unitinit = ffecom_integer_zero_node;
@@ -938,14 +1263,14 @@ ffeste_io_ialist_ (bool have_err,
default:
assert ("bad unit spec" == NULL);
- unitexp = NULL_TREE;
unitinit = ffecom_integer_zero_node;
+ unitexp = unitinit;
break;
}
inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
initn = inits;
- ffeste_f2c_init_ (unitinit);
+ ffeste_f2c_init_next_ (unitinit);
inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
@@ -963,7 +1288,20 @@ ffeste_io_ialist_ (bool have_err,
resume_momentary (yes);
- ffeste_f2c_exp_ (unitfield, unitexp);
+ /* Prepare run-time expressions. */
+
+ if (! unitexp)
+ ffecom_prepare_expr (unit_expr);
+
+ ffecom_prepare_end ();
+
+ /* Now evaluate run-time expressions as needed. */
+
+ if (! unitexp)
+ {
+ unitexp = ffecom_expr (unit_expr);
+ ffeste_f2c_compile_ (unitfield, unitexp);
+ }
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
@@ -974,15 +1312,20 @@ ffeste_io_ialist_ (bool have_err,
}
#endif
-/* ffeste_io_cilist_ -- Make arglist with ptr to external I/O control list
-
- tree arglist;
- arglist = ffeste_io_cilist_(...);
+/* Make arglist with ptr to external-I/O control list.
Returns a tree suitable as an argument list containing a pointer to
- an external-file I/O control list. First, generates that control
+ an external-I/O control list. First, generates that control
list, if necessary, along with any static and run-time initializations
- that are needed as specified by the arguments to this function. */
+ that are needed as specified by the arguments to this function.
+
+ Must ensure that all expressions are prepared before being evaluated,
+ for any whose evaluation might result in the generation of temporaries.
+
+ Note that this means this function causes a transition, within the
+ current block being code-generated via the back end, from the
+ declaration of variables (temporaries) to the expanding of expressions,
+ statements, etc. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
@@ -1037,23 +1380,23 @@ ffeste_io_cilist_ (bool have_err,
f2c_cilist_struct = ref;
}
- ffeste_f2c_flagspec_ (have_err, errinit);
+ /* Try to do as much compile-time initialization of the structure
+ as possible, to save run time. */
+
+ ffeste_f2c_init_flag_ (have_err, errinit);
switch (unit)
{
case FFESTV_unitNONE:
case FFESTV_unitASTERISK:
unitinit = build_int_2 (unit_dflt, 0);
- unitexp = NULL_TREE;
+ unitexp = unitinit;
break;
case FFESTV_unitINTEXPR:
- unitexp = ffecom_expr (unit_expr);
- if (TREE_CONSTANT (unitexp))
- {
- unitinit = unitexp;
- unitexp = NULL_TREE;
- }
+ unitexp = ffecom_const_expr (unit_expr);
+ if (unitexp)
+ unitinit = unitexp;
else
{
unitinit = ffecom_integer_zero_node;
@@ -1063,8 +1406,8 @@ ffeste_io_cilist_ (bool have_err,
default:
assert ("bad unit spec" == NULL);
- unitexp = NULL_TREE;
unitinit = ffecom_integer_zero_node;
+ unitexp = unitinit;
break;
}
@@ -1072,11 +1415,11 @@ ffeste_io_cilist_ (bool have_err,
{
case FFESTV_formatNONE:
formatinit = null_pointer_node;
- formatexp = NULL_TREE;
+ formatexp = formatinit;
break;
case FFESTV_formatLABEL:
- formatexp = NULL_TREE;
+ formatexp = error_mark_node;
formatinit = ffecom_lookup_label (format_spec->u.label);
if ((formatinit == NULL_TREE)
|| (TREE_CODE (formatinit) == ERROR_MARK))
@@ -1088,12 +1431,9 @@ ffeste_io_cilist_ (bool have_err,
break;
case FFESTV_formatCHAREXPR:
- formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
- if (TREE_CONSTANT (formatexp))
- {
- formatinit = formatexp;
- formatexp = NULL_TREE;
- }
+ formatexp = ffecom_arg_ptr_to_const_expr (format_spec->u.expr, NULL);
+ if (formatexp)
+ formatinit = formatexp;
else
{
formatinit = null_pointer_node;
@@ -1103,7 +1443,7 @@ ffeste_io_cilist_ (bool have_err,
case FFESTV_formatASTERISK:
formatinit = null_pointer_node;
- formatexp = NULL_TREE;
+ formatexp = formatinit;
break;
case FFESTV_formatINTEXPR:
@@ -1117,27 +1457,24 @@ ffeste_io_cilist_ (bool have_err,
case FFESTV_formatNAMELIST:
formatinit = ffecom_expr (format_spec->u.expr);
- formatexp = NULL_TREE;
+ formatexp = formatinit;
break;
default:
assert ("bad format spec" == NULL);
- formatexp = NULL_TREE;
formatinit = integer_zero_node;
+ formatexp = formatinit;
break;
}
- ffeste_f2c_flagspec_ (have_end, endinit);
+ ffeste_f2c_init_flag_ (have_end, endinit);
if (rec)
- recexp = ffecom_expr (rec_expr);
+ recexp = ffecom_const_expr (rec_expr);
else
recexp = ffecom_integer_zero_node;
- if (TREE_CONSTANT (recexp))
- {
- recinit = recexp;
- recexp = NULL_TREE;
- }
+ if (recexp)
+ recinit = recexp;
else
{
recinit = ffecom_integer_zero_node;
@@ -1146,10 +1483,10 @@ ffeste_io_cilist_ (bool have_err,
inits = build_tree_list ((field = TYPE_FIELDS (f2c_cilist_struct)), errinit);
initn = inits;
- ffeste_f2c_init_ (unitinit);
- ffeste_f2c_init_ (endinit);
- ffeste_f2c_init_ (formatinit);
- ffeste_f2c_init_ (recinit);
+ ffeste_f2c_init_next_ (unitinit);
+ ffeste_f2c_init_next_ (endinit);
+ ffeste_f2c_init_next_ (formatinit);
+ ffeste_f2c_init_next_ (recinit);
inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
@@ -1167,9 +1504,40 @@ ffeste_io_cilist_ (bool have_err,
resume_momentary (yes);
- ffeste_f2c_exp_ (unitfield, unitexp);
- ffeste_f2c_exp_ (formatfield, formatexp);
- ffeste_f2c_exp_ (recfield, recexp);
+ /* Prepare run-time expressions. */
+
+ if (! unitexp)
+ ffecom_prepare_expr (unit_expr);
+
+ if (! formatexp)
+ ffecom_prepare_arg_ptr_to_expr (format_spec->u.expr);
+
+ if (! recexp)
+ ffecom_prepare_expr (rec_expr);
+
+ ffecom_prepare_end ();
+
+ /* Now evaluate run-time expressions as needed. */
+
+ if (! unitexp)
+ {
+ unitexp = ffecom_expr (unit_expr);
+ ffeste_f2c_compile_ (unitfield, unitexp);
+ }
+
+ if (! formatexp)
+ {
+ formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
+ ffeste_f2c_compile_ (formatfield, formatexp);
+ }
+ else if (format == FFESTV_formatINTEXPR)
+ ffeste_f2c_compile_ (formatfield, formatexp);
+
+ if (! recexp)
+ {
+ recexp = ffecom_expr (rec_expr);
+ ffeste_f2c_compile_ (recfield, recexp);
+ }
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
@@ -1180,15 +1548,20 @@ ffeste_io_cilist_ (bool have_err,
}
#endif
-/* ffeste_io_cllist_ -- Make arglist with ptr to CLOSE control list
-
- tree arglist;
- arglist = ffeste_io_cllist_(...);
+/* Make arglist with ptr to CLOSE control list.
Returns a tree suitable as an argument list containing a pointer to
a CLOSE-statement control list. First, generates that control
list, if necessary, along with any static and run-time initializations
- that are needed as specified by the arguments to this function. */
+ that are needed as specified by the arguments to this function.
+
+ Must ensure that all expressions are prepared before being evaluated,
+ for any whose evaluation might result in the generation of temporaries.
+
+ Note that this means this function causes a transition, within the
+ current block being code-generated via the back end, from the
+ declaration of variables (temporaries) to the expanding of expressions,
+ statements, etc. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
@@ -1234,26 +1607,26 @@ ffeste_io_cllist_ (bool have_err,
f2c_close_struct = ref;
}
- ffeste_f2c_flagspec_ (have_err, errinit);
+ /* Try to do as much compile-time initialization of the structure
+ as possible, to save run time. */
- unitexp = ffecom_expr (unit_expr);
- if (TREE_CONSTANT (unitexp))
- {
- unitinit = unitexp;
- unitexp = NULL_TREE;
- }
+ ffeste_f2c_init_flag_ (have_err, errinit);
+
+ unitexp = ffecom_const_expr (unit_expr);
+ if (unitexp)
+ unitinit = unitexp;
else
{
unitinit = ffecom_integer_zero_node;
constantp = FALSE;
}
- ffeste_f2c_charnolenspec_ (stat_spec, statexp, statinit);
+ ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_close_struct)), errinit);
initn = inits;
- ffeste_f2c_init_ (unitinit);
- ffeste_f2c_init_ (statinit);
+ ffeste_f2c_init_next_ (unitinit);
+ ffeste_f2c_init_next_ (statinit);
inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
@@ -1271,8 +1644,25 @@ ffeste_io_cllist_ (bool have_err,
resume_momentary (yes);
- ffeste_f2c_exp_ (unitfield, unitexp);
- ffeste_f2c_exp_ (statfield, statexp);
+ /* Prepare run-time expressions. */
+
+ if (! unitexp)
+ ffecom_prepare_expr (unit_expr);
+
+ if (! statexp)
+ ffecom_prepare_arg_ptr_to_expr (stat_spec->u.expr);
+
+ ffecom_prepare_end ();
+
+ /* Now evaluate run-time expressions as needed. */
+
+ if (! unitexp)
+ {
+ unitexp = ffecom_expr (unit_expr);
+ ffeste_f2c_compile_ (unitfield, unitexp);
+ }
+
+ ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
@@ -1283,15 +1673,20 @@ ffeste_io_cllist_ (bool have_err,
}
#endif
-/* ffeste_io_icilist_ -- Make arglist with ptr to internal I/O control list
-
- tree arglist;
- arglist = ffeste_io_icilist_(...);
+/* Make arglist with ptr to internal-I/O control list.
Returns a tree suitable as an argument list containing a pointer to
- an internal-file I/O control list. First, generates that control
+ an internal-I/O control list. First, generates that control
list, if necessary, along with any static and run-time initializations
- that are needed as specified by the arguments to this function. */
+ that are needed as specified by the arguments to this function.
+
+ Must ensure that all expressions are prepared before being evaluated,
+ for any whose evaluation might result in the generation of temporaries.
+
+ Note that this means this function causes a transition, within the
+ current block being code-generated via the back end, from the
+ declaration of variables (temporaries) to the expanding of expressions,
+ statements, etc. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
@@ -1345,48 +1740,54 @@ ffeste_io_icilist_ (bool have_err,
f2c_icilist_struct = ref;
}
- ffeste_f2c_flagspec_ (have_err, errinit);
+ /* Try to do as much compile-time initialization of the structure
+ as possible, to save run time. */
- unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
- if ((ffeinfo_rank (ffebld_info (unit_expr)) == 0)
- || (TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
- unitnumexp = ffecom_integer_one_node;
- else
- {
- unitnumexp = size_binop (CEIL_DIV_EXPR,
- TYPE_SIZE (TREE_TYPE (TREE_TYPE (unitexp))), unitlenexp);
- unitnumexp = size_binop (CEIL_DIV_EXPR,
- unitnumexp, size_int (TYPE_PRECISION
- (char_type_node)));
- }
- if (TREE_CONSTANT (unitexp))
- {
- unitinit = unitexp;
- unitexp = NULL_TREE;
- }
+ ffeste_f2c_init_flag_ (have_err, errinit);
+
+ unitexp = ffecom_arg_ptr_to_const_expr (unit_expr, &unitlenexp);
+ if (unitexp)
+ unitinit = unitexp;
else
{
unitinit = null_pointer_node;
constantp = FALSE;
}
- if ((unitlenexp != NULL_TREE) && TREE_CONSTANT (unitlenexp))
- {
- unitleninit = unitlenexp;
- unitlenexp = NULL_TREE;
- }
+ if (unitlenexp)
+ unitleninit = unitlenexp;
else
{
unitleninit = ffecom_integer_zero_node;
constantp = FALSE;
}
- if (TREE_CONSTANT (unitnumexp))
+
+ /* Now see if we can fully initialize the number of elements, or
+ if we have to compute that at run time. */
+ if (ffeinfo_rank (ffebld_info (unit_expr)) == 0
+ || (unitexp
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
{
- unitnuminit = unitnumexp;
- unitnumexp = NULL_TREE;
+ /* Not an array, so just one element. */
+ unitnuminit = ffecom_integer_one_node;
+ unitnumexp = unitnuminit;
+ }
+ else if (unitexp && unitlenexp)
+ {
+ /* An array, but all the info is constant, so compute now. */
+ unitnuminit = size_binop (CEIL_DIV_EXPR,
+ TYPE_SIZE (TREE_TYPE (TREE_TYPE (unitexp))),
+ unitlenexp);
+ unitnuminit = size_binop (CEIL_DIV_EXPR,
+ unitnuminit,
+ size_int (TYPE_PRECISION
+ (char_type_node)));
+ unitnumexp = unitnuminit;
}
else
{
+ /* Put off computing until run time. */
unitnuminit = ffecom_integer_zero_node;
+ unitnumexp = NULL_TREE;
constantp = FALSE;
}
@@ -1394,11 +1795,11 @@ ffeste_io_icilist_ (bool have_err,
{
case FFESTV_formatNONE:
formatinit = null_pointer_node;
- formatexp = NULL_TREE;
+ formatexp = formatinit;
break;
case FFESTV_formatLABEL:
- formatexp = NULL_TREE;
+ formatexp = error_mark_node;
formatinit = ffecom_lookup_label (format_spec->u.label);
if ((formatinit == NULL_TREE)
|| (TREE_CODE (formatinit) == ERROR_MARK))
@@ -1410,22 +1811,12 @@ ffeste_io_icilist_ (bool have_err,
break;
case FFESTV_formatCHAREXPR:
- formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
- if (TREE_CONSTANT (formatexp))
- {
- formatinit = formatexp;
- formatexp = NULL_TREE;
- }
- else
- {
- formatinit = null_pointer_node;
- constantp = FALSE;
- }
+ ffeste_f2c_init_format_ (formatexp, formatinit, format_spec);
break;
case FFESTV_formatASTERISK:
formatinit = null_pointer_node;
- formatexp = NULL_TREE;
+ formatexp = formatinit;
break;
case FFESTV_formatINTEXPR:
@@ -1439,21 +1830,21 @@ ffeste_io_icilist_ (bool have_err,
default:
assert ("bad format spec" == NULL);
- formatexp = NULL_TREE;
formatinit = ffecom_integer_zero_node;
+ formatexp = formatinit;
break;
}
- ffeste_f2c_flagspec_ (have_end, endinit);
+ ffeste_f2c_init_flag_ (have_end, endinit);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_icilist_struct)),
errinit);
initn = inits;
- ffeste_f2c_init_ (unitinit);
- ffeste_f2c_init_ (endinit);
- ffeste_f2c_init_ (formatinit);
- ffeste_f2c_init_ (unitleninit);
- ffeste_f2c_init_ (unitnuminit);
+ ffeste_f2c_init_next_ (unitinit);
+ ffeste_f2c_init_next_ (endinit);
+ ffeste_f2c_init_next_ (formatinit);
+ ffeste_f2c_init_next_ (unitleninit);
+ ffeste_f2c_init_next_ (unitnuminit);
inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
@@ -1471,106 +1862,71 @@ ffeste_io_icilist_ (bool have_err,
resume_momentary (yes);
- ffeste_f2c_exp_ (unitfield, unitexp);
- ffeste_f2c_exp_ (formatfield, formatexp);
- ffeste_f2c_exp_ (unitlenfield, unitlenexp);
- ffeste_f2c_exp_ (unitnumfield, unitnumexp);
-
- ttype = build_pointer_type (TREE_TYPE (t));
- t = ffecom_1 (ADDR_EXPR, ttype, t);
+ /* Prepare run-time expressions. */
- t = build_tree_list (NULL_TREE, t);
+ if (! unitexp)
+ ffecom_prepare_arg_ptr_to_expr (unit_expr);
- return t;
-}
+ ffeste_f2c_prepare_format_ (format_spec, formatexp);
-#endif
-/* ffeste_io_impdo_ -- Handle implied-DO in I/O list
-
- ffebld expr;
- ffeste_io_impdo_(expr);
+ ffecom_prepare_end ();
- Expands code to start up the DO loop. Then for each item in the
- DO loop, handles appropriately (possibly including recursively calling
- itself). Then expands code to end the DO loop. */
-
-#if FFECOM_targetCURRENT == FFECOM_targetGCC
-static void
-ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
-{
- ffebld var = ffebld_head (ffebld_right (impdo));
- ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
- ffebld end = ffebld_head (ffebld_trail (ffebld_trail
- (ffebld_right (impdo))));
- ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
- (ffebld_trail (ffebld_right (impdo)))));
- ffebld list; /* Used for list of items in left part of
- impdo. */
- ffebld item; /* I/O item from head of given list. */
- tree tvar;
- tree tincr;
- tree titervar;
+ /* Now evaluate run-time expressions as needed. */
- if (incr == NULL)
+ if (! unitexp || ! unitlenexp)
{
- incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
- ffebld_set_info (incr, ffeinfo_new
- (FFEINFO_basictypeINTEGER,
- FFEINFO_kindtypeINTEGERDEFAULT,
- 0,
- FFEINFO_kindENTITY,
- FFEINFO_whereCONSTANT,
- FFETARGET_charactersizeNONE));
+ int need_unitexp = (! unitexp);
+ int need_unitlenexp = (! unitlenexp);
+
+ unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
+ if (need_unitexp)
+ ffeste_f2c_compile_ (unitfield, unitexp);
+ if (need_unitlenexp)
+ ffeste_f2c_compile_ (unitlenfield, unitlenexp);
}
- /* Start the DO loop. */
-
- start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
- FFEEXPR_contextLET);
- end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
- FFEEXPR_contextLET);
- incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
- FFEEXPR_contextLET);
-
- ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
- start, impdo_token,
- end, impdo_token,
- incr, impdo_token,
- "Implied DO loop");
-
- /* Handle the list of items. */
-
- for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
+ if (! unitnumexp
+ && unitexp != error_mark_node
+ && unitlenexp != error_mark_node)
{
- item = ffebld_head (list);
- if (item == NULL)
- continue;
- while (ffebld_op (item) == FFEBLD_opPAREN)
- item = ffebld_left (item);
- if (ffebld_op (item) == FFEBLD_opANY)
- continue;
- if (ffebld_op (item) == FFEBLD_opIMPDO)
- ffeste_io_impdo_ (item, impdo_token);
- else
- ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
- clear_momentary ();
+ unitnumexp = size_binop (CEIL_DIV_EXPR,
+ TYPE_SIZE (TREE_TYPE (TREE_TYPE (unitexp))),
+ unitlenexp);
+ unitnumexp = size_binop (CEIL_DIV_EXPR,
+ unitnumexp,
+ size_int (TYPE_PRECISION
+ (char_type_node)));
+ ffeste_f2c_compile_ (unitnumfield, unitnumexp);
}
- /* Generate end of implied-do construct. */
+ if (format == FFESTV_formatINTEXPR)
+ ffeste_f2c_compile_ (formatfield, formatexp);
+ else
+ ffeste_f2c_compile_format_ (formatfield, format_spec, formatexp);
- ffeste_end_iterdo_ (tvar, tincr, titervar);
-}
+ ttype = build_pointer_type (TREE_TYPE (t));
+ t = ffecom_1 (ADDR_EXPR, ttype, t);
+ t = build_tree_list (NULL_TREE, t);
+
+ return t;
+}
#endif
-/* ffeste_io_inlist_ -- Make arglist with ptr to INQUIRE control list
- tree arglist;
- arglist = ffeste_io_inlist_(...);
+/* Make arglist with ptr to INQUIRE control list
Returns a tree suitable as an argument list containing a pointer to
an INQUIRE-statement control list. First, generates that control
list, if necessary, along with any static and run-time initializations
- that are needed as specified by the arguments to this function. */
+ that are needed as specified by the arguments to this function.
+
+ Must ensure that all expressions are prepared before being evaluated,
+ for any whose evaluation might result in the generation of temporaries.
+
+ Note that this means this function causes a transition, within the
+ current block being code-generated via the back end, from the
+ declaration of variables (temporaries) to the expanding of expressions,
+ statements, etc. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
@@ -1691,58 +2047,64 @@ ffeste_io_inlist_ (bool have_err,
f2c_inquire_struct = ref;
}
- ffeste_f2c_flagspec_ (have_err, errinit);
- ffeste_f2c_intspec_ (unit_spec, unitexp, unitinit);
- ffeste_f2c_charspec_ (file_spec, fileexp, fileinit, filelenexp, fileleninit);
- ffeste_f2c_ptrtointspec_ (exist_spec, existexp, existinit);
- ffeste_f2c_ptrtointspec_ (open_spec, openexp, openinit);
- ffeste_f2c_ptrtointspec_ (number_spec, numberexp, numberinit);
- ffeste_f2c_ptrtointspec_ (named_spec, namedexp, namedinit);
- ffeste_f2c_charspec_ (name_spec, nameexp, nameinit, namelenexp, nameleninit);
- ffeste_f2c_charspec_ (access_spec, accessexp, accessinit, accesslenexp,
- accessleninit);
- ffeste_f2c_charspec_ (sequential_spec, sequentialexp, sequentialinit,
- sequentiallenexp, sequentialleninit);
- ffeste_f2c_charspec_ (direct_spec, directexp, directinit, directlenexp,
- directleninit);
- ffeste_f2c_charspec_ (form_spec, formexp, forminit, formlenexp, formleninit);
- ffeste_f2c_charspec_ (formatted_spec, formattedexp, formattedinit,
- formattedlenexp, formattedleninit);
- ffeste_f2c_charspec_ (unformatted_spec, unformattedexp, unformattedinit,
- unformattedlenexp, unformattedleninit);
- ffeste_f2c_ptrtointspec_ (recl_spec, reclexp, reclinit);
- ffeste_f2c_ptrtointspec_ (nextrec_spec, nextrecexp, nextrecinit);
- ffeste_f2c_charspec_ (blank_spec, blankexp, blankinit, blanklenexp,
- blankleninit);
+ /* Try to do as much compile-time initialization of the structure
+ as possible, to save run time. */
+
+ ffeste_f2c_init_flag_ (have_err, errinit);
+ ffeste_f2c_init_int_ (unitexp, unitinit, unit_spec);
+ ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
+ file_spec);
+ ffeste_f2c_init_ptrtoint_ (existexp, existinit, exist_spec);
+ ffeste_f2c_init_ptrtoint_ (openexp, openinit, open_spec);
+ ffeste_f2c_init_ptrtoint_ (numberexp, numberinit, number_spec);
+ ffeste_f2c_init_ptrtoint_ (namedexp, namedinit, named_spec);
+ ffeste_f2c_init_char_ (nameexp, nameinit, namelenexp, nameleninit,
+ name_spec);
+ ffeste_f2c_init_char_ (accessexp, accessinit, accesslenexp,
+ accessleninit, access_spec);
+ ffeste_f2c_init_char_ (sequentialexp, sequentialinit, sequentiallenexp,
+ sequentialleninit, sequential_spec);
+ ffeste_f2c_init_char_ (directexp, directinit, directlenexp,
+ directleninit, direct_spec);
+ ffeste_f2c_init_char_ (formexp, forminit, formlenexp, formleninit,
+ form_spec);
+ ffeste_f2c_init_char_ (formattedexp, formattedinit,
+ formattedlenexp, formattedleninit, formatted_spec);
+ ffeste_f2c_init_char_ (unformattedexp, unformattedinit, unformattedlenexp,
+ unformattedleninit, unformatted_spec);
+ ffeste_f2c_init_ptrtoint_ (reclexp, reclinit, recl_spec);
+ ffeste_f2c_init_ptrtoint_ (nextrecexp, nextrecinit, nextrec_spec);
+ ffeste_f2c_init_char_ (blankexp, blankinit, blanklenexp,
+ blankleninit, blank_spec);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_inquire_struct)),
errinit);
initn = inits;
- ffeste_f2c_init_ (unitinit);
- ffeste_f2c_init_ (fileinit);
- ffeste_f2c_init_ (fileleninit);
- ffeste_f2c_init_ (existinit);
- ffeste_f2c_init_ (openinit);
- ffeste_f2c_init_ (numberinit);
- ffeste_f2c_init_ (namedinit);
- ffeste_f2c_init_ (nameinit);
- ffeste_f2c_init_ (nameleninit);
- ffeste_f2c_init_ (accessinit);
- ffeste_f2c_init_ (accessleninit);
- ffeste_f2c_init_ (sequentialinit);
- ffeste_f2c_init_ (sequentialleninit);
- ffeste_f2c_init_ (directinit);
- ffeste_f2c_init_ (directleninit);
- ffeste_f2c_init_ (forminit);
- ffeste_f2c_init_ (formleninit);
- ffeste_f2c_init_ (formattedinit);
- ffeste_f2c_init_ (formattedleninit);
- ffeste_f2c_init_ (unformattedinit);
- ffeste_f2c_init_ (unformattedleninit);
- ffeste_f2c_init_ (reclinit);
- ffeste_f2c_init_ (nextrecinit);
- ffeste_f2c_init_ (blankinit);
- ffeste_f2c_init_ (blankleninit);
+ ffeste_f2c_init_next_ (unitinit);
+ ffeste_f2c_init_next_ (fileinit);
+ ffeste_f2c_init_next_ (fileleninit);
+ ffeste_f2c_init_next_ (existinit);
+ ffeste_f2c_init_next_ (openinit);
+ ffeste_f2c_init_next_ (numberinit);
+ ffeste_f2c_init_next_ (namedinit);
+ ffeste_f2c_init_next_ (nameinit);
+ ffeste_f2c_init_next_ (nameleninit);
+ ffeste_f2c_init_next_ (accessinit);
+ ffeste_f2c_init_next_ (accessleninit);
+ ffeste_f2c_init_next_ (sequentialinit);
+ ffeste_f2c_init_next_ (sequentialleninit);
+ ffeste_f2c_init_next_ (directinit);
+ ffeste_f2c_init_next_ (directleninit);
+ ffeste_f2c_init_next_ (forminit);
+ ffeste_f2c_init_next_ (formleninit);
+ ffeste_f2c_init_next_ (formattedinit);
+ ffeste_f2c_init_next_ (formattedleninit);
+ ffeste_f2c_init_next_ (unformattedinit);
+ ffeste_f2c_init_next_ (unformattedleninit);
+ ffeste_f2c_init_next_ (reclinit);
+ ffeste_f2c_init_next_ (nextrecinit);
+ ffeste_f2c_init_next_ (blankinit);
+ ffeste_f2c_init_next_ (blankleninit);
inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
@@ -1760,31 +2122,56 @@ ffeste_io_inlist_ (bool have_err,
resume_momentary (yes);
- ffeste_f2c_exp_ (unitfield, unitexp);
- ffeste_f2c_exp_ (filefield, fileexp);
- ffeste_f2c_exp_ (filelenfield, filelenexp);
- ffeste_f2c_exp_ (existfield, existexp);
- ffeste_f2c_exp_ (openfield, openexp);
- ffeste_f2c_exp_ (numberfield, numberexp);
- ffeste_f2c_exp_ (namedfield, namedexp);
- ffeste_f2c_exp_ (namefield, nameexp);
- ffeste_f2c_exp_ (namelenfield, namelenexp);
- ffeste_f2c_exp_ (accessfield, accessexp);
- ffeste_f2c_exp_ (accesslenfield, accesslenexp);
- ffeste_f2c_exp_ (sequentialfield, sequentialexp);
- ffeste_f2c_exp_ (sequentiallenfield, sequentiallenexp);
- ffeste_f2c_exp_ (directfield, directexp);
- ffeste_f2c_exp_ (directlenfield, directlenexp);
- ffeste_f2c_exp_ (formfield, formexp);
- ffeste_f2c_exp_ (formlenfield, formlenexp);
- ffeste_f2c_exp_ (formattedfield, formattedexp);
- ffeste_f2c_exp_ (formattedlenfield, formattedlenexp);
- ffeste_f2c_exp_ (unformattedfield, unformattedexp);
- ffeste_f2c_exp_ (unformattedlenfield, unformattedlenexp);
- ffeste_f2c_exp_ (reclfield, reclexp);
- ffeste_f2c_exp_ (nextrecfield, nextrecexp);
- ffeste_f2c_exp_ (blankfield, blankexp);
- ffeste_f2c_exp_ (blanklenfield, blanklenexp);
+ /* Prepare run-time expressions. */
+
+ ffeste_f2c_prepare_int_ (unit_spec, unitexp);
+ ffeste_f2c_prepare_char_ (file_spec, fileexp);
+ ffeste_f2c_prepare_ptrtoint_ (exist_spec, existexp);
+ ffeste_f2c_prepare_ptrtoint_ (open_spec, openexp);
+ ffeste_f2c_prepare_ptrtoint_ (number_spec, numberexp);
+ ffeste_f2c_prepare_ptrtoint_ (named_spec, namedexp);
+ ffeste_f2c_prepare_char_ (name_spec, nameexp);
+ ffeste_f2c_prepare_char_ (access_spec, accessexp);
+ ffeste_f2c_prepare_char_ (sequential_spec, sequentialexp);
+ ffeste_f2c_prepare_char_ (direct_spec, directexp);
+ ffeste_f2c_prepare_char_ (form_spec, formexp);
+ ffeste_f2c_prepare_char_ (formatted_spec, formattedexp);
+ ffeste_f2c_prepare_char_ (unformatted_spec, unformattedexp);
+ ffeste_f2c_prepare_ptrtoint_ (recl_spec, reclexp);
+ ffeste_f2c_prepare_ptrtoint_ (nextrec_spec, nextrecexp);
+ ffeste_f2c_prepare_char_ (blank_spec, blankexp);
+
+ ffecom_prepare_end ();
+
+ /* Now evaluate run-time expressions as needed. */
+
+ ffeste_f2c_compile_int_ (unitfield, unit_spec, unitexp);
+ ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec,
+ fileexp, filelenexp);
+ ffeste_f2c_compile_ptrtoint_ (existfield, exist_spec, existexp);
+ ffeste_f2c_compile_ptrtoint_ (openfield, open_spec, openexp);
+ ffeste_f2c_compile_ptrtoint_ (numberfield, number_spec, numberexp);
+ ffeste_f2c_compile_ptrtoint_ (namedfield, named_spec, namedexp);
+ ffeste_f2c_compile_char_ (namefield, namelenfield, name_spec, nameexp,
+ namelenexp);
+ ffeste_f2c_compile_char_ (accessfield, accesslenfield, access_spec,
+ accessexp, accesslenexp);
+ ffeste_f2c_compile_char_ (sequentialfield, sequentiallenfield,
+ sequential_spec, sequentialexp,
+ sequentiallenexp);
+ ffeste_f2c_compile_char_ (directfield, directlenfield, direct_spec,
+ directexp, directlenexp);
+ ffeste_f2c_compile_char_ (formfield, formlenfield, form_spec, formexp,
+ formlenexp);
+ ffeste_f2c_compile_char_ (formattedfield, formattedlenfield, formatted_spec,
+ formattedexp, formattedlenexp);
+ ffeste_f2c_compile_char_ (unformattedfield, unformattedlenfield,
+ unformatted_spec, unformattedexp,
+ unformattedlenexp);
+ ffeste_f2c_compile_ptrtoint_ (reclfield, recl_spec, reclexp);
+ ffeste_f2c_compile_ptrtoint_ (nextrecfield, nextrec_spec, nextrecexp);
+ ffeste_f2c_compile_char_ (blankfield, blanklenfield, blank_spec, blankexp,
+ blanklenexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
@@ -1795,15 +2182,20 @@ ffeste_io_inlist_ (bool have_err,
}
#endif
-/* ffeste_io_olist_ -- Make arglist with ptr to OPEN control list
-
- tree arglist;
- arglist = ffeste_io_olist_(...);
+/* Make arglist with ptr to OPEN control list
Returns a tree suitable as an argument list containing a pointer to
an OPEN-statement control list. First, generates that control
list, if necessary, along with any static and run-time initializations
- that are needed as specified by the arguments to this function. */
+ that are needed as specified by the arguments to this function.
+
+ Must ensure that all expressions are prepared before being evaluated,
+ for any whose evaluation might result in the generation of temporaries.
+
+ Note that this means this function causes a transition, within the
+ current block being code-generated via the back end, from the
+ declaration of variables (temporaries) to the expanding of expressions,
+ statements, etc. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static tree
@@ -1870,37 +2262,38 @@ ffeste_io_olist_ (bool have_err,
f2c_open_struct = ref;
}
- ffeste_f2c_flagspec_ (have_err, errinit);
+ /* Try to do as much compile-time initialization of the structure
+ as possible, to save run time. */
- unitexp = ffecom_expr (unit_expr);
- if (TREE_CONSTANT (unitexp))
- {
- unitinit = unitexp;
- unitexp = NULL_TREE;
- }
+ ffeste_f2c_init_flag_ (have_err, errinit);
+
+ unitexp = ffecom_const_expr (unit_expr);
+ if (unitexp)
+ unitinit = unitexp;
else
{
unitinit = ffecom_integer_zero_node;
constantp = FALSE;
}
- ffeste_f2c_charspec_ (file_spec, fileexp, fileinit, filelenexp, fileleninit);
- ffeste_f2c_charnolenspec_ (stat_spec, statexp, statinit);
- ffeste_f2c_charnolenspec_ (access_spec, accessexp, accessinit);
- ffeste_f2c_charnolenspec_ (form_spec, formexp, forminit);
- ffeste_f2c_intspec_ (recl_spec, reclexp, reclinit);
- ffeste_f2c_charnolenspec_ (blank_spec, blankexp, blankinit);
+ ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
+ file_spec);
+ ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
+ ffeste_f2c_init_charnolen_ (accessexp, accessinit, access_spec);
+ ffeste_f2c_init_charnolen_ (formexp, forminit, form_spec);
+ ffeste_f2c_init_int_ (reclexp, reclinit, recl_spec);
+ ffeste_f2c_init_charnolen_ (blankexp, blankinit, blank_spec);
inits = build_tree_list ((field = TYPE_FIELDS (f2c_open_struct)), errinit);
initn = inits;
- ffeste_f2c_init_ (unitinit);
- ffeste_f2c_init_ (fileinit);
- ffeste_f2c_init_ (fileleninit);
- ffeste_f2c_init_ (statinit);
- ffeste_f2c_init_ (accessinit);
- ffeste_f2c_init_ (forminit);
- ffeste_f2c_init_ (reclinit);
- ffeste_f2c_init_ (blankinit);
+ ffeste_f2c_init_next_ (unitinit);
+ ffeste_f2c_init_next_ (fileinit);
+ ffeste_f2c_init_next_ (fileleninit);
+ ffeste_f2c_init_next_ (statinit);
+ ffeste_f2c_init_next_ (accessinit);
+ ffeste_f2c_init_next_ (forminit);
+ ffeste_f2c_init_next_ (reclinit);
+ ffeste_f2c_init_next_ (blankinit);
inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
TREE_CONSTANT (inits) = constantp ? 1 : 0;
@@ -1918,14 +2311,35 @@ ffeste_io_olist_ (bool have_err,
resume_momentary (yes);
- ffeste_f2c_exp_ (unitfield, unitexp);
- ffeste_f2c_exp_ (filefield, fileexp);
- ffeste_f2c_exp_ (filelenfield, filelenexp);
- ffeste_f2c_exp_ (statfield, statexp);
- ffeste_f2c_exp_ (accessfield, accessexp);
- ffeste_f2c_exp_ (formfield, formexp);
- ffeste_f2c_exp_ (reclfield, reclexp);
- ffeste_f2c_exp_ (blankfield, blankexp);
+ /* Prepare run-time expressions. */
+
+ if (! unitexp)
+ ffecom_prepare_expr (unit_expr);
+
+ ffeste_f2c_prepare_char_ (file_spec, fileexp);
+ ffeste_f2c_prepare_charnolen_ (stat_spec, statexp);
+ ffeste_f2c_prepare_charnolen_ (access_spec, accessexp);
+ ffeste_f2c_prepare_charnolen_ (form_spec, formexp);
+ ffeste_f2c_prepare_int_ (recl_spec, reclexp);
+ ffeste_f2c_prepare_charnolen_ (blank_spec, blankexp);
+
+ ffecom_prepare_end ();
+
+ /* Now evaluate run-time expressions as needed. */
+
+ if (! unitexp)
+ {
+ unitexp = ffecom_expr (unit_expr);
+ ffeste_f2c_compile_ (unitfield, unitexp);
+ }
+
+ ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec, fileexp,
+ filelenexp);
+ ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
+ ffeste_f2c_compile_charnolen_ (accessfield, access_spec, accessexp);
+ ffeste_f2c_compile_charnolen_ (formfield, form_spec, formexp);
+ ffeste_f2c_compile_int_ (reclfield, recl_spec, reclexp);
+ ffeste_f2c_compile_charnolen_ (blankfield, blank_spec, blankexp);
ttype = build_pointer_type (TREE_TYPE (t));
t = ffecom_1 (ADDR_EXPR, ttype, t);
@@ -1936,13 +2350,11 @@ ffeste_io_olist_ (bool have_err,
}
#endif
-/* ffeste_subr_file_ -- Display file-statement specifier
-
- ffeste_subr_file_(&specifier); */
+/* Display file-statement specifier. */
#if FFECOM_targetCURRENT == FFECOM_targetFFE
static void
-ffeste_subr_file_ (char *kw, ffestpFile *spec)
+ffeste_subr_file_ (const char *kw, ffestpFile *spec)
{
if (!spec->kw_or_val_present)
return;
@@ -1963,9 +2375,7 @@ ffeste_subr_file_ (char *kw, ffestpFile *spec)
}
#endif
-/* ffeste_subr_beru_ -- Generate code for BACKSPACE/ENDFILE/REWIND
-
- ffeste_subr_beru_(FFECOM_gfrtFBACK); */
+/* Generate code for BACKSPACE/ENDFILE/REWIND. */
#if FFECOM_targetCURRENT == FFECOM_targetGCC
static void
@@ -1975,15 +2385,15 @@ ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
bool iostat;
bool errl;
-#define specified(something) (info->beru_spec[something].kw_or_val_present)
-
ffeste_emit_line_note_ ();
- /* Do the real work. */
+#define specified(something) (info->beru_spec[something].kw_or_val_present)
iostat = specified (FFESTP_beruixIOSTAT);
errl = specified (FFESTP_beruixERR);
+#undef specified
+
/* ~~For now, we assume the unit number is specified and is not ASTERISK,
because the FFE doesn't support BACKSPACE(*) and rejects a BACKSPACE
without any unit specifier. f2c, however, supports the former
@@ -1992,15 +2402,14 @@ ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
ffestvUnit indicator of FFESTV_unitINTEXPR or _unitASTERISK to
ffeste_R919 and company, and they will want to pass that same value to
this function, and that argument will replace the constant _unitINTEXPR_
- in the call below. Right now, the default unit number, 6, is ignored. */
+ in the call below. Right now, the default unit number, 6, is ignored. */
- ffecom_push_calltemps ();
-
- alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
- info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
+ ffeste_start_stmt_ ();
if (errl)
- { /* ERR= */
+ {
+ /* Have ERR= specification. */
+
ffeste_io_err_
= ffeste_io_abort_
= ffecom_lookup_label
@@ -2008,7 +2417,9 @@ ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
ffeste_io_abort_is_temp_ = FALSE;
}
else
- { /* no ERR= */
+ {
+ /* No ERR= specification. */
+
ffeste_io_err_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
@@ -2018,29 +2429,40 @@ ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
}
if (iostat)
- { /* IOSTAT= */
+ {
+ /* Have IOSTAT= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
- { /* no IOSTAT= but ERR= */
+ {
+ /* Have no IOSTAT= but have ERR=. */
+
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
- = ffecom_push_tempvar (ffecom_integer_type_node,
- FFETARGET_charactersizeNONE, -1, FALSE);
+ = ffecom_make_tempvar ("beru", ffecom_integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
}
else
- { /* no IOSTAT=, or ERR= */
+ {
+ /* No IOSTAT= or ERR= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
+ /* Now prescan, then convert, all the arguments. */
+
+ alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
+ info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
+
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
- ffeste_io_call_ (ffecom_call_gfrt (rt, alist),
- !ffeste_io_abort_is_temp_);
+ ffeste_io_call_ (ffecom_call_gfrt (rt, alist, NULL_TREE),
+ ! ffeste_io_abort_is_temp_);
/* If we've got a temp label, generate its code here. */
@@ -2053,28 +2475,16 @@ ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
assert (ffeste_io_err_ == NULL_TREE);
}
- /* If we've got a temp iostat, pop the temp. */
-
- if (ffeste_io_iostat_is_temp_)
- ffecom_pop_tempvar (ffeste_io_iostat_);
-
- ffecom_pop_calltemps ();
-
-#undef specified
-
- clear_momentary ();
+ ffeste_end_stmt_ ();
}
-
#endif
-/* ffeste_do -- End of statement following DO-term-stmt etc
- ffeste_do(TRUE);
+/* END DO statement
Also invoked by _labeldef_branch_finish_ (or, in cases
of errors, other _labeldef_ functions) when the label definition is
for a DO-target (LOOPEND) label, once per matching/outstanding DO
- block on the stack. These cases invoke this function with ok==TRUE, so
- only forced stack popping (via ffeste_eof_()) invokes it with ok==FALSE. */
+ block on the stack. */
void
ffeste_do (ffestw block)
@@ -2083,28 +2493,26 @@ ffeste_do (ffestw block)
fputs ("+ END_DO\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
+
if (ffestw_do_tvar (block) == 0)
- expand_end_loop (); /* DO WHILE and just DO. */
+ {
+ expand_end_loop (); /* DO WHILE and just DO. */
+
+ ffeste_end_block_ (block);
+ }
else
- ffeste_end_iterdo_ (ffestw_do_tvar (block),
+ ffeste_end_iterdo_ (block,
+ ffestw_do_tvar (block),
ffestw_do_incr_saved (block),
ffestw_do_count_var (block));
-
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_end_R807 -- End of statement following logical IF
+/* End of statement following logical IF.
- ffeste_end_R807(TRUE);
-
- Applies ONLY to logical IF, not to IF-THEN. For example, does not
- ffelex_token_kill the construct name for an IF-THEN block (the name
- field is invalid for logical IF). ok==TRUE iff statement following
- logical IF (substatement) is valid; else, statement is invalid or
- stack forcibly popped due to ffeste_eof_(). */
+ Applies to *only* logical IF, not to IF-THEN. */
void
ffeste_end_R807 ()
@@ -2113,16 +2521,16 @@ ffeste_end_R807 ()
fputs ("+ END_IF\n", dmpout); /* Also see ffeste_R806. */
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
+
expand_end_cond ();
- clear_momentary ();
+
+ ffeste_end_block_ (NULL);
#else
#error
#endif
}
-/* ffeste_labeldef_branch -- Generate "code" for branch label def
-
- ffeste_labeldef_branch(label); */
+/* Generate "code" for branch label definition. */
void
ffeste_labeldef_branch (ffelab label)
@@ -2137,11 +2545,15 @@ ffeste_labeldef_branch (ffelab label)
assert (glabel != NULL_TREE);
if (TREE_CODE (glabel) == ERROR_MARK)
return;
+
assert (DECL_INITIAL (glabel) == NULL_TREE);
+
DECL_INITIAL (glabel) = error_mark_node;
DECL_SOURCE_FILE (glabel) = ffelab_definition_filename (label);
DECL_SOURCE_LINE (glabel) = ffelab_definition_filelinenum (label);
+
emit_nop ();
+
expand_label (glabel);
}
#else
@@ -2149,9 +2561,7 @@ ffeste_labeldef_branch (ffelab label)
#endif
}
-/* ffeste_labeldef_format -- Generate "code" for FORMAT label def
-
- ffeste_labeldef_format(label); */
+/* Generate "code" for FORMAT label definition. */
void
ffeste_labeldef_format (ffelab label)
@@ -2165,9 +2575,7 @@ ffeste_labeldef_format (ffelab label)
#endif
}
-/* ffeste_R737A -- Assignment statement outside of WHERE
-
- ffeste_R737A(dest_expr,source_expr); */
+/* Assignment statement (outside of WHERE). */
void
ffeste_R737A (ffebld dest, ffebld source)
@@ -2182,25 +2590,21 @@ ffeste_R737A (ffebld dest, ffebld source)
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+
+ ffeste_start_stmt_ ();
ffecom_expand_let_stmt (dest, source);
- ffecom_pop_calltemps ();
- clear_momentary ();
+ ffeste_end_stmt_ ();
#else
#error
#endif
}
-/* ffeste_R803 -- Block IF (IF-THEN) statement
-
- ffeste_R803(construct_name,expr,expr_token);
-
- Make sure statement is valid here; implement. */
+/* Block IF (IF-THEN) statement. */
void
-ffeste_R803 (ffebld expr)
+ffeste_R803 (ffestw block, ffebld expr)
{
ffeste_check_simple_ ();
@@ -2209,28 +2613,53 @@ ffeste_R803 (ffebld expr)
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+ {
+ tree temp;
- expand_start_cond (ffecom_truth_value (ffecom_expr (expr)), 0);
+ ffeste_emit_line_note_ ();
- ffecom_pop_calltemps ();
- clear_momentary ();
+ ffeste_start_block_ (block);
+
+ temp = ffecom_make_tempvar ("ifthen", integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (expr);
+
+ if (ffecom_prepare_end ())
+ {
+ tree result;
+
+ result = ffecom_modify (void_type_node,
+ temp,
+ ffecom_truth_value (ffecom_expr (expr)));
+
+ expand_expr_stmt (result);
+
+ ffeste_end_stmt_ ();
+ }
+ else
+ {
+ ffeste_end_stmt_ ();
+
+ temp = ffecom_truth_value (ffecom_expr (expr));
+ }
+
+ expand_start_cond (temp, 0);
+
+ /* No fake `else' constructs introduced (yet). */
+ ffestw_set_ifthen_fake_else (block, 0);
+ }
#else
#error
#endif
}
-/* ffeste_R804 -- ELSE IF statement
-
- ffeste_R804(expr,expr_token,name_token);
-
- Make sure ffeste_kind_ identifies an IF block. If not
- NULL, make sure name_token gives the correct name. Implement the else
- of the IF block. */
+/* ELSE IF statement. */
void
-ffeste_R804 (ffebld expr)
+ffeste_R804 (ffestw block, ffebld expr)
{
ffeste_check_simple_ ();
@@ -2239,28 +2668,65 @@ ffeste_R804 (ffebld expr)
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+ {
+ tree temp;
+
+ ffeste_emit_line_note_ ();
- expand_start_elseif (ffecom_truth_value (ffecom_expr (expr)));
+ /* Since ELSEIF(expr) might require preparations for expr,
+ implement as ELSE; prepare-expr; IF (expr) THEN ...; ENDIF. */
- ffecom_pop_calltemps ();
- clear_momentary ();
+ expand_start_else ();
+
+ ffeste_start_block_ (block);
+
+ temp = ffecom_make_tempvar ("elseif", integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (expr);
+
+ if (ffecom_prepare_end ())
+ {
+ tree result;
+
+ result = ffecom_modify (void_type_node,
+ temp,
+ ffecom_truth_value (ffecom_expr (expr)));
+
+ expand_expr_stmt (result);
+
+ ffeste_end_stmt_ ();
+ }
+ else
+ {
+ /* In this case, we could probably have used expand_start_elseif
+ instead, saving the need for a fake `else' construct. But,
+ until it's clear that'd improve performance, it's easier this
+ way, since we have to expand_start_else before we get to this
+ test, given the current design. */
+
+ ffeste_end_stmt_ ();
+
+ temp = ffecom_truth_value (ffecom_expr (expr));
+ }
+
+ expand_start_cond (temp, 0);
+
+ /* Increment number of fake `else' constructs introduced. */
+ ffestw_set_ifthen_fake_else (block,
+ ffestw_ifthen_fake_else (block) + 1);
+ }
#else
#error
#endif
}
-/* ffeste_R805 -- ELSE statement
-
- ffeste_R805(name_token);
-
- Make sure ffeste_kind_ identifies an IF block. If not
- NULL, make sure name_token gives the correct name. Implement the ELSE
- of the IF block. */
+/* ELSE statement. */
void
-ffeste_R805 ()
+ffeste_R805 (ffestw block UNUSED)
{
ffeste_check_simple_ ();
@@ -2268,36 +2734,39 @@ ffeste_R805 ()
fputs ("+ ELSE\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
+
expand_start_else ();
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R806 -- End an IF-THEN
-
- ffeste_R806(TRUE); */
+/* END IF statement. */
void
-ffeste_R806 ()
+ffeste_R806 (ffestw block)
{
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputs ("+ END_IF_then\n", dmpout); /* Also see ffeste_shriek_if_. */
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- ffeste_emit_line_note_ ();
- expand_end_cond ();
- clear_momentary ();
+ {
+ int i = ffestw_ifthen_fake_else (block) + 1;
+
+ ffeste_emit_line_note_ ();
+
+ for (; i; --i)
+ {
+ expand_end_cond ();
+
+ ffeste_end_block_ (block);
+ }
+ }
#else
#error
#endif
}
-/* ffeste_R807 -- Logical IF statement
-
- ffeste_R807(expr,expr_token);
-
- Make sure statement is valid here; implement. */
+/* Logical IF statement. */
void
ffeste_R807 (ffebld expr)
@@ -2309,23 +2778,47 @@ ffeste_R807 (ffebld expr)
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+ {
+ tree temp;
- expand_start_cond (ffecom_truth_value (ffecom_expr (expr)), 0);
+ ffeste_emit_line_note_ ();
- ffecom_pop_calltemps ();
- clear_momentary ();
+ ffeste_start_block_ (NULL);
+
+ temp = ffecom_make_tempvar ("if", integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (expr);
+
+ if (ffecom_prepare_end ())
+ {
+ tree result;
+
+ result = ffecom_modify (void_type_node,
+ temp,
+ ffecom_truth_value (ffecom_expr (expr)));
+
+ expand_expr_stmt (result);
+
+ ffeste_end_stmt_ ();
+ }
+ else
+ {
+ ffeste_end_stmt_ ();
+
+ temp = ffecom_truth_value (ffecom_expr (expr));
+ }
+
+ expand_start_cond (temp, 0);
+ }
#else
#error
#endif
}
-/* ffeste_R809 -- SELECT CASE statement
-
- ffeste_R809(construct_name,expr,expr_token);
-
- Make sure statement is valid here; implement. */
+/* SELECT CASE statement. */
void
ffeste_R809 (ffestw block, ffebld expr)
@@ -2337,52 +2830,63 @@ ffeste_R809 (ffestw block, ffebld expr)
ffebld_dump (expr);
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- ffecom_push_calltemps ();
+ ffeste_emit_line_note_ ();
- {
- tree texpr;
+ ffeste_start_block_ (block);
- ffeste_emit_line_note_ ();
+ if ((expr == NULL)
+ || (ffeinfo_basictype (ffebld_info (expr))
+ == FFEINFO_basictypeANY))
+ ffestw_set_select_texpr (block, error_mark_node);
+ else if (ffeinfo_basictype (ffebld_info (expr))
+ == FFEINFO_basictypeCHARACTER)
+ {
+ /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
- if ((expr == NULL)
- || (ffeinfo_basictype (ffebld_info (expr))
- == FFEINFO_basictypeANY))
- {
- ffestw_set_select_texpr (block, error_mark_node);
- clear_momentary ();
- }
- else
- {
- texpr = ffecom_expr (expr);
- if (ffeinfo_basictype (ffebld_info (expr))
- != FFEINFO_basictypeCHARACTER)
- {
- expand_start_case (1, texpr, TREE_TYPE (texpr),
- "SELECT CASE statement");
- ffestw_set_select_texpr (block, texpr);
- ffestw_set_select_break (block, FALSE);
- push_momentary ();
- }
- else
- {
- ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
- FFEBAD_severityFATAL);
- ffebad_here (0, ffestw_line (block), ffestw_col (block));
- ffebad_finish ();
- ffestw_set_select_texpr (block, error_mark_node);
- }
- }
- }
+ ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
+ FFEBAD_severityFATAL);
+ ffebad_here (0, ffestw_line (block), ffestw_col (block));
+ ffebad_finish ();
+ ffestw_set_select_texpr (block, error_mark_node);
+ }
+ else
+ {
+ tree result;
+ tree texpr;
+
+ result = ffecom_make_tempvar ("select", ffecom_type_expr (expr),
+ ffeinfo_size (ffebld_info (expr)),
+ -1);
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (expr);
- ffecom_pop_calltemps ();
+ ffecom_prepare_end ();
+
+ texpr = ffecom_expr (expr);
+
+ assert (TYPE_MAIN_VARIANT (TREE_TYPE (texpr))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (result)));
+
+ texpr = ffecom_modify (void_type_node,
+ result,
+ texpr);
+ expand_expr_stmt (texpr);
+
+ ffeste_end_stmt_ ();
+
+ expand_start_case (1, result, TREE_TYPE (result),
+ "SELECT CASE statement");
+ ffestw_set_select_texpr (block, texpr);
+ ffestw_set_select_break (block, FALSE);
+ }
#else
#error
#endif
}
-/* ffeste_R810 -- CASE statement
-
- ffeste_R810(case_value_range_list,name);
+/* CASE statement.
If casenum is 0, it's CASE DEFAULT. Else it's the case ranges at
the start of the first_stmt list in the select object at the top of
@@ -2440,17 +2944,18 @@ ffeste_R810 (ffestw block, unsigned long casenum)
{
tree texprlow;
tree texprhigh;
- tree tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ tree tlabel;
int pushok;
tree duplicate;
ffeste_emit_line_note_ ();
- if (TREE_CODE (ffestw_select_texpr (block)) == ERROR_MARK)
- {
- clear_momentary ();
- return;
- }
+ if (ffestw_select_texpr (block) == error_mark_node)
+ return;
+
+ /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
+
+ tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
if (ffestw_select_break (block))
expand_exit_something ();
@@ -2490,15 +2995,13 @@ ffeste_R810 (ffestw block, unsigned long casenum)
while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
clear_momentary ();
- } /* ~~~handle character, character*1 */
+ }
#else
#error
#endif
}
-/* ffeste_R811 -- End a SELECT
-
- ffeste_R811(TRUE); */
+/* END SELECT statement. */
void
ffeste_R811 (ffestw block)
@@ -2508,15 +3011,12 @@ ffeste_R811 (ffestw block)
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
- if (TREE_CODE (ffestw_select_texpr (block)) == ERROR_MARK)
- {
- clear_momentary ();
- return;
- }
+ /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
+
+ if (TREE_CODE (ffestw_select_texpr (block)) != ERROR_MARK)
+ expand_end_case (ffestw_select_texpr (block));
- expand_end_case (ffestw_select_texpr (block));
- pop_momentary ();
- clear_momentary (); /* ~~~handle character and character*1 */
+ ffeste_end_block_ (block);
#else
#error
#endif
@@ -2559,9 +3059,6 @@ ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
-
- /* Start the DO loop. */
ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
var,
@@ -2569,19 +3066,13 @@ ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
end, end_token,
incr, incr_token,
"Iterative DO loop");
-
- ffecom_pop_calltemps ();
}
#else
#error
#endif
}
-/* ffeste_R819B -- DO WHILE statement
-
- ffeste_R819B(construct_name,label_token,expr,expr_token);
-
- Make sure statement is valid here; implement. */
+/* DO WHILE statement. */
void
ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
@@ -2597,32 +3088,54 @@ ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
fputs (")\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
{
+ tree result;
+
ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
- ffestw_set_do_hook (block, expand_start_loop (1));
- ffestw_set_do_tvar (block, 0); /* Means DO WHILE vs. iter DO. */
- if (expr != NULL)
- expand_exit_loop_if_false (0, ffecom_truth_value (ffecom_expr (expr)));
+ ffeste_start_block_ (block);
- ffecom_pop_calltemps ();
- clear_momentary ();
+ if (expr)
+ {
+ struct nesting *loop;
+ tree mod;
+
+ result = ffecom_make_tempvar ("dowhile", integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
+ loop = expand_start_loop (1);
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (expr);
+
+ ffecom_prepare_end ();
+
+ mod = ffecom_modify (void_type_node,
+ result,
+ ffecom_truth_value (ffecom_expr (expr)));
+ expand_expr_stmt (mod);
+
+ ffeste_end_stmt_ ();
+
+ ffestw_set_do_hook (block, loop);
+ expand_exit_loop_if_false (0, result);
+ }
+ else
+ ffestw_set_do_hook (block, expand_start_loop (1));
+
+ ffestw_set_do_tvar (block, NULL_TREE);
}
#else
#error
#endif
}
-/* ffeste_R825 -- END DO statement
+/* END DO statement.
- ffeste_R825(name_token);
-
- Make sure ffeste_kind_ identifies a DO block. If not
- NULL, make sure name_token gives the correct name. Do whatever
- is specific to seeing END DO with a DO-target label definition on it,
- where the END DO is really treated as a CONTINUE (i.e. generate th
- same code you would for CONTINUE). ffeste_do handles the actual
- generation of end-loop code. */
+ This is the MIL-STD 1753 END DO. It's syntactic sugar, similar to
+ CONTINUE (except that it has to have a label that is the target of
+ one or more iterative DO statement), not the Fortran-90 structured
+ END DO, which is handled elsewhere, as is the actual mechanism of
+ ending an iterative DO statement, even one that ends at a label. */
void
ffeste_R825 ()
@@ -2633,17 +3146,14 @@ ffeste_R825 ()
fputs ("+ END_DO_sugar\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
+
emit_nop ();
#else
#error
#endif
}
-/* ffeste_R834 -- CYCLE statement
-
- ffeste_R834(name_token);
-
- Handle a CYCLE within a loop. */
+/* CYCLE statement. */
void
ffeste_R834 (ffestw block)
@@ -2654,18 +3164,14 @@ ffeste_R834 (ffestw block)
fprintf (dmpout, "+ CYCLE block #%lu\n", ffestw_blocknum (block));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
+
expand_continue_loop (ffestw_do_hook (block));
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R835 -- EXIT statement
-
- ffeste_R835(name_token);
-
- Handle a EXIT within a loop. */
+/* EXIT statement. */
void
ffeste_R835 (ffestw block)
@@ -2676,19 +3182,14 @@ ffeste_R835 (ffestw block)
fprintf (dmpout, "+ EXIT block #%lu\n", ffestw_blocknum (block));
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
+
expand_exit_loop (ffestw_do_hook (block));
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R836 -- GOTO statement
-
- ffeste_R836(label);
-
- Make sure label_token identifies a valid label for a GOTO. Update
- that label's info to indicate it is the target of a GOTO. */
+/* GOTO statement. */
void
ffeste_R836 (ffelab label)
@@ -2702,13 +3203,13 @@ ffeste_R836 (ffelab label)
tree glabel;
ffeste_emit_line_note_ ();
+
glabel = ffecom_lookup_label (label);
if ((glabel != NULL_TREE)
&& (TREE_CODE (glabel) != ERROR_MARK))
{
- TREE_USED (glabel) = 1;
expand_goto (glabel);
- clear_momentary ();
+ TREE_USED (glabel) = 1;
}
}
#else
@@ -2716,12 +3217,7 @@ ffeste_R836 (ffelab label)
#endif
}
-/* ffeste_R837 -- Computed GOTO statement
-
- ffeste_R837(labels,count,expr);
-
- Make sure label_list identifies valid labels for a GOTO. Update
- each label's info to indicate it is the target of a GOTO. */
+/* Computed GOTO statement. */
void
ffeste_R837 (ffelab *labels, int count, ffebld expr)
@@ -2750,12 +3246,17 @@ ffeste_R837 (ffelab *labels, int count, ffebld expr)
tree duplicate;
ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (expr);
+
+ ffecom_prepare_end ();
texpr = ffecom_expr (expr);
+
expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
- push_momentary (); /* In case of lots of labels, keep clearing
- them out. */
+
for (i = 0; i < count; ++i)
{
value = build_int_2 (i + 1, 0);
@@ -2763,33 +3264,25 @@ ffeste_R837 (ffelab *labels, int count, ffebld expr)
pushok = pushcase (value, convert, tlabel, &duplicate);
assert (pushok == 0);
+
tlabel = ffecom_lookup_label (labels[i]);
if ((tlabel == NULL_TREE)
|| (TREE_CODE (tlabel) == ERROR_MARK))
continue;
- TREE_USED (tlabel) = 1;
+
expand_goto (tlabel);
- clear_momentary ();
+ TREE_USED (tlabel) = 1;
}
- pop_momentary ();
expand_end_case (texpr);
- ffecom_pop_calltemps ();
- clear_momentary ();
+ ffeste_end_stmt_ ();
}
#else
#error
#endif
}
-/* ffeste_R838 -- ASSIGN statement
-
- ffeste_R838(label_token,target_variable,target_token);
-
- Make sure label_token identifies a valid label for an assignment. Update
- that label's info to indicate it is the source of an assignment. Update
- target_variable's info to indicate it is the target the assignment of that
- label. */
+/* ASSIGN statement. */
void
ffeste_R838 (ffelab label, ffebld target)
@@ -2807,7 +3300,9 @@ ffeste_R838 (ffelab label, ffebld target)
tree target_tree;
ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+
+ /* No need to call ffeste_start_stmt_(), as the sorts of expressions
+ seen here should never require use of temporaries. */
label_tree = ffecom_lookup_label (label);
if ((label_tree != NULL_TREE)
@@ -2817,31 +3312,28 @@ ffeste_R838 (ffelab label, ffebld target)
build_pointer_type (void_type_node),
label_tree);
TREE_CONSTANT (label_tree) = 1;
+
target_tree = ffecom_expr_assign_w (target);
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
< GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
error ("ASSIGN to variable that is too small");
+
label_tree = convert (TREE_TYPE (target_tree), label_tree);
+
expr_tree = ffecom_modify (void_type_node,
target_tree,
label_tree);
expand_expr_stmt (expr_tree);
+
clear_momentary ();
}
-
- ffecom_pop_calltemps ();
}
#else
#error
#endif
}
-/* ffeste_R839 -- Assigned GOTO statement
-
- ffeste_R839(target,target_token,label_list);
-
- Make sure label_list identifies valid labels for a GOTO. Update
- each label's info to indicate it is the target of a GOTO. */
+/* Assigned GOTO statement. */
void
ffeste_R839 (ffebld target)
@@ -2857,15 +3349,17 @@ ffeste_R839 (ffebld target)
tree t;
ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+
+ /* No need to call ffeste_start_stmt_(), as the sorts of expressions
+ seen here should never require use of temporaries. */
t = ffecom_expr_assign (target);
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
< GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
error ("ASSIGNed GOTO target variable is too small");
+
expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
- ffecom_pop_calltemps ();
clear_momentary ();
}
#else
@@ -2873,11 +3367,7 @@ ffeste_R839 (ffebld target)
#endif
}
-/* ffeste_R840 -- Arithmetic IF statement
-
- ffeste_R840(expr,expr_token,neg,zero,pos);
-
- Make sure the labels are valid; implement. */
+/* Arithmetic IF statement. */
void
ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
@@ -2896,6 +3386,8 @@ ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
tree gpos = ffecom_lookup_label (pos);
tree texpr;
+ ffeste_emit_line_note_ ();
+
if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
return;
if ((TREE_CODE (gneg) == ERROR_MARK)
@@ -2903,15 +3395,19 @@ ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
|| (TREE_CODE (gpos) == ERROR_MARK))
return;
- ffecom_push_calltemps ();
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_expr (expr);
+
+ ffecom_prepare_end ();
if (neg == zero)
{
if (neg == pos)
expand_goto (gzero);
else
- { /* IF (expr.LE.0) THEN GOTO neg/zero ELSE
- GOTO pos. */
+ {
+ /* IF (expr.LE.0) THEN GOTO neg/zero ELSE GOTO pos. */
texpr = ffecom_expr (expr);
texpr = ffecom_2 (LE_EXPR, integer_type_node,
texpr,
@@ -2925,8 +3421,8 @@ ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
}
}
else if (neg == pos)
- { /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO
- zero. */
+ {
+ /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO zero. */
texpr = ffecom_expr (expr);
texpr = ffecom_2 (NE_EXPR, integer_type_node,
texpr,
@@ -2939,8 +3435,8 @@ ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
expand_end_cond ();
}
else if (zero == pos)
- { /* IF (expr.GE.0) THEN GOTO zero/pos ELSE
- GOTO neg. */
+ {
+ /* IF (expr.GE.0) THEN GOTO zero/pos ELSE GOTO neg. */
texpr = ffecom_expr (expr);
texpr = ffecom_2 (GE_EXPR, integer_type_node,
texpr,
@@ -2953,10 +3449,11 @@ ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
expand_end_cond ();
}
else
- { /* Use a SAVE_EXPR in combo with:
- IF (expr.LT.0) THEN GOTO neg
- ELSEIF (expr.GT.0) THEN GOTO pos
- ELSE GOTO zero. */
+ {
+ /* Use a SAVE_EXPR in combo with:
+ IF (expr.LT.0) THEN GOTO neg
+ ELSEIF (expr.GT.0) THEN GOTO pos
+ ELSE GOTO zero. */
tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
texpr = ffecom_2 (LT_EXPR, integer_type_node,
@@ -2975,19 +3472,15 @@ ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
expand_goto (gzero);
expand_end_cond ();
}
- ffeste_emit_line_note_ ();
- ffecom_pop_calltemps ();
- clear_momentary ();
+ ffeste_end_stmt_ ();
}
#else
#error
#endif
}
-/* ffeste_R841 -- CONTINUE statement
-
- ffeste_R841(); */
+/* CONTINUE statement. */
void
ffeste_R841 ()
@@ -2998,15 +3491,14 @@ ffeste_R841 ()
fputs ("+ CONTINUE\n", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
ffeste_emit_line_note_ ();
+
emit_nop ();
#else
#error
#endif
}
-/* ffeste_R842 -- STOP statement
-
- ffeste_R842(expr); */
+/* STOP statement. */
void
ffeste_R842 (ffebld expr)
@@ -3030,6 +3522,7 @@ ffeste_R842 (ffebld expr)
ffelexToken msg;
ffeste_emit_line_note_ ();
+
if ((expr == NULL)
|| (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeANY))
@@ -3073,12 +3566,16 @@ ffeste_R842 (ffebld expr)
== FFEINFO_kindtypeCHARACTERDEFAULT);
}
- ffecom_push_calltemps ();
+ /* No need to call ffeste_start_stmt_(), as the sorts of expressions
+ seen here should never require use of temporaries. */
+
callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
- ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
- ffecom_pop_calltemps ();
+ ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
+ NULL_TREE);
TREE_SIDE_EFFECTS (callit) = 1;
+
expand_expr_stmt (callit);
+
clear_momentary ();
}
#else
@@ -3086,12 +3583,7 @@ ffeste_R842 (ffebld expr)
#endif
}
-/* ffeste_R843 -- PAUSE statement
-
- ffeste_R843(expr,expr_token);
-
- Make sure statement is valid here; implement. expr and expr_token are
- both NULL if there was no expression. */
+/* PAUSE statement. */
void
ffeste_R843 (ffebld expr)
@@ -3115,6 +3607,7 @@ ffeste_R843 (ffebld expr)
ffelexToken msg;
ffeste_emit_line_note_ ();
+
if ((expr == NULL)
|| (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeANY))
@@ -3158,12 +3651,16 @@ ffeste_R843 (ffebld expr)
== FFEINFO_kindtypeCHARACTERDEFAULT);
}
- ffecom_push_calltemps ();
+ /* No need to call ffeste_start_stmt_(), as the sorts of expressions
+ seen here should never require use of temporaries. */
+
callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
- ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
- ffecom_pop_calltemps ();
+ ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
+ NULL_TREE);
TREE_SIDE_EFFECTS (callit) = 1;
+
expand_expr_stmt (callit);
+
clear_momentary ();
}
#if 0 /* Old approach for phantom g77 run-time
@@ -3172,28 +3669,25 @@ ffeste_R843 (ffebld expr)
tree callit;
ffeste_emit_line_note_ ();
+
if (expr == NULL)
- callit = ffecom_call_gfrt (FFECOM_gfrtPAUSENIL, NULL_TREE);
+ callit = ffecom_call_gfrt (FFECOM_gfrtPAUSENIL, NULL_TREE, NULL_TREE);
else if (ffeinfo_basictype (ffebld_info (expr))
== FFEINFO_basictypeINTEGER)
- {
- ffecom_push_calltemps ();
- callit = ffecom_call_gfrt (FFECOM_gfrtPAUSEINT,
- ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
- ffecom_pop_calltemps ();
- }
+ callit = ffecom_call_gfrt (FFECOM_gfrtPAUSEINT,
+ ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
+ NULL_TREE);
+ else if (ffeinfo_basictype (ffebld_info (expr))
+ == FFEINFO_basictypeCHARACTER)
+ callit = ffecom_call_gfrt (FFECOM_gfrtPAUSECHAR,
+ ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
+ NULL_TREE);
else
- {
- if (ffeinfo_basictype (ffebld_info (expr))
- != FFEINFO_basictypeCHARACTER)
- break;
- ffecom_push_calltemps ();
- callit = ffecom_call_gfrt (FFECOM_gfrtPAUSECHAR,
- ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)));
- ffecom_pop_calltemps ();
- }
+ abort ();
TREE_SIDE_EFFECTS (callit) = 1;
+
expand_expr_stmt (callit);
+
clear_momentary ();
}
#endif
@@ -3202,11 +3696,7 @@ ffeste_R843 (ffebld expr)
#endif
}
-/* ffeste_R904 -- OPEN statement
-
- ffeste_R904();
-
- Make sure an OPEN is valid in the current context, and implement it. */
+/* OPEN statement. */
void
ffeste_R904 (ffestpOpenStmt *info)
@@ -3251,23 +3741,16 @@ ffeste_R904 (ffestpOpenStmt *info)
bool iostat;
bool errl;
-#define specified(something) (info->open_spec[something].kw_or_val_present)
-
ffeste_emit_line_note_ ();
+#define specified(something) (info->open_spec[something].kw_or_val_present)
+
iostat = specified (FFESTP_openixIOSTAT);
errl = specified (FFESTP_openixERR);
- ffecom_push_calltemps ();
+#undef specified
- args = ffeste_io_olist_ (errl || iostat,
- info->open_spec[FFESTP_openixUNIT].u.expr,
- &info->open_spec[FFESTP_openixFILE],
- &info->open_spec[FFESTP_openixSTATUS],
- &info->open_spec[FFESTP_openixACCESS],
- &info->open_spec[FFESTP_openixFORM],
- &info->open_spec[FFESTP_openixRECL],
- &info->open_spec[FFESTP_openixBLANK]);
+ ffeste_start_stmt_ ();
if (errl)
{
@@ -3288,31 +3771,48 @@ ffeste_R904 (ffestpOpenStmt *info)
}
if (iostat)
- { /* IOSTAT= */
+ {
+ /* Have IOSTAT= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->open_spec[FFESTP_openixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
- { /* no IOSTAT= but ERR= */
+ {
+ /* Have no IOSTAT= but have ERR=. */
+
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
- = ffecom_push_tempvar (ffecom_integer_type_node,
- FFETARGET_charactersizeNONE, -1, FALSE);
+ = ffecom_make_tempvar ("open", ffecom_integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
}
else
- { /* no IOSTAT=, or ERR= */
+ {
+ /* No IOSTAT= or ERR= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
+ /* Now prescan, then convert, all the arguments. */
+
+ args = ffeste_io_olist_ (errl || iostat,
+ info->open_spec[FFESTP_openixUNIT].u.expr,
+ &info->open_spec[FFESTP_openixFILE],
+ &info->open_spec[FFESTP_openixSTATUS],
+ &info->open_spec[FFESTP_openixACCESS],
+ &info->open_spec[FFESTP_openixFORM],
+ &info->open_spec[FFESTP_openixRECL],
+ &info->open_spec[FFESTP_openixBLANK]);
+
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
- ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args),
- !ffeste_io_abort_is_temp_);
+ ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args, NULL_TREE),
+ ! ffeste_io_abort_is_temp_);
- /* If we've got a temp label, generate its code here. */
+ /* If we've got a temp label, generate its code here. */
if (ffeste_io_abort_is_temp_)
{
@@ -3323,27 +3823,14 @@ ffeste_R904 (ffestpOpenStmt *info)
assert (ffeste_io_err_ == NULL_TREE);
}
- /* If we've got a temp iostat, pop the temp. */
-
- if (ffeste_io_iostat_is_temp_)
- ffecom_pop_tempvar (ffeste_io_iostat_);
-
- ffecom_pop_calltemps ();
-
-#undef specified
+ ffeste_end_stmt_ ();
}
-
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R907 -- CLOSE statement
-
- ffeste_R907();
-
- Make sure a CLOSE is valid in the current context, and implement it. */
+/* CLOSE statement. */
void
ffeste_R907 (ffestpCloseStmt *info)
@@ -3363,18 +3850,16 @@ ffeste_R907 (ffestpCloseStmt *info)
bool iostat;
bool errl;
-#define specified(something) (info->close_spec[something].kw_or_val_present)
-
ffeste_emit_line_note_ ();
+#define specified(something) (info->close_spec[something].kw_or_val_present)
+
iostat = specified (FFESTP_closeixIOSTAT);
errl = specified (FFESTP_closeixERR);
- ffecom_push_calltemps ();
+#undef specified
- args = ffeste_io_cllist_ (errl || iostat,
- info->close_spec[FFESTP_closeixUNIT].u.expr,
- &info->close_spec[FFESTP_closeixSTATUS]);
+ ffeste_start_stmt_ ();
if (errl)
{
@@ -3395,29 +3880,41 @@ ffeste_R907 (ffestpCloseStmt *info)
}
if (iostat)
- { /* IOSTAT= */
+ {
+ /* Have IOSTAT= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->close_spec[FFESTP_closeixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
- { /* no IOSTAT= but ERR= */
+ {
+ /* Have no IOSTAT= but have ERR=. */
+
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
- = ffecom_push_tempvar (ffecom_integer_type_node,
- FFETARGET_charactersizeNONE, -1, FALSE);
+ = ffecom_make_tempvar ("close", ffecom_integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
}
else
- { /* no IOSTAT=, or ERR= */
+ {
+ /* No IOSTAT= or ERR= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
+ /* Now prescan, then convert, all the arguments. */
+
+ args = ffeste_io_cllist_ (errl || iostat,
+ info->close_spec[FFESTP_closeixUNIT].u.expr,
+ &info->close_spec[FFESTP_closeixSTATUS]);
+
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
- ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args),
- !ffeste_io_abort_is_temp_);
+ ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args, NULL_TREE),
+ ! ffeste_io_abort_is_temp_);
/* If we've got a temp label, generate its code here. */
@@ -3430,28 +3927,14 @@ ffeste_R907 (ffestpCloseStmt *info)
assert (ffeste_io_err_ == NULL_TREE);
}
- /* If we've got a temp iostat, pop the temp. */
-
- if (ffeste_io_iostat_is_temp_)
- ffecom_pop_tempvar (ffeste_io_iostat_);
-
- ffecom_pop_calltemps ();
-
-#undef specified
+ ffeste_end_stmt_ ();
}
-
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R909_start -- READ(...) statement list begin
-
- ffeste_R909_start(FALSE);
-
- Verify that READ is valid here, and begin accepting items in the
- list. */
+/* READ(...) statement -- start. */
void
ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
@@ -3527,12 +4010,8 @@ ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
-#define specified(something) (info->read_spec[something].kw_or_val_present)
-
ffeste_emit_line_note_ ();
- /* Do the real work. */
-
{
ffecomGfrt start;
ffecomGfrt end;
@@ -3542,10 +4021,9 @@ ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
bool endl;
/* First determine the start, per-item, and end run-time functions to
- call. The per-item function is picked by choosing an ffeste functio
+ call. The per-item function is picked by choosing an ffeste function
to call to handle a given item; it knows how to generate a call to the
- appropriate run-time function, and is called an "io driver". It
- handles the implied-DO construct, for example. */
+ appropriate run-time function, and is called an "I/O driver". */
switch (format)
{
@@ -3598,45 +4076,34 @@ ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
}
ffeste_io_endgfrt_ = end;
+#define specified(something) (info->read_spec[something].kw_or_val_present)
+
iostat = specified (FFESTP_readixIOSTAT);
errl = specified (FFESTP_readixERR);
endl = specified (FFESTP_readixEND);
- ffecom_push_calltemps ();
+#undef specified
- if (unit == FFESTV_unitCHAREXPR)
- {
- cilist = ffeste_io_icilist_ (errl || iostat,
- info->read_spec[FFESTP_readixUNIT].u.expr,
- endl || iostat, format,
- &info->read_spec[FFESTP_readixFORMAT]);
- }
- else
- {
- cilist = ffeste_io_cilist_ (errl || iostat, unit,
- info->read_spec[FFESTP_readixUNIT].u.expr,
- 5, endl || iostat, format,
- &info->read_spec[FFESTP_readixFORMAT],
- rec,
- info->read_spec[FFESTP_readixREC].u.expr);
- }
+ ffeste_start_stmt_ ();
if (errl)
- { /* ERR= */
+ {
+ /* Have ERR= specification. */
+
ffeste_io_err_
- = ffecom_lookup_label
- (info->read_spec[FFESTP_readixERR].u.label);
+ = ffecom_lookup_label (info->read_spec[FFESTP_readixERR].u.label);
if (endl)
- { /* ERR= END= */
+ {
+ /* Have both ERR= and END=. Need a temp label to handle both. */
ffeste_io_end_
- = ffecom_lookup_label
- (info->read_spec[FFESTP_readixEND].u.label);
+ = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
ffeste_io_abort_is_temp_ = TRUE;
ffeste_io_abort_ = ffecom_temp_label ();
}
else
- { /* ERR= but no END= */
+ {
+ /* Have ERR= but no END=. */
ffeste_io_end_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
@@ -3645,20 +4112,24 @@ ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
}
}
else
- { /* no ERR= */
+ {
+ /* No ERR= specification. */
+
ffeste_io_err_ = NULL_TREE;
if (endl)
- { /* END= but no ERR= */
+ {
+ /* Have END= but no ERR=. */
ffeste_io_end_
- = ffecom_lookup_label
- (info->read_spec[FFESTP_readixEND].u.label);
+ = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
else
ffeste_io_abort_ = ffeste_io_end_;
}
else
- { /* no ERR= or END= */
+ {
+ /* Have no ERR= or END=. */
+
ffeste_io_end_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
ffeste_io_abort_ = ffecom_temp_label ();
@@ -3668,46 +4139,59 @@ ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
}
if (iostat)
- { /* IOSTAT= */
+ {
+ /* Have IOSTAT= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
- ffeste_io_iostat_ = ffecom_expr
- (info->read_spec[FFESTP_readixIOSTAT].u.expr);
+ ffeste_io_iostat_
+ = ffecom_expr (info->read_spec[FFESTP_readixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
- { /* no IOSTAT= but ERR= or END= or both */
+ {
+ /* Have no IOSTAT= but have ERR= and/or END=. */
+
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
- = ffecom_push_tempvar (ffecom_integer_type_node,
- FFETARGET_charactersizeNONE, -1, FALSE);
+ = ffecom_make_tempvar ("read", ffecom_integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
}
else
- { /* no IOSTAT=, ERR=, or END= */
+ {
+ /* No IOSTAT=, ERR=, or END= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
+ /* Now prescan, then convert, all the arguments. */
+
+ if (unit == FFESTV_unitCHAREXPR)
+ cilist = ffeste_io_icilist_ (errl || iostat,
+ info->read_spec[FFESTP_readixUNIT].u.expr,
+ endl || iostat, format,
+ &info->read_spec[FFESTP_readixFORMAT]);
+ else
+ cilist = ffeste_io_cilist_ (errl || iostat, unit,
+ info->read_spec[FFESTP_readixUNIT].u.expr,
+ 5, endl || iostat, format,
+ &info->read_spec[FFESTP_readixFORMAT],
+ rec,
+ info->read_spec[FFESTP_readixREC].u.expr);
+
/* If there is no end function, then there are no item functions (i.e.
it's a NAMELIST), and vice versa by the way. In this situation, don't
generate the "if (iostat != 0) goto label;" if the label is temp abort
label, since we're gonna fall through to there anyway. */
- ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
- !ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
+ ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
+ (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
}
-
-#undef specified
-
- push_momentary ();
#else
#error
#endif
}
-/* ffeste_R909_item -- READ statement i/o item
-
- ffeste_R909_item(expr,expr_token);
-
- Implement output-list expression. */
+/* READ statement -- I/O item. */
void
ffeste_R909_item (ffebld expr, ffelexToken expr_token)
@@ -3720,27 +4204,35 @@ ffeste_R909_item (ffebld expr, ffelexToken expr_token)
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
if (expr == NULL)
return;
+
+ /* Strip parens off items such as in "READ *,(A)". This is really a bug
+ in the user's code, but I've been told lots of code does this. */
while (ffebld_op (expr) == FFEBLD_opPAREN)
- expr = ffebld_left (expr); /* "READ *,(A)" -- really a bug in the user's
- code, but I've been told lots of code does
- this (blech)! */
+ expr = ffebld_left (expr);
+
if (ffebld_op (expr) == FFEBLD_opANY)
return;
+
if (ffebld_op (expr) == FFEBLD_opIMPDO)
ffeste_io_impdo_ (expr, expr_token);
else
- ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
- clear_momentary ();
+ {
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_arg_ptr_to_expr (expr);
+
+ ffecom_prepare_end ();
+
+ ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
+
+ ffeste_end_stmt_ ();
+ }
#else
#error
#endif
}
-/* ffeste_R909_finish -- READ statement list complete
-
- ffeste_R909_finish();
-
- Just wrap up any local activities. */
+/* READ statement -- end. */
void
ffeste_R909_finish ()
@@ -3754,73 +4246,56 @@ ffeste_R909_finish ()
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
- {
- if (ffeste_io_endgfrt_ != FFECOM_gfrt)
- ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
- !ffeste_io_abort_is_temp_);
-
- clear_momentary ();
- pop_momentary ();
-
- /* If we've got a temp label, generate its code here and have it fan out
- to the END= or ERR= label as appropriate. */
+ if (ffeste_io_endgfrt_ != FFECOM_gfrt)
+ ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
+ NULL_TREE),
+ ! ffeste_io_abort_is_temp_);
- if (ffeste_io_abort_is_temp_)
- {
- DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
- emit_nop ();
- expand_label (ffeste_io_abort_);
+ /* If we've got a temp label, generate its code here and have it fan out
+ to the END= or ERR= label as appropriate. */
- /* if (iostat<0) goto end_label; */
-
- if ((ffeste_io_end_ != NULL_TREE)
- && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
- {
- expand_start_cond (ffecom_truth_value
- (ffecom_2 (LT_EXPR, integer_type_node,
- ffeste_io_iostat_,
- ffecom_integer_zero_node)),
- 0);
- expand_goto (ffeste_io_end_);
- expand_end_cond ();
- }
-
- /* if (iostat>0) goto err_label; */
-
- if ((ffeste_io_err_ != NULL_TREE)
- && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
- {
- expand_start_cond (ffecom_truth_value
- (ffecom_2 (GT_EXPR, integer_type_node,
- ffeste_io_iostat_,
- ffecom_integer_zero_node)),
- 0);
- expand_goto (ffeste_io_err_);
- expand_end_cond ();
- }
+ if (ffeste_io_abort_is_temp_)
+ {
+ DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
+ emit_nop ();
+ expand_label (ffeste_io_abort_);
- }
+ /* "if (iostat<0) goto end_label;". */
- /* If we've got a temp iostat, pop the temp. */
+ if ((ffeste_io_end_ != NULL_TREE)
+ && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
+ {
+ expand_start_cond (ffecom_truth_value
+ (ffecom_2 (LT_EXPR, integer_type_node,
+ ffeste_io_iostat_,
+ ffecom_integer_zero_node)),
+ 0);
+ expand_goto (ffeste_io_end_);
+ expand_end_cond ();
+ }
- if (ffeste_io_iostat_is_temp_)
- ffecom_pop_tempvar (ffeste_io_iostat_);
+ /* "if (iostat>0) goto err_label;". */
- ffecom_pop_calltemps ();
+ if ((ffeste_io_err_ != NULL_TREE)
+ && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
+ {
+ expand_start_cond (ffecom_truth_value
+ (ffecom_2 (GT_EXPR, integer_type_node,
+ ffeste_io_iostat_,
+ ffecom_integer_zero_node)),
+ 0);
+ expand_goto (ffeste_io_err_);
+ expand_end_cond ();
+ }
+ }
- clear_momentary ();
- }
+ ffeste_end_stmt_ ();
#else
#error
#endif
}
-/* ffeste_R910_start -- WRITE(...) statement list begin
-
- ffeste_R910_start();
-
- Verify that WRITE is valid here, and begin accepting items in the
- list. */
+/* WRITE statement -- start. */
void
ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
@@ -3874,12 +4349,8 @@ ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
-#define specified(something) (info->write_spec[something].kw_or_val_present)
-
ffeste_emit_line_note_ ();
- /* Do the real work. */
-
{
ffecomGfrt start;
ffecomGfrt end;
@@ -3888,10 +4359,9 @@ ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
bool errl;
/* First determine the start, per-item, and end run-time functions to
- call. The per-item function is picked by choosing an ffeste functio
+ call. The per-item function is picked by choosing an ffeste function
to call to handle a given item; it knows how to generate a call to the
- appropriate run-time function, and is called an "io driver". It
- handles the implied-DO construct, for example. */
+ appropriate run-time function, and is called an "I/O driver". */
switch (format)
{
@@ -3936,32 +4406,21 @@ ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
}
ffeste_io_endgfrt_ = end;
+#define specified(something) (info->write_spec[something].kw_or_val_present)
+
iostat = specified (FFESTP_writeixIOSTAT);
errl = specified (FFESTP_writeixERR);
- ffecom_push_calltemps ();
+#undef specified
- if (unit == FFESTV_unitCHAREXPR)
- {
- cilist = ffeste_io_icilist_ (errl || iostat,
- info->write_spec[FFESTP_writeixUNIT].u.expr,
- FALSE, format,
- &info->write_spec[FFESTP_writeixFORMAT]);
- }
- else
- {
- cilist = ffeste_io_cilist_ (errl || iostat, unit,
- info->write_spec[FFESTP_writeixUNIT].u.expr,
- 6, FALSE, format,
- &info->write_spec[FFESTP_writeixFORMAT],
- rec,
- info->write_spec[FFESTP_writeixREC].u.expr);
- }
+ ffeste_start_stmt_ ();
ffeste_io_end_ = NULL_TREE;
if (errl)
- { /* ERR= */
+ {
+ /* Have ERR= specification. */
+
ffeste_io_err_
= ffeste_io_abort_
= ffecom_lookup_label
@@ -3969,7 +4428,9 @@ ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
ffeste_io_abort_is_temp_ = FALSE;
}
else
- { /* no ERR= */
+ {
+ /* No ERR= specification. */
+
ffeste_io_err_ = NULL_TREE;
if ((ffeste_io_abort_is_temp_ = iostat))
@@ -3979,46 +4440,59 @@ ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
}
if (iostat)
- { /* IOSTAT= */
+ {
+ /* Have IOSTAT= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->write_spec[FFESTP_writeixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
- { /* no IOSTAT= but ERR= */
+ {
+ /* Have no IOSTAT= but have ERR=. */
+
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
- = ffecom_push_tempvar (ffecom_integer_type_node,
- FFETARGET_charactersizeNONE, -1, FALSE);
+ = ffecom_make_tempvar ("write", ffecom_integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
}
else
- { /* no IOSTAT=, or ERR= */
+ {
+ /* No IOSTAT= or ERR= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
+ /* Now prescan, then convert, all the arguments. */
+
+ if (unit == FFESTV_unitCHAREXPR)
+ cilist = ffeste_io_icilist_ (errl || iostat,
+ info->write_spec[FFESTP_writeixUNIT].u.expr,
+ FALSE, format,
+ &info->write_spec[FFESTP_writeixFORMAT]);
+ else
+ cilist = ffeste_io_cilist_ (errl || iostat, unit,
+ info->write_spec[FFESTP_writeixUNIT].u.expr,
+ 6, FALSE, format,
+ &info->write_spec[FFESTP_writeixFORMAT],
+ rec,
+ info->write_spec[FFESTP_writeixREC].u.expr);
+
/* If there is no end function, then there are no item functions (i.e.
it's a NAMELIST), and vice versa by the way. In this situation, don't
generate the "if (iostat != 0) goto label;" if the label is temp abort
label, since we're gonna fall through to there anyway. */
- ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
- !ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
+ ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
+ (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
}
-
-#undef specified
-
- push_momentary ();
#else
#error
#endif
}
-/* ffeste_R910_item -- WRITE statement i/o item
-
- ffeste_R910_item(expr,expr_token);
-
- Implement output-list expression. */
+/* WRITE statement -- I/O item. */
void
ffeste_R910_item (ffebld expr, ffelexToken expr_token)
@@ -4031,23 +4505,30 @@ ffeste_R910_item (ffebld expr, ffelexToken expr_token)
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
if (expr == NULL)
return;
+
if (ffebld_op (expr) == FFEBLD_opANY)
return;
+
if (ffebld_op (expr) == FFEBLD_opIMPDO)
ffeste_io_impdo_ (expr, expr_token);
else
- ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
- clear_momentary ();
+ {
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_arg_ptr_to_expr (expr);
+
+ ffecom_prepare_end ();
+
+ ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
+
+ ffeste_end_stmt_ ();
+ }
#else
#error
#endif
}
-/* ffeste_R910_finish -- WRITE statement list complete
-
- ffeste_R910_finish();
-
- Just wrap up any local activities. */
+/* WRITE statement -- end. */
void
ffeste_R910_finish ()
@@ -4061,45 +4542,29 @@ ffeste_R910_finish ()
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
- {
- if (ffeste_io_endgfrt_ != FFECOM_gfrt)
- ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
- !ffeste_io_abort_is_temp_);
-
- clear_momentary ();
- pop_momentary ();
-
- /* If we've got a temp label, generate its code here. */
-
- if (ffeste_io_abort_is_temp_)
- {
- DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
- emit_nop ();
- expand_label (ffeste_io_abort_);
-
- assert (ffeste_io_err_ == NULL_TREE);
- }
+ if (ffeste_io_endgfrt_ != FFECOM_gfrt)
+ ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
+ NULL_TREE),
+ ! ffeste_io_abort_is_temp_);
- /* If we've got a temp iostat, pop the temp. */
+ /* If we've got a temp label, generate its code here. */
- if (ffeste_io_iostat_is_temp_)
- ffecom_pop_tempvar (ffeste_io_iostat_);
+ if (ffeste_io_abort_is_temp_)
+ {
+ DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
+ emit_nop ();
+ expand_label (ffeste_io_abort_);
- ffecom_pop_calltemps ();
+ assert (ffeste_io_err_ == NULL_TREE);
+ }
- clear_momentary ();
- }
+ ffeste_end_stmt_ ();
#else
#error
#endif
}
-/* ffeste_R911_start -- PRINT statement list begin
-
- ffeste_R911_start();
-
- Verify that PRINT is valid here, and begin accepting items in the
- list. */
+/* PRINT statement -- start. */
void
ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
@@ -4132,18 +4597,15 @@ ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
ffeste_emit_line_note_ ();
- /* Do the real work. */
-
{
ffecomGfrt start;
ffecomGfrt end;
tree cilist;
/* First determine the start, per-item, and end run-time functions to
- call. The per-item function is picked by choosing an ffeste functio
+ call. The per-item function is picked by choosing an ffeste function
to call to handle a given item; it knows how to generate a call to the
- appropriate run-time function, and is called an "io driver". It
- handles the implied-DO construct, for example. */
+ appropriate run-time function, and is called an "I/O driver". */
switch (format)
{
@@ -4172,10 +4634,7 @@ ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
}
ffeste_io_endgfrt_ = end;
- ffecom_push_calltemps ();
-
- cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
- &info->print_spec[FFESTP_printixFORMAT], FALSE, NULL);
+ ffeste_start_stmt_ ();
ffeste_io_end_ = NULL_TREE;
ffeste_io_err_ = NULL_TREE;
@@ -4184,26 +4643,25 @@ ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
+ /* Now prescan, then convert, all the arguments. */
+
+ cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
+ &info->print_spec[FFESTP_printixFORMAT], FALSE, NULL);
+
/* If there is no end function, then there are no item functions (i.e.
it's a NAMELIST), and vice versa by the way. In this situation, don't
generate the "if (iostat != 0) goto label;" if the label is temp abort
label, since we're gonna fall through to there anyway. */
- ffeste_io_call_ (ffecom_call_gfrt (start, cilist),
- !ffeste_io_abort_is_temp_ || (end != FFECOM_gfrt));
+ ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
+ (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
}
-
- push_momentary ();
#else
#error
#endif
}
-/* ffeste_R911_item -- PRINT statement i/o item
-
- ffeste_R911_item(expr,expr_token);
-
- Implement output-list expression. */
+/* PRINT statement -- I/O item. */
void
ffeste_R911_item (ffebld expr, ffelexToken expr_token)
@@ -4216,23 +4674,30 @@ ffeste_R911_item (ffebld expr, ffelexToken expr_token)
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
if (expr == NULL)
return;
+
if (ffebld_op (expr) == FFEBLD_opANY)
return;
+
if (ffebld_op (expr) == FFEBLD_opIMPDO)
ffeste_io_impdo_ (expr, expr_token);
else
- ffeste_io_call_ ((*ffeste_io_driver_) (expr), FALSE);
- clear_momentary ();
+ {
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_arg_ptr_to_expr (expr);
+
+ ffecom_prepare_end ();
+
+ ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
+
+ ffeste_end_stmt_ ();
+ }
#else
#error
#endif
}
-/* ffeste_R911_finish -- PRINT statement list complete
-
- ffeste_R911_finish();
-
- Just wrap up any local activities. */
+/* PRINT statement -- end. */
void
ffeste_R911_finish ()
@@ -4242,27 +4707,19 @@ ffeste_R911_finish ()
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- {
- if (ffeste_io_endgfrt_ != FFECOM_gfrt)
- ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE),
- FALSE);
- ffecom_pop_calltemps ();
+ if (ffeste_io_endgfrt_ != FFECOM_gfrt)
+ ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
+ NULL_TREE),
+ FALSE);
- clear_momentary ();
- pop_momentary ();
- clear_momentary ();
- }
+ ffeste_end_stmt_ ();
#else
#error
#endif
}
-/* ffeste_R919 -- BACKSPACE statement
-
- ffeste_R919();
-
- Make sure a BACKSPACE is valid in the current context, and implement it. */
+/* BACKSPACE statement. */
void
ffeste_R919 (ffestpBeruStmt *info)
@@ -4282,11 +4739,7 @@ ffeste_R919 (ffestpBeruStmt *info)
#endif
}
-/* ffeste_R920 -- ENDFILE statement
-
- ffeste_R920();
-
- Make sure a ENDFILE is valid in the current context, and implement it. */
+/* ENDFILE statement. */
void
ffeste_R920 (ffestpBeruStmt *info)
@@ -4306,11 +4759,7 @@ ffeste_R920 (ffestpBeruStmt *info)
#endif
}
-/* ffeste_R921 -- REWIND statement
-
- ffeste_R921();
-
- Make sure a REWIND is valid in the current context, and implement it. */
+/* REWIND statement. */
void
ffeste_R921 (ffestpBeruStmt *info)
@@ -4330,11 +4779,7 @@ ffeste_R921 (ffestpBeruStmt *info)
#endif
}
-/* ffeste_R923A -- INQUIRE statement (non-IOLENGTH version)
-
- ffeste_R923A(bool by_file);
-
- Make sure an INQUIRE is valid in the current context, and implement it. */
+/* INQUIRE statement (non-IOLENGTH version). */
void
ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
@@ -4387,32 +4832,16 @@ ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
bool iostat;
bool errl;
-#define specified(something) (info->inquire_spec[something].kw_or_val_present)
-
ffeste_emit_line_note_ ();
+#define specified(something) (info->inquire_spec[something].kw_or_val_present)
+
iostat = specified (FFESTP_inquireixIOSTAT);
errl = specified (FFESTP_inquireixERR);
- ffecom_push_calltemps ();
-
- args = ffeste_io_inlist_ (errl || iostat,
- &info->inquire_spec[FFESTP_inquireixUNIT],
- &info->inquire_spec[FFESTP_inquireixFILE],
- &info->inquire_spec[FFESTP_inquireixEXIST],
- &info->inquire_spec[FFESTP_inquireixOPENED],
- &info->inquire_spec[FFESTP_inquireixNUMBER],
- &info->inquire_spec[FFESTP_inquireixNAMED],
- &info->inquire_spec[FFESTP_inquireixNAME],
- &info->inquire_spec[FFESTP_inquireixACCESS],
- &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
- &info->inquire_spec[FFESTP_inquireixDIRECT],
- &info->inquire_spec[FFESTP_inquireixFORM],
- &info->inquire_spec[FFESTP_inquireixFORMATTED],
- &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
- &info->inquire_spec[FFESTP_inquireixRECL],
- &info->inquire_spec[FFESTP_inquireixNEXTREC],
- &info->inquire_spec[FFESTP_inquireixBLANK]);
+#undef specified
+
+ ffeste_start_stmt_ ();
if (errl)
{
@@ -4433,31 +4862,58 @@ ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
}
if (iostat)
- { /* IOSTAT= */
+ {
+ /* Have IOSTAT= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = ffecom_expr
(info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
}
else if (ffeste_io_abort_ != NULL_TREE)
- { /* no IOSTAT= but ERR= */
+ {
+ /* Have no IOSTAT= but have ERR=. */
+
ffeste_io_iostat_is_temp_ = TRUE;
ffeste_io_iostat_
- = ffecom_push_tempvar (ffecom_integer_type_node,
- FFETARGET_charactersizeNONE, -1, FALSE);
+ = ffecom_make_tempvar ("inquire", ffecom_integer_type_node,
+ FFETARGET_charactersizeNONE, -1);
}
else
- { /* no IOSTAT=, or ERR= */
+ {
+ /* No IOSTAT= or ERR= specification. */
+
ffeste_io_iostat_is_temp_ = FALSE;
ffeste_io_iostat_ = NULL_TREE;
}
+ /* Now prescan, then convert, all the arguments. */
+
+ args
+ = ffeste_io_inlist_ (errl || iostat,
+ &info->inquire_spec[FFESTP_inquireixUNIT],
+ &info->inquire_spec[FFESTP_inquireixFILE],
+ &info->inquire_spec[FFESTP_inquireixEXIST],
+ &info->inquire_spec[FFESTP_inquireixOPENED],
+ &info->inquire_spec[FFESTP_inquireixNUMBER],
+ &info->inquire_spec[FFESTP_inquireixNAMED],
+ &info->inquire_spec[FFESTP_inquireixNAME],
+ &info->inquire_spec[FFESTP_inquireixACCESS],
+ &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
+ &info->inquire_spec[FFESTP_inquireixDIRECT],
+ &info->inquire_spec[FFESTP_inquireixFORM],
+ &info->inquire_spec[FFESTP_inquireixFORMATTED],
+ &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
+ &info->inquire_spec[FFESTP_inquireixRECL],
+ &info->inquire_spec[FFESTP_inquireixNEXTREC],
+ &info->inquire_spec[FFESTP_inquireixBLANK]);
+
/* Don't generate "if (iostat != 0) goto label;" if label is temp abort
label, since we're gonna fall through to there anyway. */
- ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args),
- !ffeste_io_abort_is_temp_);
+ ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args, NULL_TREE),
+ ! ffeste_io_abort_is_temp_);
- /* If we've got a temp label, generate its code here. */
+ /* If we've got a temp label, generate its code here. */
if (ffeste_io_abort_is_temp_)
{
@@ -4468,28 +4924,14 @@ ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
assert (ffeste_io_err_ == NULL_TREE);
}
- /* If we've got a temp iostat, pop the temp. */
-
- if (ffeste_io_iostat_is_temp_)
- ffecom_pop_tempvar (ffeste_io_iostat_);
-
- ffecom_pop_calltemps ();
-
-#undef specified
+ ffeste_end_stmt_ ();
}
-
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R923B_start -- INQUIRE(IOLENGTH=expr) statement list begin
-
- ffeste_R923B_start();
-
- Verify that INQUIRE is valid here, and begin accepting items in the
- list. */
+/* INQUIRE(IOLENGTH=expr) statement -- start. */
void
ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
@@ -4502,18 +4944,14 @@ ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
fputs (") ", dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
+
ffeste_emit_line_note_ ();
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R923B_item -- INQUIRE statement i/o item
-
- ffeste_R923B_item(expr,expr_token);
-
- Implement output-list expression. */
+/* INQUIRE(IOLENGTH=expr) statement -- I/O item. */
void
ffeste_R923B_item (ffebld expr UNUSED)
@@ -4524,17 +4962,12 @@ ffeste_R923B_item (ffebld expr UNUSED)
ffebld_dump (expr);
fputc (',', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- clear_momentary ();
#else
#error
#endif
}
-/* ffeste_R923B_finish -- INQUIRE statement list complete
-
- ffeste_R923B_finish();
-
- Just wrap up any local activities. */
+/* INQUIRE(IOLENGTH=expr) statement -- end. */
void
ffeste_R923B_finish ()
@@ -4544,7 +4977,6 @@ ffeste_R923B_finish ()
#if FFECOM_targetCURRENT == FFECOM_targetFFE
fputc ('\n', dmpout);
#elif FFECOM_targetCURRENT == FFECOM_targetGCC
- clear_momentary ();
#else
#error
#endif
@@ -4616,9 +5048,7 @@ ffeste_R1001 (ffests s)
#endif
}
-/* ffeste_R1103 -- End a PROGRAM
-
- ffeste_R1103(); */
+/* END PROGRAM. */
void
ffeste_R1103 ()
@@ -4631,9 +5061,7 @@ ffeste_R1103 ()
#endif
}
-/* ffeste_R1112 -- End a BLOCK DATA
-
- ffeste_R1112(TRUE); */
+/* END BLOCK DATA. */
void
ffeste_R1112 ()
@@ -4646,11 +5074,7 @@ ffeste_R1112 ()
#endif
}
-/* ffeste_R1212 -- CALL statement
-
- ffeste_R1212(expr,expr_token);
-
- Make sure statement is valid here; implement. */
+/* CALL statement. */
void
ffeste_R1212 (ffebld expr)
@@ -4715,6 +5139,27 @@ ffeste_R1212 (ffebld expr)
else
ffebld_set_trail (prevargs, NULL);
+ ffeste_start_stmt_ ();
+
+ /* No temporaries are actually needed at this level, but we go
+ through the motions anyway, just to be sure in case they do
+ get made. Temporaries needed for arguments should be in the
+ scopes of inner blocks, and if clean-up actions are supported,
+ such as CALL-ing an intrinsic that writes to an argument of one
+ type when a variable of a different type is provided (requiring
+ assignment to the variable from a temporary after the library
+ routine returns), the clean-up must be done by the expression
+ evaluator, generally, to handle alternate returns (which we hope
+ won't ever be supported by intrinsics, but might be a similar
+ issue, such as CALL-ing an F90-style subroutine with an INTERFACE
+ block). That implies the expression evaluator will have to
+ recognize the need for its own temporary anyway, meaning it'll
+ construct a block within the one constructed here. */
+
+ ffecom_prepare_expr (expr);
+
+ ffecom_prepare_end ();
+
if (labels == NULL)
expand_expr_stmt (ffecom_expr (expr));
else
@@ -4725,43 +5170,41 @@ ffeste_R1212 (ffebld expr)
int caseno;
int pushok;
tree duplicate;
+ ffebld label;
texpr = ffecom_expr (expr);
expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
- push_momentary (); /* In case of many labels, keep 'em cleared
- out. */
- for (caseno = 1;
- labels != NULL;
- ++caseno, labels = ffebld_trail (labels))
+
+ for (caseno = 1, label = labels;
+ label != NULL;
+ ++caseno, label = ffebld_trail (label))
{
value = build_int_2 (caseno, 0);
tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
pushok = pushcase (value, convert, tlabel, &duplicate);
assert (pushok == 0);
+
tlabel
- = ffecom_lookup_label (ffebld_labter (ffebld_head (labels)));
+ = ffecom_lookup_label (ffebld_labter (ffebld_head (label)));
if ((tlabel == NULL_TREE)
|| (TREE_CODE (tlabel) == ERROR_MARK))
continue;
TREE_USED (tlabel) = 1;
expand_goto (tlabel);
- clear_momentary ();
}
- pop_momentary ();
expand_end_case (texpr);
}
- clear_momentary ();
+
+ ffeste_end_stmt_ ();
}
#else
#error
#endif
}
-/* ffeste_R1221 -- End a FUNCTION
-
- ffeste_R1221(TRUE); */
+/* END FUNCTION. */
void
ffeste_R1221 ()
@@ -4774,9 +5217,7 @@ ffeste_R1221 ()
#endif
}
-/* ffeste_R1225 -- End a SUBROUTINE
-
- ffeste_R1225(TRUE); */
+/* END SUBROUTINE. */
void
ffeste_R1225 ()
@@ -4789,12 +5230,7 @@ ffeste_R1225 ()
#endif
}
-/* ffeste_R1226 -- ENTRY statement
-
- ffeste_R1226(entryname,arglist,ending_token);
-
- Make sure we're in a SUBROUTINE or FUNCTION, register arguments for the
- entry point name, and so on. */
+/* ENTRY statement. */
void
ffeste_R1226 (ffesymbol entry)
@@ -4842,23 +5278,19 @@ ffeste_R1226 (ffesymbol entry)
ffeste_emit_line_note_ ();
+ if (label == error_mark_node)
+ return;
+
DECL_INITIAL (label) = error_mark_node;
emit_nop ();
expand_label (label);
-
- clear_momentary ();
}
#else
#error
#endif
}
-/* ffeste_R1227 -- RETURN statement
-
- ffeste_R1227(expr);
-
- Make sure statement is valid here; implement. expr and expr_token are
- both NULL if there was no expression. */
+/* RETURN statement. */
void
ffeste_R1227 (ffestw block UNUSED, ffebld expr)
@@ -4881,7 +5313,12 @@ ffeste_R1227 (ffestw block UNUSED, ffebld expr)
tree rtn;
ffeste_emit_line_note_ ();
- ffecom_push_calltemps ();
+
+ ffeste_start_stmt_ ();
+
+ ffecom_prepare_return_expr (expr);
+
+ ffecom_prepare_end ();
rtn = ffecom_return_expr (expr);
@@ -4902,20 +5339,14 @@ ffeste_R1227 (ffestw block UNUSED, ffebld expr)
expand_null_return ();
}
- ffecom_pop_calltemps ();
- clear_momentary ();
+ ffeste_end_stmt_ ();
}
#else
#error
#endif
}
-/* ffeste_V018_start -- REWRITE(...) statement list begin
-
- ffeste_V018_start();
-
- Verify that REWRITE is valid here, and begin accepting items in the
- list. */
+/* REWRITE statement -- start. */
#if FFESTR_VXT
void
@@ -4950,11 +5381,7 @@ ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
#endif
}
-/* ffeste_V018_item -- REWRITE statement i/o item
-
- ffeste_V018_item(expr,expr_token);
-
- Implement output-list expression. */
+/* REWRITE statement -- I/O item. */
void
ffeste_V018_item (ffebld expr)
@@ -4970,11 +5397,7 @@ ffeste_V018_item (ffebld expr)
#endif
}
-/* ffeste_V018_finish -- REWRITE statement list complete
-
- ffeste_V018_finish();
-
- Just wrap up any local activities. */
+/* REWRITE statement -- end. */
void
ffeste_V018_finish ()
@@ -4989,12 +5412,7 @@ ffeste_V018_finish ()
#endif
}
-/* ffeste_V019_start -- ACCEPT statement list begin
-
- ffeste_V019_start();
-
- Verify that ACCEPT is valid here, and begin accepting items in the
- list. */
+/* ACCEPT statement -- start. */
void
ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
@@ -5029,11 +5447,7 @@ ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
#endif
}
-/* ffeste_V019_item -- ACCEPT statement i/o item
-
- ffeste_V019_item(expr,expr_token);
-
- Implement output-list expression. */
+/* ACCEPT statement -- I/O item. */
void
ffeste_V019_item (ffebld expr)
@@ -5049,11 +5463,7 @@ ffeste_V019_item (ffebld expr)
#endif
}
-/* ffeste_V019_finish -- ACCEPT statement list complete
-
- ffeste_V019_finish();
-
- Just wrap up any local activities. */
+/* ACCEPT statement -- end. */
void
ffeste_V019_finish ()
@@ -5069,12 +5479,7 @@ ffeste_V019_finish ()
}
#endif
-/* ffeste_V020_start -- TYPE statement list begin
-
- ffeste_V020_start();
-
- Verify that TYPE is valid here, and begin accepting items in the
- list. */
+/* TYPE statement -- start. */
void
ffeste_V020_start (ffestpTypeStmt *info UNUSED,
@@ -5110,11 +5515,7 @@ ffeste_V020_start (ffestpTypeStmt *info UNUSED,
#endif
}
-/* ffeste_V020_item -- TYPE statement i/o item
-
- ffeste_V020_item(expr,expr_token);
-
- Implement output-list expression. */
+/* TYPE statement -- I/O item. */
void
ffeste_V020_item (ffebld expr UNUSED)
@@ -5130,11 +5531,7 @@ ffeste_V020_item (ffebld expr UNUSED)
#endif
}
-/* ffeste_V020_finish -- TYPE statement list complete
-
- ffeste_V020_finish();
-
- Just wrap up any local activities. */
+/* TYPE statement -- end. */
void
ffeste_V020_finish ()
@@ -5149,11 +5546,7 @@ ffeste_V020_finish ()
#endif
}
-/* ffeste_V021 -- DELETE statement
-
- ffeste_V021();
-
- Make sure a DELETE is valid in the current context, and implement it. */
+/* DELETE statement. */
#if FFESTR_VXT
void
@@ -5174,11 +5567,7 @@ ffeste_V021 (ffestpDeleteStmt *info)
#endif
}
-/* ffeste_V022 -- UNLOCK statement
-
- ffeste_V022();
-
- Make sure a UNLOCK is valid in the current context, and implement it. */
+/* UNLOCK statement. */
void
ffeste_V022 (ffestpBeruStmt *info)
@@ -5197,12 +5586,7 @@ ffeste_V022 (ffestpBeruStmt *info)
#endif
}
-/* ffeste_V023_start -- ENCODE(...) statement list begin
-
- ffeste_V023_start();
-
- Verify that ENCODE is valid here, and begin accepting items in the
- list. */
+/* ENCODE statement -- start. */
void
ffeste_V023_start (ffestpVxtcodeStmt *info)
@@ -5223,11 +5607,7 @@ ffeste_V023_start (ffestpVxtcodeStmt *info)
#endif
}
-/* ffeste_V023_item -- ENCODE statement i/o item
-
- ffeste_V023_item(expr,expr_token);
-
- Implement output-list expression. */
+/* ENCODE statement -- I/O item. */
void
ffeste_V023_item (ffebld expr)
@@ -5243,11 +5623,7 @@ ffeste_V023_item (ffebld expr)
#endif
}
-/* ffeste_V023_finish -- ENCODE statement list complete
-
- ffeste_V023_finish();
-
- Just wrap up any local activities. */
+/* ENCODE statement -- end. */
void
ffeste_V023_finish ()
@@ -5262,12 +5638,7 @@ ffeste_V023_finish ()
#endif
}
-/* ffeste_V024_start -- DECODE(...) statement list begin
-
- ffeste_V024_start();
-
- Verify that DECODE is valid here, and begin accepting items in the
- list. */
+/* DECODE statement -- start. */
void
ffeste_V024_start (ffestpVxtcodeStmt *info)
@@ -5288,11 +5659,7 @@ ffeste_V024_start (ffestpVxtcodeStmt *info)
#endif
}
-/* ffeste_V024_item -- DECODE statement i/o item
-
- ffeste_V024_item(expr,expr_token);
-
- Implement output-list expression. */
+/* DECODE statement -- I/O item. */
void
ffeste_V024_item (ffebld expr)
@@ -5308,11 +5675,7 @@ ffeste_V024_item (ffebld expr)
#endif
}
-/* ffeste_V024_finish -- DECODE statement list complete
-
- ffeste_V024_finish();
-
- Just wrap up any local activities. */
+/* DECODE statement -- end. */
void
ffeste_V024_finish ()
@@ -5327,12 +5690,7 @@ ffeste_V024_finish ()
#endif
}
-/* ffeste_V025_start -- DEFINEFILE statement list begin
-
- ffeste_V025_start();
-
- Verify that DEFINEFILE is valid here, and begin accepting items in the
- list. */
+/* DEFINEFILE statement -- start. */
void
ffeste_V025_start ()
@@ -5347,11 +5705,7 @@ ffeste_V025_start ()
#endif
}
-/* ffeste_V025_item -- DEFINE FILE statement item
-
- ffeste_V025_item(u,ut,m,mt,n,nt,asv,asvt);
-
- Implement item. */
+/* DEFINE FILE statement -- item. */
void
ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
@@ -5373,11 +5727,7 @@ ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
#endif
}
-/* ffeste_V025_finish -- DEFINE FILE statement list complete
-
- ffeste_V025_finish();
-
- Just wrap up any local activities. */
+/* DEFINE FILE statement -- end. */
void
ffeste_V025_finish ()
@@ -5392,11 +5742,7 @@ ffeste_V025_finish ()
#endif
}
-/* ffeste_V026 -- FIND statement
-
- ffeste_V026();
-
- Make sure a FIND is valid in the current context, and implement it. */
+/* FIND statement. */
void
ffeste_V026 (ffestpFindStmt *info)
@@ -5417,3 +5763,11 @@ ffeste_V026 (ffestpFindStmt *info)
}
#endif
+
+#ifdef ENABLE_CHECKING
+void
+ffeste_terminate_2 (void)
+{
+ assert (! ffeste_top_block_);
+}
+#endif
diff --git a/contrib/gcc/f/ste.h b/contrib/gcc/f/ste.h
index 0ee0d0f..78e9881 100644
--- a/contrib/gcc/f/ste.h
+++ b/contrib/gcc/f/ste.h
@@ -1,6 +1,6 @@
/* ste.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -62,10 +62,10 @@ void ffeste_end_R807 (void);
void ffeste_labeldef_branch (ffelab label);
void ffeste_labeldef_format (ffelab label);
void ffeste_R737A (ffebld dest, ffebld source);
-void ffeste_R803 (ffebld expr);
-void ffeste_R804 (ffebld expr);
-void ffeste_R805 (void);
-void ffeste_R806 (void);
+void ffeste_R803 (ffestw block, ffebld expr);
+void ffeste_R804 (ffestw block, ffebld expr);
+void ffeste_R805 (ffestw block);
+void ffeste_R806 (ffestw block);
void ffeste_R807 (ffebld expr);
void ffeste_R809 (ffestw block, ffebld expr);
void ffeste_R810 (ffestw block, unsigned long casenum);
@@ -159,7 +159,11 @@ void ffeste_V026 (ffestpFindStmt *info);
#endif /* FFECOM_targetCURRENT == FFECOM_targetFFE */
#define ffeste_terminate_0()
#define ffeste_terminate_1()
+#ifdef ENABLE_CHECKING
+void ffeste_terminate_2 (void);
+#else
#define ffeste_terminate_2()
+#endif
#define ffeste_terminate_3()
#define ffeste_terminate_4()
diff --git a/contrib/gcc/f/storag.c b/contrib/gcc/f/storag.c
index 76f5cd3..f8af500 100644
--- a/contrib/gcc/f/storag.c
+++ b/contrib/gcc/f/storag.c
@@ -1,6 +1,6 @@
/* storag.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/storag.h b/contrib/gcc/f/storag.h
index 5addab5..bc5c9e6 100644
--- a/contrib/gcc/f/storag.h
+++ b/contrib/gcc/f/storag.h
@@ -1,6 +1,6 @@
/* storag.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/stp.c b/contrib/gcc/f/stp.c
index 6c95c74..7b8763d 100644
--- a/contrib/gcc/f/stp.c
+++ b/contrib/gcc/f/stp.c
@@ -1,6 +1,6 @@
/* stp.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/stp.h b/contrib/gcc/f/stp.h
index edfccc6..d995cf0 100644
--- a/contrib/gcc/f/stp.h
+++ b/contrib/gcc/f/stp.h
@@ -1,6 +1,6 @@
/* stp.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str-1t.fin b/contrib/gcc/f/str-1t.fin
index 674c92d..b74f583 100644
--- a/contrib/gcc/f/str-1t.fin
+++ b/contrib/gcc/f/str-1t.fin
@@ -1,6 +1,6 @@
{
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str-2t.fin b/contrib/gcc/f/str-2t.fin
index ea86819..d0ba9fc 100644
--- a/contrib/gcc/f/str-2t.fin
+++ b/contrib/gcc/f/str-2t.fin
@@ -1,6 +1,6 @@
{
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str-fo.fin b/contrib/gcc/f/str-fo.fin
index 243941f..ea39b6c 100644
--- a/contrib/gcc/f/str-fo.fin
+++ b/contrib/gcc/f/str-fo.fin
@@ -1,6 +1,6 @@
{
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str-io.fin b/contrib/gcc/f/str-io.fin
index 4124da6..efd4008 100644
--- a/contrib/gcc/f/str-io.fin
+++ b/contrib/gcc/f/str-io.fin
@@ -1,6 +1,6 @@
{
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str-nq.fin b/contrib/gcc/f/str-nq.fin
index cce8745..3cdae08 100644
--- a/contrib/gcc/f/str-nq.fin
+++ b/contrib/gcc/f/str-nq.fin
@@ -1,6 +1,6 @@
{
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str-op.fin b/contrib/gcc/f/str-op.fin
index 62396f2..b7a5112 100644
--- a/contrib/gcc/f/str-op.fin
+++ b/contrib/gcc/f/str-op.fin
@@ -1,6 +1,6 @@
{
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str-ot.fin b/contrib/gcc/f/str-ot.fin
index a4ad768..c96b59c 100644
--- a/contrib/gcc/f/str-ot.fin
+++ b/contrib/gcc/f/str-ot.fin
@@ -1,6 +1,6 @@
{
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str.c b/contrib/gcc/f/str.c
index 8622789..f03c893 100644
--- a/contrib/gcc/f/str.c
+++ b/contrib/gcc/f/str.c
@@ -1,6 +1,6 @@
/* str.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/str.h b/contrib/gcc/f/str.h
index 17b58ea..1ed1228 100644
--- a/contrib/gcc/f/str.h
+++ b/contrib/gcc/f/str.h
@@ -1,6 +1,6 @@
/* str.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/sts.c b/contrib/gcc/f/sts.c
index 1229ad5..143f550 100644
--- a/contrib/gcc/f/sts.c
+++ b/contrib/gcc/f/sts.c
@@ -1,6 +1,6 @@
/* sts.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -104,7 +104,7 @@ ffests_new (ffests s, mallocPool pool, ffestsLength size)
Like printf, but into a string. */
void
-ffests_printf_1D (ffests s, char *ctl, long arg1)
+ffests_printf_1D (ffests s, const char *ctl, long arg1)
{
char quickbuf[40];
char *buff;
@@ -133,7 +133,7 @@ ffests_printf_1D (ffests s, char *ctl, long arg1)
Like printf, but into a string. */
void
-ffests_printf_1U (ffests s, char *ctl, unsigned long arg1)
+ffests_printf_1U (ffests s, const char *ctl, unsigned long arg1)
{
char quickbuf[40];
char *buff;
@@ -162,7 +162,7 @@ ffests_printf_1U (ffests s, char *ctl, unsigned long arg1)
Like printf, but into a string. */
void
-ffests_printf_1s (ffests s, char *ctl, char *arg1)
+ffests_printf_1s (ffests s, const char *ctl, const char *arg1)
{
char quickbuf[40];
char *buff;
@@ -190,7 +190,7 @@ ffests_printf_1s (ffests s, char *ctl, char *arg1)
Like printf, but into a string. */
void
-ffests_printf_2Us (ffests s, char *ctl, unsigned long arg1, char *arg2)
+ffests_printf_2Us (ffests s, const char *ctl, unsigned long arg1, const char *arg2)
{
char quickbuf[60];
char *buff;
@@ -228,7 +228,7 @@ ffests_putc (ffests s, char c)
ffests_puts(s,"append me"); */
void
-ffests_puts (ffests s, char *string)
+ffests_puts (ffests s, const char *string)
{
ffests_puttext (s, string, strlen (string));
}
@@ -242,7 +242,7 @@ ffests_puts (ffests s, char *string)
and may be 0. */
void
-ffests_puttext (ffests s, char *text, ffestsLength length)
+ffests_puttext (ffests s, const char *text, ffestsLength length)
{
ffestsLength newlen;
ffestsLength newmax;
diff --git a/contrib/gcc/f/sts.h b/contrib/gcc/f/sts.h
index d2c2b6e..1432d41 100644
--- a/contrib/gcc/f/sts.h
+++ b/contrib/gcc/f/sts.h
@@ -1,6 +1,6 @@
/* sts.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -60,14 +60,14 @@ struct _ffests_
void ffests_kill (ffests s);
void ffests_new (ffests s, mallocPool pool, ffestsLength size);
-void ffests_printf_1D (ffests s, char *ctl, long arg1);
-void ffests_printf_1U (ffests s, char *ctl, unsigned long arg1);
-void ffests_printf_1s (ffests s, char *ctl, char *arg1);
-void ffests_printf_2Us (ffests s, char *ctl, unsigned long arg1,
- char *arg2);
+void ffests_printf_1D (ffests s, const char *ctl, long arg1);
+void ffests_printf_1U (ffests s, const char *ctl, unsigned long arg1);
+void ffests_printf_1s (ffests s, const char *ctl, const char *arg1);
+void ffests_printf_2Us (ffests s, const char *ctl, unsigned long arg1,
+ const char *arg2);
void ffests_putc (ffests s, char c);
-void ffests_puts (ffests s, char *string);
-void ffests_puttext (ffests s, char *text, ffestsLength length);
+void ffests_puts (ffests s, const char *string);
+void ffests_puttext (ffests s, const char *text, ffestsLength length);
/* Define macros. */
diff --git a/contrib/gcc/f/stt.c b/contrib/gcc/f/stt.c
index d2db379..4b008e2 100644
--- a/contrib/gcc/f/stt.c
+++ b/contrib/gcc/f/stt.c
@@ -1,6 +1,6 @@
/* stt.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995, 1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -598,7 +598,7 @@ ffestt_exprlist_create ()
at a time. */
void
-ffestt_exprlist_drive (ffesttExprList list, void (*fn) ())
+ffestt_exprlist_drive (ffesttExprList list, void (*fn) (ffebld, ffelexToken))
{
ffesttExprList next;
@@ -837,7 +837,7 @@ ffestt_implist_create ()
The token pairs in the list are passed to the function one pair at a time. */
void
-ffestt_implist_drive (ffesttImpList list, void (*fn) ())
+ffestt_implist_drive (ffesttImpList list, void (*fn) (ffelexToken, ffelexToken))
{
ffesttImpList next;
@@ -951,7 +951,7 @@ ffestt_tokenlist_create ()
The tokens in the list are passed to the given function. */
void
-ffestt_tokenlist_drive (ffesttTokenList tl, void (*fn) ())
+ffestt_tokenlist_drive (ffesttTokenList tl, void (*fn) (ffelexToken))
{
ffesttTokenItem ti;
diff --git a/contrib/gcc/f/stt.h b/contrib/gcc/f/stt.h
index 38ffa41..341daa7 100644
--- a/contrib/gcc/f/stt.h
+++ b/contrib/gcc/f/stt.h
@@ -1,6 +1,6 @@
/* stt.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -181,7 +181,7 @@ void ffestt_dimlist_kill (ffesttDimList list);
ffestpDimtype ffestt_dimlist_type (ffesttDimList dims, bool is_ugly_assumed);
void ffestt_exprlist_append (ffesttExprList list, ffebld expr, ffelexToken t);
ffesttExprList ffestt_exprlist_create (void);
-void ffestt_exprlist_drive (ffesttExprList list, void (*fn) ());
+void ffestt_exprlist_drive (ffesttExprList list, void (*fn) (ffebld, ffelexToken));
#if FFECOM_targetCURRENT == FFECOM_targetFFE
void ffestt_exprlist_dump (ffesttExprList list);
#endif
@@ -196,14 +196,14 @@ void ffestt_formatlist_kill (ffesttFormatList list);
void ffestt_implist_append (ffesttImpList list, ffelexToken first,
ffelexToken last);
ffesttImpList ffestt_implist_create (void);
-void ffestt_implist_drive (ffesttImpList list, void (*fn) ());
+void ffestt_implist_drive (ffesttImpList list, void (*fn) (ffelexToken, ffelexToken));
#if FFECOM_targetCURRENT == FFECOM_targetFFE
void ffestt_implist_dump (ffesttImpList list);
#endif
void ffestt_implist_kill (ffesttImpList list);
void ffestt_tokenlist_append (ffesttTokenList list, ffelexToken t);
ffesttTokenList ffestt_tokenlist_create (void);
-void ffestt_tokenlist_drive (ffesttTokenList list, void (*fn) ());
+void ffestt_tokenlist_drive (ffesttTokenList list, void (*fn) (ffelexToken));
#if FFECOM_targetCURRENT == FFECOM_targetFFE
void ffestt_tokenlist_dump (ffesttTokenList list);
#endif
diff --git a/contrib/gcc/f/stu.c b/contrib/gcc/f/stu.c
index 7dcbdcb..cc1d95c 100644
--- a/contrib/gcc/f/stu.c
+++ b/contrib/gcc/f/stu.c
@@ -1,6 +1,6 @@
/* stu.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -60,7 +60,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static void ffestu_list_exec_transition_ (ffebld list);
static bool ffestu_symter_end_transition_ (ffebld expr);
static bool ffestu_symter_exec_transition_ (ffebld expr);
-static bool ffestu_dummies_transition_ (ffesymbol (*symfunc) (),
+static bool ffestu_dummies_transition_ (ffesymbol (*symfunc) (ffesymbol),
ffebld list);
/* Internal macros. */
@@ -122,7 +122,7 @@ ffestu_sym_end_transition (ffesymbol s)
ffeinfoBasictype bt;
ffeinfoKindtype kt;
bool array;
- char *name = NULL;
+ const char *name = NULL;
ffestu_dummies_transition_ (ffecom_sym_end_transition,
ffesymbol_dummyargs (s));
@@ -1114,7 +1114,7 @@ tail: /* :::::::::::::::::::: */
Make sure we don't get called recursively ourselves! */
static bool
-ffestu_dummies_transition_ (ffesymbol (*symfunc) (), ffebld list)
+ffestu_dummies_transition_ (ffesymbol (*symfunc) (ffesymbol), ffebld list)
{
static bool in_progress = FALSE;
ffebld item;
diff --git a/contrib/gcc/f/stu.h b/contrib/gcc/f/stu.h
index 61d7b40..b9d9d52 100644
--- a/contrib/gcc/f/stu.h
+++ b/contrib/gcc/f/stu.h
@@ -1,6 +1,6 @@
/* stu.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/stv.c b/contrib/gcc/f/stv.c
index c652356..cd31ac4 100644
--- a/contrib/gcc/f/stv.c
+++ b/contrib/gcc/f/stv.c
@@ -1,6 +1,6 @@
/* stv.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/stv.h b/contrib/gcc/f/stv.h
index 9ecdd80..22b177e 100644
--- a/contrib/gcc/f/stv.h
+++ b/contrib/gcc/f/stv.h
@@ -1,6 +1,6 @@
/* stv.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/stw.c b/contrib/gcc/f/stw.c
index 90a19a5..058b1eb 100644
--- a/contrib/gcc/f/stw.c
+++ b/contrib/gcc/f/stw.c
@@ -1,6 +1,6 @@
/* stw.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -74,7 +74,7 @@ ffestw ffestw_stack_top_ = NULL;
ffestw_display_state(); */
void
-ffestw_display_state ()
+ffestw_display_state (void)
{
assert (ffestw_stack_top_ != NULL);
@@ -320,7 +320,7 @@ ffestw_kill (ffestw b)
b = ffestw_new(); */
ffestw
-ffestw_new ()
+ffestw_new (void)
{
ffestw b;
@@ -335,7 +335,7 @@ ffestw_new ()
ffestw_pop(); */
ffestw
-ffestw_pop ()
+ffestw_pop (void)
{
ffestw b;
ffestw oldb = ffestw_stack_top_;
diff --git a/contrib/gcc/f/stw.h b/contrib/gcc/f/stw.h
index 8caefbd..58818a6 100644
--- a/contrib/gcc/f/stw.h
+++ b/contrib/gcc/f/stw.h
@@ -1,6 +1,6 @@
/* stw.h -- Private #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -81,6 +81,7 @@ struct _ffestw_
tree select_texpr_; /* tree for end case. */
bool select_break_; /* TRUE when CASE should start with gen
"break;". */
+ int ifthen_fake_else_; /* Number of fake `else' introductions. */
#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC*/
};
@@ -118,11 +119,11 @@ extern ffestw ffestw_stack_top_;
/* Declare functions with prototypes. */
-void ffestw_display_state ();
+void ffestw_display_state (void);
void ffestw_kill (ffestw block);
void ffestw_init_0 (void);
-ffestw ffestw_new ();
-ffestw ffestw_pop ();
+ffestw ffestw_new (void);
+ffestw ffestw_pop (void);
ffestw ffestw_push (ffestw block);
ffestw ffestw_update (ffestw block);
ffestw ffestw_use (ffestw block);
@@ -137,6 +138,7 @@ ffestw ffestw_use (ffestw block);
#define ffestw_do_iter_var(b) ((b)->do_iter_var_)
#define ffestw_do_iter_var_t(b) ((b)->do_iter_var_t_)
#define ffestw_do_tvar(b) ((b)->do_tvar_)
+#define ffestw_ifthen_fake_else(b) ((b)->ifthen_fake_else_)
#define ffestw_init_1()
#define ffestw_init_2()
#define ffestw_init_3()
@@ -156,6 +158,7 @@ ffestw ffestw_use (ffestw block);
#define ffestw_set_do_iter_var(b,v) ((b)->do_iter_var_ = (v))
#define ffestw_set_do_iter_var_t(b,t) ((b)->do_iter_var_t_ = (t))
#define ffestw_set_do_tvar(b,d) ((b)->do_tvar_ = (d))
+#define ffestw_set_ifthen_fake_else(b,e) ((b)->ifthen_fake_else_ = (e))
#define ffestw_set_label(b,l) ((b)->label_ = (l))
#define ffestw_set_line(b,l) ((b)->line_ = (l))
#define ffestw_set_name(b,n) ((b)->name_ = (n))
diff --git a/contrib/gcc/f/symbol.c b/contrib/gcc/f/symbol.c
index 8aa7230..c4bd14d 100644
--- a/contrib/gcc/f/symbol.c
+++ b/contrib/gcc/f/symbol.c
@@ -1,6 +1,6 @@
/* Implementation of Fortran symbol manager
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -117,7 +117,7 @@ static ffesymbolRetract_ *ffesymbol_retract_list_;
/* List of state names. */
-static char *ffesymbol_state_name_[] =
+static const char *ffesymbol_state_name_[] =
{
"?",
"@",
@@ -127,7 +127,7 @@ static char *ffesymbol_state_name_[] =
/* List of attribute names. */
-static char *ffesymbol_attr_name_[] =
+static const char *ffesymbol_attr_name_[] =
{
#define DEFATTR(ATTR,ATTRS,NAME) NAME,
#include "symbol.def"
@@ -255,6 +255,7 @@ ffesymbol_new_ (ffename n)
s->reported = FALSE;
s->explicit_where = FALSE;
s->namelisted = FALSE;
+ s->assigned = FALSE;
ffename_set_symbol (n, s);
@@ -316,7 +317,7 @@ ffesymbol_whine_state_ (ffebad bad, ffelexToken t, char c)
/* Returns a string representing the attributes set. */
-char *
+const char *
ffesymbol_attrs_string (ffesymbolAttrs attrs)
{
static char string[FFESYMBOL_attr * 12 + 20];
@@ -773,7 +774,7 @@ ffesymbol_declare_subrunit (ffelexToken t)
ffesymbol_drive (fn); */
void
-ffesymbol_drive (ffesymbol (*fn) ())
+ffesymbol_drive (ffesymbol (*fn) (ffesymbol))
{
assert (ffesymbol_sfunc_ == NULL); /* Might be ok, but not for current
uses. */
@@ -787,7 +788,7 @@ ffesymbol_drive (ffesymbol (*fn) ())
ffesymbol_drive_sfnames (fn); */
void
-ffesymbol_drive_sfnames (ffesymbol (*fn) ())
+ffesymbol_drive_sfnames (ffesymbol (*fn) (ffesymbol))
{
ffename_space_drive_symbol (ffesymbol_sfunc_, fn);
}
@@ -1348,7 +1349,7 @@ ffesymbol_signal_change (ffesymbol s)
/* Returns the string based on the state. */
-char *
+const char *
ffesymbol_state_string (ffesymbolState state)
{
if (state >= ARRAY_SIZE (ffesymbol_state_name_))
diff --git a/contrib/gcc/f/symbol.def b/contrib/gcc/f/symbol.def
index 343f80e..9cddcb6 100644
--- a/contrib/gcc/f/symbol.def
+++ b/contrib/gcc/f/symbol.def
@@ -1,6 +1,6 @@
/* Definitions and documentations for attributes used in GNU F77 compiler
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/symbol.h b/contrib/gcc/f/symbol.h
index b534ae6..0c7262c 100644
--- a/contrib/gcc/f/symbol.h
+++ b/contrib/gcc/f/symbol.h
@@ -1,6 +1,6 @@
/* Interface definitions for Fortran symbol manager
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -151,14 +151,16 @@ struct _ffesymbol_
away. */
bool explicit_where; /* TRUE if INTRINSIC/EXTERNAL explicit. */
bool namelisted; /* TRUE if in NAMELIST (needs static alloc). */
+ bool assigned; /* TRUE if ever ASSIGNed to. */
};
#define ffesymbol_accretes(s) ((s)->accretes)
#define ffesymbol_accretion(s) ((s)->accretion)
#define ffesymbol_arraysize(s) ((s)->array_size)
+#define ffesymbol_assigned(s) ((s)->assigned)
#define ffesymbol_attr(s,a) ((s)->attrs & ((ffesymbolAttrs) 1 << (a)))
#define ffesymbol_attrs(s) ((s)->attrs)
-char *ffesymbol_attrs_string (ffesymbolAttrs attrs);
+const char *ffesymbol_attrs_string (ffesymbolAttrs attrs);
#define ffesymbol_basictype(s) ffeinfo_basictype((s)->info)
void ffesymbol_check (ffesymbol s, ffelexToken t, bool maybe_intrin);
#define ffesymbol_common(s) ((s)->common)
@@ -177,8 +179,8 @@ ffesymbol ffesymbol_declare_sfdummy (ffelexToken t);
ffesymbol ffesymbol_declare_subrunit (ffelexToken t);
#define ffesymbol_dims(s) ((s)->dims)
#define ffesymbol_dim_syms(s) ((s)->dim_syms)
-void ffesymbol_drive (ffesymbol (*fn) ());
-void ffesymbol_drive_sfnames (ffesymbol (*fn) ());
+void ffesymbol_drive (ffesymbol (*fn) (ffesymbol));
+void ffesymbol_drive_sfnames (ffesymbol (*fn) (ffesymbol));
#define ffesymbol_dummyargs(s) ((s)->dummy_args)
#if FFECOM_targetCURRENT == FFECOM_targetFFE
void ffesymbol_dump (ffesymbol s);
@@ -231,6 +233,7 @@ bool ffesymbol_retractable (void);
#define ffesymbol_set_accretes(s,a) ((s)->accretes = (a))
#define ffesymbol_set_accretion(s,a) ((s)->accretion = (a))
#define ffesymbol_set_arraysize(s,a) ((s)->array_size = (a))
+#define ffesymbol_set_assigned(s,a) ((s)->assigned = (a))
#define ffesymbol_set_attr(s,a) ((s)->attrs |= ((ffesymbolAttrs) 1 << (a)))
#define ffesymbol_set_attrs(s,a) ((s)->attrs = (a))
#define ffesymbol_set_common(s,c) ((s)->common = (c))
@@ -269,7 +272,7 @@ void ffesymbol_signal_change (ffesymbol s);
#define ffesymbol_specific(s) ((s)->specific)
#define ffesymbol_state(s) ((s)->state)
#define ffesymbol_state_is_specable(s) ((s) <= FFESYMBOL_stateSEEN)
-char *ffesymbol_state_string (ffesymbolState state);
+const char *ffesymbol_state_string (ffesymbolState state);
#define ffesymbol_storage(s) ((s)->storage)
void ffesymbol_terminate_0 (void);
void ffesymbol_terminate_1 (void);
diff --git a/contrib/gcc/f/system.j b/contrib/gcc/f/system.j
index 6a37324..38547c8 100644
--- a/contrib/gcc/f/system.j
+++ b/contrib/gcc/f/system.j
@@ -1,6 +1,6 @@
/* system.j -- Wrapper for GCC's system.h
Copyright (C) 1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/target.c b/contrib/gcc/f/target.c
index 5de05ff..5712bdd 100644
--- a/contrib/gcc/f/target.c
+++ b/contrib/gcc/f/target.c
@@ -1,6 +1,6 @@
/* target.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -469,7 +469,7 @@ ffetarget_iszero_hollerith (ffetargetHollerith constant)
data type info and the number of elements an array (1 for a scalar). */
void
-ffetarget_layout (char *error_text UNUSED, ffetargetAlign *alignment,
+ffetarget_layout (const char *error_text UNUSED, ffetargetAlign *alignment,
ffetargetAlign *modulo, ffetargetOffset *size,
ffeinfoBasictype bt, ffeinfoKindtype kt,
ffetargetCharacterSize charsize,
diff --git a/contrib/gcc/f/target.h b/contrib/gcc/f/target.h
index ef59f90d..467f102 100644
--- a/contrib/gcc/f/target.h
+++ b/contrib/gcc/f/target.h
@@ -1,6 +1,6 @@
/* target.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -732,7 +732,7 @@ void ffetarget_integer_bad_magical_precedence_binary (ffelexToken integer,
bool ffetarget_iszero_character1 (ffetargetCharacter1 constant);
#endif
bool ffetarget_iszero_hollerith (ffetargetHollerith constant);
-void ffetarget_layout (char *error_text, ffetargetAlign *alignment,
+void ffetarget_layout (const char *error_text, ffetargetAlign *alignment,
ffetargetAlign *modulo, ffetargetOffset *size,
ffeinfoBasictype bt, ffeinfoKindtype kt,
ffetargetCharacterSize charsize,
@@ -989,7 +989,11 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
#define ffetarget_convert_complex1_integer1 ffetarget_convert_complex1_integer
#define ffetarget_convert_complex1_integer2 ffetarget_convert_complex1_integer
#define ffetarget_convert_complex1_integer3 ffetarget_convert_complex1_integer
+#ifdef REAL_ARITHMETIC
+#define ffetarget_convert_complex1_integer4(res,l) FFEBAD_NOCANDO
+#else
#define ffetarget_convert_complex1_integer4 ffetarget_convert_complex1_integer
+#endif
#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex1_real1(res,l) \
((res)->real = (l), \
@@ -1041,7 +1045,11 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
#define ffetarget_convert_complex2_integer1 ffetarget_convert_complex2_integer
#define ffetarget_convert_complex2_integer2 ffetarget_convert_complex2_integer
#define ffetarget_convert_complex2_integer3 ffetarget_convert_complex2_integer
+#ifdef REAL_ARITHMETIC
+#define ffetarget_convert_complex2_integer4(res,l) FFEBAD_NOCANDO
+#else
#define ffetarget_convert_complex2_integer4 ffetarget_convert_complex2_integer
+#endif
#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex2_real1(res,l) \
({ REAL_VALUE_TYPE lr; \
@@ -1111,10 +1119,15 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_integer1_typeless(res,l)
#define ffetarget_convert_integer4_character1(res,l) \
ffetarget_convert_integer1_character1(res,l)
+#ifdef REAL_ARITHMETIC
+#define ffetarget_convert_integer4_complex1(res,l) FFEBAD_NOCANDO
+#define ffetarget_convert_integer4_complex2(res,l) FFEBAD_NOCANDO
+#else
#define ffetarget_convert_integer4_complex1(res,l) \
ffetarget_convert_integer1_complex1(res,l)
#define ffetarget_convert_integer4_complex2(res,l) \
ffetarget_convert_integer1_complex2(res,l)
+#endif
#define ffetarget_convert_integer4_hollerith(res,l) \
ffetarget_convert_integer1_hollerith(res,l)
#define ffetarget_convert_integer4_integer1(res,l) (*(res) = (l), FFEBAD)
@@ -1128,10 +1141,15 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_integer1_logical1(res,l)
#define ffetarget_convert_integer4_logical4(res,l) \
ffetarget_convert_integer1_logical1(res,l)
+#ifdef REAL_ARITHMETIC
+#define ffetarget_convert_integer4_real1(res,l) FFEBAD_NOCANDO
+#define ffetarget_convert_integer4_real2(res,l) FFEBAD_NOCANDO
+#else
#define ffetarget_convert_integer4_real1(res,l) \
ffetarget_convert_integer1_real1(res,l)
#define ffetarget_convert_integer4_real2(res,l) \
ffetarget_convert_integer1_real2(res,l)
+#endif
#define ffetarget_convert_integer4_typeless(res,l) \
ffetarget_convert_integer1_typeless(res,l)
#define ffetarget_convert_logical1_character1(res,l) \
@@ -1238,8 +1256,12 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_real1_integer1(res,l)
#define ffetarget_convert_real1_integer3(res,l) \
ffetarget_convert_real1_integer1(res,l)
+#ifdef REAL_ARITHMETIC
+#define ffetarget_convert_real1_integer4(res,l) FFEBAD_NOCANDO
+#else
#define ffetarget_convert_real1_integer4(res,l) \
ffetarget_convert_real1_integer1(res,l)
+#endif
#define ffetarget_convert_real1_typeless(res,l) \
ffetarget_convert_any_typeless_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_real1_complex1(res,l) (*(res) = (l).real, FFEBAD)
@@ -1272,8 +1294,12 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_real2_integer1(res,l)
#define ffetarget_convert_real2_integer3(res,l) \
ffetarget_convert_real2_integer1(res,l)
+#ifdef REAL_ARITHMETIC
+#define ffetarget_convert_real2_integer4(res,l) FFEBAD_NOCANDO
+#else
#define ffetarget_convert_real2_integer4(res,l) \
ffetarget_convert_real2_integer1(res,l)
+#endif
#define ffetarget_convert_real2_typeless(res,l) \
ffetarget_convert_any_typeless_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_real2_complex1(res,l) \
diff --git a/contrib/gcc/f/tconfig.j b/contrib/gcc/f/tconfig.j
index 4135291..9c4c3ec 100644
--- a/contrib/gcc/f/tconfig.j
+++ b/contrib/gcc/f/tconfig.j
@@ -1,6 +1,6 @@
/* tconfig.j -- Wrapper for GCC's tconfig.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/tm.j b/contrib/gcc/f/tm.j
index 443fd53..e0d7594 100644
--- a/contrib/gcc/f/tm.j
+++ b/contrib/gcc/f/tm.j
@@ -1,6 +1,6 @@
/* tm.j -- Wrapper for GCC's tm.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/top.c b/contrib/gcc/f/top.c
index 17e4139..07ddd83 100644
--- a/contrib/gcc/f/top.c
+++ b/contrib/gcc/f/top.c
@@ -1,6 +1,6 @@
/* top.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -65,7 +65,7 @@ bool ffe_is_do_internal_checks_ = FALSE;
bool ffe_is_90_ = FFETARGET_defaultIS_90;
bool ffe_is_automatic_ = FFETARGET_defaultIS_AUTOMATIC;
bool ffe_is_backslash_ = FFETARGET_defaultIS_BACKSLASH;
-bool ffe_is_emulate_complex_ = TRUE;
+bool ffe_is_emulate_complex_ = FALSE;
bool ffe_is_underscoring_ = FFETARGET_defaultEXTERNAL_UNDERSCORED
|| FFETARGET_defaultUNDERSCORED_EXTERNAL_UNDERSCORED;
bool ffe_is_second_underscore_ = FFETARGET_defaultUNDERSCORED_EXTERNAL_UNDERSCORED;
@@ -74,15 +74,16 @@ bool ffe_is_dollar_ok_ = FFETARGET_defaultIS_DOLLAR_OK;
bool ffe_is_f2c_ = FFETARGET_defaultIS_F2C;
bool ffe_is_f2c_library_ = FFETARGET_defaultIS_F2C_LIBRARY;
bool ffe_is_ffedebug_ = FALSE;
+bool ffe_is_flatten_arrays_ = FALSE;
bool ffe_is_free_form_ = FFETARGET_defaultIS_FREE_FORM;
bool ffe_is_globals_ = TRUE;
-bool ffe_is_ident_ = TRUE;
bool ffe_is_init_local_zero_ = FFETARGET_defaultIS_INIT_LOCAL_ZERO;
bool ffe_is_mainprog_; /* TRUE if current prog unit known to be
main. */
bool ffe_is_null_version_ = FALSE;
bool ffe_is_onetrip_ = FALSE;
bool ffe_is_silent_ = TRUE;
+bool ffe_is_subscript_check_ = FALSE;
bool ffe_is_typeless_boz_ = FALSE;
bool ffe_is_pedantic_ = FFETARGET_defaultIS_PEDANTIC;
bool ffe_is_saveall_; /* TRUE if mainprog or SAVE (no args) seen. */
@@ -162,7 +163,7 @@ ffe_is_digit_string_ (char *s)
int
ffe_decode_option (argc, argv)
- int argc;
+ int argc ATTRIBUTE_UNUSED;
char **argv;
{
char *opt = argv[0];
@@ -177,10 +178,6 @@ ffe_decode_option (argc, argv)
}
else if (strcmp (&opt[2], "null-version") == 0)
ffe_set_is_null_version (TRUE);
- else if (strcmp (&opt[2], "ident") == 0)
- ffe_set_is_ident (TRUE);
- else if (strcmp (&opt[2], "no-ident") == 0)
- ffe_set_is_ident (FALSE);
else if (strcmp (&opt[2], "f66") == 0)
{
ffe_set_is_onetrip (TRUE);
@@ -220,6 +217,10 @@ ffe_decode_option (argc, argv)
ffe_set_is_f2c_library (TRUE);
else if (strcmp (&opt[2], "no-f2c-library") == 0)
ffe_set_is_f2c_library (FALSE);
+ else if (strcmp (&opt[2], "flatten-arrays") == 0)
+ ffe_set_is_flatten_arrays (TRUE);
+ else if (strcmp (&opt[2], "no-flatten-arrays") == 0)
+ ffe_set_is_flatten_arrays (FALSE);
else if (strcmp (&opt[2], "free-form") == 0)
ffe_set_is_free_form (TRUE);
else if (strcmp (&opt[2], "no-free-form") == 0)
@@ -240,18 +241,6 @@ ffe_decode_option (argc, argv)
warning ("%s no longer supported -- try -fvxt", opt);
else if (strcmp (&opt[2], "f90-not-vxt") == 0)
warning ("%s no longer supported -- try -fno-vxt -ff90", opt);
- else if (strcmp (&opt[2], "ugly") == 0)
- {
- warning ("%s is overloaded with meanings and likely to be removed;", opt);
- warning ("use only the specific -fugly-* options you need");
- ffe_set_is_ugly_args (TRUE);
- ffe_set_is_ugly_assign (TRUE);
- ffe_set_is_ugly_assumed (TRUE);
- ffe_set_is_ugly_comma (TRUE);
- ffe_set_is_ugly_complex (TRUE);
- ffe_set_is_ugly_init (TRUE);
- ffe_set_is_ugly_logint (TRUE);
- }
else if (strcmp (&opt[2], "no-ugly") == 0)
{
ffe_set_is_ugly_args (FALSE);
@@ -334,6 +323,14 @@ ffe_decode_option (argc, argv)
ffe_set_is_globals (TRUE);
else if (strcmp (&opt[2], "no-globals") == 0)
ffe_set_is_globals (FALSE);
+ else if (strcmp (&opt[2], "bounds-check") == 0)
+ ffe_set_is_subscript_check (TRUE);
+ else if (strcmp (&opt[2], "no-bounds-check") == 0)
+ ffe_set_is_subscript_check (FALSE);
+ else if (strcmp (&opt[2], "fortran-bounds-check") == 0)
+ ffe_set_is_subscript_check (TRUE);
+ else if (strcmp (&opt[2], "no-fortran-bounds-check") == 0)
+ ffe_set_is_subscript_check (FALSE);
else if (strcmp (&opt[2], "typeless-boz") == 0)
ffe_set_is_typeless_boz (TRUE);
else if (strcmp (&opt[2], "no-typeless-boz") == 0)
diff --git a/contrib/gcc/f/top.h b/contrib/gcc/f/top.h
index bae6787..c5deea8 100644
--- a/contrib/gcc/f/top.h
+++ b/contrib/gcc/f/top.h
@@ -1,6 +1,6 @@
/* top.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995-1997 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -90,14 +90,15 @@ extern bool ffe_is_dollar_ok_;
extern bool ffe_is_f2c_;
extern bool ffe_is_f2c_library_;
extern bool ffe_is_ffedebug_;
+extern bool ffe_is_flatten_arrays_;
extern bool ffe_is_free_form_;
extern bool ffe_is_globals_;
-extern bool ffe_is_ident_;
extern bool ffe_is_init_local_zero_;
extern bool ffe_is_mainprog_;
extern bool ffe_is_null_version_;
extern bool ffe_is_onetrip_;
extern bool ffe_is_silent_;
+extern bool ffe_is_subscript_check_;
extern bool ffe_is_typeless_boz_;
extern bool ffe_is_pedantic_;
extern bool ffe_is_saveall_;
@@ -178,9 +179,9 @@ void ffe_terminate_4 (void);
#define ffe_is_f2c() ffe_is_f2c_
#define ffe_is_f2c_library() ffe_is_f2c_library_
#define ffe_is_ffedebug() ffe_is_ffedebug_
+#define ffe_is_flatten_arrays() ffe_is_flatten_arrays_
#define ffe_is_free_form() ffe_is_free_form_
#define ffe_is_globals() ffe_is_globals_
-#define ffe_is_ident() ffe_is_ident_
#define ffe_is_init_local_zero() ffe_is_init_local_zero_
#define ffe_is_mainprog() ffe_is_mainprog_
#define ffe_is_null_version() ffe_is_null_version_
@@ -190,6 +191,7 @@ void ffe_terminate_4 (void);
#define ffe_is_saveall() ffe_is_saveall_
#define ffe_is_second_underscore() ffe_is_second_underscore_
#define ffe_is_silent() ffe_is_silent_
+#define ffe_is_subscript_check() ffe_is_subscript_check_
#define ffe_is_typeless_boz() ffe_is_typeless_boz_
#define ffe_is_ugly_args() ffe_is_ugly_args_
#define ffe_is_ugly_assign() ffe_is_ugly_assign_
@@ -230,9 +232,9 @@ void ffe_terminate_4 (void);
#define ffe_set_is_f2c(f) (ffe_is_f2c_ = (f))
#define ffe_set_is_f2c_library(f) (ffe_is_f2c_library_ = (f))
#define ffe_set_is_ffedebug(f) (ffe_is_ffedebug_ = (f))
+#define ffe_set_is_flatten_arrays(f) (ffe_is_flatten_arrays_ = (f))
#define ffe_set_is_free_form(f) (ffe_is_free_form_ = (f))
#define ffe_set_is_globals(f) (ffe_is_globals_ = (f))
-#define ffe_set_is_ident(f) (ffe_is_ident_ = (f))
#define ffe_set_is_init_local_zero(f) (ffe_is_init_local_zero_ = (f))
#define ffe_set_is_mainprog(f) (ffe_is_mainprog_ = (f))
#define ffe_set_is_null_version(f) (ffe_is_null_version_ = (f))
@@ -241,6 +243,7 @@ void ffe_terminate_4 (void);
#define ffe_set_is_saveall(f) (ffe_is_saveall_ = (f))
#define ffe_set_is_second_underscore(f) (ffe_is_second_underscore_ = (f))
#define ffe_set_is_silent(f) (ffe_is_silent_ = (f))
+#define ffe_set_is_subscript_check(f) (ffe_is_subscript_check_ = (f))
#define ffe_set_is_typeless_boz(f) (ffe_is_typeless_boz_ = (f))
#define ffe_set_is_ugly_args(f) (ffe_is_ugly_args_ = (f))
#define ffe_set_is_ugly_assign(f) (ffe_is_ugly_assign_ = (f))
diff --git a/contrib/gcc/f/toplev.j b/contrib/gcc/f/toplev.j
index 9ee892b..4b8b797 100644
--- a/contrib/gcc/f/toplev.j
+++ b/contrib/gcc/f/toplev.j
@@ -1,6 +1,6 @@
/* toplev.j -- Wrapper for GCC's toplev.h
Copyright (C) 1998 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/tree.j b/contrib/gcc/f/tree.j
index 009af12..b0bf98a 100644
--- a/contrib/gcc/f/tree.j
+++ b/contrib/gcc/f/tree.j
@@ -1,6 +1,6 @@
/* tree.j -- Wrapper for GCC's tree.h
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/type.c b/contrib/gcc/f/type.c
index 76f0e87..7625cbb 100644
--- a/contrib/gcc/f/type.c
+++ b/contrib/gcc/f/type.c
@@ -1,6 +1,6 @@
/* Implementation of Fortran type abstraction
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/type.h b/contrib/gcc/f/type.h
index 94d6404..aaae51e 100644
--- a/contrib/gcc/f/type.h
+++ b/contrib/gcc/f/type.h
@@ -1,6 +1,6 @@
/* Interface definitions for Fortran type abstraction
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/f/version.c b/contrib/gcc/f/version.c
index 3d5baf7..97605df 100644
--- a/contrib/gcc/f/version.c
+++ b/contrib/gcc/f/version.c
@@ -1 +1 @@
-char *ffe_version_string = "0.5.24-19981002";
+const char *ffe_version_string = "0.5.25 19990816 (release)";
diff --git a/contrib/gcc/f/version.h b/contrib/gcc/f/version.h
index cd578a8..62f941d 100644
--- a/contrib/gcc/f/version.h
+++ b/contrib/gcc/f/version.h
@@ -1,6 +1,6 @@
#ifndef _H_f_version
#define _H_f_version
-extern char *ffe_version_string;
+extern const char *ffe_version_string;
#endif
diff --git a/contrib/gcc/f/where.c b/contrib/gcc/f/where.c
index 89e0f85..2792899 100644
--- a/contrib/gcc/f/where.c
+++ b/contrib/gcc/f/where.c
@@ -1,6 +1,6 @@
/* where.c -- Implementation File (module.c template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -38,7 +38,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
struct _ffewhere_line_ ffewhere_unknown_line_
=
-{NULL, NULL, 0, 0, 0};
+{NULL, NULL, 0, 0, 0, {0}};
/* Simple definitions and enumerations. */
diff --git a/contrib/gcc/f/where.h b/contrib/gcc/f/where.h
index 2091f36..32b3d4b 100644
--- a/contrib/gcc/f/where.h
+++ b/contrib/gcc/f/where.h
@@ -1,6 +1,6 @@
/* where.h -- Public #include File (module.h template V1.0)
Copyright (C) 1995 Free Software Foundation, Inc.
- Contributed by James Craig Burley (burley@gnu.org).
+ Contributed by James Craig Burley.
This file is part of GNU Fortran.
diff --git a/contrib/gcc/final.c b/contrib/gcc/final.c
index 4b05fc7..a9ae280 100644
--- a/contrib/gcc/final.c
+++ b/contrib/gcc/final.c
@@ -1,5 +1,5 @@
/* Convert RTL to assembler code and output it, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -45,11 +45,6 @@ Boston, MA 02111-1307, USA. */
FUNCTION_EPILOGUE. Those instructions never exist as rtl. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "tree.h"
@@ -69,6 +64,7 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "reload.h"
+#include "intl.h"
/* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
@@ -135,11 +131,6 @@ Boston, MA 02111-1307, USA. */
#define JUMP_TABLES_IN_TEXT_SECTION 0
#endif
-/* Nonzero means this function is a leaf function, with no function calls.
- This variable exists to be examined in FUNCTION_PROLOGUE
- and FUNCTION_EPILOGUE. Always zero, unless set by some action. */
-int leaf_function;
-
/* Last insn processed by final_scan_insn. */
static rtx debug_insn = 0;
@@ -287,7 +278,7 @@ static int bb_func_label_num = -1; /* Current label # for func */
struct bb_str {
struct bb_str *next; /* pointer to next string */
- char *string; /* string */
+ const char *string; /* string */
int label_num; /* label number */
int length; /* string length */
};
@@ -304,7 +295,7 @@ static int asm_insn_count PROTO((rtx));
static void profile_function PROTO((FILE *));
static void profile_after_prologue PROTO((FILE *));
static void add_bb PROTO((FILE *));
-static int add_bb_string PROTO((char *, int));
+static int add_bb_string PROTO((const char *, int));
static void output_source_line PROTO((FILE *, rtx));
static rtx walk_alter_subreg PROTO((rtx));
static void output_asm_name PROTO((void));
@@ -340,7 +331,7 @@ init_final (filename)
void
end_final (filename)
- char *filename;
+ const char *filename;
{
int i;
@@ -417,7 +408,7 @@ end_final (filename)
assemble_integer (const0_rtx, pointer_bytes, 1);
/* byte count for extended structure. */
- assemble_integer (GEN_INT (10 * UNITS_PER_WORD), long_bytes, 1);
+ assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, 1);
/* address of function name table */
if (profile_block_flag)
@@ -636,6 +627,9 @@ dbr_sequence_length ()
static short *insn_lengths;
int *insn_addresses;
+/* Max uid for which the above arrays are valid. */
+static int insn_lengths_max_uid;
+
/* Address of insn being processed. Used by `insn_current_length'. */
int insn_current_address;
@@ -682,6 +676,7 @@ init_insn_lengths ()
{
free (insn_lengths);
insn_lengths = 0;
+ insn_lengths_max_uid = 0;
}
if (insn_addresses)
{
@@ -707,7 +702,7 @@ get_attr_length (insn)
int i;
int length = 0;
- if (insn_lengths)
+ if (insn_lengths_max_uid > INSN_UID (insn))
return insn_lengths[INSN_UID (insn)];
else
switch (GET_CODE (insn))
@@ -1004,7 +999,9 @@ shorten_branches (first)
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
rtx old = insn;
- insn = try_split (PATTERN (old), old, 1);
+ /* Don't split the insn if it has been deleted. */
+ if (! INSN_DELETED_P (old))
+ insn = try_split (PATTERN (old), old, 1);
/* When not optimizing, the old insn will be still left around
with only the 'deleted' bit set. Transform it into a note
to avoid confusion of subsequent processing. */
@@ -1137,6 +1134,7 @@ shorten_branches (first)
/* Allocate the rest of the arrays. */
insn_lengths = (short *) xmalloc (max_uid * sizeof (short));
insn_addresses = (int *) xmalloc (max_uid * sizeof (int));
+ insn_lengths_max_uid = max_uid;
/* Syntax errors can lead to labels being outside of the main insn stream.
Initialize insn_addresses, so that we get reproducible results. */
bzero ((char *)insn_addresses, max_uid * sizeof *insn_addresses);
@@ -1322,6 +1320,8 @@ shorten_branches (first)
/* If needed, do any adjustment. */
#ifdef ADJUST_INSN_LENGTH
ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
+ if (insn_lengths[uid] < 0)
+ fatal_insn ("Negative insn length", insn);
#endif
}
@@ -1597,7 +1597,7 @@ final_start_function (first, file, optimize)
int i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (!call_used_regs[i] && !call_fixed_regs[i])
+ if (!call_used_regs[i])
regs_ever_live[i] = 1;
}
#endif
@@ -1636,7 +1636,7 @@ final_start_function (first, file, optimize)
output_source_line (file, first);
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs (first);
#endif
@@ -1871,7 +1871,7 @@ add_bb (file)
static int
add_bb_string (string, perm_p)
- char *string;
+ const char *string;
int perm_p;
{
int len;
@@ -1985,6 +1985,18 @@ final (first, file, optimize, prescan)
max_uid = INSN_UID (insn);
if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
line_note_exists[NOTE_LINE_NUMBER (insn)] = 1;
+#ifdef HAVE_cc0
+ /* If CC tracking across branches is enabled, record the insn which
+ jumps to each branch only reached from one place. */
+ if (optimize && GET_CODE (insn) == JUMP_INSN)
+ {
+ rtx lab = JUMP_LABEL (insn);
+ if (lab && LABEL_NUSES (lab) == 1)
+ {
+ LABEL_REFS (lab) = insn;
+ }
+ }
+#endif
}
/* Initialize insn_eh_region table if eh is being used. */
@@ -2028,7 +2040,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
int prescan;
int nopeepholes;
{
- register int i;
#ifdef HAVE_cc0
rtx set;
#endif
@@ -2177,28 +2188,30 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
PENDING_BLOCKS and output debugging info based on that. */
--block_depth;
+ if (block_depth < 0)
+ abort ();
#ifdef XCOFF_DEBUGGING_INFO
- if (write_symbols == XCOFF_DEBUG && block_depth >= 0)
+ if (write_symbols == XCOFF_DEBUG)
xcoffout_end_block (file, high_block_linenum,
pending_blocks[block_depth]);
#endif
#ifdef DBX_DEBUGGING_INFO
- if (write_symbols == DBX_DEBUG && block_depth >= 0)
+ if (write_symbols == DBX_DEBUG)
ASM_OUTPUT_INTERNAL_LABEL (file, "LBE",
pending_blocks[block_depth]);
#endif
#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG && block_depth >= 0)
+ if (write_symbols == SDB_DEBUG)
sdbout_end_block (file, high_block_linenum,
pending_blocks[block_depth]);
#endif
#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG && block_depth >= 0)
+ if (write_symbols == DWARF_DEBUG)
dwarfout_end_block (pending_blocks[block_depth]);
#endif
#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG && block_depth >= 0)
+ if (write_symbols == DWARF2_DEBUG)
dwarf2out_end_block (pending_blocks[block_depth]);
#endif
}
@@ -2288,7 +2301,33 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
ASM_OUTPUT_ALIGN (file, align);
#endif
}
+#ifdef HAVE_cc0
CC_STATUS_INIT;
+ /* If this label is reached from only one place, set the condition
+ codes from the instruction just before the branch. */
+
+ /* Disabled because some insns set cc_status in the C output code
+ and NOTICE_UPDATE_CC alone can set incorrect status. */
+ if (0 /* optimize && LABEL_NUSES (insn) == 1*/)
+ {
+ rtx jump = LABEL_REFS (insn);
+ rtx barrier = prev_nonnote_insn (insn);
+ rtx prev;
+ /* If the LABEL_REFS field of this label has been set to point
+ at a branch, the predecessor of the branch is a regular
+ insn, and that branch is the only way to reach this label,
+ set the condition codes based on the branch and its
+ predecessor. */
+ if (barrier && GET_CODE (barrier) == BARRIER
+ && jump && GET_CODE (jump) == JUMP_INSN
+ && (prev = prev_nonnote_insn (jump))
+ && GET_CODE (prev) == INSN)
+ {
+ NOTICE_UPDATE_CC (PATTERN (prev), prev);
+ NOTICE_UPDATE_CC (PATTERN (jump), jump);
+ }
+ }
+#endif
if (prescan > 0)
break;
new_block = 1;
@@ -2326,6 +2365,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (GET_CODE (nextbody) == ADDR_VEC
|| GET_CODE (nextbody) == ADDR_DIFF_VEC)
{
+#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
+ /* In this case, the case vector is being moved by the
+ target, so don't output the label at all. Leave that
+ to the back end macros. */
+#else
if (! JUMP_TABLES_IN_TEXT_SECTION)
{
readonly_data_section ();
@@ -2344,6 +2388,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
#else
ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
#endif
+#endif
break;
}
}
@@ -2355,7 +2400,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
{
register rtx body = PATTERN (insn);
int insn_code_number;
- char *template;
+ const char *template;
#ifdef HAVE_cc0
rtx note;
#endif
@@ -2386,7 +2431,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
{
+#if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC))
register int vlen, idx;
+#endif
if (prescan > 0)
break;
@@ -2397,6 +2444,24 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
app_on = 0;
}
+#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
+ if (GET_CODE (body) == ADDR_VEC)
+ {
+#ifdef ASM_OUTPUT_ADDR_VEC
+ ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
+#else
+ abort();
+#endif
+ }
+ else
+ {
+#ifdef ASM_OUTPUT_ADDR_DIFF_VEC
+ ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
+#else
+ abort();
+#endif
+ }
+#else
vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
for (idx = 0; idx < vlen; idx++)
{
@@ -2427,6 +2492,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
CODE_LABEL_NUMBER (PREV_INSN (insn)),
insn);
#endif
+#endif
function_section (current_function_decl);
@@ -2783,27 +2849,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
since `reload' should have changed them so that they do. */
insn_code_number = recog_memoized (insn);
- insn_extract (insn);
- for (i = 0; i < insn_n_operands[insn_code_number]; i++)
- {
- if (GET_CODE (recog_operand[i]) == SUBREG)
- recog_operand[i] = alter_subreg (recog_operand[i]);
- else if (GET_CODE (recog_operand[i]) == PLUS
- || GET_CODE (recog_operand[i]) == MULT)
- recog_operand[i] = walk_alter_subreg (recog_operand[i]);
- }
-
- for (i = 0; i < insn_n_dups[insn_code_number]; i++)
- {
- if (GET_CODE (*recog_dup_loc[i]) == SUBREG)
- *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]);
- else if (GET_CODE (*recog_dup_loc[i]) == PLUS
- || GET_CODE (*recog_dup_loc[i]) == MULT)
- *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]);
- }
+ extract_insn (insn);
+ cleanup_subreg_operands (insn);
#ifdef REGISTER_CONSTRAINTS
- if (! constrain_operands (insn_code_number, 1))
+ if (! constrain_operands (1))
fatal_insn_not_found (insn);
#endif
@@ -2811,8 +2861,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
it is output. */
#ifdef FINAL_PRESCAN_INSN
- FINAL_PRESCAN_INSN (insn, recog_operand,
- insn_n_operands[insn_code_number]);
+ FINAL_PRESCAN_INSN (insn, recog_operand, recog_n_operands);
#endif
#ifdef HAVE_cc0
@@ -2979,6 +3028,35 @@ output_source_line (file, insn)
}
}
+
+/* For each operand in INSN, simplify (subreg (reg)) so that it refers
+ directly to the desired hard register. */
+void
+cleanup_subreg_operands (insn)
+ rtx insn;
+{
+ int i;
+
+ extract_insn (insn);
+ for (i = 0; i < recog_n_operands; i++)
+ {
+ if (GET_CODE (recog_operand[i]) == SUBREG)
+ recog_operand[i] = alter_subreg (recog_operand[i]);
+ else if (GET_CODE (recog_operand[i]) == PLUS
+ || GET_CODE (recog_operand[i]) == MULT)
+ recog_operand[i] = walk_alter_subreg (recog_operand[i]);
+ }
+
+ for (i = 0; i < recog_n_dups; i++)
+ {
+ if (GET_CODE (*recog_dup_loc[i]) == SUBREG)
+ *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]);
+ else if (GET_CODE (*recog_dup_loc[i]) == PLUS
+ || GET_CODE (*recog_dup_loc[i]) == MULT)
+ *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]);
+ }
+}
+
/* If X is a SUBREG, replace it with a REG or a MEM,
based on the thing it is a subreg of. */
@@ -3012,6 +3090,9 @@ alter_subreg (x)
#else
REGNO (x) = REGNO (y) + SUBREG_WORD (x);
#endif
+ /* This field has a different meaning for REGs and SUBREGs. Make sure
+ to clear it! */
+ x->used = 0;
}
else if (GET_CODE (y) == MEM)
{
@@ -3020,8 +3101,7 @@ alter_subreg (x)
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
PUT_CODE (x, MEM);
- MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (y);
+ MEM_COPY_ATTRIBUTES (x, y);
MEM_ALIAS_SET (x) = MEM_ALIAS_SET (y);
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
}
@@ -3223,13 +3303,13 @@ alter_cond (cond)
In an `asm', it's the user's fault; otherwise, the compiler's fault. */
void
-output_operand_lossage (str)
- char *str;
+output_operand_lossage (msgid)
+ const char *msgid;
{
if (this_is_asm_operands)
- error_for_asm (this_is_asm_operands, "invalid `asm': %s", str);
+ error_for_asm (this_is_asm_operands, "invalid `asm': %s", _(msgid));
else
- fatal ("Internal compiler error, output_operand_lossage `%s'", str);
+ fatal ("Internal compiler error, output_operand_lossage `%s'", _(msgid));
}
/* Output of assembler code from a template, and its subroutines. */
@@ -3260,11 +3340,13 @@ output_asm_name ()
if (debug_insn)
{
register int num = INSN_CODE (debug_insn);
- fprintf (asm_out_file, " %s %d %s",
+ fprintf (asm_out_file, "\t%s %d\t%s",
ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]);
if (insn_n_alternatives[num] > 1)
fprintf (asm_out_file, "/%d", which_alternative + 1);
-
+#ifdef HAVE_ATTR_length
+ fprintf (asm_out_file, "\t[length = %d]", get_attr_length (debug_insn));
+#endif
/* Clear this so only the first assembler insn
of any rtl insn will get the special comment for -dp. */
debug_insn = 0;
@@ -3274,10 +3356,10 @@ output_asm_name ()
void
output_asm_insn (template, operands)
- char *template;
+ const char *template;
rtx *operands;
{
- register char *p;
+ register const char *p;
register int c;
/* An insn may return a null string template
@@ -3407,7 +3489,7 @@ output_asm_insn (template, operands)
punctuation character alone, with no operand.
The PRINT_OPERAND macro decides what is actually done. */
#ifdef PRINT_OPERAND_PUNCT_VALID_P
- else if (PRINT_OPERAND_PUNCT_VALID_P (*p))
+ else if (PRINT_OPERAND_PUNCT_VALID_P ((unsigned char)*p))
output_operand (NULL_RTX, *p++);
#endif
else
@@ -3602,11 +3684,11 @@ output_addr_const (file, x)
We handle alternate assembler dialects here, just like output_asm_insn. */
void
-asm_fprintf VPROTO((FILE *file, char *p, ...))
+asm_fprintf VPROTO((FILE *file, const char *p, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
FILE *file;
- char *p;
+ const char *p;
#endif
va_list argptr;
char buf[10];
@@ -3614,9 +3696,9 @@ asm_fprintf VPROTO((FILE *file, char *p, ...))
VA_START (argptr, p);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
file = va_arg (argptr, FILE *);
- p = va_arg (argptr, char *);
+ p = va_arg (argptr, const char *);
#endif
buf[0] = '%';
@@ -3740,9 +3822,7 @@ asm_fprintf VPROTO((FILE *file, char *p, ...))
break;
case 'U':
-#ifdef USER_LABEL_PREFIX
- fprintf (file, "%s", USER_LABEL_PREFIX);
-#endif
+ fputs (user_label_prefix, file);
break;
default:
@@ -3853,6 +3933,22 @@ split_double (value, first, second)
not necessarily BITS_PER_WORD bits. */
REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+ /* If 32 bits is an entire word for the target, but not for the host,
+ then sign-extend on the host so that the number will look the same
+ way on the host that it would on the target. See for instance
+ simplify_unary_operation. The #if is needed to avoid compiler
+ warnings. */
+
+#if HOST_BITS_PER_LONG > 32
+ if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32)
+ {
+ if (l[0] & ((long) 1 << 31))
+ l[0] |= ((long) (-1) << 32);
+ if (l[1] & ((long) 1 << 31))
+ l[1] |= ((long) (-1) << 32);
+ }
+#endif
+
*first = GEN_INT ((HOST_WIDE_INT) l[0]);
*second = GEN_INT ((HOST_WIDE_INT) l[1]);
#else
diff --git a/contrib/gcc/fix-header.c b/contrib/gcc/fix-header.c
index 8ba79ff..af0577e 100644
--- a/contrib/gcc/fix-header.c
+++ b/contrib/gcc/fix-header.c
@@ -1,5 +1,5 @@
/* fix-header.c - Make C header file suitable for C++.
- Copyright (C) 1993, 94-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-98, 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -71,19 +71,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
Written by Per Bothner <bothner@cygnus.com>, July 1993. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
-#include "gansidecl.h"
#include "obstack.h"
#include "scan.h"
#include "cpplib.h"
#include "cpphash.h"
-void fatal PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1;
+static void v_fatal PROTO ((const char *, va_list)) ATTRIBUTE_NORETURN;
+void fatal PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
sstring buf;
@@ -341,7 +336,7 @@ setgid\0setpgid\0setsid\0setuid\0sleep\0sysconf\0tcgetpgrp\0tcsetpgrp\0\
ttyname\0unlink\0write\0" },
{ CONTINUED, POSIX2_SYMBOL, "getopt\0" },
{ CONTINUED, XOPEN_EXTENDED_SYMBOL,
- "lockf\0gethostid\0gethostname\0readlink\0" },
+ "lockf\0gethostid\0gethostname\0readlink\0symlink\0" },
{ "utime.h", POSIX1_SYMBOL, "utime\0" },
@@ -372,16 +367,6 @@ xfree (ptr)
free (ptr);
}
-/* Avoid error if config defines abort as fancy_abort.
- It's not worth "really" implementing this because ordinary
- compiler users never run fix-header. */
-
-void
-fancy_abort ()
-{
- abort ();
-}
-
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free xfree
struct obstack scan_file_obstack;
@@ -401,7 +386,7 @@ lookup_std_proto (name, name_length)
if (hash_tab[i] == 0)
return NULL;
fn = &std_protos[hash_tab[i]];
- if (strlen (fn->fname) == name_length
+ if ((int) strlen (fn->fname) == name_length
&& strncmp (fn->fname, name, name_length) == 0)
return fn;
i = (i+1) % HASH_SIZE;
@@ -637,7 +622,7 @@ read_scan_file (in_fname, argc, argv)
obstack_init (&scan_file_obstack);
cpp_reader_init (&scan_in);
- scan_in.data = &scan_options;
+ scan_in.opts = &scan_options;
cpp_options_init (&scan_options);
i = cpp_handle_options (&scan_in, argc, argv);
if (i < argc && ! CPP_FATAL_ERRORS (&scan_in))
@@ -697,7 +682,7 @@ read_scan_file (in_fname, argc, argv)
/* Append "_filbuf" and/or "_flsbuf" to the required functions. */
if (need_filbuf + need_flsbuf)
{
- char *new_list;
+ const char *new_list;
if (need_filbuf)
SET_REQUIRED (fn);
if (need_flsbuf)
@@ -876,15 +861,6 @@ write_rbrac ()
#endif
}
-char *
-xstrdup (str)
- char *str;
-{
- char *copy = (char *) xmalloc (strlen (str) + 1);
- strcpy (copy, str);
- return copy;
-}
-
/* Returns 1 iff the file is properly protected from multiple inclusion:
#ifndef PROTECT_NAME
#define PROTECT_NAME
@@ -1151,7 +1127,7 @@ main (argc, argv)
special_file_handling = stdio_h;
include_entry = std_include_table;
while (include_entry->name != NULL
- && (include_entry->name == CONTINUED
+ && ((strcmp (include_entry->name, CONTINUED) == 0)
|| strcmp (inc_filename, include_entry->name) != 0))
include_entry++;
@@ -1164,7 +1140,7 @@ main (argc, argv)
if (entry->flags)
add_symbols (entry->flags, entry->names);
entry++;
- if (entry->name != CONTINUED)
+ if (strcmp (entry->name, CONTINUED) != 0)
break;
}
}
@@ -1325,71 +1301,6 @@ main (argc, argv)
return 0;
}
-/* Stub error functions. These replace cpperror.c,
- because we want to suppress error messages. */
-
-void
-cpp_file_line_for_message (pfile, filename, line, column)
- cpp_reader * pfile;
- char *filename;
- int line, column;
-{
- if (!verbose)
- return;
- if (column > 0)
- fprintf (stderr, "%s:%d:%d: ", filename, line, column);
- else
- fprintf (stderr, "%s:%d: ", filename, line);
-}
-
-void
-cpp_print_containing_files (pfile)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
-{
-}
-
-/* IS_ERROR is 2 for fatal error, 1 for error, 0 for warning */
-
-void
-v_cpp_message (pfile, is_error, msg, ap)
- cpp_reader *pfile;
- int is_error;
- const char *msg;
- va_list ap;
-{
- if (is_error == 1)
- pfile->errors++;
- else if (is_error > 1)
- pfile->errors = CPP_FATAL_LIMIT;
- if (!verbose)
- return;
- if (!is_error)
- fprintf (stderr, "warning: ");
- vfprintf (stderr, msg, ap);
- fprintf (stderr, "\n");
-}
-
-void
-cpp_message VPROTO ((cpp_reader *pfile, int is_error, const char *msg, ...))
-{
-#ifndef __STDC__
- cpp_reader *pfile;
- int is_error;
- const char *msg;
-#endif
- va_list ap;
-
- VA_START (ap, msg);
-
-#ifndef __STDC__
- pfile = va_arg (ap, cpp_reader *);
- is_error = va_arg (ap, const int);
- msg = va_arg (ap, const char *);
-#endif
-
- v_cpp_message(pfile, is_error, msg, ap);
- va_end(ap);
-}
static void
v_fatal (str, ap)
@@ -1406,46 +1317,17 @@ v_fatal (str, ap)
void
fatal VPROTO ((const char *str, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
const char *str;
#endif
va_list ap;
VA_START(ap, str);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
str = va_arg (ap, const char *);
#endif
v_fatal(str, ap);
va_end(ap);
}
-
-void
-cpp_fatal VPROTO ((cpp_reader * pfile, const char *str, ...))
-{
-#ifndef __STDC__
- cpp_reader * pfile;
- const char *str;
-#endif
- va_list ap;
-
- VA_START(ap, str);
-
-#ifndef __STDC__
- pfile = va_arg (ap, cpp_reader *);
- str = va_arg (ap, const char *);
-#endif
-
- v_fatal(str, ap);
- va_end(ap);
-}
-
-void
-cpp_pfatal_with_name (pfile, name)
- cpp_reader *pfile;
- const char *name;
-{
- cpp_perror_with_name (pfile, name);
- exit (FATAL_EXIT_CODE);
-}
diff --git a/contrib/gcc/fixincludes b/contrib/gcc/fixincludes
index 09e10bb..e5cc1c3 100755
--- a/contrib/gcc/fixincludes
+++ b/contrib/gcc/fixincludes
@@ -7,53 +7,68 @@
# Directory containing the original header files.
# (This was named INCLUDES, but that conflicts with a name in Makefile.in.)
-INPUT=${2-${INPUT-/usr/include}}
+if [ "x$1" = "x" ]
+then echo fixincludes: no output directory specified
+exit 1
+fi
+
+LIB=${1}
+shift
-# Directory in which to store the results.
-LIB=${1?"fixincludes: output directory not specified"}
+# Make sure it exists.
+if [ ! -d $LIB ]; then
+ mkdir $LIB || {
+ echo fixincludes: output dir '`'$LIB"' cannot be created"
+ exit 1
+ }
+else
+ ( \cd $LIB && touch DONE && rm DONE ) || {
+ echo fixincludes: output dir '`'$LIB"' is an invalid directory"
+ exit 1
+ }
+fi
# Define what target system we're fixing.
+#
if test -r ./Makefile; then
- target_canonical="`sed -n -e 's,^target[ ]*=[ ]*\(.*\)$,\1,p' < Makefile`"
- test -z "${target_canonical}" && target_canonical=unknown
-else
- target_canonical=unknown
+ target_canonical="`sed -n -e 's,^target[ ]*=[ ]*\(.*\)$,\1,p' < Makefile`"
+fi
+
+# If not from the Makefile, then try config.guess
+#
+if test -z "${target_canonical}" ; then
+ if test -x ./config.guess ; then
+ target_canonical="`config.guess`" ; fi
+ test -z "${target_canonical}" && target_canonical=unknown
fi
+export target_canonical
+# # # # # # # # # # # # # # # # # # # # #
+#
# Define PWDCMD as a command to use to get the working dir
# in the form that we want.
PWDCMD=pwd
-case "`pwd`" in
+
+case "`$PWDCMD`" in
//*)
- # On an Apollo, discard everything before `/usr'.
- PWDCMD="eval pwd | sed -e 's,.*/usr/,/usr/,'"
- ;;
+ # On an Apollo, discard everything before `/usr'.
+ PWDCMD="eval pwd | sed -e 's,.*/usr/,/usr/,'"
+ ;;
esac
# Original directory.
ORIGDIR=`${PWDCMD}`
-# Make sure it exists.
-if [ ! -d $LIB ]; then
- mkdir $LIB || exit 1
-fi
-
# Make LIB absolute only if needed to avoid problems with the amd.
case $LIB in
/*)
- ;;
+ ;;
*)
- cd $LIB; LIB=`${PWDCMD}`
- ;;
+ cd $LIB; LIB=`${PWDCMD}`
+ ;;
esac
-# Fail if no arg to specify a directory for the output.
-if [ x$1 = x ]
-then echo fixincludes: no output directory specified
-exit 1
-fi
-
-echo Building fixed headers in ${LIB}
+echo Fixing headers into ${LIB} for ${target_canonical} target
# Determine whether this system has symbolic links.
if ln -s X $LIB/ShouldNotExist 2>/dev/null; then
@@ -66,8 +81,30 @@ else
LINKS=false
fi
+# # # # # # # # # # # # # # # # # # # # #
+#
+# Search each input directory for broken header files.
+# This loop ends near the end of the file.
+#
+if test $# -eq 0
+then
+ INPUTLIST="/usr/include"
+else
+ INPUTLIST="$@"
+fi
+
+for INPUT in ${INPUTLIST} ; do
+
+cd ${ORIGDIR}
+
+cd ${INPUT} || continue
+INPUT=`${PWDCMD}`
+
+#
+# # # # # # # # # # # # # # # # # # # # #
+#
echo Finding directories and links to directories
-cd ${INPUT}
+
# Find all directories and all symlinks that point to directories.
# Put the list in $files.
# Each time we find a symlink, add it to newdirs
@@ -301,6 +338,7 @@ while [ $# != 0 ]; do
/#[ ]*define[ ]*[ ]CTRL/ s/'\''\([cgx]\)'\''/\1/g
/#[ ]*define[ ]*[ ]_CTRL/ s/'\''\([cgx]\)'\''/\1/g
/#[ ]*define.BSD43_CTRL/ s/'\''\([cgx]\)'\''/\1/g
+ /#[ ]*define[ ]*[ ][_]*ISCTRL/ s/'\''\([cgx]\)'\''/\1/g
/#[ ]*[el]*if/{
s/[a-zA-Z0-9_][a-zA-Z0-9_]*/ & /g
@@ -964,6 +1002,7 @@ if [ -r ${LIB}/$file ]; then
-e 's/char[ ]*\*[ ]*calloc/void \* calloc/g' \
-e 's/char[ ]*\*[ ]*malloc/void \* malloc/g' \
-e 's/char[ ]*\*[ ]*realloc/void \* realloc/g' \
+ -e 's/char[ ]*\*[ ]*bsearch/void \* bsearch/g' \
-e 's/int[ ][ ]*exit/void exit/g' \
-e "/$size_t_pattern/"'i\
#ifndef _GCC_SIZE_T\
@@ -1657,6 +1696,34 @@ if [ -r ${LIB}/$file ]; then
fi
fi
+# sys/utsname.h on Ultrix V4.[35] puts the declaration of uname before the
+# definition of struct utsname, so the prototype (added by fixproto) causes
+# havoc.
+file=sys/utsname.h
+if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
+ cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
+ chmod +w ${LIB}/$file 2>/dev/null
+fi
+
+if [ -r ${LIB}/$file ] \
+ && grep 'ULTRIX' ${LIB}/$file >/dev/null; then
+ echo Fixing $file, uname declaration
+ sed -e '/^[ ]*extern[ ]*int[ ]*uname();$/i\
+struct utsname;
+'\
+ ${LIB}/$file > ${LIB}/${file}.sed
+ rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
+ if cmp $file ${LIB}/$file >/dev/null 2>&1; then
+ rm -f ${LIB}/$file
+ else
+ # Find any include directives that use "file".
+ for include in `egrep '^[ ]*#[ ]*include[ ]*"[^/]' ${LIB}/$file | sed -e 's/^[ ]*#[ ]*include[ ]*"\([^"]*\)".*$/\1/'`; do
+ dir=`echo $file | sed -e s'|/[^/]*$||'`
+ required="$required ${INPUT} $dir/$include ${LIB}/$dir/$include"
+ done
+ fi
+fi
+
# sys/wait.h on AIX 3.2.5 puts the declaration of wait3 before the definition
# of struct rusage, so the prototype (added by fixproto) causes havoc.
file=sys/wait.h
@@ -2186,16 +2253,16 @@ if [ -r ${LIB}/$file ]; then
fi
# For C++, avoid any typedef or macro definition of bool, and use the
-# built in type instead.
-for files in curses.h; do
- if [ -r $file ] && egrep bool $file >/dev/null 2>&1; then
- if [ ! -r ${LIB}/$file ]; then
- cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
- chmod +w ${LIB}/$file 2>/dev/null
- chmod a+r ${LIB}/$file 2>/dev/null
- fi
-
- echo Fixing $file
+# built in type instead. HP/UX 10.20, at least, also has it
+# in curses_colr/curses.h.
+for file in curses.h curses_colr/curses.h ; do
+ if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
+ cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
+ chmod +w ${LIB}/$file 2>/dev/null
+ chmod a+r ${LIB}/$file 2>/dev/null
+ fi
+ if [ -r ${LIB}/$file ] && egrep bool ${LIB}/$file >/dev/null 2>&1; then
+ echo Fixing $file, typedef or macro for bool is invalid in C++
sed -e '/^#[ ]*define[ ][ ]*bool[ ][ ]*char[ ]*$/i\
#ifndef __cplusplus
'\
@@ -3177,10 +3244,22 @@ find . -name DONE -exec rm -f '{}' ';'
echo 'Removing unneeded directories:'
cd $LIB
-files=`find . -type d -print | sort -r`
+files=`find . -type d \! -name '.' -print | sort -r`
for file in $files; do
rmdir $LIB/$file > /dev/null 2>&1
done
+# # # # # # # # # # # # # # # # # # # # #
+#
+# End of for INPUT directories
+#
+done
+#
+# # # # # # # # # # # # # # # # # # # # #
+
+cd $ORIGDIR
+rm -f include/assert.h
+cp ${srcdir}/assert.h include/assert.h || exit 1
+chmod a+r include/assert.h
exit 0
diff --git a/contrib/gcc/fixproto b/contrib/gcc/fixproto
index cd495e6..9e02211 100755
--- a/contrib/gcc/fixproto
+++ b/contrib/gcc/fixproto
@@ -4,7 +4,7 @@
# fixproto TARGET-DIR SOURCE-DIR-ALL SOURCE-DIR-STD
#
# COPYRIGHT
-# Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+# Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
# This file is part of GNU CC.
#
# GNU CC is free software; you can redistribute it and/or modify
@@ -54,12 +54,27 @@
# Ron Guilmette (rfg@netcom.com) (original idea and code)
# Per Bothner (bothner@cygnus.com) (major re-write)
-progname=$0
-progname=`basename $progname`
+dirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'`
+progname=`echo "$0" | sed 's,.*/,,'`
original_dir=`pwd`
FIX_HEADER=${FIX_HEADER-$original_dir/fix-header}
DEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}"
+if mkdir -p . 2> /dev/null; then
+ # Great, mkdir accepts -p
+ mkinstalldirs="mkdir -p"
+else
+ # We expect mkinstalldirs to be passed in the environment.
+ # If it is not, assume it is in the directory that contains this script.
+ mkinstalldirs=${mkinstalldirs-"/bin/sh $dirname/mkinstalldirs"}
+ if $mkinstalldirs . 2> /dev/null; then
+ :
+ else
+ # But, in case of failure, fallback to plain mkdir, and hope it works
+ mkinstalldirs=mkdir
+ fi
+fi
+
if [ `echo $1 | wc -w` = 0 ] ; then
echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \]
exit 1
@@ -94,7 +109,7 @@ fi
if [ \! -d $abs_target_dir ] ; then
echo $progname\: creating directory $rel_target_dir
- mkdir $abs_target_dir
+ $mkinstalldirs $abs_target_dir
fi
echo $progname\: populating \`$rel_target_dir\'
@@ -175,7 +190,7 @@ for code in ALL STD ; do
abs_target_subdir=${abs_target_dir}/${rel_source_subdir}
if [ \! -d $abs_target_subdir ] ; then
- if mkdir $abs_target_subdir ; then
+ if $mkinstalldirs $abs_target_subdir ; then
subdirs_made="$abs_target_subdir $subdirs_made"
fi
fi
@@ -202,7 +217,7 @@ for code in ALL STD ; do
# Create the dir where this file will go when fixed.
xxdir=`echo ./$file | sed -e 's|/[^/]*$||'`
if [ \! -d $abs_target_subdir/$xxdir ] ; then
- if mkdir $abs_target_subdir/$xxdir ; then
+ if $mkinstalldirs $abs_target_subdir/$xxdir ; then
subdirs_made="$abs_target_subdir/$xxdir $subdirs_made"
fi
fi
diff --git a/contrib/gcc/flags.h b/contrib/gcc/flags.h
index 9fa976b..a3cc073 100644
--- a/contrib/gcc/flags.h
+++ b/contrib/gcc/flags.h
@@ -1,5 +1,5 @@
/* Compilation switch flag definitions for GNU CC.
- Copyright (C) 1987, 88, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 94-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -276,10 +276,14 @@ extern int flag_no_peephole;
extern int flag_volatile;
-/* Nonzero means treat all global and extern variables as global. */
+/* Nonzero means treat all global and extern variables as volatile. */
extern int flag_volatile_global;
+/* Nonzero means treat all static variables as volatile. */
+
+extern int flag_volatile_static;
+
/* Nonzero allows GCC to violate some IEEE or ANSI rules regarding math
operations in the interest of optimization. For example it allows
GCC to assume arguments to sqrt are nonnegative numbers, allowing
@@ -287,14 +291,20 @@ extern int flag_volatile_global;
extern int flag_fast_math;
-/* Nonzero means to run loop optimizations twice. */
+/* Nonzero means the front end generally wants `errno' maintained by math
+ operations, like built-in SQRT, unless overridden by flag_fast_math. */
-extern int flag_rerun_loop_opt;
+extern int flag_errno_math;
+
+/* 0 means straightforward implementation of complex divide acceptable.
+ 1 means wide ranges of inputs must work for complex divide.
+ 2 means C9X-like requirements for complex divide (not yet implemented). */
-/* Nonzero means to assume that a structure or an array reference at
- a varying address cannot alias a scalar at a fixed address. */
+extern int flag_complex_divide_method;
-extern int flag_structure_noalias;
+/* Nonzero means to run loop optimizations twice. */
+
+extern int flag_rerun_loop_opt;
/* Nonzero means make functions that look like good inline candidates
go inline. */
@@ -350,17 +360,22 @@ extern int flag_schedule_interblock;
extern int flag_schedule_speculative;
extern int flag_schedule_speculative_load;
extern int flag_schedule_speculative_load_dangerous;
+#endif /* HAIFA */
/* flag_on_branch_count_reg means try to replace add-1,compare,branch tupple
by a cheaper branch, on a count register. */
extern int flag_branch_on_count_reg;
-#endif /* HAIFA */
/* Nonzero means put things in delayed-branch slots if supported. */
extern int flag_delayed_branch;
+/* Nonzero means suppress output of instruction numbers and line number
+ notes in debugging dumps. */
+
+extern int flag_dump_unnumbered;
+
/* Nonzero means pretend it is OK to examine bits of target floats,
even if that isn't true. The resulting code will have incorrect constants,
but the same series of instructions that the native compiler would make. */
@@ -403,6 +418,10 @@ extern int flag_inhibit_size_directive;
extern int flag_function_sections;
+/* ... and similar for data. */
+
+extern int flag_data_sections;
+
/* -fverbose-asm causes extra commentary information to be produced in
the generated assembly code (to make it more readable). This option
is generally only of use to those who actually need to read the
@@ -449,6 +468,9 @@ extern int flag_stack_check;
/* Do the full regmove optimization pass. */
extern int flag_regmove;
+
+/* Instrument functions with calls at entry and exit, for profiling. */
+extern int flag_instrument_function_entry_exit;
/* Other basic status info about current function. */
@@ -495,3 +517,24 @@ extern int current_function_is_thunk;
/* Value of the -G xx switch, and whether it was passed or not. */
extern int g_switch_value;
extern int g_switch_set;
+
+/* Value of the -finline-limit flag. */
+
+extern int inline_max_insns;
+
+/* Nonzero if we dump in VCG format, not plain text. */
+extern int dump_for_graph;
+
+/* Selection of the graph form. */
+enum graph_dump_types
+{
+ no_graph = 0,
+ vcg
+};
+extern enum graph_dump_types graph_dump_format;
+
+/* Nonzero means ignore `#ident' directives. 0 means handle them.
+ On SVR4 targets, it also controls whether or not to emit a
+ string identifying the compiler. */
+
+extern int flag_no_ident;
diff --git a/contrib/gcc/floatlib.c b/contrib/gcc/floatlib.c
index e9e9dea..dc79139 100644
--- a/contrib/gcc/floatlib.c
+++ b/contrib/gcc/floatlib.c
@@ -17,6 +17,7 @@ host such as a VAX.
If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
+--> Double precision floating support added by James Carlson on 20 April 1998.
**
** Pat Wood
@@ -54,7 +55,6 @@ If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
*/
/* the following deal with IEEE single-precision numbers */
-#define D_PHANTOM_BIT 0x00100000
#define EXCESS 126
#define SIGNBIT 0x80000000
#define HIDDEN (1 << 23)
@@ -70,10 +70,12 @@ If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
(fp.l.lower >> 22))
+#define HIDDEND_LL ((long long)1 << 52)
+#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
+#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m))
/* define SWAP for 386/960 reverse-byte-order brain-damaged CPUs */
-union double_long
- {
+union double_long {
double d;
#ifdef SWAP
struct {
@@ -86,7 +88,8 @@ union double_long
unsigned long lower;
} l;
#endif
- };
+ long long ll;
+};
union float_long
{
@@ -94,38 +97,7 @@ union float_long
long l;
};
- struct _ieee {
-#ifdef SWAP
- unsigned mantissa2 : 32;
- unsigned mantissa1 : 20;
- unsigned exponent : 11;
- unsigned sign : 1;
-#else
- unsigned exponent : 11;
- unsigned sign : 1;
- unsigned mantissa2 : 32;
- unsigned mantissa1 : 20;
-#endif
- };
-
- union _doubleu {
- double d;
- struct _ieee ieee;
-#ifdef SWAP
- struct {
- unsigned long lower;
- long upper;
- } l;
-#else
- struct {
- long upper;
- unsigned long lower;
- } l;
-#endif
- };
-
/* add two floats */
-
float
__addsf3 (float a1, float a2)
{
@@ -138,18 +110,22 @@ __addsf3 (float a1, float a2)
fl2.f = a2;
/* check for zero args */
- if (!fl1.l)
- return (fl2.f);
+ if (!fl1.l) {
+ fl1.f = fl2.f;
+ goto test_done;
+ }
if (!fl2.l)
- return (fl1.f);
+ goto test_done;
exp1 = EXP (fl1.l);
exp2 = EXP (fl2.l);
if (exp1 > exp2 + 25)
- return (fl1.l);
- if (exp2 > exp1 + 25)
- return (fl2.l);
+ goto test_done;
+ if (exp2 > exp1 + 25) {
+ fl1.f = fl2.f;
+ goto test_done;
+ }
/* do everything in excess precision so's we can round later */
mant1 = MANT (fl1.l) << 6;
@@ -176,8 +152,10 @@ __addsf3 (float a1, float a2)
mant1 = -mant1;
sign = SIGNBIT;
}
- else if (!mant1)
- return (0);
+ else if (!mant1) {
+ fl1.f = 0;
+ goto test_done;
+ }
/* normalize up */
while (!(mant1 & 0xE0000000))
@@ -211,11 +189,11 @@ __addsf3 (float a1, float a2)
/* pack up and go home */
fl1.l = PACK (sign, exp1, mant1);
+test_done:
return (fl1.f);
}
/* subtract two floats */
-
float
__subsf3 (float a1, float a2)
{
@@ -236,7 +214,6 @@ __subsf3 (float a1, float a2)
}
/* compare two floats */
-
long
__cmpsf2 (float a1, float a2)
{
@@ -258,7 +235,6 @@ __cmpsf2 (float a1, float a2)
}
/* multiply two floats */
-
float
__mulsf3 (float a1, float a2)
{
@@ -270,8 +246,10 @@ __mulsf3 (float a1, float a2)
fl1.f = a1;
fl2.f = a2;
- if (!fl1.l || !fl2.l)
- return (0);
+ if (!fl1.l || !fl2.l) {
+ fl1.f = 0;
+ goto test_done;
+ }
/* compute sign and exponent */
sign = SIGN (fl1.l) ^ SIGN (fl2.l);
@@ -286,29 +264,34 @@ __mulsf3 (float a1, float a2)
result += ((fl1.l & 0xFF) * (fl2.l >> 8)) >> 8;
result += ((fl2.l & 0xFF) * (fl1.l >> 8)) >> 8;
- if (result & 0x80000000)
+ result >>= 2;
+ if (result & 0x20000000)
{
/* round */
- result += 0x80;
- result >>= 8;
+ result += 0x20;
+ result >>= 6;
}
else
{
/* round */
- result += 0x40;
- result >>= 7;
+ result += 0x10;
+ result >>= 5;
exp--;
}
+ if (result & (HIDDEN<<1)) {
+ result >>= 1;
+ exp++;
+ }
result &= ~HIDDEN;
/* pack up and go home */
fl1.l = PACK (sign, exp, result);
+test_done:
return (fl1.f);
}
/* divide two floats */
-
float
__divsf3 (float a1, float a2)
{
@@ -375,7 +358,6 @@ __divsf3 (float a1, float a2)
}
/* convert int to double */
-
double
__floatsidf (register long a1)
{
@@ -415,9 +397,51 @@ __floatsidf (register long a1)
return (dl.d);
}
-/* negate a float */
+double
+__floatdidf (register long long a1)
+{
+ register int exp = 63 + EXCESSD;
+ union double_long dl;
+
+ dl.l.upper = dl.l.lower = 0;
+ if (a1 == 0)
+ return (dl.d);
+
+ if (a1 < 0) {
+ dl.l.upper = SIGNBIT;
+ a1 = -a1;
+ }
+
+ while (a1 < (long long)1<<54) {
+ a1 <<= 8;
+ exp -= 8;
+ }
+ while (a1 < (long long)1<<62) {
+ a1 <<= 1;
+ exp -= 1;
+ }
+
+ /* pack up and go home */
+ dl.ll |= (a1 >> 10) & ~HIDDEND_LL;
+ dl.l.upper |= exp << 20;
+
+ return (dl.d);
+}
float
+__floatsisf (register long a1)
+{
+ (float)__floatsidf(a1);
+}
+
+float
+__floatdisf (register long long a1)
+{
+ (float)__floatdidf(a1);
+}
+
+/* negate a float */
+float
__negsf2 (float a1)
{
register union float_long fl1;
@@ -431,7 +455,6 @@ __negsf2 (float a1)
}
/* negate a double */
-
double
__negdf2 (double a1)
{
@@ -447,7 +470,6 @@ __negdf2 (double a1)
}
/* convert float to double */
-
double
__extendsfdf2 (float a1)
{
@@ -473,7 +495,6 @@ __extendsfdf2 (float a1)
}
/* convert double to float */
-
float
__truncdfsf2 (double a1)
{
@@ -485,7 +506,7 @@ __truncdfsf2 (double a1)
dl1.d = a1;
if (!dl1.l.upper && !dl1.l.lower)
- return (0);
+ return (float)(0);
exp = EXPD (dl1) - EXCESSD + EXCESS;
@@ -497,7 +518,7 @@ __truncdfsf2 (double a1)
mant >>= 1;
/* did the round overflow? */
- if (mant & 0xFF000000)
+ if (mant & 0xFE000000)
{
mant >>= 1;
exp++;
@@ -511,7 +532,6 @@ __truncdfsf2 (double a1)
}
/* compare two doubles */
-
long
__cmpdf2 (double a1, double a2)
{
@@ -537,7 +557,6 @@ __cmpdf2 (double a1, double a2)
}
/* convert double to int */
-
long
__fixdfsi (double a1)
{
@@ -554,7 +573,7 @@ __fixdfsi (double a1)
l = MANTD (dl1);
if (exp > 0)
- return (0x7FFFFFFF | SIGND (dl1)); /* largest integer */
+ return SIGND(dl1) ? (1<<31) : ((1ul<<31)-1);
/* shift down until exp = 0 or l = 0 */
if (exp < 0 && exp > -32 && l)
@@ -565,10 +584,41 @@ __fixdfsi (double a1)
return (SIGND (dl1) ? -l : l);
}
-/* convert double to unsigned int */
+/* convert double to int */
+long long
+__fixdfdi (double a1)
+{
+ register union double_long dl1;
+ register int exp;
+ register long long l;
+
+ dl1.d = a1;
+
+ if (!dl1.l.upper && !dl1.l.lower)
+ return (0);
+
+ exp = EXPD (dl1) - EXCESSD - 64;
+ l = MANTD_LL(dl1);
+
+ if (exp > 0) {
+ l = (long long)1<<63;
+ if (!SIGND(dl1))
+ l--;
+ return l;
+ }
+
+ /* shift down until exp = 0 or l = 0 */
+ if (exp < 0 && exp > -64 && l)
+ l >>= -exp;
+ else
+ return (0);
+
+ return (SIGND (dl1) ? -l : l);
+}
-unsigned
-long __fixunsdfsi (double a1)
+/* convert double to unsigned int */
+unsigned long
+__fixunsdfsi (double a1)
{
register union double_long dl1;
register int exp;
@@ -583,7 +633,7 @@ long __fixunsdfsi (double a1)
l = (((((dl1.l.upper) & 0xFFFFF) | HIDDEND) << 11) | (dl1.l.lower >> 21));
if (exp > 0)
- return (0xFFFFFFFF); /* largest integer */
+ return (0xFFFFFFFFul); /* largest integer */
/* shift down until exp = 0 or l = 0 */
if (exp < 0 && exp > -32 && l)
@@ -594,245 +644,302 @@ long __fixunsdfsi (double a1)
return (l);
}
-/* For now, the hard double-precision routines simply
- punt and do it in single */
-/* addtwo doubles */
-
-double
-__adddf3 (double a1, double a2)
-{
- return ((float) a1 + (float) a2);
-}
-
-/* subtract two doubles */
-
-double
-__subdf3 (double a1, double a2)
-{
- return ((float) a1 - (float) a2);
-}
-
-/* multiply two doubles */
-
-double
-__muldf3 (double a1, double a2)
+/* convert double to unsigned int */
+unsigned long long
+__fixunsdfdi (double a1)
{
- return ((float) a1 * (float) a2);
-}
-
-/*
- *
- * Name: Barrett Richardson
- * E-mail: barrett@iglou.com
- * When: Thu Dec 15 10:31:11 EST 1994
- *
- * callable function:
- *
- * double __divdf3(double a1, double a2);
- *
- * Does software divide of a1 / a2.
- *
- * Based largely on __divsf3() in floatlib.c in the gcc
- * distribution.
- *
- * Purpose: To be used in conjunction with the -msoft-float
- * option of gcc. You should be able to tack it to the
- * end of floatlib.c included in the gcc distribution,
- * and delete the __divdf3() already there which just
- * calls the single precision function (or may just
- * use the floating point processor with some configurations).
- *
- * You may use this code for whatever your heart desires.
- */
+ register union double_long dl1;
+ register int exp;
+ register unsigned long long l;
+ dl1.d = a1;
+ if (dl1.ll == 0)
+ return (0);
+ exp = EXPD (dl1) - EXCESSD - 64;
-/*
- * Compare the mantissas of two doubles.
- * Each mantissa is in two longs.
- *
- * return 1 if x1's mantissa is greater than x2's
- * -1 if x1's mantissa is less than x2's
- * 0 if the two mantissa's are equal.
- *
- * The Mantissas won't fit into a 4 byte word, so they are
- * broken up into two parts.
- *
- * This function is used internally by __divdf3()
- */
-
-int
-__dcmp (long x1m1, long x1m2, long x2m1, long x2m2)
-{
- if (x1m1 > x2m1)
- return 1;
-
- if (x1m1 < x2m1)
- return -1;
+ l = dl1.ll;
- /* If the first word in the two mantissas were equal check the second word */
+ if (exp > 0)
+ return (unsigned long long)-1;
- if (x1m2 > x2m2)
- return 1;
+ /* shift down until exp = 0 or l = 0 */
+ if (exp < 0 && exp > -64 && l)
+ l >>= -exp;
+ else
+ return (0);
- if (x1m2 < x2m2)
- return -1;
-
- return 0;
+ return (l);
}
-
-/* divide two doubles */
-
+/* addtwo doubles */
double
-__divdf3 (double a1, double a2)
+__adddf3 (double a1, double a2)
{
+ register long long mant1, mant2;
+ register union double_long fl1, fl2;
+ register int exp1, exp2;
+ int sign = 0;
+
+ fl1.d = a1;
+ fl2.d = a2;
+
+ /* check for zero args */
+ if (!fl2.ll)
+ goto test_done;
+ if (!fl1.ll) {
+ fl1.d = fl2.d;
+ goto test_done;
+ }
- int sign,
- exponent,
- bit_bucket;
-
- register unsigned long mantissa1,
- mantissa2,
- x1m1,
- x1m2,
- x2m1,
- x2m2,
- mask;
-
- union _doubleu x1,
- x2,
- result;
-
-
- x1.d = a1;
- x2.d = a2;
-
- exponent = x1.ieee.exponent - x2.ieee.exponent + EXCESSD;
-
- sign = x1.ieee.sign ^ x2.ieee.sign;
-
- x2.ieee.sign = 0; /* don't want the sign bit to affect any zero */
- /* comparisons when checking for zero divide */
-
- if (!x2.l.lower && !x2.l.upper) { /* check for zero divide */
- result.l.lower = 0x0;
- if (sign)
- result.l.upper = 0xFFF00000; /* negative infinity */
- else
- result.l.upper = 0x7FF00000; /* positive infinity */
- return result.d;
- }
+ exp1 = EXPD(fl1);
+ exp2 = EXPD(fl2);
- if (!x1.l.upper && !x1.l.lower) /* check for 0.0 numerator */
- return (0.0);
+ if (exp1 > exp2 + 54)
+ goto test_done;
+ if (exp2 > exp1 + 54) {
+ fl1.d = fl2.d;
+ goto test_done;
+ }
- x1m1 = x1.ieee.mantissa1 | D_PHANTOM_BIT; /* turn on phantom bit */
- x1m2 = x1.ieee.mantissa2;
+ /* do everything in excess precision so's we can round later */
+ mant1 = MANTD_LL(fl1) << 9;
+ mant2 = MANTD_LL(fl2) << 9;
- x2m1 = x2.ieee.mantissa1 | D_PHANTOM_BIT; /* turn on phantom bit */
- x2m2 = x2.ieee.mantissa2;
+ if (SIGND(fl1))
+ mant1 = -mant1;
+ if (SIGND(fl2))
+ mant2 = -mant2;
- if (__dcmp(x1m1,x1m2,x2m1,x2m2) < 0) {
+ if (exp1 > exp2)
+ mant2 >>= exp1 - exp2;
+ else {
+ mant1 >>= exp2 - exp1;
+ exp1 = exp2;
+ }
+ mant1 += mant2;
+
+ if (mant1 < 0) {
+ mant1 = -mant1;
+ sign = SIGNBIT;
+ } else if (!mant1) {
+ fl1.d = 0;
+ goto test_done;
+ }
- /* if x1's mantissa is less than x2's shift it left one and decrement */
- /* the exponent to accommodate the change in the mantissa */
+ /* normalize up */
+ while (!(mant1 & ((long long)7<<61))) {
+ mant1 <<= 1;
+ exp1--;
+ }
- x1m1 <<= 1; /* */
- bit_bucket = x1m2 >> 31; /* Shift mantissa left one */
- x1m1 |= bit_bucket; /* */
- x1m2 <<= 1; /* */
+ /* normalize down? */
+ if (mant1 & ((long long)3<<62)) {
+ mant1 >>= 1;
+ exp1++;
+ }
- exponent--;
- }
+ /* round to even */
+ mant1 += (mant1 & (1<<9)) ? (1<<8) : ((1<<8)-1);
+ /* normalize down? */
+ if (mant1 & ((long long)3<<62)) {
+ mant1 >>= 1;
+ exp1++;
+ }
- mantissa1 = 0;
- mantissa2 = 0;
+ /* lose extra precision */
+ mant1 >>= 9;
+ /* turn off hidden bit */
+ mant1 &= ~HIDDEND_LL;
- /* Get the first part of the results mantissa using successive */
- /* subtraction. */
+ /* pack up and go home */
+ fl1.ll = PACKD_LL(sign,exp1,mant1);
- mask = 0x00200000;
- while (mask) {
+test_done:
+ return (fl1.d);
+}
- if (__dcmp(x1m1,x1m2,x2m1,x2m2) >= 0) {
+/* subtract two doubles */
+double
+__subdf3 (double a1, double a2)
+{
+ register union double_long fl1, fl2;
+
+ fl1.d = a1;
+ fl2.d = a2;
+
+ /* check for zero args */
+ if (!fl2.ll)
+ return (fl1.d);
+ /* twiddle sign bit and add */
+ fl2.l.upper ^= SIGNBIT;
+ if (!fl1.ll)
+ return (fl2.d);
+ return __adddf3 (a1, fl2.d);
+}
- /* subtract x2's mantissa from x1's */
+/* multiply two doubles */
+double
+__muldf3 (double a1, double a2)
+{
+ register union double_long fl1, fl2;
+ register unsigned long long result;
+ register int exp;
+ int sign;
- mantissa1 |= mask; /* turn on a bit in the result */
+ fl1.d = a1;
+ fl2.d = a2;
- if (x2m2 > x1m2)
- x1m1--;
- x1m2 -= x2m2;
- x1m1 -= x2m1;
- }
+ if (!fl1.ll || !fl2.ll) {
+ fl1.d = 0;
+ goto test_done;
+ }
- x1m1 <<= 1; /* */
- bit_bucket = x1m2 >> 31; /* Shift mantissa left one */
- x1m1 |= bit_bucket; /* */
- x1m2 <<= 1; /* */
+ /* compute sign and exponent */
+ sign = SIGND(fl1) ^ SIGND(fl2);
+ exp = EXPD(fl1) - EXCESSD;
+ exp += EXPD(fl2);
+
+ fl1.ll = MANTD_LL(fl1);
+ fl2.ll = MANTD_LL(fl2);
+
+ /* the multiply is done as one 31x31 multiply and two 31x21 multiples */
+ result = (fl1.ll >> 21) * (fl2.ll >> 21);
+ result += ((fl1.ll & 0x1FFFFF) * (fl2.ll >> 21)) >> 21;
+ result += ((fl2.ll & 0x1FFFFF) * (fl1.ll >> 21)) >> 21;
+
+ result >>= 2;
+ if (result & ((long long)1<<61)) {
+ /* round */
+ result += 1<<8;
+ result >>= 9;
+ } else {
+ /* round */
+ result += 1<<7;
+ result >>= 8;
+ exp--;
+ }
+ if (result & (HIDDEND_LL<<1)) {
+ result >>= 1;
+ exp++;
+ }
- mask >>= 1;
- }
+ result &= ~HIDDEND_LL;
- /* Get the second part of the results mantissa using successive */
- /* subtraction. */
+ /* pack up and go home */
+ fl1.ll = PACKD_LL(sign,exp,result);
+test_done:
+ return (fl1.d);
+}
- mask = 0x80000000;
- while (mask) {
+/* divide two doubles */
+double
+__divdf3 (double a1, double a2)
+{
+ register union double_long fl1, fl2;
+ register long long mask,result;
+ register int exp, sign;
+
+ fl1.d = a1;
+ fl2.d = a2;
+
+ /* subtract exponents */
+ exp = EXPD(fl1) - EXPD(fl2) + EXCESSD;
+
+ /* compute sign */
+ sign = SIGND(fl1) ^ SIGND(fl2);
+
+ /* numerator zero??? */
+ if (fl1.ll == 0) {
+ /* divide by zero??? */
+ if (fl2.ll == 0)
+ fl1.ll = ((unsigned long long)1<<63)-1; /* NaN */
+ else
+ fl1.ll = 0;
+ goto test_done;
+ }
- if (__dcmp(x1m1,x1m2,x2m1,x2m2) >= 0) {
+ /* return +Inf or -Inf */
+ if (fl2.ll == 0) {
+ fl1.ll = PACKD_LL(SIGND(fl1),2047,0);
+ goto test_done;
+ }
- /* subtract x2's mantissa from x1's */
- mantissa2 |= mask; /* turn on a bit in the result */
+ /* now get mantissas */
+ fl1.ll = MANTD_LL(fl1);
+ fl2.ll = MANTD_LL(fl2);
- if (x2m2 > x1m2)
- x1m1--;
- x1m2 -= x2m2;
- x1m1 -= x2m1;
- }
- x1m1 <<= 1; /* */
- bit_bucket = x1m2 >> 31; /* Shift mantissa left one */
- x1m1 |= bit_bucket; /* */
- x1m2 <<= 1; /* */
+ /* this assures we have 54 bits of precision in the end */
+ if (fl1.ll < fl2.ll) {
+ fl1.ll <<= 1;
+ exp--;
+ }
- mask >>= 1;
- }
+ /* now we perform repeated subtraction of fl2.ll from fl1.ll */
+ mask = (long long)1<<53;
+ result = 0;
+ while (mask) {
+ if (fl1.ll >= fl2.ll)
+ {
+ result |= mask;
+ fl1.ll -= fl2.ll;
+ }
+ fl1.ll <<= 1;
+ mask >>= 1;
+ }
- /* round up by adding 1 to mantissa */
+ /* round */
+ result += 1;
- if (mantissa2 == 0xFFFFFFFF) { /* check for over flow */
+ /* normalize down */
+ exp++;
+ result >>= 1;
- /* spill if overflow */
+ result &= ~HIDDEND_LL;
- mantissa2 = 0;
- mantissa1++;
- }
- else
- mantissa2++;
+ /* pack up and go home */
+ fl1.ll = PACKD_LL(sign, exp, result);
- exponent++; /* increment exponent (mantissa must be shifted right */
- /* also) */
+test_done:
+ return (fl1.d);
+}
- /* shift mantissa right one and assume a phantom bit (which really gives */
- /* 53 bits of precision in the mantissa) */
+int
+__gtdf2 (double a1, double a2)
+{
+ return __cmpdf2 ((float) a1, (float) a2) > 0;
+}
- mantissa2 >>= 1;
- bit_bucket = mantissa1 & 1;
- mantissa2 |= (bit_bucket << 31);
- mantissa1 >>= 1;
+int
+__gedf2 (double a1, double a2)
+{
+ return (__cmpdf2 ((float) a1, (float) a2) >= 0) - 1;
+}
- /* put all the info into the result */
+int
+__ltdf2 (double a1, double a2)
+{
+ return - (__cmpdf2 ((float) a1, (float) a2) < 0);
+}
- result.ieee.exponent = exponent;
- result.ieee.sign = sign;
- result.ieee.mantissa1 = mantissa1;
- result.ieee.mantissa2 = mantissa2;
+int
+__ledf2 (double a1, double a2)
+{
+ return __cmpdf2 ((float) a1, (float) a2) > 0;
+}
+int
+__eqdf2 (double a1, double a2)
+{
+ return *(long long *) &a1 == *(long long *) &a2;
+}
- return result.d;
+int
+__nedf2 (double a1, double a2)
+{
+ return *(long long *) &a1 != *(long long *) &a2;
}
diff --git a/contrib/gcc/flow.c b/contrib/gcc/flow.c
index 43ea11d..ac8fd63 100644
--- a/contrib/gcc/flow.c
+++ b/contrib/gcc/flow.c
@@ -1,5 +1,5 @@
/* Data flow analysis for GNU compiler.
- Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,14 +19,13 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This file contains the data flow analysis pass of the compiler.
- It computes data flow information
- which tells combine_instructions which insns to consider combining
- and controls register allocation.
+/* This file contains the data flow analysis pass of the compiler. It
+ computes data flow information which tells combine_instructions
+ which insns to consider combining and controls register allocation.
- Additional data flow information that is too bulky to record
- is generated during the analysis, and is used at that time to
- create autoincrement and autodecrement addressing.
+ Additional data flow information that is too bulky to record is
+ generated during the analysis, and is used at that time to create
+ autoincrement and autodecrement addressing.
The first step is dividing the function into basic blocks.
find_basic_blocks does this. Then life_analysis determines
@@ -34,13 +33,12 @@ Boston, MA 02111-1307, USA. */
** find_basic_blocks **
- find_basic_blocks divides the current function's rtl
- into basic blocks. It records the beginnings and ends of the
- basic blocks in the vectors basic_block_head and basic_block_end,
- and the number of blocks in n_basic_blocks.
+ find_basic_blocks divides the current function's rtl into basic
+ blocks and constructs the CFG. The blocks are recorded in the
+ basic_block_info array; the CFG exists in the edge structures
+ referenced by the blocks.
- find_basic_blocks also finds any unreachable loops
- and deletes them.
+ find_basic_blocks also finds any unreachable loops and deletes them.
** life_analysis **
@@ -51,12 +49,12 @@ Boston, MA 02111-1307, USA. */
** live-register info **
The information about where each register is live is in two parts:
- the REG_NOTES of insns, and the vector basic_block_live_at_start.
+ the REG_NOTES of insns, and the vector basic_block->global_live_at_start.
- basic_block_live_at_start has an element for each basic block,
- and the element is a bit-vector with a bit for each hard or pseudo
- register. The bit is 1 if the register is live at the beginning
- of the basic block.
+ basic_block->global_live_at_start has an element for each basic
+ block, and the element is a bit-vector with a bit for each hard or
+ pseudo register. The bit is 1 if the register is live at the
+ beginning of the basic block.
Two types of elements can be added to an insn's REG_NOTES.
A REG_DEAD note is added to an insn's REG_NOTES for any register
@@ -106,7 +104,19 @@ Boston, MA 02111-1307, USA. */
life_analysis fills in certain vectors containing information about
register usage: reg_n_refs, reg_n_deaths, reg_n_sets, reg_live_length,
- reg_n_calls_crosses and reg_basic_block. */
+ reg_n_calls_crosses and reg_basic_block.
+
+ life_analysis sets current_function_sp_is_unchanging if the function
+ doesn't modify the stack pointer. */
+
+/* TODO:
+
+ Split out from life_analysis:
+ - local property discovery (bb->local_live, bb->local_set)
+ - global property computation
+ - log links creation
+ - pre/post modify transformation
+*/
#include "config.h"
#include "system.h"
@@ -119,11 +129,23 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
+#include "recog.h"
+#include "insn-flags.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+#ifndef EXIT_IGNORE_STACK
+#define EXIT_IGNORE_STACK 0
+#endif
+
+
/* The contents of the current function definition are allocated
in this obstack, and all are freed at the end of the function.
For top-level functions, this is temporary_obstack.
@@ -134,44 +156,51 @@ extern struct obstack *function_obstack;
/* List of labels that must never be deleted. */
extern rtx forced_labels;
-/* Get the basic block number of an insn.
- This info should not be expected to remain available
- after the end of life_analysis. */
-
-/* This is the limit of the allocated space in the following two arrays. */
-
-static int max_uid_for_flow;
-
-#define BLOCK_NUM(INSN) uid_block_number[INSN_UID (INSN)]
+/* Number of basic blocks in the current function. */
-/* This is where the BLOCK_NUM values are really stored.
- This is set up by find_basic_blocks and used there and in life_analysis,
- and then freed. */
+int n_basic_blocks;
-int *uid_block_number;
+/* The basic block array. */
-/* INSN_VOLATILE (insn) is 1 if the insn refers to anything volatile. */
+varray_type basic_block_info;
-#define INSN_VOLATILE(INSN) uid_volatile[INSN_UID (INSN)]
-static char *uid_volatile;
+/* The special entry and exit blocks. */
-/* Number of basic blocks in the current function. */
+struct basic_block_def entry_exit_blocks[2] =
+{
+ {
+ NULL, /* head */
+ NULL, /* end */
+ NULL, /* pred */
+ NULL, /* succ */
+ NULL, /* local_set */
+ NULL, /* global_live_at_start */
+ NULL, /* global_live_at_end */
+ NULL, /* aux */
+ ENTRY_BLOCK, /* index */
+ 0 /* loop_depth */
+ },
+ {
+ NULL, /* head */
+ NULL, /* end */
+ NULL, /* pred */
+ NULL, /* succ */
+ NULL, /* local_set */
+ NULL, /* global_live_at_start */
+ NULL, /* global_live_at_end */
+ NULL, /* aux */
+ EXIT_BLOCK, /* index */
+ 0 /* loop_depth */
+ }
+};
-int n_basic_blocks;
+/* Nonzero if the second flow pass has completed. */
+int flow2_completed;
/* Maximum register number used in this function, plus one. */
int max_regno;
-/* Maximum number of SCRATCH rtx's used in any basic block of this
- function. */
-
-int max_scratch;
-
-/* Number of SCRATCH rtx's in the current block. */
-
-static int num_scratch;
-
/* Indexed by n, giving various register information */
varray_type reg_n_info;
@@ -192,28 +221,8 @@ static rtx *reg_next_use;
int regset_bytes;
int regset_size;
-/* Element N is first insn in basic block N.
- This info lasts until we finish compiling the function. */
-
-rtx *basic_block_head;
-
-/* Element N is last insn in basic block N.
- This info lasts until we finish compiling the function. */
-
-rtx *basic_block_end;
-
-/* Element N indicates whether basic block N can be reached through a
- computed jump. */
-
-char *basic_block_computed_jump_target;
-
-/* Element N is a regset describing the registers live
- at the start of basic block N.
- This info lasts until we finish compiling the function. */
-
-regset *basic_block_live_at_start;
-
/* Regset of regs live when calls to `setjmp'-like functions happen. */
+/* ??? Does this exist only for the setjmp-clobbered warning message? */
regset regs_live_at_setjmp;
@@ -223,21 +232,6 @@ regset regs_live_at_setjmp;
are another pair, etc. */
rtx regs_may_share;
-/* Element N is nonzero if control can drop into basic block N
- from the preceding basic block. Freed after life_analysis. */
-
-static char *basic_block_drops_in;
-
-/* Element N is depth within loops of the last insn in basic block number N.
- Freed after life_analysis. */
-
-static short *basic_block_loop_depth;
-
-/* Element N nonzero if basic block N can actually be reached.
- Vector exists only during find_basic_blocks. */
-
-static char *block_live_static;
-
/* Depth within loops of basic block being scanned for lifetime analysis,
plus one. This is the weight attached to references to registers. */
@@ -247,24 +241,74 @@ static int loop_depth;
static int cc0_live;
-/* During propagate_block, this contains the last MEM stored into. It
- is used to eliminate consecutive stores to the same location. */
+/* During propagate_block, this contains a list of all the MEMs we are
+ tracking for dead store elimination.
+
+ ?!? Note we leak memory by not free-ing items on this list. We need to
+ write some generic routines to operate on memory lists since cse, gcse,
+ loop, sched, flow and possibly other passes all need to do basically the
+ same operations on these lists. */
-static rtx last_mem_set;
+static rtx mem_set_list;
/* Set of registers that may be eliminable. These are handled specially
in updating regs_ever_live. */
static HARD_REG_SET elim_reg_set;
+/* The basic block structure for every insn, indexed by uid. */
+
+varray_type basic_block_for_insn;
+
+/* The labels mentioned in non-jump rtl. Valid during find_basic_blocks. */
+/* ??? Should probably be using LABEL_NUSES instead. It would take a
+ bit of surgery to be able to use or co-opt the routines in jump. */
+
+static rtx label_value_list;
+
+/* INSN_VOLATILE (insn) is 1 if the insn refers to anything volatile. */
+
+#define INSN_VOLATILE(INSN) bitmap_bit_p (uid_volatile, INSN_UID (INSN))
+#define SET_INSN_VOLATILE(INSN) bitmap_set_bit (uid_volatile, INSN_UID (INSN))
+static bitmap uid_volatile;
+
/* Forward declarations */
-static void find_basic_blocks_1 PROTO((rtx, rtx, int));
-static void mark_label_ref PROTO((rtx, rtx, int));
-static void life_analysis_1 PROTO((rtx, int));
-static void propagate_block PROTO((regset, rtx, rtx, int,
- regset, int));
+static int count_basic_blocks PROTO((rtx));
+static rtx find_basic_blocks_1 PROTO((rtx, rtx*));
+static void create_basic_block PROTO((int, rtx, rtx, rtx));
+static void compute_bb_for_insn PROTO((varray_type, int));
+static void clear_edges PROTO((void));
+static void make_edges PROTO((rtx, rtx*));
+static void make_edge PROTO((basic_block, basic_block, int));
+static void make_label_edge PROTO((basic_block, rtx, int));
+static void mark_critical_edges PROTO((void));
+
+static void commit_one_edge_insertion PROTO((edge));
+
+static void delete_unreachable_blocks PROTO((void));
+static void delete_eh_regions PROTO((void));
+static int can_delete_note_p PROTO((rtx));
+static void delete_insn_chain PROTO((rtx, rtx));
+static int delete_block PROTO((basic_block));
+static void expunge_block PROTO((basic_block));
static rtx flow_delete_insn PROTO((rtx));
-static int insn_dead_p PROTO((rtx, regset, int));
+static int can_delete_label_p PROTO((rtx));
+static void merge_blocks_nomove PROTO((basic_block, basic_block));
+static int merge_blocks PROTO((edge,basic_block,basic_block));
+static void tidy_fallthru_edge PROTO((edge,basic_block,basic_block));
+static void calculate_loop_depth PROTO((rtx));
+
+static int set_noop_p PROTO((rtx));
+static int noop_move_p PROTO((rtx));
+static void notice_stack_pointer_modification PROTO ((rtx, rtx));
+static void record_volatile_insns PROTO((rtx));
+static void mark_regs_live_at_end PROTO((regset));
+static void life_analysis_1 PROTO((rtx, int, int));
+static void init_regset_vector PROTO ((regset *, int,
+ struct obstack *));
+static void propagate_block PROTO((regset, rtx, rtx, int,
+ regset, int, int));
+static int insn_dead_p PROTO((rtx, regset, int, rtx));
static int libcall_dead_p PROTO((rtx, regset, rtx, rtx));
static void mark_set_regs PROTO((regset, regset, rtx,
rtx, regset));
@@ -277,103 +321,190 @@ static int try_pre_increment PROTO((rtx, rtx, HOST_WIDE_INT));
#endif
static void mark_used_regs PROTO((regset, regset, rtx, int, rtx));
void dump_flow_info PROTO((FILE *));
-static void add_pred_succ PROTO ((int, int, int_list_ptr *,
- int_list_ptr *, int *, int *));
+static void dump_edge_info PROTO((FILE *, edge, int));
+
static int_list_ptr alloc_int_list_node PROTO ((int_list_block **));
static int_list_ptr add_int_list_node PROTO ((int_list_block **,
int_list **, int));
-static void init_regset_vector PROTO ((regset *, int,
- struct obstack *));
+
+static void add_pred_succ PROTO ((int, int, int_list_ptr *,
+ int_list_ptr *, int *, int *));
+
static void count_reg_sets_1 PROTO ((rtx));
static void count_reg_sets PROTO ((rtx));
static void count_reg_references PROTO ((rtx));
+static void notice_stack_pointer_modification PROTO ((rtx, rtx));
+static void invalidate_mems_from_autoinc PROTO ((rtx));
+void verify_flow_info PROTO ((void));
/* Find basic blocks of the current function.
- F is the first insn of the function and NREGS the number of register numbers
- in use.
- LIVE_REACHABLE_P is non-zero if the caller needs all live blocks to
- be reachable. This turns on a kludge that causes the control flow
- information to be inaccurate and not suitable for passes like GCSE. */
+ F is the first insn of the function and NREGS the number of register
+ numbers in use. */
void
-find_basic_blocks (f, nregs, file, live_reachable_p)
+find_basic_blocks (f, nregs, file, do_cleanup)
rtx f;
- int nregs;
- FILE *file;
- int live_reachable_p;
+ int nregs ATTRIBUTE_UNUSED;
+ FILE *file ATTRIBUTE_UNUSED;
+ int do_cleanup;
{
- register rtx insn;
- register int i;
- rtx nonlocal_label_list = nonlocal_label_rtx_list ();
- int in_libcall_block = 0;
+ rtx *bb_eh_end;
+ int max_uid;
+
+ /* Flush out existing data. */
+ if (basic_block_info != NULL)
+ {
+ int i;
- /* Count the basic blocks. Also find maximum insn uid value used. */
+ clear_edges ();
- {
- register RTX_CODE prev_code = JUMP_INSN;
- register RTX_CODE code;
- int eh_region = 0;
+ /* Clear bb->aux on all extant basic blocks. We'll use this as a
+ tag for reuse during create_basic_block, just in case some pass
+ copies around basic block notes improperly. */
+ for (i = 0; i < n_basic_blocks; ++i)
+ BASIC_BLOCK (i)->aux = NULL;
- max_uid_for_flow = 0;
+ VARRAY_FREE (basic_block_info);
+ }
- for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
- {
+ n_basic_blocks = count_basic_blocks (f);
- /* Track when we are inside in LIBCALL block. */
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
- in_libcall_block = 1;
-
- code = GET_CODE (insn);
- if (INSN_UID (insn) > max_uid_for_flow)
- max_uid_for_flow = INSN_UID (insn);
- if (code == CODE_LABEL
- || (GET_RTX_CLASS (code) == 'i'
- && (prev_code == JUMP_INSN
- || (prev_code == CALL_INSN
- && (nonlocal_label_list != 0 || eh_region)
- && ! in_libcall_block)
- || prev_code == BARRIER)))
- i++;
-
- if (code == CALL_INSN && find_reg_note (insn, REG_RETVAL, NULL_RTX))
- code = INSN;
-
- if (code != NOTE)
- prev_code = code;
- else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
- ++eh_region;
- else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
- --eh_region;
-
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && find_reg_note (insn, REG_RETVAL, NULL_RTX))
- in_libcall_block = 0;
- }
- }
+ /* Size the basic block table. The actual structures will be allocated
+ by find_basic_blocks_1, since we want to keep the structure pointers
+ stable across calls to find_basic_blocks. */
+ /* ??? This whole issue would be much simpler if we called find_basic_blocks
+ exactly once, and thereafter we don't have a single long chain of
+ instructions at all until close to the end of compilation when we
+ actually lay them out. */
+
+ VARRAY_BB_INIT (basic_block_info, n_basic_blocks, "basic_block_info");
+
+ /* An array to record the active exception region at the end of each
+ basic block. It is filled in by find_basic_blocks_1 for make_edges. */
+ bb_eh_end = (rtx *) alloca (n_basic_blocks * sizeof (rtx));
- n_basic_blocks = i;
+ label_value_list = find_basic_blocks_1 (f, bb_eh_end);
+
+ /* Record the block to which an insn belongs. */
+ /* ??? This should be done another way, by which (perhaps) a label is
+ tagged directly with the basic block that it starts. It is used for
+ more than that currently, but IMO that is the only valid use. */
+ max_uid = get_max_uid ();
#ifdef AUTO_INC_DEC
/* Leave space for insns life_analysis makes in some cases for auto-inc.
These cases are rare, so we don't need too much space. */
- max_uid_for_flow += max_uid_for_flow / 10;
+ max_uid += max_uid / 10;
+#endif
+
+ VARRAY_BB_INIT (basic_block_for_insn, max_uid, "basic_block_for_insn");
+ compute_bb_for_insn (basic_block_for_insn, max_uid);
+
+ /* Discover the edges of our cfg. */
+
+ make_edges (label_value_list, bb_eh_end);
+
+ /* Delete unreachable blocks. */
+
+ if (do_cleanup)
+ delete_unreachable_blocks ();
+
+ /* Mark critical edges. */
+
+ mark_critical_edges ();
+
+ /* Discover the loop depth at the start of each basic block to aid
+ register allocation. */
+ calculate_loop_depth (f);
+
+ /* Kill the data we won't maintain. */
+ label_value_list = 0;
+
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
#endif
+}
+
+/* Count the basic blocks of the function. */
+
+static int
+count_basic_blocks (f)
+ rtx f;
+{
+ register rtx insn;
+ register RTX_CODE prev_code;
+ register int count = 0;
+ int eh_region = 0;
+ int call_had_abnormal_edge = 0;
+ rtx prev_call = NULL_RTX;
+
+ prev_code = JUMP_INSN;
+ for (insn = f; insn; insn = NEXT_INSN (insn))
+ {
+ register RTX_CODE code = GET_CODE (insn);
+
+ if (code == CODE_LABEL
+ || (GET_RTX_CLASS (code) == 'i'
+ && (prev_code == JUMP_INSN
+ || prev_code == BARRIER
+ || (prev_code == CALL_INSN && call_had_abnormal_edge))))
+ {
+ count++;
- /* Allocate some tables that last till end of compiling this function
- and some needed only in find_basic_blocks and life_analysis. */
+ /* If the previous insn was a call that did not create an
+ abnormal edge, we want to add a nop so that the CALL_INSN
+ itself is not at basic_block_end. This allows us to
+ easily distinguish between normal calls and those which
+ create abnormal edges in the flow graph. */
- basic_block_head = (rtx *) xmalloc (n_basic_blocks * sizeof (rtx));
- basic_block_end = (rtx *) xmalloc (n_basic_blocks * sizeof (rtx));
- basic_block_drops_in = (char *) xmalloc (n_basic_blocks);
- basic_block_computed_jump_target = (char *) oballoc (n_basic_blocks);
- basic_block_loop_depth = (short *) xmalloc (n_basic_blocks * sizeof (short));
- uid_block_number
- = (int *) xmalloc ((max_uid_for_flow + 1) * sizeof (int));
- uid_volatile = (char *) xmalloc (max_uid_for_flow + 1);
- bzero (uid_volatile, max_uid_for_flow + 1);
+ if (count > 0 && prev_call != 0 && !call_had_abnormal_edge)
+ {
+ rtx nop = gen_rtx_USE (VOIDmode, const0_rtx);
+ emit_insn_after (nop, prev_call);
+ }
+ }
- find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p);
+ /* Record whether this call created an edge. */
+ if (code == CALL_INSN)
+ {
+ rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+ int region = (note ? XINT (XEXP (note, 0), 0) : 1);
+ prev_call = insn;
+ call_had_abnormal_edge = 0;
+
+ /* If there is a specified EH region, we have an edge. */
+ if (eh_region && region > 0)
+ call_had_abnormal_edge = 1;
+ else
+ {
+ /* If there is a nonlocal goto label and the specified
+ region number isn't -1, we have an edge. (0 means
+ no throw, but might have a nonlocal goto). */
+ if (nonlocal_goto_handler_labels && region >= 0)
+ call_had_abnormal_edge = 1;
+ }
+ }
+ else if (code != NOTE)
+ prev_call = NULL_RTX;
+
+ if (code != NOTE)
+ prev_code = code;
+ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+ ++eh_region;
+ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
+ --eh_region;
+
+ }
+
+ /* The rest of the compiler works a bit smoother when we don't have to
+ check for the edge case of do-nothing functions with no basic blocks. */
+ if (count == 0)
+ {
+ emit_insn (gen_rtx_USE (VOIDmode, const0_rtx));
+ count = 1;
+ }
+
+ return count;
}
/* Find all basic blocks of the function whose first insn is F.
@@ -381,613 +512,1554 @@ find_basic_blocks (f, nregs, file, live_reachable_p)
set up the chains of references for each CODE_LABEL, and
delete any entire basic blocks that cannot be reached.
- NONLOCAL_LABEL_LIST is a list of non-local labels in the function.
- Blocks that are otherwise unreachable may be reachable with a non-local
- goto.
- LIVE_REACHABLE_P is non-zero if the caller needs all live blocks to
- be reachable. This turns on a kludge that causes the control flow
- information to be inaccurate and not suitable for passes like GCSE. */
+ NONLOCAL_LABEL_LIST is a list of non-local labels in the function. Blocks
+ that are otherwise unreachable may be reachable with a non-local goto.
+
+ BB_EH_END is an array in which we record the list of exception regions
+ active at the end of every basic block. */
+
+static rtx
+find_basic_blocks_1 (f, bb_eh_end)
+ rtx f;
+ rtx *bb_eh_end;
+{
+ register rtx insn, next;
+ int call_has_abnormal_edge = 0;
+ int i = 0;
+ rtx bb_note = NULL_RTX;
+ rtx eh_list = NULL_RTX;
+ rtx label_value_list = NULL_RTX;
+ rtx head = NULL_RTX;
+ rtx end = NULL_RTX;
+
+ /* We process the instructions in a slightly different way than we did
+ previously. This is so that we see a NOTE_BASIC_BLOCK after we have
+ closed out the previous block, so that it gets attached at the proper
+ place. Since this form should be equivalent to the previous,
+ find_basic_blocks_0 continues to use the old form as a check. */
+
+ for (insn = f; insn; insn = next)
+ {
+ enum rtx_code code = GET_CODE (insn);
+
+ next = NEXT_INSN (insn);
+
+ if (code == CALL_INSN)
+ {
+ /* Record whether this call created an edge. */
+ rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+ int region = (note ? XINT (XEXP (note, 0), 0) : 1);
+ call_has_abnormal_edge = 0;
+
+ /* If there is an EH region, we have an edge. */
+ if (eh_list && region > 0)
+ call_has_abnormal_edge = 1;
+ else
+ {
+ /* If there is a nonlocal goto label and the specified
+ region number isn't -1, we have an edge. (0 means
+ no throw, but might have a nonlocal goto). */
+ if (nonlocal_goto_handler_labels && region >= 0)
+ call_has_abnormal_edge = 1;
+ }
+ }
+
+ switch (code)
+ {
+ case NOTE:
+ {
+ int kind = NOTE_LINE_NUMBER (insn);
+
+ /* Keep a LIFO list of the currently active exception notes. */
+ if (kind == NOTE_INSN_EH_REGION_BEG)
+ eh_list = gen_rtx_INSN_LIST (VOIDmode, insn, eh_list);
+ else if (kind == NOTE_INSN_EH_REGION_END)
+ eh_list = XEXP (eh_list, 1);
+
+ /* Look for basic block notes with which to keep the
+ basic_block_info pointers stable. Unthread the note now;
+ we'll put it back at the right place in create_basic_block.
+ Or not at all if we've already found a note in this block. */
+ else if (kind == NOTE_INSN_BASIC_BLOCK)
+ {
+ if (bb_note == NULL_RTX)
+ bb_note = insn;
+ next = flow_delete_insn (insn);
+ }
+
+ break;
+ }
+
+ case CODE_LABEL:
+ /* A basic block starts at a label. If we've closed one off due
+ to a barrier or some such, no need to do it again. */
+ if (head != NULL_RTX)
+ {
+ /* While we now have edge lists with which other portions of
+ the compiler might determine a call ending a basic block
+ does not imply an abnormal edge, it will be a bit before
+ everything can be updated. So continue to emit a noop at
+ the end of such a block. */
+ if (GET_CODE (end) == CALL_INSN)
+ {
+ rtx nop = gen_rtx_USE (VOIDmode, const0_rtx);
+ end = emit_insn_after (nop, end);
+ }
+
+ bb_eh_end[i] = eh_list;
+ create_basic_block (i++, head, end, bb_note);
+ bb_note = NULL_RTX;
+ }
+ head = end = insn;
+ break;
+
+ case JUMP_INSN:
+ /* A basic block ends at a jump. */
+ if (head == NULL_RTX)
+ head = insn;
+ else
+ {
+ /* ??? Make a special check for table jumps. The way this
+ happens is truely and amazingly gross. We are about to
+ create a basic block that contains just a code label and
+ an addr*vec jump insn. Worse, an addr_diff_vec creates
+ its own natural loop.
+
+ Prevent this bit of brain damage, pasting things together
+ correctly in make_edges.
+
+ The correct solution involves emitting the table directly
+ on the tablejump instruction as a note, or JUMP_LABEL. */
+
+ if (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ {
+ head = end = NULL;
+ n_basic_blocks--;
+ break;
+ }
+ }
+ end = insn;
+ goto new_bb_inclusive;
+
+ case BARRIER:
+ /* A basic block ends at a barrier. It may be that an unconditional
+ jump already closed the basic block -- no need to do it again. */
+ if (head == NULL_RTX)
+ break;
+
+ /* While we now have edge lists with which other portions of the
+ compiler might determine a call ending a basic block does not
+ imply an abnormal edge, it will be a bit before everything can
+ be updated. So continue to emit a noop at the end of such a
+ block. */
+ if (GET_CODE (end) == CALL_INSN)
+ {
+ rtx nop = gen_rtx_USE (VOIDmode, const0_rtx);
+ end = emit_insn_after (nop, end);
+ }
+ goto new_bb_exclusive;
+
+ case CALL_INSN:
+ /* A basic block ends at a call that can either throw or
+ do a non-local goto. */
+ if (call_has_abnormal_edge)
+ {
+ new_bb_inclusive:
+ if (head == NULL_RTX)
+ head = insn;
+ end = insn;
+
+ new_bb_exclusive:
+ bb_eh_end[i] = eh_list;
+ create_basic_block (i++, head, end, bb_note);
+ head = end = NULL_RTX;
+ bb_note = NULL_RTX;
+ break;
+ }
+ /* FALLTHRU */
+
+ default:
+ if (GET_RTX_CLASS (code) == 'i')
+ {
+ if (head == NULL_RTX)
+ head = insn;
+ end = insn;
+ }
+ break;
+ }
+
+ if (GET_RTX_CLASS (code) == 'i')
+ {
+ rtx note;
+
+ /* Make a list of all labels referred to other than by jumps
+ (which just don't have the REG_LABEL notes).
+
+ Make a special exception for labels followed by an ADDR*VEC,
+ as this would be a part of the tablejump setup code.
+
+ Make a special exception for the eh_return_stub_label, which
+ we know isn't part of any otherwise visible control flow. */
+
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_LABEL)
+ {
+ rtx lab = XEXP (note, 0), next;
+
+ if (lab == eh_return_stub_label)
+ ;
+ else if ((next = next_nonnote_insn (lab)) != NULL
+ && GET_CODE (next) == JUMP_INSN
+ && (GET_CODE (PATTERN (next)) == ADDR_VEC
+ || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
+ ;
+ else
+ label_value_list
+ = gen_rtx_EXPR_LIST (VOIDmode, XEXP (note, 0),
+ label_value_list);
+ }
+ }
+ }
+
+ if (head != NULL_RTX)
+ {
+ bb_eh_end[i] = eh_list;
+ create_basic_block (i++, head, end, bb_note);
+ }
+
+ if (i != n_basic_blocks)
+ abort ();
+
+ return label_value_list;
+}
+
+/* Create a new basic block consisting of the instructions between
+ HEAD and END inclusive. Reuses the note and basic block struct
+ in BB_NOTE, if any. */
static void
-find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
- rtx f, nonlocal_label_list;
- int live_reachable_p;
+create_basic_block (index, head, end, bb_note)
+ int index;
+ rtx head, end, bb_note;
{
- register rtx insn;
- register int i;
- register char *block_live = (char *) alloca (n_basic_blocks);
- register char *block_marked = (char *) alloca (n_basic_blocks);
- /* An array of CODE_LABELs, indexed by UID for the start of the active
- EH handler for each insn in F. */
- int *active_eh_region;
- int *nested_eh_region;
- /* List of label_refs to all labels whose addresses are taken
- and used as data. */
- rtx label_value_list;
- rtx x, note, eh_note;
- enum rtx_code prev_code, code;
- int depth, pass;
- int in_libcall_block = 0;
- int deleted_handler = 0;
+ basic_block bb;
- pass = 1;
- active_eh_region = (int *) alloca ((max_uid_for_flow + 1) * sizeof (int));
- nested_eh_region = (int *) alloca ((max_label_num () + 1) * sizeof (int));
- restart:
+ if (bb_note
+ && ! RTX_INTEGRATED_P (bb_note)
+ && (bb = NOTE_BASIC_BLOCK (bb_note)) != NULL
+ && bb->aux == NULL)
+ {
+ /* If we found an existing note, thread it back onto the chain. */
- label_value_list = 0;
- block_live_static = block_live;
- bzero (block_live, n_basic_blocks);
- bzero (block_marked, n_basic_blocks);
- bzero (basic_block_computed_jump_target, n_basic_blocks);
- bzero ((char *) active_eh_region, (max_uid_for_flow + 1) * sizeof (int));
- bzero ((char *) nested_eh_region, (max_label_num () + 1) * sizeof (int));
- current_function_has_computed_jump = 0;
+ if (GET_CODE (head) == CODE_LABEL)
+ add_insn_after (bb_note, head);
+ else
+ {
+ add_insn_before (bb_note, head);
+ head = bb_note;
+ }
+ }
+ else
+ {
+ /* Otherwise we must create a note and a basic block structure.
+ Since we allow basic block structs in rtl, give the struct
+ the same lifetime by allocating it off the function obstack
+ rather than using malloc. */
- /* Initialize with just block 0 reachable and no blocks marked. */
- if (n_basic_blocks > 0)
- block_live[0] = 1;
+ bb = (basic_block) obstack_alloc (function_obstack, sizeof (*bb));
+ memset (bb, 0, sizeof (*bb));
- /* Initialize the ref chain of each label to 0. Record where all the
- blocks start and end and their depth in loops. For each insn, record
- the block it is in. Also mark as reachable any blocks headed by labels
- that must not be deleted. */
+ if (GET_CODE (head) == CODE_LABEL)
+ bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
+ else
+ {
+ bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, head);
+ head = bb_note;
+ }
+ NOTE_BASIC_BLOCK (bb_note) = bb;
+ }
+
+ /* Always include the bb note in the block. */
+ if (NEXT_INSN (end) == bb_note)
+ end = bb_note;
+
+ bb->head = head;
+ bb->end = end;
+ bb->index = index;
+ BASIC_BLOCK (index) = bb;
+
+ /* Tag the block so that we know it has been used when considering
+ other basic block notes. */
+ bb->aux = bb;
+}
+
+/* Records the basic block struct in BB_FOR_INSN, for every instruction
+ indexed by INSN_UID. MAX is the size of the array. */
- for (eh_note = NULL_RTX, insn = f, i = -1, prev_code = JUMP_INSN, depth = 1;
- insn; insn = NEXT_INSN (insn))
+static void
+compute_bb_for_insn (bb_for_insn, max)
+ varray_type bb_for_insn;
+ int max;
+{
+ int i;
+
+ for (i = 0; i < n_basic_blocks; ++i)
{
+ basic_block bb = BASIC_BLOCK (i);
+ rtx insn, end;
+
+ end = bb->end;
+ insn = bb->head;
+ while (1)
+ {
+ int uid = INSN_UID (insn);
+ if (uid < max)
+ VARRAY_BB (bb_for_insn, uid) = bb;
+ if (insn == end)
+ break;
+ insn = NEXT_INSN (insn);
+ }
+ }
+}
- /* Track when we are inside in LIBCALL block. */
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
- in_libcall_block = 1;
+/* Free the memory associated with the edge structures. */
- code = GET_CODE (insn);
- if (code == NOTE)
+static void
+clear_edges ()
+{
+ int i;
+ edge n, e;
+
+ for (i = 0; i < n_basic_blocks; ++i)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+
+ for (e = bb->succ; e ; e = n)
{
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- depth++;
- else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
- depth--;
+ n = e->succ_next;
+ free (e);
}
- /* A basic block starts at label, or after something that can jump. */
- else if (code == CODE_LABEL
- || (GET_RTX_CLASS (code) == 'i'
- && (prev_code == JUMP_INSN
- || (prev_code == CALL_INSN
- && (nonlocal_label_list != 0 || eh_note)
- && ! in_libcall_block)
- || prev_code == BARRIER)))
+ bb->succ = 0;
+ bb->pred = 0;
+ }
+
+ for (e = ENTRY_BLOCK_PTR->succ; e ; e = n)
+ {
+ n = e->succ_next;
+ free (e);
+ }
+
+ ENTRY_BLOCK_PTR->succ = 0;
+ EXIT_BLOCK_PTR->pred = 0;
+}
+
+/* Identify the edges between basic blocks.
+
+ NONLOCAL_LABEL_LIST is a list of non-local labels in the function. Blocks
+ that are otherwise unreachable may be reachable with a non-local goto.
+
+ BB_EH_END is an array indexed by basic block number in which we record
+ the list of exception regions active at the end of the basic block. */
+
+static void
+make_edges (label_value_list, bb_eh_end)
+ rtx label_value_list;
+ rtx *bb_eh_end;
+{
+ int i;
+
+ /* Assume no computed jump; revise as we create edges. */
+ current_function_has_computed_jump = 0;
+
+ /* By nature of the way these get numbered, block 0 is always the entry. */
+ make_edge (ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
+
+ for (i = 0; i < n_basic_blocks; ++i)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+ rtx insn, x, eh_list;
+ enum rtx_code code;
+ int force_fallthru = 0;
+
+ /* If we have asynchronous exceptions, scan the notes for all exception
+ regions active in the block. In the normal case, we only need the
+ one active at the end of the block, which is bb_eh_end[i]. */
+
+ eh_list = bb_eh_end[i];
+ if (asynchronous_exceptions)
{
- basic_block_head[++i] = insn;
- basic_block_end[i] = insn;
- basic_block_loop_depth[i] = depth;
+ for (insn = bb->end; insn != bb->head; insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
+ eh_list = gen_rtx_INSN_LIST (VOIDmode, insn, eh_list);
+ }
+ }
+
+ /* Now examine the last instruction of the block, and discover the
+ ways we can leave the block. */
- if (code == CODE_LABEL)
+ insn = bb->end;
+ code = GET_CODE (insn);
+
+ /* A branch. */
+ if (code == JUMP_INSN)
+ {
+ rtx tmp;
+
+ /* ??? Recognize a tablejump and do the right thing. */
+ if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
+ && (tmp = NEXT_INSN (tmp)) != NULL_RTX
+ && GET_CODE (tmp) == JUMP_INSN
+ && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
+ || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
{
- LABEL_REFS (insn) = insn;
- /* Any label that cannot be deleted
- is considered to start a reachable block. */
- if (LABEL_PRESERVE_P (insn))
- block_live[i] = 1;
- }
+ rtvec vec;
+ int j;
+
+ if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
+ vec = XVEC (PATTERN (tmp), 0);
+ else
+ vec = XVEC (PATTERN (tmp), 1);
+
+ for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
+ make_label_edge (bb, XEXP (RTVEC_ELT (vec, j), 0), 0);
+
+ /* Some targets (eg, ARM) emit a conditional jump that also
+ contains the out-of-range target. Scan for these and
+ add an edge if necessary. */
+ if ((tmp = single_set (insn)) != NULL
+ && SET_DEST (tmp) == pc_rtx
+ && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
+ && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
+ make_label_edge (bb, XEXP (XEXP (SET_SRC (tmp), 2), 0), 0);
+
+#ifdef CASE_DROPS_THROUGH
+ /* Silly VAXen. The ADDR_VEC is going to be in the way of
+ us naturally detecting fallthru into the next block. */
+ force_fallthru = 1;
+#endif
+ }
+
+ /* If this is a computed jump, then mark it as reaching
+ everything on the label_value_list and forced_labels list. */
+ else if (computed_jump_p (insn))
+ {
+ current_function_has_computed_jump = 1;
+
+ for (x = label_value_list; x; x = XEXP (x, 1))
+ make_label_edge (bb, XEXP (x, 0), EDGE_ABNORMAL);
+
+ for (x = forced_labels; x; x = XEXP (x, 1))
+ make_label_edge (bb, XEXP (x, 0), EDGE_ABNORMAL);
+ }
+
+ /* Returns create an exit out. */
+ else if (returnjump_p (insn))
+ make_edge (bb, EXIT_BLOCK_PTR, 0);
+
+ /* Otherwise, we have a plain conditional or unconditional jump. */
+ else
+ {
+ if (! JUMP_LABEL (insn))
+ abort ();
+ make_label_edge (bb, JUMP_LABEL (insn), 0);
+ }
}
- else if (GET_RTX_CLASS (code) == 'i')
+ /* If this is a CALL_INSN, then mark it as reaching the active EH
+ handler for this CALL_INSN. If we're handling asynchronous
+ exceptions then any insn can reach any of the active handlers.
+
+ Also mark the CALL_INSN as reaching any nonlocal goto handler. */
+
+ if (code == CALL_INSN || asynchronous_exceptions)
{
- basic_block_end[i] = insn;
- basic_block_loop_depth[i] = depth;
+ int is_call = (code == CALL_INSN ? EDGE_ABNORMAL_CALL : 0);
+ handler_info *ptr;
+
+ /* Use REG_EH_RETHROW and REG_EH_REGION if available. */
+ /* ??? REG_EH_REGION is not generated presently. Is it
+ inteded that there be multiple notes for the regions?
+ or is my eh_list collection redundant with handler linking? */
+
+ x = find_reg_note (insn, REG_EH_RETHROW, 0);
+ if (!x)
+ x = find_reg_note (insn, REG_EH_REGION, 0);
+ if (x)
+ {
+ if (XINT (XEXP (x, 0), 0) > 0)
+ {
+ ptr = get_first_handler (XINT (XEXP (x, 0), 0));
+ while (ptr)
+ {
+ make_label_edge (bb, ptr->handler_label,
+ EDGE_ABNORMAL | EDGE_EH | is_call);
+ ptr = ptr->next;
+ }
+ }
+ }
+ else
+ {
+ for (x = eh_list; x; x = XEXP (x, 1))
+ {
+ ptr = get_first_handler (NOTE_BLOCK_NUMBER (XEXP (x, 0)));
+ while (ptr)
+ {
+ make_label_edge (bb, ptr->handler_label,
+ EDGE_ABNORMAL | EDGE_EH | is_call);
+ ptr = ptr->next;
+ }
+ }
+ }
+
+ if (code == CALL_INSN && nonlocal_goto_handler_labels)
+ {
+ /* ??? This could be made smarter: in some cases it's possible
+ to tell that certain calls will not do a nonlocal goto.
+
+ For example, if the nested functions that do the nonlocal
+ gotos do not have their addresses taken, then only calls to
+ those functions or to other nested functions that use them
+ could possibly do nonlocal gotos. */
+
+ for (x = nonlocal_goto_handler_labels; x ; x = XEXP (x, 1))
+ make_label_edge (bb, XEXP (x, 0),
+ EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+ }
}
- if (GET_RTX_CLASS (code) == 'i')
+ /* We know something about the structure of the function __throw in
+ libgcc2.c. It is the only function that ever contains eh_stub
+ labels. It modifies its return address so that the last block
+ returns to one of the eh_stub labels within it. So we have to
+ make additional edges in the flow graph. */
+ if (i + 1 == n_basic_blocks && eh_return_stub_label != 0)
+ make_label_edge (bb, eh_return_stub_label, EDGE_EH);
+
+ /* Find out if we can drop through to the next block. */
+ insn = next_nonnote_insn (insn);
+ if (!insn || (i + 1 == n_basic_blocks && force_fallthru))
+ make_edge (bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
+ else if (i + 1 < n_basic_blocks)
{
- /* Make a list of all labels referred to other than by jumps. */
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- if (REG_NOTE_KIND (note) == REG_LABEL)
- label_value_list = gen_rtx_EXPR_LIST (VOIDmode, XEXP (note, 0),
- label_value_list);
+ rtx tmp = BLOCK_HEAD (i + 1);
+ if (GET_CODE (tmp) == NOTE)
+ tmp = next_nonnote_insn (tmp);
+ if (force_fallthru || insn == tmp)
+ make_edge (bb, BASIC_BLOCK (i + 1), EDGE_FALLTHRU);
}
+ }
+}
- /* Keep a lifo list of the currently active exception notes. */
- if (GET_CODE (insn) == NOTE)
+/* Create an edge between two basic blocks. FLAGS are auxiliary information
+ about the edge that is accumulated between calls. */
+
+static void
+make_edge (src, dst, flags)
+ basic_block src, dst;
+ int flags;
+{
+ edge e;
+
+ /* Make sure we don't add duplicate edges. */
+
+ for (e = src->succ; e ; e = e->succ_next)
+ if (e->dest == dst)
+ {
+ e->flags |= flags;
+ return;
+ }
+
+ e = (edge) xcalloc (1, sizeof (*e));
+
+ e->succ_next = src->succ;
+ e->pred_next = dst->pred;
+ e->src = src;
+ e->dest = dst;
+ e->flags = flags;
+
+ src->succ = e;
+ dst->pred = e;
+}
+
+/* Create an edge from a basic block to a label. */
+
+static void
+make_label_edge (src, label, flags)
+ basic_block src;
+ rtx label;
+ int flags;
+{
+ if (GET_CODE (label) != CODE_LABEL)
+ abort ();
+
+ /* If the label was never emitted, this insn is junk, but avoid a
+ crash trying to refer to BLOCK_FOR_INSN (label). This can happen
+ as a result of a syntax error and a diagnostic has already been
+ printed. */
+
+ if (INSN_UID (label) == 0)
+ return;
+
+ make_edge (src, BLOCK_FOR_INSN (label), flags);
+}
+
+/* Identify critical edges and set the bits appropriately. */
+static void
+mark_critical_edges ()
+{
+ int i, n = n_basic_blocks;
+ basic_block bb;
+
+ /* We begin with the entry block. This is not terribly important now,
+ but could be if a front end (Fortran) implemented alternate entry
+ points. */
+ bb = ENTRY_BLOCK_PTR;
+ i = -1;
+
+ while (1)
+ {
+ edge e;
+
+ /* (1) Critical edges must have a source with multiple successors. */
+ if (bb->succ && bb->succ->succ_next)
{
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+ for (e = bb->succ; e ; e = e->succ_next)
{
- if (eh_note)
- nested_eh_region [NOTE_BLOCK_NUMBER (insn)] =
- NOTE_BLOCK_NUMBER (XEXP (eh_note, 0));
- else
- nested_eh_region [NOTE_BLOCK_NUMBER (insn)] = 0;
- eh_note = gen_rtx_EXPR_LIST (VOIDmode,
- insn, eh_note);
+ /* (2) Critical edges must have a destination with multiple
+ predecessors. Note that we know there is at least one
+ predecessor -- the edge we followed to get here. */
+ if (e->dest->pred->pred_next)
+ e->flags |= EDGE_CRITICAL;
+ else
+ e->flags &= ~EDGE_CRITICAL;
}
- else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
- eh_note = XEXP (eh_note, 1);
}
- /* If we encounter a CALL_INSN, note which exception handler it
- might pass control to.
-
- If doing asynchronous exceptions, record the active EH handler
- for every insn, since most insns can throw. */
- else if (eh_note
- && (asynchronous_exceptions
- || (GET_CODE (insn) == CALL_INSN
- && ! in_libcall_block)))
- active_eh_region[INSN_UID (insn)] =
- NOTE_BLOCK_NUMBER (XEXP (eh_note, 0));
- BLOCK_NUM (insn) = i;
-
- if (code != NOTE)
- prev_code = code;
+ else
+ {
+ for (e = bb->succ; e ; e = e->succ_next)
+ e->flags &= ~EDGE_CRITICAL;
+ }
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && find_reg_note (insn, REG_RETVAL, NULL_RTX))
- in_libcall_block = 0;
+ if (++i >= n)
+ break;
+ bb = BASIC_BLOCK (i);
}
+}
+
+/* Split a (typically critical) edge. Return the new block.
+ Abort on abnormal edges.
+
+ ??? The code generally expects to be called on critical edges.
+ The case of a block ending in an unconditional jump to a
+ block with multiple predecessors is not handled optimally. */
- /* During the second pass, `n_basic_blocks' is only an upper bound.
- Only perform the sanity check for the first pass, and on the second
- pass ensure `n_basic_blocks' is set to the correct value. */
- if (pass == 1 && i + 1 != n_basic_blocks)
+basic_block
+split_edge (edge_in)
+ edge edge_in;
+{
+ basic_block old_pred, bb, old_succ;
+ edge edge_out;
+ rtx bb_note;
+ int i;
+
+ /* Abnormal edges cannot be split. */
+ if ((edge_in->flags & EDGE_ABNORMAL) != 0)
abort ();
- n_basic_blocks = i + 1;
- /* Record which basic blocks control can drop in to. */
+ old_pred = edge_in->src;
+ old_succ = edge_in->dest;
- for (i = 0; i < n_basic_blocks; i++)
+ /* Remove the existing edge from the destination's pred list. */
+ {
+ edge *pp;
+ for (pp = &old_succ->pred; *pp != edge_in; pp = &(*pp)->pred_next)
+ continue;
+ *pp = edge_in->pred_next;
+ edge_in->pred_next = NULL;
+ }
+
+ /* Create the new structures. */
+ bb = (basic_block) obstack_alloc (function_obstack, sizeof (*bb));
+ edge_out = (edge) xcalloc (1, sizeof (*edge_out));
+
+ memset (bb, 0, sizeof (*bb));
+ bb->local_set = OBSTACK_ALLOC_REG_SET (function_obstack);
+ bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (function_obstack);
+ bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (function_obstack);
+
+ /* ??? This info is likely going to be out of date very soon. */
+ CLEAR_REG_SET (bb->local_set);
+ if (old_succ->global_live_at_start)
{
- for (insn = PREV_INSN (basic_block_head[i]);
- insn && GET_CODE (insn) == NOTE; insn = PREV_INSN (insn))
- ;
+ COPY_REG_SET (bb->global_live_at_start, old_succ->global_live_at_start);
+ COPY_REG_SET (bb->global_live_at_end, old_succ->global_live_at_start);
+ }
+ else
+ {
+ CLEAR_REG_SET (bb->global_live_at_start);
+ CLEAR_REG_SET (bb->global_live_at_end);
+ }
+
+ /* Wire them up. */
+ bb->pred = edge_in;
+ bb->succ = edge_out;
+
+ edge_in->dest = bb;
+ edge_in->flags &= ~EDGE_CRITICAL;
+
+ edge_out->pred_next = old_succ->pred;
+ edge_out->succ_next = NULL;
+ edge_out->src = bb;
+ edge_out->dest = old_succ;
+ edge_out->flags = EDGE_FALLTHRU;
+ edge_out->probability = REG_BR_PROB_BASE;
+
+ old_succ->pred = edge_out;
+
+ /* Tricky case -- if there existed a fallthru into the successor
+ (and we're not it) we must add a new unconditional jump around
+ the new block we're actually interested in.
+
+ Further, if that edge is critical, this means a second new basic
+ block must be created to hold it. In order to simplify correct
+ insn placement, do this before we touch the existing basic block
+ ordering for the block we were really wanting. */
+ if ((edge_in->flags & EDGE_FALLTHRU) == 0)
+ {
+ edge e;
+ for (e = edge_out->pred_next; e ; e = e->pred_next)
+ if (e->flags & EDGE_FALLTHRU)
+ break;
+
+ if (e)
+ {
+ basic_block jump_block;
+ rtx pos;
- basic_block_drops_in[i] = insn && GET_CODE (insn) != BARRIER;
+ if ((e->flags & EDGE_CRITICAL) == 0)
+ {
+ /* Non critical -- we can simply add a jump to the end
+ of the existing predecessor. */
+ jump_block = e->src;
+ }
+ else
+ {
+ /* We need a new block to hold the jump. The simplest
+ way to do the bulk of the work here is to recursively
+ call ourselves. */
+ jump_block = split_edge (e);
+ e = jump_block->succ;
+ }
+
+ /* Now add the jump insn ... */
+ pos = emit_jump_insn_after (gen_jump (old_succ->head),
+ jump_block->end);
+ jump_block->end = pos;
+ emit_barrier_after (pos);
+
+ /* ... let jump know that label is in use, ... */
+ ++LABEL_NUSES (old_succ->head);
+
+ /* ... and clear fallthru on the outgoing edge. */
+ e->flags &= ~EDGE_FALLTHRU;
+
+ /* Continue splitting the interesting edge. */
+ }
}
- /* Now find which basic blocks can actually be reached
- and put all jump insns' LABEL_REFS onto the ref-chains
- of their target labels. */
+ /* Place the new block just in front of the successor. */
+ VARRAY_GROW (basic_block_info, ++n_basic_blocks);
+ for (i = n_basic_blocks - 1; i > old_succ->index; --i)
+ {
+ basic_block tmp = BASIC_BLOCK (i - 1);
+ BASIC_BLOCK (i) = tmp;
+ tmp->index = i;
+ }
+ BASIC_BLOCK (i) = bb;
+ bb->index = i;
- if (n_basic_blocks > 0)
+ /* Create the basic block note. */
+ bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, old_succ->head);
+ NOTE_BASIC_BLOCK (bb_note) = bb;
+ bb->head = bb->end = bb_note;
+
+ /* Not quite simple -- for non-fallthru edges, we must adjust the
+ predecessor's jump instruction to target our new block. */
+ if ((edge_in->flags & EDGE_FALLTHRU) == 0)
{
- int something_marked = 1;
- int deleted;
+ rtx tmp, insn = old_pred->end;
+ rtx old_label = old_succ->head;
+ rtx new_label = gen_label_rtx ();
- /* Pass over all blocks, marking each block that is reachable
- and has not yet been marked.
- Keep doing this until, in one pass, no blocks have been marked.
- Then blocks_live and blocks_marked are identical and correct.
- In addition, all jumps actually reachable have been marked. */
+ if (GET_CODE (insn) != JUMP_INSN)
+ abort ();
- while (something_marked)
+ /* ??? Recognize a tablejump and adjust all matching cases. */
+ if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
+ && (tmp = NEXT_INSN (tmp)) != NULL_RTX
+ && GET_CODE (tmp) == JUMP_INSN
+ && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
+ || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
{
- something_marked = 0;
- for (i = 0; i < n_basic_blocks; i++)
- if (block_live[i] && !block_marked[i])
+ rtvec vec;
+ int j;
+
+ if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
+ vec = XVEC (PATTERN (tmp), 0);
+ else
+ vec = XVEC (PATTERN (tmp), 1);
+
+ for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
+ if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
{
- block_marked[i] = 1;
- something_marked = 1;
- if (i + 1 < n_basic_blocks && basic_block_drops_in[i + 1])
- block_live[i + 1] = 1;
- insn = basic_block_end[i];
- if (GET_CODE (insn) == JUMP_INSN)
- mark_label_ref (PATTERN (insn), insn, 0);
-
- /* If we have any forced labels, mark them as potentially
- reachable from this block. */
- for (x = forced_labels; x; x = XEXP (x, 1))
- if (! LABEL_REF_NONLOCAL_P (x))
- mark_label_ref (gen_rtx_LABEL_REF (VOIDmode, XEXP (x, 0)),
- insn, 0);
-
- /* Now scan the insns for this block, we may need to make
- edges for some of them to various non-obvious locations
- (exception handlers, nonlocal labels, etc). */
- for (insn = basic_block_head[i];
- insn != NEXT_INSN (basic_block_end[i]);
- insn = NEXT_INSN (insn))
- {
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
-
- /* References to labels in non-jumping insns have
- REG_LABEL notes attached to them.
-
- This can happen for computed gotos; we don't care
- about them here since the values are also on the
- label_value_list and will be marked live if we find
- a live computed goto.
-
- This can also happen when we take the address of
- a label to pass as an argument to __throw. Note
- throw only uses the value to determine what handler
- should be called -- ie the label is not used as
- a jump target, it just marks regions in the code.
-
- In theory we should be able to ignore the REG_LABEL
- notes, but we have to make sure that the label and
- associated insns aren't marked dead, so we make
- the block in question live and create an edge from
- this insn to the label. This is not strictly
- correct, but it is close enough for now. */
- for (note = REG_NOTES (insn);
- note;
- note = XEXP (note, 1))
- {
- if (REG_NOTE_KIND (note) == REG_LABEL)
- {
- x = XEXP (note, 0);
- block_live[BLOCK_NUM (x)] = 1;
- mark_label_ref (gen_rtx_LABEL_REF (VOIDmode, x),
- insn, 0);
- }
- }
-
- /* If this is a computed jump, then mark it as
- reaching everything on the label_value_list
- and forced_labels list. */
- if (computed_jump_p (insn))
- {
- current_function_has_computed_jump = 1;
- for (x = label_value_list; x; x = XEXP (x, 1))
- {
- int b = BLOCK_NUM (XEXP (x, 0));
- basic_block_computed_jump_target[b] = 1;
- mark_label_ref (gen_rtx_LABEL_REF (VOIDmode,
- XEXP (x, 0)),
- insn, 0);
- }
-
- for (x = forced_labels; x; x = XEXP (x, 1))
- {
- int b = BLOCK_NUM (XEXP (x, 0));
- basic_block_computed_jump_target[b] = 1;
- mark_label_ref (gen_rtx_LABEL_REF (VOIDmode,
- XEXP (x, 0)),
- insn, 0);
- }
- }
-
- /* If this is a CALL_INSN, then mark it as reaching
- the active EH handler for this CALL_INSN. If
- we're handling asynchronous exceptions mark every
- insn as reaching the active EH handler.
-
- Also mark the CALL_INSN as reaching any nonlocal
- goto sites. */
- else if (asynchronous_exceptions
- || (GET_CODE (insn) == CALL_INSN
- && ! find_reg_note (insn, REG_RETVAL,
- NULL_RTX)))
- {
- if (active_eh_region[INSN_UID (insn)])
- {
- int region;
- handler_info *ptr;
- region = active_eh_region[INSN_UID (insn)];
- for ( ; region;
- region = nested_eh_region[region])
- {
- ptr = get_first_handler (region);
- for ( ; ptr ; ptr = ptr->next)
- mark_label_ref (gen_rtx_LABEL_REF
- (VOIDmode, ptr->handler_label), insn, 0);
- }
- }
- if (!asynchronous_exceptions)
- {
- for (x = nonlocal_label_list;
- x;
- x = XEXP (x, 1))
- mark_label_ref (gen_rtx_LABEL_REF (VOIDmode,
- XEXP (x, 0)),
- insn, 0);
- }
- /* ??? This could be made smarter:
- in some cases it's possible to tell that
- certain calls will not do a nonlocal goto.
-
- For example, if the nested functions that
- do the nonlocal gotos do not have their
- addresses taken, then only calls to those
- functions or to other nested functions that
- use them could possibly do nonlocal gotos. */
- }
- }
- }
+ RTVEC_ELT (vec, j) = gen_rtx_LABEL_REF (VOIDmode, new_label);
+ --LABEL_NUSES (old_label);
+ ++LABEL_NUSES (new_label);
}
}
+ else
+ {
+ /* This would have indicated an abnormal edge. */
+ if (computed_jump_p (insn))
+ abort ();
+
+ /* A return instruction can't be redirected. */
+ if (returnjump_p (insn))
+ abort ();
+
+ /* If the insn doesn't go where we think, we're confused. */
+ if (JUMP_LABEL (insn) != old_label)
+ abort ();
+
+ redirect_jump (insn, new_label);
+ }
+
+ emit_label_before (new_label, bb_note);
+ bb->head = new_label;
+ }
+
+ return bb;
+}
+
+/* Queue instructions for insertion on an edge between two basic blocks.
+ The new instructions and basic blocks (if any) will not appear in the
+ CFG until commit_edge_insertions is called. */
+
+void
+insert_insn_on_edge (pattern, e)
+ rtx pattern;
+ edge e;
+{
+ /* We cannot insert instructions on an abnormal critical edge.
+ It will be easier to find the culprit if we die now. */
+ if ((e->flags & (EDGE_ABNORMAL|EDGE_CRITICAL))
+ == (EDGE_ABNORMAL|EDGE_CRITICAL))
+ abort ();
+
+ if (e->insns == NULL_RTX)
+ start_sequence ();
+ else
+ push_to_sequence (e->insns);
+
+ emit_insn (pattern);
+
+ e->insns = get_insns ();
+ end_sequence();
+}
+
+/* Update the CFG for the instructions queued on edge E. */
+
+static void
+commit_one_edge_insertion (e)
+ edge e;
+{
+ rtx before = NULL_RTX, after = NULL_RTX, tmp;
+ basic_block bb;
+
+ /* Figure out where to put these things. If the destination has
+ one predecessor, insert there. Except for the exit block. */
+ if (e->dest->pred->pred_next == NULL
+ && e->dest != EXIT_BLOCK_PTR)
+ {
+ bb = e->dest;
+
+ /* Get the location correct wrt a code label, and "nice" wrt
+ a basic block note, and before everything else. */
+ tmp = bb->head;
+ if (GET_CODE (tmp) == CODE_LABEL)
+ tmp = NEXT_INSN (tmp);
+ if (GET_CODE (tmp) == NOTE
+ && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BASIC_BLOCK)
+ tmp = NEXT_INSN (tmp);
+ if (tmp == bb->head)
+ before = tmp;
+ else
+ after = PREV_INSN (tmp);
+ }
+
+ /* If the source has one successor and the edge is not abnormal,
+ insert there. Except for the entry block. */
+ else if ((e->flags & EDGE_ABNORMAL) == 0
+ && e->src->succ->succ_next == NULL
+ && e->src != ENTRY_BLOCK_PTR)
+ {
+ bb = e->src;
+ if (GET_CODE (bb->end) == JUMP_INSN)
+ {
+ /* ??? Is it possible to wind up with non-simple jumps? Perhaps
+ a jump with delay slots already filled? */
+ if (! simplejump_p (bb->end))
+ abort ();
+
+ before = bb->end;
+ }
+ else
+ {
+ /* We'd better be fallthru, or we've lost track of what's what. */
+ if ((e->flags & EDGE_FALLTHRU) == 0)
+ abort ();
+
+ after = bb->end;
+ }
+ }
+
+ /* Otherwise we must split the edge. */
+ else
+ {
+ bb = split_edge (e);
+ after = bb->end;
+ }
+
+ /* Now that we've found the spot, do the insertion. */
+ tmp = e->insns;
+ e->insns = NULL_RTX;
+ if (before)
+ {
+ emit_insns_before (tmp, before);
+ if (before == bb->head)
+ bb->head = before;
+ }
+ else
+ {
+ tmp = emit_insns_after (tmp, after);
+ if (after == bb->end)
+ bb->end = tmp;
+ }
+}
+
+/* Update the CFG for all queued instructions. */
+
+void
+commit_edge_insertions ()
+{
+ int i;
+ basic_block bb;
+
+ i = -1;
+ bb = ENTRY_BLOCK_PTR;
+ while (1)
+ {
+ edge e, next;
+
+ for (e = bb->succ; e ; e = next)
+ {
+ next = e->succ_next;
+ if (e->insns)
+ commit_one_edge_insertion (e);
+ }
+
+ if (++i >= n_basic_blocks)
+ break;
+ bb = BASIC_BLOCK (i);
+ }
+}
+
+/* Delete all unreachable basic blocks. */
+
+static void
+delete_unreachable_blocks ()
+{
+ basic_block *worklist, *tos;
+ int deleted_handler;
+ edge e;
+ int i, n;
- /* This should never happen. If it does that means we've computed an
- incorrect flow graph, which can lead to aborts/crashes later in the
- compiler or incorrect code generation.
-
- We used to try and continue here, but that's just asking for trouble
- later during the compile or at runtime. It's easier to debug the
- problem here than later! */
- 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])
- abort ();
-
- /* Now delete the code for any basic blocks that can't be reached.
- They can occur because jump_optimize does not recognize
- unreachable loops as unreachable. */
-
- deleted = 0;
- for (i = 0; i < n_basic_blocks; i++)
- if (!block_live[i])
+ n = n_basic_blocks;
+ tos = worklist = (basic_block *) alloca (sizeof (basic_block) * n);
+
+ /* Use basic_block->aux as a marker. Clear them all. */
+
+ for (i = 0; i < n; ++i)
+ BASIC_BLOCK (i)->aux = NULL;
+
+ /* Add our starting points to the worklist. Almost always there will
+ be only one. It isn't inconcievable that we might one day directly
+ support Fortran alternate entry points. */
+
+ for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
+ {
+ *tos++ = e->dest;
+
+ /* Mark the block with a handy non-null value. */
+ e->dest->aux = e;
+ }
+
+ /* Iterate: find everything reachable from what we've already seen. */
+
+ while (tos != worklist)
+ {
+ basic_block b = *--tos;
+
+ for (e = b->succ; e ; e = e->succ_next)
+ if (!e->dest->aux)
{
- deleted++;
-
- /* Delete the insns in a (non-live) block. We physically delete
- every non-note insn except the start and end (so
- basic_block_head/end needn't be updated), we turn the latter
- into NOTE_INSN_DELETED notes.
- We use to "delete" the insns by turning them into notes, but
- we may be deleting lots of insns that subsequent passes would
- otherwise have to process. Secondly, lots of deleted blocks in
- a row can really slow down propagate_block since it will
- otherwise process insn-turned-notes multiple times when it
- looks for loop begin/end notes. */
- if (basic_block_head[i] != basic_block_end[i])
- {
- /* It would be quicker to delete all of these with a single
- unchaining, rather than one at a time, but we need to keep
- the NOTE's. */
- insn = NEXT_INSN (basic_block_head[i]);
- while (insn != basic_block_end[i])
- {
- if (GET_CODE (insn) == BARRIER)
- abort ();
- else if (GET_CODE (insn) != NOTE)
- insn = flow_delete_insn (insn);
- else
- insn = NEXT_INSN (insn);
- }
- }
- insn = basic_block_head[i];
- if (GET_CODE (insn) != NOTE)
- {
- /* Turn the head into a deleted insn note. */
- if (GET_CODE (insn) == BARRIER)
- abort ();
-
- /* If the head of this block is a CODE_LABEL, then it might
- be the label for an exception handler which can't be
- reached.
-
- We need to remove the label from the exception_handler_label
- list and remove the associated NOTE_EH_REGION_BEG and
- NOTE_EH_REGION_END notes. */
- if (GET_CODE (insn) == CODE_LABEL)
- {
- rtx x, *prev = &exception_handler_labels;
-
- for (x = exception_handler_labels; x; x = XEXP (x, 1))
- {
- if (XEXP (x, 0) == insn)
- {
- /* Found a match, splice this label out of the
- EH label list. */
- *prev = XEXP (x, 1);
- XEXP (x, 1) = NULL_RTX;
- XEXP (x, 0) = NULL_RTX;
-
- /* Remove the handler from all regions */
- remove_handler (insn);
- deleted_handler = 1;
- break;
- }
- prev = &XEXP (x, 1);
- }
- }
-
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
- insn = basic_block_end[i];
- if (GET_CODE (insn) != NOTE)
+ *tos++ = e->dest;
+ e->dest->aux = e;
+ }
+ }
+
+ /* Delete all unreachable basic blocks. Count down so that we don't
+ interfere with the block renumbering that happens in delete_block. */
+
+ deleted_handler = 0;
+
+ for (i = n - 1; i >= 0; --i)
+ {
+ basic_block b = BASIC_BLOCK (i);
+
+ if (b->aux != NULL)
+ /* This block was found. Tidy up the mark. */
+ b->aux = NULL;
+ else
+ deleted_handler |= delete_block (b);
+ }
+
+ /* Fix up edges that now fall through, or rather should now fall through
+ but previously required a jump around now deleted blocks. Simplify
+ the search by only examining blocks numerically adjacent, since this
+ is how find_basic_blocks created them. */
+
+ for (i = 1; i < n_basic_blocks; ++i)
+ {
+ basic_block b = BASIC_BLOCK (i - 1);
+ basic_block c = BASIC_BLOCK (i);
+ edge s;
+
+ /* We care about simple conditional or unconditional jumps with
+ a single successor.
+
+ If we had a conditional branch to the next instruction when
+ find_basic_blocks was called, then there will only be one
+ out edge for the block which ended with the conditional
+ branch (since we do not create duplicate edges).
+
+ Furthermore, the edge will be marked as a fallthru because we
+ merge the flags for the duplicate edges. So we do not want to
+ check that the edge is not a FALLTHRU edge. */
+ if ((s = b->succ) != NULL
+ && s->succ_next == NULL
+ && s->dest == c
+ /* If the last insn is not a normal conditional jump
+ (or an unconditional jump), then we can not tidy the
+ fallthru edge because we can not delete the jump. */
+ && GET_CODE (b->end) == JUMP_INSN
+ && condjump_p (b->end))
+ tidy_fallthru_edge (s, b, c);
+ }
+
+ /* Attempt to merge blocks as made possible by edge removal. If a block
+ has only one successor, and the successor has only one predecessor,
+ they may be combined. */
+
+ for (i = 0; i < n_basic_blocks; )
+ {
+ basic_block c, b = BASIC_BLOCK (i);
+ edge s;
+
+ /* A loop because chains of blocks might be combineable. */
+ while ((s = b->succ) != NULL
+ && s->succ_next == NULL
+ && (s->flags & EDGE_EH) == 0
+ && (c = s->dest) != EXIT_BLOCK_PTR
+ && c->pred->pred_next == NULL
+ /* If the last insn is not a normal conditional jump
+ (or an unconditional jump), then we can not merge
+ the blocks because we can not delete the jump. */
+ && GET_CODE (b->end) == JUMP_INSN
+ && condjump_p (b->end)
+ && merge_blocks (s, b, c))
+ continue;
+
+ /* Don't get confused by the index shift caused by deleting blocks. */
+ i = b->index + 1;
+ }
+
+ /* If we deleted an exception handler, we may have EH region begin/end
+ blocks to remove as well. */
+ if (deleted_handler)
+ delete_eh_regions ();
+}
+
+/* Find EH regions for which there is no longer a handler, and delete them. */
+
+static void
+delete_eh_regions ()
+{
+ rtx insn;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == NOTE)
+ {
+ if ((NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG) ||
+ (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
+ {
+ int num = CODE_LABEL_NUMBER (insn);
+ /* A NULL handler indicates a region is no longer needed */
+ if (get_first_handler (num) == NULL)
{
- /* Turn the tail into a deleted insn note. */
- if (GET_CODE (insn) == BARRIER)
- abort ();
- PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
- /* BARRIERs are between basic blocks, not part of one.
- Delete a BARRIER if the preceding jump is deleted.
- We cannot alter a BARRIER into a NOTE
- because it is too short; but we can really delete
- it because it is not part of a basic block. */
- if (NEXT_INSN (insn) != 0
- && GET_CODE (NEXT_INSN (insn)) == BARRIER)
- delete_insn (NEXT_INSN (insn));
-
- /* Each time we delete some basic blocks,
- see if there is a jump around them that is
- being turned into a no-op. If so, delete it. */
-
- if (block_live[i - 1])
- {
- register int j;
- for (j = i + 1; j < n_basic_blocks; j++)
- if (block_live[j])
- {
- rtx label;
- insn = basic_block_end[i - 1];
- if (GET_CODE (insn) == JUMP_INSN
- /* An unconditional jump is the only possibility
- we must check for, since a conditional one
- would make these blocks live. */
- && simplejump_p (insn)
- && (label = XEXP (SET_SRC (PATTERN (insn)), 0), 1)
- && INSN_UID (label) != 0
- && BLOCK_NUM (label) == j)
- {
- int k;
-
- /* The deleted blocks still show up in the cfg,
- so we must set basic_block_drops_in for blocks
- I to J inclusive to keep the cfg accurate. */
- for (k = i; k <= j; k++)
- basic_block_drops_in[k] = 1;
-
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- if (GET_CODE (NEXT_INSN (insn)) != BARRIER)
- abort ();
- delete_insn (NEXT_INSN (insn));
- }
- break;
- }
- }
}
- /* If we deleted an exception handler, we may have EH region
- begin/end blocks to remove as well. */
- if (deleted_handler)
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == NOTE)
- {
- if ((NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG) ||
- (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
- {
- int num = CODE_LABEL_NUMBER (insn);
- /* A NULL handler indicates a region is no longer needed */
- if (get_first_handler (num) == NULL)
- {
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
- }
- }
-
- /* There are pathological cases where one function calling hundreds of
- nested inline functions can generate lots and lots of unreachable
- blocks that jump can't delete. Since we don't use sparse matrices
- a lot of memory will be needed to compile such functions.
- Implementing sparse matrices is a fair bit of work and it is not
- clear that they win more than they lose (we don't want to
- unnecessarily slow down compilation of normal code). By making
- another pass for the pathological case, we can greatly speed up
- their compilation without hurting normal code. This works because
- all the insns in the unreachable blocks have either been deleted or
- turned into notes.
- Note that we're talking about reducing memory usage by 10's of
- megabytes and reducing compilation time by several minutes. */
- /* ??? The choice of when to make another pass is a bit arbitrary,
- and was derived from empirical data. */
- if (pass == 1
- && deleted > 200)
+ }
+}
+
+/* Return true if NOTE is not one of the ones that must be kept paired,
+ so that we may simply delete them. */
+
+static int
+can_delete_note_p (note)
+ rtx note;
+{
+ return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
+ || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK);
+}
+
+/* Unlink a chain of insns between START and FINISH, leaving notes
+ that must be paired. */
+
+static void
+delete_insn_chain (start, finish)
+ rtx start, finish;
+{
+ /* Unchain the insns one by one. It would be quicker to delete all
+ of these with a single unchaining, rather than one at a time, but
+ we need to keep the NOTE's. */
+
+ rtx next;
+
+ while (1)
+ {
+ next = NEXT_INSN (start);
+ if (GET_CODE (start) == NOTE && !can_delete_note_p (start))
+ ;
+ else if (GET_CODE (start) == CODE_LABEL && !can_delete_label_p (start))
+ ;
+ else
+ next = flow_delete_insn (start);
+
+ if (start == finish)
+ break;
+ start = next;
+ }
+}
+
+/* Delete the insns in a (non-live) block. We physically delete every
+ non-deleted-note insn, and update the flow graph appropriately.
+
+ Return nonzero if we deleted an exception handler. */
+
+/* ??? Preserving all such notes strikes me as wrong. It would be nice
+ to post-process the stream to remove empty blocks, loops, ranges, etc. */
+
+static int
+delete_block (b)
+ basic_block b;
+{
+ int deleted_handler = 0;
+ rtx insn, end;
+
+ /* If the head of this block is a CODE_LABEL, then it might be the
+ label for an exception handler which can't be reached.
+
+ We need to remove the label from the exception_handler_label list
+ and remove the associated NOTE_EH_REGION_BEG and NOTE_EH_REGION_END
+ notes. */
+
+ insn = b->head;
+
+ if (GET_CODE (insn) == CODE_LABEL)
+ {
+ rtx x, *prev = &exception_handler_labels;
+
+ for (x = exception_handler_labels; x; x = XEXP (x, 1))
{
- pass++;
- n_basic_blocks -= deleted;
- /* `n_basic_blocks' may not be correct at this point: two previously
- separate blocks may now be merged. That's ok though as we
- recalculate it during the second pass. It certainly can't be
- any larger than the current value. */
- goto restart;
+ if (XEXP (x, 0) == insn)
+ {
+ /* Found a match, splice this label out of the EH label list. */
+ *prev = XEXP (x, 1);
+ XEXP (x, 1) = NULL_RTX;
+ XEXP (x, 0) = NULL_RTX;
+
+ /* Remove the handler from all regions */
+ remove_handler (insn);
+ deleted_handler = 1;
+ break;
+ }
+ prev = &XEXP (x, 1);
+ }
+
+ /* This label may be referenced by code solely for its value, or
+ referenced by static data, or something. We have determined
+ that it is not reachable, but cannot delete the label itself.
+ Save code space and continue to delete the balance of the block,
+ along with properly updating the cfg. */
+ if (!can_delete_label_p (insn))
+ {
+ /* If we've only got one of these, skip the whole deleting
+ insns thing. */
+ if (insn == b->end)
+ goto no_delete_insns;
+ insn = NEXT_INSN (insn);
}
}
+
+ /* Selectively unlink the insn chain. Include any BARRIER that may
+ follow the basic block. */
+ end = next_nonnote_insn (b->end);
+ if (!end || GET_CODE (end) != BARRIER)
+ end = b->end;
+ delete_insn_chain (insn, end);
+
+no_delete_insns:
+
+ /* Remove the edges into and out of this block. Note that there may
+ indeed be edges in, if we are removing an unreachable loop. */
+ {
+ edge e, next, *q;
+
+ for (e = b->pred; e ; e = next)
+ {
+ for (q = &e->src->succ; *q != e; q = &(*q)->succ_next)
+ continue;
+ *q = e->succ_next;
+ next = e->pred_next;
+ free (e);
+ }
+ for (e = b->succ; e ; e = next)
+ {
+ for (q = &e->dest->pred; *q != e; q = &(*q)->pred_next)
+ continue;
+ *q = e->pred_next;
+ next = e->succ_next;
+ free (e);
+ }
+
+ b->pred = NULL;
+ b->succ = NULL;
+ }
+
+ /* Remove the basic block from the array, and compact behind it. */
+ expunge_block (b);
+
+ return deleted_handler;
}
-/* Record INSN's block number as BB. */
+/* Remove block B from the basic block array and compact behind it. */
-void
-set_block_num (insn, bb)
- rtx insn;
- int bb;
+static void
+expunge_block (b)
+ basic_block b;
{
- if (INSN_UID (insn) >= max_uid_for_flow)
+ int i, n = n_basic_blocks;
+
+ for (i = b->index; i + 1 < n; ++i)
{
- /* Add one-eighth the size so we don't keep calling xrealloc. */
- max_uid_for_flow = INSN_UID (insn) + (INSN_UID (insn) + 7) / 8;
- uid_block_number = (int *)
- xrealloc (uid_block_number, (max_uid_for_flow + 1) * sizeof (int));
+ basic_block x = BASIC_BLOCK (i + 1);
+ BASIC_BLOCK (i) = x;
+ x->index = i;
}
- BLOCK_NUM (insn) = bb;
+
+ basic_block_info->num_elements--;
+ n_basic_blocks--;
}
-
-/* Subroutines of find_basic_blocks. */
+/* Delete INSN by patching it out. Return the next insn. */
+
+static rtx
+flow_delete_insn (insn)
+ rtx insn;
+{
+ rtx prev = PREV_INSN (insn);
+ rtx next = NEXT_INSN (insn);
+
+ PREV_INSN (insn) = NULL_RTX;
+ NEXT_INSN (insn) = NULL_RTX;
+
+ if (prev)
+ NEXT_INSN (prev) = next;
+ if (next)
+ PREV_INSN (next) = prev;
+ else
+ set_last_insn (prev);
+
+ if (GET_CODE (insn) == CODE_LABEL)
+ remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
+
+ /* If deleting a jump, decrement the use count of the label. Deleting
+ the label itself should happen in the normal course of block merging. */
+ if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
+ LABEL_NUSES (JUMP_LABEL (insn))--;
+
+ return next;
+}
+
+/* True if a given label can be deleted. */
+
+static int
+can_delete_label_p (label)
+ rtx label;
+{
+ rtx x;
+
+ if (LABEL_PRESERVE_P (label))
+ return 0;
-/* Check expression X for label references;
- if one is found, add INSN to the label's chain of references.
+ for (x = forced_labels; x ; x = XEXP (x, 1))
+ if (label == XEXP (x, 0))
+ return 0;
+ for (x = label_value_list; x ; x = XEXP (x, 1))
+ if (label == XEXP (x, 0))
+ return 0;
+ for (x = exception_handler_labels; x ; x = XEXP (x, 1))
+ if (label == XEXP (x, 0))
+ return 0;
+
+ /* User declared labels must be preserved. */
+ if (LABEL_NAME (label) != 0)
+ return 0;
+
+ return 1;
+}
- CHECKDUP means check for and avoid creating duplicate references
- from the same insn. Such duplicates do no serious harm but
- can slow life analysis. CHECKDUP is set only when duplicates
- are likely. */
+/* Blocks A and B are to be merged into a single block. The insns
+ are already contiguous, hence `nomove'. */
static void
-mark_label_ref (x, insn, checkdup)
- rtx x, insn;
- int checkdup;
+merge_blocks_nomove (a, b)
+ basic_block a, b;
{
- register RTX_CODE code;
- register int i;
- register char *fmt;
+ edge e;
+ rtx b_head, b_end, a_end;
+ int b_empty = 0;
+
+ /* If there was a CODE_LABEL beginning B, delete it. */
+ b_head = b->head;
+ b_end = b->end;
+ if (GET_CODE (b_head) == CODE_LABEL)
+ {
+ /* Detect basic blocks with nothing but a label. This can happen
+ in particular at the end of a function. */
+ if (b_head == b_end)
+ b_empty = 1;
+ b_head = flow_delete_insn (b_head);
+ }
- /* We can be called with NULL when scanning label_value_list. */
- if (x == 0)
- return;
+ /* Delete the basic block note. */
+ if (GET_CODE (b_head) == NOTE
+ && NOTE_LINE_NUMBER (b_head) == NOTE_INSN_BASIC_BLOCK)
+ {
+ if (b_head == b_end)
+ b_empty = 1;
+ b_head = flow_delete_insn (b_head);
+ }
- code = GET_CODE (x);
- if (code == LABEL_REF)
+ /* If there was a jump out of A, delete it. */
+ a_end = a->end;
+ if (GET_CODE (a_end) == JUMP_INSN)
{
- register rtx label = XEXP (x, 0);
- register rtx y;
- if (GET_CODE (label) != CODE_LABEL)
- abort ();
- /* If the label was never emitted, this insn is junk,
- but avoid a crash trying to refer to BLOCK_NUM (label).
- This can happen as a result of a syntax error
- and a diagnostic has already been printed. */
- if (INSN_UID (label) == 0)
- return;
- CONTAINING_INSN (x) = insn;
- /* if CHECKDUP is set, check for duplicate ref from same insn
- and don't insert. */
- if (checkdup)
- for (y = LABEL_REFS (label); y != label; y = LABEL_NEXTREF (y))
- if (CONTAINING_INSN (y) == insn)
- return;
- LABEL_NEXTREF (x) = LABEL_REFS (label);
- LABEL_REFS (label) = x;
- block_live_static[BLOCK_NUM (label)] = 1;
- return;
+ rtx prev;
+
+ prev = prev_nonnote_insn (a_end);
+ if (!prev)
+ prev = a->head;
+
+#ifdef HAVE_cc0
+ /* If this was a conditional jump, we need to also delete
+ the insn that set cc0. */
+
+ if (prev && sets_cc0_p (prev))
+ {
+ rtx tmp = prev;
+ prev = prev_nonnote_insn (prev);
+ if (!prev)
+ prev = a->head;
+ flow_delete_insn (tmp);
+ }
+#endif
+
+ /* Note that a->head != a->end, since we should have at least a
+ bb note plus the jump, so prev != insn. */
+ flow_delete_insn (a_end);
+ a_end = prev;
}
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ /* By definition, there should only be one successor of A, and that is
+ B. Free that edge struct. */
+ free (a->succ);
+
+ /* Adjust the edges out of B for the new owner. */
+ for (e = b->succ; e ; e = e->succ_next)
+ e->src = a;
+ a->succ = b->succ;
+
+ /* Reassociate the insns of B with A. */
+ if (!b_empty)
{
- if (fmt[i] == 'e')
- mark_label_ref (XEXP (x, i), insn, 0);
- if (fmt[i] == 'E')
+ BLOCK_FOR_INSN (b_head) = a;
+ while (b_head != b_end)
{
- register int j;
- for (j = 0; j < XVECLEN (x, i); j++)
- mark_label_ref (XVECEXP (x, i, j), insn, 1);
+ b_head = NEXT_INSN (b_head);
+ BLOCK_FOR_INSN (b_head) = a;
}
+ a_end = b_head;
}
+ a->end = a_end;
+
+ /* Compact the basic block array. */
+ expunge_block (b);
}
-/* Delete INSN by patching it out.
- Return the next insn. */
+/* Attempt to merge basic blocks that are potentially non-adjacent.
+ Return true iff the attempt succeeded. */
-static rtx
-flow_delete_insn (insn)
- rtx insn;
+static int
+merge_blocks (e, b, c)
+ edge e;
+ basic_block b, c;
+{
+ /* If B has a fallthru edge to C, no need to move anything. */
+ if (!(e->flags & EDGE_FALLTHRU))
+ {
+ /* ??? From here on out we must make sure to not munge nesting
+ of exception regions and lexical blocks. Need to think about
+ these cases before this gets implemented. */
+ return 0;
+
+ /* If C has an outgoing fallthru, and B does not have an incoming
+ fallthru, move B before C. The later clause is somewhat arbitrary,
+ but avoids modifying blocks other than the two we've been given. */
+
+ /* Otherwise, move C after B. If C had a fallthru, which doesn't
+ happen to be the physical successor to B, insert an unconditional
+ branch. If C already ended with a conditional branch, the new
+ jump must go in a new basic block D. */
+ }
+
+ /* If a label still appears somewhere and we cannot delete the label,
+ then we cannot merge the blocks. The edge was tidied already. */
+ {
+ rtx insn, stop = NEXT_INSN (c->head);
+ for (insn = NEXT_INSN (b->end); insn != stop; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == CODE_LABEL && !can_delete_label_p (insn))
+ return 0;
+ }
+
+ merge_blocks_nomove (b, c);
+ return 1;
+}
+
+/* The given edge should potentially a fallthru edge. If that is in
+ fact true, delete the unconditional jump and barriers that are in
+ the way. */
+
+static void
+tidy_fallthru_edge (e, b, c)
+ edge e;
+ basic_block b, c;
+{
+ rtx q;
+
+ /* ??? In a late-running flow pass, other folks may have deleted basic
+ blocks by nopping out blocks, leaving multiple BARRIERs between here
+ and the target label. They ought to be chastized and fixed.
+
+ We can also wind up with a sequence of undeletable labels between
+ one block and the next.
+
+ So search through a sequence of barriers, labels, and notes for
+ the head of block C and assert that we really do fall through. */
+
+ if (next_real_insn (b->end) != next_real_insn (PREV_INSN (c->head)))
+ return;
+
+ /* Remove what will soon cease being the jump insn from the source block.
+ If block B consisted only of this single jump, turn it into a deleted
+ note. */
+ q = b->end;
+ if (GET_CODE (q) == JUMP_INSN)
+ {
+#ifdef HAVE_cc0
+ /* If this was a conditional jump, we need to also delete
+ the insn that set cc0. */
+ if (! simplejump_p (q) && condjump_p (q))
+ q = PREV_INSN (q);
+#endif
+
+ if (b->head == q)
+ {
+ PUT_CODE (q, NOTE);
+ NOTE_LINE_NUMBER (q) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (q) = 0;
+ }
+ else
+ b->end = q = PREV_INSN (q);
+ }
+
+ /* Selectively unlink the sequence. */
+ if (q != PREV_INSN (c->head))
+ delete_insn_chain (NEXT_INSN (q), PREV_INSN (c->head));
+
+ e->flags |= EDGE_FALLTHRU;
+}
+
+/* Discover and record the loop depth at the head of each basic block. */
+
+static void
+calculate_loop_depth (insns)
+ rtx insns;
{
- /* ??? For the moment we assume we don't have to watch for NULLs here
- since the start/end of basic blocks aren't deleted like this. */
- NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
- PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
- return NEXT_INSN (insn);
+ basic_block bb;
+ rtx insn;
+ int i = 0, depth = 1;
+
+ bb = BASIC_BLOCK (i);
+ for (insn = insns; insn ; insn = NEXT_INSN (insn))
+ {
+ if (insn == bb->head)
+ {
+ bb->loop_depth = depth;
+ if (++i >= n_basic_blocks)
+ break;
+ bb = BASIC_BLOCK (i);
+ }
+
+ if (GET_CODE (insn) == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+ depth++;
+ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+ depth--;
+
+ /* If we have LOOP_DEPTH == 0, there has been a bookkeeping error. */
+ if (depth == 0)
+ abort ();
+ }
+ }
}
/* Perform data flow analysis.
@@ -995,10 +2067,11 @@ flow_delete_insn (insn)
in use. */
void
-life_analysis (f, nregs, file)
+life_analysis (f, nregs, file, remove_dead_code)
rtx f;
int nregs;
FILE *file;
+ int remove_dead_code;
{
#ifdef ELIMINABLE_REGS
register size_t i;
@@ -1017,194 +2090,144 @@ life_analysis (f, nregs, file)
SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
#endif
- life_analysis_1 (f, nregs);
+ /* Allocate a bitmap to be filled in by record_volatile_insns. */
+ uid_volatile = BITMAP_ALLOCA ();
+
+ /* We want alias analysis information for local dead store elimination. */
+ init_alias_analysis ();
+ life_analysis_1 (f, nregs, remove_dead_code);
+ end_alias_analysis ();
+
if (file)
dump_flow_info (file);
+ BITMAP_FREE (uid_volatile);
free_basic_block_vars (1);
}
/* Free the variables allocated by find_basic_blocks.
- KEEP_HEAD_END_P is non-zero if basic_block_head and basic_block_end
- are not to be freed. */
+ KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed. */
void
free_basic_block_vars (keep_head_end_p)
int keep_head_end_p;
{
- if (basic_block_drops_in)
+ if (basic_block_for_insn)
{
- free (basic_block_drops_in);
- /* Tell dump_flow_info this isn't available anymore. */
- basic_block_drops_in = 0;
- }
- if (basic_block_loop_depth)
- {
- free (basic_block_loop_depth);
- basic_block_loop_depth = 0;
- }
- if (uid_block_number)
- {
- free (uid_block_number);
- uid_block_number = 0;
- }
- if (uid_volatile)
- {
- free (uid_volatile);
- uid_volatile = 0;
+ VARRAY_FREE (basic_block_for_insn);
+ basic_block_for_insn = NULL;
}
- if (! keep_head_end_p && basic_block_head)
+ if (! keep_head_end_p)
{
- free (basic_block_head);
- basic_block_head = 0;
- free (basic_block_end);
- basic_block_end = 0;
+ clear_edges ();
+ VARRAY_FREE (basic_block_info);
+ n_basic_blocks = 0;
+
+ ENTRY_BLOCK_PTR->aux = NULL;
+ ENTRY_BLOCK_PTR->global_live_at_end = NULL;
+ EXIT_BLOCK_PTR->aux = NULL;
+ EXIT_BLOCK_PTR->global_live_at_start = NULL;
}
}
-/* Determine which registers are live at the start of each
- basic block of the function whose first insn is F.
- NREGS is the number of registers used in F.
- We allocate the vector basic_block_live_at_start
- and the regsets that it points to, and fill them with the data.
- regset_size and regset_bytes are also set here. */
-
-static void
-life_analysis_1 (f, nregs)
- rtx f;
- int nregs;
+/* Return nonzero if the destination of SET equals the source. */
+static int
+set_noop_p (set)
+ rtx set;
{
- int first_pass;
- int changed;
- /* For each basic block, a bitmask of regs
- live on exit from the block. */
- regset *basic_block_live_at_end;
- /* For each basic block, a bitmask of regs
- live on entry to a successor-block of this block.
- If this does not match basic_block_live_at_end,
- that must be updated, and the block must be rescanned. */
- regset *basic_block_new_live_at_end;
- /* For each basic block, a bitmask of regs
- whose liveness at the end of the basic block
- can make a difference in which regs are live on entry to the block.
- These are the regs that are set within the basic block,
- possibly excluding those that are used after they are set. */
- regset *basic_block_significant;
- register int i;
- rtx insn;
-
- struct obstack flow_obstack;
-
- gcc_obstack_init (&flow_obstack);
-
- max_regno = nregs;
-
- bzero (regs_ever_live, sizeof regs_ever_live);
-
- /* Allocate and zero out many data structures
- that will record the data from lifetime analysis. */
+ rtx src = SET_SRC (set);
+ rtx dst = SET_DEST (set);
+ if (GET_CODE (src) == REG && GET_CODE (dst) == REG
+ && REGNO (src) == REGNO (dst))
+ return 1;
+ if (GET_CODE (src) != SUBREG || GET_CODE (dst) != SUBREG
+ || SUBREG_WORD (src) != SUBREG_WORD (dst))
+ return 0;
+ src = SUBREG_REG (src);
+ dst = SUBREG_REG (dst);
+ if (GET_CODE (src) == REG && GET_CODE (dst) == REG
+ && REGNO (src) == REGNO (dst))
+ return 1;
+ return 0;
+}
- allocate_for_life_analysis ();
+/* Return nonzero if an insn consists only of SETs, each of which only sets a
+ value to itself. */
+static int
+noop_move_p (insn)
+ rtx insn;
+{
+ rtx pat = PATTERN (insn);
- reg_next_use = (rtx *) alloca (nregs * sizeof (rtx));
- bzero ((char *) reg_next_use, nregs * sizeof (rtx));
+ /* Insns carrying these notes are useful later on. */
+ if (find_reg_note (insn, REG_EQUAL, NULL_RTX))
+ return 0;
- /* Set up several regset-vectors used internally within this function.
- Their meanings are documented above, with their declarations. */
+ if (GET_CODE (pat) == SET && set_noop_p (pat))
+ return 1;
- basic_block_live_at_end
- = (regset *) alloca (n_basic_blocks * sizeof (regset));
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ int i;
+ /* If nothing but SETs of registers to themselves,
+ this insn can also be deleted. */
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx tem = XVECEXP (pat, 0, i);
- /* Don't use alloca since that leads to a crash rather than an error message
- if there isn't enough space.
- Don't use oballoc since we may need to allocate other things during
- this function on the temporary obstack. */
- init_regset_vector (basic_block_live_at_end, n_basic_blocks, &flow_obstack);
+ if (GET_CODE (tem) == USE
+ || GET_CODE (tem) == CLOBBER)
+ continue;
- basic_block_new_live_at_end
- = (regset *) alloca (n_basic_blocks * sizeof (regset));
- init_regset_vector (basic_block_new_live_at_end, n_basic_blocks,
- &flow_obstack);
+ if (GET_CODE (tem) != SET || ! set_noop_p (tem))
+ return 0;
+ }
- basic_block_significant
- = (regset *) alloca (n_basic_blocks * sizeof (regset));
- init_regset_vector (basic_block_significant, n_basic_blocks, &flow_obstack);
+ return 1;
+ }
+ return 0;
+}
- /* Record which insns refer to any volatile memory
- or for any reason can't be deleted just because they are dead stores.
- Also, delete any insns that copy a register to itself. */
+static void
+notice_stack_pointer_modification (x, pat)
+ rtx x;
+ rtx pat ATTRIBUTE_UNUSED;
+{
+ if (x == stack_pointer_rtx
+ /* The stack pointer is only modified indirectly as the result
+ of a push until later in flow. See the comments in rtl.texi
+ regarding Embedded Side-Effects on Addresses. */
+ || (GET_CODE (x) == MEM
+ && (GET_CODE (XEXP (x, 0)) == PRE_DEC
+ || GET_CODE (XEXP (x, 0)) == PRE_INC
+ || GET_CODE (XEXP (x, 0)) == POST_DEC
+ || GET_CODE (XEXP (x, 0)) == POST_INC)
+ && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx))
+ current_function_sp_is_unchanging = 0;
+}
+/* Record which insns refer to any volatile memory
+ or for any reason can't be deleted just because they are dead stores.
+ Also, delete any insns that copy a register to itself.
+ And see if the stack pointer is modified. */
+static void
+record_volatile_insns (f)
+ rtx f;
+{
+ rtx insn;
for (insn = f; insn; insn = NEXT_INSN (insn))
{
enum rtx_code code1 = GET_CODE (insn);
if (code1 == CALL_INSN)
- INSN_VOLATILE (insn) = 1;
+ SET_INSN_VOLATILE (insn);
else if (code1 == INSN || code1 == JUMP_INSN)
{
- /* Delete (in effect) any obvious no-op moves. */
- if (GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- && (REGNO (SET_DEST (PATTERN (insn)))
- == REGNO (SET_SRC (PATTERN (insn))))
- /* Insns carrying these notes are useful later on. */
- && ! find_reg_note (insn, REG_EQUAL, NULL_RTX))
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
- /* Delete (in effect) any obvious no-op moves. */
- else if (GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == SUBREG
- && GET_CODE (SUBREG_REG (SET_DEST (PATTERN (insn)))) == REG
- && GET_CODE (SET_SRC (PATTERN (insn))) == SUBREG
- && GET_CODE (SUBREG_REG (SET_SRC (PATTERN (insn)))) == REG
- && (REGNO (SUBREG_REG (SET_DEST (PATTERN (insn))))
- == REGNO (SUBREG_REG (SET_SRC (PATTERN (insn)))))
- && SUBREG_WORD (SET_DEST (PATTERN (insn))) ==
- SUBREG_WORD (SET_SRC (PATTERN (insn)))
- /* Insns carrying these notes are useful later on. */
- && ! find_reg_note (insn, REG_EQUAL, NULL_RTX))
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
- else if (GET_CODE (PATTERN (insn)) == PARALLEL)
- {
- /* If nothing but SETs of registers to themselves,
- this insn can also be deleted. */
- for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- {
- rtx tem = XVECEXP (PATTERN (insn), 0, i);
-
- if (GET_CODE (tem) == USE
- || GET_CODE (tem) == CLOBBER)
- continue;
-
- if (GET_CODE (tem) != SET
- || GET_CODE (SET_DEST (tem)) != REG
- || GET_CODE (SET_SRC (tem)) != REG
- || REGNO (SET_DEST (tem)) != REGNO (SET_SRC (tem)))
- break;
- }
-
- if (i == XVECLEN (PATTERN (insn), 0)
- /* Insns carrying these notes are useful later on. */
- && ! find_reg_note (insn, REG_EQUAL, NULL_RTX))
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
- else
- INSN_VOLATILE (insn) = volatile_refs_p (PATTERN (insn));
- }
- else if (GET_CODE (PATTERN (insn)) != USE)
- INSN_VOLATILE (insn) = volatile_refs_p (PATTERN (insn));
+ if (GET_CODE (PATTERN (insn)) != USE
+ && volatile_refs_p (PATTERN (insn)))
+ SET_INSN_VOLATILE (insn);
+
/* A SET that makes space on the stack cannot be dead.
(Such SETs occur only for allocating variable-size data,
so they will always have a PLUS or MINUS according to the
@@ -1219,60 +2242,150 @@ life_analysis_1 (f, nregs)
&& GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
#endif
&& XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx)
- INSN_VOLATILE (insn) = 1;
+ SET_INSN_VOLATILE (insn);
+
+ /* Delete (in effect) any obvious no-op moves. */
+ else if (noop_move_p (insn))
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
}
+
+ /* Check if insn modifies the stack pointer. */
+ if ( current_function_sp_is_unchanging
+ && GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ note_stores (PATTERN (insn), notice_stack_pointer_modification);
}
+}
- if (n_basic_blocks > 0)
-#ifdef EXIT_IGNORE_STACK
- if (! EXIT_IGNORE_STACK
- || (! FRAME_POINTER_REQUIRED
- && ! current_function_calls_alloca
- && flag_omit_frame_pointer))
-#endif
- {
- /* If exiting needs the right stack value,
- consider the stack pointer live at the end of the function. */
- SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
- STACK_POINTER_REGNUM);
- SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
- STACK_POINTER_REGNUM);
- }
+/* Mark those regs which are needed at the end of the function as live
+ at the end of the last basic block. */
+static void
+mark_regs_live_at_end (set)
+ regset set;
+{
+ int i;
+
+ /* If exiting needs the right stack value, consider the stack pointer
+ live at the end of the function. */
+ if (! EXIT_IGNORE_STACK
+ || (! FRAME_POINTER_REQUIRED
+ && ! current_function_calls_alloca
+ && flag_omit_frame_pointer)
+ || current_function_sp_is_unchanging)
+ {
+ SET_REGNO_REG_SET (set, STACK_POINTER_REGNUM);
+ }
- /* Mark the frame pointer is needed at the end of the function. If
+ /* Mark the frame pointer if needed at the end of the function. If
we end up eliminating it, it will be removed from the live list
of each basic block by reload. */
- if (n_basic_blocks > 0)
+ if (! reload_completed || frame_pointer_needed)
{
- SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
- FRAME_POINTER_REGNUM);
- SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
- FRAME_POINTER_REGNUM);
+ SET_REGNO_REG_SET (set, FRAME_POINTER_REGNUM);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If they are different, also mark the hard frame pointer as live */
- SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
- HARD_FRAME_POINTER_REGNUM);
- SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
- HARD_FRAME_POINTER_REGNUM);
+ SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
#endif
- }
+ }
- /* Mark all global registers and all registers used by the epilogue
+ /* Mark all global registers, and all registers used by the epilogue
as being live at the end of the function since they may be
referenced by our caller. */
-
- if (n_basic_blocks > 0)
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i]
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (global_regs[i]
#ifdef EPILOGUE_USES
- || EPILOGUE_USES (i)
+ || EPILOGUE_USES (i)
#endif
- )
+ )
+ SET_REGNO_REG_SET (set, i);
+
+ /* ??? Mark function return value here rather than as uses. */
+}
+
+/* Determine which registers are live at the start of each
+ basic block of the function whose first insn is F.
+ NREGS is the number of registers used in F.
+ We allocate the vector basic_block_live_at_start
+ and the regsets that it points to, and fill them with the data.
+ regset_size and regset_bytes are also set here. */
+
+static void
+life_analysis_1 (f, nregs, remove_dead_code)
+ rtx f;
+ int nregs;
+ int remove_dead_code;
+{
+ int first_pass;
+ int changed;
+ register int i;
+ char save_regs_ever_live[FIRST_PSEUDO_REGISTER];
+ regset *new_live_at_end;
+
+ struct obstack flow_obstack;
+
+ gcc_obstack_init (&flow_obstack);
+
+ max_regno = nregs;
+
+ /* Allocate and zero out many data structures
+ that will record the data from lifetime analysis. */
+
+ allocate_reg_life_data ();
+ allocate_bb_life_data ();
+
+ reg_next_use = (rtx *) alloca (nregs * sizeof (rtx));
+ memset (reg_next_use, 0, nregs * sizeof (rtx));
+
+ /* Set up regset-vectors used internally within this function.
+ Their meanings are documented above, with their declarations. */
+
+ new_live_at_end = (regset *) alloca ((n_basic_blocks + 1) * sizeof (regset));
+ init_regset_vector (new_live_at_end, n_basic_blocks + 1, &flow_obstack);
+
+ /* Stick these vectors into the AUX field of the basic block, so that
+ we don't have to keep going through the index. */
+
+ for (i = 0; i < n_basic_blocks; ++i)
+ BASIC_BLOCK (i)->aux = new_live_at_end[i];
+ ENTRY_BLOCK_PTR->aux = new_live_at_end[i];
+
+ /* Assume that the stack pointer is unchanging if alloca hasn't been used.
+ This will be cleared by record_volatile_insns if it encounters an insn
+ which modifies the stack pointer. */
+ current_function_sp_is_unchanging = !current_function_calls_alloca;
+
+ record_volatile_insns (f);
+
+ if (n_basic_blocks > 0)
+ {
+ regset theend;
+ register edge e;
+
+ theend = EXIT_BLOCK_PTR->global_live_at_start;
+ mark_regs_live_at_end (theend);
+
+ /* Propogate this exit data to each of EXIT's predecessors. */
+ for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
{
- SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1], i);
- SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1], i);
+ COPY_REG_SET (e->src->global_live_at_end, theend);
+ COPY_REG_SET ((regset) e->src->aux, theend);
}
+ }
+
+ /* The post-reload life analysis have (on a global basis) the same registers
+ live as was computed by reload itself.
+
+ Otherwise elimination offsets and such may be incorrect.
+
+ Reload will make some registers as live even though they do not appear
+ in the rtl. */
+ if (reload_completed)
+ memcpy (save_regs_ever_live, regs_ever_live, sizeof (regs_ever_live));
+ memset (regs_ever_live, 0, sizeof regs_ever_live);
/* Propagate life info through the basic blocks
around the graph of basic blocks.
@@ -1291,6 +2404,7 @@ life_analysis_1 (f, nregs)
changed = 0;
for (i = n_basic_blocks - 1; i >= 0; i--)
{
+ basic_block bb = BASIC_BLOCK (i);
int consider = first_pass;
int must_rescan = first_pass;
register int j;
@@ -1307,11 +2421,10 @@ life_analysis_1 (f, nregs)
is one of the significant regs of this basic block). */
EXECUTE_IF_AND_COMPL_IN_REG_SET
- (basic_block_new_live_at_end[i],
- basic_block_live_at_end[i], 0, j,
+ ((regset) bb->aux, bb->global_live_at_end, 0, j,
{
consider = 1;
- if (REGNO_REG_SET_P (basic_block_significant[i], j))
+ if (REGNO_REG_SET_P (bb->local_set, j))
{
must_rescan = 1;
goto done;
@@ -1331,51 +2444,35 @@ life_analysis_1 (f, nregs)
/* No complete rescan needed;
just record those variables newly known live at end
as live at start as well. */
- IOR_AND_COMPL_REG_SET (basic_block_live_at_start[i],
- basic_block_new_live_at_end[i],
- basic_block_live_at_end[i]);
+ IOR_AND_COMPL_REG_SET (bb->global_live_at_start,
+ (regset) bb->aux,
+ bb->global_live_at_end);
- IOR_AND_COMPL_REG_SET (basic_block_live_at_end[i],
- basic_block_new_live_at_end[i],
- basic_block_live_at_end[i]);
+ IOR_AND_COMPL_REG_SET (bb->global_live_at_end,
+ (regset) bb->aux,
+ bb->global_live_at_end);
}
else
{
/* Update the basic_block_live_at_start
by propagation backwards through the block. */
- COPY_REG_SET (basic_block_live_at_end[i],
- basic_block_new_live_at_end[i]);
- COPY_REG_SET (basic_block_live_at_start[i],
- basic_block_live_at_end[i]);
- propagate_block (basic_block_live_at_start[i],
- basic_block_head[i], basic_block_end[i], 0,
- first_pass ? basic_block_significant[i]
- : (regset) 0,
- i);
+ COPY_REG_SET (bb->global_live_at_end, (regset) bb->aux);
+ COPY_REG_SET (bb->global_live_at_start,
+ bb->global_live_at_end);
+ propagate_block (bb->global_live_at_start,
+ bb->head, bb->end, 0,
+ first_pass ? bb->local_set : (regset) 0,
+ i, remove_dead_code);
}
+ /* Update the new_live_at_end's of the block's predecessors. */
{
- register rtx jump, head;
-
- /* Update the basic_block_new_live_at_end's of the block
- that falls through into this one (if any). */
- head = basic_block_head[i];
- if (basic_block_drops_in[i])
- IOR_REG_SET (basic_block_new_live_at_end[i-1],
- basic_block_live_at_start[i]);
-
- /* Update the basic_block_new_live_at_end's of
- all the blocks that jump to this one. */
- if (GET_CODE (head) == CODE_LABEL)
- for (jump = LABEL_REFS (head);
- jump != head;
- jump = LABEL_NEXTREF (jump))
- {
- register int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
- IOR_REG_SET (basic_block_new_live_at_end[from_block],
- basic_block_live_at_start[i]);
- }
+ register edge e;
+
+ for (e = bb->pred; e ; e = e->pred_next)
+ IOR_REG_SET ((regset) e->src->aux, bb->global_live_at_start);
}
+
#ifdef USE_C_ALLOCA
alloca (0);
#endif
@@ -1389,59 +2486,36 @@ life_analysis_1 (f, nregs)
one basic block. */
if (n_basic_blocks > 0)
- EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[0],
+ EXECUTE_IF_SET_IN_REG_SET (BASIC_BLOCK (0)->global_live_at_start,
FIRST_PSEUDO_REGISTER, i,
{
REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
});
- /* Now the life information is accurate.
- Make one more pass over each basic block
- to delete dead stores, create autoincrement addressing
- and record how many times each register is used, is set, or dies.
-
- To save time, we operate directly in basic_block_live_at_end[i],
- thus destroying it (in fact, converting it into a copy of
- basic_block_live_at_start[i]). This is ok now because
- basic_block_live_at_end[i] is no longer used past this point. */
-
- max_scratch = 0;
+ /* Now the life information is accurate. Make one more pass over each
+ basic block to delete dead stores, create autoincrement addressing
+ and record how many times each register is used, is set, or dies. */
for (i = 0; i < n_basic_blocks; i++)
{
- propagate_block (basic_block_live_at_end[i],
- basic_block_head[i], basic_block_end[i], 1,
- (regset) 0, i);
+ basic_block bb = BASIC_BLOCK (i);
+
+ /* We start with global_live_at_end to determine which stores are
+ dead. This process is destructive, and we wish to preserve the
+ contents of global_live_at_end for posterity. Fortunately,
+ new_live_at_end, due to the way we converged on a solution,
+ contains a duplicate of global_live_at_end that we can kill. */
+ propagate_block ((regset) bb->aux, bb->head, bb->end, 1, (regset) 0, i, remove_dead_code);
+
#ifdef USE_C_ALLOCA
alloca (0);
#endif
}
-#if 0
- /* Something live during a setjmp should not be put in a register
- on certain machines which restore regs from stack frames
- rather than from the jmpbuf.
- But we don't need to do this for the user's variables, since
- ANSI says only volatile variables need this. */
-#ifdef LONGJMP_RESTORE_FROM_STACK
- EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
- FIRST_PSEUDO_REGISTER, i,
- {
- if (regno_reg_rtx[i] != 0
- && ! REG_USERVAR_P (regno_reg_rtx[i]))
- {
- REG_LIVE_LENGTH (i) = -1;
- REG_BASIC_BLOCK (i) = -1;
- }
- });
-#endif
-#endif
-
- /* We have a problem with any pseudoreg that
- lives across the setjmp. ANSI says that if a
- user variable does not change in value
- between the setjmp and the longjmp, then the longjmp preserves it.
- This includes longjmp from a place where the pseudo appears dead.
+ /* We have a problem with any pseudoreg that lives across the setjmp.
+ ANSI says that if a user variable does not change in value between
+ the setjmp and the longjmp, then the longjmp preserves it. This
+ includes longjmp from a place where the pseudo appears dead.
(In principle, the value still exists if it is in scope.)
If the pseudo goes in a hard reg, some other value may occupy
that hard reg where this pseudo is dead, thus clobbering the pseudo.
@@ -1456,15 +2530,16 @@ life_analysis_1 (f, nregs)
}
});
+ /* Restore regs_ever_live that was provided by reload. */
+ if (reload_completed)
+ memcpy (regs_ever_live, save_regs_ever_live, sizeof (regs_ever_live));
- free_regset_vector (basic_block_live_at_end, n_basic_blocks);
- free_regset_vector (basic_block_new_live_at_end, n_basic_blocks);
- free_regset_vector (basic_block_significant, n_basic_blocks);
- basic_block_live_at_end = (regset *)0;
- basic_block_new_live_at_end = (regset *)0;
- basic_block_significant = (regset *)0;
-
+ free_regset_vector (new_live_at_end, n_basic_blocks);
obstack_free (&flow_obstack, NULL_PTR);
+
+ for (i = 0; i < n_basic_blocks; ++i)
+ BASIC_BLOCK (i)->aux = NULL;
+ ENTRY_BLOCK_PTR->aux = NULL;
}
/* Subroutines of life analysis. */
@@ -1473,10 +2548,32 @@ life_analysis_1 (f, nregs)
of life analysis. Not static since used also for stupid life analysis. */
void
-allocate_for_life_analysis ()
+allocate_bb_life_data ()
{
register int i;
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+
+ bb->local_set = OBSTACK_ALLOC_REG_SET (function_obstack);
+ bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (function_obstack);
+ bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (function_obstack);
+ }
+
+ ENTRY_BLOCK_PTR->global_live_at_end
+ = OBSTACK_ALLOC_REG_SET (function_obstack);
+ EXIT_BLOCK_PTR->global_live_at_start
+ = OBSTACK_ALLOC_REG_SET (function_obstack);
+
+ regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (function_obstack);
+}
+
+void
+allocate_reg_life_data ()
+{
+ int i;
+
/* Recalculate the register space, in case it has grown. Old style
vector oriented regsets would set regset_{size,bytes} here also. */
allocate_reg_info (max_regno, FALSE, FALSE);
@@ -1487,14 +2584,6 @@ allocate_for_life_analysis ()
some more registers were allocated. */
for (i = 0; i < max_regno; i++)
REG_N_SETS (i) = 0;
-
- basic_block_live_at_start
- = (regset *) oballoc (n_basic_blocks * sizeof (regset));
- init_regset_vector (basic_block_live_at_start, n_basic_blocks,
- function_obstack);
-
- regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (function_obstack);
- CLEAR_REG_SET (regs_live_at_setjmp);
}
/* Make each element of VECTOR point at a regset. The vector has
@@ -1550,70 +2639,41 @@ free_regset_vector (vector, nelts)
BNUM is the number of the basic block. */
static void
-propagate_block (old, first, last, final, significant, bnum)
+propagate_block (old, first, last, final, significant, bnum, remove_dead_code)
register regset old;
rtx first;
rtx last;
int final;
regset significant;
int bnum;
+ int remove_dead_code;
{
register rtx insn;
rtx prev;
regset live;
regset dead;
- /* The following variables are used only if FINAL is nonzero. */
- /* This vector gets one element for each reg that has been live
- at any point in the basic block that has been scanned so far.
- SOMETIMES_MAX says how many elements are in use so far. */
- register int *regs_sometimes_live;
- int sometimes_max = 0;
- /* This regset has 1 for each reg that we have seen live so far.
- It and REGS_SOMETIMES_LIVE are updated together. */
- regset maxlive;
-
- /* The loop depth may change in the middle of a basic block. Since we
- scan from end to beginning, we start with the depth at the end of the
- current basic block, and adjust as we pass ends and starts of loops. */
- loop_depth = basic_block_loop_depth[bnum];
+ /* Find the loop depth for this block. Ignore loop level changes in the
+ middle of the basic block -- for register allocation purposes, the
+ important uses will be in the blocks wholely contained within the loop
+ not in the loop pre-header or post-trailer. */
+ loop_depth = BASIC_BLOCK (bnum)->loop_depth;
dead = ALLOCA_REG_SET ();
live = ALLOCA_REG_SET ();
cc0_live = 0;
- last_mem_set = 0;
-
- /* Include any notes at the end of the block in the scan.
- This is in case the block ends with a call to setjmp. */
-
- while (NEXT_INSN (last) != 0 && GET_CODE (NEXT_INSN (last)) == NOTE)
- {
- /* Look for loop boundaries, we are going forward here. */
- last = NEXT_INSN (last);
- if (NOTE_LINE_NUMBER (last) == NOTE_INSN_LOOP_BEG)
- loop_depth++;
- else if (NOTE_LINE_NUMBER (last) == NOTE_INSN_LOOP_END)
- loop_depth--;
- }
+ mem_set_list = NULL_RTX;
if (final)
{
register int i;
- num_scratch = 0;
- maxlive = ALLOCA_REG_SET ();
- COPY_REG_SET (maxlive, old);
- regs_sometimes_live = (int *) alloca (max_regno * sizeof (int));
-
/* Process the regs live at the end of the block.
- Enter them in MAXLIVE and REGS_SOMETIMES_LIVE.
- Also mark them as not local to any one basic block. */
+ Mark them as not local to any one basic block. */
EXECUTE_IF_SET_IN_REG_SET (old, 0, i,
{
REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
- regs_sometimes_live[sometimes_max] = i;
- sometimes_max++;
});
}
@@ -1625,18 +2685,6 @@ propagate_block (old, first, last, final, significant, bnum)
if (GET_CODE (insn) == NOTE)
{
- /* Look for loop boundaries, remembering that we are going
- backwards. */
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
- loop_depth++;
- else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- loop_depth--;
-
- /* If we have LOOP_DEPTH == 0, there has been a bookkeeping error.
- Abort now rather than setting register status incorrectly. */
- if (loop_depth == 0)
- abort ();
-
/* If this is a call to `setjmp' et al,
warn if any non-volatile datum is live. */
@@ -1655,13 +2703,17 @@ propagate_block (old, first, last, final, significant, bnum)
{
register int i;
rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
- int insn_is_dead
- = (insn_dead_p (PATTERN (insn), old, 0)
- /* Don't delete something that refers to volatile storage! */
- && ! INSN_VOLATILE (insn));
- int libcall_is_dead
- = (insn_is_dead && note != 0
- && libcall_dead_p (PATTERN (insn), old, note, insn));
+ int insn_is_dead = 0;
+ int libcall_is_dead = 0;
+
+ if (remove_dead_code)
+ {
+ insn_is_dead = (insn_dead_p (PATTERN (insn), old, 0, REG_NOTES (insn))
+ /* Don't delete something that refers to volatile storage! */
+ && ! INSN_VOLATILE (insn));
+ libcall_is_dead = (insn_is_dead && note != 0
+ && libcall_dead_p (PATTERN (insn), old, note, insn));
+ }
/* If an instruction consists of just dead store(s) on final pass,
"delete" it by turning it into a NOTE of type NOTE_INSN_DELETED.
@@ -1707,7 +2759,8 @@ propagate_block (old, first, last, final, significant, bnum)
register rtx x = single_set (insn);
/* Does this instruction increment or decrement a register? */
- if (final && x != 0
+ if (!reload_completed
+ && final && x != 0
&& GET_CODE (SET_DEST (x)) == REG
&& (GET_CODE (SET_SRC (x)) == PLUS
|| GET_CODE (SET_SRC (x)) == MINUS)
@@ -1746,6 +2799,16 @@ propagate_block (old, first, last, final, significant, bnum)
;
else
{
+ /* Any regs live at the time of a call instruction
+ must not go in a register clobbered by calls.
+ Find all regs now live and record this for them. */
+
+ if (GET_CODE (insn) == CALL_INSN && final)
+ EXECUTE_IF_SET_IN_REG_SET (old, 0, i,
+ {
+ REG_N_CALLS_CROSSED (i)++;
+ });
+
/* LIVE gets the regs used in INSN;
DEAD gets those set by it. Dead insns don't make anything
live. */
@@ -1803,51 +2866,20 @@ propagate_block (old, first, last, final, significant, bnum)
final, insn);
/* Calls also clobber memory. */
- last_mem_set = 0;
+ mem_set_list = NULL_RTX;
}
/* Update OLD for the registers used or set. */
AND_COMPL_REG_SET (old, dead);
IOR_REG_SET (old, live);
- if (GET_CODE (insn) == CALL_INSN && final)
- {
- /* Any regs live at the time of a call instruction
- must not go in a register clobbered by calls.
- Find all regs now live and record this for them. */
-
- register int *p = regs_sometimes_live;
-
- for (i = 0; i < sometimes_max; i++, p++)
- if (REGNO_REG_SET_P (old, *p))
- REG_N_CALLS_CROSSED (*p)++;
- }
}
- /* On final pass, add any additional sometimes-live regs
- into MAXLIVE and REGS_SOMETIMES_LIVE.
- Also update counts of how many insns each reg is live at. */
-
+ /* On final pass, update counts of how many insns each reg is live
+ at. */
if (final)
- {
- register int regno;
- register int *p;
-
- EXECUTE_IF_AND_COMPL_IN_REG_SET
- (live, maxlive, 0, regno,
- {
- regs_sometimes_live[sometimes_max++] = regno;
- SET_REGNO_REG_SET (maxlive, regno);
- });
-
- p = regs_sometimes_live;
- for (i = 0; i < sometimes_max; i++)
- {
- regno = *p++;
- if (REGNO_REG_SET_P (old, regno))
- REG_LIVE_LENGTH (regno)++;
- }
- }
+ EXECUTE_IF_SET_IN_REG_SET (old, 0, i,
+ { REG_LIVE_LENGTH (i)++; });
}
flushed: ;
if (insn == first)
@@ -1856,27 +2888,46 @@ propagate_block (old, first, last, final, significant, bnum)
FREE_REG_SET (dead);
FREE_REG_SET (live);
- if (final)
- FREE_REG_SET (maxlive);
-
- if (num_scratch > max_scratch)
- max_scratch = num_scratch;
}
/* Return 1 if X (the body of an insn, or part of it) is just dead stores
(SET expressions whose destinations are registers dead after the insn).
NEEDED is the regset that says which regs are alive after the insn.
- Unless CALL_OK is non-zero, an insn is needed if it contains a CALL. */
+ Unless CALL_OK is non-zero, an insn is needed if it contains a CALL.
+
+ If X is the entire body of an insn, NOTES contains the reg notes
+ pertaining to the insn. */
static int
-insn_dead_p (x, needed, call_ok)
+insn_dead_p (x, needed, call_ok, notes)
rtx x;
regset needed;
int call_ok;
+ rtx notes ATTRIBUTE_UNUSED;
{
enum rtx_code code = GET_CODE (x);
+#ifdef AUTO_INC_DEC
+ /* If flow is invoked after reload, we must take existing AUTO_INC
+ expresions into account. */
+ if (reload_completed)
+ {
+ for ( ; notes; notes = XEXP (notes, 1))
+ {
+ if (REG_NOTE_KIND (notes) == REG_INC)
+ {
+ int regno = REGNO (XEXP (notes, 0));
+
+ /* Don't delete insns to set global regs. */
+ if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+ || REGNO_REG_SET_P (needed, regno))
+ return 0;
+ }
+ }
+ }
+#endif
+
/* If setting something that's a reg or part of one,
see if that register's altered value will be live. */
@@ -1893,9 +2944,21 @@ insn_dead_p (x, needed, call_ok)
return ! cc0_live;
#endif
- if (GET_CODE (r) == MEM && last_mem_set && ! MEM_VOLATILE_P (r)
- && rtx_equal_p (r, last_mem_set))
- return 1;
+ if (GET_CODE (r) == MEM && ! MEM_VOLATILE_P (r))
+ {
+ rtx temp;
+ /* Walk the set of memory locations we are currently tracking
+ and see if one is an identical match to this memory location.
+ If so, this memory write is dead (remember, we're walking
+ backwards from the end of the block to the start. */
+ temp = mem_set_list;
+ while (temp)
+ {
+ if (rtx_equal_p (XEXP (temp, 0), r))
+ return 1;
+ temp = XEXP (temp, 1);
+ }
+ }
while (GET_CODE (r) == SUBREG || GET_CODE (r) == STRICT_LOW_PART
|| GET_CODE (r) == ZERO_EXTRACT)
@@ -1908,9 +2971,11 @@ insn_dead_p (x, needed, call_ok)
/* Don't delete insns to set global regs. */
if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
/* Make sure insns to set frame pointer aren't deleted. */
- || regno == FRAME_POINTER_REGNUM
+ || (regno == FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || regno == HARD_FRAME_POINTER_REGNUM
+ || (regno == HARD_FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* Make sure insns to set arg pointer are never deleted
@@ -1947,7 +3012,7 @@ insn_dead_p (x, needed, call_ok)
for (i--; i >= 0; i--)
if (GET_CODE (XVECEXP (x, 0, i)) != CLOBBER
&& GET_CODE (XVECEXP (x, 0, i)) != USE
- && ! insn_dead_p (XVECEXP (x, 0, i), needed, call_ok))
+ && ! insn_dead_p (XVECEXP (x, 0, i), needed, call_ok, NULL_RTX))
return 0;
return 1;
@@ -1994,6 +3059,7 @@ libcall_dead_p (x, needed, note, insn)
if (GET_CODE (r) == REG)
{
rtx call = XEXP (note, 0);
+ rtx call_pat;
register int i;
/* Find the call insn. */
@@ -2007,12 +3073,12 @@ libcall_dead_p (x, needed, note, insn)
/* See if the hard reg holding the value is dead.
If this is a PARALLEL, find the call within it. */
- call = PATTERN (call);
- if (GET_CODE (call) == PARALLEL)
+ call_pat = PATTERN (call);
+ if (GET_CODE (call_pat) == PARALLEL)
{
- for (i = XVECLEN (call, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (call, 0, i)) == SET
- && GET_CODE (SET_SRC (XVECEXP (call, 0, i))) == CALL)
+ for (i = XVECLEN (call_pat, 0) - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (call_pat, 0, i)) == SET
+ && GET_CODE (SET_SRC (XVECEXP (call_pat, 0, i))) == CALL)
break;
/* This may be a library call that is returning a value
@@ -2021,19 +3087,19 @@ libcall_dead_p (x, needed, note, insn)
if (i < 0)
return 0;
- call = XVECEXP (call, 0, i);
+ call_pat = XVECEXP (call_pat, 0, i);
}
- return insn_dead_p (call, needed, 1);
+ return insn_dead_p (call_pat, needed, 1, REG_NOTES (call));
}
}
return 1;
}
-/* Return 1 if register REGNO was used before it was set.
- In other words, if it is live at function entry.
- Don't count global register variables or variables in registers
- that can be used for function arg passing, though. */
+/* Return 1 if register REGNO was used before it was set, i.e. if it is
+ live at function entry. Don't count global register variables, variables
+ in registers that can be used for function arg passing, or variables in
+ fixed hard registers. */
int
regno_uninitialized (regno)
@@ -2041,10 +3107,12 @@ regno_uninitialized (regno)
{
if (n_basic_blocks == 0
|| (regno < FIRST_PSEUDO_REGISTER
- && (global_regs[regno] || FUNCTION_ARG_REGNO_P (regno))))
+ && (global_regs[regno]
+ || fixed_regs[regno]
+ || FUNCTION_ARG_REGNO_P (regno))))
return 0;
- return REGNO_REG_SET_P (basic_block_live_at_start[0], regno);
+ return REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno);
}
/* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -2059,10 +3127,43 @@ regno_clobbered_at_setjmp (regno)
return 0;
return ((REG_N_SETS (regno) > 1
- || REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
+ || REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno))
&& REGNO_REG_SET_P (regs_live_at_setjmp, regno));
}
+/* INSN references memory, possibly using autoincrement addressing modes.
+ Find any entries on the mem_set_list that need to be invalidated due
+ to an address change. */
+static void
+invalidate_mems_from_autoinc (insn)
+ rtx insn;
+{
+ rtx note = REG_NOTES (insn);
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ {
+ if (REG_NOTE_KIND (note) == REG_INC)
+ {
+ rtx temp = mem_set_list;
+ rtx prev = NULL_RTX;
+
+ while (temp)
+ {
+ if (reg_overlap_mentioned_p (XEXP (note, 0), XEXP (temp, 0)))
+ {
+ /* Splice temp out of list. */
+ if (prev)
+ XEXP (prev, 1) = XEXP (temp, 1);
+ else
+ mem_set_list = XEXP (temp, 1);
+ }
+ else
+ prev = temp;
+ temp = XEXP (temp, 1);
+ }
+ }
+ }
+}
+
/* Process the registers that are set within X.
Their bits are set to 1 in the regset DEAD,
because they are dead prior to this insn.
@@ -2109,6 +3210,19 @@ mark_set_1 (needed, dead, x, insn, significant)
register int regno;
register rtx reg = SET_DEST (x);
+ /* Some targets place small structures in registers for
+ return values of functions. We have to detect this
+ case specially here to get correct flow information. */
+ if (GET_CODE (reg) == PARALLEL
+ && GET_MODE (reg) == BLKmode)
+ {
+ register int i;
+
+ for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
+ mark_set_1 (needed, dead, XVECEXP (reg, 0, i), insn, significant);
+ return;
+ }
+
/* Modifying just one hardware register of a multi-reg value
or just a byte field of a register
does not mean the value from before this insn is now dead.
@@ -2126,26 +3240,55 @@ mark_set_1 (needed, dead, x, insn, significant)
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);
- /* If we are writing into memory or into a register mentioned in the
- address of the last thing stored into memory, show we don't know
- what the last store was. If we are writing memory, save the address
- unless it is volatile. */
+ /* If this set is a MEM, then it kills any aliased writes.
+ If this set is a REG, then it kills any MEMs which use the reg. */
if (GET_CODE (reg) == MEM
- || (GET_CODE (reg) == REG
- && last_mem_set != 0 && reg_overlap_mentioned_p (reg, last_mem_set)))
- last_mem_set = 0;
-
+ || GET_CODE (reg) == REG)
+ {
+ rtx temp = mem_set_list;
+ rtx prev = NULL_RTX;
+
+ while (temp)
+ {
+ if ((GET_CODE (reg) == MEM
+ && output_dependence (XEXP (temp, 0), reg))
+ || (GET_CODE (reg) == REG
+ && reg_overlap_mentioned_p (reg, XEXP (temp, 0))))
+ {
+ /* Splice this entry out of the list. */
+ if (prev)
+ XEXP (prev, 1) = XEXP (temp, 1);
+ else
+ mem_set_list = XEXP (temp, 1);
+ }
+ else
+ prev = temp;
+ temp = XEXP (temp, 1);
+ }
+ }
+
+ /* If the memory reference had embedded side effects (autoincrement
+ address modes. Then we may need to kill some entries on the
+ memory set list. */
+ if (insn && GET_CODE (reg) == MEM)
+ invalidate_mems_from_autoinc (insn);
+
if (GET_CODE (reg) == MEM && ! side_effects_p (reg)
+ /* We do not know the size of a BLKmode store, so we do not track
+ them for redundant store elimination. */
+ && GET_MODE (reg) != BLKmode
/* There are no REG_INC notes for SP, so we can't assume we'll see
everything that invalidates it. To be safe, don't eliminate any
stores though SP; none of them should be redundant anyway. */
&& ! reg_mentioned_p (stack_pointer_rtx, reg))
- last_mem_set = reg;
+ mem_set_list = gen_rtx_EXPR_LIST (VOIDmode, reg, mem_set_list);
if (GET_CODE (reg) == REG
- && (regno = REGNO (reg), regno != FRAME_POINTER_REGNUM)
+ && (regno = REGNO (reg), ! (regno == FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed)))
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- && regno != HARD_FRAME_POINTER_REGNUM
+ && ! (regno == HARD_FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
@@ -2293,7 +3436,6 @@ mark_set_1 (needed, dead, x, insn, significant)
{
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (insn));
- num_scratch++;
}
}
@@ -2337,20 +3479,14 @@ find_auto_inc (needed, x, insn)
&& (y = SET_SRC (set), GET_CODE (y) == PLUS)
&& XEXP (y, 0) == addr
&& GET_CODE (XEXP (y, 1)) == CONST_INT
- && (0
-#ifdef HAVE_POST_INCREMENT
- || (INTVAL (XEXP (y, 1)) == size && offset == 0)
-#endif
-#ifdef HAVE_POST_DECREMENT
- || (INTVAL (XEXP (y, 1)) == - size && offset == 0)
-#endif
-#ifdef HAVE_PRE_INCREMENT
- || (INTVAL (XEXP (y, 1)) == size && offset == size)
-#endif
-#ifdef HAVE_PRE_DECREMENT
- || (INTVAL (XEXP (y, 1)) == - size && offset == - size)
-#endif
- )
+ && ((HAVE_POST_INCREMENT
+ && (INTVAL (XEXP (y, 1)) == size && offset == 0))
+ || (HAVE_POST_DECREMENT
+ && (INTVAL (XEXP (y, 1)) == - size && offset == 0))
+ || (HAVE_PRE_INCREMENT
+ && (INTVAL (XEXP (y, 1)) == size && offset == size))
+ || (HAVE_PRE_DECREMENT
+ && (INTVAL (XEXP (y, 1)) == - size && offset == - size)))
/* Make sure this reg appears only once in this insn. */
&& (use = find_use_as_address (PATTERN (insn), addr, offset),
use != 0 && use != (rtx) 1))
@@ -2385,21 +3521,16 @@ find_auto_inc (needed, x, insn)
Change it to q = p, ...*q..., q = q+size.
Then fall into the usual case. */
rtx insns, temp;
+ basic_block bb;
start_sequence ();
emit_move_insn (q, addr);
insns = get_insns ();
end_sequence ();
- /* If anything in INSNS have UID's that don't fit within the
- extra space we allocate earlier, we can't make this auto-inc.
- This should never happen. */
+ bb = BLOCK_FOR_INSN (insn);
for (temp = insns; temp; temp = NEXT_INSN (temp))
- {
- if (INSN_UID (temp) > max_uid_for_flow)
- return;
- BLOCK_NUM (temp) = BLOCK_NUM (insn);
- }
+ set_block_for_insn (temp, bb);
/* If we can't make the auto-inc, or can't make the
replacement into Y, exit. There's no point in making
@@ -2417,8 +3548,8 @@ find_auto_inc (needed, x, insn)
new insn(s) and do the updates. */
emit_insns_before (insns, insn);
- if (basic_block_head[BLOCK_NUM (insn)] == insn)
- basic_block_head[BLOCK_NUM (insn)] = insns;
+ if (BLOCK_FOR_INSN (insn)->head == insn)
+ BLOCK_FOR_INSN (insn)->head = insns;
/* INCR will become a NOTE and INSN won't contain a
use of ADDR. If a use of ADDR was just placed in
@@ -2521,7 +3652,6 @@ mark_used_regs (needed, live, x, final, insn)
case PC:
case ADDR_VEC:
case ADDR_DIFF_VEC:
- case ASM_INPUT:
return;
#ifdef HAVE_cc0
@@ -2542,9 +3672,33 @@ mark_used_regs (needed, live, x, final, insn)
something that can be stored into. */
if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
- ; /* needn't clear last_mem_set */
+ ; /* needn't clear the memory set list */
else
- last_mem_set = 0;
+ {
+ rtx temp = mem_set_list;
+ rtx prev = NULL_RTX;
+
+ while (temp)
+ {
+ if (anti_dependence (XEXP (temp, 0), x))
+ {
+ /* Splice temp out of the list. */
+ if (prev)
+ XEXP (prev, 1) = XEXP (temp, 1);
+ else
+ mem_set_list = XEXP (temp, 1);
+ }
+ else
+ prev = temp;
+ temp = XEXP (temp, 1);
+ }
+ }
+
+ /* If the memory reference had embedded side effects (autoincrement
+ address modes. Then we may need to kill some entries on the
+ memory set list. */
+ if (insn)
+ invalidate_mems_from_autoinc (insn);
#ifdef AUTO_INC_DEC
if (final)
@@ -2592,12 +3746,14 @@ mark_used_regs (needed, live, x, final, insn)
nothing below can be necessary, so waste no more time. */
if (regno == STACK_POINTER_REGNUM
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || regno == HARD_FRAME_POINTER_REGNUM
+ || (regno == HARD_FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
- || regno == FRAME_POINTER_REGNUM)
+ || (regno == FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed)))
{
/* If this is a register we are going to try to eliminate,
don't mark it live here. If we are successful in
@@ -2770,15 +3926,19 @@ mark_used_regs (needed, live, x, final, insn)
/* If this is a store into a register,
recursively scan the value being stored. */
- if (GET_CODE (testreg) == REG
- && (regno = REGNO (testreg), regno != FRAME_POINTER_REGNUM)
+ if ((GET_CODE (testreg) == PARALLEL
+ && GET_MODE (testreg) == BLKmode)
+ || (GET_CODE (testreg) == REG
+ && (regno = REGNO (testreg), ! (regno == FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed)))
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- && regno != HARD_FRAME_POINTER_REGNUM
+ && ! (regno == HARD_FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
+ && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
- )
+ ))
/* We used to exclude global_regs here, but that seems wrong.
Storing in them is like storing in mem. */
{
@@ -2794,13 +3954,11 @@ mark_used_regs (needed, live, x, final, insn)
/* If exiting needs the right stack value, consider this insn as
using the stack pointer. In any event, consider it as using
all global registers and all registers used by return. */
-
-#ifdef EXIT_IGNORE_STACK
if (! EXIT_IGNORE_STACK
|| (! FRAME_POINTER_REQUIRED
&& ! current_function_calls_alloca
- && flag_omit_frame_pointer))
-#endif
+ && flag_omit_frame_pointer)
+ || current_function_sp_is_unchanging)
SET_REGNO_REG_SET (live, STACK_POINTER_REGNUM);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -2812,6 +3970,44 @@ mark_used_regs (needed, live, x, final, insn)
SET_REGNO_REG_SET (live, i);
break;
+ case ASM_OPERANDS:
+ case UNSPEC_VOLATILE:
+ case TRAP_IF:
+ case ASM_INPUT:
+ {
+ /* Traditional and volatile asm instructions must be considered to use
+ and clobber all hard registers, all pseudo-registers and all of
+ memory. So must TRAP_IF and UNSPEC_VOLATILE operations.
+
+ Consider for instance a volatile asm that changes the fpu rounding
+ mode. An insn should not be moved across this even if it only uses
+ pseudo-regs because it might give an incorrectly rounded result.
+
+ ?!? Unfortunately, marking all hard registers as live causes massive
+ problems for the register allocator and marking all pseudos as live
+ creates mountains of uninitialized variable warnings.
+
+ So for now, just clear the memory set list and mark any regs
+ we can find in ASM_OPERANDS as used. */
+ if (code != ASM_OPERANDS || MEM_VOLATILE_P (x))
+ mem_set_list = NULL_RTX;
+
+ /* For all ASM_OPERANDS, we must traverse the vector of input operands.
+ We can not just fall through here since then we would be confused
+ by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
+ traditional asms unlike their normal usage. */
+ if (code == ASM_OPERANDS)
+ {
+ int j;
+
+ for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
+ mark_used_regs (needed, live, ASM_OPERANDS_INPUT (x, j),
+ final, insn);
+ }
+ break;
+ }
+
+
default:
break;
}
@@ -2911,23 +4107,15 @@ try_pre_increment (insn, reg, amount)
/* From the sign of increment, see which possibilities are conceivable
on this target machine. */
-#ifdef HAVE_PRE_INCREMENT
- if (amount > 0)
+ if (HAVE_PRE_INCREMENT && amount > 0)
pre_ok = 1;
-#endif
-#ifdef HAVE_POST_INCREMENT
- if (amount > 0)
+ if (HAVE_POST_INCREMENT && amount > 0)
post_ok = 1;
-#endif
-#ifdef HAVE_PRE_DECREMENT
- if (amount < 0)
+ if (HAVE_PRE_DECREMENT && amount < 0)
pre_ok = 1;
-#endif
-#ifdef HAVE_POST_DECREMENT
- if (amount < 0)
+ if (HAVE_POST_DECREMENT && amount < 0)
post_ok = 1;
-#endif
if (! (pre_ok || post_ok))
return 0;
@@ -3048,7 +4236,6 @@ dump_flow_info (file)
static char *reg_class_names[] = REG_CLASS_NAMES;
fprintf (file, "%d registers.\n", max_regno);
-
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (REG_N_REFS (i))
{
@@ -3087,40 +4274,91 @@ dump_flow_info (file)
fprintf (file, "; pointer");
fprintf (file, ".\n");
}
+
fprintf (file, "\n%d basic blocks.\n", n_basic_blocks);
for (i = 0; i < n_basic_blocks; i++)
{
- register rtx head, jump;
+ register basic_block bb = BASIC_BLOCK (i);
register int regno;
+ register edge e;
+
fprintf (file, "\nBasic block %d: first insn %d, last %d.\n",
- i,
- INSN_UID (basic_block_head[i]),
- INSN_UID (basic_block_end[i]));
- /* The control flow graph's storage is freed
- now when flow_analysis returns.
- Don't try to print it if it is gone. */
- if (basic_block_drops_in)
+ i, INSN_UID (bb->head), INSN_UID (bb->end));
+
+ fprintf (file, "Predecessors: ");
+ for (e = bb->pred; e ; e = e->pred_next)
+ dump_edge_info (file, e, 0);
+
+ fprintf (file, "\nSuccessors: ");
+ for (e = bb->succ; e ; e = e->succ_next)
+ dump_edge_info (file, e, 1);
+
+ fprintf (file, "\nRegisters live at start:");
+ if (bb->global_live_at_start)
{
- fprintf (file, "Reached from blocks: ");
- head = basic_block_head[i];
- if (GET_CODE (head) == CODE_LABEL)
- for (jump = LABEL_REFS (head);
- jump != head;
- jump = LABEL_NEXTREF (jump))
- {
- register int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
- fprintf (file, " %d", from_block);
- }
- if (basic_block_drops_in[i])
- fprintf (file, " previous");
+ for (regno = 0; regno < max_regno; regno++)
+ if (REGNO_REG_SET_P (bb->global_live_at_start, regno))
+ fprintf (file, " %d", regno);
}
- fprintf (file, "\nRegisters live at start:");
- for (regno = 0; regno < max_regno; regno++)
- if (REGNO_REG_SET_P (basic_block_live_at_start[i], regno))
- fprintf (file, " %d", regno);
- fprintf (file, "\n");
+ else
+ fprintf (file, " n/a");
+
+ fprintf (file, "\nRegisters live at end:");
+ if (bb->global_live_at_end)
+ {
+ for (regno = 0; regno < max_regno; regno++)
+ if (REGNO_REG_SET_P (bb->global_live_at_end, regno))
+ fprintf (file, " %d", regno);
+ }
+ else
+ fprintf (file, " n/a");
+
+ putc('\n', file);
+ }
+
+ putc('\n', file);
+}
+
+static void
+dump_edge_info (file, e, do_succ)
+ FILE *file;
+ edge e;
+ int do_succ;
+{
+ basic_block side = (do_succ ? e->dest : e->src);
+
+ if (side == ENTRY_BLOCK_PTR)
+ fputs (" ENTRY", file);
+ else if (side == EXIT_BLOCK_PTR)
+ fputs (" EXIT", file);
+ else
+ fprintf (file, " %d", side->index);
+
+ if (e->flags)
+ {
+ static char * bitnames[] = {
+ "fallthru", "crit", "ab", "abcall", "eh", "fake"
+ };
+ int comma = 0;
+ int i, flags = e->flags;
+
+ fputc (' ', file);
+ fputc ('(', file);
+ for (i = 0; flags; i++)
+ if (flags & (1 << i))
+ {
+ flags &= ~(1 << i);
+
+ if (comma)
+ fputc (',', file);
+ if (i < (int)(sizeof (bitnames) / sizeof (*bitnames)))
+ fputs (bitnames[i], file);
+ else
+ fprintf (file, "%d", i);
+ comma = 1;
+ }
+ fputc (')', file);
}
- fprintf (file, "\n");
}
@@ -3132,50 +4370,56 @@ print_rtl_with_bb (outf, rtx_first)
FILE *outf;
rtx rtx_first;
{
- extern int flag_dump_unnumbered;
register rtx tmp_rtx;
if (rtx_first == 0)
fprintf (outf, "(nil)\n");
-
else
{
- int i, bb;
+ int i;
enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
int max_uid = get_max_uid ();
- int *start = (int *) alloca (max_uid * sizeof (int));
- int *end = (int *) alloca (max_uid * sizeof (int));
- char *in_bb_p = (char *) alloca (max_uid * sizeof (enum bb_state));
+ basic_block *start = (basic_block *)
+ alloca (max_uid * sizeof (basic_block));
+ basic_block *end = (basic_block *)
+ alloca (max_uid * sizeof (basic_block));
+ enum bb_state *in_bb_p = (enum bb_state *)
+ alloca (max_uid * sizeof (enum bb_state));
- for (i = 0; i < max_uid; i++)
- {
- start[i] = end[i] = -1;
- in_bb_p[i] = NOT_IN_BB;
- }
+ memset (start, 0, max_uid * sizeof (basic_block));
+ memset (end, 0, max_uid * sizeof (basic_block));
+ memset (in_bb_p, 0, max_uid * sizeof (enum bb_state));
- for (i = n_basic_blocks-1; i >= 0; i--)
+ for (i = n_basic_blocks - 1; i >= 0; i--)
{
+ basic_block bb = BASIC_BLOCK (i);
rtx x;
- start[INSN_UID (basic_block_head[i])] = i;
- end[INSN_UID (basic_block_end[i])] = i;
- for (x = basic_block_head[i]; x != NULL_RTX; x = NEXT_INSN (x))
+
+ start[INSN_UID (bb->head)] = bb;
+ end[INSN_UID (bb->end)] = bb;
+ for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
{
- in_bb_p[ INSN_UID(x)]
- = (in_bb_p[ INSN_UID(x)] == NOT_IN_BB)
- ? IN_ONE_BB : IN_MULTIPLE_BB;
- if (x == basic_block_end[i])
+ enum bb_state state = IN_MULTIPLE_BB;
+ if (in_bb_p[INSN_UID(x)] == NOT_IN_BB)
+ state = IN_ONE_BB;
+ in_bb_p[INSN_UID(x)] = state;
+
+ if (x == bb->end)
break;
}
}
for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
{
- if ((bb = start[INSN_UID (tmp_rtx)]) >= 0)
+ int did_output;
+ basic_block bb;
+
+ if ((bb = start[INSN_UID (tmp_rtx)]) != NULL)
{
fprintf (outf, ";; Start of basic block %d, registers live:",
- bb);
+ bb->index);
- EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[bb], 0, i,
+ EXECUTE_IF_SET_IN_REG_SET (bb->global_live_at_start, 0, i,
{
fprintf (outf, " %d", i);
if (i < FIRST_PSEUDO_REGISTER)
@@ -3185,20 +4429,20 @@ print_rtl_with_bb (outf, rtx_first)
putc ('\n', outf);
}
- if (in_bb_p[ INSN_UID(tmp_rtx)] == NOT_IN_BB
+ if (in_bb_p[INSN_UID(tmp_rtx)] == NOT_IN_BB
&& GET_CODE (tmp_rtx) != NOTE
- && GET_CODE (tmp_rtx) != BARRIER)
+ && GET_CODE (tmp_rtx) != BARRIER
+ && ! obey_regdecls)
fprintf (outf, ";; Insn is not within a basic block\n");
- else if (in_bb_p[ INSN_UID(tmp_rtx)] == IN_MULTIPLE_BB)
+ else if (in_bb_p[INSN_UID(tmp_rtx)] == IN_MULTIPLE_BB)
fprintf (outf, ";; Insn is in multiple basic blocks\n");
- print_rtl_single (outf, tmp_rtx);
+ did_output = print_rtl_single (outf, tmp_rtx);
- if ((bb = end[INSN_UID (tmp_rtx)]) >= 0)
- fprintf (outf, ";; End of basic block %d\n", bb);
+ if ((bb = end[INSN_UID (tmp_rtx)]) != NULL)
+ fprintf (outf, ";; End of basic block %d\n", bb->index);
- if (! flag_dump_unnumbered
- || GET_CODE (tmp_rtx) != NOTE || NOTE_LINE_NUMBER (tmp_rtx) < 0)
+ if (did_output)
putc ('\n', outf);
}
}
@@ -3294,7 +4538,8 @@ add_pred_succ (pred_bb, succ_bb, s_preds, s_succs, num_preds, num_succs)
}
}
-/* Compute the predecessors and successors for each block. */
+/* Convert edge lists into pred/succ lists for backward compatibility. */
+
void
compute_preds_succs (s_preds, s_succs, num_preds, num_succs)
int_list_ptr *s_preds;
@@ -3302,117 +4547,34 @@ compute_preds_succs (s_preds, s_succs, num_preds, num_succs)
int *num_preds;
int *num_succs;
{
- int bb, clear_local_bb_vars = 0;
+ int i, n = n_basic_blocks;
+ edge e;
- bzero ((char *) s_preds, n_basic_blocks * sizeof (int_list_ptr));
- bzero ((char *) s_succs, n_basic_blocks * sizeof (int_list_ptr));
- bzero ((char *) num_preds, n_basic_blocks * sizeof (int));
- bzero ((char *) num_succs, n_basic_blocks * sizeof (int));
+ memset (s_preds, 0, n_basic_blocks * sizeof (int_list_ptr));
+ memset (s_succs, 0, n_basic_blocks * sizeof (int_list_ptr));
+ memset (num_preds, 0, n_basic_blocks * sizeof (int));
+ memset (num_succs, 0, n_basic_blocks * sizeof (int));
- /* This routine can be called after life analysis; in that case
- basic_block_drops_in and uid_block_number will not be available
- and we must recompute their values. */
- if (basic_block_drops_in == NULL || uid_block_number == NULL)
+ for (i = 0; i < n; ++i)
{
- clear_local_bb_vars = 1;
- basic_block_drops_in = (char *) alloca (n_basic_blocks);
- uid_block_number = (int *) alloca ((get_max_uid () + 1) * sizeof (int));
-
- bzero ((char *) basic_block_drops_in, n_basic_blocks * sizeof (char));
- bzero ((char *) uid_block_number, n_basic_blocks * sizeof (int));
-
- /* Scan each basic block setting basic_block_drops_in and
- uid_block_number as needed. */
- for (bb = 0; bb < n_basic_blocks; bb++)
- {
- rtx insn, stop_insn;
-
- if (bb == 0)
- stop_insn = NULL_RTX;
- else
- stop_insn = basic_block_end[bb-1];
-
- /* Look backwards from the start of this block. Stop if we
- hit the start of the function or the end of a previous
- block. Don't walk backwards through blocks that are just
- deleted insns! */
- for (insn = PREV_INSN (basic_block_head[bb]);
- insn && insn != stop_insn && GET_CODE (insn) == NOTE;
- insn = PREV_INSN (insn))
- ;
-
- /* Never set basic_block_drops_in for the first block. It is
- implicit.
-
- If we stopped on anything other than a BARRIER, then this
- block drops in. */
- if (bb != 0)
- basic_block_drops_in[bb] = (insn ? GET_CODE (insn) != BARRIER : 1);
-
- insn = basic_block_head[bb];
- while (insn)
- {
- BLOCK_NUM (insn) = bb;
- if (insn == basic_block_end[bb])
- break;
- insn = NEXT_INSN (insn);
- }
- }
- }
+ basic_block bb = BASIC_BLOCK (i);
- for (bb = 0; bb < n_basic_blocks; bb++)
- {
- rtx head;
- rtx jump;
-
- head = BLOCK_HEAD (bb);
-
- if (GET_CODE (head) == CODE_LABEL)
- for (jump = LABEL_REFS (head);
- jump != head;
- jump = LABEL_NEXTREF (jump))
- {
- if (! INSN_DELETED_P (CONTAINING_INSN (jump))
- && (GET_CODE (CONTAINING_INSN (jump)) != NOTE
- || (NOTE_LINE_NUMBER (CONTAINING_INSN (jump))
- != NOTE_INSN_DELETED)))
- add_pred_succ (BLOCK_NUM (CONTAINING_INSN (jump)), bb,
- s_preds, s_succs, num_preds, num_succs);
- }
-
- jump = BLOCK_END (bb);
- /* If this is a RETURN insn or a conditional jump in the last
- basic block, or a non-jump insn in the last basic block, then
- this block reaches the exit block. */
- if ((GET_CODE (jump) == JUMP_INSN && GET_CODE (PATTERN (jump)) == RETURN)
- || (((GET_CODE (jump) == JUMP_INSN
- && condjump_p (jump) && !simplejump_p (jump))
- || GET_CODE (jump) != JUMP_INSN)
- && (bb == n_basic_blocks - 1)))
- add_pred_succ (bb, EXIT_BLOCK, s_preds, s_succs, num_preds, num_succs);
-
- if (basic_block_drops_in[bb])
- add_pred_succ (bb - 1, bb, s_preds, s_succs, num_preds, num_succs);
+ for (e = bb->succ; e ; e = e->succ_next)
+ add_pred_succ (i, e->dest->index, s_preds, s_succs,
+ num_preds, num_succs);
}
- add_pred_succ (ENTRY_BLOCK, 0, s_preds, s_succs, num_preds, num_succs);
-
-
- /* If we allocated any variables in temporary storage, clear out the
- pointer to the local storage to avoid dangling pointers. */
- if (clear_local_bb_vars)
- {
- basic_block_drops_in = NULL;
- uid_block_number = NULL;
-
- }
+ for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
+ add_pred_succ (ENTRY_BLOCK, e->dest->index, s_preds, s_succs,
+ num_preds, num_succs);
}
void
-dump_bb_data (file, preds, succs)
+dump_bb_data (file, preds, succs, live_info)
FILE *file;
int_list_ptr *preds;
int_list_ptr *succs;
+ int live_info;
{
int bb;
int_list_ptr p;
@@ -3441,47 +4603,16 @@ dump_bb_data (file, preds, succs)
else
fprintf (file, " %d", succ_bb);
}
- fprintf (file, "\n");
- }
- fprintf (file, "\n");
-}
-
-void
-dump_sbitmap (file, bmap)
- FILE *file;
- sbitmap bmap;
-{
- int i,j,n;
- int set_size = bmap->size;
- int total_bits = bmap->n_bits;
-
- fprintf (file, " ");
- for (i = n = 0; i < set_size && n < total_bits; i++)
- {
- for (j = 0; j < SBITMAP_ELT_BITS && n < total_bits; j++, n++)
+ if (live_info)
{
- if (n != 0 && n % 10 == 0)
- fprintf (file, " ");
- fprintf (file, "%d", (bmap->elms[i] & (1L << j)) != 0);
+ int regno;
+ fprintf (file, "\nRegisters live at start:");
+ for (regno = 0; regno < max_regno; regno++)
+ if (REGNO_REG_SET_P (BASIC_BLOCK (bb)->global_live_at_start, regno))
+ fprintf (file, " %d", regno);
+ fprintf (file, "\n");
}
- }
- fprintf (file, "\n");
-}
-
-void
-dump_sbitmap_vector (file, title, subtitle, bmaps, n_maps)
- FILE *file;
- char *title, *subtitle;
- sbitmap *bmaps;
- int n_maps;
-{
- int bb;
-
- fprintf (file, "%s\n", title);
- for (bb = 0; bb < n_maps; bb++)
- {
- fprintf (file, "%s %d\n", subtitle, bb);
- dump_sbitmap (file, bmaps[bb]);
+ fprintf (file, "\n");
}
fprintf (file, "\n");
}
@@ -3493,468 +4624,6 @@ free_bb_mem ()
{
free_int_list (&pred_int_list_blocks);
}
-
-/* Bitmap manipulation routines. */
-
-/* Allocate a simple bitmap of N_ELMS bits. */
-
-sbitmap
-sbitmap_alloc (n_elms)
- int n_elms;
-{
- int bytes, size, amt;
- sbitmap bmap;
-
- size = SBITMAP_SET_SIZE (n_elms);
- bytes = size * sizeof (SBITMAP_ELT_TYPE);
- amt = (sizeof (struct simple_bitmap_def)
- + bytes - sizeof (SBITMAP_ELT_TYPE));
- bmap = (sbitmap) xmalloc (amt);
- bmap->n_bits = n_elms;
- bmap->size = size;
- bmap->bytes = bytes;
- return bmap;
-}
-
-/* Allocate a vector of N_VECS bitmaps of N_ELMS bits. */
-
-sbitmap *
-sbitmap_vector_alloc (n_vecs, n_elms)
- int n_vecs, n_elms;
-{
- int i, bytes, offset, elm_bytes, size, amt, vector_bytes;
- sbitmap *bitmap_vector;
-
- size = SBITMAP_SET_SIZE (n_elms);
- bytes = size * sizeof (SBITMAP_ELT_TYPE);
- elm_bytes = (sizeof (struct simple_bitmap_def)
- + bytes - sizeof (SBITMAP_ELT_TYPE));
- vector_bytes = n_vecs * sizeof (sbitmap *);
-
- /* Round up `vector_bytes' to account for the alignment requirements
- of an sbitmap. One could allocate the vector-table and set of sbitmaps
- separately, but that requires maintaining two pointers or creating
- a cover struct to hold both pointers (so our result is still just
- one pointer). Neither is a bad idea, but this is simpler for now. */
- {
- /* Based on DEFAULT_ALIGNMENT computation in obstack.c. */
- struct { char x; SBITMAP_ELT_TYPE y; } align;
- int alignment = (char *) & align.y - & align.x;
- vector_bytes = (vector_bytes + alignment - 1) & ~ (alignment - 1);
- }
-
- amt = vector_bytes + (n_vecs * elm_bytes);
- bitmap_vector = (sbitmap *) xmalloc (amt);
-
- for (i = 0, offset = vector_bytes;
- i < n_vecs;
- i++, offset += elm_bytes)
- {
- sbitmap b = (sbitmap) ((char *) bitmap_vector + offset);
- bitmap_vector[i] = b;
- b->n_bits = n_elms;
- b->size = size;
- b->bytes = bytes;
- }
-
- return bitmap_vector;
-}
-
-/* Copy sbitmap SRC to DST. */
-
-void
-sbitmap_copy (dst, src)
- sbitmap dst, src;
-{
- int i;
- sbitmap_ptr d,s;
-
- s = src->elms;
- d = dst->elms;
- for (i = 0; i < dst->size; i++)
- *d++ = *s++;
-}
-
-/* Zero all elements in a bitmap. */
-
-void
-sbitmap_zero (bmap)
- sbitmap bmap;
-{
- bzero ((char *) bmap->elms, bmap->bytes);
-}
-
-/* Set to ones all elements in a bitmap. */
-
-void
-sbitmap_ones (bmap)
- sbitmap bmap;
-{
- memset (bmap->elms, -1, bmap->bytes);
-}
-
-/* Zero a vector of N_VECS bitmaps. */
-
-void
-sbitmap_vector_zero (bmap, n_vecs)
- sbitmap *bmap;
- int n_vecs;
-{
- int i;
-
- for (i = 0; i < n_vecs; i++)
- sbitmap_zero (bmap[i]);
-}
-
-/* Set to ones a vector of N_VECS bitmaps. */
-
-void
-sbitmap_vector_ones (bmap, n_vecs)
- sbitmap *bmap;
- int n_vecs;
-{
- int i;
-
- for (i = 0; i < n_vecs; i++)
- sbitmap_ones (bmap[i]);
-}
-
-/* Set DST to be A union (B - C).
- DST = A | (B & ~C).
- Return non-zero if any change is made. */
-
-int
-sbitmap_union_of_diff (dst, a, b, c)
- sbitmap dst, a, b, c;
-{
- int i,changed;
- sbitmap_ptr dstp, ap, bp, cp;
-
- changed = 0;
- dstp = dst->elms;
- ap = a->elms;
- bp = b->elms;
- cp = c->elms;
- for (i = 0; i < dst->size; i++)
- {
- SBITMAP_ELT_TYPE tmp = *ap | (*bp & ~*cp);
- if (*dstp != tmp)
- changed = 1;
- *dstp = tmp;
- dstp++; ap++; bp++; cp++;
- }
- return changed;
-}
-
-/* Set bitmap DST to the bitwise negation of the bitmap SRC. */
-
-void
-sbitmap_not (dst, src)
- sbitmap dst, src;
-{
- int i;
- sbitmap_ptr dstp, ap;
-
- dstp = dst->elms;
- ap = src->elms;
- for (i = 0; i < dst->size; i++)
- {
- SBITMAP_ELT_TYPE tmp = ~(*ap);
- *dstp = tmp;
- dstp++; ap++;
- }
-}
-
-/* Set the bits in DST to be the difference between the bits
- in A and the bits in B. i.e. dst = a - b.
- The - operator is implemented as a & (~b). */
-
-void
-sbitmap_difference (dst, a, b)
- sbitmap dst, a, b;
-{
- int i;
- sbitmap_ptr dstp, ap, bp;
-
- dstp = dst->elms;
- ap = a->elms;
- bp = b->elms;
- for (i = 0; i < dst->size; i++)
- *dstp++ = *ap++ & (~*bp++);
-}
-
-/* Set DST to be (A and B)).
- Return non-zero if any change is made. */
-
-int
-sbitmap_a_and_b (dst, a, b)
- sbitmap dst, a, b;
-{
- int i,changed;
- sbitmap_ptr dstp, ap, bp;
-
- changed = 0;
- dstp = dst->elms;
- ap = a->elms;
- bp = b->elms;
- for (i = 0; i < dst->size; i++)
- {
- SBITMAP_ELT_TYPE tmp = *ap & *bp;
- if (*dstp != tmp)
- changed = 1;
- *dstp = tmp;
- dstp++; ap++; bp++;
- }
- return changed;
-}
-/* Set DST to be (A or B)).
- Return non-zero if any change is made. */
-
-int
-sbitmap_a_or_b (dst, a, b)
- sbitmap dst, a, b;
-{
- int i,changed;
- sbitmap_ptr dstp, ap, bp;
-
- changed = 0;
- dstp = dst->elms;
- ap = a->elms;
- bp = b->elms;
- for (i = 0; i < dst->size; i++)
- {
- SBITMAP_ELT_TYPE tmp = *ap | *bp;
- if (*dstp != tmp)
- changed = 1;
- *dstp = tmp;
- dstp++; ap++; bp++;
- }
- return changed;
-}
-
-/* Set DST to be (A or (B and C)).
- Return non-zero if any change is made. */
-
-int
-sbitmap_a_or_b_and_c (dst, a, b, c)
- sbitmap dst, a, b, c;
-{
- int i,changed;
- sbitmap_ptr dstp, ap, bp, cp;
-
- changed = 0;
- dstp = dst->elms;
- ap = a->elms;
- bp = b->elms;
- cp = c->elms;
- for (i = 0; i < dst->size; i++)
- {
- SBITMAP_ELT_TYPE tmp = *ap | (*bp & *cp);
- if (*dstp != tmp)
- changed = 1;
- *dstp = tmp;
- dstp++; ap++; bp++; cp++;
- }
- return changed;
-}
-
-/* Set DST to be (A ann (B or C)).
- Return non-zero if any change is made. */
-
-int
-sbitmap_a_and_b_or_c (dst, a, b, c)
- sbitmap dst, a, b, c;
-{
- int i,changed;
- sbitmap_ptr dstp, ap, bp, cp;
-
- changed = 0;
- dstp = dst->elms;
- ap = a->elms;
- bp = b->elms;
- cp = c->elms;
- for (i = 0; i < dst->size; i++)
- {
- SBITMAP_ELT_TYPE tmp = *ap & (*bp | *cp);
- if (*dstp != tmp)
- changed = 1;
- *dstp = tmp;
- dstp++; ap++; bp++; cp++;
- }
- return changed;
-}
-
-/* Set the bitmap DST to the intersection of SRC of all predecessors or
- successors of block number BB (PRED_SUCC says which). */
-
-void
-sbitmap_intersect_of_predsucc (dst, src, bb, pred_succ)
- sbitmap dst;
- sbitmap *src;
- int bb;
- int_list_ptr *pred_succ;
-{
- int_list_ptr ps;
- int ps_bb;
- int set_size = dst->size;
-
- ps = pred_succ[bb];
-
- /* It is possible that there are no predecessors(/successors).
- This can happen for example in unreachable code. */
-
- if (ps == NULL)
- {
- /* In APL-speak this is the `and' reduction of the empty set and thus
- the result is the identity for `and'. */
- sbitmap_ones (dst);
- return;
- }
-
- /* Set result to first predecessor/successor. */
-
- for ( ; ps != NULL; ps = ps->next)
- {
- ps_bb = INT_LIST_VAL (ps);
- if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
- continue;
- sbitmap_copy (dst, src[ps_bb]);
- /* Break out since we're only doing first predecessor. */
- break;
- }
- if (ps == NULL)
- return;
-
- /* Now do the remaining predecessors/successors. */
-
- for (ps = ps->next; ps != NULL; ps = ps->next)
- {
- int i;
- sbitmap_ptr p,r;
-
- ps_bb = INT_LIST_VAL (ps);
- if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
- continue;
-
- p = src[ps_bb]->elms;
- r = dst->elms;
-
- for (i = 0; i < set_size; i++)
- *r++ &= *p++;
- }
-}
-
-/* Set the bitmap DST to the intersection of SRC of all predecessors
- of block number BB. */
-
-void
-sbitmap_intersect_of_predecessors (dst, src, bb, s_preds)
- sbitmap dst;
- sbitmap *src;
- int bb;
- int_list_ptr *s_preds;
-{
- sbitmap_intersect_of_predsucc (dst, src, bb, s_preds);
-}
-
-/* Set the bitmap DST to the intersection of SRC of all successors
- of block number BB. */
-
-void
-sbitmap_intersect_of_successors (dst, src, bb, s_succs)
- sbitmap dst;
- sbitmap *src;
- int bb;
- int_list_ptr *s_succs;
-{
- sbitmap_intersect_of_predsucc (dst, src, bb, s_succs);
-}
-
-/* Set the bitmap DST to the union of SRC of all predecessors/successors of
- block number BB. */
-
-void
-sbitmap_union_of_predsucc (dst, src, bb, pred_succ)
- sbitmap dst;
- sbitmap *src;
- int bb;
- int_list_ptr *pred_succ;
-{
- int_list_ptr ps;
- int ps_bb;
- int set_size = dst->size;
-
- ps = pred_succ[bb];
-
- /* It is possible that there are no predecessors(/successors).
- This can happen for example in unreachable code. */
-
- if (ps == NULL)
- {
- /* In APL-speak this is the `or' reduction of the empty set and thus
- the result is the identity for `or'. */
- sbitmap_zero (dst);
- return;
- }
-
- /* Set result to first predecessor/successor. */
-
- for ( ; ps != NULL; ps = ps->next)
- {
- ps_bb = INT_LIST_VAL (ps);
- if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
- continue;
- sbitmap_copy (dst, src[ps_bb]);
- /* Break out since we're only doing first predecessor. */
- break;
- }
- if (ps == NULL)
- return;
-
- /* Now do the remaining predecessors/successors. */
-
- for (ps = ps->next; ps != NULL; ps = ps->next)
- {
- int i;
- sbitmap_ptr p,r;
-
- ps_bb = INT_LIST_VAL (ps);
- if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
- continue;
-
- p = src[ps_bb]->elms;
- r = dst->elms;
-
- for (i = 0; i < set_size; i++)
- *r++ |= *p++;
- }
-}
-
-/* Set the bitmap DST to the union of SRC of all predecessors of
- block number BB. */
-
-void
-sbitmap_union_of_predecessors (dst, src, bb, s_preds)
- sbitmap dst;
- sbitmap *src;
- int bb;
- int_list_ptr *s_preds;
-{
- sbitmap_union_of_predsucc (dst, src, bb, s_preds);
-}
-
-/* Set the bitmap DST to the union of SRC of all predecessors of
- block number BB. */
-
-void
-sbitmap_union_of_successors (dst, src, bb, s_succ)
- sbitmap dst;
- sbitmap *src;
- int bb;
- int_list_ptr *s_succ;
-{
- sbitmap_union_of_predsucc (dst, src, bb, s_succ);
-}
/* Compute dominator relationships. */
void
@@ -3975,8 +4644,8 @@ compute_dominators (dominators, post_dominators, s_preds, s_succs)
sbitmap_zero (dominators[0]);
SET_BIT (dominators[0], 0);
- sbitmap_zero (post_dominators[n_basic_blocks-1]);
- SET_BIT (post_dominators[n_basic_blocks-1], 0);
+ sbitmap_zero (post_dominators[n_basic_blocks - 1]);
+ SET_BIT (post_dominators[n_basic_blocks - 1], 0);
passes = 0;
changed = 1;
@@ -4004,6 +4673,46 @@ compute_dominators (dominators, post_dominators, s_preds, s_succs)
free (temp_bitmap);
}
+/* Given DOMINATORS, compute the immediate dominators into IDOM. */
+
+void
+compute_immediate_dominators (idom, dominators)
+ int *idom;
+ sbitmap *dominators;
+{
+ sbitmap *tmp;
+ int b;
+
+ tmp = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
+
+ /* Begin with tmp(n) = dom(n) - { n }. */
+ for (b = n_basic_blocks; --b >= 0; )
+ {
+ sbitmap_copy (tmp[b], dominators[b]);
+ RESET_BIT (tmp[b], b);
+ }
+
+ /* Subtract out all of our dominator's dominators. */
+ for (b = n_basic_blocks; --b >= 0; )
+ {
+ sbitmap tmp_b = tmp[b];
+ int s;
+
+ for (s = n_basic_blocks; --s >= 0; )
+ if (TEST_BIT (tmp_b, s))
+ sbitmap_difference (tmp_b, tmp_b, tmp[s]);
+ }
+
+ /* Find the one bit set in the bitmap and put it in the output array. */
+ for (b = n_basic_blocks; --b >= 0; )
+ {
+ int t;
+ EXECUTE_IF_SET_IN_SBITMAP (tmp[b], 0, t, { idom[b] = t; });
+ }
+
+ sbitmap_vector_free (tmp);
+}
+
/* Count for a single SET rtx, X. */
static void
@@ -4019,6 +4728,15 @@ count_reg_sets_1 (x)
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);
+ if (GET_CODE (reg) == PARALLEL
+ && GET_MODE (reg) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
+ count_reg_sets_1 (XVECEXP (reg, 0, i));
+ return;
+ }
+
if (GET_CODE (reg) == REG)
{
regno = REGNO (reg);
@@ -4064,8 +4782,6 @@ count_reg_references (x)
rtx x;
{
register RTX_CODE code;
- register int regno;
- int i;
retry:
code = GET_CODE (x);
@@ -4153,7 +4869,9 @@ count_reg_references (x)
/* If this is a store into a register,
recursively scan the value being stored. */
- if (GET_CODE (testreg) == REG)
+ if ((GET_CODE (testreg) == PARALLEL
+ && GET_MODE (testreg) == BLKmode)
+ || GET_CODE (testreg) == REG)
{
count_reg_references (SET_SRC (x));
if (mark_dest)
@@ -4205,12 +4923,18 @@ count_reg_references (x)
register allocators to prioritize pseudos for allocation to hard regs.
More accurate reference counts generally lead to better register allocation.
+ F is the first insn to be scanned.
+ LOOP_STEP denotes how much loop_depth should be incremented per
+ loop nesting level in order to increase the ref count more for references
+ in a loop.
+
It might be worthwhile to update REG_LIVE_LENGTH, REG_BASIC_BLOCK and
possibly other information which is used by the register allocators. */
void
-recompute_reg_usage (f)
+recompute_reg_usage (f, loop_step)
rtx f;
+ int loop_step;
{
rtx insn;
int i, max_reg;
@@ -4233,9 +4957,9 @@ recompute_reg_usage (f)
{
/* Look for loop boundaries. */
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
- loop_depth--;
+ loop_depth -= loop_step;
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- loop_depth++;
+ loop_depth += loop_step;
/* If we have LOOP_DEPTH == 0, there has been a bookkeeping error.
Abort now rather than setting register status incorrectly. */
@@ -4281,3 +5005,251 @@ recompute_reg_usage (f)
}
}
}
+
+/* Record INSN's block as BB. */
+
+void
+set_block_for_insn (insn, bb)
+ rtx insn;
+ basic_block bb;
+{
+ size_t uid = INSN_UID (insn);
+ if (uid >= basic_block_for_insn->num_elements)
+ {
+ int new_size;
+
+ /* Add one-eighth the size so we don't keep calling xrealloc. */
+ new_size = uid + (uid + 7) / 8;
+
+ VARRAY_GROW (basic_block_for_insn, new_size);
+ }
+ VARRAY_BB (basic_block_for_insn, uid) = bb;
+}
+
+/* Record INSN's block number as BB. */
+/* ??? This has got to go. */
+
+void
+set_block_num (insn, bb)
+ rtx insn;
+ int bb;
+{
+ set_block_for_insn (insn, BASIC_BLOCK (bb));
+}
+
+/* Verify the CFG consistency. This function check some CFG invariants and
+ aborts when something is wrong. Hope that this function will help to
+ convert many optimization passes to preserve CFG consistent.
+
+ Currently it does following checks:
+
+ - test head/end pointers
+ - overlapping of basic blocks
+ - edge list corectness
+ - headers of basic blocks (the NOTE_INSN_BASIC_BLOCK note)
+ - tails of basic blocks (ensure that boundary is necesary)
+ - scans body of the basic block for JUMP_INSN, CODE_LABEL
+ and NOTE_INSN_BASIC_BLOCK
+ - check that all insns are in the basic blocks
+ (except the switch handling code, barriers and notes)
+
+ In future it can be extended check a lot of other stuff as well
+ (reachability of basic blocks, life information, etc. etc.). */
+
+void
+verify_flow_info ()
+{
+ const int max_uid = get_max_uid ();
+ const rtx rtx_first = get_insns ();
+ basic_block *bb_info;
+ rtx x;
+ int i;
+
+ bb_info = (basic_block *) alloca (max_uid * sizeof (basic_block));
+ memset (bb_info, 0, max_uid * sizeof (basic_block));
+
+ /* First pass check head/end pointers and set bb_info array used by
+ later passes. */
+ for (i = n_basic_blocks - 1; i >= 0; i--)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+
+ /* Check the head pointer and make sure that it is pointing into
+ insn list. */
+ for (x = rtx_first; x != NULL_RTX; x = NEXT_INSN (x))
+ if (x == bb->head)
+ break;
+ if (!x)
+ {
+ fatal ("verify_flow_info: Head insn %d for block %d not found in the insn stream.\n",
+ INSN_UID (bb->head), bb->index);
+ }
+
+ /* Check the end pointer and make sure that it is pointing into
+ insn list. */
+ for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
+ {
+ if (bb_info[INSN_UID (x)] != NULL)
+ {
+ fatal ("verify_flow_info: Insn %d is in multiple basic blocks (%d and %d)",
+ INSN_UID (x), bb->index, bb_info[INSN_UID (x)]->index);
+ }
+ bb_info[INSN_UID (x)] = bb;
+
+ if (x == bb->end)
+ break;
+ }
+ if (!x)
+ {
+ fatal ("verify_flow_info: End insn %d for block %d not found in the insn stream.\n",
+ INSN_UID (bb->end), bb->index);
+ }
+ }
+
+ /* Now check the basic blocks (boundaries etc.) */
+ for (i = n_basic_blocks - 1; i >= 0; i--)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+ /* Check corectness of edge lists */
+ edge e;
+
+ e = bb->succ;
+ while (e)
+ {
+ if (e->src != bb)
+ {
+ fprintf (stderr, "verify_flow_info: Basic block %d succ edge is corrupted\n",
+ bb->index);
+ fprintf (stderr, "Predecessor: ");
+ dump_edge_info (stderr, e, 0);
+ fprintf (stderr, "\nSuccessor: ");
+ dump_edge_info (stderr, e, 1);
+ fflush (stderr);
+ abort ();
+ }
+ if (e->dest != EXIT_BLOCK_PTR)
+ {
+ edge e2 = e->dest->pred;
+ while (e2 && e2 != e)
+ e2 = e2->pred_next;
+ if (!e2)
+ {
+ fatal ("verify_flow_info: Basic block %i edge lists are corrupted\n",
+ bb->index);
+ }
+ }
+ e = e->succ_next;
+ }
+
+ e = bb->pred;
+ while (e)
+ {
+ if (e->dest != bb)
+ {
+ fprintf (stderr, "verify_flow_info: Basic block %d pred edge is corrupted\n",
+ bb->index);
+ fprintf (stderr, "Predecessor: ");
+ dump_edge_info (stderr, e, 0);
+ fprintf (stderr, "\nSuccessor: ");
+ dump_edge_info (stderr, e, 1);
+ fflush (stderr);
+ abort ();
+ }
+ if (e->src != ENTRY_BLOCK_PTR)
+ {
+ edge e2 = e->src->succ;
+ while (e2 && e2 != e)
+ e2 = e2->succ_next;
+ if (!e2)
+ {
+ fatal ("verify_flow_info: Basic block %i edge lists are corrupted\n",
+ bb->index);
+ }
+ }
+ e = e->pred_next;
+ }
+
+ /* OK pointers are correct. Now check the header of basic
+ block. It ought to contain optional CODE_LABEL followed
+ by NOTE_BASIC_BLOCK. */
+ x = bb->head;
+ if (GET_CODE (x) == CODE_LABEL)
+ {
+ if (bb->end == x)
+ {
+ fatal ("verify_flow_info: Basic block contains only CODE_LABEL and no NOTE_INSN_BASIC_BLOCK note\n");
+ }
+ x = NEXT_INSN (x);
+ }
+ if (GET_CODE (x) != NOTE
+ || NOTE_LINE_NUMBER (x) != NOTE_INSN_BASIC_BLOCK
+ || NOTE_BASIC_BLOCK (x) != bb)
+ {
+ fatal ("verify_flow_info: NOTE_INSN_BASIC_BLOCK is missing for block %d\n",
+ bb->index);
+ }
+
+ if (bb->end == x)
+ {
+ /* Do checks for empty blocks here */
+ }
+ else
+ {
+ x = NEXT_INSN (x);
+ while (x)
+ {
+ if (GET_CODE (x) == NOTE
+ && NOTE_LINE_NUMBER (x) == NOTE_INSN_BASIC_BLOCK)
+ {
+ fatal ("verify_flow_info: NOTE_INSN_BASIC_BLOCK %d in the middle of basic block %d\n",
+ INSN_UID (x), bb->index);
+ }
+
+ if (x == bb->end)
+ break;
+
+ if (GET_CODE (x) == JUMP_INSN
+ || GET_CODE (x) == CODE_LABEL
+ || GET_CODE (x) == BARRIER)
+ {
+ fatal_insn ("verify_flow_info: Incorrect insn in the middle of basic block %d\n",
+ x, bb->index);
+ }
+
+ x = NEXT_INSN (x);
+ }
+ }
+ }
+
+ x = rtx_first;
+ while (x)
+ {
+ if (!bb_info[INSN_UID (x)])
+ {
+ switch (GET_CODE (x))
+ {
+ case BARRIER:
+ case NOTE:
+ break;
+
+ case CODE_LABEL:
+ /* An addr_vec is placed outside any block block. */
+ if (NEXT_INSN (x)
+ && GET_CODE (NEXT_INSN (x)) == JUMP_INSN
+ && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC
+ || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC))
+ {
+ x = NEXT_INSN (x);
+ }
+
+ /* But in any case, non-deletable labels can appear anywhere. */
+ break;
+
+ default:
+ fatal_insn ("verify_flow_info: Insn outside basic block\n", x);
+ }
+ }
+
+ x = NEXT_INSN (x);
+ }
+}
diff --git a/contrib/gcc/fold-const.c b/contrib/gcc/fold-const.c
index 926e1eb..dc9ca93 100644
--- a/contrib/gcc/fold-const.c
+++ b/contrib/gcc/fold-const.c
@@ -47,11 +47,9 @@ Boston, MA 02111-1307, USA. */
#include <setjmp.h>
#include "flags.h"
#include "tree.h"
+#include "rtl.h"
#include "toplev.h"
-/* Handle floating overflow for `const_binop'. */
-static jmp_buf float_error;
-
static void encode PROTO((HOST_WIDE_INT *,
HOST_WIDE_INT, HOST_WIDE_INT));
static void decode PROTO((HOST_WIDE_INT *,
@@ -95,6 +93,9 @@ static tree fold_truthop PROTO((enum tree_code, tree, tree, tree));
static tree strip_compound_expr PROTO((tree, tree));
static int multiple_of_p PROTO((tree, tree, tree));
static tree constant_boolean_node PROTO((int, tree));
+static int count_cond PROTO((tree, int));
+static void const_binop_1 PROTO((PTR));
+static void fold_convert_1 PROTO((PTR));
#ifndef BRANCH_COST
#define BRANCH_COST 1
@@ -377,7 +378,7 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
void
rshift_double (l1, h1, count, prec, lv, hv, arith)
HOST_WIDE_INT l1, h1, count;
- int prec;
+ int prec ATTRIBUTE_UNUSED;
HOST_WIDE_INT *lv, *hv;
int arith;
{
@@ -528,7 +529,7 @@ div_and_round_double (code, uns,
encode (den, lden, hden);
/* Special code for when the divisor < BASE. */
- if (hden == 0 && lden < BASE)
+ if (hden == 0 && lden < (HOST_WIDE_INT) BASE)
{
/* hnum != 0 already checked. */
for (i = 4 - 1; i >= 0; i--)
@@ -884,6 +885,7 @@ exact_real_inverse (mode, r)
enum machine_mode mode;
REAL_VALUE_TYPE *r;
{
+ jmp_buf float_error;
union
{
double d;
@@ -963,6 +965,235 @@ fail:
*r = y.d;
return 1;
}
+
+
+/* Convert C9X hexadecimal floating point string constant S. Return
+ real value type in mode MODE. This function uses the host computer's
+ fp arithmetic when there is no REAL_ARITHMETIC. */
+
+REAL_VALUE_TYPE
+real_hex_to_f (s, mode)
+ char *s;
+ enum machine_mode mode;
+{
+ REAL_VALUE_TYPE ip;
+ char *p = s;
+ unsigned HOST_WIDE_INT low, high;
+ int frexpon, expon, shcount, nrmcount, k;
+ int sign, expsign, decpt, isfloat, isldouble, gotp, lost;
+ char c;
+
+ isldouble = 0;
+ isfloat = 0;
+ frexpon = 0;
+ expon = 0;
+ expsign = 1;
+ ip = 0.0;
+
+ while (*p == ' ' || *p == '\t')
+ ++p;
+
+ /* Sign, if any, comes first. */
+ sign = 1;
+ if (*p == '-')
+ {
+ sign = -1;
+ ++p;
+ }
+
+ /* The string is supposed to start with 0x or 0X . */
+ if (*p == '0')
+ {
+ ++p;
+ if (*p == 'x' || *p == 'X')
+ ++p;
+ else
+ abort ();
+ }
+ else
+ abort ();
+
+ while (*p == '0')
+ ++p;
+
+ high = 0;
+ low = 0;
+ lost = 0; /* Nonzero low order bits shifted out and discarded. */
+ frexpon = 0; /* Bits after the decimal point. */
+ expon = 0; /* Value of exponent. */
+ decpt = 0; /* How many decimal points. */
+ gotp = 0; /* How many P's. */
+ shcount = 0;
+ while ((c = *p) != '\0')
+ {
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
+ || (c >= 'a' && c <= 'f'))
+ {
+ k = c & 0x7f;
+ if (k >= 'a')
+ k = k - 'a' + 10;
+ else if (k >= 'A')
+ k = k - 'A' + 10;
+ else
+ k = k - '0';
+
+ if ((high & 0xf0000000) == 0)
+ {
+ high = (high << 4) + ((low >> 28) & 15);
+ low = (low << 4) + k;
+ shcount += 4;
+ if (decpt)
+ frexpon += 4;
+ }
+ else
+ {
+ /* Record nonzero lost bits. */
+ lost |= k;
+ if (!decpt)
+ frexpon -= 4;
+ }
+ ++p;
+ }
+ else if ( c == '.')
+ {
+ ++decpt;
+ ++p;
+ }
+ else if (c == 'p' || c == 'P')
+ {
+ ++gotp;
+ ++p;
+ /* Sign of exponent. */
+ if (*p == '-')
+ {
+ expsign = -1;
+ ++p;
+ }
+ /* Value of exponent.
+ The exponent field is a decimal integer. */
+ while (isdigit(*p))
+ {
+ k = (*p++ & 0x7f) - '0';
+ expon = 10 * expon + k;
+ }
+ expon *= expsign;
+ /* F suffix is ambiguous in the significand part
+ so it must appear after the decimal exponent field. */
+ if (*p == 'f' || *p == 'F')
+ {
+ isfloat = 1;
+ ++p;
+ break;
+ }
+ }
+ else if (c == 'l' || c == 'L')
+ {
+ isldouble = 1;
+ ++p;
+ break;
+ }
+ else
+ break;
+ }
+ /* Abort if last character read was not legitimate. */
+ c = *p;
+ if ((c != '\0' && c != ' ' && c != '\n' && c != '\r') || (decpt > 1))
+ abort ();
+ /* There must be either one decimal point or one p. */
+ if (decpt == 0 && gotp == 0)
+ abort ();
+ shcount -= 4;
+ if ((high == 0) && (low == 0))
+ {
+ return dconst0;
+ }
+
+ /* Normalize. */
+ nrmcount = 0;
+ if (high == 0)
+ {
+ high = low;
+ low = 0;
+ nrmcount += 32;
+ }
+ /* Leave a high guard bit for carry-out. */
+ if ((high & 0x80000000) != 0)
+ {
+ lost |= low & 1;
+ low = (low >> 1) | (high << 31);
+ high = high >> 1;
+ nrmcount -= 1;
+ }
+ if ((high & 0xffff8000) == 0)
+ {
+ high = (high << 16) + ((low >> 16) & 0xffff);
+ low = low << 16;
+ nrmcount += 16;
+ }
+ while ((high & 0xc0000000) == 0)
+ {
+ high = (high << 1) + ((low >> 31) & 1);
+ low = low << 1;
+ nrmcount += 1;
+ }
+ if (isfloat || GET_MODE_SIZE(mode) == UNITS_PER_WORD)
+ {
+ /* Keep 24 bits precision, bits 0x7fffff80.
+ Rounding bit is 0x40. */
+ lost = lost | low | (high & 0x3f);
+ low = 0;
+ if (high & 0x40)
+ {
+ if ((high & 0x80) || lost)
+ high += 0x40;
+ }
+ high &= 0xffffff80;
+ }
+ else
+ {
+ /* We need real.c to do long double formats, so here default
+ to double precision. */
+#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+ /* IEEE double.
+ Keep 53 bits precision, bits 0x7fffffff fffffc00.
+ Rounding bit is low word 0x200. */
+ lost = lost | (low & 0x1ff);
+ if (low & 0x200)
+ {
+ if ((low & 0x400) || lost)
+ {
+ low = (low + 0x200) & 0xfffffc00;
+ if (low == 0)
+ high += 1;
+ }
+ }
+ low &= 0xfffffc00;
+#else
+ /* Assume it's a VAX with 56-bit significand,
+ bits 0x7fffffff ffffff80. */
+ lost = lost | (low & 0x7f);
+ if (low & 0x40)
+ {
+ if ((low & 0x80) || lost)
+ {
+ low = (low + 0x40) & 0xffffff80;
+ if (low == 0)
+ high += 1;
+ }
+ }
+ low &= 0xffffff80;
+#endif
+ }
+ ip = (double) high;
+ ip = REAL_VALUE_LDEXP (ip, 32) + (double) low;
+ /* Apply shifts and exponent value as power of 2. */
+ ip = REAL_VALUE_LDEXP (ip, expon - (nrmcount + frexpon));
+
+ if (sign < 0)
+ ip = -ip;
+ return ip;
+}
+
#endif /* no REAL_ARITHMETIC */
/* Split a tree IN into a constant and a variable part
@@ -1247,6 +1478,67 @@ int_const_binop (code, arg1, arg2, notrunc, forsize)
return t;
}
+struct cb_args
+{
+ /* Input */
+ tree arg1;
+ REAL_VALUE_TYPE d1, d2;
+ enum tree_code code;
+ /* Output */
+ tree t;
+};
+
+static void
+const_binop_1 (data)
+ PTR data;
+{
+ struct cb_args * args = (struct cb_args *) data;
+ REAL_VALUE_TYPE value;
+
+#ifdef REAL_ARITHMETIC
+ REAL_ARITHMETIC (value, args->code, args->d1, args->d2);
+#else
+ switch (args->code)
+ {
+ case PLUS_EXPR:
+ value = args->d1 + args->d2;
+ break;
+
+ case MINUS_EXPR:
+ value = args->d1 - args->d2;
+ break;
+
+ case MULT_EXPR:
+ value = args->d1 * args->d2;
+ break;
+
+ case RDIV_EXPR:
+#ifndef REAL_INFINITY
+ if (args->d2 == 0)
+ abort ();
+#endif
+
+ value = args->d1 / args->d2;
+ break;
+
+ case MIN_EXPR:
+ value = MIN (args->d1, args->d2);
+ break;
+
+ case MAX_EXPR:
+ value = MAX (args->d1, args->d2);
+ break;
+
+ default:
+ abort ();
+ }
+#endif /* no REAL_ARITHMETIC */
+ args->t =
+ build_real (TREE_TYPE (args->arg1),
+ real_value_truncate (TYPE_MODE (TREE_TYPE (args->arg1)),
+ value));
+}
+
/* Combine two constants ARG1 and ARG2 under operation CODE
to produce a new constant.
We assume ARG1 and ARG2 have the same data type,
@@ -1271,8 +1563,8 @@ const_binop (code, arg1, arg2, notrunc)
REAL_VALUE_TYPE d1;
REAL_VALUE_TYPE d2;
int overflow = 0;
- REAL_VALUE_TYPE value;
tree t;
+ struct cb_args args;
d1 = TREE_REAL_CST (arg1);
d2 = TREE_REAL_CST (arg2);
@@ -1283,57 +1575,24 @@ const_binop (code, arg1, arg2, notrunc)
return arg1;
else if (REAL_VALUE_ISNAN (d2))
return arg2;
- else if (setjmp (float_error))
+
+ /* Setup input for const_binop_1() */
+ args.arg1 = arg1;
+ args.d1 = d1;
+ args.d2 = d2;
+ args.code = code;
+
+ if (do_float_handler (const_binop_1, (PTR) &args))
{
- t = copy_node (arg1);
- overflow = 1;
- goto got_float;
+ /* Receive output from const_binop_1() */
+ t = args.t;
}
-
- set_float_handler (float_error);
-
-#ifdef REAL_ARITHMETIC
- REAL_ARITHMETIC (value, code, d1, d2);
-#else
- switch (code)
+ else
{
- case PLUS_EXPR:
- value = d1 + d2;
- break;
-
- case MINUS_EXPR:
- value = d1 - d2;
- break;
-
- case MULT_EXPR:
- value = d1 * d2;
- break;
-
- case RDIV_EXPR:
-#ifndef REAL_INFINITY
- if (d2 == 0)
- abort ();
-#endif
-
- value = d1 / d2;
- break;
-
- case MIN_EXPR:
- value = MIN (d1, d2);
- break;
-
- case MAX_EXPR:
- value = MAX (d1, d2);
- break;
-
- default:
- abort ();
+ /* We got an exception from const_binop_1() */
+ t = copy_node (arg1);
+ overflow = 1;
}
-#endif /* no REAL_ARITHMETIC */
- t = build_real (TREE_TYPE (arg1),
- real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)), value));
- got_float:
- set_float_handler (NULL_PTR);
TREE_OVERFLOW (t)
= (force_fit_type (t, overflow)
@@ -1524,6 +1783,25 @@ ssize_binop (code, arg0, arg1)
return fold (build (code, ssizetype, arg0, arg1));
}
+struct fc_args
+{
+ /* Input */
+ tree arg1, type;
+ /* Output */
+ tree t;
+};
+
+static void
+fold_convert_1 (data)
+ PTR data;
+{
+ struct fc_args * args = (struct fc_args *) data;
+
+ args->t = build_real (args->type,
+ real_value_truncate (TYPE_MODE (args->type),
+ TREE_REAL_CST (args->arg1)));
+}
+
/* Given T, a tree representing type conversion of ARG1, a constant,
return a constant tree representing the result of conversion. */
@@ -1649,25 +1927,31 @@ fold_convert (t, arg1)
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
if (TREE_CODE (arg1) == REAL_CST)
{
+ struct fc_args args;
+
if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
{
t = arg1;
TREE_TYPE (arg1) = type;
return t;
}
- else if (setjmp (float_error))
+
+ /* Setup input for fold_convert_1() */
+ args.arg1 = arg1;
+ args.type = type;
+
+ if (do_float_handler (fold_convert_1, (PTR) &args))
+ {
+ /* Receive output from fold_convert_1() */
+ t = args.t;
+ }
+ else
{
+ /* We got an exception from fold_convert_1() */
overflow = 1;
t = copy_node (arg1);
- goto got_it;
}
- set_float_handler (float_error);
-
- t = build_real (type, real_value_truncate (TYPE_MODE (type),
- TREE_REAL_CST (arg1)));
- set_float_handler (NULL_PTR);
- got_it:
TREE_OVERFLOW (t)
= TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
TREE_CONSTANT_OVERFLOW (t)
@@ -1679,8 +1963,7 @@ fold_convert (t, arg1)
return t;
}
-/* Return an expr equal to X but certainly not valid as an lvalue.
- Also make sure it is not valid as an null pointer constant. */
+/* Return an expr equal to X but certainly not valid as an lvalue. */
tree
non_lvalue (x)
@@ -1694,18 +1977,7 @@ non_lvalue (x)
|| TREE_CODE (x) == REAL_CST
|| TREE_CODE (x) == STRING_CST
|| TREE_CODE (x) == ADDR_EXPR)
- {
- if (TREE_CODE (x) == INTEGER_CST && integer_zerop (x))
- {
- /* Use NOP_EXPR instead of NON_LVALUE_EXPR
- so convert_for_assignment won't strip it.
- This is so this 0 won't be treated as a null pointer constant. */
- result = build1 (NOP_EXPR, TREE_TYPE (x), x);
- TREE_CONSTANT (result) = TREE_CONSTANT (x);
- return result;
- }
- return x;
- }
+ return x;
result = build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
TREE_CONSTANT (result) = TREE_CONSTANT (x);
@@ -1928,6 +2200,11 @@ operand_equal_p (arg0, arg1, only_const)
default:
return 0;
}
+
+ case 'e':
+ if (TREE_CODE (arg0) == RTL_EXPR)
+ return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
+ return 0;
default:
return 0;
@@ -2151,7 +2428,7 @@ eval_subst (arg, old0, new0, old1, new1)
default:
break;
}
- /* fall through (???) */
+ /* fall through - ??? */
case '<':
{
@@ -2236,7 +2513,7 @@ invert_truthvalue (arg)
if (TREE_CODE_CLASS (code) == '<')
{
if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
- && code != NE_EXPR && code != EQ_EXPR)
+ && !flag_fast_math && code != NE_EXPR && code != EQ_EXPR)
return build1 (TRUTH_NOT_EXPR, type, arg);
else
return build (invert_tree_comparison (code), type,
@@ -2537,8 +2814,8 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
convert (unsigned_type, rhs),
size_int (lbitsize), 0)))
{
- warning ("comparison is always %s due to width of bitfield",
- code == NE_EXPR ? "one" : "zero");
+ warning ("comparison is always %d due to width of bitfield",
+ code == NE_EXPR);
return convert (compare_type,
(code == NE_EXPR
? integer_one_node : integer_zero_node));
@@ -2550,8 +2827,8 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
size_int (lbitsize - 1), 0);
if (! integer_zerop (tem) && ! integer_all_onesp (tem))
{
- warning ("comparison is always %s due to width of bitfield",
- code == NE_EXPR ? "one" : "zero");
+ warning ("comparison is always %d due to width of bitfield",
+ code == NE_EXPR);
return convert (compare_type,
(code == NE_EXPR
? integer_one_node : integer_zero_node));
@@ -2832,7 +3109,7 @@ make_range (exp, pin_p, plow, phigh)
tree *plow, *phigh;
{
enum tree_code code;
- tree arg0, arg1, type = NULL_TREE;
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE, type = NULL_TREE;
tree orig_type = NULL_TREE;
int in_p, n_in_p;
tree low, high, n_low, n_high;
@@ -2863,6 +3140,11 @@ make_range (exp, pin_p, plow, phigh)
arg1 = TREE_OPERAND (exp, 1);
}
+ /* Set ORIG_TYPE as soon as TYPE is non-null so that we do not
+ lose a cast by accident. */
+ if (type != NULL_TREE && orig_type == NULL_TREE)
+ orig_type = type;
+
switch (code)
{
case TRUTH_NOT_EXPR:
@@ -2981,8 +3263,6 @@ make_range (exp, pin_p, plow, phigh)
continue;
case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
- if (orig_type == NULL_TREE)
- orig_type = type;
if (TYPE_PRECISION (type) > TYPE_PRECISION (orig_type))
break;
@@ -3330,7 +3610,6 @@ fold_range_test (exp)
}
}
-
return 0;
}
@@ -3431,7 +3710,7 @@ fold_truthop (code, truth_type, lhs, rhs)
tree ll_mask, lr_mask, rl_mask, rr_mask;
tree ll_and_mask, lr_and_mask, rl_and_mask, rr_and_mask;
tree l_const, r_const;
- tree type, result;
+ tree lntype, rntype, result;
int first_bit, end_bit;
int volatilep;
@@ -3527,30 +3806,23 @@ fold_truthop (code, truth_type, lhs, rhs)
{
if (l_const && integer_zerop (l_const) && integer_pow2p (ll_mask))
{
- if (ll_unsignedp || tree_log2 (ll_mask) + 1 < ll_bitsize)
- l_const = ll_mask;
- else
- /* Since ll_arg is a single bit bit mask, we can sign extend
- it appropriately with a NEGATE_EXPR.
- l_const is made a signed value here, but since for l_const != NULL
- lr_unsignedp is not used, we don't need to clear the latter. */
- l_const = fold (build1 (NEGATE_EXPR, TREE_TYPE (ll_arg),
- convert (TREE_TYPE (ll_arg), ll_mask)));
+ /* Make the left operand unsigned, since we are only interested
+ in the value of one bit. Otherwise we are doing the wrong
+ thing below. */
+ ll_unsignedp = 1;
+ l_const = ll_mask;
}
else
return 0;
}
+ /* This is analogous to the code for l_const above. */
if (rcode != wanted_code)
{
if (r_const && integer_zerop (r_const) && integer_pow2p (rl_mask))
{
- if (rl_unsignedp || tree_log2 (rl_mask) + 1 < rl_bitsize)
- r_const = rl_mask;
- else
- /* This is analogous to the code for l_const above. */
- r_const = fold (build1 (NEGATE_EXPR, TREE_TYPE (rl_arg),
- convert (TREE_TYPE (rl_arg), rl_mask)));
+ rl_unsignedp = 1;
+ r_const = rl_mask;
}
else
return 0;
@@ -3569,7 +3841,7 @@ fold_truthop (code, truth_type, lhs, rhs)
lnbitsize = GET_MODE_BITSIZE (lnmode);
lnbitpos = first_bit & ~ (lnbitsize - 1);
- type = type_for_size (lnbitsize, 1);
+ lntype = type_for_size (lnbitsize, 1);
xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos;
if (BYTES_BIG_ENDIAN)
@@ -3578,23 +3850,22 @@ fold_truthop (code, truth_type, lhs, rhs)
xrl_bitpos = lnbitsize - xrl_bitpos - rl_bitsize;
}
- ll_mask = const_binop (LSHIFT_EXPR, convert (type, ll_mask),
+ ll_mask = const_binop (LSHIFT_EXPR, convert (lntype, ll_mask),
size_int (xll_bitpos), 0);
- rl_mask = const_binop (LSHIFT_EXPR, convert (type, rl_mask),
+ rl_mask = const_binop (LSHIFT_EXPR, convert (lntype, rl_mask),
size_int (xrl_bitpos), 0);
if (l_const)
{
- l_const = convert (type, l_const);
+ l_const = convert (lntype, l_const);
l_const = unextend (l_const, ll_bitsize, ll_unsignedp, ll_and_mask);
l_const = const_binop (LSHIFT_EXPR, l_const, size_int (xll_bitpos), 0);
if (! integer_zerop (const_binop (BIT_AND_EXPR, l_const,
fold (build1 (BIT_NOT_EXPR,
- type, ll_mask)),
+ lntype, ll_mask)),
0)))
{
- warning ("comparison is always %s",
- wanted_code == NE_EXPR ? "one" : "zero");
+ warning ("comparison is always %d", wanted_code == NE_EXPR);
return convert (truth_type,
wanted_code == NE_EXPR
@@ -3603,17 +3874,16 @@ fold_truthop (code, truth_type, lhs, rhs)
}
if (r_const)
{
- r_const = convert (type, r_const);
+ r_const = convert (lntype, r_const);
r_const = unextend (r_const, rl_bitsize, rl_unsignedp, rl_and_mask);
r_const = const_binop (LSHIFT_EXPR, r_const, size_int (xrl_bitpos), 0);
if (! integer_zerop (const_binop (BIT_AND_EXPR, r_const,
fold (build1 (BIT_NOT_EXPR,
- type, rl_mask)),
+ lntype, rl_mask)),
0)))
{
- warning ("comparison is always %s",
- wanted_code == NE_EXPR ? "one" : "zero");
-
+ warning ("comparison is always %d", wanted_code == NE_EXPR);
+
return convert (truth_type,
wanted_code == NE_EXPR
? integer_one_node : integer_zero_node);
@@ -3642,6 +3912,7 @@ fold_truthop (code, truth_type, lhs, rhs)
rnbitsize = GET_MODE_BITSIZE (rnmode);
rnbitpos = first_bit & ~ (rnbitsize - 1);
+ rntype = type_for_size (rnbitsize, 1);
xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos;
if (BYTES_BIG_ENDIAN)
@@ -3650,47 +3921,83 @@ fold_truthop (code, truth_type, lhs, rhs)
xrr_bitpos = rnbitsize - xrr_bitpos - rr_bitsize;
}
- lr_mask = const_binop (LSHIFT_EXPR, convert (type, lr_mask),
+ lr_mask = const_binop (LSHIFT_EXPR, convert (rntype, lr_mask),
size_int (xlr_bitpos), 0);
- rr_mask = const_binop (LSHIFT_EXPR, convert (type, rr_mask),
+ rr_mask = const_binop (LSHIFT_EXPR, convert (rntype, rr_mask),
size_int (xrr_bitpos), 0);
/* Make a mask that corresponds to both fields being compared.
- Do this for both items being compared. If the masks agree,
- we can do this by masking both and comparing the masked
+ Do this for both items being compared. If the operands are the
+ same size and the bits being compared are in the same position
+ then we can do this by masking both and comparing the masked
results. */
ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
lr_mask = const_binop (BIT_IOR_EXPR, lr_mask, rr_mask, 0);
- if (operand_equal_p (ll_mask, lr_mask, 0) && lnbitsize == rnbitsize)
+ if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
{
- lhs = make_bit_field_ref (ll_inner, type, lnbitsize, lnbitpos,
+ lhs = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
- rhs = make_bit_field_ref (lr_inner, type, rnbitsize, rnbitpos,
- lr_unsignedp || rr_unsignedp);
if (! all_ones_mask_p (ll_mask, lnbitsize))
- {
- lhs = build (BIT_AND_EXPR, type, lhs, ll_mask);
- rhs = build (BIT_AND_EXPR, type, rhs, ll_mask);
- }
+ lhs = build (BIT_AND_EXPR, lntype, lhs, ll_mask);
+
+ rhs = make_bit_field_ref (lr_inner, rntype, rnbitsize, rnbitpos,
+ lr_unsignedp || rr_unsignedp);
+ if (! all_ones_mask_p (lr_mask, rnbitsize))
+ rhs = build (BIT_AND_EXPR, rntype, rhs, lr_mask);
+
return build (wanted_code, truth_type, lhs, rhs);
}
/* There is still another way we can do something: If both pairs of
fields being compared are adjacent, we may be able to make a wider
- field containing them both. */
+ field containing them both.
+
+ Note that we still must mask the lhs/rhs expressions. Furthermore,
+ the mask must be shifted to account for the shift done by
+ make_bit_field_ref. */
if ((ll_bitsize + ll_bitpos == rl_bitpos
&& lr_bitsize + lr_bitpos == rr_bitpos)
|| (ll_bitpos == rl_bitpos + rl_bitsize
&& lr_bitpos == rr_bitpos + rr_bitsize))
- return build (wanted_code, truth_type,
- make_bit_field_ref (ll_inner, type,
- ll_bitsize + rl_bitsize,
- MIN (ll_bitpos, rl_bitpos),
- ll_unsignedp),
- make_bit_field_ref (lr_inner, type,
- lr_bitsize + rr_bitsize,
- MIN (lr_bitpos, rr_bitpos),
- lr_unsignedp));
+ {
+ tree type;
+
+ lhs = make_bit_field_ref (ll_inner, lntype, ll_bitsize + rl_bitsize,
+ MIN (ll_bitpos, rl_bitpos), ll_unsignedp);
+ rhs = make_bit_field_ref (lr_inner, rntype, lr_bitsize + rr_bitsize,
+ MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
+
+ ll_mask = const_binop (RSHIFT_EXPR, ll_mask,
+ size_int (MIN (xll_bitpos, xrl_bitpos)), 0);
+ lr_mask = const_binop (RSHIFT_EXPR, lr_mask,
+ size_int (MIN (xlr_bitpos, xrr_bitpos)), 0);
+
+ /* Convert to the smaller type before masking out unwanted bits. */
+ type = lntype;
+ if (lntype != rntype)
+ {
+ if (lnbitsize > rnbitsize)
+ {
+ lhs = convert (rntype, lhs);
+ ll_mask = convert (rntype, ll_mask);
+ type = rntype;
+ }
+ else if (lnbitsize < rnbitsize)
+ {
+ rhs = convert (lntype, rhs);
+ lr_mask = convert (lntype, lr_mask);
+ type = lntype;
+ }
+ }
+
+ if (! all_ones_mask_p (ll_mask, ll_bitsize + rl_bitsize))
+ lhs = build (BIT_AND_EXPR, type, lhs, ll_mask);
+
+ if (! all_ones_mask_p (lr_mask, lr_bitsize + rr_bitsize))
+ rhs = build (BIT_AND_EXPR, type, rhs, lr_mask);
+
+ return build (wanted_code, truth_type, lhs, rhs);
+ }
return 0;
}
@@ -3711,7 +4018,7 @@ fold_truthop (code, truth_type, lhs, rhs)
}
else
{
- warning ("`and' of mutually exclusive equal-tests is always zero");
+ warning ("`and' of mutually exclusive equal-tests is always 0");
return convert (truth_type, integer_zero_node);
}
}
@@ -3720,12 +4027,12 @@ fold_truthop (code, truth_type, lhs, rhs)
reference we will make. Unless the mask is all ones the width of
that field, perform the mask operation. Then compare with the
merged constant. */
- result = make_bit_field_ref (ll_inner, type, lnbitsize, lnbitpos,
+ result = make_bit_field_ref (ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask, 0);
if (! all_ones_mask_p (ll_mask, lnbitsize))
- result = build (BIT_AND_EXPR, type, result, ll_mask);
+ result = build (BIT_AND_EXPR, lntype, result, ll_mask);
return build (wanted_code, truth_type, result,
const_binop (BIT_IOR_EXPR, l_const, r_const, 0));
@@ -3788,6 +4095,27 @@ constant_boolean_node (value, type)
}
}
+/* Utility function for the following routine, to see how complex a nesting of
+ COND_EXPRs can be. EXPR is the expression and LIMIT is a count beyond which
+ we don't care (to avoid spending too much time on complex expressions.). */
+
+static int
+count_cond (expr, lim)
+ tree expr;
+ int lim;
+{
+ int true, false;
+
+ if (TREE_CODE (expr) != COND_EXPR)
+ return 0;
+ else if (lim <= 0)
+ return 0;
+
+ true = count_cond (TREE_OPERAND (expr, 1), lim - 1);
+ false = count_cond (TREE_OPERAND (expr, 2), lim - 1 - true);
+ return MIN (lim, 1 + true + false);
+}
+
/* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc.,
and application of the associative law.
@@ -4011,6 +4339,8 @@ fold (expr)
else if ((TREE_CODE (arg1) == COND_EXPR
|| (TREE_CODE_CLASS (TREE_CODE (arg1)) == '<'
&& TREE_CODE_CLASS (code) != '<'))
+ && (TREE_CODE (arg0) != COND_EXPR
+ || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
&& (! TREE_SIDE_EFFECTS (arg0)
|| (current_function_decl != 0
&& ! contains_placeholder_p (arg0))))
@@ -4084,6 +4414,8 @@ fold (expr)
else if ((TREE_CODE (arg0) == COND_EXPR
|| (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
&& TREE_CODE_CLASS (code) != '<'))
+ && (TREE_CODE (arg1) != COND_EXPR
+ || count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
&& (! TREE_SIDE_EFFECTS (arg1)
|| (current_function_decl != 0
&& ! contains_placeholder_p (arg1))))
@@ -4425,18 +4757,36 @@ fold (expr)
goto bit_ior;
}
- /* (A * C) + (B * C) -> (A+B) * C. Since we are most concerned
- about the case where C is a constant, just try one of the
- four possibilities. */
-
- if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg1, 1), 0))
- return fold (build (MULT_EXPR, type,
- fold (build (PLUS_EXPR, type,
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0))),
- TREE_OPERAND (arg0, 1)));
+ if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR)
+ {
+ tree arg00, arg01, arg10, arg11;
+ tree alt0 = NULL_TREE, alt1 = NULL_TREE, same;
+
+ /* (A * C) + (B * C) -> (A+B) * C.
+ We are most concerned about the case where C is a constant,
+ but other combinations show up during loop reduction. Since
+ it is not difficult, try all four possibilities. */
+
+ arg00 = TREE_OPERAND (arg0, 0);
+ arg01 = TREE_OPERAND (arg0, 1);
+ arg10 = TREE_OPERAND (arg1, 0);
+ arg11 = TREE_OPERAND (arg1, 1);
+ same = NULL_TREE;
+
+ if (operand_equal_p (arg01, arg11, 0))
+ same = arg01, alt0 = arg00, alt1 = arg10;
+ else if (operand_equal_p (arg00, arg10, 0))
+ same = arg00, alt0 = arg01, alt1 = arg11;
+ else if (operand_equal_p (arg00, arg11, 0))
+ same = arg00, alt0 = arg01, alt1 = arg10;
+ else if (operand_equal_p (arg01, arg10, 0))
+ same = arg01, alt0 = arg00, alt1 = arg11;
+
+ if (same)
+ return fold (build (MULT_EXPR, type,
+ fold (build (PLUS_EXPR, type, alt0, alt1)),
+ same));
+ }
}
/* In IEEE floating point, x+0 may not equal x. */
else if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
@@ -4690,6 +5040,8 @@ fold (expr)
tree01 = TREE_OPERAND (arg0, 1);
tree11 = TREE_OPERAND (arg1, 1);
+ STRIP_NOPS (tree01);
+ STRIP_NOPS (tree11);
code01 = TREE_CODE (tree01);
code11 = TREE_CODE (tree11);
if (code01 == INTEGER_CST
@@ -4700,22 +5052,40 @@ fold (expr)
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
code0 == LSHIFT_EXPR ? tree01 : tree11);
- else if (code11 == MINUS_EXPR
- && TREE_CODE (TREE_OPERAND (tree11, 0)) == INTEGER_CST
- && TREE_INT_CST_HIGH (TREE_OPERAND (tree11, 0)) == 0
- && TREE_INT_CST_LOW (TREE_OPERAND (tree11, 0))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
- && operand_equal_p (tree01, TREE_OPERAND (tree11, 1), 0))
- return build (code0 == LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
- type, TREE_OPERAND (arg0, 0), tree01);
- else if (code01 == MINUS_EXPR
- && TREE_CODE (TREE_OPERAND (tree01, 0)) == INTEGER_CST
- && TREE_INT_CST_HIGH (TREE_OPERAND (tree01, 0)) == 0
- && TREE_INT_CST_LOW (TREE_OPERAND (tree01, 0))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
- && operand_equal_p (tree11, TREE_OPERAND (tree01, 1), 0))
- return build (code0 != LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
- type, TREE_OPERAND (arg0, 0), tree11);
+ else if (code11 == MINUS_EXPR)
+ {
+ tree tree110, tree111;
+ tree110 = TREE_OPERAND (tree11, 0);
+ tree111 = TREE_OPERAND (tree11, 1);
+ STRIP_NOPS (tree110);
+ STRIP_NOPS (tree111);
+ if (TREE_CODE (tree110) == INTEGER_CST
+ && TREE_INT_CST_HIGH (tree110) == 0
+ && (TREE_INT_CST_LOW (tree110)
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ && operand_equal_p (tree01, tree111, 0))
+ return build ((code0 == LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ type, TREE_OPERAND (arg0, 0), tree01);
+ }
+ else if (code01 == MINUS_EXPR)
+ {
+ tree tree010, tree011;
+ tree010 = TREE_OPERAND (tree01, 0);
+ tree011 = TREE_OPERAND (tree01, 1);
+ STRIP_NOPS (tree010);
+ STRIP_NOPS (tree011);
+ if (TREE_CODE (tree010) == INTEGER_CST
+ && TREE_INT_CST_HIGH (tree010) == 0
+ && (TREE_INT_CST_LOW (tree010)
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ && operand_equal_p (tree11, tree011, 0))
+ return build ((code0 != LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ type, TREE_OPERAND (arg0, 0), tree11);
+ }
}
goto associate;
@@ -5824,7 +6194,8 @@ fold (expr)
t = build (code, type, tem,
TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
arg0 = tem;
- arg1 = TREE_OPERAND (t, 2);
+ /* arg1 should be the first argument of the new T. */
+ arg1 = TREE_OPERAND (t, 1);
STRIP_NOPS (arg1);
}
}
@@ -5862,11 +6233,15 @@ fold (expr)
return pedantic_non_lvalue (convert (type, arg1));
case GE_EXPR:
case GT_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (arg1)))
+ arg1 = convert (signed_type (TREE_TYPE (arg1)), arg1);
return pedantic_non_lvalue
(convert (type, fold (build1 (ABS_EXPR,
TREE_TYPE (arg1), arg1))));
case LE_EXPR:
case LT_EXPR:
+ if (TREE_UNSIGNED (TREE_TYPE (arg1)))
+ arg1 = convert (signed_type (TREE_TYPE (arg1)), arg1);
return pedantic_non_lvalue
(fold (build1 (NEGATE_EXPR, type,
convert (type,
@@ -6013,7 +6388,8 @@ fold (expr)
t = build (code, type, tem,
TREE_OPERAND (t, 2), TREE_OPERAND (t, 1));
arg0 = tem;
- arg1 = TREE_OPERAND (t, 2);
+ /* arg1 should be the first argument of the new T. */
+ arg1 = TREE_OPERAND (t, 1);
STRIP_NOPS (arg1);
}
}
@@ -6049,7 +6425,7 @@ fold (expr)
return t;
/* Don't let (0, 0) be null pointer constant. */
if (integer_zerop (arg1))
- return non_lvalue (arg1);
+ return build1 (NOP_EXPR, TREE_TYPE (arg1), arg1);
return arg1;
case COMPLEX_EXPR:
diff --git a/contrib/gcc/frame.c b/contrib/gcc/frame.c
index 4b62759..b5f643e 100644
--- a/contrib/gcc/frame.c
+++ b/contrib/gcc/frame.c
@@ -1,6 +1,6 @@
/* Subroutines needed for unwinding stack frames for exception handling. */
/* Compile this one with gcc. */
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GNU CC.
@@ -46,7 +46,6 @@ Boston, MA 02111-1307, USA. */
#include "defaults.h"
#ifdef DWARF2_UNWIND_INFO
-#include "gansidecl.h"
#include "dwarf2.h"
#include <stddef.h>
#include "frame.h"
@@ -71,6 +70,25 @@ typedef unsigned int uaddr __attribute__ ((mode (pointer)));
typedef int saddr __attribute__ ((mode (pointer)));
typedef unsigned char ubyte;
+/* Terminology:
+ CIE - Common Information Element
+ FDE - Frame Descriptor Element
+
+ There is one per function, and it describes where the function code
+ is located, and what the register lifetimes and stack layout are
+ within the function.
+
+ The data structures are defined in the DWARF specfication, although
+ not in a very readable way (see LITERATURE).
+
+ Every time an exception is thrown, the code needs to locate the FDE
+ for the current function, and starts to look for exception regions
+ from that FDE. This works in a two-level search:
+ a) in a linear search, find the shared image (i.e. DLL) containing
+ the PC
+ b) using the FDE table for that shared object, locate the FDE using
+ binary search (which requires the sorting). */
+
/* The first few fields of a CIE. The CIE_id field is 0 for a CIE,
to distinguish it from a valid FDE. FDEs are aligned to an addressing
unit boundary, but the fields within are unaligned. */
@@ -114,6 +132,33 @@ struct frame_state_internal
struct frame_state s;
struct frame_state_internal *saved_state;
};
+
+/* This is undefined below if we need it to be an actual function. */
+#define init_object_mutex_once()
+
+#if __GTHREADS
+#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
+
+/* Helper for init_object_mutex_once. */
+
+static void
+init_object_mutex (void)
+{
+ __GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
+}
+
+/* Call this to arrange to initialize the object mutex. */
+
+#undef init_object_mutex_once
+static void
+init_object_mutex_once (void)
+{
+ static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+ __gthread_once (&once, init_object_mutex);
+}
+
+#endif /* __GTHREAD_MUTEX_INIT_FUNCTION */
+#endif /* __GTHREADS */
/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
by R, and return the new value of BUF. */
@@ -468,6 +513,7 @@ find_fde (void *pc)
struct object *ob;
size_t lo, hi;
+ init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
for (ob = objects; ob; ob = ob->next)
@@ -685,6 +731,7 @@ __register_frame_info (void *begin, struct object *ob)
ob->fde_array = 0;
ob->count = 0;
+ init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
ob->next = objects;
@@ -713,6 +760,7 @@ __register_frame_info_table (void *begin, struct object *ob)
ob->pc_begin = ob->pc_end = 0;
ob->count = 0;
+ init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
ob->next = objects;
@@ -735,6 +783,7 @@ __deregister_frame_info (void *begin)
{
struct object **p;
+ init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
p = &objects;
diff --git a/contrib/gcc/frame.h b/contrib/gcc/frame.h
index 9d0d693..985416c 100644
--- a/contrib/gcc/frame.h
+++ b/contrib/gcc/frame.h
@@ -1,5 +1,25 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
- This file is part of GNU CC. */
+/* Header file for unwinding stack frames for exception handling. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+ Contributed by Jason Merrill <jason@cygnus.com>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
typedef struct frame_state
{
diff --git a/contrib/gcc/function.c b/contrib/gcc/function.c
index cf9542b..f41982e 100644
--- a/contrib/gcc/function.c
+++ b/contrib/gcc/function.c
@@ -1,5 +1,5 @@
/* Expands front end tree to back end RTL for GNU C-Compiler
- Copyright (C) 1987, 88, 89, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -56,11 +56,16 @@ Boston, MA 02111-1307, USA. */
#include "basic-block.h"
#include "obstack.h"
#include "toplev.h"
+#include "hash.h"
#ifndef TRAMPOLINE_ALIGNMENT
#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
#endif
+#ifndef LOCAL_ALIGNMENT
+#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
+#endif
+
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
@@ -127,16 +132,32 @@ int current_function_has_nonlocal_label;
int current_function_has_nonlocal_goto;
-/* Nonzero if this function has a computed goto.
+/* Nonzero if function being compiled contains nested functions. */
- It is computed during find_basic_blocks or during stupid life
- analysis. */
+int current_function_contains_functions;
-int current_function_has_computed_jump;
+/* Nonzero if function being compiled doesn't contain any calls
+ (ignoring the prologue and epilogue). This is set prior to
+ local register allocation and is valid for the remaining
+ compiler passes. */
-/* Nonzero if function being compiled contains nested functions. */
+int current_function_is_leaf;
-int current_function_contains_functions;
+/* Nonzero if function being compiled doesn't modify the stack pointer
+ (ignoring the prologue and epilogue). This is only valid after
+ life_analysis has run. */
+
+int current_function_sp_is_unchanging;
+
+/* Nonzero if the function being compiled is a leaf function which only
+ uses leaf registers. This is valid after reload (specifically after
+ sched2) and is useful only if the port defines LEAF_REGISTERS. */
+
+int current_function_uses_only_leaf_regs;
+
+/* Nonzero if the function being compiled issues a computed jump. */
+
+int current_function_has_computed_jump;
/* Nonzero if the current function is a thunk (a lightweight function that
just adjusts one of its arguments and forwards to another function), so
@@ -217,6 +238,13 @@ rtx current_function_internal_arg_pointer;
/* Language-specific reason why the current function cannot be made inline. */
char *current_function_cannot_inline;
+/* Nonzero if instrumentation calls for function entry and exit should be
+ generated. */
+int current_function_instrument_entry_exit;
+
+/* Nonzero if memory access checking be enabled in the current function. */
+int current_function_check_memory_usage;
+
/* The FUNCTION_DECL for an inline function currently being expanded. */
tree inline_function_decl;
@@ -230,10 +258,17 @@ int function_call_count;
tree nonlocal_labels;
-/* RTX for stack slot that holds the current handler for nonlocal gotos.
+/* List (chain of EXPR_LIST) of stack slots that hold the current handlers
+ for nonlocal gotos. There is one for every nonlocal label in the function;
+ this list matches the one in nonlocal_labels.
Zero when function does not have nonlocal labels. */
-rtx nonlocal_goto_handler_slot;
+rtx nonlocal_goto_handler_slots;
+
+/* List (chain of EXPR_LIST) of labels heading the current handlers for
+ nonlocal gotos. */
+
+rtx nonlocal_goto_handler_labels;
/* RTX for stack slot that holds the stack pointer value to restore
for a nonlocal goto.
@@ -363,8 +398,21 @@ struct temp_slot
/* The rtx used to represent the address if not the address of the
slot above. May be an EXPR_LIST if multiple addresses exist. */
rtx address;
+ /* The alignment (in bits) of the slot. */
+ int align;
/* The size, in units, of the slot. */
HOST_WIDE_INT size;
+ /* The alias set for the slot. If the alias set is zero, we don't
+ know anything about the alias set of the slot. We must only
+ reuse a slot if it is assigned an object of the same alias set.
+ Otherwise, the rest of the compiler may assume that the new use
+ of the slot cannot alias the old use of the slot, which is
+ false. If the slot has alias set zero, then we can't reuse the
+ slot at all, since we have no idea what alias set may have been
+ imposed on the memory. For example, if the stack slot is the
+ call frame for an inline functioned, we have no idea what alias
+ sets will be assigned to various pieces of the call frame. */
+ int alias_set;
/* The value of `sequence_rtl_expr' when this temporary is allocated. */
tree rtl_expr;
/* Non-zero if this temporary is currently in use. */
@@ -413,19 +461,30 @@ struct fixup_replacement
struct fixup_replacement *next;
};
+struct insns_for_mem_entry {
+ /* The KEY in HE will be a MEM. */
+ struct hash_entry he;
+ /* These are the INSNS which reference the MEM. */
+ rtx insns;
+};
+
/* Forward declarations. */
static rtx assign_outer_stack_local PROTO ((enum machine_mode, HOST_WIDE_INT,
int, struct function *));
+static rtx assign_stack_temp_for_type PROTO ((enum machine_mode, HOST_WIDE_INT,
+ int, tree));
static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
static void put_reg_into_stack PROTO((struct function *, rtx, tree,
enum machine_mode, enum machine_mode,
- int, int, int));
-static void fixup_var_refs PROTO((rtx, enum machine_mode, int));
+ int, int, int,
+ struct hash_table *));
+static void fixup_var_refs PROTO((rtx, enum machine_mode, int,
+ struct hash_table *));
static struct fixup_replacement
*find_fixup_replacement PROTO((struct fixup_replacement **, rtx));
static void fixup_var_refs_insns PROTO((rtx, enum machine_mode, int,
- rtx, int));
+ rtx, int, struct hash_table *));
static void fixup_var_refs_1 PROTO((rtx, enum machine_mode, rtx *, rtx,
struct fixup_replacement **));
static rtx fixup_memory_subreg PROTO((rtx, rtx, int));
@@ -452,8 +511,17 @@ static int all_blocks PROTO((tree, tree *));
static int *record_insns PROTO((rtx));
static int contains PROTO((rtx, int *));
#endif /* HAVE_prologue || HAVE_epilogue */
-static void put_addressof_into_stack PROTO((rtx));
-static void purge_addressof_1 PROTO((rtx *, rtx, int));
+static void put_addressof_into_stack PROTO((rtx, struct hash_table *));
+static void purge_addressof_1 PROTO((rtx *, rtx, int, int,
+ struct hash_table *));
+static struct hash_entry *insns_for_mem_newfunc PROTO((struct hash_entry *,
+ struct hash_table *,
+ hash_table_key));
+static unsigned long insns_for_mem_hash PROTO ((hash_table_key));
+static boolean insns_for_mem_comp PROTO ((hash_table_key, hash_table_key));
+static int insns_for_mem_walk PROTO ((rtx *, void *));
+static void compute_insns_for_mem PROTO ((rtx, rtx, struct hash_table *));
+
/* Pointer to chain of `struct function' for containing functions. */
struct function *outer_function_chain;
@@ -501,6 +569,7 @@ push_function_context_to (context)
p->has_nonlocal_label = current_function_has_nonlocal_label;
p->has_nonlocal_goto = current_function_has_nonlocal_goto;
p->contains_functions = current_function_contains_functions;
+ p->has_computed_jump = current_function_has_computed_jump;
p->is_thunk = current_function_is_thunk;
p->args_size = current_function_args_size;
p->pretend_args_size = current_function_pretend_args_size;
@@ -515,7 +584,8 @@ push_function_context_to (context)
p->parm_reg_stack_loc = parm_reg_stack_loc;
p->outgoing_args_size = current_function_outgoing_args_size;
p->return_rtx = current_function_return_rtx;
- p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;
+ p->nonlocal_goto_handler_slots = nonlocal_goto_handler_slots;
+ p->nonlocal_goto_handler_labels = nonlocal_goto_handler_labels;
p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;
p->nonlocal_labels = nonlocal_labels;
p->cleanup_label = cleanup_label;
@@ -539,6 +609,8 @@ push_function_context_to (context)
p->fixup_var_refs_queue = 0;
p->epilogue_delay_list = current_function_epilogue_delay_list;
p->args_info = current_function_args_info;
+ p->check_memory_usage = current_function_check_memory_usage;
+ p->instrument_entry_exit = current_function_instrument_entry_exit;
save_tree_status (p, context);
save_storage_status (p);
@@ -571,6 +643,7 @@ pop_function_context_from (context)
current_function_contains_functions
= p->contains_functions || p->inline_obstacks
|| context == current_function_decl;
+ current_function_has_computed_jump = p->has_computed_jump;
current_function_name = p->name;
current_function_decl = p->decl;
current_function_pops_args = p->pops_args;
@@ -597,7 +670,8 @@ pop_function_context_from (context)
parm_reg_stack_loc = p->parm_reg_stack_loc;
current_function_outgoing_args_size = p->outgoing_args_size;
current_function_return_rtx = p->return_rtx;
- nonlocal_goto_handler_slot = p->nonlocal_goto_handler_slot;
+ nonlocal_goto_handler_slots = p->nonlocal_goto_handler_slots;
+ nonlocal_goto_handler_labels = p->nonlocal_goto_handler_labels;
nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;
nonlocal_labels = p->nonlocal_labels;
cleanup_label = p->cleanup_label;
@@ -621,6 +695,8 @@ pop_function_context_from (context)
current_function_epilogue_delay_list = p->epilogue_delay_list;
reg_renumber = 0;
current_function_args_info = p->args_info;
+ current_function_check_memory_usage = p->check_memory_usage;
+ current_function_instrument_entry_exit = p->instrument_entry_exit;
restore_tree_status (p, context);
restore_storage_status (p);
@@ -635,7 +711,8 @@ pop_function_context_from (context)
/* Finish doing put_var_into_stack for any of our variables
which became addressable during the nested function. */
for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
- fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);
+ fixup_var_refs (queue->modified, queue->promoted_mode,
+ queue->unsignedp, 0);
free (p);
@@ -652,7 +729,7 @@ void pop_function_context ()
/* Allocate fixed slots in the stack frame of the current function. */
/* Return size needed for stack frame based on slots so far allocated.
- This size counts from zero. It is not rounded to STACK_BOUNDARY;
+ This size counts from zero. It is not rounded to PREFERRED_STACK_BOUNDARY;
the caller may have to do that. */
HOST_WIDE_INT
@@ -687,9 +764,19 @@ assign_stack_local (mode, size, align)
if (align == 0)
{
- alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
+ tree type;
+
+ alignment = GET_MODE_ALIGNMENT (mode);
if (mode == BLKmode)
- alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ alignment = BIGGEST_ALIGNMENT;
+
+ /* Allow the target to (possibly) increase the alignment of this
+ stack slot. */
+ type = type_for_mode (mode, 0);
+ if (type)
+ alignment = LOCAL_ALIGNMENT (type, alignment);
+
+ alignment /= BITS_PER_UNIT;
}
else if (align == -1)
{
@@ -699,6 +786,10 @@ assign_stack_local (mode, size, align)
else
alignment = align / BITS_PER_UNIT;
+#ifdef FRAME_GROWS_DOWNWARD
+ frame_offset -= size;
+#endif
+
/* Round frame offset to that alignment.
We must be careful here, since FRAME_OFFSET might be negative and
division with a negative dividend isn't as well defined as we might
@@ -715,10 +806,6 @@ assign_stack_local (mode, size, align)
if (BYTES_BIG_ENDIAN && mode != BLKmode)
bigend_correction = size - GET_MODE_SIZE (mode);
-#ifdef FRAME_GROWS_DOWNWARD
- frame_offset -= size;
-#endif
-
/* If we have already instantiated virtual registers, return the actual
address relative to the frame pointer. */
if (virtuals_instantiated)
@@ -762,9 +849,19 @@ assign_outer_stack_local (mode, size, align, function)
if (align == 0)
{
- alignment = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
+ tree type;
+
+ alignment = GET_MODE_ALIGNMENT (mode);
if (mode == BLKmode)
- alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ alignment = BIGGEST_ALIGNMENT;
+
+ /* Allow the target to (possibly) increase the alignment of this
+ stack slot. */
+ type = type_for_mode (mode, 0);
+ if (type)
+ alignment = LOCAL_ALIGNMENT (type, alignment);
+
+ alignment /= BITS_PER_UNIT;
}
else if (align == -1)
{
@@ -774,6 +871,10 @@ assign_outer_stack_local (mode, size, align, function)
else
alignment = align / BITS_PER_UNIT;
+#ifdef FRAME_GROWS_DOWNWARD
+ function->frame_offset -= size;
+#endif
+
/* Round frame offset to that alignment. */
#ifdef FRAME_GROWS_DOWNWARD
function->frame_offset = FLOOR_ROUND (function->frame_offset, alignment);
@@ -786,9 +887,6 @@ assign_outer_stack_local (mode, size, align, function)
if (BYTES_BIG_ENDIAN && mode != BLKmode)
bigend_correction = size - GET_MODE_SIZE (mode);
-#ifdef FRAME_GROWS_DOWNWARD
- function->frame_offset -= size;
-#endif
addr = plus_constant (virtual_stack_vars_rtx,
function->frame_offset + bigend_correction);
#ifndef FRAME_GROWS_DOWNWARD
@@ -818,14 +916,19 @@ assign_outer_stack_local (mode, size, align, function)
with this flag. KEEP is 2 if we allocate a longer term temporary,
whose lifetime is controlled by CLEANUP_POINT_EXPRs. KEEP is 3
if we are to allocate something at an inner level to be treated as
- a variable in the block (e.g., a SAVE_EXPR). */
+ a variable in the block (e.g., a SAVE_EXPR).
-rtx
-assign_stack_temp (mode, size, keep)
+ TYPE is the type that will be used for the stack slot. */
+
+static rtx
+assign_stack_temp_for_type (mode, size, keep, type)
enum machine_mode mode;
HOST_WIDE_INT size;
int keep;
+ tree type;
{
+ int align;
+ int alias_set;
struct temp_slot *p, *best_p = 0;
/* If SIZE is -1 it means that somebody tried to allocate a temporary
@@ -833,19 +936,41 @@ assign_stack_temp (mode, size, keep)
if (size == -1)
abort ();
- /* First try to find an available, already-allocated temporary that is the
- exact size we require. */
+ /* If we know the alias set for the memory that will be used, use
+ it. If there's no TYPE, then we don't know anything about the
+ alias set for the memory. */
+ if (type)
+ alias_set = get_alias_set (type);
+ else
+ alias_set = 0;
+
+ align = GET_MODE_ALIGNMENT (mode);
+ if (mode == BLKmode)
+ align = BIGGEST_ALIGNMENT;
+
+ if (! type)
+ type = type_for_mode (mode, 0);
+ if (type)
+ align = LOCAL_ALIGNMENT (type, align);
+
+ /* Try to find an available, already-allocated temporary of the proper
+ mode which meets the size and alignment requirements. Choose the
+ smallest one with the closest alignment. */
for (p = temp_slots; p; p = p->next)
- if (p->size == size && GET_MODE (p->slot) == mode && ! p->in_use)
- break;
-
- /* If we didn't find, one, try one that is larger than what we want. We
- find the smallest such. */
- if (p == 0)
- for (p = temp_slots; p; p = p->next)
- if (p->size > size && GET_MODE (p->slot) == mode && ! p->in_use
- && (best_p == 0 || best_p->size > p->size))
+ if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode
+ && ! p->in_use
+ && (!flag_strict_aliasing
+ || (alias_set && p->alias_set == alias_set))
+ && (best_p == 0 || best_p->size > p->size
+ || (best_p->size == p->size && best_p->align > p->align)))
+ {
+ if (p->align == align && p->size == size)
+ {
+ best_p = 0;
+ break;
+ }
best_p = p;
+ }
/* Make our best, if any, the one to use. */
if (best_p)
@@ -853,9 +978,13 @@ assign_stack_temp (mode, size, keep)
/* If there are enough aligned bytes left over, make them into a new
temp_slot so that the extra bytes don't get wasted. Do this only
for BLKmode slots, so that we can be sure of the alignment. */
- if (GET_MODE (best_p->slot) == BLKmode)
+ if (GET_MODE (best_p->slot) == BLKmode
+ /* We can't split slots if -fstrict-aliasing because the
+ information about the alias set for the new slot will be
+ lost. */
+ && !flag_strict_aliasing)
{
- int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ int alignment = best_p->align / BITS_PER_UNIT;
HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment);
if (best_p->size - rounded_size >= alignment)
@@ -868,6 +997,7 @@ assign_stack_temp (mode, size, keep)
p->slot = gen_rtx_MEM (BLKmode,
plus_constant (XEXP (best_p->slot, 0),
rounded_size));
+ p->align = best_p->align;
p->address = 0;
p->rtl_expr = 0;
p->next = temp_slots;
@@ -891,9 +1021,22 @@ assign_stack_temp (mode, size, keep)
p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
- /* If the temp slot mode doesn't indicate the alignment,
- use the largest possible, so no one will be disappointed. */
- p->slot = assign_stack_local (mode, size, mode == BLKmode ? -1 : 0);
+ /* We are passing an explicit alignment request to assign_stack_local.
+ One side effect of that is assign_stack_local will not round SIZE
+ to ensure the frame offset remains suitably aligned.
+
+ So for requests which depended on the rounding of SIZE, we go ahead
+ and round it now. We also make sure ALIGNMENT is at least
+ BIGGEST_ALIGNMENT. */
+ if (mode == BLKmode && align < (BIGGEST_ALIGNMENT / BITS_PER_UNIT))
+ abort();
+ p->slot = assign_stack_local (mode,
+ mode == BLKmode
+ ? CEIL_ROUND (size, align) : size,
+ align);
+
+ p->align = align;
+ p->alias_set = alias_set;
/* The following slot size computation is necessary because we don't
know the actual size of the temporary slot until assign_stack_local
@@ -945,8 +1088,22 @@ assign_stack_temp (mode, size, keep)
set from before. */
RTX_UNCHANGING_P (p->slot) = 0;
MEM_IN_STRUCT_P (p->slot) = 0;
+ MEM_SCALAR_P (p->slot) = 0;
+ MEM_ALIAS_SET (p->slot) = 0;
return p->slot;
}
+
+/* Allocate a temporary stack slot and record it for possible later
+ reuse. First three arguments are same as in preceding function. */
+
+rtx
+assign_stack_temp (mode, size, keep)
+ enum machine_mode mode;
+ HOST_WIDE_INT size;
+ int keep;
+{
+ return assign_stack_temp_for_type (mode, size, keep, NULL_TREE);
+}
/* Assign a temporary of given TYPE.
KEEP is as for assign_stack_temp.
@@ -979,8 +1136,8 @@ assign_temp (type, keep, memory_required, dont_promote)
&& TREE_CODE (TYPE_ARRAY_MAX_SIZE (type)) == INTEGER_CST)
size = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type));
- tmp = assign_stack_temp (mode, size, keep);
- MEM_IN_STRUCT_P (tmp) = AGGREGATE_TYPE_P (type);
+ tmp = assign_stack_temp_for_type (mode, size, keep, type);
+ MEM_SET_IN_STRUCT_P (tmp, AGGREGATE_TYPE_P (type));
return tmp;
}
@@ -1005,6 +1162,11 @@ combine_temp_slots ()
struct temp_slot *prev_p, *prev_q;
int num_slots;
+ /* We can't combine slots, because the information about which slot
+ is in which alias set will be lost. */
+ if (flag_strict_aliasing)
+ return;
+
/* If there are a lot of temp slots, don't do anything unless
high levels of optimizaton. */
if (! flag_expensive_optimizations)
@@ -1437,8 +1599,8 @@ put_var_into_stack (decl)
put_reg_into_stack (function, reg, TREE_TYPE (decl),
promoted_mode, decl_mode,
TREE_SIDE_EFFECTS (decl), 0,
- TREE_USED (decl)
- || DECL_INITIAL (decl) != 0);
+ TREE_USED (decl) || DECL_INITIAL (decl) != 0,
+ 0);
}
else if (GET_CODE (reg) == CONCAT)
{
@@ -1450,17 +1612,21 @@ put_var_into_stack (decl)
/* Since part 0 should have a lower address, do it second. */
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
- TREE_USED (decl) || DECL_INITIAL (decl) != 0);
+ TREE_USED (decl) || DECL_INITIAL (decl) != 0,
+ 0);
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
- TREE_USED (decl) || DECL_INITIAL (decl) != 0);
+ TREE_USED (decl) || DECL_INITIAL (decl) != 0,
+ 0);
#else
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
- TREE_USED (decl) || DECL_INITIAL (decl) != 0);
+ TREE_USED (decl) || DECL_INITIAL (decl) != 0,
+ 0);
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
part_mode, TREE_SIDE_EFFECTS (decl), 0,
- TREE_USED (decl) || DECL_INITIAL (decl) != 0);
+ TREE_USED (decl) || DECL_INITIAL (decl) != 0,
+ 0);
#endif
/* Change the CONCAT into a combined MEM for both parts. */
@@ -1478,9 +1644,9 @@ put_var_into_stack (decl)
else
return;
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- XEXP (reg, 0), ptr_mode,
+ XEXP (reg, 0), Pmode,
GEN_INT (GET_MODE_SIZE (GET_MODE (reg))),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
@@ -1496,7 +1662,7 @@ put_var_into_stack (decl)
static void
put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
- original_regno, used_p)
+ original_regno, used_p, ht)
struct function *function;
rtx reg;
tree type;
@@ -1504,6 +1670,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
int volatile_p;
int original_regno;
int used_p;
+ struct hash_table *ht;
{
rtx new = 0;
int regno = original_regno;
@@ -1538,7 +1705,8 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
previously generated stack slot, then we need to copy the bit in
case it was set for other reasons. For instance, it is set for
__builtin_va_alist. */
- MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type) | MEM_IN_STRUCT_P (new);
+ MEM_SET_IN_STRUCT_P (reg,
+ AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
MEM_ALIAS_SET (reg) = get_alias_set (type);
/* Now make sure that all refs to the variable, previously made
@@ -1565,14 +1733,15 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
}
else if (used_p)
/* Variable is local; fix it up now. */
- fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type));
+ fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (type), ht);
}
static void
-fixup_var_refs (var, promoted_mode, unsignedp)
+fixup_var_refs (var, promoted_mode, unsignedp, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
+ struct hash_table *ht;
{
tree pending;
rtx first_insn = get_insns ();
@@ -1580,14 +1749,18 @@ fixup_var_refs (var, promoted_mode, unsignedp)
tree rtl_exps = rtl_expr_chain;
/* Must scan all insns for stack-refs that exceed the limit. */
- fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0);
+ fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn,
+ stack == 0, ht);
+ /* If there's a hash table, it must record all uses of VAR. */
+ if (ht)
+ return;
/* Scan all pending sequences too. */
for (; stack; stack = stack->next)
{
push_to_sequence (stack->first);
fixup_var_refs_insns (var, promoted_mode, unsignedp,
- stack->first, stack->next != 0);
+ stack->first, stack->next != 0, 0);
/* Update remembered end of sequence
in case we added an insn at the end. */
stack->last = get_last_insn ();
@@ -1601,10 +1774,17 @@ fixup_var_refs (var, promoted_mode, unsignedp)
if (seq != const0_rtx && seq != 0)
{
push_to_sequence (seq);
- fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0);
+ fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0,
+ 0);
end_sequence ();
}
}
+
+ /* Scan the catch clauses for exception handling too. */
+ push_to_sequence (catch_clauses);
+ fixup_var_refs_insns (var, promoted_mode, unsignedp, catch_clauses,
+ 0, 0);
+ end_sequence ();
}
/* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
@@ -1639,14 +1819,26 @@ find_fixup_replacement (replacements, x)
main chain of insns for the current function. */
static void
-fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
+fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
rtx insn;
int toplevel;
+ struct hash_table *ht;
{
rtx call_dest = 0;
+ rtx insn_list = NULL_RTX;
+
+ /* If we already know which INSNs reference VAR there's no need
+ to walk the entire instruction chain. */
+ if (ht)
+ {
+ insn_list = ((struct insns_for_mem_entry *)
+ hash_lookup (ht, var, /*create=*/0, /*copy=*/0))->insns;
+ insn = insn_list ? XEXP (insn_list, 0) : NULL_RTX;
+ insn_list = XEXP (insn_list, 1);
+ }
while (insn)
{
@@ -1819,7 +2011,16 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
XEXP (note, 0)
= walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
}
- insn = next;
+
+ if (!ht)
+ insn = next;
+ else if (insn_list)
+ {
+ insn = XEXP (insn_list, 0);
+ insn_list = XEXP (insn_list, 1);
+ }
+ else
+ insn = NULL_RTX;
}
}
@@ -1857,18 +2058,45 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
/* Prevent sharing of rtl that might lose. */
rtx sub = copy_rtx (XEXP (var, 0));
- start_sequence ();
-
if (! validate_change (insn, loc, sub, 0))
{
- rtx y = force_operand (sub, NULL_RTX);
+ rtx y = gen_reg_rtx (GET_MODE (sub));
+ rtx seq, new_insn;
- if (! validate_change (insn, loc, y, 0))
- *loc = copy_to_reg (y);
- }
+ /* We should be able to replace with a register or all is lost.
+ Note that we can't use validate_change to verify this, since
+ we're not caring for replacing all dups simultaneously. */
+ if (! validate_replace_rtx (*loc, y, insn))
+ abort ();
- emit_insn_before (gen_sequence (), insn);
- end_sequence ();
+ /* Careful! First try to recognize a direct move of the
+ value, mimicking how things are done in gen_reload wrt
+ PLUS. Consider what happens when insn is a conditional
+ move instruction and addsi3 clobbers flags. */
+
+ start_sequence ();
+ new_insn = emit_insn (gen_rtx_SET (VOIDmode, y, sub));
+ seq = gen_sequence ();
+ end_sequence ();
+
+ if (recog_memoized (new_insn) < 0)
+ {
+ /* That failed. Fall back on force_operand and hope. */
+
+ start_sequence ();
+ force_operand (sub, y);
+ seq = gen_sequence ();
+ end_sequence ();
+ }
+
+#ifdef HAVE_cc0
+ /* Don't separate setter from user. */
+ if (PREV_INSN (insn) && sets_cc0_p (PREV_INSN (insn)))
+ insn = PREV_INSN (insn);
+#endif
+
+ emit_insn_before (seq, insn);
+ }
}
return;
@@ -1969,11 +2197,19 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
#ifdef HAVE_extzv
if (GET_CODE (x) == ZERO_EXTRACT)
- wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
+ {
+ wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
+ if (wanted_mode == VOIDmode)
+ wanted_mode = word_mode;
+ }
#endif
#ifdef HAVE_extv
if (GET_CODE (x) == SIGN_EXTRACT)
- wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
+ {
+ wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
+ if (wanted_mode == VOIDmode)
+ wanted_mode = word_mode;
+ }
#endif
/* If we have a narrower mode, we can do something. */
if (wanted_mode != VOIDmode
@@ -1994,8 +2230,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
newmem = gen_rtx_MEM (wanted_mode,
plus_constant (XEXP (tem, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
+ MEM_COPY_ATTRIBUTES (newmem, tem);
/* Make the change and see if the insn remains valid. */
INSN_CODE (insn) = -1;
@@ -2162,11 +2397,14 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
&& ! mode_dependent_address_p (XEXP (tem, 0))
&& ! MEM_VOLATILE_P (tem))
{
- enum machine_mode wanted_mode
- = insn_operand_mode[(int) CODE_FOR_insv][0];
+ enum machine_mode wanted_mode;
enum machine_mode is_mode = GET_MODE (tem);
HOST_WIDE_INT pos = INTVAL (XEXP (outerdest, 2));
+ wanted_mode = insn_operand_mode[(int) CODE_FOR_insv][0];
+ if (wanted_mode == VOIDmode)
+ wanted_mode = word_mode;
+
/* If we have a narrower mode, we can do something. */
if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
{
@@ -2183,8 +2421,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
newmem = gen_rtx_MEM (wanted_mode,
plus_constant (XEXP (tem, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);
+ MEM_COPY_ATTRIBUTES (newmem, tem);
/* Make the change and see if the insn remains valid. */
INSN_CODE (insn) = -1;
@@ -2635,7 +2872,9 @@ optimize_bit_field (body, insn, equiv_mem)
while (GET_CODE (dest) == SUBREG
&& SUBREG_WORD (dest) == 0
&& (GET_MODE_CLASS (GET_MODE (dest))
- == GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest)))))
+ == GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest))))
+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
+ <= UNITS_PER_WORD))
dest = SUBREG_REG (dest);
validate_change (insn, &SET_DEST (body), dest, 1);
@@ -2682,6 +2921,7 @@ static int in_arg_offset;
static int var_offset;
static int dynamic_offset;
static int out_arg_offset;
+static int cfa_offset;
/* In most machines, the stack pointer register is equivalent to the bottom
of the stack. */
@@ -2720,6 +2960,13 @@ static int out_arg_offset;
#endif
#endif
+/* On a few machines, the CFA coincides with the arg pointer. */
+
+#ifndef ARG_POINTER_CFA_OFFSET
+#define ARG_POINTER_CFA_OFFSET 0
+#endif
+
+
/* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just had
its address taken. DECL is the decl for the object stored in the
register, for later use if we do need to force REG into the stack.
@@ -2731,19 +2978,21 @@ gen_mem_addressof (reg, decl)
tree decl;
{
tree type = TREE_TYPE (decl);
-
rtx r = gen_rtx_ADDRESSOF (Pmode, gen_reg_rtx (GET_MODE (reg)), REGNO (reg));
SET_ADDRESSOF_DECL (r, decl);
+ /* If the original REG was a user-variable, then so is the REG whose
+ address is being taken. */
+ REG_USERVAR_P (XEXP (r, 0)) = REG_USERVAR_P (reg);
XEXP (reg, 0) = r;
PUT_CODE (reg, MEM);
PUT_MODE (reg, DECL_MODE (decl));
MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
- MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (reg, AGGREGATE_TYPE_P (type));
MEM_ALIAS_SET (reg) = get_alias_set (decl);
if (TREE_USED (decl) || DECL_INITIAL (decl) != 0)
- fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type));
+ fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), 0);
return reg;
}
@@ -2759,14 +3008,15 @@ flush_addressof (decl)
&& GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
- put_addressof_into_stack (XEXP (DECL_RTL (decl), 0));
+ put_addressof_into_stack (XEXP (DECL_RTL (decl), 0), 0);
}
/* Force the register pointed to by R, an ADDRESSOF rtx, into the stack. */
static void
-put_addressof_into_stack (r)
+put_addressof_into_stack (r, ht)
rtx r;
+ struct hash_table *ht;
{
tree decl = ADDRESSOF_DECL (r);
rtx reg = XEXP (r, 0);
@@ -2777,18 +3027,31 @@ put_addressof_into_stack (r)
put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg),
DECL_MODE (decl), TREE_SIDE_EFFECTS (decl),
ADDRESSOF_REGNO (r),
- TREE_USED (decl) || DECL_INITIAL (decl) != 0);
+ TREE_USED (decl) || DECL_INITIAL (decl) != 0, ht);
}
+/* List of replacements made below in purge_addressof_1 when creating
+ bitfield insertions. */
+static rtx purge_bitfield_addressof_replacements;
+
+/* List of replacements made below in purge_addressof_1 for patterns
+ (MEM (ADDRESSOF (REG ...))). The key of the list entry is the
+ corresponding (ADDRESSOF (REG ...)) and value is a substitution for
+ the all pattern. List PURGE_BITFIELD_ADDRESSOF_REPLACEMENTS is not
+ enough in complex cases, e.g. when some field values can be
+ extracted by usage MEM with narrower mode. */
+static rtx purge_addressof_replacements;
+
/* Helper function for purge_addressof. See if the rtx expression at *LOC
in INSN needs to be changed. If FORCE, always put any ADDRESSOFs into
the stack. */
static void
-purge_addressof_1 (loc, insn, force)
+purge_addressof_1 (loc, insn, force, store, ht)
rtx *loc;
rtx insn;
- int force;
+ int force, store;
+ struct hash_table *ht;
{
rtx x;
RTX_CODE code;
@@ -2811,49 +3074,232 @@ purge_addressof_1 (loc, insn, force)
overwriting a REG rtx which is always shared. */
rtx sub = copy_rtx (XEXP (XEXP (x, 0), 0));
- if (validate_change (insn, loc, sub, 0))
+ if (validate_change (insn, loc, sub, 0)
+ || validate_replace_rtx (x, sub, insn))
return;
-
+
start_sequence ();
- if (! validate_change (insn, loc,
- force_operand (sub, NULL_RTX),
- 0))
+ sub = force_operand (sub, NULL_RTX);
+ if (! validate_change (insn, loc, sub, 0)
+ && ! validate_replace_rtx (x, sub, insn))
abort ();
- insns = get_insns ();
+ insns = gen_sequence ();
end_sequence ();
- emit_insns_before (insns, insn);
+ emit_insn_before (insns, insn);
return;
}
else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force)
{
rtx sub = XEXP (XEXP (x, 0), 0);
+ rtx sub2;
if (GET_CODE (sub) == MEM)
- sub = gen_rtx_MEM (GET_MODE (x), copy_rtx (XEXP (sub, 0)));
+ {
+ sub2 = gen_rtx_MEM (GET_MODE (x), copy_rtx (XEXP (sub, 0)));
+ MEM_COPY_ATTRIBUTES (sub2, sub);
+ RTX_UNCHANGING_P (sub2) = RTX_UNCHANGING_P (sub);
+ sub = sub2;
+ }
if (GET_CODE (sub) == REG
&& (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
{
- put_addressof_into_stack (XEXP (x, 0));
+ put_addressof_into_stack (XEXP (x, 0), ht);
return;
}
else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
{
- if (! BYTES_BIG_ENDIAN && ! WORDS_BIG_ENDIAN)
+ int size_x, size_sub;
+
+ if (!insn)
{
- rtx sub2 = gen_rtx_SUBREG (GET_MODE (x), sub, 0);
- if (validate_change (insn, loc, sub2, 0))
- goto restart;
+ /* When processing REG_NOTES look at the list of
+ replacements done on the insn to find the register that X
+ was replaced by. */
+ rtx tem;
+
+ for (tem = purge_bitfield_addressof_replacements;
+ tem != NULL_RTX;
+ tem = XEXP (XEXP (tem, 1), 1))
+ if (rtx_equal_p (x, XEXP (tem, 0)))
+ {
+ *loc = XEXP (XEXP (tem, 1), 0);
+ return;
+ }
+
+ /* See comment for purge_addressof_replacements. */
+ for (tem = purge_addressof_replacements;
+ tem != NULL_RTX;
+ tem = XEXP (XEXP (tem, 1), 1))
+ if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
+ {
+ rtx z = XEXP (XEXP (tem, 1), 0);
+
+ if (GET_MODE (x) == GET_MODE (z)
+ || (GET_CODE (XEXP (XEXP (tem, 1), 0)) != REG
+ && GET_CODE (XEXP (XEXP (tem, 1), 0)) != SUBREG))
+ abort ();
+
+ /* It can happen that the note may speak of things
+ in a wider (or just different) mode than the
+ code did. This is especially true of
+ REG_RETVAL. */
+
+ if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
+ z = SUBREG_REG (z);
+
+ if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (x))
+ > GET_MODE_SIZE (GET_MODE (z))))
+ {
+ /* This can occur as a result in invalid
+ pointer casts, e.g. float f; ...
+ *(long long int *)&f.
+ ??? We could emit a warning here, but
+ without a line number that wouldn't be
+ very helpful. */
+ z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
+ }
+ else
+ z = gen_lowpart (GET_MODE (x), z);
+
+ *loc = z;
+ return;
+ }
+
+ /* There should always be such a replacement. */
+ abort ();
+ }
+
+ size_x = GET_MODE_BITSIZE (GET_MODE (x));
+ size_sub = GET_MODE_BITSIZE (GET_MODE (sub));
+
+ /* Don't even consider working with paradoxical subregs,
+ or the moral equivalent seen here. */
+ if (size_x <= size_sub
+ && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
+ {
+ /* Do a bitfield insertion to mirror what would happen
+ in memory. */
+
+ rtx val, seq;
+
+ if (store)
+ {
+ rtx p = PREV_INSN (insn);
+
+ start_sequence ();
+ val = gen_reg_rtx (GET_MODE (x));
+ if (! validate_change (insn, loc, val, 0))
+ {
+ /* Discard the current sequence and put the
+ ADDRESSOF on stack. */
+ end_sequence ();
+ goto give_up;
+ }
+ seq = gen_sequence ();
+ end_sequence ();
+ emit_insn_before (seq, insn);
+ compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
+ insn, ht);
+
+ start_sequence ();
+ store_bit_field (sub, size_x, 0, GET_MODE (x),
+ val, GET_MODE_SIZE (GET_MODE (sub)),
+ GET_MODE_SIZE (GET_MODE (sub)));
+
+ /* Make sure to unshare any shared rtl that store_bit_field
+ might have created. */
+ for (p = get_insns(); p; p = NEXT_INSN (p))
+ {
+ reset_used_flags (PATTERN (p));
+ reset_used_flags (REG_NOTES (p));
+ reset_used_flags (LOG_LINKS (p));
+ }
+ unshare_all_rtl (get_insns ());
+
+ seq = gen_sequence ();
+ end_sequence ();
+ p = emit_insn_after (seq, insn);
+ if (NEXT_INSN (insn))
+ compute_insns_for_mem (NEXT_INSN (insn),
+ p ? NEXT_INSN (p) : NULL_RTX,
+ ht);
+ }
+ else
+ {
+ rtx p = PREV_INSN (insn);
+
+ start_sequence ();
+ val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX,
+ GET_MODE (x), GET_MODE (x),
+ GET_MODE_SIZE (GET_MODE (sub)),
+ GET_MODE_SIZE (GET_MODE (sub)));
+
+ if (! validate_change (insn, loc, val, 0))
+ {
+ /* Discard the current sequence and put the
+ ADDRESSOF on stack. */
+ end_sequence ();
+ goto give_up;
+ }
+
+ seq = gen_sequence ();
+ end_sequence ();
+ emit_insn_before (seq, insn);
+ compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
+ insn, ht);
+ }
+
+ /* Remember the replacement so that the same one can be done
+ on the REG_NOTES. */
+ purge_bitfield_addressof_replacements
+ = gen_rtx_EXPR_LIST (VOIDmode, x,
+ gen_rtx_EXPR_LIST
+ (VOIDmode, val,
+ purge_bitfield_addressof_replacements));
+
+ /* We replaced with a reg -- all done. */
+ return;
}
}
else if (validate_change (insn, loc, sub, 0))
- goto restart;
+ {
+ /* Remember the replacement so that the same one can be done
+ on the REG_NOTES. */
+ if (GET_CODE (sub) == REG || GET_CODE (sub) == SUBREG)
+ {
+ rtx tem;
+
+ for (tem = purge_addressof_replacements;
+ tem != NULL_RTX;
+ tem = XEXP (XEXP (tem, 1), 1))
+ if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
+ {
+ XEXP (XEXP (tem, 1), 0) = sub;
+ return;
+ }
+ purge_addressof_replacements
+ = gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0),
+ gen_rtx_EXPR_LIST (VOIDmode, sub,
+ purge_addressof_replacements));
+ return;
+ }
+ goto restart;
+ }
+ give_up:;
/* else give up and put it into the stack */
}
else if (code == ADDRESSOF)
{
- put_addressof_into_stack (x);
+ put_addressof_into_stack (x, ht);
+ return;
+ }
+ else if (code == SET)
+ {
+ purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht);
+ purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht);
return;
}
@@ -2862,11 +3308,128 @@ purge_addressof_1 (loc, insn, force)
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
{
if (*fmt == 'e')
- purge_addressof_1 (&XEXP (x, i), insn, force);
+ purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht);
else if (*fmt == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
- purge_addressof_1 (&XVECEXP (x, i, j), insn, force);
+ purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht);
+ }
+}
+
+/* Return a new hash table entry in HT. */
+
+static struct hash_entry *
+insns_for_mem_newfunc (he, ht, k)
+ struct hash_entry *he;
+ struct hash_table *ht;
+ hash_table_key k ATTRIBUTE_UNUSED;
+{
+ struct insns_for_mem_entry *ifmhe;
+ if (he)
+ return he;
+
+ ifmhe = ((struct insns_for_mem_entry *)
+ hash_allocate (ht, sizeof (struct insns_for_mem_entry)));
+ ifmhe->insns = NULL_RTX;
+
+ return &ifmhe->he;
+}
+
+/* Return a hash value for K, a REG. */
+
+static unsigned long
+insns_for_mem_hash (k)
+ hash_table_key k;
+{
+ /* K is really a RTX. Just use the address as the hash value. */
+ return (unsigned long) k;
+}
+
+/* Return non-zero if K1 and K2 (two REGs) are the same. */
+
+static boolean
+insns_for_mem_comp (k1, k2)
+ hash_table_key k1;
+ hash_table_key k2;
+{
+ return k1 == k2;
+}
+
+struct insns_for_mem_walk_info {
+ /* The hash table that we are using to record which INSNs use which
+ MEMs. */
+ struct hash_table *ht;
+
+ /* The INSN we are currently proessing. */
+ rtx insn;
+
+ /* Zero if we are walking to find ADDRESSOFs, one if we are walking
+ to find the insns that use the REGs in the ADDRESSOFs. */
+ int pass;
+};
+
+/* Called from compute_insns_for_mem via for_each_rtx. If R is a REG
+ that might be used in an ADDRESSOF expression, record this INSN in
+ the hash table given by DATA (which is really a pointer to an
+ insns_for_mem_walk_info structure). */
+
+static int
+insns_for_mem_walk (r, data)
+ rtx *r;
+ void *data;
+{
+ struct insns_for_mem_walk_info *ifmwi
+ = (struct insns_for_mem_walk_info *) data;
+
+ if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF
+ && GET_CODE (XEXP (*r, 0)) == REG)
+ hash_lookup (ifmwi->ht, XEXP (*r, 0), /*create=*/1, /*copy=*/0);
+ else if (ifmwi->pass == 1 && *r && GET_CODE (*r) == REG)
+ {
+ /* Lookup this MEM in the hashtable, creating it if necessary. */
+ struct insns_for_mem_entry *ifme
+ = (struct insns_for_mem_entry *) hash_lookup (ifmwi->ht,
+ *r,
+ /*create=*/0,
+ /*copy=*/0);
+
+ /* If we have not already recorded this INSN, do so now. Since
+ we process the INSNs in order, we know that if we have
+ recorded it it must be at the front of the list. */
+ if (ifme && (!ifme->insns || XEXP (ifme->insns, 0) != ifmwi->insn))
+ {
+ /* We do the allocation on the same obstack as is used for
+ the hash table since this memory will not be used once
+ the hash table is deallocated. */
+ push_obstacks (&ifmwi->ht->memory, &ifmwi->ht->memory);
+ ifme->insns = gen_rtx_EXPR_LIST (VOIDmode, ifmwi->insn,
+ ifme->insns);
+ pop_obstacks ();
+ }
}
+
+ return 0;
+}
+
+/* Walk the INSNS, until we reach LAST_INSN, recording which INSNs use
+ which REGs in HT. */
+
+static void
+compute_insns_for_mem (insns, last_insn, ht)
+ rtx insns;
+ rtx last_insn;
+ struct hash_table *ht;
+{
+ rtx insn;
+ struct insns_for_mem_walk_info ifmwi;
+ ifmwi.ht = ht;
+
+ for (ifmwi.pass = 0; ifmwi.pass < 2; ++ifmwi.pass)
+ for (insn = insns; insn != last_insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ ifmwi.insn = insn;
+ for_each_rtx (&insn, insns_for_mem_walk, &ifmwi);
+ }
}
/* Eliminate all occurrences of ADDRESSOF from INSNS. Elide any remaining
@@ -2878,14 +3441,34 @@ purge_addressof (insns)
rtx insns;
{
rtx insn;
+ struct hash_table ht;
+
+ /* When we actually purge ADDRESSOFs, we turn REGs into MEMs. That
+ requires a fixup pass over the instruction stream to correct
+ INSNs that depended on the REG being a REG, and not a MEM. But,
+ these fixup passes are slow. Furthermore, more MEMs are not
+ mentioned in very many instructions. So, we speed up the process
+ by pre-calculating which REGs occur in which INSNs; that allows
+ us to perform the fixup passes much more quickly. */
+ hash_table_init (&ht,
+ insns_for_mem_newfunc,
+ insns_for_mem_hash,
+ insns_for_mem_comp);
+ compute_insns_for_mem (insns, NULL_RTX, &ht);
+
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN)
{
purge_addressof_1 (&PATTERN (insn), insn,
- asm_noperands (PATTERN (insn)) > 0);
- purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0);
+ asm_noperands (PATTERN (insn)) > 0, 0, &ht);
+ purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, &ht);
}
+
+ /* Clean up. */
+ hash_table_free (&ht);
+ purge_bitfield_addressof_replacements = 0;
+ purge_addressof_replacements = 0;
}
/* Pass through the INSNS of function FNDECL and convert virtual register
@@ -2904,6 +3487,7 @@ instantiate_virtual_regs (fndecl, insns)
var_offset = STARTING_FRAME_OFFSET;
dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);
out_arg_offset = STACK_POINTER_OFFSET;
+ cfa_offset = ARG_POINTER_CFA_OFFSET;
/* Scan all variables and parameters of this function. For each that is
in memory, instantiate all virtual registers if the result is a valid
@@ -3093,7 +3677,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
rtx x;
RTX_CODE code;
rtx new = 0;
- HOST_WIDE_INT offset;
+ HOST_WIDE_INT offset = 0;
rtx temp;
rtx seq;
int i, j;
@@ -3137,6 +3721,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
new = stack_pointer_rtx, offset = - dynamic_offset;
else if (SET_DEST (x) == virtual_outgoing_args_rtx)
new = stack_pointer_rtx, offset = - out_arg_offset;
+ else if (SET_DEST (x) == virtual_cfa_rtx)
+ new = arg_pointer_rtx, offset = - cfa_offset;
if (new)
{
@@ -3188,6 +3774,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
new = stack_pointer_rtx, offset = dynamic_offset;
else if (inner == virtual_outgoing_args_rtx)
new = stack_pointer_rtx, offset = out_arg_offset;
+ else if (inner == virtual_cfa_rtx)
+ new = arg_pointer_rtx, offset = cfa_offset;
else
{
loc = &XEXP (x, 0);
@@ -3207,6 +3795,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
new = stack_pointer_rtx, offset = dynamic_offset;
else if (XEXP (x, 0) == virtual_outgoing_args_rtx)
new = stack_pointer_rtx, offset = out_arg_offset;
+ else if (XEXP (x, 0) == virtual_cfa_rtx)
+ new = arg_pointer_rtx, offset = cfa_offset;
else
{
/* We know the second operand is a constant. Unless the
@@ -3414,6 +4004,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
new = stack_pointer_rtx, offset = dynamic_offset;
else if (x == virtual_outgoing_args_rtx)
new = stack_pointer_rtx, offset = out_arg_offset;
+ else if (x == virtual_cfa_rtx)
+ new = arg_pointer_rtx, offset = cfa_offset;
if (new)
{
@@ -3506,30 +4098,24 @@ delete_handlers ()
TREE_CHAIN (last_t) = TREE_CHAIN (t);
}
}
- if (GET_CODE (insn) == INSN
- && ((nonlocal_goto_handler_slot != 0
- && reg_mentioned_p (nonlocal_goto_handler_slot, PATTERN (insn)))
+ if (GET_CODE (insn) == INSN)
+ {
+ int can_delete = 0;
+ rtx t;
+ for (t = nonlocal_goto_handler_slots; t != 0; t = XEXP (t, 1))
+ if (reg_mentioned_p (t, PATTERN (insn)))
+ {
+ can_delete = 1;
+ break;
+ }
+ if (can_delete
|| (nonlocal_goto_stack_level != 0
&& reg_mentioned_p (nonlocal_goto_stack_level,
- PATTERN (insn)))))
- delete_insn (insn);
+ PATTERN (insn))))
+ delete_insn (insn);
+ }
}
}
-
-/* Return a list (chain of EXPR_LIST nodes) for the nonlocal labels
- of the current function. */
-
-rtx
-nonlocal_label_rtx_list ()
-{
- tree t;
- rtx x = 0;
-
- for (t = nonlocal_labels; t; t = TREE_CHAIN (t))
- x = gen_rtx_EXPR_LIST (VOIDmode, label_rtx (TREE_VALUE (t)), x);
-
- return x;
-}
/* Output a USE for any register use in RTL.
This is used with -noreg to mark the extent of lifespan
@@ -3679,7 +4265,9 @@ assign_parms (fndecl, second_time)
/* This is a dummy PARM_DECL that we used for the function result if
the function returns a structure. */
tree function_result_decl = 0;
+#ifdef SETUP_INCOMING_VARARGS
int varargs_setup = 0;
+#endif
rtx conversion_insns = 0;
/* Nonzero if the last arg is named `__builtin_va_alist',
@@ -3759,6 +4347,7 @@ assign_parms (fndecl, second_time)
int did_conversion = 0;
tree passed_type = DECL_ARG_TYPE (parm);
tree nominal_type = TREE_TYPE (parm);
+ int pretend_named;
/* Set LAST_NAMED if this is last named arg before some
anonymous args. */
@@ -3880,6 +4469,7 @@ assign_parms (fndecl, second_time)
In this case, we call FUNCTION_ARG with NAMED set to 1 instead of
0 as it was the previous time. */
+ pretend_named = named_arg || PRETEND_OUTGOING_VARARGS_NAMED;
locate_and_pad_parm (promoted_mode, passed_type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
1,
@@ -3887,12 +4477,11 @@ assign_parms (fndecl, second_time)
#ifdef FUNCTION_INCOMING_ARG
FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
passed_type,
- (named_arg
- || varargs_setup)) != 0,
+ pretend_named) != 0,
#else
FUNCTION_ARG (args_so_far, promoted_mode,
passed_type,
- named_arg || varargs_setup) != 0,
+ pretend_named) != 0,
#endif
#endif
fndecl, &stack_args_size, &stack_offset, &arg_size);
@@ -3912,7 +4501,7 @@ assign_parms (fndecl, second_time)
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. Likewise if it
is readonly. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
MEM_ALIAS_SET (stack_parm) = get_alias_set (parm);
}
@@ -3976,6 +4565,8 @@ assign_parms (fndecl, second_time)
to indicate there is no preallocated stack slot for the parm. */
if (entry_parm == stack_parm
+ || (GET_CODE (entry_parm) == PARALLEL
+ && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX)
#if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
/* On some machines, even if a parm value arrives in a register
there is still an (uninitialized) stack slot allocated for it.
@@ -4052,7 +4643,7 @@ assign_parms (fndecl, second_time)
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
}
#endif /* 0 */
@@ -4109,7 +4700,7 @@ assign_parms (fndecl, second_time)
/* If this is a memory ref that contains aggregate
components, mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
}
else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
@@ -4166,7 +4757,7 @@ assign_parms (fndecl, second_time)
{
DECL_RTL (parm)
= gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), parmreg);
- MEM_IN_STRUCT_P (DECL_RTL (parm)) = aggregate;
+ MEM_SET_IN_STRUCT_P (DECL_RTL (parm), aggregate);
}
else
DECL_RTL (parm) = parmreg;
@@ -4175,6 +4766,7 @@ assign_parms (fndecl, second_time)
if (nominal_mode != passed_mode
|| promoted_nominal_mode != promoted_mode)
{
+ int save_tree_used;
/* ENTRY_PARM has been converted to PROMOTED_MODE, its
mode, by the caller. We now have to convert it to
NOMINAL_MODE, if different. However, PARMREG may be in
@@ -4201,8 +4793,11 @@ assign_parms (fndecl, second_time)
push_to_sequence (conversion_insns);
tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp);
+ /* TREE_USED gets set erroneously during expand_assignment. */
+ save_tree_used = TREE_USED (parm);
expand_assignment (parm,
make_tree (nominal_type, tempreg), 0, 0);
+ TREE_USED (parm) = save_tree_used;
conversion_insns = get_insns ();
did_conversion = 1;
end_sequence ();
@@ -4267,14 +4862,14 @@ assign_parms (fndecl, second_time)
else
copy = assign_stack_temp (TYPE_MODE (type),
int_size_in_bytes (type), 1);
- MEM_IN_STRUCT_P (copy) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
RTX_UNCHANGING_P (copy) = TREE_READONLY (parm);
store_expr (parm, copy, 0);
emit_move_insn (parmreg, XEXP (copy, 0));
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- XEXP (copy, 0), ptr_mode,
+ XEXP (copy, 0), Pmode,
GEN_INT (int_size_in_bytes (type)),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
@@ -4422,7 +5017,7 @@ assign_parms (fndecl, second_time)
GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
}
if (promoted_mode != nominal_mode)
@@ -4437,11 +5032,11 @@ assign_parms (fndecl, second_time)
emit_move_insn (validize_mem (stack_parm),
validize_mem (entry_parm));
}
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
{
push_to_sequence (conversion_insns);
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- XEXP (stack_parm, 0), ptr_mode,
+ XEXP (stack_parm, 0), Pmode,
GEN_INT (GET_MODE_SIZE (GET_MODE
(entry_parm))),
TYPE_MODE (sizetype),
@@ -4464,7 +5059,8 @@ assign_parms (fndecl, second_time)
DECL_RTL (result)
= gen_rtx_MEM (DECL_MODE (result), DECL_RTL (parm));
- MEM_IN_STRUCT_P (DECL_RTL (result)) = AGGREGATE_TYPE_P (restype);
+ MEM_SET_IN_STRUCT_P (DECL_RTL (result),
+ AGGREGATE_TYPE_P (restype));
}
if (TREE_THIS_VOLATILE (parm))
@@ -4604,7 +5200,7 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
enum machine_mode passed_mode;
tree type;
int in_regs;
- tree fndecl;
+ tree fndecl ATTRIBUTE_UNUSED;
struct args_size *initial_offset_ptr;
struct args_size *offset_ptr;
struct args_size *arg_size_ptr;
@@ -4798,6 +5394,14 @@ uninitialized_vars_warning (block)
&& ! AGGREGATE_TYPE_P (TREE_TYPE (decl))
&& DECL_RTL (decl) != 0
&& GET_CODE (DECL_RTL (decl)) == REG
+ /* Global optimizations can make it difficult to determine if a
+ particular variable has been initialized. However, a VAR_DECL
+ with a nonzero DECL_INITIAL had an initializer, so do not
+ claim it is potentially uninitialized.
+
+ We do not care about the actual value in DECL_INITIAL, so we do
+ not worry that it may be a dangling pointer. */
+ && DECL_INITIAL (decl) == NULL_TREE
&& regno_uninitialized (REGNO (DECL_RTL (decl))))
warning_with_decl (decl,
"`%s' might be used uninitialized in this function");
@@ -5286,11 +5890,12 @@ init_function_start (subr, filename, line)
stack_slot_list = 0;
/* There is no stack slot for handling nonlocal gotos. */
- nonlocal_goto_handler_slot = 0;
+ nonlocal_goto_handler_slots = 0;
nonlocal_goto_stack_level = 0;
/* No labels have been declared for nonlocal use. */
nonlocal_labels = 0;
+ nonlocal_goto_handler_labels = 0;
/* No function calls so far in this function. */
function_call_count = 0;
@@ -5329,6 +5934,10 @@ init_function_start (subr, filename, line)
current_function_has_nonlocal_label = 0;
current_function_has_nonlocal_goto = 0;
current_function_contains_functions = 0;
+ current_function_is_leaf = 0;
+ current_function_sp_is_unchanging = 0;
+ current_function_uses_only_leaf_regs = 0;
+ current_function_has_computed_jump = 0;
current_function_is_thunk = 0;
current_function_returns_pcc_struct = 0;
@@ -5458,6 +6067,15 @@ expand_function_start (subr, parms_have_cleanups)
valid operands of arithmetic insns. */
init_recog_no_volatile ();
+ /* Set this before generating any memory accesses. */
+ current_function_check_memory_usage
+ = (flag_check_memory_usage
+ && ! DECL_NO_CHECK_MEMORY_USAGE (current_function_decl));
+
+ current_function_instrument_entry_exit
+ = (flag_instrument_function_entry_exit
+ && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
+
/* If function gets a static chain arg, store it in the stack frame.
Do this first, so it gets the first stack slot offset. */
if (current_function_needs_context)
@@ -5484,6 +6102,7 @@ expand_function_start (subr, parms_have_cleanups)
or if it returns a structure, or if it has parm cleanups. */
#ifdef HAVE_return
if (cleanup_label == 0 && HAVE_return
+ && ! current_function_instrument_entry_exit
&& ! current_function_returns_pcc_struct
&& ! (current_function_returns_struct && ! optimize))
return_label = 0;
@@ -5525,14 +6144,16 @@ expand_function_start (subr, parms_have_cleanups)
{
DECL_RTL (DECL_RESULT (subr))
= gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), value_address);
- MEM_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)))
- = AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)),
+ AGGREGATE_TYPE_P (TREE_TYPE
+ (DECL_RESULT
+ (subr))));
}
}
else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
/* If return mode is void, this decl rtl should not be used. */
DECL_RTL (DECL_RESULT (subr)) = 0;
- else if (parms_have_cleanups)
+ else if (parms_have_cleanups || current_function_instrument_entry_exit)
{
/* If function will end with cleanup code for parms,
compute the return values into a pseudo reg,
@@ -5650,6 +6271,21 @@ expand_function_start (subr, parms_have_cleanups)
}
}
+ if (current_function_instrument_entry_exit)
+ {
+ rtx fun = DECL_RTL (current_function_decl);
+ if (GET_CODE (fun) == MEM)
+ fun = XEXP (fun, 0);
+ else
+ abort ();
+ emit_library_call (profile_function_entry_libfunc, 0, VOIDmode, 2,
+ fun, Pmode,
+ expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+ 0,
+ hard_frame_pointer_rtx),
+ Pmode);
+ }
+
/* After the display initializations is where the tail-recursion label
should go, if we end up needing one. Ensure we have a NOTE here
since some things (like trampolines) get placed before this. */
@@ -5703,8 +6339,15 @@ expand_function_end (filename, line, end_bindings)
/* Save the argument pointer if a save area was made for it. */
if (arg_pointer_save_area)
{
- rtx x = gen_move_insn (arg_pointer_save_area, virtual_incoming_args_rtx);
- emit_insn_before (x, tail_recursion_reentry);
+ /* arg_pointer_save_area may not be a valid memory address, so we
+ have to check it and fix it if necessary. */
+ rtx seq;
+ start_sequence ();
+ emit_move_insn (validize_mem (arg_pointer_save_area),
+ virtual_incoming_args_rtx);
+ seq = gen_sequence ();
+ end_sequence ();
+ emit_insn_before (seq, tail_recursion_reentry);
}
/* Initialize any trampolines required by this function. */
@@ -5780,7 +6423,8 @@ expand_function_end (filename, line, end_bindings)
}
/* Delete handlers for nonlocal gotos if nothing uses them. */
- if (nonlocal_goto_handler_slot != 0 && !current_function_has_nonlocal_label)
+ if (nonlocal_goto_handler_slots != 0
+ && ! current_function_has_nonlocal_label)
delete_handlers ();
/* End any sequences that failed to be closed due to syntax errors. */
@@ -5863,6 +6507,21 @@ expand_function_end (filename, line, end_bindings)
}
}
+ if (current_function_instrument_entry_exit)
+ {
+ rtx fun = DECL_RTL (current_function_decl);
+ if (GET_CODE (fun) == MEM)
+ fun = XEXP (fun, 0);
+ else
+ abort ();
+ emit_library_call (profile_function_exit_libfunc, 0, VOIDmode, 2,
+ fun, Pmode,
+ expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+ 0,
+ hard_frame_pointer_rtx),
+ Pmode);
+ }
+
/* If we had calls to alloca, and this machine needs
an accurate stack pointer to exit the function,
insert some code to save and restore the stack pointer. */
@@ -5940,6 +6599,10 @@ expand_function_end (filename, line, end_bindings)
use_variable (outgoing);
}
+ /* If this is an implementation of __throw, do what's necessary to
+ communicate between __builtin_eh_return and the epilogue. */
+ expand_eh_return ();
+
/* Output a return insn if we are using one.
Otherwise, let the rtl chain end here, to drop through
into the epilogue. */
@@ -6029,100 +6692,172 @@ contains (insn, vec)
void
thread_prologue_and_epilogue_insns (f)
- rtx f;
+ rtx f ATTRIBUTE_UNUSED;
{
+ int insertted = 0;
+
+ prologue = 0;
#ifdef HAVE_prologue
if (HAVE_prologue)
{
- rtx head, seq;
-
- /* The first insn (a NOTE_INSN_DELETED) is followed by zero or more
- prologue insns and a NOTE_INSN_PROLOGUE_END. */
- emit_note_after (NOTE_INSN_PROLOGUE_END, f);
- seq = gen_prologue ();
- head = emit_insn_after (seq, f);
+ rtx seq;
- /* Include the new prologue insns in the first block. Ignore them
- if they form a basic block unto themselves. */
- if (basic_block_head && n_basic_blocks
- && GET_CODE (basic_block_head[0]) != CODE_LABEL)
- basic_block_head[0] = NEXT_INSN (f);
+ start_sequence ();
+ seq = gen_prologue();
+ emit_insn (seq);
/* Retain a map of the prologue insns. */
- prologue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : head);
+ if (GET_CODE (seq) != SEQUENCE)
+ seq = get_insns ();
+ prologue = record_insns (seq);
+
+ emit_note (NULL, NOTE_INSN_PROLOGUE_END);
+ seq = gen_sequence ();
+ end_sequence ();
+
+ /* If optimization is off, and perhaps in an empty function,
+ the entry block will have no successors. */
+ if (ENTRY_BLOCK_PTR->succ)
+ {
+ /* Can't deal with multiple successsors of the entry block. */
+ if (ENTRY_BLOCK_PTR->succ->succ_next)
+ abort ();
+
+ insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ);
+ insertted = 1;
+ }
+ else
+ emit_insn_after (seq, f);
}
- else
#endif
- prologue = 0;
+ epilogue = 0;
#ifdef HAVE_epilogue
if (HAVE_epilogue)
{
- rtx insn = get_last_insn ();
- rtx prev = prev_nonnote_insn (insn);
+ edge e;
+ basic_block bb = 0;
+ rtx tail = get_last_insn ();
+
+ /* ??? This is gastly. If function returns were not done via uses,
+ but via mark_regs_live_at_end, we could use insert_insn_on_edge
+ and all of this uglyness would go away. */
- /* If we end with a BARRIER, we don't need an epilogue. */
- if (! (prev && GET_CODE (prev) == BARRIER))
+ switch (optimize)
{
- rtx tail, seq, tem;
- rtx first_use = 0;
- rtx last_use = 0;
-
- /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
- epilogue insns, the USE insns at the end of a function,
- the jump insn that returns, and then a BARRIER. */
-
- /* Move the USE insns at the end of a function onto a list. */
- while (prev
- && GET_CODE (prev) == INSN
- && GET_CODE (PATTERN (prev)) == USE)
- {
- tem = prev;
+ default:
+ /* If the exit block has no non-fake predecessors, we don't
+ need an epilogue. Furthermore, only pay attention to the
+ fallthru predecessors; if (conditional) return insns were
+ generated, by definition we do not need to emit epilogue
+ insns. */
+
+ for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+ if ((e->flags & EDGE_FAKE) == 0
+ && (e->flags & EDGE_FALLTHRU) != 0)
+ break;
+ if (e == NULL)
+ break;
+
+ /* We can't handle multiple epilogues -- if one is needed,
+ we won't be able to place it multiple times.
+
+ ??? Fix epilogue expanders to not assume they are the
+ last thing done compiling the function. Either that
+ or copy_rtx each insn.
+
+ ??? Blah, it's not a simple expression to assert that
+ we've exactly one fallthru exit edge. */
+
+ bb = e->src;
+ tail = bb->end;
+
+ /* ??? If the last insn of the basic block is a jump, then we
+ are creating a new basic block. Wimp out and leave these
+ insns outside any block. */
+ if (GET_CODE (tail) == JUMP_INSN)
+ bb = 0;
+
+ /* FALLTHRU */
+ case 0:
+ {
+ rtx prev, seq, first_use;
+
+ /* Move the USE insns at the end of a function onto a list. */
+ prev = tail;
+ if (GET_CODE (prev) == BARRIER
+ || GET_CODE (prev) == NOTE)
prev = prev_nonnote_insn (prev);
- NEXT_INSN (PREV_INSN (tem)) = NEXT_INSN (tem);
- PREV_INSN (NEXT_INSN (tem)) = PREV_INSN (tem);
- if (first_use)
- {
- NEXT_INSN (tem) = first_use;
- PREV_INSN (first_use) = tem;
- }
- first_use = tem;
- if (!last_use)
- last_use = tem;
- }
+ first_use = 0;
+ if (prev
+ && GET_CODE (prev) == INSN
+ && GET_CODE (PATTERN (prev)) == USE)
+ {
+ /* If the end of the block is the use, grab hold of something
+ else so that we emit barriers etc in the right place. */
+ if (prev == tail)
+ {
+ do
+ tail = PREV_INSN (tail);
+ while (GET_CODE (tail) == INSN
+ && GET_CODE (PATTERN (tail)) == USE);
+ }
- emit_barrier_after (insn);
+ do
+ {
+ rtx use = prev;
+ prev = prev_nonnote_insn (prev);
+
+ remove_insn (use);
+ if (first_use)
+ {
+ NEXT_INSN (use) = first_use;
+ PREV_INSN (first_use) = use;
+ }
+ else
+ NEXT_INSN (use) = NULL_RTX;
+ first_use = use;
+ }
+ while (prev
+ && GET_CODE (prev) == INSN
+ && GET_CODE (PATTERN (prev)) == USE);
+ }
- seq = gen_epilogue ();
- tail = emit_jump_insn_after (seq, insn);
+ /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
+ epilogue insns, the USE insns at the end of a function,
+ the jump insn that returns, and then a BARRIER. */
- /* Insert the USE insns immediately before the return insn, which
- must be the first instruction before the final barrier. */
- if (first_use)
- {
- tem = prev_nonnote_insn (get_last_insn ());
- NEXT_INSN (PREV_INSN (tem)) = first_use;
- PREV_INSN (first_use) = PREV_INSN (tem);
- PREV_INSN (tem) = last_use;
- NEXT_INSN (last_use) = tem;
- }
+ if (GET_CODE (tail) != BARRIER)
+ {
+ prev = next_nonnote_insn (tail);
+ if (!prev || GET_CODE (prev) != BARRIER)
+ emit_barrier_after (tail);
+ }
- emit_note_after (NOTE_INSN_EPILOGUE_BEG, insn);
+ seq = gen_epilogue ();
+ prev = tail;
+ tail = emit_jump_insn_after (seq, tail);
- /* Include the new epilogue insns in the last block. Ignore
- them if they form a basic block unto themselves. */
- if (basic_block_end && n_basic_blocks
- && GET_CODE (basic_block_end[n_basic_blocks - 1]) != JUMP_INSN)
- basic_block_end[n_basic_blocks - 1] = tail;
+ /* Insert the USE insns immediately before the return insn, which
+ must be the last instruction emitted in the sequence. */
+ if (first_use)
+ emit_insns_before (first_use, tail);
+ emit_note_after (NOTE_INSN_EPILOGUE_BEG, prev);
- /* Retain a map of the epilogue insns. */
- epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
- return;
+ /* Update the tail of the basic block. */
+ if (bb)
+ bb->end = tail;
+
+ /* Retain a map of the epilogue insns. */
+ epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
+ }
}
}
#endif
- epilogue = 0;
+
+ if (insertted)
+ commit_edge_insertions ();
}
/* Reposition the prologue-end and epilogue-begin notes after instruction
@@ -6130,13 +6865,12 @@ thread_prologue_and_epilogue_insns (f)
void
reposition_prologue_and_epilogue_notes (f)
- rtx f;
+ rtx f ATTRIBUTE_UNUSED;
{
#if defined (HAVE_prologue) || defined (HAVE_epilogue)
/* Reposition the prologue and epilogue notes. */
if (n_basic_blocks)
{
- rtx next, prev;
int len;
if (prologue)
@@ -6157,6 +6891,7 @@ reposition_prologue_and_epilogue_notes (f)
}
else if ((len -= contains (insn, prologue)) == 0)
{
+ rtx next;
/* Find the prologue-end note if we haven't already, and
move it to just after the last prologue insn. */
if (note == 0)
@@ -6166,12 +6901,15 @@ reposition_prologue_and_epilogue_notes (f)
&& NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
break;
}
+
next = NEXT_INSN (note);
- prev = PREV_INSN (note);
- if (prev)
- NEXT_INSN (prev) = next;
- if (next)
- PREV_INSN (next) = prev;
+
+ /* Whether or not we can depend on BLOCK_HEAD,
+ attempt to keep it up-to-date. */
+ if (BLOCK_HEAD (0) == note)
+ BLOCK_HEAD (0) = next;
+
+ remove_insn (note);
add_insn_after (note, insn);
}
}
@@ -6204,13 +6942,15 @@ reposition_prologue_and_epilogue_notes (f)
&& NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
break;
}
- next = NEXT_INSN (note);
- prev = PREV_INSN (note);
- if (prev)
- NEXT_INSN (prev) = next;
- if (next)
- PREV_INSN (next) = prev;
- add_insn_after (note, PREV_INSN (insn));
+
+ /* Whether or not we can depend on BLOCK_HEAD,
+ attempt to keep it up-to-date. */
+ if (n_basic_blocks
+ && BLOCK_HEAD (n_basic_blocks-1) == insn)
+ BLOCK_HEAD (n_basic_blocks-1) = note;
+
+ remove_insn (note);
+ add_insn_before (note, insn);
}
}
}
diff --git a/contrib/gcc/function.h b/contrib/gcc/function.h
index 0382a4e..c25933c 100644
--- a/contrib/gcc/function.h
+++ b/contrib/gcc/function.h
@@ -80,8 +80,10 @@ struct function
int has_nonlocal_label;
int has_nonlocal_goto;
int contains_functions;
+ int has_computed_jump;
int is_thunk;
- rtx nonlocal_goto_handler_slot;
+ rtx nonlocal_goto_handler_slots;
+ rtx nonlocal_goto_handler_labels;
rtx nonlocal_goto_stack_level;
tree nonlocal_labels;
int args_size;
@@ -113,6 +115,7 @@ struct function
int temp_slot_level;
int target_temp_slot_level;
int var_temp_slot_level;
+ int instrument_entry_exit;
/* This slot is initialized as 0 and is added to
during the nested function. */
struct var_refs_queue *fixup_var_refs_queue;
@@ -143,6 +146,7 @@ struct function
struct label_node *caught_return_label_stack;
tree protect_list;
rtx ehc;
+ rtx eh_return_stub_label;
/* For expr.c. */
rtx pending_chain;
@@ -151,6 +155,7 @@ struct function
rtx saveregs_value;
rtx apply_args_value;
rtx forced_labels;
+ int check_memory_usage;
/* For emit-rtl.c. */
int reg_rtx_no;
@@ -212,11 +217,40 @@ struct function
/* The FUNCTION_DECL for an inline function currently being expanded. */
extern tree inline_function_decl;
+/* Label that will go on parm cleanup code, if any.
+ Jumping to this label runs cleanup code for parameters, if
+ such code must be run. Following this code is the logical return label. */
+
+extern rtx cleanup_label;
+
/* Label that will go on function epilogue.
Jumping to this label serves as a "return" instruction
on machines which require execution of the epilogue on all returns. */
+
extern rtx return_label;
+/* Offset to end of allocated area of stack frame.
+ If stack grows down, this is the address of the last stack slot allocated.
+ If stack grows up, this is the address for the next slot. */
+extern HOST_WIDE_INT frame_offset;
+
+/* Label to jump back to for tail recursion, or 0 if we have
+ not yet needed one for this function. */
+extern rtx tail_recursion_label;
+
+/* Place after which to insert the tail_recursion_label if we need one. */
+extern rtx tail_recursion_reentry;
+
+/* Location at which to save the argument pointer if it will need to be
+ referenced. There are two cases where this is done: if nonlocal gotos
+ exist, or if vars whose is an offset from the argument pointer will be
+ needed by inner routines. */
+
+extern rtx arg_pointer_save_area;
+
+/* Chain of all RTL_EXPRs that have insns in them. */
+extern tree rtl_expr_chain;
+
/* List (chain of EXPR_LISTs) of all stack slots in this function.
Made for the sake of unshare_all_rtl. */
extern rtx stack_slot_list;
diff --git a/contrib/gcc/gansidecl.h b/contrib/gcc/gansidecl.h
index 4f4bb42..cf7762f 100644
--- a/contrib/gcc/gansidecl.h
+++ b/contrib/gcc/gansidecl.h
@@ -1,5 +1,5 @@
/* ANSI and traditional C compatibility macros.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,38 +22,51 @@ Boston, MA 02111-1307, USA. */
in binutils and gdb releases.
??? Over time the two should be merged into one. */
-#ifndef ANSIDECL_H
-#define ANSIDECL_H
-
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
-#ifndef VPROTO
-#ifdef __STDC__
-#define PVPROTO(ARGS) ARGS
-#define VPROTO(ARGS) ARGS
-#define VA_START(va_list,var) va_start(va_list,var)
-#else
-#define PVPROTO(ARGS) ()
-#define VPROTO(ARGS) (va_alist) va_dcl
-#define VA_START(va_list,var) va_start(va_list)
-#endif
-#endif
+#ifndef __GANSIDECL_H__
+#define __GANSIDECL_H__
+
+#include "ansidecl.h"
+
+/* Undef ansidecl.h's "obsolete" version. */
+#undef PROTO
+/* These macros are deprecated, use ansidecl.h's PARAMS style instead. */
+#define PROTO(ARGS) PARAMS(ARGS)
+#define VPROTO(ARGS) VPARAMS(ARGS)
+#define PVPROTO(ARGS) PARAMS(ARGS)
+
+/* Autoconf will possibly define the `inline' or `const' keywords as
+ macros, however this is only valid for the stage1 compiler. If we
+ detect a modern version of gcc, unconditionally reset the values.
+ This makes sure the right thing happens in stage2 and later. We
+ need to do this very early; i.e. before any systems header files or
+ gcc header files in case they use these keywords. Otherwise
+ conflicts might occur. */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+# undef const
+# undef inline
+# define inline __inline__ /* Modern gcc can use `__inline__' freely. */
+#endif /* GCC >= 2.7 */
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __attribute__(x)
#endif
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 93)
+# define ATTRIBUTE_UNUSED_LABEL
+# else
+# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# endif /* GNUC < 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif /* ATTRIBUTE_UNUSED */
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
#ifndef ATTRIBUTE_PRINTF
#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((format (__printf__, m, n)))
#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
@@ -63,29 +76,10 @@ Boston, MA 02111-1307, USA. */
#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
#endif /* ATTRIBUTE_PRINTF */
-#ifndef GENERIC_PTR
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define GENERIC_PTR void *
-#else
-#define GENERIC_PTR char *
-#endif
-#endif
+#define GENERIC_PTR PTR
#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR) 0)
-#endif
-
-#ifdef __STDC__
-
-#define PTR void *
-
-#else
-
-#define PTR char *
-#ifndef const
-#define const
+#define NULL_PTR ((PTR) 0)
#endif
-#endif /* ! __STDC__ */
-
-#endif /* ANSIDECL_H */
+#endif /* __GANSIDECL_H__ */
diff --git a/contrib/gcc/gcc.1 b/contrib/gcc/gcc.1
index c0cf44a..74200a1 100644
--- a/contrib/gcc/gcc.1
+++ b/contrib/gcc/gcc.1
@@ -20,10 +20,10 @@
.if n .sp
.if t .sp 0.4
..
-.Id $Id: gcc.1,v 1.8 1998/08/29 10:37:47 law Exp $
+.Id $Id: gcc.1,v 1.9 1998/12/16 20:55:57 law Exp $
.TH GCC 1 "\*(Dt" "GNU Tools" "GNU Tools"
.SH NAME
-gcc, g++ \- GNU project C and C++ Compiler (egcs-1.1.2)
+gcc, g++ \- GNU project C and C++ Compiler (gcc-2.95)
.SH SYNOPSIS
.B gcc
.RI "[ " option " | " filename " ].\|.\|."
diff --git a/contrib/gcc/gcc.c b/contrib/gcc/gcc.c
index 06a688f..ea9f6ac 100644
--- a/contrib/gcc/gcc.c
+++ b/contrib/gcc/gcc.c
@@ -1,5 +1,5 @@
/* Compiler driver program that can handle many languages.
- Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -32,63 +32,17 @@ Once it knows which kind of compilation to perform, the procedure for
compilation is specified by a string called a "spec". */
#include "config.h"
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include <signal.h>
-#include <sys/stat.h>
-#include "gansidecl.h"
#include "obstack.h"
-
-
-/* ??? Need to find a GCC header to put these in. */
-extern int pexecute PROTO ((const char *, char * const *, const char *,
- const char *, char **, char **, int));
-extern int pwait PROTO ((int, int *, int));
-extern char *update_path PROTO((char *, char *));
-extern void set_std_prefix PROTO((char *, int));
-/* Flag arguments to pexecute. */
-#define PEXECUTE_FIRST 1
-#define PEXECUTE_LAST 2
-#define PEXECUTE_SEARCH 4
-#define PEXECUTE_VERBOSE 8
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(S) ((S) & 0x7f)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(S) (((S) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
-#endif
+#include "intl.h"
+#include "prefix.h"
#ifdef VMS
#define exit __posix_exit
#endif
-#ifdef USG
-#define vfork fork
-#endif /* USG */
-
-/* Test if something is a normal file. */
-#ifndef S_ISREG
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-/* Test if something is a directory. */
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
/* By default there is no special suffix for executables. */
#ifdef EXECUTABLE_SUFFIX
#define HAVE_EXECUTABLE_SUFFIX
@@ -112,17 +66,23 @@ extern void set_std_prefix PROTO((char *, int));
#define DIR_SEPARATOR '/'
#endif
+/* Define IS_DIR_SEPARATOR. */
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
static char dir_separator_str[] = {DIR_SEPARATOR, 0};
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
-extern char *my_strerror PROTO((int));
-
#ifndef HAVE_KILL
#define kill(p,s) raise(s)
#endif
@@ -140,11 +100,11 @@ static int print_search_dirs;
/* Flag saying to print the full filename of this file
as found through our usual search mechanism. */
-static char *print_file_name = NULL;
+static const char *print_file_name = NULL;
/* As print_file_name, but search for executable file. */
-static char *print_prog_name = NULL;
+static const char *print_prog_name = NULL;
/* Flag saying to print the relative path we'd use to
find libgcc.a given the current compiler flags. */
@@ -180,7 +140,7 @@ static char *spec_version = DEFAULT_TARGET_VERSION;
/* The target machine specified with -b. */
-static char *spec_machine = DEFAULT_TARGET_MACHINE;
+static const char *spec_machine = DEFAULT_TARGET_MACHINE;
/* Nonzero if cross-compiling.
When -b is used, the value comes from the `specs' file. */
@@ -212,56 +172,63 @@ extern char *version_string;
struct path_prefix;
static void init_spec PROTO((void));
-static void read_specs PROTO((char *, int));
-static void set_spec PROTO((char *, char *));
-static struct compiler *lookup_compiler PROTO((char *, size_t, char *));
-static char *build_search_list PROTO((struct path_prefix *, char *, int));
-static void putenv_from_prefixes PROTO((struct path_prefix *, char *));
-static char *find_a_file PROTO((struct path_prefix *, char *, int));
-static void add_prefix PROTO((struct path_prefix *, char *, char *,
- int, int, int *));
+static void read_specs PROTO((const char *, int));
+static void set_spec PROTO((const char *, const char *));
+static struct compiler *lookup_compiler PROTO((const char *, size_t, const char *));
+static char *build_search_list PROTO((struct path_prefix *, const char *, int));
+static void putenv_from_prefixes PROTO((struct path_prefix *, const char *));
+static char *find_a_file PROTO((struct path_prefix *, const char *, int));
+static void add_prefix PROTO((struct path_prefix *, const char *,
+ const char *, int, int, int *));
static char *skip_whitespace PROTO((char *));
-static void record_temp_file PROTO((char *, int, int));
-static void delete_if_ordinary PROTO((char *));
+static void record_temp_file PROTO((const char *, int, int));
+static void delete_if_ordinary PROTO((const char *));
static void delete_temp_files PROTO((void));
static void delete_failure_queue PROTO((void));
static void clear_failure_queue PROTO((void));
static int check_live_switch PROTO((int, int));
-static char *handle_braces PROTO((char *));
-static char *save_string PROTO((char *, int));
-static char *concat PVPROTO((char *, ...));
-extern int do_spec PROTO((char *));
-static int do_spec_1 PROTO((char *, int, char *));
-static char *find_file PROTO((char *));
-static int is_directory PROTO((char *, char *, int));
-static void validate_switches PROTO((char *));
+static const char *handle_braces PROTO((const char *));
+static char *save_string PROTO((const char *, int));
+extern int do_spec PROTO((const char *));
+static int do_spec_1 PROTO((const char *, int, const char *));
+static const char *find_file PROTO((const char *));
+static int is_directory PROTO((const char *, const char *, int));
+static void validate_switches PROTO((const char *));
static void validate_all_switches PROTO((void));
static void give_switch PROTO((int, int, int));
-static int used_arg PROTO((char *, int));
-static int default_arg PROTO((char *, int));
+static int used_arg PROTO((const char *, int));
+static int default_arg PROTO((const char *, int));
static void set_multilib_dir PROTO((void));
static void print_multilib_info PROTO((void));
-static void pfatal_with_name PROTO((char *));
-static void perror_with_name PROTO((char *));
-static void pfatal_pexecute PROTO((char *, char *));
-static void fatal PVPROTO((char *, ...));
-static void error PVPROTO((char *, ...));
+static void pfatal_with_name PROTO((const char *)) ATTRIBUTE_NORETURN;
+static void perror_with_name PROTO((const char *));
+static void pfatal_pexecute PROTO((const char *, const char *))
+ ATTRIBUTE_NORETURN;
+static void error PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
+static void notice PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
static void display_help PROTO((void));
+static void add_preprocessor_option PROTO ((const char *, int));
+static void add_assembler_option PROTO ((const char *, int));
+static void add_linker_option PROTO ((const char *, int));
+static void process_command PROTO ((int, char **));
+static int execute PROTO ((void));
+static void unused_prefix_warnings PROTO ((struct path_prefix *));
+static void clear_args PROTO ((void));
+static void fatal_error PROTO ((int));
-void fancy_abort ();
-char *xmalloc ();
-char *xrealloc ();
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
-#ifdef LANG_SPECIFIC_DRIVER
/* Called before processing to change/add/remove arguments. */
-extern void lang_specific_driver PROTO ((void (*) PVPROTO((char *, ...)), int *, char ***, int *));
+extern void lang_specific_driver PROTO ((void (*) PVPROTO((const char *, ...)),
+ int *, char ***, int *));
/* Called before linking. Returns 0 on success and -1 on failure. */
extern int lang_specific_pre_link ();
/* Number of extra output files that lang_specific_pre_link may generate. */
extern int lang_specific_extra_outfiles;
-#endif
/* Specs are strings containing lines, each of which (if not blank)
is made up of a program name, and arguments separated by spaces.
@@ -537,7 +504,7 @@ static char *multilib_defaults_raw[] = MULTILIB_DEFAULTS;
struct user_specs {
struct user_specs *next;
- char *filename;
+ const char *filename;
};
static struct user_specs *user_specs_head, *user_specs_tail;
@@ -585,10 +552,10 @@ static struct user_specs *user_specs_head, *user_specs_tail;
struct compiler
{
- char *suffix; /* Use this compiler for input files
+ const char *suffix; /* Use this compiler for input files
whose names end in this suffix. */
- char *spec[4]; /* To use this compiler, concatenate these
+ const char *spec[4]; /* To use this compiler, concatenate these
specs and pass to do_spec. */
};
@@ -615,8 +582,10 @@ static struct compiler default_compilers[] =
were not present when we built the driver, we will hit these copies
and be given a more meaningful error than "file not used since
linking is not done". */
- {".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}}, {".c++", {"#C++"}},
- {".C", {"#C++"}}, {".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}},
+ {".m", {"#Objective-C"}},
+ {".cc", {"#C++"}}, {".cxx", {"#C++"}}, {".cpp", {"#C++"}},
+ {".c++", {"#C++"}}, {".C", {"#C++"}},
+ {".ads", {"#Ada"}}, {".adb", {"#Ada"}}, {".ada", {"#Ada"}},
{".f", {"#Fortran"}}, {".for", {"#Fortran"}}, {".F", {"#Fortran"}},
{".fpp", {"#Fortran"}},
{".p", {"#Pascal"}}, {".pas", {"#Pascal"}},
@@ -625,120 +594,107 @@ static struct compiler default_compilers[] =
{"@c",
{
#if USE_CPPLIB
- "%{E|M|MM:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ "%{E|M|MM:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
+ %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs} \
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+ %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
+ %{fleading-underscore} %{fno-leading-underscore}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}\
%{!E:%{!M:%{!MM:cc1 %i %1 \
- -lang-c%{ansi:89} %{nostdinc*} %{A*} %{I*} %I\
+ %{std*} %{nostdinc*} %{A*} %{I*} %I\
%{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
%{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs} \
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+ %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{H} %C %{D*} %{U*} %{i*} %Z\
%{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
%{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*}\
- %{--help:--help} \
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+ %{aux-info*} %{Qn:-fno-ident}\
+ %{--help:--help}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
%{!pipe:%g.s} %A\n }}}}"
- }},
#else /* ! USE_CPPLIB */
- "cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ "cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
+ %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs} \
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+ %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
+ %{fleading-underscore} %{fno-leading-underscore}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
"%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \
%{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
%{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*}\
+ %{aux-info*} %{Qn:-fno-ident}\
%{--help:--help} \
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
%{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
%{!pipe:%g.s} %A\n }}}}"
- }},
#endif /* ! USE_CPPLIB */
+ }},
{"-",
- {"%{E:cpp -lang-c%{ansi:89} %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {"%{E:cpp -lang-c %{ansi:-std=c89} %{std*} %{nostdinc*}\
+ %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{ansi|std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+ %{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
+ %{fleading-underscore} %{fno-leading-underscore}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %W{o*}}\
%{!E:%e-E required when input is from standard input}"}},
- {".m", {"@objective-c"}},
- {"@objective-c",
- {"cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
- %{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__OBJC__ -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs}\
- %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{traditional} %{ftraditional:-traditional}\
- %{traditional-cpp:-traditional}\
- %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
- %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
- "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \
- %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
- -lang-objc %{gen-decls} \
- %{aux-info*}\
- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
- %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
- %{!S:as %a %Y\
- %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
- %{!pipe:%g.s} %A\n }}}}"}},
{".h", {"@c-header"}},
{"@c-header",
{"%{!E:%eCompilation of header file requested} \
- cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- -undef -D__GNUC__=%v1 -D__GNUC_MINOR__=%v2\
- %{ansi:-trigraphs -D__STRICT_ANSI__}\
- %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{std=*:%{!std=gnu*:-trigraphs -D__STRICT_ANSI__}}\
+ %{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
+ %{fleading-underscore} %{fno-leading-underscore}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %W{o*}"}},
{".i", {"@cpp-output"}},
{"@cpp-output",
{"%{!M:%{!MM:%{!E:cc1 %i %1 %{!Q:-quiet} %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*}\
%{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
- %{aux-info*}\
+ %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
%{!S:as %a %Y\
@@ -751,13 +707,15 @@ static struct compiler default_compilers[] =
%i %A\n }}}}"}},
{".S", {"@assembler-with-cpp"}},
{"@assembler-with-cpp",
- {"cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %I\
+ {"cpp -lang-asm %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} %{trigraphs}\
- -undef -$ %{!undef:%p %P} -D__ASSEMBLER__ \
+ -$ %{!undef:%p %P} -D__ASSEMBLER__ \
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
%{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional}\
+ %{fleading-underscore} %{fno-leading-underscore}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
%i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
"%{!M:%{!MM:%{!E:%{!S:as %a %Y\
@@ -784,12 +742,12 @@ static int n_default_compilers
#ifdef LINK_COMMAND_SPEC
/* Provide option to override link_command_spec from machine specific
configuration files. */
-static char *link_command_spec =
+static const char *link_command_spec =
LINK_COMMAND_SPEC;
#else
#ifdef LINK_LIBGCC_SPECIAL
/* Don't generate -L options. */
-static char *link_command_spec = "\
+static const char *link_command_spec = "\
%{!fsyntax-only: \
%{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
@@ -801,7 +759,7 @@ static char *link_command_spec = "\
\n }}}}}}";
#else
/* Use -L. */
-static char *link_command_spec = "\
+static const char *link_command_spec = "\
%{!fsyntax-only: \
%{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
@@ -838,15 +796,15 @@ static char **preprocessor_options;
struct option_map
{
/* The long option's name. */
- char *name;
+ const char *name;
/* The equivalent short option. */
- char *equivalent;
+ const char *equivalent;
/* Argument info. A string of flag chars; NULL equals no options.
a => argument required.
o => argument optional.
j => join argument to equivalent, making one word.
* => require other text after NAME as an argument. */
- char *arg_info;
+ const char *arg_info;
};
/* This is the table of mappings. Mappings are tried sequentially
@@ -858,6 +816,8 @@ struct option_map option_map[] =
{"--ansi", "-ansi", 0},
{"--assemble", "-S", 0},
{"--assert", "-A", "a"},
+ {"--classpath", "-fclasspath=", "aj"},
+ {"--CLASSPATH", "-fCLASSPATH=", "aj"},
{"--comments", "-C", 0},
{"--compile", "-c", 0},
{"--debug", "-g", "oj"},
@@ -890,6 +850,7 @@ struct option_map option_map[] =
{"--no-warnings", "-w", 0},
{"--optimize", "-O", "oj"},
{"--output", "-o", "a"},
+ {"--output-class-directory", "-foutput-class-dir=", "ja"},
{"--pedantic", "-pedantic", 0},
{"--pedantic-errors", "-pedantic-errors", 0},
{"--pipe", "-pipe", 0},
@@ -910,6 +871,7 @@ struct option_map option_map[] =
{"--silent", "-q", 0},
{"--specs", "-specs=", "aj"},
{"--static", "-static", 0},
+ {"--std", "-std=", "aj"},
{"--symbolic", "-symbolic", 0},
{"--target", "-b", "a"},
{"--trace-includes", "-H", 0},
@@ -934,12 +896,13 @@ struct option_map option_map[] =
static void
translate_options (argcp, argvp)
int *argcp;
- char ***argvp;
+ const char ***argvp;
{
- int i, j, k;
+ int i;
int argc = *argcp;
- char **argv = *argvp;
- char **newv = (char **) xmalloc ((argc + 2) * 2 * sizeof (char *));
+ const char **argv = *argvp;
+ const char **newv =
+ (const char **) xmalloc ((argc + 2) * 2 * sizeof (const char *));
int newindex = 0;
i = 0;
@@ -950,23 +913,25 @@ translate_options (argcp, argvp)
/* Translate -- options. */
if (argv[i][0] == '-' && argv[i][1] == '-')
{
+ size_t j;
/* Find a mapping that applies to this option. */
for (j = 0; j < sizeof (option_map) / sizeof (option_map[0]); j++)
{
size_t optlen = strlen (option_map[j].name);
size_t arglen = strlen (argv[i]);
size_t complen = arglen > optlen ? optlen : arglen;
- char *arginfo = option_map[j].arg_info;
+ const char *arginfo = option_map[j].arg_info;
if (arginfo == 0)
arginfo = "";
if (!strncmp (argv[i], option_map[j].name, complen))
{
- char *arg = 0;
+ const char *arg = 0;
if (arglen < optlen)
{
+ size_t k;
for (k = j + 1;
k < sizeof (option_map) / sizeof (option_map[0]);
k++)
@@ -1051,7 +1016,7 @@ translate_options (argcp, argvp)
with their arguments. */
else if (argv[i][0] == '-')
{
- char *p = argv[i] + 1;
+ const char *p = argv[i] + 1;
int c = *p;
int nskip = 1;
@@ -1089,7 +1054,7 @@ translate_options (argcp, argvp)
}
char *
-my_strerror(e)
+xstrerror(e)
int e;
{
#ifdef HAVE_STRERROR
@@ -1098,15 +1063,13 @@ my_strerror(e)
#else
- static char buffer[30];
if (!e)
- return "cannot access";
+ return "errno = 0";
if (e > 0 && e < sys_nerr)
return sys_errlist[e];
- sprintf (buffer, "Unknown error %d", e);
- return buffer;
+ return "errno = ?";
#endif
}
@@ -1181,7 +1144,16 @@ static struct spec_list static_specs[] = {
};
#ifdef EXTRA_SPECS /* additional specs needed */
-static struct spec_list extra_specs[] = { EXTRA_SPECS };
+/* Structure to keep track of just the first two args of a spec_list.
+ That is all that the EXTRA_SPECS macro gives us. */
+struct spec_list_1
+{
+ char *name;
+ char *ptr;
+};
+
+static struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
+static struct spec_list * extra_specs = (struct spec_list *)0;
#endif
/* List of dynamically allocates specs that have been defined so far. */
@@ -1202,12 +1174,20 @@ init_spec ()
return; /* already initialized */
if (verbose_flag)
- fprintf (stderr, "Using builtin specs.\n");
+ notice ("Using builtin specs.\n");
#ifdef EXTRA_SPECS
- for (i = (sizeof (extra_specs) / sizeof (extra_specs[0])) - 1; i >= 0; i--)
+ extra_specs = (struct spec_list *)
+ xmalloc (sizeof(struct spec_list) *
+ (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
+ bzero ((PTR) extra_specs, sizeof(struct spec_list) *
+ (sizeof(extra_specs_1)/sizeof(extra_specs_1[0])));
+
+ for (i = (sizeof(extra_specs_1) / sizeof(extra_specs_1[0])) - 1; i >= 0; i--)
{
sl = &extra_specs[i];
+ sl->name = extra_specs_1[i].name;
+ sl->ptr = extra_specs_1[i].ptr;
sl->next = next;
sl->name_len = strlen (sl->name);
sl->ptr_spec = &sl->ptr;
@@ -1232,8 +1212,8 @@ init_spec ()
static void
set_spec (name, spec)
- char *name;
- char *spec;
+ const char *name;
+ const char *spec;
{
struct spec_list *sl;
char *old_spec;
@@ -1273,13 +1253,13 @@ set_spec (name, spec)
}
old_spec = *(sl->ptr_spec);
- *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE (spec[1]))
+ *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
? concat (old_spec, spec + 1, NULL_PTR)
: save_string (spec, strlen (spec)));
#ifdef DEBUG_SPECS
if (verbose_flag)
- fprintf (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
+ notice ("Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
#endif
/* Free the old spec */
@@ -1308,21 +1288,19 @@ static int argbuf_index;
#ifdef MKTEMP_EACH_FILE
-extern char *make_temp_file PROTO((char *));
+extern char *make_temp_file PROTO((const char *));
/* This is the list of suffixes and codes (%g/%u/%U) and the associated
temp file. */
static struct temp_name {
- char *suffix; /* suffix associated with the code. */
+ const char *suffix; /* suffix associated with the code. */
int length; /* strlen (suffix). */
int unique; /* Indicates whether %g or %u/%U was used. */
- char *filename; /* associated filename. */
+ const char *filename; /* associated filename. */
int filename_length; /* strlen (filename). */
struct temp_name *next;
} *temp_names;
-#else
-extern char *choose_temp_base PROTO((void));
#endif
@@ -1336,7 +1314,7 @@ static int signal_count;
/* Name with which this program was invoked. */
-static char *programname;
+static const char *programname;
/* Structures to keep track of prefixes to try when looking for files. */
@@ -1353,7 +1331,7 @@ struct path_prefix
{
struct prefix_list *plist; /* List of prefixes to try */
int max_len; /* Max length of a prefix in PLIST */
- char *name; /* Name of this list (used in config stuff) */
+ const char *name; /* Name of this list (used in config stuff) */
};
/* List of prefixes to try when looking for executables. */
@@ -1371,16 +1349,16 @@ static struct path_prefix include_prefixes = { 0, 0, "include" };
/* Suffix to attach to directories searched for commands.
This looks like `MACHINE/VERSION/'. */
-static char *machine_suffix = 0;
+static const char *machine_suffix = 0;
/* Suffix to attach to directories searched for commands.
This is just `MACHINE/'. */
-static char *just_machine_suffix = 0;
+static const char *just_machine_suffix = 0;
/* Adjusted value of GCC_EXEC_PREFIX envvar. */
-static char *gcc_exec_prefix;
+static const char *gcc_exec_prefix;
/* Default prefixes to attach to command names. */
@@ -1394,10 +1372,10 @@ static char *gcc_exec_prefix;
#define STANDARD_EXEC_PREFIX "/usr/local/lib/gcc-lib/"
#endif /* !defined STANDARD_EXEC_PREFIX */
-static char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
-static char *standard_exec_prefix_1 = "/usr/lib/gcc/";
+static const char *standard_exec_prefix = STANDARD_EXEC_PREFIX;
+static const char *standard_exec_prefix_1 = "/usr/lib/gcc/";
#ifdef MD_EXEC_PREFIX
-static char *md_exec_prefix = MD_EXEC_PREFIX;
+static const char *md_exec_prefix = MD_EXEC_PREFIX;
#endif
#ifndef STANDARD_STARTFILE_PREFIX
@@ -1405,25 +1383,25 @@ static char *md_exec_prefix = MD_EXEC_PREFIX;
#endif /* !defined STANDARD_STARTFILE_PREFIX */
#ifdef MD_STARTFILE_PREFIX
-static char *md_startfile_prefix = MD_STARTFILE_PREFIX;
+static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
#endif
#ifdef MD_STARTFILE_PREFIX_1
-static char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
+static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
#endif
-static char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
-static char *standard_startfile_prefix_1 = "/lib/";
-static char *standard_startfile_prefix_2 = "/usr/lib/";
+static const char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
+static const char *standard_startfile_prefix_1 = "/lib/";
+static const char *standard_startfile_prefix_2 = "/usr/lib/";
#ifndef TOOLDIR_BASE_PREFIX
#define TOOLDIR_BASE_PREFIX "/usr/local/"
#endif
-static char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
-static char *tooldir_prefix;
+static const char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
+static const char *tooldir_prefix;
/* Subdirectory to use for locating libraries. Set by
set_multilib_dir based on the compilation options. */
-static char *multilib_dir;
+static const char *multilib_dir;
/* Clear out the vector of arguments (after a command is executed). */
@@ -1469,7 +1447,7 @@ store_arg (arg, delete_always, delete_failure)
static void
read_specs (filename, main_p)
- char *filename;
+ const char *filename;
int main_p;
{
int desc;
@@ -1479,7 +1457,7 @@ read_specs (filename, main_p)
register char *p;
if (verbose_flag)
- fprintf (stderr, "Reading specs from %s\n", filename);
+ notice ("Reading specs from %s\n", filename);
/* Open and stat the file. */
desc = open (filename, O_RDONLY, 0);
@@ -1531,8 +1509,8 @@ read_specs (filename, main_p)
p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal ("specs %%include syntax malformed after %d characters",
- p1 - buffer + 1);
+ fatal ("specs %%include syntax malformed after %ld characters",
+ (long) (p1 - buffer + 1));
p[-2] = '\0';
new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
@@ -1549,15 +1527,15 @@ read_specs (filename, main_p)
while (*p1 == ' ' || *p1 == '\t') p1++;
if (*p1++ != '<' || p[-2] != '>')
- fatal ("specs %%include syntax malformed after %d characters",
- p1 - buffer + 1);
+ fatal ("specs %%include syntax malformed after %ld characters",
+ (long) (p1 - buffer + 1));
p[-2] = '\0';
new_filename = find_a_file (&startfile_prefixes, p1, R_OK);
if (new_filename)
read_specs (new_filename, FALSE);
else if (verbose_flag)
- fprintf (stderr, "Could not find specs file %s\n", p1);
+ notice ("Could not find specs file %s\n", p1);
continue;
}
else if (!strncmp (p1, "%rename", sizeof "%rename" - 1)
@@ -1572,35 +1550,35 @@ read_specs (filename, main_p)
while (*p1 == ' ' || *p1 == '\t')
p1++;
- if (! ISALPHA (*p1))
- fatal ("specs %%rename syntax malformed after %d characters",
- p1 - buffer);
+ if (! ISALPHA ((unsigned char)*p1))
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p1 - buffer));
p2 = p1;
- while (*p2 && !ISSPACE (*p2))
+ while (*p2 && !ISSPACE ((unsigned char)*p2))
p2++;
if (*p2 != ' ' && *p2 != '\t')
- fatal ("specs %%rename syntax malformed after %d characters",
- p2 - buffer);
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p2 - buffer));
name_len = p2 - p1;
*p2++ = '\0';
while (*p2 == ' ' || *p2 == '\t')
p2++;
- if (! ISALPHA (*p2))
- fatal ("specs %%rename syntax malformed after %d characters",
- p2 - buffer);
+ if (! ISALPHA ((unsigned char)*p2))
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p2 - buffer));
/* Get new spec name */
p3 = p2;
- while (*p3 && !ISSPACE (*p3))
+ while (*p3 && !ISSPACE ((unsigned char)*p3))
p3++;
if (p3 != p-1)
- fatal ("specs %%rename syntax malformed after %d characters",
- p3 - buffer);
+ fatal ("specs %%rename syntax malformed after %ld characters",
+ (long) (p3 - buffer));
*p3 = '\0';
for (sl = specs; sl; sl = sl->next)
@@ -1615,9 +1593,9 @@ read_specs (filename, main_p)
if (verbose_flag)
{
- fprintf (stderr, "rename spec %s to %s\n", p1, p2);
+ notice ("rename spec %s to %s\n", p1, p2);
#ifdef DEBUG_SPECS
- fprintf (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
+ notice ("spec is '%s'\n\n", *(sl->ptr_spec));
#endif
}
@@ -1630,8 +1608,8 @@ read_specs (filename, main_p)
continue;
}
else
- fatal ("specs unknown %% command after %d characters",
- p1 - buffer);
+ fatal ("specs unknown %% command after %ld characters",
+ (long) (p1 - buffer));
}
/* Find the colon that should end the suffix. */
@@ -1641,7 +1619,8 @@ read_specs (filename, main_p)
/* The colon shouldn't be missing. */
if (*p1 != ':')
- fatal ("specs file malformed after %d characters", p1 - buffer);
+ fatal ("specs file malformed after %ld characters",
+ (long) (p1 - buffer));
/* Skip back over trailing whitespace. */
p2 = p1;
@@ -1653,7 +1632,8 @@ read_specs (filename, main_p)
/* Find the next line. */
p = skip_whitespace (p1 + 1);
if (p[1] == 0)
- fatal ("specs file malformed after %d characters", p - buffer);
+ fatal ("specs file malformed after %ld characters",
+ (long) (p - buffer));
p1 = p;
/* Find next blank line or end of string. */
@@ -1726,7 +1706,7 @@ read_specs (filename, main_p)
otherwise, in /usr/tmp or /tmp;
or finally the current directory if all else fails. */
-static char *temp_filename;
+static const char *temp_filename;
/* Length of the prefix. */
@@ -1736,7 +1716,7 @@ static int temp_filename_length;
struct temp_file
{
- char *name;
+ const char *name;
struct temp_file *next;
};
@@ -1753,7 +1733,7 @@ static struct temp_file *failure_delete_queue;
static void
record_temp_file (filename, always_delete, fail_delete)
- char *filename;
+ const char *filename;
int always_delete;
int fail_delete;
{
@@ -1796,7 +1776,7 @@ record_temp_file (filename, always_delete, fail_delete)
static void
delete_if_ordinary (name)
- char *name;
+ const char *name;
{
struct stat st;
#ifdef DEBUG
@@ -1890,7 +1870,7 @@ putenv (str)
/* Add a new environment variable */
environ = (char **) xmalloc (sizeof (char *) * (num_envs+2));
*environ = str;
- bcopy ((char *) old_environ, (char *) (environ + 1),
+ memcpy ((char *) (environ + 1), (char *) old_environ,
sizeof (char *) * (num_envs+1));
#endif /* VMS */
@@ -1908,7 +1888,7 @@ putenv (str)
static char *
build_search_list (paths, prefix, check_dir_p)
struct path_prefix *paths;
- char *prefix;
+ const char *prefix;
int check_dir_p;
{
int suffix_len = (machine_suffix) ? strlen (machine_suffix) : 0;
@@ -1969,7 +1949,7 @@ build_search_list (paths, prefix, check_dir_p)
static void
putenv_from_prefixes (paths, env_var)
struct path_prefix *paths;
- char *env_var;
+ const char *env_var;
{
putenv (build_search_list (paths, env_var, 1));
}
@@ -1981,14 +1961,34 @@ putenv_from_prefixes (paths, env_var)
static char *
find_a_file (pprefix, name, mode)
struct path_prefix *pprefix;
- char *name;
+ const char *name;
int mode;
{
char *temp;
- char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
+ const char *file_suffix = ((mode & X_OK) != 0 ? EXECUTABLE_SUFFIX : "");
struct prefix_list *pl;
int len = pprefix->max_len + strlen (name) + strlen (file_suffix) + 1;
+#ifdef DEFAULT_ASSEMBLER
+ if (! strcmp(name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) {
+ name = DEFAULT_ASSEMBLER;
+ len = strlen(name)+1;
+ temp = xmalloc (len);
+ strcpy (temp, name);
+ return temp;
+ }
+#endif
+
+#ifdef DEFAULT_LINKER
+ if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0) {
+ name = DEFAULT_LINKER;
+ len = strlen(name)+1;
+ temp = xmalloc (len);
+ strcpy (temp, name);
+ return temp;
+ }
+#endif
+
if (machine_suffix)
len += strlen (machine_suffix);
@@ -1996,12 +1996,14 @@ find_a_file (pprefix, name, mode)
/* Determine the filename to execute (special case for absolute paths). */
- if (*name == '/' || *name == DIR_SEPARATOR
+ if (IS_DIR_SEPARATOR (*name)
+#ifdef HAVE_DOS_BASED_FILESYSTEM
/* Check for disk name on MS-DOS-based systems. */
- || (DIR_SEPARATOR == '\\' && name[1] == ':'
- && (name[2] == DIR_SEPARATOR || name[2] == '/')))
+ || (name[0] && name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
+#endif
+ )
{
- if (access (name, mode))
+ if (access (name, mode) == 0)
{
strcpy (temp, name);
return temp;
@@ -2121,8 +2123,8 @@ find_a_file (pprefix, name, mode)
static void
add_prefix (pprefix, prefix, component, first, require_machine_suffix, warn)
struct path_prefix *pprefix;
- char *prefix;
- char *component;
+ const char *prefix;
+ const char *component;
int first;
int require_machine_suffix;
int *warn;
@@ -2201,8 +2203,8 @@ execute ()
char *string;
struct command
{
- char *prog; /* program name. */
- char **argv; /* vector of args. */
+ const char *prog; /* program name. */
+ char **argv; /* vector of args. */
int pid; /* pid of process for this command. */
};
@@ -2231,7 +2233,7 @@ execute ()
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
{ /* each command. */
-#if defined (__MSDOS__) || (defined (_WIN32) && defined (__CYGWIN32_)) || defined (OS2) || defined (VMS)
+#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
fatal ("-pipe not supported");
#endif
argbuf[i] = 0; /* termination of command args. */
@@ -2268,7 +2270,7 @@ execute ()
}
fflush (stderr);
#ifdef DEBUG
- fprintf (stderr, "\nGo ahead? (y or n) ");
+ notice ("\nGo ahead? (y or n) ");
fflush (stderr);
i = getchar ();
if (i != '\n')
@@ -2356,15 +2358,15 @@ execute ()
is a null-terminated vector containing the following arguments.
The `live_cond' field is 1 if the switch is true in a conditional spec,
-1 if false (overridden by a later switch), and is initialized to zero.
- The `valid' field is nonzero if any spec has looked at this switch;
+ The `validated' field is nonzero if any spec has looked at this switch;
if it remains zero at the end of the run, it must be meaningless. */
struct switchstr
{
- char *part1;
+ const char *part1;
char **args;
int live_cond;
- int valid;
+ int validated;
};
static struct switchstr *switches;
@@ -2373,8 +2375,8 @@ static int n_switches;
struct infile
{
- char *name;
- char *language;
+ const char *name;
+ const char *language;
};
/* Also a vector of input files specified. */
@@ -2383,14 +2385,14 @@ static struct infile *infiles;
static int n_infiles;
-/* This counts the number of libraries added by LANG_SPECIFIC_DRIVER, so that
+/* This counts the number of libraries added by lang_specific_driver, so that
we can tell if there were any user supplied any files or libraries. */
static int added_libraries;
/* And a vector of corresponding output files is made up later. */
-static char **outfiles;
+static const char **outfiles;
/* Used to track if none of the -B paths are used. */
static int warn_B;
@@ -2413,7 +2415,12 @@ convert_filename (name, do_exe)
int do_exe;
{
int i;
- int len = strlen (name);
+ int len;
+
+ if (name == NULL)
+ return NULL;
+
+ len = strlen (name);
#ifdef HAVE_OBJECT_SUFFIX
/* Convert x.o to x.obj if OBJECT_SUFFIX is ".obj". */
@@ -2434,7 +2441,7 @@ convert_filename (name, do_exe)
return name;
for (i = len - 1; i >= 0; i--)
- if (name[i] == '/' || name[i] == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (name[i]))
break;
for (i++; i < len; i++)
@@ -2477,6 +2484,7 @@ display_help ()
printf (" -save-temps Do not delete intermediate files\n");
printf (" -pipe Use pipes rather than intermediate files\n");
printf (" -specs=<file> Override builtin specs with the contents of <file>\n");
+ printf (" -std=<standard> Assume that the input sources are for <standard>\n");
printf (" -B <directory> Add <directory> to the compiler's search paths\n");
printf (" -b <machine> Run gcc for target <machine>, if installed\n");
printf (" -V <version> Run gcc version number <version>, if installed\n");
@@ -2501,58 +2509,58 @@ display_help ()
static void
add_preprocessor_option (option, len)
- char * option;
- int len;
+ const char * option;
+ int len;
{
- n_preprocessor_options++;
+ n_preprocessor_options++;
- if (! preprocessor_options)
- preprocessor_options
- = (char **) xmalloc (n_preprocessor_options * sizeof (char **));
- else
- preprocessor_options
- = (char **) xrealloc (preprocessor_options,
- n_preprocessor_options * sizeof (char **));
+ if (! preprocessor_options)
+ preprocessor_options
+ = (char **) xmalloc (n_preprocessor_options * sizeof (char *));
+ else
+ preprocessor_options
+ = (char **) xrealloc (preprocessor_options,
+ n_preprocessor_options * sizeof (char *));
- preprocessor_options [n_preprocessor_options - 1] = save_string (option, len);
+ preprocessor_options [n_preprocessor_options - 1] =
+ save_string (option, len);
}
static void
add_assembler_option (option, len)
- char * option;
- int len;
-{
- n_assembler_options++;
-
- if (! assembler_options)
- assembler_options
- = (char **) xmalloc (n_assembler_options * sizeof (char **));
- else
- assembler_options
- = (char **) xrealloc (assembler_options,
- n_assembler_options * sizeof (char **));
-
- assembler_options [n_assembler_options - 1] = save_string (option, len);
+ const char * option;
+ int len;
+{
+ n_assembler_options++;
+
+ if (! assembler_options)
+ assembler_options
+ = (char **) xmalloc (n_assembler_options * sizeof (char *));
+ else
+ assembler_options
+ = (char **) xrealloc (assembler_options,
+ n_assembler_options * sizeof (char *));
+
+ assembler_options [n_assembler_options - 1] = save_string (option, len);
}
static void
add_linker_option (option, len)
- char * option;
- int len;
-{
- n_linker_options++;
-
- if (! linker_options)
- linker_options
- = (char **) xmalloc (n_linker_options * sizeof (char **));
- else
- linker_options
- = (char **) xrealloc (linker_options,
- n_linker_options * sizeof (char **));
-
- linker_options [n_linker_options - 1] = save_string (option, len);
+ const char * option;
+ int len;
+{
+ n_linker_options++;
+
+ if (! linker_options)
+ linker_options
+ = (char **) xmalloc (n_linker_options * sizeof (char *));
+ else
+ linker_options
+ = (char **) xrealloc (linker_options,
+ n_linker_options * sizeof (char *));
+
+ linker_options [n_linker_options - 1] = save_string (option, len);
}
-
/* Create the vector `switches' and its contents.
Store its length in `n_switches'. */
@@ -2563,14 +2571,15 @@ process_command (argc, argv)
char **argv;
{
register int i;
- char *temp;
+ const char *temp;
+ char *temp1;
char *spec_lang = 0;
int last_language_n_infiles;
int have_c = 0;
int have_o = 0;
int lang_n_infiles = 0;
- GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
+ GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
n_switches = 0;
n_infiles = 0;
@@ -2578,12 +2587,13 @@ process_command (argc, argv)
/* Figure compiler version from version string. */
- compiler_version = save_string (version_string, strlen (version_string));
- for (temp = compiler_version; *temp; ++temp)
+ compiler_version = temp1 =
+ save_string (version_string, strlen (version_string));
+ for (; *temp1; ++temp1)
{
- if (*temp == ' ')
+ if (*temp1 == ' ')
{
- *temp = '\0';
+ *temp1 = '\0';
break;
}
}
@@ -2593,14 +2603,13 @@ process_command (argc, argv)
if (gcc_exec_prefix)
{
int len = strlen (gcc_exec_prefix);
- if (len > sizeof ("/lib/gcc-lib/")-1
- && (gcc_exec_prefix[len-1] == '/'
- || gcc_exec_prefix[len-1] == DIR_SEPARATOR))
+ if (len > (int) sizeof ("/lib/gcc-lib/")-1
+ && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
{
temp = gcc_exec_prefix + len - sizeof ("/lib/gcc-lib/") + 1;
- if ((*temp == '/' || *temp == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (*temp)
&& strncmp (temp+1, "lib", 3) == 0
- && (temp[4] == '/' || temp[4] == DIR_SEPARATOR)
+ && IS_DIR_SEPARATOR (temp[4])
&& strncmp (temp+5, "gcc-lib", 7) == 0)
len -= sizeof ("/lib/gcc-lib/") - 1;
}
@@ -2613,10 +2622,10 @@ process_command (argc, argv)
/* COMPILER_PATH and LIBRARY_PATH have values
that are lists of directory names with colons. */
- GET_ENVIRONMENT (temp, "COMPILER_PATH");
+ GET_ENV_PATH_LIST (temp, "COMPILER_PATH");
if (temp)
{
- char *startp, *endp;
+ const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
@@ -2627,7 +2636,7 @@ process_command (argc, argv)
strncpy (nstore, startp, endp-startp);
if (endp == startp)
strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
- else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
{
nstore[endp-startp] = DIR_SEPARATOR;
nstore[endp-startp+1] = 0;
@@ -2647,10 +2656,10 @@ process_command (argc, argv)
}
}
- GET_ENVIRONMENT (temp, "LIBRARY_PATH");
+ GET_ENV_PATH_LIST (temp, "LIBRARY_PATH");
if (temp && *cross_compile == '0')
{
- char *startp, *endp;
+ const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
@@ -2661,7 +2670,7 @@ process_command (argc, argv)
strncpy (nstore, startp, endp-startp);
if (endp == startp)
strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
- else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
{
nstore[endp-startp] = DIR_SEPARATOR;
nstore[endp-startp+1] = 0;
@@ -2680,10 +2689,10 @@ process_command (argc, argv)
}
/* Use LPATH like LIBRARY_PATH (for the CMU build program). */
- GET_ENVIRONMENT (temp, "LPATH");
+ GET_ENV_PATH_LIST (temp, "LPATH");
if (temp && *cross_compile == '0')
{
- char *startp, *endp;
+ const char *startp, *endp;
char *nstore = (char *) alloca (strlen (temp) + 3);
startp = endp = temp;
@@ -2694,7 +2703,7 @@ process_command (argc, argv)
strncpy (nstore, startp, endp-startp);
if (endp == startp)
strcpy (nstore, concat (".", dir_separator_str, NULL_PTR));
- else if (endp[-1] != '/' && endp[-1] != DIR_SEPARATOR)
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
{
nstore[endp-startp] = DIR_SEPARATOR;
nstore[endp-startp+1] = 0;
@@ -2715,10 +2724,8 @@ process_command (argc, argv)
/* Convert new-style -- options to old-style. */
translate_options (&argc, &argv);
-#ifdef LANG_SPECIFIC_DRIVER
/* Do language-specific adjustment/addition of flags. */
lang_specific_driver (fatal, &argc, &argv, &added_libraries);
-#endif
/* Scan argv twice. Here, the first time, just count how many switches
there will be in their vector, and how many input files in theirs.
@@ -2732,6 +2739,8 @@ process_command (argc, argv)
init_spec ();
for (sl = specs; sl; sl = sl->next)
printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
+ if (link_command_spec)
+ printf ("*link_command:\n%s\n\n", link_command_spec);
exit (0);
}
else if (! strcmp (argv[i], "-dumpversion"))
@@ -2899,12 +2908,10 @@ process_command (argc, argv)
int len = strlen (value);
if ((len == 7
|| (len > 7
- && (value[len - 8] == '/'
- || value[len - 8] == DIR_SEPARATOR)))
+ && (IS_DIR_SEPARATOR (value[len - 8]))))
&& strncmp (value + len - 7, "stage", 5) == 0
&& ISDIGIT (value[len - 2])
- && (value[len - 1] == '/'
- || value[len - 1] == DIR_SEPARATOR))
+ && (IS_DIR_SEPARATOR (value[len - 1])))
{
if (len == 7)
add_prefix (&include_prefixes, "include", NULL_PTR,
@@ -2949,7 +2956,7 @@ process_command (argc, argv)
The format of the version string is
([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
{
- char *v = compiler_version;
+ const char *v = compiler_version;
/* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */
while (! ISDIGIT (*v))
@@ -3071,7 +3078,7 @@ process_command (argc, argv)
directories, so that we can search both the user specified directory
and the standard place. */
- if (*tooldir_prefix != '/' && *tooldir_prefix != DIR_SEPARATOR)
+ if (!IS_DIR_SEPARATOR (*tooldir_prefix))
{
if (gcc_exec_prefix)
{
@@ -3151,7 +3158,7 @@ process_command (argc, argv)
switches[n_switches].part1 = "--help";
switches[n_switches].args = 0;
switches[n_switches].live_cond = 0;
- switches[n_switches].valid = 0;
+ switches[n_switches].validated = 0;
n_switches++;
}
@@ -3166,7 +3173,7 @@ process_command (argc, argv)
switches[n_switches].part1 = &argv[i][0];
switches[n_switches].args = 0;
switches[n_switches].live_cond = 0;
- switches[n_switches].valid = 0;
+ switches[n_switches].validated = 0;
n_switches++;
}
else if (strncmp (argv[i], "-Wl,", 4) == 0)
@@ -3265,15 +3272,15 @@ process_command (argc, argv)
switches[n_switches].args = 0;
switches[n_switches].live_cond = 0;
- switches[n_switches].valid = 0;
+ switches[n_switches].validated = 0;
/* This is always valid, since gcc.c itself understands it. */
if (!strcmp (p, "save-temps"))
- switches[n_switches].valid = 1;
+ switches[n_switches].validated = 1;
else
{
char ch = switches[n_switches].part1[0];
if (ch == 'V' || ch == 'b' || ch == 'B')
- switches[n_switches].valid = 1;
+ switches[n_switches].validated = 1;
}
n_switches++;
}
@@ -3312,12 +3319,12 @@ process_command (argc, argv)
sans all directory names, and basename_length is the number
of characters starting there excluding the suffix .c or whatever. */
-char *input_filename;
+const char *input_filename;
static int input_file_number;
size_t input_filename_length;
static int basename_length;
-static char *input_basename;
-static char *input_suffix;
+static const char *input_basename;
+static const char *input_suffix;
/* These are variables used within do_spec and do_spec_1. */
@@ -3346,7 +3353,7 @@ static int input_from_pipe;
int
do_spec (spec)
- char *spec;
+ const char *spec;
{
int value;
@@ -3387,14 +3394,14 @@ do_spec (spec)
static int
do_spec_1 (spec, inswitch, soft_matched_part)
- char *spec;
+ const char *spec;
int inswitch;
- char *soft_matched_part;
+ const char *soft_matched_part;
{
- register char *p = spec;
+ register const char *p = spec;
register int c;
int i;
- char *string;
+ const char *string;
int value;
while ((c = *p++))
@@ -3429,7 +3436,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
if (i < n_switches)
{
input_from_pipe = 1;
- switches[i].valid = 1;
+ switches[i].validated = 1;
break;
}
else
@@ -3522,7 +3529,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
/* Relative directories always come from -B,
and it is better not to use them for searching
at run time. In particular, stage1 loses */
- if (pl->prefix[0] != '/' && pl->prefix[0] != DIR_SEPARATOR)
+ if (!IS_DIR_SEPARATOR (pl->prefix[0]))
continue;
#endif
/* Try subdirectory if there is one. */
@@ -3579,8 +3586,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, machine_suffix);
idx = strlen (buffer);
- if (buffer[idx - 1] == '/'
- || buffer[idx - 1] == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (buffer[idx - 1]))
buffer[idx - 1] = 0;
do_spec_1 (buffer, 1, NULL_PTR);
/* Make this a separate argument. */
@@ -3601,8 +3607,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
buffer = (char *) xrealloc (buffer, bufsize);
strcpy (buffer, pl->prefix);
idx = strlen (buffer);
- if (buffer[idx - 1] == '/'
- || buffer[idx - 1] == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (buffer[idx - 1]))
buffer[idx - 1] = 0;
do_spec_1 (buffer, 1, NULL_PTR);
/* Make this a separate argument. */
@@ -3615,16 +3620,16 @@ do_spec_1 (spec, inswitch, soft_matched_part)
break;
case 'e':
- /* {...:%efoo} means report an error with `foo' as error message
+ /* %efoo means report an error with `foo' as error message
and don't execute any more commands for this file. */
{
- char *q = p;
+ const char *q = p;
char *buf;
while (*p != 0 && *p != '\n') p++;
buf = (char *) alloca (p - q + 1);
strncpy (buf, q, p - q);
buf[p - q] = 0;
- error ("%s", buf);
+ error (buf);
return -1;
}
break;
@@ -3646,20 +3651,20 @@ do_spec_1 (spec, inswitch, soft_matched_part)
In 2.4, do something about that. */
struct temp_name *t;
int suffix_length;
- char *suffix = p;
+ const char *suffix = p;
if (p[0] == '%' && p[1] == 'O')
{
p += 2;
/* We don't support extra suffix characters after %O. */
- if (*p == '.' || ISALPHA (*p))
+ if (*p == '.' || ISALPHA ((unsigned char)*p))
abort ();
suffix = OBJECT_SUFFIX;
suffix_length = strlen (OBJECT_SUFFIX);
}
else
{
- while (*p == '.' || ISALPHA (*p))
+ while (*p == '.' || ISALPHA ((unsigned char)*p))
p++;
suffix_length = p - suffix;
}
@@ -3739,9 +3744,15 @@ do_spec_1 (spec, inswitch, soft_matched_part)
break;
case 'o':
- for (i = 0; i < n_infiles; i++)
- store_arg (outfiles[i], 0, 0);
- break;
+ {
+ int max = n_infiles;
+ max += lang_specific_extra_outfiles;
+
+ for (i = 0; i < max; i++)
+ if (outfiles[i])
+ store_arg (outfiles[i], 0, 0);
+ break;
+ }
case 'O':
obstack_grow (&obstack, OBJECT_SUFFIX, strlen (OBJECT_SUFFIX));
@@ -3775,7 +3786,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
/* %x{OPTION} records OPTION for %X to output. */
case 'x':
{
- char *p1 = p;
+ const char *p1 = p;
char *string;
/* Skip past the option value and make a copy. */
@@ -3940,7 +3951,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
*x++ = *y++;
if (*y != '_'
- || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+ || (*(y+1) != '_'
+ && ! ISUPPER ((unsigned char)*(y+1))))
{
/* Stick __ at front of macro name. */
*x++ = '_';
@@ -3982,7 +3994,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
y += 2;
if (*y != '_'
- || (*(y+1) != '_' && ! ISUPPER (*(y+1))))
+ || (*(y+1) != '_'
+ && ! ISUPPER ((unsigned char)*(y+1))))
{
/* Stick -D__ at front of macro name. */
*x++ = '-';
@@ -4070,7 +4083,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
error ("Warning: use of obsolete %%[ operator in specs");
case '(':
{
- char *name = p;
+ const char *name = p;
struct spec_list *sl;
int len;
@@ -4085,8 +4098,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
{
name = *(sl->ptr_spec);
#ifdef DEBUG_SPECS
- fprintf (stderr, "Processing spec %c%s%c, which is '%s'\n",
- c, sl->name, (c == '(') ? ')' : ']', name);
+ notice ("Processing spec %c%s%c, which is '%s'\n",
+ c, sl->name, (c == '(') ? ')' : ']', name);
#endif
break;
}
@@ -4103,7 +4116,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
{
char *x = (char *) alloca (strlen (name) * 2 + 1);
char *buf = x;
- char *y = name;
+ const char *y = name;
int flag = 0;
/* Copy all of NAME into BUF, but put __ after
@@ -4211,11 +4224,11 @@ do_spec_1 (spec, inswitch, soft_matched_part)
/* Return 0 if we call do_spec_1 and that returns -1. */
-static char *
+static const char *
handle_braces (p)
- register char *p;
+ register const char *p;
{
- char *filter, *body = NULL, *endbody;
+ const char *filter, *body = NULL, *endbody = NULL;
int pipe_p = 0;
int negate;
int suffix;
@@ -4260,7 +4273,7 @@ next_member:
if (*p != '}')
{
register int count = 1;
- register char *q = p;
+ register const char *q = p;
while (*q++ != ':') continue;
body = q;
@@ -4284,7 +4297,7 @@ next_member:
if (suffix)
{
int found = (input_suffix != 0
- && strlen (input_suffix) == p - filter
+ && (long) strlen (input_suffix) == (long)(p - filter)
&& strncmp (input_suffix, filter, p - filter) == 0);
if (body[0] == '}')
@@ -4315,7 +4328,7 @@ next_member:
if (p[-1] == '*' && !negate)
{
int substitution;
- char *r = body;
+ const char *r = body;
/* First see whether we have %*. */
substitution = 0;
@@ -4426,7 +4439,7 @@ check_live_switch (switchnum, prefix_length)
int switchnum;
int prefix_length;
{
- char *name = switches[switchnum].part1;
+ const char *name = switches[switchnum].part1;
int i;
/* In the common case of {<at-most-one-letter>*}, a negating
@@ -4447,7 +4460,7 @@ check_live_switch (switchnum, prefix_length)
for (i = switchnum + 1; i < n_switches; i++)
if (switches[i].part1[0] == 'O')
{
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
switches[switchnum].live_cond = -1;
return 0;
}
@@ -4461,7 +4474,7 @@ check_live_switch (switchnum, prefix_length)
if (switches[i].part1[0] == name[0]
&& ! strcmp (&switches[i].part1[1], &name[4]))
{
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
switches[switchnum].live_cond = -1;
return 0;
}
@@ -4476,7 +4489,7 @@ check_live_switch (switchnum, prefix_length)
&& switches[i].part1[3] == '-'
&& !strcmp (&switches[i].part1[4], &name[1]))
{
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
switches[switchnum].live_cond = -1;
return 0;
}
@@ -4524,16 +4537,16 @@ give_switch (switchnum, omit_first_word, include_blanks)
}
do_spec_1 (" ", 0, NULL_PTR);
- switches[switchnum].valid = 1;
+ switches[switchnum].validated = 1;
}
/* Search for a file named NAME trying various prefixes including the
user's -B prefix and some standard ones.
Return the absolute file name found. If nothing is found, return NAME. */
-static char *
+static const char *
find_file (name)
- char *name;
+ const char *name;
{
char *newname;
@@ -4566,8 +4579,8 @@ find_file (name)
static int
is_directory (path1, path2, linker)
- char *path1;
- char *path2;
+ const char *path1;
+ const char *path2;
int linker;
{
int len1 = strlen (path1);
@@ -4584,10 +4597,10 @@ is_directory (path1, path2, linker)
/* Construct the path from the two parts. Ensure the string ends with "/.".
The resulting path will be a directory even if the given path is a
symbolic link. */
- bcopy (path1, path, len1);
- bcopy (path2, path + len1, len2);
+ memcpy (path, path1, len1);
+ memcpy (path + len1, path2, len2);
cp = path + len1 + len2;
- if (cp[-1] != '/' && cp[-1] != DIR_SEPARATOR)
+ if (!IS_DIR_SEPARATOR (cp[-1]))
*cp++ = DIR_SEPARATOR;
*cp++ = '.';
*cp = '\0';
@@ -4631,13 +4644,20 @@ main (argc, argv)
int linker_was_run = 0;
char *explicit_link_files;
char *specs_file;
- char *p;
+ const char *p;
struct user_specs *uptr;
p = argv[0] + strlen (argv[0]);
- while (p != argv[0] && p[-1] != '/' && p[-1] != DIR_SEPARATOR) --p;
+ while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+ --p;
programname = p;
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
if (signal (SIGINT, SIG_IGN) != SIG_IGN)
signal (SIGINT, fatal_error);
#ifdef SIGHUP
@@ -4728,10 +4748,10 @@ main (argc, argv)
sizeof ("COLLECT_GCC_OPTIONS=")-1);
first_time = TRUE;
- for (i = 0; i < n_switches; i++)
+ for (i = 0; (int)i < n_switches; i++)
{
char **args;
- char *p, *q;
+ const char *p, *q;
if (!first_time)
obstack_grow (&collect_obstack, " ", 1);
@@ -4798,18 +4818,7 @@ main (argc, argv)
if (access (specs_file, R_OK) == 0)
read_specs (specs_file, TRUE);
- /* Process any user specified specs in the order given on the command
- line. */
- for (uptr = user_specs_head; uptr; uptr = uptr->next)
- {
- char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
- read_specs (filename ? filename : uptr->filename, FALSE);
- }
-
/* If not cross-compiling, look for startfiles in the standard places. */
- /* The fact that these are done here, after reading the specs file,
- means that it cannot be found in these directories.
- But that's okay. It should never be there anyway. */
if (*cross_compile == '0')
{
#ifdef MD_EXEC_PREFIX
@@ -4831,14 +4840,12 @@ main (argc, argv)
standard_exec_prefix. This lets us move the installed tree
as a unit. If GCC_EXEC_PREFIX is defined, base
standard_startfile_prefix on that as well. */
- if (*standard_startfile_prefix == '/'
- || *standard_startfile_prefix == DIR_SEPARATOR
- || *standard_startfile_prefix == '$'
-#ifdef __MSDOS__
- /* Check for disk name on MS-DOS-based systems. */
+ if (IS_DIR_SEPARATOR (*standard_startfile_prefix)
+ || *standard_startfile_prefix == '$'
+#ifdef HAVE_DOS_BASED_FILESYSTEM
+ /* Check for disk name on MS-DOS-based systems. */
|| (standard_startfile_prefix[1] == ':'
- && (standard_startfile_prefix[2] == DIR_SEPARATOR
- || standard_startfile_prefix[2] == '/'))
+ && (IS_DIR_SEPARATOR (standard_startfile_prefix[2])))
#endif
)
add_prefix (&startfile_prefixes, standard_startfile_prefix, "BINUTILS",
@@ -4867,13 +4874,21 @@ main (argc, argv)
}
else
{
- if (*standard_startfile_prefix != DIR_SEPARATOR && gcc_exec_prefix)
+ if (!IS_DIR_SEPARATOR (*standard_startfile_prefix) && gcc_exec_prefix)
add_prefix (&startfile_prefixes,
concat (gcc_exec_prefix, machine_suffix,
standard_startfile_prefix, NULL_PTR),
"BINUTILS", 0, 0, NULL_PTR);
}
+ /* Process any user specified specs in the order given on the command
+ line. */
+ for (uptr = user_specs_head; uptr; uptr = uptr->next)
+ {
+ char *filename = find_a_file (&startfile_prefixes, uptr->filename, R_OK);
+ read_specs (filename ? filename : uptr->filename, FALSE);
+ }
+
/* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
if (gcc_exec_prefix)
{
@@ -4899,8 +4914,8 @@ main (argc, argv)
/* Warn about any switches that no pass was interested in. */
- for (i = 0; i < n_switches; i++)
- if (! switches[i].valid)
+ for (i = 0; (int)i < n_switches; i++)
+ if (! switches[i].validated)
error ("unrecognized option `-%s'", switches[i].part1);
/* Obey some of the options. */
@@ -4947,8 +4962,8 @@ main (argc, argv)
if (! verbose_flag)
{
- printf ("\nReport bugs to egcs-bugs@egcs.cygnus.com.\n");
- printf ("Please see the file BUGS (included with the sources) first.\n");
+ printf ("\nFor bug reporting instructions, please see:\n");
+ printf ("<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>.\n");
exit (0);
}
@@ -4971,10 +4986,10 @@ main (argc, argv)
if (! strncmp (version_string, compiler_version, n)
&& compiler_version[n] == 0)
- fprintf (stderr, "gcc version %s\n", version_string);
+ notice ("gcc version %s\n", version_string);
else
- fprintf (stderr, "gcc driver version %s executing gcc version %s\n",
- version_string, compiler_version);
+ notice ("gcc driver version %s executing gcc version %s\n",
+ version_string, compiler_version);
if (n_infiles == 0)
exit (0);
@@ -4987,18 +5002,16 @@ main (argc, argv)
that correspond to the input files. */
i = n_infiles;
-#ifdef LANG_SPECIFIC_DRIVER
i += lang_specific_extra_outfiles;
-#endif
- outfiles = (char **) xmalloc (i * sizeof (char *));
- bzero ((char *) outfiles, n_infiles * sizeof (char *));
+ outfiles = (const char **) xmalloc (i * sizeof (char *));
+ bzero ((char *) outfiles, i * sizeof (char *));
/* Record which files were specified explicitly as link input. */
explicit_link_files = xmalloc (n_infiles);
bzero (explicit_link_files, n_infiles);
- for (i = 0; i < n_infiles; i++)
+ for (i = 0; (int)i < n_infiles; i++)
{
register struct compiler *cp = 0;
int this_file_error = 0;
@@ -5022,7 +5035,7 @@ main (argc, argv)
{
/* Ok, we found an applicable compiler. Run its spec. */
/* First say how much of input_filename to substitute for %b */
- register char *p;
+ register const char *p;
int len;
if (cp->spec[0][0] == '#')
@@ -5031,7 +5044,7 @@ main (argc, argv)
input_basename = input_filename;
for (p = input_filename; *p; p++)
- if (*p == '/' || *p == DIR_SEPARATOR)
+ if (IS_DIR_SEPARATOR (*p))
input_basename = p + 1;
/* Find a suffix starting with the last period,
@@ -5052,18 +5065,20 @@ main (argc, argv)
if (cp->spec[j])
len += strlen (cp->spec[j]);
- p = (char *) xmalloc (len + 1);
-
- len = 0;
- for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
- if (cp->spec[j])
- {
- strcpy (p + len, cp->spec[j]);
- len += strlen (cp->spec[j]);
- }
-
- value = do_spec (p);
- free (p);
+ {
+ char *p1 = (char *) xmalloc (len + 1);
+
+ len = 0;
+ for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++)
+ if (cp->spec[j])
+ {
+ strcpy (p1 + len, cp->spec[j]);
+ len += strlen (cp->spec[j]);
+ }
+
+ value = do_spec (p1);
+ free (p1);
+ }
if (value < 0)
this_file_error = 1;
}
@@ -5086,11 +5101,14 @@ main (argc, argv)
clear_failure_queue ();
}
-#ifdef LANG_SPECIFIC_DRIVER
- if (error_count == 0
- && lang_specific_pre_link ())
- error_count++;
-#endif
+ if (error_count == 0)
+ {
+ /* Make sure INPUT_FILE_NUMBER points to first available open
+ slot. */
+ input_file_number = n_infiles;
+ if (lang_specific_pre_link ())
+ error_count++;
+ }
/* Run ld to link all the compiler output files. */
@@ -5124,7 +5142,7 @@ main (argc, argv)
complain about input files to be given to the linker. */
if (! linker_was_run && error_count == 0)
- for (i = 0; i < n_infiles; i++)
+ for (i = 0; (int)i < n_infiles; i++)
if (explicit_link_files[i])
error ("%s: linker input file unused since linking not done",
outfiles[i]);
@@ -5137,8 +5155,8 @@ main (argc, argv)
if (print_help_list)
{
- printf ("\nReport bugs to egcs-bugs@egcs.cygnus.com.\n");
- printf ("Please see the file BUGS (included with the sources) first.\n");
+ printf ("\nFor bug reporting instructions, please see:\n");
+ printf ("<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>\n");
}
exit (error_count > 0 ? (signal_count ? 2 : 1) : 0);
@@ -5152,9 +5170,9 @@ main (argc, argv)
static struct compiler *
lookup_compiler (name, length, language)
- char *name;
+ const char *name;
size_t length;
- char *language;
+ const char *language;
{
struct compiler *cp;
@@ -5216,85 +5234,35 @@ lookup_compiler (name, length, language)
return 0;
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *value = (char *) malloc (size);
+ register PTR value = (PTR) malloc (size);
if (value == 0)
fatal ("virtual memory exhausted");
return value;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- register char *value = (char *) realloc (ptr, size);
- if (value == 0)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (ptr == 0)
fatal ("virtual memory exhausted");
- return value;
-}
-
-/* This function is based on the one in libiberty. */
-
-static char *
-concat VPROTO((char *first, ...))
-{
- register int length;
- register char *newstr;
- register char *end;
- register char *arg;
- va_list args;
-#ifndef __STDC__
- char *first;
-#endif
-
- /* First compute the size of the result and get sufficient memory. */
-
- VA_START (args, first);
-#ifndef __STDC__
- first = va_arg (args, char *);
-#endif
-
- arg = first;
- length = 0;
-
- while (arg != 0)
- {
- length += strlen (arg);
- arg = va_arg (args, char *);
- }
-
- newstr = (char *) xmalloc (length + 1);
- va_end (args);
-
- /* Now copy the individual pieces to the result string. */
-
- VA_START (args, first);
-#ifndef __STDC__
- first = va_arg (args, char *);
-#endif
-
- end = newstr;
- arg = first;
- while (arg != 0)
- {
- while (*arg)
- *end++ = *arg++;
- arg = va_arg (args, char *);
- }
- *end = '\000';
- va_end (args);
-
- return (newstr);
+ return ptr;
}
static char *
save_string (s, len)
- char *s;
- int len;
+ const char *s;
+ int len;
{
register char *result = xmalloc (len + 1);
@@ -5305,34 +5273,38 @@ save_string (s, len)
static void
pfatal_with_name (name)
- char *name;
+ const char *name;
{
- fatal ("%s: %s", name, my_strerror (errno));
+ perror_with_name (name);
+ delete_temp_files ();
+ exit (1);
}
static void
perror_with_name (name)
- char *name;
+ const char *name;
{
- error ("%s: %s", name, my_strerror (errno));
+ error ("%s: %s", name, xstrerror (errno));
}
static void
pfatal_pexecute (errmsg_fmt, errmsg_arg)
- char *errmsg_fmt;
- char *errmsg_arg;
+ const char *errmsg_fmt;
+ const char *errmsg_arg;
{
- int save_errno = errno;
-
if (errmsg_arg)
{
+ int save_errno = errno;
+
/* Space for trailing '\0' is in %s. */
char *msg = xmalloc (strlen (errmsg_fmt) + strlen (errmsg_arg));
sprintf (msg, errmsg_fmt, errmsg_arg);
errmsg_fmt = msg;
+
+ errno = save_errno;
}
- fatal ("%s: %s", errmsg_fmt, my_strerror (save_errno));
+ pfatal_with_name (errmsg_fmt);
}
/* More 'friendly' abort that prints the line and file.
@@ -5346,22 +5318,22 @@ fancy_abort ()
/* Output an error message and exit */
-static void
-fatal VPROTO((char *format, ...))
+void
+fatal VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, format);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s: ", programname);
- vfprintf (stderr, format, ap);
+ vfprintf (stderr, _(msgid), ap);
va_end (ap);
fprintf (stderr, "\n");
delete_temp_files ();
@@ -5369,31 +5341,50 @@ fatal VPROTO((char *format, ...))
}
static void
-error VPROTO((char *format, ...))
+error VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, format);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s: ", programname);
- vfprintf (stderr, format, ap);
+ vfprintf (stderr, _(msgid), ap);
va_end (ap);
fprintf (stderr, "\n");
}
+
+static void
+notice VPROTO((const char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+#endif
+
+ vfprintf (stderr, _(msgid), ap);
+ va_end (ap);
+}
+
static void
validate_all_switches ()
{
struct compiler *comp;
- register char *p;
+ register const char *p;
register char c;
struct spec_list *spec;
@@ -5432,10 +5423,10 @@ validate_all_switches ()
static void
validate_switches (start)
- char *start;
+ const char *start;
{
- register char *p = start;
- char *filter;
+ register const char *p = start;
+ const char *filter;
register int i;
int suffix = 0;
@@ -5459,7 +5450,7 @@ validate_switches (start)
--p;
for (i = 0; i < n_switches; i++)
if (!strncmp (switches[i].part1, filter, p - filter))
- switches[i].valid = 1;
+ switches[i].validated = 1;
}
else
{
@@ -5468,7 +5459,7 @@ validate_switches (start)
{
if (!strncmp (switches[i].part1, filter, p - filter)
&& switches[i].part1[p - filter] == 0)
- switches[i].valid = 1;
+ switches[i].validated = 1;
}
}
}
@@ -5478,7 +5469,7 @@ validate_switches (start)
static int
used_arg (p, len)
- char *p;
+ const char *p;
int len;
{
struct mswitchstr {
@@ -5566,7 +5557,7 @@ used_arg (p, len)
static int
default_arg (p, len)
- char *p;
+ const char *p;
int len;
{
char *start, *end;
@@ -5681,9 +5672,10 @@ set_multilib_dir ()
if (this_path_len != 1
|| this_path[0] != '.')
{
- multilib_dir = xmalloc (this_path_len + 1);
- strncpy (multilib_dir, this_path, this_path_len);
- multilib_dir[this_path_len] = '\0';
+ char * new_multilib_dir = xmalloc (this_path_len + 1);
+ strncpy (new_multilib_dir, this_path, this_path_len);
+ new_multilib_dir[this_path_len] = '\0';
+ multilib_dir = new_multilib_dir;
}
break;
}
diff --git a/contrib/gcc/gcc.texi b/contrib/gcc/gcc.texi
index 6eb51c1..d2bbbb5 100644
--- a/contrib/gcc/gcc.texi
+++ b/contrib/gcc/gcc.texi
@@ -47,15 +47,15 @@
@ifset INTERNALS
@ifset USING
-@settitle Using and Porting GNU CC
+@settitle Using and Porting the GNU Compiler Collection (GCC)
@end ifset
@end ifset
@c seems reasonable to assume at least one of INTERNALS or USING is set...
@ifclear INTERNALS
-@settitle Using GNU CC
+@settitle Using the GNU Compiler Collection
@end ifclear
@ifclear USING
-@settitle Porting GNU CC
+@settitle Porting the GNU Compiler Collection
@end ifclear
@syncodeindex fn cp
@@ -82,7 +82,7 @@
@ifinfo
@dircategory Programming
@direntry
-* gcc: (gcc). The GNU C compiler.
+* gcc: (gcc). The GNU Compiler Collection.
@end direntry
@ifset INTERNALS
@ifset USING
@@ -100,7 +100,7 @@ Published by the Free Software Foundation
59 Temple Place - Suite 330
Boston, MA 02111-1307 USA
-Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -133,29 +133,29 @@ instead of in the original English.
@titlepage
@ifset INTERNALS
@ifset USING
-@center @titlefont{Using and Porting GNU CC}
+@center @titlefont{Using and Porting the GNU Compiler Collection}
@end ifset
@end ifset
@ifclear INTERNALS
-@title Using GNU CC
+@title Using the GNU Compiler Collection
@end ifclear
@ifclear USING
-@title Porting GNU CC
+@title Porting the GNU Compiler Collection
@end ifclear
@sp 2
@center Richard M. Stallman
@sp 3
-@center Last updated 16 March 1998
+@center Last updated 28 July 1999
@sp 1
@c The version number appears five times more in this file.
-@center for egcs-1.1.2
+@center for gcc-2.95
@page
@vskip 0pt plus 1filll
-Copyright @copyright{} 1988, 89, 92, 93, 94, 95, 96, 98 Free Software Foundation, Inc.
+Copyright @copyright{} 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
@sp 2
-For EGCS Version 1.0@*
+For GCC Version 2.95@*
@sp 1
Published by the Free Software Foundation @*
59 Temple Place - Suite 330@*
@@ -194,19 +194,19 @@ instead of in the original English.
@ifset USING
This manual documents how to run, install and port the GNU
compiler, as well as its new features and incompatibilities, and how to
-report bugs. It corresponds to EGCS version 1.1.2.
+report bugs. It corresponds to GCC version 2.95.
@end ifset
@end ifset
@ifclear INTERNALS
This manual documents how to run and install the GNU compiler,
as well as its new features and incompatibilities, and how to report
-bugs. It corresponds to EGCS version 1.1.2.
+bugs. It corresponds to GCC version 2.95.
@end ifclear
@ifclear USING
This manual documents how to port the GNU compiler,
as well as its new features and incompatibilities, and how to report
-bugs. It corresponds to EGCS version 1.1.2.
+bugs. It corresponds to GCC version 2.95.
@end ifclear
@end ifinfo
@@ -214,19 +214,19 @@ bugs. It corresponds to EGCS version 1.1.2.
@ifset USING
* G++ and GCC:: You can compile C or C++ programs.
* Invoking GCC:: Command options supported by @samp{gcc}.
-* Installation:: How to configure, compile and install GNU CC.
+* Installation:: How to configure, compile and install GCC.
* C Extensions:: GNU extensions to the C language family.
* C++ Extensions:: GNU extensions to the C++ language.
-* Gcov:: gcov: a GNU CC test coverage program.
-* Trouble:: If you have trouble installing GNU CC.
+* Gcov:: gcov: a GCC test coverage program.
+* Trouble:: If you have trouble installing GCC.
* Bugs:: How, why and where to report bugs.
-* Service:: How to find suppliers of support for GNU CC.
-* Contributing:: How to contribute to testing and developing GNU CC.
-* VMS:: Using GNU CC on VMS.
+* Service:: How to find suppliers of support for GCC.
+* Contributing:: How to contribute to testing and developing GCC.
+* VMS:: Using GCC on VMS.
@end ifset
@ifset INTERNALS
-* Portability:: Goals of GNU CC's portability features.
-* Interface:: Function-call interface of GNU CC output.
+* Portability:: Goals of GCC's portability features.
+* Interface:: Function-call interface of GCC output.
* Passes:: Order of passes, what they do, and what each file is for.
* RTL:: The intermediate representation that most passes work on.
* Machine Desc:: How to write machine description instruction patterns.
@@ -239,24 +239,27 @@ bugs. It corresponds to EGCS version 1.1.2.
* GNU/Linux:: Linux and the GNU Project
* Copying:: GNU General Public License says
- how you can copy and share GNU CC.
-* Contributors:: People who have contributed to GNU CC.
+ how you can copy and share GCC.
+* Contributors:: People who have contributed to GCC.
* Index:: Index of concepts and symbol names.
@end menu
@ifset USING
@node G++ and GCC
-@chapter Compile C, C++, or Objective C
+@chapter Compile C, C++, Objective C, or Fortran
@cindex Objective C
-The C, C++, and Objective C versions of the compiler are integrated; the
-GNU C compiler can compile programs written in C, C++, or Objective C.
+The C, C++, and Objective C, and Fortran versions of the compiler are
+integrated; this is why we use the name ``GNU Compiler Collection''.
+GCC can compile programs written in C, C++, Objective C, or Fortran.
+The Fortran compiler is described in a separate manual.
@cindex GCC
-``GCC'' is a common shorthand term for the GNU C compiler. This is both
+``GCC'' is a common shorthand term for the GNU Compiler Collection. This is both
the most general name for the compiler, and the name used when the
-emphasis is on compiling C programs.
+emphasis is on compiling C programs (as the abbreviation formerly
+stood for ``GNU C Compiler'').
@cindex C++
@cindex G++
@@ -265,20 +268,20 @@ When referring to C++ compilation, it is usual to call the compiler
it ``GCC'' no matter what the language context; however, the term
``G++'' is more useful when the emphasis is on compiling C++ programs.
-We use the name ``GNU CC'' to refer to the compilation system as a
+We use the name ``GCC'' to refer to the compilation system as a
whole, and more specifically to the language-independent part of the
compiler. For example, we refer to the optimization options as
-affecting the behavior of ``GNU CC'' or sometimes just ``the compiler''.
+affecting the behavior of ``GCC'' or sometimes just ``the compiler''.
Front ends for other languages, such as Ada 9X, Fortran, Modula-3, and
Pascal, are under development. These front-ends, like that for C++, are
-built in subdirectories of GNU CC and link to it. The result is an
+built in subdirectories of GCC and link to it. The result is an
integrated compiler that can compile programs written in C, C++,
Objective C, or any of the languages for which you have installed front
ends.
In this manual, we only discuss the options for the C, Objective-C, and
-C++ compilers and those of the GNU CC core. Consult the documentation
+C++ compilers and those of the GCC core. Consult the documentation
of the other front ends for the options to use when compiling programs
written in other languages.
@@ -308,13 +311,13 @@ give you comprehensive C++ source-level editing capabilities
@include gcov.texi
@node Trouble
-@chapter Known Causes of Trouble with GNU CC
+@chapter Known Causes of Trouble with GCC
@cindex bugs, known
@cindex installation trouble
@cindex known causes of trouble
-This section describes known problems that affect users of GNU CC. Most
-of these are not GNU CC bugs per se---if they were, we would fix them.
+This section describes known problems that affect users of GCC. Most
+of these are not GCC bugs per se---if they were, we would fix them.
But the result for a user may be like the result of a bug.
Some of these problems are due to bugs in other software, some are
@@ -323,12 +326,12 @@ where people's opinions differ as to what is best.
@menu
* Actual Bugs:: Bugs we will fix later.
-* Installation Problems:: Problems that manifest when you install GNU CC.
-* Cross-Compiler Problems:: Common problems of cross compiling with GNU CC.
-* Interoperation:: Problems using GNU CC with other compilers,
+* Installation Problems:: Problems that manifest when you install GCC.
+* Cross-Compiler Problems:: Common problems of cross compiling with GCC.
+* Interoperation:: Problems using GCC with other compilers,
and with certain linkers, assemblers and debuggers.
* External Bugs:: Problems compiling certain programs.
-* Incompatibilities:: GNU CC is incompatible with traditional C.
+* Incompatibilities:: GCC is incompatible with traditional C.
* Fixed Headers:: GNU C uses corrected versions of system header files.
This is necessary, but doesn't always work smoothly.
* Standard Libraries:: GNU C uses the system C library, which might not be
@@ -363,7 +366,7 @@ There are several obscure case of mis-using struct, union, and
enum tags that are not detected as errors by the compiler.
@item
-When @samp{-pedantic-errors} is specified, GNU C will incorrectly give
+When @samp{-pedantic-errors} is specified, GCC will incorrectly give
an error message when a function name is specified in an expression
involving the comma operator.
@@ -393,19 +396,19 @@ directory. Make sure you have done all the necessary preparations.
@xref{Other Dir}.
@item
-If you build GNU CC on a BSD system using a directory stored in a System
+If you build GCC on a BSD system using a directory stored in a System
V file system, problems may occur in running @code{fixincludes} if the
System V file system doesn't support symbolic links. These problems
result in a failure to fix the declaration of @code{size_t} in
@file{sys/types.h}. If you find that @code{size_t} is a signed type and
that type mismatches occur, this could be the cause.
-The solution is not to use such a directory for building GNU CC.
+The solution is not to use such a directory for building GCC.
@item
-In previous versions of GNU CC, the @code{gcc} driver program looked for
+In previous versions of GCC, the @code{gcc} driver program looked for
@code{as} and @code{ld} in various places; for example, in files
-beginning with @file{/usr/local/lib/gcc-}. GNU CC version 2 looks for
+beginning with @file{/usr/local/lib/gcc-}. GCC version 2 looks for
them in the directory
@file{/usr/local/lib/gcc-lib/@var{target}/@var{version}}.
@@ -433,12 +436,12 @@ the compiler. In one case, this was traced down to a bug in
@item
If you have installed a program known as purify, you may find that it
causes errors while linking @code{enquire}, which is part of building
-GNU CC. The fix is to get rid of the file @code{real-ld} which purify
-installs---so that GNU CC won't try to use it.
+GCC. The fix is to get rid of the file @code{real-ld} which purify
+installs---so that GCC won't try to use it.
@item
On GNU/Linux SLS 1.01, there is a problem with @file{libc.a}: it does not
-contain the obstack functions. However, GNU CC assumes that the obstack
+contain the obstack functions. However, GCC assumes that the obstack
functions are in @file{libc.a} when it is the GNU C library. To work
around this problem, change the @code{__GNU_LIBRARY__} conditional
around line 31 to @samp{#if 1}.
@@ -447,7 +450,7 @@ around line 31 to @samp{#if 1}.
On some 386 systems, building the compiler never finishes because
@code{enquire} hangs due to a hardware problem in the motherboard---it
reports floating point exceptions to the kernel incorrectly. You can
-install GNU CC except for @file{float.h} by patching out the command to
+install GCC except for @file{float.h} by patching out the command to
run @code{enquire}. You may also be able to fix the problem for real by
getting a replacement motherboard. This problem was observed in
Revision E of the Micronics motherboard, and is fixed in Revision F.
@@ -459,7 +462,7 @@ are running SCO Unix, you can reboot and force the FPU to be ignored.
To do this, type @samp{hd(40)unix auto ignorefpu}.
@item
-On some 386 systems, GNU CC crashes trying to compile @file{enquire.c}.
+On some 386 systems, GCC crashes trying to compile @file{enquire.c}.
This happens on machines that don't have a 387 FPU chip. On 386
machines, the system kernel is supposed to emulate the 387 when you
don't have one. The crash is due to a bug in the emulator.
@@ -490,48 +493,48 @@ enquire.c:2328: floating overflow
@end example
@item
-On SCO systems, when compiling GNU CC with the system's compiler,
+On SCO systems, when compiling GCC with the system's compiler,
do not use @samp{-O}. Some versions of the system's compiler miscompile
-GNU CC with @samp{-O}.
+GCC with @samp{-O}.
@cindex @code{genflags}, crash on Sun 4
@item
Sometimes on a Sun 4 you may observe a crash in the program
-@code{genflags} or @code{genoutput} while building GNU CC. This is said to
+@code{genflags} or @code{genoutput} while building GCC. This is said to
be due to a bug in @code{sh}. You can probably get around it by running
@code{genflags} or @code{genoutput} manually and then retrying the
@code{make}.
@item
-On Solaris 2, executables of GNU CC version 2.0.2 are commonly
+On Solaris 2, executables of GCC version 2.0.2 are commonly
available, but they have a bug that shows up when compiling current
-versions of GNU CC: undefined symbol errors occur during assembly if you
+versions of GCC: undefined symbol errors occur during assembly if you
use @samp{-g}.
-The solution is to compile the current version of GNU CC without
+The solution is to compile the current version of GCC without
@samp{-g}. That makes a working compiler which you can use to recompile
with @samp{-g}.
@item
Solaris 2 comes with a number of optional OS packages. Some of these
-packages are needed to use GNU CC fully. If you did not install all
+packages are needed to use GCC fully. If you did not install all
optional packages when installing Solaris, you will need to verify that
-the packages that GNU CC needs are installed.
+the packages that GCC needs are installed.
To check whether an optional package is installed, use
the @code{pkginfo} command. To add an optional package, use the
@code{pkgadd} command. For further details, see the Solaris
documentation.
-For Solaris 2.0 and 2.1, GNU CC needs six packages: @samp{SUNWarc},
+For Solaris 2.0 and 2.1, GCC needs six packages: @samp{SUNWarc},
@samp{SUNWbtool}, @samp{SUNWesu}, @samp{SUNWhea}, @samp{SUNWlibm}, and
@samp{SUNWtoo}.
-For Solaris 2.2, GNU CC needs an additional seventh package: @samp{SUNWsprot}.
+For Solaris 2.2, GCC needs an additional seventh package: @samp{SUNWsprot}.
@item
On Solaris 2, trying to use the linker and other tools in
-@file{/usr/ucb} to install GNU CC has been observed to cause trouble.
+@file{/usr/ucb} to install GCC has been observed to cause trouble.
For example, the linker may hang indefinitely. The fix is to remove
@file{/usr/ucb} from your @code{PATH}.
@@ -555,7 +558,7 @@ optional, and there should not be a warning about their absence.
@item
In Ultrix 4.0 on the MIPS machine, @file{stdio.h} does not work with GNU
CC at all unless it has been fixed with @code{fixincludes}. This causes
-problems in building GNU CC. Once GNU CC is installed, the problems go
+problems in building GCC. Once GCC is installed, the problems go
away.
To work around this problem, when making the stage 1 compiler, specify
@@ -585,7 +588,7 @@ Some versions of the MIPS linker will issue an assertion failure
when linking code that uses @code{alloca} against shared
libraries on RISC-OS 5.0, and DEC's OSF/1 systems. This is a bug
in the linker, that is supposed to be fixed in future revisions.
-To protect against this, GNU CC passes @samp{-non_shared} to the
+To protect against this, GCC passes @samp{-non_shared} to the
linker unless you pass an explicit @samp{-shared} or
@samp{-call_shared} switch.
@@ -618,7 +621,7 @@ On System V, if you get an error like this,
that too indicates a problem with disk space, ULIMIT, or @code{MAXUMEM}.
@item
-Current GNU CC versions probably do not work on version 2 of the NeXT
+Current GCC versions probably do not work on version 2 of the NeXT
operating system.
@item
@@ -628,7 +631,7 @@ does not happen on 3.1.
@item
On the Tower models 4@var{n}0 and 6@var{n}0, by default a process is not
-allowed to have more than one megabyte of memory. GNU CC cannot compile
+allowed to have more than one megabyte of memory. GCC cannot compile
itself (or many other programs) with @samp{-O} in that much memory.
To solve this problem, reconfigure the kernel adding the following line
@@ -640,7 +643,7 @@ MAXUMEM = 4096
@item
On HP 9000 series 300 or 400 running HP-UX release 8.0, there is a bug
-in the assembler that must be fixed before GNU CC can be built. This
+in the assembler that must be fixed before GCC can be built. This
bug manifests itself during the first stage of compilation, while
building @file{libgcc2.a}:
@@ -677,13 +680,13 @@ use BASH (the GNU shell) to run @code{fixproto}.
@item
Some versions of the Pyramid C compiler are reported to be unable to
-compile GNU CC. You must use an older version of GNU CC for
+compile GCC. You must use an older version of GCC for
bootstrapping. One indication of this problem is if you get a crash
-when GNU CC compiles the function @code{muldi3} in file @file{libgcc2.c}.
+when GCC compiles the function @code{muldi3} in file @file{libgcc2.c}.
-You may be able to succeed by getting GNU CC version 1, installing it,
-and using it to compile GNU CC version 2. The bug in the Pyramid C
-compiler does not seem to affect GNU CC version 1.
+You may be able to succeed by getting GCC version 1, installing it,
+and using it to compile GCC version 2. The bug in the Pyramid C
+compiler does not seem to affect GCC version 1.
@item
There may be similar problems on System V Release 3.1 on 386 systems.
@@ -691,7 +694,7 @@ There may be similar problems on System V Release 3.1 on 386 systems.
@item
On the Intel Paragon (an i860 machine), if you are using operating
system version 1.0, you will get warnings or errors about redefinition
-of @code{va_arg} when you build GNU CC.
+of @code{va_arg} when you build GCC.
If this happens, then you need to link most programs with the library
@file{iclib.a}. You must also modify @file{stdio.h} as follows: before
@@ -728,7 +731,7 @@ insert the line
These problems don't exist in operating system version 1.1.
@item
-On the Altos 3068, programs compiled with GNU CC won't work unless you
+On the Altos 3068, programs compiled with GCC won't work unless you
fix a kernel bug. This happens using system versions V.2.2 1.0gT1 and
V.2.2 1.0e and perhaps later versions as well. See the file
@file{README.ALTOS}.
@@ -819,12 +822,12 @@ run. Incompatible libraries are then detected at link time, rather than
at run time.
@item
-Older GDB versions sometimes fail to read the output of GNU CC version
+Older GDB versions sometimes fail to read the output of GCC version
2. If you have trouble, get GDB version 4.4 or later.
@item
@cindex DBX
-DBX rejects some files produced by GNU CC, though it accepts similar
+DBX rejects some files produced by GCC, though it accepts similar
constructs in output from PCC. Until someone can supply a coherent
description of what is valid DBX input and what is not, there is
nothing I can do about these problems. You are on your own.
@@ -841,10 +844,10 @@ be run.
@item
Use of @samp{-I/usr/include} may cause trouble.
-Many systems come with header files that won't work with GNU CC unless
+Many systems come with header files that won't work with GCC unless
corrected by @code{fixincludes}. The corrected header files go in a new
-directory; GNU CC searches this directory before @file{/usr/include}.
-If you use @samp{-I/usr/include}, this tells GNU CC to search
+directory; GCC searches this directory before @file{/usr/include}.
+If you use @samp{-I/usr/include}, this tells GCC to search
@file{/usr/include} earlier on, before the corrected headers. The
result is that you get the uncorrected header files.
@@ -854,7 +857,7 @@ Instead, you should use these options (when compiling C programs):
-I/usr/local/lib/gcc-lib/@var{target}/@var{version}/include -I/usr/include
@end smallexample
-For C++ programs, GNU CC also uses a special directory that defines C++
+For C++ programs, GCC also uses a special directory that defines C++
interfaces to standard C subroutines. This directory is meant to be
searched @emph{before} other standard include directories, so that it
takes precedence. If you are compiling C++ programs and specifying
@@ -871,7 +874,7 @@ options above:
There is a bug in @code{vfork} on the Sun-4 which causes the registers
of the child process to clobber those of the parent. Because of this,
programs that call @code{vfork} are likely to lose when compiled
-optimized with GNU CC when the child code alters registers which contain
+optimized with GCC when the child code alters registers which contain
C variables in the parent. This affects variables which are live in the
parent across the call to @code{vfork}.
@@ -884,18 +887,18 @@ using @samp{-O} for those source files.
@item
On some SGI systems, when you use @samp{-lgl_s} as an option,
it gets translated magically to @samp{-lgl_s -lX11_s -lc_s}.
-Naturally, this does not happen when you use GNU CC.
+Naturally, this does not happen when you use GCC.
You must specify all three options explicitly.
@item
-On a Sparc, GNU CC aligns all values of type @code{double} on an 8-byte
+On a Sparc, GCC aligns all values of type @code{double} on an 8-byte
boundary, and it expects every @code{double} to be so aligned. The Sun
compiler usually gives @code{double} values 8-byte alignment, with one
exception: function arguments of type @code{double} may not be aligned.
As a result, if a function compiled with Sun CC takes the address of an
argument of type @code{double} and passes this pointer of type
-@code{double *} to a function compiled with GNU CC, dereferencing the
+@code{double *} to a function compiled with GCC, dereferencing the
pointer may cause a fatal signal.
One way to solve this problem is to compile your entire program with GNU
@@ -926,7 +929,7 @@ Storing into the pointer can be done likewise with the same union.
@item
On Solaris, the @code{malloc} function in the @file{libmalloc.a} library
-may allocate memory that is only 4 byte aligned. Since GNU CC on the
+may allocate memory that is only 4 byte aligned. Since GCC on the
Sparc assumes that doubles are 8 byte aligned, this may result in a
fatal signal if doubles are stored in memory allocated by the
@file{libmalloc.a} library.
@@ -951,20 +954,20 @@ instructions they must be emulated by the operating system. Long
doubles do not work in Sun OS versions 4.0.3 and earlier, because the
kernel emulator uses an obsolete and incompatible format. Long doubles
do not work in Sun OS version 4.1.1 due to a problem in a Sun library.
-Long doubles do work on Sun OS versions 4.1.2 and higher, but GNU CC
+Long doubles do work on Sun OS versions 4.1.2 and higher, but GCC
does not enable them by default. Long doubles appear to work in Sun OS
5.x (Solaris 2.x).
@item
On HP-UX version 9.01 on the HP PA, the HP compiler @code{cc} does not
-compile GNU CC correctly. We do not yet know why. However, GNU CC
+compile GCC correctly. We do not yet know why. However, GCC
compiled on earlier HP-UX versions works properly on HP-UX 9.01 and can
compile itself properly on 9.01.
@item
On the HP PA machine, ADB sometimes fails to work on functions compiled
-with GNU CC. Specifically, it fails to work on functions that use
-@code{alloca} or variable-size arrays. This is because GNU CC doesn't
+with GCC. Specifically, it fails to work on functions that use
+@code{alloca} or variable-size arrays. This is because GCC doesn't
generate HP-UX unwind descriptors for such functions. It may even be
impossible to generate them.
@@ -986,11 +989,11 @@ the HP assembler. GAS for the PA does not have this problem.
In extremely rare cases involving some very large functions you may
receive errors from the HP linker complaining about an out of bounds
unconditional branch offset. This used to occur more often in previous
-versions of GNU CC, but is now exceptionally rare. If you should run
+versions of GCC, but is now exceptionally rare. If you should run
into it, you can work around by making your function smaller.
@item
-GNU CC compiled code sometimes emits warnings from the HP-UX assembler of
+GCC compiled code sometimes emits warnings from the HP-UX assembler of
the form:
@smallexample
@@ -1064,7 +1067,7 @@ by requesting PTF 421749 from IBM.
@item
There is an assembler bug in versions of DG/UX prior to 5.4.2.01 that
-occurs when the @samp{fldcr} instruction is used. GNU CC uses
+occurs when the @samp{fldcr} instruction is used. GCC uses
@samp{fldcr} on the 88100 to serialize volatile memory references. Use
the option @samp{-mno-serialize-volatile} if your version of the
assembler has this bug.
@@ -1090,7 +1093,7 @@ lines around the definition of @code{size_t}:
@cindex Alliant
@item
On the Alliant, the system's own convention for returning structures
-and unions is unusual, and is not compatible with GNU CC no matter
+and unions is unusual, and is not compatible with GCC no matter
what options are used.
@cindex RT PC
@@ -1098,7 +1101,7 @@ what options are used.
@item
On the IBM RT PC, the MetaWare HighC compiler (hc) uses a different
convention for structure and union returning. Use the option
-@samp{-mhc-struct-return} to tell GNU CC to use a convention compatible
+@samp{-mhc-struct-return} to tell GCC to use a convention compatible
with it.
@cindex Vax calling convention
@@ -1108,7 +1111,7 @@ On Ultrix, the Fortran compiler expects registers 2 through 5 to be saved
by function calls. However, the C compiler uses conventions compatible
with BSD Unix: registers 2 through 5 may be clobbered by function calls.
-GNU CC uses the same convention as the Ultrix C compiler. You can use
+GCC uses the same convention as the Ultrix C compiler. You can use
these options to produce code compatible with the Fortran compiler:
@smallexample
@@ -1116,7 +1119,7 @@ these options to produce code compatible with the Fortran compiler:
@end smallexample
@item
-On the WE32k, you may find that programs compiled with GNU CC do not
+On the WE32k, you may find that programs compiled with GCC do not
work with the standard shared C library. You may need to link with
the ordinary C compiler. If you do so, you must specify the following
options:
@@ -1128,7 +1131,7 @@ options:
The first specifies where to find the library @file{libgcc.a}
specified with the @samp{-lgcc} option.
-GNU CC does linking by invoking @code{ld}, just as @code{cc} does, and
+GCC does linking by invoking @code{ld}, just as @code{cc} does, and
there is no reason why it @emph{should} matter which compilation program
you use to invoke @code{ld}. If someone tracks this problem down,
it can probably be fixed easily.
@@ -1145,7 +1148,7 @@ sometimes reorders instructions incorrectly when optimization is turned
on. If you think this may be happening to you, try using the GNU
assembler; GAS version 2.1 supports ECOFF on Irix.
-Or use the @samp{-noasmopt} option when you compile GNU CC with itself,
+Or use the @samp{-noasmopt} option when you compile GCC with itself,
and then again when you compile your program. (This is a temporary
kludge to turn off assembler optimization on Irix.) If this proves to
be what you need, edit the assembler spec in the file @file{specs} so
@@ -1197,13 +1200,13 @@ On various 386 Unix systems derived from System V, including SCO, ISC,
and ESIX, you may get error messages about running out of virtual memory
while compiling certain programs.
-You can prevent this problem by linking GNU CC with the GNU malloc
+You can prevent this problem by linking GCC with the GNU malloc
(which thus replaces the malloc that comes with the system). GNU malloc
is available as a separate package, and also in the file
@file{src/gmalloc.c} in the GNU Emacs 19 distribution.
If you have installed GNU malloc as a separate library package, use this
-option when you relink GNU CC:
+option when you relink GCC:
@example
MALLOC=/usr/local/lib/libgmalloc.a
@@ -1211,7 +1214,7 @@ MALLOC=/usr/local/lib/libgmalloc.a
Alternatively, if you have compiled @file{gmalloc.c} from Emacs 19, copy
the object file to @file{gmalloc.o} and use this option when you relink
-GNU CC:
+GCC:
@example
MALLOC=gmalloc.o
@@ -1219,8 +1222,8 @@ MALLOC=gmalloc.o
@end itemize
@node Incompatibilities
-@section Incompatibilities of GNU CC
-@cindex incompatibilities of GNU CC
+@section Incompatibilities of GCC
+@cindex incompatibilities of GCC
There are several noteworthy incompatibilities between GNU C and most
existing (non-ANSI) versions of C. The @samp{-traditional} option
@@ -1232,8 +1235,8 @@ telling GNU C to behave like the other C compilers.
@cindex read-only strings
@cindex shared strings
@item
-GNU CC normally makes string constants read-only. If several
-identical-looking string constants are used, GNU CC stores only one
+GCC normally makes string constants read-only. If several
+identical-looking string constants are used, GCC stores only one
copy of the string.
@cindex @code{mktemp}, and constant strings
@@ -1252,7 +1255,7 @@ constant. Likewise @code{fscanf} and @code{scanf}.
The best solution to these problems is to change the program to use
@code{char}-array variables with initialization strings for these
purposes instead of string constants. But if this is not possible,
-you can use the @samp{-fwritable-strings} flag, which directs GNU CC
+you can use the @samp{-fwritable-strings} flag, which directs GCC
to handle string constants the same way most C compilers do.
@samp{-traditional} also has this effect, among others.
@@ -1264,8 +1267,8 @@ This is because 2147483648 cannot fit in the type @code{int}, so
Negating this value yields 2147483648 again.
@item
-GNU CC does not substitute macro arguments when they appear inside of
-string constants. For example, the following macro in GNU CC
+GCC does not substitute macro arguments when they appear inside of
+string constants. For example, the following macro in GCC
@example
#define foo(a) "a"
@@ -1274,7 +1277,7 @@ string constants. For example, the following macro in GNU CC
@noindent
will produce output @code{"a"} regardless of what the argument @var{a} is.
-The @samp{-traditional} option directs GNU CC to handle such cases
+The @samp{-traditional} option directs GCC to handle such cases
(among others) in the old-fashioned (non-ANSI) fashion.
@cindex @code{setjmp} incompatibilities
@@ -1308,7 +1311,7 @@ its first value is restored; otherwise, it keeps the last value stored
in it.
If you use the @samp{-W} option with the @samp{-O} option, you will
-get a warning when GNU CC thinks such a problem might be possible.
+get a warning when GCC thinks such a problem might be possible.
The @samp{-traditional} option directs GNU C to put variables in
the stack by default, rather than in registers, in functions that
@@ -1317,7 +1320,7 @@ traditional C compilers.
@item
Programs that use preprocessing directives in the middle of macro
-arguments do not work with GNU CC. For example, a program like this
+arguments do not work with GCC. For example, a program like this
will not work:
@example
@@ -1366,17 +1369,17 @@ difficulty described immediately above applies here too.
@cindex whitespace
@item
PCC allows whitespace in the middle of compound assignment operators
-such as @samp{+=}. GNU CC, following the ANSI standard, does not
+such as @samp{+=}. GCC, following the ANSI standard, does not
allow this. The difficulty described immediately above applies here
too.
@cindex apostrophes
@cindex '
@item
-GNU CC complains about unterminated character constants inside of
+GCC complains about unterminated character constants inside of
preprocessing conditionals that fail. Some programs have English
comments enclosed in conditionals that are guaranteed to fail; if these
-comments contain apostrophes, GNU CC will probably report an error. For
+comments contain apostrophes, GCC will probably report an error. For
example, this code would produce an error:
@example
@@ -1403,38 +1406,38 @@ type of @code{time}.
@cindex @code{float} as function value type
@item
When compiling functions that return @code{float}, PCC converts it to
-a double. GNU CC actually returns a @code{float}. If you are concerned
+a double. GCC actually returns a @code{float}. If you are concerned
with PCC compatibility, you should declare your functions to return
@code{double}; you might as well say what you mean.
@cindex structures
@cindex unions
@item
-When compiling functions that return structures or unions, GNU CC
+When compiling functions that return structures or unions, GCC
output code normally uses a method different from that used on most
-versions of Unix. As a result, code compiled with GNU CC cannot call
+versions of Unix. As a result, code compiled with GCC cannot call
a structure-returning function compiled with PCC, and vice versa.
-The method used by GNU CC is as follows: a structure or union which is
+The method used by GCC is as follows: a structure or union which is
1, 2, 4 or 8 bytes long is returned like a scalar. A structure or union
with any other size is stored into an address supplied by the caller
(usually in a special, fixed register, but on some machines it is passed
on the stack). The machine-description macros @code{STRUCT_VALUE} and
-@code{STRUCT_INCOMING_VALUE} tell GNU CC where to pass this address.
+@code{STRUCT_INCOMING_VALUE} tell GCC where to pass this address.
By contrast, PCC on most target machines returns structures and unions
of any size by copying the data into an area of static storage, and then
returning the address of that storage as if it were a pointer value.
The caller must copy the data from that memory area to the place where
-the value is wanted. GNU CC does not use this method because it is
+the value is wanted. GCC does not use this method because it is
slower and nonreentrant.
On some newer machines, PCC uses a reentrant convention for all
-structure and union returning. GNU CC on most of these machines uses a
+structure and union returning. GCC on most of these machines uses a
compatible convention when returning structures and unions in memory,
but still returns small structures and unions in registers.
-You can tell GNU CC to use a compatible convention for all structure and
+You can tell GCC to use a compatible convention for all structure and
union returning with the option @samp{-fpcc-struct-return}.
@cindex preprocessing tokens
@@ -1460,13 +1463,13 @@ the minus sign. This whitespace will end the preprocessing number.
@node Fixed Headers
@section Fixed Header Files
-GNU CC needs to install corrected versions of some system header files.
+GCC needs to install corrected versions of some system header files.
This is because most target systems have some header files that won't
-work with GNU CC unless they are changed. Some have bugs, some are
+work with GCC unless they are changed. Some have bugs, some are
incompatible with ANSI C, and some depend on special features of other
compilers.
-Installing GNU CC automatically creates and installs the fixed header
+Installing GCC automatically creates and installs the fixed header
files, by running a program called @code{fixincludes} (or for certain
targets an alternative such as @code{fixinc.svr4}). Normally, you
don't need to pay attention to this. But there are cases where it
@@ -1475,8 +1478,8 @@ doesn't do the right thing automatically.
@itemize @bullet
@item
If you update the system's header files, such as by installing a new
-system version, the fixed header files of GNU CC are not automatically
-updated. The easiest way to update them is to reinstall GNU CC. (If
+system version, the fixed header files of GCC are not automatically
+updated. The easiest way to update them is to reinstall GCC. (If
you want to be clever, look in the makefile and you can find a
shortcut.)
@@ -1499,18 +1502,18 @@ different machine models, and arrange a structure of symbolic links so
as to use the proper set, but you'll have to do this by hand.
@item
-On Lynxos, GNU CC by default does not fix the header files. This is
+On Lynxos, GCC by default does not fix the header files. This is
because bugs in the shell cause the @code{fixincludes} script to fail.
This means you will encounter problems due to bugs in the system header
-files. It may be no comfort that they aren't GNU CC's fault, but it
+files. It may be no comfort that they aren't GCC's fault, but it
does mean that there's nothing for us to do about them.
@end itemize
@node Standard Libraries
@section Standard Libraries
-GNU CC by itself attempts to be what the ISO/ANSI C standard calls a
+GCC by itself attempts to be what the ISO/ANSI C standard calls a
@dfn{conforming freestanding implementation}. This means all ANSI
C language features are available, as well as the contents of
@file{float.h}, @file{limits.h}, @file{stdarg.h}, and
@@ -1526,7 +1529,7 @@ this function match the Standard, but that would be wrong, since the
function will still return @code{char *}.
If you need a Standard compliant library, then you need to find one, as
-GNU CC does not provide one. The GNU C library (called @code{glibc})
+GCC does not provide one. The GNU C library (called @code{glibc})
has been ported to a number of operating systems, and provides ANSI/ISO,
POSIX, BSD and SystemV compatibility. You could also ask your operating
system vendor if newer libraries are available.
@@ -1542,10 +1545,10 @@ way around them.
Certain local variables aren't recognized by debuggers when you compile
with optimization.
-This occurs because sometimes GNU CC optimizes the variable out of
+This occurs because sometimes GCC optimizes the variable out of
existence. There is no way to tell the debugger how to compute the
value such a variable ``would have had'', and it is not clear that would
-be desirable anyway. So GNU CC simply does not mention the eliminated
+be desirable anyway. So GCC simply does not mention the eliminated
variable when it writes debugging information.
You have to expect a certain amount of disagreement between the
@@ -1554,7 +1557,7 @@ executable and your source code, when you use optimization.
@cindex conflicting types
@cindex scope of declaration
@item
-Users often think it is a bug when GNU CC reports an error for code
+Users often think it is a bug when GCC reports an error for code
like this:
@example
@@ -1592,14 +1595,14 @@ If you care about controlling the amount of memory that is accessed, use
volatile but do not use bitfields.
@item
-GNU CC comes with shell scripts to fix certain known problems in system
+GCC comes with shell scripts to fix certain known problems in system
header files. They install corrected copies of various header files in
-a special directory where only GNU CC will normally look for them. The
+a special directory where only GCC will normally look for them. The
scripts adapt to various systems by searching all the system header
files for the problem cases that we know about.
If new system header files are installed, nothing automatically arranges
-to update the corrected header files. You will have to reinstall GNU CC
+to update the corrected header files. You will have to reinstall GCC
to fix the new header files. More specifically, go to the build
directory and delete the files @file{stmp-fixinc} and
@file{stmp-headers}, and the subdirectory @code{include}; then do
@@ -1643,15 +1646,16 @@ in scope at the time of the call.
@cindex misunderstandings in C++
@cindex surprises in C++
@cindex C++ misunderstandings
-C++ is a complex language and an evolving one, and its standard definition
-(the ANSI C++ draft standard) is also evolving. As a result,
-your C++ compiler may occasionally surprise you, even when its behavior is
-correct. This section discusses some areas that frequently give rise to
-questions of this sort.
+C++ is a complex language and an evolving one, and its standard
+definition (the ISO C++ standard) was only recently completed. As a
+result, your C++ compiler may occasionally surprise you, even when its
+behavior is correct. This section discusses some areas that frequently
+give rise to questions of this sort.
@menu
* Static Definitions:: Static member declarations are not definitions
* Temporaries:: Temporaries may vanish before you expect
+* Copy Assignment:: Copy Assignment operators copy virtual bases twice
@end menu
@node Static Definitions
@@ -1698,52 +1702,109 @@ symbols any static data members that lack definitions.
It is dangerous to use pointers or references to @emph{portions} of a
temporary object. The compiler may very well delete the object before
you expect it to, leaving a pointer to garbage. The most common place
-where this problem crops up is in classes like the libg++
-@code{String} class, that define a conversion function to type
-@code{char *} or @code{const char *}. However, any class that returns
-a pointer to some internal structure is potentially subject to this
-problem.
+where this problem crops up is in classes like string classes,
+especially ones that define a conversion function to type @code{char *}
+or @code{const char *} -- which is one reason why the standard
+@code{string} class requires you to call the @code{c_str} member
+function. However, any class that returns a pointer to some internal
+structure is potentially subject to this problem.
For example, a program may use a function @code{strfunc} that returns
-@code{String} objects, and another function @code{charfunc} that
+@code{string} objects, and another function @code{charfunc} that
operates on pointers to @code{char}:
@example
-String strfunc ();
+string strfunc ();
void charfunc (const char *);
+
+void
+f ()
+@{
+ const char *p = strfunc().c_str();
+ ...
+ charfunc (p);
+ ...
+ charfunc (p);
+@}
@end example
@noindent
-In this situation, it may seem natural to write @w{@samp{charfunc
-(strfunc ());}} based on the knowledge that class @code{String} has an
-explicit conversion to @code{char} pointers. However, what really
-happens is akin to @samp{charfunc (@w{strfunc ()}.@w{convert ()});},
-where the @code{convert} method is a function to do the same data
-conversion normally performed by a cast. Since the last use of the
-temporary @code{String} object is the call to the conversion function,
-the compiler may delete that object before actually calling
-@code{charfunc}. The compiler has no way of knowing that deleting the
-@code{String} object will invalidate the pointer. The pointer then
-points to garbage, so that by the time @code{charfunc} is called, it
-gets an invalid argument.
+In this situation, it may seem reasonable to save a pointer to the C
+string returned by the @code{c_str} member function and use that rather
+than call @code{c_str} repeatedly. However, the temporary string
+created by the call to @code{strfunc} is destroyed after @code{p} is
+initialized, at which point @code{p} is left pointing to freed memory.
Code like this may run successfully under some other compilers,
-especially those that delete temporaries relatively late. However, the
-GNU C++ behavior is also standard-conforming, so if your program depends
-on late destruction of temporaries it is not portable.
+particularly obsolete cfront-based compilers that delete temporaries
+along with normal local variables. However, the GNU C++ behavior is
+standard-conforming, so if your program depends on late destruction of
+temporaries it is not portable.
+
+The safe way to write such code is to give the temporary a name, which
+forces it to remain until the end of the scope of the name. For
+example:
+
+@example
+string& tmp = strfunc ();
+charfunc (tmp.c_str ());
+@end example
-If you think this is surprising, you should be aware that the ANSI C++
-committee continues to debate the lifetime-of-temporaries problem.
+@node Copy Assignment
+@subsection Implicit Copy-Assignment for Virtual Bases
-For now, at least, the safe way to write such code is to give the
-temporary a name, which forces it to remain until the end of the scope of
-the name. For example:
+When a base class is virtual, only one subobject of the base class
+belongs to each full object. Also, the constructors and destructors are
+invoked only once, and called from the most-derived class. However, such
+objects behave unspecified when being assigned. For example:
@example
-String& tmp = strfunc ();
-charfunc (tmp);
+struct Base@{
+ char *name;
+ Base(char *n) : name(strdup(n))@{@}
+ Base& operator= (const Base& other)@{
+ free (name);
+ name = strdup (other.name);
+ @}
+@};
+
+struct A:virtual Base@{
+ int val;
+ A():Base("A")@{@}
+@};
+
+struct B:virtual Base@{
+ int bval;
+ B():Base("B")@{@}
+@};
+
+struct Derived:public A, public B@{
+ Derived():Base("Derived")@{@}
+@};
+
+void func(Derived &d1, Derived &d2)
+@{
+ d1 = d2;
+@}
@end example
+The C++ standard specifies that @samp{Base::Base} is only called once
+when constructing or copy-constructing a Derived object. It is
+unspecified whether @samp{Base::operator=} is called more than once when
+the implicit copy-assignment for Derived objects is invoked (as it is
+inside @samp{func} in the example).
+
+g++ implements the "intuitive" algorithm for copy-assignment: assign all
+direct bases, then assign all members. In that algorithm, the virtual
+base subobject can be encountered many times. In the example, copying
+proceeds in the following order: @samp{val}, @samp{name} (via
+@code{strdup}), @samp{bval}, and @samp{name} again.
+
+If application code relies on copy-assignment, a user-defined
+copy-assignment operator removes any uncertainties. With such an
+operator, the application can define whether and how the virtual base
+subobject is assigned.
+
@node Protoize Caveats
@section Caveats of using @code{protoize}
@@ -1833,7 +1894,7 @@ eighty characters in any case.)
@section Certain Changes We Don't Want to Make
This section lists changes that people frequently request, but which
-we do not make because we think GNU CC is better without them.
+we do not make because we think GCC is better without them.
@itemize @bullet
@item
@@ -1934,12 +1995,12 @@ that machine. But such applications are rare. And users writing a
program to run on more than one type of machine cannot possibly benefit
from this kind of compatibility.
-This is why GNU CC does and will treat plain bitfields in the same
+This is why GCC does and will treat plain bitfields in the same
fashion on all types of machines (by default).
There are some arguments for making bitfields unsigned by default on all
machines. If, for example, this becomes a universal de facto standard,
-it would make sense for GNU CC to go along with it. This is something
+it would make sense for GCC to go along with it. This is something
to be considered in the future.
(Of course, users strongly concerned about portability should indicate
@@ -1949,7 +2010,7 @@ they write programs which have the same meaning in both C dialects.)
@item
Undefining @code{__STDC__} when @samp{-ansi} is not used.
-Currently, GNU CC defines @code{__STDC__} as long as you don't use
+Currently, GCC defines @code{__STDC__} as long as you don't use
@samp{-traditional}. This provides good results in practice.
Programmers normally use conditionals on @code{__STDC__} to ask whether
@@ -1975,11 +2036,11 @@ compilers such as plain @samp{gcc}. Whatever the ANSI C standard says
is relevant to the design of plain @samp{gcc} without @samp{-ansi} only
for pragmatic reasons, not as a requirement.
-GNU CC normally defines @code{__STDC__} to be 1, and in addition
+GCC normally defines @code{__STDC__} to be 1, and in addition
defines @code{__STRICT_ANSI__} if you specify the @samp{-ansi} option.
On some hosts, system include files use a different convention, where
@code{__STDC__} is normally 0, but is 1 if the user specifies strict
-conformance to the C Standard. GNU CC follows the host convention when
+conformance to the C Standard. GCC follows the host convention when
processing system include files, but when processing user files it follows
the usual GNU C convention.
@@ -2005,12 +2066,18 @@ test explicitly for C++ as well.
@item
Deleting ``empty'' loops.
-GNU CC does not delete ``empty'' loops because the most likely reason
-you would put one in a program is to have a delay. Deleting them will
-not make real programs run any faster, so it would be pointless.
+Historically, GCC has not deleted ``empty'' loops under the
+assumption that the most likely reason you would put one in a program is
+to have a delay, so deleting them will not make real programs run any
+faster.
-It would be different if optimization of a nonempty loop could produce
-an empty one. But this generally can't happen.
+However, the rationale here is that optimization of a nonempty loop
+cannot produce an empty one, which holds for C but is not always the
+case for C++.
+
+Moreover, with @samp{-funroll-loops} small ``empty'' loops are already
+removed, so the current behavior is both sub-optimal and inconsistent
+and will change in the future.
@item
Making side effects happen in the same order as in some other compiler.
@@ -2054,7 +2121,7 @@ warnings. Each kind has a different purpose:
@itemize @w{}
@item
@emph{Errors} report problems that make it impossible to compile your
-program. GNU CC reports errors with the source file name and line
+program. GCC reports errors with the source file name and line
number where the problem is apparent.
@item
@@ -2072,12 +2139,12 @@ warnings are issued only if you ask for them, with one of the @samp{-W}
options (for instance, @samp{-Wall} requests a variety of useful
warnings).
-GNU CC always tries to compile your program if possible; it never
+GCC always tries to compile your program if possible; it never
gratuitously rejects a program whose meaning is clear merely because
(for instance) it fails to conform to a standard. In some cases,
however, the C and C++ standards specify that certain extensions are
forbidden, and a diagnostic @emph{must} be issued by a conforming
-compiler. The @samp{-pedantic} option tells GNU CC to issue warnings in
+compiler. The @samp{-pedantic} option tells GCC to issue warnings in
such cases; @samp{-pedantic-errors} says to make them errors instead.
This does not mean that @emph{all} non-ANSI constructs get warnings
or errors.
@@ -2090,7 +2157,7 @@ more detail on these and related command-line options.
@cindex bugs
@cindex reporting bugs
-Your bug reports play an essential role in making GNU CC reliable.
+Your bug reports play an essential role in making GCC reliable.
When you encounter a problem, the first thing to do is to see if it is
already known. @xref{Trouble}. If it isn't known, then you should
@@ -2099,8 +2166,8 @@ report the problem.
Reporting a bug may help you by bringing a solution to your problem, or
it may not. (If it does not, look in the service directory; see
@ref{Service}.) In any case, the principal function of a bug report is
-to help the entire community by making the next version of GNU CC work
-better. Bug reports are your contribution to the maintenance of GNU CC.
+to help the entire community by making the next version of GCC work
+better. Bug reports are your contribution to the maintenance of GCC.
Since the maintainers are very overloaded, we cannot respond to every
bug report. However, if the bug has not been fixed, we are likely to
@@ -2113,7 +2180,7 @@ information that makes for fixing the bug.
* Criteria: Bug Criteria. Have you really found a bug?
* Where: Bug Lists. Where to send your bug report.
* Reporting: Bug Reporting. How to report a bug effectively.
-* Patches: Sending Patches. How to send a patch for GNU CC.
+* Patches: Sending Patches. How to send a patch for GCC.
* Known: Trouble. Known problems.
* Help: Service. Where to ask for help.
@end menu
@@ -2157,11 +2224,11 @@ by chance to give the desired results with another C or C++ compiler.
For example, in many nonoptimizing compilers, you can write @samp{x;}
at the end of a function instead of @samp{return x;}, with the same
results. But the value of the function is undefined if @code{return}
-is omitted; it is not a bug when GNU CC produces different results.
+is omitted; it is not a bug when GCC produces different results.
Problems often result from expressions with two increment operators,
as in @code{f (*p++, *p++)}. Your previous compiler might have
-interpreted that expression the way you intended; GNU CC might
+interpreted that expression the way you intended; GCC might
interpret it another way. Neither compiler is wrong. The bug is
in your code.
@@ -2181,20 +2248,23 @@ that is a compiler bug. However, you should note that your idea of
for traditional practice''.
@item
-If you are an experienced user of C or C++ compilers, your suggestions
-for improvement of GNU CC or GNU C++ are welcome in any case.
+If you are an experienced user of C or C++ (or Fortran or Objective-C)
+compilers, your suggestions
+for improvement of GCC are welcome in any case.
@end itemize
@node Bug Lists
@section Where to Report Bugs
@cindex bug report mailing lists
-@kindex egcs-bugs@@egcs.cygnus.com
-Send bug reports for GNU C to @samp{egcs-bugs@@egcs.cygnus.com}.
+@kindex gcc-bugs@@gcc.gnu.org or bug-gcc@@gnu.org
+Send bug reports for the GNU Compiler Collection to
+@samp{gcc-bugs@@gcc.gnu.org}. In accordance with the GNU-wide
+convention, in which bug reports for tool ``foo'' are sent
+to @samp{bug-foo@@gnu.org}, the address @samp{bug-gcc@@gnu.org}
+may also be used; it will forward to the address given above.
-@kindex egcs-bugs@@egcs.cygnus.com
-@kindex egcs-bugs@@egcs.cygnus.com
-Send bug reports for GNU C++ and the C++ runtime libraries to
-@samp{egcs-bugs@@egcs.cygnus.com}.
+Please read @samp{<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>} for
+bug reporting instructions before you post a bug report.
Often people think of posting bug reports to the newsgroup instead of
mailing them. This appears to work, but it has one problem which can be
@@ -2216,6 +2286,9 @@ Boston, MA 02111-1307, USA
@section How to Report Bugs
@cindex compiler bugs, reporting
+You may find additional and/or more up-to-date instructions at
+@samp{<URL:http://www.gnu.org/software/gcc/faq.html#bugreport>}.
+
The fundamental principle of reporting bugs usefully is this:
@strong{report all the facts}. If you are not sure whether to state a
fact or leave it out, state it!
@@ -2248,40 +2321,26 @@ Please report each bug in a separate message. This makes it easier for
us to track which bugs have been fixed and to forward your bugs reports
to the appropriate maintainer.
-If you include source code in your message, you can send it as clear
-text if it is small. If the message is larger, you may compress it using
-@file{gzip}, @file{bzip2}, or @file{pkzip}. Please be aware that sending
-compressed files needs an additional binary-safe mechanism such as
-@code{MIME} or @code{uuencode}. There is a 100k message limit on the
-@samp{egcs-bugs@@egcs.cygnus.com} mailing list at the time of this
-writing (March 1999). We're trying to create some mechanism for larger
-bug reports to be submitted; please check the on-line FAQ for more
-up-to-date instructions. Don't think that just posting a URL to the
-code is better, we do want to archive bug reports, and not all
-maintainers have good network connectivity to download large pieces of
-software when they need them; it's much easier for them to have them in
-their mailboxes.
-
To enable someone to investigate the bug, you should include all these
things:
@itemize @bullet
@item
-The version of GNU CC. You can get this by running it with the
+The version of GCC. You can get this by running it with the
@samp{-v} option.
Without this, we won't know whether there is any point in looking for
-the bug in the current version of GNU CC.
+the bug in the current version of GCC.
@item
A complete input file that will reproduce the bug. If the bug is in the
C preprocessor, send a source file and any header files that it
-requires. If the bug is in the compiler proper (@file{cc1}), run your
-source file through the C preprocessor by doing @samp{gcc -E
-@var{sourcefile} > @var{outfile}}, then include the contents of
-@var{outfile} in the bug report. (When you do this, use the same
-@samp{-I}, @samp{-D} or @samp{-U} options that you used in actual
-compilation.)
+requires. If the bug is in the compiler proper (@file{cc1}), send the
+preprocessor output generated by adding @samp{-save-temps} to the
+compilation command (@pxref{Debugging Options}). When you do this, use
+the same @samp{-I}, @samp{-D} or @samp{-U} options that you used in
+actual compilation. Then send the @var{input}.i or @var{input}.ii files
+generated.
A single statement is not enough of an example. In order to compile it,
it must be embedded in a complete file of compiler input; and the bug
@@ -2293,16 +2352,16 @@ provoke the bug. For example, bugs in register allocation and reloading
frequently depend on every little detail of the function they happen in.
Even if the input file that fails comes from a GNU program, you should
-still send the complete test case. Don't ask the GNU CC maintainers to
+still send the complete test case. Don't ask the GCC maintainers to
do the extra work of obtaining the program in question---they are all
overworked as it is. Also, the problem may depend on what is in the
-header files on your system; it is unreliable for the GNU CC maintainers
+header files on your system; it is unreliable for the GCC maintainers
to try the problem with the header files available to them. By sending
CPP output, you can eliminate this source of uncertainty and save us
a certain percentage of wild goose chases.
@item
-The command arguments you gave GNU CC or GNU C++ to compile that example
+The command arguments you gave GCC to compile that example
and observe the bug. For example, did you use @samp{-O}? To guarantee
you won't omit something important, list all the options.
@@ -2331,7 +2390,7 @@ don't support) is a modification of the compiler source.
@item
Details of any other deviations from the standard procedure for installing
-GNU CC.
+GCC.
@item
A description of what behavior you observe that you believe is
@@ -2354,7 +2413,7 @@ was not happening. If you don't say to expect a crash, then we would
not know whether the bug was happening. We would not be able to draw
any conclusion from our observations.
-If the problem is a diagnostic when compiling GNU CC with some other
+If the problem is a diagnostic when compiling GCC with some other
compiler, say whether it is a warning or an error.
Often the observed symptom is incorrect output when your program is run.
@@ -2367,13 +2426,13 @@ person who understands the program can find this as easily as finding a
bug in the program itself.
@item
-If you send examples of assembler code output from GNU CC or GNU C++,
+If you send examples of assembler code output from GCC,
please use @samp{-g} when you make them. The debugging information
includes source line numbers which are essential for correlating the
output with the input.
@item
-If you wish to mention something in the GNU CC source, refer to it by
+If you wish to mention something in the GCC source, refer to it by
context, not by line number.
The line numbers in the development sources don't match those in your
@@ -2389,7 +2448,7 @@ any chance of being useful.
@cindex backtrace for bug reports
For example, many people send just a backtrace, but that is never
useful by itself. A simple backtrace with arguments conveys little
-about GNU CC because the compiler is largely data-driven; the same
+about GCC because the compiler is largely data-driven; the same
functions are called over and over for different RTL insns, doing
different things depending on the details of the insn.
@@ -2433,7 +2492,7 @@ as well save your time for something else.
Of course, if you can find a simpler example to report @emph{instead} of
the original one, that is a convenience. Errors in the output will be
easier to spot, running under the debugger will take less time, etc.
-Most GNU CC bugs involve just one function, so the most straightforward
+Most GCC bugs involve just one function, so the most straightforward
way to simplify an example is to delete all the function definitions
except the one where the bug occurs. Those earlier in the file may be
replaced by external declarations if the crucial function depends on
@@ -2457,7 +2516,7 @@ necessary information, such as the test case, on the assumption that a
patch is all we need. We might see problems with your patch and decide
to fix the problem another way, or we might not understand it at all.
-Sometimes with a program as complicated as GNU CC it is very hard to
+Sometimes with a program as complicated as GCC it is very hard to
construct an example that will make the program follow a certain path
through the code. If you don't send the example, we won't be able to
construct one, so we won't be able to verify that the bug is fixed.
@@ -2484,11 +2543,11 @@ we should be able to reproduce the crash ourselves.
@end itemize
@node Sending Patches,, Bug Reporting, Bugs
-@section Sending Patches for GNU CC
+@section Sending Patches for GCC
If you would like to write bug fixes or improvements for the GNU C
-compiler, that is very helpful. Send suggested fixes to the bug report
-mailing list, @code{egcs-bugs@@egcs.cygnus.com}.
+compiler, that is very helpful. Send suggested fixes to the patches
+mailing list, @code{gcc-patches@@gcc.gnu.org}.
Please follow these guidelines so we can study your patches efficiently.
If you don't follow these guidelines, your information might still be
@@ -2581,7 +2640,7 @@ would break other systems.
People often suggest fixing a problem by changing machine-independent
files such as @file{toplev.c} to do something special that a particular
system needs. Sometimes it is totally obvious that such changes would
-break GNU CC for almost all users. We can't possibly make a change like
+break GCC for almost all users. We can't possibly make a change like
that. At best it might tell us how to write another patch that would
solve the problem acceptably.
@@ -2600,48 +2659,48 @@ form that is good to install.
@end itemize
@node Service
-@chapter How To Get Help with GNU CC
+@chapter How To Get Help with GCC
-If you need help installing, using or changing GNU CC, there are two
+If you need help installing, using or changing GCC, there are two
ways to find it:
@itemize @bullet
@item
Send a message to a suitable network mailing list. First try
-@code{egcs-bugs@@egcs.cygnus.com}, and if that brings no response, try
-@code{egcs@@egcs.cygnus.com}.
+@code{gcc-bugs@@gcc.gnu.org} or @code{bug-gcc@@gnu.org}, and if that
+brings no response, try @code{gcc@@gcc.gnu.org}.
@item
Look in the service directory for someone who might help you for a fee.
The service directory is found in the file named @file{SERVICE} in the
-GNU CC distribution.
+GCC distribution.
@end itemize
@node Contributing
-@chapter Contributing to GNU CC Development
+@chapter Contributing to GCC Development
-If you would like to help pretest GNU CC releases to assure they work
-well, or if you would like to work on improving GNU CC, please contact
-the maintainers at @code{egcs@@egcs.cygnus.com}. A pretester should
+If you would like to help pretest GCC releases to assure they work
+well, or if you would like to work on improving GCC, please contact
+the maintainers at @code{gcc@@gcc.gnu.org}. A pretester should
be willing to try to investigate bugs as well as report them.
If you'd like to work on improvements, please ask for suggested projects
or suggest your own ideas. If you have already written an improvement,
please tell us about it. If you have not yet started work, it is useful
-to contact @code{egcs@@egcs.cygnus.com} before you start; the
+to contact @code{gcc@@gcc.gnu.org} before you start; the
maintainers may be able to suggest ways to make your extension fit in
-better with the rest of GNU CC and with other development plans.
+better with the rest of GCC and with other development plans.
@node VMS
-@chapter Using GNU CC on VMS
+@chapter Using GCC on VMS
@c prevent bad page break with this line
-Here is how to use GNU CC on VMS.
+Here is how to use GCC on VMS.
@menu
* Include Files and VMS:: Where the preprocessor looks for the include files.
* Global Declarations:: How to do globaldef, globalref and globalvalue with
- GNU CC.
+ GCC.
* VMS Misc:: Misc information.
@end menu
@@ -2651,11 +2710,11 @@ Here is how to use GNU CC on VMS.
@cindex include files and VMS
@cindex VMS and include files
@cindex header files and VMS
-Due to the differences between the filesystems of Unix and VMS, GNU CC
+Due to the differences between the filesystems of Unix and VMS, GCC
attempts to translate file names in @samp{#include} into names that VMS
will understand. The basic strategy is to prepend a prefix to the
specification of the include file, convert the whole filename to a VMS
-filename, and then try to open the file. GNU CC tries various prefixes
+filename, and then try to open the file. GCC tries various prefixes
one by one until one of them succeeds:
@enumerate
@@ -2699,9 +2758,9 @@ Include directives of the form:
@end example
@noindent
-are a common source of incompatibility between VAX-C and GNU CC. VAX-C
+are a common source of incompatibility between VAX-C and GCC. VAX-C
treats this much like a standard @code{#include <foobar.h>} directive.
-That is incompatible with the ANSI C behavior implemented by GNU CC: to
+That is incompatible with the ANSI C behavior implemented by GCC: to
expand the name @code{foobar} as a macro. Macro expansion should
eventually yield one of the two standard formats for @code{#include}:
@@ -2730,17 +2789,17 @@ Another source of incompatibility is that VAX-C assumes that:
@end example
@noindent
-is actually asking for the file @file{foobar.h}. GNU CC does not
+is actually asking for the file @file{foobar.h}. GCC does not
make this assumption, and instead takes what you ask for literally;
it tries to read the file @file{foobar}. The best way to avoid this
problem is to always specify the desired file extension in your include
directives.
-GNU CC for VMS is distributed with a set of include files that is
+GCC for VMS is distributed with a set of include files that is
sufficient to compile most general purpose programs. Even though the
-GNU CC distribution does not contain header files to define constants
+GCC distribution does not contain header files to define constants
and structures for some VMS system-specific functions, there is no
-reason why you cannot use GNU CC with any of these functions. You first
+reason why you cannot use GCC with any of these functions. You first
may have to generate or create header files, either by using the public
domain utility @code{UNSDL} (which can be found on a DECUS tape), or by
extracting the relevant modules from one of the system macro libraries,
@@ -2757,7 +2816,7 @@ whether explicitly, or implicitly via a logical name.
@findex GLOBALDEF
@findex GLOBALVALUEDEF
@findex GLOBALVALUEREF
-GNU CC does not provide the @code{globalref}, @code{globaldef} and
+GCC does not provide the @code{globalref}, @code{globaldef} and
@code{globalvalue} keywords of VAX-C. You can get the same effect with
an obscure feature of GAS, the GNU assembler. (This requires GAS
version 1.39 or later.) The following macros allow you to use this
@@ -2876,19 +2935,19 @@ enum globaldef color @{RED, BLUE, GREEN = 3@};
@cindex exit status and VMS
@cindex return value of @code{main}
@cindex @code{main} and the exit status
-GNU CC automatically arranges for @code{main} to return 1 by default if
+GCC automatically arranges for @code{main} to return 1 by default if
you fail to specify an explicit return value. This will be interpreted
by VMS as a status code indicating a normal successful completion.
-Version 1 of GNU CC did not provide this default.
+Version 1 of GCC did not provide this default.
-GNU CC on VMS works only with the GNU assembler, GAS. You need version
+GCC on VMS works only with the GNU assembler, GAS. You need version
1.37 or later of GAS in order to produce value debugging information for
the VMS debugger. Use the ordinary VMS linker with the object files
produced by GAS.
@cindex shared VMS run time system
@cindex @file{VAXCRTL}
-Under previous versions of GNU CC, the generated code would occasionally
+Under previous versions of GCC, the generated code would occasionally
give strange results when linked to the sharable @file{VAXCRTL} library.
Now this should work.
@@ -2905,10 +2964,10 @@ placed in writable storage.
Although the VMS linker does distinguish between upper and lower case
letters in global symbols, most VMS compilers convert all such symbols
into upper case and most run-time library routines also have upper case
-names. To be able to reliably call such routines, GNU CC (by means of
+names. To be able to reliably call such routines, GCC (by means of
the assembler GAS) converts global symbols into upper case like other
VMS compilers. However, since the usual practice in C is to distinguish
-case, GNU CC (via GAS) tries to preserve usual C behavior by augmenting
+case, GCC (via GAS) tries to preserve usual C behavior by augmenting
each name that is not all lower case. This means truncating the name
to at most 23 characters and then adding more characters at the end
which encode the case pattern of those 23. Names which contain at
@@ -2962,16 +3021,16 @@ number of changes to your source code.
@ifset INTERNALS
@node Portability
-@chapter GNU CC and Portability
+@chapter GCC and Portability
@cindex portability
-@cindex GNU CC and portability
+@cindex GCC and portability
-The main goal of GNU CC was to make a good, fast compiler for machines in
+The main goal of GCC was to make a good, fast compiler for machines in
the class that the GNU system aims to run on: 32-bit machines that address
8-bit bytes and have several general registers. Elegance, theoretical
power and simplicity are only secondary.
-GNU CC gets most of the information about the target machine from a machine
+GCC gets most of the information about the target machine from a machine
description which gives an algebraic formula for each of the machine's
instructions. This is a very clean way to describe the target. But when
the compiler needs information that is difficult to express in this
@@ -2982,7 +3041,7 @@ on the compiler; it was not of interest for its own sake.
@cindex endianness
@cindex autoincrement addressing, availability
@findex abort
-GNU CC does not contain machine dependent code, but it does contain code
+GCC does not contain machine dependent code, but it does contain code
that depends on machine parameters such as endianness (whether the most
significant byte has the highest or lowest address of the bytes in a word)
and the availability of autoincrement addressing. In the RTL-generation
@@ -2998,13 +3057,13 @@ affect only the target machines that need them.
@ifset INTERNALS
@node Interface
-@chapter Interfacing to GNU CC Output
-@cindex interfacing to GNU CC output
+@chapter Interfacing to GCC Output
+@cindex interfacing to GCC output
@cindex run-time conventions
@cindex function call conventions
@cindex conventions, run-time
-GNU CC is normally configured to use the same function calling convention
+GCC is normally configured to use the same function calling convention
normally in use on the target system. This is done with the
machine-description macros described (@pxref{Target Macros}).
@@ -3013,43 +3072,43 @@ machine-description macros described (@pxref{Target Macros}).
@cindex returning structures and unions
However, returning of structure and union values is done differently on
some target machines. As a result, functions compiled with PCC
-returning such types cannot be called from code compiled with GNU CC,
+returning such types cannot be called from code compiled with GCC,
and vice versa. This does not cause trouble often because few Unix
library routines return structures or unions.
-GNU CC code returns structures and unions that are 1, 2, 4 or 8 bytes
+GCC code returns structures and unions that are 1, 2, 4 or 8 bytes
long in the same registers used for @code{int} or @code{double} return
-values. (GNU CC typically allocates variables of such types in
+values. (GCC typically allocates variables of such types in
registers also.) Structures and unions of other sizes are returned by
storing them into an address passed by the caller (usually in a
register). The machine-description macros @code{STRUCT_VALUE} and
-@code{STRUCT_INCOMING_VALUE} tell GNU CC where to pass this address.
+@code{STRUCT_INCOMING_VALUE} tell GCC where to pass this address.
By contrast, PCC on most target machines returns structures and unions
of any size by copying the data into an area of static storage, and then
returning the address of that storage as if it were a pointer value.
The caller must copy the data from that memory area to the place where
-the value is wanted. This is slower than the method used by GNU CC, and
+the value is wanted. This is slower than the method used by GCC, and
fails to be reentrant.
On some target machines, such as RISC machines and the 80386, the
standard system convention is to pass to the subroutine the address of
-where to return the value. On these machines, GNU CC has been
+where to return the value. On these machines, GCC has been
configured to be compatible with the standard compiler, when this method
is used. It may not be compatible for structures of 1, 2, 4 or 8 bytes.
@cindex argument passing
@cindex passing arguments
-GNU CC uses the system's standard convention for passing arguments. On
+GCC uses the system's standard convention for passing arguments. On
some machines, the first few arguments are passed in registers; in
others, all are passed on the stack. It would be possible to use
registers for argument passing on any machine, and this would probably
result in a significant speedup. But the result would be complete
incompatibility with code that follows the standard convention. So this
-change is practical only if you are switching to GNU CC as the sole C
+change is practical only if you are switching to GCC as the sole C
compiler for the system. We may implement register argument passing on
certain machines once we have a complete GNU system so that we can
-compile the libraries with GNU CC.
+compile the libraries with GCC.
On some machines (particularly the Sparc), certain types of arguments
are passed ``by invisible reference''. This means that the value is
@@ -3059,9 +3118,9 @@ the subroutine.
@cindex @code{longjmp} and automatic variables
If you use @code{longjmp}, beware of automatic variables. ANSI C says that
automatic variables that are not declared @code{volatile} have undefined
-values after a @code{longjmp}. And this is all GNU CC promises to do,
+values after a @code{longjmp}. And this is all GCC promises to do,
because it is very difficult to restore register variables correctly, and
-one of GNU CC's features is that it can put variables in registers without
+one of GCC's features is that it can put variables in registers without
your asking it to.
If you want a variable to be unaltered by @code{longjmp}, and you don't
@@ -3080,7 +3139,7 @@ go in a register:
@cindex arithmetic libraries
@cindex math libraries
-Code compiled with GNU CC may call certain library routines. Most of
+Code compiled with GCC may call certain library routines. Most of
them handle arithmetic for which there are no instructions. This
includes multiply and divide on some machines, and floating point
operations on any machine for which floating point support is disabled
@@ -3089,7 +3148,7 @@ with @samp{-msoft-float}. Some standard parts of the C library, such as
function call interface is used for calling the library routines.
These library routines should be defined in the library @file{libgcc.a},
-which GNU CC automatically searches whenever it links a program. On
+which GCC automatically searches whenever it links a program. On
machines that have multiply and divide instructions, if hardware
floating point is in use, normally @file{libgcc.a} is not needed, but it
is searched just in case.
@@ -3098,7 +3157,7 @@ Each arithmetic function is defined in @file{libgcc1.c} to use the
corresponding C arithmetic operator. As long as the file is compiled
with another C compiler, which supports all the C arithmetic operators,
this file will work portably. However, @file{libgcc1.c} does not work if
-compiled with GNU CC, because each arithmetic function would compile
+compiled with GCC, because each arithmetic function would compile
into a call to itself!
@end ifset
@@ -3253,7 +3312,7 @@ function must meet certain criteria, currently related to the size of
the function and the types and number of parameters it has. Note that
this function may contain loops, recursive calls to itself
(tail-recursive functions can be inlined!), gotos, in short, all
-constructs supported by GNU CC. The file @file{integrate.c} contains
+constructs supported by GCC. The file @file{integrate.c} contains
the code to save a function's rtl for later inlining and to inline that
rtl when the function is called. The header file @file{integrate.h}
is also used for this purpose.
@@ -3394,6 +3453,18 @@ The option @samp{-dc} causes a debugging dump of the RTL code after
this pass. This dump file's name is made by appending @samp{.combine}
to the input file name.
+@cindex register movement
+@item
+Register movement (@file{regmove.c}). This pass looks for cases where
+matching constraints would force an instruction to need a reload, and
+this reload would be a register to register move. It them attempts
+to change the registers used by the instruction to avoid the move
+instruction.
+
+The option @samp{-dN} causes a debugging dump of the RTL code after
+this pass. This dump file's name is made by appending @samp{.regmove}
+to the input file name.
+
@cindex instruction scheduling
@cindex scheduling, instruction
@item
@@ -3592,7 +3663,7 @@ definitions that describe the machine and system on which the compiler
is running, unlike the definitions in @file{@var{machine}.h}, which
describe the machine for which the compiler is producing output. Most
of the values in @file{xm-@var{machine}.h} are actually the same on all
-machines that GNU CC runs on, so large parts of all configuration files
+machines that GCC runs on, so large parts of all configuration files
are identical. But there are some macros that vary:
@table @code
@@ -3617,7 +3688,7 @@ exits without serious errors.
@findex HOST_WORDS_BIG_ENDIAN
@item HOST_WORDS_BIG_ENDIAN
Defined if the host machine stores words of multi-word values in
-big-endian order. (GNU CC does not depend on the host byte ordering
+big-endian order. (GCC does not depend on the host byte ordering
within a word.)
@findex HOST_FLOAT_WORDS_BIG_ENDIAN
@@ -3696,7 +3767,7 @@ If you do define this macro, you should probably do it as follows:
@end example
@noindent
-so that when the compiler is compiled with GNU CC it uses the more
+so that when the compiler is compiled with GCC it uses the more
efficient built-in @code{alloca} function.
@item FUNCTION_CONVERSION_BUG
@@ -3708,7 +3779,7 @@ used in an expression.
@findex MULTIBYTE_CHARS
@item MULTIBYTE_CHARS
Define this macro to enable support for multibyte characters in the
-input to GNU CC. This requires that the host system support the ANSI C
+input to GCC. This requires that the host system support the ANSI C
library functions for converting multibyte characters to wide
characters.
@@ -3739,7 +3810,7 @@ Therefore, if you define @code{sys_siglist}, you should also define
Define this to be 1 if you know that the host compiler supports
prototypes, even if it doesn't define __STDC__, or define
it to be 0 if you do not want any prototypes used in compiling
-GNU CC. If @samp{USE_PROTOTYPES} is not defined, it will be
+GCC. If @samp{USE_PROTOTYPES} is not defined, it will be
determined automatically whether your compiler supports
prototypes by checking if @samp{__STDC__} is defined.
@@ -3747,7 +3818,7 @@ prototypes by checking if @samp{__STDC__} is defined.
@item NO_MD_PROTOTYPES
Define this if you wish suppression of prototypes generated from
the machine description file, but to use other prototypes within
-GNU CC. If @samp{USE_PROTOTYPES} is defined to be 0, or the
+GCC. If @samp{USE_PROTOTYPES} is defined to be 0, or the
host compiler does not support prototypes, this macro has no
effect.
@@ -3772,20 +3843,20 @@ the colon character
@item DIR_SEPARATOR
If your system uses some character other than slash to separate
directory names within a file specification, define this macro to be a C
-character constant specifying that character. When GNU CC displays file
-names, the character you specify will be used. GNU CC will test for
+character constant specifying that character. When GCC displays file
+names, the character you specify will be used. GCC will test for
both slash and the character you specify when parsing filenames.
@findex OBJECT_SUFFIX
@item OBJECT_SUFFIX
Define this macro to be a C string representing the suffix for object
-files on your machine. If you do not define this macro, GNU CC will use
+files on your machine. If you do not define this macro, GCC will use
@samp{.o} as the suffix for object files.
@findex EXECUTABLE_SUFFIX
@item EXECUTABLE_SUFFIX
Define this macro to be a C string representing the suffix for executable
-files on your machine. If you do not define this macro, GNU CC will use
+files on your machine. If you do not define this macro, GCC will use
the null string as the suffix for object files.
@findex COLLECT_EXPORT_LIST
@@ -3801,14 +3872,14 @@ lists.
@findex bcmp
In addition, configuration files for system V define @code{bcopy},
@code{bzero} and @code{bcmp} as aliases. Some files define @code{alloca}
-as a macro when compiled with GNU CC, in order to take advantage of the
-benefit of GNU CC's built-in @code{alloca}.
+as a macro when compiled with GCC, in order to take advantage of the
+benefit of GCC's built-in @code{alloca}.
@node Fragments
@chapter Makefile Fragments
@cindex makefile fragment
-When you configure GNU CC using the @file{configure} script
+When you configure GCC using the @file{configure} script
(@pxref{Installation}), it will construct the file @file{Makefile} from
the template file @file{Makefile.in}. When it does this, it will
incorporate makefile fragment files from the @file{config} directory,
@@ -3866,11 +3937,11 @@ in @code{EXTRA-PARTS}.
@findex MULTILIB_OPTIONS
@item MULTILIB_OPTIONS
-For some targets, invoking GNU CC in different ways produces objects
-that can not be linked together. For example, for some targets GNU CC
+For some targets, invoking GCC in different ways produces objects
+that can not be linked together. For example, for some targets GCC
produces both big and little endian code. For these targets, you must
arrange for multiple versions of @file{libgcc.a} to be compiled, one for
-each set of incompatible options. When GNU CC invokes the linker, it
+each set of incompatible options. When GCC invokes the linker, it
arranges to link in the right version of @file{libgcc.a}, based on
the command line options used.
@@ -3903,7 +3974,7 @@ you desire a different set of directory names.
@findex MULTILIB_MATCHES
@item MULTILIB_MATCHES
Sometimes the same option may be written in two different ways. If an
-option is listed in @code{MULTILIB_OPTIONS}, GNU CC needs to know about
+option is listed in @code{MULTILIB_OPTIONS}, GCC needs to know about
any synonyms. In that case, set @code{MULTILIB_MATCHES} to a list of
items of the form @samp{option=option} to describe all relevant
synonyms. For example, @samp{m68000=mc68000 m68020=mc68020}.
@@ -3997,7 +4068,7 @@ difference than others. For example, maintaining a separate version of
a program contributes very little; maintaining the standard version of a
program for the whole community contributes much. Easy new ports
contribute little, since someone else would surely do them; difficult
-ports such as adding a new CPU to the GNU C compiler contribute more;
+ports such as adding a new CPU to the GNU Compiler Collection contribute more;
major new features or packages contribute the most.
By establishing the idea that supporting further development is ``the
@@ -4447,7 +4518,7 @@ the ``copyright'' line and a pointer to where the full notice is found.
@smallexample
@var{one line to give the program's name and a brief idea of what it does.}
-Copyright (C) 19@var{yy} @var{name of author}
+Copyright (C) @var{yyyy} @var{name of author}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -4470,7 +4541,7 @@ If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
@smallexample
-Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision version 69, Copyright (C) @var{yyyy} @var{name of author}
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'.
This is free software, and you are welcome to redistribute it
@@ -4502,11 +4573,11 @@ library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
@node Contributors
-@unnumbered Contributors to GNU CC
+@unnumbered Contributors to GCC
@cindex contributors
In addition to Richard Stallman, several people have written parts
-of GNU CC.
+of GCC.
@itemize @bullet
@item
@@ -4558,13 +4629,13 @@ Randy Smith finished the Sun FPA support.
Robert Brown implemented the support for Encore 32000 systems.
@item
-David Kashtan of SRI adapted GNU CC to VMS.
+David Kashtan of SRI adapted GCC to VMS.
@item
Alex Crain provided changes for the 3b1.
@item
-Greg Satz and Chris Hanson assisted in making GNU CC work on HP-UX for
+Greg Satz and Chris Hanson assisted in making GCC work on HP-UX for
the 9000 series 300.
@item
@@ -4581,16 +4652,16 @@ Dario Dariol contributed the four varieties of sample programs
that print a copy of their source.
@item
-Alain Lichnewsky ported GNU CC to the Mips cpu.
+Alain Lichnewsky ported GCC to the Mips cpu.
@item
-Devon Bowen, Dale Wiles and Kevin Zachmann ported GNU CC to the Tahoe.
+Devon Bowen, Dale Wiles and Kevin Zachmann ported GCC to the Tahoe.
@item
Jonathan Stone wrote the machine description for the Pyramid computer.
@item
-Gary Miller ported GNU CC to Charles River Data Systems machines.
+Gary Miller ported GCC to Charles River Data Systems machines.
@item
Richard Kenner of the New York University Ultracomputer Research
diff --git a/contrib/gcc/gccspec.c b/contrib/gcc/gccspec.c
new file mode 100644
index 0000000..78c67d2
--- /dev/null
+++ b/contrib/gcc/gccspec.c
@@ -0,0 +1,43 @@
+/* Specific flags and argument handling of the C front-end.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+
+/* Filter argc and argv before processing by the gcc driver proper. */
+void
+lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
+ void (*fn)() ATTRIBUTE_UNUSED;
+ int *in_argc ATTRIBUTE_UNUSED;
+ char ***in_argv ATTRIBUTE_UNUSED;
+ int *in_added_libraries ATTRIBUTE_UNUSED;
+{
+ return; /* Not used for C. */
+}
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
+int
+lang_specific_pre_link ()
+{
+ return 0; /* Not used for C. */
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for C. */
diff --git a/contrib/gcc/gcov-io.h b/contrib/gcc/gcov-io.h
index c2949a3..d2605fe 100644
--- a/contrib/gcc/gcov-io.h
+++ b/contrib/gcc/gcov-io.h
@@ -1,5 +1,5 @@
/* Machine-independent I/O routines for gcov.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Bob Manson <manson@cygnus.com>.
This file is part of GNU CC.
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <sys/types.h>
-static int __fetch_long PROTO ((long *, char *, int));
+static int __fetch_long PROTO ((long *, char *, size_t));
static int __store_long PROTO ((long, char *, size_t));
static int __read_long PROTO ((long *, FILE *, size_t));
static int __write_long PROTO ((long, FILE *, size_t));
@@ -74,17 +74,17 @@ static int
__fetch_long (dest, source, bytes)
long *dest;
char *source;
- int bytes;
+ size_t bytes;
{
long value = 0;
int i;
- for (i = bytes - 1; i > (sizeof (*dest) - 1); i--)
- if (source[i] & (i == (bytes - 1) ? 127 : 255 ))
+ for (i = bytes - 1; (size_t) i > (sizeof (*dest) - 1); i--)
+ if (source[i] & ((size_t) i == (bytes - 1) ? 127 : 255 ))
return 1;
for (; i >= 0; i--)
- value = value * 256 + (source[i] & (i == (bytes - 1) ? 127 : 255));
+ value = value * 256 + (source[i] & ((size_t)i == (bytes - 1) ? 127 : 255));
if ((source[bytes - 1] & 128) && (value > 0))
value = - value;
diff --git a/contrib/gcc/gcov.c b/contrib/gcc/gcov.c
index eff68f1..629aa02 100644
--- a/contrib/gcc/gcov.c
+++ b/contrib/gcc/gcov.c
@@ -1,6 +1,6 @@
/* Gcov.c: prepend line execution counts and branch probabilities to a
source file.
- Copyright (C) 1990, 91, 92, 93, 94, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91-94, 96, 97, 98, 1999 Free Software Foundation, Inc.
Contributed by James E. Wilson of Cygnus Support.
Mangled by Bob Manson of Cygnus Support.
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Gcov; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* ??? The code in final.c that produces the struct bb assumes that there is
no padding between the fields. This is not necessary true. The current
@@ -43,8 +44,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "system.h"
-#include <sys/stat.h>
-#include "gansidecl.h"
+#include "intl.h"
+#undef abort
#include "gcov-io.h"
@@ -218,14 +219,19 @@ static void open_files PROTO ((void));
static void read_files PROTO ((void));
static void scan_for_source_files PROTO ((void));
static void output_data PROTO ((void));
-static void print_usage PROTO ((void));
-char * xmalloc ();
+static void print_usage PROTO ((void)) ATTRIBUTE_NORETURN;
int
main (argc, argv)
int argc;
char **argv;
{
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
process_args (argc, argv);
open_files ();
@@ -239,14 +245,36 @@ main (argc, argv)
return 0;
}
-char *
+static void fnotice PVPROTO ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
+static void
+fnotice VPROTO ((FILE *file, const char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ FILE *file;
+ const char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ file = va_arg (ap, FILE *);
+ msgid = va_arg (ap, const char *);
+#endif
+
+ vfprintf (file, _(msgid), ap);
+ va_end (ap);
+}
+
+
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *value = (char *) malloc (size);
+ register PTR value = (PTR) malloc (size);
if (value == 0)
{
- fprintf (stderr, "error: virtual memory exhausted");
+ fnotice (stderr, "error: virtual memory exhausted");
exit (FATAL_EXIT_CODE);
}
return value;
@@ -258,7 +286,7 @@ xmalloc (size)
void
fancy_abort ()
{
- fprintf (stderr, "Internal gcc abort.\n");
+ fnotice (stderr, "Internal gcc abort.\n");
exit (FATAL_EXIT_CODE);
}
@@ -267,7 +295,7 @@ fancy_abort ()
static void
print_usage ()
{
- fprintf (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
+ fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
exit (FATAL_EXIT_CODE);
}
@@ -385,7 +413,7 @@ open_files ()
bb_file = fopen (bb_file_name, "r");
if (bb_file == NULL)
{
- fprintf (stderr, "Could not open basic block file %s.\n", bb_file_name);
+ fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
exit (FATAL_EXIT_CODE);
}
@@ -394,14 +422,14 @@ open_files ()
da_file = fopen (da_file_name, "r");
if (da_file == NULL)
{
- fprintf (stderr, "Could not open data file %s.\n", da_file_name);
- fprintf (stderr, "Assuming that all execution counts are zero.\n");
+ fnotice (stderr, "Could not open data file %s.\n", da_file_name);
+ fnotice (stderr, "Assuming that all execution counts are zero.\n");
}
bbg_file = fopen (bbg_file_name, "r");
if (bbg_file == NULL)
{
- fprintf (stderr, "Could not open program flow graph file %s.\n",
+ fnotice (stderr, "Could not open program flow graph file %s.\n",
bbg_file_name);
exit (FATAL_EXIT_CODE);
}
@@ -412,7 +440,7 @@ open_files ()
ungetc (getc (bbg_file), bbg_file);
if (feof (bbg_file))
{
- fprintf (stderr, "No executable code associated with file %s.\n",
+ fnotice (stderr, "No executable code associated with file %s.\n",
input_file_name);
exit (FATAL_EXIT_CODE);
}
@@ -713,10 +741,10 @@ read_files ()
if (da_file)
{
if (feof (da_file))
- fprintf (stderr, ".da file contents exhausted too early\n");
+ fnotice (stderr, ".da file contents exhausted too early\n");
/* Should be at end of file now. */
if (__read_long (&total, da_file, 8) == 0)
- fprintf (stderr, ".da file contents not exhausted\n");
+ fnotice (stderr, ".da file contents not exhausted\n");
}
/* Calculate all of the basic block execution counts and branch
@@ -897,33 +925,33 @@ static void
function_summary ()
{
if (function_source_lines)
- fprintf (stdout, "%6.2f%% of %d source lines executed in function %s\n",
+ fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
(((double) function_source_lines_executed / function_source_lines)
* 100), function_source_lines, function_name);
else
- fprintf (stdout, "No executable source lines in function %s\n",
+ fnotice (stdout, "No executable source lines in function %s\n",
function_name);
if (output_branch_probs)
{
if (function_branches)
{
- fprintf (stdout, "%6.2f%% of %d branches executed in function %s\n",
+ fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
(((double) function_branches_executed / function_branches)
* 100), function_branches, function_name);
- fprintf (stdout,
+ fnotice (stdout,
"%6.2f%% of %d branches taken at least once in function %s\n",
(((double) function_branches_taken / function_branches)
* 100), function_branches, function_name);
}
else
- fprintf (stdout, "No branches in function %s\n", function_name);
+ fnotice (stdout, "No branches in function %s\n", function_name);
if (function_calls)
- fprintf (stdout, "%6.2f%% of %d calls executed in function %s\n",
+ fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
(((double) function_calls_executed / function_calls)
* 100), function_calls, function_name);
else
- fprintf (stdout, "No calls in function %s\n", function_name);
+ fnotice (stdout, "No calls in function %s\n", function_name);
}
}
@@ -997,10 +1025,10 @@ output_data ()
bzero (line_exists, s_ptr->maxlineno);
if (output_branch_probs)
{
- branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata **)
+ branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata *)
* s_ptr->maxlineno);
bzero ((char *) branch_probs,
- sizeof (struct arcdata **) * s_ptr->maxlineno);
+ sizeof (struct arcdata *) * s_ptr->maxlineno);
}
/* There will be a zero at the beginning of the bb info, before the
@@ -1054,10 +1082,10 @@ output_data ()
}
else
{
- fprintf (stderr,
+ fnotice (stderr,
"didn't use all bb entries of graph, function %s\n",
function_name);
- fprintf (stderr, "block_num = %ld, num_blocks = %d\n",
+ fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
block_num, current_graph->num_blocks);
}
@@ -1095,7 +1123,7 @@ output_data ()
if (block_num >= current_graph->num_blocks)
{
- fprintf (stderr, "ERROR: too many basic blocks in .bb file %s\n",
+ fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
function_name);
abort ();
}
@@ -1171,34 +1199,34 @@ output_data ()
}
if (total_source_lines)
- fprintf (stdout,
+ fnotice (stdout,
"%6.2f%% of %d source lines executed in file %s\n",
(((double) total_source_lines_executed / total_source_lines)
* 100), total_source_lines, source_file_name);
else
- fprintf (stdout, "No executable source lines in file %s\n",
+ fnotice (stdout, "No executable source lines in file %s\n",
source_file_name);
if (output_branch_probs)
{
if (total_branches)
{
- fprintf (stdout, "%6.2f%% of %d branches executed in file %s\n",
+ fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
(((double) total_branches_executed / total_branches)
* 100), total_branches, source_file_name);
- fprintf (stdout,
+ fnotice (stdout,
"%6.2f%% of %d branches taken at least once in file %s\n",
(((double) total_branches_taken / total_branches)
* 100), total_branches, source_file_name);
}
else
- fprintf (stdout, "No branches in file %s\n", source_file_name);
+ fnotice (stdout, "No branches in file %s\n", source_file_name);
if (total_calls)
- fprintf (stdout, "%6.2f%% of %d calls executed in file %s\n",
+ fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
(((double) total_calls_executed / total_calls)
* 100), total_calls, source_file_name);
else
- fprintf (stdout, "No calls in file %s\n", source_file_name);
+ fnotice (stdout, "No calls in file %s\n", source_file_name);
}
if (output_gcov_file)
@@ -1210,7 +1238,7 @@ output_data ()
source_file = fopen (source_file_name, "r");
if (source_file == NULL)
{
- fprintf (stderr, "Could not open source file %s.\n",
+ fnotice (stderr, "Could not open source file %s.\n",
source_file_name);
free (line_counts);
free (line_exists);
@@ -1260,7 +1288,7 @@ output_data ()
if (gcov_file == NULL)
{
- fprintf (stderr, "Could not open output file %s.\n",
+ fnotice (stderr, "Could not open output file %s.\n",
gcov_file_name);
fclose (source_file);
free (line_counts);
@@ -1268,7 +1296,7 @@ output_data ()
continue;
}
- fprintf (stdout, "Creating %s.\n", gcov_file_name);
+ fnotice (stdout, "Creating %s.\n", gcov_file_name);
for (count = 1; count < s_ptr->maxlineno; count++)
{
@@ -1312,19 +1340,19 @@ output_data ()
if (a_ptr->call_insn)
{
if (a_ptr->prob == -1)
- fprintf (gcov_file, "call %d never executed\n", i);
+ fnotice (gcov_file, "call %d never executed\n", i);
else
- fprintf (gcov_file,
+ fnotice (gcov_file,
"call %d returns = %d%%\n",
i, 100 - a_ptr->prob);
}
else
{
if (a_ptr->prob == -1)
- fprintf (gcov_file, "branch %d never executed\n",
+ fnotice (gcov_file, "branch %d never executed\n",
i);
else
- fprintf (gcov_file, "branch %d taken = %d%%\n", i,
+ fnotice (gcov_file, "branch %d taken = %d%%\n", i,
a_ptr->prob);
}
}
@@ -1333,7 +1361,7 @@ output_data ()
/* Gracefully handle errors while reading the source file. */
if (retval == NULL)
{
- fprintf (stderr,
+ fnotice (stderr,
"Unexpected EOF while reading source file %s.\n",
source_file_name);
break;
diff --git a/contrib/gcc/gcse.c b/contrib/gcc/gcse.c
index f0efdb7..deebc73 100644
--- a/contrib/gcc/gcse.c
+++ b/contrib/gcc/gcse.c
@@ -1,6 +1,6 @@
-/* Global common subexpression elimination
+/* Global common subexpression elimination/Partial redundancy elimination
and global constant/copy propagation for GNU compiler.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,18 +24,17 @@ Boston, MA 02111-1307, USA. */
- do rough calc of how many regs are needed in each block, and a rough
calc of how many regs are available in each class and use that to
throttle back the code in cases where RTX_COST is minimal.
- - memory aliasing support
+ - dead store elimination
+ - a store to the same address as a load does not kill the load if the
+ source of the store is also the destination of the load. Handling this
+ allows more load motion, particularly out of loops.
- ability to realloc sbitmap vectors would allow one initial computation
of reg_set_in_block with only subsequent additions, rather than
recomputing it for each pass
- NOTES
- - the classic gcse implementation is kept in for now for comparison
*/
/* References searched while implementing this.
- This list will eventually be deleted but I wanted to have a record of it
- for now.
Compilers Principles, Techniques and Tools
Aho, Sethi, Ullman
@@ -49,12 +48,6 @@ Boston, MA 02111-1307, USA. */
Frederick Chow
Stanford Ph.D. thesis, Dec. 1983
-xxx
- Elimination Algorithms for Data Flow Analysis
- B.G. Ryder, M.C. Paull
- ACM Computing Surveys, Vol. 18, Num. 3, Sep. 1986
-
-reread
A Fast Algorithm for Code Movement Optimization
D.M. Dhamdhere
SIGPLAN Notices, Vol. 23, Num. 10, Oct. 1988
@@ -74,11 +67,6 @@ reread
R. Cytron, J. Ferrante, B.K. Rosen, M.N. Wegman, and F.K. Zadeck
ACM TOPLAS, Vol. 13, Num. 4, Oct. 1991
-yyy
- How to Analyze Large Programs Efficiently and Informatively
- D.M. Dhamdhere, B.K. Rosen, F.K. Zadeck
- ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
-
Lazy Code Motion
J. Knoop, O. Ruthing, B. Steffen
ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
@@ -134,14 +122,26 @@ yyy
Michael Wolfe
Addison-Wesley, 1996
- People wishing to speed up the code here should read xxx, yyy.
+ Advanced Compiler Design and Implementation
+ Steven Muchnick
+ Morgan Kaufmann, 1997
+
+ People wishing to speed up the code here should read:
+ Elimination Algorithms for Data Flow Analysis
+ B.G. Ryder, M.C. Paull
+ ACM Computing Surveys, Vol. 18, Num. 3, Sep. 1986
+
+ How to Analyze Large Programs Efficiently and Informatively
+ D.M. Dhamdhere, B.K. Rosen, F.K. Zadeck
+ ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
+
People wishing to do something different can find various possibilities
in the above papers and elsewhere.
*/
#include "config.h"
-/* Must precede rtl.h for FFS. */
#include "system.h"
+#include "toplev.h"
#include "rtl.h"
#include "regs.h"
@@ -152,6 +152,7 @@ yyy
#include "recog.h"
#include "basic-block.h"
#include "output.h"
+#include "expr.h"
#include "obstack.h"
#define obstack_chunk_alloc gmalloc
@@ -173,11 +174,10 @@ yyy
heuristics into gcse.c. */
#define FOLLOW_BACK_EDGES 1
-/* We support two GCSE implementations: Classic GCSE (i.e. Dragon Book)
- and PRE (Partial Redundancy Elimination) GCSE (based on Fred Chow's thesis).
- The default is PRE.
+/* We support GCSE via Partial Redundancy Elimination. PRE optimizations
+ are a superset of those done by GCSE.
- In either case we perform the following steps:
+ We perform the following steps:
1) Compute basic block information.
@@ -187,7 +187,7 @@ yyy
4) Perform global cse.
- 5) Perform another pass of copy/constant propagation [only if PRE].
+ 5) Perform another pass of copy/constant propagation.
Two passes of copy/constant propagation are done because the first one
enables more GCSE and the second one helps to clean up the copies that
@@ -201,10 +201,7 @@ yyy
Function want_to_gcse_p says what these are.
PRE handles moving invariant expressions out of loops (by treating them as
- partially redundant). This feature of PRE is disabled here (by not
- propagating dataflow information along back edges) because loop.c has more
- involved (and thus typically better) heuristics for what to move out of
- loops.
+ partially redundant).
Eventually it would be nice to replace cse.c/gcse.c with SSA (static single
assignment) based GVN (global value numbering). L. T. Simpson's paper
@@ -253,7 +250,7 @@ yyy
argue it is not. The number of iterations for the algorithm to converge
is typically 2-4 so I don't view it as that expensive (relatively speaking).
- PRE GCSE depends heavily on the seconds CSE pass to clean up the copies
+ PRE GCSE depends heavily on the second CSE pass to clean up the copies
we create. To make an expression reach the place where it's redundant,
the result of the expression is copied to a new register, and the redundant
expression is deleted by replacing it with this new register. Classic GCSE
@@ -262,35 +259,6 @@ yyy
**********************
- When -fclassic-gcse, we perform a classic global CSE pass.
- It is based on the algorithms in the Dragon book, and is based on code
- written by Devor Tevi at Intel.
-
- The steps for Classic GCSE are:
-
- 1) Build the hash table of expressions we wish to GCSE (expr_hash_table).
- Also recorded are reaching definition "gen" statements (rd_gen)
-
- 2) Compute the reaching definitions (reaching_defs).
- This is a bitmap for each basic block indexed by INSN_CUID that is 1
- for each statement containing a definition that reaches the block.
-
- 3) Compute the available expressions (ae_in).
- This is a bitmap for each basic block indexed by expression number
- that is 1 for each expression that is available at the beginning of
- the block.
-
- 4) Perform GCSE.
- This is done by scanning each instruction looking for sets of the form
- (set (pseudo-reg) (expression)) and checking if `expression' is in the
- hash table. If it is, and if the expression is available, and if only
- one computation of the expression reaches the instruction, we substitute
- the expression for a register containing its value. If there is no
- such register, but the expression is expensive enough we create an
- instruction to copy the result of the expression into and use that.
-
- **********************
-
A fair bit of simplicity is created by creating small functions for simple
tasks, even when the function is only called in one place. This may
measurably slow things down [or may not] by creating more function call
@@ -306,6 +274,23 @@ yyy
/* -dG dump file. */
static FILE *gcse_file;
+/* Note whether or not we should run jump optimization after gcse. We
+ want to do this for two cases.
+
+ * If we changed any jumps via cprop.
+
+ * If we added any labels via edge splitting. */
+
+static int run_jump_opt_after_gcse;
+
+/* Element I is a list of I's predecessors/successors. */
+static int_list_ptr *s_preds;
+static int_list_ptr *s_succs;
+
+/* Element I is the number of predecessors/successors of basic block I. */
+static int *num_preds;
+static int *num_succs;
+
/* Bitmaps are normally not included in debugging dumps.
However it's useful to be able to print them from GDB.
We could create special functions for this, but it's simpler to
@@ -324,14 +309,6 @@ static char can_copy_p[(int) NUM_MACHINE_MODES];
/* Non-zero if can_copy_p has been initialized. */
static int can_copy_init_p;
-/* Element I is a list of I's predecessors/successors. */
-static int_list_ptr *s_preds;
-static int_list_ptr *s_succs;
-
-/* Element I is the number of predecessors/successors of basic block I. */
-static int *num_preds;
-static int *num_succs;
-
/* Hash table of expressions. */
struct expr
@@ -344,8 +321,9 @@ struct expr
struct expr *next_same_hash;
/* List of anticipatable occurrences in basic blocks in the function.
An "anticipatable occurrence" is one that is the first occurrence in the
- basic block and the operands are not modified in the basic block prior
- to the occurrence. */
+ basic block, the operands are not modified in the basic block prior
+ to the occurrence and the output is not used between the start of
+ the block and the occurrence. */
struct occr *antic_occr;
/* List of available occurrence in basic blocks in the function.
An "available occurrence" is one that is the last occurrence in the
@@ -434,11 +412,10 @@ static int n_sets;
For simplicity, GCSE is done on sets of pseudo-regs only. PRE GCSE only
requires knowledge of which blocks kill which regs [and thus could use
- a bitmap instead of the lists `reg_set_table' uses]. The classic GCSE
- uses the information in lists.
+ a bitmap instead of the lists `reg_set_table' uses].
- If the classic GCSE pass is deleted `reg_set_table' and could be turned
- into an array of bitmaps (num-bbs x num-regs)
+ `reg_set_table' and could be turned into an array of bitmaps
+ (num-bbs x num-regs)
[however perhaps it may be useful to keep the data as is].
One advantage of recording things this way is that `reg_set_table' is
fairly sparse with respect to pseudo regs but for hard regs could be
@@ -505,7 +482,6 @@ static int copy_prop_count;
extern char *current_function_name;
extern int current_function_calls_setjmp;
-extern int current_function_calls_longjmp;
/* These variables are used by classic GCSE.
Normally they'd be defined a bit later, but `rd_gen' needs to
@@ -534,120 +510,114 @@ static sbitmap *rd_kill, *rd_gen, *reaching_defs, *rd_out;
/* for available exprs */
static sbitmap *ae_kill, *ae_gen, *ae_in, *ae_out;
+
-static void compute_can_copy PROTO ((void));
-
-static char *gmalloc PROTO ((unsigned int));
-static char *grealloc PROTO ((char *, unsigned int));
-static char *gcse_alloc PROTO ((unsigned long));
-static void alloc_gcse_mem PROTO ((rtx));
-static void free_gcse_mem PROTO ((void));
-extern void dump_cuid_table PROTO ((FILE *));
-
-static void alloc_reg_set_mem PROTO ((int));
-static void free_reg_set_mem PROTO ((void));
-static void record_one_set PROTO ((int, rtx));
-static void record_set_info PROTO ((rtx, rtx));
-static void compute_sets PROTO ((rtx));
-
-static void hash_scan_insn PROTO ((rtx, int, int));
-static void hash_scan_set PROTO ((rtx, rtx, int));
-static void hash_scan_clobber PROTO ((rtx, rtx));
-static void hash_scan_call PROTO ((rtx, rtx));
-static void maybe_set_rd_gen PROTO ((int, rtx));
-static int want_to_gcse_p PROTO ((rtx));
-static int oprs_unchanged_p PROTO ((rtx, rtx, int));
+static void compute_can_copy PROTO ((void));
+
+static char *gmalloc PROTO ((unsigned int));
+static char *grealloc PROTO ((char *, unsigned int));
+static char *gcse_alloc PROTO ((unsigned long));
+static void alloc_gcse_mem PROTO ((rtx));
+static void free_gcse_mem PROTO ((void));
+static void alloc_reg_set_mem PROTO ((int));
+static void free_reg_set_mem PROTO ((void));
+static void record_one_set PROTO ((int, rtx));
+static void record_set_info PROTO ((rtx, rtx));
+static void compute_sets PROTO ((rtx));
+
+static void hash_scan_insn PROTO ((rtx, int, int));
+static void hash_scan_set PROTO ((rtx, rtx, int));
+static void hash_scan_clobber PROTO ((rtx, rtx));
+static void hash_scan_call PROTO ((rtx, rtx));
+static int want_to_gcse_p PROTO ((rtx));
+static int oprs_unchanged_p PROTO ((rtx, rtx, int));
static int oprs_anticipatable_p PROTO ((rtx, rtx));
-static int oprs_available_p PROTO ((rtx, rtx));
-static void insert_expr_in_table PROTO ((rtx, enum machine_mode, rtx, int, int));
+static int oprs_available_p PROTO ((rtx, rtx));
+static void insert_expr_in_table PROTO ((rtx, enum machine_mode,
+ rtx, int, int));
static void insert_set_in_table PROTO ((rtx, rtx));
-static unsigned int hash_expr PROTO ((rtx, enum machine_mode, int *, int));
+static unsigned int hash_expr PROTO ((rtx, enum machine_mode,
+ int *, int));
static unsigned int hash_expr_1 PROTO ((rtx, enum machine_mode, int *));
-static unsigned int hash_set PROTO ((int, int));
-static int expr_equiv_p PROTO ((rtx, rtx));
+static unsigned int hash_set PROTO ((int, int));
+static int expr_equiv_p PROTO ((rtx, rtx));
static void record_last_reg_set_info PROTO ((rtx, int));
static void record_last_mem_set_info PROTO ((rtx));
static void record_last_set_info PROTO ((rtx, rtx));
-static void compute_hash_table PROTO ((rtx, int));
+static void compute_hash_table PROTO ((int));
static void alloc_set_hash_table PROTO ((int));
static void free_set_hash_table PROTO ((void));
-static void compute_set_hash_table PROTO ((rtx));
+static void compute_set_hash_table PROTO ((void));
static void alloc_expr_hash_table PROTO ((int));
static void free_expr_hash_table PROTO ((void));
-static void compute_expr_hash_table PROTO ((rtx));
-static void dump_hash_table PROTO ((FILE *, char *, struct expr **, int, int));
+static void compute_expr_hash_table PROTO ((void));
+static void dump_hash_table PROTO ((FILE *, const char *, struct expr **,
+ int, int));
static struct expr *lookup_expr PROTO ((rtx));
-static struct expr *lookup_set PROTO ((int, rtx));
-static struct expr *next_set PROTO ((int, struct expr *));
+static struct expr *lookup_set PROTO ((int, rtx));
+static struct expr *next_set PROTO ((int, struct expr *));
static void reset_opr_set_tables PROTO ((void));
-static int oprs_not_set_p PROTO ((rtx, rtx));
-static void mark_call PROTO ((rtx, rtx));
-static void mark_set PROTO ((rtx, rtx));
-static void mark_clobber PROTO ((rtx, rtx));
-static void mark_oprs_set PROTO ((rtx));
-
-static void alloc_rd_mem PROTO ((int, int));
-static void free_rd_mem PROTO ((void));
-static void compute_kill_rd PROTO ((void));
-static void handle_rd_kill_set PROTO ((rtx, int, int));
-static void compute_rd PROTO ((void));
-extern void dump_rd_table PROTO ((FILE *, char *, sbitmap *));
+static int oprs_not_set_p PROTO ((rtx, rtx));
+static void mark_call PROTO ((rtx));
+static void mark_set PROTO ((rtx, rtx));
+static void mark_clobber PROTO ((rtx, rtx));
+static void mark_oprs_set PROTO ((rtx));
+
+static void alloc_cprop_mem PROTO ((int, int));
+static void free_cprop_mem PROTO ((void));
+static void compute_transp PROTO ((rtx, int, sbitmap *, int));
+static void compute_transpout PROTO ((void));
+static void compute_local_properties PROTO ((sbitmap *, sbitmap *,
+ sbitmap *, int));
+static void compute_cprop_avinout PROTO ((void));
+static void compute_cprop_data PROTO ((void));
+static void find_used_regs PROTO ((rtx));
+static int try_replace_reg PROTO ((rtx, rtx, rtx));
+static struct expr *find_avail_set PROTO ((int, rtx));
+static int cprop_insn PROTO ((rtx, int));
+static int cprop PROTO ((int));
+static int one_cprop_pass PROTO ((int, int));
+
+static void alloc_pre_mem PROTO ((int, int));
+static void free_pre_mem PROTO ((void));
+static void compute_pre_data PROTO ((void));
+static int pre_expr_reaches_here_p PROTO ((int, struct expr *,
+ int, int, char *));
+static void insert_insn_end_bb PROTO ((struct expr *, int, int));
+static void pre_insert PROTO ((struct expr **));
+static void pre_insert_copy_insn PROTO ((struct expr *, rtx));
+static void pre_insert_copies PROTO ((void));
+static int pre_delete PROTO ((void));
+static int pre_gcse PROTO ((void));
+static int one_pre_gcse_pass PROTO ((int));
+
+static void add_label_notes PROTO ((rtx, rtx));
+static void alloc_rd_mem PROTO ((int, int));
+static void free_rd_mem PROTO ((void));
+static void handle_rd_kill_set PROTO ((rtx, int, int));
+static void compute_kill_rd PROTO ((void));
+static void compute_rd PROTO ((void));
static void alloc_avail_expr_mem PROTO ((int, int));
static void free_avail_expr_mem PROTO ((void));
-static void compute_ae_gen PROTO ((void));
-static void compute_ae_kill PROTO ((void));
-static int expr_killed_p PROTO ((rtx, int));
-static void compute_available PROTO ((void));
-
-static int expr_reaches_here_p PROTO ((struct occr *, struct expr *,
+static void compute_ae_gen PROTO ((void));
+static int expr_killed_p PROTO ((rtx, int));
+static void compute_ae_kill PROTO ((void));
+static void compute_available PROTO ((void));
+static int expr_reaches_here_p PROTO ((struct occr *, struct expr *,
int, int, char *));
-static rtx computing_insn PROTO ((struct expr *, rtx));
-static int def_reaches_here_p PROTO ((rtx, rtx));
+static rtx computing_insn PROTO ((struct expr *, rtx));
+static int def_reaches_here_p PROTO ((rtx, rtx));
static int can_disregard_other_sets PROTO ((struct reg_set **, rtx, int));
-static int handle_avail_expr PROTO ((rtx, struct expr *));
-static int classic_gcse PROTO ((void));
-static int one_classic_gcse_pass PROTO ((rtx, int));
-
-static void alloc_cprop_mem PROTO ((int, int));
-static void free_cprop_mem PROTO ((void));
-extern void dump_cprop_data PROTO ((FILE *));
-static void compute_transp PROTO ((rtx, int, sbitmap *, int));
-static void compute_cprop_local_properties PROTO ((void));
-static void compute_cprop_avinout PROTO ((void));
-static void compute_cprop_data PROTO ((void));
-static void find_used_regs PROTO ((rtx));
-static int try_replace_reg PROTO ((rtx, rtx, rtx));
-static struct expr *find_avail_set PROTO ((int, rtx));
-static int cprop_insn PROTO ((rtx));
-static int cprop PROTO ((void));
-static int one_cprop_pass PROTO ((rtx, int));
-
-static void alloc_pre_mem PROTO ((int, int));
-static void free_pre_mem PROTO ((void));
-extern void dump_pre_data PROTO ((FILE *));
-static void compute_pre_local_properties PROTO ((void));
-static void compute_pre_avinout PROTO ((void));
-static void compute_pre_antinout PROTO ((void));
-static void compute_pre_pavinout PROTO ((void));
-static void compute_pre_ppinout PROTO ((void));
-static void compute_pre_data PROTO ((void));
-static int pre_expr_reaches_here_p PROTO ((struct occr *, struct expr *,
- int, char *));
-static void pre_insert_insn PROTO ((struct expr *, int));
-static void pre_insert PROTO ((struct expr **));
-static void pre_insert_copy_insn PROTO ((struct expr *, rtx));
-static void pre_insert_copies PROTO ((void));
-static int pre_delete PROTO ((void));
-static int pre_gcse PROTO ((void));
-static int one_pre_gcse_pass PROTO ((rtx, int));
+static int handle_avail_expr PROTO ((rtx, struct expr *));
+static int classic_gcse PROTO ((void));
+static int one_classic_gcse_pass PROTO ((int));
-static void add_label_notes PROTO ((rtx, rtx));
/* Entry point for global common subexpression elimination.
F is the first instruction in the function. */
-void
+int
gcse_main (f, file)
rtx f;
FILE *file;
@@ -660,23 +630,29 @@ gcse_main (f, file)
/* Point to release obstack data from for each pass. */
char *gcse_obstack_bottom;
- /* It's impossible to construct a correct control flow graph in the
- presense of setjmp, so just punt to be safe. */
+ /* We do not construct an accurate cfg in functions which call
+ setjmp, so just punt to be safe. */
if (current_function_calls_setjmp)
- return;
+ return 0;
+ /* Assume that we do not need to run jump optimizations after gcse. */
+ run_jump_opt_after_gcse = 0;
+
/* For calling dump_foo fns from gdb. */
debug_stderr = stderr;
+ gcse_file = file;
+ /* Identify the basic block information for this function, including
+ successors and predecessors. */
max_gcse_regno = max_reg_num ();
- find_basic_blocks (f, max_gcse_regno, file, 0);
+ find_basic_blocks (f, max_gcse_regno, file, 1);
/* Return if there's nothing to do. */
if (n_basic_blocks <= 1)
{
/* Free storage allocated by find_basic_blocks. */
free_basic_block_vars (0);
- return;
+ return 0;
}
/* See what modes support reg/reg copy operations. */
@@ -688,8 +664,6 @@ gcse_main (f, file)
gcc_obstack_init (&gcse_obstack);
- gcse_file = file;
-
/* Allocate and compute predecessors/successors. */
s_preds = (int_list_ptr *) alloca (n_basic_blocks * sizeof (int_list_ptr));
@@ -700,15 +674,17 @@ gcse_main (f, file)
compute_preds_succs (s_preds, s_succs, num_preds, num_succs);
if (file)
- {
- dump_bb_data (file, s_preds, s_succs);
- }
+ dump_bb_data (file, s_preds, s_succs, 0);
/* Record where pseudo-registers are set.
This data is kept accurate during each pass.
- ??? We could also record hard-reg and memory information here
+ ??? We could also record hard-reg information here
[since it's unchanging], however it is currently done during
- hash table computation. */
+ hash table computation.
+
+ It may be tempting to compute MEM set information here too, but MEM
+ sets will be subject to code motion one day and thus we need to compute
+ information about memory sets when we build the hash tables. */
alloc_reg_set_mem (max_gcse_regno);
compute_sets (f);
@@ -733,12 +709,14 @@ gcse_main (f, file)
alloc_gcse_mem (f);
- changed = one_cprop_pass (f, pass + 1);
+ /* Don't allow constant propagation to modify jumps
+ during this pass. */
+ changed = one_cprop_pass (pass + 1, 0);
if (optimize_size)
- changed |= one_classic_gcse_pass (f, pass + 1);
+ changed |= one_classic_gcse_pass (pass + 1);
else
- changed |= one_pre_gcse_pass (f, pass + 1);
+ changed |= one_pre_gcse_pass (pass + 1);
if (max_pass_bytes < bytes_used)
max_pass_bytes = bytes_used;
@@ -754,14 +732,14 @@ gcse_main (f, file)
pass++;
}
- /* If we're doing PRE, do one last pass of copy propagation. */
- if (! optimize_size)
- {
- max_gcse_regno = max_reg_num ();
- alloc_gcse_mem (f);
- one_cprop_pass (f, pass + 1);
- free_gcse_mem ();
- }
+ /* Do one last pass of copy propagation, including cprop into
+ conditional jumps. */
+
+ max_gcse_regno = max_reg_num ();
+ alloc_gcse_mem (f);
+ /* This time, go ahead and allow cprop to alter jumps. */
+ one_cprop_pass (pass + 1, 1);
+ free_gcse_mem ();
if (file)
{
@@ -779,6 +757,7 @@ gcse_main (f, file)
free_bb_mem ();
/* Free storage allocated by find_basic_blocks. */
free_basic_block_vars (0);
+ return run_jump_opt_after_gcse;
}
/* Misc. utilities. */
@@ -923,23 +902,119 @@ free_gcse_mem ()
free (mem_set_in_block);
}
-void
-dump_cuid_table (file)
- FILE *file;
-{
- int i,n;
+
+/* Compute the local properties of each recorded expression.
+ Local properties are those that are defined by the block, irrespective
+ of other blocks.
+
+ An expression is transparent in a block if its operands are not modified
+ in the block.
+
+ An expression is computed (locally available) in a block if it is computed
+ at least once and expression would contain the same value if the
+ computation was moved to the end of the block.
+
+ An expression is locally anticipatable in a block if it is computed at
+ least once and expression would contain the same value if the computation
+ was moved to the beginning of the block.
- fprintf (file, "CUID table\n");
- for (i = n = 0; i < max_cuid; i++)
+ We call this routine for cprop, pre and code hoisting. They all
+ compute basically the same information and thus can easily share
+ this code.
+
+ TRANSP, COMP, and ANTLOC are destination sbitmaps for recording
+ local properties. If NULL, then it is not necessary to compute
+ or record that particular property.
+
+ SETP controls which hash table to look at. If zero, this routine
+ looks at the expr hash table; if nonzero this routine looks at
+ the set hash table. Additionally, TRANSP is computed as ~TRANSP,
+ since this is really cprop's ABSALTERED. */
+
+static void
+compute_local_properties (transp, comp, antloc, setp)
+ sbitmap *transp;
+ sbitmap *comp;
+ sbitmap *antloc;
+ int setp;
+{
+ int i, hash_table_size;
+ struct expr **hash_table;
+
+ /* Initialize any bitmaps that were passed in. */
+ if (transp)
{
- rtx insn = CUID_INSN (i);
- if (n != 0 && n % 10 == 0)
- fprintf (file, "\n");
- if (insn != NULL)
- fprintf (file, " %d", INSN_UID (insn));
+ if (setp)
+ sbitmap_vector_zero (transp, n_basic_blocks);
+ else
+ sbitmap_vector_ones (transp, n_basic_blocks);
+ }
+ if (comp)
+ sbitmap_vector_zero (comp, n_basic_blocks);
+ if (antloc)
+ sbitmap_vector_zero (antloc, n_basic_blocks);
+
+ /* We use the same code for cprop, pre and hoisting. For cprop
+ we care about the set hash table, for pre and hoisting we
+ care about the expr hash table. */
+ hash_table_size = setp ? set_hash_table_size : expr_hash_table_size;
+ hash_table = setp ? set_hash_table : expr_hash_table;
+
+ for (i = 0; i < hash_table_size; i++)
+ {
+ struct expr *expr;
+
+ for (expr = hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+ {
+ struct occr *occr;
+ int indx = expr->bitmap_index;
+
+ /* The expression is transparent in this block if it is not killed.
+ We start by assuming all are transparent [none are killed], and
+ then reset the bits for those that are. */
+
+ if (transp)
+ compute_transp (expr->expr, indx, transp, setp);
+
+ /* The occurrences recorded in antic_occr are exactly those that
+ we want to set to non-zero in ANTLOC. */
+
+ if (antloc)
+ {
+ for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
+ {
+ int bb = BLOCK_NUM (occr->insn);
+ SET_BIT (antloc[bb], indx);
+
+ /* While we're scanning the table, this is a good place to
+ initialize this. */
+ occr->deleted_p = 0;
+ }
+ }
+
+ /* The occurrences recorded in avail_occr are exactly those that
+ we want to set to non-zero in COMP. */
+ if (comp)
+ {
+
+ for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
+ {
+ int bb = BLOCK_NUM (occr->insn);
+ SET_BIT (comp[bb], indx);
+
+ /* While we're scanning the table, this is a good place to
+ initialize this. */
+ occr->copied_p = 0;
+ }
+ }
+
+ /* While we're scanning the table, this is a good place to
+ initialize this. */
+ expr->reaching_reg = 0;
+ }
}
- fprintf (file, "\n\n");
}
+
/* Register set information.
@@ -1058,12 +1133,12 @@ compute_sets (f)
#define NEVER_SET -1
/* For each register, the cuid of the first/last insn in the block to set it,
- or zero if not set. */
+ or -1 if not set. */
static int *reg_first_set;
static int *reg_last_set;
/* While computing "first/last set" info, this is the CUID of first/last insn
- to set memory or zero if not set. `mem_last_set' is also used when
+ to set memory or -1 if not set. `mem_last_set' is also used when
performing GCSE to record whether memory has been set since the beginning
of the block.
Note that handling of memory is very simple, we don't make any attempt
@@ -1071,18 +1146,6 @@ static int *reg_last_set;
static int mem_first_set;
static int mem_last_set;
-/* Set the appropriate bit in `rd_gen' [the gen for reaching defs] if the
- register set in this insn is not set after this insn in this block. */
-
-static void
-maybe_set_rd_gen (regno, insn)
- int regno;
- rtx insn;
-{
- if (reg_last_set[regno] <= INSN_CUID (insn))
- SET_BIT (rd_gen[BLOCK_NUM (insn)], INSN_CUID (insn));
-}
-
/* Perform a quick check whether X, the source of a set, is something
we want to consider for GCSE. */
@@ -1801,7 +1864,8 @@ hash_scan_set (pat, insn, set_p)
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
&& can_copy_p [GET_MODE (dest)])
/* ??? CONST_INT:wip */
- || GET_CODE (src) == CONST_INT)
+ || GET_CODE (src) == CONST_INT
+ || GET_CODE (src) == CONST_DOUBLE)
/* A copy is not available if its src or dest is subsequently
modified. Here we want to search from INSN+1 on, but
oprs_available_p searches from INSN on. */
@@ -1810,22 +1874,6 @@ hash_scan_set (pat, insn, set_p)
&& oprs_available_p (pat, tmp))))
insert_set_in_table (pat, insn);
}
-
- /* Check if first/last set in this block for classic gcse,
- but not for copy/constant propagation. */
- if (optimize_size && !set_p)
-
- {
- rtx dest = SET_DEST (pat);
-
- while (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == STRICT_LOW_PART)
- dest = XEXP (dest, 0);
- if (GET_CODE (dest) == REG)
- maybe_set_rd_gen (REGNO (dest), insn);
- }
}
static void
@@ -1880,21 +1928,6 @@ hash_scan_insn (insn, set_p, in_libcall_block)
{
if (GET_CODE (SET_SRC (x)) == CALL)
hash_scan_call (SET_SRC (x), insn);
-
- /* Check if first/last set in this block for classic
- gcse, but not for constant/copy propagation. */
- if (optimize_size && !set_p)
- {
- rtx dest = SET_DEST (x);
-
- while (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == STRICT_LOW_PART)
- dest = XEXP (dest, 0);
- if (GET_CODE (dest) == REG)
- maybe_set_rd_gen (REGNO (dest), insn);
- }
}
else if (GET_CODE (x) == CLOBBER)
hash_scan_clobber (x, insn);
@@ -1911,7 +1944,7 @@ hash_scan_insn (insn, set_p, in_libcall_block)
static void
dump_hash_table (file, name, table, table_size, total_size)
FILE *file;
- char *name;
+ const char *name;
struct expr **table;
int table_size, total_size;
{
@@ -2017,8 +2050,7 @@ record_last_set_info (dest, setter)
SET_P is non-zero for computing the assignment hash table. */
static void
-compute_hash_table (f, set_p)
- rtx f ATTRIBUTE_UNUSED;
+compute_hash_table (set_p)
int set_p;
{
int bb;
@@ -2055,8 +2087,8 @@ compute_hash_table (f, set_p)
mem_first_set = NEVER_SET;
mem_last_set = NEVER_SET;
- for (insn = basic_block_head[bb];
- insn && insn != NEXT_INSN (basic_block_end[bb]);
+ for (insn = BLOCK_HEAD (bb);
+ insn && insn != NEXT_INSN (BLOCK_END (bb));
insn = NEXT_INSN (insn))
{
#ifdef NON_SAVING_SETJMP
@@ -2075,7 +2107,20 @@ compute_hash_table (f, set_p)
if (GET_CODE (insn) == CALL_INSN)
{
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (call_used_regs[regno])
+ if ((call_used_regs[regno]
+ && regno != STACK_POINTER_REGNUM
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && regno != HARD_FRAME_POINTER_REGNUM
+#endif
+#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
+#endif
+#if defined (PIC_OFFSET_TABLE_REGNUM) && !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
+ && ! (regno == PIC_OFFSET_TABLE_REGNUM && flag_pic)
+#endif
+
+ && regno != FRAME_POINTER_REGNUM)
+ || global_regs[regno])
record_last_reg_set_info (insn, regno);
if (! CONST_CALL_P (insn))
record_last_mem_set_info (insn);
@@ -2087,8 +2132,8 @@ compute_hash_table (f, set_p)
/* The next pass builds the hash table. */
- for (insn = basic_block_head[bb], in_libcall_block = 0;
- insn && insn != NEXT_INSN (basic_block_end[bb]);
+ for (insn = BLOCK_HEAD (bb), in_libcall_block = 0;
+ insn && insn != NEXT_INSN (BLOCK_END (bb));
insn = NEXT_INSN (insn))
{
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
@@ -2140,14 +2185,13 @@ free_set_hash_table ()
/* Compute the hash table for doing copy/const propagation. */
static void
-compute_set_hash_table (f)
- rtx f;
+compute_set_hash_table ()
{
/* Initialize count of number of entries in hash table. */
n_sets = 0;
bzero ((char *) set_hash_table, set_hash_table_size * sizeof (struct expr *));
- compute_hash_table (f, 1);
+ compute_hash_table (1);
}
/* Allocate space for the expression hash table.
@@ -2183,14 +2227,13 @@ free_expr_hash_table ()
/* Compute the hash table for doing GCSE. */
static void
-compute_expr_hash_table (f)
- rtx f;
+compute_expr_hash_table ()
{
/* Initialize count of number of entries in hash table. */
n_exprs = 0;
bzero ((char *) expr_hash_table, expr_hash_table_size * sizeof (struct expr *));
- compute_hash_table (f, 0);
+ compute_hash_table (0);
}
/* Expression tracking support. */
@@ -2355,8 +2398,8 @@ repeat:
/* Mark things set by a CALL. */
static void
-mark_call (pat, insn)
- rtx pat ATTRIBUTE_UNUSED, insn;
+mark_call (insn)
+ rtx insn;
{
mem_last_set = INSN_CUID (insn);
}
@@ -2381,7 +2424,7 @@ mark_set (pat, insn)
mem_last_set = INSN_CUID (insn);
if (GET_CODE (SET_SRC (pat)) == CALL)
- mark_call (SET_SRC (pat), insn);
+ mark_call (insn);
}
/* Record things set by a CLOBBER. */
@@ -2425,14 +2468,15 @@ mark_oprs_set (insn)
else if (GET_CODE (x) == CLOBBER)
mark_clobber (x, insn);
else if (GET_CODE (x) == CALL)
- mark_call (x, insn);
+ mark_call (insn);
}
}
else if (GET_CODE (pat) == CLOBBER)
mark_clobber (pat, insn);
else if (GET_CODE (pat) == CALL)
- mark_call (pat, insn);
+ mark_call (insn);
}
+
/* Classic GCSE reaching definition support. */
@@ -2484,38 +2528,6 @@ handle_rd_kill_set (insn, regno, bb)
}
}
-void
-dump_rd_table (file, title, bmap)
- FILE *file;
- char *title;
- sbitmap *bmap;
-{
- int bb,cuid,i,j,n;
-
- fprintf (file, "%s\n", title);
- for (bb = 0; bb < n_basic_blocks; bb++)
- {
- fprintf (file, "BB %d\n", bb);
- dump_sbitmap (file, bmap[bb]);
- for (i = n = cuid = 0; i < bmap[bb]->size; i++)
- {
- for (j = 0; j < SBITMAP_ELT_BITS; j++, cuid++)
- {
- if ((bmap[bb]->elms[i] & (1 << j)) != 0)
- {
- if (n % 10 == 0)
- fprintf (file, " ");
- fprintf (file, " %d", INSN_UID (CUID_INSN (cuid)));
- n++;
- }
- }
- }
- if (n != 0)
- fprintf (file, "\n");
- }
- fprintf (file, "\n");
-}
-
/* Compute the set of kill's for reaching definitions. */
static void
@@ -2525,12 +2537,12 @@ compute_kill_rd ()
/* For each block
For each set bit in `gen' of the block (i.e each insn which
- generates a definition in the block)
- Call the reg set by the insn corresponding to that bit regx
- Look at the linked list starting at reg_set_table[regx]
- For each setting of regx in the linked list, which is not in
- this block
- Set the bit in `kill' corresponding to that insn
+ generates a definition in the block)
+ Call the reg set by the insn corresponding to that bit regx
+ Look at the linked list starting at reg_set_table[regx]
+ For each setting of regx in the linked list, which is not in
+ this block
+ Set the bit in `kill' corresponding to that insn
*/
for (bb = 0; bb < n_basic_blocks; bb++)
@@ -2538,20 +2550,33 @@ compute_kill_rd ()
for (cuid = 0; cuid < max_cuid; cuid++)
{
if (TEST_BIT (rd_gen[bb], cuid))
- {
+ {
rtx insn = CUID_INSN (cuid);
rtx pat = PATTERN (insn);
if (GET_CODE (insn) == CALL_INSN)
- {
+ {
int regno;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- {
- if (call_used_regs[regno])
+ {
+ if ((call_used_regs[regno]
+ && regno != STACK_POINTER_REGNUM
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && regno != HARD_FRAME_POINTER_REGNUM
+#endif
+#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && ! (regno == ARG_POINTER_REGNUM
+ && fixed_regs[regno])
+#endif
+#if defined (PIC_OFFSET_TABLE_REGNUM) && !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
+ && ! (regno == PIC_OFFSET_TABLE_REGNUM && flag_pic)
+#endif
+ && regno != FRAME_POINTER_REGNUM)
+ || global_regs[regno])
handle_rd_kill_set (insn, regno, bb);
- }
- }
+ }
+ }
if (GET_CODE (pat) == PARALLEL)
{
@@ -2576,9 +2601,9 @@ compute_kill_rd ()
must be marked in the set of kills in this block. */
handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), bb);
}
- }
+ }
/* FIXME: CLOBBER? */
- }
+ }
}
}
}
@@ -2602,12 +2627,12 @@ compute_rd ()
{
changed = 0;
for (bb = 0; bb < n_basic_blocks; bb++)
- {
+ {
sbitmap_union_of_predecessors (reaching_defs[bb], rd_out,
bb, s_preds);
changed |= sbitmap_union_of_diff (rd_out[bb], rd_gen[bb],
reaching_defs[bb], rd_kill[bb]);
- }
+ }
passes++;
}
@@ -2804,8 +2829,7 @@ compute_available ()
changed = 0;
for (bb = 1; bb < n_basic_blocks; bb++)
{
- sbitmap_intersect_of_predecessors (ae_in[bb], ae_out,
- bb, s_preds);
+ sbitmap_intersect_of_predecessors (ae_in[bb], ae_out, bb, s_preds);
changed |= sbitmap_union_of_diff (ae_out[bb], ae_gen[bb],
ae_in[bb], ae_kill[bb]);
}
@@ -2855,20 +2879,20 @@ expr_reaches_here_p (occr, expr, bb, check_self_loop, visited)
int pred_bb = INT_LIST_VAL (pred);
if (visited[pred_bb])
- {
+ {
/* This predecessor has already been visited.
Nothing to do. */
;
}
else if (pred_bb == bb)
- {
+ {
/* BB loops on itself. */
if (check_self_loop
&& TEST_BIT (ae_gen[pred_bb], expr->bitmap_index)
&& BLOCK_NUM (occr->insn) == pred_bb)
return 1;
visited[pred_bb] = 1;
- }
+ }
/* Ignore this predecessor if it kills the expression. */
else if (TEST_BIT (ae_kill[pred_bb], expr->bitmap_index))
visited[pred_bb] = 1;
@@ -2884,11 +2908,11 @@ expr_reaches_here_p (occr, expr, bb, check_self_loop, visited)
}
/* Neither gen nor kill. */
else
- {
+ {
visited[pred_bb] = 1;
if (expr_reaches_here_p (occr, expr, pred_bb, check_self_loop, visited))
return 1;
- }
+ }
}
/* All paths have been checked. */
@@ -2980,7 +3004,7 @@ def_reaches_here_p (insn, def_insn)
if (BLOCK_NUM (insn) == BLOCK_NUM (def_insn))
{
if (INSN_CUID (def_insn) < INSN_CUID (insn))
- {
+ {
if (GET_CODE (PATTERN (def_insn)) == PARALLEL)
return 1;
if (GET_CODE (PATTERN (def_insn)) == CLOBBER)
@@ -3163,13 +3187,13 @@ handle_avail_expr (insn, expr)
gcse_create_count++;
if (gcse_file != NULL)
- {
+ {
fprintf (gcse_file, "GCSE: Creating insn %d to copy value of reg %d, computed in insn %d,\n",
INSN_UID (NEXT_INSN (insn_computes_expr)),
REGNO (SET_SRC (PATTERN (NEXT_INSN (insn_computes_expr)))),
INSN_UID (insn_computes_expr));
fprintf (gcse_file, " into newly allocated reg %d\n", REGNO (to));
- }
+ }
pat = PATTERN (insn);
@@ -3218,8 +3242,8 @@ classic_gcse ()
start of the block]. */
reset_opr_set_tables ();
- for (insn = basic_block_head[bb];
- insn != NULL && insn != NEXT_INSN (basic_block_end[bb]);
+ for (insn = BLOCK_HEAD (bb);
+ insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
insn = NEXT_INSN (insn))
{
/* Is insn of form (set (pseudo-reg) ...)? */
@@ -3249,7 +3273,7 @@ classic_gcse ()
/* ??? Need to be careful w.r.t. mods done to INSN. */
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
mark_oprs_set (insn);
- }
+ }
}
return changed;
@@ -3260,8 +3284,7 @@ classic_gcse ()
Return non-zero if a change was made. */
static int
-one_classic_gcse_pass (f, pass)
- rtx f;
+one_classic_gcse_pass (pass)
int pass;
{
int changed = 0;
@@ -3271,7 +3294,7 @@ one_classic_gcse_pass (f, pass)
alloc_expr_hash_table (max_cuid);
alloc_rd_mem (n_basic_blocks, max_cuid);
- compute_expr_hash_table (f);
+ compute_expr_hash_table ();
if (gcse_file)
dump_hash_table (gcse_file, "Expression", expr_hash_table,
expr_hash_table_size, n_exprs);
@@ -3338,23 +3361,6 @@ free_cprop_mem ()
free (cprop_avout);
}
-/* Dump copy/const propagation data. */
-
-void
-dump_cprop_data (file)
- FILE *file;
-{
- dump_sbitmap_vector (file, "CPROP partially locally available sets", "BB",
- cprop_pavloc, n_basic_blocks);
- dump_sbitmap_vector (file, "CPROP absolutely altered sets", "BB",
- cprop_absaltered, n_basic_blocks);
-
- dump_sbitmap_vector (file, "CPROP available incoming sets", "BB",
- cprop_avin, n_basic_blocks);
- dump_sbitmap_vector (file, "CPROP available outgoing sets", "BB",
- cprop_avout, n_basic_blocks);
-}
-
/* For each block, compute whether X is transparent.
X is either an expression or an assignment [though we don't care which,
for this context an assignment is treated as an expression].
@@ -3481,42 +3487,11 @@ compute_transp (x, indx, bmap, set_p)
}
}
-static void
-compute_cprop_local_properties ()
-{
- int i;
-
- sbitmap_vector_zero (cprop_absaltered, n_basic_blocks);
- sbitmap_vector_zero (cprop_pavloc, n_basic_blocks);
-
- for (i = 0; i < set_hash_table_size; i++)
- {
- struct expr *expr;
-
- for (expr = set_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
- {
- struct occr *occr;
- int indx = expr->bitmap_index;
-
- /* The assignment is absolutely altered if any operand is modified
- by this block [excluding the assignment itself].
- We start by assuming all are transparent [none are killed], and
- then setting the bits for those that are. */
-
- compute_transp (expr->expr, indx, cprop_absaltered, 1);
-
- /* The occurrences recorded in avail_occr are exactly those that
- we want to set to non-zero in PAVLOC. */
-
- for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
- {
- int bb = BLOCK_NUM (occr->insn);
- SET_BIT (cprop_pavloc[bb], indx);
- }
- }
- }
-}
-
+/* Compute the available expressions at the start and end of each
+ basic block for cprop. This particular dataflow equation is
+ used often enough that we might want to generalize it and make
+ as a subroutine for other global optimizations that need available
+ in/out information. */
static void
compute_cprop_avinout ()
{
@@ -3531,10 +3506,10 @@ compute_cprop_avinout ()
{
changed = 0;
for (bb = 0; bb < n_basic_blocks; bb++)
- {
+ {
if (bb != 0)
- sbitmap_intersect_of_predecessors (cprop_avin[bb], cprop_avout,
- bb, s_preds);
+ sbitmap_intersect_of_predecessors (cprop_avin[bb],
+ cprop_avout, bb, s_preds);
changed |= sbitmap_union_of_diff (cprop_avout[bb],
cprop_pavloc[bb],
cprop_avin[bb],
@@ -3553,7 +3528,7 @@ compute_cprop_avinout ()
static void
compute_cprop_data ()
{
- compute_cprop_local_properties ();
+ compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, 1);
compute_cprop_avinout ();
}
@@ -3665,6 +3640,11 @@ static int
try_replace_reg (from, to, insn)
rtx from, to, insn;
{
+ /* If this fails we could try to simplify the result of the
+ replacement and attempt to recognize the simplified insn.
+
+ But we need a general simplify_rtx that doesn't have pass
+ specific state variables. I'm not aware of one at the moment. */
return validate_replace_src (from, to, insn);
}
@@ -3692,14 +3672,17 @@ find_avail_set (regno, insn)
The result is non-zero if a change was made. */
static int
-cprop_insn (insn)
+cprop_insn (insn, alter_jumps)
rtx insn;
+ int alter_jumps;
{
struct reg_use *reg_used;
int changed = 0;
- /* ??? For now only propagate into SETs. */
- if (GET_CODE (insn) != INSN
+ /* Only propagate into SETs. Note that a conditional jump is a
+ SET with pc_rtx as the destination. */
+ if ((GET_CODE (insn) != INSN
+ && GET_CODE (insn) != JUMP_INSN)
|| GET_CODE (PATTERN (insn)) != SET)
return 0;
@@ -3735,9 +3718,12 @@ cprop_insn (insn)
abort ();
src = SET_SRC (pat);
- if (GET_CODE (src) == CONST_INT)
+ /* Constant propagation. */
+ if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
{
- if (try_replace_reg (reg_used->reg_rtx, src, insn))
+ /* Handle normal insns first. */
+ if (GET_CODE (insn) == INSN
+ && try_replace_reg (reg_used->reg_rtx, src, insn))
{
changed = 1;
const_prop_count++;
@@ -3745,13 +3731,93 @@ cprop_insn (insn)
{
fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
regno, INSN_UID (insn));
- fprintf (gcse_file, HOST_WIDE_INT_PRINT_DEC, INTVAL (src));
+ print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
}
/* The original insn setting reg_used may or may not now be
deletable. We leave the deletion to flow. */
}
+
+ /* Try to propagate a CONST_INT into a conditional jump.
+ We're pretty specific about what we will handle in this
+ code, we can extend this as necessary over time.
+
+ Right now the insn in question must look like
+
+ (set (pc) (if_then_else ...))
+
+ Note this does not currently handle machines which use cc0. */
+ else if (alter_jumps
+ && GET_CODE (insn) == JUMP_INSN
+ && condjump_p (insn)
+ && ! simplejump_p (insn))
+ {
+ /* We want a copy of the JUMP_INSN so we can modify it
+ in-place as needed without effecting the original. */
+ rtx copy = copy_rtx (insn);
+ rtx set = PATTERN (copy);
+ rtx temp;
+
+ /* Replace the register with the appropriate constant. */
+ replace_rtx (SET_SRC (set), reg_used->reg_rtx, src);
+
+ temp = simplify_ternary_operation (GET_CODE (SET_SRC (set)),
+ GET_MODE (SET_SRC (set)),
+ GET_MODE (XEXP (SET_SRC (set), 0)),
+ XEXP (SET_SRC (set), 0),
+ XEXP (SET_SRC (set), 1),
+ XEXP (SET_SRC (set), 2));
+
+ /* If no simplification can be made, then try the next
+ register. */
+ if (temp)
+ SET_SRC (set) = temp;
+ else
+ continue;
+
+ /* That may have changed the structure of TEMP, so
+ force it to be rerecognized if it has not turned
+ into a nop or unconditional jump. */
+
+ INSN_CODE (copy) = -1;
+ if ((SET_DEST (set) == pc_rtx
+ && (SET_SRC (set) == pc_rtx
+ || GET_CODE (SET_SRC (set)) == LABEL_REF))
+ || recog (PATTERN (copy), copy, NULL) >= 0)
+ {
+ /* This has either become an unconditional jump
+ or a nop-jump. We'd like to delete nop jumps
+ here, but doing so confuses gcse. So we just
+ make the replacement and let later passes
+ sort things out. */
+ PATTERN (insn) = set;
+ INSN_CODE (insn) = -1;
+
+ /* One less use of the label this insn used to jump to
+ if we turned this into a NOP jump. */
+ if (SET_SRC (set) == pc_rtx && JUMP_LABEL (insn) != 0)
+ --LABEL_NUSES (JUMP_LABEL (insn));
+
+ /* If this has turned into an unconditional jump,
+ then put a barrier after it so that the unreachable
+ code will be deleted. */
+ if (GET_CODE (SET_SRC (set)) == LABEL_REF)
+ emit_barrier_after (insn);
+
+ run_jump_opt_after_gcse = 1;
+
+ changed = 1;
+ const_prop_count++;
+ if (gcse_file != NULL)
+ {
+ fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
+ regno, INSN_UID (insn));
+ print_rtl (gcse_file, src);
+ fprintf (gcse_file, "\n");
+ }
+ }
+ }
}
else if (GET_CODE (src) == REG
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
@@ -3790,7 +3856,8 @@ cprop_insn (insn)
Return non-zero if a change was made. */
static int
-cprop ()
+cprop (alter_jumps)
+ int alter_jumps;
{
int bb, changed;
rtx insn;
@@ -3804,19 +3871,19 @@ cprop ()
start of the block]. */
reset_opr_set_tables ();
- for (insn = basic_block_head[bb];
- insn != NULL && insn != NEXT_INSN (basic_block_end[bb]);
+ for (insn = BLOCK_HEAD (bb);
+ insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
insn = NEXT_INSN (insn))
{
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
- changed |= cprop_insn (insn);
+ changed |= cprop_insn (insn, alter_jumps);
/* Keep track of everything modified by this insn. */
/* ??? Need to be careful w.r.t. mods done to INSN. */
mark_oprs_set (insn);
}
- }
+ }
}
if (gcse_file != NULL)
@@ -3830,9 +3897,9 @@ cprop ()
PASS is the pass count. */
static int
-one_cprop_pass (f, pass)
- rtx f;
+one_cprop_pass (pass, alter_jumps)
int pass;
+ int alter_jumps;
{
int changed = 0;
@@ -3840,7 +3907,7 @@ one_cprop_pass (f, pass)
copy_prop_count = 0;
alloc_set_hash_table (max_cuid);
- compute_set_hash_table (f);
+ compute_set_hash_table ();
if (gcse_file)
dump_hash_table (gcse_file, "SET", set_hash_table, set_hash_table_size,
n_sets);
@@ -3848,7 +3915,7 @@ one_cprop_pass (f, pass)
{
alloc_cprop_mem (n_basic_blocks, n_sets);
compute_cprop_data ();
- changed = cprop ();
+ changed = cprop (alter_jumps);
free_cprop_mem ();
}
free_set_hash_table ();
@@ -3864,383 +3931,63 @@ one_cprop_pass (f, pass)
return changed;
}
-/* Compute PRE working variables. */
+/* Compute PRE+LCM working variables. */
/* Local properties of expressions. */
/* Nonzero for expressions that are transparent in the block. */
-static sbitmap *pre_transp;
-/* Nonzero for expressions that are computed (available) in the block. */
-static sbitmap *pre_comp;
-/* Nonzero for expressions that are locally anticipatable in the block. */
-static sbitmap *pre_antloc;
-
-/* Global properties (computed from the expression local properties). */
-/* Nonzero for expressions that are available on block entry/exit. */
-static sbitmap *pre_avin;
-static sbitmap *pre_avout;
-/* Nonzero for expressions that are anticipatable on block entry/exit. */
-static sbitmap *pre_antin;
-static sbitmap *pre_antout;
-/* Nonzero for expressions that are partially available on block entry/exit. */
-static sbitmap *pre_pavin;
-static sbitmap *pre_pavout;
-/* Nonzero for expressions that are "placement possible" on block entry/exit. */
-static sbitmap *pre_ppin;
-static sbitmap *pre_ppout;
-
-/* Used while performing PRE to denote which insns are redundant. */
-static sbitmap pre_redundant;
+static sbitmap *transp;
-/* Allocate vars used for PRE analysis. */
+/* Nonzero for expressions that are transparent at the end of the block.
+ This is only zero for expressions killed by abnormal critical edge
+ created by a calls. */
+static sbitmap *transpout;
-static void
-alloc_pre_mem (n_blocks, n_exprs)
- int n_blocks, n_exprs;
-{
- pre_transp = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_comp = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
-
- pre_avin = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_avout = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_antin = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_antout = sbitmap_vector_alloc (n_blocks, n_exprs);
-
- pre_pavin = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_pavout = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_ppin = sbitmap_vector_alloc (n_blocks, n_exprs);
- pre_ppout = sbitmap_vector_alloc (n_blocks, n_exprs);
-}
-
-/* Free vars used for PRE analysis. */
-
-static void
-free_pre_mem ()
-{
- free (pre_transp);
- free (pre_comp);
- free (pre_antloc);
-
- free (pre_avin);
- free (pre_avout);
- free (pre_antin);
- free (pre_antout);
-
- free (pre_pavin);
- free (pre_pavout);
- free (pre_ppin);
- free (pre_ppout);
-}
-
-/* Dump PRE data. */
-
-void
-dump_pre_data (file)
- FILE *file;
-{
- dump_sbitmap_vector (file, "PRE locally transparent expressions", "BB",
- pre_transp, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE locally available expressions", "BB",
- pre_comp, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE locally anticipatable expressions", "BB",
- pre_antloc, n_basic_blocks);
-
- dump_sbitmap_vector (file, "PRE available incoming expressions", "BB",
- pre_avin, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE available outgoing expressions", "BB",
- pre_avout, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE anticipatable incoming expressions", "BB",
- pre_antin, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE anticipatable outgoing expressions", "BB",
- pre_antout, n_basic_blocks);
-
- dump_sbitmap_vector (file, "PRE partially available incoming expressions", "BB",
- pre_pavin, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE partially available outgoing expressions", "BB",
- pre_pavout, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE placement possible on incoming", "BB",
- pre_ppin, n_basic_blocks);
- dump_sbitmap_vector (file, "PRE placement possible on outgoing", "BB",
- pre_ppout, n_basic_blocks);
-}
-
-/* Compute the local properties of each recorded expression.
- Local properties are those that are defined by the block, irrespective
- of other blocks.
-
- An expression is transparent in a block if its operands are not modified
- in the block.
-
- An expression is computed (locally available) in a block if it is computed
- at least once and expression would contain the same value if the
- computation was moved to the end of the block.
-
- An expression is locally anticipatable in a block if it is computed at
- least once and expression would contain the same value if the computation
- was moved to the beginning of the block. */
-
-static void
-compute_pre_local_properties ()
-{
- int i;
-
- sbitmap_vector_ones (pre_transp, n_basic_blocks);
- sbitmap_vector_zero (pre_comp, n_basic_blocks);
- sbitmap_vector_zero (pre_antloc, n_basic_blocks);
-
- for (i = 0; i < expr_hash_table_size; i++)
- {
- struct expr *expr;
-
- for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
- {
- struct occr *occr;
- int indx = expr->bitmap_index;
-
- /* The expression is transparent in this block if it is not killed.
- We start by assuming all are transparent [none are killed], and then
- reset the bits for those that are. */
-
- compute_transp (expr->expr, indx, pre_transp, 0);
-
- /* The occurrences recorded in antic_occr are exactly those that
- we want to set to non-zero in ANTLOC. */
-
- for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
- {
- int bb = BLOCK_NUM (occr->insn);
- SET_BIT (pre_antloc[bb], indx);
-
- /* While we're scanning the table, this is a good place to
- initialize this. */
- occr->deleted_p = 0;
- }
-
- /* The occurrences recorded in avail_occr are exactly those that
- we want to set to non-zero in COMP. */
-
- for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
- {
- int bb = BLOCK_NUM (occr->insn);
- SET_BIT (pre_comp[bb], indx);
-
- /* While we're scanning the table, this is a good place to
- initialize this. */
- occr->copied_p = 0;
- }
-
- /* While we're scanning the table, this is a good place to
- initialize this. */
- expr->reaching_reg = 0;
- }
- }
-}
-
-/* Compute expression availability at entrance and exit of each block. */
-
-static void
-compute_pre_avinout ()
-{
- int bb, changed, passes;
-
- sbitmap_zero (pre_avin[0]);
- sbitmap_vector_ones (pre_avout, n_basic_blocks);
-
- passes = 0;
- changed = 1;
- while (changed)
- {
- changed = 0;
- for (bb = 0; bb < n_basic_blocks; bb++)
- {
- if (bb != 0)
- sbitmap_intersect_of_predecessors (pre_avin[bb], pre_avout,
- bb, s_preds);
- changed |= sbitmap_a_or_b_and_c (pre_avout[bb], pre_comp[bb],
- pre_transp[bb], pre_avin[bb]);
- }
- passes++;
- }
+/* Nonzero for expressions that are computed (available) in the block. */
+static sbitmap *comp;
- if (gcse_file)
- fprintf (gcse_file, "avail expr computation: %d passes\n", passes);
-}
+/* Nonzero for expressions that are locally anticipatable in the block. */
+static sbitmap *antloc;
-/* Compute expression anticipatability at entrance and exit of each block. */
+/* Nonzero for expressions where this block is an optimal computation
+ point. */
+static sbitmap *pre_optimal;
-static void
-compute_pre_antinout ()
-{
- int bb, changed, passes;
+/* Nonzero for expressions which are redundant in a particular block. */
+static sbitmap *pre_redundant;
- sbitmap_zero (pre_antout[n_basic_blocks - 1]);
- sbitmap_vector_ones (pre_antin, n_basic_blocks);
+static sbitmap *temp_bitmap;
- passes = 0;
- changed = 1;
- while (changed)
- {
- changed = 0;
- /* We scan the blocks in the reverse order to speed up
- the convergence. */
- for (bb = n_basic_blocks - 1; bb >= 0; bb--)
- {
- if (bb != n_basic_blocks - 1)
- sbitmap_intersect_of_successors (pre_antout[bb], pre_antin,
- bb, s_succs);
- changed |= sbitmap_a_or_b_and_c (pre_antin[bb], pre_antloc[bb],
- pre_transp[bb], pre_antout[bb]);
- }
- passes++;
- }
+/* Redundant insns. */
+static sbitmap pre_redundant_insns;
- if (gcse_file)
- fprintf (gcse_file, "antic expr computation: %d passes\n", passes);
-}
-
-/* Compute expression partial availability at entrance and exit of
- each block. */
+/* Allocate vars used for PRE analysis. */
static void
-compute_pre_pavinout ()
+alloc_pre_mem (n_blocks, n_exprs)
+ int n_blocks, n_exprs;
{
- int bb, changed, passes;
-
- sbitmap_zero (pre_pavin[0]);
- sbitmap_vector_zero (pre_pavout, n_basic_blocks);
-
- passes = 0;
- changed = 1;
- while (changed)
- {
- changed = 0;
- for (bb = 0; bb < n_basic_blocks; bb++)
- {
- if (bb != 0)
- sbitmap_union_of_predecessors (pre_pavin[bb], pre_pavout,
- bb, s_preds);
- changed |= sbitmap_a_or_b_and_c (pre_pavout[bb], pre_comp[bb],
- pre_transp[bb], pre_pavin[bb]);
- }
- passes++;
- }
-
- if (gcse_file)
- fprintf (gcse_file, "partially avail expr computation: %d passes\n", passes);
+ transp = sbitmap_vector_alloc (n_blocks, n_exprs);
+ comp = sbitmap_vector_alloc (n_blocks, n_exprs);
+ antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
+
+ temp_bitmap = sbitmap_vector_alloc (n_blocks, n_exprs);
+ pre_optimal = sbitmap_vector_alloc (n_blocks, n_exprs);
+ pre_redundant = sbitmap_vector_alloc (n_blocks, n_exprs);
+ transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
}
-/* Compute "placement possible" information on entrance and exit of
- each block.
-
- From Fred Chow's Thesis:
- A computation `e' is PP at a point `p' if it is anticipated at `p' and
- all the anticipated e's can be rendered redundant by zero or more
- insertions at that point and some other points in the procedure, and
- these insertions satisfy the conditions that the insertions are always
- at points that `e' is anticipated and the first anticipated e's after the
- insertions are rendered redundant. */
+/* Free vars used for PRE analysis. */
static void
-compute_pre_ppinout ()
+free_pre_mem ()
{
- int bb, i, changed, size, passes;
-
- sbitmap_vector_ones (pre_ppin, n_basic_blocks);
- /* ??? Inefficient as we set pre_ppin[0] twice, but simple. */
- sbitmap_zero (pre_ppin[0]);
-
- sbitmap_vector_ones (pre_ppout, n_basic_blocks);
- /* ??? Inefficient as we set pre_ppout[n_basic_blocks-1] twice, but simple. */
- sbitmap_zero (pre_ppout[n_basic_blocks - 1]);
-
- size = pre_ppin[0]->size;
- passes = 0;
- changed = 1;
- while (changed)
- {
- changed = 0;
- for (bb = 1; bb < n_basic_blocks; bb++)
- {
- sbitmap_ptr antin = pre_antin[bb]->elms;
- sbitmap_ptr pavin = pre_pavin[bb]->elms;
- sbitmap_ptr antloc = pre_antloc[bb]->elms;
- sbitmap_ptr transp = pre_transp[bb]->elms;
- sbitmap_ptr ppout = pre_ppout[bb]->elms;
- sbitmap_ptr ppin = pre_ppin[bb]->elms;
-
- for (i = 0; i < size; i++)
- {
- int_list_ptr pred;
- SBITMAP_ELT_TYPE tmp = *antin & *pavin & (*antloc | (*transp & *ppout));
- SBITMAP_ELT_TYPE pred_val = -1L;
-
- for (pred = s_preds[bb]; pred != NULL; pred = pred->next)
- {
- int pred_bb = INT_LIST_VAL (pred);
- sbitmap_ptr ppout_j,avout_j;
-
- if (pred_bb == ENTRY_BLOCK)
- continue;
-
- /* If this is a back edge, propagate info along the back
- edge to allow for loop invariant code motion.
-
- See FOLLOW_BACK_EDGES at the top of this file for a longer
- discussion about loop invariant code motion in pre. */
- if (! FOLLOW_BACK_EDGES
- && (INSN_CUID (BLOCK_HEAD (bb))
- < INSN_CUID (BLOCK_END (pred_bb))))
- {
- pred_val = 0;
- }
- else
- {
- ppout_j = pre_ppout[pred_bb]->elms + i;
- avout_j = pre_avout[pred_bb]->elms + i;
- pred_val &= *ppout_j | *avout_j;
- }
- }
- tmp &= pred_val;
- *ppin = tmp;
- antin++; pavin++; antloc++; transp++; ppout++; ppin++;
- }
- }
-
- for (bb = 0; bb < n_basic_blocks - 1; bb++)
- {
- sbitmap_ptr ppout = pre_ppout[bb]->elms;
-
- for (i = 0; i < size; i++)
- {
- int_list_ptr succ;
- SBITMAP_ELT_TYPE tmp = -1L;
-
- for (succ = s_succs[bb]; succ != NULL; succ = succ->next)
- {
- int succ_bb = INT_LIST_VAL (succ);
- sbitmap_ptr ppin;
-
- if (succ_bb == EXIT_BLOCK)
- continue;
-
- ppin = pre_ppin[succ_bb]->elms + i;
- tmp &= *ppin;
- }
- if (*ppout != tmp)
- {
- changed = 1;
- *ppout++ = tmp;
- }
- else
- ppout++;
- }
- }
-
- passes++;
- }
+ free (transp);
+ free (comp);
+ free (antloc);
- if (gcse_file)
- fprintf (gcse_file, "placement possible computation: %d passes\n", passes);
+ free (pre_optimal);
+ free (pre_redundant);
+ free (transpout);
}
/* Top level routine to do the dataflow analysis needed by PRE. */
@@ -4248,22 +3995,24 @@ compute_pre_ppinout ()
static void
compute_pre_data ()
{
- compute_pre_local_properties ();
- compute_pre_avinout ();
- compute_pre_antinout ();
- compute_pre_pavinout ();
- compute_pre_ppinout ();
- if (gcse_file)
- fprintf (gcse_file, "\n");
+ compute_local_properties (transp, comp, antloc, 0);
+ compute_transpout ();
+ pre_lcm (n_basic_blocks, n_exprs, s_preds, s_succs, transp,
+ antloc, pre_redundant, pre_optimal);
}
+
/* PRE utilities */
-/* Return non-zero if occurrence OCCR of expression EXPR reaches block BB.
+/* Return non-zero if an occurrence of expression EXPR in OCCR_BB would reach
+ block BB.
VISITED is a pointer to a working buffer for tracking which BB's have
been visited. It is NULL for the top-level call.
+ CHECK_PRE_COMP controls whether or not we check for a computation of
+ EXPR in OCCR_BB.
+
We treat reaching expressions that go through blocks containing the same
reaching expression as "not reaching". E.g. if EXPR is generated in blocks
2 and 3, INSN is in block 4, and 2->3->4, we treat the expression in block
@@ -4272,10 +4021,11 @@ compute_pre_data ()
the closest such expression. */
static int
-pre_expr_reaches_here_p (occr, expr, bb, visited)
- struct occr *occr;
+pre_expr_reaches_here_p (occr_bb, expr, bb, check_pre_comp, visited)
+ int occr_bb;
struct expr *expr;
int bb;
+ int check_pre_comp;
char *visited;
{
int_list_ptr pred;
@@ -4293,49 +4043,64 @@ pre_expr_reaches_here_p (occr, expr, bb, visited)
if (pred_bb == ENTRY_BLOCK
/* Has predecessor has already been visited? */
|| visited[pred_bb])
- {
+ {
/* Nothing to do. */
}
/* Does this predecessor generate this expression? */
- else if (TEST_BIT (pre_comp[pred_bb], expr->bitmap_index))
+ else if ((!check_pre_comp && occr_bb == pred_bb)
+ || TEST_BIT (comp[pred_bb], expr->bitmap_index))
{
/* Is this the occurrence we're looking for?
Note that there's only one generating occurrence per block
so we just need to check the block number. */
- if (BLOCK_NUM (occr->insn) == pred_bb)
+ if (occr_bb == pred_bb)
return 1;
visited[pred_bb] = 1;
}
/* Ignore this predecessor if it kills the expression. */
- else if (! TEST_BIT (pre_transp[pred_bb], expr->bitmap_index))
+ else if (! TEST_BIT (transp[pred_bb], expr->bitmap_index))
visited[pred_bb] = 1;
/* Neither gen nor kill. */
else
- {
+ {
visited[pred_bb] = 1;
- if (pre_expr_reaches_here_p (occr, expr, pred_bb, visited))
+ if (pre_expr_reaches_here_p (occr_bb, expr, pred_bb,
+ check_pre_comp, visited))
return 1;
- }
+ }
}
/* All paths have been checked. */
return 0;
}
-/* Add EXPR to the end of basic block BB. */
+/* Add EXPR to the end of basic block BB.
+
+ This is used by both the PRE and code hoisting.
+
+ For PRE, we want to verify that the expr is either transparent
+ or locally anticipatable in the target block. This check makes
+ no sense for code hoisting. */
static void
-pre_insert_insn (expr, bb)
+insert_insn_end_bb (expr, bb, pre)
struct expr *expr;
int bb;
+ int pre;
{
rtx insn = BLOCK_END (bb);
rtx new_insn;
rtx reg = expr->reaching_reg;
int regno = REGNO (reg);
- rtx pat;
+ rtx pat, copied_expr;
+ rtx first_new_insn;
- pat = gen_rtx_SET (VOIDmode, reg, copy_rtx (expr->expr));
+ start_sequence ();
+ copied_expr = copy_rtx (expr->expr);
+ emit_move_insn (reg, copied_expr);
+ first_new_insn = get_insns ();
+ pat = gen_sequence ();
+ end_sequence ();
/* If the last insn is a jump, insert EXPR in front [taking care to
handle cc0, etc. properly]. */
@@ -4370,20 +4135,107 @@ pre_insert_insn (expr, bb)
#endif
/* FIXME: What if something in cc0/jump uses value set in new insn? */
new_insn = emit_insn_before (pat, insn);
- add_label_notes (SET_SRC (pat), new_insn);
if (BLOCK_HEAD (bb) == insn)
BLOCK_HEAD (bb) = new_insn;
- /* Keep block number table up to date. */
- set_block_num (new_insn, bb);
- /* Keep register set table up to date. */
- record_one_set (regno, new_insn);
+ }
+ /* Likewise if the last insn is a call, as will happen in the presence
+ of exception handling. */
+ else if (GET_CODE (insn) == CALL_INSN)
+ {
+ HARD_REG_SET parm_regs;
+ int nparm_regs;
+ rtx p;
+
+ /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
+ we search backward and place the instructions before the first
+ parameter is loaded. Do this for everyone for consistency and a
+ presumtion that we'll get better code elsewhere as well. */
+
+ /* It should always be the case that we can put these instructions
+ anywhere in the basic block with performing PRE optimizations.
+ Check this. */
+ if (pre
+ && !TEST_BIT (antloc[bb], expr->bitmap_index)
+ && !TEST_BIT (transp[bb], expr->bitmap_index))
+ abort ();
+
+ /* Since different machines initialize their parameter registers
+ in different orders, assume nothing. Collect the set of all
+ parameter registers. */
+ CLEAR_HARD_REG_SET (parm_regs);
+ nparm_regs = 0;
+ for (p = CALL_INSN_FUNCTION_USAGE (insn); p ; p = XEXP (p, 1))
+ if (GET_CODE (XEXP (p, 0)) == USE
+ && GET_CODE (XEXP (XEXP (p, 0), 0)) == REG)
+ {
+ int regno = REGNO (XEXP (XEXP (p, 0), 0));
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ abort ();
+ SET_HARD_REG_BIT (parm_regs, regno);
+ nparm_regs++;
+ }
+
+ /* Search backward for the first set of a register in this set. */
+ while (nparm_regs && BLOCK_HEAD (bb) != insn)
+ {
+ insn = PREV_INSN (insn);
+ p = single_set (insn);
+ if (p && GET_CODE (SET_DEST (p)) == REG
+ && REGNO (SET_DEST (p)) < FIRST_PSEUDO_REGISTER
+ && TEST_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p))))
+ {
+ CLEAR_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p)));
+ nparm_regs--;
+ }
+ }
+
+ /* If we found all the parameter loads, then we want to insert
+ before the first parameter load.
+
+ If we did not find all the parameter loads, then we might have
+ stopped on the head of the block, which could be a CODE_LABEL.
+ If we inserted before the CODE_LABEL, then we would be putting
+ the insn in the wrong basic block. In that case, put the insn
+ after the CODE_LABEL.
+
+ ?!? Do we need to account for NOTE_INSN_BASIC_BLOCK here? */
+ if (GET_CODE (insn) != CODE_LABEL)
+ {
+ new_insn = emit_insn_before (pat, insn);
+ if (BLOCK_HEAD (bb) == insn)
+ BLOCK_HEAD (bb) = new_insn;
+ }
+ else
+ {
+ new_insn = emit_insn_after (pat, insn);
+ }
}
else
{
new_insn = emit_insn_after (pat, insn);
- add_label_notes (SET_SRC (pat), new_insn);
BLOCK_END (bb) = new_insn;
- /* Keep block number table up to date. */
+ }
+
+ /* Keep block number table up to date.
+ Note, PAT could be a multiple insn sequence, we have to make
+ sure that each insn in the sequence is handled. */
+ if (GET_CODE (pat) == SEQUENCE)
+ {
+ int i;
+
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx insn = XVECEXP (pat, 0, i);
+ set_block_num (insn, bb);
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ add_label_notes (PATTERN (insn), new_insn);
+ record_set_insn = insn;
+ note_stores (PATTERN (insn), record_set_info);
+ }
+ }
+ else
+ {
+ add_label_notes (SET_SRC (pat), new_insn);
set_block_num (new_insn, bb);
/* Keep register set table up to date. */
record_one_set (regno, new_insn);
@@ -4393,49 +4245,69 @@ pre_insert_insn (expr, bb)
if (gcse_file)
{
- fprintf (gcse_file, "PRE: end of bb %d, insn %d, copying expression %d to reg %d\n",
+ fprintf (gcse_file, "PRE/HOIST: end of bb %d, insn %d, copying expression %d to reg %d\n",
bb, INSN_UID (new_insn), expr->bitmap_index, regno);
}
}
/* Insert partially redundant expressions at the ends of appropriate basic
- blocks making them now redundant. */
+ blocks making them fully redundant. */
static void
pre_insert (index_map)
struct expr **index_map;
{
- int bb, i, size;
+ int bb, i, set_size;
+ sbitmap *inserted;
+
+ /* Compute INSERT = PRE_OPTIMAL & ~PRE_REDUNDANT.
+ Where INSERT is nonzero, we add the expression at the end of the basic
+ block if it reaches any of the deleted expressions. */
- /* Compute INSERT = PPOUT & (~AVOUT) & (~PPIN | ~TRANSP) for each
- expression. Where INSERT == TRUE, add the expression at the end of
- the basic block. */
+ set_size = pre_optimal[0]->size;
+ inserted = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
+ sbitmap_vector_zero (inserted, n_basic_blocks);
- size = pre_ppout[0]->size;
for (bb = 0; bb < n_basic_blocks; bb++)
{
int indx;
- sbitmap_ptr ppout = pre_ppout[bb]->elms;
- sbitmap_ptr avout = pre_avout[bb]->elms;
- sbitmap_ptr ppin = pre_ppin[bb]->elms;
- sbitmap_ptr transp = pre_transp[bb]->elms;
-
- for (i = indx = 0;
- i < size;
- i++, indx += SBITMAP_ELT_BITS, ppout++, avout++, ppin++, transp++)
+
+ /* This computes the number of potential insertions we need. */
+ sbitmap_not (temp_bitmap[bb], pre_redundant[bb]);
+ sbitmap_a_and_b (temp_bitmap[bb], temp_bitmap[bb], pre_optimal[bb]);
+
+ /* TEMP_BITMAP[bb] now contains a bitmap of the expressions that we need
+ to insert at the end of this basic block. */
+ for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS)
{
+ SBITMAP_ELT_TYPE insert = temp_bitmap[bb]->elms[i];
int j;
- SBITMAP_ELT_TYPE insert = *ppout & (~*avout) & (~*ppin | ~*transp);
- for (j = indx; insert != 0 && j < n_exprs; j++, insert >>= 1)
+ for (j = indx; insert && j < n_exprs; j++, insert >>= 1)
{
- if ((insert & 1) != 0
- /* If the basic block isn't reachable, PPOUT will be TRUE.
- However, we don't want to insert a copy here because the
- expression may not really be redundant. So only insert
- an insn if the expression was deleted. */
- && index_map[j]->reaching_reg != NULL)
- pre_insert_insn (index_map[j], bb);
+ if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
+ {
+ struct expr *expr = index_map[j];
+ struct occr *occr;
+
+ /* Now look at each deleted occurence of this expression. */
+ for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
+ {
+ if (! occr->deleted_p)
+ continue;
+
+ /* Insert this expression at the end of BB if it would
+ reach the deleted occurence. */
+ if (!TEST_BIT (inserted[bb], j)
+ && pre_expr_reaches_here_p (bb, expr,
+ BLOCK_NUM (occr->insn), 0,
+ NULL))
+ {
+ SET_BIT (inserted[bb], j);
+ insert_insn_end_bb (index_map[j], bb, 1);
+ }
+ }
+ }
}
}
}
@@ -4479,7 +4351,12 @@ pre_insert_copy_insn (expr, insn)
static void
pre_insert_copies ()
{
- int i;
+ int i, bb;
+
+ for (bb = 0; bb < n_basic_blocks; bb++)
+ {
+ sbitmap_a_and_b (temp_bitmap[bb], pre_optimal[bb], pre_redundant[bb]);
+ }
/* For each available expression in the table, copy the result to
`reaching_reg' if the expression reaches a deleted one.
@@ -4514,17 +4391,21 @@ pre_insert_copies ()
for (avail = expr->avail_occr; avail != NULL; avail = avail->next)
{
rtx insn = avail->insn;
+ int bb = BLOCK_NUM (insn);
+
+ if (!TEST_BIT (temp_bitmap[bb], expr->bitmap_index))
+ continue;
/* No need to handle this one if handled already. */
if (avail->copied_p)
continue;
/* Don't handle this one if it's a redundant one. */
- if (TEST_BIT (pre_redundant, INSN_CUID (insn)))
+ if (TEST_BIT (pre_redundant_insns, INSN_CUID (insn)))
continue;
/* Or if the expression doesn't reach the deleted one. */
- if (! pre_expr_reaches_here_p (avail, expr,
+ if (! pre_expr_reaches_here_p (BLOCK_NUM (avail->insn), expr,
BLOCK_NUM (occr->insn),
- NULL))
+ 1, NULL))
continue;
/* Copy the result of avail to reaching_reg. */
@@ -4537,7 +4418,6 @@ pre_insert_copies ()
}
/* Delete redundant computations.
- These are ones that satisy ANTLOC & PPIN.
Deletion is done by changing the insn to copy the `reaching_reg' of
the expression into the result of the SET. It is left to later passes
(cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it.
@@ -4547,7 +4427,15 @@ pre_insert_copies ()
static int
pre_delete ()
{
- int i, changed;
+ int i, bb, changed;
+
+ /* Compute the expressions which are redundant and need to be replaced by
+ copies from the reaching reg to the target reg. */
+ for (bb = 0; bb < n_basic_blocks; bb++)
+ {
+ sbitmap_not (temp_bitmap[bb], pre_optimal[bb]);
+ sbitmap_a_and_b (temp_bitmap[bb], temp_bitmap[bb], pre_redundant[bb]);
+ }
changed = 0;
for (i = 0; i < expr_hash_table_size; i++)
@@ -4567,9 +4455,8 @@ pre_delete ()
rtx insn = occr->insn;
rtx set;
int bb = BLOCK_NUM (insn);
- sbitmap ppin = pre_ppin[bb];
- if (TEST_BIT (ppin, indx))
+ if (TEST_BIT (temp_bitmap[bb], indx))
{
set = single_set (insn);
if (! set)
@@ -4587,20 +4474,21 @@ pre_delete ()
However, on the x86 some of the movXX patterns actually
contain clobbers of scratch regs. This may cause the
- insn created by validate_change to not patch any pattern
+ insn created by validate_change to not match any pattern
and thus cause validate_change to fail. */
if (validate_change (insn, &SET_SRC (set),
expr->reaching_reg, 0))
{
occr->deleted_p = 1;
- SET_BIT (pre_redundant, INSN_CUID (insn));
+ SET_BIT (pre_redundant_insns, INSN_CUID (insn));
changed = 1;
gcse_subst_count++;
}
if (gcse_file)
{
- fprintf (gcse_file, "PRE: redundant insn %d (expression %d) in bb %d, reaching reg is %d\n",
+ fprintf (gcse_file,
+ "PRE: redundant insn %d (expression %d) in bb %d, reaching reg is %d\n",
INSN_UID (insn), indx, bb, REGNO (expr->reaching_reg));
}
}
@@ -4615,10 +4503,9 @@ pre_delete ()
This is called by one_pre_gcse_pass after all the dataflow analysis
has been done.
- This is based on the original Morel-Renvoise paper and Fred Chow's thesis.
-
- The M-R paper uses "TRANSP" to describe an expression as being transparent
- in a block where as Chow's thesis uses "ALTERED". We use TRANSP.
+ This is based on the original Morel-Renvoise paper Fred Chow's thesis,
+ and lazy code motion from Knoop, Ruthing and Steffen as described in
+ Advanced Compiler Design and Implementation.
??? A new pseudo reg is created to hold the reaching expression.
The nice thing about the classical approach is that it would try to
@@ -4653,8 +4540,8 @@ pre_gcse ()
}
/* Reset bitmap used to track which insns are redundant. */
- pre_redundant = sbitmap_alloc (max_cuid);
- sbitmap_zero (pre_redundant);
+ pre_redundant_insns = sbitmap_alloc (max_cuid);
+ sbitmap_zero (pre_redundant_insns);
/* Delete the redundant insns first so that
- we know what register to use for the new insns and for the other
@@ -4670,7 +4557,7 @@ pre_gcse ()
specially allocated pseudo-reg that reaches the redundant expression. */
pre_insert_copies ();
- free (pre_redundant);
+ free (pre_redundant_insns);
return changed;
}
@@ -4680,8 +4567,7 @@ pre_gcse ()
Return non-zero if a change was made. */
static int
-one_pre_gcse_pass (f, pass)
- rtx f;
+one_pre_gcse_pass (pass)
int pass;
{
int changed = 0;
@@ -4690,7 +4576,7 @@ one_pre_gcse_pass (f, pass)
gcse_create_count = 0;
alloc_expr_hash_table (max_cuid);
- compute_expr_hash_table (f);
+ compute_expr_hash_table ();
if (gcse_file)
dump_hash_table (gcse_file, "Expression", expr_hash_table,
expr_hash_table_size, n_exprs);
@@ -4737,10 +4623,10 @@ add_label_notes (x, insn)
if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x))
{
/* This code used to ignore labels that referred to dispatch tables to
- avoid flow generating (slighly) worse code.
+ avoid flow generating (slighly) worse code.
- We no longer ignore such label references (see LABEL_REF handling in
- mark_jump_label for additional information). */
+ We no longer ignore such label references (see LABEL_REF handling in
+ mark_jump_label for additional information). */
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL, XEXP (x, 0),
REG_NOTES (insn));
return;
@@ -4756,3 +4642,54 @@ add_label_notes (x, insn)
add_label_notes (XVECEXP (x, i, j), insn);
}
}
+
+/* Compute transparent outgoing information for each block.
+
+ An expression is transparent to an edge unless it is killed by
+ the edge itself. This can only happen with abnormal control flow,
+ when the edge is traversed through a call. This happens with
+ non-local labels and exceptions.
+
+ This would not be necessary if we split the edge. While this is
+ normally impossible for abnormal critical edges, with some effort
+ it should be possible with exception handling, since we still have
+ control over which handler should be invoked. But due to increased
+ EH table sizes, this may not be worthwhile. */
+
+static void
+compute_transpout ()
+{
+ int bb;
+
+ sbitmap_vector_ones (transpout, n_basic_blocks);
+
+ for (bb = 0; bb < n_basic_blocks; ++bb)
+ {
+ int i;
+
+ /* Note that flow inserted a nop a the end of basic blocks that
+ end in call instructions for reasons other than abnormal
+ control flow. */
+ if (GET_CODE (BLOCK_END (bb)) != CALL_INSN)
+ continue;
+
+ for (i = 0; i < expr_hash_table_size; i++)
+ {
+ struct expr *expr;
+ for (expr = expr_hash_table[i]; expr ; expr = expr->next_same_hash)
+ if (GET_CODE (expr->expr) == MEM)
+ {
+ rtx addr = XEXP (expr->expr, 0);
+
+ if (GET_CODE (addr) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (addr))
+ continue;
+
+ /* ??? Optimally, we would use interprocedural alias
+ analysis to determine if this mem is actually killed
+ by this call. */
+ RESET_BIT (transpout[bb], expr->bitmap_index);
+ }
+ }
+ }
+}
diff --git a/contrib/gcc/gen-protos.c b/contrib/gcc/gen-protos.c
index 8b018cd..1085035 100644
--- a/contrib/gcc/gen-protos.c
+++ b/contrib/gcc/gen-protos.c
@@ -17,10 +17,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "hconfig.h"
#include "system.h"
-#include "gansidecl.h"
#include "scan.h"
#include "cpplib.h"
#include "cpphash.h"
+#undef abort
int verbose = 0;
char *progname;
@@ -29,20 +29,6 @@ char *progname;
int hash_tab[HASH_SIZE];
int next_index;
-int
-hashf (name, len, hashsize)
- register const U_CHAR *name;
- register int len;
- int hashsize;
-{
- register int r = 0;
-
- while (len--)
- r = HASHSTEP (r, *name++);
-
- return MAKE_POS (r) % hashsize;
-}
-
static void
add_hash (fname)
char *fname;
@@ -110,7 +96,7 @@ parse_fn_proto (start, end, fn)
ptr--;
while (*ptr == ' ' || *ptr == '\t') ptr--;
- if (!ISALNUM (*ptr))
+ if (!ISALNUM ((unsigned char)*ptr))
{
if (verbose)
fprintf (stderr, "%s: Can't handle this complex prototype: %s\n",
@@ -119,7 +105,7 @@ parse_fn_proto (start, end, fn)
}
name_end = ptr+1;
- while (ISALNUM (*ptr) || *ptr == '_') --ptr;
+ while (ISALNUM ((unsigned char)*ptr) || *ptr == '_') --ptr;
name_start = ptr+1;
while (*ptr == ' ' || *ptr == '\t') ptr--;
ptr[1] = 0;
@@ -140,7 +126,7 @@ parse_fn_proto (start, end, fn)
int
main (argc, argv)
- int argc;
+ int argc ATTRIBUTE_UNUSED;
char **argv;
{
FILE *inf = stdin;
@@ -158,7 +144,7 @@ main (argc, argv)
fprintf (outf, "struct fn_decl std_protos[] = {\n");
/* A hash table entry of 0 means "unused" so reserve it. */
- fprintf (outf, " {\"\", \"\", \"\"},\n");
+ fprintf (outf, " {\"\", \"\", \"\", 0},\n");
next_index = 1;
for (;;)
@@ -180,13 +166,13 @@ main (argc, argv)
add_hash (fn_decl.fname);
- fprintf (outf, " {\"%s\", \"%s\", \"%s\"},\n",
+ fprintf (outf, " {\"%s\", \"%s\", \"%s\", 0},\n",
fn_decl.fname, fn_decl.rtype, fn_decl.params);
if (c == EOF)
break;
}
- fprintf (outf, " {0, 0, 0}\n};\n");
+ fprintf (outf, " {0, 0, 0, 0}\n};\n");
fprintf (outf, "#define HASH_SIZE %d\n", HASH_SIZE);
@@ -197,21 +183,3 @@ main (argc, argv)
return 0;
}
-
-/* Avoid error if config defines abort as fancy_abort.
- It's not worth "really" implementing this because ordinary
- compiler users never run fix-header. */
-
-void
-fancy_abort ()
-{
- abort ();
-}
-
-void
-fatal (s)
- char *s;
-{
- fprintf (stderr, "%s: %s\n", "gen-protos", s);
- exit (FATAL_EXIT_CODE);
-}
diff --git a/contrib/gcc/genattr.c b/contrib/gcc/genattr.c
index c50e0fd4..55d6fb1 100644
--- a/contrib/gcc/genattr.c
+++ b/contrib/gcc/genattr.c
@@ -1,5 +1,5 @@
/* Generate attribute information (insn-attr.h) from machine description.
- Copyright (C) 1991, 1994, 1996, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1994, 1996, 1998, 1999 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -21,11 +21,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -36,9 +31,9 @@ struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
/* Define this so we can link with print-rtl.o to get debug_rtx function. */
char **insn_name_ptr = 0;
@@ -203,40 +198,44 @@ write_units (num_units, multiplicity, simultaneity,
printf ("#define INSN_QUEUE_SIZE %d\n", q_size);
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char * result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genattr: ");
diff --git a/contrib/gcc/genattrtab.c b/contrib/gcc/genattrtab.c
index 686bf5c..fcb50c1 100644
--- a/contrib/gcc/genattrtab.c
+++ b/contrib/gcc/genattrtab.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to compute values of attributes.
- Copyright (C) 1991, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -34,7 +34,7 @@ Boston, MA 02111-1307, USA. */
If the attribute `alternative', or a random C expression is present,
`constrain_operands' is called. If either of these cases of a reference to
- an operand is found, `insn_extract' is called.
+ an operand is found, `extract_insn' is called.
The special attribute `length' is also recognized. For this operand,
expressions involving the address of an operand or the current insn,
@@ -96,12 +96,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-/* varargs must always be included after *config.h, but before stdio.h. */
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "insn-config.h" /* For REGISTER_CONSTRAINTS */
@@ -125,8 +119,9 @@ struct obstack *temp_obstack = &obstack2;
/* Define this so we can link with print-rtl.o to get debug_rtx function. */
char **insn_name_ptr = 0;
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
/* enough space to reserve for printing out ints */
#define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3)
@@ -370,12 +365,13 @@ rtx pic_offset_table_rtx;
static void attr_hash_add_rtx PROTO((int, rtx));
static void attr_hash_add_string PROTO((int, char *));
static rtx attr_rtx PVPROTO((enum rtx_code, ...));
-static char *attr_printf PVPROTO((int, char *, ...));
-static char *attr_string PROTO((char *, int));
+static char *attr_printf PVPROTO((int, const char *, ...))
+ ATTRIBUTE_PRINTF_2;
+static char *attr_string PROTO((const char *, int));
static rtx check_attr_test PROTO((rtx, int));
static rtx check_attr_value PROTO((rtx, struct attr_desc *));
-static rtx convert_set_attr_alternative PROTO((rtx, int, int, int));
-static rtx convert_set_attr PROTO((rtx, int, int, int));
+static rtx convert_set_attr_alternative PROTO((rtx, int, int));
+static rtx convert_set_attr PROTO((rtx, int, int));
static void check_defs PROTO((void));
#if 0
static rtx convert_const_symbol_ref PROTO((rtx, struct attr_desc *));
@@ -430,36 +426,35 @@ static void gen_insn PROTO((rtx));
static void gen_delay PROTO((rtx));
static void gen_unit PROTO((rtx));
static void write_test_expr PROTO((rtx, int));
-static int max_attr_value PROTO((rtx));
-static int or_attr_value PROTO((rtx));
+static int max_attr_value PROTO((rtx, int*));
+static int or_attr_value PROTO((rtx, int*));
static void walk_attr_value PROTO((rtx));
static void write_attr_get PROTO((struct attr_desc *));
static rtx eliminate_known_true PROTO((rtx, rtx, int, int));
-static void write_attr_set PROTO((struct attr_desc *, int, rtx, char *,
- char *, rtx, int, int));
+static void write_attr_set PROTO((struct attr_desc *, int, rtx,
+ const char *, const char *, rtx,
+ int, int));
static void write_attr_case PROTO((struct attr_desc *, struct attr_value *,
- int, char *, char *, int, rtx));
-static void write_unit_name PROTO((char *, int, char *));
+ int, const char *, const char *, int, rtx));
+static void write_unit_name PROTO((const char *, int, const char *));
static void write_attr_valueq PROTO((struct attr_desc *, char *));
static void write_attr_value PROTO((struct attr_desc *, rtx));
static void write_upcase PROTO((char *));
static void write_indent PROTO((int));
-static void write_eligible_delay PROTO((char *));
+static void write_eligible_delay PROTO((const char *));
static void write_function_unit_info PROTO((void));
-static void write_complex_function PROTO((struct function_unit *, char *,
- char *));
+static void write_complex_function PROTO((struct function_unit *, const char *,
+ const char *));
static int write_expr_attr_cache PROTO((rtx, struct attr_desc *));
static void write_toplevel_expr PROTO((rtx));
static int n_comma_elts PROTO((char *));
static char *next_comma_elt PROTO((char **));
-static struct attr_desc *find_attr PROTO((char *, int));
-static void make_internal_attr PROTO((char *, rtx, int));
+static struct attr_desc *find_attr PROTO((const char *, int));
+static void make_internal_attr PROTO((const char *, rtx, int));
static struct attr_value *find_most_used PROTO((struct attr_desc *));
static rtx find_single_value PROTO((struct attr_desc *));
static rtx make_numeric_value PROTO((int));
static void extend_range PROTO((struct range *, int, int));
-char *xrealloc PROTO((char *, unsigned));
-char *xmalloc PROTO((unsigned));
#define oballoc(size) obstack_alloc (hash_obstack, size)
@@ -543,7 +538,7 @@ attr_hash_add_string (hashcode, str)
static rtx
attr_rtx VPROTO((enum rtx_code code, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
enum rtx_code code;
#endif
va_list p;
@@ -556,7 +551,7 @@ attr_rtx VPROTO((enum rtx_code code, ...))
VA_START (p, code);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
code = va_arg (p, enum rtx_code);
#endif
@@ -738,20 +733,20 @@ attr_rtx VPROTO((enum rtx_code code, ...))
/*VARARGS2*/
static char *
-attr_printf VPROTO((register int len, char *fmt, ...))
+attr_printf VPROTO((register int len, const char *fmt, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
register int len;
- char *fmt;
+ const char *fmt;
#endif
va_list p;
register char *str;
VA_START (p, fmt);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
len = va_arg (p, int);
- fmt = va_arg (p, char *);
+ fmt = va_arg (p, const char *);
#endif
/* Print the string into a temporary location. */
@@ -782,7 +777,7 @@ attr_numeral (n)
static char *
attr_string (str, len)
- char *str;
+ const char *str;
int len;
{
register struct attr_hash *h;
@@ -1088,7 +1083,7 @@ check_attr_value (exp, attr)
fatal ("CONST_INT not valid for non-numeric `%s' attribute",
attr->name);
- if (INTVAL (exp) < 0)
+ if (INTVAL (exp) < 0 && ! attr->negative_ok)
fatal ("Negative numeric value specified for `%s' attribute",
attr->name);
@@ -1128,6 +1123,16 @@ check_attr_value (exp, attr)
XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
break;
+ case PLUS:
+ case MINUS:
+ case MULT:
+ case DIV:
+ case MOD:
+ if (attr && !attr->is_numeric)
+ fatal ("Invalid operation `%s' for non-numeric attribute value",
+ GET_RTX_NAME (GET_CODE (exp)));
+ /* FALLTHRU */
+
case IOR:
case AND:
XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
@@ -1153,12 +1158,27 @@ check_attr_value (exp, attr)
XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
break;
+ case ATTR:
+ {
+ struct attr_desc *attr2 = find_attr (XSTR (exp, 0), 0);
+ if (attr2 == NULL)
+ fatal ("Unknown attribute `%s' in ATTR", XSTR (exp, 0));
+ else if ((attr && attr->is_const) && ! attr2->is_const)
+ fatal ("Non-constant attribute `%s' referenced from `%s'",
+ XSTR (exp, 0), attr->name);
+ else if (attr
+ && (attr->is_numeric != attr2->is_numeric
+ || (! attr->negative_ok && attr2->negative_ok)))
+ fatal ("Numeric attribute mismatch calling `%s' from `%s'",
+ XSTR (exp, 0), attr->name);
+ }
+ break;
+
case SYMBOL_REF:
- if (attr && attr->is_const)
- /* A constant SYMBOL_REF is valid as a constant attribute test and
- is expanded later by make_canonical into a COND. */
- return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
- /* Otherwise, fall through... */
+ /* A constant SYMBOL_REF is valid as a constant attribute test and
+ is expanded later by make_canonical into a COND. In a non-constant
+ attribute test, it is left be. */
+ return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
default:
fatal ("Invalid operation `%s' for attribute value",
@@ -1172,10 +1192,10 @@ check_attr_value (exp, attr)
It becomes a COND with each test being (eq_attr "alternative "n") */
static rtx
-convert_set_attr_alternative (exp, num_alt, insn_code, insn_index)
+convert_set_attr_alternative (exp, num_alt, insn_index)
rtx exp;
int num_alt;
- int insn_code, insn_index;
+ int insn_index;
{
rtx condexp;
int i;
@@ -1213,10 +1233,10 @@ convert_set_attr_alternative (exp, num_alt, insn_code, insn_index)
list of values is given, convert to SET_ATTR_ALTERNATIVE first. */
static rtx
-convert_set_attr (exp, num_alt, insn_code, insn_index)
+convert_set_attr (exp, num_alt, insn_index)
rtx exp;
int num_alt;
- int insn_code, insn_index;
+ int insn_index;
{
rtx newexp;
char *name_ptr;
@@ -1240,7 +1260,7 @@ convert_set_attr (exp, num_alt, insn_code, insn_index)
while ((p = next_comma_elt (&name_ptr)) != NULL)
XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p);
- return convert_set_attr_alternative (newexp, num_alt, insn_code, insn_index);
+ return convert_set_attr_alternative (newexp, num_alt, insn_index);
}
/* Scan all definitions, checking for validity. Also, convert any SET_ATTR
@@ -1273,13 +1293,12 @@ check_defs ()
case SET_ATTR_ALTERNATIVE:
value = convert_set_attr_alternative (value,
id->num_alternatives,
- id->insn_code,
id->insn_index);
break;
case SET_ATTR:
value = convert_set_attr (value, id->num_alternatives,
- id->insn_code, id->insn_index);
+ id->insn_index);
break;
default:
@@ -1823,7 +1842,7 @@ expand_units ()
rtx unitsmask;
rtx readycost;
rtx newexp;
- char *str;
+ const char *str;
int i, j, u, num, nvalues;
/* Rebuild the condition for the unit to share the RTL expressions.
@@ -2107,7 +2126,10 @@ expand_units ()
}
/* Record MAX (BLOCKAGE (*,*)). */
- unit->max_blockage = max_attr_value (max_blockage);
+ {
+ int unknown;
+ unit->max_blockage = max_attr_value (max_blockage, &unknown);
+ }
/* See if the upper and lower bounds of BLOCKAGE (E,*) are the
same. If so, the blockage function carries no additional
@@ -2192,9 +2214,14 @@ simplify_knowing (exp, known_true)
{
if (GET_CODE (exp) != CONST_STRING)
{
- exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
- make_numeric_value (max_attr_value (exp)));
- exp = simplify_by_exploding (exp);
+ int unknown = 0, max;
+ max = max_attr_value (exp, &unknown);
+ if (! unknown)
+ {
+ exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
+ make_numeric_value (max));
+ exp = simplify_by_exploding (exp);
+ }
}
return exp;
}
@@ -2392,9 +2419,9 @@ substitute_address (exp, no_address_fn, address_fn)
static void
make_length_attrs ()
{
- static char *new_names[] = {"*insn_default_length",
- "*insn_variable_length_p",
- "*insn_current_length"};
+ static const char *new_names[] = {"*insn_default_length",
+ "*insn_variable_length_p",
+ "*insn_current_length"};
static rtx (*no_address_fn[]) PROTO((rtx)) = {identity_fn, zero_fn, zero_fn};
static rtx (*address_fn[]) PROTO((rtx)) = {max_fn, one_fn, identity_fn};
size_t i;
@@ -2464,7 +2491,8 @@ static rtx
max_fn (exp)
rtx exp;
{
- return make_numeric_value (max_attr_value (exp));
+ int unknown;
+ return make_numeric_value (max_attr_value (exp, &unknown));
}
static void
@@ -2474,16 +2502,23 @@ write_length_unit_log ()
struct attr_value *av;
struct insn_ent *ie;
unsigned int length_unit_log, length_or;
+ int unknown = 0;
if (length_attr == 0)
return;
- length_or = or_attr_value (length_attr->default_val->value);
- for (av = length_attr->first_value; av; av = av->next)
- for (ie = av->first_insn; ie; ie = ie->next)
- length_or |= or_attr_value (av->value);
- length_or = ~length_or;
- for (length_unit_log = 0; length_or & 1; length_or >>= 1)
- length_unit_log++;
+ length_or = or_attr_value (length_attr->default_val->value, &unknown);
+ for (av = length_attr->first_value; av; av = av->next)
+ for (ie = av->first_insn; ie; ie = ie->next)
+ length_or |= or_attr_value (av->value, &unknown);
+
+ if (unknown)
+ length_unit_log = 0;
+ else
+ {
+ length_or = ~length_or;
+ for (length_unit_log = 0; length_or & 1; length_or >>= 1)
+ length_unit_log++;
+ }
printf ("int length_unit_log = %u;\n", length_unit_log);
}
@@ -3709,6 +3744,8 @@ find_and_mark_used_attributes (exp, terms, nterms)
*nterms += 1;
MEM_VOLATILE_P (exp) = 1;
}
+ return 1;
+
case CONST_STRING:
case CONST_INT:
return 1;
@@ -4112,7 +4149,7 @@ gen_attr (exp)
fatal ("Duplicate definition for `%s' attribute", attr->name);
if (*XSTR (exp, 1) == '\0')
- attr->is_numeric = 1;
+ attr->is_numeric = 1;
else
{
name_ptr = XSTR (exp, 1);
@@ -4658,80 +4695,83 @@ write_test_expr (exp, flags)
}
/* Given an attribute value, return the maximum CONST_STRING argument
- encountered. It is assumed that they are all numeric. */
+ encountered. Set *UNKNOWNP and return INT_MAX if the value is unknown. */
static int
-max_attr_value (exp)
+max_attr_value (exp, unknownp)
rtx exp;
+ int *unknownp;
{
- int current_max = 0;
- int n;
- int i;
+ int current_max;
+ int i, n;
- if (GET_CODE (exp) == CONST_STRING)
- return atoi (XSTR (exp, 0));
-
- else if (GET_CODE (exp) == COND)
+ switch (GET_CODE (exp))
{
+ case CONST_STRING:
+ current_max = atoi (XSTR (exp, 0));
+ break;
+
+ case COND:
+ current_max = max_attr_value (XEXP (exp, 1), unknownp);
for (i = 0; i < XVECLEN (exp, 0); i += 2)
{
- n = max_attr_value (XVECEXP (exp, 0, i + 1));
+ n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
if (n > current_max)
current_max = n;
}
+ break;
- n = max_attr_value (XEXP (exp, 1));
+ case IF_THEN_ELSE:
+ current_max = max_attr_value (XEXP (exp, 1), unknownp);
+ n = max_attr_value (XEXP (exp, 2), unknownp);
if (n > current_max)
current_max = n;
- }
+ break;
- else if (GET_CODE (exp) == IF_THEN_ELSE)
- {
- current_max = max_attr_value (XEXP (exp, 1));
- n = max_attr_value (XEXP (exp, 2));
- if (n > current_max)
- current_max = n;
+ default:
+ *unknownp = 1;
+ current_max = INT_MAX;
+ break;
}
- else
- abort ();
-
return current_max;
}
/* Given an attribute value, return the result of ORing together all
- CONST_STRING arguments encountered. It is assumed that they are
- all numeric. */
+ CONST_STRING arguments encountered. Set *UNKNOWNP and return -1
+ if the numeric value is not known. */
static int
-or_attr_value (exp)
+or_attr_value (exp, unknownp)
rtx exp;
+ int *unknownp;
{
- int current_or = 0;
+ int current_or;
int i;
- if (GET_CODE (exp) == CONST_STRING)
- return atoi (XSTR (exp, 0));
-
- else if (GET_CODE (exp) == COND)
+ switch (GET_CODE (exp))
{
+ case CONST_STRING:
+ current_or = atoi (XSTR (exp, 0));
+ break;
+
+ case COND:
+ current_or = or_attr_value (XEXP (exp, 1), unknownp);
for (i = 0; i < XVECLEN (exp, 0); i += 2)
- {
- current_or |= or_attr_value (XVECEXP (exp, 0, i + 1));
- }
+ current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
+ break;
- current_or |= or_attr_value (XEXP (exp, 1));
- }
+ case IF_THEN_ELSE:
+ current_or = or_attr_value (XEXP (exp, 1), unknownp);
+ current_or |= or_attr_value (XEXP (exp, 2), unknownp);
+ break;
- else if (GET_CODE (exp) == IF_THEN_ELSE)
- {
- current_or = or_attr_value (XEXP (exp, 1));
- current_or |= or_attr_value (XEXP (exp, 2));
+ default:
+ *unknownp = 1;
+ current_or = -1;
+ break;
}
- else
- abort ();
-
return current_or;
}
@@ -4929,19 +4969,12 @@ write_attr_set (attr, indent, value, prefix, suffix, known_true,
struct attr_desc *attr;
int indent;
rtx value;
- char *prefix;
- char *suffix;
+ const char *prefix;
+ const char *suffix;
rtx known_true;
int insn_code, insn_index;
{
- if (GET_CODE (value) == CONST_STRING)
- {
- write_indent (indent);
- printf ("%s ", prefix);
- write_attr_value (attr, value);
- printf ("%s\n", suffix);
- }
- else if (GET_CODE (value) == COND)
+ if (GET_CODE (value) == COND)
{
/* Assume the default value will be the default of the COND unless we
find an always true expression. */
@@ -5015,7 +5048,12 @@ write_attr_set (attr, indent, value, prefix, suffix, known_true,
}
}
else
- abort ();
+ {
+ write_indent (indent);
+ printf ("%s ", prefix);
+ write_attr_value (attr, value);
+ printf ("%s\n", suffix);
+ }
}
/* Write out the computation for one attribute value. */
@@ -5026,7 +5064,7 @@ write_attr_case (attr, av, write_case_lines, prefix, suffix, indent,
struct attr_desc *attr;
struct attr_value *av;
int write_case_lines;
- char *prefix, *suffix;
+ const char *prefix, *suffix;
int indent;
rtx known_true;
{
@@ -5069,14 +5107,14 @@ write_attr_case (attr, av, write_case_lines, prefix, suffix, indent,
if (must_extract)
{
write_indent (indent + 2);
- printf ("insn_extract (insn);\n");
+ printf ("extract_insn (insn);\n");
}
if (must_constrain)
{
#ifdef REGISTER_CONSTRAINTS
write_indent (indent + 2);
- printf ("if (! constrain_operands (INSN_CODE (insn), reload_completed))\n");
+ printf ("if (! constrain_operands (reload_completed))\n");
write_indent (indent + 2);
printf (" fatal_insn_not_found (insn);\n");
#endif
@@ -5182,9 +5220,9 @@ write_toplevel_expr (p)
static void
write_unit_name (prefix, num, suffix)
- char *prefix;
+ const char *prefix;
int num;
- char *suffix;
+ const char *suffix;
{
struct function_unit *unit;
@@ -5220,7 +5258,7 @@ write_attr_valueq (attr, s)
else
{
int i;
- char *sep = " /* units: ";
+ const char *sep = " /* units: ";
for (i = 0, num = ~num; num; i++, num >>= 1)
if (num & 1)
{
@@ -5250,10 +5288,53 @@ write_attr_value (attr, value)
struct attr_desc *attr;
rtx value;
{
- if (GET_CODE (value) != CONST_STRING)
- abort ();
+ int op;
- write_attr_valueq (attr, XSTR (value, 0));
+ switch (GET_CODE (value))
+ {
+ case CONST_STRING:
+ write_attr_valueq (attr, XSTR (value, 0));
+ break;
+
+ case SYMBOL_REF:
+ fputs (XSTR (value, 0), stdout);
+ break;
+
+ case ATTR:
+ {
+ struct attr_desc *attr2 = find_attr (XSTR (value, 0), 0);
+ printf ("get_attr_%s (%s)", attr2->name,
+ (attr2->is_const ? "" : "insn"));
+ }
+ break;
+
+ case PLUS:
+ op = '+';
+ goto do_operator;
+ case MINUS:
+ op = '-';
+ goto do_operator;
+ case MULT:
+ op = '*';
+ goto do_operator;
+ case DIV:
+ op = '/';
+ goto do_operator;
+ case MOD:
+ op = '%';
+ goto do_operator;
+
+ do_operator:
+ write_attr_value (attr, XEXP (value, 0));
+ putchar (' ');
+ putchar (op);
+ putchar (' ');
+ write_attr_value (attr, XEXP (value, 1));
+ break;
+
+ default:
+ abort ();
+ }
}
static void
@@ -5292,7 +5373,7 @@ write_indent (indent)
static void
write_eligible_delay (kind)
- char *kind;
+ const char *kind;
{
struct delay_desc *delay;
int max_slots;
@@ -5481,7 +5562,7 @@ write_function_unit_info ()
static void
write_complex_function (unit, name, connection)
struct function_unit *unit;
- char *name, *connection;
+ const char *name, *connection;
{
struct attr_desc *case_attr, *attr;
struct attr_value *av, *common_av;
@@ -5622,7 +5703,7 @@ next_comma_elt (pstr)
static struct attr_desc *
find_attr (name, create)
- char *name;
+ const char *name;
int create;
{
struct attr_desc *attr;
@@ -5660,7 +5741,7 @@ find_attr (name, create)
static void
make_internal_attr (name, value, special)
- char *name;
+ const char *name;
rtx value;
int special;
{
@@ -5758,22 +5839,26 @@ extend_range (range, min, max)
if (range->max < max) range->max = max;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
@@ -5819,18 +5904,18 @@ copy_rtx_unchanging (orig)
#endif
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genattrtab: ");
@@ -6006,6 +6091,7 @@ from the machine description file `md'. */\n\n");
printf ("#include \"real.h\"\n");
printf ("#include \"output.h\"\n");
printf ("#include \"insn-attr.h\"\n");
+ printf ("#include \"toplev.h\"\n");
printf ("\n");
printf ("#define operands recog_operand\n\n");
diff --git a/contrib/gcc/gencheck.c b/contrib/gcc/gencheck.c
index f7548ce..80d7c4f 100644
--- a/contrib/gcc/gencheck.c
+++ b/contrib/gcc/gencheck.c
@@ -23,8 +23,9 @@ Boston, MA 02111-1307, USA. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) STRINGIFY(SYM),
-char *tree_codes[] = {
+const char *tree_codes[] = {
#include "tree.def"
+#include "gencheck.h"
(char*)0
};
@@ -35,7 +36,7 @@ void usage ()
int main (argc, argv)
int argc;
- char *argv[];
+ char *argv[] ATTRIBUTE_UNUSED;
{
int i;
@@ -61,22 +62,23 @@ int main (argc, argv)
return 0;
}
-#if defined(USE_C_ALLOCA) && !defined(__GNUC__)
+#if defined(USE_C_ALLOCA)
/* FIXME: We only need an xmalloc definition because we are forced to
link with alloca.o on some platforms. This should go away if/when
we link against libiberty.a. (ghazi@caip.rutgers.edu 6/3/98) */
-char *
+PTR
xmalloc (nbytes)
- int nbytes;
+ size_t nbytes;
{
- char *tmp = (char *) malloc (nbytes);
+ register PTR tmp = (PTR) malloc (nbytes);
if (!tmp)
{
- fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", nbytes);
+ fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n",
+ nbytes);
exit (FATAL_EXIT_CODE);
}
return tmp;
}
-#endif /* USE_C_ALLOCA && !__GNUC__ */
+#endif /* USE_C_ALLOCA */
diff --git a/contrib/gcc/gencodes.c b/contrib/gcc/gencodes.c
index a3aa1fe..2658216 100644
--- a/contrib/gcc/gencodes.c
+++ b/contrib/gcc/gencodes.c
@@ -2,7 +2,7 @@
- some macros CODE_FOR_... giving the insn_code_number value
for each of the defined standard insn names.
- Copyright (C) 1987, 1991, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991, 1995, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -23,11 +23,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -38,9 +33,9 @@ struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
/* Define this so we can link with print-rtl.o to get debug_rtx function. */
char **insn_name_ptr = 0;
@@ -61,40 +56,44 @@ gen_insn (insn)
insn_code_number);
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "gencodes: ");
diff --git a/contrib/gcc/genconfig.c b/contrib/gcc/genconfig.c
index b01a24b..9f79e58 100644
--- a/contrib/gcc/genconfig.c
+++ b/contrib/gcc/genconfig.c
@@ -1,6 +1,6 @@
/* Generate from machine description:
- some #define configuration flags.
- Copyright (C) 1987, 1991, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,11 +21,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -54,9 +49,9 @@ static int max_insns_per_split = 1;
static int clobbers_seen_this_insn;
static int dup_operands_seen_this_insn;
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
static void walk_insn_part PROTO((rtx, int, int));
static void gen_insn PROTO((rtx));
@@ -249,11 +244,11 @@ gen_peephole (peep)
walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
@@ -261,29 +256,33 @@ xmalloc (size)
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genconfig: ");
diff --git a/contrib/gcc/genemit.c b/contrib/gcc/genemit.c
index e4341b8..c7daa1d 100644
--- a/contrib/gcc/genemit.c
+++ b/contrib/gcc/genemit.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to emit insns as rtl.
- Copyright (C) 1987, 88, 91, 94, 95, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 94, 95, 97, 98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,11 +20,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -35,9 +30,9 @@ struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
/* Define this so we can link with print-rtl.o to get debug_rtx function. */
char **insn_name_ptr = 0;
@@ -683,11 +678,11 @@ output_init_mov_optab ()
#endif
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
@@ -695,29 +690,33 @@ xmalloc (size)
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genemit: ");
@@ -775,15 +774,15 @@ from the machine description file `md'. */\n\n");
printf ("#include \"real.h\"\n");
printf ("#include \"flags.h\"\n");
printf ("#include \"output.h\"\n");
- printf ("#include \"insn-config.h\"\n\n");
- printf ("#include \"insn-flags.h\"\n\n");
- printf ("#include \"insn-codes.h\"\n\n");
- printf ("#include \"reload.h\"\n");
- printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n");
+ printf ("#include \"insn-config.h\"\n");
+ printf ("#include \"insn-flags.h\"\n");
+ printf ("#include \"insn-codes.h\"\n");
+ printf ("#include \"recog.h\"\n");
+ printf ("#include \"reload.h\"\n\n");
printf ("extern rtx recog_operand[];\n");
printf ("#define operands emit_operand\n\n");
- printf ("#define FAIL do {end_sequence (); return _val;} while (0)\n");
- printf ("#define DONE do {_val = gen_sequence (); end_sequence (); return _val;} while (0)\n");
+ printf ("#define FAIL return (end_sequence (), _val)\n");
+ printf ("#define DONE return (_val = gen_sequence (), end_sequence (), _val)\n");
/* Read the machine description. */
diff --git a/contrib/gcc/genextract.c b/contrib/gcc/genextract.c
index c06a74c..24d3d51 100644
--- a/contrib/gcc/genextract.c
+++ b/contrib/gcc/genextract.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to extract operands from insn as rtl.
- Copyright (C) 1987, 91, 92, 93, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91-93, 97-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,11 +20,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -101,14 +96,11 @@ static int dupnums[MAX_DUP_OPERANDS];
static struct code_ptr *peepholes;
static void gen_insn PROTO ((rtx));
-static void walk_rtx PROTO ((rtx, char *));
+static void walk_rtx PROTO ((rtx, const char *));
static void print_path PROTO ((char *));
-char *xmalloc PROTO ((unsigned));
-char *xrealloc PROTO ((char *, unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-static char *copystr PROTO ((char *));
-static void mybzero ();
-void fancy_abort PROTO ((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO ((void)) ATTRIBUTE_NORETURN;
static void
gen_insn (insn)
@@ -122,7 +114,7 @@ gen_insn (insn)
dup_count = 0;
/* No operands seen so far in this pattern. */
- mybzero (oplocs, sizeof oplocs);
+ memset (oplocs, 0, sizeof oplocs);
/* Walk the insn's pattern, remembering at all times the path
down to the walking point. */
@@ -193,7 +185,7 @@ gen_insn (insn)
static void
walk_rtx (x, path)
rtx x;
- char *path;
+ const char *path;
{
register RTX_CODE code;
register int i;
@@ -217,19 +209,19 @@ walk_rtx (x, path)
case MATCH_OPERAND:
case MATCH_SCRATCH:
- oplocs[XINT (x, 0)] = copystr (path);
+ oplocs[XINT (x, 0)] = xstrdup (path);
op_count = MAX (op_count, XINT (x, 0) + 1);
break;
case MATCH_DUP:
case MATCH_PAR_DUP:
- duplocs[dup_count] = copystr (path);
+ duplocs[dup_count] = xstrdup (path);
dupnums[dup_count] = XINT (x, 0);
dup_count++;
break;
case MATCH_OP_DUP:
- duplocs[dup_count] = copystr (path);
+ duplocs[dup_count] = xstrdup (path);
dupnums[dup_count] = XINT (x, 0);
dup_count++;
@@ -245,7 +237,7 @@ walk_rtx (x, path)
return;
case MATCH_OPERATOR:
- oplocs[XINT (x, 0)] = copystr (path);
+ oplocs[XINT (x, 0)] = xstrdup (path);
op_count = MAX (op_count, XINT (x, 0) + 1);
newpath = (char *) alloca (depth + 2);
@@ -260,7 +252,7 @@ walk_rtx (x, path)
return;
case MATCH_PARALLEL:
- oplocs[XINT (x, 0)] = copystr (path);
+ oplocs[XINT (x, 0)] = xstrdup (path);
op_count = MAX (op_count, XINT (x, 0) + 1);
newpath = (char *) alloca (depth + 2);
@@ -352,40 +344,44 @@ print_path (path)
}
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genextract: ");
@@ -404,28 +400,14 @@ fancy_abort ()
fatal ("Internal gcc abort.");
}
-static char *
-copystr (s1)
- char *s1;
-{
- register char *tem;
-
- if (s1 == 0)
- return 0;
-
- tem = (char *) xmalloc (strlen (s1) + 1);
- strcpy (tem, s1);
-
- return tem;
-}
-
-static void
-mybzero (b, length)
- register char *b;
- register unsigned length;
+char *
+xstrdup (input)
+ const char *input;
{
- while (length-- > 0)
- *b++ = 0;
+ register size_t len = strlen (input) + 1;
+ register char *output = xmalloc (len);
+ memcpy (output, input, len);
+ return output;
}
int
@@ -463,17 +445,15 @@ from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
printf ("#include \"system.h\"\n");
- printf ("#include \"rtl.h\"\n\n");
+ printf ("#include \"rtl.h\"\n");
+ printf ("#include \"insn-config.h\"\n");
+ printf ("#include \"recog.h\"\n");
+ printf ("#include \"toplev.h\"\n\n");
/* This variable exists only so it can be the "location"
of any missing operand whose numbers are skipped by a given pattern. */
printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
- printf ("extern rtx recog_operand[];\n");
- printf ("extern rtx *recog_operand_loc[];\n");
- printf ("extern rtx *recog_dup_loc[];\n");
- printf ("extern char recog_dup_num[];\n");
-
printf ("void\ninsn_extract (insn)\n");
printf (" rtx insn;\n");
printf ("{\n");
@@ -481,6 +461,8 @@ from the machine description file `md'. */\n\n");
printf (" register rtx **ro_loc = recog_operand_loc;\n");
printf (" rtx pat = PATTERN (insn);\n");
printf (" int i ATTRIBUTE_UNUSED;\n\n");
+ printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
+ printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n");
printf (" switch (INSN_CODE (insn))\n");
printf (" {\n");
printf (" case -1:\n");
diff --git a/contrib/gcc/genflags.c b/contrib/gcc/genflags.c
index d389a73..636aafe 100644
--- a/contrib/gcc/genflags.c
+++ b/contrib/gcc/genflags.c
@@ -2,7 +2,7 @@
- some flags HAVE_... saying which simple standard instructions are
available for this machine.
- Copyright (C) 1987, 1991, 1995, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991, 1995, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -23,11 +23,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -38,9 +33,9 @@ struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
/* Names for patterns. Need to allow linking with print-rtl. */
char **insn_name_ptr;
@@ -180,11 +175,11 @@ gen_insn (insn)
obstack_grow (obstack_ptr, &insn, sizeof (rtx));
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
@@ -192,29 +187,33 @@ xmalloc (size)
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genflags: ");
diff --git a/contrib/gcc/gengenrtl.c b/contrib/gcc/gengenrtl.c
index ade07ff..bf98a71 100644
--- a/contrib/gcc/gengenrtl.c
+++ b/contrib/gcc/gengenrtl.c
@@ -1,5 +1,5 @@
/* Generate code to allocate RTL structures.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,10 +21,7 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
#include "system.h"
-
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
+#undef abort
#define NO_GENRTL_H
#include "rtl.h"
@@ -56,6 +53,8 @@ static void genlegend PROTO((FILE *));
static void genheader PROTO((FILE *));
static void gencode PROTO((FILE *));
+/* Decode a format letter into a C type string. */
+
static const char *
type_from_format (c)
int c;
@@ -88,6 +87,8 @@ type_from_format (c)
}
}
+/* Decode a format letter into the proper accessor function. */
+
static const char *
accessor_from_format (c)
int c;
@@ -114,6 +115,8 @@ accessor_from_format (c)
}
}
+/* Return true if a format character doesn't need normal processing. */
+
static int
special_format (fmt)
const char *fmt;
@@ -124,15 +127,20 @@ special_format (fmt)
|| strchr (fmt, 'n') != 0);
}
+/* Return true if an rtx requires special processing. */
+
static int
special_rtx (idx)
int idx;
{
return (strcmp (defs[idx].enumname, "CONST_INT") == 0
+ || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
|| strcmp (defs[idx].enumname, "REG") == 0
|| strcmp (defs[idx].enumname, "MEM") == 0);
}
+/* Fill `formats' with all unique format strings. */
+
static void
find_formats ()
{
@@ -146,7 +154,7 @@ find_formats ()
continue;
for (f = formats; *f ; ++f)
- if (!strcmp(*f, defs[i].format))
+ if (! strcmp (*f, defs[i].format))
break;
if (!*f)
@@ -154,6 +162,8 @@ find_formats ()
}
}
+/* Emit a prototype for the rtx generator for a format. */
+
static void
gendecl (f, format)
FILE *f;
@@ -170,6 +180,8 @@ gendecl (f, format)
fprintf (f, "));\n");
}
+/* Emit a define mapping an rtx code to the generator for its format. */
+
static void
genmacro (f, idx)
FILE *f;
@@ -193,6 +205,8 @@ genmacro (f, idx)
fprintf (f, ")\n");
}
+/* Emit the implementation for the rtx generator for a format. */
+
static void
gendef (f, format)
FILE *f;
@@ -229,14 +243,18 @@ gendef (f, format)
fprintf (f, "\n return rt;\n}\n\n");
}
+/* Emit the `do not edit' banner. */
+
static void
genlegend (f)
FILE *f;
{
- fprintf (f, "/* Generated automaticaly by the program `gengenrtl'\n");
- fprintf (f, " from the RTL description file `rtl.def' */\n\n");
+ fputs ("/* Generated automaticaly by the program `gengenrtl'\n", f);
+ fputs (" from the RTL description file `rtl.def' */\n\n", f);
}
+/* Emit "genrtl.h". */
+
static void
genheader (f)
FILE *f;
@@ -247,7 +265,7 @@ genheader (f)
for (fmt = formats; *fmt; ++fmt)
gendecl (f, *fmt);
- fprintf(f, "\n");
+ fprintf (f, "\n");
for (i = 0; i < NUM_RTX_CODE; i++)
{
@@ -257,6 +275,8 @@ genheader (f)
}
}
+/* Emit "genrtl.c". */
+
static void
gencode (f)
FILE *f;
@@ -272,34 +292,30 @@ gencode (f)
fputs ("static rtx obstack_alloc_rtx (length)\n", f);
fputs (" register int length;\n{\n", f);
fputs (" rtx rt = (rtx) obstack_alloc (rtl_obstack, length);\n\n", f);
- fputs (" if (sizeof(struct rtx_def) - sizeof(rtunion) == sizeof(int))\n", f);
- fputs (" *(int *)rt = 0;\n", f);
- fputs (" else if (sizeof(struct rtx_def) - sizeof(rtunion) == sizeof(HOST_WIDE_INT))\n", f);
- fputs (" *(HOST_WIDE_INT *)rt = 0;\n", f);
- fputs (" else\n", f);
- fputs (" bzero((char *) rt, sizeof(struct rtx_def) - sizeof(rtunion));\n\n", f);
+ fputs (" memset(rt, 0, sizeof(struct rtx_def) - sizeof(rtunion));\n\n", f);
fputs (" return rt;\n}\n\n", f);
for (fmt = formats; *fmt; ++fmt)
gendef (f, *fmt);
}
-#if defined(USE_C_ALLOCA) && !defined(__GNUC__)
-char *
+#if defined(USE_C_ALLOCA)
+PTR
xmalloc (nbytes)
- int nbytes;
+ size_t nbytes;
{
- char *tmp = (char *) malloc (nbytes);
+ register PTR tmp = (PTR) malloc (nbytes);
if (!tmp)
{
- fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n", nbytes);
+ fprintf (stderr, "can't allocate %d bytes (out of virtual memory)\n",
+ nbytes);
exit (FATAL_EXIT_CODE);
}
return tmp;
}
-#endif /* USE_C_ALLOCA && !__GNUC__ */
+#endif /* USE_C_ALLOCA */
int
main(argc, argv)
@@ -316,22 +332,22 @@ main(argc, argv)
f = fopen (argv[1], "w");
if (f == NULL)
{
- perror(argv[1]);
+ perror (argv[1]);
exit (1);
}
genlegend (f);
genheader (f);
- fclose(f);
+ fclose (f);
f = fopen (argv[2], "w");
if (f == NULL)
{
- perror(argv[2]);
+ perror (argv[2]);
exit (1);
}
genlegend (f);
gencode (f);
- fclose(f);
+ fclose (f);
exit (0);
}
diff --git a/contrib/gcc/genopinit.c b/contrib/gcc/genopinit.c
index a31a444..2cd67b3 100644
--- a/contrib/gcc/genopinit.c
+++ b/contrib/gcc/genopinit.c
@@ -1,5 +1,5 @@
/* Generate code to initialize optabs from machine description.
- Copyright (C) 1993, 94-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,11 +20,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -35,9 +30,9 @@ struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
/* Many parts of GCC use arrays that are indexed by machine mode and
contain the insn codes for pattern in the MD file that perform a given
@@ -68,7 +63,7 @@ void fancy_abort PROTO((void));
/* The reason we use \% is to avoid sequences of the form %-capletter-%
which SCCS treats as magic. This gets warnings which you should ignore. */
-char *optabs[] =
+const char *optabs[] =
{ "extendtab[(int) %B][(int) %A][0] = CODE_FOR_%(extend%a\%b2%)",
"extendtab[(int) %B][(int) %A][1] = CODE_FOR_%(zero_extend%a\%b2%)",
"fixtab[(int) %A][(int) %B][0] = CODE_FOR_%(fix%F\%a%I\%b2%)",
@@ -139,7 +134,7 @@ gen_insn (insn)
int m1, m2, op;
size_t pindex;
int i;
- char *np, *pp, *p, *q;
+ const char *np, *pp, *p, *q;
/* Don't mention instructions whose names are the null string.
They are in the machine description just to be recognized. */
@@ -206,7 +201,7 @@ gen_insn (insn)
for (i = ((int) MAX_MACHINE_MODE) - 1; i >= 0; i--)
{
for (p = mode_name[i], q = np; *p; p++, q++)
- if (tolower (*p) != *q)
+ if (tolower ((unsigned char)*p) != *q)
break;
if (*p == 0
@@ -260,11 +255,11 @@ gen_insn (insn)
break;
case 'a':
for (np = mode_name[m1]; *np; np++)
- printf ("%c", tolower (*np));
+ printf ("%c", tolower ((unsigned char)*np));
break;
case 'b':
for (np = mode_name[m2]; *np; np++)
- printf ("%c", tolower (*np));
+ printf ("%c", tolower ((unsigned char)*np));
break;
case 'A':
printf ("%smode", mode_name[m1]);
@@ -277,7 +272,7 @@ gen_insn (insn)
break;
case 'C':
for (np = rtx_name[op]; *np; np++)
- printf ("%c", toupper (*np));
+ printf ("%c", toupper ((unsigned char)*np));
break;
}
}
@@ -285,11 +280,11 @@ gen_insn (insn)
printf (";\n");
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
@@ -297,29 +292,33 @@ xmalloc (size)
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genopinit: ");
diff --git a/contrib/gcc/genoutput.c b/contrib/gcc/genoutput.c
index 9f40c85..2956ec6 100644
--- a/contrib/gcc/genoutput.c
+++ b/contrib/gcc/genoutput.c
@@ -1,5 +1,5 @@
/* Generate code from to output assembler insns as recognized from rtl.
- Copyright (C) 1987, 88, 92, 94, 95, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 94-95, 97-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -91,11 +91,6 @@ It would not make an case in output_insn_hairy because the template
given in the entry is a constant (it does not start with `*'). */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -112,12 +107,10 @@ struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
-static void error PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-static void mybcopy ();
-static void mybzero ();
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
+static void error PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1;
static int n_occurrences PROTO((int, char *));
/* Define this so we can link with print-rtl.o to get debug_rtx function. */
@@ -177,6 +170,7 @@ int have_constraints;
static int have_error;
+static char * name_for_index PROTO((int));
static void output_prologue PROTO((void));
static void output_epilogue PROTO((void));
static void scan_operands PROTO((rtx, int, int));
@@ -188,6 +182,29 @@ static void gen_expand PROTO((rtx));
static void gen_split PROTO((rtx));
static int n_occurrences PROTO((int, char *));
+static char *
+name_for_index (index)
+ int index;
+{
+ static char buf[100];
+
+ struct data *i, *last_named = NULL;
+ for (i = insn_data; i ; i = i->next)
+ {
+ if (i->index_number == index)
+ return i->name;
+ if (i->name)
+ last_named = i;
+ }
+
+ if (last_named)
+ sprintf(buf, "%s+%d", last_named->name, index - last_named->index_number);
+ else
+ sprintf(buf, "insn %d", index);
+
+ return buf;
+}
+
static void
output_prologue ()
{
@@ -216,7 +233,7 @@ output_epilogue ()
{
register struct data *d;
- printf ("\nchar * const insn_template[] =\n {\n");
+ printf ("\nconst char * const insn_template[] =\n {\n");
for (d = insn_data; d; d = d->next)
{
if (d->template)
@@ -226,7 +243,7 @@ output_epilogue ()
}
printf (" };\n");
- printf ("\nchar *(*const insn_outfun[])() =\n {\n");
+ printf ("\nconst char *(*const insn_outfun[])() =\n {\n");
for (d = insn_data; d; d = d->next)
{
if (d->outfun)
@@ -246,7 +263,7 @@ output_epilogue ()
}
printf (" };\n");
- printf ("\nchar *insn_name[] =\n {\n");
+ printf ("\nconst char *insn_name[] =\n {\n");
{
int offset = 0;
int next;
@@ -287,7 +304,7 @@ output_epilogue ()
}
}
printf (" };\n");
- printf ("char **insn_name_ptr = insn_name;\n");
+ printf ("const char **insn_name_ptr = insn_name;\n");
printf ("\nconst int insn_n_operands[] =\n {\n");
for (d = insn_data; d; d = d->next)
@@ -301,7 +318,7 @@ output_epilogue ()
if (have_constraints)
{
- printf ("\nchar *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n");
+ printf ("\nconst char *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n");
for (d = insn_data; d; d = d->next)
{
register int i;
@@ -420,7 +437,7 @@ static int max_opno;
static int num_dups;
static char *constraints[MAX_MAX_OPERANDS];
static int op_n_alternatives[MAX_MAX_OPERANDS];
-static char *predicates[MAX_MAX_OPERANDS];
+static const char *predicates[MAX_MAX_OPERANDS];
static char address_p[MAX_MAX_OPERANDS];
static enum machine_mode modes[MAX_MAX_OPERANDS];
static char strict_low[MAX_MAX_OPERANDS];
@@ -447,13 +464,13 @@ scan_operands (part, this_address_p, this_strict_low)
max_opno = opno;
if (max_opno >= MAX_MAX_OPERANDS)
{
- error ("Too many operands (%d) in definition %d.\n",
- max_opno + 1, next_index_number);
+ error ("Too many operands (%d) in definition %s.\n",
+ max_opno + 1, name_for_index (next_index_number));
return;
}
if (seen[opno])
- error ("Definition %d specified operand number %d more than once.\n",
- next_index_number, opno);
+ error ("Definition %s specified operand number %d more than once.\n",
+ name_for_index (next_index_number), opno);
seen[opno] = 1;
modes[opno] = GET_MODE (part);
strict_low[opno] = this_strict_low;
@@ -473,13 +490,13 @@ scan_operands (part, this_address_p, this_strict_low)
max_opno = opno;
if (max_opno >= MAX_MAX_OPERANDS)
{
- error ("Too many operands (%d) in definition %d.\n",
- max_opno + 1, next_index_number);
+ error ("Too many operands (%d) in definition %s.\n",
+ max_opno + 1, name_for_index (next_index_number));
return;
}
if (seen[opno])
- error ("Definition %d specified operand number %d more than once.\n",
- next_index_number, opno);
+ error ("Definition %s specified operand number %d more than once.\n",
+ name_for_index (next_index_number), opno);
seen[opno] = 1;
modes[opno] = GET_MODE (part);
strict_low[opno] = 0;
@@ -500,13 +517,13 @@ scan_operands (part, this_address_p, this_strict_low)
max_opno = opno;
if (max_opno >= MAX_MAX_OPERANDS)
{
- error ("Too many operands (%d) in definition %d.\n",
- max_opno + 1, next_index_number);
+ error ("Too many operands (%d) in definition %s.\n",
+ max_opno + 1, name_for_index (next_index_number));
return;
}
if (seen[opno])
- error ("Definition %d specified operand number %d more than once.\n",
- next_index_number, opno);
+ error ("Definition %s specified operand number %d more than once.\n",
+ name_for_index (next_index_number), opno);
seen[opno] = 1;
modes[opno] = GET_MODE (part);
strict_low[opno] = 0;
@@ -578,7 +595,7 @@ process_template (d, template)
d->template = 0;
d->outfun = 1;
- printf ("\nstatic char *\n");
+ printf ("\nstatic const char *\n");
printf ("output_%d (operands, insn)\n", d->code_number);
printf (" rtx *operands ATTRIBUTE_UNUSED;\n");
printf (" rtx insn ATTRIBUTE_UNUSED;\n");
@@ -591,7 +608,7 @@ process_template (d, template)
if (template[0] == '@')
{
- printf (" static /*const*/ char *const strings_%d[] = {\n",
+ printf (" static const char *const strings_%d[] = {\n",
d->code_number);
for (i = 0, cp = &template[1]; *cp; )
@@ -651,8 +668,8 @@ validate_insn_alternatives (d)
if (n == 0)
n = d->op_n_alternatives[start];
else if (n != d->op_n_alternatives[start])
- error ("wrong number of alternatives in operand %d of insn number %d",
- start, d->index_number);
+ error ("wrong number of alternatives in operand %d of insn %s",
+ start, name_for_index (d->index_number));
}
/* Record the insn's overall number of alternatives. */
d->n_alternatives = n;
@@ -689,13 +706,13 @@ gen_insn (insn)
max_opno = -1;
num_dups = 0;
- mybzero (constraints, sizeof constraints);
- mybzero (op_n_alternatives, sizeof op_n_alternatives);
- mybzero (predicates, sizeof predicates);
- mybzero (address_p, sizeof address_p);
- mybzero (modes, sizeof modes);
- mybzero (strict_low, sizeof strict_low);
- mybzero (seen, sizeof seen);
+ memset (constraints, 0, sizeof constraints);
+ memset (op_n_alternatives, 0, sizeof op_n_alternatives);
+ memset (predicates, 0, sizeof predicates);
+ memset (address_p, 0, sizeof address_p);
+ memset (modes, 0, sizeof modes);
+ memset (strict_low, 0, sizeof strict_low);
+ memset (seen, 0, sizeof seen);
for (i = 0; i < XVECLEN (insn, 1); i++)
scan_operands (XVECEXP (insn, 1, i), 0, 0);
@@ -703,12 +720,12 @@ gen_insn (insn)
d->n_operands = max_opno + 1;
d->n_dups = num_dups;
- mybcopy (constraints, d->constraints, sizeof constraints);
- mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
- mybcopy (predicates, d->predicates, sizeof predicates);
- mybcopy (address_p, d->address_p, sizeof address_p);
- mybcopy (modes, d->modes, sizeof modes);
- mybcopy (strict_low, d->strict_low, sizeof strict_low);
+ memcpy (d->constraints, constraints, sizeof constraints);
+ memcpy (d->op_n_alternatives, op_n_alternatives, sizeof op_n_alternatives);
+ memcpy (d->predicates, predicates, sizeof predicates);
+ memcpy (d->address_p, address_p, sizeof address_p);
+ memcpy (d->modes, modes, sizeof modes);
+ memcpy (d->strict_low, strict_low, sizeof strict_low);
validate_insn_alternatives (d);
process_template (d, XSTR (insn, 3));
@@ -740,13 +757,13 @@ gen_peephole (peep)
end_of_insn_data = d;
max_opno = -1;
- mybzero (constraints, sizeof constraints);
- mybzero (op_n_alternatives, sizeof op_n_alternatives);
- mybzero (predicates, sizeof predicates);
- mybzero (address_p, sizeof address_p);
- mybzero (modes, sizeof modes);
- mybzero (strict_low, sizeof strict_low);
- mybzero (seen, sizeof seen);
+ memset (constraints, 0, sizeof constraints);
+ memset (op_n_alternatives, 0, sizeof op_n_alternatives);
+ memset (predicates, 0, sizeof predicates);
+ memset (address_p, 0, sizeof address_p);
+ memset (modes, 0, sizeof modes);
+ memset (strict_low, 0, sizeof strict_low);
+ memset (seen, 0, sizeof seen);
/* Get the number of operands by scanning all the
patterns of the peephole optimizer.
@@ -757,12 +774,12 @@ gen_peephole (peep)
d->n_operands = max_opno + 1;
d->n_dups = 0;
- mybcopy (constraints, d->constraints, sizeof constraints);
- mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
- mybzero (d->predicates, sizeof predicates);
- mybzero (d->address_p, sizeof address_p);
- mybzero (d->modes, sizeof modes);
- mybzero (d->strict_low, sizeof strict_low);
+ memcpy (d->constraints, constraints, sizeof constraints);
+ memcpy (d->op_n_alternatives, op_n_alternatives, sizeof op_n_alternatives);
+ memset (d->predicates, 0, sizeof predicates);
+ memset (d->address_p, 0, sizeof address_p);
+ memset (d->modes, 0, sizeof modes);
+ memset (d->strict_low, 0, sizeof strict_low);
validate_insn_alternatives (d);
process_template (d, XSTR (peep, 2));
@@ -801,13 +818,13 @@ gen_expand (insn)
/* Scan the operands to get the specified predicates and modes,
since expand_binop needs to know them. */
- mybzero (constraints, sizeof constraints);
- mybzero (op_n_alternatives, sizeof op_n_alternatives);
- mybzero (predicates, sizeof predicates);
- mybzero (address_p, sizeof address_p);
- mybzero (modes, sizeof modes);
- mybzero (strict_low, sizeof strict_low);
- mybzero (seen, sizeof seen);
+ memset (constraints, 0, sizeof constraints);
+ memset (op_n_alternatives, 0, sizeof op_n_alternatives);
+ memset (predicates, 0, sizeof predicates);
+ memset (address_p, 0, sizeof address_p);
+ memset (modes, 0, sizeof modes);
+ memset (strict_low, 0, sizeof strict_low);
+ memset (seen, 0, sizeof seen);
if (XVEC (insn, 1))
for (i = 0; i < XVECLEN (insn, 1); i++)
@@ -816,12 +833,12 @@ gen_expand (insn)
d->n_operands = max_opno + 1;
d->n_dups = num_dups;
- mybcopy (constraints, d->constraints, sizeof constraints);
- mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives);
- mybcopy (predicates, d->predicates, sizeof predicates);
- mybcopy (address_p, d->address_p, sizeof address_p);
- mybcopy (modes, d->modes, sizeof modes);
- mybcopy (strict_low, d->strict_low, sizeof strict_low);
+ memcpy (d->constraints, constraints, sizeof constraints);
+ memcpy (d->op_n_alternatives, op_n_alternatives, sizeof op_n_alternatives);
+ memcpy (d->predicates, predicates, sizeof predicates);
+ memcpy (d->address_p, address_p, sizeof address_p);
+ memcpy (d->modes, modes, sizeof modes);
+ memcpy (d->strict_low, strict_low, sizeof strict_low);
d->template = 0;
d->outfun = 0;
@@ -856,13 +873,13 @@ gen_split (split)
max_opno = -1;
num_dups = 0;
- mybzero (constraints, sizeof constraints);
- mybzero (op_n_alternatives, sizeof op_n_alternatives);
- mybzero (predicates, sizeof predicates);
- mybzero (address_p, sizeof address_p);
- mybzero (modes, sizeof modes);
- mybzero (strict_low, sizeof strict_low);
- mybzero (seen, sizeof seen);
+ memset (constraints, 0, sizeof constraints);
+ memset (op_n_alternatives, 0, sizeof op_n_alternatives);
+ memset (predicates, 0, sizeof predicates);
+ memset (address_p, 0, sizeof address_p);
+ memset (modes, 0, sizeof modes);
+ memset (strict_low, 0, sizeof strict_low);
+ memset (seen, 0, sizeof seen);
/* Get the number of operands by scanning all the
patterns of the split patterns.
@@ -872,12 +889,12 @@ gen_split (split)
d->n_operands = max_opno + 1;
- mybzero (d->constraints, sizeof constraints);
- mybzero (d->op_n_alternatives, sizeof op_n_alternatives);
- mybzero (d->predicates, sizeof predicates);
- mybzero (d->address_p, sizeof address_p);
- mybzero (d->modes, sizeof modes);
- mybzero (d->strict_low, sizeof strict_low);
+ memset (d->constraints, 0, sizeof constraints);
+ memset (d->op_n_alternatives, 0, sizeof op_n_alternatives);
+ memset (d->predicates, 0, sizeof predicates);
+ memset (d->address_p, 0, sizeof address_p);
+ memset (d->modes, 0, sizeof modes);
+ memset (d->strict_low, 0, sizeof strict_low);
d->n_dups = 0;
d->n_alternatives = 0;
@@ -885,59 +902,44 @@ gen_split (split)
d->outfun = 0;
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-mybzero (b, length)
- register char *b;
- register unsigned length;
-{
- while (length-- > 0)
- *b++ = 0;
-}
-
-static void
-mybcopy (b1, b2, length)
- register char *b1;
- register char *b2;
- register unsigned length;
-{
- while (length-- > 0)
- *b2++ = *b1++;
-}
-
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genoutput: ");
@@ -957,17 +959,17 @@ fancy_abort ()
}
static void
-error VPROTO ((char *format, ...))
+error VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genoutput: ");
diff --git a/contrib/gcc/genpeep.c b/contrib/gcc/genpeep.c
index ab65df7..65ba963 100644
--- a/contrib/gcc/genpeep.c
+++ b/contrib/gcc/genpeep.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to perform peephole optimizations.
- Copyright (C) 1987, 1989, 1992, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92, 97, 98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,11 +20,6 @@ Boston, MA 02111-1307, USA. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
@@ -51,9 +46,9 @@ struct link
int vecelt;
};
-char *xmalloc PROTO((unsigned));
-static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
-void fancy_abort PROTO((void));
+void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
static int max_opno;
@@ -389,40 +384,44 @@ print_code (code)
}
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
return val;
}
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genpeep: ");
@@ -471,10 +470,12 @@ from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
printf ("#include \"system.h\"\n");
+ printf ("#include \"insn-config.h\"\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"regs.h\"\n");
printf ("#include \"output.h\"\n");
printf ("#include \"real.h\"\n");
+ printf ("#include \"recog.h\"\n");
printf ("#include \"except.h\"\n\n");
printf ("extern rtx peep_operand[];\n\n");
diff --git a/contrib/gcc/genrecog.c b/contrib/gcc/genrecog.c
index a4b14e3..546f922 100644
--- a/contrib/gcc/genrecog.c
+++ b/contrib/gcc/genrecog.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to recognize rtl as insns.
- Copyright (C) 1987, 88, 92, 93, 94, 95, 97, 98 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-95, 97-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -47,23 +47,22 @@ Boston, MA 02111-1307, USA. */
it returns the split rtl in a SEQUENCE. */
#include "hconfig.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "obstack.h"
+#define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
+ printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
+
static struct obstack obstack;
struct obstack *rtl_obstack = &obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-/* Define this so we can link with print-rtl.o to get debug_rtx function. */
+/* Holds an array of names indexed by insn_code_number. */
char **insn_name_ptr = 0;
+int insn_name_ptr_size = 0;
/* Data structure for a listhead of decision trees. The alternatives
to a node are kept in a doublely-linked list so we can easily add nodes
@@ -91,7 +90,7 @@ struct decision
int elt_one_int; /* Required value for XINT (rtl, 1) */
int test_elt_zero_wide; /* Nonzero if should test XWINT (rtl, 0) */
HOST_WIDE_INT elt_zero_wide; /* Required value for XWINT (rtl, 0) */
- char *tests; /* If nonzero predicate to call */
+ const char *tests; /* If nonzero predicate to call */
int pred; /* `preds' index of predicate or -1 */
char *c_test; /* Additional test to perform */
struct decision_head success; /* Nodes to test on success */
@@ -142,7 +141,7 @@ static int max_depth;
static struct pred_table
{
- char *name;
+ const char *name;
RTX_CODE codes[NUM_RTX_CODE];
} preds[]
= {{"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
@@ -162,6 +161,7 @@ static struct pred_table
{"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
LABEL_REF, SUBREG, REG}},
{"push_operand", {MEM}},
+ {"pop_operand", {MEM}},
{"memory_operand", {SUBREG, MEM}},
{"indirect_operand", {SUBREG, MEM}},
{"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU}},
@@ -172,7 +172,7 @@ static struct pred_table
static struct decision_head make_insn_sequence PROTO((rtx, enum routine_type));
static struct decision *add_to_sequence PROTO((rtx, struct decision_head *,
- char *));
+ const char *));
static int not_both_true PROTO((struct decision *, struct decision *,
int));
static int position_merit PROTO((struct decision *, enum machine_mode,
@@ -182,24 +182,20 @@ static struct decision_head merge_trees PROTO((struct decision_head,
static int break_out_subroutines PROTO((struct decision_head,
enum routine_type, int));
static void write_subroutine PROTO((struct decision *, enum routine_type));
-static void write_tree_1 PROTO((struct decision *, char *,
+static void write_tree_1 PROTO((struct decision *, const char *,
struct decision *, enum routine_type));
static void print_code PROTO((enum rtx_code));
static int same_codes PROTO((struct decision *, enum rtx_code));
static void clear_codes PROTO((struct decision *));
static int same_modes PROTO((struct decision *, enum machine_mode));
static void clear_modes PROTO((struct decision *));
-static void write_tree PROTO((struct decision *, char *,
+static void write_tree PROTO((struct decision *, const char *,
struct decision *, int,
enum routine_type));
-static void change_state PROTO((char *, char *, int));
-static char *copystr PROTO((char *));
-static void mybzero PROTO((char *, unsigned));
-static void mybcopy PROTO((char *, char *, unsigned));
-static void fatal PVPROTO((char *, ...)) ATTRIBUTE_PRINTF_1;
-char *xrealloc PROTO((char *, unsigned));
-char *xmalloc PROTO((unsigned));
-void fancy_abort PROTO((void));
+static void change_state PROTO((const char *, const char *, int));
+void fatal PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
/* Construct and return a sequence of decisions
that will recognize INSN.
@@ -216,6 +212,38 @@ make_insn_sequence (insn, type)
struct decision *last;
struct decision_head head;
+ {
+ static char *last_real_name = "insn";
+ static int last_real_code = 0;
+ char *name;
+
+ if (insn_name_ptr_size <= next_insn_code)
+ {
+ int new_size;
+ new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
+ insn_name_ptr =
+ (char **) xrealloc (insn_name_ptr, sizeof(char *) * new_size);
+ bzero ((PTR)(insn_name_ptr + insn_name_ptr_size),
+ sizeof(char *) * (new_size - insn_name_ptr_size));
+ insn_name_ptr_size = new_size;
+ }
+
+ name = XSTR (insn, 0);
+ if (!name || name[0] == '\0')
+ {
+ name = xmalloc (strlen (last_real_name) + 10);
+ sprintf (name, "%s+%d", last_real_name,
+ next_insn_code - last_real_code);
+ }
+ else
+ {
+ last_real_name = name;
+ last_real_code = next_insn_code;
+ }
+
+ insn_name_ptr[next_insn_code] = name;
+ }
+
if (XVECLEN (insn, type == RECOG) == 1)
x = XVECEXP (insn, type == RECOG, 0);
else
@@ -297,7 +325,7 @@ static struct decision *
add_to_sequence (pattern, last, position)
rtx pattern;
struct decision_head *last;
- char *position;
+ const char *position;
{
register RTX_CODE code;
register struct decision *new
@@ -313,7 +341,7 @@ add_to_sequence (pattern, last, position)
max_depth = depth;
new->number = next_number++;
- new->position = copystr (position);
+ new->position = xstrdup (position);
new->ignore_code = 0;
new->ignore_mode = 0;
new->enforce_mode = 1;
@@ -421,7 +449,7 @@ add_to_sequence (pattern, last, position)
if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
{
- for (i = 0; i < XVECLEN (pattern, 2); i++)
+ for (i = 0; i < (size_t) XVECLEN (pattern, 2); i++)
{
newpos[depth] = i + (code == MATCH_OPERATOR ? '0': 'a');
new = add_to_sequence (XVECEXP (pattern, 2, i),
@@ -436,7 +464,7 @@ add_to_sequence (pattern, last, position)
new->dupno = XINT (pattern, 0);
new->code = UNKNOWN;
new->tests = 0;
- for (i = 0; i < XVECLEN (pattern, 1); i++)
+ for (i = 0; i < (size_t) XVECLEN (pattern, 1); i++)
{
newpos[depth] = i + '0';
new = add_to_sequence (XVECEXP (pattern, 1, i),
@@ -456,6 +484,19 @@ add_to_sequence (pattern, last, position)
goto restart;
case SET:
+ /* The operands of a SET must have the same mode unless one is VOIDmode. */
+ if (GET_MODE (SET_SRC (pattern)) != VOIDmode
+ && GET_MODE (SET_DEST (pattern)) != VOIDmode
+ && GET_MODE (SET_SRC (pattern)) != GET_MODE (SET_DEST (pattern))
+ /* The mode of an ADDRESS_OPERAND is the mode of the memory reference,
+ not the mode of the address. */
+ && ! (GET_CODE (SET_SRC (pattern)) == MATCH_OPERAND
+ && ! strcmp (XSTR (SET_SRC (pattern), 1), "address_operand")))
+ {
+ print_rtl (stderr, pattern);
+ fputc ('\n', stderr);
+ fatal ("mode mismatch in SET");
+ }
newpos[depth] = '0';
new = add_to_sequence (SET_DEST (pattern), &new->success, newpos);
this->success.first->enforce_mode = 1;
@@ -520,7 +561,7 @@ add_to_sequence (pattern, last, position)
fmt = GET_RTX_FORMAT (code);
len = GET_RTX_LENGTH (code);
- for (i = 0; i < len; i++)
+ for (i = 0; i < (size_t) len; i++)
{
newpos[depth] = '0' + i;
if (fmt[i] == 'e' || fmt[i] == 'u')
@@ -823,8 +864,7 @@ merge_trees (oldh, addh)
struct decision *split
= (struct decision *) xmalloc (sizeof (struct decision));
- mybcopy ((char *) old, (char *) split,
- sizeof (struct decision));
+ memcpy (split, old, sizeof (struct decision));
old->success.first = old->success.last = split;
old->c_test = 0;
@@ -850,8 +890,7 @@ merge_trees (oldh, addh)
struct decision *split
= (struct decision *) xmalloc (sizeof (struct decision));
- mybcopy ((char *) add, (char *) split,
- sizeof (struct decision));
+ memcpy (split, add, sizeof (struct decision));
add->success.first = add->success.last = split;
add->c_test = 0;
@@ -891,7 +930,11 @@ merge_trees (oldh, addh)
old->num_clobbers_to_add = 0;
}
else
- fatal ("Two actions at one point in tree");
+ fatal ("Two actions at one point in tree for insns \"%s\" (%d) and \"%s\" (%d)",
+ insn_name_ptr[old->insn_code_number],
+ old->insn_code_number,
+ insn_name_ptr[add->insn_code_number],
+ add->insn_code_number);
}
if (old->insn_code_number == -1)
@@ -1024,7 +1067,7 @@ write_subroutine (tree, type)
conditions or switch statements. We only support small indentations
and always indent at least two spaces. */
-static char *indents[]
+static const char *indents[]
= {" ", " ", " ", " ", " ", " ", " ", " ",
"\t", "\t ", "\t ", "\t ", "\t ", "\t ", "\t ",
"\t\t", "\t\t ", "\t\t ", "\t\t ", "\t\t ", "\t\t "};
@@ -1053,7 +1096,7 @@ static char *indents[]
static void
write_tree_1 (tree, prevpos, afterward, type)
struct decision *tree;
- char *prevpos;
+ const char *prevpos;
struct decision *afterward;
enum routine_type type;
{
@@ -1096,7 +1139,7 @@ write_tree_1 (tree, prevpos, afterward, type)
printf ("\n");
if (tree && tree->subroutine_number == 0)
{
- printf (" L%d:\n", tree->number);
+ OUTPUT_LABEL (" ", tree->number);
tree->label_needed = 0;
}
@@ -1232,7 +1275,7 @@ write_tree_1 (tree, prevpos, afterward, type)
if (p->label_needed && (p->retest_mode || p->retest_code))
{
- printf ("%sL%d:\n", indents[indent - 2], p->number);
+ OUTPUT_LABEL (indents[indent - 2], p->number);
p->label_needed = 0;
}
@@ -1290,7 +1333,7 @@ write_tree_1 (tree, prevpos, afterward, type)
if (switch_mode == VOIDmode && mode != VOIDmode && p->next != 0
&& p->next->enforce_mode && p->next->mode != VOIDmode)
{
- mybzero (modemap, sizeof modemap);
+ memset (modemap, 0, sizeof modemap);
printf ("%sswitch (GET_MODE (x%d))\n", indents[indent], depth);
printf ("%s{\n", indents[indent + 2]);
indent += 4;
@@ -1307,7 +1350,7 @@ write_tree_1 (tree, prevpos, afterward, type)
if (switch_code == UNKNOWN && p->code != UNKNOWN && ! p->ignore_code
&& p->next != 0 && p->next->code != UNKNOWN)
{
- mybzero (codemap, sizeof codemap);
+ memset (codemap, 0, sizeof codemap);
printf ("%sswitch (GET_CODE (x%d))\n", indents[indent], depth);
printf ("%s{\n", indents[indent + 2]);
indent += 4;
@@ -1323,7 +1366,7 @@ write_tree_1 (tree, prevpos, afterward, type)
/* Now that most mode and code tests have been done, we can write out
a label for an inner node, if we haven't already. */
if (p->label_needed)
- printf ("%sL%d:\n", indents[indent - 2], p->number);
+ OUTPUT_LABEL (indents[indent - 2], p->number);
inner_indent = indent;
@@ -1545,18 +1588,18 @@ clear_modes (p)
static void
write_tree (tree, prevpos, afterward, initial, type)
struct decision *tree;
- char *prevpos;
+ const char *prevpos;
struct decision *afterward;
int initial;
enum routine_type type;
{
register struct decision *p;
- char *name_prefix = (type == SPLIT ? "split" : "recog");
- char *call_suffix = (type == SPLIT ? "" : ", pnum_clobbers");
+ const char *name_prefix = (type == SPLIT ? "split" : "recog");
+ const char *call_suffix = (type == SPLIT ? "" : ", pnum_clobbers");
if (! initial && tree->subroutine_number > 0)
{
- printf (" L%d:\n", tree->number);
+ OUTPUT_LABEL (" ", tree->number);
if (afterward)
{
@@ -1591,8 +1634,8 @@ write_tree (tree, prevpos, afterward, initial, type)
static void
change_state (oldpos, newpos, indent)
- char *oldpos;
- char *newpos;
+ const char *oldpos;
+ const char *newpos;
int indent;
{
int odepth = strlen (oldpos);
@@ -1618,73 +1661,54 @@ change_state (oldpos, newpos, indent)
}
}
-static char *
-copystr (s1)
- char *s1;
-{
- register char *tem;
-
- if (s1 == 0)
- return 0;
-
- tem = (char *) xmalloc (strlen (s1) + 1);
- strcpy (tem, s1);
-
- return tem;
-}
-
-static void
-mybzero (b, length)
- register char *b;
- register unsigned length;
+char *
+xstrdup (input)
+ const char *input;
{
- while (length-- > 0)
- *b++ = 0;
+ register size_t len = strlen (input) + 1;
+ register char *output = xmalloc (len);
+ memcpy (output, input, len);
+ return output;
}
-static void
-mybcopy (in, out, length)
- register char *in, *out;
- register unsigned length;
+PTR
+xrealloc (old, size)
+ PTR old;
+ size_t size;
{
- while (length-- > 0)
- *out++ = *in++;
-}
-
-char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- char *result = (char *) realloc (ptr, size);
- if (!result)
+ register PTR ptr;
+ if (old)
+ ptr = (PTR) realloc (old, size);
+ else
+ ptr = (PTR) malloc (size);
+ if (!ptr)
fatal ("virtual memory exhausted");
- return result;
+ return ptr;
}
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *val = (char *) malloc (size);
+ register PTR val = (PTR) malloc (size);
if (val == 0)
fatal ("virtual memory exhausted");
return val;
}
-static void
-fatal VPROTO ((char *format, ...))
+void
+fatal VPROTO ((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
fprintf (stderr, "genrecog: ");
@@ -1793,10 +1817,6 @@ from the machine description file `md'. */\n\n");
printf ("*/\n\n");
- printf ("rtx recog_operand[MAX_RECOG_OPERANDS];\n\n");
- printf ("rtx *recog_operand_loc[MAX_RECOG_OPERANDS];\n\n");
- printf ("rtx *recog_dup_loc[MAX_DUP_OPERANDS];\n\n");
- printf ("char recog_dup_num[MAX_DUP_OPERANDS];\n\n");
printf ("#define operands recog_operand\n\n");
next_subroutine_number = 0;
diff --git a/contrib/gcc/getpwd.c b/contrib/gcc/getpwd.c
index 947383e..c3d155e 100644
--- a/contrib/gcc/getpwd.c
+++ b/contrib/gcc/getpwd.c
@@ -2,7 +2,6 @@
#include "config.h"
#include "system.h"
-#include <sys/stat.h>
/* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
BSD systems) now provides getcwd as called for by POSIX. Allow for
@@ -20,9 +19,7 @@
#define GUESSPATHLEN 100
#endif /* (defined (USG) || defined (VMS)) */
-char *xmalloc ();
-
-#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN32__)))
+#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
/* Get the working directory. Use the PWD environment variable if it's
set correctly, since this is faster and gives more uniform answers
@@ -70,7 +67,7 @@ getpwd ()
return p;
}
-#else /* VMS || _WIN32 && !__CYGWIN32__ */
+#else /* VMS || _WIN32 && !__CYGWIN__ */
#ifndef MAXPATHLEN
#define MAXPATHLEN 255
@@ -90,4 +87,4 @@ getpwd ()
return pwd;
}
-#endif /* VMS || _WIN32 && !__CYGWIN32__ */
+#endif /* VMS || _WIN32 && !__CYGWIN__ */
diff --git a/contrib/gcc/glimits.h b/contrib/gcc/glimits.h
index 0e3228b..559e712 100644
--- a/contrib/gcc/glimits.h
+++ b/contrib/gcc/glimits.h
@@ -64,7 +64,7 @@
/* Minimum and maximum values a `signed long int' can hold.
(Same as `int'). */
#ifndef __LONG_MAX__
-#if defined (__alpha__) || (defined (__sparc_v9__) && defined (__arch64__))
+#if defined (__alpha__) || defined (__sparc_v9__) || defined (__sparcv9)
#define __LONG_MAX__ 9223372036854775807L
#else
#define __LONG_MAX__ 2147483647L
diff --git a/contrib/gcc/global.c b/contrib/gcc/global.c
index d382537..9649b6e 100644
--- a/contrib/gcc/global.c
+++ b/contrib/gcc/global.c
@@ -1,5 +1,5 @@
/* Allocate registers for pseudo-registers that span basic blocks.
- Copyright (C) 1987, 88, 91, 94, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 94, 96-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */
#include "basic-block.h"
#include "regs.h"
#include "insn-config.h"
+#include "reload.h"
#include "output.h"
#include "toplev.h"
@@ -45,8 +46,9 @@ Boston, MA 02111-1307, USA. */
reg for it. The reload pass is independent in other respects
and it is run even when stupid register allocation is in use.
- 1. count the pseudo-registers still needing allocation
- and assign allocation-numbers (allocnos) to them.
+ 1. Assign allocation-numbers (allocnos) to the pseudo-registers
+ still needing allocations and to the pseudo-registers currently
+ allocated by local-alloc which may be spilled by reload.
Set up tables reg_allocno and allocno_reg to map
reg numbers to allocnos and vice versa.
max_allocno gets the number of allocnos in use.
@@ -56,13 +58,13 @@ Boston, MA 02111-1307, USA. */
for conflicts between allocnos and explicit hard register use
(which includes use of pseudo-registers allocated by local_alloc).
- 3. for each basic block
+ 3. For each basic block
walk forward through the block, recording which
- unallocated registers and which hardware registers are live.
- Build the conflict matrix between the unallocated registers
- and another of unallocated registers versus hardware registers.
+ pseudo-registers and which hardware registers are live.
+ Build the conflict matrix between the pseudo-registers
+ and another of pseudo-registers versus hardware registers.
Also record the preferred hardware registers
- for each unallocated one.
+ for each pseudo-register.
4. Sort a table of the allocnos into order of
desirability of the variables.
@@ -70,15 +72,14 @@ Boston, MA 02111-1307, USA. */
5. Allocate the variables in that order; each if possible into
a preferred register, else into another register. */
-/* Number of pseudo-registers still requiring allocation
- (not allocated by local_allocate). */
+/* Number of pseudo-registers which are candidates for allocation. */
static int max_allocno;
/* Indexed by (pseudo) reg number, gives the allocno, or -1
- for pseudo registers already allocated by local_allocate. */
+ for pseudo registers which are not to be allocated. */
-int *reg_allocno;
+static int *reg_allocno;
/* Indexed by allocno, gives the reg number. */
@@ -260,7 +261,7 @@ static void expand_preferences PROTO((void));
static void prune_preferences PROTO((void));
static void find_reg PROTO((int, HARD_REG_SET, int, int, int));
static void record_one_conflict PROTO((int));
-static void record_conflicts PROTO((short *, int));
+static void record_conflicts PROTO((int *, int));
static void mark_reg_store PROTO((rtx, rtx));
static void mark_reg_clobber PROTO((rtx, rtx));
static void mark_reg_conflicts PROTO((rtx));
@@ -268,6 +269,9 @@ static void mark_reg_death PROTO((rtx));
static void mark_reg_live_nc PROTO((int, enum machine_mode));
static void set_preference PROTO((rtx, rtx));
static void dump_conflicts PROTO((FILE *));
+static void reg_becomes_live PROTO((rtx, rtx));
+static void reg_dies PROTO((int, enum machine_mode));
+static void build_insn_chain PROTO((rtx));
/* Perform allocation of pseudo-registers not allocated by local_alloc.
FILE is a file to output debugging information on,
@@ -359,7 +363,7 @@ global_alloc (file)
SET_HARD_REG_BIT (regs_used_so_far, i);
#endif
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
if (reg_renumber[i] >= 0)
SET_HARD_REG_BIT (regs_used_so_far, reg_renumber[i]);
@@ -385,17 +389,17 @@ global_alloc (file)
reg_may_share[r2] = r1;
}
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
/* Note that reg_live_length[i] < 0 indicates a "constant" reg
that we are supposed to refrain from putting in a hard reg.
-2 means do make an allocno but don't allocate it. */
- if (REG_N_REFS (i) != 0 && reg_renumber[i] < 0 && REG_LIVE_LENGTH (i) != -1
+ if (REG_N_REFS (i) != 0 && REG_LIVE_LENGTH (i) != -1
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
&& (! current_function_has_nonlocal_label
|| REG_N_CALLS_CROSSED (i) == 0))
{
- if (reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
+ if (reg_renumber[i] < 0 && reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
reg_allocno[i] = reg_allocno[reg_may_share[i]];
else
reg_allocno[i] = max_allocno++;
@@ -415,7 +419,7 @@ global_alloc (file)
bzero ((char *) allocno_n_refs, max_allocno * sizeof (int));
bzero ((char *) allocno_live_length, max_allocno * sizeof (int));
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
if (reg_allocno[i] >= 0)
{
int allocno = reg_allocno[i];
@@ -432,8 +436,8 @@ global_alloc (file)
override it. */
bzero ((char *) local_reg_live_length, sizeof local_reg_live_length);
bzero ((char *) local_reg_n_refs, sizeof local_reg_n_refs);
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (reg_allocno[i] < 0 && reg_renumber[i] >= 0)
+ for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
+ if (reg_renumber[i] >= 0)
{
int regno = reg_renumber[i];
int endregno = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
@@ -450,18 +454,6 @@ global_alloc (file)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i])
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
initialize them. */
@@ -517,7 +509,7 @@ global_alloc (file)
So in either case, we can ignore the conflict. Likewise for
preferences. */
- for (i = 0; i < max_allocno; i++)
+ for (i = 0; i < (size_t) max_allocno; i++)
{
AND_COMPL_HARD_REG_SET (hard_reg_conflicts[i], eliminable_regset);
AND_COMPL_HARD_REG_SET (hard_reg_copy_preferences[i],
@@ -532,7 +524,7 @@ global_alloc (file)
/* Determine the order to allocate the remaining pseudo registers. */
allocno_order = (int *) alloca (max_allocno * sizeof (int));
- for (i = 0; i < max_allocno; i++)
+ for (i = 0; i < (size_t) max_allocno; i++)
allocno_order[i] = i;
/* Default the size to 1, since allocno_compare uses it to divide by.
@@ -542,7 +534,7 @@ global_alloc (file)
allocate it. So avoid the divide-by-zero and set it to a low
priority. */
- for (i = 0; i < max_allocno; i++)
+ for (i = 0; i < (size_t) max_allocno; i++)
{
if (allocno_size[i] == 0)
allocno_size[i] = 1;
@@ -560,8 +552,9 @@ global_alloc (file)
/* Try allocating them, one by one, in that order,
except for parameters marked with reg_live_length[regno] == -2. */
- for (i = 0; i < max_allocno; i++)
- if (REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0)
+ for (i = 0; i < (size_t) max_allocno; i++)
+ if (reg_renumber[allocno_reg[allocno_order[i]]] < 0
+ && REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0)
{
/* If we have more than one register class,
first try allocating in the class that is cheapest
@@ -584,7 +577,10 @@ global_alloc (file)
for the sake of debugging information. */
if (n_basic_blocks > 0)
#endif
- retval = reload (get_insns (), 1, file);
+ {
+ build_insn_chain (get_insns ());
+ retval = reload (get_insns (), 1, file);
+ }
free (conflicts);
return retval;
@@ -627,12 +623,12 @@ global_conflicts ()
{
register int b, i;
register rtx insn;
- short *block_start_allocnos;
+ int *block_start_allocnos;
/* Make a vector that mark_reg_{store,clobber} will store in. */
regs_set = (rtx *) alloca (max_parallel * sizeof (rtx) * 2);
- block_start_allocnos = (short *) alloca (max_allocno * sizeof (short));
+ block_start_allocnos = (int *) alloca (max_allocno * sizeof (int));
for (b = 0; b < n_basic_blocks; b++)
{
@@ -652,7 +648,7 @@ global_conflicts ()
are explicitly marked in basic_block_live_at_start. */
{
- register regset old = basic_block_live_at_start[b];
+ register regset old = BASIC_BLOCK (b)->global_live_at_start;
int ax = 0;
REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
@@ -675,16 +671,26 @@ global_conflicts ()
record_conflicts (block_start_allocnos, ax);
#ifdef STACK_REGS
- /* Pseudos can't go in stack regs at the start of a basic block
- that can be reached through a computed goto, since reg-stack
- can't handle computed gotos. */
- if (basic_block_computed_jump_target[b])
- for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
- record_one_conflict (ax);
+ {
+ /* Pseudos can't go in stack regs at the start of a basic block
+ that can be reached through a computed goto, since reg-stack
+ can't handle computed gotos. */
+ /* ??? Seems more likely that reg-stack can't handle any abnormal
+ edges, critical or not, computed goto or otherwise. */
+
+ edge e;
+ for (e = BASIC_BLOCK (b)->pred; e ; e = e->pred_next)
+ if (e->flags & EDGE_ABNORMAL)
+ break;
+
+ if (e != NULL)
+ for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
+ record_one_conflict (ax);
+ }
#endif
}
- insn = basic_block_head[b];
+ insn = BLOCK_HEAD (b);
/* Scan the code of this basic block, noting which allocnos
and hard regs are born or die. When one is born,
@@ -743,9 +749,16 @@ global_conflicts ()
/* If INSN has multiple outputs, then any reg that dies here
and is used inside of an output
- must conflict with the other outputs. */
-
- if (GET_CODE (PATTERN (insn)) == PARALLEL && !single_set (insn))
+ must conflict with the other outputs.
+
+ It is unsafe to use !single_set here since it will ignore an
+ unused output. Just because an output is unused does not mean
+ the compiler can assume the side effect will not occur.
+ Consider if REG appears in the address of an output and we
+ reload the output. If we allocate REG to the same hard
+ register as an unused output we could set the hard register
+ before the output reload insn. */
+ if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_DEAD)
{
@@ -774,7 +787,7 @@ global_conflicts ()
mark_reg_death (regs_set[n_regs_set]);
}
- if (insn == basic_block_end[b])
+ if (insn == BLOCK_END (b))
break;
insn = NEXT_INSN (insn);
}
@@ -975,7 +988,10 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
int regno = i;
#endif
if (! TEST_HARD_REG_BIT (used, regno)
- && HARD_REGNO_MODE_OK (regno, mode))
+ && HARD_REGNO_MODE_OK (regno, mode)
+ && (allocno_calls_crossed[allocno] == 0
+ || accept_call_clobbered
+ || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
{
register int j;
register int lim = regno + HARD_REGNO_NREGS (regno, mode);
@@ -1292,7 +1308,7 @@ record_one_conflict (regno)
static void
record_conflicts (allocno_vec, len)
- register short *allocno_vec;
+ register int *allocno_vec;
register int len;
{
register int allocno;
@@ -1324,16 +1340,13 @@ record_conflicts (allocno_vec, len)
if so, we do nothing.
SETTER is 0 if this register was modified by an auto-increment (i.e.,
- a REG_INC note was found for it).
-
- CLOBBERs are processed here by calling mark_reg_clobber. */
+ a REG_INC note was found for it). */
static void
-mark_reg_store (orig_reg, setter)
- rtx orig_reg, setter;
+mark_reg_store (reg, setter)
+ rtx reg, setter;
{
register int regno;
- register rtx reg = orig_reg;
/* WORD is which word of a multi-register group is being stored.
For the case where the store is actually into a SUBREG of REG.
@@ -1350,23 +1363,13 @@ mark_reg_store (orig_reg, setter)
if (GET_CODE (reg) != REG)
return;
- if (setter && GET_CODE (setter) == CLOBBER)
- {
- /* A clobber of a register should be processed here too. */
- mark_reg_clobber (orig_reg, setter);
- return;
- }
-
regs_set[n_regs_set++] = reg;
- if (setter)
+ if (setter && GET_CODE (setter) != CLOBBER)
set_preference (reg, SET_SRC (setter));
regno = REGNO (reg);
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno] /* + word */;
-
/* Either this is one of the max_allocno pseudo regs not allocated,
or it is or has a hardware reg. First handle the pseudo-regs. */
if (regno >= FIRST_PSEUDO_REGISTER)
@@ -1377,8 +1380,12 @@ mark_reg_store (orig_reg, setter)
record_one_conflict (regno);
}
}
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno] /* + word */;
+
/* Handle hardware regs (and pseudos allocated to hard regs). */
- else if (! fixed_regs[regno])
+ if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
@@ -1396,54 +1403,8 @@ static void
mark_reg_clobber (reg, setter)
rtx reg, setter;
{
- register int regno;
-
- /* WORD is which word of a multi-register group is being stored.
- For the case where the store is actually into a SUBREG of REG.
- Except we don't use it; I believe the entire REG needs to be
- made live. */
- int word = 0;
-
- if (GET_CODE (setter) != CLOBBER)
- return;
-
- if (GET_CODE (reg) == SUBREG)
- {
- word = SUBREG_WORD (reg);
- reg = SUBREG_REG (reg);
- }
-
- if (GET_CODE (reg) != REG)
- return;
-
- regs_set[n_regs_set++] = reg;
-
- regno = REGNO (reg);
-
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno] /* + word */;
-
- /* Either this is one of the max_allocno pseudo regs not allocated,
- or it is or has a hardware reg. First handle the pseudo-regs. */
- if (regno >= FIRST_PSEUDO_REGISTER)
- {
- if (reg_allocno[regno] >= 0)
- {
- SET_ALLOCNO_LIVE (reg_allocno[regno]);
- record_one_conflict (regno);
- }
- }
- /* Handle hardware regs (and pseudos allocated to hard regs). */
- else if (! fixed_regs[regno])
- {
- register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
- while (regno < last)
- {
- record_one_conflict (regno);
- SET_HARD_REG_BIT (hard_regs_live, regno);
- regno++;
- }
- }
+ if (GET_CODE (setter) == CLOBBER)
+ mark_reg_store (reg, setter);
}
/* Record that REG has conflicts with all the regs currently live.
@@ -1463,9 +1424,6 @@ mark_reg_conflicts (reg)
regno = REGNO (reg);
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
-
/* Either this is one of the max_allocno pseudo regs not allocated,
or it is or has a hardware reg. First handle the pseudo-regs. */
if (regno >= FIRST_PSEUDO_REGISTER)
@@ -1473,8 +1431,12 @@ mark_reg_conflicts (reg)
if (reg_allocno[regno] >= 0)
record_one_conflict (regno);
}
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
/* Handle hardware regs (and pseudos allocated to hard regs). */
- else if (! fixed_regs[regno])
+ if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
@@ -1494,10 +1456,6 @@ mark_reg_death (reg)
{
register int regno = REGNO (reg);
- /* For pseudo reg, see if it has been assigned a hardware reg. */
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
-
/* Either this is one of the max_allocno pseudo regs not allocated,
or it is a hardware reg. First handle the pseudo-regs. */
if (regno >= FIRST_PSEUDO_REGISTER)
@@ -1505,8 +1463,13 @@ mark_reg_death (reg)
if (reg_allocno[regno] >= 0)
CLEAR_ALLOCNO_LIVE (reg_allocno[regno]);
}
+
+ /* For pseudo reg, see if it has been assigned a hardware reg. */
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
/* Handle hardware regs (and pseudos allocated to hard regs). */
- else if (! fixed_regs[regno])
+ if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
{
/* Pseudo regs already assigned hardware regs are treated
almost the same as explicit hardware regs. */
@@ -1645,11 +1608,157 @@ mark_elimination (from, to)
int i;
for (i = 0; i < n_basic_blocks; i++)
- if (REGNO_REG_SET_P (basic_block_live_at_start[i], from))
- {
- CLEAR_REGNO_REG_SET (basic_block_live_at_start[i], from);
- SET_REGNO_REG_SET (basic_block_live_at_start[i], to);
- }
+ {
+ register regset r = BASIC_BLOCK (i)->global_live_at_start;
+ if (REGNO_REG_SET_P (r, from))
+ {
+ CLEAR_REGNO_REG_SET (r, from);
+ SET_REGNO_REG_SET (r, to);
+ }
+ }
+}
+
+/* Used for communication between the following functions. Holds the
+ current life information. */
+static regset live_relevant_regs;
+
+/* Record in live_relevant_regs that register REG became live. This
+ is called via note_stores. */
+static void
+reg_becomes_live (reg, setter)
+ rtx reg;
+ rtx setter ATTRIBUTE_UNUSED;
+{
+ int regno;
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+
+ if (GET_CODE (reg) != REG)
+ return;
+
+ regno = REGNO (reg);
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ while (nregs-- > 0)
+ SET_REGNO_REG_SET (live_relevant_regs, regno++);
+ }
+ else if (reg_renumber[regno] >= 0)
+ SET_REGNO_REG_SET (live_relevant_regs, regno);
+}
+
+/* Record in live_relevant_regs that register REGNO died. */
+static void
+reg_dies (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int nregs = HARD_REGNO_NREGS (regno, mode);
+ while (nregs-- > 0)
+ CLEAR_REGNO_REG_SET (live_relevant_regs, regno++);
+ }
+ else
+ CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
+}
+
+/* Walk the insns of the current function and build reload_insn_chain,
+ and record register life information. */
+static void
+build_insn_chain (first)
+ rtx first;
+{
+ struct insn_chain **p = &reload_insn_chain;
+ struct insn_chain *prev = 0;
+ int b = 0;
+
+ live_relevant_regs = ALLOCA_REG_SET ();
+
+ for (; first; first = NEXT_INSN (first))
+ {
+ struct insn_chain *c;
+
+ if (first == BLOCK_HEAD (b))
+ {
+ int i;
+ CLEAR_REG_SET (live_relevant_regs);
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, i)
+ && ! TEST_HARD_REG_BIT (eliminable_regset, i))
+ SET_REGNO_REG_SET (live_relevant_regs, i);
+
+ for (; i < max_regno; i++)
+ if (reg_renumber[i] >= 0
+ && REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, i))
+ SET_REGNO_REG_SET (live_relevant_regs, i);
+ }
+
+ if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
+ {
+ c = new_insn_chain ();
+ c->prev = prev;
+ prev = c;
+ *p = c;
+ p = &c->next;
+ c->insn = first;
+ c->block = b;
+
+ COPY_REG_SET (c->live_before, live_relevant_regs);
+
+ if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
+ {
+ rtx link;
+
+ /* Mark the death of everything that dies in this instruction. */
+
+ for (link = REG_NOTES (first); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_DEAD
+ && GET_CODE (XEXP (link, 0)) == REG)
+ reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+
+ /* Mark everything born in this instruction as live. */
+
+ note_stores (PATTERN (first), reg_becomes_live);
+ }
+
+ /* Remember which registers are live at the end of the insn, before
+ killing those with REG_UNUSED notes. */
+ COPY_REG_SET (c->live_after, live_relevant_regs);
+
+ if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
+ {
+ rtx link;
+
+ /* Mark anything that is set in this insn and then unused as dying. */
+
+ for (link = REG_NOTES (first); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_UNUSED
+ && GET_CODE (XEXP (link, 0)) == REG)
+ reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+ }
+ }
+
+ if (first == BLOCK_END (b))
+ b++;
+
+ /* Stop after we pass the end of the last basic block. Verify that
+ no real insns are after the end of the last basic block.
+
+ We may want to reorganize the loop somewhat since this test should
+ always be the right exit test. */
+ if (b == n_basic_blocks)
+ {
+ for (first = NEXT_INSN (first) ; first; first = NEXT_INSN (first))
+ if (GET_RTX_CLASS (GET_CODE (first)) == 'i'
+ && GET_CODE (PATTERN (first)) != USE)
+ abort ();
+ break;
+ }
+ }
+ FREE_REG_SET (live_relevant_regs);
+ *p = 0;
}
/* Print debugging trace information if -greg switch is given,
@@ -1661,10 +1770,20 @@ dump_conflicts (file)
{
register int i;
register int has_preferences;
- fprintf (file, ";; %d regs to allocate:", max_allocno);
+ register int nregs;
+ nregs = 0;
+ for (i = 0; i < max_allocno; i++)
+ {
+ if (reg_renumber[allocno_reg[allocno_order[i]]] >= 0)
+ continue;
+ nregs++;
+ }
+ fprintf (file, ";; %d regs to allocate:", nregs);
for (i = 0; i < max_allocno; i++)
{
int j;
+ if (reg_renumber[allocno_reg[allocno_order[i]]] >= 0)
+ continue;
fprintf (file, " %d", allocno_reg[allocno_order[i]]);
for (j = 0; j < max_regno; j++)
if (reg_allocno[j] == allocno_order[i]
diff --git a/contrib/gcc/gmon.c b/contrib/gcc/gmon.c
index 04fc13a..2bb7366 100644
--- a/contrib/gcc/gmon.c
+++ b/contrib/gcc/gmon.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1991 The Regents of the University of California.
+ * Copyright (c) 1991, 1998 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/contrib/gcc/graph.c b/contrib/gcc/graph.c
new file mode 100644
index 0000000..f586314
--- /dev/null
+++ b/contrib/gcc/graph.c
@@ -0,0 +1,475 @@
+/* Output routines for graphical representation.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <config.h>
+#include "system.h"
+
+#include "rtl.h"
+#include "flags.h"
+#include "output.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "toplev.h"
+
+static const char *graph_ext[] =
+{
+ /* no_graph */ "",
+ /* vcg */ ".vcg",
+};
+
+/* Output text for new basic block. */
+static void
+start_fct (fp)
+ FILE *fp;
+{
+
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fprintf (fp, "\
+graph: { title: \"%s\"\nfolding: 1\nhidden: 2\nnode: { title: \"%s.0\" }\n",
+ current_function_name, current_function_name);
+ break;
+ case no_graph:
+ break;
+ }
+}
+
+static void
+start_bb (fp, bb)
+ FILE *fp;
+ int bb;
+{
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fprintf (fp, "\
+graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\
+label: \"basic block %d",
+ current_function_name, bb, bb);
+ break;
+ case no_graph:
+ break;
+ }
+
+#if 0
+ /* FIXME Should this be printed? It makes the graph significantly larger. */
+
+ /* Print the live-at-start register list. */
+ fputc ('\n', fp);
+ EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[bb], 0, i,
+ {
+ fprintf (fp, " %d", i);
+ if (i < FIRST_PSEUDO_REGISTER)
+ fprintf (fp, " [%s]",
+ reg_names[i]);
+ });
+#endif
+
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fputs ("\"\n\n", fp);
+ break;
+ case no_graph:
+ break;
+ }
+}
+
+static void
+node_data (fp, tmp_rtx)
+ FILE *fp;
+ rtx tmp_rtx;
+{
+
+ if (PREV_INSN (tmp_rtx) == 0)
+ {
+ /* This is the first instruction. Add an edge from the starting
+ block. */
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fprintf (fp, "\
+edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n",
+ current_function_name,
+ current_function_name, XINT (tmp_rtx, 0));
+ break;
+ case no_graph:
+ break;
+ }
+ }
+
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fprintf (fp, "node: {\n title: \"%s.%d\"\n color: %s\n \
+label: \"%s %d\n",
+ current_function_name, XINT (tmp_rtx, 0),
+ GET_CODE (tmp_rtx) == NOTE ? "lightgrey"
+ : GET_CODE (tmp_rtx) == INSN ? "green"
+ : GET_CODE (tmp_rtx) == JUMP_INSN ? "darkgreen"
+ : GET_CODE (tmp_rtx) == CALL_INSN ? "darkgreen"
+ : GET_CODE (tmp_rtx) == CODE_LABEL ? "\
+darkgrey\n shape: ellipse" : "white",
+ GET_RTX_NAME (GET_CODE (tmp_rtx)), XINT (tmp_rtx, 0));
+ break;
+ case no_graph:
+ break;
+ }
+
+ /* Print the RTL. */
+ if (GET_CODE (tmp_rtx) == NOTE)
+ {
+ static const char *note_names[] =
+ {
+ NULL,
+ "deleted",
+ "block_beg",
+ "block_end",
+ "loop_beg",
+ "loop_end",
+ "function_end",
+ "setjmp",
+ "loop_cont",
+ "loop_vtop",
+ "prologue_end",
+ "epilogue_beg",
+ "deleted_label",
+ "function_beg",
+ "eh_region_beg",
+ "eh_region_end",
+ "repeated_line_number",
+ "range_start",
+ "range_end",
+ "live",
+ "basic_block"
+ };
+
+ fprintf (fp, " %s",
+ XINT (tmp_rtx, 4) < 0 ? note_names[-XINT (tmp_rtx, 4)] : "");
+ }
+ else if (GET_RTX_CLASS (GET_CODE (tmp_rtx)) == 'i')
+ print_rtl_single (fp, PATTERN (tmp_rtx));
+ else
+ print_rtl_single (fp, tmp_rtx);
+
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fputs ("\"\n}\n", fp);
+ break;
+ case no_graph:
+ break;
+ }
+}
+
+static void
+draw_edge (fp, from, to, bb_edge, class)
+ FILE *fp;
+ int from;
+ int to;
+ int bb_edge;
+ int class;
+{
+ char * color;
+ switch (graph_dump_format)
+ {
+ case vcg:
+ color = "";
+ if (class == 2)
+ color = "color: red ";
+ else if (bb_edge)
+ color = "color: blue ";
+ else if (class == 3)
+ color = "color: green ";
+ fprintf (fp,
+ "edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s",
+ current_function_name, from,
+ current_function_name, to, color);
+ if (class)
+ fprintf (fp, "class: %d ", class);
+ fputs ("}\n", fp);
+ break;
+ case no_graph:
+ break;
+ }
+}
+
+static void
+end_bb (fp, bb)
+ FILE *fp;
+ int bb ATTRIBUTE_UNUSED;
+{
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fputs ("}\n", fp);
+ break;
+ case no_graph:
+ break;
+ }
+}
+
+static void
+end_fct (fp)
+ FILE *fp;
+{
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fprintf (fp, "node: { title: \"%s.999999\" label: \"END\" }\n}\n",
+ current_function_name);
+ break;
+ case no_graph:
+ break;
+ }
+}
+
+/* Like print_rtl, but also print out live information for the start of each
+ basic block. */
+void
+print_rtl_graph_with_bb (base, suffix, rtx_first)
+ const char *base;
+ const char *suffix;
+ rtx rtx_first;
+{
+ register rtx tmp_rtx;
+ size_t namelen = strlen (base);
+ size_t suffixlen = strlen (suffix);
+ size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
+ char *buf = (char *) alloca (namelen + suffixlen + extlen);
+ FILE *fp;
+
+ if (basic_block_info == NULL)
+ return;
+
+ memcpy (buf, base, namelen);
+ memcpy (buf + namelen, suffix, suffixlen);
+ memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
+
+ fp = fopen (buf, "a");
+ if (fp == NULL)
+ return;
+
+ if (rtx_first == 0)
+ fprintf (fp, "(nil)\n");
+ else
+ {
+ int i;
+ enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
+ int max_uid = get_max_uid ();
+ int *start = (int *) alloca (max_uid * sizeof (int));
+ int *end = (int *) alloca (max_uid * sizeof (int));
+ enum bb_state *in_bb_p = (enum bb_state *)
+ alloca (max_uid * sizeof (enum bb_state));
+ basic_block bb;
+
+ for (i = 0; i < max_uid; ++i)
+ {
+ start[i] = end[i] = -1;
+ in_bb_p[i] = NOT_IN_BB;
+ }
+
+ for (i = n_basic_blocks - 1; i >= 0; --i)
+ {
+ rtx x;
+ bb = BASIC_BLOCK (i);
+ start[INSN_UID (bb->head)] = i;
+ end[INSN_UID (bb->end)] = i;
+ for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
+ {
+ in_bb_p[INSN_UID (x)]
+ = (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
+ ? IN_ONE_BB : IN_MULTIPLE_BB;
+ if (x == bb->end)
+ break;
+ }
+ }
+
+ /* Tell print-rtl that we want graph output. */
+ dump_for_graph = 1;
+
+ /* Start new function. */
+ start_fct (fp);
+
+ for (tmp_rtx = NEXT_INSN (rtx_first); NULL != tmp_rtx;
+ tmp_rtx = NEXT_INSN (tmp_rtx))
+ {
+ int edge_printed = 0;
+ rtx next_insn;
+
+ if (start[INSN_UID (tmp_rtx)] < 0 && end[INSN_UID (tmp_rtx)] < 0)
+ {
+ if (GET_CODE (tmp_rtx) == BARRIER)
+ continue;
+ if (GET_CODE (tmp_rtx) == NOTE
+ && (1 || in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB))
+ continue;
+ }
+
+ if ((i = start[INSN_UID (tmp_rtx)]) >= 0)
+ {
+ /* We start a subgraph for each basic block. */
+ start_bb (fp, i);
+
+ if (i == 0)
+ draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0);
+ }
+
+ /* Print the data for this node. */
+ node_data (fp, tmp_rtx);
+ next_insn = next_nonnote_insn (tmp_rtx);
+
+ if ((i = end[INSN_UID (tmp_rtx)]) >= 0)
+ {
+ edge e;
+
+ bb = BASIC_BLOCK (i);
+
+ /* End of the basic block. */
+ end_bb (fp, bb);
+
+ /* Now specify the edges to all the successors of this
+ basic block. */
+ for (e = bb->succ; e ; e = e->succ_next)
+ {
+ if (e->dest != EXIT_BLOCK_PTR)
+ {
+ rtx block_head = e->dest->head;
+
+ draw_edge (fp, INSN_UID (tmp_rtx),
+ INSN_UID (block_head),
+ next_insn != block_head,
+ (e->flags & EDGE_ABNORMAL ? 2 : 0));
+
+ if (block_head == next_insn)
+ edge_printed = 1;
+ }
+ else
+ {
+ draw_edge (fp, INSN_UID (tmp_rtx), 999999,
+ next_insn != 0,
+ (e->flags & EDGE_ABNORMAL ? 2 : 0));
+
+ if (next_insn == 0)
+ edge_printed = 1;
+ }
+ }
+ }
+
+ if (!edge_printed)
+ {
+ /* Don't print edges to barriers. */
+ if (next_insn == 0
+ || GET_CODE (next_insn) != BARRIER)
+ draw_edge (fp, XINT (tmp_rtx, 0),
+ next_insn ? INSN_UID (next_insn) : 999999, 0, 0);
+ else
+ {
+ /* We draw the remaining edges in class 3. We have
+ to skip over the barrier since these nodes are
+ not printed at all. */
+ do
+ next_insn = NEXT_INSN (next_insn);
+ while (next_insn
+ && (GET_CODE (next_insn) == NOTE
+ || GET_CODE (next_insn) == BARRIER));
+
+ draw_edge (fp, XINT (tmp_rtx, 0),
+ next_insn ? INSN_UID (next_insn) : 999999, 0, 3);
+ }
+ }
+ }
+
+ dump_for_graph = 0;
+
+ end_fct (fp);
+ }
+
+ fclose (fp);
+}
+
+
+/* Similar as clean_dump_file, but this time for graph output files. */
+void
+clean_graph_dump_file (base, suffix)
+ const char *base;
+ const char *suffix;
+{
+ size_t namelen = strlen (base);
+ size_t suffixlen = strlen (suffix);
+ size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
+ char *buf = (char *) alloca (namelen + extlen + suffixlen);
+ FILE *fp;
+
+ memcpy (buf, base, namelen);
+ memcpy (buf + namelen, suffix, suffixlen);
+ memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
+
+ fp = fopen (buf, "w");
+
+ if (fp == NULL)
+ pfatal_with_name (buf);
+
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fputs ("graph: {\nport_sharing: no\n", fp);
+ break;
+ case no_graph:
+ abort ();
+ }
+
+ fclose (fp);
+}
+
+
+/* Do final work on the graph output file. */
+void
+finish_graph_dump_file (base, suffix)
+ const char *base;
+ const char *suffix;
+{
+ size_t namelen = strlen (base);
+ size_t suffixlen = strlen (suffix);
+ size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
+ char *buf = (char *) alloca (namelen + suffixlen + extlen);
+ FILE *fp;
+
+ memcpy (buf, base, namelen);
+ memcpy (buf + namelen, suffix, suffixlen);
+ memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
+
+ fp = fopen (buf, "a");
+ if (fp != NULL)
+ {
+ switch (graph_dump_format)
+ {
+ case vcg:
+ fputs ("}\n", fp);
+ break;
+ case no_graph:
+ abort ();
+ }
+
+ fclose (fp);
+ }
+}
diff --git a/contrib/gcc/gthr-vxworks.h b/contrib/gcc/gthr-vxworks.h
index 9876646..6d51ded 100644
--- a/contrib/gcc/gthr-vxworks.h
+++ b/contrib/gcc/gthr-vxworks.h
@@ -60,11 +60,16 @@ extern __gthread_key_t eh_context_key;
don't map well enough onto VxWorks. */
static void
-__ehdtor ()
+__ehdtor (void *pTcb)
{
- if (eh_context_key)
- free ((void*)eh_context_key);
- eh_context_key = 0;
+ int tid = (int) pTcb;
+ void *p = (void*)taskVarGet(tid, &eh_context_key);
+ if (p != (void*)-1)
+ {
+ if (p)
+ free (p);
+ taskVarSet(tid, &eh_context_key, 0);
+ }
}
/* This only works for the code in libgcc2.c. */
@@ -74,6 +79,11 @@ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
{
*key = 0;
+ /* Do this first so that the task variables are visible during the
+ running of the delete hook. */
+
+ taskVarInit();
+
/* We don't have a way to track dtor here, so instead, we
register a generic routine that can cleanup any task. */
diff --git a/contrib/gcc/gthr.h b/contrib/gcc/gthr.h
index d1028cb..7511e35 100644
--- a/contrib/gcc/gthr.h
+++ b/contrib/gcc/gthr.h
@@ -1,6 +1,6 @@
/* Threads compatibily routines for libgcc2. */
/* Compile this one with gcc. */
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -48,6 +48,12 @@ Boston, MA 02111-1307, USA. */
__GTHREAD_MUTEX_INIT
to initialize __gthread_mutex_t to get a fast
non-recursive mutex.
+ __GTHREAD_MUTEX_INIT_FUNCTION
+ some systems can't initalize a mutex without a
+ function call. On such systems, define this to a
+ function which looks like this:
+ void __GTHREAD_MUTEX_INIT_FUNCTION (__gthread_mutex_t *)
+ Don't define __GTHREAD_MUTEX_INIT in this case
The threads interface must define the following static functions:
diff --git a/contrib/gcc/haifa-sched.c b/contrib/gcc/haifa-sched.c
index 0eebda9..d4d2121 100644
--- a/contrib/gcc/haifa-sched.c
+++ b/contrib/gcc/haifa-sched.c
@@ -1,5 +1,5 @@
/* Instruction scheduling pass.
- Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -136,8 +136,8 @@
This pass must update information that subsequent passes expect to
be correct. Namely: reg_n_refs, reg_n_sets, reg_n_deaths,
- reg_n_calls_crossed, and reg_live_length. Also, basic_block_head,
- basic_block_end.
+ reg_n_calls_crossed, and reg_live_length. Also, BLOCK_HEAD,
+ BLOCK_END.
The information in the line number notes is carefully retained by
this pass. Notes that refer to the starting and ending of
@@ -157,6 +157,7 @@
#include "config.h"
#include "system.h"
+#include "toplev.h"
#include "rtl.h"
#include "basic-block.h"
#include "regs.h"
@@ -166,6 +167,7 @@
#include "insn-attr.h"
#include "except.h"
#include "toplev.h"
+#include "recog.h"
extern char *reg_known_equiv_p;
extern rtx *reg_known_value;
@@ -250,7 +252,9 @@ static int current_block_num;
by splitting insns. */
static rtx *reg_last_uses;
static rtx *reg_last_sets;
+static rtx *reg_last_clobbers;
static regset reg_pending_sets;
+static regset reg_pending_clobbers;
static int reg_pending_sets_all;
/* Vector indexed by INSN_UID giving the original ordering of the insns. */
@@ -293,9 +297,9 @@ static unsigned int *insn_blockage;
#define UNIT_BITS 5
#define BLOCKAGE_MASK ((1 << BLOCKAGE_BITS) - 1)
#define ENCODE_BLOCKAGE(U, R) \
-((((U) << UNIT_BITS) << BLOCKAGE_BITS \
+(((U) << BLOCKAGE_BITS \
| MIN_BLOCKAGE_COST (R)) << BLOCKAGE_BITS \
- | MAX_BLOCKAGE_COST (R))
+ | MAX_BLOCKAGE_COST (R))
#define UNIT_BLOCKED(B) ((B) >> (2 * BLOCKAGE_BITS))
#define BLOCKAGE_RANGE(B) \
(((((B) >> BLOCKAGE_BITS) & BLOCKAGE_MASK) << (HOST_BITS_PER_INT / 2)) \
@@ -447,11 +451,9 @@ static void attach_deaths_insn PROTO ((rtx));
static int new_sometimes_live PROTO ((struct sometimes *, int, int));
static void finish_sometimes_live PROTO ((struct sometimes *, int));
static int schedule_block PROTO ((int, int));
-static rtx regno_use_in PROTO ((int, rtx));
static void split_hard_reg_notes PROTO ((rtx, rtx, rtx));
static void new_insn_dead_notes PROTO ((rtx, rtx, rtx, rtx));
static void update_n_sets PROTO ((rtx, int));
-static void update_flow_info PROTO ((rtx, rtx, rtx, rtx));
static char *safe_concat PROTO ((char *, char *, char *));
static int insn_issue_delay PROTO ((rtx));
static int birthing_insn_p PROTO ((rtx));
@@ -473,8 +475,8 @@ typedef struct
int next_in;
int next_out;
}
-edge;
-static edge *edge_table;
+haifa_edge;
+static haifa_edge *edge_table;
#define NEXT_IN(edge) (edge_table[edge].next_in)
#define NEXT_OUT(edge) (edge_table[edge].next_out)
@@ -764,7 +766,6 @@ static rtx group_leader PROTO ((rtx));
static int set_priorities PROTO ((int));
static void init_rtx_vector PROTO ((rtx **, rtx *, int, int));
static void schedule_region PROTO ((int));
-static void split_block_insns PROTO ((int));
#endif /* INSN_SCHEDULING */
@@ -862,6 +863,12 @@ add_dependence (insn, elem, dep_type)
if (insn == elem)
return;
+ /* We can get a dependency on deleted insns due to optimizations in
+ the register allocation and reloading or due to splitting. Any
+ such dependency is useless and can be ignored. */
+ if (GET_CODE (elem) == NOTE)
+ return;
+
/* If elem is part of a sequence that must be scheduled together, then
make the dependence point to the last insn of the sequence.
When HAVE_cc0, it is possible for NOTEs to exist between users and
@@ -1050,6 +1057,7 @@ static rtx last_scheduled_insn;
static rtx **bb_reg_last_uses;
static rtx **bb_reg_last_sets;
+static rtx **bb_reg_last_clobbers;
static rtx *bb_pending_read_insns;
static rtx *bb_pending_read_mems;
@@ -1078,7 +1086,7 @@ is_cfg_nonregular ()
/* If we have a label that could be the target of a nonlocal goto, then
the cfg is not well structured. */
- if (nonlocal_label_rtx_list () != NULL)
+ if (nonlocal_goto_handler_labels)
return 1;
/* If we have any forced labels, then the cfg is not well structured. */
@@ -1100,7 +1108,7 @@ is_cfg_nonregular ()
the cfg not well structured. */
/* check for labels referred to other thn by jumps */
for (b = 0; b < n_basic_blocks; b++)
- for (insn = basic_block_head[b];; insn = NEXT_INSN (insn))
+ for (insn = BLOCK_HEAD (b);; insn = NEXT_INSN (insn))
{
code = GET_CODE (insn);
if (GET_RTX_CLASS (code) == 'i')
@@ -1112,7 +1120,7 @@ is_cfg_nonregular ()
return 1;
}
- if (insn == basic_block_end[b])
+ if (insn == BLOCK_END (b))
break;
}
@@ -1165,8 +1173,8 @@ build_control_flow (s_preds, s_succs, num_preds, num_succs)
bzero ((char *) in_edges, n_basic_blocks * sizeof (int));
bzero ((char *) out_edges, n_basic_blocks * sizeof (int));
- edge_table = (edge *) xmalloc ((nr_edges) * sizeof (edge));
- bzero ((char *) edge_table, ((nr_edges) * sizeof (edge)));
+ edge_table = (haifa_edge *) xmalloc ((nr_edges) * sizeof (haifa_edge));
+ bzero ((char *) edge_table, ((nr_edges) * sizeof (haifa_edge)));
nr_edges = 0;
for (i = 0; i < n_basic_blocks; i++)
@@ -1405,8 +1413,8 @@ too_large (block, num_bbs, num_insns)
int block, *num_bbs, *num_insns;
{
(*num_bbs)++;
- (*num_insns) += (INSN_LUID (basic_block_end[block]) -
- INSN_LUID (basic_block_head[block]));
+ (*num_insns) += (INSN_LUID (BLOCK_END (block)) -
+ INSN_LUID (BLOCK_HEAD (block)));
if ((*num_bbs > MAX_RGN_BLOCKS) || (*num_insns > MAX_RGN_INSNS))
return 1;
else
@@ -1682,8 +1690,8 @@ find_rgns (s_preds, s_succs, num_preds, num_succs, dom)
/* Estimate # insns, and count # blocks in the region. */
num_bbs = 1;
- num_insns = (INSN_LUID (basic_block_end[i])
- - INSN_LUID (basic_block_head[i]));
+ num_insns = (INSN_LUID (BLOCK_END (i))
+ - INSN_LUID (BLOCK_HEAD (i)));
/* Find all loop latches (blocks which back edges to the loop
@@ -2117,6 +2125,16 @@ check_live_1 (src, x)
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);
+ if (GET_CODE (reg) == PARALLEL
+ && GET_MODE (reg) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
+ if (check_live_1 (src, XVECEXP (reg, 0, i)))
+ return 1;
+ return 0;
+ }
+
if (GET_CODE (reg) != REG)
return 1;
@@ -2139,7 +2157,8 @@ check_live_1 (src, x)
{
int b = candidate_table[src].split_bbs.first_member[i];
- if (REGNO_REG_SET_P (basic_block_live_at_start[b], regno + j))
+ if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start,
+ regno + j))
{
return 0;
}
@@ -2153,7 +2172,7 @@ check_live_1 (src, x)
{
int b = candidate_table[src].split_bbs.first_member[i];
- if (REGNO_REG_SET_P (basic_block_live_at_start[b], regno))
+ if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, regno))
{
return 0;
}
@@ -2185,6 +2204,15 @@ update_live_1 (src, x)
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);
+ if (GET_CODE (reg) == PARALLEL
+ && GET_MODE (reg) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
+ update_live_1 (src, XVECEXP (reg, 0, i));
+ return;
+ }
+
if (GET_CODE (reg) != REG)
return;
@@ -2204,7 +2232,8 @@ update_live_1 (src, x)
{
int b = candidate_table[src].update_bbs.first_member[i];
- SET_REGNO_REG_SET (basic_block_live_at_start[b], regno + j);
+ SET_REGNO_REG_SET (BASIC_BLOCK (b)->global_live_at_start,
+ regno + j);
}
}
}
@@ -2214,7 +2243,7 @@ update_live_1 (src, x)
{
int b = candidate_table[src].update_bbs.first_member[i];
- SET_REGNO_REG_SET (basic_block_live_at_start[b], regno);
+ SET_REGNO_REG_SET (BASIC_BLOCK (b)->global_live_at_start, regno);
}
}
}
@@ -2839,7 +2868,7 @@ blockage_range (unit, insn)
unsigned int blockage = INSN_BLOCKAGE (insn);
unsigned int range;
- if (UNIT_BLOCKED (blockage) != unit + 1)
+ if ((int) UNIT_BLOCKED (blockage) != unit + 1)
{
range = function_units[unit].blockage_range_function (insn);
/* We only cache the blockage range for one unit and then only if
@@ -3284,10 +3313,22 @@ sched_analyze_1 (x, insn)
{
register int regno;
register rtx dest = SET_DEST (x);
+ enum rtx_code code = GET_CODE (x);
if (dest == 0)
return;
+ if (GET_CODE (dest) == PARALLEL
+ && GET_MODE (dest) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ sched_analyze_1 (XVECEXP (dest, 0, i), insn);
+ if (GET_CODE (x) == SET)
+ sched_analyze_2 (SET_SRC (x), insn);
+ return;
+ }
+
while (GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SIGN_EXTRACT)
{
@@ -3317,15 +3358,25 @@ sched_analyze_1 (x, insn)
for (u = reg_last_uses[regno + i]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
- reg_last_uses[regno + i] = 0;
for (u = reg_last_sets[regno + i]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), REG_DEP_OUTPUT);
- SET_REGNO_REG_SET (reg_pending_sets, regno + i);
+ /* Clobbers need not be ordered with respect to one another,
+ but sets must be ordered with respect to a pending clobber. */
+ if (code == SET)
+ {
+ reg_last_uses[regno + i] = 0;
+ for (u = reg_last_clobbers[regno + i]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), REG_DEP_OUTPUT);
+ SET_REGNO_REG_SET (reg_pending_sets, regno + i);
+ }
+ else
+ SET_REGNO_REG_SET (reg_pending_clobbers, regno + i);
- if ((call_used_regs[regno + i] || global_regs[regno + i]))
- /* Function calls clobber all call_used regs. */
+ /* Function calls clobber all call_used regs. */
+ if (global_regs[regno + i]
+ || (code == SET && call_used_regs[regno + i]))
for (u = last_function_call; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
}
@@ -3336,12 +3387,19 @@ sched_analyze_1 (x, insn)
for (u = reg_last_uses[regno]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
- reg_last_uses[regno] = 0;
for (u = reg_last_sets[regno]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), REG_DEP_OUTPUT);
- SET_REGNO_REG_SET (reg_pending_sets, regno);
+ if (code == SET)
+ {
+ reg_last_uses[regno] = 0;
+ for (u = reg_last_clobbers[regno]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), REG_DEP_OUTPUT);
+ SET_REGNO_REG_SET (reg_pending_sets, regno);
+ }
+ else
+ SET_REGNO_REG_SET (reg_pending_clobbers, regno);
/* Pseudos that are REG_EQUIV to something may be replaced
by that during reloading. We need only add dependencies for
@@ -3492,6 +3550,10 @@ sched_analyze_2 (x, insn)
for (u = reg_last_sets[regno + i]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), 0);
+ /* ??? This should never happen. */
+ for (u = reg_last_clobbers[regno + i]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), 0);
+
if ((call_used_regs[regno + i] || global_regs[regno + i]))
/* Function calls clobber all call_used regs. */
for (u = last_function_call; u; u = XEXP (u, 1))
@@ -3505,6 +3567,10 @@ sched_analyze_2 (x, insn)
for (u = reg_last_sets[regno]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), 0);
+ /* ??? This should never happen. */
+ for (u = reg_last_clobbers[regno]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), 0);
+
/* Pseudos that are REG_EQUIV to something may be replaced
by that during reloading. We need only add dependencies for
the address in the REG_EQUIV note. */
@@ -3595,9 +3661,11 @@ sched_analyze_2 (x, insn)
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
reg_last_uses[i] = 0;
- /* reg_last_sets[r] is now a list of insns */
for (u = reg_last_sets[i]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), 0);
+
+ for (u = reg_last_clobbers[i]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), 0);
}
reg_pending_sets_all = 1;
@@ -3687,73 +3755,81 @@ sched_analyze_insn (x, insn, loop_notes)
sched_analyze_2 (XEXP (link, 0), insn);
}
- /* If there is a {LOOP,EHREGION}_{BEG,END} note in the middle of a basic block, then
- we must be sure that no instructions are scheduled across it.
+ /* If there is a {LOOP,EHREGION}_{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 ();
+ int schedule_barrier_found = 0;
rtx link;
- for (i = 0; i < max_reg; i++)
+ /* Update loop_notes with any notes from this insn. Also determine
+ if any of the notes on the list correspond to instruction scheduling
+ barriers (loop, eh & setjmp notes, but not range notes. */
+ link = loop_notes;
+ while (XEXP (link, 1))
{
- 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 (INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_BEG
+ || INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_END
+ || INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_BEG
+ || INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_END
+ || INTVAL (XEXP (link, 0)) == NOTE_INSN_SETJMP)
+ schedule_barrier_found = 1;
- /* reg_last_sets[r] is now a list of insns */
- for (u = reg_last_sets[i]; u; u = XEXP (u, 1))
- add_dependence (insn, XEXP (u, 0), 0);
+ link = XEXP (link, 1);
}
- reg_pending_sets_all = 1;
-
- flush_pending_lists (insn, 0);
-
- 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
- for a register that actually dies a few instructions earlier. For
- example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
- In this case, we must consider the insn to use the register mentioned
- in the REG_DEAD note. Otherwise, we may accidentally move this insn
- after another insn that sets the register, thus getting obviously invalid
- rtl. This confuses reorg which believes that REG_DEAD notes are still
- meaningful.
+ /* Add dependencies if a scheduling barrier was found. */
+ if (schedule_barrier_found)
+ {
+ 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;
- ??? We would get better code if we fixed reload to put the REG_DEAD
- notes in the right places, but that may not be worth the effort. */
+ for (u = reg_last_sets[i]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), 0);
- if (reload_completed)
- {
- rtx note;
+ for (u = reg_last_clobbers[i]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), 0);
+ }
+ reg_pending_sets_all = 1;
+
+ flush_pending_lists (insn, 0);
+ }
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- if (REG_NOTE_KIND (note) == REG_DEAD)
- sched_analyze_2 (XEXP (note, 0), insn);
}
+ /* Accumulate clobbers until the next set so that it will be output dependant
+ on all of them. At the next set we can clear the clobber list, since
+ subsequent sets will be output dependant on it. */
EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i,
{
- /* reg_last_sets[r] is now a list of insns */
free_list (&reg_last_sets[i], &unused_insn_list);
+ free_list (&reg_last_clobbers[i],
+ &unused_insn_list);
reg_last_sets[i]
= alloc_INSN_LIST (insn, NULL_RTX);
});
+ EXECUTE_IF_SET_IN_REG_SET (reg_pending_clobbers, 0, i,
+ {
+ reg_last_clobbers[i]
+ = alloc_INSN_LIST (insn, reg_last_clobbers[i]);
+ });
CLEAR_REG_SET (reg_pending_sets);
+ CLEAR_REG_SET (reg_pending_clobbers);
if (reg_pending_sets_all)
{
for (i = 0; i < maxreg; i++)
{
- /* reg_last_sets[r] is now a list of insns */
free_list (&reg_last_sets[i], &unused_insn_list);
reg_last_sets[i] = alloc_INSN_LIST (insn, NULL_RTX);
}
@@ -3851,9 +3927,11 @@ sched_analyze (head, tail)
reg_last_uses[i] = 0;
- /* reg_last_sets[r] is now a list of insns */
for (u = reg_last_sets[i]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), 0);
+
+ for (u = reg_last_clobbers[i]; u; u = XEXP (u, 1))
+ add_dependence (insn, XEXP (u, 0), 0);
}
reg_pending_sets_all = 1;
@@ -3874,13 +3952,11 @@ sched_analyze (head, tail)
{
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;
- /* reg_last_sets[r] is now a list of insns */
for (u = reg_last_sets[i]; u; u = XEXP (u, 1))
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
- SET_REGNO_REG_SET (reg_pending_sets, i);
+ SET_REGNO_REG_SET (reg_pending_clobbers, i);
}
}
@@ -3912,13 +3988,23 @@ sched_analyze (head, tail)
}
/* See comments on reemit_notes as to why we do this. */
+ /* ??? Actually, the reemit_notes just say what is done, not why. */
+
+ else if (GET_CODE (insn) == NOTE
+ && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_START
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_END))
+ {
+ loop_notes = alloc_EXPR_LIST (REG_DEAD, NOTE_RANGE_INFO (insn),
+ loop_notes);
+ loop_notes = alloc_EXPR_LIST (REG_DEAD,
+ GEN_INT (NOTE_LINE_NUMBER (insn)),
+ loop_notes);
+ }
else if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_START
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_END
|| (NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP
&& GET_CODE (PREV_INSN (insn)) != CALL_INSN)))
{
@@ -3954,6 +4040,15 @@ sched_note_set (x, death)
if (reg == 0)
return;
+ if (GET_CODE (reg) == PARALLEL
+ && GET_MODE (reg) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
+ sched_note_set (XVECEXP (reg, 0, i), death);
+ return;
+ }
+
while (GET_CODE (reg) == SUBREG || GET_CODE (reg) == STRICT_LOW_PART
|| GET_CODE (reg) == SIGN_EXTRACT || GET_CODE (reg) == ZERO_EXTRACT)
{
@@ -4187,18 +4282,31 @@ birthing_insn_p (pat)
return 0;
if (GET_CODE (pat) == SET
- && GET_CODE (SET_DEST (pat)) == REG)
+ && (GET_CODE (SET_DEST (pat)) == REG
+ || (GET_CODE (SET_DEST (pat)) == PARALLEL
+ && GET_MODE (SET_DEST (pat)) == BLKmode)))
{
rtx dest = SET_DEST (pat);
- int i = REGNO (dest);
+ int i;
/* It would be more accurate to use refers_to_regno_p or
- reg_mentioned_p to determine when the dest is not live before this
- insn. */
-
- if (REGNO_REG_SET_P (bb_live_regs, i))
- return (REG_N_SETS (i) == 1);
-
+ reg_mentioned_p to determine when the dest is not live before this
+ insn. */
+ if (GET_CODE (dest) == REG)
+ {
+ i = REGNO (dest);
+ if (REGNO_REG_SET_P (bb_live_regs, i))
+ return (REG_N_SETS (i) == 1);
+ }
+ else
+ {
+ for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ {
+ int regno = REGNO (SET_DEST (XVECEXP (dest, 0, i)));
+ if (REGNO_REG_SET_P (bb_live_regs, regno))
+ return (REG_N_SETS (regno) == 1);
+ }
+ }
return 0;
}
if (GET_CODE (pat) == PARALLEL)
@@ -4261,6 +4369,9 @@ adjust_priority (prev)
}
}
+/* Clock at which the previous instruction was issued. */
+static int last_clock_var;
+
/* INSN is the "currently executing insn". Launch each insn which was
waiting on INSN. READY is a vector of insns which are ready to fire.
N_READY is the number of elements in READY. CLOCK is the current
@@ -4345,6 +4456,17 @@ schedule_insn (insn, ready, n_ready, clock)
}
}
+ /* Annotate the instruction with issue information -- TImode
+ indicates that the instruction is expected not to be able
+ to issue on the same cycle as the previous insn. A machine
+ may use this information to decide how the instruction should
+ be aligned. */
+ if (reload_completed && issue_rate > 1)
+ {
+ PUT_MODE (insn, clock > last_clock_var ? TImode : VOIDmode);
+ last_clock_var = clock;
+ }
+
return n_ready;
}
@@ -4503,12 +4625,15 @@ attach_deaths (x, insn, set_p)
if (regno >= FIRST_PSEUDO_REGISTER || ! global_regs[regno])
{
- /* Never add REG_DEAD notes for the FRAME_POINTER_REGNUM or the
- STACK_POINTER_REGNUM, since these are always considered to be
- live. Similarly for ARG_POINTER_REGNUM if it is fixed. */
- if (regno != FRAME_POINTER_REGNUM
+ /* Never add REG_DEAD notes for STACK_POINTER_REGNUM
+ since it's always considered to be live. Similarly
+ for FRAME_POINTER_REGNUM if a frame pointer is needed
+ and for ARG_POINTER_REGNUM if it is fixed. */
+ if (! (regno == FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && ! (regno == HARD_FRAME_POINTER_REGNUM)
+ && ! (regno == HARD_FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#endif
#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
&& ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
@@ -4596,6 +4721,16 @@ attach_deaths (x, insn, set_p)
attach_deaths (XEXP (x, 2), insn, 0);
return;
+ case PARALLEL:
+ if (set_p
+ && GET_MODE (x) == BLKmode)
+ {
+ for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+ attach_deaths (SET_DEST (XVECEXP (x, 0, i)), insn, 1);
+ return;
+ }
+
+ /* fallthrough */
default:
/* Other cases: walk the insn. */
fmt = GET_RTX_FORMAT (code);
@@ -4756,8 +4891,8 @@ get_block_head_tail (bb, headp, tailp)
b = BB_TO_BLOCK (bb);
/* HEAD and TAIL delimit the basic block being scheduled. */
- head = basic_block_head[b];
- tail = basic_block_end[b];
+ head = BLOCK_HEAD (b);
+ tail = BLOCK_END (b);
/* Don't include any notes or labels at the beginning of the
basic block, or notes at the ends of basic blocks. */
@@ -4838,7 +4973,7 @@ save_line_notes (bb)
get_block_head_tail (bb, &head, &tail);
next_tail = NEXT_INSN (tail);
- for (insn = basic_block_head[BB_TO_BLOCK (bb)];
+ for (insn = BLOCK_HEAD (BB_TO_BLOCK (bb));
insn != next_tail;
insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
@@ -4861,8 +4996,8 @@ restore_line_notes (bb)
b = BB_TO_BLOCK (bb);
- head = basic_block_head[b];
- next_tail = NEXT_INSN (basic_block_end[b]);
+ head = BLOCK_HEAD (b);
+ next_tail = NEXT_INSN (BLOCK_END (b));
/* Determine the current line-number. We want to know the current
line number of the first insn of the block here, in case it is
@@ -5048,7 +5183,7 @@ finish_sometimes_live (regs_sometimes_live, sometimes_max)
/* functions for computation of registers live/usage info */
-/* It is assumed that prior to scheduling basic_block_live_at_start (b)
+/* It is assumed that prior to scheduling BASIC_BLOCK (b)->global_live_at_start
contains the registers that are alive at the entry to b.
Two passes follow: The first pass is performed before the scheduling
@@ -5078,7 +5213,7 @@ find_pre_sched_live (bb)
int b = BB_TO_BLOCK (bb);
get_block_head_tail (bb, &head, &tail);
- COPY_REG_SET (bb_live_regs, basic_block_live_at_start[b]);
+ COPY_REG_SET (bb_live_regs, BASIC_BLOCK (b)->global_live_at_start);
next_tail = NEXT_INSN (tail);
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
@@ -5216,7 +5351,8 @@ find_post_sched_live (bb)
int b_succ;
b_succ = TO_BLOCK (e);
- IOR_REG_SET (bb_live_regs, basic_block_live_at_start[b_succ]);
+ IOR_REG_SET (bb_live_regs,
+ BASIC_BLOCK (b_succ)->global_live_at_start);
e = NEXT_OUT (e);
}
while (e != first_edge);
@@ -5238,7 +5374,7 @@ find_post_sched_live (bb)
&& (GET_RTX_CLASS (GET_CODE (tail)) != 'i'))
{
if (current_nr_blocks > 1)
- COPY_REG_SET (basic_block_live_at_start[b], bb_live_regs);
+ COPY_REG_SET (BASIC_BLOCK (b)->global_live_at_start, bb_live_regs);
return;
}
@@ -5361,9 +5497,9 @@ find_post_sched_live (bb)
finish_sometimes_live (regs_sometimes_live, sometimes_max);
- /* In interblock scheduling, basic_block_live_at_start may have changed. */
+ /* In interblock scheduling, global_live_at_start may have changed. */
if (current_nr_blocks > 1)
- COPY_REG_SET (basic_block_live_at_start[b], bb_live_regs);
+ COPY_REG_SET (BASIC_BLOCK (b)->global_live_at_start, bb_live_regs);
FREE_REG_SET (old_live_regs);
@@ -5435,7 +5571,7 @@ update_reg_usage ()
pseudos which are live in more than one block.
This is because combine might have made an optimization which
- invalidated basic_block_live_at_start and reg_n_calls_crossed,
+ invalidated global_live_at_start and reg_n_calls_crossed,
but it does not update them. If we update reg_n_calls_crossed
here, the two variables are now inconsistent, and this might
confuse the caller-save code into saving a register that doesn't
@@ -5699,8 +5835,17 @@ print_exp (buf, x, verbose)
{
case PLUS:
op[0] = XEXP (x, 0);
- st[1] = "+";
- op[1] = XEXP (x, 1);
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) < 0)
+ {
+ st[1] = "-";
+ op[1] = GEN_INT (-INTVAL (XEXP (x, 1)));
+ }
+ else
+ {
+ st[1] = "+";
+ op[1] = XEXP (x, 1);
+ }
break;
case LO_SUM:
op[0] = XEXP (x, 0);
@@ -6026,7 +6171,7 @@ print_value (buf, x, verbose)
switch (GET_CODE (x))
{
case CONST_INT:
- sprintf (t, "0x%lx", (long)INTVAL (x));
+ sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
cur = safe_concat (buf, cur, t);
break;
case CONST_DOUBLE:
@@ -6429,13 +6574,22 @@ reemit_notes (insn, last)
if (REG_NOTE_KIND (note) == REG_DEAD
&& GET_CODE (XEXP (note, 0)) == CONST_INT)
{
- if (INTVAL (XEXP (note, 0)) == NOTE_INSN_SETJMP)
+ int note_type = INTVAL (XEXP (note, 0));
+ if (note_type == NOTE_INSN_SETJMP)
{
- retval = emit_note_after (INTVAL (XEXP (note, 0)), insn);
+ retval = emit_note_after (NOTE_INSN_SETJMP, insn);
CONST_CALL_P (retval) = CONST_CALL_P (note);
remove_note (insn, note);
note = XEXP (note, 1);
}
+ else if (note_type == NOTE_INSN_RANGE_START
+ || note_type == NOTE_INSN_RANGE_END)
+ {
+ last = emit_note_before (note_type, last);
+ remove_note (insn, note);
+ note = XEXP (note, 1);
+ NOTE_RANGE_INFO (last) = XEXP (note, 0);
+ }
else
{
last = emit_note_before (INTVAL (XEXP (note, 0)), last);
@@ -6590,8 +6744,7 @@ schedule_block (bb, rgn_n_insns)
fprintf (dump, ";; ======================================================\n");
fprintf (dump,
";; -- basic block %d from %d to %d -- %s reload\n",
- b, INSN_UID (basic_block_head[b]),
- INSN_UID (basic_block_end[b]),
+ b, INSN_UID (BLOCK_HEAD (b)), INSN_UID (BLOCK_END (b)),
(reload_completed ? "after" : "before"));
fprintf (dump, ";; ======================================================\n");
fprintf (dump, "\n");
@@ -6721,15 +6874,16 @@ schedule_block (bb, rgn_n_insns)
q_ptr = 0;
q_size = 0;
clock_var = 0;
+ last_clock_var = 0;
bzero ((char *) insn_queue, sizeof (insn_queue));
/* We start inserting insns after PREV_HEAD. */
last = prev_head;
/* Initialize INSN_QUEUE, LIST and NEW_NEEDS. */
- new_needs = (NEXT_INSN (prev_head) == basic_block_head[b]
+ new_needs = (NEXT_INSN (prev_head) == BLOCK_HEAD (b)
? NEED_HEAD : NEED_NOTHING);
- if (PREV_INSN (next_tail) == basic_block_end[b])
+ if (PREV_INSN (next_tail) == BLOCK_END (b))
new_needs |= NEED_TAIL;
/* loop until all the insns in BB are scheduled. */
@@ -6813,29 +6967,29 @@ schedule_block (bb, rgn_n_insns)
/* Update source block boundaries. */
b1 = INSN_BLOCK (temp);
- if (temp == basic_block_head[b1]
- && insn == basic_block_end[b1])
+ if (temp == BLOCK_HEAD (b1)
+ && insn == BLOCK_END (b1))
{
/* We moved all the insns in the basic block.
Emit a note after the last insn and update the
begin/end boundaries to point to the note. */
emit_note_after (NOTE_INSN_DELETED, insn);
- basic_block_end[b1] = NEXT_INSN (insn);
- basic_block_head[b1] = NEXT_INSN (insn);
+ BLOCK_END (b1) = NEXT_INSN (insn);
+ BLOCK_HEAD (b1) = NEXT_INSN (insn);
}
- else if (insn == basic_block_end[b1])
+ else if (insn == BLOCK_END (b1))
{
/* We took insns from the end of the basic block,
so update the end of block boundary so that it
points to the first insn we did not move. */
- basic_block_end[b1] = PREV_INSN (temp);
+ BLOCK_END (b1) = PREV_INSN (temp);
}
- else if (temp == basic_block_head[b1])
+ else if (temp == BLOCK_HEAD (b1))
{
/* We took insns from the start of the basic block,
so update the start of block boundary so that
it points to the first insn we did not move. */
- basic_block_head[b1] = NEXT_INSN (insn);
+ BLOCK_HEAD (b1) = NEXT_INSN (insn);
}
}
else
@@ -6911,18 +7065,18 @@ schedule_block (bb, rgn_n_insns)
/* update target block boundaries. */
if (new_needs & NEED_HEAD)
- basic_block_head[b] = head;
+ BLOCK_HEAD (b) = head;
if (new_needs & NEED_TAIL)
- basic_block_end[b] = tail;
+ BLOCK_END (b) = tail;
/* debugging */
if (sched_verbose)
{
fprintf (dump, ";; total time = %d\n;; new basic block head = %d\n",
- clock_var, INSN_UID (basic_block_head[b]));
+ clock_var, INSN_UID (BLOCK_HEAD (b)));
fprintf (dump, ";; new basic block end = %d\n\n",
- INSN_UID (basic_block_end[b]));
+ INSN_UID (BLOCK_END (b)));
}
return (sched_n_insns);
@@ -7133,9 +7287,11 @@ compute_block_backward_dependences (bb)
{
reg_last_uses = (rtx *) alloca (max_reg * sizeof (rtx));
reg_last_sets = (rtx *) alloca (max_reg * sizeof (rtx));
+ reg_last_clobbers = (rtx *) alloca (max_reg * sizeof (rtx));
bzero ((char *) reg_last_uses, max_reg * sizeof (rtx));
bzero ((char *) reg_last_sets, max_reg * sizeof (rtx));
+ bzero ((char *) reg_last_clobbers, max_reg * sizeof (rtx));
pending_read_insns = 0;
pending_read_mems = 0;
@@ -7153,6 +7309,7 @@ compute_block_backward_dependences (bb)
{
reg_last_uses = bb_reg_last_uses[bb];
reg_last_sets = bb_reg_last_sets[bb];
+ reg_last_clobbers = bb_reg_last_clobbers[bb];
pending_read_insns = bb_pending_read_insns[bb];
pending_read_mems = bb_pending_read_mems[bb];
@@ -7224,6 +7381,16 @@ compute_block_backward_dependences (bb)
= alloc_INSN_LIST (XEXP (u, 0),
(bb_reg_last_sets[bb_succ])[reg]);
}
+
+ for (u = reg_last_clobbers[reg]; u; u = XEXP (u, 1))
+ {
+ if (find_insn_list (XEXP (u, 0), (bb_reg_last_clobbers[bb_succ])[reg]))
+ continue;
+
+ (bb_reg_last_clobbers[bb_succ])[reg]
+ = alloc_INSN_LIST (XEXP (u, 0),
+ (bb_reg_last_clobbers[bb_succ])[reg]);
+ }
}
/* mem read/write lists are inherited by bb_succ */
@@ -7298,6 +7465,8 @@ compute_block_backward_dependences (bb)
3-5% on average. */
for (b = 0; b < max_reg; ++b)
{
+ if (reg_last_clobbers[b])
+ free_list (&reg_last_clobbers[b], &unused_insn_list);
if (reg_last_sets[b])
free_list (&reg_last_sets[b], &unused_insn_list);
if (reg_last_uses[b])
@@ -7309,6 +7478,7 @@ compute_block_backward_dependences (bb)
{
bb_reg_last_uses[bb] = (rtx *) NULL_RTX;
bb_reg_last_sets[bb] = (rtx *) NULL_RTX;
+ bb_reg_last_clobbers[bb] = (rtx *) NULL_RTX;
}
}
@@ -7461,6 +7631,7 @@ schedule_region (rgn)
current_blocks = RGN_BLOCKS (rgn);
reg_pending_sets = ALLOCA_REG_SET ();
+ reg_pending_clobbers = ALLOCA_REG_SET ();
reg_pending_sets_all = 0;
/* initializations for region data dependence analyisis */
@@ -7472,21 +7643,34 @@ schedule_region (rgn)
bb_reg_last_uses = (rtx **) alloca (current_nr_blocks * sizeof (rtx *));
space = (rtx *) alloca (current_nr_blocks * maxreg * sizeof (rtx));
bzero ((char *) space, current_nr_blocks * maxreg * sizeof (rtx));
- init_rtx_vector (bb_reg_last_uses, space, current_nr_blocks, maxreg * sizeof (rtx *));
+ init_rtx_vector (bb_reg_last_uses, space, current_nr_blocks,
+ maxreg * sizeof (rtx *));
bb_reg_last_sets = (rtx **) alloca (current_nr_blocks * sizeof (rtx *));
space = (rtx *) alloca (current_nr_blocks * maxreg * sizeof (rtx));
bzero ((char *) space, current_nr_blocks * maxreg * sizeof (rtx));
- init_rtx_vector (bb_reg_last_sets, space, current_nr_blocks, maxreg * sizeof (rtx *));
+ init_rtx_vector (bb_reg_last_sets, space, current_nr_blocks,
+ maxreg * sizeof (rtx *));
+
+ bb_reg_last_clobbers =
+ (rtx **) alloca (current_nr_blocks * sizeof (rtx *));
+ space = (rtx *) alloca (current_nr_blocks * maxreg * sizeof (rtx));
+ bzero ((char *) space, current_nr_blocks * maxreg * sizeof (rtx));
+ init_rtx_vector (bb_reg_last_clobbers, space, current_nr_blocks,
+ maxreg * sizeof (rtx *));
bb_pending_read_insns = (rtx *) alloca (current_nr_blocks * sizeof (rtx));
bb_pending_read_mems = (rtx *) alloca (current_nr_blocks * sizeof (rtx));
- bb_pending_write_insns = (rtx *) alloca (current_nr_blocks * sizeof (rtx));
+ bb_pending_write_insns =
+ (rtx *) alloca (current_nr_blocks * sizeof (rtx));
bb_pending_write_mems = (rtx *) alloca (current_nr_blocks * sizeof (rtx));
- bb_pending_lists_length = (int *) alloca (current_nr_blocks * sizeof (int));
- bb_last_pending_memory_flush = (rtx *) alloca (current_nr_blocks * sizeof (rtx));
+ bb_pending_lists_length =
+ (int *) alloca (current_nr_blocks * sizeof (int));
+ bb_last_pending_memory_flush =
+ (rtx *) alloca (current_nr_blocks * sizeof (rtx));
bb_last_function_call = (rtx *) alloca (current_nr_blocks * sizeof (rtx));
- bb_sched_before_next_call = (rtx *) alloca (current_nr_blocks * sizeof (rtx));
+ bb_sched_before_next_call =
+ (rtx *) alloca (current_nr_blocks * sizeof (rtx));
init_rgn_data_dependences (current_nr_blocks);
}
@@ -7604,39 +7788,7 @@ schedule_region (rgn)
free_pending_lists ();
FREE_REG_SET (reg_pending_sets);
-}
-
-/* Subroutine of split_hard_reg_notes. Searches X for any reference to
- REGNO, returning the rtx of the reference found if any. Otherwise,
- returns 0. */
-
-static rtx
-regno_use_in (regno, x)
- int regno;
- rtx x;
-{
- register char *fmt;
- int i, j;
- rtx tem;
-
- if (GET_CODE (x) == REG && REGNO (x) == regno)
- return x;
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if ((tem = regno_use_in (regno, XEXP (x, i))))
- return tem;
- }
- else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if ((tem = regno_use_in (regno, XVECEXP (x, i, j))))
- return tem;
- }
-
- return 0;
+ FREE_REG_SET (reg_pending_clobbers);
}
/* Subroutine of update_flow_info. Determines whether any new REG_NOTEs are
@@ -7825,7 +7977,7 @@ update_n_sets (x, inc)
the insns from FIRST to LAST inclusive that were created by splitting
ORIG_INSN. NOTES are the original REG_NOTES. */
-static void
+void
update_flow_info (notes, first, last, orig_insn)
rtx notes;
rtx first, last;
@@ -7893,16 +8045,7 @@ update_flow_info (notes, first, last, orig_insn)
register that was not needed by this instantiation of the
pattern, so we can safely ignore it. */
if (insn == first)
- {
- /* After reload, REG_DEAD notes come sometimes an
- instruction after the register actually dies. */
- if (reload_completed && REG_NOTE_KIND (note) == REG_DEAD)
- {
- XEXP (note, 1) = REG_NOTES (insn);
- REG_NOTES (insn) = note;
- break;
- }
-
+ {
if (REG_NOTE_KIND (note) != REG_UNUSED)
abort ();
@@ -8255,8 +8398,28 @@ update_flow_info (notes, first, last, orig_insn)
}
else if (!found_orig_dest)
{
- /* This should never happen. */
- abort ();
+ int i, regno;
+
+ /* Should never reach here for a pseudo reg. */
+ if (REGNO (orig_dest) >= FIRST_PSEUDO_REGISTER)
+ abort ();
+
+ /* This can happen for a hard register, if the splitter
+ does not bother to emit instructions which would be no-ops.
+ We try to verify that this is the case by checking to see if
+ the original instruction uses all of the registers that it
+ set. This case is OK, because deleting a no-op can not affect
+ REG_DEAD notes on other insns. If this is not the case, then
+ abort. */
+
+ regno = REGNO (orig_dest);
+ for (i = HARD_REGNO_NREGS (regno, GET_MODE (orig_dest)) - 1;
+ i >= 0; i--)
+ if (! refers_to_regno_p (regno + i, regno + i + 1, orig_insn,
+ NULL_PTR))
+ break;
+ if (i >= 0)
+ abort ();
}
}
@@ -8305,79 +8468,6 @@ update_flow_info (notes, first, last, orig_insn)
}
}
-/* Do the splitting of insns in the block b. */
-
-static void
-split_block_insns (b)
- int b;
-{
- rtx insn, next;
-
- for (insn = basic_block_head[b];; insn = next)
- {
- rtx set, last, first, notes;
-
- /* Can't use `next_real_insn' because that
- might go across CODE_LABELS and short-out basic blocks. */
- next = NEXT_INSN (insn);
- if (GET_CODE (insn) != INSN)
- {
- if (insn == basic_block_end[b])
- break;
-
- continue;
- }
-
- /* Don't split no-op move insns. These should silently disappear
- later in final. Splitting such insns would break the code
- that handles REG_NO_CONFLICT blocks. */
- set = single_set (insn);
- if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set)))
- {
- if (insn == basic_block_end[b])
- break;
-
- /* Nops get in the way while scheduling, so delete them now if
- register allocation has already been done. It is too risky
- to try to do this before register allocation, and there are
- unlikely to be very many nops then anyways. */
- if (reload_completed)
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
-
- continue;
- }
-
- /* Split insns here to get max fine-grain parallelism. */
- first = PREV_INSN (insn);
- notes = REG_NOTES (insn);
- last = try_split (PATTERN (insn), insn, 1);
- if (last != insn)
- {
- /* try_split returns the NOTE that INSN became. */
- first = NEXT_INSN (first);
- update_flow_info (notes, first, last, insn);
-
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- if (insn == basic_block_head[b])
- basic_block_head[b] = first;
- if (insn == basic_block_end[b])
- {
- basic_block_end[b] = last;
- break;
- }
- }
-
- if (insn == basic_block_end[b])
- break;
- }
-}
-
/* The one entry point in this file. DUMP_FILE is the dump file for
this pass. */
@@ -8431,7 +8521,7 @@ schedule_insns (dump_file)
/* do the splitting first for all blocks */
for (b = 0; b < n_basic_blocks; b++)
- split_block_insns (b);
+ split_block_insns (b, 1);
max_uid = (get_max_uid () + 1);
@@ -8449,12 +8539,12 @@ schedule_insns (dump_file)
luid = 0;
for (b = 0; b < n_basic_blocks; b++)
- for (insn = basic_block_head[b];; insn = NEXT_INSN (insn))
+ for (insn = BLOCK_HEAD (b);; insn = NEXT_INSN (insn))
{
INSN_BLOCK (insn) = b;
INSN_LUID (insn) = luid++;
- if (insn == basic_block_end[b])
+ if (insn == BLOCK_END (b))
break;
}
@@ -8465,7 +8555,7 @@ schedule_insns (dump_file)
rtx insn;
for (b = 0; b < n_basic_blocks; b++)
- for (insn = basic_block_head[b];; insn = NEXT_INSN (insn))
+ for (insn = BLOCK_HEAD (b);; insn = NEXT_INSN (insn))
{
rtx link, prev;
@@ -8487,7 +8577,7 @@ schedule_insns (dump_file)
}
}
- if (insn == basic_block_end[b])
+ if (insn == BLOCK_END (b))
break;
}
}
@@ -8529,7 +8619,7 @@ schedule_insns (dump_file)
/* The scheduler runs after flow; therefore, we can't blindly call
back into find_basic_blocks since doing so could invalidate the
- info in basic_block_live_at_start.
+ info in global_live_at_start.
Consider a block consisting entirely of dead stores; after life
analysis it would be a block of NOTE_INSN_DELETED notes. If
@@ -8620,7 +8710,7 @@ schedule_insns (dump_file)
determine the correct line number for the first insn of the block. */
for (b = 0; b < n_basic_blocks; b++)
- for (line = basic_block_head[b]; line; line = PREV_INSN (line))
+ for (line = BLOCK_HEAD (b); line; line = PREV_INSN (line))
if (GET_CODE (line) == NOTE && NOTE_LINE_NUMBER (line) > 0)
{
line_note_head[b] = line;
@@ -8647,15 +8737,15 @@ schedule_insns (dump_file)
/* ??? Add a NOTE after the last insn of the last basic block. It is not
known why this is done. */
- insn = basic_block_end[n_basic_blocks - 1];
+ insn = BLOCK_END (n_basic_blocks - 1);
if (NEXT_INSN (insn) == 0
|| (GET_CODE (insn) != NOTE
&& GET_CODE (insn) != CODE_LABEL
- /* Don't emit a NOTE if it would end up between an unconditional
- jump and a BARRIER. */
+ /* Don't emit a NOTE if it would end up between an unconditional
+ jump and a BARRIER. */
&& !(GET_CODE (insn) == JUMP_INSN
&& GET_CODE (NEXT_INSN (insn)) == BARRIER)))
- emit_note_after (NOTE_INSN_DELETED, basic_block_end[n_basic_blocks - 1]);
+ emit_note_after (NOTE_INSN_DELETED, BLOCK_END (n_basic_blocks - 1));
/* Schedule every region in the subroutine */
for (rgn = 0; rgn < nr_regions; rgn++)
diff --git a/contrib/gcc/halfpic.c b/contrib/gcc/halfpic.c
index 2c19c55..6233ca9 100644
--- a/contrib/gcc/halfpic.c
+++ b/contrib/gcc/halfpic.c
@@ -1,5 +1,5 @@
/* OSF/rose half-pic support functions.
- Copyright (C) 1992, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern char *xmalloc ();
extern rtx eliminate_constant_term ();
extern void assemble_name ();
extern void output_addr_const ();
@@ -217,10 +216,9 @@ half_pic_encode (decl)
#ifdef HALF_PIC_DEBUG
if (HALF_PIC_DEBUG)
{
- if (HALF_PIC_DEBUG)
- fprintf (stderr, "\n========== Half_pic_encode %.*s\n",
- IDENTIFIER_LENGTH (asm_name),
- IDENTIFIER_POINTER (asm_name));
+ fprintf (stderr, "\n========== Half_pic_encode %.*s\n",
+ IDENTIFIER_LENGTH (asm_name),
+ IDENTIFIER_POINTER (asm_name));
debug_tree (decl);
}
#endif
diff --git a/contrib/gcc/halfpic.h b/contrib/gcc/halfpic.h
index 80e6543..562121e 100644
--- a/contrib/gcc/halfpic.h
+++ b/contrib/gcc/halfpic.h
@@ -1,5 +1,5 @@
/* OSF/rose half-pic support definitions.
- Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,9 +20,7 @@ Boston, MA 02111-1307, USA. */
#ifndef NO_HALF_PIC
-#include "gansidecl.h"
-
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
+#ifdef ANSI_PROTOTYPES
union tree_node; /* forward reference */
struct rtx_def;
#endif
diff --git a/contrib/gcc/hash.c b/contrib/gcc/hash.c
index 1428ae1..f333c6c 100644
--- a/contrib/gcc/hash.c
+++ b/contrib/gcc/hash.c
@@ -1,5 +1,5 @@
/* hash.c -- hash table routines
- Copyright (C) 1993, 94 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1998 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
This file was lifted from BFD, the Binary File Descriptor library.
@@ -16,32 +16,32 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "hash.h"
#include "obstack.h"
-#include "gansidecl.h"
#include "toplev.h"
/* Obstack allocation and deallocation routines. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern char * xmalloc ();
-
/* The default number of entries to use when creating a hash table. */
#define DEFAULT_SIZE (1009)
/* Create a new hash table, given a number of entries. */
boolean
-hash_table_init_n (table, newfunc, size)
+hash_table_init_n (table, newfunc, hash, comp, size)
struct hash_table *table;
struct hash_entry *(*newfunc) PARAMS ((struct hash_entry *,
- struct hash_table *,
- const char *));
+ struct hash_table *,
+ hash_table_key));
+ unsigned long (*hash) PARAMS ((hash_table_key));
+ boolean (*comp) PARAMS ((hash_table_key, hash_table_key));
unsigned int size;
{
unsigned int alloc;
@@ -62,19 +62,23 @@ hash_table_init_n (table, newfunc, size)
memset ((PTR) table->table, 0, alloc);
table->size = size;
table->newfunc = newfunc;
+ table->hash = hash;
+ table->comp = comp;
return true;
}
/* Create a new hash table with the default number of entries. */
boolean
-hash_table_init (table, newfunc)
+hash_table_init (table, newfunc, hash, comp)
struct hash_table *table;
struct hash_entry *(*newfunc) PARAMS ((struct hash_entry *,
- struct hash_table *,
- const char *));
+ struct hash_table *,
+ hash_table_key));
+ unsigned long (*hash) PARAMS ((hash_table_key));
+ boolean (*comp) PARAMS ((hash_table_key, hash_table_key));
{
- return hash_table_init_n (table, newfunc, DEFAULT_SIZE);
+ return hash_table_init_n (table, newfunc, hash, comp, DEFAULT_SIZE);
}
/* Free a hash table. */
@@ -86,33 +90,22 @@ hash_table_free (table)
obstack_free (&table->memory, (PTR) NULL);
}
-/* Look up a string in a hash table. */
+/* Look up KEY in TABLE. If CREATE is non-NULL a new entry is
+ created if one does not previously exist. */
struct hash_entry *
-hash_lookup (table, string, create, copy)
+hash_lookup (table, key, create, copy)
struct hash_table *table;
- const char *string;
+ hash_table_key key;
boolean create;
- boolean copy;
+ hash_table_key (*copy) PARAMS ((struct obstack* memory,
+ hash_table_key key));
{
- register const unsigned char *s;
register unsigned long hash;
- register unsigned int c;
struct hash_entry *hashp;
- unsigned int len;
unsigned int index;
- hash = 0;
- len = 0;
- s = (const unsigned char *) string;
- while ((c = *s++) != '\0')
- {
- hash += c + (c << 17);
- hash ^= hash >> 2;
- ++len;
- }
- hash += len + (len << 17);
- hash ^= hash >> 2;
+ hash = (*table->hash)(key);
index = hash % table->size;
for (hashp = table->table[index];
@@ -120,30 +113,19 @@ hash_lookup (table, string, create, copy)
hashp = hashp->next)
{
if (hashp->hash == hash
- && strcmp (hashp->string, string) == 0)
+ && (*table->comp)(hashp->key, key))
return hashp;
}
if (! create)
return (struct hash_entry *) NULL;
- hashp = (*table->newfunc) ((struct hash_entry *) NULL, table, string);
+ hashp = (*table->newfunc) ((struct hash_entry *) NULL, table, key);
if (hashp == (struct hash_entry *) NULL)
return (struct hash_entry *) NULL;
if (copy)
- {
- char *new;
-
- new = (char *) obstack_alloc (&table->memory, len + 1);
- if (!new)
- {
- error ("no memory");
- return (struct hash_entry *) NULL;
- }
- strcpy (new, string);
- string = new;
- }
- hashp->string = string;
+ key = (*copy) (&table->memory, key);
+ hashp->key = key;
hashp->hash = hash;
hashp->next = table->table[index];
table->table[index] = hashp;
@@ -155,10 +137,10 @@ hash_lookup (table, string, create, copy)
/*ARGSUSED*/
struct hash_entry *
-hash_newfunc (entry, table, string)
+hash_newfunc (entry, table, p)
struct hash_entry *entry;
struct hash_table *table;
- const char *string;
+ hash_table_key p;
{
if (entry == (struct hash_entry *) NULL)
entry = ((struct hash_entry *)
@@ -186,7 +168,7 @@ hash_allocate (table, size)
void
hash_traverse (table, func, info)
struct hash_table *table;
- boolean (*func) PARAMS ((struct hash_entry *, PTR));
+ boolean (*func) PARAMS ((struct hash_entry *, hash_table_key));
PTR info;
{
unsigned int i;
@@ -202,3 +184,62 @@ hash_traverse (table, func, info)
}
}
}
+
+/* Hash a string. Return a hash-code for the string. */
+
+unsigned long
+string_hash (k)
+ hash_table_key k;
+{
+ const unsigned char *s;
+ unsigned long hash;
+ unsigned char c;
+ unsigned int len;
+
+ s = (const unsigned char *) k;
+ hash = 0;
+ len = 0;
+
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ ++len;
+ }
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ return hash;
+}
+
+/* Compare two strings. Return non-zero iff the two strings are
+ the same. */
+
+boolean
+string_compare (k1, k2)
+ hash_table_key k1;
+ hash_table_key k2;
+{
+ return (strcmp ((char*) k1, (char*) k2) == 0);
+}
+
+/* Copy K to OBSTACK. */
+
+hash_table_key
+string_copy (memory, k)
+ struct obstack* memory;
+ hash_table_key k;
+{
+ char *new;
+ char *string = (char*) k;
+
+ new = (char *) obstack_alloc (memory, strlen (string) + 1);
+ if (!new)
+ {
+ error ("no memory");
+ return NULL;
+ }
+ strcpy (new, string);
+
+ return new;
+}
diff --git a/contrib/gcc/hash.h b/contrib/gcc/hash.h
index 5a3838c..ac3b1ed 100644
--- a/contrib/gcc/hash.h
+++ b/contrib/gcc/hash.h
@@ -1,5 +1,5 @@
/* Header file for generic hash table support.
- Copyright (C) 1993, 94 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
This file was lifted from BFD, the Binary File Descriptor library.
@@ -16,38 +16,19 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifdef IN_GCC
-
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
-#define PARAMS(ARGS) PROTO(ARGS)
-
-#ifdef __STDC__
-#define PTR void *
-#else
-#ifndef const
-#define const
-#endif
-#define PTR char *
-#endif
-
-#else /* ! IN_GCC */
+Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef IN_GCC
#include <ansidecl.h>
-#endif /* IN_GCC */
+#endif /* ! IN_GCC */
#include "obstack.h"
typedef enum {false, true} boolean;
+typedef PTR hash_table_key;
+
/* Hash table routines. There is no way to free up a hash table. */
/* An element in the hash table. Most uses will actually use a larger
@@ -57,8 +38,8 @@ struct hash_entry
{
/* Next entry for this hash code. */
struct hash_entry *next;
- /* String being hashed. */
- const char *string;
+ /* The thing being hashed. */
+ hash_table_key key;
/* Hash code. This is the full hash code, not the index into the
table. */
unsigned long hash;
@@ -81,7 +62,11 @@ struct hash_table
only if the argument is NULL. */
struct hash_entry *(*newfunc) PARAMS ((struct hash_entry *,
struct hash_table *,
- const char *));
+ hash_table_key));
+ /* A function to compute the hash code for a key in the hash table. */
+ unsigned long (*hash) PARAMS ((hash_table_key));
+ /* A function to compare two keys. */
+ boolean (*comp) PARAMS ((hash_table_key, hash_table_key));
/* An obstack for this hash table. */
struct obstack memory;
};
@@ -91,31 +76,35 @@ extern boolean hash_table_init
PARAMS ((struct hash_table *,
struct hash_entry *(*) (struct hash_entry *,
struct hash_table *,
- const char *)));
+ hash_table_key),
+ unsigned long (*hash) (hash_table_key),
+ boolean (*comp) (hash_table_key, hash_table_key)));
/* Initialize a hash table specifying a size. */
extern boolean hash_table_init_n
PARAMS ((struct hash_table *,
struct hash_entry *(*) (struct hash_entry *,
struct hash_table *,
- const char *),
+ hash_table_key),
+ unsigned long (*hash) (hash_table_key),
+ boolean (*comp) (hash_table_key, hash_table_key),
unsigned int size));
/* Free up a hash table. */
extern void hash_table_free PARAMS ((struct hash_table *));
-/* Look up a string in a hash table. If CREATE is true, a new entry
- will be created for this string if one does not already exist. The
- COPY argument must be true if this routine should copy the string
- into newly allocated memory when adding an entry. */
+/* Look up KEY in a hash table. If CREATE is true, a new entry
+ will be created for this KEY if one does not already exist. If
+ COPY is non-NULL, it is used to copy the KEY before storing it in
+ the hash table. */
extern struct hash_entry *hash_lookup
- PARAMS ((struct hash_table *, const char *, boolean create,
- boolean copy));
+ PARAMS ((struct hash_table *, hash_table_key key, boolean create,
+ hash_table_key (*copy)(struct obstack*, hash_table_key)));
/* Base method for creating a hash table entry. */
extern struct hash_entry *hash_newfunc
- PARAMS ((struct hash_entry *, struct hash_table *,
- const char *));
+ PARAMS ((struct hash_entry *, struct hash_table *,
+ hash_table_key key));
/* Grab some space for a hash table entry. */
extern PTR hash_allocate PARAMS ((struct hash_table *,
@@ -126,5 +115,17 @@ extern PTR hash_allocate PARAMS ((struct hash_table *,
INFO argument is passed to the function. */
extern void hash_traverse PARAMS ((struct hash_table *,
boolean (*) (struct hash_entry *,
- PTR),
- PTR info));
+ hash_table_key),
+ hash_table_key info));
+
+/* Hash a string K, which is really of type `char*'. */
+extern unsigned long string_hash PARAMS ((hash_table_key k));
+
+/* Compare two strings K1, K2 which are really of type `char*'. */
+extern boolean string_compare PARAMS ((hash_table_key k1,
+ hash_table_key k2));
+
+/* Copy a string K, which is really of type `char*'. */
+extern hash_table_key string_copy PARAMS ((struct obstack* memory,
+ hash_table_key k));
+
diff --git a/contrib/gcc/hwint.h b/contrib/gcc/hwint.h
new file mode 100644
index 0000000..91973b8
--- /dev/null
+++ b/contrib/gcc/hwint.h
@@ -0,0 +1,96 @@
+/* HOST_WIDE_INT definitions for the GNU compiler.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ Provide definitions for macros which depend on HOST_BITS_PER_INT
+ and HOST_BITS_PER_LONG. */
+
+#ifndef __HWINT_H__
+#define __HWINT_H__
+
+/* Only do all of this if both of these macros are defined, otherwise
+ they'll evaluate to zero, which is not what you want. */
+#if defined (HOST_BITS_PER_LONG) && defined (HOST_BITS_PER_INT)
+
+/* 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 /* ! HOST_BITS_PER_WIDE_INT */
+
+
+/* Provide defaults for the way to print a HOST_WIDE_INT
+ in various manners. */
+
+#ifndef HOST_WIDE_INT_PRINT_DEC
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+# define HOST_WIDE_INT_PRINT_DEC "%d"
+# else
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+# define HOST_WIDE_INT_PRINT_DEC "%ld"
+# else
+# define HOST_WIDE_INT_PRINT_DEC "%lld"
+# endif
+# endif
+#endif /* ! HOST_WIDE_INT_PRINT_DEC */
+
+#ifndef HOST_WIDE_INT_PRINT_UNSIGNED
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+# define HOST_WIDE_INT_PRINT_UNSIGNED "%u"
+# else
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+# define HOST_WIDE_INT_PRINT_UNSIGNED "%lu"
+# else
+# define HOST_WIDE_INT_PRINT_UNSIGNED "%llu"
+# endif
+# endif
+#endif /* ! HOST_WIDE_INT_PRINT_UNSIGNED */
+
+#ifndef HOST_WIDE_INT_PRINT_HEX
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+# define HOST_WIDE_INT_PRINT_HEX "0x%x"
+# else
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+# define HOST_WIDE_INT_PRINT_HEX "0x%lx"
+# else
+# define HOST_WIDE_INT_PRINT_HEX "0x%llx"
+# endif
+# endif
+#endif /* ! HOST_WIDE_INT_PRINT_HEX */
+
+#ifndef HOST_WIDE_INT_PRINT_DOUBLE_HEX
+# if HOST_BITS_PER_WIDE_INT == 64
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%016x"
+# else
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%016lx"
+# else
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%016llx"
+# endif
+# endif
+# else
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%08x"
+# else
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%08lx"
+# else
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%08llx"
+# endif
+# endif
+# endif
+#endif /* ! HOST_WIDE_INT_PRINT_DOUBLE_HEX */
+
+#endif /* HOST_BITS_PER_LONG && HOST_BITS_PER_INT */
+
+#endif /* __HWINT_H__ */
diff --git a/contrib/gcc/input.h b/contrib/gcc/input.h
index 7bcde83..5de5cde 100644
--- a/contrib/gcc/input.h
+++ b/contrib/gcc/input.h
@@ -1,6 +1,6 @@
/* Declarations for variables relating to reading the source file.
Used by parsers, lexical analyzers, and error message routines.
- Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/contrib/gcc/integrate.c b/contrib/gcc/integrate.c
index 38a900a..33a96c4 100644
--- a/contrib/gcc/integrate.c
+++ b/contrib/gcc/integrate.c
@@ -1,5 +1,5 @@
/* Procedure integration for GNU CC.
- Copyright (C) 1988, 91, 93-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1988, 91, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "function.h"
#include "toplev.h"
+#include "intl.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
@@ -55,29 +56,46 @@ extern struct obstack *function_maybepermanent_obstack;
all. Assume 1 instruction for the call and 1.5 insns per argument. */
#define INTEGRATE_THRESHOLD(DECL) \
(optimize_size \
- ? (1 + (3 * list_length (DECL_ARGUMENTS (DECL)) / 2)) \
+ ? (1 + (3 * list_length (DECL_ARGUMENTS (DECL))) / 2) \
: (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
#endif
-static rtx initialize_for_inline PROTO((tree, int, int, int, int));
-static void finish_inline PROTO((tree, rtx));
-static void adjust_copied_decl_tree PROTO((tree));
-static tree copy_decl_list PROTO((tree));
-static tree copy_decl_tree PROTO((tree));
-static void copy_decl_rtls PROTO((tree));
-static void save_constants PROTO((rtx *));
-static void note_modified_parmregs PROTO((rtx, rtx));
-static rtx copy_for_inline PROTO((rtx));
-static void integrate_parm_decls PROTO((tree, struct inline_remap *, rtvec));
-static void integrate_decl_tree PROTO((tree, int, struct inline_remap *));
+static rtx initialize_for_inline PROTO((tree, int, int, int, int));
+static void finish_inline PROTO((tree, rtx));
+static void adjust_copied_decl_tree PROTO((tree));
+static tree copy_decl_list PROTO((tree));
+static tree copy_decl_tree PROTO((tree));
+static void copy_decl_rtls PROTO((tree));
+static void save_constants PROTO((rtx *));
+static void note_modified_parmregs PROTO((rtx, rtx));
+static rtx copy_for_inline PROTO((rtx));
+static void integrate_parm_decls PROTO((tree, struct inline_remap *,
+ rtvec));
+static void integrate_decl_tree PROTO((tree, int,
+ struct inline_remap *));
static void save_constants_in_decl_trees PROTO ((tree));
-static void subst_constants PROTO((rtx *, rtx, struct inline_remap *));
-static void restore_constants PROTO((rtx *));
-static void set_block_origin_self PROTO((tree));
-static void set_decl_origin_self PROTO((tree));
-static void set_block_abstract_flags PROTO((tree, int));
+static void subst_constants PROTO((rtx *, rtx,
+ struct inline_remap *));
+static void restore_constants PROTO((rtx *));
+static void set_block_origin_self PROTO((tree));
+static void set_decl_origin_self PROTO((tree));
+static void set_block_abstract_flags PROTO((tree, int));
+static void process_reg_param PROTO((struct inline_remap *, rtx,
+ rtx));
+
+
+void set_decl_abstract_flags PROTO((tree, int));
+static tree copy_and_set_decl_abstract_origin PROTO((tree));
+
+/* The maximum number of instructions accepted for inlining a
+ function. Increasing values mean more agressive inlining.
+ This affects currently only functions explicitly marked as
+ inline (or methods defined within the class definition for C++).
+ The default value of 10000 is arbitrary but high to match the
+ previously unlimited gcc capabilities. */
+
+int inline_max_insns = 10000;
-void set_decl_abstract_flags PROTO((tree, int));
/* Returns the Ith entry in the label_map contained in MAP. If the
Ith entry has not yet been set, return a fresh label. This function
@@ -92,28 +110,32 @@ get_label_from_map (map, i)
rtx x = map->label_map[i];
if (x == NULL_RTX)
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- x = map->label_map[i] = gen_label_rtx();
- pop_obstacks ();
- }
+ x = map->label_map[i] = gen_label_rtx();
return x;
}
/* Zero if the current function (whose FUNCTION_DECL is FNDECL)
is safe and reasonable to integrate into other functions.
- Nonzero means value is a warning message with a single %s
+ Nonzero means value is a warning msgid with a single %s
for the function's name. */
-char *
+const char *
function_cannot_inline_p (fndecl)
register tree fndecl;
{
register rtx insn;
tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
- int max_insns = INTEGRATE_THRESHOLD (fndecl);
+
+ /* For functions marked as inline increase the maximum size to
+ inline_max_insns (-finline-limit-<n>). For regular functions
+ use the limit given by INTEGRATE_THRESHOLD. */
+
+ int max_insns = (DECL_INLINE (fndecl))
+ ? (inline_max_insns
+ + 8 * list_length (DECL_ARGUMENTS (fndecl)))
+ : INTEGRATE_THRESHOLD (fndecl);
+
register int ninsns = 0;
register tree parms;
rtx result;
@@ -121,20 +143,20 @@ function_cannot_inline_p (fndecl)
/* No inlines with varargs. */
if ((last && TREE_VALUE (last) != void_type_node)
|| current_function_varargs)
- return "varargs function cannot be inline";
+ return N_("varargs function cannot be inline");
if (current_function_calls_alloca)
- return "function using alloca cannot be inline";
+ return N_("function using alloca cannot be inline");
if (current_function_contains_functions)
- return "function with nested functions cannot be inline";
+ return N_("function with nested functions cannot be inline");
if (current_function_cannot_inline)
return current_function_cannot_inline;
/* If its not even close, don't even look. */
- if (!DECL_INLINE (fndecl) && get_max_uid () > 3 * max_insns)
- return "function too large to be inline";
+ if (get_max_uid () > 3 * max_insns)
+ return N_("function too large to be inline");
#if 0
/* Don't inline functions which do not specify a function prototype and
@@ -144,35 +166,30 @@ function_cannot_inline_p (fndecl)
if (TYPE_MODE (TREE_TYPE (parms)) == BLKmode)
TREE_ADDRESSABLE (parms) = 1;
if (last == NULL_TREE && TREE_ADDRESSABLE (parms))
- return "no prototype, and parameter address used; cannot be inline";
+ return N_("no prototype, and parameter address used; cannot be inline");
}
#endif
/* We can't inline functions that return structures
the old-fashioned PCC way, copying into a static block. */
if (current_function_returns_pcc_struct)
- return "inline functions not supported for this return value type";
-
- /* We can't inline functions that return BLKmode structures in registers. */
- if (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
- && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
- return "inline functions not supported for this return value type";
+ return N_("inline functions not supported for this return value type");
/* We can't inline functions that return structures of varying size. */
if (int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
- return "function with varying-size return value cannot be inline";
+ return N_("function with varying-size return value cannot be inline");
/* 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))
{
if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
- return "function with varying-size parameter cannot be inline";
+ return N_("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";
+ return N_("function with transparent unit parameter cannot be inline");
}
- if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns)
+ if (get_max_uid () > max_insns)
{
for (ninsns = 0, insn = get_first_nonparm_insn ();
insn && ninsns < max_insns;
@@ -181,22 +198,18 @@ function_cannot_inline_p (fndecl)
ninsns++;
if (ninsns >= max_insns)
- return "function too large to be inline";
+ return N_("function too large to be inline");
}
- /* We cannot inline this function if forced_labels is non-zero. This
- implies that a label in this function was used as an initializer.
- Because labels can not be duplicated, all labels in the function
- will be renamed when it is inlined. However, there is no way to find
- and fix all variables initialized with addresses of labels in this
- function, hence inlining is impossible. */
-
- if (forced_labels)
- return "function with label addresses used in initializers cannot inline";
+ /* We will not inline a function which uses computed goto. The addresses of
+ its local labels, which may be tucked into global storage, are of course
+ not constant across instantiations, which causes unexpected behaviour. */
+ if (current_function_has_computed_jump)
+ return N_("function with computed jump cannot inline");
/* We cannot inline a nested function that jumps to a nonlocal label. */
if (current_function_has_nonlocal_goto)
- return "function with nonlocal goto cannot be inline";
+ return N_("function with nonlocal goto cannot be inline");
/* This is a hack, until the inliner is taught about eh regions at
the start of the function. */
@@ -208,13 +221,13 @@ function_cannot_inline_p (fndecl)
{
if (insn && GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
- return "function with complex parameters cannot be inline";
+ return N_("function with complex parameters cannot be inline");
}
/* We can't inline functions that return a PARALLEL rtx. */
result = DECL_RTL (DECL_RESULT (fndecl));
if (result && GET_CODE (result) == PARALLEL)
- return "inline functions not supported for this return value type";
+ return N_("inline functions not supported for this return value type");
return 0;
}
@@ -263,6 +276,16 @@ static rtvec copy_asm_constraints_vector;
/* In save_for_inline, nonzero if past the parm-initialization insns. */
static int in_nonparm_insns;
+/* subroutines passed to duplicate_eh_handlers to map exception labels */
+
+static rtx
+save_for_inline_eh_labelmap (label)
+ rtx label;
+{
+ int index = CODE_LABEL_NUMBER (label);
+ return label_map[index];
+}
+
/* Subroutine for `save_for_inline{copying,nocopy}'. Performs initialization
needed to save FNDECL's insns and info for future inline expansion. */
@@ -285,12 +308,16 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
+ current_function_calls_setjmp * FUNCTION_FLAGS_CALLS_SETJMP
+ current_function_calls_longjmp * FUNCTION_FLAGS_CALLS_LONGJMP
+ current_function_returns_struct * FUNCTION_FLAGS_RETURNS_STRUCT
- + current_function_returns_pcc_struct * FUNCTION_FLAGS_RETURNS_PCC_STRUCT
+ + (current_function_returns_pcc_struct
+ * FUNCTION_FLAGS_RETURNS_PCC_STRUCT)
+ current_function_needs_context * FUNCTION_FLAGS_NEEDS_CONTEXT
- + current_function_has_nonlocal_label * FUNCTION_FLAGS_HAS_NONLOCAL_LABEL
+ + (current_function_has_nonlocal_label
+ * FUNCTION_FLAGS_HAS_NONLOCAL_LABEL)
+ current_function_returns_pointer * FUNCTION_FLAGS_RETURNS_POINTER
+ current_function_uses_const_pool * FUNCTION_FLAGS_USES_CONST_POOL
- + current_function_uses_pic_offset_table * FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE);
+ + (current_function_uses_pic_offset_table
+ * FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
+ + current_function_has_computed_jump * FUNCTION_FLAGS_HAS_COMPUTED_JUMP);
/* Clear out PARMDECL_MAP. It was allocated in the caller's frame. */
bzero ((char *) parmdecl_map, max_parm_reg * sizeof (tree));
@@ -560,10 +587,7 @@ save_for_inline_copying (fndecl)
regno_reg_rtx = reg_map;
/* Put copies of all the virtual register rtx into the new regno_reg_rtx. */
- regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
- regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
- regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
- regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
+ init_virtual_regs ();
/* Likewise each label rtx must have a unique rtx as its copy. */
@@ -668,19 +692,8 @@ save_for_inline_copying (fndecl)
/* we have to duplicate the handlers for the original */
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
- {
- handler_info *ptr, *temp;
- int nr;
- nr = new_eh_region_entry (new_region);
- ptr = get_first_handler (NOTE_BLOCK_NUMBER (copy));
- for ( ; ptr; ptr = ptr->next)
- {
- temp = get_new_handler (
- label_map[CODE_LABEL_NUMBER (ptr->handler_label)],
- ptr->type_info);
- add_new_handler (nr, temp);
- }
- }
+ duplicate_eh_handlers (NOTE_BLOCK_NUMBER (copy), new_region,
+ save_for_inline_eh_labelmap);
/* We have to forward these both to match the new exception
region. */
@@ -752,11 +765,30 @@ save_for_inline_copying (fndecl)
free (label_map);
}
+/* Copy NODE (as with copy_node). NODE must be a DECL. Set the
+ DECL_ABSTRACT_ORIGIN for the new accordinly. */
+
+static tree
+copy_and_set_decl_abstract_origin (node)
+ tree node;
+{
+ tree copy = copy_node (node);
+ if (DECL_ABSTRACT_ORIGIN (copy) != NULL_TREE)
+ /* That means that NODE already had a DECL_ABSTRACT_ORIGIN. (This
+ situation occurs if we inline a function which itself made
+ calls to inline functions.) Since DECL_ABSTRACT_ORIGIN is the
+ most distant ancestor, we don't have to do anything here. */
+ ;
+ else
+ /* The most distant ancestor must be NODE. */
+ DECL_ABSTRACT_ORIGIN (copy) = node;
+
+ return copy;
+}
+
/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
For example, this can copy a list made of TREE_LIST nodes. While copying,
- for each node copied which doesn't already have is DECL_ABSTRACT_ORIGIN
- set to some non-zero value, set the DECL_ABSTRACT_ORIGIN of the copy to
- point to the corresponding (abstract) original node. */
+ set DECL_ABSTRACT_ORIGIN appropriately. */
static tree
copy_decl_list (list)
@@ -768,17 +800,13 @@ copy_decl_list (list)
if (list == 0)
return 0;
- head = prev = copy_node (list);
- if (DECL_ABSTRACT_ORIGIN (head) == NULL_TREE)
- DECL_ABSTRACT_ORIGIN (head) = list;
+ head = prev = copy_and_set_decl_abstract_origin (list);
next = TREE_CHAIN (list);
while (next)
{
register tree copy;
- copy = copy_node (next);
- if (DECL_ABSTRACT_ORIGIN (copy) == NULL_TREE)
- DECL_ABSTRACT_ORIGIN (copy) = next;
+ copy = copy_and_set_decl_abstract_origin (next);
TREE_CHAIN (prev) = copy;
prev = copy;
next = TREE_CHAIN (next);
@@ -1061,11 +1089,15 @@ copy_for_inline (orig)
{
case QUEUED:
case CONST_INT:
- case SYMBOL_REF:
case PC:
case CC0:
return x;
+ case SYMBOL_REF:
+ if (! SYMBOL_REF_NEED_ADJUST (x))
+ return x;
+ return rethrow_symbol_map (x, save_for_inline_eh_labelmap);
+
case CONST_DOUBLE:
/* We have to make a new CONST_DOUBLE to ensure that we account for
it correctly. Using the old CONST_DOUBLE_MEM data is wrong. */
@@ -1283,8 +1315,7 @@ copy_for_inline (orig)
with a function called from note_stores. Be *very* careful that this
is used properly in the presence of recursion. */
-rtx *global_const_equiv_map;
-int global_const_equiv_map_size;
+varray_type global_const_equiv_varray;
#define FIXED_BASE_PLUS_P(X) \
(GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
@@ -1292,6 +1323,46 @@ int global_const_equiv_map_size;
&& REGNO (XEXP (X, 0)) >= FIRST_VIRTUAL_REGISTER \
&& REGNO (XEXP (X, 0)) <= LAST_VIRTUAL_REGISTER)
+/* Called to set up a mapping for the case where a parameter is in a
+ register. If it is read-only and our argument is a constant, set up the
+ constant equivalence.
+
+ If LOC is REG_USERVAR_P, the usual case, COPY must also have that flag set
+ if it is a register.
+
+ Also, don't allow hard registers here; they might not be valid when
+ substituted into insns. */
+static void
+process_reg_param (map, loc, copy)
+ struct inline_remap *map;
+ rtx loc, copy;
+{
+ if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
+ || (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
+ && ! REG_USERVAR_P (copy))
+ || (GET_CODE (copy) == REG
+ && REGNO (copy) < FIRST_PSEUDO_REGISTER))
+ {
+ rtx temp = copy_to_mode_reg (GET_MODE (loc), copy);
+ REG_USERVAR_P (temp) = REG_USERVAR_P (loc);
+ if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
+ SET_CONST_EQUIV_DATA (map, temp, copy, CONST_AGE_PARM);
+ copy = temp;
+ }
+ map->reg_map[REGNO (loc)] = copy;
+}
+
+/* Used by duplicate_eh_handlers to map labels for the exception table */
+static struct inline_remap *eif_eh_map;
+
+static rtx
+expand_inline_function_eh_labelmap (label)
+ rtx label;
+{
+ int index = CODE_LABEL_NUMBER (label);
+ return get_label_from_map (eif_eh_map, index);
+}
+
/* Integrate the procedure defined by FNDECL. Note that this function
may wind up calling itself. Since the static variables are not
reentrant, we do not assign them until after the possibility
@@ -1330,7 +1401,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
rtx loc;
rtx stack_save = 0;
rtx temp;
- struct inline_remap *map;
+ struct inline_remap *map = 0;
#ifdef HAVE_cc0
rtx cc0_insn = 0;
#endif
@@ -1416,7 +1487,8 @@ expand_inline_function (fndecl, parms, target, ignore, type,
rtx stack_slot
= assign_stack_temp (TYPE_MODE (TREE_TYPE (arg)),
int_size_in_bytes (TREE_TYPE (arg)), 1);
- MEM_IN_STRUCT_P (stack_slot) = AGGREGATE_TYPE_P (TREE_TYPE (arg));
+ MEM_SET_IN_STRUCT_P (stack_slot,
+ AGGREGATE_TYPE_P (TREE_TYPE (arg)));
store_expr (arg, stack_slot, 0);
@@ -1491,30 +1563,25 @@ expand_inline_function (fndecl, parms, target, ignore, type,
map->integrating = 1;
- /* const_equiv_map maps pseudos in our routine to constants, so it needs to
- be large enough for all our pseudos. This is the number we are currently
- using plus the number in the called routine, plus 15 for each arg,
- five to compute the virtual frame pointer, and five for the return value.
- This should be enough for most cases. We do not reference entries
- outside the range of the map.
+ /* const_equiv_varray maps pseudos in our routine to constants, so
+ it needs to be large enough for all our pseudos. This is the
+ number we are currently using plus the number in the called
+ routine, plus 15 for each arg, five to compute the virtual frame
+ pointer, and five for the return value. This should be enough
+ for most cases. We do not reference entries outside the range of
+ the map.
??? These numbers are quite arbitrary and were obtained by
experimentation. At some point, we should try to allocate the
table after all the parameters are set up so we an more accurately
estimate the number of pseudos we will need. */
- map->const_equiv_map_size
- = max_reg_num () + (max_regno - FIRST_PSEUDO_REGISTER) + 15 * nargs + 10;
-
- map->const_equiv_map
- = (rtx *)alloca (map->const_equiv_map_size * sizeof (rtx));
- bzero ((char *) map->const_equiv_map,
- map->const_equiv_map_size * sizeof (rtx));
-
- map->const_age_map
- = (unsigned *)alloca (map->const_equiv_map_size * sizeof (unsigned));
- bzero ((char *) map->const_age_map,
- map->const_equiv_map_size * sizeof (unsigned));
+ VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray,
+ (max_reg_num ()
+ + (max_regno - FIRST_PSEUDO_REGISTER)
+ + 15 * nargs
+ + 10),
+ "expand_inline_function");
map->const_age = 0;
/* Record the current insn in case we have to set up pointers to frame
@@ -1583,12 +1650,8 @@ expand_inline_function (fndecl, parms, target, ignore, type,
if (GET_CODE (copy) != REG)
{
temp = copy_addr_to_reg (copy);
- if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
- && REGNO (temp) < map->const_equiv_map_size)
- {
- map->const_equiv_map[REGNO (temp)] = copy;
- map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
- }
+ if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
+ SET_CONST_EQUIV_DATA (map, temp, copy, CONST_AGE_PARM);
copy = temp;
}
map->reg_map[REGNO (XEXP (loc, 0))] = copy;
@@ -1602,87 +1665,16 @@ expand_inline_function (fndecl, parms, target, ignore, type,
;
}
else if (GET_CODE (loc) == REG)
- {
- /* This is the good case where the parameter is in a register.
- If it is read-only and our argument is a constant, set up the
- constant equivalence.
-
- If LOC is REG_USERVAR_P, the usual case, COPY must also have
- that flag set if it is a register.
-
- Also, don't allow hard registers here; they might not be valid
- when substituted into insns. */
-
- if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
- || (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
- && ! REG_USERVAR_P (copy))
- || (GET_CODE (copy) == REG
- && REGNO (copy) < FIRST_PSEUDO_REGISTER))
- {
- temp = copy_to_mode_reg (GET_MODE (loc), copy);
- REG_USERVAR_P (temp) = REG_USERVAR_P (loc);
- if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
- && REGNO (temp) < map->const_equiv_map_size)
- {
- map->const_equiv_map[REGNO (temp)] = copy;
- map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
- }
- copy = temp;
- }
- map->reg_map[REGNO (loc)] = copy;
- }
+ process_reg_param (map, loc, copy);
else if (GET_CODE (loc) == CONCAT)
{
- /* This is the good case where the parameter is in a
- pair of separate pseudos.
- If it is read-only and our argument is a constant, set up the
- constant equivalence.
-
- If LOC is REG_USERVAR_P, the usual case, COPY must also have
- that flag set if it is a register.
-
- Also, don't allow hard registers here; they might not be valid
- when substituted into insns. */
rtx locreal = gen_realpart (GET_MODE (XEXP (loc, 0)), loc);
rtx locimag = gen_imagpart (GET_MODE (XEXP (loc, 0)), loc);
rtx copyreal = gen_realpart (GET_MODE (locreal), copy);
rtx copyimag = gen_imagpart (GET_MODE (locimag), copy);
- if ((GET_CODE (copyreal) != REG && GET_CODE (copyreal) != SUBREG)
- || (GET_CODE (copyreal) == REG && REG_USERVAR_P (locreal)
- && ! REG_USERVAR_P (copyreal))
- || (GET_CODE (copyreal) == REG
- && REGNO (copyreal) < FIRST_PSEUDO_REGISTER))
- {
- temp = copy_to_mode_reg (GET_MODE (locreal), copyreal);
- REG_USERVAR_P (temp) = REG_USERVAR_P (locreal);
- if ((CONSTANT_P (copyreal) || FIXED_BASE_PLUS_P (copyreal))
- && REGNO (temp) < map->const_equiv_map_size)
- {
- map->const_equiv_map[REGNO (temp)] = copyreal;
- map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
- }
- copyreal = temp;
- }
- map->reg_map[REGNO (locreal)] = copyreal;
-
- if ((GET_CODE (copyimag) != REG && GET_CODE (copyimag) != SUBREG)
- || (GET_CODE (copyimag) == REG && REG_USERVAR_P (locimag)
- && ! REG_USERVAR_P (copyimag))
- || (GET_CODE (copyimag) == REG
- && REGNO (copyimag) < FIRST_PSEUDO_REGISTER))
- {
- temp = copy_to_mode_reg (GET_MODE (locimag), copyimag);
- REG_USERVAR_P (temp) = REG_USERVAR_P (locimag);
- if ((CONSTANT_P (copyimag) || FIXED_BASE_PLUS_P (copyimag))
- && REGNO (temp) < map->const_equiv_map_size)
- {
- map->const_equiv_map[REGNO (temp)] = copyimag;
- map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
- }
- copyimag = temp;
- }
- map->reg_map[REGNO (locimag)] = copyimag;
+ process_reg_param (map, locreal, copyreal);
+ process_reg_param (map, locimag, copyimag);
}
else
abort ();
@@ -1724,46 +1716,60 @@ expand_inline_function (fndecl, parms, target, ignore, type,
map->inline_target = 0;
loc = DECL_RTL (DECL_RESULT (fndecl));
+
if (TYPE_MODE (type) == VOIDmode)
/* There is no return value to worry about. */
;
else if (GET_CODE (loc) == MEM)
{
- if (! structure_value_addr || ! aggregate_value_p (DECL_RESULT (fndecl)))
- abort ();
+ if (GET_CODE (XEXP (loc, 0)) == ADDRESSOF)
+ {
+ temp = copy_rtx_and_substitute (loc, map);
+ subst_constants (&temp, NULL_RTX, map);
+ apply_change_group ();
+ target = temp;
+ }
+ else
+ {
+ if (! structure_value_addr
+ || ! aggregate_value_p (DECL_RESULT (fndecl)))
+ abort ();
- /* Pass the function the address in which to return a structure value.
- Note that a constructor can cause someone to call us with
- STRUCTURE_VALUE_ADDR, but the initialization takes place
- via the first parameter, rather than the struct return address.
+ /* Pass the function the address in which to return a structure
+ value. Note that a constructor can cause someone to call us
+ with STRUCTURE_VALUE_ADDR, but the initialization takes place
+ via the first parameter, rather than the struct return address.
- We have two cases: If the address is a simple register indirect,
- use the mapping mechanism to point that register to our structure
- return address. Otherwise, store the structure return value into
- the place that it will be referenced from. */
+ We have two cases: If the address is a simple register
+ indirect, use the mapping mechanism to point that register to
+ our structure return address. Otherwise, store the structure
+ return value into the place that it will be referenced from. */
- if (GET_CODE (XEXP (loc, 0)) == REG)
- {
- temp = force_reg (Pmode,
- force_operand (structure_value_addr, NULL_RTX));
- map->reg_map[REGNO (XEXP (loc, 0))] = temp;
- if ((CONSTANT_P (structure_value_addr)
- || GET_CODE (structure_value_addr) == ADDRESSOF
- || (GET_CODE (structure_value_addr) == PLUS
- && XEXP (structure_value_addr, 0) == virtual_stack_vars_rtx
- && GET_CODE (XEXP (structure_value_addr, 1)) == CONST_INT))
- && REGNO (temp) < map->const_equiv_map_size)
+ if (GET_CODE (XEXP (loc, 0)) == REG)
{
- map->const_equiv_map[REGNO (temp)] = structure_value_addr;
- map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
+ temp = force_operand (structure_value_addr, NULL_RTX);
+ temp = force_reg (Pmode, temp);
+ map->reg_map[REGNO (XEXP (loc, 0))] = temp;
+
+ if (CONSTANT_P (structure_value_addr)
+ || GET_CODE (structure_value_addr) == ADDRESSOF
+ || (GET_CODE (structure_value_addr) == PLUS
+ && (XEXP (structure_value_addr, 0)
+ == virtual_stack_vars_rtx)
+ && (GET_CODE (XEXP (structure_value_addr, 1))
+ == CONST_INT)))
+ {
+ SET_CONST_EQUIV_DATA (map, temp, structure_value_addr,
+ CONST_AGE_PARM);
+ }
+ }
+ else
+ {
+ temp = copy_rtx_and_substitute (loc, map);
+ subst_constants (&temp, NULL_RTX, map);
+ apply_change_group ();
+ emit_move_insn (temp, structure_value_addr);
}
- }
- else
- {
- temp = copy_rtx_and_substitute (loc, map);
- subst_constants (&temp, NULL_RTX, map);
- apply_change_group ();
- emit_move_insn (temp, structure_value_addr);
}
}
else if (ignore)
@@ -1791,7 +1797,23 @@ expand_inline_function (fndecl, parms, target, ignore, type,
Let the combiner substitute the MEM if that is valid. */
if (target == 0 || GET_CODE (target) != REG
|| GET_MODE (target) != departing_mode)
+ {
+ /* Don't make BLKmode registers. If this looks like
+ a BLKmode object being returned in a register, get
+ the mode from that, otherwise abort. */
+ if (departing_mode == BLKmode)
+ {
+ if (REG == GET_CODE (DECL_RTL (DECL_RESULT (fndecl))))
+ {
+ departing_mode = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
+ arriving_mode = departing_mode;
+ }
+ else
+ abort();
+ }
+
target = gen_reg_rtx (departing_mode);
+ }
/* If function's value was promoted before return,
avoid machine mode mismatch when we substitute INLINE_TARGET.
@@ -1841,10 +1863,9 @@ expand_inline_function (fndecl, parms, target, ignore, type,
/* Clean up stack so that variables might have smaller offsets. */
do_pending_stack_adjust ();
- /* Save a copy of the location of const_equiv_map for mark_stores, called
- via note_stores. */
- global_const_equiv_map = map->const_equiv_map;
- global_const_equiv_map_size = map->const_equiv_map_size;
+ /* Save a copy of the location of const_equiv_varray for
+ mark_stores, called via note_stores. */
+ global_const_equiv_varray = map->const_equiv_varray;
/* If the called function does an alloca, save and restore the
stack pointer around the call. This saves stack space, but
@@ -2028,7 +2049,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
/* Be lazy and assume CALL_INSNs clobber all hard registers. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- map->const_equiv_map[i] = 0;
+ VARRAY_CONST_EQUIV (map->const_equiv_varray, i).rtx = 0;
break;
case CODE_LABEL:
@@ -2064,17 +2085,12 @@ expand_inline_function (fndecl, parms, target, ignore, type,
/* we have to duplicate the handlers for the original */
if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG)
{
- handler_info *ptr, *temp;
- int nr;
- nr = new_eh_region_entry (CODE_LABEL_NUMBER (label));
- ptr = get_first_handler (NOTE_BLOCK_NUMBER (copy));
- for ( ; ptr; ptr = ptr->next)
- {
- temp = get_new_handler ( get_label_from_map (map,
- CODE_LABEL_NUMBER (ptr->handler_label)),
- ptr->type_info);
- add_new_handler (nr, temp);
- }
+ /* We need to duplicate the handlers for the EH region
+ and we need to indicate where the label map is */
+ eif_eh_map = map;
+ duplicate_eh_handlers (NOTE_BLOCK_NUMBER (copy),
+ CODE_LABEL_NUMBER (label),
+ expand_inline_function_eh_labelmap);
}
/* We have to forward these both to match the new exception
@@ -2151,17 +2167,25 @@ expand_inline_function (fndecl, parms, target, ignore, type,
emit_line_note (input_filename, lineno);
+ /* If the function returns a BLKmode object in a register, copy it
+ out of the temp register into a BLKmode memory object. */
+ if (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
+ && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+ target = copy_blkmode_from_reg (0, target, TREE_TYPE (TREE_TYPE (fndecl)));
+
if (structure_value_addr)
{
target = gen_rtx_MEM (TYPE_MODE (type),
memory_address (TYPE_MODE (type),
structure_value_addr));
- MEM_IN_STRUCT_P (target) = 1;
+ MEM_SET_IN_STRUCT_P (target, 1);
}
/* Make sure we free the things we explicitly allocated with xmalloc. */
if (real_label_map)
free (real_label_map);
+ if (map)
+ VARRAY_FREE (map->const_equiv_varray);
return target;
}
@@ -2192,7 +2216,7 @@ integrate_parm_decls (args, map, arg_vector)
/* These args would always appear unused, if not for this. */
TREE_USED (decl) = 1;
/* Prevent warning for shadowing with these. */
- DECL_ABSTRACT_ORIGIN (decl) = tail;
+ DECL_ABSTRACT_ORIGIN (decl) = DECL_ORIGIN (tail);
pushdecl (decl);
/* Fully instantiate the address with the equivalent form so that the
debugging information contains the actual register, instead of the
@@ -2231,7 +2255,7 @@ integrate_decl_tree (let, level, map)
push_obstacks_nochange ();
saveable_allocation ();
- d = copy_node (t);
+ d = copy_and_set_decl_abstract_origin (t);
pop_obstacks ();
if (DECL_RTL (t) != 0)
@@ -2246,8 +2270,6 @@ integrate_decl_tree (let, level, map)
}
/* These args would always appear unused, if not for this. */
TREE_USED (d) = 1;
- /* Prevent warning for shadowing with these. */
- DECL_ABSTRACT_ORIGIN (d) = t;
if (DECL_LANG_SPECIFIC (d))
copy_lang_decl (d);
@@ -2367,11 +2389,7 @@ copy_rtx_and_substitute (orig, map)
STACK_BOUNDARY / BITS_PER_UNIT);
#endif
- if (REGNO (temp) < map->const_equiv_map_size)
- {
- map->const_equiv_map[REGNO (temp)] = loc;
- map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
- }
+ SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
seq = gen_sequence ();
end_sequence ();
@@ -2402,11 +2420,7 @@ copy_rtx_and_substitute (orig, map)
STACK_BOUNDARY / BITS_PER_UNIT);
#endif
- if (REGNO (temp) < map->const_equiv_map_size)
- {
- map->const_equiv_map[REGNO (temp)] = loc;
- map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
- }
+ SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
seq = gen_sequence ();
end_sequence ();
@@ -2417,12 +2431,13 @@ copy_rtx_and_substitute (orig, map)
{
/* This is a reference to the function return value. If
the function doesn't have a return value, error. If the
- mode doesn't agree, make a SUBREG. */
+ mode doesn't agree, and it ain't BLKmode, make a SUBREG. */
if (map->inline_target == 0)
/* Must be unrolling loops or replicating code if we
reach here, so return the register unchanged. */
return orig;
- else if (mode != GET_MODE (map->inline_target))
+ else if (GET_MODE (map->inline_target) != BLKmode
+ && mode != GET_MODE (map->inline_target))
return gen_lowpart (mode, map->inline_target);
else
return map->inline_target;
@@ -2450,7 +2465,17 @@ copy_rtx_and_substitute (orig, map)
return gen_rtx_SUBREG (GET_MODE (orig), SUBREG_REG (copy),
SUBREG_WORD (orig) + SUBREG_WORD (copy));
else if (GET_CODE (copy) == CONCAT)
- return (subreg_realpart_p (orig) ? XEXP (copy, 0) : XEXP (copy, 1));
+ {
+ rtx retval = subreg_realpart_p (orig) ? XEXP (copy, 0) : XEXP (copy, 1);
+
+ if (GET_MODE (retval) == GET_MODE (orig))
+ return retval;
+ else
+ return gen_rtx_SUBREG (GET_MODE (orig), retval,
+ (SUBREG_WORD (orig) %
+ (GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (orig)))
+ / (unsigned) UNITS_PER_WORD)));
+ }
else
return gen_rtx_SUBREG (GET_MODE (orig), copy,
SUBREG_WORD (orig));
@@ -2537,6 +2562,13 @@ copy_rtx_and_substitute (orig, map)
map)),
0);
}
+ else
+ if (SYMBOL_REF_NEED_ADJUST (orig))
+ {
+ eif_eh_map = map;
+ return rethrow_symbol_map (orig,
+ expand_inline_function_eh_labelmap);
+ }
return orig;
@@ -2670,7 +2702,7 @@ copy_rtx_and_substitute (orig, map)
copy_rtx_and_substitute (SET_DEST (orig), map);
equiv_reg = map->reg_map[REGNO (SET_DEST (orig))];
- equiv_loc = map->const_equiv_map[REGNO (equiv_reg)];
+ equiv_loc = VARRAY_CONST_EQUIV (map->const_equiv_varray, REGNO (equiv_reg)).rtx;
loc_offset
= GET_CODE (equiv_loc) == REG ? 0 : INTVAL (XEXP (equiv_loc, 1));
return gen_rtx_SET (VOIDmode, SET_DEST (orig),
@@ -2686,8 +2718,7 @@ copy_rtx_and_substitute (orig, map)
copy = rtx_alloc (MEM);
PUT_MODE (copy, mode);
XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (orig, 0), map);
- MEM_IN_STRUCT_P (copy) = MEM_IN_STRUCT_P (orig);
- MEM_VOLATILE_P (copy) = MEM_VOLATILE_P (orig);
+ MEM_COPY_ATTRIBUTES (copy, orig);
MEM_ALIAS_SET (copy) = MEM_ALIAS_SET (orig);
/* If doing function inlining, this MEM might not be const in the
@@ -2797,16 +2828,15 @@ try_constants (insn, map)
{
int regno = REGNO (map->equiv_sets[i].dest);
- if (regno < map->const_equiv_map_size
- && (map->const_equiv_map[regno] == 0
- /* Following clause is a hack to make case work where GNU C++
- reassigns a variable to make cse work right. */
- || ! rtx_equal_p (map->const_equiv_map[regno],
- map->equiv_sets[i].equiv)))
- {
- map->const_equiv_map[regno] = map->equiv_sets[i].equiv;
- map->const_age_map[regno] = map->const_age;
- }
+ MAYBE_EXTEND_CONST_EQUIV_VARRAY (map, regno);
+ if (VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).rtx == 0
+ /* Following clause is a hack to make case work where GNU C++
+ reassigns a variable to make cse work right. */
+ || ! rtx_equal_p (VARRAY_CONST_EQUIV (map->const_equiv_varray,
+ regno).rtx,
+ map->equiv_sets[i].equiv))
+ SET_CONST_EQUIV_DATA (map, map->equiv_sets[i].dest,
+ map->equiv_sets[i].equiv, map->const_age);
}
else if (map->equiv_sets[i].dest == pc_rtx)
map->last_pc_value = map->equiv_sets[i].equiv;
@@ -2842,7 +2872,7 @@ subst_constants (loc, insn, map)
register char *format_ptr;
int num_changes = num_validated_changes ();
rtx new = 0;
- enum machine_mode op0_mode;
+ enum machine_mode op0_mode = MAX_MACHINE_MODE;
code = GET_CODE (x);
@@ -2876,12 +2906,14 @@ subst_constants (loc, insn, map)
hard regs used as user variables with constants. */
{
int regno = REGNO (x);
+ struct const_equiv_data *p;
if (! (regno < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
- && regno < map->const_equiv_map_size
- && map->const_equiv_map[regno] != 0
- && map->const_age_map[regno] >= map->const_age)
- validate_change (insn, loc, map->const_equiv_map[regno], 1);
+ && regno < VARRAY_SIZE (map->const_equiv_varray)
+ && (p = &VARRAY_CONST_EQUIV (map->const_equiv_varray, regno),
+ p->rtx != 0)
+ && p->age >= map->const_age)
+ validate_change (insn, loc, p->rtx, 1);
return;
}
@@ -3054,6 +3086,8 @@ subst_constants (loc, insn, map)
switch (GET_RTX_CLASS (code))
{
case '1':
+ if (op0_mode == MAX_MACHINE_MODE)
+ abort ();
new = simplify_unary_operation (code, GET_MODE (x),
XEXP (x, 0), op0_mode);
break;
@@ -3082,6 +3116,8 @@ subst_constants (loc, insn, map)
case 'b':
case '3':
+ if (op0_mode == MAX_MACHINE_MODE)
+ abort ();
new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
XEXP (x, 0), XEXP (x, 1), XEXP (x, 2));
break;
@@ -3124,8 +3160,8 @@ mark_stores (dest, x)
if (regno != VIRTUAL_INCOMING_ARGS_REGNUM
&& regno != VIRTUAL_STACK_VARS_REGNUM)
for (i = regno; i <= last_reg; i++)
- if (i < global_const_equiv_map_size)
- global_const_equiv_map[i] = 0;
+ if (i < VARRAY_SIZE (global_const_equiv_varray))
+ VARRAY_CONST_EQUIV (global_const_equiv_varray, i).rtx = 0;
}
}
@@ -3370,6 +3406,9 @@ output_inline_function (fndecl)
stack_slot_list = STACK_SLOT_LIST (head);
forced_labels = FORCED_LABELS (head);
+ if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_HAS_COMPUTED_JUMP)
+ current_function_has_computed_jump = 1;
+
if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_ALLOCA)
current_function_calls_alloca = 1;
diff --git a/contrib/gcc/integrate.h b/contrib/gcc/integrate.h
index 23e2e56..0382559 100644
--- a/contrib/gcc/integrate.h
+++ b/contrib/gcc/integrate.h
@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "varray.h"
+
/* This structure is used to remap objects in the function being inlined to
those belonging to the calling function. It is passed by
expand_inline_function to its children.
@@ -67,19 +69,15 @@ struct inline_remap
pseudos that contain pointers into the replacement area allocated for
this inline instance. These pseudos are then marked as being equivalent
to the appropriate address and substituted if valid. */
- rtx *const_equiv_map;
- /* Number of entries in const_equiv_map and const_arg_map. */
- int const_equiv_map_size;
+ varray_type const_equiv_varray;
/* This is incremented for each new basic block.
- It is used to store in const_age_map to record the domain of validity
- of each entry in const_equiv_map.
+ It is used to store in the age field to record the domain of validity
+ of each entry in const_equiv_varray.
A value of -1 indicates an entry for a reg which is a parm.
All other values are "positive". */
#define CONST_AGE_PARM (-1)
unsigned int const_age;
- /* In parallel with const_equiv_map, record the valid age for each entry.
- The entry is invalid if its age is less than const_age. */
- unsigned int *const_age_map;
+
/* Target of the inline function being expanded, or NULL if none. */
rtx inline_target;
/* When an insn is being copied by copy_rtx_and_substitute,
@@ -128,9 +126,29 @@ extern rtx get_label_from_map PROTO((struct inline_remap *, int));
/* Set the label indicated. */
#define set_label_in_map(MAP, I, X) ((MAP)->label_map[I] = (X))
-/* Unfortunately, we need a global copy of const_equiv map for communication
- with a function called from note_stores. Be *very* careful that this
- is used properly in the presence of recursion. */
-
-extern rtx *global_const_equiv_map;
-extern int global_const_equiv_map_size;
+/* Unfortunately, we need a global copy of const_equiv varray for
+ communication with a function called from note_stores. Be *very*
+ careful that this is used properly in the presence of recursion. */
+
+extern varray_type global_const_equiv_varray;
+
+#define MAYBE_EXTEND_CONST_EQUIV_VARRAY(MAP,MAX) \
+ { \
+ if ((MAX) >= VARRAY_SIZE ((MAP)->const_equiv_varray)) \
+ { \
+ int is_global = (global_const_equiv_varray \
+ == (MAP)->const_equiv_varray); \
+ VARRAY_GROW ((MAP)->const_equiv_varray, (MAX)+1); \
+ if (is_global) \
+ global_const_equiv_varray = (MAP)->const_equiv_varray; \
+ } \
+ }
+
+#define SET_CONST_EQUIV_DATA(MAP,REG,RTX,AGE) \
+ { \
+ struct const_equiv_data *p; \
+ MAYBE_EXTEND_CONST_EQUIV_VARRAY ((MAP), REGNO (REG)); \
+ p = &VARRAY_CONST_EQUIV ((MAP)->const_equiv_varray, REGNO (REG)); \
+ p->rtx = (RTX); \
+ p->age = (AGE); \
+ }
diff --git a/contrib/gcc/intl.c b/contrib/gcc/intl.c
new file mode 100644
index 0000000..e039909
--- /dev/null
+++ b/contrib/gcc/intl.c
@@ -0,0 +1,6 @@
+/* intl.c - internationalization */
+
+#include "gansidecl.h"
+#include "intl.h"
+
+const char localedir[] = LOCALEDIR;
diff --git a/contrib/gcc/intl.h b/contrib/gcc/intl.h
new file mode 100644
index 0000000..56c075e
--- /dev/null
+++ b/contrib/gcc/intl.h
@@ -0,0 +1,52 @@
+/* intl.h - internationalization
+ Copyright 1998 Free Software Foundation, Inc.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifndef HAVE_SETLOCALE
+# define setlocale(category, locale) (locale)
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+ extern const char localedir[];
+#else
+/* Stubs that do something close enough. */
+# ifdef textdomain
+# undef textdomain
+# endif
+# define textdomain(domain) (domain)
+# ifdef bindtextdomain
+# undef bindtextdomain
+# endif
+# define bindtextdomain(domain, directory) (domain)
+# ifdef gettext
+# undef gettext
+# endif
+# define gettext(msgid) (msgid)
+#endif
+
+#ifndef _
+# define _(msgid) gettext (msgid)
+#endif
+
+#ifndef N_
+# define N_(msgid) (msgid)
+#endif
diff --git a/contrib/gcc/invoke.texi b/contrib/gcc/invoke.texi
index 01dd7a8..adf167f 100644
--- a/contrib/gcc/invoke.texi
+++ b/contrib/gcc/invoke.texi
@@ -1,14 +1,14 @@
-@c Copyright (C) 1988,89,92,93,94,95,96,97,1998 Free Software Foundation, Inc.
+@c Copyright (C) 1988, 89, 92-98, 1999 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@node Invoking GCC
-@chapter GNU CC Command Options
-@cindex GNU CC command options
+@chapter GCC Command Options
+@cindex GCC command options
@cindex command options
-@cindex options, GNU CC command
+@cindex options, GCC command
-When you invoke GNU CC, it normally does preprocessing, compilation,
+When you invoke GCC, it normally does preprocessing, compilation,
assembly and linking. The ``overall options'' allow you to stop this
process at an intermediate stage. For example, the @samp{-c} option
says not to run the linker. Then the output consists of object files
@@ -20,7 +20,7 @@ options control the assembler and linker; most of these are not
documented here, since you rarely need to use any of them.
@cindex C compilation options
-Most of the command line options that you can use with GNU CC are useful
+Most of the command line options that you can use with GCC are useful
for C programs; when an option is only useful with another language
(usually C++), the explanation says so explicitly. If the description
for a particular option does not mention a source language, you can use
@@ -68,12 +68,12 @@ only one of these two forms, whichever one is not the default.
* Link Options:: Specifying libraries and so on.
* Directory Options:: Where to find header files and libraries.
Where to find the compiler executable files.
-* Target Options:: Running a cross-compiler, or an old version of GNU CC.
+* Target Options:: Running a cross-compiler, or an old version of GCC.
* Submodel Options:: Specifying minor hardware or convention variations,
such as 68010 vs 68020.
* Code Gen Options:: Specifying conventions for function calls, data layout
and register usage.
-* Environment Variables:: Env vars that affect GNU CC.
+* Environment Variables:: Env vars that affect GCC.
* Running Protoize:: Automatically adding or removing function prototypes.
@end menu
@@ -87,13 +87,13 @@ in the following sections.
@item Overall Options
@xref{Overall Options,,Options Controlling the Kind of Output}.
@smallexample
--c -S -E -o @var{file} -pipe -v -x @var{language}
+-c -S -E -o @var{file} -pipe -v --help -x @var{language}
@end smallexample
@item C Language Options
@xref{C Dialect Options,,Options Controlling C Dialect}.
@smallexample
--ansi -fallow-single-precision -fcond-mismatch -fno-asm
+-ansi -flang-isoc9x -fallow-single-precision -fcond-mismatch -fno-asm
-fno-builtin -ffreestanding -fhosted -fsigned-bitfields -fsigned-char
-funsigned-bitfields -funsigned-char -fwritable-strings
-traditional -traditional-cpp -trigraphs
@@ -102,13 +102,17 @@ in the following sections.
@item C++ Language Options
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@smallexample
--fall-virtual -fdollars-in-identifiers -felide-constructors
--fenum-int-equiv -fexternal-templates -ffor-scope
--fno-for-scope -fhandle-signatures -fmemoize-lookups
--fname-mangling-version-@var{n} -fno-default-inline
--fno-gnu-keywords -fnonnull-objects -fguiding-decls
--foperator-names -fno-optional-diags -fstrict-prototype -fthis-is-variable
--ftemplate-depth-@var{n} -nostdinc++ -traditional +e@var{n}
+-fno-access-control -fcheck-new -fconserve-space -fdollars-in-identifiers
+-fno-elide-constructors -fexternal-templates -ffor-scope
+-fno-for-scope -fno-gnu-keywords -fguiding-decls -fhandle-signatures
+-fhonor-std -fhuge-objects -fno-implicit-templates -finit-priority
+-fno-implement-inlines -fname-mangling-version-@var{n} -fno-default-inline
+-foperator-names -fno-optional-diags -fpermissive -frepo -fstrict-prototype
+-fsquangle -ftemplate-depth-@var{n} -fthis-is-variable -fvtable-thunks
+-nostdinc++ -Wctor-dtor-privacy -Wno-deprecated -Weffc++
+-Wno-non-template-friend
+-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual
+-Wno-pmf-conversions -Wreorder -Wsign-promo -Wsynth
@end smallexample
@item Warning Options
@@ -116,26 +120,25 @@ in the following sections.
@smallexample
-fsyntax-only -pedantic -pedantic-errors
-w -W -Wall -Waggregate-return -Wbad-function-cast
--Wcast-align -Wcast-qual -Wchar-subscript -Wcomment
+-Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment
-Wconversion -Werror -Wformat
-Wid-clash-@var{len} -Wimplicit -Wimplicit-int
-Wimplicit-function-declaration -Wimport
-Werror-implicit-function-declaration -Winline
-Wlarger-than-@var{len} -Wlong-long
--Wmain -Wmissing-declarations
+-Wmain -Wmissing-declarations -Wmissing-noreturn
-Wmissing-prototypes -Wmultichar -Wnested-externs -Wno-import
--Wold-style-cast -Woverloaded-virtual -Wparentheses
--Wpointer-arith -Wredundant-decls -Wreorder -Wreturn-type
--Wshadow -Wsign-compare -Wstrict-prototypes -Wswitch
--Wsynth -Wtemplate-debugging -Wtraditional -Wtrigraphs
--Wundef -Wuninitialized -Wunused -Wwrite-strings
+-Wparentheses -Wpointer-arith -Wredundant-decls
+-Wreturn-type -Wshadow -Wsign-compare -Wstrict-prototypes
+-Wswitch -Wtraditional
+-Wtrigraphs -Wundef -Wuninitialized -Wunused -Wwrite-strings
-Wunknown-pragmas
@end smallexample
@item Debugging Options
@xref{Debugging Options,,Options for Debugging Your Program or GCC}.
@smallexample
--a -ax -d@var{letters} -fpretend-float
+-a -ax -d@var{letters} -fdump-unnumbered -fpretend-float
-fprofile-arcs -ftest-coverage
-g -g@var{level} -gcoff -gdwarf -gdwarf-1 -gdwarf-1+ -gdwarf-2
-ggdb -gstabs -gstabs+ -gxcoff -gxcoff+
@@ -150,15 +153,14 @@ in the following sections.
-fcaller-saves -fcse-follow-jumps -fcse-skip-blocks
-fdelayed-branch -fexpensive-optimizations
-ffast-math -ffloat-store -fforce-addr -fforce-mem
--ffunction-sections -fgcse -finline-functions
--fkeep-inline-functions -fno-default-inline
--fno-defer-pop -fno-function-cse
+-fdata-sections -ffunction-sections -fgcse
+-finline-functions -finline-limit-@var{n} -fkeep-inline-functions
+-fno-default-inline -fno-defer-pop -fno-function-cse
-fno-inline -fno-peephole -fomit-frame-pointer -fregmove
-frerun-cse-after-loop -frerun-loop-opt -fschedule-insns
-fschedule-insns2 -fstrength-reduce -fthread-jumps
-funroll-all-loops -funroll-loops
-fmove-all-movables -freduce-all-givs -fstrict-aliasing
--fstructure-noalias
-O -O0 -O1 -O2 -O3 -Os
@end smallexample
@@ -170,7 +172,7 @@ in the following sections.
-idirafter @var{dir}
-include @var{file} -imacros @var{file}
-iprefix @var{file} -iwithprefix @var{dir}
--iwithprefixbefore @var{dir} -isystem @var{dir}
+-iwithprefixbefore @var{dir} -isystem @var{dir} -isystem-c++ @var{dir}
-M -MD -MM -MMD -MG -nostdinc -P -trigraphs
-undef -U@var{macro} -Wp,@var{option}
@end smallexample
@@ -259,6 +261,8 @@ in the following sections.
-mcpu= -march= -mfpe=
-mstructure-size-boundary=
-mbsd -mxopen -mno-symrename
+-mabort-on-noreturn
+-mno-sched-prolog
@emph{Thumb Options}
-mtpcs-frame -mno-tpcs-frame
@@ -320,7 +324,7 @@ in the following sections.
-mabicalls -mcpu=@var{cpu type} -membedded-data
-membedded-pic -mfp32 -mfp64 -mgas -mgp32 -mgp64
-mgpopt -mhalf-pic -mhard-float -mint64 -mips1
--mips2 -mips3 -mips4 -mlong64 -mlong-calls -mmemcpy
+-mips2 -mips3 -mips4 -mlong64 -mlong32 -mlong-calls -mmemcpy
-mmips-as -mmips-tfile -mno-abicalls
-mno-embedded-data -mno-embedded-pic
-mno-gpopt -mno-long-calls
@@ -338,9 +342,10 @@ in the following sections.
-mno-wide-multiply -mrtd -malign-double
-mreg-alloc=@var{list} -mregparm=@var{num}
-malign-jumps=@var{num} -malign-loops=@var{num}
--malign-functions=@var{num}
+-malign-functions=@var{num} -mpreferred-stack-boundary=@var{num}
@emph{HPPA Options}
+-march=@var{architecture type}
-mbig-switch -mdisable-fpregs -mdisable-indexing
-mfast-indirect-calls -mgas -mjump-in-delay
-mlong-load-store -mno-big-switch -mno-disable-fpregs
@@ -348,8 +353,8 @@ in the following sections.
-mno-jump-in-delay -mno-long-load-store
-mno-portable-runtime -mno-soft-float -mno-space
-mno-space-regs -msoft-float -mpa-risc-1-0
--mpa-risc-1-1 -mportable-runtime
--mschedule=@var{list} -mspace -mspace-regs
+-mpa-risc-1-1 -mpa-risc-2-0 -mportable-runtime
+-mschedule=@var{cpu type} -mspace -mspace-regs
@emph{Intel 960 Options}
-m@var{cpu type} -masm-compat -mclean-linkage
@@ -388,11 +393,22 @@ in the following sections.
-mmangle-cpu -mcpu=@var{cpu} -mtext=@var{text section}
-mdata=@var{data section} -mrodata=@var{readonly data section}
+@emph{TMS320C3x/C4x Options}
+-mcpu=@var{cpu} -mbig -msmall -mregparm -mmemparm
+-mfast-fix -mmpyi -mbk -mti -mdp-isr-reload
+-mrpts=@var{count} -mrptb -mdb -mloop-unsigned
+-mparallel-insns -mparallel-mpy -mpreserve-float
+
@emph{V850 Options}
-mlong-calls -mno-long-calls -mep -mno-ep
-mprolog-function -mno-prolog-function -mspace
-mtda=@var{n} -msda=@var{n} -mzda=@var{n}
-mv850 -mbig-switch
+
+@emph{NS32K Options}
+-m32032 -m32332 -m32532 -m32081 -m32381 -mmult-add -mnomult-add
+-msoft-float -mrtd -mnortd -mregparam -mnoregparam -msb -mnosb
+-mbitfield -mnobitfield -mhimem -mnohimem
@end smallexample
@item Code Generation Options
@@ -404,10 +420,11 @@ in the following sections.
-fno-common -fno-ident -fno-gnu-linker
-fpcc-struct-return -fpic -fPIC
-freg-struct-return -fshared-data -fshort-enums
--fshort-double -fvolatile -fvolatile-global
--fverbose-asm -fpack-struct -fstack-check +e0 +e1
+-fshort-double -fvolatile -fvolatile-global -fvolatile-static
+-fverbose-asm -fpack-struct -fstack-check
-fargument-alias -fargument-noalias
-fargument-noalias-global
+-fleading-underscore
@end smallexample
@end table
@@ -426,7 +443,7 @@ in the following sections.
* Link Options:: Specifying libraries and so on.
* Directory Options:: Where to find header files and libraries.
Where to find the compiler executable files.
-* Target Options:: Running a cross-compiler, or an old version of GNU CC.
+* Target Options:: Running a cross-compiler, or an old version of GCC.
@end menu
@node Overall Options
@@ -558,6 +575,15 @@ Use pipes rather than temporary files for communication between the
various stages of compilation. This fails to work on some systems where
the assembler is unable to read from a pipe; but the GNU assembler has
no trouble.
+
+@item --help
+Print (on the standard output) a description of the command line options
+understood by @code{gcc}. If the @code{-v} option is also specified
+then @code{--help} will also be passed on to the various processes
+invoked by @code{gcc}, so that they can display the command line options
+they accept. If the @code{-W} option is also specified then command
+line options which have no documentation associated with them will also
+be displayed.
@end table
@node Invoking G++
@@ -566,10 +592,11 @@ no trouble.
@cindex suffixes for C++ source
@cindex C++ source file suffixes
C++ source files conventionally use one of the suffixes @samp{.C},
-@samp{.cc}, @samp{cpp}, or @samp{.cxx}; preprocessed C++ files use the
-suffix @samp{.ii}. GNU CC recognizes files with these names and
-compiles them as C++ programs even if you call the compiler the same way
-as for compiling C programs (usually with the name @code{gcc}).
+@samp{.cc}, @samp{.cpp}, @samp{.c++}, @samp{.cp}, or @samp{.cxx};
+preprocessed C++ files use the suffix @samp{.ii}. GCC recognizes
+files with these names and compiles them as C++ programs even if you
+call the compiler the same way as for compiling C programs (usually with
+the name @code{gcc}).
@findex g++
@findex c++
@@ -577,19 +604,9 @@ However, C++ programs often require class libraries as well as a
compiler that understands the C++ language---and under some
circumstances, you might want to compile programs from standard input,
or otherwise without a suffix that flags them as C++ programs.
-@code{g++} is a program that calls GNU CC with the default language
+@code{g++} is a program that calls GCC with the default language
set to C++, and automatically specifies linking against the C++
-library.
-@cindex @code{g++ 1.@var{xx}}
-@cindex @code{g++}, separate compiler
-@cindex @code{g++} older version
-@footnote{Prior to release 2 of the compiler,
-there was a separate @code{g++} compiler. That version was based on GNU
-CC, but not integrated with it. Versions of @code{g++} with a
-@samp{1.@var{xx}} version number---for example, @code{g++} version 1.37
-or 1.42---are much less reliable than the versions integrated with GCC
-2. Moreover, combining G++ @samp{1.@var{xx}} with a version 2 GCC will
-simply not work.} On many systems, the script @code{g++} is also
+library. On many systems, the script @code{g++} is also
installed with the name @code{c++}.
@cindex invoking @code{g++}
@@ -614,14 +631,20 @@ from C, such as C++ and Objective C) that the compiler accepts:
@table @code
@cindex ANSI support
@item -ansi
-Support all ANSI standard C programs.
+In C mode, support all ANSI standard C programs. In C++ mode,
+remove GNU extensions that conflict with ANSI C++.
+@c shouldn't we be saying "ISO"?
-This turns off certain features of GNU C that are incompatible with ANSI
-C, such as the @code{asm}, @code{inline} and @code{typeof} keywords, and
+This turns off certain features of GCC that are incompatible with ANSI
+C (when compiling C code), or of ANSI standard C++ (when compiling C++ code),
+such as the @code{asm} and @code{typeof} keywords, and
predefined macros such as @code{unix} and @code{vax} that identify the
type of system you are using. It also enables the undesirable and
-rarely used ANSI trigraph feature, and it disables recognition of C++
-style @samp{//} comments.
+rarely used ANSI trigraph feature. For the C compiler,
+it disables recognition of C++ style @samp{//} comments as well as
+the @code{inline} keyword. For the C++ compiler,
+@samp{-foperator-names} is enabled as well.
+
The alternate keywords @code{__asm__}, @code{__extension__},
@code{__inline__} and @code{__typeof__} continue to work despite
@@ -644,6 +667,15 @@ programs that might use these names for other things.
The functions @code{alloca}, @code{abort}, @code{exit}, and
@code{_exit} are not builtin functions when @samp{-ansi} is used.
+@item -flang-isoc9x
+Enable support for features found in the C9X standard. In particular,
+enable support for the C9X @code{restrict} keyword.
+
+Even when this option is not specified, you can still use some C9X
+features in so far as they do not conflict with previous C standards.
+For example, you may use @code{__restrict__} even when -flang-isoc9x
+is not specified.
+
@item -fno-asm
Do not recognize @code{asm}, @code{inline} or @code{typeof} as a
keyword, so that code can use these words as identifiers. You can use
@@ -672,7 +704,7 @@ other, C++-specific, extension keywords such as @code{headof}.
@findex strcmp
@findex strcpy
@findex strlen
-Don't recognize builtin functions that do not begin with `__builtin_'
+Don't recognize builtin functions that do not begin with @samp{__builtin_}
as prefix. Currently, the functions affected include @code{abort},
@code{abs}, @code{alloca}, @code{cos}, @code{exit}, @code{fabs},
@code{ffs}, @code{labs}, @code{memcmp}, @code{memcpy}, @code{sin},
@@ -764,11 +796,6 @@ The character escape sequences @samp{\x} and @samp{\a} evaluate as the
literal characters @samp{x} and @samp{a} respectively. Without
@w{@samp{-traditional}}, @samp{\x} is a prefix for the hexadecimal
representation of a character, and @samp{\a} produces a bell.
-
-@item
-In C++ programs, assignment to @code{this} is permitted with
-@samp{-traditional}. (The option @samp{-fthis-is-variable} also has
-this effect.)
@end itemize
You may wish to use @samp{-fno-builtin} as well as @samp{-traditional}
@@ -909,13 +936,13 @@ regardless of what language your program is in. For example, you
might compile a file @code{firstClass.C} like this:
@example
-g++ -g -felide-constructors -O -c firstClass.C
+g++ -g -frepo -O -c firstClass.C
@end example
@noindent
-In this example, only @samp{-felide-constructors} is an option meant
+In this example, only @samp{-frepo} is an option meant
only for C++ programs; you can use the other options with any
-language supported by GNU CC.
+language supported by GCC.
Here is a list of options that are @emph{only} for compiling C++ programs:
@@ -924,24 +951,17 @@ Here is a list of options that are @emph{only} for compiling C++ programs:
Turn off all access checking. This switch is mainly useful for working
around bugs in the access control code.
-@item -fall-virtual
-Treat all possible member functions as virtual, implicitly.
-All member functions (except for constructor functions and @code{new} or
-@code{delete} member operators) are treated as virtual functions of the
-class where they appear.
-
-This does not mean that all calls to these member functions will be made
-through the internal table of virtual functions. Under some
-circumstances, the compiler can determine that a call to a given virtual
-function can be made directly; in these cases the calls are direct in
-any case.
-
@item -fcheck-new
Check that the pointer returned by @code{operator new} is non-null
before attempting to modify the storage allocated. The current Working
Paper requires that @code{operator new} never return a null pointer, so
this check is normally unnecessary.
+An alternative to using this option is to specify that your
+@code{operator new} does not throw any exceptions; if you declare it
+@samp{throw()}, g++ will check the return value. See also @samp{new
+(nothrow)}.
+
@item -fconserve-space
Put uninitialized or runtime-initialized global variables into the
common segment, as C does. This saves space in the executable at the
@@ -950,6 +970,9 @@ flag and your program mysteriously crashes after @code{main()} has
completed, you may have an object that is being destroyed twice because
two definitions were merged.
+This option is no longer useful on most targets, now that support has
+been added for putting variables into BSS without making them common.
+
@item -fdollars-in-identifiers
Accept @samp{$} in identifiers. You can also explicitly prohibit use of
@samp{$} with the option @samp{-fno-dollars-in-identifiers}. (GNU C allows
@@ -957,10 +980,11 @@ Accept @samp{$} in identifiers. You can also explicitly prohibit use of
Traditional C allowed the character @samp{$} to form part of
identifiers. However, ANSI C and C++ forbid @samp{$} in identifiers.
-@item -fenum-int-equiv
-Anachronistically permit implicit conversion of @code{int} to
-enumeration types. Current C++ allows conversion of @code{enum} to
-@code{int}, but not the other way around.
+@item -fno-elide-constructors
+The C++ standard allows an implementation to omit creating a temporary
+which is only used to initialize another object of the same type.
+Specifying this option disables that optimization, and forces g++ to
+call the copy constructor in all cases.
@item -fexternal-templates
Cause template instantiations to obey @samp{#pragma interface} and
@@ -1009,12 +1033,9 @@ be instantiated. This behavior reflects the C++ language prior to
September 1996, when guiding declarations were removed.
This option implies @samp{-fname-mangling-version-0}, and will not work
-with other name mangling versions.
-
-@item -fno-implicit-templates
-Never emit code for templates which are instantiated implicitly (i.e. by
-use); only emit code for explicit instantiations. @xref{Template
-Instantiation}, for more information.
+with other name mangling versions. Like all options that change the
+ABI, all C++ code, @emph{including libgcc.a} must be built with the same
+setting of this option.
@item -fhandle-signatures
Recognize the @code{signature} and @code{sigof} keywords for specifying
@@ -1022,71 +1043,42 @@ abstract types. The default (@samp{-fno-handle-signatures}) is not to
recognize them. @xref{C++ Signatures, Type Abstraction using
Signatures}.
+@item -fhonor-std
+Treat the @code{namespace std} as a namespace, instead of ignoring
+it. For compatibility with earlier versions of g++, the compiler will,
+by default, ignore @code{namespace-declarations},
+@code{using-declarations}, @code{using-directives}, and
+@code{namespace-names}, if they involve @code{std}.
+
@item -fhuge-objects
Support virtual function calls for objects that exceed the size
representable by a @samp{short int}. Users should not use this flag by
-default; if you need to use it, the compiler will tell you so. If you
-compile any of your code with this flag, you must compile @emph{all} of
-your code with this flag (including the C++ library, if you use it).
+default; if you need to use it, the compiler will tell you so.
This flag is not useful when compiling with -fvtable-thunks.
-@item -fno-implement-inlines
-To save space, do not emit out-of-line copies of inline functions
-controlled by @samp{#pragma implementation}. This will cause linker
-errors if these functions are not inlined everywhere they are called.
-
-@item -fmemoize-lookups
-@itemx -fsave-memoized
-Use heuristics to compile faster. These heuristics are not enabled by
-default, since they are only effective for certain input files. Other
-input files compile more slowly.
-
-The first time the compiler must build a call to a member function (or
-reference to a data member), it must (1) determine whether the class
-implements member functions of that name; (2) resolve which member
-function to call (which involves figuring out what sorts of type
-conversions need to be made); and (3) check the visibility of the member
-function to the caller. All of this adds up to slower compilation.
-Normally, the second time a call is made to that member function (or
-reference to that data member), it must go through the same lengthy
-process again. This means that code like this:
+Like all options that change the ABI, all C++ code, @emph{including
+libgcc} must be built with the same setting of this option.
-@smallexample
-cout << "This " << p << " has " << n << " legs.\n";
-@end smallexample
+@item -fno-implicit-templates
+Never emit code for non-inline templates which are instantiated
+implicitly (i.e. by use); only emit code for explicit instantiations.
+@xref{Template Instantiation}, for more information.
-@noindent
-makes six passes through all three steps. By using a software cache, a
-``hit'' significantly reduces this cost. Unfortunately, using the cache
-introduces another layer of mechanisms which must be implemented, and so
-incurs its own overhead. @samp{-fmemoize-lookups} enables the software
-cache.
-
-Because access privileges (visibility) to members and member functions
-may differ from one function context to the next, G++ may need to flush
-the cache. With the @samp{-fmemoize-lookups} flag, the cache is flushed
-after every function that is compiled. The @samp{-fsave-memoized} flag
-enables the same software cache, but when the compiler determines that
-the context of the last function compiled would yield the same access
-privileges of the next function to compile, it preserves the cache.
-This is most helpful when defining many member functions for the same
-class: with the exception of member functions which are friends of other
-classes, each member function has exactly the same access privileges as
-every other, and the cache need not be flushed.
-
-The code that implements these flags has rotted; you should probably
-avoid using them.
+@item -fno-implicit-inline-templates
+Don't emit code for implicit instantiations of inline templates, either.
+The default is to handle inlines differently so that compiles with and
+without optimization will need the same set of explicit instantiations.
-@item -fstrict-prototype
-Within an @samp{extern "C"} linkage specification, treat a function
-declaration with no arguments, such as @samp{int foo ();}, as declaring
-the function to take no arguments. Normally, such a declaration means
-that the function @code{foo} can take any combination of arguments, as
-in C. @samp{-pedantic} implies @samp{-fstrict-prototype} unless
-overridden with @samp{-fno-strict-prototype}.
+@item -finit-priority
+Support @samp{__attribute__ ((init_priority (n)))} for controlling the
+order of initialization of file-scope objects. On ELF targets, this
+requires GNU ld 2.10 or later.
-This flag no longer affects declarations with C++ linkage.
+@item -fno-implement-inlines
+To save space, do not emit out-of-line copies of inline functions
+controlled by @samp{#pragma implementation}. This will cause linker
+errors if these functions are not inlined everywhere they are called.
@item -fname-mangling-version-@var{n}
Control the way in which names are mangled. Version 0 is compatible
@@ -1099,14 +1091,8 @@ given this declaration:
template <class T, class U> void foo(T t);
@end example
-@item -fno-nonnull-objects
-Don't assume that a reference is initialized to refer to a valid object.
-Although the current C++ Working Paper prohibits null references, some
-old code may rely on them, and you can use @samp{-fno-nonnull-objects}
-to turn on checking.
-
-At the moment, the compiler only does this checking for conversions to
-virtual base classes.
+Like all options that change the ABI, all C++ code, @emph{including
+libgcc} must be built with the same setting of this option.
@item -foperator-names
Recognize the operator name keywords @code{and}, @code{bitand},
@@ -1116,14 +1102,40 @@ synonyms for the symbols they refer to. @samp{-ansi} implies
@item -fno-optional-diags
Disable diagnostics that the standard says a compiler does not need to
-issue. Currently, this means the diagnostic for a name having multiple
-meanings within a class.
+issue. Currently, the only such diagnostic issued by g++ is the one for
+a name having multiple meanings within a class.
+
+@item -fpermissive
+Downgrade messages about nonconformant code from errors to warnings. By
+default, g++ effectively sets @samp{-pedantic-errors} without
+@samp{-pedantic}; this option reverses that. This behavior and this
+option are superceded by @samp{-pedantic}, which works as it does for GNU C.
@item -frepo
Enable automatic template instantiation. This option also implies
@samp{-fno-implicit-templates}. @xref{Template Instantiation}, for more
information.
+@item -fno-rtti
+Disable generation of the information used by C++ runtime type
+identification features (@samp{dynamic_cast} and @samp{typeid}). If you
+don't use those parts of the language (or exception handling, which uses
+@samp{dynamic_cast} internally), you can save some space by using this
+flag.
+
+@item -fstrict-prototype
+Within an @samp{extern "C"} linkage specification, treat a function
+declaration with no arguments, such as @samp{int foo ();}, as declaring
+the function to take no arguments. Normally, such a declaration means
+that the function @code{foo} can take any combination of arguments, as
+in C. @samp{-pedantic} implies @samp{-fstrict-prototype} unless
+overridden with @samp{-fno-strict-prototype}.
+
+Specifying this option will also suppress implicit declarations of
+functions.
+
+This flag no longer affects declarations with C++ linkage.
+
@item -fsquangle
@itemx -fno-squangle
@samp{-fsquangle} will enable a compressed form of name mangling for
@@ -1133,6 +1145,15 @@ short ID codes. This option also requires any C++ libraries being used to
be compiled with this option as well. The compiler has this disabled (the
equivalent of @samp{-fno-squangle}) by default.
+Like all options that change the ABI, all C++ code, @emph{including
+libgcc.a} must be built with the same setting of this option.
+
+@item -ftemplate-depth-@var{n}
+Set the maximum instantiation depth for template classes to @var{n}.
+A limit on the template instantiation depth is needed to detect
+endless recursions during template class instantiation. ANSI/ISO C++
+conforming programs must not rely on a maximum depth greater than 17.
+
@item -fthis-is-variable
Permit assignment to @code{this}. The incorporation of user-defined
free store management into C++ has made assignment to @samp{this} an
@@ -1155,21 +1176,13 @@ vtables; if a class has any non-inline virtual functions, the vtable
will be emitted in the translation unit containing the first one of
those.
-@item -ftemplate-depth-@var{n}
-Set the maximum instantiation depth for template classes to @var{n}.
-A limit on the template instantiation depth is needed to detect
-endless recursions during template class instantiation. ANSI/ISO C++
-conforming programs must not rely on a maximum depth greater than 17.
+Like all options that change the ABI, all C++ code, @emph{including
+libgcc.a} must be built with the same setting of this option.
@item -nostdinc++
Do not search for header files in the standard directories specific to
C++, but do still search the other standard directories. (This option
is used when building the C++ library.)
-
-@item -traditional
-For C++ programs (in addition to the effects that apply to both C and
-C++), this has the same effect as @samp{-fthis-is-variable}.
-@xref{C Dialect Options,, Options Controlling C Dialect}.
@end table
In addition, these optimization, warning, and code generation options
@@ -1178,21 +1191,113 @@ have meanings only for C++ programs:
@table @code
@item -fno-default-inline
Do not assume @samp{inline} for functions defined inside a class scope.
-@xref{Optimize Options,,Options That Control Optimization}.
+@xref{Optimize Options,,Options That Control Optimization}. Note that these
+functions will have linkage like inline functions; they just won't be
+inlined by default.
-@item -Wold-style-cast
-@itemx -Woverloaded-virtual
-@itemx -Wtemplate-debugging
-Warnings that apply only to C++ programs. @xref{Warning
-Options,,Options to Request or Suppress Warnings}.
+@item -Wctor-dtor-privacy (C++ only)
+Warn when a class seems unusable, because all the constructors or
+destructors in a class are private and the class has no friends or
+public static member functions.
-@item -Weffc++
-Warn about violation of some style rules from Effective C++ by Scott Myers.
+@item -Wnon-virtual-dtor (C++ only)
+Warn when a class declares a non-virtual destructor that should probably
+be virtual, because it looks like the class will be used polymorphically.
+
+@item -Wreorder (C++ only)
+@cindex reordering, warning
+@cindex warning for reordering of member initializers
+Warn when the order of member initializers given in the code does not
+match the order in which they must be executed. For instance:
-@item +e@var{n}
-Control how virtual function definitions are used, in a fashion
-compatible with @code{cfront} 1.x. @xref{Code Gen Options,,Options for
-Code Generation Conventions}.
+@smallexample
+struct A @{
+ int i;
+ int j;
+ A(): j (0), i (1) @{ @}
+@};
+@end smallexample
+
+Here the compiler will warn that the member initializers for @samp{i}
+and @samp{j} will be rearranged to match the declaration order of the
+members.
+@end table
+
+The following @samp{-W@dots{}} options are not affected by @samp{-Wall}.
+
+@table @code
+@item -Weffc++ (C++ only)
+Warn about violations of various style guidelines from Scott Meyers'
+@cite{Effective C++} books. If you use this option, you should be aware
+that the standard library headers do not obey all of these guidelines;
+you can use @samp{grep -v} to filter out those warnings.
+
+@item -Wno-deprecated (C++ only)
+Do not warn about usage of deprecated features. @xref{Deprecated Features}.
+
+@item -Wno-non-template-friend (C++ only)
+Disable warnings when non-templatized friend functions are declared
+within a template. With the advent of explicit template specification
+support in g++, if the name of the friend is an unqualified-id (ie,
+@samp{friend foo(int)}), the C++ language specification demands that the
+friend declare or define an ordinary, nontemplate function. (Section
+14.5.3). Before g++ implemented explicit specification, unqualified-ids
+could be interpreted as a particular specialization of a templatized
+function. Because this non-conforming behavior is no longer the default
+behavior for g++, @samp{-Wnon-template-friend} allows the compiler to
+check existing code for potential trouble spots, and is on by default.
+This new compiler behavior can also be turned off with the flag
+@samp{-fguiding-decls}, which activates the older, non-specification
+compiler code, or with @samp{-Wno-non-template-friend} which keeps the
+conformant compiler code but disables the helpful warning.
+
+@item -Wold-style-cast (C++ only)
+Warn if an old-style (C-style) cast is used within a C++ program. The
+new-style casts (@samp{static_cast}, @samp{reinterpret_cast}, and
+@samp{const_cast}) are less vulnerable to unintended effects.
+
+@item -Woverloaded-virtual (C++ only)
+@cindex overloaded virtual fn, warning
+@cindex warning for overloaded virtual fn
+Warn when a derived class function declaration may be an error in
+defining a virtual function. In a derived class, the
+definitions of virtual functions must match the type signature of a
+virtual function declared in the base class. With this option, the
+compiler warns when you define a function with the same name as a
+virtual function, but with a type signature that does not match any
+declarations from the base class.
+
+@item -Wno-pmf-conversions (C++ only)
+Disable the diagnostic for converting a bound pointer to member function
+to a plain pointer.
+
+@item -Wsign-promo (C++ only)
+Warn when overload resolution chooses a promotion from unsigned or
+enumeral type to a signed type over a conversion to an unsigned type of
+the same size. Previous versions of g++ would try to preserve
+unsignedness, but the standard mandates the current behavior.
+
+@item -Wsynth (C++ only)
+@cindex warning for synthesized methods
+@cindex synthesized methods, warning
+Warn when g++'s synthesis behavior does not match that of cfront. For
+instance:
+
+@smallexample
+struct A @{
+ operator int ();
+ A& operator = (int);
+@};
+
+main ()
+@{
+ A a,b;
+ a = b;
+@}
+@end smallexample
+
+In this example, g++ will synthesize a default @samp{A& operator =
+(const A&);}, while cfront will use the user-defined @samp{operator =}.
@end table
@node Warning Options
@@ -1213,8 +1318,7 @@ negative form beginning @samp{-Wno-} to turn off warnings;
for example, @samp{-Wno-implicit}. This manual lists only one of the
two forms, whichever is not the default.
-These options control the amount and kinds of warnings produced by GNU
-CC:
+These options control the amount and kinds of warnings produced by GCC:
@table @code
@cindex syntax checking
@@ -1238,7 +1342,7 @@ these escape routes; application programs should avoid them.
@xref{Alternate Keywords}.
This option is not intended to be @i{useful}; it exists only to satisfy
-pedants who would otherwise claim that GNU CC fails to support the ANSI
+pedants who would otherwise claim that GCC fails to support the ANSI
standard.
Some users try to use @samp{-pedantic} to check programs for strict ANSI
@@ -1248,11 +1352,8 @@ ANSI C @emph{requires} a diagnostic.
A feature to report any failure to conform to ANSI C might be useful in
some instances, but would require considerable additional work and would
-be quite different from @samp{-pedantic}. We recommend, rather, that
-users take advantage of the extensions of GNU C and disregard the
-limitations of other compilers. Aside from certain supercomputers and
-obsolete small machines, there is less and less reason ever to use any
-other C compiler other than for bootstrapping GNU CC.
+be quite different from @samp{-pedantic}. We don't have plans to
+support such a feature in the near future.
@item -pedantic-errors
Like @samp{-pedantic}, except that errors are produced rather than
@@ -1366,7 +1467,7 @@ In order to get a warning about an unused function parameter, you must
specify both @samp{-W} and @samp{-Wunused}.
To suppress this warning for an expression, simply cast it to void. For
-unused variables and parameters, use the @samp{unused} attribute
+unused variables, parameters and labels, use the @samp{unused} attribute
(@pxref{Variable Attributes}).
@item -Wuninitialized
@@ -1388,7 +1489,7 @@ to compute a value that itself is never used, because such
computations may be deleted by data flow analysis before the warnings
are printed.
-These warnings are made optional because GNU CC is not smart
+These warnings are made optional because GCC is not smart
enough to see all the reasons why the code might be correct
despite appearing to have an error. Here is one example of how
this can happen:
@@ -1410,7 +1511,7 @@ this can happen:
@noindent
If the value of @code{y} is always 1, 2 or 3, then @code{x} is
-always initialized, but GNU CC doesn't know this. Here is
+always initialized, but GCC doesn't know this. Here is
another common case:
@smallexample
@@ -1429,29 +1530,6 @@ Some spurious warnings can be avoided if you declare all the functions
you use that never return as @code{noreturn}. @xref{Function
Attributes}.
-@item -Wreorder (C++ only)
-@cindex reordering, warning
-@cindex warning for reordering of member initializers
-Warn when the order of member initializers given in the code does not
-match the order in which they must be executed. For instance:
-
-@smallexample
-struct A @{
- int i;
- int j;
- A(): j (0), i (1) @{ @}
-@};
-@end smallexample
-
-Here the compiler will warn that the member initializers for @samp{i}
-and @samp{j} will be rearranged to match the declaration order of the
-members.
-
-@item -Wtemplate-debugging
-@cindex template debugging
-When using templates in a C++ program, warn if debugging is not yet
-fully available (C++ only).
-
@item -Wunknown-pragmas
@cindex warning for unknown pragmas
@cindex unknown pragmas, warning
@@ -1574,6 +1652,10 @@ the block.
@item
A @code{switch} statement has an operand of type @code{long}.
+
+@item
+A non-@code{static} function declaration follows a @code{static} one.
+This construct is not accepted by some traditional C compilers.
@end itemize
@item -Wundef
@@ -1664,6 +1746,13 @@ Do so even if the definition itself provides a prototype.
Use this option to detect global functions that are not declared in
header files.
+@item -Wmissing-noreturn
+Warn about functions which might be candidates for attribute @code{noreturn}.
+Note these are only possible candidates, not absolute ones. Care should
+be taken to manually verify functions actually do not ever return before
+adding the @code{noreturn} attribute, otherwise subtle code generation
+bugs could be introduced.
+
@item -Wredundant-decls
Warn if anything is declared more than once in the same scope, even in
cases where multiple declaration is valid and changes nothing.
@@ -1675,42 +1764,6 @@ Warn if an @code{extern} declaration is encountered within an function.
Warn if a function can not be inlined, and either it was declared as inline,
or else the @samp{-finline-functions} option was given.
-@item -Wold-style-cast
-Warn if an old-style (C-style) cast is used within a program.
-
-@item -Woverloaded-virtual
-@cindex overloaded virtual fn, warning
-@cindex warning for overloaded virtual fn
-Warn when a derived class function declaration may be an error in
-defining a virtual function (C++ only). In a derived class, the
-definitions of virtual functions must match the type signature of a
-virtual function declared in the base class. With this option, the
-compiler warns when you define a function with the same name as a
-virtual function, but with a type signature that does not match any
-declarations from the base class.
-
-@item -Wsynth (C++ only)
-@cindex warning for synthesized methods
-@cindex synthesized methods, warning
-Warn when g++'s synthesis behavior does not match that of cfront. For
-instance:
-
-@smallexample
-struct A @{
- operator int ();
- A& operator = (int);
-@};
-
-main ()
-@{
- A a,b;
- a = b;
-@}
-@end smallexample
-
-In this example, g++ will synthesize a default @samp{A& operator =
-(const A&);}, while cfront will use the user-defined @samp{operator =}.
-
@item -Wlong-long
Warn if @samp{long long} type is used. This is default. To inhibit
the warning messages, use @samp{-Wno-long-long}. Flags
@@ -1722,11 +1775,11 @@ Make all warnings into errors.
@end table
@node Debugging Options
-@section Options for Debugging Your Program or GNU CC
+@section Options for Debugging Your Program or GCC
@cindex options, debugging
@cindex debugging information options
-GNU CC has various special options that are used for debugging
+GCC has various special options that are used for debugging
either your program or GCC:
@table @code
@@ -1744,7 +1797,7 @@ to generate the extra information, use @samp{-gstabs+}, @samp{-gstabs},
@samp{-gxcoff+}, @samp{-gxcoff}, @samp{-gdwarf-1+}, or @samp{-gdwarf-1}
(see below).
-Unlike most other C compilers, GNU CC allows you to use @samp{-g} with
+Unlike most other C compilers, GCC allows you to use @samp{-g} with
@samp{-O}. The shortcuts taken by optimized code may occasionally
produce surprising results: some variables you declared may not exist
at all; flow of control may briefly move where you did not expect it;
@@ -1755,7 +1808,7 @@ execute in different places because they were moved out of loops.
Nevertheless it proves possible to debug optimized output. This makes
it reasonable to use the optimizer for programs that might have bugs.
-The following options are useful when GNU CC is generated with the
+The following options are useful when GCC is generated with the
capability for more than one debugging format.
@item -ggdb
@@ -1933,7 +1986,7 @@ frequencies.
@item -fprofile-arcs
Instrument @dfn{arcs} during compilation. For each function of your
-program, GNU CC creates a program flow graph, then finds a spanning tree
+program, GCC creates a program flow graph, then finds a spanning tree
for the graph. Only arcs that are not on the spanning tree have to be
instrumented: the compiler adds code to count the number of times that these
arcs are executed. When an arc is the only exit or only entrance to a
@@ -1963,7 +2016,7 @@ branch probabilities.
@need 2000
@item -ftest-coverage
Create data files for the @code{gcov} code-coverage utility
-(@pxref{Gcov,, @code{gcov}: a GNU CC Test Coverage Program}).
+(@pxref{Gcov,, @code{gcov}: a GCC Test Coverage Program}).
The data file names begin with the name of your source file:
@table @code
@@ -2000,18 +2053,10 @@ Dump after delayed branch scheduling, to @file{@var{file}.dbr}.
@item D
Dump all macro definitions, at the end of preprocessing, in addition to
normal output.
-@item y
-Dump debugging information during parsing, to standard error.
@item r
Dump after RTL generation, to @file{@var{file}.rtl}.
-@item x
-Just generate RTL for a function instead of compiling it. Usually used
-with @samp{r}.
@item j
Dump after first jump optimization, to @file{@var{file}.jump}.
-@item s
-Dump after CSE (including the jump optimization that sometimes
-follows CSE), to @file{@var{file}.cse}.
@item F
Dump after purging ADDRESSOF, to @file{@var{file}.addressof}.
@item f
@@ -2047,9 +2092,6 @@ Dump after the first instruction scheduling pass, to @file{@var{file}.sched}.
@item t
Dump after the second CSE pass (including the jump optimization that
sometimes follows CSE), to @file{@var{file}.cse2}.
-@item x
-Just generate RTL for a function instead of compiling it. Usually used
-with @samp{r}.
@item a
Produce all the dumps listed above.
@item m
@@ -2057,18 +2099,28 @@ Print statistics on memory usage, at the end of the run, to
standard error.
@item p
Annotate the assembler output with a comment indicating which
-pattern and alternative was used.
+pattern and alternative was used. The length of each instruction is
+also printed.
+@item x
+Just generate RTL for a function instead of compiling it. Usually used
+with @samp{r}.
@item y
Dump debugging information during parsing, to standard error.
@item A
Annotate the assembler output with miscellaneous debugging information.
@end table
+@item -fdump-unnumbered
+When doing debugging dumps (see -d option above), suppress instruction
+numbers and line number note output. This makes it more feasible to
+use diff on debugging dumps for compiler invokations with different
+options, in particular with and without -g.
+
@item -fpretend-float
When running a cross-compiler, pretend that the target machine uses the
same floating point format as the host machine. This causes incorrect
output of the actual floating constants, but the actual instruction
-sequence will probably be the same as GNU CC would make when running on
+sequence will probably be the same as GCC would make when running on
the target machine.
@item -save-temps
@@ -2080,7 +2132,7 @@ compiling @file{foo.c} with @samp{-c -save-temps} would produce files
@item -print-file-name=@var{library}
Print the full absolute name of the library file @var{library} that
would be used when linking---and don't do anything else. With this
-option, GNU CC does not compile or link anything; it just prints the
+option, GCC does not compile or link anything; it just prints the
file name.
@item -print-prog-name=@var{program}
@@ -2144,7 +2196,7 @@ without a frame pointer. On some machines the compiler also turns
on other flags.@refill
@item -O2
-Optimize even more. GNU CC performs nearly all supported optimizations
+Optimize even more. GCC performs nearly all supported optimizations
that do not involve a space-speed tradeoff. The compiler does not
perform loop unrolling or function inlining when you specify @samp{-O2}.
As compared to @samp{-O}, this option increases both compilation time
@@ -2190,7 +2242,8 @@ the 68000 where the floating registers (of the 68881) keep more
precision than a @code{double} is supposed to have. Similarly for the
x86 architecture. For most programs, the excess precision does only
good, but a few programs rely on the precise definition of IEEE floating
-point. Use @samp{-ffloat-store} for such programs.
+point. Use @samp{-ffloat-store} for such programs, after modifying
+them to store all pertinent intermediate computations into variables.
@item -fno-default-inline
Do not make member functions inline by default merely because they are
@@ -2254,6 +2307,23 @@ If all calls to a given function are integrated, and the function is
declared @code{static}, then the function is normally not output as
assembler code in its own right.
+@item -finline-limit-@var{n}
+By default, gcc limits the size of functions that can be inlined. This flag
+allows the control of this limit for functions that are explicitly marked as
+inline (ie marked with the inline keyword or defined within the class
+definition in c++). @var{n} is the size of functions that can be inlined in
+number of pseudo instructions (not counting parameter handling). The default
+value of n is 10000. Increasing this value can result in more inlined code at
+the cost of compilation time and memory consumption. Decreasing usually makes
+the compilation faster and less code will be inlined (which presumably
+means slower programs). This option is particularly useful for programs that
+use inlining heavily such as those based on recursive templates with c++.
+
+@emph{Note:} pseudo instruction represents, in this particular context, an
+abstract measurement of function's size. In no way, it represents a count
+of assembly instructions and as such its exact meaning might change from one
+release to an another.
+
@item -fkeep-inline-functions
Even if all calls to a given function are integrated, and the function
is declared @code{static}, nevertheless output a separate run-time
@@ -2264,7 +2334,7 @@ callable version of the function. This switch does not affect
Emit variables declared @code{static const} when optimization isn't turned
on, even if the variables aren't referenced.
-GNU CC enables this option by default. If you want to force the compiler to
+GCC enables this option by default. If you want to force the compiler to
check if the variable was referenced, regardless of whether or not
optimization is turned on, use the @samp{-fno-keep-static-consts} option.
@@ -2341,11 +2411,11 @@ This pass also performs global constant and copy propagation.
Perform a number of minor optimizations that are relatively expensive.
@item -foptimize-register-moves
-@item -fregmove
+@itemx -fregmove
Attempt to reassign register numbers in move instructions and as
operands of other simple instructions in order to maximize the amount of
register tying. This is especially helpful on machines with two-operand
-instructions. GNU CC enables this optimization by default with @samp{-O2}
+instructions. GCC enables this optimization by default with @samp{-O2}
or higher.
Note @code{-fregmove} and @code{-foptimize-register-moves} are the same
@@ -2370,18 +2440,20 @@ especially useful on machines with a relatively small number of
registers and where memory load instructions take more than one cycle.
@item -ffunction-sections
-Place each function into its own section in the output file if the
-target supports arbitrary sections. The function's name determines
-the section's name in the output file.
+@itemx -fdata-sections
+Place each function or data item into its own section in the output
+file if the target supports arbitrary sections. The name of the
+function or the name of the data item determines the section's name
+in the output file.
-Use this option on systems where the linker can perform optimizations
+Use these options on systems where the linker can perform optimizations
to improve locality of reference in the instruction space. HPPA
processors running HP-UX and Sparc processors running Solaris 2 have
linkers with such optimizations. Other systems using the ELF object format
as well as AIX may have these optimizations in the future.
-Only use this option when there are significant benefits from doing
-so. When you specify this option, the assembler and linker will
+Only use these options when there are significant benefits from doing
+so. When you specify these options, the assembler and linker will
create larger object and executable files and will also be slower.
You will not be able to use @code{gprof} on all systems if you
specify this option and you may have problems with debugging if
@@ -2393,13 +2465,16 @@ function calls, by emitting extra instructions to save and restore the
registers around such calls. Such allocation is done only when it
seems to result in better code than would otherwise be produced.
-This option is enabled by default on certain machines, usually those
-which have no call-preserved registers to use instead.
+This option is always enabled by default on certain machines, usually
+those which have no call-preserved registers to use instead.
+
+For all machines, optimization level 2 and higher enables this flag by
+default.
@item -funroll-loops
Perform the optimization of loop unrolling. This is only done for loops
whose number of iterations can be determined at compile time or run time.
-@samp{-funroll-loop} implies both @samp{-fstrength-reduce} and
+@samp{-funroll-loops} implies both @samp{-fstrength-reduce} and
@samp{-frerun-cse-after-loop}.
@item -funroll-all-loops
@@ -2416,7 +2491,7 @@ Forces all general-induction variables in loops to be
strength-reduced.
@emph{Note:} When compiling programs written in Fortran,
-@samp{-fmove-all-moveables} and @samp{-freduce-all-givs} are enabled
+@samp{-fmove-all-movables} and @samp{-freduce-all-givs} are enabled
by default when you use the optimizer.
These options may generate better or worse code; results are highly
@@ -2426,7 +2501,7 @@ These two options are intended to be removed someday, once
they have helped determine the efficacy of various
approaches to improving loop optimizations.
-Please let us (@code{egcs@@egcs.cygnus.com} and @code{fortran@@gnu.org})
+Please let us (@code{gcc@@gcc.gnu.org} and @code{fortran@@gnu.org})
know how use of these options affects
the performance of your production code.
We're very interested in code that runs @emph{slower}
@@ -2490,10 +2565,6 @@ int f() @{
@}
@end example
-This option is not enabled by default at any optimization level because
-it is new and has yet to be subjected to thorough testing. You may
-of course enable it manually with @samp{-fstrict-aliasing}.
-
@ifset INTERNALS
Every language that wishes to perform language-specific alias analysis
should define a function that computes, given an @code{tree}
@@ -2502,17 +2573,6 @@ allowed to alias. For an example, see the C front-end function
@code{c_get_alias_set}.
@end ifset
-@item -fstructure-noalias
-Allows the compiler to assume that structure / varying array references
-do not alias fixed scalars.
-
-Although this optimization is safe, GCC can occasionally lose track
-of which references refer to scalars and which to structures,
-leading it to perform unsafe transformations. Release 1.2 of EGCS
-will incorporate changes which allow GCC to track the
-scalar/structure distinction safely. Thus, the optimization will
-always be same, and this option will likely be removed or will have
-no effect.
@end table
@node Preprocessor Options
@@ -2786,20 +2846,20 @@ mechanism when this option is specified.
@cindex unresolved references and @code{-nodefaultlibs}
One of the standard libraries bypassed by @samp{-nostdlib} and
@samp{-nodefaultlibs} is @file{libgcc.a}, a library of internal subroutines
-that GNU CC uses to overcome shortcomings of particular machines, or special
+that GCC uses to overcome shortcomings of particular machines, or special
needs for some languages.
@ifset INTERNALS
-(@xref{Interface,,Interfacing to GNU CC Output}, for more discussion of
+(@xref{Interface,,Interfacing to GCC Output}, for more discussion of
@file{libgcc.a}.)
@end ifset
@ifclear INTERNALS
-(@xref{Interface,,Interfacing to GNU CC Output,gcc.info,Porting GNU CC},
+(@xref{Interface,,Interfacing to GCC Output,gcc.info,Porting GCC},
for more discussion of @file{libgcc.a}.)
@end ifclear
In most cases, you need @file{libgcc.a} even when you want to avoid
other standard libraries. In other words, when you specify @samp{-nostdlib}
or @samp{-nodefaultlibs} you should usually specify @samp{-lgcc} as well.
-This ensures that you have no unresolved references to internal GNU CC
+This ensures that you have no unresolved references to internal GCC
library subroutines. (For example, @samp{__main}, used to ensure C++
constructors will be called; @pxref{Collect2,,@code{collect2}}.)
@@ -2824,7 +2884,7 @@ this option.
@item -Xlinker @var{option}
Pass @var{option} as an option to the linker. You can use this to
-supply system-specific linker options which GNU CC does not know how to
+supply system-specific linker options which GCC does not know how to
recognize.
If you want to pass an option that takes an argument, you must use
@@ -2939,24 +2999,24 @@ are processed in order, from left to right.
@cindex compiler version, specifying
@cindex target machine, specifying
-By default, GNU CC compiles code for the same type of machine that you
+By default, GCC compiles code for the same type of machine that you
are using. However, it can also be installed as a cross-compiler, to
compile for some other type of machine. In fact, several different
-configurations of GNU CC, for different target machines, can be
+configurations of GCC, for different target machines, can be
installed side by side. Then you specify which one to use with the
@samp{-b} option.
-In addition, older and newer versions of GNU CC can be installed side
+In addition, older and newer versions of GCC can be installed side
by side. One of them (probably the newest) will be the default, but
you may sometimes wish to use another.
@table @code
@item -b @var{machine}
The argument @var{machine} specifies the target machine for compilation.
-This is useful when you have installed GNU CC as a cross-compiler.
+This is useful when you have installed GCC as a cross-compiler.
The value to use for @var{machine} is the same as was specified as the
-machine type when configuring GNU CC as a cross-compiler. For
+machine type when configuring GCC as a cross-compiler. For
example, if a cross-compiler was configured with @samp{configure
i386v}, meaning to compile for an 80386 running System V, then you
would specify @samp{-b i386v} to run that cross compiler.
@@ -2965,17 +3025,17 @@ When you do not specify @samp{-b}, it normally means to compile for
the same type of machine that you are using.
@item -V @var{version}
-The argument @var{version} specifies which version of GNU CC to run.
+The argument @var{version} specifies which version of GCC to run.
This is useful when multiple versions are installed. For example,
-@var{version} might be @samp{2.0}, meaning to run GNU CC version 2.0.
+@var{version} might be @samp{2.0}, meaning to run GCC version 2.0.
The default version, when you do not specify @samp{-V}, is the last
-version of GNU CC that you installed.
+version of GCC that you installed.
@end table
The @samp{-b} and @samp{-V} options actually work by controlling part of
the file name used for the executable files and libraries used for
-compilation. A given version of GNU CC, for a given target machine, is
+compilation. A given version of GCC, for a given target machine, is
normally kept in the directory @file{/usr/local/lib/gcc-lib/@var{machine}/@var{version}}.@refill
Thus, sites can customize the effect of @samp{-b} or @samp{-V} either by
@@ -3061,8 +3121,10 @@ that macro, which enables you to change the defaults.
* H8/300 Options::
* SH Options::
* System V Options::
+* TMS320C3x/C4x Options::
* V850 Options::
* ARC Options::
+* NS32K Options::
@end menu
@node M680x0 Options
@@ -3190,13 +3252,13 @@ The @code{rtd} instruction is supported by the 68010, 68020, 68030,
@item -malign-int
@itemx -mno-align-int
-Control whether GNU CC aligns @code{int}, @code{long}, @code{long long},
+Control whether GCC aligns @code{int}, @code{long}, @code{long long},
@code{float}, @code{double}, and @code{long double} variables on a 32-bit
boundary (@samp{-malign-int}) or a 16-bit boundary (@samp{-mno-align-int}).
Aligning variables on 32-bit boundaries produces code that runs somewhat
faster on processors with 32-bit busses at the expense of more memory.
-@strong{Warning:} if you use the @samp{-malign-int} switch, GNU CC will
+@strong{Warning:} if you use the @samp{-malign-int} switch, GCC will
align structures containing the above types differently than
most published application binary interface specifications for the m68k.
@@ -3257,7 +3319,7 @@ cross-compilation. The embedded targets @samp{sparc-*-aout} and
@samp{-msoft-float} changes the calling convention in the output file;
therefore, it is only useful if you compile @emph{all} of a program with
this option. In particular, you need to compile @file{libgcc.a}, the
-library that comes with GNU CC, with @samp{-msoft-float} in order for
+library that comes with GCC, with @samp{-msoft-float} in order for
this to work.
@item -mhard-quad-float
@@ -3302,7 +3364,7 @@ instructions (except for leaf functions) and is the normal mode of operation.
@itemx -munaligned-doubles
Assume that doubles have 8 byte alignment. This is the default.
-With @samp{-munaligned-doubles}, GNU CC assumes that doubles have 8 byte
+With @samp{-munaligned-doubles}, GCC assumes that doubles have 8 byte
alignment only if they are contained in another type, or if they have an
absolute address. Otherwise, it assumes they have 4 byte alignment.
Specifying this option avoids some rare compatibility problems with code
@@ -3324,7 +3386,7 @@ divide instructions which exist in SPARC v8 but not in SPARC v7.
multiply, integer divide step and scan (@code{ffs}) instructions which
exist in SPARClite but not in SPARC v7.
-These options are deprecated and will be deleted in GNU CC 2.9.
+These options are deprecated and will be deleted in a future GCC release.
They have been replaced with @samp{-mcpu=xxx}.
@item -mcypress
@@ -3339,15 +3401,15 @@ With @samp{-msupersparc} the compiler optimizes code for the SuperSparc cpu, as
used in the SparcStation 10, 1000 and 2000 series. This flag also enables use
of the full SPARC v8 instruction set.
-These options are deprecated and will be deleted in GNU CC 2.9.
+These options are deprecated and will be deleted in a future GCC release.
They have been replaced with @samp{-mcpu=xxx}.
@item -mcpu=@var{cpu_type}
Set the instruction set, register set, and instruction scheduling parameters
for machine type @var{cpu_type}. Supported values for @var{cpu_type} are
@samp{v7}, @samp{cypress}, @samp{v8}, @samp{supersparc}, @samp{sparclite},
-@samp{f930}, @samp{f934}, @samp{sparclet}, @samp{tsc701}, @samp{v9}, and
-@samp{ultrasparc}.
+@samp{hypersparc}, @samp{sparclite86x}, @samp{f930}, @samp{f934},
+@samp{sparclet}, @samp{tsc701}, @samp{v9}, and @samp{ultrasparc}.
Default instruction scheduling parameters are used for values that select
an architecture and not an implementation. These are @samp{v7}, @samp{v8},
@@ -3358,8 +3420,8 @@ implementations.
@smallexample
v7: cypress
- v8: supersparc
- sparclite: f930, f934
+ v8: supersparc, hypersparc
+ sparclite: f930, f934, sparclite86x
sparclet: tsc701
v9: ultrasparc
@end smallexample
@@ -3372,7 +3434,8 @@ option @samp{-mcpu=}@var{cpu_type} would.
The same values for @samp{-mcpu=}@var{cpu_type} are used for
@samp{-mtune=}@*@var{cpu_type}, though the only useful values are those that
select a particular cpu implementation: @samp{cypress}, @samp{supersparc},
-@samp{f930}, @samp{f934}, @samp{tsc701}, @samp{ultrasparc}.
+@samp{hypersparc}, @samp{f930}, @samp{f934}, @samp{sparclite86x},
+@samp{tsc701}, @samp{ultrasparc}.
@item -malign-loops=@var{num}
Align loops to a 2 raised to a @var{num} byte boundary. If
@@ -3452,7 +3515,7 @@ Programs are statically linked, PIC is not supported.
@item -mstack-bias
@itemx -mno-stack-bias
-With @samp{-mstack-bias}, GNU CC assumes that the stack pointer, and
+With @samp{-mstack-bias}, GCC assumes that the stack pointer, and
frame pointer if present, are offset by -2047 which must be added back
when making stack frame references.
Otherwise, assume no such offset is present.
@@ -3619,11 +3682,16 @@ not pass @samp{-assert pure-text} to the linker when linking a shared object.
@item -msoft-float
@kindex -msoft-float
Generate output containing library calls for floating point.
-@strong{Warning:} the requisite libraries are not part of GNU CC.
+@strong{Warning:} the requisite libraries are not part of GCC.
Normally the facilities of the machine's usual C compiler are used, but
this can't be done directly in cross-compilation. You must make your
own arrangements to provide suitable library functions for
cross-compilation.
+
+@item -mno-multm
+@kindex -mno-multm
+Do not generate multm or multmu instructions. This is useful for some embedded
+systems which do not have trap handlers for these instructions.
@end table
@node ARM Options
@@ -3723,7 +3791,7 @@ cross-compilation.
@samp{-msoft-float} changes the calling convention in the output file;
therefore, it is only useful if you compile @emph{all} of a program with
this option. In particular, you need to compile @file{libgcc.a}, the
-library that comes with GNU CC, with @samp{-msoft-float} in order for
+library that comes with GCC, with @samp{-msoft-float} in order for
this to work.
@item -mlittle-endian
@@ -3783,13 +3851,17 @@ suppresses this pass. The post-processor is never run when the
compiler is built for cross-compilation.
@item -mcpu=<name>
+@itemx -mtune=<name>
@kindex -mcpu=
+@kindex -mtune=
This specifies the name of the target ARM processor. GCC uses this name
to determine what kind of instructions it can use when generating
assembly code. Permissable names are: arm2, arm250, arm3, arm6, arm60,
arm600, arm610, arm620, arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi,
arm70, arm700, arm700i, arm710, arm710c, arm7100, arm7500, arm7500fe,
-arm7tdmi, arm8, strongarm, strongarm110
+arm7tdmi, arm8, strongarm, strongarm110, strongarm1100, arm8, arm810,
+arm9, arm9tdmi. @samp{-mtune=} is a synonym for @samp{-mcpue=} to
+support older versions of GCC.
@item -march=<name>
@kindex -march=
@@ -3800,9 +3872,12 @@ of the @samp{-mcpu=} option. Permissable names are: armv2, armv2a,
armv3, armv3m, armv4, armv4t
@item -mfpe=<number>
+@itemx -mfp=<number>
@kindex -mfpe=
+@kindex -mfp=
This specifes the version of the floating point emulation available on
-the target. Permissable values are 2 and 3.
+the target. Permissable values are 2 and 3. @samp{-mfp=} is a synonym
+for @samp{-mfpe=} to support older versions of GCC.
@item -mstructure-size-boundary=<n>
@kindex -mstructure-size-boundary
@@ -3817,6 +3892,12 @@ libraries compiled with the other value, if they exchange information
using structures or unions. Programmers are encouraged to use the 32
value as future versions of the toolchain may default to this value.
+@item -mabort-on-noreturn
+@kindex -mabort-on-noreturn
+@kindex -mnoabort-on-noreturn
+Generate a call to the function abort at the end of a noreturn function.
+It will be executed if the function tries to return.
+
@end table
@node Thumb Options
@@ -4053,7 +4134,7 @@ Control how function arguments are stored in stack frames.
@samp{-moptimize-arg-area} saves space by optimizing them, but this
conflicts with the 88open specifications. The opposite alternative,
@samp{-mno-optimize-arg-area}, agrees with 88open standards. By default
-GNU CC does not optimize the argument area.
+GCC does not optimize the argument area.
@item -mshort-data-@var{num}
@kindex -mshort-data-@var{num}
@@ -4113,7 +4194,7 @@ Which variant of the assembler syntax to emit.
@samp{-msvr4} makes the C preprocessor recognize @samp{#pragma weak}
that is used on System V release 4.
@item
-@samp{-msvr4} makes GNU CC issue additional declaration directives used in
+@samp{-msvr4} makes GCC issue additional declaration directives used in
SVr4.
@end enumerate
@@ -4184,7 +4265,7 @@ particular, the behavior of such a division with and without
@cindex bit shift overflow (88k)
@cindex large bit shifts (88k)
Include code to detect bit-shifts of more than 31 bits; respectively,
-trap such shifts or emit code to handle them properly. By default GNU CC
+trap such shifts or emit code to handle them properly. By default GCC
makes no special provision for large bit shifts.
@item -mwarn-passed-structs
@@ -4193,7 +4274,7 @@ makes no special provision for large bit shifts.
Warn when a function passes a struct as an argument or result.
Structure-passing conventions have changed during the evolution of the C
language, and are often the source of portability problems. By default,
-GNU CC issues no such warning.
+GCC issues no such warning.
@end table
@node RS/6000 and PowerPC Options
@@ -4221,7 +4302,7 @@ These @samp{-m} options are defined for the IBM RS/6000 and PowerPC:
@kindex -mpowerpc-gpopt
@kindex -mpowerpc-gfxopt
@kindex -mpowerpc64
-GNU CC supports two related instruction set architectures for the
+GCC supports two related instruction set architectures for the
RS/6000 and PowerPC. The @dfn{POWER} instruction set are those
instructions supported by the @samp{rios} chip set used in the original
RS/6000 systems and the @dfn{PowerPC} instruction set is the
@@ -4234,36 +4315,36 @@ register is included in processors supporting the POWER architecture.
You use these options to specify which instructions are available on the
processor you are using. The default value of these options is
-determined when configuring GNU CC. Specifying the
+determined when configuring GCC. Specifying the
@samp{-mcpu=@var{cpu_type}} overrides the specification of these
options. We recommend you use the @samp{-mcpu=@var{cpu_type}} option
rather than the options listed above.
-The @samp{-mpower} option allows GNU CC to generate instructions that
+The @samp{-mpower} option allows GCC to generate instructions that
are found only in the POWER architecture and to use the MQ register.
-Specifying @samp{-mpower2} implies @samp{-power} and also allows GNU CC
+Specifying @samp{-mpower2} implies @samp{-power} and also allows GCC
to generate instructions that are present in the POWER2 architecture but
not the original POWER architecture.
-The @samp{-mpowerpc} option allows GNU CC to generate instructions that
+The @samp{-mpowerpc} option allows GCC to generate instructions that
are found only in the 32-bit subset of the PowerPC architecture.
Specifying @samp{-mpowerpc-gpopt} implies @samp{-mpowerpc} and also allows
-GNU CC to use the optional PowerPC architecture instructions in the
+GCC to use the optional PowerPC architecture instructions in the
General Purpose group, including floating-point square root. Specifying
-@samp{-mpowerpc-gfxopt} implies @samp{-mpowerpc} and also allows GNU CC to
+@samp{-mpowerpc-gfxopt} implies @samp{-mpowerpc} and also allows GCC to
use the optional PowerPC architecture instructions in the Graphics
group, including floating-point select.
-The @samp{-mpowerpc64} option allows GNU CC to generate the additional
+The @samp{-mpowerpc64} option allows GCC to generate the additional
64-bit instructions that are found in the full PowerPC64 architecture
-and to treat GPRs as 64-bit, doubleword quantities. GNU CC defaults to
+and to treat GPRs as 64-bit, doubleword quantities. GCC defaults to
@samp{-mno-powerpc64}.
-If you specify both @samp{-mno-power} and @samp{-mno-powerpc}, GNU CC
+If you specify both @samp{-mno-power} and @samp{-mno-powerpc}, GCC
will use only the instructions in the common subset of both
architectures plus some special AIX common-mode calls, and will not use
the MQ register. Specifying both @samp{-mpower} and @samp{-mpowerpc}
-permits GNU CC to use any instruction from either architecture and to
+permits GCC to use any instruction from either architecture and to
allow use of the MQ register; specify this for the Motorola MPC601.
@item -mnew-mnemonics
@@ -4275,10 +4356,10 @@ Select which mnemonics to use in the generated assembler code.
defined for the PowerPC architecture, while @samp{-mold-mnemonics}
requests the assembler mnemonics defined for the POWER architecture.
Instructions defined in only one architecture have only one mnemonic;
-GNU CC uses that mnemonic irrespective of which of these options is
+GCC uses that mnemonic irrespective of which of these options is
specified.
-GNU CC defaults to the mnemonics appropriate for the architecture in
+GCC defaults to the mnemonics appropriate for the architecture in
use. Specifying @samp{-mcpu=@var{cpu_type}} sometimes overrides the
value of these option. Unless you are building a cross-compiler, you
should normally not specify either @samp{-mnew-mnemonics} or
@@ -4290,13 +4371,13 @@ Set architecture type, register usage, choice of mnemonics, and
instruction scheduling parameters for machine type @var{cpu_type}.
Supported values for @var{cpu_type} are @samp{rs6000}, @samp{rios1},
@samp{rios2}, @samp{rsc}, @samp{601}, @samp{602}, @samp{603},
-@samp{603e}, @samp{604}, @samp{604e}, @samp{620}, @samp{power},
-@samp{power2}, @samp{powerpc}, @samp{403}, @samp{505}, @samp{801},
-@samp{821}, @samp{823}, and @samp{860} and @samp{common}.
-@samp{-mcpu=power}, @samp{-mcpu=power2}, and @samp{-mcpu=powerpc}
-specify generic POWER, POWER2 and pure PowerPC (i.e., not MPC601)
-architecture machine types, with an appropriate, generic processor model
-assumed for scheduling purposes.@refill
+@samp{603e}, @samp{604}, @samp{604e}, @samp{620}, @samp{740},
+@samp{750}, @samp{power}, @samp{power2}, @samp{powerpc}, @samp{403},
+@samp{505}, @samp{801}, @samp{821}, @samp{823}, and @samp{860} and
+@samp{common}. @samp{-mcpu=power}, @samp{-mcpu=power2}, and
+@samp{-mcpu=powerpc} specify generic POWER, POWER2 and pure PowerPC
+(i.e., not MPC601) architecture machine types, with an appropriate,
+generic processor model assumed for scheduling purposes.@refill
@c overfull hbox here --bob 22 jul96
@c original text between ignore ... end ignore
@@ -4331,9 +4412,9 @@ enable the @samp{-mpowerpc} option and disable the @samp{-mpower} option.
AIX versions 4 or greater selects @samp{-mcpu=common} by default, so
that code will operate on all members of the RS/6000 and PowerPC
-families. In that case, GNU CC will use only the instructions in the
+families. In that case, GCC will use only the instructions in the
common subset of both architectures plus some special AIX common-mode
-calls, and will not use the MQ register. GNU CC assumes a generic
+calls, and will not use the MQ register. GCC assumes a generic
processor model for scheduling purposes.
Specifying any of the options @samp{-mcpu=rios1}, @samp{-mcpu=rios2},
@@ -4362,25 +4443,25 @@ instruction scheduling parameters.
@kindex -mminimal-toc
Modify generation of the TOC (Table Of Contents), which is created for
every executable file. The @samp{-mfull-toc} option is selected by
-default. In that case, GNU CC will allocate at least one TOC entry for
-each unique non-automatic variable reference in your program. GNU CC
+default. In that case, GCC will allocate at least one TOC entry for
+each unique non-automatic variable reference in your program. GCC
will also place floating-point constants in the TOC. However, only
16,384 entries are available in the TOC.
If you receive a linker error message that saying you have overflowed
the available TOC space, you can reduce the amount of TOC space used
with the @samp{-mno-fp-in-toc} and @samp{-mno-sum-in-toc} options.
-@samp{-mno-fp-in-toc} prevents GNU CC from putting floating-point
-constants in the TOC and @samp{-mno-sum-in-toc} forces GNU CC to
+@samp{-mno-fp-in-toc} prevents GCC from putting floating-point
+constants in the TOC and @samp{-mno-sum-in-toc} forces GCC to
generate code to calculate the sum of an address and a constant at
run-time instead of putting that sum into the TOC. You may specify one
-or both of these options. Each causes GNU CC to produce very slightly
+or both of these options. Each causes GCC to produce very slightly
slower and larger code at the expense of conserving TOC space.
If you still run out of space in the TOC even when you specify both of
these options, specify @samp{-mminimal-toc} instead. This option causes
-GNU CC to make only one TOC entry for every file. When you specify this
-option, GNU CC will produce code that is slower and larger but which
+GCC to make only one TOC entry for every file. When you specify this
+option, GCC will produce code that is slower and larger but which
uses extremely little TOC space. You may wish to use this option
only on files that contain less frequently executed code. @refill
@@ -4392,7 +4473,7 @@ Enable AIX 64-bit ABI and calling convention: 64-bit pointers, 64-bit
@code{long} type, and the infrastructure needed to support them.
Specifying @samp{-maix64} implies @samp{-mpowerpc64} and
@samp{-mpowerpc}, while @samp{-maix32} disables the 64-bit ABI and
-implies @samp{-mno-powerpc64}. GNU CC defaults to @samp{-maix32}.
+implies @samp{-mno-powerpc64}. GCC defaults to @samp{-maix32}.
@item -mxl-call
@itemx -mno-xl-call
@@ -4431,7 +4512,7 @@ option are incompatible.
@kindex -msoft-float
Generate code that does not use (uses) the floating-point register set.
Software floating point emulation is provided if you use the
-@samp{-msoft-float} option, and pass the option to GNU CC when linking.
+@samp{-msoft-float} option, and pass the option to GCC when linking.
@item -mmultiple
@itemx -mno-multiple
@@ -4440,17 +4521,20 @@ instructions and the store multiple word instructions. These
instructions are generated by default on POWER systems, and not
generated on PowerPC systems. Do not use @samp{-mmultiple} on little
endian PowerPC systems, since those instructions do not work when the
-processor is in little endian mode.
+processor is in little endian mode. The exceptions are PPC740 and
+PPC750 which permit the instructions usage in little endian mode.
@item -mstring
@itemx -mno-string
@kindex -mstring
-Generate code that uses (does not use) the load string instructions and the
-store string word instructions to save multiple registers and do small block
-moves. These instructions are generated by default on POWER systems, and not
-generated on PowerPC systems. Do not use @samp{-mstring} on little endian
-PowerPC systems, since those instructions do not work when the processor is in
-little endian mode.
+Generate code that uses (does not use) the load string instructions
+and the store string word instructions to save multiple registers and
+do small block moves. These instructions are generated by default on
+POWER systems, and not generated on PowerPC systems. Do not use
+@samp{-mstring} on little endian PowerPC systems, since those
+instructions do not work when the processor is in little endian mode.
+The exceptions are PPC740 and PPC750 which permit the instructions
+usage in little endian mode.
@item -mupdate
@itemx -mno-update
@@ -4650,7 +4734,9 @@ All modules should be compiled with the same @samp{-G @var{num}} value.
@itemx -mno-regnames
On System V.4 and embedded PowerPC systems do (do not) emit register
names in the assembly language output using symbolic forms.
+
@end table
+
@node RT Options
@subsection IBM RT Options
@cindex RT options
@@ -4710,11 +4796,15 @@ These @samp{-m} options are defined for the MIPS family of computers:
@item -mcpu=@var{cpu type}
Assume the defaults for the machine type @var{cpu type} when scheduling
instructions. The choices for @var{cpu type} are @samp{r2000}, @samp{r3000},
-@samp{r4000}, @samp{r4400}, @samp{r4600}, and @samp{r6000}. While picking a
-specific @var{cpu type} will schedule things appropriately for that
-particular chip, the compiler will not generate any code that does not
-meet level 1 of the MIPS ISA (instruction set architecture) without
-the @samp{-mips2} or @samp{-mips3} switches being used.
+@samp{r3900}, @samp{r4000}, @samp{r4100}, @samp{r4300}, @samp{r4400},
+@samp{r4600}, @samp{r4650}, @samp{r5000}, @samp{r6000}, @samp{r8000},
+and @samp{orion}. Additionally, the @samp{r2000}, @samp{r3000},
+@samp{r4000}, @samp{r5000}, and @samp{r6000} can be abbreviated as
+@samp{r2k} (or @samp{r2K}), @samp{r3k}, etc. While picking a specific
+@var{cpu type} will schedule things appropriately for that particular
+chip, the compiler will not generate any code that does not meet level 1
+of the MIPS ISA (instruction set architecture) without a @samp{-mipsX}
+or @samp{-mabi} switch being used.
@item -mips1
Issue instructions from level 1 of the MIPS ISA. This is the default.
@@ -4728,11 +4818,11 @@ ISA level.
@item -mips3
Issue instructions from level 3 of the MIPS ISA (64 bit instructions).
@samp{r4000} is the default @var{cpu type} at this ISA level.
-This option does not change the sizes of any of the C data types.
@item -mips4
-Issue instructions from level 4 of the MIPS ISA. @samp{r8000} is the
-default @var{cpu type} at this ISA level.
+Issue instructions from level 4 of the MIPS ISA (conditional move,
+prefetch, enhanced FPU instructions). @samp{r8000} is the default
+@var{cpu type} at this ISA level.
@item -mfp32
Assume that 32 32-bit floating point registers are available. This is
@@ -4751,18 +4841,36 @@ Assume that 32 64-bit general purpose registers are available. This is
the default when the @samp{-mips3} option is used.
@item -mint64
-Types long, int, and pointer are 64 bits. This works only if @samp{-mips3}
-is also specified.
+Force int and long types to be 64 bits wide. See @samp{-mlong32} for an
+explanation of the default, and the width of pointers.
@item -mlong64
-Types long and pointer are 64 bits, and type int is 32 bits.
-This works only if @samp{-mips3} is also specified.
+Force long types to be 64 bits wide. See @samp{-mlong32} for an
+explanation of the default, and the width of pointers.
-@itemx -mabi=32
+@item -mlong32
+Force long, int, and pointer types to be 32 bits wide.
+
+If none of @samp{-mlong32}, @samp{-mlong64}, or @samp{-mint64} are set,
+the size of ints, longs, and pointers depends on the ABI and ISA choosen.
+For @samp{-mabi=32}, and @samp{-mabi=n32}, ints and longs are 32 bits
+wide. For @samp{-mabi=64}, ints are 32 bits, and longs are 64 bits wide.
+For @samp{-mabi=eabi} and either @samp{-mips1} or @samp{-mips2}, ints
+and longs are 32 bits wide. For @samp{-mabi=eabi} and higher ISAs, ints
+are 32 bits, and longs are 64 bits wide. The width of pointer types is
+the smaller of the width of longs or the width of general purpose
+registers (which in turn depends on the ISA).
+
+@item -mabi=32
+@itemx -mabi=o64
@itemx -mabi=n32
@itemx -mabi=64
@itemx -mabi=eabi
-Generate code for the indicated ABI.
+Generate code for the indicated ABI. The default instruction level is
+@samp{-mips1} for @samp{32}, @samp{-mips3} for @samp{n32}, and
+@samp{-mips4} otherwise. Conversely, with @samp{-mips1} or
+@samp{-mips2}, the default ABI is @samp{32}; otherwise, the default ABI
+is @samp{64}.
@item -mmips-as
Generate code for the MIPS assembler, and invoke @file{mips-tfile} to
@@ -4828,7 +4936,7 @@ prevents compilation.
@item -msoft-float
Generate output containing library calls for floating point.
-@strong{Warning:} the requisite libraries are not part of GNU CC.
+@strong{Warning:} the requisite libraries are not part of GCC.
Normally the facilities of the machine's usual C compiler are used, but
this can't be done directly in cross-compilation. You must make your
own arrangements to provide suitable library functions for
@@ -4887,6 +4995,14 @@ as on the @samp{r4650} chip.
Turns on @samp{-msingle-float}, @samp{-mmad}, and, at least for now,
@samp{-mcpu=r4650}.
+@item -mips16
+@itemx -mno-mips16
+Enable 16-bit instructions.
+
+@item -mentry
+Use the entry and exit pseudo ops. This option can only be used with
+@samp{-mips16}.
+
@item -EL
Compile code for the processor in little endian mode.
The requisite libraries are assumed to exist.
@@ -4930,25 +5046,31 @@ These @samp{-m} options are defined for the i386 family of computers:
@table @code
@item -mcpu=@var{cpu type}
Assume the defaults for the machine type @var{cpu type} when scheduling
-instructions. The choices for @var{cpu type} are: @samp{i386},
-@samp{i486}, @samp{i586} (@samp{pentium}), @samp{pentium}, @samp{i686}
-(@samp{pentiumpro}) and @samp{pentiumpro}. While picking a specific
-@var{cpu type} will schedule things appropriately for that particular
-chip, the compiler will not generate any code that does not run on the
-i386 without the @samp{-march=@var{cpu type}} option being used.
+instructions. The choices for @var{cpu type} are:
+
+@multitable @columnfractions .20 .20 .20 .20
+@item @samp{i386} @tab @samp{i486} @tab @samp{i586} @tab @samp{i686}
+@item @samp{pentium} @tab @samp{pentiumpro} @tab @samp{k6}
+@end multitable
+
+While picking a specific @var{cpu type} will schedule things appropriately
+for that particular chip, the compiler will not generate any code that
+does not run on the i386 without the @samp{-march=@var{cpu type}} option
+being used. @samp{i586} is equivalent to @samp{pentium} and @samp{i686}
+is equivalent to @samp{pentiumpro}. @samp{k6} is the AMD chip as
+opposed to the Intel ones.
@item -march=@var{cpu type}
Generate instructions for the machine type @var{cpu type}. The choices
-for @var{cpu type} are: @samp{i386}, @samp{i486}, @samp{pentium}, and
-@samp{pentiumpro}. Specifying @samp{-march=@var{cpu type}} implies
-@samp{-mcpu=@var{cpu type}}.
+for @var{cpu type} are the same as for @samp{-mcpu}. Moreover,
+specifying @samp{-march=@var{cpu type}} implies @samp{-mcpu=@var{cpu type}}.
@item -m386
@itemx -m486
@itemx -mpentium
@itemx -mpentiumpro
Synonyms for -mcpu=i386, -mcpu=i486, -mcpu=pentium, and -mcpu=pentiumpro
-respectively.
+respectively. These synonyms are deprecated.
@item -mieee-fp
@itemx -mno-ieee-fp
@@ -4958,7 +5080,7 @@ comparison is unordered.
@item -msoft-float
Generate output containing library calls for floating point.
-@strong{Warning:} the requisite libraries are not part of GNU CC.
+@strong{Warning:} the requisite libraries are not part of GCC.
Normally the facilities of the machine's usual C compiler are used, but
this can't be done directly in cross-compilation. You must make your
own arrangements to provide suitable library functions for
@@ -4988,7 +5110,7 @@ also use the @samp{-ffast-math} switch.
@item -malign-double
@itemx -mno-align-double
-Control whether GNU CC aligns @code{double}, @code{long double}, and
+Control whether GCC aligns @code{double}, @code{long double}, and
@code{long long} variables on a two word boundary or a one word
boundary. Aligning @code{double} variables on a two word boundary will
produce code that runs somewhat faster on a @samp{Pentium} at the
@@ -5000,13 +5122,13 @@ the published application binary interface specifications for the 386.
@item -msvr3-shlib
@itemx -mno-svr3-shlib
-Control whether GNU CC places uninitialized locals into @code{bss} or
+Control whether GCC places uninitialized locals into @code{bss} or
@code{data}. @samp{-msvr3-shlib} places these locals into @code{bss}.
These options are meaningful only on System V Release 3.
@item -mno-wide-multiply
@itemx -mwide-multiply
-Control whether GNU CC uses the @code{mul} and @code{imul} that produce
+Control whether GCC uses the @code{mul} and @code{imul} that produce
64 bit results in @code{eax:edx} from 32 bit operands to do @code{long
long} multiplies and 32-bit division by constants.
@@ -5073,6 +5195,31 @@ than 8 bytes away.
Align the start of functions to a 2 raised to @var{num} byte boundary.
If @samp{-malign-functions} is not specified, the default is 2 if optimizing
for a 386, and 4 if optimizing for a 486.
+
+@item -mpreferred-stack-boundary=@var{num}
+Attempt to keep the stack boundary aligned to a 2 raised to @var{num}
+byte boundary. If @samp{-mpreferred-stack-boundary} is not specified,
+the default is 4 (16 bytes or 128 bits).
+
+The stack is required to be aligned on a 4 byte boundary. On Pentium
+and PentiumPro, @code{double} and @code{long double} values should be
+aligned to an 8 byte boundary (see @samp{-malign-double}) or suffer
+significant run time performance penalties. On Pentium III, the
+Streaming SIMD Extention (SSE) data type @code{__m128} suffers similar
+penalties if it is not 16 byte aligned.
+
+To ensure proper alignment of this values on the stack, the stack boundary
+must be as aligned as that required by any value stored on the stack.
+Further, every function must be generated such that it keeps the stack
+aligned. Thus calling a function compiled with a higher preferred
+stack boundary from a function compiled with a lower preferred stack
+boundary will most likely misalign the stack. It is recommended that
+libraries that use callbacks always use the default setting.
+
+This extra alignment does consume extra stack space. Code that is sensitive
+to stack space usage, such as embedded systems and operating system kernels,
+may want to reduce the preferred alignment to
+@samp{-mpreferred-stack-boundary=2}.
@end table
@node HPPA Options
@@ -5082,11 +5229,23 @@ for a 386, and 4 if optimizing for a 486.
These @samp{-m} options are defined for the HPPA family of computers:
@table @code
-@item -mpa-risc-1-0
-Generate code for a PA 1.0 processor.
+@item -march=@var{architecture type}
+Generate code for the specified architecture. The choices for
+@var{architecture type} are @samp{1.0} for PA 1.0, @samp{1.1} for PA
+1.1, and @samp{2.0} for PA 2.0 processors. Refer to
+@file{/usr/lib/sched.models} on an HP-UX system to determine the proper
+architecture option for your machine. Code compiled for lower numbered
+architectures will run on higher numbered architectures, but not the
+other way around.
+
+PA 2.0 support currently requires gas snapshot 19990413 or later. The
+next release of binutils (current is 2.9.1) will probably contain PA 2.0
+support.
-@item -mpa-risc-1-1
-Generate code for a PA 1.1 processor.
+@item -mpa-risc-1-0
+@itemx -mpa-risc-1-1
+@itemx -mpa-risc-2-0
+Synonyms for -march=1.0, -march=1.1, and -march=2.0 respectively.
@item -mbig-switch
Generate code suitable for big switch tables. Use this option only if
@@ -5139,13 +5298,10 @@ Enable the use of assembler directives only GAS understands.
@item -mschedule=@var{cpu type}
Schedule code according to the constraints for the machine type
-@var{cpu type}. The choices for @var{cpu type} are @samp{700} for
-7@var{n}0 machines, @samp{7100} for 7@var{n}5 machines, and @samp{7100LC}
-for 7@var{n}2 machines. @samp{7100} is the default for @var{cpu type}.
-
-Note the @samp{7100LC} scheduling information is incomplete and using
-@samp{7100LC} often leads to bad schedules. For now it's probably best
-to use @samp{7100} instead of @samp{7100LC} for the 7@var{n}2 machines.
+@var{cpu type}. The choices for @var{cpu type} are @samp{700}
+@samp{7100}, @samp{7100LC}, @samp{7200}, and @samp{8000}. Refer to
+@file{/usr/lib/sched.models} on an HP-UX system to determine the
+proper scheduling option for your machine.
@item -mlinker-opt
Enable the optimization pass in the HPUX linker. Note this makes symbolic
@@ -5164,7 +5320,7 @@ does provide software floating point support.
@samp{-msoft-float} changes the calling convention in the output file;
therefore, it is only useful if you compile @emph{all} of a program with
this option. In particular, you need to compile @file{libgcc.a}, the
-library that comes with GNU CC, with @samp{-msoft-float} in order for
+library that comes with GCC, with @samp{-msoft-float} in order for
this to work.
@end table
@@ -5241,6 +5397,15 @@ Do not permit (do permit) unaligned accesses.
@item -mold-align
Enable structure-alignment compatibility with Intel's gcc release version
1.3 (based on gcc 1.37). This option implies @samp{-mstrict-align}.
+
+@item -mlong-double-64
+Implement type @samp{long double} as 64-bit floating point numbers.
+Without the option @samp{long double} is implemented by 80-bit
+floating point numbers. The only reason we have it because there is
+no 128-bit @samp{long double} support in @samp{fp-bit.c} yet. So it
+is only useful for people using soft-float targets. Otherwise, we
+should recommend against use of it.
+
@end table
@node DEC Alpha Options
@@ -5367,13 +5532,14 @@ Dynamic rounding mode. A field in the floating point control register
(@var{fpcr}, see Alpha architecture reference manual) controls the
rounding mode in effect. The C library initializes this register for
rounding towards plus infinity. Thus, unless your program modifies the
-@var{fpcr}, @samp{d} corresponds to round towards plus infinity.@end table
+@var{fpcr}, @samp{d} corresponds to round towards plus infinity.
+@end table
@item -mtrap-precision=@var{trap precision}
In the Alpha architecture, floating point traps are imprecise. This
means without software assistance it is impossible to recover from a
floating trap and program execution normally needs to be terminated.
-GNU CC can generate code that can assist operating system trap handlers
+GCC can generate code that can assist operating system trap handlers
in determining the exact location that caused a floating point trap.
Depending on the requirements of an application, different levels of
precisions can be selected:
@@ -5404,12 +5570,12 @@ generated assembly file. Under DEC Unix, this has the effect that
IEEE-conformant math library routines will be linked in.
@item -mbuild-constants
-Normally GNU CC examines a 32- or 64-bit integer constant to
+Normally GCC examines a 32- or 64-bit integer constant to
see if it can construct it from smaller constants in two or three
instructions. If it cannot, it will output the constant as a literal and
generate code to load it from the data segment at runtime.
-Use this option to require GNU CC to construct @emph{all} integer constants
+Use this option to require GCC to construct @emph{all} integer constants
using code, even if it takes more instructions (the maximum is six).
You would typically use this option to build a shared library dynamic
@@ -5427,19 +5593,19 @@ assembler (@samp{-malpha-as}) or by the GNU assembler @samp{-mgas}.
@itemx -mno-cix
@itemx -mmax
@itemx -mno-max
-Indicate whether GNU CC should generate code to use the optional BWX,
+Indicate whether GCC should generate code to use the optional BWX,
CIX, and MAX instruction sets. The default is to use the instruction sets
supported by the CPU type specified via @samp{-mcpu=} option or that
-of the CPU on which GNU CC was built if none was specified.
+of the CPU on which GCC was built if none was specified.
@item -mcpu=@var{cpu_type}
Set the instruction set, register set, and instruction scheduling
parameters for machine type @var{cpu_type}. You can specify either the
-@samp{EV} style name or the corresponding chip number. GNU CC
+@samp{EV} style name or the corresponding chip number. GCC
supports scheduling parameters for the EV4 and EV5 family of processors
and will choose the default values for the instruction set from
the processor you specify. If you do not specify a processor type,
-GNU CC will default to the processor on which the compiler was built.
+GCC will default to the processor on which the compiler was built.
Supported values for @var{cpu_type} are
@@ -5500,7 +5666,7 @@ These @samp{-m} options are defined for the Clipper implementations:
@item -mc300
Produce code for a C300 Clipper processor. This is the default.
-@itemx -mc400
+@item -mc400
Produce code for a C400 Clipper processor i.e. use floating point
registers f8..f15.
@end table
@@ -5596,6 +5762,130 @@ The assembler uses this option.
@c the generic assembler that comes with Solaris takes just -Ym.
@end table
+@node TMS320C3x/C4x Options
+@subsection TMS320C3x/C4x Options
+@cindex TMS320C3x/C4x Options
+
+These @samp{-m} options are defined for TMS320C3x/C4x implementations:
+
+@table @code
+
+@item -mcpu=@var{cpu_type}
+Set the instruction set, register set, and instruction scheduling
+parameters for machine type @var{cpu_type}. Supported values for
+@var{cpu_type} are @samp{c30}, @samp{c31}, @samp{c32}, @samp{c40}, and
+@samp{c44}. The default is @samp{c40} to generate code for the
+TMS320C40.
+
+@item -mbig-memory
+@item -mbig
+@itemx -msmall-memory
+@itemx -msmall
+Generates code for the big or small memory model. The small memory
+model assumed that all data fits into one 64K word page. At run-time
+the data page (DP) register must be set to point to the 64K page
+containing the .bss and .data program sections. The big memory model is
+the default and requires reloading of the DP register for every direct
+memory access.
+
+@item -mbk
+@itemx -mno-bk
+Allow (disallow) allocation of general integer operands into the block
+count register BK.
+
+@item -mdb
+@itemx -mno-db
+Enable (disable) generation of code using decrement and branch,
+DBcond(D), instructions. This is enabled by default for the C4x. To be
+on the safe side, this is disabled for the C3x, since the maximum
+iteration count on the C3x is 2^23 + 1 (but who iterates loops more than
+2^23 times on the C3x?). Note that GCC will try to reverse a loop so
+that it can utilise the decrement and branch instruction, but will give
+up if there is more than one memory reference in the loop. Thus a loop
+where the loop counter is decremented can generate slightly more
+efficient code, in cases where the RPTB instruction cannot be utilised.
+
+@item -mdp-isr-reload
+@itemx -mparanoid
+Force the DP register to be saved on entry to an interrupt service
+routine (ISR), reloaded to point to the data section, and restored on
+exit from the ISR. This should not be required unless someone has
+violated the small memory model by modifying the DP register, say within
+an object library.
+
+@item -mmpyi
+@itemx -mno-mpyi
+For the C3x use the 24-bit MPYI instruction for integer multiplies
+instead of a library call to guarantee 32-bit results. Note that if one
+of the operands is a constant, then the multiplication will be performed
+using shifts and adds. If the -mmpyi option is not specified for the C3x,
+then squaring operations are performed inline instead of a library call.
+
+@item -mfast-fix
+@itemx -mno-fast-fix
+The C3x/C4x FIX instruction to convert a floating point value to an
+integer value chooses the nearest integer less than or equal to the
+floating point value rather than to the nearest integer. Thus if the
+floating point number is negative, the result will be incorrectly
+truncated an additional code is necessary to detect and correct this
+case. This option can be used to disable generation of the additional
+code required to correct the result.
+
+@item -mrptb
+@itemx -mno-rptb
+Enable (disable) generation of repeat block sequences using the RPTB
+instruction for zero overhead looping. The RPTB construct is only used
+for innermost loops that do not call functions or jump across the loop
+boundaries. There is no advantage having nested RPTB loops due to the
+overhead required to save and restore the RC, RS, and RE registers.
+This is enabled by default with -O2.
+
+@item -mrpts=@var{count}
+@itemx -mno-rpts
+Enable (disable) the use of the single instruction repeat instruction
+RPTS. If a repeat block contains a single instruction, and the loop
+count can be guaranteed to be less than the value @var{count}, GCC will
+emit a RPTS instruction instead of a RPTB. If no value is specified,
+then a RPTS will be emitted even if the loop count cannot be determined
+at compile time. Note that the repeated instruction following RPTS does
+not have to be reloaded from memory each iteration, thus freeing up the
+CPU buses for oeprands. However, since interrupts are blocked by this
+instruction, it is disabled by default.
+
+@item -mloop-unsigned
+@itemx -mno-loop-unsigned
+The maximum iteration count when using RPTS and RPTB (and DB on the C40)
+is 2^31 + 1 since these instructions test if the iteration count is
+negative to terminate the loop. If the iteration count is unsigned
+there is a possibility than the 2^31 + 1 maximum iteration count may be
+exceeded. This switch allows an unsigned iteration count.
+
+@item -mti
+Try to emit an assembler syntax that the TI assembler (asm30) is happy
+with. This also enforces compatibility with the API employed by the TI
+C3x C compiler. For example, long doubles are passed as structures
+rather than in floating point registers.
+
+@item -mregparm
+@itemx -mmemparm
+Generate code that uses registers (stack) for passing arguments to functions.
+By default, arguments are passed in registers where possible rather
+than by pushing arguments on to the stack.
+
+@item -mparallel-insns
+@itemx -mno-parallel-insns
+Allow the generation of parallel instructions. This is enabled by
+default with -O2.
+
+@item -mparallel-mpy
+@itemx -mno-parallel-mpy
+Allow the generation of MPY||ADD and MPY||SUB parallel instructions,
+provided -mparallel-insns is also specified. These instructions have
+tight register constraints which can pessimize the code generation
+of large functions.
+
+@end table
+
@node V850 Options
@subsection V850 Options
@cindex V850 Options
@@ -5678,8 +5968,8 @@ Which variants are supported depend on the configuration.
All variants support @samp{-mcpu=base}, this is the default.
@item -mtext=@var{text section}
-@item -mdata=@var{data section}
-@item -mrodata=@var{readonly data section}
+@itemx -mdata=@var{data section}
+@itemx -mrodata=@var{readonly data section}
Put functions, data, and readonly data in @var{text section},
@var{data section}, and @var{readonly data section} respectively
by default. This can be overridden with the @code{section} attribute.
@@ -5687,6 +5977,121 @@ by default. This can be overridden with the @code{section} attribute.
@end table
+@node NS32K Options
+@subsection NS32K Options
+@cindex NS32K options
+
+These are the @samp{-m} options defined for the 32000 series. The default
+values for these options depends on which style of 32000 was selected when
+the compiler was configured; the defaults for the most common choices are
+given below.
+
+@table @code
+@item -m32032
+@itemx -m32032
+Generate output for a 32032. This is the default
+when the compiler is configured for 32032 and 32016 based systems.
+
+@item -m32332
+@itemx -m32332
+Generate output for a 32332. This is the default
+when the compiler is configured for 32332-based systems.
+
+@item -m32532
+@itemx -m32532
+Generate output for a 32532. This is the default
+when the compiler is configured for 32532-based systems.
+
+@item -m32081
+Generate output containing 32081 instructions for floating point.
+This is the default for all systems.
+
+@item -m32381
+Generate output containing 32381 instructions for floating point. This
+also implies @samp{-m32081}. The 32381 is only compatible with the 32332
+and 32532 cpus. This is the default for the pc532-netbsd configuration.
+
+@item -mmulti-add
+Try and generate multiply-add floating point instructions @code{polyF}
+and @code{dotF}. This option is only available if the @samp{-m32381}
+option is in effect. Using these instructions requires changes to to
+register allocation which generally has a negative impact on
+performance. This option should only be enabled when compiling code
+particularly likely to make heavy use of multiply-add instructions.
+
+@item -mnomulti-add
+Do not try and generate multiply-add floating point instructions
+@code{polyF} and @code{dotF}. This is the default on all platforms.
+
+@item -msoft-float
+Generate output containing library calls for floating point.
+@strong{Warning:} the requisite libraries may not be available.
+
+@item -mnobitfield
+Do not use the bit-field instructions. On some machines it is faster to
+use shifting and masking operations. This is the default for the pc532.
+
+@item -mbitfield
+Do use the bit-field instructions. This is the default for all platforms
+except the pc532.
+
+@item -mrtd
+Use a different function-calling convention, in which functions
+that take a fixed number of arguments return pop their
+arguments on return with the @code{ret} instruction.
+
+This calling convention is incompatible with the one normally
+used on Unix, so you cannot use it if you need to call libraries
+compiled with the Unix compiler.
+
+Also, you must provide function prototypes for all functions that
+take variable numbers of arguments (including @code{printf});
+otherwise incorrect code will be generated for calls to those
+functions.
+
+In addition, seriously incorrect code will result if you call a
+function with too many arguments. (Normally, extra arguments are
+harmlessly ignored.)
+
+This option takes its name from the 680x0 @code{rtd} instruction.
+
+
+@item -mregparam
+Use a different function-calling convention where the first two arguments
+are passed in registers.
+
+This calling convention is incompatible with the one normally
+used on Unix, so you cannot use it if you need to call libraries
+compiled with the Unix compiler.
+
+@item -mnoregparam
+Do not pass any arguments in registers. This is the default for all
+targets.
+
+@item -msb
+It is OK to use the sb as an index register which is always loaded with
+zero. This is the default for the pc532-netbsd target.
+
+@item -mnosb
+The sb register is not available for use or has not been initialized to
+zero by the run time system. This is the default for all targets except
+the pc532-netbsd. It is also implied whenever @samp{-mhimem} or
+@samp{-fpic} is set.
+
+@item -mhimem
+Many ns32000 series addressing modes use displacements of up to 512MB.
+If an address is above 512MB then displacements from zero can not be used.
+This option causes code to be generated which can be loaded above 512MB.
+This may be useful for operating systems or ROM code.
+
+@item -mnohimem
+Assume code will be loaded in the first 512MB of virtual address space.
+This is the default for all platforms.
+
+
+@end table
+
+
@node Code Gen Options
@section Options for Code Generation Conventions
@@ -5705,9 +6110,12 @@ it.
@table @code
@item -fexceptions
-Enable exception handling, and generate extra code needed to propagate
-exceptions. If you do not specify this option, GNU CC enables it by
-default for languages like C++ that normally require exception handling,
+Enable exception handling. Generates extra code needed to propagate
+exceptions. For some targets, this implies generation of frame unwind
+information for all functions. This can produce significant data size
+overhead, although it does not affect execution.
+If you do not specify this option, it is enabled by
+default for languages like C++ which normally require exception handling,
and disabled for languages like C that do not normally require it.
However, when compiling C code that needs to interoperate properly with
exception handlers written in C++, you may need to enable this option.
@@ -5718,7 +6126,7 @@ programs that don't use exception handling.
Return ``short'' @code{struct} and @code{union} values in memory like
longer ones, rather than in registers. This convention is less
efficient, but it has the advantage of allowing intercallability between
-GNU CC-compiled files and files compiled with other compilers.
+GCC-compiled files and files compiled with other compilers.
The precise convention for returning structures in memory depends
on the target configuration macros.
@@ -5732,9 +6140,9 @@ returned in registers when possible. This is more efficient for small
structures than @samp{-fpcc-struct-return}.
If you specify neither @samp{-fpcc-struct-return} nor its contrary
-@samp{-freg-struct-return}, GNU CC defaults to whichever convention is
-standard for the target. If there is no standard convention, GNU CC
-defaults to @samp{-fpcc-struct-return}, except on targets where GNU CC
+@samp{-freg-struct-return}, GCC defaults to whichever convention is
+standard for the target. If there is no standard convention, GCC
+defaults to @samp{-fpcc-struct-return}, except on targets where GCC
is the principal compiler. In those cases, we can choose the standard,
and we chose the more efficient register return alternative.
@@ -5770,7 +6178,7 @@ destructors) in the form used by the GNU linker (on systems where the GNU
linker is the standard method of handling them). Use this option when
you want to use a non-GNU linker, which also requires using the
@code{collect2} program to make sure the system linker includes
-constructors and destructors. (@code{collect2} is included in the GNU CC
+constructors and destructors. (@code{collect2} is included in the GCC
distribution.) For systems which @emph{must} use @code{collect2}, the
compiler driver @code{gcc} is configured to do this automatically.
@@ -5796,7 +6204,11 @@ Consider all memory references through pointers to be volatile.
@item -fvolatile-global
Consider all memory references to extern and global data items to
-be volatile.
+be volatile. GCC does not consider static data items to be volatile
+because of this switch.
+
+@item -fvolatile-static
+Consider all memory references to static data to be volatile.
@item -fpic
@cindex global offset table
@@ -5805,7 +6217,7 @@ Generate position-independent code (PIC) suitable for use in a shared
library, if supported for the target machine. Such code accesses all
constant addresses through a global offset table (GOT). The dynamic
loader resolves the GOT entries when the program starts (the dynamic
-loader is not part of GNU CC; it is part of the operating system). If
+loader is not part of GCC; it is part of the operating system). If
the GOT size for the linked executable exceeds a machine-specific
maximum size, you get an error message from the linker indicating that
@samp{-fpic} does not work; in that case, recompile with @samp{-fPIC}
@@ -5813,7 +6225,7 @@ instead. (These maximums are 16k on the m88k, 8k on the Sparc, and 32k
on the m68k and RS/6000. The 386 has no such limit.)
Position-independent code requires special support, and therefore works
-only on certain machines. For the 386, GNU CC supports PIC for System V
+only on certain machines. For the 386, GCC supports PIC for System V
but not for the Sun 386i. Code generated for the IBM RS/6000 is always
position-independent.
@@ -5844,9 +6256,9 @@ clobbered by function calls. It may be allocated for temporaries or
variables that do not live across a call. Functions compiled this way
will not save and restore the register @var{reg}.
-Use of this flag for a register that has a fixed pervasive role in the
-machine's execution model, such as the stack pointer or frame pointer,
-will produce disastrous results.
+It is an error to used this flag with the frame pointer or stack pointer.
+Use of this flag for other registers that have fixed pervasive roles in
+the machine's execution model will produce disastrous results.
This flag does not have a negative form, because it specifies a
three-way choice.
@@ -5857,9 +6269,9 @@ functions. It may be allocated even for temporaries or variables that
live across a call. Functions compiled this way will save and restore
the register @var{reg} if they use it.
-Use of this flag for a register that has a fixed pervasive role in the
-machine's execution model, such as the stack pointer or frame pointer,
-will produce disastrous results.
+It is an error to used this flag with the frame pointer or stack pointer.
+Use of this flag for other registers that have fixed pervasive roles in
+the machine's execution model will produce disastrous results.
A different sort of disaster will result from the use of this flag for
a register in which function values may be returned.
@@ -5873,29 +6285,51 @@ not want to use this option, since it makes the code suboptimal, and
the offsets of structure members won't agree with system libraries.
@item -fcheck-memory-usage
-Generate extra code to check each memory access. GNU CC will generate
+Generate extra code to check each memory access. GCC will generate
code that is suitable for a detector of bad memory accesses such as
-@file{Checker}. If you specify this option, you can not use the
-@code{asm} or @code{__asm__} keywords.
+@file{Checker}.
+
+Normally, you should compile all, or none, of your code with this option.
+
+If you do mix code compiled with and without this option,
+you must ensure that all code that has side effects
+and that is called by code compiled with this option
+is, itself, compiled with this option.
+If you do not, you might get erroneous messages from the detector.
-You must also specify this option when you compile functions you call that
-have side effects. If you do not, you may get erroneous messages from
-the detector. Normally, you should compile all your code with this option.
If you use functions from a library that have side-effects (such as
-@code{read}), you may not be able to recompile the library and
+@code{read}), you might not be able to recompile the library and
specify this option. In that case, you can enable the
-@samp{-fprefix-function-name} option, which requests GNU CC to encapsulate
+@samp{-fprefix-function-name} option, which requests GCC to encapsulate
your code and make other functions look as if they were compiled with
@samp{-fcheck-memory-usage}. This is done by calling ``stubs'',
which are provided by the detector. If you cannot find or build
-stubs for every function you call, you may have to specify
+stubs for every function you call, you might have to specify
@samp{-fcheck-memory-usage} without @samp{-fprefix-function-name}.
+If you specify this option, you can not use the @code{asm} or
+@code{__asm__} keywords in functions with memory checking enabled. The
+compiler cannot understand what the @code{asm} statement will do, and
+therefore cannot generate the appropriate code, so it is rejected.
+However, the function attribute @code{no_check_memory_usage} will
+disable memory checking within a function, and @code{asm} statements can
+be put inside such functions. Inline expansion of a non-checked
+function within a checked function is permitted; the inline function's
+memory accesses won't be checked, but the rest will.
+
+If you move your @code{asm} statements to non-checked inline functions,
+but they do access memory, you can add calls to the support code in your
+inline function, to indicate any reads, writes, or copies being done.
+These calls would be similar to those done in the stubs described above.
+
+@c FIXME: The support-routine interface is defined by the compiler and
+@c should be documented!
+
@item -fprefix-function-name
-Request GNU CC to add a prefix to the symbols generated for function names.
-GNU CC adds a prefix to the names of functions defined as well as
+Request GCC to add a prefix to the symbols generated for function names.
+GCC adds a prefix to the names of functions defined as well as
functions called. Code compiled with this option and code compiled
-without the option can't be linked together, unless or stubs are used.
+without the option can't be linked together, unless stubs are used.
If you compile the following code with @samp{-fprefix-function-name}
@example
@@ -5904,12 +6338,11 @@ void
foo (int a)
@{
return bar (a + 5);
-
@}
@end example
@noindent
-GNU CC will compile the code as if it was written:
+GCC will compile the code as if it was written:
@example
extern void prefix_bar (int);
void
@@ -5920,6 +6353,41 @@ prefix_foo (int a)
@end example
This option is designed to be used with @samp{-fcheck-memory-usage}.
+@item -finstrument-functions
+Generate instrumentation calls for entry and exit to functions. Just
+after function entry and just before function exit, the following
+profiling functions will be called with the address of the current
+function and its call site. (On some platforms,
+@code{__builtin_return_address} does not work beyond the current
+function, so the call site information may not be available to the
+profiling functions otherwise.)
+
+@example
+void __cyg_profile_func_enter (void *this_fn, void *call_site);
+void __cyg_profile_func_exit (void *this_fn, void *call_site);
+@end example
+
+The first argument is the address of the start of the current function,
+which may be looked up exactly in the symbol table.
+
+This instrumentation is also done for functions expanded inline in other
+functions. The profiling calls will indicate where, conceptually, the
+inline function is entered and exited. This means that addressable
+versions of such functions must be available. If all your uses of a
+function are expanded inline, this may mean an additional expansion of
+code size. If you use @samp{extern inline} in your C code, an
+addressable version of such functions must be provided. (This is
+normally the case anyways, but if you get lucky and the optimizer always
+expands the functions inline, you might have gotten away without
+providing static copies.)
+
+A function may be given the attribute @code{no_instrument_function}, in
+which case this instrumentation will not be done. This can be used, for
+example, for the profiling functions listed above, high-priority
+interrupt routines, and any functions from which the profiling functions
+cannot safely be called (perhaps signal handlers, if the profiling
+routines generate output or allocate memory).
+
@item -fstack-check
Generate code to verify that you do not go beyond the boundary of the
stack. You should specify this flag if you are running in an
@@ -5927,32 +6395,6 @@ environment with multiple threads, but only rarely need to specify it in
a single-threaded environment since stack overflow is automatically
detected on nearly all systems if there is only one stack.
-@item -fexceptions
-Enable exception handling. For some targets, this implies
-generation of frame unwind information for all functions, which can produce
-significant data size overhead, though it does not affect execution.
-
-This option is on by default for languages that support exception
-handling (such as C++), and off for those that don't (such as C).
-
-@item +e0
-@itemx +e1
-Control whether virtual function definitions in classes are used to
-generate code, or only to define interfaces for their callers. (C++
-only).
-
-These options are provided for compatibility with @code{cfront} 1.x
-usage; the recommended alternative GNU C++ usage is in flux. @xref{C++
-Interface,,Declarations and Definitions in One Header}.
-
-With @samp{+e0}, virtual function definitions in classes are declared
-@code{extern}; the declaration is used only as an interface
-specification, not to generate code for the virtual functions (in this
-compilation).
-
-With @samp{+e1}, G++ actually generates the code implementing virtual
-functions defined in the code, and makes them publicly visible.
-
@cindex aliasing of parameters
@cindex parameters, aliased
@item -fargument-alias
@@ -5970,36 +6412,85 @@ alias each other and do not alias global storage.
Each language will automatically use whatever option is required by
the language standard. You should not need to use these options yourself.
+
+@item -fleading-underscore
+This option and its counterpart, -fno-leading-underscore, forcibly
+change the way C symbols are represented in the object file. One use
+is to help link with legacy assembly code.
+
+Be warned that you should know what you are doing when invoking this
+option, and that not all targets provide complete support for it.
@end table
@node Environment Variables
-@section Environment Variables Affecting GNU CC
+@section Environment Variables Affecting GCC
@cindex environment variables
-This section describes several environment variables that affect how GNU
-CC operates. They work by specifying directories or prefixes to use
-when searching for various kinds of files.
+This section describes several environment variables that affect how GCC
+operates. Some of them work by specifying directories or prefixes to use
+when searching for various kinds of files. Some are used to specify other
+aspects of the compilation environment.
@ifclear INTERNALS
Note that you can also specify places to search using options such as
@samp{-B}, @samp{-I} and @samp{-L} (@pxref{Directory Options}). These
take precedence over places specified using environment variables, which
-in turn take precedence over those specified by the configuration of GNU
-CC.
+in turn take precedence over those specified by the configuration of GCC.
+
@end ifclear
@ifset INTERNALS
Note that you can also specify places to search using options such as
@samp{-B}, @samp{-I} and @samp{-L} (@pxref{Directory Options}). These
take precedence over places specified using environment variables, which
-in turn take precedence over those specified by the configuration of GNU
-CC. @xref{Driver}.
+in turn take precedence over those specified by the configuration of GCC.
+@xref{Driver}.
@end ifset
@table @code
+@item LANG
+@itemx LC_CTYPE
+@c @itemx LC_COLLATE
+@itemx LC_MESSAGES
+@c @itemx LC_MONETARY
+@c @itemx LC_NUMERIC
+@c @itemx LC_TIME
+@itemx LC_ALL
+@findex LANG
+@findex LC_CTYPE
+@c @findex LC_COLLATE
+@findex LC_MESSAGES
+@c @findex LC_MONETARY
+@c @findex LC_NUMERIC
+@c @findex LC_TIME
+@findex LC_ALL
+@cindex locale
+These environment variables control the way that GCC uses
+localization information that allow GCC to work with different
+national conventions. GCC inspects the locale categories
+@code{LC_CTYPE} and @code{LC_MESSAGES} if it has been configured to do
+so. These locale categories can be set to any value supported by your
+installation. A typical value is @samp{en_UK} for English in the United
+Kingdom.
+
+The @code{LC_CTYPE} environment variable specifies character
+classification. GCC uses it to determine the character boundaries in
+a string; this is needed for some multibyte encodings that contain quote
+and escape characters that would otherwise be interpreted as a string
+end or escape.
+
+The @code{LC_MESSAGES} environment variable specifies the language to
+use in diagnostic messages.
+
+If the @code{LC_ALL} environment variable is set, it overrides the value
+of @code{LC_CTYPE} and @code{LC_MESSAGES}; otherwise, @code{LC_CTYPE}
+and @code{LC_MESSAGES} default to the value of the @code{LANG}
+environment variable. If none of these variables are set, GCC
+defaults to traditional C English behavior.
+
@item TMPDIR
@findex TMPDIR
If @code{TMPDIR} is set, it specifies the directory to use for temporary
-files. GNU CC uses temporary files to hold the output of one stage of
+files. GCC uses temporary files to hold the output of one stage of
compilation which is to be used as input to the next stage: for example,
the output of the preprocessor, which is the input to the compiler
proper.
@@ -6011,7 +6502,7 @@ names of the subprograms executed by the compiler. No slash is added
when this prefix is combined with the name of a subprogram, but you can
specify a prefix that ends with a slash if you wish.
-If GNU CC cannot find the subprogram using the specified prefix, it
+If GCC cannot find the subprogram using the specified prefix, it
tries looking in the usual places for the subprogram.
The default value of @code{GCC_EXEC_PREFIX} is
@@ -6026,9 +6517,9 @@ used for linking.
In addition, the prefix is used in an unusual way in finding the
directories to search for header files. For each of the standard
directories whose name normally begins with @samp{/usr/local/lib/gcc-lib}
-(more precisely, with the value of @code{GCC_INCLUDE_DIR}), GNU CC tries
+(more precisely, with the value of @code{GCC_INCLUDE_DIR}), GCC tries
replacing that beginning with the specified prefix to produce an
-alternate directory name. Thus, with @samp{-Bfoo/}, GNU CC will search
+alternate directory name. Thus, with @samp{-Bfoo/}, GCC will search
@file{foo/bar} where it would normally search @file{/usr/local/lib/bar}.
These alternate directories are searched first; the standard directories
come next.
@@ -6036,7 +6527,7 @@ come next.
@item COMPILER_PATH
@findex COMPILER_PATH
The value of @code{COMPILER_PATH} is a colon-separated list of
-directories, much like @code{PATH}. GNU CC tries the directories thus
+directories, much like @code{PATH}. GCC tries the directories thus
specified when searching for subprograms, if it can't find the
subprograms using @code{GCC_EXEC_PREFIX}.
@@ -6044,9 +6535,9 @@ subprograms using @code{GCC_EXEC_PREFIX}.
@findex LIBRARY_PATH
The value of @code{LIBRARY_PATH} is a colon-separated list of
directories, much like @code{PATH}. When configured as a native compiler,
-GNU CC tries the directories thus specified when searching for special
+GCC tries the directories thus specified when searching for special
linker files, if it can't find them using @code{GCC_EXEC_PREFIX}. Linking
-using GNU CC also uses these directories when searching for ordinary
+using GCC also uses these directories when searching for ordinary
libraries for the @samp{-l} option (but directories specified with
@samp{-L} come first).
@@ -6059,7 +6550,7 @@ libraries for the @samp{-l} option (but directories specified with
@c @itemx OBJCPLUS_INCLUDE_PATH
These environment variables pertain to particular languages. Each
variable's value is a colon-separated list of directories, much like
-@code{PATH}. When GNU CC searches for header files, it tries the
+@code{PATH}. When GCC searches for header files, it tries the
directories listed in the variable for the language you are using, after
the directories specified with @samp{-I} but before the standard header
file directories.
@@ -6078,6 +6569,28 @@ which case the Make rules are written to that file, guessing the target
name from the source file name. Or the value can have the form
@samp{@var{file} @var{target}}, in which case the rules are written to
file @var{file} using @var{target} as the target name.
+
+@item LANG
+@findex LANG
+@cindex locale definition
+This variable is used to pass locale information to the compiler. One way in
+which this information is used is to determine the character set to be used
+when character literals, string literals and comments are parsed in C and C++.
+When the compiler is configured to allow multibyte characters,
+the following values for @code{LANG} are recognized:
+
+@table @code
+@item C-JIS
+Recognize JIS characters.
+@item C-SJIS
+Recognize SJIS characters.
+@item C-EUCJP
+Recognize EUCJP characters.
+@end table
+
+If @code{LANG} is not defined, or if it has some other value, then the
+compiler will use mblen and mbtowc as defined by the default locale to
+recognize and translate multibyte characters.
@end table
@node Running Protoize
@@ -6130,9 +6643,9 @@ original source file. The original file is renamed to a name ending
with @samp{.save}. If the @samp{.save} file already exists, then
the source file is simply discarded.
-@code{protoize} and @code{unprotoize} both depend on GNU CC itself to
+@code{protoize} and @code{unprotoize} both depend on GCC itself to
scan the program and collect information about the functions it uses.
-So neither of these programs will work until GNU CC is installed.
+So neither of these programs will work until GCC is installed.
Here is a table of the options you can use with @code{protoize} and
@code{unprotoize}. Each option works with both programs unless
diff --git a/contrib/gcc/jump.c b/contrib/gcc/jump.c
index ff4680c..e24adb2 100644
--- a/contrib/gcc/jump.c
+++ b/contrib/gcc/jump.c
@@ -1,5 +1,5 @@
/* Optimize jump instructions, for GNU compiler.
- Copyright (C) 1987, 88, 89, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -109,6 +109,12 @@ int can_reach_end;
static int cross_jump_death_matters = 0;
+static int init_label_info PROTO((rtx));
+static void delete_barrier_successors PROTO((rtx));
+static void mark_all_labels PROTO((rtx, int));
+static rtx delete_unreferenced_labels PROTO((rtx));
+static void delete_noop_moves PROTO((rtx));
+static int calculate_can_reach_end PROTO((rtx, int, int));
static int duplicate_loop_exit_test PROTO((rtx));
static void find_cross_jump PROTO((rtx, rtx, int, rtx *, rtx *));
static void do_cross_jump PROTO((rtx, rtx, rtx));
@@ -120,9 +126,33 @@ static void delete_from_jump_chain PROTO((rtx));
static int delete_labelref_insn PROTO((rtx, rtx, int));
static void mark_modified_reg PROTO((rtx, rtx));
static void redirect_tablejump PROTO((rtx, rtx));
+static void jump_optimize_1 PROTO ((rtx, int, int, int, int));
#ifndef HAVE_cc0
static rtx find_insert_position PROTO((rtx, rtx));
#endif
+
+/* Main external entry point into the jump optimizer. See comments before
+ jump_optimize_1 for descriptions of the arguments. */
+void
+jump_optimize (f, cross_jump, noop_moves, after_regscan)
+ rtx f;
+ int cross_jump;
+ int noop_moves;
+ int after_regscan;
+{
+ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, 0);
+}
+
+/* Alternate entry into the jump optimizer. This entry point only rebuilds
+ the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping
+ instructions. */
+void
+rebuild_jump_labels (f)
+ rtx f;
+{
+ jump_optimize_1 (f, 0, 0, 0, 1);
+}
+
/* Delete no-op jumps and optimize jumps to jumps
and jumps around jumps.
@@ -137,20 +167,24 @@ static rtx find_insert_position PROTO((rtx, rtx));
If AFTER_REGSCAN is nonzero, then this jump pass is being run immediately
after regscan, and it is safe to use regno_first_uid and regno_last_uid.
+ If MARK_LABELS_ONLY is nonzero, then we only rebuild the jump chain
+ and JUMP_LABEL field for jumping insns.
+
If `optimize' is zero, don't change any code,
just determine whether control drops off the end of the function.
This case occurs when we have -W and not -O.
It works because `delete_insn' checks the value of `optimize'
and refrains from actually deleting when that is 0. */
-void
-jump_optimize (f, cross_jump, noop_moves, after_regscan)
+static void
+jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, mark_labels_only)
rtx f;
int cross_jump;
int noop_moves;
int after_regscan;
+ int mark_labels_only;
{
- register rtx insn, next, note;
+ register rtx insn, next;
int changed;
int old_max_reg;
int first = 1;
@@ -158,30 +192,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
rtx last_insn;
cross_jump_death_matters = (cross_jump == 2);
-
- /* Initialize LABEL_NUSES and JUMP_LABEL fields. Delete any REG_LABEL
- notes whose labels don't occur in the insn any more. */
-
- for (insn = f; insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == CODE_LABEL)
- LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
- else if (GET_CODE (insn) == JUMP_INSN)
- JUMP_LABEL (insn) = 0;
- else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
- for (note = REG_NOTES (insn); note; note = next)
- {
- next = XEXP (note, 1);
- if (REG_NOTE_KIND (note) == REG_LABEL
- && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
- remove_note (insn, note);
- }
-
- if (INSN_UID (insn) > max_uid)
- max_uid = INSN_UID (insn);
- }
-
- max_uid++;
+ max_uid = init_label_info (f) + 1;
/* If we are performing cross jump optimizations, then initialize
tables mapping UIDs to EH regions to avoid incorrect movement
@@ -189,26 +200,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
if (flag_exceptions && cross_jump)
init_insn_eh_region (f, max_uid);
- /* Delete insns following barriers, up to next label. */
-
- for (insn = f; insn;)
- {
- if (GET_CODE (insn) == BARRIER)
- {
- insn = NEXT_INSN (insn);
- while (insn != 0 && GET_CODE (insn) != CODE_LABEL)
- {
- if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)
- insn = NEXT_INSN (insn);
- else
- insn = delete_insn (insn);
- }
- /* INSN is now the code_label. */
- }
- else
- insn = NEXT_INSN (insn);
- }
+ delete_barrier_successors (f);
/* Leave some extra room for labels and duplicate exit test insns
we make. */
@@ -216,32 +208,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
jump_chain = (rtx *) alloca (max_jump_chain * sizeof (rtx));
bzero ((char *) jump_chain, max_jump_chain * sizeof (rtx));
- /* Mark the label each jump jumps to.
- Combine consecutive labels, and count uses of labels.
-
- For each label, make a chain (using `jump_chain')
- of all the *unconditional* jumps that jump to it;
- also make a chain of all returns. */
-
- for (insn = f; insn; insn = NEXT_INSN (insn))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
- mark_jump_label (PATTERN (insn), insn, cross_jump);
- if (! INSN_DELETED_P (insn) && GET_CODE (insn) == JUMP_INSN)
- {
- if (JUMP_LABEL (insn) != 0 && simplejump_p (insn))
- {
- jump_chain[INSN_UID (insn)]
- = jump_chain[INSN_UID (JUMP_LABEL (insn))];
- jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn;
- }
- if (GET_CODE (PATTERN (insn)) == RETURN)
- {
- jump_chain[INSN_UID (insn)] = jump_chain[0];
- jump_chain[0] = insn;
- }
- }
- }
+ mark_all_labels (f, cross_jump);
/* Keep track of labels used from static data;
they cannot ever be deleted. */
@@ -257,52 +224,22 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
LABEL_NUSES (XEXP (insn, 0))++;
+ /* Quit now if we just wanted to rebuild the JUMP_LABEL and REG_LABEL
+ notes and recompute LABEL_NUSES. */
+ if (mark_labels_only)
+ return;
+
exception_optimize ();
- /* Delete all labels already not referenced.
- Also find the last insn. */
-
- last_insn = 0;
- for (insn = f; insn; )
- {
- if (GET_CODE (insn) == CODE_LABEL && LABEL_NUSES (insn) == 0)
- insn = delete_insn (insn);
- else
- {
- last_insn = insn;
- insn = NEXT_INSN (insn);
- }
- }
+ last_insn = delete_unreferenced_labels (f);
if (!optimize)
{
- /* See if there is still a NOTE_INSN_FUNCTION_END in this function.
- If so record that this function can drop off the end. */
-
- insn = last_insn;
- {
- int n_labels = 1;
- while (insn
- /* One label can follow the end-note: the return label. */
- && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0)
- /* Ordinary insns can follow it if returning a structure. */
- || GET_CODE (insn) == INSN
- /* If machine uses explicit RETURN insns, no epilogue,
- then one of them follows the note. */
- || (GET_CODE (insn) == JUMP_INSN
- && GET_CODE (PATTERN (insn)) == RETURN)
- /* A barrier can follow the return insn. */
- || GET_CODE (insn) == BARRIER
- /* Other kinds of notes can follow also. */
- || (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)))
- insn = PREV_INSN (insn);
- }
-
- /* Report if control can fall through at the end of the function. */
- if (insn && GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END
- && ! INSN_DELETED_P (insn))
+ /* CAN_REACH_END is persistent for each function. Once set it should
+ not be cleared. This is especially true for the case where we
+ delete the NOTE_FUNCTION_END note. CAN_REACH_END is cleared by
+ the front-end before compiling each function. */
+ if (calculate_can_reach_end (last_insn, 1, 0))
can_reach_end = 1;
/* Zero the "deleted" flag of all the "deleted" insns. */
@@ -334,249 +271,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
#endif
if (noop_moves)
- for (insn = f; insn; )
- {
- next = NEXT_INSN (insn);
-
- if (GET_CODE (insn) == INSN)
- {
- register rtx body = PATTERN (insn);
-
-/* Combine stack_adjusts with following push_insns. */
-#ifdef PUSH_ROUNDING
- if (GET_CODE (body) == SET
- && SET_DEST (body) == stack_pointer_rtx
- && GET_CODE (SET_SRC (body)) == PLUS
- && XEXP (SET_SRC (body), 0) == stack_pointer_rtx
- && GET_CODE (XEXP (SET_SRC (body), 1)) == CONST_INT
- && INTVAL (XEXP (SET_SRC (body), 1)) > 0)
- {
- rtx p;
- rtx stack_adjust_insn = insn;
- int stack_adjust_amount = INTVAL (XEXP (SET_SRC (body), 1));
- int total_pushed = 0;
- int pushes = 0;
-
- /* Find all successive push insns. */
- p = insn;
- /* Don't convert more than three pushes;
- that starts adding too many displaced addresses
- and the whole thing starts becoming a losing
- proposition. */
- while (pushes < 3)
- {
- rtx pbody, dest;
- p = next_nonnote_insn (p);
- if (p == 0 || GET_CODE (p) != INSN)
- break;
- pbody = PATTERN (p);
- if (GET_CODE (pbody) != SET)
- break;
- dest = SET_DEST (pbody);
- /* Allow a no-op move between the adjust and the push. */
- if (GET_CODE (dest) == REG
- && GET_CODE (SET_SRC (pbody)) == REG
- && REGNO (dest) == REGNO (SET_SRC (pbody)))
- continue;
- if (! (GET_CODE (dest) == MEM
- && GET_CODE (XEXP (dest, 0)) == POST_INC
- && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx))
- break;
- pushes++;
- if (total_pushed + GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)))
- > stack_adjust_amount)
- break;
- total_pushed += GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)));
- }
-
- /* Discard the amount pushed from the stack adjust;
- maybe eliminate it entirely. */
- if (total_pushed >= stack_adjust_amount)
- {
- delete_computation (stack_adjust_insn);
- total_pushed = stack_adjust_amount;
- }
- else
- XEXP (SET_SRC (PATTERN (stack_adjust_insn)), 1)
- = GEN_INT (stack_adjust_amount - total_pushed);
-
- /* Change the appropriate push insns to ordinary stores. */
- p = insn;
- while (total_pushed > 0)
- {
- rtx pbody, dest;
- p = next_nonnote_insn (p);
- if (GET_CODE (p) != INSN)
- break;
- pbody = PATTERN (p);
- if (GET_CODE (pbody) != SET)
- break;
- dest = SET_DEST (pbody);
- /* Allow a no-op move between the adjust and the push. */
- if (GET_CODE (dest) == REG
- && GET_CODE (SET_SRC (pbody)) == REG
- && REGNO (dest) == REGNO (SET_SRC (pbody)))
- continue;
- if (! (GET_CODE (dest) == MEM
- && GET_CODE (XEXP (dest, 0)) == POST_INC
- && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx))
- break;
- total_pushed -= GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)));
- /* If this push doesn't fully fit in the space
- of the stack adjust that we deleted,
- make another stack adjust here for what we
- didn't use up. There should be peepholes
- to recognize the resulting sequence of insns. */
- if (total_pushed < 0)
- {
- emit_insn_before (gen_add2_insn (stack_pointer_rtx,
- GEN_INT (- total_pushed)),
- p);
- break;
- }
- XEXP (dest, 0)
- = plus_constant (stack_pointer_rtx, total_pushed);
- }
- }
-#endif
-
- /* Detect and delete no-op move instructions
- resulting from not allocating a parameter in a register. */
-
- if (GET_CODE (body) == SET
- && (SET_DEST (body) == SET_SRC (body)
- || (GET_CODE (SET_DEST (body)) == MEM
- && GET_CODE (SET_SRC (body)) == MEM
- && rtx_equal_p (SET_SRC (body), SET_DEST (body))))
- && ! (GET_CODE (SET_DEST (body)) == MEM
- && MEM_VOLATILE_P (SET_DEST (body)))
- && ! (GET_CODE (SET_SRC (body)) == MEM
- && MEM_VOLATILE_P (SET_SRC (body))))
- delete_computation (insn);
-
- /* Detect and ignore no-op move instructions
- resulting from smart or fortuitous register allocation. */
-
- else if (GET_CODE (body) == SET)
- {
- int sreg = true_regnum (SET_SRC (body));
- int dreg = true_regnum (SET_DEST (body));
-
- if (sreg == dreg && sreg >= 0)
- delete_insn (insn);
- else if (sreg >= 0 && dreg >= 0)
- {
- rtx trial;
- rtx tem = find_equiv_reg (NULL_RTX, insn, 0,
- sreg, NULL_PTR, dreg,
- GET_MODE (SET_SRC (body)));
-
- if (tem != 0
- && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
- {
- /* DREG may have been the target of a REG_DEAD note in
- the insn which makes INSN redundant. If so, reorg
- would still think it is dead. So search for such a
- note and delete it if we find it. */
- if (! find_regno_note (insn, REG_UNUSED, dreg))
- for (trial = prev_nonnote_insn (insn);
- trial && GET_CODE (trial) != CODE_LABEL;
- trial = prev_nonnote_insn (trial))
- if (find_regno_note (trial, REG_DEAD, dreg))
- {
- remove_death (dreg, trial);
- break;
- }
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- /* Deleting insn could lose a death-note for SREG
- so don't do it if final needs accurate
- death-notes. */
- if (PRESERVE_DEATH_INFO_REGNO_P (sreg)
- && (trial = find_regno_note (insn, REG_DEAD, sreg)))
- {
- /* Change this into a USE so that we won't emit
- code for it, but still can keep the note. */
- PATTERN (insn)
- = gen_rtx_USE (VOIDmode, XEXP (trial, 0));
- INSN_CODE (insn) = -1;
- /* Remove all reg notes but the REG_DEAD one. */
- REG_NOTES (insn) = trial;
- XEXP (trial, 1) = NULL_RTX;
- }
- else
-#endif
- delete_insn (insn);
- }
- }
- else if (dreg >= 0 && CONSTANT_P (SET_SRC (body))
- && find_equiv_reg (SET_SRC (body), insn, 0, dreg,
- NULL_PTR, 0,
- GET_MODE (SET_DEST (body))))
- {
- /* This handles the case where we have two consecutive
- assignments of the same constant to pseudos that didn't
- get a hard reg. Each SET from the constant will be
- converted into a SET of the spill register and an
- output reload will be made following it. This produces
- two loads of the same constant into the same spill
- register. */
-
- rtx in_insn = insn;
-
- /* Look back for a death note for the first reg.
- If there is one, it is no longer accurate. */
- while (in_insn && GET_CODE (in_insn) != CODE_LABEL)
- {
- if ((GET_CODE (in_insn) == INSN
- || GET_CODE (in_insn) == JUMP_INSN)
- && find_regno_note (in_insn, REG_DEAD, dreg))
- {
- remove_death (dreg, in_insn);
- break;
- }
- in_insn = PREV_INSN (in_insn);
- }
-
- /* Delete the second load of the value. */
- delete_insn (insn);
- }
- }
- else if (GET_CODE (body) == PARALLEL)
- {
- /* If each part is a set between two identical registers or
- a USE or CLOBBER, delete the insn. */
- int i, sreg, dreg;
- rtx tem;
-
- for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
- {
- tem = XVECEXP (body, 0, i);
- if (GET_CODE (tem) == USE || GET_CODE (tem) == CLOBBER)
- continue;
-
- if (GET_CODE (tem) != SET
- || (sreg = true_regnum (SET_SRC (tem))) < 0
- || (dreg = true_regnum (SET_DEST (tem))) < 0
- || dreg != sreg)
- break;
- }
-
- if (i < 0)
- delete_insn (insn);
- }
- /* Also delete insns to store bit fields if they are no-ops. */
- /* Not worth the hair to detect this in the big-endian case. */
- else if (! BYTES_BIG_ENDIAN
- && GET_CODE (body) == SET
- && GET_CODE (SET_DEST (body)) == ZERO_EXTRACT
- && XEXP (SET_DEST (body), 2) == const0_rtx
- && XEXP (SET_DEST (body), 0) == SET_SRC (body)
- && ! (GET_CODE (SET_SRC (body)) == MEM
- && MEM_VOLATILE_P (SET_SRC (body))))
- delete_insn (insn);
- }
- insn = next;
- }
+ delete_noop_moves (f);
/* If we haven't yet gotten to reload and we have just run regscan,
delete any insn that sets a register that isn't used elsewhere.
@@ -862,7 +557,12 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& ! reg_referenced_between_p (temp1, p, NEXT_INSN (temp3))
&& ! reg_set_between_p (temp1, p, temp3)
&& (GET_CODE (SET_SRC (temp4)) == CONST_INT
- || ! modified_between_p (SET_SRC (temp4), p, temp2)))
+ || ! modified_between_p (SET_SRC (temp4), p, temp2))
+ /* Verify that registers used by the jump are not clobbered
+ by the instruction being moved. */
+ && ! regs_set_between_p (PATTERN (temp),
+ PREV_INSN (temp2),
+ NEXT_INSN (temp2)))
{
emit_insn_after_with_line_notes (PATTERN (temp2), p, temp2);
delete_insn (temp2);
@@ -960,6 +660,11 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
NEXT_INSN (temp2))
&& ! reg_set_between_p (temp1, insert_after, temp)
&& ! modified_between_p (SET_SRC (temp4), insert_after, temp)
+ /* Verify that registers used by the jump are not clobbered
+ by the instruction being moved. */
+ && ! regs_set_between_p (PATTERN (temp),
+ PREV_INSN (temp3),
+ NEXT_INSN (temp3))
&& invert_jump (temp, JUMP_LABEL (insn)))
{
emit_insn_after_with_line_notes (PATTERN (temp3),
@@ -2368,41 +2073,465 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
}
#endif
- /* See if there is still a NOTE_INSN_FUNCTION_END in this function.
- If so, delete it, and record that this function can drop off the end. */
+ /* CAN_REACH_END is persistent for each function. Once set it should
+ not be cleared. This is especially true for the case where we
+ delete the NOTE_FUNCTION_END note. CAN_REACH_END is cleared by
+ the front-end before compiling each function. */
+ if (calculate_can_reach_end (last_insn, 0, 1))
+ can_reach_end = 1;
+
+ /* Show JUMP_CHAIN no longer valid. */
+ jump_chain = 0;
+}
+
+/* Initialize LABEL_NUSES and JUMP_LABEL fields. Delete any REG_LABEL
+ notes whose labels don't occur in the insn any more. Returns the
+ largest INSN_UID found. */
+static int
+init_label_info (f)
+ rtx f;
+{
+ int largest_uid = 0;
+ rtx insn;
+
+ for (insn = f; insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == CODE_LABEL)
+ LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+ else if (GET_CODE (insn) == JUMP_INSN)
+ JUMP_LABEL (insn) = 0;
+ else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+ {
+ rtx note, next;
+
+ for (note = REG_NOTES (insn); note; note = next)
+ {
+ next = XEXP (note, 1);
+ if (REG_NOTE_KIND (note) == REG_LABEL
+ && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
+ remove_note (insn, note);
+ }
+ }
+ if (INSN_UID (insn) > largest_uid)
+ largest_uid = INSN_UID (insn);
+ }
+
+ return largest_uid;
+}
+
+/* Delete insns following barriers, up to next label.
+
+ Also delete no-op jumps created by gcse. */
+static void
+delete_barrier_successors (f)
+ rtx f;
+{
+ rtx insn;
+
+ for (insn = f; insn;)
+ {
+ if (GET_CODE (insn) == BARRIER)
+ {
+ insn = NEXT_INSN (insn);
+ while (insn != 0 && GET_CODE (insn) != CODE_LABEL)
+ {
+ if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)
+ insn = NEXT_INSN (insn);
+ else
+ insn = delete_insn (insn);
+ }
+ /* INSN is now the code_label. */
+ }
+ /* Also remove (set (pc) (pc)) insns which can be created by
+ gcse. We eliminate such insns now to avoid having them
+ cause problems later. */
+ else if (GET_CODE (insn) == JUMP_INSN
+ && SET_SRC (PATTERN (insn)) == pc_rtx
+ && SET_DEST (PATTERN (insn)) == pc_rtx)
+ insn = delete_insn (insn);
+
+ else
+ insn = NEXT_INSN (insn);
+ }
+}
+
+/* Mark the label each jump jumps to.
+ Combine consecutive labels, and count uses of labels.
+
+ For each label, make a chain (using `jump_chain')
+ of all the *unconditional* jumps that jump to it;
+ also make a chain of all returns.
+
+ CROSS_JUMP indicates whether we are doing cross jumping
+ and if we are whether we will be paying attention to
+ death notes or not. */
+
+static void
+mark_all_labels (f, cross_jump)
+ rtx f;
+ int cross_jump;
+{
+ rtx insn;
+
+ for (insn = f; insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ mark_jump_label (PATTERN (insn), insn, cross_jump);
+ if (! INSN_DELETED_P (insn) && GET_CODE (insn) == JUMP_INSN)
+ {
+ if (JUMP_LABEL (insn) != 0 && simplejump_p (insn))
+ {
+ jump_chain[INSN_UID (insn)]
+ = jump_chain[INSN_UID (JUMP_LABEL (insn))];
+ jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn;
+ }
+ if (GET_CODE (PATTERN (insn)) == RETURN)
+ {
+ jump_chain[INSN_UID (insn)] = jump_chain[0];
+ jump_chain[0] = insn;
+ }
+ }
+ }
+}
+
+/* Delete all labels already not referenced.
+ Also find and return the last insn. */
+
+static rtx
+delete_unreferenced_labels (f)
+ rtx f;
+{
+ rtx final = NULL_RTX;
+ rtx insn;
+
+ for (insn = f; insn; )
+ {
+ if (GET_CODE (insn) == CODE_LABEL && LABEL_NUSES (insn) == 0)
+ insn = delete_insn (insn);
+ else
+ {
+ final = insn;
+ insn = NEXT_INSN (insn);
+ }
+ }
+
+ return final;
+}
+
+/* Delete various simple forms of moves which have no necessary
+ side effect. */
+
+static void
+delete_noop_moves (f)
+ rtx f;
+{
+ rtx insn, next;
+
+ for (insn = f; insn; )
+ {
+ next = NEXT_INSN (insn);
+
+ if (GET_CODE (insn) == INSN)
+ {
+ register rtx body = PATTERN (insn);
+
+/* Combine stack_adjusts with following push_insns. */
+#ifdef PUSH_ROUNDING
+ if (GET_CODE (body) == SET
+ && SET_DEST (body) == stack_pointer_rtx
+ && GET_CODE (SET_SRC (body)) == PLUS
+ && XEXP (SET_SRC (body), 0) == stack_pointer_rtx
+ && GET_CODE (XEXP (SET_SRC (body), 1)) == CONST_INT
+ && INTVAL (XEXP (SET_SRC (body), 1)) > 0)
+ {
+ rtx p;
+ rtx stack_adjust_insn = insn;
+ int stack_adjust_amount = INTVAL (XEXP (SET_SRC (body), 1));
+ int total_pushed = 0;
+ int pushes = 0;
+
+ /* Find all successive push insns. */
+ p = insn;
+ /* Don't convert more than three pushes;
+ that starts adding too many displaced addresses
+ and the whole thing starts becoming a losing
+ proposition. */
+ while (pushes < 3)
+ {
+ rtx pbody, dest;
+ p = next_nonnote_insn (p);
+ if (p == 0 || GET_CODE (p) != INSN)
+ break;
+ pbody = PATTERN (p);
+ if (GET_CODE (pbody) != SET)
+ break;
+ dest = SET_DEST (pbody);
+ /* Allow a no-op move between the adjust and the push. */
+ if (GET_CODE (dest) == REG
+ && GET_CODE (SET_SRC (pbody)) == REG
+ && REGNO (dest) == REGNO (SET_SRC (pbody)))
+ continue;
+ if (! (GET_CODE (dest) == MEM
+ && GET_CODE (XEXP (dest, 0)) == POST_INC
+ && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx))
+ break;
+ pushes++;
+ if (total_pushed + GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)))
+ > stack_adjust_amount)
+ break;
+ total_pushed += GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)));
+ }
+
+ /* Discard the amount pushed from the stack adjust;
+ maybe eliminate it entirely. */
+ if (total_pushed >= stack_adjust_amount)
+ {
+ delete_computation (stack_adjust_insn);
+ total_pushed = stack_adjust_amount;
+ }
+ else
+ XEXP (SET_SRC (PATTERN (stack_adjust_insn)), 1)
+ = GEN_INT (stack_adjust_amount - total_pushed);
+
+ /* Change the appropriate push insns to ordinary stores. */
+ p = insn;
+ while (total_pushed > 0)
+ {
+ rtx pbody, dest;
+ p = next_nonnote_insn (p);
+ if (GET_CODE (p) != INSN)
+ break;
+ pbody = PATTERN (p);
+ if (GET_CODE (pbody) != SET)
+ break;
+ dest = SET_DEST (pbody);
+ /* Allow a no-op move between the adjust and the push. */
+ if (GET_CODE (dest) == REG
+ && GET_CODE (SET_SRC (pbody)) == REG
+ && REGNO (dest) == REGNO (SET_SRC (pbody)))
+ continue;
+ if (! (GET_CODE (dest) == MEM
+ && GET_CODE (XEXP (dest, 0)) == POST_INC
+ && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx))
+ break;
+ total_pushed -= GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)));
+ /* If this push doesn't fully fit in the space
+ of the stack adjust that we deleted,
+ make another stack adjust here for what we
+ didn't use up. There should be peepholes
+ to recognize the resulting sequence of insns. */
+ if (total_pushed < 0)
+ {
+ emit_insn_before (gen_add2_insn (stack_pointer_rtx,
+ GEN_INT (- total_pushed)),
+ p);
+ break;
+ }
+ XEXP (dest, 0)
+ = plus_constant (stack_pointer_rtx, total_pushed);
+ }
+ }
+#endif
+
+ /* Detect and delete no-op move instructions
+ resulting from not allocating a parameter in a register. */
+
+ if (GET_CODE (body) == SET
+ && (SET_DEST (body) == SET_SRC (body)
+ || (GET_CODE (SET_DEST (body)) == MEM
+ && GET_CODE (SET_SRC (body)) == MEM
+ && rtx_equal_p (SET_SRC (body), SET_DEST (body))))
+ && ! (GET_CODE (SET_DEST (body)) == MEM
+ && MEM_VOLATILE_P (SET_DEST (body)))
+ && ! (GET_CODE (SET_SRC (body)) == MEM
+ && MEM_VOLATILE_P (SET_SRC (body))))
+ delete_computation (insn);
+
+ /* Detect and ignore no-op move instructions
+ resulting from smart or fortuitous register allocation. */
+
+ else if (GET_CODE (body) == SET)
+ {
+ int sreg = true_regnum (SET_SRC (body));
+ int dreg = true_regnum (SET_DEST (body));
+
+ if (sreg == dreg && sreg >= 0)
+ delete_insn (insn);
+ else if (sreg >= 0 && dreg >= 0)
+ {
+ rtx trial;
+ rtx tem = find_equiv_reg (NULL_RTX, insn, 0,
+ sreg, NULL_PTR, dreg,
+ GET_MODE (SET_SRC (body)));
+
+ if (tem != 0
+ && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
+ {
+ /* DREG may have been the target of a REG_DEAD note in
+ the insn which makes INSN redundant. If so, reorg
+ would still think it is dead. So search for such a
+ note and delete it if we find it. */
+ if (! find_regno_note (insn, REG_UNUSED, dreg))
+ for (trial = prev_nonnote_insn (insn);
+ trial && GET_CODE (trial) != CODE_LABEL;
+ trial = prev_nonnote_insn (trial))
+ if (find_regno_note (trial, REG_DEAD, dreg))
+ {
+ remove_death (dreg, trial);
+ break;
+ }
+
+ /* Deleting insn could lose a death-note for SREG. */
+ if ((trial = find_regno_note (insn, REG_DEAD, sreg)))
+ {
+ /* Change this into a USE so that we won't emit
+ code for it, but still can keep the note. */
+ PATTERN (insn)
+ = gen_rtx_USE (VOIDmode, XEXP (trial, 0));
+ INSN_CODE (insn) = -1;
+ /* Remove all reg notes but the REG_DEAD one. */
+ REG_NOTES (insn) = trial;
+ XEXP (trial, 1) = NULL_RTX;
+ }
+ else
+ delete_insn (insn);
+ }
+ }
+ else if (dreg >= 0 && CONSTANT_P (SET_SRC (body))
+ && find_equiv_reg (SET_SRC (body), insn, 0, dreg,
+ NULL_PTR, 0,
+ GET_MODE (SET_DEST (body))))
+ {
+ /* This handles the case where we have two consecutive
+ assignments of the same constant to pseudos that didn't
+ get a hard reg. Each SET from the constant will be
+ converted into a SET of the spill register and an
+ output reload will be made following it. This produces
+ two loads of the same constant into the same spill
+ register. */
+
+ rtx in_insn = insn;
+
+ /* Look back for a death note for the first reg.
+ If there is one, it is no longer accurate. */
+ while (in_insn && GET_CODE (in_insn) != CODE_LABEL)
+ {
+ if ((GET_CODE (in_insn) == INSN
+ || GET_CODE (in_insn) == JUMP_INSN)
+ && find_regno_note (in_insn, REG_DEAD, dreg))
+ {
+ remove_death (dreg, in_insn);
+ break;
+ }
+ in_insn = PREV_INSN (in_insn);
+ }
+
+ /* Delete the second load of the value. */
+ delete_insn (insn);
+ }
+ }
+ else if (GET_CODE (body) == PARALLEL)
+ {
+ /* If each part is a set between two identical registers or
+ a USE or CLOBBER, delete the insn. */
+ int i, sreg, dreg;
+ rtx tem;
+
+ for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
+ {
+ tem = XVECEXP (body, 0, i);
+ if (GET_CODE (tem) == USE || GET_CODE (tem) == CLOBBER)
+ continue;
+
+ if (GET_CODE (tem) != SET
+ || (sreg = true_regnum (SET_SRC (tem))) < 0
+ || (dreg = true_regnum (SET_DEST (tem))) < 0
+ || dreg != sreg)
+ break;
+ }
+
+ if (i < 0)
+ delete_insn (insn);
+ }
+ /* Also delete insns to store bit fields if they are no-ops. */
+ /* Not worth the hair to detect this in the big-endian case. */
+ else if (! BYTES_BIG_ENDIAN
+ && GET_CODE (body) == SET
+ && GET_CODE (SET_DEST (body)) == ZERO_EXTRACT
+ && XEXP (SET_DEST (body), 2) == const0_rtx
+ && XEXP (SET_DEST (body), 0) == SET_SRC (body)
+ && ! (GET_CODE (SET_SRC (body)) == MEM
+ && MEM_VOLATILE_P (SET_SRC (body))))
+ delete_insn (insn);
+ }
+ insn = next;
+ }
+}
+
+/* See if there is still a NOTE_INSN_FUNCTION_END in this function.
+ If so indicate that this function can drop off the end by returning
+ 1, else return 0.
+
+ CHECK_DELETED indicates whether we must check if the note being
+ searched for has the deleted flag set.
+
+ DELETE_FINAL_NOTE indicates whether we should delete the note
+ if we find it. */
+
+static int
+calculate_can_reach_end (last, check_deleted, delete_final_note)
+ rtx last;
+ int check_deleted;
+ int delete_final_note;
+{
+ rtx insn = last;
+ int n_labels = 1;
+
+ while (insn != NULL_RTX)
+ {
+ int ok = 0;
+
+ /* One label can follow the end-note: the return label. */
+ if (GET_CODE (insn) == CODE_LABEL && n_labels-- > 0)
+ ok = 1;
+ /* Ordinary insns can follow it if returning a structure. */
+ else if (GET_CODE (insn) == INSN)
+ ok = 1;
+ /* If machine uses explicit RETURN insns, no epilogue,
+ then one of them follows the note. */
+ else if (GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) == RETURN)
+ ok = 1;
+ /* A barrier can follow the return insn. */
+ else if (GET_CODE (insn) == BARRIER)
+ ok = 1;
+ /* Other kinds of notes can follow also. */
+ else if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)
+ ok = 1;
+
+ if (ok != 1)
+ break;
- insn = last_insn;
- {
- int n_labels = 1;
- while (insn
- /* One label can follow the end-note: the return label. */
- && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0)
- /* Ordinary insns can follow it if returning a structure. */
- || GET_CODE (insn) == INSN
- /* If machine uses explicit RETURN insns, no epilogue,
- then one of them follows the note. */
- || (GET_CODE (insn) == JUMP_INSN
- && GET_CODE (PATTERN (insn)) == RETURN)
- /* A barrier can follow the return insn. */
- || GET_CODE (insn) == BARRIER
- /* Other kinds of notes can follow also. */
- || (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)))
insn = PREV_INSN (insn);
- }
+ }
- /* Report if control can fall through at the end of the function. */
- if (insn && GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END)
+ /* See if we backed up to the appropriate type of note. */
+ if (insn != NULL_RTX
+ && GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END
+ && (check_deleted == 0
+ || ! INSN_DELETED_P (insn)))
{
- can_reach_end = 1;
- delete_insn (insn);
+ if (delete_final_note)
+ delete_insn (insn);
+ return 1;
}
- /* Show JUMP_CHAIN no longer valid. */
- jump_chain = 0;
+ return 0;
}
-
+
/* LOOP_START is a NOTE_INSN_LOOP_BEG note that is followed by an unconditional
jump. Assume that this unconditional jump is to the exit test code. If
the code is sufficiently simple, make a copy of it before INSN,
@@ -2433,8 +2562,7 @@ duplicate_loop_exit_test (loop_start)
has a REG_RETVAL or REG_LIBCALL note (hard to adjust)
is a NOTE_INSN_LOOP_BEG because this means we have a nested loop
is a NOTE_INSN_BLOCK_{BEG,END} because duplicating these notes
- are not valid
-
+ is not valid.
We also do not do this if we find an insn with ASM_OPERANDS. While
this restriction should not be necessary, copying an insn with
@@ -2479,6 +2607,10 @@ duplicate_loop_exit_test (loop_start)
break;
case JUMP_INSN:
case INSN:
+ /* The code below would grossly mishandle REG_WAS_0 notes,
+ so get rid of them here. */
+ while ((p = find_reg_note (insn, REG_WAS_0, NULL_RTX)) != 0)
+ remove_note (insn, p);
if (++num_insns > 20
|| find_reg_note (insn, REG_RETVAL, NULL_RTX)
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX)
@@ -2715,10 +2847,10 @@ find_cross_jump (e1, e2, minimum, f1, f2)
if (i2 == 0 || GET_CODE (i1) != GET_CODE (i2))
break;
- /* Avoid moving insns across EH regions.
-
- ??? This is only necessary if i1 or i2 can throw an exception. */
+ /* Avoid moving insns across EH regions if either of the insns
+ can throw. */
if (flag_exceptions
+ && (asynchronous_exceptions || GET_CODE (i1) == CALL_INSN)
&& !in_same_eh_region (i1, i2))
break;
@@ -2745,7 +2877,7 @@ find_cross_jump (e1, e2, minimum, f1, f2)
indicates whether or not the insn contains any stack-like
regs. */
- if (!lose && cross_jump_death_matters && GET_MODE (i1) == QImode)
+ if (!lose && cross_jump_death_matters && stack_regs_mentioned (i1))
{
/* If register stack conversion has already been done, then
death notes must also be compared before it is certain that
@@ -3029,8 +3161,17 @@ can_reverse_comparison_p (comparison, insn)
)
{
rtx prev = prev_nonnote_insn (insn);
- rtx set = single_set (prev);
+ rtx set;
+
+ /* If the comparison itself was a loop invariant, it could have been
+ hoisted out of the loop. If we proceed to unroll such a loop, then
+ we may not be able to find the comparison when copying the loop.
+
+ Returning zero in that case is the safe thing to do. */
+ if (prev == 0)
+ return 0;
+ set = single_set (prev);
if (set == 0 || SET_DEST (set) != arg0)
return 0;
@@ -3324,6 +3465,52 @@ condjump_in_parallel_p (insn)
return 0;
}
+/* Return the label of a conditional jump. */
+
+rtx
+condjump_label (insn)
+ rtx insn;
+{
+ register rtx x = PATTERN (insn);
+
+ if (GET_CODE (x) == PARALLEL)
+ x = XVECEXP (x, 0, 0);
+ if (GET_CODE (x) != SET)
+ return NULL_RTX;
+ if (GET_CODE (SET_DEST (x)) != PC)
+ return NULL_RTX;
+ x = SET_SRC (x);
+ if (GET_CODE (x) == LABEL_REF)
+ return x;
+ if (GET_CODE (x) != IF_THEN_ELSE)
+ return NULL_RTX;
+ if (XEXP (x, 2) == pc_rtx && GET_CODE (XEXP (x, 1)) == LABEL_REF)
+ return XEXP (x, 1);
+ if (XEXP (x, 1) == pc_rtx && GET_CODE (XEXP (x, 2)) == LABEL_REF)
+ return XEXP (x, 2);
+ return NULL_RTX;
+}
+
+/* Return true if INSN is a (possibly conditional) return insn. */
+
+static int
+returnjump_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *loc;
+ return GET_CODE (x) == RETURN;
+}
+
+int
+returnjump_p (insn)
+ rtx insn;
+{
+ return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
+}
+
+#ifdef HAVE_cc0
+
/* Return 1 if X is an RTX that does nothing but set the condition codes
and CLOBBER or USE registers.
Return -1 if X does explicitly set the condition codes,
@@ -3331,9 +3518,8 @@ condjump_in_parallel_p (insn)
int
sets_cc0_p (x)
- rtx x;
+ rtx x ATTRIBUTE_UNUSED;
{
-#ifdef HAVE_cc0
if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
return 1;
if (GET_CODE (x) == PARALLEL)
@@ -3352,10 +3538,8 @@ sets_cc0_p (x)
return ! sets_cc0 ? 0 : other_things ? -1 : 1;
}
return 0;
-#else
- abort ();
-#endif
}
+#endif
/* Follow any unconditional jump at LABEL;
return the ultimate label reached by any such chain of jumps.
@@ -3757,6 +3941,9 @@ delete_insn (insn)
if (INSN_DELETED_P (insn))
return next;
+ if (was_code_label)
+ remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
+
/* Don't delete user-declared labels. Convert them to special NOTEs
instead. */
if (was_code_label && LABEL_NAME (insn) != 0
@@ -3811,20 +3998,36 @@ delete_insn (insn)
and delete the label if it is now unused. */
if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
- if (--LABEL_NUSES (JUMP_LABEL (insn)) == 0)
- {
- /* This can delete NEXT or PREV,
- either directly if NEXT is JUMP_LABEL (INSN),
- or indirectly through more levels of jumps. */
- delete_insn (JUMP_LABEL (insn));
- /* I feel a little doubtful about this loop,
- but I see no clean and sure alternative way
- to find the first insn after INSN that is not now deleted.
- I hope this works. */
- while (next && INSN_DELETED_P (next))
- next = NEXT_INSN (next);
- return next;
- }
+ {
+ rtx lab = JUMP_LABEL (insn), lab_next;
+
+ if (--LABEL_NUSES (lab) == 0)
+ {
+ /* This can delete NEXT or PREV,
+ either directly if NEXT is JUMP_LABEL (INSN),
+ or indirectly through more levels of jumps. */
+ delete_insn (lab);
+
+ /* I feel a little doubtful about this loop,
+ but I see no clean and sure alternative way
+ to find the first insn after INSN that is not now deleted.
+ I hope this works. */
+ while (next && INSN_DELETED_P (next))
+ next = NEXT_INSN (next);
+ return next;
+ }
+ else if ((lab_next = next_nonnote_insn (lab)) != NULL
+ && GET_CODE (lab_next) == JUMP_INSN
+ && (GET_CODE (PATTERN (lab_next)) == ADDR_VEC
+ || GET_CODE (PATTERN (lab_next)) == ADDR_DIFF_VEC))
+ {
+ /* If we're deleting the tablejump, delete the dispatch table.
+ We may not be able to kill the label immediately preceeding
+ just yet, as it might be referenced in code leading up to
+ the tablejump. */
+ delete_insn (lab_next);
+ }
+ }
/* Likewise if we're deleting a dispatch table. */
@@ -4259,7 +4462,15 @@ delete_labelref_insn (insn, label, delete_this)
/* Like rtx_equal_p except that it considers two REGs as equal
if they renumber to the same value and considers two commutative
operations to be the same if the order of the operands has been
- reversed. */
+ reversed.
+
+ ??? Addition is not commutative on the PA due to the weird implicit
+ space register selection rules for memory addresses. Therefore, we
+ don't consider a + b == b + a.
+
+ We could/should make this test a little tighter. Possibly only
+ disabling it on the PA via some backend macro or only disabling this
+ case when the PLUS is inside a MEM. */
int
rtx_renumbered_equal_p (x, y)
@@ -4371,8 +4582,11 @@ rtx_renumbered_equal_p (x, y)
return 0;
/* For commutative operations, the RTX match if the operand match in any
- order. Also handle the simple binary and unary cases without a loop. */
- if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
+ order. Also handle the simple binary and unary cases without a loop.
+
+ ??? Don't consider PLUS a commutative operator; see comments above. */
+ if ((code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
+ && code != PLUS)
return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
&& rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
|| (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
diff --git a/contrib/gcc/lcm.c b/contrib/gcc/lcm.c
new file mode 100644
index 0000000..01367e3
--- /dev/null
+++ b/contrib/gcc/lcm.c
@@ -0,0 +1,799 @@
+/* Generic partial redundancy elimination with lazy code motion
+ support.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* These routines are meant to be used by various optimization
+ passes which can be modeled as lazy code motion problems.
+ Including, but not limited to:
+
+ * Traditional partial redundancy elimination.
+
+ * Placement of caller/caller register save/restores.
+
+ * Load/store motion.
+
+ * Copy motion.
+
+ * Conversion of flat register files to a stacked register
+ model.
+
+ * Dead load/store elimination.
+
+ These routines accept as input:
+
+ * Basic block information (number of blocks, lists of
+ predecessors and successors). Note the granularity
+ does not need to be basic block, they could be statements
+ or functions.
+
+ * Bitmaps of local properties (computed, transparent and
+ anticipatable expressions).
+
+ The output of these routines is bitmap of redundant computations
+ and a bitmap of optimal placement points. */
+
+
+#include "config.h"
+#include "system.h"
+
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "flags.h"
+#include "real.h"
+#include "insn-config.h"
+#include "recog.h"
+#include "basic-block.h"
+
+static void compute_antinout PROTO ((int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *, sbitmap *));
+static void compute_earlyinout PROTO ((int, int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *, sbitmap *));
+static void compute_delayinout PROTO ((int, int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *,
+ sbitmap *, sbitmap *));
+static void compute_latein PROTO ((int, int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *));
+static void compute_isoinout PROTO ((int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *, sbitmap *));
+static void compute_optimal PROTO ((int, sbitmap *,
+ sbitmap *, sbitmap *));
+static void compute_redundant PROTO ((int, int, sbitmap *,
+ sbitmap *, sbitmap *, sbitmap *));
+
+/* Similarly, but for the reversed flowgraph. */
+static void compute_avinout PROTO ((int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *, sbitmap *));
+static void compute_fartherinout PROTO ((int, int, int_list_ptr *,
+ sbitmap *, sbitmap *,
+ sbitmap *, sbitmap *));
+static void compute_earlierinout PROTO ((int, int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *,
+ sbitmap *, sbitmap *));
+static void compute_firstout PROTO ((int, int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *));
+static void compute_rev_isoinout PROTO ((int, int_list_ptr *, sbitmap *,
+ sbitmap *, sbitmap *, sbitmap *));
+
+/* Given local properties TRANSP, ANTLOC, return the redundant and optimal
+ computation points for expressions.
+
+ To reduce overall memory consumption, we allocate memory immediately
+ before its needed and deallocate it as soon as possible. */
+void
+pre_lcm (n_blocks, n_exprs, s_preds, s_succs, transp,
+ antloc, redundant, optimal)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_preds;
+ int_list_ptr *s_succs;
+ sbitmap *transp;
+ sbitmap *antloc;
+ sbitmap *redundant;
+ sbitmap *optimal;
+{
+ sbitmap *antin, *antout, *earlyin, *earlyout, *delayin, *delayout;
+ sbitmap *latein, *isoin, *isoout;
+
+ /* Compute global anticipatability. ANTOUT is not needed except to
+ compute ANTIN, so free its memory as soon as we return from
+ compute_antinout. */
+ antin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ antout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_antinout (n_blocks, s_succs, antloc,
+ transp, antin, antout);
+ free (antout);
+ antout = NULL;
+
+ /* Compute earliestness. EARLYOUT is not needed except to compute
+ EARLYIN, so free its memory as soon as we return from
+ compute_earlyinout. */
+ earlyin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ earlyout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_earlyinout (n_blocks, n_exprs, s_preds, transp, antin,
+ earlyin, earlyout);
+ free (earlyout);
+ earlyout = NULL;
+
+ /* Compute delayedness. DELAYOUT is not needed except to compute
+ DELAYIN, so free its memory as soon as we return from
+ compute_delayinout. We also no longer need ANTIN and EARLYIN. */
+ delayin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ delayout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_delayinout (n_blocks, n_exprs, s_preds, antloc,
+ antin, earlyin, delayin, delayout);
+ free (delayout);
+ delayout = NULL;
+ free (antin);
+ antin = NULL;
+ free (earlyin);
+ earlyin = NULL;
+
+ /* Compute latestness. We no longer need DELAYIN after we compute
+ LATEIN. */
+ latein = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_latein (n_blocks, n_exprs, s_succs, antloc, delayin, latein);
+ free (delayin);
+ delayin = NULL;
+
+ /* Compute isolatedness. ISOIN is not needed except to compute
+ ISOOUT, so free its memory as soon as we return from
+ compute_isoinout. */
+ isoin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ isoout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_isoinout (n_blocks, s_succs, antloc, latein, isoin, isoout);
+ free (isoin);
+ isoin = NULL;
+
+ /* Now compute optimal placement points and the redundant expressions. */
+ compute_optimal (n_blocks, latein, isoout, optimal);
+ compute_redundant (n_blocks, n_exprs, antloc, latein, isoout, redundant);
+ free (latein);
+ latein = NULL;
+ free (isoout);
+ isoout = NULL;
+}
+
+/* Given local properties TRANSP, AVLOC, return the redundant and optimal
+ computation points for expressions on the reverse flowgraph.
+
+ To reduce overall memory consumption, we allocate memory immediately
+ before its needed and deallocate it as soon as possible. */
+
+void
+pre_rev_lcm (n_blocks, n_exprs, s_preds, s_succs, transp,
+ avloc, redundant, optimal)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_preds;
+ int_list_ptr *s_succs;
+ sbitmap *transp;
+ sbitmap *avloc;
+ sbitmap *redundant;
+ sbitmap *optimal;
+{
+ sbitmap *avin, *avout, *fartherin, *fartherout, *earlierin, *earlierout;
+ sbitmap *firstout, *rev_isoin, *rev_isoout;
+
+ /* Compute global availability. AVIN is not needed except to
+ compute AVOUT, so free its memory as soon as we return from
+ compute_avinout. */
+ avin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ avout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_avinout (n_blocks, s_preds, avloc, transp, avin, avout);
+ free (avin);
+ avin = NULL;
+
+ /* Compute fartherness. FARTHERIN is not needed except to compute
+ FARTHEROUT, so free its memory as soon as we return from
+ compute_earlyinout. */
+ fartherin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ fartherout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_fartherinout (n_blocks, n_exprs, s_succs, transp,
+ avout, fartherin, fartherout);
+ free (fartherin);
+ fartherin = NULL;
+
+ /* Compute earlierness. EARLIERIN is not needed except to compute
+ EARLIEROUT, so free its memory as soon as we return from
+ compute_delayinout. We also no longer need AVOUT and FARTHEROUT. */
+ earlierin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ earlierout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_earlierinout (n_blocks, n_exprs, s_succs, avloc,
+ avout, fartherout, earlierin, earlierout);
+ free (earlierin);
+ earlierin = NULL;
+ free (avout);
+ avout = NULL;
+ free (fartherout);
+ fartherout = NULL;
+
+ /* Compute firstness. We no longer need EARLIEROUT after we compute
+ FIRSTOUT. */
+ firstout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_firstout (n_blocks, n_exprs, s_preds, avloc, earlierout, firstout);
+ free (earlierout);
+ earlierout = NULL;
+
+ /* Compute rev_isolatedness. ISOIN is not needed except to compute
+ ISOOUT, so free its memory as soon as we return from
+ compute_isoinout. */
+ rev_isoin = sbitmap_vector_alloc (n_blocks, n_exprs);
+ rev_isoout = sbitmap_vector_alloc (n_blocks, n_exprs);
+ compute_rev_isoinout (n_blocks, s_preds, avloc, firstout,
+ rev_isoin, rev_isoout);
+ free (rev_isoout);
+ rev_isoout = NULL;
+
+ /* Now compute optimal placement points and the redundant expressions. */
+ compute_optimal (n_blocks, firstout, rev_isoin, optimal);
+ compute_redundant (n_blocks, n_exprs, avloc, firstout, rev_isoin, redundant);
+ free (firstout);
+ firstout = NULL;
+ free (rev_isoin);
+ rev_isoin = NULL;
+}
+
+/* Compute expression anticipatability at entrance and exit of each block. */
+
+static void
+compute_antinout (n_blocks, s_succs, antloc, transp, antin, antout)
+ int n_blocks;
+ int_list_ptr *s_succs;
+ sbitmap *antloc;
+ sbitmap *transp;
+ sbitmap *antin;
+ sbitmap *antout;
+{
+ int bb, changed, passes;
+ sbitmap old_changed, new_changed;
+
+ sbitmap_zero (antout[n_blocks - 1]);
+ sbitmap_vector_ones (antin, n_blocks);
+
+ old_changed = sbitmap_alloc (n_blocks);
+ new_changed = sbitmap_alloc (n_blocks);
+ sbitmap_ones (old_changed);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ sbitmap_zero (new_changed);
+ /* We scan the blocks in the reverse order to speed up
+ the convergence. */
+ for (bb = n_blocks - 1; bb >= 0; bb--)
+ {
+ int_list_ptr ps;
+
+ /* If none of the successors of this block have changed,
+ then this block is not going to change. */
+ for (ps = s_succs[bb] ; ps; ps = ps->next)
+ {
+ if (INT_LIST_VAL (ps) == EXIT_BLOCK
+ || INT_LIST_VAL (ps) == ENTRY_BLOCK)
+ break;
+
+ if (TEST_BIT (old_changed, INT_LIST_VAL (ps))
+ || TEST_BIT (new_changed, INT_LIST_VAL (ps)))
+ break;
+ }
+
+ if (!ps)
+ continue;
+
+ if (bb != n_blocks - 1)
+ sbitmap_intersect_of_successors (antout[bb], antin,
+ bb, s_succs);
+ if (sbitmap_a_or_b_and_c (antin[bb], antloc[bb],
+ transp[bb], antout[bb]))
+ {
+ changed = 1;
+ SET_BIT (new_changed, bb);
+ }
+ }
+ sbitmap_copy (old_changed, new_changed);
+ passes++;
+ }
+ free (old_changed);
+ free (new_changed);
+}
+
+/* Compute expression earliestness at entrance and exit of each block.
+
+ From Advanced Compiler Design and Implementation pp411.
+
+ An expression is earliest at the entrance to basic block BB if no
+ block from entry to block BB both evaluates the expression and
+ produces the same value as evaluating it at the entry to block BB
+ does. Similarly for earlistness at basic block BB exit. */
+
+static void
+compute_earlyinout (n_blocks, n_exprs, s_preds, transp, antin,
+ earlyin, earlyout)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_preds;
+ sbitmap *transp;
+ sbitmap *antin;
+ sbitmap *earlyin;
+ sbitmap *earlyout;
+{
+ int bb, changed, passes;
+ sbitmap temp_bitmap;
+ sbitmap old_changed, new_changed;
+
+ temp_bitmap = sbitmap_alloc (n_exprs);
+
+ sbitmap_vector_zero (earlyout, n_blocks);
+ sbitmap_ones (earlyin[0]);
+
+ old_changed = sbitmap_alloc (n_blocks);
+ new_changed = sbitmap_alloc (n_blocks);
+ sbitmap_ones (old_changed);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ sbitmap_zero (new_changed);
+ for (bb = 0; bb < n_blocks; bb++)
+ {
+ int_list_ptr ps;
+
+ /* If none of the predecessors of this block have changed,
+ then this block is not going to change. */
+ for (ps = s_preds[bb] ; ps; ps = ps->next)
+ {
+ if (INT_LIST_VAL (ps) == EXIT_BLOCK
+ || INT_LIST_VAL (ps) == ENTRY_BLOCK)
+ break;
+
+ if (TEST_BIT (old_changed, INT_LIST_VAL (ps))
+ || TEST_BIT (new_changed, INT_LIST_VAL (ps)))
+ break;
+ }
+
+ if (!ps)
+ continue;
+
+ if (bb != 0)
+ sbitmap_union_of_predecessors (earlyin[bb], earlyout,
+ bb, s_preds);
+ sbitmap_not (temp_bitmap, transp[bb]);
+ if (sbitmap_union_of_diff (earlyout[bb], temp_bitmap,
+ earlyin[bb], antin[bb]))
+ {
+ changed = 1;
+ SET_BIT (new_changed, bb);
+ }
+ }
+ sbitmap_copy (old_changed, new_changed);
+ passes++;
+ }
+ free (old_changed);
+ free (new_changed);
+ free (temp_bitmap);
+}
+
+/* Compute expression delayedness at entrance and exit of each block.
+
+ From Advanced Compiler Design and Implementation pp411.
+
+ An expression is delayed at the entrance to BB if it is anticipatable
+ and earliest at that point and if all subsequent computations of
+ the expression are in block BB. */
+
+static void
+compute_delayinout (n_blocks, n_exprs, s_preds, antloc,
+ antin, earlyin, delayin, delayout)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_preds;
+ sbitmap *antloc;
+ sbitmap *antin;
+ sbitmap *earlyin;
+ sbitmap *delayin;
+ sbitmap *delayout;
+{
+ int bb, changed, passes;
+ sbitmap *anti_and_early;
+ sbitmap temp_bitmap;
+
+ temp_bitmap = sbitmap_alloc (n_exprs);
+
+ /* This is constant throughout the flow equations below, so compute
+ it once to save time. */
+ anti_and_early = sbitmap_vector_alloc (n_blocks, n_exprs);
+ for (bb = 0; bb < n_blocks; bb++)
+ sbitmap_a_and_b (anti_and_early[bb], antin[bb], earlyin[bb]);
+
+ sbitmap_vector_zero (delayout, n_blocks);
+ sbitmap_copy (delayin[0], anti_and_early[0]);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (bb = 0; bb < n_blocks; bb++)
+ {
+ if (bb != 0)
+ {
+ sbitmap_intersect_of_predecessors (temp_bitmap, delayout,
+ bb, s_preds);
+ changed |= sbitmap_a_or_b (delayin[bb],
+ anti_and_early[bb],
+ temp_bitmap);
+ }
+ sbitmap_not (temp_bitmap, antloc[bb]);
+ changed |= sbitmap_a_and_b (delayout[bb],
+ temp_bitmap,
+ delayin[bb]);
+ }
+ passes++;
+ }
+
+ /* We're done with this, so go ahead and free it's memory now instead
+ of waiting until the end of pre. */
+ free (anti_and_early);
+ free (temp_bitmap);
+}
+
+/* Compute latestness.
+
+ From Advanced Compiler Design and Implementation pp412.
+
+ An expression is latest at the entrance to block BB if that is an optimal
+ point for computing the expression and if on every path from block BB's
+ entrance to the exit block, any optimal computation point for the
+ expression occurs after one of the points at which the expression was
+ computed in the original flowgraph. */
+
+static void
+compute_latein (n_blocks, n_exprs, s_succs, antloc, delayin, latein)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_succs;
+ sbitmap *antloc;
+ sbitmap *delayin;
+ sbitmap *latein;
+{
+ int bb;
+ sbitmap temp_bitmap;
+
+ temp_bitmap = sbitmap_alloc (n_exprs);
+
+ for (bb = 0; bb < n_blocks; bb++)
+ {
+ /* The last block is succeeded only by the exit block; therefore,
+ temp_bitmap will not be set by the following call! */
+ if (bb == n_blocks - 1)
+ {
+ sbitmap_intersect_of_successors (temp_bitmap, delayin,
+ bb, s_succs);
+ sbitmap_not (temp_bitmap, temp_bitmap);
+ }
+ else
+ sbitmap_ones (temp_bitmap);
+ sbitmap_a_and_b_or_c (latein[bb], delayin[bb],
+ antloc[bb], temp_bitmap);
+ }
+ free (temp_bitmap);
+}
+
+/* Compute isolated.
+
+ From Advanced Compiler Design and Implementation pp413.
+
+ A computationally optimal placement for the evaluation of an expression
+ is defined to be isolated if and only if on every path from a successor
+ of the block in which it is computed to the exit block, every original
+ computation of the expression is preceded by the optimal placement point. */
+
+static void
+compute_isoinout (n_blocks, s_succs, antloc, latein, isoin, isoout)
+ int n_blocks;
+ int_list_ptr *s_succs;
+ sbitmap *antloc;
+ sbitmap *latein;
+ sbitmap *isoin;
+ sbitmap *isoout;
+{
+ int bb, changed, passes;
+
+ sbitmap_vector_zero (isoin, n_blocks);
+ sbitmap_zero (isoout[n_blocks - 1]);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (bb = n_blocks - 1; bb >= 0; bb--)
+ {
+ if (bb != n_blocks - 1)
+ sbitmap_intersect_of_successors (isoout[bb], isoin,
+ bb, s_succs);
+ changed |= sbitmap_union_of_diff (isoin[bb], latein[bb],
+ isoout[bb], antloc[bb]);
+ }
+ passes++;
+ }
+}
+
+/* Compute the set of expressions which have optimal computational points
+ in each basic block. This is the set of expressions that are latest, but
+ that are not isolated in the block. */
+
+static void
+compute_optimal (n_blocks, latein, isoout, optimal)
+ int n_blocks;
+ sbitmap *latein;
+ sbitmap *isoout;
+ sbitmap *optimal;
+{
+ int bb;
+
+ for (bb = 0; bb < n_blocks; bb++)
+ sbitmap_difference (optimal[bb], latein[bb], isoout[bb]);
+}
+
+/* Compute the set of expressions that are redundant in a block. They are
+ the expressions that are used in the block and that are neither isolated
+ or latest. */
+
+static void
+compute_redundant (n_blocks, n_exprs, antloc, latein, isoout, redundant)
+ int n_blocks;
+ int n_exprs;
+ sbitmap *antloc;
+ sbitmap *latein;
+ sbitmap *isoout;
+ sbitmap *redundant;
+{
+ int bb;
+ sbitmap temp_bitmap;
+
+ temp_bitmap = sbitmap_alloc (n_exprs);
+
+ for (bb = 0; bb < n_blocks; bb++)
+ {
+ sbitmap_a_or_b (temp_bitmap, latein[bb], isoout[bb]);
+ sbitmap_difference (redundant[bb], antloc[bb], temp_bitmap);
+ }
+ free (temp_bitmap);
+}
+
+/* Compute expression availability at entrance and exit of each block. */
+
+static void
+compute_avinout (n_blocks, s_preds, avloc, transp, avin, avout)
+ int n_blocks;
+ int_list_ptr *s_preds;
+ sbitmap *avloc;
+ sbitmap *transp;
+ sbitmap *avin;
+ sbitmap *avout;
+{
+ int bb, changed, passes;
+
+ sbitmap_zero (avin[0]);
+ sbitmap_vector_ones (avout, n_blocks);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (bb = 0; bb < n_blocks; bb++)
+ {
+ if (bb != 0)
+ sbitmap_intersect_of_predecessors (avin[bb], avout,
+ bb, s_preds);
+ changed |= sbitmap_a_or_b_and_c (avout[bb], avloc[bb],
+ transp[bb], avin[bb]);
+ }
+ passes++;
+ }
+}
+
+/* Compute expression latestness.
+
+ This is effectively the same as earliestness computed on the reverse
+ flow graph. */
+
+static void
+compute_fartherinout (n_blocks, n_exprs, s_succs,
+ transp, avout, fartherin, fartherout)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_succs;
+ sbitmap *transp;
+ sbitmap *avout;
+ sbitmap *fartherin;
+ sbitmap *fartherout;
+{
+ int bb, changed, passes;
+ sbitmap temp_bitmap;
+
+ temp_bitmap = sbitmap_alloc (n_exprs);
+
+ sbitmap_vector_zero (fartherin, n_blocks);
+ sbitmap_ones (fartherout[n_blocks - 1]);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (bb = n_blocks - 1; bb >= 0; bb--)
+ {
+ if (bb != n_blocks - 1)
+ sbitmap_union_of_successors (fartherout[bb], fartherin,
+ bb, s_succs);
+ sbitmap_not (temp_bitmap, transp[bb]);
+ changed |= sbitmap_union_of_diff (fartherin[bb], temp_bitmap,
+ fartherout[bb], avout[bb]);
+ }
+ passes++;
+ }
+
+ free (temp_bitmap);
+}
+
+/* Compute expression earlierness at entrance and exit of each block.
+
+ This is effectively the same as delayedness computed on the reverse
+ flow graph. */
+
+static void
+compute_earlierinout (n_blocks, n_exprs, s_succs, avloc,
+ avout, fartherout, earlierin, earlierout)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_succs;
+ sbitmap *avloc;
+ sbitmap *avout;
+ sbitmap *fartherout;
+ sbitmap *earlierin;
+ sbitmap *earlierout;
+{
+ int bb, changed, passes;
+ sbitmap *av_and_farther;
+ sbitmap temp_bitmap;
+
+ temp_bitmap = sbitmap_alloc (n_exprs);
+
+ /* This is constant throughout the flow equations below, so compute
+ it once to save time. */
+ av_and_farther = sbitmap_vector_alloc (n_blocks, n_exprs);
+ for (bb = 0; bb < n_blocks; bb++)
+ sbitmap_a_and_b (av_and_farther[bb], avout[bb], fartherout[bb]);
+
+ sbitmap_vector_zero (earlierin, n_blocks);
+ sbitmap_copy (earlierout[n_blocks - 1], av_and_farther[n_blocks - 1]);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (bb = n_blocks - 1; bb >= 0; bb--)
+ {
+ if (bb != n_blocks - 1)
+ {
+ sbitmap_intersect_of_successors (temp_bitmap, earlierin,
+ bb, s_succs);
+ changed |= sbitmap_a_or_b (earlierout[bb],
+ av_and_farther[bb],
+ temp_bitmap);
+ }
+ sbitmap_not (temp_bitmap, avloc[bb]);
+ changed |= sbitmap_a_and_b (earlierin[bb],
+ temp_bitmap,
+ earlierout[bb]);
+ }
+ passes++;
+ }
+
+ /* We're done with this, so go ahead and free it's memory now instead
+ of waiting until the end of pre. */
+ free (av_and_farther);
+ free (temp_bitmap);
+}
+
+/* Compute firstness.
+
+ This is effectively the same as latestness computed on the reverse
+ flow graph. */
+
+static void
+compute_firstout (n_blocks, n_exprs, s_preds, avloc, earlierout, firstout)
+ int n_blocks;
+ int n_exprs;
+ int_list_ptr *s_preds;
+ sbitmap *avloc;
+ sbitmap *earlierout;
+ sbitmap *firstout;
+{
+ int bb;
+ sbitmap temp_bitmap;
+
+ temp_bitmap = sbitmap_alloc (n_exprs);
+
+ for (bb = 0; bb < n_blocks; bb++)
+ {
+ /* The first block is preceded only by the entry block; therefore,
+ temp_bitmap will not be set by the following call! */
+ if (bb != 0)
+ {
+ sbitmap_intersect_of_predecessors (temp_bitmap, earlierout,
+ bb, s_preds);
+ sbitmap_not (temp_bitmap, temp_bitmap);
+ }
+ else
+ {
+ sbitmap_ones (temp_bitmap);
+ }
+ sbitmap_a_and_b_or_c (firstout[bb], earlierout[bb],
+ avloc[bb], temp_bitmap);
+ }
+ free (temp_bitmap);
+}
+
+/* Compute reverse isolated.
+
+ This is effectively the same as isolatedness computed on the reverse
+ flow graph. */
+
+static void
+compute_rev_isoinout (n_blocks, s_preds, avloc, firstout,
+ rev_isoin, rev_isoout)
+ int n_blocks;
+ int_list_ptr *s_preds;
+ sbitmap *avloc;
+ sbitmap *firstout;
+ sbitmap *rev_isoin;
+ sbitmap *rev_isoout;
+{
+ int bb, changed, passes;
+
+ sbitmap_vector_zero (rev_isoout, n_blocks);
+ sbitmap_zero (rev_isoin[0]);
+
+ passes = 0;
+ changed = 1;
+ while (changed)
+ {
+ changed = 0;
+ for (bb = 0; bb < n_blocks; bb++)
+ {
+ if (bb != 0)
+ sbitmap_intersect_of_predecessors (rev_isoin[bb], rev_isoout,
+ bb, s_preds);
+ changed |= sbitmap_union_of_diff (rev_isoout[bb], firstout[bb],
+ rev_isoin[bb], avloc[bb]);
+ }
+ passes++;
+ }
+}
diff --git a/contrib/gcc/libgcc2.c b/contrib/gcc/libgcc2.c
index d1854ed..6d8fb0b 100644
--- a/contrib/gcc/libgcc2.c
+++ b/contrib/gcc/libgcc2.c
@@ -1,6 +1,6 @@
/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
-/* Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -72,6 +72,10 @@ Boston, MA 02111-1307, USA. */
#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
#endif
+#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
+#endif
+
/* In the first part of this file, we are interfacing to calls generated
by the compiler itself. These calls pass values into these routines
which have very specific modes (rather than very specific types), and
@@ -90,10 +94,10 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef float SFtype __attribute__ ((mode (SF)));
typedef float DFtype __attribute__ ((mode (DF)));
-#if LONG_DOUBLE_TYPE_SIZE == 96
+#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
typedef float XFtype __attribute__ ((mode (XF)));
#endif
-#if LONG_DOUBLE_TYPE_SIZE == 128
+#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
typedef float TFtype __attribute__ ((mode (TF)));
#endif
@@ -144,10 +148,10 @@ typedef union
extern DItype __fixunssfdi (SFtype a);
extern DItype __fixunsdfdi (DFtype a);
-#if LONG_DOUBLE_TYPE_SIZE == 96
+#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
extern DItype __fixunsxfdi (XFtype a);
#endif
-#if LONG_DOUBLE_TYPE_SIZE == 128
+#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
extern DItype __fixunstfdi (TFtype a);
#endif
@@ -768,7 +772,7 @@ __ucmpdi2 (DItype a, DItype b)
}
#endif
-#if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
+#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
@@ -800,7 +804,7 @@ __fixunstfdi (TFtype a)
}
#endif
-#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
+#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
DItype
__fixtfdi (TFtype a)
{
@@ -810,7 +814,7 @@ __fixtfdi (TFtype a)
}
#endif
-#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
@@ -842,7 +846,7 @@ __fixunsxfdi (XFtype a)
}
#endif
-#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
DItype
__fixxfdi (XFtype a)
{
@@ -940,7 +944,7 @@ __fixsfdi (SFtype a)
}
#endif
-#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
@@ -959,7 +963,7 @@ __floatdixf (DItype u)
}
#endif
-#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
+#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
@@ -1065,7 +1069,7 @@ __floatdisf (DItype u)
}
#endif
-#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
+#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
/* Reenable the normal types, in case limits.h needs them. */
#undef char
#undef short
@@ -1403,6 +1407,9 @@ __builtin_saveregs ()
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
/* This is used by the `assert' macro. */
+extern void __eprintf (const char *, const char *, unsigned int, const char *)
+ __attribute__ ((__noreturn__));
+
void
__eprintf (const char *string, const char *expression,
unsigned int line, const char *filename)
@@ -2569,7 +2576,7 @@ __clear_cache (char *beg, char *end)
/* Jump to a trampoline, loading the static chain address. */
-#if defined(WINNT) && ! defined(__CYGWIN32__)
+#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
long getpagesize()
{
@@ -2608,7 +2615,7 @@ mprotect (char *addr, int len, int prot)
return -1;
}
-#endif
+#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
#ifdef TRANSFER_FROM_TRAMPOLINE
TRANSFER_FROM_TRAMPOLINE
@@ -2807,7 +2814,7 @@ cacheflush (char *beg, int size, int flag)
#endif /* sony_news */
#endif /* L_trampoline */
-#ifndef __CYGWIN32__
+#ifndef __CYGWIN__
#ifdef L__main
#include "gbl-ctors.h"
@@ -2889,7 +2896,7 @@ SYMBOL__MAIN ()
#endif /* no HAS_INIT_SECTION or INVOKE__main */
#endif /* L__main */
-#endif /* __CYGWIN32__ */
+#endif /* __CYGWIN__ */
#ifdef L_ctors
@@ -2901,10 +2908,15 @@ SYMBOL__MAIN ()
the right values. */
/* We declare the lists here with two elements each,
- so that they are valid empty lists if no other definition is loaded. */
+ so that they are valid empty lists if no other definition is loaded.
+
+ If we are using the old "set" extensions to have the gnu linker
+ collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
+ must be in the bss/common section.
+
+ Long term no port should use those extensions. But many still do. */
#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
-#if defined(__NeXT__) || defined(_AIX)
-/* After 2.3, try this definition on all systems. */
+#if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
func_ptr __CTOR_LIST__[2] = {0, 0};
func_ptr __DTOR_LIST__[2] = {0, 0};
#else
@@ -3023,6 +3035,8 @@ int atexit (func_ptr func)
/* Shared exception handling support routines. */
+extern void __default_terminate (void) __attribute__ ((__noreturn__));
+
void
__default_terminate ()
{
@@ -3058,6 +3072,9 @@ __empty ()
/* Include definitions of EH context and table layout */
#include "eh-common.h"
+#ifndef inhibit_libc
+#include <stdio.h>
+#endif
/* Allocate and return a new EH context structure. */
@@ -3177,10 +3194,17 @@ eh_context_initialize ()
static struct eh_context *
eh_context_static ()
{
- static struct eh_context *eh;
- if (! eh)
- eh = new_eh_context ();
- return eh;
+ static struct eh_context eh;
+ static int initialized;
+ static void *top_elt[2];
+
+ if (! initialized)
+ {
+ initialized = 1;
+ memset (&eh, 0, sizeof eh);
+ eh.dynamic_handler_chain = top_elt;
+ }
+ return &eh;
}
#if __GTHREADS
@@ -3230,6 +3254,8 @@ __get_dynamic_handler_chain ()
dynamic handler chain, and use longjmp to transfer back to the associated
handler. */
+extern void __sjthrow (void) __attribute__ ((__noreturn__));
+
void
__sjthrow ()
{
@@ -3306,6 +3332,8 @@ __sjthrow ()
then throw. This is used to skip the first handler, and transfer
control to the next handler in the dynamic handler stack. */
+extern void __sjpopnthrow (void) __attribute__ ((__noreturn__));
+
void
__sjpopnthrow ()
{
@@ -3362,6 +3390,26 @@ __sjpopnthrow ()
/* Support code for all exception region-based exception handling. */
+int
+__eh_rtime_match (void *rtime)
+{
+ void *info;
+ __eh_matcher matcher;
+ void *ret;
+
+ info = *(__get_eh_info ());
+ matcher = ((__eh_info *)info)->match_function;
+ if (! matcher)
+ {
+#ifndef inhibit_libc
+ fprintf (stderr, "Internal Compiler Bug: No runtime type matcher.");
+#endif
+ return 0;
+ }
+ ret = (*matcher) (info, rtime, (void *)0);
+ return (ret != NULL);
+}
+
/* This value identifies the place from which an exception is being
thrown. */
@@ -3429,45 +3477,82 @@ old_find_exception_handler (void *pc, old_exception_table *table)
return (void *) 0;
}
+/* find_exception_handler finds the correct handler, if there is one, to
+ handle an exception.
+ returns a pointer to the handler which controlled should be transferred
+ to, or NULL if there is nothing left.
+ Parameters:
+ PC - pc where the exception originates. If this is a rethrow,
+ then this starts out as a pointer to the exception table
+ entry we wish to rethrow out of.
+ TABLE - exception table for the current module.
+ EH_INFO - eh info pointer for this exception.
+ RETHROW - 1 if this is a rethrow. (see incoming value of PC).
+ CLEANUP - returned flag indicating whether this is a cleanup handler.
+*/
static void *
-find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
+find_exception_handler (void *pc, exception_descriptor *table,
+ __eh_info *eh_info, int rethrow, int *cleanup)
{
+
+ void *retval = NULL;
+ *cleanup = 1;
if (table)
{
+ int pos = 0;
/* The new model assumed the table is sorted inner-most out so the
first region we find which matches is the correct one */
- int pos;
- void *ret;
exception_table *tab = &(table->table[0]);
/* Subtract 1 from the PC to avoid hitting the next region */
- pc--;
+ if (rethrow)
+ {
+ /* pc is actually the region table entry to rethrow out of */
+ pos = ((exception_table *) pc) - tab;
+ pc = ((exception_table *) pc)->end_region - 1;
+
+ /* The label is always on the LAST handler entry for a region,
+ so we know the next entry is a different region, even if the
+ addresses are the same. Make sure its not end of table tho. */
+ if (tab[pos].start_region != (void *) -1)
+ pos++;
+ }
+ else
+ pc--;
/* We can't do a binary search because the table is in inner-most
to outermost address ranges within functions */
- for (pos = 0; tab[pos].start_region != (void *) -1; pos++)
+ for ( ; tab[pos].start_region != (void *) -1; pos++)
{
if (tab[pos].start_region <= pc && tab[pos].end_region > pc)
{
if (tab[pos].match_info)
{
- __eh_matcher matcher = ((__eh_info *)eh_info)->match_function;
+ __eh_matcher matcher = eh_info->match_function;
/* match info but no matcher is NOT a match */
if (matcher)
{
- ret = (*matcher)(eh_info, tab[pos].match_info, table);
- if (ret)
- return tab[pos].exception_handler;
+ void *ret = (*matcher)((void *) eh_info,
+ tab[pos].match_info, table);
+ if (ret)
+ {
+ if (retval == NULL)
+ retval = tab[pos].exception_handler;
+ *cleanup = 0;
+ break;
+ }
}
}
else
- return tab[pos].exception_handler;
+ {
+ if (retval == NULL)
+ retval = tab[pos].exception_handler;
+ }
}
}
}
-
- return (void *) 0;
+ return retval;
}
#endif /* DWARF2_UNWIND_INFO */
#endif /* EH_TABLE_LOOKUP */
@@ -3484,31 +3569,71 @@ find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
typedef int ptr_type __attribute__ ((mode (pointer)));
-/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
+#ifdef INCOMING_REGNO
+/* Is the saved value for register REG in frame UDATA stored in a register
+ window in the previous frame? */
+
+/* ??? The Sparc INCOMING_REGNO references TARGET_FLAT. This allows us
+ to use the macro here. One wonders, though, that perhaps TARGET_FLAT
+ compiled functions won't work with the frame-unwind stuff here.
+ Perhaps the entireity of in_reg_window should be conditional on having
+ seen a DW_CFA_GNU_window_save? */
+#define target_flags 0
+
+static int
+in_reg_window (int reg, frame_state *udata)
+{
+ if (udata->saved[reg] == REG_SAVED_REG)
+ return INCOMING_REGNO (reg) == reg;
+ if (udata->saved[reg] != REG_SAVED_OFFSET)
+ return 0;
+
+#ifdef STACK_GROWS_DOWNWARD
+ return udata->reg_or_offset[reg] > 0;
+#else
+ return udata->reg_or_offset[reg] < 0;
+#endif
+}
+#else
+static inline int in_reg_window (int reg, frame_state *udata) { return 0; }
+#endif /* INCOMING_REGNO */
+
+/* Get the address of register REG as saved in UDATA, where SUB_UDATA is a
frame called by UDATA or 0. */
-static void*
-get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
+static word_type *
+get_reg_addr (unsigned reg, frame_state *udata, frame_state *sub_udata)
{
+ while (udata->saved[reg] == REG_SAVED_REG)
+ {
+ reg = udata->reg_or_offset[reg];
+ if (in_reg_window (reg, udata))
+ {
+ udata = sub_udata;
+ sub_udata = NULL;
+ }
+ }
if (udata->saved[reg] == REG_SAVED_OFFSET)
- return (void *)(ptr_type)
- *(word_type *)(udata->cfa + udata->reg_or_offset[reg]);
- else if (udata->saved[reg] == REG_SAVED_REG && sub_udata)
- return get_reg (udata->reg_or_offset[reg], sub_udata, 0);
+ return (word_type *)(udata->cfa + udata->reg_or_offset[reg]);
else
abort ();
}
+/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
+ frame called by UDATA or 0. */
+
+static inline void *
+get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
+{
+ return (void *)(ptr_type) *get_reg_addr (reg, udata, sub_udata);
+}
+
/* Overwrite the saved value for register REG in frame UDATA with VAL. */
-static void
+static inline void
put_reg (unsigned reg, void *val, frame_state *udata)
{
- if (udata->saved[reg] == REG_SAVED_OFFSET)
- *(word_type *)(udata->cfa + udata->reg_or_offset[reg])
- = (word_type)(ptr_type) val;
- else
- abort ();
+ *get_reg_addr (reg, udata, NULL) = (word_type)(ptr_type) val;
}
/* Copy the saved value for register REG from frame UDATA to frame
@@ -3518,17 +3643,13 @@ put_reg (unsigned reg, void *val, frame_state *udata)
static void
copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
{
- if (udata->saved[reg] == REG_SAVED_OFFSET
- && target_udata->saved[reg] == REG_SAVED_OFFSET)
- memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
- udata->cfa + udata->reg_or_offset[reg],
- __builtin_dwarf_reg_size (reg));
- else
- abort ();
+ word_type *preg = get_reg_addr (reg, udata, NULL);
+ word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
+
+ memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
}
-/* Retrieve the return address for frame UDATA, where SUB_UDATA is a
- frame called by UDATA or 0. */
+/* Retrieve the return address for frame UDATA. */
static inline void *
get_return_addr (frame_state *udata, frame_state *sub_udata)
@@ -3568,76 +3689,55 @@ next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
return caller_udata;
}
-#ifdef INCOMING_REGNO
-/* Is the saved value for register REG in frame UDATA stored in a register
- window in the previous frame? */
-
-static int
-in_reg_window (int reg, frame_state *udata)
+/* Hook to call before __terminate if only cleanup handlers remain. */
+void
+__unwinding_cleanup ()
{
- if (udata->saved[reg] != REG_SAVED_OFFSET)
- return 0;
-
-#ifdef STACK_GROWS_DOWNWARD
- return udata->reg_or_offset[reg] > 0;
-#else
- return udata->reg_or_offset[reg] < 0;
-#endif
}
-#endif /* INCOMING_REGNO */
-/* We first search for an exception handler, and if we don't find
- it, we call __terminate on the current stack frame so that we may
- use the debugger to walk the stack and understand why no handler
- was found.
+/* throw_helper performs some of the common grunt work for a throw. This
+ routine is called by throw and rethrows. This is pretty much split
+ out from the old __throw routine. An addition has been added which allows
+ for a dummy call to a routine __unwinding_cleanup() when there are nothing
+ but cleanups remaining. This allows a debugger to examine the state
+ at which the throw was executed, before any cleanups, rather than
+ at the terminate point after the stack has been unwound.
- If we find one, then we unwind the frames down to the one that
- has the handler and transfer control into the handler. */
+ EH is the current eh_context structure.
+ PC is the address of the call to __throw.
+ MY_UDATA is the unwind information for __throw.
+ OFFSET_P is where we return the SP adjustment offset. */
-void
-__throw ()
-{
- struct eh_context *eh = (*get_eh_context) ();
- void *saved_pc, *pc, *handler, *retaddr;
- frame_state ustruct, ustruct2;
- frame_state *udata = &ustruct;
- frame_state *sub_udata = &ustruct2;
- frame_state my_ustruct, *my_udata = &my_ustruct;
+static void *
+throw_helper (eh, pc, my_udata, offset_p)
+ struct eh_context *eh;
+ void *pc;
+ frame_state *my_udata;
+ long *offset_p;
+{
+ frame_state ustruct2, *udata = &ustruct2;
+ frame_state ustruct;
+ frame_state *sub_udata = &ustruct;
+ void *saved_pc = pc;
+ void *handler;
+ void *handler_p;
+ void *pc_p;
+ frame_state saved_ustruct;
+ int new_eh_model;
+ int cleanup = 0;
+ int only_cleanup = 0;
+ int rethrow = 0;
+ int saved_state = 0;
long args_size;
- int new_exception_model;
+ __eh_info *eh_info = (__eh_info *)eh->info;
- /* This is required for C++ semantics. We must call terminate if we
- try and rethrow an exception, when there is no exception currently
- active. */
- if (! eh->info)
- __terminate ();
-
- /* Start at our stack frame. */
-label:
- udata = __frame_state_for (&&label, udata);
- if (! udata)
- __terminate ();
-
- /* We need to get the value from the CFA register. At this point in
- compiling __throw we don't know whether or not we will use the frame
- pointer register for the CFA, so we check our unwind info. */
- if (udata->cfa_reg == __builtin_dwarf_fp_regnum ())
- udata->cfa = __builtin_fp ();
- else
- udata->cfa = __builtin_sp ();
- udata->cfa += udata->cfa_offset;
+ /* Do we find a handler based on a re-throw PC? */
+ if (eh->table_index != (void *) 0)
+ rethrow = 1;
- memcpy (my_udata, udata, sizeof (*udata));
+ memcpy (udata, my_udata, sizeof (*udata));
- /* Do any necessary initialization to access arbitrary stack frames.
- On the SPARC, this means flushing the register windows. */
- __builtin_unwind_init ();
-
- /* Now reset pc to the right throw point. */
- pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
- saved_pc = pc;
-
- handler = 0;
+ handler = (void *) 0;
for (;;)
{
frame_state *p = udata;
@@ -3649,21 +3749,46 @@ label:
break;
if (udata->eh_ptr == NULL)
- new_exception_model = 0;
+ new_eh_model = 0;
else
- new_exception_model = (((exception_descriptor *)(udata->eh_ptr))->
+ new_eh_model = (((exception_descriptor *)(udata->eh_ptr))->
runtime_id_field == NEW_EH_RUNTIME);
- if (new_exception_model)
- handler = find_exception_handler (pc, udata->eh_ptr, eh->info);
+ if (rethrow)
+ {
+ rethrow = 0;
+ handler = find_exception_handler (eh->table_index, udata->eh_ptr,
+ eh_info, 1, &cleanup);
+ eh->table_index = (void *)0;
+ }
else
- handler = old_find_exception_handler (pc, udata->eh_ptr);
-
- /* If we found one, we can stop searching. */
+ if (new_eh_model)
+ handler = find_exception_handler (pc, udata->eh_ptr, eh_info,
+ 0, &cleanup);
+ else
+ handler = old_find_exception_handler (pc, udata->eh_ptr);
+
+ /* If we found one, we can stop searching, if its not a cleanup.
+ for cleanups, we save the state, and keep looking. This allows
+ us to call a debug hook if there are nothing but cleanups left. */
if (handler)
{
- args_size = udata->args_size;
- break;
+ if (cleanup)
+ {
+ if (!saved_state)
+ {
+ saved_ustruct = *udata;
+ handler_p = handler;
+ pc_p = pc;
+ saved_state = 1;
+ only_cleanup = 1;
+ }
+ }
+ else
+ {
+ only_cleanup = 0;
+ break;
+ }
}
/* Otherwise, we continue searching. We subtract 1 from PC to avoid
@@ -3671,13 +3796,24 @@ label:
pc = get_return_addr (udata, sub_udata) - 1;
}
+ if (saved_state)
+ {
+ udata = &saved_ustruct;
+ handler = handler_p;
+ pc = pc_p;
+ if (only_cleanup)
+ __unwinding_cleanup ();
+ }
+
/* If we haven't found a handler by now, this is an unhandled
exception. */
- if (! handler)
- __terminate ();
+ if (! handler)
+ __terminate();
eh->handler_label = handler;
+ args_size = udata->args_size;
+
if (pc == saved_pc)
/* We found a handler in the throw context, no need to unwind. */
udata = my_udata;
@@ -3704,7 +3840,6 @@ label:
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
if (i != udata->retaddr_column && udata->saved[i])
{
-#ifdef INCOMING_REGNO
/* If you modify the saved value of the return address
register on the SPARC, you modify the return address for
your caller's frame. Don't do that here, as it will
@@ -3713,14 +3848,12 @@ label:
&& udata->saved[udata->retaddr_column] == REG_SAVED_REG
&& udata->reg_or_offset[udata->retaddr_column] == i)
continue;
-#endif
copy_reg (i, udata, my_udata);
}
pc = get_return_addr (udata, sub_udata) - 1;
}
-#ifdef INCOMING_REGNO
/* But we do need to update the saved return address register from
the last frame we unwind, or the handler frame will have the wrong
return address. */
@@ -3730,42 +3863,123 @@ label:
if (in_reg_window (i, udata))
copy_reg (i, udata, my_udata);
}
-#endif
}
/* udata now refers to the frame called by the handler frame. */
- /* Emit the stub to adjust sp and jump to the handler. */
- if (new_exception_model)
- retaddr = __builtin_eh_stub ();
- else
- retaddr = __builtin_eh_stub_old ();
-
- /* And then set our return address to point to the stub. */
- if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET)
- put_return_addr (retaddr, my_udata);
- else
- __builtin_set_return_addr_reg (retaddr);
-
- /* Set up the registers we use to communicate with the stub.
- We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack. */
-
- if (new_exception_model)
- __builtin_set_eh_regs ((void *)eh,
+ /* We adjust SP by the difference between __throw's CFA and the CFA for
+ the frame called by the handler frame, because those CFAs correspond
+ to the SP values at the two call sites. We need to further adjust by
+ the args_size of the handler frame itself to get the handler frame's
+ SP from before the args were pushed for that call. */
#ifdef STACK_GROWS_DOWNWARD
- udata->cfa - my_udata->cfa
+ *offset_p = udata->cfa - my_udata->cfa + args_size;
#else
- my_udata->cfa - udata->cfa
+ *offset_p = my_udata->cfa - udata->cfa - args_size;
#endif
- + args_size);
- else
- __builtin_set_eh_regs (handler,
+
+ return handler;
+}
-#ifdef STACK_GROWS_DOWNWARD
- udata->cfa - my_udata->cfa
-#else
- my_udata->cfa - udata->cfa
-#endif
- + args_size);
+
+/* We first search for an exception handler, and if we don't find
+ it, we call __terminate on the current stack frame so that we may
+ use the debugger to walk the stack and understand why no handler
+ was found.
+
+ If we find one, then we unwind the frames down to the one that
+ has the handler and transfer control into the handler. */
+
+/*extern void __throw(void) __attribute__ ((__noreturn__));*/
+
+void
+__throw ()
+{
+ struct eh_context *eh = (*get_eh_context) ();
+ void *pc, *handler;
+ long offset;
+
+ /* XXX maybe make my_ustruct static so we don't have to look it up for
+ each throw. */
+ frame_state my_ustruct, *my_udata = &my_ustruct;
+
+ /* This is required for C++ semantics. We must call terminate if we
+ try and rethrow an exception, when there is no exception currently
+ active. */
+ if (! eh->info)
+ __terminate ();
+
+ /* Start at our stack frame. */
+label:
+ my_udata = __frame_state_for (&&label, my_udata);
+ if (! my_udata)
+ __terminate ();
+
+ /* We need to get the value from the CFA register. */
+ my_udata->cfa = __builtin_dwarf_cfa ();
+
+ /* Do any necessary initialization to access arbitrary stack frames.
+ On the SPARC, this means flushing the register windows. */
+ __builtin_unwind_init ();
+
+ /* Now reset pc to the right throw point. */
+ pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
+
+ handler = throw_helper (eh, pc, my_udata, &offset);
+
+ /* Now go! */
+
+ __builtin_eh_return ((void *)eh, offset, handler);
+
+ /* Epilogue: restore the handler frame's register values and return
+ to the stub. */
+}
+
+/*extern void __rethrow(void *) __attribute__ ((__noreturn__));*/
+
+void
+__rethrow (index)
+ void *index;
+{
+ struct eh_context *eh = (*get_eh_context) ();
+ void *pc, *handler;
+ long offset;
+
+ /* XXX maybe make my_ustruct static so we don't have to look it up for
+ each throw. */
+ frame_state my_ustruct, *my_udata = &my_ustruct;
+
+ /* This is required for C++ semantics. We must call terminate if we
+ try and rethrow an exception, when there is no exception currently
+ active. */
+ if (! eh->info)
+ __terminate ();
+
+ /* This is the table index we want to rethrow from. The value of
+ the END_REGION label is used for the PC of the throw, and the
+ search begins with the next table entry. */
+ eh->table_index = index;
+
+ /* Start at our stack frame. */
+label:
+ my_udata = __frame_state_for (&&label, my_udata);
+ if (! my_udata)
+ __terminate ();
+
+ /* We need to get the value from the CFA register. */
+ my_udata->cfa = __builtin_dwarf_cfa ();
+
+ /* Do any necessary initialization to access arbitrary stack frames.
+ On the SPARC, this means flushing the register windows. */
+ __builtin_unwind_init ();
+
+ /* Now reset pc to the right throw point. */
+ pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
+
+ handler = throw_helper (eh, pc, my_udata, &offset);
+
+ /* Now go! */
+
+ __builtin_eh_return ((void *)eh, offset, handler);
/* Epilogue: restore the handler frame's register values and return
to the stub. */
@@ -3795,6 +4009,6 @@ __pure_virtual ()
#ifndef inhibit_libc
write (2, MESSAGE, sizeof (MESSAGE) - 1);
#endif
- _exit (-1);
+ __terminate ();
}
#endif
diff --git a/contrib/gcc/local-alloc.c b/contrib/gcc/local-alloc.c
index ee2ffe9..d1df595 100644
--- a/contrib/gcc/local-alloc.c
+++ b/contrib/gcc/local-alloc.c
@@ -1,5 +1,5 @@
/* Allocate registers within a basic block, for GNU compiler.
- Copyright (C) 1987, 88, 91, 93-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 93-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -55,8 +55,8 @@ Boston, MA 02111-1307, USA. */
But this is currently disabled since tying in global_alloc is not
yet implemented. */
-/* Pseudos allocated here cannot be reallocated by global.c if the hard
- register is used as a spill register. So we don't allocate such pseudos
+/* Pseudos allocated here can be reallocated by global.c if the hard register
+ is used as a spill register. Currently we don't allocate such pseudos
here if their preferred class is likely to be used by spills. */
#include "config.h"
@@ -156,19 +156,14 @@ static int *qty_n_calls_crossed;
static enum reg_class *qty_alternate_class;
-/* Element Q is the SCRATCH expression for which this quantity is being
- allocated or 0 if this quantity is allocating registers. */
-
-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
- 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. */
+ reg_qty value is Q. This register should be the head of the chain
+ maintained in reg_next_in_qty. */
static int *qty_first_reg;
@@ -227,11 +222,6 @@ static HARD_REG_SET regs_live;
static HARD_REG_SET *regs_live_at;
-int *scratch_block;
-rtx *scratch_list;
-int scratch_list_length;
-static int scratch_index;
-
/* Communicate local vars `insn_number' and `insn'
from `block_alloc' to `reg_is_set', `wipe_dead_reg', and `alloc_qty'. */
static int this_insn_number;
@@ -244,14 +234,20 @@ static rtx this_insn;
static rtx *reg_equiv_replacement;
+/* Used for communication between update_equiv_regs and no_equiv. */
+static rtx *reg_equiv_init_insns;
+
+/* Nonzero if we recorded an equivalence for a LABEL_REF. */
+static int recorded_label_ref;
+
static void alloc_qty PROTO((int, enum machine_mode, int, int));
-static void alloc_qty_for_scratch PROTO((rtx, int, rtx, int, int));
static void validate_equiv_mem_from_store PROTO((rtx, rtx));
static int validate_equiv_mem PROTO((rtx, rtx, rtx));
static int contains_replace_regs PROTO((rtx, char *));
static int memref_referenced_p PROTO((rtx, rtx));
static int memref_used_between_p PROTO((rtx, rtx, rtx));
static void update_equiv_regs PROTO((void));
+static void no_equiv PROTO((rtx, rtx));
static void block_alloc PROTO((int));
static int qty_sugg_compare PROTO((int, int));
static int qty_sugg_compare_1 PROTO((const GENERIC_PTR, const GENERIC_PTR));
@@ -268,7 +264,7 @@ static int find_free_reg PROTO((enum reg_class, enum machine_mode,
static void mark_life PROTO((int, enum machine_mode, int));
static void post_mark_life PROTO((int, enum machine_mode, int, int, int));
static int no_conflict_p PROTO((rtx, rtx, rtx));
-static int requires_inout PROTO((char *));
+static int requires_inout PROTO((const char *));
/* Allocate a new quantity (new within current basic block)
for register number REGNO which is born at index BIRTH
@@ -297,104 +293,18 @@ alloc_qty (regno, mode, size, birth)
qty_changes_size[qty] = REG_CHANGES_SIZE (regno);
}
-/* Similar to `alloc_qty', but allocates a quantity for a SCRATCH rtx
- used as operand N in INSN. We assume here that the SCRATCH is used in
- a CLOBBER. */
-
-static void
-alloc_qty_for_scratch (scratch, n, insn, insn_code_num, insn_number)
- rtx scratch;
- int n;
- rtx insn;
- int insn_code_num, insn_number;
-{
- register int qty;
- enum reg_class class;
- char *p, c;
- int i;
-
-#ifdef REGISTER_CONSTRAINTS
- /* If we haven't yet computed which alternative will be used, do so now.
- Then set P to the constraints for that alternative. */
- if (which_alternative == -1)
- if (! constrain_operands (insn_code_num, 0))
- return;
-
- for (p = insn_operand_constraint[insn_code_num][n], i = 0;
- *p && i < which_alternative; p++)
- if (*p == ',')
- i++;
-
- /* Compute the class required for this SCRATCH. If we don't need a
- register, the class will remain NO_REGS. If we guessed the alternative
- number incorrectly, reload will fix things up for us. */
-
- class = NO_REGS;
- while ((c = *p++) != '\0' && c != ',')
- switch (c)
- {
- case '=': case '+': case '?':
- case '#': case '&': case '!':
- case '*': case '%':
- case '0': case '1': case '2': case '3': case '4':
- case 'm': case '<': case '>': case 'V': case 'o':
- case 'E': case 'F': case 'G': case 'H':
- case 's': case 'i': case 'n':
- case 'I': case 'J': case 'K': case 'L':
- case 'M': case 'N': case 'O': case 'P':
-#ifdef EXTRA_CONSTRAINT
- case 'Q': case 'R': case 'S': case 'T': case 'U':
-#endif
- case 'p':
- /* These don't say anything we care about. */
- break;
-
- case 'X':
- /* We don't need to allocate this SCRATCH. */
- return;
-
- case 'g': case 'r':
- class = reg_class_subunion[(int) class][(int) GENERAL_REGS];
- break;
-
- default:
- class
- = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER (c)];
- break;
- }
-
- if (class == NO_REGS)
- return;
-
-#else /* REGISTER_CONSTRAINTS */
-
- class = GENERAL_REGS;
-#endif
-
-
- qty = next_qty++;
-
- qty_first_reg[qty] = -1;
- qty_scratch_rtx[qty] = scratch;
- qty_size[qty] = GET_MODE_SIZE (GET_MODE (scratch));
- qty_mode[qty] = GET_MODE (scratch);
- qty_birth[qty] = 2 * insn_number - 1;
- qty_death[qty] = 2 * insn_number + 1;
- qty_n_calls_crossed[qty] = 0;
- qty_min_class[qty] = class;
- qty_alternate_class[qty] = NO_REGS;
- qty_n_refs[qty] = 1;
- qty_changes_size[qty] = 0;
-}
-
/* Main entry point of this file. */
-void
+int
local_alloc ()
{
register int b, i;
int max_qty;
+ /* We need to keep track of whether or not we recorded a LABEL_REF so
+ that we know if the jump optimizer needs to be rerun. */
+ recorded_label_ref = 0;
+
/* Leaf functions and non-leaf functions have different needs.
If defined, let the machine say what kind of ordering we
should use. */
@@ -407,26 +317,13 @@ local_alloc ()
update_equiv_regs ();
/* This sets the maximum number of quantities we can have. Quantity
- numbers start at zero and we can have one for each pseudo plus the
- number of SCRATCHes in the largest block, in the worst case. */
- max_qty = (max_regno - FIRST_PSEUDO_REGISTER) + max_scratch;
+ numbers start at zero and we can have one for each pseudo. */
+ max_qty = (max_regno - FIRST_PSEUDO_REGISTER);
/* Allocate vectors of temporary data.
See the declarations of these variables, above,
for what they mean. */
- /* There can be up to MAX_SCRATCH * N_BASIC_BLOCKS SCRATCHes to allocate.
- Instead of allocating this much memory from now until the end of
- reload, only allocate space for MAX_QTY SCRATCHes. If there are more
- reload will allocate them. */
-
- scratch_list_length = max_qty;
- scratch_list = (rtx *) xmalloc (scratch_list_length * sizeof (rtx));
- bzero ((char *) scratch_list, scratch_list_length * sizeof (rtx));
- scratch_block = (int *) xmalloc (scratch_list_length * sizeof (int));
- bzero ((char *) scratch_block, scratch_list_length * sizeof (int));
- scratch_index = 0;
-
qty_phys_reg = (short *) alloca (max_qty * sizeof (short));
qty_phys_copy_sugg
= (HARD_REG_SET *) alloca (max_qty * sizeof (HARD_REG_SET));
@@ -435,7 +332,6 @@ local_alloc ()
qty_phys_num_sugg = (short *) alloca (max_qty * sizeof (short));
qty_birth = (int *) alloca (max_qty * sizeof (int));
qty_death = (int *) alloca (max_qty * sizeof (int));
- qty_scratch_rtx = (rtx *) alloca (max_qty * sizeof (rtx));
qty_first_reg = (int *) alloca (max_qty * sizeof (int));
qty_size = (int *) alloca (max_qty * sizeof (int));
qty_mode
@@ -493,7 +389,6 @@ local_alloc ()
{
for (i = 0; i < next_qty; i++)
{
- qty_scratch_rtx[i] = 0;
CLEAR_HARD_REG_SET (qty_phys_copy_sugg[i]);
qty_phys_num_copy_sugg[i] = 0;
CLEAR_HARD_REG_SET (qty_phys_sugg[i]);
@@ -505,7 +400,6 @@ local_alloc ()
#define CLEAR(vector) \
bzero ((char *) (vector), (sizeof (*(vector))) * next_qty);
- CLEAR (qty_scratch_rtx);
CLEAR (qty_phys_copy_sugg);
CLEAR (qty_phys_num_copy_sugg);
CLEAR (qty_phys_sugg);
@@ -523,6 +417,7 @@ local_alloc ()
free (reg_qty);
free (reg_offset);
free (reg_next_in_qty);
+ return recorded_label_ref;
}
/* Depth of loops we are in while in update_equiv_regs. */
@@ -541,7 +436,7 @@ static int equiv_mem_modified;
static void
validate_equiv_mem_from_store (dest, set)
rtx dest;
- rtx set;
+ rtx set ATTRIBUTE_UNUSED;
{
if ((GET_CODE (dest) == REG
&& reg_overlap_mentioned_p (dest, equiv_mem))
@@ -743,6 +638,22 @@ memref_used_between_p (memref, start, end)
return 0;
}
+/* Return nonzero if the rtx X is invariant over the current function. */
+int
+function_invariant_p (x)
+ rtx x;
+{
+ if (CONSTANT_P (x))
+ return 1;
+ if (x == frame_pointer_rtx || x == arg_pointer_rtx)
+ return 1;
+ if (GET_CODE (x) == PLUS
+ && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
+ && CONSTANT_P (XEXP (x, 1)))
+ return 1;
+ return 0;
+}
+
/* Find registers that are equivalent to a single value throughout the
compilation (either because they can be referenced in memory or are set once
from a single constant). Lower their priority for a register.
@@ -754,7 +665,6 @@ memref_used_between_p (memref, start, end)
static void
update_equiv_regs ()
{
- rtx *reg_equiv_init_insn = (rtx *) alloca (max_regno * sizeof (rtx *));
/* Set when an attempt should be made to replace a register with the
associated reg_equiv_replacement entry at the end of this function. */
char *reg_equiv_replace
@@ -762,10 +672,11 @@ update_equiv_regs ()
rtx insn;
int block, depth;
- reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
+ reg_equiv_init_insns = (rtx *) alloca (max_regno * sizeof (rtx));
+ reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx));
- bzero ((char *) reg_equiv_init_insn, max_regno * sizeof (rtx *));
- bzero ((char *) reg_equiv_replacement, max_regno * sizeof (rtx *));
+ bzero ((char *) reg_equiv_init_insns, max_regno * sizeof (rtx));
+ bzero ((char *) reg_equiv_replacement, max_regno * sizeof (rtx));
bzero ((char *) reg_equiv_replace, max_regno * sizeof *reg_equiv_replace);
init_alias_analysis ();
@@ -778,7 +689,7 @@ update_equiv_regs ()
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx note;
- rtx set = single_set (insn);
+ rtx set;
rtx dest, src;
int regno;
@@ -790,10 +701,34 @@ update_equiv_regs ()
loop_depth--;
}
- /* If this insn contains more (or less) than a single SET, ignore it. */
- if (set == 0)
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
continue;
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_INC)
+ no_equiv (XEXP (note, 0), note);
+
+ set = single_set (insn);
+
+ /* If this insn contains more (or less) than a single SET,
+ only mark all destinations as having no known equivalence. */
+ if (set == 0)
+ {
+ note_stores (PATTERN (insn), no_equiv);
+ continue;
+ }
+ else if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ {
+ int i;
+
+ for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+ {
+ rtx part = XVECEXP (PATTERN (insn), 0, i);
+ if (part != set)
+ note_stores (part, no_equiv);
+ }
+ }
+
dest = SET_DEST (set);
src = SET_SRC (set);
@@ -809,60 +744,83 @@ update_equiv_regs ()
If one of the regs in the address is marked as reg_equiv_replace,
then we can't add this REG_EQUIV note. The reg_equiv_replace
optimization may move the set of this register immediately before
- insn, which puts it after reg_equiv_init_insn[regno], and hence
+ insn, which puts it after reg_equiv_init_insns[regno], and hence
the mention in the REG_EQUIV note would be to an uninitialized
pseudo. */
-
- if (GET_CODE (dest) == MEM && GET_CODE (SET_SRC (set)) == REG
- && (regno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER
+ /* ????? This test isn't good enough; we might see a MEM with a use of
+ a pseudo register before we see its setting insn that will cause
+ reg_equiv_replace for that pseudo to be set.
+ Equivalences to MEMs should be made in another pass, after the
+ reg_equiv_replace information has been gathered. */
+
+ if (GET_CODE (dest) == MEM && GET_CODE (src) == REG
+ && (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
&& REG_BASIC_BLOCK (regno) >= 0
- && reg_equiv_init_insn[regno] != 0
+ && REG_N_SETS (regno) == 1
+ && reg_equiv_init_insns[regno] != 0
+ && reg_equiv_init_insns[regno] != const0_rtx
&& ! find_reg_note (insn, REG_EQUIV, NULL_RTX)
- && ! contains_replace_regs (XEXP (dest, 0), reg_equiv_replace)
- && validate_equiv_mem (reg_equiv_init_insn[regno], SET_SRC (set),
- dest)
- && ! memref_used_between_p (SET_DEST (set),
- reg_equiv_init_insn[regno], insn))
- REG_NOTES (reg_equiv_init_insn[regno])
- = gen_rtx_EXPR_LIST (REG_EQUIV, dest,
- REG_NOTES (reg_equiv_init_insn[regno]));
+ && ! contains_replace_regs (XEXP (dest, 0), reg_equiv_replace))
+ {
+ rtx init_insn = XEXP (reg_equiv_init_insns[regno], 0);
+ if (validate_equiv_mem (init_insn, src, dest)
+ && ! memref_used_between_p (dest, init_insn, insn))
+ REG_NOTES (init_insn)
+ = gen_rtx_EXPR_LIST (REG_EQUIV, dest, REG_NOTES (init_insn));
+ }
/* We only handle the case of a pseudo register being set
- once and only if neither the source nor the destination are
- in a register class that's likely to be spilled. */
+ once, or always to the same value. */
+ /* ??? The mn10200 port breaks if we add equivalences for
+ values that need an ADDRESS_REGS register and set them equivalent
+ to a MEM of a pseudo. The actual problem is in the over-conservative
+ handling of INPADDR_ADDRESS / INPUT_ADDRESS / INPUT triples in
+ calculate_needs, but we traditionally work around this problem
+ here by rejecting equivalences when the destination is in a register
+ that's likely spilled. This is fragile, of course, since the
+ preferred class of a pseudo depends on all instructions that set
+ or use it. */
+
if (GET_CODE (dest) != REG
|| (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
- || REG_N_SETS (regno) != 1
- || CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (dest)))
- || (GET_CODE (src) == REG
- && REGNO (src) >= FIRST_PSEUDO_REGISTER
- && CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (src)))))
- continue;
+ || reg_equiv_init_insns[regno] == const0_rtx
+ || (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
+ && GET_CODE (src) == MEM))
+ {
+ /* This might be seting a SUBREG of a pseudo, a pseudo that is
+ also set somewhere else to a constant. */
+ note_stores (set, no_equiv);
+ continue;
+ }
+ /* Don't handle the equivalence if the source is in a register
+ class that's likely to be spilled. */
+ if (GET_CODE (src) == REG
+ && REGNO (src) >= FIRST_PSEUDO_REGISTER
+ && CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (src))))
+ {
+ no_equiv (dest, set);
+ continue;
+ }
note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-#ifdef DONT_RECORD_EQUIVALENCE
- /* Allow the target to reject promotions of some REG_EQUAL notes to
- REG_EQUIV notes.
-
- In some cases this can improve register allocation if the existence
- of the REG_EQUIV note is likely to increase the lifetime of a register
- that is likely to be spilled.
-
- It may also be necessary if the target can't handle certain constant
- expressions appearing randomly in insns, but for whatever reason
- those expressions must be considered legitimate constant expressions
- to prevent them from being forced into memory. */
- if (note && DONT_RECORD_EQUIVALENCE (note))
- note = NULL;
-#endif
-
+ if (REG_N_SETS (regno) != 1
+ && (! note
+ || ! function_invariant_p (XEXP (note, 0))
+ || (reg_equiv_replacement[regno]
+ && ! rtx_equal_p (XEXP (note, 0),
+ reg_equiv_replacement[regno]))))
+ {
+ no_equiv (dest, set);
+ continue;
+ }
/* Record this insn as initializing this register. */
- reg_equiv_init_insn[regno] = insn;
+ reg_equiv_init_insns[regno]
+ = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init_insns[regno]);
/* If this register is known to be equal to a constant, record that
it is always equivalent to the constant. */
- if (note && CONSTANT_P (XEXP (note, 0)))
+ if (note && function_invariant_p (XEXP (note, 0)))
PUT_MODE (note, (enum machine_mode) REG_EQUIV);
/* If this insn introduces a "constant" register, decrease the priority
@@ -892,6 +850,19 @@ update_equiv_regs ()
{
int regno = REGNO (dest);
+ /* Record whether or not we created a REG_EQUIV note for a LABEL_REF.
+ We might end up substituting the LABEL_REF for uses of the
+ pseudo here or later. That kind of transformation may turn an
+ indirect jump into a direct jump, in which case we must rerun the
+ jump optimizer to ensure that the JUMP_LABEL fields are valid. */
+ if (GET_CODE (XEXP (note, 0)) == LABEL_REF
+ || (GET_CODE (XEXP (note, 0)) == CONST
+ && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
+ && (GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0))
+ == LABEL_REF)))
+ recorded_label_ref = 1;
+
+
reg_equiv_replacement[regno] = XEXP (note, 0);
/* Don't mess with things live during setjmp. */
@@ -938,7 +909,7 @@ update_equiv_regs ()
/* Keep track of which basic block we are in. */
if (block + 1 < n_basic_blocks
- && basic_block_head[block + 1] == insn)
+ && BLOCK_HEAD (block + 1) == insn)
++block;
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
@@ -970,7 +941,12 @@ update_equiv_regs ()
if (! reg_equiv_replace[regno])
continue;
- equiv_insn = reg_equiv_init_insn[regno];
+ /* reg_equiv_replace[REGNO] gets set only when
+ REG_N_REFS[REGNO] is 2, i.e. the register is set
+ once and used once. (If it were only set, but not used,
+ flow would have deleted the setting insns.) Hence
+ there can only be one insn in reg_equiv_init_insns. */
+ equiv_insn = XEXP (reg_equiv_init_insns[regno], 0);
if (validate_replace_rtx (regno_reg_rtx[regno],
reg_equiv_replacement[regno], insn))
@@ -1007,16 +983,46 @@ update_equiv_regs ()
REG_N_CALLS_CROSSED (regno) = 0;
REG_LIVE_LENGTH (regno) = 2;
- if (block >= 0 && insn == basic_block_head[block])
- basic_block_head[block] = PREV_INSN (insn);
+ if (block >= 0 && insn == BLOCK_HEAD (block))
+ BLOCK_HEAD (block) = PREV_INSN (insn);
for (l = 0; l < n_basic_blocks; l++)
- CLEAR_REGNO_REG_SET (basic_block_live_at_start[l], regno);
+ CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_start,
+ regno);
}
}
}
}
}
+
+/* Mark REG as having no known equivalence.
+ Some instructions might have been proceessed before and furnished
+ with REG_EQUIV notes for this register; these notes will have to be
+ removed.
+ STORE is the piece of RTL that does the non-constant / conflicting
+ assignment - a SET, CLOBBER or REG_INC note. It is currently not used,
+ but needs to be there because this function is called from note_stores. */
+static void
+no_equiv (reg, store)
+ rtx reg, store ATTRIBUTE_UNUSED;
+{
+ int regno;
+ rtx list;
+
+ if (GET_CODE (reg) != REG)
+ return;
+ regno = REGNO (reg);
+ list = reg_equiv_init_insns[regno];
+ if (list == const0_rtx)
+ return;
+ for (; list; list = XEXP (list, 1))
+ {
+ rtx insn = XEXP (list, 0);
+ remove_note (insn, find_reg_note (insn, REG_EQUIV, NULL_RTX));
+ }
+ reg_equiv_init_insns[regno] = const0_rtx;
+ reg_equiv_replacement[regno] = NULL_RTX;
+}
/* Allocate hard regs to the pseudo regs used only within block number B.
Only the pseudos that die but once can be handled. */
@@ -1033,19 +1039,16 @@ block_alloc (b)
int max_uid = get_max_uid ();
int *qty_order;
int no_conflict_combined_regno = -1;
- /* Counter to prevent allocating more SCRATCHes than can be stored
- in SCRATCH_LIST. */
- int scratches_allocated = scratch_index;
/* Count the instructions in the basic block. */
- insn = basic_block_end[b];
+ insn = BLOCK_END (b);
while (1)
{
if (GET_CODE (insn) != NOTE)
if (++insn_count > max_uid)
abort ();
- if (insn == basic_block_head[b])
+ if (insn == BLOCK_HEAD (b))
break;
insn = PREV_INSN (insn);
}
@@ -1058,13 +1061,13 @@ block_alloc (b)
/* Initialize table of hardware registers currently live. */
- REG_SET_TO_HARD_REG_SET (regs_live, basic_block_live_at_start[b]);
+ REG_SET_TO_HARD_REG_SET (regs_live, BASIC_BLOCK (b)->global_live_at_start);
/* This loop scans the instructions of the basic block
and assigns quantities to registers.
It computes which registers to tie. */
- insn = basic_block_head[b];
+ insn = BLOCK_HEAD (b);
while (1)
{
register rtx body = PATTERN (insn);
@@ -1079,13 +1082,11 @@ block_alloc (b)
register rtx r0, r1;
int combined_regno = -1;
int i;
- int insn_code_number = recog_memoized (insn);
this_insn_number = insn_number;
this_insn = insn;
- if (insn_code_number >= 0)
- insn_extract (insn);
+ extract_insn (insn);
which_alternative = -1;
/* Is this insn suitable for tying two registers?
@@ -1106,11 +1107,11 @@ block_alloc (b)
If tying is done, WIN is set nonzero. */
- if (insn_code_number >= 0
+ if (1
#ifdef REGISTER_CONSTRAINTS
- && insn_n_operands[insn_code_number] > 1
- && insn_operand_constraint[insn_code_number][0][0] == '='
- && insn_operand_constraint[insn_code_number][0][1] != '&'
+ && recog_n_operands > 1
+ && recog_constraints[0][0] == '='
+ && recog_constraints[0][1] != '&'
#else
&& GET_CODE (PATTERN (insn)) == SET
&& rtx_equal_p (SET_DEST (PATTERN (insn)), recog_operand[0])
@@ -1124,19 +1125,19 @@ block_alloc (b)
operand 0. */
int n_matching_alts = 0;
- for (i = 1; i < insn_n_operands[insn_code_number]; i++)
+ for (i = 1; i < recog_n_operands; i++)
{
- char *p = insn_operand_constraint[insn_code_number][i];
+ const char *p = recog_constraints[i];
int this_match = (requires_inout (p));
n_matching_alts += this_match;
- if (this_match == insn_n_alternatives[insn_code_number])
+ if (this_match == recog_n_alternatives)
must_match_0 = i;
}
#endif
r0 = recog_operand[0];
- for (i = 1; i < insn_n_operands[insn_code_number]; i++)
+ for (i = 1; i < recog_n_operands; i++)
{
#ifdef REGISTER_CONSTRAINTS
/* Skip this operand if we found an operand that
@@ -1145,9 +1146,9 @@ block_alloc (b)
if (must_match_0 >= 0 && i != must_match_0
&& ! (i == must_match_0 + 1
- && insn_operand_constraint[insn_code_number][i-1][0] == '%')
+ && recog_constraints[i-1][0] == '%')
&& ! (i == must_match_0 - 1
- && insn_operand_constraint[insn_code_number][i][0] == '%'))
+ && recog_constraints[i][0] == '%'))
continue;
/* Likewise if each alternative has some operand that
@@ -1155,9 +1156,8 @@ block_alloc (b)
operand that doesn't list operand 0 since we know that
the operand always conflicts with operand 0. We
ignore commutatity in this case to keep things simple. */
- if (n_matching_alts == insn_n_alternatives[insn_code_number]
- && (0 == requires_inout
- (insn_operand_constraint[insn_code_number][i])))
+ if (n_matching_alts == recog_n_alternatives
+ && 0 == requires_inout (recog_constraints[i]))
continue;
#endif
@@ -1168,9 +1168,9 @@ block_alloc (b)
of them. */
if (
#ifdef REGISTER_CONSTRAINTS
- insn_operand_constraint[insn_code_number][i][0] == 'p'
+ recog_constraints[i][0] == 'p'
#else
- insn_operand_address_p[insn_code_number][i]
+ recog_operand_address_p[i]
#endif
)
while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
@@ -1289,15 +1289,6 @@ block_alloc (b)
&& GET_CODE (XEXP (link, 0)) == REG)
wipe_dead_reg (XEXP (link, 0), 1);
- /* Allocate quantities for any SCRATCH operands of this insn. */
-
- if (insn_code_number >= 0)
- for (i = 0; i < insn_n_operands[insn_code_number]; i++)
- if (GET_CODE (recog_operand[i]) == SCRATCH
- && scratches_allocated++ < scratch_list_length)
- alloc_qty_for_scratch (recog_operand[i], i, insn,
- insn_code_number, insn_number);
-
/* If this is an insn that has a REG_RETVAL note pointing at a
CLOBBER insn, we have reached the end of a REG_NO_CONFLICT
block, so clear any register number that combined within it. */
@@ -1314,7 +1305,7 @@ block_alloc (b)
IOR_HARD_REG_SET (regs_live_at[2 * insn_number], regs_live);
IOR_HARD_REG_SET (regs_live_at[2 * insn_number + 1], regs_live);
- if (insn == basic_block_end[b])
+ if (insn == BLOCK_END (b))
break;
insn = NEXT_INSN (insn);
@@ -1429,8 +1420,8 @@ block_alloc (b)
discourage the register allocator from creating false
dependencies.
- The adjustment by the value +-3 indicates precisely that
- this qty conflicts with qtys in the instructions immediately
+ The adjustment value is choosen to indicate that this qty
+ conflicts with all the qtys in the instructions immediately
before and after the lifetime of this qty.
Experiments have shown that higher values tend to hurt
@@ -1438,8 +1429,9 @@ block_alloc (b)
If allocation using the extended lifetime fails we will try
again with the qty's unadjusted lifetime. */
- int fake_birth = MAX (0, qty_birth[q] - 3);
- int fake_death = MIN (insn_number * 2 + 1, qty_death[q] + 3);
+ int fake_birth = MAX (0, qty_birth[q] - 2 + qty_birth[q] % 2);
+ int fake_death = MIN (insn_number * 2 + 1,
+ qty_death[q] + 2 - qty_death[q] % 2);
#endif
if (N_REG_CLASSES > 1)
@@ -1496,16 +1488,6 @@ block_alloc (b)
{
for (i = qty_first_reg[q]; i >= 0; i = reg_next_in_qty[i])
reg_renumber[i] = qty_phys_reg[q] + reg_offset[i];
- if (qty_scratch_rtx[q])
- {
- if (GET_CODE (qty_scratch_rtx[q]) == REG)
- abort ();
- qty_scratch_rtx[q] = gen_rtx_REG (GET_MODE (qty_scratch_rtx[q]),
- qty_phys_reg[q]);
- scratch_block[scratch_index] = b;
- scratch_list[scratch_index++] = qty_scratch_rtx[q];
-
- }
}
}
@@ -1687,6 +1669,11 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
|| ureg == sreg
/* Don't try to connect two different hardware registers. */
|| (ureg < FIRST_PSEUDO_REGISTER && sreg < FIRST_PSEUDO_REGISTER)
+ /* Don't use a hard reg that might be spilled. */
+ || (ureg < FIRST_PSEUDO_REGISTER
+ && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (ureg)))
+ || (sreg < FIRST_PSEUDO_REGISTER
+ && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (sreg)))
/* Don't connect two different machine modes if they have different
implications as to which registers may be used. */
|| !MODES_TIEABLE_P (GET_MODE (usedreg), GET_MODE (setreg)))
@@ -1900,9 +1887,16 @@ wipe_dead_reg (reg, output_p)
/* If this insn has multiple results,
and the dead reg is used in one of the results,
extend its life to after this insn,
- so it won't get allocated together with any other result of this insn. */
+ so it won't get allocated together with any other result of this insn.
+
+ It is unsafe to use !single_set here since it will ignore an unused
+ output. Just because an output is unused does not mean the compiler
+ can assume the side effect will not occur. Consider if REG appears
+ in the address of an output and we reload the output. If we allocate
+ REG to the same hard register as an unused output we could set the hard
+ register before the output reload insn. */
if (GET_CODE (PATTERN (this_insn)) == PARALLEL
- && !single_set (this_insn))
+ && multiple_sets (this_insn))
{
int i;
for (i = XVECLEN (PATTERN (this_insn), 0) - 1; i >= 0; i--)
@@ -2001,7 +1995,7 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
This is true of any register that can be eliminated. */
#ifdef ELIMINABLE_REGS
- for (i = 0; i < sizeof eliminables / sizeof eliminables[0]; i++)
+ for (i = 0; i < (int)(sizeof eliminables / sizeof eliminables[0]); i++)
SET_HARD_REG_BIT (used, eliminables[i].from);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If FRAME_POINTER_REGNUM is not a real register, then protect the one
@@ -2047,7 +2041,10 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
int regno = i;
#endif
if (! TEST_HARD_REG_BIT (first_used, regno)
- && HARD_REGNO_MODE_OK (regno, mode))
+ && HARD_REGNO_MODE_OK (regno, mode)
+ && (qty_n_calls_crossed[qty] == 0
+ || accept_call_clobbered
+ || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
{
register int j;
register int size1 = HARD_REGNO_NREGS (regno, mode);
@@ -2207,7 +2204,7 @@ no_conflict_p (insn, r0, r1)
static int
requires_inout (p)
- char *p;
+ const char *p;
{
char c;
int found_zero = 0;
diff --git a/contrib/gcc/longlong.h b/contrib/gcc/longlong.h
index f86f894..d1859ef 100644
--- a/contrib/gcc/longlong.h
+++ b/contrib/gcc/longlong.h
@@ -1,5 +1,5 @@
/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
- Copyright (C) 1991, 92, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1991, 92, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc.
This definition file is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
@@ -978,9 +978,11 @@ UDItype __umulsidi3 (USItype, USItype);
: "%g1" __AND_CLOBBER_CC)
#define UDIV_TIME 37
#define count_leading_zeros(count, x) \
- __asm__ ("scan %1,0,%0" \
- : "=r" ((USItype) (x)) \
- : "r" ((USItype) (count)))
+ do { \
+ __asm__ ("scan %1,1,%0" \
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x))); \
+ } while (0)
#else
/* SPARC without integer multiplication and divide instructions.
(i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
diff --git a/contrib/gcc/loop.c b/contrib/gcc/loop.c
index 04c8083..7acd727 100644
--- a/contrib/gcc/loop.c
+++ b/contrib/gcc/loop.c
@@ -1,5 +1,5 @@
/* Perform various loop optimizations, including strength reduction.
- Copyright (C) 1987, 88, 89, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -78,38 +78,25 @@ static int max_loop_num;
static rtx *loop_number_loop_starts, *loop_number_loop_ends;
-/* For each loop, gives the containing loop number, -1 if none. */
+/* Likewise for the continue insn */
+static rtx *loop_number_loop_cont;
-int *loop_outer_loop;
+/* The first code_label that is reached in every loop iteration.
+ 0 when not computed yet, initially const0_rtx if a jump couldn't be
+ followed.
+ Also set to 0 when there is no such label before the NOTE_INSN_LOOP_CONT
+ of this loop, or in verify_dominator, if a jump couldn't be followed. */
+static rtx *loop_number_cont_dominator;
-#ifdef HAIFA
-/* The main output of analyze_loop_iterations is placed here */
+/* For each loop, gives the containing loop number, -1 if none. */
-int *loop_can_insert_bct;
+int *loop_outer_loop;
-/* For each loop, determines whether some of its inner loops has used
- count register */
+#ifdef HAVE_decrement_and_branch_on_count
+/* Records whether resource in use by inner loop. */
int *loop_used_count_register;
-
-/* loop parameters for arithmetic loops. These loops have a loop variable
- which is initialized to loop_start_value, incremented in each iteration
- by "loop_increment". At the end of the iteration the loop variable is
- compared to the loop_comparison_value (using loop_comparison_code). */
-
-rtx *loop_increment;
-rtx *loop_comparison_value;
-rtx *loop_start_value;
-enum rtx_code *loop_comparison_code;
-#endif /* HAIFA */
-
-/* For each loop, keep track of its unrolling factor.
- Potential values:
- 0: unrolled
- 1: not unrolled.
- -1: completely unrolled
- >0: holds the unroll exact factor. */
-int *loop_unroll_factor;
+#endif /* HAVE_decrement_and_branch_on_count */
/* Indexed by loop number, contains a nonzero value if the "loop" isn't
really a loop (an insn outside the loop branches into it). */
@@ -133,14 +120,6 @@ rtx *loop_number_exit_labels;
int *loop_number_exit_count;
-/* Holds the number of loop iterations. It is zero if the number could not be
- calculated. Must be unsigned since the number of iterations can
- be as high as 2^wordsize-1. For loops with a wider iterator, this number
- will be zero if the number of loop iterations is too large for an
- unsigned integer to hold. */
-
-unsigned HOST_WIDE_INT loop_n_iterations;
-
/* Nonzero if there is a subroutine call in the current loop. */
static int loop_has_call;
@@ -150,6 +129,10 @@ static int loop_has_call;
static int loop_has_volatile;
+/* Nonzero if there is a tablejump in the current loop. */
+
+static int loop_has_tablejump;
+
/* Added loop_continue which is the NOTE_INSN_LOOP_CONT of the
current loop. A continue statement will generate a branch to
NEXT_INSN (loop_continue). */
@@ -168,36 +151,57 @@ static rtx loop_continue;
Therefore, at all times, == 0 indicates an invariant register;
< 0 a conditionally invariant one. */
-static int *n_times_set;
+static varray_type set_in_loop;
-/* Original value of n_times_set; same except that this value
+/* Original value of set_in_loop; same except that this value
is not set negative for a reg whose sets have been made candidates
and not set to 0 for a reg that is moved. */
-static int *n_times_used;
+static varray_type n_times_set;
/* Index by register number, 1 indicates that the register
cannot be moved or strength reduced. */
-static char *may_not_optimize;
+static varray_type may_not_optimize;
+
+/* Contains the insn in which a register was used if it was used
+ exactly once; contains const0_rtx if it was used more than once. */
+
+static varray_type reg_single_usage;
/* Nonzero means reg N has already been moved out of one loop.
This reduces the desire to move it out of another. */
static char *moved_once;
-/* Array of MEMs that are stored in this loop. If there are too many to fit
- here, we just turn on unknown_address_altered. */
+/* List of MEMs that are stored in this loop. */
-#define NUM_STORES 30
-static rtx loop_store_mems[NUM_STORES];
-
-/* Index of first available slot in above array. */
-static int loop_store_mems_idx;
+static rtx loop_store_mems;
/* The insn where the first of these was found. */
static rtx first_loop_store_insn;
+typedef struct loop_mem_info {
+ rtx mem; /* The MEM itself. */
+ rtx reg; /* Corresponding pseudo, if any. */
+ int optimize; /* Nonzero if we can optimize access to this MEM. */
+} loop_mem_info;
+
+/* Array of MEMs that are used (read or written) in this loop, but
+ cannot be aliased by anything in this loop, except perhaps
+ themselves. In other words, if loop_mems[i] is altered during the
+ loop, it is altered by an expression that is rtx_equal_p to it. */
+
+static loop_mem_info *loop_mems;
+
+/* The index of the next available slot in LOOP_MEMS. */
+
+static int loop_mems_idx;
+
+/* The number of elements allocated in LOOP_MEMs. */
+
+static int loop_mems_allocated;
+
/* Nonzero if we don't know what MEMs were changed in the current loop.
This happens if the loop contains a call (in which case `loop_has_call'
will also be set) or if we store into more than NUM_STORES MEMs. */
@@ -275,21 +279,26 @@ struct movable
struct movable *next;
};
+static struct movable *the_movables;
+
FILE *loop_dump_stream;
/* Forward declarations. */
+static void verify_dominator PROTO((int));
static void find_and_verify_loops PROTO((rtx));
static void mark_loop_jump PROTO((rtx, int));
static void prescan_loop PROTO((rtx, rtx));
static int reg_in_basic_block_p PROTO((rtx, rtx));
static int consec_sets_invariant_p PROTO((rtx, int, rtx));
-static rtx libcall_other_reg PROTO((rtx, rtx));
static int labels_in_range_p PROTO((rtx, int));
-static void count_loop_regs_set PROTO((rtx, rtx, char *, rtx *, int *, int));
+static void count_one_set PROTO((rtx, rtx, varray_type, rtx *));
+
+static void count_loop_regs_set PROTO((rtx, rtx, varray_type, varray_type,
+ int *, int));
static void note_addr_stored PROTO((rtx, rtx));
static int loop_reg_used_before_p PROTO((rtx, rtx, rtx, rtx, rtx));
-static void scan_loop PROTO((rtx, rtx, int, int));
+static void scan_loop PROTO((rtx, rtx, rtx, int, int));
#if 0
static void replace_call_address PROTO((rtx, rtx, rtx));
#endif
@@ -303,64 +312,87 @@ static int rtx_equal_for_loop_p PROTO((rtx, rtx, struct movable *));
static void add_label_notes PROTO((rtx, rtx));
static void move_movables PROTO((struct movable *, int, int, rtx, rtx, int));
static int count_nonfixed_reads PROTO((rtx));
-static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx, int));
-static void find_single_use_in_loop PROTO((rtx, rtx, rtx *));
+static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx, rtx, int, int));
+static void find_single_use_in_loop PROTO((rtx, rtx, varray_type));
static int valid_initial_value_p PROTO((rtx, rtx, int, rtx));
static void find_mem_givs PROTO((rtx, rtx, int, rtx, rtx));
-static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, int, int));
-static void check_final_value PROTO((struct induction *, rtx, rtx));
+static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx *, int, int));
+static void check_final_value PROTO((struct induction *, rtx, rtx,
+ unsigned HOST_WIDE_INT));
static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, rtx *, rtx, rtx));
static void update_giv_derive PROTO((rtx));
-static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *));
+static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *, rtx **));
static rtx simplify_giv_expr PROTO((rtx, int *));
-static int general_induction_var PROTO((rtx, rtx *, rtx *, rtx *));
-static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *));
-static int check_dbra_loop PROTO((rtx, int, rtx));
-#ifdef ADDRESS_COST
-static rtx express_from PROTO((struct induction *, struct induction *));
-#endif
-static int combine_givs_p PROTO((struct induction *, struct induction *));
-#ifdef GIV_SORT_CRITERION
-static int giv_sort PROTO((struct induction **, struct induction **));
-#endif
+static int general_induction_var PROTO((rtx, rtx *, rtx *, rtx *, int, int *));
+static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *));
+static int check_dbra_loop PROTO((rtx, int, rtx, struct loop_info *));
+static rtx express_from_1 PROTO((rtx, rtx, rtx));
+static rtx combine_givs_p PROTO((struct induction *, struct induction *));
static void combine_givs PROTO((struct iv_class *));
+struct recombine_givs_stats;
+static int find_life_end PROTO((rtx, struct recombine_givs_stats *, rtx, rtx));
+static void recombine_givs PROTO((struct iv_class *, rtx, rtx, int));
static int product_cheap_p PROTO((rtx, rtx));
static int maybe_eliminate_biv PROTO((struct iv_class *, rtx, rtx, int, int, int));
static int maybe_eliminate_biv_1 PROTO((rtx, rtx, struct iv_class *, int, rtx));
static int last_use_this_basic_block PROTO((rtx, rtx));
static void record_initial PROTO((rtx, rtx));
static void update_reg_last_use PROTO((rtx, rtx));
+static rtx next_insn_in_loop PROTO((rtx, rtx, rtx, rtx));
+static void load_mems_and_recount_loop_regs_set PROTO((rtx, rtx, rtx,
+ rtx, int *));
+static void load_mems PROTO((rtx, rtx, rtx, rtx));
+static int insert_loop_mem PROTO((rtx *, void *));
+static int replace_loop_mem PROTO((rtx *, void *));
+static int replace_label PROTO((rtx *, void *));
+
+typedef struct rtx_and_int {
+ rtx r;
+ int i;
+} rtx_and_int;
+
+typedef struct rtx_pair {
+ rtx r1;
+ rtx r2;
+} rtx_pair;
-#ifdef HAIFA
-/* This is extern from unroll.c */
-extern void iteration_info PROTO((rtx, rtx *, rtx *, rtx, rtx));
+/* Nonzero iff INSN is between START and END, inclusive. */
+#define INSN_IN_RANGE_P(INSN, START, END) \
+ (INSN_UID (INSN) < max_uid_for_loop \
+ && INSN_LUID (INSN) >= INSN_LUID (START) \
+ && INSN_LUID (INSN) <= INSN_LUID (END))
-/* Two main functions for implementing bct:
- first - to be called before loop unrolling, and the second - after */
#ifdef HAVE_decrement_and_branch_on_count
-static void analyze_loop_iterations PROTO((rtx, rtx));
-static void insert_bct PROTO((rtx, rtx));
+/* Test whether BCT applicable and safe. */
+static void insert_bct PROTO((rtx, rtx, struct loop_info *));
-/* Auxiliary function that inserts the bct pattern into the loop */
+/* Auxiliary function that inserts the BCT pattern into the loop. */
static void instrument_loop_bct PROTO((rtx, rtx, rtx));
#endif /* HAVE_decrement_and_branch_on_count */
-#endif /* HAIFA */
/* Indirect_jump_in_function is computed once per function. */
int indirect_jump_in_function = 0;
static int indirect_jump_in_function_p PROTO((rtx));
+static int compute_luids PROTO((rtx, rtx, int));
+
+static int biv_elimination_giv_has_0_offset PROTO((struct induction *,
+ struct induction *, rtx));
/* Relative gain of eliminating various kinds of operations. */
-int add_cost;
+static int add_cost;
#if 0
-int shift_cost;
-int mult_cost;
+static int shift_cost;
+static int mult_cost;
#endif
/* Benefit penalty, if a giv is not replaceable, i.e. must emit an insn to
copy the value of the strength reduced giv to its original register. */
-int copy_cost;
+static int copy_cost;
+
+/* Cost of using a register, to normalize the benefits of a giv. */
+static int reg_address_cost;
+
void
init_loop ()
@@ -370,6 +402,12 @@ init_loop ()
add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
+#ifdef ADDRESS_COST
+ reg_address_cost = ADDRESS_COST (reg);
+#else
+ reg_address_cost = rtx_cost (reg, MEM);
+#endif
+
/* We multiply by 2 to reconcile the difference in scale between
these two ways of computing costs. Otherwise the cost of a copy
will be far less than the cost of an add. */
@@ -383,21 +421,49 @@ init_loop ()
gcc_obstack_init (&temp_obstack);
}
+/* Compute the mapping from uids to luids.
+ LUIDs are numbers assigned to insns, like uids,
+ except that luids increase monotonically through the code.
+ Start at insn START and stop just before END. Assign LUIDs
+ starting with PREV_LUID + 1. Return the last assigned LUID + 1. */
+static int
+compute_luids (start, end, prev_luid)
+ rtx start, end;
+ int prev_luid;
+{
+ int i;
+ rtx insn;
+
+ for (insn = start, i = prev_luid; insn != end; insn = NEXT_INSN (insn))
+ {
+ if (INSN_UID (insn) >= max_uid_for_loop)
+ continue;
+ /* Don't assign luids to line-number NOTEs, so that the distance in
+ luids between two insns is not affected by -g. */
+ if (GET_CODE (insn) != NOTE
+ || NOTE_LINE_NUMBER (insn) <= 0)
+ uid_luid[INSN_UID (insn)] = ++i;
+ else
+ /* Give a line number note the same luid as preceding insn. */
+ uid_luid[INSN_UID (insn)] = i;
+ }
+ return i + 1;
+}
+
/* Entry point of this file. Perform loop optimization
on the current function. F is the first insn of the function
and DUMPFILE is a stream for output of a trace of actions taken
(or 0 if none should be output). */
void
-loop_optimize (f, dumpfile, unroll_p)
+loop_optimize (f, dumpfile, unroll_p, bct_p)
/* f is the first instruction of a chain of insns for one function */
rtx f;
FILE *dumpfile;
- int unroll_p;
+ int unroll_p, bct_p;
{
register rtx insn;
register int i;
- rtx last_insn;
loop_dump_stream = dumpfile;
@@ -438,36 +504,18 @@ loop_optimize (f, dumpfile, unroll_p)
not be zeroed. */
loop_number_loop_starts = (rtx *) alloca (max_loop_num * sizeof (rtx));
loop_number_loop_ends = (rtx *) alloca (max_loop_num * sizeof (rtx));
+ loop_number_loop_cont = (rtx *) alloca (max_loop_num * sizeof (rtx));
+ loop_number_cont_dominator = (rtx *) alloca (max_loop_num * sizeof (rtx));
loop_outer_loop = (int *) alloca (max_loop_num * sizeof (int));
loop_invalid = (char *) alloca (max_loop_num * sizeof (char));
loop_number_exit_labels = (rtx *) alloca (max_loop_num * sizeof (rtx));
loop_number_exit_count = (int *) alloca (max_loop_num * sizeof (int));
- /* This is initialized by the unrolling code, so we go ahead
- and clear them just in case we are not performing loop
- unrolling. */
- loop_unroll_factor = (int *) alloca (max_loop_num *sizeof (int));
- bzero ((char *) loop_unroll_factor, max_loop_num * sizeof (int));
-
-#ifdef HAIFA
+#ifdef HAVE_decrement_and_branch_on_count
/* Allocate for BCT optimization */
- loop_can_insert_bct = (int *) alloca (max_loop_num * sizeof (int));
- bzero ((char *) loop_can_insert_bct, max_loop_num * sizeof (int));
-
loop_used_count_register = (int *) alloca (max_loop_num * sizeof (int));
bzero ((char *) loop_used_count_register, max_loop_num * sizeof (int));
-
- loop_increment = (rtx *) alloca (max_loop_num * sizeof (rtx));
- loop_comparison_value = (rtx *) alloca (max_loop_num * sizeof (rtx));
- loop_start_value = (rtx *) alloca (max_loop_num * sizeof (rtx));
- bzero ((char *) loop_increment, max_loop_num * sizeof (rtx));
- bzero ((char *) loop_comparison_value, max_loop_num * sizeof (rtx));
- bzero ((char *) loop_start_value, max_loop_num * sizeof (rtx));
-
- loop_comparison_code
- = (enum rtx_code *) alloca (max_loop_num * sizeof (enum rtx_code));
- bzero ((char *) loop_comparison_code, max_loop_num * sizeof (enum rtx_code));
-#endif /* HAIFA */
+#endif /* HAVE_decrement_and_branch_on_count */
/* Find and process each loop.
First, find them, and record them in order of their beginnings. */
@@ -485,30 +533,16 @@ loop_optimize (f, dumpfile, unroll_p)
but moving this call to init_alias_analysis is more efficient. */
init_alias_analysis ();
- /* See if we went too far. */
+ /* See if we went too far. Note that get_max_uid already returns
+ one more that the maximum uid of all insn. */
if (get_max_uid () > max_uid_for_loop)
abort ();
/* Now reset it to the actual size we need. See above. */
- max_uid_for_loop = get_max_uid () + 1;
-
- /* Compute the mapping from uids to luids.
- LUIDs are numbers assigned to insns, like uids,
- except that luids increase monotonically through the code.
- Don't assign luids to line-number NOTEs, so that the distance in luids
- between two insns is not affected by -g. */
-
- for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
- {
- last_insn = insn;
- if (GET_CODE (insn) != NOTE
- || NOTE_LINE_NUMBER (insn) <= 0)
- uid_luid[INSN_UID (insn)] = ++i;
- else
- /* Give a line number note the same luid as preceding insn. */
- uid_luid[INSN_UID (insn)] = i;
- }
+ max_uid_for_loop = get_max_uid ();
- max_luid = i + 1;
+ /* find_and_verify_loops has already called compute_luids, but it might
+ have rearranged code afterwards, so we need to recompute the luids now. */
+ max_luid = compute_luids (f, NULL_RTX, 0);
/* Don't leave gaps in uid_luid for insns that have been
deleted. It is possible that the first or last insn
@@ -538,18 +572,53 @@ loop_optimize (f, dumpfile, unroll_p)
for (i = max_loop_num-1; i >= 0; i--)
if (! loop_invalid[i] && loop_number_loop_ends[i])
scan_loop (loop_number_loop_starts[i], loop_number_loop_ends[i],
- max_reg_num (), unroll_p);
+ loop_number_loop_cont[i], unroll_p, bct_p);
/* If debugging and unrolling loops, we must replicate the tree nodes
corresponding to the blocks inside the loop, so that the original one
to one mapping will remain. */
if (unroll_p && write_symbols != NO_DEBUG)
unroll_block_trees ();
+
+ end_alias_analysis ();
}
+/* Returns the next insn, in execution order, after INSN. START and
+ END are the NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END for the loop,
+ respectively. LOOP_TOP, if non-NULL, is the top of the loop in the
+ insn-stream; it is used with loops that are entered near the
+ bottom. */
+
+static rtx
+next_insn_in_loop (insn, start, end, loop_top)
+ rtx insn;
+ rtx start;
+ rtx end;
+ rtx loop_top;
+{
+ insn = NEXT_INSN (insn);
+
+ if (insn == end)
+ {
+ if (loop_top)
+ /* Go to the top of the loop, and continue there. */
+ insn = loop_top;
+ else
+ /* We're done. */
+ insn = NULL_RTX;
+ }
+
+ if (insn == start)
+ /* We're done. */
+ insn = NULL_RTX;
+
+ return insn;
+}
+
/* Optimize one loop whose start is LOOP_START and end is END.
LOOP_START is the NOTE_INSN_LOOP_BEG and END is the matching
- NOTE_INSN_LOOP_END. */
+ NOTE_INSN_LOOP_END.
+ LOOP_CONT is the NOTE_INSN_LOOP_CONT. */
/* ??? Could also move memory writes out of loops if the destination address
is invariant, the source is invariant, the memory write is not volatile,
@@ -558,13 +627,12 @@ loop_optimize (f, dumpfile, unroll_p)
write, then we can also mark the memory read as invariant. */
static void
-scan_loop (loop_start, end, nregs, unroll_p)
- rtx loop_start, end;
- int nregs;
- int unroll_p;
+scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
+ rtx loop_start, end, loop_cont;
+ int unroll_p, bct_p;
{
register int i;
- register rtx p;
+ rtx p;
/* 1 if we are scanning insns that could be executed zero times. */
int maybe_never = 0;
/* 1 if we are scanning insns that might never be executed
@@ -593,16 +661,9 @@ scan_loop (loop_start, end, nregs, unroll_p)
since in that case saving an insn makes more difference
and more registers are available. */
int threshold;
- /* If we have calls, contains the insn in which a register was used
- if it was used exactly once; contains const0_rtx if it was used more
- than once. */
- rtx *reg_single_usage = 0;
/* Nonzero if we are scanning instructions in a sub-loop. */
int loop_depth = 0;
-
- n_times_set = (int *) alloca (nregs * sizeof (int));
- n_times_used = (int *) alloca (nregs * sizeof (int));
- may_not_optimize = (char *) alloca (nregs);
+ int nregs;
/* Determine whether this loop starts with a jump down to a test at
the end. This will occur for a small number of loops with a test
@@ -653,9 +714,7 @@ scan_loop (loop_start, end, nregs, unroll_p)
do {..} while (0). If this label was generated previously
by loop, we can't tell anything about it and have to reject
the loop. */
- && INSN_UID (JUMP_LABEL (p)) < max_uid_for_loop
- && INSN_LUID (JUMP_LABEL (p)) >= INSN_LUID (loop_start)
- && INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (end))
+ && INSN_IN_RANGE_P (JUMP_LABEL (p), loop_start, end))
{
loop_top = next_label (scan_start);
scan_start = JUMP_LABEL (p);
@@ -680,25 +739,39 @@ scan_loop (loop_start, end, nregs, unroll_p)
}
/* Count number of times each reg is set during this loop.
- Set may_not_optimize[I] if it is not safe to move out
- the setting of register I. If this loop has calls, set
- reg_single_usage[I]. */
+ Set VARRAY_CHAR (may_not_optimize, I) if it is not safe to move out
+ the setting of register I. Set VARRAY_RTX (reg_single_usage, I). */
+
+ /* Allocate extra space for REGS that might be created by
+ load_mems. We allocate a little extra slop as well, in the hopes
+ that even after the moving of movables creates some new registers
+ we won't have to reallocate these arrays. However, we do grow
+ the arrays, if necessary, in load_mems_recount_loop_regs_set. */
+ nregs = max_reg_num () + loop_mems_idx + 16;
+ VARRAY_INT_INIT (set_in_loop, nregs, "set_in_loop");
+ VARRAY_INT_INIT (n_times_set, nregs, "n_times_set");
+ VARRAY_CHAR_INIT (may_not_optimize, nregs, "may_not_optimize");
+ VARRAY_RTX_INIT (reg_single_usage, nregs, "reg_single_usage");
- bzero ((char *) n_times_set, nregs * sizeof (int));
- bzero (may_not_optimize, nregs);
+ count_loop_regs_set (loop_top ? loop_top : loop_start, end,
+ may_not_optimize, reg_single_usage, &insn_count, nregs);
- if (loop_has_call)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- reg_single_usage = (rtx *) alloca (nregs * sizeof (rtx));
- bzero ((char *) reg_single_usage, nregs * sizeof (rtx));
+ VARRAY_CHAR (may_not_optimize, i) = 1;
+ VARRAY_INT (set_in_loop, i) = 1;
}
- count_loop_regs_set (loop_top ? loop_top : loop_start, end,
- may_not_optimize, reg_single_usage, &insn_count, nregs);
+#ifdef AVOID_CCMODE_COPIES
+ /* Don't try to move insns which set CC registers if we should not
+ create CCmode register copies. */
+ for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
+ if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
+ VARRAY_CHAR (may_not_optimize, i) = 1;
+#endif
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- may_not_optimize[i] = 1, n_times_set[i] = 1;
- bcopy ((char *) n_times_set, (char *) n_times_used, nregs * sizeof (int));
+ bcopy ((char *) &set_in_loop->data,
+ (char *) &n_times_set->data, nregs * sizeof (int));
if (loop_dump_stream)
{
@@ -710,7 +783,7 @@ scan_loop (loop_start, end, nregs, unroll_p)
}
/* Scan through the loop finding insns that are safe to move.
- Set n_times_set negative for the reg being set, so that
+ Set set_in_loop negative for the reg being set, so that
this reg will be considered invariant for subsequent insns.
We consider whether subsequent insns use the reg
in deciding whether it is worth actually moving.
@@ -722,24 +795,10 @@ scan_loop (loop_start, end, nregs, unroll_p)
When MAYBE_NEVER is 0, all insns will be executed at least once
so that is not a problem. */
- p = scan_start;
- while (1)
+ for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top);
+ p != NULL_RTX;
+ p = next_insn_in_loop (p, scan_start, end, loop_top))
{
- p = NEXT_INSN (p);
- /* At end of a straight-in loop, we are done.
- At end of a loop entered at the bottom, scan the top. */
- if (p == scan_start)
- break;
- if (p == end)
- {
- if (loop_top != 0)
- p = loop_top;
- else
- break;
- if (p == scan_start)
- break;
- }
-
if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
&& find_reg_note (p, REG_LIBCALL, NULL_RTX))
in_libcall = 1;
@@ -750,7 +809,7 @@ scan_loop (loop_start, end, nregs, unroll_p)
if (GET_CODE (p) == INSN
&& (set = single_set (p))
&& GET_CODE (SET_DEST (set)) == REG
- && ! may_not_optimize[REGNO (SET_DEST (set))])
+ && ! VARRAY_CHAR (may_not_optimize, REGNO (SET_DEST (set))))
{
int tem1 = 0;
int tem2 = 0;
@@ -789,23 +848,39 @@ scan_loop (loop_start, end, nregs, unroll_p)
We don't know its life-span, so we can't compute the benefit. */
if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
;
- /* In order to move a register, we need to have either:
- (1) it is used only in the same basic block as the set
- (2) the set is guaranteed to be executed once the loop starts,
- and the reg is not used until after that. */
- else if (! (reg_in_basic_block_p (p, SET_DEST (set))
- || (! maybe_never
- && ! loop_reg_used_before_p (set, p, loop_start,
- scan_start, end))))
+ else if (/* The register is used in basic blocks other
+ than the one where it is set (meaning that
+ something after this point in the loop might
+ depend on its value before the set). */
+ ! reg_in_basic_block_p (p, SET_DEST (set))
+ /* And the set is not guaranteed to be executed one
+ the loop starts, or the value before the set is
+ needed before the set occurs...
+
+ ??? Note we have quadratic behaviour here, mitigated
+ by the fact that the previous test will often fail for
+ large loops. Rather than re-scanning the entire loop
+ each time for register usage, we should build tables
+ of the register usage and use them here instead. */
+ && (maybe_never
+ || loop_reg_used_before_p (set, p, loop_start,
+ scan_start, end)))
+ /* It is unsafe to move the set.
+
+ This code used to consider it OK to move a set of a variable
+ which was not created by the user and not used in an exit test.
+ That behavior is incorrect and was removed. */
;
else if ((tem = invariant_p (src))
&& (dependencies == 0
|| (tem2 = invariant_p (dependencies)) != 0)
- && (n_times_set[REGNO (SET_DEST (set))] == 1
+ && (VARRAY_INT (set_in_loop,
+ REGNO (SET_DEST (set))) == 1
|| (tem1
- = consec_sets_invariant_p (SET_DEST (set),
- n_times_set[REGNO (SET_DEST (set))],
- p)))
+ = consec_sets_invariant_p
+ (SET_DEST (set),
+ VARRAY_INT (set_in_loop, REGNO (SET_DEST (set))),
+ p)))
/* If the insn can cause a trap (such as divide by zero),
can't move it unless it's guaranteed to be executed
once loop is entered. Even a function call might
@@ -831,12 +906,13 @@ scan_loop (loop_start, end, nregs, unroll_p)
Don't do this if P has a REG_RETVAL note or if we have
SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */
- if (reg_single_usage && reg_single_usage[regno] != 0
- && reg_single_usage[regno] != const0_rtx
+ if (loop_has_call
+ && VARRAY_RTX (reg_single_usage, regno) != 0
+ && VARRAY_RTX (reg_single_usage, regno) != const0_rtx
&& REGNO_FIRST_UID (regno) == INSN_UID (p)
&& (REGNO_LAST_UID (regno)
- == INSN_UID (reg_single_usage[regno]))
- && n_times_set[REGNO (SET_DEST (set))] == 1
+ == INSN_UID (VARRAY_RTX (reg_single_usage, regno)))
+ && VARRAY_INT (set_in_loop, regno) == 1
&& ! side_effects_p (SET_SRC (set))
&& ! find_reg_note (p, REG_RETVAL, NULL_RTX)
&& (! SMALL_REGISTER_CLASSES
@@ -846,22 +922,25 @@ scan_loop (loop_start, end, nregs, unroll_p)
a call-clobbered register and the life of REGNO
might span a call. */
&& ! modified_between_p (SET_SRC (set), p,
- reg_single_usage[regno])
- && no_labels_between_p (p, reg_single_usage[regno])
+ VARRAY_RTX
+ (reg_single_usage, regno))
+ && no_labels_between_p (p, VARRAY_RTX (reg_single_usage, regno))
&& validate_replace_rtx (SET_DEST (set), SET_SRC (set),
- reg_single_usage[regno]))
+ VARRAY_RTX
+ (reg_single_usage, regno)))
{
/* Replace any usage in a REG_EQUAL note. Must copy the
new source, so that we don't get rtx sharing between the
SET_SOURCE and REG_NOTES of insn p. */
- REG_NOTES (reg_single_usage[regno])
- = replace_rtx (REG_NOTES (reg_single_usage[regno]),
+ REG_NOTES (VARRAY_RTX (reg_single_usage, regno))
+ = replace_rtx (REG_NOTES (VARRAY_RTX
+ (reg_single_usage, regno)),
SET_DEST (set), copy_rtx (SET_SRC (set)));
PUT_CODE (p, NOTE);
NOTE_LINE_NUMBER (p) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (p) = 0;
- n_times_set[regno] = 0;
+ VARRAY_INT (set_in_loop, regno) = 0;
continue;
}
@@ -872,7 +951,8 @@ scan_loop (loop_start, end, nregs, unroll_p)
m->dependencies = dependencies;
m->set_dest = SET_DEST (set);
m->force = 0;
- m->consec = n_times_set[REGNO (SET_DEST (set))] - 1;
+ m->consec = VARRAY_INT (set_in_loop,
+ REGNO (SET_DEST (set))) - 1;
m->done = 0;
m->forces = 0;
m->partial = 0;
@@ -889,10 +969,10 @@ scan_loop (loop_start, end, nregs, unroll_p)
m->match = 0;
m->lifetime = (uid_luid[REGNO_LAST_UID (regno)]
- uid_luid[REGNO_FIRST_UID (regno)]);
- m->savings = n_times_used[regno];
+ m->savings = VARRAY_INT (n_times_set, regno);
if (find_reg_note (p, REG_RETVAL, NULL_RTX))
m->savings += libcall_benefit (p);
- n_times_set[regno] = move_insn ? -2 : -1;
+ VARRAY_INT (set_in_loop, regno) = move_insn ? -2 : -1;
/* Add M to the end of the chain MOVABLES. */
if (movables == 0)
movables = m;
@@ -951,7 +1031,7 @@ scan_loop (loop_start, end, nregs, unroll_p)
&& !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
{
register int regno = REGNO (SET_DEST (set));
- if (n_times_set[regno] == 2)
+ if (VARRAY_INT (set_in_loop, regno) == 2)
{
register struct movable *m;
m = (struct movable *) alloca (sizeof (struct movable));
@@ -1001,7 +1081,7 @@ scan_loop (loop_start, end, nregs, unroll_p)
m->lifetime = (uid_luid[REGNO_LAST_UID (regno)]
- uid_luid[REGNO_FIRST_UID (regno)]);
m->savings = 1;
- n_times_set[regno] = -1;
+ VARRAY_INT (set_in_loop, regno) = -1;
/* Add M to the end of the chain MOVABLES. */
if (movables == 0)
movables = m;
@@ -1066,7 +1146,7 @@ scan_loop (loop_start, end, nregs, unroll_p)
combine_movables (movables, nregs);
/* Now consider each movable insn to decide whether it is worth moving.
- Store 0 in n_times_set for each reg that is moved.
+ Store 0 in set_in_loop for each reg that is moved.
Generally this increases code size, so do not move moveables when
optimizing for code size. */
@@ -1076,14 +1156,27 @@ scan_loop (loop_start, end, nregs, unroll_p)
insn_count, loop_start, end, nregs);
/* Now candidates that still are negative are those not moved.
- Change n_times_set to indicate that those are not actually invariant. */
+ Change set_in_loop to indicate that those are not actually invariant. */
for (i = 0; i < nregs; i++)
- if (n_times_set[i] < 0)
- n_times_set[i] = n_times_used[i];
+ if (VARRAY_INT (set_in_loop, i) < 0)
+ VARRAY_INT (set_in_loop, i) = VARRAY_INT (n_times_set, i);
+
+ /* Now that we've moved some things out of the loop, we might be able to
+ hoist even more memory references. */
+ load_mems_and_recount_loop_regs_set (scan_start, end, loop_top,
+ loop_start, &insn_count);
if (flag_strength_reduce)
- strength_reduce (scan_start, end, loop_top,
- insn_count, loop_start, end, unroll_p);
+ {
+ the_movables = movables;
+ strength_reduce (scan_start, end, loop_top,
+ insn_count, loop_start, end, loop_cont, unroll_p, bct_p);
+ }
+
+ VARRAY_FREE (reg_single_usage);
+ VARRAY_FREE (set_in_loop);
+ VARRAY_FREE (n_times_set);
+ VARRAY_FREE (may_not_optimize);
}
/* Add elements to *OUTPUT to record all the pseudo-regs
@@ -1145,7 +1238,7 @@ record_excess_regs (in_this, not_in_this, output)
If there are none, return 0.
If there are one or more, return an EXPR_LIST containing all of them. */
-static rtx
+rtx
libcall_other_reg (insn, equiv)
rtx insn, equiv;
{
@@ -1357,7 +1450,7 @@ combine_movables (movables, nregs)
/* Perhaps testing m->consec_sets would be more appropriate here? */
for (m = movables; m; m = m->next)
- if (m->match == 0 && n_times_used[m->regno] == 1 && !m->partial)
+ if (m->match == 0 && VARRAY_INT (n_times_set, m->regno) == 1 && !m->partial)
{
register struct movable *m1;
int regno = m->regno;
@@ -1368,7 +1461,7 @@ combine_movables (movables, nregs)
/* We want later insns to match the first one. Don't make the first
one match any later ones. So start this loop at m->next. */
for (m1 = m->next; m1; m1 = m1->next)
- if (m != m1 && m1->match == 0 && n_times_used[m1->regno] == 1
+ if (m != m1 && m1->match == 0 && VARRAY_INT (n_times_set, m1->regno) == 1
/* A reg used outside the loop mustn't be eliminated. */
&& !m1->global
/* A reg used for zero-extending mustn't be eliminated. */
@@ -1505,7 +1598,7 @@ rtx_equal_for_loop_p (x, y, movables)
/* If we have a register and a constant, they may sometimes be
equal. */
- if (GET_CODE (x) == REG && n_times_set[REGNO (x)] == -2
+ if (GET_CODE (x) == REG && VARRAY_INT (set_in_loop, REGNO (x)) == -2
&& CONSTANT_P (y))
{
for (m = movables; m; m = m->next)
@@ -1513,7 +1606,7 @@ rtx_equal_for_loop_p (x, y, movables)
&& rtx_equal_p (m->set_src, y))
return 1;
}
- else if (GET_CODE (y) == REG && n_times_set[REGNO (y)] == -2
+ else if (GET_CODE (y) == REG && VARRAY_INT (set_in_loop, REGNO (y)) == -2
&& CONSTANT_P (x))
{
for (m = movables; m; m = m->next)
@@ -1719,13 +1812,8 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
if (loop_dump_stream)
fprintf (loop_dump_stream, "savings %d ", savings);
- if (moved_once[regno])
- {
- insn_count *= 2;
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream, "halved since already moved ");
- }
+ if (moved_once[regno] && loop_dump_stream)
+ fprintf (loop_dump_stream, "halved since already moved ");
/* An insn MUST be moved if we already moved something else
which is safe only if this one is moved too: that is,
@@ -1742,9 +1830,10 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
if (already_moved[regno]
|| flag_move_all_movables
- || (threshold * savings * m->lifetime) >= insn_count
+ || (threshold * savings * m->lifetime) >=
+ (moved_once[regno] ? insn_count * 2 : insn_count)
|| (m->forces && m->forces->done
- && n_times_used[m->forces->regno] == 1))
+ && VARRAY_INT (n_times_set, m->forces->regno) == 1))
{
int count;
register struct movable *m1;
@@ -1808,9 +1897,17 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
temp = delete_insn (temp);
}
+ temp = p;
p = delete_insn (p);
+
+ /* simplify_giv_expr expects that it can walk the insns
+ at m->insn forwards and see this old sequence we are
+ tossing here. delete_insn does preserve the next
+ pointers, but when we skip over a NOTE we must fix
+ it up. Otherwise that code walks into the non-deleted
+ insn stream. */
while (p && GET_CODE (p) == NOTE)
- p = NEXT_INSN (p);
+ p = NEXT_INSN (temp) = NEXT_INSN (p);
}
start_sequence ();
@@ -1929,6 +2026,8 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
REG_NOTES (i1) = REG_NOTES (temp);
delete_insn (temp);
}
+ if (new_start == 0)
+ new_start = first;
}
if (m->savemode != VOIDmode)
{
@@ -2017,9 +2116,18 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
XEXP (temp, 0) = i1;
}
+ temp = p;
delete_insn (p);
- do p = NEXT_INSN (p);
- while (p && GET_CODE (p) == NOTE);
+ p = NEXT_INSN (p);
+
+ /* simplify_giv_expr expects that it can walk the insns
+ at m->insn forwards and see this old sequence we are
+ tossing here. delete_insn does preserve the next
+ pointers, but when we skip over a NOTE we must fix
+ it up. Otherwise that code walks into the non-deleted
+ insn stream. */
+ while (p && GET_CODE (p) == NOTE)
+ p = NEXT_INSN (temp) = NEXT_INSN (p);
}
/* The more regs we move, the less we like moving them. */
@@ -2035,7 +2143,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
/* The reg set here is now invariant. */
if (! m->partial)
- n_times_set[regno] = 0;
+ VARRAY_INT (set_in_loop, regno) = 0;
m->done = 1;
@@ -2092,7 +2200,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
/* The reg merged here is now invariant,
if the reg it matches is invariant. */
if (! m->partial)
- n_times_set[m1->regno] = 0;
+ VARRAY_INT (set_in_loop, m1->regno) = 0;
}
}
else if (loop_dump_stream)
@@ -2277,22 +2385,32 @@ constant_high_bytes (p, loop_start)
#endif
/* Scan a loop setting the variables `unknown_address_altered',
- `num_mem_sets', `loop_continue', loops_enclosed', `loop_has_call',
- and `loop_has_volatile'.
- Also, fill in the array `loop_store_mems'. */
+ `num_mem_sets', `loop_continue', `loops_enclosed', `loop_has_call',
+ `loop_has_volatile', and `loop_has_tablejump'.
+ Also, fill in the array `loop_mems' and the list `loop_store_mems'. */
static void
prescan_loop (start, end)
rtx start, end;
{
register int level = 1;
- register rtx insn;
+ rtx insn;
+ int loop_has_multiple_exit_targets = 0;
+ /* The label after END. Jumping here is just like falling off the
+ end of the loop. We use next_nonnote_insn instead of next_label
+ as a hedge against the (pathological) case where some actual insn
+ might end up between the two. */
+ rtx exit_target = next_nonnote_insn (end);
+ if (exit_target == NULL_RTX || GET_CODE (exit_target) != CODE_LABEL)
+ loop_has_multiple_exit_targets = 1;
unknown_address_altered = 0;
loop_has_call = 0;
loop_has_volatile = 0;
+ loop_has_tablejump = 0;
+ loop_store_mems = NULL_RTX;
first_loop_store_insn = NULL_RTX;
- loop_store_mems_idx = 0;
+ loop_mems_idx = 0;
num_mem_sets = 0;
loops_enclosed = 1;
@@ -2330,22 +2448,138 @@ prescan_loop (start, end)
unknown_address_altered = 1;
loop_has_call = 1;
}
- else
+ else if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
{
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
+ rtx label1 = NULL_RTX;
+ rtx label2 = NULL_RTX;
+
+ if (volatile_refs_p (PATTERN (insn)))
+ loop_has_volatile = 1;
+
+ if (GET_CODE (insn) == JUMP_INSN
+ && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_VEC))
+ loop_has_tablejump = 1;
+
+ note_stores (PATTERN (insn), note_addr_stored);
+ if (! first_loop_store_insn && loop_store_mems)
+ first_loop_store_insn = insn;
+
+ if (! loop_has_multiple_exit_targets
+ && GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && SET_DEST (PATTERN (insn)) == pc_rtx)
{
- if (volatile_refs_p (PATTERN (insn)))
- loop_has_volatile = 1;
+ if (GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
+ {
+ label1 = XEXP (SET_SRC (PATTERN (insn)), 1);
+ label2 = XEXP (SET_SRC (PATTERN (insn)), 2);
+ }
+ else
+ {
+ label1 = SET_SRC (PATTERN (insn));
+ }
- note_stores (PATTERN (insn), note_addr_stored);
- if (! first_loop_store_insn && loop_store_mems_idx != 0)
- first_loop_store_insn = insn;
+ do {
+ if (label1 && label1 != pc_rtx)
+ {
+ if (GET_CODE (label1) != LABEL_REF)
+ {
+ /* Something tricky. */
+ loop_has_multiple_exit_targets = 1;
+ break;
+ }
+ else if (XEXP (label1, 0) != exit_target
+ && LABEL_OUTSIDE_LOOP_P (label1))
+ {
+ /* A jump outside the current loop. */
+ loop_has_multiple_exit_targets = 1;
+ break;
+ }
+ }
+ label1 = label2;
+ label2 = NULL_RTX;
+ } while (label1);
}
}
+ else if (GET_CODE (insn) == RETURN)
+ loop_has_multiple_exit_targets = 1;
}
+
+ /* Now, rescan the loop, setting up the LOOP_MEMS array. */
+ if (/* We can't tell what MEMs are aliased by what. */
+ !unknown_address_altered
+ /* An exception thrown by a called function might land us
+ anywhere. */
+ && !loop_has_call
+ /* We don't want loads for MEMs moved to a location before the
+ one at which their stack memory becomes allocated. (Note
+ that this is not a problem for malloc, etc., since those
+ require actual function calls. */
+ && !current_function_calls_alloca
+ /* There are ways to leave the loop other than falling off the
+ end. */
+ && !loop_has_multiple_exit_targets)
+ for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
+ insn = NEXT_INSN (insn))
+ for_each_rtx (&insn, insert_loop_mem, 0);
}
+/* LOOP_NUMBER_CONT_DOMINATOR is now the last label between the loop start
+ and the continue note that is a the destination of a (cond)jump after
+ the continue note. If there is any (cond)jump between the loop start
+ and what we have so far as LOOP_NUMBER_CONT_DOMINATOR that has a
+ target between LOOP_DOMINATOR and the continue note, move
+ LOOP_NUMBER_CONT_DOMINATOR forward to that label; if a jump's
+ destination cannot be determined, clear LOOP_NUMBER_CONT_DOMINATOR. */
+
+static void
+verify_dominator (loop_number)
+ int loop_number;
+{
+ rtx insn;
+
+ if (! loop_number_cont_dominator[loop_number])
+ /* This can happen for an empty loop, e.g. in
+ gcc.c-torture/compile/920410-2.c */
+ return;
+ if (loop_number_cont_dominator[loop_number] == const0_rtx)
+ {
+ loop_number_cont_dominator[loop_number] = 0;
+ return;
+ }
+ for (insn = loop_number_loop_starts[loop_number];
+ insn != loop_number_cont_dominator[loop_number];
+ insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) != RETURN)
+ {
+ rtx label = JUMP_LABEL (insn);
+ int label_luid;
+
+ /* If it is not a jump we can easily understand or for
+ which we do not have jump target information in the JUMP_LABEL
+ field (consider ADDR_VEC and ADDR_DIFF_VEC insns), then clear
+ LOOP_NUMBER_CONT_DOMINATOR. */
+ if ((! condjump_p (insn)
+ && ! condjump_in_parallel_p (insn))
+ || label == NULL_RTX)
+ {
+ loop_number_cont_dominator[loop_number] = NULL_RTX;
+ return;
+ }
+
+ label_luid = INSN_LUID (label);
+ if (label_luid < INSN_LUID (loop_number_loop_cont[loop_number])
+ && (label_luid
+ > INSN_LUID (loop_number_cont_dominator[loop_number])))
+ loop_number_cont_dominator[loop_number] = label;
+ }
+ }
+}
+
/* Scan the function looking for loops. Record the start and end of each loop.
Also mark as invalid loops any loops that contain a setjmp or are branched
to from outside the loop. */
@@ -2359,6 +2593,8 @@ find_and_verify_loops (f)
int next_loop = -1;
int loop;
+ compute_luids (f, NULL_RTX, 0);
+
/* If there are jumps to undefined labels,
treat them as jumps out of any/all loops.
This also avoids writing past end of tables when there are no loops. */
@@ -2375,6 +2611,8 @@ find_and_verify_loops (f)
case NOTE_INSN_LOOP_BEG:
loop_number_loop_starts[++next_loop] = insn;
loop_number_loop_ends[next_loop] = 0;
+ loop_number_loop_cont[next_loop] = 0;
+ loop_number_cont_dominator[next_loop] = 0;
loop_outer_loop[next_loop] = current_loop;
loop_invalid[next_loop] = 0;
loop_number_exit_labels[next_loop] = 0;
@@ -2395,17 +2633,63 @@ find_and_verify_loops (f)
}
break;
+ case NOTE_INSN_LOOP_CONT:
+ loop_number_loop_cont[current_loop] = insn;
+ break;
case NOTE_INSN_LOOP_END:
if (current_loop == -1)
abort ();
loop_number_loop_ends[current_loop] = insn;
+ verify_dominator (current_loop);
current_loop = loop_outer_loop[current_loop];
break;
default:
break;
}
+ /* If for any loop, this is a jump insn between the NOTE_INSN_LOOP_CONT
+ and NOTE_INSN_LOOP_END notes, update loop_number_loop_dominator. */
+ else if (GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) != RETURN
+ && current_loop >= 0)
+ {
+ int this_loop;
+ rtx label = JUMP_LABEL (insn);
+
+ if (! condjump_p (insn) && ! condjump_in_parallel_p (insn))
+ label = NULL_RTX;
+
+ this_loop = current_loop;
+ do
+ {
+ /* First see if we care about this loop. */
+ if (loop_number_loop_cont[this_loop]
+ && loop_number_cont_dominator[this_loop] != const0_rtx)
+ {
+ /* If the jump destination is not known, invalidate
+ loop_number_const_dominator. */
+ if (! label)
+ loop_number_cont_dominator[this_loop] = const0_rtx;
+ else
+ /* Check if the destination is between loop start and
+ cont. */
+ if ((INSN_LUID (label)
+ < INSN_LUID (loop_number_loop_cont[this_loop]))
+ && (INSN_LUID (label)
+ > INSN_LUID (loop_number_loop_starts[this_loop]))
+ /* And if there is no later destination already
+ recorded. */
+ && (! loop_number_cont_dominator[this_loop]
+ || (INSN_LUID (label)
+ > INSN_LUID (loop_number_cont_dominator
+ [this_loop]))))
+ loop_number_cont_dominator[this_loop] = label;
+ }
+ this_loop = loop_outer_loop[this_loop];
+ }
+ while (this_loop >= 0);
+ }
/* Note that this will mark the NOTE_INSN_LOOP_END note as being in the
enclosing loop, but this doesn't matter. */
@@ -2840,8 +3124,6 @@ note_addr_stored (x, y)
rtx x;
rtx y ATTRIBUTE_UNUSED;
{
- register int i;
-
if (x == 0 || GET_CODE (x) != MEM)
return;
@@ -2856,23 +3138,7 @@ note_addr_stored (x, y)
if (unknown_address_altered)
return;
- for (i = 0; i < loop_store_mems_idx; i++)
- if (rtx_equal_p (XEXP (loop_store_mems[i], 0), XEXP (x, 0))
- && MEM_IN_STRUCT_P (x) == MEM_IN_STRUCT_P (loop_store_mems[i]))
- {
- /* We are storing at the same address as previously noted. Save the
- wider reference. */
- if (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (loop_store_mems[i])))
- loop_store_mems[i] = x;
- break;
- }
-
- if (i == NUM_STORES)
- unknown_address_altered = 1;
-
- else if (i == loop_store_mems_idx)
- loop_store_mems[loop_store_mems_idx++] = x;
+ loop_store_mems = gen_rtx_EXPR_LIST (VOIDmode, x, loop_store_mems);
}
/* Return nonzero if the rtx X is invariant over the current loop.
@@ -2891,6 +3157,7 @@ invariant_p (x)
register enum rtx_code code;
register char *fmt;
int conditional = 0;
+ rtx mem_list_entry;
if (x == 0)
return 1;
@@ -2936,10 +3203,10 @@ invariant_p (x)
&& REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
return 0;
- if (n_times_set[REGNO (x)] < 0)
+ if (VARRAY_INT (set_in_loop, REGNO (x)) < 0)
return 2;
- return n_times_set[REGNO (x)] == 0;
+ return VARRAY_INT (set_in_loop, REGNO (x)) == 0;
case MEM:
/* Volatile memory references must be rejected. Do this before
@@ -2953,15 +3220,20 @@ invariant_p (x)
if (RTX_UNCHANGING_P (x))
break;
- /* If we filled the table (or had a subroutine call), any location
- in memory could have been clobbered. */
+ /* If we had a subroutine call, any location in memory could have been
+ clobbered. */
if (unknown_address_altered)
return 0;
/* See if there is any dependence between a store and this load. */
- for (i = loop_store_mems_idx - 1; i >= 0; i--)
- if (true_dependence (loop_store_mems[i], VOIDmode, x, rtx_varies_p))
- return 0;
+ mem_list_entry = loop_store_mems;
+ while (mem_list_entry)
+ {
+ if (true_dependence (XEXP (mem_list_entry, 0), VOIDmode,
+ x, rtx_varies_p))
+ return 0;
+ mem_list_entry = XEXP (mem_list_entry, 1);
+ }
/* It's not invalidated by a store in memory
but we must still verify the address is invariant. */
@@ -3027,7 +3299,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
rtx temp;
/* Number of sets we have to insist on finding after INSN. */
int count = n_sets - 1;
- int old = n_times_set[regno];
+ int old = VARRAY_INT (set_in_loop, regno);
int value = 0;
int this;
@@ -3035,7 +3307,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
if (n_sets == 127)
return 0;
- n_times_set[regno] = 0;
+ VARRAY_INT (set_in_loop, regno) = 0;
while (count > 0)
{
@@ -3074,12 +3346,12 @@ consec_sets_invariant_p (reg, n_sets, insn)
count--;
else if (code != NOTE)
{
- n_times_set[regno] = old;
+ VARRAY_INT (set_in_loop, regno) = old;
return 0;
}
}
- n_times_set[regno] = old;
+ VARRAY_INT (set_in_loop, regno) = old;
/* If invariant_p ever returned 2, we return 2. */
return 1 + (value & 2);
}
@@ -3125,15 +3397,16 @@ static void
find_single_use_in_loop (insn, x, usage)
rtx insn;
rtx x;
- rtx *usage;
+ varray_type usage;
{
enum rtx_code code = GET_CODE (x);
char *fmt = GET_RTX_FORMAT (code);
int i, j;
if (code == REG)
- usage[REGNO (x)]
- = (usage[REGNO (x)] != 0 && usage[REGNO (x)] != insn)
+ VARRAY_RTX (usage, REGNO (x))
+ = (VARRAY_RTX (usage, REGNO (x)) != 0
+ && VARRAY_RTX (usage, REGNO (x)) != insn)
? const0_rtx : insn;
else if (code == SET)
@@ -3157,9 +3430,54 @@ find_single_use_in_loop (insn, x, usage)
}
}
-/* Increment N_TIMES_SET at the index of each register
+/* Count and record any set in X which is contained in INSN. Update
+ MAY_NOT_MOVE and LAST_SET for any register set in X. */
+
+static void
+count_one_set (insn, x, may_not_move, last_set)
+ rtx insn, x;
+ varray_type may_not_move;
+ rtx *last_set;
+{
+ if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
+ /* Don't move a reg that has an explicit clobber.
+ It's not worth the pain to try to do it correctly. */
+ VARRAY_CHAR (may_not_move, REGNO (XEXP (x, 0))) = 1;
+
+ if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
+ {
+ rtx dest = SET_DEST (x);
+ while (GET_CODE (dest) == SUBREG
+ || GET_CODE (dest) == ZERO_EXTRACT
+ || GET_CODE (dest) == SIGN_EXTRACT
+ || GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
+ if (GET_CODE (dest) == REG)
+ {
+ register int regno = REGNO (dest);
+ /* If this is the first setting of this reg
+ in current basic block, and it was set before,
+ it must be set in two basic blocks, so it cannot
+ be moved out of the loop. */
+ if (VARRAY_INT (set_in_loop, regno) > 0
+ && last_set[regno] == 0)
+ VARRAY_CHAR (may_not_move, regno) = 1;
+ /* If this is not first setting in current basic block,
+ see if reg was used in between previous one and this.
+ If so, neither one can be moved. */
+ if (last_set[regno] != 0
+ && reg_used_between_p (dest, last_set[regno], insn))
+ VARRAY_CHAR (may_not_move, regno) = 1;
+ if (VARRAY_INT (set_in_loop, regno) < 127)
+ ++VARRAY_INT (set_in_loop, regno);
+ last_set[regno] = insn;
+ }
+ }
+}
+
+/* Increment SET_IN_LOOP at the index of each register
that is modified by an insn between FROM and TO.
- If the value of an element of N_TIMES_SET becomes 127 or more,
+ If the value of an element of SET_IN_LOOP becomes 127 or more,
stop incrementing it, to avoid overflow.
Store in SINGLE_USAGE[I] the single insn in which register I is
@@ -3176,15 +3494,14 @@ find_single_use_in_loop (insn, x, usage)
static void
count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
register rtx from, to;
- char *may_not_move;
- rtx *single_usage;
+ varray_type may_not_move;
+ varray_type single_usage;
int *count_ptr;
int nregs;
{
register rtx *last_set = (rtx *) alloca (nregs * sizeof (rtx));
register rtx insn;
register int count = 0;
- register rtx dest;
bzero ((char *) last_set, nregs * sizeof (rtx));
for (insn = from; insn != to; insn = NEXT_INSN (insn))
@@ -3193,84 +3510,22 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
{
++count;
- /* If requested, record registers that have exactly one use. */
- if (single_usage)
- {
- find_single_use_in_loop (insn, PATTERN (insn), single_usage);
-
- /* Include uses in REG_EQUAL notes. */
- if (REG_NOTES (insn))
- find_single_use_in_loop (insn, REG_NOTES (insn), single_usage);
- }
+ /* Record registers that have exactly one use. */
+ find_single_use_in_loop (insn, PATTERN (insn), single_usage);
- if (GET_CODE (PATTERN (insn)) == CLOBBER
- && GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
- /* Don't move a reg that has an explicit clobber.
- We might do so sometimes, but it's not worth the pain. */
- may_not_move[REGNO (XEXP (PATTERN (insn), 0))] = 1;
+ /* Include uses in REG_EQUAL notes. */
+ if (REG_NOTES (insn))
+ find_single_use_in_loop (insn, REG_NOTES (insn), single_usage);
if (GET_CODE (PATTERN (insn)) == SET
|| GET_CODE (PATTERN (insn)) == CLOBBER)
- {
- dest = SET_DEST (PATTERN (insn));
- while (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == STRICT_LOW_PART)
- dest = XEXP (dest, 0);
- if (GET_CODE (dest) == REG)
- {
- register int regno = REGNO (dest);
- /* If this is the first setting of this reg
- in current basic block, and it was set before,
- it must be set in two basic blocks, so it cannot
- be moved out of the loop. */
- if (n_times_set[regno] > 0 && last_set[regno] == 0)
- may_not_move[regno] = 1;
- /* If this is not first setting in current basic block,
- see if reg was used in between previous one and this.
- If so, neither one can be moved. */
- if (last_set[regno] != 0
- && reg_used_between_p (dest, last_set[regno], insn))
- may_not_move[regno] = 1;
- if (n_times_set[regno] < 127)
- ++n_times_set[regno];
- last_set[regno] = insn;
- }
- }
+ count_one_set (insn, PATTERN (insn), may_not_move, last_set);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
register int i;
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
- {
- register rtx x = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
- /* Don't move a reg that has an explicit clobber.
- It's not worth the pain to try to do it correctly. */
- may_not_move[REGNO (XEXP (x, 0))] = 1;
-
- if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
- {
- dest = SET_DEST (x);
- while (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
- || GET_CODE (dest) == STRICT_LOW_PART)
- dest = XEXP (dest, 0);
- if (GET_CODE (dest) == REG)
- {
- register int regno = REGNO (dest);
- if (n_times_set[regno] > 0 && last_set[regno] == 0)
- may_not_move[regno] = 1;
- if (last_set[regno] != 0
- && reg_used_between_p (dest, last_set[regno], insn))
- may_not_move[regno] = 1;
- if (n_times_set[regno] < 127)
- ++n_times_set[regno];
- last_set[regno] = insn;
- }
- }
- }
+ count_one_set (insn, XVECEXP (PATTERN (insn), 0, i),
+ may_not_move, last_set);
}
}
@@ -3318,18 +3573,18 @@ loop_reg_used_before_p (set, insn, loop_start, scan_start, loop_end)
value is a linear function of a biv. */
/* Bivs are recognized by `basic_induction_var';
- Givs by `general_induct_var'. */
+ Givs by `general_induction_var'. */
/* Indexed by register number, indicates whether or not register is an
induction variable, and if so what type. */
-enum iv_mode *reg_iv_type;
+varray_type reg_iv_type;
/* Indexed by register number, contains pointer to `struct induction'
if register is an induction variable. This holds general info for
all induction variables. */
-struct induction **reg_iv_info;
+varray_type reg_iv_info;
/* Indexed by register number, contains pointer to `struct iv_class'
if register is a basic induction variable. This holds info describing
@@ -3343,6 +3598,11 @@ struct iv_class **reg_biv_class;
struct iv_class *loop_iv_list;
+/* Givs made from biv increments are always splittable for loop unrolling.
+ Since there is no regscan info for them, we have to keep track of them
+ separately. */
+int first_increment_giv, last_increment_giv;
+
/* Communication with routines called via `note_stores'. */
static rtx note_insn;
@@ -3354,18 +3614,6 @@ static rtx addr_placeholder;
/* ??? Unfinished optimizations, and possible future optimizations,
for the strength reduction code. */
-/* ??? There is one more optimization you might be interested in doing: to
- allocate pseudo registers for frequently-accessed memory locations.
- If the same memory location is referenced each time around, it might
- be possible to copy it into a register before and out after.
- This is especially useful when the memory location is a variable which
- is in a stack slot because somewhere its address is taken. If the
- loop doesn't contain a function call and the variable isn't volatile,
- it is safe to keep the value in a register for the duration of the
- loop. One tricky thing is that the copying of the value back from the
- register has to be done on all exits from the loop. You need to check that
- all the exits from the loop go to the same place. */
-
/* ??? The interaction of biv elimination, and recognition of 'constant'
bivs, may cause problems. */
@@ -3390,36 +3638,47 @@ static rtx addr_placeholder;
was rerun in loop_optimize whenever a register was added or moved.
Also, some of the optimizations could be a little less conservative. */
-/* Perform strength reduction and induction variable elimination. */
+/* Perform strength reduction and induction variable elimination.
-/* Pseudo registers created during this function will be beyond the last
+ Pseudo registers created during this function will be beyond the last
valid index in several tables including n_times_set and regno_last_uid.
This does not cause a problem here, because the added registers cannot be
givs outside of their loop, and hence will never be reconsidered.
- But scan_loop must check regnos to make sure they are in bounds. */
+ But scan_loop must check regnos to make sure they are in bounds.
+
+ SCAN_START is the first instruction in the loop, as the loop would
+ actually be executed. END is the NOTE_INSN_LOOP_END. LOOP_TOP is
+ the first instruction in the loop, as it is layed out in the
+ instruction stream. LOOP_START is the NOTE_INSN_LOOP_BEG.
+ LOOP_CONT is the NOTE_INSN_LOOP_CONT. */
static void
strength_reduce (scan_start, end, loop_top, insn_count,
- loop_start, loop_end, unroll_p)
+ loop_start, loop_end, loop_cont, unroll_p, bct_p)
rtx scan_start;
rtx end;
rtx loop_top;
int insn_count;
rtx loop_start;
rtx loop_end;
- int unroll_p;
+ rtx loop_cont;
+ int unroll_p, bct_p ATTRIBUTE_UNUSED;
{
rtx p;
rtx set;
rtx inc_val;
rtx mult_val;
rtx dest_reg;
+ rtx *location;
/* This is 1 if current insn is not executed at least once for every loop
iteration. */
int not_every_iteration = 0;
/* This is 1 if current insn may be executed more than once for every
loop iteration. */
int maybe_multiple = 0;
+ /* This is 1 if we have past a branch back to the top of the loop
+ (aka a loop latch). */
+ int past_loop_latch = 0;
/* Temporary list pointers for traversing loop_iv_list. */
struct iv_class *bl, **backbl;
/* Ratio of extra register life span we can justify
@@ -3430,18 +3689,22 @@ strength_reduce (scan_start, end, loop_top, insn_count,
int threshold = (loop_has_call ? 1 : 2) * (3 + n_non_fixed_regs);
/* Map of pseudo-register replacements. */
rtx *reg_map;
+ int reg_map_size;
int call_seen;
rtx test;
rtx end_insert_before;
int loop_depth = 0;
+ int n_extra_increment;
+ struct loop_info loop_iteration_info;
+ struct loop_info *loop_info = &loop_iteration_info;
+
+ /* If scan_start points to the loop exit test, we have to be wary of
+ subversive use of gotos inside expression statements. */
+ if (prev_nonnote_insn (scan_start) != prev_nonnote_insn (loop_start))
+ maybe_multiple = back_branch_in_range_p (scan_start, loop_start, loop_end);
- reg_iv_type = (enum iv_mode *) alloca (max_reg_before_loop
- * sizeof (enum iv_mode *));
- bzero ((char *) reg_iv_type, max_reg_before_loop * sizeof (enum iv_mode *));
- reg_iv_info = (struct induction **)
- alloca (max_reg_before_loop * sizeof (struct induction *));
- bzero ((char *) reg_iv_info, (max_reg_before_loop
- * sizeof (struct induction *)));
+ VARRAY_INT_INIT (reg_iv_type, max_reg_before_loop, "reg_iv_type");
+ VARRAY_GENERIC_PTR_INIT (reg_iv_info, max_reg_before_loop, "reg_iv_info");
reg_biv_class = (struct iv_class **)
alloca (max_reg_before_loop * sizeof (struct iv_class *));
bzero ((char *) reg_biv_class, (max_reg_before_loop
@@ -3464,24 +3727,10 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Scan through loop to find all possible bivs. */
- p = scan_start;
- while (1)
+ for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top);
+ p != NULL_RTX;
+ p = next_insn_in_loop (p, scan_start, end, loop_top))
{
- p = NEXT_INSN (p);
- /* At end of a straight-in loop, we are done.
- At end of a loop entered at the bottom, scan the top. */
- if (p == scan_start)
- break;
- if (p == end)
- {
- if (loop_top != 0)
- p = loop_top;
- else
- break;
- if (p == scan_start)
- break;
- }
-
if (GET_CODE (p) == INSN
&& (set = single_set (p))
&& GET_CODE (SET_DEST (set)) == REG)
@@ -3489,10 +3738,11 @@ strength_reduce (scan_start, end, loop_top, insn_count,
dest_reg = SET_DEST (set);
if (REGNO (dest_reg) < max_reg_before_loop
&& REGNO (dest_reg) >= FIRST_PSEUDO_REGISTER
- && reg_iv_type[REGNO (dest_reg)] != NOT_BASIC_INDUCT)
+ && REG_IV_TYPE (REGNO (dest_reg)) != NOT_BASIC_INDUCT)
{
if (basic_induction_var (SET_SRC (set), GET_MODE (SET_SRC (set)),
- dest_reg, p, &inc_val, &mult_val))
+ dest_reg, p, &inc_val, &mult_val,
+ &location))
{
/* It is a possible basic induction variable.
Create and initialize an induction structure for it. */
@@ -3500,20 +3750,20 @@ strength_reduce (scan_start, end, loop_top, insn_count,
struct induction *v
= (struct induction *) alloca (sizeof (struct induction));
- record_biv (v, p, dest_reg, inc_val, mult_val,
+ record_biv (v, p, dest_reg, inc_val, mult_val, location,
not_every_iteration, maybe_multiple);
- reg_iv_type[REGNO (dest_reg)] = BASIC_INDUCT;
+ REG_IV_TYPE (REGNO (dest_reg)) = BASIC_INDUCT;
}
else if (REGNO (dest_reg) < max_reg_before_loop)
- reg_iv_type[REGNO (dest_reg)] = NOT_BASIC_INDUCT;
+ REG_IV_TYPE (REGNO (dest_reg)) = NOT_BASIC_INDUCT;
}
}
/* Past CODE_LABEL, we get to insns that may be executed multiple
times. The only way we can be sure that they can't is if every
jump insn between here and the end of the loop either
- returns, exits the loop, is a forward jump, or is a jump
- to the loop start. */
+ returns, exits the loop, is a jump to a location that is still
+ behind the label, or is a jump to the loop start. */
if (GET_CODE (p) == CODE_LABEL)
{
@@ -3541,10 +3791,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& (! condjump_p (insn)
|| (JUMP_LABEL (insn) != 0
&& JUMP_LABEL (insn) != scan_start
- && (INSN_UID (JUMP_LABEL (insn)) >= max_uid_for_loop
- || INSN_UID (insn) >= max_uid_for_loop
- || (INSN_LUID (JUMP_LABEL (insn))
- < INSN_LUID (insn))))))
+ && ! loop_insn_first_p (p, JUMP_LABEL (insn)))))
{
maybe_multiple = 1;
break;
@@ -3585,8 +3832,13 @@ strength_reduce (scan_start, end, loop_top, insn_count,
{
/* At the virtual top of a converted loop, insns are again known to
be executed each iteration: logically, the loop begins here
- even though the exit code has been duplicated. */
- if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP && loop_depth == 0)
+ even though the exit code has been duplicated.
+
+ Insns are also again known to be executed each iteration at
+ the LOOP_CONT note. */
+ if ((NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP
+ || NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_CONT)
+ && loop_depth == 0)
not_every_iteration = 0;
else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
loop_depth++;
@@ -3594,17 +3846,32 @@ strength_reduce (scan_start, end, loop_top, insn_count,
loop_depth--;
}
+ /* Note if we pass a loop latch. If we do, then we can not clear
+ NOT_EVERY_ITERATION below when we pass the last CODE_LABEL in
+ a loop since a jump before the last CODE_LABEL may have started
+ a new loop iteration.
+
+ Note that LOOP_TOP is only set for rotated loops and we need
+ this check for all loops, so compare against the CODE_LABEL
+ which immediately follows LOOP_START. */
+ if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == NEXT_INSN (loop_start))
+ past_loop_latch = 1;
+
/* Unlike in the code motion pass where MAYBE_NEVER indicates that
an insn may never be executed, NOT_EVERY_ITERATION indicates whether
or not an insn is known to be executed each iteration of the
loop, whether or not any iterations are known to occur.
Therefore, if we have just passed a label and have no more labels
- between here and the test insn of the loop, we know these insns
- will be executed each iteration. */
-
- if (not_every_iteration && GET_CODE (p) == CODE_LABEL
- && no_labels_between_p (p, loop_end))
+ between here and the test insn of the loop, and we have not passed
+ a jump to the top of the loop, then we know these insns will be
+ executed each iteration. */
+
+ if (not_every_iteration
+ && ! past_loop_latch
+ && GET_CODE (p) == CODE_LABEL
+ && no_labels_between_p (p, loop_end)
+ && loop_insn_first_p (p, loop_cont))
not_every_iteration = 0;
}
@@ -3612,10 +3879,10 @@ strength_reduce (scan_start, end, loop_top, insn_count,
Make a sanity check against n_times_set. */
for (backbl = &loop_iv_list, bl = *backbl; bl; bl = bl->next)
{
- if (reg_iv_type[bl->regno] != BASIC_INDUCT
+ if (REG_IV_TYPE (bl->regno) != BASIC_INDUCT
/* Above happens if register modified by subreg, etc. */
/* Make sure it is not recognized as a basic induction var: */
- || n_times_set[bl->regno] != bl->biv_count
+ || VARRAY_INT (n_times_set, bl->regno) != bl->biv_count
/* If never incremented, it is invariant that we decided not to
move. So leave it alone. */
|| ! bl->incremented)
@@ -3623,12 +3890,12 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (loop_dump_stream)
fprintf (loop_dump_stream, "Reg %d: biv discarded, %s\n",
bl->regno,
- (reg_iv_type[bl->regno] != BASIC_INDUCT
+ (REG_IV_TYPE (bl->regno) != BASIC_INDUCT
? "not induction variable"
: (! bl->incremented ? "never incremented"
: "count error")));
- reg_iv_type[bl->regno] = NOT_BASIC_INDUCT;
+ REG_IV_TYPE (bl->regno) = NOT_BASIC_INDUCT;
*backbl = bl->next;
}
else
@@ -3646,7 +3913,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Can still unroll the loop anyways, but indicate that there is no
strength reduction info available. */
if (unroll_p)
- unroll_loop (loop_end, insn_count, loop_start, end_insert_before, 0);
+ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
+ loop_info, 0);
return;
}
@@ -3694,7 +3962,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Look at the each biv and see if we can say anything better about its
initial value from any initializing insns set up above. (This is done
in two passes to avoid missing SETs in a PARALLEL.) */
- for (bl = loop_iv_list; bl; bl = bl->next)
+ for (backbl = &loop_iv_list; (bl = *backbl); backbl = &bl->next)
{
rtx src;
rtx note;
@@ -3739,14 +4007,356 @@ strength_reduce (scan_start, end, loop_top, insn_count,
}
else
{
- /* Biv initial value is not simple move,
- so let it keep initial value of "itself". */
+ struct iv_class *bl2 = 0;
+ rtx increment;
+
+ /* Biv initial value is not a simple move. If it is the sum of
+ another biv and a constant, check if both bivs are incremented
+ in lockstep. Then we are actually looking at a giv.
+ For simplicity, we only handle the case where there is but a
+ single increment, and the register is not used elsewhere. */
+ if (bl->biv_count == 1
+ && bl->regno < max_reg_before_loop
+ && uid_luid[REGNO_LAST_UID (bl->regno)] < INSN_LUID (loop_end)
+ && GET_CODE (src) == PLUS
+ && GET_CODE (XEXP (src, 0)) == REG
+ && CONSTANT_P (XEXP (src, 1))
+ && ((increment = biv_total_increment (bl, loop_start, loop_end))
+ != NULL_RTX))
+ {
+ int regno = REGNO (XEXP (src, 0));
- if (loop_dump_stream)
+ for (bl2 = loop_iv_list; bl2; bl2 = bl2->next)
+ if (bl2->regno == regno)
+ break;
+ }
+
+ /* Now, can we transform this biv into a giv? */
+ if (bl2
+ && bl2->biv_count == 1
+ && rtx_equal_p (increment,
+ biv_total_increment (bl2, loop_start, loop_end))
+ /* init_insn is only set to insns that are before loop_start
+ without any intervening labels. */
+ && ! reg_set_between_p (bl2->biv->src_reg,
+ PREV_INSN (bl->init_insn), loop_start)
+ /* The register from BL2 must be set before the register from
+ BL is set, or we must be able to move the latter set after
+ the former set. Currently there can't be any labels
+ in-between when biv_toal_increment returns nonzero both times
+ but we test it here in case some day some real cfg analysis
+ gets used to set always_computable. */
+ && ((loop_insn_first_p (bl2->biv->insn, bl->biv->insn)
+ && no_labels_between_p (bl2->biv->insn, bl->biv->insn))
+ || (! reg_used_between_p (bl->biv->src_reg, bl->biv->insn,
+ bl2->biv->insn)
+ && no_jumps_between_p (bl->biv->insn, bl2->biv->insn)))
+ && validate_change (bl->biv->insn,
+ &SET_SRC (single_set (bl->biv->insn)),
+ copy_rtx (src), 0))
+ {
+ int loop_num = uid_loop_num[INSN_UID (loop_start)];
+ rtx dominator = loop_number_cont_dominator[loop_num];
+ rtx giv = bl->biv->src_reg;
+ rtx giv_insn = bl->biv->insn;
+ rtx after_giv = NEXT_INSN (giv_insn);
+
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream, "is giv of biv %d\n", bl2->regno);
+ /* Let this giv be discovered by the generic code. */
+ REG_IV_TYPE (bl->regno) = UNKNOWN_INDUCT;
+ /* We can get better optimization if we can move the giv setting
+ before the first giv use. */
+ if (dominator
+ && ! loop_insn_first_p (dominator, scan_start)
+ && ! reg_set_between_p (bl2->biv->src_reg, loop_start,
+ dominator)
+ && ! reg_used_between_p (giv, loop_start, dominator)
+ && ! reg_used_between_p (giv, giv_insn, loop_end))
+ {
+ rtx p;
+ rtx next;
+
+ for (next = NEXT_INSN (dominator); ; next = NEXT_INSN (next))
+ {
+ if ((GET_RTX_CLASS (GET_CODE (next)) == 'i'
+ && (reg_mentioned_p (giv, PATTERN (next))
+ || reg_set_p (bl2->biv->src_reg, next)))
+ || GET_CODE (next) == JUMP_INSN)
+ break;
+#ifdef HAVE_cc0
+ if (GET_RTX_CLASS (GET_CODE (next)) != 'i'
+ || ! sets_cc0_p (PATTERN (next)))
+#endif
+ dominator = next;
+ }
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream, "move after insn %d\n",
+ INSN_UID (dominator));
+ /* Avoid problems with luids by actually moving the insn
+ and adjusting all luids in the range. */
+ reorder_insns (giv_insn, giv_insn, dominator);
+ for (p = dominator; INSN_UID (p) >= max_uid_for_loop; )
+ p = PREV_INSN (p);
+ compute_luids (giv_insn, after_giv, INSN_LUID (p));
+ /* If the only purpose of the init insn is to initialize
+ this giv, delete it. */
+ if (single_set (bl->init_insn)
+ && ! reg_used_between_p (giv, bl->init_insn, loop_start))
+ delete_insn (bl->init_insn);
+ }
+ else if (! loop_insn_first_p (bl2->biv->insn, bl->biv->insn))
+ {
+ rtx p = PREV_INSN (giv_insn);
+ while (INSN_UID (p) >= max_uid_for_loop)
+ p = PREV_INSN (p);
+ reorder_insns (giv_insn, giv_insn, bl2->biv->insn);
+ compute_luids (after_giv, NEXT_INSN (giv_insn),
+ INSN_LUID (p));
+ }
+ /* Remove this biv from the chain. */
+ if (bl->next)
+ *bl = *bl->next;
+ else
+ {
+ *backbl = 0;
+ break;
+ }
+ }
+
+ /* If we can't make it a giv,
+ let biv keep initial value of "itself". */
+ else if (loop_dump_stream)
fprintf (loop_dump_stream, "is complex\n");
}
}
+ /* If a biv is unconditionally incremented several times in a row, convert
+ all but the last increment into a giv. */
+
+ /* Get an upper bound for the number of registers
+ we might have after all bivs have been processed. */
+ first_increment_giv = max_reg_num ();
+ for (n_extra_increment = 0, bl = loop_iv_list; bl; bl = bl->next)
+ n_extra_increment += bl->biv_count - 1;
+
+ /* If the loop contains volatile memory references do not allow any
+ replacements to take place, since this could loose the volatile
+ markers.
+
+ Disabled for the gcc-2.95 release. There are still some problems with
+ giv recombination. We have a patch from Joern which should fix those
+ problems. But the patch is fairly complex and not really suitable for
+ the gcc-2.95 branch at this stage. */
+ if (0 && n_extra_increment && ! loop_has_volatile)
+
+ {
+ int nregs = first_increment_giv + n_extra_increment;
+
+ /* Reallocate reg_iv_type and reg_iv_info. */
+ VARRAY_GROW (reg_iv_type, nregs);
+ VARRAY_GROW (reg_iv_info, nregs);
+
+ for (bl = loop_iv_list; bl; bl = bl->next)
+ {
+ struct induction **vp, *v, *next;
+ int biv_dead_after_loop = 0;
+
+ /* The biv increments lists are in reverse order. Fix this first. */
+ for (v = bl->biv, bl->biv = 0; v; v = next)
+ {
+ next = v->next_iv;
+ v->next_iv = bl->biv;
+ bl->biv = v;
+ }
+
+ /* We must guard against the case that an early exit between v->insn
+ and next->insn leaves the biv live after the loop, since that
+ would mean that we'd be missing an increment for the final
+ value. The following test to set biv_dead_after_loop is like
+ the first part of the test to set bl->eliminable.
+ We don't check here if we can calculate the final value, since
+ this can't succeed if we already know that there is a jump
+ between v->insn and next->insn, yet next->always_executed is
+ set and next->maybe_multiple is cleared. Such a combination
+ implies that the jump destination is outside the loop.
+ If we want to make this check more sophisticated, we should
+ check each branch between v->insn and next->insn individually
+ to see if the biv is dead at its destination. */
+
+ if (uid_luid[REGNO_LAST_UID (bl->regno)] < INSN_LUID (loop_end)
+ && bl->init_insn
+ && INSN_UID (bl->init_insn) < max_uid_for_loop
+ && (uid_luid[REGNO_FIRST_UID (bl->regno)]
+ >= INSN_LUID (bl->init_insn))
+#ifdef HAVE_decrement_and_branch_until_zero
+ && ! bl->nonneg
+#endif
+ && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
+ biv_dead_after_loop = 1;
+
+ for (vp = &bl->biv, next = *vp; v = next, next = v->next_iv;)
+ {
+ HOST_WIDE_INT offset;
+ rtx set, add_val, old_reg, dest_reg, last_use_insn;
+ int old_regno, new_regno;
+
+ if (! v->always_executed
+ || v->maybe_multiple
+ || GET_CODE (v->add_val) != CONST_INT
+ || ! next->always_executed
+ || next->maybe_multiple
+ || ! CONSTANT_P (next->add_val)
+ || v->mult_val != const1_rtx
+ || next->mult_val != const1_rtx
+ || ! (biv_dead_after_loop
+ || no_jumps_between_p (v->insn, next->insn)))
+ {
+ vp = &v->next_iv;
+ continue;
+ }
+ offset = INTVAL (v->add_val);
+ set = single_set (v->insn);
+ add_val = plus_constant (next->add_val, offset);
+ old_reg = v->dest_reg;
+ dest_reg = gen_reg_rtx (v->mode);
+
+ /* Unlike reg_iv_type / reg_iv_info, the other three arrays
+ have been allocated with some slop space, so we may not
+ actually need to reallocate them. If we do, the following
+ if statement will be executed just once in this loop. */
+ if ((unsigned) max_reg_num () > n_times_set->num_elements)
+ {
+ /* Grow all the remaining arrays. */
+ VARRAY_GROW (set_in_loop, nregs);
+ VARRAY_GROW (n_times_set, nregs);
+ VARRAY_GROW (may_not_optimize, nregs);
+ VARRAY_GROW (reg_single_usage, nregs);
+ }
+
+ if (! validate_change (next->insn, next->location, add_val, 0))
+ {
+ vp = &v->next_iv;
+ continue;
+ }
+
+ /* Here we can try to eliminate the increment by combining
+ it into the uses. */
+
+ /* Set last_use_insn so that we can check against it. */
+
+ for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
+ p != next->insn;
+ p = next_insn_in_loop (p, scan_start, end, loop_top))
+ {
+ if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
+ continue;
+ if (reg_mentioned_p (old_reg, PATTERN (p)))
+ {
+ last_use_insn = p;
+ }
+ }
+
+ /* If we can't get the LUIDs for the insns, we can't
+ calculate the lifetime. This is likely from unrolling
+ of an inner loop, so there is little point in making this
+ a DEST_REG giv anyways. */
+ if (INSN_UID (v->insn) >= max_uid_for_loop
+ || INSN_UID (last_use_insn) >= max_uid_for_loop
+ || ! validate_change (v->insn, &SET_DEST (set), dest_reg, 0))
+ {
+ /* Change the increment at NEXT back to what it was. */
+ if (! validate_change (next->insn, next->location,
+ next->add_val, 0))
+ abort ();
+ vp = &v->next_iv;
+ continue;
+ }
+ next->add_val = add_val;
+ v->dest_reg = dest_reg;
+ v->giv_type = DEST_REG;
+ v->location = &SET_SRC (set);
+ v->cant_derive = 0;
+ v->combined_with = 0;
+ v->maybe_dead = 0;
+ v->derive_adjustment = 0;
+ v->same = 0;
+ v->ignore = 0;
+ v->new_reg = 0;
+ v->final_value = 0;
+ v->same_insn = 0;
+ v->auto_inc_opt = 0;
+ v->unrolled = 0;
+ v->shared = 0;
+ v->derived_from = 0;
+ v->always_computable = 1;
+ v->always_executed = 1;
+ v->replaceable = 1;
+ v->no_const_addval = 0;
+
+ old_regno = REGNO (old_reg);
+ new_regno = REGNO (dest_reg);
+ VARRAY_INT (set_in_loop, old_regno)--;
+ VARRAY_INT (set_in_loop, new_regno) = 1;
+ VARRAY_INT (n_times_set, old_regno)--;
+ VARRAY_INT (n_times_set, new_regno) = 1;
+ VARRAY_CHAR (may_not_optimize, new_regno) = 0;
+
+ REG_IV_TYPE (new_regno) = GENERAL_INDUCT;
+ REG_IV_INFO (new_regno) = v;
+
+ /* Remove the increment from the list of biv increments,
+ and record it as a giv. */
+ *vp = next;
+ bl->biv_count--;
+ v->next_iv = bl->giv;
+ bl->giv = v;
+ bl->giv_count++;
+ v->benefit = rtx_cost (SET_SRC (set), SET);
+ bl->total_benefit += v->benefit;
+
+ /* Now replace the biv with DEST_REG in all insns between
+ the replaced increment and the next increment, and
+ remember the last insn that needed a replacement. */
+ for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
+ p != next->insn;
+ p = next_insn_in_loop (p, scan_start, end, loop_top))
+ {
+ rtx note;
+
+ if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
+ continue;
+ if (reg_mentioned_p (old_reg, PATTERN (p)))
+ {
+ last_use_insn = p;
+ if (! validate_replace_rtx (old_reg, dest_reg, p))
+ abort ();
+ }
+ for (note = REG_NOTES (p); note; note = XEXP (note, 1))
+ {
+ if (GET_CODE (note) == EXPR_LIST)
+ XEXP (note, 0)
+ = replace_rtx (XEXP (note, 0), old_reg, dest_reg);
+ }
+ }
+
+ v->last_use = last_use_insn;
+ v->lifetime = INSN_LUID (v->insn) - INSN_LUID (last_use_insn);
+ /* If the lifetime is zero, it means that this register is really
+ a dead store. So mark this as a giv that can be ignored.
+ This will not prevent the biv from being eliminated. */
+ if (v->lifetime == 0)
+ v->ignore = 1;
+
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Increment %d of biv %d converted to giv %d.\n\n",
+ INSN_UID (v->insn), old_regno, new_regno);
+ }
+ }
+ }
+ last_increment_giv = max_reg_num () - 1;
+
/* Search the loop for general induction variables. */
/* A register is a giv if: it is only set once, it is a function of a
@@ -3776,62 +4386,50 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (GET_CODE (p) == INSN
&& (set = single_set (p))
&& GET_CODE (SET_DEST (set)) == REG
- && ! may_not_optimize[REGNO (SET_DEST (set))])
+ && ! VARRAY_CHAR (may_not_optimize, REGNO (SET_DEST (set))))
{
rtx src_reg;
rtx add_val;
rtx mult_val;
int benefit;
rtx regnote = 0;
+ rtx last_consec_insn;
dest_reg = SET_DEST (set);
if (REGNO (dest_reg) < FIRST_PSEUDO_REGISTER)
continue;
if (/* SET_SRC is a giv. */
- ((benefit = general_induction_var (SET_SRC (set),
- &src_reg, &add_val,
- &mult_val))
+ (general_induction_var (SET_SRC (set), &src_reg, &add_val,
+ &mult_val, 0, &benefit)
/* Equivalent expression is a giv. */
|| ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX))
- && (benefit = general_induction_var (XEXP (regnote, 0),
- &src_reg,
- &add_val, &mult_val))))
+ && general_induction_var (XEXP (regnote, 0), &src_reg,
+ &add_val, &mult_val, 0,
+ &benefit)))
/* Don't try to handle any regs made by loop optimization.
We have nothing on them in regno_first_uid, etc. */
&& REGNO (dest_reg) < max_reg_before_loop
/* Don't recognize a BASIC_INDUCT_VAR here. */
&& dest_reg != src_reg
/* This must be the only place where the register is set. */
- && (n_times_set[REGNO (dest_reg)] == 1
+ && (VARRAY_INT (n_times_set, REGNO (dest_reg)) == 1
/* or all sets must be consecutive and make a giv. */
|| (benefit = consec_sets_giv (benefit, p,
src_reg, dest_reg,
- &add_val, &mult_val))))
+ &add_val, &mult_val,
+ &last_consec_insn))))
{
- int count;
struct induction *v
= (struct induction *) alloca (sizeof (struct induction));
- rtx temp;
/* If this is a library call, increase benefit. */
if (find_reg_note (p, REG_RETVAL, NULL_RTX))
benefit += libcall_benefit (p);
/* Skip the consecutive insns, if there are any. */
- for (count = n_times_set[REGNO (dest_reg)] - 1;
- count > 0; count--)
- {
- /* If first insn of libcall sequence, skip to end.
- Do this at start of loop, since INSN is guaranteed to
- be an insn here. */
- if (GET_CODE (p) != NOTE
- && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
- p = XEXP (temp, 0);
-
- do p = NEXT_INSN (p);
- while (GET_CODE (p) == NOTE);
- }
+ if (VARRAY_INT (n_times_set, REGNO (dest_reg)) != 1)
+ p = last_consec_insn;
record_giv (v, p, src_reg, dest_reg, mult_val, add_val, benefit,
DEST_REG, not_every_iteration, NULL_PTR, loop_start,
@@ -3888,8 +4486,13 @@ strength_reduce (scan_start, end, loop_top, insn_count,
{
/* At the virtual top of a converted loop, insns are again known to
be executed each iteration: logically, the loop begins here
- even though the exit code has been duplicated. */
- if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP && loop_depth == 0)
+ even though the exit code has been duplicated.
+
+ Insns are also again known to be executed each iteration at
+ the LOOP_CONT note. */
+ if ((NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP
+ || NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_CONT)
+ && loop_depth == 0)
not_every_iteration = 0;
else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
loop_depth++;
@@ -3907,7 +4510,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
will be executed each iteration. */
if (not_every_iteration && GET_CODE (p) == CODE_LABEL
- && no_labels_between_p (p, loop_end))
+ && no_labels_between_p (p, loop_end)
+ && loop_insn_first_p (p, loop_cont))
not_every_iteration = 0;
}
@@ -3916,7 +4520,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
be called after all giv's have been identified, since otherwise it may
fail if the iteration variable is a giv. */
- loop_n_iterations = loop_iterations (loop_start, loop_end);
+ loop_iterations (loop_start, loop_end, loop_info);
/* Now for each giv for which we still don't know whether or not it is
replaceable, check to see if it is replaceable because its final value
@@ -3929,27 +4533,20 @@ strength_reduce (scan_start, end, loop_top, insn_count,
for (v = bl->giv; v; v = v->next_iv)
if (! v->replaceable && ! v->not_replaceable)
- check_final_value (v, loop_start, loop_end);
+ check_final_value (v, loop_start, loop_end, loop_info->n_iterations);
}
/* Try to prove that the loop counter variable (if any) is always
nonnegative; if so, record that fact with a REG_NONNEG note
so that "decrement and branch until zero" insn can be used. */
- check_dbra_loop (loop_end, insn_count, loop_start);
-
-#ifdef HAIFA
- /* record loop-variables relevant for BCT optimization before unrolling
- the loop. Unrolling may update part of this information, and the
- correct data will be used for generating the BCT. */
-#ifdef HAVE_decrement_and_branch_on_count
- if (HAVE_decrement_and_branch_on_count)
- analyze_loop_iterations (loop_start, loop_end);
-#endif
-#endif /* HAIFA */
+ check_dbra_loop (loop_end, insn_count, loop_start, loop_info);
- /* Create reg_map to hold substitutions for replaceable giv regs. */
- reg_map = (rtx *) alloca (max_reg_before_loop * sizeof (rtx));
- bzero ((char *) reg_map, max_reg_before_loop * sizeof (rtx));
+ /* Create reg_map to hold substitutions for replaceable giv regs.
+ Some givs might have been made from biv increments, so look at
+ reg_iv_type for a suitable size. */
+ reg_map_size = reg_iv_type->num_elements;
+ reg_map = (rtx *) alloca (reg_map_size * sizeof (rtx));
+ bzero ((char *) reg_map, reg_map_size * sizeof (rtx));
/* Examine each iv class for feasibility of strength reduction/induction
variable elimination. */
@@ -3960,6 +4557,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
int benefit;
int all_reduced;
rtx final_value = 0;
+ unsigned nregs;
/* Test whether it will be possible to eliminate this biv
provided all givs are reduced. This is possible if either
@@ -3985,7 +4583,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& ! bl->nonneg
#endif
&& ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
- || ((final_value = final_biv_value (bl, loop_start, loop_end))
+ || ((final_value = final_biv_value (bl, loop_start, loop_end,
+ loop_info->n_iterations))
#ifdef HAVE_decrement_and_branch_until_zero
&& ! bl->nonneg
#endif
@@ -4054,14 +4653,18 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (v->giv_type == DEST_ADDR
&& GET_CODE (v->mult_val) == CONST_INT)
{
-#if defined (HAVE_POST_INCREMENT) || defined (HAVE_PRE_INCREMENT)
- if (INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
+ if (HAVE_POST_INCREMENT
+ && INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
benefit += add_cost * bl->biv_count;
-#endif
-#if defined (HAVE_POST_DECREMENT) || defined (HAVE_PRE_DECREMENT)
- if (-INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
+ else if (HAVE_PRE_INCREMENT
+ && INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
+ benefit += add_cost * bl->biv_count;
+ else if (HAVE_POST_DECREMENT
+ && -INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
+ benefit += add_cost * bl->biv_count;
+ else if (HAVE_PRE_DECREMENT
+ && -INTVAL (v->mult_val) == GET_MODE_SIZE (v->mem_mode))
benefit += add_cost * bl->biv_count;
-#endif
}
#endif
@@ -4105,6 +4708,60 @@ strength_reduce (scan_start, end, loop_top, insn_count,
}
}
+ /* Check for givs whose first use is their definition and whose
+ last use is the definition of another giv. If so, it is likely
+ dead and should not be used to derive another giv nor to
+ eliminate a biv. */
+ for (v = bl->giv; v; v = v->next_iv)
+ {
+ if (v->ignore
+ || (v->same && v->same->ignore))
+ continue;
+
+ if (v->last_use)
+ {
+ struct induction *v1;
+
+ for (v1 = bl->giv; v1; v1 = v1->next_iv)
+ if (v->last_use == v1->insn)
+ v->maybe_dead = 1;
+ }
+ else if (v->giv_type == DEST_REG
+ && REGNO_FIRST_UID (REGNO (v->dest_reg)) == INSN_UID (v->insn))
+ {
+ struct induction *v1;
+
+ for (v1 = bl->giv; v1; v1 = v1->next_iv)
+ if (REGNO_LAST_UID (REGNO (v->dest_reg)) == INSN_UID (v1->insn))
+ v->maybe_dead = 1;
+ }
+ }
+
+ /* Now that we know which givs will be reduced, try to rearrange the
+ combinations to reduce register pressure.
+ recombine_givs calls find_life_end, which needs reg_iv_type and
+ reg_iv_info to be valid for all pseudos. We do the necessary
+ reallocation here since it allows to check if there are still
+ more bivs to process. */
+ nregs = max_reg_num ();
+ if (nregs > reg_iv_type->num_elements)
+ {
+ /* If there are still more bivs to process, allocate some slack
+ space so that we're not constantly reallocating these arrays. */
+ if (bl->next)
+ nregs += nregs / 4;
+ /* Reallocate reg_iv_type and reg_iv_info. */
+ VARRAY_GROW (reg_iv_type, nregs);
+ VARRAY_GROW (reg_iv_info, nregs);
+ }
+#if 0
+ /* Disabled for the gcc-2.95 release. There are still some problems with
+ giv recombination. We have a patch from Joern which should fix those
+ problems. But the patch is fairly complex and not really suitable for
+ the gcc-2.95 branch at this stage. */
+ recombine_givs (bl, loop_start, loop_end, unroll_p);
+#endif
+
/* Reduce each giv that we decided to reduce. */
for (v = bl->giv; v; v = v->next_iv)
@@ -4114,7 +4771,41 @@ strength_reduce (scan_start, end, loop_top, insn_count,
{
int auto_inc_opt = 0;
- v->new_reg = gen_reg_rtx (v->mode);
+ /* If the code for derived givs immediately below has already
+ allocated a new_reg, we must keep it. */
+ if (! v->new_reg)
+ v->new_reg = gen_reg_rtx (v->mode);
+
+ if (v->derived_from)
+ {
+ struct induction *d = v->derived_from;
+
+ /* In case d->dest_reg is not replaceable, we have
+ to replace it in v->insn now. */
+ if (! d->new_reg)
+ d->new_reg = gen_reg_rtx (d->mode);
+ PATTERN (v->insn)
+ = replace_rtx (PATTERN (v->insn), d->dest_reg, d->new_reg);
+ PATTERN (v->insn)
+ = replace_rtx (PATTERN (v->insn), v->dest_reg, v->new_reg);
+ if (bl->biv_count != 1)
+ {
+ /* For each place where the biv is incremented, add an
+ insn to set the new, reduced reg for the giv. */
+ for (tv = bl->biv; tv; tv = tv->next_iv)
+ {
+ /* We always emit reduced giv increments before the
+ biv increment when bl->biv_count != 1. So by
+ emitting the add insns for derived givs after the
+ biv increment, they pick up the updated value of
+ the reduced giv. */
+ emit_insn_after (copy_rtx (PATTERN (v->insn)),
+ tv->insn);
+
+ }
+ }
+ continue;
+ }
#ifdef AUTO_INC_DEC
/* If the target has auto-increment addressing modes, and
@@ -4228,11 +4919,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
For each giv register that can be reduced now: if replaceable,
substitute reduced reg wherever the old giv occurs;
- else add new move insn "giv_reg = reduced_reg".
+ else add new move insn "giv_reg = reduced_reg". */
- Also check for givs whose first use is their definition and whose
- last use is the definition of another giv. If so, it is likely
- dead and should not be used to eliminate a biv. */
for (v = bl->giv; v; v = v->next_iv)
{
if (v->same && v->same->ignore)
@@ -4241,16 +4929,6 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (v->ignore)
continue;
- if (v->giv_type == DEST_REG
- && REGNO_FIRST_UID (REGNO (v->dest_reg)) == INSN_UID (v->insn))
- {
- struct induction *v1;
-
- for (v1 = bl->giv; v1; v1 = v1->next_iv)
- if (REGNO_LAST_UID (REGNO (v->dest_reg)) == INSN_UID (v1->insn))
- v->maybe_dead = 1;
- }
-
/* Update expression if this was combined, in case other giv was
replaced. */
if (v->same)
@@ -4434,8 +5112,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
|| GET_CODE (p) == CALL_INSN)
{
- replace_regs (PATTERN (p), reg_map, max_reg_before_loop, 0);
- replace_regs (REG_NOTES (p), reg_map, max_reg_before_loop, 0);
+ replace_regs (PATTERN (p), reg_map, reg_map_size, 0);
+ replace_regs (REG_NOTES (p), reg_map, reg_map_size, 0);
INSN_CODE (p) = -1;
}
@@ -4444,18 +5122,20 @@ strength_reduce (scan_start, end, loop_top, insn_count,
collected. */
if (unroll_p)
- unroll_loop (loop_end, insn_count, loop_start, end_insert_before, 1);
+ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
+ loop_info, 1);
-#ifdef HAIFA
- /* instrument the loop with bct insn */
#ifdef HAVE_decrement_and_branch_on_count
- if (HAVE_decrement_and_branch_on_count)
- insert_bct (loop_start, loop_end);
-#endif
-#endif /* HAIFA */
+ /* Instrument the loop with BCT insn. */
+ if (HAVE_decrement_and_branch_on_count && bct_p
+ && flag_branch_on_count_reg)
+ insert_bct (loop_start, loop_end, loop_info);
+#endif /* HAVE_decrement_and_branch_on_count */
if (loop_dump_stream)
fprintf (loop_dump_stream, "\n");
+ VARRAY_FREE (reg_iv_type);
+ VARRAY_FREE (reg_iv_info);
}
/* Return 1 if X is a valid source for an initial value (or as value being
@@ -4540,12 +5220,13 @@ find_mem_givs (x, insn, not_every_iteration, loop_start, loop_end)
rtx mult_val;
int benefit;
- benefit = general_induction_var (XEXP (x, 0),
- &src_reg, &add_val, &mult_val);
+ /* This code used to disable creating GIVs with mult_val == 1 and
+ add_val == 0. However, this leads to lost optimizations when
+ it comes time to combine a set of related DEST_ADDR GIVs, since
+ this one would not be seen. */
- /* Don't make a DEST_ADDR giv with mult_val == 1 && add_val == 0.
- Such a giv isn't useful. */
- if (benefit > 0 && (mult_val != const1_rtx || add_val != const0_rtx))
+ if (general_induction_var (XEXP (x, 0), &src_reg, &add_val,
+ &mult_val, 1, &benefit))
{
/* Found one; record it. */
struct induction *v
@@ -4594,13 +5275,14 @@ find_mem_givs (x, insn, not_every_iteration, loop_start, loop_end)
executed exactly once per iteration. */
static void
-record_biv (v, insn, dest_reg, inc_val, mult_val,
+record_biv (v, insn, dest_reg, inc_val, mult_val, location,
not_every_iteration, maybe_multiple)
struct induction *v;
rtx insn;
rtx dest_reg;
rtx inc_val;
rtx mult_val;
+ rtx *location;
int not_every_iteration;
int maybe_multiple;
{
@@ -4611,6 +5293,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val,
v->dest_reg = dest_reg;
v->mult_val = mult_val;
v->add_val = inc_val;
+ v->location = location;
v->mode = GET_MODE (dest_reg);
v->always_computable = ! not_every_iteration;
v->always_executed = ! not_every_iteration;
@@ -4731,6 +5414,8 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
v->auto_inc_opt = 0;
v->unrolled = 0;
v->shared = 0;
+ v->derived_from = 0;
+ v->last_use = 0;
/* The v->always_computable field is used in update_giv_derive, to
determine whether a giv can be used to derive another giv. For a
@@ -4751,7 +5436,6 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
{
v->mode = GET_MODE (*location);
v->lifetime = 1;
- v->times_used = 1;
}
else /* type == DEST_REG */
{
@@ -4760,16 +5444,14 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
v->lifetime = (uid_luid[REGNO_LAST_UID (REGNO (dest_reg))]
- uid_luid[REGNO_FIRST_UID (REGNO (dest_reg))]);
- v->times_used = n_times_used[REGNO (dest_reg)];
-
/* If the lifetime is zero, it means that this register is
really a dead store. So mark this as a giv that can be
ignored. This will not prevent the biv from being eliminated. */
if (v->lifetime == 0)
v->ignore = 1;
- reg_iv_type[REGNO (dest_reg)] = GENERAL_INDUCT;
- reg_iv_info[REGNO (dest_reg)] = v;
+ REG_IV_TYPE (REGNO (dest_reg)) = GENERAL_INDUCT;
+ REG_IV_INFO (REGNO (dest_reg)) = v;
}
/* Add the giv to the class of givs computed from one biv. */
@@ -4858,6 +5540,32 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
}
}
+ /* Record whether the add_val contains a const_int, for later use by
+ combine_givs. */
+ {
+ rtx tem = add_val;
+
+ v->no_const_addval = 1;
+ if (tem == const0_rtx)
+ ;
+ else if (GET_CODE (tem) == CONST_INT)
+ v->no_const_addval = 0;
+ else if (GET_CODE (tem) == PLUS)
+ {
+ while (1)
+ {
+ if (GET_CODE (XEXP (tem, 0)) == PLUS)
+ tem = XEXP (tem, 0);
+ else if (GET_CODE (XEXP (tem, 1)) == PLUS)
+ tem = XEXP (tem, 1);
+ else
+ break;
+ }
+ if (GET_CODE (XEXP (tem, 1)) == CONST_INT)
+ v->no_const_addval = 0;
+ }
+ }
+
if (loop_dump_stream)
{
if (type == DEST_REG)
@@ -4869,12 +5577,15 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
fprintf (loop_dump_stream, " src reg %d benefit %d",
REGNO (src_reg), v->benefit);
- fprintf (loop_dump_stream, " used %d lifetime %d",
- v->times_used, v->lifetime);
+ fprintf (loop_dump_stream, " lifetime %d",
+ v->lifetime);
if (v->replaceable)
fprintf (loop_dump_stream, " replaceable");
+ if (v->no_const_addval)
+ fprintf (loop_dump_stream, " ncav");
+
if (GET_CODE (mult_val) == CONST_INT)
{
fprintf (loop_dump_stream, " mult ");
@@ -4911,9 +5622,10 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
have been identified. */
static void
-check_final_value (v, loop_start, loop_end)
+check_final_value (v, loop_start, loop_end, n_iterations)
struct induction *v;
rtx loop_start, loop_end;
+ unsigned HOST_WIDE_INT n_iterations;
{
struct iv_class *bl;
rtx final_value = 0;
@@ -4940,7 +5652,7 @@ check_final_value (v, loop_start, loop_end)
v->replaceable = 0;
#endif
- if ((final_value = final_giv_value (v, loop_start, loop_end))
+ if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations))
&& (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn)))
{
int biv_increment_seen = 0;
@@ -5013,13 +5725,10 @@ check_final_value (v, loop_start, loop_end)
if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
&& LABEL_NAME (JUMP_LABEL (p))
- && ((INSN_UID (JUMP_LABEL (p)) >= max_uid_for_loop)
- || (INSN_UID (v->insn) >= max_uid_for_loop)
- || (INSN_UID (last_giv_use) >= max_uid_for_loop)
- || (INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (v->insn)
- && INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (loop_start))
- || (INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (last_giv_use)
- && INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (loop_end))))
+ && ((loop_insn_first_p (JUMP_LABEL (p), v->insn)
+ && loop_insn_first_p (loop_start, JUMP_LABEL (p)))
+ || (loop_insn_first_p (last_giv_use, JUMP_LABEL (p))
+ && loop_insn_first_p (JUMP_LABEL (p), loop_end))))
{
v->replaceable = 0;
v->not_replaceable = 1;
@@ -5154,7 +5863,8 @@ update_giv_derive (p)
REG = INVARIANT + REG
If X is suitable, we return 1, set *MULT_VAL to CONST1_RTX,
- and store the additive term into *INC_VAL.
+ store the additive term into *INC_VAL, and store the place where
+ we found the additive term into *LOCATION.
If X is an assignment of an invariant into DEST_REG, we set
*MULT_VAL to CONST0_RTX, and store the invariant into *INC_VAL.
@@ -5181,40 +5891,47 @@ update_giv_derive (p)
If we cannot find a biv, we return 0. */
static int
-basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val)
+basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
register rtx x;
enum machine_mode mode;
rtx p;
rtx dest_reg;
rtx *inc_val;
rtx *mult_val;
+ rtx **location;
{
register enum rtx_code code;
- rtx arg;
+ rtx *argp, arg;
rtx insn, set = 0;
code = GET_CODE (x);
switch (code)
{
case PLUS:
- if (XEXP (x, 0) == dest_reg
+ if (rtx_equal_p (XEXP (x, 0), dest_reg)
|| (GET_CODE (XEXP (x, 0)) == SUBREG
&& SUBREG_PROMOTED_VAR_P (XEXP (x, 0))
&& SUBREG_REG (XEXP (x, 0)) == dest_reg))
- arg = XEXP (x, 1);
- else if (XEXP (x, 1) == dest_reg
+ {
+ argp = &XEXP (x, 1);
+ }
+ else if (rtx_equal_p (XEXP (x, 1), dest_reg)
|| (GET_CODE (XEXP (x, 1)) == SUBREG
&& SUBREG_PROMOTED_VAR_P (XEXP (x, 1))
&& SUBREG_REG (XEXP (x, 1)) == dest_reg))
- arg = XEXP (x, 0);
+ {
+ argp = &XEXP (x, 0);
+ }
else
return 0;
+ arg = *argp;
if (invariant_p (arg) != 1)
return 0;
*inc_val = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
*mult_val = const1_rtx;
+ *location = argp;
return 1;
case SUBREG:
@@ -5222,34 +5939,40 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val)
value. */
if (SUBREG_PROMOTED_VAR_P (x))
return basic_induction_var (SUBREG_REG (x), GET_MODE (SUBREG_REG (x)),
- dest_reg, p, inc_val, mult_val);
+ dest_reg, p, inc_val, mult_val, location);
return 0;
case REG:
- /* If this register is assigned in the previous insn, look at its
+ /* If this register is assigned in a previous insn, look at its
source, but don't go outside the loop or past a label. */
- for (insn = PREV_INSN (p);
- (insn && GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
- insn = PREV_INSN (insn))
- ;
+ insn = p;
+ while (1)
+ {
+ do {
+ insn = PREV_INSN (insn);
+ } while (insn && GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
- if (insn)
- set = single_set (insn);
+ if (!insn)
+ break;
+ set = single_set (insn);
+ if (set == 0)
+ break;
- if (set != 0
- && (SET_DEST (set) == x
- || (GET_CODE (SET_DEST (set)) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
- <= UNITS_PER_WORD)
- && SUBREG_REG (SET_DEST (set)) == x)))
- return basic_induction_var (SET_SRC (set),
- (GET_MODE (SET_SRC (set)) == VOIDmode
- ? GET_MODE (x)
- : GET_MODE (SET_SRC (set))),
- dest_reg, insn,
- inc_val, mult_val);
+ if ((SET_DEST (set) == x
+ || (GET_CODE (SET_DEST (set)) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
+ <= UNITS_PER_WORD)
+ && SUBREG_REG (SET_DEST (set)) == x))
+ && basic_induction_var (SET_SRC (set),
+ (GET_MODE (SET_SRC (set)) == VOIDmode
+ ? GET_MODE (x)
+ : GET_MODE (SET_SRC (set))),
+ dest_reg, insn,
+ inc_val, mult_val, location))
+ return 1;
+ }
/* ... fall through ... */
/* Can accept constant setting of biv only when inside inner most loop.
@@ -5279,7 +6002,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val)
case SIGN_EXTEND:
return basic_induction_var (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
- dest_reg, p, inc_val, mult_val);
+ dest_reg, p, inc_val, mult_val, location);
+
case ASHIFTRT:
/* Similar, since this can be a sign extension. */
for (insn = PREV_INSN (p);
@@ -5298,7 +6022,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val)
&& XEXP (x, 1) == XEXP (SET_SRC (set), 1))
return basic_induction_var (XEXP (SET_SRC (set), 0),
GET_MODE (XEXP (x, 0)),
- dest_reg, insn, inc_val, mult_val);
+ dest_reg, insn, inc_val, mult_val,
+ location);
return 0;
default:
@@ -5321,14 +6046,15 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val)
such that the value of X is biv * mult + add; */
static int
-general_induction_var (x, src_reg, add_val, mult_val)
+general_induction_var (x, src_reg, add_val, mult_val, is_addr, pbenefit)
rtx x;
rtx *src_reg;
rtx *add_val;
rtx *mult_val;
+ int is_addr;
+ int *pbenefit;
{
rtx orig_x = x;
- int benefit = 0;
char *storage;
/* If this is an invariant, forget it, it isn't a giv. */
@@ -5338,7 +6064,8 @@ general_induction_var (x, src_reg, add_val, mult_val)
/* See if the expression could be a giv and get its form.
Mark our place on the obstack in case we don't find a giv. */
storage = (char *) oballoc (0);
- x = simplify_giv_expr (x, &benefit);
+ *pbenefit = 0;
+ x = simplify_giv_expr (x, pbenefit);
if (x == 0)
{
obfree (storage);
@@ -5398,12 +6125,21 @@ general_induction_var (x, src_reg, add_val, mult_val)
if (GET_CODE (*mult_val) == USE)
*mult_val = XEXP (*mult_val, 0);
- benefit += rtx_cost (orig_x, SET);
+ if (is_addr)
+ {
+#ifdef ADDRESS_COST
+ *pbenefit += ADDRESS_COST (orig_x) - reg_address_cost;
+#else
+ *pbenefit += rtx_cost (orig_x, MEM) - reg_address_cost;
+#endif
+ }
+ else
+ *pbenefit += rtx_cost (orig_x, SET);
- /* Always return some benefit if this is a giv so it will be detected
- as such. This allows elimination of bivs that might otherwise
- not be eliminated. */
- return benefit == 0 ? 1 : benefit;
+ /* Always return true if this is a giv so it will be detected as such,
+ even if the benefit is zero or negative. This allows elimination
+ of bivs that might otherwise not be eliminated. */
+ return 1;
}
/* Given an expression, X, try to form it as a linear function of a biv.
@@ -5426,6 +6162,9 @@ general_induction_var (x, src_reg, add_val, mult_val)
*BENEFIT will be incremented by the benefit of any sub-giv encountered. */
+static rtx sge_plus PROTO ((enum machine_mode, rtx, rtx));
+static rtx sge_plus_constant PROTO ((rtx, rtx));
+
static rtx
simplify_giv_expr (x, benefit)
rtx x;
@@ -5440,7 +6179,7 @@ simplify_giv_expr (x, benefit)
if (mode != VOIDmode
&& (GET_MODE_CLASS (mode) != MODE_INT
|| GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT))
- return 0;
+ return NULL_RTX;
switch (GET_CODE (x))
{
@@ -5448,12 +6187,14 @@ simplify_giv_expr (x, benefit)
arg0 = simplify_giv_expr (XEXP (x, 0), benefit);
arg1 = simplify_giv_expr (XEXP (x, 1), benefit);
if (arg0 == 0 || arg1 == 0)
- return 0;
+ return NULL_RTX;
/* Put constant last, CONST_INT last if both constant. */
if ((GET_CODE (arg0) == USE
|| GET_CODE (arg0) == CONST_INT)
- && GET_CODE (arg1) != CONST_INT)
+ && ! ((GET_CODE (arg0) == USE
+ && GET_CODE (arg1) == USE)
+ || GET_CODE (arg1) == CONST_INT))
tem = arg0, arg0 = arg1, arg1 = tem;
/* Handle addition of zero, then addition of an invariant. */
@@ -5464,29 +6205,22 @@ simplify_giv_expr (x, benefit)
{
case CONST_INT:
case USE:
- /* Both invariant. Only valid if sum is machine operand.
- First strip off possible USE on the operands. */
+ /* Adding two invariants must result in an invariant, so enclose
+ addition operation inside a USE and return it. */
if (GET_CODE (arg0) == USE)
arg0 = XEXP (arg0, 0);
-
if (GET_CODE (arg1) == USE)
arg1 = XEXP (arg1, 0);
- tem = 0;
- if (CONSTANT_P (arg0) && GET_CODE (arg1) == CONST_INT)
- {
- tem = plus_constant (arg0, INTVAL (arg1));
- if (GET_CODE (tem) != CONST_INT)
- tem = gen_rtx_USE (mode, tem);
- }
+ if (GET_CODE (arg0) == CONST_INT)
+ tem = arg0, arg0 = arg1, arg1 = tem;
+ if (GET_CODE (arg1) == CONST_INT)
+ tem = sge_plus_constant (arg0, arg1);
else
- {
- /* Adding two invariants must result in an invariant,
- so enclose addition operation inside a USE and
- return it. */
- tem = gen_rtx_USE (mode, gen_rtx_PLUS (mode, arg0, arg1));
- }
+ tem = sge_plus (mode, arg0, arg1);
+ if (GET_CODE (tem) != CONST_INT)
+ tem = gen_rtx_USE (mode, tem);
return tem;
case REG:
@@ -5496,11 +6230,10 @@ simplify_giv_expr (x, benefit)
case PLUS:
/* (a + invar_1) + invar_2. Associate. */
- return simplify_giv_expr (gen_rtx_PLUS (mode,
- XEXP (arg0, 0),
- gen_rtx_PLUS (mode,
- XEXP (arg0, 1), arg1)),
- benefit);
+ return simplify_giv_expr (
+ gen_rtx_PLUS (mode, XEXP (arg0, 0),
+ gen_rtx_PLUS (mode, XEXP (arg0, 1), arg1)),
+ benefit);
default:
abort ();
@@ -5528,10 +6261,10 @@ simplify_giv_expr (x, benefit)
/* Now must have MULT + MULT. Distribute if same biv, else not giv. */
if (GET_CODE (arg0) != MULT || GET_CODE (arg1) != MULT)
- abort ();
+ return NULL_RTX;
- if (XEXP (arg0, 0) != XEXP (arg1, 0))
- return 0;
+ if (!rtx_equal_p (arg0, arg1))
+ return NULL_RTX;
return simplify_giv_expr (gen_rtx_MULT (mode,
XEXP (arg0, 0),
@@ -5552,7 +6285,7 @@ simplify_giv_expr (x, benefit)
arg0 = simplify_giv_expr (XEXP (x, 0), benefit);
arg1 = simplify_giv_expr (XEXP (x, 1), benefit);
if (arg0 == 0 || arg1 == 0)
- return 0;
+ return NULL_RTX;
/* Put constant last, CONST_INT last if both constant. */
if ((GET_CODE (arg0) == USE || GET_CODE (arg0) == CONST_INT)
@@ -5561,7 +6294,7 @@ simplify_giv_expr (x, benefit)
/* If second argument is not now constant, not giv. */
if (GET_CODE (arg1) != USE && GET_CODE (arg1) != CONST_INT)
- return 0;
+ return NULL_RTX;
/* Handle multiply by 0 or 1. */
if (arg1 == const0_rtx)
@@ -5581,8 +6314,25 @@ simplify_giv_expr (x, benefit)
return GEN_INT (INTVAL (arg0) * INTVAL (arg1));
case USE:
- /* invar * invar. Not giv. */
- return 0;
+ /* invar * invar. It is a giv, but very few of these will
+ actually pay off, so limit to simple registers. */
+ if (GET_CODE (arg1) != CONST_INT)
+ return NULL_RTX;
+
+ arg0 = XEXP (arg0, 0);
+ if (GET_CODE (arg0) == REG)
+ tem = gen_rtx_MULT (mode, arg0, arg1);
+ else if (GET_CODE (arg0) == MULT
+ && GET_CODE (XEXP (arg0, 0)) == REG
+ && GET_CODE (XEXP (arg0, 1)) == CONST_INT)
+ {
+ tem = gen_rtx_MULT (mode, XEXP (arg0, 0),
+ GEN_INT (INTVAL (XEXP (arg0, 1))
+ * INTVAL (arg1)));
+ }
+ else
+ return NULL_RTX;
+ return gen_rtx_USE (mode, tem);
case MULT:
/* (a * invar_1) * invar_2. Associate. */
@@ -5640,13 +6390,13 @@ simplify_giv_expr (x, benefit)
return 0;
/* Check for biv or giv. */
- switch (reg_iv_type[REGNO (x)])
+ switch (REG_IV_TYPE (REGNO (x)))
{
case BASIC_INDUCT:
return x;
case GENERAL_INDUCT:
{
- struct induction *v = reg_iv_info[REGNO (x)];
+ struct induction *v = REG_IV_INFO (REGNO (x));
/* Form expression from giv and add benefit. Ensure this giv
can derive another and subtract any needed adjustment if so. */
@@ -5663,6 +6413,72 @@ simplify_giv_expr (x, benefit)
}
default:
+ /* If it isn't an induction variable, and it is invariant, we
+ may be able to simplify things further by looking through
+ the bits we just moved outside the loop. */
+ if (invariant_p (x) == 1)
+ {
+ struct movable *m;
+
+ for (m = the_movables; m ; m = m->next)
+ if (rtx_equal_p (x, m->set_dest))
+ {
+ /* Ok, we found a match. Substitute and simplify. */
+
+ /* If we match another movable, we must use that, as
+ this one is going away. */
+ if (m->match)
+ return simplify_giv_expr (m->match->set_dest, benefit);
+
+ /* If consec is non-zero, this is a member of a group of
+ instructions that were moved together. We handle this
+ case only to the point of seeking to the last insn and
+ looking for a REG_EQUAL. Fail if we don't find one. */
+ if (m->consec != 0)
+ {
+ int i = m->consec;
+ tem = m->insn;
+ do { tem = NEXT_INSN (tem); } while (--i > 0);
+
+ tem = find_reg_note (tem, REG_EQUAL, NULL_RTX);
+ if (tem)
+ tem = XEXP (tem, 0);
+ }
+ else
+ {
+ tem = single_set (m->insn);
+ if (tem)
+ tem = SET_SRC (tem);
+ }
+
+ if (tem)
+ {
+ /* What we are most interested in is pointer
+ arithmetic on invariants -- only take
+ patterns we may be able to do something with. */
+ if (GET_CODE (tem) == PLUS
+ || GET_CODE (tem) == MULT
+ || GET_CODE (tem) == ASHIFT
+ || GET_CODE (tem) == CONST_INT
+ || GET_CODE (tem) == SYMBOL_REF)
+ {
+ tem = simplify_giv_expr (tem, benefit);
+ if (tem)
+ return tem;
+ }
+ else if (GET_CODE (tem) == CONST
+ && GET_CODE (XEXP (tem, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (tem, 0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)
+ {
+ tem = simplify_giv_expr (XEXP (tem, 0), benefit);
+ if (tem)
+ return tem;
+ }
+ }
+ break;
+ }
+ }
break;
}
@@ -5677,13 +6493,67 @@ simplify_giv_expr (x, benefit)
{
if (GET_CODE (x) == CONST_INT)
return x;
- else
- return gen_rtx_USE (mode, x);
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ x = XEXP (x, 0);
+ return gen_rtx_USE (mode, x);
}
else
return 0;
}
}
+
+/* This routine folds invariants such that there is only ever one
+ CONST_INT in the summation. It is only used by simplify_giv_expr. */
+
+static rtx
+sge_plus_constant (x, c)
+ rtx x, c;
+{
+ if (GET_CODE (x) == CONST_INT)
+ return GEN_INT (INTVAL (x) + INTVAL (c));
+ else if (GET_CODE (x) != PLUS)
+ return gen_rtx_PLUS (GET_MODE (x), x, c);
+ else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ return gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+ GEN_INT (INTVAL (XEXP (x, 1)) + INTVAL (c)));
+ }
+ else if (GET_CODE (XEXP (x, 0)) == PLUS
+ || GET_CODE (XEXP (x, 1)) != PLUS)
+ {
+ return gen_rtx_PLUS (GET_MODE (x),
+ sge_plus_constant (XEXP (x, 0), c), XEXP (x, 1));
+ }
+ else
+ {
+ return gen_rtx_PLUS (GET_MODE (x),
+ sge_plus_constant (XEXP (x, 1), c), XEXP (x, 0));
+ }
+}
+
+static rtx
+sge_plus (mode, x, y)
+ enum machine_mode mode;
+ rtx x, y;
+{
+ while (GET_CODE (y) == PLUS)
+ {
+ rtx a = XEXP (y, 0);
+ if (GET_CODE (a) == CONST_INT)
+ x = sge_plus_constant (x, a);
+ else
+ x = gen_rtx_PLUS (mode, x, a);
+ y = XEXP (y, 1);
+ }
+ if (GET_CODE (y) == CONST_INT)
+ x = sge_plus_constant (x, y);
+ else
+ x = gen_rtx_PLUS (mode, x, y);
+ return x;
+}
/* Help detect a giv that is calculated by several consecutive insns;
for example,
@@ -5706,13 +6576,14 @@ simplify_giv_expr (x, benefit)
static int
consec_sets_giv (first_benefit, p, src_reg, dest_reg,
- add_val, mult_val)
+ add_val, mult_val, last_consec_insn)
int first_benefit;
rtx p;
rtx src_reg;
rtx dest_reg;
rtx *add_val;
rtx *mult_val;
+ rtx *last_consec_insn;
{
int count;
enum rtx_code code;
@@ -5736,10 +6607,10 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg,
v->cant_derive = 0;
v->derive_adjustment = 0;
- reg_iv_type[REGNO (dest_reg)] = GENERAL_INDUCT;
- reg_iv_info[REGNO (dest_reg)] = v;
+ REG_IV_TYPE (REGNO (dest_reg)) = GENERAL_INDUCT;
+ REG_IV_INFO (REGNO (dest_reg)) = v;
- count = n_times_set[REGNO (dest_reg)] - 1;
+ count = VARRAY_INT (n_times_set, REGNO (dest_reg)) - 1;
while (count > 0)
{
@@ -5754,12 +6625,12 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg,
&& (set = single_set (p))
&& GET_CODE (SET_DEST (set)) == REG
&& SET_DEST (set) == dest_reg
- && ((benefit = general_induction_var (SET_SRC (set), &src_reg,
- add_val, mult_val))
+ && (general_induction_var (SET_SRC (set), &src_reg,
+ add_val, mult_val, 0, &benefit)
/* Giv created by equivalent expression. */
|| ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))
- && (benefit = general_induction_var (XEXP (temp, 0), &src_reg,
- add_val, mult_val))))
+ && general_induction_var (XEXP (temp, 0), &src_reg,
+ add_val, mult_val, 0, &benefit)))
&& src_reg == v->src_reg)
{
if (find_reg_note (p, REG_RETVAL, NULL_RTX))
@@ -5781,11 +6652,12 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg,
&& CONSTANT_P (SET_SRC (set)))
continue;
- reg_iv_type[REGNO (dest_reg)] = UNKNOWN_INDUCT;
+ REG_IV_TYPE (REGNO (dest_reg)) = UNKNOWN_INDUCT;
return 0;
}
}
+ *last_consec_insn = p;
return v->benefit;
}
@@ -5794,14 +6666,111 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg,
it cannot possibly be a valid address, 0 is returned.
To perform the computation, we note that
- G1 = a * v + b and
- G2 = c * v + d
+ G1 = x * v + a and
+ G2 = y * v + b
where `v' is the biv.
- So G2 = (c/a) * G1 + (d - b*c/a) */
+ So G2 = (y/b) * G1 + (b - a*y/x).
+
+ Note that MULT = y/x.
+
+ Update: A and B are now allowed to be additive expressions such that
+ B contains all variables in A. That is, computing B-A will not require
+ subtracting variables. */
-#ifdef ADDRESS_COST
static rtx
+express_from_1 (a, b, mult)
+ rtx a, b, mult;
+{
+ /* If MULT is zero, then A*MULT is zero, and our expression is B. */
+
+ if (mult == const0_rtx)
+ return b;
+
+ /* If MULT is not 1, we cannot handle A with non-constants, since we
+ would then be required to subtract multiples of the registers in A.
+ This is theoretically possible, and may even apply to some Fortran
+ constructs, but it is a lot of work and we do not attempt it here. */
+
+ if (mult != const1_rtx && GET_CODE (a) != CONST_INT)
+ return NULL_RTX;
+
+ /* In general these structures are sorted top to bottom (down the PLUS
+ chain), but not left to right across the PLUS. If B is a higher
+ order giv than A, we can strip one level and recurse. If A is higher
+ order, we'll eventually bail out, but won't know that until the end.
+ If they are the same, we'll strip one level around this loop. */
+
+ while (GET_CODE (a) == PLUS && GET_CODE (b) == PLUS)
+ {
+ rtx ra, rb, oa, ob, tmp;
+
+ ra = XEXP (a, 0), oa = XEXP (a, 1);
+ if (GET_CODE (ra) == PLUS)
+ tmp = ra, ra = oa, oa = tmp;
+
+ rb = XEXP (b, 0), ob = XEXP (b, 1);
+ if (GET_CODE (rb) == PLUS)
+ tmp = rb, rb = ob, ob = tmp;
+
+ if (rtx_equal_p (ra, rb))
+ /* We matched: remove one reg completely. */
+ a = oa, b = ob;
+ else if (GET_CODE (ob) != PLUS && rtx_equal_p (ra, ob))
+ /* An alternate match. */
+ a = oa, b = rb;
+ else if (GET_CODE (oa) != PLUS && rtx_equal_p (oa, rb))
+ /* An alternate match. */
+ a = ra, b = ob;
+ else
+ {
+ /* Indicates an extra register in B. Strip one level from B and
+ recurse, hoping B was the higher order expression. */
+ ob = express_from_1 (a, ob, mult);
+ if (ob == NULL_RTX)
+ return NULL_RTX;
+ return gen_rtx_PLUS (GET_MODE (b), rb, ob);
+ }
+ }
+
+ /* Here we are at the last level of A, go through the cases hoping to
+ get rid of everything but a constant. */
+
+ if (GET_CODE (a) == PLUS)
+ {
+ rtx ra, oa;
+
+ ra = XEXP (a, 0), oa = XEXP (a, 1);
+ if (rtx_equal_p (oa, b))
+ oa = ra;
+ else if (!rtx_equal_p (ra, b))
+ return NULL_RTX;
+
+ if (GET_CODE (oa) != CONST_INT)
+ return NULL_RTX;
+
+ return GEN_INT (-INTVAL (oa) * INTVAL (mult));
+ }
+ else if (GET_CODE (a) == CONST_INT)
+ {
+ return plus_constant (b, -INTVAL (a) * INTVAL (mult));
+ }
+ else if (GET_CODE (b) == PLUS)
+ {
+ if (rtx_equal_p (a, XEXP (b, 0)))
+ return XEXP (b, 1);
+ else if (rtx_equal_p (a, XEXP (b, 1)))
+ return XEXP (b, 0);
+ else
+ return NULL_RTX;
+ }
+ else if (rtx_equal_p (a, b))
+ return const0_rtx;
+
+ return NULL_RTX;
+}
+
+rtx
express_from (g1, g2)
struct induction *g1, *g2;
{
@@ -5810,15 +6779,25 @@ express_from (g1, g2)
/* The value that G1 will be multiplied by must be a constant integer. Also,
the only chance we have of getting a valid address is if b*c/a (see above
for notation) is also an integer. */
- if (GET_CODE (g1->mult_val) != CONST_INT
- || GET_CODE (g2->mult_val) != CONST_INT
- || GET_CODE (g1->add_val) != CONST_INT
- || g1->mult_val == const0_rtx
- || INTVAL (g2->mult_val) % INTVAL (g1->mult_val) != 0)
- return 0;
+ if (GET_CODE (g1->mult_val) == CONST_INT
+ && GET_CODE (g2->mult_val) == CONST_INT)
+ {
+ if (g1->mult_val == const0_rtx
+ || INTVAL (g2->mult_val) % INTVAL (g1->mult_val) != 0)
+ return NULL_RTX;
+ mult = GEN_INT (INTVAL (g2->mult_val) / INTVAL (g1->mult_val));
+ }
+ else if (rtx_equal_p (g1->mult_val, g2->mult_val))
+ mult = const1_rtx;
+ else
+ {
+ /* ??? Find out if the one is a multiple of the other? */
+ return NULL_RTX;
+ }
- mult = GEN_INT (INTVAL (g2->mult_val) / INTVAL (g1->mult_val));
- add = plus_constant (g2->add_val, - INTVAL (g1->add_val) * INTVAL (mult));
+ add = express_from_1 (g1->add_val, g2->add_val, mult);
+ if (add == NULL_RTX)
+ return NULL_RTX;
/* Form simplified final result. */
if (mult == const0_rtx)
@@ -5831,61 +6810,83 @@ express_from (g1, g2)
if (add == const0_rtx)
return mult;
else
- return gen_rtx_PLUS (g2->mode, mult, add);
+ {
+ if (GET_CODE (add) == PLUS
+ && CONSTANT_P (XEXP (add, 1)))
+ {
+ rtx tem = XEXP (add, 1);
+ mult = gen_rtx_PLUS (g2->mode, mult, XEXP (add, 0));
+ add = tem;
+ }
+
+ return gen_rtx_PLUS (g2->mode, mult, add);
+ }
+
}
-#endif
-/* Return 1 if giv G2 can be combined with G1. This means that G2 can use
- (either directly or via an address expression) a register used to represent
- G1. Set g2->new_reg to a represtation of G1 (normally just
- g1->dest_reg). */
+/* Return an rtx, if any, that expresses giv G2 as a function of the register
+ represented by G1. This indicates that G2 should be combined with G1 and
+ that G2 can use (either directly or via an address expression) a register
+ used to represent G1. */
-static int
+static rtx
combine_givs_p (g1, g2)
struct induction *g1, *g2;
{
-#ifdef ADDRESS_COST
- rtx tem;
-#endif
-
- /* If these givs are identical, they can be combined. */
- if (rtx_equal_p (g1->mult_val, g2->mult_val)
- && rtx_equal_p (g1->add_val, g2->add_val))
+ rtx tem = express_from (g1, g2);
+
+ /* If these givs are identical, they can be combined. We use the results
+ of express_from because the addends are not in a canonical form, so
+ rtx_equal_p is a weaker test. */
+ /* But don't combine a DEST_REG giv with a DEST_ADDR giv; we want the
+ combination to be the other way round. */
+ if (tem == g1->dest_reg
+ && (g1->giv_type == DEST_REG || g2->giv_type == DEST_ADDR))
{
- g2->new_reg = g1->dest_reg;
- return 1;
+ return g1->dest_reg;
}
-#ifdef ADDRESS_COST
/* If G2 can be expressed as a function of G1 and that function is valid
as an address and no more expensive than using a register for G2,
the expression of G2 in terms of G1 can be used. */
- if (g2->giv_type == DEST_ADDR
- && (tem = express_from (g1, g2)) != 0
+ if (tem != NULL_RTX
+ && g2->giv_type == DEST_ADDR
&& memory_address_p (g2->mem_mode, tem)
- && ADDRESS_COST (tem) <= ADDRESS_COST (*g2->location))
+ /* ??? Looses, especially with -fforce-addr, where *g2->location
+ will always be a register, and so anything more complicated
+ gets discarded. */
+#if 0
+#ifdef ADDRESS_COST
+ && ADDRESS_COST (tem) <= ADDRESS_COST (*g2->location)
+#else
+ && rtx_cost (tem, MEM) <= rtx_cost (*g2->location, MEM)
+#endif
+#endif
+ )
{
- g2->new_reg = tem;
- return 1;
+ return tem;
}
-#endif
- return 0;
+ return NULL_RTX;
}
-#ifdef GIV_SORT_CRITERION
-/* Compare two givs and sort the most desirable one for combinations first.
- This is used only in one qsort call below. */
+struct combine_givs_stats
+{
+ int giv_number;
+ int total_benefit;
+};
static int
-giv_sort (x, y)
- struct induction **x, **y;
+cmp_combine_givs_stats (x, y)
+ struct combine_givs_stats *x, *y;
{
- GIV_SORT_CRITERION (*x, *y);
-
- return 0;
+ int d;
+ d = y->total_benefit - x->total_benefit;
+ /* Stabilize the sort. */
+ if (!d)
+ d = x->giv_number - y->giv_number;
+ return d;
}
-#endif
/* Check all pairs of givs for iv_class BL and see if any can be combined with
any other. If so, point SAME to the giv combined with and set NEW_REG to
@@ -5896,81 +6897,582 @@ static void
combine_givs (bl)
struct iv_class *bl;
{
+ /* Additional benefit to add for being combined multiple times. */
+ const int extra_benefit = 3;
+
struct induction *g1, *g2, **giv_array;
- int i, j, giv_count, pass;
+ int i, j, k, giv_count;
+ struct combine_givs_stats *stats;
+ rtx *can_combine;
/* Count givs, because bl->giv_count is incorrect here. */
giv_count = 0;
for (g1 = bl->giv; g1; g1 = g1->next_iv)
- giv_count++;
+ if (!g1->ignore)
+ giv_count++;
giv_array
= (struct induction **) alloca (giv_count * sizeof (struct induction *));
i = 0;
for (g1 = bl->giv; g1; g1 = g1->next_iv)
- giv_array[i++] = g1;
-
-#ifdef GIV_SORT_CRITERION
- /* Sort the givs if GIV_SORT_CRITERION is defined.
- This is usually defined for processors which lack
- negative register offsets so more givs may be combined. */
+ if (!g1->ignore)
+ giv_array[i++] = g1;
- if (loop_dump_stream)
- fprintf (loop_dump_stream, "%d givs counted, sorting...\n", giv_count);
+ stats = (struct combine_givs_stats *) alloca (giv_count * sizeof (*stats));
+ bzero ((char *) stats, giv_count * sizeof (*stats));
- qsort (giv_array, giv_count, sizeof (struct induction *), giv_sort);
-#endif
+ can_combine = (rtx *) alloca (giv_count * giv_count * sizeof(rtx));
+ bzero ((char *) can_combine, giv_count * giv_count * sizeof(rtx));
for (i = 0; i < giv_count; i++)
{
+ int this_benefit;
+ rtx single_use;
+
g1 = giv_array[i];
- for (pass = 0; pass <= 1; pass++)
- for (j = 0; j < giv_count; j++)
+ stats[i].giv_number = i;
+
+ /* If a DEST_REG GIV is used only once, do not allow it to combine
+ with anything, for in doing so we will gain nothing that cannot
+ be had by simply letting the GIV with which we would have combined
+ to be reduced on its own. The losage shows up in particular with
+ DEST_ADDR targets on hosts with reg+reg addressing, though it can
+ be seen elsewhere as well. */
+ if (g1->giv_type == DEST_REG
+ && (single_use = VARRAY_RTX (reg_single_usage, REGNO (g1->dest_reg)))
+ && single_use != const0_rtx)
+ continue;
+
+ this_benefit = g1->benefit;
+ /* Add an additional weight for zero addends. */
+ if (g1->no_const_addval)
+ this_benefit += 1;
+
+ for (j = 0; j < giv_count; j++)
+ {
+ rtx this_combine;
+
+ g2 = giv_array[j];
+ if (g1 != g2
+ && (this_combine = combine_givs_p (g1, g2)) != NULL_RTX)
+ {
+ can_combine[i*giv_count + j] = this_combine;
+ this_benefit += g2->benefit + extra_benefit;
+ }
+ }
+ stats[i].total_benefit = this_benefit;
+ }
+
+ /* Iterate, combining until we can't. */
+restart:
+ qsort (stats, giv_count, sizeof(*stats), cmp_combine_givs_stats);
+
+ if (loop_dump_stream)
+ {
+ fprintf (loop_dump_stream, "Sorted combine statistics:\n");
+ for (k = 0; k < giv_count; k++)
+ {
+ g1 = giv_array[stats[k].giv_number];
+ if (!g1->combined_with && !g1->same)
+ fprintf (loop_dump_stream, " {%d, %d}",
+ INSN_UID (giv_array[stats[k].giv_number]->insn),
+ stats[k].total_benefit);
+ }
+ putc ('\n', loop_dump_stream);
+ }
+
+ for (k = 0; k < giv_count; k++)
+ {
+ int g1_add_benefit = 0;
+
+ i = stats[k].giv_number;
+ g1 = giv_array[i];
+
+ /* If it has already been combined, skip. */
+ if (g1->combined_with || g1->same)
+ continue;
+
+ for (j = 0; j < giv_count; j++)
+ {
+ g2 = giv_array[j];
+ if (g1 != g2 && can_combine[i*giv_count + j]
+ /* If it has already been combined, skip. */
+ && ! g2->same && ! g2->combined_with)
+ {
+ int l;
+
+ g2->new_reg = can_combine[i*giv_count + j];
+ g2->same = g1;
+ g1->combined_with++;
+ g1->lifetime += g2->lifetime;
+
+ g1_add_benefit += g2->benefit;
+
+ /* ??? The new final_[bg]iv_value code does a much better job
+ of finding replaceable giv's, and hence this code may no
+ longer be necessary. */
+ if (! g2->replaceable && REG_USERVAR_P (g2->dest_reg))
+ g1_add_benefit -= copy_cost;
+
+ /* To help optimize the next set of combinations, remove
+ this giv from the benefits of other potential mates. */
+ for (l = 0; l < giv_count; ++l)
+ {
+ int m = stats[l].giv_number;
+ if (can_combine[m*giv_count + j])
+ stats[l].total_benefit -= g2->benefit + extra_benefit;
+ }
+
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "giv at %d combined with giv at %d\n",
+ INSN_UID (g2->insn), INSN_UID (g1->insn));
+ }
+ }
+
+ /* To help optimize the next set of combinations, remove
+ this giv from the benefits of other potential mates. */
+ if (g1->combined_with)
+ {
+ for (j = 0; j < giv_count; ++j)
+ {
+ int m = stats[j].giv_number;
+ if (can_combine[m*giv_count + i])
+ stats[j].total_benefit -= g1->benefit + extra_benefit;
+ }
+
+ g1->benefit += g1_add_benefit;
+
+ /* We've finished with this giv, and everything it touched.
+ Restart the combination so that proper weights for the
+ rest of the givs are properly taken into account. */
+ /* ??? Ideally we would compact the arrays at this point, so
+ as to not cover old ground. But sanely compacting
+ can_combine is tricky. */
+ goto restart;
+ }
+ }
+}
+
+struct recombine_givs_stats
+{
+ int giv_number;
+ int start_luid, end_luid;
+};
+
+/* Used below as comparison function for qsort. We want a ascending luid
+ when scanning the array starting at the end, thus the arguments are
+ used in reverse. */
+static int
+cmp_recombine_givs_stats (x, y)
+ struct recombine_givs_stats *x, *y;
+{
+ int d;
+ d = y->start_luid - x->start_luid;
+ /* Stabilize the sort. */
+ if (!d)
+ d = y->giv_number - x->giv_number;
+ return d;
+}
+
+/* Scan X, which is a part of INSN, for the end of life of a giv. Also
+ look for the start of life of a giv where the start has not been seen
+ yet to unlock the search for the end of its life.
+ Only consider givs that belong to BIV.
+ Return the total number of lifetime ends that have been found. */
+static int
+find_life_end (x, stats, insn, biv)
+ rtx x, insn, biv;
+ struct recombine_givs_stats *stats;
+{
+ enum rtx_code code;
+ char *fmt;
+ int i, j;
+ int retval;
+
+ code = GET_CODE (x);
+ switch (code)
+ {
+ case SET:
+ {
+ rtx reg = SET_DEST (x);
+ if (GET_CODE (reg) == REG)
{
- g2 = giv_array[j];
- if (g1 != g2
- /* First try to combine with replaceable givs, then all givs. */
- && (g1->replaceable || pass == 1)
- /* If either has already been combined or is to be ignored, can't
- combine. */
- && ! g1->ignore && ! g2->ignore && ! g1->same && ! g2->same
- /* If something has been based on G2, G2 cannot itself be based
- on something else. */
- && ! g2->combined_with
- && combine_givs_p (g1, g2))
+ int regno = REGNO (reg);
+ struct induction *v = REG_IV_INFO (regno);
+
+ if (REG_IV_TYPE (regno) == GENERAL_INDUCT
+ && ! v->ignore
+ && v->src_reg == biv
+ && stats[v->ix].end_luid <= 0)
{
- /* g2->new_reg set by `combine_givs_p' */
- g2->same = g1;
- g1->combined_with = 1;
-
- /* If one of these givs is a DEST_REG that was only used
- once, by the other giv, this is actually a single use.
- The DEST_REG has the correct cost, while the other giv
- counts the REG use too often. */
- if (g2->giv_type == DEST_REG
- && n_times_used[REGNO (g2->dest_reg)] == 1
- && reg_mentioned_p (g2->dest_reg, PATTERN (g1->insn)))
- g1->benefit = g2->benefit;
- else if (g1->giv_type != DEST_REG
- || n_times_used[REGNO (g1->dest_reg)] != 1
- || ! reg_mentioned_p (g1->dest_reg,
- PATTERN (g2->insn)))
+ /* If we see a 0 here for end_luid, it means that we have
+ scanned the entire loop without finding any use at all.
+ We must not predicate this code on a start_luid match
+ since that would make the test fail for givs that have
+ been hoisted out of inner loops. */
+ if (stats[v->ix].end_luid == 0)
{
- g1->benefit += g2->benefit;
- g1->times_used += g2->times_used;
+ stats[v->ix].end_luid = stats[v->ix].start_luid;
+ return 1 + find_life_end (SET_SRC (x), stats, insn, biv);
}
- /* ??? The new final_[bg]iv_value code does a much better job
- of finding replaceable giv's, and hence this code may no
- longer be necessary. */
- if (! g2->replaceable && REG_USERVAR_P (g2->dest_reg))
- g1->benefit -= copy_cost;
- g1->lifetime += g2->lifetime;
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream, "giv at %d combined with giv at %d\n",
- INSN_UID (g2->insn), INSN_UID (g1->insn));
+ else if (stats[v->ix].start_luid == INSN_LUID (insn))
+ stats[v->ix].end_luid = 0;
}
+ return find_life_end (SET_SRC (x), stats, insn, biv);
+ }
+ break;
+ }
+ case REG:
+ {
+ int regno = REGNO (x);
+ struct induction *v = REG_IV_INFO (regno);
+
+ if (REG_IV_TYPE (regno) == GENERAL_INDUCT
+ && ! v->ignore
+ && v->src_reg == biv
+ && stats[v->ix].end_luid == 0)
+ {
+ while (INSN_UID (insn) >= max_uid_for_loop)
+ insn = NEXT_INSN (insn);
+ stats[v->ix].end_luid = INSN_LUID (insn);
+ return 1;
}
+ return 0;
+ }
+ case LABEL_REF:
+ case CONST_DOUBLE:
+ case CONST_INT:
+ case CONST:
+ return 0;
+ default:
+ break;
+ }
+ fmt = GET_RTX_FORMAT (code);
+ retval = 0;
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ retval += find_life_end (XEXP (x, i), stats, insn, biv);
+
+ else if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ retval += find_life_end (XVECEXP (x, i, j), stats, insn, biv);
+ }
+ return retval;
+}
+
+/* For each giv that has been combined with another, look if
+ we can combine it with the most recently used one instead.
+ This tends to shorten giv lifetimes, and helps the next step:
+ try to derive givs from other givs. */
+static void
+recombine_givs (bl, loop_start, loop_end, unroll_p)
+ struct iv_class *bl;
+ rtx loop_start, loop_end;
+ int unroll_p;
+{
+ struct induction *v, **giv_array, *last_giv;
+ struct recombine_givs_stats *stats;
+ int giv_count;
+ int i, rescan;
+ int ends_need_computing;
+
+ for (giv_count = 0, v = bl->giv; v; v = v->next_iv)
+ {
+ if (! v->ignore)
+ giv_count++;
+ }
+ giv_array
+ = (struct induction **) alloca (giv_count * sizeof (struct induction *));
+ stats = (struct recombine_givs_stats *) alloca (giv_count * sizeof *stats);
+
+ /* Initialize stats and set up the ix field for each giv in stats to name
+ the corresponding index into stats. */
+ for (i = 0, v = bl->giv; v; v = v->next_iv)
+ {
+ rtx p;
+
+ if (v->ignore)
+ continue;
+ giv_array[i] = v;
+ stats[i].giv_number = i;
+ /* If this giv has been hoisted out of an inner loop, use the luid of
+ the previous insn. */
+ for (p = v->insn; INSN_UID (p) >= max_uid_for_loop; )
+ p = PREV_INSN (p);
+ stats[i].start_luid = INSN_LUID (p);
+ v->ix = i;
+ i++;
+ }
+
+ qsort (stats, giv_count, sizeof(*stats), cmp_recombine_givs_stats);
+
+ /* Do the actual most-recently-used recombination. */
+ for (last_giv = 0, i = giv_count - 1; i >= 0; i--)
+ {
+ v = giv_array[stats[i].giv_number];
+ if (v->same)
+ {
+ struct induction *old_same = v->same;
+ rtx new_combine;
+
+ /* combine_givs_p actually says if we can make this transformation.
+ The other tests are here only to avoid keeping a giv alive
+ that could otherwise be eliminated. */
+ if (last_giv
+ && ((old_same->maybe_dead && ! old_same->combined_with)
+ || ! last_giv->maybe_dead
+ || last_giv->combined_with)
+ && (new_combine = combine_givs_p (last_giv, v)))
+ {
+ old_same->combined_with--;
+ v->new_reg = new_combine;
+ v->same = last_giv;
+ last_giv->combined_with++;
+ /* No need to update lifetimes / benefits here since we have
+ already decided what to reduce. */
+
+ if (loop_dump_stream)
+ {
+ fprintf (loop_dump_stream,
+ "giv at %d recombined with giv at %d as ",
+ INSN_UID (v->insn), INSN_UID (last_giv->insn));
+ print_rtl (loop_dump_stream, v->new_reg);
+ putc ('\n', loop_dump_stream);
+ }
+ continue;
+ }
+ v = v->same;
+ }
+ else if (v->giv_type != DEST_REG)
+ continue;
+ if (! last_giv
+ || (last_giv->maybe_dead && ! last_giv->combined_with)
+ || ! v->maybe_dead
+ || v->combined_with)
+ last_giv = v;
+ }
+
+ ends_need_computing = 0;
+ /* For each DEST_REG giv, compute lifetime starts, and try to compute
+ lifetime ends from regscan info. */
+ for (i = 0, v = bl->giv; v; v = v->next_iv)
+ {
+ if (v->ignore)
+ continue;
+ if (v->giv_type == DEST_ADDR)
+ {
+ /* Loop unrolling of an inner loop can even create new DEST_REG
+ givs. */
+ rtx p;
+ for (p = v->insn; INSN_UID (p) >= max_uid_for_loop; )
+ p = PREV_INSN (p);
+ stats[i].start_luid = stats[i].end_luid = INSN_LUID (p);
+ if (p != v->insn)
+ stats[i].end_luid++;
+ }
+ else /* v->giv_type == DEST_REG */
+ {
+ if (v->last_use)
+ {
+ stats[i].start_luid = INSN_LUID (v->insn);
+ stats[i].end_luid = INSN_LUID (v->last_use);
+ }
+ else if (INSN_UID (v->insn) >= max_uid_for_loop)
+ {
+ rtx p;
+ /* This insn has been created by loop optimization on an inner
+ loop. We don't have a proper start_luid that will match
+ when we see the first set. But we do know that there will
+ be no use before the set, so we can set end_luid to 0 so that
+ we'll start looking for the last use right away. */
+ for (p = PREV_INSN (v->insn); INSN_UID (p) >= max_uid_for_loop; )
+ p = PREV_INSN (p);
+ stats[i].start_luid = INSN_LUID (p);
+ stats[i].end_luid = 0;
+ ends_need_computing++;
+ }
+ else
+ {
+ int regno = REGNO (v->dest_reg);
+ int count = VARRAY_INT (n_times_set, regno) - 1;
+ rtx p = v->insn;
+
+ /* Find the first insn that sets the giv, so that we can verify
+ if this giv's lifetime wraps around the loop. We also need
+ the luid of the first setting insn in order to detect the
+ last use properly. */
+ while (count)
+ {
+ p = prev_nonnote_insn (p);
+ if (reg_set_p (v->dest_reg, p))
+ count--;
+ }
+
+ stats[i].start_luid = INSN_LUID (p);
+ if (stats[i].start_luid > uid_luid[REGNO_FIRST_UID (regno)])
+ {
+ stats[i].end_luid = -1;
+ ends_need_computing++;
+ }
+ else
+ {
+ stats[i].end_luid = uid_luid[REGNO_LAST_UID (regno)];
+ if (stats[i].end_luid > INSN_LUID (loop_end))
+ {
+ stats[i].end_luid = -1;
+ ends_need_computing++;
+ }
+ }
+ }
+ }
+ i++;
+ }
+
+ /* If the regscan information was unconclusive for one or more DEST_REG
+ givs, scan the all insn in the loop to find out lifetime ends. */
+ if (ends_need_computing)
+ {
+ rtx biv = bl->biv->src_reg;
+ rtx p = loop_end;
+
+ do
+ {
+ if (p == loop_start)
+ p = loop_end;
+ p = PREV_INSN (p);
+ if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
+ continue;
+ ends_need_computing -= find_life_end (PATTERN (p), stats, p, biv);
+ }
+ while (ends_need_computing);
+ }
+
+ /* Set start_luid back to the last insn that sets the giv. This allows
+ more combinations. */
+ for (i = 0, v = bl->giv; v; v = v->next_iv)
+ {
+ if (v->ignore)
+ continue;
+ if (INSN_UID (v->insn) < max_uid_for_loop)
+ stats[i].start_luid = INSN_LUID (v->insn);
+ i++;
+ }
+
+ /* Now adjust lifetime ends by taking combined givs into account. */
+ for (i = 0, v = bl->giv; v; v = v->next_iv)
+ {
+ unsigned luid;
+ int j;
+
+ if (v->ignore)
+ continue;
+ if (v->same && ! v->same->ignore)
+ {
+ j = v->same->ix;
+ luid = stats[i].start_luid;
+ /* Use unsigned arithmetic to model loop wrap-around. */
+ if (luid - stats[j].start_luid
+ > (unsigned) stats[j].end_luid - stats[j].start_luid)
+ stats[j].end_luid = luid;
+ }
+ i++;
+ }
+
+ qsort (stats, giv_count, sizeof(*stats), cmp_recombine_givs_stats);
+
+ /* Try to derive DEST_REG givs from previous DEST_REG givs with the
+ same mult_val and non-overlapping lifetime. This reduces register
+ pressure.
+ Once we find a DEST_REG giv that is suitable to derive others from,
+ we set last_giv to this giv, and try to derive as many other DEST_REG
+ givs from it without joining overlapping lifetimes. If we then
+ encounter a DEST_REG giv that we can't derive, we set rescan to the
+ index for this giv (unless rescan is already set).
+ When we are finished with the current LAST_GIV (i.e. the inner loop
+ terminates), we start again with rescan, which then becomes the new
+ LAST_GIV. */
+ for (i = giv_count - 1; i >= 0; i = rescan)
+ {
+ int life_start, life_end;
+
+ for (last_giv = 0, rescan = -1; i >= 0; i--)
+ {
+ rtx sum;
+
+ v = giv_array[stats[i].giv_number];
+ if (v->giv_type != DEST_REG || v->derived_from || v->same)
+ continue;
+ if (! last_giv)
+ {
+ /* Don't use a giv that's likely to be dead to derive
+ others - that would be likely to keep that giv alive. */
+ if (! v->maybe_dead || v->combined_with)
+ {
+ last_giv = v;
+ life_start = stats[i].start_luid;
+ life_end = stats[i].end_luid;
+ }
+ continue;
+ }
+ /* Use unsigned arithmetic to model loop wrap around. */
+ if (((unsigned) stats[i].start_luid - life_start
+ >= (unsigned) life_end - life_start)
+ && ((unsigned) stats[i].end_luid - life_start
+ > (unsigned) life_end - life_start)
+ /* Check that the giv insn we're about to use for deriving
+ precedes all uses of that giv. Note that initializing the
+ derived giv would defeat the purpose of reducing register
+ pressure.
+ ??? We could arrange to move the insn. */
+ && ((unsigned) stats[i].end_luid - INSN_LUID (loop_start)
+ > (unsigned) stats[i].start_luid - INSN_LUID (loop_start))
+ && rtx_equal_p (last_giv->mult_val, v->mult_val)
+ /* ??? Could handle libcalls, but would need more logic. */
+ && ! find_reg_note (v->insn, REG_RETVAL, NULL_RTX)
+ /* We would really like to know if for any giv that v
+ is combined with, v->insn or any intervening biv increment
+ dominates that combined giv. However, we
+ don't have this detailed control flow information.
+ N.B. since last_giv will be reduced, it is valid
+ anywhere in the loop, so we don't need to check the
+ validity of last_giv.
+ We rely here on the fact that v->always_executed implies that
+ there is no jump to someplace else in the loop before the
+ giv insn, and hence any insn that is executed before the
+ giv insn in the loop will have a lower luid. */
+ && (v->always_executed || ! v->combined_with)
+ && (sum = express_from (last_giv, v))
+ /* Make sure we don't make the add more expensive. ADD_COST
+ doesn't take different costs of registers and constants into
+ account, so compare the cost of the actual SET_SRCs. */
+ && (rtx_cost (sum, SET)
+ <= rtx_cost (SET_SRC (single_set (v->insn)), SET))
+ /* ??? unroll can't understand anything but reg + const_int
+ sums. It would be cleaner to fix unroll. */
+ && ((GET_CODE (sum) == PLUS
+ && GET_CODE (XEXP (sum, 0)) == REG
+ && GET_CODE (XEXP (sum, 1)) == CONST_INT)
+ || ! unroll_p)
+ && validate_change (v->insn, &PATTERN (v->insn),
+ gen_rtx_SET (VOIDmode, v->dest_reg, sum), 0))
+ {
+ v->derived_from = last_giv;
+ life_end = stats[i].end_luid;
+
+ if (loop_dump_stream)
+ {
+ fprintf (loop_dump_stream,
+ "giv at %d derived from %d as ",
+ INSN_UID (v->insn), INSN_UID (last_giv->insn));
+ print_rtl (loop_dump_stream, sum);
+ putc ('\n', loop_dump_stream);
+ }
+ }
+ else if (rescan < 0)
+ rescan = i;
+ }
}
}
@@ -6115,10 +7617,11 @@ product_cheap_p (a, b)
final_[bg]iv_value. */
static int
-check_dbra_loop (loop_end, insn_count, loop_start)
+check_dbra_loop (loop_end, insn_count, loop_start, loop_info)
rtx loop_end;
int insn_count;
rtx loop_start;
+ struct loop_info *loop_info;
{
struct iv_class *bl;
rtx reg;
@@ -6224,7 +7727,7 @@ check_dbra_loop (loop_end, insn_count, loop_start)
}
}
}
- else if (num_mem_sets <= 1)
+ else if (INTVAL (bl->biv->add_val) > 0)
{
/* Try to change inc to dec, so can apply above optimization. */
/* Can do this if:
@@ -6244,10 +7747,6 @@ check_dbra_loop (loop_end, insn_count, loop_start)
which is reversible. */
int reversible_mem_store = 1;
- for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
- if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
- num_nonfixed_reads += count_nonfixed_reads (PATTERN (p));
-
if (bl->giv_count == 0
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
{
@@ -6271,7 +7770,6 @@ check_dbra_loop (loop_end, insn_count, loop_start)
/* Don't bother about the end test. */
;
else if (reg_mentioned_p (bivreg, PATTERN (p)))
- /* Any other use of the biv is no good. */
{
no_use_except_counting = 0;
break;
@@ -6279,48 +7777,60 @@ check_dbra_loop (loop_end, insn_count, loop_start)
}
}
- /* If the loop has a single store, and the destination address is
- invariant, then we can't reverse the loop, because this address
- might then have the wrong value at loop exit.
- This would work if the source was invariant also, however, in that
- case, the insn should have been moved out of the loop. */
-
- if (num_mem_sets == 1)
+ if (no_use_except_counting)
+ ; /* no need to worry about MEMs. */
+ else if (num_mem_sets <= 1)
{
- struct induction *v;
+ for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
+ if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+ num_nonfixed_reads += count_nonfixed_reads (PATTERN (p));
- reversible_mem_store
- = (! unknown_address_altered
- && ! invariant_p (XEXP (loop_store_mems[0], 0)));
+ /* If the loop has a single store, and the destination address is
+ invariant, then we can't reverse the loop, because this address
+ might then have the wrong value at loop exit.
+ This would work if the source was invariant also, however, in that
+ case, the insn should have been moved out of the loop. */
- /* If the store depends on a register that is set after the
- store, it depends on the initial value, and is thus not
- reversible. */
- for (v = bl->giv; reversible_mem_store && v; v = v->next_iv)
+ if (num_mem_sets == 1)
{
- if (v->giv_type == DEST_REG
- && reg_mentioned_p (v->dest_reg, loop_store_mems[0])
- && (INSN_UID (v->insn) >= max_uid_for_loop
- || (INSN_LUID (v->insn)
- > INSN_LUID (first_loop_store_insn))))
- reversible_mem_store = 0;
+ struct induction *v;
+
+ reversible_mem_store
+ = (! unknown_address_altered
+ && ! invariant_p (XEXP (XEXP (loop_store_mems, 0), 0)));
+
+ /* If the store depends on a register that is set after the
+ store, it depends on the initial value, and is thus not
+ reversible. */
+ for (v = bl->giv; reversible_mem_store && v; v = v->next_iv)
+ {
+ if (v->giv_type == DEST_REG
+ && reg_mentioned_p (v->dest_reg,
+ XEXP (loop_store_mems, 0))
+ && loop_insn_first_p (first_loop_store_insn, v->insn))
+ reversible_mem_store = 0;
+ }
}
}
+ else
+ return 0;
/* This code only acts for innermost loops. Also it simplifies
the memory address check by only reversing loops with
zero or one memory access.
Two memory accesses could involve parts of the same array,
- and that can't be reversed. */
-
- if (num_nonfixed_reads <= 1
- && !loop_has_call
- && !loop_has_volatile
- && reversible_mem_store
- && (no_use_except_counting
- || ((bl->giv_count + bl->biv_count + num_mem_sets
- + num_movables + compare_and_branch == insn_count)
- && (bl == loop_iv_list && bl->next == 0))))
+ and that can't be reversed.
+ If the biv is used only for counting, than we don't need to worry
+ about all these things. */
+
+ if ((num_nonfixed_reads <= 1
+ && !loop_has_call
+ && !loop_has_volatile
+ && reversible_mem_store
+ && (bl->giv_count + bl->biv_count + num_mem_sets
+ + num_movables + compare_and_branch == insn_count)
+ && (bl == loop_iv_list && bl->next == 0))
+ || no_use_except_counting)
{
rtx tem;
@@ -6338,46 +7848,130 @@ check_dbra_loop (loop_end, insn_count, loop_start)
confusing. */
if (comparison
- && GET_CODE (XEXP (comparison, 1)) == CONST_INT
- /* LE gets turned into LT */
- && GET_CODE (comparison) == LT
- && GET_CODE (bl->initial_value) == CONST_INT)
+ /* for constants, LE gets turned into LT */
+ && (GET_CODE (comparison) == LT
+ || (GET_CODE (comparison) == LE
+ && no_use_except_counting)))
{
- HOST_WIDE_INT add_val, comparison_val;
- rtx initial_value;
+ HOST_WIDE_INT add_val, add_adjust, comparison_val;
+ rtx initial_value, comparison_value;
+ int nonneg = 0;
+ enum rtx_code cmp_code;
+ int comparison_const_width;
+ unsigned HOST_WIDE_INT comparison_sign_mask;
add_val = INTVAL (bl->biv->add_val);
- comparison_val = INTVAL (XEXP (comparison, 1));
- final_value = XEXP (comparison, 1);
+ comparison_value = XEXP (comparison, 1);
+ if (GET_MODE (comparison_value) == VOIDmode)
+ comparison_const_width
+ = GET_MODE_BITSIZE (GET_MODE (XEXP (comparison, 0)));
+ else
+ comparison_const_width
+ = GET_MODE_BITSIZE (GET_MODE (comparison_value));
+ if (comparison_const_width > HOST_BITS_PER_WIDE_INT)
+ comparison_const_width = HOST_BITS_PER_WIDE_INT;
+ comparison_sign_mask
+ = (unsigned HOST_WIDE_INT)1 << (comparison_const_width - 1);
+
+ /* If the comparison value is not a loop invariant, then we
+ can not reverse this loop.
+
+ ??? If the insns which initialize the comparison value as
+ a whole compute an invariant result, then we could move
+ them out of the loop and proceed with loop reversal. */
+ if (!invariant_p (comparison_value))
+ return 0;
+
+ if (GET_CODE (comparison_value) == CONST_INT)
+ comparison_val = INTVAL (comparison_value);
initial_value = bl->initial_value;
/* Normalize the initial value if it is an integer and
has no other use except as a counter. This will allow
a few more loops to be reversed. */
if (no_use_except_counting
+ && GET_CODE (comparison_value) == CONST_INT
&& GET_CODE (initial_value) == CONST_INT)
{
comparison_val = comparison_val - INTVAL (bl->initial_value);
- /* Check for overflow. If comparison_val ends up as a
- negative value, then we can't reverse the loop. */
- if (comparison_val >= 0)
- initial_value = const0_rtx;
+ /* The code below requires comparison_val to be a multiple
+ of add_val in order to do the loop reversal, so
+ round up comparison_val to a multiple of add_val.
+ Since comparison_value is constant, we know that the
+ current comparison code is LT. */
+ comparison_val = comparison_val + add_val - 1;
+ comparison_val
+ -= (unsigned HOST_WIDE_INT) comparison_val % add_val;
+ /* We postpone overflow checks for COMPARISON_VAL here;
+ even if there is an overflow, we might still be able to
+ reverse the loop, if converting the loop exit test to
+ NE is possible. */
+ initial_value = const0_rtx;
+ }
+
+ /* First check if we can do a vanilla loop reversal. */
+ if (initial_value == const0_rtx
+ /* If we have a decrement_and_branch_on_count, prefer
+ the NE test, since this will allow that instruction to
+ be generated. Note that we must use a vanilla loop
+ reversal if the biv is used to calculate a giv or has
+ a non-counting use. */
+#if ! defined (HAVE_decrement_and_branch_until_zero) && defined (HAVE_decrement_and_branch_on_count)
+ && (! (add_val == 1 && loop_info->vtop
+ && (bl->biv_count == 0
+ || no_use_except_counting)))
+#endif
+ && GET_CODE (comparison_value) == CONST_INT
+ /* Now do postponed overflow checks on COMPARISON_VAL. */
+ && ! (((comparison_val - add_val) ^ INTVAL (comparison_value))
+ & comparison_sign_mask))
+ {
+ /* Register will always be nonnegative, with value
+ 0 on last iteration */
+ add_adjust = add_val;
+ nonneg = 1;
+ cmp_code = GE;
}
+ else if (add_val == 1 && loop_info->vtop
+ && (bl->biv_count == 0
+ || no_use_except_counting))
+ {
+ add_adjust = 0;
+ cmp_code = NE;
+ }
+ else
+ return 0;
+
+ if (GET_CODE (comparison) == LE)
+ add_adjust -= add_val;
/* If the initial value is not zero, or if the comparison
value is not an exact multiple of the increment, then we
can not reverse this loop. */
- if (initial_value != const0_rtx
- || (comparison_val % add_val) != 0)
- return 0;
+ if (initial_value == const0_rtx
+ && GET_CODE (comparison_value) == CONST_INT)
+ {
+ if (((unsigned HOST_WIDE_INT) comparison_val % add_val) != 0)
+ return 0;
+ }
+ else
+ {
+ if (! no_use_except_counting || add_val != 1)
+ return 0;
+ }
+
+ final_value = comparison_value;
/* Reset these in case we normalized the initial value
and comparison value above. */
+ if (GET_CODE (comparison_value) == CONST_INT
+ && GET_CODE (initial_value) == CONST_INT)
+ {
+ comparison_value = GEN_INT (comparison_val);
+ final_value
+ = GEN_INT (comparison_val + INTVAL (bl->initial_value));
+ }
bl->initial_value = initial_value;
- XEXP (comparison, 1) = GEN_INT (comparison_val);
-
- /* Register will always be nonnegative, with value
- 0 on last iteration if loop reversed */
/* Save some info needed to produce the new insns. */
reg = bl->biv->dest_reg;
@@ -6386,18 +7980,68 @@ check_dbra_loop (loop_end, insn_count, loop_start)
jump_label = XEXP (SET_SRC (PATTERN (PREV_INSN (loop_end))), 2);
new_add_val = GEN_INT (- INTVAL (bl->biv->add_val));
- start_value = GEN_INT (INTVAL (XEXP (comparison, 1))
- - INTVAL (bl->biv->add_val));
-
- /* Initialize biv to start_value before loop start.
+ /* Set start_value; if this is not a CONST_INT, we need
+ to generate a SUB.
+ Initialize biv to start_value before loop start.
The old initializing insn will be deleted as a
dead store by flow.c. */
- emit_insn_before (gen_move_insn (reg, start_value), loop_start);
+ if (initial_value == const0_rtx
+ && GET_CODE (comparison_value) == CONST_INT)
+ {
+ start_value = GEN_INT (comparison_val - add_adjust);
+ emit_insn_before (gen_move_insn (reg, start_value),
+ loop_start);
+ }
+ else if (GET_CODE (initial_value) == CONST_INT)
+ {
+ rtx offset = GEN_INT (-INTVAL (initial_value) - add_adjust);
+ enum machine_mode mode = GET_MODE (reg);
+ enum insn_code icode
+ = add_optab->handlers[(int) mode].insn_code;
+ if (! (*insn_operand_predicate[icode][0]) (reg, mode)
+ || ! ((*insn_operand_predicate[icode][1])
+ (comparison_value, mode))
+ || ! (*insn_operand_predicate[icode][2]) (offset, mode))
+ return 0;
+ start_value
+ = gen_rtx_PLUS (mode, comparison_value, offset);
+ emit_insn_before ((GEN_FCN (icode)
+ (reg, comparison_value, offset)),
+ loop_start);
+ if (GET_CODE (comparison) == LE)
+ final_value = gen_rtx_PLUS (mode, comparison_value,
+ GEN_INT (add_val));
+ }
+ else if (! add_adjust)
+ {
+ enum machine_mode mode = GET_MODE (reg);
+ enum insn_code icode
+ = sub_optab->handlers[(int) mode].insn_code;
+ if (! (*insn_operand_predicate[icode][0]) (reg, mode)
+ || ! ((*insn_operand_predicate[icode][1])
+ (comparison_value, mode))
+ || ! ((*insn_operand_predicate[icode][2])
+ (initial_value, mode)))
+ return 0;
+ start_value
+ = gen_rtx_MINUS (mode, comparison_value, initial_value);
+ emit_insn_before ((GEN_FCN (icode)
+ (reg, comparison_value, initial_value)),
+ loop_start);
+ }
+ else
+ /* We could handle the other cases too, but it'll be
+ better to have a testcase first. */
+ return 0;
- /* Add insn to decrement register, and delete insn
- that incremented the register. */
- p = emit_insn_before (gen_add2_insn (reg, new_add_val),
- bl->biv->insn);
+ /* We may not have a single insn which can increment a reg, so
+ create a sequence to hold all the insns from expand_inc. */
+ start_sequence ();
+ expand_inc (reg, new_add_val);
+ tem = gen_sequence ();
+ end_sequence ();
+
+ p = emit_insn_before (tem, bl->biv->insn);
delete_insn (bl->biv->insn);
/* Update biv info to reflect its new status. */
@@ -6405,6 +8049,15 @@ check_dbra_loop (loop_end, insn_count, loop_start)
bl->initial_value = start_value;
bl->biv->add_val = new_add_val;
+ /* Update loop info. */
+ loop_info->initial_value = reg;
+ loop_info->initial_equiv_value = reg;
+ loop_info->final_value = const0_rtx;
+ loop_info->final_equiv_value = const0_rtx;
+ loop_info->comparison_value = const0_rtx;
+ loop_info->comparison_code = cmp_code;
+ loop_info->increment = new_add_val;
+
/* Inc LABEL_NUSES so that delete_insn will
not delete the label. */
LABEL_NUSES (XEXP (jump_label, 0)) ++;
@@ -6424,29 +8077,34 @@ check_dbra_loop (loop_end, insn_count, loop_start)
/* Add new compare/branch insn at end of loop. */
start_sequence ();
- emit_cmp_insn (reg, const0_rtx, GE, NULL_RTX,
- GET_MODE (reg), 0, 0);
- emit_jump_insn (gen_bge (XEXP (jump_label, 0)));
+ emit_cmp_and_jump_insns (reg, const0_rtx, cmp_code, NULL_RTX,
+ GET_MODE (reg), 0, 0,
+ XEXP (jump_label, 0));
tem = gen_sequence ();
end_sequence ();
emit_jump_insn_before (tem, loop_end);
for (tem = PREV_INSN (loop_end);
- tem && GET_CODE (tem) != JUMP_INSN; tem = PREV_INSN (tem))
+ tem && GET_CODE (tem) != JUMP_INSN;
+ tem = PREV_INSN (tem))
;
+
if (tem)
- {
- JUMP_LABEL (tem) = XEXP (jump_label, 0);
+ JUMP_LABEL (tem) = XEXP (jump_label, 0);
- /* Increment of LABEL_NUSES done above. */
- /* Register is now always nonnegative,
- so add REG_NONNEG note to the branch. */
- REG_NOTES (tem) = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
- REG_NOTES (tem));
+ if (nonneg)
+ {
+ if (tem)
+ {
+ /* Increment of LABEL_NUSES done above. */
+ /* Register is now always nonnegative,
+ so add REG_NONNEG note to the branch. */
+ REG_NOTES (tem) = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
+ REG_NOTES (tem));
+ }
+ bl->nonneg = 1;
}
- bl->nonneg = 1;
-
/* Mark that this biv has been reversed. Each giv which depends
on this biv, and which is also live past the end of the loop
will have to be fixed up. */
@@ -6454,8 +8112,13 @@ check_dbra_loop (loop_end, insn_count, loop_start)
bl->reversed = 1;
if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Reversed loop and added reg_nonneg\n");
+ {
+ fprintf (loop_dump_stream, "Reversed loop");
+ if (bl->nonneg)
+ fprintf (loop_dump_stream, " and added reg_nonneg\n");
+ else
+ fprintf (loop_dump_stream, "\n");
+ }
return 1;
}
@@ -6494,6 +8157,27 @@ maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count)
enum rtx_code code = GET_CODE (p);
rtx where = threshold >= insn_count ? loop_start : p;
+ /* If this is a libcall that sets a giv, skip ahead to its end. */
+ if (GET_RTX_CLASS (code) == 'i')
+ {
+ rtx note = find_reg_note (p, REG_LIBCALL, NULL_RTX);
+
+ if (note)
+ {
+ rtx last = XEXP (note, 0);
+ rtx set = single_set (last);
+
+ if (set && GET_CODE (SET_DEST (set)) == REG)
+ {
+ int regno = REGNO (SET_DEST (set));
+
+ if (regno < max_reg_before_loop
+ && REG_IV_TYPE (regno) == GENERAL_INDUCT
+ && REG_IV_INFO (regno)->src_reg == bl->biv->src_reg)
+ p = last;
+ }
+ }
+ }
if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
&& reg_mentioned_p (reg, PATTERN (p))
&& ! maybe_eliminate_biv_1 (PATTERN (p), p, bl, eliminate_p, where))
@@ -6517,6 +8201,78 @@ maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count)
return 0;
}
+/* INSN and REFERENCE are instructions in the same insn chain.
+ Return non-zero if INSN is first. */
+
+int
+loop_insn_first_p (insn, reference)
+ rtx insn, reference;
+{
+ rtx p, q;
+
+ for (p = insn, q = reference; ;)
+ {
+ /* Start with test for not first so that INSN == REFERENCE yields not
+ first. */
+ if (q == insn || ! p)
+ return 0;
+ if (p == reference || ! q)
+ return 1;
+
+ /* Either of P or Q might be a NOTE. Notes have the same LUID as the
+ previous insn, hence the <= comparison below does not work if
+ P is a note. */
+ if (INSN_UID (p) < max_uid_for_loop
+ && INSN_UID (q) < max_uid_for_loop
+ && GET_CODE (p) != NOTE)
+ return INSN_LUID (p) <= INSN_LUID (q);
+
+ if (INSN_UID (p) >= max_uid_for_loop
+ || GET_CODE (p) == NOTE)
+ p = NEXT_INSN (p);
+ if (INSN_UID (q) >= max_uid_for_loop)
+ q = NEXT_INSN (q);
+ }
+}
+
+/* We are trying to eliminate BIV in INSN using GIV. Return non-zero if
+ the offset that we have to take into account due to auto-increment /
+ div derivation is zero. */
+static int
+biv_elimination_giv_has_0_offset (biv, giv, insn)
+ struct induction *biv, *giv;
+ rtx insn;
+{
+ /* If the giv V had the auto-inc address optimization applied
+ to it, and INSN occurs between the giv insn and the biv
+ insn, then we'd have to adjust the value used here.
+ This is rare, so we don't bother to make this possible. */
+ if (giv->auto_inc_opt
+ && ((loop_insn_first_p (giv->insn, insn)
+ && loop_insn_first_p (insn, biv->insn))
+ || (loop_insn_first_p (biv->insn, insn)
+ && loop_insn_first_p (insn, giv->insn))))
+ return 0;
+
+ /* If the giv V was derived from another giv, and INSN does
+ not occur between the giv insn and the biv insn, then we'd
+ have to adjust the value used here. This is rare, so we don't
+ bother to make this possible. */
+ if (giv->derived_from
+ && ! (giv->always_executed
+ && loop_insn_first_p (giv->insn, insn)
+ && loop_insn_first_p (insn, biv->insn)))
+ return 0;
+ if (giv->same
+ && giv->same->derived_from
+ && ! (giv->same->always_executed
+ && loop_insn_first_p (giv->same->insn, insn)
+ && loop_insn_first_p (insn, biv->insn)))
+ return 0;
+
+ return 1;
+}
+
/* If BL appears in X (part of the pattern of INSN), see if we can
eliminate its use. If so, return 1. If not, return 0.
@@ -6567,42 +8323,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
return 1;
#ifdef HAVE_cc0
- /* The idea here is to replace the SET of cc0 by a REG with
- a comparison involving related induction variables.
- Unfortunately, however, such a replacement does not work
- correctly if the REG is being used as signed and the
- replacement value is unsigned, or vice versa. For
- example, in:
-
- for (int i = n; i >= 0; --i)
- s[i] = 3;
-
- `s' is an address (an unsigned quantity), while `i' is a
- signed quantity. The exit test for the loop might look
- something like:
-
- (SET cc0 i)
- (JUMP (SET (PC) (IF_THEN_ELSE (LT (CC0) (CONST_INT 0))
- (LABEL_REF L) (PC))))
-
- If we replace the SET of cc0 with a comparison of the
- induction variable for `s + i' and the original value of `s',
- however, we should be change the comparison in the
- IF_THEN_ELSE to be unsigned. Otherwise, an array the spans
- the boundary between "negative" and "positive" addresses will
- confuse us.
-
- There are related problems with overflow. If an induction
- variable "wraps around" but the original value doest not, we
- can get confused when doing the comparison.
-
- Pointers can't wrap around, or overflow, in a conformant
- program. Therefore, it's safe to do these optimizations if
- both the original REG and the values in the replacement are
- pointers. For now, though, we just disable these
- optimizations. */
-
- if (0 && SET_DEST (x) == cc0_rtx && SET_SRC (x) == reg)
+ if (SET_DEST (x) == cc0_rtx && SET_SRC (x) == reg)
{
/* Can replace with any giv that was reduced and
that has (MULT_VAL != 0) and (ADD_VAL == 0).
@@ -6617,15 +8338,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
&& v->mode == mode
&& 0)
{
- /* If the giv V had the auto-inc address optimization applied
- to it, and INSN occurs between the giv insn and the biv
- insn, then we must adjust the value used here.
- This is rare, so we don't bother to do so. */
- if (v->auto_inc_opt
- && ((INSN_LUID (v->insn) < INSN_LUID (insn)
- && INSN_LUID (insn) < INSN_LUID (bl->biv->insn))
- || (INSN_LUID (v->insn) > INSN_LUID (insn)
- && INSN_LUID (insn) > INSN_LUID (bl->biv->insn))))
+ if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
if (! eliminate_p)
@@ -6660,15 +8373,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
|| (GET_CODE (v->add_val) == REG
&& REGNO_POINTER_FLAG (REGNO (v->add_val)))))
{
- /* If the giv V had the auto-inc address optimization applied
- to it, and INSN occurs between the giv insn and the biv
- insn, then we must adjust the value used here.
- This is rare, so we don't bother to do so. */
- if (v->auto_inc_opt
- && ((INSN_LUID (v->insn) < INSN_LUID (insn)
- && INSN_LUID (insn) < INSN_LUID (bl->biv->insn))
- || (INSN_LUID (v->insn) > INSN_LUID (insn)
- && INSN_LUID (insn) > INSN_LUID (bl->biv->insn))))
+ if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
if (! eliminate_p)
@@ -6733,15 +8438,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
&& ! v->ignore && ! v->maybe_dead && v->always_computable
&& v->mode == mode)
{
- /* If the giv V had the auto-inc address optimization applied
- to it, and INSN occurs between the giv insn and the biv
- insn, then we must adjust the value used here.
- This is rare, so we don't bother to do so. */
- if (v->auto_inc_opt
- && ((INSN_LUID (v->insn) < INSN_LUID (insn)
- && INSN_LUID (insn) < INSN_LUID (bl->biv->insn))
- || (INSN_LUID (v->insn) > INSN_LUID (insn)
- && INSN_LUID (insn) > INSN_LUID (bl->biv->insn))))
+ if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
if (! eliminate_p)
@@ -6784,15 +8481,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
{
rtx tem;
- /* If the giv V had the auto-inc address optimization applied
- to it, and INSN occurs between the giv insn and the biv
- insn, then we must adjust the value used here.
- This is rare, so we don't bother to do so. */
- if (v->auto_inc_opt
- && ((INSN_LUID (v->insn) < INSN_LUID (insn)
- && INSN_LUID (insn) < INSN_LUID (bl->biv->insn))
- || (INSN_LUID (v->insn) > INSN_LUID (insn)
- && INSN_LUID (insn) > INSN_LUID (bl->biv->insn))))
+ if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
if (! eliminate_p)
@@ -6828,15 +8517,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
{
rtx tem;
- /* If the giv V had the auto-inc address optimization applied
- to it, and INSN occurs between the giv insn and the biv
- insn, then we must adjust the value used here.
- This is rare, so we don't bother to do so. */
- if (v->auto_inc_opt
- && ((INSN_LUID (v->insn) < INSN_LUID (insn)
- && INSN_LUID (insn) < INSN_LUID (bl->biv->insn))
- || (INSN_LUID (v->insn) > INSN_LUID (insn)
- && INSN_LUID (insn) > INSN_LUID (bl->biv->insn))))
+ if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
if (! eliminate_p)
@@ -6872,7 +8553,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
#if 0
/* Otherwise the reg compared with had better be a biv. */
if (GET_CODE (arg) != REG
- || reg_iv_type[REGNO (arg)] != BASIC_INDUCT)
+ || REG_IV_TYPE (REGNO (arg)) != BASIC_INDUCT)
return 0;
/* Look for a pair of givs, one for each biv,
@@ -6890,15 +8571,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
&& rtx_equal_p (tv->add_val, v->add_val)
&& tv->mode == mode)
{
- /* If the giv V had the auto-inc address optimization applied
- to it, and INSN occurs between the giv insn and the biv
- insn, then we must adjust the value used here.
- This is rare, so we don't bother to do so. */
- if (v->auto_inc_opt
- && ((INSN_LUID (v->insn) < INSN_LUID (insn)
- && INSN_LUID (insn) < INSN_LUID (bl->biv->insn))
- || (INSN_LUID (v->insn) > INSN_LUID (insn)
- && INSN_LUID (insn) > INSN_LUID (bl->biv->insn))))
+ if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
if (! eliminate_p)
@@ -6985,7 +8658,7 @@ record_initial (dest, set)
if (GET_CODE (dest) != REG
|| REGNO (dest) >= max_reg_before_loop
- || reg_iv_type[REGNO (dest)] != BASIC_INDUCT)
+ || REG_IV_TYPE (REGNO (dest)) != BASIC_INDUCT)
return;
bl = reg_biv_class[REGNO (dest)];
@@ -7142,7 +8815,14 @@ get_condition (jump, earliest)
like Alpha that have an IEEE compliant EQ instruction, and
a non-IEEE compliant BEQ instruction. The use of CCmode is
actually artificial, simply to prevent the combination, but
- should not affect other platforms. */
+ should not affect other platforms.
+
+ However, we must allow VOIDmode comparisons to match either
+ CCmode or non-CCmode comparison, because some ports have
+ modeless comparisons inside branch patterns.
+
+ ??? This mode check should perhaps look more like the mode check
+ in simplify_comparison in combine. */
if ((GET_CODE (SET_SRC (set)) == COMPARE
|| (((code == NE
@@ -7160,8 +8840,9 @@ get_condition (jump, earliest)
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'))
- && ((GET_MODE_CLASS (mode) == MODE_CC)
- != (GET_MODE_CLASS (inner_mode) == MODE_CC)))
+ && (((GET_MODE_CLASS (mode) == MODE_CC)
+ == (GET_MODE_CLASS (inner_mode) == MODE_CC))
+ || mode == VOIDmode || inner_mode == VOIDmode))
x = SET_SRC (set);
else if (((code == EQ
|| (code == GE
@@ -7178,8 +8859,10 @@ get_condition (jump, earliest)
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'
- && ((GET_MODE_CLASS (mode) == MODE_CC)
- != (GET_MODE_CLASS (inner_mode) == MODE_CC)))
+ && (((GET_MODE_CLASS (mode) == MODE_CC)
+ == (GET_MODE_CLASS (inner_mode) == MODE_CC))
+ || mode == VOIDmode || inner_mode == VOIDmode))
+
{
/* We might have reversed a LT to get a GE here. But this wasn't
actually the comparison of data, so we don't flag that we
@@ -7238,14 +8921,14 @@ get_condition (jump, earliest)
switch (code)
{
case LE:
- if (const_val != max_val >> 1)
+ if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1)
code = LT, op1 = GEN_INT (const_val + 1);
break;
/* When cross-compiling, const_val might be sign-extended from
BITS_PER_WORD to HOST_BITS_PER_WIDE_INT */
case GE:
- if ((const_val & max_val)
+ if ((HOST_WIDE_INT) (const_val & max_val)
!= (((HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
code = GT, op1 = GEN_INT (const_val - 1);
@@ -7301,551 +8984,720 @@ get_condition_for_loop (x)
XEXP (comparison, 1), XEXP (comparison, 0));
}
-#ifdef HAIFA
-/* Analyze a loop in order to instrument it with the use of count register.
- loop_start and loop_end are the first and last insns of the loop.
- This function works in cooperation with insert_bct ().
- loop_can_insert_bct[loop_num] is set according to whether the optimization
- is applicable to the loop. When it is applicable, the following variables
- are also set:
- loop_start_value[loop_num]
- loop_comparison_value[loop_num]
- loop_increment[loop_num]
- loop_comparison_code[loop_num] */
-
#ifdef HAVE_decrement_and_branch_on_count
-static
-void analyze_loop_iterations (loop_start, loop_end)
- rtx loop_start, loop_end;
-{
- rtx comparison, comparison_value;
- rtx iteration_var, initial_value, increment;
- enum rtx_code comparison_code;
+/* Instrument loop for insertion of bct instruction. We distinguish between
+ loops with compile-time bounds and those with run-time bounds.
+ Information from loop_iterations() is used to compute compile-time bounds.
+ Run-time bounds should use loop preconditioning, but currently ignored.
+ */
- rtx last_loop_insn;
- rtx insn;
+static void
+insert_bct (loop_start, loop_end, loop_info)
+ rtx loop_start, loop_end;
+ struct loop_info *loop_info;
+{
int i;
+ unsigned HOST_WIDE_INT n_iterations;
- /* loop_variable mode */
- enum machine_mode original_mode;
+ int increment_direction, compare_direction;
- /* find the number of the loop */
- int loop_num = uid_loop_num [INSN_UID (loop_start)];
+ /* If the loop condition is <= or >=, the number of iteration
+ is 1 more than the range of the bounds of the loop. */
+ int add_iteration = 0;
- /* we change our mind only when we are sure that loop will be instrumented */
- loop_can_insert_bct[loop_num] = 0;
+ enum machine_mode loop_var_mode = word_mode;
- /* is the optimization suppressed. */
- if ( !flag_branch_on_count_reg )
- return;
+ int loop_num = uid_loop_num [INSN_UID (loop_start)];
- /* make sure that count-reg is not in use */
- if (loop_used_count_register[loop_num]){
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT instrumentation failed: count register already in use\n",
- loop_num);
+ /* It's impossible to instrument a competely unrolled loop. */
+ if (loop_info->unroll_number == -1)
return;
- }
- /* make sure that the function has no indirect jumps. */
- if (indirect_jump_in_function){
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT instrumentation failed: indirect jump in function\n",
- loop_num);
- return;
- }
+ /* Make sure that the count register is not in use. */
+ if (loop_used_count_register [loop_num])
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "insert_bct %d: BCT instrumentation failed: count register already in use\n",
+ loop_num);
+ return;
+ }
- /* make sure that the last loop insn is a conditional jump */
- last_loop_insn = PREV_INSN (loop_end);
- if (GET_CODE (last_loop_insn) != JUMP_INSN || !condjump_p (last_loop_insn)) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT instrumentation failed: invalid jump at loop end\n",
- loop_num);
- return;
- }
+ /* Make sure that the function has no indirect jumps. */
+ if (indirect_jump_in_function)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "insert_bct %d: BCT instrumentation failed: indirect jump in function\n",
+ loop_num);
+ return;
+ }
- /* First find the iteration variable. If the last insn is a conditional
- branch, and the insn preceding it tests a register value, make that
- register the iteration variable. */
+ /* Make sure that the last loop insn is a conditional jump. */
+ if (GET_CODE (PREV_INSN (loop_end)) != JUMP_INSN
+ || ! condjump_p (PREV_INSN (loop_end))
+ || simplejump_p (PREV_INSN (loop_end)))
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "insert_bct %d: BCT instrumentation failed: invalid jump at loop end\n",
+ loop_num);
+ return;
+ }
- /* We used to use prev_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. */
+ /* Make sure that the loop does not contain a function call
+ (the count register might be altered by the called function). */
+ if (loop_has_call)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "insert_bct %d: BCT instrumentation failed: function call in loop\n",
+ loop_num);
+ return;
+ }
- comparison = get_condition_for_loop (last_loop_insn);
- /* ??? Get_condition may switch position of induction variable and
- invariant register when it canonicalizes the comparison. */
+ /* Make sure that the loop does not jump via a table.
+ (the count register might be used to perform the branch on table). */
+ if (loop_has_tablejump)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "insert_bct %d: BCT instrumentation failed: computed branch in the loop\n",
+ loop_num);
+ return;
+ }
- if (comparison == 0) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT instrumentation failed: comparison not found\n",
- loop_num);
- return;
- }
+ /* Account for loop unrolling in instrumented iteration count. */
+ if (loop_info->unroll_number > 1)
+ n_iterations = loop_info->n_iterations / loop_info->unroll_number;
+ else
+ n_iterations = loop_info->n_iterations;
- comparison_code = GET_CODE (comparison);
- iteration_var = XEXP (comparison, 0);
- comparison_value = XEXP (comparison, 1);
+ if (n_iterations != 0 && n_iterations < 3)
+ {
+ /* Allow an enclosing outer loop to benefit if possible. */
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "insert_bct %d: Too few iterations to benefit from BCT optimization\n",
+ loop_num);
+ return;
+ }
- original_mode = GET_MODE (iteration_var);
- if (GET_MODE_CLASS (original_mode) != MODE_INT
- || GET_MODE_SIZE (original_mode) != UNITS_PER_WORD) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT Instrumentation failed: loop variable not integer\n",
- loop_num);
- return;
- }
+ /* Try to instrument the loop. */
- /* get info about loop bounds and increment */
- iteration_info (iteration_var, &initial_value, &increment,
- loop_start, loop_end);
+ /* Handle the simpler case, where the bounds are known at compile time. */
+ if (n_iterations > 0)
+ {
+ /* Mark all enclosing loops that they cannot use count register. */
+ for (i = loop_num; i != -1; i = loop_outer_loop[i])
+ loop_used_count_register[i] = 1;
+ instrument_loop_bct (loop_start, loop_end, GEN_INT (n_iterations));
+ return;
+ }
- /* make sure that all required loop data were found */
- if (!(initial_value && increment && comparison_value
- && invariant_p (comparison_value) && invariant_p (increment)
- && ! indirect_jump_in_function))
+ /* Handle the more complex case, that the bounds are NOT known
+ at compile time. In this case we generate run_time calculation
+ of the number of iterations. */
+
+ if (loop_info->iteration_var == 0)
{
- if (loop_dump_stream) {
+ if (loop_dump_stream)
fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT instrumentation failed because of wrong loop: ", loop_num);
- if (!(initial_value && increment && comparison_value)) {
- fprintf (loop_dump_stream, "\tbounds not available: ");
- if ( ! initial_value )
- fprintf (loop_dump_stream, "initial ");
- if ( ! increment )
- fprintf (loop_dump_stream, "increment ");
- if ( ! comparison_value )
- fprintf (loop_dump_stream, "comparison ");
- fprintf (loop_dump_stream, "\n");
- }
- if (!invariant_p (comparison_value) || !invariant_p (increment))
- fprintf (loop_dump_stream, "\tloop bounds not invariant\n");
- }
+ "insert_bct %d: BCT Runtime Instrumentation failed: no loop iteration variable found\n",
+ loop_num);
return;
}
- /* make sure that the increment is constant */
- if (GET_CODE (increment) != CONST_INT) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: instrumentation failed: not arithmetic loop\n",
- loop_num);
- return;
- }
-
- /* make sure that the loop contains neither function call, nor jump on table.
- (the count register might be altered by the called function, and might
- be used for a branch on table). */
- for (insn = loop_start; insn && insn != loop_end; insn = NEXT_INSN (insn)) {
- if (GET_CODE (insn) == CALL_INSN){
+ if (GET_MODE_CLASS (GET_MODE (loop_info->iteration_var)) != MODE_INT
+ || GET_MODE_SIZE (GET_MODE (loop_info->iteration_var)) != UNITS_PER_WORD)
+ {
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT instrumentation failed: function call in the loop\n",
- loop_num);
+ "insert_bct %d: BCT Runtime Instrumentation failed: loop variable not integer\n",
+ loop_num);
return;
}
- if (GET_CODE (insn) == JUMP_INSN
- && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_VEC)){
+ /* With runtime bounds, if the compare is of the form '!=' we give up */
+ if (loop_info->comparison_code == NE)
+ {
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "analyze_loop_iterations %d: BCT instrumentation failed: computed branch in the loop\n",
- loop_num);
+ "insert_bct %d: BCT Runtime Instrumentation failed: runtime bounds with != comparison\n",
+ loop_num);
return;
}
- }
+/* Use common loop preconditioning code instead. */
+#if 0
+ else
+ {
+ /* We rely on the existence of run-time guard to ensure that the
+ loop executes at least once. */
+ rtx sequence;
+ rtx iterations_num_reg;
- /* At this point, we are sure that the loop can be instrumented with BCT.
- Some of the loops, however, will not be instrumented - the final decision
- is taken by insert_bct () */
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "analyze_loop_iterations: loop (luid =%d) can be BCT instrumented.\n",
- loop_num);
-
- /* mark all enclosing loops that they cannot use count register */
- /* ???: In fact, since insert_bct may decide not to instrument this loop,
- marking here may prevent instrumenting an enclosing loop that could
- actually be instrumented. But since this is rare, it is safer to mark
- here in case the order of calling (analyze/insert)_bct would be changed. */
- for (i=loop_num; i != -1; i = loop_outer_loop[i])
- loop_used_count_register[i] = 1;
-
- /* Set data structures which will be used by the instrumentation phase */
- loop_start_value[loop_num] = initial_value;
- loop_comparison_value[loop_num] = comparison_value;
- loop_increment[loop_num] = increment;
- loop_comparison_code[loop_num] = comparison_code;
- loop_can_insert_bct[loop_num] = 1;
-}
+ unsigned HOST_WIDE_INT increment_value_abs
+ = INTVAL (increment) * increment_direction;
+
+ /* make sure that the increment is a power of two, otherwise (an
+ expensive) divide is needed. */
+ if (exact_log2 (increment_value_abs) == -1)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "insert_bct: not instrumenting BCT because the increment is not power of 2\n");
+ return;
+ }
+ /* compute the number of iterations */
+ start_sequence ();
+ {
+ rtx temp_reg;
-/* instrument loop for insertion of bct instruction. We distinguish between
- loops with compile-time bounds, to those with run-time bounds. The loop
- behaviour is analized according to the following characteristics/variables:
- ; Input variables:
- ; comparison-value: the value to which the iteration counter is compared.
- ; initial-value: iteration-counter initial value.
- ; increment: iteration-counter increment.
- ; Computed variables:
- ; increment-direction: the sign of the increment.
- ; compare-direction: '1' for GT, GTE, '-1' for LT, LTE, '0' for NE.
- ; range-direction: sign (comparison-value - initial-value)
- We give up on the following cases:
- ; loop variable overflow.
- ; run-time loop bounds with comparison code NE.
- */
+ /* Again, the number of iterations is calculated by:
+ ;
+ ; compare-val - initial-val + (increment -1) + additional-iteration
+ ; num_iterations = -----------------------------------------------------------------
+ ; increment
+ */
+ /* ??? Do we have to call copy_rtx here before passing rtx to
+ expand_binop? */
+ if (compare_direction > 0)
+ {
+ /* <, <= :the loop variable is increasing */
+ temp_reg = expand_binop (loop_var_mode, sub_optab,
+ comparison_value, initial_value,
+ NULL_RTX, 0, OPTAB_LIB_WIDEN);
+ }
+ else
+ {
+ temp_reg = expand_binop (loop_var_mode, sub_optab,
+ initial_value, comparison_value,
+ NULL_RTX, 0, OPTAB_LIB_WIDEN);
+ }
+
+ if (increment_value_abs - 1 + add_iteration != 0)
+ temp_reg = expand_binop (loop_var_mode, add_optab, temp_reg,
+ GEN_INT (increment_value_abs - 1
+ + add_iteration),
+ NULL_RTX, 0, OPTAB_LIB_WIDEN);
+
+ if (increment_value_abs != 1)
+ {
+ /* ??? This will generate an expensive divide instruction for
+ most targets. The original authors apparently expected this
+ to be a shift, since they test for power-of-2 divisors above,
+ but just naively generating a divide instruction will not give
+ a shift. It happens to work for the PowerPC target because
+ the rs6000.md file has a divide pattern that emits shifts.
+ It will probably not work for any other target. */
+ iterations_num_reg = expand_binop (loop_var_mode, sdiv_optab,
+ temp_reg,
+ GEN_INT (increment_value_abs),
+ NULL_RTX, 0, OPTAB_LIB_WIDEN);
+ }
+ else
+ iterations_num_reg = temp_reg;
+ }
+ sequence = gen_sequence ();
+ end_sequence ();
+ emit_insn_before (sequence, loop_start);
+ instrument_loop_bct (loop_start, loop_end, iterations_num_reg);
+ }
+
+ return;
+#endif /* Complex case */
+}
+
+/* Instrument loop by inserting a bct in it as follows:
+ 1. A new counter register is created.
+ 2. In the head of the loop the new variable is initialized to the value
+ passed in the loop_num_iterations parameter.
+ 3. At the end of the loop, comparison of the register with 0 is generated.
+ The created comparison follows the pattern defined for the
+ decrement_and_branch_on_count insn, so this insn will be generated.
+ 4. The branch on the old variable are deleted. The compare must remain
+ because it might be used elsewhere. If the loop-variable or condition
+ register are used elsewhere, they will be eliminated by flow. */
static void
-insert_bct (loop_start, loop_end)
+instrument_loop_bct (loop_start, loop_end, loop_num_iterations)
rtx loop_start, loop_end;
+ rtx loop_num_iterations;
{
- rtx initial_value, comparison_value, increment;
- enum rtx_code comparison_code;
+ rtx counter_reg;
+ rtx start_label;
+ rtx sequence;
- int increment_direction, compare_direction;
- int unsigned_p = 0;
+ if (HAVE_decrement_and_branch_on_count)
+ {
+ if (loop_dump_stream)
+ {
+ fputs ("instrument_bct: Inserting BCT (", loop_dump_stream);
+ if (GET_CODE (loop_num_iterations) == CONST_INT)
+ fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
+ INTVAL (loop_num_iterations));
+ else
+ fputs ("runtime", loop_dump_stream);
+ fputs (" iterations)", loop_dump_stream);
+ }
- /* if the loop condition is <= or >=, the number of iteration
- is 1 more than the range of the bounds of the loop */
- int add_iteration = 0;
+ /* Discard original jump to continue loop. Original compare result
+ may still be live, so it cannot be discarded explicitly. */
+ delete_insn (PREV_INSN (loop_end));
- /* the only machine mode we work with - is the integer of the size that the
- machine has */
- enum machine_mode loop_var_mode = SImode;
+ /* Insert the label which will delimit the start of the loop. */
+ start_label = gen_label_rtx ();
+ emit_label_after (start_label, loop_start);
- int loop_num = uid_loop_num [INSN_UID (loop_start)];
+ /* Insert initialization of the count register into the loop header. */
+ start_sequence ();
+ counter_reg = gen_reg_rtx (word_mode);
+ emit_insn (gen_move_insn (counter_reg, loop_num_iterations));
+ sequence = gen_sequence ();
+ end_sequence ();
+ emit_insn_before (sequence, loop_start);
- /* get loop-variables. No need to check that these are valid - already
- checked in analyze_loop_iterations (). */
- comparison_code = loop_comparison_code[loop_num];
- initial_value = loop_start_value[loop_num];
- comparison_value = loop_comparison_value[loop_num];
- increment = loop_increment[loop_num];
+ /* Insert new comparison on the count register instead of the
+ old one, generating the needed BCT pattern (that will be
+ later recognized by assembly generation phase). */
+ emit_jump_insn_before (gen_decrement_and_branch_on_count (counter_reg,
+ start_label),
+ loop_end);
+ LABEL_NUSES (start_label)++;
+ }
- /* check analyze_loop_iterations decision for this loop. */
- if (! loop_can_insert_bct[loop_num]){
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: [%d] - was decided not to instrument by analyze_loop_iterations ()\n",
- loop_num);
- return;
- }
+}
+#endif /* HAVE_decrement_and_branch_on_count */
- /* It's impossible to instrument a competely unrolled loop. */
- if (loop_unroll_factor [loop_num] == -1)
- return;
+/* Scan the function and determine whether it has indirect (computed) jumps.
- /* make sure that the last loop insn is a conditional jump .
- This check is repeated from analyze_loop_iterations (),
- because unrolling might have changed that. */
- if (GET_CODE (PREV_INSN (loop_end)) != JUMP_INSN
- || !condjump_p (PREV_INSN (loop_end))) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: not instrumenting BCT because of invalid branch\n");
- return;
- }
+ This is taken mostly from flow.c; similar code exists elsewhere
+ in the compiler. It may be useful to put this into rtlanal.c. */
+static int
+indirect_jump_in_function_p (start)
+ rtx start;
+{
+ rtx insn;
- /* fix increment in case loop was unrolled. */
- if (loop_unroll_factor [loop_num] > 1)
- increment = GEN_INT ( INTVAL (increment) * loop_unroll_factor [loop_num] );
-
- /* determine properties and directions of the loop */
- increment_direction = (INTVAL (increment) > 0) ? 1:-1;
- switch ( comparison_code ) {
- case LEU:
- unsigned_p = 1;
- /* fallthrough */
- case LE:
- compare_direction = 1;
- add_iteration = 1;
- break;
- case GEU:
- unsigned_p = 1;
- /* fallthrough */
- case GE:
- compare_direction = -1;
- add_iteration = 1;
- break;
- case EQ:
- /* in this case we cannot know the number of iterations */
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: %d: loop cannot be instrumented: == in condition\n",
- loop_num);
- return;
- case LTU:
- unsigned_p = 1;
- /* fallthrough */
- case LT:
- compare_direction = 1;
- break;
- case GTU:
- unsigned_p = 1;
- /* fallthrough */
- case GT:
- compare_direction = -1;
- break;
- case NE:
- compare_direction = 0;
- break;
- default:
- abort ();
- }
+ for (insn = start; insn; insn = NEXT_INSN (insn))
+ if (computed_jump_p (insn))
+ return 1;
+ return 0;
+}
- /* make sure that the loop does not end by an overflow */
- if (compare_direction != increment_direction) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: %d: loop cannot be instrumented: terminated by overflow\n",
- loop_num);
- return;
- }
+/* Add MEM to the LOOP_MEMS array, if appropriate. See the
+ documentation for LOOP_MEMS for the definition of `appropriate'.
+ This function is called from prescan_loop via for_each_rtx. */
- /* try to instrument the loop. */
+static int
+insert_loop_mem (mem, data)
+ rtx *mem;
+ void *data ATTRIBUTE_UNUSED;
+{
+ int i;
+ rtx m = *mem;
- /* Handle the simpler case, where the bounds are known at compile time. */
- if (GET_CODE (initial_value) == CONST_INT && GET_CODE (comparison_value) == CONST_INT)
+ if (m == NULL_RTX)
+ return 0;
+
+ switch (GET_CODE (m))
{
- int n_iterations;
- int increment_value_abs = INTVAL (increment) * increment_direction;
+ case MEM:
+ break;
- /* check the relation between compare-val and initial-val */
- int difference = INTVAL (comparison_value) - INTVAL (initial_value);
- int range_direction = (difference > 0) ? 1 : -1;
+ case CONST_DOUBLE:
+ /* We're not interested in the MEM associated with a
+ CONST_DOUBLE, so there's no need to traverse into this. */
+ return -1;
- /* make sure the loop executes enough iterations to gain from BCT */
- if (difference > -3 && difference < 3) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: loop %d not BCT instrumented: too small iteration count.\n",
- loop_num);
- return;
+ default:
+ /* This is not a MEM. */
+ return 0;
+ }
+
+ /* See if we've already seen this MEM. */
+ for (i = 0; i < loop_mems_idx; ++i)
+ if (rtx_equal_p (m, loop_mems[i].mem))
+ {
+ if (GET_MODE (m) != GET_MODE (loop_mems[i].mem))
+ /* The modes of the two memory accesses are different. If
+ this happens, something tricky is going on, and we just
+ don't optimize accesses to this MEM. */
+ loop_mems[i].optimize = 0;
+
+ return 0;
}
- /* make sure that the loop executes at least once */
- if ((range_direction == 1 && compare_direction == -1)
- || (range_direction == -1 && compare_direction == 1))
+ /* Resize the array, if necessary. */
+ if (loop_mems_idx == loop_mems_allocated)
+ {
+ if (loop_mems_allocated != 0)
+ loop_mems_allocated *= 2;
+ else
+ loop_mems_allocated = 32;
+
+ loop_mems = (loop_mem_info*)
+ xrealloc (loop_mems,
+ loop_mems_allocated * sizeof (loop_mem_info));
+ }
+
+ /* Actually insert the MEM. */
+ loop_mems[loop_mems_idx].mem = m;
+ /* We can't hoist this MEM out of the loop if it's a BLKmode MEM
+ because we can't put it in a register. We still store it in the
+ table, though, so that if we see the same address later, but in a
+ non-BLK mode, we'll not think we can optimize it at that point. */
+ loop_mems[loop_mems_idx].optimize = (GET_MODE (m) != BLKmode);
+ loop_mems[loop_mems_idx].reg = NULL_RTX;
+ ++loop_mems_idx;
+
+ return 0;
+}
+
+/* Like load_mems, but also ensures that SET_IN_LOOP,
+ MAY_NOT_OPTIMIZE, REG_SINGLE_USAGE, and INSN_COUNT have the correct
+ values after load_mems. */
+
+static void
+load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start,
+ insn_count)
+ rtx scan_start;
+ rtx end;
+ rtx loop_top;
+ rtx start;
+ int *insn_count;
+{
+ int nregs = max_reg_num ();
+
+ load_mems (scan_start, end, loop_top, start);
+
+ /* Recalculate set_in_loop and friends since load_mems may have
+ created new registers. */
+ if (max_reg_num () > nregs)
+ {
+ int i;
+ int old_nregs;
+
+ old_nregs = nregs;
+ nregs = max_reg_num ();
+
+ if ((unsigned) nregs > set_in_loop->num_elements)
{
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: loop %d: does not iterate even once. Not instrumenting.\n",
- loop_num);
- return;
+ /* Grow all the arrays. */
+ VARRAY_GROW (set_in_loop, nregs);
+ VARRAY_GROW (n_times_set, nregs);
+ VARRAY_GROW (may_not_optimize, nregs);
+ VARRAY_GROW (reg_single_usage, nregs);
}
+ /* Clear the arrays */
+ bzero ((char *) &set_in_loop->data, nregs * sizeof (int));
+ bzero ((char *) &may_not_optimize->data, nregs * sizeof (char));
+ bzero ((char *) &reg_single_usage->data, nregs * sizeof (rtx));
- /* make sure that the loop does not end by an overflow (in compile time
- bounds we must have an additional check for overflow, because here
- we also support the compare code of 'NE'. */
- if (comparison_code == NE
- && increment_direction != range_direction) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct (compile time bounds): %d: loop not instrumented: terminated by overflow\n",
- loop_num);
- return;
- }
+ count_loop_regs_set (loop_top ? loop_top : start, end,
+ may_not_optimize, reg_single_usage,
+ insn_count, nregs);
- /* Determine the number of iterations by:
- ;
- ; compare-val - initial-val + (increment -1) + additional-iteration
- ; num_iterations = -----------------------------------------------------------------
- ; increment
- */
- difference = (range_direction > 0) ? difference : -difference;
-#if 0
- fprintf (stderr, "difference is: %d\n", difference); /* @*/
- fprintf (stderr, "increment_value_abs is: %d\n", increment_value_abs); /* @*/
- fprintf (stderr, "add_iteration is: %d\n", add_iteration); /* @*/
- fprintf (stderr, "INTVAL (comparison_value) is: %d\n", INTVAL (comparison_value)); /* @*/
- fprintf (stderr, "INTVAL (initial_value) is: %d\n", INTVAL (initial_value)); /* @*/
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ VARRAY_CHAR (may_not_optimize, i) = 1;
+ VARRAY_INT (set_in_loop, i) = 1;
+ }
+
+#ifdef AVOID_CCMODE_COPIES
+ /* Don't try to move insns which set CC registers if we should not
+ create CCmode register copies. */
+ for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
+ if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
+ VARRAY_CHAR (may_not_optimize, i) = 1;
#endif
- if (increment_value_abs == 0) {
- fprintf (stderr, "insert_bct: error: increment == 0 !!!\n");
- abort ();
- }
- n_iterations = (difference + increment_value_abs - 1 + add_iteration)
- / increment_value_abs;
+ /* Set n_times_set for the new registers. */
+ bcopy ((char *) (&set_in_loop->data.i[0] + old_nregs),
+ (char *) (&n_times_set->data.i[0] + old_nregs),
+ (nregs - old_nregs) * sizeof (int));
+ }
+}
-#if 0
- fprintf (stderr, "number of iterations is: %d\n", n_iterations); /* @*/
-#endif
- instrument_loop_bct (loop_start, loop_end, GEN_INT (n_iterations));
+/* Move MEMs into registers for the duration of the loop. SCAN_START
+ is the first instruction in the loop (as it is executed). The
+ other parameters are as for next_insn_in_loop. */
- /* Done with this loop. */
- return;
- }
+static void
+load_mems (scan_start, end, loop_top, start)
+ rtx scan_start;
+ rtx end;
+ rtx loop_top;
+ rtx start;
+{
+ int maybe_never = 0;
+ int i;
+ rtx p;
+ rtx label = NULL_RTX;
+ rtx end_label;
- /* Handle the more complex case, that the bounds are NOT known at compile time. */
- /* In this case we generate run_time calculation of the number of iterations */
+ if (loop_mems_idx > 0)
+ {
+ /* Nonzero if the next instruction may never be executed. */
+ int next_maybe_never = 0;
+
+ /* Check to see if it's possible that some instructions in the
+ loop are never executed. */
+ for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top);
+ p != NULL_RTX && !maybe_never;
+ p = next_insn_in_loop (p, scan_start, end, loop_top))
+ {
+ if (GET_CODE (p) == CODE_LABEL)
+ maybe_never = 1;
+ else if (GET_CODE (p) == JUMP_INSN
+ /* If we enter the loop in the middle, and scan
+ around to the beginning, don't set maybe_never
+ for that. This must be an unconditional jump,
+ otherwise the code at the top of the loop might
+ never be executed. Unconditional jumps are
+ followed a by barrier then loop end. */
+ && ! (GET_CODE (p) == JUMP_INSN
+ && JUMP_LABEL (p) == loop_top
+ && NEXT_INSN (NEXT_INSN (p)) == end
+ && simplejump_p (p)))
+ {
+ if (!condjump_p (p))
+ /* Something complicated. */
+ maybe_never = 1;
+ else
+ /* If there are any more instructions in the loop, they
+ might not be reached. */
+ next_maybe_never = 1;
+ }
+ else if (next_maybe_never)
+ maybe_never = 1;
+ }
- /* With runtime bounds, if the compare is of the form '!=' we give up */
- if (comparison_code == NE) {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: fail for loop %d: runtime bounds with != comparison\n",
- loop_num);
- return;
- }
+ /* Actually move the MEMs. */
+ for (i = 0; i < loop_mems_idx; ++i)
+ {
+ int written = 0;
+ rtx reg;
+ rtx mem = loop_mems[i].mem;
+ rtx mem_list_entry;
+
+ if (MEM_VOLATILE_P (mem)
+ || invariant_p (XEXP (mem, 0)) != 1)
+ /* There's no telling whether or not MEM is modified. */
+ loop_mems[i].optimize = 0;
+
+ /* Go through the MEMs written to in the loop to see if this
+ one is aliased by one of them. */
+ mem_list_entry = loop_store_mems;
+ while (mem_list_entry)
+ {
+ if (rtx_equal_p (mem, XEXP (mem_list_entry, 0)))
+ written = 1;
+ else if (true_dependence (XEXP (mem_list_entry, 0), VOIDmode,
+ mem, rtx_varies_p))
+ {
+ /* MEM is indeed aliased by this store. */
+ loop_mems[i].optimize = 0;
+ break;
+ }
+ mem_list_entry = XEXP (mem_list_entry, 1);
+ }
+
+ /* If this MEM is written to, we must be sure that there
+ are no reads from another MEM that aliases this one. */
+ if (loop_mems[i].optimize && written)
+ {
+ int j;
- else {
- /* We rely on the existence of run-time guard to ensure that the
- loop executes at least once. */
- rtx sequence;
- rtx iterations_num_reg;
+ for (j = 0; j < loop_mems_idx; ++j)
+ {
+ if (j == i)
+ continue;
+ else if (true_dependence (mem,
+ VOIDmode,
+ loop_mems[j].mem,
+ rtx_varies_p))
+ {
+ /* It's not safe to hoist loop_mems[i] out of
+ the loop because writes to it might not be
+ seen by reads from loop_mems[j]. */
+ loop_mems[i].optimize = 0;
+ break;
+ }
+ }
+ }
- int increment_value_abs = INTVAL (increment) * increment_direction;
+ if (maybe_never && may_trap_p (mem))
+ /* We can't access the MEM outside the loop; it might
+ cause a trap that wouldn't have happened otherwise. */
+ loop_mems[i].optimize = 0;
+
+ if (!loop_mems[i].optimize)
+ /* We thought we were going to lift this MEM out of the
+ loop, but later discovered that we could not. */
+ continue;
- /* make sure that the increment is a power of two, otherwise (an
- expensive) divide is needed. */
- if (exact_log2 (increment_value_abs) == -1)
- {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "insert_bct: not instrumenting BCT because the increment is not power of 2\n");
- return;
- }
+ /* Allocate a pseudo for this MEM. We set REG_USERVAR_P in
+ order to keep scan_loop from moving stores to this MEM
+ out of the loop just because this REG is neither a
+ user-variable nor used in the loop test. */
+ reg = gen_reg_rtx (GET_MODE (mem));
+ REG_USERVAR_P (reg) = 1;
+ loop_mems[i].reg = reg;
+
+ /* Now, replace all references to the MEM with the
+ corresponding pesudos. */
+ for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top);
+ p != NULL_RTX;
+ p = next_insn_in_loop (p, scan_start, end, loop_top))
+ {
+ rtx_and_int ri;
+ ri.r = p;
+ ri.i = i;
+ for_each_rtx (&p, replace_loop_mem, &ri);
+ }
- /* compute the number of iterations */
- start_sequence ();
- {
- rtx temp_reg;
+ if (!apply_change_group ())
+ /* We couldn't replace all occurrences of the MEM. */
+ loop_mems[i].optimize = 0;
+ else
+ {
+ rtx set;
- /* Again, the number of iterations is calculated by:
- ;
- ; compare-val - initial-val + (increment -1) + additional-iteration
- ; num_iterations = -----------------------------------------------------------------
- ; increment
- */
- /* ??? Do we have to call copy_rtx here before passing rtx to
- expand_binop? */
- if (compare_direction > 0) {
- /* <, <= :the loop variable is increasing */
- temp_reg = expand_binop (loop_var_mode, sub_optab, comparison_value,
- initial_value, NULL_RTX, 0, OPTAB_LIB_WIDEN);
- }
- else {
- temp_reg = expand_binop (loop_var_mode, sub_optab, initial_value,
- comparison_value, NULL_RTX, 0, OPTAB_LIB_WIDEN);
- }
+ /* Load the memory immediately before START, which is
+ the NOTE_LOOP_BEG. */
+ set = gen_move_insn (reg, mem);
+ emit_insn_before (set, start);
+
+ if (written)
+ {
+ if (label == NULL_RTX)
+ {
+ /* We must compute the former
+ right-after-the-end label before we insert
+ the new one. */
+ end_label = next_label (end);
+ label = gen_label_rtx ();
+ emit_label_after (label, end);
+ }
+
+ /* Store the memory immediately after END, which is
+ the NOTE_LOOP_END. */
+ set = gen_move_insn (copy_rtx (mem), reg);
+ emit_insn_after (set, label);
+ }
- if (increment_value_abs - 1 + add_iteration != 0)
- temp_reg = expand_binop (loop_var_mode, add_optab, temp_reg,
- GEN_INT (increment_value_abs - 1 + add_iteration),
- NULL_RTX, 0, OPTAB_LIB_WIDEN);
+ if (loop_dump_stream)
+ {
+ fprintf (loop_dump_stream, "Hoisted regno %d %s from ",
+ REGNO (reg), (written ? "r/w" : "r/o"));
+ print_rtl (loop_dump_stream, mem);
+ fputc ('\n', loop_dump_stream);
+ }
+ }
+ }
+ }
+
+ if (label != NULL_RTX)
+ {
+ /* Now, we need to replace all references to the previous exit
+ label with the new one. */
+ rtx_pair rr;
+ rr.r1 = end_label;
+ rr.r2 = label;
- if (increment_value_abs != 1)
+ for (p = start; p != end; p = NEXT_INSN (p))
{
- /* ??? This will generate an expensive divide instruction for
- most targets. The original authors apparently expected this
- to be a shift, since they test for power-of-2 divisors above,
- but just naively generating a divide instruction will not give
- a shift. It happens to work for the PowerPC target because
- the rs6000.md file has a divide pattern that emits shifts.
- It will probably not work for any other target. */
- iterations_num_reg = expand_binop (loop_var_mode, sdiv_optab,
- temp_reg,
- GEN_INT (increment_value_abs),
- NULL_RTX, 0, OPTAB_LIB_WIDEN);
+ for_each_rtx (&p, replace_label, &rr);
+
+ /* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
+ field. This is not handled by for_each_rtx because it doesn't
+ handle unprinted ('0') fields. We need to update JUMP_LABEL
+ because the immediately following unroll pass will use it.
+ replace_label would not work anyways, because that only handles
+ LABEL_REFs. */
+ if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == end_label)
+ JUMP_LABEL (p) = label;
}
- else
- iterations_num_reg = temp_reg;
}
- sequence = gen_sequence ();
- end_sequence ();
- emit_insn_before (sequence, loop_start);
- instrument_loop_bct (loop_start, loop_end, iterations_num_reg);
- }
}
-/* instrument loop by inserting a bct in it. This is done in the following way:
- 1. A new register is created and assigned the hard register number of the count
- register.
- 2. In the head of the loop the new variable is initialized by the value passed in the
- loop_num_iterations parameter.
- 3. At the end of the loop, comparison of the register with 0 is generated.
- The created comparison follows the pattern defined for the
- decrement_and_branch_on_count insn, so this insn will be generated in assembly
- generation phase.
- 4. The compare&branch on the old variable is deleted. So, if the loop-variable was
- not used elsewhere, it will be eliminated by data-flow analisys. */
+/* Replace MEM with its associated pseudo register. This function is
+ called from load_mems via for_each_rtx. DATA is actually an
+ rtx_and_int * describing the instruction currently being scanned
+ and the MEM we are currently replacing. */
-static void
-instrument_loop_bct (loop_start, loop_end, loop_num_iterations)
- rtx loop_start, loop_end;
- rtx loop_num_iterations;
+static int
+replace_loop_mem (mem, data)
+ rtx *mem;
+ void *data;
{
- rtx temp_reg1, temp_reg2;
- rtx start_label;
+ rtx_and_int *ri;
+ rtx insn;
+ int i;
+ rtx m = *mem;
- rtx sequence;
- enum machine_mode loop_var_mode = SImode;
+ if (m == NULL_RTX)
+ return 0;
- if (HAVE_decrement_and_branch_on_count)
+ switch (GET_CODE (m))
{
- if (loop_dump_stream)
- fprintf (loop_dump_stream, "Loop: Inserting BCT\n");
+ case MEM:
+ break;
- /* eliminate the check on the old variable */
- delete_insn (PREV_INSN (loop_end));
- delete_insn (PREV_INSN (loop_end));
+ case CONST_DOUBLE:
+ /* We're not interested in the MEM associated with a
+ CONST_DOUBLE, so there's no need to traverse into one. */
+ return -1;
- /* insert the label which will delimit the start of the loop */
- start_label = gen_label_rtx ();
- emit_label_after (start_label, loop_start);
+ default:
+ /* This is not a MEM. */
+ return 0;
+ }
- /* insert initialization of the count register into the loop header */
- start_sequence ();
- temp_reg1 = gen_reg_rtx (loop_var_mode);
- emit_insn (gen_move_insn (temp_reg1, loop_num_iterations));
+ ri = (rtx_and_int*) data;
+ i = ri->i;
- /* this will be count register */
- temp_reg2 = gen_rtx_REG (loop_var_mode, COUNT_REGISTER_REGNUM);
- /* we have to move the value to the count register from an GPR
- because rtx pointed to by loop_num_iterations could contain
- expression which cannot be moved into count register */
- emit_insn (gen_move_insn (temp_reg2, temp_reg1));
+ if (!rtx_equal_p (loop_mems[i].mem, m))
+ /* This is not the MEM we are currently replacing. */
+ return 0;
- sequence = gen_sequence ();
- end_sequence ();
- emit_insn_after (sequence, loop_start);
+ insn = ri->r;
- /* insert new comparison on the count register instead of the
- old one, generating the needed BCT pattern (that will be
- later recognized by assembly generation phase). */
- emit_jump_insn_before (gen_decrement_and_branch_on_count (temp_reg2, start_label),
- loop_end);
- LABEL_NUSES (start_label)++;
- }
+ /* Actually replace the MEM. */
+ validate_change (insn, mem, loop_mems[i].reg, 1);
+ return 0;
}
-#endif /* HAVE_decrement_and_branch_on_count */
-#endif /* HAIFA */
+/* Replace occurrences of the old exit label for the loop with the new
+ one. DATA is an rtx_pair containing the old and new labels,
+ respectively. */
-/* Scan the function and determine whether it has indirect (computed) jumps.
-
- This is taken mostly from flow.c; similar code exists elsewhere
- in the compiler. It may be useful to put this into rtlanal.c. */
static int
-indirect_jump_in_function_p (start)
- rtx start;
+replace_label (x, data)
+ rtx *x;
+ void *data;
{
- rtx insn;
+ rtx l = *x;
+ rtx old_label = ((rtx_pair*) data)->r1;
+ rtx new_label = ((rtx_pair*) data)->r2;
- for (insn = start; insn; insn = NEXT_INSN (insn))
- if (computed_jump_p (insn))
- return 1;
+ if (l == NULL_RTX)
+ return 0;
+
+ if (GET_CODE (l) != LABEL_REF)
+ return 0;
+
+ if (XEXP (l, 0) != old_label)
+ return 0;
+
+ XEXP (l, 0) = new_label;
+ ++LABEL_NUSES (new_label);
+ --LABEL_NUSES (old_label);
return 0;
}
+
diff --git a/contrib/gcc/loop.h b/contrib/gcc/loop.h
index 25c16f0..e164428 100644
--- a/contrib/gcc/loop.h
+++ b/contrib/gcc/loop.h
@@ -1,5 +1,5 @@
/* Loop optimization definitions for GNU C-Compiler
- Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1995, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "varray.h"
+
/* Get the luid of an insn. Catch the error of trying to reference the LUID
of an insn added during loop, since these don't have LUIDs. */
@@ -54,6 +56,8 @@ struct induction
For a DEST_ADDR type giv, this is 0. */
rtx *location; /* Place in the insn where this giv occurs.
If GIV_TYPE is DEST_REG, this is 0. */
+ /* For a biv, this is the place where add_val
+ was found. */
enum machine_mode mode; /* The mode of this biv or giv */
enum machine_mode mem_mode; /* For DEST_ADDR, mode of the memory object. */
rtx mult_val; /* Multiplicative factor for src_reg. */
@@ -63,6 +67,9 @@ struct induction
final value could be calculated, it is put
here, and the giv is made replaceable. Set
the giv to this value before the loop. */
+ unsigned combined_with; /* The number of givs this giv has been
+ combined with. If nonzero, this giv
+ cannot combine with any other giv. */
unsigned replaceable : 1; /* 1 if we can substitute the strength-reduced
variable for the original variable.
0 means they must be kept separate and the
@@ -85,8 +92,6 @@ struct induction
another giv. This occurs in many cases
where a giv's lifetime spans an update to
a biv. */
- unsigned combined_with : 1; /* 1 if this giv has been combined with. It
- then cannot combine with any other giv. */
unsigned maybe_dead : 1; /* 1 if this giv might be dead. In that case,
we won't use it to eliminate a biv, it
would probably lose. */
@@ -95,8 +100,8 @@ struct induction
unsigned unrolled : 1; /* 1 if new register has been allocated and
initialized in unrolled loop. */
unsigned shared : 1;
+ unsigned no_const_addval : 1; /* 1 if add_val does not contain a const. */
int lifetime; /* Length of life of this giv */
- int times_used; /* # times this giv is used. */
rtx derive_adjustment; /* If nonzero, is an adjustment to be
subtracted from add_val when this giv
derives another. This occurs when the
@@ -108,14 +113,20 @@ struct induction
struct induction *same; /* If this giv has been combined with another
giv, this points to the base giv. The base
giv will have COMBINED_WITH non-zero. */
+ struct induction *derived_from;/* For a giv, if we decided to derive this
+ giv from another one. */
HOST_WIDE_INT const_adjust; /* Used by loop unrolling, when an address giv
is split, and a constant is eliminated from
the address, the -constant is stored here
for later use. */
+ int ix; /* Used by recombine_givs, as n index into
+ the stats array. */
struct induction *same_insn; /* If there are multiple identical givs in
the same insn, then all but one have this
field set, and they all point to the giv
that doesn't have this field set. */
+ rtx last_use; /* For a giv made from a biv increment, this is
+ a substitute for the lifetime information. */
};
/* A `struct iv_class' is created for each biv. */
@@ -142,6 +153,45 @@ struct iv_class {
biv controls. */
};
+/* Information required to calculate the number of loop iterations.
+ This is set by loop_iterations. */
+
+struct loop_info
+{
+ /* Register or constant initial loop value. */
+ rtx initial_value;
+ /* Register or constant value used for comparison test. */
+ rtx comparison_value;
+ /* Register or constant approximate final value. */
+ rtx final_value;
+ /* Register or constant initial loop value with term common to
+ final_value removed. */
+ rtx initial_equiv_value;
+ /* Register or constant final loop value with term common to
+ initial_value removed. */
+ rtx final_equiv_value;
+ /* Register corresponding to iteration variable. */
+ rtx iteration_var;
+ /* Constant loop increment. */
+ rtx increment;
+ enum rtx_code comparison_code;
+ /* Holds the number of loop iterations. It is zero if the number
+ could not be calculated. Must be unsigned since the number of
+ iterations can be as high as 2^wordsize - 1. For loops with a
+ wider iterator, this number will be zero if the number of loop
+ iterations is too large for an unsigned integer to hold. */
+ unsigned HOST_WIDE_INT n_iterations;
+ /* The loop unrolling factor.
+ Potential values:
+ 0: unrolled
+ 1: not unrolled.
+ -1: completely unrolled
+ >0: holds the unroll exact factor. */
+ unsigned int unroll_number;
+ /* Non-zero if the loop has a NOTE_INSN_LOOP_VTOP. */
+ rtx vtop;
+};
+
/* Definitions used by the basic induction variable discovery code. */
enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT,
GENERAL_INDUCT };
@@ -154,38 +204,46 @@ extern int *uid_loop_num;
extern int *loop_outer_loop;
extern rtx *loop_number_exit_labels;
extern int *loop_number_exit_count;
-extern unsigned HOST_WIDE_INT loop_n_iterations;
extern int max_reg_before_loop;
extern FILE *loop_dump_stream;
-extern enum iv_mode *reg_iv_type;
-extern struct induction **reg_iv_info;
+extern varray_type reg_iv_type;
+extern varray_type reg_iv_info;
+
+#define REG_IV_TYPE(n) \
+ (*(enum iv_mode *) &VARRAY_INT(reg_iv_type, (n)))
+#define REG_IV_INFO(n) \
+ (*(struct induction **) &VARRAY_GENERIC_PTR(reg_iv_info, (n)))
+
extern struct iv_class **reg_biv_class;
extern struct iv_class *loop_iv_list;
+extern int first_increment_giv, last_increment_giv;
+
/* Forward declarations for non-static functions declared in loop.c and
unroll.c. */
int invariant_p PROTO((rtx));
rtx get_condition_for_loop PROTO((rtx));
void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx));
+rtx express_from PROTO((struct induction *, struct induction *));
-/* Forward declarations for non-static functions declared in stmt.c. */
-void find_loop_tree_blocks PROTO((void));
-void unroll_block_trees PROTO((void));
-
-void unroll_loop PROTO((rtx, int, rtx, rtx, int));
+void unroll_loop PROTO((rtx, int, rtx, rtx, struct loop_info *, int));
rtx biv_total_increment PROTO((struct iv_class *, rtx, rtx));
-unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx));
-rtx final_biv_value PROTO((struct iv_class *, rtx, rtx));
-rtx final_giv_value PROTO((struct induction *, rtx, rtx));
+unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx, struct loop_info *));
+int precondition_loop_p PROTO((rtx, struct loop_info *,
+ rtx *, rtx *, rtx *,
+ enum machine_mode *mode));
+rtx final_biv_value PROTO((struct iv_class *, rtx, rtx,
+ unsigned HOST_WIDE_INT));
+rtx final_giv_value PROTO((struct induction *, rtx, rtx,
+ unsigned HOST_WIDE_INT));
void emit_unrolled_add PROTO((rtx, rtx, rtx));
int back_branch_in_range_p PROTO((rtx, rtx, rtx));
+int loop_insn_first_p PROTO((rtx, rtx));
-extern int *loop_unroll_factor;
-#ifdef HAIFA
-/* variables for interaction between unroll.c and loop.c, for
- the insertion of branch-on-count instruction. */
-extern rtx *loop_start_value;
-#endif /* HAIFA */
+extern int *loop_unroll_number;
+/* Forward declarations for non-static functions declared in stmt.c. */
+void find_loop_tree_blocks PROTO((void));
+void unroll_block_trees PROTO((void));
diff --git a/contrib/gcc/machmode.h b/contrib/gcc/machmode.h
index 5f8459d..5814007 100644
--- a/contrib/gcc/machmode.h
+++ b/contrib/gcc/machmode.h
@@ -1,5 +1,5 @@
/* Machine mode definitions for GNU C-Compiler; included by rtl.h and tree.h.
- Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1994, 1996, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,34 +21,8 @@ Boston, MA 02111-1307, USA. */
#ifndef HAVE_MACHINE_MODES
#define HAVE_MACHINE_MODES
-#include "gansidecl.h"
-
/* Strictly speaking, this isn't the proper place to include these definitions,
- but this file is included by every GCC file.
-
- Some systems define these in, e.g., param.h. We undefine these names
- here to avoid the warnings. We prefer to use our definitions since we
- know they are correct. */
-
-#undef MIN
-#undef MAX
-
-#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-
-/* 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
+ but this file is included by every GCC file. */
/* Provide a default way to print an address in hex via printf. */
@@ -62,69 +36,6 @@ Boston, MA 02111-1307, USA. */
# endif
#endif /* ! HOST_PTR_PRINTF */
-/* Provide defaults for the way to print a HOST_WIDE_INT
- in various manners. */
-
-#ifndef HOST_WIDE_INT_PRINT_DEC
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
-#define HOST_WIDE_INT_PRINT_DEC "%d"
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-#define HOST_WIDE_INT_PRINT_DEC "%ld"
-#else
-#define HOST_WIDE_INT_PRINT_DEC "%lld"
-#endif
-#endif
-#endif
-
-#ifndef HOST_WIDE_INT_PRINT_UNSIGNED
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
-#define HOST_WIDE_INT_PRINT_UNSIGNED "%u"
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-#define HOST_WIDE_INT_PRINT_UNSIGNED "%lu"
-#else
-#define HOST_WIDE_INT_PRINT_UNSIGNED "%llu"
-#endif
-#endif
-#endif
-
-#ifndef HOST_WIDE_INT_PRINT_HEX
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
-#define HOST_WIDE_INT_PRINT_HEX "0x%x"
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-#define HOST_WIDE_INT_PRINT_HEX "0x%lx"
-#else
-#define HOST_WIDE_INT_PRINT_HEX "0x%llx"
-#endif
-#endif
-#endif
-
-#ifndef HOST_WIDE_INT_PRINT_DOUBLE_HEX
-#if HOST_BITS_PER_WIDE_INT == 64
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
-#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%016x"
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%016lx"
-#else
-#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%016llx"
-#endif
-#endif
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
-#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%08x"
-#else
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%08lx"
-#else
-#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%08llx"
-#endif
-#endif
-#endif
-#endif
-
/* Make an enum class that gives all the machine modes. */
#define DEF_MACHMODE(SYM, NAME, TYPE, SIZE, UNIT, WIDER) SYM,
@@ -193,17 +104,21 @@ extern int mode_unit_size[];
#define GET_MODE_BITSIZE(MODE) (BITS_PER_UNIT * mode_size[(int) (MODE)])
+#ifdef HOST_WIDE_INT
+
/* Get a bitmask containing 1 for all bits in a word
that fit within mode MODE. */
-#define GET_MODE_MASK(MODE) \
- ((GET_MODE_BITSIZE (MODE) >= HOST_BITS_PER_WIDE_INT) \
- ?(HOST_WIDE_INT) ~0 : (((HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (MODE)) - 1))
+extern unsigned HOST_WIDE_INT mode_mask_array[];
+
+#define GET_MODE_MASK(MODE) mode_mask_array[(int) (MODE)]
+
+#endif /* HOST_WIDE_INT */
/* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */
-extern enum machine_mode mode_wider_mode[];
-#define GET_MODE_WIDER_MODE(MODE) (mode_wider_mode[(int) (MODE)])
+extern unsigned char mode_wider_mode[];
+#define GET_MODE_WIDER_MODE(MODE) ((enum machine_mode)mode_wider_mode[(int) (MODE)])
/* Return the mode for data of a given size SIZE and mode class CLASS.
If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
@@ -211,6 +126,17 @@ extern enum machine_mode mode_wider_mode[];
extern enum machine_mode mode_for_size PROTO((unsigned int, enum mode_class, int));
+/* Similar, but find the smallest mode for a given width. */
+
+extern enum machine_mode smallest_mode_for_size PROTO((unsigned int,
+ enum mode_class));
+
+
+/* Return an integer mode of the exact same size as the input mode,
+ or BLKmode on failure. */
+
+extern enum machine_mode int_mode_for_mode PROTO((enum machine_mode));
+
/* Find the best mode to use to access a bit field. */
extern enum machine_mode get_best_mode PROTO((int, int, int, enum machine_mode, int));
diff --git a/contrib/gcc/mbchar.c b/contrib/gcc/mbchar.c
new file mode 100644
index 0000000..a22e52b
--- /dev/null
+++ b/contrib/gcc/mbchar.c
@@ -0,0 +1,290 @@
+/* Multibyte Character Functions.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* These functions are used to manipulate multibyte characters. */
+
+/* Note regarding cross compilation:
+
+ In general translation of multibyte characters to wide characters can
+ only work in a native compiler since the translation function (mbtowc)
+ needs to know about both the source and target character encoding. However,
+ this particular implementation for JIS, SJIS and EUCJP source characters
+ will work for any compiler with a newlib target. Other targets may also
+ work provided that their wchar_t implementation is 2 bytes and the encoding
+ leaves the source character values unchanged (except for removing the
+ state shifting markers). */
+
+#ifdef MULTIBYTE_CHARS
+#include "config.h"
+#include "system.h"
+#include "mbchar.h"
+#include <locale.h>
+
+typedef enum
+{
+ ESCAPE, DOLLAR, BRACKET, AT, B, J, NUL, JIS_CHAR, OTHER, JIS_C_NUM
+} JIS_CHAR_TYPE;
+
+typedef enum
+{
+ ASCII, A_ESC, A_ESC_DL, JIS, JIS_1, JIS_2, J_ESC, J_ESC_BR,
+ J2_ESC, J2_ESC_BR, INV, JIS_S_NUM
+} JIS_STATE;
+
+typedef enum
+{
+ COPYA, COPYJ, COPYJ2, MAKE_A, MAKE_J, NOOP, EMPTY, ERROR
+} JIS_ACTION;
+
+/*****************************************************************************
+ * state/action tables for processing JIS encoding
+ * Where possible, switches to JIS are grouped with proceding JIS characters
+ * and switches to ASCII are grouped with preceding JIS characters.
+ * Thus, maximum returned length is:
+ * 2 (switch to JIS) + 2 (JIS characters) + 2 (switch back to ASCII) = 6.
+ *****************************************************************************/
+static JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = {
+/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTHER*/
+/*ASCII*/ { A_ESC, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,ASCII,ASCII},
+/*A_ESC*/ { ASCII, A_ESC_DL,ASCII, ASCII, ASCII, ASCII, ASCII,ASCII,ASCII},
+/*A_ESC_DL*/{ ASCII, ASCII, ASCII, JIS, JIS, ASCII, ASCII,ASCII,ASCII},
+/*JIS*/ { J_ESC, JIS_1, JIS_1, JIS_1, JIS_1, JIS_1, INV, JIS_1,INV },
+/*JIS_1*/ { INV, JIS_2, JIS_2, JIS_2, JIS_2, JIS_2, INV, JIS_2,INV },
+/*JIS_2*/ { J2_ESC,JIS, JIS, JIS, JIS, JIS, INV, JIS, JIS },
+/*J_ESC*/ { INV, INV, J_ESC_BR, INV, INV, INV, INV, INV, INV },
+/*J_ESC_BR*/{ INV, INV, INV, INV, ASCII, ASCII, INV, INV, INV },
+/*J2_ESC*/ { INV, INV, J2_ESC_BR,INV, INV, INV, INV, INV, INV },
+/*J2_ESC_BR*/{INV, INV, INV, INV, ASCII, ASCII, INV, INV, INV },
+};
+
+static JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = {
+/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTHER */
+/*ASCII */ {NOOP, COPYA, COPYA, COPYA, COPYA, COPYA, EMPTY, COPYA, COPYA},
+/*A_ESC */ {COPYA, NOOP, COPYA, COPYA, COPYA, COPYA, COPYA, COPYA, COPYA},
+/*A_ESC_DL */{COPYA, COPYA, COPYA, MAKE_J, MAKE_J, COPYA, COPYA, COPYA, COPYA},
+/*JIS */ {NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR },
+/*JIS_1 */ {ERROR, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR },
+/*JIS_2 */ {NOOP, COPYJ2,COPYJ2,COPYJ2, COPYJ2, COPYJ2,ERROR, COPYJ2,COPYJ2},
+/*J_ESC */ {ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR },
+/*J_ESC_BR */{ERROR, ERROR, ERROR, ERROR, NOOP, NOOP, ERROR, ERROR, ERROR },
+/*J2_ESC */ {ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR },
+/*J2_ESC_BR*/{ERROR, ERROR, ERROR, ERROR, COPYJ, COPYJ, ERROR, ERROR, ERROR },
+};
+
+
+char *literal_codeset = NULL;
+
+int
+local_mbtowc (pwc, s, n)
+ wchar_t *pwc;
+ const char *s;
+ size_t n;
+{
+ static JIS_STATE save_state = ASCII;
+ JIS_STATE curr_state = save_state;
+ unsigned char *t = (unsigned char *)s;
+
+ if (s != NULL && n == 0)
+ return -1;
+
+ if (literal_codeset == NULL || strlen (literal_codeset) <= 1)
+ {
+ /* This must be the "C" locale or unknown locale -- fall thru */
+ }
+ else if (! strcmp (literal_codeset, "C-SJIS"))
+ {
+ int char1;
+ if (s == NULL)
+ return 0; /* not state-dependent */
+ char1 = *t;
+ if (ISSJIS1 (char1))
+ {
+ int char2 = t[1];
+ if (n <= 1)
+ return -1;
+ if (ISSJIS2 (char2))
+ {
+ if (pwc != NULL)
+ *pwc = (((wchar_t)*t) << 8) + (wchar_t)(*(t+1));
+ return 2;
+ }
+ return -1;
+ }
+ if (pwc != NULL)
+ *pwc = (wchar_t)*t;
+ if (*t == '\0')
+ return 0;
+ return 1;
+ }
+ else if (! strcmp (literal_codeset, "C-EUCJP"))
+ {
+ int char1;
+ if (s == NULL)
+ return 0; /* not state-dependent */
+ char1 = *t;
+ if (ISEUCJP (char1))
+ {
+ int char2 = t[1];
+ if (n <= 1)
+ return -1;
+ if (ISEUCJP (char2))
+ {
+ if (pwc != NULL)
+ *pwc = (((wchar_t)*t) << 8) + (wchar_t)(*(t+1));
+ return 2;
+ }
+ return -1;
+ }
+ if (pwc != NULL)
+ *pwc = (wchar_t)*t;
+ if (*t == '\0')
+ return 0;
+ return 1;
+ }
+ else if (! strcmp (literal_codeset, "C-JIS"))
+ {
+ JIS_ACTION action;
+ JIS_CHAR_TYPE ch;
+ unsigned char *ptr;
+ int i, curr_ch;
+
+ if (s == NULL)
+ {
+ save_state = ASCII;
+ return 1; /* state-dependent */
+ }
+
+ ptr = t;
+
+ for (i = 0; i < n; ++i)
+ {
+ curr_ch = t[i];
+ switch (curr_ch)
+ {
+ case JIS_ESC_CHAR:
+ ch = ESCAPE;
+ break;
+ case '$':
+ ch = DOLLAR;
+ break;
+ case '@':
+ ch = AT;
+ break;
+ case '(':
+ ch = BRACKET;
+ break;
+ case 'B':
+ ch = B;
+ break;
+ case 'J':
+ ch = J;
+ break;
+ case '\0':
+ ch = NUL;
+ break;
+ default:
+ if (ISJIS (curr_ch))
+ ch = JIS_CHAR;
+ else
+ ch = OTHER;
+ }
+
+ action = JIS_action_table[curr_state][ch];
+ curr_state = JIS_state_table[curr_state][ch];
+
+ switch (action)
+ {
+ case NOOP:
+ break;
+ case EMPTY:
+ if (pwc != NULL)
+ *pwc = (wchar_t)0;
+ save_state = curr_state;
+ return i;
+ case COPYA:
+ if (pwc != NULL)
+ *pwc = (wchar_t)*ptr;
+ save_state = curr_state;
+ return (i + 1);
+ case COPYJ:
+ if (pwc != NULL)
+ *pwc = (((wchar_t)*ptr) << 8) + (wchar_t)(*(ptr+1));
+ save_state = curr_state;
+ return (i + 1);
+ case COPYJ2:
+ if (pwc != NULL)
+ *pwc = (((wchar_t)*ptr) << 8) + (wchar_t)(*(ptr+1));
+ save_state = curr_state;
+ return (ptr - t) + 2;
+ case MAKE_A:
+ case MAKE_J:
+ ptr = (char *)(t + i + 1);
+ break;
+ case ERROR:
+ default:
+ return -1;
+ }
+ }
+
+ return -1; /* n < bytes needed */
+ }
+
+#ifdef CROSS_COMPILE
+ if (s == NULL)
+ return 0; /* not state-dependent */
+ if (pwc != NULL)
+ *pwc = *s;
+ return 1;
+#else
+ /* This must be the "C" locale or unknown locale. */
+ return mbtowc (pwc, s, n);
+#endif
+}
+
+int
+local_mblen (s, n)
+ const char *s;
+ size_t n;
+{
+ return local_mbtowc (NULL, s, n);
+}
+
+int
+local_mb_cur_max ()
+{
+ if (literal_codeset == NULL || strlen (literal_codeset) <= 1)
+ ;
+ else if (! strcmp (literal_codeset, "C-SJIS"))
+ return 2;
+ else if (! strcmp (literal_codeset, "C-EUCJP"))
+ return 2;
+ else if (! strcmp (literal_codeset, "C-JIS"))
+ return 8; /* 3 + 2 + 3 */
+
+#ifdef CROSS_COMPILE
+ return 1;
+#else
+ if (MB_CUR_MAX > 0)
+ return MB_CUR_MAX;
+
+ return 1; /* default */
+#endif
+}
+#endif /* MULTIBYTE_CHARS */
diff --git a/contrib/gcc/mbchar.h b/contrib/gcc/mbchar.h
new file mode 100644
index 0000000..65f281a
--- /dev/null
+++ b/contrib/gcc/mbchar.h
@@ -0,0 +1,41 @@
+/* mbchar.h - Various declarations for functions found in mbchar.c
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef __GCC_MBCHAR_H__
+#define __GCC_MBCHAR_H__
+
+#ifdef MULTIBYTE_CHARS
+/* escape character used for JIS encoding */
+#define JIS_ESC_CHAR 0x1b
+
+#define ISSJIS1(c) ((c) >= 0x81 && (c) <= 0x9f || (c) >= 0xe0 && (c) <= 0xef)
+#define ISSJIS2(c) ((c) >= 0x40 && (c) <= 0x7e || (c) >= 0x80 && (c) <= 0xfc)
+#define ISEUCJP(c) ((c) >= 0xa1 && (c) <= 0xfe)
+#define ISJIS(c) ((c) >= 0x21 && (c) <= 0x7e)
+
+int local_mbtowc PROTO ((wchar_t *, const char *, size_t));
+int local_mblen PROTO ((const char *, size_t));
+int local_mb_cur_max PROTO ((void));
+
+/* The locale being used for multibyte characters in string/char literals. */
+extern char *literal_codeset;
+#endif /* MULTIBYTE_CHARS */
+
+#endif /* __GCC_MBCHAR_H__ */
diff --git a/contrib/gcc/md.texi b/contrib/gcc/md.texi
index e9d810c..907df37 100644
--- a/contrib/gcc/md.texi
+++ b/contrib/gcc/md.texi
@@ -1377,6 +1377,9 @@ Floating point register
@item y
@samp{CR} register (condition register)
+@item z
+@samp{FPMEM} stack memory for FPR-GPR transfers
+
@item I
Signed 16 bit constant
@@ -1413,10 +1416,7 @@ for @code{asm} statements)
AIX TOC entry
@item S
-Windows NT SYMBOL_REF
-
-@item T
-Windows NT LABEL_REF
+Constant suitable as a 64-bit mask operand
@item U
System V Release 4 small data area reference
@@ -1746,14 +1746,20 @@ pseudo registers that did not get hard registers, while on other
machines explicit memory references will get optional reloads.
If a scratch register is required to move an object to or from memory,
-it can be allocated using @code{gen_reg_rtx} prior to reload. But this
-is impossible during and after reload. If there are cases needing
+it can be allocated using @code{gen_reg_rtx} prior to life analysis.
+
+If there are cases needing
scratch registers after reload, you must define
@code{SECONDARY_INPUT_RELOAD_CLASS} and perhaps also
@code{SECONDARY_OUTPUT_RELOAD_CLASS} to detect them, and provide
patterns @samp{reload_in@var{m}} or @samp{reload_out@var{m}} to handle
them. @xref{Register Classes}.
+@findex no_new_pseudos
+The global variable @code{no_new_pseudos} can be used to determine if it
+is unsafe to create new pseudo registers. If this variable is nonzero, then
+it is unsafe to call @code{gen_reg_rtx} to allocate a new pseudo.
+
The constraints on a @samp{mov@var{m}} must permit moving any hard
register to any other hard register provided that
@code{HARD_REGNO_MODE_OK} permits mode @var{m} in both registers and
@@ -2531,6 +2537,61 @@ This pattern, if defined, performs the entire action of the longjmp.
You will not normally need to define this pattern unless you also define
@code{builtin_setjmp_setup}. The single argument is a pointer to the
@code{jmp_buf}.
+
+@cindex @code{eh_epilogue} instruction pattern
+@item @samp{eh_epilogue}
+This pattern, if defined, affects the way @code{__builtin_eh_return},
+and thence @code{__throw} are built. It is intended to allow communication
+between the exception handling machinery and the normal epilogue code
+for the target.
+
+The pattern takes three arguments. The first is the exception context
+pointer. This will have already been copied to the function return
+register appropriate for a pointer; normally this can be ignored. The
+second argument is an offset to be added to the stack pointer. It will
+have been copied to some arbitrary call-clobbered hard reg so that it
+will survive until after reload to when the normal epilogue is generated.
+The final argument is the address of the exception handler to which
+the function should return. This will normally need to copied by the
+pattern to some special register.
+
+This pattern must be defined if @code{RETURN_ADDR_RTX} does not yield
+something that can be reliably and permanently modified, i.e. a fixed
+hard register or a stack memory reference.
+
+@cindex @code{prologue} instruction pattern
+@item @samp{prologue}
+This pattern, if defined, emits RTL for entry to a function. The function
+entry is resposible for setting up the stack frame, initializing the frame
+pointer register, saving callee saved registers, etc.
+
+Using a prologue pattern is generally preferred over defining
+@code{FUNCTION_PROLOGUE} to emit assembly code for the prologue.
+
+The @code{prologue} pattern is particularly useful for targets which perform
+instruction scheduling.
+
+@cindex @code{epilogue} instruction pattern
+@item @samp{epilogue}
+This pattern, if defined, emits RTL for exit from a function. The function
+exit is resposible for deallocating the stack frame, restoring callee saved
+registers and emitting the return instruction.
+
+Using an epilogue pattern is generally preferred over defining
+@code{FUNCTION_EPILOGUE} to emit assembly code for the prologue.
+
+The @code{epilogue} pattern is particularly useful for targets which perform
+instruction scheduling or which have delay slots for their return instruction.
+
+@cindex @code{sibcall_epilogue} instruction pattern
+@item @samp{sibcall_epilogue}
+This pattern, if defined, emits RTL for exit from a function without the final
+branch back to the calling function. This pattern will be emitted before any
+sibling call (aka tail call) sites.
+
+The @code{sibcall_epilogue} pattern must not clobber any arguments used for
+parameter passing or any stack slots for arguments passed to the current
+function.
@end table
@node Pattern Ordering
@@ -3528,9 +3589,10 @@ The integer @var{i} specifies the value of a numeric attribute. @var{i}
must be non-negative.
The value of a numeric attribute can be specified either with a
-@code{const_int} or as an integer represented as a string in
-@code{const_string}, @code{eq_attr} (see below), and @code{set_attr}
-(@pxref{Tagging Insns}) expressions.
+@code{const_int}, or as an integer represented as a string in
+@code{const_string}, @code{eq_attr} (see below), @code{attr},
+@code{symbol_ref}, simple arithmetic expressions, and @code{set_attr}
+overrides on specific instructions (@pxref{Tagging Insns}).
@cindex @code{const_string} and attributes
@item (const_string @var{value})
@@ -3713,6 +3775,12 @@ The @code{very_unlikely} and @code{unlikely} flags are false if the
@code{attr_flag} is only used during delay slot scheduling and has no
meaning to other passes of the compiler.
+
+@findex attr
+@item (attr @var{name})
+The value of another attribute is returned. This is most useful
+for numeric attributes, as @code{eq_attr} and @code{attr_flag}
+produce more efficient code for non-numeric attributes.
@end table
@node Tagging Insns
diff --git a/contrib/gcc/mips-tdump.c b/contrib/gcc/mips-tdump.c
index 558e090..9d3143d 100644
--- a/contrib/gcc/mips-tdump.c
+++ b/contrib/gcc/mips-tdump.c
@@ -1,5 +1,5 @@
/* Read and manage MIPS symbol tables from object modules.
- Copyright (C) 1991, 1994, 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1994, 1995, 1997, 1998, 1999 Free Software Foundation, Inc.
Contributed by hartzell@boulder.colorado.edu,
Rewritten by meissner@osf.org.
@@ -47,24 +47,9 @@ Boston, MA 02111-1307, USA. */
#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK)
#endif
-#ifdef __STDC__
-typedef void *PTR_T;
-typedef const void *CPTR_T;
-#define __proto(x) x
-#else
-
-#if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
-typedef void *PTR_T;
-typedef void *CPTR_T;
-
-#else
-typedef char *PTR_T; /* Ultrix 3.1 */
-typedef char *CPTR_T;
-#endif
-
-#define __proto(x) ()
-#define const
-#endif
+#define __proto(x) PARAMS(x)
+typedef PTR PTR_T;
+typedef const PTR_T CPTR_T;
#define uchar unsigned char
#define ushort unsigned short
@@ -72,7 +57,28 @@ typedef char *CPTR_T;
#define ulong unsigned long
-/* Do to size_t being defined in sys/types.h and different
+static void
+fatal(s)
+ const char *s;
+{
+ fprintf(stderr, "%s\n", s);
+ exit(FATAL_EXIT_CODE);
+}
+
+/* Same as `malloc' but report error if no memory available. */
+/* Do this before size_t is fiddled with so it matches the prototype
+ in libiberty.h . */
+PTR
+xmalloc (size)
+ size_t size;
+{
+ register PTR value = (PTR) malloc (size);
+ if (value == 0)
+ fatal ("Virtual memory exhausted.");
+ return value;
+}
+
+/* Due to size_t being defined in sys/types.h and different
in stddef.h, we have to do this by hand..... Note, these
types are correct for MIPS based systems, and may not be
correct for other systems. */
@@ -263,17 +269,22 @@ void print_file_desc __proto((FDR *, int));
void print_symbol __proto((SYMR *, int, char *, AUXU *, int, FDR *));
void print_aux __proto((AUXU, int, int));
void emit_aggregate __proto((char *, AUXU, AUXU, const char *, FDR *));
-char *st_to_string __proto((st_t));
-char *sc_to_string __proto((sc_t));
-char *glevel_to_string __proto((glevel_t));
-char *lang_to_string __proto((lang_t));
-char *type_to_string __proto((AUXU *, int, FDR *));
+const char *st_to_string __proto((st_t));
+const char *sc_to_string __proto((sc_t));
+const char *glevel_to_string __proto((glevel_t));
+const char *lang_to_string __proto((lang_t));
+const char *type_to_string __proto((AUXU *, int, FDR *));
#ifndef __alpha
+# ifdef NEED_DECLARATION_MALLOC
extern PTR_T malloc __proto((size_t));
+# endif
+# ifdef NEED_DECLARATION_CALLOC
extern PTR_T calloc __proto((size_t, size_t));
+# endif
+# ifdef NEED_DECLARATION_REALLOC
extern PTR_T realloc __proto((PTR_T, size_t));
-extern void free __proto((PTR_T));
+# endif
#endif
extern char *optarg;
@@ -325,7 +336,7 @@ read_seek (ptr, size, offset, context)
/* Convert language code to string format. */
-char *
+const char *
lang_to_string (lang)
lang_t lang;
{
@@ -348,7 +359,7 @@ lang_to_string (lang)
/* Convert storage class to string. */
-char *
+const char *
sc_to_string(storage_class)
sc_t storage_class;
{
@@ -386,7 +397,7 @@ sc_to_string(storage_class)
/* Convert symbol type to string. */
-char *
+const char *
st_to_string(symbol_type)
st_t symbol_type;
{
@@ -427,7 +438,7 @@ st_to_string(symbol_type)
/* Convert debug level to string. */
-char *
+const char *
glevel_to_string (g_level)
glevel_t g_level;
{
@@ -445,7 +456,7 @@ glevel_to_string (g_level)
/* Convert the type information to string format. */
-char *
+const char *
type_to_string (aux_ptr, index, fdp)
AUXU *aux_ptr;
int index;
@@ -1014,7 +1025,7 @@ print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
scope_ptr != (scope_t *) 0;
scope_ptr = scope_ptr->prev)
{
- char *class;
+ const char *class;
if (scope_ptr->st == st_Proc || scope_ptr->st == st_StaticProc)
class = "func.";
else if (scope_ptr->st == st_File)
@@ -1046,7 +1057,7 @@ print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
if (MIPS_IS_STAB(sym_ptr))
{
register int i = sizeof(stab_names) / sizeof(stab_names[0]);
- char *stab_name = "stab";
+ const char *stab_name = "stab";
short code = MIPS_UNMARK_STAB(sym_ptr->index);
while (--i >= 0)
if (stab_names[i].code == code)
@@ -1147,8 +1158,10 @@ print_file_desc (fdp, number)
aux_base = aux_symbols + fdp->iauxBase;
used_base = aux_used + (aux_base - aux_symbols);
- printf ("\nFile #%d, \"%s\"\n\n", number, str_base + fdp->rss);
-
+ printf ("\nFile #%d, \"%s\"\n\n",
+ number,
+ fdp->rss != issNil ? str_base + fdp->rss : "<unknown>");
+
printf (" Name index = %-10ld Readin = %s\n",
(long) fdp->rss, (fdp->fReadin) ? "Yes" : "No");
@@ -1264,7 +1277,7 @@ print_file_desc (fdp, number)
(ulong) fdp->rfdBase);
rfd_ptr = rfile_desc + fdp->rfdBase;
- for (i = 0; i < fdp->crfd; i++)
+ for (i = 0; i < (ulong) fdp->crfd; i++)
{
printf ("\t#%-5ld %11ld, 0x%08lx\n", i, *rfd_ptr, *rfd_ptr);
rfd_ptr++;
@@ -1282,9 +1295,10 @@ print_file_desc (fdp, number)
PDR *proc_ptr = &proc_desc[pdi];
printf ("\n\tProcedure descriptor %d:\n", (pdi - fdp->ipdFirst));
- printf ("\t Name index = %-11ld Name = \"%s\"\n",
- (long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
- l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
+ if (l_symbols != 0)
+ printf ("\t Name index = %-11ld Name = \"%s\"\n",
+ (long) l_symbols[proc_ptr->isym + fdp->isymBase].iss,
+ l_symbols[proc_ptr->isym + fdp->isymBase].iss + str_base);
printf ("\t .mask 0x%08lx,%-9ld .fmask 0x%08lx,%ld\n",
(long) proc_ptr->regmask,
@@ -1590,23 +1604,3 @@ fancy_abort ()
fprintf (stderr, "mips-tdump internal error");
exit (1);
}
-
-void
-fatal(s)
-char *s;
-{
- fprintf(stderr, "%s\n", s);
- exit(1);
-}
-
-/* Same as `malloc' but report error if no memory available. */
-
-PTR_T
-xmalloc (size)
- unsigned size;
-{
- register PTR_T value = malloc (size);
- if (value == 0)
- fatal ("Virtual memory exhausted.");
- return value;
-}
diff --git a/contrib/gcc/mips-tfile.c b/contrib/gcc/mips-tfile.c
index 9918397..588f4ef 100644
--- a/contrib/gcc/mips-tfile.c
+++ b/contrib/gcc/mips-tfile.c
@@ -2,7 +2,7 @@
contain debugging information specified by the GNU compiler
in the form of comments (the mips assembler does not support
assembly access to debug information).
- Copyright (C) 1991, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93-95, 97, 98, 1999 Free Software Foundation, Inc.
Contributed by Michael Meissner (meissner@cygnus.com).
This file is part of GNU CC.
@@ -600,11 +600,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#ifndef __SABER__
@@ -615,36 +610,11 @@ Boston, MA 02111-1307, USA. */
#define __LINE__ 0
#endif
-#ifdef __STDC__
-typedef void *PTR_T;
-typedef const void *CPTR_T;
-#define __proto(x) x
-#ifndef VPROTO
-#define PVPROTO(ARGS) ARGS
-#define VPROTO(ARGS) ARGS
-#define VA_START(va_list,var) va_start(va_list,var)
-#endif
-#else
-
-#if defined(_STDIO_H_) || defined(__STDIO_H__) /* Ultrix 4.0, SGI */
-typedef void *PTR_T;
-typedef void *CPTR_T;
-
-#else
-typedef char *PTR_T; /* Ultrix 3.1 */
-typedef char *CPTR_T;
-#endif
-
-#define __proto(x) ()
-#define const
-#ifndef VPROTO
-#define PVPROTO(ARGS) ()
-#define VPROTO(ARGS) (va_alist) va_dcl
-#define VA_START(va_list,var) va_start(va_list)
-#endif
-#endif
+#define __proto(x) PARAMS(x)
+typedef PTR PTR_T;
+typedef const PTR_T CPTR_T;
-/* Do to size_t being defined in sys/types.h and different
+/* Due to size_t being defined in sys/types.h and different
in stddef.h, we have to do this by hand..... Note, these
types are correct for MIPS based systems, and may not be
correct for other systems. Ultrix 4.0 and Silicon Graphics
@@ -663,16 +633,13 @@ typedef char *CPTR_T;
so they can't be static. */
extern void pfatal_with_name
- __proto((char *));
+ __proto((const char *));
extern void fancy_abort __proto((void));
void botch __proto((const char *));
-extern PTR_T xmalloc __proto((Size_t));
-extern PTR_T xcalloc __proto((Size_t, Size_t));
-extern PTR_T xrealloc __proto((PTR_T, Size_t));
-extern void xfree __proto((PTR_T));
+extern void xfree __proto((PTR));
-extern void fatal PVPROTO((const char *format, ...));
-extern void error PVPROTO((const char *format, ...));
+extern void fatal PVPROTO((const char *format, ...)) ATTRIBUTE_PRINTF_1;
+extern void error PVPROTO((const char *format, ...)) ATTRIBUTE_PRINTF_1;
#ifndef MIPS_DEBUGGING_INFO
@@ -680,8 +647,8 @@ static int line_number;
static int cur_line_start;
static int debug;
static int had_errors;
-static char *progname;
-static char *input_name;
+static const char *progname;
+static const char *input_name;
int
main ()
@@ -699,7 +666,6 @@ main ()
#undef index
#include <signal.h>
-#include <sys/stat.h>
#ifndef CROSS_COMPILE
#include <a.out.h>
@@ -1191,7 +1157,7 @@ typedef union page {
/* Structure holding allocation information for small sized structures. */
typedef struct alloc_info {
- char *alloc_name; /* name of this allocation type (must be first) */
+ const char *alloc_name; /* name of this allocation type (must be first) */
page_t *cur_page; /* current page being allocated from */
small_free_t free_list; /* current free list if any */
int unallocated; /* number of elements unallocated on page */
@@ -1588,7 +1554,7 @@ static long max_file_offset = 0; /* maximum file offset */
static FILE *object_stream = (FILE *) 0; /* file desc. to output .o */
static FILE *obj_in_stream = (FILE *) 0; /* file desc. to input .o */
static char *progname = (char *) 0; /* program name for errors */
-static char *input_name = "stdin"; /* name of input file */
+static const char *input_name = "stdin"; /* name of input file */
static char *object_name = (char *) 0; /* tmp. name of object file */
static char *obj_in_name = (char *) 0; /* name of input object file */
static char *cur_line_start = (char *) 0; /* current line read in */
@@ -1680,8 +1646,8 @@ STATIC void update_headers __proto((void));
STATIC void write_varray __proto((varray_t *, off_t, const char *));
STATIC void write_object __proto((void));
-STATIC char *st_to_string __proto((st_t));
-STATIC char *sc_to_string __proto((sc_t));
+STATIC const char *st_to_string __proto((st_t));
+STATIC const char *sc_to_string __proto((sc_t));
STATIC char *read_line __proto((void));
STATIC void parse_input __proto((void));
STATIC void mark_stabs __proto((const char *));
@@ -1727,6 +1693,7 @@ STATIC void free_thead __proto((thead_t *));
STATIC char *local_index __proto((const char *, int));
STATIC char *local_rindex __proto((const char *, int));
+STATIC const char *my_strsignal __proto((int));
extern char *mktemp __proto((char *));
extern long strtol __proto((const char *, char **, int));
@@ -1735,12 +1702,6 @@ extern char *optarg;
extern int optind;
extern int opterr;
extern char *version_string;
-#ifndef NO_SYS_SIGLIST
-#ifndef SYS_SIGLIST_DECLARED
-extern char *sys_siglist[NSIG + 1];
-#endif
-#endif
-
/* List of assembler pseudo ops and beginning sequences that need
special actions. Someday, this should be a hash table, and such,
@@ -1827,7 +1788,7 @@ hash_string (text, hash_len, hash_tbl, ret_hash_index)
*ret_hash_index = hi;
for (ptr = hash_tbl[hi]; ptr != (shash_t *) 0; ptr = ptr->next)
- if (hash_len == ptr->len
+ if ((symint_t) hash_len == ptr->len
&& first_ch == ptr->string[0]
&& memcmp ((CPTR_T) text, (CPTR_T) ptr->string, hash_len) == 0)
break;
@@ -1852,7 +1813,7 @@ add_string (vp, hash_tbl, start, end_p1, ret_hash)
register shash_t *hash_ptr;
symint_t hi;
- if (len >= PAGE_USIZE)
+ if (len >= (Ptrdiff_t) PAGE_USIZE)
fatal ("String too big (%ld bytes)", (long) len);
hash_ptr = hash_string (start, len, hash_tbl, &hi);
@@ -1860,7 +1821,7 @@ add_string (vp, hash_tbl, start, end_p1, ret_hash)
{
register char *p;
- if (vp->objects_last_page + len >= PAGE_USIZE)
+ if (vp->objects_last_page + len >= (long) PAGE_USIZE)
{
vp->num_allocated
= ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
@@ -2047,8 +2008,8 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
&& (debug > 2 || type == st_Block || type == st_End
|| type == st_Proc || type == st_StaticProc))
{
- char *sc_str = sc_to_string (storage);
- char *st_str = st_to_string (type);
+ const char *sc_str = sc_to_string (storage);
+ const char *st_str = st_to_string (type);
int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
fprintf (stderr,
@@ -2087,8 +2048,8 @@ add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
if (debug > 1)
{
- char *sc_str = sc_to_string (storage);
- char *st_str = st_to_string (type);
+ const char *sc_str = sc_to_string (storage);
+ const char *st_str = st_to_string (type);
fprintf (stderr,
"\tesym\tv= %10ld, ifd= %2d, sc= %-12s",
@@ -2396,7 +2357,7 @@ add_unknown_tag (ptag)
if (debug > 1)
{
- char *agg_type = "{unknown aggregate type}";
+ const char *agg_type = "{unknown aggregate type}";
switch (ptag->basic_type)
{
case bt_Struct: agg_type = "struct"; break;
@@ -2490,7 +2451,8 @@ add_procedure (func_start, func_end_p1)
}
if (cur_oproc_ptr == (PDR *) 0)
- error ("Did not find a PDR block for %.*s", func_end_p1 - func_start, func_start);
+ error ("Did not find a PDR block for %.*s",
+ (int) (func_end_p1 - func_start), func_start);
/* Determine the start of symbols. */
new_proc_ptr->isym = file_ptr->symbols.num_allocated;
@@ -2557,7 +2519,7 @@ add_file (file_start, file_end_p1)
&zero_bytes[0],
(shash_t **) 0);
- if (file_end_p1 - file_start > PAGE_USIZE-2)
+ if (file_end_p1 - file_start > (long) PAGE_USIZE-2)
fatal ("Filename goes over one page boundary.");
/* Push the start of the filename. We assume that the filename
@@ -2626,7 +2588,7 @@ add_bytes (vp, input_ptr, nitems)
/* Convert storage class to string. */
-STATIC char *
+STATIC const char *
sc_to_string(storage_class)
sc_t storage_class;
{
@@ -2664,7 +2626,7 @@ sc_to_string(storage_class)
/* Convert symbol type to string. */
-STATIC char *
+STATIC const char *
st_to_string(symbol_type)
st_t symbol_type;
{
@@ -2807,13 +2769,15 @@ parse_begin (start)
if (hash_ptr == (shash_t *) 0)
{
- error ("Label %.*s not found for #.begin", end_p1 - start, start);
+ error ("Label %.*s not found for #.begin",
+ (int) (end_p1 - start), start);
return;
}
if (cur_oproc_begin == (SYMR *) 0)
{
- error ("Procedure table %.*s not found for #.begin", end_p1 - start, start);
+ error ("Procedure table %.*s not found for #.begin",
+ (int) (end_p1 - start), start);
return;
}
@@ -2857,13 +2821,14 @@ parse_bend (start)
if (hash_ptr == (shash_t *) 0)
{
- error ("Label %.*s not found for #.bend", end_p1 - start, start);
+ error ("Label %.*s not found for #.bend", (int) (end_p1 - start), start);
return;
}
if (cur_oproc_begin == (SYMR *) 0)
{
- error ("Procedure table %.*s not found for #.bend", end_p1 - start, start);
+ error ("Procedure table %.*s not found for #.bend",
+ (int) (end_p1 - start), start);
return;
}
@@ -3319,7 +3284,7 @@ parse_def (name_start)
if (tag_start == (char *) 0)
{
error ("No tag specified for %.*s",
- name_end_p1 - name_start,
+ (int) (name_end_p1 - name_start),
name_start);
return;
}
@@ -3482,7 +3447,7 @@ parse_end (start)
}
/* Get the function name, skipping whitespace. */
- for (start_func = start; ISSPACE (*start_func); start_func++)
+ for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
;
ch = *start_func;
@@ -3509,7 +3474,8 @@ parse_end (start)
value = cur_oproc_end->value;
else
- error ("Cannot find .end block for %.*s", end_func_p1 - start_func, start_func);
+ error ("Cannot find .end block for %.*s",
+ (int) (end_func_p1 - start_func), start_func);
(void) add_local_symbol (start_func, end_func_p1,
st_End, sc_Text,
@@ -3541,7 +3507,7 @@ parse_ent (start)
return;
}
- for (start_func = start; ISSPACE (*start_func); start_func++)
+ for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
;
ch = *start_func;
@@ -3590,7 +3556,7 @@ parse_file (start)
static void
mark_stabs (start)
- const char *start; /* Start of directive (ignored) */
+ const char *start ATTRIBUTE_UNUSED; /* Start of directive (ignored) */
{
if (!stabs_seen)
{
@@ -3688,7 +3654,7 @@ parse_stabs_common (string_start, string_end, rest)
dummy_symr.index = code;
if (dummy_symr.index != code)
{
- error ("Line number (%d) for .stabs/.stabn directive cannot fit in index field (20 bits)",
+ error ("Line number (%lu) for .stabs/.stabn directive cannot fit in index field (20 bits)",
code);
return;
@@ -3863,7 +3829,7 @@ STATIC void
parse_input __proto((void))
{
register char *p;
- register int i;
+ register Size_t i;
register thead_t *ptag_head;
register tag_t *ptag;
register tag_t *ptag_next;
@@ -3881,16 +3847,16 @@ parse_input __proto((void))
while ((p = read_line ()) != (char *) 0)
{
/* Skip leading blanks */
- while (ISSPACE (*p))
+ while (ISSPACE ((unsigned char)*p))
p++;
/* See if it's a directive we handle. If so, dispatch handler. */
for (i = 0; i < sizeof (pseudo_ops) / sizeof (pseudo_ops[0]); i++)
if (memcmp (p, pseudo_ops[i].name, pseudo_ops[i].len) == 0
- && ISSPACE (p[pseudo_ops[i].len]))
+ && ISSPACE ((unsigned char)(p[pseudo_ops[i].len])))
{
p += pseudo_ops[i].len; /* skip to first argument */
- while (ISSPACE (*p))
+ while (ISSPACE ((unsigned char)*p))
p++;
(*pseudo_ops[i].func)( p );
@@ -4180,7 +4146,7 @@ write_object __proto((void))
else if (sys_write != sizeof (symbolic_header))
fatal ("Wrote %d bytes to %s, system returned %d",
- sizeof (symbolic_header),
+ (int) sizeof (symbolic_header),
object_name,
sys_write);
@@ -4213,8 +4179,8 @@ write_object __proto((void))
pfatal_with_name (object_name);
else if (sys_write != symbolic_header.cbLine)
- fatal ("Wrote %d bytes to %s, system returned %d",
- symbolic_header.cbLine,
+ fatal ("Wrote %ld bytes to %s, system returned %ld",
+ (long) symbolic_header.cbLine,
object_name,
sys_write);
@@ -4248,7 +4214,7 @@ write_object __proto((void))
pfatal_with_name (object_name);
else if (sys_write != num_write)
- fatal ("Wrote %d bytes to %s, system returned %d",
+ fatal ("Wrote %ld bytes to %s, system returned %ld",
num_write,
object_name,
sys_write);
@@ -4341,7 +4307,7 @@ write_object __proto((void))
else if (sys_write != sizeof (FDR))
fatal ("Wrote %d bytes to %s, system returned %d",
- sizeof (FDR),
+ (int) sizeof (FDR),
object_name,
sys_write);
@@ -4375,8 +4341,8 @@ write_object __proto((void))
if (sys_write <= 0)
pfatal_with_name (object_name);
- else if (sys_write != num_write)
- fatal ("Wrote %d bytes to %s, system returned %d",
+ else if (sys_write != (long)num_write)
+ fatal ("Wrote %lu bytes to %s, system returned %ld",
num_write,
object_name,
sys_write);
@@ -4431,9 +4397,9 @@ read_seek (size, offset, str)
if (sys_read <= 0)
pfatal_with_name (obj_in_name);
- if (sys_read != difference)
- fatal ("Wanted to read %d bytes from %s, system returned %d",
- size,
+ if ((symint_t)sys_read != difference)
+ fatal ("Wanted to read %lu bytes from %s, system returned %ld",
+ (unsigned long) size,
obj_in_name,
sys_read);
}
@@ -4445,9 +4411,9 @@ read_seek (size, offset, str)
if (sys_read <= 0)
pfatal_with_name (obj_in_name);
- if (sys_read != size)
- fatal ("Wanted to read %d bytes from %s, system returned %d",
- size,
+ if (sys_read != (long) size)
+ fatal ("Wanted to read %lu bytes from %s, system returned %ld",
+ (unsigned long) size,
obj_in_name,
sys_read);
@@ -4495,16 +4461,16 @@ copy_object __proto((void))
else if (sys_read == 0 && feof (obj_in_stream))
return; /* create a .T file sans file header */
- else if (sys_read < sizeof (struct filehdr))
+ else if (sys_read < (int) sizeof (struct filehdr))
fatal ("Wanted to read %d bytes from %s, system returned %d",
- sizeof (struct filehdr),
+ (int) sizeof (struct filehdr),
obj_in_name,
sys_read);
if (orig_file_header.f_nsyms != sizeof (HDRR))
fatal ("%s symbolic header wrong size (%d bytes, should be %d)",
- input_name, orig_file_header.f_nsyms, sizeof (HDRR));
+ input_name, orig_file_header.f_nsyms, (int) sizeof (HDRR));
/* Read in the current symbolic header. */
@@ -4519,9 +4485,9 @@ copy_object __proto((void))
if (sys_read < 0)
pfatal_with_name (object_name);
- else if (sys_read < sizeof (struct filehdr))
+ else if (sys_read < (int) sizeof (struct filehdr))
fatal ("Wanted to read %d bytes from %s, system returned %d",
- sizeof (struct filehdr),
+ (int) sizeof (struct filehdr),
obj_in_name,
sys_read);
@@ -4660,7 +4626,7 @@ copy_object __proto((void))
(sc_t) eptr->asym.sc,
eptr->asym.value,
(symint_t) ((eptr->asym.index == indexNil) ? indexNil : 0),
- (ifd < orig_sym_hdr.ifdMax) ? remap_file_number[ ifd ] : ifd);
+ ((long) ifd < orig_sym_hdr.ifdMax) ? remap_file_number[ ifd ] : ifd);
}
@@ -4812,7 +4778,8 @@ copy_object __proto((void))
remaining > 0;
remaining -= num_write)
{
- num_write = (remaining <= sizeof (buffer)) ? remaining : sizeof (buffer);
+ num_write =
+ (remaining <= (int) sizeof (buffer)) ? remaining : sizeof (buffer);
sys_read = fread ((PTR_T) buffer, 1, num_write, obj_in_stream);
if (sys_read <= 0)
pfatal_with_name (obj_in_name);
@@ -4858,13 +4825,13 @@ main (argc, argv)
#if !defined(__SABER__) && !defined(lint)
if (sizeof (efdr_t) > PAGE_USIZE)
fatal ("Efdr_t has a sizeof %d bytes, when it should be less than %d",
- sizeof (efdr_t),
- PAGE_USIZE);
+ (int) sizeof (efdr_t),
+ (int) PAGE_USIZE);
if (sizeof (page_t) != PAGE_USIZE)
fatal ("Page_t has a sizeof %d bytes, when it should be %d",
- sizeof (page_t),
- PAGE_USIZE);
+ (int) sizeof (page_t),
+ (int) PAGE_USIZE);
#endif
@@ -5055,6 +5022,29 @@ main (argc, argv)
}
+STATIC const char *
+my_strsignal (s)
+ int s;
+{
+#ifdef HAVE_STRSIGNAL
+ return strsignal (s);
+#else
+ if (s >= 0 && s < NSIG)
+ {
+# ifdef NO_SYS_SIGLIST
+ static char buffer[30];
+
+ sprintf (buffer, "Unknown signal %d", s);
+ return buffer;
+# else
+ return sys_siglist[s];
+# endif
+ }
+ else
+ return NULL;
+#endif /* HAVE_STRSIGNAL */
+}
+
/* Catch a signal and exit without dumping core. */
STATIC void
@@ -5062,11 +5052,7 @@ catch_signal (signum)
int signum;
{
(void) signal (signum, SIG_DFL); /* just in case... */
-#ifdef NO_SYS_SIGLIST
- fatal ("caught signal");
-#else
- fatal (sys_siglist[signum]);
-#endif
+ fatal (my_strsignal(signum));
}
/* Print a fatal error message. NAME is the text.
@@ -5074,7 +5060,7 @@ catch_signal (signum)
void
pfatal_with_name (msg)
- char *msg;
+ const char *msg;
{
int save_errno = errno; /* just in case.... */
if (line_number > 0)
@@ -5598,15 +5584,15 @@ free_thead (ptr)
void
fatal VPROTO((const char *format, ...))
{
-#ifndef __STDC__
- char *format;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
- format = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (ap, const char *);
#endif
if (line_number > 0)
@@ -5628,14 +5614,14 @@ fatal VPROTO((const char *format, ...))
void
error VPROTO((const char *format, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
char *format;
#endif
va_list ap;
VA_START (ap, format);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
format = va_arg (ap, char *);
#endif
@@ -5677,11 +5663,11 @@ botch (s)
/* Same as `malloc' but report error if no memory available. */
-PTR_T
+PTR
xmalloc (size)
- Size_t size;
+ size_t size;
{
- register PTR_T value = malloc (size);
+ register PTR value = (PTR) malloc (size);
if (value == 0)
fatal ("Virtual memory exhausted.");
@@ -5697,11 +5683,11 @@ xmalloc (size)
/* Same as `calloc' but report error if no memory available. */
-PTR_T
+PTR
xcalloc (size1, size2)
- Size_t size1, size2;
+ size_t size1, size2;
{
- register PTR_T value = calloc (size1, size2);
+ register PTR value = (PTR) calloc (size1, size2);
if (value == 0)
fatal ("Virtual memory exhausted.");
@@ -5719,12 +5705,16 @@ xcalloc (size1, size2)
/* Same as `realloc' but report error if no memory available. */
-PTR_T
+PTR
xrealloc (ptr, size)
- PTR_T ptr;
- Size_t size;
+ PTR ptr;
+ size_t size;
{
- register PTR_T result = realloc (ptr, size);
+ register PTR result;
+ if (ptr)
+ result = (PTR) realloc (ptr, size);
+ else
+ result = (PTR) malloc (size);
if (!result)
fatal ("Virtual memory exhausted.");
@@ -5742,7 +5732,7 @@ xrealloc (ptr, size)
void
xfree (ptr)
- PTR_T ptr;
+ PTR ptr;
{
if (debug > 3)
{
diff --git a/contrib/gcc/objc/Make-lang.in b/contrib/gcc/objc/Make-lang.in
index 3774e22..9a84f0f 100644
--- a/contrib/gcc/objc/Make-lang.in
+++ b/contrib/gcc/objc/Make-lang.in
@@ -50,21 +50,17 @@ OBJC_FLAGS_TO_PASS = \
#
# Define the names for selecting Objective-C in LANGUAGES.
-OBJC objc: cc1obj$(exeext) objc-runtime
-OBJECTIVE-C objective-c: cc1obj$(exeext) objc-runtime
+OBJC objc: cc1obj$(exeext)
+OBJECTIVE-C objective-c: cc1obj$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: objective-c objc ObjC
-# The Objective C thread file
-OBJC_THREAD_FILE=thr-$(GCC_THREAD_FILE)
-
# Language-specific object files for Objective C.
OBJC_OBJS = objc-parse.o objc-act.o $(C_AND_OBJC_OBJS)
-cc1obj$(exeext): $(P) $(OBJC_OBJS) $(OBJS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(OBJC_OBJS) $(OBJS) \
- $(LIBS)
+cc1obj$(exeext): $(P) $(OBJS) $(OBJC_OBJS) $(LIBDEPS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(OBJC_OBJS) $(LIBS)
# Objective C language specific files.
@@ -75,9 +71,10 @@ objc-parse.o : $(srcdir)/objc/objc-parse.c \
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -I$(srcdir)/objc \
-c $(srcdir)/objc/objc-parse.c
+$(INTL_TARGETS): $(srcdir)/objc/objc-parse.c
$(srcdir)/objc/objc-parse.c : $(srcdir)/objc/objc-parse.y
cd $(srcdir)/objc; \
- $(BISON) $(BISONFLAGS) objc-parse.y -o objc-parse.c
+ $(BISON) $(BISONFLAGS) -o objc-parse.c objc-parse.y
$(srcdir)/objc/objc-parse.y: $(srcdir)/c-parse.in
echo '/*WARNING: This file is automatically generated!*/' >tmp-objc-prs.y
@@ -94,125 +91,6 @@ objc-act.o : $(srcdir)/objc/objc-act.c \
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -I$(srcdir)/objc \
-c $(srcdir)/objc/objc-act.c
-objc-runtime: objc-headers libobjc.a
-
-# copy objc header files into build directory
-objc-headers: stmp-fixinc
- if [ -d include ]; then true; else mkdir include; fi
- cd objc; \
- if [ -f Makefile ]; then \
- $(MAKE) copy-headers \
- tooldir=$(tooldir) \
- AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" \
- GCC_FOR_TARGET="../xgcc -B../" \
- GCC_CFLAGS="$(GCC_CFLAGS)" incinstalldir=../include; \
- fi
- touch objc-headers
-
-# Objective C runtime library specific files.
-
-OBJC_O = objc/hash.o objc/sarray.o \
- objc/class.o objc/sendmsg.o \
- objc/init.o objc/archive.o \
- objc/encoding.o objc/selector.o \
- objc/objects.o objc/misc.o \
- objc/NXConstStr.o objc/Object.o \
- objc/Protocol.o objc/nil_method.o \
- objc/thr.o objc/linking.o \
- objc/$(OBJC_THREAD_FILE).o
-
-objc/hash.o: $(srcdir)/objc/hash.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/hash.c -o $@
-objc/sarray.o: $(srcdir)/objc/sarray.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/sarray.c -o $@
-objc/class.o: $(srcdir)/objc/class.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/class.c -o $@
-objc/sendmsg.o: $(srcdir)/objc/sendmsg.c $(GCC_PASSES) objc/runtime-info.h
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -Iobjc \
- -c $(srcdir)/objc/sendmsg.c -o $@
-objc/init.o: $(srcdir)/objc/init.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/init.c -o $@
-objc/archive.o: $(srcdir)/objc/archive.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/archive.c -o $@
-objc/encoding.o: $(srcdir)/objc/encoding.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/encoding.c -o $@
-objc/selector.o: $(srcdir)/objc/selector.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/selector.c -o $@
-objc/objects.o: $(srcdir)/objc/objects.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/objects.c -o $@
-objc/misc.o: $(srcdir)/objc/misc.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/misc.c -o $@
-objc/NXConstStr.o: $(srcdir)/objc/NXConstStr.m $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -fgnu-runtime -c $(srcdir)/objc/NXConstStr.m -o $@
-objc/Object.o: $(srcdir)/objc/Object.m $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -fgnu-runtime -c $(srcdir)/objc/Object.m -o $@
-objc/Protocol.o: $(srcdir)/objc/Protocol.m $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -fgnu-runtime -c $(srcdir)/objc/Protocol.m -o $@
-objc/thr.o: $(srcdir)/objc/thr.h $(srcdir)/objc/thr.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/thr.c -o $@
-objc/$(OBJC_THREAD_FILE).o: $(srcdir)/objc/$(OBJC_THREAD_FILE).c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/$(OBJC_THREAD_FILE).c -o $@
-objc/nil_method.o: $(srcdir)/objc/nil_method.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/nil_method.c -o $@
-objc/linking.o: $(srcdir)/objc/linking.m $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -fgnu-runtime -c $(srcdir)/objc/linking.m -o $@
-
-objc/libobjc_entry.o: $(srcdir)/objc/libobjc_entry.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/objc/libobjc_entry.c -o $@
-
-$(OBJC_O): $(GCC_PASSES) cc1obj$(exeext)
-
-# Build the Objective C runtime library.
-libobjc.a: cc1obj$(exeext) specs stmp-int-hdrs libgcc2.ready \
- $(USE_COLLECT2) $(EXTRA_PARTS) objc/runtime-info.h $(OBJC_O)
- -rm -f libobjc.a
- $(AR) $(AR_FLAGS) libobjc.a $(OBJC_O)
- -if $(RANLIB_TEST) ; then $(RANLIB) libobjc.a; else true; fi
-
-libobjc_s.a: libobjc.a
- mv libobjc.a libobjc_s.a
-
-# Create a relocatable DLL
-libobjc.dll: libobjc_s.a objc/libobjc_entry.o
- $(GCC_FOR_TARGET) -mdll -Wl,--base-file -Wl,libobjc.base \
- -o libobjc.dll libobjc_s.a \
- objc/libobjc_entry.o -lkernel32
- $(DLLTOOL) --dllname libobjc.dll --def $(srcdir)/objc/libobjc.def \
- --base-file libobjc.base --output-exp libobjc.exp
- $(GCC_FOR_TARGET) -mdll -Wl,--base-file libobjc.base libobjc.exp \
- -o libobjc.dll libobjc_s.a \
- objc/libobjc_entry.o -lkernel32
- $(DLLTOOL) --dllname libobjc.dll --def $(srcdir)/objc/libobjc.def \
- --base-file libobjc.base --output-exp libobjc.exp
- $(GCC_FOR_TARGET) libobjc.exp -mdll \
- -o libobjc.dll libobjc_s.a \
- objc/libobjc_entry.o -lkernel32
- $(DLLTOOL) --dllname libobjc.dll --def $(srcdir)/objc/libobjc.def \
- --output-lib libobjc.a
-
-# Platform generated information needed by ObjC runtime
-objc/runtime-info.h: cc1obj$(exeext)
- echo "" > tmp-runtime
- echo "/* This file is automatically generated */" >$@
- ./cc1obj -print-objc-runtime-info tmp-runtime >>$@
- rm -f tmp-runtime
#
# Build hooks:
@@ -228,25 +106,7 @@ objc.dvi:
# Install hooks:
# cc1obj is installed elsewhere as part of $(COMPILERS).
-objc.install-normal: installdirs
- -if [ -f libobjc.a ] ; then \
- rm -f $(libsubdir)/libobjc.a; \
- $(INSTALL_DATA) libobjc.a $(libsubdir)/libobjc.a; \
- if $(RANLIB_TEST) ; then \
- (cd $(libsubdir); $(RANLIB) libobjc.a); else true; fi; \
- chmod a-x $(libsubdir)/libobjc.a; \
- else true; fi
- -if [ -f libobjc_s.a ] ; then \
- rm -f $(libsubdir)/libobjc_s.a; \
- $(INSTALL_DATA) libobjc_s.a $(libsubdir)/libobjc_s.a; \
- if $(RANLIB_TEST) ; then \
- (cd $(libsubdir); $(RANLIB) libobjc_s.a); else true; fi; \
- chmod a-x $(libsubdir)/libobjc_s.a; \
- else true; fi
- -if [ -f libobjc.dll ] ; then \
- rm -f $(bindir)/libobjc.dll; \
- $(INSTALL_DATA) libobjc.dll $(bindir)/libobjc.dll; \
- else true; fi
+objc.install-normal:
objc.install-common:
@@ -262,9 +122,6 @@ objc.uninstall:
objc.mostlyclean:
-rm -f tmp-objc-prs.y
-rm -f objc/*$(objext) objc/xforward objc/fflags
- -rm -f objc/runtime-info.h
- -rm -f libobjc.a libobjc_s.a libobjc.dll
- -rm -f libobjc.base libobjc.exp
objc.clean: objc.mostlyclean
-rm -rf objc-headers
objc.distclean:
@@ -282,19 +139,15 @@ objc.maintainer-clean:
objc.stage1: stage1-start
-mv objc/*$(objext) stage1/objc
-mv cc1obj$(exeext) stage1
- -mv libobjc.a stage1
objc.stage2: stage2-start
-mv objc/*$(objext) stage2/objc
-mv cc1obj$(exeext) stage2
- -mv libobjc.a stage2
objc.stage3: stage3-start
-mv objc/*$(objext) stage3/objc
-mv cc1obj$(exeext) stage3
- -mv libobjc.a stage3
objc.stage4: stage4-start
-mv objc/*$(objext) stage4/objc
-mv cc1obj$(exeext) stage4
- -mv libobjc.a stage4
#
# Maintenance hooks:
diff --git a/contrib/gcc/objc/Makefile.in b/contrib/gcc/objc/Makefile.in
index 5f1bc88..71c564c 100644
--- a/contrib/gcc/objc/Makefile.in
+++ b/contrib/gcc/objc/Makefile.in
@@ -1,5 +1,5 @@
-# GNU Objective C Runtime Makefile
-# Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
+# GNU Objective C frontend Makefile
+# Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
#
# This file is part of GNU CC.
#
@@ -17,21 +17,19 @@
# Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
-# This makefile is run by the parent dir's makefile.
-# thisdir1=`pwd`; \
-# srcdir1=`cd $(srcdir); pwd`; \
-# cd objc; \
-# $(MAKE) $(MAKEFLAGS) -f $$srcdir1/objc/Makefile libobjc.a \
-# srcdir=$$srcdir1 tooldir=$(tooldir) AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" \
-# GCC_FOR_TARGET="$$thisdir1/xgcc -B$$thisdir1/" \
-# GCC_CFLAGS="$(GCC_CFLAGS)" incinstalldir=$$thisdir1/include
-# OBJC_THREAD_FILE="$(OBJC_THREAD_FILE)"
-# Two targets are used by ../Makefile: `all' and `mostlyclean'.
+# The Makefile built from this file lives in the objc language subdirectory.
+# Its purpose is to provide support for:
+#
+# 1. recursion where necessary, and only then (building .o's), and
+# 2. building and debugging cc1objc from the language subdirectory.
+#
+# The parent Makefile handles all other chores, with help from the language
+# Makefile fragment.
+#
+# The targets for external use are `all' and `mostlyclean'.
SHELL=/bin/sh
-.SUFFIXES: .m
-
OPTIMIZE= -O
srcdir = .
@@ -56,33 +54,17 @@ all: all.indirect
####build overrides
#
-OBJC_H = hash.h objc-list.h sarray.h objc.h objc-api.h \
- NXConstStr.h Object.h Protocol.h encoding.h typedstream.h thr.h
-
# Now figure out from those variables how to compile and link.
-all.indirect: Makefile compiler objc-runtime
+all.indirect: Makefile frontend
-compiler:
+frontend:
cd ..; $(MAKE) cc1obj$(exeext)
-objc-runtime:
- cd ..; $(MAKE) libobjc.a
-
-# copy objc headers to installation include directory
-copy-headers:
- -rm -fr $(incinstalldir)/objc
- -mkdir $(incinstalldir)/objc
- for file in $(OBJC_H); do \
- realfile=$(srcdir)/$${file}; \
- cp $${realfile} $(incinstalldir)/objc; \
- chmod a+r $(incinstalldir)/objc/$${file}; \
- done
-
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
mostlyclean:
- -rm -f *.o libobjc.a xforward fflags
+ -rm -f *.o xforward fflags
clean: mostlyclean
distclean: mostlyclean
extraclean: mostlyclean
diff --git a/contrib/gcc/objc/config-lang.in b/contrib/gcc/objc/config-lang.in
index 6c9b203..5287c8d 100644
--- a/contrib/gcc/objc/config-lang.in
+++ b/contrib/gcc/objc/config-lang.in
@@ -33,5 +33,3 @@ compilers="cc1obj\$(exeext)"
stagestuff=""
diff_excludes="-x objc-parse.c -x objc-parse.y "
-
-echo "Using \`$srcdir/objc/thr-${thread_file}.c' as Objective-C Runtime thread file."
diff --git a/contrib/gcc/objc/lang-specs.h b/contrib/gcc/objc/lang-specs.h
new file mode 100644
index 0000000..41dc097
--- /dev/null
+++ b/contrib/gcc/objc/lang-specs.h
@@ -0,0 +1,96 @@
+/* Definitions for specs for Objective-C.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This is the contribution to the `default_compilers' array in gcc.c for
+ objc. */
+
+ {".m", {"@objective-c"}},
+ {"@objective-c",
+#if USE_CPPLIB
+ {"%{E|M|MM:cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
+ %{C:%{!E:%eGNU C does not support -C without using -E}}\
+ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ -D__OBJC__ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{ansi:-trigraphs -D__STRICT_ANSI__}\
+ %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
+ %{traditional} %{ftraditional:-traditional}\
+ %{traditional-cpp:-traditional}\
+ %{fleading-underscore} %{fno-leading-underscore}\
+ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
+ %i %{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}}\n}",
+ "%{!M:%{!MM:%{!E:cc1obj %i %1 \
+ %{nostdinc*} %{A*} %{I*} %{P} %I\
+ %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ -D__OBJC__ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
+ %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a*}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+ %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
+ -lang-objc %{gen-decls} \
+ %{aux-info*} %{Qn:-fno-ident}\
+ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
+ %{!S:as %a %Y\
+ %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
+ %{!pipe:%g.s} %A\n }}}}"}
+#else /* ! USE_CPPLIB */
+ {"cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
+ %{C:%{!E:%eGNU C does not support -C without using -E}}\
+ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
+ -D__OBJC__ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{ansi:-trigraphs -D__STRICT_ANSI__}\
+ %{!undef:%{!ansi:%p} %P} %{trigraphs}\
+ %c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
+ %{ffast-math:-D__FAST_MATH__}\
+ %{traditional} %{ftraditional:-traditional}\
+ %{traditional-cpp:-traditional}\
+ %{fleading-underscore} %{fno-leading-underscore}\
+ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
+ %i %{!M:%{!MM:%{!E:%{!pipe:%g.mi}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n",
+ "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.mi} %1 \
+ %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a*}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+ %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
+ -lang-objc %{gen-decls} \
+ %{aux-info*} %{Qn:-fno-ident}\
+ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
+ %{!S:as %a %Y\
+ %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
+ %{!pipe:%g.s} %A\n }}}}"}
+#endif /* ! USE_CPPLIB */
+ },
+ {".mi", {"@objc-cpp-output"}},
+ {"@objc-cpp-output",
+ {"%{!M:%{!MM:%{!E:cc1obj %i %1 \
+ %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a*}\
+ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \
+ %{traditional} %{v:-version} %{pg:-p} %{p} %{f*} \
+ -lang-objc %{gen-decls} \
+ %{aux-info*} %{Qn:-fno-ident}\
+ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n",
+ "%{!S:as %a %Y\
+ %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\
+ %{!pipe:%g.s} %A\n }}}}"}},
diff --git a/contrib/gcc/objc/objc-act.c b/contrib/gcc/objc/objc-act.c
index 0f4058b..a2842c8 100644
--- a/contrib/gcc/objc/objc-act.c
+++ b/contrib/gcc/objc/objc-act.c
@@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA. */
#include "cpplib.h"
extern cpp_reader parse_in;
extern cpp_options parse_options;
-static int cpp_initialized;
#endif
/* This is the default way of generating a method name. */
@@ -284,7 +283,8 @@ static void dump_interface PROTO((FILE *, tree));
/* Everything else. */
-static void objc_fatal PROTO((void));
+static void objc_fatal PROTO((void))
+ ATTRIBUTE_NORETURN;
static tree define_decl PROTO((tree, tree));
static tree lookup_method_in_protocol_list PROTO((tree, tree, int));
static tree lookup_protocol_in_reflist PROTO((tree, tree));
@@ -591,9 +591,18 @@ generate_struct_by_value_array ()
exit (0);
}
+#if USE_CPPLIB
+extern char *yy_cur;
+#endif
+
void
lang_init_options ()
{
+#if USE_CPPLIB
+ cpp_reader_init (&parse_in);
+ parse_in.opts = &parse_options;
+ cpp_options_init (&parse_options);
+#endif
}
void
@@ -604,7 +613,10 @@ lang_init ()
With luck, we discover the real source file's name from that
and put it in input_filename. */
ungetc (check_newline (), finput);
-#endif
+#else
+ check_newline ();
+ yy_cur--;
+#endif
/* The line number can be -1 if we had -g3 and the input file
had a directive specifying line 0. But we want predefined
@@ -682,15 +694,6 @@ lang_decode_option (argc, argv)
char **argv;
{
char *p = argv[0];
-#if USE_CPPLIB
- if (! cpp_initialized)
- {
- cpp_reader_init (&parse_in);
- parse_in.data = &parse_options;
- cpp_options_init (&parse_options);
- cpp_initialized = 1;
- }
-#endif
if (!strcmp (p, "-lang-objc"))
doing_objc_thang = 1;
else if (!strcmp (p, "-gen-decls"))
@@ -1317,7 +1320,7 @@ my_build_string (len, str)
tree
build_objc_string (len, str)
int len;
- char *str;
+ const char *str;
{
tree s = build_string (len, str);
@@ -1855,6 +1858,8 @@ get_objc_string_decl (ident, section)
chain = meth_var_names_chain;
else if (section == meth_var_types)
chain = meth_var_types_chain;
+ else
+ abort ();
for (; chain != 0; chain = TREE_VALUE (chain))
if (TREE_VALUE (chain) == ident)
@@ -2078,7 +2083,7 @@ build_selector_translation_table ()
tree sc_spec, decl_specs;
tree chain, initlist = NULL_TREE;
int offset = 0;
- tree decl, var_decl, name;
+ tree decl = NULL_TREE, var_decl, name;
/* The corresponding pop_obstacks is in finish_decl,
called at the end of this function. */
@@ -2350,6 +2355,8 @@ add_objc_string (ident, section)
chain = &meth_var_names_chain;
else if (section == meth_var_types)
chain = &meth_var_types_chain;
+ else
+ abort ();
while (*chain)
{
@@ -3380,6 +3387,7 @@ build_selector_template ()
struct objc_class *sibling_class;
}
struct objc_protocol_list *protocols;
+ void *gc_object_type;
}; */
static void
@@ -3515,6 +3523,21 @@ build_class_template ()
decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
+ /* void *sel_id; */
+
+ decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
+ field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
+ field_decl
+ = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
+ chainon (field_decl_chain, field_decl);
+
+ /* void *gc_object_type; */
+
+ decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
+ field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
+ field_decl
+ = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
+ chainon (field_decl_chain, field_decl);
finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
}
@@ -4203,6 +4226,8 @@ generate_protocol_list (i_or_p)
synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
i_or_p),
build_int_2 (size + 2, 0));
+ else
+ abort ();
expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl);
@@ -4287,6 +4312,7 @@ build_category_initializer (type, cat_name, class_name,
struct objc_class *sibling_class;
}
struct objc_protocol_list *protocols;
+ void *gc_object_type;
}; */
static tree
@@ -4377,6 +4403,9 @@ build_shared_structure_initializer (type, isa, super, name, size, status,
initlist = tree_cons (NULL_TREE, expr, initlist);
}
+ /* gc_object_type = NULL */
+ initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+
return build_constructor (type, nreverse (initlist));
}
@@ -4576,6 +4605,9 @@ synth_id_with_class_suffix (preamble, ctxt)
= (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3);
sprintf (string, "%s_%s", preamble, protocol_name);
}
+ else
+ abort ();
+
return get_identifier (string);
}
@@ -4590,6 +4622,7 @@ is_objc_type_qualifier (node)
|| node == ridpointers [(int) RID_OUT]
|| node == ridpointers [(int) RID_INOUT]
|| node == ridpointers [(int) RID_BYCOPY]
+ || node == ridpointers [(int) RID_BYREF]
|| node == ridpointers [(int) RID_ONEWAY]));
}
@@ -4676,6 +4709,8 @@ build_keyword_selector (selector)
key_name = KEYWORD_KEY_NAME (key_chain);
else if (TREE_CODE (selector) == TREE_LIST)
key_name = TREE_PURPOSE (key_chain);
+ else
+ abort ();
if (key_name)
len += IDENTIFIER_LENGTH (key_name) + 1;
@@ -4693,6 +4728,8 @@ build_keyword_selector (selector)
key_name = KEYWORD_KEY_NAME (key_chain);
else if (TREE_CODE (selector) == TREE_LIST)
key_name = TREE_PURPOSE (key_chain);
+ else
+ abort ();
if (key_name)
strcat (buf, IDENTIFIER_POINTER (key_name));
@@ -4945,6 +4982,8 @@ build_message_expr (mess)
sel_name = args;
else if (TREE_CODE (args) == TREE_LIST)
sel_name = build_keyword_selector (args);
+ else
+ abort ();
/* Build the parameter list to give to the method. */
@@ -5351,6 +5390,8 @@ build_selector_expr (selnamelist)
selname = selnamelist;
else if (TREE_CODE (selnamelist) == TREE_LIST)
selname = build_keyword_selector (selnamelist);
+ else
+ abort ();
if (flag_typed_selectors)
return build_typed_selector_reference (selname, 0);
@@ -6475,6 +6516,8 @@ encode_type_qualifiers (declspecs)
obstack_1grow (&util_obstack, 'o');
else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
obstack_1grow (&util_obstack, 'O');
+ else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'R');
else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
obstack_1grow (&util_obstack, 'V');
}
@@ -6819,6 +6862,62 @@ encode_type (type, curtype, format)
}
static void
+encode_complete_bitfield (int position, tree type, int size)
+{
+ enum tree_code code = TREE_CODE (type);
+ char buffer[40];
+ char charType = '?';
+
+ if (code == INTEGER_TYPE)
+ {
+ if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
+ && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
+ {
+ /* Unsigned integer types. */
+
+ if (TYPE_MODE (type) == QImode)
+ charType = 'C';
+ else if (TYPE_MODE (type) == HImode)
+ charType = 'S';
+ else if (TYPE_MODE (type) == SImode)
+ {
+ if (type == long_unsigned_type_node)
+ charType = 'L';
+ else
+ charType = 'I';
+ }
+ else if (TYPE_MODE (type) == DImode)
+ charType = 'Q';
+ }
+
+ else
+ /* Signed integer types. */
+ {
+ if (TYPE_MODE (type) == QImode)
+ charType = 'c';
+ else if (TYPE_MODE (type) == HImode)
+ charType = 's';
+ else if (TYPE_MODE (type) == SImode)
+ {
+ if (type == long_integer_type_node)
+ charType = 'l';
+ else
+ charType = 'i';
+ }
+
+ else if (TYPE_MODE (type) == DImode)
+ charType = 'q';
+ }
+ }
+
+ else
+ abort ();
+
+ sprintf (buffer, "b%d%c%d", position, charType, size);
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+}
+
+static void
encode_field_decl (field_decl, curtype, format)
tree field_decl;
int curtype;
@@ -6826,18 +6925,36 @@ encode_field_decl (field_decl, curtype, format)
{
tree type;
- /* If this field is obviously a bitfield, or is a bitfield that has been
+ type = TREE_TYPE (field_decl);
+
+ /* If this field is obviously a bitfield, or is a bitfield that has been
clobbered to look like a ordinary integer mode, go ahead and generate
the bitfield typing information. */
- type = TREE_TYPE (field_decl);
- if (DECL_BIT_FIELD (field_decl))
- encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
- else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && DECL_FIELD_SIZE (field_decl)
- && TYPE_MODE (type) > DECL_MODE (field_decl))
- encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
+ if (flag_next_runtime)
+ {
+ if (DECL_BIT_FIELD (field_decl))
+ encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
+ else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && DECL_FIELD_SIZE (field_decl)
+ && TYPE_MODE (type) > DECL_MODE (field_decl))
+ encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
+ else
+ encode_type (TREE_TYPE (field_decl), curtype, format);
+ }
else
- encode_type (TREE_TYPE (field_decl), curtype, format);
+ {
+ if (DECL_BIT_FIELD (field_decl)
+ || (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && DECL_FIELD_SIZE (field_decl)
+ && TYPE_MODE (type) > DECL_MODE (field_decl)))
+ {
+ encode_complete_bitfield (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)),
+ DECL_BIT_FIELD_TYPE (field_decl),
+ DECL_FIELD_SIZE (field_decl));
+ }
+ else
+ encode_type (TREE_TYPE (field_decl), curtype, format);
+ }
}
static tree
@@ -7535,7 +7652,7 @@ gen_declarator (decl, buf, name)
return buf;
default:
- break;
+ abort ();
}
return str;
diff --git a/contrib/gcc/objc/objc-tree.def b/contrib/gcc/objc/objc-tree.def
index 9d6765b..a661624 100644
--- a/contrib/gcc/objc/objc-tree.def
+++ b/contrib/gcc/objc/objc-tree.def
@@ -1,7 +1,7 @@
/* This file contains the definitions and documentation for the
additional tree codes used in the Objective C front end (see tree.def
for the standard codes).
- Copyright (C) 1990 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/contrib/gcc/optabs.c b/contrib/gcc/optabs.c
index 4b31fe0..2b9091b 100644
--- a/contrib/gcc/optabs.c
+++ b/contrib/gcc/optabs.c
@@ -1,5 +1,5 @@
/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,13 +21,17 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "toplev.h"
+
+/* Include insn-config.h before expr.h so that HAVE_conditional_move
+ is properly defined. */
+#include "insn-config.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "insn-flags.h"
#include "insn-codes.h"
#include "expr.h"
-#include "insn-config.h"
#include "recog.h"
#include "reload.h"
@@ -119,11 +123,13 @@ rtx memset_libfunc;
rtx bzero_libfunc;
rtx throw_libfunc;
+rtx rethrow_libfunc;
rtx sjthrow_libfunc;
rtx sjpopnthrow_libfunc;
rtx terminate_libfunc;
rtx setjmp_libfunc;
rtx longjmp_libfunc;
+rtx eh_rtime_match_libfunc;
rtx eqhf2_libfunc;
rtx nehf2_libfunc;
@@ -214,6 +220,9 @@ rtx chkr_copy_bitmap_libfunc;
rtx chkr_check_exec_libfunc;
rtx chkr_check_str_libfunc;
+rtx profile_function_entry_libfunc;
+rtx profile_function_exit_libfunc;
+
/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
gives the gen_function to make a branch to test that condition. */
@@ -237,15 +246,23 @@ enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
static rtx widen_operand PROTO((rtx, enum machine_mode,
enum machine_mode, int, int));
+static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx,
+ rtx, rtx, enum machine_mode,
+ int, enum optab_methods,
+ enum mode_class, optab));
+static int expand_cmplxdiv_wide PROTO((rtx, rtx, rtx, rtx,
+ rtx, rtx, enum machine_mode,
+ int, enum optab_methods,
+ enum mode_class, optab));
static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode,
int, int *));
static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
int));
static rtx ftruncify PROTO((rtx));
static optab init_optab PROTO((enum rtx_code));
-static void init_libfuncs PROTO((optab, int, int, char *, int));
-static void init_integral_libfuncs PROTO((optab, char *, int));
-static void init_floating_libfuncs PROTO((optab, char *, int));
+static void init_libfuncs PROTO((optab, int, int, const char *, int));
+static void init_integral_libfuncs PROTO((optab, const char *, int));
+static void init_floating_libfuncs PROTO((optab, const char *, int));
#ifdef HAVE_conditional_trap
static void init_traps PROTO((void));
#endif
@@ -297,9 +314,7 @@ add_equal_note (seq, target, code, op0, op1)
else
note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
- REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))
- = gen_rtx_EXPR_LIST (REG_EQUAL, note,
- REG_NOTES (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)));
+ set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
return 1;
}
@@ -341,6 +356,379 @@ widen_operand (op, mode, oldmode, unsignedp, no_extend)
return result;
}
+/* Generate code to perform a straightforward complex divide. */
+
+static int
+expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
+ unsignedp, methods, class, binoptab)
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
+{
+ rtx divisor;
+ rtx real_t, imag_t;
+ rtx temp1, temp2;
+ rtx res;
+
+ /* Don't fetch these from memory more than once. */
+ real0 = force_reg (submode, real0);
+ real1 = force_reg (submode, real1);
+
+ if (imag0 != 0)
+ imag0 = force_reg (submode, imag0);
+
+ imag1 = force_reg (submode, imag1);
+
+ /* Divisor: c*c + d*d. */
+ temp1 = expand_binop (submode, smul_optab, real1, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, imag1, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+ if (divisor == 0)
+ return 0;
+
+ if (imag0 == 0)
+ {
+ /* Mathematically, ((a)(c-id))/divisor. */
+ /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
+
+ /* Calculate the dividend. */
+ real_t = expand_binop (submode, smul_optab, real0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ imag_t = expand_binop (submode, smul_optab, real0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+
+ imag_t = expand_unop (submode, neg_optab, imag_t,
+ NULL_RTX, unsignedp);
+ }
+ else
+ {
+ /* Mathematically, ((a+ib)(c-id))/divider. */
+ /* Calculate the dividend. */
+ temp1 = expand_binop (submode, smul_optab, real0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, imag0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, imag0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, real0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ return 1;
+}
+
+/* Generate code to perform a wide-input-range-acceptable complex divide. */
+
+static int
+expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
+ unsignedp, methods, class, binoptab)
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
+{
+ rtx ratio, divisor;
+ rtx real_t, imag_t;
+ rtx temp1, temp2, lab1, lab2;
+ enum machine_mode mode;
+ int align;
+ rtx res;
+
+ /* Don't fetch these from memory more than once. */
+ real0 = force_reg (submode, real0);
+ real1 = force_reg (submode, real1);
+
+ if (imag0 != 0)
+ imag0 = force_reg (submode, imag0);
+
+ imag1 = force_reg (submode, imag1);
+
+ /* XXX What's an "unsigned" complex number? */
+ if (unsignedp)
+ {
+ temp1 = real1;
+ temp2 = imag1;
+ }
+ else
+ {
+ temp1 = expand_abs (submode, real1, NULL_RTX, 1);
+ temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
+ }
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ mode = GET_MODE (temp1);
+ align = GET_MODE_ALIGNMENT (mode);
+ lab1 = gen_label_rtx ();
+ emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
+ mode, unsignedp, align, lab1);
+
+ /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
+
+ if (class == MODE_COMPLEX_FLOAT)
+ ratio = expand_binop (submode, binoptab, imag1, real1,
+ NULL_RTX, unsignedp, methods);
+ else
+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag1, real1, NULL_RTX, unsignedp);
+
+ if (ratio == 0)
+ return 0;
+
+ /* Calculate divisor. */
+
+ temp1 = expand_binop (submode, smul_optab, imag1, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, real1,
+ NULL_RTX, unsignedp, methods);
+
+ if (divisor == 0)
+ return 0;
+
+ /* Calculate dividend. */
+
+ if (imag0 == 0)
+ {
+ real_t = real0;
+
+ /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
+
+ imag_t = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (imag_t == 0)
+ return 0;
+
+ imag_t = expand_unop (submode, neg_optab, imag_t,
+ NULL_RTX, unsignedp);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+ else
+ {
+ /* Compute (a+ib)/(c+id) as
+ (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
+
+ temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, real0,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, imag0, temp1,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ lab2 = gen_label_rtx ();
+ emit_jump_insn (gen_jump (lab2));
+ emit_barrier ();
+
+ emit_label (lab1);
+
+ /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
+
+ if (class == MODE_COMPLEX_FLOAT)
+ ratio = expand_binop (submode, binoptab, real1, imag1,
+ NULL_RTX, unsignedp, methods);
+ else
+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real1, imag1, NULL_RTX, unsignedp);
+
+ if (ratio == 0)
+ return 0;
+
+ /* Calculate divisor. */
+
+ temp1 = expand_binop (submode, smul_optab, real1, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (divisor == 0)
+ return 0;
+
+ /* Calculate dividend. */
+
+ if (imag0 == 0)
+ {
+ /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
+
+ real_t = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ imag_t = expand_unop (submode, neg_optab, real0,
+ NULL_RTX, unsignedp);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+ else
+ {
+ /* Compute (a+ib)/(c+id) as
+ (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
+
+ temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, imag0,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, temp1, real0,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ emit_label (lab2);
+
+ return 1;
+}
+
/* Generate code to perform an operation specified by BINOPTAB
on operands OP0 and OP1, with result having machine-mode MODE.
@@ -891,7 +1279,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
rtx carry_tmp = gen_reg_rtx (word_mode);
optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
- rtx carry_in, carry_out;
+ rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
rtx xop0, xop1;
/* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
@@ -982,12 +1370,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
{
rtx temp = emit_move_insn (target, target);
- REG_NOTES (temp)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_fmt_ee (binoptab->code, mode,
- copy_rtx (xop0),
- copy_rtx (xop1)),
- REG_NOTES (temp));
+ set_unique_reg_note (temp,
+ REG_EQUAL,
+ gen_rtx_fmt_ee (binoptab->code, mode,
+ copy_rtx (xop0),
+ copy_rtx (xop1)));
}
return target;
}
@@ -1062,8 +1449,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
rtx op1_high = operand_subword_force (op1, high, mode);
rtx op1_low = operand_subword_force (op1, low, mode);
rtx product = 0;
- rtx op0_xhigh;
- rtx op1_xhigh;
+ rtx op0_xhigh = NULL_RTX;
+ rtx op1_xhigh = NULL_RTX;
/* If the target is the same as one of the inputs, don't use it. This
prevents problems with the REG_EQUAL note. */
@@ -1165,12 +1552,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
temp = emit_move_insn (product, product);
- REG_NOTES (temp)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_fmt_ee (MULT, mode,
- copy_rtx (op0),
- copy_rtx (op1)),
- REG_NOTES (temp));
+ set_unique_reg_note (temp,
+ REG_EQUAL,
+ gen_rtx_fmt_ee (MULT, mode,
+ copy_rtx (op0),
+ copy_rtx (op1)));
}
return product;
}
@@ -1214,12 +1600,12 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
start_sequence ();
- realr = gen_realpart (submode, target);
+ realr = gen_realpart (submode, target);
imagr = gen_imagpart (submode, target);
if (GET_MODE (op0) == mode)
{
- real0 = gen_realpart (submode, op0);
+ real0 = gen_realpart (submode, op0);
imag0 = gen_imagpart (submode, op0);
}
else
@@ -1227,7 +1613,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (GET_MODE (op1) == mode)
{
- real1 = gen_realpart (submode, op1);
+ real1 = gen_realpart (submode, op1);
imag1 = gen_imagpart (submode, op1);
}
else
@@ -1385,111 +1771,25 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
}
else
{
- /* Divisor is of complex type:
- X/(a+ib) */
- rtx divisor;
- rtx real_t, imag_t;
- rtx temp1, temp2;
-
- /* Don't fetch these from memory more than once. */
- real0 = force_reg (submode, real0);
- real1 = force_reg (submode, real1);
-
- if (imag0 != 0)
- imag0 = force_reg (submode, imag0);
-
- imag1 = force_reg (submode, imag1);
-
- /* Divisor: c*c + d*d */
- temp1 = expand_binop (submode, smul_optab, real1, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, imag1, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
-
- divisor = expand_binop (submode, add_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
- if (divisor == 0)
- break;
-
- if (imag0 == 0)
- {
- /* ((a)(c-id))/divisor */
- /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
-
- /* Calculate the dividend */
- real_t = expand_binop (submode, smul_optab, real0, real1,
- NULL_RTX, unsignedp, methods);
-
- imag_t = expand_binop (submode, smul_optab, real0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (real_t == 0 || imag_t == 0)
- break;
-
- imag_t = expand_unop (submode, neg_optab, imag_t,
- NULL_RTX, unsignedp);
- }
- else
+ switch (flag_complex_divide_method)
{
- /* ((a+ib)(c-id))/divider */
- /* Calculate the dividend */
- temp1 = expand_binop (submode, smul_optab, real0, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, imag0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
-
- real_t = expand_binop (submode, add_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
-
- temp1 = expand_binop (submode, smul_optab, imag0, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, real0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
+ case 0:
+ ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
+ realr, imagr, submode,
+ unsignedp, methods,
+ class, binoptab);
+ break;
- imag_t = expand_binop (submode, sub_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
+ case 1:
+ ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
+ realr, imagr, submode,
+ unsignedp, methods,
+ class, binoptab);
+ break;
- if (real_t == 0 || imag_t == 0)
- break;
+ default:
+ abort ();
}
-
- if (class == MODE_COMPLEX_FLOAT)
- res = expand_binop (submode, binoptab, real_t, divisor,
- realr, unsignedp, methods);
- else
- res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
- real_t, divisor, realr, unsignedp);
-
- if (res == 0)
- break;
- else if (res != realr)
- emit_move_insn (realr, res);
-
- if (class == MODE_COMPLEX_FLOAT)
- res = expand_binop (submode, binoptab, imag_t, divisor,
- imagr, unsignedp, methods);
- else
- res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
- imag_t, divisor, imagr, unsignedp);
-
- if (res == 0)
- break;
- else if (res != imagr)
- emit_move_insn (imagr, res);
-
- ok = 1;
}
break;
@@ -2101,14 +2401,13 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
MODE is the mode of the operand; the mode of the result is
different but can be deduced from MODE.
- UNSIGNEDP is relevant if extension is needed. */
+ */
rtx
-expand_abs (mode, op0, target, unsignedp, safe)
+expand_abs (mode, op0, target, safe)
enum machine_mode mode;
rtx op0;
rtx target;
- int unsignedp;
int safe;
{
rtx temp, op1;
@@ -2538,8 +2837,7 @@ emit_no_conflict_block (insns, target, op0, op1, equiv)
{
last = emit_move_insn (target, target);
if (equiv)
- REG_NOTES (last)
- = gen_rtx_EXPR_LIST (REG_EQUAL, equiv, REG_NOTES (last));
+ set_unique_reg_note (last, REG_EQUAL, equiv);
}
else
last = get_last_insn ();
@@ -2591,6 +2889,21 @@ emit_libcall_block (insns, target, result, equiv)
{
rtx prev, next, first, last, insn;
+ /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
+ reg note to indicate that this call cannot throw. (Unless there is
+ already a REG_EH_REGION note.) */
+
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+ if (note == NULL_RTX)
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
+ REG_NOTES (insn));
+ }
+ }
+
/* First emit all insns that set pseudos. Remove them from the list as
we go. Avoid insns that set pseudos which were referenced in previous
insns. These can be generated by move_by_pieces, for example,
@@ -2637,8 +2950,7 @@ emit_libcall_block (insns, target, result, equiv)
last = emit_move_insn (target, result);
if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
!= CODE_FOR_nothing)
- REG_NOTES (last) = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (equiv),
- REG_NOTES (last));
+ set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
if (prev == 0)
first = get_insns ();
@@ -2717,6 +3029,14 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
if (CONSTANT_P (y) && preserve_subexpressions_p () && rtx_cost (y, COMPARE) > 2)
y = force_reg (mode, y);
+#ifdef HAVE_cc0
+ /* Abort if we have a non-canonical comparison. The RTL documentation
+ states that canonical comparisons are required only for targets which
+ have cc0. */
+ if (CONSTANT_P (x) && ! CONSTANT_P (y))
+ abort();
+#endif
+
/* Don't let both operands fail to indicate the mode. */
if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
x = force_reg (mode, x);
@@ -2908,6 +3228,66 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
abort ();
}
+/* Generate code to compare X with Y so that the condition codes are
+ set and to jump to LABEL if the condition is true. If X is a
+ constant and Y is not a constant, then the comparison is swapped to
+ ensure that the comparison RTL has the canonical form.
+
+ UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
+ need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
+ the proper branch condition code.
+
+ If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y,
+ and ALIGN specifies the known shared alignment of X and Y.
+
+ MODE is the mode of the inputs (in case they are const_int).
+
+ COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
+ be passed unchanged to emit_cmp_insn, then potentially converted into an
+ unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
+
+void
+emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
+ rtx x, y;
+ enum rtx_code comparison;
+ rtx size;
+ enum machine_mode mode;
+ int unsignedp;
+ int align;
+ rtx label;
+{
+ rtx op0;
+ rtx op1;
+
+ if (CONSTANT_P (x))
+ {
+ /* Swap operands and condition to ensure canonical RTL. */
+ op0 = y;
+ op1 = x;
+ comparison = swap_condition (comparison);
+ }
+ else
+ {
+ op0 = x;
+ op1 = y;
+ }
+
+#ifdef HAVE_cc0
+ /* If OP0 is still a constant, then both X and Y must be constants. Force
+ X into a register to avoid aborting in emit_cmp_insn due to non-canonical
+ RTL. */
+ if (CONSTANT_P (op0))
+ op0 = force_reg (mode, op0);
+#endif
+
+ emit_cmp_insn (op0, op1, comparison, size, mode, unsignedp, align);
+
+ if (unsignedp)
+ comparison = unsigned_condition (comparison);
+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
+}
+
+
/* Nonzero if a compare of mode MODE can be done straightforwardly
(without splitting it into pieces). */
@@ -3384,8 +3764,7 @@ gen_move_insn (x, y)
{
x = gen_rtx_MEM (tmode, XEXP (x1, 0));
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (x1);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (x1);
- MEM_VOLATILE_P (x) = MEM_VOLATILE_P (x1);
+ MEM_COPY_ATTRIBUTES (x, x1);
copy_replacements (x1, x);
}
@@ -3394,8 +3773,7 @@ gen_move_insn (x, y)
{
y = gen_rtx_MEM (tmode, XEXP (y1, 0));
RTX_UNCHANGING_P (y) = RTX_UNCHANGING_P (y1);
- MEM_IN_STRUCT_P (y) = MEM_IN_STRUCT_P (y1);
- MEM_VOLATILE_P (y) = MEM_VOLATILE_P (y1);
+ MEM_COPY_ATTRIBUTES (y, y1);
copy_replacements (y1, y);
}
}
@@ -3629,8 +4007,8 @@ expand_float (to, from, unsignedp)
correct its value by 2**bitwidth. */
do_pending_stack_adjust ();
- emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0);
- emit_jump_insn (gen_bge (label));
+ emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
+ 0, 0, label);
/* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
Rather than setting up a dconst_dot_5, let's hope SCO
@@ -3837,8 +4215,8 @@ expand_fix (to, from, unsignedp)
/* See if we need to do the subtraction. */
do_pending_stack_adjust ();
- emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0);
- emit_jump_insn (gen_bge (lab1));
+ emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
+ 0, 0, lab1);
/* If not, do the signed "fix" and branch around fixup code. */
expand_fix (to, from, 0);
@@ -3866,12 +4244,11 @@ expand_fix (to, from, unsignedp)
{
/* Make a place for a REG_NOTE and add it. */
insn = emit_move_insn (to, to);
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- gen_rtx_fmt_e (UNSIGNED_FIX,
- GET_MODE (to),
- copy_rtx (from)),
- REG_NOTES (insn));
+ set_unique_reg_note (insn,
+ REG_EQUAL,
+ gen_rtx_fmt_e (UNSIGNED_FIX,
+ GET_MODE (to),
+ copy_rtx (from)));
}
return;
}
@@ -4008,7 +4385,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
register optab optable;
register int first_mode;
register int last_mode;
- register char *opname;
+ register const char *opname;
register int suffix;
{
register int mode;
@@ -4022,7 +4399,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
register char *libfunc_name
= (char *) xmalloc (2 + opname_len + mname_len + 1 + 1);
register char *p;
- register char *q;
+ register const char *q;
p = libfunc_name;
*p++ = '_';
@@ -4030,7 +4407,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
for (q = opname; *q; )
*p++ = *q++;
for (q = mname; *q; q++)
- *p++ = tolower (*q);
+ *p++ = tolower ((unsigned char)*q);
*p++ = suffix;
*p++ = '\0';
optable->handlers[(int) mode].libfunc
@@ -4046,7 +4423,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
static void
init_integral_libfuncs (optable, opname, suffix)
register optab optable;
- register char *opname;
+ register const char *opname;
register int suffix;
{
init_libfuncs (optable, SImode, TImode, opname, suffix);
@@ -4060,7 +4437,7 @@ init_integral_libfuncs (optable, opname, suffix)
static void
init_floating_libfuncs (optable, opname, suffix)
register optab optable;
- register char *opname;
+ register const char *opname;
register int suffix;
{
init_libfuncs (optable, SFmode, TFmode, opname, suffix);
@@ -4290,9 +4667,11 @@ init_optabs ()
bzero_libfunc = gen_rtx_SYMBOL_REF (Pmode, "bzero");
throw_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__throw");
+ rethrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__rethrow");
sjthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjthrow");
sjpopnthrow_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__sjpopnthrow");
terminate_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__terminate");
+ eh_rtime_match_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match");
#ifndef DONT_USE_BUILTIN_SETJMP
setjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_setjmp");
longjmp_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__builtin_longjmp");
@@ -4385,11 +4764,17 @@ init_optabs ()
fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
/* For check-memory-usage. */
- chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_check_addr");
- chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_set_right");
- chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_copy_bitmap");
- chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_check_exec");
- chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_check_str");
+ chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
+ chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
+ chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
+ chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
+ chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
+
+ /* For function entry/exit instrumentation. */
+ profile_function_entry_libfunc
+ = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
+ profile_function_exit_libfunc
+ = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
#ifdef HAVE_conditional_trap
init_traps ();
@@ -4440,8 +4825,8 @@ init_traps ()
rtx
gen_cond_trap (code, op1, op2, tcode)
- enum rtx_code code;
- rtx op1, op2, tcode;
+ enum rtx_code code ATTRIBUTE_UNUSED;
+ rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
{
enum machine_mode mode = GET_MODE (op1);
diff --git a/contrib/gcc/output.h b/contrib/gcc/output.h
index e2c9f4d..8531085 100644
--- a/contrib/gcc/output.h
+++ b/contrib/gcc/output.h
@@ -1,6 +1,6 @@
/* Declarations for insn-output.c. These functions are defined in recog.c,
final.c, and varasm.c.
- Copyright (C) 1987, 1991, 1994, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991, 1994, 97-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,7 +24,7 @@ extern void init_final PROTO((char *));
/* Called at end of source file,
to output the block-profiling table for this entire compilation. */
-extern void end_final PROTO((char *));
+extern void end_final PROTO((const char *));
/* Enable APP processing of subsequent output.
Used before the output from an `asm' statement. */
@@ -77,17 +77,21 @@ extern rtx alter_subreg PROTO((rtx));
/* Report inconsistency between the assembler template and the operands.
In an `asm', it's the user's fault; otherwise, the compiler's fault. */
-extern void output_operand_lossage PROTO((char *));
+extern void output_operand_lossage PROTO((const char *));
/* Output a string of assembler code, substituting insn operands.
Defined in final.c. */
-extern void output_asm_insn PROTO((char *, rtx *));
+extern void output_asm_insn PROTO((const char *, rtx *));
/* Compute a worst-case reference address of a branch so that it
can be safely used in the presence of aligned labels.
Defined in final.c. */
extern int insn_current_reference_address PROTO((rtx));
+/* Find the alignment associated with a CODE_LABEL.
+ Defined in final.c. */
+extern int label_to_alignment PROTO((rtx));
+
/* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
extern void output_asm_label PROTO((rtx));
@@ -102,7 +106,7 @@ extern void output_addr_const PROTO((FILE *, rtx));
/* Output a string of assembler code, substituting numbers, strings
and fixed syntactic prefixes. */
-extern void asm_fprintf PROTO(PVPROTO((FILE *file, char *p, ...)));
+extern void asm_fprintf PVPROTO((FILE *file, const char *p, ...));
/* Split up a CONST_DOUBLE or integer constant rtx into two rtx's for single
words. */
@@ -127,7 +131,7 @@ extern void dump_flow_info PROTO((FILE *));
extern void find_basic_blocks PROTO((rtx, int, FILE *, int));
extern void free_basic_block_vars PROTO((int));
extern void set_block_num PROTO((rtx, int));
-extern void life_analysis PROTO((rtx, int, FILE *));
+extern void life_analysis PROTO((rtx, int, FILE *, int));
#endif
/* Functions in varasm.c. */
@@ -138,6 +142,9 @@ extern void text_section PROTO((void));
/* Tell assembler to switch to data section. */
extern void data_section PROTO((void));
+/* Tell assembler to make sure its in the data section. */
+extern void force_data_section PROTO((void));
+
/* Tell assembler to switch to read-only data section. This is normally
the text section. */
extern void readonly_data_section PROTO((void));
@@ -154,7 +161,7 @@ extern void eh_frame_section PROTO ((void));
If DECL is NULL, just switch to section NAME.
If NAME is NULL, get the name from DECL.
If RELOC is 1, the initializer for DECL contains relocs. */
-extern void named_section PROTO((tree, char *, int));
+extern void named_section PROTO((tree, const char *, int));
/* Tell assembler to switch to the section for function DECL. */
extern void function_section PROTO((tree));
@@ -181,7 +188,7 @@ extern void weak_finish PROTO ((void));
or -4 if ASMSPEC is `memory' and is not recognized.
Accept an exact spelling or a decimal number.
Prefixes such as % are optional. */
-extern int decode_reg_name PROTO((char *));
+extern int decode_reg_name PROTO((const char *));
#ifdef TREE_CODE
/* Create the DECL_RTL for a declaration for a static or external variable
@@ -191,7 +198,7 @@ extern int decode_reg_name PROTO((char *));
TOP_LEVEL is nonzero if this is a file-scope variable.
This is never called for PARM_DECL nodes. */
-extern void make_decl_rtl PROTO((tree, char *, int));
+extern void make_decl_rtl PROTO((tree, const char *, int));
/* Make the rtl for variable VAR be volatile.
Use this only for static variables. */
@@ -238,7 +245,7 @@ extern void assemble_zeros PROTO((int));
extern void assemble_align PROTO((int));
/* Assemble a string constant with the specified C string as contents. */
-extern void assemble_string PROTO((char *, int));
+extern void assemble_string PROTO((const char *, int));
/* Assemble everything that is needed for a variable or function declaration.
Not used for automatic variables, and not used for function definitions.
Should not be called for variables of incomplete structure type.
@@ -376,6 +383,29 @@ extern int current_function_has_nonlocal_label;
extern int current_function_contains_functions;
+/* Nonzero if function being compiled doesn't contain any calls
+ (ignoring the prologue and epilogue). This is set prior to
+ local register allocation and is valid for the remaining
+ compiler passes. */
+
+extern int current_function_is_leaf;
+
+/* Nonzero if function being compiled doesn't modify the stack pointer
+ (ignoring the prologue and epilogue). This is only valid after
+ life_analysis has run. */
+
+extern int current_function_sp_is_unchanging;
+
+/* Nonzero if the function being compiled is a leaf function which only
+ uses leaf registers. This is valid after reload (specifically after
+ sched2) and is useful only if the port defines LEAF_REGISTERS. */
+
+extern int current_function_uses_only_leaf_regs;
+
+/* Nonzero if the function being compiled issues a computed jump. */
+
+extern int current_function_has_computed_jump;
+
/* Nonzero if the current function returns a pointer type */
extern int current_function_returns_pointer;
@@ -456,6 +486,12 @@ extern int sdb_begin_function_line;
extern FILE *asm_out_file;
#endif
+/* Default file in which to dump debug output. */
+
+#ifdef BUFSIZ
+extern FILE *rtl_dump_file;
+#endif
+
/* Decide whether DECL needs to be in a writable section. RELOC is the same
as for SELECT_SECTION. */
@@ -466,3 +502,14 @@ extern FILE *asm_out_file;
&& (DECL_INITIAL (DECL) == error_mark_node \
|| TREE_CONSTANT (DECL_INITIAL (DECL))) \
&& ! (RELOC && (flag_pic || DECL_ONE_ONLY (DECL))))
+
+/* User label prefix in effect for this compilation. */
+extern const char *user_label_prefix;
+
+/* This macro gets just the user-specified name
+ out of the string in a SYMBOL_REF. On most machines,
+ we discard the * if any and that's all. */
+#ifndef STRIP_NAME_ENCODING
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+ (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'))
+#endif
diff --git a/contrib/gcc/prefix.c b/contrib/gcc/prefix.c
index 1c96c58..8bf5696 100644
--- a/contrib/gcc/prefix.c
+++ b/contrib/gcc/prefix.c
@@ -1,5 +1,5 @@
/* Utility to update paths from internal to external forms.
- Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -64,37 +64,41 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#ifdef _WIN32
#include <windows.h>
#endif
+#include "prefix.h"
-#include "gansidecl.h"
-
-static char *std_prefix = PREFIX;
+static const char *std_prefix = PREFIX;
-static char *get_key_value PROTO((char *));
-static char *translate_name PROTO((char *));
-static char *concat PVPROTO((char *, ...));
-static char *save_string PROTO((char *, int));
+static const char *get_key_value PROTO((char *));
+static const char *translate_name PROTO((const char *));
+static char *save_string PROTO((const char *, int));
#ifdef _WIN32
static char *lookup_key PROTO((char *));
static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE;
#endif
+#ifndef DIR_SEPARATOR
+# define IS_DIR_SEPARATOR(ch) ((ch) == '/')
+#else /* DIR_SEPARATOR */
+# ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+# else /* DIR_SEPARATOR && DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+# endif /* DIR_SEPARATOR && DIR_SEPARATOR_2 */
+#endif /* DIR_SEPARATOR */
+
/* Given KEY, as above, return its value. */
-static char *
+static const char *
get_key_value (key)
char *key;
{
- char *prefix = 0;
+ const char *prefix = 0;
char *temp = 0;
#ifdef _WIN32
@@ -117,23 +121,23 @@ get_key_value (key)
This function is based on the one in libiberty. */
-static char *
-concat VPROTO((char *first, ...))
+char *
+concat VPROTO((const char *first, ...))
{
register int length;
register char *newstr;
register char *end;
- register char *arg;
+ register const char *arg;
va_list args;
-#ifndef __STDC__
- char *first;
+#ifndef ANSI_PROTOTYPES
+ const char *first;
#endif
/* First compute the size of the result and get sufficient memory. */
VA_START (args, first);
-#ifndef __STDC__
- first = va_arg (args, char *);
+#ifndef ANSI_PROTOTYPES
+ first = va_arg (args, const char *);
#endif
arg = first;
@@ -142,7 +146,7 @@ concat VPROTO((char *first, ...))
while (arg != 0)
{
length += strlen (arg);
- arg = va_arg (args, char *);
+ arg = va_arg (args, const char *);
}
newstr = (char *) malloc (length + 1);
@@ -151,7 +155,7 @@ concat VPROTO((char *first, ...))
/* Now copy the individual pieces to the result string. */
VA_START (args, first);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
first = va_arg (args, char *);
#endif
@@ -161,7 +165,7 @@ concat VPROTO((char *first, ...))
{
while (*arg)
*end++ = *arg++;
- arg = va_arg (args, char *);
+ arg = va_arg (args, const char *);
}
*end = '\000';
va_end (args);
@@ -173,10 +177,10 @@ concat VPROTO((char *first, ...))
static char *
save_string (s, len)
- char *s;
- int len;
+ const char *s;
+ int len;
{
- register char *result = (char *) malloc (len + 1);
+ register char *result = xmalloc (len + 1);
bcopy (s, result, len);
result[len] = 0;
@@ -235,27 +239,24 @@ lookup_key (key)
/* If NAME starts with a '@' or '$', apply the translation rules above
and return a new name. Otherwise, return the given name. */
-static char *
+static const char *
translate_name (name)
- char *name;
+ const char *name;
{
char code = name[0];
- char *key, *prefix = 0;
+ char *key;
+ const char *prefix = 0;
int keylen;
if (code != '@' && code != '$')
return name;
for (keylen = 0;
- (name[keylen + 1] != 0 && name[keylen + 1] != '/'
-#ifdef DIR_SEPARATOR
- && name[keylen + 1] != DIR_SEPARATOR
-#endif
- );
+ (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1]));
keylen++)
;
- key = alloca (keylen + 1);
+ key = (char *) alloca (keylen + 1);
strncpy (key, &name[1], keylen);
key[keylen] = 0;
@@ -274,14 +275,11 @@ translate_name (name)
prefix = PREFIX;
/* Remove any trailing directory separator from what we got. */
- if (prefix[strlen (prefix) - 1] == '/'
-#ifdef DIR_SEPARATOR
- || prefix[strlen (prefix) - 1] == DIR_SEPARATOR
-#endif
- )
+ if (IS_DIR_SEPARATOR (prefix[strlen (prefix) - 1]))
{
- prefix = save_string (prefix, strlen (prefix));
- prefix[strlen (prefix) - 1] = 0;
+ char * temp = save_string (prefix, strlen (prefix));
+ temp[strlen (temp) - 1] = 0;
+ prefix = temp;
}
return concat (prefix, name, NULL_PTR);
@@ -289,10 +287,10 @@ translate_name (name)
/* Update PATH using KEY if PATH starts with PREFIX. */
-char *
+const char *
update_path (path, key)
- char *path;
- char *key;
+ const char *path;
+ const char *key;
{
if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0)
{
@@ -304,17 +302,33 @@ update_path (path, key)
while (path[0] == '@' || path[0] == '$')
path = translate_name (path);
}
+
+#ifdef DIR_SEPARATOR_2
+ /* Convert DIR_SEPARATOR_2 to DIR_SEPARATOR. */
+ if (DIR_SEPARATOR != DIR_SEPARATOR_2)
+ {
+ int i;
+ int len = strlen (path);
+ char *new_path = save_string (path, len);
+ for (i = 0; i < len; i++)
+ if (new_path[i] == DIR_SEPARATOR_2)
+ new_path[i] = DIR_SEPARATOR;
+ path = new_path;
+ }
+#endif
-#ifdef DIR_SEPARATOR
+#if defined (DIR_SEPARATOR) && !defined (DIR_SEPARATOR_2)
if (DIR_SEPARATOR != '/')
{
int i;
int len = strlen (path);
+ char *new_path = save_string (path, len);
- path = save_string (path, len);
for (i = 0; i < len; i++)
- if (path[i] == '/')
- path[i] = DIR_SEPARATOR;
+ if (new_path[i] == '/')
+ new_path[i] = DIR_SEPARATOR;
+
+ path = new_path;
}
#endif
@@ -324,8 +338,8 @@ update_path (path, key)
/* Reset the standard prefix */
void
set_std_prefix (prefix, len)
- char *prefix;
- int len;
+ const char *prefix;
+ int len;
{
std_prefix = save_string (prefix, len);
}
diff --git a/contrib/gcc/prefix.h b/contrib/gcc/prefix.h
new file mode 100644
index 0000000..b7c3648
--- /dev/null
+++ b/contrib/gcc/prefix.h
@@ -0,0 +1,28 @@
+/* Provide prototypes for functions exported from prefix.c.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#ifndef __GCC_PREFIX_H__
+#define __GCC_PREFIX_H__
+
+extern const char *update_path PARAMS ((const char *, const char *));
+extern void set_std_prefix PARAMS ((const char *, int));
+
+#endif /* ! __GCC_PREFIX_H__ */
diff --git a/contrib/gcc/print-rtl.c b/contrib/gcc/print-rtl.c
index 947a9b7..e097aad 100644
--- a/contrib/gcc/print-rtl.c
+++ b/contrib/gcc/print-rtl.c
@@ -1,5 +1,5 @@
/* Print RTL for GNU C Compiler.
- Copyright (C) 1987, 1988, 1992, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,8 +22,9 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "rtl.h"
-#include "bitmap.h"
#include "real.h"
+#include "flags.h"
+#include "basic-block.h"
/* How to print out a register name.
@@ -44,7 +45,7 @@ static char *reg_names[] = REGISTER_NAMES;
static FILE *outfile;
-char spaces[] = " ";
+static const char xspaces[] = " ";
static int sawclose = 0;
@@ -54,59 +55,93 @@ static int indent;
extern char **insn_name_ptr;
+static void print_rtx PROTO ((rtx));
+
+/* Nonzero means suppress output of instruction numbers and line number
+ notes in debugging dumps.
+ This must be defined here so that programs like gencodes can be linked. */
int flag_dump_unnumbered = 0;
+
+/* Nonzero if we are dumping graphical description. */
+int dump_for_graph;
+
/* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */
static void
print_rtx (in_rtx)
register rtx in_rtx;
{
- register int i, j;
+ register int i = 0;
+ register int j;
register char *format_ptr;
register int is_insn;
if (sawclose)
{
fprintf (outfile, "\n%s",
- (spaces + (sizeof spaces - 1 - indent * 2)));
+ (xspaces + (sizeof xspaces - 1 - indent * 2)));
sawclose = 0;
}
if (in_rtx == 0)
{
- fprintf (outfile, "(nil)");
+ fputs ("(nil)", outfile);
sawclose = 1;
return;
}
- /* print name of expression code */
- fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
+ is_insn = (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i');
- if (in_rtx->in_struct)
- fprintf (outfile, "/s");
+ /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER
+ in separate nodes and therefore have to handle them special here. */
+ if (dump_for_graph &&
+ (is_insn || GET_CODE (in_rtx) == NOTE || GET_CODE (in_rtx) == CODE_LABEL
+ || GET_CODE (in_rtx) == BARRIER))
+ {
+ i = 3;
+ indent = 0;
+ }
+ else
+ {
+ /* print name of expression code */
+ fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
- if (in_rtx->volatil)
- fprintf (outfile, "/v");
+ if (in_rtx->in_struct)
+ fputs ("/s", outfile);
- if (in_rtx->unchanging)
- fprintf (outfile, "/u");
+ if (in_rtx->volatil)
+ fputs ("/v", outfile);
- if (in_rtx->integrated)
- fprintf (outfile, "/i");
+ if (in_rtx->unchanging)
+ fputs ("/u", outfile);
- if (GET_MODE (in_rtx) != VOIDmode)
- {
- /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
- if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST)
- fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
- else
- fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
+ if (in_rtx->integrated)
+ fputs ("/i", outfile);
+
+ if (in_rtx->frame_related)
+ fputs ("/f", outfile);
+
+ if (in_rtx->jump)
+ fputs ("/j", outfile);
+
+ if (in_rtx->call)
+ fputs ("/c", outfile);
+
+ if (GET_MODE (in_rtx) != VOIDmode)
+ {
+ /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
+ if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST)
+ fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
+ else
+ fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
+ }
}
- is_insn = (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i');
- format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
+ /* Get the format string and skip the first elements if we have handled
+ them already. */
+ format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
+ for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
switch (*format_ptr++)
{
case 'S':
@@ -124,7 +159,8 @@ print_rtx (in_rtx)
if (i == 3 && GET_CODE (in_rtx) == NOTE
&& (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_RANGE_START
- || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_RANGE_END))
+ || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_RANGE_END
+ || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_LIVE))
{
indent += 2;
if (!sawclose)
@@ -135,19 +171,18 @@ print_rtx (in_rtx)
}
if (i == 3 && GET_CODE (in_rtx) == NOTE
- && NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_LIVE)
+ && NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_BASIC_BLOCK)
{
- if (XBITMAP (in_rtx, i) == NULL)
- fprintf (outfile, " {null}");
- else
- bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}");
- sawclose = 0;
+ basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
+ fprintf (outfile, " [bb %d]", bb->index);
+ break;
}
if (XSTR (in_rtx, i) == 0)
- fprintf (outfile, " \"\"");
+ fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
else
- fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i));
+ fprintf (outfile, dump_for_graph ? " (\\\"%s\\\")" : " (\"%s\")",
+ XSTR (in_rtx, i));
sawclose = 1;
break;
@@ -169,10 +204,10 @@ print_rtx (in_rtx)
if (sawclose)
{
fprintf (outfile, "\n%s",
- (spaces + (sizeof spaces - 1 - indent * 2)));
+ (xspaces + (sizeof xspaces - 1 - indent * 2)));
sawclose = 0;
}
- fprintf (outfile, "[ ");
+ fputs ("[ ", outfile);
if (NULL != XVEC (in_rtx, i))
{
indent += 2;
@@ -186,9 +221,9 @@ print_rtx (in_rtx)
}
if (sawclose)
fprintf (outfile, "\n%s",
- (spaces + (sizeof spaces - 1 - indent * 2)));
+ (xspaces + (sizeof xspaces - 1 - indent * 2)));
- fprintf (outfile, "] ");
+ fputs ("] ", outfile);
sawclose = 1;
indent -= 2;
break;
@@ -196,6 +231,9 @@ print_rtx (in_rtx)
case 'w':
fprintf (outfile, " ");
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i));
+ fprintf (outfile, " [");
+ fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, XWINT (in_rtx, i));
+ fprintf (outfile, "]");
break;
case 'i':
@@ -209,7 +247,7 @@ print_rtx (in_rtx)
}
else if (flag_dump_unnumbered
&& (is_insn || GET_CODE (in_rtx) == NOTE))
- fprintf (outfile, "#");
+ fputc ('#', outfile);
else
fprintf (outfile, " %d", value);
}
@@ -234,18 +272,18 @@ print_rtx (in_rtx)
if (XEXP (in_rtx, i) != NULL)
{
if (flag_dump_unnumbered)
- fprintf (outfile, "#");
+ fputc ('#', outfile);
else
fprintf (outfile, " %d", INSN_UID (XEXP (in_rtx, i)));
}
else
- fprintf (outfile, " 0");
+ fputs (" 0", outfile);
sawclose = 0;
break;
case 'b':
if (XBITMAP (in_rtx, i) == NULL)
- fprintf (outfile, " {null}");
+ fputs (" {null}", outfile);
else
bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}");
sawclose = 0;
@@ -257,7 +295,7 @@ print_rtx (in_rtx)
break;
case '*':
- fprintf (outfile, " Unknown");
+ fputs (" Unknown", outfile);
sawclose = 0;
break;
@@ -268,6 +306,9 @@ print_rtx (in_rtx)
abort ();
}
+ if (GET_CODE (in_rtx) == MEM)
+ fprintf (outfile, " %d", MEM_ALIAS_SET (in_rtx));
+
#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && LONG_DOUBLE_TYPE_SIZE == 64
if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx)))
{
@@ -277,8 +318,18 @@ print_rtx (in_rtx)
}
#endif
- fprintf (outfile, ")");
- sawclose = 1;
+ if (GET_CODE (in_rtx) == CODE_LABEL)
+ fprintf (outfile, " [num uses: %d]", LABEL_NUSES (in_rtx));
+
+ if (dump_for_graph
+ && (is_insn || GET_CODE (in_rtx) == NOTE
+ || GET_CODE (in_rtx) == CODE_LABEL || GET_CODE (in_rtx) == BARRIER))
+ sawclose = 0;
+ else
+ {
+ fputc (')', outfile);
+ sawclose = 1;
+ }
}
/* Print an rtx on the current line of FILE. Initially indent IND
@@ -387,7 +438,7 @@ print_rtl (outf, rtx_first)
sawclose = 0;
if (rtx_first == 0)
- fprintf (outf, "(nil)\n");
+ fputs ("(nil)\n", outf);
else
switch (GET_CODE (rtx_first))
{
@@ -415,8 +466,9 @@ print_rtl (outf, rtx_first)
}
/* Like print_rtx, except specify a file. */
+/* Return nonzero if we actually printed anything. */
-void
+int
print_rtl_single (outf, x)
FILE *outf;
rtx x;
@@ -428,5 +480,7 @@ print_rtl_single (outf, x)
{
print_rtx (x);
putc ('\n', outf);
+ return 1;
}
+ return 0;
}
diff --git a/contrib/gcc/print-tree.c b/contrib/gcc/print-tree.c
index 6163b1f..18ec929 100644
--- a/contrib/gcc/print-tree.c
+++ b/contrib/gcc/print-tree.c
@@ -1,5 +1,5 @@
/* Prints out tree in human readable form - GNU C-compiler
- Copyright (C) 1990, 91, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91, 93-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -64,7 +64,7 @@ debug_tree (node)
void
print_node_brief (file, prefix, node, indent)
FILE *file;
- char *prefix;
+ const char *prefix;
tree node;
int indent;
{
@@ -176,7 +176,7 @@ indent_to (file, column)
void
print_node (file, prefix, node, indent)
FILE *file;
- char *prefix;
+ const char *prefix;
tree node;
int indent;
{
@@ -404,6 +404,8 @@ print_node (file, prefix, node, indent)
fprintf (file, " built-in code %d", DECL_FUNCTION_CODE (node));
if (TREE_CODE (node) == FIELD_DECL)
print_node (file, "bitpos", DECL_FIELD_BITPOS (node), indent + 4);
+ if (DECL_POINTER_ALIAS_SET_KNOWN_P (node))
+ fprintf (file, " alias set %d", DECL_POINTER_ALIAS_SET (node));
print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
print_node_brief (file, "machine_attributes", DECL_MACHINE_ATTRIBUTES (node), indent + 4);
print_node_brief (file, "abstract_origin",
@@ -532,7 +534,7 @@ print_node (file, prefix, node, indent)
print_node (file, "chain", BLOCK_CHAIN (node), indent + 4);
print_node (file, "abstract_origin",
BLOCK_ABSTRACT_ORIGIN (node), indent + 4);
- return;
+ break;
case 'e':
case '<':
@@ -545,7 +547,7 @@ print_node (file, prefix, node, indent)
print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4);
print_node (file, "body", TREE_OPERAND (node, 1), indent + 4);
print_node (file, "block", TREE_OPERAND (node, 2), indent + 4);
- return;
+ break;
}
len = tree_code_length[(int) TREE_CODE (node)];
diff --git a/contrib/gcc/profile.c b/contrib/gcc/profile.c
index b06f91b..17923c5 100644
--- a/contrib/gcc/profile.c
+++ b/contrib/gcc/profile.c
@@ -1,5 +1,5 @@
/* Calculate branch probabilities, and basic block execution counts.
- Copyright (C) 1990, 91-94, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91-94, 96-98, 1999 Free Software Foundation, Inc.
Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
based on some ideas from Dain Samples of UC Berkeley.
Further mangling by Bob Manson, Cygnus Support.
@@ -18,7 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* ??? Really should not put insns inside of LIBCALL sequences, when putting
insns after a call, should look for the insn setting the retval, and
@@ -53,8 +54,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "gcov-io.h"
#include "toplev.h"
-extern char * xmalloc ();
-
/* One of these is dynamically created whenever we identify an arc in the
function. */
@@ -1408,7 +1407,7 @@ expand_spanning_tree (block)
void
init_branch_prob (filename)
- char *filename;
+ const char *filename;
{
long len;
int i;
@@ -1668,7 +1667,13 @@ output_func_start_profiler ()
TREE_PUBLIC (fndecl) = 1;
DECL_ASSEMBLER_NAME (fndecl) = fnname;
DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+
+ fndecl = pushdecl (fndecl);
+ rest_of_decl_compilation (fndecl, 0, 1, 0);
+ announce_function (fndecl);
current_function_decl = fndecl;
+ DECL_INITIAL (fndecl) = error_mark_node;
+ temporary_allocation ();
pushlevel (0);
make_function_rtl (fndecl);
init_function_start (fndecl, input_filename, lineno);
diff --git a/contrib/gcc/protoize.c b/contrib/gcc/protoize.c
index 48908e5..7e9205c 100644
--- a/contrib/gcc/protoize.c
+++ b/contrib/gcc/protoize.c
@@ -1,5 +1,5 @@
/* Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
- Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -57,14 +57,11 @@ Boston, MA 02111-1307, USA. */
#define _POSIX_SOURCE
#endif
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
-#include <sys/stat.h>
-#if ! defined (_WIN32) || defined (__CYGWIN32__)
+#include "intl.h"
+#undef abort
+
+#if ! defined (_WIN32) || defined (__CYGWIN__) || defined (_UWIN)
#if defined(POSIX) || defined(CONCURRENT)
#include <dirent.h>
#else
@@ -72,7 +69,6 @@ Boston, MA 02111-1307, USA. */
#endif
#endif
#include <setjmp.h>
-#include "gansidecl.h"
/* Some systems like Linux don't declare rindex if _POSIX_SOURCE is declared,
but it normally does declare it. This means that configure thinks we don't
@@ -115,49 +111,23 @@ extern char *version_string;
extern char *getpwd ();
-extern char *choose_temp_base PROTO ((void));
-extern char * my_strerror PROTO ((int));
-
-extern int pexecute PROTO ((const char *, char * const *, const char *,
- const char *, char **, char **, int));
-extern int pwait PROTO ((int, int *, int));
-/* Flag arguments to pexecute. */
-#define PEXECUTE_FIRST 1
-#define PEXECUTE_LAST 2
-#define PEXECUTE_SEARCH 4
+static void usage PROTO ((void)) ATTRIBUTE_NORETURN;
+static void aux_info_corrupted PROTO ((void)) ATTRIBUTE_NORETURN;
+static void declare_source_confusing PROTO ((const char *)) ATTRIBUTE_NORETURN;
/* Aliases for pointers to void.
These were made to facilitate compilation with old brain-dead DEC C
compilers which didn't properly grok `void*' types. */
-#ifdef __STDC__
-typedef void * pointer_type;
-typedef const void * const_pointer_type;
-#else
-typedef char * pointer_type;
-typedef char * const_pointer_type;
-#endif
+typedef PTR pointer_type;
+typedef const PTR const_pointer_type;
#if defined(POSIX)
#include <signal.h>
-#include <sys/wait.h>
#else /* !defined(POSIX) */
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(S) ((S) & 0x7f)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(S) (((S) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
-#endif
-
/* Declaring stat or __flsbuf with a prototype
causes conflicts with system headers on some systems. */
@@ -173,8 +143,12 @@ extern int close ();
extern int fflush ();
extern int atoi ();
extern int puts ();
+#ifndef fputs /* This may have been #defined by "system.h". */
extern int fputs ();
+#endif
+#ifndef fputc /* some systems define this as a macro. */
extern int fputc ();
+#endif
extern int unlink ();
extern int access ();
@@ -183,12 +157,6 @@ extern int access ();
extern size_t strlen ()
#endif
-/* Fork is not declared because the declaration caused a conflict
- on the HPPA. */
-#if !(defined (USG) || defined (VMS))
-#define fork vfork
-#endif /* (defined (USG) || defined (VMS)) */
-
#endif /* !defined (POSIX) */
/* Look for these where the `const' qualifier is intentionally cast aside. */
@@ -600,25 +568,44 @@ static char * saved_repl_write_ptr;
static const char *shortpath ();
+/* Translate and output an error message. */
+static void notice PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
+static void
+notice VPROTO ((const char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+#endif
+
+ vfprintf (stderr, _(msgid), ap);
+ va_end (ap);
+}
+
+
char *
-my_strerror(e)
- int e;
+xstrerror(e)
+ int e;
{
#ifdef HAVE_STRERROR
return strerror(e);
#else
-
- static char buffer[30];
if (!e)
return "";
if (e > 0 && e < sys_nerr)
return sys_errlist[e];
- sprintf (buffer, "Unknown error %d", e);
- return buffer;
+ return "errno = ?";
#endif
}
@@ -627,19 +614,15 @@ my_strerror(e)
pointer_type
xmalloc (byte_count)
- size_t byte_count;
+ size_t byte_count;
{
- pointer_type rv;
-
- rv = (pointer_type) malloc (byte_count);
+ register pointer_type rv = (pointer_type) malloc (byte_count);
if (rv == NULL)
{
- fprintf (stderr, "\n%s: virtual memory exceeded\n", pname);
+ notice ("\n%s: virtual memory exceeded\n", pname);
exit (FATAL_EXIT_CODE);
- return 0; /* avoid warnings */
}
- else
- return rv;
+ return rv;
}
/* Reallocate some space, but check that the reallocation was successful. */
@@ -649,17 +632,17 @@ xrealloc (old_space, byte_count)
pointer_type old_space;
size_t byte_count;
{
- pointer_type rv;
-
- rv = (pointer_type) realloc (old_space, byte_count);
+ register pointer_type rv;
+ if (old_space)
+ rv = (pointer_type) realloc (old_space, byte_count);
+ else
+ rv = (pointer_type) malloc (byte_count);
if (rv == NULL)
{
- fprintf (stderr, "\n%s: virtual memory exceeded\n", pname);
+ notice ("\n%s: virtual memory exceeded\n", pname);
exit (FATAL_EXIT_CODE);
- return 0; /* avoid warnings */
}
- else
- return rv;
+ return rv;
}
/* Deallocate the area pointed to by an arbitrary pointer, but first, strip
@@ -707,7 +690,7 @@ savestring2 (input1, size1, input2, size2)
void
fancy_abort ()
{
- fprintf (stderr, "%s: internal abort\n", pname);
+ notice ("%s: internal abort\n", pname);
exit (FATAL_EXIT_CODE);
}
@@ -797,8 +780,8 @@ safe_write (desc, ptr, len, out_fname)
if (errno_val == EINTR)
continue;
#endif
- fprintf (stderr, "%s: error writing file `%s': %s\n",
- pname, shortpath (NULL, out_fname), my_strerror (errno_val));
+ notice ("%s: error writing file `%s': %s\n",
+ pname, shortpath (NULL, out_fname), xstrerror (errno_val));
return;
}
ptr += written;
@@ -829,7 +812,7 @@ restore_pointers ()
static int
is_id_char (ch)
- char ch;
+ unsigned char ch;
{
return (ISALNUM (ch) || (ch == '_') || (ch == '$'));
}
@@ -841,11 +824,11 @@ static void
usage ()
{
#ifdef UNPROTOIZE
- fprintf (stderr, "%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
- pname, pname);
+ notice ("%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
+ pname, pname);
#else /* !defined (UNPROTOIZE) */
- fprintf (stderr, "%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
- pname, pname);
+ notice ("%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
+ pname, pname);
#endif /* !defined (UNPROTOIZE) */
exit (FATAL_EXIT_CODE);
}
@@ -931,24 +914,24 @@ file_normally_convertible (const char *path)
if (my_access (path, R_OK))
{
if (!quiet_flag)
- fprintf (stderr, "%s: warning: no read access for file `%s'\n",
- pname, shortpath (NULL, path));
+ notice ("%s: warning: no read access for file `%s'\n",
+ pname, shortpath (NULL, path));
return 0;
}
if (my_access (path, W_OK))
{
if (!quiet_flag)
- fprintf (stderr, "%s: warning: no write access for file `%s'\n",
- pname, shortpath (NULL, path));
+ notice ("%s: warning: no write access for file `%s'\n",
+ pname, shortpath (NULL, path));
return 0;
}
if (my_access (dir_name, W_OK))
{
if (!quiet_flag)
- fprintf (stderr, "%s: warning: no write access for dir containing `%s'\n",
- pname, shortpath (NULL, path));
+ notice ("%s: warning: no write access for dir containing `%s'\n",
+ pname, shortpath (NULL, path));
return 0;
}
@@ -1305,7 +1288,7 @@ abspath (cwd, rel_filename)
outp = inp = abs_buffer;
*outp++ = *inp++; /* copy first slash */
-#ifdef apollo
+#if defined (apollo) || defined (_WIN32) || defined (__INTERIX)
if (inp[0] == '/')
*outp++ = *inp++; /* copy second slash */
#endif
@@ -1339,8 +1322,8 @@ abspath (cwd, rel_filename)
point above the absolute root of the logical file
system. */
- fprintf (stderr, "%s: invalid file name: %s\n",
- pname, rel_filename);
+ notice ("%s: invalid file name: %s\n",
+ pname, rel_filename);
exit (FATAL_EXIT_CODE);
}
*++outp = '\0';
@@ -1490,9 +1473,9 @@ find_file (filename, do_not_stat)
if (my_stat (filename, &stat_buf) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: %s: can't get status: %s\n",
- pname, shortpath (NULL, filename),
- my_strerror (errno_val));
+ notice ("%s: %s: can't get status: %s\n",
+ pname, shortpath (NULL, filename),
+ xstrerror (errno_val));
stat_buf.st_mtime = (time_t) -1;
}
}
@@ -1511,8 +1494,8 @@ find_file (filename, do_not_stat)
static void
aux_info_corrupted ()
{
- fprintf (stderr, "\n%s: fatal error: aux info file corrupted at line %d\n",
- pname, current_aux_info_lineno);
+ notice ("\n%s: fatal error: aux info file corrupted at line %d\n",
+ pname, current_aux_info_lineno);
exit (FATAL_EXIT_CODE);
}
@@ -1835,10 +1818,10 @@ save_def_or_dec (l, is_syscalls)
{
if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
{
- fprintf (stderr, "%s:%d: declaration of function `%s' takes different forms\n",
- def_dec_p->file->hash_entry->symbol,
- def_dec_p->line,
- def_dec_p->hash_entry->symbol);
+ notice ("%s:%d: declaration of function `%s' takes different forms\n",
+ def_dec_p->file->hash_entry->symbol,
+ def_dec_p->line,
+ def_dec_p->hash_entry->symbol);
exit (FATAL_EXIT_CODE);
}
free_def_dec (def_dec_p);
@@ -2007,12 +1990,12 @@ munge_compile_params (params_list)
temp_params[param_count++] = compiler_file_name;
for (;;)
{
- while (ISSPACE (*params_list))
+ while (ISSPACE ((const unsigned char)*params_list))
params_list++;
if (!*params_list)
break;
param = params_list;
- while (*params_list && !ISSPACE (*params_list))
+ while (*params_list && !ISSPACE ((const unsigned char)*params_list))
params_list++;
if (param[0] != '-')
temp_params[param_count++]
@@ -2027,9 +2010,10 @@ munge_compile_params (params_list)
case 'c':
break; /* Don't copy these. */
case 'o':
- while (ISSPACE (*params_list))
+ while (ISSPACE ((const unsigned char)*params_list))
params_list++;
- while (*params_list && !ISSPACE (*params_list))
+ while (*params_list
+ && !ISSPACE ((const unsigned char)*params_list))
params_list++;
break;
default:
@@ -2085,8 +2069,8 @@ gen_aux_info_file (base_filename)
2);
if (!quiet_flag)
- fprintf (stderr, "%s: compiling `%s'\n",
- pname, compile_params[input_file_name_index]);
+ notice ("%s: compiling `%s'\n",
+ pname, compile_params[input_file_name_index]);
{
char *errmsg_fmt, *errmsg_arg;
@@ -2102,28 +2086,28 @@ gen_aux_info_file (base_filename)
int errno_val = errno;
fprintf (stderr, "%s: ", pname);
fprintf (stderr, errmsg_fmt, errmsg_arg);
- fprintf (stderr, ": %s\n", my_strerror (errno_val));
+ fprintf (stderr, ": %s\n", xstrerror (errno_val));
return 0;
}
pid = pwait (pid, &wait_status, 0);
if (pid == -1)
{
- fprintf (stderr, "%s: wait: %s\n", pname, my_strerror (errno));
+ notice ("%s: wait: %s\n", pname, xstrerror (errno));
return 0;
}
if (WIFSIGNALED (wait_status))
{
- fprintf (stderr, "%s: subprocess got fatal signal %d\n",
- pname, WTERMSIG (wait_status));
+ notice ("%s: subprocess got fatal signal %d\n",
+ pname, WTERMSIG (wait_status));
return 0;
}
if (WIFEXITED (wait_status))
{
if (WEXITSTATUS (wait_status) != 0)
{
- fprintf (stderr, "%s: %s exited with status %d\n",
- pname, compile_params[0], WEXITSTATUS (wait_status));
+ notice ("%s: %s exited with status %d\n",
+ pname, compile_params[0], WEXITSTATUS (wait_status));
return 0;
}
return 1;
@@ -2174,8 +2158,8 @@ start_over: ;
{
if (is_syscalls)
{
- fprintf (stderr, "%s: warning: missing SYSCALLS file `%s'\n",
- pname, aux_info_filename);
+ notice ("%s: warning: missing SYSCALLS file `%s'\n",
+ pname, aux_info_filename);
return;
}
must_create = 1;
@@ -2183,9 +2167,9 @@ start_over: ;
else
{
int errno_val = errno;
- fprintf (stderr, "%s: can't read aux info file `%s': %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: can't read aux info file `%s': %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
errors++;
return;
}
@@ -2212,9 +2196,9 @@ start_over: ;
if (my_access (aux_info_filename, R_OK) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't read aux info file `%s': %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: can't read aux info file `%s': %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
errors++;
return;
}
@@ -2228,9 +2212,9 @@ start_over: ;
if (my_stat (aux_info_filename, &stat_buf) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't get status of aux info file `%s': %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: can't get status of aux info file `%s': %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
errors++;
return;
}
@@ -2256,9 +2240,9 @@ start_over: ;
if (my_stat (base_source_filename, &stat_buf) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't get status of aux info file `%s': %s\n",
- pname, shortpath (NULL, base_source_filename),
- my_strerror (errno_val));
+ notice ("%s: can't get status of aux info file `%s': %s\n",
+ pname, shortpath (NULL, base_source_filename),
+ xstrerror (errno_val));
errors++;
return;
}
@@ -2278,9 +2262,9 @@ start_over: ;
if ((aux_info_file = my_open (aux_info_filename, O_RDONLY, 0444 )) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't open aux info file `%s' for reading: %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: can't open aux info file `%s' for reading: %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
return;
}
@@ -2292,12 +2276,13 @@ start_over: ;
/* Read the aux_info file into memory. */
- if (safe_read (aux_info_file, aux_info_base, aux_info_size) != aux_info_size)
+ if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
+ (int) aux_info_size)
{
int errno_val = errno;
- fprintf (stderr, "%s: error reading aux info file `%s': %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: error reading aux info file `%s': %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
free (aux_info_base);
close (aux_info_file);
return;
@@ -2308,9 +2293,9 @@ start_over: ;
if (close (aux_info_file))
{
int errno_val = errno;
- fprintf (stderr, "%s: error closing aux info file `%s': %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: error closing aux info file `%s': %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
free (aux_info_base);
close (aux_info_file);
return;
@@ -2324,9 +2309,9 @@ start_over: ;
if (my_unlink (aux_info_filename) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't delete aux info file `%s': %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: can't delete aux info file `%s': %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
}
/* Save a pointer into the first line of the aux_info file which
@@ -2392,9 +2377,9 @@ start_over: ;
if (keep_it && my_unlink (aux_info_filename) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't delete file `%s': %s\n",
- pname, shortpath (NULL, aux_info_filename),
- my_strerror (errno_val));
+ notice ("%s: can't delete file `%s': %s\n",
+ pname, shortpath (NULL, aux_info_filename),
+ xstrerror (errno_val));
return;
}
must_create = 1;
@@ -2469,9 +2454,9 @@ rename_c_file (hp)
if (my_link (filename, new_filename) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: warning: can't link file `%s' to `%s': %s\n",
- pname, shortpath (NULL, filename),
- shortpath (NULL, new_filename), my_strerror (errno_val));
+ notice ("%s: warning: can't link file `%s' to `%s': %s\n",
+ pname, shortpath (NULL, filename),
+ shortpath (NULL, new_filename), xstrerror (errno_val));
errors++;
return;
}
@@ -2479,8 +2464,8 @@ rename_c_file (hp)
if (my_unlink (filename) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: warning: can't delete file `%s': %s\n",
- pname, shortpath (NULL, filename), my_strerror (errno_val));
+ notice ("%s: warning: can't delete file `%s': %s\n",
+ pname, shortpath (NULL, filename), xstrerror (errno_val));
errors++;
return;
}
@@ -2603,14 +2588,14 @@ find_extern_def (head, user)
if (!conflict_noted) /* first time we noticed? */
{
conflict_noted = 1;
- fprintf (stderr, "%s: conflicting extern definitions of '%s'\n",
- pname, head->hash_entry->symbol);
+ notice ("%s: conflicting extern definitions of '%s'\n",
+ pname, head->hash_entry->symbol);
if (!quiet_flag)
{
- fprintf (stderr, "%s: declarations of '%s' will not be converted\n",
- pname, head->hash_entry->symbol);
- fprintf (stderr, "%s: conflict list for '%s' follows:\n",
- pname, head->hash_entry->symbol);
+ notice ("%s: declarations of '%s' will not be converted\n",
+ pname, head->hash_entry->symbol);
+ notice ("%s: conflict list for '%s' follows:\n",
+ pname, head->hash_entry->symbol);
fprintf (stderr, "%s: %s(%d): %s\n",
pname,
shortpath (NULL, extern_def_p->file->hash_entry->symbol),
@@ -2642,10 +2627,10 @@ find_extern_def (head, user)
{
extern_def_p = dd_p; /* save a pointer to the definition */
if (!quiet_flag)
- fprintf (stderr, "%s: warning: using formals list from %s(%d) for function `%s'\n",
- pname,
- shortpath (NULL, dd_p->file->hash_entry->symbol),
- dd_p->line, dd_p->hash_entry->symbol);
+ notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
+ pname,
+ shortpath (NULL, dd_p->file->hash_entry->symbol),
+ dd_p->line, dd_p->hash_entry->symbol);
break;
}
@@ -2682,15 +2667,15 @@ find_extern_def (head, user)
*p++ = '?';
strcpy (p, ");");
- fprintf (stderr, "%s: %d: `%s' used but missing from SYSCALLS\n",
- shortpath (NULL, file), user->line,
- needed+7); /* Don't print "extern " */
+ notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
+ shortpath (NULL, file), user->line,
+ needed+7); /* Don't print "extern " */
}
#if 0
else
- fprintf (stderr, "%s: %d: warning: no extern definition for `%s'\n",
- shortpath (NULL, file), user->line,
- user->hash_entry->symbol);
+ notice ("%s: %d: warning: no extern definition for `%s'\n",
+ shortpath (NULL, file), user->line,
+ user->hash_entry->symbol);
#endif
}
}
@@ -2719,15 +2704,15 @@ find_static_definition (user)
if (num_static_defs == 0)
{
if (!quiet_flag)
- fprintf (stderr, "%s: warning: no static definition for `%s' in file `%s'\n",
- pname, head->hash_entry->symbol,
- shortpath (NULL, user->file->hash_entry->symbol));
+ notice ("%s: warning: no static definition for `%s' in file `%s'\n",
+ pname, head->hash_entry->symbol,
+ shortpath (NULL, user->file->hash_entry->symbol));
}
else if (num_static_defs > 1)
{
- fprintf (stderr, "%s: multiple static defs of `%s' in file `%s'\n",
- pname, head->hash_entry->symbol,
- shortpath (NULL, user->file->hash_entry->symbol));
+ notice ("%s: multiple static defs of `%s' in file `%s'\n",
+ pname, head->hash_entry->symbol,
+ shortpath (NULL, user->file->hash_entry->symbol));
return NULL;
}
return static_def_p;
@@ -2898,12 +2883,12 @@ declare_source_confusing (clean_p)
if (!quiet_flag)
{
if (clean_p == 0)
- fprintf (stderr, "%s: %d: warning: source too confusing\n",
- shortpath (NULL, convert_filename), last_known_line_number);
+ notice ("%s: %d: warning: source too confusing\n",
+ shortpath (NULL, convert_filename), last_known_line_number);
else
- fprintf (stderr, "%s: %d: warning: source too confusing\n",
- shortpath (NULL, convert_filename),
- identify_lineno (clean_p));
+ notice ("%s: %d: warning: source too confusing\n",
+ shortpath (NULL, convert_filename),
+ identify_lineno (clean_p));
}
longjmp (source_confusion_recovery, 1);
}
@@ -2960,7 +2945,8 @@ static const char *
forward_to_next_token_char (ptr)
const char *ptr;
{
- for (++ptr; ISSPACE (*ptr); check_source (++ptr < clean_text_limit, 0))
+ for (++ptr; ISSPACE ((const unsigned char)*ptr);
+ check_source (++ptr < clean_text_limit, 0))
continue;
return ptr;
}
@@ -3106,9 +3092,9 @@ edit_fn_declaration (def_dec_p, clean_text_p)
if (other_variable_style_function (definition->ansi_decl))
{
if (!quiet_flag)
- fprintf (stderr, "%s: %d: warning: varargs function declaration not converted\n",
- shortpath (NULL, def_dec_p->file->hash_entry->symbol),
- def_dec_p->line);
+ notice ("%s: %d: warning: varargs function declaration not converted\n",
+ shortpath (NULL, def_dec_p->file->hash_entry->symbol),
+ def_dec_p->line);
return;
}
@@ -3121,8 +3107,8 @@ edit_fn_declaration (def_dec_p, clean_text_p)
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
- fprintf (stderr, "%s: declaration of function `%s' not converted\n",
- pname, function_to_edit);
+ notice ("%s: declaration of function `%s' not converted\n",
+ pname, function_to_edit);
return;
}
@@ -3244,8 +3230,8 @@ edit_fn_declaration (def_dec_p, clean_text_p)
else
{
if (!quiet_flag)
- fprintf (stderr, "%s: warning: too many parameter lists in declaration of `%s'\n",
- pname, def_dec_p->hash_entry->symbol);
+ notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
+ pname, def_dec_p->hash_entry->symbol);
check_source (0, end_formals); /* leave the declaration intact */
}
#endif /* !defined (UNPROTOIZE) */
@@ -3265,8 +3251,8 @@ edit_fn_declaration (def_dec_p, clean_text_p)
if (this_f_list_chain_item)
{
if (!quiet_flag)
- fprintf (stderr, "\n%s: warning: too few parameter lists in declaration of `%s'\n",
- pname, def_dec_p->hash_entry->symbol);
+ notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
+ pname, def_dec_p->hash_entry->symbol);
check_source (0, start_formals); /* leave the decl intact */
}
#endif /* !defined (UNPROTOIZE) */
@@ -3328,7 +3314,7 @@ edit_formals_lists (end_formals, f_list_count, def_dec_p)
next_end = start_formals - 1;
check_source (next_end > clean_read_ptr, 0);
- while (ISSPACE (*next_end))
+ while (ISSPACE ((const unsigned char)*next_end))
check_source (--next_end > clean_read_ptr, 0);
check_source (*next_end == ')', next_end);
check_source (--next_end > clean_read_ptr, 0);
@@ -3348,7 +3334,8 @@ edit_formals_lists (end_formals, f_list_count, def_dec_p)
const char *func_name_limit;
size_t func_name_len;
- for (func_name_limit = start_formals-1; ISSPACE (*func_name_limit); )
+ for (func_name_limit = start_formals-1;
+ ISSPACE ((const unsigned char)*func_name_limit); )
check_source (--func_name_limit > clean_read_ptr, 0);
for (func_name_start = func_name_limit++;
@@ -3362,11 +3349,11 @@ edit_formals_lists (end_formals, f_list_count, def_dec_p)
if (func_name_len != strlen (expected)
|| strncmp (func_name_start, expected, func_name_len))
{
- fprintf (stderr, "%s: %d: warning: found `%s' but expected `%s'\n",
- shortpath (NULL, def_dec_p->file->hash_entry->symbol),
- identify_lineno (func_name_start),
- dupnstr (func_name_start, func_name_len),
- expected);
+ notice ("%s: %d: warning: found `%s' but expected `%s'\n",
+ shortpath (NULL, def_dec_p->file->hash_entry->symbol),
+ identify_lineno (func_name_start),
+ dupnstr (func_name_start, func_name_len),
+ expected);
return 1;
}
}
@@ -3444,8 +3431,8 @@ find_rightmost_formals_list (clean_text_p)
while (*end_formals != ')')
{
- if (ISSPACE (*end_formals))
- while (ISSPACE (*end_formals))
+ if (ISSPACE ((unsigned char)*end_formals))
+ while (ISSPACE ((unsigned char)*end_formals))
check_source (--end_formals > clean_read_ptr, 0);
else
check_source (--end_formals > clean_read_ptr, 0);
@@ -3474,8 +3461,8 @@ find_rightmost_formals_list (clean_text_p)
while (*end_formals != ')')
{
- if (ISSPACE (*end_formals))
- while (ISSPACE (*end_formals))
+ if (ISSPACE ((const unsigned char)*end_formals))
+ while (ISSPACE ((const unsigned char)*end_formals))
check_source (--end_formals > clean_read_ptr, 0);
else
check_source (--end_formals > clean_read_ptr, 0);
@@ -3493,7 +3480,7 @@ find_rightmost_formals_list (clean_text_p)
by an alphabetic character, while others *cannot* validly be followed
by such characters. */
- if ((ch == '{') || ISALPHA (ch))
+ if ((ch == '{') || ISALPHA ((unsigned char)ch))
break;
/* At this point, we have found a right paren, but we know that it is
@@ -3540,8 +3527,8 @@ add_local_decl (def_dec_p, clean_text_p)
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
- fprintf (stderr, "%s: local declaration for function `%s' not inserted\n",
- pname, function_to_edit);
+ notice ("%s: local declaration for function `%s' not inserted\n",
+ pname, function_to_edit);
return;
}
@@ -3567,8 +3554,7 @@ add_local_decl (def_dec_p, clean_text_p)
if (*start_of_block != '{')
{
if (!quiet_flag)
- fprintf (stderr,
- "\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
+ notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
def_dec_p->file->hash_entry->symbol, def_dec_p->line,
def_dec_p->hash_entry->symbol);
return;
@@ -3589,7 +3575,7 @@ add_local_decl (def_dec_p, clean_text_p)
We can now just scan backwards and find the left end of the existing
indentation string, and then copy it to the output buffer. */
- for (sp = ep; ISSPACE (*sp) && *sp != '\n'; sp--)
+ for (sp = ep; ISSPACE ((const unsigned char)*sp) && *sp != '\n'; sp--)
continue;
/* Now write out the open { which began this block, and any following
@@ -3642,8 +3628,8 @@ add_global_decls (file_p, clean_text_p)
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
- fprintf (stderr, "%s: global declarations for file `%s' not inserted\n",
- pname, shortpath (NULL, file_p->hash_entry->symbol));
+ notice ("%s: global declarations for file `%s' not inserted\n",
+ pname, shortpath (NULL, file_p->hash_entry->symbol));
return;
}
@@ -3670,7 +3656,7 @@ add_global_decls (file_p, clean_text_p)
header. We will put in the added declarations just prior to that. */
scan_p++;
- while (ISSPACE (*scan_p))
+ while (ISSPACE ((const unsigned char)*scan_p))
scan_p++;
scan_p--;
@@ -3733,8 +3719,8 @@ edit_fn_definition (def_dec_p, clean_text_p)
if (setjmp (source_confusion_recovery))
{
restore_pointers ();
- fprintf (stderr, "%s: definition of function `%s' not converted\n",
- pname, function_to_edit);
+ notice ("%s: definition of function `%s' not converted\n",
+ pname, function_to_edit);
return;
}
@@ -3752,10 +3738,10 @@ edit_fn_definition (def_dec_p, clean_text_p)
if (other_variable_style_function (def_dec_p->ansi_decl))
{
if (!quiet_flag)
- fprintf (stderr, "%s: %d: warning: definition of %s not converted\n",
- shortpath (NULL, def_dec_p->file->hash_entry->symbol),
- identify_lineno (end_formals),
- other_var_style);
+ notice ("%s: %d: warning: definition of %s not converted\n",
+ shortpath (NULL, def_dec_p->file->hash_entry->symbol),
+ identify_lineno (end_formals),
+ other_var_style);
output_up_to (end_formals);
return;
}
@@ -3763,8 +3749,8 @@ edit_fn_definition (def_dec_p, clean_text_p)
if (edit_formals_lists (end_formals, def_dec_p->f_list_count, def_dec_p))
{
restore_pointers ();
- fprintf (stderr, "%s: definition of function `%s' not converted\n",
- pname, function_to_edit);
+ notice ("%s: definition of function `%s' not converted\n",
+ pname, function_to_edit);
return;
}
@@ -3839,7 +3825,7 @@ edit_fn_definition (def_dec_p, clean_text_p)
{
have_newlines |= (*scan_orig == '\n');
/* Leave identical whitespace alone. */
- if (!ISSPACE (*scan_orig))
+ if (!ISSPACE ((const unsigned char)*scan_orig))
*((NONCONST char *)scan_orig) = ' '; /* identical - so whiteout */
}
else
@@ -3883,7 +3869,7 @@ do_cleaning (new_clean_text_base, new_clean_text_limit)
scan_p += 2;
while (scan_p[1] != '/' || scan_p[0] != '*')
{
- if (!ISSPACE (*scan_p))
+ if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
if (++scan_p >= new_clean_text_limit)
abort ();
@@ -3898,7 +3884,7 @@ do_cleaning (new_clean_text_base, new_clean_text_limit)
*scan_p = ' ';
while (scan_p[1] != '\n' || scan_p[0] == '\\')
{
- if (!ISSPACE (*scan_p))
+ if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
if (++scan_p >= new_clean_text_limit)
abort ();
@@ -3910,9 +3896,10 @@ do_cleaning (new_clean_text_base, new_clean_text_limit)
non_whitespace_since_newline = 1;
while (scan_p[1] != '\'' || scan_p[0] == '\\')
{
- if (scan_p[0] == '\\' && !ISSPACE (scan_p[1]))
+ if (scan_p[0] == '\\'
+ && !ISSPACE ((const unsigned char)scan_p[1]))
scan_p[1] = ' ';
- if (!ISSPACE (*scan_p))
+ if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
if (++scan_p >= new_clean_text_limit)
abort ();
@@ -3924,14 +3911,15 @@ do_cleaning (new_clean_text_base, new_clean_text_limit)
non_whitespace_since_newline = 1;
while (scan_p[1] != '"' || scan_p[0] == '\\')
{
- if (scan_p[0] == '\\' && !ISSPACE (scan_p[1]))
+ if (scan_p[0] == '\\'
+ && !ISSPACE ((const unsigned char)scan_p[1]))
scan_p[1] = ' ';
- if (!ISSPACE (*scan_p))
+ if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
if (++scan_p >= new_clean_text_limit)
abort ();
}
- if (!ISSPACE (*scan_p))
+ if (!ISSPACE ((const unsigned char)*scan_p))
*scan_p = ' ';
scan_p++;
break;
@@ -4024,12 +4012,12 @@ scan_for_missed_items (file_p)
last_r_paren = scan_p;
- for (ahead_p = scan_p + 1; ISSPACE (*ahead_p); )
+ for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
check_source (++ahead_p < limit, limit);
scan_p = ahead_p - 1;
- if (ISALPHA (*ahead_p) || *ahead_p == '{')
+ if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
{
const char *last_l_paren;
const int lineno = identify_lineno (ahead_p);
@@ -4043,7 +4031,8 @@ scan_for_missed_items (file_p)
do
{
last_l_paren = careful_find_l_paren (last_r_paren);
- for (last_r_paren = last_l_paren-1; ISSPACE (*last_r_paren); )
+ for (last_r_paren = last_l_paren-1;
+ ISSPACE ((const unsigned char)*last_r_paren); )
check_source (--last_r_paren >= backup_limit, backup_limit);
}
while (*last_r_paren == ')');
@@ -4079,11 +4068,11 @@ scan_for_missed_items (file_p)
goto not_missed;
#if 0
- fprintf (stderr, "%s: found definition of `%s' at %s(%d)\n",
- pname,
- func_name,
- shortpath (NULL, file_p->hash_entry->symbol),
- identify_lineno (id_start));
+ notice ("%s: found definition of `%s' at %s(%d)\n",
+ pname,
+ func_name,
+ shortpath (NULL, file_p->hash_entry->symbol),
+ identify_lineno (id_start));
#endif /* 0 */
/* We really should check for a match of the function name
here also, but why bother. */
@@ -4095,11 +4084,11 @@ scan_for_missed_items (file_p)
/* If we make it here, then we did not know about this
function definition. */
- fprintf (stderr, "%s: %d: warning: `%s' excluded by preprocessing\n",
- shortpath (NULL, file_p->hash_entry->symbol),
- identify_lineno (id_start), func_name);
- fprintf (stderr, "%s: function definition not converted\n",
- pname);
+ notice ("%s: %d: warning: `%s' excluded by preprocessing\n",
+ shortpath (NULL, file_p->hash_entry->symbol),
+ identify_lineno (id_start), func_name);
+ notice ("%s: function definition not converted\n",
+ pname);
}
not_missed: ;
}
@@ -4157,19 +4146,19 @@ edit_file (hp)
&& !in_system_include_dir (convert_filename)
#endif /* defined (UNPROTOIZE) */
)
- fprintf (stderr, "%s: `%s' not converted\n",
- pname, shortpath (NULL, convert_filename));
+ notice ("%s: `%s' not converted\n",
+ pname, shortpath (NULL, convert_filename));
return;
}
/* Let the user know what we are up to. */
if (nochange_flag)
- fprintf (stderr, "%s: would convert file `%s'\n",
- pname, shortpath (NULL, convert_filename));
+ notice ("%s: would convert file `%s'\n",
+ pname, shortpath (NULL, convert_filename));
else
- fprintf (stderr, "%s: converting file `%s'\n",
- pname, shortpath (NULL, convert_filename));
+ notice ("%s: converting file `%s'\n",
+ pname, shortpath (NULL, convert_filename));
fflush (stderr);
/* Find out the size (in bytes) of the original file. */
@@ -4178,9 +4167,9 @@ edit_file (hp)
if (my_stat ((char *)convert_filename, &stat_buf) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't get status for file `%s': %s\n",
- pname, shortpath (NULL, convert_filename),
- my_strerror (errno_val));
+ notice ("%s: can't get status for file `%s': %s\n",
+ pname, shortpath (NULL, convert_filename),
+ xstrerror (errno_val));
return;
}
orig_size = stat_buf.st_size;
@@ -4214,9 +4203,9 @@ edit_file (hp)
if ((input_file = my_open (convert_filename, O_RDONLY, 0444)) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't open file `%s' for reading: %s\n",
- pname, shortpath (NULL, convert_filename),
- my_strerror (errno_val));
+ notice ("%s: can't open file `%s' for reading: %s\n",
+ pname, shortpath (NULL, convert_filename),
+ xstrerror (errno_val));
return;
}
@@ -4224,13 +4213,14 @@ edit_file (hp)
in one swell fwoop. Then figure out where the end of the text is and
make sure that it ends with a newline followed by a null. */
- if (safe_read (input_file, new_orig_text_base, orig_size) != orig_size)
+ if (safe_read (input_file, new_orig_text_base, orig_size) !=
+ (int) orig_size)
{
int errno_val = errno;
close (input_file);
- fprintf (stderr, "\n%s: error reading input file `%s': %s\n",
- pname, shortpath (NULL, convert_filename),
- my_strerror (errno_val));
+ notice ("\n%s: error reading input file `%s': %s\n",
+ pname, shortpath (NULL, convert_filename),
+ xstrerror (errno_val));
return;
}
@@ -4262,9 +4252,9 @@ edit_file (hp)
if ((clean_file = creat (clean_filename, 0666)) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't create/open clean file `%s': %s\n",
- pname, shortpath (NULL, clean_filename),
- my_strerror (errno_val));
+ notice ("%s: can't create/open clean file `%s': %s\n",
+ pname, shortpath (NULL, clean_filename),
+ xstrerror (errno_val));
return;
}
@@ -4363,18 +4353,18 @@ edit_file (hp)
if (errno_val == EEXIST)
{
if (!quiet_flag)
- fprintf (stderr, "%s: warning: file `%s' already saved in `%s'\n",
- pname,
- shortpath (NULL, convert_filename),
- shortpath (NULL, new_filename));
+ notice ("%s: warning: file `%s' already saved in `%s'\n",
+ pname,
+ shortpath (NULL, convert_filename),
+ shortpath (NULL, new_filename));
}
else
{
- fprintf (stderr, "%s: can't link file `%s' to `%s': %s\n",
- pname,
- shortpath (NULL, convert_filename),
- shortpath (NULL, new_filename),
- my_strerror (errno_val));
+ notice ("%s: can't link file `%s' to `%s': %s\n",
+ pname,
+ shortpath (NULL, convert_filename),
+ shortpath (NULL, new_filename),
+ xstrerror (errno_val));
return;
}
}
@@ -4383,9 +4373,9 @@ edit_file (hp)
if (my_unlink (convert_filename) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't delete file `%s': %s\n",
- pname, shortpath (NULL, convert_filename),
- my_strerror (errno_val));
+ notice ("%s: can't delete file `%s': %s\n",
+ pname, shortpath (NULL, convert_filename),
+ xstrerror (errno_val));
return;
}
@@ -4397,9 +4387,9 @@ edit_file (hp)
if ((output_file = creat (convert_filename, 0666)) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't create/open output file `%s': %s\n",
- pname, shortpath (NULL, convert_filename),
- my_strerror (errno_val));
+ notice ("%s: can't create/open output file `%s': %s\n",
+ pname, shortpath (NULL, convert_filename),
+ xstrerror (errno_val));
return;
}
@@ -4426,9 +4416,9 @@ edit_file (hp)
if (my_chmod ((char *)convert_filename, stat_buf.st_mode) == -1)
{
int errno_val = errno;
- fprintf (stderr, "%s: can't change mode of file `%s': %s\n",
- pname, shortpath (NULL, convert_filename),
- my_strerror (errno_val));
+ notice ("%s: can't change mode of file `%s': %s\n",
+ pname, shortpath (NULL, convert_filename),
+ xstrerror (errno_val));
}
/* Note: We would try to change the owner and group of the output file
@@ -4568,11 +4558,17 @@ main (argc, argv)
pname = strrchr (argv[0], '/');
pname = pname ? pname+1 : argv[0];
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
cwd_buffer = getpwd ();
if (!cwd_buffer)
{
- fprintf (stderr, "%s: cannot get working directory: %s\n",
- pname, my_strerror(errno));
+ notice ("%s: cannot get working directory: %s\n",
+ pname, xstrerror(errno));
exit (FATAL_EXIT_CODE);
}
@@ -4669,8 +4665,8 @@ main (argc, argv)
base_source_filenames[n_base_source_files++] = path;
else
{
- fprintf (stderr, "%s: input file names must have .c suffixes: %s\n",
- pname, shortpath (NULL, path));
+ notice ("%s: input file names must have .c suffixes: %s\n",
+ pname, shortpath (NULL, path));
errors++;
}
}
@@ -4682,7 +4678,8 @@ main (argc, argv)
{
const char *cp;
- for (cp = varargs_style_indicator; ISALNUM (*cp) || *cp == '_'; cp++)
+ for (cp = varargs_style_indicator;
+ ISALNUM ((const unsigned char)*cp) || *cp == '_'; cp++)
continue;
if (*cp != 0)
varargs_style_indicator = savestring (varargs_style_indicator,
diff --git a/contrib/gcc/pself4.c b/contrib/gcc/pself4.c
new file mode 100644
index 0000000..02a6f7c
--- /dev/null
+++ b/contrib/gcc/pself4.c
@@ -0,0 +1,2 @@
+#include <stdio.h>
+int main(void){char*p="#include <stdio.h>%cint main(void){char*p=%c%s%c;(void)printf(p,10,34,p,34,10);return 0;}%c";(void)printf(p,10,34,p,34,10);return 0;}
diff --git a/contrib/gcc/pself5.c b/contrib/gcc/pself5.c
new file mode 100644
index 0000000..8f6f8e3
--- /dev/null
+++ b/contrib/gcc/pself5.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+#define N '\n'
+#define Q '\"'
+#define B '\\'
+int main(void){char*p="#include <stdio.h>%c#define N '%cn'%c#define Q '%c%c'%c#define B '%c%c'%cint main(void){char*p=%c%s%c;(void)printf(p,N,B,N,B,Q,N,B,B,N,Q,p,Q,N);return 0;}%c";(void)printf(p,N,B,N,B,Q,N,B,B,N,Q,p,Q,N);return 0;}
diff --git a/contrib/gcc/real.c b/contrib/gcc/real.c
index ed854e0..a3fda6d 100644
--- a/contrib/gcc/real.c
+++ b/contrib/gcc/real.c
@@ -1,6 +1,6 @@
/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
and support for XFmode IEEE extended real floating point arithmetic.
- Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94-98, 1999 Free Software Foundation, Inc.
Contributed by Stephen L. Moshier (moshier@world.std.com).
This file is part of GNU CC.
@@ -79,14 +79,17 @@ netlib.att.com: netlib/cephes. */
`C4X' refers specifically to the floating point format used on
Texas Instruments TMS320C3x and TMS320C4x digital signal
processors. This supports QFmode (32-bit float, double) and HFmode
- (40-bit long double) where BITS_PER_BYTE is 32.
+ (40-bit long double) where BITS_PER_BYTE is 32. Unlike IEEE
+ floats, C4x floats are not rounded to be even. The C4x conversions
+ were contributed by m.hayes@elec.canterbury.ac.nz (Michael Hayes) and
+ Haj.Ten.Brugge@net.HCC.nl (Herman ten Brugge).
If LONG_DOUBLE_TYPE_SIZE = 64 (the default, unless tm.h defines it)
then `long double' and `double' are both implemented, but they
both mean DFmode. In this case, the software floating-point
support available here is activated by writing
#define REAL_ARITHMETIC
- in tm.h.
+ in tm.h.
The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support
and may deactivate XFmode since `long double' is used to refer
@@ -245,7 +248,12 @@ unknown arithmetic type
#define MAXDECEXP 4932
#define MINDECEXP -4956
#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
-#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)
+#define PUT_REAL(e,r) \
+do { \
+ if (2*NE < sizeof(*r)) \
+ bzero((char *)r, sizeof(*r)); \
+ bcopy ((char *) e, (char *) r, 2*NE); \
+} while (0)
#else /* no XFmode */
#if LONG_DOUBLE_TYPE_SIZE == 128
#define NE 10
@@ -261,34 +269,34 @@ unknown arithmetic type
/* Emulator uses target format internally
but host stores it in host endian-ness. */
-#define GET_REAL(r,e) \
-do { \
- if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
- e53toe ((unsigned EMUSHORT *) (r), (e)); \
- else \
- { \
- unsigned EMUSHORT w[4]; \
- w[3] = ((EMUSHORT *) r)[0]; \
- w[2] = ((EMUSHORT *) r)[1]; \
- w[1] = ((EMUSHORT *) r)[2]; \
- w[0] = ((EMUSHORT *) r)[3]; \
- e53toe (w, (e)); \
- } \
+#define GET_REAL(r,e) \
+do { \
+ if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
+ e53toe ((unsigned EMUSHORT *) (r), (e)); \
+ else \
+ { \
+ unsigned EMUSHORT w[4]; \
+ bcopy (((EMUSHORT *) r), &w[3], sizeof (EMUSHORT)); \
+ bcopy (((EMUSHORT *) r) + 1, &w[2], sizeof (EMUSHORT)); \
+ bcopy (((EMUSHORT *) r) + 2, &w[1], sizeof (EMUSHORT)); \
+ bcopy (((EMUSHORT *) r) + 3, &w[0], sizeof (EMUSHORT)); \
+ e53toe (w, (e)); \
+ } \
} while (0)
-#define PUT_REAL(e,r) \
-do { \
- if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
- etoe53 ((e), (unsigned EMUSHORT *) (r)); \
- else \
- { \
- unsigned EMUSHORT w[4]; \
- etoe53 ((e), w); \
- *((EMUSHORT *) r) = w[3]; \
- *((EMUSHORT *) r + 1) = w[2]; \
- *((EMUSHORT *) r + 2) = w[1]; \
- *((EMUSHORT *) r + 3) = w[0]; \
- } \
+#define PUT_REAL(e,r) \
+do { \
+ if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
+ etoe53 ((e), (unsigned EMUSHORT *) (r)); \
+ else \
+ { \
+ unsigned EMUSHORT w[4]; \
+ etoe53 ((e), w); \
+ bcopy (&w[3], ((EMUSHORT *) r), sizeof (EMUSHORT)); \
+ bcopy (&w[2], ((EMUSHORT *) r) + 1, sizeof (EMUSHORT)); \
+ bcopy (&w[1], ((EMUSHORT *) r) + 2, sizeof (EMUSHORT)); \
+ bcopy (&w[0], ((EMUSHORT *) r) + 3, sizeof (EMUSHORT)); \
+ } \
} while (0)
#else /* not REAL_ARITHMETIC */
@@ -406,12 +414,12 @@ static void e64toasc PROTO((unsigned EMUSHORT *, char *, int));
static void e113toasc PROTO((unsigned EMUSHORT *, char *, int));
#endif /* 0 */
static void etoasc PROTO((unsigned EMUSHORT *, char *, int));
-static void asctoe24 PROTO((char *, unsigned EMUSHORT *));
-static void asctoe53 PROTO((char *, unsigned EMUSHORT *));
-static void asctoe64 PROTO((char *, unsigned EMUSHORT *));
-static void asctoe113 PROTO((char *, unsigned EMUSHORT *));
-static void asctoe PROTO((char *, unsigned EMUSHORT *));
-static void asctoeg PROTO((char *, unsigned EMUSHORT *, int));
+static void asctoe24 PROTO((const char *, unsigned EMUSHORT *));
+static void asctoe53 PROTO((const char *, unsigned EMUSHORT *));
+static void asctoe64 PROTO((const char *, unsigned EMUSHORT *));
+static void asctoe113 PROTO((const char *, unsigned EMUSHORT *));
+static void asctoe PROTO((const char *, unsigned EMUSHORT *));
+static void asctoeg PROTO((const char *, unsigned EMUSHORT *, int));
static void efloor PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
static void efrexp PROTO((unsigned EMUSHORT *, int *,
@@ -423,7 +431,7 @@ static void eremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
#endif
static void eiremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
-static void mtherr PROTO((char *, int));
+static void mtherr PROTO((const char *, int));
#ifdef DEC
static void dectoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etodec PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
@@ -458,7 +466,7 @@ static void esqrt PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
swapping ends if required, into output array of longs. The
result is normally passed to fprintf by the ASM_OUTPUT_ macros. */
-static void
+static void
endian (e, x, mode)
unsigned EMUSHORT e[];
long x[];
@@ -555,7 +563,7 @@ endian (e, x, mode)
/* This is the implementation of the REAL_ARITHMETIC macro. */
-void
+void
earith (value, icode, r1, r2)
REAL_VALUE_TYPE *value;
int icode;
@@ -634,7 +642,7 @@ PUT_REAL (v, value);
/* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT.
implements REAL_VALUE_RNDZINT (x) (etrunci (x)). */
-REAL_VALUE_TYPE
+REAL_VALUE_TYPE
etrunci (x)
REAL_VALUE_TYPE x;
{
@@ -657,7 +665,7 @@ etrunci (x)
/* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT;
implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x)). */
-REAL_VALUE_TYPE
+REAL_VALUE_TYPE
etruncui (x)
REAL_VALUE_TYPE x;
{
@@ -677,13 +685,13 @@ etruncui (x)
}
-/* This is the REAL_VALUE_ATOF function. It converts a decimal string to
- binary, rounding off as indicated by the machine_mode argument. Then it
- promotes the rounded value to REAL_VALUE_TYPE. */
+/* This is the REAL_VALUE_ATOF function. It converts a decimal or hexadecimal
+ string to binary, rounding off as indicated by the machine_mode argument.
+ Then it promotes the rounded value to REAL_VALUE_TYPE. */
-REAL_VALUE_TYPE
+REAL_VALUE_TYPE
ereal_atof (s, t)
- char *s;
+ const char *s;
enum machine_mode t;
{
unsigned EMUSHORT tem[NE], e[NE];
@@ -731,7 +739,7 @@ ereal_atof (s, t)
/* Expansion of REAL_NEGATE. */
-REAL_VALUE_TYPE
+REAL_VALUE_TYPE
ereal_negate (x)
REAL_VALUE_TYPE x;
{
@@ -793,7 +801,7 @@ efixui (x)
/* REAL_VALUE_FROM_INT macro. */
-void
+void
ereal_from_int (d, i, j, mode)
REAL_VALUE_TYPE *d;
HOST_WIDE_INT i, j;
@@ -860,7 +868,7 @@ ereal_from_int (d, i, j, mode)
/* REAL_VALUE_FROM_UNSIGNED_INT macro. */
-void
+void
ereal_from_uint (d, i, j, mode)
REAL_VALUE_TYPE *d;
unsigned HOST_WIDE_INT i, j;
@@ -914,7 +922,7 @@ ereal_from_uint (d, i, j, mode)
/* REAL_VALUE_TO_INT macro. */
-void
+void
ereal_to_int (low, high, rr)
HOST_WIDE_INT *low, *high;
REAL_VALUE_TYPE rr;
@@ -1164,15 +1172,15 @@ debug_real (r)
REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);
fprintf (stderr, "%s", dstr);
-}
+}
/* The following routines convert REAL_VALUE_TYPE to the various floating
point formats that are meaningful to supported computers.
- The results are returned in 32-bit pieces, each piece stored in a `long'.
+ The results are returned in 32-bit pieces, each piece stored in a `long'.
This is so they can be printed by statements like
-
+
fprintf (file, "%lx, %lx", L[0], L[1]);
that will work on both narrow- and wide-word host computers. */
@@ -1181,7 +1189,7 @@ debug_real (r)
contains four 32-bit pieces of the result, in the order they would appear
in memory. */
-void
+void
etartdouble (r, l)
REAL_VALUE_TYPE r;
long l[];
@@ -1197,7 +1205,7 @@ etartdouble (r, l)
contains three 32-bit pieces of the result, in the order they would
appear in memory. */
-void
+void
etarldouble (r, l)
REAL_VALUE_TYPE r;
long l[];
@@ -1212,7 +1220,7 @@ etarldouble (r, l)
/* Convert R to a double precision value. The output array L contains two
32-bit pieces of the result, in the order they would appear in memory. */
-void
+void
etardouble (r, l)
REAL_VALUE_TYPE r;
long l[];
@@ -1310,11 +1318,11 @@ ereal_isneg (x)
most significant word first,
most significant bit is set)
ei[NI-1] low guard word (0x8000 bit is rounding place)
-
-
-
+
+
+
Routines for external format e-type numbers
-
+
asctoe (string, e) ASCII string to extended double e type
asctoe64 (string, &d) ASCII string to long double
asctoe53 (string, &d) ASCII string to double
@@ -1361,10 +1369,10 @@ ereal_isneg (x)
eisinf (e) 1 if e has maximum exponent (non-IEEE)
or is infinite (IEEE)
eisnan (e) 1 if e is a NaN
-
+
Routines for internal format exploded e-type numbers
-
+
eaddm (ai, bi) add significands, bi = bi + ai
ecleaz (ei) ei = 0
ecleazs (ei) set ei = 0 but leave its sign alone
@@ -1396,13 +1404,13 @@ ereal_isneg (x)
after each arithmetic operation.
Exception flags are NOT fully supported.
-
+
Signaling NaN's are NOT supported; they are treated the same
as quiet NaN's.
-
+
Define INFINITY for support of infinity; otherwise a
saturation arithmetic is implemented.
-
+
Define NANS for support of Not-a-Number items; otherwise the
arithmetic will never produce a NaN output, and might be confused
by a NaN input.
@@ -1410,7 +1418,7 @@ ereal_isneg (x)
either a or b is a NaN. This means asking `if (ecmp (a,b) < 0)'
may not be legitimate. Use `if (ecmp (a,b) == -1)' for `less than'
if in doubt.
-
+
Denormals are always supported here where appropriate (e.g., not
for conversion to DEC numbers). */
@@ -1423,7 +1431,7 @@ ereal_isneg (x)
mode, most floating point constants are given as arrays
of octal integers to eliminate decimal to binary conversion
errors that might be introduced by the compiler.
-
+
For computers, such as IBM PC, that follow the IEEE
Standard for Binary Floating Point Arithmetic (ANSI/IEEE
Std 754-1985), the symbol IEEE should be defined.
@@ -1431,20 +1439,20 @@ ereal_isneg (x)
are provided as arrays of hexadecimal 16 bit integers.
The endian-ness of generated values is controlled by
REAL_WORDS_BIG_ENDIAN.
-
+
To accommodate other types of computer arithmetic, all
constants are also provided in a normal decimal radix
which one can hope are correctly converted to a suitable
format by the available C language compiler. To invoke
this mode, the symbol UNK is defined.
-
+
An important difference among these modes is a predefined
set of machine arithmetic constants for each. The numbers
MACHEP (the machine roundoff error), MAXNUM (largest number
represented), and several other parameters are preset by
the configuration symbol. Check the file const.c to
ensure that these values are correct for your computer.
-
+
For ANSI C compatibility, define ANSIC equal to 1. Currently
this affects only the atan2 function and others that use it. */
@@ -1537,7 +1545,7 @@ extern int rndprc;
/* Clear out entire e-type number X. */
-static void
+static void
eclear (x)
register unsigned EMUSHORT *x;
{
@@ -1549,7 +1557,7 @@ eclear (x)
/* Move e-type number from A to B. */
-static void
+static void
emov (a, b)
register unsigned EMUSHORT *a, *b;
{
@@ -1563,18 +1571,18 @@ emov (a, b)
#if 0
/* Absolute value of e-type X. */
-static void
+static void
eabs (x)
unsigned EMUSHORT x[];
{
/* sign is top bit of last word of external format */
- x[NE - 1] &= 0x7fff;
+ x[NE - 1] &= 0x7fff;
}
#endif /* 0 */
/* Negate the e-type number X. */
-static void
+static void
eneg (x)
unsigned EMUSHORT x[];
{
@@ -1584,7 +1592,7 @@ eneg (x)
/* Return 1 if sign bit of e-type number X is nonzero, else zero. */
-static int
+static int
eisneg (x)
unsigned EMUSHORT x[];
{
@@ -1597,7 +1605,7 @@ eisneg (x)
/* Return 1 if e-type number X is infinity, else return zero. */
-static int
+static int
eisinf (x)
unsigned EMUSHORT x[];
{
@@ -1615,7 +1623,7 @@ eisinf (x)
/* Check if e-type number is not a number. The bit pattern is one that we
defined, so we know for sure how to detect it. */
-static int
+static int
eisnan (x)
unsigned EMUSHORT x[];
{
@@ -1639,7 +1647,7 @@ eisnan (x)
/* Fill e-type number X with infinity pattern (IEEE)
or largest possible number (non-IEEE). */
-static void
+static void
einfin (x)
register unsigned EMUSHORT *x;
{
@@ -1682,7 +1690,7 @@ einfin (x)
This generates Intel's quiet NaN pattern for extended real.
The exponent is 7fff, the leading mantissa word is c000. */
-static void
+static void
enan (x, sign)
register unsigned EMUSHORT *x;
int sign;
@@ -1697,7 +1705,7 @@ enan (x, sign)
/* Move in an e-type number A, converting it to exploded e-type B. */
-static void
+static void
emovi (a, b)
unsigned EMUSHORT *a, *b;
{
@@ -1744,7 +1752,7 @@ emovi (a, b)
/* Move out exploded e-type number A, converting it to e type B. */
-static void
+static void
emovo (a, b)
unsigned EMUSHORT *a, *b;
{
@@ -1783,7 +1791,7 @@ emovo (a, b)
/* Clear out exploded e-type number XI. */
-static void
+static void
ecleaz (xi)
register unsigned EMUSHORT *xi;
{
@@ -1795,7 +1803,7 @@ ecleaz (xi)
/* Clear out exploded e-type XI, but don't touch the sign. */
-static void
+static void
ecleazs (xi)
register unsigned EMUSHORT *xi;
{
@@ -1808,7 +1816,7 @@ ecleazs (xi)
/* Move exploded e-type number from A to B. */
-static void
+static void
emovz (a, b)
register unsigned EMUSHORT *a, *b;
{
@@ -1836,7 +1844,7 @@ einan (x)
/* Return nonzero if exploded e-type X is a NaN. */
-static int
+static int
eiisnan (x)
unsigned EMUSHORT x[];
{
@@ -1855,7 +1863,7 @@ eiisnan (x)
/* Return nonzero if sign of exploded e-type X is nonzero. */
-static int
+static int
eiisneg (x)
unsigned EMUSHORT x[];
{
@@ -1879,7 +1887,7 @@ eiinfin (x)
/* Return nonzero if exploded e-type X is infinite. */
-static int
+static int
eiisinf (x)
unsigned EMUSHORT x[];
{
@@ -1925,7 +1933,7 @@ ecmpm (a, b)
/* Shift significand of exploded e-type X down by 1 bit. */
-static void
+static void
eshdn1 (x)
register unsigned EMUSHORT *x;
{
@@ -1949,7 +1957,7 @@ eshdn1 (x)
/* Shift significand of exploded e-type X up by 1 bit. */
-static void
+static void
eshup1 (x)
register unsigned EMUSHORT *x;
{
@@ -1974,7 +1982,7 @@ eshup1 (x)
/* Shift significand of exploded e-type X down by 8 bits. */
-static void
+static void
eshdn8 (x)
register unsigned EMUSHORT *x;
{
@@ -1995,7 +2003,7 @@ eshdn8 (x)
/* Shift significand of exploded e-type X up by 8 bits. */
-static void
+static void
eshup8 (x)
register unsigned EMUSHORT *x;
{
@@ -2017,7 +2025,7 @@ eshup8 (x)
/* Shift significand of exploded e-type X up by 16 bits. */
-static void
+static void
eshup6 (x)
register unsigned EMUSHORT *x;
{
@@ -2035,7 +2043,7 @@ eshup6 (x)
/* Shift significand of exploded e-type X down by 16 bits. */
-static void
+static void
eshdn6 (x)
register unsigned EMUSHORT *x;
{
@@ -2053,7 +2061,7 @@ eshdn6 (x)
/* Add significands of exploded e-type X and Y. X + Y replaces Y. */
-static void
+static void
eaddm (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -2079,7 +2087,7 @@ eaddm (x, y)
/* Subtract significands of exploded e-type X and Y. Y - X replaces Y. */
-static void
+static void
esubm (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -2113,7 +2121,7 @@ static unsigned EMUSHORT equot[NI];
/* Divide significands */
-int
+int
edivm (den, num)
unsigned EMUSHORT den[], num[];
{
@@ -2211,7 +2219,7 @@ edivm (den, num)
/* Multiply significands */
-int
+int
emulm (a, b)
unsigned EMUSHORT a[], b[];
{
@@ -2333,7 +2341,7 @@ edivm (den, num)
tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1];
/* Do not execute the divide instruction if it will overflow. */
- if ((tdenm * 0xffffL) < tnum)
+ if ((tdenm * (unsigned long)0xffff) < tnum)
tquot = 0xffff;
else
tquot = tnum / tdenm;
@@ -2417,15 +2425,15 @@ emulm (a, b)
The internal format number to be rounded is S.
Input LOST is 0 if the value is exact. This is the so-called sticky bit.
-
+
Input SUBFLG indicates whether the number was obtained
by a subtraction operation. In that case if LOST is nonzero
then the number is slightly smaller than indicated.
-
+
Input EXP is the biased exponent, which may be negative.
the exponent field of S is ignored but is replaced by
EXP as adjusted by normalization and rounding.
-
+
Input RCNTRL is the rounding control. If it is nonzero, the
returned value will be rounded to RNDPRC bits.
@@ -2434,7 +2442,7 @@ emulm (a, b)
adjusted to be the actual value it would have after conversion to
the final floating point type. This adjustment has been
implemented for all type conversions (etoe53, etc.) and decimal
- conversions, but not for the arithmetic functions (eadd, etc.).
+ conversions, but not for the arithmetic functions (eadd, etc.).
Data types having standard 15-bit exponents are not affected by
this, but SFmode and DFmode are affected. For example, ediv with
rndprc = 24 will not round correctly to 24-bit precision if the
@@ -2448,7 +2456,7 @@ static unsigned EMUSHORT rebit = 0;
static int re = 0;
static unsigned EMUSHORT rbit[NI];
-static void
+static void
emdnorm (s, lost, subflg, exp, rcntrl)
unsigned EMUSHORT s[];
int lost;
@@ -2594,6 +2602,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
s[rw] &= ~rmsk;
if ((r & rmbit) != 0)
{
+#ifndef C4X
if (r == rmbit)
{
if (lost == 0)
@@ -2607,6 +2616,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
goto mddone;
}
}
+#endif
eaddm (rbit, s);
}
mddone:
@@ -2662,7 +2672,7 @@ emdnorm (s, lost, subflg, exp, rcntrl)
static int subflg = 0;
-static void
+static void
esub (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
@@ -2694,7 +2704,7 @@ esub (a, b, c)
/* Add. C = A + B, all e type. */
-static void
+static void
eadd (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
@@ -2727,7 +2737,7 @@ eadd (a, b, c)
/* Arithmetic common to both addition and subtraction. */
-static void
+static void
eadd1 (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
@@ -2838,7 +2848,7 @@ eadd1 (a, b, c)
/* Divide: C = B/A, all e type. */
-static void
+static void
ediv (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
@@ -2942,7 +2952,7 @@ ediv (a, b, c)
/* Multiply e-types A and B, return e-type product C. */
-static void
+static void
emul (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
@@ -3132,7 +3142,7 @@ e53toe (pe, y)
#endif
eshift (yy, -5);
if (denorm)
- {
+ {
/* If zero exponent, then normalize the significand. */
if ((k = enormlz (yy)) > NBITS)
ecleazs (yy);
@@ -3147,7 +3157,7 @@ e53toe (pe, y)
/* Convert double extended precision float PE to e type Y. */
-static void
+static void
e64toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
@@ -3269,7 +3279,7 @@ bigend_nan:
/* Convert 128-bit long double precision float PE to e type Y. */
-static void
+static void
e113toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
@@ -3354,7 +3364,7 @@ e113toe (pe, y)
/* Convert single precision float PE to e type Y. */
-static void
+static void
e24toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
@@ -3457,7 +3467,7 @@ e24toe (pe, y)
/* Convert e-type X to IEEE 128-bit long double format E. */
-static void
+static void
etoe113 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3490,7 +3500,7 @@ etoe113 (x, e)
/* Convert exploded e-type X, that has already been rounded to
113-bit precision, to IEEE 128-bit long double format Y. */
-static void
+static void
toe113 (a, b)
unsigned EMUSHORT *a, *b;
{
@@ -3548,7 +3558,7 @@ toe113 (a, b)
/* Convert e-type X to IEEE double extended format E. */
-static void
+static void
etoe64 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3582,7 +3592,7 @@ etoe64 (x, e)
/* Convert exploded e-type X, that has already been rounded to
64-bit precision, to IEEE double extended format Y. */
-static void
+static void
toe64 (a, b)
unsigned EMUSHORT *a, *b;
{
@@ -3698,7 +3708,7 @@ toe64 (a, b)
#ifdef DEC
/* Convert e-type X to DEC-format double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3708,7 +3718,7 @@ etoe53 (x, e)
/* Convert exploded e-type X, that has already been rounded to
56-bit double precision, to DEC double Y. */
-static void
+static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -3719,7 +3729,7 @@ toe53 (x, y)
#ifdef IBM
/* Convert e-type X to IBM 370-format double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3729,7 +3739,7 @@ etoe53 (x, e)
/* Convert exploded e-type X, that has already been rounded to
56-bit precision, to IBM 370 double Y. */
-static void
+static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -3740,7 +3750,7 @@ toe53 (x, y)
#ifdef C4X
/* Convert e-type X to C4X-format long double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3750,7 +3760,7 @@ etoe53 (x, e)
/* Convert exploded e-type X, that has already been rounded to
56-bit precision, to IBM 370 double Y. */
-static void
+static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -3761,7 +3771,7 @@ toe53 (x, y)
/* Convert e-type X to IEEE double E. */
-static void
+static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3795,7 +3805,7 @@ etoe53 (x, e)
/* Convert exploded e-type X, that has already been rounded to
53-bit precision, to IEEE double Y. */
-static void
+static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -3892,7 +3902,7 @@ toe53 (x, y)
#ifdef IBM
/* Convert e-type X to IBM 370 float E. */
-static void
+static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3902,7 +3912,7 @@ etoe24 (x, e)
/* Convert exploded e-type X, that has already been rounded to
float precision, to IBM 370 float Y. */
-static void
+static void
toe24 (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -3914,7 +3924,7 @@ toe24 (x, y)
#ifdef C4X
/* Convert e-type X to C4X float E. */
-static void
+static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3924,7 +3934,7 @@ etoe24 (x, e)
/* Convert exploded e-type X, that has already been rounded to
float precision, to IBM 370 float Y. */
-static void
+static void
toe24 (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -3935,7 +3945,7 @@ toe24 (x, y)
/* Convert e-type X to IEEE float E. DEC float is the same as IEEE float. */
-static void
+static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
@@ -3969,7 +3979,7 @@ etoe24 (x, e)
/* Convert exploded e-type X, that has already been rounded to
float precision, to IEEE float Y. */
-static void
+static void
toe24 (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -4061,13 +4071,13 @@ toe24 (x, y)
#endif /* not C4X */
#endif /* not IBM */
-/* Compare two e type numbers.
+/* Compare two e type numbers.
Return +1 if a > b
0 if a == b
-1 if a < b
-2 if either a or b is a NaN. */
-static int
+static int
ecmp (a, b)
unsigned EMUSHORT *a, *b;
{
@@ -4130,7 +4140,7 @@ ecmp (a, b)
#if 0
/* Find e-type nearest integer to X, as floor (X + 0.5). */
-static void
+static void
eround (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -4141,7 +4151,7 @@ eround (x, y)
/* Convert HOST_WIDE_INT LP to e type Y. */
-static void
+static void
ltoe (lp, y)
HOST_WIDE_INT *lp;
unsigned EMUSHORT *y;
@@ -4183,7 +4193,7 @@ ltoe (lp, y)
/* Convert unsigned HOST_WIDE_INT LP to e type Y. */
-static void
+static void
ultoe (lp, y)
unsigned HOST_WIDE_INT *lp;
unsigned EMUSHORT *y;
@@ -4223,7 +4233,7 @@ ultoe (lp, y)
The output e-type fraction FRAC is the positive fractional
part of abs (X). */
-static void
+static void
eifrac (x, i, frac)
unsigned EMUSHORT *x;
HOST_WIDE_INT *i;
@@ -4306,7 +4316,7 @@ eifrac (x, i, frac)
FRAC of e-type X. A negative input yields integer output = 0 but
correct fraction. */
-static void
+static void
euifrac (x, i, frac)
unsigned EMUSHORT *x;
unsigned HOST_WIDE_INT *i;
@@ -4375,7 +4385,7 @@ euifrac (x, i, frac)
/* Shift the significand of exploded e-type X up or down by SC bits. */
-static int
+static int
eshift (x, sc)
unsigned EMUSHORT *x;
int sc;
@@ -4441,7 +4451,7 @@ eshift (x, sc)
/* Shift normalize the significand area of exploded e-type X.
Return the shift count (up = positive). */
-static int
+static int
enormlz (x)
unsigned EMUSHORT x[];
{
@@ -4613,7 +4623,7 @@ static unsigned EMUSHORT emtens[NTEN + 1][NE] =
/* Convert float value X to ASCII string STRING with NDIG digits after
the decimal point. */
-static void
+static void
e24toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
@@ -4628,7 +4638,7 @@ e24toasc (x, string, ndigs)
/* Convert double value X to ASCII string STRING with NDIG digits after
the decimal point. */
-static void
+static void
e53toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
@@ -4643,7 +4653,7 @@ e53toasc (x, string, ndigs)
/* Convert double extended value X to ASCII string STRING with NDIG digits
after the decimal point. */
-static void
+static void
e64toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
@@ -4658,7 +4668,7 @@ e64toasc (x, string, ndigs)
/* Convert 128-bit long double value X to ASCII string STRING with NDIG digits
after the decimal point. */
-static void
+static void
e113toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
@@ -4676,7 +4686,7 @@ e113toasc (x, string, ndigs)
static char wstring[80]; /* working storage for ASCII output */
-static void
+static void
etoasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
@@ -4932,8 +4942,10 @@ etoasc (x, string, ndigs)
emovo (y, t);
if (ecmp (t, ezero) != 0)
goto roun; /* round to nearest */
+#ifndef C4X
if ((*(s - 1) & 1) == 0)
goto doexp; /* round to even */
+#endif
}
/* Round up and propagate carry-outs */
roun:
@@ -4992,9 +5004,9 @@ etoasc (x, string, ndigs)
/* Convert ASCII string S to single precision float value Y. */
-static void
+static void
asctoe24 (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 24);
@@ -5003,9 +5015,9 @@ asctoe24 (s, y)
/* Convert ASCII string S to double precision value Y. */
-static void
+static void
asctoe53 (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
#if defined(DEC) || defined(IBM)
@@ -5022,9 +5034,9 @@ asctoe53 (s, y)
/* Convert ASCII string S to double extended value Y. */
-static void
+static void
asctoe64 (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 64);
@@ -5032,9 +5044,9 @@ asctoe64 (s, y)
/* Convert ASCII string S to 128-bit long double Y. */
-static void
+static void
asctoe113 (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 113);
@@ -5042,20 +5054,20 @@ asctoe113 (s, y)
/* Convert ASCII string S to e type Y. */
-static void
+static void
asctoe (s, y)
- char *s;
+ const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, NBITS);
}
/* Convert ASCII string SS to e type Y, with a specified rounding precision
- of OPREC bits. */
+ of OPREC bits. BASE is 16 for C9X hexadecimal floating constants. */
-static void
+static void
asctoeg (ss, y, oprec)
- char *ss;
+ const char *ss;
unsigned EMUSHORT *y;
int oprec;
{
@@ -5065,17 +5077,25 @@ asctoeg (ss, y, oprec)
EMULONG lexp;
unsigned EMUSHORT nsign, *p;
char *sp, *s, *lstr;
+ int base = 10;
/* Copy the input string. */
lstr = (char *) alloca (strlen (ss) + 1);
- s = ss;
- while (*s == ' ') /* skip leading spaces */
- ++s;
+
+ while (*ss == ' ') /* skip leading spaces */
+ ++ss;
+
sp = lstr;
- while ((*sp++ = *s++) != '\0')
+ while ((*sp++ = *ss++) != '\0')
;
s = lstr;
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ {
+ base = 16;
+ s += 2;
+ }
+
rndsav = rndprc;
rndprc = NBITS; /* Set to full precision */
lost = 0;
@@ -5089,8 +5109,13 @@ asctoeg (ss, y, oprec)
trail = 0;
nxtcom:
- k = *s - '0';
- if ((k >= 0) && (k <= 9))
+ if (*s >= '0' && *s <= '9')
+ k = *s - '0';
+ else if (*s >= 'a')
+ k = 10 + *s - 'a';
+ else
+ k = 10 + *s - 'A';
+ if ((k >= 0) && (k < base))
{
/* Ignore leading zeros */
if ((prec == 0) && (decflg == 0) && (k == 0))
@@ -5099,11 +5124,15 @@ asctoeg (ss, y, oprec)
if ((trail == 0) && (decflg != 0))
{
sp = s;
- while ((*sp >= '0') && (*sp <= '9'))
+ while ((*sp >= '0' && *sp <= '9')
+ || (base == 16 && ((*sp >= 'a' && *sp <= 'f')
+ || (*sp >= 'A' && *sp <= 'F'))))
++sp;
/* Check for syntax error */
c = *sp & 0x7f;
- if ((c != 'e') && (c != 'E') && (c != '\0')
+ if ((base != 10 || ((c != 'e') && (c != 'E')))
+ && (base != 16 || ((c != 'p') && (c != 'P')))
+ && (c != '\0')
&& (c != '\n') && (c != '\r') && (c != ' ')
&& (c != ','))
goto error;
@@ -5122,13 +5151,28 @@ asctoeg (ss, y, oprec)
if (yy[2] == 0)
{
- if (decflg)
- nexp += 1; /* count digits after decimal point */
- eshup1 (yy); /* multiply current number by 10 */
- emovz (yy, xt);
- eshup1 (xt);
- eshup1 (xt);
- eaddm (xt, yy);
+ if (base == 16)
+ {
+ if (decflg)
+ nexp += 4; /* count digits after decimal point */
+
+ eshup1 (yy); /* multiply current number by 16 */
+ eshup1 (yy);
+ eshup1 (yy);
+ eshup1 (yy);
+ }
+ else
+ {
+ if (decflg)
+ nexp += 1; /* count digits after decimal point */
+
+ eshup1 (yy); /* multiply current number by 10 */
+ emovz (yy, xt);
+ eshup1 (xt);
+ eshup1 (xt);
+ eaddm (xt, yy);
+ }
+ /* Insert the current digit. */
ecleaz (xt);
xt[NI - 2] = (unsigned EMUSHORT) k;
eaddm (xt, yy);
@@ -5139,7 +5183,12 @@ asctoeg (ss, y, oprec)
lost |= k;
/* Count lost digits before the decimal point. */
if (decflg == 0)
- nexp -= 1;
+ {
+ if (base == 10)
+ nexp -= 1;
+ else
+ nexp -= 4;
+ }
}
prec += 1;
goto donchr;
@@ -5151,6 +5200,8 @@ asctoeg (ss, y, oprec)
break;
case 'E':
case 'e':
+ case 'P':
+ case 'p':
goto expnt;
case '.': /* decimal point */
if (decflg)
@@ -5217,24 +5268,19 @@ read_expnt:
{
exp *= 10;
exp += *s++ - '0';
- if (exp > -(MINDECEXP))
- {
- if (esign < 0)
- goto zero;
- else
- goto infinite;
- }
+ if (exp > 999999)
+ break;
}
if (esign < 0)
exp = -exp;
- if (exp > MAXDECEXP)
+ if ((exp > MAXDECEXP) && (base == 10))
{
infinite:
ecleaz (yy);
yy[E] = 0x7fff; /* infinity */
goto aexit;
}
- if (exp < MINDECEXP)
+ if ((exp < MINDECEXP) && (base == 10))
{
zero:
ecleaz (yy);
@@ -5242,6 +5288,25 @@ read_expnt:
}
daldone:
+ if (base == 16)
+ {
+ /* Base 16 hexadecimal floating constant. */
+ if ((k = enormlz (yy)) > NBITS)
+ {
+ ecleaz (yy);
+ goto aexit;
+ }
+ /* Adjust the exponent. NEXP is the number of hex digits,
+ EXP is a power of 2. */
+ lexp = (EXONE - 1 + NBITS) - k + yy[E] + exp - nexp;
+ if (lexp > 0x7fff)
+ goto infinite;
+ if (lexp < 0)
+ goto zero;
+ yy[E] = lexp;
+ goto expdon;
+ }
+
nexp = exp - nexp;
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
while ((nexp > 0) && (yy[2] == 0))
@@ -5263,6 +5328,7 @@ read_expnt:
}
lexp = (EXONE - 1 + NBITS) - k;
emdnorm (yy, lost, 0, lexp, 64);
+ lost = 0;
/* Convert to external format:
@@ -5318,6 +5384,7 @@ read_expnt:
k = emulm (tt, yy);
lexp -= EXONE - 1;
}
+ lost = k;
expdon:
@@ -5341,7 +5408,7 @@ read_expnt:
lexp -= EXONE - 0201;
#endif
rndprc = oprec;
- emdnorm (yy, k, 0, lexp, 64);
+ emdnorm (yy, lost, 0, lexp, 64);
aexit:
@@ -5409,7 +5476,7 @@ static unsigned EMUSHORT bmask[] =
0x0000,
};
-static void
+static void
efloor (x, y)
unsigned EMUSHORT x[], y[];
{
@@ -5460,7 +5527,7 @@ efloor (x, y)
/* Return S and EXP such that S * 2^EXP = X and .5 <= S < 1.
For example, 1.1 = 0.55 * 2^1. */
-static void
+static void
efrexp (x, exp, s)
unsigned EMUSHORT x[];
int *exp;
@@ -5485,7 +5552,7 @@ efrexp (x, exp, s)
/* Return e type Y = X * 2^PWR2. */
-static void
+static void
eldexp (x, pwr2, y)
unsigned EMUSHORT x[];
int pwr2;
@@ -5508,7 +5575,7 @@ eldexp (x, pwr2, y)
/* C = remainder after dividing B by A, all e type values.
Least significant integer quotient bits left in EQUOT. */
-static void
+static void
eremain (a, b, c)
unsigned EMUSHORT a[], b[], c[];
{
@@ -5545,7 +5612,7 @@ eremain (a, b, c)
/* Return quotient of exploded e-types NUM / DEN in EQUOT,
remainder in NUM. */
-static void
+static void
eiremain (den, num)
unsigned EMUSHORT den[], num[];
{
@@ -5575,10 +5642,9 @@ eiremain (den, num)
}
/* Report an error condition CODE encountered in function NAME.
- CODE is one of the following:
Mnemonic Value Significance
-
+
DOMAIN 1 argument domain error
SING 2 function singularity
OVERFLOW 3 overflow range error
@@ -5588,42 +5654,53 @@ eiremain (den, num)
INVALID 7 NaN - producing operation
EDOM 33 Unix domain error code
ERANGE 34 Unix range error code
-
+
The order of appearance of the following messages is bound to the
error codes defined above. */
-#define NMSGS 8
-static char *ermsg[NMSGS] =
-{
- "unknown", /* error code 0 */
- "domain", /* error code 1 */
- "singularity", /* et seq. */
- "overflow",
- "underflow",
- "total loss of precision",
- "partial loss of precision",
- "invalid operation"
-};
-
int merror = 0;
extern int merror;
-static void
+static void
mtherr (name, code)
- char *name;
+ const char *name;
int code;
{
- char errstr[80];
-
/* The string passed by the calling program is supposed to be the
name of the function in which the error occurred.
The code argument selects which error message string will be printed. */
- if ((code <= 0) || (code >= NMSGS))
- code = 0;
- sprintf (errstr, " %s %s error", name, ermsg[code]);
+ if (strcmp (name, "esub") == 0)
+ name = "subtraction";
+ else if (strcmp (name, "ediv") == 0)
+ name = "division";
+ else if (strcmp (name, "emul") == 0)
+ name = "multiplication";
+ else if (strcmp (name, "enormlz") == 0)
+ name = "normalization";
+ else if (strcmp (name, "etoasc") == 0)
+ name = "conversion to text";
+ else if (strcmp (name, "asctoe") == 0)
+ name = "parsing";
+ else if (strcmp (name, "eremain") == 0)
+ name = "modulus";
+ else if (strcmp (name, "esqrt") == 0)
+ name = "square root";
if (extra_warnings)
- warning (errstr);
+ {
+ switch (code)
+ {
+ case DOMAIN: warning ("%s: argument domain error" , name); break;
+ case SING: warning ("%s: function singularity" , name); break;
+ case OVERFLOW: warning ("%s: overflow range error" , name); break;
+ case UNDERFLOW: warning ("%s: underflow range error" , name); break;
+ case TLOSS: warning ("%s: total loss of precision" , name); break;
+ case PLOSS: warning ("%s: partial loss of precision", name); break;
+ case INVALID: warning ("%s: NaN - producing operation", name); break;
+ default: abort ();
+ }
+ }
+
/* Set global error message word */
merror = code + 1;
}
@@ -5631,7 +5708,7 @@ mtherr (name, code)
#ifdef DEC
/* Convert DEC double precision D to e type E. */
-static void
+static void
dectoe (d, e)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
@@ -5671,7 +5748,7 @@ dectoe (d, e)
/* Convert e type X to DEC double precision D. */
-static void
+static void
etodec (x, d)
unsigned EMUSHORT *x, *d;
{
@@ -5693,7 +5770,7 @@ etodec (x, d)
/* Convert exploded e-type X, that has already been rounded to
56-bit precision, to DEC format double Y. */
-static void
+static void
todec (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -5739,7 +5816,7 @@ todec (x, y)
#ifdef IBM
/* Convert IBM single/double precision to e type. */
-static void
+static void
ibmtoe (d, e, mode)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
@@ -5783,7 +5860,7 @@ ibmtoe (d, e, mode)
/* Convert e type to IBM single/double precision. */
-static void
+static void
etoibm (x, d, mode)
unsigned EMUSHORT *x, *d;
enum machine_mode mode;
@@ -5802,7 +5879,7 @@ etoibm (x, d, mode)
toibm (xi, d, mode);
}
-static void
+static void
toibm (x, y, mode)
unsigned EMUSHORT *x, *y;
enum machine_mode mode;
@@ -5860,7 +5937,7 @@ toibm (x, y, mode)
#ifdef C4X
/* Convert C4X single/double precision to e type. */
-static void
+static void
c4xtoe (d, e, mode)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
@@ -5868,7 +5945,6 @@ c4xtoe (d, e, mode)
{
unsigned EMUSHORT y[NI];
int r;
- int rndsav;
int isnegative;
int size;
int i;
@@ -5899,7 +5975,7 @@ c4xtoe (d, e, mode)
{
isnegative = FALSE;
}
-
+
r >>= 8; /* Shift exponent word down 8 bits. */
if (r & 0x80) /* Make the exponent negative if it is. */
{
@@ -5911,7 +5987,7 @@ c4xtoe (d, e, mode)
/* Now do the high order mantissa. We don't "or" on the high bit
because it is 2 (not 1) and is handled a little differently
below. */
- y[M] = d[0] & 0x7f;
+ y[M] = d[0] & 0x7f;
y[M+1] = d[1];
if (mode != QFmode) /* There are only 2 words in QFmode. */
@@ -5956,11 +6032,11 @@ c4xtoe (d, e, mode)
{
/* Add our e type exponent offset to form our exponent. */
r += EXONE;
- y[1] = r;
+ y[1] = r;
/* Now do the high order mantissa strip off the exponent and sign
bits and add the high 1 bit. */
- y[M] = d[0] & 0x7f | 0x80;
+ y[M] = (d[0] & 0x7f) | 0x80;
y[M+1] = d[1];
if (mode != QFmode) /* There are only 2 words in QFmode. */
@@ -5977,7 +6053,7 @@ c4xtoe (d, e, mode)
/* Convert e type to C4X single/double precision. */
-static void
+static void
etoc4x (x, d, mode)
unsigned EMUSHORT *x, *d;
enum machine_mode mode;
@@ -5999,16 +6075,15 @@ etoc4x (x, d, mode)
toc4x (xi, d, mode);
}
-static void
+static void
toc4x (x, y, mode)
unsigned EMUSHORT *x, *y;
enum machine_mode mode;
{
int i;
- int r;
int v;
int carry;
-
+
/* Short-circuit the zero case */
if ((x[0] == 0) /* Zero exponent and sign */
&& (x[1] == 0)
@@ -6027,17 +6102,17 @@ toc4x (x, y, mode)
}
return;
}
-
+
*y = 0;
-
+
/* Negative number require a two's complement conversion of the
mantissa. */
if (x[0])
{
*y = 0x0080;
-
+
i = ((int) x[1]) - 0x7f;
-
+
/* Now add 1 to the inverted data to do the two's complement. */
if (mode != QFmode)
v = 4 + M;
@@ -6057,7 +6132,7 @@ toc4x (x, y, mode)
}
v--;
}
-
+
/* The following is a special case. The C4X negative float requires
a zero in the high bit (because the format is (2 - x) x 2^m), so
if a one is in that bit, we have to shift left one to get rid
@@ -6089,11 +6164,11 @@ toc4x (x, y, mode)
#endif
return;
}
-
+
y[0] |= ((i & 0xff) << 8);
-
+
eshift (x, 8);
-
+
y[0] |= x[M] & 0x7f;
y[1] = x[M + 1];
if (mode != QFmode)
@@ -6200,11 +6275,11 @@ make_nan (nan, sign, mode)
abort ();
}
if (REAL_WORDS_BIG_ENDIAN)
- *nan++ = (sign << 15) | *p++;
+ *nan++ = (sign << 15) | (*p++ & 0x7fff);
while (--n != 0)
*nan++ = *p++;
if (! REAL_WORDS_BIG_ENDIAN)
- *nan = (sign << 15) | *p;
+ *nan = (sign << 15) | (*p & 0x7fff);
}
/* This is the inverse of the function `etarsingle' invoked by
@@ -6325,17 +6400,19 @@ ereal_from_double (d)
/* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */
if (REAL_WORDS_BIG_ENDIAN)
{
+#if HOST_BITS_PER_WIDE_INT == 32
s[0] = (unsigned EMUSHORT) (d[0] >> 16);
s[1] = (unsigned EMUSHORT) d[0];
-#if HOST_BITS_PER_WIDE_INT == 32
s[2] = (unsigned EMUSHORT) (d[1] >> 16);
s[3] = (unsigned EMUSHORT) d[1];
#else
/* In this case the entire target double is contained in the
first array element. The second element of the input is
ignored. */
- s[2] = (unsigned EMUSHORT) (d[0] >> 48);
- s[3] = (unsigned EMUSHORT) (d[0] >> 32);
+ s[0] = (unsigned EMUSHORT) (d[0] >> 48);
+ s[1] = (unsigned EMUSHORT) (d[0] >> 32);
+ s[2] = (unsigned EMUSHORT) (d[0] >> 16);
+ s[3] = (unsigned EMUSHORT) d[0];
#endif
}
else
@@ -6442,7 +6519,7 @@ ditoe (di, e)
/* Convert e-type to unsigned 64-bit int. */
-static void
+static void
etoudi (x, i)
unsigned EMUSHORT *x;
unsigned EMUSHORT *i;
@@ -6525,7 +6602,7 @@ noshift:
/* Convert e-type to signed 64-bit int. */
-static void
+static void
etodi (x, i)
unsigned EMUSHORT *x;
unsigned EMUSHORT *i;
@@ -6627,7 +6704,7 @@ etodi (x, i)
static int esqinited = 0;
static unsigned short sqrndbit[NI];
-static void
+static void
esqrt (x, y)
unsigned EMUSHORT *x, *y;
{
@@ -6748,7 +6825,7 @@ significand_size (mode)
switch (GET_MODE_BITSIZE (mode))
{
case 32:
-
+
#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
return 56;
#endif
diff --git a/contrib/gcc/real.h b/contrib/gcc/real.h
index 0719c26..f289379 100644
--- a/contrib/gcc/real.h
+++ b/contrib/gcc/real.h
@@ -1,5 +1,5 @@
/* Definitions of floating-point access for GNU compiler.
- Copyright (C) 1989, 1991, 1994, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1989, 91, 94, 96-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -132,7 +132,7 @@ extern void earith PROTO((REAL_VALUE_TYPE *, int,
REAL_VALUE_TYPE *, REAL_VALUE_TYPE *));
extern REAL_VALUE_TYPE etrunci PROTO((REAL_VALUE_TYPE));
extern REAL_VALUE_TYPE etruncui PROTO((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_atof PROTO((char *, enum machine_mode));
+extern REAL_VALUE_TYPE ereal_atof PROTO((const char *, enum machine_mode));
extern REAL_VALUE_TYPE ereal_negate PROTO((REAL_VALUE_TYPE));
extern HOST_WIDE_INT efixi PROTO((REAL_VALUE_TYPE));
extern unsigned HOST_WIDE_INT efixui PROTO((REAL_VALUE_TYPE));
@@ -178,7 +178,11 @@ extern REAL_VALUE_TYPE real_value_truncate PROTO ((enum machine_mode,
toward zero. */
#define REAL_VALUE_UNSIGNED_FIX(x) (efixui (x))
+/* Convert ASCII string S to floating point in mode M.
+ Decimal input uses ATOF. Hexadecimal uses HTOF. */
#define REAL_VALUE_ATOF ereal_atof
+#define REAL_VALUE_HTOF ereal_atof
+
#define REAL_VALUE_NEGATE ereal_negate
#define REAL_VALUE_MINUS_ZERO(x) \
@@ -355,6 +359,9 @@ extern double ldexp ();
/* Use real.c to convert decimal numbers to binary, ... */
REAL_VALUE_TYPE ereal_atof ();
#define REAL_VALUE_ATOF(x, s) ereal_atof (x, s)
+/* Could use ereal_atof here for hexadecimal floats too, but real_hex_to_f
+ is OK and it uses faster native fp arithmetic. */
+/* #define REAL_VALUE_HTOF(x, s) ereal_atof (x, s) */
#else
/* ... or, if you like the host computer's atof, go ahead and use it: */
#define REAL_VALUE_ATOF(x, s) atof (x)
@@ -369,6 +376,13 @@ extern double (atof) ();
#endif
#endif
+/* Hexadecimal floating constant input for use with host computer's
+ fp arithmetic. */
+#ifndef REAL_VALUE_HTOF
+extern REAL_VALUE_TYPE real_hex_to_f PROTO((char *, enum machine_mode));
+#define REAL_VALUE_HTOF(s,m) real_hex_to_f(s,m)
+#endif
+
/* Negate the floating-point value X. */
#ifndef REAL_VALUE_NEGATE
#define REAL_VALUE_NEGATE(x) (- (x))
diff --git a/contrib/gcc/recog.c b/contrib/gcc/recog.c
index ded35f7..94e7abb 100644
--- a/contrib/gcc/recog.c
+++ b/contrib/gcc/recog.c
@@ -1,5 +1,5 @@
/* Subroutines used by or related to instruction recognition.
- Copyright (C) 1987, 1988, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,6 +31,8 @@ Boston, MA 02111-1307, USA. */
#include "hard-reg-set.h"
#include "flags.h"
#include "real.h"
+#include "toplev.h"
+#include "basic-block.h"
#ifndef STACK_PUSH_CODE
#ifdef STACK_GROWS_DOWNWARD
@@ -40,12 +42,18 @@ Boston, MA 02111-1307, USA. */
#endif
#endif
-/* Import from final.c: */
-extern rtx alter_subreg ();
+#ifndef STACK_POP_CODE
+#ifdef STACK_GROWS_DOWNWARD
+#define STACK_POP_CODE POST_INC
+#else
+#define STACK_POP_CODE POST_DEC
+#endif
+#endif
-static void validate_replace_rtx_1 PROTO((rtx *, rtx, rtx, rtx));
-static rtx *find_single_use_1 PROTO((rtx, rtx *));
-static rtx *find_constant_term_loc PROTO((rtx *));
+static void validate_replace_rtx_1 PROTO((rtx *, rtx, rtx, rtx));
+static rtx *find_single_use_1 PROTO((rtx, rtx *));
+static rtx *find_constant_term_loc PROTO((rtx *));
+static int insn_invalid_p PROTO((rtx));
/* Nonzero means allow operands to be volatile.
This should be 0 if you are generating rtl, such as if you are calling
@@ -57,6 +65,50 @@ static rtx *find_constant_term_loc PROTO((rtx *));
int volatile_ok;
+/* The next variables are set up by extract_insn. The first four of them
+ are also set up during insn_extract. */
+
+/* Indexed by N, gives value of operand N. */
+rtx recog_operand[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives location where operand N was found. */
+rtx *recog_operand_loc[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives location where the Nth duplicate-appearance of
+ an operand was found. This is something that matched MATCH_DUP. */
+rtx *recog_dup_loc[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives the operand number that was duplicated in the
+ Nth duplicate-appearance of an operand. */
+char recog_dup_num[MAX_RECOG_OPERANDS];
+
+/* The number of operands of the insn. */
+int recog_n_operands;
+
+/* The number of MATCH_DUPs in the insn. */
+int recog_n_dups;
+
+/* The number of alternatives in the constraints for the insn. */
+int recog_n_alternatives;
+
+/* Indexed by N, gives the mode of operand N. */
+enum machine_mode recog_operand_mode[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives the constraint string for operand N. */
+const char *recog_constraints[MAX_RECOG_OPERANDS];
+
+/* Indexed by N, gives the type (in, out, inout) for operand N. */
+enum op_type recog_op_type[MAX_RECOG_OPERANDS];
+
+#ifndef REGISTER_CONSTRAINTS
+/* Indexed by N, nonzero if operand N should be an address. */
+char recog_operand_address_p[MAX_RECOG_OPERANDS];
+#endif
+
+/* Contains a vector of operand_alternative structures for every operand.
+ Set up by preprocess_constraints. */
+struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES];
+
/* On return from `constrain_operands', indicate which alternative
was satisfied. */
@@ -109,38 +161,58 @@ int
check_asm_operands (x)
rtx x;
{
- int noperands = asm_noperands (x);
+ int noperands;
rtx *operands;
+ const char **constraints;
int i;
+ /* Post-reload, be more strict with things. */
+ if (reload_completed)
+ {
+ /* ??? Doh! We've not got the wrapping insn. Cook one up. */
+ extract_insn (make_insn_raw (x));
+ constrain_operands (1);
+ return which_alternative >= 0;
+ }
+
+ noperands = asm_noperands (x);
if (noperands < 0)
return 0;
if (noperands == 0)
return 1;
operands = (rtx *) alloca (noperands * sizeof (rtx));
- decode_asm_operands (x, operands, NULL_PTR, NULL_PTR, NULL_PTR);
+ constraints = (const char **) alloca (noperands * sizeof (char *));
+
+ decode_asm_operands (x, operands, NULL_PTR, constraints, NULL_PTR);
for (i = 0; i < noperands; i++)
- if (!general_operand (operands[i], VOIDmode))
- return 0;
+ {
+ const char *c = constraints[i];
+ if (c[0] == '%')
+ c++;
+ if (ISDIGIT ((unsigned char)c[0]) && c[1] == '\0')
+ c = constraints[c[0] - '0'];
+
+ if (! asm_operand_ok (operands[i], c))
+ return 0;
+ }
return 1;
}
-/* Static data for the next two routines.
-
- The maximum number of changes supported is defined as the maximum
- number of operands times 5. This allows for repeated substitutions
- inside complex indexed address, or, alternatively, changes in up
- to 5 insns. */
+/* Static data for the next two routines. */
-#define MAX_CHANGE_LOCS (MAX_RECOG_OPERANDS * 5)
+typedef struct change_t
+{
+ rtx object;
+ int old_code;
+ rtx *loc;
+ rtx old;
+} change_t;
-static rtx change_objects[MAX_CHANGE_LOCS];
-static int change_old_codes[MAX_CHANGE_LOCS];
-static rtx *change_locs[MAX_CHANGE_LOCS];
-static rtx change_olds[MAX_CHANGE_LOCS];
+static change_t *changes;
+static int changes_allocated;
static int num_changes = 0;
@@ -174,22 +246,35 @@ validate_change (object, loc, new, in_group)
if (old == new || rtx_equal_p (old, new))
return 1;
- if (num_changes >= MAX_CHANGE_LOCS
- || (in_group == 0 && num_changes != 0))
+ if (in_group == 0 && num_changes != 0)
abort ();
*loc = new;
/* Save the information describing this change. */
- change_objects[num_changes] = object;
- change_locs[num_changes] = loc;
- change_olds[num_changes] = old;
+ if (num_changes >= changes_allocated)
+ {
+ if (changes_allocated == 0)
+ /* This value allows for repeated substitutions inside complex
+ indexed addresses, or changes in up to 5 insns. */
+ changes_allocated = MAX_RECOG_OPERANDS * 5;
+ else
+ changes_allocated *= 2;
+
+ changes =
+ (change_t*) xrealloc (changes,
+ sizeof (change_t) * changes_allocated);
+ }
+
+ changes[num_changes].object = object;
+ changes[num_changes].loc = loc;
+ changes[num_changes].old = old;
if (object && GET_CODE (object) != MEM)
{
/* Set INSN_CODE to force rerecognition of insn. Save old code in
case invalid. */
- change_old_codes[num_changes] = INSN_CODE (object);
+ changes[num_changes].old_code = INSN_CODE (object);
INSN_CODE (object) = -1;
}
@@ -204,6 +289,33 @@ validate_change (object, loc, new, in_group)
return apply_change_group ();
}
+/* This subroutine of apply_change_group verifies whether the changes to INSN
+ were valid; i.e. whether INSN can still be recognized. */
+
+static int
+insn_invalid_p (insn)
+ rtx insn;
+{
+ int icode = recog_memoized (insn);
+ int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
+
+ if (is_asm && ! check_asm_operands (PATTERN (insn)))
+ return 1;
+ if (! is_asm && icode < 0)
+ return 1;
+
+ /* After reload, verify that all constraints are satisfied. */
+ if (reload_completed)
+ {
+ extract_insn (insn);
+
+ if (! constrain_operands (1))
+ return 1;
+ }
+
+ return 0;
+}
+
/* Apply a group of changes previously issued with `validate_change'.
Return 1 if all changes are valid, zero otherwise. */
@@ -219,12 +331,11 @@ apply_change_group ()
given a MEM and it still is a valid address, or if this is in insn
and it is recognized. In the latter case, if reload has completed,
we also require that the operands meet the constraints for
- the insn. We do not allow modifying an ASM_OPERANDS after reload
- has completed because verifying the constraints is too difficult. */
+ the insn. */
for (i = 0; i < num_changes; i++)
{
- rtx object = change_objects[i];
+ rtx object = changes[i].object;
if (object == 0)
continue;
@@ -234,13 +345,7 @@ apply_change_group ()
if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
break;
}
- else if ((recog_memoized (object) < 0
- && (asm_noperands (PATTERN (object)) < 0
- || ! check_asm_operands (PATTERN (object))
- || reload_completed))
- || (reload_completed
- && (insn_extract (object),
- ! constrain_operands (INSN_CODE (object), 1))))
+ else if (insn_invalid_p (object))
{
rtx pat = PATTERN (object);
@@ -319,9 +424,9 @@ cancel_changes (num)
they were made. */
for (i = num_changes - 1; i >= num; i--)
{
- *change_locs[i] = change_olds[i];
- if (change_objects[i] && GET_CODE (change_objects[i]) != MEM)
- INSN_CODE (change_objects[i]) = change_old_codes[i];
+ *changes[i].loc = changes[i].old;
+ if (changes[i].object && GET_CODE (changes[i].object) != MEM)
+ INSN_CODE (changes[i].object) = changes[i].old_code;
}
num_changes = num;
}
@@ -445,9 +550,8 @@ validate_replace_rtx_1 (loc, from, to, object)
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
- MEM_VOLATILE_P (new) = MEM_VOLATILE_P (to);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (to);
- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (to);
+ MEM_COPY_ATTRIBUTES (new, to);
validate_change (object, loc, new, 1);
return;
}
@@ -472,11 +576,19 @@ validate_replace_rtx_1 (loc, from, to, object)
#ifdef HAVE_extzv
if (code == ZERO_EXTRACT)
- wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
+ {
+ wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
+ if (wanted_mode == VOIDmode)
+ wanted_mode = word_mode;
+ }
#endif
#ifdef HAVE_extv
if (code == SIGN_EXTRACT)
- wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
+ {
+ wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
+ if (wanted_mode == VOIDmode)
+ wanted_mode = word_mode;
+ }
#endif
/* If we have a narrower mode, we can do something. */
@@ -497,8 +609,7 @@ validate_replace_rtx_1 (loc, from, to, object)
newmem = gen_rtx_MEM (wanted_mode,
plus_constant (XEXP (to, 0), offset));
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (to);
- MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (to);
- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (to);
+ MEM_COPY_ATTRIBUTES (newmem, to);
validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
validate_change (object, &XEXP (x, 0), newmem, 1);
@@ -538,6 +649,16 @@ validate_replace_rtx (from, to, insn)
return apply_change_group ();
}
+/* Try replacing every occurrence of FROM in INSN with TO. After all
+ changes have been made, validate by seeing if INSN is still valid. */
+
+void
+validate_replace_rtx_group (from, to, insn)
+ rtx from, to, insn;
+{
+ validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
+}
+
/* Try replacing every occurrence of FROM in INSN with TO, avoiding
SET_DESTs. After all changes have been made, validate by seeing if
INSN is still valid. */
@@ -970,6 +1091,12 @@ immediate_operand (op, mode)
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
return 0;
+ /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
+ result in 0/1. It seems a safe assumption that this is
+ in range for everyone. */
+ if (GET_CODE (op) == CONSTANT_P_RTX)
+ return 1;
+
return (CONSTANT_P (op)
&& (GET_MODE (op) == mode || mode == VOIDmode
|| GET_MODE (op) == VOIDmode)
@@ -984,7 +1111,7 @@ immediate_operand (op, mode)
int
const_int_operand (op, mode)
register rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return GET_CODE (op) == CONST_INT;
}
@@ -1079,7 +1206,7 @@ push_operand (op, mode)
if (GET_CODE (op) != MEM)
return 0;
- if (GET_MODE (op) != mode)
+ if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
op = XEXP (op, 0);
@@ -1090,6 +1217,31 @@ push_operand (op, mode)
return XEXP (op, 0) == stack_pointer_rtx;
}
+/* Return 1 if OP is a valid operand that stands for popping a
+ value of mode MODE off the stack.
+
+ The main use of this function is as a predicate in match_operand
+ expressions in the machine description. */
+
+int
+pop_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) != MEM)
+ return 0;
+
+ if (mode != VOIDmode && GET_MODE (op) != mode)
+ return 0;
+
+ op = XEXP (op, 0);
+
+ if (GET_CODE (op) != STACK_POP_CODE)
+ return 0;
+
+ return XEXP (op, 0) == stack_pointer_rtx;
+}
+
/* Return 1 if ADDR is a valid memory address for mode MODE. */
int
@@ -1273,7 +1425,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
rtx body;
rtx *operands;
rtx **operand_locs;
- char **constraints;
+ const char **constraints;
enum machine_mode *modes;
{
register int i;
@@ -1400,6 +1552,218 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
return template;
}
+
+/* Check if an asm_operand matches it's constraints.
+ Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
+
+int
+asm_operand_ok (op, constraint)
+ rtx op;
+ const char *constraint;
+{
+ int result = 0;
+
+ /* Use constrain_operands after reload. */
+ if (reload_completed)
+ abort ();
+
+ while (*constraint)
+ {
+ switch (*constraint++)
+ {
+ case '=':
+ case '+':
+ case '*':
+ case '%':
+ case '?':
+ case '!':
+ case '#':
+ case '&':
+ case ',':
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* For best results, our caller should have given us the
+ proper matching constraint, but we can't actually fail
+ the check if they didn't. Indicate that results are
+ inconclusive. */
+ result = -1;
+ break;
+
+ case 'p':
+ if (address_operand (op, VOIDmode))
+ return 1;
+ break;
+
+ case 'm':
+ case 'V': /* non-offsettable */
+ if (memory_operand (op, VOIDmode))
+ return 1;
+ break;
+
+ case 'o': /* offsettable */
+ if (offsettable_nonstrict_memref_p (op))
+ return 1;
+ break;
+
+ case '<':
+ /* ??? Before flow, auto inc/dec insns are not supposed to exist,
+ excepting those that expand_call created. Further, on some
+ machines which do not have generalized auto inc/dec, an inc/dec
+ is not a memory_operand.
+
+ Match any memory and hope things are resolved after reload. */
+
+ if (GET_CODE (op) == MEM
+ && (1
+ || GET_CODE (XEXP (op, 0)) == PRE_DEC
+ || GET_CODE (XEXP (op, 0)) == POST_DEC))
+ return 1;
+ break;
+
+ case '>':
+ if (GET_CODE (op) == MEM
+ && (1
+ || GET_CODE (XEXP (op, 0)) == PRE_INC
+ || GET_CODE (XEXP (op, 0)) == POST_INC))
+ return 1;
+ break;
+
+ case 'E':
+#ifndef REAL_ARITHMETIC
+ /* Match any floating double constant, but only if
+ we can examine the bits of it reliably. */
+ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
+ || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
+ && GET_MODE (op) != VOIDmode && ! flag_pretend_float)
+ break;
+#endif
+ /* FALLTHRU */
+
+ case 'F':
+ if (GET_CODE (op) == CONST_DOUBLE)
+ return 1;
+ break;
+
+ case 'G':
+ if (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'G'))
+ return 1;
+ break;
+ case 'H':
+ if (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'H'))
+ return 1;
+ break;
+
+ case 's':
+ if (GET_CODE (op) == CONST_INT
+ || (GET_CODE (op) == CONST_DOUBLE
+ && GET_MODE (op) == VOIDmode))
+ break;
+ /* FALLTHRU */
+
+ case 'i':
+ if (CONSTANT_P (op)
+#ifdef LEGITIMATE_PIC_OPERAND_P
+ && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
+#endif
+ )
+ return 1;
+ break;
+
+ case 'n':
+ if (GET_CODE (op) == CONST_INT
+ || (GET_CODE (op) == CONST_DOUBLE
+ && GET_MODE (op) == VOIDmode))
+ return 1;
+ break;
+
+ case 'I':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))
+ return 1;
+ break;
+ case 'J':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'))
+ return 1;
+ break;
+ case 'K':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
+ return 1;
+ break;
+ case 'L':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'))
+ return 1;
+ break;
+ case 'M':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
+ return 1;
+ break;
+ case 'N':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'N'))
+ return 1;
+ break;
+ case 'O':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'))
+ return 1;
+ break;
+ case 'P':
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'))
+ return 1;
+ break;
+
+ case 'X':
+ return 1;
+
+ case 'g':
+ if (general_operand (op, VOIDmode))
+ return 1;
+ break;
+
+#ifdef EXTRA_CONSTRAINT
+ case 'Q':
+ if (EXTRA_CONSTRAINT (op, 'Q'))
+ return 1;
+ break;
+ case 'R':
+ if (EXTRA_CONSTRAINT (op, 'R'))
+ return 1;
+ break;
+ case 'S':
+ if (EXTRA_CONSTRAINT (op, 'S'))
+ return 1;
+ break;
+ case 'T':
+ if (EXTRA_CONSTRAINT (op, 'T'))
+ return 1;
+ break;
+ case 'U':
+ if (EXTRA_CONSTRAINT (op, 'U'))
+ return 1;
+ break;
+#endif
+
+ case 'r':
+ default:
+ if (GET_MODE (op) == BLKmode)
+ break;
+ if (register_operand (op, VOIDmode))
+ return 1;
+ break;
+ }
+ }
+
+ return result;
+}
/* Given an rtx *P, if it is a sum containing an integer constant term,
return the location (type rtx *) of the pointer to that constant term.
@@ -1551,11 +1915,12 @@ offsettable_address_p (strictp, mode, y)
int
mode_dependent_address_p (addr)
- rtx addr;
+ rtx addr ATTRIBUTE_UNUSED; /* Maybe used in GO_IF_MODE_DEPENDENT_ADDRESS. */
{
GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
return 0;
- win:
+ /* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS. */
+ win: ATTRIBUTE_UNUSED_LABEL
return 1;
}
@@ -1578,7 +1943,8 @@ mode_independent_operand (op, mode)
addr = XEXP (op, 0);
GO_IF_MODE_DEPENDENT_ADDRESS (addr, lose);
return 1;
- lose:
+ /* Label `lose' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS. */
+ lose: ATTRIBUTE_UNUSED_LABEL
return 0;
}
@@ -1629,11 +1995,206 @@ adj_offsettable_operand (op, offset)
abort ();
}
+/* Analyze INSN and compute the variables recog_n_operands, recog_n_dups,
+ recog_n_alternatives, recog_operand, recog_operand_loc, recog_constraints,
+ recog_operand_mode, recog_dup_loc and recog_dup_num.
+ If REGISTER_CONSTRAINTS is not defined, also compute
+ recog_operand_address_p. */
+void
+extract_insn (insn)
+ rtx insn;
+{
+ int i;
+ int icode;
+ int noperands;
+ rtx body = PATTERN (insn);
+
+ recog_n_operands = 0;
+ recog_n_alternatives = 0;
+ recog_n_dups = 0;
+
+ switch (GET_CODE (body))
+ {
+ case USE:
+ case CLOBBER:
+ case ASM_INPUT:
+ case ADDR_VEC:
+ case ADDR_DIFF_VEC:
+ return;
+
+ case SET:
+ case PARALLEL:
+ case ASM_OPERANDS:
+ recog_n_operands = noperands = asm_noperands (body);
+ if (noperands >= 0)
+ {
+ /* This insn is an `asm' with operands. */
+
+ /* expand_asm_operands makes sure there aren't too many operands. */
+ if (noperands > MAX_RECOG_OPERANDS)
+ abort ();
+
+ /* Now get the operand values and constraints out of the insn. */
+ decode_asm_operands (body, recog_operand, recog_operand_loc,
+ recog_constraints, recog_operand_mode);
+ if (noperands > 0)
+ {
+ const char *p = recog_constraints[0];
+ recog_n_alternatives = 1;
+ while (*p)
+ recog_n_alternatives += (*p++ == ',');
+ }
+#ifndef REGISTER_CONSTRAINTS
+ bzero (recog_operand_address_p, sizeof recog_operand_address_p);
+#endif
+ break;
+ }
+
+ /* FALLTHROUGH */
+
+ default:
+ /* Ordinary insn: recognize it, get the operands via insn_extract
+ and get the constraints. */
+
+ icode = recog_memoized (insn);
+ if (icode < 0)
+ fatal_insn_not_found (insn);
+
+ recog_n_operands = noperands = insn_n_operands[icode];
+ recog_n_alternatives = insn_n_alternatives[icode];
+ recog_n_dups = insn_n_dups[icode];
+
+ insn_extract (insn);
+
+ for (i = 0; i < noperands; i++)
+ {
+#ifdef REGISTER_CONSTRAINTS
+ recog_constraints[i] = insn_operand_constraint[icode][i];
+#else
+ recog_operand_address_p[i] = insn_operand_address_p[icode][i];
+#endif
+ recog_operand_mode[i] = insn_operand_mode[icode][i];
+ }
+ }
+ for (i = 0; i < noperands; i++)
+ recog_op_type[i] = (recog_constraints[i][0] == '=' ? OP_OUT
+ : recog_constraints[i][0] == '+' ? OP_INOUT
+ : OP_IN);
+
+ if (recog_n_alternatives > MAX_RECOG_ALTERNATIVES)
+ abort ();
+}
+
+/* After calling extract_insn, you can use this function to extract some
+ information from the constraint strings into a more usable form.
+ The collected data is stored in recog_op_alt. */
+void
+preprocess_constraints ()
+{
+ int i;
+
+ for (i = 0; i < recog_n_operands; i++)
+ {
+ int j;
+ struct operand_alternative *op_alt;
+ const char *p = recog_constraints[i];
+
+ op_alt = recog_op_alt[i];
+
+ for (j = 0; j < recog_n_alternatives; j++)
+ {
+ op_alt[j].class = NO_REGS;
+ op_alt[j].constraint = p;
+ op_alt[j].matches = -1;
+ op_alt[j].matched = -1;
+
+ if (*p == '\0' || *p == ',')
+ {
+ op_alt[j].anything_ok = 1;
+ continue;
+ }
+
+ for (;;)
+ {
+ char c = *p++;
+ if (c == '#')
+ do
+ c = *p++;
+ while (c != ',' && c != '\0');
+ if (c == ',' || c == '\0')
+ break;
+
+ switch (c)
+ {
+ case '=': case '+': case '*': case '%':
+ case 'E': case 'F': case 'G': case 'H':
+ case 's': case 'i': case 'n':
+ case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P':
+#ifdef EXTRA_CONSTRAINT
+ case 'Q': case 'R': case 'S': case 'T': case 'U':
+#endif
+ /* These don't say anything we care about. */
+ break;
+
+ case '?':
+ op_alt[j].reject += 6;
+ break;
+ case '!':
+ op_alt[j].reject += 600;
+ break;
+ case '&':
+ op_alt[j].earlyclobber = 1;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ op_alt[j].matches = c - '0';
+ op_alt[op_alt[j].matches].matched = i;
+ break;
+
+ case 'm':
+ op_alt[j].memory_ok = 1;
+ break;
+ case '<':
+ op_alt[j].decmem_ok = 1;
+ break;
+ case '>':
+ op_alt[j].incmem_ok = 1;
+ break;
+ case 'V':
+ op_alt[j].nonoffmem_ok = 1;
+ break;
+ case 'o':
+ op_alt[j].offmem_ok = 1;
+ break;
+ case 'X':
+ op_alt[j].anything_ok = 1;
+ break;
+
+ case 'p':
+ op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) BASE_REG_CLASS];
+ break;
+
+ case 'g': case 'r':
+ op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) GENERAL_REGS];
+ break;
+
+ default:
+ op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char)c)];
+ break;
+ }
+ }
+ }
+ }
+}
+
#ifdef REGISTER_CONSTRAINTS
-/* Check the operands of an insn (found in recog_operands)
- against the insn's operand constraints (found via INSN_CODE_NUM)
+/* Check the operands of an insn against the insn's operand constraints
and return 1 if they are valid.
+ The information about the insn's operands, constraints, operand modes
+ etc. is obtained from the global variables set up by extract_insn.
WHICH_ALTERNATIVE is set to a number which indicates which
alternative of constraints was matched: 0 for the first alternative,
@@ -1663,44 +2224,39 @@ struct funny_match
};
int
-constrain_operands (insn_code_num, strict)
- int insn_code_num;
+constrain_operands (strict)
int strict;
{
- char *constraints[MAX_RECOG_OPERANDS];
+ const char *constraints[MAX_RECOG_OPERANDS];
int matching_operands[MAX_RECOG_OPERANDS];
- enum op_type {OP_IN, OP_OUT, OP_INOUT} op_types[MAX_RECOG_OPERANDS];
int earlyclobber[MAX_RECOG_OPERANDS];
register int c;
- int noperands = insn_n_operands[insn_code_num];
struct funny_match funny_match[MAX_RECOG_OPERANDS];
int funny_match_index;
- int nalternatives = insn_n_alternatives[insn_code_num];
- if (noperands == 0 || nalternatives == 0)
+ if (recog_n_operands == 0 || recog_n_alternatives == 0)
return 1;
- for (c = 0; c < noperands; c++)
+ for (c = 0; c < recog_n_operands; c++)
{
- constraints[c] = insn_operand_constraint[insn_code_num][c];
+ constraints[c] = recog_constraints[c];
matching_operands[c] = -1;
- op_types[c] = OP_IN;
}
which_alternative = 0;
- while (which_alternative < nalternatives)
+ while (which_alternative < recog_n_alternatives)
{
register int opno;
int lose = 0;
funny_match_index = 0;
- for (opno = 0; opno < noperands; opno++)
+ for (opno = 0; opno < recog_n_operands; opno++)
{
register rtx op = recog_operand[opno];
enum machine_mode mode = GET_MODE (op);
- register char *p = constraints[opno];
+ register const char *p = constraints[opno];
int offset = 0;
int win = 0;
int val;
@@ -1732,6 +2288,8 @@ constrain_operands (insn_code_num, strict)
case '!':
case '*':
case '%':
+ case '=':
+ case '+':
break;
case '#':
@@ -1741,23 +2299,12 @@ constrain_operands (insn_code_num, strict)
p++;
break;
- case '=':
- op_types[opno] = OP_OUT;
- break;
-
- case '+':
- op_types[opno] = OP_INOUT;
- break;
-
case '&':
earlyclobber[opno] = 1;
break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
/* This operand must be the same as a previous one.
This kind of constraint is used for instructions such
as add when they take only two operands.
@@ -1769,8 +2316,19 @@ constrain_operands (insn_code_num, strict)
if (strict < 0)
val = 1;
else
- val = operands_match_p (recog_operand[c - '0'],
- recog_operand[opno]);
+ {
+ rtx op1 = recog_operand[c - '0'];
+ rtx op2 = recog_operand[opno];
+
+ /* A unary operator may be accepted by the predicate,
+ but it is irrelevant for matching constraints. */
+ if (GET_RTX_CLASS (GET_CODE (op1)) == '1')
+ op1 = XEXP (op1, 0);
+ if (GET_RTX_CLASS (GET_CODE (op2)) == '1')
+ op2 = XEXP (op2, 0);
+
+ val = operands_match_p (op1, op2);
+ }
matching_operands[opno] = c - '0';
matching_operands[c - '0'] = opno;
@@ -1793,8 +2351,8 @@ constrain_operands (insn_code_num, strict)
strictly valid, i.e., that all pseudos requiring hard regs
have gotten them. */
if (strict <= 0
- || (strict_memory_address_p
- (insn_operand_mode[insn_code_num][opno], op)))
+ || (strict_memory_address_p (recog_operand_mode[opno],
+ op)))
win = 1;
break;
@@ -1974,18 +2532,18 @@ constrain_operands (insn_code_num, strict)
operand. */
if (strict > 0)
- for (eopno = 0; eopno < noperands; eopno++)
+ for (eopno = 0; eopno < recog_n_operands; eopno++)
/* Ignore earlyclobber operands now in memory,
because we would often report failure when we have
two memory operands, one of which was formerly a REG. */
if (earlyclobber[eopno]
&& GET_CODE (recog_operand[eopno]) == REG)
- for (opno = 0; opno < noperands; opno++)
+ for (opno = 0; opno < recog_n_operands; opno++)
if ((GET_CODE (recog_operand[opno]) == MEM
- || op_types[opno] != OP_OUT)
+ || recog_op_type[opno] != OP_OUT)
&& opno != eopno
/* Ignore things like match_operator operands. */
- && *insn_operand_constraint[insn_code_num][opno] != 0
+ && *recog_constraints[opno] != 0
&& ! (matching_operands[opno] == eopno
&& operands_match_p (recog_operand[opno],
recog_operand[eopno]))
@@ -2011,7 +2569,7 @@ constrain_operands (insn_code_num, strict)
/* If we are about to reject this, but we are not to test strictly,
try a very loose test. Only return failure if it fails also. */
if (strict == 0)
- return constrain_operands (insn_code_num, -1);
+ return constrain_operands (-1);
else
return 0;
}
@@ -2047,3 +2605,84 @@ reg_fits_class_p (operand, class, offset, mode)
}
#endif /* REGISTER_CONSTRAINTS */
+
+/* Do the splitting of insns in the block B. Only try to actually split if
+ DO_SPLIT is true; otherwise, just remove nops. */
+
+void
+split_block_insns (b, do_split)
+ int b;
+ int do_split;
+{
+ rtx insn, next;
+
+ for (insn = BLOCK_HEAD (b);; insn = next)
+ {
+ rtx set;
+
+ /* Can't use `next_real_insn' because that
+ might go across CODE_LABELS and short-out basic blocks. */
+ next = NEXT_INSN (insn);
+ if (GET_CODE (insn) != INSN)
+ {
+ if (insn == BLOCK_END (b))
+ break;
+
+ continue;
+ }
+
+ /* Don't split no-op move insns. These should silently disappear
+ later in final. Splitting such insns would break the code
+ that handles REG_NO_CONFLICT blocks. */
+ set = single_set (insn);
+ if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set)))
+ {
+ if (insn == BLOCK_END (b))
+ break;
+
+ /* Nops get in the way while scheduling, so delete them now if
+ register allocation has already been done. It is too risky
+ to try to do this before register allocation, and there are
+ unlikely to be very many nops then anyways. */
+ if (reload_completed)
+ {
+
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
+
+ continue;
+ }
+
+ if (do_split)
+ {
+ /* Split insns here to get max fine-grain parallelism. */
+ rtx first = PREV_INSN (insn);
+ rtx notes = REG_NOTES (insn);
+ rtx last = try_split (PATTERN (insn), insn, 1);
+
+ if (last != insn)
+ {
+ /* try_split returns the NOTE that INSN became. */
+ first = NEXT_INSN (first);
+#ifdef INSN_SCHEDULING
+ update_flow_info (notes, first, last, insn);
+#endif
+ PUT_CODE (insn, NOTE);
+ NOTE_SOURCE_FILE (insn) = 0;
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ if (insn == BLOCK_HEAD (b))
+ BLOCK_HEAD (b) = first;
+ if (insn == BLOCK_END (b))
+ {
+ BLOCK_END (b) = last;
+ break;
+ }
+ }
+ }
+
+ if (insn == BLOCK_END (b))
+ break;
+ }
+}
diff --git a/contrib/gcc/recog.h b/contrib/gcc/recog.h
index 6e6bb06..c8a6598 100644
--- a/contrib/gcc/recog.h
+++ b/contrib/gcc/recog.h
@@ -1,5 +1,5 @@
/* Declarations for interface to insn recognizer and insn-output.c.
- Copyright (C) 1987, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,21 +18,72 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "gansidecl.h"
+/* Random number that should be large enough for all purposes. */
+#define MAX_RECOG_ALTERNATIVES 30
+
+/* Types of operands. */
+enum op_type {
+ OP_IN,
+ OP_OUT,
+ OP_INOUT
+};
+
+struct operand_alternative
+{
+ /* Pointer to the beginning of the constraint string for this alternative,
+ for easier access by alternative number. */
+ const char *constraint;
+
+ /* The register class valid for this alternative (possibly NO_REGS). */
+ enum reg_class class;
+
+ /* "Badness" of this alternative, computed from number of '?' and '!'
+ characters in the constraint string. */
+ unsigned int reject;
+
+ /* -1 if no matching constraint was found, or an operand number. */
+ int matches;
+ /* The same information, but reversed: -1 if this operand is not
+ matched by any other, or the operand number of the operand that
+ matches this one. */
+ int matched;
+
+ /* Nonzero if '&' was found in the constraint string. */
+ unsigned int earlyclobber:1;
+ /* Nonzero if 'm' was found in the constraint string. */
+ unsigned int memory_ok:1;
+ /* Nonzero if 'o' was found in the constraint string. */
+ unsigned int offmem_ok:1;
+ /* Nonzero if 'V' was found in the constraint string. */
+ unsigned int nonoffmem_ok:1;
+ /* Nonzero if '<' was found in the constraint string. */
+ unsigned int decmem_ok:1;
+ /* Nonzero if '>' was found in the constraint string. */
+ unsigned int incmem_ok:1;
+ /* Nonzero if 'X' was found in the constraint string, or if the constraint
+ string for this alternative was empty. */
+ unsigned int anything_ok:1;
+};
+
extern void init_recog PROTO((void));
extern void init_recog_no_volatile PROTO((void));
extern int recog_memoized PROTO((rtx));
extern int check_asm_operands PROTO((rtx));
+extern int asm_operand_ok PROTO((rtx, const char *));
extern int validate_change PROTO((rtx, rtx *, rtx, int));
extern int apply_change_group PROTO((void));
extern int num_validated_changes PROTO((void));
extern void cancel_changes PROTO((int));
-extern int constrain_operands PROTO((int, int));
+extern int constrain_operands PROTO((int));
extern int memory_address_p PROTO((enum machine_mode, rtx));
extern int strict_memory_address_p PROTO((enum machine_mode, rtx));
extern int validate_replace_rtx PROTO((rtx, rtx, rtx));
+extern void validate_replace_rtx_group PROTO((rtx, rtx, rtx));
extern int validate_replace_src PROTO((rtx, rtx, rtx));
+#ifdef HAVE_cc0
+extern int next_insn_tests_no_inequality PROTO ((rtx));
+#endif
extern int reg_fits_class_p PROTO((rtx, enum reg_class, int,
enum machine_mode));
extern rtx *find_single_use PROTO((rtx, rtx, rtx *));
@@ -43,10 +94,11 @@ extern int register_operand PROTO((rtx, enum machine_mode));
extern int scratch_operand PROTO((rtx, enum machine_mode));
extern int immediate_operand PROTO((rtx, enum machine_mode));
extern int const_int_operand PROTO((rtx, enum machine_mode));
-extern int cosnt_double_operand PROTO((rtx, enum machine_mode));
+extern int const_double_operand PROTO((rtx, enum machine_mode));
extern int nonimmediate_operand PROTO((rtx, enum machine_mode));
extern int nonmemory_operand PROTO((rtx, enum machine_mode));
extern int push_operand PROTO((rtx, enum machine_mode));
+extern int pop_operand PROTO((rtx, enum machine_mode));
extern int memory_operand PROTO((rtx, enum machine_mode));
extern int indirect_operand PROTO((rtx, enum machine_mode));
extern int mode_independent_operand PROTO((rtx, enum machine_mode));
@@ -60,10 +112,16 @@ extern int mode_dependent_address_p PROTO((rtx));
extern int recog PROTO((rtx, rtx, int *));
extern void add_clobbers PROTO((rtx, int));
extern void insn_extract PROTO((rtx));
+extern void extract_insn PROTO((rtx));
+extern void preprocess_constraints PROTO((void));
/* Nonzero means volatile operands are recognized. */
extern int volatile_ok;
+/* Set by constrain_operands to the number of the alternative that
+ matched. */
+extern int which_alternative;
+
/* The following vectors hold the results from insn_extract. */
/* Indexed by N, gives value of operand N. */
@@ -80,6 +138,35 @@ extern rtx *recog_dup_loc[];
Nth duplicate-appearance of an operand. */
extern char recog_dup_num[];
+/* The next variables are set up by extract_insn. */
+
+/* The number of operands of the insn. */
+extern int recog_n_operands;
+
+/* The number of MATCH_DUPs in the insn. */
+extern int recog_n_dups;
+
+/* The number of alternatives in the constraints for the insn. */
+extern int recog_n_alternatives;
+
+/* Indexed by N, gives the mode of operand N. */
+extern enum machine_mode recog_operand_mode[];
+
+/* Indexed by N, gives the constraint string for operand N. */
+extern const char *recog_constraints[];
+
+/* Indexed by N, gives the type (in, out, inout) for operand N. */
+extern enum op_type recog_op_type[];
+
+#ifndef REGISTER_CONSTRAINTS
+/* Indexed by N, nonzero if operand N should be an address. */
+extern char recog_operand_address_p[];
+#endif
+
+/* Contains a vector of operand_alternative structures for every operand.
+ Set up by preprocess_constraints. */
+extern struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES];
+
/* Access the output function for CODE. */
#define OUT_FCN(CODE) (*insn_outfun[(int) (CODE)])
@@ -89,9 +176,9 @@ extern char recog_dup_num[];
/* These are vectors indexed by insn-code. Details in genoutput.c. */
-extern char *const insn_template[];
+extern const char *const insn_template[];
-extern char *(*const insn_outfun[]) ();
+extern const char *(*const insn_outfun[]) PROTO ((rtx *, rtx));
extern const int insn_n_operands[];
@@ -105,7 +192,7 @@ extern const int insn_n_alternatives[];
and second by the operand number. Details in genoutput.c. */
#ifdef REGISTER_CONSTRAINTS /* Avoid undef sym in certain broken linkers. */
-extern char *const insn_operand_constraint[][MAX_RECOG_OPERANDS];
+extern const char *const insn_operand_constraint[][MAX_RECOG_OPERANDS];
#endif
#ifndef REGISTER_CONSTRAINTS /* Avoid undef sym in certain broken linkers. */
@@ -116,6 +203,6 @@ extern const enum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS];
extern const char insn_operand_strict_low[][MAX_RECOG_OPERANDS];
-extern int (*const insn_operand_predicate[][MAX_RECOG_OPERANDS]) ();
+extern int (*const insn_operand_predicate[][MAX_RECOG_OPERANDS]) PROTO ((rtx, enum machine_mode));
-extern char * insn_name[];
+extern const char * insn_name[];
diff --git a/contrib/gcc/reg-stack.c b/contrib/gcc/reg-stack.c
index d92a1f9..dd4a87e 100644
--- a/contrib/gcc/reg-stack.c
+++ b/contrib/gcc/reg-stack.c
@@ -1,5 +1,5 @@
/* Register to Stack convert for GNU compiler.
- Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -74,13 +74,6 @@ Boston, MA 02111-1307, USA. */
deleted and recreated from scratch. REG_DEAD is never created for a
SET_DEST, only REG_UNUSED.
- Before life analysis, the mode of each insn is set based on whether
- or not any stack registers are mentioned within that insn. VOIDmode
- means that no regs are mentioned anyway, and QImode means that at
- least one pattern within the insn mentions stack registers. This
- information is valid until after reg_to_stack returns, and is used
- from jump_optimize.
-
* asm_operands:
There are several rules on the usage of stack-like regs in
@@ -166,7 +159,9 @@ Boston, MA 02111-1307, USA. */
#include "hard-reg-set.h"
#include "flags.h"
#include "insn-flags.h"
+#include "recog.h"
#include "toplev.h"
+#include "varray.h"
#ifdef STACK_REGS
@@ -218,6 +213,14 @@ static HARD_REG_SET *block_out_reg_set;
add insns within a block. */
static int *block_number;
+/* We use this array to cache info about insns, because otherwise we
+ spend too much time in stack_regs_mentioned_p.
+
+ Indexed by insn UIDs. A value of zero is uninitialized, one indicates
+ the insn uses stack registers, two indicates the insn does not use
+ stack registers. */
+static varray_type stack_regs_mentioned_data;
+
/* This is the register file for all register after conversion */
static rtx
FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE];
@@ -228,9 +231,23 @@ static rtx
/* Get the basic block number of an insn. See note at block_number
definition are validity of this information. */
-#define BLOCK_NUM(INSN) \
- ((INSN_UID (INSN) > max_uid) \
- ? (abort() , -1) : block_number[INSN_UID (INSN)])
+static int BLOCK_NUM PROTO((rtx));
+
+#ifdef __GNUC__
+__inline__
+#endif
+static int
+BLOCK_NUM(insn)
+ rtx insn;
+{
+ int tmp = INSN_UID (insn);
+ if (tmp > max_uid)
+ abort ();
+ tmp = block_number[tmp];
+ if (tmp < 0)
+ abort ();
+ return tmp;
+}
extern rtx forced_labels;
@@ -241,14 +258,11 @@ static void straighten_stack PROTO((rtx, stack));
static void pop_stack PROTO((stack, int));
static void record_label_references PROTO((rtx, rtx));
static rtx *get_true_reg PROTO((rtx *));
-static int constrain_asm_operands PROTO((int, rtx *, char **, int *,
- enum reg_class *));
-static void record_asm_reg_life PROTO((rtx,stack, rtx *, char **,
- int, int));
+static void record_asm_reg_life PROTO((rtx, stack));
static void record_reg_life_pat PROTO((rtx, HARD_REG_SET *,
HARD_REG_SET *, int));
-static void get_asm_operand_lengths PROTO((rtx, int, int *, int *));
+static int get_asm_operand_n_inputs PROTO((rtx));
static void record_reg_life PROTO((rtx, int, stack));
static void find_blocks PROTO((rtx));
static rtx stack_result PROTO((tree));
@@ -263,8 +277,7 @@ static void move_for_stack_reg PROTO((rtx, stack, rtx));
static void swap_rtx_condition PROTO((rtx));
static void compare_for_stack_reg PROTO((rtx, stack, rtx));
static void subst_stack_regs_pat PROTO((rtx, stack, rtx));
-static void subst_asm_stack_regs PROTO((rtx, stack, rtx *, rtx **,
- char **, int, int));
+static void subst_asm_stack_regs PROTO((rtx, stack));
static void subst_stack_regs PROTO((rtx, stack));
static void change_stack PROTO((rtx, stack, stack, rtx (*) ()));
@@ -272,6 +285,47 @@ static void goto_block_pat PROTO((rtx, stack, rtx));
static void convert_regs PROTO((void));
static void print_blocks PROTO((FILE *, rtx, rtx));
static void dump_stack_info PROTO((FILE *));
+static int check_stack_regs_mentioned PROTO((rtx insn));
+
+/* Initialize stack_regs_mentioned_data for INSN (growing the virtual array
+ if needed. Return nonzero if INSN mentions stacked registers. */
+
+static int
+check_stack_regs_mentioned (insn)
+ rtx insn;
+{
+ unsigned int uid = INSN_UID (insn);
+ if (uid >= VARRAY_SIZE (stack_regs_mentioned_data))
+ /* Allocate some extra size to avoid too many reallocs, but
+ do not grow exponentially. */
+ VARRAY_GROW (stack_regs_mentioned_data, uid + uid / 20);
+ if (stack_regs_mentioned_p (PATTERN (insn)))
+ {
+ VARRAY_CHAR (stack_regs_mentioned_data, uid) = 1;
+ return 1;
+ }
+ else
+ VARRAY_CHAR (stack_regs_mentioned_data, uid) = 2;
+ return 0;
+}
+
+/* Return nonzero if INSN mentions stacked registers, else return
+ zero. */
+
+int
+stack_regs_mentioned (insn)
+ rtx insn;
+{
+ unsigned int uid;
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ return 0;
+ uid = INSN_UID (insn);
+ if (uid >= VARRAY_SIZE (stack_regs_mentioned_data)
+ || ! VARRAY_CHAR (stack_regs_mentioned_data, uid))
+ return (check_stack_regs_mentioned (insn));
+ return VARRAY_CHAR (stack_regs_mentioned_data, uid) == 1;
+}
+
/* Mark all registers needed for this pattern. */
@@ -401,6 +455,10 @@ reg_to_stack (first, file)
enum machine_mode mode;
HARD_REG_SET stackentry;
+ max_uid = get_max_uid ();
+ VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1,
+ "stack_regs_mentioned cache");
+
CLEAR_HARD_REG_SET (stackentry);
{
@@ -461,7 +519,7 @@ reg_to_stack (first, file)
&& stack_regs_mentioned_p (PATTERN (insn)))
{
stack_reg_seen = 1;
- PUT_MODE (insn, QImode);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 1;
/* Note any register passing parameters. */
@@ -471,7 +529,7 @@ reg_to_stack (first, file)
&stackentry, 1);
}
else
- PUT_MODE (insn, VOIDmode);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
if (code == CODE_LABEL)
LABEL_REFS (insn) = insn; /* delete old chain */
@@ -485,7 +543,10 @@ reg_to_stack (first, file)
anything to convert. */
if (! stack_reg_seen)
- return;
+ {
+ VARRAY_FREE (stack_regs_mentioned_data);
+ return;
+ }
/* If there are stack registers, there must be at least one block. */
@@ -505,6 +566,7 @@ reg_to_stack (first, file)
bzero ((char *) block_out_reg_set, blocks * sizeof (HARD_REG_SET));
block_number = (int *) alloca ((max_uid + 1) * sizeof (int));
+ memset (block_number, -1, (max_uid + 1) * sizeof (int));
find_blocks (first);
stack_reg_life_analysis (first, &stackentry);
@@ -520,6 +582,8 @@ reg_to_stack (first, file)
if (optimize)
jump_optimize (first, 2, 0, 0);
+
+ VARRAY_FREE (stack_regs_mentioned_data);
}
/* Check PAT, which is in INSN, for LABEL_REFs. Add INSN to the
@@ -607,297 +671,8 @@ get_true_reg (pat)
}
}
-/* Scan the OPERANDS and OPERAND_CONSTRAINTS of an asm_operands.
- N_OPERANDS is the total number of operands. Return which alternative
- matched, or -1 is no alternative matches.
-
- OPERAND_MATCHES is an array which indicates which operand this
- operand matches due to the constraints, or -1 if no match is required.
- If two operands match by coincidence, but are not required to match by
- the constraints, -1 is returned.
-
- OPERAND_CLASS is an array which indicates the smallest class
- required by the constraints. If the alternative that matches calls
- for some class `class', and the operand matches a subclass of `class',
- OPERAND_CLASS is set to `class' as required by the constraints, not to
- the subclass. If an alternative allows more than one class,
- OPERAND_CLASS is set to the smallest class that is a union of the
- allowed classes. */
-
-static int
-constrain_asm_operands (n_operands, operands, operand_constraints,
- operand_matches, operand_class)
- int n_operands;
- rtx *operands;
- char **operand_constraints;
- int *operand_matches;
- enum reg_class *operand_class;
-{
- char **constraints = (char **) alloca (n_operands * sizeof (char *));
- char *q;
- int this_alternative, this_operand;
- int n_alternatives;
- int j;
-
- for (j = 0; j < n_operands; j++)
- constraints[j] = operand_constraints[j];
-
- /* Compute the number of alternatives in the operands. reload has
- already guaranteed that all operands have the same number of
- alternatives. */
-
- if (n_operands == 0)
- n_alternatives = 0;
- else
- {
- n_alternatives = 1;
- for (q = constraints[0]; *q; q++)
- n_alternatives += (*q == ',');
- }
-
- this_alternative = 0;
- while (this_alternative < n_alternatives)
- {
- int lose = 0;
- int i;
-
- /* No operands match, no narrow class requirements yet. */
- for (i = 0; i < n_operands; i++)
- {
- operand_matches[i] = -1;
- operand_class[i] = NO_REGS;
- }
-
- for (this_operand = 0; this_operand < n_operands; this_operand++)
- {
- rtx op = operands[this_operand];
- enum machine_mode mode = GET_MODE (op);
- char *p = constraints[this_operand];
- int offset = 0;
- int win = 0;
- int c;
-
- if (GET_CODE (op) == SUBREG)
- {
- if (GET_CODE (SUBREG_REG (op)) == REG
- && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
- offset = SUBREG_WORD (op);
- op = SUBREG_REG (op);
- }
-
- /* An empty constraint or empty alternative
- allows anything which matched the pattern. */
- if (*p == 0 || *p == ',')
- win = 1;
-
- while (*p && (c = *p++) != ',')
- switch (c)
- {
- case '=':
- case '+':
- case '?':
- case '&':
- case '!':
- case '*':
- case '%':
- /* Ignore these. */
- break;
-
- case '#':
- /* Ignore rest of this alternative. */
- while (*p && *p != ',') p++;
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- /* This operand must be the same as a previous one.
- This kind of constraint is used for instructions such
- as add when they take only two operands.
-
- Note that the lower-numbered operand is passed first. */
-
- if (operands_match_p (operands[c - '0'],
- operands[this_operand]))
- {
- operand_matches[this_operand] = c - '0';
- win = 1;
- }
- break;
-
- case 'p':
- /* p is used for address_operands. Since this is an asm,
- just to make sure that the operand is valid for Pmode. */
-
- if (strict_memory_address_p (Pmode, op))
- win = 1;
- break;
-
- case 'g':
- /* Anything goes unless it is a REG and really has a hard reg
- but the hard reg is not in the class GENERAL_REGS. */
- if (GENERAL_REGS == ALL_REGS
- || GET_CODE (op) != REG
- || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
- {
- if (GET_CODE (op) == REG)
- operand_class[this_operand]
- = reg_class_subunion[(int) operand_class[this_operand]][(int) GENERAL_REGS];
- win = 1;
- }
- break;
-
- case 'r':
- if (GET_CODE (op) == REG
- && (GENERAL_REGS == ALL_REGS
- || reg_fits_class_p (op, GENERAL_REGS, offset, mode)))
- {
- operand_class[this_operand]
- = reg_class_subunion[(int) operand_class[this_operand]][(int) GENERAL_REGS];
- win = 1;
- }
- break;
-
- case 'X':
- /* This is used for a MATCH_SCRATCH in the cases when we
- don't actually need anything. So anything goes any time. */
- win = 1;
- break;
-
- case 'm':
- if (GET_CODE (op) == MEM)
- win = 1;
- break;
-
- case '<':
- if (GET_CODE (op) == MEM
- && (GET_CODE (XEXP (op, 0)) == PRE_DEC
- || GET_CODE (XEXP (op, 0)) == POST_DEC))
- win = 1;
- break;
-
- case '>':
- if (GET_CODE (op) == MEM
- && (GET_CODE (XEXP (op, 0)) == PRE_INC
- || GET_CODE (XEXP (op, 0)) == POST_INC))
- win = 1;
- break;
-
- case 'E':
- /* Match any CONST_DOUBLE, but only if
- we can examine the bits of it reliably. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
- && GET_CODE (op) != VOIDmode && ! flag_pretend_float)
- break;
- if (GET_CODE (op) == CONST_DOUBLE)
- win = 1;
- break;
-
- case 'F':
- if (GET_CODE (op) == CONST_DOUBLE)
- win = 1;
- break;
-
- case 'G':
- case 'H':
- if (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
- win = 1;
- break;
-
- case 's':
- if (GET_CODE (op) == CONST_INT
- || (GET_CODE (op) == CONST_DOUBLE
- && GET_MODE (op) == VOIDmode))
- break;
- /* Fall through */
- case 'i':
- if (CONSTANT_P (op))
- win = 1;
- break;
-
- case 'n':
- if (GET_CODE (op) == CONST_INT
- || (GET_CODE (op) == CONST_DOUBLE
- && GET_MODE (op) == VOIDmode))
- win = 1;
- break;
-
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), c))
- win = 1;
- break;
-
-#ifdef EXTRA_CONSTRAINT
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- if (EXTRA_CONSTRAINT (op, c))
- win = 1;
- break;
-#endif
-
- case 'V':
- if (GET_CODE (op) == MEM && ! offsettable_memref_p (op))
- win = 1;
- break;
-
- case 'o':
- if (offsettable_memref_p (op))
- win = 1;
- break;
-
- default:
- if (GET_CODE (op) == REG
- && reg_fits_class_p (op, REG_CLASS_FROM_LETTER (c),
- offset, mode))
- {
- operand_class[this_operand]
- = reg_class_subunion[(int)operand_class[this_operand]][(int) REG_CLASS_FROM_LETTER (c)];
- win = 1;
- }
- }
-
- constraints[this_operand] = p;
- /* If this operand did not win somehow,
- this alternative loses. */
- if (! win)
- lose = 1;
- }
- /* This alternative won; the operands are ok.
- Change whichever operands this alternative says to change. */
- if (! lose)
- break;
-
- this_alternative++;
- }
-
- /* For operands constrained to match another operand, copy the other
- operand's class to this operand's class. */
- for (j = 0; j < n_operands; j++)
- if (operand_matches[j] >= 0)
- operand_class[j] = operand_class[operand_matches[j]];
-
- return this_alternative == n_alternatives ? -1 : this_alternative;
-}
-
/* Record the life info of each stack reg in INSN, updating REGSTACK.
- N_INPUTS is the number of inputs; N_OUTPUTS the outputs. CONSTRAINTS
- is an array of the constraint strings used in the asm statement.
+ N_INPUTS is the number of inputs; N_OUTPUTS the outputs.
OPERANDS is an array of all operands for the insn, and is assumed to
contain all output operands, then all inputs operands.
@@ -906,43 +681,47 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
numbers below refer to that explanation. */
static void
-record_asm_reg_life (insn, regstack, operands, constraints,
- n_inputs, n_outputs)
+record_asm_reg_life (insn, regstack)
rtx insn;
stack regstack;
- rtx *operands;
- char **constraints;
- int n_inputs, n_outputs;
{
int i;
- int n_operands = n_inputs + n_outputs;
- int first_input = n_outputs;
int n_clobbers;
int malformed_asm = 0;
rtx body = PATTERN (insn);
- int *operand_matches = (int *) alloca (n_operands * sizeof (int *));
-
- enum reg_class *operand_class
- = (enum reg_class *) alloca (n_operands * sizeof (enum reg_class *));
-
int reg_used_as_output[FIRST_PSEUDO_REGISTER];
int implicitly_dies[FIRST_PSEUDO_REGISTER];
+ int alt;
rtx *clobber_reg;
+ int n_inputs, n_outputs;
/* Find out what the constraints require. If no constraint
alternative matches, this asm is malformed. */
- i = constrain_asm_operands (n_operands, operands, constraints,
- operand_matches, operand_class);
- if (i < 0)
- malformed_asm = 1;
+ extract_insn (insn);
+ constrain_operands (1);
+ alt = which_alternative;
+
+ preprocess_constraints ();
+
+ n_inputs = get_asm_operand_n_inputs (body);
+ n_outputs = recog_n_operands - n_inputs;
+
+ if (alt < 0)
+ {
+ malformed_asm = 1;
+ /* Avoid further trouble with this insn. */
+ PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
+ return;
+ }
/* Strip SUBREGs here to make the following code simpler. */
- for (i = 0; i < n_operands; i++)
- if (GET_CODE (operands[i]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[i])) == REG)
- operands[i] = SUBREG_REG (operands[i]);
+ for (i = 0; i < recog_n_operands; i++)
+ if (GET_CODE (recog_operand[i]) == SUBREG
+ && GET_CODE (SUBREG_REG (recog_operand[i])) == REG)
+ recog_operand[i] = SUBREG_REG (recog_operand[i]);
/* Set up CLOBBER_REG. */
@@ -950,7 +729,7 @@ record_asm_reg_life (insn, regstack, operands, constraints,
if (GET_CODE (body) == PARALLEL)
{
- clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx *));
+ clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx));
for (i = 0; i < XVECLEN (body, 0); i++)
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
@@ -978,15 +757,15 @@ record_asm_reg_life (insn, regstack, operands, constraints,
bzero ((char *) reg_used_as_output, sizeof (reg_used_as_output));
for (i = 0; i < n_outputs; i++)
- if (STACK_REG_P (operands[i]))
+ if (STACK_REG_P (recog_operand[i]))
{
- if (reg_class_size[(int) operand_class[i]] != 1)
+ if (reg_class_size[(int) recog_op_alt[i][alt].class] != 1)
{
error_for_asm (insn, "Output constraint %d must specify a single register", i);
malformed_asm = 1;
}
else
- reg_used_as_output[REGNO (operands[i])] = 1;
+ reg_used_as_output[REGNO (recog_operand[i])] = 1;
}
@@ -1011,19 +790,19 @@ record_asm_reg_life (insn, regstack, operands, constraints,
popped. */
bzero ((char *) implicitly_dies, sizeof (implicitly_dies));
- for (i = first_input; i < first_input + n_inputs; i++)
- if (STACK_REG_P (operands[i]))
+ for (i = n_outputs; i < n_outputs + n_inputs; i++)
+ if (STACK_REG_P (recog_operand[i]))
{
/* An input reg is implicitly popped if it is tied to an
output, or if there is a CLOBBER for it. */
int j;
for (j = 0; j < n_clobbers; j++)
- if (operands_match_p (clobber_reg[j], operands[i]))
+ if (operands_match_p (clobber_reg[j], recog_operand[i]))
break;
- if (j < n_clobbers || operand_matches[i] >= 0)
- implicitly_dies[REGNO (operands[i])] = 1;
+ if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
+ implicitly_dies[REGNO (recog_operand[i])] = 1;
}
/* Search for first non-popped reg. */
@@ -1049,13 +828,13 @@ record_asm_reg_life (insn, regstack, operands, constraints,
??? Detect this more deterministically by having constraint_asm_operands
record any earlyclobber. */
- for (i = first_input; i < first_input + n_inputs; i++)
- if (operand_matches[i] == -1)
+ for (i = n_outputs; i < n_outputs + n_inputs; i++)
+ if (recog_op_alt[i][alt].matches == -1)
{
int j;
for (j = 0; j < n_outputs; j++)
- if (operands_match_p (operands[j], operands[i]))
+ if (operands_match_p (recog_operand[j], recog_operand[i]))
{
error_for_asm (insn,
"Output operand %d must use `&' constraint", j);
@@ -1067,14 +846,14 @@ record_asm_reg_life (insn, regstack, operands, constraints,
{
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
- PUT_MODE (insn, VOIDmode);
+ VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
return;
}
/* Process all outputs */
for (i = 0; i < n_outputs; i++)
{
- rtx op = operands[i];
+ rtx op = recog_operand[i];
if (! STACK_REG_P (op))
{
@@ -1096,11 +875,12 @@ record_asm_reg_life (insn, regstack, operands, constraints,
}
/* Process all inputs */
- for (i = first_input; i < first_input + n_inputs; i++)
+ for (i = n_outputs; i < n_outputs + n_inputs; i++)
{
- if (! STACK_REG_P (operands[i]))
+ rtx op = recog_operand[i];
+ if (! STACK_REG_P (op))
{
- if (stack_regs_mentioned_p (operands[i]))
+ if (stack_regs_mentioned_p (op))
abort ();
else
continue;
@@ -1110,13 +890,12 @@ record_asm_reg_life (insn, regstack, operands, constraints,
But don't record a death note if there is already a death note,
or if the input is also an output. */
- if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (operands[i]))
- && operand_matches[i] == -1
- && find_regno_note (insn, REG_DEAD, REGNO (operands[i])) == NULL_RTX)
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, operands[i],
- REG_NOTES (insn));
+ if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (op))
+ && recog_op_alt[i][alt].matches == -1
+ && find_regno_note (insn, REG_DEAD, REGNO (op)) == NULL_RTX)
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, op, REG_NOTES (insn));
- SET_HARD_REG_BIT (regstack->reg_set, REGNO (operands[i]));
+ SET_HARD_REG_BIT (regstack->reg_set, REGNO (op));
}
}
@@ -1178,29 +957,25 @@ record_reg_life_pat (pat, src, dest, douse)
N_INPUTS and N_OUTPUTS are pointers to ints into which the results are
placed. */
-static void
-get_asm_operand_lengths (body, n_operands, n_inputs, n_outputs)
+static int
+get_asm_operand_n_inputs (body)
rtx body;
- int n_operands;
- int *n_inputs, *n_outputs;
{
if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
- *n_inputs = ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body));
+ return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body));
else if (GET_CODE (body) == ASM_OPERANDS)
- *n_inputs = ASM_OPERANDS_INPUT_LENGTH (body);
+ return ASM_OPERANDS_INPUT_LENGTH (body);
else if (GET_CODE (body) == PARALLEL
&& GET_CODE (XVECEXP (body, 0, 0)) == SET)
- *n_inputs = ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)));
+ return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)));
else if (GET_CODE (body) == PARALLEL
&& GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
- *n_inputs = ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
- else
- abort ();
+ return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
- *n_outputs = n_operands - *n_inputs;
+ abort ();
}
/* Scan INSN, which is in BLOCK, and record the life & death of stack
@@ -1244,18 +1019,7 @@ record_reg_life (insn, block, regstack)
n_operands = asm_noperands (PATTERN (insn));
if (n_operands >= 0)
{
- /* This insn is an `asm' with operands. Decode the operands,
- decide how many are inputs, and record the life information. */
-
- rtx operands[MAX_RECOG_OPERANDS];
- rtx body = PATTERN (insn);
- int n_inputs, n_outputs;
- char **constraints = (char **) alloca (n_operands * sizeof (char *));
-
- decode_asm_operands (body, operands, NULL_PTR, constraints, NULL_PTR);
- get_asm_operand_lengths (body, n_operands, &n_inputs, &n_outputs);
- record_asm_reg_life (insn, regstack, operands, constraints,
- n_inputs, n_outputs);
+ record_asm_reg_life (insn, regstack);
return;
}
@@ -1310,7 +1074,6 @@ record_reg_life (insn, block, regstack)
pat = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, DFmode),
CONST0_RTX (DFmode));
init = emit_insn_after (pat, insn);
- PUT_MODE (init, QImode);
CLEAR_HARD_REG_BIT (regstack->reg_set, reg);
@@ -1487,14 +1250,14 @@ stack_reg_life_analysis (first, stackentry)
for (block = blocks - 1; --block >= 0;)
if (GET_CODE (block_end[block]) == JUMP_INSN
- && GET_CODE (PATTERN (block_end[block])) == RETURN)
+ && returnjump_p (block_end[block]))
mark_regs_pat (retvalue, block_out_reg_set+block);
/* Mark off the end of last block if we "fall off" the end of the
function into the epilogue. */
if (GET_CODE (block_end[blocks-1]) != JUMP_INSN
- || GET_CODE (PATTERN (block_end[blocks-1])) == RETURN)
+ || returnjump_p (block_end[blocks-1]))
mark_regs_pat (retvalue, block_out_reg_set+blocks-1);
}
}
@@ -1520,7 +1283,7 @@ stack_reg_life_analysis (first, stackentry)
everything dies. But otherwise don't process unless there
are some stack regs present. */
- if (GET_MODE (insn) == QImode || GET_CODE (insn) == CALL_INSN)
+ if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN)
record_reg_life (insn, block, &regstack);
} while (insn != block_begin[block]);
@@ -1606,7 +1369,6 @@ stack_reg_life_analysis (first, stackentry)
init_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG(reg, DFmode),
CONST0_RTX (DFmode));
block_begin[0] = emit_insn_after (init_rtx, first);
- PUT_MODE (block_begin[0], QImode);
CLEAR_HARD_REG_BIT (block_stack_in[0].reg_set, reg);
}
@@ -1693,6 +1455,14 @@ static void
delete_insn_for_stacker (insn)
rtx insn;
{
+ int i;
+
+ /* Ensure that the side effects were clobbers when deleting a PARALLEL. */
+ if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
+ if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) != CLOBBER)
+ abort ();
+
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
@@ -1700,9 +1470,12 @@ delete_insn_for_stacker (insn)
/* Emit an insn to pop virtual register REG before or after INSN.
REGSTACK is the stack state after INSN and is updated to reflect this
- pop. WHEN is either emit_insn_before or emit_insn_after. A pop insn
- is represented as a SET whose destination is the register to be popped
- and source is the top of stack. A death note for the top of stack
+ pop. WHEN is either emit_insn_before, emit_insn_after or NULL.
+ in case WHEN is NULL we don't really emit the insn, just modify stack
+ information. Caller is expected to emit insn himself.
+
+ A pop insn is represented as a SET whose destination is the register to
+ be popped and source is the top of stack. A death note for the top of stack
cases the movdf pattern to pop. */
static rtx
@@ -1720,16 +1493,18 @@ emit_pop_insn (insn, regstack, reg, when)
if (hard_regno < FIRST_STACK_REG)
abort ();
- pop_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG (hard_regno, DFmode),
- FP_MODE_REG (FIRST_STACK_REG, DFmode));
+ if (when)
+ {
+ pop_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG (hard_regno, DFmode),
+ FP_MODE_REG (FIRST_STACK_REG, DFmode));
- pop_insn = (*when) (pop_rtx, insn);
- /* ??? This used to be VOIDmode, but that seems wrong. */
- PUT_MODE (pop_insn, QImode);
+ pop_insn = (*when) (pop_rtx, insn);
- REG_NOTES (pop_insn) = gen_rtx_EXPR_LIST (REG_DEAD,
- FP_MODE_REG (FIRST_STACK_REG, DFmode),
- REG_NOTES (pop_insn));
+ REG_NOTES (pop_insn) = gen_rtx_EXPR_LIST (REG_DEAD,
+ FP_MODE_REG (FIRST_STACK_REG,
+ DFmode),
+ REG_NOTES (pop_insn));
+ }
regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)]
= regstack->reg[regstack->top];
@@ -1776,7 +1551,7 @@ emit_swap_insn (insn, regstack, reg)
/* Find the previous insn involving stack regs, but don't go past
any labels, calls or jumps. */
i1 = prev_nonnote_insn (insn);
- while (i1 && GET_CODE (i1) == INSN && GET_MODE (i1) != QImode)
+ while (i1 && GET_CODE (i1) == INSN && !stack_regs_mentioned (i1))
i1 = prev_nonnote_insn (i1);
if (i1)
@@ -1814,8 +1589,6 @@ emit_swap_insn (insn, regstack, reg)
swap_rtx = gen_swapdf (FP_MODE_REG (hard_regno, DFmode),
FP_MODE_REG (FIRST_STACK_REG, DFmode));
swap_insn = emit_insn_after (swap_rtx, i1);
- /* ??? This used to be VOIDmode, but that seems wrong. */
- PUT_MODE (swap_insn, QImode);
}
/* Handle a move to or from a stack register in PAT, which is in INSN.
@@ -1932,7 +1705,6 @@ move_for_stack_reg (insn, regstack, pat)
push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
push_insn = emit_insn_before (push_rtx, insn);
- PUT_MODE (push_insn, QImode);
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg,
REG_NOTES (insn));
}
@@ -1992,10 +1764,18 @@ swap_rtx_condition (pat)
/* Handle a comparison. Special care needs to be taken to avoid
causing comparisons that a 387 cannot do correctly, such as EQ.
- Also, a pop insn may need to be emitted. The 387 does have an
+ Also, a fstp instruction may need to be emitted. The 387 does have an
`fcompp' insn that can pop two regs, but it is sometimes too expensive
to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to
- set up. */
+ set up.
+
+ We can not handle this by emiting fpop instruction after compare, because
+ it appears between cc0 setter and user. So we emit only
+ REG_DEAD note and handle it as a special case in machine description.
+
+ This code used trick with delay_slot filling to emit pop insn after
+ comparsion but it didn't worked because it caused confusion with cc_status
+ in final pass. */
static void
compare_for_stack_reg (insn, regstack, pat)
@@ -2007,6 +1787,7 @@ compare_for_stack_reg (insn, regstack, pat)
rtx src1_note, src2_note;
rtx cc0_user;
int have_cmove;
+ int hard_regno;
src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));
@@ -2073,7 +1854,10 @@ compare_for_stack_reg (insn, regstack, pat)
replace_reg (src1, FIRST_STACK_REG);
if (STACK_REG_P (*src2))
- replace_reg (src2, get_hard_regnum (regstack, *src2));
+ {
+ hard_regno = get_hard_regnum (regstack, *src2);
+ replace_reg (src2, hard_regno);
+ }
if (src1_note)
{
@@ -2102,16 +1886,11 @@ compare_for_stack_reg (insn, regstack, pat)
}
else
{
- /* The 386 can only represent death of the first operand in
- the case handled above. In all other cases, emit a separate
- pop and remove the death note from here. */
-
- link_cc0_insns (insn);
+ /* Pop of second operand is handled using special REG_DEAD note
+ because we can't emit pop insn after cc0 setter. */
- remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src2_note, 0)));
-
- emit_pop_insn (insn, regstack, XEXP (src2_note, 0),
- emit_insn_after);
+ emit_pop_insn (insn, regstack, XEXP (src2_note, 0), NULL);
+ replace_reg (&XEXP (src2_note, 0), hard_regno);
}
}
}
@@ -2419,12 +2198,7 @@ subst_stack_regs_pat (insn, regstack, pat)
/* Substitute hard regnums for any stack regs in INSN, which has
N_INPUTS inputs and N_OUTPUTS outputs. REGSTACK is the stack info
- before the insn, and is updated with changes made here. CONSTRAINTS is
- an array of the constraint strings used in the asm statement.
-
- OPERANDS is an array of the operands, and OPERANDS_LOC is a
- parallel array of where the operands were found. The output operands
- all precede the input operands.
+ before the insn, and is updated with changes made here.
There are several requirements and assumptions about the use of
stack-like regs in asm statements. These rules are enforced by
@@ -2433,21 +2207,12 @@ subst_stack_regs_pat (insn, regstack, pat)
requirements, since record_asm_stack_regs removes any problem asm. */
static void
-subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
- n_inputs, n_outputs)
+subst_asm_stack_regs (insn, regstack)
rtx insn;
stack regstack;
- rtx *operands, **operands_loc;
- char **constraints;
- int n_inputs, n_outputs;
{
- int n_operands = n_inputs + n_outputs;
- int first_input = n_outputs;
rtx body = PATTERN (insn);
-
- int *operand_matches = (int *) alloca (n_operands * sizeof (int *));
- enum reg_class *operand_class
- = (enum reg_class *) alloca (n_operands * sizeof (enum reg_class *));
+ int alt;
rtx *note_reg; /* Array of note contents */
rtx **note_loc; /* Address of REG field of each note */
@@ -2461,24 +2226,31 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
int n_clobbers;
rtx note;
int i;
+ int n_inputs, n_outputs;
/* Find out what the constraints required. If no constraint
alternative matches, that is a compiler bug: we should have caught
such an insn during the life analysis pass (and reload should have
caught it regardless). */
+ extract_insn (insn);
+ constrain_operands (1);
+ alt = which_alternative;
+
+ preprocess_constraints ();
- i = constrain_asm_operands (n_operands, operands, constraints,
- operand_matches, operand_class);
- if (i < 0)
+ n_inputs = get_asm_operand_n_inputs (body);
+ n_outputs = recog_n_operands - n_inputs;
+
+ if (alt < 0)
abort ();
/* Strip SUBREGs here to make the following code simpler. */
- for (i = 0; i < n_operands; i++)
- if (GET_CODE (operands[i]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[i])) == REG)
+ for (i = 0; i < recog_n_operands; i++)
+ if (GET_CODE (recog_operand[i]) == SUBREG
+ && GET_CODE (SUBREG_REG (recog_operand[i])) == REG)
{
- operands_loc[i] = & SUBREG_REG (operands[i]);
- operands[i] = SUBREG_REG (operands[i]);
+ recog_operand_loc[i] = & SUBREG_REG (recog_operand[i]);
+ recog_operand[i] = SUBREG_REG (recog_operand[i]);
}
/* Set up NOTE_REG, NOTE_LOC and NOTE_KIND. */
@@ -2519,8 +2291,8 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
if (GET_CODE (body) == PARALLEL)
{
- clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx *));
- clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx **));
+ clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx));
+ clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx *));
for (i = 0; i < XVECLEN (body, 0); i++)
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
@@ -2548,34 +2320,35 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
/* Put the input regs into the desired place in TEMP_STACK. */
- for (i = first_input; i < first_input + n_inputs; i++)
- if (STACK_REG_P (operands[i])
- && reg_class_subset_p (operand_class[i], FLOAT_REGS)
- && operand_class[i] != FLOAT_REGS)
+ for (i = n_outputs; i < n_outputs + n_inputs; i++)
+ if (STACK_REG_P (recog_operand[i])
+ && reg_class_subset_p (recog_op_alt[i][alt].class,
+ FLOAT_REGS)
+ && recog_op_alt[i][alt].class != FLOAT_REGS)
{
/* If an operand needs to be in a particular reg in
FLOAT_REGS, the constraint was either 't' or 'u'. Since
these constraints are for single register classes, and reload
guaranteed that operand[i] is already in that class, we can
- just use REGNO (operands[i]) to know which actual reg this
+ just use REGNO (recog_operand[i]) to know which actual reg this
operand needs to be in. */
- int regno = get_hard_regnum (&temp_stack, operands[i]);
+ int regno = get_hard_regnum (&temp_stack, recog_operand[i]);
if (regno < 0)
abort ();
- if (regno != REGNO (operands[i]))
+ if (regno != REGNO (recog_operand[i]))
{
- /* operands[i] is not in the right place. Find it
+ /* recog_operand[i] is not in the right place. Find it
and swap it with whatever is already in I's place.
- K is where operands[i] is now. J is where it should
+ K is where recog_operand[i] is now. J is where it should
be. */
int j, k, temp;
k = temp_stack.top - (regno - FIRST_STACK_REG);
j = (temp_stack.top
- - (REGNO (operands[i]) - FIRST_STACK_REG));
+ - (REGNO (recog_operand[i]) - FIRST_STACK_REG));
temp = temp_stack.reg[k];
temp_stack.reg[k] = temp_stack.reg[j];
@@ -2591,15 +2364,15 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
/* Make the needed input register substitutions. Do death notes and
clobbers too, because these are for inputs, not outputs. */
- for (i = first_input; i < first_input + n_inputs; i++)
- if (STACK_REG_P (operands[i]))
+ for (i = n_outputs; i < n_outputs + n_inputs; i++)
+ if (STACK_REG_P (recog_operand[i]))
{
- int regnum = get_hard_regnum (regstack, operands[i]);
+ int regnum = get_hard_regnum (regstack, recog_operand[i]);
if (regnum < 0)
abort ();
- replace_reg (operands_loc[i], regnum);
+ replace_reg (recog_operand_loc[i], regnum);
}
for (i = 0; i < n_notes; i++)
@@ -2631,21 +2404,21 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
/* Now remove from REGSTACK any inputs that the asm implicitly popped. */
- for (i = first_input; i < first_input + n_inputs; i++)
- if (STACK_REG_P (operands[i]))
+ for (i = n_outputs; i < n_outputs + n_inputs; i++)
+ if (STACK_REG_P (recog_operand[i]))
{
/* An input reg is implicitly popped if it is tied to an
output, or if there is a CLOBBER for it. */
int j;
for (j = 0; j < n_clobbers; j++)
- if (operands_match_p (clobber_reg[j], operands[i]))
+ if (operands_match_p (clobber_reg[j], recog_operand[i]))
break;
- if (j < n_clobbers || operand_matches[i] >= 0)
+ if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
{
- /* operands[i] might not be at the top of stack. But that's OK,
- because all we need to do is pop the right number of regs
+ /* recog_operand[i] might not be at the top of stack. But that's
+ OK, because all we need to do is pop the right number of regs
off of the top of the reg-stack. record_asm_stack_regs
guaranteed that all implicitly popped regs were grouped
at the top of the reg-stack. */
@@ -2666,7 +2439,7 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
int j;
for (j = 0; j < n_outputs; j++)
- if (STACK_REG_P (operands[j]) && REGNO (operands[j]) == i)
+ if (STACK_REG_P (recog_operand[j]) && REGNO (recog_operand[j]) == i)
{
regstack->reg[++regstack->top] = i;
SET_HARD_REG_BIT (regstack->reg_set, i);
@@ -2682,31 +2455,32 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
in the death notes have already been substituted. */
for (i = 0; i < n_outputs; i++)
- if (STACK_REG_P (operands[i]))
+ if (STACK_REG_P (recog_operand[i]))
{
int j;
for (j = 0; j < n_notes; j++)
- if (REGNO (operands[i]) == REGNO (note_reg[j])
+ if (REGNO (recog_operand[i]) == REGNO (note_reg[j])
&& note_kind[j] == REG_UNUSED)
{
- insn = emit_pop_insn (insn, regstack, operands[i],
+ insn = emit_pop_insn (insn, regstack, recog_operand[i],
emit_insn_after);
break;
}
}
- for (i = first_input; i < first_input + n_inputs; i++)
- if (STACK_REG_P (operands[i]))
+ for (i = n_outputs; i < n_outputs + n_inputs; i++)
+ if (STACK_REG_P (recog_operand[i]))
{
int j;
for (j = 0; j < n_notes; j++)
- if (REGNO (operands[i]) == REGNO (note_reg[j])
+ if (REGNO (recog_operand[i]) == REGNO (note_reg[j])
&& note_kind[j] == REG_DEAD
- && TEST_HARD_REG_BIT (regstack->reg_set, REGNO (operands[i])))
+ && TEST_HARD_REG_BIT (regstack->reg_set,
+ REGNO (recog_operand[i])))
{
- insn = emit_pop_insn (insn, regstack, operands[i],
+ insn = emit_pop_insn (insn, regstack, recog_operand[i],
emit_insn_after);
break;
}
@@ -2725,7 +2499,6 @@ subst_stack_regs (insn, regstack)
{
register rtx *note_link, note;
register int i;
- int n_operands;
if (GET_CODE (insn) == CALL_INSN)
{
@@ -2755,27 +2528,16 @@ subst_stack_regs (insn, regstack)
we must check each pattern in a parallel here. A call_value_pop could
fail otherwise. */
- if (GET_MODE (insn) == QImode)
+ if (stack_regs_mentioned (insn))
{
- n_operands = asm_noperands (PATTERN (insn));
+ int n_operands = asm_noperands (PATTERN (insn));
if (n_operands >= 0)
{
/* This insn is an `asm' with operands. Decode the operands,
decide how many are inputs, and do register substitution.
Any REG_UNUSED notes will be handled by subst_asm_stack_regs. */
- rtx operands[MAX_RECOG_OPERANDS];
- rtx *operands_loc[MAX_RECOG_OPERANDS];
- rtx body = PATTERN (insn);
- int n_inputs, n_outputs;
- char **constraints
- = (char **) alloca (n_operands * sizeof (char *));
-
- decode_asm_operands (body, operands, operands_loc,
- constraints, NULL_PTR);
- get_asm_operand_lengths (body, n_operands, &n_inputs, &n_outputs);
- subst_asm_stack_regs (insn, regstack, operands, operands_loc,
- constraints, n_inputs, n_outputs);
+ subst_asm_stack_regs (insn, regstack);
return;
}
@@ -2783,8 +2545,14 @@ subst_stack_regs (insn, regstack)
for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
{
if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
- subst_stack_regs_pat (insn, regstack,
- XVECEXP (PATTERN (insn), 0, i));
+ {
+ subst_stack_regs_pat (insn, regstack,
+ XVECEXP (PATTERN (insn), 0, i));
+
+ /* subst_stack_regs_pat may have deleted a no-op insn. */
+ if (GET_CODE (insn) == NOTE)
+ break;
+ }
}
else
subst_stack_regs_pat (insn, regstack, PATTERN (insn));
@@ -2872,43 +2640,46 @@ change_stack (insn, old, new, when)
if (old->top != new->top)
abort ();
- /* Loop here emitting swaps until the stack is correct. The
- worst case number of swaps emitted is N + 2, where N is the
+ /* If the stack is not empty (new->top != -1), loop here emitting
+ swaps until the stack is correct.
+
+ The worst case number of swaps emitted is N + 2, where N is the
depth of the stack. In some cases, the reg at the top of
stack may be correct, but swapped anyway in order to fix
other regs. But since we never swap any other reg away from
its correct slot, this algorithm will converge. */
- do
- {
- /* Swap the reg at top of stack into the position it is
- supposed to be in, until the correct top of stack appears. */
+ if (new->top != -1)
+ do
+ {
+ /* Swap the reg at top of stack into the position it is
+ supposed to be in, until the correct top of stack appears. */
- while (old->reg[old->top] != new->reg[new->top])
- {
- for (reg = new->top; reg >= 0; reg--)
- if (new->reg[reg] == old->reg[old->top])
- break;
+ while (old->reg[old->top] != new->reg[new->top])
+ {
+ for (reg = new->top; reg >= 0; reg--)
+ if (new->reg[reg] == old->reg[old->top])
+ break;
- if (reg == -1)
- abort ();
+ if (reg == -1)
+ abort ();
- emit_swap_insn (insn, old,
- FP_MODE_REG (old->reg[reg], DFmode));
- }
+ emit_swap_insn (insn, old,
+ FP_MODE_REG (old->reg[reg], DFmode));
+ }
- /* See if any regs remain incorrect. If so, bring an
+ /* See if any regs remain incorrect. If so, bring an
incorrect reg to the top of stack, and let the while loop
above fix it. */
- for (reg = new->top; reg >= 0; reg--)
- if (new->reg[reg] != old->reg[reg])
- {
- emit_swap_insn (insn, old,
- FP_MODE_REG (old->reg[reg], DFmode));
- break;
- }
- } while (reg >= 0);
+ for (reg = new->top; reg >= 0; reg--)
+ if (new->reg[reg] != old->reg[reg])
+ {
+ emit_swap_insn (insn, old,
+ FP_MODE_REG (old->reg[reg], DFmode));
+ break;
+ }
+ } while (reg >= 0);
/* At this point there must be no differences. */
@@ -3082,7 +2853,7 @@ convert_regs ()
mentioned or if it's a CALL_INSN (register passing of
floating point values). */
- if (GET_MODE (insn) == QImode || GET_CODE (insn) == CALL_INSN)
+ if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN)
subst_stack_regs (insn, &regstack);
} while (insn != block_end[block]);
diff --git a/contrib/gcc/regclass.c b/contrib/gcc/regclass.c
index 25cac8f..4e16288 100644
--- a/contrib/gcc/regclass.c
+++ b/contrib/gcc/regclass.c
@@ -1,5 +1,5 @@
/* Compute register class preferences for pseudo-registers.
- Copyright (C) 1987, 88, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -41,6 +41,9 @@ Boston, MA 02111-1307, USA. */
#define REGISTER_MOVE_COST(x, y) 2
#endif
+static void init_reg_sets_1 PROTO((void));
+static void init_reg_modes PROTO((void));
+
/* If we have auto-increment or auto-decrement and we can have secondary
reloads, we are not allowed to use classes requiring secondary
reloads for pseudos auto-incremented since reload can't handle it. */
@@ -56,7 +59,7 @@ Boston, MA 02111-1307, USA. */
/* Indexed by hard register number, contains 1 for registers
that are fixed use (stack pointer, pc, frame pointer, etc.).
These are the registers that cannot be used to allocate
- a pseudo reg whose life does not cross calls. */
+ a pseudo reg for general use. */
char fixed_regs[FIRST_PSEUDO_REGISTER];
@@ -71,7 +74,8 @@ static char initial_fixed_regs[] = FIXED_REGISTERS;
/* Indexed by hard register number, contains 1 for registers
that are fixed use or are clobbered by function calls.
These are the registers that cannot be used to allocate
- a pseudo reg whose life crosses calls. */
+ a pseudo reg whose life crosses calls unless we are able
+ to save/restore them across the calls. */
char call_used_regs[FIRST_PSEUDO_REGISTER];
@@ -87,10 +91,9 @@ HARD_REG_SET losing_caller_save_reg_set;
static char initial_call_used_regs[] = CALL_USED_REGISTERS;
/* Indexed by hard register number, contains 1 for registers that are
- fixed use -- i.e. in fixed_regs -- or a function value return register
- or STRUCT_VALUE_REGNUM or STATIC_CHAIN_REGNUM. These are the
- registers that cannot hold quantities across calls even if we are
- willing to save and restore them. */
+ fixed use or call used registers that cannot hold quantities across
+ calls even if we are willing to save and restore them. call fixed
+ registers are a subset of call used registers. */
char call_fixed_regs[FIRST_PSEUDO_REGISTER];
@@ -233,6 +236,25 @@ init_reg_sets ()
bcopy (initial_call_used_regs, call_used_regs, sizeof call_used_regs);
bzero (global_regs, sizeof global_regs);
+ /* Do any additional initialization regsets may need */
+ INIT_ONCE_REG_SET ();
+}
+
+/* After switches have been processed, which perhaps alter
+ `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs. */
+
+static void
+init_reg_sets_1 ()
+{
+ register unsigned int i, j;
+
+ /* This macro allows the fixed or call-used registers
+ and the register classes to depend on target flags. */
+
+#ifdef CONDITIONAL_REGISTER_USAGE
+ CONDITIONAL_REGISTER_USAGE;
+#endif
+
/* Compute number of hard regs in each class. */
bzero ((char *) reg_class_size, sizeof reg_class_size);
@@ -336,25 +358,6 @@ init_reg_sets ()
}
}
- /* Do any additional initialization regsets may need */
- INIT_ONCE_REG_SET ();
-}
-
-/* After switches have been processed, which perhaps alter
- `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs. */
-
-static void
-init_reg_sets_1 ()
-{
- register unsigned int i, j;
-
- /* This macro allows the fixed or call-used registers
- to depend on target flags. */
-
-#ifdef CONDITIONAL_REGISTER_USAGE
- CONDITIONAL_REGISTER_USAGE;
-#endif
-
/* Initialize "constant" tables. */
CLEAR_HARD_REG_SET (fixed_reg_set);
@@ -574,8 +577,27 @@ fix_register (name, fixed, call_used)
if ((i = decode_reg_name (name)) >= 0)
{
- fixed_regs[i] = fixed;
- call_used_regs[i] = call_used;
+ if ((i == STACK_POINTER_REGNUM
+#ifdef HARD_FRAME_POINTER_REGNUM
+ || i == HARD_FRAME_POINTER_REGNUM
+#else
+ || i == FRAME_POINTER_REGNUM
+#endif
+ )
+ && (fixed == 0 || call_used == 0))
+ {
+ static char* what_option[2][2] = {
+ { "call-saved", "call-used" },
+ { "no-such-option", "fixed" }};
+
+ error ("can't use '%s' as a %s register", name,
+ what_option[fixed][call_used]);
+ }
+ else
+ {
+ fixed_regs[i] = fixed;
+ call_used_regs[i] = call_used;
+ }
}
else
{
@@ -629,6 +651,10 @@ struct costs
static struct costs *costs;
+/* Initialized once, and used to initialize cost values for each insn. */
+
+static struct costs init_cost;
+
/* Record the same data by operand number, accumulated for each alternative
in an insn. The contribution to a pseudo is that of the minimum-cost
alternative. */
@@ -665,8 +691,9 @@ static int loop_depth;
static int loop_cost;
+static rtx scan_one_insn PROTO((rtx, int));
static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *,
- char **, rtx));
+ char *, const char **, rtx));
static int copy_cost PROTO((rtx, enum machine_mode,
enum reg_class, int));
static void record_address_regs PROTO((rtx, enum reg_class, int));
@@ -698,15 +725,223 @@ reg_alternate_class (regno)
return (enum reg_class) altclass[regno];
}
-/* This prevents dump_flow_info from losing if called
- before regclass is run. */
+/* Initialize some global data for this pass. */
void
regclass_init ()
{
+ int i;
+
+ init_cost.mem_cost = 10000;
+ for (i = 0; i < N_REG_CLASSES; i++)
+ init_cost.cost[i] = 10000;
+
+ /* This prevents dump_flow_info from losing if called
+ before regclass is run. */
prefclass = 0;
}
+/* Subroutine of regclass, processes one insn INSN. Scan it and record each
+ time it would save code to put a certain register in a certain class.
+ PASS, when nonzero, inhibits some optimizations which need only be done
+ once.
+ Return the last insn processed, so that the scan can be continued from
+ there. */
+
+static rtx
+scan_one_insn (insn, pass)
+ rtx insn;
+ int pass;
+{
+ enum rtx_code code = GET_CODE (insn);
+ enum rtx_code pat_code;
+ const char *constraints[MAX_RECOG_OPERANDS];
+ enum machine_mode modes[MAX_RECOG_OPERANDS];
+ char subreg_changes_size[MAX_RECOG_OPERANDS];
+ rtx set, note;
+ int i, j;
+
+ /* Show that an insn inside a loop is likely to be executed three
+ times more than insns outside a loop. This is much more aggressive
+ than the assumptions made elsewhere and is being tried as an
+ experiment. */
+
+ if (code == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+ loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5));
+ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+ loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5));
+
+ return insn;
+ }
+
+ if (GET_RTX_CLASS (code) != 'i')
+ return insn;
+
+ pat_code = GET_CODE (PATTERN (insn));
+ if (pat_code == USE
+ || pat_code == CLOBBER
+ || pat_code == ASM_INPUT
+ || pat_code == ADDR_VEC
+ || pat_code == ADDR_DIFF_VEC)
+ return insn;
+
+ set = single_set (insn);
+ extract_insn (insn);
+
+ for (i = 0; i < recog_n_operands; i++)
+ {
+ constraints[i] = recog_constraints[i];
+ modes[i] = recog_operand_mode[i];
+ }
+ memset (subreg_changes_size, 0, sizeof (subreg_changes_size));
+
+ /* If this insn loads a parameter from its stack slot, then
+ it represents a savings, rather than a cost, if the
+ parameter is stored in memory. Record this fact. */
+
+ if (set != 0 && GET_CODE (SET_DEST (set)) == REG
+ && GET_CODE (SET_SRC (set)) == MEM
+ && (note = find_reg_note (insn, REG_EQUIV,
+ NULL_RTX)) != 0
+ && GET_CODE (XEXP (note, 0)) == MEM)
+ {
+ costs[REGNO (SET_DEST (set))].mem_cost
+ -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
+ GENERAL_REGS, 1)
+ * loop_cost);
+ record_address_regs (XEXP (SET_SRC (set), 0),
+ BASE_REG_CLASS, loop_cost * 2);
+ return insn;
+ }
+
+ /* Improve handling of two-address insns such as
+ (set X (ashift CONST Y)) where CONST must be made to
+ match X. Change it into two insns: (set X CONST)
+ (set X (ashift X Y)). If we left this for reloading, it
+ would probably get three insns because X and Y might go
+ in the same place. This prevents X and Y from receiving
+ the same hard reg.
+
+ We can only do this if the modes of operands 0 and 1
+ (which might not be the same) are tieable and we only need
+ do this during our first pass. */
+
+ if (pass == 0 && optimize
+ && recog_n_operands >= 3
+ && recog_constraints[1][0] == '0'
+ && recog_constraints[1][1] == 0
+ && CONSTANT_P (recog_operand[1])
+ && ! rtx_equal_p (recog_operand[0], recog_operand[1])
+ && ! rtx_equal_p (recog_operand[0], recog_operand[2])
+ && GET_CODE (recog_operand[0]) == REG
+ && MODES_TIEABLE_P (GET_MODE (recog_operand[0]),
+ recog_operand_mode[1]))
+ {
+ rtx previnsn = prev_real_insn (insn);
+ rtx dest
+ = gen_lowpart (recog_operand_mode[1],
+ recog_operand[0]);
+ rtx newinsn
+ = emit_insn_before (gen_move_insn (dest,
+ recog_operand[1]),
+ insn);
+
+ /* If this insn was the start of a basic block,
+ include the new insn in that block.
+ We need not check for code_label here;
+ while a basic block can start with a code_label,
+ INSN could not be at the beginning of that block. */
+ if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN)
+ {
+ int b;
+ for (b = 0; b < n_basic_blocks; b++)
+ if (insn == BLOCK_HEAD (b))
+ BLOCK_HEAD (b) = newinsn;
+ }
+
+ /* This makes one more setting of new insns's dest. */
+ REG_N_SETS (REGNO (recog_operand[0]))++;
+
+ *recog_operand_loc[1] = recog_operand[0];
+ for (i = recog_n_dups - 1; i >= 0; i--)
+ if (recog_dup_num[i] == 1)
+ *recog_dup_loc[i] = recog_operand[0];
+
+ return PREV_INSN (newinsn);
+ }
+
+ /* If we get here, we are set up to record the costs of all the
+ operands for this insn. Start by initializing the costs.
+ Then handle any address registers. Finally record the desired
+ classes for any pseudos, doing it twice if some pair of
+ operands are commutative. */
+
+ for (i = 0; i < recog_n_operands; i++)
+ {
+ op_costs[i] = init_cost;
+
+ if (GET_CODE (recog_operand[i]) == SUBREG)
+ {
+ rtx inner = SUBREG_REG (recog_operand[i]);
+ if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)))
+ subreg_changes_size[i] = 1;
+ recog_operand[i] = inner;
+ }
+
+ if (GET_CODE (recog_operand[i]) == MEM)
+ record_address_regs (XEXP (recog_operand[i], 0),
+ BASE_REG_CLASS, loop_cost * 2);
+ else if (constraints[i][0] == 'p')
+ record_address_regs (recog_operand[i],
+ BASE_REG_CLASS, loop_cost * 2);
+ }
+
+ /* Check for commutative in a separate loop so everything will
+ have been initialized. We must do this even if one operand
+ is a constant--see addsi3 in m68k.md. */
+
+ for (i = 0; i < recog_n_operands - 1; i++)
+ if (constraints[i][0] == '%')
+ {
+ const char *xconstraints[MAX_RECOG_OPERANDS];
+ int j;
+
+ /* Handle commutative operands by swapping the constraints.
+ We assume the modes are the same. */
+
+ for (j = 0; j < recog_n_operands; j++)
+ xconstraints[j] = constraints[j];
+
+ xconstraints[i] = constraints[i+1];
+ xconstraints[i+1] = constraints[i];
+ record_reg_classes (recog_n_alternatives, recog_n_operands,
+ recog_operand, modes, subreg_changes_size,
+ xconstraints, insn);
+ }
+
+ record_reg_classes (recog_n_alternatives, recog_n_operands, recog_operand,
+ modes, subreg_changes_size, constraints, insn);
+
+ /* Now add the cost for each operand to the total costs for
+ its register. */
+
+ for (i = 0; i < recog_n_operands; i++)
+ if (GET_CODE (recog_operand[i]) == REG
+ && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER)
+ {
+ int regno = REGNO (recog_operand[i]);
+ struct costs *p = &costs[regno], *q = &op_costs[i];
+
+ p->mem_cost += q->mem_cost * loop_cost;
+ for (j = 0; j < N_REG_CLASSES; j++)
+ p->cost[j] += q->cost[j] * loop_cost;
+ }
+
+ return insn;
+}
+
/* This is a pass of the compiler that scans all instructions
and calculates the preferred class for each pseudo-register.
This information can be accessed later by calling `reg_preferred_class'.
@@ -719,14 +954,12 @@ regclass (f, nregs)
{
#ifdef REGISTER_CONSTRAINTS
register rtx insn;
- register int i, j;
- struct costs init_cost;
- rtx set;
+ register int i;
int pass;
init_recog ();
- costs = (struct costs *) alloca (nregs * sizeof (struct costs));
+ costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
#ifdef FORBIDDEN_INC_DEC_CLASSES
@@ -741,6 +974,7 @@ regclass (f, nregs)
{
rtx r = gen_rtx_REG (VOIDmode, 0);
enum machine_mode m;
+ register int j;
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
@@ -780,10 +1014,6 @@ regclass (f, nregs)
}
#endif /* FORBIDDEN_INC_DEC_CLASSES */
- init_cost.mem_cost = 10000;
- for (i = 0; i < N_REG_CLASSES; i++)
- init_cost.cost[i] = 10000;
-
/* Normally we scan the insns once and determine the best class to use for
each register. However, if -fexpensive_optimizations are on, we do so
twice, the second time using the tentative best classes to guide the
@@ -806,199 +1036,9 @@ regclass (f, nregs)
for (insn = f; insn; insn = NEXT_INSN (insn))
{
- char *constraints[MAX_RECOG_OPERANDS];
- enum machine_mode modes[MAX_RECOG_OPERANDS];
- int nalternatives;
- int noperands;
-
- /* Show that an insn inside a loop is likely to be executed three
- times more than insns outside a loop. This is much more aggressive
- than the assumptions made elsewhere and is being tried as an
- experiment. */
-
- if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5));
- else if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
- loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5));
-
- else if ((GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER
- && GET_CODE (PATTERN (insn)) != ASM_INPUT)
- || (GET_CODE (insn) == JUMP_INSN
- && GET_CODE (PATTERN (insn)) != ADDR_VEC
- && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
- || GET_CODE (insn) == CALL_INSN)
- {
- if (GET_CODE (insn) == INSN
- && (noperands = asm_noperands (PATTERN (insn))) >= 0)
- {
- decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR,
- constraints, modes);
- nalternatives = (noperands == 0 ? 0
- : n_occurrences (',', constraints[0]) + 1);
- }
- else
- {
- int insn_code_number = recog_memoized (insn);
- rtx note;
-
- set = single_set (insn);
- insn_extract (insn);
-
- nalternatives = insn_n_alternatives[insn_code_number];
- noperands = insn_n_operands[insn_code_number];
-
- /* If this insn loads a parameter from its stack slot, then
- it represents a savings, rather than a cost, if the
- parameter is stored in memory. Record this fact. */
-
- if (set != 0 && GET_CODE (SET_DEST (set)) == REG
- && GET_CODE (SET_SRC (set)) == MEM
- && (note = find_reg_note (insn, REG_EQUIV,
- NULL_RTX)) != 0
- && GET_CODE (XEXP (note, 0)) == MEM)
- {
- costs[REGNO (SET_DEST (set))].mem_cost
- -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
- GENERAL_REGS, 1)
- * loop_cost);
- record_address_regs (XEXP (SET_SRC (set), 0),
- BASE_REG_CLASS, loop_cost * 2);
- continue;
- }
-
- /* Improve handling of two-address insns such as
- (set X (ashift CONST Y)) where CONST must be made to
- match X. Change it into two insns: (set X CONST)
- (set X (ashift X Y)). If we left this for reloading, it
- would probably get three insns because X and Y might go
- in the same place. This prevents X and Y from receiving
- the same hard reg.
-
- We can only do this if the modes of operands 0 and 1
- (which might not be the same) are tieable and we only need
- do this during our first pass. */
-
- if (pass == 0 && optimize
- && noperands >= 3
- && insn_operand_constraint[insn_code_number][1][0] == '0'
- && insn_operand_constraint[insn_code_number][1][1] == 0
- && CONSTANT_P (recog_operand[1])
- && ! rtx_equal_p (recog_operand[0], recog_operand[1])
- && ! rtx_equal_p (recog_operand[0], recog_operand[2])
- && GET_CODE (recog_operand[0]) == REG
- && MODES_TIEABLE_P (GET_MODE (recog_operand[0]),
- insn_operand_mode[insn_code_number][1]))
- {
- rtx previnsn = prev_real_insn (insn);
- rtx dest
- = gen_lowpart (insn_operand_mode[insn_code_number][1],
- recog_operand[0]);
- rtx newinsn
- = emit_insn_before (gen_move_insn (dest,
- recog_operand[1]),
- insn);
-
- /* If this insn was the start of a basic block,
- include the new insn in that block.
- We need not check for code_label here;
- while a basic block can start with a code_label,
- INSN could not be at the beginning of that block. */
- if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN)
- {
- int b;
- for (b = 0; b < n_basic_blocks; b++)
- if (insn == basic_block_head[b])
- basic_block_head[b] = newinsn;
- }
-
- /* This makes one more setting of new insns's dest. */
- REG_N_SETS (REGNO (recog_operand[0]))++;
-
- *recog_operand_loc[1] = recog_operand[0];
- for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
- if (recog_dup_num[i] == 1)
- *recog_dup_loc[i] = recog_operand[0];
-
- insn = PREV_INSN (newinsn);
- continue;
- }
-
- for (i = 0; i < noperands; i++)
- {
- constraints[i]
- = insn_operand_constraint[insn_code_number][i];
- modes[i] = insn_operand_mode[insn_code_number][i];
- }
- }
-
- /* If we get here, we are set up to record the costs of all the
- operands for this insn. Start by initializing the costs.
- Then handle any address registers. Finally record the desired
- classes for any pseudos, doing it twice if some pair of
- operands are commutative. */
-
- for (i = 0; i < noperands; i++)
- {
- op_costs[i] = init_cost;
-
- if (GET_CODE (recog_operand[i]) == SUBREG)
- recog_operand[i] = SUBREG_REG (recog_operand[i]);
-
- if (GET_CODE (recog_operand[i]) == MEM)
- record_address_regs (XEXP (recog_operand[i], 0),
- BASE_REG_CLASS, loop_cost * 2);
- else if (constraints[i][0] == 'p')
- record_address_regs (recog_operand[i],
- BASE_REG_CLASS, loop_cost * 2);
- }
-
- /* Check for commutative in a separate loop so everything will
- have been initialized. We must do this even if one operand
- is a constant--see addsi3 in m68k.md. */
-
- for (i = 0; i < noperands - 1; i++)
- if (constraints[i][0] == '%')
- {
- char *xconstraints[MAX_RECOG_OPERANDS];
- int j;
-
- /* Handle commutative operands by swapping the constraints.
- We assume the modes are the same. */
-
- for (j = 0; j < noperands; j++)
- xconstraints[j] = constraints[j];
-
- xconstraints[i] = constraints[i+1];
- xconstraints[i+1] = constraints[i];
- record_reg_classes (nalternatives, noperands,
- recog_operand, modes, xconstraints,
- insn);
- }
-
- record_reg_classes (nalternatives, noperands, recog_operand,
- modes, constraints, insn);
-
- /* Now add the cost for each operand to the total costs for
- its register. */
-
- for (i = 0; i < noperands; i++)
- if (GET_CODE (recog_operand[i]) == REG
- && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER)
- {
- int regno = REGNO (recog_operand[i]);
- struct costs *p = &costs[regno], *q = &op_costs[i];
-
- p->mem_cost += q->mem_cost * loop_cost;
- for (j = 0; j < N_REG_CLASSES; j++)
- p->cost[j] += q->cost[j] * loop_cost;
- }
- }
+ insn = scan_one_insn (insn, pass);
}
-
+
/* Now for each register look at how desirable each class is
and find which class is preferred. Store that in
`prefclass[REGNO]'. Record in `altclass[REGNO]' the largest register
@@ -1067,6 +1107,8 @@ regclass (f, nregs)
}
}
#endif /* REGISTER_CONSTRAINTS */
+
+ free (costs);
}
#ifdef REGISTER_CONSTRAINTS
@@ -1096,24 +1138,20 @@ regclass (f, nregs)
alternatives. */
static void
-record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
+record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
+ constraints, insn)
int n_alts;
int n_ops;
rtx *ops;
enum machine_mode *modes;
- char **constraints;
+ char *subreg_changes_size;
+ const char **constraints;
rtx insn;
{
int alt;
- enum op_type {OP_READ, OP_WRITE, OP_READ_WRITE} op_types[MAX_RECOG_OPERANDS];
int i, j;
rtx set;
- /* By default, each operand is an input operand. */
-
- for (i = 0; i < n_ops; i++)
- op_types[i] = OP_READ;
-
/* Process each alternative, each time minimizing an operand's cost with
the cost for each operand in that alternative. */
@@ -1127,12 +1165,16 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
for (i = 0; i < n_ops; i++)
{
- char *p = constraints[i];
+ const char *p = constraints[i];
rtx op = ops[i];
enum machine_mode mode = modes[i];
+ int allows_addr = 0;
int allows_mem = 0;
int win = 0;
- char c;
+ unsigned char c;
+
+ /* Initially show we know nothing about the register class. */
+ classes[i] = NO_REGS;
/* If this operand has no constraints at all, we can conclude
nothing about it since anything is valid. */
@@ -1145,12 +1187,13 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
continue;
}
- if (*p == '%')
- p++;
-
/* If this alternative is only relevant when this operand
matches a previous operand, we do different things depending
- on whether this operand is a pseudo-reg or not. */
+ on whether this operand is a pseudo-reg or not. We must process
+ any modifiers for the operand before we can make this test. */
+
+ while (*p == '%' || *p == '=' || *p == '+' || *p == '&')
+ p++;
if (p[0] >= '0' && p[0] <= '0' + i && (p[1] == ',' || p[1] == 0))
{
@@ -1216,18 +1259,9 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
any of the constraints. Collect the valid register classes
and see if this operand accepts memory. */
- classes[i] = NO_REGS;
while (*p && (c = *p++) != ',')
switch (c)
{
- case '=':
- op_types[i] = OP_WRITE;
- break;
-
- case '+':
- op_types[i] = OP_READ_WRITE;
- break;
-
case '*':
/* Ignore the next letter for this pass. */
p++;
@@ -1235,11 +1269,20 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
case '?':
alt_cost += 2;
- case '%':
- case '!': case '#':
- case '&':
+ case '!': case '#': case '&':
case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ break;
+
case 'p':
+ allows_addr = 1;
+ win = address_operand (op, GET_MODE (op));
+ /* We know this operand is an address, so we want it to be
+ allocated to a register that can be the base of an
+ address, ie BASE_REG_CLASS. */
+ classes[i]
+ = reg_class_subunion[(int) classes[i]]
+ [(int) BASE_REG_CLASS];
break;
case 'm': case 'o': case 'V':
@@ -1360,6 +1403,16 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
constraints[i] = p;
+#ifdef CLASS_CANNOT_CHANGE_SIZE
+ /* If we noted a subreg earlier, and the selected class is a
+ subclass of CLASS_CANNOT_CHANGE_SIZE, zap it. */
+ if (subreg_changes_size[i]
+ && (reg_class_subunion[(int) CLASS_CANNOT_CHANGE_SIZE]
+ [(int) classes[i]]
+ == CLASS_CANNOT_CHANGE_SIZE))
+ classes[i] = NO_REGS;
+#endif
+
/* How we account for this operand now depends on whether it is a
pseudo register or not. If it is, we first check if any
register classes are valid. If not, we ignore this alternative,
@@ -1370,7 +1423,15 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)
{
if (classes[i] == NO_REGS)
- alt_fail = 1;
+ {
+ /* We must always fail if the operand is a REG, but
+ we did not find a suitable class.
+
+ Otherwise we may perform an uninitialized read
+ from this_op_costs after the `continue' statement
+ below. */
+ alt_fail = 1;
+ }
else
{
struct costs *pp = &this_op_costs[i];
@@ -1392,7 +1453,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
if (prefclass)
alt_cost
- += may_move_cost[prefclass[REGNO (op)]][(int) classes[i]];
+ += may_move_cost[(unsigned char)prefclass[REGNO (op)]][(int) classes[i]];
}
}
@@ -1410,17 +1471,17 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
else if (classes[i] != NO_REGS)
{
- if (op_types[i] != OP_WRITE)
+ if (recog_op_type[i] != OP_OUT)
alt_cost += copy_cost (op, mode, classes[i], 1);
- if (op_types[i] != OP_READ)
+ if (recog_op_type[i] != OP_IN)
alt_cost += copy_cost (op, mode, classes[i], 0);
}
/* The only other way this alternative can be used is if this is a
constant that could be placed into memory. */
- else if (CONSTANT_P (op) && allows_mem)
+ else if (CONSTANT_P (op) && (allows_addr || allows_mem))
alt_cost += MEMORY_MOVE_COST (mode, classes[i], 1);
else
alt_fail = 1;
@@ -1437,7 +1498,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
&& REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)
{
struct costs *pp = &op_costs[i], *qq = &this_op_costs[i];
- int scale = 1 + (op_types[i] == OP_READ_WRITE);
+ int scale = 1 + (recog_op_type[i] == OP_INOUT);
pp->mem_cost = MIN (pp->mem_cost,
(qq->mem_cost + alt_cost) * scale);
@@ -1464,9 +1525,9 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
int nr;
if (regno >= FIRST_PSEUDO_REGISTER && prefclass != 0
- && (reg_class_size[prefclass[regno]]
+ && (reg_class_size[(unsigned char)prefclass[regno]]
== CLASS_MAX_NREGS (prefclass[regno], mode)))
- op_costs[i].cost[prefclass[regno]] = -1;
+ op_costs[i].cost[(unsigned char)prefclass[regno]] = -1;
else if (regno < FIRST_PSEUDO_REGISTER)
for (class = 0; class < N_REG_CLASSES; class++)
if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
@@ -1734,25 +1795,21 @@ auto_inc_dec_reg_p (reg, mode)
rtx reg;
enum machine_mode mode;
{
-#ifdef HAVE_POST_INCREMENT
- if (memory_address_p (mode, gen_rtx_POST_INC (Pmode, reg)))
+ if (HAVE_POST_INCREMENT
+ && memory_address_p (mode, gen_rtx_POST_INC (Pmode, reg)))
return 1;
-#endif
-#ifdef HAVE_POST_DECREMENT
- if (memory_address_p (mode, gen_rtx_POST_DEC (Pmode, reg)))
+ if (HAVE_POST_DECREMENT
+ && memory_address_p (mode, gen_rtx_POST_DEC (Pmode, reg)))
return 1;
-#endif
-#ifdef HAVE_PRE_INCREMENT
- if (memory_address_p (mode, gen_rtx_PRE_INC (Pmode, reg)))
+ if (HAVE_PRE_INCREMENT
+ && memory_address_p (mode, gen_rtx_PRE_INC (Pmode, reg)))
return 1;
-#endif
-#ifdef HAVE_PRE_DECREMENT
- if (memory_address_p (mode, gen_rtx_PRE_DEC (Pmode, reg)))
+ if (HAVE_PRE_DECREMENT
+ && memory_address_p (mode, gen_rtx_PRE_DEC (Pmode, reg)))
return 1;
-#endif
return 0;
}
@@ -1760,6 +1817,9 @@ auto_inc_dec_reg_p (reg, mode)
#endif /* REGISTER_CONSTRAINTS */
+static short *renumber = (short *)0;
+static size_t regno_allocated = 0;
+
/* Allocate enough space to hold NUM_REGS registers for the tables used for
reg_scan and flow_analysis that are indexed by the register number. If
NEW_P is non zero, initialize all of the registers, otherwise only
@@ -1773,39 +1833,12 @@ allocate_reg_info (num_regs, new_p, renumber_p)
int new_p;
int renumber_p;
{
- static size_t regno_allocated = 0;
- static short *renumber = (short *)0;
- int i;
size_t size_info;
size_t size_renumber;
size_t min = (new_p) ? 0 : reg_n_max;
struct reg_info_data *reg_data;
struct reg_info_data *reg_next;
- /* Free up all storage allocated */
- if (num_regs < 0)
- {
- if (reg_n_info)
- {
- VARRAY_FREE (reg_n_info);
- for (reg_data = reg_info_head; reg_data; reg_data = reg_next)
- {
- reg_next = reg_data->next;
- free ((char *)reg_data);
- }
-
- free (prefclass_buffer);
- free (altclass_buffer);
- prefclass_buffer = (char *)0;
- altclass_buffer = (char *)0;
- reg_info_head = (struct reg_info_data *)0;
- renumber = (short *)0;
- }
- regno_allocated = 0;
- reg_n_max = 0;
- return;
- }
-
if (num_regs > regno_allocated)
{
size_t old_allocated = regno_allocated;
@@ -1870,6 +1903,8 @@ allocate_reg_info (num_regs, new_p, renumber_p)
{
size_t max = max_index;
size_t local_min = min - min_index;
+ size_t i;
+
if (min < min_index)
local_min = 0;
if (!reg_data->used_p) /* page just allocated with calloc */
@@ -1905,6 +1940,32 @@ allocate_reg_info (num_regs, new_p, renumber_p)
MAX_REGNO_REG_SET (num_regs, new_p, renumber_p);
}
+/* Free up the space allocated by allocate_reg_info. */
+void
+free_reg_info ()
+{
+ if (reg_n_info)
+ {
+ struct reg_info_data *reg_data;
+ struct reg_info_data *reg_next;
+
+ VARRAY_FREE (reg_n_info);
+ for (reg_data = reg_info_head; reg_data; reg_data = reg_next)
+ {
+ reg_next = reg_data->next;
+ free ((char *)reg_data);
+ }
+
+ free (prefclass_buffer);
+ free (altclass_buffer);
+ prefclass_buffer = (char *)0;
+ altclass_buffer = (char *)0;
+ reg_info_head = (struct reg_info_data *)0;
+ renumber = (short *)0;
+ }
+ regno_allocated = 0;
+ reg_n_max = 0;
+}
/* This is the `regscan' pass of the compiler, run just before cse
and again just before loop.
@@ -1993,18 +2054,11 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
register rtx dest;
register rtx note;
- /* This can happen when scanning insns referenced by certain notes.
-
- It is unclear if we should be scanning such insns; until someone can
- say for sure this seems like the safest fix. */
- if (x == NULL_RTX)
- return;
-
code = GET_CODE (x);
switch (code)
{
- case CONST_INT:
case CONST:
+ case CONST_INT:
case CONST_DOUBLE:
case CC0:
case PC:
@@ -2173,12 +2227,5 @@ reg_classes_intersect_p (c1, c2)
void
regset_release_memory ()
{
- if (basic_block_live_at_start)
- {
- free_regset_vector (basic_block_live_at_start, n_basic_blocks);
- basic_block_live_at_start = 0;
- }
-
- FREE_REG_SET (regs_live_at_setjmp);
bitmap_release_memory ();
}
diff --git a/contrib/gcc/regmove.c b/contrib/gcc/regmove.c
index 605169a..81a3520 100644
--- a/contrib/gcc/regmove.c
+++ b/contrib/gcc/regmove.c
@@ -15,7 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* This module looks for cases where matching constraints would force
@@ -24,16 +25,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
instruction to avoid the move instruction. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-/* stdio.h must precede rtl.h for FFS. */
#include "system.h"
-
-#include "rtl.h"
+#include "rtl.h" /* stdio.h must precede rtl.h for FFS. */
#include "insn-config.h"
#include "recog.h"
#include "output.h"
@@ -50,7 +43,7 @@ static int optimize_reg_copy_1 PROTO((rtx, rtx, rtx));
static void optimize_reg_copy_2 PROTO((rtx, rtx, rtx));
static void optimize_reg_copy_3 PROTO((rtx, rtx, rtx));
static rtx gen_add3_insn PROTO((rtx, rtx, rtx));
-static void copy_src_to_dest PROTO((rtx, rtx, rtx, int));
+static void copy_src_to_dest PROTO((rtx, rtx, rtx, int, int));
static int *regmove_bb_head;
struct match {
@@ -60,16 +53,32 @@ struct match {
int early_clobber[MAX_RECOG_OPERANDS];
};
-#ifdef AUTO_INC_DEC
+static rtx discover_flags_reg PROTO((void));
+static void mark_flags_life_zones PROTO((rtx));
+static void flags_set_1 PROTO((rtx, rtx));
+
static int try_auto_increment PROTO((rtx, rtx, rtx, rtx, HOST_WIDE_INT, int));
-#endif
static int find_matches PROTO((rtx, struct match *));
static int fixup_match_1 PROTO((rtx, rtx, rtx, rtx, rtx, int, int, int, FILE *))
;
static int reg_is_remote_constant_p PROTO((rtx, rtx, rtx));
static int stable_but_for_p PROTO((rtx, rtx, rtx));
+static int regclass_compatible_p PROTO((int, int));
static int loop_depth;
+/* Return non-zero if registers with CLASS1 and CLASS2 can be merged without
+ causing too much register allocation problems. */
+static int
+regclass_compatible_p (class0, class1)
+ int class0, class1;
+{
+ return (class0 == class1
+ || (reg_class_subset_p (class0, class1)
+ && ! CLASS_LIKELY_SPILLED_P (class0))
+ || (reg_class_subset_p (class1, class0)
+ && ! CLASS_LIKELY_SPILLED_P (class1)));
+}
+
/* Generate and return an insn body to add r1 and c,
storing the result in r0. */
static rtx
@@ -87,7 +96,6 @@ gen_add3_insn (r0, r1, c)
return (GEN_FCN (icode) (r0, r1, c));
}
-#ifdef AUTO_INC_DEC
/* INC_INSN is an instruction that adds INCREMENT to REG.
Try to fold INC_INSN as a post/pre in/decrement into INSN.
@@ -111,18 +119,14 @@ try_auto_increment (insn, inc_insn, inc_insn_set, reg, increment, pre)
{
int size = GET_MODE_SIZE (GET_MODE (use));
if (0
-#ifdef HAVE_POST_INCREMENT
- || (pre == 0 && (inc_code = POST_INC, increment == size))
-#endif
-#ifdef HAVE_PRE_INCREMENT
- || (pre == 1 && (inc_code = PRE_INC, increment == size))
-#endif
-#ifdef HAVE_POST_DECREMENT
- || (pre == 0 && (inc_code = POST_DEC, increment == -size))
-#endif
-#ifdef HAVE_PRE_DECREMENT
- || (pre == 1 && (inc_code = PRE_DEC, increment == -size))
-#endif
+ || (HAVE_POST_INCREMENT
+ && pre == 0 && (inc_code = POST_INC, increment == size))
+ || (HAVE_PRE_INCREMENT
+ && pre == 1 && (inc_code = PRE_INC, increment == size))
+ || (HAVE_POST_DECREMENT
+ && pre == 0 && (inc_code = POST_DEC, increment == -size))
+ || (HAVE_PRE_DECREMENT
+ && pre == 1 && (inc_code = PRE_DEC, increment == -size))
)
{
if (inc_insn_set)
@@ -150,8 +154,175 @@ try_auto_increment (insn, inc_insn, inc_insn_set, reg, increment, pre)
}
return 0;
}
-#endif /* AUTO_INC_DEC */
+
+/* Determine if the pattern generated by add_optab has a clobber,
+ such as might be issued for a flags hard register. To make the
+ code elsewhere simpler, we handle cc0 in this same framework.
+
+ Return the register if one was discovered. Return NULL_RTX if
+ if no flags were found. Return pc_rtx if we got confused. */
+
+static rtx
+discover_flags_reg ()
+{
+ rtx tmp;
+ tmp = gen_rtx_REG (word_mode, 10000);
+ tmp = gen_add3_insn (tmp, tmp, GEN_INT (2));
+
+ /* If we get something that isn't a simple set, or a
+ [(set ..) (clobber ..)], this whole function will go wrong. */
+ if (GET_CODE (tmp) == SET)
+ return NULL_RTX;
+ else if (GET_CODE (tmp) == PARALLEL)
+ {
+ int found;
+
+ if (XVECLEN (tmp, 0) != 2)
+ return pc_rtx;
+ tmp = XVECEXP (tmp, 0, 1);
+ if (GET_CODE (tmp) != CLOBBER)
+ return pc_rtx;
+ tmp = XEXP (tmp, 0);
+
+ /* Don't do anything foolish if the md wanted to clobber a
+ scratch or something. We only care about hard regs.
+ Moreover we don't like the notion of subregs of hard regs. */
+ if (GET_CODE (tmp) == SUBREG
+ && GET_CODE (SUBREG_REG (tmp)) == REG
+ && REGNO (SUBREG_REG (tmp)) < FIRST_PSEUDO_REGISTER)
+ return pc_rtx;
+ found = (GET_CODE (tmp) == REG && REGNO (tmp) < FIRST_PSEUDO_REGISTER);
+
+ return (found ? tmp : NULL_RTX);
+ }
+
+ return pc_rtx;
+}
+
+/* It is a tedious task identifying when the flags register is live and
+ when it is safe to optimize. Since we process the instruction stream
+ multiple times, locate and record these live zones by marking the
+ mode of the instructions --
+
+ QImode is used on the instruction at which the flags becomes live.
+
+ HImode is used within the range (exclusive) that the flags are
+ live. Thus the user of the flags is not marked.
+
+ All other instructions are cleared to VOIDmode. */
+/* Used to communicate with flags_set_1. */
+static rtx flags_set_1_rtx;
+static int flags_set_1_set;
+
+static void
+mark_flags_life_zones (flags)
+ rtx flags;
+{
+ int flags_regno;
+ int flags_nregs;
+ int block;
+
+#ifdef HAVE_cc0
+ /* If we found a flags register on a cc0 host, bail. */
+ if (flags == NULL_RTX)
+ flags = cc0_rtx;
+ else if (flags != cc0_rtx)
+ flags = pc_rtx;
+#endif
+
+ /* Simple cases first: if no flags, clear all modes. If confusing,
+ mark the entire function as being in a flags shadow. */
+ if (flags == NULL_RTX || flags == pc_rtx)
+ {
+ enum machine_mode mode = (flags ? HImode : VOIDmode);
+ rtx insn;
+ for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
+ PUT_MODE (insn, mode);
+ return;
+ }
+
+#ifdef HAVE_cc0
+ flags_regno = -1;
+ flags_nregs = 1;
+#else
+ flags_regno = REGNO (flags);
+ flags_nregs = HARD_REGNO_NREGS (flags_regno, GET_MODE (flags));
+#endif
+ flags_set_1_rtx = flags;
+
+ /* Process each basic block. */
+ for (block = n_basic_blocks - 1; block >= 0; block--)
+ {
+ rtx insn, end;
+ int live;
+
+ insn = BLOCK_HEAD (block);
+ end = BLOCK_END (block);
+
+ /* Look out for the (unlikely) case of flags being live across
+ basic block boundaries. */
+ live = 0;
+#ifndef HAVE_cc0
+ {
+ int i;
+ for (i = 0; i < flags_nregs; ++i)
+ live |= REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start,
+ flags_regno + i);
+ }
+#endif
+
+ while (1)
+ {
+ /* Process liveness in reverse order of importance --
+ alive, death, birth. This lets more important info
+ overwrite the mode of lesser info. */
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+#ifdef HAVE_cc0
+ /* In the cc0 case, death is not marked in reg notes,
+ but is instead the mere use of cc0 when it is alive. */
+ if (live && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
+ live = 0;
+#else
+ /* In the hard reg case, we watch death notes. */
+ if (live && find_regno_note (insn, REG_DEAD, flags_regno))
+ live = 0;
+#endif
+ PUT_MODE (insn, (live ? HImode : VOIDmode));
+
+ /* In either case, birth is denoted simply by it's presence
+ as the destination of a set. */
+ flags_set_1_set = 0;
+ note_stores (PATTERN (insn), flags_set_1);
+ if (flags_set_1_set)
+ {
+ live = 1;
+ PUT_MODE (insn, QImode);
+ }
+ }
+ else
+ PUT_MODE (insn, (live ? HImode : VOIDmode));
+
+ if (insn == end)
+ break;
+ insn = NEXT_INSN (insn);
+ }
+ }
+}
+
+/* A subroutine of mark_flags_life_zones, called through note_stores. */
+
+static void
+flags_set_1 (x, pat)
+ rtx x, pat;
+{
+ if (GET_CODE (pat) == SET
+ && reg_overlap_mentioned_p (x, flags_set_1_rtx))
+ flags_set_1_set = 1;
+}
+
static int *regno_src_regno;
/* Indicate how good a choice REG (which appears as a source) is to replace
@@ -496,18 +667,6 @@ optimize_reg_copy_3 (insn, dest, src)
rtx p, set, subreg;
enum machine_mode old_mode;
- /* This code has been disabled on the egcs-1.1 release branch due to
- a potentially serious bug.
-
- In a nutshell, if we perform a series of substitutions, then have a
- later substitution fail we will not be able to undo the previous
- substitutions, leaving bogus RTL.
-
- A fix for this can be found in the mainline sources, but it did not
- seem worth the trouble and potential problems to migrate the real
- fix to the egcs-1.1 branch. */
- return;
-
if (src_no < FIRST_PSEUDO_REGISTER
|| dst_no < FIRST_PSEUDO_REGISTER
|| ! find_reg_note (insn, REG_DEAD, src_reg)
@@ -536,23 +695,48 @@ optimize_reg_copy_3 (insn, dest, src)
|| GET_CODE (SET_SRC (set)) != MEM
|| SET_DEST (set) != src_reg)
return;
+
+ /* Be conserative: although this optimization is also valid for
+ volatile memory references, that could cause trouble in later passes. */
+ if (MEM_VOLATILE_P (SET_SRC (set)))
+ return;
+
+ /* Do not use a SUBREG to truncate from one mode to another if truncation
+ is not a nop. */
+ if (GET_MODE_BITSIZE (GET_MODE (src_reg)) <= GET_MODE_BITSIZE (GET_MODE (src))
+ && !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE (src)),
+ GET_MODE_BITSIZE (GET_MODE (src_reg))))
+ return;
+
old_mode = GET_MODE (src_reg);
PUT_MODE (src_reg, GET_MODE (src));
XEXP (src, 0) = SET_SRC (set);
- if (! validate_change (p, &SET_SRC (set), src, 0))
- {
- PUT_MODE (src_reg, old_mode);
- XEXP (src, 0) = src_reg;
- return;
- }
+
+ /* Include this change in the group so that it's easily undone if
+ one of the changes in the group is invalid. */
+ validate_change (p, &SET_SRC (set), src, 1);
+
+ /* Now walk forward making additional replacements. We want to be able
+ to undo all the changes if a later substitution fails. */
subreg = gen_rtx_SUBREG (old_mode, src_reg, 0);
while (p = NEXT_INSN (p), p != insn)
{
if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
continue;
- validate_replace_rtx (src_reg, subreg, p);
+
+ /* Make a tenative change. */
+ validate_replace_rtx_group (src_reg, subreg, p);
+ }
+
+ validate_replace_rtx_group (src, src_reg, insn);
+
+ /* Now see if all the changes are valid. */
+ if (! apply_change_group ())
+ {
+ /* One or more changes were no good. Back out everything. */
+ PUT_MODE (src_reg, old_mode);
+ XEXP (src, 0) = src_reg;
}
- validate_replace_rtx (src, src_reg, insn);
}
@@ -560,11 +744,12 @@ optimize_reg_copy_3 (insn, dest, src)
instead moving the value to dest directly before the operation. */
static void
-copy_src_to_dest (insn, src, dest, loop_depth)
+copy_src_to_dest (insn, src, dest, loop_depth, old_max_uid)
rtx insn;
rtx src;
rtx dest;
int loop_depth;
+ int old_max_uid;
{
rtx seq;
rtx link;
@@ -590,13 +775,25 @@ copy_src_to_dest (insn, src, dest, loop_depth)
&& REG_LIVE_LENGTH (REGNO (dest)) > 0
&& (set = single_set (insn)) != NULL_RTX
&& !reg_mentioned_p (dest, SET_SRC (set))
- && validate_replace_rtx (src, dest, insn))
+ && GET_MODE (src) == GET_MODE (dest))
{
+ int old_num_regs = reg_rtx_no;
+
/* Generate the src->dest move. */
start_sequence ();
emit_move_insn (dest, src);
seq = gen_sequence ();
end_sequence ();
+ /* If this sequence uses new registers, we may not use it. */
+ if (old_num_regs != reg_rtx_no
+ || ! validate_replace_rtx (src, dest, insn))
+ {
+ /* We have to restore reg_rtx_no to its old value, lest
+ recompute_reg_usage will try to compute the usage of the
+ new regs, yet reg_n_info is not valid for them. */
+ reg_rtx_no = old_num_regs;
+ return;
+ }
emit_insn_before (seq, insn);
move_insn = PREV_INSN (insn);
p_move_notes = &REG_NOTES (move_insn);
@@ -624,11 +821,14 @@ copy_src_to_dest (insn, src, dest, loop_depth)
/* Is the insn the head of a basic block? If so extend it */
insn_uid = INSN_UID (insn);
move_uid = INSN_UID (move_insn);
- bb = regmove_bb_head[insn_uid];
- if (bb >= 0)
+ if (insn_uid < old_max_uid)
{
- basic_block_head[bb] = move_insn;
- regmove_bb_head[insn_uid] = -1;
+ bb = regmove_bb_head[insn_uid];
+ if (bb >= 0)
+ {
+ BLOCK_HEAD (bb) = move_insn;
+ regmove_bb_head[insn_uid] = -1;
+ }
}
/* Update the various register tables. */
@@ -877,19 +1077,24 @@ regmove_optimize (f, nregs, regmove_dump_file)
int nregs;
FILE *regmove_dump_file;
{
+ int old_max_uid = get_max_uid ();
rtx insn;
struct match match;
int pass;
- int maxregnum = max_reg_num (), i;
+ int i;
rtx copy_src, copy_dst;
- regno_src_regno = (int *)alloca (sizeof *regno_src_regno * maxregnum);
- for (i = maxregnum; --i >= 0; ) regno_src_regno[i] = -1;
+ /* Find out where a potential flags register is live, and so that we
+ can supress some optimizations in those zones. */
+ mark_flags_life_zones (discover_flags_reg ());
- regmove_bb_head = (int *)alloca (sizeof (int) * (get_max_uid () + 1));
- for (i = get_max_uid (); i >= 0; i--) regmove_bb_head[i] = -1;
+ regno_src_regno = (int *)alloca (sizeof *regno_src_regno * nregs);
+ for (i = nregs; --i >= 0; ) regno_src_regno[i] = -1;
+
+ regmove_bb_head = (int *)alloca (sizeof (int) * (old_max_uid + 1));
+ for (i = old_max_uid; i >= 0; i--) regmove_bb_head[i] = -1;
for (i = 0; i < n_basic_blocks; i++)
- regmove_bb_head[INSN_UID (basic_block_head[i])] = i;
+ regmove_bb_head[INSN_UID (BLOCK_HEAD (i))] = i;
/* A forward/backward pass. Replace output operands with input operands. */
@@ -908,8 +1113,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
insn = pass ? PREV_INSN (insn) : NEXT_INSN (insn))
{
rtx set;
- int insn_code_number;
- int operand_number, match_number;
+ int op_no, match_no;
if (GET_CODE (insn) == NOTE)
{
@@ -954,11 +1158,11 @@ regmove_optimize (f, nregs, regmove_dump_file)
}
}
}
-#ifdef REGISTER_CONSTRAINTS
- insn_code_number
- = find_matches (insn, &match);
+ if (! flag_regmove)
+ continue;
- if (insn_code_number < 0)
+#ifdef REGISTER_CONSTRAINTS
+ if (! find_matches (insn, &match))
continue;
/* Now scan through the operands looking for a source operand
@@ -968,21 +1172,19 @@ regmove_optimize (f, nregs, regmove_dump_file)
If it dies there, then replace the dest in both operands with
the source operand. */
- for (operand_number = 0;
- operand_number < insn_n_operands[insn_code_number];
- operand_number++)
+ for (op_no = 0; op_no < recog_n_operands; op_no++)
{
rtx src, dst, src_subreg;
enum reg_class src_class, dst_class;
- match_number = match.with[operand_number];
+ match_no = match.with[op_no];
/* Nothing to do if the two operands aren't supposed to match. */
- if (match_number < 0)
+ if (match_no < 0)
continue;
- src = recog_operand[operand_number];
- dst = recog_operand[match_number];
+ src = recog_operand[op_no];
+ dst = recog_operand[match_no];
if (GET_CODE (src) != REG)
continue;
@@ -1003,7 +1205,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
if (REGNO (src) < FIRST_PSEUDO_REGISTER)
{
- if (match.commutative[operand_number] < operand_number)
+ if (match.commutative[op_no] < op_no)
regno_src_regno[REGNO (dst)] = REGNO (src);
continue;
}
@@ -1011,42 +1213,38 @@ regmove_optimize (f, nregs, regmove_dump_file)
if (REG_LIVE_LENGTH (REGNO (src)) < 0)
continue;
- /* operand_number/src must be a read-only operand, and
+ /* op_no/src must be a read-only operand, and
match_operand/dst must be a write-only operand. */
- if (match.use[operand_number] != READ
- || match.use[match_number] != WRITE)
+ if (match.use[op_no] != READ
+ || match.use[match_no] != WRITE)
continue;
- if (match.early_clobber[match_number]
+ if (match.early_clobber[match_no]
&& count_occurrences (PATTERN (insn), src) > 1)
continue;
/* Make sure match_operand is the destination. */
- if (recog_operand[match_number] != SET_DEST (set))
+ if (recog_operand[match_no] != SET_DEST (set))
continue;
/* If the operands already match, then there is nothing to do. */
/* But in the commutative case, we might find a better match. */
if (operands_match_p (src, dst)
- || (match.commutative[operand_number] >= 0
+ || (match.commutative[op_no] >= 0
&& operands_match_p (recog_operand[match.commutative
- [operand_number]], dst)
+ [op_no]], dst)
&& (replacement_quality (recog_operand[match.commutative
- [operand_number]])
+ [op_no]])
>= replacement_quality (src))))
continue;
src_class = reg_preferred_class (REGNO (src));
dst_class = reg_preferred_class (REGNO (dst));
- if (src_class != dst_class
- && (! reg_class_subset_p (src_class, dst_class)
- || CLASS_LIKELY_SPILLED_P (src_class))
- && (! reg_class_subset_p (dst_class, src_class)
- || CLASS_LIKELY_SPILLED_P (dst_class)))
+ if (! regclass_compatible_p (src_class, dst_class))
continue;
if (fixup_match_1 (insn, set, src, src_subreg, dst, pass,
- operand_number, match_number,
+ op_no, match_no,
regmove_dump_file))
break;
}
@@ -1071,11 +1269,10 @@ regmove_optimize (f, nregs, regmove_dump_file)
}
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
- int insn_code_number = find_matches (insn, &match);
- int operand_number, match_number;
+ int op_no, match_no;
int success = 0;
-
- if (insn_code_number < 0)
+
+ if (! find_matches (insn, &match))
continue;
/* Now scan through the operands looking for a destination operand
@@ -1086,9 +1283,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
copy_src = NULL_RTX;
copy_dst = NULL_RTX;
- for (operand_number = 0;
- operand_number < insn_n_operands[insn_code_number];
- operand_number++)
+ for (op_no = 0; op_no < recog_n_operands; op_no++)
{
rtx set, p, src, dst;
rtx src_note, dst_note;
@@ -1096,14 +1291,14 @@ regmove_optimize (f, nregs, regmove_dump_file)
enum reg_class src_class, dst_class;
int length;
- match_number = match.with[operand_number];
+ match_no = match.with[op_no];
/* Nothing to do if the two operands aren't supposed to match. */
- if (match_number < 0)
+ if (match_no < 0)
continue;
- dst = recog_operand[match_number];
- src = recog_operand[operand_number];
+ dst = recog_operand[match_no];
+ src = recog_operand[op_no];
if (GET_CODE (src) != REG)
continue;
@@ -1115,26 +1310,26 @@ regmove_optimize (f, nregs, regmove_dump_file)
/* If the operands already match, then there is nothing to do. */
if (operands_match_p (src, dst)
- || (match.commutative[operand_number] >= 0
- && operands_match_p (recog_operand[match.commutative[operand_number]], dst)))
+ || (match.commutative[op_no] >= 0
+ && operands_match_p (recog_operand[match.commutative[op_no]], dst)))
continue;
set = single_set (insn);
if (! set)
continue;
- /* match_number/dst must be a write-only operand, and
+ /* match_no/dst must be a write-only operand, and
operand_operand/src must be a read-only operand. */
- if (match.use[operand_number] != READ
- || match.use[match_number] != WRITE)
+ if (match.use[op_no] != READ
+ || match.use[match_no] != WRITE)
continue;
- if (match.early_clobber[match_number]
+ if (match.early_clobber[match_no]
&& count_occurrences (PATTERN (insn), src) > 1)
continue;
- /* Make sure match_number is the destination. */
- if (recog_operand[match_number] != SET_DEST (set))
+ /* Make sure match_no is the destination. */
+ if (recog_operand[match_no] != SET_DEST (set))
continue;
if (REGNO (src) < FIRST_PSEUDO_REGISTER)
@@ -1150,11 +1345,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
}
src_class = reg_preferred_class (REGNO (src));
dst_class = reg_preferred_class (REGNO (dst));
- if (src_class != dst_class
- && (! reg_class_subset_p (src_class, dst_class)
- || CLASS_LIKELY_SPILLED_P (src_class))
- && (! reg_class_subset_p (dst_class, src_class)
- || CLASS_LIKELY_SPILLED_P (dst_class)))
+ if (! regclass_compatible_p (src_class, dst_class))
{
if (!copy_src)
{
@@ -1206,11 +1397,11 @@ regmove_optimize (f, nregs, regmove_dump_file)
if (regmove_dump_file)
fprintf (regmove_dump_file,
"Could fix operand %d of insn %d matching operand %d.\n",
- operand_number, INSN_UID (insn), match_number);
+ op_no, INSN_UID (insn), match_no);
/* Scan backward to find the first instruction that uses
the input operand. If the operand is set here, then
- replace it in both instructions with match_number. */
+ replace it in both instructions with match_no. */
for (length = 0, p = PREV_INSN (insn); p; p = PREV_INSN (p))
{
@@ -1258,7 +1449,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
validate_replace_rtx (dst, src, insn);
/* Now make sure the dst is right. */
validate_change (insn,
- recog_operand_loc[match_number],
+ recog_operand_loc[match_no],
dst, 0);
}
}
@@ -1338,7 +1529,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
if (regmove_dump_file)
fprintf (regmove_dump_file,
"Fixed operand %d of insn %d matching operand %d.\n",
- operand_number, INSN_UID (insn), match_number);
+ op_no, INSN_UID (insn), match_no);
break;
}
@@ -1347,16 +1538,30 @@ regmove_optimize (f, nregs, regmove_dump_file)
/* If we weren't able to replace any of the alternatives, try an
alternative appoach of copying the source to the destination. */
if (!success && copy_src != NULL_RTX)
- copy_src_to_dest (insn, copy_src, copy_dst, loop_depth);
+ copy_src_to_dest (insn, copy_src, copy_dst, loop_depth,
+ old_max_uid);
}
}
#endif /* REGISTER_CONSTRAINTS */
+
+ /* In fixup_match_1, some insns may have been inserted after basic block
+ ends. Fix that here. */
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ rtx end = BLOCK_END (i);
+ rtx new = end;
+ rtx next = NEXT_INSN (new);
+ while (next != 0 && INSN_UID (next) >= old_max_uid
+ && (i == n_basic_blocks - 1 || BLOCK_HEAD (i + 1) != next))
+ new = next, next = NEXT_INSN (new);
+ BLOCK_END (i) = new;
+ }
}
-/* Returns the INSN_CODE for INSN if its pattern has matching constraints for
- any operand. Returns -1 if INSN can't be recognized, or if the alternative
- can't be determined.
+/* Returns nonzero if INSN's pattern has matching constraints for any operand.
+ Returns 0 if INSN can't be recognized, or if the alternative can't be
+ determined.
Initialize the info in MATCHP based on the constraints. */
@@ -1366,39 +1571,34 @@ find_matches (insn, matchp)
struct match *matchp;
{
int likely_spilled[MAX_RECOG_OPERANDS];
- int operand_number;
- int insn_code_number = recog_memoized (insn);
+ int op_no;
int any_matches = 0;
- if (insn_code_number < 0)
- return -1;
-
- insn_extract (insn);
- if (! constrain_operands (insn_code_number, 0))
- return -1;
+ extract_insn (insn);
+ if (! constrain_operands (0))
+ return 0;
/* Must initialize this before main loop, because the code for
the commutative case may set matches for operands other than
the current one. */
- for (operand_number = insn_n_operands[insn_code_number];
- --operand_number >= 0; )
- matchp->with[operand_number] = matchp->commutative[operand_number] = -1;
+ for (op_no = recog_n_operands; --op_no >= 0; )
+ matchp->with[op_no] = matchp->commutative[op_no] = -1;
- for (operand_number = 0; operand_number < insn_n_operands[insn_code_number];
- operand_number++)
+ for (op_no = 0; op_no < recog_n_operands; op_no++)
{
- char *p, c;
+ const char *p;
+ char c;
int i = 0;
- p = insn_operand_constraint[insn_code_number][operand_number];
+ p = recog_constraints[op_no];
- likely_spilled[operand_number] = 0;
- matchp->use[operand_number] = READ;
- matchp->early_clobber[operand_number] = 0;
+ likely_spilled[op_no] = 0;
+ matchp->use[op_no] = READ;
+ matchp->early_clobber[op_no] = 0;
if (*p == '=')
- matchp->use[operand_number] = WRITE;
+ matchp->use[op_no] = WRITE;
else if (*p == '+')
- matchp->use[operand_number] = READWRITE;
+ matchp->use[op_no] = READWRITE;
for (;*p && i < which_alternative; p++)
if (*p == ',')
@@ -1412,32 +1612,32 @@ find_matches (insn, matchp)
case '+':
break;
case '&':
- matchp->early_clobber[operand_number] = 1;
+ matchp->early_clobber[op_no] = 1;
break;
case '%':
- matchp->commutative[operand_number] = operand_number + 1;
- matchp->commutative[operand_number + 1] = operand_number;
+ matchp->commutative[op_no] = op_no + 1;
+ matchp->commutative[op_no + 1] = op_no;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c -= '0';
- if (c < operand_number && likely_spilled[(unsigned char) c])
+ if (c < op_no && likely_spilled[(unsigned char) c])
break;
- matchp->with[operand_number] = c;
+ matchp->with[op_no] = c;
any_matches = 1;
- if (matchp->commutative[operand_number] >= 0)
- matchp->with[matchp->commutative[operand_number]] = c;
+ if (matchp->commutative[op_no] >= 0)
+ matchp->with[matchp->commutative[op_no]] = c;
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h':
case 'j': case 'k': case 'l': case 'p': case 'q': case 't': case 'u':
case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
case 'C': case 'D': case 'W': case 'Y': case 'Z':
- if (CLASS_LIKELY_SPILLED_P (REG_CLASS_FROM_LETTER (c)))
- likely_spilled[operand_number] = 1;
+ if (CLASS_LIKELY_SPILLED_P (REG_CLASS_FROM_LETTER ((unsigned char)c)))
+ likely_spilled[op_no] = 1;
break;
}
}
- return any_matches ? insn_code_number : -1;
+ return any_matches;
}
/* Try to replace output operand DST in SET, with input operand SRC. SET is
@@ -1590,13 +1790,17 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
This also gives opportunities for subsequent
optimizations in the backward pass, so do it there. */
if (code == PLUS && backward
-#ifdef HAVE_cc0
- /* We may not emit an insn directly
- after P if the latter sets CC0. */
- && ! sets_cc0_p (PATTERN (p))
-#endif
- )
-
+ /* Don't do this if we can likely tie DST to SET_DEST
+ of P later; we can't do this tying here if we got a
+ hard register. */
+ && ! (dst_note && ! REG_N_CALLS_CROSSED (REGNO (dst))
+ && single_set (p)
+ && GET_CODE (SET_DEST (single_set (p))) == REG
+ && (REGNO (SET_DEST (single_set (p)))
+ < FIRST_PSEUDO_REGISTER))
+ /* We may only emit an insn directly after P if we
+ are not in the shadow of a live flags register. */
+ && GET_MODE (p) == VOIDmode)
{
search_end = q;
q = insn;
@@ -1670,11 +1874,10 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
if (code == MINUS)
{
post_inc = emit_insn_after (copy_rtx (PATTERN (insn)), p);
-#if defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT)
- if (search_end
+ if ((HAVE_PRE_INCREMENT || HAVE_PRE_DECREMENT)
+ && search_end
&& try_auto_increment (search_end, post_inc, 0, src, newconst, 1))
post_inc = 0;
-#endif
validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (insn_const), 0);
REG_N_SETS (REGNO (src))++;
REG_N_REFS (REGNO (src)) += true_loop_depth;
@@ -1687,12 +1890,11 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
rtx pat = PATTERN (insn);
if (src_note)
remove_note (overlap, src_note);
-#if defined (HAVE_POST_INCREMENT) || defined (HAVE_POST_DECREMENT)
- if (code == PLUS
+ if ((HAVE_POST_INCREMENT || HAVE_POST_DECREMENT)
+ && code == PLUS
&& try_auto_increment (overlap, insn, 0, src, insn_const, 0))
insn = overlap;
else
-#endif
{
rtx notes = REG_NOTES (insn);
@@ -1775,35 +1977,23 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
}
}
- /* Don't remove this seemingly useless if, it is needed to pair with the
- else in the next two conditionally included code blocks. */
- if (0)
- {;}
-#if defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT)
- else if ((code == PLUS || code == MINUS) && insn_const
+ if ((HAVE_PRE_INCREMENT || HAVE_PRE_DECREMENT)
+ && (code == PLUS || code == MINUS) && insn_const
&& try_auto_increment (p, insn, 0, src, insn_const, 1))
insn = p;
-#endif
-#if defined (HAVE_POST_INCREMENT) || defined (HAVE_POST_DECREMENT)
- else if (post_inc
+ else if ((HAVE_POST_INCREMENT || HAVE_POST_DECREMENT)
+ && post_inc
&& try_auto_increment (p, post_inc, post_inc_set, src, newconst, 0))
post_inc = 0;
-#endif
-#if defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT)
/* If post_inc still prevails, try to find an
insn where it can be used as a pre-in/decrement.
If code is MINUS, this was already tried. */
if (post_inc && code == PLUS
/* Check that newconst is likely to be usable
in a pre-in/decrement before starting the search. */
- && (0
-#if defined (HAVE_PRE_INCREMENT)
- || (newconst > 0 && newconst <= MOVE_MAX)
-#endif
-#if defined (HAVE_PRE_DECREMENT)
- || (newconst < 0 && newconst >= -MOVE_MAX)
-#endif
- ) && exact_log2 (newconst))
+ && ((HAVE_PRE_INCREMENT && newconst > 0 && newconst <= MOVE_MAX)
+ || (HAVE_PRE_DECREMENT && newconst < 0 && newconst >= -MOVE_MAX))
+ && exact_log2 (newconst))
{
rtx q, inc_dest;
@@ -1840,7 +2030,6 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
}
}
}
-#endif /* defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT) */
/* Move the death note for DST to INSN if it is used
there. */
if (reg_overlap_mentioned_p (dst, PATTERN (insn)))
@@ -1973,7 +2162,7 @@ regmove_profitable_p ()
we find a machine where this occurs and regmove should
be enabled. */
break;
- if (find_matches (pat, &match) >= 0)
+ if (find_matches (pat, &match))
return 1;
break;
}
diff --git a/contrib/gcc/regs.h b/contrib/gcc/regs.h
index e248665..d513093 100644
--- a/contrib/gcc/regs.h
+++ b/contrib/gcc/regs.h
@@ -38,10 +38,6 @@ Boston, MA 02111-1307, USA. */
extern int max_regno;
-/* Maximum number of SCRATCH rtx's in each block of this function. */
-
-extern int max_scratch;
-
/* Register information indexed by register number */
typedef struct reg_info_def {
/* fields set by reg_scan */
@@ -211,14 +207,17 @@ extern int caller_save_needed;
#define CLASS_LIKELY_SPILLED_P(CLASS) (reg_class_size[(int) (CLASS)] == 1)
#endif
-/* Allocated in local_alloc. */
+/* Select a register mode required for caller save of hard regno REGNO. */
+#ifndef HARD_REGNO_CALLER_SAVE_MODE
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) \
+ choose_hard_reg_mode (REGNO, NREGS)
+#endif
-/* A list of SCRATCH rtl allocated by local-alloc. */
-extern rtx *scratch_list;
-/* The basic block in which each SCRATCH is used. */
-extern int *scratch_block;
-/* The length of the arrays pointed to by scratch_block and scratch_list. */
-extern int scratch_list_length;
+/* Registers that get partially clobbered by a call in a given mode.
+ These must not be call used registers. */
+#ifndef HARD_REGNO_CALL_PART_CLOBBERED
+#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
+#endif
/* Allocate reg_n_info tables */
extern void allocate_reg_info PROTO((size_t, int, int));
diff --git a/contrib/gcc/reload.c b/contrib/gcc/reload.c
index b1483d1..d8b4136 100644
--- a/contrib/gcc/reload.c
+++ b/contrib/gcc/reload.c
@@ -1,5 +1,5 @@
/* Search an insn for pseudo regs that must be in hard regs and are not.
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -181,6 +181,7 @@ char reload_optional[MAX_RELOADS];
char reload_nongroup[MAX_RELOADS];
int reload_inc[MAX_RELOADS];
rtx reload_in_reg[MAX_RELOADS];
+rtx reload_out_reg[MAX_RELOADS];
char reload_nocombine[MAX_RELOADS];
int reload_opnum[MAX_RELOADS];
enum reload_type reload_when_needed[MAX_RELOADS];
@@ -232,11 +233,6 @@ struct decomposition
HOST_WIDE_INT end; /* Ending offset or register number. */
};
-/* MEM-rtx's created for pseudo-regs in stack slots not directly addressable;
- (see reg_equiv_address). */
-static rtx memlocs[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
-static int n_memlocs;
-
#ifdef SECONDARY_MEMORY_NEEDED
/* Save MEMs needed to copy from one class of registers to another. One MEM
@@ -321,6 +317,8 @@ static int push_reload PROTO((rtx, rtx, rtx *, rtx *, enum reg_class,
int, int, int, enum reload_type));
static void push_replacement PROTO((rtx *, int, enum machine_mode));
static void combine_reloads PROTO((void));
+static int find_reusable_reload PROTO((rtx *, rtx, enum reg_class,
+ enum reload_type, int, int));
static rtx find_dummy_reload PROTO((rtx, rtx, rtx *, rtx *,
enum machine_mode, enum machine_mode,
enum reg_class, int, int));
@@ -328,19 +326,22 @@ static int earlyclobber_operand_p PROTO((rtx));
static int hard_reg_set_here_p PROTO((int, int, rtx));
static struct decomposition decompose PROTO((rtx));
static int immune_p PROTO((rtx, rtx, struct decomposition));
-static int alternative_allows_memconst PROTO((char *, int));
-static rtx find_reloads_toplev PROTO((rtx, int, enum reload_type, int, int));
+static int alternative_allows_memconst PROTO((const char *, int));
+static rtx find_reloads_toplev PROTO((rtx, int, enum reload_type, int, int, rtx));
static rtx make_memloc PROTO((rtx, int));
static int find_reloads_address PROTO((enum machine_mode, rtx *, rtx, rtx *,
int, enum reload_type, int, rtx));
-static rtx subst_reg_equivs PROTO((rtx));
+static rtx subst_reg_equivs PROTO((rtx, rtx));
static rtx subst_indexed_address PROTO((rtx));
static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *,
int, enum reload_type,int, rtx));
static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class,
enum machine_mode, int,
enum reload_type, int));
+static rtx find_reloads_subreg_address PROTO((rtx, int, int, enum reload_type,
+ int, rtx));
static int find_inc_amount PROTO((rtx, rtx));
+static int loc_mentioned_in_p PROTO((rtx *, rtx));
#ifdef HAVE_SECONDARY_RELOADS
@@ -445,7 +446,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
char insn_letter = insn_operand_constraint[(int) icode][!in_p][in_p];
enum reg_class insn_class
= (insn_letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_LETTER (insn_letter));
+ : REG_CLASS_FROM_LETTER ((unsigned char) insn_letter));
if (insn_class == NO_REGS
|| (in_p && insn_operand_constraint[(int) icode][!in_p][0] != '=')
@@ -462,7 +463,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
class = insn_class;
t_mode = insn_operand_mode[(int) icode][2];
t_class = (t_letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_LETTER (t_letter));
+ : REG_CLASS_FROM_LETTER ((unsigned char) t_letter));
t_icode = icode;
icode = CODE_FOR_nothing;
}
@@ -536,6 +537,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
/* Maybe we could combine these, but it seems too tricky. */
reload_nocombine[t_reload] = 1;
reload_in_reg[t_reload] = 0;
+ reload_out_reg[t_reload] = 0;
reload_opnum[t_reload] = opnum;
reload_when_needed[t_reload] = secondary_type;
reload_secondary_in_reload[t_reload] = -1;
@@ -605,6 +607,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
/* Maybe we could combine these, but it seems too tricky. */
reload_nocombine[s_reload] = 1;
reload_in_reg[s_reload] = 0;
+ reload_out_reg[s_reload] = 0;
reload_opnum[s_reload] = opnum;
reload_when_needed[s_reload] = secondary_type;
reload_secondary_in_reload[s_reload] = in_p ? t_reload : -1;
@@ -745,6 +748,96 @@ find_valid_class (m1, n)
return best_class;
}
+/* Return the number of a previously made reload that can be combined with
+ a new one, or n_reloads if none of the existing reloads can be used.
+ OUT, CLASS, TYPE and OPNUM are the same arguments as passed to
+ push_reload, they determine the kind of the new reload that we try to
+ combine. P_IN points to the corresponding value of IN, which can be
+ modified by this function.
+ DONT_SHARE is nonzero if we can't share any input-only reload for IN. */
+static int
+find_reusable_reload (p_in, out, class, type, opnum, dont_share)
+ rtx *p_in, out;
+ enum reg_class class;
+ enum reload_type type;
+ int opnum, dont_share;
+{
+ rtx in = *p_in;
+ int i;
+ /* We can't merge two reloads if the output of either one is
+ earlyclobbered. */
+
+ if (earlyclobber_operand_p (out))
+ return n_reloads;
+
+ /* We can use an existing reload if the class is right
+ and at least one of IN and OUT is a match
+ and the other is at worst neutral.
+ (A zero compared against anything is neutral.)
+
+ If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are
+ for the same thing since that can cause us to need more reload registers
+ than we otherwise would. */
+
+ for (i = 0; i < n_reloads; i++)
+ if ((reg_class_subset_p (class, reload_reg_class[i])
+ || reg_class_subset_p (reload_reg_class[i], class))
+ /* If the existing reload has a register, it must fit our class. */
+ && (reload_reg_rtx[i] == 0
+ || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ true_regnum (reload_reg_rtx[i])))
+ && ((in != 0 && MATCHES (reload_in[i], in) && ! dont_share
+ && (out == 0 || reload_out[i] == 0 || MATCHES (reload_out[i], out)))
+ ||
+ (out != 0 && MATCHES (reload_out[i], out)
+ && (in == 0 || reload_in[i] == 0 || MATCHES (reload_in[i], in))))
+ && (reload_out[i] == 0 || ! earlyclobber_operand_p (reload_out[i]))
+ && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && MERGABLE_RELOADS (type, reload_when_needed[i],
+ opnum, reload_opnum[i]))
+ return i;
+
+ /* Reloading a plain reg for input can match a reload to postincrement
+ that reg, since the postincrement's value is the right value.
+ Likewise, it can match a preincrement reload, since we regard
+ the preincrementation as happening before any ref in this insn
+ to that register. */
+ for (i = 0; i < n_reloads; i++)
+ if ((reg_class_subset_p (class, reload_reg_class[i])
+ || reg_class_subset_p (reload_reg_class[i], class))
+ /* If the existing reload has a register, it must fit our
+ class. */
+ && (reload_reg_rtx[i] == 0
+ || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ true_regnum (reload_reg_rtx[i])))
+ && out == 0 && reload_out[i] == 0 && reload_in[i] != 0
+ && ((GET_CODE (in) == REG
+ && (GET_CODE (reload_in[i]) == POST_INC
+ || GET_CODE (reload_in[i]) == POST_DEC
+ || GET_CODE (reload_in[i]) == PRE_INC
+ || GET_CODE (reload_in[i]) == PRE_DEC)
+ && MATCHES (XEXP (reload_in[i], 0), in))
+ ||
+ (GET_CODE (reload_in[i]) == REG
+ && (GET_CODE (in) == POST_INC
+ || GET_CODE (in) == POST_DEC
+ || GET_CODE (in) == PRE_INC
+ || GET_CODE (in) == PRE_DEC)
+ && MATCHES (XEXP (in, 0), reload_in[i])))
+ && (reload_out[i] == 0 || ! earlyclobber_operand_p (reload_out[i]))
+ && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && MERGABLE_RELOADS (type, reload_when_needed[i],
+ opnum, reload_opnum[i]))
+ {
+ /* Make sure reload_in ultimately has the increment,
+ not the plain register. */
+ if (GET_CODE (in) == REG)
+ *p_in = reload_in[i];
+ return i;
+ }
+ return n_reloads;
+}
+
/* Record one reload that needs to be performed.
IN is an rtx saying where the data are to be found before this instruction.
OUT says where they must be stored after the instruction.
@@ -781,7 +874,7 @@ find_valid_class (m1, n)
static int
push_reload (in, out, inloc, outloc, class,
inmode, outmode, strict_low, optional, opnum, type)
- register rtx in, out;
+ rtx in, out;
rtx *inloc, *outloc;
enum reg_class class;
enum machine_mode inmode, outmode;
@@ -870,9 +963,11 @@ push_reload (in, out, inloc, outloc, class,
the class whose registers cannot be referenced in a different size
and M1 is not the same size as M2. If SUBREG_WORD is nonzero, we
cannot reload just the inside since we might end up with the wrong
- register class. */
+ register class. But if it is inside a STRICT_LOW_PART, we have
+ no choice, so we hope we do get the right register class there. */
- if (in != 0 && GET_CODE (in) == SUBREG && SUBREG_WORD (in) == 0
+ if (in != 0 && GET_CODE (in) == SUBREG
+ && (SUBREG_WORD (in) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_SIZE
&& class != CLASS_CANNOT_CHANGE_SIZE
#endif
@@ -989,7 +1084,8 @@ push_reload (in, out, inloc, outloc, class,
storing in a subreg is entitled to clobber it all
(except in the case of STRICT_LOW_PART,
and in that case the constraint should label it input-output.) */
- if (out != 0 && GET_CODE (out) == SUBREG && SUBREG_WORD (out) == 0
+ if (out != 0 && GET_CODE (out) == SUBREG
+ && (SUBREG_WORD (out) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_SIZE
&& class != CLASS_CANNOT_CHANGE_SIZE
#endif
@@ -1170,72 +1266,14 @@ push_reload (in, out, inloc, outloc, class,
}
}
- if (class == NO_REGS)
+ /* Optional output reloads are always OK even if we have no register class,
+ since the function of these reloads is only to have spill_reg_store etc.
+ set, so that the storing insn can be deleted later. */
+ if (class == NO_REGS
+ && (optional == 0 || type != RELOAD_FOR_OUTPUT))
abort ();
- /* We can use an existing reload if the class is right
- and at least one of IN and OUT is a match
- and the other is at worst neutral.
- (A zero compared against anything is neutral.)
-
- If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are
- for the same thing since that can cause us to need more reload registers
- than we otherwise would. */
-
- for (i = 0; i < n_reloads; i++)
- if ((reg_class_subset_p (class, reload_reg_class[i])
- || reg_class_subset_p (reload_reg_class[i], class))
- /* If the existing reload has a register, it must fit our class. */
- && (reload_reg_rtx[i] == 0
- || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
- true_regnum (reload_reg_rtx[i])))
- && ((in != 0 && MATCHES (reload_in[i], in) && ! dont_share
- && (out == 0 || reload_out[i] == 0 || MATCHES (reload_out[i], out)))
- ||
- (out != 0 && MATCHES (reload_out[i], out)
- && (in == 0 || reload_in[i] == 0 || MATCHES (reload_in[i], in))))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
- && MERGABLE_RELOADS (type, reload_when_needed[i],
- opnum, reload_opnum[i]))
- break;
-
- /* Reloading a plain reg for input can match a reload to postincrement
- that reg, since the postincrement's value is the right value.
- Likewise, it can match a preincrement reload, since we regard
- the preincrementation as happening before any ref in this insn
- to that register. */
- if (i == n_reloads)
- for (i = 0; i < n_reloads; i++)
- if ((reg_class_subset_p (class, reload_reg_class[i])
- || reg_class_subset_p (reload_reg_class[i], class))
- /* If the existing reload has a register, it must fit our class. */
- && (reload_reg_rtx[i] == 0
- || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
- true_regnum (reload_reg_rtx[i])))
- && out == 0 && reload_out[i] == 0 && reload_in[i] != 0
- && ((GET_CODE (in) == REG
- && (GET_CODE (reload_in[i]) == POST_INC
- || GET_CODE (reload_in[i]) == POST_DEC
- || GET_CODE (reload_in[i]) == PRE_INC
- || GET_CODE (reload_in[i]) == PRE_DEC)
- && MATCHES (XEXP (reload_in[i], 0), in))
- ||
- (GET_CODE (reload_in[i]) == REG
- && (GET_CODE (in) == POST_INC
- || GET_CODE (in) == POST_DEC
- || GET_CODE (in) == PRE_INC
- || GET_CODE (in) == PRE_DEC)
- && MATCHES (XEXP (in, 0), reload_in[i])))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
- && MERGABLE_RELOADS (type, reload_when_needed[i],
- opnum, reload_opnum[i]))
- {
- /* Make sure reload_in ultimately has the increment,
- not the plain register. */
- if (GET_CODE (in) == REG)
- in = reload_in[i];
- break;
- }
+ i = find_reusable_reload (&in, out, class, type, opnum, dont_share);
if (i == n_reloads)
{
@@ -1281,6 +1319,7 @@ push_reload (in, out, inloc, outloc, class,
reload_inc[i] = 0;
reload_nocombine[i] = 0;
reload_in_reg[i] = inloc ? *inloc : 0;
+ reload_out_reg[i] = outloc ? *outloc : 0;
reload_opnum[i] = opnum;
reload_when_needed[i] = type;
reload_secondary_in_reload[i] = secondary_in_reload;
@@ -1315,9 +1354,44 @@ push_reload (in, out, inloc, outloc, class,
&& GET_MODE_SIZE (outmode) > GET_MODE_SIZE (reload_outmode[i]))
reload_outmode[i] = outmode;
if (in != 0)
- reload_in[i] = in;
+ {
+ rtx in_reg = inloc ? *inloc : 0;
+ /* If we merge reloads for two distinct rtl expressions that
+ are identical in content, there might be duplicate address
+ reloads. Remove the extra set now, so that if we later find
+ that we can inherit this reload, we can get rid of the
+ address reloads altogether.
+
+ Do not do this if both reloads are optional since the result
+ would be an optional reload which could potentially leave
+ unresolved address replacements.
+
+ It is not sufficient to call transfer_replacements since
+ choose_reload_regs will remove the replacements for address
+ reloads of inherited reloads which results in the same
+ problem. */
+ if (reload_in[i] != in && rtx_equal_p (in, reload_in[i])
+ && ! (reload_optional[i] && optional))
+ {
+ /* We must keep the address reload with the lower operand
+ number alive. */
+ if (opnum > reload_opnum[i])
+ {
+ remove_address_replacements (in);
+ in = reload_in[i];
+ in_reg = reload_in_reg[i];
+ }
+ else
+ remove_address_replacements (reload_in[i]);
+ }
+ reload_in[i] = in;
+ reload_in_reg[i] = in_reg;
+ }
if (out != 0)
- reload_out[i] = out;
+ {
+ reload_out[i] = out;
+ reload_out_reg[i] = outloc ? *outloc : 0;
+ }
if (reg_class_subset_p (class, reload_reg_class[i]))
reload_reg_class[i] = class;
reload_optional[i] &= optional;
@@ -1506,19 +1580,69 @@ transfer_replacements (to, from)
replacements[i].what = to;
}
-/* Remove all replacements in reload FROM. */
-void
-remove_replacements (from)
- int from;
+/* IN_RTX is the value loaded by a reload that we now decided to inherit,
+ or a subpart of it. If we have any replacements registered for IN_RTX,
+ cancel the reloads that were supposed to load them.
+ Return non-zero if we canceled any reloads. */
+int
+remove_address_replacements (in_rtx)
+ rtx in_rtx;
{
int i, j;
+ char reload_flags[MAX_RELOADS];
+ int something_changed = 0;
+ bzero (reload_flags, sizeof reload_flags);
for (i = 0, j = 0; i < n_replacements; i++)
{
- if (replacements[i].what == from)
- continue;
- replacements[j++] = replacements[i];
+ if (loc_mentioned_in_p (replacements[i].where, in_rtx))
+ reload_flags[replacements[i].what] |= 1;
+ else
+ {
+ replacements[j++] = replacements[i];
+ reload_flags[replacements[i].what] |= 2;
+ }
+ }
+ /* Note that the following store must be done before the recursive calls. */
+ n_replacements = j;
+
+ for (i = n_reloads - 1; i >= 0; i--)
+ {
+ if (reload_flags[i] == 1)
+ {
+ deallocate_reload_reg (i);
+ remove_address_replacements (reload_in[i]);
+ reload_in[i] = 0;
+ something_changed = 1;
+ }
}
+ return something_changed;
+}
+
+/* Return non-zero if IN contains a piece of rtl that has the address LOC */
+static int
+loc_mentioned_in_p (loc, in)
+ rtx *loc, in;
+{
+ enum rtx_code code = GET_CODE (in);
+ char *fmt = GET_RTX_FORMAT (code);
+ int i, j;
+
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (loc == &XEXP (in, i))
+ return 1;
+ if (fmt[i] == 'e')
+ {
+ if (loc_mentioned_in_p (loc, XEXP (in, i)))
+ return 1;
+ }
+ else if (fmt[i] == 'E')
+ for (j = XVECLEN (in, i) - 1; i >= 0; i--)
+ if (loc_mentioned_in_p (loc, XVECEXP (in, i, j)))
+ return 1;
+ }
+ return 0;
}
/* If there is only one output reload, and it is not for an earlyclobber
@@ -1617,6 +1741,7 @@ combine_reloads ()
/* We have found a reload to combine with! */
reload_out[i] = reload_out[output_reload];
+ reload_out_reg[i] = reload_out_reg[output_reload];
reload_outmode[i] = reload_outmode[output_reload];
/* Mark the old output reload as inoperative. */
reload_out[output_reload] = 0;
@@ -2031,7 +2156,7 @@ operands_match_p (x, y)
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
- int val;
+ int val, j;
switch (fmt[i])
{
case 'w':
@@ -2057,6 +2182,19 @@ operands_match_p (x, y)
case '0':
break;
+ case 'E':
+ if (XVECLEN (x, i) != XVECLEN (y, i))
+ return 0;
+ for (j = XVECLEN (x, i) - 1; j >= 0; --j)
+ {
+ val = operands_match_p (XVECEXP (x, i, j), XVECEXP (y, i, j));
+ if (val == 0)
+ return 0;
+ if (val == 2)
+ success_2 = 1;
+ }
+ break;
+
/* It is believed that rtx's at this level will never
contain anything but integers and other rtx's,
except for within LABEL_REFs and SYMBOL_REFs. */
@@ -2067,19 +2205,6 @@ operands_match_p (x, y)
return 1 + success_2;
}
-/* Return the number of times character C occurs in string S. */
-
-int
-n_occurrences (c, s)
- int c;
- char *s;
-{
- int n = 0;
- while (*s)
- n += (*s++ == c);
- return n;
-}
-
/* Describe the range of registers or memory referenced by X.
If X is a register, set REG_FLAG and put the first register
number into START and the last plus one into END.
@@ -2286,9 +2411,12 @@ safe_from_earlyclobber (op, clobber)
RELOAD_REG_P if nonzero is a vector indexed by hard reg number
which is nonnegative if the reg has been commandeered for reloading into.
It is copied into STATIC_RELOAD_REG_P and referenced from there
- by various subroutines. */
+ by various subroutines.
-void
+ Return TRUE if some operands need to be changed, because of swapping
+ commutative operands, reg_equiv_address substitution, or whatever. */
+
+int
find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
rtx insn;
int replace, ind_levels;
@@ -2300,8 +2428,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
register int insn_code_number;
register int i, j;
int noperands;
- /* These are the constraints for the insn. We don't change them. */
- char *constraints1[MAX_RECOG_OPERANDS];
/* These start out as the constraints for the insn
and they are chewed up as we consider alternatives. */
char *constraints[MAX_RECOG_OPERANDS];
@@ -2344,15 +2470,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
rtx set = single_set (insn);
int goal_earlyclobber, this_earlyclobber;
enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+ int retval = 0;
/* Cache the last regno for the last pseudo we did an output reload
for in case the next insn uses it. */
static int last_output_reload_regno = -1;
this_insn = insn;
- this_insn_is_asm = 0; /* Tentative. */
n_reloads = 0;
n_replacements = 0;
- n_memlocs = 0;
n_earlyclobbers = 0;
replace_reloads = replace;
hard_regs_live_known = live_known;
@@ -2378,94 +2503,34 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
bzero ((char *) secondary_memlocs_elim, sizeof secondary_memlocs_elim);
#endif
- /* Find what kind of insn this is. NOPERANDS gets number of operands.
- Make OPERANDS point to a vector of operand values.
- Make OPERAND_LOCS point to a vector of pointers to
- where the operands were found.
- Fill CONSTRAINTS and CONSTRAINTS1 with pointers to the
- constraint-strings for this insn.
- Return if the insn needs no reload processing. */
-
- switch (GET_CODE (body))
- {
- case USE:
- case CLOBBER:
- case ASM_INPUT:
- case ADDR_VEC:
- case ADDR_DIFF_VEC:
- return;
-
- case SET:
- /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
- is cheap to move between them. If it is not, there may not be an insn
- to do the copy, so we may need a reload. */
- if (GET_CODE (SET_DEST (body)) == REG
- && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
- && GET_CODE (SET_SRC (body)) == REG
- && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
- && REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
- REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
- return;
- case PARALLEL:
- case ASM_OPERANDS:
- reload_n_operands = noperands = asm_noperands (body);
- if (noperands >= 0)
- {
- /* This insn is an `asm' with operands. */
-
- insn_code_number = -1;
- this_insn_is_asm = 1;
-
- /* expand_asm_operands makes sure there aren't too many operands. */
- if (noperands > MAX_RECOG_OPERANDS)
- abort ();
-
- /* Now get the operand values and constraints out of the insn. */
+ /* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
+ is cheap to move between them. If it is not, there may not be an insn
+ to do the copy, so we may need a reload. */
+ if (GET_CODE (body) == SET
+ && GET_CODE (SET_DEST (body)) == REG
+ && REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
+ && GET_CODE (SET_SRC (body)) == REG
+ && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
+ && REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
+ REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
+ return 0;
- decode_asm_operands (body, recog_operand, recog_operand_loc,
- constraints, operand_mode);
- if (noperands > 0)
- {
- bcopy ((char *) constraints, (char *) constraints1,
- noperands * sizeof (char *));
- n_alternatives = n_occurrences (',', constraints[0]) + 1;
- for (i = 1; i < noperands; i++)
- if (n_alternatives != n_occurrences (',', constraints[i]) + 1)
- {
- error_for_asm (insn, "operand constraints differ in number of alternatives");
- /* Avoid further trouble with this insn. */
- PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
- n_reloads = 0;
- return;
- }
- }
- break;
- }
+ extract_insn (insn);
- default:
- /* Ordinary insn: recognize it, get the operands via insn_extract
- and get the constraints. */
+ noperands = reload_n_operands = recog_n_operands;
+ n_alternatives = recog_n_alternatives;
- insn_code_number = recog_memoized (insn);
- if (insn_code_number < 0)
- fatal_insn_not_found (insn);
+ /* Just return "no reloads" if insn has no operands with constraints. */
+ if (noperands == 0 || n_alternatives == 0)
+ return 0;
- reload_n_operands = noperands = insn_n_operands[insn_code_number];
- n_alternatives = insn_n_alternatives[insn_code_number];
- /* Just return "no reloads" if insn has no operands with constraints. */
- if (n_alternatives == 0)
- return;
- insn_extract (insn);
- for (i = 0; i < noperands; i++)
- {
- constraints[i] = constraints1[i]
- = insn_operand_constraint[insn_code_number][i];
- operand_mode[i] = insn_operand_mode[insn_code_number][i];
- }
- }
+ insn_code_number = INSN_CODE (insn);
+ this_insn_is_asm = insn_code_number < 0;
- if (noperands == 0)
- return;
+ bcopy ((char *) recog_operand_mode, (char *) operand_mode,
+ noperands * sizeof (enum machine_mode));
+ bcopy ((char *) recog_constraints, (char *) constraints,
+ noperands * sizeof (char *));
commutative = -1;
@@ -2497,15 +2562,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
{
/* The last operand should not be marked commutative. */
if (i == noperands - 1)
- {
- if (this_insn_is_asm)
- warning_for_asm (this_insn,
- "`%%' constraint used with last operand");
- else
- abort ();
- }
- else
- commutative = i;
+ abort ();
+
+ commutative = i;
}
else if (c >= '0' && c <= '9')
{
@@ -2515,13 +2574,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* An operand may not match itself. */
if (c == i)
- {
- if (this_insn_is_asm)
- warning_for_asm (this_insn,
- "operand %d has constraint %d", i, c);
- else
- abort ();
- }
+ abort ();
/* If C can be commuted with C+1, and C might need to match I,
then C+1 might also need to match I. */
@@ -2585,21 +2638,21 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|| GET_CODE (recog_operand[i]) == PLUS))
{
INSN_CODE (insn) = -1;
- find_reloads (insn, replace, ind_levels, live_known,
- reload_reg_p);
- return;
+ retval = find_reloads (insn, replace, ind_levels, live_known,
+ reload_reg_p);
+ return retval;
}
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
else if (code == MEM)
{
- if (find_reloads_address (GET_MODE (recog_operand[i]),
+ address_reloaded[i]
+ = find_reloads_address (GET_MODE (recog_operand[i]),
recog_operand_loc[i],
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
- i, address_type[i], ind_levels, insn))
- address_reloaded[i] = 1;
+ i, address_type[i], ind_levels, insn);
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
else if (code == SUBREG)
@@ -2609,14 +2662,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
= find_reloads_toplev (recog_operand[i], i, address_type[i],
ind_levels,
set != 0
- && &SET_DEST (set) == recog_operand_loc[i]);
+ && &SET_DEST (set) == recog_operand_loc[i],
+ insn);
/* If we made a MEM to load (a part of) the stackslot of a pseudo
that didn't get a hard register, emit a USE with a REG_EQUAL
note in front so that we might inherit a previous, possibly
wider reload. */
- if (GET_CODE (op) == MEM
+ if (replace
+ && GET_CODE (op) == MEM
&& GET_CODE (reg) == REG
&& (GET_MODE_SIZE (GET_MODE (reg))
>= GET_MODE_SIZE (GET_MODE (op))))
@@ -2624,15 +2679,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
= gen_rtx_EXPR_LIST (REG_EQUAL,
reg_equiv_memory_loc[REGNO (reg)], NULL_RTX);
- substed_operand[i] = recog_operand[i] = *recog_operand_loc[i] = op;
+ substed_operand[i] = recog_operand[i] = op;
}
else if (code == PLUS || GET_RTX_CLASS (code) == '1')
/* We can get a PLUS as an "operand" as a result of register
elimination. See eliminate_regs and gen_reload. We handle
a unary operator by reloading the operand. */
- substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]
+ substed_operand[i] = recog_operand[i]
= find_reloads_toplev (recog_operand[i], i, address_type[i],
- ind_levels, 0);
+ ind_levels, 0, insn);
else if (code == REG)
{
/* This is equivalent to calling find_reloads_toplev.
@@ -2654,44 +2709,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
substed_operand[i] = recog_operand[i]
= reg_equiv_constant[regno];
}
-#if 0 /* This might screw code in reload1.c to delete prior output-reload
- that feeds this insn. */
- if (reg_equiv_mem[regno] != 0)
+ if (reg_equiv_memory_loc[regno] != 0
+ && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+ /* We need not give a valid is_set_dest argument since the case
+ of a constant equivalence was checked above. */
substed_operand[i] = recog_operand[i]
- = reg_equiv_mem[regno];
-#endif
- if (reg_equiv_address[regno] != 0)
- {
- /* If reg_equiv_address is not a constant address, copy it,
- since it may be shared. */
- /* We must rerun eliminate_regs, in case the elimination
- offsets have changed. */
- rtx address = XEXP (eliminate_regs (reg_equiv_memory_loc[regno],
- 0, NULL_RTX),
- 0);
-
- if (rtx_varies_p (address))
- address = copy_rtx (address);
-
- /* Emit a USE that shows what register is being used/modified. */
- REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode,
- recog_operand[i]),
- insn))
- = gen_rtx_EXPR_LIST (REG_EQUAL,
- reg_equiv_memory_loc[regno],
- NULL_RTX);
-
- *recog_operand_loc[i] = recog_operand[i]
- = gen_rtx_MEM (GET_MODE (recog_operand[i]), address);
- RTX_UNCHANGING_P (recog_operand[i])
- = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
- find_reloads_address (GET_MODE (recog_operand[i]),
- recog_operand_loc[i],
- XEXP (recog_operand[i], 0),
- &XEXP (recog_operand[i], 0),
- i, address_type[i], ind_levels, insn);
- substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
- }
+ = find_reloads_toplev (recog_operand[i], i, address_type[i],
+ ind_levels, 0, insn);
}
/* If the operand is still a register (we didn't replace it with an
equivalent), get the preferred class to reload it into. */
@@ -2704,6 +2728,15 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
&& reg_alternate_class (REGNO (recog_operand[i])) == NO_REGS);
}
+#ifdef HAVE_cc0
+ /* If we made any reloads for addresses, see if they violate a
+ "no input reloads" requirement for this insn. */
+ if (no_input_reloads)
+ for (i = 0; i < n_reloads; i++)
+ if (reload_in[i] != 0)
+ abort ();
+#endif
+
/* If this is simply a copy from operand 1 to operand 0, merge the
preferred classes for the operands. */
if (set != 0 && noperands >= 2 && recog_operand[0] == SET_DEST (set)
@@ -3041,24 +3074,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* If IND_LEVELS, find_reloads_address won't reload a
pseudo that didn't get a hard reg, so we have to
reject that case. */
- && (ind_levels ? offsettable_memref_p (operand)
- : offsettable_nonstrict_memref_p (operand)))
- /* A reloaded auto-increment address is offsettable,
- because it is now just a simple register indirect. */
- || (GET_CODE (operand) == MEM
- && address_reloaded[i]
- && (GET_CODE (XEXP (operand, 0)) == PRE_INC
- || GET_CODE (XEXP (operand, 0)) == PRE_DEC
- || GET_CODE (XEXP (operand, 0)) == POST_INC
- || GET_CODE (XEXP (operand, 0)) == POST_DEC))
- /* Certain mem addresses will become offsettable
- after they themselves are reloaded. This is important;
- we don't want our own handling of unoffsettables
- to override the handling of reg_equiv_address. */
- || (GET_CODE (operand) == MEM
- && GET_CODE (XEXP (operand, 0)) == REG
- && (ind_levels == 0
- || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0))
+ && ((ind_levels ? offsettable_memref_p (operand)
+ : offsettable_nonstrict_memref_p (operand))
+ /* A reloaded address is offsettable because it is now
+ just a simple register indirect. */
+ || address_reloaded[i]))
|| (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
@@ -3359,14 +3379,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
early_data = decompose (recog_operand[i]);
if (modified[i] == RELOAD_READ)
- {
- if (this_insn_is_asm)
- warning_for_asm (this_insn,
- "`&' constraint used with input operand");
- else
- abort ();
- continue;
- }
+ abort ();
if (this_alternative[i] == NO_REGS)
{
@@ -3384,7 +3397,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|| modified[j] != RELOAD_WRITE)
&& j != i
/* Ignore things like match_operator operands. */
- && *constraints1[j] != 0
+ && *recog_constraints[j] != 0
/* Don't count an input operand that is constrained to match
the early clobber operand. */
&& ! (this_alternative_matches[j] == i
@@ -3501,7 +3514,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
pref_or_nothing[commutative + 1] = t;
- bcopy ((char *) constraints1, (char *) constraints,
+ bcopy ((char *) recog_constraints, (char *) constraints,
noperands * sizeof (char *));
goto try_swapped;
}
@@ -3521,12 +3534,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
{
/* No alternative works with reloads?? */
if (insn_code_number >= 0)
- abort ();
+ fatal_insn ("Unable to generate reloads for:", insn);
error_for_asm (insn, "inconsistent operand constraints in an `asm'");
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
n_reloads = 0;
- return;
+ return 0;
}
/* Jump to `finish' from above if all operands are valid already.
@@ -3561,6 +3574,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
tem = recog_operand[commutative];
recog_operand[commutative] = recog_operand[commutative + 1];
recog_operand[commutative + 1] = tem;
+ tem = *recog_operand_loc[commutative];
+ *recog_operand_loc[commutative] = *recog_operand_loc[commutative+1];
+ *recog_operand_loc[commutative+1] = tem;
for (i = 0; i < n_reloads; i++)
{
@@ -3571,14 +3587,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
}
}
- /* Perform whatever substitutions on the operands we are supposed
- to make due to commutativity or replacement of registers
- with equivalent constants or memory slots. */
-
for (i = 0; i < noperands; i++)
{
- *recog_operand_loc[i] = substed_operand[i];
- /* While we are looping on operands, initialize this. */
operand_reloadnum[i] = -1;
/* If this is an earlyclobber operand, we need to widen the scope.
@@ -3617,11 +3627,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|| no_input_reloads)
&& operand_mode[i] != VOIDmode)
{
- *recog_operand_loc[i] = recog_operand[i]
+ substed_operand[i] = recog_operand[i]
= find_reloads_toplev (force_const_mem (operand_mode[i],
recog_operand[i]),
- i, address_type[i], ind_levels, 0);
- if (alternative_allows_memconst (constraints1[i],
+ i, address_type[i], ind_levels, 0, insn);
+ if (alternative_allows_memconst (recog_constraints[i],
goal_alternative_number))
goal_alternative_win[i] = 1;
}
@@ -3745,7 +3755,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
n_reloads = 0;
- return;
+ return 0;
}
}
else if (goal_alternative_matched[i] < 0
@@ -3763,13 +3773,21 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if ((GET_CODE (operand) == MEM
|| (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
- && (enum reg_class) goal_alternative[i] != NO_REGS
+ /* If this is only for an output, the optional reload would not
+ actually cause us to use a register now, just note that
+ something is stored here. */
+ && ((enum reg_class) goal_alternative[i] != NO_REGS
+ || modified[i] == RELOAD_WRITE)
&& ! no_input_reloads
- /* Optional output reloads don't do anything and we mustn't
- make in-out reloads on insns that are not permitted output
- reloads. */
+ /* An optional output reload might allow to delete INSN later.
+ We mustn't make in-out reloads on insns that are not permitted
+ output reloads.
+ If this is an asm, we can't delete it; we must not even call
+ push_reload for an optional output reload in this case,
+ because we can't be sure that the constraint allows a register,
+ and push_reload verifies the constraints for asms. */
&& (modified[i] == RELOAD_READ
- || (modified[i] == RELOAD_READ_WRITE && ! no_output_reloads)))
+ || (! no_output_reloads && ! this_insn_is_asm)))
operand_reloadnum[i]
= push_reload (modified[i] != RELOAD_WRITE ? recog_operand[i] : 0,
modified[i] != RELOAD_READ ? recog_operand[i] : 0,
@@ -3785,6 +3803,29 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
(insn_code_number < 0 ? 0
: insn_operand_strict_low[insn_code_number][i]),
1, i, operand_type[i]);
+ /* If a memory reference remains (either as a MEM or a pseudo that
+ did not get a hard register), yet we can't make an optional
+ reload, check if this is actually a pseudo register reference;
+ we then need to emit a USE and/or a CLOBBER so that reload
+ inheritance will do the right thing. */
+ else if (replace
+ && (GET_CODE (operand) == MEM
+ || (GET_CODE (operand) == REG
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber [REGNO (operand)] < 0)))
+ {
+ operand = *recog_operand_loc[i];
+
+ while (GET_CODE (operand) == SUBREG)
+ operand = XEXP (operand, 0);
+ if (GET_CODE (operand) == REG)
+ {
+ if (modified[i] != RELOAD_WRITE)
+ emit_insn_before (gen_rtx_USE (VOIDmode, operand), insn);
+ if (modified[i] != RELOAD_READ)
+ emit_insn_after (gen_rtx_CLOBBER (VOIDmode, operand), insn);
+ }
+ }
}
else if (goal_alternative_matches[i] >= 0
&& goal_alternative_win[goal_alternative_matches[i]]
@@ -3816,6 +3857,37 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
0, 1, goal_alternative_matches[i], RELOAD_OTHER);
}
+ /* Perform whatever substitutions on the operands we are supposed
+ to make due to commutativity or replacement of registers
+ with equivalent constants or memory slots. */
+
+ for (i = 0; i < noperands; i++)
+ {
+ /* We only do this on the last pass through reload, because it is
+ possible for some data (like reg_equiv_address) to be changed during
+ later passes. Moreover, we loose the opportunity to get a useful
+ reload_{in,out}_reg when we do these replacements. */
+
+ if (replace)
+ {
+ rtx substitution = substed_operand[i];
+
+ *recog_operand_loc[i] = substitution;
+
+ /* If we're replacing an operand with a LABEL_REF, we need
+ to make sure that there's a REG_LABEL note attached to
+ this instruction. */
+ if (GET_CODE (insn) != JUMP_INSN
+ && GET_CODE (substitution) == LABEL_REF
+ && !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL,
+ XEXP (substitution, 0),
+ REG_NOTES (insn));
+ }
+ else
+ retval |= (substed_operand[i] != *recog_operand_loc[i]);
+ }
+
/* If this insn pattern contains any MATCH_DUP's, make sure that
they will be substituted if the operands they match are substituted.
Also do now any substitutions we already did on the operands.
@@ -3970,7 +4042,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
= RELOAD_FOR_OPADDR_ADDR;
}
- reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
+ if (reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS
+ || reload_when_needed[i] == RELOAD_FOR_OUTADDR_ADDRESS)
+ reload_when_needed[i] = RELOAD_FOR_OPADDR_ADDR;
+ else
+ reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
}
if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
@@ -4000,12 +4076,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
actually fail are extremely rare, so it turns out to be better to fix
the problem here by not generating cases that choose_reload_regs will
fail for. */
- /* There is a similar problem with RELAOD_FOR_INPUT_ADDRESS /
+ /* There is a similar problem with RELOAD_FOR_INPUT_ADDRESS /
RELOAD_FOR_OUTPUT_ADDRESS when there is more than one of a kind for
a single operand.
We can reduce the register pressure by exploiting that a
RELOAD_FOR_X_ADDR_ADDR that precedes all RELOAD_FOR_X_ADDRESS reloads
- does not conflict with any of them. */
+ does not conflict with any of them, if it is only used for the first of
+ the RELOAD_FOR_X_ADDRESS reloads. */
{
int first_op_addr_num = -2;
int first_inpaddr_num[MAX_RECOG_OPERANDS];
@@ -4024,21 +4101,21 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
switch (reload_when_needed[i])
{
case RELOAD_FOR_OPERAND_ADDRESS:
- if (! ++first_op_addr_num)
+ if (++first_op_addr_num >= 0)
{
- first_op_addr_num= i;
+ first_op_addr_num = i;
need_change = 1;
}
break;
case RELOAD_FOR_INPUT_ADDRESS:
- if (! ++first_inpaddr_num[reload_opnum[i]])
+ if (++first_inpaddr_num[reload_opnum[i]] >= 0)
{
first_inpaddr_num[reload_opnum[i]] = i;
need_change = 1;
}
break;
case RELOAD_FOR_OUTPUT_ADDRESS:
- if (! ++first_outpaddr_num[reload_opnum[i]])
+ if (++first_outpaddr_num[reload_opnum[i]] >= 0)
{
first_outpaddr_num[reload_opnum[i]] = i;
need_change = 1;
@@ -4072,8 +4149,26 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
default:
continue;
}
- if (i > first_num)
+ if (first_num < 0)
+ continue;
+ else if (i > first_num)
reload_when_needed[i] = type;
+ else
+ {
+ /* Check if the only TYPE reload that uses reload I is
+ reload FIRST_NUM. */
+ for (j = n_reloads - 1; j > first_num; j--)
+ {
+ if (reload_when_needed[j] == type
+ && (reload_secondary_p[i]
+ ? reload_secondary_in_reload[j] == i
+ : reg_mentioned_p (reload_in[i], reload_in[j])))
+ {
+ reload_when_needed[i] = type;
+ break;
+ }
+ }
+ }
}
}
}
@@ -4168,6 +4263,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
int goal_earlyclobber = 0; /* Always 0, to make combine_reloads happen. */
register int i;
rtx body = PATTERN (insn);
+ int retval = 0;
n_reloads = 0;
n_replacements = 0;
@@ -4175,50 +4271,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
replace_reloads = replace;
this_insn = insn;
- /* Find what kind of insn this is. NOPERANDS gets number of operands.
- Store the operand values in RECOG_OPERAND and the locations
- of the words in the insn that point to them in RECOG_OPERAND_LOC.
- Return if the insn needs no reload processing. */
-
- switch (GET_CODE (body))
- {
- case USE:
- case CLOBBER:
- case ASM_INPUT:
- case ADDR_VEC:
- case ADDR_DIFF_VEC:
- return;
-
- case PARALLEL:
- case SET:
- noperands = asm_noperands (body);
- if (noperands >= 0)
- {
- /* This insn is an `asm' with operands.
- First, find out how many operands, and allocate space. */
-
- insn_code_number = -1;
- /* ??? This is a bug! ???
- Give up and delete this insn if it has too many operands. */
- if (noperands > MAX_RECOG_OPERANDS)
- abort ();
-
- /* Now get the operand values out of the insn. */
-
- decode_asm_operands (body, recog_operand, recog_operand_loc,
- NULL_PTR, NULL_PTR);
- break;
- }
-
- default:
- /* Ordinary insn: recognize it, allocate space for operands and
- constraints, and get them out via insn_extract. */
+ extract_insn (insn);
- insn_code_number = recog_memoized (insn);
- noperands = insn_n_operands[insn_code_number];
- insn_extract (insn);
- }
+ noperands = reload_n_operands = recog_n_operands;
+ /* Return if the insn needs no reload processing. */
if (noperands == 0)
return;
@@ -4267,6 +4324,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (!goal_earlyclobber)
combine_reloads ();
#endif /* no REGISTER_CONSTRAINTS */
+ return retval;
}
/* Return 1 if alternative number ALTNUM in constraint-string CONSTRAINT
@@ -4274,7 +4332,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
static int
alternative_allows_memconst (constraint, altnum)
- char *constraint;
+ const char *constraint;
int altnum;
{
register int c;
@@ -4305,20 +4363,26 @@ alternative_allows_memconst (constraint, altnum)
OPNUM and TYPE identify the purpose of the reload.
IS_SET_DEST is true if X is the destination of a SET, which is not
- appropriate to be replaced by a constant. */
+ appropriate to be replaced by a constant.
+
+ INSN, if nonzero, is the insn in which we do the reload. It is used
+ to determine if we may generate output reloads, and where to put USEs
+ for pseudos that we have to replace with stack slots. */
static rtx
-find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
+find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn)
rtx x;
int opnum;
enum reload_type type;
int ind_levels;
int is_set_dest;
+ rtx insn;
{
register RTX_CODE code = GET_CODE (x);
register char *fmt = GET_RTX_FORMAT (code);
register int i;
+ int copied;
if (code == REG)
{
@@ -4332,23 +4396,22 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
else if (reg_equiv_mem[regno] != 0)
x = reg_equiv_mem[regno];
#endif
- else if (reg_equiv_address[regno] != 0)
+ else if (reg_equiv_memory_loc[regno]
+ && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
{
- /* If reg_equiv_address varies, it may be shared, so copy it. */
- /* We must rerun eliminate_regs, in case the elimination
- offsets have changed. */
- rtx addr = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0,
- NULL_RTX),
- 0);
-
- if (rtx_varies_p (addr))
- addr = copy_rtx (addr);
-
- x = gen_rtx_MEM (GET_MODE (x), addr);
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
- find_reloads_address (GET_MODE (x), NULL_PTR,
- XEXP (x, 0),
- &XEXP (x, 0), opnum, type, ind_levels, 0);
+ rtx mem = make_memloc (x, regno);
+ if (reg_equiv_address[regno]
+ || ! rtx_equal_p (mem, reg_equiv_mem[regno]))
+ {
+ /* If this is not a toplevel operand, find_reloads doesn't see
+ this substitution. We have to emit a USE of the pseudo so
+ that delete_output_reload can see it. */
+ if (replace_reloads && recog_operand[opnum] != x)
+ emit_insn_before (gen_rtx_USE (VOIDmode, x), insn);
+ x = mem;
+ find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
+ opnum, type, ind_levels, insn);
+ }
}
return x;
}
@@ -4356,7 +4419,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
{
rtx tem = x;
find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
- opnum, type, ind_levels, 0);
+ opnum, type, ind_levels, insn);
return tem;
}
@@ -4450,37 +4513,30 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
|| (reg_equiv_mem[regno] != 0
&& (! strict_memory_address_p (GET_MODE (x),
XEXP (reg_equiv_mem[regno], 0))
- || ! offsettable_memref_p (reg_equiv_mem[regno])))))
- {
- int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
- /* We must rerun eliminate_regs, in case the elimination
- offsets have changed. */
- rtx addr = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0,
- NULL_RTX),
- 0);
- if (BYTES_BIG_ENDIAN)
- {
- int size;
- size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
- offset += MIN (size, UNITS_PER_WORD);
- size = GET_MODE_SIZE (GET_MODE (x));
- offset -= MIN (size, UNITS_PER_WORD);
- }
- addr = plus_constant (addr, offset);
- x = gen_rtx_MEM (GET_MODE (x), addr);
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
- find_reloads_address (GET_MODE (x), NULL_PTR,
- XEXP (x, 0),
- &XEXP (x, 0), opnum, type, ind_levels, 0);
- }
-
+ || ! offsettable_memref_p (reg_equiv_mem[regno])
+ || num_not_at_initial_offset))))
+ x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
+ insn);
}
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- XEXP (x, i) = find_reloads_toplev (XEXP (x, i), opnum, type,
- ind_levels, is_set_dest);
+ {
+ rtx new_part = find_reloads_toplev (XEXP (x, i), opnum, type,
+ ind_levels, is_set_dest, insn);
+ /* If we have replaced a reg with it's equivalent memory loc -
+ that can still be handled here e.g. if it's in a paradoxical
+ subreg - we must make the change in a copy, rather than using
+ a destructive change. This way, find_reloads can still elect
+ not to do the change. */
+ if (new_part != XEXP (x, i) && ! CONSTANT_P (new_part) && ! copied)
+ {
+ x = shallow_copy_rtx (x);
+ copied = 1;
+ }
+ XEXP (x, i) = new_part;
+ }
}
return x;
}
@@ -4493,22 +4549,10 @@ make_memloc (ad, regno)
rtx ad;
int regno;
{
-#if 0
- register int i;
-#endif
/* We must rerun eliminate_regs, in case the elimination
offsets have changed. */
- rtx tem = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
-
-#if 0 /* We cannot safely reuse a memloc made here;
- if the pseudo appears twice, and its mem needs a reload,
- it gets two separate reloads assigned, but it only
- gets substituted with the second of them;
- then it can get used before that reload reg gets loaded up. */
- for (i = 0; i < n_memlocs; i++)
- if (rtx_equal_p (tem, XEXP (memlocs[i], 0)))
- return memlocs[i];
-#endif
+ rtx tem
+ = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
/* If TEM might contain a pseudo, we must copy it to avoid
modifying it when we do the substitution for the reload. */
@@ -4517,7 +4561,6 @@ make_memloc (ad, regno)
tem = gen_rtx_MEM (GET_MODE (ad), tem);
RTX_UNCHANGING_P (tem) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
- memlocs[n_memlocs++] = tem;
return tem;
}
@@ -4533,7 +4576,8 @@ make_memloc (ad, regno)
supports.
INSN, if nonzero, is the insn in which we do the reload. It is used
- to determine if we may generate output reloads.
+ to determine if we may generate output reloads, and where to put USEs
+ for pseudos that we have to replace with stack slots.
Value is nonzero if this address is reloaded or replaced as a whole.
This is interesting to the caller if the address is an autoincrement.
@@ -4556,6 +4600,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
rtx insn;
{
register int regno;
+ int removed_and = 0;
rtx tem;
/* If the address is a register, see if it is a legitimate address and
@@ -4570,35 +4615,51 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
&& strict_memory_address_p (mode, reg_equiv_constant[regno]))
{
*loc = ad = reg_equiv_constant[regno];
- return 1;
+ return 0;
}
- else if (reg_equiv_address[regno] != 0)
+ tem = reg_equiv_memory_loc[regno];
+ if (tem != 0)
{
- tem = make_memloc (ad, regno);
- find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, ADDR_TYPE (type),
- ind_levels, insn);
- push_reload (tem, NULL_RTX, loc, NULL_PTR,
- reload_address_base_reg_class,
- GET_MODE (ad), VOIDmode, 0, 0,
- opnum, type);
- return 1;
+ if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
+ {
+ tem = make_memloc (ad, regno);
+ if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
+ {
+ find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum, ADDR_TYPE (type),
+ ind_levels, insn);
+ }
+ /* We can avoid a reload if the register's equivalent memory
+ expression is valid as an indirect memory address.
+ But not all addresses are valid in a mem used as an indirect
+ address: only reg or reg+constant. */
+
+ if (ind_levels > 0
+ && strict_memory_address_p (mode, tem)
+ && (GET_CODE (XEXP (tem, 0)) == REG
+ || (GET_CODE (XEXP (tem, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (tem, 0), 0)) == REG
+ && CONSTANT_P (XEXP (XEXP (tem, 0), 1)))))
+ {
+ /* TEM is not the same as what we'll be replacing the
+ pseudo with after reload, put a USE in front of INSN
+ in the final reload pass. */
+ if (replace_reloads
+ && num_not_at_initial_offset
+ && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ {
+ *loc = tem;
+ emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
+ /* This doesn't really count as replacing the address
+ as a whole, since it is still a memory access. */
+ }
+ return 0;
+ }
+ ad = tem;
+ }
}
- /* We can avoid a reload if the register's equivalent memory expression
- is valid as an indirect memory address.
- But not all addresses are valid in a mem used as an indirect address:
- only reg or reg+constant. */
-
- else if (reg_equiv_mem[regno] != 0 && ind_levels > 0
- && strict_memory_address_p (mode, reg_equiv_mem[regno])
- && (GET_CODE (XEXP (reg_equiv_mem[regno], 0)) == REG
- || (GET_CODE (XEXP (reg_equiv_mem[regno], 0)) == PLUS
- && GET_CODE (XEXP (XEXP (reg_equiv_mem[regno], 0), 0)) == REG
- && CONSTANT_P (XEXP (XEXP (reg_equiv_mem[regno], 0), 1)))))
- return 0;
-
/* The only remaining case where we can avoid a reload is if this is a
hard register that is valid as a base register and which is not the
subject of a CLOBBER in this insn. */
@@ -4609,7 +4670,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
return 0;
/* If we do not have one of the cases above, we must do the reload. */
- push_reload (ad, NULL_RTX, loc, NULL_PTR, reload_address_base_reg_class,
+ push_reload (ad, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -4631,7 +4692,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
return 0;
subst_reg_equivs_changed = 0;
- *loc = subst_reg_equivs (ad);
+ *loc = subst_reg_equivs (ad, insn);
if (! subst_reg_equivs_changed)
return 0;
@@ -4659,12 +4720,22 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
while (0);
#endif
- /* The address is not valid. We have to figure out why. One possibility
- is that it is itself a MEM. This can happen when the frame pointer is
- being eliminated, a pseudo is not allocated to a hard register, and the
- offset between the frame and stack pointers is not its initial value.
- In that case the pseudo will have been replaced by a MEM referring to
- the stack pointer. */
+ /* The address is not valid. We have to figure out why. First see if
+ we have an outer AND and remove it if so. Then analyze what's inside. */
+
+ if (GET_CODE (ad) == AND)
+ {
+ removed_and = 1;
+ loc = &XEXP (ad, 0);
+ ad = *loc;
+ }
+
+ /* One possibility for why the address is invalid is that it is itself
+ a MEM. This can happen when the frame pointer is being eliminated, a
+ pseudo is not allocated to a hard register, and the offset between the
+ frame and stack pointers is not its initial value. In that case the
+ pseudo will have been replaced by a MEM referring to the
+ stack pointer. */
if (GET_CODE (ad) == MEM)
{
/* First ensure that the address in this MEM is valid. Then, unless
@@ -4681,6 +4752,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
*memrefloc = copy_rtx (*memrefloc);
copy_replacements (tem, XEXP (*memrefloc, 0));
loc = &XEXP (*memrefloc, 0);
+ if (removed_and)
+ loc = &XEXP (*loc, 0);
}
/* Check similar cases as for indirect addresses as above except
@@ -4698,10 +4771,10 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
push_reload (tem, NULL_RTX, loc, NULL_PTR,
- reload_address_base_reg_class, GET_MODE (tem),
+ BASE_REG_CLASS, GET_MODE (tem),
VOIDmode, 0,
0, opnum, type);
- return 1;
+ return ! removed_and;
}
else
return 0;
@@ -4723,26 +4796,31 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
{
*memrefloc = copy_rtx (*memrefloc);
loc = &XEXP (*memrefloc, 0);
+ if (removed_and)
+ loc = &XEXP (*loc, 0);
}
+
if (double_reg_address_ok)
{
/* Unshare the sum as well. */
*loc = ad = copy_rtx (ad);
+
/* Reload the displacement into an index reg.
We assume the frame pointer or arg pointer is a base reg. */
find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
- reload_address_index_reg_class,
- GET_MODE (ad), opnum, type, ind_levels);
+ INDEX_REG_CLASS, GET_MODE (ad), opnum,
+ type, ind_levels);
+ return 0;
}
else
{
/* If the sum of two regs is not necessarily valid,
reload the sum into a base reg.
That will at least work. */
- find_reloads_address_part (ad, loc, reload_address_base_reg_class,
+ find_reloads_address_part (ad, loc, BASE_REG_CLASS,
Pmode, opnum, type, ind_levels);
}
- return 1;
+ return ! removed_and;
}
/* If we have an indexed stack slot, there are three possible reasons why
@@ -4790,13 +4868,12 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
plus_constant (XEXP (XEXP (ad, 0), 0),
INTVAL (XEXP (ad, 1))),
XEXP (XEXP (ad, 0), 1));
- find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
- reload_address_base_reg_class,
+ find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0), BASE_REG_CLASS,
GET_MODE (ad), opnum, type, ind_levels);
find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
type, 0, insn);
- return 1;
+ return 0;
}
else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
@@ -4815,13 +4892,12 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
XEXP (XEXP (ad, 0), 0),
plus_constant (XEXP (XEXP (ad, 0), 1),
INTVAL (XEXP (ad, 1))));
- find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
- reload_address_base_reg_class,
+ find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1), BASE_REG_CLASS,
GET_MODE (ad), opnum, type, ind_levels);
find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
type, 0, insn);
- return 1;
+ return 0;
}
/* See if address becomes valid when an eliminable register
@@ -4836,7 +4912,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
registers. */
subst_reg_equivs_changed = 0;
- tem = subst_reg_equivs (tem);
+ tem = subst_reg_equivs (tem, insn);
/* Make sure that didn't make the address invalid again. */
@@ -4858,12 +4934,13 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
{
*memrefloc = copy_rtx (*memrefloc);
loc = &XEXP (*memrefloc, 0);
+ if (removed_and)
+ loc = &XEXP (*loc, 0);
}
- find_reloads_address_part (ad, loc, reload_address_base_reg_class,
- Pmode, opnum, type,
+ find_reloads_address_part (ad, loc, BASE_REG_CLASS, Pmode, opnum, type,
ind_levels);
- return 1;
+ return ! removed_and;
}
return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels,
@@ -4872,11 +4949,14 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
/* Find all pseudo regs appearing in AD
that are eliminable in favor of equivalent values
- and do not have hard regs; replace them by their equivalents. */
+ and do not have hard regs; replace them by their equivalents.
+ INSN, if nonzero, is the insn in which we do the reload. We put USEs in
+ front of it for pseudos that we have to replace with stack slots. */
static rtx
-subst_reg_equivs (ad)
+subst_reg_equivs (ad, insn)
rtx ad;
+ rtx insn;
{
register RTX_CODE code = GET_CODE (ad);
register int i;
@@ -4903,6 +4983,16 @@ subst_reg_equivs (ad)
subst_reg_equivs_changed = 1;
return reg_equiv_constant[regno];
}
+ if (reg_equiv_memory_loc[regno] && num_not_at_initial_offset)
+ {
+ rtx mem = make_memloc (ad, regno);
+ if (! rtx_equal_p (mem, reg_equiv_mem[regno]))
+ {
+ subst_reg_equivs_changed = 1;
+ emit_insn_before (gen_rtx_USE (VOIDmode, ad), insn);
+ return mem;
+ }
+ }
}
return ad;
@@ -4920,7 +5010,7 @@ subst_reg_equivs (ad)
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (fmt[i] == 'e')
- XEXP (ad, i) = subst_reg_equivs (XEXP (ad, i));
+ XEXP (ad, i) = subst_reg_equivs (XEXP (ad, i), insn);
return ad;
}
@@ -5193,19 +5283,24 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
/* Handle a register that is equivalent to a memory location
which cannot be addressed directly. */
- if (reg_equiv_address[regno] != 0)
+ if (reg_equiv_memory_loc[regno] != 0
+ && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
{
rtx tem = make_memloc (XEXP (x, 0), regno);
- /* First reload the memory location's address.
- We can't use ADDR_TYPE (type) here, because we need to
- write back the value after reading it, hence we actually
- need two registers. */
- find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, type,
- ind_levels, insn);
- /* Put this inside a new increment-expression. */
- x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
- /* Proceed to reload that, as if it contained a register. */
+ if (reg_equiv_address[regno]
+ || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ {
+ /* First reload the memory location's address.
+ We can't use ADDR_TYPE (type) here, because we need to
+ write back the value after reading it, hence we actually
+ need two registers. */
+ find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum, type,
+ ind_levels, insn);
+ /* Put this inside a new increment-expression. */
+ x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
+ /* Proceed to reload that, as if it contained a register. */
+ }
}
/* If we have a hard register that is ok as an index,
@@ -5238,9 +5333,12 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
memory location, since this will make it harder to
reuse address reloads, and increases register pressure.
Also don't do this if we can probably update x directly. */
- rtx equiv = reg_equiv_mem[regno];
+ rtx equiv = (GET_CODE (XEXP (x, 0)) == MEM
+ ? XEXP (x, 0)
+ : reg_equiv_mem[regno]);
int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
if (insn && GET_CODE (insn) == INSN && equiv
+ && memory_operand (equiv, GET_MODE (equiv))
#ifdef HAVE_cc0
&& ! sets_cc0_p (PATTERN (insn))
#endif
@@ -5252,19 +5350,23 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
x = XEXP (x, 0);
reloadnum
= push_reload (x, x, loc, loc,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
+
+ /* If we created a new MEM based on reg_equiv_mem[REGNO], then
+ LOC above is part of the new MEM, not the MEM in INSN.
+
+ We must also replace the address of the MEM in INSN. */
+ if (&XEXP (x_orig, 0) != loc)
+ push_replacement (&XEXP (x_orig, 0), reloadnum, VOIDmode);
+
}
else
{
reloadnum
= push_reload (x, NULL_RTX, loc, NULL_PTR,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, type);
reload_inc[reloadnum]
@@ -5292,7 +5394,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
of an equivalent address for a pseudo that was not allocated to a
hard register. Verify that the specified address is valid and
reload it into a register. */
- rtx tem = XEXP (x, 0);
+ /* Variable `tem' might or might not be used in FIND_REG_INC_NOTE. */
+ rtx tem ATTRIBUTE_UNUSED = XEXP (x, 0);
register rtx link;
int reloadnum;
@@ -5310,9 +5413,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
opnum, type, ind_levels, insn);
reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
reload_inc[reloadnum]
= find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
@@ -5341,8 +5442,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, NULL_PTR,
- (context ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
@@ -5352,10 +5452,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
if (reg_equiv_constant[regno] != 0)
{
- find_reloads_address_part (reg_equiv_constant[regno], loc,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ find_reloads_address_part (reg_equiv_constant[regno], loc,
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), opnum, type, ind_levels);
return 1;
}
@@ -5365,19 +5463,24 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
if (reg_equiv_mem[regno] != 0)
{
push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
#endif
- if (reg_equiv_address[regno] != 0)
+ if (reg_equiv_memory_loc[regno]
+ && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
{
- x = make_memloc (x, regno);
- find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
- opnum, ADDR_TYPE (type), ind_levels, insn);
+ rtx tem = make_memloc (x, regno);
+ if (reg_equiv_address[regno] != 0
+ || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ {
+ x = tem;
+ find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
+ &XEXP (x, 0), opnum, ADDR_TYPE (type),
+ ind_levels, insn);
+ }
}
if (reg_renumber[regno] >= 0)
@@ -5388,9 +5491,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
: REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
{
push_reload (x, NULL_RTX, loc, NULL_PTR,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5402,9 +5503,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
if (regno_clobbered_p (regno, this_insn))
{
push_reload (x, NULL_RTX, loc, NULL_PTR,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5425,9 +5524,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
: REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
{
push_reload (x, NULL_RTX, loc, NULL_PTR,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
+ (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
@@ -5436,12 +5533,13 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
is larger than the class size, then reload the whole SUBREG. */
else
{
- enum reg_class class = (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class);
+ enum reg_class class = (context ? INDEX_REG_CLASS
+ : BASE_REG_CLASS);
if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
> reg_class_size[class])
{
+ x = find_reloads_subreg_address (x, 0, opnum, type,
+ ind_levels, insn);
push_reload (x, NULL_RTX, loc, NULL_PTR, class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
@@ -5498,7 +5596,20 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
&& (! LEGITIMATE_CONSTANT_P (x)
|| PREFERRED_RELOAD_CLASS (x, class) == NO_REGS))
{
- rtx tem = x = force_const_mem (mode, x);
+ rtx tem;
+
+ /* If this is a CONST_INT, it could have been created by a
+ plus_constant call in eliminate_regs, which means it may be
+ on the reload_obstack. reload_obstack will be freed later, so
+ we can't allow such RTL to be put in the constant pool. There
+ is code in force_const_mem to check for this case, but it doesn't
+ work because we have already popped off the reload_obstack, so
+ rtl_obstack == saveable_obstack is true at this point. */
+ if (GET_CODE (x) == CONST_INT)
+ tem = x = force_const_mem (mode, GEN_INT (INTVAL (x)));
+ else
+ tem = x = force_const_mem (mode, x);
+
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
opnum, type, ind_levels, 0);
}
@@ -5508,7 +5619,13 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
&& (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
|| PREFERRED_RELOAD_CLASS (XEXP (x, 1), class) == NO_REGS))
{
- rtx tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
+ rtx tem;
+
+ /* See comment above. */
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ tem = force_const_mem (GET_MODE (x), GEN_INT (INTVAL (XEXP (x, 1))));
+ else
+ tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), tem);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
@@ -5519,6 +5636,86 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
mode, VOIDmode, 0, 0, opnum, type);
}
+/* X, a subreg of a pseudo, is a part of an address that needs to be
+ reloaded.
+
+ If the pseudo is equivalent to a memory location that cannot be directly
+ addressed, make the necessary address reloads.
+
+ If address reloads have been necessary, or if the address is changed
+ by register elimination, return the rtx of the memory location;
+ otherwise, return X.
+
+ If FORCE_REPLACE is nonzero, unconditionally replace the subreg with the
+ memory location.
+
+ OPNUM and TYPE identify the purpose of the reload.
+
+ IND_LEVELS says how many levels of indirect addressing are
+ supported at this point in the address.
+
+ INSN, if nonzero, is the insn in which we do the reload. It is used
+ to determine where to put USEs for pseudos that we have to replace with
+ stack slots. */
+
+static rtx
+find_reloads_subreg_address (x, force_replace, opnum, type,
+ ind_levels, insn)
+ rtx x;
+ int force_replace;
+ int opnum;
+ enum reload_type type;
+ int ind_levels;
+ rtx insn;
+{
+ int regno = REGNO (SUBREG_REG (x));
+
+ if (reg_equiv_memory_loc[regno])
+ {
+ /* If the address is not directly addressable, or if the address is not
+ offsettable, then it must be replaced. */
+ if (! force_replace
+ && (reg_equiv_address[regno]
+ || ! offsettable_memref_p (reg_equiv_mem[regno])))
+ force_replace = 1;
+
+ if (force_replace || num_not_at_initial_offset)
+ {
+ rtx tem = make_memloc (SUBREG_REG (x), regno);
+
+ /* If the address changes because of register elimination, then
+ it must be replaced. */
+ if (force_replace
+ || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ {
+ int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ int size;
+
+ size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
+ offset += MIN (size, UNITS_PER_WORD);
+ size = GET_MODE_SIZE (GET_MODE (x));
+ offset -= MIN (size, UNITS_PER_WORD);
+ }
+ XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
+ PUT_MODE (tem, GET_MODE (x));
+ find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum, ADDR_TYPE (type),
+ ind_levels, insn);
+ /* If this is not a toplevel operand, find_reloads doesn't see
+ this substitution. We have to emit a USE of the pseudo so
+ that delete_output_reload can see it. */
+ if (replace_reloads && recog_operand[opnum] != x)
+ emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
+ x = tem;
+ }
+ }
+ }
+ return x;
+}
+
/* Substitute into the current INSN the registers into which we have reloaded
the things that need reloading. The array `replacements'
says contains the locations of all pointers that must be changed
@@ -6515,6 +6712,12 @@ debug_reload_to_stream (f)
print_inline_rtx (f, reload_in_reg[r], 24);
}
+ if (reload_out_reg[r] != 0)
+ {
+ fprintf (f, "\n\treload_out_reg: ");
+ print_inline_rtx (f, reload_out_reg[r], 24);
+ }
+
if (reload_reg_rtx[r] != 0)
{
fprintf (f, "\n\treload_reg_rtx: ");
diff --git a/contrib/gcc/reload.h b/contrib/gcc/reload.h
index d99b0c1..968d312 100644
--- a/contrib/gcc/reload.h
+++ b/contrib/gcc/reload.h
@@ -50,11 +50,10 @@ extern int memory_move_secondary_cost PROTO ((enum machine_mode, enum reg_class,
/* Maximum number of reloads we can need. */
#define MAX_RELOADS (2 * MAX_RECOG_OPERANDS * (MAX_REGS_PER_ADDRESS + 1))
-extern enum reg_class reload_address_base_reg_class;
-extern enum reg_class reload_address_index_reg_class;
extern rtx reload_in[MAX_RELOADS];
extern rtx reload_out[MAX_RELOADS];
extern rtx reload_in_reg[MAX_RELOADS];
+extern rtx reload_out_reg[MAX_RELOADS];
extern enum reg_class reload_reg_class[MAX_RELOADS];
extern enum machine_mode reload_inmode[MAX_RELOADS];
extern enum machine_mode reload_outmode[MAX_RELOADS];
@@ -134,6 +133,8 @@ extern char indirect_symref_ok;
/* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */
extern char double_reg_address_ok;
+extern int num_not_at_initial_offset;
+
#ifdef MAX_INSN_CODE
/* These arrays record the insn_code of insns that may be needed to
perform input and output reloads of special objects. They provide a
@@ -142,6 +143,85 @@ extern enum insn_code reload_in_optab[];
extern enum insn_code reload_out_optab[];
#endif
+struct needs
+{
+ /* [0] is normal, [1] is nongroup. */
+ short regs[2][N_REG_CLASSES];
+ short groups[N_REG_CLASSES];
+};
+
+#if defined SET_HARD_REG_BIT && defined CLEAR_REG_SET
+/* This structure describes instructions which are relevant for reload.
+ Apart from all regular insns, this also includes CODE_LABELs, since they
+ must be examined for register elimination. */
+struct insn_chain
+{
+ /* Links to the neighbour instructions. */
+ struct insn_chain *next, *prev;
+
+ /* Link through a chains set up by calculate_needs_all_insns, containing
+ all insns that need reloading. */
+ struct insn_chain *next_need_reload;
+
+ /* The basic block this insn is in. */
+ int block;
+ /* The rtx of the insn. */
+ rtx insn;
+ /* Register life information: record all live hard registers, and all
+ live pseudos that have a hard register.
+ This information is recorded for the point immediately before the insn
+ (in live_before), and for the point within the insn at which all
+ outputs have just been written to (in live_after). */
+ regset live_before;
+ regset live_after;
+
+ /* For each class, size of group of consecutive regs
+ that is needed for the reloads of this class. */
+ char group_size[N_REG_CLASSES];
+ /* For each class, the machine mode which requires consecutive
+ groups of regs of that class.
+ If two different modes ever require groups of one class,
+ they must be the same size and equally restrictive for that class,
+ otherwise we can't handle the complexity. */
+ enum machine_mode group_mode[N_REG_CLASSES];
+
+ /* Indicates if a register was counted against the need for
+ groups. 0 means it can count against max_nongroup instead. */
+ HARD_REG_SET counted_for_groups;
+
+ /* Indicates if a register was counted against the need for
+ non-groups. 0 means it can become part of a new group.
+ During choose_reload_regs, 1 here means don't use this reg
+ as part of a group, even if it seems to be otherwise ok. */
+ HARD_REG_SET counted_for_nongroups;
+
+ /* Indicates which registers have already been used for spills. */
+ HARD_REG_SET used_spill_regs;
+
+ /* Describe the needs for reload registers of this insn. */
+ struct needs need;
+
+ /* Nonzero if find_reloads said the insn requires reloading. */
+ unsigned int need_reload:1;
+ /* Nonzero if find_reloads needs to be run during reload_as_needed to
+ perform modifications on any operands. */
+ unsigned int need_operand_change:1;
+ /* Nonzero if eliminate_regs_in_insn said it requires eliminations. */
+ unsigned int need_elim:1;
+ /* Nonzero if this insn was inserted by perform_caller_saves. */
+ unsigned int is_caller_save_insn:1;
+};
+
+/* A chain of insn_chain structures to describe all non-note insns in
+ a function. */
+extern struct insn_chain *reload_insn_chain;
+
+/* Allocate a new insn_chain structure. */
+extern struct insn_chain *new_insn_chain PROTO((void));
+
+extern void compute_use_by_pseudos PROTO((HARD_REG_SET *, regset));
+#endif
+
/* Functions from reload.c: */
/* Return a memory location that will be used to copy X in mode MODE.
@@ -157,24 +237,24 @@ extern void clear_secondary_mem PROTO((void));
reload TO. */
extern void transfer_replacements PROTO((int, int));
-/* Remove all replacements in reload FROM. */
-extern void remove_replacements PROTO((int));
+/* IN_RTX is the value loaded by a reload that we now decided to inherit,
+ or a subpart of it. If we have any replacements registered for IN_RTX,
+ chancel the reloads that were supposed to load them.
+ Return non-zero if we chanceled any reloads. */
+extern int remove_address_replacements PROTO((rtx in_rtx));
/* Like rtx_equal_p except that it allows a REG and a SUBREG to match
if they are the same hard reg, and has special hacks for
autoincrement and autodecrement. */
extern int operands_match_p PROTO((rtx, rtx));
-/* Return the number of times character C occurs in string S. */
-extern int n_occurrences PROTO((int, char *));
-
/* Return 1 if altering OP will not modify the value of CLOBBER. */
extern int safe_from_earlyclobber PROTO((rtx, rtx));
/* Search the body of INSN for values that need reloading and record them
with push_reload. REPLACE nonzero means record also where the values occur
so that subst_reloads can be used. */
-extern void find_reloads PROTO((rtx, int, int, int, short *));
+extern int find_reloads PROTO((rtx, int, int, int, short *));
/* Compute the sum of X and Y, making canonicalizations assumed in an
address, namely: sum constant integers, surround the sum of two
@@ -243,6 +323,9 @@ extern rtx eliminate_regs PROTO((rtx, enum machine_mode, rtx));
OPNUM with reload type TYPE. */
extern rtx gen_reload PROTO((rtx, rtx, int, enum reload_type));
+/* Deallocate the reload register used by reload number R. */
+extern void deallocate_reload_reg PROTO((int r));
+
/* Functions in caller-save.c: */
/* Initialize for caller-save. */
@@ -252,7 +335,10 @@ extern void init_caller_save PROTO((void));
extern void init_save_areas PROTO((void));
/* Allocate save areas for any hard registers that might need saving. */
-extern int setup_save_areas PROTO((int *));
+extern void setup_save_areas PROTO((void));
/* Find the places where hard regs are live across calls and save them. */
-extern void save_call_clobbered_regs PROTO((enum machine_mode));
+extern void save_call_clobbered_regs PROTO((void));
+
+/* Replace (subreg (reg)) with the appropriate (reg) for any operands. */
+extern void cleanup_subreg_operands PROTO ((rtx));
diff --git a/contrib/gcc/reload1.c b/contrib/gcc/reload1.c
index c2987bb..0ec2a92 100644
--- a/contrib/gcc/reload1.c
+++ b/contrib/gcc/reload1.c
@@ -1,5 +1,5 @@
/* Reload pseudo regs into hard regs for insns that require hard regs.
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -32,13 +32,17 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "expr.h"
#include "regs.h"
+#include "basic-block.h"
#include "reload.h"
#include "recog.h"
-#include "basic-block.h"
#include "output.h"
#include "real.h"
#include "toplev.h"
+#if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
+#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
+#endif
+
/* This file contains the reload pass of the compiler, which is
run after register allocation has been done. It checks that
each insn is valid (operands required to be in registers really
@@ -54,9 +58,10 @@ Boston, MA 02111-1307, USA. */
called ``reload regs'', and for each place where a pseudo reg
must be in a hard reg, copy it temporarily into one of the reload regs.
- All the pseudos that were formerly allocated to the hard regs that
- are now in use as reload regs must be ``spilled''. This means
- that they go to other hard regs, or to stack slots if no other
+ Reload regs are allocated locally for every instruction that needs
+ reloads. When there are pseudos which are allocated to a register that
+ has been chosen as a reload reg, such pseudos must be ``spilled''.
+ This means that they go to other hard regs, or to stack slots if no other
available hard regs can be found. Spilling can invalidate more
insns, requiring additional need for reloads, so we must keep checking
until the process stabilizes.
@@ -113,12 +118,15 @@ rtx *reg_equiv_mem;
/* Widest width in which each pseudo reg is referred to (via subreg). */
static int *reg_max_ref_width;
-/* Element N is the insn that initialized reg N from its equivalent
+/* Element N is the list of insns that initialized reg N from its equivalent
constant or memory slot. */
static rtx *reg_equiv_init;
+/* Vector to remember old contents of reg_renumber before spilling. */
+static short *reg_old_renumber;
+
/* During reload_as_needed, element N contains the last pseudo regno reloaded
- into hard register N. If that pseudo reg occupied more than one register,
+ into hard register N. If that pseudo reg occupied more than one register,
reg_reloaded_contents points to that pseudo for each spill register in
use; all of these must remain set for an inheritance to occur. */
static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
@@ -148,41 +156,61 @@ static rtx spill_reg_rtx[FIRST_PSEUDO_REGISTER];
The precise value is the insn generated to do the store. */
static rtx spill_reg_store[FIRST_PSEUDO_REGISTER];
+/* This is the register that was stored with spill_reg_store. This is a
+ copy of reload_out / reload_out_reg when the value was stored; if
+ reload_out is a MEM, spill_reg_stored_to will be set to reload_out_reg. */
+static rtx spill_reg_stored_to[FIRST_PSEUDO_REGISTER];
+
/* This table is the inverse mapping of spill_regs:
indexed by hard reg number,
it contains the position of that reg in spill_regs,
- or -1 for something that is not in spill_regs. */
-static short spill_reg_order[FIRST_PSEUDO_REGISTER];
-
-/* This reg set indicates registers that may not be used for retrying global
- allocation. The registers that may not be used include all spill registers
- and the frame pointer (if we are using one). */
-HARD_REG_SET forbidden_regs;
+ or -1 for something that is not in spill_regs.
-/* This reg set indicates registers that are not good for spill registers.
- They will not be used to complete groups of spill registers. This includes
- all fixed registers, registers that may be eliminated, and, if
- SMALL_REGISTER_CLASSES is zero, registers explicitly used in the rtl.
+ ?!? This is no longer accurate. */
+static short spill_reg_order[FIRST_PSEUDO_REGISTER];
- (spill_reg_order prevents these registers from being used to start a
- group.) */
+/* This reg set indicates registers that can't be used as spill registers for
+ the currently processed insn. These are the hard registers which are live
+ during the insn, but not allocated to pseudos, as well as fixed
+ registers. */
static HARD_REG_SET bad_spill_regs;
+/* These are the hard registers that can't be used as spill register for any
+ insn. This includes registers used for user variables and registers that
+ we can't eliminate. A register that appears in this set also can't be used
+ to retry register allocation. */
+static HARD_REG_SET bad_spill_regs_global;
+
/* Describes order of use of registers for reloading
- of spilled pseudo-registers. `spills' is the number of
- elements that are actually valid; new ones are added at the end. */
+ of spilled pseudo-registers. `n_spills' is the number of
+ elements that are actually valid; new ones are added at the end.
+
+ Both spill_regs and spill_reg_order are used on two occasions:
+ once during find_reload_regs, where they keep track of the spill registers
+ for a single insn, but also during reload_as_needed where they show all
+ the registers ever used by reload. For the latter case, the information
+ is calculated during finish_spills. */
static short spill_regs[FIRST_PSEUDO_REGISTER];
-/* This reg set indicates those registers that have been used a spill
- registers. This information is used in reorg.c, to help figure out
- what registers are live at any point. It is assumed that all spill_regs
- are dead at every CODE_LABEL. */
+/* This vector of reg sets indicates, for each pseudo, which hard registers
+ may not be used for retrying global allocation because the register was
+ formerly spilled from one of them. If we allowed reallocating a pseudo to
+ a register that it was already allocated to, reload might not
+ terminate. */
+static HARD_REG_SET *pseudo_previous_regs;
+
+/* This vector of reg sets indicates, for each pseudo, which hard
+ registers may not be used for retrying global allocation because they
+ are used as spill registers during one of the insns in which the
+ pseudo is live. */
+static HARD_REG_SET *pseudo_forbidden_regs;
-HARD_REG_SET used_spill_regs;
+/* All hard regs that have been used as spill registers for any insn are
+ marked in this set. */
+static HARD_REG_SET used_spill_regs;
/* Index of last register assigned as a spill register. We allocate in
a round-robin fashion. */
-
static int last_spill_reg;
/* Describes order of preference for putting regs into spill_regs.
@@ -192,54 +220,30 @@ static int last_spill_reg;
Empty elements at the end contain -1. */
static short potential_reload_regs[FIRST_PSEUDO_REGISTER];
-/* 1 for a hard register that appears explicitly in the rtl
- (for example, function value registers, special registers
- used by insns, structure value pointer registers). */
-static char regs_explicitly_used[FIRST_PSEUDO_REGISTER];
-
-/* Indicates if a register was counted against the need for
- groups. 0 means it can count against max_nongroup instead. */
-static HARD_REG_SET counted_for_groups;
-
-/* Indicates if a register was counted against the need for
- non-groups. 0 means it can become part of a new group.
- During choose_reload_regs, 1 here means don't use this reg
- as part of a group, even if it seems to be otherwise ok. */
-static HARD_REG_SET counted_for_nongroups;
-
/* Nonzero if indirect addressing is supported on the machine; this means
that spilling (REG n) does not require reloading it into a register in
order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))). The
value indicates the level of indirect addressing supported, e.g., two
means that (MEM (MEM (REG n))) is also valid if (REG n) does not get
a hard register. */
-
static char spill_indirect_levels;
/* Nonzero if indirect addressing is supported when the innermost MEM is
of the form (MEM (SYMBOL_REF sym)). It is assumed that the level to
which these are valid is the same as spill_indirect_levels, above. */
-
char indirect_symref_ok;
/* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid. */
-
char double_reg_address_ok;
/* Record the stack slot for each spilled hard register. */
-
static rtx spill_stack_slot[FIRST_PSEUDO_REGISTER];
/* Width allocated so far for that stack slot. */
-
static int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];
-/* Indexed by register class and basic block number, nonzero if there is
- any need for a spill register of that class in that basic block.
- The pointer is 0 if we did stupid allocation and don't know
- the structure of basic blocks. */
-
-char *basic_block_needs[N_REG_CLASSES];
+/* Record which pseudos needed to be spilled. */
+static regset spilled_pseudos;
/* First uid used by insns created by reload in this function.
Used in find_equiv_reg. */
@@ -247,38 +251,29 @@ int reload_first_uid;
/* Flag set by local-alloc or global-alloc if anything is live in
a call-clobbered reg across calls. */
-
int caller_save_needed;
-/* The register class to use for a base register when reloading an
- address. This is normally BASE_REG_CLASS, but it may be different
- when using SMALL_REGISTER_CLASSES and passing parameters in
- registers. */
-enum reg_class reload_address_base_reg_class;
-
-/* The register class to use for an index register when reloading an
- address. This is normally INDEX_REG_CLASS, but it may be different
- when using SMALL_REGISTER_CLASSES and passing parameters in
- registers. */
-enum reg_class reload_address_index_reg_class;
-
/* Set to 1 while reload_as_needed is operating.
Required by some machines to handle any generated moves differently. */
-
int reload_in_progress = 0;
/* These arrays record the insn_code of insns that may be needed to
perform input and output reloads of special objects. They provide a
place to pass a scratch register. */
-
enum insn_code reload_in_optab[NUM_MACHINE_MODES];
enum insn_code reload_out_optab[NUM_MACHINE_MODES];
/* This obstack is used for allocation of rtl during register elimination.
The allocated storage can be freed once find_reloads has processed the
insn. */
-
struct obstack reload_obstack;
+
+/* Points to the beginning of the reload_obstack. All insn_chain structures
+ are allocated first. */
+char *reload_startobj;
+
+/* The point after all insn_chain structures. Used to quickly deallocate
+ memory used while processing one insn. */
char *reload_firstobj;
#define obstack_chunk_alloc xmalloc
@@ -287,15 +282,25 @@ char *reload_firstobj;
/* List of labels that must never be deleted. */
extern rtx forced_labels;
-/* Allocation number table from global register allocation. */
-extern int *reg_allocno;
+/* List of insn_chain instructions, one for every insn that reload needs to
+ examine. */
+struct insn_chain *reload_insn_chain;
+
+#ifdef TREE_CODE
+extern tree current_function_decl;
+#else
+extern union tree_node *current_function_decl;
+#endif
+
+/* List of all insns needing reloads. */
+static struct insn_chain *insns_need_reload;
/* This structure is used to record information about register eliminations.
Each array entry describes one possible way of eliminating a register
in favor of another. If there is more than one way of eliminating a
particular register, the most preferred should be specified first. */
-static struct elim_table
+struct elim_table
{
int from; /* Register number to be eliminated. */
int to; /* Register number used as replacement. */
@@ -304,7 +309,6 @@ static struct elim_table
int can_eliminate_previous; /* Value of CAN_ELIMINATE in previous scan over
insns made by reload. */
int offset; /* Current offset between the two regs. */
- int max_offset; /* Maximum offset between the two regs. */
int previous_offset; /* Offset at end of previous insn. */
int ref_outside_mem; /* "to" has been referenced outside a MEM. */
rtx from_rtx; /* REG rtx for the register to be eliminated.
@@ -313,7 +317,17 @@ static struct elim_table
register corresponding to a pseudo
assigned to the reg to be eliminated. */
rtx to_rtx; /* REG rtx for the replacement. */
-} reg_eliminate[] =
+};
+
+static struct elim_table * reg_eliminate = 0;
+
+/* This is an intermediate structure to initialize the table. It has
+ exactly the members provided by ELIMINABLE_REGS. */
+static struct elim_table_1
+{
+ int from;
+ int to;
+} reg_eliminate_1[] =
/* If a set of eliminable registers was specified, define the table from it.
Otherwise, default to the normal case of the frame pointer being
@@ -325,15 +339,18 @@ static struct elim_table
{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}};
#endif
-#define NUM_ELIMINABLE_REGS (sizeof reg_eliminate / sizeof reg_eliminate[0])
+#define NUM_ELIMINABLE_REGS (sizeof reg_eliminate_1/sizeof reg_eliminate_1[0])
/* Record the number of pending eliminations that have an offset not equal
to their initial offset. If non-zero, we use a new copy of each
replacement result in any insns encountered. */
-static int num_not_at_initial_offset;
+int num_not_at_initial_offset;
/* Count the number of registers that we may be able to eliminate. */
static int num_eliminable;
+/* And the number of registers that are equivalent to a constant that
+ can be eliminated to frame_pointer / arg_pointer + constant. */
+static int num_eliminable_invariants;
/* For each label, we record the offset of each elimination. If we reach
a label by more than one path and an offset differs, we cannot do the
@@ -349,29 +366,52 @@ static int (*offsets_at)[NUM_ELIMINABLE_REGS];
static int num_labels;
-struct hard_reg_n_uses { int regno; int uses; };
+struct hard_reg_n_uses
+{
+ int regno;
+ unsigned int uses;
+};
-static int possible_group_p PROTO((int, int *));
-static void count_possible_groups PROTO((int *, enum machine_mode *,
- int *, int));
+static void maybe_fix_stack_asms PROTO((void));
+static void calculate_needs_all_insns PROTO((int));
+static void calculate_needs PROTO((struct insn_chain *));
+static void find_reload_regs PROTO((struct insn_chain *chain,
+ FILE *));
+static void find_tworeg_group PROTO((struct insn_chain *, int,
+ FILE *));
+static void find_group PROTO((struct insn_chain *, int,
+ FILE *));
+static int possible_group_p PROTO((struct insn_chain *, int));
+static void count_possible_groups PROTO((struct insn_chain *, int));
static int modes_equiv_for_class_p PROTO((enum machine_mode,
enum machine_mode,
enum reg_class));
+static void delete_caller_save_insns PROTO((void));
+
static void spill_failure PROTO((rtx));
-static int new_spill_reg PROTO((int, int, int *, int *, int,
- FILE *));
+static void new_spill_reg PROTO((struct insn_chain *, int, int,
+ int, FILE *));
+static void maybe_mark_pseudo_spilled PROTO((int));
static void delete_dead_insn PROTO((rtx));
static void alter_reg PROTO((int, int));
-static void mark_scratch_live PROTO((rtx));
static void set_label_offsets PROTO((rtx, rtx, int));
static int eliminate_regs_in_insn PROTO((rtx, int));
+static void update_eliminable_offsets PROTO((void));
static void mark_not_eliminable PROTO((rtx, rtx));
-static int spill_hard_reg PROTO((int, int, FILE *, int));
+static void set_initial_elim_offsets PROTO((void));
+static void verify_initial_elim_offsets PROTO((void));
+static void set_initial_label_offsets PROTO((void));
+static void set_offsets_for_label PROTO((rtx));
+static void init_elim_table PROTO((void));
+static void update_eliminables PROTO((HARD_REG_SET *));
+static void spill_hard_reg PROTO((int, FILE *, int));
+static int finish_spills PROTO((int, FILE *));
+static void ior_hard_reg_set PROTO((HARD_REG_SET *, HARD_REG_SET *));
static void scan_paradoxical_subregs PROTO((rtx));
static int hard_reg_use_compare PROTO((const GENERIC_PTR, const GENERIC_PTR));
-static void order_regs_for_reload PROTO((int));
-static int compare_spill_regs PROTO((const GENERIC_PTR, const GENERIC_PTR));
-static void reload_as_needed PROTO((rtx, int));
+static void count_pseudo PROTO((struct hard_reg_n_uses *, int));
+static void order_regs_for_reload PROTO((struct insn_chain *));
+static void reload_as_needed PROTO((int));
static void forget_old_reloads_1 PROTO((rtx, rtx));
static int reload_reg_class_lower PROTO((const GENERIC_PTR, const GENERIC_PTR));
static void mark_reload_reg_in_use PROTO((int, int, enum reload_type,
@@ -379,16 +419,19 @@ static void mark_reload_reg_in_use PROTO((int, int, enum reload_type,
static void clear_reload_reg_in_use PROTO((int, int, enum reload_type,
enum machine_mode));
static int reload_reg_free_p PROTO((int, int, enum reload_type));
-static int reload_reg_free_before_p PROTO((int, int, enum reload_type));
-static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int));
+static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int, int));
static int reload_reg_reaches_end_p PROTO((int, int, enum reload_type));
-static int allocate_reload_reg PROTO((int, rtx, int, int));
-static void choose_reload_regs PROTO((rtx, rtx));
+static int allocate_reload_reg PROTO((struct insn_chain *, int, int,
+ int));
+static void choose_reload_regs PROTO((struct insn_chain *));
static void merge_assigned_reloads PROTO((rtx));
-static void emit_reload_insns PROTO((rtx));
-static void delete_output_reload PROTO((rtx, int, rtx));
-static void inc_for_reload PROTO((rtx, rtx, int));
-static int constraint_accepts_reg_p PROTO((char *, rtx));
+static void emit_reload_insns PROTO((struct insn_chain *));
+static void delete_output_reload PROTO((rtx, int, int));
+static void delete_address_reloads PROTO((rtx, rtx));
+static void delete_address_reloads_1 PROTO((rtx, rtx, rtx));
+static rtx inc_for_reload PROTO((rtx, rtx, rtx, int));
+static int constraint_accepts_reg_p PROTO((const char *, rtx));
+static void reload_cse_regs_1 PROTO((rtx));
static void reload_cse_invalidate_regno PROTO((int, enum machine_mode, int));
static int reload_cse_mem_conflict_p PROTO((rtx, rtx));
static void reload_cse_invalidate_mem PROTO((rtx));
@@ -399,8 +442,14 @@ static int reload_cse_simplify_set PROTO((rtx, rtx));
static int reload_cse_simplify_operands PROTO((rtx));
static void reload_cse_check_clobber PROTO((rtx, rtx));
static void reload_cse_record_set PROTO((rtx, rtx));
-static void reload_cse_delete_death_notes PROTO((rtx));
-static void reload_cse_no_longer_dead PROTO((int, enum machine_mode));
+static void reload_combine PROTO((void));
+static void reload_combine_note_use PROTO((rtx *, rtx));
+static void reload_combine_note_store PROTO((rtx, rtx));
+static void reload_cse_move2add PROTO((rtx));
+static void move2add_note_store PROTO((rtx, rtx));
+#ifdef AUTO_INC_DEC
+static void add_auto_inc_notes PROTO((rtx, rtx));
+#endif
/* Initialize the reload pass once per compilation. */
@@ -450,66 +499,77 @@ init_reload ()
/* Initialize obstack for our rtl allocation. */
gcc_obstack_init (&reload_obstack);
- reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+ reload_startobj = (char *) obstack_alloc (&reload_obstack, 0);
+}
- /* Decide which register class should be used when reloading
- addresses. If we are using SMALL_REGISTER_CLASSES, and any
- parameters are passed in registers, then we do not want to use
- those registers when reloading an address. Otherwise, if a
- function argument needs a reload, we may wind up clobbering
- another argument to the function which was already computed. If
- we find a subset class which simply avoids those registers, we
- use it instead. ??? It would be better to only use the
- restricted class when we actually are loading function arguments,
- but that is hard to determine. */
- reload_address_base_reg_class = BASE_REG_CLASS;
- reload_address_index_reg_class = INDEX_REG_CLASS;
- if (SMALL_REGISTER_CLASSES)
- {
- int regno;
- HARD_REG_SET base, index;
- enum reg_class *p;
+/* List of insn chains that are currently unused. */
+static struct insn_chain *unused_insn_chains = 0;
- COPY_HARD_REG_SET (base, reg_class_contents[BASE_REG_CLASS]);
- COPY_HARD_REG_SET (index, reg_class_contents[INDEX_REG_CLASS]);
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- {
- if (FUNCTION_ARG_REGNO_P (regno))
- {
- CLEAR_HARD_REG_BIT (base, regno);
- CLEAR_HARD_REG_BIT (index, regno);
- }
- }
-
- GO_IF_HARD_REG_EQUAL (base, reg_class_contents[BASE_REG_CLASS],
- baseok);
- for (p = reg_class_subclasses[BASE_REG_CLASS];
- *p != LIM_REG_CLASSES;
- p++)
- {
- GO_IF_HARD_REG_EQUAL (base, reg_class_contents[*p], usebase);
- continue;
- usebase:
- reload_address_base_reg_class = *p;
- break;
- }
- baseok:;
+/* Allocate an empty insn_chain structure. */
+struct insn_chain *
+new_insn_chain ()
+{
+ struct insn_chain *c;
- GO_IF_HARD_REG_EQUAL (index, reg_class_contents[INDEX_REG_CLASS],
- indexok);
- for (p = reg_class_subclasses[INDEX_REG_CLASS];
- *p != LIM_REG_CLASSES;
- p++)
- {
- GO_IF_HARD_REG_EQUAL (index, reg_class_contents[*p], useindex);
- continue;
- useindex:
- reload_address_index_reg_class = *p;
- break;
- }
- indexok:;
+ if (unused_insn_chains == 0)
+ {
+ c = (struct insn_chain *)
+ obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
+ c->live_before = OBSTACK_ALLOC_REG_SET (&reload_obstack);
+ c->live_after = OBSTACK_ALLOC_REG_SET (&reload_obstack);
+ }
+ else
+ {
+ c = unused_insn_chains;
+ unused_insn_chains = c->next;
}
+ c->is_caller_save_insn = 0;
+ c->need_operand_change = 0;
+ c->need_reload = 0;
+ c->need_elim = 0;
+ return c;
+}
+
+/* Small utility function to set all regs in hard reg set TO which are
+ allocated to pseudos in regset FROM. */
+void
+compute_use_by_pseudos (to, from)
+ HARD_REG_SET *to;
+ regset from;
+{
+ int regno;
+ EXECUTE_IF_SET_IN_REG_SET
+ (from, FIRST_PSEUDO_REGISTER, regno,
+ {
+ int r = reg_renumber[regno];
+ int nregs;
+ if (r < 0)
+ {
+ /* reload_combine uses the information from
+ BASIC_BLOCK->global_live_at_start, which might still
+ contain registers that have not actually been allocated
+ since they have an equivalence. */
+ if (! reload_completed)
+ abort ();
+ }
+ else
+ {
+ nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (regno));
+ while (nregs-- > 0)
+ SET_HARD_REG_BIT (*to, r + nregs);
+ }
+ });
}
+
+/* Global variables used by reload and its subroutines. */
+
+/* Set during calculate_needs if an insn needs register elimination. */
+static int something_needs_elimination;
+/* Set during calculate_needs if an insn needs an operand changed. */
+int something_needs_operands_changed;
+
+/* Nonzero means we couldn't get enough spill regs. */
+static int failure;
/* Main entry point for the reload pass.
@@ -535,8 +595,7 @@ reload (first, global, dumpfile)
int global;
FILE *dumpfile;
{
- register int class;
- register int i, j, k;
+ register int i;
register rtx insn;
register struct elim_table *ep;
@@ -545,38 +604,25 @@ reload (first, global, dumpfile)
char *real_known_ptr = NULL_PTR;
int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
- int something_changed;
- int something_needs_reloads;
- int something_needs_elimination;
- int new_basic_block_needs;
- enum reg_class caller_save_spill_class = NO_REGS;
- int caller_save_group_size = 1;
+ /* Make sure even insns with volatile mem refs are recognizable. */
+ init_recog ();
- /* Nonzero means we couldn't get enough spill regs. */
- int failure = 0;
+ failure = 0;
- /* The basic block number currently being processed for INSN. */
- int this_block;
+ reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
- /* Make sure even insns with volatile mem refs are recognizable. */
- init_recog ();
+ /* Make sure that the last insn in the chain
+ is not something that needs reloading. */
+ emit_note (NULL_PTR, NOTE_INSN_DELETED);
/* Enable find_equiv_reg to distinguish insns made by reload. */
reload_first_uid = get_max_uid ();
- for (i = 0; i < N_REG_CLASSES; i++)
- basic_block_needs[i] = 0;
-
#ifdef SECONDARY_MEMORY_NEEDED
/* Initialize the secondary memory table. */
clear_secondary_mem ();
#endif
- /* Remember which hard regs appear explicitly
- before we merge into `regs_ever_live' the ones in which
- pseudo regs have been allocated. */
- bcopy (regs_ever_live, regs_explicitly_used, sizeof regs_ever_live);
-
/* We don't have a stack slot for any spill reg yet. */
bzero ((char *) spill_stack_slot, sizeof spill_stack_slot);
bzero ((char *) spill_stack_slot_width, sizeof spill_stack_slot_width);
@@ -601,14 +647,6 @@ reload (first, global, dumpfile)
regs_ever_live[i] = 1;
}
- for (i = 0; i < scratch_list_length; i++)
- if (scratch_list[i])
- mark_scratch_live (scratch_list[i]);
-
- /* Make sure that the last insn in the chain
- is not something that needs reloading. */
- emit_note (NULL_PTR, NOTE_INSN_DELETED);
-
/* Find all the pseudo registers that didn't get hard regs
but do have known equivalent constants or memory slots.
These include parameters (known equivalent to parameter slots)
@@ -619,21 +657,27 @@ reload (first, global, dumpfile)
Record memory equivalents in reg_mem_equiv so they can
be substituted eventually by altering the REG-rtx's. */
- reg_equiv_constant = (rtx *) alloca (max_regno * sizeof (rtx));
+ reg_equiv_constant = (rtx *) xmalloc (max_regno * sizeof (rtx));
bzero ((char *) reg_equiv_constant, max_regno * sizeof (rtx));
- reg_equiv_memory_loc = (rtx *) alloca (max_regno * sizeof (rtx));
+ reg_equiv_memory_loc = (rtx *) xmalloc (max_regno * sizeof (rtx));
bzero ((char *) reg_equiv_memory_loc, max_regno * sizeof (rtx));
- reg_equiv_mem = (rtx *) alloca (max_regno * sizeof (rtx));
+ reg_equiv_mem = (rtx *) xmalloc (max_regno * sizeof (rtx));
bzero ((char *) reg_equiv_mem, max_regno * sizeof (rtx));
- reg_equiv_init = (rtx *) alloca (max_regno * sizeof (rtx));
+ reg_equiv_init = (rtx *) xmalloc (max_regno * sizeof (rtx));
bzero ((char *) reg_equiv_init, max_regno * sizeof (rtx));
- reg_equiv_address = (rtx *) alloca (max_regno * sizeof (rtx));
+ reg_equiv_address = (rtx *) xmalloc (max_regno * sizeof (rtx));
bzero ((char *) reg_equiv_address, max_regno * sizeof (rtx));
- reg_max_ref_width = (int *) alloca (max_regno * sizeof (int));
+ reg_max_ref_width = (int *) xmalloc (max_regno * sizeof (int));
bzero ((char *) reg_max_ref_width, max_regno * sizeof (int));
+ reg_old_renumber = (short *) xmalloc (max_regno * sizeof (short));
+ bcopy ((PTR) reg_renumber, (PTR) reg_old_renumber, max_regno * sizeof (short));
+ pseudo_forbidden_regs
+ = (HARD_REG_SET *) xmalloc (max_regno * sizeof (HARD_REG_SET));
+ pseudo_previous_regs
+ = (HARD_REG_SET *) xmalloc (max_regno * sizeof (HARD_REG_SET));
- if (SMALL_REGISTER_CLASSES)
- CLEAR_HARD_REG_SET (forbidden_regs);
+ CLEAR_HARD_REG_SET (bad_spill_regs_global);
+ bzero ((char *) pseudo_previous_regs, max_regno * sizeof (HARD_REG_SET));
/* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
Also find all paradoxical subregs and find largest such for each pseudo.
@@ -642,6 +686,7 @@ reload (first, global, dumpfile)
Also look for a "constant" NOTE_INSN_SETJMP. This means that all
caller-saved registers must be marked live. */
+ num_eliminable_invariants = 0;
for (insn = first; insn; insn = NEXT_INSN (insn))
{
rtx set = single_set (insn);
@@ -657,7 +702,8 @@ reload (first, global, dumpfile)
rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
if (note
#ifdef LEGITIMATE_PIC_OPERAND_P
- && (! CONSTANT_P (XEXP (note, 0)) || ! flag_pic
+ && (! function_invariant_p (XEXP (note, 0))
+ || ! flag_pic
|| LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))
#endif
)
@@ -675,9 +721,22 @@ reload (first, global, dumpfile)
reg_equiv_memory_loc[i] = x;
}
- else if (CONSTANT_P (x))
+ else if (function_invariant_p (x))
{
- if (LEGITIMATE_CONSTANT_P (x))
+ if (GET_CODE (x) == PLUS)
+ {
+ /* This is PLUS of frame pointer and a constant,
+ and might be shared. Unshare it. */
+ reg_equiv_constant[i] = copy_rtx (x);
+ num_eliminable_invariants++;
+ }
+ else if (x == frame_pointer_rtx
+ || x == arg_pointer_rtx)
+ {
+ reg_equiv_constant[i] = x;
+ num_eliminable_invariants++;
+ }
+ else if (LEGITIMATE_CONSTANT_P (x))
reg_equiv_constant[i] = x;
else
reg_equiv_memory_loc[i]
@@ -692,7 +751,8 @@ reload (first, global, dumpfile)
So don't mark this insn now. */
if (GET_CODE (x) != MEM
|| rtx_equal_p (SET_SRC (set), x))
- reg_equiv_init[i] = insn;
+ reg_equiv_init[i]
+ = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[i]);
}
}
}
@@ -704,52 +764,15 @@ reload (first, global, dumpfile)
&& reg_equiv_memory_loc[REGNO (SET_SRC (set))]
&& rtx_equal_p (SET_DEST (set),
reg_equiv_memory_loc[REGNO (SET_SRC (set))]))
- reg_equiv_init[REGNO (SET_SRC (set))] = insn;
+ reg_equiv_init[REGNO (SET_SRC (set))]
+ = gen_rtx_INSN_LIST (VOIDmode, insn,
+ reg_equiv_init[REGNO (SET_SRC (set))]);
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
scan_paradoxical_subregs (PATTERN (insn));
}
- /* Does this function require a frame pointer? */
-
- frame_pointer_needed = (! flag_omit_frame_pointer
-#ifdef EXIT_IGNORE_STACK
- /* ?? If EXIT_IGNORE_STACK is set, we will not save
- and restore sp for alloca. So we can't eliminate
- the frame pointer in that case. At some point,
- we should improve this by emitting the
- sp-adjusting insns for this case. */
- || (current_function_calls_alloca
- && EXIT_IGNORE_STACK)
-#endif
- || FRAME_POINTER_REQUIRED);
-
- num_eliminable = 0;
-
- /* Initialize the table of registers to eliminate. The way we do this
- depends on how the eliminable registers were defined. */
-#ifdef ELIMINABLE_REGS
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- {
- ep->can_eliminate = ep->can_eliminate_previous
- = (CAN_ELIMINATE (ep->from, ep->to)
- && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed));
- }
-#else
- reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous
- = ! frame_pointer_needed;
-#endif
-
- /* Count the number of eliminable registers and build the FROM and TO
- REG rtx's. Note that code in gen_rtx will cause, e.g.,
- gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
- We depend on this. */
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- {
- num_eliminable += ep->can_eliminate;
- ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
- ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
- }
+ init_elim_table ();
num_labels = max_label_num () - get_first_label_num ();
@@ -799,114 +822,55 @@ reload (first, global, dumpfile)
{
free (real_known_ptr);
free (real_at_ptr);
- return;
+ free (reg_equiv_constant);
+ free (reg_equiv_memory_loc);
+ free (reg_equiv_mem);
+ free (reg_equiv_init);
+ free (reg_equiv_address);
+ free (reg_max_ref_width);
+ free (reg_old_renumber);
+ free (pseudo_previous_regs);
+ free (pseudo_forbidden_regs);
+ return 0;
}
#endif
- /* Compute the order of preference for hard registers to spill.
- Store them by decreasing preference in potential_reload_regs. */
-
- order_regs_for_reload (global);
-
- /* So far, no hard regs have been spilled. */
- n_spills = 0;
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- spill_reg_order[i] = -1;
+ maybe_fix_stack_asms ();
+ insns_need_reload = 0;
+ something_needs_elimination = 0;
+
/* Initialize to -1, which means take the first spill register. */
last_spill_reg = -1;
- /* On most machines, we can't use any register explicitly used in the
- rtl as a spill register. But on some, we have to. Those will have
- taken care to keep the life of hard regs as short as possible. */
-
- if (! SMALL_REGISTER_CLASSES)
- COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);
+ spilled_pseudos = ALLOCA_REG_SET ();
/* Spill any hard regs that we know we can't eliminate. */
+ CLEAR_HARD_REG_SET (used_spill_regs);
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
if (! ep->can_eliminate)
- spill_hard_reg (ep->from, global, dumpfile, 1);
+ spill_hard_reg (ep->from, dumpfile, 1);
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
if (frame_pointer_needed)
- spill_hard_reg (HARD_FRAME_POINTER_REGNUM, global, dumpfile, 1);
+ spill_hard_reg (HARD_FRAME_POINTER_REGNUM, dumpfile, 1);
#endif
+ finish_spills (global, dumpfile);
- if (global)
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- basic_block_needs[i] = (char *) alloca (n_basic_blocks);
- bzero (basic_block_needs[i], n_basic_blocks);
- }
-
- /* From now on, we need to emit any moves without making new pseudos. */
+ /* From now on, we may need to generate moves differently. We may also
+ allow modifications of insns which cause them to not be recognized.
+ Any such modifications will be cleaned up during reload itself. */
reload_in_progress = 1;
/* This loop scans the entire function each go-round
and repeats until one repetition spills no additional hard regs. */
+ for (;;)
+ {
+ int something_changed;
+ int did_spill;
+ struct insn_chain *chain;
- /* This flag is set when a pseudo reg is spilled,
- to require another pass. Note that getting an additional reload
- reg does not necessarily imply any pseudo reg was spilled;
- sometimes we find a reload reg that no pseudo reg was allocated in. */
- something_changed = 1;
- /* This flag is set if there are any insns that require reloading. */
- something_needs_reloads = 0;
- /* This flag is set if there are any insns that require register
- eliminations. */
- something_needs_elimination = 0;
- while (something_changed)
- {
- rtx after_call = 0;
-
- /* For each class, number of reload regs needed in that class.
- This is the maximum over all insns of the needs in that class
- of the individual insn. */
- int max_needs[N_REG_CLASSES];
- /* For each class, size of group of consecutive regs
- that is needed for the reloads of this class. */
- int group_size[N_REG_CLASSES];
- /* For each class, max number of consecutive groups needed.
- (Each group contains group_size[CLASS] consecutive registers.) */
- int max_groups[N_REG_CLASSES];
- /* For each class, max number needed of regs that don't belong
- to any of the groups. */
- int max_nongroups[N_REG_CLASSES];
- /* For each class, the machine mode which requires consecutive
- groups of regs of that class.
- If two different modes ever require groups of one class,
- they must be the same size and equally restrictive for that class,
- otherwise we can't handle the complexity. */
- enum machine_mode group_mode[N_REG_CLASSES];
- /* Record the insn where each maximum need is first found. */
- rtx max_needs_insn[N_REG_CLASSES];
- rtx max_groups_insn[N_REG_CLASSES];
- rtx max_nongroups_insn[N_REG_CLASSES];
- rtx x;
HOST_WIDE_INT starting_frame_size;
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- int previous_frame_pointer_needed = frame_pointer_needed;
-#endif
- static char *reg_class_names[] = REG_CLASS_NAMES;
-
- something_changed = 0;
- bzero ((char *) max_needs, sizeof max_needs);
- bzero ((char *) max_groups, sizeof max_groups);
- bzero ((char *) max_nongroups, sizeof max_nongroups);
- bzero ((char *) max_needs_insn, sizeof max_needs_insn);
- bzero ((char *) max_groups_insn, sizeof max_groups_insn);
- bzero ((char *) max_nongroups_insn, sizeof max_nongroups_insn);
- bzero ((char *) group_size, sizeof group_size);
- for (i = 0; i < N_REG_CLASSES; i++)
- group_mode[i] = VOIDmode;
-
- /* Keep track of which basic blocks are needing the reloads. */
- this_block = 0;
-
- /* Remember whether any element of basic_block_needs
- changes from 0 to 1 in this pass. */
- new_basic_block_needs = 0;
/* Round size of stack frame to BIGGEST_ALIGNMENT. This must be done
here because the stack size may be a part of the offset computation
@@ -916,38 +880,8 @@ reload (first, global, dumpfile)
starting_frame_size = get_frame_size ();
- /* Reset all offsets on eliminable registers to their initial values. */
-#ifdef ELIMINABLE_REGS
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- {
- INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset);
- ep->previous_offset = ep->offset
- = ep->max_offset = ep->initial_offset;
- }
-#else
-#ifdef INITIAL_FRAME_POINTER_OFFSET
- INITIAL_FRAME_POINTER_OFFSET (reg_eliminate[0].initial_offset);
-#else
- if (!FRAME_POINTER_REQUIRED)
- abort ();
- reg_eliminate[0].initial_offset = 0;
-#endif
- reg_eliminate[0].previous_offset = reg_eliminate[0].max_offset
- = reg_eliminate[0].offset = reg_eliminate[0].initial_offset;
-#endif
-
- num_not_at_initial_offset = 0;
-
- bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels);
-
- /* Set a known offset for each forced label to be at the initial offset
- of each elimination. We do this because we assume that all
- computed jumps occur from a location where each elimination is
- at its initial offset. */
-
- for (x = forced_labels; x; x = XEXP (x, 1))
- if (XEXP (x, 0))
- set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+ set_initial_elim_offsets ();
+ set_initial_label_offsets ();
/* For each pseudo register that has an equivalent location defined,
try to eliminate any eliminable registers (such as the frame pointer)
@@ -1001,1201 +935,1181 @@ reload (first, global, dumpfile)
reg_equiv_memory_loc[i] = 0;
reg_equiv_init[i] = 0;
alter_reg (i, -1);
- something_changed = 1;
}
}
- /* If we allocated another pseudo to the stack, redo elimination
- bookkeeping. */
- if (something_changed)
- continue;
+ if (caller_save_needed)
+ setup_save_areas ();
- /* If caller-saves needs a group, initialize the group to include
- the size and mode required for caller-saves. */
+ /* If we allocated another stack slot, redo elimination bookkeeping. */
+ if (starting_frame_size != get_frame_size ())
+ continue;
- if (caller_save_group_size > 1)
+ if (caller_save_needed)
{
- group_mode[(int) caller_save_spill_class] = Pmode;
- group_size[(int) caller_save_spill_class] = caller_save_group_size;
+ save_call_clobbered_regs ();
+ /* That might have allocated new insn_chain structures. */
+ reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
}
- /* Compute the most additional registers needed by any instruction.
- Collect information separately for each class of regs. */
+ calculate_needs_all_insns (global);
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (global && this_block + 1 < n_basic_blocks
- && insn == basic_block_head[this_block+1])
- ++this_block;
+ CLEAR_REG_SET (spilled_pseudos);
+ did_spill = 0;
- /* If this is a label, a JUMP_INSN, or has REG_NOTES (which
- might include REG_LABEL), we need to see what effects this
- has on the known offsets at labels. */
+ something_changed = 0;
- if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN
- || (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && REG_NOTES (insn) != 0))
- set_label_offsets (insn, insn, 0);
+ /* If we allocated any new memory locations, make another pass
+ since it might have changed elimination offsets. */
+ if (starting_frame_size != get_frame_size ())
+ something_changed = 1;
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ HARD_REG_SET to_spill;
+ CLEAR_HARD_REG_SET (to_spill);
+ update_eliminables (&to_spill);
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (to_spill, i))
{
- /* Nonzero means don't use a reload reg that overlaps
- the place where a function value can be returned. */
- rtx avoid_return_reg = 0;
-
- rtx old_body = PATTERN (insn);
- int old_code = INSN_CODE (insn);
- rtx old_notes = REG_NOTES (insn);
- int did_elimination = 0;
-
- /* To compute the number of reload registers of each class
- needed for an insn, we must simulate what choose_reload_regs
- can do. We do this by splitting an insn into an "input" and
- an "output" part. RELOAD_OTHER reloads are used in both.
- The input part uses those reloads, RELOAD_FOR_INPUT reloads,
- which must be live over the entire input section of reloads,
- and the maximum of all the RELOAD_FOR_INPUT_ADDRESS and
- RELOAD_FOR_OPERAND_ADDRESS reloads, which conflict with the
- inputs.
-
- The registers needed for output are RELOAD_OTHER and
- RELOAD_FOR_OUTPUT, which are live for the entire output
- portion, and the maximum of all the RELOAD_FOR_OUTPUT_ADDRESS
- reloads for each operand.
-
- The total number of registers needed is the maximum of the
- inputs and outputs. */
-
- struct needs
- {
- /* [0] is normal, [1] is nongroup. */
- int regs[2][N_REG_CLASSES];
- int groups[N_REG_CLASSES];
- };
-
- /* Each `struct needs' corresponds to one RELOAD_... type. */
- struct {
- struct needs other;
- struct needs input;
- struct needs output;
- struct needs insn;
- struct needs other_addr;
- struct needs op_addr;
- struct needs op_addr_reload;
- struct needs in_addr[MAX_RECOG_OPERANDS];
- struct needs in_addr_addr[MAX_RECOG_OPERANDS];
- struct needs out_addr[MAX_RECOG_OPERANDS];
- struct needs out_addr_addr[MAX_RECOG_OPERANDS];
- } insn_needs;
-
- /* If needed, eliminate any eliminable registers. */
- if (num_eliminable)
- did_elimination = eliminate_regs_in_insn (insn, 0);
-
- /* Set avoid_return_reg if this is an insn
- that might use the value of a function call. */
- if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
- {
- if (GET_CODE (PATTERN (insn)) == SET)
- after_call = SET_DEST (PATTERN (insn));
- else if (GET_CODE (PATTERN (insn)) == PARALLEL
- && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
- after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
- else
- after_call = 0;
- }
- else if (SMALL_REGISTER_CLASSES && after_call != 0
- && !(GET_CODE (PATTERN (insn)) == SET
- && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
- && GET_CODE (PATTERN (insn)) != USE)
- {
- if (reg_referenced_p (after_call, PATTERN (insn)))
- avoid_return_reg = after_call;
- after_call = 0;
- }
+ spill_hard_reg (i, dumpfile, 1);
+ did_spill = 1;
+
+ /* Regardless of the state of spills, if we previously had
+ a register that we thought we could eliminate, but no can
+ not eliminate, we must run another pass.
+
+ Consider pseudos which have an entry in reg_equiv_* which
+ reference an eliminable register. We must make another pass
+ to update reg_equiv_* so that we do not substitute in the
+ old value from when we thought the elimination could be
+ performed. */
+ something_changed = 1;
+ }
+ }
- /* Analyze the instruction. */
- find_reloads (insn, 0, spill_indirect_levels, global,
- spill_reg_order);
+ CLEAR_HARD_REG_SET (used_spill_regs);
+ /* Try to satisfy the needs for each insn. */
+ for (chain = insns_need_reload; chain != 0;
+ chain = chain->next_need_reload)
+ find_reload_regs (chain, dumpfile);
- /* Remember for later shortcuts which insns had any reloads or
- register eliminations.
+ if (failure)
+ goto failed;
- One might think that it would be worthwhile to mark insns
- that need register replacements but not reloads, but this is
- not safe because find_reloads may do some manipulation of
- the insn (such as swapping commutative operands), which would
- be lost when we restore the old pattern after register
- replacement. So the actions of find_reloads must be redone in
- subsequent passes or in reload_as_needed.
+ if (insns_need_reload != 0 || did_spill)
+ something_changed |= finish_spills (global, dumpfile);
- However, it is safe to mark insns that need reloads
- but not register replacement. */
+ if (! something_changed)
+ break;
- PUT_MODE (insn, (did_elimination ? QImode
- : n_reloads ? HImode
- : GET_MODE (insn) == DImode ? DImode
- : VOIDmode));
+ if (caller_save_needed)
+ delete_caller_save_insns ();
+ }
+
+ /* If global-alloc was run, notify it of any register eliminations we have
+ done. */
+ if (global)
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (ep->can_eliminate)
+ mark_elimination (ep->from, ep->to);
- /* Discard any register replacements done. */
- if (did_elimination)
+ /* If a pseudo has no hard reg, delete the insns that made the equivalence.
+ If that insn didn't set the register (i.e., it copied the register to
+ memory), just delete that insn instead of the equivalencing insn plus
+ anything now dead. If we call delete_dead_insn on that insn, we may
+ delete the insn that actually sets the register if the register dies
+ there and that is incorrect. */
+
+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ {
+ if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0)
+ {
+ rtx list;
+ for (list = reg_equiv_init[i]; list; list = XEXP (list, 1))
+ {
+ rtx equiv_insn = XEXP (list, 0);
+ if (GET_CODE (equiv_insn) == NOTE)
+ continue;
+ if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
+ delete_dead_insn (equiv_insn);
+ else
{
- obstack_free (&reload_obstack, reload_firstobj);
- PATTERN (insn) = old_body;
- INSN_CODE (insn) = old_code;
- REG_NOTES (insn) = old_notes;
- something_needs_elimination = 1;
+ PUT_CODE (equiv_insn, NOTE);
+ NOTE_SOURCE_FILE (equiv_insn) = 0;
+ NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
}
+ }
+ }
+ }
- /* If this insn has no reloads, we need not do anything except
- in the case of a CALL_INSN when we have caller-saves and
- caller-save needs reloads. */
+ /* Use the reload registers where necessary
+ by generating move instructions to move the must-be-register
+ values into or out of the reload registers. */
- if (n_reloads == 0
- && ! (GET_CODE (insn) == CALL_INSN
- && caller_save_spill_class != NO_REGS))
- continue;
+ if (insns_need_reload != 0 || something_needs_elimination
+ || something_needs_operands_changed)
+ {
+ int old_frame_size = get_frame_size ();
- something_needs_reloads = 1;
- bzero ((char *) &insn_needs, sizeof insn_needs);
+ reload_as_needed (global);
- /* Count each reload once in every class
- containing the reload's own class. */
+ if (old_frame_size != get_frame_size ())
+ abort ();
- for (i = 0; i < n_reloads; i++)
- {
- register enum reg_class *p;
- enum reg_class class = reload_reg_class[i];
- int size;
- enum machine_mode mode;
- struct needs *this_needs;
-
- /* Don't count the dummy reloads, for which one of the
- regs mentioned in the insn can be used for reloading.
- Don't count optional reloads.
- Don't count reloads that got combined with others. */
- if (reload_reg_rtx[i] != 0
- || reload_optional[i] != 0
- || (reload_out[i] == 0 && reload_in[i] == 0
- && ! reload_secondary_p[i]))
- continue;
-
- /* Show that a reload register of this class is needed
- in this basic block. We do not use insn_needs and
- insn_groups because they are overly conservative for
- this purpose. */
- if (global && ! basic_block_needs[(int) class][this_block])
- {
- basic_block_needs[(int) class][this_block] = 1;
- new_basic_block_needs = 1;
- }
+ if (num_eliminable)
+ verify_initial_elim_offsets ();
+ }
- mode = reload_inmode[i];
- if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
- mode = reload_outmode[i];
- size = CLASS_MAX_NREGS (class, mode);
+ /* If we were able to eliminate the frame pointer, show that it is no
+ longer live at the start of any basic block. If it ls live by
+ virtue of being in a pseudo, that pseudo will be marked live
+ and hence the frame pointer will be known to be live via that
+ pseudo. */
- /* Decide which time-of-use to count this reload for. */
- switch (reload_when_needed[i])
- {
- case RELOAD_OTHER:
- this_needs = &insn_needs.other;
- break;
- case RELOAD_FOR_INPUT:
- this_needs = &insn_needs.input;
- break;
- case RELOAD_FOR_OUTPUT:
- this_needs = &insn_needs.output;
- break;
- case RELOAD_FOR_INSN:
- this_needs = &insn_needs.insn;
- break;
- case RELOAD_FOR_OTHER_ADDRESS:
- this_needs = &insn_needs.other_addr;
- break;
- case RELOAD_FOR_INPUT_ADDRESS:
- this_needs = &insn_needs.in_addr[reload_opnum[i]];
- break;
- case RELOAD_FOR_INPADDR_ADDRESS:
- this_needs = &insn_needs.in_addr_addr[reload_opnum[i]];
- break;
- case RELOAD_FOR_OUTPUT_ADDRESS:
- this_needs = &insn_needs.out_addr[reload_opnum[i]];
- break;
- case RELOAD_FOR_OUTADDR_ADDRESS:
- this_needs = &insn_needs.out_addr_addr[reload_opnum[i]];
- break;
- case RELOAD_FOR_OPERAND_ADDRESS:
- this_needs = &insn_needs.op_addr;
- break;
- case RELOAD_FOR_OPADDR_ADDR:
- this_needs = &insn_needs.op_addr_reload;
- break;
- }
+ if (! frame_pointer_needed)
+ for (i = 0; i < n_basic_blocks; i++)
+ CLEAR_REGNO_REG_SET (BASIC_BLOCK (i)->global_live_at_start,
+ HARD_FRAME_POINTER_REGNUM);
- if (size > 1)
- {
- enum machine_mode other_mode, allocate_mode;
-
- /* Count number of groups needed separately from
- number of individual regs needed. */
- this_needs->groups[(int) class]++;
- p = reg_class_superclasses[(int) class];
- while (*p != LIM_REG_CLASSES)
- this_needs->groups[(int) *p++]++;
-
- /* Record size and mode of a group of this class. */
- /* If more than one size group is needed,
- make all groups the largest needed size. */
- if (group_size[(int) class] < size)
- {
- other_mode = group_mode[(int) class];
- allocate_mode = mode;
+ /* Come here (with failure set nonzero) if we can't get enough spill regs
+ and we decide not to abort about it. */
+ failed:
- group_size[(int) class] = size;
- group_mode[(int) class] = mode;
- }
- else
- {
- other_mode = mode;
- allocate_mode = group_mode[(int) class];
- }
+ reload_in_progress = 0;
- /* Crash if two dissimilar machine modes both need
- groups of consecutive regs of the same class. */
+ /* Now eliminate all pseudo regs by modifying them into
+ their equivalent memory references.
+ The REG-rtx's for the pseudos are modified in place,
+ so all insns that used to refer to them now refer to memory.
- if (other_mode != VOIDmode && other_mode != allocate_mode
- && ! modes_equiv_for_class_p (allocate_mode,
- other_mode, class))
- fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class",
- insn);
- }
- else if (size == 1)
- {
- this_needs->regs[reload_nongroup[i]][(int) class] += 1;
- p = reg_class_superclasses[(int) class];
- while (*p != LIM_REG_CLASSES)
- this_needs->regs[reload_nongroup[i]][(int) *p++] += 1;
- }
- else
- abort ();
- }
+ For a reg that has a reg_equiv_address, all those insns
+ were changed by reloading so that no insns refer to it any longer;
+ but the DECL_RTL of a variable decl may refer to it,
+ and if so this causes the debugging info to mention the variable. */
- /* All reloads have been counted for this insn;
- now merge the various times of use.
- This sets insn_needs, etc., to the maximum total number
- of registers needed at any point in this insn. */
+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ {
+ rtx addr = 0;
+ int in_struct = 0;
+ int is_scalar;
+ int is_readonly = 0;
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- int in_max, out_max;
+ if (reg_equiv_memory_loc[i])
+ {
+ in_struct = MEM_IN_STRUCT_P (reg_equiv_memory_loc[i]);
+ is_scalar = MEM_SCALAR_P (reg_equiv_memory_loc[i]);
+ is_readonly = RTX_UNCHANGING_P (reg_equiv_memory_loc[i]);
+ }
- /* Compute normal and nongroup needs. */
- for (j = 0; j <= 1; j++)
- {
- for (in_max = 0, out_max = 0, k = 0;
- k < reload_n_operands; k++)
- {
- in_max
- = MAX (in_max,
- (insn_needs.in_addr[k].regs[j][i]
- + insn_needs.in_addr_addr[k].regs[j][i]));
- out_max
- = MAX (out_max, insn_needs.out_addr[k].regs[j][i]);
- out_max
- = MAX (out_max,
- insn_needs.out_addr_addr[k].regs[j][i]);
- }
+ if (reg_equiv_mem[i])
+ addr = XEXP (reg_equiv_mem[i], 0);
- /* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
- and operand addresses but not things used to reload
- them. Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads
- don't conflict with things needed to reload inputs or
- outputs. */
+ if (reg_equiv_address[i])
+ addr = reg_equiv_address[i];
- in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
- insn_needs.op_addr_reload.regs[j][i]),
- in_max);
+ if (addr)
+ {
+ if (reg_renumber[i] < 0)
+ {
+ rtx reg = regno_reg_rtx[i];
+ XEXP (reg, 0) = addr;
+ REG_USERVAR_P (reg) = 0;
+ RTX_UNCHANGING_P (reg) = is_readonly;
+ MEM_IN_STRUCT_P (reg) = in_struct;
+ MEM_SCALAR_P (reg) = is_scalar;
+ /* We have no alias information about this newly created
+ MEM. */
+ MEM_ALIAS_SET (reg) = 0;
+ PUT_CODE (reg, MEM);
+ }
+ else if (reg_equiv_mem[i])
+ XEXP (reg_equiv_mem[i], 0) = addr;
+ }
+ }
- out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
+ /* We must set reload_completed now since the cleanup_subreg_operands call
+ below will re-recognize each insn and reload may have generated insns
+ which are only valid during and after reload. */
+ reload_completed = 1;
- insn_needs.input.regs[j][i]
- = MAX (insn_needs.input.regs[j][i]
- + insn_needs.op_addr.regs[j][i]
- + insn_needs.insn.regs[j][i],
- in_max + insn_needs.input.regs[j][i]);
+ /* Make a pass over all the insns and delete all USEs which we
+ inserted only to tag a REG_EQUAL note on them. Remove all
+ REG_DEAD and REG_UNUSED notes. Delete all CLOBBER insns and
+ simplify (subreg (reg)) operands. Also remove all REG_RETVAL and
+ REG_LIBCALL notes since they are no longer useful or accurate.
+ Strip and regenerate REG_INC notes that may have been moved
+ around. */
- insn_needs.output.regs[j][i] += out_max;
- insn_needs.other.regs[j][i]
- += MAX (MAX (insn_needs.input.regs[j][i],
- insn_needs.output.regs[j][i]),
- insn_needs.other_addr.regs[j][i]);
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ rtx *pnote;
- }
+ if ((GET_CODE (PATTERN (insn)) == USE
+ && find_reg_note (insn, REG_EQUAL, NULL_RTX))
+ || GET_CODE (PATTERN (insn)) == CLOBBER)
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_SOURCE_FILE (insn) = 0;
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ continue;
+ }
- /* Now compute group needs. */
- for (in_max = 0, out_max = 0, j = 0;
- j < reload_n_operands; j++)
- {
- in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]);
- in_max = MAX (in_max,
- insn_needs.in_addr_addr[j].groups[i]);
- out_max
- = MAX (out_max, insn_needs.out_addr[j].groups[i]);
- out_max
- = MAX (out_max, insn_needs.out_addr_addr[j].groups[i]);
- }
+ pnote = &REG_NOTES (insn);
+ while (*pnote != 0)
+ {
+ if (REG_NOTE_KIND (*pnote) == REG_DEAD
+ || REG_NOTE_KIND (*pnote) == REG_UNUSED
+ || REG_NOTE_KIND (*pnote) == REG_INC
+ || REG_NOTE_KIND (*pnote) == REG_RETVAL
+ || REG_NOTE_KIND (*pnote) == REG_LIBCALL)
+ *pnote = XEXP (*pnote, 1);
+ else
+ pnote = &XEXP (*pnote, 1);
+ }
- in_max = MAX (MAX (insn_needs.op_addr.groups[i],
- insn_needs.op_addr_reload.groups[i]),
- in_max);
- out_max = MAX (out_max, insn_needs.insn.groups[i]);
-
- insn_needs.input.groups[i]
- = MAX (insn_needs.input.groups[i]
- + insn_needs.op_addr.groups[i]
- + insn_needs.insn.groups[i],
- in_max + insn_needs.input.groups[i]);
-
- insn_needs.output.groups[i] += out_max;
- insn_needs.other.groups[i]
- += MAX (MAX (insn_needs.input.groups[i],
- insn_needs.output.groups[i]),
- insn_needs.other_addr.groups[i]);
- }
+#ifdef AUTO_INC_DEC
+ add_auto_inc_notes (insn, PATTERN (insn));
+#endif
- /* If this is a CALL_INSN and caller-saves will need
- a spill register, act as if the spill register is
- needed for this insn. However, the spill register
- can be used by any reload of this insn, so we only
- need do something if no need for that class has
- been recorded.
+ /* And simplify (subreg (reg)) if it appears as an operand. */
+ cleanup_subreg_operands (insn);
+ }
- The assumption that every CALL_INSN will trigger a
- caller-save is highly conservative, however, the number
- of cases where caller-saves will need a spill register but
- a block containing a CALL_INSN won't need a spill register
- of that class should be quite rare.
+ /* If we are doing stack checking, give a warning if this function's
+ frame size is larger than we expect. */
+ if (flag_stack_check && ! STACK_CHECK_BUILTIN)
+ {
+ HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
+ static int verbose_warned = 0;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (regs_ever_live[i] && ! fixed_regs[i] && call_used_regs[i])
+ size += UNITS_PER_WORD;
- If a group is needed, the size and mode of the group will
- have been set up at the beginning of this loop. */
+ if (size > STACK_CHECK_MAX_FRAME_SIZE)
+ {
+ warning ("frame size too large for reliable stack checking");
+ if (! verbose_warned)
+ {
+ warning ("try reducing the number of local variables");
+ verbose_warned = 1;
+ }
+ }
+ }
- if (GET_CODE (insn) == CALL_INSN
- && caller_save_spill_class != NO_REGS)
- {
- /* See if this register would conflict with any reload that
- needs a group or any reload that needs a nongroup. */
- int nongroup_need = 0;
- int *caller_save_needs;
-
- for (j = 0; j < n_reloads; j++)
- if (reg_classes_intersect_p (caller_save_spill_class,
- reload_reg_class[j])
- && ((CLASS_MAX_NREGS
- (reload_reg_class[j],
- (GET_MODE_SIZE (reload_outmode[j])
- > GET_MODE_SIZE (reload_inmode[j]))
- ? reload_outmode[j] : reload_inmode[j])
- > 1)
- || reload_nongroup[j]))
- {
- nongroup_need = 1;
- break;
- }
+ /* Indicate that we no longer have known memory locations or constants. */
+ if (reg_equiv_constant)
+ free (reg_equiv_constant);
+ reg_equiv_constant = 0;
+ if (reg_equiv_memory_loc)
+ free (reg_equiv_memory_loc);
+ reg_equiv_memory_loc = 0;
- caller_save_needs
- = (caller_save_group_size > 1
- ? insn_needs.other.groups
- : insn_needs.other.regs[nongroup_need]);
+ if (real_known_ptr)
+ free (real_known_ptr);
+ if (real_at_ptr)
+ free (real_at_ptr);
- if (caller_save_needs[(int) caller_save_spill_class] == 0)
- {
- register enum reg_class *p
- = reg_class_superclasses[(int) caller_save_spill_class];
+ free (reg_equiv_mem);
+ free (reg_equiv_init);
+ free (reg_equiv_address);
+ free (reg_max_ref_width);
+ free (reg_old_renumber);
+ free (pseudo_previous_regs);
+ free (pseudo_forbidden_regs);
- caller_save_needs[(int) caller_save_spill_class]++;
+ FREE_REG_SET (spilled_pseudos);
- while (*p != LIM_REG_CLASSES)
- caller_save_needs[(int) *p++] += 1;
- }
+ CLEAR_HARD_REG_SET (used_spill_regs);
+ for (i = 0; i < n_spills; i++)
+ SET_HARD_REG_BIT (used_spill_regs, spill_regs[i]);
- /* Show that this basic block will need a register of
- this class. */
+ /* Free all the insn_chain structures at once. */
+ obstack_free (&reload_obstack, reload_startobj);
+ unused_insn_chains = 0;
- if (global
- && ! (basic_block_needs[(int) caller_save_spill_class]
- [this_block]))
- {
- basic_block_needs[(int) caller_save_spill_class]
- [this_block] = 1;
- new_basic_block_needs = 1;
- }
- }
+ return failure;
+}
- /* If this insn stores the value of a function call,
- and that value is in a register that has been spilled,
- and if the insn needs a reload in a class
- that might use that register as the reload register,
- then add an extra need in that class.
- This makes sure we have a register available that does
- not overlap the return value. */
+/* Yet another special case. Unfortunately, reg-stack forces people to
+ write incorrect clobbers in asm statements. These clobbers must not
+ cause the register to appear in bad_spill_regs, otherwise we'll call
+ fatal_insn later. We clear the corresponding regnos in the live
+ register sets to avoid this.
+ The whole thing is rather sick, I'm afraid. */
+static void
+maybe_fix_stack_asms ()
+{
+#ifdef STACK_REGS
+ char *constraints[MAX_RECOG_OPERANDS];
+ enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+ struct insn_chain *chain;
- if (SMALL_REGISTER_CLASSES && avoid_return_reg)
- {
- int regno = REGNO (avoid_return_reg);
- int nregs
- = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
- int r;
- int basic_needs[N_REG_CLASSES], basic_groups[N_REG_CLASSES];
-
- /* First compute the "basic needs", which counts a
- need only in the smallest class in which it
- is required. */
-
- bcopy ((char *) insn_needs.other.regs[0],
- (char *) basic_needs, sizeof basic_needs);
- bcopy ((char *) insn_needs.other.groups,
- (char *) basic_groups, sizeof basic_groups);
-
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- enum reg_class *p;
+ for (chain = reload_insn_chain; chain != 0; chain = chain->next)
+ {
+ int i, noperands;
+ HARD_REG_SET clobbered, allowed;
+ rtx pat;
- if (basic_needs[i] >= 0)
- for (p = reg_class_superclasses[i];
- *p != LIM_REG_CLASSES; p++)
- basic_needs[(int) *p] -= basic_needs[i];
+ if (GET_RTX_CLASS (GET_CODE (chain->insn)) != 'i'
+ || (noperands = asm_noperands (PATTERN (chain->insn))) < 0)
+ continue;
+ pat = PATTERN (chain->insn);
+ if (GET_CODE (pat) != PARALLEL)
+ continue;
- if (basic_groups[i] >= 0)
- for (p = reg_class_superclasses[i];
- *p != LIM_REG_CLASSES; p++)
- basic_groups[(int) *p] -= basic_groups[i];
- }
+ CLEAR_HARD_REG_SET (clobbered);
+ CLEAR_HARD_REG_SET (allowed);
- /* Now count extra regs if there might be a conflict with
- the return value register. */
+ /* First, make a mask of all stack regs that are clobbered. */
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx t = XVECEXP (pat, 0, i);
+ if (GET_CODE (t) == CLOBBER && STACK_REG_P (XEXP (t, 0)))
+ SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
+ }
- for (r = regno; r < regno + nregs; r++)
- if (spill_reg_order[r] >= 0)
- for (i = 0; i < N_REG_CLASSES; i++)
- if (TEST_HARD_REG_BIT (reg_class_contents[i], r))
- {
- if (basic_needs[i] > 0)
- {
- enum reg_class *p;
+ /* Get the operand values and constraints out of the insn. */
+ decode_asm_operands (pat, recog_operand, recog_operand_loc,
+ constraints, operand_mode);
- insn_needs.other.regs[0][i]++;
- p = reg_class_superclasses[i];
- while (*p != LIM_REG_CLASSES)
- insn_needs.other.regs[0][(int) *p++]++;
- }
- if (basic_groups[i] > 0)
- {
- enum reg_class *p;
+ /* For every operand, see what registers are allowed. */
+ for (i = 0; i < noperands; i++)
+ {
+ char *p = constraints[i];
+ /* For every alternative, we compute the class of registers allowed
+ for reloading in CLS, and merge its contents into the reg set
+ ALLOWED. */
+ int cls = (int) NO_REGS;
- insn_needs.other.groups[i]++;
- p = reg_class_superclasses[i];
- while (*p != LIM_REG_CLASSES)
- insn_needs.other.groups[(int) *p++]++;
- }
- }
- }
+ for (;;)
+ {
+ char c = *p++;
- /* For each class, collect maximum need of any insn. */
+ if (c == '\0' || c == ',' || c == '#')
+ {
+ /* End of one alternative - mark the regs in the current
+ class, and reset the class. */
+ IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
+ cls = NO_REGS;
+ if (c == '#')
+ do {
+ c = *p++;
+ } while (c != '\0' && c != ',');
+ if (c == '\0')
+ break;
+ continue;
+ }
- for (i = 0; i < N_REG_CLASSES; i++)
+ switch (c)
{
- if (max_needs[i] < insn_needs.other.regs[0][i])
- {
- max_needs[i] = insn_needs.other.regs[0][i];
- max_needs_insn[i] = insn;
- }
- if (max_groups[i] < insn_needs.other.groups[i])
- {
- max_groups[i] = insn_needs.other.groups[i];
- max_groups_insn[i] = insn;
- }
- if (max_nongroups[i] < insn_needs.other.regs[1][i])
- {
- max_nongroups[i] = insn_needs.other.regs[1][i];
- max_nongroups_insn[i] = insn;
- }
+ case '=': case '+': case '*': case '%': case '?': case '!':
+ case '0': case '1': case '2': case '3': case '4': case 'm':
+ case '<': case '>': case 'V': case 'o': case '&': case 'E':
+ case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
+ case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P':
+#ifdef EXTRA_CONSTRAINT
+ case 'Q': case 'R': case 'S': case 'T': case 'U':
+#endif
+ break;
+
+ case 'p':
+ cls = (int) reg_class_subunion[cls][(int) BASE_REG_CLASS];
+ break;
+
+ case 'g':
+ case 'r':
+ cls = (int) reg_class_subunion[cls][(int) GENERAL_REGS];
+ break;
+
+ default:
+ cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
+
}
}
- /* Note that there is a continue statement above. */
}
-
- /* If we allocated any new memory locations, make another pass
- since it might have changed elimination offsets. */
- if (starting_frame_size != get_frame_size ())
- something_changed = 1;
-
- if (dumpfile)
- for (i = 0; i < N_REG_CLASSES; i++)
+ /* Those of the registers which are clobbered, but allowed by the
+ constraints, must be usable as reload registers. So clear them
+ out of the life information. */
+ AND_HARD_REG_SET (allowed, clobbered);
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (allowed, i))
{
- if (max_needs[i] > 0)
- fprintf (dumpfile,
- ";; Need %d reg%s of class %s (for insn %d).\n",
- max_needs[i], max_needs[i] == 1 ? "" : "s",
- reg_class_names[i], INSN_UID (max_needs_insn[i]));
- if (max_nongroups[i] > 0)
- fprintf (dumpfile,
- ";; Need %d nongroup reg%s of class %s (for insn %d).\n",
- max_nongroups[i], max_nongroups[i] == 1 ? "" : "s",
- reg_class_names[i], INSN_UID (max_nongroups_insn[i]));
- if (max_groups[i] > 0)
- fprintf (dumpfile,
- ";; Need %d group%s (%smode) of class %s (for insn %d).\n",
- max_groups[i], max_groups[i] == 1 ? "" : "s",
- mode_name[(int) group_mode[i]],
- reg_class_names[i], INSN_UID (max_groups_insn[i]));
+ CLEAR_REGNO_REG_SET (chain->live_before, i);
+ CLEAR_REGNO_REG_SET (chain->live_after, i);
}
-
- /* If we have caller-saves, set up the save areas and see if caller-save
- will need a spill register. */
+ }
- if (caller_save_needed)
- {
- /* Set the offsets for setup_save_areas. */
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
- ep++)
- ep->previous_offset = ep->max_offset;
+#endif
+}
+
+
+/* Walk the chain of insns, and determine for each whether it needs reloads
+ and/or eliminations. Build the corresponding insns_need_reload list, and
+ set something_needs_elimination as appropriate. */
+static void
+calculate_needs_all_insns (global)
+ int global;
+{
+ struct insn_chain **pprev_reload = &insns_need_reload;
+ struct insn_chain **pchain;
+
+ something_needs_elimination = 0;
- if ( ! setup_save_areas (&something_changed)
- && caller_save_spill_class == NO_REGS)
+ for (pchain = &reload_insn_chain; *pchain != 0; pchain = &(*pchain)->next)
+ {
+ rtx insn;
+ struct insn_chain *chain;
+
+ chain = *pchain;
+ insn = chain->insn;
+
+ /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
+ include REG_LABEL), we need to see what effects this has on the
+ known offsets at labels. */
+
+ if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN
+ || (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+ && REG_NOTES (insn) != 0))
+ set_label_offsets (insn, insn, 0);
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ rtx old_body = PATTERN (insn);
+ int old_code = INSN_CODE (insn);
+ rtx old_notes = REG_NOTES (insn);
+ int did_elimination = 0;
+ int operands_changed = 0;
+ rtx set = single_set (insn);
+
+ /* Skip insns that only set an equivalence. */
+ if (set && GET_CODE (SET_DEST (set)) == REG
+ && reg_renumber[REGNO (SET_DEST (set))] < 0
+ && reg_equiv_constant[REGNO (SET_DEST (set))])
{
- /* The class we will need depends on whether the machine
- supports the sum of two registers for an address; see
- find_address_reloads for details. */
-
- caller_save_spill_class
- = double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS;
- caller_save_group_size
- = CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
- something_changed = 1;
+ /* Must clear out the shortcuts, in case they were set last
+ time through. */
+ chain->need_elim = 0;
+ chain->need_reload = 0;
+ chain->need_operand_change = 0;
+ continue;
}
- }
- /* See if anything that happened changes which eliminations are valid.
- For example, on the Sparc, whether or not the frame pointer can
- be eliminated can depend on what registers have been used. We need
- not check some conditions again (such as flag_omit_frame_pointer)
- since they can't have changed. */
+ /* If needed, eliminate any eliminable registers. */
+ if (num_eliminable || num_eliminable_invariants)
+ did_elimination = eliminate_regs_in_insn (insn, 0);
+
+ /* Analyze the instruction. */
+ operands_changed = find_reloads (insn, 0, spill_indirect_levels,
+ global, spill_reg_order);
+
+ /* If a no-op set needs more than one reload, this is likely
+ to be something that needs input address reloads. We
+ can't get rid of this cleanly later, and it is of no use
+ anyway, so discard it now.
+ We only do this when expensive_optimizations is enabled,
+ since this complements reload inheritance / output
+ reload deletion, and it can make debugging harder. */
+ if (flag_expensive_optimizations && n_reloads > 1)
+ {
+ rtx set = single_set (insn);
+ if (set
+ && SET_SRC (set) == SET_DEST (set)
+ && GET_CODE (SET_SRC (set)) == REG
+ && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_SOURCE_FILE (insn) = 0;
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ continue;
+ }
+ }
+ if (num_eliminable)
+ update_eliminable_offsets ();
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)
-#ifdef ELIMINABLE_REGS
- || ! CAN_ELIMINATE (ep->from, ep->to)
-#endif
- )
- ep->can_eliminate = 0;
+ /* Remember for later shortcuts which insns had any reloads or
+ register eliminations. */
+ chain->need_elim = did_elimination;
+ chain->need_reload = n_reloads > 0;
+ chain->need_operand_change = operands_changed;
- /* Look for the case where we have discovered that we can't replace
- register A with register B and that means that we will now be
- trying to replace register A with register C. This means we can
- no longer replace register C with register B and we need to disable
- such an elimination, if it exists. This occurs often with A == ap,
- B == sp, and C == fp. */
+ /* Discard any register replacements done. */
+ if (did_elimination)
+ {
+ obstack_free (&reload_obstack, reload_firstobj);
+ PATTERN (insn) = old_body;
+ INSN_CODE (insn) = old_code;
+ REG_NOTES (insn) = old_notes;
+ something_needs_elimination = 1;
+ }
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- {
- struct elim_table *op;
- register int new_to = -1;
+ something_needs_operands_changed |= operands_changed;
- if (! ep->can_eliminate && ep->can_eliminate_previous)
+ if (n_reloads != 0)
{
- /* Find the current elimination for ep->from, if there is a
- new one. */
- for (op = reg_eliminate;
- op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
- if (op->from == ep->from && op->can_eliminate)
- {
- new_to = op->to;
- break;
- }
+ *pprev_reload = chain;
+ pprev_reload = &chain->next_need_reload;
- /* See if there is an elimination of NEW_TO -> EP->TO. If so,
- disable it. */
- for (op = reg_eliminate;
- op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
- if (op->from == new_to && op->to == ep->to)
- op->can_eliminate = 0;
+ calculate_needs (chain);
}
}
+ }
+ *pprev_reload = 0;
+}
- /* See if any registers that we thought we could eliminate the previous
- time are no longer eliminable. If so, something has changed and we
- must spill the register. Also, recompute the number of eliminable
- registers and see if the frame pointer is needed; it is if there is
- no elimination of the frame pointer that we can perform. */
+/* Compute the most additional registers needed by one instruction,
+ given by CHAIN. Collect information separately for each class of regs.
- frame_pointer_needed = 1;
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ To compute the number of reload registers of each class needed for an
+ insn, we must simulate what choose_reload_regs can do. We do this by
+ splitting an insn into an "input" and an "output" part. RELOAD_OTHER
+ reloads are used in both. The input part uses those reloads,
+ RELOAD_FOR_INPUT reloads, which must be live over the entire input section
+ of reloads, and the maximum of all the RELOAD_FOR_INPUT_ADDRESS and
+ RELOAD_FOR_OPERAND_ADDRESS reloads, which conflict with the inputs.
+
+ The registers needed for output are RELOAD_OTHER and RELOAD_FOR_OUTPUT,
+ which are live for the entire output portion, and the maximum of all the
+ RELOAD_FOR_OUTPUT_ADDRESS reloads for each operand.
+
+ The total number of registers needed is the maximum of the
+ inputs and outputs. */
+
+static void
+calculate_needs (chain)
+ struct insn_chain *chain;
+{
+ int i;
+
+ /* Each `struct needs' corresponds to one RELOAD_... type. */
+ struct {
+ struct needs other;
+ struct needs input;
+ struct needs output;
+ struct needs insn;
+ struct needs other_addr;
+ struct needs op_addr;
+ struct needs op_addr_reload;
+ struct needs in_addr[MAX_RECOG_OPERANDS];
+ struct needs in_addr_addr[MAX_RECOG_OPERANDS];
+ struct needs out_addr[MAX_RECOG_OPERANDS];
+ struct needs out_addr_addr[MAX_RECOG_OPERANDS];
+ } insn_needs;
+
+ bzero ((char *) chain->group_size, sizeof chain->group_size);
+ for (i = 0; i < N_REG_CLASSES; i++)
+ chain->group_mode[i] = VOIDmode;
+ bzero ((char *) &insn_needs, sizeof insn_needs);
+
+ /* Count each reload once in every class
+ containing the reload's own class. */
+
+ for (i = 0; i < n_reloads; i++)
+ {
+ register enum reg_class *p;
+ enum reg_class class = reload_reg_class[i];
+ int size;
+ enum machine_mode mode;
+ struct needs *this_needs;
+
+ /* Don't count the dummy reloads, for which one of the
+ regs mentioned in the insn can be used for reloading.
+ Don't count optional reloads.
+ Don't count reloads that got combined with others. */
+ if (reload_reg_rtx[i] != 0
+ || reload_optional[i] != 0
+ || (reload_out[i] == 0 && reload_in[i] == 0
+ && ! reload_secondary_p[i]))
+ continue;
+
+ mode = reload_inmode[i];
+ if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
+ mode = reload_outmode[i];
+ size = CLASS_MAX_NREGS (class, mode);
+
+ /* Decide which time-of-use to count this reload for. */
+ switch (reload_when_needed[i])
{
- if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM
- && ep->to != HARD_FRAME_POINTER_REGNUM)
- frame_pointer_needed = 0;
+ case RELOAD_OTHER:
+ this_needs = &insn_needs.other;
+ break;
+ case RELOAD_FOR_INPUT:
+ this_needs = &insn_needs.input;
+ break;
+ case RELOAD_FOR_OUTPUT:
+ this_needs = &insn_needs.output;
+ break;
+ case RELOAD_FOR_INSN:
+ this_needs = &insn_needs.insn;
+ break;
+ case RELOAD_FOR_OTHER_ADDRESS:
+ this_needs = &insn_needs.other_addr;
+ break;
+ case RELOAD_FOR_INPUT_ADDRESS:
+ this_needs = &insn_needs.in_addr[reload_opnum[i]];
+ break;
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ this_needs = &insn_needs.in_addr_addr[reload_opnum[i]];
+ break;
+ case RELOAD_FOR_OUTPUT_ADDRESS:
+ this_needs = &insn_needs.out_addr[reload_opnum[i]];
+ break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ this_needs = &insn_needs.out_addr_addr[reload_opnum[i]];
+ break;
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ this_needs = &insn_needs.op_addr;
+ break;
+ case RELOAD_FOR_OPADDR_ADDR:
+ this_needs = &insn_needs.op_addr_reload;
+ break;
+ default:
+ abort();
+ }
- if (! ep->can_eliminate && ep->can_eliminate_previous)
+ if (size > 1)
+ {
+ enum machine_mode other_mode, allocate_mode;
+
+ /* Count number of groups needed separately from
+ number of individual regs needed. */
+ this_needs->groups[(int) class]++;
+ p = reg_class_superclasses[(int) class];
+ while (*p != LIM_REG_CLASSES)
+ this_needs->groups[(int) *p++]++;
+
+ /* Record size and mode of a group of this class. */
+ /* If more than one size group is needed,
+ make all groups the largest needed size. */
+ if (chain->group_size[(int) class] < size)
{
- ep->can_eliminate_previous = 0;
- spill_hard_reg (ep->from, global, dumpfile, 1);
- something_changed = 1;
- num_eliminable--;
+ other_mode = chain->group_mode[(int) class];
+ allocate_mode = mode;
+
+ chain->group_size[(int) class] = size;
+ chain->group_mode[(int) class] = mode;
+ }
+ else
+ {
+ other_mode = mode;
+ allocate_mode = chain->group_mode[(int) class];
}
- }
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- /* If we didn't need a frame pointer last time, but we do now, spill
- the hard frame pointer. */
- if (frame_pointer_needed && ! previous_frame_pointer_needed)
+ /* Crash if two dissimilar machine modes both need
+ groups of consecutive regs of the same class. */
+
+ if (other_mode != VOIDmode && other_mode != allocate_mode
+ && ! modes_equiv_for_class_p (allocate_mode,
+ other_mode, class))
+ fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class",
+ chain->insn);
+ }
+ else if (size == 1)
{
- spill_hard_reg (HARD_FRAME_POINTER_REGNUM, global, dumpfile, 1);
- something_changed = 1;
+ this_needs->regs[(unsigned char)reload_nongroup[i]][(int) class] += 1;
+ p = reg_class_superclasses[(int) class];
+ while (*p != LIM_REG_CLASSES)
+ this_needs->regs[(unsigned char)reload_nongroup[i]][(int) *p++] += 1;
}
-#endif
+ else
+ abort ();
+ }
- /* If all needs are met, we win. */
+ /* All reloads have been counted for this insn;
+ now merge the various times of use.
+ This sets insn_needs, etc., to the maximum total number
+ of registers needed at any point in this insn. */
- for (i = 0; i < N_REG_CLASSES; i++)
- if (max_needs[i] > 0 || max_groups[i] > 0 || max_nongroups[i] > 0)
- break;
- if (i == N_REG_CLASSES && !new_basic_block_needs && ! something_changed)
- break;
+ for (i = 0; i < N_REG_CLASSES; i++)
+ {
+ int j, in_max, out_max;
- /* Not all needs are met; must spill some hard regs. */
-
- /* Put all registers spilled so far back in potential_reload_regs, but
- put them at the front, since we've already spilled most of the
- pseudos in them (we might have left some pseudos unspilled if they
- were in a block that didn't need any spill registers of a conflicting
- class. We used to try to mark off the need for those registers,
- but doing so properly is very complex and reallocating them is the
- simpler approach. First, "pack" potential_reload_regs by pushing
- any nonnegative entries towards the end. That will leave room
- for the registers we already spilled.
-
- Also, undo the marking of the spill registers from the last time
- around in FORBIDDEN_REGS since we will be probably be allocating
- them again below.
-
- ??? It is theoretically possible that we might end up not using one
- of our previously-spilled registers in this allocation, even though
- they are at the head of the list. It's not clear what to do about
- this, but it was no better before, when we marked off the needs met
- by the previously-spilled registers. With the current code, globals
- can be allocated into these registers, but locals cannot. */
-
- if (n_spills)
+ /* Compute normal and nongroup needs. */
+ for (j = 0; j <= 1; j++)
{
- for (i = j = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
- if (potential_reload_regs[i] != -1)
- potential_reload_regs[j--] = potential_reload_regs[i];
-
- for (i = 0; i < n_spills; i++)
+ int k;
+ for (in_max = 0, out_max = 0, k = 0; k < reload_n_operands; k++)
{
- potential_reload_regs[i] = spill_regs[i];
- spill_reg_order[spill_regs[i]] = -1;
- CLEAR_HARD_REG_BIT (forbidden_regs, spill_regs[i]);
+ in_max = MAX (in_max,
+ (insn_needs.in_addr[k].regs[j][i]
+ + insn_needs.in_addr_addr[k].regs[j][i]));
+ out_max = MAX (out_max, insn_needs.out_addr[k].regs[j][i]);
+ out_max = MAX (out_max,
+ insn_needs.out_addr_addr[k].regs[j][i]);
}
- n_spills = 0;
- }
-
- /* Now find more reload regs to satisfy the remaining need
- Do it by ascending class number, since otherwise a reg
- might be spilled for a big class and might fail to count
- for a smaller class even though it belongs to that class.
+ /* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
+ and operand addresses but not things used to reload
+ them. Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads
+ don't conflict with things needed to reload inputs or
+ outputs. */
- Count spilled regs in `spills', and add entries to
- `spill_regs' and `spill_reg_order'.
+ in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
+ insn_needs.op_addr_reload.regs[j][i]),
+ in_max);
- ??? Note there is a problem here.
- When there is a need for a group in a high-numbered class,
- and also need for non-group regs that come from a lower class,
- the non-group regs are chosen first. If there aren't many regs,
- they might leave no room for a group.
+ out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
- This was happening on the 386. To fix it, we added the code
- that calls possible_group_p, so that the lower class won't
- break up the last possible group.
+ insn_needs.input.regs[j][i]
+ = MAX (insn_needs.input.regs[j][i]
+ + insn_needs.op_addr.regs[j][i]
+ + insn_needs.insn.regs[j][i],
+ in_max + insn_needs.input.regs[j][i]);
- Really fixing the problem would require changes above
- in counting the regs already spilled, and in choose_reload_regs.
- It might be hard to avoid introducing bugs there. */
+ insn_needs.output.regs[j][i] += out_max;
+ insn_needs.other.regs[j][i]
+ += MAX (MAX (insn_needs.input.regs[j][i],
+ insn_needs.output.regs[j][i]),
+ insn_needs.other_addr.regs[j][i]);
- CLEAR_HARD_REG_SET (counted_for_groups);
- CLEAR_HARD_REG_SET (counted_for_nongroups);
+ }
- for (class = 0; class < N_REG_CLASSES; class++)
+ /* Now compute group needs. */
+ for (in_max = 0, out_max = 0, j = 0; j < reload_n_operands; j++)
{
- /* First get the groups of registers.
- If we got single registers first, we might fragment
- possible groups. */
- while (max_groups[class] > 0)
- {
- /* If any single spilled regs happen to form groups,
- count them now. Maybe we don't really need
- to spill another group. */
- count_possible_groups (group_size, group_mode, max_groups,
- class);
+ in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]);
+ in_max = MAX (in_max, insn_needs.in_addr_addr[j].groups[i]);
+ out_max = MAX (out_max, insn_needs.out_addr[j].groups[i]);
+ out_max = MAX (out_max, insn_needs.out_addr_addr[j].groups[i]);
+ }
- if (max_groups[class] <= 0)
- break;
+ in_max = MAX (MAX (insn_needs.op_addr.groups[i],
+ insn_needs.op_addr_reload.groups[i]),
+ in_max);
+ out_max = MAX (out_max, insn_needs.insn.groups[i]);
+
+ insn_needs.input.groups[i]
+ = MAX (insn_needs.input.groups[i]
+ + insn_needs.op_addr.groups[i]
+ + insn_needs.insn.groups[i],
+ in_max + insn_needs.input.groups[i]);
+
+ insn_needs.output.groups[i] += out_max;
+ insn_needs.other.groups[i]
+ += MAX (MAX (insn_needs.input.groups[i],
+ insn_needs.output.groups[i]),
+ insn_needs.other_addr.groups[i]);
+ }
- /* Groups of size 2 (the only groups used on most machines)
- are treated specially. */
- if (group_size[class] == 2)
- {
- /* First, look for a register that will complete a group. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int other;
-
- j = potential_reload_regs[i];
- if (j >= 0 && ! TEST_HARD_REG_BIT (bad_spill_regs, j)
- &&
- ((j > 0 && (other = j - 1, spill_reg_order[other] >= 0)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j)
- && TEST_HARD_REG_BIT (reg_class_contents[class], other)
- && HARD_REGNO_MODE_OK (other, group_mode[class])
- && ! TEST_HARD_REG_BIT (counted_for_nongroups,
- other)
- /* We don't want one part of another group.
- We could get "two groups" that overlap! */
- && ! TEST_HARD_REG_BIT (counted_for_groups, other))
- ||
- (j < FIRST_PSEUDO_REGISTER - 1
- && (other = j + 1, spill_reg_order[other] >= 0)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j)
- && TEST_HARD_REG_BIT (reg_class_contents[class], other)
- && HARD_REGNO_MODE_OK (j, group_mode[class])
- && ! TEST_HARD_REG_BIT (counted_for_nongroups,
- other)
- && ! TEST_HARD_REG_BIT (counted_for_groups,
- other))))
- {
- register enum reg_class *p;
+ /* Record the needs for later. */
+ chain->need = insn_needs.other;
+}
+
+/* Find a group of exactly 2 registers.
- /* We have found one that will complete a group,
- so count off one group as provided. */
- max_groups[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- {
- if (group_size [(int) *p] <= group_size [class])
- max_groups[(int) *p]--;
- p++;
- }
+ First try to fill out the group by spilling a single register which
+ would allow completion of the group.
- /* Indicate both these regs are part of a group. */
- SET_HARD_REG_BIT (counted_for_groups, j);
- SET_HARD_REG_BIT (counted_for_groups, other);
- break;
- }
- }
- /* We can't complete a group, so start one. */
- /* Look for a pair neither of which is explicitly used. */
- if (SMALL_REGISTER_CLASSES && i == FIRST_PSEUDO_REGISTER)
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int k;
- j = potential_reload_regs[i];
- /* Verify that J+1 is a potential reload reg. */
- for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
- if (potential_reload_regs[k] == j + 1)
- break;
- if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
- && k < FIRST_PSEUDO_REGISTER
- && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
- && TEST_HARD_REG_BIT (reg_class_contents[class], j)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
- && HARD_REGNO_MODE_OK (j, group_mode[class])
- && ! TEST_HARD_REG_BIT (counted_for_nongroups,
- j + 1)
- && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1)
- /* Reject J at this stage
- if J+1 was explicitly used. */
- && ! regs_explicitly_used[j + 1])
- break;
- }
- /* Now try any group at all
- whose registers are not in bad_spill_regs. */
- if (i == FIRST_PSEUDO_REGISTER)
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int k;
- j = potential_reload_regs[i];
- /* Verify that J+1 is a potential reload reg. */
- for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
- if (potential_reload_regs[k] == j + 1)
- break;
- if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
- && k < FIRST_PSEUDO_REGISTER
- && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
- && TEST_HARD_REG_BIT (reg_class_contents[class], j)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
- && HARD_REGNO_MODE_OK (j, group_mode[class])
- && ! TEST_HARD_REG_BIT (counted_for_nongroups,
- j + 1)
- && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1))
- break;
- }
+ Then try to create a new group from a pair of registers, neither of
+ which are explicitly used.
- /* I should be the index in potential_reload_regs
- of the new reload reg we have found. */
+ Then try to create a group from any pair of registers. */
- if (i >= FIRST_PSEUDO_REGISTER)
- {
- /* There are no groups left to spill. */
- spill_failure (max_groups_insn[class]);
- failure = 1;
- goto failed;
- }
- else
- something_changed
- |= new_spill_reg (i, class, max_needs, NULL_PTR,
- global, dumpfile);
- }
- else
- {
- /* For groups of more than 2 registers,
- look for a sufficient sequence of unspilled registers,
- and spill them all at once. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- int k;
-
- j = potential_reload_regs[i];
- if (j >= 0
- && j + group_size[class] <= FIRST_PSEUDO_REGISTER
- && HARD_REGNO_MODE_OK (j, group_mode[class]))
- {
- /* Check each reg in the sequence. */
- for (k = 0; k < group_size[class]; k++)
- if (! (spill_reg_order[j + k] < 0
- && ! TEST_HARD_REG_BIT (bad_spill_regs, j + k)
- && TEST_HARD_REG_BIT (reg_class_contents[class], j + k)))
- break;
- /* We got a full sequence, so spill them all. */
- if (k == group_size[class])
- {
- register enum reg_class *p;
- for (k = 0; k < group_size[class]; k++)
- {
- int idx;
- SET_HARD_REG_BIT (counted_for_groups, j + k);
- for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
- if (potential_reload_regs[idx] == j + k)
- break;
- something_changed
- |= new_spill_reg (idx, class,
- max_needs, NULL_PTR,
- global, dumpfile);
- }
+static void
+find_tworeg_group (chain, class, dumpfile)
+ struct insn_chain *chain;
+ int class;
+ FILE *dumpfile;
+{
+ int i;
+ /* First, look for a register that will complete a group. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ int j, other;
+
+ j = potential_reload_regs[i];
+ if (j >= 0 && ! TEST_HARD_REG_BIT (bad_spill_regs, j)
+ && ((j > 0 && (other = j - 1, spill_reg_order[other] >= 0)
+ && TEST_HARD_REG_BIT (reg_class_contents[class], j)
+ && TEST_HARD_REG_BIT (reg_class_contents[class], other)
+ && HARD_REGNO_MODE_OK (other, chain->group_mode[class])
+ && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, other)
+ /* We don't want one part of another group.
+ We could get "two groups" that overlap! */
+ && ! TEST_HARD_REG_BIT (chain->counted_for_groups, other))
+ || (j < FIRST_PSEUDO_REGISTER - 1
+ && (other = j + 1, spill_reg_order[other] >= 0)
+ && TEST_HARD_REG_BIT (reg_class_contents[class], j)
+ && TEST_HARD_REG_BIT (reg_class_contents[class], other)
+ && HARD_REGNO_MODE_OK (j, chain->group_mode[class])
+ && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, other)
+ && ! TEST_HARD_REG_BIT (chain->counted_for_groups, other))))
+ {
+ register enum reg_class *p;
- /* We have found one that will complete a group,
- so count off one group as provided. */
- max_groups[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- {
- if (group_size [(int) *p]
- <= group_size [class])
- max_groups[(int) *p]--;
- p++;
- }
- break;
- }
- }
- }
- /* We couldn't find any registers for this reload.
- Avoid going into an infinite loop. */
- if (i >= FIRST_PSEUDO_REGISTER)
- {
- /* There are no groups left. */
- spill_failure (max_groups_insn[class]);
- failure = 1;
- goto failed;
- }
- }
+ /* We have found one that will complete a group,
+ so count off one group as provided. */
+ chain->need.groups[class]--;
+ p = reg_class_superclasses[class];
+ while (*p != LIM_REG_CLASSES)
+ {
+ if (chain->group_size [(int) *p] <= chain->group_size [class])
+ chain->need.groups[(int) *p]--;
+ p++;
}
- /* Now similarly satisfy all need for single registers. */
+ /* Indicate both these regs are part of a group. */
+ SET_HARD_REG_BIT (chain->counted_for_groups, j);
+ SET_HARD_REG_BIT (chain->counted_for_groups, other);
+ break;
+ }
+ }
+ /* We can't complete a group, so start one. */
+ if (i == FIRST_PSEUDO_REGISTER)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ int j, k;
+ j = potential_reload_regs[i];
+ /* Verify that J+1 is a potential reload reg. */
+ for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
+ if (potential_reload_regs[k] == j + 1)
+ break;
+ if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
+ && k < FIRST_PSEUDO_REGISTER
+ && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
+ && TEST_HARD_REG_BIT (reg_class_contents[class], j)
+ && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
+ && HARD_REGNO_MODE_OK (j, chain->group_mode[class])
+ && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, j + 1)
+ && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1))
+ break;
+ }
- while (max_needs[class] > 0 || max_nongroups[class] > 0)
- {
- /* If we spilled enough regs, but they weren't counted
- against the non-group need, see if we can count them now.
- If so, we can avoid some actual spilling. */
- if (max_needs[class] <= 0 && max_nongroups[class] > 0)
- 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])
- && max_nongroups[class] > 0)
- {
- register enum reg_class *p;
+ /* I should be the index in potential_reload_regs
+ of the new reload reg we have found. */
- SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]);
- max_nongroups[class]--;
- p = reg_class_superclasses[class];
- while (*p != LIM_REG_CLASSES)
- max_nongroups[(int) *p++]--;
- }
- if (max_needs[class] <= 0 && max_nongroups[class] <= 0)
- break;
+ new_spill_reg (chain, i, class, 0, dumpfile);
+}
- /* Consider the potential reload regs that aren't
- yet in use as reload regs, in order of preference.
- Find the most preferred one that's in this class. */
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (potential_reload_regs[i] >= 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- potential_reload_regs[i])
- /* If this reg will not be available for groups,
- pick one that does not foreclose possible groups.
- This is a kludge, and not very general,
- but it should be sufficient to make the 386 work,
- and the problem should not occur on machines with
- more registers. */
- && (max_nongroups[class] == 0
- || possible_group_p (potential_reload_regs[i], max_groups)))
- break;
+/* Find a group of more than 2 registers.
+ Look for a sufficient sequence of unspilled registers, and spill them all
+ at once. */
- /* If we couldn't get a register, try to get one even if we
- might foreclose possible groups. This may cause problems
- later, but that's better than aborting now, since it is
- possible that we will, in fact, be able to form the needed
- group even with this allocation. */
-
- if (i >= FIRST_PSEUDO_REGISTER
- && (asm_noperands (max_needs[class] > 0
- ? max_needs_insn[class]
- : max_nongroups_insn[class])
- < 0))
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (potential_reload_regs[i] >= 0
- && TEST_HARD_REG_BIT (reg_class_contents[class],
- potential_reload_regs[i]))
- break;
+static void
+find_group (chain, class, dumpfile)
+ struct insn_chain *chain;
+ int class;
+ FILE *dumpfile;
+{
+ int i;
- /* I should be the index in potential_reload_regs
- of the new reload reg we have found. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ int j = potential_reload_regs[i];
- if (i >= FIRST_PSEUDO_REGISTER)
+ if (j >= 0
+ && j + chain->group_size[class] <= FIRST_PSEUDO_REGISTER
+ && HARD_REGNO_MODE_OK (j, chain->group_mode[class]))
+ {
+ int k;
+ /* Check each reg in the sequence. */
+ for (k = 0; k < chain->group_size[class]; k++)
+ if (! (spill_reg_order[j + k] < 0
+ && ! TEST_HARD_REG_BIT (bad_spill_regs, j + k)
+ && TEST_HARD_REG_BIT (reg_class_contents[class], j + k)))
+ break;
+ /* We got a full sequence, so spill them all. */
+ if (k == chain->group_size[class])
+ {
+ register enum reg_class *p;
+ for (k = 0; k < chain->group_size[class]; k++)
{
- /* There are no possible registers left to spill. */
- spill_failure (max_needs[class] > 0 ? max_needs_insn[class]
- : max_nongroups_insn[class]);
- failure = 1;
- goto failed;
+ int idx;
+ SET_HARD_REG_BIT (chain->counted_for_groups, j + k);
+ for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
+ if (potential_reload_regs[idx] == j + k)
+ break;
+ new_spill_reg (chain, idx, class, 0, dumpfile);
}
- else
- something_changed
- |= new_spill_reg (i, class, max_needs, max_nongroups,
- global, dumpfile);
+
+ /* We have found one that will complete a group,
+ so count off one group as provided. */
+ chain->need.groups[class]--;
+ p = reg_class_superclasses[class];
+ while (*p != LIM_REG_CLASSES)
+ {
+ if (chain->group_size [(int) *p]
+ <= chain->group_size [class])
+ chain->need.groups[(int) *p]--;
+ p++;
+ }
+ return;
}
}
}
+ /* There are no groups left. */
+ spill_failure (chain->insn);
+ failure = 1;
+}
- /* If global-alloc was run, notify it of any register eliminations we have
- done. */
- if (global)
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- if (ep->can_eliminate)
- mark_elimination (ep->from, ep->to);
+/* If pseudo REG conflicts with one of our reload registers, mark it as
+ spilled. */
+static void
+maybe_mark_pseudo_spilled (reg)
+ int reg;
+{
+ int i;
+ int r = reg_renumber[reg];
+ int nregs;
- /* Insert code to save and restore call-clobbered hard regs
- around calls. Tell if what mode to use so that we will process
- those insns in reload_as_needed if we have to. */
+ if (r < 0)
+ abort ();
+ nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
+ for (i = 0; i < n_spills; i++)
+ if (r <= spill_regs[i] && r + nregs > spill_regs[i])
+ {
+ SET_REGNO_REG_SET (spilled_pseudos, reg);
+ return;
+ }
+}
- if (caller_save_needed)
- save_call_clobbered_regs (num_eliminable ? QImode
- : caller_save_spill_class != NO_REGS ? HImode
- : VOIDmode);
+/* Find more reload regs to satisfy the remaining need of an insn, which
+ is given by CHAIN.
+ Do it by ascending class number, since otherwise a reg
+ might be spilled for a big class and might fail to count
+ for a smaller class even though it belongs to that class.
- /* If a pseudo has no hard reg, delete the insns that made the equivalence.
- If that insn didn't set the register (i.e., it copied the register to
- memory), just delete that insn instead of the equivalencing insn plus
- anything now dead. If we call delete_dead_insn on that insn, we may
- delete the insn that actually sets the register if the register die
- there and that is incorrect. */
+ Count spilled regs in `spills', and add entries to
+ `spill_regs' and `spill_reg_order'.
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0
- && GET_CODE (reg_equiv_init[i]) != NOTE)
- {
- if (reg_set_p (regno_reg_rtx[i], PATTERN (reg_equiv_init[i])))
- delete_dead_insn (reg_equiv_init[i]);
- else
- {
- PUT_CODE (reg_equiv_init[i], NOTE);
- NOTE_SOURCE_FILE (reg_equiv_init[i]) = 0;
- NOTE_LINE_NUMBER (reg_equiv_init[i]) = NOTE_INSN_DELETED;
- }
- }
+ ??? Note there is a problem here.
+ When there is a need for a group in a high-numbered class,
+ and also need for non-group regs that come from a lower class,
+ the non-group regs are chosen first. If there aren't many regs,
+ they might leave no room for a group.
- /* Use the reload registers where necessary
- by generating move instructions to move the must-be-register
- values into or out of the reload registers. */
+ This was happening on the 386. To fix it, we added the code
+ that calls possible_group_p, so that the lower class won't
+ break up the last possible group.
- if (something_needs_reloads || something_needs_elimination
- || (caller_save_needed && num_eliminable)
- || caller_save_spill_class != NO_REGS)
- reload_as_needed (first, global);
+ Really fixing the problem would require changes above
+ in counting the regs already spilled, and in choose_reload_regs.
+ It might be hard to avoid introducing bugs there. */
- /* If we were able to eliminate the frame pointer, show that it is no
- longer live at the start of any basic block. If it ls live by
- virtue of being in a pseudo, that pseudo will be marked live
- and hence the frame pointer will be known to be live via that
- pseudo. */
+static void
+find_reload_regs (chain, dumpfile)
+ struct insn_chain *chain;
+ FILE *dumpfile;
+{
+ int i, class;
+ short *group_needs = chain->need.groups;
+ short *simple_needs = chain->need.regs[0];
+ short *nongroup_needs = chain->need.regs[1];
- if (! frame_pointer_needed)
- for (i = 0; i < n_basic_blocks; i++)
- CLEAR_REGNO_REG_SET (basic_block_live_at_start[i],
- HARD_FRAME_POINTER_REGNUM);
+ if (dumpfile)
+ fprintf (dumpfile, "Spilling for insn %d.\n", INSN_UID (chain->insn));
- /* Come here (with failure set nonzero) if we can't get enough spill regs
- and we decide not to abort about it. */
- failed:
+ /* Compute the order of preference for hard registers to spill.
+ Store them by decreasing preference in potential_reload_regs. */
- reload_in_progress = 0;
+ order_regs_for_reload (chain);
- /* Now eliminate all pseudo regs by modifying them into
- their equivalent memory references.
- The REG-rtx's for the pseudos are modified in place,
- so all insns that used to refer to them now refer to memory.
+ /* So far, no hard regs have been spilled. */
+ n_spills = 0;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ spill_reg_order[i] = -1;
- For a reg that has a reg_equiv_address, all those insns
- were changed by reloading so that no insns refer to it any longer;
- but the DECL_RTL of a variable decl may refer to it,
- and if so this causes the debugging info to mention the variable. */
+ CLEAR_HARD_REG_SET (chain->used_spill_regs);
+ CLEAR_HARD_REG_SET (chain->counted_for_groups);
+ CLEAR_HARD_REG_SET (chain->counted_for_nongroups);
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ for (class = 0; class < N_REG_CLASSES; class++)
{
- rtx addr = 0;
- int in_struct = 0;
- int is_readonly = 0;
-
- if (reg_equiv_memory_loc[i])
+ /* First get the groups of registers.
+ If we got single registers first, we might fragment
+ possible groups. */
+ while (group_needs[class] > 0)
{
- in_struct = MEM_IN_STRUCT_P (reg_equiv_memory_loc[i]);
- is_readonly = RTX_UNCHANGING_P (reg_equiv_memory_loc[i]);
- }
+ /* If any single spilled regs happen to form groups,
+ count them now. Maybe we don't really need
+ to spill another group. */
+ count_possible_groups (chain, class);
- if (reg_equiv_mem[i])
- addr = XEXP (reg_equiv_mem[i], 0);
+ if (group_needs[class] <= 0)
+ break;
- if (reg_equiv_address[i])
- addr = reg_equiv_address[i];
+ /* Groups of size 2, the only groups used on most machines,
+ are treated specially. */
+ if (chain->group_size[class] == 2)
+ find_tworeg_group (chain, class, dumpfile);
+ else
+ find_group (chain, class, dumpfile);
+ if (failure)
+ return;
+ }
- if (addr)
+ /* Now similarly satisfy all need for single registers. */
+
+ while (simple_needs[class] > 0 || nongroup_needs[class] > 0)
{
- if (reg_renumber[i] < 0)
- {
- rtx reg = regno_reg_rtx[i];
- XEXP (reg, 0) = addr;
- REG_USERVAR_P (reg) = 0;
- RTX_UNCHANGING_P (reg) = is_readonly;
- MEM_IN_STRUCT_P (reg) = in_struct;
- /* We have no alias information about this newly created
- MEM. */
- MEM_ALIAS_SET (reg) = 0;
- PUT_CODE (reg, MEM);
- }
- else if (reg_equiv_mem[i])
- XEXP (reg_equiv_mem[i], 0) = addr;
- }
- }
+ /* If we spilled enough regs, but they weren't counted
+ against the non-group need, see if we can count them now.
+ If so, we can avoid some actual spilling. */
+ if (simple_needs[class] <= 0 && nongroup_needs[class] > 0)
+ for (i = 0; i < n_spills; i++)
+ {
+ int regno = spill_regs[i];
+ if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+ && !TEST_HARD_REG_BIT (chain->counted_for_groups, regno)
+ && !TEST_HARD_REG_BIT (chain->counted_for_nongroups, regno)
+ && nongroup_needs[class] > 0)
+ {
+ register enum reg_class *p;
- /* Make a pass over all the insns and delete all USEs which we inserted
- only to tag a REG_EQUAL note on them; if PRESERVE_DEATH_INFO_REGNO_P
- is defined, also remove death notes for things that are no longer
- registers or no longer die in the insn (e.g., an input and output
- pseudo being tied). */
+ SET_HARD_REG_BIT (chain->counted_for_nongroups, regno);
+ nongroup_needs[class]--;
+ p = reg_class_superclasses[class];
+ while (*p != LIM_REG_CLASSES)
+ nongroup_needs[(int) *p++]--;
+ }
+ }
- for (insn = first; insn; insn = NEXT_INSN (insn))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- {
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- rtx note, next;
-#endif
+ if (simple_needs[class] <= 0 && nongroup_needs[class] <= 0)
+ break;
- if (GET_CODE (PATTERN (insn)) == USE
- && find_reg_note (insn, REG_EQUAL, NULL_RTX))
- {
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- continue;
- }
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- for (note = REG_NOTES (insn); note; note = next)
- {
- next = XEXP (note, 1);
- if (REG_NOTE_KIND (note) == REG_DEAD
- && (GET_CODE (XEXP (note, 0)) != REG
- || reg_set_p (XEXP (note, 0), PATTERN (insn))))
- remove_note (insn, note);
- }
-#endif
- }
+ /* Consider the potential reload regs that aren't
+ yet in use as reload regs, in order of preference.
+ Find the most preferred one that's in this class. */
- /* If we are doing stack checking, give a warning if this function's
- frame size is larger than we expect. */
- if (flag_stack_check && ! STACK_CHECK_BUILTIN)
- {
- HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ int regno = potential_reload_regs[i];
+ if (regno >= 0
+ && TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+ /* If this reg will not be available for groups,
+ pick one that does not foreclose possible groups.
+ This is a kludge, and not very general,
+ but it should be sufficient to make the 386 work,
+ and the problem should not occur on machines with
+ more registers. */
+ && (nongroup_needs[class] == 0
+ || possible_group_p (chain, regno)))
+ break;
+ }
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (regs_ever_live[i] && ! fixed_regs[i] && call_used_regs[i])
- size += UNITS_PER_WORD;
+ /* If we couldn't get a register, try to get one even if we
+ might foreclose possible groups. This may cause problems
+ later, but that's better than aborting now, since it is
+ possible that we will, in fact, be able to form the needed
+ group even with this allocation. */
+
+ if (i >= FIRST_PSEUDO_REGISTER
+ && asm_noperands (chain->insn) < 0)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (potential_reload_regs[i] >= 0
+ && TEST_HARD_REG_BIT (reg_class_contents[class],
+ potential_reload_regs[i]))
+ break;
- if (size > STACK_CHECK_MAX_FRAME_SIZE)
- warning ("frame size too large for reliable stack checking");
- }
-
- /* Indicate that we no longer have known memory locations or constants. */
- reg_equiv_constant = 0;
- reg_equiv_memory_loc = 0;
+ /* I should be the index in potential_reload_regs
+ of the new reload reg we have found. */
- if (real_known_ptr)
- free (real_known_ptr);
- if (real_at_ptr)
- free (real_at_ptr);
+ new_spill_reg (chain, i, class, 1, dumpfile);
+ if (failure)
+ return;
+ }
+ }
+
+ /* We know which hard regs to use, now mark the pseudos that live in them
+ as needing to be kicked out. */
+ EXECUTE_IF_SET_IN_REG_SET
+ (chain->live_before, FIRST_PSEUDO_REGISTER, i,
+ {
+ maybe_mark_pseudo_spilled (i);
+ });
+ EXECUTE_IF_SET_IN_REG_SET
+ (chain->live_after, FIRST_PSEUDO_REGISTER, i,
+ {
+ maybe_mark_pseudo_spilled (i);
+ });
+
+ IOR_HARD_REG_SET (used_spill_regs, chain->used_spill_regs);
+}
- if (scratch_list)
- free (scratch_list);
- scratch_list = 0;
- if (scratch_block)
- free (scratch_block);
- scratch_block = 0;
+void
+dump_needs (chain, dumpfile)
+ struct insn_chain *chain;
+ FILE *dumpfile;
+{
+ static char *reg_class_names[] = REG_CLASS_NAMES;
+ int i;
+ struct needs *n = &chain->need;
- CLEAR_HARD_REG_SET (used_spill_regs);
- for (i = 0; i < n_spills; i++)
- SET_HARD_REG_BIT (used_spill_regs, spill_regs[i]);
+ for (i = 0; i < N_REG_CLASSES; i++)
+ {
+ if (n->regs[i][0] > 0)
+ fprintf (dumpfile,
+ ";; Need %d reg%s of class %s.\n",
+ n->regs[i][0], n->regs[i][0] == 1 ? "" : "s",
+ reg_class_names[i]);
+ if (n->regs[i][1] > 0)
+ fprintf (dumpfile,
+ ";; Need %d nongroup reg%s of class %s.\n",
+ n->regs[i][1], n->regs[i][1] == 1 ? "" : "s",
+ reg_class_names[i]);
+ if (n->groups[i] > 0)
+ fprintf (dumpfile,
+ ";; Need %d group%s (%smode) of class %s.\n",
+ n->groups[i], n->groups[i] == 1 ? "" : "s",
+ mode_name[(int) chain->group_mode[i]],
+ reg_class_names[i]);
+ }
+}
+
+/* Delete all insns that were inserted by emit_caller_save_insns during
+ this iteration. */
+static void
+delete_caller_save_insns ()
+{
+ struct insn_chain *c = reload_insn_chain;
- return failure;
+ while (c != 0)
+ {
+ while (c != 0 && c->is_caller_save_insn)
+ {
+ struct insn_chain *next = c->next;
+ rtx insn = c->insn;
+
+ if (insn == BLOCK_HEAD (c->block))
+ BLOCK_HEAD (c->block) = NEXT_INSN (insn);
+ if (insn == BLOCK_END (c->block))
+ BLOCK_END (c->block) = PREV_INSN (insn);
+ if (c == reload_insn_chain)
+ reload_insn_chain = next;
+
+ if (NEXT_INSN (insn) != 0)
+ PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
+ if (PREV_INSN (insn) != 0)
+ NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
+
+ if (next)
+ next->prev = c->prev;
+ if (c->prev)
+ c->prev->next = next;
+ c->next = unused_insn_chains;
+ unused_insn_chains = c;
+ c = next;
+ }
+ if (c != 0)
+ c = c->next;
+ }
}
/* Nonzero if, after spilling reg REGNO for non-groups,
it will still be possible to find a group if we still need one. */
static int
-possible_group_p (regno, max_groups)
+possible_group_p (chain, regno)
+ struct insn_chain *chain;
int regno;
- int *max_groups;
{
int i;
int class = (int) NO_REGS;
for (i = 0; i < (int) N_REG_CLASSES; i++)
- if (max_groups[i] > 0)
+ if (chain->need.groups[i] > 0)
{
class = i;
break;
@@ -2230,28 +2144,26 @@ possible_group_p (regno, max_groups)
if (spill_reg_order[i] < 0
&& ! TEST_HARD_REG_BIT (bad_spill_regs, i)
&& spill_reg_order[i + 1] >= 0
- && ! TEST_HARD_REG_BIT (counted_for_groups, i + 1)
- && ! TEST_HARD_REG_BIT (counted_for_nongroups, i + 1))
+ && ! TEST_HARD_REG_BIT (chain->counted_for_groups, i + 1)
+ && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, i + 1))
return 1;
if (spill_reg_order[i + 1] < 0
&& ! TEST_HARD_REG_BIT (bad_spill_regs, i + 1)
&& spill_reg_order[i] >= 0
- && ! TEST_HARD_REG_BIT (counted_for_groups, i)
- && ! TEST_HARD_REG_BIT (counted_for_nongroups, i))
+ && ! TEST_HARD_REG_BIT (chain->counted_for_groups, i)
+ && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, i))
return 1;
}
return 0;
}
-
+
/* Count any groups of CLASS that can be formed from the registers recently
spilled. */
static void
-count_possible_groups (group_size, group_mode, max_groups, class)
- int *group_size;
- enum machine_mode *group_mode;
- int *max_groups;
+count_possible_groups (chain, class)
+ struct insn_chain *chain;
int class;
{
HARD_REG_SET new;
@@ -2261,46 +2173,50 @@ count_possible_groups (group_size, group_mode, max_groups, class)
and mark each group off against the need for such groups.
But don't count them against ordinary need, yet. */
- if (group_size[class] == 0)
+ if (chain->group_size[class] == 0)
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]);
+ {
+ int regno = spill_regs[i];
+
+ if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+ && ! TEST_HARD_REG_BIT (chain->counted_for_groups, regno)
+ && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regno))
+ SET_HARD_REG_BIT (new, regno);
+ }
/* Find each consecutive group of them. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER && max_groups[class] > 0; i++)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER && chain->need.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]))
+ && i + chain->group_size[class] <= FIRST_PSEUDO_REGISTER
+ && HARD_REGNO_MODE_OK (i, chain->group_mode[class]))
{
- for (j = 1; j < group_size[class]; j++)
+ for (j = 1; j < chain->group_size[class]; j++)
if (! TEST_HARD_REG_BIT (new, i + j))
break;
- if (j == group_size[class])
+ if (j == chain->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;
- max_groups[class]--;
+ chain->need.groups[class]--;
p = reg_class_superclasses[class];
while (*p != LIM_REG_CLASSES)
{
- if (group_size [(int) *p] <= group_size [class])
- max_groups[(int) *p]--;
+ if (chain->group_size [(int) *p] <= chain->group_size [class])
+ chain->need.groups[(int) *p]--;
p++;
}
/* Don't count these registers again. */
- for (j = 0; j < group_size[class]; j++)
- SET_HARD_REG_BIT (counted_for_groups, i + j);
+ for (j = 0; j < chain->group_size[class]; j++)
+ SET_HARD_REG_BIT (chain->counted_for_groups, i + j);
}
/* Skip to the last reg in this group. When i is incremented above,
@@ -2336,7 +2252,7 @@ modes_equiv_for_class_p (allocate_mode, other_mode, class)
}
return 1;
}
-
+
/* Handle the failure to find a register to spill.
INSN should be one of the insns which needed this particular spill reg. */
@@ -2350,37 +2266,53 @@ spill_failure (insn)
fatal_insn ("Unable to find a register to spill.", insn);
}
-/* Add a new register to the tables of available spill-registers
- (as well as spilling all pseudos allocated to the register).
+/* Add a new register to the tables of available spill-registers.
+ CHAIN is the insn for which the register will be used; we decrease the
+ needs of that insn.
I is the index of this register in potential_reload_regs.
CLASS is the regclass whose need is being satisfied.
- MAX_NEEDS and MAX_NONGROUPS are the vectors of needs,
- so that this register can count off against them.
- MAX_NONGROUPS is 0 if this register is part of a group.
- GLOBAL and DUMPFILE are the same as the args that `reload' got. */
+ NONGROUP is 0 if this register is part of a group.
+ DUMPFILE is the same as the one that `reload' got. */
-static int
-new_spill_reg (i, class, max_needs, max_nongroups, global, dumpfile)
+static void
+new_spill_reg (chain, i, class, nongroup, dumpfile)
+ struct insn_chain *chain;
int i;
int class;
- int *max_needs;
- int *max_nongroups;
- int global;
+ int nongroup;
FILE *dumpfile;
{
register enum reg_class *p;
- int val;
int regno = potential_reload_regs[i];
if (i >= FIRST_PSEUDO_REGISTER)
- abort (); /* Caller failed to find any register. */
+ {
+ spill_failure (chain->insn);
+ failure = 1;
+ return;
+ }
- if (fixed_regs[regno] || TEST_HARD_REG_BIT (forbidden_regs, regno))
+ if (TEST_HARD_REG_BIT (bad_spill_regs, regno))
{
static char *reg_class_names[] = REG_CLASS_NAMES;
- fatal ("fixed or forbidden register %d (%s) was spilled for class %s.\n\
-This may be due to a compiler bug or to impossible asm\n\
-statements or clauses.", regno, reg_names[regno], reg_class_names[class]);
+
+ if (asm_noperands (PATTERN (chain->insn)) < 0)
+ {
+ /* The error message is still correct - we know only that it wasn't
+ an asm statement that caused the problem, but one of the global
+ registers declared by the users might have screwed us. */
+ error ("fixed or forbidden register %d (%s) was spilled for class %s.",
+ regno, reg_names[regno], reg_class_names[class]);
+ error ("This may be due to a compiler bug or to impossible asm");
+ error ("statements or clauses.");
+ fatal_insn ("This is the instruction:", chain->insn);
+ }
+ error_for_asm (chain->insn, "Invalid `asm' statement:");
+ error_for_asm (chain->insn,
+ "fixed or forbidden register %d (%s) was spilled for class %s.",
+ regno, reg_names[regno], reg_class_names[class]);
+ failure = 1;
+ return;
}
/* Make reg REGNO an additional reload reg. */
@@ -2389,49 +2321,26 @@ statements or clauses.", regno, reg_names[regno], reg_class_names[class]);
spill_regs[n_spills] = regno;
spill_reg_order[regno] = n_spills;
if (dumpfile)
- fprintf (dumpfile, "Spilling reg %d.\n", spill_regs[n_spills]);
+ fprintf (dumpfile, "Spilling reg %d.\n", regno);
+ SET_HARD_REG_BIT (chain->used_spill_regs, regno);
/* Clear off the needs we just satisfied. */
- max_needs[class]--;
+ chain->need.regs[0][class]--;
p = reg_class_superclasses[class];
while (*p != LIM_REG_CLASSES)
- max_needs[(int) *p++]--;
+ chain->need.regs[0][(int) *p++]--;
- if (max_nongroups && max_nongroups[class] > 0)
+ if (nongroup && chain->need.regs[1][class] > 0)
{
- SET_HARD_REG_BIT (counted_for_nongroups, regno);
- max_nongroups[class]--;
+ SET_HARD_REG_BIT (chain->counted_for_nongroups, regno);
+ chain->need.regs[1][class]--;
p = reg_class_superclasses[class];
while (*p != LIM_REG_CLASSES)
- max_nongroups[(int) *p++]--;
+ chain->need.regs[1][(int) *p++]--;
}
- /* Spill every pseudo reg that was allocated to this reg
- or to something that overlaps this reg. */
-
- val = spill_hard_reg (spill_regs[n_spills], global, dumpfile, 0);
-
- /* If there are some registers still to eliminate and this register
- wasn't ever used before, additional stack space may have to be
- allocated to store this register. Thus, we may have changed the offset
- between the stack and frame pointers, so mark that something has changed.
- (If new pseudos were spilled, thus requiring more space, VAL would have
- been set non-zero by the call to spill_hard_reg above since additional
- reloads may be needed in that case.
-
- One might think that we need only set VAL to 1 if this is a call-used
- register. However, the set of registers that must be saved by the
- prologue is not identical to the call-used set. For example, the
- register used by the call insn for the return PC is a call-used register,
- but must be saved by the prologue. */
- if (num_eliminable && ! regs_ever_live[spill_regs[n_spills]])
- val = 1;
-
- regs_ever_live[spill_regs[n_spills]] = 1;
n_spills++;
-
- return val;
}
/* Delete an unneeded INSN and any previous insns who sole purpose is loading
@@ -2604,20 +2513,6 @@ mark_home_live (regno)
while (i < lim)
regs_ever_live[i++] = 1;
}
-
-/* Mark the registers used in SCRATCH as being live. */
-
-static void
-mark_scratch_live (scratch)
- rtx scratch;
-{
- register int i;
- int regno = REGNO (scratch);
- int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (scratch));
-
- for (i = regno; i < lim; i++)
- regs_ever_live[i] = 1;
-}
/* This function handles the tracking of elimination offsets around branches.
@@ -2637,7 +2532,7 @@ set_label_offsets (x, insn, initial_p)
{
enum rtx_code code = GET_CODE (x);
rtx tem;
- int i;
+ unsigned int i;
struct elim_table *p;
switch (code)
@@ -2674,19 +2569,7 @@ set_label_offsets (x, insn, initial_p)
else if (x == insn
&& (tem = prev_nonnote_insn (insn)) != 0
&& GET_CODE (tem) == BARRIER)
- {
- num_not_at_initial_offset = 0;
- for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- {
- reg_eliminate[i].offset = reg_eliminate[i].previous_offset
- = offsets_at[CODE_LABEL_NUMBER (x)][i];
- if (reg_eliminate[i].can_eliminate
- && (reg_eliminate[i].offset
- != reg_eliminate[i].initial_offset))
- num_not_at_initial_offset++;
- }
- }
-
+ set_offsets_for_label (insn);
else
/* If neither of the above cases is true, compare each offset
with those previously recorded and suppress any eliminations
@@ -2720,7 +2603,7 @@ set_label_offsets (x, insn, initial_p)
offsets. We want the first field for ADDR_VEC and the second
field for ADDR_DIFF_VEC. */
- for (i = 0; i < XVECLEN (x, code == ADDR_DIFF_VEC); i++)
+ for (i = 0; i < (unsigned) XVECLEN (x, code == ADDR_DIFF_VEC); i++)
set_label_offsets (XVECEXP (x, code == ADDR_DIFF_VEC, i),
insn, initial_p);
return;
@@ -2828,6 +2711,9 @@ eliminate_regs (x, mem_mode, insn)
char *fmt;
int copied = 0;
+ if (! current_function_decl)
+ return x;
+
switch (code)
{
case CONST_INT:
@@ -2872,27 +2758,11 @@ eliminate_regs (x, mem_mode, insn)
}
}
- else if (reg_equiv_memory_loc && reg_equiv_memory_loc[regno]
- && (reg_equiv_address[regno] || num_not_at_initial_offset))
- {
- /* In this case, find_reloads would attempt to either use an
- incorrect address (if something is not at its initial offset)
- or substitute an replaced address into an insn (which loses
- if the offset is changed by some later action). So we simply
- return the replaced stack slot (assuming it is changed by
- elimination) and ignore the fact that this is actually a
- reference to the pseudo. Ensure we make a copy of the
- address in case it is shared. */
- new = eliminate_regs (reg_equiv_memory_loc[regno], mem_mode, insn);
- if (new != reg_equiv_memory_loc[regno])
- {
- if (insn != 0 && GET_CODE (insn) != EXPR_LIST
- && GET_CODE (insn) != INSN_LIST)
- REG_NOTES (emit_insn_before (gen_rtx_USE (VOIDmode, x), insn))
- = gen_rtx_EXPR_LIST (REG_EQUAL, new, NULL_RTX);
- return copy_rtx (new);
- }
- }
+ else if (reg_renumber[regno] < 0 && reg_equiv_constant
+ && reg_equiv_constant[regno]
+ && ! CONSTANT_P (reg_equiv_constant[regno]))
+ return eliminate_regs (copy_rtx (reg_equiv_constant[regno]),
+ mem_mode, insn);
return x;
case PLUS:
@@ -3035,7 +2905,17 @@ eliminate_regs (x, mem_mode, insn)
{
new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
if (new != XEXP (x, 0))
- x = gen_rtx_EXPR_LIST (REG_NOTE_KIND (x), new, XEXP (x, 1));
+ {
+ /* If this is a REG_DEAD note, it is not valid anymore.
+ Using the eliminated version could result in creating a
+ REG_DEAD note for the stack or frame pointer. */
+ if (GET_MODE (x) == REG_DEAD)
+ return (XEXP (x, 1)
+ ? eliminate_regs (XEXP (x, 1), mem_mode, insn)
+ : NULL_RTX);
+
+ x = gen_rtx_EXPR_LIST (REG_NOTE_KIND (x), new, XEXP (x, 1));
+ }
}
/* ... fall through ... */
@@ -3100,6 +2980,7 @@ eliminate_regs (x, mem_mode, insn)
&& reg_equiv_memory_loc != 0
&& reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
{
+#if 0
new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))],
mem_mode, insn);
@@ -3120,6 +3001,9 @@ eliminate_regs (x, mem_mode, insn)
/* Ensure NEW isn't shared in case we have to reload it. */
new = copy_rtx (new);
}
+#else
+ new = SUBREG_REG (x);
+#endif
}
else
new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
@@ -3410,7 +3294,7 @@ eliminate_regs_in_insn (insn, replace)
&& ep->to == HARD_FRAME_POINTER_REGNUM)
{
rtx src = SET_SRC (old_set);
- int offset, ok = 0;
+ int offset = 0, ok = 0;
rtx prev_insn, prev_set;
if (src == ep->to_rtx)
@@ -3482,7 +3366,7 @@ eliminate_regs_in_insn (insn, replace)
in the insn is the negative of the offset in FROM. Substitute
(set (reg) (reg to)) for the insn and change its code.
- We have to do this here, rather than in eliminate_regs, do that we can
+ We have to do this here, rather than in eliminate_regs, so that we can
change the insn code. */
if (GET_CODE (SET_SRC (old_set)) == PLUS
@@ -3569,11 +3453,7 @@ eliminate_regs_in_insn (insn, replace)
val = 1;
}
- /* Loop through all elimination pairs. See if any have changed and
- recalculate the number not at initial offset.
-
- Compute the maximum offset (minimum offset if the stack does not
- grow downward) for each elimination pair.
+ /* Loop through all elimination pairs. See if any have changed.
We also detect a cases where register elimination cannot be done,
namely, if a register would be both changed and referenced outside a MEM
@@ -3584,7 +3464,6 @@ eliminate_regs_in_insn (insn, replace)
If anything changes, return nonzero. */
- num_not_at_initial_offset = 0;
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
{
if (ep->previous_offset != ep->offset && ep->ref_outside_mem)
@@ -3594,16 +3473,6 @@ eliminate_regs_in_insn (insn, replace)
if (ep->previous_offset != ep->offset)
val = 1;
-
- ep->previous_offset = ep->offset;
- if (ep->can_eliminate && ep->offset != ep->initial_offset)
- num_not_at_initial_offset++;
-
-#ifdef STACK_GROWS_DOWNWARD
- ep->max_offset = MAX (ep->max_offset, ep->offset);
-#else
- ep->max_offset = MIN (ep->max_offset, ep->offset);
-#endif
}
done:
@@ -3621,6 +3490,26 @@ eliminate_regs_in_insn (insn, replace)
return val;
}
+/* Loop through all elimination pairs.
+ Recalculate the number not at initial offset.
+
+ Compute the maximum offset (minimum offset if the stack does not
+ grow downward) for each elimination pair. */
+
+static void
+update_eliminable_offsets ()
+{
+ struct elim_table *ep;
+
+ num_not_at_initial_offset = 0;
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ {
+ ep->previous_offset = ep->offset;
+ if (ep->can_eliminate && ep->offset != ep->initial_offset)
+ num_not_at_initial_offset++;
+ }
+}
+
/* Given X, a SET or CLOBBER of DEST, if DEST is the target of a register
replacement we currently believe is valid, mark it as not eliminable if X
modifies DEST in any way other than by adding a constant integer to it.
@@ -3640,7 +3529,7 @@ mark_not_eliminable (dest, x)
rtx dest;
rtx x;
{
- register int i;
+ register unsigned int i;
/* A SUBREG of a hard register here is just changing its mode. We should
not see a SUBREG of an eliminable hard register, but check just in
@@ -3663,9 +3552,237 @@ mark_not_eliminable (dest, x)
num_eliminable--;
}
}
+
+/* Verify that the initial elimination offsets did not change since the
+ last call to set_initial_elim_offsets. This is used to catch cases
+ where something illegal happened during reload_as_needed that could
+ cause incorrect code to be generated if we did not check for it. */
+static void
+verify_initial_elim_offsets ()
+{
+ int t;
+
+#ifdef ELIMINABLE_REGS
+ struct elim_table *ep;
+
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ {
+ INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, t);
+ if (t != ep->initial_offset)
+ abort ();
+ }
+#else
+ INITIAL_FRAME_POINTER_OFFSET (t);
+ if (t != reg_eliminate[0].initial_offset)
+ abort ();
+#endif
+}
+
+/* Reset all offsets on eliminable registers to their initial values. */
+static void
+set_initial_elim_offsets ()
+{
+ struct elim_table *ep = reg_eliminate;
+
+#ifdef ELIMINABLE_REGS
+ for (; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ {
+ INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset);
+ ep->previous_offset = ep->offset = ep->initial_offset;
+ }
+#else
+ INITIAL_FRAME_POINTER_OFFSET (ep->initial_offset);
+ ep->previous_offset = ep->offset = ep->initial_offset;
+#endif
+
+ num_not_at_initial_offset = 0;
+}
+
+/* Initialize the known label offsets.
+ Set a known offset for each forced label to be at the initial offset
+ of each elimination. We do this because we assume that all
+ computed jumps occur from a location where each elimination is
+ at its initial offset.
+ For all other labels, show that we don't know the offsets. */
+
+static void
+set_initial_label_offsets ()
+{
+ rtx x;
+ bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels);
+
+ for (x = forced_labels; x; x = XEXP (x, 1))
+ if (XEXP (x, 0))
+ set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+}
+
+/* Set all elimination offsets to the known values for the code label given
+ by INSN. */
+static void
+set_offsets_for_label (insn)
+ rtx insn;
+{
+ unsigned int i;
+ int label_nr = CODE_LABEL_NUMBER (insn);
+ struct elim_table *ep;
+
+ num_not_at_initial_offset = 0;
+ for (i = 0, ep = reg_eliminate; i < NUM_ELIMINABLE_REGS; ep++, i++)
+ {
+ ep->offset = ep->previous_offset = offsets_at[label_nr][i];
+ if (ep->can_eliminate && ep->offset != ep->initial_offset)
+ num_not_at_initial_offset++;
+ }
+}
+
+/* See if anything that happened changes which eliminations are valid.
+ For example, on the Sparc, whether or not the frame pointer can
+ be eliminated can depend on what registers have been used. We need
+ not check some conditions again (such as flag_omit_frame_pointer)
+ since they can't have changed. */
+
+static void
+update_eliminables (pset)
+ HARD_REG_SET *pset;
+{
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ int previous_frame_pointer_needed = frame_pointer_needed;
+#endif
+ struct elim_table *ep;
+
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)
+#ifdef ELIMINABLE_REGS
+ || ! CAN_ELIMINATE (ep->from, ep->to)
+#endif
+ )
+ ep->can_eliminate = 0;
+
+ /* Look for the case where we have discovered that we can't replace
+ register A with register B and that means that we will now be
+ trying to replace register A with register C. This means we can
+ no longer replace register C with register B and we need to disable
+ such an elimination, if it exists. This occurs often with A == ap,
+ B == sp, and C == fp. */
+
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ {
+ struct elim_table *op;
+ register int new_to = -1;
+
+ if (! ep->can_eliminate && ep->can_eliminate_previous)
+ {
+ /* Find the current elimination for ep->from, if there is a
+ new one. */
+ for (op = reg_eliminate;
+ op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
+ if (op->from == ep->from && op->can_eliminate)
+ {
+ new_to = op->to;
+ break;
+ }
+
+ /* See if there is an elimination of NEW_TO -> EP->TO. If so,
+ disable it. */
+ for (op = reg_eliminate;
+ op < &reg_eliminate[NUM_ELIMINABLE_REGS]; op++)
+ if (op->from == new_to && op->to == ep->to)
+ op->can_eliminate = 0;
+ }
+ }
+
+ /* See if any registers that we thought we could eliminate the previous
+ time are no longer eliminable. If so, something has changed and we
+ must spill the register. Also, recompute the number of eliminable
+ registers and see if the frame pointer is needed; it is if there is
+ no elimination of the frame pointer that we can perform. */
+
+ frame_pointer_needed = 1;
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ {
+ if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM
+ && ep->to != HARD_FRAME_POINTER_REGNUM)
+ frame_pointer_needed = 0;
+
+ if (! ep->can_eliminate && ep->can_eliminate_previous)
+ {
+ ep->can_eliminate_previous = 0;
+ SET_HARD_REG_BIT (*pset, ep->from);
+ num_eliminable--;
+ }
+ }
+
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ /* If we didn't need a frame pointer last time, but we do now, spill
+ the hard frame pointer. */
+ if (frame_pointer_needed && ! previous_frame_pointer_needed)
+ SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
+#endif
+}
+
+/* Initialize the table of registers to eliminate. */
+static void
+init_elim_table ()
+{
+ struct elim_table *ep;
+#ifdef ELIMINABLE_REGS
+ struct elim_table_1 *ep1;
+#endif
+
+ if (!reg_eliminate)
+ {
+ reg_eliminate = (struct elim_table *)
+ xmalloc(sizeof(struct elim_table) * NUM_ELIMINABLE_REGS);
+ bzero ((PTR) reg_eliminate,
+ sizeof(struct elim_table) * NUM_ELIMINABLE_REGS);
+ }
+
+ /* Does this function require a frame pointer? */
+
+ frame_pointer_needed = (! flag_omit_frame_pointer
+#ifdef EXIT_IGNORE_STACK
+ /* ?? If EXIT_IGNORE_STACK is set, we will not save
+ and restore sp for alloca. So we can't eliminate
+ the frame pointer in that case. At some point,
+ we should improve this by emitting the
+ sp-adjusting insns for this case. */
+ || (current_function_calls_alloca
+ && EXIT_IGNORE_STACK)
+#endif
+ || FRAME_POINTER_REQUIRED);
+
+ num_eliminable = 0;
+
+#ifdef ELIMINABLE_REGS
+ for (ep = reg_eliminate, ep1 = reg_eliminate_1;
+ ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
+ {
+ ep->from = ep1->from;
+ ep->to = ep1->to;
+ ep->can_eliminate = ep->can_eliminate_previous
+ = (CAN_ELIMINATE (ep->from, ep->to)
+ && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed));
+ }
+#else
+ reg_eliminate[0].from = reg_eliminate_1[0].from;
+ reg_eliminate[0].to = reg_eliminate_1[0].to;
+ reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous
+ = ! frame_pointer_needed;
+#endif
+
+ /* Count the number of eliminable registers and build the FROM and TO
+ REG rtx's. Note that code in gen_rtx will cause, e.g.,
+ gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
+ We depend on this. */
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ {
+ num_eliminable += ep->can_eliminate;
+ ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
+ ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
+ }
+}
/* Kick all pseudos out of hard register REGNO.
- If GLOBAL is nonzero, try to find someplace else to put them.
If DUMPFILE is nonzero, log actions taken on that file.
If CANT_ELIMINATE is nonzero, it means that we are doing this spill
@@ -3676,21 +3793,19 @@ mark_not_eliminable (dest, x)
Return nonzero if any pseudos needed to be kicked out. */
-static int
-spill_hard_reg (regno, global, dumpfile, cant_eliminate)
+static void
+spill_hard_reg (regno, dumpfile, cant_eliminate)
register int regno;
- int global;
FILE *dumpfile;
int cant_eliminate;
{
- enum reg_class class = REGNO_REG_CLASS (regno);
- int something_changed = 0;
register int i;
- SET_HARD_REG_BIT (forbidden_regs, regno);
-
if (cant_eliminate)
- regs_ever_live[regno] = 1;
+ {
+ SET_HARD_REG_BIT (bad_spill_regs_global, regno);
+ regs_ever_live[regno] = 1;
+ }
/* Spill every pseudo reg that was allocated to this reg
or to something that overlaps this reg. */
@@ -3702,70 +3817,163 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
+ HARD_REGNO_NREGS (reg_renumber[i],
PSEUDO_REGNO_MODE (i))
> regno))
- {
- /* If this register belongs solely to a basic block which needed no
- spilling of any class that this register is contained in,
- leave it be, unless we are spilling this register because
- it was a hard register that can't be eliminated. */
-
- if (! cant_eliminate
- && basic_block_needs[0]
- && REG_BASIC_BLOCK (i) >= 0
- && basic_block_needs[(int) class][REG_BASIC_BLOCK (i)] == 0)
- {
- enum reg_class *p;
+ SET_REGNO_REG_SET (spilled_pseudos, i);
+}
- for (p = reg_class_superclasses[(int) class];
- *p != LIM_REG_CLASSES; p++)
- if (basic_block_needs[(int) *p][REG_BASIC_BLOCK (i)] > 0)
- break;
+/* I'm getting weird preprocessor errors if I use IOR_HARD_REG_SET
+ from within EXECUTE_IF_SET_IN_REG_SET. Hence this awkwardness. */
+static void
+ior_hard_reg_set (set1, set2)
+ HARD_REG_SET *set1, *set2;
+{
+ IOR_HARD_REG_SET (*set1, *set2);
+}
+
+/* After find_reload_regs has been run for all insn that need reloads,
+ and/or spill_hard_regs was called, this function is used to actually
+ spill pseudo registers and try to reallocate them. It also sets up the
+ spill_regs array for use by choose_reload_regs. */
- if (*p == LIM_REG_CLASSES)
- continue;
- }
+static int
+finish_spills (global, dumpfile)
+ int global;
+ FILE *dumpfile;
+{
+ struct insn_chain *chain;
+ int something_changed = 0;
+ int i;
+
+ /* Build the spill_regs array for the function. */
+ /* If there are some registers still to eliminate and one of the spill regs
+ wasn't ever used before, additional stack space may have to be
+ allocated to store this register. Thus, we may have changed the offset
+ between the stack and frame pointers, so mark that something has changed.
+
+ One might think that we need only set VAL to 1 if this is a call-used
+ register. However, the set of registers that must be saved by the
+ prologue is not identical to the call-used set. For example, the
+ register used by the call insn for the return PC is a call-used register,
+ but must be saved by the prologue. */
+
+ n_spills = 0;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (used_spill_regs, i))
+ {
+ spill_reg_order[i] = n_spills;
+ spill_regs[n_spills++] = i;
+ if (num_eliminable && ! regs_ever_live[i])
+ something_changed = 1;
+ regs_ever_live[i] = 1;
+ }
+ else
+ spill_reg_order[i] = -1;
+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ if (REGNO_REG_SET_P (spilled_pseudos, i))
+ {
+ /* Record the current hard register the pseudo is allocated to in
+ pseudo_previous_regs so we avoid reallocating it to the same
+ hard reg in a later pass. */
+ if (reg_renumber[i] < 0)
+ abort ();
+ SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
/* Mark it as no longer having a hard register home. */
reg_renumber[i] = -1;
/* We will need to scan everything again. */
something_changed = 1;
- if (global)
- retry_global_alloc (i, forbidden_regs);
+ }
- alter_reg (i, regno);
- if (dumpfile)
+ /* Retry global register allocation if possible. */
+ if (global)
+ {
+ bzero ((char *) pseudo_forbidden_regs, max_regno * sizeof (HARD_REG_SET));
+ /* For every insn that needs reloads, set the registers used as spill
+ regs in pseudo_forbidden_regs for every pseudo live across the
+ insn. */
+ for (chain = insns_need_reload; chain; chain = chain->next_need_reload)
+ {
+ EXECUTE_IF_SET_IN_REG_SET
+ (chain->live_before, FIRST_PSEUDO_REGISTER, i,
+ {
+ ior_hard_reg_set (pseudo_forbidden_regs + i,
+ &chain->used_spill_regs);
+ });
+ EXECUTE_IF_SET_IN_REG_SET
+ (chain->live_after, FIRST_PSEUDO_REGISTER, i,
+ {
+ ior_hard_reg_set (pseudo_forbidden_regs + i,
+ &chain->used_spill_regs);
+ });
+ }
+
+ /* Retry allocating the spilled pseudos. For each reg, merge the
+ various reg sets that indicate which hard regs can't be used,
+ and call retry_global_alloc.
+ We change spill_pseudos here to only contain pseudos that did not
+ get a new hard register. */
+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ if (reg_old_renumber[i] != reg_renumber[i])
{
- if (reg_renumber[i] == -1)
- fprintf (dumpfile, " Register %d now on stack.\n\n", i);
- else
- fprintf (dumpfile, " Register %d now in %d.\n\n",
- i, reg_renumber[i]);
+ HARD_REG_SET forbidden;
+ COPY_HARD_REG_SET (forbidden, bad_spill_regs_global);
+ IOR_HARD_REG_SET (forbidden, pseudo_forbidden_regs[i]);
+ IOR_HARD_REG_SET (forbidden, pseudo_previous_regs[i]);
+ retry_global_alloc (i, forbidden);
+ if (reg_renumber[i] >= 0)
+ CLEAR_REGNO_REG_SET (spilled_pseudos, i);
}
- }
- for (i = 0; i < scratch_list_length; i++)
+ }
+
+ /* Fix up the register information in the insn chain.
+ This involves deleting those of the spilled pseudos which did not get
+ a new hard register home from the live_{before,after} sets. */
+ for (chain = reload_insn_chain; chain; chain = chain->next)
{
- if (scratch_list[i]
- && regno >= REGNO (scratch_list[i])
- && regno < REGNO (scratch_list[i])
- + HARD_REGNO_NREGS (REGNO (scratch_list[i]),
- GET_MODE (scratch_list[i])))
- {
- if (! cant_eliminate && basic_block_needs[0]
- && ! basic_block_needs[(int) class][scratch_block[i]])
- {
- enum reg_class *p;
+ HARD_REG_SET used_by_pseudos;
+ HARD_REG_SET used_by_pseudos2;
- for (p = reg_class_superclasses[(int) class];
- *p != LIM_REG_CLASSES; p++)
- if (basic_block_needs[(int) *p][scratch_block[i]] > 0)
- break;
+ AND_COMPL_REG_SET (chain->live_before, spilled_pseudos);
+ AND_COMPL_REG_SET (chain->live_after, spilled_pseudos);
- if (*p == LIM_REG_CLASSES)
- continue;
- }
- PUT_CODE (scratch_list[i], SCRATCH);
- scratch_list[i] = 0;
- something_changed = 1;
- continue;
+ /* Mark any unallocated hard regs as available for spills. That
+ makes inheritance work somewhat better. */
+ if (chain->need_reload)
+ {
+ REG_SET_TO_HARD_REG_SET (used_by_pseudos, chain->live_before);
+ REG_SET_TO_HARD_REG_SET (used_by_pseudos2, chain->live_after);
+ IOR_HARD_REG_SET (used_by_pseudos, used_by_pseudos2);
+
+ /* Save the old value for the sanity test below. */
+ COPY_HARD_REG_SET (used_by_pseudos2, chain->used_spill_regs);
+
+ compute_use_by_pseudos (&used_by_pseudos, chain->live_before);
+ compute_use_by_pseudos (&used_by_pseudos, chain->live_after);
+ COMPL_HARD_REG_SET (chain->used_spill_regs, used_by_pseudos);
+ AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs);
+
+ /* Make sure we only enlarge the set. */
+ GO_IF_HARD_REG_SUBSET (used_by_pseudos2, chain->used_spill_regs, ok);
+ abort ();
+ ok:;
+ }
+ }
+
+ /* Let alter_reg modify the reg rtx's for the modified pseudos. */
+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ {
+ int regno = reg_renumber[i];
+ if (reg_old_renumber[i] == regno)
+ continue;
+
+ alter_reg (i, reg_old_renumber[i]);
+ reg_old_renumber[i] = regno;
+ if (dumpfile)
+ {
+ if (regno == -1)
+ fprintf (dumpfile, " Register %d now on stack.\n\n", i);
+ else
+ fprintf (dumpfile, " Register %d now in %d.\n\n",
+ i, reg_renumber[i]);
}
}
@@ -3787,9 +3995,11 @@ scan_paradoxical_subregs (x)
switch (code)
{
case REG:
+#if 0
if (SMALL_REGISTER_CLASSES && REGNO (x) < FIRST_PSEUDO_REGISTER
&& REG_USERVAR_P (x))
- SET_HARD_REG_BIT (forbidden_regs, REGNO (x));
+ SET_HARD_REG_BIT (bad_spill_regs_global, REGNO (x));
+#endif
return;
case CONST_INT:
@@ -3830,101 +4040,105 @@ scan_paradoxical_subregs (x)
static int
hard_reg_use_compare (p1p, p2p)
- const GENERIC_PTR p1p;
- const GENERIC_PTR p2p;
-{
- struct hard_reg_n_uses *p1 = (struct hard_reg_n_uses *)p1p,
- *p2 = (struct hard_reg_n_uses *)p2p;
- int tem = p1->uses - p2->uses;
- if (tem != 0) return tem;
+ const GENERIC_PTR p1p;
+ const GENERIC_PTR p2p;
+{
+ struct hard_reg_n_uses *p1 = (struct hard_reg_n_uses *)p1p;
+ struct hard_reg_n_uses *p2 = (struct hard_reg_n_uses *)p2p;
+ int bad1 = TEST_HARD_REG_BIT (bad_spill_regs, p1->regno);
+ int bad2 = TEST_HARD_REG_BIT (bad_spill_regs, p2->regno);
+ if (bad1 && bad2)
+ return p1->regno - p2->regno;
+ if (bad1)
+ return 1;
+ if (bad2)
+ return -1;
+ if (p1->uses > p2->uses)
+ return 1;
+ if (p1->uses < p2->uses)
+ return -1;
/* If regs are equally good, sort by regno,
so that the results of qsort leave nothing to chance. */
return p1->regno - p2->regno;
}
+/* Used for communication between order_regs_for_reload and count_pseudo.
+ Used to avoid counting one pseudo twice. */
+static regset pseudos_counted;
+
+/* Update the costs in N_USES, considering that pseudo REG is live. */
+static void
+count_pseudo (n_uses, reg)
+ struct hard_reg_n_uses *n_uses;
+ int reg;
+{
+ int r = reg_renumber[reg];
+ int nregs;
+
+ if (REGNO_REG_SET_P (pseudos_counted, reg))
+ return;
+ SET_REGNO_REG_SET (pseudos_counted, reg);
+
+ if (r < 0)
+ abort ();
+
+ nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
+ while (nregs-- > 0)
+ n_uses[r++].uses += REG_N_REFS (reg);
+}
/* Choose the order to consider regs for use as reload registers
based on how much trouble would be caused by spilling one.
Store them in order of decreasing preference in potential_reload_regs. */
static void
-order_regs_for_reload (global)
- int global;
+order_regs_for_reload (chain)
+ struct insn_chain *chain;
{
register int i;
register int o = 0;
- int large = 0;
-
struct hard_reg_n_uses hard_reg_n_uses[FIRST_PSEUDO_REGISTER];
- CLEAR_HARD_REG_SET (bad_spill_regs);
+ pseudos_counted = ALLOCA_REG_SET ();
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- potential_reload_regs[i] = -1;
+ COPY_HARD_REG_SET (bad_spill_regs, bad_spill_regs_global);
/* Count number of uses of each hard reg by pseudo regs allocated to it
and then order them by decreasing use. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- hard_reg_n_uses[i].uses = 0;
+ int j;
+
hard_reg_n_uses[i].regno = i;
- }
+ hard_reg_n_uses[i].uses = 0;
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- {
- int regno = reg_renumber[i];
- if (regno >= 0)
+ /* Test the various reasons why we can't use a register for
+ spilling in this insn. */
+ if (fixed_regs[i]
+ || REGNO_REG_SET_P (chain->live_before, i)
+ || REGNO_REG_SET_P (chain->live_after, i))
{
- int lim = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
- while (regno < lim)
- {
- /* If allocated by local-alloc, show more uses since
- we're not going to be able to reallocate it, but
- we might if allocated by global alloc. */
- if (global && reg_allocno[i] < 0)
- hard_reg_n_uses[regno].uses += (REG_N_REFS (i) + 1) / 2;
-
- hard_reg_n_uses[regno++].uses += REG_N_REFS (i);
- }
- }
- large += REG_N_REFS (i);
- }
-
- /* Now fixed registers (which cannot safely be used for reloading)
- get a very high use count so they will be considered least desirable.
- Registers used explicitly in the rtl code are almost as bad. */
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- if (fixed_regs[i])
- {
- hard_reg_n_uses[i].uses += 2 * large + 2;
SET_HARD_REG_BIT (bad_spill_regs, i);
+ continue;
}
- else if (regs_explicitly_used[i])
- {
- hard_reg_n_uses[i].uses += large + 1;
- if (! SMALL_REGISTER_CLASSES)
- /* ??? We are doing this here because of the potential
- that bad code may be generated if a register explicitly
- used in an insn was used as a spill register for that
- insn. But not using these are spill registers may lose
- on some machine. We'll have to see how this works out. */
- SET_HARD_REG_BIT (bad_spill_regs, i);
- }
- }
- hard_reg_n_uses[HARD_FRAME_POINTER_REGNUM].uses += 2 * large + 2;
- SET_HARD_REG_BIT (bad_spill_regs, HARD_FRAME_POINTER_REGNUM);
-#ifdef ELIMINABLE_REGS
- /* If registers other than the frame pointer are eliminable, mark them as
- poor choices. */
- for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- {
- hard_reg_n_uses[reg_eliminate[i].from].uses += 2 * large + 2;
- SET_HARD_REG_BIT (bad_spill_regs, reg_eliminate[i].from);
+ /* Now find out which pseudos are allocated to it, and update
+ hard_reg_n_uses. */
+ CLEAR_REG_SET (pseudos_counted);
+
+ EXECUTE_IF_SET_IN_REG_SET
+ (chain->live_before, FIRST_PSEUDO_REGISTER, j,
+ {
+ count_pseudo (hard_reg_n_uses, j);
+ });
+ EXECUTE_IF_SET_IN_REG_SET
+ (chain->live_after, FIRST_PSEUDO_REGISTER, j,
+ {
+ count_pseudo (hard_reg_n_uses, j);
+ });
}
-#endif
+
+ FREE_REG_SET (pseudos_counted);
/* Prefer registers not so far used, for use in temporary loading.
Among them, if REG_ALLOC_ORDER is defined, use that order.
@@ -3935,18 +4149,21 @@ order_regs_for_reload (global)
{
int regno = reg_alloc_order[i];
- if (hard_reg_n_uses[regno].uses == 0)
+ if (hard_reg_n_uses[regno].uses == 0
+ && ! TEST_HARD_REG_BIT (bad_spill_regs, regno))
potential_reload_regs[o++] = regno;
}
#else
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- if (hard_reg_n_uses[i].uses == 0 && call_used_regs[i])
+ if (hard_reg_n_uses[i].uses == 0 && call_used_regs[i]
+ && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
potential_reload_regs[o++] = i;
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- if (hard_reg_n_uses[i].uses == 0 && ! call_used_regs[i])
+ if (hard_reg_n_uses[i].uses == 0 && ! call_used_regs[i]
+ && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
potential_reload_regs[o++] = i;
}
#endif
@@ -3959,21 +4176,14 @@ order_regs_for_reload (global)
registers will be at the end of this list. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (hard_reg_n_uses[i].uses != 0)
+ if (hard_reg_n_uses[i].uses != 0
+ && ! TEST_HARD_REG_BIT (bad_spill_regs, hard_reg_n_uses[i].regno))
+ potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (bad_spill_regs, hard_reg_n_uses[i].regno))
potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
}
-/* Used in reload_as_needed to sort the spilled regs. */
-
-static int
-compare_spill_regs (r1p, r2p)
- const GENERIC_PTR r1p;
- const GENERIC_PTR r2p;
-{
- short r1 = *(short *)r1p, r2 = *(short *)r2p;
- return r1 - r2;
-}
-
/* Reload pseudo-registers into hard regs around each insn as needed.
Additional register load insns are output before the insn that needs it
and perhaps store insns after insns that modify the reloaded pseudo reg.
@@ -3984,15 +4194,14 @@ compare_spill_regs (r1p, r2p)
as the insns are scanned. */
static void
-reload_as_needed (first, live_known)
- rtx first;
+reload_as_needed (live_known)
int live_known;
{
- register rtx insn;
+ struct insn_chain *chain;
+#if defined (AUTO_INC_DEC) || defined (INSN_CLOBBERS_REGNO_P)
register int i;
- int this_block = 0;
+#endif
rtx x;
- rtx after_call = 0;
bzero ((char *) spill_reg_rtx, sizeof spill_reg_rtx);
bzero ((char *) spill_reg_store, sizeof spill_reg_store);
@@ -4001,84 +4210,23 @@ reload_as_needed (first, live_known)
reg_has_output_reload = (char *) alloca (max_regno);
CLEAR_HARD_REG_SET (reg_reloaded_valid);
- /* Reset all offsets on eliminable registers to their initial values. */
-#ifdef ELIMINABLE_REGS
- for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- {
- INITIAL_ELIMINATION_OFFSET (reg_eliminate[i].from, reg_eliminate[i].to,
- reg_eliminate[i].initial_offset);
- reg_eliminate[i].previous_offset
- = reg_eliminate[i].offset = reg_eliminate[i].initial_offset;
- }
-#else
- INITIAL_FRAME_POINTER_OFFSET (reg_eliminate[0].initial_offset);
- reg_eliminate[0].previous_offset
- = reg_eliminate[0].offset = reg_eliminate[0].initial_offset;
-#endif
+ set_initial_elim_offsets ();
- num_not_at_initial_offset = 0;
-
- /* Order the spilled regs, so that allocate_reload_regs can guarantee to
- pack registers with group needs. */
- if (n_spills > 1)
- {
- qsort (spill_regs, n_spills, sizeof (short), compare_spill_regs);
- for (i = 0; i < n_spills; i++)
- spill_reg_order[spill_regs[i]] = i;
- }
-
- for (insn = first; insn;)
+ for (chain = reload_insn_chain; chain; chain = chain->next)
{
- register rtx next = NEXT_INSN (insn);
-
- /* Notice when we move to a new basic block. */
- if (live_known && this_block + 1 < n_basic_blocks
- && insn == basic_block_head[this_block+1])
- ++this_block;
+ rtx prev;
+ rtx insn = chain->insn;
+ rtx old_next = NEXT_INSN (insn);
/* If we pass a label, copy the offsets from the label information
into the current offsets of each elimination. */
if (GET_CODE (insn) == CODE_LABEL)
- {
- num_not_at_initial_offset = 0;
- for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- {
- reg_eliminate[i].offset = reg_eliminate[i].previous_offset
- = offsets_at[CODE_LABEL_NUMBER (insn)][i];
- if (reg_eliminate[i].can_eliminate
- && (reg_eliminate[i].offset
- != reg_eliminate[i].initial_offset))
- num_not_at_initial_offset++;
- }
- }
+ set_offsets_for_label (insn);
else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
- rtx avoid_return_reg = 0;
rtx oldpat = PATTERN (insn);
- /* Set avoid_return_reg if this is an insn
- that might use the value of a function call. */
- if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
- {
- if (GET_CODE (PATTERN (insn)) == SET)
- after_call = SET_DEST (PATTERN (insn));
- else if (GET_CODE (PATTERN (insn)) == PARALLEL
- && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
- after_call = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
- else
- after_call = 0;
- }
- else if (SMALL_REGISTER_CLASSES && after_call != 0
- && !(GET_CODE (PATTERN (insn)) == SET
- && SET_DEST (PATTERN (insn)) == stack_pointer_rtx)
- && GET_CODE (PATTERN (insn)) != USE)
- {
- if (reg_referenced_p (after_call, PATTERN (insn)))
- avoid_return_reg = after_call;
- after_call = 0;
- }
-
/* If this is a USE and CLOBBER of a MEM, ensure that any
references to eliminable registers have been removed. */
@@ -4092,17 +4240,25 @@ reload_as_needed (first, live_known)
/* If we need to do register elimination processing, do so.
This might delete the insn, in which case we are done. */
- if (num_eliminable && GET_MODE (insn) == QImode)
+ if ((num_eliminable || num_eliminable_invariants) && chain->need_elim)
{
eliminate_regs_in_insn (insn, 1);
if (GET_CODE (insn) == NOTE)
{
- insn = next;
+ update_eliminable_offsets ();
continue;
}
}
- if (GET_MODE (insn) == VOIDmode)
+ /* If need_elim is nonzero but need_reload is zero, one might think
+ that we could simply set n_reloads to 0. However, find_reloads
+ could have done some manipulation of the insn (such as swapping
+ commutative operands), and these manipulations are lost during
+ the first pass for every insn that needs register elimination.
+ So the actions of find_reloads must be redone here. */
+
+ if (! chain->need_elim && ! chain->need_reload
+ && ! chain->need_operand_change)
n_reloads = 0;
/* First find the pseudo regs that must be reloaded for this insn.
This info is returned in the tables reload_... (see reload.h).
@@ -4117,32 +4273,21 @@ reload_as_needed (first, live_known)
spill_reg_order);
}
+ if (num_eliminable && chain->need_elim)
+ update_eliminable_offsets ();
+
if (n_reloads > 0)
{
- rtx prev = PREV_INSN (insn), next = NEXT_INSN (insn);
+ rtx next = NEXT_INSN (insn);
rtx p;
- int class;
-
- /* If this block has not had spilling done for a
- particular clas and we have any non-optionals that need a
- spill reg in that class, abort. */
-
- for (class = 0; class < N_REG_CLASSES; class++)
- if (basic_block_needs[class] != 0
- && basic_block_needs[class][this_block] == 0)
- for (i = 0; i < n_reloads; i++)
- if (class == (int) reload_reg_class[i]
- && reload_reg_rtx[i] == 0
- && ! reload_optional[i]
- && (reload_in[i] != 0 || reload_out[i] != 0
- || reload_secondary_p[i] != 0))
- fatal_insn ("Non-optional registers need a spill register", insn);
+
+ prev = PREV_INSN (insn);
/* Now compute which reload regs to reload them into. Perhaps
reusing reload regs from previous insns, or else output
load insns to reload them. Maybe output store insns too.
Record the choices of reload reg in reload_reg_rtx. */
- choose_reload_regs (insn, avoid_return_reg);
+ choose_reload_regs (chain);
/* Merge any reloads that we didn't combine for fear of
increasing the number of spill registers needed but now
@@ -4152,7 +4297,7 @@ reload_as_needed (first, live_known)
/* Generate the insns to reload operands into or out of
their reload regs. */
- emit_reload_insns (insn);
+ emit_reload_insns (chain);
/* Substitute the chosen reload regs from reload_reg_rtx
into the insn's body (or perhaps into the bodies of other
@@ -4168,8 +4313,7 @@ reload_as_needed (first, live_known)
for (p = NEXT_INSN (prev); p != next; p = NEXT_INSN (p))
if (p != insn && GET_RTX_CLASS (GET_CODE (p)) == 'i'
&& (recog_memoized (p) < 0
- || (insn_extract (p),
- ! constrain_operands (INSN_CODE (p), 1))))
+ || (extract_insn (p), ! constrain_operands (1))))
{
error_for_asm (insn,
"`asm' operand requires impossible reload");
@@ -4188,14 +4332,109 @@ reload_as_needed (first, live_known)
/* There may have been CLOBBER insns placed after INSN. So scan
between INSN and NEXT and use them to forget old reloads. */
- for (x = NEXT_INSN (insn); x != next; x = NEXT_INSN (x))
+ for (x = NEXT_INSN (insn); x != old_next; x = NEXT_INSN (x))
if (GET_CODE (x) == INSN && GET_CODE (PATTERN (x)) == CLOBBER)
note_stores (PATTERN (x), forget_old_reloads_1);
#ifdef AUTO_INC_DEC
/* Likewise for regs altered by auto-increment in this insn.
- But note that the reg-notes are not changed by reloading:
- they still contain the pseudo-regs, not the spill regs. */
+ REG_INC notes have been changed by reloading:
+ find_reloads_address_1 records substitutions for them,
+ which have been performed by subst_reloads above. */
+ for (i = n_reloads - 1; i >= 0; i--)
+ {
+ rtx in_reg = reload_in_reg[i];
+ if (in_reg)
+ {
+ enum rtx_code code = GET_CODE (in_reg);
+ /* PRE_INC / PRE_DEC will have the reload register ending up
+ with the same value as the stack slot, but that doesn't
+ hold true for POST_INC / POST_DEC. Either we have to
+ convert the memory access to a true POST_INC / POST_DEC,
+ or we can't use the reload register for inheritance. */
+ if ((code == POST_INC || code == POST_DEC)
+ && TEST_HARD_REG_BIT (reg_reloaded_valid,
+ REGNO (reload_reg_rtx[i]))
+ /* Make sure it is the inc/dec pseudo, and not
+ some other (e.g. output operand) pseudo. */
+ && (reg_reloaded_contents[REGNO (reload_reg_rtx[i])]
+ == REGNO (XEXP (in_reg, 0))))
+
+ {
+ rtx reload_reg = reload_reg_rtx[i];
+ enum machine_mode mode = GET_MODE (reload_reg);
+ int n = 0;
+ rtx p;
+
+ for (p = PREV_INSN (old_next); p != prev; p = PREV_INSN (p))
+ {
+ /* We really want to ignore REG_INC notes here, so
+ use PATTERN (p) as argument to reg_set_p . */
+ if (reg_set_p (reload_reg, PATTERN (p)))
+ break;
+ n = count_occurrences (PATTERN (p), reload_reg);
+ if (! n)
+ continue;
+ if (n == 1)
+ {
+ n = validate_replace_rtx (reload_reg,
+ gen_rtx (code, mode,
+ reload_reg),
+ p);
+
+ /* We must also verify that the constraints
+ are met after the replacement. */
+ extract_insn (p);
+ if (n)
+ n = constrain_operands (1);
+ else
+ break;
+
+ /* If the constraints were not met, then
+ undo the replacement. */
+ if (!n)
+ {
+ validate_replace_rtx (gen_rtx (code, mode,
+ reload_reg),
+ reload_reg, p);
+ break;
+ }
+
+ }
+ break;
+ }
+ if (n == 1)
+ {
+ REG_NOTES (p)
+ = gen_rtx_EXPR_LIST (REG_INC, reload_reg,
+ REG_NOTES (p));
+ /* Mark this as having an output reload so that the
+ REG_INC processing code below won't invalidate
+ the reload for inheritance. */
+ SET_HARD_REG_BIT (reg_is_output_reload,
+ REGNO (reload_reg));
+ reg_has_output_reload[REGNO (XEXP (in_reg, 0))] = 1;
+ }
+ else
+ forget_old_reloads_1 (XEXP (in_reg, 0), NULL_RTX);
+ }
+ else if ((code == PRE_INC || code == PRE_DEC)
+ && TEST_HARD_REG_BIT (reg_reloaded_valid,
+ REGNO (reload_reg_rtx[i]))
+ /* Make sure it is the inc/dec pseudo, and not
+ some other (e.g. output operand) pseudo. */
+ && (reg_reloaded_contents[REGNO (reload_reg_rtx[i])]
+ == REGNO (XEXP (in_reg, 0))))
+ {
+ SET_HARD_REG_BIT (reg_is_output_reload,
+ REGNO (reload_reg_rtx[i]));
+ reg_has_output_reload[REGNO (XEXP (in_reg, 0))] = 1;
+ }
+ }
+ }
+ /* If a pseudo that got a hard register is auto-incremented,
+ we must purge records of copying it into pseudos without
+ hard registers. */
for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
if (REG_NOTE_KIND (x) == REG_INC)
{
@@ -4230,8 +4469,6 @@ reload_as_needed (first, live_known)
CLEAR_HARD_REG_BIT (reg_reloaded_valid, i);
#endif
- insn = next;
-
#ifdef USE_C_ALLOCA
alloca (0);
#endif
@@ -4251,43 +4488,27 @@ forget_old_reloads_1 (x, ignored)
rtx ignored ATTRIBUTE_UNUSED;
{
register int regno;
- enum machine_mode mode = GET_MODE (x);
int nr;
+ int offset = 0;
- /* note_stores does give us subregs of hard regs.
-
- This is a egcs-1.1 tree hack only. A better solution is being
- developed for mainline sources. Do not import this back to the
- mainline tree.
-
- We want to strip all the SUBREGs, but also keep track of the
- largest mode we encounter so that we can invalidate all the
- hard regs which are needed to hold the widest mode.
-
- This avoids a bug in choose_reload_regs (which is where the real
- fix for the mainline tree will be). */
-
+ /* note_stores does give us subregs of hard regs. */
while (GET_CODE (x) == SUBREG)
{
- if (GET_MODE_BITSIZE (GET_MODE (x)) > GET_MODE_BITSIZE (mode))
- mode = GET_MODE (x);
+ offset += SUBREG_WORD (x);
x = SUBREG_REG (x);
}
- if (GET_MODE_BITSIZE (GET_MODE (x)) > GET_MODE_BITSIZE (mode))
- mode = GET_MODE (x);
-
if (GET_CODE (x) != REG)
return;
- regno = REGNO (x);
+ regno = REGNO (x) + offset;
if (regno >= FIRST_PSEUDO_REGISTER)
nr = 1;
else
{
int i;
- nr = HARD_REGNO_NREGS (regno, mode);
+ nr = HARD_REGNO_NREGS (regno, GET_MODE (x));
/* Storing into a spilled-reg invalidates its contents.
This can happen if a block-local pseudo is allocated to that reg
and it wasn't spilled because this block's total need is 0.
@@ -4386,6 +4607,10 @@ static HARD_REG_SET reload_reg_used_at_all;
in the group. */
static HARD_REG_SET reload_reg_used_for_inherit;
+/* Records which hard regs are used in any way, either as explicit use or
+ by being allocated to a pseudo during any point of the current insn. */
+static HARD_REG_SET reg_used_in_insn;
+
/* Mark reg REGNO as in use for a reload of the sort spec'd by OPNUM and
TYPE. MODE is used to indicate how many consecutive regs are
actually used. */
@@ -4463,57 +4688,104 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
enum machine_mode mode;
{
int nregs = HARD_REGNO_NREGS (regno, mode);
+ int start_regno, end_regno;
int i;
+ /* A complication is that for some reload types, inheritance might
+ allow multiple reloads of the same types to share a reload register.
+ We set check_opnum if we have to check only reloads with the same
+ operand number, and check_any if we have to check all reloads. */
+ int check_opnum = 0;
+ int check_any = 0;
+ HARD_REG_SET *used_in_set;
- for (i = regno; i < nregs + regno; i++)
+ switch (type)
{
- switch (type)
- {
- case RELOAD_OTHER:
- CLEAR_HARD_REG_BIT (reload_reg_used, i);
- break;
+ case RELOAD_OTHER:
+ used_in_set = &reload_reg_used;
+ break;
- case RELOAD_FOR_INPUT_ADDRESS:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], i);
- break;
+ case RELOAD_FOR_INPUT_ADDRESS:
+ used_in_set = &reload_reg_used_in_input_addr[opnum];
+ break;
- case RELOAD_FOR_INPADDR_ADDRESS:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], i);
- break;
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ check_opnum = 1;
+ used_in_set = &reload_reg_used_in_inpaddr_addr[opnum];
+ break;
- case RELOAD_FOR_OUTPUT_ADDRESS:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], i);
- break;
+ case RELOAD_FOR_OUTPUT_ADDRESS:
+ used_in_set = &reload_reg_used_in_output_addr[opnum];
+ break;
- case RELOAD_FOR_OUTADDR_ADDRESS:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], i);
- break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ check_opnum = 1;
+ used_in_set = &reload_reg_used_in_outaddr_addr[opnum];
+ break;
- case RELOAD_FOR_OPERAND_ADDRESS:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
- break;
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ used_in_set = &reload_reg_used_in_op_addr;
+ break;
- case RELOAD_FOR_OPADDR_ADDR:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, i);
- break;
+ case RELOAD_FOR_OPADDR_ADDR:
+ check_any = 1;
+ used_in_set = &reload_reg_used_in_op_addr_reload;
+ break;
- case RELOAD_FOR_OTHER_ADDRESS:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_other_addr, i);
- break;
+ case RELOAD_FOR_OTHER_ADDRESS:
+ used_in_set = &reload_reg_used_in_other_addr;
+ check_any = 1;
+ break;
- case RELOAD_FOR_INPUT:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_input[opnum], i);
- break;
+ case RELOAD_FOR_INPUT:
+ used_in_set = &reload_reg_used_in_input[opnum];
+ break;
- case RELOAD_FOR_OUTPUT:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_output[opnum], i);
- break;
+ case RELOAD_FOR_OUTPUT:
+ used_in_set = &reload_reg_used_in_output[opnum];
+ break;
- case RELOAD_FOR_INSN:
- CLEAR_HARD_REG_BIT (reload_reg_used_in_insn, i);
- break;
+ case RELOAD_FOR_INSN:
+ used_in_set = &reload_reg_used_in_insn;
+ break;
+ default:
+ abort ();
+ }
+ /* We resolve conflicts with remaining reloads of the same type by
+ excluding the intervals of of reload registers by them from the
+ interval of freed reload registers. Since we only keep track of
+ one set of interval bounds, we might have to exclude somewhat
+ more then what would be necessary if we used a HARD_REG_SET here.
+ But this should only happen very infrequently, so there should
+ be no reason to worry about it. */
+
+ start_regno = regno;
+ end_regno = regno + nregs;
+ if (check_opnum || check_any)
+ {
+ for (i = n_reloads - 1; i >= 0; i--)
+ {
+ if (reload_when_needed[i] == type
+ && (check_any || reload_opnum[i] == opnum)
+ && reload_reg_rtx[i])
+ {
+ int conflict_start = true_regnum (reload_reg_rtx[i]);
+ int conflict_end
+ = (conflict_start
+ + HARD_REGNO_NREGS (conflict_start, reload_mode[i]));
+
+ /* If there is an overlap with the first to-be-freed register,
+ adjust the interval start. */
+ if (conflict_start <= start_regno && conflict_end > start_regno)
+ start_regno = conflict_end;
+ /* Otherwise, if there is a conflict with one of the other
+ to-be-freed registers, adjust the interval end. */
+ if (conflict_start > start_regno && conflict_start < end_regno)
+ end_regno = conflict_start;
+ }
}
}
+ for (i = start_regno; i < end_regno; i++)
+ CLEAR_HARD_REG_BIT (*used_in_set, i);
}
/* 1 if reg REGNO is free as a reload reg for a reload of the sort
@@ -4672,123 +4944,6 @@ reload_reg_free_p (regno, opnum, type)
/* Return 1 if the value in reload reg REGNO, as used by a reload
needed for the part of the insn specified by OPNUM and TYPE,
- is not in use for a reload in any prior part of the insn.
-
- We can assume that the reload reg was already tested for availability
- at the time it is needed, and we should not check this again,
- in case the reg has already been marked in use. */
-
-static int
-reload_reg_free_before_p (regno, opnum, type)
- int regno;
- int opnum;
- enum reload_type type;
-{
- int i;
-
- switch (type)
- {
- case RELOAD_FOR_OTHER_ADDRESS:
- /* These always come first. */
- return 1;
-
- case RELOAD_OTHER:
- return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
-
- /* If this use is for part of the insn,
- check the reg is not in use for any prior part. It is tempting
- to try to do this by falling through from objecs that occur
- later in the insn to ones that occur earlier, but that will not
- correctly take into account the fact that here we MUST ignore
- things that would prevent the register from being allocated in
- the first place, since we know that it was allocated. */
-
- case RELOAD_FOR_OUTPUT_ADDRESS:
- /* Earlier reloads include RELOAD_FOR_OUTADDR_ADDRESS reloads. */
- if (TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
- return 0;
- /* ... fall through ... */
- case RELOAD_FOR_OUTADDR_ADDRESS:
- /* Earlier reloads are for earlier outputs or their addresses,
- any RELOAD_FOR_INSN reloads, any inputs or their addresses, or any
- RELOAD_FOR_OTHER_ADDRESS reloads (we know it can't conflict with
- RELOAD_OTHER).. */
- for (i = 0; i < opnum; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
- || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
- || TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
- return 0;
-
- if (TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno))
- return 0;
-
- for (i = 0; i < reload_n_operands; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
- || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
- || TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
- return 0;
-
- return (! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno)
- && ! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno)
- && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
- && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno));
-
- case RELOAD_FOR_OUTPUT:
- /* There is no reason to call this function for output reloads, thus
- anything we'd put here wouldn't be tested. So just abort. */
- abort ();
-
- case RELOAD_FOR_OPERAND_ADDRESS:
- /* Earlier reloads include RELOAD_FOR_OPADDR_ADDR reloads. */
- if (TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno))
- return 0;
-
- /* ... fall through ... */
-
- case RELOAD_FOR_OPADDR_ADDR:
- case RELOAD_FOR_INSN:
- /* These can't conflict with inputs, or each other, so all we have to
- test is input addresses and the addresses of OTHER items. */
-
- for (i = 0; i < reload_n_operands; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
- || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
- return 0;
-
- return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
-
- case RELOAD_FOR_INPUT:
- /* The only things earlier are the address for this and
- earlier inputs, other inputs (which we know we don't conflict
- with), and addresses of RELOAD_OTHER objects. */
-
- for (i = 0; i <= opnum; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
- || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
- return 0;
-
- return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
-
- case RELOAD_FOR_INPUT_ADDRESS:
- /* Earlier reloads include RELOAD_FOR_INPADDR_ADDRESS reloads. */
- if (TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], regno))
- return 0;
- /* ... fall through ... */
- case RELOAD_FOR_INPADDR_ADDRESS:
- /* Similarly, all we have to check is for use in earlier inputs'
- addresses. */
- for (i = 0; i < opnum; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
- || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
- return 0;
-
- return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
- }
- abort ();
-}
-
-/* Return 1 if the value in reload reg REGNO, as used by a reload
- needed for the part of the insn specified by OPNUM and TYPE,
is still available in REGNO at the end of the insn.
We can assume that the reload reg was already tested for availability
@@ -5023,22 +5178,37 @@ int reload_spill_index[MAX_RELOADS];
Other read-only reloads with the same value do not conflict
unless OUT is non-zero and these other reloads have to live while
output reloads live.
+ If OUT is CONST0_RTX, this is a special case: it means that the
+ test should not be for using register REGNO as reload register, but
+ for copying from register REGNO into the reload register.
RELOADNUM is the number of the reload we want to load this value for;
a reload does not conflict with itself.
+ When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with
+ reloads that load an address for the very reload we are considering.
+
The caller has to make sure that there is no conflict with the return
register. */
static int
-reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum)
+reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
+ ignore_address_reloads)
int regno;
int opnum;
enum reload_type type;
rtx value, out;
int reloadnum;
+ int ignore_address_reloads;
{
int time1;
int i;
+ int copy = 0;
+
+ if (out == const0_rtx)
+ {
+ copy = 1;
+ out = NULL_RTX;
+ }
/* We use some pseudo 'time' value to check if the lifetimes of the
new register use would overlap with the one of a previous reload
@@ -5060,6 +5230,9 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum)
case RELOAD_FOR_OTHER_ADDRESS:
time1 = 0;
break;
+ case RELOAD_OTHER:
+ time1 = copy ? 1 : MAX_RECOG_OPERANDS * 5 + 5;
+ break;
/* For each input, we might have a sequence of RELOAD_FOR_INPADDR_ADDRESS,
RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_INPUT. By adding 0 / 1 / 2 ,
respectively, to the time values for these, we get distinct time
@@ -5067,23 +5240,34 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum)
multiply opnum by at least three. We round that up to four because
multiply by four is often cheaper. */
case RELOAD_FOR_INPADDR_ADDRESS:
- time1 = opnum * 4 + 1;
+ time1 = opnum * 4 + 2;
break;
case RELOAD_FOR_INPUT_ADDRESS:
- time1 = opnum * 4 + 2;
+ time1 = opnum * 4 + 3;
break;
case RELOAD_FOR_INPUT:
- /* All RELOAD_FOR_INPUT reloads remain live till just before the
- instruction is executed. */
- time1 = (MAX_RECOG_OPERANDS - 1) * 4 + 3;
+ /* All RELOAD_FOR_INPUT reloads remain live till the instruction
+ executes (inclusive). */
+ time1 = copy ? opnum * 4 + 4 : MAX_RECOG_OPERANDS * 4 + 3;
break;
- /* opnum * 4 + 3 < opnum * 4 + 4
+ case RELOAD_FOR_OPADDR_ADDR:
+ /* opnum * 4 + 4
<= (MAX_RECOG_OPERANDS - 1) * 4 + 4 == MAX_RECOG_OPERANDS * 4 */
+ time1 = MAX_RECOG_OPERANDS * 4 + 1;
+ break;
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ /* RELOAD_FOR_OPERAND_ADDRESS reloads are live even while the insn
+ is executed. */
+ time1 = copy ? MAX_RECOG_OPERANDS * 4 + 2 : MAX_RECOG_OPERANDS * 4 + 3;
+ break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ time1 = MAX_RECOG_OPERANDS * 4 + 4 + opnum;
+ break;
case RELOAD_FOR_OUTPUT_ADDRESS:
- time1 = MAX_RECOG_OPERANDS * 4 + opnum;
+ time1 = MAX_RECOG_OPERANDS * 4 + 5 + opnum;
break;
default:
- time1 = MAX_RECOG_OPERANDS * 5;
+ time1 = MAX_RECOG_OPERANDS * 5 + 5;
}
for (i = 0; i < n_reloads; i++)
@@ -5094,13 +5278,8 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum)
<= HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)) - (unsigned)1)
&& i != reloadnum)
{
- if (out
- && reload_when_needed[i] != RELOAD_FOR_INPUT
- && reload_when_needed[i] != RELOAD_FOR_INPUT_ADDRESS
- && reload_when_needed[i] != RELOAD_FOR_INPADDR_ADDRESS)
- return 0;
if (! reload_in[i] || ! rtx_equal_p (reload_in[i], value)
- || reload_out[i])
+ || reload_out[i] || out)
{
int time2;
switch (reload_when_needed[i])
@@ -5109,34 +5288,96 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum)
time2 = 0;
break;
case RELOAD_FOR_INPADDR_ADDRESS:
- time2 = reload_opnum[i] * 4 + 1;
+ /* find_reloads makes sure that a
+ RELOAD_FOR_{INP,OP,OUT}ADDR_ADDRESS reload is only used
+ by at most one - the first -
+ RELOAD_FOR_{INPUT,OPERAND,OUTPUT}_ADDRESS . If the
+ address reload is inherited, the address address reload
+ goes away, so we can ignore this conflict. */
+ if (type == RELOAD_FOR_INPUT_ADDRESS && reloadnum == i + 1
+ && ignore_address_reloads
+ /* Unless the RELOAD_FOR_INPUT is an auto_inc expression.
+ Then the address address is still needed to store
+ back the new address. */
+ && ! reload_out[reloadnum])
+ continue;
+ /* Likewise, if a RELOAD_FOR_INPUT can inherit a value, its
+ RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
+ reloads go away. */
+ if (type == RELOAD_FOR_INPUT && opnum == reload_opnum[i]
+ && ignore_address_reloads
+ /* Unless we are reloading an auto_inc expression. */
+ && ! reload_out[reloadnum])
+ continue;
+ time2 = reload_opnum[i] * 4 + 2;
break;
case RELOAD_FOR_INPUT_ADDRESS:
- time2 = reload_opnum[i] * 4 + 2;
+ if (type == RELOAD_FOR_INPUT && opnum == reload_opnum[i]
+ && ignore_address_reloads
+ && ! reload_out[reloadnum])
+ continue;
+ time2 = reload_opnum[i] * 4 + 3;
break;
case RELOAD_FOR_INPUT:
- time2 = reload_opnum[i] * 4 + 3;
+ time2 = reload_opnum[i] * 4 + 4;
+ break;
+ /* reload_opnum[i] * 4 + 4 <= (MAX_RECOG_OPERAND - 1) * 4 + 4
+ == MAX_RECOG_OPERAND * 4 */
+ case RELOAD_FOR_OPADDR_ADDR:
+ if (type == RELOAD_FOR_OPERAND_ADDRESS && reloadnum == i + 1
+ && ignore_address_reloads
+ && ! reload_out[reloadnum])
+ continue;
+ time2 = MAX_RECOG_OPERANDS * 4 + 1;
+ break;
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ time2 = MAX_RECOG_OPERANDS * 4 + 2;
+ break;
+ case RELOAD_FOR_INSN:
+ time2 = MAX_RECOG_OPERANDS * 4 + 3;
break;
case RELOAD_FOR_OUTPUT:
/* All RELOAD_FOR_OUTPUT reloads become live just after the
instruction is executed. */
- time2 = MAX_RECOG_OPERANDS * 4;
+ time2 = MAX_RECOG_OPERANDS * 4 + 4;
+ break;
+ /* The first RELOAD_FOR_OUTADDR_ADDRESS reload conflicts with
+ the RELOAD_FOR_OUTPUT reloads, so assign it the same time
+ value. */
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ if (type == RELOAD_FOR_OUTPUT_ADDRESS && reloadnum == i + 1
+ && ignore_address_reloads
+ && ! reload_out[reloadnum])
+ continue;
+ time2 = MAX_RECOG_OPERANDS * 4 + 4 + reload_opnum[i];
break;
- /* The first RELOAD_FOR_OUTPUT_ADDRESS reload conflicts with the
- RELOAD_FOR_OUTPUT reloads, so assign it the same time value. */
case RELOAD_FOR_OUTPUT_ADDRESS:
- time2 = MAX_RECOG_OPERANDS * 4 + reload_opnum[i];
+ time2 = MAX_RECOG_OPERANDS * 4 + 5 + reload_opnum[i];
break;
case RELOAD_OTHER:
+ /* If there is no conflict in the input part, handle this
+ like an output reload. */
if (! reload_in[i] || rtx_equal_p (reload_in[i], value))
{
- time2 = MAX_RECOG_OPERANDS * 4;
+ time2 = MAX_RECOG_OPERANDS * 4 + 4;
break;
}
+ time2 = 1;
+ /* RELOAD_OTHER might be live beyond instruction execution,
+ but this is not obvious when we set time2 = 1. So check
+ here if there might be a problem with the new reload
+ clobbering the register used by the RELOAD_OTHER. */
+ if (out)
+ return 0;
+ break;
default:
- time2 = 0;
+ return 0;
}
- if (time1 >= time2)
+ if ((time1 >= time2
+ && (! reload_in[i] || reload_out[i]
+ || ! rtx_equal_p (reload_in[i], value)))
+ || (out && reload_out_reg[reloadnum]
+ && time2 >= MAX_RECOG_OPERANDS * 4 + 3))
return 0;
}
}
@@ -5154,17 +5395,15 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum)
or 0 if we couldn't find a spill reg and we didn't change anything. */
static int
-allocate_reload_reg (r, insn, last_reload, noerror)
+allocate_reload_reg (chain, r, last_reload, noerror)
+ struct insn_chain *chain;
int r;
- rtx insn;
int last_reload;
int noerror;
{
- int i;
- int pass;
- int count;
+ rtx insn = chain->insn;
+ int i, pass, count, regno;
rtx new;
- int regno;
/* If we put this reload ahead, thinking it is a group,
then insist on finding a group. Otherwise we can grab a
@@ -5213,32 +5452,36 @@ allocate_reload_reg (r, insn, last_reload, noerror)
for (count = 0; count < n_spills; count++)
{
int class = (int) reload_reg_class[r];
+ int regnum;
- i = (i + 1) % n_spills;
+ i++;
+ if (i >= n_spills)
+ i -= n_spills;
+ regnum = spill_regs[i];
- if ((reload_reg_free_p (spill_regs[i], reload_opnum[r],
+ if ((reload_reg_free_p (regnum, reload_opnum[r],
reload_when_needed[r])
|| (reload_in[r]
/* We check reload_reg_used to make sure we
don't clobber the return register. */
- && ! TEST_HARD_REG_BIT (reload_reg_used, spill_regs[i])
- && reload_reg_free_for_value_p (spill_regs[i],
+ && ! TEST_HARD_REG_BIT (reload_reg_used, regnum)
+ && reload_reg_free_for_value_p (regnum,
reload_opnum[r],
reload_when_needed[r],
reload_in[r],
- reload_out[r], r)))
- && TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
- && HARD_REGNO_MODE_OK (spill_regs[i], reload_mode[r])
+ reload_out[r], r, 1)))
+ && TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
+ && HARD_REGNO_MODE_OK (regnum, reload_mode[r])
/* Look first for regs to share, then for unshared. But
don't share regs used for inherited reloads; they are
the ones we want to preserve. */
&& (pass
|| (TEST_HARD_REG_BIT (reload_reg_used_at_all,
- spill_regs[i])
+ regnum)
&& ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
- spill_regs[i]))))
+ regnum))))
{
- int nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode[r]);
+ int nr = HARD_REGNO_NREGS (regnum, reload_mode[r]);
/* Avoid the problem where spilling a GENERAL_OR_FP_REG
(on 68000) got us two FP regs. If NR is 1,
we would reject both of them. */
@@ -5256,15 +5499,15 @@ allocate_reload_reg (r, insn, last_reload, noerror)
are available here.
Also, don't use for a group registers that are
needed for nongroups. */
- if (! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]))
+ if (! TEST_HARD_REG_BIT (chain->counted_for_nongroups, regnum))
while (nr > 1)
{
- regno = spill_regs[i] + nr - 1;
+ regno = regnum + nr - 1;
if (!(TEST_HARD_REG_BIT (reg_class_contents[class], regno)
&& spill_reg_order[regno] >= 0
&& reload_reg_free_p (regno, reload_opnum[r],
reload_when_needed[r])
- && ! TEST_HARD_REG_BIT (counted_for_nongroups,
+ && ! TEST_HARD_REG_BIT (chain->counted_for_nongroups,
regno)))
break;
nr--;
@@ -5360,14 +5603,15 @@ allocate_reload_reg (r, insn, last_reload, noerror)
finding a reload reg in the proper class. */
static void
-choose_reload_regs (insn, avoid_return_reg)
- rtx insn;
- rtx avoid_return_reg;
+choose_reload_regs (chain)
+ struct insn_chain *chain;
{
+ rtx insn = chain->insn;
register int i, j;
int max_group_size = 1;
enum reg_class group_class = NO_REGS;
int inheritance;
+ int pass;
rtx save_reload_reg_rtx[MAX_RELOADS];
char save_reload_inherited[MAX_RELOADS];
@@ -5398,6 +5642,16 @@ choose_reload_regs (insn, avoid_return_reg)
CLEAR_HARD_REG_SET (reload_reg_used_in_insn);
CLEAR_HARD_REG_SET (reload_reg_used_in_other_addr);
+ CLEAR_HARD_REG_SET (reg_used_in_insn);
+ {
+ HARD_REG_SET tmp;
+ REG_SET_TO_HARD_REG_SET (tmp, chain->live_before);
+ IOR_HARD_REG_SET (reg_used_in_insn, tmp);
+ REG_SET_TO_HARD_REG_SET (tmp, chain->live_after);
+ IOR_HARD_REG_SET (reg_used_in_insn, tmp);
+ compute_use_by_pseudos (&reg_used_in_insn, chain->live_before);
+ compute_use_by_pseudos (&reg_used_in_insn, chain->live_after);
+ }
for (i = 0; i < reload_n_operands; i++)
{
CLEAR_HARD_REG_SET (reload_reg_used_in_output[i]);
@@ -5408,29 +5662,8 @@ choose_reload_regs (insn, avoid_return_reg)
CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
}
- /* Don't bother with avoiding the return reg
- if we have no mandatory reload that could use it. */
- if (SMALL_REGISTER_CLASSES && avoid_return_reg)
- {
- int do_avoid = 0;
- int regno = REGNO (avoid_return_reg);
- int nregs
- = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
- int r;
-
- for (r = regno; r < regno + nregs; r++)
- if (spill_reg_order[r] >= 0)
- for (j = 0; j < n_reloads; j++)
- if (!reload_optional[j] && reload_reg_rtx[j] == 0
- && (reload_in[j] != 0 || reload_out[j] != 0
- || reload_secondary_p[j])
- &&
- TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[j]], r))
- do_avoid = 1;
- if (!do_avoid)
- avoid_return_reg = 0;
- }
-
+ IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
+
#if 0 /* Not needed, now that we can always retry without inheritance. */
/* See if we have more mandatory reloads than spill regs.
If so, then we cannot risk optimizations that could prevent
@@ -5440,7 +5673,7 @@ choose_reload_regs (insn, avoid_return_reg)
unless it is equal to reload_in or reload_out, count such reloads. */
{
- int tem = SMALL_REGISTER_CLASSES? (avoid_return_reg != 0): 0;
+ int tem = 0;
for (j = 0; j < n_reloads; j++)
if (! reload_optional[j]
&& (reload_in[j] != 0 || reload_out[j] != 0 || reload_secondary_p[j])
@@ -5453,20 +5686,6 @@ choose_reload_regs (insn, avoid_return_reg)
}
#endif
- /* Don't use the subroutine call return reg for a reload
- if we are supposed to avoid it. */
- if (SMALL_REGISTER_CLASSES && avoid_return_reg)
- {
- int regno = REGNO (avoid_return_reg);
- int nregs
- = HARD_REGNO_NREGS (regno, GET_MODE (avoid_return_reg));
- int r;
-
- for (r = regno; r < regno + nregs; r++)
- if (spill_reg_order[r] >= 0)
- SET_HARD_REG_BIT (reload_reg_used, r);
- }
-
/* In order to be certain of getting the registers we need,
we must sort the reloads into order of increasing register class.
Then our grabbing of reload registers will parallel the process
@@ -5575,19 +5794,23 @@ choose_reload_regs (insn, avoid_return_reg)
for (j = 0; j < n_reloads; j++)
{
register int r = reload_order[j];
+ rtx search_equiv = NULL_RTX;
/* Ignore reloads that got marked inoperative. */
if (reload_out[r] == 0 && reload_in[r] == 0
&& ! reload_secondary_p[r])
continue;
- /* If find_reloads chose a to use reload_in or reload_out as a reload
+ /* If find_reloads chose to use reload_in or reload_out as a reload
register, we don't need to chose one. Otherwise, try even if it
found one since we might save an insn if we find the value lying
- around. */
+ around.
+ Try also when reload_in is a pseudo without a hard reg. */
if (reload_in[r] != 0 && reload_reg_rtx[r] != 0
&& (rtx_equal_p (reload_in[r], reload_reg_rtx[r])
- || rtx_equal_p (reload_out[r], reload_reg_rtx[r])))
+ || (rtx_equal_p (reload_out[r], reload_reg_rtx[r])
+ && GET_CODE (reload_in[r]) != MEM
+ && true_regnum (reload_in[r]) < FIRST_PSEUDO_REGISTER)))
continue;
#if 0 /* No longer needed for correct operation.
@@ -5603,7 +5826,7 @@ choose_reload_regs (insn, avoid_return_reg)
|| reload_secondary_p[reload_order[i]])
&& ! reload_optional[reload_order[i]]
&& reload_reg_rtx[reload_order[i]] == 0)
- allocate_reload_reg (reload_order[i], insn, 0, inheritance);
+ allocate_reload_reg (chain, reload_order[i], 0, inheritance);
#endif
/* First see if this pseudo is already available as reloaded
@@ -5622,6 +5845,7 @@ choose_reload_regs (insn, avoid_return_reg)
if (inheritance)
{
+ int word = 0;
register int regno = -1;
enum machine_mode mode;
@@ -5637,33 +5861,27 @@ choose_reload_regs (insn, avoid_return_reg)
regno = REGNO (reload_in_reg[r]);
mode = GET_MODE (reload_in_reg[r]);
}
- else if (GET_CODE (reload_in[r]) == MEM)
+ else if (GET_CODE (reload_in_reg[r]) == SUBREG
+ && GET_CODE (SUBREG_REG (reload_in_reg[r])) == REG)
{
- rtx prev = prev_nonnote_insn (insn), note;
-
- if (prev && GET_CODE (prev) == INSN
- && GET_CODE (PATTERN (prev)) == USE
- && GET_CODE (XEXP (PATTERN (prev), 0)) == REG
- && (REGNO (XEXP (PATTERN (prev), 0))
- >= FIRST_PSEUDO_REGISTER)
- && (note = find_reg_note (prev, REG_EQUAL, NULL_RTX))
- && GET_CODE (XEXP (note, 0)) == MEM)
- {
- rtx addr = XEXP (XEXP (note, 0), 0);
- int size_diff
- = (GET_MODE_SIZE (GET_MODE (addr))
- - GET_MODE_SIZE (GET_MODE (reload_in[r])));
- if (size_diff >= 0
- && rtx_equal_p ((BYTES_BIG_ENDIAN
- ? plus_constant (addr, size_diff)
- : addr),
- XEXP (reload_in[r], 0)))
- {
- regno = REGNO (XEXP (PATTERN (prev), 0));
- mode = GET_MODE (reload_in[r]);
- }
- }
+ word = SUBREG_WORD (reload_in_reg[r]);
+ regno = REGNO (SUBREG_REG (reload_in_reg[r]));
+ if (regno < FIRST_PSEUDO_REGISTER)
+ regno += word;
+ mode = GET_MODE (reload_in_reg[r]);
}
+#ifdef AUTO_INC_DEC
+ else if ((GET_CODE (reload_in_reg[r]) == PRE_INC
+ || GET_CODE (reload_in_reg[r]) == PRE_DEC
+ || GET_CODE (reload_in_reg[r]) == POST_INC
+ || GET_CODE (reload_in_reg[r]) == POST_DEC)
+ && GET_CODE (XEXP (reload_in_reg[r], 0)) == REG)
+ {
+ regno = REGNO (XEXP (reload_in_reg[r], 0));
+ mode = GET_MODE (XEXP (reload_in_reg[r], 0));
+ reload_out[r] = reload_in[r];
+ }
+#endif
#if 0
/* This won't work, since REGNO can be a pseudo reg number.
Also, it takes much more hair to keep track of all the things
@@ -5675,26 +5893,41 @@ choose_reload_regs (insn, avoid_return_reg)
if (regno >= 0 && reg_last_reload_reg[regno] != 0)
{
- i = REGNO (reg_last_reload_reg[regno]);
-
- if (reg_reloaded_contents[i] == regno
+ enum reg_class class = reload_reg_class[r], last_class;
+ rtx last_reg = reg_last_reload_reg[regno];
+
+ i = REGNO (last_reg) + word;
+ last_class = REGNO_REG_CLASS (i);
+ if ((GET_MODE_SIZE (GET_MODE (last_reg))
+ >= GET_MODE_SIZE (mode) + word * UNITS_PER_WORD)
+ && reg_reloaded_contents[i] == regno
&& TEST_HARD_REG_BIT (reg_reloaded_valid, i)
- && (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno]))
- >= GET_MODE_SIZE (mode))
&& HARD_REGNO_MODE_OK (i, reload_mode[r])
- && TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
- i)
+ && (TEST_HARD_REG_BIT (reg_class_contents[(int) class], i)
+ /* Even if we can't use this register as a reload
+ register, we might use it for reload_override_in,
+ if copying it to the desired class is cheap
+ enough. */
+ || ((REGISTER_MOVE_COST (last_class, class)
+ < MEMORY_MOVE_COST (mode, class, 1))
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+ && (SECONDARY_INPUT_RELOAD_CLASS (class, mode,
+ last_reg)
+ == NO_REGS)
+#endif
+#ifdef SECONDARY_MEMORY_NEEDED
+ && ! SECONDARY_MEMORY_NEEDED (last_class, class,
+ mode)
+#endif
+ ))
+
&& (reload_nregs[r] == max_group_size
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
i))
- && ((reload_reg_free_p (i, reload_opnum[r],
- reload_when_needed[r])
- && reload_reg_free_before_p (i, reload_opnum[r],
- reload_when_needed[r]))
- || reload_reg_free_for_value_p (i, reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r)))
+ && reload_reg_free_for_value_p (i, reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r],
+ const0_rtx, r, 1))
{
/* If a group is needed, verify that all the subsequent
registers still have their values intact. */
@@ -5711,6 +5944,9 @@ choose_reload_regs (insn, avoid_return_reg)
{
int i1;
+ last_reg = (GET_MODE (last_reg) == mode
+ ? last_reg : gen_rtx_REG (mode, i));
+
/* We found a register that contains the
value we need. If this register is the
same as an `earlyclobber' operand of the
@@ -5725,15 +5961,34 @@ choose_reload_regs (insn, avoid_return_reg)
break;
if (i1 != n_earlyclobbers
+ || ! (reload_reg_free_for_value_p
+ (i, reload_opnum[r], reload_when_needed[r],
+ reload_in[r], reload_out[r], r, 1))
/* Don't use it if we'd clobber a pseudo reg. */
- || (spill_reg_order[i] < 0
+ || (TEST_HARD_REG_BIT (reg_used_in_insn, i)
&& reload_out[r]
&& ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
+ /* Don't clobber the frame pointer. */
+ || (i == HARD_FRAME_POINTER_REGNUM
+ && reload_out[r])
/* Don't really use the inherited spill reg
if we need it wider than we've got it. */
|| (GET_MODE_SIZE (reload_mode[r])
- > GET_MODE_SIZE (mode)))
- reload_override_in[r] = reg_last_reload_reg[regno];
+ > GET_MODE_SIZE (mode))
+ || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
+ i)
+
+ /* If find_reloads chose reload_out as reload
+ register, stay with it - that leaves the
+ inherited register for subsequent reloads. */
+ || (reload_out[r] && reload_reg_rtx[r]
+ && rtx_equal_p (reload_out[r],
+ reload_reg_rtx[r])))
+ {
+ reload_override_in[r] = last_reg;
+ reload_inheritance_insn[r]
+ = reg_reloaded_insn[i];
+ }
else
{
int k;
@@ -5744,7 +5999,7 @@ choose_reload_regs (insn, avoid_return_reg)
reload_opnum[r],
reload_when_needed[r],
reload_mode[r]);
- reload_reg_rtx[r] = reg_last_reload_reg[regno];
+ reload_reg_rtx[r] = last_reg;
reload_inherited[r] = 1;
reload_inheritance_insn[r]
= reg_reloaded_insn[i];
@@ -5769,9 +6024,23 @@ choose_reload_regs (insn, avoid_return_reg)
|| GET_CODE (reload_in[r]) == MEM)
&& (reload_nregs[r] == max_group_size
|| ! reg_classes_intersect_p (reload_reg_class[r], group_class)))
+ search_equiv = reload_in[r];
+ /* If this is an output reload from a simple move insn, look
+ if an equivalence for the input is available. */
+ else if (inheritance && reload_in[r] == 0 && reload_out[r] != 0)
+ {
+ rtx set = single_set (insn);
+
+ if (set
+ && rtx_equal_p (reload_out[r], SET_DEST (set))
+ && CONSTANT_P (SET_SRC (set)))
+ search_equiv = SET_SRC (set);
+ }
+
+ if (search_equiv)
{
register rtx equiv
- = find_equiv_reg (reload_in[r], insn, reload_reg_class[r],
+ = find_equiv_reg (search_equiv, insn, reload_reg_class[r],
-1, NULL_PTR, 0, reload_mode[r]);
int regno;
@@ -5795,21 +6064,15 @@ choose_reload_regs (insn, avoid_return_reg)
/* If we found a spill reg, reject it unless it is free
and of the desired class. */
if (equiv != 0
- && ((spill_reg_order[regno] >= 0
- && ! (reload_reg_free_before_p (regno, reload_opnum[r],
- reload_when_needed[r])
- || reload_reg_free_for_value_p (regno,
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r)))
+ && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
+ && ! reload_reg_free_for_value_p (regno, reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r],
+ reload_out[r], r, 1))
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
regno)))
equiv = 0;
- if (equiv != 0 && TEST_HARD_REG_BIT (reload_reg_used_at_all, regno))
- equiv = 0;
-
if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, reload_mode[r]))
equiv = 0;
@@ -5922,7 +6185,7 @@ choose_reload_regs (insn, avoid_return_reg)
if (i == n_reloads)
continue;
- allocate_reload_reg (r, insn, j == n_reloads - 1, inheritance);
+ allocate_reload_reg (chain, r, j == n_reloads - 1, inheritance);
#endif
}
@@ -5941,7 +6204,7 @@ choose_reload_regs (insn, avoid_return_reg)
if (reload_reg_rtx[r] != 0 || reload_optional[r])
continue;
- if (! allocate_reload_reg (r, insn, j == n_reloads - 1, inheritance))
+ if (! allocate_reload_reg (chain, r, j == n_reloads - 1, inheritance))
break;
}
@@ -5949,7 +6212,6 @@ choose_reload_regs (insn, avoid_return_reg)
if (j == n_reloads)
break;
- fail:
/* Loop around and try without any inheritance. */
/* First undo everything done by the failed attempt
to allocate with inheritance. */
@@ -5994,75 +6256,56 @@ choose_reload_regs (insn, avoid_return_reg)
/* If we thought we could inherit a reload, because it seemed that
nothing else wanted the same reload register earlier in the insn,
- verify that assumption, now that all reloads have been assigned. */
+ verify that assumption, now that all reloads have been assigned.
+ Likewise for reloads where reload_override_in has been set. */
- for (j = 0; j < n_reloads; j++)
+ /* If doing expensive optimizations, do one preliminary pass that doesn't
+ cancel any inheritance, but removes reloads that have been needed only
+ for reloads that we know can be inherited. */
+ for (pass = flag_expensive_optimizations; pass >= 0; pass--)
{
- register int r = reload_order[j];
-
- if (reload_inherited[r] && reload_reg_rtx[r] != 0
- && ! (reload_reg_free_before_p (true_regnum (reload_reg_rtx[r]),
- reload_opnum[r],
- reload_when_needed[r])
- || reload_reg_free_for_value_p (true_regnum (reload_reg_rtx[r]),
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r)))
- reload_inherited[r] = 0;
- /* If we can inherit a RELOAD_FOR_INPUT, then we do not need its related
- RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS reloads.
- ??? This could be extended to other reload types, but these are
- more tricky to handle:
- RELOAD_FOR_OTHER_ADDRESS reloads might have been merged, so we
- can't eliminate them without a check that *all* references are
- now unused due to inheritance.
- While RELOAD_FOR_INPADDR_ADDRESS and RELOAD_FOR_OUTADDR_ADDRESS are
- not merged, we can't be sure that we have eliminated the use of
- that particular reload if we have seen just one
- RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_OUTPUT_ADDRESS being inherited,
- since there might be multiple of the latter two reloads for a single
- operand.
- RELOAD_FOR_OPADDR_ADDR reloads for different operands are not
- merged, but might share the same register by courtesy of
- reload_reg_free_for_value_p. reload_reg_used_in_op_addr_reload
- does not differentiate by opnum, thus calling clear_reload_reg_in_use
- for one of these reloads would mark the register as free even though
- another RELOAD_FOR_OPADDR_ADDR reload might still use it. */
- else if (reload_inherited[r] && reload_when_needed[r] == RELOAD_FOR_INPUT)
+ for (j = 0; j < n_reloads; j++)
{
- for (i = 0; i < n_reloads; i++)
+ register int r = reload_order[j];
+ rtx check_reg;
+ if (reload_inherited[r] && reload_reg_rtx[r])
+ check_reg = reload_reg_rtx[r];
+ else if (reload_override_in[r]
+ && (GET_CODE (reload_override_in[r]) == REG
+ || GET_CODE (reload_override_in[r]) == SUBREG))
+ check_reg = reload_override_in[r];
+ else
+ continue;
+ if (! reload_reg_free_for_value_p (true_regnum (check_reg),
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r],
+ (reload_inherited[r]
+ ? reload_out[r] : const0_rtx),
+ r, 1))
{
- if ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
- || reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS)
- && reload_opnum[i] == reload_opnum[r]
- && reload_in[i] && reload_reg_rtx[i])
- {
- int regno = true_regnum (reload_reg_rtx[i]);
-
- reload_in[i] = 0;
- if (spill_reg_order[regno] >= 0)
- clear_reload_reg_in_use (regno, reload_opnum[i],
- reload_when_needed[i],
- reload_mode[i]);
- reload_reg_rtx[i] = 0;
- reload_spill_index[i] = -1;
- remove_replacements (i);
- }
+ if (pass)
+ continue;
+ reload_inherited[r] = 0;
+ reload_override_in[r] = 0;
}
- }
-
- /* If we found a better place to reload from,
- validate it in the same fashion, if it is a reload reg. */
- if (reload_override_in[r]
- && (GET_CODE (reload_override_in[r]) == REG
- || GET_CODE (reload_override_in[r]) == SUBREG))
- {
- int regno = true_regnum (reload_override_in[r]);
- if (spill_reg_order[regno] >= 0
- && ! reload_reg_free_before_p (regno, reload_opnum[r],
- reload_when_needed[r]))
- reload_override_in[r] = 0;
+ /* If we can inherit a RELOAD_FOR_INPUT, or can use a
+ reload_override_in, then we do not need its related
+ RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS reloads;
+ likewise for other reload types.
+ We handle this by removing a reload when its only replacement
+ is mentioned in reload_in of the reload we are going to inherit.
+ A special case are auto_inc expressions; even if the input is
+ inherited, we still need the address for the output. We can
+ recognize them because they have RELOAD_OUT set but not
+ RELOAD_OUT_REG.
+ If we suceeded removing some reload and we are doing a preliminary
+ pass just to remove such reloads, make another pass, since the
+ removal of one reload might allow us to inherit another one. */
+ else if ((! reload_out[r] || reload_out_reg[r])
+ && reload_in[r]
+ && remove_address_replacements (reload_in[r]) && pass)
+ pass = 2;
}
}
@@ -6099,10 +6342,10 @@ choose_reload_regs (insn, avoid_return_reg)
/* I is nonneg if this reload uses a register.
If reload_reg_rtx[r] is 0, this is an optional reload
that we opted to ignore. */
- if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG
+ if (reload_out_reg[r] != 0 && GET_CODE (reload_out_reg[r]) == REG
&& reload_reg_rtx[r] != 0)
{
- register int nregno = REGNO (reload_out[r]);
+ register int nregno = REGNO (reload_out_reg[r]);
int nr = 1;
if (nregno < FIRST_PSEUDO_REGISTER)
@@ -6125,6 +6368,24 @@ choose_reload_regs (insn, avoid_return_reg)
}
}
}
+
+/* Deallocate the reload register for reload R. This is called from
+ remove_address_replacements. */
+void
+deallocate_reload_reg (r)
+ int r;
+{
+ int regno;
+
+ if (! reload_reg_rtx[r])
+ return;
+ regno = true_regnum (reload_reg_rtx[r]);
+ reload_reg_rtx[r] = 0;
+ if (spill_reg_order[regno] >= 0)
+ clear_reload_reg_in_use (regno, reload_opnum[r], reload_when_needed[r],
+ reload_mode[r]);
+ reload_spill_index[r] = -1;
+}
/* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
reloads of the same item for fear that we might not have enough reload
@@ -6240,9 +6501,11 @@ merge_assigned_reloads (insn)
/* Output insns to reload values in and out of the chosen reload regs. */
static void
-emit_reload_insns (insn)
- rtx insn;
+emit_reload_insns (chain)
+ struct insn_chain *chain;
{
+ rtx insn = chain->insn;
+
register int j;
rtx input_reload_insns[MAX_RECOG_OPERANDS];
rtx other_input_address_reload_insns = 0;
@@ -6256,7 +6519,7 @@ emit_reload_insns (insn)
rtx other_operand_reload_insns = 0;
rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
rtx following_insn = NEXT_INSN (insn);
- rtx before_insn = insn;
+ rtx before_insn = PREV_INSN (insn);
int special;
/* Values to be put in spill_reg_store are put here first. */
rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
@@ -6283,11 +6546,17 @@ emit_reload_insns (insn)
rtx this_reload_insn = 0;
int expect_occurrences = 1;
- if (reload_spill_index[j] >= 0)
- new_spill_reg_store[reload_spill_index[j]] = 0;
+ if (reload_reg_rtx[j]
+ && REGNO (reload_reg_rtx[j]) < FIRST_PSEUDO_REGISTER)
+ new_spill_reg_store[REGNO (reload_reg_rtx[j])] = 0;
- old = reload_in[j];
- if (old != 0 && ! reload_inherited[j]
+ old = (reload_in[j] && GET_CODE (reload_in[j]) == MEM
+ ? reload_in_reg[j] : reload_in[j]);
+
+ if (old != 0
+ /* AUTO_INC reloads need to be handled even if inherited. We got an
+ AUTO_INC reload if reload_out is set but reload_out_reg isn't. */
+ && (! reload_inherited[j] || (reload_out[j] && ! reload_out_reg[j]))
&& ! rtx_equal_p (reload_reg_rtx[j], old)
&& reload_reg_rtx[j] != 0)
{
@@ -6367,31 +6636,14 @@ emit_reload_insns (insn)
{
int regno = true_regnum (oldequiv);
- /* If OLDEQUIV is a spill register, don't use it for this
- if any other reload needs it at an earlier stage of this insn
- or at this stage. */
- if (spill_reg_order[regno] >= 0
- && (! reload_reg_free_p (regno, reload_opnum[j],
- reload_when_needed[j])
- || ! reload_reg_free_before_p (regno, reload_opnum[j],
- reload_when_needed[j])))
+ /* Don't use OLDEQUIV if any other reload changes it at an
+ earlier stage of this insn or at this stage. */
+ if (! reload_reg_free_for_value_p (regno, reload_opnum[j],
+ reload_when_needed[j],
+ reload_in[j], const0_rtx, j,
+ 0))
oldequiv = 0;
- /* If OLDEQUIV is not a spill register,
- don't use it if any other reload wants it. */
- if (spill_reg_order[regno] < 0)
- {
- int k;
- for (k = 0; k < n_reloads; k++)
- if (reload_reg_rtx[k] != 0 && k != j
- && reg_overlap_mentioned_for_reload_p (reload_reg_rtx[k],
- oldequiv))
- {
- oldequiv = 0;
- break;
- }
- }
-
/* If it is no cheaper to copy from OLDEQUIV into the
reload register than it would be to move from memory,
don't use it. Likewise, if we need a secondary register
@@ -6416,6 +6668,17 @@ emit_reload_insns (insn)
oldequiv = 0;
}
+ /* delete_output_reload is only invoked properly if old contains
+ the original pseudo register. Since this is replaced with a
+ hard reg when RELOAD_OVERRIDE_IN is set, see if we can
+ find the pseudo in RELOAD_IN_REG. */
+ if (oldequiv == 0
+ && reload_override_in[j]
+ && GET_CODE (reload_in_reg[j]) == REG)
+ {
+ oldequiv = old;
+ old = reload_in_reg[j];
+ }
if (oldequiv == 0)
oldequiv = old;
else if (GET_CODE (oldequiv) == REG)
@@ -6430,11 +6693,11 @@ emit_reload_insns (insn)
if (optimize && GET_CODE (oldequiv) == REG
&& REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
&& spill_reg_store[REGNO (oldequiv)]
- && GET_CODE (old) == REG && dead_or_set_p (insn, old)
- /* This is unsafe if operand occurs more than once in current
- insn. Perhaps some occurrences weren't reloaded. */
- && count_occurrences (PATTERN (insn), old) == 1)
- delete_output_reload (insn, j, spill_reg_store[REGNO (oldequiv)]);
+ && GET_CODE (old) == REG
+ && (dead_or_set_p (insn, spill_reg_stored_to[REGNO (oldequiv)])
+ || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
+ reload_out_reg[j])))
+ delete_output_reload (insn, j, REGNO (oldequiv));
/* Encapsulate both RELOADREG and OLDEQUIV into that mode,
then load RELOADREG from OLDEQUIV. Note that we cannot use
@@ -6488,20 +6751,35 @@ emit_reload_insns (insn)
special = 0;
/* Auto-increment addresses must be reloaded in a special way. */
- if (GET_CODE (oldequiv) == POST_INC
- || GET_CODE (oldequiv) == POST_DEC
- || GET_CODE (oldequiv) == PRE_INC
- || GET_CODE (oldequiv) == PRE_DEC)
+ if (reload_out[j] && ! reload_out_reg[j])
{
/* We are not going to bother supporting the case where a
incremented register can't be copied directly from
OLDEQUIV since this seems highly unlikely. */
if (reload_secondary_in_reload[j] >= 0)
abort ();
+
+ if (reload_inherited[j])
+ oldequiv = reloadreg;
+
+ old = XEXP (reload_in_reg[j], 0);
+
+ if (optimize && GET_CODE (oldequiv) == REG
+ && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
+ && spill_reg_store[REGNO (oldequiv)]
+ && GET_CODE (old) == REG
+ && (dead_or_set_p (insn,
+ spill_reg_stored_to[REGNO (oldequiv)])
+ || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
+ old)))
+ delete_output_reload (insn, j, REGNO (oldequiv));
+
/* Prevent normal processing of this reload. */
special = 1;
/* Output a special code sequence for this case. */
- inc_for_reload (reloadreg, oldequiv, reload_inc[j]);
+ new_spill_reg_store[REGNO (reloadreg)]
+ = inc_for_reload (reloadreg, oldequiv, reload_out[j],
+ reload_inc[j]);
}
/* If we are reloading a pseudo-register that was set by the previous
@@ -6513,9 +6791,11 @@ emit_reload_insns (insn)
&& dead_or_set_p (insn, old)
/* This is unsafe if some other reload
uses the same reg first. */
- && reload_reg_free_before_p (REGNO (reloadreg),
- reload_opnum[j],
- reload_when_needed[j]))
+ && reload_reg_free_for_value_p (REGNO (reloadreg),
+ reload_opnum[j],
+ reload_when_needed[j],
+ old, reload_out[j],
+ j, 0))
{
rtx temp = PREV_INSN (insn);
while (temp && GET_CODE (temp) == NOTE)
@@ -6537,6 +6817,18 @@ emit_reload_insns (insn)
{
/* Store into the reload register instead of the pseudo. */
SET_DEST (PATTERN (temp)) = reloadreg;
+
+ /* If the previous insn is an output reload, the source is
+ a reload register, and its spill_reg_store entry will
+ contain the previous destination. This is now
+ invalid. */
+ if (GET_CODE (SET_SRC (PATTERN (temp))) == REG
+ && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
+ {
+ spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+ spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+ }
+
/* If these are the only uses of the pseudo reg,
pretend for GDB it lives in the reload reg we used. */
if (REG_N_DEATHS (REGNO (old)) == 1
@@ -6573,19 +6865,52 @@ emit_reload_insns (insn)
int secondary_reload = reload_secondary_in_reload[j];
rtx real_oldequiv = oldequiv;
rtx real_old = old;
+ rtx tmp;
/* If OLDEQUIV is a pseudo with a MEM, get the real MEM
and similarly for OLD.
See comments in get_secondary_reload in reload.c. */
- if (GET_CODE (oldequiv) == REG
- && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_mem[REGNO (oldequiv)] != 0)
- real_oldequiv = reg_equiv_mem[REGNO (oldequiv)];
+ /* If it is a pseudo that cannot be replaced with its
+ equivalent MEM, we must fall back to reload_in, which
+ will have all the necessary substitutions registered.
+ Likewise for a pseudo that can't be replaced with its
+ equivalent constant.
+
+ Take extra care for subregs of such pseudos. Note that
+ we cannot use reg_equiv_mem in this case because it is
+ not in the right mode. */
+
+ tmp = oldequiv;
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG
+ && REGNO (tmp) >= FIRST_PSEUDO_REGISTER
+ && (reg_equiv_memory_loc[REGNO (tmp)] != 0
+ || reg_equiv_constant[REGNO (tmp)] != 0))
+ {
+ if (! reg_equiv_mem[REGNO (tmp)]
+ || num_not_at_initial_offset
+ || GET_CODE (oldequiv) == SUBREG)
+ real_oldequiv = reload_in[j];
+ else
+ real_oldequiv = reg_equiv_mem[REGNO (tmp)];
+ }
- if (GET_CODE (old) == REG
- && REGNO (old) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_mem[REGNO (old)] != 0)
- real_old = reg_equiv_mem[REGNO (old)];
+ tmp = old;
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG
+ && REGNO (tmp) >= FIRST_PSEUDO_REGISTER
+ && (reg_equiv_memory_loc[REGNO (tmp)] != 0
+ || reg_equiv_constant[REGNO (tmp)] != 0))
+ {
+ if (! reg_equiv_mem[REGNO (tmp)]
+ || num_not_at_initial_offset
+ || GET_CODE (old) == SUBREG)
+ real_old = reload_in[j];
+ else
+ real_old = reg_equiv_mem[REGNO (tmp)];
+ }
second_reload_reg = reload_reg_rtx[secondary_reload];
icode = reload_secondary_in_icode[j];
@@ -6670,7 +6995,7 @@ emit_reload_insns (insn)
third_reload_reg)));
}
else
- gen_reload (second_reload_reg, oldequiv,
+ gen_reload (second_reload_reg, real_oldequiv,
reload_opnum[j],
reload_when_needed[j]);
@@ -6681,37 +7006,37 @@ emit_reload_insns (insn)
#endif
if (! special && ! rtx_equal_p (reloadreg, oldequiv))
- gen_reload (reloadreg, oldequiv, reload_opnum[j],
- reload_when_needed[j]);
-
-#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
- register in the insns we just made. Find the last insn that
- mentioned the register. */
- if (! special && second_reload_reg
- && PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reload_reg)))
{
- rtx prev;
+ rtx real_oldequiv = oldequiv;
- for (prev = get_last_insn (); prev;
- prev = PREV_INSN (prev))
- if (GET_RTX_CLASS (GET_CODE (prev) == 'i')
- && reg_overlap_mentioned_for_reload_p (second_reload_reg,
- PATTERN (prev)))
- {
- REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_DEAD,
- second_reload_reg,
- REG_NOTES (prev));
- break;
- }
+ if ((GET_CODE (oldequiv) == REG
+ && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
+ && (reg_equiv_memory_loc[REGNO (oldequiv)] != 0
+ || reg_equiv_constant[REGNO (oldequiv)] != 0))
+ || (GET_CODE (oldequiv) == SUBREG
+ && GET_CODE (SUBREG_REG (oldequiv)) == REG
+ && (REGNO (SUBREG_REG (oldequiv))
+ >= FIRST_PSEUDO_REGISTER)
+ && ((reg_equiv_memory_loc
+ [REGNO (SUBREG_REG (oldequiv))] != 0)
+ || (reg_equiv_constant
+ [REGNO (SUBREG_REG (oldequiv))] != 0))))
+ real_oldequiv = reload_in[j];
+ gen_reload (reloadreg, real_oldequiv, reload_opnum[j],
+ reload_when_needed[j]);
}
-#endif
+
}
this_reload_insn = get_last_insn ();
/* End this sequence. */
*where = get_insns ();
end_sequence ();
+
+ /* Update reload_override_in so that delete_address_reloads_1
+ can see the actual register usage. */
+ if (oldequiv_reg)
+ reload_override_in[j] = oldequiv;
}
/* When inheriting a wider reload, we have a MEM in reload_in[j],
@@ -6719,6 +7044,7 @@ emit_reload_insns (insn)
(mem:HI (plus:SI (reg:SI 14 fp) (const_int 10))) */
if (optimize && reload_inherited[j] && reload_in[j]
&& GET_CODE (reload_in[j]) == MEM
+ && GET_CODE (reload_in_reg[j]) == MEM
&& reload_spill_index[j] >= 0
&& TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
{
@@ -6727,143 +7053,31 @@ emit_reload_insns (insn)
reload_in[j]
= regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
}
- /* Add a note saying the input reload reg
- dies in this insn, if anyone cares. */
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- if (old != 0
- && reload_reg_rtx[j] != old
- && reload_reg_rtx[j] != 0
- && reload_out[j] == 0
- && ! reload_inherited[j]
- && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j])))
- {
- register rtx reloadreg = reload_reg_rtx[j];
-
-#if 0
- /* We can't abort here because we need to support this for sched.c.
- It's not terrible to miss a REG_DEAD note, but we should try
- to figure out how to do this correctly. */
- /* The code below is incorrect for address-only reloads. */
- if (reload_when_needed[j] != RELOAD_OTHER
- && reload_when_needed[j] != RELOAD_FOR_INPUT)
- abort ();
-#endif
-
- /* Add a death note to this insn, for an input reload. */
-
- if ((reload_when_needed[j] == RELOAD_OTHER
- || reload_when_needed[j] == RELOAD_FOR_INPUT)
- && ! dead_or_set_p (insn, reloadreg))
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_DEAD,
- reloadreg, REG_NOTES (insn));
- }
-
- /* When we inherit a reload, the last marked death of the reload reg
- may no longer really be a death. */
- if (reload_reg_rtx[j] != 0
- && PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j]))
- && reload_inherited[j])
- {
- /* Handle inheriting an output reload.
- Remove the death note from the output reload insn. */
- if (reload_spill_index[j] >= 0
- && GET_CODE (reload_in[j]) == REG
- && spill_reg_store[reload_spill_index[j]] != 0
- && find_regno_note (spill_reg_store[reload_spill_index[j]],
- REG_DEAD, REGNO (reload_reg_rtx[j])))
- remove_death (REGNO (reload_reg_rtx[j]),
- spill_reg_store[reload_spill_index[j]]);
- /* Likewise for input reloads that were inherited. */
- else if (reload_spill_index[j] >= 0
- && GET_CODE (reload_in[j]) == REG
- && spill_reg_store[reload_spill_index[j]] == 0
- && reload_inheritance_insn[j] != 0
- && find_regno_note (reload_inheritance_insn[j], REG_DEAD,
- REGNO (reload_reg_rtx[j])))
- remove_death (REGNO (reload_reg_rtx[j]),
- reload_inheritance_insn[j]);
- else
- {
- rtx prev;
-
- /* We got this register from find_equiv_reg.
- Search back for its last death note and get rid of it.
- But don't search back too far.
- Don't go past a place where this reg is set,
- since a death note before that remains valid. */
- for (prev = PREV_INSN (insn);
- prev && GET_CODE (prev) != CODE_LABEL;
- prev = PREV_INSN (prev))
- if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
- && dead_or_set_p (prev, reload_reg_rtx[j]))
- {
- if (find_regno_note (prev, REG_DEAD,
- REGNO (reload_reg_rtx[j])))
- remove_death (REGNO (reload_reg_rtx[j]), prev);
- break;
- }
- }
- }
-
- /* We might have used find_equiv_reg above to choose an alternate
- place from which to reload. If so, and it died, we need to remove
- that death and move it to one of the insns we just made. */
-
- if (oldequiv_reg != 0
- && PRESERVE_DEATH_INFO_REGNO_P (true_regnum (oldequiv_reg)))
- {
- rtx prev, prev1;
-
- for (prev = PREV_INSN (insn); prev && GET_CODE (prev) != CODE_LABEL;
- prev = PREV_INSN (prev))
- if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
- && dead_or_set_p (prev, oldequiv_reg))
- {
- if (find_regno_note (prev, REG_DEAD, REGNO (oldequiv_reg)))
- {
- for (prev1 = this_reload_insn;
- prev1; prev1 = PREV_INSN (prev1))
- if (GET_RTX_CLASS (GET_CODE (prev1) == 'i')
- && reg_overlap_mentioned_for_reload_p (oldequiv_reg,
- PATTERN (prev1)))
- {
- REG_NOTES (prev1) = gen_rtx_EXPR_LIST (REG_DEAD,
- oldequiv_reg,
- REG_NOTES (prev1));
- break;
- }
- remove_death (REGNO (oldequiv_reg), prev);
- }
- break;
- }
- }
-#endif
/* If we are reloading a register that was recently stored in with an
output-reload, see if we can prove there was
actually no need to store the old value in it. */
- if (optimize && reload_inherited[j] && reload_spill_index[j] >= 0
- && reload_in[j] != 0
- && GET_CODE (reload_in[j]) == REG
+ if (optimize
+ && (reload_inherited[j] || reload_override_in[j])
+ && reload_reg_rtx[j]
+ && GET_CODE (reload_reg_rtx[j]) == REG
+ && spill_reg_store[REGNO (reload_reg_rtx[j])] != 0
#if 0
/* There doesn't seem to be any reason to restrict this to pseudos
and doing so loses in the case where we are copying from a
register of the wrong class. */
- && REGNO (reload_in[j]) >= FIRST_PSEUDO_REGISTER
+ && REGNO (spill_reg_stored_to[REGNO (reload_reg_rtx[j])])
+ >= FIRST_PSEUDO_REGISTER
#endif
- && spill_reg_store[reload_spill_index[j]] != 0
- /* This is unsafe if some other reload uses the same reg first. */
- && reload_reg_free_before_p (reload_spill_index[j],
- reload_opnum[j], reload_when_needed[j])
- && dead_or_set_p (insn, reload_in[j])
- /* This is unsafe if operand occurs more than once in current
- insn. Perhaps some occurrences weren't reloaded. */
- && (count_occurrences (PATTERN (insn), reload_in[j])
- == expect_occurrences))
- delete_output_reload (insn, j,
- spill_reg_store[reload_spill_index[j]]);
+ /* The insn might have already some references to stackslots
+ replaced by MEMs, while reload_out_reg still names the
+ original pseudo. */
+ && (dead_or_set_p (insn,
+ spill_reg_stored_to[REGNO (reload_reg_rtx[j])])
+ || rtx_equal_p (spill_reg_stored_to[REGNO (reload_reg_rtx[j])],
+ reload_out_reg[j])))
+ delete_output_reload (insn, j, REGNO (reload_reg_rtx[j]));
/* Input-reloading is done. Now do output-reloading,
storing the value from the reload-register after the main insn
@@ -6871,7 +7085,33 @@ emit_reload_insns (insn)
??? At some point we need to support handling output reloads of
JUMP_INSNs or insns that set cc0. */
- old = reload_out[j];
+
+ /* If this is an output reload that stores something that is
+ not loaded in this same reload, see if we can eliminate a previous
+ store. */
+ {
+ rtx pseudo = reload_out_reg[j];
+
+ if (pseudo
+ && GET_CODE (pseudo) == REG
+ && ! rtx_equal_p (reload_in_reg[j], pseudo)
+ && REGNO (pseudo) >= FIRST_PSEUDO_REGISTER
+ && reg_last_reload_reg[REGNO (pseudo)])
+ {
+ int pseudo_no = REGNO (pseudo);
+ int last_regno = REGNO (reg_last_reload_reg[pseudo_no]);
+
+ /* We don't need to test full validity of last_regno for
+ inherit here; we only want to know if the store actually
+ matches the pseudo. */
+ if (reg_reloaded_contents[last_regno] == pseudo_no
+ && spill_reg_store[last_regno]
+ && rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
+ delete_output_reload (insn, j, last_regno);
+ }
+ }
+
+ old = reload_out_reg[j];
if (old != 0
&& reload_reg_rtx[j] != old
&& reload_reg_rtx[j] != 0)
@@ -6927,6 +7167,8 @@ emit_reload_insns (insn)
else
push_to_sequence (output_reload_insns[reload_opnum[j]]);
+ old = reload_out[j];
+
/* Determine the mode to reload in.
See comments above (for input reloading). */
@@ -7043,30 +7285,6 @@ emit_reload_insns (insn)
reload_when_needed[j]);
}
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- /* If final will look at death notes for this reg,
- put one on the last output-reload insn to use it. Similarly
- for any secondary register. */
- if (PRESERVE_DEATH_INFO_REGNO_P (REGNO (reloadreg)))
- for (p = get_last_insn (); p; p = PREV_INSN (p))
- if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
- && reg_overlap_mentioned_for_reload_p (reloadreg,
- PATTERN (p)))
- REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
- reloadreg, REG_NOTES (p));
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- if (! special && second_reloadreg
- && PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reloadreg)))
- for (p = get_last_insn (); p; p = PREV_INSN (p))
- if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
- && reg_overlap_mentioned_for_reload_p (second_reloadreg,
- PATTERN (p)))
- REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
- second_reloadreg,
- REG_NOTES (p));
-#endif
-#endif
/* Look at all insns we emitted, just to be safe. */
for (p = get_insns (); p; p = NEXT_INSN (p))
if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
@@ -7081,21 +7299,22 @@ emit_reload_insns (insn)
if (reg_mentioned_p (reload_reg_rtx[j], pat))
{
+ rtx set = single_set (insn);
if (reload_spill_index[j] < 0
- && GET_CODE (pat) == SET
- && SET_SRC (pat) == reload_reg_rtx[j])
+ && set
+ && SET_SRC (set) == reload_reg_rtx[j])
{
- int src = REGNO (SET_SRC (pat));
+ int src = REGNO (SET_SRC (set));
reload_spill_index[j] = src;
SET_HARD_REG_BIT (reg_is_output_reload, src);
if (find_regno_note (insn, REG_DEAD, src))
SET_HARD_REG_BIT (reg_reloaded_died, src);
}
- if (reload_spill_index[j] >= 0)
+ if (REGNO (reload_reg_rtx[j]) < FIRST_PSEUDO_REGISTER)
{
int s = reload_secondary_out_reload[j];
- rtx set = single_set (p);
+ set = single_set (p);
/* If this reload copies only to the secondary reload
register, the secondary reload does the actual
store. */
@@ -7114,13 +7333,18 @@ emit_reload_insns (insn)
rtx s_reg = reload_reg_rtx[s];
rtx next = NEXT_INSN (p);
reload_out[s] = reload_out[j];
+ reload_out_reg[s] = reload_out_reg[j];
set = single_set (next);
if (set && SET_SRC (set) == s_reg
&& ! new_spill_reg_store[REGNO (s_reg)])
- new_spill_reg_store[REGNO (s_reg)] = next;
+ {
+ SET_HARD_REG_BIT (reg_is_output_reload,
+ REGNO (s_reg));
+ new_spill_reg_store[REGNO (s_reg)] = next;
+ }
}
else
- new_spill_reg_store[reload_spill_index[j]] = p;
+ new_spill_reg_store[REGNO (reload_reg_rtx[j])] = p;
}
}
}
@@ -7161,18 +7385,18 @@ emit_reload_insns (insn)
reloads for the operand. The RELOAD_OTHER output reloads are
output in descending order by reload number. */
- emit_insns_before (other_input_address_reload_insns, before_insn);
- emit_insns_before (other_input_reload_insns, before_insn);
+ emit_insns_before (other_input_address_reload_insns, insn);
+ emit_insns_before (other_input_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
- emit_insns_before (inpaddr_address_reload_insns[j], before_insn);
- emit_insns_before (input_address_reload_insns[j], before_insn);
- emit_insns_before (input_reload_insns[j], before_insn);
+ emit_insns_before (inpaddr_address_reload_insns[j], insn);
+ emit_insns_before (input_address_reload_insns[j], insn);
+ emit_insns_before (input_reload_insns[j], insn);
}
- emit_insns_before (other_operand_reload_insns, before_insn);
- emit_insns_before (operand_reload_insns, before_insn);
+ emit_insns_before (other_operand_reload_insns, insn);
+ emit_insns_before (operand_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
@@ -7182,49 +7406,14 @@ emit_reload_insns (insn)
emit_insns_before (other_output_reload_insns[j], following_insn);
}
- /* Move death notes from INSN
- to output-operand-address and output reload insns. */
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- {
- rtx insn1;
- /* Loop over those insns, last ones first. */
- for (insn1 = PREV_INSN (following_insn); insn1 != insn;
- insn1 = PREV_INSN (insn1))
- if (GET_CODE (insn1) == INSN && GET_CODE (PATTERN (insn1)) == SET)
- {
- rtx source = SET_SRC (PATTERN (insn1));
- rtx dest = SET_DEST (PATTERN (insn1));
-
- /* The note we will examine next. */
- rtx reg_notes = REG_NOTES (insn);
- /* The place that pointed to this note. */
- rtx *prev_reg_note = &REG_NOTES (insn);
-
- /* If the note is for something used in the source of this
- reload insn, or in the output address, move the note. */
- while (reg_notes)
- {
- rtx next_reg_notes = XEXP (reg_notes, 1);
- if (REG_NOTE_KIND (reg_notes) == REG_DEAD
- && GET_CODE (XEXP (reg_notes, 0)) == REG
- && ((GET_CODE (dest) != REG
- && reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
- dest))
- || reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
- source)))
- {
- *prev_reg_note = next_reg_notes;
- XEXP (reg_notes, 1) = REG_NOTES (insn1);
- REG_NOTES (insn1) = reg_notes;
- }
- else
- prev_reg_note = &XEXP (reg_notes, 1);
-
- reg_notes = next_reg_notes;
- }
- }
- }
-#endif
+ /* Keep basic block info up to date. */
+ if (n_basic_blocks)
+ {
+ if (BLOCK_HEAD (chain->block) == insn)
+ BLOCK_HEAD (chain->block) = NEXT_INSN (before_insn);
+ if (BLOCK_END (chain->block) == insn)
+ BLOCK_END (chain->block) = PREV_INSN (following_insn);
+ }
/* For all the spill regs newly reloaded in this instruction,
record what they were reloaded from, so subsequent instructions
@@ -7238,6 +7427,34 @@ emit_reload_insns (insn)
register int r = reload_order[j];
register int i = reload_spill_index[r];
+ /* If this is a non-inherited input reload from a pseudo, we must
+ clear any memory of a previous store to the same pseudo. Only do
+ something if there will not be an output reload for the pseudo
+ being reloaded. */
+ if (reload_in_reg[r] != 0
+ && ! (reload_inherited[r] || reload_override_in[r]))
+ {
+ rtx reg = reload_in_reg[r];
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+
+ if (GET_CODE (reg) == REG
+ && REGNO (reg) >= FIRST_PSEUDO_REGISTER
+ && ! reg_has_output_reload[REGNO (reg)])
+ {
+ int nregno = REGNO (reg);
+
+ if (reg_last_reload_reg[nregno])
+ {
+ int last_regno = REGNO (reg_last_reload_reg[nregno]);
+
+ if (reg_reloaded_contents[last_regno] == nregno)
+ spill_reg_store[last_regno] = 0;
+ }
+ }
+ }
+
/* I is nonneg if this reload used a register.
If reload_reg_rtx[r] is 0, this is an optional reload
that we opted to ignore. */
@@ -7272,14 +7489,25 @@ emit_reload_insns (insn)
CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
/* Maybe the spill reg contains a copy of reload_out. */
- if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
+ if (reload_out[r] != 0
+ && (GET_CODE (reload_out[r]) == REG
+#ifdef AUTO_INC_DEC
+ || ! reload_out_reg[r]
+#endif
+ || GET_CODE (reload_out_reg[r]) == REG))
{
- register int nregno = REGNO (reload_out[r]);
+ rtx out = (GET_CODE (reload_out[r]) == REG
+ ? reload_out[r]
+ : reload_out_reg[r]
+ ? reload_out_reg[r]
+/* AUTO_INC */ : XEXP (reload_in_reg[r], 0));
+ register int nregno = REGNO (out);
int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
: HARD_REGNO_NREGS (nregno,
GET_MODE (reload_reg_rtx[r])));
spill_reg_store[i] = new_spill_reg_store[i];
+ spill_reg_stored_to[i] = out;
reg_last_reload_reg[nregno] = reload_reg_rtx[r];
/* If NREGNO is a hard register, it may occupy more than
@@ -7312,21 +7540,25 @@ emit_reload_insns (insn)
/* Maybe the spill reg contains a copy of reload_in. Only do
something if there will not be an output reload for
the register being reloaded. */
- else if (reload_out[r] == 0
+ else if (reload_out_reg[r] == 0
&& reload_in[r] != 0
- && spill_reg_order[i] >= 0
&& ((GET_CODE (reload_in[r]) == REG
+ && REGNO (reload_in[r]) >= FIRST_PSEUDO_REGISTER
&& ! reg_has_output_reload[REGNO (reload_in[r])])
|| (GET_CODE (reload_in_reg[r]) == REG
- && ! reg_has_output_reload[REGNO (reload_in_reg[r])])))
+ && ! reg_has_output_reload[REGNO (reload_in_reg[r])]))
+ && ! reg_set_p (reload_reg_rtx[r], PATTERN (insn)))
{
register int nregno;
int nnr;
- if (GET_CODE (reload_in[r]) == REG)
+ if (GET_CODE (reload_in[r]) == REG
+ && REGNO (reload_in[r]) >= FIRST_PSEUDO_REGISTER)
nregno = REGNO (reload_in[r]);
- else
+ else if (GET_CODE (reload_in_reg[r]) == REG)
nregno = REGNO (reload_in_reg[r]);
+ else
+ nregno = REGNO (XEXP (reload_in_reg[r], 0));
nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
: HARD_REGNO_NREGS (nregno,
@@ -7343,8 +7575,11 @@ emit_reload_insns (insn)
: 0);
/* Unless we inherited this reload, show we haven't
- recently done a store. */
- if (! reload_inherited[r])
+ recently done a store.
+ Previous stores of inherited auto_inc expressions
+ also have to be discarded. */
+ if (! reload_inherited[r]
+ || (reload_out[r] && ! reload_out_reg[r]))
spill_reg_store[i] = 0;
for (k = 0; k < nr; k++)
@@ -7380,11 +7615,77 @@ emit_reload_insns (insn)
that invalidates any previous reloaded copy of it.
But forget_old_reloads_1 won't get to see it, because
it thinks only about the original insn. So invalidate it here. */
- if (i < 0 && reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
+ if (i < 0 && reload_out[r] != 0
+ && (GET_CODE (reload_out[r]) == REG
+ || (GET_CODE (reload_out[r]) == MEM
+ && GET_CODE (reload_out_reg[r]) == REG)))
{
- register int nregno = REGNO (reload_out[r]);
+ rtx out = (GET_CODE (reload_out[r]) == REG
+ ? reload_out[r] : reload_out_reg[r]);
+ register int nregno = REGNO (out);
if (nregno >= FIRST_PSEUDO_REGISTER)
- reg_last_reload_reg[nregno] = 0;
+ {
+ rtx src_reg, store_insn;
+
+ reg_last_reload_reg[nregno] = 0;
+
+ /* If we can find a hard register that is stored, record
+ the storing insn so that we may delete this insn with
+ delete_output_reload. */
+ src_reg = reload_reg_rtx[r];
+
+ /* If this is an optional reload, try to find the source reg
+ from an input reload. */
+ if (! src_reg)
+ {
+ rtx set = single_set (insn);
+ if (set && SET_DEST (set) == reload_out[r])
+ {
+ int k;
+
+ src_reg = SET_SRC (set);
+ store_insn = insn;
+ for (k = 0; k < n_reloads; k++)
+ {
+ if (reload_in[k] == src_reg)
+ {
+ src_reg = reload_reg_rtx[k];
+ break;
+ }
+ }
+ }
+ }
+ else
+ store_insn = new_spill_reg_store[REGNO (src_reg)];
+ if (src_reg && GET_CODE (src_reg) == REG
+ && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
+ {
+ int src_regno = REGNO (src_reg);
+ int nr = HARD_REGNO_NREGS (src_regno, reload_mode[r]);
+ /* The place where to find a death note varies with
+ PRESERVE_DEATH_INFO_REGNO_P . The condition is not
+ necessarily checked exactly in the code that moves
+ notes, so just check both locations. */
+ rtx note = find_regno_note (insn, REG_DEAD, src_regno);
+ if (! note)
+ note = find_regno_note (store_insn, REG_DEAD, src_regno);
+ while (nr-- > 0)
+ {
+ spill_reg_store[src_regno + nr] = store_insn;
+ spill_reg_stored_to[src_regno + nr] = out;
+ reg_reloaded_contents[src_regno + nr] = nregno;
+ reg_reloaded_insn[src_regno + nr] = store_insn;
+ CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + nr);
+ SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + nr);
+ SET_HARD_REG_BIT (reg_is_output_reload, src_regno + nr);
+ if (note)
+ SET_HARD_REG_BIT (reg_reloaded_died, src_regno);
+ else
+ CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
+ }
+ reg_last_reload_reg[nregno] = src_reg;
+ }
+ }
else
{
int num_regs = HARD_REGNO_NREGS (nregno,GET_MODE (reload_out[r]));
@@ -7471,7 +7772,7 @@ gen_reload (out, in, opnum, type)
It might be better not to actually emit the insn unless it is valid,
but we need to pass the insn as an operand to `recog' and
- `insn_extract' and it is simpler to emit and then delete the insn if
+ `extract_insn' and it is simpler to emit and then delete the insn if
not valid than to dummy things up. */
rtx op0, op1, tem, insn;
@@ -7499,11 +7800,11 @@ gen_reload (out, in, opnum, type)
if (code >= 0)
{
- insn_extract (insn);
+ extract_insn (insn);
/* We want constrain operands to treat this insn strictly in
its validity determination, i.e., the way it would after reload
has completed. */
- if (constrain_operands (code, 1))
+ if (constrain_operands (1))
return insn;
}
@@ -7518,9 +7819,13 @@ gen_reload (out, in, opnum, type)
DEFINE_PEEPHOLE should be specified that recognizes the sequence
we emit below. */
+ code = (int) add_optab->handlers[(int) GET_MODE (out)].insn_code;
+
if (CONSTANT_P (op1) || GET_CODE (op1) == MEM || GET_CODE (op1) == SUBREG
|| (GET_CODE (op1) == REG
- && REGNO (op1) >= FIRST_PSEUDO_REGISTER))
+ && REGNO (op1) >= FIRST_PSEUDO_REGISTER)
+ || (code != CODE_FOR_nothing
+ && ! (*insn_operand_predicate[code][2]) (op1, insn_operand_mode[code][2])))
tem = op0, op0 = op1, op1 = tem;
gen_reload (out, op0, opnum, type);
@@ -7541,11 +7846,11 @@ gen_reload (out, in, opnum, type)
if (code >= 0)
{
- insn_extract (insn);
+ extract_insn (insn);
/* We want constrain operands to treat this insn strictly in
its validity determination, i.e., the way it would after reload
has completed. */
- if (constrain_operands (code, 1))
+ if (constrain_operands (1))
{
/* Add a REG_EQUIV note so that find_equiv_reg can find it. */
REG_NOTES (insn)
@@ -7610,22 +7915,68 @@ gen_reload (out, in, opnum, type)
First we double-check.
INSN is the insn now being processed.
- OUTPUT_RELOAD_INSN is the insn of the output reload.
- J is the reload-number for this insn. */
+ LAST_RELOAD_REG is the hard register number for which we want to delete
+ the last output reload.
+ J is the reload-number that originally used REG. The caller has made
+ certain that reload J doesn't use REG any longer for input. */
static void
-delete_output_reload (insn, j, output_reload_insn)
+delete_output_reload (insn, j, last_reload_reg)
rtx insn;
int j;
- rtx output_reload_insn;
+ int last_reload_reg;
{
+ rtx output_reload_insn = spill_reg_store[last_reload_reg];
+ rtx reg = spill_reg_stored_to[last_reload_reg];
+ int k;
+ int n_occurrences;
+ int n_inherited = 0;
register rtx i1;
-
+ rtx substed;
+
/* Get the raw pseudo-register referred to. */
- rtx reg = reload_in[j];
while (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
+ substed = reg_equiv_memory_loc[REGNO (reg)];
+
+ /* This is unsafe if the operand occurs more often in the current
+ insn than it is inherited. */
+ for (k = n_reloads - 1; k >= 0; k--)
+ {
+ rtx reg2 = reload_in[k];
+ if (! reg2)
+ continue;
+ if (GET_CODE (reg2) == MEM || reload_override_in[k])
+ reg2 = reload_in_reg[k];
+#ifdef AUTO_INC_DEC
+ if (reload_out[k] && ! reload_out_reg[k])
+ reg2 = XEXP (reload_in_reg[k], 0);
+#endif
+ while (GET_CODE (reg2) == SUBREG)
+ reg2 = SUBREG_REG (reg2);
+ if (rtx_equal_p (reg2, reg))
+ {
+ if (reload_inherited[k] || reload_override_in[k] || k == j)
+ {
+ n_inherited++;
+ reg2 = reload_out_reg[k];
+ if (! reg2)
+ continue;
+ while (GET_CODE (reg2) == SUBREG)
+ reg2 = XEXP (reg2, 0);
+ if (rtx_equal_p (reg2, reg))
+ n_inherited++;
+ }
+ else
+ return;
+ }
+ }
+ n_occurrences = count_occurrences (PATTERN (insn), reg);
+ if (substed)
+ n_occurrences += count_occurrences (PATTERN (insn), substed);
+ if (n_occurrences > n_inherited)
+ return;
/* If the pseudo-reg we are reloading is no longer referenced
anywhere between the store into it and here,
@@ -7640,21 +7991,14 @@ delete_output_reload (insn, j, output_reload_insn)
if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN)
&& reg_mentioned_p (reg, PATTERN (i1)))
{
- /* If this is just a single USE with an REG_EQUAL note in front
- of INSN, this is no problem, because this mentions just the
- address that we are using here.
- But if there is more than one such USE, the insn might use
- the operand directly, or another reload might do that.
- This is analogous to the count_occurences check in the callers. */
- int num_occurences = 0;
-
- while (GET_CODE (i1) == INSN && GET_CODE (PATTERN (i1)) == USE
- && find_reg_note (i1, REG_EQUAL, NULL_RTX))
+ /* If this is USE in front of INSN, we only have to check that
+ there are no more references than accounted for by inheritance. */
+ while (GET_CODE (i1) == INSN && GET_CODE (PATTERN (i1)) == USE)
{
- num_occurences += rtx_equal_p (reg, XEXP (PATTERN (i1), 0)) != 0;
+ n_occurrences += rtx_equal_p (reg, XEXP (PATTERN (i1), 0)) != 0;
i1 = NEXT_INSN (i1);
}
- if (num_occurences == 1 && i1 == insn)
+ if (n_occurrences <= n_inherited && i1 == insn)
break;
return;
}
@@ -7671,6 +8015,7 @@ delete_output_reload (insn, j, output_reload_insn)
and forget we had a stack slot for the pseudo. */
if (reload_out[j] != reload_in[j]
&& REG_N_DEATHS (REGNO (reg)) == 1
+ && REG_N_SETS (REGNO (reg)) == 1
&& REG_BASIC_BLOCK (REGNO (reg)) >= 0
&& find_regno_note (insn, REG_DEAD, REGNO (reg)))
{
@@ -7697,7 +8042,10 @@ delete_output_reload (insn, j, output_reload_insn)
{
/* Some other ref remains; just delete the output reload we
know to be dead. */
- delete_insn (output_reload_insn);
+ delete_address_reloads (output_reload_insn, insn);
+ PUT_CODE (output_reload_insn, NOTE);
+ NOTE_SOURCE_FILE (output_reload_insn) = 0;
+ NOTE_LINE_NUMBER (output_reload_insn) = NOTE_INSN_DELETED;
return;
}
}
@@ -7709,6 +8057,7 @@ delete_output_reload (insn, j, output_reload_insn)
if (set != 0 && SET_DEST (set) == reg)
{
+ delete_address_reloads (i2, insn);
/* This might be a basic block head,
thus don't use delete_insn. */
PUT_CODE (i2, NOTE);
@@ -7725,22 +8074,179 @@ delete_output_reload (insn, j, output_reload_insn)
reg_renumber[REGNO (reg)] = REGNO (reload_reg_rtx[j]);
alter_reg (REGNO (reg), -1);
}
- delete_insn (output_reload_insn);
+ delete_address_reloads (output_reload_insn, insn);
+ PUT_CODE (output_reload_insn, NOTE);
+ NOTE_SOURCE_FILE (output_reload_insn) = 0;
+ NOTE_LINE_NUMBER (output_reload_insn) = NOTE_INSN_DELETED;
}
+
+/* We are going to delete DEAD_INSN. Recursively delete loads of
+ reload registers used in DEAD_INSN that are not used till CURRENT_INSN.
+ CURRENT_INSN is being reloaded, so we have to check its reloads too. */
+static void
+delete_address_reloads (dead_insn, current_insn)
+ rtx dead_insn, current_insn;
+{
+ rtx set = single_set (dead_insn);
+ rtx set2, dst, prev, next;
+ if (set)
+ {
+ rtx dst = SET_DEST (set);
+ if (GET_CODE (dst) == MEM)
+ delete_address_reloads_1 (dead_insn, XEXP (dst, 0), current_insn);
+ }
+ /* If we deleted the store from a reloaded post_{in,de}c expression,
+ we can delete the matching adds. */
+ prev = PREV_INSN (dead_insn);
+ next = NEXT_INSN (dead_insn);
+ if (! prev || ! next)
+ return;
+ set = single_set (next);
+ set2 = single_set (prev);
+ if (! set || ! set2
+ || GET_CODE (SET_SRC (set)) != PLUS || GET_CODE (SET_SRC (set2)) != PLUS
+ || GET_CODE (XEXP (SET_SRC (set), 1)) != CONST_INT
+ || GET_CODE (XEXP (SET_SRC (set2), 1)) != CONST_INT)
+ return;
+ dst = SET_DEST (set);
+ if (! rtx_equal_p (dst, SET_DEST (set2))
+ || ! rtx_equal_p (dst, XEXP (SET_SRC (set), 0))
+ || ! rtx_equal_p (dst, XEXP (SET_SRC (set2), 0))
+ || (INTVAL (XEXP (SET_SRC (set), 1))
+ != - INTVAL (XEXP (SET_SRC (set2), 1))))
+ return;
+ delete_insn (prev);
+ delete_insn (next);
+}
+
+/* Subfunction of delete_address_reloads: process registers found in X. */
+static void
+delete_address_reloads_1 (dead_insn, x, current_insn)
+ rtx dead_insn, x, current_insn;
+{
+ rtx prev, set, dst, i2;
+ int i, j;
+ enum rtx_code code = GET_CODE (x);
+
+ if (code != REG)
+ {
+ char *fmt= GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ delete_address_reloads_1 (dead_insn, XEXP (x, i), current_insn);
+ else if (fmt[i] == 'E')
+ {
+ for (j = XVECLEN (x, i) - 1; j >=0; j--)
+ delete_address_reloads_1 (dead_insn, XVECEXP (x, i, j),
+ current_insn);
+ }
+ }
+ return;
+ }
+
+ if (spill_reg_order[REGNO (x)] < 0)
+ return;
+
+ /* Scan backwards for the insn that sets x. This might be a way back due
+ to inheritance. */
+ for (prev = PREV_INSN (dead_insn); prev; prev = PREV_INSN (prev))
+ {
+ code = GET_CODE (prev);
+ if (code == CODE_LABEL || code == JUMP_INSN)
+ return;
+ if (GET_RTX_CLASS (code) != 'i')
+ continue;
+ if (reg_set_p (x, PATTERN (prev)))
+ break;
+ if (reg_referenced_p (x, PATTERN (prev)))
+ return;
+ }
+ if (! prev || INSN_UID (prev) < reload_first_uid)
+ return;
+ /* Check that PREV only sets the reload register. */
+ set = single_set (prev);
+ if (! set)
+ return;
+ dst = SET_DEST (set);
+ if (GET_CODE (dst) != REG
+ || ! rtx_equal_p (dst, x))
+ return;
+ if (! reg_set_p (dst, PATTERN (dead_insn)))
+ {
+ /* Check if DST was used in a later insn -
+ it might have been inherited. */
+ for (i2 = NEXT_INSN (dead_insn); i2; i2 = NEXT_INSN (i2))
+ {
+ if (GET_CODE (i2) == CODE_LABEL)
+ break;
+ if (GET_RTX_CLASS (GET_CODE (i2)) != 'i')
+ continue;
+ if (reg_referenced_p (dst, PATTERN (i2)))
+ {
+ /* If there is a reference to the register in the current insn,
+ it might be loaded in a non-inherited reload. If no other
+ reload uses it, that means the register is set before
+ referenced. */
+ if (i2 == current_insn)
+ {
+ for (j = n_reloads - 1; j >= 0; j--)
+ if ((reload_reg_rtx[j] == dst && reload_inherited[j])
+ || reload_override_in[j] == dst)
+ return;
+ for (j = n_reloads - 1; j >= 0; j--)
+ if (reload_in[j] && reload_reg_rtx[j] == dst)
+ break;
+ if (j >= 0)
+ break;
+ }
+ return;
+ }
+ if (GET_CODE (i2) == JUMP_INSN)
+ break;
+ /* If DST is still live at CURRENT_INSN, check if it is used for
+ any reload. Note that even if CURRENT_INSN sets DST, we still
+ have to check the reloads. */
+ if (i2 == current_insn)
+ {
+ for (j = n_reloads - 1; j >= 0; j--)
+ if ((reload_reg_rtx[j] == dst && reload_inherited[j])
+ || reload_override_in[j] == dst)
+ return;
+ /* ??? We can't finish the loop here, because dst might be
+ allocated to a pseudo in this block if no reload in this
+ block needs any of the clsses containing DST - see
+ spill_hard_reg. There is no easy way to tell this, so we
+ have to scan till the end of the basic block. */
+ }
+ if (reg_set_p (dst, PATTERN (i2)))
+ break;
+ }
+ }
+ delete_address_reloads_1 (prev, SET_SRC (set), current_insn);
+ reg_reloaded_contents[REGNO (dst)] = -1;
+ /* Can't use delete_insn here because PREV might be a basic block head. */
+ PUT_CODE (prev, NOTE);
+ NOTE_LINE_NUMBER (prev) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (prev) = 0;
+}
/* Output reload-insns to reload VALUE into RELOADREG.
VALUE is an autoincrement or autodecrement RTX whose operand
is a register or memory location;
so reloading involves incrementing that location.
+ IN is either identical to VALUE, or some cheaper place to reload from.
INC_AMOUNT is the number to increment or decrement by (always positive).
- This cannot be deduced from VALUE. */
+ This cannot be deduced from VALUE.
-static void
-inc_for_reload (reloadreg, value, inc_amount)
+ Return the instruction that stores into RELOADREG. */
+
+static rtx
+inc_for_reload (reloadreg, in, value, inc_amount)
rtx reloadreg;
- rtx value;
+ rtx in, value;
int inc_amount;
{
/* REG or MEM to be copied and incremented. */
@@ -7751,6 +8257,8 @@ inc_for_reload (reloadreg, value, inc_amount)
rtx inc;
rtx add_insn;
int code;
+ rtx store;
+ rtx real_in = in == value ? XEXP (in, 0) : in;
/* No hard register is equivalent to this register after
inc/dec operation. If REG_LAST_RELOAD_REG were non-zero,
@@ -7765,36 +8273,38 @@ inc_for_reload (reloadreg, value, inc_amount)
inc = GEN_INT (inc_amount);
/* If this is post-increment, first copy the location to the reload reg. */
- if (post)
- emit_insn (gen_move_insn (reloadreg, incloc));
+ if (post && real_in != reloadreg)
+ emit_insn (gen_move_insn (reloadreg, real_in));
- /* See if we can directly increment INCLOC. Use a method similar to that
- in gen_reload. */
+ if (in == value)
+ {
+ /* See if we can directly increment INCLOC. Use a method similar to
+ that in gen_reload. */
- last = get_last_insn ();
- add_insn = emit_insn (gen_rtx_SET (VOIDmode, incloc,
- gen_rtx_PLUS (GET_MODE (incloc),
- incloc, inc)));
+ last = get_last_insn ();
+ add_insn = emit_insn (gen_rtx_SET (VOIDmode, incloc,
+ gen_rtx_PLUS (GET_MODE (incloc),
+ incloc, inc)));
- code = recog_memoized (add_insn);
- if (code >= 0)
- {
- insn_extract (add_insn);
- if (constrain_operands (code, 1))
+ code = recog_memoized (add_insn);
+ if (code >= 0)
{
- /* If this is a pre-increment and we have incremented the value
- where it lives, copy the incremented value to RELOADREG to
- be used as an address. */
+ extract_insn (add_insn);
+ if (constrain_operands (1))
+ {
+ /* If this is a pre-increment and we have incremented the value
+ where it lives, copy the incremented value to RELOADREG to
+ be used as an address. */
- if (! post)
- emit_insn (gen_move_insn (reloadreg, incloc));
+ if (! post)
+ emit_insn (gen_move_insn (reloadreg, incloc));
- return;
+ return add_insn;
+ }
}
+ delete_insns_since (last);
}
- delete_insns_since (last);
-
/* If couldn't do the increment directly, must increment in RELOADREG.
The way we do this depends on whether this is pre- or post-increment.
For pre-increment, copy INCLOC to the reload register, increment it
@@ -7802,9 +8312,10 @@ inc_for_reload (reloadreg, value, inc_amount)
if (! post)
{
- emit_insn (gen_move_insn (reloadreg, incloc));
+ if (in != reloadreg)
+ emit_insn (gen_move_insn (reloadreg, real_in));
emit_insn (gen_add2_insn (reloadreg, inc));
- emit_insn (gen_move_insn (incloc, reloadreg));
+ store = emit_insn (gen_move_insn (incloc, reloadreg));
}
else
{
@@ -7813,16 +8324,16 @@ inc_for_reload (reloadreg, value, inc_amount)
may not be available after the insn in an input reload, we must do
the incrementation before the insn being reloaded for.
- We have already copied INCLOC to RELOADREG. Increment the copy in
+ We have already copied IN to RELOADREG. Increment the copy in
RELOADREG, save that back, then decrement RELOADREG so it has
the original value. */
emit_insn (gen_add2_insn (reloadreg, inc));
- emit_insn (gen_move_insn (incloc, reloadreg));
+ store = emit_insn (gen_move_insn (incloc, reloadreg));
emit_insn (gen_add2_insn (reloadreg, GEN_INT (-inc_amount)));
}
- return;
+ return store;
}
/* Return 1 if we are certain that the constraint-string STRING allows
@@ -7830,7 +8341,7 @@ inc_for_reload (reloadreg, value, inc_amount)
static int
constraint_accepts_reg_p (string, reg)
- char *string;
+ const char *string;
rtx reg;
{
int value = 0;
@@ -7901,6 +8412,10 @@ count_occurrences (x, find)
case CC0:
return 0;
+ case MEM:
+ if (GET_CODE (find) == MEM && rtx_equal_p (x, find))
+ return 1;
+ break;
case SET:
if (SET_DEST (x) == find)
return count_occurrences (SET_SRC (x), find);
@@ -7955,13 +8470,6 @@ static rtx *reg_values;
static rtx invalidate_regno_rtx;
-/* This is a set of registers for which we must remove REG_DEAD notes in
- previous insns, because our modifications made them invalid. That can
- happen if we introduced the register into the current insn, or we deleted
- the current insn which used to set the register. */
-
-static HARD_REG_SET no_longer_dead_regs;
-
/* Invalidate any entries in reg_values which depend on REGNO,
including those for REGNO itself. This is called if REGNO is
changing. If CLOBBER is true, then always forget anything we
@@ -8164,55 +8672,6 @@ reload_cse_invalidate_rtx (dest, ignore)
reload_cse_invalidate_mem (dest);
}
-/* Possibly delete death notes on the insns before INSN if modifying INSN
- extended the lifespan of the registers. */
-
-static void
-reload_cse_delete_death_notes (insn)
- rtx insn;
-{
- int dreg;
-
- for (dreg = 0; dreg < FIRST_PSEUDO_REGISTER; dreg++)
- {
- rtx trial;
-
- if (! TEST_HARD_REG_BIT (no_longer_dead_regs, dreg))
- continue;
-
- for (trial = prev_nonnote_insn (insn);
- (trial
- && GET_CODE (trial) != CODE_LABEL
- && GET_CODE (trial) != BARRIER);
- trial = prev_nonnote_insn (trial))
- {
- if (find_regno_note (trial, REG_DEAD, dreg))
- {
- remove_death (dreg, trial);
- break;
- }
- }
- }
-}
-
-/* Record that the current insn uses hard reg REGNO in mode MODE. This
- will be used in reload_cse_delete_death_notes to delete prior REG_DEAD
- notes for this register. */
-
-static void
-reload_cse_no_longer_dead (regno, mode)
- int regno;
- enum machine_mode mode;
-{
- int nregs = HARD_REGNO_NREGS (regno, mode);
- while (nregs-- > 0)
- {
- SET_HARD_REG_BIT (no_longer_dead_regs, regno);
- regno++;
- }
-}
-
-
/* Do a very simple CSE pass over the hard registers.
This function detects no-op moves where we happened to assign two
@@ -8230,8 +8689,8 @@ reload_cse_no_longer_dead (regno, mode)
hard register. It then replaces the operand with the hard register
if possible, much like an optional reload would. */
-void
-reload_cse_regs (first)
+static void
+reload_cse_regs_1 (first)
rtx first;
{
char *firstobj;
@@ -8285,8 +8744,6 @@ reload_cse_regs (first)
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
continue;
- CLEAR_HARD_REG_SET (no_longer_dead_regs);
-
/* If this is a call instruction, forget anything stored in a
call clobbered register, or, if this is not a const call, in
memory. */
@@ -8300,64 +8757,110 @@ reload_cse_regs (first)
reload_cse_invalidate_mem (callmem);
}
+
+ /* Forget all the register values at a volatile asm. */
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
+ && MEM_VOLATILE_P (PATTERN (insn)))
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_values[i] = 0;
+
body = PATTERN (insn);
if (GET_CODE (body) == SET)
{
int count = 0;
if (reload_cse_noop_set_p (body, insn))
{
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- reload_cse_delete_death_notes (insn);
+ /* If this sets the return value of the function, we must keep
+ a USE around, in case this is in a different basic block
+ than the final USE. Otherwise, we could loose important
+ register lifeness information on SMALL_REGISTER_CLASSES
+ machines, where return registers might be used as spills:
+ subsequent passes assume that spill registers are dead at
+ the end of a basic block. */
+ if (REG_FUNCTION_VALUE_P (SET_DEST (body)))
+ {
+ pop_obstacks ();
+ PATTERN (insn) = gen_rtx_USE (VOIDmode, SET_DEST (body));
+ INSN_CODE (insn) = -1;
+ REG_NOTES (insn) = NULL_RTX;
+ push_obstacks (&reload_obstack, &reload_obstack);
+ }
+ else
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
/* We're done with this insn. */
continue;
}
/* It's not a no-op, but we can try to simplify it. */
- CLEAR_HARD_REG_SET (no_longer_dead_regs);
count += reload_cse_simplify_set (body, insn);
- if (count > 0 && apply_change_group ())
- reload_cse_delete_death_notes (insn);
- else if (reload_cse_simplify_operands (insn))
- reload_cse_delete_death_notes (insn);
+ if (count > 0)
+ apply_change_group ();
+ else
+ reload_cse_simplify_operands (insn);
reload_cse_record_set (body, body);
}
else if (GET_CODE (body) == PARALLEL)
{
int count = 0;
+ rtx value = NULL_RTX;
/* If every action in a PARALLEL is a noop, we can delete
the entire PARALLEL. */
for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
- if ((GET_CODE (XVECEXP (body, 0, i)) != SET
- || ! reload_cse_noop_set_p (XVECEXP (body, 0, i), insn))
- && GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
- break;
+ {
+ rtx part = XVECEXP (body, 0, i);
+ if (GET_CODE (part) == SET)
+ {
+ if (! reload_cse_noop_set_p (part, insn))
+ break;
+ if (REG_FUNCTION_VALUE_P (SET_DEST (part)))
+ {
+ if (value)
+ break;
+ value = SET_DEST (part);
+ }
+ }
+ else if (GET_CODE (part) != CLOBBER)
+ break;
+ }
if (i < 0)
{
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- reload_cse_delete_death_notes (insn);
+ if (value)
+ {
+ pop_obstacks ();
+ PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
+ INSN_CODE (insn) = -1;
+ REG_NOTES (insn) = NULL_RTX;
+ push_obstacks (&reload_obstack, &reload_obstack);
+ }
+ else
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
/* We're done with this insn. */
continue;
}
/* It's not a no-op, but we can try to simplify it. */
- CLEAR_HARD_REG_SET (no_longer_dead_regs);
for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
if (GET_CODE (XVECEXP (body, 0, i)) == SET)
count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
- if (count > 0 && apply_change_group ())
- reload_cse_delete_death_notes (insn);
- else if (reload_cse_simplify_operands (insn))
- reload_cse_delete_death_notes (insn);
+ if (count > 0)
+ apply_change_group ();
+ else
+ reload_cse_simplify_operands (insn);
/* Look through the PARALLEL and record the values being
set, if possible. Also handle any CLOBBERs. */
@@ -8405,6 +8908,19 @@ reload_cse_regs (first)
pop_obstacks ();
}
+/* Call cse / combine like post-reload optimization phases.
+ FIRST is the first instruction. */
+void
+reload_cse_regs (first)
+ rtx first;
+{
+ reload_cse_regs_1 (first);
+ reload_combine ();
+ reload_cse_move2add (first);
+ if (flag_expensive_optimizations)
+ reload_cse_regs_1 (first);
+}
+
/* Return whether the values known for REGNO are equal to VAL. MODE
is the mode of the object that VAL is being copied to; this matters
if VAL is a CONST_INT. */
@@ -8523,14 +9039,6 @@ reload_cse_noop_set_p (set, insn)
ret = 1;
}
- /* If we can delete this SET, then we need to look for an earlier
- REG_DEAD note on DREG, and remove it if it exists. */
- if (ret && dreg >= 0)
- {
- if (! find_regno_note (insn, REG_UNUSED, dreg))
- reload_cse_no_longer_dead (dreg, dest_mode);
- }
-
return ret;
}
@@ -8590,11 +9098,8 @@ reload_cse_simplify_set (set, insn)
storage. */
push_obstacks (&reload_obstack, &reload_obstack);
- if (validated && ! find_regno_note (insn, REG_UNUSED, i))
- {
- reload_cse_no_longer_dead (i, dest_mode);
- return 1;
- }
+ if (validated)
+ return 1;
}
}
return 0;
@@ -8616,10 +9121,9 @@ reload_cse_simplify_operands (insn)
rtx insn;
{
#ifdef REGISTER_CONSTRAINTS
- int insn_code_number, n_operands, n_alternatives;
int i,j;
- char *constraints[MAX_RECOG_OPERANDS];
+ const char *constraints[MAX_RECOG_OPERANDS];
/* Vector recording how bad an alternative is. */
int *alternative_reject;
@@ -8634,41 +9138,33 @@ reload_cse_simplify_operands (insn)
int *alternative_order;
rtx reg = gen_rtx_REG (VOIDmode, -1);
- /* Find out some information about this insn. */
- insn_code_number = recog_memoized (insn);
- /* We don't modify asm instructions. */
- if (insn_code_number < 0)
- return 0;
+ extract_insn (insn);
- n_operands = insn_n_operands[insn_code_number];
- n_alternatives = insn_n_alternatives[insn_code_number];
-
- if (n_alternatives == 0 || n_operands == 0)
+ if (recog_n_alternatives == 0 || recog_n_operands == 0)
return 0;
- insn_extract (insn);
/* Figure out which alternative currently matches. */
- if (! constrain_operands (insn_code_number, 1))
+ if (! constrain_operands (1))
fatal_insn_not_found (insn);
- alternative_reject = (int *) alloca (n_alternatives * sizeof (int));
- alternative_nregs = (int *) alloca (n_alternatives * sizeof (int));
- alternative_order = (int *) alloca (n_alternatives * sizeof (int));
- bzero ((char *)alternative_reject, n_alternatives * sizeof (int));
- bzero ((char *)alternative_nregs, n_alternatives * sizeof (int));
+ alternative_reject = (int *) alloca (recog_n_alternatives * sizeof (int));
+ alternative_nregs = (int *) alloca (recog_n_alternatives * sizeof (int));
+ alternative_order = (int *) alloca (recog_n_alternatives * sizeof (int));
+ bzero ((char *)alternative_reject, recog_n_alternatives * sizeof (int));
+ bzero ((char *)alternative_nregs, recog_n_alternatives * sizeof (int));
- for (i = 0; i < n_operands; i++)
+ for (i = 0; i < recog_n_operands; i++)
{
enum machine_mode mode;
int regno;
- char *p;
+ const char *p;
- op_alt_regno[i] = (int *) alloca (n_alternatives * sizeof (int));
- for (j = 0; j < n_alternatives; j++)
+ op_alt_regno[i] = (int *) alloca (recog_n_alternatives * sizeof (int));
+ for (j = 0; j < recog_n_alternatives; j++)
op_alt_regno[i][j] = -1;
- p = constraints[i] = insn_operand_constraint[insn_code_number][i];
- mode = insn_operand_mode[insn_code_number][i];
+ p = constraints[i] = recog_constraints[i];
+ mode = recog_operand_mode[i];
/* Add the reject values for each alternative given by the constraints
for this operand. */
@@ -8735,7 +9231,7 @@ reload_cse_simplify_operands (insn)
default:
class
- = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER (c)];
+ = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char)c)];
break;
case ',': case '\0':
@@ -8763,21 +9259,21 @@ reload_cse_simplify_operands (insn)
/* Record all alternatives which are better or equal to the currently
matching one in the alternative_order array. */
- for (i = j = 0; i < n_alternatives; i++)
+ for (i = j = 0; i < recog_n_alternatives; i++)
if (alternative_reject[i] <= alternative_reject[which_alternative])
alternative_order[j++] = i;
- n_alternatives = j;
+ recog_n_alternatives = j;
/* Sort it. Given a small number of alternatives, a dumb algorithm
won't hurt too much. */
- for (i = 0; i < n_alternatives - 1; i++)
+ for (i = 0; i < recog_n_alternatives - 1; i++)
{
int best = i;
int best_reject = alternative_reject[alternative_order[i]];
int best_nregs = alternative_nregs[alternative_order[i]];
int tmp;
- for (j = i + 1; j < n_alternatives; j++)
+ for (j = i + 1; j < recog_n_alternatives; j++)
{
int this_reject = alternative_reject[alternative_order[j]];
int this_nregs = alternative_nregs[alternative_order[j]];
@@ -8799,31 +9295,28 @@ reload_cse_simplify_operands (insn)
/* Substitute the operands as determined by op_alt_regno for the best
alternative. */
j = alternative_order[0];
- CLEAR_HARD_REG_SET (no_longer_dead_regs);
/* Pop back to the real obstacks while changing the insn. */
pop_obstacks ();
- for (i = 0; i < n_operands; i++)
+ for (i = 0; i < recog_n_operands; i++)
{
- enum machine_mode mode = insn_operand_mode[insn_code_number][i];
+ enum machine_mode mode = recog_operand_mode[i];
if (op_alt_regno[i][j] == -1)
continue;
- reload_cse_no_longer_dead (op_alt_regno[i][j], mode);
validate_change (insn, recog_operand_loc[i],
gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
}
- for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
+ for (i = recog_n_dups - 1; i >= 0; i--)
{
int op = recog_dup_num[i];
- enum machine_mode mode = insn_operand_mode[insn_code_number][op];
+ enum machine_mode mode = recog_operand_mode[op];
if (op_alt_regno[op][j] == -1)
continue;
- reload_cse_no_longer_dead (op_alt_regno[op][j], mode);
validate_change (insn, recog_dup_loc[i],
gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
}
@@ -9002,3 +9495,761 @@ reload_cse_record_set (set, body)
abort ();
}
}
+
+/* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
+ addressing now.
+ This code might also be useful when reload gave up on reg+reg addresssing
+ because of clashes between the return register and INDEX_REG_CLASS. */
+
+/* The maximum number of uses of a register we can keep track of to
+ replace them with reg+reg addressing. */
+#define RELOAD_COMBINE_MAX_USES 6
+
+/* INSN is the insn where a register has ben used, and USEP points to the
+ location of the register within the rtl. */
+struct reg_use { rtx insn, *usep; };
+
+/* If the register is used in some unknown fashion, USE_INDEX is negative.
+ If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
+ indicates where it becomes live again.
+ Otherwise, USE_INDEX is the index of the last encountered use of the
+ register (which is first among these we have seen since we scan backwards),
+ OFFSET contains the constant offset that is added to the register in
+ all encountered uses, and USE_RUID indicates the first encountered, i.e.
+ last, of these uses.
+ STORE_RUID is always meaningful if we only want to use a value in a
+ register in a different place: it denotes the next insn in the insn
+ stream (i.e. the last ecountered) that sets or clobbers the register. */
+static struct
+ {
+ struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
+ int use_index;
+ rtx offset;
+ int store_ruid;
+ int use_ruid;
+ } reg_state[FIRST_PSEUDO_REGISTER];
+
+/* Reverse linear uid. This is increased in reload_combine while scanning
+ the instructions from last to first. It is used to set last_label_ruid
+ and the store_ruid / use_ruid fields in reg_state. */
+static int reload_combine_ruid;
+
+#define LABEL_LIVE(LABEL) \
+ (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
+
+static void
+reload_combine ()
+{
+ rtx insn, set;
+ int first_index_reg = 1, last_index_reg = 0;
+ int i;
+ int last_label_ruid;
+ int min_labelno, n_labels;
+ HARD_REG_SET ever_live_at_start, *label_live;
+
+ /* If reg+reg can be used in offsetable memory adresses, the main chunk of
+ reload has already used it where appropriate, so there is no use in
+ trying to generate it now. */
+ if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS)
+ return;
+
+ /* To avoid wasting too much time later searching for an index register,
+ determine the minimum and maximum index register numbers. */
+ for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+ {
+ if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i))
+ {
+ if (! last_index_reg)
+ last_index_reg = i;
+ first_index_reg = i;
+ }
+ }
+ /* If no index register is available, we can quit now. */
+ if (first_index_reg > last_index_reg)
+ return;
+
+ /* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime
+ information is a bit fuzzy immediately after reload, but it's
+ still good enough to determine which registers are live at a jump
+ destination. */
+ min_labelno = get_first_label_num ();
+ n_labels = max_label_num () - min_labelno;
+ label_live = (HARD_REG_SET *) xmalloc (n_labels * sizeof (HARD_REG_SET));
+ CLEAR_HARD_REG_SET (ever_live_at_start);
+ for (i = n_basic_blocks - 1; i >= 0; i--)
+ {
+ insn = BLOCK_HEAD (i);
+ if (GET_CODE (insn) == CODE_LABEL)
+ {
+ HARD_REG_SET live;
+
+ REG_SET_TO_HARD_REG_SET (live, BASIC_BLOCK (i)->global_live_at_start);
+ compute_use_by_pseudos (&live, BASIC_BLOCK (i)->global_live_at_start);
+ COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
+ IOR_HARD_REG_SET (ever_live_at_start, live);
+ }
+ }
+
+ /* Initialize last_label_ruid, reload_combine_ruid and reg_state. */
+ last_label_ruid = reload_combine_ruid = 0;
+ for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+ {
+ reg_state[i].store_ruid = reload_combine_ruid;
+ if (fixed_regs[i])
+ reg_state[i].use_index = -1;
+ else
+ reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
+ }
+
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+ {
+ rtx note;
+
+ /* We cannot do our optimization across labels. Invalidating all the use
+ information we have would be costly, so we just note where the label
+ is and then later disable any optimization that would cross it. */
+ if (GET_CODE (insn) == CODE_LABEL)
+ last_label_ruid = reload_combine_ruid;
+ if (GET_CODE (insn) == BARRIER)
+ {
+ for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+ reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
+ }
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ continue;
+ reload_combine_ruid++;
+
+ /* Look for (set (REGX) (CONST_INT))
+ (set (REGX) (PLUS (REGX) (REGY)))
+ ...
+ ... (MEM (REGX)) ...
+ and convert it to
+ (set (REGZ) (CONST_INT))
+ ...
+ ... (MEM (PLUS (REGZ) (REGY)))... .
+
+ First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
+ and that we know all uses of REGX before it dies. */
+ set = single_set (insn);
+ if (set != NULL_RTX
+ && GET_CODE (SET_DEST (set)) == REG
+ && (HARD_REGNO_NREGS (REGNO (SET_DEST (set)),
+ GET_MODE (SET_DEST (set)))
+ == 1)
+ && GET_CODE (SET_SRC (set)) == PLUS
+ && GET_CODE (XEXP (SET_SRC (set), 1)) == REG
+ && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set))
+ && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid)
+ {
+ rtx reg = SET_DEST (set);
+ rtx plus = SET_SRC (set);
+ rtx base = XEXP (plus, 1);
+ rtx prev = prev_nonnote_insn (insn);
+ rtx prev_set = prev ? single_set (prev) : NULL_RTX;
+ int regno = REGNO (reg);
+ rtx const_reg;
+ rtx reg_sum = NULL_RTX;
+
+ /* Now, we need an index register.
+ We'll set index_reg to this index register, const_reg to the
+ register that is to be loaded with the constant
+ (denoted as REGZ in the substitution illustration above),
+ and reg_sum to the register-register that we want to use to
+ substitute uses of REG (typically in MEMs) with.
+ First check REG and BASE for being index registers;
+ we can use them even if they are not dead. */
+ if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
+ || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
+ REGNO (base)))
+ {
+ const_reg = reg;
+ reg_sum = plus;
+ }
+ else
+ {
+ /* Otherwise, look for a free index register. Since we have
+ checked above that neiter REG nor BASE are index registers,
+ if we find anything at all, it will be different from these
+ two registers. */
+ for (i = first_index_reg; i <= last_index_reg; i++)
+ {
+ if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
+ && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
+ && reg_state[i].store_ruid <= reg_state[regno].use_ruid
+ && HARD_REGNO_NREGS (i, GET_MODE (reg)) == 1)
+ {
+ rtx index_reg = gen_rtx_REG (GET_MODE (reg), i);
+ const_reg = index_reg;
+ reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
+ break;
+ }
+ }
+ }
+ /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
+ (REGY), i.e. BASE, is not clobbered before the last use we'll
+ create. */
+ if (prev_set
+ && GET_CODE (SET_SRC (prev_set)) == CONST_INT
+ && rtx_equal_p (SET_DEST (prev_set), reg)
+ && reg_state[regno].use_index >= 0
+ && reg_state[REGNO (base)].store_ruid <= reg_state[regno].use_ruid
+ && reg_sum)
+ {
+ int i;
+
+ /* Change destination register and - if necessary - the
+ constant value in PREV, the constant loading instruction. */
+ validate_change (prev, &SET_DEST (prev_set), const_reg, 1);
+ if (reg_state[regno].offset != const0_rtx)
+ validate_change (prev,
+ &SET_SRC (prev_set),
+ GEN_INT (INTVAL (SET_SRC (prev_set))
+ + INTVAL (reg_state[regno].offset)),
+ 1);
+ /* Now for every use of REG that we have recorded, replace REG
+ with REG_SUM. */
+ for (i = reg_state[regno].use_index;
+ i < RELOAD_COMBINE_MAX_USES; i++)
+ validate_change (reg_state[regno].reg_use[i].insn,
+ reg_state[regno].reg_use[i].usep,
+ reg_sum, 1);
+
+ if (apply_change_group ())
+ {
+ rtx *np;
+
+ /* Delete the reg-reg addition. */
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+
+ if (reg_state[regno].offset != const0_rtx)
+ {
+ /* Previous REG_EQUIV / REG_EQUAL notes for PREV
+ are now invalid. */
+ for (np = &REG_NOTES (prev); *np; )
+ {
+ if (REG_NOTE_KIND (*np) == REG_EQUAL
+ || REG_NOTE_KIND (*np) == REG_EQUIV)
+ *np = XEXP (*np, 1);
+ else
+ np = &XEXP (*np, 1);
+ }
+ }
+ reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
+ reg_state[REGNO (const_reg)].store_ruid = reload_combine_ruid;
+ continue;
+ }
+ }
+ }
+ note_stores (PATTERN (insn), reload_combine_note_store);
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ rtx link;
+
+ for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+ {
+ if (call_used_regs[i])
+ {
+ reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
+ reg_state[i].store_ruid = reload_combine_ruid;
+ }
+ }
+ for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
+ link = XEXP (link, 1))
+ {
+ rtx use = XEXP (link, 0);
+ int regno = REGNO (XEXP (use, 0));
+ if (GET_CODE (use) == CLOBBER)
+ {
+ reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
+ reg_state[regno].store_ruid = reload_combine_ruid;
+ }
+ else
+ reg_state[regno].use_index = -1;
+ }
+ }
+ if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) != RETURN)
+ {
+ /* Non-spill registers might be used at the call destination in
+ some unknown fashion, so we have to mark the unknown use. */
+ HARD_REG_SET *live;
+ if ((condjump_p (insn) || condjump_in_parallel_p (insn))
+ && JUMP_LABEL (insn))
+ live = &LABEL_LIVE (JUMP_LABEL (insn));
+ else
+ live = &ever_live_at_start;
+ for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
+ {
+ if (TEST_HARD_REG_BIT (*live, i))
+ reg_state[i].use_index = -1;
+ }
+ }
+ reload_combine_note_use (&PATTERN (insn), insn);
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ {
+ if (REG_NOTE_KIND (note) == REG_INC
+ && GET_CODE (XEXP (note, 0)) == REG)
+ {
+ int regno = REGNO (XEXP (note, 0));
+
+ reg_state[regno].store_ruid = reload_combine_ruid;
+ reg_state[regno].use_index = -1;
+ }
+ }
+ }
+ free (label_live);
+}
+
+/* Check if DST is a register or a subreg of a register; if it is,
+ update reg_state[regno].store_ruid and reg_state[regno].use_index
+ accordingly. Called via note_stores from reload_combine. */
+static void
+reload_combine_note_store (dst, set)
+ rtx dst, set;
+{
+ int regno = 0;
+ int i;
+ unsigned size = GET_MODE_SIZE (GET_MODE (dst));
+
+ if (GET_CODE (dst) == SUBREG)
+ {
+ regno = SUBREG_WORD (dst);
+ dst = SUBREG_REG (dst);
+ }
+ if (GET_CODE (dst) != REG)
+ return;
+ regno += REGNO (dst);
+
+ /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
+ careful with registers / register parts that are not full words.
+
+ Similarly for ZERO_EXTRACT and SIGN_EXTRACT. */
+ if (GET_CODE (set) != SET
+ || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
+ || GET_CODE (SET_DEST (set)) == SIGN_EXTRACT
+ || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
+ {
+ for (i = (size - 1) / UNITS_PER_WORD + regno; i >= regno; i--)
+ {
+ reg_state[i].use_index = -1;
+ reg_state[i].store_ruid = reload_combine_ruid;
+ }
+ }
+ else
+ {
+ for (i = (size - 1) / UNITS_PER_WORD + regno; i >= regno; i--)
+ {
+ reg_state[i].store_ruid = reload_combine_ruid;
+ reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
+ }
+ }
+}
+
+/* XP points to a piece of rtl that has to be checked for any uses of
+ registers.
+ *XP is the pattern of INSN, or a part of it.
+ Called from reload_combine, and recursively by itself. */
+static void
+reload_combine_note_use (xp, insn)
+ rtx *xp, insn;
+{
+ rtx x = *xp;
+ enum rtx_code code = x->code;
+ char *fmt;
+ int i, j;
+ rtx offset = const0_rtx; /* For the REG case below. */
+
+ switch (code)
+ {
+ case SET:
+ if (GET_CODE (SET_DEST (x)) == REG)
+ {
+ reload_combine_note_use (&SET_SRC (x), insn);
+ return;
+ }
+ break;
+
+ case CLOBBER:
+ if (GET_CODE (SET_DEST (x)) == REG)
+ return;
+ break;
+
+ case PLUS:
+ /* We are interested in (plus (reg) (const_int)) . */
+ if (GET_CODE (XEXP (x, 0)) != REG || GET_CODE (XEXP (x, 1)) != CONST_INT)
+ break;
+ offset = XEXP (x, 1);
+ x = XEXP (x, 0);
+ /* Fall through. */
+ case REG:
+ {
+ int regno = REGNO (x);
+ int use_index;
+
+ /* Some spurious USEs of pseudo registers might remain.
+ Just ignore them. */
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
+ /* If this register is already used in some unknown fashion, we
+ can't do anything.
+ If we decrement the index from zero to -1, we can't store more
+ uses, so this register becomes used in an unknown fashion. */
+ use_index = --reg_state[regno].use_index;
+ if (use_index < 0)
+ return;
+
+ if (use_index != RELOAD_COMBINE_MAX_USES - 1)
+ {
+ /* We have found another use for a register that is already
+ used later. Check if the offsets match; if not, mark the
+ register as used in an unknown fashion. */
+ if (! rtx_equal_p (offset, reg_state[regno].offset))
+ {
+ reg_state[regno].use_index = -1;
+ return;
+ }
+ }
+ else
+ {
+ /* This is the first use of this register we have seen since we
+ marked it as dead. */
+ reg_state[regno].offset = offset;
+ reg_state[regno].use_ruid = reload_combine_ruid;
+ }
+ reg_state[regno].reg_use[use_index].insn = insn;
+ reg_state[regno].reg_use[use_index].usep = xp;
+ return;
+ }
+
+ default:
+ break;
+ }
+
+ /* Recursively process the components of X. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ reload_combine_note_use (&XEXP (x, i), insn);
+ else if (fmt[i] == 'E')
+ {
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ reload_combine_note_use (&XVECEXP (x, i, j), insn);
+ }
+ }
+}
+
+/* See if we can reduce the cost of a constant by replacing a move with
+ an add. */
+/* We cannot do our optimization across labels. Invalidating all the
+ information about register contents we have would be costly, so we
+ use last_label_luid (local variable of reload_cse_move2add) to note
+ where the label is and then later disable any optimization that would
+ cross it.
+ reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
+ reg_set_luid[n] is larger than last_label_luid[n] . */
+static int reg_set_luid[FIRST_PSEUDO_REGISTER];
+/* reg_offset[n] has to be CONST_INT for it and reg_base_reg[n] /
+ reg_mode[n] to be valid.
+ If reg_offset[n] is a CONST_INT and reg_base_reg[n] is negative, register n
+ has been set to reg_offset[n] in mode reg_mode[n] .
+ If reg_offset[n] is a CONST_INT and reg_base_reg[n] is non-negative,
+ register n has been set to the sum of reg_offset[n] and register
+ reg_base_reg[n], calculated in mode reg_mode[n] . */
+static rtx reg_offset[FIRST_PSEUDO_REGISTER];
+static int reg_base_reg[FIRST_PSEUDO_REGISTER];
+static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
+/* move2add_luid is linearily increased while scanning the instructions
+ from first to last. It is used to set reg_set_luid in
+ reload_cse_move2add and move2add_note_store. */
+static int move2add_luid;
+
+/* Generate a CONST_INT and force it in the range of MODE. */
+static rtx
+gen_mode_int (mode, value)
+ enum machine_mode mode;
+ HOST_WIDE_INT value;
+{
+ HOST_WIDE_INT cval = value & GET_MODE_MASK (mode);
+ int width = GET_MODE_BITSIZE (mode);
+
+ /* If MODE is narrower than HOST_WIDE_INT and CVAL is a negative number,
+ sign extend it. */
+ if (width > 0 && width < HOST_BITS_PER_WIDE_INT
+ && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
+ cval |= (HOST_WIDE_INT) -1 << width;
+
+ return GEN_INT (cval);
+}
+
+static void
+reload_cse_move2add (first)
+ rtx first;
+{
+ int i;
+ rtx insn;
+ int last_label_luid;
+
+ for (i = FIRST_PSEUDO_REGISTER-1; i >= 0; i--)
+ reg_set_luid[i] = 0;
+
+ last_label_luid = 0;
+ move2add_luid = 1;
+ for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
+ {
+ rtx pat, note;
+
+ if (GET_CODE (insn) == CODE_LABEL)
+ last_label_luid = move2add_luid;
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ continue;
+ pat = PATTERN (insn);
+ /* For simplicity, we only perform this optimization on
+ straightforward SETs. */
+ if (GET_CODE (pat) == SET
+ && GET_CODE (SET_DEST (pat)) == REG)
+ {
+ rtx reg = SET_DEST (pat);
+ int regno = REGNO (reg);
+ rtx src = SET_SRC (pat);
+
+ /* Check if we have valid information on the contents of this
+ register in the mode of REG. */
+ /* ??? We don't know how zero / sign extension is handled, hence
+ we can't go from a narrower to a wider mode. */
+ if (reg_set_luid[regno] > last_label_luid
+ && (GET_MODE_SIZE (GET_MODE (reg))
+ <= GET_MODE_SIZE (reg_mode[regno]))
+ && GET_CODE (reg_offset[regno]) == CONST_INT)
+ {
+ /* Try to transform (set (REGX) (CONST_INT A))
+ ...
+ (set (REGX) (CONST_INT B))
+ to
+ (set (REGX) (CONST_INT A))
+ ...
+ (set (REGX) (plus (REGX) (CONST_INT B-A))) */
+
+ if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0)
+ {
+ int success = 0;
+ rtx new_src
+ = gen_mode_int (GET_MODE (reg),
+ INTVAL (src) - INTVAL (reg_offset[regno]));
+ /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
+ use (set (reg) (reg)) instead.
+ We don't delete this insn, nor do we convert it into a
+ note, to avoid losing register notes or the return
+ value flag. jump2 already knowns how to get rid of
+ no-op moves. */
+ if (new_src == const0_rtx)
+ success = validate_change (insn, &SET_SRC (pat), reg, 0);
+ else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET)
+ && have_add2_insn (GET_MODE (reg)))
+ success = validate_change (insn, &PATTERN (insn),
+ gen_add2_insn (reg, new_src), 0);
+ reg_set_luid[regno] = move2add_luid;
+ reg_mode[regno] = GET_MODE (reg);
+ reg_offset[regno] = src;
+ continue;
+ }
+
+ /* Try to transform (set (REGX) (REGY))
+ (set (REGX) (PLUS (REGX) (CONST_INT A)))
+ ...
+ (set (REGX) (REGY))
+ (set (REGX) (PLUS (REGX) (CONST_INT B)))
+ to
+ (REGX) (REGY))
+ (set (REGX) (PLUS (REGX) (CONST_INT A)))
+ ...
+ (set (REGX) (plus (REGX) (CONST_INT B-A))) */
+ else if (GET_CODE (src) == REG
+ && reg_base_reg[regno] == REGNO (src)
+ && reg_set_luid[regno] > reg_set_luid[REGNO (src)])
+ {
+ rtx next = next_nonnote_insn (insn);
+ rtx set;
+ if (next)
+ set = single_set (next);
+ if (next
+ && set
+ && SET_DEST (set) == reg
+ && GET_CODE (SET_SRC (set)) == PLUS
+ && XEXP (SET_SRC (set), 0) == reg
+ && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
+ {
+ rtx src3 = XEXP (SET_SRC (set), 1);
+ rtx new_src
+ = gen_mode_int (GET_MODE (reg),
+ INTVAL (src3)
+ - INTVAL (reg_offset[regno]));
+ int success = 0;
+
+ if (new_src == const0_rtx)
+ /* See above why we create (set (reg) (reg)) here. */
+ success
+ = validate_change (next, &SET_SRC (set), reg, 0);
+ else if ((rtx_cost (new_src, PLUS)
+ < 2 + rtx_cost (src3, SET))
+ && have_add2_insn (GET_MODE (reg)))
+ success
+ = validate_change (next, &PATTERN (next),
+ gen_add2_insn (reg, new_src), 0);
+ if (success)
+ {
+ /* INSN might be the first insn in a basic block
+ if the preceding insn is a conditional jump
+ or a possible-throwing call. */
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
+ insn = next;
+ reg_set_luid[regno] = move2add_luid;
+ reg_mode[regno] = GET_MODE (reg);
+ reg_offset[regno] = src3;
+ continue;
+ }
+ }
+ }
+ }
+
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ {
+ if (REG_NOTE_KIND (note) == REG_INC
+ && GET_CODE (XEXP (note, 0)) == REG)
+ {
+ /* Indicate that this register has been recently written to,
+ but the exact contents are not available. */
+ int regno = REGNO (XEXP (note, 0));
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ reg_set_luid[regno] = move2add_luid;
+ reg_offset[regno] = note;
+ }
+ }
+ }
+ note_stores (PATTERN (insn), move2add_note_store);
+ /* If this is a CALL_INSN, all call used registers are stored with
+ unknown values. */
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ for (i = FIRST_PSEUDO_REGISTER-1; i >= 0; i--)
+ {
+ if (call_used_regs[i])
+ {
+ reg_set_luid[i] = move2add_luid;
+ reg_offset[i] = insn; /* Invalidate contents. */
+ }
+ }
+ }
+ }
+}
+
+/* SET is a SET or CLOBBER that sets DST.
+ Update reg_set_luid, reg_offset and reg_base_reg accordingly.
+ Called from reload_cse_move2add via note_stores. */
+static void
+move2add_note_store (dst, set)
+ rtx dst, set;
+{
+ int regno = 0;
+ int i;
+
+ enum machine_mode mode = GET_MODE (dst);
+ if (GET_CODE (dst) == SUBREG)
+ {
+ regno = SUBREG_WORD (dst);
+ dst = SUBREG_REG (dst);
+ }
+ if (GET_CODE (dst) != REG)
+ return;
+
+ regno += REGNO (dst);
+
+ if (HARD_REGNO_NREGS (regno, mode) == 1 && GET_CODE (set) == SET
+ && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
+ && GET_CODE (SET_DEST (set)) != SIGN_EXTRACT
+ && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
+ {
+ rtx src = SET_SRC (set);
+
+ reg_mode[regno] = mode;
+ switch (GET_CODE (src))
+ {
+ case PLUS:
+ {
+ rtx src0 = XEXP (src, 0);
+ if (GET_CODE (src0) == REG)
+ {
+ if (REGNO (src0) != regno
+ || reg_offset[regno] != const0_rtx)
+ {
+ reg_base_reg[regno] = REGNO (src0);
+ reg_set_luid[regno] = move2add_luid;
+ }
+ reg_offset[regno] = XEXP (src, 1);
+ break;
+ }
+ reg_set_luid[regno] = move2add_luid;
+ reg_offset[regno] = set; /* Invalidate contents. */
+ break;
+ }
+
+ case REG:
+ reg_base_reg[regno] = REGNO (SET_SRC (set));
+ reg_offset[regno] = const0_rtx;
+ reg_set_luid[regno] = move2add_luid;
+ break;
+
+ default:
+ reg_base_reg[regno] = -1;
+ reg_offset[regno] = SET_SRC (set);
+ reg_set_luid[regno] = move2add_luid;
+ break;
+ }
+ }
+ else
+ {
+ for (i = regno + HARD_REGNO_NREGS (regno, mode) - 1; i >= regno; i--)
+ {
+ /* Indicate that this register has been recently written to,
+ but the exact contents are not available. */
+ reg_set_luid[i] = move2add_luid;
+ reg_offset[i] = dst;
+ }
+ }
+}
+
+#ifdef AUTO_INC_DEC
+static void
+add_auto_inc_notes (insn, x)
+ rtx insn;
+ rtx x;
+{
+ enum rtx_code code = GET_CODE (x);
+ char *fmt;
+ int i, j;
+
+ if (code == MEM && auto_inc_p (XEXP (x, 0)))
+ {
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_INC, XEXP (XEXP (x, 0), 0), REG_NOTES (insn));
+ return;
+ }
+
+ /* Scan all the operand sub-expressions. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ add_auto_inc_notes (insn, XEXP (x, i));
+ else if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ add_auto_inc_notes (insn, XVECEXP (x, i, j));
+ }
+}
+#endif
diff --git a/contrib/gcc/reorg.c b/contrib/gcc/reorg.c
index 4e823e4..09b6dd8 100644
--- a/contrib/gcc/reorg.c
+++ b/contrib/gcc/reorg.c
@@ -1,5 +1,5 @@
/* Perform instruction reorganizations for delay slot filling.
- Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
Hacked by Michael Tiemann (tiemann@cygnus.com).
@@ -61,6 +61,10 @@ Boston, MA 02111-1307, USA. */
we can hoist insns from the fall-through path for forward branches or
steal insns from the target of backward branches.
+ The TMS320C3x and C4x have three branch delay slots. When the three
+ slots are filled, the branch penalty is zero. Most insns can fill the
+ delay slots except jump insns.
+
Three techniques for filling delay slots have been implemented so far:
(1) `fill_simple_delay_slots' is the simplest, most efficient way
@@ -117,6 +121,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "toplev.h"
#include "rtl.h"
#include "expr.h"
#include "insn-config.h"
@@ -130,12 +135,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "obstack.h"
#include "insn-attr.h"
-
-/* Import list of registers used as spill regs from reload. */
-extern HARD_REG_SET used_spill_regs;
-
-/* Import highest label used in function at end of reload. */
-extern int max_label_num_after_reload;
+#include "resource.h"
#ifdef DELAY_SLOTS
@@ -165,58 +165,9 @@ static rtx *unfilled_firstobj;
#define unfilled_slots_next \
((rtx *) obstack_next_free (&unfilled_slots_obstack))
-/* This structure is used to indicate which hardware resources are set or
- needed by insns so far. */
-
-struct resources
-{
- char memory; /* Insn sets or needs a memory location. */
- char unch_memory; /* Insn sets of needs a "unchanging" MEM. */
- char volatil; /* Insn sets or needs a volatile memory loc. */
- char cc; /* Insn sets or needs the condition codes. */
- HARD_REG_SET regs; /* Which registers are set or needed. */
-};
-
-/* Macro to clear all resources. */
-#define CLEAR_RESOURCE(RES) \
- do { (RES)->memory = (RES)->unch_memory = (RES)->volatil = (RES)->cc = 0; \
- CLEAR_HARD_REG_SET ((RES)->regs); } while (0)
-
-/* Indicates what resources are required at the beginning of the epilogue. */
-static struct resources start_of_epilogue_needs;
-
-/* Indicates what resources are required at function end. */
-static struct resources end_of_function_needs;
-
/* Points to the label before the end of the function. */
static rtx end_of_function_label;
-/* This structure is used to record liveness information at the targets or
- fallthrough insns of branches. We will most likely need the information
- at targets again, so save them in a hash table rather than recomputing them
- each time. */
-
-struct target_info
-{
- int uid; /* INSN_UID of target. */
- struct target_info *next; /* Next info for same hash bucket. */
- HARD_REG_SET live_regs; /* Registers live at target. */
- int block; /* Basic block number containing target. */
- int bb_tick; /* Generation count of basic block info. */
-};
-
-#define TARGET_HASH_PRIME 257
-
-/* Define the hash table itself. */
-static struct target_info **target_hash_table;
-
-/* For each basic block, we maintain a generation number of its basic
- block info, which is updated each time we move an insn from the
- target of a jump. This is the generation number indexed by block
- number. */
-
-static int *bb_ticks;
-
/* Mapping between INSN_UID's and position in the code since INSN_UID's do
not always monotonically increase. */
static int *uid_to_ruid;
@@ -224,25 +175,26 @@ static int *uid_to_ruid;
/* Highest valid index in `uid_to_ruid'. */
static int max_uid;
-static void mark_referenced_resources PROTO((rtx, struct resources *, int));
-static void mark_set_resources PROTO((rtx, struct resources *, int, int));
-static int stop_search_p PROTO((rtx, int));
-static int resource_conflicts_p PROTO((struct resources *,
- struct resources *));
-static int insn_references_resource_p PROTO((rtx, struct resources *, int));
-static int insn_sets_resource_p PROTO((rtx, struct resources *, int));
-static rtx find_end_label PROTO((void));
-static rtx emit_delay_sequence PROTO((rtx, rtx, int));
-static rtx add_to_delay_list PROTO((rtx, rtx));
-static void delete_from_delay_slot PROTO((rtx));
-static void delete_scheduled_jump PROTO((rtx));
-static void note_delay_statistics PROTO((int, int));
-static rtx optimize_skip PROTO((rtx));
-static int get_jump_flags PROTO((rtx, rtx));
-static int rare_destination PROTO((rtx));
-static int mostly_true_jump PROTO((rtx, rtx));
-static rtx get_branch_condition PROTO((rtx, rtx));
-static int condition_dominates_p PROTO((rtx, rtx));
+static int stop_search_p PROTO((rtx, int));
+static int resource_conflicts_p PROTO((struct resources *,
+ struct resources *));
+static int insn_references_resource_p PROTO((rtx, struct resources *, int));
+static int insn_sets_resource_p PROTO((rtx, struct resources *, int));
+static rtx find_end_label PROTO((void));
+static rtx emit_delay_sequence PROTO((rtx, rtx, int));
+static rtx add_to_delay_list PROTO((rtx, rtx));
+static rtx delete_from_delay_slot PROTO((rtx));
+static void delete_scheduled_jump PROTO((rtx));
+static void note_delay_statistics PROTO((int, int));
+static rtx optimize_skip PROTO((rtx));
+static int get_jump_flags PROTO((rtx, rtx));
+static int rare_destination PROTO((rtx));
+static int mostly_true_jump PROTO((rtx, rtx));
+static rtx get_branch_condition PROTO((rtx, rtx));
+static int condition_dominates_p PROTO((rtx, rtx));
+static int redirect_with_delay_slots_safe_p PROTO ((rtx, rtx, rtx));
+static int redirect_with_delay_list_safe_p PROTO ((rtx, rtx, rtx));
+static int check_annul_list_true_false PROTO ((int, rtx));
static rtx steal_delay_list_from_target PROTO((rtx, rtx, rtx, rtx,
struct resources *,
struct resources *,
@@ -253,442 +205,20 @@ static rtx steal_delay_list_from_fallthrough PROTO((rtx, rtx, rtx, rtx,
struct resources *,
struct resources *,
int, int *, int *));
-static void try_merge_delay_insns PROTO((rtx, rtx));
-static rtx redundant_insn PROTO((rtx, rtx, rtx));
-static int own_thread_p PROTO((rtx, rtx, int));
-static int find_basic_block PROTO((rtx));
-static void update_block PROTO((rtx, rtx));
-static int reorg_redirect_jump PROTO((rtx, rtx));
-static void update_reg_dead_notes PROTO((rtx, rtx));
-static void fix_reg_dead_note PROTO((rtx, rtx));
-static void update_reg_unused_notes PROTO((rtx, rtx));
-static void update_live_status PROTO((rtx, rtx));
-static rtx next_insn_no_annul PROTO((rtx));
-static rtx find_dead_or_set_registers PROTO ((rtx, struct resources *, rtx *,
- int, struct resources,
- struct resources));
-static void mark_target_live_regs PROTO((rtx, struct resources *));
-static void fill_simple_delay_slots PROTO((int));
-static rtx fill_slots_from_thread PROTO((rtx, rtx, rtx, rtx, int, int,
- int, int, int *, rtx));
-static void fill_eager_delay_slots PROTO((void));
-static void relax_delay_slots PROTO((rtx));
-static void make_return_insns PROTO((rtx));
-static int redirect_with_delay_slots_safe_p PROTO ((rtx, rtx, rtx));
-static int redirect_with_delay_list_safe_p PROTO ((rtx, rtx, rtx));
-
-/* Given X, some rtl, and RES, a pointer to a `struct resource', mark
- which resources are references by the insn. If INCLUDE_DELAYED_EFFECTS
- is TRUE, resources used by the called routine will be included for
- CALL_INSNs. */
-
-static void
-mark_referenced_resources (x, res, include_delayed_effects)
- register rtx x;
- register struct resources *res;
- register int include_delayed_effects;
-{
- register enum rtx_code code = GET_CODE (x);
- register int i, j;
- register char *format_ptr;
-
- /* Handle leaf items for which we set resource flags. Also, special-case
- CALL, SET and CLOBBER operators. */
- switch (code)
- {
- case CONST:
- case CONST_INT:
- case CONST_DOUBLE:
- case PC:
- case SYMBOL_REF:
- case LABEL_REF:
- return;
-
- case SUBREG:
- if (GET_CODE (SUBREG_REG (x)) != REG)
- mark_referenced_resources (SUBREG_REG (x), res, 0);
- 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:
- for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
- SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
- return;
-
- case MEM:
- /* If this memory shouldn't change, it really isn't referencing
- memory. */
- if (RTX_UNCHANGING_P (x))
- res->unch_memory = 1;
- else
- res->memory = 1;
- res->volatil = MEM_VOLATILE_P (x);
-
- /* Mark registers used to access memory. */
- mark_referenced_resources (XEXP (x, 0), res, 0);
- return;
-
- case CC0:
- res->cc = 1;
- return;
-
- case UNSPEC_VOLATILE:
- case ASM_INPUT:
- /* Traditional asm's are always volatile. */
- res->volatil = 1;
- return;
-
- case TRAP_IF:
- res->volatil = 1;
- break;
-
- case ASM_OPERANDS:
- res->volatil = MEM_VOLATILE_P (x);
-
- /* For all ASM_OPERANDS, we must traverse the vector of input operands.
- We can not just fall through here since then we would be confused
- by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
- traditional asms unlike their normal usage. */
-
- for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
- mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0);
- return;
-
- case CALL:
- /* The first operand will be a (MEM (xxx)) but doesn't really reference
- memory. The second operand may be referenced, though. */
- mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, 0);
- mark_referenced_resources (XEXP (x, 1), res, 0);
- return;
-
- case SET:
- /* Usually, the first operand of SET is set, not referenced. But
- registers used to access memory are referenced. SET_DEST is
- also referenced if it is a ZERO_EXTRACT or SIGN_EXTRACT. */
-
- mark_referenced_resources (SET_SRC (x), res, 0);
-
- x = SET_DEST (x);
- if (GET_CODE (x) == SIGN_EXTRACT || GET_CODE (x) == ZERO_EXTRACT)
- mark_referenced_resources (x, res, 0);
- else if (GET_CODE (x) == SUBREG)
- x = SUBREG_REG (x);
- if (GET_CODE (x) == MEM)
- mark_referenced_resources (XEXP (x, 0), res, 0);
- return;
-
- case CLOBBER:
- return;
-
- case CALL_INSN:
- if (include_delayed_effects)
- {
- /* A CALL references memory, the frame pointer if it exists, the
- stack pointer, any global registers and any registers given in
- USE insns immediately in front of the CALL.
-
- However, we may have moved some of the parameter loading insns
- into the delay slot of this CALL. If so, the USE's for them
- don't count and should be skipped. */
- rtx insn = PREV_INSN (x);
- rtx sequence = 0;
- int seq_size = 0;
- rtx next = NEXT_INSN (x);
- int i;
-
- /* If we are part of a delay slot sequence, point at the SEQUENCE. */
- if (NEXT_INSN (insn) != x)
- {
- next = NEXT_INSN (NEXT_INSN (insn));
- sequence = PATTERN (NEXT_INSN (insn));
- seq_size = XVECLEN (sequence, 0);
- if (GET_CODE (sequence) != SEQUENCE)
- abort ();
- }
-
- res->memory = 1;
- SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM);
- if (frame_pointer_needed)
- {
- SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
-#endif
- }
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i])
- SET_HARD_REG_BIT (res->regs, i);
-
- /* Check for a NOTE_INSN_SETJMP. If it exists, then we must
- assume that this call can need any register.
-
- This is done to be more conservative about how we handle setjmp.
- We assume that they both use and set all registers. Using all
- registers ensures that a register will not be considered dead
- just because it crosses a setjmp call. A register should be
- considered dead only if the setjmp call returns non-zero. */
- if (next && GET_CODE (next) == NOTE
- && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)
- SET_HARD_REG_SET (res->regs);
-
- {
- rtx link;
-
- for (link = CALL_INSN_FUNCTION_USAGE (x);
- link;
- link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == USE)
- {
- for (i = 1; i < seq_size; i++)
- {
- rtx slot_pat = PATTERN (XVECEXP (sequence, 0, i));
- if (GET_CODE (slot_pat) == SET
- && rtx_equal_p (SET_DEST (slot_pat),
- SET_DEST (XEXP (link, 0))))
- break;
- }
- if (i >= seq_size)
- mark_referenced_resources (SET_DEST (XEXP (link, 0)),
- res, 0);
- }
- }
- }
-
- /* ... fall through to other INSN processing ... */
-
- case INSN:
- case JUMP_INSN:
-
-#ifdef INSN_REFERENCES_ARE_DELAYED
- if (! include_delayed_effects
- && INSN_REFERENCES_ARE_DELAYED (x))
- return;
-#endif
-
- /* No special processing, just speed up. */
- mark_referenced_resources (PATTERN (x), res, include_delayed_effects);
- return;
-
- default:
- break;
- }
-
- /* Process each sub-expression and flag what it needs. */
- format_ptr = GET_RTX_FORMAT (code);
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- switch (*format_ptr++)
- {
- case 'e':
- mark_referenced_resources (XEXP (x, i), res, include_delayed_effects);
- break;
-
- case 'E':
- for (j = 0; j < XVECLEN (x, i); j++)
- mark_referenced_resources (XVECEXP (x, i, j), res,
- include_delayed_effects);
- break;
- }
-}
-
-/* Given X, a part of an insn, and a pointer to a `struct resource',
- RES, indicate which resources are modified by the insn. If
- INCLUDE_DELAYED_EFFECTS is nonzero, also mark resources potentially
- set by the called routine.
-
- If IN_DEST is nonzero, it means we are inside a SET. Otherwise,
- objects are being referenced instead of set.
-
- We never mark the insn as modifying the condition code unless it explicitly
- SETs CC0 even though this is not totally correct. The reason for this is
- that we require a SET of CC0 to immediately precede the reference to CC0.
- So if some other insn sets CC0 as a side-effect, we know it cannot affect
- our computation and thus may be placed in a delay slot. */
-
-static void
-mark_set_resources (x, res, in_dest, include_delayed_effects)
- register rtx x;
- register struct resources *res;
- int in_dest;
- int include_delayed_effects;
-{
- register enum rtx_code code;
- register int i, j;
- register char *format_ptr;
-
- restart:
-
- code = GET_CODE (x);
-
- switch (code)
- {
- case NOTE:
- case BARRIER:
- case CODE_LABEL:
- case USE:
- case CONST_INT:
- case CONST_DOUBLE:
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST:
- case PC:
- /* These don't set any resources. */
- return;
-
- case CC0:
- if (in_dest)
- res->cc = 1;
- return;
-
- case CALL_INSN:
- /* Called routine modifies the condition code, memory, any registers
- that aren't saved across calls, global registers and anything
- explicitly CLOBBERed immediately after the CALL_INSN. */
-
- if (include_delayed_effects)
- {
- rtx next = NEXT_INSN (x);
- rtx prev = PREV_INSN (x);
- rtx link;
-
- res->cc = res->memory = 1;
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (call_used_regs[i] || global_regs[i])
- SET_HARD_REG_BIT (res->regs, i);
-
- /* If X is part of a delay slot sequence, then NEXT should be
- the first insn after the sequence. */
- if (NEXT_INSN (prev) != x)
- next = NEXT_INSN (NEXT_INSN (prev));
-
- for (link = CALL_INSN_FUNCTION_USAGE (x);
- link; link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == CLOBBER)
- mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1, 0);
-
- /* Check for a NOTE_INSN_SETJMP. If it exists, then we must
- assume that this call can clobber any register. */
- if (next && GET_CODE (next) == NOTE
- && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)
- SET_HARD_REG_SET (res->regs);
- }
-
- /* ... and also what its RTL says it modifies, if anything. */
-
- case JUMP_INSN:
- case INSN:
-
- /* An insn consisting of just a CLOBBER (or USE) is just for flow
- and doesn't actually do anything, so we ignore it. */
-
-#ifdef INSN_SETS_ARE_DELAYED
- if (! include_delayed_effects
- && INSN_SETS_ARE_DELAYED (x))
- return;
-#endif
-
- x = PATTERN (x);
- if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
- goto restart;
- return;
-
- case SET:
- /* If the source of a SET is a CALL, this is actually done by
- the called routine. So only include it if we are to include the
- effects of the calling routine. */
-
- mark_set_resources (SET_DEST (x), res,
- (include_delayed_effects
- || GET_CODE (SET_SRC (x)) != CALL),
- 0);
-
- mark_set_resources (SET_SRC (x), res, 0, 0);
- return;
-
- case CLOBBER:
- mark_set_resources (XEXP (x, 0), res, 1, 0);
- return;
-
- case SEQUENCE:
- for (i = 0; i < XVECLEN (x, 0); i++)
- if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
- && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))
- mark_set_resources (XVECEXP (x, 0, i), res, 0,
- include_delayed_effects);
- return;
-
- case POST_INC:
- case PRE_INC:
- case POST_DEC:
- case PRE_DEC:
- mark_set_resources (XEXP (x, 0), res, 1, 0);
- return;
-
- case ZERO_EXTRACT:
- mark_set_resources (XEXP (x, 0), res, in_dest, 0);
- mark_set_resources (XEXP (x, 1), res, 0, 0);
- mark_set_resources (XEXP (x, 2), res, 0, 0);
- return;
-
- case MEM:
- if (in_dest)
- {
- res->memory = 1;
- res->unch_memory = RTX_UNCHANGING_P (x);
- res->volatil = MEM_VOLATILE_P (x);
- }
-
- mark_set_resources (XEXP (x, 0), res, 0, 0);
- 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:
- if (in_dest)
- for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
- SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
- return;
-
- default:
- break;
- }
-
- /* Process each sub-expression and flag what it needs. */
- format_ptr = GET_RTX_FORMAT (code);
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- switch (*format_ptr++)
- {
- case 'e':
- mark_set_resources (XEXP (x, i), res, in_dest, include_delayed_effects);
- break;
-
- case 'E':
- for (j = 0; j < XVECLEN (x, i); j++)
- mark_set_resources (XVECEXP (x, i, j), res, in_dest,
- include_delayed_effects);
- break;
- }
-}
+static void try_merge_delay_insns PROTO((rtx, rtx));
+static rtx redundant_insn PROTO((rtx, rtx, rtx));
+static int own_thread_p PROTO((rtx, rtx, int));
+static void update_block PROTO((rtx, rtx));
+static int reorg_redirect_jump PROTO((rtx, rtx));
+static void update_reg_dead_notes PROTO((rtx, rtx));
+static void fix_reg_dead_note PROTO((rtx, rtx));
+static void update_reg_unused_notes PROTO((rtx, rtx));
+static void fill_simple_delay_slots PROTO((int));
+static rtx fill_slots_from_thread PROTO((rtx, rtx, rtx, rtx, int, int,
+ int, int, int *, rtx));
+static void fill_eager_delay_slots PROTO((void));
+static void relax_delay_slots PROTO((rtx));
+static void make_return_insns PROTO((rtx));
/* Return TRUE if this insn should stop the search for insn to fill delay
slots. LABELS_P indicates that labels should terminate the search.
@@ -988,16 +518,7 @@ add_to_delay_list (insn, delay_list)
if (delay_list == 0)
{
- struct target_info *tinfo;
-
- for (tinfo = target_hash_table[INSN_UID (insn) % TARGET_HASH_PRIME];
- tinfo; tinfo = tinfo->next)
- if (tinfo->uid == INSN_UID (insn))
- break;
-
- if (tinfo)
- tinfo->block = -1;
-
+ clear_hashed_info_for_insn (insn);
return gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX);
}
@@ -1008,10 +529,10 @@ add_to_delay_list (insn, delay_list)
return delay_list;
}
-/* Delete INSN from the delay slot of the insn that it is in. This may
- produce an insn without anything in its delay slots. */
+/* Delete INSN from the delay slot of the insn that it is in, which may
+ produce an insn with no delay slots. Return the new insn. */
-static void
+static rtx
delete_from_delay_slot (insn)
rtx insn;
{
@@ -1060,6 +581,8 @@ delete_from_delay_slot (insn)
/* Show we need to fill this insn again. */
obstack_ptr_grow (&unfilled_slots_obstack, trial);
+
+ return trial;
}
/* Delete INSN, a JUMP_INSN. If it is a conditional jump, we must track down
@@ -1377,7 +900,7 @@ mostly_true_jump (jump_insn, condition)
always gives a correct answer. */
if (flag_branch_probabilities)
{
- rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);;
+ rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
if (note)
{
int prob = XINT (note, 0);
@@ -1624,6 +1147,32 @@ redirect_with_delay_list_safe_p (jump, newlabel, delay_list)
return (li == NULL);
}
+/* DELAY_LIST is a list of insns that have already been placed into delay
+ slots. See if all of them have the same annulling status as ANNUL_TRUE_P.
+ If not, return 0; otherwise return 1. */
+
+static int
+check_annul_list_true_false (annul_true_p, delay_list)
+ int annul_true_p;
+ rtx delay_list;
+{
+ rtx temp;
+
+ if (delay_list)
+ {
+ for (temp = delay_list; temp; temp = XEXP (temp, 1))
+ {
+ rtx trial = XEXP (temp, 0);
+
+ if ((annul_true_p && INSN_FROM_TARGET_P (trial))
+ || (!annul_true_p && !INSN_FROM_TARGET_P (trial)))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
/* INSN branches to an insn whose pattern SEQ is a SEQUENCE. Given that
the condition tested by INSN is CONDITION and the resources shown in
@@ -1664,7 +1213,9 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
int total_slots_filled = *pslots_filled;
rtx new_delay_list = 0;
int must_annul = *pannul_p;
+ int used_annul = 0;
int i;
+ struct resources cc_set;
/* We can't do anything if there are more delay slots in SEQ than we
can handle, or if we don't know that it will be a taken branch.
@@ -1674,7 +1225,23 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
Also, exit if the branch has more than one set, since then it is computing
other results that can't be ignored, e.g. the HPPA mov&branch instruction.
??? It may be possible to move other sets into INSN in addition to
- moving the instructions in the delay slots. */
+ moving the instructions in the delay slots.
+
+ We can not steal the delay list if one of the instructions in the
+ current delay_list modifies the condition codes and the jump in the
+ sequence is a conditional jump. We can not do this because we can
+ not change the direction of the jump because the condition codes
+ will effect the direction of the jump in the sequence. */
+
+ CLEAR_RESOURCE (&cc_set);
+ for (temp = delay_list; temp; temp = XEXP (temp, 1))
+ {
+ rtx trial = XEXP (temp, 0);
+
+ mark_set_resources (trial, &cc_set, 0, 1);
+ if (insn_references_resource_p (XVECEXP (seq , 0, 0), &cc_set, 0))
+ return delay_list;
+ }
if (XVECLEN (seq, 0) - 1 > slots_remaining
|| ! condition_dominates_p (condition, XVECEXP (seq, 0, 0))
@@ -1714,9 +1281,15 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
|| (! insn_sets_resource_p (trial, other_needed, 0)
&& ! may_trap_p (PATTERN (trial)))))
? eligible_for_delay (insn, total_slots_filled, trial, flags)
- : (must_annul = 1,
- eligible_for_annul_false (insn, total_slots_filled, trial, flags)))
+ : (must_annul || (delay_list == NULL && new_delay_list == NULL))
+ && (must_annul = 1,
+ check_annul_list_true_false (0, delay_list)
+ && check_annul_list_true_false (0, new_delay_list)
+ && eligible_for_annul_false (insn, total_slots_filled,
+ trial, flags)))
{
+ if (must_annul)
+ used_annul = 1;
temp = copy_rtx (trial);
INSN_FROM_TARGET_P (temp) = 1;
new_delay_list = add_to_delay_list (temp, new_delay_list);
@@ -1735,7 +1308,8 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
/* Add any new insns to the delay list and update the count of the
number of slots filled. */
*pslots_filled = total_slots_filled;
- *pannul_p = must_annul;
+ if (used_annul)
+ *pannul_p = 1;
if (delay_list == 0)
return new_delay_list;
@@ -1765,6 +1339,8 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
{
int i;
int flags;
+ int must_annul = *pannul_p;
+ int used_annul = 0;
flags = get_jump_flags (insn, JUMP_LABEL (insn));
@@ -1798,14 +1374,17 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
continue;
}
- if (! *pannul_p
+ if (! must_annul
&& ((condition == const_true_rtx
|| (! insn_sets_resource_p (trial, other_needed, 0)
&& ! may_trap_p (PATTERN (trial)))))
? eligible_for_delay (insn, *pslots_filled, trial, flags)
- : (*pannul_p = 1,
- eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
+ : (must_annul || delay_list == NULL) && (must_annul = 1,
+ check_annul_list_true_false (1, delay_list)
+ && eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
{
+ if (must_annul)
+ used_annul = 1;
delete_from_delay_slot (trial);
delay_list = add_to_delay_list (trial, delay_list);
@@ -1816,8 +1395,11 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
break;
}
+ if (used_annul)
+ *pannul_p = 1;
return delay_list;
}
+
/* Try merging insns starting at THREAD which match exactly the insns in
INSN's delay list.
@@ -1849,13 +1431,15 @@ try_merge_delay_insns (insn, thread)
CLEAR_RESOURCE (&set);
/* If this is not an annulling branch, take into account anything needed in
- NEXT_TO_MATCH. This prevents two increments from being incorrectly
+ INSN's delay slot. This prevents two increments from being incorrectly
folded into one. If we are annulling, this would be the correct
thing to do. (The alternative, looking at things set in NEXT_TO_MATCH
will essentially disable this optimization. This method is somewhat of
a kludge, but I don't see a better way.) */
if (! annul_p)
- mark_referenced_resources (next_to_match, &needed, 1);
+ for (i = 1 ; i < num_slots ; i++)
+ if (XVECEXP (PATTERN (insn), 0, i))
+ mark_referenced_resources (XVECEXP (PATTERN (insn), 0, i), &needed, 1);
for (trial = thread; !stop_search_p (trial, 1); trial = next_trial)
{
@@ -1904,8 +1488,6 @@ try_merge_delay_insns (insn, thread)
break;
next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
- if (! annul_p)
- mark_referenced_resources (next_to_match, &needed, 1);
}
mark_set_resources (trial, &set, 0, 1);
@@ -1941,8 +1523,12 @@ try_merge_delay_insns (insn, thread)
{
if (! annul_p)
{
+ rtx new;
+
update_block (dtrial, thread);
- delete_from_delay_slot (dtrial);
+ new = delete_from_delay_slot (dtrial);
+ if (INSN_DELETED_P (thread))
+ thread = new;
INSN_FROM_TARGET_P (next_to_match) = 0;
}
else
@@ -1954,6 +1540,13 @@ try_merge_delay_insns (insn, thread)
next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
}
+ else
+ {
+ /* Keep track of the set/referenced resources for the delay
+ slots of any trial insns we encounter. */
+ mark_set_resources (dtrial, &set, 0, 1);
+ mark_referenced_resources (dtrial, &needed, 1);
+ }
}
}
@@ -1968,8 +1561,12 @@ try_merge_delay_insns (insn, thread)
{
if (GET_MODE (merged_insns) == SImode)
{
+ rtx new;
+
update_block (XEXP (merged_insns, 0), thread);
- delete_from_delay_slot (XEXP (merged_insns, 0));
+ new = delete_from_delay_slot (XEXP (merged_insns, 0));
+ if (INSN_DELETED_P (thread))
+ thread = new;
}
else
{
@@ -2248,41 +1845,6 @@ own_thread_p (thread, label, allow_fallthrough)
return 1;
}
-/* Find the number of the basic block that starts closest to INSN. Return -1
- if we couldn't find such a basic block. */
-
-static int
-find_basic_block (insn)
- rtx insn;
-{
- int i;
-
- /* Scan backwards to the previous BARRIER. Then see if we can find a
- label that starts a basic block. Return the basic block number. */
-
- for (insn = prev_nonnote_insn (insn);
- insn && GET_CODE (insn) != BARRIER;
- insn = prev_nonnote_insn (insn))
- ;
-
- /* The start of the function is basic block zero. */
- if (insn == 0)
- return 0;
-
- /* See if any of the upcoming CODE_LABELs start a basic block. If we reach
- anything other than a CODE_LABEL or note, we can't find this code. */
- for (insn = next_nonnote_insn (insn);
- insn && GET_CODE (insn) == CODE_LABEL;
- insn = next_nonnote_insn (insn))
- {
- for (i = 0; i < n_basic_blocks; i++)
- if (insn == basic_block_head[i])
- return i;
- }
-
- return -1;
-}
-
/* Called when INSN is being moved from a location near the target of a jump.
We leave a marker of the form (use (INSN)) immediately in front
of WHERE for mark_target_live_regs. These markers will be deleted when
@@ -2297,8 +1859,6 @@ update_block (insn, where)
rtx insn;
rtx where;
{
- int b;
-
/* Ignore if this was in a delay slot and it came from the target of
a branch. */
if (INSN_FROM_TARGET_P (insn))
@@ -2309,9 +1869,7 @@ update_block (insn, where)
/* INSN might be making a value live in a block where it didn't use to
be. So recompute liveness information for this block. */
- b = find_basic_block (insn);
- if (b != -1)
- bb_ticks[b]++;
+ incr_ticks_for_insn (insn);
}
/* Similar to REDIRECT_JUMP except that we update the BB_TICKS entry for
@@ -2322,11 +1880,7 @@ reorg_redirect_jump (jump, nlabel)
rtx jump;
rtx nlabel;
{
- int b = find_basic_block (jump);
-
- if (b != -1)
- bb_ticks[b]++;
-
+ incr_ticks_for_insn (jump);
return redirect_jump (jump, nlabel);
}
@@ -2426,557 +1980,6 @@ update_reg_unused_notes (insn, redundant_insn)
}
}
-/* Marks registers possibly live at the current place being scanned by
- mark_target_live_regs. Used only by next two function. */
-
-static HARD_REG_SET current_live_regs;
-
-/* Marks registers for which we have seen a REG_DEAD note but no assignment.
- Also only used by the next two functions. */
-
-static HARD_REG_SET pending_dead_regs;
-
-/* Utility function called from mark_target_live_regs via note_stores.
- It deadens any CLOBBERed registers and livens any SET registers. */
-
-static void
-update_live_status (dest, x)
- rtx dest;
- rtx x;
-{
- int first_regno, last_regno;
- int i;
-
- if (GET_CODE (dest) != REG
- && (GET_CODE (dest) != SUBREG || GET_CODE (SUBREG_REG (dest)) != REG))
- return;
-
- if (GET_CODE (dest) == SUBREG)
- first_regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
- else
- first_regno = REGNO (dest);
-
- last_regno = first_regno + HARD_REGNO_NREGS (first_regno, GET_MODE (dest));
-
- if (GET_CODE (x) == CLOBBER)
- for (i = first_regno; i < last_regno; i++)
- CLEAR_HARD_REG_BIT (current_live_regs, i);
- else
- for (i = first_regno; i < last_regno; i++)
- {
- SET_HARD_REG_BIT (current_live_regs, i);
- CLEAR_HARD_REG_BIT (pending_dead_regs, i);
- }
-}
-
-/* Similar to next_insn, but ignores insns in the delay slots of
- an annulled branch. */
-
-static rtx
-next_insn_no_annul (insn)
- rtx insn;
-{
- if (insn)
- {
- /* If INSN is an annulled branch, skip any insns from the target
- of the branch. */
- if (INSN_ANNULLED_BRANCH_P (insn)
- && NEXT_INSN (PREV_INSN (insn)) != insn)
- while (INSN_FROM_TARGET_P (NEXT_INSN (insn)))
- insn = NEXT_INSN (insn);
-
- insn = NEXT_INSN (insn);
- if (insn && GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SEQUENCE)
- insn = XVECEXP (PATTERN (insn), 0, 0);
- }
-
- return insn;
-}
-
-/* A subroutine of mark_target_live_regs. Search forward from TARGET
- looking for registers that are set before they are used. These are dead.
- Stop after passing a few conditional jumps, and/or a small
- number of unconditional branches. */
-
-static rtx
-find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
- rtx target;
- struct resources *res;
- rtx *jump_target;
- int jump_count;
- struct resources set, needed;
-{
- HARD_REG_SET scratch;
- rtx insn, next;
- rtx jump_insn = 0;
- int i;
-
- for (insn = target; insn; insn = next)
- {
- rtx this_jump_insn = insn;
-
- next = NEXT_INSN (insn);
- switch (GET_CODE (insn))
- {
- case CODE_LABEL:
- /* After a label, any pending dead registers that weren't yet
- used can be made dead. */
- AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs);
- AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
- CLEAR_HARD_REG_SET (pending_dead_regs);
-
- if (CODE_LABEL_NUMBER (insn) < max_label_num_after_reload)
- {
- /* All spill registers are dead at a label, so kill all of the
- ones that aren't needed also. */
- COPY_HARD_REG_SET (scratch, used_spill_regs);
- AND_COMPL_HARD_REG_SET (scratch, needed.regs);
- AND_COMPL_HARD_REG_SET (res->regs, scratch);
- }
- continue;
-
- case BARRIER:
- case NOTE:
- continue;
-
- case INSN:
- if (GET_CODE (PATTERN (insn)) == USE)
- {
- /* If INSN is a USE made by update_block, we care about the
- underlying insn. Any registers set by the underlying insn
- are live since the insn is being done somewhere else. */
- if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
- mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1);
-
- /* All other USE insns are to be ignored. */
- continue;
- }
- else if (GET_CODE (PATTERN (insn)) == CLOBBER)
- continue;
- else if (GET_CODE (PATTERN (insn)) == SEQUENCE)
- {
- /* An unconditional jump can be used to fill the delay slot
- of a call, so search for a JUMP_INSN in any position. */
- for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- {
- this_jump_insn = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (this_jump_insn) == JUMP_INSN)
- break;
- }
- }
-
- default:
- break;
- }
-
- if (GET_CODE (this_jump_insn) == JUMP_INSN)
- {
- if (jump_count++ < 10)
- {
- if (simplejump_p (this_jump_insn)
- || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
- {
- next = JUMP_LABEL (this_jump_insn);
- if (jump_insn == 0)
- {
- jump_insn = insn;
- if (jump_target)
- *jump_target = JUMP_LABEL (this_jump_insn);
- }
- }
- else if (condjump_p (this_jump_insn)
- || condjump_in_parallel_p (this_jump_insn))
- {
- struct resources target_set, target_res;
- struct resources fallthrough_res;
-
- /* We can handle conditional branches here by following
- both paths, and then IOR the results of the two paths
- together, which will give us registers that are dead
- on both paths. Since this is expensive, we give it
- a much higher cost than unconditional branches. The
- cost was chosen so that we will follow at most 1
- conditional branch. */
-
- jump_count += 4;
- if (jump_count >= 10)
- break;
-
- mark_referenced_resources (insn, &needed, 1);
-
- /* For an annulled branch, mark_set_resources ignores slots
- filled by instructions from the target. This is correct
- if the branch is not taken. Since we are following both
- paths from the branch, we must also compute correct info
- if the branch is taken. We do this by inverting all of
- the INSN_FROM_TARGET_P bits, calling mark_set_resources,
- and then inverting the INSN_FROM_TARGET_P bits again. */
-
- if (GET_CODE (PATTERN (insn)) == SEQUENCE
- && INSN_ANNULLED_BRANCH_P (this_jump_insn))
- {
- for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
- INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
- = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
-
- target_set = set;
- mark_set_resources (insn, &target_set, 0, 1);
-
- for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
- INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
- = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
-
- mark_set_resources (insn, &set, 0, 1);
- }
- else
- {
- mark_set_resources (insn, &set, 0, 1);
- target_set = set;
- }
-
- target_res = *res;
- COPY_HARD_REG_SET (scratch, target_set.regs);
- AND_COMPL_HARD_REG_SET (scratch, needed.regs);
- AND_COMPL_HARD_REG_SET (target_res.regs, scratch);
-
- fallthrough_res = *res;
- COPY_HARD_REG_SET (scratch, set.regs);
- AND_COMPL_HARD_REG_SET (scratch, needed.regs);
- AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
-
- find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
- &target_res, 0, jump_count,
- target_set, needed);
- find_dead_or_set_registers (next,
- &fallthrough_res, 0, jump_count,
- set, needed);
- IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs);
- AND_HARD_REG_SET (res->regs, fallthrough_res.regs);
- break;
- }
- else
- break;
- }
- else
- {
- /* Don't try this optimization if we expired our jump count
- above, since that would mean there may be an infinite loop
- in the function being compiled. */
- jump_insn = 0;
- break;
- }
- }
-
- mark_referenced_resources (insn, &needed, 1);
- mark_set_resources (insn, &set, 0, 1);
-
- COPY_HARD_REG_SET (scratch, set.regs);
- AND_COMPL_HARD_REG_SET (scratch, needed.regs);
- AND_COMPL_HARD_REG_SET (res->regs, scratch);
- }
-
- return jump_insn;
-}
-
-/* Set the resources that are live at TARGET.
-
- If TARGET is zero, we refer to the end of the current function and can
- return our precomputed value.
-
- Otherwise, we try to find out what is live by consulting the basic block
- information. This is tricky, because we must consider the actions of
- reload and jump optimization, which occur after the basic block information
- has been computed.
-
- Accordingly, we proceed as follows::
-
- We find the previous BARRIER and look at all immediately following labels
- (with no intervening active insns) to see if any of them start a basic
- block. If we hit the start of the function first, we use block 0.
-
- Once we have found a basic block and a corresponding first insns, we can
- accurately compute the live status from basic_block_live_regs and
- reg_renumber. (By starting at a label following a BARRIER, we are immune
- to actions taken by reload and jump.) Then we scan all insns between
- that point and our target. For each CLOBBER (or for call-clobbered regs
- when we pass a CALL_INSN), mark the appropriate registers are dead. For
- a SET, mark them as live.
-
- We have to be careful when using REG_DEAD notes because they are not
- updated by such things as find_equiv_reg. So keep track of registers
- marked as dead that haven't been assigned to, and mark them dead at the
- next CODE_LABEL since reload and jump won't propagate values across labels.
-
- If we cannot find the start of a basic block (should be a very rare
- case, if it can happen at all), mark everything as potentially live.
-
- Next, scan forward from TARGET looking for things set or clobbered
- before they are used. These are not live.
-
- Because we can be called many times on the same target, save our results
- in a hash table indexed by INSN_UID. */
-
-static void
-mark_target_live_regs (target, res)
- rtx target;
- struct resources *res;
-{
- int b = -1;
- int i;
- struct target_info *tinfo;
- rtx insn;
- rtx jump_insn = 0;
- rtx jump_target;
- HARD_REG_SET scratch;
- struct resources set, needed;
-
- /* Handle end of function. */
- if (target == 0)
- {
- *res = end_of_function_needs;
- return;
- }
-
- /* We have to assume memory is needed, but the CC isn't. */
- res->memory = 1;
- res->volatil = res->unch_memory = 0;
- res->cc = 0;
-
- /* See if we have computed this value already. */
- for (tinfo = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
- tinfo; tinfo = tinfo->next)
- if (tinfo->uid == INSN_UID (target))
- break;
-
- /* Start by getting the basic block number. If we have saved information,
- we can get it from there unless the insn at the start of the basic block
- has been deleted. */
- if (tinfo && tinfo->block != -1
- && ! INSN_DELETED_P (basic_block_head[tinfo->block]))
- b = tinfo->block;
-
- if (b == -1)
- b = find_basic_block (target);
-
- if (tinfo)
- {
- /* If the information is up-to-date, use it. Otherwise, we will
- update it below. */
- if (b == tinfo->block && b != -1 && tinfo->bb_tick == bb_ticks[b])
- {
- COPY_HARD_REG_SET (res->regs, tinfo->live_regs);
- return;
- }
- }
- else
- {
- /* Allocate a place to put our results and chain it into the
- hash table. */
- tinfo = (struct target_info *) oballoc (sizeof (struct target_info));
- tinfo->uid = INSN_UID (target);
- tinfo->block = b;
- tinfo->next = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
- target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME] = tinfo;
- }
-
- CLEAR_HARD_REG_SET (pending_dead_regs);
-
- /* If we found a basic block, get the live registers from it and update
- them with anything set or killed between its start and the insn before
- TARGET. Otherwise, we must assume everything is live. */
- if (b != -1)
- {
- regset regs_live = basic_block_live_at_start[b];
- int j;
- int regno;
- rtx start_insn, stop_insn;
-
- /* Compute hard regs live at start of block -- this is the real hard regs
- marked live, plus live pseudo regs that have been renumbered to
- hard regs. */
-
- REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
-
- EXECUTE_IF_SET_IN_REG_SET
- (regs_live, FIRST_PSEUDO_REGISTER, i,
- {
- if ((regno = reg_renumber[i]) >= 0)
- for (j = regno;
- j < regno + HARD_REGNO_NREGS (regno,
- PSEUDO_REGNO_MODE (i));
- j++)
- SET_HARD_REG_BIT (current_live_regs, j);
- });
-
- /* Get starting and ending insn, handling the case where each might
- be a SEQUENCE. */
- start_insn = (b == 0 ? get_insns () : basic_block_head[b]);
- stop_insn = target;
-
- if (GET_CODE (start_insn) == INSN
- && GET_CODE (PATTERN (start_insn)) == SEQUENCE)
- start_insn = XVECEXP (PATTERN (start_insn), 0, 0);
-
- if (GET_CODE (stop_insn) == INSN
- && GET_CODE (PATTERN (stop_insn)) == SEQUENCE)
- stop_insn = next_insn (PREV_INSN (stop_insn));
-
- for (insn = start_insn; insn != stop_insn;
- insn = next_insn_no_annul (insn))
- {
- rtx link;
- rtx real_insn = insn;
-
- /* If this insn is from the target of a branch, it isn't going to
- be used in the sequel. If it is used in both cases, this
- test will not be true. */
- if (INSN_FROM_TARGET_P (insn))
- continue;
-
- /* If this insn is a USE made by update_block, we care about the
- underlying insn. */
- if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
- && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
- real_insn = XEXP (PATTERN (insn), 0);
-
- if (GET_CODE (real_insn) == CALL_INSN)
- {
- /* CALL clobbers all call-used regs that aren't fixed except
- sp, ap, and fp. Do this before setting the result of the
- call live. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (call_used_regs[i]
- && i != STACK_POINTER_REGNUM && i != FRAME_POINTER_REGNUM
- && i != ARG_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && i != HARD_FRAME_POINTER_REGNUM
-#endif
-#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
-#endif
-#ifdef PIC_OFFSET_TABLE_REGNUM
- && ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
-#endif
- )
- CLEAR_HARD_REG_BIT (current_live_regs, i);
-
- /* A CALL_INSN sets any global register live, since it may
- have been modified by the call. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i])
- SET_HARD_REG_BIT (current_live_regs, i);
- }
-
- /* Mark anything killed in an insn to be deadened at the next
- label. Ignore USE insns; the only REG_DEAD notes will be for
- parameters. But they might be early. A CALL_INSN will usually
- clobber registers used for parameters. It isn't worth bothering
- with the unlikely case when it won't. */
- if ((GET_CODE (real_insn) == INSN
- && GET_CODE (PATTERN (real_insn)) != USE
- && GET_CODE (PATTERN (real_insn)) != CLOBBER)
- || GET_CODE (real_insn) == JUMP_INSN
- || GET_CODE (real_insn) == CALL_INSN)
- {
- for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_DEAD
- && GET_CODE (XEXP (link, 0)) == REG
- && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
- {
- int first_regno = REGNO (XEXP (link, 0));
- int last_regno
- = (first_regno
- + HARD_REGNO_NREGS (first_regno,
- GET_MODE (XEXP (link, 0))));
-
- for (i = first_regno; i < last_regno; i++)
- SET_HARD_REG_BIT (pending_dead_regs, i);
- }
-
- note_stores (PATTERN (real_insn), update_live_status);
-
- /* If any registers were unused after this insn, kill them.
- These notes will always be accurate. */
- for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_UNUSED
- && GET_CODE (XEXP (link, 0)) == REG
- && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
- {
- int first_regno = REGNO (XEXP (link, 0));
- int last_regno
- = (first_regno
- + HARD_REGNO_NREGS (first_regno,
- GET_MODE (XEXP (link, 0))));
-
- for (i = first_regno; i < last_regno; i++)
- CLEAR_HARD_REG_BIT (current_live_regs, i);
- }
- }
-
- else if (GET_CODE (real_insn) == CODE_LABEL)
- {
- /* A label clobbers the pending dead registers since neither
- reload nor jump will propagate a value across a label. */
- AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
- CLEAR_HARD_REG_SET (pending_dead_regs);
- }
-
- /* The beginning of the epilogue corresponds to the end of the
- RTL chain when there are no epilogue insns. Certain resources
- are implicitly required at that point. */
- else if (GET_CODE (real_insn) == NOTE
- && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG)
- IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs);
- }
-
- COPY_HARD_REG_SET (res->regs, current_live_regs);
- tinfo->block = b;
- tinfo->bb_tick = bb_ticks[b];
- }
- else
- /* We didn't find the start of a basic block. Assume everything
- in use. This should happen only extremely rarely. */
- SET_HARD_REG_SET (res->regs);
-
- CLEAR_RESOURCE (&set);
- CLEAR_RESOURCE (&needed);
-
- jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
- set, needed);
-
- /* If we hit an unconditional branch, we have another way of finding out
- what is live: we can see what is live at the branch target and include
- anything used but not set before the branch. The only things that are
- live are those that are live using the above test and the test below. */
-
- if (jump_insn)
- {
- struct resources new_resources;
- rtx stop_insn = next_active_insn (jump_insn);
-
- mark_target_live_regs (next_active_insn (jump_target), &new_resources);
- CLEAR_RESOURCE (&set);
- CLEAR_RESOURCE (&needed);
-
- /* Include JUMP_INSN in the needed registers. */
- for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
- {
- mark_referenced_resources (insn, &needed, 1);
-
- COPY_HARD_REG_SET (scratch, needed.regs);
- AND_COMPL_HARD_REG_SET (scratch, set.regs);
- IOR_HARD_REG_SET (new_resources.regs, scratch);
-
- mark_set_resources (insn, &set, 0, 1);
- }
-
- AND_HARD_REG_SET (res->regs, new_resources.regs);
- }
-
- COPY_HARD_REG_SET (tinfo->live_regs, res->regs);
-}
-
/* Scan a function looking for insns that need a delay slot and find insns to
put into the delay slot.
@@ -3131,7 +2134,7 @@ fill_simple_delay_slots (non_jumps_p)
#ifdef HAVE_cc0
/* Can't separate set of cc0 from its use. */
&& ! (reg_mentioned_p (cc0_rtx, pat)
- && ! sets_cc0_p (cc0_rtx, pat))
+ && ! sets_cc0_p (pat))
#endif
)
{
@@ -3249,9 +2252,11 @@ fill_simple_delay_slots (non_jumps_p)
break;
else if (JUMP_LABEL (trial_delay) != target)
{
- mark_target_live_regs
- (next_active_insn (JUMP_LABEL (trial_delay)),
- &needed_at_jump);
+ rtx ninsn =
+ next_active_insn (JUMP_LABEL (trial_delay));
+
+ mark_target_live_regs (get_insns (), ninsn,
+ &needed_at_jump);
needed.memory |= needed_at_jump.memory;
needed.unch_memory |= needed_at_jump.unch_memory;
IOR_HARD_REG_SET (needed.regs, needed_at_jump.regs);
@@ -3394,7 +2399,8 @@ fill_simple_delay_slots (non_jumps_p)
SET_HARD_REG_BIT (needed.regs, HARD_FRAME_POINTER_REGNUM);
#endif
#ifdef EXIT_IGNORE_STACK
- if (! EXIT_IGNORE_STACK)
+ if (! EXIT_IGNORE_STACK
+ || current_function_sp_is_unchanging)
#endif
SET_HARD_REG_BIT (needed.regs, STACK_POINTER_REGNUM);
}
@@ -3436,7 +2442,7 @@ fill_simple_delay_slots (non_jumps_p)
current_function_epilogue_delay_list
= gen_rtx_INSN_LIST (VOIDmode, trial,
current_function_epilogue_delay_list);
- mark_referenced_resources (trial, &end_of_function_needs, 1);
+ mark_end_of_function_resources (trial, 1);
update_block (trial, trial);
delete_insn (trial);
@@ -3518,7 +2524,7 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
if (condition == const_true_rtx)
CLEAR_RESOURCE (&opposite_needed);
else
- mark_target_live_regs (opposite_thread, &opposite_needed);
+ mark_target_live_regs (get_insns (), opposite_thread, &opposite_needed);
/* If the insn at THREAD can be split, do it here to avoid having to
update THREAD and NEW_THREAD if it is done in the loop below. Also
@@ -3600,9 +2606,10 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
/* There are two ways we can win: If TRIAL doesn't set anything
needed at the opposite thread and can't trap, or if it can
go into an annulled delay slot. */
- if (condition == const_true_rtx
- || (! insn_sets_resource_p (trial, &opposite_needed, 1)
- && ! may_trap_p (pat)))
+ if (!must_annul
+ && (condition == const_true_rtx
+ || (! insn_sets_resource_p (trial, &opposite_needed, 1)
+ && ! may_trap_p (pat))))
{
old_trial = trial;
trial = try_split (pat, trial, 0);
@@ -3630,9 +2637,11 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
if (thread == old_trial)
thread = trial;
pat = PATTERN (trial);
- if ((thread_if_true
- ? eligible_for_annul_false (insn, *pslots_filled, trial, flags)
- : eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
+ if ((must_annul || delay_list == NULL) && (thread_if_true
+ ? check_annul_list_true_false (0, delay_list)
+ && eligible_for_annul_false (insn, *pslots_filled, trial, flags)
+ : check_annul_list_true_false (1, delay_list)
+ && eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
{
rtx temp;
@@ -3668,8 +2677,6 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
delay_list = add_to_delay_list (temp, delay_list);
- mark_set_resources (trial, &opposite_needed, 0, 1);
-
if (slots_to_fill == ++(*pslots_filled))
{
/* Even though we have filled all the slots, we
@@ -3747,9 +2754,7 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
{
/* If this is the `true' thread, we will want to follow the jump,
so we can only do this if we have taken everything up to here. */
- if (thread_if_true && trial == new_thread
- && ! insn_references_resource_p (XVECEXP (PATTERN (trial), 0, 0),
- &opposite_needed, 0))
+ if (thread_if_true && trial == new_thread)
delay_list
= steal_delay_list_from_target (insn, condition, PATTERN (trial),
delay_list, &set, &needed,
@@ -3810,8 +2815,7 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
insn);
if (recog_memoized (ninsn) < 0
- || (insn_extract (ninsn),
- ! constrain_operands (INSN_CODE (ninsn), 1)))
+ || (extract_insn (ninsn), ! constrain_operands (1)))
{
delete_insn (ninsn);
return 0;
@@ -4099,7 +3103,7 @@ relax_delay_slots (first)
&& (other = prev_active_insn (insn)) != 0
&& (condjump_p (other) || condjump_in_parallel_p (other))
&& no_labels_between_p (other, insn)
- && 0 < mostly_true_jump (other,
+ && 0 > mostly_true_jump (other,
get_branch_condition (other,
JUMP_LABEL (other))))
{
@@ -4136,6 +3140,40 @@ relax_delay_slots (first)
continue;
}
+ /* See if we have a RETURN insn with a filled delay slot followed
+ by a RETURN insn with an unfilled a delay slot. If so, we can delete
+ the first RETURN (but not it's delay insn). This gives the same
+ effect in fewer instructions.
+
+ Only do so if optimizing for size since this results in slower, but
+ smaller code. */
+ if (optimize_size
+ && GET_CODE (PATTERN (delay_insn)) == RETURN
+ && next
+ && GET_CODE (next) == JUMP_INSN
+ && GET_CODE (PATTERN (next)) == RETURN)
+ {
+ int i;
+
+ /* Delete the RETURN and just execute the delay list insns.
+
+ We do this by deleting the INSN containing the SEQUENCE, then
+ re-emitting the insns separately, and then deleting the RETURN.
+ This allows the count of the jump target to be properly
+ decremented. */
+
+ /* Clear the from target bit, since these insns are no longer
+ in delay slots. */
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
+
+ trial = PREV_INSN (insn);
+ delete_insn (insn);
+ emit_insn_after (pat, trial);
+ delete_scheduled_jump (delay_insn);
+ continue;
+ }
+
/* Now look only at the cases where we have a filled JUMP_INSN. */
if (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) != JUMP_INSN
|| ! (condjump_p (XVECEXP (PATTERN (insn), 0, 0))
@@ -4486,7 +3524,7 @@ dbr_schedule (first, file)
epilogue_insn = insn;
}
- uid_to_ruid = (int *) alloca ((max_uid + 1) * sizeof (int *));
+ uid_to_ruid = (int *) alloca ((max_uid + 1) * sizeof (int));
for (i = 0, insn = first; insn; i++, insn = NEXT_INSN (insn))
uid_to_ruid[INSN_UID (insn)] = i;
@@ -4522,79 +3560,11 @@ dbr_schedule (first, file)
redirect_jump (insn, target);
}
- /* Indicate what resources are required to be valid at the end of the current
- function. The condition code never is and memory always is. If the
- frame pointer is needed, it is and so is the stack pointer unless
- EXIT_IGNORE_STACK is non-zero. If the frame pointer is not needed, the
- stack pointer is. Registers used to return the function value are
- needed. Registers holding global variables are needed. */
-
- end_of_function_needs.cc = 0;
- end_of_function_needs.memory = 1;
- end_of_function_needs.unch_memory = 0;
- CLEAR_HARD_REG_SET (end_of_function_needs.regs);
-
- if (frame_pointer_needed)
- {
- SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM);
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
-#endif
-#ifdef EXIT_IGNORE_STACK
- if (! EXIT_IGNORE_STACK)
-#endif
- SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
- }
- else
- SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
-
- if (current_function_return_rtx != 0)
- mark_referenced_resources (current_function_return_rtx,
- &end_of_function_needs, 1);
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i]
-#ifdef EPILOGUE_USES
- || EPILOGUE_USES (i)
-#endif
- )
- SET_HARD_REG_BIT (end_of_function_needs.regs, i);
-
- /* The registers required to be live at the end of the function are
- represented in the flow information as being dead just prior to
- reaching the end of the function. For example, the return of a value
- might be represented by a USE of the return register immediately
- followed by an unconditional jump to the return label where the
- return label is the end of the RTL chain. The end of the RTL chain
- is then taken to mean that the return register is live.
-
- This sequence is no longer maintained when epilogue instructions are
- added to the RTL chain. To reconstruct the original meaning, the
- start of the epilogue (NOTE_INSN_EPILOGUE_BEG) is regarded as the
- point where these registers become live (start_of_epilogue_needs).
- If epilogue instructions are present, the registers set by those
- instructions won't have been processed by flow. Thus, those
- registers are additionally required at the end of the RTL chain
- (end_of_function_needs). */
-
- start_of_epilogue_needs = end_of_function_needs;
-
- while ((epilogue_insn = next_nonnote_insn (epilogue_insn)))
- mark_set_resources (epilogue_insn, &end_of_function_needs, 0, 1);
+ init_resource_info (epilogue_insn);
/* Show we haven't computed an end-of-function label yet. */
end_of_function_label = 0;
- /* Allocate and initialize the tables used by mark_target_live_regs. */
- target_hash_table
- = (struct target_info **) alloca ((TARGET_HASH_PRIME
- * sizeof (struct target_info *)));
- bzero ((char *) target_hash_table,
- TARGET_HASH_PRIME * sizeof (struct target_info *));
-
- bb_ticks = (int *) alloca (n_basic_blocks * sizeof (int));
- bzero ((char *) bb_ticks, n_basic_blocks * sizeof (int));
-
/* Initialize the statistics for this function. */
bzero ((char *) num_insns_needing_delays, sizeof num_insns_needing_delays);
bzero ((char *) num_filled_delays, sizeof num_filled_delays);
@@ -4683,6 +3653,13 @@ dbr_schedule (first, file)
{
int pred_flags;
+ if (GET_CODE (insn) == INSN)
+ {
+ rtx pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == SEQUENCE)
+ insn = XVECEXP (pat, 0, 0);
+ }
if (GET_CODE (insn) != JUMP_INSN)
continue;
@@ -4691,5 +3668,6 @@ dbr_schedule (first, file)
GEN_INT (pred_flags),
REG_NOTES (insn));
}
+ free_resource_info ();
}
#endif /* DELAY_SLOTS */
diff --git a/contrib/gcc/resource.c b/contrib/gcc/resource.c
new file mode 100644
index 0000000..ddf7df5
--- /dev/null
+++ b/contrib/gcc/resource.c
@@ -0,0 +1,1289 @@
+/* Definitions for computing resource usage of specific insns.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "toplev.h"
+#include "rtl.h"
+#include "hard-reg-set.h"
+#include "system.h"
+#include "basic-block.h"
+#include "regs.h"
+#include "flags.h"
+#include "output.h"
+#include "resource.h"
+
+/* This structure is used to record liveness information at the targets or
+ fallthrough insns of branches. We will most likely need the information
+ at targets again, so save them in a hash table rather than recomputing them
+ each time. */
+
+struct target_info
+{
+ int uid; /* INSN_UID of target. */
+ struct target_info *next; /* Next info for same hash bucket. */
+ HARD_REG_SET live_regs; /* Registers live at target. */
+ int block; /* Basic block number containing target. */
+ int bb_tick; /* Generation count of basic block info. */
+};
+
+#define TARGET_HASH_PRIME 257
+
+/* Indicates what resources are required at the beginning of the epilogue. */
+static struct resources start_of_epilogue_needs;
+
+/* Indicates what resources are required at function end. */
+static struct resources end_of_function_needs;
+
+/* Define the hash table itself. */
+static struct target_info **target_hash_table = NULL;
+
+/* For each basic block, we maintain a generation number of its basic
+ block info, which is updated each time we move an insn from the
+ target of a jump. This is the generation number indexed by block
+ number. */
+
+static int *bb_ticks;
+
+/* Marks registers possibly live at the current place being scanned by
+ mark_target_live_regs. Used only by next two function. */
+
+static HARD_REG_SET current_live_regs;
+
+/* Marks registers for which we have seen a REG_DEAD note but no assignment.
+ Also only used by the next two functions. */
+
+static HARD_REG_SET pending_dead_regs;
+
+static void update_live_status PROTO ((rtx, rtx));
+static int find_basic_block PROTO ((rtx));
+static rtx next_insn_no_annul PROTO ((rtx));
+static rtx find_dead_or_set_registers PROTO ((rtx, struct resources*,
+ rtx*, int, struct resources,
+ struct resources));
+
+/* Utility function called from mark_target_live_regs via note_stores.
+ It deadens any CLOBBERed registers and livens any SET registers. */
+
+static void
+update_live_status (dest, x)
+ rtx dest;
+ rtx x;
+{
+ int first_regno, last_regno;
+ int i;
+
+ if (GET_CODE (dest) != REG
+ && (GET_CODE (dest) != SUBREG || GET_CODE (SUBREG_REG (dest)) != REG))
+ return;
+
+ if (GET_CODE (dest) == SUBREG)
+ first_regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
+ else
+ first_regno = REGNO (dest);
+
+ last_regno = first_regno + HARD_REGNO_NREGS (first_regno, GET_MODE (dest));
+
+ if (GET_CODE (x) == CLOBBER)
+ for (i = first_regno; i < last_regno; i++)
+ CLEAR_HARD_REG_BIT (current_live_regs, i);
+ else
+ for (i = first_regno; i < last_regno; i++)
+ {
+ SET_HARD_REG_BIT (current_live_regs, i);
+ CLEAR_HARD_REG_BIT (pending_dead_regs, i);
+ }
+}
+/* Find the number of the basic block that starts closest to INSN. Return -1
+ if we couldn't find such a basic block. */
+
+static int
+find_basic_block (insn)
+ rtx insn;
+{
+ int i;
+
+ /* Scan backwards to the previous BARRIER. Then see if we can find a
+ label that starts a basic block. Return the basic block number. */
+
+ for (insn = prev_nonnote_insn (insn);
+ insn && GET_CODE (insn) != BARRIER;
+ insn = prev_nonnote_insn (insn))
+ ;
+
+ /* The start of the function is basic block zero. */
+ if (insn == 0)
+ return 0;
+
+ /* See if any of the upcoming CODE_LABELs start a basic block. If we reach
+ anything other than a CODE_LABEL or note, we can't find this code. */
+ for (insn = next_nonnote_insn (insn);
+ insn && GET_CODE (insn) == CODE_LABEL;
+ insn = next_nonnote_insn (insn))
+ {
+ for (i = 0; i < n_basic_blocks; i++)
+ if (insn == BLOCK_HEAD (i))
+ return i;
+ }
+
+ return -1;
+}
+
+/* Similar to next_insn, but ignores insns in the delay slots of
+ an annulled branch. */
+
+static rtx
+next_insn_no_annul (insn)
+ rtx insn;
+{
+ if (insn)
+ {
+ /* If INSN is an annulled branch, skip any insns from the target
+ of the branch. */
+ if (INSN_ANNULLED_BRANCH_P (insn)
+ && NEXT_INSN (PREV_INSN (insn)) != insn)
+ while (INSN_FROM_TARGET_P (NEXT_INSN (insn)))
+ insn = NEXT_INSN (insn);
+
+ insn = NEXT_INSN (insn);
+ if (insn && GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ insn = XVECEXP (PATTERN (insn), 0, 0);
+ }
+
+ return insn;
+}
+
+/* Given X, some rtl, and RES, a pointer to a `struct resource', mark
+ which resources are references by the insn. If INCLUDE_DELAYED_EFFECTS
+ is TRUE, resources used by the called routine will be included for
+ CALL_INSNs. */
+
+void
+mark_referenced_resources (x, res, include_delayed_effects)
+ register rtx x;
+ register struct resources *res;
+ register int include_delayed_effects;
+{
+ register enum rtx_code code = GET_CODE (x);
+ register int i, j;
+ register char *format_ptr;
+
+ /* Handle leaf items for which we set resource flags. Also, special-case
+ CALL, SET and CLOBBER operators. */
+ switch (code)
+ {
+ case CONST:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case PC:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return;
+
+ case SUBREG:
+ if (GET_CODE (SUBREG_REG (x)) != REG)
+ mark_referenced_resources (SUBREG_REG (x), res, 0);
+ 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:
+ for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
+ SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
+ return;
+
+ case MEM:
+ /* If this memory shouldn't change, it really isn't referencing
+ memory. */
+ if (RTX_UNCHANGING_P (x))
+ res->unch_memory = 1;
+ else
+ res->memory = 1;
+ res->volatil |= MEM_VOLATILE_P (x);
+
+ /* Mark registers used to access memory. */
+ mark_referenced_resources (XEXP (x, 0), res, 0);
+ return;
+
+ case CC0:
+ res->cc = 1;
+ return;
+
+ case UNSPEC_VOLATILE:
+ case ASM_INPUT:
+ /* Traditional asm's are always volatile. */
+ res->volatil = 1;
+ return;
+
+ case TRAP_IF:
+ res->volatil = 1;
+ break;
+
+ case ASM_OPERANDS:
+ res->volatil |= MEM_VOLATILE_P (x);
+
+ /* For all ASM_OPERANDS, we must traverse the vector of input operands.
+ We can not just fall through here since then we would be confused
+ by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
+ traditional asms unlike their normal usage. */
+
+ for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
+ mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0);
+ return;
+
+ case CALL:
+ /* The first operand will be a (MEM (xxx)) but doesn't really reference
+ memory. The second operand may be referenced, though. */
+ mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, 0);
+ mark_referenced_resources (XEXP (x, 1), res, 0);
+ return;
+
+ case SET:
+ /* Usually, the first operand of SET is set, not referenced. But
+ registers used to access memory are referenced. SET_DEST is
+ also referenced if it is a ZERO_EXTRACT or SIGN_EXTRACT. */
+
+ mark_referenced_resources (SET_SRC (x), res, 0);
+
+ x = SET_DEST (x);
+ if (GET_CODE (x) == SIGN_EXTRACT || GET_CODE (x) == ZERO_EXTRACT)
+ mark_referenced_resources (x, res, 0);
+ else if (GET_CODE (x) == SUBREG)
+ x = SUBREG_REG (x);
+ if (GET_CODE (x) == MEM)
+ mark_referenced_resources (XEXP (x, 0), res, 0);
+ return;
+
+ case CLOBBER:
+ return;
+
+ case CALL_INSN:
+ if (include_delayed_effects)
+ {
+ /* A CALL references memory, the frame pointer if it exists, the
+ stack pointer, any global registers and any registers given in
+ USE insns immediately in front of the CALL.
+
+ However, we may have moved some of the parameter loading insns
+ into the delay slot of this CALL. If so, the USE's for them
+ don't count and should be skipped. */
+ rtx insn = PREV_INSN (x);
+ rtx sequence = 0;
+ int seq_size = 0;
+ rtx next = NEXT_INSN (x);
+ int i;
+
+ /* If we are part of a delay slot sequence, point at the SEQUENCE. */
+ if (NEXT_INSN (insn) != x)
+ {
+ next = NEXT_INSN (NEXT_INSN (insn));
+ sequence = PATTERN (NEXT_INSN (insn));
+ seq_size = XVECLEN (sequence, 0);
+ if (GET_CODE (sequence) != SEQUENCE)
+ abort ();
+ }
+
+ res->memory = 1;
+ SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM);
+ if (frame_pointer_needed)
+ {
+ SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);
+#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
+#endif
+ }
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (global_regs[i])
+ SET_HARD_REG_BIT (res->regs, i);
+
+ /* Check for a NOTE_INSN_SETJMP. If it exists, then we must
+ assume that this call can need any register.
+
+ This is done to be more conservative about how we handle setjmp.
+ We assume that they both use and set all registers. Using all
+ registers ensures that a register will not be considered dead
+ just because it crosses a setjmp call. A register should be
+ considered dead only if the setjmp call returns non-zero. */
+ if (next && GET_CODE (next) == NOTE
+ && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)
+ SET_HARD_REG_SET (res->regs);
+
+ {
+ rtx link;
+
+ for (link = CALL_INSN_FUNCTION_USAGE (x);
+ link;
+ link = XEXP (link, 1))
+ if (GET_CODE (XEXP (link, 0)) == USE)
+ {
+ for (i = 1; i < seq_size; i++)
+ {
+ rtx slot_pat = PATTERN (XVECEXP (sequence, 0, i));
+ if (GET_CODE (slot_pat) == SET
+ && rtx_equal_p (SET_DEST (slot_pat),
+ SET_DEST (XEXP (link, 0))))
+ break;
+ }
+ if (i >= seq_size)
+ mark_referenced_resources (SET_DEST (XEXP (link, 0)),
+ res, 0);
+ }
+ }
+ }
+
+ /* ... fall through to other INSN processing ... */
+
+ case INSN:
+ case JUMP_INSN:
+
+#ifdef INSN_REFERENCES_ARE_DELAYED
+ if (! include_delayed_effects
+ && INSN_REFERENCES_ARE_DELAYED (x))
+ return;
+#endif
+
+ /* No special processing, just speed up. */
+ mark_referenced_resources (PATTERN (x), res, include_delayed_effects);
+ return;
+
+ default:
+ break;
+ }
+
+ /* Process each sub-expression and flag what it needs. */
+ format_ptr = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ switch (*format_ptr++)
+ {
+ case 'e':
+ mark_referenced_resources (XEXP (x, i), res, include_delayed_effects);
+ break;
+
+ case 'E':
+ for (j = 0; j < XVECLEN (x, i); j++)
+ mark_referenced_resources (XVECEXP (x, i, j), res,
+ include_delayed_effects);
+ break;
+ }
+}
+
+/* A subroutine of mark_target_live_regs. Search forward from TARGET
+ looking for registers that are set before they are used. These are dead.
+ Stop after passing a few conditional jumps, and/or a small
+ number of unconditional branches. */
+
+static rtx
+find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
+ rtx target;
+ struct resources *res;
+ rtx *jump_target;
+ int jump_count;
+ struct resources set, needed;
+{
+ HARD_REG_SET scratch;
+ rtx insn, next;
+ rtx jump_insn = 0;
+ int i;
+
+ for (insn = target; insn; insn = next)
+ {
+ rtx this_jump_insn = insn;
+
+ next = NEXT_INSN (insn);
+ switch (GET_CODE (insn))
+ {
+ case CODE_LABEL:
+ /* After a label, any pending dead registers that weren't yet
+ used can be made dead. */
+ AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs);
+ AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
+ CLEAR_HARD_REG_SET (pending_dead_regs);
+
+ continue;
+
+ case BARRIER:
+ case NOTE:
+ continue;
+
+ case INSN:
+ if (GET_CODE (PATTERN (insn)) == USE)
+ {
+ /* If INSN is a USE made by update_block, we care about the
+ underlying insn. Any registers set by the underlying insn
+ are live since the insn is being done somewhere else. */
+ if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
+ mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1);
+
+ /* All other USE insns are to be ignored. */
+ continue;
+ }
+ else if (GET_CODE (PATTERN (insn)) == CLOBBER)
+ continue;
+ else if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+ /* An unconditional jump can be used to fill the delay slot
+ of a call, so search for a JUMP_INSN in any position. */
+ for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+ {
+ this_jump_insn = XVECEXP (PATTERN (insn), 0, i);
+ if (GET_CODE (this_jump_insn) == JUMP_INSN)
+ break;
+ }
+ }
+
+ default:
+ break;
+ }
+
+ if (GET_CODE (this_jump_insn) == JUMP_INSN)
+ {
+ if (jump_count++ < 10)
+ {
+ if (simplejump_p (this_jump_insn)
+ || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
+ {
+ next = JUMP_LABEL (this_jump_insn);
+ if (jump_insn == 0)
+ {
+ jump_insn = insn;
+ if (jump_target)
+ *jump_target = JUMP_LABEL (this_jump_insn);
+ }
+ }
+ else if (condjump_p (this_jump_insn)
+ || condjump_in_parallel_p (this_jump_insn))
+ {
+ struct resources target_set, target_res;
+ struct resources fallthrough_res;
+
+ /* We can handle conditional branches here by following
+ both paths, and then IOR the results of the two paths
+ together, which will give us registers that are dead
+ on both paths. Since this is expensive, we give it
+ a much higher cost than unconditional branches. The
+ cost was chosen so that we will follow at most 1
+ conditional branch. */
+
+ jump_count += 4;
+ if (jump_count >= 10)
+ break;
+
+ mark_referenced_resources (insn, &needed, 1);
+
+ /* For an annulled branch, mark_set_resources ignores slots
+ filled by instructions from the target. This is correct
+ if the branch is not taken. Since we are following both
+ paths from the branch, we must also compute correct info
+ if the branch is taken. We do this by inverting all of
+ the INSN_FROM_TARGET_P bits, calling mark_set_resources,
+ and then inverting the INSN_FROM_TARGET_P bits again. */
+
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE
+ && INSN_ANNULLED_BRANCH_P (this_jump_insn))
+ {
+ for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
+ INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
+ = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
+
+ target_set = set;
+ mark_set_resources (insn, &target_set, 0, 1);
+
+ for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
+ INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
+ = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
+
+ mark_set_resources (insn, &set, 0, 1);
+ }
+ else
+ {
+ mark_set_resources (insn, &set, 0, 1);
+ target_set = set;
+ }
+
+ target_res = *res;
+ COPY_HARD_REG_SET (scratch, target_set.regs);
+ AND_COMPL_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (target_res.regs, scratch);
+
+ fallthrough_res = *res;
+ COPY_HARD_REG_SET (scratch, set.regs);
+ AND_COMPL_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
+
+ find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
+ &target_res, 0, jump_count,
+ target_set, needed);
+ find_dead_or_set_registers (next,
+ &fallthrough_res, 0, jump_count,
+ set, needed);
+ IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs);
+ AND_HARD_REG_SET (res->regs, fallthrough_res.regs);
+ break;
+ }
+ else
+ break;
+ }
+ else
+ {
+ /* Don't try this optimization if we expired our jump count
+ above, since that would mean there may be an infinite loop
+ in the function being compiled. */
+ jump_insn = 0;
+ break;
+ }
+ }
+
+ mark_referenced_resources (insn, &needed, 1);
+ mark_set_resources (insn, &set, 0, 1);
+
+ COPY_HARD_REG_SET (scratch, set.regs);
+ AND_COMPL_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (res->regs, scratch);
+ }
+
+ return jump_insn;
+}
+
+/* Given X, a part of an insn, and a pointer to a `struct resource',
+ RES, indicate which resources are modified by the insn. If
+ INCLUDE_DELAYED_EFFECTS is nonzero, also mark resources potentially
+ set by the called routine.
+
+ If IN_DEST is nonzero, it means we are inside a SET. Otherwise,
+ objects are being referenced instead of set.
+
+ We never mark the insn as modifying the condition code unless it explicitly
+ SETs CC0 even though this is not totally correct. The reason for this is
+ that we require a SET of CC0 to immediately precede the reference to CC0.
+ So if some other insn sets CC0 as a side-effect, we know it cannot affect
+ our computation and thus may be placed in a delay slot. */
+
+void
+mark_set_resources (x, res, in_dest, include_delayed_effects)
+ register rtx x;
+ register struct resources *res;
+ int in_dest;
+ int include_delayed_effects;
+{
+ register enum rtx_code code;
+ register int i, j;
+ register char *format_ptr;
+
+ restart:
+
+ code = GET_CODE (x);
+
+ switch (code)
+ {
+ case NOTE:
+ case BARRIER:
+ case CODE_LABEL:
+ case USE:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST:
+ case PC:
+ /* These don't set any resources. */
+ return;
+
+ case CC0:
+ if (in_dest)
+ res->cc = 1;
+ return;
+
+ case CALL_INSN:
+ /* Called routine modifies the condition code, memory, any registers
+ that aren't saved across calls, global registers and anything
+ explicitly CLOBBERed immediately after the CALL_INSN. */
+
+ if (include_delayed_effects)
+ {
+ rtx next = NEXT_INSN (x);
+ rtx prev = PREV_INSN (x);
+ rtx link;
+
+ res->cc = res->memory = 1;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (call_used_regs[i] || global_regs[i])
+ SET_HARD_REG_BIT (res->regs, i);
+
+ /* If X is part of a delay slot sequence, then NEXT should be
+ the first insn after the sequence. */
+ if (NEXT_INSN (prev) != x)
+ next = NEXT_INSN (NEXT_INSN (prev));
+
+ for (link = CALL_INSN_FUNCTION_USAGE (x);
+ link; link = XEXP (link, 1))
+ if (GET_CODE (XEXP (link, 0)) == CLOBBER)
+ mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1, 0);
+
+ /* Check for a NOTE_INSN_SETJMP. If it exists, then we must
+ assume that this call can clobber any register. */
+ if (next && GET_CODE (next) == NOTE
+ && NOTE_LINE_NUMBER (next) == NOTE_INSN_SETJMP)
+ SET_HARD_REG_SET (res->regs);
+ }
+
+ /* ... and also what its RTL says it modifies, if anything. */
+
+ case JUMP_INSN:
+ case INSN:
+
+ /* An insn consisting of just a CLOBBER (or USE) is just for flow
+ and doesn't actually do anything, so we ignore it. */
+
+#ifdef INSN_SETS_ARE_DELAYED
+ if (! include_delayed_effects
+ && INSN_SETS_ARE_DELAYED (x))
+ return;
+#endif
+
+ x = PATTERN (x);
+ if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
+ goto restart;
+ return;
+
+ case SET:
+ /* If the source of a SET is a CALL, this is actually done by
+ the called routine. So only include it if we are to include the
+ effects of the calling routine. */
+
+ mark_set_resources (SET_DEST (x), res,
+ (include_delayed_effects
+ || GET_CODE (SET_SRC (x)) != CALL),
+ 0);
+
+ mark_set_resources (SET_SRC (x), res, 0, 0);
+ return;
+
+ case CLOBBER:
+ mark_set_resources (XEXP (x, 0), res, 1, 0);
+ return;
+
+ case SEQUENCE:
+ for (i = 0; i < XVECLEN (x, 0); i++)
+ if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
+ && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))
+ mark_set_resources (XVECEXP (x, 0, i), res, 0,
+ include_delayed_effects);
+ return;
+
+ case POST_INC:
+ case PRE_INC:
+ case POST_DEC:
+ case PRE_DEC:
+ mark_set_resources (XEXP (x, 0), res, 1, 0);
+ return;
+
+ case ZERO_EXTRACT:
+ mark_set_resources (XEXP (x, 0), res, in_dest, 0);
+ mark_set_resources (XEXP (x, 1), res, 0, 0);
+ mark_set_resources (XEXP (x, 2), res, 0, 0);
+ return;
+
+ case MEM:
+ if (in_dest)
+ {
+ res->memory = 1;
+ res->unch_memory |= RTX_UNCHANGING_P (x);
+ res->volatil |= MEM_VOLATILE_P (x);
+ }
+
+ mark_set_resources (XEXP (x, 0), res, 0, 0);
+ 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:
+ if (in_dest)
+ for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
+ SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
+ return;
+
+ case UNSPEC_VOLATILE:
+ case ASM_INPUT:
+ /* Traditional asm's are always volatile. */
+ res->volatil = 1;
+ return;
+
+ case TRAP_IF:
+ res->volatil = 1;
+ break;
+
+ case ASM_OPERANDS:
+ res->volatil |= MEM_VOLATILE_P (x);
+
+ /* For all ASM_OPERANDS, we must traverse the vector of input operands.
+ We can not just fall through here since then we would be confused
+ by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
+ traditional asms unlike their normal usage. */
+
+ for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
+ mark_set_resources (ASM_OPERANDS_INPUT (x, i), res, in_dest, 0);
+ return;
+
+ default:
+ break;
+ }
+
+ /* Process each sub-expression and flag what it needs. */
+ format_ptr = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ switch (*format_ptr++)
+ {
+ case 'e':
+ mark_set_resources (XEXP (x, i), res, in_dest, include_delayed_effects);
+ break;
+
+ case 'E':
+ for (j = 0; j < XVECLEN (x, i); j++)
+ mark_set_resources (XVECEXP (x, i, j), res, in_dest,
+ include_delayed_effects);
+ break;
+ }
+}
+
+/* Set the resources that are live at TARGET.
+
+ If TARGET is zero, we refer to the end of the current function and can
+ return our precomputed value.
+
+ Otherwise, we try to find out what is live by consulting the basic block
+ information. This is tricky, because we must consider the actions of
+ reload and jump optimization, which occur after the basic block information
+ has been computed.
+
+ Accordingly, we proceed as follows::
+
+ We find the previous BARRIER and look at all immediately following labels
+ (with no intervening active insns) to see if any of them start a basic
+ block. If we hit the start of the function first, we use block 0.
+
+ Once we have found a basic block and a corresponding first insns, we can
+ accurately compute the live status from basic_block_live_regs and
+ reg_renumber. (By starting at a label following a BARRIER, we are immune
+ to actions taken by reload and jump.) Then we scan all insns between
+ that point and our target. For each CLOBBER (or for call-clobbered regs
+ when we pass a CALL_INSN), mark the appropriate registers are dead. For
+ a SET, mark them as live.
+
+ We have to be careful when using REG_DEAD notes because they are not
+ updated by such things as find_equiv_reg. So keep track of registers
+ marked as dead that haven't been assigned to, and mark them dead at the
+ next CODE_LABEL since reload and jump won't propagate values across labels.
+
+ If we cannot find the start of a basic block (should be a very rare
+ case, if it can happen at all), mark everything as potentially live.
+
+ Next, scan forward from TARGET looking for things set or clobbered
+ before they are used. These are not live.
+
+ Because we can be called many times on the same target, save our results
+ in a hash table indexed by INSN_UID. This is only done if the function
+ init_resource_info () was invoked before we are called. */
+
+void
+mark_target_live_regs (insns, target, res)
+ rtx insns;
+ rtx target;
+ struct resources *res;
+{
+ int b = -1;
+ int i;
+ struct target_info *tinfo = NULL;
+ rtx insn;
+ rtx jump_insn = 0;
+ rtx jump_target;
+ HARD_REG_SET scratch;
+ struct resources set, needed;
+
+ /* Handle end of function. */
+ if (target == 0)
+ {
+ *res = end_of_function_needs;
+ return;
+ }
+
+ /* We have to assume memory is needed, but the CC isn't. */
+ res->memory = 1;
+ res->volatil = res->unch_memory = 0;
+ res->cc = 0;
+
+ /* See if we have computed this value already. */
+ if (target_hash_table != NULL)
+ {
+ for (tinfo = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
+ tinfo; tinfo = tinfo->next)
+ if (tinfo->uid == INSN_UID (target))
+ break;
+
+ /* Start by getting the basic block number. If we have saved
+ information, we can get it from there unless the insn at the
+ start of the basic block has been deleted. */
+ if (tinfo && tinfo->block != -1
+ && ! INSN_DELETED_P (BLOCK_HEAD (tinfo->block)))
+ b = tinfo->block;
+ }
+
+ if (b == -1)
+ b = find_basic_block (target);
+
+ if (target_hash_table != NULL)
+ {
+ if (tinfo)
+ {
+ /* If the information is up-to-date, use it. Otherwise, we will
+ update it below. */
+ if (b == tinfo->block && b != -1 && tinfo->bb_tick == bb_ticks[b])
+ {
+ COPY_HARD_REG_SET (res->regs, tinfo->live_regs);
+ return;
+ }
+ }
+ else
+ {
+ /* Allocate a place to put our results and chain it into the
+ hash table. */
+ tinfo = (struct target_info *) oballoc (sizeof (struct target_info));
+ tinfo->uid = INSN_UID (target);
+ tinfo->block = b;
+ tinfo->next = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
+ target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME] = tinfo;
+ }
+ }
+
+ CLEAR_HARD_REG_SET (pending_dead_regs);
+
+ /* If we found a basic block, get the live registers from it and update
+ them with anything set or killed between its start and the insn before
+ TARGET. Otherwise, we must assume everything is live. */
+ if (b != -1)
+ {
+ regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
+ int j;
+ int regno;
+ rtx start_insn, stop_insn;
+
+ /* Compute hard regs live at start of block -- this is the real hard regs
+ marked live, plus live pseudo regs that have been renumbered to
+ hard regs. */
+
+ REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
+
+ EXECUTE_IF_SET_IN_REG_SET
+ (regs_live, FIRST_PSEUDO_REGISTER, i,
+ {
+ if ((regno = reg_renumber[i]) >= 0)
+ for (j = regno;
+ j < regno + HARD_REGNO_NREGS (regno,
+ PSEUDO_REGNO_MODE (i));
+ j++)
+ SET_HARD_REG_BIT (current_live_regs, j);
+ });
+
+ /* Get starting and ending insn, handling the case where each might
+ be a SEQUENCE. */
+ start_insn = (b == 0 ? insns : BLOCK_HEAD (b));
+ stop_insn = target;
+
+ if (GET_CODE (start_insn) == INSN
+ && GET_CODE (PATTERN (start_insn)) == SEQUENCE)
+ start_insn = XVECEXP (PATTERN (start_insn), 0, 0);
+
+ if (GET_CODE (stop_insn) == INSN
+ && GET_CODE (PATTERN (stop_insn)) == SEQUENCE)
+ stop_insn = next_insn (PREV_INSN (stop_insn));
+
+ for (insn = start_insn; insn != stop_insn;
+ insn = next_insn_no_annul (insn))
+ {
+ rtx link;
+ rtx real_insn = insn;
+
+ /* If this insn is from the target of a branch, it isn't going to
+ be used in the sequel. If it is used in both cases, this
+ test will not be true. */
+ if (INSN_FROM_TARGET_P (insn))
+ continue;
+
+ /* If this insn is a USE made by update_block, we care about the
+ underlying insn. */
+ if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
+ && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
+ real_insn = XEXP (PATTERN (insn), 0);
+
+ if (GET_CODE (real_insn) == CALL_INSN)
+ {
+ /* CALL clobbers all call-used regs that aren't fixed except
+ sp, ap, and fp. Do this before setting the result of the
+ call live. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (call_used_regs[i]
+ && i != STACK_POINTER_REGNUM && i != FRAME_POINTER_REGNUM
+ && i != ARG_POINTER_REGNUM
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && i != HARD_FRAME_POINTER_REGNUM
+#endif
+#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ && ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
+#endif
+#ifdef PIC_OFFSET_TABLE_REGNUM
+ && ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
+#endif
+ )
+ CLEAR_HARD_REG_BIT (current_live_regs, i);
+
+ /* A CALL_INSN sets any global register live, since it may
+ have been modified by the call. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (global_regs[i])
+ SET_HARD_REG_BIT (current_live_regs, i);
+ }
+
+ /* Mark anything killed in an insn to be deadened at the next
+ label. Ignore USE insns; the only REG_DEAD notes will be for
+ parameters. But they might be early. A CALL_INSN will usually
+ clobber registers used for parameters. It isn't worth bothering
+ with the unlikely case when it won't. */
+ if ((GET_CODE (real_insn) == INSN
+ && GET_CODE (PATTERN (real_insn)) != USE
+ && GET_CODE (PATTERN (real_insn)) != CLOBBER)
+ || GET_CODE (real_insn) == JUMP_INSN
+ || GET_CODE (real_insn) == CALL_INSN)
+ {
+ for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_DEAD
+ && GET_CODE (XEXP (link, 0)) == REG
+ && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
+ {
+ int first_regno = REGNO (XEXP (link, 0));
+ int last_regno
+ = (first_regno
+ + HARD_REGNO_NREGS (first_regno,
+ GET_MODE (XEXP (link, 0))));
+
+ for (i = first_regno; i < last_regno; i++)
+ SET_HARD_REG_BIT (pending_dead_regs, i);
+ }
+
+ note_stores (PATTERN (real_insn), update_live_status);
+
+ /* If any registers were unused after this insn, kill them.
+ These notes will always be accurate. */
+ for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_UNUSED
+ && GET_CODE (XEXP (link, 0)) == REG
+ && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
+ {
+ int first_regno = REGNO (XEXP (link, 0));
+ int last_regno
+ = (first_regno
+ + HARD_REGNO_NREGS (first_regno,
+ GET_MODE (XEXP (link, 0))));
+
+ for (i = first_regno; i < last_regno; i++)
+ CLEAR_HARD_REG_BIT (current_live_regs, i);
+ }
+ }
+
+ else if (GET_CODE (real_insn) == CODE_LABEL)
+ {
+ /* A label clobbers the pending dead registers since neither
+ reload nor jump will propagate a value across a label. */
+ AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
+ CLEAR_HARD_REG_SET (pending_dead_regs);
+ }
+
+ /* The beginning of the epilogue corresponds to the end of the
+ RTL chain when there are no epilogue insns. Certain resources
+ are implicitly required at that point. */
+ else if (GET_CODE (real_insn) == NOTE
+ && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG)
+ IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs);
+ }
+
+ COPY_HARD_REG_SET (res->regs, current_live_regs);
+ if (tinfo != NULL)
+ {
+ tinfo->block = b;
+ tinfo->bb_tick = bb_ticks[b];
+ }
+ }
+ else
+ /* We didn't find the start of a basic block. Assume everything
+ in use. This should happen only extremely rarely. */
+ SET_HARD_REG_SET (res->regs);
+
+ CLEAR_RESOURCE (&set);
+ CLEAR_RESOURCE (&needed);
+
+ jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
+ set, needed);
+
+ /* If we hit an unconditional branch, we have another way of finding out
+ what is live: we can see what is live at the branch target and include
+ anything used but not set before the branch. The only things that are
+ live are those that are live using the above test and the test below. */
+
+ if (jump_insn)
+ {
+ struct resources new_resources;
+ rtx stop_insn = next_active_insn (jump_insn);
+
+ mark_target_live_regs (insns, next_active_insn (jump_target),
+ &new_resources);
+ CLEAR_RESOURCE (&set);
+ CLEAR_RESOURCE (&needed);
+
+ /* Include JUMP_INSN in the needed registers. */
+ for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
+ {
+ mark_referenced_resources (insn, &needed, 1);
+
+ COPY_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (scratch, set.regs);
+ IOR_HARD_REG_SET (new_resources.regs, scratch);
+
+ mark_set_resources (insn, &set, 0, 1);
+ }
+
+ AND_HARD_REG_SET (res->regs, new_resources.regs);
+ }
+
+ if (tinfo != NULL)
+ {
+ COPY_HARD_REG_SET (tinfo->live_regs, res->regs);
+ }
+}
+
+/* Initialize the resources required by mark_target_live_regs ().
+ This should be invoked before the first call to mark_target_live_regs. */
+
+void
+init_resource_info (epilogue_insn)
+ rtx epilogue_insn;
+{
+ int i;
+
+ /* Indicate what resources are required to be valid at the end of the current
+ function. The condition code never is and memory always is. If the
+ frame pointer is needed, it is and so is the stack pointer unless
+ EXIT_IGNORE_STACK is non-zero. If the frame pointer is not needed, the
+ stack pointer is. Registers used to return the function value are
+ needed. Registers holding global variables are needed. */
+
+ end_of_function_needs.cc = 0;
+ end_of_function_needs.memory = 1;
+ end_of_function_needs.unch_memory = 0;
+ CLEAR_HARD_REG_SET (end_of_function_needs.regs);
+
+ if (frame_pointer_needed)
+ {
+ SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM);
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
+#endif
+#ifdef EXIT_IGNORE_STACK
+ if (! EXIT_IGNORE_STACK
+ || current_function_sp_is_unchanging)
+#endif
+ SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
+ }
+ else
+ SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
+
+ if (current_function_return_rtx != 0)
+ mark_referenced_resources (current_function_return_rtx,
+ &end_of_function_needs, 1);
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (global_regs[i]
+#ifdef EPILOGUE_USES
+ || EPILOGUE_USES (i)
+#endif
+ )
+ SET_HARD_REG_BIT (end_of_function_needs.regs, i);
+
+ /* The registers required to be live at the end of the function are
+ represented in the flow information as being dead just prior to
+ reaching the end of the function. For example, the return of a value
+ might be represented by a USE of the return register immediately
+ followed by an unconditional jump to the return label where the
+ return label is the end of the RTL chain. The end of the RTL chain
+ is then taken to mean that the return register is live.
+
+ This sequence is no longer maintained when epilogue instructions are
+ added to the RTL chain. To reconstruct the original meaning, the
+ start of the epilogue (NOTE_INSN_EPILOGUE_BEG) is regarded as the
+ point where these registers become live (start_of_epilogue_needs).
+ If epilogue instructions are present, the registers set by those
+ instructions won't have been processed by flow. Thus, those
+ registers are additionally required at the end of the RTL chain
+ (end_of_function_needs). */
+
+ start_of_epilogue_needs = end_of_function_needs;
+
+ while ((epilogue_insn = next_nonnote_insn (epilogue_insn)))
+ mark_set_resources (epilogue_insn, &end_of_function_needs, 0, 1);
+
+ /* Allocate and initialize the tables used by mark_target_live_regs. */
+ target_hash_table
+ = (struct target_info **) xmalloc ((TARGET_HASH_PRIME
+ * sizeof (struct target_info *)));
+ bzero ((char *) target_hash_table,
+ TARGET_HASH_PRIME * sizeof (struct target_info *));
+
+ bb_ticks = (int *) xmalloc (n_basic_blocks * sizeof (int));
+ bzero ((char *) bb_ticks, n_basic_blocks * sizeof (int));
+}
+
+/* Free up the resources allcated to mark_target_live_regs (). This
+ should be invoked after the last call to mark_target_live_regs (). */
+
+void
+free_resource_info ()
+{
+ if (target_hash_table != NULL)
+ {
+ free (target_hash_table);
+ target_hash_table = NULL;
+ }
+
+ if (bb_ticks != NULL)
+ {
+ free (bb_ticks);
+ bb_ticks = NULL;
+ }
+}
+
+/* Clear any hashed information that we have stored for INSN. */
+
+void
+clear_hashed_info_for_insn (insn)
+ rtx insn;
+{
+ struct target_info *tinfo;
+
+ if (target_hash_table != NULL)
+ {
+ for (tinfo = target_hash_table[INSN_UID (insn) % TARGET_HASH_PRIME];
+ tinfo; tinfo = tinfo->next)
+ if (tinfo->uid == INSN_UID (insn))
+ break;
+
+ if (tinfo)
+ tinfo->block = -1;
+ }
+}
+
+/* Increment the tick count for the basic block that contains INSN. */
+
+void
+incr_ticks_for_insn (insn)
+ rtx insn;
+{
+ int b = find_basic_block (insn);
+
+ if (b != -1)
+ bb_ticks[b]++;
+}
+
+/* Add TRIAL to the set of resources used at the end of the current
+ function. */
+void
+mark_end_of_function_resources (trial, include_delayed_effects)
+ rtx trial;
+ int include_delayed_effects;
+{
+ mark_referenced_resources (trial, &end_of_function_needs,
+ include_delayed_effects);
+}
+
+/* Try to find an available hard register of mode MODE at
+ CURRENT_INSN, matching the register class in CLASS_STR. Registers
+ that already have bits set in REG_SET will not be considered.
+
+ If an appropriate register is available, it will be returned and the
+ corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
+ returned. */
+
+rtx
+find_free_register (current_insn, class_str, mode, reg_set)
+ rtx current_insn;
+ char *class_str;
+ int mode;
+ HARD_REG_SET *reg_set;
+{
+ int i, j;
+ struct resources used;
+ unsigned char clet = class_str[0];
+ enum reg_class class
+ = (clet == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (clet));
+
+ mark_target_live_regs (get_insns (), current_insn, &used);
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ int success = 1;
+
+ if (! TEST_HARD_REG_BIT (reg_class_contents[class], i))
+ continue;
+ for (j = HARD_REGNO_NREGS (i, mode) - 1; j >= 0; j--)
+ {
+ if (TEST_HARD_REG_BIT (*reg_set, i + j)
+ || TEST_HARD_REG_BIT (used.regs, i + j))
+ {
+ success = 0;
+ break;
+ }
+ }
+ if (success)
+ {
+ for (j = HARD_REGNO_NREGS (i, mode) - 1; j >= 0; j--)
+ {
+ SET_HARD_REG_BIT (*reg_set, i + j);
+ }
+ return gen_rtx_REG (mode, i);
+ }
+ }
+ return NULL_RTX;
+}
diff --git a/contrib/gcc/resource.h b/contrib/gcc/resource.h
new file mode 100644
index 0000000..d3a8e2c
--- /dev/null
+++ b/contrib/gcc/resource.h
@@ -0,0 +1,46 @@
+/* Definitions for computing resource usage of specific insns.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Macro to clear all resources. */
+#define CLEAR_RESOURCE(RES) \
+ do { (RES)->memory = (RES)->unch_memory = (RES)->volatil = (RES)->cc = 0; \
+ CLEAR_HARD_REG_SET ((RES)->regs); } while (0)
+
+/* The resources used by a given insn. */
+struct resources
+{
+ char memory; /* Insn sets or needs a memory location. */
+ char unch_memory; /* Insn sets of needs a "unchanging" MEM. */
+ char volatil; /* Insn sets or needs a volatile memory loc. */
+ char cc; /* Insn sets or needs the condition codes. */
+ HARD_REG_SET regs; /* Which registers are set or needed. */
+};
+
+extern void mark_target_live_regs PROTO((rtx, rtx, struct resources *));
+extern void mark_set_resources PROTO((rtx, struct resources *, int,
+ int));
+extern void mark_referenced_resources PROTO((rtx, struct resources *, int));
+extern void clear_hashed_info_for_insn PROTO((rtx));
+extern void incr_ticks_for_insn PROTO((rtx));
+extern void mark_end_of_function_resources PROTO ((rtx, int));
+extern void init_resource_info PROTO((rtx));
+extern void free_resource_info PROTO((void));
+extern rtx find_free_register PROTO((rtx, char *, int,
+ HARD_REG_SET *));
diff --git a/contrib/gcc/rtl.c b/contrib/gcc/rtl.c
index 396566d..6b04bcd 100644
--- a/contrib/gcc/rtl.c
+++ b/contrib/gcc/rtl.c
@@ -1,5 +1,5 @@
/* Allocate and read RTL for GNU C Compiler.
- Copyright (C) 1987, 1988, 1991, 1994, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -58,13 +58,15 @@ char *rtx_name[] = {
#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) NAME,
-char *mode_name[(int) MAX_MACHINE_MODE] = {
+char *mode_name[(int) MAX_MACHINE_MODE + 1] = {
#include "machmode.def"
#ifdef EXTRA_CC_MODES
- EXTRA_CC_NAMES
+ EXTRA_CC_NAMES,
#endif
-
+ /* Add an extra field to avoid a core dump if someone tries to convert
+ MAX_MACHINE_MODE to a string. */
+ ""
};
#undef DEF_MACHMODE
@@ -107,14 +109,23 @@ int mode_unit_size[(int) MAX_MACHINE_MODE] = {
use this. */
#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \
- (enum machine_mode) WIDER,
+ (unsigned char) WIDER,
-enum machine_mode mode_wider_mode[(int) MAX_MACHINE_MODE] = {
+unsigned char mode_wider_mode[(int) MAX_MACHINE_MODE] = {
#include "machmode.def" /* machine modes are documented here */
};
#undef DEF_MACHMODE
+#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER) \
+ ((SIZE) * BITS_PER_UNIT >= HOST_BITS_PER_WIDE_INT) ? ~(unsigned HOST_WIDE_INT)0 : ((unsigned HOST_WIDE_INT) 1 << (SIZE) * BITS_PER_UNIT) - 1,
+
+/* Indexed by machine mode, gives mask of significant bits in mode. */
+
+unsigned HOST_WIDE_INT mode_mask_array[(int) MAX_MACHINE_MODE] = {
+#include "machmode.def"
+};
+
/* Indexed by mode class, gives the narrowest mode for each class. */
enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
@@ -173,7 +184,8 @@ char *note_insn_name[] = { 0 , "NOTE_INSN_DELETED",
"NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
"NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
"NOTE_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_START",
- "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE" };
+ "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE",
+ "NOTE_INSN_BASIC_BLOCK" };
char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
"REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
@@ -181,9 +193,11 @@ char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
"REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
"REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
"REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
- "REG_BR_PRED", "REG_EH_CONTEXT" };
+ "REG_BR_PRED", "REG_EH_CONTEXT",
+ "REG_FRAME_RELATED_EXPR", "REG_EH_REGION",
+ "REG_EH_RETHROW" };
-static void dump_and_abort PROTO((int, int, FILE *));
+static void dump_and_abort PROTO((int, int, FILE *)) ATTRIBUTE_NORETURN;
static void read_name PROTO((char *, FILE *));
/* Allocate an rtx vector of N elements.
@@ -241,9 +255,7 @@ rtx_alloc (code)
one int, but we don't want to assume that and it isn't very portable
anyway; this is. */
- length = (sizeof (struct rtx_def) - sizeof (rtunion) - 1) / sizeof (int);
- for (; length >= 0; length--)
- ((int *) rt)[length] = 0;
+ memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
PUT_CODE (rt, code);
@@ -308,11 +320,24 @@ copy_rtx (orig)
}
copy = rtx_alloc (code);
- PUT_MODE (copy, GET_MODE (orig));
- copy->in_struct = orig->in_struct;
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
- copy->integrated = orig->integrated;
+
+ /* Copy the various flags, and other information. We assume that
+ all fields need copying, and then clear the fields that should
+ not be copied. That is the sensible default behavior, and forces
+ us to explicitly document why we are *not* copying a flag. */
+ memcpy (copy, orig, sizeof (struct rtx_def) - sizeof (rtunion));
+
+ /* We do not copy the USED flag, which is used as a mark bit during
+ walks over the RTL. */
+ copy->used = 0;
+
+ /* We do not copy JUMP, CALL, or FRAME_RELATED for INSNs. */
+ if (GET_RTX_CLASS (code) == 'i')
+ {
+ copy->jump = 0;
+ copy->call = 0;
+ copy->frame_related = 0;
+ }
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
@@ -463,6 +488,28 @@ copy_most_rtx (orig, may_share)
}
return copy;
}
+
+/* Create a new copy of an rtx. Only copy just one level. */
+rtx
+shallow_copy_rtx (orig)
+ rtx orig;
+{
+ register int i;
+ register char *format_ptr;
+ register RTX_CODE code = GET_CODE (orig);
+ register rtx copy = rtx_alloc (code);
+
+ PUT_MODE (copy, GET_MODE (orig));
+ copy->in_struct = orig->in_struct;
+ copy->volatil = orig->volatil;
+ copy->unchanging = orig->unchanging;
+ copy->integrated = orig->integrated;
+
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ copy->fld[i] = orig->fld[i];
+
+ return copy;
+}
/* Subroutines of read_rtx. */
@@ -889,10 +936,11 @@ init_rtl ()
for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
{
mode_class[i] = MODE_CC;
+ mode_mask_array[i] = mode_mask_array[(int) CCmode];
mode_size[i] = mode_size[(int) CCmode];
mode_unit_size[i] = mode_unit_size[(int) CCmode];
- mode_wider_mode[i - 1] = (enum machine_mode) i;
- mode_wider_mode[i] = VOIDmode;
+ mode_wider_mode[i - 1] = i;
+ mode_wider_mode[i] = (unsigned char)VOIDmode;
}
#endif
diff --git a/contrib/gcc/rtl.def b/contrib/gcc/rtl.def
index 1e45157..7b8c845 100644
--- a/contrib/gcc/rtl.def
+++ b/contrib/gcc/rtl.def
@@ -1,7 +1,7 @@
/* This file contains the definitions and documentation for the
Register Transfer Expressions (rtx's) that make up the
Register Transfer Language (rtl) used in the Back End of the GNU compiler.
- Copyright (C) 1987, 88, 92, 94, 95, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 94, 95, 97, 98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -723,6 +723,14 @@ DEF_RTL_EXPR(PRE_INC, "pre_inc", "e", 'x')
DEF_RTL_EXPR(POST_DEC, "post_dec", "e", 'x')
DEF_RTL_EXPR(POST_INC, "post_inc", "e", 'x')
+/* These binary operations are used to represent generic address
+ side-effects in memory addresses, except for simple incrementation
+ or decrementation which use the above operations. They are
+ created automatically by the life_analysis pass in flow.c.
+ (Note that these operators are currently placeholders.) */
+DEF_RTL_EXPR(PRE_MODIFY, "pre_modify", "ee", 'x')
+DEF_RTL_EXPR(POST_MODIFY, "post_modify", "ee", 'x')
+
/* Comparison operations. The ordered comparisons exist in two
flavors, signed and unsigned. */
DEF_RTL_EXPR(NE, "ne", "ee", '<')
@@ -845,7 +853,25 @@ DEF_RTL_EXPR(RANGE_LIVE, "range_live", "bi", 'x')
/* A unary `__builtin_constant_p' expression. These are only emitted
during RTL generation, and then only if optimize > 0. They are
eliminated by the first CSE pass. */
-DEF_RTL_EXPR(CONSTANT_P_RTX, "constant_p", "e", 'x')
+DEF_RTL_EXPR(CONSTANT_P_RTX, "constant_p_rtx", "e", 'x')
+
+/* A placeholder for a CALL_INSN which may be turned into a normal call,
+ a sibling (tail) call or tail recursion.
+
+ Immediately after RTL generation, this placeholder will be replaced
+ by the insns to perform the call, sibcall or tail recursion.
+
+ This RTX has 4 operands. The first three are lists of instructions to
+ perform the call as a normal call, sibling call and tail recursion
+ respectively. The latter two lists may be NULL, the first may never
+ be NULL.
+
+ The last operand is the tail recursion CODE_LABEL, which may be NULL if no
+ potential tail recursive calls were found.
+
+ The tail recursion label is needed so that we can clear LABEL_PRESERVE_P
+ after we select a call method. */
+DEF_RTL_EXPR(CALL_PLACEHOLDER, "call_placeholder", "uuuu", 'x')
/*
Local variables:
diff --git a/contrib/gcc/rtl.h b/contrib/gcc/rtl.h
index 4aa25b2..8eba5ea 100644
--- a/contrib/gcc/rtl.h
+++ b/contrib/gcc/rtl.h
@@ -1,5 +1,5 @@
/* Register Transfer Language (RTL) definitions for GNU C-Compiler
- Copyright (C) 1987, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -91,6 +91,7 @@ typedef union rtunion_def
addr_diff_vec_flags rt_addr_diff_vec_flags;
struct bitmap_head_def *rtbit;
union tree_node *rttree;
+ struct basic_block_def *bb;
} rtunion;
/* RTL expression ("rtx"). */
@@ -113,10 +114,9 @@ typedef struct rtx_def
#else
enum machine_mode mode : 8;
#endif
- /* 1 in an INSN if it can alter flow of control
- within this function. Not yet used! */
+ /* LINK_COST_ZERO in an INSN_LIST. */
unsigned int jump : 1;
- /* 1 in an INSN if it can call another function. Not yet used! */
+ /* LINK_COST_FREE in an INSN_LIST. */
unsigned int call : 1;
/* 1 in a MEM or REG if value of this expression will never change
during the current function, even though it is not
@@ -163,9 +163,11 @@ typedef struct rtx_def
In a REG, nonzero means this reg refers to the return value
of the current function. */
unsigned integrated : 1;
- /* Nonzero if this rtx is related to the call frame, either changing how
- we compute the frame address or saving and restoring registers in
- the prologue and epilogue. */
+ /* 1 in an INSN or a SET if this rtx is related to the call frame,
+ either changing how we compute the frame address or saving and
+ restoring registers in the prologue and epilogue.
+ 1 in a MEM if the MEM refers to a scalar, rather than a member of
+ an aggregate. */
unsigned frame_related : 1;
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
@@ -173,8 +175,6 @@ typedef struct rtx_def
rtunion fld[1];
} *rtx;
-#include "gansidecl.h"
-
#define NULL_RTX (rtx) 0
/* Define macros to access the `code' field of the rtx. */
@@ -338,8 +338,20 @@ typedef struct rtvec_def{
REG_SAVE_AREA is used to optimize rtl generated by dynamic stack
allocations for targets where SETJMP_VIA_SAVE_AREA is true.
REG_BR_PRED is attached to JUMP_INSNs only, it holds the branch prediction
- flags computed by get_jump_flags() after dbr scheduling is complete. */
-
+ flags computed by get_jump_flags() after dbr scheduling is complete.
+ REG_FRAME_RELATED_EXPR is attached to insns that are RTX_FRAME_RELATED_P,
+ but are too complex for DWARF to interpret what they imply. The attached
+ rtx is used instead of intuition. */
+/* REG_EH_REGION is used to indicate what exception region an INSN
+ belongs in. This can be used to indicate what region a call may throw
+ to. A REGION of 0 indicates that a call cannot throw at all.
+ A REGION of -1 indicates that it cannot throw, nor will it execute
+ a non-local goto.
+ REG_EH_RETHROW is used to indicate what that a call is actually a
+ call to rethrow, and specifies which region the rethrow is targetting.
+ This provides a way to generate the non standard flow edges required
+ for a rethrow. */
+
#define REG_NOTES(INSN) ((INSN)->fld[6].rtx)
@@ -352,7 +364,9 @@ enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
REG_CC_SETTER = 11, REG_CC_USER = 12, REG_LABEL = 13,
REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15, REG_BR_PROB = 16,
REG_EXEC_COUNT = 17, REG_NOALIAS = 18, REG_SAVE_AREA = 19,
- REG_BR_PRED = 20, REG_EH_CONTEXT = 21 };
+ REG_BR_PRED = 20, REG_EH_CONTEXT = 21,
+ REG_FRAME_RELATED_EXPR = 22, REG_EH_REGION = 23,
+ REG_EH_RETHROW = 24 };
/* The base value for branch probability notes. */
#define REG_BR_PROB_BASE 10000
@@ -392,6 +406,7 @@ extern char *reg_note_name[];
#define NOTE_BLOCK_NUMBER(INSN) ((INSN)->fld[3].rtint)
#define NOTE_RANGE_INFO(INSN) ((INSN)->fld[3].rtx)
#define NOTE_LIVE_INFO(INSN) ((INSN)->fld[3].rtx)
+#define NOTE_BASIC_BLOCK(INSN) ((INSN)->fld[3].bb)
/* If the NOTE_BLOCK_NUMBER field gets a -1, it means create a new
block node for a live range block. */
@@ -457,6 +472,8 @@ extern char *reg_note_name[];
#define NOTE_INSN_RANGE_END -18
/* Record which registers are currently live. */
#define NOTE_INSN_LIVE -19
+/* Record the struct for the following basic block. */
+#define NOTE_INSN_BASIC_BLOCK -20
#if 0 /* These are not used, and I don't know what they were for. --rms. */
#define NOTE_DECL_NAME(INSN) ((INSN)->fld[3].rtstr)
@@ -559,9 +576,29 @@ extern char *note_insn_name[];
Also in an ASM_OPERANDS rtx. */
#define MEM_VOLATILE_P(RTX) ((RTX)->volatil)
-/* For a MEM rtx, 1 if it refers to a field of an aggregate. */
+/* For a MEM rtx, 1 if it refers to a field of an aggregate. If zero,
+ RTX may or may not refer to a field of an aggregate. */
#define MEM_IN_STRUCT_P(RTX) ((RTX)->in_struct)
+/* For a MEM rtx, 1 if it refers to a scalar. If zero, RTX may or may
+ not refer to a scalar.*/
+#define MEM_SCALAR_P(RTX) ((RTX)->frame_related)
+
+/* Copy the MEM_VOLATILE_P, MEM_IN_STRUCT_P, and MEM_SCALAR_P
+ attributes from RHS to LHS. */
+#define MEM_COPY_ATTRIBUTES(LHS, RHS) \
+ (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
+ MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
+ MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS))
+
+/* If VAL is non-zero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in
+ RTX. Otherwise, vice versa. Use this macro only when you are
+ *sure* that you know that the MEM is in a structure, or is a
+ scalar. VAL is evaluated only once. */
+#define MEM_SET_IN_STRUCT_P(RTX, VAL) \
+ ((VAL) ? (MEM_IN_STRUCT_P (RTX) = 1, MEM_SCALAR_P (RTX) = 0) \
+ : (MEM_IN_STRUCT_P (RTX) = 0, MEM_SCALAR_P (RTX) = 1))
+
/* For a MEM rtx, the alias set. If 0, this MEM is not in any alias
set, and may alias anything. Otherwise, the MEM can only alias
MEMs in the same alias set. This value is set in a
@@ -616,6 +653,10 @@ extern char *note_insn_name[];
/* Flag in a SYMBOL_REF for machine-specific purposes. */
#define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
+/* 1 in a SYMBOL_REF if it represents a symbol which might have to change
+ if its inlined or unrolled. */
+#define SYMBOL_REF_NEED_ADJUST(RTX) ((RTX)->in_struct)
+
/* 1 means a SYMBOL_REF has been the library function in emit_library_call. */
#define SYMBOL_REF_USED(RTX) ((RTX)->used)
@@ -679,6 +720,7 @@ extern char *note_insn_name[];
#define FUNCTION_FLAGS_USES_CONST_POOL 0200
#define FUNCTION_FLAGS_CALLS_LONGJMP 0400
#define FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE 01000
+#define FUNCTION_FLAGS_HAS_COMPUTED_JUMP 02000
/* Define a macro to look for REG_INC notes,
but save time on machines where they never exist. */
@@ -698,6 +740,60 @@ extern char *note_insn_name[];
#define AUTO_INC_DEC
#endif
+#ifndef HAVE_PRE_INCREMENT
+#define HAVE_PRE_INCREMENT 0
+#endif
+
+#ifndef HAVE_PRE_DECREMENT
+#define HAVE_PRE_DECREMENT 0
+#endif
+
+#ifndef HAVE_POST_INCREMENT
+#define HAVE_POST_INCREMENT 0
+#endif
+
+#ifndef HAVE_POST_DECREMENT
+#define HAVE_POST_DECREMENT 0
+#endif
+
+
+/* Some architectures do not have complete pre/post increment/decrement
+ instruction sets, or only move some modes efficiently. These macros
+ allow us to tune autoincrement generation. */
+
+#ifndef USE_LOAD_POST_INCREMENT
+#define USE_LOAD_POST_INCREMENT(MODE) HAVE_POST_INCREMENT
+#endif
+
+#ifndef USE_LOAD_POST_DECREMENT
+#define USE_LOAD_POST_DECREMENT(MODE) HAVE_POST_DECREMENT
+#endif
+
+#ifndef USE_LOAD_PRE_INCREMENT
+#define USE_LOAD_PRE_INCREMENT(MODE) HAVE_PRE_INCREMENT
+#endif
+
+#ifndef USE_LOAD_PRE_DECREMENT
+#define USE_LOAD_PRE_DECREMENT(MODE) HAVE_PRE_DECREMENT
+#endif
+
+#ifndef USE_STORE_POST_INCREMENT
+#define USE_STORE_POST_INCREMENT(MODE) HAVE_POST_INCREMENT
+#endif
+
+#ifndef USE_STORE_POST_DECREMENT
+#define USE_STORE_POST_DECREMENT(MODE) HAVE_POST_DECREMENT
+#endif
+
+#ifndef USE_STORE_PRE_INCREMENT
+#define USE_STORE_PRE_INCREMENT(MODE) HAVE_PRE_INCREMENT
+#endif
+
+#ifndef USE_STORE_PRE_DECREMENT
+#define USE_STORE_PRE_DECREMENT(MODE) HAVE_PRE_DECREMENT
+#endif
+
+
/* Accessors for RANGE_INFO. */
/* For RANGE_{START,END} notes return the RANGE_START note. */
#define RANGE_INFO_NOTE_START(INSN) (XEXP (INSN, 0))
@@ -825,19 +921,6 @@ extern rtvec gen_rtvec PVPROTO((int, ...));
extern rtx read_rtx PROTO((FILE *));
#endif
-#if 0
-/* At present, don't prototype xrealloc, since all of the callers don't
- cast their pointers to char *, and all of the xrealloc's don't use
- void * yet. */
-extern char *xmalloc PROTO((size_t));
-extern char *xcalloc PROTO((size_t, size_t));
-extern char *xrealloc PROTO((void *, size_t));
-#else
-extern char *xmalloc ();
-extern char *xcalloc ();
-extern char *xrealloc ();
-#endif
-
extern char *oballoc PROTO((int));
extern char *permalloc PROTO((int));
extern rtx rtx_alloc PROTO((RTX_CODE));
@@ -845,6 +928,7 @@ extern rtvec rtvec_alloc PROTO((int));
extern rtx copy_rtx PROTO((rtx));
extern rtx copy_rtx_if_shared PROTO((rtx));
extern rtx copy_most_rtx PROTO((rtx, rtx));
+extern rtx shallow_copy_rtx PROTO((rtx));
extern rtvec gen_rtvec_v PROTO((int, rtx *));
extern rtvec gen_rtvec_vv PROTO((int, rtunion *));
extern rtx gen_reg_rtx PROTO((enum machine_mode));
@@ -892,6 +976,7 @@ extern rtx emit_insn_before PROTO((rtx, rtx));
extern rtx emit_jump_insn_before PROTO((rtx, rtx));
extern rtx emit_call_insn_before PROTO((rtx, rtx));
extern rtx emit_barrier_before PROTO((rtx));
+extern rtx emit_label_before PROTO((rtx, rtx));
extern rtx emit_note_before PROTO((int, rtx));
extern rtx emit_insn_after PROTO((rtx, rtx));
extern rtx emit_jump_insn_after PROTO((rtx, rtx));
@@ -942,7 +1027,6 @@ extern rtx simplify_unary_operation PROTO((enum rtx_code, enum machine_mode, rtx
extern rtx simplify_binary_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx));
extern rtx simplify_ternary_operation PROTO((enum rtx_code, enum machine_mode, enum machine_mode, rtx, rtx, rtx));
extern rtx simplify_relational_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx));
-extern rtx nonlocal_label_rtx_list PROTO((void));
extern rtx gen_move_insn PROTO((rtx, rtx));
extern rtx gen_jump PROTO((rtx));
extern rtx gen_beq PROTO((rtx));
@@ -952,14 +1036,7 @@ extern rtx gen_mem_addressof PROTO((rtx, union tree_node *));
extern rtx eliminate_constant_term PROTO((rtx, rtx *));
extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int));
extern enum machine_mode choose_hard_reg_mode PROTO((int, int));
-extern int rtx_varies_p PROTO((rtx));
-extern int may_trap_p PROTO((rtx));
-extern int side_effects_p PROTO((rtx));
-extern int volatile_refs_p PROTO((rtx));
-extern int volatile_insn_p PROTO((rtx));
-extern void remove_note PROTO((rtx, rtx));
-extern int refers_to_regno_p PROTO((int, int, rtx, rtx *));
-extern int reg_overlap_mentioned_p PROTO((rtx, rtx));
+extern void set_unique_reg_note PROTO((rtx, enum reg_note, rtx));
/* Functions in rtlanal.c */
@@ -973,16 +1050,18 @@ extern int reg_referenced_p PROTO((rtx, rtx));
extern int reg_used_between_p PROTO((rtx, rtx, rtx));
extern int reg_referenced_between_p PROTO((rtx, rtx, rtx));
extern int reg_set_between_p PROTO((rtx, rtx, rtx));
+extern int regs_set_between_p PROTO((rtx, rtx, rtx));
extern int modified_between_p PROTO((rtx, rtx, rtx));
extern int no_labels_between_p PROTO((rtx, rtx));
+extern int no_jumps_between_p PROTO((rtx, rtx));
extern int modified_in_p PROTO((rtx, rtx));
extern int reg_set_p PROTO((rtx, rtx));
extern rtx single_set PROTO((rtx));
-extern rtx find_last_value PROTO((rtx, rtx *, rtx));
+extern int multiple_sets PROTO((rtx));
+extern rtx find_last_value PROTO((rtx, rtx *, rtx, int));
extern int refers_to_regno_p PROTO((int, int, rtx, rtx *));
extern int reg_overlap_mentioned_p PROTO((rtx, rtx));
-extern rtx find_use_as_address PROTO((rtx, rtx, HOST_WIDE_INT));
-extern void note_stores PROTO((rtx, void (*)()));
+extern void note_stores PROTO((rtx, void (*)(rtx, rtx)));
extern rtx reg_set_last PROTO((rtx, rtx));
extern int rtx_equal_p PROTO((rtx, rtx));
extern int dead_or_set_p PROTO((rtx, rtx));
@@ -996,10 +1075,21 @@ extern int side_effects_p PROTO((rtx));
extern int volatile_refs_p PROTO((rtx));
extern int volatile_insn_p PROTO((rtx));
extern int may_trap_p PROTO((rtx));
-extern int inequality_comparison_p PROTO((rtx));
+extern int inequality_comparisons_p PROTO ((rtx));
extern rtx replace_rtx PROTO((rtx, rtx, rtx));
extern rtx replace_regs PROTO((rtx, rtx *, int, int));
extern int computed_jump_p PROTO((rtx));
+typedef int (*rtx_function) PROTO((rtx *, void *));
+extern int for_each_rtx PROTO((rtx *, rtx_function, void *));
+extern rtx regno_use_in PROTO((int, rtx));
+extern int auto_inc_p PROTO((rtx));
+extern void remove_node_from_expr_list PROTO((rtx, rtx *));
+
+/* flow.c */
+
+extern rtx find_use_as_address PROTO((rtx, rtx, HOST_WIDE_INT));
+
+/* regclass.c */
/* Maximum number of parallel sets and clobbers in any insn in this fn.
Always at least 3, since the combiner could put that many togetherm
@@ -1007,14 +1097,23 @@ extern int computed_jump_p PROTO((rtx));
extern int max_parallel;
+/* Free up register info memory. */
+extern void free_reg_info PROTO((void));
+
+/* recog.c */
extern int asm_noperands PROTO((rtx));
-extern char *decode_asm_operands PROTO((rtx, rtx *, rtx **, char **, enum machine_mode *));
+extern char *decode_asm_operands PROTO((rtx, rtx *, rtx **,
+ const char **,
+ enum machine_mode *));
extern enum reg_class reg_preferred_class PROTO((int));
extern enum reg_class reg_alternate_class PROTO((int));
extern rtx get_first_nonparm_insn PROTO((void));
+extern void split_block_insns PROTO((int, int));
+extern void update_flow_info PROTO((rtx, rtx, rtx, rtx));
+
/* Standard pieces of rtx, to be substituted directly into things. */
#define pc_rtx (&global_rtl.pc_val)
#define cc0_rtx (&global_rtl.cc0_val)
@@ -1050,6 +1149,7 @@ extern struct _global_rtl
struct rtx_def virtual_stack_vars_val;
struct rtx_def virtual_stack_dynamic_val;
struct rtx_def virtual_outgoing_args_val;
+ struct rtx_def virtual_cfa_val;
} global_rtl;
/* All references to certain hard regs, except those created
@@ -1063,7 +1163,7 @@ extern rtx struct_value_rtx;
extern rtx struct_value_incoming_rtx;
extern rtx static_chain_rtx;
extern rtx static_chain_incoming_rtx;
-
+extern rtx return_address_pointer_rtx;
/* Include the RTL generation functions. */
@@ -1076,6 +1176,8 @@ extern rtx static_chain_incoming_rtx;
add to this list, modify special_rtx in gengenrtl.c as well. You
should also modify gen_rtx to use the special function. */
+extern rtx gen_rtx_CONST_DOUBLE PROTO((enum machine_mode, rtx,
+ HOST_WIDE_INT, HOST_WIDE_INT));
extern rtx gen_rtx_CONST_INT PROTO((enum machine_mode, HOST_WIDE_INT));
extern rtx gen_rtx_REG PROTO((enum machine_mode, int));
extern rtx gen_rtx_MEM PROTO((enum machine_mode, rtx));
@@ -1154,7 +1256,17 @@ extern rtx gen_rtx_MEM PROTO((enum machine_mode, rtx));
#define VIRTUAL_OUTGOING_ARGS_REGNUM ((FIRST_VIRTUAL_REGISTER) + 3)
-#define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 3)
+/* This points to the Canonical Frame Address of the function. This
+ should corrospond to the CFA produced by INCOMING_FRAME_SP_OFFSET,
+ but is calculated relative to the arg pointer for simplicity; the
+ frame pointer nor stack pointer are necessarily fixed relative to
+ the CFA until after reload. */
+
+#define virtual_cfa_rtx (&global_rtl.virtual_cfa_val)
+
+#define VIRTUAL_CFA_REGNUM ((FIRST_VIRTUAL_REGISTER) + 4)
+
+#define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 4)
extern rtx find_next_ref PROTO((rtx, rtx));
extern rtx *find_single_use PROTO((rtx, rtx, rtx *));
@@ -1163,18 +1275,18 @@ extern rtx output_constant_def PROTO((union tree_node *));
extern rtx immed_real_const PROTO((union tree_node *));
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. */
#ifndef STORE_FLAG_VALUE
#define STORE_FLAG_VALUE 1
#endif
+/* Nonzero after the second flow pass has completed.
+ Set to 1 or 0 by toplev.c */
+extern int flow2_completed;
+
/* Nonzero after end of reload pass.
- Set to 1 or 0 by toplev.c. */
+ Set to 1 or 0 by reload1.c. */
extern int reload_completed;
@@ -1191,6 +1303,10 @@ extern int reload_in_progress;
the same indirect address eventually. */
extern int cse_not_expected;
+/* Set to nonzero before life analysis to indicate that it is unsafe to
+ generate any new pseudo registers. */
+extern int no_new_pseudos;
+
/* Indexed by pseudo register number, gives the rtx for that pseudo.
Allocated in parallel with regno_pointer_flag. */
extern rtx *regno_reg_rtx;
@@ -1206,24 +1322,6 @@ extern char *regno_pointer_align;
extern int rtx_to_tree_code PROTO((enum rtx_code));
-/* In rtlanal.c */
-extern int reg_set_p PROTO ((rtx, rtx));
-extern int reg_mentioned_p PROTO ((rtx, rtx));
-extern int reg_referenced_p PROTO ((rtx, rtx));
-extern int reg_used_between_p PROTO ((rtx, rtx, rtx));
-extern int reg_set_p PROTO ((rtx, rtx));
-extern int reg_referenced_between_p PROTO ((rtx, rtx, rtx));
-extern int reg_set_between_p PROTO ((rtx, rtx, rtx));
-extern int rtx_unstable_p PROTO ((rtx));
-extern int rtx_addr_varies_p PROTO ((rtx));
-extern int rtx_equal_p PROTO ((rtx, rtx));
-extern int inequality_comparisons_p PROTO ((rtx));
-extern int dead_or_set_p PROTO ((rtx, rtx));
-extern int dead_or_set_regno_p PROTO ((rtx, int));
-extern int no_labels_between_p PROTO ((rtx, rtx));
-extern int modified_between_p PROTO ((rtx, rtx, rtx));
-extern int modified_in_p PROTO ((rtx, rtx));
-
/* In tree.c */
extern void obfree PROTO ((char *));
struct obstack;
@@ -1249,13 +1347,16 @@ extern void cse_end_of_basic_block PROTO ((rtx,
/* In jump.c */
extern int comparison_dominates_p PROTO ((enum rtx_code, enum rtx_code));
extern int condjump_p PROTO ((rtx));
+extern rtx condjump_label PROTO ((rtx));
extern int simplejump_p PROTO ((rtx));
+extern int returnjump_p PROTO ((rtx));
extern int sets_cc0_p PROTO ((rtx));
extern int invert_jump PROTO ((rtx, rtx));
extern int rtx_renumbered_equal_p PROTO ((rtx, rtx));
extern int true_regnum PROTO ((rtx));
extern int redirect_jump PROTO ((rtx, rtx));
extern void jump_optimize PROTO ((rtx, int, int, int));
+extern void rebuild_jump_labels PROTO ((rtx));
extern void thread_jumps PROTO ((rtx, int, int));
extern int redirect_exp PROTO ((rtx *, rtx, rtx, rtx));
extern int rtx_equal_for_thread_p PROTO ((rtx, rtx, rtx));
@@ -1295,9 +1396,11 @@ extern void link_cc0_insns PROTO ((rtx));
extern void add_insn PROTO ((rtx));
extern void add_insn_before PROTO ((rtx, rtx));
extern void add_insn_after PROTO ((rtx, rtx));
+extern void remove_insn PROTO ((rtx));
extern void reorder_insns_with_line_notes PROTO ((rtx, rtx, rtx));
extern void emit_insn_after_with_line_notes PROTO ((rtx, rtx, rtx));
extern enum rtx_code classify_insn PROTO ((rtx));
+extern void init_virtual_regs PROTO ((void));
extern rtx emit PROTO ((rtx));
/* Query and clear/ restore no_line_numbers. This is used by the
switch / case handling in stmt.c to give proper line numbers in
@@ -1331,14 +1434,15 @@ extern void debug_rtx_list PROTO ((rtx, int));
extern rtx debug_rtx_find PROTO ((rtx, int));
#ifdef BUFSIZ
extern void print_rtl PROTO ((FILE *, rtx));
-extern void print_rtl_single PROTO ((FILE *, rtx));
+extern int print_rtl_single PROTO ((FILE *, rtx));
extern void print_inline_rtx PROTO ((FILE *, rtx, int));
#endif
/* In loop.c */
extern void init_loop PROTO ((void));
+extern rtx libcall_other_reg PROTO ((rtx, rtx));
#ifdef BUFSIZ
-extern void loop_optimize PROTO ((rtx, FILE *, int));
+extern void loop_optimize PROTO ((rtx, FILE *, int, int));
#endif
extern void record_excess_regs PROTO ((rtx, rtx, rtx *));
@@ -1356,53 +1460,20 @@ extern void purge_addressof PROTO ((rtx));
/* In reload.c */
extern int operands_match_p PROTO ((rtx, rtx));
extern int safe_from_earlyclobber PROTO ((rtx, rtx));
-extern int strict_memory_address_p PROTO ((enum machine_mode, rtx));
-
-/* In recog.c */
-extern int memory_address_p PROTO ((enum machine_mode, rtx));
-extern int constrain_operands PROTO ((int, int));
-extern int mode_dependent_address_p PROTO ((rtx));
-extern void init_recog_no_volatile PROTO ((void));
-extern int offsettable_memref_p PROTO ((rtx));
-extern int offsettable_nonstrict_memref_p PROTO ((rtx));
-extern int reg_fits_class_p PROTO ((rtx, register enum reg_class,
- int, enum machine_mode));
-extern int check_asm_operands PROTO ((rtx));
-extern int address_operand PROTO ((rtx, enum machine_mode));
-extern int const_int_operand PROTO ((rtx, enum machine_mode));
-extern int const_double_operand PROTO ((rtx, enum machine_mode));
-extern int general_operand PROTO ((rtx, enum machine_mode));
-extern int immediate_operand PROTO ((rtx, enum machine_mode));
-extern int nonimmediate_operand PROTO ((rtx, enum machine_mode));
-extern int memory_operand PROTO ((rtx, enum machine_mode));
-extern int nonmemory_operand PROTO ((rtx, enum machine_mode));
-extern int push_operand PROTO ((rtx, enum machine_mode));
-extern int register_operand PROTO ((rtx, enum machine_mode));
-extern int scratch_operand PROTO ((rtx, enum machine_mode));
-extern int indirect_operand PROTO ((rtx, enum machine_mode));
-extern int mode_independent_operand PROTO ((rtx, enum machine_mode));
-extern int comparison_operator PROTO ((rtx, enum machine_mode));
-extern void init_recog_no_volatile PROTO ((void));
-extern void init_recog PROTO ((void));
-extern int validate_replace_rtx PROTO ((rtx, rtx, rtx));
-extern int offsettable_address_p PROTO ((int, enum machine_mode, rtx));
-extern int next_insn_tests_no_inequality PROTO ((rtx));
-extern int recog_memoized PROTO ((rtx));
-extern int validate_change PROTO ((rtx, rtx *, rtx, int));
-extern int apply_change_group PROTO ((void));
-extern void cancel_changes PROTO ((int));
-extern int num_validated_changes PROTO ((void));
-
-/* In insn-recog.c */
-extern int recog PROTO ((rtx, rtx, int *));
/* In stmt.c */
extern void expand_null_return PROTO((void));
extern void emit_jump PROTO ((rtx));
extern int preserve_subexpressions_p PROTO ((void));
+/* List (chain of EXPR_LIST) of labels heading the current handlers for
+ nonlocal gotos. */
+extern rtx nonlocal_goto_handler_labels;
+
/* In expr.c */
extern void init_expr_once PROTO ((void));
+extern void move_by_pieces PROTO ((rtx, rtx, int, int));
+
/* In stupid.c */
#ifdef BUFSIZ
@@ -1410,11 +1481,13 @@ extern void stupid_life_analysis PROTO ((rtx, int, FILE *));
#endif
/* In flow.c */
-extern void allocate_for_life_analysis PROTO ((void));
-extern void recompute_reg_usage PROTO ((rtx));
+extern void allocate_bb_life_data PROTO ((void));
+extern void allocate_reg_life_data PROTO ((void));
+extern void recompute_reg_usage PROTO ((rtx, int));
#ifdef BUFSIZ
extern void dump_flow_info PROTO ((FILE *));
#endif
+extern void free_bb_mem PROTO ((void));
/* In expmed.c */
extern void init_expmed PROTO ((void));
@@ -1426,7 +1499,7 @@ extern rtx expand_mult_highpart PROTO ((enum machine_mode, rtx,
/* In gcse.c */
#ifdef BUFSIZ
-extern void gcse_main PROTO ((rtx, FILE *));
+extern int gcse_main PROTO ((rtx, FILE *));
#endif
/* In global.c */
@@ -1469,7 +1542,8 @@ extern void init_optabs PROTO ((void));
#ifdef BUFSIZ
extern void dump_local_alloc PROTO ((FILE *));
#endif
-extern void local_alloc PROTO ((void));
+extern int local_alloc PROTO ((void));
+extern int function_invariant_p PROTO ((rtx));
/* In reload1.c */
extern void reload_cse_regs PROTO ((rtx));
@@ -1483,7 +1557,7 @@ extern int reload PROTO ((rtx, int, FILE *));
extern void init_caller_save PROTO ((void));
/* In profile.c */
-extern void init_branch_prob PROTO ((char *));
+extern void init_branch_prob PROTO ((const char *));
#ifdef BUFSIZ
extern void branch_prob PROTO ((rtx, FILE *));
extern void end_branch_prob PROTO ((FILE *));
@@ -1549,5 +1623,11 @@ extern void init_alias_analysis PROTO ((void));
extern void end_alias_analysis PROTO ((void));
extern void record_base_value PROTO ((int, rtx, int));
+extern void record_alias_subset PROTO ((int, int));
+extern rtx addr_side_effect_eval PROTO ((rtx, int, int));
+
+#ifdef STACK_REGS
+extern int stack_regs_mentioned PROTO((rtx insn));
+#endif
#endif /* _RTL_H */
diff --git a/contrib/gcc/rtl.texi b/contrib/gcc/rtl.texi
index baba532..ebb07ac 100644
--- a/contrib/gcc/rtl.texi
+++ b/contrib/gcc/rtl.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 89, 92, 94, 97, 1998 Free Software Foundation, Inc.
+@c Copyright (C) 1988, 89, 92, 94, 97, 1998, 1999 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -20,6 +20,7 @@ form uses nested parentheses to indicate the pointers in the internal form.
@menu
* RTL Objects:: Expressions vs vectors vs strings vs integers.
+* RTL Classes:: Categories of RTL expresion objects, and their structure.
* Accessors:: Macros to access expression operands or vector elts.
* Flags:: Other flags in an RTL expression.
* Machine Modes:: Describing the size and format of a datum.
@@ -39,7 +40,7 @@ form uses nested parentheses to indicate the pointers in the internal form.
* Reading RTL:: Reading textual RTL from a file.
@end menu
-@node RTL Objects, Accessors, RTL, RTL
+@node RTL Objects, RTL Classes, RTL, RTL
@section RTL Object Types
@cindex RTL object types
@@ -108,11 +109,68 @@ manual, they are shown as follows: @code{const_int}.
In a few contexts a null pointer is valid where an expression is normally
wanted. The written form of this is @code{(nil)}.
-@node Accessors, Flags, RTL Objects, RTL
-@section Access to Operands
-@cindex accessors
-@cindex access to operands
-@cindex operand access
+@node RTL Classes, Accessors, RTL Objects, RTL
+@section RTL Classes and Formats
+@cindex RTL classes
+@cindex classes of RTX codes
+@cindex RTX codes, classes of
+@findex GET_RTX_CLASS
+
+The various expression codes are divided into several @dfn{classes},
+which are represented by single characters. You can determine the class
+of an RTX code with the macro @code{GET_RTX_CLASS (@var{code})}.
+Currently, @file{rtx.def} defines these classes:
+
+@table @code
+@item o
+An RTX code that represents an actual object, such as a register
+(@code{REG}) or a memory location (@code{MEM}, @code{SYMBOL_REF}).
+Constants and basic transforms on objects (@code{ADDRESSOF},
+@code{HIGH}, @code{LO_SUM}) are also included. Note that @code{SUBREG}
+and @code{STRICT_LOW_PART} are not in this class, but in class @code{x}.
+
+@item <
+An RTX code for a comparison, such as @code{NE} or @code{LT}.
+
+@item 1
+An RTX code for a unary arithmetic operation, such as @code{NEG},
+@code{NOT}, or @code{ABS}. This category also includes value extension
+(sign or zero) and conversions between integer and floating point.
+
+@item c
+An RTX code for a commutative binary operation, such as @code{PLUS} or
+@code{AND}. @code{NE} and @code{EQ} are comparisons, so they have class
+@code{<}.
+
+@item 2
+An RTX code for a non-commutative binary operation, such as @code{MINUS},
+@code{DIV}, or @code{ASHIFTRT}.
+
+@item b
+An RTX code for a bitfield operation. Currently only
+@code{ZERO_EXTRACT} and @code{SIGN_EXTRACT}. These have three inputs
+and are lvalues (so they can be used for insertion as well). @xref{Bit
+Fields}.
+
+@item 3
+An RTX code for other three input operations. Currently only
+@code{IF_THEN_ELSE}.
+
+@item i
+An RTX code for an entire instruction: @code{INSN}, @code{JUMP_INSN}, and
+@code{CALL_INSN}. @xref{Insns}.
+
+@item m
+An RTX code for something that matches in insns, such as
+@code{MATCH_DUP}. These only occur in machine descriptions.
+
+@item x
+All other RTX codes. This category includes the remaining codes used
+only in machine descriptions (@code{DEFINE_*}, etc.). It also includes
+all the codes describing side effects (@code{SET}, @code{USE},
+@code{CLOBBER}, etc.) and the non-insns that may appear on an insn
+chain, such as @code{NOTE}, @code{BARRIER}, and @code{CODE_LABEL}.
+@end table
@cindex RTL format
For each expression type @file{rtl.def} specifies the number of
@@ -120,7 +178,7 @@ contained objects and their kinds, with four possibilities: @samp{e} for
expression (actually a pointer to an expression), @samp{i} for integer,
@samp{w} for wide integer, @samp{s} for string, and @samp{E} for vector
of expressions. The sequence of letters for an expression code is
-called its @dfn{format}. Thus, the format of @code{subreg} is
+called its @dfn{format}. For example, the format of @code{subreg} is
@samp{ei}.@refill
@cindex RTL format characters
@@ -154,8 +212,8 @@ An omitted vector is effectively the same as a vector of no elements.
special ways by small parts of the compiler.
@end table
-There are macros to get the number of operands, the format, and the
-class of an expression code:
+There are macros to get the number of operands and the format
+of an expression code:
@table @code
@findex GET_RTX_LENGTH
@@ -165,54 +223,41 @@ Number of operands of an RTX of code @var{code}.
@findex GET_RTX_FORMAT
@item GET_RTX_FORMAT (@var{code})
The format of an RTX of code @var{code}, as a C string.
+@end table
-@findex GET_RTX_CLASS
-@cindex classes of RTX codes
-@item GET_RTX_CLASS (@var{code})
-A single character representing the type of RTX operation that code
-@var{code} performs.
-
-The following classes are defined:
+Some classes of RTX codes always have the same format. For example, it
+is safe to assume that all comparison operations have format @code{ee}.
@table @code
-@item o
-An RTX code that represents an actual object, such as @code{reg} or
-@code{mem}. @code{subreg} is not in this class.
-
-@item <
-An RTX code for a comparison. The codes in this class are
-@code{NE}, @code{EQ}, @code{LE}, @code{LT}, @code{GE}, @code{GT},
-@code{LEU}, @code{LTU}, @code{GEU}, @code{GTU}.@refill
-
@item 1
-An RTX code for a unary arithmetic operation, such as @code{neg}.
+All codes of this class have format @code{e}.
-@item c
-An RTX code for a commutative binary operation, other than @code{NE}
-and @code{EQ} (which have class @samp{<}).
-
-@item 2
-An RTX code for a noncommutative binary operation, such as @code{MINUS}.
+@item <
+@itemx c
+@itemx 2
+All codes of these classes have format @code{ee}.
@item b
-An RTX code for a bitfield operation, either @code{ZERO_EXTRACT} or
-@code{SIGN_EXTRACT}.
-
-@item 3
-An RTX code for other three input operations, such as @code{IF_THEN_ELSE}.
+@itemx 3
+All codes of these classes have format @code{eee}.
@item i
-An RTX code for a machine insn (@code{INSN}, @code{JUMP_INSN}, and
-@code{CALL_INSN}).@refill
-
-@item m
-An RTX code for something that matches in insns, such as @code{MATCH_DUP}.
+All codes of this class have formats that begin with @code{iuueiee}.
+@xref{Insns}. Note that not all RTL objects linked onto an insn chain
+are of class @code{i}.
-@item x
-All other RTX codes.
-@end table
+@item o
+@itemx m
+@itemx x
+You can make no assumptions about the format of these codes.
@end table
+@node Accessors, Flags, RTL Classes, RTL
+@section Access to Operands
+@cindex accessors
+@cindex access to operands
+@cindex operand access
+
@findex XEXP
@findex XINT
@findex XWINT
@@ -305,10 +350,24 @@ Stored in the @code{volatil} field and printed as @samp{/v}.
@cindex @code{in_struct}, in @code{mem}
@cindex @samp{/s} in RTL dump
@item MEM_IN_STRUCT_P (@var{x})
-In @code{mem} expressions, nonzero for reference to an entire
-structure, union or array, or to a component of one. Zero for
-references to a scalar variable or through a pointer to a scalar.
-Stored in the @code{in_struct} field and printed as @samp{/s}.
+In @code{mem} expressions, nonzero for reference to an entire structure,
+union or array, or to a component of one. Zero for references to a
+scalar variable or through a pointer to a scalar. Stored in the
+@code{in_struct} field and printed as @samp{/s}. If both this flag and
+MEM_SCALAR_P are clear, then we don't know whether this MEM is in a
+structure or not. Both flags should never be simultaneously set.
+
+@findex MEM_SCALAR_P
+@cindex @code{mem} and @samp{/f}
+@cindex @code{frame_related}, in@code{mem}
+@cindex @samp{/f} in RTL dump
+@item MEM_SCALAR_P (@var{x})
+In @code{mem} expressions, nonzero for reference to a scalar known not
+to be a member of a structure, union, or array. Zero for such
+references and for indirections through pointers, even pointers pointing
+to scalar types. If both this flag and MEM_STRUCT_P are clear, then we
+don't know whether this MEM is in a structure or not. Both flags should
+never be simultaneously set.
@findex MEM_ALIAS_SET
@item MEM_ALIAS_SET (@var{x})
@@ -391,6 +450,13 @@ other functions or by aliasing.) Stored in the
Nonzero in an insn if it resulted from an in-line function call.
Stored in the @code{integrated} field and printed as @samp{/i}.
+@findex RTX_FRAME_RELATED_P
+@item RTX_FRAME_RELATED_P (@var{x})
+Nonzero in an insn or expression which is part of a function
+prologue and sets the stack pointer, sets the frame pointer, or saves a
+register. This flag is required for exception handling support
+on targets with RTL prologues.
+
@findex SYMBOL_REF_USED
@cindex @code{used}, in @code{symbol_ref}
@item SYMBOL_REF_USED (@var{x})
@@ -2036,7 +2102,7 @@ and of @var{min} and @var{max} to @var{base}. See rtl.def for details.@refill
@cindex RTL predecrement
@cindex RTL postdecrement
-Four special side-effect expression codes appear as memory addresses.
+Six special side-effect expression codes appear as memory addresses.
@table @code
@findex pre_dec
@@ -2071,6 +2137,38 @@ being decremented.
@findex post_inc
@item (post_inc:@var{m} @var{x})
Similar, but specifies incrementing @var{x} instead of decrementing it.
+
+@findex post_modify
+@item (post_modify:@var{m} @var{x} @var{y})
+
+Represents the side effect of setting @var{x} to @var{y} and
+represents @var{x} before @var{x} is modified. @var{x} must be a
+@code{reg} or @code{mem}, but most machines allow only a @code{reg}.
+@var{m} must be the machine mode for pointers on the machine in use.
+The amount @var{x} is decremented by is the length in bytes of the
+machine mode of the containing memory reference of which this expression
+serves as the address. Note that this is not currently implemented.
+
+The expression @var{y} must be one of three forms:
+@table @code
+@code{(plus:@var{m} @var{x} @var{z})},
+@code{(minus:@var{m} @var{x} @var{z})}, or
+@code{(plus:@var{m} @var{x} @var{i})},
+@end table
+where @var{z} is an index register and @var{i} is a constant.
+
+Here is an example of its use:@refill
+
+@example
+(mem:SF (post_modify:SI (reg:SI 42) (plus (reg:SI 42) (reg:SI 48))))
+@end example
+
+This says to modify pseudo register 42 by adding the contents of pseudo
+register 48 to it, after the use of what ever 42 points to.
+
+@findex post_modify
+@item (pre_modify:@var{m} @var{x} @var{expr})
+Similar except side effects happen before the use.
@end table
These embedded side effect expressions must be used with care. Instruction
@@ -2368,14 +2466,21 @@ Appears following each call to @code{setjmp} or a related function.
These codes are printed symbolically when they appear in debugging dumps.
@end table
+@cindex @code{TImode}, in @code{insn}
@cindex @code{HImode}, in @code{insn}
@cindex @code{QImode}, in @code{insn}
The machine mode of an insn is normally @code{VOIDmode}, but some
-phases use the mode for various purposes; for example, the reload pass
-sets it to @code{HImode} if the insn needs reloading but not register
-elimination and @code{QImode} if both are required. The common
-subexpression elimination pass sets the mode of an insn to @code{QImode}
-when it is the first insn in a block that has already been processed.
+phases use the mode for various purposes.
+
+The common subexpression elimination pass sets the mode of an insn to
+@code{QImode} when it is the first insn in a block that has already
+been processed.
+
+The second Haifa scheduling pass, for targets that can multiple issue,
+sets the mode of an insn to @code{TImode} when it is believed that the
+instruction begins an issue group. That is, when the instruction
+cannot issue simultaneously with the previous. This may be relied on
+by later passes, in particular machine-dependant reorg.
Here is a table of the extra fields of @code{insn}, @code{jump_insn}
and @code{call_insn} insns:
@@ -2625,11 +2730,17 @@ delete such sequences whose results are dead.
A @code{REG_EQUAL} note will also usually be attached to this insn to
provide the expression being computed by the sequence.
+These notes will be deleted after reload, since they are no longer
+accurate or useful.
+
@findex REG_LIBCALL
@item REG_LIBCALL
This is the inverse of @code{REG_RETVAL}: it is placed on the first
insn of a multi-insn sequence, and it points to the last one.
+These notes are deleted after reload, since they are no longer useful or
+accurate.
+
@findex REG_CC_SETTER
@findex REG_CC_USER
@item REG_CC_SETTER
@@ -2682,6 +2793,12 @@ probability that the branch will be taken.
These notes are found in JUMP insns after delayed branch scheduling
has taken place. They indicate both the direction and the likelyhood
of the JUMP. The format is a bitmask of ATTR_FLAG_* values.
+
+@findex REG_FRAME_RELATED_EXPR
+@item REG_FRAME_RELATED_EXPR
+This is used on an RTX_FRAME_RELATED_P insn wherein the attached expression
+is used in place of the actual insn pattern. This is done in cases where
+the pattern is either complex or misleading.
@end table
For convenience, the machine mode in an @code{insn_list} or
diff --git a/contrib/gcc/rtlanal.c b/contrib/gcc/rtlanal.c
index 221b3fa..fb4f87c 100644
--- a/contrib/gcc/rtlanal.c
+++ b/contrib/gcc/rtlanal.c
@@ -1,5 +1,5 @@
/* Analyze RTL for C-Compiler
- Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -326,6 +326,20 @@ no_labels_between_p (beg, end)
return 1;
}
+/* Return 1 if in between BEG and END, exclusive of BEG and END, there is
+ no JUMP_INSN insn. */
+
+int
+no_jumps_between_p (beg, end)
+ rtx beg, end;
+{
+ register rtx p;
+ for (p = NEXT_INSN (beg); p != end; p = NEXT_INSN (p))
+ if (GET_CODE (p) == JUMP_INSN)
+ return 0;
+ return 1;
+}
+
/* Nonzero if register REG is used in an insn between
FROM_INSN and TO_INSN (exclusive of those two). */
@@ -500,6 +514,52 @@ reg_set_p (reg, insn)
}
/* Similar to reg_set_between_p, but check all registers in X. Return 0
+ only if none of them are modified between START and END. Do not
+ consider non-registers one way or the other. */
+
+int
+regs_set_between_p (x, start, end)
+ rtx x;
+ rtx start, end;
+{
+ enum rtx_code code = GET_CODE (x);
+ char *fmt;
+ int i, j;
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case PC:
+ case CC0:
+ return 0;
+
+ case REG:
+ return reg_set_between_p (x, start, end);
+
+ default:
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e' && regs_set_between_p (XEXP (x, i), start, end))
+ return 1;
+
+ else if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (regs_set_between_p (XVECEXP (x, i, j), start, end))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Similar to reg_set_between_p, but check all registers in X. Return 0
only if none of them are modified between START and END. Return 1 if
X contains a MEM; this routine does not perform any memory aliasing. */
@@ -644,17 +704,51 @@ single_set (insn)
return 0;
}
+
+/* Given an INSN, return nonzero if it has more than one SET, else return
+ zero. */
+
+int
+multiple_sets (insn)
+ rtx insn;
+{
+ int found;
+ int i;
+
+ /* INSN must be an insn. */
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ return 0;
+
+ /* Only a PARALLEL can have multiple SETs. */
+ if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ {
+ for (i = 0, found = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+ if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
+ {
+ /* If we have already found a SET, then return now. */
+ if (found)
+ return 1;
+ else
+ found = 1;
+ }
+ }
+
+ /* Either zero or one SET. */
+ return 0;
+}
/* Return the last thing that X was assigned from before *PINSN. Verify that
the object is not modified up to VALID_TO. If it was, if we hit
a partial assignment to X, or hit a CODE_LABEL first, return X. If we
- found an assignment, update *PINSN to point to it. */
+ found an assignment, update *PINSN to point to it.
+ ALLOW_HWREG is set to 1 if hardware registers are allowed to be the src. */
rtx
-find_last_value (x, pinsn, valid_to)
+find_last_value (x, pinsn, valid_to, allow_hwreg)
rtx x;
rtx *pinsn;
rtx valid_to;
+ int allow_hwreg;
{
rtx p;
@@ -675,8 +769,8 @@ find_last_value (x, pinsn, valid_to)
if (! modified_between_p (src, PREV_INSN (p), valid_to)
/* Reject hard registers because we don't usually want
to use them; we'd rather use a pseudo. */
- && ! (GET_CODE (src) == REG
- && REGNO (src) < FIRST_PSEUDO_REGISTER))
+ && (! (GET_CODE (src) == REG
+ && REGNO (src) < FIRST_PSEUDO_REGISTER) || allow_hwreg))
{
*pinsn = p;
return src;
@@ -851,6 +945,18 @@ reg_overlap_mentioned_p (x, in)
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
|| GET_CODE (x) == CC0)
return reg_mentioned_p (x, in);
+ else if (GET_CODE (x) == PARALLEL
+ && GET_MODE (x) == BLKmode)
+ {
+ register int i;
+
+ /* If any register in here refers to it
+ we return true. */
+ for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+ if (reg_overlap_mentioned_p (SET_DEST (XVECEXP (x, 0, i)), in))
+ return 1;
+ return 0;
+ }
else
abort ();
@@ -1074,7 +1180,7 @@ rtx_equal_p (x, y)
void
note_stores (x, fun)
register rtx x;
- void (*fun) ();
+ void (*fun) PROTO ((rtx, rtx));
{
if ((GET_CODE (x) == SET || GET_CODE (x) == CLOBBER))
{
@@ -1086,7 +1192,16 @@ note_stores (x, fun)
|| GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- (*fun) (dest, x);
+
+ if (GET_CODE (dest) == PARALLEL
+ && GET_MODE (dest) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ (*fun) (SET_DEST (XVECEXP (dest, 0, i)), x);
+ }
+ else
+ (*fun) (dest, x);
}
else if (GET_CODE (x) == PARALLEL)
{
@@ -1105,7 +1220,15 @@ note_stores (x, fun)
|| GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- (*fun) (dest, y);
+ if (GET_CODE (dest) == PARALLEL
+ && GET_MODE (dest) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ (*fun) (SET_DEST (XVECEXP (dest, 0, i)), y);
+ }
+ else
+ (*fun) (dest, y);
}
}
}
@@ -1165,30 +1288,21 @@ dead_or_set_regno_p (insn, test_regno)
int regno, endregno;
rtx link;
- /* REG_READ notes are not normally maintained after reload, so we
- ignore them if the are invalid. */
- if (! reload_completed
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- || PRESERVE_DEATH_INFO_REGNO_P (test_regno)
-#endif
- )
+ /* See if there is a death note for something that includes
+ TEST_REGNO. */
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
{
- /* See if there is a death note for something that includes
- TEST_REGNO. */
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- {
- if (REG_NOTE_KIND (link) != REG_DEAD
- || GET_CODE (XEXP (link, 0)) != REG)
- continue;
+ if (REG_NOTE_KIND (link) != REG_DEAD
+ || GET_CODE (XEXP (link, 0)) != REG)
+ continue;
- regno = REGNO (XEXP (link, 0));
- endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
- : regno + HARD_REGNO_NREGS (regno,
- GET_MODE (XEXP (link, 0))));
+ regno = REGNO (XEXP (link, 0));
+ endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
+ : regno + HARD_REGNO_NREGS (regno,
+ GET_MODE (XEXP (link, 0))));
- if (test_regno >= regno && test_regno < endregno)
- return 1;
- }
+ if (test_regno >= regno && test_regno < endregno)
+ return 1;
}
if (GET_CODE (insn) == CALL_INSN
@@ -1202,7 +1316,7 @@ dead_or_set_regno_p (insn, test_regno)
/* A value is totally replaced if it is the destination or the
destination is a SUBREG of REGNO that does not change the number of
words in it. */
- if (GET_CODE (dest) == SUBREG
+ if (GET_CODE (dest) == SUBREG
&& (((GET_MODE_SIZE (GET_MODE (dest))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
@@ -1415,6 +1529,36 @@ remove_note (insn, note)
abort ();
}
+
+/* Search LISTP (an EXPR_LIST) for NODE and remove NODE from the list
+ if it is found.
+
+ A simple equality test is used to determine if NODE is on the
+ EXPR_LIST. */
+
+void
+remove_node_from_expr_list (node, listp)
+ rtx node;
+ rtx *listp;
+{
+ rtx temp = *listp;
+ rtx prev = NULL_RTX;
+
+ while (temp)
+ {
+ if (node == XEXP (temp, 0))
+ {
+ /* Splice the node out of the list. */
+ if (prev)
+ XEXP (prev, 1) = XEXP (temp, 1);
+ else
+ *listp = XEXP (temp, 1);
+
+ return;
+ }
+ temp = XEXP (temp, 1);
+ }
+}
/* Nonzero if X contains any volatile instructions. These are instructions
which may cause unpredictable machine state instructions, and thus no
@@ -2015,3 +2159,133 @@ computed_jump_p (insn)
}
return 0;
}
+
+/* Traverse X via depth-first search, calling F for each
+ sub-expression (including X itself). F is also passed the DATA.
+ If F returns -1, do not traverse sub-expressions, but continue
+ traversing the rest of the tree. If F ever returns any other
+ non-zero value, stop the traversal, and return the value returned
+ by F. Otherwise, return 0. This function does not traverse inside
+ tree structure that contains RTX_EXPRs, or into sub-expressions
+ whose format code is `0' since it is not known whether or not those
+ codes are actually RTL.
+
+ This routine is very general, and could (should?) be used to
+ implement many of the other routines in this file. */
+
+int
+for_each_rtx (x, f, data)
+ rtx *x;
+ rtx_function f;
+ void *data;
+{
+ int result;
+ int length;
+ char* format;
+ int i;
+
+ /* Call F on X. */
+ result = (*f)(x, data);
+ if (result == -1)
+ /* Do not traverse sub-expressions. */
+ return 0;
+ else if (result != 0)
+ /* Stop the traversal. */
+ return result;
+
+ if (*x == NULL_RTX)
+ /* There are no sub-expressions. */
+ return 0;
+
+ length = GET_RTX_LENGTH (GET_CODE (*x));
+ format = GET_RTX_FORMAT (GET_CODE (*x));
+
+ for (i = 0; i < length; ++i)
+ {
+ switch (format[i])
+ {
+ case 'e':
+ result = for_each_rtx (&XEXP (*x, i), f, data);
+ if (result != 0)
+ return result;
+ break;
+
+ case 'V':
+ case 'E':
+ if (XVEC (*x, i) != 0)
+ {
+ int j;
+ for (j = 0; j < XVECLEN (*x, i); ++j)
+ {
+ result = for_each_rtx (&XVECEXP (*x, i, j), f, data);
+ if (result != 0)
+ return result;
+ }
+ }
+ break;
+
+ default:
+ /* Nothing to do. */
+ break;
+ }
+
+ }
+
+ return 0;
+}
+
+/* Searches X for any reference to REGNO, returning the rtx of the
+ reference found if any. Otherwise, returns NULL_RTX. */
+
+rtx
+regno_use_in (regno, x)
+ int regno;
+ rtx x;
+{
+ register char *fmt;
+ int i, j;
+ rtx tem;
+
+ if (GET_CODE (x) == REG && REGNO (x) == regno)
+ return x;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ {
+ if ((tem = regno_use_in (regno, XEXP (x, i))))
+ return tem;
+ }
+ else if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
+ return tem;
+ }
+
+ return NULL_RTX;
+}
+
+
+/* Return 1 if X is an autoincrement side effect and the register is
+ not the stack pointer. */
+int
+auto_inc_p (x)
+ rtx x;
+{
+ switch (GET_CODE (x))
+ {
+ case PRE_INC:
+ case POST_INC:
+ case PRE_DEC:
+ case POST_DEC:
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ /* There are no REG_INC notes for SP. */
+ if (XEXP (x, 0) != stack_pointer_rtx)
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
diff --git a/contrib/gcc/sbitmap.c b/contrib/gcc/sbitmap.c
new file mode 100644
index 0000000..2a41792
--- /dev/null
+++ b/contrib/gcc/sbitmap.c
@@ -0,0 +1,470 @@
+/* Simple bitmaps.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "flags.h"
+#include "basic-block.h"
+
+/* Bitmap manipulation routines. */
+
+/* Allocate a simple bitmap of N_ELMS bits. */
+
+sbitmap
+sbitmap_alloc (n_elms)
+ int n_elms;
+{
+ int bytes, size, amt;
+ sbitmap bmap;
+
+ size = SBITMAP_SET_SIZE (n_elms);
+ bytes = size * sizeof (SBITMAP_ELT_TYPE);
+ amt = (sizeof (struct simple_bitmap_def)
+ + bytes - sizeof (SBITMAP_ELT_TYPE));
+ bmap = (sbitmap) xmalloc (amt);
+ bmap->n_bits = n_elms;
+ bmap->size = size;
+ bmap->bytes = bytes;
+ return bmap;
+}
+
+/* Allocate a vector of N_VECS bitmaps of N_ELMS bits. */
+
+sbitmap *
+sbitmap_vector_alloc (n_vecs, n_elms)
+ int n_vecs, n_elms;
+{
+ int i, bytes, offset, elm_bytes, size, amt, vector_bytes;
+ sbitmap *bitmap_vector;
+
+ size = SBITMAP_SET_SIZE (n_elms);
+ bytes = size * sizeof (SBITMAP_ELT_TYPE);
+ elm_bytes = (sizeof (struct simple_bitmap_def)
+ + bytes - sizeof (SBITMAP_ELT_TYPE));
+ vector_bytes = n_vecs * sizeof (sbitmap *);
+
+ /* Round up `vector_bytes' to account for the alignment requirements
+ of an sbitmap. One could allocate the vector-table and set of sbitmaps
+ separately, but that requires maintaining two pointers or creating
+ a cover struct to hold both pointers (so our result is still just
+ one pointer). Neither is a bad idea, but this is simpler for now. */
+ {
+ /* Based on DEFAULT_ALIGNMENT computation in obstack.c. */
+ struct { char x; SBITMAP_ELT_TYPE y; } align;
+ int alignment = (char *) & align.y - & align.x;
+ vector_bytes = (vector_bytes + alignment - 1) & ~ (alignment - 1);
+ }
+
+ amt = vector_bytes + (n_vecs * elm_bytes);
+ bitmap_vector = (sbitmap *) xmalloc (amt);
+
+ for (i = 0, offset = vector_bytes;
+ i < n_vecs;
+ i++, offset += elm_bytes)
+ {
+ sbitmap b = (sbitmap) ((char *) bitmap_vector + offset);
+ bitmap_vector[i] = b;
+ b->n_bits = n_elms;
+ b->size = size;
+ b->bytes = bytes;
+ }
+
+ return bitmap_vector;
+}
+
+/* Copy sbitmap SRC to DST. */
+
+void
+sbitmap_copy (dst, src)
+ sbitmap dst, src;
+{
+ bcopy ((PTR) src->elms, (PTR) dst->elms,
+ sizeof (SBITMAP_ELT_TYPE) * dst->size);
+}
+
+/* Zero all elements in a bitmap. */
+
+void
+sbitmap_zero (bmap)
+ sbitmap bmap;
+{
+ bzero ((char *) bmap->elms, bmap->bytes);
+}
+
+/* Set to ones all elements in a bitmap. */
+
+void
+sbitmap_ones (bmap)
+ sbitmap bmap;
+{
+ memset (bmap->elms, -1, bmap->bytes);
+}
+
+/* Zero a vector of N_VECS bitmaps. */
+
+void
+sbitmap_vector_zero (bmap, n_vecs)
+ sbitmap *bmap;
+ int n_vecs;
+{
+ int i;
+
+ for (i = 0; i < n_vecs; i++)
+ sbitmap_zero (bmap[i]);
+}
+
+/* Set to ones a vector of N_VECS bitmaps. */
+
+void
+sbitmap_vector_ones (bmap, n_vecs)
+ sbitmap *bmap;
+ int n_vecs;
+{
+ int i;
+
+ for (i = 0; i < n_vecs; i++)
+ sbitmap_ones (bmap[i]);
+}
+
+/* Set DST to be A union (B - C).
+ DST = A | (B & ~C).
+ Return non-zero if any change is made. */
+
+int
+sbitmap_union_of_diff (dst, a, b, c)
+ sbitmap dst, a, b, c;
+{
+ int i,changed;
+ sbitmap_ptr dstp, ap, bp, cp;
+
+ changed = 0;
+ dstp = dst->elms;
+ ap = a->elms;
+ bp = b->elms;
+ cp = c->elms;
+ for (i = 0; i < dst->size; i++)
+ {
+ SBITMAP_ELT_TYPE tmp = *ap | (*bp & ~*cp);
+ if (*dstp != tmp)
+ changed = 1;
+ *dstp = tmp;
+ dstp++; ap++; bp++; cp++;
+ }
+ return changed;
+}
+
+/* Set bitmap DST to the bitwise negation of the bitmap SRC. */
+
+void
+sbitmap_not (dst, src)
+ sbitmap dst, src;
+{
+ int i;
+ sbitmap_ptr dstp, ap;
+
+ dstp = dst->elms;
+ ap = src->elms;
+ for (i = 0; i < dst->size; i++)
+ {
+ SBITMAP_ELT_TYPE tmp = ~(*ap);
+ *dstp = tmp;
+ dstp++; ap++;
+ }
+}
+
+/* Set the bits in DST to be the difference between the bits
+ in A and the bits in B. i.e. dst = a - b.
+ The - operator is implemented as a & (~b). */
+
+void
+sbitmap_difference (dst, a, b)
+ sbitmap dst, a, b;
+{
+ int i;
+ sbitmap_ptr dstp, ap, bp;
+
+ dstp = dst->elms;
+ ap = a->elms;
+ bp = b->elms;
+ for (i = 0; i < dst->size; i++)
+ *dstp++ = *ap++ & (~*bp++);
+}
+
+/* Set DST to be (A and B)).
+ Return non-zero if any change is made. */
+
+int
+sbitmap_a_and_b (dst, a, b)
+ sbitmap dst, a, b;
+{
+ int i,changed;
+ sbitmap_ptr dstp, ap, bp;
+
+ changed = 0;
+ dstp = dst->elms;
+ ap = a->elms;
+ bp = b->elms;
+ for (i = 0; i < dst->size; i++)
+ {
+ SBITMAP_ELT_TYPE tmp = *ap & *bp;
+ if (*dstp != tmp)
+ changed = 1;
+ *dstp = tmp;
+ dstp++; ap++; bp++;
+ }
+ return changed;
+}
+/* Set DST to be (A or B)).
+ Return non-zero if any change is made. */
+
+int
+sbitmap_a_or_b (dst, a, b)
+ sbitmap dst, a, b;
+{
+ int i,changed;
+ sbitmap_ptr dstp, ap, bp;
+
+ changed = 0;
+ dstp = dst->elms;
+ ap = a->elms;
+ bp = b->elms;
+ for (i = 0; i < dst->size; i++)
+ {
+ SBITMAP_ELT_TYPE tmp = *ap | *bp;
+ if (*dstp != tmp)
+ changed = 1;
+ *dstp = tmp;
+ dstp++; ap++; bp++;
+ }
+ return changed;
+}
+
+/* Set DST to be (A or (B and C)).
+ Return non-zero if any change is made. */
+
+int
+sbitmap_a_or_b_and_c (dst, a, b, c)
+ sbitmap dst, a, b, c;
+{
+ int i,changed;
+ sbitmap_ptr dstp, ap, bp, cp;
+
+ changed = 0;
+ dstp = dst->elms;
+ ap = a->elms;
+ bp = b->elms;
+ cp = c->elms;
+ for (i = 0; i < dst->size; i++)
+ {
+ SBITMAP_ELT_TYPE tmp = *ap | (*bp & *cp);
+ if (*dstp != tmp)
+ changed = 1;
+ *dstp = tmp;
+ dstp++; ap++; bp++; cp++;
+ }
+ return changed;
+}
+
+/* Set DST to be (A ann (B or C)).
+ Return non-zero if any change is made. */
+
+int
+sbitmap_a_and_b_or_c (dst, a, b, c)
+ sbitmap dst, a, b, c;
+{
+ int i,changed;
+ sbitmap_ptr dstp, ap, bp, cp;
+
+ changed = 0;
+ dstp = dst->elms;
+ ap = a->elms;
+ bp = b->elms;
+ cp = c->elms;
+ for (i = 0; i < dst->size; i++)
+ {
+ SBITMAP_ELT_TYPE tmp = *ap & (*bp | *cp);
+ if (*dstp != tmp)
+ changed = 1;
+ *dstp = tmp;
+ dstp++; ap++; bp++; cp++;
+ }
+ return changed;
+}
+
+/* Set the bitmap DST to the intersection of SRC of all predecessors or
+ successors of block number BB (PRED_SUCC says which). */
+
+void
+sbitmap_intersect_of_predsucc (dst, src, bb, pred_succ)
+ sbitmap dst;
+ sbitmap *src;
+ int bb;
+ int_list_ptr *pred_succ;
+{
+ int_list_ptr ps;
+ int ps_bb;
+ int set_size = dst->size;
+
+ ps = pred_succ[bb];
+
+ /* It is possible that there are no predecessors(/successors).
+ This can happen for example in unreachable code. */
+
+ if (ps == NULL)
+ {
+ /* In APL-speak this is the `and' reduction of the empty set and thus
+ the result is the identity for `and'. */
+ sbitmap_ones (dst);
+ return;
+ }
+
+ /* Set result to first predecessor/successor. */
+
+ for ( ; ps != NULL; ps = ps->next)
+ {
+ ps_bb = INT_LIST_VAL (ps);
+ if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
+ continue;
+ sbitmap_copy (dst, src[ps_bb]);
+ /* Break out since we're only doing first predecessor. */
+ break;
+ }
+ if (ps == NULL)
+ return;
+
+ /* Now do the remaining predecessors/successors. */
+
+ for (ps = ps->next; ps != NULL; ps = ps->next)
+ {
+ int i;
+ sbitmap_ptr p,r;
+
+ ps_bb = INT_LIST_VAL (ps);
+ if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
+ continue;
+
+ p = src[ps_bb]->elms;
+ r = dst->elms;
+
+ for (i = 0; i < set_size; i++)
+ *r++ &= *p++;
+ }
+}
+
+/* Set the bitmap DST to the union of SRC of all predecessors/successors of
+ block number BB. */
+
+void
+sbitmap_union_of_predsucc (dst, src, bb, pred_succ)
+ sbitmap dst;
+ sbitmap *src;
+ int bb;
+ int_list_ptr *pred_succ;
+{
+ int_list_ptr ps;
+ int ps_bb;
+ int set_size = dst->size;
+
+ ps = pred_succ[bb];
+
+ /* It is possible that there are no predecessors(/successors).
+ This can happen for example in unreachable code. */
+
+ if (ps == NULL)
+ {
+ /* In APL-speak this is the `or' reduction of the empty set and thus
+ the result is the identity for `or'. */
+ sbitmap_zero (dst);
+ return;
+ }
+
+ /* Set result to first predecessor/successor. */
+
+ for ( ; ps != NULL; ps = ps->next)
+ {
+ ps_bb = INT_LIST_VAL (ps);
+ if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
+ continue;
+ sbitmap_copy (dst, src[ps_bb]);
+ /* Break out since we're only doing first predecessor. */
+ break;
+ }
+ if (ps == NULL)
+ return;
+
+ /* Now do the remaining predecessors/successors. */
+
+ for (ps = ps->next; ps != NULL; ps = ps->next)
+ {
+ int i;
+ sbitmap_ptr p,r;
+
+ ps_bb = INT_LIST_VAL (ps);
+ if (ps_bb == ENTRY_BLOCK || ps_bb == EXIT_BLOCK)
+ continue;
+
+ p = src[ps_bb]->elms;
+ r = dst->elms;
+
+ for (i = 0; i < set_size; i++)
+ *r++ |= *p++;
+ }
+}
+
+void
+dump_sbitmap (file, bmap)
+ FILE *file;
+ sbitmap bmap;
+{
+ int i,j,n;
+ int set_size = bmap->size;
+ int total_bits = bmap->n_bits;
+
+ fprintf (file, " ");
+ for (i = n = 0; i < set_size && n < total_bits; i++)
+ {
+ for (j = 0; j < SBITMAP_ELT_BITS && n < total_bits; j++, n++)
+ {
+ if (n != 0 && n % 10 == 0)
+ fprintf (file, " ");
+ fprintf (file, "%d", (bmap->elms[i] & (1L << j)) != 0);
+ }
+ }
+ fprintf (file, "\n");
+}
+
+void
+dump_sbitmap_vector (file, title, subtitle, bmaps, n_maps)
+ FILE *file;
+ const char *title, *subtitle;
+ sbitmap *bmaps;
+ int n_maps;
+{
+ int bb;
+
+ fprintf (file, "%s\n", title);
+ for (bb = 0; bb < n_maps; bb++)
+ {
+ fprintf (file, "%s %d\n", subtitle, bb);
+ dump_sbitmap (file, bmaps[bb]);
+ }
+ fprintf (file, "\n");
+}
diff --git a/contrib/gcc/sbitmap.h b/contrib/gcc/sbitmap.h
new file mode 100644
index 0000000..ca475fa
--- /dev/null
+++ b/contrib/gcc/sbitmap.h
@@ -0,0 +1,122 @@
+/* Simple bitmaps.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* It's not clear yet whether using bitmap.[ch] will be a win.
+ It should be straightforward to convert so for now we keep things simple
+ while more important issues are dealt with. */
+
+#define SBITMAP_ELT_BITS HOST_BITS_PER_WIDE_INT
+#define SBITMAP_ELT_TYPE unsigned HOST_WIDE_INT
+
+typedef struct simple_bitmap_def {
+ /* Number of bits. */
+ int n_bits;
+ /* Size in elements. */
+ int size;
+ /* Size in bytes. */
+ int bytes;
+ /* The elements. */
+ SBITMAP_ELT_TYPE elms[1];
+} *sbitmap;
+
+typedef SBITMAP_ELT_TYPE *sbitmap_ptr;
+
+/* Return the set size needed for N elements. */
+#define SBITMAP_SET_SIZE(n) (((n) + SBITMAP_ELT_BITS - 1) / SBITMAP_ELT_BITS)
+
+/* set bit number bitno in the bitmap */
+#define SET_BIT(bitmap, bitno) \
+ ((bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] \
+ |= (SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS)
+
+/* test if bit number bitno in the bitmap is set */
+#define TEST_BIT(bitmap, bitno) \
+((bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] >> (bitno) % SBITMAP_ELT_BITS & 1)
+
+/* reset bit number bitno in the bitmap */
+#define RESET_BIT(bitmap, bitno) \
+ ((bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] \
+ &= ~((SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS))
+
+/* Loop over all elements of SBITSET, starting with MIN. */
+#define EXECUTE_IF_SET_IN_SBITMAP(SBITMAP, MIN, N, CODE) \
+do { \
+ unsigned int bit_num_ = (MIN) % (unsigned) SBITMAP_ELT_BITS; \
+ unsigned int word_num_ = (MIN) / (unsigned) SBITMAP_ELT_BITS; \
+ unsigned int size_ = (SBITMAP)->size; \
+ SBITMAP_ELT_TYPE *ptr_ = (SBITMAP)->elms; \
+ \
+ while (word_num_ < size_) \
+ { \
+ SBITMAP_ELT_TYPE word_ = ptr_[word_num_]; \
+ if (word_ != 0) \
+ { \
+ for (; bit_num_ < SBITMAP_ELT_BITS; ++bit_num_) \
+ { \
+ SBITMAP_ELT_TYPE mask_ = (SBITMAP_ELT_TYPE)1 << bit_num_; \
+ if ((word_ & mask_) != 0) \
+ { \
+ word_ &= ~mask_; \
+ (N) = word_num_ * SBITMAP_ELT_BITS + bit_num_; \
+ CODE; \
+ if (word_ == 0) \
+ break; \
+ } \
+ } \
+ } \
+ bit_num_ = 0; \
+ word_num_++; \
+ } \
+} while (0)
+
+#define sbitmap_free(map) free(map)
+#define sbitmap_vector_free(vec) free(vec)
+
+extern void dump_sbitmap PROTO ((FILE *, sbitmap));
+extern void dump_sbitmap_vector PROTO ((FILE *, const char *, const char *,
+ sbitmap *, int));
+
+extern sbitmap sbitmap_alloc PROTO ((int));
+extern sbitmap *sbitmap_vector_alloc PROTO ((int, int));
+
+extern void sbitmap_copy PROTO ((sbitmap, sbitmap));
+extern void sbitmap_zero PROTO ((sbitmap));
+extern void sbitmap_ones PROTO ((sbitmap));
+extern void sbitmap_vector_zero PROTO ((sbitmap *, int));
+extern void sbitmap_vector_ones PROTO ((sbitmap *, int));
+
+extern int sbitmap_union_of_diff PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
+extern void sbitmap_difference PROTO ((sbitmap, sbitmap, sbitmap));
+extern void sbitmap_not PROTO ((sbitmap, sbitmap));
+extern int sbitmap_a_or_b_and_c PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
+extern int sbitmap_a_and_b_or_c PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
+extern int sbitmap_a_and_b PROTO ((sbitmap, sbitmap, sbitmap));
+extern int sbitmap_a_or_b PROTO ((sbitmap, sbitmap, sbitmap));
+
+struct int_list;
+extern void sbitmap_intersect_of_predsucc PROTO ((sbitmap, sbitmap *,
+ int, struct int_list **));
+#define sbitmap_intersect_of_predecessors sbitmap_intersect_of_predsucc
+#define sbitmap_intersect_of_successors sbitmap_intersect_of_predsucc
+
+extern void sbitmap_union_of_predsucc PROTO ((sbitmap, sbitmap *, int,
+ struct int_list **));
+#define sbitmap_union_of_predecessors sbitmap_union_of_predsucc
+#define sbitmap_union_of_successors sbitmap_union_of_predsucc
diff --git a/contrib/gcc/scan-decls.c b/contrib/gcc/scan-decls.c
index d2f32a8..5fea643 100644
--- a/contrib/gcc/scan-decls.c
+++ b/contrib/gcc/scan-decls.c
@@ -1,5 +1,5 @@
/* scan-decls.c - Extracts declarations from cpp output.
- Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 97-98, 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -19,7 +19,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "hconfig.h"
#include "system.h"
-#include "gansidecl.h"
#include "cpplib.h"
#include "scan.h"
@@ -78,8 +77,8 @@ Here dname is the actual name being declared.
int
scan_decls (pfile, argc, argv)
cpp_reader *pfile;
- int argc;
- char **argv;
+ int argc ATTRIBUTE_UNUSED;
+ char **argv ATTRIBUTE_UNUSED;
{
int saw_extern, saw_inline;
int start_written;
@@ -170,7 +169,7 @@ scan_decls (pfile, argc, argv)
}
break;
case CPP_OTHER:
- if (CPP_WRITTEN (pfile) == start_written + 1
+ if (CPP_WRITTEN (pfile) == (size_t) start_written + 1
&& (CPP_PWRITTEN (pfile)[-1] == '*'
|| CPP_PWRITTEN (pfile)[-1] == '&'))
declarator_start = start_written;
@@ -190,7 +189,9 @@ scan_decls (pfile, argc, argv)
maybe_handle_comma:
if (token != CPP_COMMA)
goto new_statement;
+#if 0
handle_comma:
+#endif
/* Handle multiple declarators in a single declaration,
as in: extern char *strcpy (), *strcat (), ... ; */
if (declarator_start == 0)
diff --git a/contrib/gcc/scan.c b/contrib/gcc/scan.c
index 63e2470..156cd0e 100644
--- a/contrib/gcc/scan.c
+++ b/contrib/gcc/scan.c
@@ -1,5 +1,5 @@
/* Utility functions for scan-decls and fix-header programs.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1998 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
diff --git a/contrib/gcc/scan.h b/contrib/gcc/scan.h
index 12879c0..f59cd27 100644
--- a/contrib/gcc/scan.h
+++ b/contrib/gcc/scan.h
@@ -1,5 +1,5 @@
/* scan.h - Utility declarations for scan-decls and fix-header programs.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1998, 1999 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -34,7 +34,7 @@ typedef struct sstring
if ((STR)->limit - (STR)->ptr < (COUNT)) make_sstring_space (STR, COUNT);
#ifndef _PARAMS
-#if defined(__STDC__) || defined(__cplusplus)
+#if defined(ANSI_PROTOTYPES) || defined(__cplusplus)
#define _PARAMS(args) args
#else
#define _PARAMS(args) ()
@@ -44,9 +44,9 @@ typedef struct sstring
struct partial_proto;
struct fn_decl
{
- char *fname;
- char *rtype;
- char *params;
+ const char *fname;
+ const char *rtype;
+ const char *params;
struct partial_proto *partial;
};
@@ -57,8 +57,6 @@ extern int skip_spaces _PARAMS((FILE *, int));
extern int scan_ident _PARAMS((FILE *, sstring *, int));
extern int scan_string _PARAMS((FILE *, sstring *, int));
extern int read_upto _PARAMS((FILE *, sstring *, int));
-extern char *xmalloc _PARAMS((unsigned));
-extern char *xrealloc _PARAMS((char *, unsigned));
extern unsigned long hash _PARAMS((const char *));
extern void recognized_function _PARAMS((char *, int, int, char *, int, int, char *, int));
extern void recognized_extern _PARAMS((char *, int, char *, int));
diff --git a/contrib/gcc/sched.c b/contrib/gcc/sched.c
index 5b54028..e8cd070 100644
--- a/contrib/gcc/sched.c
+++ b/contrib/gcc/sched.c
@@ -1,5 +1,5 @@
/* Instruction scheduling pass.
- Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
Enhanced by, and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -108,8 +108,8 @@ Boston, MA 02111-1307, USA. */
This pass must update information that subsequent passes expect to be
correct. Namely: reg_n_refs, reg_n_sets, reg_n_deaths,
- reg_n_calls_crossed, and reg_live_length. Also, basic_block_head,
- basic_block_end.
+ reg_n_calls_crossed, and reg_live_length. Also, BLOCK_HEAD,
+ BLOCK_END.
The information in the line number notes is carefully retained by
this pass. Notes that refer to the starting and ending of
@@ -119,6 +119,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "toplev.h"
#include "rtl.h"
#include "basic-block.h"
#include "regs.h"
@@ -126,11 +127,19 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "insn-config.h"
#include "insn-attr.h"
+#include "recog.h"
+
+#ifndef INSN_SCHEDULING
+void
+schedule_insns (dump_file)
+ FILE *dump_file ATTRIBUTE_UNUSED;
+{
+}
+#else /* INSN_SCHEDULING -- rest of file */
extern char *reg_known_equiv_p;
extern rtx *reg_known_value;
-#ifdef INSN_SCHEDULING
/* Arrays set up by scheduling for the same respective purposes as
similar-named arrays set up by flow analysis. We work with these
arrays during the scheduling pass so we can compare values against
@@ -318,7 +327,7 @@ static void sched_analyze_1 PROTO((rtx, rtx));
static void sched_analyze_2 PROTO((rtx, rtx));
static void sched_analyze_insn PROTO((rtx, rtx, rtx));
static int sched_analyze PROTO((rtx, rtx));
-static void sched_note_set PROTO((int, rtx, int));
+static void sched_note_set PROTO((rtx, int));
static int rank_for_schedule PROTO((const GENERIC_PTR, const GENERIC_PTR));
static void swap_sort PROTO((rtx *, int));
static void queue_insn PROTO((rtx, int));
@@ -334,16 +343,12 @@ static int new_sometimes_live PROTO((struct sometimes *, int, int));
static void finish_sometimes_live PROTO((struct sometimes *, int));
static rtx reemit_notes PROTO((rtx, rtx));
static void schedule_block PROTO((int, FILE *));
-static rtx regno_use_in PROTO((int, rtx));
-static void split_hard_reg_notes PROTO((rtx, rtx, rtx, rtx));
+static void split_hard_reg_notes PROTO((rtx, rtx, rtx));
static void new_insn_dead_notes PROTO((rtx, rtx, rtx, rtx));
static void update_n_sets PROTO((rtx, int));
-static void update_flow_info PROTO((rtx, rtx, rtx, rtx));
/* Main entry point of this file. */
void schedule_insns PROTO((FILE *));
-
-#endif /* INSN_SCHEDULING */
#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
@@ -451,13 +456,6 @@ remove_dependence (insn, elem)
return;
}
-#ifndef INSN_SCHEDULING
-void
-schedule_insns (dump_file)
- FILE *dump_file;
-{
-}
-#else
#ifndef __GNUC__
#define __inline
#endif
@@ -608,7 +606,7 @@ blockage_range (unit, insn)
unsigned int blockage = INSN_BLOCKAGE (insn);
unsigned int range;
- if (UNIT_BLOCKED (blockage) != unit + 1)
+ if ((int) UNIT_BLOCKED (blockage) != unit + 1)
{
range = function_units[unit].blockage_range_function (insn);
/* We only cache the blockage range for one unit and then only if
@@ -1555,27 +1553,6 @@ sched_analyze_insn (x, insn, loop_notes)
REG_NOTES (insn) = loop_notes;
}
- /* 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
- example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
- In this case, we must consider the insn to use the register mentioned
- in the REG_DEAD note. Otherwise, we may accidentally move this insn
- after another insn that sets the register, thus getting obviously invalid
- rtl. This confuses reorg which believes that REG_DEAD notes are still
- meaningful.
-
- ??? We would get better code if we fixed reload to put the REG_DEAD
- notes in the right places, but that may not be worth the effort. */
-
- if (reload_completed)
- {
- rtx note;
-
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- if (REG_NOTE_KIND (note) == REG_DEAD)
- sched_analyze_2 (XEXP (note, 0), insn);
- }
-
EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i,
{
reg_last_sets[i] = insn;
@@ -1764,8 +1741,7 @@ sched_analyze (head, tail)
are scanning forwards. Mark that register as being born. */
static void
-sched_note_set (b, x, death)
- int b;
+sched_note_set (x, death)
rtx x;
int death;
{
@@ -2333,12 +2309,15 @@ attach_deaths (x, insn, set_p)
if (regno >= FIRST_PSEUDO_REGISTER || ! global_regs[regno])
{
- /* Never add REG_DEAD notes for the FRAME_POINTER_REGNUM or the
- STACK_POINTER_REGNUM, since these are always considered to be
- live. Similarly for ARG_POINTER_REGNUM if it is fixed. */
- if (regno != FRAME_POINTER_REGNUM
+ /* Never add REG_DEAD notes for STACK_POINTER_REGNUM
+ since it's always considered to be live. Similarly
+ for FRAME_POINTER_REGNUM if a frame pointer is needed
+ and for ARG_POINTER_REGNUM if it is fixed. */
+ if (! (regno == FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- && ! (regno == HARD_FRAME_POINTER_REGNUM)
+ && ! (regno == HARD_FRAME_POINTER_REGNUM
+ && (! reload_completed || frame_pointer_needed))
#endif
#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
&& ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
@@ -2639,8 +2618,8 @@ schedule_block (b, file)
int new_needs;
/* HEAD and TAIL delimit the region being scheduled. */
- rtx head = basic_block_head[b];
- rtx tail = basic_block_end[b];
+ rtx head = BLOCK_HEAD (b);
+ rtx tail = BLOCK_END (b);
/* PREV_HEAD and NEXT_TAIL are the boundaries of the insns
being scheduled. When the insns have been ordered,
these insns delimit where the new insns are to be
@@ -2654,7 +2633,7 @@ schedule_block (b, file)
if (file)
fprintf (file, ";;\t -- basic block number %d from %d to %d --\n",
- b, INSN_UID (basic_block_head[b]), INSN_UID (basic_block_end[b]));
+ b, INSN_UID (BLOCK_HEAD (b)), INSN_UID (BLOCK_END (b)));
i = max_reg_num ();
reg_last_uses = (rtx *) alloca (i * sizeof (rtx));
@@ -2904,7 +2883,7 @@ schedule_block (b, file)
if (reload_completed == 0)
{
- COPY_REG_SET (bb_live_regs, basic_block_live_at_start[b]);
+ COPY_REG_SET (bb_live_regs, BASIC_BLOCK (b)->global_live_at_start);
CLEAR_REG_SET (bb_dead_regs);
if (b == 0)
@@ -2916,7 +2895,7 @@ schedule_block (b, file)
/* We don't want to remove any REG_DEAD notes as the code below
does. */
- for (insn = basic_block_head[b]; insn != head;
+ for (insn = BLOCK_HEAD (b); insn != head;
insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
@@ -2928,20 +2907,20 @@ schedule_block (b, file)
a register must be marked as dead after this insn. */
if (GET_CODE (PATTERN (insn)) == SET
|| GET_CODE (PATTERN (insn)) == CLOBBER)
- sched_note_set (b, PATTERN (insn), 0);
+ sched_note_set (PATTERN (insn), 0);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
int j;
for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
|| GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == CLOBBER)
- sched_note_set (b, XVECEXP (PATTERN (insn), 0, j), 0);
+ sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
/* ??? This code is obsolete and should be deleted. It
is harmless though, so we will leave it in for now. */
for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == USE)
- sched_note_set (b, XVECEXP (PATTERN (insn), 0, j), 0);
+ sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
}
/* Each call clobbers (makes live) all call-clobbered regs
@@ -3000,7 +2979,7 @@ schedule_block (b, file)
block may have changed the current line number. */
rtx line = line_note_head[b];
- for (insn = basic_block_head[b];
+ for (insn = BLOCK_HEAD (b);
insn != next_tail;
insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
@@ -3038,20 +3017,20 @@ schedule_block (b, file)
must be marked as dead after this insn. */
if (GET_CODE (PATTERN (insn)) == SET
|| GET_CODE (PATTERN (insn)) == CLOBBER)
- sched_note_set (b, PATTERN (insn), 0);
+ sched_note_set (PATTERN (insn), 0);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
int j;
for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
|| GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == CLOBBER)
- sched_note_set (b, XVECEXP (PATTERN (insn), 0, j), 0);
+ sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
/* ??? This code is obsolete and should be deleted. It
is harmless though, so we will leave it in for now. */
for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == USE)
- sched_note_set (b, XVECEXP (PATTERN (insn), 0, j), 0);
+ sched_note_set (XVECEXP (PATTERN (insn), 0, j), 0);
}
/* Each call clobbers (makes live) all call-clobbered regs that are
@@ -3164,9 +3143,9 @@ schedule_block (b, file)
/* Where we start inserting insns is after TAIL. */
last = next_tail;
- new_needs = (NEXT_INSN (prev_head) == basic_block_head[b]
+ new_needs = (NEXT_INSN (prev_head) == BLOCK_HEAD (b)
? NEED_HEAD : NEED_NOTHING);
- if (PREV_INSN (next_tail) == basic_block_end[b])
+ if (PREV_INSN (next_tail) == BLOCK_END (b))
new_needs |= NEED_TAIL;
new_ready = n_ready;
@@ -3281,14 +3260,14 @@ schedule_block (b, file)
/* See if this is the last notice we must take of a register. */
if (GET_CODE (PATTERN (insn)) == SET
|| GET_CODE (PATTERN (insn)) == CLOBBER)
- sched_note_set (b, PATTERN (insn), 1);
+ sched_note_set (PATTERN (insn), 1);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
int j;
for (j = XVECLEN (PATTERN (insn), 0) - 1; j >= 0; j--)
if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET
|| GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == CLOBBER)
- sched_note_set (b, XVECEXP (PATTERN (insn), 0, j), 1);
+ sched_note_set (XVECEXP (PATTERN (insn), 0, j), 1);
}
/* This code keeps life analysis information up to date. */
@@ -3473,12 +3452,12 @@ schedule_block (b, file)
#endif
if (new_needs & NEED_HEAD)
- basic_block_head[b] = head;
+ BLOCK_HEAD (b) = head;
PREV_INSN (head) = prev_head;
NEXT_INSN (prev_head) = head;
if (new_needs & NEED_TAIL)
- basic_block_end[b] = tail;
+ BLOCK_END (b) = tail;
NEXT_INSN (tail) = next_tail;
PREV_INSN (next_tail) = tail;
@@ -3488,8 +3467,8 @@ schedule_block (b, file)
rtx line, note, prev, new;
int notes = 0;
- head = basic_block_head[b];
- next_tail = NEXT_INSN (basic_block_end[b]);
+ head = BLOCK_HEAD (b);
+ next_tail = NEXT_INSN (BLOCK_END (b));
/* Determine the current line-number. We want to know the current
line number of the first insn of the block here, in case it is
@@ -3543,7 +3522,7 @@ schedule_block (b, file)
if (file)
{
fprintf (file, ";; total time = %d\n;; new basic block head = %d\n;; new basic block end = %d\n\n",
- clock, INSN_UID (basic_block_head[b]), INSN_UID (basic_block_end[b]));
+ clock, INSN_UID (BLOCK_HEAD (b)), INSN_UID (BLOCK_END (b)));
}
/* Yow! We're done! */
@@ -3556,47 +3535,14 @@ ret:
return;
}
-/* Subroutine of split_hard_reg_notes. Searches X for any reference to
- REGNO, returning the rtx of the reference found if any. Otherwise,
- returns 0. */
-
-static rtx
-regno_use_in (regno, x)
- int regno;
- rtx x;
-{
- register char *fmt;
- int i, j;
- rtx tem;
-
- if (GET_CODE (x) == REG && REGNO (x) == regno)
- return x;
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if ((tem = regno_use_in (regno, XEXP (x, i))))
- return tem;
- }
- else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
- return tem;
- }
-
- return 0;
-}
-
/* Subroutine of update_flow_info. Determines whether any new REG_NOTEs are
needed for the hard register mentioned in the note. This can happen
if the reference to the hard register in the original insn was split into
several smaller hard register references in the split insns. */
static void
-split_hard_reg_notes (note, first, last, orig_insn)
- rtx note, first, last, orig_insn;
+split_hard_reg_notes (note, first, last)
+ rtx note, first, last;
{
rtx reg, temp, link;
int n_regs, i, new_reg;
@@ -3783,7 +3729,7 @@ update_n_sets (x, inc)
the insns from FIRST to LAST inclusive that were created by splitting
ORIG_INSN. NOTES are the original REG_NOTES. */
-static void
+void
update_flow_info (notes, first, last, orig_insn)
rtx notes;
rtx first, last;
@@ -3825,7 +3771,7 @@ update_flow_info (notes, first, last, orig_insn)
&& GET_CODE (temp) == REG
&& REGNO (temp) < FIRST_PSEUDO_REGISTER
&& HARD_REGNO_NREGS (REGNO (temp), GET_MODE (temp)) > 1)
- split_hard_reg_notes (note, first, last, orig_insn);
+ split_hard_reg_notes (note, first, last);
else
{
XEXP (note, 1) = REG_NOTES (insn);
@@ -3851,16 +3797,7 @@ update_flow_info (notes, first, last, orig_insn)
register that was not needed by this instantiation of the
pattern, so we can safely ignore it. */
if (insn == first)
- {
- /* After reload, REG_DEAD notes come sometimes an
- instruction after the register actually dies. */
- if (reload_completed && REG_NOTE_KIND (note) == REG_DEAD)
- {
- XEXP (note, 1) = REG_NOTES (insn);
- REG_NOTES (insn) = note;
- break;
- }
-
+ {
if (REG_NOTE_KIND (note) != REG_UNUSED)
abort ();
@@ -4206,8 +4143,28 @@ update_flow_info (notes, first, last, orig_insn)
}
else if (! found_orig_dest)
{
- /* This should never happen. */
- abort ();
+ int i, regno;
+
+ /* Should never reach here for a pseudo reg. */
+ if (REGNO (orig_dest) >= FIRST_PSEUDO_REGISTER)
+ abort ();
+
+ /* This can happen for a hard register, if the splitter
+ does not bother to emit instructions which would be no-ops.
+ We try to verify that this is the case by checking to see if
+ the original instruction uses all of the registers that it
+ set. This case is OK, because deleting a no-op can not affect
+ REG_DEAD notes on other insns. If this is not the case, then
+ abort. */
+
+ regno = REGNO (orig_dest);
+ for (i = HARD_REGNO_NREGS (regno, GET_MODE (orig_dest)) - 1;
+ i >= 0; i--)
+ if (! refers_to_regno_p (regno + i, regno + i + 1, orig_insn,
+ NULL_PTR))
+ break;
+ if (i >= 0)
+ abort ();
}
}
@@ -4339,7 +4296,7 @@ schedule_insns (dump_file)
determine the correct line number for the first insn of the block. */
for (b = 0; b < n_basic_blocks; b++)
- for (line = basic_block_head[b]; line; line = PREV_INSN (line))
+ for (line = BLOCK_HEAD (b); line; line = PREV_INSN (line))
if (GET_CODE (line) == NOTE && NOTE_LINE_NUMBER (line) > 0)
{
line_note_head[b] = line;
@@ -4362,7 +4319,7 @@ schedule_insns (dump_file)
/* ??? Perhaps it's done to ensure NEXT_TAIL in schedule_block is a
valid insn. */
- insn = basic_block_end[n_basic_blocks-1];
+ insn = BLOCK_END (n_basic_blocks-1);
if (NEXT_INSN (insn) == 0
|| (GET_CODE (insn) != NOTE
&& GET_CODE (insn) != CODE_LABEL
@@ -4370,86 +4327,13 @@ schedule_insns (dump_file)
jump and a BARRIER. */
&& ! (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (NEXT_INSN (insn)) == BARRIER)))
- emit_note_after (NOTE_INSN_DELETED, basic_block_end[n_basic_blocks-1]);
+ emit_note_after (NOTE_INSN_DELETED, BLOCK_END (n_basic_blocks-1));
for (b = 0; b < n_basic_blocks; b++)
{
- rtx insn, next;
-
note_list = 0;
- for (insn = basic_block_head[b]; ; insn = next)
- {
- rtx prev;
- rtx set;
-
- /* Can't use `next_real_insn' because that
- might go across CODE_LABELS and short-out basic blocks. */
- next = NEXT_INSN (insn);
- if (GET_CODE (insn) != INSN)
- {
- if (insn == basic_block_end[b])
- break;
-
- continue;
- }
-
- /* Don't split no-op move insns. These should silently disappear
- later in final. Splitting such insns would break the code
- that handles REG_NO_CONFLICT blocks. */
- set = single_set (insn);
- if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set)))
- {
- if (insn == basic_block_end[b])
- break;
-
- /* Nops get in the way while scheduling, so delete them now if
- register allocation has already been done. It is too risky
- to try to do this before register allocation, and there are
- unlikely to be very many nops then anyways. */
- if (reload_completed)
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
-
- continue;
- }
-
- /* Split insns here to get max fine-grain parallelism. */
- prev = PREV_INSN (insn);
- /* It is probably not worthwhile to try to split again in the
- second pass. However, if flag_schedule_insns is not set,
- the first and only (if any) scheduling pass is after reload. */
- if (reload_completed == 0 || ! flag_schedule_insns)
- {
- rtx last, first = PREV_INSN (insn);
- rtx notes = REG_NOTES (insn);
-
- last = try_split (PATTERN (insn), insn, 1);
- if (last != insn)
- {
- /* try_split returns the NOTE that INSN became. */
- first = NEXT_INSN (first);
- update_flow_info (notes, first, last, insn);
-
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- if (insn == basic_block_head[b])
- basic_block_head[b] = first;
- if (insn == basic_block_end[b])
- {
- basic_block_end[b] = last;
- break;
- }
- }
- }
-
- if (insn == basic_block_end[b])
- break;
- }
+ split_block_insns (b, reload_completed == 0 || ! flag_schedule_insns);
schedule_block (b, dump_file);
diff --git a/contrib/gcc/sdbout.c b/contrib/gcc/sdbout.c
index 62559a9..0aebd83 100644
--- a/contrib/gcc/sdbout.c
+++ b/contrib/gcc/sdbout.c
@@ -59,7 +59,7 @@ AT&T C compiler. From the example below I would conclude the following:
supply usable syms.h include files. Which syms.h file to use is a
target parameter so don't use the native one if we're cross compiling. */
-#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__) && !defined(CROSS_COMPILE)
+#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__) && !defined(__INTERIX) && !defined(CROSS_COMPILE)
#include <syms.h>
/* Use T_INT if we don't have T_VOID. */
#ifndef T_VOID
@@ -338,7 +338,7 @@ void
sdbout_init (asm_file, input_file_name, syms)
FILE *asm_file;
char *input_file_name;
- tree syms;
+ tree syms ATTRIBUTE_UNUSED;
{
#ifdef MIPS_DEBUGGING_INFO
current_file = (struct sdb_file *) xmalloc (sizeof *current_file);
@@ -527,6 +527,7 @@ plain_type_1 (type, level)
{
case VOID_TYPE:
return T_VOID;
+ case BOOLEAN_TYPE:
case INTEGER_TYPE:
{
int size = int_size_in_bytes (type) * BITS_PER_UNIT;
@@ -810,7 +811,7 @@ sdbout_symbol (decl, local)
DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
value = DECL_RTL (decl);
@@ -928,7 +929,12 @@ sdbout_symbol (decl, local)
PUT_SDB_SCL (C_AUTO);
}
- type = build_pointer_type (TREE_TYPE (decl));
+ /* Effectively do build_pointer_type, but don't cache this type,
+ since it might be temporary whereas the type it points to
+ might have been saved for inlining. */
+ /* Don't use REFERENCE_TYPE because dbx can't handle that. */
+ type = make_node (POINTER_TYPE);
+ TREE_TYPE (type) = TREE_TYPE (decl);
}
else if (GET_CODE (value) == MEM
&& ((GET_CODE (XEXP (value, 0)) == PLUS
@@ -1082,10 +1088,18 @@ sdbout_field_types (type)
tree tail;
for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
- if (POINTER_TYPE_P (TREE_TYPE (tail)))
- sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
- else
- sdbout_one_type (TREE_TYPE (tail));
+ /* This condition should match the one for emitting the actual members
+ below. */
+ if (TREE_CODE (tail) == FIELD_DECL
+ && DECL_NAME (tail) != 0
+ && TREE_CODE (DECL_SIZE (tail)) == INTEGER_CST
+ && TREE_CODE (DECL_FIELD_BITPOS (tail)) == INTEGER_CST)
+ {
+ if (POINTER_TYPE_P (TREE_TYPE (tail)))
+ sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
+ else
+ sdbout_one_type (TREE_TYPE (tail));
+ }
}
/* Use this to put out the top level defined record and union types
@@ -1198,34 +1212,41 @@ sdbout_one_type (type)
/* Print out the base class information with fields
named after the types they hold. */
- if (TYPE_BINFO (type)
- && TYPE_BINFO_BASETYPES (type))
- n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
- for (i = 0; i < n_baseclasses; i++)
+ /* This is only relevent to aggregate types. TYPE_BINFO is used
+ for other purposes in an ENUMERAL_TYPE, so we must exclude that
+ case. */
+ if (TREE_CODE (type) != ENUMERAL_TYPE)
{
- tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);
- tree child_type = BINFO_TYPE (child);
- tree child_type_name;
- if (TYPE_NAME (child_type) == 0)
- continue;
- if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
- child_type_name = TYPE_NAME (child_type);
- else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
+ if (TYPE_BINFO (type)
+ && TYPE_BINFO_BASETYPES (type))
+ n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
+ for (i = 0; i < n_baseclasses; i++)
{
- child_type_name = DECL_NAME (TYPE_NAME (child_type));
- if (child_type_name && template_name_p (child_type_name))
- child_type_name
- = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
- }
- else
- continue;
+ tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)),
+ i);
+ tree child_type = BINFO_TYPE (child);
+ tree child_type_name;
+ if (TYPE_NAME (child_type) == 0)
+ continue;
+ if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
+ child_type_name = TYPE_NAME (child_type);
+ else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
+ {
+ child_type_name = DECL_NAME (TYPE_NAME (child_type));
+ if (child_type_name && template_name_p (child_type_name))
+ child_type_name
+ = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
+ }
+ else
+ continue;
- CONTIN;
- PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
- PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child)));
- PUT_SDB_SCL (member_scl);
- sdbout_type (BINFO_TYPE (child));
- PUT_SDB_ENDEF;
+ CONTIN;
+ PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
+ PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child)));
+ PUT_SDB_SCL (member_scl);
+ sdbout_type (BINFO_TYPE (child));
+ PUT_SDB_ENDEF;
+ }
}
/* output the individual fields */
@@ -1545,7 +1566,7 @@ void
sdbout_end_block (file, line, n)
FILE *file;
int line;
- int n;
+ int n ATTRIBUTE_UNUSED;
{
MAKE_LINE_SAFE (line);
diff --git a/contrib/gcc/stab.def b/contrib/gcc/stab.def
index 48ea231..81d442a 100644
--- a/contrib/gcc/stab.def
+++ b/contrib/gcc/stab.def
@@ -1,5 +1,5 @@
/* Table of DBX symbol codes for the GNU system.
- Copyright (C) 1988, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/contrib/gcc/stmt.c b/contrib/gcc/stmt.c
index 8d11a75..018e190 100644
--- a/contrib/gcc/stmt.c
+++ b/contrib/gcc/stmt.c
@@ -1,5 +1,5 @@
/* Expands front end tree to back end RTL for GNU C-Compiler
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -88,45 +88,6 @@ static rtx last_block_end_note;
/* Number of binding contours started so far in this function. */
int block_start_count;
-
-/* Nonzero if function being compiled needs to
- return the address of where it has put a structure value. */
-
-extern int current_function_returns_pcc_struct;
-
-/* Label that will go on parm cleanup code, if any.
- Jumping to this label runs cleanup code for parameters, if
- such code must be run. Following this code is the logical return label. */
-
-extern rtx cleanup_label;
-
-/* Label that will go on function epilogue.
- Jumping to this label serves as a "return" instruction
- on machines which require execution of the epilogue on all returns. */
-
-extern rtx return_label;
-
-/* Offset to end of allocated area of stack frame.
- If stack grows down, this is the address of the last stack slot allocated.
- If stack grows up, this is the address for the next slot. */
-extern int frame_offset;
-
-/* Label to jump back to for tail recursion, or 0 if we have
- not yet needed one for this function. */
-extern rtx tail_recursion_label;
-
-/* Place after which to insert the tail_recursion_label if we need one. */
-extern rtx tail_recursion_reentry;
-
-/* Location at which to save the argument pointer if it will need to be
- referenced. There are two cases where this is done: if nonlocal gotos
- exist, or if vars whose is an offset from the argument pointer will be
- needed by inner routines. */
-
-extern rtx arg_pointer_save_area;
-
-/* Chain of all RTL_EXPRs that have insns in them. */
-extern tree rtl_expr_chain;
/* Functions and data structures for expanding case statements. */
@@ -306,7 +267,7 @@ struct nesting
/* Number of range exprs in case statement. */
int num_ranges;
/* Name of this kind of statement, for warnings. */
- char *printname;
+ const char *printname;
/* Used to save no_line_numbers till we see the first case label.
We set this to -1 when we see the first case label in this
case statement. */
@@ -425,8 +386,12 @@ struct label_chain
static int using_eh_for_cleanups_p = 0;
+static int n_occurrences PROTO((int, const char *));
static void expand_goto_internal PROTO((tree, rtx, rtx));
static int expand_fixup PROTO((tree, rtx, rtx));
+static rtx expand_nl_handler_label PROTO((rtx, rtx));
+static void expand_nl_goto_receiver PROTO((void));
+static void expand_nl_goto_receivers PROTO((struct nesting *));
static void fixup_gotos PROTO((struct nesting *, rtx, tree,
rtx, int));
static void expand_null_return_1 PROTO((rtx, int));
@@ -583,12 +548,14 @@ expand_computed_goto (exp)
emit_queue ();
/* Be sure the function is executable. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_check_exec_libfunc, 1,
VOIDmode, 1, x, ptr_mode);
do_pending_stack_adjust ();
emit_indirect_jump (x);
+
+ current_function_has_computed_jump = 1;
}
/* Handle goto statements and the labels that they can go to. */
@@ -631,16 +598,18 @@ void
declare_nonlocal_label (label)
tree label;
{
+ rtx slot = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
+
nonlocal_labels = tree_cons (NULL_TREE, label, nonlocal_labels);
LABEL_PRESERVE_P (label_rtx (label)) = 1;
- if (nonlocal_goto_handler_slot == 0)
+ if (nonlocal_goto_handler_slots == 0)
{
- nonlocal_goto_handler_slot
- = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
emit_stack_save (SAVE_NONLOCAL,
&nonlocal_goto_stack_level,
PREV_INSN (tail_recursion_reentry));
}
+ nonlocal_goto_handler_slots
+ = gen_rtx_EXPR_LIST (VOIDmode, slot, nonlocal_goto_handler_slots);
}
/* Generate RTL code for a `goto' statement with target label LABEL.
@@ -659,7 +628,15 @@ expand_goto (label)
{
struct function *p = find_function_data (context);
rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label));
- rtx temp;
+ rtx temp, handler_slot;
+ tree link;
+
+ /* Find the corresponding handler slot for this label. */
+ handler_slot = p->nonlocal_goto_handler_slots;
+ for (link = p->nonlocal_labels; TREE_VALUE (link) != label;
+ link = TREE_CHAIN (link))
+ handler_slot = XEXP (handler_slot, 1);
+ handler_slot = XEXP (handler_slot, 0);
p->has_nonlocal_label = 1;
current_function_has_nonlocal_goto = 1;
@@ -672,7 +649,7 @@ expand_goto (label)
#if HAVE_nonlocal_goto
if (HAVE_nonlocal_goto)
emit_insn (gen_nonlocal_goto (lookup_static_chain (label),
- copy_rtx (p->nonlocal_goto_handler_slot),
+ copy_rtx (handler_slot),
copy_rtx (p->nonlocal_goto_stack_level),
label_ref));
else
@@ -694,7 +671,7 @@ expand_goto (label)
/* Get addr of containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */
- addr = copy_rtx (p->nonlocal_goto_handler_slot);
+ addr = copy_rtx (handler_slot);
temp = copy_to_reg (replace_rtx (addr, virtual_stack_vars_rtx,
hard_frame_pointer_rtx));
@@ -707,13 +684,10 @@ expand_goto (label)
emit_stack_restore (SAVE_NONLOCAL, addr, NULL_RTX);
- /* Put in the static chain register the nonlocal label address. */
- emit_move_insn (static_chain_rtx, label_ref);
/* USE of hard_frame_pointer_rtx added for consistency; not clear if
really needed. */
emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
- emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
emit_indirect_jump (temp);
}
}
@@ -1102,8 +1076,18 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
f->stack_level = stack_level;
}
}
-
-
+
+/* Return the number of times character C occurs in string S. */
+static int
+n_occurrences (c, s)
+ int c;
+ const char *s;
+{
+ int n = 0;
+ while (*s)
+ n += (*s++ == c);
+ return n;
+}
/* Generate RTL for an asm statement (explicit assembler code).
BODY is a STRING_CST node containing the assembler code text,
@@ -1113,7 +1097,7 @@ void
expand_asm (body)
tree body;
{
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
{
error ("`asm' cannot be used with `-fcheck-memory-usage'");
return;
@@ -1160,6 +1144,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
/* Vector of RTX's of evaluated output operands. */
rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
int *inout_opnum = (int *) alloca (noutputs * sizeof (int));
+ rtx *real_output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
enum machine_mode *inout_mode
= (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
/* The insn we have emitted. */
@@ -1169,7 +1154,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
if (noutputs == 0)
vol = 1;
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
{
error ("`asm' cannot be used with `-fcheck-memory-usage'");
return;
@@ -1190,14 +1175,47 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
last_expr_type = 0;
+ /* Check that the number of alternatives is constant across all
+ operands. */
+ if (outputs || inputs)
+ {
+ tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
+ int nalternatives = n_occurrences (',', TREE_STRING_POINTER (tmp));
+ tree next = inputs;
+
+ if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
+ {
+ error ("too many alternatives in `asm'");
+ return;
+ }
+
+ tmp = outputs;
+ while (tmp)
+ {
+ char *constraint = TREE_STRING_POINTER (TREE_PURPOSE (tmp));
+ if (n_occurrences (',', constraint) != nalternatives)
+ {
+ error ("operand constraints for `asm' differ in number of alternatives");
+ return;
+ }
+ if (TREE_CHAIN (tmp))
+ tmp = TREE_CHAIN (tmp);
+ else
+ tmp = next, next = 0;
+ }
+ }
+
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
{
tree val = TREE_VALUE (tail);
tree type = TREE_TYPE (val);
+ char *constraint;
+ char *p;
+ int c_len;
int j;
- int found_equal = 0;
- int found_plus = 0;
+ int is_inout = 0;
int allows_reg = 0;
+ int allows_mem = 0;
/* If there's an erroneous arg, emit no insn. */
if (TREE_TYPE (val) == error_mark_node)
@@ -1208,29 +1226,62 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
the worst that happens if we get it wrong is we issue an error
message. */
- for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
- switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
+ c_len = TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1;
+ constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+
+ /* Allow the `=' or `+' to not be at the beginning of the string,
+ since it wasn't explicitly documented that way, and there is a
+ large body of code that puts it last. Swap the character to
+ the front, so as not to uglify any place else. */
+ switch (c_len)
+ {
+ default:
+ if ((p = strchr (constraint, '=')) != NULL)
+ break;
+ if ((p = strchr (constraint, '+')) != NULL)
+ break;
+ case 0:
+ error ("output operand constraint lacks `='");
+ return;
+ }
+
+ if (p != constraint)
+ {
+ j = *p;
+ bcopy (constraint, constraint+1, p-constraint);
+ *constraint = j;
+
+ warning ("output constraint `%c' for operand %d is not at the beginning", j, i);
+ }
+
+ is_inout = constraint[0] == '+';
+ /* Replace '+' with '='. */
+ constraint[0] = '=';
+ /* Make sure we can specify the matching operand. */
+ if (is_inout && i > 9)
+ {
+ error ("output operand constraint %d contains `+'", i);
+ return;
+ }
+
+ for (j = 1; j < c_len; j++)
+ switch (constraint[j])
{
case '+':
- /* Make sure we can specify the matching operand. */
- if (i > 9)
+ case '=':
+ error ("operand constraint contains '+' or '=' at illegal position.");
+ return;
+
+ case '%':
+ if (i + 1 == ninputs + noutputs)
{
- error ("output operand constraint %d contains `+'", i);
+ error ("`%%' constraint used with last operand");
return;
}
-
- /* Replace '+' with '='. */
- TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] = '=';
- found_plus = 1;
break;
- case '=':
- found_equal = 1;
- break;
-
- case '?': case '!': case '*': case '%': case '&':
- case 'V': case 'm': case 'o': case '<': case '>':
- case 'E': case 'F': case 'G': case 'H': case 'X':
+ case '?': case '!': case '*': case '&':
+ case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L': case 'M':
case 'N': case 'O': case 'P': case ',':
@@ -1244,29 +1295,42 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
error ("matching constraint not valid in output operand");
break;
- case 'p': case 'g': case 'r':
+ case 'V': case 'm': case 'o':
+ allows_mem = 1;
+ break;
+
+ case '<': case '>':
+ /* ??? Before flow, auto inc/dec insns are not supposed to exist,
+ excepting those that expand_call created. So match memory
+ and hope. */
+ allows_mem = 1;
+ break;
+
+ case 'g': case 'X':
+ allows_reg = 1;
+ allows_mem = 1;
+ break;
+
+ case 'p': case 'r':
default:
allows_reg = 1;
break;
}
- if (! found_equal && ! found_plus)
- {
- error ("output operand constraint lacks `='");
- return;
- }
-
/* If an output operand is not a decl or indirect ref and our constraint
allows a register, make a temporary to act as an intermediate.
Make the asm insn write into that, then our caller will copy it to
the real output operand. Likewise for promoted variables. */
- if (TREE_CODE (val) == INDIRECT_REF
+ real_output_rtx[i] = NULL_RTX;
+ if ((TREE_CODE (val) == INDIRECT_REF
+ && allows_mem)
|| (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
+ && (allows_mem || GET_CODE (DECL_RTL (val)) == REG)
&& ! (GET_CODE (DECL_RTL (val)) == REG
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
|| ! allows_reg
- || found_plus)
+ || is_inout)
{
if (! allows_reg)
mark_addressable (TREE_VALUE (tail));
@@ -1277,6 +1341,13 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
error ("output number %d not directly addressable", i);
+ if (! allows_mem && GET_CODE (output_rtx[i]) == MEM)
+ {
+ real_output_rtx[i] = protect_from_queue (output_rtx[i], 1);
+ output_rtx[i] = gen_reg_rtx (GET_MODE (output_rtx[i]));
+ if (is_inout)
+ emit_move_insn (output_rtx[i], real_output_rtx[i]);
+ }
}
else
{
@@ -1284,7 +1355,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
TREE_VALUE (tail) = make_tree (type, output_rtx[i]);
}
- if (found_plus)
+ if (is_inout)
{
inout_mode[ninout] = TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)));
inout_opnum[ninout++] = i;
@@ -1316,13 +1387,18 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
for (tail = inputs; tail; tail = TREE_CHAIN (tail))
{
int j;
- int allows_reg = 0;
+ int allows_reg = 0, allows_mem = 0;
+ char *constraint, *orig_constraint;
+ int c_len;
+ rtx op;
/* If there's an erroneous arg, emit no insn,
because the ASM_INPUT would get VOIDmode
and that could cause a crash in reload. */
if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
return;
+
+ /* ??? Can this happen, and does the error message make any sense? */
if (TREE_PURPOSE (tail) == NULL_TREE)
{
error ("hard register `%s' listed as input operand to `asm'",
@@ -1330,18 +1406,38 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
return;
}
- /* Make sure constraint has neither `=' nor `+'. */
+ c_len = TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1;
+ constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+ orig_constraint = constraint;
+
+ /* Make sure constraint has neither `=', `+', nor '&'. */
- for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
- switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
+ for (j = 0; j < c_len; j++)
+ switch (constraint[j])
{
- case '+': case '=':
- error ("input operand constraint contains `%c'",
- TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);
- return;
+ case '+': case '=': case '&':
+ if (constraint == orig_constraint)
+ {
+ error ("input operand constraint contains `%c'", constraint[j]);
+ return;
+ }
+ break;
- case '?': case '!': case '*': case '%': case '&':
- case 'V': case 'm': case 'o': case '<': case '>':
+ case '%':
+ if (constraint == orig_constraint
+ && i + 1 == ninputs - ninout)
+ {
+ error ("`%%' constraint used with last operand");
+ return;
+ }
+ break;
+
+ case 'V': case 'm': case 'o':
+ allows_mem = 1;
+ break;
+
+ case '<': case '>':
+ case '?': case '!': case '*':
case 'E': case 'F': case 'G': case 'H': case 'X':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L': case 'M':
@@ -1358,56 +1454,81 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
operands to memory. */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]
- >= '0' + noutputs)
+ if (constraint[j] >= '0' + noutputs)
{
error
("matching constraint references invalid operand number");
return;
}
+ /* Try and find the real constraint for this dup. */
+ if ((j == 0 && c_len == 1)
+ || (j == 1 && c_len == 2 && constraint[0] == '%'))
+ {
+ tree o = outputs;
+ for (j = constraint[j] - '0'; j > 0; --j)
+ o = TREE_CHAIN (o);
+
+ c_len = TREE_STRING_LENGTH (TREE_PURPOSE (o)) - 1;
+ constraint = TREE_STRING_POINTER (TREE_PURPOSE (o));
+ j = 0;
+ break;
+ }
+
/* ... fall through ... */
- case 'p': case 'g': case 'r':
+ case 'p': case 'r':
default:
allows_reg = 1;
break;
+
+ case 'g':
+ allows_reg = 1;
+ allows_mem = 1;
+ break;
}
- if (! allows_reg)
+ if (! allows_reg && allows_mem)
mark_addressable (TREE_VALUE (tail));
- XVECEXP (body, 3, i) /* argvec */
- = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
- if (CONSTANT_P (XVECEXP (body, 3, i))
- && ! general_operand (XVECEXP (body, 3, i),
- TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)))))
+ op = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
+
+ if (asm_operand_ok (op, constraint) <= 0)
{
if (allows_reg)
- XVECEXP (body, 3, i)
- = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- XVECEXP (body, 3, i));
+ op = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), op);
+ else if (!allows_mem)
+ warning ("asm operand %d probably doesn't match constraints", i);
+ else if (CONSTANT_P (op))
+ op = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
+ op);
+ else if (GET_CODE (op) == REG
+ || GET_CODE (op) == SUBREG
+ || GET_CODE (op) == CONCAT)
+ {
+ tree type = TREE_TYPE (TREE_VALUE (tail));
+ rtx memloc = assign_temp (type, 1, 1, 1);
+
+ emit_move_insn (memloc, op);
+ op = memloc;
+ }
+ else if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op))
+ /* We won't recognize volatile memory as available a
+ memory_operand at this point. Ignore it. */
+ ;
+ else if (queued_subexp_p (op))
+ ;
else
- XVECEXP (body, 3, i)
- = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- XVECEXP (body, 3, i));
+ /* ??? Leave this only until we have experience with what
+ happens in combine and elsewhere when constraints are
+ not satisfied. */
+ warning ("asm operand %d probably doesn't match constraints", i);
}
+ XVECEXP (body, 3, i) = op;
- if (! allows_reg
- && (GET_CODE (XVECEXP (body, 3, i)) == REG
- || GET_CODE (XVECEXP (body, 3, i)) == SUBREG
- || GET_CODE (XVECEXP (body, 3, i)) == CONCAT))
- {
- tree type = TREE_TYPE (TREE_VALUE (tail));
- rtx memloc = assign_temp (type, 1, 1, 1);
-
- emit_move_insn (memloc, XVECEXP (body, 3, i));
- XVECEXP (body, 3, i) = memloc;
- }
-
XVECEXP (body, 4, i) /* constraints */
= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
- TREE_STRING_POINTER (TREE_PURPOSE (tail)));
+ orig_constraint);
i++;
}
@@ -1509,6 +1630,12 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
insn = emit_insn (body);
}
+ /* For any outputs that needed reloading into registers, spill them
+ back to where they belong. */
+ for (i = 0; i < noutputs; ++i)
+ if (real_output_rtx[i])
+ emit_move_insn (real_output_rtx[i], output_rtx[i]);
+
free_temp_slots ();
}
@@ -1539,13 +1666,10 @@ expand_expr_stmt (exp)
exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
last_expr_type = TREE_TYPE (exp);
- if (flag_syntax_only && ! expr_stmts_for_value)
- last_expr_value = 0;
- else
- last_expr_value = expand_expr (exp,
- (expr_stmts_for_value
- ? NULL_RTX : const0_rtx),
- VOIDmode, 0);
+ last_expr_value = expand_expr (exp,
+ (expr_stmts_for_value
+ ? NULL_RTX : const0_rtx),
+ VOIDmode, 0);
/* If all we do is reference a volatile value in memory,
copy it to a register to be sure it is actually touched. */
@@ -1561,12 +1685,12 @@ expand_expr_stmt (exp)
rtx lab = gen_label_rtx ();
/* Compare the value with itself to reference it. */
- emit_cmp_insn (last_expr_value, last_expr_value, EQ,
- expand_expr (TYPE_SIZE (last_expr_type),
- NULL_RTX, VOIDmode, 0),
- BLKmode, 0,
- TYPE_ALIGN (last_expr_type) / BITS_PER_UNIT);
- emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (lab));
+ emit_cmp_and_jump_insns (last_expr_value, last_expr_value, EQ,
+ expand_expr (TYPE_SIZE (last_expr_type),
+ NULL_RTX, VOIDmode, 0),
+ BLKmode, 0,
+ TYPE_ALIGN (last_expr_type) / BITS_PER_UNIT,
+ lab);
emit_label (lab);
}
}
@@ -1917,13 +2041,9 @@ expand_loop_continue_here ()
void
expand_end_loop ()
{
- register rtx insn;
- register rtx start_label;
- rtx last_test_insn = 0;
- int num_insns = 0;
-
- insn = get_last_insn ();
- start_label = loop_stack->data.loop.start_label;
+ rtx start_label = loop_stack->data.loop.start_label;
+ rtx insn = get_last_insn ();
+ int needs_end_jump = 1;
/* Mark the continue-point at the top of the loop if none elsewhere. */
if (start_label == loop_stack->data.loop.continue_label)
@@ -1931,9 +2051,77 @@ expand_end_loop ()
do_pending_stack_adjust ();
- /* If optimizing, perhaps reorder the loop. If the loop starts with
- a loop exit, roll that to the end where it will optimize together
- with the jump back.
+ /* If optimizing, perhaps reorder the loop.
+ First, try to use a condjump near the end.
+ expand_exit_loop_if_false ends loops with unconditional jumps,
+ like this:
+
+ if (test) goto label;
+ optional: cleanup
+ goto loop_stack->data.loop.end_label
+ barrier
+ label:
+
+ If we find such a pattern, we can end the loop earlier. */
+
+ if (optimize
+ && GET_CODE (insn) == CODE_LABEL
+ && LABEL_NAME (insn) == NULL
+ && GET_CODE (PREV_INSN (insn)) == BARRIER)
+ {
+ rtx label = insn;
+ rtx jump = PREV_INSN (PREV_INSN (label));
+
+ if (GET_CODE (jump) == JUMP_INSN
+ && GET_CODE (PATTERN (jump)) == SET
+ && SET_DEST (PATTERN (jump)) == pc_rtx
+ && GET_CODE (SET_SRC (PATTERN (jump))) == LABEL_REF
+ && (XEXP (SET_SRC (PATTERN (jump)), 0)
+ == loop_stack->data.loop.end_label))
+ {
+ rtx prev;
+
+ /* The test might be complex and reference LABEL multiple times,
+ like the loop in loop_iterations to set vtop. To handle this,
+ we move LABEL. */
+ insn = PREV_INSN (label);
+ reorder_insns (label, label, start_label);
+
+ for (prev = PREV_INSN (jump); ; prev = PREV_INSN (prev))
+ {
+ /* We ignore line number notes, but if we see any other note,
+ in particular NOTE_INSN_BLOCK_*, NOTE_INSN_EH_REGION_*,
+ NOTE_INSN_LOOP_*, we disable this optimization. */
+ if (GET_CODE (prev) == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (prev) < 0)
+ break;
+ continue;
+ }
+ if (GET_CODE (prev) == CODE_LABEL)
+ break;
+ if (GET_CODE (prev) == JUMP_INSN)
+ {
+ if (GET_CODE (PATTERN (prev)) == SET
+ && SET_DEST (PATTERN (prev)) == pc_rtx
+ && GET_CODE (SET_SRC (PATTERN (prev))) == IF_THEN_ELSE
+ && (GET_CODE (XEXP (SET_SRC (PATTERN (prev)), 1))
+ == LABEL_REF)
+ && XEXP (XEXP (SET_SRC (PATTERN (prev)), 1), 0) == label)
+ {
+ XEXP (XEXP (SET_SRC (PATTERN (prev)), 1), 0)
+ = start_label;
+ emit_note_after (NOTE_INSN_LOOP_END, prev);
+ needs_end_jump = 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /* If the loop starts with a loop exit, roll that to the end where
+ it will optimize together with the jump back.
We look for the conditional branch to the exit, except that once
we find such a branch, we don't look past 30 instructions.
@@ -1944,7 +2132,7 @@ expand_end_loop ()
if (test) goto end_label;
body;
goto start_label;
- end_label;
+ end_label:
transform it to look like:
@@ -1954,11 +2142,13 @@ expand_end_loop ()
start_label:
if (test) goto end_label;
goto newstart_label;
- end_label;
+ end_label:
Here, the `test' may actually consist of some reasonably complex
code, terminating in a test. */
+
if (optimize
+ && needs_end_jump
&&
! (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (PATTERN (insn)) == SET
@@ -1966,6 +2156,8 @@ expand_end_loop ()
&& GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE))
{
int eh_regions = 0;
+ int num_insns = 0;
+ rtx last_test_insn = NULL_RTX;
/* Scan insns from the top of the loop looking for a qualified
conditional exit. */
@@ -2001,6 +2193,10 @@ expand_end_loop ()
abort ();
}
+ /* We must not walk into a nested loop. */
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+ break;
+
/* We already know this INSN is a NOTE, so there's no
point in looking at it to see if it's a JUMP. */
continue;
@@ -2042,31 +2238,46 @@ expand_end_loop ()
So we don't look for tests within an EH region. */
continue;
- if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET
- && SET_DEST (PATTERN (insn)) == pc_rtx
- && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE
- && ((GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == LABEL_REF
- && ((XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0)
- == loop_stack->data.loop.end_label)
- || (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0)
- == loop_stack->data.loop.alt_end_label)))
- || (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 2)) == LABEL_REF
- && ((XEXP (XEXP (SET_SRC (PATTERN (insn)), 2), 0)
- == loop_stack->data.loop.end_label)
- || (XEXP (XEXP (SET_SRC (PATTERN (insn)), 2), 0)
- == loop_stack->data.loop.alt_end_label)))))
- last_test_insn = insn;
-
- if (last_test_insn == 0 && GET_CODE (insn) == JUMP_INSN
+ if (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (PATTERN (insn)) == SET
- && SET_DEST (PATTERN (insn)) == pc_rtx
- && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF
- && ((XEXP (SET_SRC (PATTERN (insn)), 0)
- == loop_stack->data.loop.end_label)
- || (XEXP (SET_SRC (PATTERN (insn)), 0)
- == loop_stack->data.loop.alt_end_label)))
- /* Include BARRIER. */
- last_test_insn = NEXT_INSN (insn);
+ && SET_DEST (PATTERN (insn)) == pc_rtx)
+ {
+ /* This is indeed a jump. */
+ rtx dest1 = NULL_RTX;
+ rtx dest2 = NULL_RTX;
+ rtx potential_last_test;
+ if (GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
+ {
+ /* A conditional jump. */
+ dest1 = XEXP (SET_SRC (PATTERN (insn)), 1);
+ dest2 = XEXP (SET_SRC (PATTERN (insn)), 2);
+ potential_last_test = insn;
+ }
+ else
+ {
+ /* An unconditional jump. */
+ dest1 = SET_SRC (PATTERN (insn));
+ /* Include the BARRIER after the JUMP. */
+ potential_last_test = NEXT_INSN (insn);
+ }
+
+ do {
+ if (dest1 && GET_CODE (dest1) == LABEL_REF
+ && ((XEXP (dest1, 0)
+ == loop_stack->data.loop.alt_end_label)
+ || (XEXP (dest1, 0)
+ == loop_stack->data.loop.end_label)))
+ {
+ last_test_insn = potential_last_test;
+ break;
+ }
+
+ /* If this was a conditional jump, there may be
+ another label at which we should look. */
+ dest1 = dest2;
+ dest2 = NULL_RTX;
+ } while (dest1);
+ }
}
if (last_test_insn != 0 && last_test_insn != get_last_insn ())
@@ -2125,8 +2336,11 @@ expand_end_loop ()
}
}
- emit_jump (start_label);
- emit_note (NULL_PTR, NOTE_INSN_LOOP_END);
+ if (needs_end_jump)
+ {
+ emit_jump (start_label);
+ emit_note (NULL_PTR, NOTE_INSN_LOOP_END);
+ }
emit_label (loop_stack->data.loop.end_label);
POPSTACK (loop_stack);
@@ -2202,6 +2416,14 @@ expand_exit_loop_if_false (whichloop, cond)
return 1;
}
+/* Return nonzero if the loop nest is empty. Else return zero. */
+
+int
+stmt_loop_nest_empty ()
+{
+ return (loop_stack == NULL);
+}
+
/* Return non-zero if we should preserve sub-expressions as separate
pseudos. We never do so if we aren't optimizing. We always do so
if -fexpensive-optimizations.
@@ -2442,6 +2664,7 @@ expand_return (retval)
tree expr;
do_jump (TREE_OPERAND (retval_rhs, 0), label, NULL_RTX);
+ start_cleanup_deferral ();
expr = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (current_function_decl)),
DECL_RESULT (current_function_decl),
TREE_OPERAND (retval_rhs, 1));
@@ -2454,35 +2677,14 @@ expand_return (retval)
TREE_OPERAND (retval_rhs, 2));
TREE_SIDE_EFFECTS (expr) = 1;
expand_return (expr);
+ end_cleanup_deferral ();
return;
}
- /* For tail-recursive call to current function,
- just jump back to the beginning.
- It's unsafe if any auto variable in this function
- has its address taken; for simplicity,
- require stack frame to be empty. */
- if (optimize && retval_rhs != 0
- && frame_offset == 0
- && TREE_CODE (retval_rhs) == CALL_EXPR
- && TREE_CODE (TREE_OPERAND (retval_rhs, 0)) == ADDR_EXPR
- && TREE_OPERAND (TREE_OPERAND (retval_rhs, 0), 0) == current_function_decl
- /* Finish checking validity, and if valid emit code
- to set the argument variables for the new call. */
- && tail_recursion_args (TREE_OPERAND (retval_rhs, 1),
- DECL_ARGUMENTS (current_function_decl)))
- {
- if (tail_recursion_label == 0)
- {
- tail_recursion_label = gen_label_rtx ();
- emit_label_after (tail_recursion_label,
- tail_recursion_reentry);
- }
- emit_queue ();
- expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn);
- emit_barrier ();
- return;
- }
+ /* Attempt to optimize the call if it is tail recursive. */
+ if (optimize_tail_recursion (retval_rhs, last_insn))
+ return;
+
#ifdef HAVE_return
/* This optimization is safe if there are local cleanups
because expand_null_return takes care of them.
@@ -2564,7 +2766,8 @@ expand_return (retval)
int big_endian_correction = 0;
int bytes = int_size_in_bytes (TREE_TYPE (retval_rhs));
int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
- int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)),BITS_PER_WORD);
+ int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)),
+ (unsigned int)BITS_PER_WORD);
rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
@@ -2686,6 +2889,49 @@ drop_through_at_end_p ()
return insn && GET_CODE (insn) != BARRIER;
}
+/* Test CALL_EXPR to determine if it is a potential tail recursion call
+ and emit code to optimize the tail recursion. LAST_INSN indicates where
+ to place the jump to the tail recursion label. Return TRUE if the
+ call was optimized into a goto.
+
+ This is only used by expand_return, but expand_call is expected to
+ use it soon. */
+
+int
+optimize_tail_recursion (call_expr, last_insn)
+ tree call_expr;
+ rtx last_insn;
+{
+ /* For tail-recursive call to current function,
+ just jump back to the beginning.
+ It's unsafe if any auto variable in this function
+ has its address taken; for simplicity,
+ require stack frame to be empty. */
+ if (optimize && call_expr != 0
+ && frame_offset == 0
+ && TREE_CODE (call_expr) == CALL_EXPR
+ && TREE_CODE (TREE_OPERAND (call_expr, 0)) == ADDR_EXPR
+ && TREE_OPERAND (TREE_OPERAND (call_expr, 0), 0) == current_function_decl
+ /* Finish checking validity, and if valid emit code
+ to set the argument variables for the new call. */
+ && tail_recursion_args (TREE_OPERAND (call_expr, 1),
+ DECL_ARGUMENTS (current_function_decl)))
+ {
+ if (tail_recursion_label == 0)
+ {
+ tail_recursion_label = gen_label_rtx ();
+ emit_label_after (tail_recursion_label,
+ tail_recursion_reentry);
+ }
+ emit_queue ();
+ expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn);
+ emit_barrier ();
+ return 1;
+ }
+
+ return 0;
+}
+
/* Emit code to alter this function's formal parms for a tail-recursive call.
ACTUALS is a list of actual parameter expressions (chain of TREE_LISTs).
FORMALS is the chain of decls of formals.
@@ -2900,9 +3146,177 @@ remember_end_note (block)
last_block_end_note = NULL_RTX;
}
+/* Emit a handler label for a nonlocal goto handler.
+ Also emit code to store the handler label in SLOT before BEFORE_INSN. */
+
+static rtx
+expand_nl_handler_label (slot, before_insn)
+ rtx slot, before_insn;
+{
+ rtx insns;
+ rtx handler_label = gen_label_rtx ();
+
+ /* Don't let jump_optimize delete the handler. */
+ LABEL_PRESERVE_P (handler_label) = 1;
+
+ start_sequence ();
+ emit_move_insn (slot, gen_rtx_LABEL_REF (Pmode, handler_label));
+ insns = get_insns ();
+ end_sequence ();
+ emit_insns_before (insns, before_insn);
+
+ emit_label (handler_label);
+
+ return handler_label;
+}
+
+/* Emit code to restore vital registers at the beginning of a nonlocal goto
+ handler. */
+static void
+expand_nl_goto_receiver ()
+{
+#ifdef HAVE_nonlocal_goto
+ if (! HAVE_nonlocal_goto)
+#endif
+ /* First adjust our frame pointer to its actual value. It was
+ previously set to the start of the virtual area corresponding to
+ the stacked variables when we branched here and now needs to be
+ adjusted to the actual hardware fp value.
+
+ Assignments are to virtual registers are converted by
+ instantiate_virtual_regs into the corresponding assignment
+ to the underlying register (fp in this case) that makes
+ the original assignment true.
+ So the following insn will actually be
+ decrementing fp by STARTING_FRAME_OFFSET. */
+ emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
+
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ if (fixed_regs[ARG_POINTER_REGNUM])
+ {
+#ifdef ELIMINABLE_REGS
+ /* If the argument pointer can be eliminated in favor of the
+ frame pointer, we don't need to restore it. We assume here
+ that if such an elimination is present, it can always be used.
+ This is the case on all known machines; if we don't make this
+ assumption, we do unnecessary saving on many machines. */
+ static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
+ size_t i;
+
+ for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
+ if (elim_regs[i].from == ARG_POINTER_REGNUM
+ && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
+ break;
+
+ if (i == sizeof elim_regs / sizeof elim_regs [0])
+#endif
+ {
+ /* Now restore our arg pointer from the address at which it
+ was saved in our stack frame.
+ If there hasn't be space allocated for it yet, make
+ some now. */
+ if (arg_pointer_save_area == 0)
+ arg_pointer_save_area
+ = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
+ emit_move_insn (virtual_incoming_args_rtx,
+ /* We need a pseudo here, or else
+ instantiate_virtual_regs_1 complains. */
+ copy_to_reg (arg_pointer_save_area));
+ }
+ }
+#endif
+
+#ifdef HAVE_nonlocal_goto_receiver
+ if (HAVE_nonlocal_goto_receiver)
+ emit_insn (gen_nonlocal_goto_receiver ());
+#endif
+}
+
+/* Make handlers for nonlocal gotos taking place in the function calls in
+ block THISBLOCK. */
+
+static void
+expand_nl_goto_receivers (thisblock)
+ struct nesting *thisblock;
+{
+ tree link;
+ rtx afterward = gen_label_rtx ();
+ rtx insns, slot;
+ rtx label_list;
+ int any_invalid;
+
+ /* Record the handler address in the stack slot for that purpose,
+ during this block, saving and restoring the outer value. */
+ if (thisblock->next != 0)
+ for (slot = nonlocal_goto_handler_slots; slot; slot = XEXP (slot, 1))
+ {
+ rtx save_receiver = gen_reg_rtx (Pmode);
+ emit_move_insn (XEXP (slot, 0), save_receiver);
+
+ start_sequence ();
+ emit_move_insn (save_receiver, XEXP (slot, 0));
+ insns = get_insns ();
+ end_sequence ();
+ emit_insns_before (insns, thisblock->data.block.first_insn);
+ }
+
+ /* Jump around the handlers; they run only when specially invoked. */
+ emit_jump (afterward);
+
+ /* Make a separate handler for each label. */
+ link = nonlocal_labels;
+ slot = nonlocal_goto_handler_slots;
+ label_list = NULL_RTX;
+ for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
+ /* Skip any labels we shouldn't be able to jump to from here,
+ we generate one special handler for all of them below which just calls
+ abort. */
+ if (! DECL_TOO_LATE (TREE_VALUE (link)))
+ {
+ rtx lab;
+ lab = expand_nl_handler_label (XEXP (slot, 0),
+ thisblock->data.block.first_insn);
+ label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
+
+ expand_nl_goto_receiver ();
+
+ /* Jump to the "real" nonlocal label. */
+ expand_goto (TREE_VALUE (link));
+ }
+
+ /* A second pass over all nonlocal labels; this time we handle those
+ we should not be able to jump to at this point. */
+ link = nonlocal_labels;
+ slot = nonlocal_goto_handler_slots;
+ any_invalid = 0;
+ for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
+ if (DECL_TOO_LATE (TREE_VALUE (link)))
+ {
+ rtx lab;
+ lab = expand_nl_handler_label (XEXP (slot, 0),
+ thisblock->data.block.first_insn);
+ label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
+ any_invalid = 1;
+ }
+
+ if (any_invalid)
+ {
+ expand_nl_goto_receiver ();
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "abort"), 0,
+ VOIDmode, 0);
+ emit_barrier ();
+ }
+
+ nonlocal_goto_handler_labels = label_list;
+ emit_label (afterward);
+}
+
/* Generate RTL code to terminate a binding contour.
- VARS is the chain of VAR_DECL nodes
- for the variables bound in this contour.
+
+ VARS is the chain of VAR_DECL nodes for the variables bound in this
+ contour. There may actually be other nodes in this chain, but any
+ nodes other than VAR_DECLS are ignored.
+
MARK_ENDS is nonzero if we should put a note at the beginning
and end of this binding contour.
@@ -2939,7 +3353,8 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
if (warn_unused)
for (decl = vars; decl; decl = TREE_CHAIN (decl))
- if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL
+ if (TREE_CODE (decl) == VAR_DECL
+ && ! TREE_USED (decl)
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
warning_with_decl (decl, "unused variable `%s'");
@@ -2950,7 +3365,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
emit_label (thisblock->exit_label);
}
- /* If necessary, make a handler for nonlocal gotos taking
+ /* If necessary, make handlers for nonlocal gotos taking
place in the function calls in this block. */
if (function_call_count != thisblock->data.block.function_call_count
&& nonlocal_labels
@@ -2961,119 +3376,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
special to do when you jump out of it. */
: (thisblock->data.block.cleanups != 0
|| thisblock->data.block.stack_level != 0)))
- {
- tree link;
- rtx afterward = gen_label_rtx ();
- rtx handler_label = gen_label_rtx ();
- rtx save_receiver = gen_reg_rtx (Pmode);
- rtx insns;
-
- /* Don't let jump_optimize delete the handler. */
- LABEL_PRESERVE_P (handler_label) = 1;
-
- /* Record the handler address in the stack slot for that purpose,
- during this block, saving and restoring the outer value. */
- if (thisblock->next != 0)
- {
- emit_move_insn (nonlocal_goto_handler_slot, save_receiver);
-
- start_sequence ();
- emit_move_insn (save_receiver, nonlocal_goto_handler_slot);
- insns = get_insns ();
- end_sequence ();
- emit_insns_before (insns, thisblock->data.block.first_insn);
- }
-
- start_sequence ();
- emit_move_insn (nonlocal_goto_handler_slot,
- gen_rtx_LABEL_REF (Pmode, handler_label));
- insns = get_insns ();
- end_sequence ();
- emit_insns_before (insns, thisblock->data.block.first_insn);
-
- /* Jump around the handler; it runs only when specially invoked. */
- emit_jump (afterward);
- emit_label (handler_label);
-
-#ifdef HAVE_nonlocal_goto
- if (! HAVE_nonlocal_goto)
-#endif
- /* First adjust our frame pointer to its actual value. It was
- previously set to the start of the virtual area corresponding to
- the stacked variables when we branched here and now needs to be
- adjusted to the actual hardware fp value.
-
- Assignments are to virtual registers are converted by
- instantiate_virtual_regs into the corresponding assignment
- to the underlying register (fp in this case) that makes
- the original assignment true.
- So the following insn will actually be
- decrementing fp by STARTING_FRAME_OFFSET. */
- emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
-
-#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- if (fixed_regs[ARG_POINTER_REGNUM])
- {
-#ifdef ELIMINABLE_REGS
- /* If the argument pointer can be eliminated in favor of the
- frame pointer, we don't need to restore it. We assume here
- that if such an elimination is present, it can always be used.
- This is the case on all known machines; if we don't make this
- assumption, we do unnecessary saving on many machines. */
- static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
- size_t i;
-
- for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
- if (elim_regs[i].from == ARG_POINTER_REGNUM
- && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
- break;
-
- if (i == sizeof elim_regs / sizeof elim_regs [0])
-#endif
- {
- /* Now restore our arg pointer from the address at which it
- was saved in our stack frame.
- If there hasn't be space allocated for it yet, make
- some now. */
- if (arg_pointer_save_area == 0)
- arg_pointer_save_area
- = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
- emit_move_insn (virtual_incoming_args_rtx,
- /* We need a pseudo here, or else
- instantiate_virtual_regs_1 complains. */
- copy_to_reg (arg_pointer_save_area));
- }
- }
-#endif
-
-#ifdef HAVE_nonlocal_goto_receiver
- if (HAVE_nonlocal_goto_receiver)
- emit_insn (gen_nonlocal_goto_receiver ());
-#endif
-
- /* The handler expects the desired label address in the static chain
- register. It tests the address and does an appropriate jump
- to whatever label is desired. */
- for (link = nonlocal_labels; link; link = TREE_CHAIN (link))
- /* Skip any labels we shouldn't be able to jump to from here. */
- if (! DECL_TOO_LATE (TREE_VALUE (link)))
- {
- rtx not_this = gen_label_rtx ();
- rtx this = gen_label_rtx ();
- do_jump_if_equal (static_chain_rtx,
- gen_rtx_LABEL_REF (Pmode, DECL_RTL (TREE_VALUE (link))),
- this, 0);
- emit_jump (not_this);
- emit_label (this);
- expand_goto (TREE_VALUE (link));
- emit_label (not_this);
- }
- /* If label is not recognized, abort. */
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "abort"), 0,
- VOIDmode, 0);
- emit_barrier ();
- emit_label (afterward);
- }
+ expand_nl_goto_receivers (thisblock);
/* Don't allow jumping into a block that has a stack level.
Cleanups are allowed, though. */
@@ -3127,7 +3430,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
{
emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
thisblock->data.block.stack_level, NULL_RTX);
- if (nonlocal_goto_handler_slot != 0)
+ if (nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level,
NULL_RTX);
}
@@ -3157,11 +3460,8 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
if (obey_regdecls)
for (decl = vars; decl; decl = TREE_CHAIN (decl))
- {
- rtx rtl = DECL_RTL (decl);
- if (TREE_CODE (decl) == VAR_DECL && rtl != 0)
- use_variable (rtl);
- }
+ if (TREE_CODE (decl) == VAR_DECL && DECL_RTL (decl))
+ use_variable (DECL_RTL (decl));
/* Restore the temporary level of TARGET_EXPRs. */
target_temp_slot_level = thisblock->data.block.target_temp_slot_level;
@@ -3174,8 +3474,6 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
/* Pop the stack slot nesting and free any slots at this level. */
pop_temp_slots ();
}
-
-
/* Generate RTL for the automatic variable declaration DECL.
(Other kinds of declarations are simply ignored if seen here.) */
@@ -3214,7 +3512,7 @@ expand_decl (decl)
/* An initializer is going to decide the size of this array.
Until we know the size, represent its address with a reg. */
DECL_RTL (decl) = gen_rtx_MEM (BLKmode, gen_reg_rtx (Pmode));
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (type);
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl), AGGREGATE_TYPE_P (type));
}
else if (DECL_MODE (decl) != BLKmode
/* If -ffloat-store, don't put explicit float vars
@@ -3225,7 +3523,7 @@ expand_decl (decl)
&& ! TREE_ADDRESSABLE (decl)
&& (DECL_REGISTER (decl) || ! obey_regdecls)
/* if -fcheck-memory-usage, check all variables. */
- && ! flag_check_memory_usage)
+ && ! current_function_check_memory_usage)
{
/* Automatic variable that can go in a register. */
int unsignedp = TREE_UNSIGNED (type);
@@ -3263,13 +3561,9 @@ expand_decl (decl)
oldaddr = XEXP (DECL_RTL (decl), 0);
}
- DECL_RTL (decl)
- = assign_stack_temp (DECL_MODE (decl),
- ((TREE_INT_CST_LOW (DECL_SIZE (decl))
- + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT),
- 1);
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ DECL_RTL (decl) = assign_temp (TREE_TYPE (decl), 1, 1, 1);
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
/* Set alignment we actually gave this decl. */
DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
@@ -3284,7 +3578,8 @@ expand_decl (decl)
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
#if 0
/* If this is in memory because of -ffloat-store,
set the volatile bit, to prevent optimizations from
@@ -3330,7 +3625,8 @@ expand_decl (decl)
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (DECL_RTL (decl)) = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
/* Indicate the alignment we actually gave this variable. */
#ifdef STACK_BOUNDARY
@@ -3663,7 +3959,7 @@ expand_anon_union_decl (decl, cleanup, decl_elts)
else
{
DECL_RTL (decl_elt) = gen_rtx_MEM (mode, copy_rtx (XEXP (x, 0)));
- MEM_IN_STRUCT_P (DECL_RTL (decl_elt)) = MEM_IN_STRUCT_P (x);
+ MEM_COPY_ATTRIBUTES (DECL_RTL (decl_elt), x);
RTX_UNCHANGING_P (DECL_RTL (decl_elt)) = RTX_UNCHANGING_P (x);
}
}
@@ -3857,7 +4153,7 @@ expand_start_case (exit_flag, expr, type, printname)
int exit_flag;
tree expr;
tree type;
- char *printname;
+ const char *printname;
{
register struct nesting *thiscase = ALLOC_NESTING ();
@@ -4705,7 +5001,7 @@ void
expand_end_case (orig_index)
tree orig_index;
{
- tree minval, maxval, range, orig_minval;
+ tree minval = NULL_TREE, maxval = NULL_TREE, range, orig_minval;
rtx default_label = 0;
register struct case_node *n;
unsigned int count;
@@ -4833,7 +5129,7 @@ expand_end_case (orig_index)
#endif /* CASE_VALUES_THRESHOLD */
else if (TREE_INT_CST_HIGH (range) != 0
- || count < CASE_VALUES_THRESHOLD
+ || count < (unsigned int) CASE_VALUES_THRESHOLD
|| ((unsigned HOST_WIDE_INT) (TREE_INT_CST_LOW (range))
> 10 * count)
#ifndef ASM_OUTPUT_ADDR_DIFF_ELT
@@ -4953,8 +5249,8 @@ expand_end_case (orig_index)
index_expr, minval);
minval = integer_zero_node;
index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
- emit_cmp_insn (rangertx, index, LTU, NULL_RTX, omode, 1, 0);
- emit_jump_insn (gen_bltu (default_label));
+ emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
+ omode, 1, 0, default_label);
/* Now we can safely truncate. */
index = convert_to_mode (index_mode, index, 0);
}
@@ -5123,8 +5419,8 @@ do_jump_if_equal (op1, op2, label, unsignedp)
enum machine_mode mode = GET_MODE (op1);
if (mode == VOIDmode)
mode = GET_MODE (op2);
- emit_cmp_insn (op1, op2, EQ, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn (gen_beq (label));
+ emit_cmp_and_jump_insns (op1, op2, EQ, NULL_RTX, mode, unsignedp,
+ 0, label);
}
}
@@ -5532,11 +5828,7 @@ emit_case_nodes (index, node, default_label, index_type)
{
/* If INDEX has an unsigned type, we must make unsigned branches. */
int unsignedp = TREE_UNSIGNED (index_type);
- typedef rtx rtx_function ();
- rtx_function *gen_bgt_pat = unsignedp ? gen_bgtu : gen_bgt;
- rtx_function *gen_bge_pat = unsignedp ? gen_bgeu : gen_bge;
- rtx_function *gen_blt_pat = unsignedp ? gen_bltu : gen_blt;
- rtx_function *gen_ble_pat = unsignedp ? gen_bleu : gen_ble;
+ typedef rtx rtx_fn ();
enum machine_mode mode = GET_MODE (index);
/* See if our parents have already tested everything for us.
@@ -5562,20 +5854,19 @@ emit_case_nodes (index, node, default_label, index_type)
if (node_is_bounded (node->right, index_type))
{
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- GT, NULL_RTX, mode, unsignedp, 0);
-
- emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->code_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ GT, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (node->right->code_label));
emit_case_nodes (index, node->left, default_label, index_type);
}
else if (node_is_bounded (node->left, index_type))
{
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- LT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_blt_pat) (label_rtx (node->left->code_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ LT, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (node->left->code_label));
emit_case_nodes (index, node->right, default_label, index_type);
}
@@ -5588,10 +5879,10 @@ emit_case_nodes (index, node, default_label, index_type)
= build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
/* See if the value is on the right. */
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- GT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_bgt_pat) (label_rtx (test_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ GT, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (test_label));
/* Value must be on the left.
Handle the left-hand subtree. */
@@ -5619,10 +5910,11 @@ emit_case_nodes (index, node, default_label, index_type)
{
if (!node_has_low_bound (node, index_type))
{
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- LT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_blt_pat) (default_label));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high,
+ NULL_RTX,
+ VOIDmode, 0),
+ LT, NULL_RTX, mode, unsignedp, 0,
+ default_label);
}
emit_case_nodes (index, node->right, default_label, index_type);
@@ -5659,10 +5951,11 @@ emit_case_nodes (index, node, default_label, index_type)
{
if (!node_has_high_bound (node, index_type))
{
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- GT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_bgt_pat) (default_label));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high,
+ NULL_RTX,
+ VOIDmode, 0),
+ GT, NULL_RTX, mode, unsignedp, 0,
+ default_label);
}
emit_case_nodes (index, node->left, default_label, index_type);
@@ -5692,28 +5985,32 @@ emit_case_nodes (index, node, default_label, index_type)
then handle the two subtrees. */
tree test_label = 0;
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- GT, NULL_RTX, mode, unsignedp, 0);
if (node_is_bounded (node->right, index_type))
/* Right hand node is fully bounded so we can eliminate any
testing and branch directly to the target code. */
- emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->code_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ GT, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (node->right->code_label));
else
{
/* Right hand node requires testing.
Branch to a label where we will handle it later. */
test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- emit_jump_insn ((*gen_bgt_pat) (label_rtx (test_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ GT, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (test_label));
}
/* Value belongs to this node or to the left-hand subtree. */
- emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0),
- GE, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->low, NULL_RTX,
+ VOIDmode, 0),
+ GE, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (node->code_label));
/* Handle the left-hand subtree. */
emit_case_nodes (index, node->left, default_label, index_type);
@@ -5737,18 +6034,18 @@ emit_case_nodes (index, node, default_label, index_type)
if they are possible. */
if (!node_has_low_bound (node, index_type))
{
- emit_cmp_insn (index, expand_expr (node->low, NULL_RTX,
- VOIDmode, 0),
- LT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_blt_pat) (default_label));
+ emit_cmp_and_jump_insns (index, expand_expr (node->low, NULL_RTX,
+ VOIDmode, 0),
+ LT, NULL_RTX, mode, unsignedp, 0,
+ default_label);
}
/* Value belongs to this node or to the right-hand subtree. */
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- LE, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_ble_pat) (label_rtx (node->code_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ LE, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (node->code_label));
emit_case_nodes (index, node->right, default_label, index_type);
}
@@ -5759,17 +6056,18 @@ emit_case_nodes (index, node, default_label, index_type)
if they are possible. */
if (!node_has_high_bound (node, index_type))
{
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- GT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_bgt_pat) (default_label));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ GT, NULL_RTX, mode, unsignedp, 0,
+ default_label);
}
/* Value belongs to this node or to the left-hand subtree. */
- emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0),
- GE, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label)));
+ emit_cmp_and_jump_insns (index, expand_expr (node->low, NULL_RTX,
+ VOIDmode, 0),
+ GE, NULL_RTX, mode, unsignedp, 0,
+ label_rtx (node->code_label));
emit_case_nodes (index, node->left, default_label, index_type);
}
@@ -5782,18 +6080,18 @@ emit_case_nodes (index, node, default_label, index_type)
if (!node_has_high_bound (node, index_type))
{
- emit_cmp_insn (index, expand_expr (node->high, NULL_RTX,
- VOIDmode, 0),
- GT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_bgt_pat) (default_label));
+ emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
+ VOIDmode, 0),
+ GT, NULL_RTX, mode, unsignedp, 0,
+ default_label);
}
if (!node_has_low_bound (node, index_type))
{
- emit_cmp_insn (index, expand_expr (node->low, NULL_RTX,
- VOIDmode, 0),
- LT, NULL_RTX, mode, unsignedp, 0);
- emit_jump_insn ((*gen_blt_pat) (default_label));
+ emit_cmp_and_jump_insns (index, expand_expr (node->low, NULL_RTX,
+ VOIDmode, 0),
+ LT, NULL_RTX, mode, unsignedp, 0,
+ default_label);
}
emit_jump (label_rtx (node->code_label));
diff --git a/contrib/gcc/stor-layout.c b/contrib/gcc/stor-layout.c
index 043ad28..798a795 100644
--- a/contrib/gcc/stor-layout.c
+++ b/contrib/gcc/stor-layout.c
@@ -53,8 +53,6 @@ int maximum_field_alignment;
May be overridden by front-ends. */
int set_alignment = 0;
-static enum machine_mode smallest_mode_for_size PROTO((unsigned int,
- enum mode_class));
static tree layout_record PROTO((tree));
static void layout_union PROTO((tree));
@@ -144,13 +142,13 @@ mode_for_size (size, class, limit)
{
register enum machine_mode mode;
- if (limit && size > MAX_FIXED_MODE_SIZE)
+ if (limit && size > (unsigned int)(MAX_FIXED_MODE_SIZE))
return BLKmode;
/* Get the first mode which has this size, in the specified class. */
for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- if (GET_MODE_BITSIZE (mode) == size)
+ if ((unsigned int)GET_MODE_BITSIZE (mode) == size)
return mode;
return BLKmode;
@@ -159,7 +157,7 @@ mode_for_size (size, class, limit)
/* Similar, but never return BLKmode; return the narrowest mode that
contains at least the requested number of bits. */
-static enum machine_mode
+enum machine_mode
smallest_mode_for_size (size, class)
unsigned int size;
enum mode_class class;
@@ -170,12 +168,43 @@ smallest_mode_for_size (size, class)
specified class. */
for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- if (GET_MODE_BITSIZE (mode) >= size)
+ if ((unsigned int)GET_MODE_BITSIZE (mode) >= size)
return mode;
abort ();
}
+/* Find an integer mode of the exact same size, or BLKmode on failure. */
+
+enum machine_mode
+int_mode_for_mode (mode)
+ enum machine_mode mode;
+{
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ break;
+
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_FLOAT:
+ mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
+ break;
+
+ case MODE_RANDOM:
+ if (mode == BLKmode)
+ break;
+ /* FALLTHRU */
+
+ case MODE_CC:
+ default:
+ abort();
+ }
+
+ return mode;
+}
+
/* Return the value of VALUE, rounded up to a multiple of DIVISOR. */
tree
@@ -252,7 +281,8 @@ layout_decl (decl, known_align)
{
DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0;
if (maximum_field_alignment != 0)
- DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
+ DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl),
+ (unsigned)maximum_field_alignment);
else if (DECL_PACKED (decl))
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
}
@@ -268,7 +298,7 @@ layout_decl (decl, known_align)
if (xmode != BLKmode
&& known_align % GET_MODE_ALIGNMENT (xmode) == 0)
{
- DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),
+ DECL_ALIGN (decl) = MAX ((unsigned) GET_MODE_ALIGNMENT (xmode),
DECL_ALIGN (decl));
DECL_MODE (decl) = xmode;
DECL_SIZE (decl) = size_int (GET_MODE_BITSIZE (xmode));
@@ -382,7 +412,7 @@ layout_record (rec)
It does, however, affect the alignment of the next field
within the structure. */
if (! integer_zerop (DECL_SIZE (field)))
- record_align = MAX (record_align, desired_align);
+ record_align = MAX ((int)record_align, desired_align);
else if (! DECL_PACKED (field))
desired_align = TYPE_ALIGN (TREE_TYPE (field));
/* A named bit field of declared type `int'
@@ -395,11 +425,11 @@ layout_record (rec)
else if (DECL_PACKED (field))
type_align = MIN (type_align, BITS_PER_UNIT);
- record_align = MAX (record_align, type_align);
+ record_align = MAX ((int)record_align, type_align);
}
}
else
- record_align = MAX (record_align, desired_align);
+ record_align = MAX ((int)record_align, desired_align);
#endif
/* Does this field automatically have alignment it needs
@@ -783,6 +813,7 @@ layout_type (type)
tree ub = TYPE_MAX_VALUE (index);
tree lb = TYPE_MIN_VALUE (index);
tree length;
+ tree element_size;
/* If UB is max (lb - 1, x), remove the MAX_EXPR since the
test for negative below covers it. */
@@ -815,15 +846,30 @@ layout_type (type)
&& TREE_CODE (TYPE_MAX_VALUE (index)) != INTEGER_CST)
length = size_binop (MAX_EXPR, length, size_zero_node);
- TYPE_SIZE (type) = size_binop (MULT_EXPR, TYPE_SIZE (element),
- length);
+ /* Special handling for arrays of bits (for Chill). */
+ element_size = TYPE_SIZE (element);
+ if (TYPE_PACKED (type) && INTEGRAL_TYPE_P (element))
+ {
+ HOST_WIDE_INT maxvalue, minvalue;
+ maxvalue = TREE_INT_CST_LOW (TYPE_MAX_VALUE (element));
+ minvalue = TREE_INT_CST_LOW (TYPE_MIN_VALUE (element));
+ if (maxvalue - minvalue == 1
+ && (maxvalue == 1 || maxvalue == 0))
+ element_size = integer_one_node;
+ }
+
+ TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size, length);
/* If we know the size of the element, calculate the total
size directly, rather than do some division thing below.
This optimization helps Fortran assumed-size arrays
(where the size of the array is determined at runtime)
- substantially. */
- if (TYPE_SIZE_UNIT (element) != 0)
+ substantially.
+ Note that we can't do this in the case where the size of
+ the elements is one bit since TYPE_SIZE_UNIT cannot be
+ set correctly in that case. */
+ if (TYPE_SIZE_UNIT (element) != 0
+ && element_size != integer_one_node)
{
TYPE_SIZE_UNIT (type)
= size_binop (MULT_EXPR, TYPE_SIZE_UNIT (element), length);
@@ -866,7 +912,7 @@ layout_type (type)
MODE_INT, 1);
if (STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT
- && TYPE_ALIGN (type) < TREE_INT_CST_LOW (TYPE_SIZE (type))
+ && (int)TYPE_ALIGN (type) < TREE_INT_CST_LOW (TYPE_SIZE (type))
&& TYPE_MODE (type) != BLKmode)
{
TYPE_NO_FORCE_BLK (type) = 1;
@@ -932,7 +978,7 @@ layout_type (type)
then stick with BLKmode. */
if (STRICT_ALIGNMENT
&& ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
- || (TYPE_ALIGN (type)
+ || ((int)TYPE_ALIGN (type)
>= TREE_INT_CST_LOW (TYPE_SIZE (type)))))
{
if (TYPE_MODE (type) != BLKmode)
@@ -964,7 +1010,7 @@ layout_type (type)
then stick with BLKmode. */
&& (! STRICT_ALIGNMENT
|| TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
- || TYPE_ALIGN (type) >= TREE_INT_CST_LOW (TYPE_SIZE (type))))
+ || (int)TYPE_ALIGN (type) >= TREE_INT_CST_LOW (TYPE_SIZE (type))))
{
tree field;
/* A union which has any BLKmode members must itself be BLKmode;
@@ -1037,6 +1083,18 @@ layout_type (type)
&& TREE_CODE (type) != ARRAY_TYPE)))
TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+ /* Do machine-dependent extra alignment. */
+#ifdef ROUND_TYPE_ALIGN
+ TYPE_ALIGN (type)
+ = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT);
+#endif
+
+#ifdef ROUND_TYPE_SIZE
+ if (TYPE_SIZE (type) != 0)
+ TYPE_SIZE (type)
+ = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
+#endif
+
/* Evaluate nonconstant size only once, either now or as soon as safe. */
if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
TYPE_SIZE (type) = variable_size (TYPE_SIZE (type));
@@ -1335,7 +1393,7 @@ get_best_mode (bitsize, bitpos, align, largest_mode, volatilep)
void
save_storage_status (p)
- struct function *p;
+ struct function *p ATTRIBUTE_UNUSED;
{
#if 0 /* Need not save, since always 0 and non0 (resp.) within a function. */
p->pending_sizes = pending_sizes;
@@ -1348,7 +1406,7 @@ save_storage_status (p)
void
restore_storage_status (p)
- struct function *p;
+ struct function *p ATTRIBUTE_UNUSED;
{
#if 0
pending_sizes = p->pending_sizes;
diff --git a/contrib/gcc/stupid.c b/contrib/gcc/stupid.c
index 718c39b..b2cd170 100644
--- a/contrib/gcc/stupid.c
+++ b/contrib/gcc/stupid.c
@@ -1,5 +1,5 @@
/* Dummy data flow analysis for GNU compiler in nonoptimizing mode.
- Copyright (C) 1987, 91, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 94-96, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -47,7 +47,10 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "hard-reg-set.h"
+#include "basic-block.h"
#include "regs.h"
+#include "insn-config.h"
+#include "reload.h"
#include "flags.h"
#include "toplev.h"
@@ -77,9 +80,21 @@ static int last_setjmp_suid;
static int *reg_where_dead;
+/* Likewise, but point to the insn_chain structure of the insn at which
+ the reg dies. */
+static struct insn_chain **reg_where_dead_chain;
+
/* Element N is suid of insn where life span of pseudo reg N begins. */
+static int *reg_where_born_exact;
+
+/* Element N is 1 if the birth of pseudo reg N is due to a CLOBBER,
+ 0 otherwise. */
+static int *reg_where_born_clobber;
-static int *reg_where_born;
+/* Return the suid of the insn where the register is born, or the suid
+ of the insn before if the birth is due to a CLOBBER. */
+#define REG_WHERE_BORN(N) \
+ (reg_where_born_exact[(N)] - reg_where_born_clobber[(N)])
/* Numbers of pseudo-regs to be allocated, highest priority first. */
@@ -111,7 +126,43 @@ static HARD_REG_SET *after_insn_hard_regs;
static int stupid_reg_compare PROTO((const GENERIC_PTR,const GENERIC_PTR));
static int stupid_find_reg PROTO((int, enum reg_class, enum machine_mode,
int, int, int));
-static void stupid_mark_refs PROTO((rtx, rtx));
+static void stupid_mark_refs PROTO((rtx, struct insn_chain *));
+static void find_clobbered_regs PROTO((rtx, rtx));
+
+/* For communication between stupid_life_analysis and find_clobbered_regs. */
+static struct insn_chain *current_chain;
+
+/* This function, called via note_stores, marks any hard registers that are
+ clobbered in an insn as being live in the live_after and live_before fields
+ of the appropriate insn_chain structure. */
+
+static void
+find_clobbered_regs (reg, setter)
+ rtx reg, setter;
+{
+ int regno, nregs;
+ if (setter == 0 || GET_CODE (setter) != CLOBBER)
+ return;
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+
+ if (GET_CODE (reg) != REG)
+ return;
+ regno = REGNO (reg);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return;
+
+ if (GET_MODE (reg) == VOIDmode)
+ abort ();
+ else
+ nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ while (nregs-- > 0)
+ {
+ SET_REGNO_REG_SET (current_chain->live_after, regno);
+ SET_REGNO_REG_SET (current_chain->live_before, regno++);
+ }
+}
/* Stupid life analysis is for the case where only variables declared
`register' go in registers. For this case, we mark all
@@ -135,7 +186,7 @@ stupid_life_analysis (f, nregs, file)
bzero (regs_ever_live, sizeof regs_ever_live);
- regs_live = (char *) alloca (nregs);
+ regs_live = (char *) xmalloc (nregs);
/* First find the last real insn, and count the number of insns,
and assign insns their suids. */
@@ -145,7 +196,7 @@ stupid_life_analysis (f, nregs, file)
i = INSN_UID (insn);
max_uid = i + 1;
- uid_suid = (int *) alloca ((i + 1) * sizeof (int));
+ uid_suid = (int *) xmalloc ((i + 1) * sizeof (int));
/* Compute the mapping from uids to suids.
Suids are numbers assigned to insns, like uids,
@@ -168,19 +219,25 @@ stupid_life_analysis (f, nregs, file)
/* Allocate tables to record info about regs. */
- reg_where_dead = (int *) alloca (nregs * sizeof (int));
+ reg_where_dead = (int *) xmalloc (nregs * sizeof (int));
bzero ((char *) reg_where_dead, nregs * sizeof (int));
- reg_where_born = (int *) alloca (nregs * sizeof (int));
- bzero ((char *) reg_where_born, nregs * sizeof (int));
+ reg_where_born_exact = (int *) xmalloc (nregs * sizeof (int));
+ bzero ((char *) reg_where_born_exact, nregs * sizeof (int));
- reg_order = (int *) alloca (nregs * sizeof (int));
+ reg_where_born_clobber = (int *) xmalloc (nregs * sizeof (int));
+ bzero ((char *) reg_where_born_clobber, nregs * sizeof (int));
+
+ reg_where_dead_chain = (struct insn_chain **) xmalloc (nregs * sizeof (struct insn_chain *));
+ bzero ((char *) reg_where_dead_chain, nregs * sizeof (struct insn_chain *));
+
+ reg_order = (int *) xmalloc (nregs * sizeof (int));
bzero ((char *) reg_order, nregs * sizeof (int));
- regs_change_size = (char *) alloca (nregs * sizeof (char));
+ regs_change_size = (char *) xmalloc (nregs * sizeof (char));
bzero ((char *) regs_change_size, nregs * sizeof (char));
- regs_crosses_setjmp = (char *) alloca (nregs * sizeof (char));
+ regs_crosses_setjmp = (char *) xmalloc (nregs * sizeof (char));
bzero ((char *) regs_crosses_setjmp, nregs * sizeof (char));
/* Allocate the reg_renumber array */
@@ -189,14 +246,15 @@ stupid_life_analysis (f, nregs, file)
reg_renumber[i] = i;
after_insn_hard_regs
- = (HARD_REG_SET *) alloca (max_suid * sizeof (HARD_REG_SET));
+ = (HARD_REG_SET *) xmalloc (max_suid * sizeof (HARD_REG_SET));
bzero ((char *) after_insn_hard_regs, max_suid * sizeof (HARD_REG_SET));
/* Allocate and zero out many data structures
that will record the data from lifetime analysis. */
- allocate_for_life_analysis ();
+ allocate_reg_life_data ();
+ allocate_bb_life_data ();
for (i = 0; i < max_regno; i++)
REG_N_DEATHS (i) = 1;
@@ -210,11 +268,15 @@ stupid_life_analysis (f, nregs, file)
Also find where each hard register is live
and record that info in after_insn_hard_regs.
regs_live[I] is 1 if hard reg I is live
- at the current point in the scan. */
+ at the current point in the scan.
+
+ Build reload_insn_chain while we're walking the insns. */
+ reload_insn_chain = 0;
for (insn = last; insn; insn = PREV_INSN (insn))
{
register HARD_REG_SET *p = after_insn_hard_regs + INSN_SUID (insn);
+ struct insn_chain *chain;
/* Copy the info in regs_live into the element of after_insn_hard_regs
for the current position in the rtl code. */
@@ -223,12 +285,27 @@ stupid_life_analysis (f, nregs, file)
if (regs_live[i])
SET_HARD_REG_BIT (*p, i);
+ if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER)
+ {
+ chain = new_insn_chain ();
+ if (reload_insn_chain)
+ reload_insn_chain->prev = chain;
+ chain->next = reload_insn_chain;
+ chain->prev = 0;
+ reload_insn_chain = chain;
+ chain->block = 0;
+ chain->insn = insn;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (regs_live[i])
+ SET_REGNO_REG_SET (chain->live_before, i);
+ }
+
/* Update which hard regs are currently live
and also the birth and death suids of pseudo regs
based on the pattern of this insn. */
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- stupid_mark_refs (PATTERN (insn), insn);
+ stupid_mark_refs (PATTERN (insn), chain);
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
@@ -266,8 +343,23 @@ stupid_life_analysis (f, nregs, file)
/* It is important that this be done after processing the insn's
pattern because we want the function result register to still
be live if it's also used to pass arguments. */
- stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), insn);
+ stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), chain);
}
+
+ if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER)
+ {
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (regs_live[i])
+ SET_REGNO_REG_SET (chain->live_after, i);
+
+ /* The regs_live array doesn't say anything about hard registers
+ clobbered by this insn. So we need an extra pass over the
+ pattern. */
+ current_chain = chain;
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ note_stores (PATTERN (insn), find_clobbered_regs);
+ }
+
if (GET_CODE (insn) == JUMP_INSN && computed_jump_p (insn))
current_function_has_computed_jump = 1;
}
@@ -289,8 +381,10 @@ stupid_life_analysis (f, nregs, file)
/* Some regnos disappear from the rtl. Ignore them to avoid crash.
Also don't allocate registers that cross a setjmp, or live across
- a call if this function receives a nonlocal goto. */
+ a call if this function receives a nonlocal goto.
+ Also ignore registers we didn't see during the scan. */
if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r]
+ || (reg_where_born_exact[r] == 0 && reg_where_dead[r] == 0)
|| (REG_N_CALLS_CROSSED (r) > 0
&& current_function_has_nonlocal_label))
continue;
@@ -300,7 +394,7 @@ stupid_life_analysis (f, nregs, file)
reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
reg_preferred_class (r),
PSEUDO_REGNO_MODE (r),
- reg_where_born[r],
+ REG_WHERE_BORN (r),
reg_where_dead[r],
regs_change_size[r]);
@@ -309,13 +403,52 @@ stupid_life_analysis (f, nregs, file)
reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
reg_alternate_class (r),
PSEUDO_REGNO_MODE (r),
- reg_where_born[r],
+ REG_WHERE_BORN (r),
reg_where_dead[r],
regs_change_size[r]);
}
+ /* Fill in the pseudo reg life information into the insn chain. */
+ for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
+ {
+ struct insn_chain *chain;
+ int regno;
+
+ regno = reg_renumber[i];
+ if (regno < 0)
+ continue;
+
+ chain = reg_where_dead_chain[i];
+ if (reg_where_dead[i] > INSN_SUID (chain->insn))
+ SET_REGNO_REG_SET (chain->live_after, i);
+
+ while (INSN_SUID (chain->insn) > reg_where_born_exact[i])
+ {
+ SET_REGNO_REG_SET (chain->live_before, i);
+ chain = chain->prev;
+ if (!chain)
+ break;
+ SET_REGNO_REG_SET (chain->live_after, i);
+ }
+
+ if (INSN_SUID (chain->insn) == reg_where_born_exact[i]
+ && reg_where_born_clobber[i])
+ SET_REGNO_REG_SET (chain->live_before, i);
+ }
+
if (file)
dump_flow_info (file);
+
+ free (regs_live);
+ free (uid_suid);
+ free (reg_where_dead);
+ free (reg_where_born_exact);
+ free (reg_where_born_clobber);
+ free (reg_where_dead_chain);
+ free (reg_order);
+ free (regs_change_size);
+ free (regs_crosses_setjmp);
+ free (after_insn_hard_regs);
}
/* Comparison function for qsort.
@@ -327,8 +460,8 @@ stupid_reg_compare (r1p, r2p)
const GENERIC_PTR r2p;
{
register int r1 = *(int *)r1p, r2 = *(int *)r2p;
- register int len1 = reg_where_dead[r1] - reg_where_born[r1];
- register int len2 = reg_where_dead[r2] - reg_where_born[r2];
+ register int len1 = reg_where_dead[r1] - REG_WHERE_BORN (r1);
+ register int len2 = reg_where_dead[r2] - REG_WHERE_BORN (r2);
int tem;
tem = len2 - len1;
@@ -365,7 +498,7 @@ stupid_find_reg (call_preserved, class, mode,
enum reg_class class;
enum machine_mode mode;
int born_insn, dead_insn;
- int changes_size;
+ int changes_size ATTRIBUTE_UNUSED;
{
register int i, ins;
#ifdef HARD_REG_SET
@@ -387,7 +520,7 @@ stupid_find_reg (call_preserved, class, mode,
call_preserved ? call_used_reg_set : fixed_reg_set);
#ifdef ELIMINABLE_REGS
- for (i = 0; i < sizeof eliminables / sizeof eliminables[0]; i++)
+ for (i = 0; i < (int)(sizeof eliminables / sizeof eliminables[0]); i++)
SET_HARD_REG_BIT (used, eliminables[i].from);
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
SET_HARD_REG_BIT (used, HARD_FRAME_POINTER_REGNUM);
@@ -461,12 +594,14 @@ stupid_find_reg (call_preserved, class, mode,
INSN is the current insn, supplied so we can find its suid. */
static void
-stupid_mark_refs (x, insn)
- rtx x, insn;
+stupid_mark_refs (x, chain)
+ rtx x;
+ struct insn_chain *chain;
{
register RTX_CODE code;
register char *fmt;
register int regno, i;
+ rtx insn = chain->insn;
if (x == 0)
return;
@@ -521,7 +656,11 @@ stupid_mark_refs (x, insn)
the clobbering insn. When setting, just after. */
int where_born = INSN_SUID (insn) - (code == CLOBBER);
- reg_where_born[regno] = where_born;
+ reg_where_born_exact[regno] = INSN_SUID (insn);
+ reg_where_born_clobber[regno] = (code == CLOBBER);
+
+ if (reg_where_dead_chain[regno] == 0)
+ reg_where_dead_chain[regno] = chain;
/* The reg must live at least one insn even
in it is never again used--because it has to go
@@ -543,16 +682,18 @@ stupid_mark_refs (x, insn)
if (last_setjmp_suid < reg_where_dead[regno])
regs_crosses_setjmp[regno] = 1;
- /* If this register is only used in this insn and is only
- set, mark it unused. We have to do this even when not
- optimizing so that MD patterns which count on this
- behavior (e.g., it not causing an output reload on
- an insn setting CC) will operate correctly. */
+ /* If this register is clobbered or it is only used in
+ this insn and is only set, mark it unused. We have
+ to do this even when not optimizing so that MD patterns
+ which count on this behavior (e.g., it not causing an
+ output reload on an insn setting CC) will operate
+ correctly. */
if (GET_CODE (SET_DEST (x)) == REG
- && REGNO_FIRST_UID (regno) == INSN_UID (insn)
- && REGNO_LAST_UID (regno) == INSN_UID (insn)
- && (code == CLOBBER || ! reg_mentioned_p (SET_DEST (x),
- SET_SRC (x))))
+ && (code == CLOBBER
+ || (REGNO_FIRST_UID (regno) == INSN_UID (insn)
+ && REGNO_LAST_UID (regno) == INSN_UID (insn)
+ && ! reg_mentioned_p (SET_DEST (x),
+ SET_SRC (x)))))
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_UNUSED,
SET_DEST (x),
REG_NOTES (insn));
@@ -564,9 +705,9 @@ stupid_mark_refs (x, insn)
If setting a SUBREG, we treat the entire reg as *used*. */
if (code == SET)
{
- stupid_mark_refs (SET_SRC (x), insn);
+ stupid_mark_refs (SET_SRC (x), chain);
if (GET_CODE (SET_DEST (x)) != REG)
- stupid_mark_refs (SET_DEST (x), insn);
+ stupid_mark_refs (SET_DEST (x), chain);
}
return;
}
@@ -599,12 +740,14 @@ stupid_mark_refs (x, insn)
{
/* Pseudo reg: record first use, last use and number of uses. */
- reg_where_born[regno] = INSN_SUID (insn);
+ reg_where_born_exact[regno] = INSN_SUID (insn);
+ reg_where_born_clobber[regno] = 0;
REG_N_REFS (regno)++;
if (regs_live[regno] == 0)
{
regs_live[regno] = 1;
reg_where_dead[regno] = INSN_SUID (insn);
+ reg_where_dead_chain[regno] = chain;
}
}
return;
@@ -616,12 +759,12 @@ stupid_mark_refs (x, insn)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- stupid_mark_refs (XEXP (x, i), insn);
+ stupid_mark_refs (XEXP (x, i), chain);
if (fmt[i] == 'E')
{
register int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- stupid_mark_refs (XVECEXP (x, i, j), insn);
+ stupid_mark_refs (XVECEXP (x, i, j), chain);
}
}
}
diff --git a/contrib/gcc/system.h b/contrib/gcc/system.h
index 27b1fee..7d6082c 100644
--- a/contrib/gcc/system.h
+++ b/contrib/gcc/system.h
@@ -1,12 +1,34 @@
/* system.h - Get common system includes and various definitions and
declarations based on autoconf macros.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
- */
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#ifndef __GCC_SYSTEM_H__
#define __GCC_SYSTEM_H__
+/* We must include stdarg.h/varargs.h before stdio.h. */
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
#include <stdio.h>
/* Define a generic NULL if one hasn't already been defined. */
@@ -14,6 +36,31 @@
#define NULL 0
#endif
+/* The compiler is not a multi-threaded application and therefore we
+ do not have to use the locking functions.
+
+ NEED_DECLARATION_PUTC_UNLOCKED actually indicates whether or not
+ the IO code is multi-thread safe by default. If it is not declared,
+ then do not worry about using the _unlocked functions.
+
+ fputs_unlocked is an extension and needs to be prototyped specially. */
+
+#if defined HAVE_PUTC_UNLOCKED && !defined NEED_DECLARATION_PUTC_UNLOCKED
+# undef putc
+# define putc(C, Stream) putc_unlocked (C, Stream)
+#endif
+#if defined HAVE_FPUTC_UNLOCKED && !defined NEED_DECLARATION_PUTC_UNLOCKED
+# undef fputc
+# define fputc(C, Stream) fputc_unlocked (C, Stream)
+#endif
+#if defined HAVE_FPUTS_UNLOCKED && !defined NEED_DECLARATION_PUTC_UNLOCKED
+# undef fputs
+# define fputs(String, Stream) fputs_unlocked (String, Stream)
+# ifdef NEED_DECLARATION_FPUTS_UNLOCKED
+extern int fputs_unlocked PROTO ((const char *, FILE *));
+# endif
+#endif
+
#include <ctype.h>
/* Jim Meyering writes:
@@ -81,11 +128,16 @@
extern int errno;
#endif
-#ifdef HAVE_STRING_H
+#ifdef STRING_WITH_STRINGS
# include <string.h>
+# include <strings.h>
#else
-# ifdef HAVE_STRINGS_H
-# include <strings.h>
+# ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
# endif
#endif
@@ -105,6 +157,34 @@ extern int errno;
# include <limits.h>
#endif
+/* Find HOST_WIDEST_INT and set its bit size, type and print macros.
+ It will be the largest integer mode supported by the host which may
+ (or may not) be larger than HOST_WIDE_INT. This must appear after
+ <limits.h> since we only use `long long' if its bigger than a
+ `long' and also if it is supported by macros in limits.h. For old
+ hosts which don't have a limits.h (and thus won't include it in
+ stage2 cause we don't rerun configure) we assume gcc supports long
+ long.) Note, you won't get these defined if you don't include
+ {ht}config.h before this file to set the HOST_BITS_PER_* macros. */
+
+#ifndef HOST_WIDEST_INT
+# if defined (HOST_BITS_PER_LONG) && defined (HOST_BITS_PER_LONGLONG)
+# if (HOST_BITS_PER_LONGLONG > HOST_BITS_PER_LONG) && (defined (LONG_LONG_MAX) || defined (LONGLONG_MAX) || defined (LLONG_MAX) || defined (__GNUC__))
+# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG
+# define HOST_WIDEST_INT long long
+# define HOST_WIDEST_INT_PRINT_DEC "%lld"
+# define HOST_WIDEST_INT_PRINT_UNSIGNED "%llu"
+# define HOST_WIDEST_INT_PRINT_HEX "0x%llx"
+# else
+# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONG
+# define HOST_WIDEST_INT long
+# define HOST_WIDEST_INT_PRINT_DEC "%ld"
+# define HOST_WIDEST_INT_PRINT_UNSIGNED "%lu"
+# define HOST_WIDEST_INT_PRINT_HEX "0x%lx"
+# endif /*(long long>long) && (LONG_LONG_MAX||LONGLONG_MAX||LLONG_MAX||GNUC)*/
+# endif /* defined(HOST_BITS_PER_LONG) && defined(HOST_BITS_PER_LONGLONG) */
+#endif /* ! HOST_WIDEST_INT */
+
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
@@ -144,6 +224,35 @@ extern int errno;
# define O_WRONLY 1
#endif
+/* Some systems define these in, e.g., param.h. We undefine these names
+ here to avoid the warnings. We prefer to use our definitions since we
+ know they are correct. */
+
+#undef MIN
+#undef MAX
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(S) ((S) & 0x7f)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(S) (((S) & 0xff) == 0)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
+#endif
+#ifndef WSTOPSIG
+#define WSTOPSIG WEXITSTATUS
+#endif
+
#ifndef bcopy
@@ -152,7 +261,7 @@ extern int errno;
extern void bcopy ();
# endif
# else /* ! HAVE_BCOPY */
-# define bcopy(src,dst,len) memcpy ((dst),(src),(len))
+# define bcopy(src,dst,len) memmove((dst),(src),(len))
# endif
#endif
@@ -224,6 +333,10 @@ extern char *getwd ();
extern char *sbrk ();
#endif
+#ifdef NEED_DECLARATION_STRSTR
+extern char *strstr ();
+#endif
+
#ifdef HAVE_STRERROR
# ifdef NEED_DECLARATION_STRERROR
# ifndef strerror
@@ -235,6 +348,20 @@ extern int sys_nerr;
extern char *sys_errlist[];
#endif /* HAVE_STRERROR */
+#ifdef HAVE_STRSIGNAL
+# ifdef NEED_DECLARATION_STRSIGNAL
+# ifndef strsignal
+extern char * strsignal ();
+# endif
+# endif
+#else /* ! HAVE_STRSIGNAL */
+# ifndef SYS_SIGLIST_DECLARED
+# ifndef NO_SYS_SIGLIST
+extern char * sys_siglist[];
+# endif
+# endif
+#endif /* HAVE_STRSIGNAL */
+
#ifdef HAVE_GETRLIMIT
# ifdef NEED_DECLARATION_GETRLIMIT
# ifndef getrlimit
@@ -258,38 +385,27 @@ extern int setrlimit ();
#endif
/* Redefine abort to report an internal error w/o coredump, and reporting the
- location of the error in the source file. */
-#ifndef abort
-#ifndef __STDC__
-#ifndef __GNUC__
-#ifndef USE_SYSTEM_ABORT
-#define USE_SYSTEM_ABORT
-#endif /* !USE_SYSTEM_ABORT */
-#endif /* !__GNUC__ */
-#endif /* !__STDC__ */
-
-#ifdef USE_SYSTEM_ABORT
-# ifdef NEED_DECLARATION_ABORT
+ location of the error in the source file.
+ Some files undefine abort again, so we must prototype the real thing
+ for their sake. */
+#ifdef NEED_DECLARATION_ABORT
extern void abort ();
-# endif
-#else
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-#define abort() \
-(fprintf (stderr, \
- "%s:%d: Internal compiler error\n", __FILE__, __LINE__), \
- exit (FATAL_EXIT_CODE))
+#endif
+extern void fatal PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#define abort() fatal ("Internal compiler error at %s:%d\n", \
+ trim_filename (__FILE__), __LINE__)
#else
-#define abort() \
-(fprintf (stderr, \
- "%s:%d: Internal compiler error in function %s\n", \
- __FILE__, __LINE__, __PRETTY_FUNCTION__), \
- exit (FATAL_EXIT_CODE))
-
+#define abort() fatal ("Internal compiler error in `%s', at %s:%d\n" \
+ "Please submit a full bug report.\n" \
+ "See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.", \
+ __PRETTY_FUNCTION__, trim_filename (__FILE__), __LINE__)
#endif /* recent gcc */
-#endif /* USE_SYSTEM_ABORT */
-#endif /* !abort */
+/* trim_filename is in toplev.c. Define a stub macro for files that
+ don't link toplev.c. toplev.h will reset it to the real version. */
+#define trim_filename(x) (x)
/* Define a STRINGIFY macro that's right for ANSI or traditional C.
HAVE_CPP_STRINGIFY only refers to the stage1 compiler. Assume that
@@ -308,9 +424,70 @@ extern void abort ();
# endif
#endif /* ! STRINGIFY */
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+/* Test if something is a normal file. */
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+/* Test if something is a directory. */
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+/* Test if something is a character special file. */
+#ifndef S_ISCHR
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+
+/* Test if something is a socket. */
+#ifndef S_ISSOCK
+# ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+# define S_ISSOCK(m) 0
+# endif
+#endif
+
+/* Test if something is a FIFO. */
+#ifndef S_ISFIFO
+# ifdef S_IFIFO
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) 0
+# endif
+#endif
+
+/* Approximate O_NONBLOCK. */
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+/* Approximate O_NOCTTY. */
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
+/* Define well known filenos if the system does not define them. */
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Some systems have mkdir that takes a single argument. */
+#ifdef MKDIR_TAKES_ONE_ARG
+# define mkdir(a,b) mkdir(a)
+#endif
-/* These macros are here in preparation for the use of gettext in egcs. */
-#define _(String) String
-#define N_(String) String
+/* Get libiberty declarations. */
+#include "libiberty.h"
#endif /* __GCC_SYSTEM_H__ */
diff --git a/contrib/gcc/tlink.c b/contrib/gcc/tlink.c
index d5fa00c..9f058c9 100644
--- a/contrib/gcc/tlink.c
+++ b/contrib/gcc/tlink.c
@@ -18,13 +18,15 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "hash.h"
#include "demangle.h"
#include "toplev.h"
+#include "collect2.h"
#define MAX_ITERATIONS 17
@@ -32,8 +34,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern char * xmalloc PARAMS((unsigned));
-
/* Defined in collect2.c. */
extern int vflag, debug;
extern char *ldout;
@@ -47,7 +47,8 @@ extern int prepends_underscore;
static int tlink_verbose;
-/* Hash table code. */
+/* Hash table boilerplate for working with hash.[ch]. We have hash tables
+ for symbol names, file names, and demangled symbols. */
typedef struct symbol_hash_entry
{
@@ -75,11 +76,46 @@ typedef struct demangled_hash_entry
static struct hash_table symbol_table;
+static struct hash_entry * symbol_hash_newfunc PARAMS ((struct hash_entry *,
+ struct hash_table *,
+ hash_table_key));
+static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
+ boolean));
+static struct hash_entry * file_hash_newfunc PARAMS ((struct hash_entry *,
+ struct hash_table *,
+ hash_table_key));
+static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
+static struct hash_entry * demangled_hash_newfunc PARAMS ((struct hash_entry *,
+ struct hash_table *,
+ hash_table_key));
+static struct demangled_hash_entry *
+ demangled_hash_lookup PARAMS ((const char *, boolean));
+static void symbol_push PARAMS ((symbol *));
+static symbol * symbol_pop PARAMS ((void));
+static void file_push PARAMS ((file *));
+static file * file_pop PARAMS ((void));
+static void tlink_init PARAMS ((void));
+static int tlink_execute PARAMS ((char *, char **, char *));
+static char * frob_extension PARAMS ((char *, const char *));
+static char * obstack_fgets PARAMS ((FILE *, struct obstack *));
+static char * tfgets PARAMS ((FILE *));
+static char * pfgets PARAMS ((FILE *));
+static void freadsym PARAMS ((FILE *, file *, int));
+static void read_repo_file PARAMS ((file *));
+static void maybe_tweak PARAMS ((char *, file *));
+static int recompile_files PARAMS ((void));
+static int read_repo_files PARAMS ((char **));
+static void demangle_new_symbols PARAMS ((void));
+static int scan_linker_output PARAMS ((const char *));
+
+/* Create a new entry for the symbol hash table.
+ Passed to hash_table_init. */
+
static struct hash_entry *
symbol_hash_newfunc (entry, table, string)
struct hash_entry *entry;
struct hash_table *table;
- const char *string;
+ hash_table_key string;
{
struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
if (ret == NULL)
@@ -89,8 +125,6 @@ symbol_hash_newfunc (entry, table, string)
if (ret == NULL)
return NULL;
}
- ret = ((struct symbol_hash_entry *)
- hash_newfunc ((struct hash_entry *) ret, table, string));
ret->file = NULL;
ret->chosen = 0;
ret->tweaking = 0;
@@ -98,22 +132,28 @@ symbol_hash_newfunc (entry, table, string)
return (struct hash_entry *) ret;
}
+/* Look up an entry in the symbol hash table. */
+
static struct symbol_hash_entry *
symbol_hash_lookup (string, create)
const char *string;
boolean create;
{
return ((struct symbol_hash_entry *)
- hash_lookup (&symbol_table, string, create, true));
+ hash_lookup (&symbol_table, (hash_table_key) string,
+ create, &string_copy));
}
static struct hash_table file_table;
+/* Create a new entry for the file hash table.
+ Passed to hash_table_init. */
+
static struct hash_entry *
file_hash_newfunc (entry, table, string)
struct hash_entry *entry;
struct hash_table *table;
- const char *string;
+ hash_table_key string;
{
struct file_hash_entry *ret = (struct file_hash_entry *) entry;
if (ret == NULL)
@@ -123,8 +163,6 @@ file_hash_newfunc (entry, table, string)
if (ret == NULL)
return NULL;
}
- ret = ((struct file_hash_entry *)
- hash_newfunc ((struct hash_entry *) ret, table, string));
ret->args = NULL;
ret->dir = NULL;
ret->main = NULL;
@@ -132,21 +170,27 @@ file_hash_newfunc (entry, table, string)
return (struct hash_entry *) ret;
}
+/* Look up an entry in the file hash table. */
+
static struct file_hash_entry *
file_hash_lookup (string)
const char *string;
{
return ((struct file_hash_entry *)
- hash_lookup (&file_table, string, true, true));
+ hash_lookup (&file_table, (hash_table_key) string, true,
+ &string_copy));
}
static struct hash_table demangled_table;
+/* Create a new entry for the demangled name hash table.
+ Passed to hash_table_init. */
+
static struct hash_entry *
demangled_hash_newfunc (entry, table, string)
struct hash_entry *entry;
struct hash_table *table;
- const char *string;
+ hash_table_key string;
{
struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
if (ret == NULL)
@@ -156,19 +200,20 @@ demangled_hash_newfunc (entry, table, string)
if (ret == NULL)
return NULL;
}
- ret = ((struct demangled_hash_entry *)
- hash_newfunc ((struct hash_entry *) ret, table, string));
ret->mangled = NULL;
return (struct hash_entry *) ret;
}
+/* Look up an entry in the demangled name hash table. */
+
static struct demangled_hash_entry *
demangled_hash_lookup (string, create)
const char *string;
boolean create;
{
return ((struct demangled_hash_entry *)
- hash_lookup (&demangled_table, string, create, true));
+ hash_lookup (&demangled_table, (hash_table_key) string,
+ create, &string_copy));
}
/* Stack code. */
@@ -246,14 +291,19 @@ file_pop ()
/* Other machinery. */
+/* Initialize the tlink machinery. Called from do_tlink. */
+
static void
tlink_init ()
{
char *p;
- hash_table_init (&symbol_table, symbol_hash_newfunc);
- hash_table_init (&file_table, file_hash_newfunc);
- hash_table_init (&demangled_table, demangled_hash_newfunc);
+ hash_table_init (&symbol_table, symbol_hash_newfunc, &string_hash,
+ &string_compare);
+ hash_table_init (&file_table, file_hash_newfunc, &string_hash,
+ &string_compare);
+ hash_table_init (&demangled_table, demangled_hash_newfunc,
+ &string_hash, &string_compare);
obstack_begin (&symbol_stack_obstack, 0);
obstack_begin (&file_stack_obstack, 0);
@@ -282,7 +332,8 @@ tlink_execute (prog, argv, redir)
static char *
frob_extension (s, ext)
- char *s, *ext;
+ char *s;
+ const char *ext;
{
char *p = rindex (s, '/');
if (! p)
@@ -325,6 +376,12 @@ pfgets (stream)
/* Real tlink code. */
+/* Subroutine of read_repo_file. We are reading the repo file for file F,
+ which is coming in on STREAM, and the symbol that comes next in STREAM
+ is offerred, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
+
+ XXX "provided" is unimplemented, both here and in the compiler. */
+
static void
freadsym (stream, f, chosen)
FILE *stream;
@@ -340,12 +397,16 @@ freadsym (stream, f, chosen)
if (sym->file == NULL)
{
+ /* We didn't have this symbol already, so we choose this file. */
+
symbol_push (sym);
sym->file = f;
sym->chosen = chosen;
}
else if (chosen)
{
+ /* We want this file; cast aside any pretender. */
+
if (sym->chosen && sym->file != f)
{
if (sym->chosen == 1)
@@ -362,15 +423,18 @@ freadsym (stream, f, chosen)
}
}
+/* Read in the repo file denoted by F, and record all its information. */
+
static void
read_repo_file (f)
file *f;
{
char c;
- FILE *stream = fopen (f->root.string, "r");
+ FILE *stream = fopen ((char*) f->root.key, "r");
if (tlink_verbose >= 2)
- fprintf (stderr, "collect: reading %s\n", f->root.string);
+ fprintf (stderr, "collect: reading %s\n",
+ (char*) f->root.key);
while (fscanf (stream, "%c ", &c) == 1)
{
@@ -404,6 +468,11 @@ read_repo_file (f)
f->dir = ".";
}
+/* We might want to modify LINE, which is a symbol line from file F. We do
+ this if either we saw an error message referring to the symbol in
+ question, or we have already allocated the symbol to another file and
+ this one wants to emit it as well. */
+
static void
maybe_tweak (line, f)
char *line;
@@ -424,6 +493,11 @@ maybe_tweak (line, f)
}
}
+/* Update the repo files for each of the object files we have adjusted and
+ recompile.
+
+ XXX Should this use collect_execute instead of system? */
+
static int
recompile_files ()
{
@@ -432,8 +506,8 @@ recompile_files ()
while ((f = file_pop ()) != NULL)
{
char *line, *command;
- FILE *stream = fopen (f->root.string, "r");
- char *outname = frob_extension (f->root.string, ".rnw");
+ FILE *stream = fopen ((char*) f->root.key, "r");
+ char *outname = frob_extension ((char*) f->root.key, ".rnw");
FILE *output = fopen (outname, "w");
while ((line = tfgets (stream)) != NULL)
@@ -448,7 +522,7 @@ recompile_files ()
}
fclose (stream);
fclose (output);
- rename (outname, f->root.string);
+ rename (outname, (char*) f->root.key);
obstack_grow (&temporary_obstack, "cd ", 3);
obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
@@ -474,6 +548,9 @@ recompile_files ()
return 1;
}
+/* The first phase of processing: determine which object files have
+ .rpo files associated with them, and read in the information. */
+
static int
read_repo_files (object_lst)
char **object_lst;
@@ -499,6 +576,8 @@ read_repo_files (object_lst)
return (symbol_stack != NULL);
}
+/* Add the demangled forms of any new symbols to the hash table. */
+
static void
demangle_new_symbols ()
{
@@ -507,19 +586,23 @@ demangle_new_symbols ()
while ((sym = symbol_pop ()) != NULL)
{
demangled *dem;
- char *p = cplus_demangle (sym->root.string, DMGL_PARAMS | DMGL_ANSI);
+ char *p = cplus_demangle ((char*) sym->root.key,
+ DMGL_PARAMS | DMGL_ANSI);
if (! p)
continue;
dem = demangled_hash_lookup (p, true);
- dem->mangled = sym->root.string;
+ dem->mangled = (char*) sym->root.key;
}
}
+/* Step through the output of the linker, in the file named FNAME, and
+ adjust the settings for each symbol encountered. */
+
static int
scan_linker_output (fname)
- char *fname;
+ const char *fname;
{
FILE *stream = fopen (fname, "r");
char *line;
@@ -530,13 +613,13 @@ scan_linker_output (fname)
symbol *sym;
int end;
- while (*p && ISSPACE (*p))
+ while (*p && ISSPACE ((unsigned char)*p))
++p;
if (! *p)
continue;
- for (q = p; *q && ! ISSPACE (*q); ++q)
+ for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
;
/* Try the first word on the line. */
@@ -550,26 +633,29 @@ scan_linker_output (fname)
sym = symbol_hash_lookup (p, false);
if (! sym && ! end)
- /* Try a mangled name in `quotes'. */
+ /* Try a mangled name in quotes. */
{
+ char *oldq = q+1;
demangled *dem = 0;
- p = index (q+1, '`');
q = 0;
-#define MUL "multiple definition of "
-#define UND "undefined reference to "
+ /* First try `GNU style'. */
+ p = index (oldq, '`');
+ if (p)
+ p++, q = index (p, '\'');
+ /* Then try "double quotes". */
+ else if (p = index (oldq, '"'), p)
+ p++, q = index (p, '"');
- if (p && (p - line > sizeof (MUL)))
+ if (q)
{
- char *beg = p - sizeof (MUL) + 1;
- *p = 0;
- if (!strcmp (beg, MUL) || !strcmp (beg, UND))
- p++, q = index (p, '\'');
+ *q = 0;
+ dem = demangled_hash_lookup (p, false);
+ if (dem)
+ sym = symbol_hash_lookup (dem->mangled, false);
+ else
+ sym = symbol_hash_lookup (p, false);
}
- if (q)
- *q = 0, dem = demangled_hash_lookup (p, false);
- if (dem)
- sym = symbol_hash_lookup (dem->mangled, false);
}
if (sym && sym->tweaked)
@@ -581,7 +667,7 @@ scan_linker_output (fname)
{
if (tlink_verbose >= 2)
fprintf (stderr, "collect: tweaking %s in %s\n",
- sym->root.string, sym->file->root.string);
+ (char*) sym->root.key, (char*) sym->file->root.key);
sym->tweaking = 1;
file_push (sym->file);
}
@@ -593,6 +679,15 @@ scan_linker_output (fname)
return (file_stack != NULL);
}
+/* Entry point for tlink. Called from main in collect2.c.
+
+ Iteratively try to provide definitions for all the unresolved symbols
+ mentioned in the linker error messages.
+
+ LD_ARGV is an array of arguments for the linker.
+ OBJECT_LST is an array of object files that we may be able to recompile
+ to provide missing definitions. Currently ignored. */
+
void
do_tlink (ld_argv, object_lst)
char **ld_argv, **object_lst;
diff --git a/contrib/gcc/tm.texi b/contrib/gcc/tm.texi
index 8265773..a13c6d9 100644
--- a/contrib/gcc/tm.texi
+++ b/contrib/gcc/tm.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988,89,92,93,94,96,97,1998 Free Software Foundation, Inc.
+@c Copyright (C) 1988,89,92,93,94,96,97,98,1999 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -321,7 +321,8 @@ try when searching for the executable files of the compiler.
If defined, this macro is an additional prefix to try after
@code{STANDARD_EXEC_PREFIX}. @code{MD_EXEC_PREFIX} is not searched
when the @samp{-b} option is used, or the compiler is built as a cross
-compiler.
+compiler. If you define @code{MD_EXEC_PREFIX}, then be sure to add it
+to the list of directories used to find the assembler in @file{configure.in}.
@findex STANDARD_STARTFILE_PREFIX
@item STANDARD_STARTFILE_PREFIX
@@ -790,15 +791,24 @@ size of an integer.
@findex STACK_BOUNDARY
@item STACK_BOUNDARY
+Define this macro if there is a guaranteed alignment for the stack
+pointer on this machine. The definition is a C expression
+for the desired alignment (measured in bits). This value is used as a
+default if PREFERRED_STACK_BOUNDARY is not defined.
+
+@findex PREFERRED_STACK_BOUNDARY
+@item PREFERRED_STACK_BOUNDARY
Define this macro if you wish to preserve a certain alignment for
the stack pointer. The definition is a C expression
-for the desired alignment (measured in bits).
+for the desired alignment (measured in bits). If STACK_BOUNDARY is
+also defined, this macro must evaluate to a value equal to or larger
+than STACK_BOUNDARY.
-@cindex @code{PUSH_ROUNDING}, interaction with @code{STACK_BOUNDARY}
+@cindex @code{PUSH_ROUNDING}, interaction with @code{PREFERRED_STACK_BOUNDARY}
If @code{PUSH_ROUNDING} is not defined, the stack will always be aligned
-to the specified boundary. If @code{PUSH_ROUNDING} is defined and specifies a
-less strict alignment than @code{STACK_BOUNDARY}, the stack may be
-momentarily unaligned while pushing arguments.
+to the specified boundary. If @code{PUSH_ROUNDING} is defined and specifies
+a less strict alignment than @code{PREFERRED_STACK_BOUNDARY}, the stack may
+be momentarily unaligned while pushing arguments.
@findex FUNCTION_BOUNDARY
@item FUNCTION_BOUNDARY
@@ -864,6 +874,18 @@ The typical use of this macro is to increase alignment for string
constants to be word aligned so that @code{strcpy} calls that copy
constants can be done inline.
+@findex LOCAL_ALIGNMENT
+@item LOCAL_ALIGNMENT (@var{type}, @var{basic-align})
+If defined, a C expression to compute the alignment for a variables in
+the local store. @var{type} is the data type, and @var{basic-align} is
+the alignment that the object would ordinarily have. The value of this
+macro is used instead of that alignment to align the object.
+
+If this macro is not defined, then @var{basic-align} is used.
+
+One use of this macro is to increase alignment of medium-size data to
+make it all fit in fewer cache lines.
+
@findex EMPTY_FIELD_BOUNDARY
@item EMPTY_FIELD_BOUNDARY
Alignment in bits to be given to a structure bit field that follows an
@@ -957,18 +979,18 @@ Like PCC_BITFIELD_TYPE_MATTERS except that its effect is limited to
aligning a bitfield within the structure.
@findex ROUND_TYPE_SIZE
-@item ROUND_TYPE_SIZE (@var{struct}, @var{size}, @var{align})
-Define this macro as an expression for the overall size of a structure
-(given by @var{struct} as a tree node) when the size computed from the
-fields is @var{size} and the alignment is @var{align}.
+@item ROUND_TYPE_SIZE (@var{type}, @var{computed}, @var{specified})
+Define this macro as an expression for the overall size of a type
+(given by @var{type} as a tree node) when the size computed in the
+usual way is @var{computed} and the alignment is @var{specified}.
-The default is to round @var{size} up to a multiple of @var{align}.
+The default is to round @var{computed} up to a multiple of @var{specified}.
@findex ROUND_TYPE_ALIGN
-@item ROUND_TYPE_ALIGN (@var{struct}, @var{computed}, @var{specified})
-Define this macro as an expression for the alignment of a structure
-(given by @var{struct} as a tree node) if the alignment computed in the
-usual way is @var{computed} and the alignment explicitly specified was
+@item ROUND_TYPE_ALIGN (@var{type}, @var{computed}, @var{specified})
+Define this macro as an expression for the alignment of a type (given
+by @var{type} as a tree node) if the alignment computed in the usual
+way is @var{computed} and the alignment explicitly specified was
@var{specified}.
The default is to use @var{specified} if it is larger; otherwise, use
@@ -1333,13 +1355,32 @@ If a register has 0 in @code{CALL_USED_REGISTERS}, the compiler
automatically saves it on function entry and restores it on function
exit, if the register is used within the function.
+@findex HARD_REGNO_CALL_PART_CLOBBERED
+@item HARD_REGNO_CALL_PART_CLOBBERED (@var{regno}, @var{mode})
+@cindex call-used register
+@cindex call-clobbered register
+@cindex call-saved register
+A C expression that is non-zero if it is not permissible to store a
+value of mode @var{mode} in hard register number @var{regno} across a
+call without some part of it being clobbered. For most machines this
+macro need not be defined. It is only required for machines that do not
+preserve the entire contents of a register across a call.
+
@findex CONDITIONAL_REGISTER_USAGE
@findex fixed_regs
@findex call_used_regs
@item CONDITIONAL_REGISTER_USAGE
-Zero or more C statements that may conditionally modify two variables
-@code{fixed_regs} and @code{call_used_regs} (both of type @code{char
-[]}) after they have been initialized from the two preceding macros.
+Zero or more C statements that may conditionally modify four variables
+@code{fixed_regs}, @code{call_used_regs}, @code{global_regs}
+(these three are of type @code{char []}) and @code{reg_class_contents}
+(of type @code{HARD_REG_SET}).
+Before the macro is called @code{fixed_regs}, @code{call_used_regs}
+and @code{reg_class_contents} have been initialized from
+@code{FIXED_REGISTERS}, @code{CALL_USED_REGISTERS} and
+@code{REG_CLASS_CONTENTS}, respectively,
+@code{global_regs} has been cleared, and any @samp{-ffixed-@var{reg}},
+@samp{-fcall-used-@var{reg}} and @samp{-fcall-saved-@var{reg}} command
+options have been applied.
This is necessary in case the fixed or call-clobbered registers depend
on target flags.
@@ -1602,12 +1643,17 @@ treatment of leaf functions, and registers need to be renumbered to do
this.
@end table
-@findex leaf_function
+@findex current_function_is_leaf
+@findex current_function_uses_only_leaf_regs
Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
-treat leaf functions specially. It can test the C variable
-@code{leaf_function} which is nonzero for leaf functions. (The variable
-@code{leaf_function} is defined only if @code{LEAF_REGISTERS} is
-defined.)
+treat leaf functions specially. They can test the C variable
+@code{current_function_is_leaf} which is nonzero for leaf functions.
+@code{current_function_is_leaf} is set prior to local register allocation
+and is valid for the remaining compiler passes. They can also test the C
+variable @code{current_function_uses_only_leaf_regs} which is nonzero for
+leaf functions which only use leaf registers.
+@code{current_function_uses_only_leaf_regs} is valid after reload and is
+only useful if @code{LEAF_REGISTERS} is defined.
@c changed this to fix overfull. ALSO: why the "it" at the beginning
@c of the next paragraph?! --mew 2feb93
@@ -1673,24 +1719,6 @@ If this macro is not defined, it means that no insn clobbers registers
mysteriously. This is the usual situation; all else being equal,
it is best for the RTL expression to show all the activity.
-@cindex death notes
-@findex PRESERVE_DEATH_INFO_REGNO_P
-@item PRESERVE_DEATH_INFO_REGNO_P (@var{regno})
-If defined, this is a C expression whose value is nonzero if correct
-@code{REG_DEAD} notes are needed for hard register number @var{regno}
-after reload.
-
-You would arrange to preserve death info for a register when some of the
-code in the machine description which is executed to write the assembler
-code looks at the death notes. This is necessary only when the actual
-hardware feature which GNU CC thinks of as a register is not actually a
-register of the usual sort. (It might, for example, be a hardware
-stack.)
-
-It is also useful for peepholes and linker relaxation.
-
-If this macro is not defined, it means that no death notes need to be
-preserved, and some may even be incorrect. This is the usual situation.
@end table
@node Register Classes
@@ -2012,17 +2040,15 @@ is @code{BITS_PER_WORD} bits wide is correct for your machine.
@findex SMALL_REGISTER_CLASSES
@item SMALL_REGISTER_CLASSES
-Normally the compiler avoids choosing registers that have been
-explicitly mentioned in the rtl as spill registers (these registers are
-normally those used to pass parameters and return values). However,
-some machines have so few registers of certain classes that there
-would not be enough registers to use as spill registers if this were
-done.
+On some machines, it is risky to let hard registers live across arbitrary
+insns. Typically, these machines have instructions that require values
+to be in specific registers (like an accumulator), and reload will fail
+if the required hard register is used for another purpose across such an
+insn.
Define @code{SMALL_REGISTER_CLASSES} to be an expression with a non-zero
value on these machines. When this macro has a non-zero value, the
-compiler allows registers explicitly used in the rtl to be used as spill
-registers but avoids extending the lifetime of these registers.
+compiler will try to minimize the lifetime of hard registers.
It is always safe to define this macro with a non-zero value, but if you
unnecessarily define it, you will reduce the amount of optimizations
@@ -2277,6 +2303,17 @@ previous frame, just before the call instruction.
You only need to define this macro if you want to support call frame
debugging information like that provided by DWARF 2.
+
+@findex ARG_POINTER_CFA_OFFSET
+@item ARG_POINTER_CFA_OFFSET
+A C expression whose value is an integer giving the offset, in bytes,
+from the argument pointer to the canonical frame address (cfa). The
+final value should coincide with that calculated by
+@code{INCOMING_FRAME_SP_OFFSET}. Which is unfortunately not usable
+during virtual register instantiation.
+
+You only need to define this macro if you want to support call frame
+debugging information like that provided by DWARF 2.
@end table
@node Stack Checking
@@ -2620,7 +2657,8 @@ allocated for arguments even when their values are passed in
registers.
The value of this macro is the size, in bytes, of the area reserved for
-arguments passed in registers for the function represented by @var{fndecl}.
+arguments passed in registers for the function represented by @var{fndecl},
+which can be zero if GNU CC is calling a library function.
This space can be allocated by the caller, or be a part of the
machine-dependent stack frame: @code{OUTGOING_REG_PARM_STACK_SPACE} says
@@ -2750,13 +2788,16 @@ The value of the expression can also be a @code{parallel} RTX. This is
used when an argument is passed in multiple locations. The mode of the
of the @code{parallel} should be the mode of the entire argument. The
@code{parallel} holds any number of @code{expr_list} pairs; each one
-describes where part of the argument is passed. In each @code{expr_list},
-the first operand can be either a @code{reg} RTX for the hard register
-in which to pass this part of the argument, or zero to pass the argument
-on the stack. If this operand is a @code{reg}, then the mode indicates
-how large this part of the argument is. The second operand of the
-@code{expr_list} is a @code{const_int} which gives the offset in bytes
-into the entire argument where this part starts.
+describes where part of the argument is passed. In each
+@code{expr_list} the first operand must be a @code{reg} RTX for the hard
+register in which to pass this part of the argument, and the mode of the
+register RTX indicates how large this part of the argument is. The
+second operand of the @code{expr_list} is a @code{const_int} which gives
+the offset in bytes into the entire argument of where this part starts.
+As a special exception the first @code{expr_list} in the @code{parallel}
+RTX may have a first operand of zero. This indicates that the bytes
+starting from the second operand of that @code{expr_list} are stored on
+the stack and not held in a register.
@cindex @file{stdarg.h} and register arguments
The usual way to make the ANSI library @file{stdarg.h} work on a machine
@@ -3150,9 +3191,9 @@ must live across calls.
@item DEFAULT_CALLER_SAVES
Define this macro if function calls on the target machine do not preserve
any registers; in other words, if @code{CALL_USED_REGISTERS} has 1
-for all registers. This macro enables @samp{-fcaller-saves} by default.
-Eventually that option will be enabled by default on all machines and both
-the option and this macro will be eliminated.
+for all registers. When defined, this macro enables @samp{-fcaller-saves}
+by default for all optimization levels. It has no effect for optimization
+levels 2 and higher, where @samp{-fcaller-saves} is the default.
@findex CALLER_SAVE_PROFITABLE
@item CALLER_SAVE_PROFITABLE (@var{refs}, @var{calls})
@@ -3163,6 +3204,14 @@ this is worth doing, and 0 otherwise.
If you don't define this macro, a default is used which is good on most
machines: @code{4 * @var{calls} < @var{refs}}.
+
+@findex HARD_REGNO_CALLER_SAVE_MODE
+@item HARD_REGNO_CALLER_SAVE_MODE (@var{regno}, @var{nregs})
+A C expression specifying which mode is required for saving @var{nregs}
+of a pseudo-register in call-clobbered hard register @var{regno}. If
+@var{regno} is unsuitable for caller save, @code{VOIDmode} should be
+returned. For most machines this macro need not be defined since GCC
+will select the smallest suitable mode.
@end table
@node Function Entry
@@ -3256,7 +3305,7 @@ argument lists of the function. @xref{Stack Arguments}.
Normally, it is necessary for the macros @code{FUNCTION_PROLOGUE} and
@code{FUNCTION_EPILOGUE} to treat leaf functions specially. The C
-variable @code{leaf_function} is nonzero for such a function.
+variable @code{current_function_is_leaf} is nonzero for such a function.
@findex EXIT_IGNORE_STACK
@item EXIT_IGNORE_STACK
@@ -3306,8 +3355,8 @@ is wanted, the macro can refer to the variable
a function that needs a frame pointer.
Normally, @code{FUNCTION_PROLOGUE} and @code{FUNCTION_EPILOGUE} must
-treat leaf functions specially. The C variable @code{leaf_function} is
-nonzero for such a function. @xref{Leaf Functions}.
+treat leaf functions specially. The C variable @code{current_function_is_leaf}
+is nonzero for such a function. @xref{Leaf Functions}.
On some machines, some functions pop their arguments on exit while
others leave that for the caller to do. For example, the 68020 when
@@ -3699,11 +3748,8 @@ that were passed to @code{__builtin_saveregs}.
If this macro is not defined, the compiler will output an ordinary
call to the library function @samp{__builtin_saveregs}.
-@c !!! a bug in texinfo; how to make the entry on the @item line allow
-@c more than one line of text... help... --mew 10feb93
@findex SETUP_INCOMING_VARARGS
-@item SETUP_INCOMING_VARARGS (@var{args_so_far}, @var{mode}, @var{type},
-@var{pretend_args_size}, @var{second_time})
+@item SETUP_INCOMING_VARARGS (@var{args_so_far}, @var{mode}, @var{type}, @var{pretend_args_size}, @var{second_time})
This macro offers an alternative to using @code{__builtin_saveregs} and
defining the macro @code{EXPAND_BUILTIN_SAVEREGS}. Use it to store the
anonymous register arguments into the stack so that all the arguments
@@ -3749,6 +3795,15 @@ are treated as named. Otherwise, all named arguments except the last
are treated as named.
You need not define this macro if it always returns zero.
+
+@findex PRETEND_OUTGOING_VARARGS_NAMED
+@item PRETEND_OUTGOING_VARARGS_NAMED
+If you need to conditionally change ABIs so that one works with
+@code{SETUP_INCOMING_VARARGS}, but the other works like neither
+@code{SETUP_INCOMING_VARARGS} nor @code{STRICT_ARGUMENT_NAMING} was
+defined, then define this macro to return nonzero if
+@code{SETUP_INCOMING_VARARGS} is used, zero otherwise.
+Otherwise, you should not define this macro.
@end table
@node Trampolines
@@ -4135,7 +4190,7 @@ This is about addressing modes.
@table @code
@findex HAVE_POST_INCREMENT
@item HAVE_POST_INCREMENT
-Define this macro if the machine supports post-increment addressing.
+A C expression that is nonzero the machine supports post-increment addressing.
@findex HAVE_PRE_INCREMENT
@findex HAVE_POST_DECREMENT
@@ -4362,16 +4417,6 @@ an immediate operand on the target machine. You can assume that
@var{x} satisfies @code{CONSTANT_P}, so you need not check this. In fact,
@samp{1} is a suitable definition for this macro on machines where
anything @code{CONSTANT_P} is valid.@refill
-
-@findex DONT_RECORD_EQUIVALENCE
-@item DONT_RECORD_EQUIVALENCE (@var{note})
-A C expression that is nonzero if the @code{REG_EQUAL} note @var{x} should not
-be promoted to a @code{REG_EQUIV} note.
-
-Define this macro if @var{note} refers to a constant that must be accepted
-by @code{LEGITIMATE_CONSTANT_P}, but must not appear as an immediate operand.
-
-Most machine descriptions do not need to define this macro.
@end table
@node Condition Code
@@ -4727,12 +4772,76 @@ than good.)
@findex MOVE_RATIO
@item MOVE_RATIO
-The number of scalar move insns which should be generated instead of a
+The threshold of number of scalar memory-to-memory move insns, @emph{below}
+which a sequence of insns should be generated instead of a
string move insn or a library call. Increasing the value will always
make code faster, but eventually incurs high cost in increased code size.
+Note that on machines with no memory-to-memory move insns, this macro denotes
+the corresponding number of memory-to-memory @emph{sequences}.
+
If you don't define this, a reasonable default is used.
+@findex MOVE_BY_PIECES_P
+@item MOVE_BY_PIECES_P (@var{size}, @var{alignment})
+A C expression used to determine whether @code{move_by_pieces} will be used to
+copy a chunk of memory, or whether some other block move mechanism
+will be used. Defaults to 1 if @code{move_by_pieces_ninsns} returns less
+than @code{MOVE_RATIO}.
+
+@findex MOVE_MAX_PIECES
+@item MOVE_MAX_PIECES
+A C expression used by @code{move_by_pieces} to determine the largest unit
+a load or store used to copy memory is. Defaults to @code{MOVE_MAX}.
+
+@findex USE_LOAD_POST_INCREMENT
+@item USE_LOAD_POST_INCREMENT (@var{mode})
+A C expression used to determine whether a load postincrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_POST_INCREMENT}.
+
+@findex USE_LOAD_POST_DECREMENT
+@item USE_LOAD_POST_DECREMENT (@var{mode})
+A C expression used to determine whether a load postdecrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_POST_DECREMENT}.
+
+@findex USE_LOAD_PRE_INCREMENT
+@item USE_LOAD_PRE_INCREMENT (@var{mode})
+A C expression used to determine whether a load preincrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_PRE_INCREMENT}.
+
+@findex USE_LOAD_PRE_DECREMENT
+@item USE_LOAD_PRE_DECREMENT (@var{mode})
+A C expression used to determine whether a load predecrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_PRE_DECREMENT}.
+
+@findex USE_STORE_POST_INCREMENT
+@item USE_STORE_POST_INCREMENT (@var{mode})
+A C expression used to determine whether a store postincrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_POST_INCREMENT}.
+
+@findex USE_STORE_POST_DECREMENT
+@item USE_STORE_POST_DECREMENT (@var{mode})
+A C expression used to determine whether a store postdeccrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_POST_DECREMENT}.
+
+@findex USE_STORE_PRE_INCREMENT
+@item USE_STORE_PRE_INCREMENT (@var{mode})
+This macro is used to determine whether a store preincrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_PRE_INCREMENT}.
+
+@findex USE_STORE_PRE_DECREMENT
+@item USE_STORE_PRE_DECREMENT (@var{mode})
+This macro is used to determine whether a store predecrement is a good
+thing to use for a given mode. Defaults to the value of
+@code{HAVE_PRE_DECREMENT}.
+
@findex NO_FUNCTION_CSE
@item NO_FUNCTION_CSE
Define this macro if it is as good or better to call a constant
@@ -4952,7 +5061,7 @@ necessary).
@item PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
Define this macro if the register defined by
@code{PIC_OFFSET_TABLE_REGNUM} is clobbered by calls. Do not define
-this macro if @code{PPIC_OFFSET_TABLE_REGNUM} is not defined.
+this macro if @code{PIC_OFFSET_TABLE_REGNUM} is not defined.
@findex FINALIZE_PIC
@item FINALIZE_PIC
@@ -6366,6 +6475,14 @@ section.
A C statement to output to the stdio stream @var{stream} an assembler
command to advance the location counter to a multiple of 2 to the
@var{power} bytes. @var{power} will be a C expression of type @code{int}.
+
+@findex ASM_OUTPUT_MAX_SKIP_ALIGN
+@item ASM_OUTPUT_MAX_SKIP_ALIGN (@var{stream}, @var{power}, @var{max_skip})
+A C statement to output to the stdio stream @var{stream} an assembler
+command to advance the location counter to a multiple of 2 to the
+@var{power} bytes, but only if @var{max_skip} or fewer bytes are needed to
+satisfy the alignment request. @var{power} and @var{max_skip} will be
+a C expression of type @code{int}.
@end table
@need 3000
@@ -7038,7 +7155,7 @@ when the minimum and maximum offset are known. If you define this,
it enables extra code in branch shortening to deal with @code{addr_diff_vec}.
To make this work, you also have to define INSN_ALIGN and
make the alignment for @code{addr_diff_vec} explicit.
-The @var{body} argument is provided so that teh offset_unsigned and scale
+The @var{body} argument is provided so that the offset_unsigned and scale
flags can be updated.
@findex CASE_VECTOR_PC_RELATIVE
@@ -7318,18 +7435,63 @@ C++, which is to pretend that the file's contents are enclosed in
@findex HANDLE_PRAGMA
@findex #pragma
@findex pragma
-@item HANDLE_PRAGMA (@var{stream}, @var{node})
+@item HANDLE_PRAGMA (@var{getc}, @var{ungetc}, @var{name})
Define this macro if you want to implement any pragmas. If defined, it
-is a C expression whose value is 1 if the pragma was handled by the function.
-The argument @var{stream} is the stdio input stream from which the source text
-can be read. @var{node} is the tree node for the identifier after the
-@code{#pragma}.
+is a C expression whose value is 1 if the pragma was handled by the
+macro, zero otherwise. The argument @var{getc} is a function of type
+@samp{int (*)(void)} which will return the next character in the input
+stream, or EOF if no characters are left. The argument @var{ungetc} is
+a function of type @samp{void (*)(int)} which will push a character back
+into the input stream. The argument @var{name} is the word following
+#pragma in the input stream. The input stream pointer will be pointing
+just beyond the end of this word. The input stream should be left
+undistrubed if the expression returns zero, otherwise it should be
+pointing at the next character after the end of the pragma. Any
+characters remaining on the line will be ignored.
It is generally a bad idea to implement new uses of @code{#pragma}. The
only reason to define this macro is for compatibility with other
compilers that do support @code{#pragma} for the sake of any user
programs which already use it.
+If the pragma can be implemented by atttributes then the macro
+@samp{INSERT_ATTRIBUTES} might be a useful one to define as well.
+
+Note: older versions of this macro only had two arguments: @var{stream}
+and @var{token}. The macro was changed in order to allow it to work
+when gcc is built both with and without a cpp library.
+
+@findex HANDLE_SYSV_PRAGMA
+@findex #pragma
+@findex pragma
+@item HANDLE_SYSV_PRAGMA
+Define this macro (to a value of 1) if you want the System V style
+pragmas @samp{#pragma pack(<n>)} and @samp{#pragma weak <name>
+[=<value>]} to be supported by gcc.
+
+The pack pragma specifies the maximum alignment (in bytes) of fields
+within a structure, in much the same way as the @samp{__aligned__} and
+@samp{__packed__} @code{__attribute__}s do. A pack value of zero resets
+the behaviour to the default.
+
+The weak pragma only works if @code{SUPPORTS_WEAK} and
+@code{ASM_WEAKEN_LABEL} are defined. If enabled it allows the creation
+of specifically named weak labels, optionally with a value.
+
+@findex HANDLE_PRAGMA_PACK_PUSH_POP
+@findex #pragma
+@findex pragma
+@item HANDLE_PRAGMA_PACK_PUSH_POP
+Define this macro (to a value of 1) if you want to support the Win32
+style pragmas @samp{#pragma pack(push,<n>)} and @samp{#pragma
+pack(pop)}. The pack(push,<n>) pragma specifies the maximum alignment
+(in bytes) of fields within a structure, in much the same way as the
+@samp{__aligned__} and @samp{__packed__} @code{__attribute__}s do. A
+pack value of zero resets the behaviour to the default. Successive
+invocations of this pragma cause the previous values to be stacked, so
+that invocations of @samp{#pragma pack(pop)} will return to the previous
+value.
+
@findex VALID_MACHINE_DECL_ATTRIBUTE
@item VALID_MACHINE_DECL_ATTRIBUTE (@var{decl}, @var{attributes}, @var{identifier}, @var{args})
If defined, a C expression whose value is nonzero if @var{identifier} with
@@ -7370,6 +7532,17 @@ of @var{olddecl}. Examples of when this is needed are when one attribute
overrides another, or when an attribute is nullified by a subsequent
definition.
+@findex INSERT_ATTRIBUTES
+@item INSERT_ATTRIBUTES (@var{node}, @var{attr_ptr}, @var{prefix_ptr})
+Define this macro if you want to be able to add attributes to a decl
+when it is being created. This is normally useful for backends which
+wish to implement a pragma by using the attributes which correspond to
+the pragma's effect. The @var{node} argument is the decl which is being
+created. The @var{attr_ptr} argument is a pointer to the attribute list
+for this decl. The @var{prefix_ptr} is a pointer to the list of
+attributes that have appeared after the specifiers and modifiers of the
+declaration, but before the declaration proper.
+
@findex SET_DEFAULT_DECL_ATTRIBUTES
@item SET_DEFAULT_DECL_ATTRIBUTES (@var{decl}, @var{attributes})
If defined, a C statement that assigns default attributes to
@@ -7461,15 +7634,6 @@ unit may not be bound to undefined symbols in another translation unit
without user intervention. For instance, under Microsoft Windows
symbols must be explicitly imported from shared libraries (DLLs).
-@findex GIV_SORT_CRITERION
-@item GIV_SORT_CRITERION (@var{giv1}, @var{giv2})
-In some cases, the strength reduction optimization pass can produce better
-code if this is defined. This macro controls the order that induction
-variables are combined. This macro is particularly useful if the target has
-limited addressing modes. For instance, the SH target has only positive
-offsets in addresses. Thus sorting to put the smallest address first
-allows the most combinations to be found.
-
@findex ISSUE_RATE
@item ISSUE_RATE
A C expression that returns how many instructions can be issued at the
@@ -7477,7 +7641,7 @@ same time if the machine is a superscalar machine. This is only used by
the @samp{Haifa} scheduler, and not the traditional scheduler.
@findex MD_SCHED_INIT
-@item MD_SCHED_INIT (@var{file}, @var{verbose}
+@item MD_SCHED_INIT (@var{file}, @var{verbose})
A C statement which is executed by the @samp{Haifa} scheduler at the
beginning of each block of instructions that are to be scheduled.
@var{file} is either a null pointer, or a stdio stream to write any
@@ -7517,12 +7681,11 @@ You need only define this macro if the target holds values larger than
@code{word_mode} in general purpose registers. Most targets should not define
this macro.
-@findex NEED_MATH_LIBRARY
-@item NEED_MATH_LIBRARY
-Define this macro as a C expression that is nonzero if @code{g++} should
-automatically link in the math library or to zero if @code{g++} should not
-automatically link in the math library.
+@findex MATH_LIBRARY
+@item MATH_LIBRARY
+Define this macro as a C string constant for the linker argument to link
+in the system math library, or @samp{""} if the target does not have a
+separate math library.
-You need only define this macro if the target does not always need the math
-library linked into C++ programs.
+You need only define this macro if the default of @samp{"-lm"} is wrong.
@end table
diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c
index 497359e..1822930 100644
--- a/contrib/gcc/toplev.c
+++ b/contrib/gcc/toplev.c
@@ -1,5 +1,5 @@
/* Top level of GNU C compiler
- Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,17 +24,11 @@ Boston, MA 02111-1307, USA. */
Error messages and low-level interface to malloc also handled here. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#undef FLOAT /* This is for hpux. They should change hpux. */
#undef FFS /* Some systems define this in param.h. */
#include "system.h"
#include <signal.h>
#include <setjmp.h>
-#include <sys/stat.h>
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
@@ -56,6 +50,9 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
+#include "expr.h"
+#include "basic-block.h"
+#include "intl.h"
#ifdef DWARF_DEBUGGING_INFO
#include "dwarfout.h"
@@ -135,6 +132,10 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
#endif
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
extern int rtx_equal_function_value_matters;
#if ! (defined (VMS) || defined (OS2))
@@ -167,53 +168,68 @@ extern void print_rtl ();
extern void print_rtl_with_bb ();
void rest_of_decl_compilation ();
-void error_with_file_and_line PVPROTO((char *file, int line, char *s, ...));
-void error_with_decl PVPROTO((tree decl, char *s, ...));
-void error PVPROTO((char *s, ...));
-void fatal PVPROTO((char *s, ...));
-void warning_with_file_and_line PVPROTO((char *file, int line, char *s, ...));
-void warning_with_decl PVPROTO((tree decl, char *s, ...));
-void warning PVPROTO((char *s, ...));
-void pedwarn PVPROTO((char *s, ...));
-void pedwarn_with_decl PVPROTO((tree decl, char *s, ...));
-void pedwarn_with_file_and_line PVPROTO((char *file, int line, char *s, ...));
-void sorry PVPROTO((char *s, ...));
-void really_sorry PVPROTO((char *s, ...));
-void fancy_abort ();
-void set_target_switch ();
+void error_with_file_and_line PVPROTO((const char *file,
+ int line, const char *s, ...));
+void error_with_decl PVPROTO((tree decl, const char *s, ...));
+void error_for_asm PVPROTO((rtx insn, const char *s, ...));
+void notice PVPROTO((const char *s, ...));
+void error PVPROTO((const char *s, ...));
+void fatal PVPROTO((const char *s, ...));
+void warning_with_file_and_line PVPROTO((const char *file,
+ int line, const char *s, ...));
+void warning_with_decl PVPROTO((tree decl, const char *s, ...));
+void warning PVPROTO((const char *s, ...));
+void pedwarn PVPROTO((const char *s, ...));
+void pedwarn_with_decl PVPROTO((tree decl, const char *s, ...));
+void pedwarn_with_file_and_line PVPROTO((const char *file,
+ int line, const char *s, ...));
+void sorry PVPROTO((const char *s, ...));
+static void set_target_switch PROTO((const char *));
static char *decl_name PROTO((tree, int));
-static void vmessage PROTO((char *, char *, va_list));
-static void v_message_with_file_and_line PROTO((char *, int, char *,
- char *, va_list));
-static void v_message_with_decl PROTO((tree, char *, char *, va_list));
+static void vmessage PROTO((const char *, const char *, va_list));
+static void v_message_with_file_and_line PROTO((const char *, int, int,
+ const char *, va_list));
+static void v_message_with_decl PROTO((tree, int, const char *, va_list));
static void file_and_line_for_asm PROTO((rtx, char **, int *));
-static void v_error_with_file_and_line PROTO((char *, int, char *, va_list));
-static void v_error_with_decl PROTO((tree, char *, va_list));
-static void v_error_for_asm PROTO((rtx, char *, va_list));
-static void verror PROTO((char *, va_list));
-static void vfatal PROTO((char *, va_list));
-static void v_warning_with_file_and_line PROTO ((char *, int, char *, va_list));
-static void v_warning_with_decl PROTO((tree, char *, va_list));
-static void v_warning_for_asm PROTO((rtx, char *, va_list));
-static void vwarning PROTO((char *, va_list));
-static void vpedwarn PROTO((char *, va_list));
-static void v_pedwarn_with_decl PROTO((tree, char *, va_list));
-static void v_pedwarn_with_file_and_line PROTO((char *, int, char *, va_list));
-static void vsorry PROTO((char *, va_list));
-static void v_really_sorry PROTO((char *, va_list));
-static void float_signal PROTO((int));
-static void pipe_closed PROTO((int));
-static void output_lang_identify PROTO((FILE *));
-static void open_dump_file PROTO((char *, char *));
+static void v_error_with_file_and_line PROTO((const char *, int,
+ const char *, va_list));
+static void v_error_with_decl PROTO((tree, const char *, va_list));
+static void v_error_for_asm PROTO((rtx, const char *, va_list));
+static void verror PROTO((const char *, va_list));
+static void vfatal PROTO((const char *, va_list)) ATTRIBUTE_NORETURN;
+static void v_warning_with_file_and_line PROTO ((const char *, int,
+ const char *, va_list));
+static void v_warning_with_decl PROTO((tree, const char *, va_list));
+static void v_warning_for_asm PROTO((rtx, const char *, va_list));
+static void vwarning PROTO((const char *, va_list));
+static void vpedwarn PROTO((const char *, va_list));
+static void v_pedwarn_with_decl PROTO((tree, const char *, va_list));
+static void v_pedwarn_with_file_and_line PROTO((const char *, int,
+ const char *, va_list));
+static void vsorry PROTO((const char *, va_list));
+static void float_signal PROTO((int)) ATTRIBUTE_NORETURN;
+static void pipe_closed PROTO((int)) ATTRIBUTE_NORETURN;
+#ifdef ASM_IDENTIFY_LANGUAGE
+/* This might or might not be used in ASM_IDENTIFY_LANGUAGE. */
+static void output_lang_identify PROTO((FILE *)) ATTRIBUTE_UNUSED;
+#endif
+static void open_dump_file PROTO((const char *, const char *));
static void close_dump_file PROTO((void (*) (FILE *, rtx), rtx));
-static void dump_rtl PROTO((char *, tree, void (*) (FILE *, rtx), rtx));
-static void clean_dump_file PROTO((char *));
+static void dump_rtl PROTO((const char *, tree, void (*) (FILE *, rtx), rtx));
+static void clean_dump_file PROTO((const char *));
static void compile_file PROTO((char *));
static void display_help PROTO ((void));
-void print_version ();
-int print_single_switch ();
-void print_switch_values ();
+static void print_version PROTO((FILE *, const char *));
+static int print_single_switch PROTO((FILE *, int, int, const char *,
+ const char *, const char *,
+ const char *, const char *));
+static void print_switch_values PROTO((FILE *, int, int, const char *,
+ const char *, const char *));
+
+void print_rtl_graph_with_bb PROTO ((const char *, const char *, rtx));
+void clean_graph_dump_file PROTO ((const char *, const char *));
+void finish_graph_dump_file PROTO ((const char *, const char *));
/* Length of line when printing switch values. */
#define MAX_LINE 75
@@ -240,6 +256,9 @@ char *main_input_filename;
int lineno;
+/* Nonzero if it is unsafe to create any new pseudo registers. */
+int no_new_pseudos;
+
/* Stack of currently pending input files. */
struct file_stack *input_file_stack;
@@ -253,7 +272,7 @@ extern tree current_function_decl;
/* Name to use as base of names for dump output files. */
-char *dump_base_name;
+const char *dump_base_name;
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
@@ -278,6 +297,7 @@ int regmove_dump = 0;
int sched_dump = 0;
int local_reg_dump = 0;
int global_reg_dump = 0;
+int flow2_dump = 0;
int sched2_dump = 0;
int jump2_opt_dump = 0;
#ifdef DELAY_SLOTS
@@ -290,6 +310,7 @@ int stack_reg_dump = 0;
#ifdef MACHINE_DEPENDENT_REORG
int mach_dep_reorg_dump = 0;
#endif
+enum graph_dump_types graph_dump_format;
/* Name for output file of assembly code, specified with -o. */
@@ -344,20 +365,22 @@ int sorrycount = 0;
2: and any other information that might be interesting, such as function
parameter types in C++. */
-char *(*decl_printable_name) (/* tree decl, int verbosity */);
+char *(*decl_printable_name) PROTO ((tree, int));
/* Pointer to function to compute rtl for a language-specific tree code. */
-struct rtx_def *(*lang_expand_expr) ();
+typedef rtx (*lang_expand_expr_t)
+ PROTO ((union tree_node *, rtx, enum machine_mode,
+ enum expand_modifier modifier));
-/* Pointer to function to finish handling an incomplete decl at the
- end of compilation. */
+lang_expand_expr_t lang_expand_expr = 0;
-void (*incomplete_decl_finalize_hook) () = 0;
+tree (*lang_expand_constant) PROTO((tree)) = 0;
-/* Highest label number used at the end of reload. */
+/* Pointer to function to finish handling an incomplete decl at the
+ end of compilation. */
-int max_label_num_after_reload;
+void (*incomplete_decl_finalize_hook) PROTO((tree)) = 0;
/* Nonzero if generating code to do profiling. */
@@ -522,6 +545,10 @@ int flag_omit_frame_pointer = 0;
int flag_function_sections = 0;
+/* ... and similar for data. */
+
+int flag_data_sections = 0;
+
/* Nonzero to inhibit use of define_optimization peephole opts. */
int flag_no_peephole = 0;
@@ -533,14 +560,29 @@ int flag_no_peephole = 0;
int flag_fast_math = 0;
+/* Nonzero means the front end generally wants `errno' maintained by math
+ operations, like built-in SQRT, unless overridden by flag_fast_math. */
+
+int flag_errno_math = 1;
+
+/* 0 means straightforward implementation of complex divide acceptable.
+ 1 means wide ranges of inputs must work for complex divide.
+ 2 means C9X-like requirements for complex divide (not yet implemented). */
+
+int flag_complex_divide_method = 0;
+
/* Nonzero means all references through pointers are volatile. */
int flag_volatile;
-/* Nonzero means treat all global and extern variables as global. */
+/* Nonzero means treat all global and extern variables as volatile. */
int flag_volatile_global;
+/* Nonzero means treat all static variables as volatile. */
+
+int flag_volatile_static;
+
/* Nonzero means just do syntax checking; don't output anything. */
int flag_syntax_only = 0;
@@ -554,11 +596,6 @@ static int flag_gcse;
static int flag_rerun_cse_after_loop;
-/* Nonzero means to assume that a structure or an array reference at
- a varying address cannot alias a scalar at a fixed address. */
-
-int flag_structure_noalias = 0;
-
/* Nonzero means to run loop optimizations twice. */
int flag_rerun_loop_opt;
@@ -655,12 +692,11 @@ int flag_schedule_interblock = 1;
int flag_schedule_speculative = 1;
int flag_schedule_speculative_load = 0;
int flag_schedule_speculative_load_dangerous = 0;
+#endif /* HAIFA */
/* flag_on_branch_count_reg means try to replace add-1,compare,branch tupple
by a cheaper branch, on a count register. */
int flag_branch_on_count_reg;
-#endif /* HAIFA */
-
/* -finhibit-size-directive inhibits output of .size for ELF.
This is used only for compiling crtstuff.c,
@@ -726,18 +762,24 @@ int flag_argument_noalias = 0;
if alias analysis (in general) is enabled. */
int flag_strict_aliasing = 0;
-extern int flag_dump_unnumbered;
+/* Instrument functions with calls at entry and exit, for profiling. */
+int flag_instrument_function_entry_exit = 0;
+/* Nonzero means ignore `#ident' directives. 0 means handle them.
+ On SVR4 targets, it also controls whether or not to emit a
+ string identifying the compiler. */
+
+int flag_no_ident = 0;
/* Table of supported debugging formats. */
static struct
{
- char * arg;
+ const char * arg;
/* Since PREFERRED_DEBUGGING_TYPE isn't necessarily a
constant expression, we use NO_DEBUG in its place. */
enum debug_info_type debug_type;
int use_extensions_p;
- char * description;
+ const char * description;
} *da,
debug_args[] =
{
@@ -763,18 +805,29 @@ debug_args[] =
#ifdef SDB_DEBUGGING_INFO
{ "gcoff", SDB_DEBUG, 0, "Generate COFF format debug output" },
#endif
- { 0, 0, 0 }
+ { 0, 0, 0, 0 }
};
typedef struct
{
- char * string;
+ const char * string;
int * variable;
int on_value;
- char * description;
+ const char * description;
}
lang_independent_options;
+/* Add or remove a leading underscore from user symbols. */
+int flag_leading_underscore = -1;
+
+/* The user symbol prefix after having resolved same. */
+const char *user_label_prefix;
+
+/* A default for same. */
+#ifndef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#endif
+
/* Table of language-independent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
@@ -789,6 +842,8 @@ lang_independent_options f_options[] =
"Consider all mem refs through pointers as volatile"},
{"volatile-global", &flag_volatile_global, 1,
"Consider all mem refs to global data to be volatile" },
+ {"volatile-static", &flag_volatile_static, 1,
+ "Consider all mem refs to static data to be volatile" },
{"defer-pop", &flag_defer_pop, 1,
"Defer popping functions args from stack until later" },
{"omit-frame-pointer", &flag_omit_frame_pointer, 1,
@@ -804,9 +859,9 @@ lang_independent_options f_options[] =
{"strength-reduce", &flag_strength_reduce, 1,
"Perform strength reduction optimisations" },
{"unroll-loops", &flag_unroll_loops, 1,
- "Perform loop unrolling when interation count is known" },
+ "Perform loop unrolling when iteration count is known" },
{"unroll-all-loops", &flag_unroll_all_loops, 1,
- "Perofm loop onrolling for all loops" },
+ "Perform loop unrolling for all loops" },
{"move-all-movables", &flag_move_all_movables, 1,
"Force all loop invariant computations out of loops" },
{"reduce-all-givs", &flag_reduce_all_givs, 1,
@@ -845,8 +900,6 @@ lang_independent_options f_options[] =
"Perform the global common subexpression elimination" },
{"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1,
"Run CSE pass after loop optimisations"},
- {"structure-noalias", &flag_structure_noalias, 1,
- "Assume structure / array reference and fixed scalar cannot alias"},
{"rerun-loop-opt", &flag_rerun_loop_opt, 1,
"Run the loop optimiser twice"},
{"pretend-float", &flag_pretend_float, 1,
@@ -864,9 +917,9 @@ lang_independent_options f_options[] =
"Allow speculative motion of some loads" },
{"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1,
"Allow speculative motion of more loads" },
+#endif /* HAIFA */
{"branch-count-reg",&flag_branch_on_count_reg, 1,
"Replace add,compare,branch with branch on count reg"},
-#endif /* HAIFA */
{"pic", &flag_pic, 1,
"Generate position independent code, if possible"},
{"PIC", &flag_pic, 2, ""},
@@ -883,7 +936,7 @@ lang_independent_options f_options[] =
{"test-coverage", &flag_test_coverage, 1,
"Create data files needed by gcov" },
{"branch-probabilities", &flag_branch_probabilities, 1,
- "Use profiling information for branch porbabilities" },
+ "Use profiling information for branch probabilities" },
{"fast-math", &flag_fast_math, 1,
"Improve FP speed by violating ANSI & IEEE rules" },
{"common", &flag_no_common, 0,
@@ -892,13 +945,16 @@ lang_independent_options f_options[] =
"Do not generate .size directives" },
{"function-sections", &flag_function_sections, 1,
"place each function into its own section" },
+ {"data-sections", &flag_data_sections, 1,
+ "place data items into their own section" },
{"verbose-asm", &flag_verbose_asm, 1,
"Add extra commentry to assembler output"},
{"gnu-linker", &flag_gnu_linker, 1,
"Output GNU ld formatted global initialisers"},
{"regmove", &flag_regmove, 1,
- "Enables a regoster move optimisation"},
- {"optimize-register-move", &flag_regmove, 1},
+ "Enables a register move optimisation"},
+ {"optimize-register-move", &flag_regmove, 1,
+ "Do the full regmove optimization pass"},
{"pack-struct", &flag_pack_struct, 1,
"Pack structure members together without holes" },
{"stack-check", &flag_stack_check, 1,
@@ -915,7 +971,14 @@ lang_independent_options f_options[] =
"Generate code to check every memory access" },
{"prefix-function-name", &flag_prefix_function_name, 1,
"Add a prefix to all function names" },
- {"dump-unnumbered", &flag_dump_unnumbered, 1}
+ {"dump-unnumbered", &flag_dump_unnumbered, 1,
+ "Suppress output of instruction numbers and line number notes in debugging dumps"},
+ {"instrument-functions", &flag_instrument_function_entry_exit, 1,
+ "Instrument function entry/exit with profiling calls"},
+ {"leading-underscore", &flag_leading_underscore, 1,
+ "External symbols have a leading underscore" },
+ {"ident", &flag_no_ident, 0,
+ "Process #ident directives"}
};
#define NUM_ELEM(a) (sizeof (a) / sizeof ((a)[0]))
@@ -924,8 +987,8 @@ lang_independent_options f_options[] =
static struct lang_opt
{
- char * option;
- char * description;
+ const char * option;
+ const char * description;
}
documented_lang_options[] =
{
@@ -936,6 +999,7 @@ documented_lang_options[] =
{ "-ansi", "Compile just for ANSI C" },
{ "-fallow-single-precision",
"Do not promote floats to double if using -traditional" },
+ { "-std= ", "Determine language standard"},
{ "-fsigned-bitfields", "" },
{ "-funsigned-bitfields","Make bitfields by unsigned by default" },
@@ -962,10 +1026,8 @@ documented_lang_options[] =
{ "-fno-freestanding", "" },
{ "-fcond-mismatch", "Allow different types as args of ? operator"},
{ "-fno-cond-mismatch", "" },
- { "-fdollars-in-identifiers", "Allow the use of $ inside indentifiers" },
+ { "-fdollars-in-identifiers", "Allow the use of $ inside identifiers" },
{ "-fno-dollars-in-identifiers", "" },
- { "-fident", "" },
- { "-fno-ident", "Ignore #ident directives" },
{ "-fshort-double", "Use the same size for double as for float" },
{ "-fno-short-double", "" },
{ "-fshort-enums", "Use the smallest fitting integer to hold enums"},
@@ -975,14 +1037,17 @@ documented_lang_options[] =
{ "-Wbad-function-cast",
"Warn about casting functions to incompatible types" },
{ "-Wno-bad-function-cast", "" },
+ { "-Wmissing-noreturn",
+ "Warn about functions which might be candidates for attribute noreturn" },
+ { "-Wno-missing-noreturn", "" },
{ "-Wcast-qual", "Warn about casts which discard qualifiers"},
{ "-Wno-cast-qual", "" },
- { "-Wchar-subscripts", "Warn about subscripts whoes type is 'char'"},
+ { "-Wchar-subscripts", "Warn about subscripts whose type is 'char'"},
{ "-Wno-char-subscripts", "" },
{ "-Wcomment", "Warn if nested comments are detected" },
- { "-Wno-comment", },
- { "-Wcomments", },
- { "-Wno-comments", },
+ { "-Wno-comment", "" },
+ { "-Wcomments", "Warn if nested comments are detected" },
+ { "-Wno-comments", "" },
{ "-Wconversion", "Warn about possibly confusing type conversions" },
{ "-Wno-conversion", "" },
{ "-Wformat", "Warn about printf format anomalies" },
@@ -1026,7 +1091,7 @@ documented_lang_options[] =
{ "-Wno-unknown-pragmas", "" },
{ "-Wstrict-prototypes", "Warn about non-prototyped function decls" },
{ "-Wno-strict-prototypes", "" },
- { "-Wtraditional", "Warn about constructs whoes meaning change in ANSI C"},
+ { "-Wtraditional", "Warn about constructs whose meaning change in ANSI C"},
{ "-Wno-traditional", "" },
{ "-Wtrigraphs", "Warn when trigraphs are encountered" },
{ "-Wno-trigraphs", "" },
@@ -1041,18 +1106,29 @@ documented_lang_options[] =
{ "-A", "" },
{ "-D", "" },
{ "-I", "" },
+#if USE_CPPLIB
+ { "-MD", "Print dependencies to FILE.d" },
+ { "-MMD", "Print dependencies to FILE.d" },
+ { "-M", "Print dependencies to stdout" },
+ { "-MM", "Print dependencies to stdout" },
+#endif /* USE_CPPLIB */
{ "-U", "" },
+ { "-H", "" },
{ "-idirafter", "" },
+ { "-imacros", "" },
+ { "-include", "" },
{ "-iprefix", "" },
{ "-isystem", "" },
+ { "-iwithprefix", "" },
+ { "-iwithprefixbefore", "" },
{ "-lang-c", "" },
{ "-lang-c89", "" },
{ "-lang-c++", "" },
+ { "-remap", "" },
{ "-nostdinc", "" },
{ "-nostdinc++", "" },
{ "-trigraphs", "" },
{ "-undef", "" },
- { "-remap", "" },
#define DEFINE_LANG_NAME(NAME) { NULL, NAME },
@@ -1061,7 +1137,7 @@ documented_lang_options[] =
{ "-lang-objc", "" },
{ "-gen-decls", "Dump decls to a .decl file" },
- { "-fgnu-runtime", "Generate code for GNU runtime envrionment" },
+ { "-fgnu-runtime", "Generate code for GNU runtime environment" },
{ "-fno-gnu-runtime", "" },
{ "-fnext-runtime", "Generate code for NeXT runtime environment" },
{ "-fno-next-runtime", "" },
@@ -1084,9 +1160,9 @@ documented_lang_options[] =
struct
{
- char * name;
+ const char * name;
int value;
- char * description;
+ const char * description;
}
target_switches [] = TARGET_SWITCHES;
@@ -1095,9 +1171,9 @@ target_switches [] = TARGET_SWITCHES;
#ifdef TARGET_OPTIONS
struct
{
- char * prefix;
- char ** variable;
- char * description;
+ const char * prefix;
+ const char ** variable;
+ const char * description;
}
target_options [] = TARGET_OPTIONS;
#endif
@@ -1191,6 +1267,38 @@ FILE *asm_out_file;
FILE *aux_info_file;
FILE *rtl_dump_file = NULL;
+/* Decode the string P as an integral parameter.
+ If the string is indeed an integer return its numeric value else
+ issue an Invalid Option error for the option PNAME and return DEFVAL.
+ If PNAME is zero just return DEFVAL, do not call error. */
+
+int
+read_integral_parameter (p, pname, defval)
+ const char *p;
+ const char *pname;
+ const int defval;
+{
+ const char *endp = p;
+
+ while (*endp)
+ {
+ if (*endp >= '0' && *endp <= '9')
+ endp++;
+ else
+ break;
+ }
+
+ if (*endp != 0)
+ {
+ if (pname != 0)
+ error ("Invalid option `%s'", pname);
+ return defval;
+ }
+
+ return atoi (p);
+}
+
+
/* Time accumulators, to count the total time spent in various passes. */
int parse_time;
@@ -1208,6 +1316,7 @@ int regmove_time;
int sched_time;
int local_alloc_time;
int global_alloc_time;
+int flow2_time;
int sched2_time;
#ifdef DELAY_SLOTS
int dbr_sched_time;
@@ -1220,7 +1329,7 @@ int dump_time;
/* Return time used so far, in microseconds. */
-int
+long
get_run_time ()
{
if (quiet_flag)
@@ -1229,7 +1338,7 @@ get_run_time ()
#ifdef __BEOS__
return 0;
#else /* not BeOS */
-#if defined (_WIN32) && !defined (__CYGWIN32__)
+#if defined (_WIN32) && !defined (__CYGWIN__)
if (clock() < 0)
return 0;
else
@@ -1292,7 +1401,7 @@ do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while
void
print_time (str, total)
- char *str;
+ const char *str;
int total;
{
fprintf (stderr,
@@ -1317,7 +1426,7 @@ count_error (warningp)
if (warningp && !warning_message)
{
- fprintf (stderr, "%s: warnings being treated as errors\n", progname);
+ notice ("%s: warnings being treated as errors\n", progname);
warning_message = 1;
}
errorcount++;
@@ -1331,7 +1440,7 @@ count_error (warningp)
void
pfatal_with_name (name)
- char *name;
+ const char *name;
{
fprintf (stderr, "%s: ", progname);
perror (name);
@@ -1340,9 +1449,9 @@ pfatal_with_name (name)
void
fatal_io_error (name)
- char *name;
+ const char *name;
{
- fprintf (stderr, "%s: %s: I/O error\n", progname, name);
+ notice ("%s: %s: I/O error\n", progname, name);
exit (FATAL_EXIT_CODE);
}
@@ -1350,21 +1459,24 @@ fatal_io_error (name)
just calling abort(). */
void
-fatal_insn (message, insn)
- char *message;
- rtx insn;
+fatal_insn VPROTO((const char *msgid, rtx insn, ...))
{
- error (message);
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
+ rtx insn;
+#endif
+ va_list ap;
+
+ VA_START (ap, insn);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
+ insn = va_arg (ap, rtx);
+#endif
+
+ verror (msgid, ap);
debug_rtx (insn);
- if (asm_out_file)
- fflush (asm_out_file);
- if (aux_info_file)
- fflush (aux_info_file);
- if (rtl_dump_file != NULL)
- fflush (rtl_dump_file);
- fflush (stdout);
- fflush (stderr);
- abort ();
+ exit (FATAL_EXIT_CODE);
}
/* Called to give a better error message when we don't have an insn to match
@@ -1386,7 +1498,7 @@ fatal_insn_not_found (insn)
static char *
decl_name (decl, verbosity)
tree decl;
- int verbosity;
+ int verbosity ATTRIBUTE_UNUSED;
{
return IDENTIFIER_POINTER (DECL_NAME (decl));
}
@@ -1425,25 +1537,20 @@ announce_function (decl)
void
default_print_error_function (file)
- char *file;
+ const char *file;
{
if (last_error_function != current_function_decl)
{
- char *kind = "function";
- if (current_function_decl != 0
- && TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)
- kind = "method";
-
if (file)
fprintf (stderr, "%s: ", file);
if (current_function_decl == NULL)
- fprintf (stderr, "At top level:\n");
+ notice ("At top level:\n");
else
- {
- char *name = (*decl_printable_name) (current_function_decl, 2);
- fprintf (stderr, "In %s `%s':\n", kind, name);
- }
+ notice ((TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
+ ? "In method `%s':\n"
+ : "In function `%s':\n"),
+ (*decl_printable_name) (current_function_decl, 2));
last_error_function = current_function_decl;
}
@@ -1452,14 +1559,16 @@ default_print_error_function (file)
/* Called by report_error_function to print out function name.
* Default may be overridden by language front-ends. */
-void (*print_error_function) PROTO((char *)) = default_print_error_function;
+void (*print_error_function) PROTO((const char *)) =
+ default_print_error_function;
/* Prints out, if necessary, the name of the current function
- that caused an error. Called from all error and warning functions. */
+ that caused an error. Called from all error and warning functions.
+ We ignore the FILE parameter, as it cannot be relied upon. */
void
report_error_function (file)
- char *file;
+ const char *file ATTRIBUTE_UNUSED;
{
struct file_stack *p;
@@ -1469,102 +1578,160 @@ report_error_function (file)
need_error_newline = 0;
}
- (*print_error_function) (file);
-
if (input_file_stack && input_file_stack->next != 0
- && input_file_stack_tick != last_error_tick
- && file == input_filename)
+ && input_file_stack_tick != last_error_tick)
{
- fprintf (stderr, "In file included");
for (p = input_file_stack->next; p; p = p->next)
- {
- fprintf (stderr, " from %s:%d", p->name, p->line);
- if (p->next)
- fprintf (stderr, ",\n ");
- }
+ notice ((p == input_file_stack->next
+ ? "In file included from %s:%d"
+ : ",\n from %s:%d"),
+ p->name, p->line);
fprintf (stderr, ":\n");
last_error_tick = input_file_stack_tick;
}
+
+ (*print_error_function) (input_filename);
}
/* Print a message. */
static void
-vmessage (prefix, s, ap)
- char *prefix;
- char *s;
+vnotice (file, msgid, ap)
+ FILE *file;
+ char *msgid;
va_list ap;
{
- if (prefix)
- fprintf (stderr, "%s: ", prefix);
+ vfprintf (file, _(msgid), ap);
+}
- vfprintf (stderr, s, ap);
+void
+notice VPROTO((const char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, char *);
+#endif
+
+ vnotice (stderr, msgid, ap);
+ va_end (ap);
}
-/* Print a message relevant to line LINE of file FILE. */
+void
+fnotice VPROTO((FILE *file, const char *msgid, ...))
+{
+#ifndef ANSI_PROTOTYPES
+ FILE *file;
+ const char *msgid;
+#endif
+ va_list ap;
+
+ VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+ file = va_arg (ap, FILE *);
+ msgid = va_arg (ap, const char *);
+#endif
+
+ vnotice (file, msgid, ap);
+ va_end (ap);
+}
+
+/* Report FILE and LINE (or program name), and optionally just WARN. */
static void
-v_message_with_file_and_line (file, line, prefix, s, ap)
+report_file_and_line (file, line, warn)
char *file;
int line;
- char *prefix;
- char *s;
- va_list ap;
+ int warn;
{
if (file)
fprintf (stderr, "%s:%d: ", file, line);
else
fprintf (stderr, "%s: ", progname);
- vmessage (prefix, s, ap);
+ if (warn)
+ notice ("warning: ");
+}
+
+/* Print a message. */
+
+static void
+vmessage (prefix, msgid, ap)
+ const char *prefix;
+ const char *msgid;
+ va_list ap;
+{
+ if (prefix)
+ fprintf (stderr, "%s: ", prefix);
+
+ vfprintf (stderr, msgid, ap);
+}
+
+/* Print a message relevant to line LINE of file FILE. */
+
+static void
+v_message_with_file_and_line (file, line, warn, msgid, ap)
+ const char *file;
+ int line;
+ int warn;
+ const char *msgid;
+ va_list ap;
+{
+ report_file_and_line (file, line, warn);
+ vnotice (stderr, msgid, ap);
fputc ('\n', stderr);
}
/* Print a message relevant to the given DECL. */
static void
-v_message_with_decl (decl, prefix, s, ap)
+v_message_with_decl (decl, warn, msgid, ap)
tree decl;
- char *prefix;
- char *s;
+ int warn;
+ const char *msgid;
va_list ap;
{
- char *p;
-
- fprintf (stderr, "%s:%d: ",
- DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
+ const char *p;
- if (prefix)
- fprintf (stderr, "%s: ", prefix);
+ report_file_and_line (DECL_SOURCE_FILE (decl),
+ DECL_SOURCE_LINE (decl), warn);
/* Do magic to get around lack of varargs support for insertion
of arguments into existing list. We know that the decl is first;
we ass_u_me that it will be printed with "%s". */
- for (p = s; *p; ++p)
+ for (p = _(msgid); *p; ++p)
{
if (*p == '%')
{
if (*(p + 1) == '%')
++p;
+ else if (*(p + 1) != 's')
+ abort ();
else
break;
}
}
- if (p > s) /* Print the left-hand substring. */
+ if (p > _(msgid)) /* Print the left-hand substring. */
{
char fmt[sizeof "%.255s"];
- long width = p - s;
+ long width = p - _(msgid);
if (width > 255L) width = 255L; /* arbitrary */
sprintf (fmt, "%%.%lds", width);
- fprintf (stderr, fmt, s);
+ fprintf (stderr, fmt, _(msgid));
}
if (*p == '%') /* Print the name. */
{
- char *n = (DECL_NAME (decl)
+ const char *n = (DECL_NAME (decl)
? (*decl_printable_name) (decl, 2)
: "((anonymous))");
fputs (n, stderr);
@@ -1622,71 +1789,72 @@ file_and_line_for_asm (insn, pfile, pline)
/* Report an error at line LINE of file FILE. */
static void
-v_error_with_file_and_line (file, line, s, ap)
- char *file;
+v_error_with_file_and_line (file, line, msgid, ap)
+ const char *file;
int line;
- char *s;
+ const char *msgid;
va_list ap;
{
count_error (0);
report_error_function (file);
- v_message_with_file_and_line (file, line, (char *)NULL, s, ap);
+ v_message_with_file_and_line (file, line, 0, msgid, ap);
}
void
-error_with_file_and_line VPROTO((char *file, int line, char *s, ...))
+error_with_file_and_line VPROTO((const char *file, int line,
+ const char *msgid, ...))
{
-#ifndef __STDC__
- char *file;
+#ifndef ANSI_PROTOTYPES
+ const char *file;
int line;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- file = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ file = va_arg (ap, const char *);
line = va_arg (ap, int);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_error_with_file_and_line (file, line, s, ap);
+ v_error_with_file_and_line (file, line, msgid, ap);
va_end (ap);
}
/* Report an error at the declaration DECL.
- S is a format string which uses %s to substitute the declaration
+ MSGID is a format string which uses %s to substitute the declaration
name; subsequent substitutions are a la printf. */
static void
-v_error_with_decl (decl, s, ap)
+v_error_with_decl (decl, msgid, ap)
tree decl;
- char *s;
+ const char *msgid;
va_list ap;
{
count_error (0);
report_error_function (DECL_SOURCE_FILE (decl));
- v_message_with_decl (decl, (char *)NULL, s, ap);
+ v_message_with_decl (decl, 0, msgid, ap);
}
void
-error_with_decl VPROTO((tree decl, char *s, ...))
+error_with_decl VPROTO((tree decl, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
tree decl;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
decl = va_arg (ap, tree);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_error_with_decl (decl, s, ap);
+ v_error_with_decl (decl, msgid, ap);
va_end (ap);
}
@@ -1695,9 +1863,9 @@ error_with_decl VPROTO((tree decl, char *s, ...))
and each ASM_OPERANDS records its own source file and line. */
static void
-v_error_for_asm (insn, s, ap)
+v_error_for_asm (insn, msgid, ap)
rtx insn;
- char *s;
+ const char *msgid;
va_list ap;
{
char *file;
@@ -1706,158 +1874,159 @@ v_error_for_asm (insn, s, ap)
count_error (0);
file_and_line_for_asm (insn, &file, &line);
report_error_function (file);
- v_message_with_file_and_line (file, line, (char *)NULL, s, ap);
+ v_message_with_file_and_line (file, line, 0, msgid, ap);
}
void
-error_for_asm VPROTO((rtx insn, char *s, ...))
+error_for_asm VPROTO((rtx insn, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
rtx insn;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
insn = va_arg (ap, rtx);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_error_for_asm (insn, s, ap);
+ v_error_for_asm (insn, msgid, ap);
va_end (ap);
}
/* Report an error at the current line number. */
static void
-verror (s, ap)
- char *s;
+verror (msgid, ap)
+ const char *msgid;
va_list ap;
{
- v_error_with_file_and_line (input_filename, lineno, s, ap);
+ v_error_with_file_and_line (input_filename, lineno, msgid, ap);
}
void
-error VPROTO((char *s, ...))
+error VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *s;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- s = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
- verror (s, ap);
+ verror (msgid, ap);
va_end (ap);
}
/* Report a fatal error at the current line number. */
static void
-vfatal (s, ap)
- char *s;
+vfatal (msgid, ap)
+ const char *msgid;
va_list ap;
{
- verror (s, ap);
+ verror (msgid, ap);
exit (FATAL_EXIT_CODE);
}
void
-fatal VPROTO((char *s, ...))
+fatal VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *s;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- s = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
- vfatal (s, ap);
+ vfatal (msgid, ap);
va_end (ap);
}
/* Report a warning at line LINE of file FILE. */
static void
-v_warning_with_file_and_line (file, line, s, ap)
- char *file;
+v_warning_with_file_and_line (file, line, msgid, ap)
+ const char *file;
int line;
- char *s;
+ const char *msgid;
va_list ap;
{
if (count_error (1))
{
report_error_function (file);
- v_message_with_file_and_line (file, line, "warning", s, ap);
+ v_message_with_file_and_line (file, line, 1, msgid, ap);
}
}
void
-warning_with_file_and_line VPROTO((char *file, int line, char *s, ...))
+warning_with_file_and_line VPROTO((const char *file, int line,
+ const char *msgid, ...))
{
-#ifndef __STDC__
- char *file;
+#ifndef ANSI_PROTOTYPES
+ const char *file;
int line;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- file = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ file = va_arg (ap, const char *);
line = va_arg (ap, int);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_warning_with_file_and_line (file, line, s, ap);
+ v_warning_with_file_and_line (file, line, msgid, ap);
va_end (ap);
}
/* Report a warning at the declaration DECL.
- S is a format string which uses %s to substitute the declaration
+ MSGID is a format string which uses %s to substitute the declaration
name; subsequent substitutions are a la printf. */
static void
-v_warning_with_decl (decl, s, ap)
+v_warning_with_decl (decl, msgid, ap)
tree decl;
- char *s;
+ const char *msgid;
va_list ap;
{
if (count_error (1))
{
report_error_function (DECL_SOURCE_FILE (decl));
- v_message_with_decl (decl, "warning", s, ap);
+ v_message_with_decl (decl, 1, msgid, ap);
}
}
void
-warning_with_decl VPROTO((tree decl, char *s, ...))
+warning_with_decl VPROTO((tree decl, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
tree decl;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
decl = va_arg (ap, tree);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_warning_with_decl (decl, s, ap);
+ v_warning_with_decl (decl, msgid, ap);
va_end (ap);
}
@@ -1866,9 +2035,9 @@ warning_with_decl VPROTO((tree decl, char *s, ...))
and each ASM_OPERANDS records its own source file and line. */
static void
-v_warning_for_asm (insn, s, ap)
+v_warning_for_asm (insn, msgid, ap)
rtx insn;
- char *s;
+ const char *msgid;
va_list ap;
{
if (count_error (1))
@@ -1878,55 +2047,55 @@ v_warning_for_asm (insn, s, ap)
file_and_line_for_asm (insn, &file, &line);
report_error_function (file);
- v_message_with_file_and_line (file, line, "warning", s, ap);
+ v_message_with_file_and_line (file, line, 1, msgid, ap);
}
}
void
-warning_for_asm VPROTO((rtx insn, char *s, ...))
+warning_for_asm VPROTO((rtx insn, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
rtx insn;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
insn = va_arg (ap, rtx);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_warning_for_asm (insn, s, ap);
+ v_warning_for_asm (insn, msgid, ap);
va_end (ap);
}
/* Report a warning at the current line number. */
static void
-vwarning (s, ap)
- char *s;
+vwarning (msgid, ap)
+ const char *msgid;
va_list ap;
{
- v_warning_with_file_and_line (input_filename, lineno, s, ap);
+ v_warning_with_file_and_line (input_filename, lineno, msgid, ap);
}
void
-warning VPROTO((char *s, ...))
+warning VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *s;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- s = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
- vwarning (s, ap);
+ vwarning (msgid, ap);
va_end (ap);
}
@@ -1934,38 +2103,38 @@ warning VPROTO((char *s, ...))
-pedantic-errors. */
static void
-vpedwarn (s, ap)
- char *s;
+vpedwarn (msgid, ap)
+ const char *msgid;
va_list ap;
{
if (flag_pedantic_errors)
- verror (s, ap);
+ verror (msgid, ap);
else
- vwarning (s, ap);
+ vwarning (msgid, ap);
}
void
-pedwarn VPROTO((char *s, ...))
+pedwarn VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *s;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- s = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
- vpedwarn (s, ap);
+ vpedwarn (msgid, ap);
va_end (ap);
}
static void
-v_pedwarn_with_decl (decl, s, ap)
+v_pedwarn_with_decl (decl, msgid, ap)
tree decl;
- char *s;
+ const char *msgid;
va_list ap;
{
/* We don't want -pedantic-errors to cause the compilation to fail from
@@ -1978,72 +2147,73 @@ v_pedwarn_with_decl (decl, s, ap)
if (! DECL_IN_SYSTEM_HEADER (decl))
{
if (flag_pedantic_errors)
- v_error_with_decl (decl, s, ap);
+ v_error_with_decl (decl, msgid, ap);
else
- v_warning_with_decl (decl, s, ap);
+ v_warning_with_decl (decl, msgid, ap);
}
}
void
-pedwarn_with_decl VPROTO((tree decl, char *s, ...))
+pedwarn_with_decl VPROTO((tree decl, const char *msgid, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
tree decl;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
decl = va_arg (ap, tree);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_pedwarn_with_decl (decl, s, ap);
+ v_pedwarn_with_decl (decl, msgid, ap);
va_end (ap);
}
static void
-v_pedwarn_with_file_and_line (file, line, s, ap)
- char *file;
+v_pedwarn_with_file_and_line (file, line, msgid, ap)
+ const char *file;
int line;
- char *s;
+ const char *msgid;
va_list ap;
{
if (flag_pedantic_errors)
- v_error_with_file_and_line (file, line, s, ap);
+ v_error_with_file_and_line (file, line, msgid, ap);
else
- v_warning_with_file_and_line (file, line, s, ap);
+ v_warning_with_file_and_line (file, line, msgid, ap);
}
void
-pedwarn_with_file_and_line VPROTO((char *file, int line, char *s, ...))
+pedwarn_with_file_and_line VPROTO((const char *file, int line,
+ const char *msgid, ...))
{
-#ifndef __STDC__
- char *file;
+#ifndef ANSI_PROTOTYPES
+ const char *file;
int line;
- char *s;
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- file = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ file = va_arg (ap, const char *);
line = va_arg (ap, int);
- s = va_arg (ap, char *);
+ msgid = va_arg (ap, const char *);
#endif
- v_pedwarn_with_file_and_line (file, line, s, ap);
+ v_pedwarn_with_file_and_line (file, line, msgid, ap);
va_end (ap);
}
/* Apologize for not implementing some feature. */
static void
-vsorry (s, ap)
- char *s;
+vsorry (msgid, ap)
+ const char *msgid;
va_list ap;
{
sorrycount++;
@@ -2051,62 +2221,51 @@ vsorry (s, ap)
fprintf (stderr, "%s:%d: ", input_filename, lineno);
else
fprintf (stderr, "%s: ", progname);
- vmessage ("sorry, not implemented", s, ap);
+ notice ("sorry, not implemented: ");
+ vnotice (stderr, msgid, ap);
fputc ('\n', stderr);
}
void
-sorry VPROTO((char *s, ...))
+sorry VPROTO((const char *msgid, ...))
{
-#ifndef __STDC__
- char *s;
+#ifndef ANSI_PROTOTYPES
+ const char *msgid;
#endif
va_list ap;
- VA_START (ap, s);
+ VA_START (ap, msgid);
-#ifndef __STDC__
- s = va_arg (ap, char *);
+#ifndef ANSI_PROTOTYPES
+ msgid = va_arg (ap, const char *);
#endif
- vsorry (s, ap);
+ vsorry (msgid, ap);
va_end (ap);
}
-
-/* Apologize for not implementing some feature, then quit. */
-
-static void
-v_really_sorry (s, ap)
- char *s;
- va_list ap;
-{
- sorrycount++;
- if (input_filename)
- fprintf (stderr, "%s:%d: ", input_filename, lineno);
- else
- fprintf (stderr, "%s: ", progname);
- vmessage ("sorry, not implemented", s, ap);
- fatal (" (fatal)\n");
-}
-
-void
-really_sorry VPROTO((char *s, ...))
+
+/* Given a partial pathname as input, return another pathname that shares
+ no elements with the pathname of __FILE__. This is used by abort() to
+ print `Internal compiler error in expr.c' instead of `Internal compiler
+ error in ../../egcs/gcc/expr.c'. */
+const char *
+trim_filename (name)
+ const char *name;
{
-#ifndef __STDC__
- char *s;
-#endif
- va_list ap;
+ static const char *this_file = __FILE__;
+ const char *p = name, *q = this_file;
- VA_START (ap, s);
-
-#ifndef __STDC__
- s = va_arg (ap, char *);
+ while (*p == *q && *p != 0 && *q != 0) p++, q++;
+ while (p > name && p[-1] != DIR_SEPARATOR
+#ifdef DIR_SEPARATOR_2
+ && p[-1] != DIR_SEPARATOR_2
#endif
+ )
+ p--;
- v_really_sorry (s, ap);
- va_end (ap);
+ return p;
}
-
+
/* More 'friendly' abort that prints the line and file.
config.h can #define abort fancy_abort if you like that sort of thing.
@@ -2135,23 +2294,23 @@ do_abort ()
void
botch (s)
- char * s;
+ const char * s ATTRIBUTE_UNUSED;
{
abort ();
}
/* Same as `malloc' but report error if no memory available. */
-char *
+PTR
xmalloc (size)
- unsigned size;
+ size_t size;
{
- register char *value;
+ register PTR value;
if (size == 0)
size = 1;
- value = (char *) malloc (size);
+ value = (PTR) malloc (size);
if (value == 0)
fatal ("virtual memory exhausted");
return value;
@@ -2159,16 +2318,16 @@ xmalloc (size)
/* Same as `calloc' but report error if no memory available. */
-char *
+PTR
xcalloc (size1, size2)
- unsigned size1, size2;
+ size_t size1, size2;
{
- register char *value;
+ register PTR value;
if (size1 == 0 || size2 == 0)
size1 = size2 = 1;
- value = (char *) calloc (size1, size2);
+ value = (PTR) calloc (size1, size2);
if (value == 0)
fatal ("virtual memory exhausted");
return value;
@@ -2178,19 +2337,17 @@ xcalloc (size1, size2)
/* Same as `realloc' but report error if no memory available.
Also handle null PTR even if the vendor realloc gets it wrong. */
-char *
+PTR
xrealloc (ptr, size)
- char *ptr;
- int size;
+ PTR ptr;
+ size_t size;
{
- char *result;
+ register PTR result;
if (size == 0)
size = 1;
- result = (ptr
- ? (char *) realloc (ptr, size)
- : (char *) malloc (size));
+ result = (ptr ? (PTR) realloc (ptr, size) : (PTR) malloc (size));
if (!result)
fatal ("virtual memory exhausted");
@@ -2202,7 +2359,7 @@ xrealloc (ptr, size)
char *
xstrdup (s)
- register char *s;
+ register const char *s;
{
register char *result = (char *) malloc (strlen (s) + 1);
@@ -2285,6 +2442,33 @@ set_float_handler (handler)
}
}
+/* This is a wrapper function for code which might elicit an
+ arithmetic exception. That code should be passed in as a function
+ pointer FN, and one argument DATA. DATA is usually a struct which
+ contains the real input and output for function FN. This function
+ returns 0 (failure) if longjmp was called (i.e. an exception
+ occured.) It returns 1 (success) otherwise. */
+
+int
+do_float_handler (fn, data)
+ void (*fn) PROTO ((PTR));
+ PTR data;
+{
+ jmp_buf buf;
+
+ if (setjmp (buf))
+ {
+ /* We got here via longjmp() caused by an exception in function fn() */
+ set_float_handler (NULL);
+ return 0;
+ }
+
+ set_float_handler (buf);
+ (*fn)(data);
+ set_float_handler (NULL);
+ return 1;
+}
+
/* Specify, in HANDLER, where to longjmp to when a floating arithmetic
error happens, pushing the previous specification into OLD_HANDLER.
Return an indication of whether there was a previous handler in effect. */
@@ -2297,10 +2481,10 @@ push_float_handler (handler, old_handler)
float_handled = 1;
if (was_handled)
- bcopy ((char *) float_handler, (char *) old_handler,
+ memcpy ((char *) old_handler, (char *) float_handler,
sizeof (float_handler));
- bcopy ((char *) handler, (char *) float_handler, sizeof (float_handler));
+ memcpy ((char *) float_handler, (char *) handler, sizeof (float_handler));
return was_handled;
}
@@ -2353,7 +2537,7 @@ strip_off_ending (name, len)
void
output_quoted_string (asm_file, string)
FILE *asm_file;
- char *string;
+ const char *string;
{
#ifdef OUTPUT_QUOTED_STRING
OUTPUT_QUOTED_STRING (asm_file, string);
@@ -2376,16 +2560,20 @@ output_quoted_string (asm_file, string)
void
output_file_directive (asm_file, input_name)
FILE *asm_file;
- char *input_name;
+ const char *input_name;
{
int len = strlen (input_name);
- char *na = input_name + len;
+ const char *na = input_name + len;
/* NA gets INPUT_NAME sans directory names. */
while (na > input_name)
{
if (na[-1] == '/')
break;
+#ifdef DIR_SEPARATOR
+ if (na[-1] == DIR_SEPARATOR)
+ break;
+#endif
na--;
}
@@ -2402,8 +2590,8 @@ output_file_directive (asm_file, input_name)
#endif
}
+#ifdef ASM_IDENTIFY_LANGUAGE
/* Routine to build language identifier for object file. */
-
static void
output_lang_identify (asm_out_file)
FILE *asm_out_file;
@@ -2413,12 +2601,13 @@ output_lang_identify (asm_out_file)
sprintf (s, "__gnu_compiled_%s", lang_identify ());
ASM_OUTPUT_LABEL (asm_out_file, s);
}
+#endif
/* Routine to open a dump file. */
static void
open_dump_file (suffix, function_name)
- char *suffix;
- char *function_name;
+ const char *suffix;
+ const char *function_name;
{
char *dumpname;
@@ -2471,7 +2660,7 @@ close_dump_file (func, insns)
/* Routine to dump rtl into a file. */
static void
dump_rtl (suffix, decl, func, insns)
- char *suffix;
+ const char *suffix;
tree decl;
void (*func) PROTO ((FILE *, rtx));
rtx insns;
@@ -2483,9 +2672,9 @@ dump_rtl (suffix, decl, func, insns)
/* Routine to empty a dump file. */
static void
clean_dump_file (suffix)
- char * suffix;
+ const char *suffix;
{
- char * dumpname;
+ char *dumpname;
dumpname = (char *) xmalloc (strlen (dump_base_name) + strlen (suffix) + 1);
@@ -2505,6 +2694,207 @@ clean_dump_file (suffix)
return;
}
+/* Do any final processing required for the declarations in VEC, of
+ which there are LEN. We write out inline functions and variables
+ that have been deferred until this point, but which are required.
+ Returns non-zero if anything was put out. */
+int
+wrapup_global_declarations (vec, len)
+ tree *vec;
+ int len;
+{
+ tree decl;
+ int i;
+ int reconsider;
+ int output_something = 0;
+
+ for (i = 0; i < len; i++)
+ {
+ decl = vec[i];
+
+ /* We're not deferring this any longer. */
+ DECL_DEFER_OUTPUT (decl) = 0;
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0
+ && incomplete_decl_finalize_hook != 0)
+ (*incomplete_decl_finalize_hook) (decl);
+ }
+
+ /* Now emit any global variables or functions that we have been
+ putting off. We need to loop in case one of the things emitted
+ here references another one which comes earlier in the list. */
+ do
+ {
+ reconsider = 0;
+ for (i = 0; i < len; i++)
+ {
+ decl = vec[i];
+
+ if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
+ continue;
+
+ /* Don't write out static consts, unless we still need them.
+
+ We also keep static consts if not optimizing (for debugging),
+ unless the user specified -fno-keep-static-consts.
+ ??? They might be better written into the debug information.
+ This is possible when using DWARF.
+
+ A language processor that wants static constants to be always
+ written out (even if it is not used) is responsible for
+ calling rest_of_decl_compilation itself. E.g. the C front-end
+ calls rest_of_decl_compilation from finish_decl.
+ One motivation for this is that is conventional in some
+ environments to write things like:
+ static const char rcsid[] = "... version string ...";
+ intending to force the string to be in the executable.
+
+ A language processor that would prefer to have unneeded
+ static constants "optimized away" would just defer writing
+ them out until here. E.g. C++ does this, because static
+ constants are often defined in header files.
+
+ ??? A tempting alternative (for both C and C++) would be
+ to force a constant to be written if and only if it is
+ defined in a main file, as opposed to an include file. */
+
+ if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
+ && (! TREE_READONLY (decl)
+ || TREE_PUBLIC (decl)
+ || (!optimize && flag_keep_static_consts)
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ {
+ reconsider = 1;
+ rest_of_decl_compilation (decl, NULL_PTR, 1, 1);
+ }
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INITIAL (decl) != 0
+ && DECL_SAVED_INSNS (decl) != 0
+ && (flag_keep_inline_functions
+ || (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+ {
+ reconsider = 1;
+ temporary_allocation ();
+ output_inline_function (decl);
+ permanent_allocation (1);
+ }
+ }
+
+ if (reconsider)
+ output_something = 1;
+ }
+ while (reconsider);
+
+ return output_something;
+}
+
+/* Issue appropriate warnings for the global declarations in VEC (of
+ which there are LEN). Output debugging information for them. */
+void
+check_global_declarations (vec, len)
+ tree *vec;
+ int len;
+{
+ tree decl;
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ decl = vec[i];
+
+ if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
+ && ! TREE_ASM_WRITTEN (decl))
+ /* Cancel the RTL for this decl so that, if debugging info
+ output for global variables is still to come,
+ this one will be omitted. */
+ DECL_RTL (decl) = NULL;
+
+ /* Warn about any function
+ declared static but not defined.
+ We don't warn about variables,
+ because many programs have static variables
+ that exist only to get some text into the object file. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && (warn_unused
+ || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ && DECL_INITIAL (decl) == 0
+ && DECL_EXTERNAL (decl)
+ && ! DECL_ARTIFICIAL (decl)
+ && ! TREE_PUBLIC (decl))
+ {
+ if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ pedwarn_with_decl (decl,
+ "`%s' used but never defined");
+ else
+ warning_with_decl (decl,
+ "`%s' declared `static' but never defined");
+ /* This symbol is effectively an "extern" declaration now. */
+ TREE_PUBLIC (decl) = 1;
+ assemble_external (decl);
+ }
+
+ /* Warn about static fns or vars defined but not used,
+ but not about inline functions or static consts
+ since defining those in header files is normal practice. */
+ if (warn_unused
+ && ((TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
+ || (TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
+ && ! DECL_IN_SYSTEM_HEADER (decl)
+ && ! DECL_EXTERNAL (decl)
+ && ! TREE_PUBLIC (decl)
+ && ! TREE_USED (decl)
+ && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl))
+ /* The TREE_USED bit for file-scope decls
+ is kept in the identifier, to handle multiple
+ external decls in different scopes. */
+ && ! TREE_USED (DECL_NAME (decl)))
+ warning_with_decl (decl, "`%s' defined but not used");
+
+#ifdef SDB_DEBUGGING_INFO
+ /* The COFF linker can move initialized global vars to the end.
+ And that can screw up the symbol ordering.
+ By putting the symbols in that order to begin with,
+ we avoid a problem. mcsun!unido!fauern!tumuc!pes@uunet.uu.net. */
+ if (write_symbols == SDB_DEBUG && TREE_CODE (decl) == VAR_DECL
+ && TREE_PUBLIC (decl) && DECL_INITIAL (decl)
+ && ! DECL_EXTERNAL (decl)
+ && DECL_RTL (decl) != 0)
+ TIMEVAR (symout_time, sdbout_symbol (decl, 0));
+
+ /* Output COFF information for non-global
+ file-scope initialized variables. */
+ if (write_symbols == SDB_DEBUG
+ && TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIAL (decl)
+ && ! DECL_EXTERNAL (decl)
+ && DECL_RTL (decl) != 0
+ && GET_CODE (DECL_RTL (decl)) == MEM)
+ TIMEVAR (symout_time, sdbout_toplevel_data (decl));
+#endif /* SDB_DEBUGGING_INFO */
+#ifdef DWARF_DEBUGGING_INFO
+ /* Output DWARF information for file-scope tentative data object
+ declarations, file-scope (extern) function declarations (which
+ had no corresponding body) and file-scope tagged type declarations
+ and definitions which have not yet been forced out. */
+
+ if (write_symbols == DWARF_DEBUG
+ && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
+ TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 1));
+#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ /* Output DWARF2 information for file-scope tentative data object
+ declarations, file-scope (extern) function declarations (which
+ had no corresponding body) and file-scope tagged type declarations
+ and definitions which have not yet been forced out. */
+
+ if (write_symbols == DWARF2_DEBUG
+ && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
+ TIMEVAR (symout_time, dwarf2out_decl (decl));
+#endif
+ }
+}
/* Compile an entire file of output from cpp, named NAME.
Write a file of assembly output and various debugging dumps. */
@@ -2536,6 +2926,7 @@ compile_file (name)
sched_time = 0;
local_alloc_time = 0;
global_alloc_time = 0;
+ flow2_time = 0;
sched2_time = 0;
#ifdef DELAY_SLOTS
dbr_sched_time = 0;
@@ -2578,80 +2969,163 @@ compile_file (name)
pfatal_with_name (aux_info_file_name);
}
- /* Clear the dump files file. */
+ /* Clear the dump files. */
if (rtl_dump)
clean_dump_file (".rtl");
if (jump_opt_dump)
- clean_dump_file (".jump");
+ {
+ clean_dump_file (".jump");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".jump");
+ }
if (addressof_dump)
- clean_dump_file (".addressof");
+ {
+ clean_dump_file (".addressof");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".addressof");
+ }
if (cse_dump)
- clean_dump_file (".cse");
+ {
+ clean_dump_file (".cse");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".cse");
+ }
if (loop_dump)
- clean_dump_file (".loop");
+ {
+ clean_dump_file (".loop");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".loop");
+ }
if (cse2_dump)
- clean_dump_file (".cse2");
+ {
+ clean_dump_file (".cse2");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".cse2");
+ }
if (branch_prob_dump)
- clean_dump_file (".bp");
+ {
+ clean_dump_file (".bp");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".bp");
+ }
if (flow_dump)
- clean_dump_file (".flow");
+ {
+ clean_dump_file (".flow");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".flow");
+ }
if (combine_dump)
- clean_dump_file (".combine");
+ {
+ clean_dump_file (".combine");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".combine");
+ }
if (regmove_dump)
- clean_dump_file (".regmove");
+ {
+ clean_dump_file (".regmove");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".regmove");
+ }
if (sched_dump)
- clean_dump_file (".sched");
+ {
+ clean_dump_file (".sched");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".sched");
+ }
if (local_reg_dump)
- clean_dump_file (".lreg");
+ {
+ clean_dump_file (".lreg");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".lreg");
+ }
if (global_reg_dump)
- clean_dump_file (".greg");
+ {
+ clean_dump_file (".greg");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".greg");
+ }
+ if (flow2_dump)
+ {
+ clean_dump_file (".flow2");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".flow2");
+ }
if (sched2_dump)
- clean_dump_file (".sched2");
+ {
+ clean_dump_file (".sched2");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".sched2");
+ }
if (jump2_opt_dump)
- clean_dump_file (".jump2");
+ {
+ clean_dump_file (".jump2");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".jump2");
+ }
#ifdef DELAY_SLOTS
if (dbr_sched_dump)
- clean_dump_file (".dbr");
+ {
+ clean_dump_file (".dbr");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".dbr");
+ }
#endif
if (gcse_dump)
- clean_dump_file (".gcse");
+ {
+ clean_dump_file (".gcse");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".gcse");
+ }
#ifdef STACK_REGS
if (stack_reg_dump)
- clean_dump_file (".stack");
+ {
+ clean_dump_file (".stack");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".stack");
+ }
#endif
#ifdef MACHINE_DEPENDENT_REORG
if (mach_dep_reorg_dump)
- clean_dump_file (".mach");
+ {
+ clean_dump_file (".mach");
+ if (graph_dump_format != no_graph)
+ clean_graph_dump_file (dump_base_name, ".mach");
+ }
#endif
/* Open assembler code output file. */
- if (! name_specified && asm_file_name == 0)
- asm_out_file = stdout;
+ if (flag_syntax_only)
+ asm_out_file = NULL;
else
{
- int len = strlen (dump_base_name);
- register char *dumpname = (char *) xmalloc (len + 6);
- strcpy (dumpname, dump_base_name);
- strip_off_ending (dumpname, len);
- strcat (dumpname, ".s");
- if (asm_file_name == 0)
- {
- asm_file_name = (char *) xmalloc (strlen (dumpname) + 1);
- strcpy (asm_file_name, dumpname);
- }
- if (!strcmp (asm_file_name, "-"))
+ if (! name_specified && asm_file_name == 0)
asm_out_file = stdout;
else
- asm_out_file = fopen (asm_file_name, "w");
- if (asm_out_file == 0)
- pfatal_with_name (asm_file_name);
- }
+ {
+ int len = strlen (dump_base_name);
+ register char *dumpname = (char *) xmalloc (len + 6);
+ strcpy (dumpname, dump_base_name);
+ strip_off_ending (dumpname, len);
+ strcat (dumpname, ".s");
+ if (asm_file_name == 0)
+ {
+ asm_file_name = (char *) xmalloc (strlen (dumpname) + 1);
+ strcpy (asm_file_name, dumpname);
+ }
+ if (!strcmp (asm_file_name, "-"))
+ asm_out_file = stdout;
+ else
+ asm_out_file = fopen (asm_file_name, "w");
+ if (asm_out_file == 0)
+ pfatal_with_name (asm_file_name);
+ }
#ifdef IO_BUFFER_SIZE
- setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE),
- _IOFBF, IO_BUFFER_SIZE);
+ setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE),
+ _IOFBF, IO_BUFFER_SIZE);
#endif
+ }
input_filename = name;
@@ -2670,32 +3144,41 @@ compile_file (name)
if (main_input_filename == 0)
main_input_filename = name;
- ASM_FILE_START (asm_out_file);
+ if (flag_syntax_only)
+ {
+ write_symbols = NO_DEBUG;
+ profile_flag = 0;
+ profile_block_flag = 0;
+ }
+ else
+ {
+ ASM_FILE_START (asm_out_file);
#ifdef ASM_COMMENT_START
- if (flag_verbose_asm)
- {
- /* Print the list of options in effect. */
- print_version (asm_out_file, ASM_COMMENT_START);
- print_switch_values (asm_out_file, 0, MAX_LINE,
+ if (flag_verbose_asm)
+ {
+ /* Print the list of options in effect. */
+ print_version (asm_out_file, ASM_COMMENT_START);
+ print_switch_values (asm_out_file, 0, MAX_LINE,
ASM_COMMENT_START, " ", "\n");
- /* Add a blank line here so it appears in assembler output but not
- screen output. */
- fprintf (asm_out_file, "\n");
- }
+ /* Add a blank line here so it appears in assembler output but not
+ screen output. */
+ fprintf (asm_out_file, "\n");
+ }
#endif
- /* Output something to inform GDB that this compilation was by GCC. */
+ /* Output something to inform GDB that this compilation was by GCC. */
#ifndef ASM_IDENTIFY_GCC
- fprintf (asm_out_file, "gcc2_compiled.:\n");
+ fprintf (asm_out_file, "gcc2_compiled.:\n");
#else
- ASM_IDENTIFY_GCC (asm_out_file);
+ ASM_IDENTIFY_GCC (asm_out_file);
#endif
/* Output something to identify which front-end produced this file. */
#ifdef ASM_IDENTIFY_LANGUAGE
- ASM_IDENTIFY_LANGUAGE (asm_out_file);
+ ASM_IDENTIFY_LANGUAGE (asm_out_file);
#endif
+ } /* ! flag_syntax_only */
#ifndef ASM_OUTPUT_SECTION_NAME
if (flag_function_sections)
@@ -2703,6 +3186,11 @@ compile_file (name)
warning ("-ffunction-sections not supported for this target.");
flag_function_sections = 0;
}
+ if (flag_data_sections)
+ {
+ warning ("-fdata-sections not supported for this target.");
+ flag_data_sections = 0;
+ }
#endif
if (flag_function_sections
@@ -2712,8 +3200,10 @@ compile_file (name)
flag_function_sections = 0;
}
+#ifndef OBJECT_FORMAT_ELF
if (flag_function_sections && write_symbols != NO_DEBUG)
warning ("-ffunction-sections may affect debugging on some targets.");
+#endif
/* ??? Note: There used to be a conditional here
to call assemble_zeros without fail if DBX_DEBUGGING_INFO is defined.
@@ -2775,7 +3265,7 @@ compile_file (name)
if (yyparse () != 0)
{
if (errorcount == 0)
- fprintf (stderr, "Errors detected in input file (your bison.simple is out of date)");
+ notice ("Errors detected in input file (your bison.simple is out of date)\n");
/* In case there were missing closebraces,
get us back to the global binding level. */
@@ -2783,8 +3273,6 @@ compile_file (name)
poplevel (0, 0, 0);
}
- output_func_start_profiler ();
-
/* Compilation is now finished except for writing
what's left of the symbol table output. */
@@ -2793,6 +3281,9 @@ compile_file (name)
parse_time -= integration_time;
parse_time -= varconst_time;
+ if (flag_syntax_only)
+ goto finish_syntax;
+
globals = getdecls ();
/* Really define vars that have had only a tentative definition.
@@ -2804,7 +3295,6 @@ compile_file (name)
tree *vec = (tree *) alloca (sizeof (tree) * len);
int i;
tree decl;
- int reconsider = 1;
/* Process the decls in reverse order--earliest first.
Put them into VEC from back to front, then take out from front. */
@@ -2812,176 +3302,23 @@ compile_file (name)
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
vec[len - i - 1] = decl;
- for (i = 0; i < len; i++)
- {
- decl = vec[i];
+ wrapup_global_declarations (vec, len);
- /* We're not deferring this any longer. */
- DECL_DEFER_OUTPUT (decl) = 0;
+ /* This must occur after the loop to output deferred functions. Else
+ the profiler initializer would not be emitted if all the functions
+ in this compilation unit were deferred.
- if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0
- && incomplete_decl_finalize_hook != 0)
- (*incomplete_decl_finalize_hook) (decl);
- }
-
- /* Now emit any global variables or functions that we have been putting
- off. We need to loop in case one of the things emitted here
- references another one which comes earlier in the list. */
- while (reconsider)
- {
- reconsider = 0;
- for (i = 0; i < len; i++)
- {
- decl = vec[i];
-
- if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
- continue;
-
- /* Don't write out static consts, unless we still need them.
-
- We also keep static consts if not optimizing (for debugging),
- unless the user specified -fno-keep-static-consts.
- ??? They might be better written into the debug information.
- This is possible when using DWARF.
-
- A language processor that wants static constants to be always
- written out (even if it is not used) is responsible for
- calling rest_of_decl_compilation itself. E.g. the C front-end
- calls rest_of_decl_compilation from finish_decl.
- One motivation for this is that is conventional in some
- environments to write things like:
- static const char rcsid[] = "... version string ...";
- intending to force the string to be in the executable.
-
- A language processor that would prefer to have unneeded
- static constants "optimized away" would just defer writing
- them out until here. E.g. C++ does this, because static
- constants are often defined in header files.
-
- ??? A tempting alternative (for both C and C++) would be
- to force a constant to be written if and only if it is
- defined in a main file, as opposed to an include file. */
-
- if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
- && (! TREE_READONLY (decl)
- || TREE_PUBLIC (decl)
- || (!optimize && flag_keep_static_consts)
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
- {
- reconsider = 1;
- rest_of_decl_compilation (decl, NULL_PTR, 1, 1);
- }
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl) != 0
- && DECL_SAVED_INSNS (decl) != 0
- && (flag_keep_inline_functions
- || TREE_PUBLIC (decl)
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
- {
- reconsider = 1;
- temporary_allocation ();
- output_inline_function (decl);
- permanent_allocation (1);
- }
- }
- }
+ output_func_start_profiler can not cause any additional functions or
+ data to need to be output, so it need not be in the deferred function
+ loop above. */
+ output_func_start_profiler ();
/* Now that all possible functions have been output, we can dump
the exception table. */
output_exception_table ();
- for (i = 0; i < len; i++)
- {
- decl = vec[i];
-
- if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
- && ! TREE_ASM_WRITTEN (decl))
- /* Cancel the RTL for this decl so that, if debugging info
- output for global variables is still to come,
- this one will be omitted. */
- DECL_RTL (decl) = NULL;
-
- /* Warn about any function
- declared static but not defined.
- We don't warn about variables,
- because many programs have static variables
- that exist only to get some text into the object file. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && (warn_unused
- || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- && DECL_INITIAL (decl) == 0
- && DECL_EXTERNAL (decl)
- && ! DECL_ARTIFICIAL (decl)
- && ! TREE_PUBLIC (decl))
- {
- pedwarn_with_decl (decl,
- "`%s' declared `static' but never defined");
- /* This symbol is effectively an "extern" declaration now. */
- TREE_PUBLIC (decl) = 1;
- assemble_external (decl);
- }
-
- /* Warn about static fns or vars defined but not used,
- but not about inline functions or static consts
- since defining those in header files is normal practice. */
- if (warn_unused
- && ((TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
- || (TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
- && ! DECL_IN_SYSTEM_HEADER (decl)
- && ! DECL_EXTERNAL (decl)
- && ! TREE_PUBLIC (decl)
- && ! TREE_USED (decl)
- && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl))
- /* The TREE_USED bit for file-scope decls
- is kept in the identifier, to handle multiple
- external decls in different scopes. */
- && ! TREE_USED (DECL_NAME (decl)))
- warning_with_decl (decl, "`%s' defined but not used");
-
-#ifdef SDB_DEBUGGING_INFO
- /* The COFF linker can move initialized global vars to the end.
- And that can screw up the symbol ordering.
- By putting the symbols in that order to begin with,
- we avoid a problem. mcsun!unido!fauern!tumuc!pes@uunet.uu.net. */
- if (write_symbols == SDB_DEBUG && TREE_CODE (decl) == VAR_DECL
- && TREE_PUBLIC (decl) && DECL_INITIAL (decl)
- && ! DECL_EXTERNAL (decl)
- && DECL_RTL (decl) != 0)
- TIMEVAR (symout_time, sdbout_symbol (decl, 0));
-
- /* Output COFF information for non-global
- file-scope initialized variables. */
- if (write_symbols == SDB_DEBUG
- && TREE_CODE (decl) == VAR_DECL
- && DECL_INITIAL (decl)
- && ! DECL_EXTERNAL (decl)
- && DECL_RTL (decl) != 0
- && GET_CODE (DECL_RTL (decl)) == MEM)
- TIMEVAR (symout_time, sdbout_toplevel_data (decl));
-#endif /* SDB_DEBUGGING_INFO */
-#ifdef DWARF_DEBUGGING_INFO
- /* Output DWARF information for file-scope tentative data object
- declarations, file-scope (extern) function declarations (which
- had no corresponding body) and file-scope tagged type declarations
- and definitions which have not yet been forced out. */
-
- if (write_symbols == DWARF_DEBUG
- && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 1));
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- /* Output DWARF2 information for file-scope tentative data object
- declarations, file-scope (extern) function declarations (which
- had no corresponding body) and file-scope tagged type declarations
- and definitions which have not yet been forced out. */
-
- if (write_symbols == DWARF2_DEBUG
- && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
- TIMEVAR (symout_time, dwarf2out_decl (decl));
-#endif
- }
+ check_global_declarations (vec, len);
}
/* Write out any pending weak symbol declarations. */
@@ -3034,8 +3371,9 @@ compile_file (name)
ASM_FILE_END (asm_out_file);
#endif
- /* Language-specific end of compilation actions. */
+ /* Language-specific end of compilation actions. */
+ finish_syntax:
lang_finish ();
/* Close the dump files. */
@@ -3060,9 +3398,62 @@ compile_file (name)
finish_parse ();
- if (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0)
+ if (! flag_syntax_only
+ && (ferror (asm_out_file) != 0 || fclose (asm_out_file) != 0))
fatal_io_error (asm_file_name);
+ /* Do whatever is necessary to finish printing the graphs. */
+ if (graph_dump_format != no_graph)
+ {
+ if (jump_opt_dump)
+ finish_graph_dump_file (dump_base_name, ".jump");
+ if (addressof_dump)
+ finish_graph_dump_file (dump_base_name, ".addressof");
+ if (cse_dump)
+ finish_graph_dump_file (dump_base_name, ".cse");
+ if (loop_dump)
+ finish_graph_dump_file (dump_base_name, ".loop");
+ if (cse2_dump)
+ finish_graph_dump_file (dump_base_name, ".cse2");
+ if (branch_prob_dump)
+ finish_graph_dump_file (dump_base_name, ".bp");
+ if (flow_dump)
+ finish_graph_dump_file (dump_base_name, ".flow");
+ if (combine_dump)
+ finish_graph_dump_file (dump_base_name, ".combine");
+ if (regmove_dump)
+ finish_graph_dump_file (dump_base_name, ".regmove");
+ if (sched_dump)
+ finish_graph_dump_file (dump_base_name, ".sched");
+ if (local_reg_dump)
+ finish_graph_dump_file (dump_base_name, ".lreg");
+ if (global_reg_dump)
+ finish_graph_dump_file (dump_base_name, ".greg");
+ if (flow2_dump)
+ finish_graph_dump_file (dump_base_name, ".flow2");
+ if (sched2_dump)
+ finish_graph_dump_file (dump_base_name, ".sched2");
+ if (jump2_opt_dump)
+ finish_graph_dump_file (dump_base_name, ".jump2");
+#ifdef DELAY_SLOTS
+ if (dbr_sched_dump)
+ finish_graph_dump_file (dump_base_name, ".dbr");
+#endif
+ if (gcse_dump)
+ finish_graph_dump_file (dump_base_name, ".gcse");
+#ifdef STACK_REGS
+ if (stack_reg_dump)
+ finish_graph_dump_file (dump_base_name, ".stack");
+#endif
+#ifdef MACHINE_DEPENDENT_REORG
+ if (mach_dep_reorg_dump)
+ finish_graph_dump_file (dump_base_name, ".mach");
+#endif
+ }
+
+ /* Free up memory for the benefit of leak detectors. */
+ free_reg_info ();
+
/* Print the times. */
if (! quiet_flag)
@@ -3083,6 +3474,7 @@ compile_file (name)
print_time ("sched", sched_time);
print_time ("local-alloc", local_alloc_time);
print_time ("global-alloc", global_alloc_time);
+ print_time ("flow2", flow2_time);
print_time ("sched2", sched2_time);
#ifdef DELAY_SLOTS
print_time ("dbranch", dbr_sched_time);
@@ -3110,7 +3502,7 @@ compile_file (name)
void
rest_of_decl_compilation (decl, asmspec, top_level, at_end)
tree decl;
- char *asmspec;
+ const char *asmspec;
int top_level;
int at_end;
{
@@ -3175,8 +3567,13 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
void
rest_of_type_compilation (type, toplev)
+#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) || defined (SDB_DEBUGGING_INFO)
tree type;
int toplev;
+#else
+ tree type ATTRIBUTE_UNUSED;
+ int toplev ATTRIBUTE_UNUSED;
+#endif
{
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
@@ -3208,6 +3605,7 @@ rest_of_compilation (decl)
/* Likewise, for DECL_ARGUMENTS. */
tree saved_arguments = 0;
int failure = 0;
+ int rebuild_label_notes_after_reload;
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
@@ -3215,7 +3613,7 @@ rest_of_compilation (decl)
if (DECL_SAVED_INSNS (decl) == 0)
{
int inlinable = 0;
- char *lose;
+ const char *lose;
/* If requested, consider whether to make this function inline. */
if (DECL_INLINE (decl) || flag_inline_functions)
@@ -3373,8 +3771,9 @@ rest_of_compilation (decl)
}
/* If specified extern inline but we aren't inlining it, we are
- done. */
- if (DECL_INLINE (decl) && DECL_EXTERNAL (decl))
+ done. This goes for anything that gets here with DECL_EXTERNAL
+ set, not just things with DECL_INLINE. */
+ if (DECL_EXTERNAL (decl))
goto exit_rest_of_compilation;
}
@@ -3479,28 +3878,49 @@ rest_of_compilation (decl)
!JUMP_AFTER_REGSCAN));
/* Dump rtl code after cse, if we are doing that. */
-
+
if (cse_dump)
- close_dump_file (print_rtl, insns);
+ {
+ close_dump_file (print_rtl, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".cse", insns);
+ }
}
purge_addressof (insns);
reg_scan (insns, max_reg_num (), 1);
if (addressof_dump)
- dump_rtl (".addressof", decl, print_rtl, insns);
-
+ {
+ dump_rtl (".addressof", decl, print_rtl, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".addressof", insns);
+ }
+
/* Perform global cse. */
if (optimize > 0 && flag_gcse)
{
if (gcse_dump)
open_dump_file (".gcse", IDENTIFIER_POINTER (DECL_NAME (decl)));
-
- TIMEVAR (gcse_time, gcse_main (insns, rtl_dump_file));
+
+ TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file));
+
+ /* If gcse altered any jumps, rerun jump optimizations to clean
+ things up. */
+ if (tem)
+ {
+ TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
+ !JUMP_NOOP_MOVES,
+ !JUMP_AFTER_REGSCAN));
+ }
if (gcse_dump)
- close_dump_file (print_rtl, insns);
+ {
+ close_dump_file (print_rtl, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".gcse", insns);
+ }
}
/* Move constant computations out of loops. */
@@ -3516,7 +3936,7 @@ rest_of_compilation (decl)
{
/* We only want to perform unrolling once. */
- loop_optimize (insns, rtl_dump_file, 0);
+ loop_optimize (insns, rtl_dump_file, 0, 0);
/* The first call to loop_optimize makes some instructions
@@ -3529,20 +3949,24 @@ rest_of_compilation (decl)
analysis code depends on this information. */
reg_scan (insns, max_reg_num (), 1);
}
- loop_optimize (insns, rtl_dump_file, flag_unroll_loops);
+ loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1);
});
-
+
/* Dump rtl code after loop opt, if we are doing that. */
-
+
if (loop_dump)
- close_dump_file (print_rtl, insns);
+ {
+ close_dump_file (print_rtl, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".loop", insns);
+ }
}
if (optimize > 0)
{
if (cse2_dump)
open_dump_file (".cse2", decl_printable_name (decl, 2));
-
+
if (flag_rerun_cse_after_loop)
{
/* Running another jump optimization pass before the second
@@ -3571,28 +3995,36 @@ rest_of_compilation (decl)
TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 0));
}
-
+
/* Dump rtl code after cse, if we are doing that. */
-
+
if (cse2_dump)
- close_dump_file (print_rtl, insns);
+ {
+ close_dump_file (print_rtl, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".cse2", insns);
+ }
}
-
+
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
{
if (branch_prob_dump)
open_dump_file (".bp", decl_printable_name (decl, 2));
-
+
TIMEVAR
(branch_prob_time,
{
branch_prob (insns, rtl_dump_file);
});
-
+
if (branch_prob_dump)
- close_dump_file (print_rtl, insns);
+ {
+ close_dump_file (print_rtl, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".bp", insns);
+ }
}
-
+
/* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1;
@@ -3601,7 +4033,7 @@ rest_of_compilation (decl)
(if we got the -noreg switch and not -opt)
and smart register allocation. */
- if (optimize > 0) /* Stupid allocation probably won't work */
+ if (optimize > 0) /* Stupid allocation probably won't work */
obey_regdecls = 0; /* if optimizations being done. */
regclass_init ();
@@ -3630,7 +4062,7 @@ rest_of_compilation (decl)
(flow_time,
{
find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
- life_analysis (insns, max_reg_num (), rtl_dump_file);
+ life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
});
if (warn_uninitialized)
@@ -3643,18 +4075,30 @@ rest_of_compilation (decl)
/* Dump rtl after flow analysis. */
if (flow_dump)
- close_dump_file (print_rtl_with_bb, insns);
-
+ {
+ close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".flow", insns);
+ }
+
+ /* The first life analysis pass has finished. From now on we can not
+ generate any new pseudos. */
+ no_new_pseudos = 1;
+
/* If -opt, try combining insns through substitution. */
if (optimize > 0)
{
TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ()));
-
+
/* Dump rtl code after insn combination. */
-
+
if (combine_dump)
- dump_rtl (".combine", decl, print_rtl_with_bb, insns);
+ {
+ dump_rtl (".combine", decl, print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".combine", insns);
+ }
}
/* Register allocation pre-pass, to reduce number of moves
@@ -3663,12 +4107,16 @@ rest_of_compilation (decl)
{
if (regmove_dump)
open_dump_file (".regmove", decl_printable_name (decl, 2));
-
+
TIMEVAR (regmove_time, regmove_optimize (insns, max_reg_num (),
rtl_dump_file));
-
+
if (regmove_dump)
- close_dump_file (print_rtl_with_bb, insns);
+ {
+ close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".regmove", insns);
+ }
}
/* Print function header into sched dump now
@@ -3678,48 +4126,60 @@ rest_of_compilation (decl)
{
if (sched_dump)
open_dump_file (".sched", decl_printable_name (decl, 2));
-
+
/* Do control and data sched analysis,
and write some of the results to dump file. */
TIMEVAR (sched_time, schedule_insns (rtl_dump_file));
-
+
/* Dump rtl after instruction scheduling. */
-
+
if (sched_dump)
- close_dump_file (print_rtl_with_bb, insns);
+ {
+ close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".sched", insns);
+ }
}
+ /* Determine if the current function is a leaf before running reload
+ since this can impact optimizations done by the prologue and
+ epilogue thus changing register elimination offsets. */
+ current_function_is_leaf = leaf_function_p ();
+
/* Unless we did stupid register allocation,
- allocate pseudo-regs that are used only within 1 basic block. */
+ allocate pseudo-regs that are used only within 1 basic block.
+
+ RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
+ jump optimizer after register allocation and reloading are finished. */
if (!obey_regdecls)
TIMEVAR (local_alloc_time,
{
- recompute_reg_usage (insns);
+ recompute_reg_usage (insns, ! optimize_size);
regclass (insns, max_reg_num ());
- local_alloc ();
+ rebuild_label_notes_after_reload = local_alloc ();
});
+ else
+ rebuild_label_notes_after_reload = 0;
/* Dump rtl code after allocating regs within basic blocks. */
if (local_reg_dump)
{
open_dump_file (".lreg", decl_printable_name (decl, 2));
-
+
TIMEVAR (dump_time, dump_flow_info (rtl_dump_file));
TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
-
+
close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".lreg", insns);
}
if (global_reg_dump)
open_dump_file (".greg", decl_printable_name (decl, 2));
- /* Save the last label number used so far, so reorg can tell
- when it's safe to kill spill regs. */
- max_label_num_after_reload = max_label_num ();
-
/* Unless we did stupid register allocation,
allocate remaining pseudo-regs, then do the reload pass
fixing up any insns that are invalid. */
@@ -3736,12 +4196,68 @@ rest_of_compilation (decl)
if (failure)
goto exit_rest_of_compilation;
- reload_completed = 1;
-
/* Do a very simple CSE pass over just the hard registers. */
if (optimize > 0)
reload_cse_regs (insns);
+ /* Register allocation and reloading may have turned an indirect jump into
+ a direct jump. If so, we must rebuild the JUMP_LABEL fields of
+ jumping instructions. */
+ if (rebuild_label_notes_after_reload)
+ TIMEVAR (jump_time, rebuild_jump_labels (insns));
+
+ /* If optimizing and we are performing instruction scheduling after
+ reload, then go ahead and split insns now since we are about to
+ recompute flow information anyway.
+
+ reload_cse_regs may expose more splitting opportunities, expecially
+ for double-word operations. */
+ if (optimize > 0 && flag_schedule_insns_after_reload)
+ {
+ rtx insn;
+
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ {
+ rtx last;
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ continue;
+
+ last = try_split (PATTERN (insn), insn, 1);
+
+ if (last != insn)
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_SOURCE_FILE (insn) = 0;
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ }
+ }
+ }
+
+ if (global_reg_dump)
+ {
+ TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
+ close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".greg", insns);
+ }
+
+ /* Re-create the death notes which were deleted during reload. */
+ if (flow2_dump)
+ open_dump_file (".flow2", decl_printable_name (decl, 2));
+
+ if (optimize)
+ {
+ TIMEVAR
+ (flow2_time,
+ {
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
+ life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
+ });
+ }
+
+ flow2_completed = 1;
+
/* On some machines, the prologue and epilogue code, or parts thereof,
can be represented as RTL. Doing so lets us schedule insns between
it and the rest of the code and also allows delayed branch
@@ -3749,11 +4265,13 @@ rest_of_compilation (decl)
thread_prologue_and_epilogue_insns (insns);
- if (global_reg_dump)
+ if (flow2_dump)
{
- TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".flow2", insns);
}
+
if (optimize > 0 && flag_schedule_insns_after_reload)
{
if (sched2_dump)
@@ -3767,13 +4285,16 @@ rest_of_compilation (decl)
/* Dump rtl after post-reorder instruction scheduling. */
if (sched2_dump)
- close_dump_file (print_rtl_with_bb, insns);
+ {
+ close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".sched2", insns);
+ }
}
#ifdef LEAF_REGISTERS
- leaf_function = 0;
- if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ())
- leaf_function = 1;
+ current_function_uses_only_leaf_regs
+ = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
#endif
/* One more attempt to remove jumps to .+1
@@ -3786,11 +4307,15 @@ rest_of_compilation (decl)
TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP,
JUMP_NOOP_MOVES,
!JUMP_AFTER_REGSCAN));
-
+
/* Dump rtl code after jump, if we are doing that. */
if (jump2_opt_dump)
- dump_rtl (".jump2", decl, print_rtl_with_bb, insns);
+ {
+ dump_rtl (".jump2", decl, print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".jump2", insns);
+ }
}
/* If a machine dependent reorganization is needed, call it. */
@@ -3798,7 +4323,11 @@ rest_of_compilation (decl)
MACHINE_DEPENDENT_REORG (insns);
if (mach_dep_reorg_dump)
- dump_rtl (".mach", decl, print_rtl_with_bb, insns);
+ {
+ dump_rtl (".mach", decl, print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".mach", insns);
+ }
#endif
/* If a scheduling pass for delayed branches is to be done,
@@ -3807,10 +4336,17 @@ rest_of_compilation (decl)
#ifdef DELAY_SLOTS
if (optimize > 0 && flag_delayed_branch)
{
+ if (dbr_sched_dump)
+ open_dump_file (".dbr", decl_printable_name (decl, 2));
+
TIMEVAR (dbr_sched_time, dbr_schedule (insns, rtl_dump_file));
-
+
if (dbr_sched_dump)
- dump_rtl (".dbr", decl, print_rtl_with_bb, insns);
+ {
+ close_dump_file (print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".dbr", insns);
+ }
}
#endif
@@ -3821,10 +4357,17 @@ rest_of_compilation (decl)
});
#ifdef STACK_REGS
+ if (stack_reg_dump)
+ open_dump_file (".stack", decl_printable_name (decl, 2));
+
TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file));
if (stack_reg_dump)
- dump_rtl (".stack", decl, print_rtl_with_bb, insns);
+ {
+ dump_rtl (".stack", decl, print_rtl_with_bb, insns);
+ if (graph_dump_format != no_graph)
+ print_rtl_graph_with_bb (dump_base_name, ".stack", insns);
+ }
#endif
/* Now turn the rtl into assembler code. */
@@ -3854,6 +4397,9 @@ rest_of_compilation (decl)
if (! quiet_flag)
fflush (asm_out_file);
+ /* Release all memory allocated by flow. */
+ free_basic_block_vars (0);
+
/* Release all memory held by regsets now */
regset_release_memory ();
});
@@ -3885,6 +4431,8 @@ rest_of_compilation (decl)
exit_rest_of_compilation:
+ free_bb_mem ();
+
/* In case the function was not output,
don't leave any temporary anonymous types
queued up for sdb output. */
@@ -3906,6 +4454,8 @@ rest_of_compilation (decl)
}
reload_completed = 0;
+ flow2_completed = 0;
+ no_new_pseudos = 0;
TIMEVAR (final_time,
{
@@ -3939,26 +4489,30 @@ rest_of_compilation (decl)
*except* what is spent in this function. */
parse_time -= get_run_time () - start_time;
+
+ /* Reset global variables. */
+ free_basic_block_vars (0);
}
static void
display_help ()
{
int undoc;
- long i;
- char * lang;
-
-#ifndef USE_CPPLIB
+ unsigned long i;
+ const char * lang;
+
+#ifndef USE_CPPLIB
printf ("Usage: %s input [switches]\n", progname);
printf ("Switches:\n");
#endif
printf (" -ffixed-<register> Mark <register> as being unavailable to the compiler\n");
printf (" -fcall-used-<register> Mark <register> as being corrupted by function calls\n");
printf (" -fcall-saved-<register> Mark <register> as being preserved across functions\n");
+ printf (" -finline-limit-<number> Limits the size of inlined functions to <number>\n");
for (i = NUM_ELEM (f_options); i--;)
{
- char * description = f_options[i].description;
+ const char * description = f_options[i].description;
if (description != NULL && * description != 0)
printf (" -f%-21s %s\n",
@@ -3974,7 +4528,7 @@ display_help ()
for (i = NUM_ELEM (W_options); i--;)
{
- char * description = W_options[i].description;
+ const char * description = W_options[i].description;
if (description != NULL && * description != 0)
printf (" -W%-21s %s\n",
@@ -4018,22 +4572,25 @@ display_help ()
If the description is empty, do not display anything. (This allows
options to be deliberately undocumented, for whatever reason).
If the option string is missing, then this is a marker, indicating
- that the description string is in fact the name of a language, whoes
+ that the description string is in fact the name of a language, whose
language specific options are to follow. */
if (NUM_ELEM (documented_lang_options) > 1)
{
- int looking_for_start = 0;
-
printf ("\nLanguage specific options:\n");
for (i = 0; i < NUM_ELEM (documented_lang_options); i++)
{
- char * description = documented_lang_options[i].description;
- char * option = documented_lang_options[i].option;
+ const char * description = documented_lang_options[i].description;
+ const char * option = documented_lang_options[i].option;
if (description == NULL)
- undoc = 1;
+ {
+ undoc = 1;
+
+ if (extra_warnings)
+ printf (" %-23.23s [undocumented]\n", option);
+ }
else if (* description == 0)
continue;
else if (option == NULL)
@@ -4070,36 +4627,48 @@ display_help ()
for (i = NUM_ELEM (target_switches); i--;)
{
- char * option = target_switches[i].name;
- char * description = target_switches[i].description;
+ const char * option = target_switches[i].name;
+ const char * description = target_switches[i].description;
- if (option == NULL)
+ if (option == NULL || * option == 0)
continue;
else if (description == NULL)
- undoc = 1;
+ {
+ undoc = 1;
+
+ if (extra_warnings)
+ printf (" -m%-21.21s [undocumented]\n", option);
+ }
else if (* description != 0)
- doc += printf (" %-23.23s %s\n", option, description);
+ doc += printf (" -m%-21.21s %s\n", option, description);
}
#ifdef TARGET_OPTIONS
for (i = NUM_ELEM (target_options); i--;)
{
- char * option = target_options[i].prefix;
- char * description = target_options[i].description;
+ const char * option = target_options[i].prefix;
+ const char * description = target_options[i].description;
- if (option == NULL)
+ if (option == NULL || * option == 0)
continue;
else if (description == NULL)
- undoc = 1;
+ {
+ undoc = 1;
+
+ if (extra_warnings)
+ printf (" -m%-21.21s [undocumented]\n", option);
+ }
else if (* description != 0)
- doc += printf (" %-23.23s %s\n", option, description);
+ doc += printf (" -m%-21.21s %s\n", option, description);
}
#endif
if (undoc)
- if (doc)
- printf ("\nThere are undocumented target specific options as well.\n");
- else
- printf (" They exist, but they are not documented.\n");
+ {
+ if (doc)
+ printf ("\nThere are undocumented target specific options as well.\n");
+ else
+ printf (" They exist, but they are not documented.\n");
+ }
}
}
@@ -4115,55 +4684,59 @@ check_lang_option (option, lang_option)
lang_independent_options * indep_options;
int len;
long k;
-
+ char * space;
+
/* Ignore NULL entries. */
if (option == NULL || lang_option == NULL)
return 0;
- len = strlen (lang_option);
-
+ if ((space = strchr (lang_option, ' ')) != NULL)
+ len = space - lang_option;
+ else
+ len = strlen (lang_option);
+
/* If they do not match to the first n characters then fail. */
if (strncmp (option, lang_option, len) != 0)
return 0;
-
+
/* Do not accept a lang option, if it matches a normal -f or -W
option. Chill defines a -fpack, but we want to support
-fpack-struct. */
-
+
/* An exact match is OK */
- if (strlen (option) == len)
+ if ((int) strlen (option) == len)
return 1;
-
+
/* If it is not an -f or -W option allow the match */
if (option[0] != '-')
return 1;
-
+
switch (option[1])
{
case 'f': indep_options = f_options; break;
case 'W': indep_options = W_options; break;
default: return 1;
}
-
+
/* The option is a -f or -W option.
Skip past the prefix and search for the remainder in the
appropriate table of options. */
option += 2;
-
+
if (option[0] == 'n' && option[1] == 'o' && option[2] == '-')
option += 3;
-
+
for (k = NUM_ELEM (indep_options); k--;)
{
if (!strcmp (option, indep_options[k].string))
{
/* The option matched a language independent option,
do not allow the language specific match. */
-
+
return 0;
}
}
-
+
/* The option matches the start of the langauge specific option
and it is not an exact match for a language independent option. */
return 1;
@@ -4174,10 +4747,9 @@ check_lang_option (option, lang_option)
33 if had nonfatal errors, else success. */
int
-main (argc, argv, envp)
+main (argc, argv)
int argc;
char **argv;
- char **envp;
{
register int i;
char *filename = 0;
@@ -4210,6 +4782,12 @@ main (argc, argv, envp)
}
#endif
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_MESSAGES, "");
+#endif
+ (void) bindtextdomain (PACKAGE, localedir);
+ (void) textdomain (PACKAGE);
+
signal (SIGFPE, float_signal);
#ifdef SIGPIPE
@@ -4217,7 +4795,7 @@ main (argc, argv, envp)
#endif
decl_printable_name = decl_name;
- lang_expand_expr = (struct rtx_def *(*)()) do_abort;
+ lang_expand_expr = (lang_expand_expr_t) do_abort;
/* Initialize whether `char' is signed. */
flag_signed_char = DEFAULT_SIGNED_CHAR;
@@ -4236,30 +4814,32 @@ main (argc, argv, envp)
if (!strcmp (argv[i], "-O"))
{
optimize = 1;
+ optimize_size = 0;
}
else if (argv[i][0] == '-' && argv[i][1] == 'O')
{
/* Handle -Os, -O2, -O3, -O69, ... */
char *p = &argv[i][2];
- int c;
if ((p[0] == 's') && (p[1] == 0))
- optimize_size = 1;
+ {
+ optimize_size = 1;
+
+ /* Optimizing for size forces optimize to be 2. */
+ optimize = 2;
+ }
else
{
- while ((c = *p++))
- if (! (c >= '0' && c <= '9'))
- break;
- if (c == 0)
- optimize = atoi (&argv[i][2]);
+ const int optimize_val = read_integral_parameter (p, p - 2, -1);
+ if (optimize_val != -1)
+ {
+ optimize = optimize_val;
+ optimize_size = 0;
+ }
}
}
}
- /* Optimizing for size forces optimize to be no less than 2. */
- if (optimize_size && (optimize < 2))
- optimize = 2;
-
obey_regdecls = (optimize == 0);
if (optimize >= 1)
@@ -4290,9 +4870,7 @@ main (argc, argv, envp)
flag_schedule_insns_after_reload = 1;
#endif
flag_regmove = 1;
- /* We don't set flag_strict_aliasing here because we're still
- testing the functionality. After it has been tested, it
- should be turned on here. */
+ flag_strict_aliasing = 1;
}
if (optimize >= 3)
@@ -4323,19 +4901,17 @@ main (argc, argv, envp)
if (check_lang_option (argv[i], documented_lang_options[j].option))
break;
- if (j != -1)
+ if (j != (size_t)-1)
{
/* If the option is valid for *some* language,
treat it as valid even if this language doesn't understand it. */
int strings_processed = lang_decode_option (argc - i, argv + i);
- /* BEGIN CYGNUS LOCAL --help/nickc */
if (!strcmp (argv[i], "--help"))
{
display_help ();
exit (0);
}
- /* END CYGNUS LOCAL */
if (strings_processed != 0)
i += strings_processed - 1;
@@ -4365,6 +4941,7 @@ main (argc, argv, envp)
dbr_sched_dump = 1;
#endif
flow_dump = 1;
+ flow2_dump = 1;
global_reg_dump = 1;
jump_opt_dump = 1;
addressof_dump = 1;
@@ -4456,12 +5033,21 @@ main (argc, argv, envp)
case 'N':
regmove_dump = 1;
break;
+ case 'v':
+ graph_dump_format = vcg;
+ break;
+ case 'w':
+ flow2_dump = 1;
+ break;
case 'y':
set_yydebug (1);
break;
case 'x':
rtl_dump_and_exit = 1;
break;
+ case 'D': /* these are handled by the preprocessor */
+ case 'I':
+ break;
default:
warning ("unrecognised gcc debugging option: %c", p[-1]);
break;
@@ -4497,6 +5083,9 @@ main (argc, argv, envp)
if (found)
;
+ else if (!strncmp (p, "inline-limit-", 13))
+ inline_max_insns =
+ read_integral_parameter (p + 13, p - 2, inline_max_insns);
#ifdef HAIFA
#ifdef INSN_SCHEDULING
else if (!strncmp (p, "sched-verbose-",14))
@@ -4514,16 +5103,7 @@ main (argc, argv, envp)
}
else if (str[0] == 'O')
{
- register char *p = str+1;
- if (*p == 's')
- p++;
- else
- while (*p && *p >= '0' && *p <= '9')
- p++;
- if (*p == '\0')
- ;
- else
- error ("Invalid option `%s'", argv[i]);
+ /* Already been treated above. Do nothing. */
}
else if (!strcmp (str, "pedantic"))
pedantic = 1;
@@ -4576,39 +5156,23 @@ main (argc, argv, envp)
;
else if (!strncmp (p, "id-clash-", 9))
{
- char *endp = p + 9;
-
- while (*endp)
+ const int id_clash_val
+ = read_integral_parameter (p + 9, p - 2, -1);
+ if (id_clash_val != -1)
{
- if (*endp >= '0' && *endp <= '9')
- endp++;
- else
- {
- error ("Invalid option `%s'", argv[i]);
- goto id_clash_lose;
- }
+ id_clash_len = id_clash_val;
+ warn_id_clash = 1;
}
- warn_id_clash = 1;
- id_clash_len = atoi (str + 10);
- id_clash_lose: ;
}
else if (!strncmp (p, "larger-than-", 12))
{
- char *endp = p + 12;
-
- while (*endp)
+ const int larger_than_val
+ = read_integral_parameter (p + 12, p - 2, -1);
+ if (larger_than_val != -1)
{
- if (*endp >= '0' && *endp <= '9')
- endp++;
- else
- {
- error ("Invalid option `%s'", argv[i]);
- goto larger_than_lose;
- }
+ larger_than_size = larger_than_val;
+ warn_larger_than = 1;
}
- warn_larger_than = 1;
- larger_than_size = atoi (str + 13);
- larger_than_lose: ;
}
else
error ("Invalid option `%s'", argv[i]);
@@ -4636,7 +5200,6 @@ main (argc, argv, envp)
}
else if (str[0] == 'g')
{
- unsigned len;
unsigned level;
/* A lot of code assumes write_symbols == NO_DEBUG if the
debugging level is 0 (thus -gstabs1 -gstabs0 would lose track
@@ -4649,53 +5212,60 @@ main (argc, argv, envp)
-gdwarf -g3 is equivalent to -gdwarf3. */
static int type_explicitly_set_p = 0;
/* Indexed by enum debug_info_type. */
- static char *debug_type_names[] =
+ static const char *debug_type_names[] =
{
"none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff"
};
+ /* The maximum admissible debug level value. */
+ static const unsigned max_debug_level = 3;
+
/* Look up STR in the table. */
for (da = debug_args; da->arg; da++)
{
- if (! strncmp (str, da->arg, strlen (da->arg)))
+ const int da_len = strlen (da->arg);
+
+ if (! strncmp (str, da->arg, da_len))
{
enum debug_info_type type = da->debug_type;
- char *p, *q;
+ const char *p = str + da_len;
- p = str + strlen (da->arg);
if (*p && (*p < '0' || *p > '9'))
continue;
- len = p - str;
- q = p;
- while (*q && (*q >= '0' && *q <= '9'))
- q++;
+
+ /* A debug flag without a level defaults to level 2.
+ Note we do not want to call read_integral_parameter
+ for that case since it will call atoi which
+ will return zero.
+
+ ??? We may want to generalize the interface to
+ read_integral_parameter to better handle this case
+ if this case shows up often. */
if (*p)
+ level = read_integral_parameter (p, 0,
+ max_debug_level + 1);
+ else
+ level = 2;
+
+ if (da_len > 1 && *p && !strncmp (str, "gdwarf", da_len))
{
- level = atoi (p);
- if (len > 1 && !strncmp (str, "gdwarf", len))
- {
- error ("use -gdwarf -g%d for DWARF v1, level %d",
- level, level);
- if (level == 2)
- error ("use -gdwarf-2 for DWARF v2");
- }
+ error ("use -gdwarf -g%d for DWARF v1, level %d",
+ level, level);
+ if (level == 2)
+ error ("use -gdwarf-2 for DWARF v2");
}
- else
- level = 2; /* default debugging info level */
- if (*q || level > 3)
+
+ if (level > max_debug_level)
{
- warning ("invalid debug level specification in option: `-%s'",
- str);
- /* ??? This error message is incorrect in the case of
- -g4 -g. */
- warning ("no debugging information will be generated");
- level = 0;
+ warning ("ignoring option `%s' due to invalid debug level specification",
+ str - 1);
+ level = debug_info_level;
}
if (type == NO_DEBUG)
{
type = PREFERRED_DEBUGGING_TYPE;
- if (len > 1 && strncmp (str, "ggdb", len) == 0)
+ if (da_len > 1 && strncmp (str, "ggdb", da_len) == 0)
{
#if defined (DWARF2_DEBUGGING_INFO) && !defined (LINKER_DOES_NOT_WORK_WITH_DWARF2)
type = DWARF2_DEBUG;
@@ -4749,8 +5319,19 @@ main (argc, argv, envp)
}
else if (str[0] == 'G')
{
- g_switch_set = TRUE;
- g_switch_value = atoi ((str[1] != '\0') ? str+1 : argv[++i]);
+ const int g_switch_val = (str[1] != '\0') ?
+ read_integral_parameter(str + 1, 0, -1) :
+ read_integral_parameter(argv[++i], 0, -1);
+
+ if (g_switch_val != -1)
+ {
+ g_switch_set = TRUE;
+ g_switch_value = g_switch_val;
+ }
+ else
+ {
+ error("Invalid option `-%s'",str);
+ }
}
else if (!strncmp (str, "aux-info", 8))
{
@@ -4833,6 +5414,21 @@ main (argc, argv, envp)
warning ("this target machine does not have delayed branches");
#endif
+ user_label_prefix = USER_LABEL_PREFIX;
+ if (flag_leading_underscore != -1)
+ {
+ /* If the default prefix is more complicated than "" or "_",
+ issue a warning and ignore this option. */
+ if (user_label_prefix[0] == 0 ||
+ (user_label_prefix[0] == '_' && user_label_prefix[1] == 0))
+ {
+ user_label_prefix = flag_leading_underscore ? "_" : "";
+ }
+ else
+ warning ("-f%sleading-underscore not supported on this target machine",
+ flag_leading_underscore ? "" : "no-");
+ }
+
/* If we are in verbose mode, write out the version and maybe all the
option flags in use. */
if (version_flag)
@@ -4844,12 +5440,12 @@ main (argc, argv, envp)
compile_file (filename);
-#if !defined(OS2) && !defined(VMS) && (!defined(_WIN32) || defined (__CYGWIN32__))
+#if !defined(OS2) && !defined(VMS) && (!defined(_WIN32) || defined (__CYGWIN__)) && !defined(__INTERIX)
if (flag_print_mem)
{
char *lim = (char *) sbrk (0);
- fprintf (stderr, "Data size %ld.\n", (long)(lim - (char *) &environ));
+ notice ("Data size %ld.\n", (long) (lim - (char *) &environ));
fflush (stderr);
#ifndef __MSDOS__
@@ -4860,7 +5456,7 @@ main (argc, argv, envp)
#endif /* not USG */
#endif
}
-#endif /* ! OS2 && ! VMS && (! _WIN32 || CYGWIN32) */
+#endif /* ! OS2 && ! VMS && (! _WIN32 || CYGWIN) && ! __INTERIX */
if (errorcount)
exit (FATAL_EXIT_CODE);
@@ -4873,12 +5469,12 @@ main (argc, argv, envp)
/* Decode -m switches. */
/* Decode the switch -mNAME. */
-void
+static void
set_target_switch (name)
- char *name;
+ const char *name;
{
register size_t j;
- int valid = 0;
+ int valid_target_option = 0;
for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++)
if (!strcmp (target_switches[j].name, name))
@@ -4887,23 +5483,23 @@ set_target_switch (name)
target_flags &= ~-target_switches[j].value;
else
target_flags |= target_switches[j].value;
- valid = 1;
+ valid_target_option = 1;
}
#ifdef TARGET_OPTIONS
- if (!valid)
+ if (!valid_target_option)
for (j = 0; j < sizeof target_options / sizeof target_options[0]; j++)
{
int len = strlen (target_options[j].prefix);
if (!strncmp (target_options[j].prefix, name, len))
{
*target_options[j].variable = name + len;
- valid = 1;
+ valid_target_option = 1;
}
}
#endif
- if (!valid)
+ if (!valid_target_option)
error ("Invalid option `%s'", name);
}
@@ -4911,33 +5507,33 @@ set_target_switch (name)
Each line begins with INDENT (for the case where FILE is the
assembler output file). */
-void
+static void
print_version (file, indent)
FILE *file;
- char *indent;
+ const char *indent;
{
- fprintf (file, "%s%s%s version %s", indent, *indent != 0 ? " " : "",
- language_string, version_string);
- fprintf (file, " (%s)", TARGET_NAME);
-#ifdef __GNUC__
#ifndef __VERSION__
-#define __VERSION__ "[unknown]"
+#define __VERSION__ "[?]"
#endif
- fprintf (file, " compiled by GNU C version %s.\n", __VERSION__);
+ fnotice (file,
+#ifdef __GNUC__
+ "%s%s%s version %s (%s) compiled by GNU C version %s.\n"
#else
- fprintf (file, " compiled by CC.\n");
+ "%s%s%s version %s (%s) compiled by CC.\n"
#endif
+ , indent, *indent != 0 ? " " : "",
+ language_string, version_string, TARGET_NAME, __VERSION__);
}
/* Print an option value and return the adjusted position in the line.
??? We don't handle error returns from fprintf (disk full); presumably
other code will catch a disk full though. */
-int
+static int
print_single_switch (file, pos, max, indent, sep, term, type, name)
FILE *file;
int pos, max;
- char *indent, *sep, *term, *type, *name;
+ const char *indent, *sep, *term, *type, *name;
{
/* The ultrix fprintf returns 0 on success, so compute the result we want
here since we need it for the following test. */
@@ -4964,11 +5560,11 @@ print_single_switch (file, pos, max, indent, sep, term, type, name)
Each line begins with INDENT and ends with TERM.
Each switch is separated from the next by SEP. */
-void
+static void
print_switch_values (file, pos, max, indent, sep, term)
FILE *file;
int pos, max;
- char *indent, *sep, *term;
+ const char *indent, *sep, *term;
{
size_t j;
char **p;
@@ -4976,7 +5572,7 @@ print_switch_values (file, pos, max, indent, sep, term)
/* Print the options as passed. */
pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
- "options passed: ", "");
+ _("options passed: "), "");
for (p = &save_argv[1]; *p != NULL; p++)
if (**p == '-')
@@ -5005,7 +5601,7 @@ print_switch_values (file, pos, max, indent, sep, term)
should suffice. */
pos = print_single_switch (file, 0, max, indent, *indent ? " " : "", term,
- "options enabled: ", "");
+ _("options enabled: "), "");
for (j = 0; j < sizeof f_options / sizeof f_options[0]; j++)
if (*f_options[j].variable == f_options[j].on_value)
@@ -5042,7 +5638,7 @@ print_switch_values (file, pos, max, indent, sep, term)
void
debug_start_source_file (filename)
- register char *filename;
+ register char *filename ATTRIBUTE_UNUSED;
{
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
@@ -5069,7 +5665,7 @@ debug_start_source_file (filename)
void
debug_end_source_file (lineno)
- register unsigned lineno;
+ register unsigned lineno ATTRIBUTE_UNUSED;
{
#ifdef DBX_DEBUGGING_INFO
if (write_symbols == DBX_DEBUG)
@@ -5097,8 +5693,8 @@ debug_end_source_file (lineno)
void
debug_define (lineno, buffer)
- register unsigned lineno;
- register char *buffer;
+ register unsigned lineno ATTRIBUTE_UNUSED;
+ register char *buffer ATTRIBUTE_UNUSED;
{
#ifdef DWARF_DEBUGGING_INFO
if (debug_info_level == DINFO_LEVEL_VERBOSE
@@ -5118,8 +5714,8 @@ debug_define (lineno, buffer)
void
debug_undef (lineno, buffer)
- register unsigned lineno;
- register char *buffer;
+ register unsigned lineno ATTRIBUTE_UNUSED;
+ register char *buffer ATTRIBUTE_UNUSED;
{
#ifdef DWARF_DEBUGGING_INFO
if (debug_info_level == DINFO_LEVEL_VERBOSE
diff --git a/contrib/gcc/toplev.h b/contrib/gcc/toplev.h
index d206000..3ffad1f 100644
--- a/contrib/gcc/toplev.h
+++ b/contrib/gcc/toplev.h
@@ -1,65 +1,118 @@
/* toplev.h - Various declarations for functions found in toplev.c
- Copyright (C) 1998 Free Software Foundation, Inc.
- */
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#ifndef __GCC_TOPLEV_H__
#define __GCC_TOPLEV_H__
-#ifdef __STDC__
+#ifdef ANSI_PROTOTYPES
union tree_node;
struct rtx_def;
#endif
+extern int read_integral_parameter PROTO ((const char *, const char *,
+ const int));
extern int count_error PROTO ((int));
extern void strip_off_ending PROTO ((char *, int));
-extern void print_time PROTO ((char *, int));
-extern int get_run_time PROTO ((void));
+extern void print_time PROTO ((const char *, int));
extern void debug_start_source_file PROTO ((char *));
extern void debug_end_source_file PROTO ((unsigned));
extern void debug_define PROTO ((unsigned, char *));
extern void debug_undef PROTO ((unsigned, char *));
-extern void fatal PVPROTO ((char *, ...))
- ATTRIBUTE_PRINTF_1;
-extern void fatal_io_error PROTO ((char *));
-extern void pfatal_with_name PROTO ((char *));
-extern void warning PVPROTO ((char *, ...))
- ATTRIBUTE_PRINTF_1;
-extern void error PVPROTO ((char *, ...))
+extern void fatal PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+extern void fatal_io_error PROTO ((const char *))
+ ATTRIBUTE_NORETURN;
+extern void pfatal_with_name PROTO ((const char *))
+ ATTRIBUTE_NORETURN;
+extern void fatal_insn_not_found PROTO ((struct rtx_def *))
+ ATTRIBUTE_NORETURN;
+extern void fatal_insn PVPROTO ((const char *,
+ struct rtx_def *, ...))
+ ATTRIBUTE_PRINTF(1, 3) ATTRIBUTE_NORETURN;
+extern void warning PVPROTO ((const char *, ...))
ATTRIBUTE_PRINTF_1;
-extern void pedwarn PVPROTO ((char *, ...))
+extern void error PVPROTO ((const char *, ...))
ATTRIBUTE_PRINTF_1;
-extern void pedwarn_with_file_and_line PVPROTO ((char *, int, char *, ...))
- ATTRIBUTE_PRINTF_3;
-extern void warning_with_file_and_line PVPROTO ((char *, int, char *, ...))
- ATTRIBUTE_PRINTF_3;
-extern void error_with_file_and_line PVPROTO ((char *, int, char *, ...))
- ATTRIBUTE_PRINTF_3;
-extern void sorry PVPROTO ((char *s, ...))
+extern void pedwarn PVPROTO ((const char *, ...))
ATTRIBUTE_PRINTF_1;
-extern void default_print_error_function PROTO ((char *));
-extern void report_error_function PROTO ((char *));
+extern void pedwarn_with_file_and_line PVPROTO ((const char *, int,
+ const char *, ...))
+ ATTRIBUTE_PRINTF_3;
+extern void warning_with_file_and_line PVPROTO ((const char *, int,
+ const char *, ...))
+ ATTRIBUTE_PRINTF_3;
+extern void error_with_file_and_line PVPROTO ((const char *, int,
+ const char *, ...))
+ ATTRIBUTE_PRINTF_3;
+extern void sorry PVPROTO ((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
+extern void really_sorry PVPROTO((const char *, ...))
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+extern void default_print_error_function PROTO ((const char *));
+extern void report_error_function PROTO ((const char *));
-extern void rest_of_decl_compilation PROTO ((union tree_node *, char *, int, int));
+extern void rest_of_decl_compilation PROTO ((union tree_node *,
+ const char *, int, int));
extern void rest_of_type_compilation PROTO ((union tree_node *, int));
extern void rest_of_compilation PROTO ((union tree_node *));
-extern void pedwarn_with_decl PVPROTO ((union tree_node *, char *, ...));
-extern void warning_with_decl PVPROTO ((union tree_node *, char *, ...));
-extern void error_with_decl PVPROTO ((union tree_node *, char *, ...));
+
+/* The *_with_decl functions aren't suitable for ATTRIBUTE_PRINTF. */
+extern void pedwarn_with_decl PVPROTO ((union tree_node *,
+ const char *, ...));
+extern void warning_with_decl PVPROTO ((union tree_node *,
+ const char *, ...));
+extern void error_with_decl PVPROTO ((union tree_node *,
+ const char *, ...));
+
extern void announce_function PROTO ((union tree_node *));
-extern void error_for_asm PVPROTO((struct rtx_def *, char *, ...))
- ATTRIBUTE_PRINTF_2;
-extern void warning_for_asm PVPROTO((struct rtx_def *, char *, ...))
- ATTRIBUTE_PRINTF_2;
-#ifdef _JBLEN
+extern void error_for_asm PVPROTO((struct rtx_def *,
+ const char *, ...))
+ ATTRIBUTE_PRINTF_2;
+extern void warning_for_asm PVPROTO((struct rtx_def *,
+ const char *, ...))
+ ATTRIBUTE_PRINTF_2;
+#if defined (_JBLEN) || defined (setjmp)
extern void set_float_handler PROTO((jmp_buf));
+extern int push_float_handler PROTO((jmp_buf, jmp_buf));
+extern void pop_float_handler PROTO((int, jmp_buf));
#endif
+extern int do_float_handler PROTO((void (*) (PTR), PTR));
#ifdef BUFSIZ
-extern void output_quoted_string PROTO ((FILE *, char *));
-extern void output_file_directive PROTO ((FILE *, char *));
+extern void output_quoted_string PROTO ((FILE *, const char *));
+extern void output_file_directive PROTO ((FILE *, const char *));
#endif
-extern void fancy_abort PROTO ((void));
+extern void fancy_abort PROTO ((void)) ATTRIBUTE_NORETURN;
+extern void do_abort PROTO ((void)) ATTRIBUTE_NORETURN;
+extern void botch PROTO ((const char *))
+ ATTRIBUTE_NORETURN;
+
+#ifdef BUFSIZ
+extern void fnotice PROTO ((FILE *, const char *, ...))
+ ATTRIBUTE_PRINTF_2;
+#endif
+#undef trim_filename
+extern const char *trim_filename PROTO ((const char *));
+extern int wrapup_global_declarations PROTO ((union tree_node **, int));
+extern void check_global_declarations PROTO ((union tree_node **, int));
#endif /* __GCC_TOPLEV_H */
diff --git a/contrib/gcc/tree.c b/contrib/gcc/tree.c
index ebe6e14..5e29d2f 100644
--- a/contrib/gcc/tree.c
+++ b/contrib/gcc/tree.c
@@ -1,5 +1,5 @@
/* Language-independent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -34,13 +34,7 @@ Boston, MA 02111-1307, USA. */
by all passes of the compiler. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
-#include <setjmp.h>
#include "flags.h"
#include "tree.h"
#include "except.h"
@@ -230,7 +224,7 @@ int tree_node_counts[(int)all_kinds];
int tree_node_sizes[(int)all_kinds];
int id_string_size = 0;
-char *tree_node_kind_names[] = {
+const char *tree_node_kind_names[] = {
"decls",
"types",
"blocks",
@@ -269,7 +263,9 @@ int (*lang_get_alias_set) PROTO((tree));
codes are made. */
#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
+static void set_type_quals PROTO((tree, int));
static void append_random_chars PROTO((char *));
+static void build_real_from_int_cst_1 PROTO((PTR));
extern char *mode_name[];
@@ -324,8 +320,11 @@ gcc_obstack_init (obstack)
(void (*) ()) OBSTACK_CHUNK_FREE);
}
-/* Save all variables describing the current status into the structure *P.
- This is used before starting a nested function.
+/* Save all variables describing the current status into the structure
+ *P. This function is called whenever we start compiling one
+ function in the midst of compiling another. For example, when
+ compiling a nested function, or, in C++, a template instantiation
+ that is required by the function we are currently compiling.
CONTEXT is the decl_function_context for the function we're about to
compile; if it isn't current_function_decl, we have to play some games. */
@@ -349,7 +348,7 @@ save_tree_status (p, context)
p->rtl_obstack = rtl_obstack;
p->inline_obstacks = inline_obstacks;
- if (context == current_function_decl)
+ if (current_function_decl && context == current_function_decl)
/* Objects that need to be saved in this function can be in the nonsaved
obstack of the enclosing function since they can't possibly be needed
once it has returned. */
@@ -747,10 +746,10 @@ void
print_obstack_name (object, file, prefix)
char *object;
FILE *file;
- char *prefix;
+ const char *prefix;
{
struct obstack *obstack = NULL;
- char *obstack_name = NULL;
+ const char *obstack_name = NULL;
struct function *p;
for (p = outer_function_chain; p; p = p->next)
@@ -944,7 +943,6 @@ make_node (code)
register int type = TREE_CODE_CLASS (code);
register int length = 0;
register struct obstack *obstack = current_obstack;
- register int i;
#ifdef GATHER_STATISTICS
register tree_node_kind kind;
#endif
@@ -1075,19 +1073,13 @@ make_node (code)
}
t = (tree) obstack_alloc (obstack, length);
+ bzero ((PTR) t, length);
#ifdef GATHER_STATISTICS
tree_node_counts[(int)kind]++;
tree_node_sizes[(int)kind] += length;
#endif
- /* Clear a word at a time. */
- for (i = (length / sizeof (int)) - 1; i >= 0; i--)
- ((int *) t)[i] = 0;
- /* Clear any extra bytes. */
- for (i = length / sizeof (int) * sizeof (int); i < length; i++)
- ((char *) t)[i] = 0;
-
TREE_SET_CODE (t, code);
if (obstack == &permanent_obstack)
TREE_PERMANENT (t) = 1;
@@ -1107,6 +1099,9 @@ make_node (code)
DECL_SOURCE_LINE (t) = lineno;
DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : "<built-in>";
DECL_UID (t) = next_decl_uid++;
+ /* Note that we have not yet computed the alias set for this
+ declaration. */
+ DECL_POINTER_ALIAS_SET (t) = -1;
break;
case 't':
@@ -1141,7 +1136,6 @@ copy_node (node)
register tree t;
register enum tree_code code = TREE_CODE (node);
register int length = 0;
- register int i;
switch (TREE_CODE_CLASS (code))
{
@@ -1190,12 +1184,7 @@ copy_node (node)
}
t = (tree) obstack_alloc (current_obstack, length);
-
- for (i = (length / sizeof (int)) - 1; i >= 0; i--)
- ((int *) t)[i] = ((int *) node)[i];
- /* Clear any extra bytes. */
- for (i = length / sizeof (int) * sizeof (int); i < length; i++)
- ((char *) t)[i] = ((char *) node)[i];
+ memcpy (t, node, length);
/* EXPR_WITH_FILE_LOCATION must keep filename info stored in TREE_CHAIN */
if (TREE_CODE (node) != EXPR_WITH_FILE_LOCATION)
@@ -1255,7 +1244,7 @@ copy_list (list)
tree
get_identifier (text)
- register char *text;
+ register const char *text;
{
register int hi;
register int i;
@@ -1263,11 +1252,11 @@ get_identifier (text)
register int len, hash_len;
/* Compute length of text in len. */
- for (len = 0; text[len]; len++);
+ len = strlen (text);
/* Decide how much of that length to hash on */
hash_len = len;
- if (warn_id_clash && len > id_clash_len)
+ if (warn_id_clash && (unsigned)len > id_clash_len)
hash_len = id_clash_len;
/* Compute hash code */
@@ -1286,7 +1275,7 @@ get_identifier (text)
return idp; /* <-- return if found */
/* Not found; optionally warn about a similar identifier */
- if (warn_id_clash && do_identifier_warnings && len >= id_clash_len)
+ if (warn_id_clash && do_identifier_warnings && (unsigned)len >= id_clash_len)
for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
if (!strncmp (IDENTIFIER_POINTER (idp), text, id_clash_len))
{
@@ -1318,7 +1307,7 @@ get_identifier (text)
tree
maybe_get_identifier (text)
- register char *text;
+ register const char *text;
{
register int hi;
register int i;
@@ -1326,11 +1315,11 @@ maybe_get_identifier (text)
register int len, hash_len;
/* Compute length of text in len. */
- for (len = 0; text[len]; len++);
+ len = strlen (text);
/* Decide how much of that length to hash on */
hash_len = len;
- if (warn_id_clash && len > id_clash_len)
+ if (warn_id_clash && (unsigned)len > id_clash_len)
hash_len = id_clash_len;
/* Compute hash code */
@@ -1461,6 +1450,29 @@ real_value_from_int_cst (type, i)
return d;
}
+struct brfic_args
+{
+ /* Input */
+ tree type, i;
+ /* Output */
+ REAL_VALUE_TYPE d;
+};
+
+static void
+build_real_from_int_cst_1 (data)
+ PTR data;
+{
+ struct brfic_args * args = (struct brfic_args *) data;
+
+#ifdef REAL_ARITHMETIC
+ args->d = real_value_from_int_cst (args->type, args->i);
+#else
+ args->d =
+ REAL_VALUE_TRUNCATE (TYPE_MODE (args->type),
+ real_value_from_int_cst (args->type, args->i));
+#endif
+}
+
/* This function can't be implemented if we can't do arithmetic
on the float representation. */
@@ -1472,32 +1484,29 @@ build_real_from_int_cst (type, i)
tree v;
int overflow = TREE_OVERFLOW (i);
REAL_VALUE_TYPE d;
- jmp_buf float_error;
+ struct brfic_args args;
v = make_node (REAL_CST);
TREE_TYPE (v) = type;
- if (setjmp (float_error))
+ /* Setup input for build_real_from_int_cst_1() */
+ args.type = type;
+ args.i = i;
+
+ if (do_float_handler (build_real_from_int_cst_1, (PTR) &args))
{
+ /* Receive output from build_real_from_int_cst_1() */
+ d = args.d;
+ }
+ else
+ {
+ /* We got an exception from build_real_from_int_cst_1() */
d = dconst0;
overflow = 1;
- goto got_it;
}
-
- set_float_handler (float_error);
-
-#ifdef REAL_ARITHMETIC
- d = real_value_from_int_cst (type, i);
-#else
- d = REAL_VALUE_TRUNCATE (TYPE_MODE (type),
- real_value_from_int_cst (type, i));
-#endif
-
+
/* Check for valid float value for this type on this target machine. */
- got_it:
- set_float_handler (NULL_PTR);
-
#ifdef CHECK_FLOAT_VALUE
CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);
#endif
@@ -1516,7 +1525,7 @@ build_real_from_int_cst (type, i)
tree
build_string (len, str)
int len;
- char *str;
+ const char *str;
{
/* Put the string in saveable_obstack since it will be placed in the RTL
for an "asm" statement and will also be kept around a while if
@@ -1558,7 +1567,6 @@ make_tree_vec (len)
register tree t;
register int length = (len-1) * sizeof (tree) + sizeof (struct tree_vec);
register struct obstack *obstack = current_obstack;
- register int i;
#ifdef GATHER_STATISTICS
tree_node_counts[(int)vec_kind]++;
@@ -1566,9 +1574,7 @@ make_tree_vec (len)
#endif
t = (tree) obstack_alloc (obstack, length);
-
- for (i = (length / sizeof (int)) - 1; i >= 0; i--)
- ((int *) t)[i] = 0;
+ bzero ((PTR) t, length);
TREE_SET_CODE (t, TREE_VEC);
TREE_VEC_LENGTH (t) = len;
@@ -1950,9 +1956,11 @@ chainon (op1, op2)
for (t1 = op1; TREE_CHAIN (t1); t1 = TREE_CHAIN (t1))
;
TREE_CHAIN (t1) = op2;
+#ifdef ENABLE_CHECKING
for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
if (t2 == t1)
abort (); /* Circularity created. */
+#endif
return op1;
}
else return op2;
@@ -2401,6 +2409,7 @@ first_rtl_op (code)
{
case SAVE_EXPR:
return 2;
+ case GOTO_SUBROUTINE_EXPR:
case RTL_EXPR:
return 0;
case CALL_EXPR:
@@ -2594,6 +2603,7 @@ has_cleanups (exp)
switch (TREE_CODE (exp))
{
case TARGET_EXPR:
+ case GOTO_SUBROUTINE_EXPR:
case WITH_CLEANUP_EXPR:
return 1;
@@ -2984,7 +2994,7 @@ stabilize_reference_1 (e)
tree
build VPROTO((enum tree_code code, tree tt, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
enum tree_code code;
tree tt;
#endif
@@ -2995,7 +3005,7 @@ build VPROTO((enum tree_code code, tree tt, ...))
VA_START (p, tt);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
code = va_arg (p, enum tree_code);
tt = va_arg (p, tree);
#endif
@@ -3059,7 +3069,7 @@ build1 (code, type, node)
tree node;
{
register struct obstack *obstack = expression_obstack;
- register int i, length;
+ register int length;
#ifdef GATHER_STATISTICS
register tree_node_kind kind;
#endif
@@ -3075,15 +3085,13 @@ build1 (code, type, node)
length = sizeof (struct tree_exp);
t = (tree) obstack_alloc (obstack, length);
+ bzero ((PTR) t, length);
#ifdef GATHER_STATISTICS
tree_node_counts[(int)kind]++;
tree_node_sizes[(int)kind] += length;
#endif
- for (i = (length / sizeof (int)) - 1; i >= 0; i--)
- ((int *) t)[i] = 0;
-
TREE_TYPE (t) = type;
TREE_SET_CODE (t, code);
@@ -3110,7 +3118,7 @@ build1 (code, type, node)
tree
build_nt VPROTO((enum tree_code code, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
enum tree_code code;
#endif
va_list p;
@@ -3120,7 +3128,7 @@ build_nt VPROTO((enum tree_code code, ...))
VA_START (p, code);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
code = va_arg (p, enum tree_code);
#endif
@@ -3140,7 +3148,7 @@ build_nt VPROTO((enum tree_code code, ...))
tree
build_parse_node VPROTO((enum tree_code code, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
enum tree_code code;
#endif
register struct obstack *ambient_obstack = expression_obstack;
@@ -3151,7 +3159,7 @@ build_parse_node VPROTO((enum tree_code code, ...))
VA_START (p, code);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
code = va_arg (p, enum tree_code);
#endif
@@ -3239,10 +3247,10 @@ build_block (vars, tags, subblocks, supercontext, chain)
tree
build_expr_wfl (node, file, line, col)
tree node;
- char *file;
+ const char *file;
int line, col;
{
- static char *last_file = 0;
+ static const char *last_file = 0;
static tree last_filenode = NULL_TREE;
register tree wfl = make_node (EXPR_WITH_FILE_LOCATION);
@@ -3292,7 +3300,6 @@ build_type_attribute_variant (ttype, attribute)
current_obstack = TYPE_OBSTACK (ttype);
ntype = copy_node (ttype);
- current_obstack = ambient_obstack;
TYPE_POINTER_TO (ntype) = 0;
TYPE_REFERENCE_TO (ntype) = 0;
@@ -3301,7 +3308,7 @@ build_type_attribute_variant (ttype, attribute)
/* Create a new main variant of TYPE. */
TYPE_MAIN_VARIANT (ntype) = ntype;
TYPE_NEXT_VARIANT (ntype) = 0;
- TYPE_READONLY (ntype) = TYPE_VOLATILE (ntype) = 0;
+ set_type_quals (ntype, TYPE_UNQUALIFIED);
hashcode = TYPE_HASH (TREE_CODE (ntype))
+ TYPE_HASH (TREE_TYPE (ntype))
@@ -3326,8 +3333,13 @@ build_type_attribute_variant (ttype, attribute)
}
ntype = type_hash_canon (hashcode, ntype);
- ttype = build_type_variant (ntype, TYPE_READONLY (ttype),
- TYPE_VOLATILE (ttype));
+ ttype = build_qualified_type (ntype, TYPE_QUALS (ttype));
+
+ /* We must restore the current obstack after the type_hash_canon call,
+ because type_hash_canon calls type_hash_add for permanent types, and
+ then type_hash_add calls oballoc expecting to get something permanent
+ back. */
+ current_obstack = ambient_obstack;
}
return ttype;
@@ -3339,11 +3351,12 @@ build_type_attribute_variant (ttype, attribute)
int
valid_machine_attribute (attr_name, attr_args, decl, type)
- tree attr_name, attr_args;
- tree decl;
- tree type;
+ tree attr_name;
+ tree attr_args ATTRIBUTE_UNUSED;
+ tree decl ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
{
- int valid = 0;
+ int validated = 0;
#ifdef VALID_MACHINE_DECL_ATTRIBUTE
tree decl_attr_list = decl != 0 ? DECL_MACHINE_ATTRIBUTES (decl) : 0;
#endif
@@ -3373,12 +3386,15 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
decl = build_decl_attribute_variant (decl, decl_attr_list);
}
- valid = 1;
+ validated = 1;
}
#endif
#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
- if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name, attr_args))
+ if (validated)
+ /* Don't apply the attribute to both the decl and the type. */;
+ else if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name,
+ attr_args))
{
tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
type_attr_list);
@@ -3404,7 +3420,7 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
}
if (decl != 0)
TREE_TYPE (decl) = type;
- valid = 1;
+ validated = 1;
}
/* Handle putting a type attribute on pointer-to-function-type by putting
@@ -3430,12 +3446,19 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
if (decl != 0)
TREE_TYPE (decl) = build_pointer_type (inner_type);
+ else
+ {
+ /* Clear TYPE_POINTER_TO for the old inner type, since
+ `type' won't be pointing to it anymore. */
+ TYPE_POINTER_TO (TREE_TYPE (type)) = NULL_TREE;
+ TREE_TYPE (type) = inner_type;
+ }
- valid = 1;
+ validated = 1;
}
#endif
- return valid;
+ return validated;
}
/* Return non-zero if IDENT is a valid name for attribute ATTR,
@@ -3448,7 +3471,7 @@ valid_machine_attribute (attr_name, attr_args, decl, type)
int
is_attribute_p (attr, ident)
- char *attr;
+ const char *attr;
tree ident;
{
int ident_len, attr_len;
@@ -3493,7 +3516,7 @@ is_attribute_p (attr, ident)
tree
lookup_attribute (attr_name, list)
- char *attr_name;
+ const char *attr_name;
tree list;
{
tree l;
@@ -3579,45 +3602,44 @@ merge_machine_decl_attributes (olddecl, newdecl)
#endif
}
-/* Return a type like TYPE except that its TYPE_READONLY is CONSTP
- and its TYPE_VOLATILE is VOLATILEP.
+/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
+ of the various TYPE_QUAL values. */
- Such variant types already made are recorded so that duplicates
- are not made.
+static void
+set_type_quals (type, type_quals)
+ tree type;
+ int type_quals;
+{
+ TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
+ TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
+ TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+}
- A variant types should never be used as the type of an expression.
- Always copy the variant information into the TREE_READONLY
- and TREE_THIS_VOLATILE of the expression, and then give the expression
- as its type the "main variant", the variant whose TYPE_READONLY
- and TYPE_VOLATILE are zero. Use TYPE_MAIN_VARIANT to find the
- main variant. */
+/* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
+ the same kind of data as TYPE describes. Variants point to the
+ "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
+ and it points to a chain of other variants so that duplicate
+ variants are never made. Only main variants should ever appear as
+ types of expressions. */
tree
-build_type_variant (type, constp, volatilep)
+build_qualified_type (type, type_quals)
tree type;
- int constp, volatilep;
+ int type_quals;
{
register tree t;
-
- /* Treat any nonzero argument as 1. */
- constp = !!constp;
- volatilep = !!volatilep;
-
+
/* Search the chain of variants to see if there is already one there just
like the one we need to have. If so, use that existing one. We must
preserve the TYPE_NAME, since there is code that depends on this. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t)
- && TYPE_NAME (t) == TYPE_NAME (type))
+ if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
return t;
/* We need a new one. */
-
t = build_type_copy (type);
- TYPE_READONLY (t) = constp;
- TYPE_VOLATILE (t) = volatilep;
-
+ set_type_quals (t, type_quals);
return t;
}
@@ -3960,10 +3982,13 @@ simple_cst_equal (t1, t2)
code2 = TREE_CODE (t2);
if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
- if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
- return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
- else
- return simple_cst_equal (TREE_OPERAND (t1, 0), t2);
+ {
+ if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ || code2 == NON_LVALUE_EXPR)
+ return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ else
+ return simple_cst_equal (TREE_OPERAND (t1, 0), t2);
+ }
else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
|| code2 == NON_LVALUE_EXPR)
return simple_cst_equal (t1, TREE_OPERAND (t2, 0));
@@ -4422,8 +4447,7 @@ build_complex_type (component_type)
t = make_node (COMPLEX_TYPE);
TREE_TYPE (t) = TYPE_MAIN_VARIANT (component_type);
- TYPE_VOLATILE (t) = TYPE_VOLATILE (component_type);
- TYPE_READONLY (t) = TYPE_READONLY (component_type);
+ set_type_quals (t, TYPE_QUALS (component_type));
/* If we already have such a type, use the old one and free this one. */
hashcode = TYPE_HASH (component_type);
@@ -4745,7 +4769,7 @@ print_inline_obstack_statistics ()
void
print_obstack_statistics (str, o)
- char *str;
+ const char *str;
struct obstack *o;
{
struct _obstack_chunk *chunk = o->chunk;
@@ -4870,7 +4894,7 @@ append_random_chars (template)
tree
get_file_function_name_long (type)
- char *type;
+ const char *type;
{
char *buf;
register char *p;
@@ -4882,8 +4906,8 @@ get_file_function_name_long (type)
/* We don't have anything that we know to be unique to this translation
unit, so use what we do have and throw in some randomness. */
- char *name = weak_global_object_name;
- char *file = main_input_filename;
+ const char *name = weak_global_object_name;
+ const char *file = main_input_filename;
if (! name)
name = "";
@@ -5053,7 +5077,7 @@ tree
tree_check (node, code, file, line, nofatal)
tree node;
enum tree_code code;
- char *file;
+ const char *file;
int line;
int nofatal;
{
@@ -5073,7 +5097,7 @@ tree
tree_class_check (node, cl, file, line, nofatal)
tree node;
char cl;
- char *file;
+ const char *file;
int line;
int nofatal;
{
@@ -5092,7 +5116,7 @@ tree
expr_check (node, ignored, file, line, nofatal)
tree node;
int ignored;
- char *file;
+ const char *file;
int line;
int nofatal;
{
@@ -5121,7 +5145,8 @@ expr_check (node, ignored, file, line, nofatal)
/* Return the alias set for T, which may be either a type or an
expression. */
-int get_alias_set (t)
+int
+get_alias_set (t)
tree t;
{
if (!flag_strict_aliasing || !lang_get_alias_set)
@@ -5131,3 +5156,15 @@ int get_alias_set (t)
else
return (*lang_get_alias_set) (t);
}
+
+/* Return a brand-new alias set. */
+
+int
+new_alias_set ()
+{
+ static int last_alias_set;
+ if (flag_strict_aliasing)
+ return ++last_alias_set;
+ else
+ return 0;
+}
diff --git a/contrib/gcc/tree.def b/contrib/gcc/tree.def
index 632358b..2056c62 100644
--- a/contrib/gcc/tree.def
+++ b/contrib/gcc/tree.def
@@ -1,6 +1,6 @@
/* This file contains the definitions and documentation for the
tree codes used in the GNU C compiler.
- Copyright (C) 1987, 1988, 1993, 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -82,7 +82,7 @@ DEFTREECODE (TREE_VEC, "tree_vec", 'x', 2)
outermost scope of a particular inlining of a function).
BLOCK_ABSTRACT is non-zero if the block represents an abstract
instance of a block (i.e. one which is nested within an abstract
- instance of a inline function. */
+ instance of an inline function). */
DEFTREECODE (BLOCK, "block", 'b', 0)
/* Each data type is represented by a tree node whose code is one of
@@ -98,8 +98,14 @@ DEFTREECODE (BLOCK, "block", 'b', 0)
points to the start of the chain.
The TYPE_NONCOPIED_PARTS field is a list specifying which parts
of an object of this type should *not* be copied by assignment.
- The TREE_PURPOSE of each element is the offset of the part
- and the TREE_VALUE is the size in bits of the part.
+ The TREE_VALUE of each is a FIELD_DECL that should not be
+ copied. The TREE_PURPOSE is an initial value for that field when
+ an object of this type is initialized via an INIT_EXPR. It may
+ be NULL if no special value is required. Even the things in this
+ list are copied if the right-hand side of an assignment is known
+ to be a complete object (rather than being, perhaps, a subobject
+ of some other object.) The determination of what constitutes a
+ complete object is done by fixed_type_p.
The TYPE_NAME field contains info on the name used in the program
for this type (for GDB symbol table output). It is either a
TYPE_DECL node, for types that are typedefs, or an IDENTIFIER_NODE
@@ -306,11 +312,10 @@ DEFTREECODE (STRING_CST, "string_cst", 'c', 3)
DECL_RESULT holds a RESULT_DECL node for the value of a function,
or it is 0 for a function that returns no value.
(C functions returning void have zero here.)
- DECL_RESULT_TYPE holds the type in which the result is actually
- returned. This is usually the same as the type of DECL_RESULT,
- but (1) it may be a wider integer type and
- (2) it remains valid, for the sake of inlining, even after the
- function's compilation is done.
+ The TREE_TYPE field is the type in which the result is actually
+ returned. This is usually the same as the return type of the
+ FUNCTION_DECL, but it may be a wider integer type because of
+ promotion.
DECL_FUNCTION_CODE is a code number that is nonzero for
built-in functions. Its value is an enum built_in_function
that says which built-in function it is.
@@ -359,8 +364,7 @@ DEFTREECODE (INDIRECT_REF, "indirect_ref", 'r', 1)
DEFTREECODE (BUFFER_REF, "buffer_ref", 'r', 1)
/* Array indexing in languages other than C.
- Operand 0 is the array; operand 1 is a list of indices
- stored as a chain of TREE_LIST nodes. */
+ Operand 0 is the array; operand 1 is a (single) array index. */
DEFTREECODE (ARRAY_REF, "array_ref", 'r', 2)
/* Constructor: return an aggregate value made from specified components.
@@ -704,6 +708,27 @@ DEFTREECODE (POSTINCREMENT_EXPR, "postincrement_expr", 'e', 2)
evaluated unless an exception is throw. */
DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", 'e', 2)
+/* Evaluate the first operand.
+ The second operand is a a cleanup expression which is evaluated
+ before an exit (normal, exception, or jump out) from this expression.
+
+ Like a CLEANUP_POINT_EXPR/WITH_CLEANUP_EXPR combination, but those
+ always copy the cleanup expression where needed. In contrast,
+ TRY_FINALLY_EXPR generates a jump to a cleanup subroutine.
+ (At least conceptually; the optimizer could inline the cleanup
+ subroutine in the same way it could inline normal subroutines.)
+ TRY_FINALLY_EXPR should be used when the cleanup is actual statements
+ in the source of the current function (which people might want to
+ set breakpoints in). */
+DEFTREECODE (TRY_FINALLY_EXPR, "try_finally", 'e', 2)
+
+/* Used internally for cleanups in the implementation of TRY_FINALLY_EXPR.
+ (Specifically, it is created by expand_expr, not front-ends.)
+ Operand 0 is the rtx for the start of the subroutine we need to call.
+ Operand 1 is the rtx for a variable in which to store the address
+ of where the subroutine should return to. */
+DEFTREECODE (GOTO_SUBROUTINE_EXPR, "goto_subroutine", 'e', 2)
+
/* Pop the top element off the dynamic handler chain. Used in
conjunction with setjmp/longjmp based exception handling, see
except.c for more details. This is meant to be used only by the
@@ -723,7 +748,7 @@ DEFTREECODE (POPDCC_EXPR, "popdcc_expr", 's', 0)
The type should be void and the value should be ignored. */
DEFTREECODE (LABEL_EXPR, "label_expr", 's', 1)
-/* GOTO. Operand 0 is a LABEL_DECL node.
+/* GOTO. Operand 0 is a LABEL_DECL node or an expression.
The type should be void and the value should be ignored. */
DEFTREECODE (GOTO_EXPR, "goto_expr", 's', 1)
@@ -743,11 +768,28 @@ DEFTREECODE (EXIT_EXPR, "exit_expr", 's', 1)
The type should be void and the value should be ignored. */
DEFTREECODE (LOOP_EXPR, "loop_expr", 's', 1)
-/* Used to represent a tree node, such as IDENTIFIER_NODE or an EXPR
- node, adding several location information: a file name, a line
- number and column number. It is expanded as the node it refers to
- and can be considered a no-op "conversion" with an annotation. */
-DEFTREECODE (EXPR_WITH_FILE_LOCATION, "expr_with_file_location", '1', 2)
+/* A labeled block. Operand 0 is the label that will be generated to
+ mark the end of the block.
+ Operand 1 is the labeled block body. */
+DEFTREECODE (LABELED_BLOCK_EXPR, "labeled_block_expr", 'e', 2)
+
+/* Exit a labeled block, possibly returning a value. Operand 0 is a
+ LABELED_BLOCK_EXPR to exit. Operand 1 is the value to return. It
+ may be left null. */
+DEFTREECODE (EXIT_BLOCK_EXPR, "exit_block_expr", 'e', 2)
+
+/* Annotates a tree node (usually an expression) with source location
+ information: a file name (EXPR_WFL_FILENAME); a line number
+ (EXPR_WFL_LINENO); and column number (EXPR_WFL_COLNO). It is
+ expanded as the contained node (EXPR_WFL_NODE); a line note should
+ be emitted first if EXPR_WFL_EMIT_LINE_NOTE. */
+DEFTREECODE (EXPR_WITH_FILE_LOCATION, "expr_with_file_location", 'e', 2)
+
+/* Switch expression.
+ Operand 0 is the expression used to perform the branch,
+ Operand 1 contains the case values. The way they're organized is
+ front-end implementation defined. */
+DEFTREECODE (SWITCH_EXPR, "switch_expr", 'e', 2)
/*
Local variables:
mode:c
diff --git a/contrib/gcc/tree.h b/contrib/gcc/tree.h
index 039170e..0d7ea84 100644
--- a/contrib/gcc/tree.h
+++ b/contrib/gcc/tree.h
@@ -1,5 +1,5 @@
/* Front-end tree definitions for GNU compiler.
- Copyright (C) 1989, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 93-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -101,7 +101,6 @@ enum built_in_function
BUILT_IN_FRAME_ADDRESS,
BUILT_IN_RETURN_ADDRESS,
BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
- BUILT_IN_CALLER_RETURN_ADDRESS,
BUILT_IN_APPLY_ARGS,
BUILT_IN_APPLY,
BUILT_IN_RETURN,
@@ -110,16 +109,13 @@ enum built_in_function
BUILT_IN_TRAP,
/* Various hooks for the DWARF 2 __throw routine. */
- BUILT_IN_FP, BUILT_IN_SP,
BUILT_IN_UNWIND_INIT,
+ BUILT_IN_DWARF_CFA,
BUILT_IN_DWARF_FP_REGNUM,
BUILT_IN_DWARF_REG_SIZE,
BUILT_IN_FROB_RETURN_ADDR,
BUILT_IN_EXTRACT_RETURN_ADDR,
- BUILT_IN_SET_RETURN_ADDR_REG,
- BUILT_IN_EH_STUB_OLD,
- BUILT_IN_EH_STUB,
- BUILT_IN_SET_EH_REGS,
+ BUILT_IN_EH_RETURN,
/* C++ extensions */
BUILT_IN_NEW,
@@ -227,6 +223,8 @@ struct tree_common
VAR_DECL or FUNCTION_DECL
TREE_VIA_PUBLIC in
TREE_LIST or TREE_VEC
+ EXPR_WFL_EMIT_LINE_NOTE in
+ EXPR_WITH_FILE_LOCATION
private_flag:
@@ -329,8 +327,8 @@ struct tree_common
#include "tree-check.h"
-#define TYPE_CHECK(t) DO_CHECK (tree_class_check, t, 't')
-#define TYPE_CHECK1(t) DO_CHECK1 (tree_class_check, t, 't')
+#define TYPE_CHECK(tree) DO_CHECK (tree_class_check, tree, 't')
+#define TYPE_CHECK1(tree) DO_CHECK1 (tree_class_check, tree, 't')
#define DECL_CHECK(t) DO_CHECK (tree_class_check, t, 'd')
#define DECL_CHECK1(t) DO_CHECK1 (tree_class_check, t, 'd')
#define CST_CHECK(t) DO_CHECK (tree_class_check, t, 'c')
@@ -686,7 +684,18 @@ struct tree_vec
#define TREE_OPERAND(NODE, I) (EXPR_CHECK (NODE)->exp.operands[I])
#define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity)
-/* In expression with file location information. */
+/* In a LABELED_BLOCK_EXPR node. */
+#define LABELED_BLOCK_LABEL(NODE) TREE_OPERAND (NODE, 0)
+#define LABELED_BLOCK_BODY(NODE) TREE_OPERAND (NODE, 1)
+
+/* In a EXIT_BLOCK_EXPR node. */
+#define EXIT_BLOCK_LABELED_BLOCK(NODE) TREE_OPERAND (NODE, 0)
+#define EXIT_BLOCK_RETURN(NODE) TREE_OPERAND (NODE, 1)
+
+/* In a LOOP_EXPR node. */
+#define LOOP_EXPR_BODY(NODE) TREE_OPERAND (NODE, 0)
+
+/* In a EXPR_WITH_FILE_LOCATION node. */
#define EXPR_WFL_NODE(NODE) TREE_OPERAND((NODE), 0)
#define EXPR_WFL_FILENAME(NODE) (IDENTIFIER_POINTER ((NODE)->common.chain))
#define EXPR_WFL_FILENAME_NODE(NODE) ((NODE)->common.chain)
@@ -695,7 +704,7 @@ struct tree_vec
#define EXPR_WFL_LINECOL(NODE) (EXPR_CHECK (NODE)->exp.complexity)
#define EXPR_WFL_SET_LINECOL(NODE, LINE, COL) \
(EXPR_WFL_LINECOL(NODE) = ((LINE) << 12) | ((COL) & 0xfff))
-#define EXPR_WFL_EMIT_LINE_NOTE(NODE) ((NODE)->common.lang_flag_0)
+#define EXPR_WFL_EMIT_LINE_NOTE(NODE) ((NODE)->common.public_flag)
struct tree_exp
{
@@ -778,12 +787,16 @@ struct tree_block
#define TYPE_NAME(NODE) (TYPE_CHECK (NODE)->type.name)
#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type.next_variant)
#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant)
-#define TYPE_BINFO(NODE) (TYPE_CHECK (NODE)->type.binfo)
#define TYPE_NONCOPIED_PARTS(NODE) (TYPE_CHECK (NODE)->type.noncopied_parts)
#define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type.context)
#define TYPE_OBSTACK(NODE) (TYPE_CHECK (NODE)->type.obstack)
#define TYPE_LANG_SPECIFIC(NODE) (TYPE_CHECK (NODE)->type.lang_specific)
+/* For aggregate types, information about this type, as a base type
+ for itself. Used in a language-dependent way for types that are
+ neither a RECORD_TYPE, QUAL_UNION_TYPE, nor a UNION_TYPE. */
+#define TYPE_BINFO(NODE) (TYPE_CHECK (NODE)->type.binfo)
+
/* The (language-specific) typed-based alias set for this type.
Objects whose TYPE_ALIAS_SETs are different cannot alias each
other. If the TYPE_ALIAS_SET is -1, no alias set has yet been
@@ -817,6 +830,25 @@ struct tree_block
/* Means this type is const-qualified. */
#define TYPE_READONLY(NODE) ((NODE)->common.readonly_flag)
+/* If nonzero, this type is `restrict'-qualified, in the C sense of
+ the term. */
+#define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type.restrict_flag)
+
+/* There is a TYPE_QUAL value for each type qualifier. They can be
+ combined by bitwise-or to form the complete set of qualifiers for a
+ type. */
+
+#define TYPE_UNQUALIFIED 0x0
+#define TYPE_QUAL_CONST 0x1
+#define TYPE_QUAL_VOLATILE 0x2
+#define TYPE_QUAL_RESTRICT 0x4
+
+/* The set of type qualifiers for this type. */
+#define TYPE_QUALS(NODE) \
+ ((TYPE_READONLY(NODE) * TYPE_QUAL_CONST) | \
+ (TYPE_VOLATILE(NODE) * TYPE_QUAL_VOLATILE) | \
+ (TYPE_RESTRICT(NODE) * TYPE_QUAL_RESTRICT))
+
/* These flags are available for each language front end to use internally. */
#define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type.lang_flag_0)
#define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type.lang_flag_1)
@@ -868,6 +900,8 @@ struct tree_type
unsigned needs_constructing_flag : 1;
unsigned transparent_union_flag : 1;
unsigned packed_flag : 1;
+ unsigned restrict_flag : 1;
+
unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1;
unsigned lang_flag_2 : 1;
@@ -875,7 +909,7 @@ struct tree_type
unsigned lang_flag_4 : 1;
unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1;
- /* room for 4 more bits */
+ /* room for 3 more bits */
unsigned int align;
union tree_node *pointer_to;
@@ -978,6 +1012,8 @@ struct tree_type
/* Define fields and accessors for nodes representing declared names. */
+/* Nonzero if DECL represents a decl. */
+#define DECL_P(DECL) (TREE_CODE_CLASS (TREE_CODE (DECL)) == 'd')
/* This is the name of the object as written by the user.
It is an IDENTIFIER_NODE. */
#define DECL_NAME(NODE) (DECL_CHECK (NODE)->decl.name)
@@ -1088,6 +1124,11 @@ struct tree_type
definition. */
#define DECL_ABSTRACT_ORIGIN(NODE) (DECL_CHECK (NODE)->decl.abstract_origin)
+/* Like DECL_ABSTRACT_ORIGIN, but returns NODE if there's no abstract
+ origin. This is useful when setting the DECL_ABSTRACT_ORIGIN. */
+#define DECL_ORIGIN(NODE) \
+ (DECL_ABSTRACT_ORIGIN (NODE) ? DECL_ABSTRACT_ORIGIN (NODE) : NODE)
+
/* Nonzero for any sort of ..._DECL node means this decl node represents
an inline instance of some original (abstract) decl from an inline function;
suppress any warnings about shadowing some other variable. */
@@ -1122,6 +1163,12 @@ struct tree_type
do not allocate storage, and refer to a definition elsewhere. */
#define DECL_EXTERNAL(NODE) (DECL_CHECK (NODE)->decl.external_flag)
+/* In a VAR_DECL for a RECORD_TYPE, sets number for non-init_priority
+ initializatons. */
+#define DEFAULT_INIT_PRIORITY 65535
+#define MAX_INIT_PRIORITY 65535
+#define MAX_RESERVED_INIT_PRIORITY 100
+
/* In a TYPE_DECL
nonzero means the detail info about this type is not dumped into stabs.
Instead it will generate cross reference ('x') of names.
@@ -1199,6 +1246,25 @@ struct tree_type
multiple translation units should be merged. */
#define DECL_ONE_ONLY(NODE) (DECL_CHECK (NODE)->decl.transparent_union)
+/* Used in a DECL to indicate that, even if it TREE_PUBLIC, it need
+ not be put out unless it is needed in this translation unit.
+ Entities like this are shared across translation units (like weak
+ entities), but are guaranteed to be generated by any translation
+ unit that needs them, and therefore need not be put out anywhere
+ where they are not needed. DECL_COMDAT is just a hint to the
+ back-end; it is up to front-ends which set this flag to ensure
+ that there will never be any harm, other than bloat, in putting out
+ something which is DECL_COMDAT. */
+#define DECL_COMDAT(NODE) (DECL_CHECK (NODE)->decl.comdat_flag)
+
+/* Used in FUNCTION_DECLs to indicate that function entry and exit should
+ be instrumented with calls to support routines. */
+#define DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(NODE) ((NODE)->decl.no_instrument_function_entry_exit)
+
+/* Used in FUNCTION_DECLs to indicate that in this function,
+ check-memory-usage should be disabled. */
+#define DECL_NO_CHECK_MEMORY_USAGE(NODE) ((NODE)->decl.no_check_memory_usage)
+
/* Additional flags for language-specific uses. */
#define DECL_LANG_FLAG_0(NODE) (DECL_CHECK (NODE)->decl.lang_flag_0)
#define DECL_LANG_FLAG_1(NODE) (DECL_CHECK (NODE)->decl.lang_flag_1)
@@ -1213,6 +1279,16 @@ struct tree_type
an address constant. */
#define DECL_NON_ADDR_CONST_P(NODE) (DECL_CHECK (NODE)->decl.non_addr_const_p)
+/* Used to indicate an alias set for the memory pointed to by this
+ particular FIELD_DECL, PARM_DECL, or VAR_DECL, which must have
+ pointer (or reference) type. */
+#define DECL_POINTER_ALIAS_SET(NODE) \
+ (DECL_CHECK (NODE)->decl.pointer_alias_set)
+
+/* Nonzero if an alias set has been assigned to this declaration. */
+#define DECL_POINTER_ALIAS_SET_KNOWN_P(NODE) \
+ (DECL_POINTER_ALIAS_SET (NODE) != - 1)
+
struct tree_decl
{
char common[sizeof (struct tree_common)];
@@ -1243,7 +1319,6 @@ struct tree_decl
unsigned static_dtor_flag : 1;
unsigned artificial_flag : 1;
unsigned weak_flag : 1;
- /* room for no more */
unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1;
@@ -1255,6 +1330,9 @@ struct tree_decl
unsigned lang_flag_7 : 1;
unsigned non_addr_const_p : 1;
+ unsigned no_instrument_function_entry_exit : 1;
+ unsigned no_check_memory_usage : 1;
+ unsigned comdat_flag : 1;
/* For a FUNCTION_DECL, if inline, this is the size of frame needed.
If built-in, this is the code for which built-in function.
@@ -1284,6 +1362,7 @@ struct tree_decl
HOST_WIDE_INT i;
} saved_insns;
union tree_node *vindex;
+ int pointer_alias_set;
/* Points to a structure whose details depend on the language in use. */
struct lang_decl *lang_specific;
};
@@ -1308,8 +1387,6 @@ union tree_node
struct tree_block block;
};
-#include "gansidecl.h"
-
#define NULL_TREE (tree) NULL
/* The following functions accept a wide integer argument. Rather than
@@ -1323,21 +1400,6 @@ union tree_node
extern int exact_log2_wide PROTO((unsigned HOST_WIDE_INT));
extern int floor_log2_wide PROTO((unsigned HOST_WIDE_INT));
-#if 0
-/* At present, don't prototype xrealloc, since all of the callers don't
- cast their pointers to char *, and all of the xrealloc's don't use
- void * yet. */
-extern char *xmalloc PROTO((size_t));
-extern char *xcalloc PROTO((size_t, size_t));
-extern char *xrealloc PROTO((void *, size_t));
-#else
-extern char *xmalloc ();
-extern char *xcalloc ();
-extern char *xrealloc ();
-#endif
-
-extern char *xstrdup PROTO((char *));
-
extern char *oballoc PROTO((int));
extern char *permalloc PROTO((int));
extern char *savealloc PROTO((int));
@@ -1366,13 +1428,13 @@ extern tree make_tree_vec PROTO((int));
/* Return the (unique) IDENTIFIER_NODE node for a given name.
The name is supplied as a char *. */
-extern tree get_identifier PROTO((char *));
+extern tree get_identifier PROTO((const char *));
/* If an identifier with the name TEXT (a null-terminated string) has
previously been referred to, return that node; otherwise return
NULL_TREE. */
-extern tree maybe_get_identifier PROTO((char *));
+extern tree maybe_get_identifier PROTO((const char *));
/* Construct various types of nodes. */
@@ -1387,14 +1449,14 @@ extern tree build_int_2_wide PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
extern tree build_real PROTO((tree, REAL_VALUE_TYPE));
extern tree build_real_from_int_cst PROTO((tree, tree));
extern tree build_complex PROTO((tree, tree, tree));
-extern tree build_string PROTO((int, char *));
+extern tree build_string PROTO((int, const char *));
extern tree build1 PROTO((enum tree_code, tree, tree));
extern tree build_tree_list PROTO((tree, tree));
extern tree build_decl_list PROTO((tree, tree));
extern tree build_expr_list PROTO((tree, tree));
extern tree build_decl PROTO((enum tree_code, tree, tree));
extern tree build_block PROTO((tree, tree, tree, tree, tree));
-extern tree build_expr_wfl PROTO((tree, char *, int, int));
+extern tree build_expr_wfl PROTO((tree, const char *, int, int));
/* Construct various nodes representing data types. */
@@ -1459,25 +1521,35 @@ extern int valid_machine_attribute PROTO((tree, tree, tree, tree));
/* Given a tree node and a string, return non-zero if the tree node is
a valid attribute name for the string. */
-extern int is_attribute_p PROTO((char *, tree));
+extern int is_attribute_p PROTO((const char *, tree));
/* Given an attribute name and a list of attributes, return the list element
of the attribute or NULL_TREE if not found. */
-extern tree lookup_attribute PROTO((char *, tree));
+extern tree lookup_attribute PROTO((const char *, tree));
/* Given two attributes lists, return a list of their union. */
extern tree merge_attributes PROTO((tree, tree));
-/* Given a type node TYPE, and CONSTP and VOLATILEP, return a type
- for the same kind of data as TYPE describes.
- Variants point to the "main variant" (which has neither CONST nor VOLATILE)
- via TYPE_MAIN_VARIANT, and it points to a chain of other variants
- so that duplicate variants are never made.
- Only main variants should ever appear as types of expressions. */
+/* Given a type node TYPE and a TYPE_QUALIFIER_SET, return a type for
+ the same kind of data as TYPE describes. Variants point to the
+ "main variant" (which has no qualifiers set) via TYPE_MAIN_VARIANT,
+ and it points to a chain of other variants so that duplicate
+ variants are never made. Only main variants should ever appear as
+ types of expressions. */
-extern tree build_type_variant PROTO((tree, int, int));
+extern tree build_qualified_type PROTO((tree, int));
+
+/* Like build_qualified_type, but only deals with the `const' and
+ `volatile' qualifiers. This interface is retained for backwards
+ compatiblity with the various front-ends; new code should use
+ build_qualified_type instead. */
+
+#define build_type_variant(TYPE, CONST_P, VOLATILE_P) \
+ build_qualified_type (TYPE, \
+ ((CONST_P) ? TYPE_QUAL_CONST : 0) \
+ | ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
/* Make a copy of a type node. */
@@ -1612,7 +1684,7 @@ extern int staticp PROTO((tree));
/* Gets an error if argument X is not an lvalue.
Also returns 1 if X is an lvalue, 0 if not. */
-extern int lvalue_or_else PROTO((tree, char *));
+extern int lvalue_or_else PROTO((tree, const char *));
/* save_expr (EXP) returns an expression equivalent to EXP
but it can be used multiple times within context CTX
@@ -1745,7 +1817,7 @@ extern tree decl_type_context PROTO((tree));
Otherwise return a warning message with a single %s
for the function's name. */
-extern char *function_cannot_inline_p PROTO((tree));
+extern const char *function_cannot_inline_p PROTO((tree));
/* Return 1 if EXPR is the real constant zero. */
extern int real_zerop PROTO((tree));
@@ -1837,10 +1909,12 @@ extern void (*incomplete_decl_finalize_hook) PROTO((tree));
/* In tree.c */
extern char *perm_calloc PROTO((int, long));
extern tree get_file_function_name PROTO((int));
+extern tree get_file_function_name_long PROTO((const char *));
extern tree get_set_constructor_bits PROTO((tree, char *, int));
extern tree get_set_constructor_bytes PROTO((tree,
unsigned char *, int));
extern int get_alias_set PROTO((tree));
+extern int new_alias_set PROTO((void));
extern int (*lang_get_alias_set) PROTO((tree));
/* In stmt.c */
@@ -1871,6 +1945,7 @@ extern int expand_exit_something PROTO((void));
extern void expand_null_return PROTO((void));
extern void expand_return PROTO((tree));
+extern int optimize_tail_recursion PROTO((tree, struct rtx_def *));
extern void expand_start_bindings PROTO((int));
extern void expand_end_bindings PROTO((tree, int, int));
extern void start_cleanup_deferral PROTO((void));
@@ -1883,7 +1958,7 @@ extern tree last_cleanup_this_contour PROTO((void));
extern int expand_dhc_cleanup PROTO((tree));
extern int expand_dcc_cleanup PROTO((tree));
extern void expand_start_case PROTO((int, tree, tree,
- char *));
+ const char *));
extern void expand_end_case PROTO((tree));
extern int pushcase PROTO((tree,
tree (*) (tree, tree),
@@ -1892,6 +1967,7 @@ extern int pushcase_range PROTO((tree, tree,
tree (*) (tree, tree),
tree, tree *));
extern void using_eh_for_cleanups PROTO((void));
+extern int stmt_loop_nest_empty PROTO((void));
/* In fold-const.c */
@@ -2089,9 +2165,10 @@ extern void rtl_in_current_obstack PROTO ((void));
extern void rtl_in_saveable_obstack PROTO ((void));
extern void init_tree_codes PROTO ((void));
extern void dump_tree_statistics PROTO ((void));
-extern void print_obstack_statistics PROTO ((char *, struct obstack *));
+extern void print_obstack_statistics PROTO ((const char *,
+ struct obstack *));
#ifdef BUFSIZ
-extern void print_obstack_name PROTO ((char *, FILE *, char *));
+extern void print_obstack_name PROTO ((char *, FILE *, const char *));
#endif
extern void expand_function_end PROTO ((char *, int, int));
extern void expand_function_start PROTO ((tree, int));
@@ -2101,9 +2178,12 @@ extern void start_identifier_warnings PROTO ((void));
extern void gcc_obstack_init PROTO ((struct obstack *));
extern void init_obstacks PROTO ((void));
extern void obfree PROTO ((char *));
-extern tree tree_check PROTO ((tree, enum tree_code, char*, int, int));
-extern tree tree_class_check PROTO ((tree, char, char*, int, int));
-extern tree expr_check PROTO ((tree, int, char*, int, int));
+extern tree tree_check PROTO ((tree, enum tree_code,
+ const char *, int, int));
+extern tree tree_class_check PROTO ((tree, char, const char *,
+ int, int));
+extern tree expr_check PROTO ((tree, int, const char *,
+ int, int));
/* In function.c */
extern void setjmp_protect_args PROTO ((void));
@@ -2141,8 +2221,8 @@ extern void print_rtl PROTO ((FILE *, struct rtx_def *));
/* In print-tree.c */
extern void debug_tree PROTO ((tree));
#ifdef BUFSIZ
-extern void print_node PROTO ((FILE *, char *, tree, int));
-extern void print_node_brief PROTO ((FILE *, char *, tree, int));
+extern void print_node PROTO ((FILE *, const char *, tree, int));
+extern void print_node_brief PROTO ((FILE *, const char *, tree, int));
extern void indent_to PROTO ((FILE *, int));
#endif
@@ -2198,7 +2278,7 @@ extern void set_yydebug PROTO ((int));
extern void fixup_signed_type PROTO ((tree));
/* varasm.c */
-extern void make_decl_rtl PROTO ((tree, char *, int));
+extern void make_decl_rtl PROTO ((tree, const char *, int));
extern void make_decl_one_only PROTO ((tree));
extern int supports_one_only PROTO ((void));
extern void variable_section PROTO ((tree, int));
diff --git a/contrib/gcc/unroll.c b/contrib/gcc/unroll.c
index cfb51f6..d6dbcf0 100644
--- a/contrib/gcc/unroll.c
+++ b/contrib/gcc/unroll.c
@@ -99,11 +99,11 @@ Boston, MA 02111-1307, USA. */
int iterations = (len + 1) >> 1;
int i;
for (p; p < q; p++, q--;)
- {
- tmp = *q;
- *q = *p;
- *p = tmp;
- }
+ {
+ tmp = *q;
+ *q = *p;
+ *p = tmp;
+ }
}
Note that:
start value = p = &buffer + current_iteration
@@ -141,7 +141,7 @@ Boston, MA 02111-1307, USA. */
struct _factor { int factor, count; } factors[NUM_FACTORS]
= { {2, 0}, {3, 0}, {5, 0}, {7, 0}};
-
+
/* Describes the different types of loop unrolling performed. */
enum unroll_types { UNROLL_COMPLETELY, UNROLL_MODULO, UNROLL_NAIVE };
@@ -180,34 +180,28 @@ static struct induction **addr_combined_regs;
static rtx *splittable_regs;
/* Indexed by register number, if this is a splittable induction variable,
+ this indicates if it was made from a derived giv. */
+static char *derived_regs;
+
+/* Indexed by register number, if this is a splittable induction variable,
then this will hold the number of instructions in the loop that modify
the induction variable. Used to ensure that only the last insn modifying
a split iv will update the original iv of the dest. */
static int *splittable_regs_updates;
-/* Values describing the current loop's iteration variable. These are set up
- by loop_iterations, and used by precondition_loop_p. */
-
-static rtx loop_iteration_var;
-static rtx loop_initial_value;
-static rtx loop_increment;
-static rtx loop_final_value;
-static enum rtx_code loop_comparison_code;
-
/* Forward declarations. */
static void init_reg_map PROTO((struct inline_remap *, int));
-static int precondition_loop_p PROTO((rtx *, rtx *, rtx *, rtx, rtx));
static rtx calculate_giv_inc PROTO((rtx, rtx, int));
static rtx initial_reg_note_copy PROTO((rtx, struct inline_remap *));
static void final_reg_note_copy PROTO((rtx, struct inline_remap *));
static void copy_loop_body PROTO((rtx, rtx, struct inline_remap *, rtx, int,
enum unroll_types, rtx, rtx, rtx, rtx));
-void iteration_info PROTO((rtx, rtx *, rtx *, rtx, rtx));
-static rtx approx_final_value PROTO((enum rtx_code, rtx, int *, int *));
-static int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int));
-static int find_splittable_givs PROTO((struct iv_class *,enum unroll_types,
+static void iteration_info PROTO((rtx, rtx *, rtx *, rtx, rtx));
+static int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int,
+ unsigned HOST_WIDE_INT));
+static int find_splittable_givs PROTO((struct iv_class *, enum unroll_types,
rtx, rtx, rtx, int));
static int reg_dead_after_loop PROTO((rtx, rtx, rtx));
static rtx fold_rtx_mult_add PROTO((rtx, rtx, rtx, enum machine_mode));
@@ -227,11 +221,12 @@ static rtx remap_split_bivs PROTO((rtx));
void
unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
- strength_reduce_p)
+ loop_info, strength_reduce_p)
rtx loop_end;
int insn_count;
rtx loop_start;
rtx end_insert_before;
+ struct loop_info *loop_info;
int strength_reduce_p;
{
int i, j, temp;
@@ -243,8 +238,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
struct inline_remap *map;
char *local_label;
char *local_regno;
+ int max_local_regnum;
int maxregnum;
- int new_maxregnum;
rtx exit_label = 0;
rtx start_label;
struct iv_class *bl;
@@ -304,18 +299,19 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* Determine type of unroll to perform. Depends on the number of iterations
and the size of the loop. */
- /* If there is no strength reduce info, then set loop_n_iterations to zero.
- This can happen if strength_reduce can't find any bivs in the loop.
- A value of zero indicates that the number of iterations could not be
- calculated. */
+ /* If there is no strength reduce info, then set
+ loop_info->n_iterations to zero. This can happen if
+ strength_reduce can't find any bivs in the loop. A value of zero
+ indicates that the number of iterations could not be calculated. */
if (! strength_reduce_p)
- loop_n_iterations = 0;
+ loop_info->n_iterations = 0;
- if (loop_dump_stream && loop_n_iterations > 0)
+ if (loop_dump_stream && loop_info->n_iterations > 0)
{
fputs ("Loop unrolling: ", loop_dump_stream);
- fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, loop_n_iterations);
+ fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
+ loop_info->n_iterations);
fputs (" iterations.\n", loop_dump_stream);
}
@@ -326,7 +322,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* Calculate how many times to unroll the loop. Indicate whether or
not the loop is being completely unrolled. */
- if (loop_n_iterations == 1)
+ if (loop_info->n_iterations == 1)
{
/* If number of iterations is exactly 1, then eliminate the compare and
branch at the end of the loop since they will never be taken.
@@ -355,13 +351,13 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
}
return;
}
- else if (loop_n_iterations > 0
- && loop_n_iterations * insn_count < MAX_UNROLLED_INSNS)
+ else if (loop_info->n_iterations > 0
+ && loop_info->n_iterations * insn_count < MAX_UNROLLED_INSNS)
{
- unroll_number = loop_n_iterations;
+ unroll_number = loop_info->n_iterations;
unroll_type = UNROLL_COMPLETELY;
}
- else if (loop_n_iterations > 0)
+ else if (loop_info->n_iterations > 0)
{
/* Try to factor the number of iterations. Don't bother with the
general case, only using 2, 3, 5, and 7 will get 75% of all
@@ -370,7 +366,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
for (i = 0; i < NUM_FACTORS; i++)
factors[i].count = 0;
- temp = loop_n_iterations;
+ temp = loop_info->n_iterations;
for (i = NUM_FACTORS - 1; i >= 0; i--)
while (temp % factors[i].factor == 0)
{
@@ -688,6 +684,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
map = (struct inline_remap *) alloca (sizeof (struct inline_remap));
map->integrating = 0;
+ map->const_equiv_varray = 0;
/* Allocate the label map. */
@@ -759,6 +756,9 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* The preconditioning code may allocate two new pseudo registers. */
maxregnum = max_reg_num ();
+ /* local_regno is only valid for regnos < max_local_regnum. */
+ max_local_regnum = maxregnum;
+
/* Allocate and zero out the splittable_regs and addr_combined_regs
arrays. These must be zeroed here because they will be used if
loop preconditioning is performed, and must be zero for that case.
@@ -769,16 +769,15 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
splittable_regs = (rtx *) alloca (maxregnum * sizeof (rtx));
bzero ((char *) splittable_regs, maxregnum * sizeof (rtx));
+ derived_regs = alloca (maxregnum);
+ bzero (derived_regs, maxregnum);
splittable_regs_updates = (int *) alloca (maxregnum * sizeof (int));
bzero ((char *) splittable_regs_updates, maxregnum * sizeof (int));
addr_combined_regs
= (struct induction **) alloca (maxregnum * sizeof (struct induction *));
bzero ((char *) addr_combined_regs, maxregnum * sizeof (struct induction *));
- /* We must limit it to max_reg_before_loop, because only these pseudo
- registers have valid regno_first_uid info. Any register created after
- that is unlikely to be local to the loop anyways. */
- local_regno = (char *) alloca (max_reg_before_loop);
- bzero (local_regno, max_reg_before_loop);
+ local_regno = (char *) alloca (maxregnum);
+ bzero (local_regno, maxregnum);
/* Mark all local registers, i.e. the ones which are referenced only
inside the loop. */
@@ -791,6 +790,14 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
since it will also be used outside the loop. */
if (GET_CODE (copy_end) == JUMP_INSN)
copy_end_luid--;
+
+ /* If we have a target that uses cc0, then we also must not duplicate
+ the insn that sets cc0 before the jump insn. */
+#ifdef HAVE_cc0
+ if (GET_CODE (copy_end) == JUMP_INSN)
+ copy_end_luid--;
+#endif
+
/* If copy_start points to the NOTE that starts the loop, then we must
use the next luid, because invariant pseudo-regs moved out of the loop
have their lifetimes modified to start here, but they are not safe
@@ -801,6 +808,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* If a pseudo's lifetime is entirely contained within this loop, then we
can use a different pseudo in each unrolled copy of the loop. This
results in better code. */
+ /* We must limit the generic test to max_reg_before_loop, because only
+ these pseudo registers have valid regno_first_uid info. */
for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; ++j)
if (REGNO_FIRST_UID (j) > 0 && REGNO_FIRST_UID (j) <= max_uid_for_loop
&& uid_luid[REGNO_FIRST_UID (j)] >= copy_start_luid
@@ -829,6 +838,14 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
j);
}
}
+ /* Givs that have been created from multiple biv increments always have
+ local registers. */
+ for (j = first_increment_giv; j <= last_increment_giv; j++)
+ {
+ local_regno[j] = 1;
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream, "Marked reg %d as local\n", j);
+ }
}
/* If this loop requires exit tests when unrolled, check to see if we
@@ -856,23 +873,21 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
if (unroll_type == UNROLL_NAIVE && ! splitting_not_safe && strength_reduce_p)
{
rtx initial_value, final_value, increment;
+ enum machine_mode mode;
- if (precondition_loop_p (&initial_value, &final_value, &increment,
- loop_start, loop_end))
+ if (precondition_loop_p (loop_start, loop_info,
+ &initial_value, &final_value, &increment,
+ &mode))
{
register rtx diff ;
- enum machine_mode mode;
rtx *labels;
int abs_inc, neg_inc;
map->reg_map = (rtx *) alloca (maxregnum * sizeof (rtx));
- map->const_equiv_map = (rtx *) alloca (maxregnum * sizeof (rtx));
- map->const_age_map = (unsigned *) alloca (maxregnum
- * sizeof (unsigned));
- map->const_equiv_map_size = maxregnum;
- global_const_equiv_map = map->const_equiv_map;
- global_const_equiv_map_size = maxregnum;
+ VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray, maxregnum,
+ "unroll_loop");
+ global_const_equiv_varray = map->const_equiv_varray;
init_reg_map (map, maxregnum);
@@ -893,25 +908,10 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
start_sequence ();
- /* Decide what mode to do these calculations in. Choose the larger
- of final_value's mode and initial_value's mode, or a full-word if
- both are constants. */
- mode = GET_MODE (final_value);
- if (mode == VOIDmode)
- {
- mode = GET_MODE (initial_value);
- if (mode == VOIDmode)
- mode = word_mode;
- }
- else if (mode != GET_MODE (initial_value)
- && (GET_MODE_SIZE (mode)
- < GET_MODE_SIZE (GET_MODE (initial_value))))
- mode = GET_MODE (initial_value);
-
/* Calculate the difference between the final and initial values.
Final value may be a (plus (reg x) (const_int 1)) rtx.
Let the following cse pass simplify this if initial value is
- a constant.
+ a constant.
We must copy the final and initial values here to avoid
improperly shared rtl. */
@@ -939,14 +939,11 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
case. This check does not apply if the loop has a NE
comparison at the end. */
- if (loop_comparison_code != NE)
+ if (loop_info->comparison_code != NE)
{
- emit_cmp_insn (initial_value, final_value, neg_inc ? LE : GE,
- NULL_RTX, mode, 0, 0);
- if (neg_inc)
- emit_jump_insn (gen_ble (labels[1]));
- else
- emit_jump_insn (gen_bge (labels[1]));
+ emit_cmp_and_jump_insns (initial_value, final_value,
+ neg_inc ? LE : GE,
+ NULL_RTX, mode, 0, 0, labels[1]);
JUMP_LABEL (get_last_insn ()) = labels[1];
LABEL_NUSES (labels[1])++;
}
@@ -987,15 +984,9 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
cmp_code = LE;
}
- emit_cmp_insn (diff, GEN_INT (abs_inc * cmp_const),
- cmp_code, NULL_RTX, mode, 0, 0);
-
- if (i == 0)
- emit_jump_insn (gen_beq (labels[i]));
- else if (neg_inc)
- emit_jump_insn (gen_bge (labels[i]));
- else
- emit_jump_insn (gen_ble (labels[i]));
+ emit_cmp_and_jump_insns (diff, GEN_INT (abs_inc * cmp_const),
+ cmp_code, NULL_RTX, mode, 0, 0,
+ labels[i]);
JUMP_LABEL (get_last_insn ()) = labels[i];
LABEL_NUSES (labels[i])++;
}
@@ -1008,7 +999,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
For the negative increment case, the branch here could easily
be merged with the `0' case branch above. For the positive
increment case, it is not clear how this can be simplified. */
-
+
if (abs_inc != 1)
{
int cmp_const;
@@ -1025,13 +1016,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
cmp_code = GE;
}
- emit_cmp_insn (diff, GEN_INT (cmp_const), cmp_code, NULL_RTX,
- mode, 0, 0);
-
- if (neg_inc)
- emit_jump_insn (gen_ble (labels[0]));
- else
- emit_jump_insn (gen_bge (labels[0]));
+ emit_cmp_and_jump_insns (diff, GEN_INT (cmp_const), cmp_code,
+ NULL_RTX, mode, 0, 0, labels[0]);
JUMP_LABEL (get_last_insn ()) = labels[0];
LABEL_NUSES (labels[0])++;
}
@@ -1039,7 +1025,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
sequence = gen_sequence ();
end_sequence ();
emit_insn_before (sequence, loop_start);
-
+
/* Only the last copy of the loop body here needs the exit
test, so set copy_end to exclude the compare/branch here,
and then reset it inside the loop when get to the last
@@ -1068,16 +1054,16 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
PREV_INSN (loop_start));
bzero ((char *) map->insn_map, max_insnno * sizeof (rtx));
- bzero ((char *) map->const_equiv_map, maxregnum * sizeof (rtx));
- bzero ((char *) map->const_age_map,
- maxregnum * sizeof (unsigned));
+ bzero ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
+ (VARRAY_SIZE (map->const_equiv_varray)
+ * sizeof (struct const_equiv_data)));
map->const_age = 0;
for (j = 0; j < max_labelno; j++)
if (local_label[j])
set_label_in_map (map, j, gen_label_rtx ());
- for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; j++)
+ for (j = FIRST_PSEUDO_REGISTER; j < max_local_regnum; j++)
if (local_regno[j])
{
map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
@@ -1127,13 +1113,6 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* Set unroll type to MODULO now. */
unroll_type = UNROLL_MODULO;
loop_preconditioned = 1;
-
-#ifdef HAIFA
- /* Fix the initial value for the loop as needed. */
- if (loop_n_iterations <= 0)
- loop_start_value [uid_loop_num [INSN_UID (loop_start)]]
- = initial_value;
-#endif
}
}
@@ -1143,16 +1122,16 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
{
if (loop_dump_stream)
fprintf (loop_dump_stream, "Unrolling failure: Naive unrolling not being done.\n");
- return;
+ goto egress;
}
/* At this point, we are guaranteed to unroll the loop. */
- /* Keep track of the unroll factor for each loop. */
+ /* Keep track of the unroll factor for the loop. */
if (unroll_type == UNROLL_COMPLETELY)
- loop_unroll_factor [uid_loop_num [INSN_UID (loop_start)]] = -1;
+ loop_info->unroll_number = -1;
else
- loop_unroll_factor [uid_loop_num [INSN_UID (loop_start)]] = unroll_number;
+ loop_info->unroll_number = unroll_number;
/* For each biv and giv, determine whether it can be safely split into
@@ -1167,7 +1146,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
temp = 0;
else
temp = find_splittable_regs (unroll_type, loop_start, loop_end,
- end_insert_before, unroll_number);
+ end_insert_before, unroll_number,
+ loop_info->n_iterations);
/* find_splittable_regs may have created some new registers, so must
reallocate the reg_map with the new larger size, and must realloc
@@ -1178,19 +1158,11 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
init_reg_map (map, maxregnum);
- /* Space is needed in some of the map for new registers, so new_maxregnum
- is an (over)estimate of how many registers will exist at the end. */
- new_maxregnum = maxregnum + (temp * unroll_number * 2);
-
- /* Must realloc space for the constant maps, because the number of registers
- may have changed. */
-
- map->const_equiv_map = (rtx *) alloca (new_maxregnum * sizeof (rtx));
- map->const_age_map = (unsigned *) alloca (new_maxregnum * sizeof (unsigned));
-
- map->const_equiv_map_size = new_maxregnum;
- global_const_equiv_map = map->const_equiv_map;
- global_const_equiv_map_size = new_maxregnum;
+ if (map->const_equiv_varray == 0)
+ VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray,
+ maxregnum + temp * unroll_number * 2,
+ "unroll_loop");
+ global_const_equiv_varray = map->const_equiv_varray;
/* Search the list of bivs and givs to find ones which need to be remapped
when split, and set their reg_map entry appropriately. */
@@ -1224,22 +1196,22 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
PATTERN (insn) = remap_split_bivs (PATTERN (insn));
}
- /* For unroll_number - 1 times, make a copy of each instruction
+ /* For unroll_number times, make a copy of each instruction
between copy_start and copy_end, and insert these new instructions
before the end of the loop. */
for (i = 0; i < unroll_number; i++)
{
bzero ((char *) map->insn_map, max_insnno * sizeof (rtx));
- bzero ((char *) map->const_equiv_map, new_maxregnum * sizeof (rtx));
- bzero ((char *) map->const_age_map, new_maxregnum * sizeof (unsigned));
+ bzero ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
+ VARRAY_SIZE (map->const_equiv_varray) * sizeof (struct const_equiv_data));
map->const_age = 0;
for (j = 0; j < max_labelno; j++)
if (local_label[j])
set_label_in_map (map, j, gen_label_rtx ());
- for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; j++)
+ for (j = FIRST_PSEUDO_REGISTER; j < max_local_regnum; j++)
if (local_regno[j])
{
map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
@@ -1253,7 +1225,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
{
insn = PREV_INSN (copy_start);
pattern = PATTERN (insn);
-
+
tem = get_label_from_map (map,
CODE_LABEL_NUMBER
(XEXP (SET_SRC (pattern), 0)));
@@ -1284,13 +1256,24 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
else
safety_label = emit_label_after (gen_label_rtx (), copy_end);
- /* Delete all of the original loop instructions. Don't delete the
+ /* Delete all of the original loop instructions. Don't delete the
LOOP_BEG note, or the first code label in the loop. */
insn = NEXT_INSN (copy_start);
while (insn != safety_label)
{
- if (insn != start_label)
+ /* ??? Don't delete named code labels. They will be deleted when the
+ jump that references them is deleted. Otherwise, we end up deleting
+ them twice, which causes them to completely disappear instead of turn
+ into NOTE_INSN_DELETED_LABEL notes. This in turn causes aborts in
+ dwarfout.c/dwarf2out.c. We could perhaps fix the dwarf*out.c files
+ to handle deleted labels instead. Or perhaps fix DECL_RTL of the
+ associated LABEL_DECL to point to one of the new label instances. */
+ /* ??? Likewise, we can't delete a NOTE_INSN_DELETED_LABEL note. */
+ if (insn != start_label
+ && ! (GET_CODE (insn) == CODE_LABEL && LABEL_NAME (insn))
+ && ! (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
insn = delete_insn (insn);
else
insn = NEXT_INSN (insn);
@@ -1309,6 +1292,10 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
not taken. */
if (exit_label)
emit_label_after (exit_label, loop_end);
+
+ egress:
+ if (map && map->const_equiv_varray)
+ VARRAY_FREE (map->const_equiv_varray);
}
/* Return true if the loop can be safely, and profitably, preconditioned
@@ -1323,55 +1310,61 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* ??? If the loop is known to be executed very many times, or the machine
has a very cheap divide instruction, then preconditioning is a win even
when the increment is not a power of 2. Use RTX_COST to compute
- whether divide is cheap. */
+ whether divide is cheap.
+ ??? A divide by constant doesn't actually need a divide, look at
+ expand_divmod. The reduced cost of this optimized modulo is not
+ reflected in RTX_COST. */
-static int
-precondition_loop_p (initial_value, final_value, increment, loop_start,
- loop_end)
+int
+precondition_loop_p (loop_start, loop_info,
+ initial_value, final_value, increment, mode)
+ rtx loop_start;
+ struct loop_info *loop_info;
rtx *initial_value, *final_value, *increment;
- rtx loop_start, loop_end;
+ enum machine_mode *mode;
{
- if (loop_n_iterations > 0)
+ if (loop_info->n_iterations > 0)
{
*initial_value = const0_rtx;
*increment = const1_rtx;
- *final_value = GEN_INT (loop_n_iterations);
+ *final_value = GEN_INT (loop_info->n_iterations);
+ *mode = word_mode;
if (loop_dump_stream)
{
fputs ("Preconditioning: Success, number of iterations known, ",
loop_dump_stream);
fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
- loop_n_iterations);
+ loop_info->n_iterations);
fputs (".\n", loop_dump_stream);
}
return 1;
}
- if (loop_initial_value == 0)
+ if (loop_info->initial_value == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Preconditioning: Could not find initial value.\n");
return 0;
}
- else if (loop_increment == 0)
+ else if (loop_info->increment == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Preconditioning: Could not find increment value.\n");
return 0;
}
- else if (GET_CODE (loop_increment) != CONST_INT)
+ else if (GET_CODE (loop_info->increment) != CONST_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Preconditioning: Increment not a constant.\n");
return 0;
}
- else if ((exact_log2 (INTVAL (loop_increment)) < 0)
- && (exact_log2 (- INTVAL (loop_increment)) < 0))
+ else if ((exact_log2 (INTVAL (loop_info->increment)) < 0)
+ && (exact_log2 (- INTVAL (loop_info->increment)) < 0))
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@@ -1382,7 +1375,7 @@ precondition_loop_p (initial_value, final_value, increment, loop_start,
/* Unsigned_compare and compare_dir can be ignored here, since they do
not matter for preconditioning. */
- if (loop_final_value == 0)
+ if (loop_info->final_value == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@@ -1395,11 +1388,11 @@ precondition_loop_p (initial_value, final_value, increment, loop_start,
to make sure that the register is in the range covered by invariant_p.
If it isn't, then it is most likely a biv/giv which by definition are
not invariant. */
- if ((GET_CODE (loop_final_value) == REG
- && REGNO (loop_final_value) >= max_reg_before_loop)
- || (GET_CODE (loop_final_value) == PLUS
- && REGNO (XEXP (loop_final_value, 0)) >= max_reg_before_loop)
- || ! invariant_p (loop_final_value))
+ if ((GET_CODE (loop_info->final_value) == REG
+ && REGNO (loop_info->final_value) >= max_reg_before_loop)
+ || (GET_CODE (loop_info->final_value) == PLUS
+ && REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop)
+ || ! invariant_p (loop_info->final_value))
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@@ -1409,8 +1402,8 @@ precondition_loop_p (initial_value, final_value, increment, loop_start,
/* Fail for floating point values, since the caller of this function
does not have code to deal with them. */
- if (GET_MODE_CLASS (GET_MODE (loop_final_value)) == MODE_FLOAT
- || GET_MODE_CLASS (GET_MODE (loop_initial_value)) == MODE_FLOAT)
+ if (GET_MODE_CLASS (GET_MODE (loop_info->final_value)) == MODE_FLOAT
+ || GET_MODE_CLASS (GET_MODE (loop_info->initial_value)) == MODE_FLOAT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@@ -1418,23 +1411,10 @@ precondition_loop_p (initial_value, final_value, increment, loop_start,
return 0;
}
- /* Now set initial_value to be the iteration_var, since that may be a
- simpler expression, and is guaranteed to be correct if all of the
- above tests succeed.
-
- We can not use the initial_value as calculated, because it will be
- one too small for loops of the form "while (i-- > 0)". We can not
- emit code before the loop_skip_over insns to fix this problem as this
- will then give a number one too large for loops of the form
- "while (--i > 0)".
+ /* Fail if loop_info->iteration_var is not live before loop_start,
+ since we need to test its value in the preconditioning code. */
- Note that all loops that reach here are entered at the top, because
- this function is not called if the loop starts with a jump. */
-
- /* Fail if loop_iteration_var is not live before loop_start, since we need
- to test its value in the preconditioning code. */
-
- if (uid_luid[REGNO_FIRST_UID (REGNO (loop_iteration_var))]
+ if (uid_luid[REGNO_FIRST_UID (REGNO (loop_info->iteration_var))]
> INSN_LUID (loop_start))
{
if (loop_dump_stream)
@@ -1443,9 +1423,31 @@ precondition_loop_p (initial_value, final_value, increment, loop_start,
return 0;
}
- *initial_value = loop_iteration_var;
- *increment = loop_increment;
- *final_value = loop_final_value;
+ /* Note that iteration_info biases the initial value for GIV iterators
+ such as "while (i-- > 0)" so that we can calculate the number of
+ iterations just like for BIV iterators.
+
+ Also note that the absolute values of initial_value and
+ final_value are unimportant as only their difference is used for
+ calculating the number of loop iterations. */
+ *initial_value = loop_info->initial_value;
+ *increment = loop_info->increment;
+ *final_value = loop_info->final_value;
+
+ /* Decide what mode to do these calculations in. Choose the larger
+ of final_value's mode and initial_value's mode, or a full-word if
+ both are constants. */
+ *mode = GET_MODE (*final_value);
+ if (*mode == VOIDmode)
+ {
+ *mode = GET_MODE (*initial_value);
+ if (*mode == VOIDmode)
+ *mode = word_mode;
+ }
+ else if (*mode != GET_MODE (*initial_value)
+ && (GET_MODE_SIZE (*mode)
+ < GET_MODE_SIZE (GET_MODE (*initial_value))))
+ *mode = GET_MODE (*initial_value);
/* Success! */
if (loop_dump_stream)
@@ -1508,7 +1510,7 @@ calculate_giv_inc (pattern, src_insn, regno)
pattern = PATTERN (src_insn);
if (GET_CODE (SET_SRC (pattern)) != PLUS)
abort ();
-
+
/* The last insn emitted is not needed, so delete it to avoid confusing
the second cse pass. This insn sets the giv unnecessarily. */
delete_insn (get_last_insn ());
@@ -1532,11 +1534,11 @@ calculate_giv_inc (pattern, src_insn, regno)
/* Some ports store large constants in memory and add a REG_EQUAL
note to the store insn. */
else if (GET_CODE (increment) == MEM)
- {
- rtx note = find_reg_note (src_insn, REG_EQUAL, 0);
- if (note)
- increment = XEXP (note, 0);
- }
+ {
+ rtx note = find_reg_note (src_insn, REG_EQUAL, 0);
+ if (note)
+ increment = XEXP (note, 0);
+ }
else if (GET_CODE (increment) == IOR
|| GET_CODE (increment) == ASHIFT
@@ -1566,7 +1568,7 @@ calculate_giv_inc (pattern, src_insn, regno)
if (GET_CODE (increment) != CONST_INT)
abort ();
-
+
/* The insn loading the constant into a register is no longer needed,
so delete it. */
delete_insn (get_last_insn ());
@@ -1650,7 +1652,7 @@ final_reg_note_copy (notes, map)
/* Copy each instruction in the loop, substituting from map as appropriate.
This is very similar to a loop in expand_inline_function. */
-
+
static void
copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
unroll_type, start_label, loop_end, insert_before,
@@ -1681,35 +1683,41 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
{
final_label = gen_label_rtx ();
set_label_in_map (map, CODE_LABEL_NUMBER (start_label),
- final_label);
+ final_label);
}
else
set_label_in_map (map, CODE_LABEL_NUMBER (start_label), start_label);
start_sequence ();
-
+
+ /* Emit a NOTE_INSN_DELETED to force at least two insns onto the sequence.
+ Else gen_sequence could return a raw pattern for a jump which we pass
+ off to emit_insn_before (instead of emit_jump_insn_before) which causes
+ a variety of losing behaviors later. */
+ emit_note (0, NOTE_INSN_DELETED);
+
insn = copy_start;
do
{
insn = NEXT_INSN (insn);
-
+
map->orig_asm_operands_vector = 0;
-
+
switch (GET_CODE (insn))
{
case INSN:
pattern = PATTERN (insn);
copy = 0;
giv_inc = 0;
-
+
/* Check to see if this is a giv that has been combined with
- some split address givs. (Combined in the sense that
+ some split address givs. (Combined in the sense that
`combine_givs' in loop.c has put two givs in the same register.)
In this case, we must search all givs based on the same biv to
find the address givs. Then split the address givs.
Do this before splitting the giv, since that may map the
SET_DEST to a new register. */
-
+
if ((set = single_set (insn))
&& GET_CODE (SET_DEST (set)) == REG
&& addr_combined_regs[REGNO (SET_DEST (set))])
@@ -1717,17 +1725,18 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
struct iv_class *bl;
struct induction *v, *tv;
int regno = REGNO (SET_DEST (set));
-
+
v = addr_combined_regs[REGNO (SET_DEST (set))];
bl = reg_biv_class[REGNO (v->src_reg)];
-
+
/* Although the giv_inc amount is not needed here, we must call
calculate_giv_inc here since it might try to delete the
last insn emitted. If we wait until later to call it,
we might accidentally delete insns generated immediately
below by emit_unrolled_add. */
- giv_inc = calculate_giv_inc (set, insn, regno);
+ if (! derived_regs[regno])
+ giv_inc = calculate_giv_inc (set, insn, regno);
/* Now find all address giv's that were combined with this
giv 'v'. */
@@ -1746,24 +1755,24 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
if (tv->mult_val != v->mult_val)
this_giv_inc = (this_giv_inc / INTVAL (v->mult_val)
* INTVAL (tv->mult_val));
-
+
tv->dest_reg = plus_constant (tv->dest_reg, this_giv_inc);
*tv->location = tv->dest_reg;
-
+
if (last_iteration && unroll_type != UNROLL_COMPLETELY)
{
/* Must emit an insn to increment the split address
giv. Add in the const_adjust field in case there
was a constant eliminated from the address. */
rtx value, dest_reg;
-
+
/* tv->dest_reg will be either a bare register,
or else a register plus a constant. */
if (GET_CODE (tv->dest_reg) == REG)
dest_reg = tv->dest_reg;
else
dest_reg = XEXP (tv->dest_reg, 0);
-
+
/* Check for shared address givs, and avoid
incrementing the shared pseudo reg more than
once. */
@@ -1782,7 +1791,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
emit_unrolled_add (dest_reg, XEXP (value, 0),
XEXP (value, 1));
}
-
+
/* Reset the giv to be just the register again, in case
it is used after the set we have just emitted.
We must subtract the const_adjust factor added in
@@ -1793,39 +1802,53 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
}
}
}
-
+
/* If this is a setting of a splittable variable, then determine
how to split the variable, create a new set based on this split,
and set up the reg_map so that later uses of the variable will
use the new split variable. */
-
+
dest_reg_was_split = 0;
-
+
if ((set = single_set (insn))
&& GET_CODE (SET_DEST (set)) == REG
&& splittable_regs[REGNO (SET_DEST (set))])
{
int regno = REGNO (SET_DEST (set));
-
+ int src_regno;
+
dest_reg_was_split = 1;
-
- /* Compute the increment value for the giv, if it wasn't
- already computed above. */
- if (giv_inc == 0)
- giv_inc = calculate_giv_inc (set, insn, regno);
giv_dest_reg = SET_DEST (set);
- giv_src_reg = SET_DEST (set);
+ if (derived_regs[regno])
+ {
+ /* ??? This relies on SET_SRC (SET) to be of
+ the form (plus (reg) (const_int)), and thus
+ forces recombine_givs to restrict the kind
+ of giv derivations it does before unrolling. */
+ giv_src_reg = XEXP (SET_SRC (set), 0);
+ giv_inc = XEXP (SET_SRC (set), 1);
+ }
+ else
+ {
+ giv_src_reg = giv_dest_reg;
+ /* Compute the increment value for the giv, if it wasn't
+ already computed above. */
+ if (giv_inc == 0)
+ giv_inc = calculate_giv_inc (set, insn, regno);
+ }
+ src_regno = REGNO (giv_src_reg);
if (unroll_type == UNROLL_COMPLETELY)
{
/* Completely unrolling the loop. Set the induction
variable to a known constant value. */
-
+
/* The value in splittable_regs may be an invariant
value, so we must use plus_constant here. */
splittable_regs[regno]
- = plus_constant (splittable_regs[regno], INTVAL (giv_inc));
+ = plus_constant (splittable_regs[src_regno],
+ INTVAL (giv_inc));
if (GET_CODE (splittable_regs[regno]) == PLUS)
{
@@ -1848,7 +1871,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
be a constant plus the original register. Except
on the last iteration, when the result has to
go back into the original iteration var register. */
-
+
/* Handle bivs which must be mapped to a new register
when split. This happens for bivs which need their
final value set before loop entry. The new register
@@ -1856,23 +1879,23 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
induction entry by find_splittable_regs. */
if (regno < max_reg_before_loop
- && reg_iv_type[regno] == BASIC_INDUCT)
+ && REG_IV_TYPE (regno) == BASIC_INDUCT)
{
giv_src_reg = reg_biv_class[regno]->biv->src_reg;
giv_dest_reg = giv_src_reg;
}
-
+
#if 0
/* If non-reduced/final-value givs were split, then
this would have to remap those givs also. See
find_splittable_regs. */
#endif
-
+
splittable_regs[regno]
= GEN_INT (INTVAL (giv_inc)
- + INTVAL (splittable_regs[regno]));
+ + INTVAL (splittable_regs[src_regno]));
giv_inc = splittable_regs[regno];
-
+
/* Now split the induction variable by changing the dest
of this insn to a new register, and setting its
reg_map entry to point to this new register.
@@ -1916,7 +1939,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
copy = emit_insn (pattern);
}
REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
-
+
#ifdef HAVE_cc0
/* If this insn is setting CC0, it may need to look at
the insn that uses CC0 to see what type of insn it is.
@@ -1951,12 +1974,13 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
{
int regno = REGNO (SET_DEST (pattern));
- if (regno < map->const_equiv_map_size
- && map->const_age_map[regno] == map->const_age)
- map->const_age_map[regno] = -1;
+ if (regno < VARRAY_SIZE (map->const_equiv_varray)
+ && (VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).age
+ == map->const_age))
+ VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).age = -1;
}
break;
-
+
case JUMP_INSN:
pattern = copy_rtx_and_substitute (PATTERN (insn), map);
copy = emit_jump_insn (pattern);
@@ -2000,7 +2024,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
abort ();
}
}
-
+
#ifdef HAVE_cc0
if (cc0_insn)
try_constants (cc0_insn, map);
@@ -2038,10 +2062,10 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
for a switch statement. This label must have been mapped,
so just use the label_map to get the new jump label. */
JUMP_LABEL (copy)
- = get_label_from_map (map,
- CODE_LABEL_NUMBER (JUMP_LABEL (insn)));
+ = get_label_from_map (map,
+ CODE_LABEL_NUMBER (JUMP_LABEL (insn)));
}
-
+
/* If this is a non-local jump, then must increase the label
use count so that the label will not be deleted when the
original jump is deleted. */
@@ -2088,7 +2112,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
emit_barrier ();
}
break;
-
+
case CALL_INSN:
pattern = copy_rtx_and_substitute (PATTERN (insn), map);
copy = emit_call_insn (pattern);
@@ -2108,9 +2132,9 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
/* Be lazy and assume CALL_INSNs clobber all hard registers. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- map->const_equiv_map[i] = 0;
+ VARRAY_CONST_EQUIV (map->const_equiv_varray, i).rtx = 0;
break;
-
+
case CODE_LABEL:
/* If this is the loop start label, then we don't need to emit a
copy of this label since no one will use it. */
@@ -2122,33 +2146,38 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
map->const_age++;
}
break;
-
+
case BARRIER:
copy = emit_barrier ();
break;
-
+
case NOTE:
- /* VTOP notes are valid only before the loop exit test. If placed
- anywhere else, loop may generate bad code. */
-
+ /* VTOP and CONT notes are valid only before the loop exit test.
+ If placed anywhere else, loop may generate bad code. */
+ /* BASIC_BLOCK notes exist to stabilize basic block structures with
+ the associated rtl. We do not want to share the structure in
+ this new block. */
+
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
- && (NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
+ && ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
|| (last_iteration && unroll_type != UNROLL_COMPLETELY)))
copy = emit_note (NOTE_SOURCE_FILE (insn),
NOTE_LINE_NUMBER (insn));
else
copy = 0;
break;
-
+
default:
abort ();
break;
}
-
+
map->insn_map[INSN_UID (insn)] = copy;
}
while (insn != copy_end);
-
+
/* Now finish coping the REG_NOTES. */
insn = copy_start;
do
@@ -2175,8 +2204,17 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
{
for (insn = copy_notes_from; insn != loop_end; insn = NEXT_INSN (insn))
{
+ /* VTOP notes are valid only before the loop exit test.
+ If placed anywhere else, loop may generate bad code.
+ There is no need to test for NOTE_INSN_LOOP_CONT notes
+ here, since COPY_NOTES_FROM will be at most one or two (for cc0)
+ instructions before the last insn in the loop, and if the
+ end test is that short, there will be a VTOP note between
+ the CONT note and the test. */
if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP)
emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
}
}
@@ -2243,7 +2281,7 @@ back_branch_in_range_p (insn, loop_start, loop_end)
if (GET_CODE (p) == JUMP_INSN)
{
target_insn = JUMP_LABEL (p);
-
+
/* Search from loop_start to insn, to see if one of them is
the target_insn. We can't use INSN_LUID comparisons here,
since insn may not have an LUID entry. */
@@ -2309,7 +2347,7 @@ fold_rtx_mult_add (mult1, mult2, add1, mode)
Returns the increment value as an rtx, simplified as much as possible,
if it can be calculated. Otherwise, returns 0. */
-rtx
+rtx
biv_total_increment (bl, loop_start, loop_end)
struct iv_class *bl;
rtx loop_start, loop_end;
@@ -2328,7 +2366,7 @@ biv_total_increment (bl, loop_start, loop_end)
for (v = bl->biv; v; v = v->next_iv)
{
if (v->always_computable && v->mult_val == const1_rtx
- && ! back_branch_in_range_p (v->insn, loop_start, loop_end))
+ && ! v->maybe_multiple)
result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
else
return 0;
@@ -2344,7 +2382,7 @@ biv_total_increment (bl, loop_start, loop_end)
Initial_value and/or increment are set to zero if their values could not
be calculated. */
-void
+static void
iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
rtx iteration_var, *initial_value, *increment;
rtx loop_start, loop_end;
@@ -2364,7 +2402,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
/* If this is a new register, can't handle it since we don't have any
reg_iv_type entry for it. */
- if (REGNO (iteration_var) >= max_reg_before_loop)
+ if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@@ -2374,7 +2412,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
/* Reject iteration variables larger than the host wide int size, since they
could result in a number of iterations greater than the range of our
- `unsigned HOST_WIDE_INT' variable loop_n_iterations. */
+ `unsigned HOST_WIDE_INT' variable loop_info->n_iterations. */
else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
> HOST_BITS_PER_WIDE_INT))
{
@@ -2390,44 +2428,62 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
"Loop unrolling: Iteration var not an integer.\n");
return;
}
- else if (reg_iv_type[REGNO (iteration_var)] == BASIC_INDUCT)
+ else if (REG_IV_TYPE (REGNO (iteration_var)) == BASIC_INDUCT)
{
+ /* When reg_iv_type / reg_iv_info is resized for biv increments
+ that are turned into givs, reg_biv_class is not resized.
+ So check here that we don't make an out-of-bounds access. */
+ if (REGNO (iteration_var) >= max_reg_before_loop)
+ abort ();
+
/* Grab initial value, only useful if it is a constant. */
bl = reg_biv_class[REGNO (iteration_var)];
*initial_value = bl->initial_value;
*increment = biv_total_increment (bl, loop_start, loop_end);
}
- else if (reg_iv_type[REGNO (iteration_var)] == GENERAL_INDUCT)
- {
-#if 1
- /* ??? The code below does not work because the incorrect number of
- iterations is calculated when the biv is incremented after the giv
- is set (which is the usual case). This can probably be accounted
- for by biasing the initial_value by subtracting the amount of the
- increment that occurs between the giv set and the giv test. However,
- a giv as an iterator is very rare, so it does not seem worthwhile
- to handle this. */
- /* ??? An example failure is: i = 6; do {;} while (i++ < 9). */
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Loop unrolling: Giv iterators are not handled.\n");
- return;
-#else
- /* Initial value is mult_val times the biv's initial value plus
- add_val. Only useful if it is a constant. */
- v = reg_iv_info[REGNO (iteration_var)];
+ else if (REG_IV_TYPE (REGNO (iteration_var)) == GENERAL_INDUCT)
+ {
+ HOST_WIDE_INT offset = 0;
+ struct induction *v = REG_IV_INFO (REGNO (iteration_var));
+
+ if (REGNO (v->src_reg) >= max_reg_before_loop)
+ abort ();
+
bl = reg_biv_class[REGNO (v->src_reg)];
- *initial_value = fold_rtx_mult_add (v->mult_val, bl->initial_value,
- v->add_val, v->mode);
-
+
/* Increment value is mult_val times the increment value of the biv. */
*increment = biv_total_increment (bl, loop_start, loop_end);
if (*increment)
- *increment = fold_rtx_mult_add (v->mult_val, *increment, const0_rtx,
- v->mode);
-#endif
+ {
+ struct induction *biv_inc;
+
+ *increment
+ = fold_rtx_mult_add (v->mult_val, *increment, const0_rtx, v->mode);
+ /* The caller assumes that one full increment has occured at the
+ first loop test. But that's not true when the biv is incremented
+ after the giv is set (which is the usual case), e.g.:
+ i = 6; do {;} while (i++ < 9) .
+ Therefore, we bias the initial value by subtracting the amount of
+ the increment that occurs between the giv set and the giv test. */
+ for (biv_inc = bl->biv; biv_inc; biv_inc = biv_inc->next_iv)
+ {
+ if (loop_insn_first_p (v->insn, biv_inc->insn))
+ offset -= INTVAL (biv_inc->add_val);
+ }
+ offset *= INTVAL (v->mult_val);
+ }
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Loop unrolling: Giv iterator, initial value bias %ld.\n",
+ (long) offset);
+ /* Initial value is mult_val times the biv's initial value plus
+ add_val. Only useful if it is a constant. */
+ *initial_value
+ = fold_rtx_mult_add (v->mult_val,
+ plus_constant (bl->initial_value, offset),
+ v->add_val, v->mode);
}
else
{
@@ -2438,60 +2494,6 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
}
}
-/* Calculate the approximate final value of the iteration variable
- which has an loop exit test with code COMPARISON_CODE and comparison value
- of COMPARISON_VALUE. Also returns an indication of whether the comparison
- was signed or unsigned, and the direction of the comparison. This info is
- needed to calculate the number of loop iterations. */
-
-static rtx
-approx_final_value (comparison_code, comparison_value, unsigned_p, compare_dir)
- enum rtx_code comparison_code;
- rtx comparison_value;
- int *unsigned_p;
- int *compare_dir;
-{
- /* Calculate the final value of the induction variable.
- The exact final value depends on the branch operator, and increment sign.
- This is only an approximate value. It will be wrong if the iteration
- variable is not incremented by one each time through the loop, and
- approx final value - start value % increment != 0. */
-
- *unsigned_p = 0;
- switch (comparison_code)
- {
- case LEU:
- *unsigned_p = 1;
- case LE:
- *compare_dir = 1;
- return plus_constant (comparison_value, 1);
- case GEU:
- *unsigned_p = 1;
- case GE:
- *compare_dir = -1;
- return plus_constant (comparison_value, -1);
- case EQ:
- /* Can not calculate a final value for this case. */
- *compare_dir = 0;
- return 0;
- case LTU:
- *unsigned_p = 1;
- case LT:
- *compare_dir = 1;
- return comparison_value;
- break;
- case GTU:
- *unsigned_p = 1;
- case GT:
- *compare_dir = -1;
- return comparison_value;
- case NE:
- *compare_dir = 0;
- return comparison_value;
- default:
- abort ();
- }
-}
/* For each biv and giv, determine whether it can be safely split into
a different variable for each unrolled copy of the loop body. If it
@@ -2519,11 +2521,12 @@ approx_final_value (comparison_code, comparison_value, unsigned_p, compare_dir)
static int
find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
- unroll_number)
+ unroll_number, n_iterations)
enum unroll_types unroll_type;
rtx loop_start, loop_end;
rtx end_insert_before;
int unroll_number;
+ unsigned HOST_WIDE_INT n_iterations;
{
struct iv_class *bl;
struct induction *v;
@@ -2561,7 +2564,8 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
|| (uid_luid[REGNO_FIRST_UID (bl->regno)]
< INSN_LUID (bl->init_insn))
|| reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
- && ! (biv_final_value = final_biv_value (bl, loop_start, loop_end)))
+ && ! (biv_final_value = final_biv_value (bl, loop_start, loop_end,
+ n_iterations)))
biv_splittable = 0;
/* If any of the insns setting the BIV don't do so with a simple
@@ -2750,7 +2754,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
&& (! v->always_computable
|| back_branch_in_range_p (v->insn, loop_start, loop_end)))
continue;
-
+
/* The giv increment value must be a constant. */
giv_inc = fold_rtx_mult_add (v->mult_val, increment, const0_rtx,
v->mode);
@@ -2762,7 +2766,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
the loop, or else the final value of the giv must be known.
Otherwise, it is not safe to split the giv since it may not have the
proper value on loop exit. */
-
+
/* The used outside loop test will fail for DEST_ADDR givs. They are
never used outside the loop anyways, so it is always safe to split a
DEST_ADDR giv. */
@@ -2786,6 +2790,10 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
/* Line above always fails if INSN was moved by loop opt. */
|| (uid_luid[REGNO_LAST_UID (REGNO (v->dest_reg))]
>= INSN_LUID (loop_end)))
+ /* Givs made from biv increments are missed by the above test, so
+ test explicitly for them. */
+ && (REGNO (v->dest_reg) < first_increment_giv
+ || REGNO (v->dest_reg) > last_increment_giv)
&& ! (final_value = v->final_value))
continue;
@@ -2806,11 +2814,11 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
emit_insn_before (gen_move_insn (tem, v->dest_reg), loop_start);
emit_insn_before (gen_move_insn (v->dest_reg, final_value),
loop_start);
-
+
if (loop_dump_stream)
fprintf (loop_dump_stream, "Giv %d mapped to %d for split.\n",
REGNO (v->dest_reg), REGNO (tem));
-
+
v->src_reg = tem;
}
#endif
@@ -2884,8 +2892,9 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
v->add_val, tem, loop_start);
value = tem;
}
-
+
splittable_regs[REGNO (v->new_reg)] = value;
+ derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
}
else
{
@@ -2941,17 +2950,38 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
Emit insn to initialize its value before loop start. */
rtx tem = gen_reg_rtx (v->mode);
+ struct induction *same = v->same;
+ rtx new_reg = v->new_reg;
record_base_value (REGNO (tem), v->add_val, 0);
+ if (same && same->derived_from)
+ {
+ /* calculate_giv_inc doesn't work for derived givs.
+ copy_loop_body works around the problem for the
+ DEST_REG givs themselves, but it can't handle
+ DEST_ADDR givs that have been combined with
+ a derived DEST_REG giv.
+ So Handle V as if the giv from which V->SAME has
+ been derived has been combined with V.
+ recombine_givs only derives givs from givs that
+ are reduced the ordinary, so we need not worry
+ about same->derived_from being in turn derived. */
+
+ same = same->derived_from;
+ new_reg = express_from (same, v);
+ new_reg = replace_rtx (new_reg, same->dest_reg,
+ same->new_reg);
+ }
+
/* If the address giv has a constant in its new_reg value,
then this constant can be pulled out and put in value,
instead of being part of the initialization code. */
-
- if (GET_CODE (v->new_reg) == PLUS
- && GET_CODE (XEXP (v->new_reg, 1)) == CONST_INT)
+
+ if (GET_CODE (new_reg) == PLUS
+ && GET_CODE (XEXP (new_reg, 1)) == CONST_INT)
{
v->dest_reg
- = plus_constant (tem, INTVAL (XEXP (v->new_reg,1)));
+ = plus_constant (tem, INTVAL (XEXP (new_reg, 1)));
/* Only succeed if this will give valid addresses.
Try to validate both the first and the last
@@ -2962,9 +2992,9 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
/* Save the negative of the eliminated const, so
that we can calculate the dest_reg's increment
value later. */
- v->const_adjust = - INTVAL (XEXP (v->new_reg, 1));
+ v->const_adjust = - INTVAL (XEXP (new_reg, 1));
- v->new_reg = XEXP (v->new_reg, 0);
+ new_reg = XEXP (new_reg, 0);
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Eliminating constant from giv %d\n",
@@ -2975,7 +3005,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
}
else
v->dest_reg = tem;
-
+
/* If the address hasn't been checked for validity yet, do so
now, and fail completely if either the first or the last
unrolled copy of the address is not a valid address
@@ -2993,7 +3023,10 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
INSN_UID (v->insn));
continue;
}
-
+
+ v->new_reg = new_reg;
+ v->same = same;
+
/* We set this after the address check, to guarantee that
the register will be initialized. */
v->unrolled = 1;
@@ -3032,7 +3065,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
else
{
v->dest_reg = value;
-
+
/* Check the resulting address for validity, and fail
if the resulting address would be invalid. */
if (! verify_addresses (v, giv_inc, unroll_number))
@@ -3047,29 +3080,41 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
INSN_UID (v->insn));
continue;
}
+ if (v->same && v->same->derived_from)
+ {
+ /* Handle V as if the giv from which V->SAME has
+ been derived has been combined with V. */
+
+ v->same = v->same->derived_from;
+ v->new_reg = express_from (v->same, v);
+ v->new_reg = replace_rtx (v->new_reg, v->same->dest_reg,
+ v->same->new_reg);
+ }
+
}
-
+
/* Store the value of dest_reg into the insn. This sharing
will not be a problem as this insn will always be copied
later. */
-
+
*v->location = v->dest_reg;
-
+
/* If this address giv is combined with a dest reg giv, then
save the base giv's induction pointer so that we will be
able to handle this address giv properly. The base giv
itself does not have to be splittable. */
-
+
if (v->same && v->same->giv_type == DEST_REG)
addr_combined_regs[REGNO (v->same->new_reg)] = v->same;
-
+
if (GET_CODE (v->new_reg) == REG)
{
/* This giv maybe hasn't been combined with any others.
Make sure that it's giv is marked as splittable here. */
-
+
splittable_regs[REGNO (v->new_reg)] = value;
-
+ derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
+
/* Make it appear to depend upon itself, so that the
giv will be properly split in the main loop above. */
if (! v->same)
@@ -3092,7 +3137,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
it makes sense to reduce&split givs when possible, as this will
result in simpler instructions, and will not require that a reg
be live across loop iterations. */
-
+
splittable_regs[REGNO (v->dest_reg)] = value;
fprintf (stderr, "Giv %d at insn %d not reduced\n",
REGNO (v->dest_reg), INSN_UID (v->insn));
@@ -3100,7 +3145,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
continue;
#endif
}
-
+
/* Unreduced givs are only updated once by definition. Reduced givs
are updated as many times as their biv is. Mark it so if this is
a splittable register. Don't need to do anything for address givs
@@ -3112,15 +3157,20 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
if (! v->ignore)
count = reg_biv_class[REGNO (v->src_reg)]->biv_count;
+ if (count > 1 && v->derived_from)
+ /* In this case, there is one set where the giv insn was and one
+ set each after each biv increment. (Most are likely dead.) */
+ count++;
+
splittable_regs_updates[REGNO (v->new_reg)] = count;
}
result++;
-
+
if (loop_dump_stream)
{
int regnum;
-
+
if (GET_CODE (v->dest_reg) == CONST_INT)
regnum = -1;
else if (GET_CODE (v->dest_reg) != REG)
@@ -3157,7 +3207,7 @@ reg_dead_after_loop (reg, loop_start, loop_end)
all exits of inner nested loops that would exit this loop. We don't
have any way to identify those, so we just give up if there are any
such inner loop exits. */
-
+
for (label = loop_number_exit_labels[this_loop_num]; label;
label = LABEL_NEXTREF (label))
label_count++;
@@ -3215,11 +3265,12 @@ reg_dead_after_loop (reg, loop_start, loop_end)
/* Try to calculate the final value of the biv, the value it will have at
the end of the loop. If we can do it, return that value. */
-
+
rtx
-final_biv_value (bl, loop_start, loop_end)
+final_biv_value (bl, loop_start, loop_end, n_iterations)
struct iv_class *bl;
rtx loop_start, loop_end;
+ unsigned HOST_WIDE_INT n_iterations;
{
rtx increment, tem;
@@ -3237,7 +3288,7 @@ final_biv_value (bl, loop_start, loop_end)
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Final biv value for %d, reversed biv.\n", bl->regno);
-
+
return const0_rtx;
}
@@ -3247,12 +3298,12 @@ final_biv_value (bl, loop_start, loop_end)
it may not have its final value when the loop exits), and the initial
value of the biv must be invariant. */
- if (loop_n_iterations != 0
+ if (n_iterations != 0
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]
&& invariant_p (bl->initial_value))
{
increment = biv_total_increment (bl, loop_start, loop_end);
-
+
if (increment && invariant_p (increment))
{
/* Can calculate the loop exit value, emit insns after loop
@@ -3264,13 +3315,13 @@ final_biv_value (bl, loop_start, loop_end)
/* Make sure loop_end is not the last insn. */
if (NEXT_INSN (loop_end) == 0)
emit_note_after (NOTE_INSN_DELETED, loop_end);
- emit_iv_add_mult (increment, GEN_INT (loop_n_iterations),
+ emit_iv_add_mult (increment, GEN_INT (n_iterations),
bl->initial_value, tem, NEXT_INSN (loop_end));
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Final biv value for %d, calculated.\n", bl->regno);
-
+
return tem;
}
}
@@ -3293,9 +3344,10 @@ final_biv_value (bl, loop_start, loop_end)
the end of the loop. If we can do it, return that value. */
rtx
-final_giv_value (v, loop_start, loop_end)
+final_giv_value (v, loop_start, loop_end, n_iterations)
struct induction *v;
rtx loop_start, loop_end;
+ unsigned HOST_WIDE_INT n_iterations;
{
struct iv_class *bl;
rtx insn;
@@ -3320,13 +3372,13 @@ final_giv_value (v, loop_start, loop_end)
/* Try to calculate the final value as a function of the biv it depends
upon. The only exit from the loop must be the fall through at the bottom
(otherwise it may not have its final value when the loop exits). */
-
+
/* ??? Can calculate the final giv value by subtracting off the
extra biv increments times the giv's mult_val. The loop must have
only one exit for this to work, but the loop iterations does not need
to be known. */
- if (loop_n_iterations != 0
+ if (n_iterations != 0
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
{
/* ?? It is tempting to use the biv's value here since these insns will
@@ -3346,8 +3398,8 @@ final_giv_value (v, loop_start, loop_end)
&& invariant_p (bl->initial_value))
{
/* Can calculate the loop exit value of its biv as
- (loop_n_iterations * increment) + initial_value */
-
+ (n_iterations * increment) + initial_value */
+
/* The loop exit value of the giv is then
(final_biv_value - extra increments) * mult_val + add_val.
The extra increments are any increments to the biv which
@@ -3360,7 +3412,7 @@ final_giv_value (v, loop_start, loop_end)
/* Put the final biv value in tem. */
tem = gen_reg_rtx (bl->biv->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0);
- emit_iv_add_mult (increment, GEN_INT (loop_n_iterations),
+ emit_iv_add_mult (increment, GEN_INT (n_iterations),
bl->initial_value, tem, insert_before);
/* Subtract off extra increments as we find them. */
@@ -3381,11 +3433,11 @@ final_giv_value (v, loop_start, loop_end)
emit_insn_before (seq, insert_before);
}
}
-
+
/* Now calculate the giv's final value. */
emit_iv_add_mult (tem, v->mult_val, v->add_val, tem,
insert_before);
-
+
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Final giv value for %d, calc from biv's value.\n",
@@ -3414,43 +3466,185 @@ final_giv_value (v, loop_start, loop_end)
}
+/* Look back before LOOP_START for then insn that sets REG and return
+ the equivalent constant if there is a REG_EQUAL note otherwise just
+ the SET_SRC of REG. */
+
+static rtx
+loop_find_equiv_value (loop_start, reg)
+ rtx loop_start;
+ rtx reg;
+{
+ rtx insn, set;
+ rtx ret;
+
+ ret = reg;
+ for (insn = PREV_INSN (loop_start); insn ; insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) == CODE_LABEL)
+ break;
+
+ else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+ && reg_set_p (reg, insn))
+ {
+ /* We found the last insn before the loop that sets the register.
+ If it sets the entire register, and has a REG_EQUAL note,
+ then use the value of the REG_EQUAL note. */
+ if ((set = single_set (insn))
+ && (SET_DEST (set) == reg))
+ {
+ rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+
+ /* Only use the REG_EQUAL note if it is a constant.
+ Other things, divide in particular, will cause
+ problems later if we use them. */
+ if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST
+ && CONSTANT_P (XEXP (note, 0)))
+ ret = XEXP (note, 0);
+ else
+ ret = SET_SRC (set);
+ }
+ break;
+ }
+ }
+ return ret;
+}
+
+
+/* Return a simplified rtx for the expression OP - REG.
+
+ REG must appear in OP, and OP must be a register or the sum of a register
+ and a second term.
+
+ Thus, the return value must be const0_rtx or the second term.
+
+ The caller is responsible for verifying that REG appears in OP and OP has
+ the proper form. */
+
+static rtx
+subtract_reg_term (op, reg)
+ rtx op, reg;
+{
+ if (op == reg)
+ return const0_rtx;
+ if (GET_CODE (op) == PLUS)
+ {
+ if (XEXP (op, 0) == reg)
+ return XEXP (op, 1);
+ else if (XEXP (op, 1) == reg)
+ return XEXP (op, 0);
+ }
+ /* OP does not contain REG as a term. */
+ abort ();
+}
+
+
+/* Find and return register term common to both expressions OP0 and
+ OP1 or NULL_RTX if no such term exists. Each expression must be a
+ REG or a PLUS of a REG. */
+
+static rtx
+find_common_reg_term (op0, op1)
+ rtx op0, op1;
+{
+ if ((GET_CODE (op0) == REG || GET_CODE (op0) == PLUS)
+ && (GET_CODE (op1) == REG || GET_CODE (op1) == PLUS))
+ {
+ rtx op00;
+ rtx op01;
+ rtx op10;
+ rtx op11;
+
+ if (GET_CODE (op0) == PLUS)
+ op01 = XEXP (op0, 1), op00 = XEXP (op0, 0);
+ else
+ op01 = const0_rtx, op00 = op0;
+
+ if (GET_CODE (op1) == PLUS)
+ op11 = XEXP (op1, 1), op10 = XEXP (op1, 0);
+ else
+ op11 = const0_rtx, op10 = op1;
+
+ /* Find and return common register term if present. */
+ if (REG_P (op00) && (op00 == op10 || op00 == op11))
+ return op00;
+ else if (REG_P (op01) && (op01 == op10 || op01 == op11))
+ return op01;
+ }
+
+ /* No common register term found. */
+ return NULL_RTX;
+}
+
+
/* Calculate the number of loop iterations. Returns the exact number of loop
iterations if it can be calculated, otherwise returns zero. */
unsigned HOST_WIDE_INT
-loop_iterations (loop_start, loop_end)
+loop_iterations (loop_start, loop_end, loop_info)
rtx loop_start, loop_end;
+ struct loop_info *loop_info;
{
rtx comparison, comparison_value;
rtx iteration_var, initial_value, increment, final_value;
enum rtx_code comparison_code;
- HOST_WIDE_INT i;
+ HOST_WIDE_INT abs_inc;
+ unsigned HOST_WIDE_INT abs_diff;
+ int off_by_one;
int increment_dir;
- int unsigned_compare, compare_dir, final_larger;
- unsigned long tempu;
+ int unsigned_p, compare_dir, final_larger;
rtx last_loop_insn;
-
- /* First find the iteration variable. If the last insn is a conditional
- branch, and the insn before tests a register value, make that the
- iteration variable. */
-
- loop_initial_value = 0;
- loop_increment = 0;
- loop_final_value = 0;
- loop_iteration_var = 0;
-
- /* We used to use pren_nonnote_insn here, but that fails because it might
+ rtx vtop;
+ rtx reg_term;
+
+ loop_info->n_iterations = 0;
+ loop_info->initial_value = 0;
+ loop_info->initial_equiv_value = 0;
+ loop_info->comparison_value = 0;
+ loop_info->final_value = 0;
+ loop_info->final_equiv_value = 0;
+ loop_info->increment = 0;
+ loop_info->iteration_var = 0;
+ loop_info->unroll_number = 1;
+ loop_info->vtop = 0;
+
+ /* We used to use prev_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);
+ /* ??? We should probably try harder to find the jump insn
+ at the end of the loop. The following code assumes that
+ the last loop insn is a jump to the top of the loop. */
+ if (GET_CODE (last_loop_insn) != JUMP_INSN)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Loop iterations: No final conditional branch found.\n");
+ return 0;
+ }
+
+ /* If there is a more than a single jump to the top of the loop
+ we cannot (easily) determine the iteration count. */
+ if (LABEL_NUSES (JUMP_LABEL (last_loop_insn)) > 1)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Loop iterations: Loop has multiple back edges.\n");
+ return 0;
+ }
+
+ /* Find the iteration variable. If the last insn is a conditional
+ branch, and the insn before tests a register value, make that the
+ iteration variable. */
+
comparison = get_condition_for_loop (last_loop_insn);
if (comparison == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "Loop unrolling: No final conditional branch found.\n");
+ "Loop iterations: No final comparison found.\n");
return 0;
}
@@ -3461,18 +3655,37 @@ loop_iterations (loop_start, loop_end)
iteration_var = XEXP (comparison, 0);
comparison_value = XEXP (comparison, 1);
+ /* Check if there is a NOTE_INSN_LOOP_VTOP note. If there is,
+ that means that this is a for or while style loop, with
+ a loop exit test at the start. Thus, we can assume that
+ the loop condition was true when the loop was entered.
+
+ We start at the end and search backwards for the previous
+ NOTE. If there is no NOTE_INSN_LOOP_VTOP for this loop,
+ the search will stop at the NOTE_INSN_LOOP_CONT. */
+ vtop = loop_end;
+ do
+ vtop = PREV_INSN (vtop);
+ while (GET_CODE (vtop) != NOTE
+ || NOTE_LINE_NUMBER (vtop) > 0
+ || NOTE_LINE_NUMBER (vtop) == NOTE_REPEATED_LINE_NUMBER
+ || NOTE_LINE_NUMBER (vtop) == NOTE_INSN_DELETED);
+ if (NOTE_LINE_NUMBER (vtop) != NOTE_INSN_LOOP_VTOP)
+ vtop = NULL_RTX;
+ loop_info->vtop = vtop;
+
if (GET_CODE (iteration_var) != REG)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "Loop unrolling: Comparison not against register.\n");
+ "Loop iterations: Comparison not against register.\n");
return 0;
}
- /* Loop iterations is always called before any new registers are created
- now, so this should never occur. */
+ /* The only new registers that care created before loop iterations are
+ givs made from biv increments, so this should never occur. */
- if (REGNO (iteration_var) >= max_reg_before_loop)
+ if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements)
abort ();
iteration_info (iteration_var, &initial_value, &increment,
@@ -3481,102 +3694,233 @@ loop_iterations (loop_start, loop_end)
/* iteration_info already printed a message. */
return 0;
+ unsigned_p = 0;
+ off_by_one = 0;
+ switch (comparison_code)
+ {
+ case LEU:
+ unsigned_p = 1;
+ case LE:
+ compare_dir = 1;
+ off_by_one = 1;
+ break;
+ case GEU:
+ unsigned_p = 1;
+ case GE:
+ compare_dir = -1;
+ off_by_one = -1;
+ break;
+ case EQ:
+ /* Cannot determine loop iterations with this case. */
+ compare_dir = 0;
+ break;
+ case LTU:
+ unsigned_p = 1;
+ case LT:
+ compare_dir = 1;
+ break;
+ case GTU:
+ unsigned_p = 1;
+ case GT:
+ compare_dir = -1;
+ case NE:
+ compare_dir = 0;
+ break;
+ default:
+ abort ();
+ }
+
/* If the comparison value is an invariant register, then try to find
its value from the insns before the start of the loop. */
+ final_value = comparison_value;
if (GET_CODE (comparison_value) == REG && invariant_p (comparison_value))
{
- rtx insn, set;
-
- for (insn = PREV_INSN (loop_start); insn ; insn = PREV_INSN (insn))
+ final_value = loop_find_equiv_value (loop_start, comparison_value);
+ /* If we don't get an invariant final value, we are better
+ off with the original register. */
+ if (!invariant_p (final_value))
+ final_value = comparison_value;
+ }
+
+ /* Calculate the approximate final value of the induction variable
+ (on the last successful iteration). The exact final value
+ depends on the branch operator, and increment sign. It will be
+ wrong if the iteration variable is not incremented by one each
+ time through the loop and (comparison_value + off_by_one -
+ initial_value) % increment != 0.
+ ??? Note that the final_value may overflow and thus final_larger
+ will be bogus. A potentially infinite loop will be classified
+ as immediate, e.g. for (i = 0x7ffffff0; i <= 0x7fffffff; i++) */
+ if (off_by_one)
+ final_value = plus_constant (final_value, off_by_one);
+
+ /* Save the calculated values describing this loop's bounds, in case
+ precondition_loop_p will need them later. These values can not be
+ recalculated inside precondition_loop_p because strength reduction
+ optimizations may obscure the loop's structure.
+
+ These values are only required by precondition_loop_p and insert_bct
+ whenever the number of iterations cannot be computed at compile time.
+ Only the difference between final_value and initial_value is
+ important. Note that final_value is only approximate. */
+ loop_info->initial_value = initial_value;
+ loop_info->comparison_value = comparison_value;
+ loop_info->final_value = plus_constant (comparison_value, off_by_one);
+ loop_info->increment = increment;
+ loop_info->iteration_var = iteration_var;
+ loop_info->comparison_code = comparison_code;
+
+ /* Try to determine the iteration count for loops such
+ as (for i = init; i < init + const; i++). When running the
+ loop optimization twice, the first pass often converts simple
+ loops into this form. */
+
+ if (REG_P (initial_value))
+ {
+ rtx reg1;
+ rtx reg2;
+ rtx const2;
+
+ reg1 = initial_value;
+ if (GET_CODE (final_value) == PLUS)
+ reg2 = XEXP (final_value, 0), const2 = XEXP (final_value, 1);
+ else
+ reg2 = final_value, const2 = const0_rtx;
+
+ /* Check for initial_value = reg1, final_value = reg2 + const2,
+ where reg1 != reg2. */
+ if (REG_P (reg2) && reg2 != reg1)
{
- if (GET_CODE (insn) == CODE_LABEL)
- break;
+ rtx temp;
- else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
- && reg_set_p (comparison_value, insn))
+ /* Find what reg1 is equivalent to. Hopefully it will
+ either be reg2 or reg2 plus a constant. */
+ temp = loop_find_equiv_value (loop_start, reg1);
+ if (find_common_reg_term (temp, reg2))
+ initial_value = temp;
+ else
{
- /* We found the last insn before the loop that sets the register.
- If it sets the entire register, and has a REG_EQUAL note,
- then use the value of the REG_EQUAL note. */
- if ((set = single_set (insn))
- && (SET_DEST (set) == comparison_value))
- {
- rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-
- /* Only use the REG_EQUAL note if it is a constant.
- Other things, divide in particular, will cause
- problems later if we use them. */
- if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST
- && CONSTANT_P (XEXP (note, 0)))
- comparison_value = XEXP (note, 0);
- }
- break;
+ /* Find what reg2 is equivalent to. Hopefully it will
+ either be reg1 or reg1 plus a constant. Let's ignore
+ the latter case for now since it is not so common. */
+ temp = loop_find_equiv_value (loop_start, reg2);
+ if (temp == loop_info->iteration_var)
+ temp = initial_value;
+ if (temp == reg1)
+ final_value = (const2 == const0_rtx)
+ ? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2);
+ }
+ }
+ else if (loop_info->vtop && GET_CODE (reg2) == CONST_INT)
+ {
+ rtx temp;
+
+ /* When running the loop optimizer twice, check_dbra_loop
+ further obfuscates reversible loops of the form:
+ for (i = init; i < init + const; i++). We often end up with
+ final_value = 0, initial_value = temp, temp = temp2 - init,
+ where temp2 = init + const. If the loop has a vtop we
+ can replace initial_value with const. */
+
+ temp = loop_find_equiv_value (loop_start, reg1);
+ if (GET_CODE (temp) == MINUS && REG_P (XEXP (temp, 0)))
+ {
+ rtx temp2 = loop_find_equiv_value (loop_start, XEXP (temp, 0));
+ if (GET_CODE (temp2) == PLUS
+ && XEXP (temp2, 0) == XEXP (temp, 1))
+ initial_value = XEXP (temp2, 1);
}
}
}
- final_value = approx_final_value (comparison_code, comparison_value,
- &unsigned_compare, &compare_dir);
+ /* If have initial_value = reg + const1 and final_value = reg +
+ const2, then replace initial_value with const1 and final_value
+ with const2. This should be safe since we are protected by the
+ initial comparison before entering the loop if we have a vtop.
+ For example, a + b < a + c is not equivalent to b < c for all a
+ when using modulo arithmetic.
+
+ ??? Without a vtop we could still perform the optimization if we check
+ the initial and final values carefully. */
+ if (loop_info->vtop
+ && (reg_term = find_common_reg_term (initial_value, final_value)))
+ {
+ initial_value = subtract_reg_term (initial_value, reg_term);
+ final_value = subtract_reg_term (final_value, reg_term);
+ }
- /* Save the calculated values describing this loop's bounds, in case
- precondition_loop_p will need them later. These values can not be
- recalculated inside precondition_loop_p because strength reduction
- optimizations may obscure the loop's structure. */
+ loop_info->initial_equiv_value = initial_value;
+ loop_info->final_equiv_value = final_value;
- loop_iteration_var = iteration_var;
- loop_initial_value = initial_value;
- loop_increment = increment;
- loop_final_value = final_value;
- loop_comparison_code = comparison_code;
+ /* For EQ comparison loops, we don't have a valid final value.
+ Check this now so that we won't leave an invalid value if we
+ return early for any other reason. */
+ if (comparison_code == EQ)
+ loop_info->final_equiv_value = loop_info->final_value = 0;
if (increment == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "Loop unrolling: Increment value can't be calculated.\n");
+ "Loop iterations: Increment value can't be calculated.\n");
return 0;
}
- else if (GET_CODE (increment) != CONST_INT)
+
+ if (GET_CODE (increment) != CONST_INT)
{
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Loop unrolling: Increment value not constant.\n");
- return 0;
+ /* If we have a REG, check to see if REG holds a constant value. */
+ /* ??? Other RTL, such as (neg (reg)) is possible here, but it isn't
+ clear if it is worthwhile to try to handle such RTL. */
+ if (GET_CODE (increment) == REG || GET_CODE (increment) == SUBREG)
+ increment = loop_find_equiv_value (loop_start, increment);
+
+ if (GET_CODE (increment) != CONST_INT)
+ {
+ if (loop_dump_stream)
+ {
+ fprintf (loop_dump_stream,
+ "Loop iterations: Increment value not constant ");
+ print_rtl (loop_dump_stream, increment);
+ fprintf (loop_dump_stream, ".\n");
+ }
+ return 0;
+ }
+ loop_info->increment = increment;
}
- else if (GET_CODE (initial_value) != CONST_INT)
+
+ if (GET_CODE (initial_value) != CONST_INT)
{
if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Loop unrolling: Initial value not constant.\n");
+ {
+ fprintf (loop_dump_stream,
+ "Loop iterations: Initial value not constant ");
+ print_rtl (loop_dump_stream, initial_value);
+ fprintf (loop_dump_stream, ".\n");
+ }
return 0;
}
- else if (final_value == 0)
+ else if (comparison_code == EQ)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "Loop unrolling: EQ comparison loop.\n");
+ "Loop iterations: EQ comparison loop.\n");
return 0;
}
else if (GET_CODE (final_value) != CONST_INT)
{
if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Loop unrolling: Final value not constant.\n");
+ {
+ fprintf (loop_dump_stream,
+ "Loop iterations: Final value not constant ");
+ print_rtl (loop_dump_stream, final_value);
+ fprintf (loop_dump_stream, ".\n");
+ }
return 0;
}
- /* ?? Final value and initial value do not have to be constants.
- Only their difference has to be constant. When the iteration variable
- is an array address, the final value and initial value might both
- be addresses with the same base but different constant offsets.
- Final value must be invariant for this to work.
-
- To do this, need some way to find the values of registers which are
- invariant. */
-
/* Final_larger is 1 if final larger, 0 if they are equal, otherwise -1. */
- if (unsigned_compare)
+ if (unsigned_p)
final_larger
= ((unsigned HOST_WIDE_INT) INTVAL (final_value)
> (unsigned HOST_WIDE_INT) INTVAL (initial_value))
@@ -3599,7 +3943,7 @@ loop_iterations (loop_start, loop_end)
will overflow before the loop exits), 4 infinite loop cases, and 15
immediate exit (0 or 1 iteration depending on loop type) cases.
Only try to optimize the normal cases. */
-
+
/* (compare_dir/final_larger/increment_dir)
Normal cases: (0/-1/-1), (0/1/1), (-1/-1/-1), (1/1/1)
Reverse cases: (0/-1/1), (0/1/-1), (-1/-1/1), (1/1/-1)
@@ -3628,35 +3972,40 @@ loop_iterations (loop_start, loop_end)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "Loop unrolling: Not normal loop.\n");
+ "Loop iterations: Not normal loop.\n");
return 0;
}
/* Calculate the number of iterations, final_value is only an approximation,
- so correct for that. Note that tempu and loop_n_iterations are
+ so correct for that. Note that abs_diff and n_iterations are
unsigned, because they can be as large as 2^n - 1. */
- i = INTVAL (increment);
- if (i > 0)
- tempu = INTVAL (final_value) - INTVAL (initial_value);
- else if (i < 0)
+ abs_inc = INTVAL (increment);
+ if (abs_inc > 0)
+ abs_diff = INTVAL (final_value) - INTVAL (initial_value);
+ else if (abs_inc < 0)
{
- tempu = INTVAL (initial_value) - INTVAL (final_value);
- i = -i;
+ abs_diff = INTVAL (initial_value) - INTVAL (final_value);
+ abs_inc = -abs_inc;
}
else
abort ();
- /* For NE tests, make sure that the iteration variable won't miss the
- final value. If tempu mod i is not zero, then the iteration variable
- will overflow before the loop exits, and we can not calculate the
- number of iterations. */
- if (compare_dir == 0 && (tempu % i) != 0)
+ /* For NE tests, make sure that the iteration variable won't miss
+ the final value. If abs_diff mod abs_incr is not zero, then the
+ iteration variable will overflow before the loop exits, and we
+ can not calculate the number of iterations. */
+ if (compare_dir == 0 && (abs_diff % abs_inc) != 0)
return 0;
- return tempu / i + ((tempu % i) != 0);
+ /* Note that the number of iterations could be calculated using
+ (abs_diff + abs_inc - 1) / abs_inc, provided care was taken to
+ handle potential overflow of the summation. */
+ loop_info->n_iterations = abs_diff / abs_inc + ((abs_diff % abs_inc) != 0);
+ return loop_info->n_iterations;
}
+
/* Replace uses of split bivs with their split pseudo register. This is
for original instructions which remain after loop unrolling without
copying. */
@@ -3691,10 +4040,10 @@ remap_split_bivs (x)
have to remap those givs also. */
#endif
if (REGNO (x) < max_reg_before_loop
- && reg_iv_type[REGNO (x)] == BASIC_INDUCT)
+ && REG_IV_TYPE (REGNO (x)) == BASIC_INDUCT)
return reg_biv_class[REGNO (x)]->biv->src_reg;
break;
-
+
default:
break;
}
diff --git a/contrib/gcc/varasm.c b/contrib/gcc/varasm.c
index 0055d68..f463d84 100644
--- a/contrib/gcc/varasm.c
+++ b/contrib/gcc/varasm.c
@@ -1,5 +1,5 @@
/* Output variables, constants and external declarations, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -72,14 +72,6 @@ Boston, MA 02111-1307, USA. */
#endif
#define CHKR_PREFIX_SIZE (sizeof (CHKR_PREFIX) - 1)
-/* This macro gets just the user-specified name
- out of the string in a SYMBOL_REF. On most machines,
- we discard the * if any and that's all. */
-#ifndef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
- (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'))
-#endif
-
/* File in which assembler code is being written. */
extern FILE *asm_out_file;
@@ -116,20 +108,6 @@ int size_directive_output;
tree last_assemble_variable_decl;
-
-#ifdef HANDLE_PRAGMA_WEAK
-/* Any weak symbol declarations waiting to be emitted. */
-
-struct weak_syms
-{
- struct weak_syms *next;
- char *name;
- char *value;
-};
-
-static struct weak_syms *weak_decls;
-#endif
-
/* Nonzero if at least one function definition has been seen. */
static int function_defined;
@@ -139,7 +117,7 @@ struct constant_descriptor;
struct rtx_const;
struct pool_constant;
-static char *strip_reg_name PROTO((char *));
+static const char *strip_reg_name PROTO((const char *));
static int contains_pointers_p PROTO((tree));
static void decode_addr_const PROTO((tree, struct addr_const *));
static int const_hash PROTO((tree));
@@ -163,6 +141,7 @@ static void mark_constants PROTO((rtx));
static int output_addressed_constants PROTO((tree));
static void output_after_function_constants PROTO((void));
static void output_constructor PROTO((tree, int));
+static void remove_from_pending_weak_list PROTO ((char *));
#ifdef ASM_OUTPUT_BSS
static void asm_output_bss PROTO((FILE *, tree, char *, int, int));
#endif
@@ -230,6 +209,15 @@ data_section ()
in_section = in_data;
}
}
+/* Tell assembler to ALWAYS switch to data section, in case
+ it's not sure where it it. */
+
+void
+force_data_section ()
+{
+ in_section = no_section;
+ data_section ();
+}
/* Tell assembler to switch to read-only data section. This is normally
the text section. */
@@ -268,8 +256,8 @@ in_data_section ()
void
named_section (decl, name, reloc)
tree decl;
- char *name;
- int reloc;
+ const char *name;
+ int reloc ATTRIBUTE_UNUSED;
{
if (decl != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (decl)) != 'd')
@@ -554,9 +542,9 @@ make_function_rtl (decl)
/* Given NAME, a putative register name, discard any customary prefixes. */
-static char *
+static const char *
strip_reg_name (name)
- char *name;
+ const char *name;
{
#ifdef REGISTER_PREFIX
if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX)))
@@ -577,7 +565,7 @@ strip_reg_name (name)
int
decode_reg_name (asmspec)
- char *asmspec;
+ const char *asmspec;
{
if (asmspec != 0)
{
@@ -606,10 +594,10 @@ decode_reg_name (asmspec)
#ifdef ADDITIONAL_REGISTER_NAMES
{
- static struct { char *name; int number; } table[]
+ static struct { const char *name; int number; } table[]
= ADDITIONAL_REGISTER_NAMES;
- for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ for (i = 0; i < (int)(sizeof (table) / sizeof (table[0])); i++)
if (! strcmp (asmspec, table[i].name))
return table[i].number;
}
@@ -638,7 +626,7 @@ decode_reg_name (asmspec)
void
make_decl_rtl (decl, asmspec, top_level)
tree decl;
- char *asmspec;
+ const char *asmspec;
int top_level;
{
register char *name = 0;
@@ -774,13 +762,17 @@ make_decl_rtl (decl, asmspec, top_level)
if (flag_volatile_global && TREE_CODE (decl) == VAR_DECL
&& TREE_PUBLIC (decl))
TREE_SIDE_EFFECTS (decl) = 1;
+ else if (flag_volatile_static && TREE_CODE (decl) == VAR_DECL
+ && (TREE_PUBLIC (decl) || TREE_STATIC (decl)))
+ TREE_SIDE_EFFECTS (decl) = 1;
+
if (TREE_SIDE_EFFECTS (decl))
MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
if (TREE_READONLY (decl))
RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
- MEM_IN_STRUCT_P (DECL_RTL (decl))
- = AGGREGATE_TYPE_P (TREE_TYPE (decl));
+ MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
+ AGGREGATE_TYPE_P (TREE_TYPE (decl)));
/* Optionally set flags or add text to the name to record information
such as that it is a function name.
@@ -1021,7 +1013,13 @@ assemble_start_function (decl, fnname)
#ifdef ASM_WEAKEN_LABEL
if (DECL_WEAK (decl))
- ASM_WEAKEN_LABEL (asm_out_file, fnname);
+ {
+ ASM_WEAKEN_LABEL (asm_out_file, fnname);
+ /* Remove this function from the pending weak list so that
+ we do not emit multiple .weak directives for it. */
+ remove_from_pending_weak_list
+ (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+ }
else
#endif
ASM_GLOBALIZE_LABEL (asm_out_file, fnname);
@@ -1063,6 +1061,10 @@ void
assemble_zeros (size)
int size;
{
+ /* Do no output if -fsyntax-only. */
+ if (flag_syntax_only)
+ return;
+
#ifdef ASM_NO_SKIP_IN_TEXT
/* The `space' pseudo in the text section outputs nop insns rather than 0s,
so we must output 0s explicitly in the text section. */
@@ -1113,7 +1115,7 @@ assemble_align (align)
void
assemble_string (p, size)
- char *p;
+ const char *p;
int size;
{
int pos = 0;
@@ -1148,7 +1150,7 @@ assemble_string (p, size)
void
assemble_variable (decl, top_level, at_end, dont_output_data)
tree decl;
- int top_level;
+ int top_level ATTRIBUTE_UNUSED;
int at_end;
int dont_output_data;
{
@@ -1169,6 +1171,10 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
return;
TREE_ASM_WRITTEN (decl) = 1;
+ /* Do no output if -fsyntax-only. */
+ if (flag_syntax_only)
+ return;
+
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
/* File-scope global variables are output here. */
if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
@@ -1236,6 +1242,10 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
TREE_ASM_WRITTEN (decl) = 1;
+ /* Do no output if -fsyntax-only. */
+ if (flag_syntax_only)
+ return;
+
app_disable ();
if (! dont_output_data)
@@ -1319,6 +1329,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
&& DECL_COMMON (decl)
#endif
+ && DECL_SECTION_NAME (decl) == 0
&& ! dont_output_data)
{
int size = TREE_INT_CST_LOW (size_tree);
@@ -1441,8 +1452,14 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
if (TREE_PUBLIC (decl) && DECL_NAME (decl))
{
#ifdef ASM_WEAKEN_LABEL
- if (DECL_WEAK (decl))
- ASM_WEAKEN_LABEL (asm_out_file, name);
+ if (DECL_WEAK (decl))
+ {
+ ASM_WEAKEN_LABEL (asm_out_file, name);
+ /* Remove this variable from the pending weak list so that
+ we do not emit multiple .weak directives for it. */
+ remove_from_pending_weak_list
+ (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+ }
else
#endif
ASM_GLOBALIZE_LABEL (asm_out_file, name);
@@ -1464,7 +1481,9 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
reloc = output_addressed_constants (DECL_INITIAL (decl));
#ifdef ASM_OUTPUT_SECTION_NAME
- if (UNIQUE_SECTION_P (decl))
+ if ((flag_data_sections != 0
+ && DECL_SECTION_NAME (decl) == NULL_TREE)
+ || UNIQUE_SECTION_P (decl))
UNIQUE_SECTION (decl, reloc);
#endif
@@ -1597,7 +1616,7 @@ contains_pointers_p (type)
void
assemble_external (decl)
- tree decl;
+ tree decl ATTRIBUTE_UNUSED;
{
#ifdef ASM_OUTPUT_EXTERNAL
if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd'
@@ -1620,7 +1639,7 @@ assemble_external (decl)
void
assemble_external_libcall (fun)
- rtx fun;
+ rtx fun ATTRIBUTE_UNUSED;
{
#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
/* Declare library function name external when first used, if nec. */
@@ -1714,9 +1733,11 @@ assemble_static_space (size)
{
/* Round size up to multiple of BIGGEST_ALIGNMENT bits
so that each uninitialized object starts on such a boundary. */
- int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
- / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+ /* Variable `rounded' might or might not be used in ASM_OUTPUT_LOCAL. */
+ int rounded ATTRIBUTE_UNUSED
+ = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
+ / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
+ * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
}
#endif
@@ -2563,6 +2584,7 @@ compare_constant_1 (exp, p)
case PLUS_EXPR:
case MINUS_EXPR:
+ case RANGE_EXPR:
p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
if (p == 0)
return 0;
@@ -2739,6 +2761,7 @@ record_constant_1 (exp)
case PLUS_EXPR:
case MINUS_EXPR:
+ case RANGE_EXPR:
record_constant_1 (TREE_OPERAND (exp, 0));
record_constant_1 (TREE_OPERAND (exp, 1));
return;
@@ -2965,7 +2988,7 @@ output_constant_def (exp)
= gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), def);
RTX_UNCHANGING_P (TREE_CST_RTL (exp)) = 1;
if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
- MEM_IN_STRUCT_P (TREE_CST_RTL (exp)) = 1;
+ MEM_SET_IN_STRUCT_P (TREE_CST_RTL (exp), 1);
pop_obstacks ();
@@ -3011,7 +3034,12 @@ output_constant_def (exp)
}
}
else
- output_constant_def_contents (exp, reloc, const_labelno++);
+ {
+ /* Do no output if -fsyntax-only. */
+ if (! flag_syntax_only)
+ output_constant_def_contents (exp, reloc, const_labelno);
+ ++const_labelno;
+ }
}
return TREE_CST_RTL (exp);
@@ -3582,8 +3610,8 @@ get_pool_size ()
void
output_constant_pool (fnname, fndecl)
- char *fnname;
- tree fndecl;
+ char *fnname ATTRIBUTE_UNUSED;
+ tree fndecl ATTRIBUTE_UNUSED;
{
struct pool_constant *pool;
rtx x;
@@ -3592,8 +3620,7 @@ output_constant_pool (fnname, fndecl)
/* It is possible for gcc to call force_const_mem and then to later
discard the instructions which refer to the constant. In such a
case we do not need to output the constant. */
- if (optimize >= 0 && flag_expensive_optimizations)
- mark_constant_pool ();
+ mark_constant_pool ();
#ifdef ASM_OUTPUT_POOL_PROLOGUE
ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset);
@@ -3633,7 +3660,7 @@ output_constant_pool (fnname, fndecl)
#endif
if (pool->align > 1)
- ASM_OUTPUT_ALIGN (asm_out_file, exact_log2 (pool->align));
+ ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (pool->align));
/* Output the label. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", pool->labelno);
@@ -3696,6 +3723,33 @@ mark_constant_pool ()
insn = XEXP (insn, 1))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
mark_constants (PATTERN (insn));
+
+ /* It's possible that the only reference to a symbol is in a symbol
+ that's in the constant pool. This happens in Fortran under some
+ situations. (When the constant contains the address of another
+ constant, and only the first is used directly in an insn.)
+ This is potentially suboptimal if there's ever a possibility of
+ backwards (in pool order) 2'd level references. However, it's
+ not clear that 2'd level references can happen. */
+ for (pool = first_pool; pool; pool = pool->next)
+ {
+ struct pool_sym *sym;
+ char *label;
+
+ /* skip unmarked entries; no insn refers to them. */
+ if (!pool->mark)
+ continue;
+
+ label = XSTR (pool->constant, 0);
+
+ /* Be sure the symbol's value is marked. */
+ for (sym = const_rtx_sym_hash_table[SYMHASH (label)]; sym;
+ sym = sym->next)
+ if (sym->label == label)
+ sym->pool->mark = 1;
+ /* If we didn't find it, there's something truly wrong here, but it
+ will be announced by the assembler. */
+ }
}
static void
@@ -3848,7 +3902,14 @@ output_constant (exp, size)
{
register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
- if (size == 0)
+ /* Some front-ends use constants other than the standard
+ language-indepdent varieties, but which may still be output
+ directly. Give the front-end a chance to convert EXP to a
+ language-independent representation. */
+ if (lang_expand_constant)
+ exp = (*lang_expand_constant) (exp);
+
+ if (size == 0 || flag_syntax_only)
return;
/* Eliminate the NON_LVALUE_EXPR_EXPR that makes a cast not be an lvalue.
@@ -3992,7 +4053,11 @@ output_constructor (exp, size)
FIELD goes through the structure fields, if the constant is a structure.
if the constant is a union, then we override this,
by getting the field from the TREE_LIST element.
- But the constant could also be an array. Then FIELD is zero. */
+ But the constant could also be an array. Then FIELD is zero.
+
+ There is always a maximum of one element in the chain LINK for unions
+ (even if the initializer in a source program incorrectly contains
+ more one). */
for (link = CONSTRUCTOR_ELTS (exp);
link;
link = TREE_CHAIN (link),
@@ -4242,37 +4307,30 @@ output_constructor (exp, size)
assemble_zeros (size - total_bytes);
}
-/* Output asm to handle ``#pragma weak'' */
-
-void
-handle_pragma_weak (what, name, value)
- enum pragma_state what;
- char *name, *value;
-{
#ifdef HANDLE_PRAGMA_WEAK
- if (what == ps_name || what == ps_value)
- {
- struct weak_syms *weak =
- (struct weak_syms *)permalloc (sizeof (struct weak_syms));
- weak->next = weak_decls;
- weak->name = permalloc (strlen (name) + 1);
- strcpy (weak->name, name);
+/* Add function NAME to the weak symbols list. VALUE is a weak alias
+ associatd with NAME. */
+
+int
+add_weak (name, value)
+ char *name;
+ char *value;
+{
+ struct weak_syms *weak;
- if (what != ps_value)
- weak->value = NULL_PTR;
+ weak = (struct weak_syms *) permalloc (sizeof (struct weak_syms));
- else
- {
- weak->value = permalloc (strlen (value) + 1);
- strcpy (weak->value, value);
- }
+ if (weak == NULL)
+ return 0;
- weak_decls = weak;
- }
- else if (! (what == ps_done || what == ps_start))
- warning ("malformed `#pragma weak'");
-#endif /* HANDLE_PRAGMA_WEAK */
+ weak->next = weak_decls;
+ weak->name = name;
+ weak->value = value;
+ weak_decls = weak;
+
+ return 1;
}
+#endif /* HANDLE_PRAGMA_WEAK */
/* Declare DECL to be a weak symbol. */
@@ -4286,17 +4344,17 @@ declare_weak (decl)
error_with_decl (decl, "weak declaration of `%s' must precede definition");
else if (SUPPORTS_WEAK)
DECL_WEAK (decl) = 1;
-
#ifdef HANDLE_PRAGMA_WEAK
- /* Make sure this function name gets on the weak declaration list. */
- handle_pragma_weak (ps_name,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
- NULL);
+ add_weak (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), NULL);
#endif
}
/* Emit any pending weak declarations. */
+#ifdef HANDLE_PRAGMA_WEAK
+struct weak_syms * weak_decls;
+#endif
+
void
weak_finish ()
{
@@ -4306,9 +4364,32 @@ weak_finish ()
struct weak_syms *t;
for (t = weak_decls; t; t = t->next)
{
- ASM_WEAKEN_LABEL (asm_out_file, t->name);
- if (t->value)
- ASM_OUTPUT_DEF (asm_out_file, t->name, t->value);
+ if (t->name)
+ {
+ ASM_WEAKEN_LABEL (asm_out_file, t->name);
+ if (t->value)
+ ASM_OUTPUT_DEF (asm_out_file, t->name, t->value);
+ }
+ }
+ }
+#endif
+}
+
+/* Remove NAME from the pending list of weak symbols. This prevents
+ the compiler from emitting multiple .weak directives which confuses
+ some assemblers. */
+static void
+remove_from_pending_weak_list (name)
+ char *name;
+{
+#ifdef HANDLE_PRAGMA_WEAK
+ if (HANDLE_PRAGMA_WEAK)
+ {
+ struct weak_syms *t;
+ for (t = weak_decls; t; t = t->next)
+ {
+ if (t->name && strcmp (name, t->name) == 0)
+ t->name = NULL;
}
}
#endif
@@ -4316,7 +4397,7 @@ weak_finish ()
void
assemble_alias (decl, target)
- tree decl, target;
+ tree decl, target ATTRIBUTE_UNUSED;
{
char *name;
@@ -4330,7 +4411,13 @@ assemble_alias (decl, target)
{
#ifdef ASM_WEAKEN_LABEL
if (DECL_WEAK (decl))
- ASM_WEAKEN_LABEL (asm_out_file, name);
+ {
+ ASM_WEAKEN_LABEL (asm_out_file, name);
+ /* Remove this function from the pending weak list so that
+ we do not emit multiple .weak directives for it. */
+ remove_from_pending_weak_list
+ (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+ }
else
#endif
ASM_GLOBALIZE_LABEL (asm_out_file, name);
diff --git a/contrib/gcc/varray.h b/contrib/gcc/varray.h
index df3ca31..7d4f697 100644
--- a/contrib/gcc/varray.h
+++ b/contrib/gcc/varray.h
@@ -22,10 +22,6 @@
#ifndef _VARRAY_H_
#define _VARRAY_H_
-#ifndef PROTO
-#include "gansidecl.h"
-#endif
-
#ifndef HOST_WIDE_INT
#include "machmode.h"
#endif
@@ -34,6 +30,30 @@
#include "system.h"
#endif
+/* Auxiliary structure used inside the varray structure, used for
+ function integration data. */
+
+struct const_equiv_data {
+ /* Map pseudo reg number in calling function to equivalent constant. We
+ cannot in general substitute constants into parameter pseudo registers,
+ since some machine descriptions (many RISCs) won't always handle
+ the resulting insns. So if an incoming parameter has a constant
+ equivalent, we record it here, and if the resulting insn is
+ recognizable, we go with it.
+
+ We also use this mechanism to convert references to incoming arguments
+ and stacked variables. copy_rtx_and_substitute will replace the virtual
+ incoming argument and virtual stacked variables registers with new
+ pseudos that contain pointers into the replacement area allocated for
+ this inline instance. These pseudos are then marked as being equivalent
+ to the appropriate address and substituted if valid. */
+ rtx rtx;
+
+ /* Record the valid age for each entry. The entry is invalid if its
+ age is less than const_age. */
+ unsigned age;
+};
+
/* Union of various array types that are used. */
typedef union varray_data_tag {
char c[1];
@@ -54,6 +74,8 @@ typedef union varray_data_tag {
struct bitmap_head_def *bitmap[1];
struct sched_info_tag *sched[1];
struct reg_info_def *reg[1];
+ struct const_equiv_data const_equiv[1];
+ struct basic_block_def *bb[1];
} varray_data;
/* Virtual array of pointers header. */
@@ -122,15 +144,24 @@ extern varray_type varray_init PROTO ((size_t, size_t, const char *));
#define VARRAY_REG_INIT(va, num, name) \
va = varray_init (num, sizeof (struct reg_info_def *), name)
+#define VARRAY_CONST_EQUIV_INIT(va, num, name) \
+ va = varray_init (num, sizeof (struct const_equiv_data), name)
+
+#define VARRAY_BB_INIT(va, num, name) \
+ va = varray_init (num, sizeof (struct basic_block_def *), name)
+
/* Free up memory allocated by the virtual array, but do not free any of the
elements involved. */
-#define VARRAY_FREE(vp) ((vp) && (free (vp), (vp = (varray_type)0)))
+#define VARRAY_FREE(vp) \
+ do { if (vp) { free (vp); vp = (varray_type)0; } } while (0)
/* Grow/shrink the virtual array VA to N elements. */
extern varray_type varray_grow PROTO((varray_type, size_t));
#define VARRAY_GROW(VA, N) ((VA) = varray_grow (VA, N))
+#define VARRAY_SIZE(VA) ((VA)->num_elements)
+
/* Check for VARRAY_xxx macros being in bound, return N for use as an
index. */
#ifdef ENABLE_CHECKING
@@ -162,5 +193,7 @@ extern varray_type varray_grow PROTO((varray_type, size_t));
#define VARRAY_BITMAP(VA, N) ((VA)->data.bitmap[ VARRAY_CHECK (VA, N) ])
#define VARRAY_SCHED(VA, N) ((VA)->data.sched[ VARRAY_CHECK (VA, N) ])
#define VARRAY_REG(VA, N) ((VA)->data.reg[ VARRAY_CHECK (VA, N) ])
+#define VARRAY_CONST_EQUIV(VA, N) ((VA)->data.const_equiv[VARRAY_CHECK (VA, N)])
+#define VARRAY_BB(VA, N) ((VA)->data.bb[ VARRAY_CHECK (VA, N) ])
#endif /* _VARRAY_H_ */
diff --git a/contrib/gcc/version.c b/contrib/gcc/version.c
index 573f16b..d28821d 100644
--- a/contrib/gcc/version.c
+++ b/contrib/gcc/version.c
@@ -1 +1 @@
-char *version_string = "egcs-2.91.66 19990314 (egcs-1.1.2 release)";
+char *version_string = "2.95.1 19990816 (release)";
diff --git a/contrib/gcc/xcoffout.c b/contrib/gcc/xcoffout.c
index baa0cd2..4da5079 100644
--- a/contrib/gcc/xcoffout.c
+++ b/contrib/gcc/xcoffout.c
@@ -1,5 +1,5 @@
/* Output xcoff-format symbol table information from GNU compiler.
- Copyright (C) 1992, 1994, 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -177,7 +177,7 @@ xcoff_output_standard_types (syms)
#define UNKNOWN_STAB(STR) \
do { \
- fprintf(stderr, "Error, unknown stab %s: : 0x%x\n", STR, stab); \
+ error ("Unknown stab %s: : 0x%x\n", STR, stab); \
fflush (stderr); \
} while (0)
diff --git a/contrib/gcc/xcoffout.h b/contrib/gcc/xcoffout.h
index 2781a79..1683a88 100644
--- a/contrib/gcc/xcoffout.h
+++ b/contrib/gcc/xcoffout.h
@@ -1,5 +1,24 @@
/* XCOFF definitions. These are needed in dbxout.c, final.c,
- and xcoffout.h. */
+ and xcoffout.h.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
#define ASM_STABS_OP ".stabx"
OpenPOWER on IntegriCloud